/* Панель findesign-consult.
   Смотрят с телефона и с компьютера; читают длинные тексты — отчёты, дневники, переписку.
   Отсюда тёплая бумажная палитра и ограниченная длина строки, а не плотный дашборд.
   Шрифты системные: панель публична, и тянуть на неё сторонний CDN мы отказались
   осознанно (там же, где отказались от CDN для htmx). */

@layer reset, base, layout, components;

@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  body, h1, h2, h3, p, ul, ol, figure { margin: 0; }
  ul[class] { padding: 0; list-style: none; }
  button, input, textarea, select { font: inherit; color: inherit; }
  img { max-inline-size: 100%; display: block; }
}

@layer base {
  :root {
    color-scheme: light dark;

    /* Тир 1 — литеральные значения. Тёплый камень и янтарь: панель для чтения,
       холодный синий на длинных текстах утомляет и звучит «корпоративно». */
    --stone-50:  #faf8f5;
    --stone-100: #f3efe9;
    --stone-200: #e7e1d8;
    --stone-300: #d3cabd;
    /* не #78716c: на светлом фоне давал контраст 4.53:1 — впритык к AA, а этим цветом
       набраны мелкие подписи. Здесь запас до ~5.5:1 */
    --stone-500: #6a635d;
    --stone-700: #443f3a;
    --stone-800: #2b2724;
    --stone-900: #1c1917;
    --stone-950: #12100e;
    --amber-500: #b45309;
    --amber-400: #d97706;
    --amber-200: #fcd9a5;
    --red-600:   #c2410c;
    --red-400:   #f87171;
    --green-600: #15803d;
    --green-400: #4ade80;

    /* Тир 2 — смысловые. Дальше в файле используются только они. */
    --bg:            light-dark(var(--stone-50), var(--stone-950));
    --surface:       light-dark(#fffdfa, var(--stone-900));
    --surface-sunk:  light-dark(var(--stone-100), var(--stone-800));
    --text:          light-dark(var(--stone-900), var(--stone-100));
    --text-muted:    light-dark(var(--stone-500), #a9a29b);
    --border:        light-dark(var(--stone-200), var(--stone-700));
    --border-strong: light-dark(var(--stone-300), var(--stone-500));
    --accent:        light-dark(var(--amber-500), var(--amber-400));
    --accent-soft:   light-dark(#fdf3e3, #3a2c17);
    --danger:        light-dark(var(--red-600), var(--red-400));
    --ok:            light-dark(var(--green-600), var(--green-400));

    /* Единственная шкала отступов. Кратна 4px; в разметке нет ни одного значения мимо неё —
       иначе блоки начинают «дышать» по-разному и страница читается как свалка. */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.25rem;
    --space-6: 1.5rem;
    --space-8: 2rem;
    --space-10: 2.5rem;
    --radius: 0.5rem;
    --radius-sm: 0.3rem;

    --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
    /* Длина строки, комфортная для чтения отчёта. Раньше строка тянулась на 960px. */
    --measure: 68ch;

    accent-color: var(--accent);
  }

  body {
    font-family: var(--font);
    font-size: 1rem;
    line-height: 1.5;
    color: var(--text);
    background: var(--bg);
    /* dvh, а не vh: на телефоне адресная строка прячется и ломает vh */
    min-block-size: 100dvh;
    -webkit-text-size-adjust: 100%;
  }

  h1 { font-size: clamp(1.4rem, 1.1rem + 1.4vw, 1.9rem); line-height: 1.2; text-wrap: balance; }
  h2 { font-size: clamp(1.1rem, 1rem + 0.5vw, 1.3rem); line-height: 1.25; text-wrap: balance; }
  h3 { font-size: 1rem; }

  p { text-wrap: pretty; }

  /* убирает 300-миллисекундную задержку двойного тапа на телефоне */
  :where(a, button, summary, label, select, input) { touch-action: manipulation; }

  a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
  a:hover { text-decoration-thickness: 2px; }

  :focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
  }

  /* Длинные слова и ссылки в чужих текстах не должны растягивать страницу */
  p, li, td, th, dd, dt, .bubble, .answer { overflow-wrap: break-word; }
}

@layer layout {
  .site-header {
    border-block-end: 1px solid var(--border);
    background: var(--surface);
    position: sticky;
    inset-block-start: 0;
    z-index: 1;
  }

  .site-header nav {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    max-inline-size: 60rem;
    margin-inline: auto;
    padding: var(--space-2) var(--space-4);
  }

  .site-header a {
    color: var(--text-muted);
    text-decoration: none;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    /* WCAG 2.5.8: цель нажатия не меньше 24px, на пальце — крупнее */
    min-block-size: 2.75rem;
    display: flex;
    align-items: center;
  }
  .site-header a:hover { background: var(--surface-sunk); color: var(--text); }
  /* текущий раздел: подсветка плюс сам атрибут, который читает скринридер */
  .site-header a[aria-current="page"] {
    background: var(--surface-sunk);
    color: var(--text);
    font-weight: 500;
  }

  .nav-right {
    margin-inline-start: auto;
    display: flex;
    align-items: center;
    gap: var(--space-1);
  }

  /* --- страница входа ------------------------------------------------------- */
  .login-page main {
    display: grid;
    place-items: center;
    min-block-size: 100dvh;
    max-inline-size: 100%;
  }
  .login-card {
    inline-size: min(24rem, 100%);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-6);
    display: grid;
    gap: var(--space-4);
  }
  .login-card h1 { font-size: 1.35rem; }
  .login-card label { display: block; margin-block-end: var(--space-1); font-size: 0.9rem; }
  /* на всю ширину — только «Войти»; «Показать» стоит в строке рядом с полем */
  .login-card > form > button { inline-size: 100%; }

  main {
    max-inline-size: 60rem;
    margin-inline: auto;
    padding: var(--space-6) var(--space-4) var(--space-8);
  }

  section { margin-block-end: var(--space-6); }

  /* Блок-панель: всё содержимое страницы живёт в таких блоках, поэтому границы смысла
     видны глазом, а отступы одинаковые везде. */
  .panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-5);
    display: grid;
    gap: var(--space-4);
    container-type: inline-size;
  }
  .panel > h2 { margin: 0; font-size: 1.05rem; }
  .panel-note { color: var(--text-muted); font-size: 0.9rem; margin: 0; }

  /* Заголовок смысловой группы: несколько панелей об одном. */
  .group { margin-block-end: var(--space-10); display: grid; gap: var(--space-3); }
  .group > h2 {
    margin: 0;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    font-weight: 600;
  }
  /* Две короткие панели рядом на широком экране: меньше вертикали и видно,
     что это два взгляда на одно и то же. */
  @media (min-width: 60rem) {
    .group-pair { grid-template-columns: 1fr 1fr; align-items: start; }
    .group-pair > h2 { grid-column: 1 / -1; }
  }

  /* Панель фильтров: поля в ряд, на узком экране — в столбец */
  .filters {
    /* 15rem: в первой ячейке селект и переключатель направления стоят в ряд —
       при меньшей ширине кнопка ↓ переносится под селект и ломает ряд */
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    align-items: end;
    margin-block-end: var(--space-4);
  }
  .filters label { display: block; margin-block-end: var(--space-1);
                   font-size: 0.85rem; color: var(--text-muted); }
  .filters-actions { display: flex; gap: var(--space-2); align-items: center; }
  /* Селект сортировки ужимается под ячейку, а переключатель рядом не сжимается:
     иначе при узкой колонке кнопка ↓ переносится под селект и ломает ряд. */
  .filters .form-row select { flex: 1; min-inline-size: 0; }

  /* Переключатель направления — квадратный, по высоте селекта рядом */
  .sort-order {
    flex: none;
    min-inline-size: 2.75rem;
    padding-inline: 0;
    justify-content: center;
    font-size: 1.1rem;
  }

  /* Срезы соцдема: колонки подстраиваются под ширину, панели в ряду одной высоты —
     иначе рядом с короткой панелью зияет пустота. */
  .cohorts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: var(--space-3);
  }

  /* шапка липкая: без этого переход по якорю из оглавления прячет заголовок под неё */
  :where(section, h2, h3)[id], section[id] > h2 { scroll-margin-block-start: 4.5rem; }

  /* ссылка для клавиатуры: первый Tab уводит сразу к содержимому, минуя навигацию */
  .skip-link {
    position: absolute;
    inset-block-start: -100%;
    inset-inline-start: var(--space-2);
    background: var(--surface);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    z-index: 2;
  }
  .skip-link:focus { inset-block-start: var(--space-2); }
  section > h2 { margin-block-end: var(--space-3); }
  section > h3 { margin-block: var(--space-6) var(--space-3); }
  h1 + section, header + section, .toc + section { margin-block-start: var(--space-6); }
  h1 + p { margin-block-start: var(--space-2); }
  header .toc { margin-block-start: var(--space-3); }
  /* details тоже контейнер: внутри них живут .facts и карточки установок */
  details { container-type: inline-size; }

  .stack > * + * { margin-block-start: var(--space-3); }
  .prose { max-inline-size: var(--measure); }
}

