/* ===========================================================================
   base.css — сброс, фон-глубина, типографика, фокус, движение, скроллбары,
   утилиты. Требует tokens.css. Ни одного литерального цвета — только var()
   (единственное исключение — блок @media print внизу: там цвет задаёт бумага,
   а не тема).

   ТЕМА ОДНА — ТЁМНАЯ. Ни prefers-color-scheme, ни [data-theme] в файле нет.
   Стеклянные слои рассчитаны на тёмную глубину; на светлом фоне те же
   прозрачности дают молочную муть (см. шапку tokens.css).
   =========================================================================== */

/* ---------------------------------------------------------------------------
   1. Сброс
   --------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Опора для 100dvh на мобильных: адресная строка не должна резать доску. */
  height: 100%;
  /* База глубины живёт на корне, а не на body. Фон корневого элемента
     распространяется на холст окна, поэтому он покрывает и область
     переспуска (overscroll), и полосу под адресной строкой. Если бы база
     стояла на body, она перекрыла бы пятна из body::before: отрицательный
     z-index рисуется раньше фона блока-предка. */
  background-color: var(--bg-base);
}

body {
  margin: 0;
  min-height: 100dvh;
  min-width: 320px;          /* поддержка от 360px с запасом */
  /* Прозрачный намеренно: фон идёт от html + body::before. */
  background-color: transparent;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overscroll-behavior-y: none;
}

/* ---------------------------------------------------------------------------
   1a. ГЛУБИНА ФОНА
   Стекло видно только над неоднородным фоном: размытие однородной заливки
   неотличимо от самой заливки. Поэтому под интерфейсом лежат два мягких
   цветных пятна и виньетка.

   Слой прибит к вьюпорту (position: fixed), а не к документу. Это не
   украшение, а условие работы стекла: при прокрутке доски пятна обязаны
   стоять на месте, иначе размытие под панелью «плывёт» и пластина
   перестаёт читаться как физический предмет.

   z-index: -1 ставит слой позади всего содержимого, но поверх холста окна.
   pointer-events: none — слой не перехватывает клики и не мешает
   перетаскиванию карточек.
   --------------------------------------------------------------------------- */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  /* Порядок слоёв в background-image — сверху вниз, поэтому виньетка идёт
     ПОСЛЕДНЕЙ: она лежит под пятнами и не гасит их.
     Центры пятен сдвинуты внутрь кадра (а не в углы) намеренно: в углах их
     съедала бы та же виньетка, и на экране осталась бы ровная чернота, под
     которой стеклу нечего показывать. */
  background-image:
    /* холодное пятно — за первыми колонками доски */
    radial-gradient(62% 58% at 24% 16%, var(--bg-glow-1) 0%, transparent 66%),
    /* фиолетовое пятно — в противоположной четверти, для диагонали */
    radial-gradient(58% 54% at 78% 74%, var(--bg-glow-2) 0%, transparent 64%),
    /* виньетка: гасит только сами края кадра */
    radial-gradient(125% 110% at 50% 45%, transparent 58%, var(--bg-vignette) 100%);
  background-repeat: no-repeat;
}

h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }
ul[class], ol[class] { list-style: none; margin: 0; padding: 0; }

img, svg, video, canvas, picture {
  display: block;
  max-width: 100%;
}
img, video { height: auto; }

button, input, select, textarea, optgroup {
  font: inherit;
  color: inherit;
  margin: 0;
}
button { background: none; border: 0; padding: 0; cursor: pointer; }
button:disabled, input:disabled, select:disabled, textarea:disabled { cursor: not-allowed; }
textarea { resize: vertical; }

table { border-collapse: collapse; border-spacing: 0; }

hr {
  border: 0;
  height: var(--hairline);
  background-color: var(--border);
  margin: var(--space-4) 0;
}

/* Диалог: сброс браузерных полей — оформление в components.css. */
dialog { padding: 0; border: 0; color: inherit; max-width: none; max-height: none; }

::selection {
  background-color: var(--selection-bg);
  color: var(--selection-text);
}

/* ---------------------------------------------------------------------------
   2. Типографика
   --------------------------------------------------------------------------- */
