/* ==========================================================================
   v4/shared/tokens.css — единственный источник истины для палитры, шрифтовой
   и пространственной шкал. Подключается КАЖДЫМ вариантом до его style.css.

   Здесь нет ни одного правила раскладки: только переменные + сброс + утилиты,
   которые обязаны вести себя одинаково во всех четырёх вариантах
   (skip-link, :focus-visible, reduced-motion, размер тап-таргета).

   Палитра «Песок и море» — из прототипа design/project/Nadjusha Photo.dc.html.
   Вариант может пере-взвешивать, какую часть палитры использует, но не может
   вводить другое семейство оттенков.
   ========================================================================== */

@import url("./fonts/fonts.css");

:root {
  /* --- Палитра «Песок и море» ------------------------------------------- */
  --bg: #f2e6cc;        /* песок, основной фон */
  --bg2: #fbf3de;       /* светлее — полотно секций */
  --ink: #1f2e2c;       /* тёмно-зелёные чернила, основной текст */
  --soft: #546663;      /* приглушённый текст */
  --accent: #e07b2f;    /* закатный оранжевый */
  --deep: #0f6e84;      /* глубокая морская волна */
  --line: #e0cfa8;      /* линии, рамки */
  --heroem: #ffce7a;    /* тёплый акцент на тёмном/фото */
  /* Прототипный #4a2f14 на #e07b2f даёт измеренные 4.12:1 — это провал AA для
     обычного текста (нужно 4.5:1). Затемнено до #2f1d0b → 5.41:1, оттенок тот
     же. Проверка: python3 scripts/contrast.py '#2f1d0b' '#e07b2f' */
  --onaccent: #2f1d0b;  /* текст на --accent (5.41:1) */
  --ondeep: #fdf6e3;    /* текст на --deep (5.43:1) */
  /* --heroem на --deep = 4.01:1 → только для КРУПНОГО текста (≥24px/19px bold). */

  /* Производные: тексты поверх фотографий. Пелена + чистый белый даёт
     измеренный контраст ≥ 4.5:1 — дефект прототипа (подзаголовок утопал
     в светлом небе) лечится здесь, а не в каждом варианте. */
  --onphoto: #ffffff;
  --onphoto-soft: #f4ece0;
  /* Вертикальная пелена под текстом на фото. Верх слегка притемнён ради
     читаемости шапки, низ — сильно, там живут заголовок и CTA. */
  --veil: linear-gradient(
      180deg,
      rgba(18, 26, 27, 0.42) 0%,
      rgba(18, 26, 27, 0.18) 30%,
      rgba(18, 26, 27, 0.5) 62%,
      rgba(14, 21, 22, 0.82) 100%);
  /* Локальная подложка под конкретный текстовый блок на фото. */
  --veil-block: radial-gradient(
      120% 100% at 12% 100%,
      rgba(12, 19, 20, 0.78) 0%,
      rgba(12, 19, 20, 0.5) 45%,
      rgba(12, 19, 20, 0) 100%);

  /* --- Шрифты ----------------------------------------------------------- */
  --serif: "Cormorant Garamond", "Times New Roman", serif;
  --sans: "Jost", "Helvetica Neue", Arial, sans-serif;

  /* --- Типографическая шкала (мажорная терция, 1.25, fluid) -------------- */
  --t-micro: 0.72rem;                              /* надзаголовки, капс */
  --t-small: 0.83rem;                              /* подписи */
  --t-body: clamp(0.98rem, 0.94rem + 0.2vw, 1.08rem);
  --t-lead: clamp(1.1rem, 1rem + 0.5vw, 1.32rem);  /* лид-абзац */
  --t-h4: clamp(1.1rem, 1rem + 0.6vw, 1.4rem);
  --t-h3: clamp(1.35rem, 1.15rem + 0.9vw, 1.85rem);
  --t-h2: clamp(1.95rem, 1.4rem + 2.4vw, 3.1rem);
  --t-h1: clamp(2.5rem, 1.5rem + 4.6vw, 5.2rem);
  --t-display: clamp(3rem, 1.4rem + 7vw, 7.5rem);  /* вариант B, крупный вынос */

  --lh-tight: 1.06;
  --lh-head: 1.14;
  --lh-body: 1.65;
  --tr-caps: 0.28em;   /* трекинг для капса */
  --tr-wide: 0.14em;

  /* --- Пространственная шкала (база 8px, ×1.5/×2) ------------------------ */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;
  --s-10: 8rem;
  /* Вертикальный ритм секции и боковые поля — единые для всех вариантов. */
  --sec-y: clamp(3.5rem, 9vh, 7rem);
  --gut: clamp(1.25rem, 4vw, 4rem);
  --measure: 62ch;      /* предел строки для читаемого текста */

  --rad: 6px;
  --rad-pill: 999px;
  --shadow-lift: 0 14px 44px rgba(30, 40, 42, 0.16);
  --shadow-deep: 0 24px 80px rgba(12, 19, 20, 0.45);

  /* --- Движение ---------------------------------------------------------- */
  --ease: cubic-bezier(0.2, 0.6, 0.2, 1);
  --dur-fast: 0.18s;
  --dur: 0.32s;
  --dur-slow: 0.8s;

  /* --- Гарантии мобильного опыта ----------------------------------------- */
  --tap: 44px;          /* минимальный тап-таргет */
  --header-h: 56px;     /* потолок фиксированной шапки; ось 3 требует ≤ 64px */
  color-scheme: light;
}

/* ==== Сброс ================================================================ */

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-h) + var(--s-4));
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 300;
  font-size: var(--t-body);
  line-height: var(--lh-body);
  /* overflow-x: clip вместо hidden — не создаёт scroll-контейнер и не ломает
     position: sticky у кинематографической сцены варианта A. */
  overflow-x: clip;
  text-rendering: optimizeLegibility;
  /* На 200% масштабе (html{font-size:200%} — прокси-тест reflow/WCAG
     1.4.10 без настоящего браузерного зума) отдельные ДЛИННЫЕ слова
     (заголовки вроде «прозрачность», хэндлы вроде «@nadjusha.shcherbina»,
     нумерованные пункты борда) оказываются физически шире своей колонки —
     не строка целиком, а одно неразрывное слово/токен. text-wrap: balance/
     pretty этого не чинят: они выбирают ГДЕ перенести строку МЕЖДУ
     словами, а тут не помещается одно слово. overflow-wrap: anywhere
     разрешает разрыв ВНУТРИ слова и только когда оно правда не влезает —
     наследуется на все h1-h4/p/li/кнопки разом, не трогая переносы там,
     где слова и так помещаются. Без него текст не ломался видимо (просто
     вылезал через ink overflow скрыто от глаз), но раздвигал
     document.documentElement.scrollWidth на десятки пикселей на каждой
     из пяти страниц проекта — один и тот же класс дефекта возникал
     заново в каждом отдельном компоненте, пока не унаследовали отсюда. */
  overflow-wrap: anywhere;
}

h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 400;
  line-height: var(--lh-head);
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; text-wrap: pretty; }

/* height: auto — обязательная половина идиомы, а не украшение. Без неё
   `max-width: 100%` ужимает ТОЛЬКО ширину, а высота остаётся равной атрибуту
   height= из разметки, и кадр тянется. Так фото автора (родные 851×851)
   рисовалось 480×851 в a-cinematic, 416×851 в b-editorial и c-gallery.
   Картинки, которым высота нужна явная (object-fit: cover в плитках, лентах,
   миниатюрах), задают её классом — селектор класса перебивает этот сброс. */
img, picture, video { display: block; max-width: 100%; height: auto; }

a { color: var(--deep); text-decoration: none; }

button { font: inherit; color: inherit; }

ul { margin: 0; padding: 0; list-style: none; }

/* ==== Доступность =========================================================
   Единые для всех вариантов: скип-линк, видимый фокус, класс для скринридера.
   ========================================================================= */

.skip-link {
  position: absolute;
  left: var(--s-4);
  top: var(--s-2);
  z-index: 200;
  /* Без max-width — только с `left` (без `right`/`width`) — раскладка
     абсолютного элемента считает ширину по содержимому (shrink-to-fit) и
     ничем не ограничена справа: на 200% масштабе (прокси-тест reflow)
     текст «Перейти к содержанию» шире 320px-вьюпорта и уезжает за край.
     max-width заставляет обычный (не заданный явно, значит normal)
     white-space перенести строку — так же, как перенеслась бы любая
     обычная надпись в контейнере с ограниченной шириной. */
  max-width: calc(100% - 2 * var(--s-4));
  transform: translateY(-160%);
  background: var(--deep);
  color: var(--ondeep);
  padding: var(--s-3) var(--s-5);
  border-radius: var(--rad);
  font-size: var(--t-small);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  transition: transform var(--dur) var(--ease);
}
.skip-link:focus { transform: translateY(0); }

