/* ==========================================================================
   devpopov.ru v2 — дизайн-токены
   Обоснования, расчёты контраста, реестр решений: /DESIGN-SYSTEM.md
   Подключается ПЕРВЫМ, до badge.css.

   Комментарии здесь — только указатели на разделы документа. Рассуждения
   живут в одном месте; дублировать их сюда значит и раздувать файл,
   который качает каждый посетитель, и заводить вторую копию, которая
   однажды разойдётся с первой.

   В badge.css цвета, размеры и длительности пишутся ТОЛЬКО через var().
   ========================================================================== */

:root {
  /* --- Цвет — §1. Все пары проходят AA, коэффициенты в §1.2.
         Пастель только заливка, никогда не текст. ---------------------- */
  --bg:          #FDF3EA;
  --card:        #FFFFFF;  /* карточка остаётся бумажно-белой — §0, решение Д41 */
  --pastel:      #FBE5D2;
  --accent:      #B8400C;
  --accent-deep: #9A3412;
  --ink:         #1C1310;
  --muted:       #6B5548;
  --border:      #9A7B68;  /* граница, несущая информацию — 3:1 на всех фонах */
  --hairline:    #EAD3C0;  /* декоративный разделитель                        */
  --chip:        #AFB6BC;  /* единственный ХОЛОДНЫЙ тон на странице — §0.2    */
  --danger:      #9F1239;  /* ТОЛЬКО 404/500; холоднее акцента, иначе слился  */

  --shadow-rgb: 28 19 16;  /* компоненты --ink; чёрная тень грязнит — §4.3 */

  /* Ссылки каскадируют через переменные, а не через специфичность
     селекторов — §1.3. Контекст переопределяет --link, а не color. */
  --link:       var(--accent);
  --link-hover: var(--accent-deep);

  /* --- Типографика — §2.
         Веб-шрифтов нет. Именованные семейства после system-ui —
         страховка от кириллицы (§2.2), а не украшение стека. ------------ */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "SF Mono", Menlo, Consolas, monospace;

  /* Шкала текучая от ШИРИНЫ КАРТОЧКИ (cqi), а не от ширины окна — §2.3.
     rem + cqi, а не чистый cqi: чистая относительная единица не реагирует
     на увеличение шрифта и проваливает WCAG 1.4.4.
     Работает только внутри .badge-box (см. базовый слой ниже).
     --fs-xs (11px) допустим ТОЛЬКО для моноширинной полосы-штампа.      */
  --fs-xs:   clamp(0.6875rem, 0.5625rem + 0.833cqi, 0.750rem);  /* 11 → 12 */
  --fs-sm:   clamp(0.8125rem, 0.6875rem + 0.833cqi, 0.875rem);  /* 13 → 14 */
  --fs-base: clamp(0.9375rem, 0.8125rem + 0.833cqi, 1.000rem);  /* 15 → 16 */
  --fs-lg:   clamp(1.1250rem, 0.6250rem + 3.330cqi, 1.375rem);  /* 18 → 22 */
  --fs-xl:   clamp(1.5000rem, 0.2500rem + 8.330cqi, 2.125rem);  /* 24 → 34 */

  --lh-tight: 1.15;
  --lh-snug:  1.35;
  --lh-base:  1.55;

  --ls-tight: -0.01em;
  --ls-mono:   0.08em;  /* строки допуска — носитель образа, §0 */
  --ls-label:  0.12em;

  /* 500 намеренно отсутствует — §2.4 */
  --fw-regular:  400;
  --fw-semibold: 600;
  --fw-bold:     700;

  /* --- Отступы — §3.4. База 4px, промежуточных значений быть не должно. */
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-5:  1.5rem;
  --space-6:  2rem;
  --space-8:  3rem;
  --space-10: 4rem;

  /* --- Размеры бейджа — §3.
         Пропорция ISO/IEC 7810 ID-1 в портретной ориентации.
         Высота НЕ токен: badge.css берёт aspect-ratio: var(--badge-ratio),
         чтобы у пропорции остался ровно один источник — §3.1.            */
  --badge-ratio: 54 / 86;

  --lanyard-w: clamp(2.5rem, 11vw, 3.25rem);   /* 40 …  52px */
  --lanyard-h: clamp(2rem, 12dvh, 7rem);       /* 32 … 112px */

  /* Ниже этого текст на карточке нечитаем; дальше сжимать нельзя. */
  --badge-w-min: 15rem;                        /* 240px */

  /* Ссылка «Контакты» стоит ПОД карточкой и обязана входить в расчёт:
     44px цели касания плюс отступ. Без этого слагаемого сборка не влезала
     в ноутбук 1280×720 и 1366×640 — §3.2.                                */
  --flip-block: calc(2.75rem + var(--space-5)); /* 68px */

  /* Карточка хочет 280…360px, но не шире остатка высоты после шнурка
     и полей. Внешний max() — обязателен: без него при высоте порта
     меньше 96px выражение уходит в минус и даёт невалидную ширину,
     а любой телефон в альбомной ориентации получает нечитаемые 137…197px.
     Ниже порога страница прокручивается — §3.2.                          */
  --badge-w: max(
    var(--badge-w-min),
    min(
      clamp(17.5rem, 78vw, 22.5rem),
      calc((100dvh - var(--lanyard-h) - var(--flip-block) - 2 * var(--space-6)) * var(--badge-ratio))
    )
  );

  /* --- Форма — §4. --r-pill намеренно отсутствует (решение Д14). ------- */
  --r-xs:   2px;
  --r-sm:   4px;
  --r-card: 14px;

  --bw:       1px;
  --bw-thick: 2px;

  --shadow-card: 0 1px 2px rgb(var(--shadow-rgb) / 0.06),
                 0 8px 24px -8px rgb(var(--shadow-rgb) / 0.18);
  --shadow-lift: 0 2px 4px rgb(var(--shadow-rgb) / 0.08),
                 0 16px 32px -12px rgb(var(--shadow-rgb) / 0.24);

  /* --- Состояния — §5. Кольцо: 5.56 на --card, 5.08 на --bg. ---------- */
  --focus-w:      2px;
  --focus-offset: 2px;
  --touch-min:    44px;

  /* --- Движение — §6.
         Нули здесь не заглушка: реальные значения включаются только
         в prefers-reduced-motion: no-preference. Забытое свойство
         не анимируется, а не протекает к тем, кто просил покоя.          */
  --dur-fast: 0s;
  --dur-flip: 0s;
  --ease-out:  cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-flip: cubic-bezier(0.40, 0.00, 0.20, 1);

  --z-lanyard: 1;
  --z-card:    2;

  /* Только структурные. В медиазапросах var() не работает — значения
     дублируются литералами в badge.css, здесь они документированы. §3.5 */
  --bp-sm: 30rem;  /* 480px */
  --bp-md: 48rem;  /* 768px */

  /* Тёмной темы нет (решение Д5) — сообщаем браузеру явно, чтобы он
     не инвертировал системные контролы и полосы прокрутки. */
  color-scheme: light;
}

