Анализ страницы https://help.xilo.net/tickets
Основное Готовность: 100%
Домен
help.xilo.net
Состояние доменного имени
?
Проверяем корректность доменного имени и наличие технических проблем на уровне домена.
Используйте для продвижения только домен второго уровня.
Отличный запоминающийся домен.
Ответ сервера
200 Успешный ответ
HTTP-код ответа и цепочка редиректов
?
Код 200 — страница доступна. Коды 3xx — редиректы (цепочки замедляют загрузку и размывают ссылочный вес). Коды 4xx/5xx — ошибки, поисковик не сможет проиндексировать страницу.
Сервер настроен корректно.
Безопасность
Сайт безопасен
Использование HTTPS и SSL-сертификат
?
HTTPS — обязательный стандарт. Google и Яндекс отдают предпочтение защищённым сайтам. Отсутствие SSL или просроченный сертификат ведут к предупреждениям в браузере и снижению позиций.
На сайте работает защищенный протокол ssl и сайт открывается по https.
Ssl-сертификат действителен до 08.11.2026 5:24:32.
Включён HSTS (Strict-Transport-Security) — защита от подмены на http.
Поздравляем! Сайт не содержится в реестре РКН.
Кодировка
utf-8
Кодировка символов страницы
?
Стандарт — UTF-8. Неправильная кодировка вызывает нечитаемые символы и мешает поисковику корректно распознать текст страницы.
Указана кодировка на странице utf-8.
Язык
en
Атрибут lang в HTML-теге
?
Атрибут lang (<html lang="ru">) сообщает поисковикам и браузерам, на каком языке написана страница. Помогает при ранжировании в региональном поиске.
Язык документа указан явно: en.
Скорость загрузки
~0,62сек
Время отклика сервера (TTFB)
?
Time To First Byte — время до получения первого байта от сервера. Норма до 200 мс. Медленный отклик ухудшает пользовательский опыт и ранжирование: Яндекс и Google учитывают скорость страниц.
Скорость загрузки сайта 0,62сек оптимальна.
Объем документа
79Кб
Размер HTML-кода страницы
?
Слишком большой HTML замедляет парсинг браузером и сканирование поисковым роботом. Рекомендуется не более 200 Кб.
Объем html-документа 79Кб оптимален.
Структура html-документа корректна.
Ресурсы
Ресурсы: 4
Внешние ресурсы страницы (CSS, JS, изображения)
?
Количество и тип подключённых ресурсов влияют на скорость загрузки. Большое число запросов увеличивает время рендеринга страницы.
Кол-во файлов ресурсов 4 достаточно.
Показать полный список ресурсов
| Тип | Название | Значение |
|---|---|---|
| stylesheet | /vendor/fonts.css | |
| js | /vendor/tailwind.js | |
| js | /vendor/alpine.js | |
| js | /app.js |
Серверные заголовки
Кол-во: 10
HTTP-заголовки ответа сервера
?
Заголовки сервера передают браузеру и поисковику служебную информацию: кеширование, безопасность (CSP, HSTS), сжатие (gzip). Правильная настройка ускоряет загрузку и повышает защищённость.
Найдены серверные заголовки 10шт. Подробнее про серверные заголовки.
Показать полный список серверных заголовков
| Ключ | Значение |
|---|---|
| Date | Tue, 25 Aug 2026 05:10:26 GMT |
| Vary | Accept-Encoding |
| X-Frame-Options | DENY |
| X-Content-Type-Options | nosniff |
| Referrer-Policy | strict-origin-when-cross-origin |
| ETag | "13d00-6599062af3ce9" |
| Accept-Ranges | bytes |
| Cache-Control | public, no-cache |
| Server | Webserver |
| Strict-Transport-Security | max-age=63072000; preload |
CMS
Не определена
Система управления сайтом (движок)
?
CMS — это движок, на котором работает сайт (WordPress, 1C-Bitrix, Tilda и др.). Знание CMS помогает понять возможности SEO-оптимизации и подобрать подходящие инструменты. «Не определена» — вероятно, самописный сайт или нестандартная сборка.
CMS не определена. Вероятно, сайт самописный либо движок надёжно скрыт. Это не ошибка.
Веб-сервер
Webserver
Программное обеспечение сервера
?
Веб-сервер — это ПО, которое отдаёт страницы посетителям (nginx, Apache, IIS, LiteSpeed и др.). Определяется по серверным заголовкам ответа (Server, X-Powered-By и т.п.). «Не определён» — сервер намеренно скрывает эти заголовки, это нормальная практика безопасности.
В заголовке Server указано: Webserver.
Мета-теги Готовность: 32%
Title
Support
Заголовок страницы в браузере и поисковой выдаче
?
Title — главный SEO-заголовок страницы. Влияет на CTR в поиске и ранжирование. Оптимальная длина: 50–70 символов. Ключевые слова — ближе к началу.
Необходимо увеличить число символов в title (текущее значение мало: 7, минимум: 25, оптимально: от 40 до 45)
Дублей словоформ в title не найдено.
Description
Описание страницы в поисковой выдаче (сниппет)
?
Meta Description — текст под заголовком в выдаче. Напрямую на позиции не влияет, но влияет на CTR. Оптимальная длина: 120–160 символов.
Установите мета-тег description!
Keywords
Список ключевых слов страницы (устаревший тег)
?
Meta Keywords не учитывается Яндексом и Google для ранжирования с 2009–2012 годов. Заполнение не обязательно, но не вредит. Конкурент может использовать содержимое для анализа.
Установите мета-тег keywords!
Канонический Url
Указывает поисковику основную версию страницы
?
Canonical (rel=canonical) предотвращает проблему дублей страниц. Должен точно совпадать с URL проверяемой страницы. Неправильный canonical может передать ссылочный вес на другую страницу.
Рекомендуем прописать канонический Url.
Robots
Ошибок нет
Директивы для поисковых роботов на уровне страницы
?
Meta Robots управляет индексацией конкретной страницы: index/noindex — индексировать ли, follow/nofollow — следовать ли по ссылкам. Noindex полностью исключает страницу из поиска.
Meta-тег robots не указан. Страница свободна для индексации.
Адаптивность
width=device-width, initial-scale=1
Настройка масштабирования на мобильных устройствах
?
Тег viewport (<meta name="viewport">) сообщает браузеру, как масштабировать страницу на мобильных. Стандарт: width=device-width, initial-scale=1. Отсутствие — признак отсутствия мобильной версии.
Meta-тег viewport со значением-константой width=device-width задаёт ширину страницы в соответствии с размером экрана.
Meta-тег viewport со значением initial-scale=1.0 определяет масштаб 1:1, т.е. «не масштабировать».
Разметка OpenGraph
Не найдено
Мета-теги для красивых превью в соцсетях
?
OpenGraph (og:title, og:description, og:image) управляет тем, как страница выглядит при репосте в социальных сетях и мессенджерах. Отсутствие OG-тегов — невзрачный превью при шеринге.
Разметка OpenGraph не задана. Страница не оптимизирована под социальные сети. Мета-теги с разметкой Og помогают социальным роботам лучше структурировать Ваш сайт.
Все мета-теги
Кол-во: 1
Полный список мета-тегов страницы
?
Таблица всех meta-тегов, включая нестандартные. Позволяет найти опечатки, дубли и лишние теги.
Найдены мета-теги 1шт. Мета-теги не видимы для человека и предназначены для обмена информацией между веб-страницей и поисковыми системами, браузерами и другими веб-службами. С ними роботы 🤖 и устройства ведут себя более ожидаемо.
Показать полный список мета-тегов
| Тип | Название | Значение |
|---|---|---|
| name | viewport | width=device-width, initial-scale=1 |
Оптимизация Готовность: 55%
Структура
Ошибок нет
Семантические HTML-элементы страницы
?
Проверяет наличие основных структурных элементов: nav, header, footer, main. Корректная семантическая структура помогает поисковику понять архитектуру страницы.
Структура документа корректна (теги <html> и <body> присутствуют по одному на документ).
Контент
Есть ошибки
Объём и качество текстового содержимого
?
Анализирует объём полезного текста на странице. Слишком мало — страница может считаться малополезной. Слишком много — ухудшается читаемость и восприятие.
Слова из title 1 встречаются в тексте редко. Добавьте в контент страницы слова из тега <title>!
Кол-во слов 298 слишком мало. Добавьте больше текста (минимум 400 слов)!
Абзацев с текстом 19 достаточно.
Среднее число слов в абзаце 10 достаточно.
Кол-во знаков контента 1701 на странице оптимально.
Заголовки
Ошибок нет
Иерархия заголовков H1–H6
?
H1 должен быть один и содержать ключевой запрос. H2–H6 описывают подразделы. Пропуск уровней (H1 → H3) и несколько H1 — типичные ошибки, снижающие понятность страницы для поисковика.
На странице присутствуют заголовки <h1> 12. Это прекрасно.
На странице присутствуют заголовки <h2> 6. Это хорошо.
Тошнота
3,46
Насколько одно слово доминирует в тексте
?
Классическая тошнота = √(частота самого повторяющегося слова). Норма до 7–8: текст воспринимается естественно. Выше — поисковик может счесть страницу переспамленной.
Тошнота превышает норму 3. Измените текст страницы!
Академич. тошнота
24,83%
Насколько текст перенасыщен ключевыми словами
?
Академическая тошнота = (частота слова / общее количество слов) × 100%. Показывает долю конкретного слова в тексте. Норма 5–15%.
Академическая тошнота превышает норму 5-15%. Измените текст страницы!
Семантическое ядро
20
Наиболее часто встречающиеся слова на странице
?
Топ слов по частоте использования. Показывает, какие слова доминируют в тексте с точки зрения поисковика.
Контент страницы содержит осмысленный текст и слова.
Показать список слов
| Слово | Кол-во | Частота |
|---|---|---|
| articles | 12 | 4,03% |
| tickets | 9 | 3,02% |
| submit | 7 | 2,35% |
| request | 7 | 2,35% |
| categories | 5 | 1,68% |
| ticket | 5 | 1,68% |
| search | 4 | 1,34% |
| support | 3 | 1,01% |
| category | 3 | 1,01% |
| related | 3 | 1,01% |
| results | 3 | 1,01% |
| browse | 3 | 1,01% |
| portal | 2 | 0,67% |
| sub-categories | 2 | 0,67% |
| loading… | 2 | 0,67% |
| closed | 2 | 0,67% |
| longer | 2 | 0,67% |
| replied | 2 | 0,67% |
| rating | 2 | 0,67% |
| thanks | 2 | 0,67% |
Индексация Готовность: 75%
Индексирование
Ошибок нет
Разрешено ли индексирование страницы
?
Проверяет, не закрыта ли страница от индексации через robots.txt, meta robots или X-Robots-Tag. Страница, закрытая от индексации, не появится в поисковой выдаче.
Анкоров на странице 22 оптимально. Поисковые роботы обязательно проиндексируют сайт.
Robots.txt
Найден корректный robots.txt
Файл управления сканированием сайта роботами
?
Robots.txt указывает поисковым роботам, какие страницы сканировать, а какие — нет. Ошибки в файле могут случайно закрыть важные разделы от индексации.
Robots.txt настроен корректно. Размер файла: 81066 байт. Загружен за: 1сек.
Проверяемая страница не запрещена в robots.txt.
Robots.txt доступен по постоянному адресу
Показать содержимое robots.txt
<!DOCTYPE html>
<html lang="en" class="h-full bg-slate-50 dark:bg-slate-900">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Support</title>
<link rel="icon" href="/portal-api/brand/favicon">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<script>(function(){var w=console.warn;console.warn=function(m){if(typeof m==='string'&&m.indexOf('cdn.tailwindcss.com')>-1)return;return w.apply(console,arguments);};})();</script>
<script src="/vendor/tailwind.js"></script>
<script>tailwind.config = { darkMode: 'class' }</script>
<script>
// Apply the saved (or system) theme before paint to avoid a flash.
(function () {
try {
var t = localStorage.getItem('portalTheme');
if (t === 'dark' || (!t && matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
}
} catch (e) {}
})();
</script>
<link rel="stylesheet" href="/vendor/fonts.css">
<script defer src="/vendor/alpine.js"></script>
<script src="/app.js"></script>
<style>
[x-cloak]{display:none!important}
mark{ background:color-mix(in srgb,#facc15 55%,transparent); color:inherit; border-radius:2px; padding:0 1px; }
.dark mark{ background:color-mix(in srgb,#facc15 28%,transparent); color:#fde68a; }
#nav-loading{ position:fixed; top:0; left:0; right:0; height:3px; z-index:100; pointer-events:none;
opacity:0; animation:navload-in .01s linear .2s forwards; }
#nav-loading span{ position:absolute; top:0; bottom:0; left:0; width:38%; border-radius:3px;
background:var(--brand,#2563eb); animation:navload-sweep 1.1s ease-in-out infinite; }
@keyframes navload-in{ to{ opacity:1; } }
@keyframes navload-sweep{ from{ transform:translateX(-110%); } to{ transform:translateX(290%); } }
.hc{
--accent-ink:#fff; --bg:#f6f7f9; --surface:#fff; --text:#0f172a; --muted:#64748b;
--border:#e6e8ec; --radius:10px; --radius-lg:16px;
--heading:'Plus Jakarta Sans',system-ui,sans-serif; --body:'Public Sans',system-ui,sans-serif;
font-family:var(--body); color:var(--text); background:var(--bg); min-height:100vh;
}
.dark .hc{ --bg:#0b1120; --surface:#111a2e; --text:#e6edf7; --muted:#93a4bd; --border:#24304a; }
.hc *{ box-sizing:border-box; }
.hc-wrap{ max-width:1180px; margin:0 auto; padding:0 24px; }
.hc-h{ font-family:var(--heading); letter-spacing:-.015em; }
.hc-header{ position:sticky; top:0; z-index:50; background:var(--surface); border-bottom:1px solid var(--border); }
.hc-logo-mark{ display:inline-flex; width:34px; height:34px; align-items:center; justify-content:center; border-radius:9px; background:var(--accent); color:var(--accent-ink); font-family:var(--heading); font-weight:800; }
.hc-navlink{ padding:8px 13px; font-size:14.5px; font-weight:500; color:var(--text); text-decoration:none; border-radius:8px; cursor:pointer; opacity:.85; }
.hc-navlink:hover{ opacity:1; background:color-mix(in srgb, var(--text) 8%, transparent); }
.hc-search{ display:flex; align-items:center; gap:9px; height:40px; padding:0 14px; min-width:200px; background:color-mix(in srgb, var(--text) 6%, transparent); border:1px solid var(--border); border-radius:var(--radius); color:var(--muted); font:inherit; font-size:14px; cursor:pointer; }
.hc-search:hover{ border-color:color-mix(in srgb, var(--accent) 50%, transparent); color:var(--text); }
.hc-cta{ display:inline-flex; align-items:center; height:40px; padding:0 16px; background:var(--accent); color:var(--accent-ink); border:none; border-radius:var(--radius); font-family:var(--heading); font-weight:600; font-size:14px; cursor:pointer; white-space:nowrap; text-decoration:none; }
.hc-cta:hover{ filter:brightness(1.07); }
.hc-hero{ background:linear-gradient(180deg, color-mix(in srgb, var(--accent) 9%, var(--bg)), var(--bg)); border-bottom:1px solid var(--border); padding:70px 24px 60px; }
.hc-hero-box{ display:flex; align-items:center; gap:13px; width:100%; height:60px; padding:0 22px; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg); box-shadow:0 14px 40px -22px rgba(15,23,42,.4); cursor:text; }
.hc-hero-box:hover{ border-color:color-mix(in srgb, var(--accent) 55%, var(--border)); }
.hc-pill{ padding:6px 13px; background:var(--surface); border:1px solid var(--border); border-radius:999px; font-size:13.5px; font-weight:500; color:var(--text); text-decoration:none; cursor:pointer; }
.hc-pill:hover{ border-color:var(--accent); color:var(--accent); }
.hc-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(min(330px,100%),1fr)); gap:12px; }
.hc-art{ display:flex; align-items:center; gap:14px; padding:17px 18px; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); text-decoration:none; color:inherit; cursor:pointer; transition:.15s; }
.hc-art:hover{ border-color:color-mix(in srgb, var(--accent) 45%, var(--border)); background:color-mix(in srgb, var(--accent) 3%, var(--surface)); }
.hc-art-icon{ display:inline-flex; flex-shrink:0; width:36px; height:36px; align-items:center; justify-content:center; border-radius:9px; background:color-mix(in srgb, var(--accent) 10%, var(--surface)); color:var(--accent); }
.hc-card{ background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg); }
.hc-input{ width:100%; height:46px; padding:0 16px; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); color:var(--text); font:inherit; font-size:15px; }
.hc-input:focus{ outline:none; border-color:var(--accent); }
.hc-btn{ display:inline-flex; align-items:center; justify-content:center; height:42px; padding:0 18px; background:var(--accent); color:var(--accent-ink); border:none; border-radius:var(--radius); font-family:var(--heading); font-weight:600; font-size:14px; cursor:pointer; }
.hc-btn:disabled{ opacity:.5; cursor:default; }
.hc-btn-ghost{ background:var(--surface); color:var(--text); border:1px solid var(--border); }
.hc-btn-ghost:hover{ border-color:var(--accent); color:var(--accent); }
.hc-prose{ font-size:16.5px; line-height:1.72; color:color-mix(in srgb, var(--text) 90%, var(--muted)); }
.hc-prose h1,.hc-prose h2,.hc-prose h3{ font-family:var(--heading); color:var(--text); letter-spacing:-.01em; margin:34px 0 12px; }
.hc-prose h1{ font-size:30px; } .hc-prose h2{ font-size:23px; } .hc-prose h3{ font-size:19px; }
.hc-prose p{ margin:0 0 18px; } .hc-prose ul,.hc-prose ol{ margin:0 0 20px; padding-left:22px; }
.hc-prose li{ margin:8px 0; } .hc-prose a{ color:var(--accent); }
.hc-prose code{ background:color-mix(in srgb, var(--text) 8%, transparent); padding:2px 6px; border-radius:6px; font-size:.9em; }
.hc-prose pre{ margin:0 0 18px; padding:14px 16px; background:color-mix(in srgb, var(--text) 6%, transparent); border:1px solid var(--border); border-radius:var(--radius); overflow-x:auto; line-height:1.55; }
.hc-prose pre code{ display:block; background:none; padding:0; border-radius:0; font-size:.88em; }
.hc-prose ul{ list-style:disc; } .hc-prose ol{ list-style:decimal; }
.hc-prose ul.kb-checklist{ list-style:none; }
.hc-prose blockquote{ margin:0 0 18px; padding:4px 0 4px 16px; border-left:3px solid var(--accent); color:var(--muted); }
.hc-prose blockquote p{ margin:0; }
.hc-prose blockquote cite{ display:block; margin-top:6px; font-size:.85em; font-style:normal; }
.hc-prose hr{ margin:28px 0; border:none; border-top:1px solid var(--border); }
.hc-prose table{ width:100%; margin:0 0 18px; border-collapse:collapse; font-size:.95em; }
.hc-prose th,.hc-prose td{ padding:8px 12px; border:1px solid var(--border); text-align:left; }
.hc-prose th{ background:color-mix(in srgb, var(--text) 5%, transparent); }
.hc-prose figure{ margin:0 0 18px; }
.hc-prose figure img{ max-width:100%; border-radius:var(--radius); }
.hc-prose figcaption{ margin-top:6px; font-size:.85em; color:var(--muted); }
.hc-breadcrumb{ display:flex; align-items:center; flex-wrap:wrap; gap:4px 8px; font-size:13.5px; color:var(--muted); }
.hc-breadcrumb a{ color:inherit; text-decoration:none; cursor:pointer; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%; }
.hc-breadcrumb a:hover{ color:var(--accent); }
.hc-breadcrumb svg{ flex-shrink:0; }
.hc-breadcrumb > span{ min-width:0; max-width:100%; }
.hc-pill-tag{ display:inline-block; padding:4px 11px; background:color-mix(in srgb, var(--accent) 11%, var(--surface)); color:var(--accent); font-size:12.5px; font-weight:600; border-radius:999px; }
a.hc-pill-tag{ text-decoration:none; cursor:pointer; }
a.hc-pill-tag:hover{ background:color-mix(in srgb, var(--accent) 22%, var(--surface)); }
.hc-header-bar{ height:70px; display:flex; align-items:center; gap:18px; }
.hc-brand-link{ flex-shrink:0; }
.hc-csat{ min-height:100vh; display:flex; align-items:center; justify-content:center; padding:24px; background:linear-gradient(180deg, color-mix(in srgb, var(--accent) 14%, var(--bg)), var(--bg)); }
.hc-bare{ min-height:100vh; padding:26px 0 60px; background:linear-gradient(180deg, color-mix(in srgb, var(--accent) 12%, var(--bg)), var(--bg) 420px); }
.hc-clean-input{ flex:1; min-width:0; border:none; background:none; font:inherit; color:var(--text); }
.hc-clean-input:focus{ outline:none; box-shadow:none; border:none; }
.hc-article-grid{ display:grid; grid-template-columns:250px minmax(0,1fr); gap:36px; align-items:start; }
.hc-article-solo > div{ max-width:880px; margin:0 auto; }
.hc-art-tree{ position:sticky; top:86px; font-size:14px; }
.hc-art-tree a{ display:block; padding:5px 10px; border-radius:8px; color:var(--muted); text-decoration:none; cursor:pointer; }
.hc-art-tree a:hover{ color:var(--text); background:color-mix(in srgb, var(--text) 6%, transparent); }
.hc-art-tree a.on{ color:var(--accent); font-weight:600; background:color-mix(in srgb, var(--accent) 9%, transparent); }
.hc-tree-lbl{ display:block; margin-bottom:8px; padding:0 10px; font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); }
@media (max-width:1000px){ .hc-article-grid{ grid-template-columns:1fr; } .hc-art-tree{ display:none; } .hc-art-box{ padding:20px 18px 6px; } }
.hc-banner{ background:color-mix(in srgb, var(--accent) 6%, var(--bg)); border-bottom:1px solid var(--border); }
.hc-banner-sub{ margin:8px 0 0; font-size:15px; line-height:22px; min-height:22px; color:var(--muted); }
.hc-art-meta{ display:flex; align-items:center; gap:8px 16px; flex-wrap:wrap; font-size:13.5px; color:var(--muted); padding-bottom:16px; border-bottom:1px solid var(--border); margin-bottom:24px; }
.hc-meta-item{ display:inline-flex; align-items:center; gap:7px; }
.hc-toc{ padding:14px 18px 12px; margin-bottom:26px; }
.hc-toc a{ display:block; padding:4px 0; font-size:14px; color:var(--muted); text-decoration:none; cursor:pointer; }
.hc-toc a:hover{ color:var(--accent); }
.hc-prose h2,.hc-prose h3{ scroll-margin-top:86px; }
.hc-art-box{ position:relative; padding:26px 32px 8px; border-radius:var(--radius-lg);
background:linear-gradient(180deg, var(--surface) 0%, var(--surface) calc(100% - 260px), transparent 100%); }
.hc-art-box::before{ content:''; position:absolute; inset:0; pointer-events:none;
border:1px solid var(--border); border-radius:inherit;
-webkit-mask-image:linear-gradient(180deg, #000 0%, #000 calc(100% - 260px), transparent 100%);
mask-image:linear-gradient(180deg, #000 0%, #000 calc(100% - 260px), transparent 100%); }
.hc-pills{ display:flex; flex-wrap:wrap; gap:8px; }
.hc-pills-c{ display:flex; flex-wrap:wrap; justify-content:center; gap:8px; }
.hc-hero-wrap{ position:relative; }
.hc-hero-drop{ position:absolute; top:calc(100% + 8px); left:0; right:0; z-index:40; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg); box-shadow:0 18px 50px -20px rgba(15,23,42,.45); overflow:hidden; text-align:left; }
.hc-hero-drop a{ display:block; padding:12px 18px; text-decoration:none; color:inherit; cursor:pointer; }
.hc-hero-drop a:hover{ background:color-mix(in srgb, var(--accent) 6%, var(--surface)); }
.hc-hero-drop a + a{ border-top:1px solid var(--border); }
.hc-hero-drop-all{ display:block; width:100%; padding:11px 18px; background:color-mix(in srgb, var(--accent) 8%, var(--surface)); color:var(--accent); border:none; border-top:1px solid var(--border); font:inherit; font-size:14px; font-weight:600; cursor:pointer; text-align:center; }
.hc-hero-drop-all:hover{ background:color-mix(in srgb, var(--accent) 14%, var(--surface)); }
.hc-hero-empty{ display:block; padding:14px 18px; font-size:14px; color:var(--muted); }
@media (max-width:760px){
.hc-header-bar{ gap:8px; }
.hc-header-bar .hc-nav-home{ display:none; }
.hc-search{ min-width:0; padding:0 11px; }
.hc-search .hc-search-label{ display:none; }
.hc-hero{ padding:44px 18px 40px; }
.hc-hero-box{ height:54px; padding:0 16px; }
.hc-brand-link{ flex-shrink:1; min-width:0; overflow:hidden; }
.hc-brand-link img{ max-width:100%; }
.hc-brand-link .hc-h{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
}
html.dark, html.dark body { background-color:#0f172a; }
.dark input:not([type=file]), .dark textarea, .dark select {
background-color:#1e293b; border-color:#475569; color:#e2e8f0;
}
.dark input::placeholder, .dark textarea::placeholder { color:#64748b; }
.dark input.hc-clean-input{ background-color:transparent; border-color:transparent; color:var(--text); }
.dark input.hc-clean-input::placeholder{ color:var(--muted); }
</style>
</head>
<body class="h-full text-slate-800 dark:text-slate-100" x-data="portalApp()" x-init="boot()" x-cloak
:style="brand.theme_color ? ('--brand:'+brand.theme_color) : ''">
<div id="nav-loading" x-show="pageLoading" x-cloak><span></span></div>
<template x-if="ready && unavailable">
<div style="min-height:100vh; display:flex; align-items:center; justify-content:center; padding:24px; font-family:system-ui,sans-serif;">
<div style="max-width:440px; text-align:center;">
<template x-if="brand.logo_url"><img :src="brand.logo_url" alt="" style="display:block; margin:0 auto; height:52px; width:auto; max-width:220px; border-radius:12px;"></template>
<template x-if="!brand.logo_url"><span style="display:inline-flex; width:52px; height:52px; align-items:center; justify-content:center; border-radius:14px; color:#fff; font-size:24px; font-weight:800;"
:style="'background:'+(brand.theme_color||'#64748b')" x-text="(brand.name||'?').slice(0,1)"></span></template>
<h1 style="margin:18px 0 8px; font-size:24px; font-weight:700;" x-text="(brand.name || 'This support portal')"></h1>
<p style="margin:0; font-size:15.5px; line-height:1.6; color:#64748b;">
The support portal is temporarily unavailable - please check back shortly.
If it's urgent, reply to any email you've received from us.
</p>
</div>
</div>
</template>
<template x-if="ready && !unavailable && design !== 'helpcenter'"><div>
<header class="border-b border-slate-200 bg-white dark:border-slate-700 dark:bg-slate-800" x-show="route.name!=='csat' && route.name!=='ticket'">
<div class="mx-auto flex max-w-3xl items-center justify-between px-4 py-4">
<a href="/" @click.prevent="go('/')" class="flex items-center gap-2.5">
<template x-if="brand.logo_url"><img :src="brand.logo_url" alt="" class="h-7 w-auto max-w-[140px] rounded"></template>
<template x-if="!brand.logo_url"><span class="inline-flex h-7 w-7 items-center justify-center rounded text-sm font-bold text-white" style="background:var(--brand,#2563eb)" x-text="(brand.name||'?').slice(0,1)"></span></template>
<span class="font-semibold" x-show="headerNameOn()" x-text="(brand.theme && brand.theme.site_title) || brand.name || 'Support'"></span>
</a>
<nav class="flex items-center gap-4 text-sm">
<button @click="go('/search')" class="text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white" x-show="brand.features && brand.features.kb" title="Search">🔍</button>
<a href="/tickets" @click.prevent="go('/tickets')" class="text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white" x-show="authed">My tickets</a>
<button @click="logout()" class="text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white" x-show="authed">Sign out</button>
<button @click="toggleDark()" :title="dark ? 'Switch to light mode' : 'Switch to dark mode'" class="text-base leading-none" x-text="dark ? '☀️' : '🌙'"></button>
</nav>
</div>
</header>
<main class="mx-auto max-w-3xl px-4 py-8">
<template x-if="flash"><div class="mb-4 rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-2 text-sm text-emerald-800 dark:border-emerald-800 dark:bg-emerald-950 dark:text-emerald-200" x-text="flash"></div></template>
<template x-if="error"><div class="mb-4 rounded-lg border border-rose-200 bg-rose-50 px-4 py-2 text-sm text-rose-800 dark:border-rose-800 dark:bg-rose-950 dark:text-rose-200" x-text="error"></div></template>
<section x-show="route.name==='home'" class="space-y-8">
<p class="text-slate-600 dark:text-slate-300" x-text="brand.description"></p>
<div x-show="brand.features && brand.features.submit" class="rounded-xl border border-slate-200 bg-white p-6 dark:border-slate-700 dark:bg-slate-800">
<h2 class="mb-4 text-lg font-semibold">Submit a request</h2>
<form @submit.prevent="submitTicket()" class="space-y-3">
<div class="grid gap-3 sm:grid-cols-2">
<input x-model="form.name" placeholder="Your name" required class="rounded-lg border-slate-300 text-sm">
<input x-model="form.email" type="email" placeholder="Email" required class="rounded-lg border-slate-300 text-sm">
</div>
<input x-model="form.subject" placeholder="Subject" required class="w-full rounded-lg border-slate-300 text-sm">
<textarea x-model="form.body" rows="5" placeholder="How can we help?" required class="w-full rounded-lg border-slate-300 text-sm"></textarea>
<input type="file" multiple x-ref="files" class="block text-xs text-slate-500 dark:text-slate-400">
<button class="rounded-lg px-4 py-2 text-sm font-medium text-white" style="background:var(--brand,#2563eb)">Send request</button>
</form>
</div>
<div x-show="brand.features && brand.features.kb" class="rounded-xl border border-slate-200 bg-white p-6 dark:border-slate-700 dark:bg-slate-800">
<h2 class="mb-4 text-lg font-semibold" x-text="helpLabel()"></h2>
<input x-model.debounce.300ms="kb.term" placeholder="Search articles…" class="w-full rounded-lg border-slate-300 text-sm">
<div x-show="tags.length" class="mt-3 flex flex-wrap gap-1.5">
<template x-for="t in tags" :key="t.slug">
<button @click="setTag(t.slug)" :class="kb.tag===t.slug ? 'ring-2 ring-blue-400 ring-offset-1' : 'opacity-80 hover:opacity-100'" class="rounded-full px-2.5 py-0.5 text-xs" :style="'background-color:'+(t.color||'#64748b')+';color:'+tagText(t.color)" x-text="t.name"></button>
</template>
</div>
<ul class="mt-3 divide-y divide-slate-100 dark:divide-slate-700">
<template x-for="a in kb.results" :key="a.slug">
<li><a :href="'/kb/'+a.slug" @click.prevent="go('/kb/'+a.slug)" class="block py-2 hover:bg-slate-50 dark:hover:bg-slate-700/50">
<span class="font-medium" x-text="a.title"></span>
<span class="block text-xs text-slate-400" x-text="a.excerpt"></span>
</a></li>
</template>
<template x-if="kb.term && !kb.results.length"><li class="py-2 text-sm text-slate-400">No matching articles.</li></template>
</ul>
</div>
<div class="rounded-xl border border-slate-200 bg-white p-6 dark:border-slate-700 dark:bg-slate-800">
<h2 class="mb-2 text-lg font-semibold">Track your requests</h2>
<p class="mb-3 text-sm text-slate-500 dark:text-slate-400">Enter your email and we'll send a secure link to view your tickets.</p>
<form @submit.prevent="requestAccess()" class="flex gap-2">
<input x-model="accessEmail" type="email" placeholder="you@example.com" required class="flex-1 rounded-lg border-slate-300 text-sm">
<button class="rounded-lg border border-slate-300 px-4 py-2 text-sm hover:bg-slate-50 dark:border-slate-600 dark:hover:bg-slate-700">Email me a link</button>
</form>
</div>
</section>
<section x-show="route.name==='category'" class="space-y-4">
<div class="rounded-xl border border-slate-200 bg-white p-6 dark:border-slate-700 dark:bg-slate-800">
<nav class="flex flex-wrap items-center gap-1.5 text-sm text-slate-500 dark:text-slate-400">
<a href="/" @click.prevent="go('/')" class="hover:text-slate-900 dark:hover:text-white" x-text="helpLabel()"></a>
<template x-for="(c, i) in (category.breadcrumb || [])" :key="c.slug">
<span class="flex items-center gap-1.5">
<span>›</span>
<a x-show="i < (category.breadcrumb || []).length - 1" href="#" @click.prevent="go('/category/'+c.slug)" class="hover:text-slate-900 dark:hover:text-white" x-text="c.name"></a>
<span x-show="i === (category.breadcrumb || []).length - 1" class="font-medium text-slate-700 dark:text-slate-200" x-text="c.name"></span>
</span>
</template>
</nav>
<h1 class="mt-3 text-2xl font-bold" x-text="category.name"></h1>
<p x-show="category.description" class="mt-1 text-sm text-slate-500 dark:text-slate-400" x-text="category.description"></p>
</div>
<div x-show="category.subcategories && category.subcategories.length" class="rounded-xl border border-slate-200 bg-white dark:border-slate-700 dark:bg-slate-800">
<p class="px-4 pt-4 text-xs font-semibold uppercase tracking-wide text-slate-400">Sub-categories</p>
<ul class="divide-y divide-slate-100 dark:divide-slate-700">
<template x-for="c in (category.subcategories || [])" :key="c.slug">
<li><a href="#" @click.prevent="go('/category/'+c.slug)" class="block px-4 py-3 hover:bg-slate-50 dark:hover:bg-slate-700/50">
<span class="font-medium" x-text="c.name"></span>
<span class="ml-2 text-xs text-blue-600 dark:text-blue-400" x-text="c.article_count + (c.article_count === 1 ? ' article' : ' articles')"></span>
<span x-show="c.description" class="mt-0.5 block text-xs text-slate-500 dark:text-slate-400" x-text="c.description"></span>
</a></li>
</template>
</ul>
</div>
<div x-show="(category.articles && category.articles.length) || !(category.subcategories && category.subcategories.length)"
class="rounded-xl border border-slate-200 bg-white dark:border-slate-700 dark:bg-slate-800">
<p x-show="category.articles && category.articles.length" class="px-4 pt-4 text-xs font-semibold uppercase tracking-wide text-slate-400">Articles</p>
<ul class="divide-y divide-slate-100 dark:divide-slate-700">
<template x-for="a in (category.articles || [])" :key="a.slug">
<li><a href="#" @click.prevent="go('/kb/'+a.slug)" class="block px-4 py-3 hover:bg-slate-50 dark:hover:bg-slate-700/50">
<span class="font-medium" x-text="a.title"></span>
<span class="mt-0.5 block text-xs text-slate-500 dark:text-slate-400" x-text="a.excerpt"></span>
</a></li>
</template>
<template x-if="!(category.articles && category.articles.length) && !(category.subcategories && category.subcategories.length)"><li class="px-4 py-6 text-sm text-slate-400">No articles in this category yet.</li></template>
</ul>
</div>
</section>
<section x-show="route.name==='article'" class="rounded-xl border border-slate-200 bg-white p-6 dark:border-slate-700 dark:bg-slate-800">
<a href="/" @click.prevent="go('/')" class="text-sm text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white" x-text="'← ' + helpLabel()"></a>
<h1 class="mt-3 text-2xl font-bold" x-text="article.title"></h1>
<p x-show="!article.html && !error" class="mt-4 text-sm text-slate-400">Loading…</p>
<div class="prose prose-sm mt-4 max-w-none dark:prose-invert" x-html="article.html"></div>
<div class="mt-4 flex flex-wrap gap-1.5" x-show="article.tags && article.tags.length">
<template x-for="t in article.tags" :key="t.slug">
<a :href="base+'/tag/'+t.slug" @click.prevent="go('/tag/'+encodeURIComponent(t.slug))" class="rounded-full px-2.5 py-0.5 text-xs opacity-90 hover:opacity-100" :style="'background-color:'+(t.color||'#64748b')+';color:'+tagText(t.color)" x-text="t.name" :title="'All articles tagged '+t.name"></a>
</template>
</div>
<div class="mt-6 border-t border-slate-100 pt-4 dark:border-slate-700" x-show="article.related && article.related.length">
<p class="mb-2 text-xs font-semibold uppercase tracking-wide text-slate-400">Related articles</p>
<ul class="space-y-1 text-sm">
<template x-for="ra in (article.related || [])" :key="ra.slug">
<li><a href="#" @click.prevent="go('/kb/'+ra.slug)" class="text-blue-600 hover:underline dark:text-blue-400" x-text="ra.title"></a></li>
</template>
</ul>
</div>
<div class="mt-6 flex items-center gap-3 border-t border-slate-100 pt-4 text-sm dark:border-slate-700">
<span class="text-slate-500 dark:text-slate-400" x-text="articleHelpful===null ? 'Was this article helpful?' : 'Thanks for your feedback!'"></span>
<div class="flex gap-2" x-show="articleHelpful===null">
<button @click="rateArticle(true)" class="rounded-lg border border-slate-300 px-3 py-1 hover:bg-slate-50 dark:border-slate-600 dark:hover:bg-slate-700">👍 Yes</button>
<button @click="rateArticle(false)" class="rounded-lg border border-slate-300 px-3 py-1 hover:bg-slate-50 dark:border-slate-600 dark:hover:bg-slate-700">👎 No</button>
</div>
</div>
</section>
<section x-show="route.name==='search'" class="space-y-4">
<div class="rounded-xl border border-slate-200 bg-white p-4 dark:border-slate-700 dark:bg-slate-800">
<div class="flex items-center gap-2">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-slate-400"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
<input x-model.debounce.250ms="search.term" x-ref="searchBox" placeholder="Search the help center…" class="w-full border-0 bg-transparent p-0 text-sm focus:ring-0">
</div>
</div>
<div x-show="search.categories.length" class="rounded-xl border border-slate-200 bg-white p-4 dark:border-slate-700 dark:bg-slate-800">
<p class="mb-2 text-xs font-semibold uppercase tracking-wide text-slate-400">Categories</p>
<div class="flex flex-wrap gap-2">
<template x-for="c in search.categories" :key="c.slug">
<a href="#" @click.prevent="go('/category/'+c.slug)" class="rounded-full border border-slate-200 px-2.5 py-0.5 text-xs hover:border-blue-400 dark:border-slate-600" x-text="c.name"></a>
</template>
</div>
</div>
<div class="rounded-xl border border-slate-200 bg-white dark:border-slate-700 dark:bg-slate-800">
<ul class="divide-y divide-slate-100 dark:divide-slate-700">
<template x-for="a in search.articles" :key="a.slug">
<li><a href="#" @click.prevent="go('/kb/'+a.slug)" class="block px-4 py-3 hover:bg-slate-50 dark:hover:bg-slate-700/50">
<span class="font-medium" x-text="a.title"></span>
<span x-show="a.category" class="ml-2 text-xs text-blue-600 dark:text-blue-400" x-text="a.category"></span>
<span class="mt-0.5 block text-xs text-slate-500 dark:text-slate-400" x-html="a.snippet"></span>
</a></li>
</template>
<template x-if="search.done && !search.articles.length && !search.categories.length"><li class="px-4 py-6 text-sm text-slate-400">No results for “<span x-text="search.term"></span>”.</li></template>
<template x-if="!search.term.trim()"><li class="px-4 py-6 text-sm text-slate-400">Type to search articles and categories.</li></template>
</ul>
</div>
</section>
<section x-show="route.name==='login'" class="rounded-xl border border-slate-200 bg-white p-6 text-sm text-slate-600 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300">
<span x-text="loginMsg"></span>
</section>
<section x-show="route.name==='tickets'" class="rounded-xl border border-slate-200 bg-white dark:border-slate-700 dark:bg-slate-800">
<h2 class="border-b border-slate-200 px-6 py-4 text-lg font-semibold dark:border-slate-700">My tickets</h2>
<ul class="divide-y divide-slate-100 dark:divide-slate-700">
<template x-for="t in tickets" :key="t.reference">
<li><a :href="'/tickets/'+t.reference" @click.prevent="go('/tickets/'+t.reference)" class="flex items-center justify-between px-6 py-3 hover:bg-slate-50 dark:hover:bg-slate-700/50">
<span><span class="font-medium" x-text="t.subject"></span><span class="block text-xs text-slate-400" x-text="t.reference + ' · ' + t.messages + ' messages'"></span></span>
<span class="rounded-full bg-slate-100 px-2 py-0.5 text-xs capitalize dark:bg-slate-700 dark:text-slate-200" x-text="t.status.replace(/_/g,' ')"></span>
</a></li>
</template>
<template x-if="!tickets.length"><li class="px-6 py-6 text-sm text-slate-400">No tickets yet.</li></template>
</ul>
</section>
<section x-show="route.name==='ticket'" class="space-y-4 rounded-2xl p-4"
:style="{ background: 'linear-gradient(180deg, color-mix(in srgb, '+(brand.theme_color||'#2563eb')+' 10%, transparent), transparent 380px)' }">
<a href="/tickets" @click.prevent="go('/tickets')" x-show="authed || !guestKey" class="text-sm text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white">← My tickets</a>
<div class="rounded-xl border border-slate-200 bg-white p-6 dark:border-slate-700 dark:bg-slate-800">
<div class="flex items-center justify-between">
<h1 class="text-xl font-semibold" x-text="ticket.subject"></h1>
<span class="rounded-full bg-slate-100 px-2 py-0.5 text-xs capitalize dark:bg-slate-700 dark:text-slate-200" x-text="(ticket.status||'').replace(/_/g,' ')"></span>
</div>
<p class="text-xs text-slate-400" x-text="ticket.reference"></p>
</div>
<div x-show="ticket.locked" class="flex flex-wrap items-center justify-between gap-3 rounded-xl border border-slate-200 bg-white p-4 text-sm text-slate-500 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-400">
<span>This ticket is closed and can no longer be replied to.</span>
<button x-show="brand.features && brand.features.submit" @click="go('/')" class="rounded-lg px-3 py-1.5 text-sm font-medium text-white" style="background:var(--brand,#2563eb)">Open a new ticket</button>
</div>
<form x-show="!ticket.locked" @submit.prevent="sendReply()" class="rounded-xl border border-slate-200 bg-white p-4 dark:border-slate-700 dark:bg-slate-800">
<textarea x-model="replyBody" rows="4" placeholder="Write a reply…" required class="w-full rounded-lg border-slate-300 text-sm"></textarea>
<div class="mt-2 flex items-center justify-between">
<input type="file" multiple x-ref="replyFiles" class="text-xs text-slate-500 dark:text-slate-400">
<button class="rounded-lg px-4 py-2 text-sm font-medium text-white" style="background:var(--brand,#2563eb)">Send reply</button>
</div>
</form>
<template x-for="r in [...ticket.replies].reverse()" :key="r.id">
<div class="rounded-xl border p-4"
:class="r.author==='you'
? 'border-slate-200 bg-white dark:border-slate-700 dark:bg-slate-800'
: 'border-sky-200 bg-sky-50 dark:border-sky-900 dark:bg-sky-950/40'">
<p class="mb-1 text-xs font-medium" :class="r.author==='you' ? 'text-slate-500 dark:text-slate-400' : 'text-sky-700 dark:text-sky-300'">
<span x-text="r.author==='you' ? 'You' : (r.author_name||'Support')"></span> · <span x-text="new Date(r.created_at).toLocaleString()"></span>
</p>
<div class="whitespace-pre-line text-sm text-slate-700 dark:text-slate-200" x-text="r.body"></div>
<div class="mt-2 flex flex-wrap gap-2" x-show="r.attachments && r.attachments.length">
<template x-for="a in r.attachments" :key="a.token">
<button @click="openAttachment(a)" class="rounded border border-slate-200 px-2 py-1 text-xs text-slate-600 hover:bg-slate-50 dark:border-slate-600 dark:text-slate-300 dark:hover:bg-slate-700"><span x-text="a.kind ? '👁' : '📎'"></span> <span x-text="a.name"></span> <span class="text-slate-400" x-text="'('+a.size+')'"></span></button>
</template>
</div>
</div>
</template>
</section>
<section x-show="route.name==='csat'" class="flex min-h-[80vh] items-center justify-center rounded-2xl p-6"
:style="{ background: 'linear-gradient(180deg, color-mix(in srgb, '+(brand.theme_color||'#2563eb')+' 12%, transparent), transparent)' }">
<div class="w-full max-w-md rounded-xl border border-slate-200 bg-white p-6 text-center shadow-lg dark:border-slate-700 dark:bg-slate-800">
<template x-if="!csat.rated">
<div>
<h1 class="text-xl font-semibold">How did we do?</h1>
<p class="mt-1 text-sm text-slate-500 dark:text-slate-400" x-text="csat.subject"></p>
<div class="mt-4 flex justify-center gap-2">
<template x-for="n in 5" :key="n">
<button @click="csat.score=n" class="text-3xl transition" :class="csat.score>=n ? 'opacity-100' : 'opacity-30'">⭐</button>
</template>
</div>
<textarea x-model="csat.comment" rows="3" placeholder="Any comments? (optional)" class="mt-4 w-full rounded-lg border-slate-300 text-sm"></textarea>
<button @click="submitCsat()" :disabled="!csat.score" class="mt-3 rounded-lg px-4 py-2 text-sm font-medium text-white disabled:opacity-50" style="background:var(--brand,#2563eb)">Submit rating</button>
</div>
</template>
<template x-if="csat.rated"><p class="text-lg">Thanks for your feedback! 🙏</p></template>
</div>
</section>
</main>
</div></template>
<template x-if="ready && !unavailable && design === 'helpcenter'"><div class="hc" :style="'--accent:'+(brand.theme_color||'#2563eb')">
<header class="hc-header" x-show="route.name!=='csat' && route.name!=='ticket'">
<div class="hc-wrap hc-header-bar">
<a href="/" @click.prevent="go('/')" class="hc-brand-link" style="display:flex; align-items:center; gap:11px; text-decoration:none; color:inherit; cursor:pointer;">
<template x-if="brand.logo_url"><img :src="brand.logo_url" alt="" style="height:34px; width:auto; max-width:160px; border-radius:9px;"></template>
<template x-if="!brand.logo_url"><span class="hc-logo-mark" style="font-size:18px;" x-text="(brand.name||'?').slice(0,1)"></span></template>
<span class="hc-h" x-show="headerNameOn()" style="font-weight:800; font-size:20px;" x-text="(brand.theme && brand.theme.site_title) || brand.name || 'Help center'"></span>
</a>
<nav style="display:flex; align-items:center; gap:2px; margin-left:6px;">
<a class="hc-navlink hc-nav-home" href="/" @click.prevent="go('/')" x-text="helpLabel()"></a>
</nav>
<div style="margin-left:auto; display:flex; align-items:center; gap:10px;">
<button class="hc-search" @click="go('/search')" x-show="brand.features && brand.features.kb">
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
<span class="hc-search-label">Search</span>
</button>
<button class="hc-cta" @click="go('/submit')" x-show="brand.features && brand.features.submit">Submit a request</button>
<a class="hc-navlink" href="/tickets" @click.prevent="go('/tickets')" x-show="authed">My tickets</a>
<button class="hc-navlink" style="border:none; background:none; font:inherit;" @click="logout()" x-show="authed">Sign out</button>
<button class="hc-navlink" style="border:none; background:none;" @click="toggleDark()" :title="dark ? 'Light mode' : 'Dark mode'" x-text="dark ? '☀️' : '🌙'"></button>
</div>
</div>
</header>
<main>
<div class="hc-wrap" x-show="(flash || error) && route.name !== 'home'" x-cloak style="padding-top:16px;">
<template x-if="flash"><div style="padding:10px 16px; border-radius:var(--radius); background:color-mix(in srgb,#10b981 14%,var(--surface)); border:1px solid color-mix(in srgb,#10b981 35%,transparent); font-size:14px; margin-bottom:8px;" x-text="flash"></div></template>
<template x-if="error"><div style="padding:10px 16px; border-radius:var(--radius); background:color-mix(in srgb,#ef4444 12%,var(--surface)); border:1px solid color-mix(in srgb,#ef4444 35%,transparent); font-size:14px; margin-bottom:8px;" x-text="error"></div></template>
</div>
<div x-show="route.name==='home'">
<section class="hc-hero">
<div style="max-width:760px; margin:0 auto; text-align:center;">
<template x-if="flash"><div style="margin:0 auto 22px; max-width:560px; padding:10px 16px; border-radius:var(--radius); background:color-mix(in srgb,#10b981 14%,var(--surface)); border:1px solid color-mix(in srgb,#10b981 35%,transparent); font-size:14px;" x-text="flash"></div></template>
<template x-if="error"><div style="margin:0 auto 22px; max-width:560px; padding:10px 16px; border-radius:var(--radius); background:color-mix(in srgb,#ef4444 12%,var(--surface)); border:1px solid color-mix(in srgb,#ef4444 35%,transparent); font-size:14px;" x-text="error"></div></template>
<h1 class="hc-h" style="font-weight:800; font-size:clamp(30px,6vw,42px); line-height:1.08; margin:0 0 14px;" x-text="(brand.theme && brand.theme.hero_title) || 'How can we help?'">How can we help?</h1>
<p style="font-size:18px; line-height:1.5; color:var(--muted); margin:0 0 28px;" x-text="(brand.theme && brand.theme.hero_subtitle) || brand.description || 'Search our guides, or browse the articles below.'"></p>
<div class="hc-hero-wrap" x-show="brand.features && brand.features.kb" @click.outside="hero.open = false">
<label class="hc-hero-box">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
<input x-model.debounce.250ms="hero.term" @focus="hero.term.trim() && (hero.open = true)"
@keydown.enter.prevent="hero.term = $event.target.value; heroGo()" placeholder="Search for articles…"
autocomplete="off" data-bwignore data-1p-ignore data-lpignore="true"
class="hc-clean-input" style="font-size:17px;">
</label>
<div class="hc-hero-drop" x-show="hero.open && hero.term.trim()" x-cloak>
<template x-for="a in hero.results" :key="a.slug">
<a href="#" @click.prevent="hero.open = false; go('/kb/'+a.slug)">
<span style="display:block; font-weight:600; font-size:15px;" x-text="a.title"></span>
<span style="display:block; font-size:13px; color:var(--muted); margin-top:2px;" x-html="a.snippet"></span>
</a>
</template>
<template x-if="!hero.results.length"><span class="hc-hero-empty">No matches yet - press Enter to search everything.</span></template>
<button class="hc-hero-drop-all" x-show="hero.results.length" @click="heroGo()">See all results</button>
</div>
</div>
<button class="hc-cta" style="margin-top:8px;" @click="go('/submit')" x-show="brand.features && brand.features.submit && !(brand.features && brand.features.kb)">Submit a request</button>
</div>
</section>
<section class="hc-wrap" style="padding:48px 24px 10px;" x-show="categories.length && !kb.tag">
<h2 class="hc-h" style="font-weight:700; font-size:24px; margin:0 0 18px;">Browse by category</h2>
<div style="display:grid; grid-template-columns:repeat(auto-fill,minmax(min(300px,100%),1fr)); gap:16px;">
<template x-for="c in categories" :key="c.slug">
<a class="hc-card" href="#" @click.prevent="go('/category/'+c.slug)"
style="display:flex; flex-direction:column; gap:10px; padding:22px; text-decoration:none; color:inherit; transition:.16s;"
@mouseenter="$el.style.borderColor='var(--accent)'" @mouseleave="$el.style.borderColor='var(--border)'">
<span class="hc-art-icon" style="width:44px; height:44px;"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg></span>
<span class="hc-h" style="font-weight:700; font-size:17px;" x-text="c.name"></span>
<span style="font-size:13.5px; line-height:1.5; color:var(--muted); flex:1;" x-text="c.description"></span>
<span style="font-size:13px; font-weight:600; color:var(--accent);" x-text="c.article_count + (c.children.length ? ' articles · '+c.children.length+' sub-categories' : ' articles')"></span>
</a>
</template>
</div>
</section>
<section class="hc-wrap" style="padding:38px 24px 44px;" x-show="brand.features && brand.features.kb">
<div style="display:flex; align-items:baseline; gap:14px; flex-wrap:wrap; margin:0 0 18px;">
<h2 class="hc-h" style="font-weight:700; font-size:24px; margin:0;" x-text="kb.tag ? ('Articles tagged “' + tagName(kb.tag) + '”') : (categories.length ? 'Popular articles' : 'Browse articles')"></h2>
<a href="/" @click.prevent="go('/')" x-show="kb.tag" x-cloak style="font-size:13.5px; font-weight:600; color:var(--accent); text-decoration:none; cursor:pointer;">× Show all articles</a>
</div>
<div class="hc-grid">
<template x-for="a in kb.results" :key="a.slug">
<a class="hc-art" href="#" @click.prevent="go('/kb/'+a.slug)">
<span class="hc-art-icon"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M14 3v5h5M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/></svg></span>
<span style="flex:1; min-width:0;"><span style="display:block; font-weight:600; font-size:15px;" x-text="a.title"></span><span style="display:block; font-size:13px; color:var(--muted); margin-top:2px;" x-text="a.excerpt"></span></span>
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="var(--muted)" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</a>
</template>
<template x-if="!kb.results.length && !pageLoading && kb.tag"><p style="color:var(--muted);">No articles carry this tag yet.</p></template>
<template x-if="!kb.results.length && !pageLoading && !kb.tag"><p style="color:var(--muted);">No articles published yet.</p></template>
</div>
</section>
<section class="hc-wrap" style="padding:0 24px 70px;" x-show="brand.features && brand.features.submit">
<div class="hc-card" style="padding:26px; display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap;">
<span>
<span class="hc-h" style="display:block; font-weight:700; font-size:18px;">Still need help?</span>
<span style="font-size:14.5px; color:var(--muted);">Can't find what you're looking for? Send us the details and we'll get back to you.</span>
</span>
<button class="hc-cta" @click="go('/submit')">Submit a request</button>
</div>
</section>
</div>
<div x-show="route.name==='category'">
<div class="hc-banner">
<div class="hc-wrap" style="padding:26px 24px 30px;">
<nav class="hc-breadcrumb" style="margin-bottom:14px;">
<a href="/" @click.prevent="go('/')" x-text="helpLabel()"></a>
<template x-for="c in (category.breadcrumb || []).slice(0, -1)" :key="c.slug">
<span style="display:inline-flex; align-items:center; gap:8px;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
<a href="#" @click.prevent="go('/category/'+c.slug)" x-text="c.name"></a>
</span>
</template>
</nav>
<h1 class="hc-h" style="font-weight:800; font-size:30px; margin:0;" x-text="category.name"></h1>
<p class="hc-banner-sub" x-text="category.description"></p>
</div>
</div>
<div class="hc-wrap" :class="articleTreeOn() && categories.length ? 'hc-article-grid' : 'hc-article-solo'" style="padding:30px 24px 70px;">
<aside class="hc-art-tree" x-show="articleTreeOn() && categories.length" x-cloak>
<span class="hc-tree-lbl">Browse</span>
<template x-for="c in categories" :key="c.slug">
<div>
<a href="#" @click.prevent="go('/category/'+c.slug)" :class="inCategoryPath(c.slug) ? 'on' : ''" x-text="c.name"></a>
<div x-show="inCategoryPath(c.slug)" style="margin-left:12px;">
<template x-if="c.slug === category.slug">
<div>
<template x-for="na in (category.articles || [])" :key="na.slug">
<a href="#" @click.prevent="go('/kb/'+na.slug)" style="font-size:13px;" x-text="na.title"></a>
</template>
</div>
</template>
<template x-for="sc in (c.children || [])" :key="sc.slug">
<div>
<a href="#" @click.prevent="go('/category/'+sc.slug)" :class="inCategoryPath(sc.slug) ? 'on' : ''" x-text="sc.name"></a>
<template x-if="sc.slug === category.slug">
<div style="margin-left:12px;">
<template x-for="na in (category.articles || [])" :key="na.slug">
<a href="#" @click.prevent="go('/kb/'+na.slug)" style="font-size:13px;" x-text="na.title"></a>
</template>
</div>
</template>
</div>
</template>
</div>
</div>
</template>
</aside>
<div style="min-width:0;">
<div x-show="category.subcategories && category.subcategories.length" style="margin-bottom:30px;">
<span style="display:block; font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); margin-bottom:12px;">Sub-categories</span>
<div style="display:grid; grid-template-columns:repeat(auto-fill,minmax(min(280px,100%),1fr)); gap:12px;">
<template x-for="c in (category.subcategories || [])" :key="c.slug">
<a class="hc-art" href="#" @click.prevent="go('/category/'+c.slug)" style="align-items:flex-start;">
<span class="hc-art-icon"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg></span>
<span style="flex:1; min-width:0;">
<span style="display:block; font-weight:600;" x-text="c.name"></span>
<span x-show="c.description" style="display:block; font-size:13px; color:var(--muted); margin-top:2px; line-height:1.45;" x-text="c.description"></span>
<span style="display:block; font-size:12.5px; font-weight:600; color:var(--accent); margin-top:6px;" x-text="c.article_count + (c.article_count === 1 ? ' article' : ' articles')"></span>
</span>
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="var(--muted)" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="margin-top:3px;"><path d="m9 18 6-6-6-6"/></svg>
</a>
</template>
</div>
</div>
<span x-show="category.subcategories && category.subcategories.length && category.articles && category.articles.length"
style="display:block; font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); margin-bottom:12px;">Articles</span>
<div style="display:flex; flex-direction:column; gap:10px;">
<template x-for="a in (category.articles || [])" :key="a.slug">
<a class="hc-art" href="#" @click.prevent="go('/kb/'+a.slug)">
<span class="hc-art-icon"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M14 3v5h5M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/></svg></span>
<span style="flex:1; min-width:0;"><span style="display:block; font-weight:600; font-size:15px;" x-text="a.title"></span><span style="display:block; font-size:13px; color:var(--muted); margin-top:2px;" x-text="a.excerpt"></span></span>
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="var(--muted)" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</a>
</template>
<template x-if="!(category.articles && category.articles.length) && !(category.subcategories && category.subcategories.length)"><p style="color:var(--muted);">No articles in this category yet.</p></template>
</div>
<div x-show="category.related && category.related.length" style="margin-top:34px;">
<span style="display:block; font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); margin-bottom:12px;">Related categories</span>
<div style="display:flex; flex-wrap:wrap; gap:8px;">
<template x-for="c in (category.related || [])" :key="c.slug">
<a class="hc-pill" href="#" @click.prevent="go('/category/'+c.slug)" x-text="c.name"></a>
</template>
</div>
</div>
</div>
</div>
</div>
<div x-show="route.name==='search'">
<div style="background:color-mix(in srgb, var(--accent) 6%, var(--bg)); border-bottom:1px solid var(--border);">
<div class="hc-wrap" style="padding:30px 24px;">
<div class="hc-hero-box" style="max-width:680px; cursor:text;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
<input x-model.debounce.250ms="search.term" x-ref="searchBox" placeholder="Search the help center…" class="hc-clean-input" style="font-size:17px;">
</div>
</div>
</div>
<section class="hc-wrap" style="padding:28px 24px 70px;">
<p x-show="search.done && search.term.trim() && !search.loading" style="margin:0 0 18px; font-size:14px; color:var(--muted);"
x-text="search.articles.length + (search.articles.length === 1 ? ' article matches' : ' articles match') + ' “' + search.term.trim() + '”'"></p>
<p x-show="search.loading" style="margin:0 0 18px; font-size:14px; color:var(--muted);">Searching…</p>
<div x-show="search.categories.length" style="margin-bottom:22px;">
<span style="display:block; font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); margin-bottom:10px;">Categories</span>
<div style="display:flex; flex-wrap:wrap; gap:8px;">
<template x-for="c in search.categories" :key="c.slug">
<a class="hc-pill" href="#" @click.prevent="go('/category/'+c.slug)" x-text="c.name"></a>
</template>
</div>
</div>
<div style="display:flex; flex-direction:column; gap:10px;">
<template x-for="a in search.articles" :key="a.slug">
<a class="hc-art" href="#" @click.prevent="go('/kb/'+a.slug)" style="align-items:flex-start;">
<span style="flex:1; min-width:0;">
<span style="display:block; font-weight:600; font-size:15.5px;" x-text="a.title"></span>
<span x-show="a.category" style="display:inline-block; margin-top:2px; font-size:12px; color:var(--accent);" x-text="a.category"></span>
<span class="hc-snippet" style="display:block; font-size:13.5px; color:var(--muted); margin-top:4px; line-height:1.5;" x-html="a.snippet"></span>
</span>
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="var(--muted)" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" style="margin-top:3px;"><path d="m9 18 6-6-6-6"/></svg>
</a>
</template>
<template x-if="search.done && !search.articles.length && !search.categories.length"><p style="color:var(--muted);">No results for “<span x-text="search.term"></span>”.</p></template>
<template x-if="!search.term.trim()"><p style="color:var(--muted);">Type to search articles and categories.</p></template>
</div>
</section>
</div>
<div x-show="route.name==='article'">
<div class="hc-banner">
<div class="hc-wrap" style="padding:26px 24px 30px;">
<nav class="hc-breadcrumb" style="margin-bottom:14px;">
<a href="/" @click.prevent="go('/')" x-text="helpLabel()"></a>
<template x-for="c in (article.category ? article.category.breadcrumb : [])" :key="c.slug">
<span style="display:inline-flex; align-items:center; gap:8px;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
<a href="#" @click.prevent="go('/category/'+c.slug)" x-text="c.name"></a>
</span>
</template>
</nav>
<h1 class="hc-h" style="font-weight:800; font-size:30px; margin:0;" x-text="article.title"></h1>
<p class="hc-banner-sub"></p>
</div>
</div>
<div class="hc-wrap" :class="articleTreeOn() && categories.length ? 'hc-article-grid' : 'hc-article-solo'" style="padding:30px 24px 70px;">
<aside class="hc-art-tree" x-show="articleTreeOn() && categories.length" x-cloak>
<span class="hc-tree-lbl">Browse</span>
<template x-for="c in categories" :key="c.slug">
<div>
<a href="#" @click.prevent="go('/category/'+c.slug)" :class="inArticlePath(c.slug) ? 'on' : ''" x-text="c.name"></a>
<div x-show="inArticlePath(c.slug)" style="margin-left:12px;">
<template x-if="article.category && c.slug === article.category.slug">
<div>
<template x-for="na in articleNav.articles" :key="na.slug">
<a href="#" @click.prevent="go('/kb/'+na.slug)" :class="na.slug === article.slug ? 'on' : ''" style="font-size:13px;" x-text="na.title"></a>
</template>
</div>
</template>
<template x-for="sc in (c.children || [])" :key="sc.slug">
<div>
<a href="#" @click.prevent="go('/category/'+sc.slug)" :class="inArticlePath(sc.slug) ? 'on' : ''" x-text="sc.name"></a>
<template x-if="article.category && sc.slug === article.category.slug">
<div style="margin-left:12px;">
<template x-for="na in articleNav.articles" :key="na.slug">
<a href="#" @click.prevent="go('/kb/'+na.slug)" :class="na.slug === article.slug ? 'on' : ''" style="font-size:13px;" x-text="na.title"></a>
</template>
</div>
</template>
</div>
</template>
</div>
</div>
</template>
</aside>
<div style="min-width:0; max-width:880px;">
<div class="hc-art-box">
<p x-show="!article.html && !error" style="color:var(--muted);">Loading…</p>
<div class="hc-art-meta" x-show="article.html" x-cloak>
<span class="hc-meta-item">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>
<span x-text="readingTime()"></span>
</span>
<span class="hc-meta-item" x-show="article.updated_at">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M16 3v4M8 3v4M3 11h18"/></svg>
<span x-text="articleUpdated()"></span>
</span>
<template x-for="t in (article.tags || [])" :key="t.slug">
<a class="hc-pill-tag" :href="base+'/tag/'+t.slug" @click.prevent="go('/tag/'+encodeURIComponent(t.slug))" x-text="t.name" :title="'All articles tagged '+t.name"></a>
</template>
</div>
<div class="hc-card hc-toc" x-show="toc.length >= 2" x-cloak>
<span class="hc-tree-lbl" style="padding:0;">In this article</span>
<template x-for="h in toc" :key="h.id">
<a href="#" @click.prevent="scrollToHeading(h.id)" :style="h.level === 3 ? 'padding-left:16px;' : ''" x-text="h.text"></a>
</template>
</div>
<div class="hc-prose" x-ref="artBody" x-html="article.html"></div>
</div>
<div class="hc-card" style="margin-top:26px; padding:22px; display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap;">
<span class="hc-h" style="font-weight:600; font-size:16px;" x-text="articleHelpful===null ? 'Was this article helpful?' : 'Thanks for your feedback!'"></span>
<div style="display:flex; gap:10px;" x-show="articleHelpful===null">
<button class="hc-btn hc-btn-ghost" @click="rateArticle(true)">👍 Yes</button>
<button class="hc-btn hc-btn-ghost" @click="rateArticle(false)">👎 No</button>
</div>
<span x-show="articleHelpful===false && brand.features && brand.features.submit" style="font-size:14px; color:var(--muted);">
Sorry this didn't help - <a href="#" @click.prevent="go('/submit')" style="color:var(--accent); font-weight:600;">contact support</a> and we'll get you sorted.
</span>
</div>
<div x-show="article.related && article.related.length" style="margin-top:30px;">
<span style="display:block; font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); margin-bottom:12px;">Related articles</span>
<div style="display:flex; flex-direction:column; gap:8px;">
<template x-for="ra in (article.related || [])" :key="ra.slug">
<a class="hc-art" href="#" @click.prevent="go('/kb/'+ra.slug)" style="padding:13px 16px;">
<span style="flex:1; min-width:0; font-weight:600; font-size:14.5px;" x-text="ra.title"></span>
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="var(--muted)" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
</a>
</template>
</div>
</div>
</div>
</div>
</div>
<div x-show="route.name==='submit' && !(brand.features && brand.features.submit)" class="hc-wrap" style="max-width:680px; padding:40px 24px 70px;">
<div class="hc-card" style="padding:24px; color:var(--muted);">Ticket submission is not available on this portal.</div>
</div>
<div x-show="route.name==='submit' && brand.features && brand.features.submit" class="hc-wrap" style="max-width:680px; padding:40px 24px 70px;">
<h1 class="hc-h" style="font-weight:800; font-size:30px; margin:0 0 18px;">Submit a request</h1>
<form @submit.prevent="submitTicket()" style="display:flex; flex-direction:column; gap:12px;">
<input class="hc-input" x-model="form.name" placeholder="Your name" required>
<input class="hc-input" x-model="form.email" type="email" placeholder="Email" required>
<input class="hc-input" x-model="form.subject" placeholder="Subject" required>
<textarea class="hc-input" x-model="form.body" rows="6" placeholder="How can we help?" required style="height:auto; padding:12px 16px;"></textarea>
<input type="file" multiple x-ref="files" style="font-size:13px; color:var(--muted);">
<button class="hc-btn" style="align-self:flex-start;">Send request</button>
</form>
</div>
<div x-show="route.name==='login'" class="hc-wrap" style="max-width:520px; padding:50px 24px;">
<div class="hc-card" style="padding:24px;"><span style="color:var(--muted);" x-text="loginMsg"></span></div>
</div>
<div x-show="route.name==='tickets'" class="hc-wrap" style="max-width:760px; padding:40px 24px;">
<h1 class="hc-h" style="font-weight:800; font-size:26px; margin:0 0 18px;">My tickets</h1>
<div style="display:flex; flex-direction:column; gap:10px;">
<template x-for="t in tickets" :key="t.reference">
<a class="hc-art" href="#" @click.prevent="go('/tickets/'+t.reference)">
<span style="flex:1; min-width:0;"><span style="display:block; font-weight:600;" x-text="t.subject"></span><span style="display:block; font-size:13px; color:var(--muted);" x-text="t.reference + ' · ' + t.messages + ' messages'"></span></span>
<span class="hc-pill-tag" x-text="t.status.replace(/_/g,' ')"></span>
</a>
</template>
<template x-if="!tickets.length"><p style="color:var(--muted);">No tickets yet.</p></template>
</div>
</div>
<div x-show="route.name==='ticket'" class="hc-bare">
<div class="hc-wrap" style="max-width:760px; padding:0 24px;">
<a href="/" @click.prevent="go('/')" style="display:inline-flex; align-items:center; gap:10px; margin-bottom:16px; text-decoration:none; color:inherit; cursor:pointer;">
<template x-if="brand.logo_url"><img :src="brand.logo_url" alt="" style="height:30px; width:auto; max-width:140px; border-radius:8px;"></template>
<template x-if="!brand.logo_url"><span class="hc-logo-mark" style="width:30px; height:30px; font-size:15px;" x-text="(brand.name||'?').slice(0,1)"></span></template>
<span class="hc-h" x-show="headerNameOn()" style="font-weight:700; font-size:16px;" x-text="brand.name || 'Support'"></span>
</a>
<br>
<a class="hc-breadcrumb" href="/tickets" @click.prevent="go('/tickets')" x-show="authed || !guestKey" style="margin-bottom:16px;">← My tickets</a>
<div class="hc-card" style="padding:22px; margin:14px 0;">
<div style="display:flex; align-items:center; justify-content:space-between; gap:12px;">
<h1 class="hc-h" style="font-weight:700; font-size:22px;" x-text="ticket.subject"></h1>
<span class="hc-pill-tag" x-text="(ticket.status||'').replace(/_/g,' ')"></span>
</div>
<p style="font-size:12px; color:var(--muted); margin-top:4px;" x-text="ticket.reference"></p>
</div>
<div x-show="ticket.locked" class="hc-card" style="padding:18px 20px; margin-bottom:16px; display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap;">
<span style="font-size:14.5px; color:var(--muted);">This ticket is closed and can no longer be replied to.</span>
<button class="hc-cta" x-show="brand.features && brand.features.submit" @click="go('/submit')">Open a new ticket</button>
</div>
<form x-show="!ticket.locked" @submit.prevent="sendReply()" class="hc-card" style="padding:16px; margin-bottom:16px;">
<textarea class="hc-input" x-model="replyBody" rows="4" placeholder="Write a reply…" required style="height:auto; padding:12px 16px;"></textarea>
<div style="display:flex; align-items:center; justify-content:space-between; margin-top:10px;">
<input type="file" multiple x-ref="replyFiles" style="font-size:13px; color:var(--muted);">
<button class="hc-btn">Send reply</button>
</div>
</form>
<div style="display:flex; flex-direction:column; gap:12px;">
<template x-for="r in [...ticket.replies].reverse()" :key="r.id">
<div class="hc-card" :style="r.author==='you' ? 'padding:16px;' : 'padding:16px; background:color-mix(in srgb, var(--accent) 6%, var(--surface)); border-color:color-mix(in srgb, var(--accent) 30%, var(--border));'">
<p style="font-size:12px; font-weight:600; margin:0 0 6px;" :style="r.author==='you' ? 'color:var(--muted);' : 'color:var(--accent);'"><span x-text="r.author==='you' ? 'You' : (r.author_name||'Support')"></span> · <span x-text="new Date(r.created_at).toLocaleString()"></span></p>
<div style="white-space:pre-line; font-size:14.5px;" x-text="r.body"></div>
<div style="margin-top:8px; display:flex; flex-wrap:wrap; gap:8px;" x-show="r.attachments && r.attachments.length">
<template x-for="a in r.attachments" :key="a.token"><button class="hc-btn hc-btn-ghost" style="height:30px; padding:0 10px; font-size:12px; font-weight:500;" @click="openAttachment(a)"><span x-text="a.kind ? '👁' : '📎'"></span> <span x-text="a.name"></span></button></template>
</div>
</div>
</template>
</div>
</div>
</div>
<div x-show="route.name==='csat'" class="hc-csat">
<div class="hc-card" style="padding:34px; width:100%; max-width:560px; text-align:center; box-shadow:0 18px 50px -24px rgba(15,23,42,.35);">
<span style="display:inline-flex; align-items:center; gap:10px; margin-bottom:18px;">
<template x-if="brand.logo_url"><img :src="brand.logo_url" alt="" style="height:30px; width:auto; max-width:140px; border-radius:8px;"></template>
<template x-if="!brand.logo_url"><span class="hc-logo-mark" style="width:30px; height:30px; font-size:15px;" x-text="(brand.name||'?').slice(0,1)"></span></template>
<span class="hc-h" x-show="headerNameOn()" style="font-weight:700; font-size:16px;" x-text="brand.name || 'Support'"></span>
</span>
<template x-if="!csat.rated">
<div>
<h1 class="hc-h" style="font-weight:700; font-size:22px;">How did we do?</h1>
<p style="color:var(--muted); margin-top:6px;" x-text="csat.subject"></p>
<div style="display:flex; justify-content:center; gap:8px; margin-top:18px;">
<template x-for="n in 5" :key="n"><button @click="csat.score=n" style="font-size:30px; background:none; border:none; cursor:pointer; transition:.15s;" :style="csat.score>=n ? 'opacity:1;' : 'opacity:.3;'">⭐</button></template>
</div>
<textarea class="hc-input" x-model="csat.comment" rows="3" placeholder="Any comments? (optional)" style="height:auto; padding:12px 16px; margin-top:16px;"></textarea>
<button class="hc-btn" @click="submitCsat()" :disabled="!csat.score" style="margin-top:14px;">Submit rating</button>
</div>
</template>
<template x-if="csat.rated"><p style="font-size:18px;">Thanks for your feedback! 🙏</p></template>
</div>
</div>
<footer x-show="route.name!=='csat' && route.name!=='ticket'" style="border-top:1px solid var(--border); padding:26px 24px; margin-top:20px;">
<div class="hc-wrap" style="display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap; font-size:13.5px; color:var(--muted);">
<span x-text="(brand.theme && brand.theme.footer_text) || ('© ' + (brand.name || 'Support'))"></span>
<button class="hc-navlink" style="border:none; background:none;" @click="go('/submit')" x-show="brand.features && brand.features.submit">Contact support</button>
</div>
</footer>
</main>
</div></template>
<div x-show="preview.shown" x-cloak @keydown.escape.window="closePreview()"
@click.self="closePreview()"
style="position:fixed; inset:0; z-index:100; display:flex; align-items:center; justify-content:center; background:rgba(0,0,0,.72); padding:16px;">
<div style="display:flex; flex-direction:column; max-height:90vh; width:100%; max-width:880px; background:#fff; border-radius:12px; overflow:hidden; box-shadow:0 20px 60px rgba(0,0,0,.4);">
<div style="display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 14px; border-bottom:1px solid #e2e8f0;">
<span style="font-size:14px; font-weight:600; color:#334155; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" x-text="preview.name"></span>
<span style="display:flex; gap:8px; flex-shrink:0;">
<button @click="download(preview.att)" style="display:inline-flex; align-items:center; gap:4px; height:32px; padding:0 12px; font-size:12px; font-weight:600; color:#fff; background:#2563eb; border:none; border-radius:8px; cursor:pointer;">⬇ Download</button>
<button @click="closePreview()" title="Close (Esc)" style="display:flex; align-items:center; justify-content:center; width:32px; height:32px; font-size:14px; color:#64748b; background:none; border:none; border-radius:8px; cursor:pointer;">✕</button>
</span>
</div>
<div style="display:flex; align-items:center; justify-content:center; overflow:auto; background:#f8fafc; padding:16px; min-height:200px;">
<template x-if="preview.shown && preview.kind === 'image'">
<img :src="preview.url" :alt="preview.name" style="max-height:75vh; max-width:100%; object-fit:contain;">
</template>
<template x-if="preview.shown && preview.kind === 'video'">
<video :src="preview.url" controls style="max-height:75vh; max-width:100%;"></video>
</template>
<template x-if="preview.shown && preview.kind === 'audio'">
<audio :src="preview.url" controls style="width:100%;"></audio>
</template>
</div>
</div>
</div>
</body>
</html>
Sitemap
Кол-во: 0
XML-карта сайта для поисковиков
?
Sitemap.xml помогает поисковику быстрее находить и индексировать страницы. Особенно важен для крупных сайтов и новых страниц, на которые ещё нет входящих ссылок.
Robots.txt не содержит ссылку на карту сайта. Рекомендуется добавить карту сайта и указать ссылку на нее в robots.txt.
Внутренние ссылки
Кол-во: 10
Ссылки на другие страницы своего сайта
?
Внутренние ссылки распределяют ссылочный вес между страницами и помогают поисковику обходить сайт. Пустые анкоры и ссылки на запрещённые robots.txt страницы — типичные ошибки.
На странице присутствуют внутренние ссылки с пустым анкором: 5!
Внутренних ссылок на странице 10 оптимально.
Внутренние ссылки не запрещены к индексации в robots.txt.
На странице присутствуют изображения 3.
Показать внутренние ссылки
| Url | Анкор | Состояние |
|---|---|---|
| /tickets |
My tickets
|
|
| / |
Пустой анкор
|
|
| / |
Пустой анкор
|
|
| /tickets |
← My tickets
|
|
| / |
Пустой анкор
|
|
| /tickets |
My tickets
|
|
| / |
× Show all articles
|
|
| / |
Пустой анкор
|
|
| / |
Пустой анкор
|
|
| /tickets |
← My tickets
|
|
Внешние ссылки
Не найдено
Ссылки на сторонние сайты
?
Исходящие внешние ссылки передают часть ссылочного веса на чужие сайты. Ссылки на авторитетные ресурсы безопасны; ссылки на мусорные сайты могут навредить репутации страницы.
Внешних ссылок на странице не найдено.
Конкуренты Готовность: 0%
Конкуренты в Яндексе
Кол-во: 0
Топ сайтов-конкурентов в Яндексе
?
Сайты, чаще всего появляющиеся в ТОПе Яндекса по запросам из семантического ядра этой страницы.
Мы не нашли у вас конкурентов в Яндексе. Сайт или очень молодой или плохо продвигается.
Конкурентов в ТОП-10 Яндекса не нашлось.
Конкуренты в Google
Кол-во: 0
Топ сайтов-конкурентов в Google
?
Сайты, чаще всего появляющиеся в ТОПе Google по запросам из семантического ядра этой страницы.
Конкуренты в Google тоже не найдены. Займитесь продвижением сайта!
Конкурентов в ТОП-10 Google не нашлось.
ЗоЗПП: права потребителей Готовность: 100%
Нарушения
Не выявлены
Признаков дистанционной продажи товаров (интернет-магазина) не обнаружено — требования ЗоЗПП о раскрытии информации продавца к сайту не применяются. Нарушений нет.
ФЗ-149: рекомендательные технологии Готовность: 100%
Нарушения
Не выявлены
Рекомендательные блоки («с этим покупают», «похожие товары» и т.п.) на сайте не обнаружены — требования ст. 10.7 ФЗ-149 к сайту не применяются. Нарушений нет.
ФЗ-38: реклама Готовность: 100%
Нарушения
Не выявлены
Рекламных тематик с обязательными оговорками (медицина, БАД, кредиты и займы, новостройки) на сайте не обнаружено. Нарушений нет.
ФЗ-436: защита детей Готовность: 100%
Нарушения
Не выявлены
Признаков информационной продукции (новости, видео, книги, игры, курсы) не обнаружено — обязательная возрастная маркировка по ФЗ-436 сайту не требуется. Нарушений нет.
Вердикт
Страница https://help.xilo.net/tickets готова к продвижению на 66%. Чтобы еще улучшить страницу и попасть на первые места поисковой выдачи необходимо:
Исправьте ошибки в мета-тегах.
Исправьте ошибки оптимизации.
Поделитесь с друзьями: