/* Лендинг Oboton в дизайн-системе «ТокенСток» — той же, что живёт в кабинете
   agent.oboton.ru: тёплая бумага, графитовые чернила, моно-акценты, точечная
   фактура. Человек, пришедший с лендинга в кабинет, не должен почувствовать,
   что сменил продукт.
   Шрифты лежат рядом: страница не зависит от чужих серверов и не мигает
   системным шрифтом на медленной сети. */

/* ── шрифты ─────────────────────────────────────────────────────────────── */
/* Manrope вариативный: один файл закрывает начертания 200–800. Кириллица
   отдельным подмножеством — латинский файл её не содержит. */
@font-face {
  font-family: Manrope; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url(/fonts/manrope-latin.woff2) format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: Manrope; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url(/fonts/manrope-cyrillic.woff2) format("woff2-variations");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "JB Mono"; font-style: normal; font-weight: 100 800; font-display: swap;
  src: url(/fonts/mono-latin.woff2) format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+2122, U+2212;
}
@font-face {
  font-family: "JB Mono"; font-style: normal; font-weight: 100 800; font-display: swap;
  src: url(/fonts/mono-cyrillic.woff2) format("woff2-variations");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* ── тема ───────────────────────────────────────────────────────────────── */
/*
 * Токены — те же имена и значения, что в globals.css кабинета. Светлая
 * «бумага» — база, как и там; тёмная переопределяет те же имена, поэтому
 * разметка ниже про темы ничего не знает.
 *
 * Три состояния: auto (по системе, значение по умолчанию), light и dark —
 * выбор человека. Порядок правил важен: медиазапрос стоит выше явных
 * переопределений, иначе тёмная система перебивала бы кнопку «светлая».
 *
 * Шесть цветов агентов — расширение лендинга: кабинет монохромный, но здесь
 * агентов надо различать. Тона земляные, в палитре бумаги; на тёмной теме —
 * светлее, иначе не читаются.
 */
:root {
  --pad: clamp(20px, 5vw, 44px);
  --maxw: 1160px;
  --sans: Manrope, -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
  --mono: "JB Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --r-sm: 10px; --r-md: 14px; --r-lg: 18px; --r-xl: 24px; --r-pill: 999px;
  --ease: cubic-bezier(.2, .7, .2, 1);
  /* Кривая появлений wellmade.studio: резкий старт и очень длинный мягкий
     хвост — блок почти сразу на месте, но ещё долго «дозванивает». */
  --ease-float: cubic-bezier(.19, 1, .22, 1);
  --dur: .2s;
}

:root, :root[data-theme="light"] {
  color-scheme: light;
  --bg:        #faf9f6;
  --paper:     #f0ede4;
  --card:      #ffffff;
  --ink:       #0c0c0c;
  --ink2:      #2a2a2a;
  --mute:      #6c6c6c;
  --mute2:     #868377;
  --line:      #e6e3da;
  --line2:     #d9d6cd;
  --chip:      #f0ede4;
  --bubble-in: #f0ede4;
  --bubble-out:#0c0c0c;
  --bubble-out-fg:#faf9f6;
  --glow:      12,12,12;

  --accent:    #0c0c0c;
  --accent-fg: #faf9f6;
  --danger:    #b23a2b;
  --success:   #5a6b3a;

  /* Точечная фактура бумаги — как на странице регистрации кабинета. */
  --dot: rgba(30, 27, 18, .05);

  --teal:   #257a68;
  --orange: #a8641c;
  --violet: #6553b8;
  --blue:   #2f6cb3;
  --red:    #b23a2b;
  --green:  #5a7a2e;

  --sh-1: 0 1px 2px rgba(0,0,0,.06);
  --sh-2: 0 8px 30px -14px rgba(0,0,0,.22);
  --sh-3: 0 24px 60px -24px rgba(0,0,0,.30);
}

@media (prefers-color-scheme: dark) {
  /* Не [data-theme="auto"], а «всё, кроме явного выбора»: при полностью
     отключённом JS атрибут не проставится вовсе, и тёмная система получила бы
     светлую страницу. */
  :root:not([data-theme="light"]):not([data-theme="dark"]) {
    color-scheme: dark;
    --bg:        #100f0d;
    --paper:     #1a1814;
    --card:      #16140f;
    --ink:       #f4f1ea;
    --ink2:      #cfcbbf;
    --mute:      #8a867a;
    --mute2:     #756e61;
    --line:      #26221c;
    --line2:     #332e26;
    --chip:      #23201a;
    --bubble-in: #1f1c16;
    --bubble-out:#f4f1ea;
    --bubble-out-fg:#100f0d;
    --glow:      244,241,234;

    --accent:    #f4f1ea;
    --accent-fg: #100f0d;
    --danger:    #e2784f;
    --success:   #8aa05a;

    --dot: rgba(244, 241, 234, .045);

    --teal:   #5fc4ad;
    --orange: #dd9a4e;
    --violet: #a493e8;
    --blue:   #6ea9e0;
    --red:    #e2784f;
    --green:  #9cb86a;

    --sh-1: 0 1px 2px rgba(0,0,0,.3);
    --sh-2: 0 8px 30px -14px rgba(0,0,0,.55);
    --sh-3: 0 24px 60px -24px rgba(0,0,0,.65);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:        #100f0d;
  --paper:     #1a1814;
  --card:      #16140f;
  --ink:       #f4f1ea;
  --ink2:      #cfcbbf;
  --mute:      #8a867a;
  --mute2:     #756e61;
  --line:      #26221c;
  --line2:     #332e26;
  --chip:      #23201a;
  --bubble-in: #1f1c16;
  --bubble-out:#f4f1ea;
  --bubble-out-fg:#100f0d;
  --glow:      244,241,234;

  --accent:    #f4f1ea;
  --accent-fg: #100f0d;
  --danger:    #e2784f;
  --success:   #8aa05a;

  --dot: rgba(244, 241, 234, .045);

  --teal:   #5fc4ad;
  --orange: #dd9a4e;
  --violet: #a493e8;
  --blue:   #6ea9e0;
  --red:    #e2784f;
  --green:  #9cb86a;

  --sh-1: 0 1px 2px rgba(0,0,0,.3);
  --sh-2: 0 8px 30px -14px rgba(0,0,0,.55);
  --sh-3: 0 24px 60px -24px rgba(0,0,0,.65);
}

/* Переключение темы: цвета переезжают за треть секунды, а не хлопают.
   Класс висит только на время перехода — постоянный transition на всей
   странице стоил бы кадров на каждой прокрутке. */
:root.theming, :root.theming * {
  transition: background-color .35s ease, color .35s ease, border-color .35s ease !important;
}
@media (prefers-reduced-motion: reduce) {
  :root.theming, :root.theming * { transition: none !important; }
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background-color: var(--bg);
  /* Точки в клетку 14px — фактура бумаги из кабинета: ровная заливка на
     большом экране выглядит дешёвой, точки убирают это без шума и блюра. */
  background-image: radial-gradient(var(--dot) 1px, transparent 1px);
  background-size: 14px 14px;
  color: var(--ink);
  font: 400 16.5px/1.62 var(--sans);
  letter-spacing: -.006em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Живая сеть агентов на той же решётке (app.js, «фон: живая сеть»). Лежит
   между CSS-точками body и содержимым, поэтому всё, что закрывает точки,
   закрывает и его. */
.bg-algo { position: fixed; inset: 0; z-index: -1; pointer-events: none; }

/* Зерно из прежней, «неоновой» версии страницы: в бумажной системе фактуру
   даёт точечная сетка на фоне, плёнка поверх не нужна. */
.grain { display: none; }

img, video { max-width: 100%; display: block; }
a { color: inherit; }
::selection { background: var(--ink); color: var(--bg); }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 6px; }

/* скроллбары — тонкие, в тон бумаги (как в кабинете) */
* { scrollbar-width: thin; scrollbar-color: var(--line2) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-thumb { background: var(--line2); border-radius: 999px; border: 3px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--mute2); background-clip: content-box; }

.wrap { width: min(100%, var(--maxw)); margin-inline: auto; padding-inline: var(--pad); position: relative; z-index: 2; }

/* ── шапка ──────────────────────────────────────────────────────────────── */
/* Глухая, без стекла и блюра — как топбар кабинета: бумага, линия снизу. */

.top {
  position: sticky; top: 0; z-index: 60;
  background: var(--bg);
  border-bottom: 1px solid transparent;
  transition: border-color .35s;
}
.top--stuck { border-bottom-color: var(--line); }
.top__in { display: flex; align-items: center; justify-content: space-between; gap: 16px; height: 66px; }
/* Полоска прочитанного: заодно показывает, что страница длинная. Чернильная,
   а не радужная — в этой системе один акцент, и это графит. */
.top__prog {
  position: absolute; left: 0; bottom: -1px; height: 2px; width: 0;
  background: var(--ink);
}
.brand {
  /* Кольцо-«О» стоит вместо первой буквы, дальше дописано «ботон», поэтому
     зазор — как между буквами слова, а не как между значком и подписью.
     Начертание — как у логотипа ТокенСтока: Manrope 800 с -.02em. */
  display: inline-flex; align-items: center; gap: 2px;
  font-family: var(--sans); font-weight: 800; font-size: 20px;
  letter-spacing: -.02em; text-decoration: none; color: var(--ink);
}
/* Знак Oboton — «Спутник»: кольцо-O и точка-агент на орбите. Один SVG,
   цвет наследует currentColor, высота — от кегля строки, где стоит.
   Аватары агентов остаются «лицами» с глазами,
   а молния — знак самого продукта. */
.mark-o { display: block; height: 1.16em; width: auto; flex: none; }
/* Подпись авторства в подвале: слово «сделано» — тихое, логотип — обычный. */
.madeby { margin: 0; display: flex; align-items: center; gap: 9px; color: var(--mute); font-size: 14px; }
.top__nav { display: flex; align-items: center; gap: 28px; }
.top__nav a {
  color: var(--mute); text-decoration: none; font-size: 14.5px; font-weight: 500;
  letter-spacing: -.01em; transition: color var(--dur); position: relative;
}
.top__nav a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: -6px; height: 1.5px;
  background: currentColor; transition: right .3s var(--ease);
}
.top__nav a:hover { color: var(--ink); }
.top__nav a:hover::after { right: 0; }
@media (max-width: 980px) { .top__nav { display: none; } }
.top__side { display: flex; align-items: center; gap: 10px; }

/* ── переключатель темы ─────────────────────────────────────────────────── */
/* Три состояния по кругу: авто → светлая → тёмная. «Авто» оставлено кнопкой:
   человек, случайно переключивший тему, должен уметь вернуть её системе,
   не чистя хранилище браузера. Сама кнопка — icon-btn из кабинета. */
.theme {
  width: 38px; height: 38px; flex: none; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--line); background: transparent; color: var(--mute);
  display: grid; place-items: center; position: relative;
  transition: color var(--dur), background var(--dur) var(--ease), border-color var(--dur);
}
.theme:hover { color: var(--ink); background: var(--chip); }
.theme:active { transform: scale(.95); }
.theme svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.7; grid-area: 1 / 1; }
.theme svg { opacity: 0; transform: scale(.6) rotate(-40deg); transition: opacity .3s, transform .4s var(--ease); }
:root[data-theme="auto"] .theme .i-auto,
:root[data-theme="light"] .theme .i-sun,
:root[data-theme="dark"] .theme .i-moon { opacity: 1; transform: none; }
/* Точка-подсказка: тема не выбрана вручную, идёт за системой. */
.theme::after {
  content: ""; position: absolute; right: 6px; bottom: 6px; width: 5px; height: 5px;
  border-radius: 50%; background: var(--ink); opacity: 0; transition: opacity .25s;
}
:root[data-theme="auto"] .theme::after { opacity: .8; }