h1 { font-size: var(--text-2xl); font-weight: var(--weight-bold);     line-height: var(--leading-tight); }
h2 { font-size: var(--text-xl);  font-weight: var(--weight-semibold); line-height: var(--leading-tight); }
h3 { font-size: var(--text-lg);  font-weight: var(--weight-semibold); line-height: var(--leading-snug); }
h4 { font-size: var(--text-md);  font-weight: var(--weight-semibold); line-height: var(--leading-snug); }
h5, h6 { font-size: var(--text-sm); font-weight: var(--weight-semibold); }

small { font-size: var(--text-xs); }

a {
  color: var(--text-link);
  text-decoration: none;
  border-radius: var(--radius-sm);
}
a:hover { color: var(--text-link-hover); text-decoration: underline; }

/* Пользовательский текст (описание карточки, комментарий) — читаемая мера
   строки и подчёркнутые ссылки, чтобы они не терялись в потоке. */
.prose {
  line-height: var(--leading-loose);
  max-width: 72ch;
  overflow-wrap: anywhere;
}
.prose > * + * { margin-top: var(--space-3); }
.prose a { text-decoration: underline; }
.prose h1, .prose h2, .prose h3 { margin-top: var(--space-5); }
.prose ul, .prose ol { padding-left: var(--space-5); }
.prose li + li { margin-top: var(--space-1); }
.prose code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  padding: 1px var(--space-1);
  border-radius: var(--radius-xs);
  background-color: var(--surface-sunken);
  color: var(--text);            /* на sunken 15.38 */
}
.prose pre {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  background-color: var(--surface-sunken);
  color: var(--text);
  overflow-x: auto;
}
.prose pre code { background: none; padding: 0; }
.prose blockquote {
  padding-left: var(--space-3);
  border-left: 3px solid var(--border-strong);
  color: var(--text-secondary);  /* 8.33 */
}
.prose img { border-radius: var(--radius-md); }

/* Заголовок-рубрика над группой (ВЕРХНИЙ РЕГИСТР — только мелким кеглем и с
   разрядкой, иначе капс нечитаем). */
.eyebrow {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);      /* 6.59 */
}

/* ---------------------------------------------------------------------------
   3. Фокус
      Видимое кольцо только для клавиатуры (:focus-visible). Ширина 2px,
      отступ 2px — кольцо не съедает содержимое и не сливается с рамкой.

      КОЛЬЦО НА СТЕКЛЕ. Кольцо #7FB4FF проверено против непрозрачных
      эквивалентов всех трёх плотностей (это худший случай — стекло над самым
      светлым местом фонового пятна):
          --glass-thin-solid  #232830 → 6.79:1
          --glass-solid       #1F242B → 7.46:1
          --glass-thick-solid #232931 → 6.74:1
      Всюду выше требуемых 3:1 для нетекстовых элементов. Дополнительно
      outline-offset в 2px отделяет кольцо от кромочного блика
      (--glass-highlight), с которым синяя линия иначе спорит.
   --------------------------------------------------------------------------- */
:focus { outline: none; }

:focus-visible {
  outline: var(--focus-width) solid var(--focus-ring);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-sm);
}

/* Поверх фото доски системный синий может утонуть — там кольцо белое.
   Белый на скриме 0.62 даёт ≥6.19:1 даже на полностью белом фото. */
.on-board :focus-visible,
.board__bar :focus-visible,
.board__canvas > :focus-visible { outline-color: var(--focus-ring-inverse); }

/* Элемент, которому фокус ставится программно (открытая модалка, поповер),
   кольца не показывает — оно там только шумит. */
[tabindex="-1"]:focus:not(:focus-visible) { outline: none; }

/* ---------------------------------------------------------------------------
   4. Движение
      Полный отказ от анимации при системной настройке. 0.01ms, а не 0 —
      чтобы события transitionend/animationend продолжали приходить и
      скрипты, ждущие их, не зависали.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  html { scroll-behavior: auto; }
}

/* ---------------------------------------------------------------------------
   4a. ПОНИЖЕННАЯ ПРОЗРАЧНОСТЬ
      Системная настройка «уменьшить прозрачность» (macOS/iOS Reduce
      Transparency, Windows «Эффекты прозрачности») — просьба человека, а не
      предпочтение оформителя. Подменяем стеклянные токены на их непрозрачные
      эквиваленты и заодно снимаем размытие: без прозрачности размывать нечего,
      а backdrop-filter продолжал бы жечь GPU впустую.

      Пятна фона при этом остаются: они рисуются под интерфейсом, а не сквозь
      него, и на читаемость не влияют.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-transparency: reduce) {
  :root {
    --glass-thin:  var(--glass-thin-solid);
    --glass:       var(--glass-solid);
    --glass-thick: var(--glass-thick-solid);

    --glass-blur:        none;
    --glass-blur-strong: none;
    --glass-blur-weak:   none;
  }
}

/* ---------------------------------------------------------------------------
   5. Скроллбары
      Тонкие и в цвете темы. Горизонтальный скролл холста доски — толще,
      его тянут мышью.
   --------------------------------------------------------------------------- */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background-color: var(--border-strong);
  border-radius: var(--radius-pill);
  border: 2px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--text-muted); background-clip: content-box; }
::-webkit-scrollbar-corner { background: transparent; }

.board__canvas::-webkit-scrollbar { height: 12px; }

/* ---------------------------------------------------------------------------
   6. Пальцевой ввод
      На мыши интерфейс компактный (32px — как в Trello). Как только
      указатель грубый, все интерактивные элементы дорастают до 44px.
   --------------------------------------------------------------------------- */
@media (pointer: coarse) {
  button,
  [role="button"],
  a.btn,
  input:not([type="checkbox"]):not([type="radio"]),
  select,
  summary,
  .btn,
  .menu__item,
  .sidebar__item {
    min-height: var(--tap-target);
  }
  .btn--icon,
  .icon-button {
    min-width: var(--tap-target);
    min-height: var(--tap-target);
  }
  /* Мелкий чекбокс остаётся 16px визуально, но получает невидимую площадь
     нажатия 44×44 через псевдоэлемент. */
  input[type="checkbox"],
  input[type="radio"] { position: relative; }
  input[type="checkbox"]::after,
  input[type="radio"]::after {
    content: "";
    position: absolute;
    inset: 50% auto auto 50%;
    width: var(--tap-target);
    height: var(--tap-target);
    transform: translate(-50%, -50%);
  }
}

/* ---------------------------------------------------------------------------
   7. Иконки
      Векторные SVG вместо эмодзи: эмодзи в каждой ОС свои, не наследуют
      цвет текста, не масштабируются вместе с ним и озвучиваются
      скринридером как случайное слово.
   --------------------------------------------------------------------------- */
.icon {
  flex: none;
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* Выравнивание по оптической середине строки. */
  vertical-align: -0.15em;
}
.icon--sm { width: 12px; height: 12px; stroke-width: 1.8; }
.icon--lg { width: 20px; height: 20px; }
.icon--xl { width: 24px; height: 24px; stroke-width: 1.5; }
.icon--filled { fill: currentColor; stroke: none; }

/* ---------------------------------------------------------------------------
   8. Утилиты
      Маленький закрытый набор. Всё, что повторяется больше трёх раз, должно
      переехать в components.css компонентом, а не разрастаться здесь.
   --------------------------------------------------------------------------- */

/* Скрыто визуально, доступно скринридеру. Основной инструмент подписи для
   иконочных кнопок и цветовых полосок. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.sr-only-focusable:not(:focus):not(:focus-within) {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.u-hidden { display: none !important; }
.u-invisible { visibility: hidden; }

.u-truncate {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.u-clamp-2,
.u-clamp-3 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.u-clamp-2 { -webkit-line-clamp: 2; line-clamp: 2; }
.u-clamp-3 { -webkit-line-clamp: 3; line-clamp: 3; }

.u-break { overflow-wrap: anywhere; word-break: break-word; }
.u-nowrap { white-space: nowrap; }

.u-row    { display: flex; align-items: center; gap: var(--space-2); }
.u-row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.u-col    { display: flex; flex-direction: column; gap: var(--space-2); }
.u-wrap   { flex-wrap: wrap; }
.u-grow   { flex: 1 1 auto; min-width: 0; }
.u-none   { flex: none; }

.u-gap-1 { gap: var(--space-1); }
.u-gap-2 { gap: var(--space-2); }
.u-gap-3 { gap: var(--space-3); }
.u-gap-4 { gap: var(--space-4); }
.u-gap-6 { gap: var(--space-6); }

.u-muted     { color: var(--text-muted); }      /* 6.59 */
.u-secondary { color: var(--text-secondary); }  /* 8.33 */
.u-danger    { color: var(--danger-text); }     /* 7.23 */
.u-success   { color: var(--success-text); }    /* 9.66 */

.u-text-2xs { font-size: var(--text-xs); }
.u-text-xs  { font-size: var(--text-xs); }
.u-text-sm  { font-size: var(--text-sm); }
.u-text-lg  { font-size: var(--text-lg); }
.u-semibold { font-weight: var(--weight-semibold); }
.u-center   { text-align: center; }

.u-scroll-x { overflow-x: auto; overscroll-behavior-x: contain; }
.u-scroll-y { overflow-y: auto; overscroll-behavior-y: contain; }

/* Ширина контента страницы. clamp вместо max-width, чтобы на 360px не
   осталось нулевых полей. */
.container {
  width: 100%;
  max-width: 1240px;
  margin-inline: auto;
  padding-inline: clamp(var(--space-3), 3vw, var(--space-8));
}
.container--narrow { max-width: 720px; }

/* Ссылка «к содержимому» для клавиатуры. Стеклянная пластина: она всплывает
   над произвольным содержимым, и предсказуемого фона под ней нет. */
.skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: var(--z-toast);
  padding: var(--space-2) var(--space-4);
  border: var(--hairline) solid var(--glass-border);
  border-radius: var(--radius-lg);
  background-color: var(--glass-thick);
  -webkit-backdrop-filter: var(--glass-blur-strong);
  backdrop-filter: var(--glass-blur-strong);
  color: var(--text);            /* на thick-solid 12.02 */
  box-shadow: inset 0 1px 0 var(--glass-highlight),
              inset 0 -1px 0 var(--glass-shade),
              var(--shadow-lg);
}

/* ---------------------------------------------------------------------------
   9. Режимы повышенного контраста и принудительных цветов
   --------------------------------------------------------------------------- */
@media (prefers-contrast: more) {
  :root {
    --border: var(--border-strong);
    --border-subtle: var(--border-strong);
    /* Прозрачность и повышенный контраст несовместимы: сквозь стекло
       проступает фон и «съедает» разницу. Гасим до непрозрачного. */
    --glass-thin:  var(--glass-thin-solid);
    --glass:       var(--glass-solid);
    --glass-thick: var(--glass-thick-solid);
    --glass-border: var(--border-strong);
    --glass-border-strong: var(--border-strong);
  }
  :focus-visible { outline-width: 3px; }
}

@media (forced-colors: active) {
  /* В режиме высокой контрастности Windows фон и рамки задаёт система.
     Наша задача — не потерять границы там, где мы рисовали их фоном или
     стеклом, и снять размытие: оно в forced-colors только мылит текст. */
  .btn,
  .input,
  .card,
  .list,
  .popover,
  .panel,
  .board-tile,
  .toast,
  .modal { border: 1px solid CanvasText; }

  .app-bar,
  .board__bar,
  .sidebar,
  .list,
  .popover,
  .menu,
  .panel,
  .toast,
  .modal,
  .skip-link {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
  }

  .label { forced-color-adjust: none; } /* цвет метки — сам смысл, сохраняем */
  :focus-visible { outline: 3px solid Highlight; }
}

/* ---------------------------------------------------------------------------
   10. Печать
      Единственное место с литеральным цветом: бумага всегда белая, и тема
      интерфейса к ней отношения не имеет. Стекло и пятна фона на печати
      выключаются целиком.
   --------------------------------------------------------------------------- */
@media print {
  html { background: #fff; }
  body { background: #fff; color: #000; }
  body::before { display: none; }
  .app-bar, .sidebar, .toast-stack, .skeleton { display: none !important; }
  .board__canvas { display: block; overflow: visible; height: auto; }
  .list {
    break-inside: avoid;
    width: 100%;
    max-width: none;
    background: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
  }
}