/* Одноцветное кольцо не проходит WCAG 1.4.11 на всех фонах разом:
   --accent на --bg/--bg2 даёт 2.41:1/2.69:1 (нужно ≥3:1), --ink на тёмной
   сцене варианта A — 1.17:1. Один сплошной тон не может быть виден и на
   песке, и на тёмном сразу.
   Решение — двойное кольцо (WCAG technique G195): тёмное вплотную к
   элементу + акцентное снаружи. На светлом фоне (B/C/D) контраст даёт
   тёмное кольцо (--ink на --bg 11.42:1, на --bg2 12.78:1), акцентное
   кольцо там же — просто декоративный акцент бренда. На тёмной сцене
   варианта A тёмное кольцо сливается с фоном (1.17:1, невидимо), но
   акцентное кольцо снаружи держит 5.54:1 — кольцо остаётся видимым в
   обоих случаях. outline оставлен прозрачным ради forced-colors/Windows
   High Contrast: там box-shadow браузер убирает, а outline принудительно
   перекрашивается системой и остаётся единственным видимым индикатором.
   Проверка: python3 scripts/contrast.py '#1f2e2c' '#f2e6cc'  → 11.42:1
             python3 scripts/contrast.py '#1f2e2c' '#fbf3de'  → 12.78:1
             python3 scripts/contrast.py '#e07b2f' '#16211f'  → 5.54:1 */
:focus-visible {
  outline: 3px solid transparent;
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--ink), 0 0 0 6px var(--accent);
  border-radius: 2px;
}
/* На фото/тёмном фоне яркость под текстом непредсказуема (заливка +
   веер), поэтому внешнее кольцо там — тёплый heroem вместо accent (тот же
   принцип двойного кольца, просто внешний тон ярче: 11.30:1 на тёмной
   сцене против 5.54:1 у accent — с запасом на разные фотографии). */
.on-photo :focus-visible,
.lb :focus-visible {
  box-shadow: 0 0 0 3px var(--ink), 0 0 0 6px var(--heroem);
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Любой интерактивный элемент обязан быть не меньше пальца. */
.tap {
  min-width: var(--tap);
  min-height: var(--tap);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ==== Кнопки — общая механика, вид довариант дорабатывает ================= */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: var(--tap);
  padding: var(--s-3) var(--s-6);
  border: 1px solid transparent;
  border-radius: var(--rad-pill);
  font-size: var(--t-small);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  cursor: pointer;
  /* Подписи каналов связи вида «Instagram · @nadjusha.shcherbina» несут
     неразрывный хэндл, который на 200% масштабе шире кнопки — перенос
     внутри слова уже унаследован от body { overflow-wrap: anywhere }
     выше, здесь отдельно объявлять не нужно. */
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease),
              color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              filter var(--dur) var(--ease);
}
.btn--accent { background: var(--accent); color: var(--onaccent); }
.btn--accent:hover { transform: translateY(-2px); filter: brightness(1.06); color: var(--onaccent); }
.btn--deep { background: var(--deep); color: var(--ondeep); }
.btn--deep:hover { transform: translateY(-2px); filter: brightness(1.08); color: var(--ondeep); }
.btn--ghost { border-color: var(--deep); color: var(--deep); background: transparent; }
.btn--ghost:hover { background: var(--deep); color: var(--ondeep); }
.btn--onphoto {
  border-color: rgba(255, 255, 255, 0.8);
  color: var(--onphoto);
  background: rgba(14, 21, 22, 0.34);
  backdrop-filter: blur(6px);
}
.btn--onphoto:hover { background: rgba(255, 255, 255, 0.2); color: var(--onphoto); }

/* ==== Уважение к prefers-reduced-motion ==================================
   Один блок на весь проект: гасит анимации, отключает smooth-scroll и
   переводит скролл-сцену варианта A в статический режим (см. его style.css).
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