/* ── кнопки ─────────────────────────────────────────────────────────────── */
/* Как в кабинете: главная — графитовая плашка со скруглением 14px, вторая —
   прозрачная с линией. Никаких пилюль, бликов и теней-гало. */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 13px 22px; border-radius: var(--r-md); border: 1px solid transparent;
  font: 600 15px/1 var(--sans); letter-spacing: -.01em;
  text-decoration: none; cursor: pointer;
  transition: all var(--dur) var(--ease);
}
.btn--primary { color: var(--accent-fg); background: var(--accent); border-color: var(--accent); }
.btn--primary:hover { filter: brightness(1.12); }
.btn--primary:active { transform: translateY(1px); }
.btn--ghost { color: var(--ink); background: transparent; border-color: var(--line2); }
.btn--ghost:hover { background: var(--chip); }
.btn--sm { padding: 9px 15px; font-size: 13.5px; }
@media (prefers-reduced-motion: reduce) { .btn { transition: none; } }

/* ── общие блоки ────────────────────────────────────────────────────────── */

section { padding-block: clamp(72px, 10vw, 128px); position: relative; }

/* Мелкая моноширинная метка над заголовком — тот же приём, что eyebrow в
   кабинете: она задаёт ритм разделам и читается как навигация по документу. */
.klabel {
  display: inline-flex; align-items: center; gap: 10px;
  font: 500 11px/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
  color: var(--mute); margin-bottom: 20px;
}
.klabel::before { content: ""; width: 26px; height: 1px; background: var(--line2); }
.center .klabel::after { content: ""; width: 26px; height: 1px; background: var(--line2); }

.eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 7px 14px 7px 11px; border-radius: var(--r-pill);
  border: 1px solid var(--line2); background: var(--card);
  font: 500 11px/1.5 var(--mono); letter-spacing: .07em; text-transform: uppercase;
  color: var(--mute);
}
.eyebrow b { color: var(--ink); font-weight: 600; }
@media (max-width: 560px) { .hide-sm { display: none; } }

h1, h2, h3 { margin: 0; text-wrap: balance; color: var(--ink); }
h1, h2 { font-weight: 800; line-height: 1.04; letter-spacing: -.03em; }
h1 { font-size: clamp(2.5rem, 7.2vw, 4.6rem); }
h2 { font-size: clamp(1.9rem, 5.2vw, 3.2rem); }
h3 { font-size: clamp(1.18rem, 2.4vw, 1.4rem); line-height: 1.25; letter-spacing: -.02em; font-weight: 700; }

.lead {
  font-size: clamp(1.02rem, 1.95vw, 1.22rem); line-height: 1.58;
  color: var(--mute); margin: 22px 0 0; letter-spacing: -.008em;
}
.center { text-align: center; }
.center .lead { margin-inline: auto; max-width: 48ch; }
.section-head { max-width: 50ch; }
.center.section-head { margin-inline: auto; }

/* ── герой ──────────────────────────────────────────────────────────────── */