@media (prefers-reduced-motion: no-preference) {
  :root {
    --dur-fast: 160ms;
    --dur-flip: 520ms;
  }
}

/* ==========================================================================
   Базовый слой — ровно то, без чего токены работают неверно.
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* iOS раздувает кегль в альбомной ориентации и ломает текучую шкалу. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background-color: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  font-weight: var(--fw-regular);
  line-height: var(--lh-base);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, p, figure, blockquote {
  margin: 0;
}

img, picture, svg {
  display: block;
  max-width: 100%;
}

/* Единственное структурное правило в этом файле, и оно здесь не случайно:
   шкала --fs-* считается в cqi, то есть от ближайшего контейнера запроса.
   Забудь объявить его — и cqi молча начнёт резолвиться от окна, вернув
   ровно тот дефект, который нашла задача #3 (крупный шрифт в маленькой
   карточке на низком широком экране). Токен и его предусловие обязаны
   лежать рядом — §2.3, решение Д34.                                      */
.badge-box {
  inline-size: var(--badge-w);
  container-type: inline-size;

  /* Потолок по фактической ширине родителя обязателен, и вот почему.
     --badge-w-min задан в rem, то есть растёт вместе с кеглем, который
     посетитель выставил в браузере. При 200% минимум становится 480px —
     больше, чем экран телефона, — и страница уезжает вбок. Горизонтальная
     прокрутка появляется ровно у тех, кто увеличил шрифт, потому что плохо
     видит (WCAG 1.4.10). 100% здесь точнее, чем 100vw: оно уже учитывает
     и поля .hang, и полосу прокрутки. */
  max-inline-size: 100%;
}

/* Подчёркивание обязательно и снимать его нельзя: цвет не может быть
   единственным признаком ссылки (WCAG 1.4.1) — §5.7. */
a {
  color: var(--link);
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

/* Контекст переопределяет ПЕРЕМЕННЫЕ, а не color: иначе селектор
   контекста перебивает :hover по специфичности и отклик пропадает. §1.3 */
.on-pastel {
  --link:       var(--accent-deep);
  --link-hover: var(--ink);
}

button {
  font: inherit;
  color: inherit;
}

/* Переопределять можно только увеличением заметности.
   outline: none запрещён во всём проекте — решение Д17. */
:focus-visible {
  outline: var(--focus-w) solid var(--accent);
  outline-offset: var(--focus-offset);
}

/* Только там, где есть настоящий курсор: иначе состояние залипает
   на тач-устройствах после тапа. §5.2 */
@media (hover: hover) {
  a:hover {
    color: var(--link-hover);
  }
}