@layer components {
  /* --- карточки-плитки: список людей и блоки данных ------------------------ */
  .card {
    /* контейнер обязателен: без него вложенные @container-правила (.facts) не сработают */
    container-type: inline-size;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-4);
  }
  .card + .card { margin-block-start: var(--space-3); }

  /* контейнер — родитель: элемент не может отвечать на собственный @container,
     правило применяется только к потомкам контейнера */
  .people { container-type: inline-size; display: grid; gap: var(--space-3); }

  .person {
    background: var(--surface);
    border: 1px solid var(--border);
    border-inline-start: 3px solid var(--border-strong);
    border-radius: var(--radius);
    padding: var(--space-3) var(--space-4);
    display: grid;
    gap: var(--space-2);
  }
  /* Молчит дольше недели — это и есть главный вопрос панели «кто застрял» */
  .person:has(.silent-long) { border-inline-start-color: var(--accent); }

  .person-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-2) var(--space-3);
  }
  .person-name { font-weight: 600; font-size: 1.05rem; text-decoration: none; }
  .person-facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    color: var(--text-muted);
    font-size: 0.9rem;
  }
  /* Место для формы роли появляется, только когда карточка достаточно широкая */
  @container (min-width: 34rem) {
    .person { grid-template-columns: 1fr auto; align-items: center; }
    .person-role-form { justify-self: end; }
  }

  /* --- бейджи -------------------------------------------------------------- */
  .badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0.15em 0.6em;
    border-radius: 999px;
    background: var(--surface-sunk);
    color: var(--text);
    font-size: 0.85rem;
    white-space: nowrap;
  }
  .badge-step { background: var(--accent-soft); color: var(--accent); font-weight: 500; }
  .badge-live { background: var(--accent); color: #fff; }
  .badge-muted { color: var(--text-muted); }

  /* --- определения «поле — значение» --------------------------------------- */
  .facts { display: grid; gap: var(--space-3) var(--space-6); margin: 0; }
  @container (min-width: 26rem) {
    .facts { grid-template-columns: minmax(auto, 14rem) 1fr; align-items: baseline; }
  }
  .facts dt { color: var(--text-muted); font-size: 0.9rem; }
  .facts dd { margin: 0; }

  /* сама формулировка установки — главное на своей панели */
  .belief { font-size: 1.05rem; font-weight: 500; margin: 0; max-inline-size: var(--measure); }

  .page-head { display: grid; gap: var(--space-3); margin-block-end: var(--space-8); }
  .page-head h1 { margin: 0; }
  .badges { display: flex; flex-wrap: wrap; gap: var(--space-2); }
  .back-link { margin-block-end: var(--space-4); }
  .record + .record { margin-block-start: var(--space-4); padding-block-start: var(--space-4); border-block-start: 1px solid var(--border); }

  /* --- таблицы (журнал, события) ------------------------------------------- */
  .table-wrap { overflow-x: auto; }
  /* Моноширинные цифры там, где они стоят колонкой: иначе даты и числа «пляшут»
     по горизонтали от строки к строке. */
  table, .facts dd, .funnel-row, .diary-when, .person-facts {
    font-variant-numeric: tabular-nums;
  }
  table { border-collapse: collapse; inline-size: 100%; font-size: 0.95rem; }
  th, td { padding: var(--space-2) var(--space-3); text-align: start; vertical-align: top; }
  th { color: var(--text-muted); font-weight: 500; font-size: 0.85rem; }
  tbody tr:not(:last-child) td { border-block-end: 1px solid var(--border); }

  /* --- воронка на дашборде -------------------------------------------------- */
  .funnel { display: grid; gap: var(--space-2); }
  .funnel-row {
    display: grid;
    /* последняя колонка фиксированной ширины: иначе «· осталось N» сжимает трек, и
       полосы разной длины становятся несопоставимыми на глаз */
    grid-template-columns: minmax(7rem, 12rem) 1fr 9rem;
    gap: var(--space-3);
    align-items: center;
    font-size: 0.95rem;
  }
  @media (max-width: 34rem) {
    .funnel-row { grid-template-columns: 1fr 5rem; }
    .funnel-row .funnel-track { grid-column: 1 / -1; order: 1; }
  }
  /* display обязателен: оба элемента — <span>, а инлайновым ширина в % не применяется */
  .funnel-track {
    display: block;
    background: var(--surface-sunk);
    border-radius: var(--radius-sm);
    block-size: 1.1rem;
    overflow: hidden;
  }
  .funnel-bar {
    display: block;
    background: var(--accent);
    block-size: 100%;
    border-radius: var(--radius-sm);
    min-inline-size: 2px;
  }
  .funnel-stuck { color: var(--accent); font-weight: 600; }

  /* --- показатели: крупное число и подпись под ним --------------------------- */
  /* Пары «подпись — значение» для счётчиков не годятся: значение уезжало в колонку
     на другой конец панели, и глазу приходилось перепрыгивать через пустоту. */
  .stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
    gap: var(--space-4);
  }
  .stat-value {
    font-size: 1.75rem;
    font-weight: 600;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
  }
  .stat-label { color: var(--text-muted); font-size: 0.9rem; }

  /* --- распределение: подпись, доля полоской, количество --------------------- */
  .dist { display: grid; gap: var(--space-3); }
  .dist-row {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: var(--space-1) var(--space-3);
    align-items: baseline;
  }
  /* Полоска идёт отдельной строкой под подписью: длинные значения соцдема
     («Предприниматель / собственник бизнеса») переносятся, и число рядом с ними
     висело бы криво. */
  .dist-track {
    grid-column: 1 / -1;
    display: block;
    background: var(--surface-sunk);
    border-radius: 999px;
    block-size: 0.35rem;
  }
  .dist-bar {
    display: block;
    background: var(--accent);
    border-radius: inherit;
    block-size: 100%;
    min-inline-size: 2px;
  }
  .dist-count { font-variant-numeric: tabular-nums; font-weight: 500; }

  /* --- длинные тексты: отчёт, тесты, ответы чекапа -------------------------- */
  .doc { max-inline-size: var(--measure); }
  /* внутри панели у документа своей рамки нет: две вложенные рамки дробят страницу */
  .panel > .doc { background: transparent; border: 0; padding: 0; }
  .doc > * + * { margin-block-start: var(--space-3); }
  .doc strong { color: var(--text); }
  .doc ul, .doc ol { padding-inline-start: 1.2em; }

  .qa { max-inline-size: var(--measure); display: grid; gap: var(--space-4); }
  .qa .question { color: var(--text-muted); font-size: 0.9rem; }
  .qa .answer { font-weight: 500; }
  .qa .answer-open { font-weight: 400; font-style: italic; }

  /* --- переписка ------------------------------------------------------------ */
  .dialog { display: grid; gap: var(--space-3); max-inline-size: var(--measure); }
  .turn { display: grid; gap: var(--space-1); }
  .turn-who { font-size: 0.8rem; color: var(--text-muted); }
  .bubble {
    padding: var(--space-3);
    border-radius: var(--radius);
    background: var(--surface);
    border: 1px solid var(--border);
  }
  .bubble > * + * { margin-block-start: var(--space-2); }
  .turn-user { justify-items: end; }
  .turn-user .bubble { background: var(--accent-soft); border-color: transparent; }
  /* пузырь по содержимому, а не во всю ширину — иначе короткая реплика выглядит полосой */
  .bubble { inline-size: fit-content; max-inline-size: min(90%, 60ch); }

  /* --- дневник -------------------------------------------------------------- */
  .diary { display: grid; gap: var(--space-3); max-inline-size: var(--measure); }
  .diary-entry { border-inline-start: 2px solid var(--border-strong); padding-inline-start: var(--space-3); }
  .diary-when { font-size: 0.8rem; color: var(--text-muted); }

  /* --- формы ---------------------------------------------------------------- */
  form { display: grid; gap: var(--space-3); }
  label { display: flex; align-items: center; gap: var(--space-2); }

  textarea, input[type="text"], input[type="password"], select {
    inline-size: 100%;
    /* 2.75rem = 44px: минимальная цель нажатия пальцем (WCAG 2.5.8, Apple HIG) */
    min-block-size: 2.75rem;
    padding: var(--space-3);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    resize: vertical;
  }
  textarea { min-block-size: 6rem; }

  /* Галочка по умолчанию ~13px — мимо пальца. Целью служит вся строка с меткой,
     поэтому 44px задаём ей: сам квадратик крупнее делать некуда, он выглядел бы чужеродно. */
  input[type="checkbox"] {
    inline-size: 1.15rem;
    block-size: 1.15rem;
    margin: 0;
    flex: none;
  }
  label:has(> input[type="checkbox"]) { min-block-size: 2.75rem; }

  button {
    min-block-size: 2.75rem;
    padding-inline: var(--space-4);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: var(--accent);
    color: #fff;
    font-weight: 500;
    cursor: pointer;
    transition: filter 150ms ease;
  }
  button:hover:not(:disabled) { filter: brightness(1.1); }
  /* Отклик на нажатие: на телефоне hover не существует, и без этого кнопка кажется
     мёртвой. Не transform — он дёргал бы соседей в grid-строке карточки человека. */
  button:active:not(:disabled) { filter: brightness(0.92); }
  button:disabled { opacity: 0.6; cursor: progress; }
  button.secondary {
    background: var(--surface);
    color: var(--text);
    border-color: var(--border-strong);
  }
  /* Выход — пункт меню, а не действие первого плана. Правило живёт именно здесь:
     в слое layout его перебивал бы `button` из components, каким бы специфичным
     ни был селектор — порядок слоёв важнее специфичности. */
  button.linklike {
    background: transparent;
    color: var(--text-muted);
    border: 0;
    padding-inline: var(--space-3);
    font-weight: 400;
  }
  button.linklike:hover:not(:disabled) {
    background: var(--surface-sunk);
    color: var(--text);
    filter: none;
  }

  .form-row { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
  /* Внутри строки поле занимает остаток, а кнопка жмётся по содержимому: без этого
     inline-size:100% выталкивает кнопку на отдельную строку.
     ⚠️ Селектор НЕ по type: кнопка «Показать» переключает поле пароля на type="text",
     и правило, привязанное к типу, перестраивало бы ряд прямо под курсором. */
  .form-row select { inline-size: auto; }
  .form-row input:not([type="checkbox"]) { flex: 1; inline-size: auto; min-inline-size: 0; }
  .form-hint { color: var(--text-muted); font-size: 0.85rem; }

  /* htmx показывает индикатор только на время запроса */
  .htmx-indicator { display: none; color: var(--text-muted); font-size: 0.9rem; }
  .htmx-request .htmx-indicator, .htmx-request.htmx-indicator { display: inline; }

  .error-slot:empty { display: none; }
  .error-slot {
    color: var(--danger);
    background: var(--surface-sunk);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
  }

  /* --- прочее ---------------------------------------------------------------- */
  .empty { color: var(--text-muted); }
  .status-sent { color: var(--ok); }
  .status-failed { color: var(--danger); }
  .status-pending { color: var(--text-muted); }

  /* details-панель выглядит как обычная панель: сворачивание не должно менять ритм */
  details.panel { display: block; }
  details.panel[open] > summary { margin-block-end: var(--space-4); }
  details.panel > :not(summary) { margin-block-start: var(--space-4); }
  summary {
    cursor: pointer;
    font-weight: 500;
    font-size: 1.05rem;
    min-block-size: 2.75rem;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
  }

  /* Свёрнутый блок должен читаться как свёрнутый: свой треугольник вместо системного
     маркера (он мелкий и теряется), плюс метка «пройден / нет» — чтобы было понятно,
     есть ли внутри что-то, не раскрывая. */
  .spoiler > summary { list-style: none; }
  .spoiler > summary::-webkit-details-marker { display: none; }
  .spoiler > summary::before {
    content: "";
    inline-size: 0.5rem;
    block-size: 0.5rem;
    flex: none;
    border-inline-end: 2px solid var(--text-muted);
    border-block-end: 2px solid var(--text-muted);
    rotate: -45deg;                       /* ▸ вправо, когда закрыт */
    transition: rotate 150ms ease;
    translate: 0 -1px;
  }
  .spoiler[open] > summary::before { rotate: 45deg; }   /* ▾ вниз, когда открыт */
  .spoiler > summary:hover::before { border-color: var(--accent); }
  .spoiler-title { flex: 1; }
  .badge-ok { background: var(--accent-soft); color: var(--accent); }

  /* Ссылка, ведущая себя как кнопка: переход в новую вкладку — это навигация,
     поэтому именно <a>, а не button (работает Cmd+клик и средняя кнопка). */
  .button-link {
    display: inline-flex;
    align-items: center;
    min-block-size: 2.75rem;
    padding-inline: var(--space-4);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    color: var(--text);
    text-decoration: none;
  }
  .button-link:hover { background: var(--surface-sunk); }

  /* --- подтверждение отправки ------------------------------------------------ */
  .confirm {
    inline-size: min(30rem, calc(100vw - 2rem));
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    padding: var(--space-6);
    gap: var(--space-4);
  }
  /* display ТОЛЬКО для открытого: закрытый <dialog> браузер прячет через display:none,
     и безусловный display:grid показывал бы подтверждение всегда */
  .confirm[open] { display: grid; }
  .confirm::backdrop { background: rgb(0 0 0 / 0.5); }
  .confirm-text {
    margin: 0;
    padding-inline-start: var(--space-3);
    border-inline-start: 3px solid var(--border-strong);
    white-space: pre-wrap;      /* переносы, как их набрали, — уйдёт ровно это */
    max-block-size: 40vh;
    overflow-y: auto;
  }
  .confirm-signed { color: var(--accent); font-weight: 500; }
  .confirm-signed[hidden] { display: none; }

  .toc {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
    font-size: 0.9rem;
    color: var(--text-muted);
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 1ms !important; animation-duration: 1ms !important; }
}

/* В режиме высокой контрастности авторские цвета отбрасываются: границы должны
   остаться видимыми, иначе карточки сливаются в сплошное полотно. */
@media (forced-colors: active) {
  .card, .person, .bubble, details, .doc { border: 1px solid CanvasText; }
  .funnel-bar { background: Highlight; }
}