.hero { padding-top: clamp(56px, 8vw, 100px); padding-bottom: clamp(48px, 6vw, 84px); overflow: hidden; }
/* Рой: канвас поверх точечной бумаги. Пока агенты в окне работают, часть
   точек решётки «просыпается» и кружит у окна; сделали — каждая возвращается
   точно в свой узел, и канвас очищается. Рисуются только ожившие точки,
   остальная бумага — прежний CSS-фон. */
.hero__dots { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
/* Сетка и неоновые пятна прежней версии. Фактуру в этой системе даёт
   точечная бумага, свечение ей чуждо; элементы остаются в разметке
   (на них смотрит скрипт), но не рисуются. */
.hero__grid { display: none; }
.hero__glow { display: none; }

.hero h1 { margin-top: 26px; }
/* Появление по мотивам «Text streaming»: отсчёт по-прежнему от класса loaded
   (шторка отпустила страницу), но заголовок не всплывает плитой, а
   печатается посимвольно с кареткой — см. «текст печатается на экране» ниже.
   Строчное всплытие остаётся запасным: оно работает, пока скрипт не
   разметил знаки под печать. */
.ln { display: block; padding-bottom: .04em; }
.js .ln__i { display: block; opacity: 0; }
.loaded .ln__i { animation: floatUp 1.7s var(--ease-float) both; }
.loaded .ln:nth-child(2) .ln__i { animation-delay: .12s; }
.loaded .ln:nth-child(3) .ln__i { animation-delay: .24s; }
/* Знаки размечены — строки видимы сразу, набирается сам текст. */
.js h1.tt .ln__i { opacity: 1; animation: none; }
@keyframes floatUp { from { opacity: 0; transform: translateY(60px); } to { opacity: 1; transform: none; } }
/* Короткий подъём — для мелочей вроде строк выпадающей панели. */
@keyframes fadeUp { from { opacity: 0; transform: translateY(18px); } }

.hero .lead { max-width: 54ch; }
.hero__cta { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 34px; }
.hero__note { margin: 20px 0 0; font-size: 14px; color: var(--mute2); letter-spacing: -.005em; }
.hero__note code {
  font: 500 12.5px/1 var(--mono); color: var(--ink2); letter-spacing: -.01em;
  background: var(--chip); border: 1px solid var(--line); padding: 2px 6px; border-radius: 6px;
}

/* Появление первого экрана: не всё разом, а по порядку чтения — тем же
   долгим всплытием, что и заголовок. */
.js .hero__in > .eyebrow, .js .hero__in > .lead, .js .hero__in > .hero__cta, .js .hero__in > .hero__note { opacity: 0; }
.loaded .hero__in > .eyebrow, .loaded .hero__in > .lead, .loaded .hero__in > .hero__cta, .loaded .hero__in > .hero__note {
  animation: floatUp 1.6s var(--ease-float) both;
}
.loaded .hero__in > .eyebrow { animation-delay: .05s; }
.loaded .hero__in > .lead { animation-delay: .48s; }
.loaded .hero__in > .hero__cta { animation-delay: .62s; }
.loaded .hero__in > .hero__note { animation-delay: .74s; }

@media (prefers-reduced-motion: reduce) {
  .js .ln__i,
  .js .hero__in > .eyebrow, .js .hero__in > .lead, .js .hero__in > .hero__cta, .js .hero__in > .hero__note { opacity: 1; animation: none; }
}

/* ── текст печатается на экране ─────────────────────────────────────────────
   Приёмы «Typewriter» и «Token stream» из серии «Text streaming»: заголовки
   набираются посимвольно, лиды приходят порциями слов — как ответ агента в
   кабинете. Скрипт (prepType в app.js) заранее прячет знаки в span.ch —
   место под текст занято с самого начала, и строки не пересчитываются во
   время печати; потом открывает их по одному. Каретка — span нулевой ширины,
   полоска нарисована поверх абсолютом, чтобы не двигать соседний текст. */
.js .tt .ch { visibility: hidden; }
.js .tt.tt--done .ch { visibility: visible; }
/* Печатается — значит уже видим: штатное всплытие этому блоку не нужно. */
.js .hero__in > .lead.tt { opacity: 1; animation: none; }

.tcaret { display: inline; position: relative; }
.tcaret::after {
  content: ""; position: absolute; left: .04em; bottom: -.05em;
  width: max(2px, .05em); height: 1.02em;
  background: currentColor;
}
.tcaret--blink::after { animation: caret 1.1s steps(1) infinite; }

@media (prefers-reduced-motion: reduce) {
  .js .tt .ch { visibility: visible; }
  .tcaret { display: none; }
}

/* ── шторка первой загрузки ─────────────────────────────────────────────────
   Полотно цвета чернил с орбитой логотипа по центру; когда страница готова
   (класс loaded), уезжает вверх той же длинной кривой — как у wellmade.studio.
   Без работающего скрипта шторки нет вовсе: некому было бы её поднять. */
.veil { display: none; }
.js .veil {
  display: grid; place-items: center;
  position: fixed; inset: 0; z-index: 300;
  background: var(--ink);
  transition: transform 1.2s var(--ease-float) .05s, visibility 0s 1.3s;
}
.loaded .veil { transform: translateY(-101%); visibility: hidden; }
.veil svg { width: 72px; height: auto; color: var(--bg); animation: veilSpin 1.5s linear infinite; }
@keyframes veilSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .js .veil { display: none; } }

/* ── макет окна кабинета ────────────────────────────────────────────────── */
/* Белая карточка с линией — так выглядит сам кабинет, никакого стекла. */

.win {
  border: 1px solid var(--line); border-radius: var(--r-xl); overflow: hidden;
  background: var(--card);
  box-shadow: var(--sh-2);
}
.win__bar {
  display: flex; align-items: center; gap: 8px;
  padding: 13px 16px; border-bottom: 1px solid var(--line); background: var(--bg);
}
/* Светофор окна — приглушённый, в земляных тонах бумаги. */
.dot { width: 10px; height: 10px; border-radius: 50%; background: var(--line2); flex: none; }
.dot--r { background: #c96f5f; } .dot--y { background: #cfa54e; } .dot--g { background: #7d9a5a; }
.win__title {
  margin-left: 10px; display: inline-flex; align-items: center; gap: 9px;
  font: 500 13px/1 var(--mono); letter-spacing: -.02em; color: var(--mute);
}
.win__title .mark-o { height: 15px; }
/* Иконка роли в заголовке окна — lucide-контур из набора кабинета. */
.win__title > svg {
  width: 15px; height: 15px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
/* Внутри рамки — настоящий кабинет: шапка, тред, композер. Как .shell
   в globals.css кабинета: колонка не шире 720px по центру, по бокам линии,
   на узком экране — во всю ширину. */
.win__body {
  display: flex; flex-direction: column; min-height: 380px;
  width: 100%; max-width: 720px; margin-inline: auto;
  border-left: 1px solid var(--line); border-right: 1px solid var(--line);
  background: var(--bg);
}
.win { background: var(--bg); }
@media (max-width: 900px) { .win__body { border-left: 0; border-right: 0; } }
/* ── шапка кабинета: бургер, пилюли модели и профиля, кнопки справа ─────── */
/* Один в один .topbar кабинета: грид auto 1fr auto. Имя другое, чтобы не
   путать с .top — шапкой самого лендинга. */
/* minmax(0, 1fr), а не 1fr: колонка по умолчанию не сжимается ниже своего
   содержимого, и на узком экране пара пилюль наезжала на бургер слева и на
   кнопки справа. Ноль в минимуме разрешает колонке отдать лишнее. */
.cabbar {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 10px;
  padding: 10px 12px 11px; border-bottom: 1px solid var(--line); background: var(--bg);
}
.cabbar > * { min-width: 0; }
.cluster { display: flex; align-items: center; gap: 4px; }
.pillrow { justify-self: center; display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; }
.icon-btn {
  width: 36px; height: 36px; flex: none; display: grid; place-items: center;
  border-radius: 50%; background: transparent; border: 1px solid var(--line); color: var(--ink);
}
.icon-btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.icon-btn.has-dot { position: relative; }
.icon-btn.has-dot::after {
  content: ""; position: absolute; top: 6px; right: 6px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--bg);
}
.modelpill {
  display: inline-flex; align-items: center; gap: 5px; padding: 5px 8px 5px 5px;
  border: 1px solid var(--line); border-radius: var(--r-pill);
  background: var(--card); color: var(--ink);
  font: 600 13px/1.2 var(--sans); min-width: 0;
}
.modelpill__glyph {
  width: 24px; height: 24px; flex: none; border-radius: 50%;
  background: var(--chip); border: 1px solid var(--line2);
  display: grid; place-items: center; color: var(--ink);
}
.modelpill__glyph svg { width: 13px; height: 13px; display: block; }
.modelpill__chev { color: var(--mute); flex: none; }
.modelpill__chev svg { width: 10px; height: 10px; display: block; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.profpill { padding: 6px 8px 6px 12px; min-width: 0; flex: 0 1 auto; }
.profpill__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* На телефоне место в шапке кончается: кнопки чуть мельче, отступы теснее.
   Всё остаётся на местах и нажимается — 32px это всё ещё уверенное попадание
   пальцем, а имя агента, если не влезло, подрезается многоточием. */
@media (max-width: 620px) {
  .cabbar { gap: 6px; padding: 9px 8px 10px; }
  .cluster { gap: 2px; }
  .icon-btn { width: 30px; height: 30px; }
  .icon-btn svg { width: 17px; height: 17px; }
  .modelpill { font-size: 12.5px; padding: 4px 6px 4px 4px; }
  .modelpill__glyph { width: 21px; height: 21px; }
  .modelpill__chev svg { width: 9px; height: 9px; }
  .profpill { padding: 5px 6px 5px 10px; }
  /* У пилюли модели галочку прячем: знак модели сам по себе кнопка, а
     освободившиеся полтора десятка пикселей дают имени агента влезть целиком
     вместо «Личный аге…». У пилюли агента галочка остаётся. */
  .modelpill:not(.profpill) { padding: 4px; }
  .modelpill:not(.profpill) .modelpill__chev { display: none; }
}

/* ── меню кабинета ──────────────────────────────────────────────────────── */
/* Кнопки шапки — настоящие: за каждой открывается список, как в кабинете.
   Сбрасываем то, что браузер навязывает кнопке, — остальное уже описано
   классами .icon-btn / .modelpill, они общие с декоративной версией. */
button.icon-btn, button.modelpill, button.field__btn, button.send {
  padding: 0; font: inherit; cursor: pointer;
  -webkit-appearance: none; appearance: none;
}
/* У .field__btn своей рамки нет — гасим ту, что браузер рисует кнопке сам. */
button.field__btn { border: 0; background: none; }
button.modelpill { padding: 5px 8px 5px 5px; }
button.profpill { padding: 6px 8px 6px 12px; }
@media (hover: hover) {
  button.icon-btn:hover, button.modelpill:hover { border-color: var(--line2); background: var(--chip); }
  button.field__btn:hover { color: var(--ink); }
}
button.icon-btn[aria-expanded="true"], button.modelpill[aria-expanded="true"] { border-color: var(--ink); }

/* Обёртка меню стоит между рядом и пилюлей: без min-width: 0 сжималась бы
   пилюля, а обёртка держала бы прежнюю ширину — и ряд всё равно наезжал бы
   на соседей. */
.pop-anchor { position: relative; display: inline-flex; min-width: 0; }
/* Список раскрывается внутри рамки окна: .win режет то, что вылезло наружу,
   и это правильно — меню принадлежит кабинету, а не странице. */
.pop {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 6;
  min-width: 190px; max-width: min(280px, 74vw); padding: 5px;
  max-height: 300px; overflow-y: auto; overscroll-behavior: contain;
  border: 1px solid var(--line2); border-radius: var(--r-md);
  background: var(--card); box-shadow: var(--sh-2);
  /* Появление — через свойство translate, а не transform: transform здесь
     занят центрированием, и анимация на нём сбивала бы замер положения. */
  animation: popIn .16s var(--ease) both;
}
@keyframes popIn { from { opacity: 0; translate: 0 6px; } }
.pop-anchor--mid .pop { left: 50%; transform: translateX(-50%); }
.pop-anchor--end .pop { left: auto; right: 0; }
.pop-anchor--up .pop { top: auto; bottom: calc(100% + 10px); }
.pop__hint {
  display: block; padding: 6px 9px 7px; font: 500 11.5px/1.3 var(--mono);
  letter-spacing: -.02em; color: var(--mute2);
}
.pop__i {
  display: flex; align-items: center; gap: 9px; width: 100%; padding: 8px 9px;
  border: 0; border-radius: 9px; background: transparent; cursor: pointer;
  font: 500 13.5px/1.25 var(--sans); letter-spacing: -.01em; color: var(--ink);
  text-align: left;
}
.pop__i:hover, .pop__i:focus-visible { background: var(--chip); }
.pop__i[aria-current="true"] { font-weight: 700; }
.pop__i svg { width: 15px; height: 15px; flex: none; }
.pop__dot { width: 9px; height: 9px; flex: none; border-radius: 50%; background: currentColor; }
.pop__note { margin-left: auto; font: 500 11.5px/1 var(--mono); color: var(--mute2); }

.thread { flex: 1; padding: 16px 16px 10px; display: flex; flex-direction: column; gap: 14px; }
/* Реплики — как в треде кабинета: своя — чернильный пузырь со срезанным
   уголком, ответ агента — просто текст во всю ширину, без пузыря и фона. */
.msg {
  max-width: 100%; min-width: 0; align-self: flex-start;
  font-size: 15px; line-height: 1.5; letter-spacing: -.005em; color: var(--ink);
  padding: 2px 0; overflow-wrap: anywhere;
}
.msg--me {
  align-self: flex-end; max-width: 86%; width: fit-content;
  background: var(--bubble-out); color: var(--bubble-out-fg);
  padding: 9px 13px; border-radius: 18px 18px 4px 18px;
}
.msg__who { font-weight: 700; }
/* Тире после имени — из CSS, чтобы реплика в разметке оставалась чистым
   текстом, как в настоящем треде. */
.msg__who::after { content: " —"; font-weight: 400; color: var(--ink); }
.who-teal { color: var(--teal); } .who-orange { color: var(--orange); }
.who-violet { color: var(--violet); } .who-blue { color: var(--blue); }
.who-green { color: var(--green); } .who-red { color: var(--red); }
/* Пометка под ответом — .msg__note кабинета. */
.msg small { display: block; margin-top: 8px; font-size: 12.5px; line-height: 1.45; color: var(--mute); }
/* Служебная строка в треде: «модель переключена», «чат создан». Не реплика —
   поэтому по центру, мелким моношрифтом, как системные пометки кабинета. */
.sysline {
  align-self: center; text-align: center; max-width: 90%;
  font: 500 12px/1.4 var(--mono); letter-spacing: -.02em; color: var(--mute2);
}

/* Разговор в первом окне набирается сам, когда доезжает до экрана: реплики
   приходят по очереди, как они приходили бы от шести агентов на самом деле.
   Скрываем только под классом от скрипта — без него окно просто заполнено. */
.js .win--seq .thread .msg { opacity: 0; transform: translateY(14px) scale(.985); }
.js .win--seq.win--play .thread .msg { animation: msgIn .55s var(--ease) forwards; }
.js .win--seq.win--play .thread .msg:nth-child(1) { animation-delay: .05s; }
.js .win--seq.win--play .thread .msg:nth-child(2) { animation-delay: .75s; }
.js .win--seq.win--play .thread .msg:nth-child(3) { animation-delay: 1.4s; }
.js .win--seq.win--play .thread .msg:nth-child(4) { animation-delay: 2.05s; }
.js .win--seq.win--play .thread .msg:nth-child(5) { animation-delay: 2.7s; }
@keyframes msgIn { to { opacity: 1; transform: none; } }
/* Индикатор «думает» — знак «Спутник» в роли спиннера: точка-агент кружит
   по орбите кольца-O, за ней короткий хвост. Геометрия та же, что у .mark-o
   в шапке. Живёт под последней пришедшей репликой и гаснет, когда разговор
   набран. */
.doing { display: none; align-items: center; gap: 9px; font-size: 13px; color: var(--mute); padding: 2px 0 4px; }
.js .win--seq .doing { display: flex; }
.js .win--seq.win--done .doing { display: none; }
.thinking { display: inline-flex; color: var(--mute2); }
.thinking svg { display: block; width: 18px; height: 16px; overflow: visible; }
.thinking__orb { transform-box: view-box; transform-origin: 52px 56px; animation: think-orbit 1.5s linear infinite -.12s; }
.thinking__orb--t { animation-delay: 0s; opacity: .35; }
@keyframes think-orbit { to { transform: rotate(360deg); } }

/* Композер — нижняя часть настоящего кабинета: лента навыков и поле ввода
   с отправкой. Здесь он декорация (aria-hidden), но собран из тех же классов
   и токенов, что в globals.css кабинета, — чтобы не врать картинкой. */
.composer { border-top: 1px solid var(--line); background: var(--bg); padding: 8px 12px 10px; min-width: 0; }
.skillbar { display: flex; gap: 6px; overflow: hidden; padding-bottom: 8px; }
.skill {
  display: inline-flex; align-items: center; gap: 6px; flex: none; white-space: nowrap;
  font: 500 12.5px/1 var(--sans); letter-spacing: -.01em; color: var(--ink2);
  background: var(--chip); border: 1px solid var(--line); border-radius: var(--r-pill);
  padding: 7px 12px;
}
.skill svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.skill--next { border-color: var(--ink); color: var(--ink); font-weight: 600; }
.skill--manage { padding: 7px 10px; color: var(--mute); }

/* ── живые окна: кнопки-реплики ─────────────────────────────────────────── */
/* Скрипт превращает чипы навыков в настоящие кнопки и добавляет панельным
   окнам блок вариантов ответа — демо, по которому можно кликать. */
button.skill { cursor: pointer; }
.skill--used { opacity: .4; pointer-events: none; }
.choices { border-top: 1px solid var(--line); background: var(--bg); padding: 10px 14px 12px; }
.choices__hint { display: block; font: 500 12px/1 var(--mono); letter-spacing: -.02em; color: var(--mute2); margin-bottom: 9px; }
.choices__row { display: flex; flex-wrap: wrap; gap: 6px; }
.choice {
  display: inline-flex; align-items: center; gap: 6px;
  font: 500 13px/1.35 var(--sans); letter-spacing: -.01em; color: var(--ink2);
  background: var(--chip); border: 1px solid var(--line); border-radius: var(--r-pill);
  padding: 8px 13px; cursor: pointer; text-align: left; text-decoration: none;
  transition: border-color .18s ease, color .18s ease, transform .18s var(--ease);
}
.choice--go { border-color: var(--ink); color: var(--ink); font-weight: 600; }
@media (hover: hover) {
  .choice:hover, button.skill:not(.skill--used):hover { border-color: var(--ink); color: var(--ink); }
  .choice:hover { transform: translateY(-1px); }
}
.choice:active { transform: translateY(0); }
/* Реплика, пришедшая от нажатия, въезжает как в настоящем треде. */
.msg--in { animation: msgIn .45s var(--ease) both; }
.doing--on { display: flex; }
@media (prefers-reduced-motion: reduce) { .msg--in { animation: none; } }
/* Чипы в hero скроллятся пальцем, раз по ним теперь можно попасть. */
.skillbar { overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.skillbar::-webkit-scrollbar { display: none; }
.field {
  display: flex; align-items: center; gap: 6px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-xl);
  padding: 5px 6px;
}
.field__btn { width: 34px; height: 34px; flex: none; display: grid; place-items: center; color: var(--mute); }
.field__btn svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
/* Поле настоящее: в него пишут и отправляют. Рамку подсвечиваем на фокусе —
   так же, как это делает композер кабинета. */
.field__in {
  flex: 1; min-width: 0; border: 0; background: transparent; color: var(--ink);
  font: 400 14.5px/1.35 var(--sans); letter-spacing: -.005em; padding: 6px 2px;
}
.field__in::placeholder { color: var(--mute); }
.field__in:focus { outline: none; }
.field:focus-within { border-color: var(--line2); }
/* Диктовка: пока «слушаем», микрофон горит и поле подписано об этом. */
.field--listen { border-color: var(--ink); }
.field--listen [data-act="mic"] { color: var(--ink); }
.field--listen .field__in::placeholder { color: var(--ink2); }
@keyframes caret { 50% { opacity: 0; } }
.send {
  width: 34px; height: 34px; flex: none; border-radius: 50%;
  display: grid; place-items: center; color: var(--accent-fg); background: var(--accent);
}
.send svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* Живая точка — как .live в кабинете: чернильная, мягко пульсирует. */
.pulse { width: 6px; height: 6px; border-radius: 50%; background: var(--ink); }
.pulse--live { animation: pulse 1.5s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: .3; } }
@media (prefers-reduced-motion: reduce) {
  .pulse--live, .thinking__orb, .pop { animation: none; }
  .js .win--seq .thread .msg { opacity: 1; transform: none; }
  .js .win--seq .doing { display: none; }
}

.hero__win { margin-top: clamp(40px, 6vw, 64px); }

/* ── полоса фактов ──────────────────────────────────────────────────────── */

.facts { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; }
.facts div {
  padding: 22px 20px; border-radius: var(--r-md); border: 1px solid var(--line);
  background: var(--card); box-shadow: var(--sh-1);
  transition: border-color var(--dur) var(--ease);
}
.facts div:hover { border-color: var(--line2); }
.facts b { display: block; font-size: 15px; font-weight: 700; letter-spacing: -.015em; }
.facts span { display: block; margin-top: 6px; font-size: 13.5px; color: var(--mute); line-height: 1.5; }
@media (max-width: 1000px) {
  .facts { grid-template-columns: repeat(2, 1fr); }
  /* Нечётный хвост: последний факт растягивается на обе колонки, чтобы не висел один. */
  .facts div:last-child:nth-child(odd) { grid-column: 1 / -1; }
}

/* ── лента моделей ──────────────────────────────────────────────────────── */
/* Имён больше, чем влезает в строку, а резать список по ширине экрана значит
   на телефоне показать три знака из десяти. Поэтому лента едет сама: дорожка —
   две одинаковые копии ряда, сдвиг ровно на половину и есть бесшовный цикл.
   Вторая копия скрыта от читалок экрана: для них список читается один раз. */

.ticker { padding-block: clamp(40px, 5vw, 64px); }
/* В герое лента идёт сразу за кнопками: свой нижний отступ ей не нужен —
   его задаёт margin-top у окна кабинета, иначе между ними зияет двойная пауза. */
.hero .ticker { padding-block: clamp(30px, 4vw, 46px) 0; }
.ticker__note {
  margin: 0; font-size: 14px; color: var(--mute); letter-spacing: -.005em;
}
/* Лента едет сама, но это обычный прокручиваемый ряд: её можно листать
   пальцем, колесом, перетаскиванием мышью и стрелками с клавиатуры — иначе
   имя, проехавшее мимо, не догнать. Скрипт двигает scrollLeft и умолкает,
   пока лентой заняты вы. */
.ticker__strip {
  overflow-x: auto; overflow-y: hidden; margin-top: 22px;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain; cursor: grab;
  /* Края растворяются в фоне: без этого знаки обрубаются ровной вертикалью
     и лента выглядит не едущей, а обрезанной. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.ticker__strip::-webkit-scrollbar { display: none; }
.ticker__strip:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; border-radius: 6px; }
.ticker__strip.is-drag { cursor: grabbing; user-select: none; }
.ticker__track { display: flex; width: max-content; }
.ticker__row { display: flex; align-items: center; }
.ticker__i {
  display: inline-flex; align-items: center; gap: 10px; padding: 0 clamp(18px, 2.4vw, 32px);
  font-size: 15.5px; font-weight: 600; letter-spacing: -.015em; white-space: nowrap;
  color: var(--mute); transition: color var(--dur) var(--ease);
}
.ticker__i:hover { color: var(--ink); }
.ticker__i svg { width: 19px; height: 19px; flex: none; }

/* ── табы ролей ─────────────────────────────────────────────────────────── */
/* Пилюли — как панель навыков в композере кабинета: плитка, линия, при выборе
   рамка перекрашивается в цвет агента. */

.tabs { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 42px; }
.tab {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 16px; border-radius: var(--r-pill); cursor: pointer;
  border: 1px solid var(--line); background: var(--chip); color: var(--ink2);
  font: 500 14px/1 var(--sans); letter-spacing: -.01em;
  transition: all var(--dur) var(--ease);
}
.tab:hover { border-color: var(--line2); color: var(--ink); }
.tab:active { transform: scale(.97); }
/* Значки ролей — lucide-контуры из набора иконок кабинета, не «лица». */
.tab svg {
  width: 16px; height: 16px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .55; transition: opacity var(--dur);
}
.tab[aria-selected="true"] {
  color: var(--ink); background: var(--card); border-color: currentColor;
  font-weight: 600; box-shadow: var(--sh-1);
}
.tab[aria-selected="true"] svg { opacity: 1; }
.tab--teal[aria-selected="true"] { color: var(--teal); }
.tab--orange[aria-selected="true"] { color: var(--orange); }
.tab--violet[aria-selected="true"] { color: var(--violet); }
.tab--blue[aria-selected="true"] { color: var(--blue); }
.tab--green[aria-selected="true"] { color: var(--green); }
.tab--red[aria-selected="true"] { color: var(--red); }

/* На телефоне шесть пилюль занимают три строки и отжимают содержимое вниз.
   Лента с прокруткой вбок — тот же жест, что и в самом кабинете. */
@media (max-width: 700px) {
  .tabs {
    flex-wrap: nowrap; overflow-x: auto; justify-content: flex-start;
    margin-inline: calc(var(--pad) * -1); padding-inline: var(--pad); padding-block: 2px;
    scrollbar-width: none; scroll-snap-type: x proximity;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tab { flex: none; scroll-snap-align: start; }
}

/* Панели разной высоты: без запаса страница подпрыгивает под курсором при
   переключении вкладки. Запас по самой высокой. */
.panels { margin-top: 36px; }
@media (min-width: 901px) { .panels { min-height: 430px; } }
.panel { display: grid; grid-template-columns: 1fr 1.12fr; gap: clamp(24px, 4vw, 56px); align-items: center; }
.panel[hidden] { display: none; }
.panel__text h3 { margin-bottom: 14px; }
.panel__text p { color: var(--mute); margin: 0 0 18px; letter-spacing: -.008em; }
.panel__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.panel__list li { position: relative; padding-left: 24px; color: var(--ink2); font-size: 15px; line-height: 1.5; }
.panel__list li::before {
  content: ""; position: absolute; left: 3px; top: .58em; width: 7px; height: 7px;
  border-radius: 2px; background: var(--mute2);
}
/* Панель не просто появляется, а въезжает: переключение читается как смена
   экрана, а не как подмена текста. Текст и макет — с разной задержкой. */
.panel:not([hidden]) > * { animation: panelIn .5s var(--ease) both; }
.panel:not([hidden]) > *:nth-child(2) { animation-delay: .08s; }
.panel:not([hidden]) .panel__list li { animation: fadeUp .5s var(--ease) both; }
.panel:not([hidden]) .panel__list li:nth-child(1) { animation-delay: .12s; }
.panel:not([hidden]) .panel__list li:nth-child(2) { animation-delay: .18s; }
.panel:not([hidden]) .panel__list li:nth-child(3) { animation-delay: .24s; }
.panel:not([hidden]) .panel__list li:nth-child(4) { animation-delay: .3s; }
@keyframes panelIn { from { opacity: 0; transform: translateY(14px); } }
@media (prefers-reduced-motion: reduce) {
  .panel:not([hidden]) > *, .panel:not([hidden]) .panel__list li { animation: none; }
}
@media (max-width: 900px) { .panel { grid-template-columns: 1fr; } }

/* ── галерея работ ──────────────────────────────────────────────────────── */

.gal { margin-top: 48px; display: grid; grid-template-columns: repeat(12, 1fr); gap: 12px; }
.shot {
  position: relative; overflow: hidden; border-radius: var(--r-lg);
  border: 1px solid var(--line); background: var(--paper);
  grid-column: span 4; aspect-ratio: 16 / 9;
  transition: box-shadow .35s var(--ease), border-color var(--dur);
}
.shot:hover { border-color: var(--line2); box-shadow: var(--sh-2); }
.shot img, .shot video {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .8s var(--ease);
}
.shot:hover img, .shot:hover video { transform: scale(1.04); }
/* У некоторых работ подпись нарисована внизу самой картинки: кадрируем
   выше, иначе две надписи налезают друг на друга. */
.shot--top img { object-position: 50% 18%; }
.shot--wide { grid-column: span 6; }
.shot--tall { grid-column: span 3; aspect-ratio: 3 / 4; }
.shot--half { grid-column: span 6; }
/* На широком экране в первом ряду рядом стоят широкая карточка и две
   вертикальные: пропорция широкой дала бы низ ряда «лесенкой». Отдаём её
   высоту ряду — вертикали задают, широкая дотягивается. На узких экранах
   соседей нет и пропорция снова нужна: без неё карточка схлопнется в ноль. */
@media (min-width: 901px) { .shot--wide { aspect-ratio: auto; } }
/* Подпись на медиа всегда по тёмному: она лежит на фотографии, а не на фоне
   страницы, и от темы не зависит. */
.shot__cap {
  position: absolute; inset: auto 0 0; padding: 52px 16px 14px;
  background: linear-gradient(transparent, rgba(10, 9, 7, .6) 38%, rgba(10, 9, 7, .94));
  font-size: 13px; line-height: 1.45; color: rgba(250, 249, 246, .95);
  letter-spacing: -.005em;
}
/* Светлые кадры: тёмная заливка съела бы у них весь низ. Подложку кладём
   светлую, текст — тёмный; читается так же, картинка остаётся воздушной. */
.shot--light .shot__cap {
  background: linear-gradient(transparent, rgba(250, 249, 246, .74) 34%, rgba(250, 249, 246, .97));
  color: rgba(12, 12, 12, .92);
}
.shot--light .shot__cap i { color: rgba(12, 12, 12, .5); }
.shot__cap i {
  display: block; font-style: normal; color: rgba(250, 249, 246, .55);
  font: 400 11.5px/1.4 var(--mono); letter-spacing: -.01em; margin-top: 6px;
}
.shot__badge {
  position: absolute; top: 12px; left: 12px; padding: 5px 10px; border-radius: var(--r-pill);
  background: rgba(10, 9, 7, .62); backdrop-filter: blur(8px);
  border: 1px solid rgba(250, 249, 246, .22); font: 500 10.5px/1 var(--mono);
  letter-spacing: .06em; text-transform: uppercase; color: rgba(250, 249, 246, .85);
}
/* Браузер отказал в автозапуске (энергосбережение на айфоне, экономия
   трафика) — вместо молчащего постера показываем кнопку: ролик ждёт касания.
   Рисуем её на псевдоэлементе карточки, чтобы клик доставался самому video. */
.shot.is-blocked, .appwin.is-blocked { position: relative; }
.shot.is-blocked::after, .appwin.is-blocked::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 62px; height: 62px;
  transform: translate(-50%, -50%); border-radius: 50%; pointer-events: none;
  background: rgba(10, 9, 7, .58) no-repeat center/20px 22px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 22'%3E%3Cpath d='M2 1.6 18 11 2 20.4Z' fill='%23faf9f6'/%3E%3C/svg%3E");
  border: 1px solid rgba(250, 249, 246, .28); backdrop-filter: blur(8px);
}
/* У окон приложений заголовок и подпись лежат над и под роликом, а не поверх:
   центр карточки ниже центра видео. Раскладываем окно в одну колонку сеткой и
   кладём кнопку в ту же ячейку, что и ролик, — тогда она ровно по его центру.
   На поток это не влияет: три блока в одной колонке стоят как стояли.
   Место закрепляем за каждой частью явно — и строку, и колонку: у
   псевдоэлемента место указано, а такие раскладываются раньше прочих. Без
   этого он занял бы первую ячейку, а ролик уехал бы в соседнюю. */
.appwin { display: grid; grid-template-columns: 1fr; grid-template-rows: auto auto auto; }
.appwin .win__bar { grid-area: 1 / 1; }
.appwin video { grid-area: 2 / 1; }
.appwin .appwin__cap { grid-area: 3 / 1; }
.appwin.is-blocked::after { position: static; grid-area: 2 / 1; place-self: center; transform: none; }

@media (max-width: 900px) {
  .gal { grid-template-columns: repeat(6, 1fr); }
  .shot, .shot--wide, .shot--half, .shot--tall { grid-column: span 3; }
}
@media (max-width: 560px) {
  .shot, .shot--wide, .shot--half, .shot--tall { grid-column: span 6; }
  .shot--tall { aspect-ratio: 4 / 5; }
}

/* ── карточки ───────────────────────────────────────────────────────────── */

.cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-top: 48px; }
.cards--2 { grid-template-columns: repeat(2, 1fr); }
.card {
  border: 1px solid var(--line); border-radius: var(--r-lg); padding: 26px;
  background: var(--card); box-shadow: var(--sh-1);
  transition: border-color var(--dur) var(--ease), box-shadow .3s;
  position: relative; overflow: hidden;
}
/* Пятно, идущее за курсором, — графитовое и едва заметное: тот же приём,
   что дымка у скроллов кабинета (rgba от --glow). Координаты ставит скрипт
   в --mx/--my; без него пятно стоит по центру верхней грани. */
.card::before {
  content: ""; position: absolute; inset: -1px; opacity: 0; pointer-events: none;
  background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 0%), rgba(var(--glow), .05), transparent 70%);
  transition: opacity .35s;
}
.card:hover { border-color: var(--line2); box-shadow: var(--sh-2); }
.card:hover::before { opacity: 1; }
.card > * { position: relative; }
.card h3 { font-size: 1.14rem; margin-bottom: 10px; }
.card p { margin: 0; color: var(--mute); font-size: 14.5px; line-height: 1.58; letter-spacing: -.005em; }
.card__ico {
  width: 40px; height: 40px; border-radius: var(--r-sm); margin-bottom: 18px;
  display: grid; place-items: center;
  background: var(--chip); border: 1px solid var(--line); color: var(--ink);
  transition: background var(--dur) var(--ease);
}
.card:hover .card__ico { background: var(--paper); }
.card__ico svg { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 1.6; }
@media (max-width: 900px) { .cards, .cards--2 { grid-template-columns: 1fr; } }

.price-note { font-size: 14px; color: var(--mute2); margin-top: 22px; line-height: 1.6; }
.price-note b { color: var(--ink2); }

/* ── строки-возможности ─────────────────────────────────────────────────── */

.rows { margin-top: 48px; border-top: 1px solid var(--line); }
.row {
  display: grid; grid-template-columns: 230px 1fr auto; gap: 22px; align-items: baseline;
  padding: 21px 14px; border-bottom: 1px solid var(--line);
  margin-inline: -14px; border-radius: var(--r-sm);
  transition: background var(--dur), padding-left .25s var(--ease);
}
.row:hover { background: var(--chip); padding-left: 20px; }
.row b { font-weight: 700; letter-spacing: -.018em; font-size: 16px; }
.row span { color: var(--mute); font-size: 15px; letter-spacing: -.005em; }
.row em { font-style: normal; color: var(--mute2); font: 400 12.5px/1.4 var(--mono); letter-spacing: -.01em; white-space: nowrap; }
@media (max-width: 800px) {
  .row { grid-template-columns: 1fr; gap: 7px; }
  .row:hover { padding-left: 14px; }
  .row em { white-space: normal; }
}

/* ── честный блок ───────────────────────────────────────────────────────── */

.honest { background: var(--paper); border-block: 1px solid var(--line); }
.honest .card { background: var(--card); }

/* ── финал ──────────────────────────────────────────────────────────────── */

.final { overflow: hidden; }
.final__glow { display: none; }
.final h2 { font-size: clamp(2.1rem, 6vw, 3.7rem); }

/* ── подвал ─────────────────────────────────────────────────────────────── */

footer { border-top: 1px solid var(--line); padding-block: 44px 56px; color: var(--mute2); font-size: 13.5px; }
.foot { display: flex; flex-wrap: wrap; gap: 28px; justify-content: space-between; align-items: flex-start; }
.foot__links { display: flex; flex-wrap: wrap; gap: 22px; }
.foot a { color: var(--mute); text-decoration: none; transition: color var(--dur); }
.foot a:hover { color: var(--ink); }
.foot__legal { max-width: 62ch; line-height: 1.6; }

/* ── появление при прокрутке ────────────────────────────────────────────── */

/* Прячем только когда скрипт жив (класс js ставит он же в <head>): иначе
   сломанный или заблокированный JS оставил бы от страницы один заголовок.
   Ход и темп — wellmade.studio: 70px пути и почти две секунды длинного
   хвоста; непрозрачность догоняет раньше, чем блок доезжает. */
.js .rise { opacity: 0; transform: translateY(70px); transition: opacity 1.1s ease, transform 1.8s var(--ease-float); }
.js .rise--in { opacity: 1; transform: none; }
/* Ряд карточек проявляется не разом, а по одной: глазу есть за чем идти. */
.js .stagger { opacity: 1; transform: none; }
.js .stagger > * { opacity: 0; transform: translateY(52px); transition: opacity 1s ease, transform 1.6s var(--ease-float); }
.js .stagger.rise--in > * { opacity: 1; transform: none; }
.js .stagger.rise--in > *:nth-child(2) { transition-delay: .1s; }
.js .stagger.rise--in > *:nth-child(3) { transition-delay: .2s; }
.js .stagger.rise--in > *:nth-child(4) { transition-delay: .3s; }
.js .stagger.rise--in > *:nth-child(5) { transition-delay: .4s; }
.js .stagger.rise--in > *:nth-child(6) { transition-delay: .5s; }
.js .stagger.rise--in > *:nth-child(7) { transition-delay: .6s; }
.js .stagger.rise--in > *:nth-child(8) { transition-delay: .7s; }
@media (prefers-reduced-motion: reduce) {
  .js .rise, .js .stagger > * { opacity: 1; transform: none; transition: none; }
}

