/* ==========================================================================
   Design tokens — выгружены из Figma (Variables), имена 1:1 с макетом.
   Figma `color/text/primary` → `--color-text-primary`.

   Тем в макете две, и это два мода одной коллекции переменных, а не два
   разных макета: разметка, сетка, шрифты и отступы у светлой и тёмной
   совпадают до пикселя, меняются только значения цветов. Поэтому тёмная тема
   живёт целиком в этом файле — в `blocks/` она не стоила ни одной правки.

   Светлая · Figma 3:3893, 3:3579, 3:3620, 3:3685, 3:3738, 3:3803
   Тёмная  · Figma 36:2779, 36:2465, 36:2506, 36:2571, 36:2624, 36:2689
   (те же шесть брейкпоинтов главной, один к одному).
   ========================================================================== */

:root {
  /* --- Color -------------------------------------------------------------
     Тем две, и каждая — мод одной коллекции переменных. Значения обеих
     половин лежат ниже по одному разу, в паре `--*-light` / `--*-dark`, а
     действующий токен на них ссылается. Переключают тему два правила в конце
     раздела: системная тема (медиазапрос) и выбор пользователя (атрибут).

       color-scheme: light dark  — идём за системной темой (по умолчанию);
       [data-theme="light"|"dark"] — действующая тема, её ставит js/theme.js
       (и бутстрап в <head>, чтобы страница не мигнула светлой до загрузки JS).

     В атрибуте именно действующая тема, а не выбор пользователя: выбор живёт
     в localStorage, а когда его нет — атрибуту достаётся системная. Так по
     одному атрибуту видно, какая тема сейчас, и на него же опирается подпись
     кнопки в меню (blocks/menu.css) — иначе ей понадобился бы свой
     медиазапрос, то есть вторая копия той же развилки.

     Побочно `color-scheme` красит и то, до чего CSS не дотягивается:
     полосы прокрутки, поля ввода на странице кейса, подложку между экраном и
     <html>. Ради этого он и стоит на :root, а не на body.

     Почему не light-dark(), которым это было записано вдвое короче: функция
     появилась в Safari 17.5 и Chrome 123 (обе — весна 2024). В браузере
     старше неё значение токена становится невалидным не при разборе, а при
     вычислении, и запасного пути у него нет: var() отдаёт `unset`, цвет
     наследуется, фон пропадает. Одной строкой сносит палитру всего сайта, и
     подстраховать её порядком объявлений нельзя — кастомное свойство при
     разборе валидно любое, поэтому побеждает всегда последнее. Пара правил
     ниже работает в любом браузере, где вообще есть тёмная тема. */
  color-scheme: light dark;

  /* Figma `color/bg/base`, `color/text/primary`, `color/border/primary` —
     три переменные, которыми тёмная тема и отличается от светлой.

     У фона половинки названы ещё и по отдельности не только ради этой пары:
     их читает js/theme.js, чтобы держать <meta name="theme-color"> (цвет
     панели браузера на мобильных) в согласии с темой. */
  --color-bg-base-light: #fafafa;
  --color-bg-base-dark: #0a0a0a;
  --color-bg-base: var(--color-bg-base-light);

  --color-text-primary-light: #222222;
  --color-text-primary-dark: #e6e6e6;
  --color-text-primary: var(--color-text-primary-light);

  --color-border-primary-light: #222222;
  --color-border-primary-dark: #e6e6e6;
  --color-border-primary: var(--color-border-primary-light);

  /* Figma `color/text/subtle` — в обоих модах один и тот же серый: он сидит
     ровно посередине между двумя фонами и читается на любом из них. */
  --color-text-subtle: #767676;

  /* Figma `color/border/subtle` — тонкая линия над строкой фильтров каталога.
     Тёмное значение — НЕ из макета (тёмных фреймов каталога пока нет), взято
     зеркалом светлого: в светлой теме это чернила тёмной темы (#e6e6e6),
     значит в тёмной — чернила светлой. На главной не используется вовсе. */
  --color-border-subtle-light: #e6e6e6;
  --color-border-subtle-dark: #222222;
  --color-border-subtle: var(--color-border-subtle-light);

  /* Поверх картинки кейса (активное состояние плитки). Figma:
     `color/text/on solid/img` и `color/border/on-soild/img` — оба #e6e6e6,
     опечатка в имени переменной сохранена только в Figma, здесь имя чинится.
     От темы не зависят: лежат на фотографии, а не на фоне страницы. */
  --color-text-on-solid-img: #e6e6e6;
  --color-border-on-solid-img: #e6e6e6;

  /* Заливка активного состояния — в макете чистый чёрный на 50%, не токен.
     Тоже общая на обе темы: затемнение считается от самой картинки. */
  --color-overlay-card: rgba(0, 0, 0, 0.5);

  /* Служебный: подложка карточки до загрузки картинки (в макете не виден).
     Тёмное значение выведено тем же сдвигом от фона, что и светлое: #fafafa
     темнее на 4% → #f0f0f0, #0a0a0a светлее на 4% → #141414. */
  --color-bg-placeholder-light: #f0f0f0;
  --color-bg-placeholder-dark: #141414;
  --color-bg-placeholder: var(--color-bg-placeholder-light);

  /* Figma `color/border/error` и `color/text/error` — форма заявки на странице
     кейса: рамка поля с ошибкой и подсказка под ним (blocks/contact.css).
     Больше нигде на сайте красного нет. На обе темы пока одна пара: тёмного
     макета формы нет, а на #0a0a0a оба цвета читаются. */
  --color-border-error: #ffc5ca;
  --color-text-error: #ff3445;

  /* Figma `color/bg/hover/base` — пункт раскрытого списка бюджетов под
     курсором (blocks/contact.css). Тёмное значение — НЕ из макета (тёмного
     фрейма списка нет), взято тем же зеркалом, что у --color-border-subtle:
     в светлой теме это чернила тёмной, значит в тёмной — чернила светлой. */
  --color-bg-hover-base-light: #e6e6e6;
  --color-bg-hover-base-dark: #222222;
  --color-bg-hover-base: var(--color-bg-hover-base-light);

  /* Figma `color/shadow/shadow` (#00000014) и эффект `Shadow/sm` — тень под
     раскрытым списком, единственная тень на сайте. От темы не зависит:
     чёрной тени на #0a0a0a всё равно не видно, и панель там держит не более
     густая тень, а линия ниже. */
  --color-shadow: rgba(0, 0, 0, 0.08);
  --shadow-sm: 0 8px 8px 0 var(--color-shadow);

  /* Обводка раскрытого списка — не из Figma. В светлой теме её нет: панель
     держит тень, как в макете; в тёмной без неё панель сливалась бы со
     страницей (фон у обеих #0a0a0a), поэтому там она в цвет subtle. */
  --color-border-panel-light: transparent;
  --color-border-panel-dark: #222222;
  --color-border-panel: var(--color-border-panel-light);

  /* --- Typography ------------------------------------------------------- */
  --font-family-base: "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --font-weight-regular: 400;
  --font-weight-medium: 500;

  /* Размеры шрифта переопределяются на 1024+ — см. блок в конце файла */
  --font-size-xs: 12px;
  --font-size-sm: 14px;
  --font-size-3xl: 32px;

  /* Figma font-size/md. До 1024 им набраны пункты меню (см. blocks/menu.css)
     и заголовок кейса в активном состоянии плитки; на 1024+ меню уходит на
     свою шкалу, а заголовок кейса растёт до 18 — см. блок ниже. */
  --font-size-md: 16px;

  /* Figma font-size/lg. Display sm — название карточки в постоянной подписи
     каталога (blocks/catalog.css) и «Or Contact Us Directly» в форме заявки.
     На 1024+ растёт до 24. */
  --font-size-lg: 20px;

  /* Figma font-size/xl. Display md — заголовки разделов правовой страницы
     (blocks/legal.css) и больше пока нигде. На 1024+ растёт до 32. */
  --font-size-xl: 24px;

  /* Figma font-size/2xl. Display lg — заголовки секций страницы кейса:
     «More Identity Cases» и «Get a Free Consultation». На 1024+ растёт до 40. */
  --font-size-2xl: 28px;

  /* Figma line-height: Display xl = 1, Text = 1.4.
     Figma округляет высоту строки до целого пикселя, поэтому текстовые стили
     заданы в px: 14 × 1.4 = 19.6 → 20; 12 × 1.4 = 16.8 → 17.
     Так высоты блоков совпадают с макетом (hero meta = 40, footer = 96). */
  --line-height-display: 1;
  --line-height-text-md: 20px; /* для --font-size-sm */
  --line-height-text-sm: 17px; /* для --font-size-xs */

  /* Текстовые стили меню (Figma Text sm/md/xl) заданы с lineHeight 1.5, а не
     1.4, как остальная страница. Множитель здесь безопасен: 14 × 1.5 = 21 и
     16 × 1.5 = 24 — целые, округлять нечего. Стили Uppercase остались на 1.4,
     поэтому их высоты по-прежнему считаются в px (см. blocks/menu.css). */
  --line-height-text-relaxed: 1.5;

  /* Figma letterSpacing: Text md = -2% → -0.02em; Uppercase = 0 */
  --letter-spacing-text: -0.02em;
  --letter-spacing-uppercase: 0;

  /* --- Spacing ---------------------------------------------------------- */
  --spacing-0: 0px;
  --spacing-xs: 2px;
  --spacing-sm: 4px;
  --spacing-md: 8px;
  --spacing-lg: 16px;
  --spacing-xl: 24px;
  --spacing-2xl: 32px;
  --spacing-3xl: 40px;
  --spacing-4xl: 48px;
  --spacing-6xl: 80px;

  /* --- Безопасная зона ---------------------------------------------------
     Телефон с вырезом в альбомной ориентации отдаёт под чёлку и под полосу
     «домой» края экрана, и в <head> у страниц стоит viewport-fit=cover —
     значит рисуем мы во весь экран и разойтись с вырезом обязаны сами.

     Токены нужны затем, что запасной ноль в env() иначе пришлось бы повторять
     в каждом месте, а забытый — это пропавшее поле целиком. Так безопасная
     зона названа один раз и подставляется в те четыре места, где вёрстка
     касается края экрана:
     .container (base.css), сетка кейсов (blocks/cases.css), сетка каталога
     (blocks/catalog.css) и полоса кук (blocks/cookies.css). Везде через
     max(): в портрете и на любом устройстве без выреза env() равен нулю, и
     остаётся исходное поле из макета — ничего не сдвигается.

     Второй аргумент env() (0px) обязателен: без него в браузере, который про
     safe-area не знает, всё выражение стало бы невалидным и поле пропало бы
     совсем. */
  --safe-inline-start: env(safe-area-inset-left, 0px);
  --safe-inline-end: env(safe-area-inset-right, 0px);
  --safe-block-end: env(safe-area-inset-bottom, 0px);

  /* --- Radius -----------------------------------------------------------
     Figma `corner-radius/md` — картинка кейса, стопка галереи и раскрытый
     список в форме заявки; `corner-radius/sm` — чекбокс там же. */
  --radius-md: 8px;
  --radius-sm: 4px;

  /* --- Motion -----------------------------------------------------------
     Движения в Figma нет — значения выбраны здесь и держатся в одном месте,
     чтобы приход и уход везде шли по одной кривой. Уход короче прихода: курсор
     ушёл — состояние снимается быстрее, чем появлялось.
     Кривая — вход резкий, выход длинный хвост: движение читается сразу, но
     останавливается мягко, без «щелчка» в конце, как у линейной или ease.
     Длительности заданы в мс и парсятся из JS (js/cards.js ждёт конца ухода,
     чтобы не мерить колонку на промежуточной высоте) — единицу не менять. */
  --duration-enter: 420ms;
  --duration-leave: 300ms;
  /* Нажатие — единственное движение, которому длинный хвост вреден: отклик на
     касание должен успеть за палец */
  --duration-press: 180ms;
  /* Смена темы — наоборот, самое длинное движение на сайте, вдвое длиннее
     ухода. Она перекрашивает всю страницу разом, и на общей длительности это
     читалось бы как щелчок: глазу нужно время проследить за переходом.
     Токен свой, а не --duration-leave, именно поэтому — чтобы растянуть
     смену темы и не замедлить заодно плитку и панель меню.
     Значение парсится из js/theme.js — единицу не менять. */
  --duration-theme: 600ms;
  --ease-soft: cubic-bezier(0.22, 0.61, 0.36, 1);

  /* --- Opacity ---------------------------------------------------------- */
  /* Содержимое страницы при открытом меню — в макете ровно 50% (blocks/menu.css) */
  --menu-dim-opacity: 0.5;
  /* Наведение на элемент без обводки — вторая половина политики наведения
     (css/base.css). Значение то же, что у приглушения под меню: «половина» на
     сайте одна, и приглушённый пункт читается так же, как приглушённая
     страница, — состояние, а не новый цвет. */
  --opacity-hover: 0.5;
  /* Пункт меню, выключенный в админке (blocks/menu.css). Та же половина:
     выключенный пункт читается как приглушённый, а не как другой цвет. */
  --opacity-disabled: 0.5;

  /* --- Layout ----------------------------------------------------------- */
  /* Брейкпоинты макета: 320–575 (3:3893), 576–767 (3:3579), 768–1023 (3:3620),
     1024–1279 (3:3685), 1280–1920 (3:3738), 1920–max (3:3803). Внутри диапазона
     всё резиновое — фиксированных ширин нет, сверка идёт по опорной ширине фрейма
     (425, 576, 768, 1024, 1280, 4362). Медиазапросы пишутся mobile-first от
     min-width, значения в px дублируются вручную: var() в @media не работает.
     На 320–1023 отличия сводятся к футеру (см. blocks/footer.css) и числу
     колонок сетки; на 1024 меняется ещё и шкала шрифта — блок в конце файла;
     на 1280 и 1920 — снова только число колонок (на 1920 плюс снятый предел
     ширины сетки). */

  /* Пределы ширины сняты с 1920 — верхней границы макета 1280–1920: у контента
     поля 24 (1920 − 2·24), у сетки кейсов свои 4 (1920 − 2·4), поэтому пределов
     два. Дальше они расходятся: в макете 1920–max контент замирает на 1872 и
     центрируется (в кадре 4362 шапка, hero и футер стоят на x = 1245 =
     (4362 − 1872) / 2), а сетка идёт во всю ширину — предел с неё снимается,
     см. блок 1920+ в конце файла. */
  --container-max: 1872px;
  --grid-max: 1912px;
  --header-height: 48px;

  /* Сетка кейсов: число колонок — единственная точка правки на брейкпоинтах.
     Читается и из CSS, и из JS (раскладка «кирпичами» построчно). */
  --grid-columns: 2;
  --grid-gap: var(--spacing-sm);
  --grid-inset: var(--spacing-sm);

  /* Каталог кейсов (/cases) — своя сетка и свой счёт колонок: 1 / 2 / 3 против
     2 / 4 / 3 / 4 / 6 у ленты на главной. Ломается она в двух местах из
     шести — на 768 и на 1280, — поэтому переопределения ниже стоят не во всех
     блоках. Кладка построчная, поэтому JS про это число ничего не знает:
     колонки раскладывает сам грид (blocks/catalog.css). */
  --catalog-columns: 1;
}