/* ── полоса моделей ─────────────────────────────────────────────────────── */
/* Каталог нейросетей агента — через ТокенСток. Число живёт отдельной цифрой:
   оно и есть аргумент. Точного счёта не пишем — каталог растёт каждую неделю. */
.card--models { display: grid; grid-template-columns: auto 1fr; gap: clamp(20px, 3vw, 34px); align-items: start; margin-top: 16px; }
@media (max-width: 700px) { .card--models { grid-template-columns: 1fr; } }
.models__stat { text-align: center; padding-top: 4px; }
.models__stat b { display: block; font-size: clamp(46px, 6vw, 66px); font-weight: 800; letter-spacing: -.04em; line-height: 1; }
.models__stat span { font: 500 11.5px/1.4 var(--mono); color: var(--mute); letter-spacing: .06em; text-transform: uppercase; }
.card--models p a { color: inherit; }
.models__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 16px; }
.models__tags span {
  font: 500 12.5px/1 var(--sans); letter-spacing: -.01em; color: var(--ink2);
  background: var(--chip); border: 1px solid var(--line); border-radius: var(--r-pill);
  padding: 7px 12px;
}

/* ── окна с сайтами и играми ────────────────────────────────────────────── */
/* Ролики сняты с настоящих приложений этой же машины и играют в рамке окна
   кабинета. preload="none": за экраном ролик не качается, играют только
   видимые (см. app.js, «ролики»). */
.appgrid { margin-top: 44px; display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 900px) { .appgrid { grid-template-columns: 1fr; } }
.appwin { margin: 0; }
.appwin video { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; background: var(--chip); }
.appwin__cap {
  padding: 12px 16px 14px; border-top: 1px solid var(--line);
  font-size: 13px; line-height: 1.5; color: var(--ink2); letter-spacing: -.005em;
}
.appwin__cap i {
  display: block; font-style: normal; color: var(--mute);
  font: 400 11.5px/1.4 var(--mono); letter-spacing: -.01em; margin-top: 6px;
}
/* У опубликованных сайтов в заголовке окна — их настоящий адрес, ссылкой. */
.appwin .win__title a { color: inherit; text-decoration: none; }
.appwin .win__title a:hover { color: var(--ink); text-decoration: underline; }

/* ── окно заявки на альфа-тест ──────────────────────────────────────────── */
/* Кнопка «Создать компьютер» открывает не регистрацию, а форму: доступ дают
   вручную. Окно — родной <dialog>, поэтому в разметке нет ни подложки, ни
   ловушки фокуса: браузер делает и то и другое сам, и делает это правильнее.
   Оформление — карточка кабинета: бумага, линия, скругление 24. */

.req {
  width: min(100%, 480px);
  max-height: calc(100dvh - 36px);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  overflow: visible;
}
/* Подложка тёплая, а не чёрная: страница за ней — бумага, и серый провал
   выглядел бы чужой деталью из другого интерфейса. */
.req::backdrop { background: rgba(12, 12, 12, .55); backdrop-filter: blur(3px); }
:root[data-theme="dark"] .req::backdrop,
:root:not([data-theme="light"]) .req::backdrop { background: rgba(4, 4, 3, .68); }

.req__in {
  display: grid;
  gap: 14px;
  padding: clamp(22px, 4.5vw, 32px);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-3);
  font: 400 15px/1.55 var(--sans);
}
/* Собственный display перебивает встроенное правило браузера для [hidden] —
   без этой строки «Заявка принята» видна рядом с формой ещё до отправки. */
.req__in[hidden] { display: none; }
.req[open] .req__in { animation: reqIn .34s var(--ease-float) both; }
@keyframes reqIn { from { opacity: 0; transform: translateY(14px) scale(.985); } }

.req h3 { font-size: clamp(1.14rem, 2.2vw, 1.32rem); }
.req__note { margin: -2px 0 4px; font-size: 14px; color: var(--mute); letter-spacing: -.005em; }

/* Крестик поверх карточки, а не внутри сетки: иначе он занимал бы строку и
   отодвигал заголовок. */
.req__x {
  position: absolute; top: 14px; right: 14px; z-index: 2;
  width: 34px; height: 34px; display: grid; place-items: center;
  border: 0; border-radius: 50%; background: transparent; color: var(--mute);
  cursor: pointer; transition: all var(--dur) var(--ease);
}
.req__x svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; }
.req__x:hover { background: var(--chip); color: var(--ink); }

.req__f { display: grid; gap: 6px; }
.req__l {
  font: 500 11px/1.4 var(--mono); letter-spacing: .07em; text-transform: uppercase;
  color: var(--mute);
}
.req__l b { font-weight: 500; color: var(--mute2); }
.req__i {
  width: 100%; box-sizing: border-box;
  padding: 12px 14px;
  border: 1px solid var(--line2); border-radius: var(--r-md);
  background: var(--bg); color: var(--ink);
  font: 500 15px/1.4 var(--sans); letter-spacing: -.01em;
  transition: border-color var(--dur) var(--ease);
}
.req__i::placeholder { color: var(--mute2); font-weight: 400; }
.req__i:focus { outline: none; border-color: var(--accent); }
/* :user-invalid, а не :invalid: подсвечивать пустое поле, к которому человек
   ещё не притрагивался, — значит ругаться на него до разговора. */
.req__i:user-invalid { border-color: var(--danger); }
.req__t { resize: vertical; min-height: 88px; }

.req__foot { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 4px; }
.req__foot .btn { flex: none; }
.req__foot .btn[disabled] { opacity: .55; cursor: default; }
.req__status { margin: 0; font-size: 13.5px; line-height: 1.4; color: var(--mute); }
.req__status--bad { color: var(--danger); }

@media (prefers-reduced-motion: reduce) {
  .req[open] .req__in { animation: none; }
  .req__x, .req__i { transition: none; }
}