/* --- Тёмная тема ---------------------------------------------------------
   Развилок две, и обе нужны: системная тема и выбор пользователя. Значения
   при этом не дублируются — оба правила раздают одни и те же `--*-dark`,
   объявленные выше по одному разу.

   Списки токенов одинаковые, и это единственное, что здесь повторено. Свести
   их в один селектор нельзя: медиазапрос и селектор в CSS не объединяются, а
   переключать кастомные свойства «через переменную-тумблер» — трюк, который
   читается хуже, чем два честных блока.

   Первое правило — системная тема. `:not([data-theme="light"])` обязателен:
   без него выбранная светлая тема на системной тёмной перекрашивалась бы
   обратно, потому что атрибут стоит ниже по специфичности только у второго
   правила.

   Второе — выбор пользователя. Атрибут ставит js/theme.js и бутстрап в
   <head> каждой страницы (до загрузки JS, чтобы страница не мигнула светлой).
   Оба правила по 0,2,0, и спор решает порядок: выбор объявлен ниже системы,
   поэтому и побеждает. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --color-bg-base: var(--color-bg-base-dark);
    --color-text-primary: var(--color-text-primary-dark);
    --color-border-primary: var(--color-border-primary-dark);
    --color-border-subtle: var(--color-border-subtle-dark);
    --color-bg-placeholder: var(--color-bg-placeholder-dark);
    --color-bg-hover-base: var(--color-bg-hover-base-dark);
    --color-border-panel: var(--color-border-panel-dark);
  }
}

:root[data-theme="light"] {
  color-scheme: light;
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --color-bg-base: var(--color-bg-base-dark);
  --color-text-primary: var(--color-text-primary-dark);
  --color-border-primary: var(--color-border-primary-dark);
  --color-border-subtle: var(--color-border-subtle-dark);
  --color-bg-placeholder: var(--color-bg-placeholder-dark);
  --color-bg-hover-base: var(--color-bg-hover-base-dark);
  --color-border-panel: var(--color-border-panel-dark);
}

/* 768–1023 · Figma 3:3620 — четыре колонки вместо двух.
   Колонка при опорной ширине 768: (768 − 4·2 − 4·3) / 4 = 187.
   Больше в этом брейкпоинте не меняется ничего: JS перечитает переменную
   и переложит плитки, параллакс пересчитает дельты сам. */
@media (min-width: 768px) {
  :root {
    --grid-columns: 4;
    /* Каталог · Figma 22:3703 — две колонки: (768 − 4·2 − 4) / 2 = 378 */
    --catalog-columns: 2;
  }
}

/* 1024–1279 · Figma 3:3685 — у этого фрейма другой мод Figma Variables,
   поэтому меняются сами токены размера, а не отдельные блоки:
     font-size/xs  12 → 14   (шапка, теги кейса)
     font-size/sm  14 → 16   (подписи hero, футер, крошки и фильтры каталога)
     font-size/md  16 → 18   (заголовок кейса в активном состоянии, описание
                              карточки каталога)
     font-size/lg  20 → 24   (название карточки каталога)
     font-size/xl  24 → 32   (заголовки разделов правовой страницы)
     font-size/2xl 28 → 40   (заголовки секций страницы кейса)
     font-size/3xl 32 → 48   (H1, «Cases» в шапке каталога)
   Высоты строк пересчитаны по тому же правилу «×1.4 и округлить»:
   14 × 1.4 = 19.6 → 20; 16 × 1.4 = 22.4 → 22. Отсюда высоты блоков макета:
   hero 340, футер 70.
   font-size/md ходит по множителю 1.5 (Text xl), там округлять нечего:
   16 × 1.5 = 24, 18 × 1.5 = 27 — обе высоты целые и совпадают с Figma.
   Колонок в сетке — три (шире, чем четыре на 768): при опорной ширине 1024
   колонка (1024 − 4·2 − 4·2) / 3 = 336. */
@media (min-width: 1024px) {
  :root {
    --font-size-xs: 14px;
    --font-size-sm: 16px;
    --font-size-md: 18px;
    --font-size-lg: 24px;
    --font-size-xl: 32px;
    --font-size-2xl: 40px;
    --font-size-3xl: 48px;

    --line-height-text-md: 22px;
    --line-height-text-sm: 20px;

    --grid-columns: 3;
  }
}

/* 1280–1920 · Figma 3:3738 — мод Figma Variables тот же, что на 1024 (xs 14,
   sm 16, 3xl 48), поэтому шапка, hero и футер правок не требуют вовсе: их
   геометрия резиновая и на 1280 сходится с макетом сама. Отличие ровно одно —
   колонок в сетке снова четыре, плитки в макете мельче.
   Колонка при опорной ширине 1280: (1280 − 4·2 − 4·3) / 4 = 315. */
@media (min-width: 1280px) {
  :root {
    --grid-columns: 4;
    /* Каталог · Figma 22:3887 — три колонки: (1280 − 4·2 − 4·2) / 3 = 421.33.
       На 1024 их было две (506) — единственная смена между 768 и 1920. */
    --catalog-columns: 3;
  }
}

/* 1920–max · Figma 3:3803 (кадр 4362×10336.85) — мод Figma Variables снова тот
   же (xs 14, sm 16, 3xl 48), поэтому шапка, hero и футер правок не требуют:
   их контейнер уже упирается в --container-max = 1872 и центрируется, а в
   макете они и стоят на x = 1245 = (4362 − 1872) / 2.
   Меняется только сетка кейсов, и сразу двумя правками:
     колонок шесть вместо четырёх;
     предел ширины снимается — в макете сетка идёт во всю ширину кадра
     (внутренний фрейм 4354 = 4362 − 4·2, поля те же 4).
   Колонка = (W − 4·2 − 4·5) / 6: при 1920 — 315.33, при 4362 — 722.33
   (в макете 722.33). То есть на 1920 плитка возвращается к размеру из макета
   1280 (315) — дизайнер добрал ширину колонками, а не размером плитки.

   Каталога кейсов это не касается вовсе: там и колонок по-прежнему три, и
   предел ширины свой — сетка замирает на 1872 вровень с контентом (в макете
   22:3990 шапка, фильтры и сетка стоят на одном x = 344), поэтому
   --grid-max: none её не задевает. */
@media (min-width: 1920px) {
  :root {
    --grid-columns: 6;
    --grid-max: none;
  }
}
