/* ============================================================
   МОСТ ТОКЕНОВ — ALCHEMY
   Anna Gorodetskaya — Portfolio · 13 сент 2026

   Рукописный файл, никогда не перегенерируется (тот же статус,
   что у _alchemy-fontface.css, — site/tools/split-alchemy-css.mjs
   его не трогает). Страничный CSS, написанный для другой темы
   (первым сюда встаёт case-jelly.css — вёрстка кейса уровня A
   переезжает на alchemy как есть), читает собственные имена
   токенов Анны: --ink-80, --g-hero, --rule и так далее.
   skin-alchemy.css сгенерирован сплиттером из чужого референса и
   знает только свои имена (--ink, --pink, --hot, --lime, --line,
   --gutter). Из 25 токенов, которые читает case-jelly.css,
   skin-alchemy.css объявляет только --ink — без этого моста
   остальные 24 падают на тёмный редакторский дефолт base.css, и
   кейс перекрашивается в чужую тему вместо alchemy.

   Ничего here не изобретается заново: каждое значение читано с
   уже существующих поверхностей темы — либо это готовый токен
   skin-alchemy.css, либо цвет/тень реальной карточки в
   site/css/home-alchemy.css. Источник назван в комментарии к
   каждой строке.

   Подключается в _head-alchemy.html после skin-alchemy.css и до
   {{pageCss}} — тогда любой файл, написанный для другой темы,
   каскадит поверх уже готового моста и получает alchemy-палитру,
   а не редакторский дефолт.
   ============================================================ */

:root {
  /* --- грунт страницы. Не входит в список 25 токенов case-jelly.css
     (сам файл --ground не читает), но найден при проверке в браузере:
     base.css §10 красит "шторку" кроп-реванного появления
     (.jcase .media{overflow:visible} у case-jelly.css снимает клип,
     и не до конца доигравшая translateY(-101%) "шторка" остаётся
     видна поверх кадра) через var(--shutter, var(--ground)) — без
     этой строки она красится в редакторский дефолт base.css
     (#F4F3F0, тёплый белый) и торчит светлым прямоугольником над
     ведущим кадром на тёмном грунте. У jelly та же утечка есть, но
     не видна: там --ground сама розовая и совпадает с грунтом
     страницы. skin-alchemy.css красит body напрямую хардкодом
     (#11140f), а не через --ground — здесь тот же хардкод как
     переменная, один источник. */
  --ground: #11140f;

  /* --- лесенка чернил ---
     jelly сама нигде не хранит формулу — её ink-80/55/30/12 это
     четыре готовых hex поверх её же грунта. Замерено, какую долю
     --ink несёт каждая ступень относительно её --ground (пропорция
     по трём каналам, округлено): ink-80 ≈ 90%, ink-55 ≈ 79%,
     ink-30 ≈ 52%, ink-12 ≈ 15%. Те же пропорции здесь применены к
     паре ink/ground alchemy через color-mix — формула живая, а не
     замороженный снимок, и переживёт правку --ink без пересчёта. */
  --ink-80: color-mix(in srgb, var(--ink) 88%, #11140f);
  --ink-55: color-mix(in srgb, var(--ink) 72%, #11140f);
  --ink-30: color-mix(in srgb, var(--ink) 48%, #11140f);
  --ink-12: color-mix(in srgb, var(--ink) 16%, #11140f);

  /* --- акцент и линия: переиспользуем то, что уже объявлено
         сплиттером в skin-alchemy.css, а не подбираем новый цвет --- */
  --accent: var(--hot);     /* skin-alchemy.css :root — охра #c7af82, тот же тон, что у кнопок и фамильяров */
  --rule:   var(--line);    /* skin-alchemy.css :root — хэйрлайн #e7f6cc24, уже снят с референса */
  --margin: var(--gutter);  /* skin-alchemy.css :root — тот же clamp(24px,4.4vw,84px), что jelly держит в --margin жёстко */

  /* --- текстовые шрифты темы. Три токена, а не один: case-jelly.css
     и base.css (.t-deck, .t-meta/.t-micro/.t-num/.tag/.award через
     классы t-meta и т.п. в разметке кейса) читают --font-display,
     --font-text и --font-meta по отдельности, но ни skin-alchemy.css,
     ни type-6-manrope-oxanium.css не объявляют ни один из трёх —
     они просто ставят текстовые правила голыми селекторами
     (body, h1/h2/h3, em). Без моста все три падали на дефолт
     base.css: --font-display на var(--serif) (по ошибке — Oxanium,
     акцентный шрифт em, а не текст), --font-text и --font-meta на
     system-ui/ui-monospace редакторской темы. В референсе Oxanium
     несёт только em (type-6-manrope-oxanium.css: h1{font-weight:550},
     h1,h2,h3{font-weight:500} — сами заголовки наследуют body,
     то есть Manrope; единственное правило с Oxanium — селектор
     em, h1 em, h2 em, .service h3 em, .studio-hero h1 em,
     .contact-section h2 em, .intro-copy>p em). Все три текстовых
     токена — та же пара Manrope/Arial, что уже держит body и <p>
     в skin-alchemy.css :root (--sans). Акцент на em это не трогает:
     тот селектор прописывает Oxanium литералом, а не через
     --font-display. */
  --font-display: var(--sans); /* было var(--serif) — заголовки уходили в Oxanium целиком, чего нет в референсе */
  --font-text:    var(--sans); /* новый токен — .jcase .case__sub/.case__one (класс t-deck) падали на system-ui base.css */
  --font-meta:    var(--sans); /* новый токен — .jcase__tier/.jcase__counter/.jcase__back/.jcase__tags/.jcontact .t-meta (класс t-meta) падали на ui-monospace base.css */

  /* --- трекинг меты. Тот же класс t-meta без этого токена держал
     трекинг 0.05em — дефолт base.css, а не голос темы: у alchemy
     есть собственный аналог этой роли, .eyebrow (используется на
     главной для role/location и номеров секций), и там разрядка
     буквально 0.13em (type-6-manrope-oxanium.css). Значение то же,
     что jelly держит в --ls-meta своего type-5 — не совпадение,
     а общий рисунок «мета = капс + широкий трекинг» у обеих тем. */
  --ls-meta: 0.13em; /* type-6-manrope-oxanium.css .eyebrow — тот же трекинг, что у мета-роли темы */

  /* --- грунты четырёх секций кейса. Три взяты буквально с
         поверхностей референса; четвёртый в референсе отдельно не
         назван — выведен из его же «faint tint», это мой выбор,
         а не считанное значение (см. отчёт). --- */
  --g-hero:  linear-gradient(112deg, #242e1d, #1d2619 72%, #293720); /* .intro, home-alchemy.css — самый светлый и текстурный грунт для обложки */
  --g-work:  #141811;                                                /* .work-section, home-alchemy.css — тот же смысл секции, что jelly вкладывает в --g-work */
  --g-about: #10170f;                                                 /* .about-section, home-alchemy.css — тот же смысл, что --g-about у jelly */
  --g-quiet: color-mix(in srgb, #d3eea5 5%, #11140f);                 /* мой выбор: лёгкий подъём тона из «faint tint» .button.outline:hover (#d3eea50a) над грунтом — отдельного четвёртого грунта референс не даёт */

  /* --- g-intro — добавлено 13.09.2026 для pagesCss (About/CV/Contact/
     Impressum/Privacy, pages-jelly.css). У jelly это отдельный, седьмой
     по счёту грунт (skin-jelly.css: --g-intro — розовый градиент,
     не равный ни --g-hero, ни --g-work). У alchemy своей страницы,
     откуда снять седьмой самостоятельный литерал, ещё нет: домашняя
     home-alchemy.css знает только четыре секции — .intro/.work-section/
     .about-section/.services-section — и все четыре уже разобраны
     по --g-hero/--g-work/--g-about/--g-services выше, ни одной пятой
     не осталось. Выдумывать новый hex значило бы нарушить «бери из
     палитры эталона, а не изобретай».

     Роль нужна одна конкретная: фон ЧИТАЮЩЕГО тела страницы — большая
     плоская площадь под мелким текстом, а не текстурная обложка и не
     подчёркнуто самая тёмная плашка. --g-hero занят обложками (cover/
     hero везде), --g-about уже держит соседнюю секцию на этой же
     странице (About: .jabout-proof, прямо под телом) — переиспользовать
     его для тела значило бы слить два соседних блока в одно пятно.
     --g-work никем из пяти статических страниц не занят и по смыслу
     ровно то же самое, чем был в доме: ровная тихая плоскость средней
     тёмности, без текстуры и без претензии быть самой глухой точкой
     макета. Тот же приём уже есть в этом файле десятью строками ниже —
     --ground-alt: var(--g-work) — второй токен на то же значение,
     когда роли не пересекаются на одной странице. */
  --g-intro: var(--g-work);

  /* --- g-services — добавлено 13.09.2026 для страниц направлений
     (/for/<slug>/). У jelly это пятый именованный грунт из того же
     семейства (--g-hero → --g-work → --g-services → --g-about →
     --g-quiet), которого раньше в этом списке не было: он нужен
     только офферам (.ps-offers), а до practice-alchemy-tune.css
     здесь не было ни одной страницы, которая их печатает. Источник —
     .services-section, home-alchemy.css (та же секция «offers» темы,
     просто другое имя разметки), а не выдуманный цвет. */
  --g-services: linear-gradient(125deg, #252127, #1d1a20 70%, #302534); /* .services-section, home-alchemy.css */

  /* --- ground-alt — вторая плоскость грунта, читает её home.css
     (.work, .card, .card__frame, .card__plate) как более тёмный/
     светлый сосед --ground для карточек без загруженной картинки.
     base.css объявляет дефолт (#EAE8E4, тёплый бежевый редакторской
     темы) — на alchemy это читалось бы светлым пятном на тёмной
     карточке. var(--g-work) уже держит то же значение (#141811,
     .work-section), которое на alchemy и есть вторая плоскость
     грунта — переопределяем на неё, а не изобретаем третий цвет. */
  --ground-alt: var(--g-work);

  /* --- поверхности карточек: тень и радиус сняты с настоящих
         карточек темы (.project-card / .service, home-alchemy.css),
         а не с розовой тени jelly --- */
  --r-card:     20px;                          /* .project-card и .service — оба 20px (home-alchemy.css) */
  --sheen:      inset 0 1px 1px #ffffff14;      /* .service, состояние покоя (home-alchemy.css) */
  --lift:       0 12px 28px rgba(0, 0, 0, 0.2); /* .project-card, состояние покоя, #0003 развёрнут (home-alchemy.css) */
  --lift-hover: 0 20px 35px rgba(0, 0, 0, 0.4); /* .project-card:hover, #0006 развёрнут (home-alchemy.css) */

  /* --- g-card — добавлено 13.09.2026 для карточек стены на странице
     направления (.wl__card, wallCardsLight()). home-alchemy.css уже
     решает точно эту задачу для .project-card: пять цветных jelly-
     ротаций (розовый/лиловый/т.д., унаследованные от референса)
     переопределены ОДНИМ тёмным градиентом на все карточки без
     исключения (см. home-alchemy.css, правило после «.project-card,
     .project-card:nth-child(5n+2)…{background:...}» — литерал взят
     оттуда дословно, это не новый цвет). practice-alchemy-tune.css
     делает то же самое для .wl__card через этот токен — один
     источник вместо двух литералов в двух файлах. */
  --g-card: linear-gradient(145deg, #252c20, #1a2016);
}

/* --- Оставлено на дефолте base.css, без переопределения ---
   --dur-mid     — такого токена нет даже у jelly: обе темы всегда
                   идут через инлайн-фолбэк var(--dur-mid, 0.35s)
                   прямо в case-jelly.css, определять его здесь
                   нечем и незачем.
   --ease-out    — общая грамматика движения всего проекта
                   (design/system/base.css), ни одна тема её не
                   трогает, jelly в том числе.
   --s-1/-2/-3   — шкала отступов, общая для всего сайта.
   --practice-ai — цвет практики «AI & Automation» — это метка
                   таксономии, а не тема; jelly тоже её не красит.

   --frame-pad и --r в списке не участвуют вовсе: case-jelly.css
   назначает их сам локально (.jcase{--frame-pad:22px} и
   .jcase .ar-NN{--r:...}), в :root они не читаются — мосту тут
   нечего наводить.
   ============================================================ */

/* ============================================================
   ПОДАВЛЕНИЕ ЗАВИСШЕЙ КРОП-ШТОРКИ — общее для всех alchemy-страниц.
   Anna Gorodetskaya — Portfolio · 13 сент 2026

   base.css §6 рисует шторку раскрытия [data-m="crop"]::after
   (background: var(--shutter, var(--ground))) и рассчитывает, что
   overflow:hidden на самом [data-m="crop"] обрежет её после того,
   как .is-in уводит transform в translateY(-101%) — шторка должна
   уехать ЗА рамку и исчезнуть под клипом. Но case-jelly.css:141
   переопределяет .jcase .media{overflow:visible} (это нужно, чтобы
   подпись media__label, стоящая ниже рамки на top:calc(100% + 12px),
   не резалась) — и та же снятая обрезка держит уехавшую шторку на
   весу: прямоугольник высотой в кадр повисает НАД тем, что ниже
   рамки, а не исчезает.

   На jelly это не видно случайно: --shutter нигде не объявлен,
   шторка красится в --ground, а --ground у jelly (#F6C6DE) совпадает
   с розовым грунтом обложки — розовое на розовом. На alchemy --ground
   тёмный (см. :root выше, #11140f), и та же утечка читается сплошным
   чёрным блоком поверх текста.

   Раньше правило было прибито частным случаем в
   site/css/case-alchemy-tune.css (только обложка кейса A,
   .jcase .case__hero.is-in::after) — как только briefCss/practiceCss
   тоже подключат case-jelly.css/practice-jelly.css, тот же чёрный
   блок вылез бы там снова. Здесь — один источник для всех: этот файл
   грузится на КАЖДОЙ странице темы (см. systemCss в THEMES.alchemy,
   site/build.mjs), поэтому подавление достаточно объявить один раз.

   Резать через overflow/clip-path на самом контейнере нельзя — это
   заодно обрежет то, что намеренно вынесено за рамку (подпись и
   т.п.). Поэтому шторка просто снимается с рендера, как только
   раскрытие уже отработало: правило целится в состояние ПОСЛЕ
   .is-in и не трогает состояние ДО (шторка остаётся на месте кадра,
   закрывая его, пока класс не появился, — жест раскрытия не ломается).

   Специфичность: [data-m="crop"].is-in::after — атрибут (0,1,0) +
   класс (0,1,0) + псевдоэлемент (0,0,1) = (0,2,1), выше базового
   правила транзишна и фона (0,1,1) у base.css. Порядок подключения
   в <head> роли не играет — бридж и так стоит раньше {{pageCss}},
   но даже встань он позже, специфичность решила бы сама. Проверено
   в браузере (см. отчёт агента, 13.09.2026): до .is-in шторка на
   месте (кадр закрыт), исчезает только после раскрытия. */
[data-m="crop"].is-in::after,
[data-m="crop-x"].is-in::after { content: none; }

/* ============================================================
   КНОПКИ СВЯЗИ (.ch__row / .ch__btn) — общее для КАЖДОЙ страницы
   темы. Anna Gorodetskaya — Portfolio · 13 сент 2026

   Дефект: разметку блока Next (channelsHtml() в build.mjs) печатает
   каждая страница с подвалом-Next, но базовые правила для .ch__row/
   .ch__btn/.btn лежат в skin-editorial.css и skin-technical.css —
   скинах ДРУГИХ тем. Alchemy подключает вместо них skin-alchemy.css,
   где этих классов нет вовсе. Замерено: класс .ch__btn стоит на 18
   страницах из 22 сборки, а хоть какую-то раскладку получают 6 —
   только кейсы уровня A, и то не отсюда, а от частного правила
   .jcontact__ch .ch__row в case-alchemy-tune.css (см. файл, §1).
   На остальных двенадцати ссылки слипаются в голый текст
   «Telegram ↗Email ↗». Мост — единственный файл, подключаемый
   ВЕЗДЕ (systemCss в THEMES.alchemy), поэтому чинить здесь —
   значит закрыть дефект разом на всех текущих и будущих страницах.

   Оформление сведено к языку .button/.primary/.outline, уже
   объявленному сплиттером в skin-alchemy.css (строки ~44–118):
   пилюля, вес 650, поле в районе 17px/27px. Но ТЕЛО .button сюда
   не копируется — этот файл рукописный, а skin-alchemy.css
   сгенерирован и трогать его нельзя, так что свести оба места к
   общему селектору (.button, .ch__btn { … }) физически негде.
   Копия рецепта в двух файлах — ровно то, как через полгода один
   поправят, а другой забудут, и палитры разойдутся. Вместо
   копирования literal-значений .button.primary/.outline (у них
   свои приватные hex, не токены) .ch__btn красится через токены,
   которые уже держит вся тема (--accent/--ink/--ground/--rule) —
   рецепт остаётся один и живёт в переменных, а не в двух списках
   hex. Форма (радиус, отступ, вес) при этом та же, что у .button —
   геометрия скопирована открыто, потому что несоответствие
   геометрии было бы заметно на глаз, а несоответствие оттенка
   токена — нет.

   Различие «почта — главный канал, мессенджер — второй» уже в
   разметке: channelsHtml() ставит mailto-ссылку без отдельного
   модификатора, поэтому селектор [href^="mailto"] — тот самый
   сигнал, а не новый класс в шаблонах (задача просила без них
   обойтись).
   ============================================================ */

/* --- Правка 13.09.2026 (Анна): «кнопки прилипают к тексту» на
   /about/, и не только там. .closer__ch — вторая разметка блока
   Next (section.closer#contact, а не .jcontact у кейсов A), стоит
   на 12 страницах: about, contact, cv, все четыре /for/<slug>/, и
   пять проектов уровня B/C (atalanta-fugiens, clariozo,
   greenau-pots, growth-tracking-school, world-cannabis-tour).
   Замерено в браузере (Puppeteer, getBoundingClientRect, 1440px,
   до правки): .closer__body — margin-bottom:0 (общий ресет
   base.css, h1..p{margin:0} — здесь этот класс никем не
   переопределён), .closer__ch — margin-top:0 — зазор между низом
   абзаца и верхом первой .ch__btn буквально 0px на 11 страницах из
   12 (на /contact/ 1px — другая разметка над кнопками, тот же
   эффект слипания). Ориентир — уже одобренный ритм у семьи
   .jcontact__ch (шесть кейсов A, case-alchemy-tune.css): там тот
   же зазор держат body{margin-bottom:30px}+ch{margin-top:0} = 30px
   ровно. Здесь тот же результат получен с другой стороны —
   margin-top на .closer__ch, а не margin-bottom на .closer__body —
   чтобы не трогать .t-body, общий класс параграфов по всему сайту.
   Селектор .closer__ch не пересекается с .jcontact__ch (разные
   имена классов в разных шаблонах) — семью кейсов A трогать не
   пришлось, её 30px уже жили в case-alchemy-tune.css. */
.closer__ch { margin-top: 30px; }

.ch__row {
  display: flex;
  flex-wrap: wrap;
  gap: 15px; /* то же число, что .jcontact__ch .ch__row уже держит в case-alchemy-tune.css — общий вид, а не два независимых зазора */
}

.ch__btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  border-radius: 100px;   /* форма .button — пилюля, skin-alchemy.css:44 */
  padding: 15px 26px;     /* тот же порядок величины, что .button (17px 27px) */
  font-weight: 650;
  font-size: 14px;
  line-height: 1.3;
  border: 1px solid transparent;
  transition: transform .3s, box-shadow .3s, background .3s, border-color .3s, color .3s;
  /* вторичная кнопка по умолчанию — язык .button.outline: тонкая
     обводка, почти прозрачная заливка */
  color: var(--ink-80);
  background: color-mix(in srgb, var(--ink) 4%, transparent);
  border-color: var(--rule);
}
.ch__btn:hover { transform: translateY(-3px); border-color: var(--accent); }
.ch__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* главный канал — язык .button.primary: сплошная охра */
.ch__btn[href^="mailto"] {
  color: var(--ground);
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 7px 22px rgba(0, 0, 0, 0.25);
}
.ch__btn[href^="mailto"]:hover {
  background: color-mix(in srgb, var(--accent) 82%, white);
}

/* Незаполненный канал (see channelsHtml() — печатается только вне
   PROD, в этом проекте у обоих каналов уже есть url и .is-pending
   на alchemy сейчас не рендерится; стиль на будущее, чтобы новый
   канал без адреса не оставался голым). */
.ch__btn.is-pending {
  cursor: default;
  color: var(--ink-55);
  border-style: dashed;
  background: transparent;
  box-shadow: none;
}
.ch__btn.is-pending:hover { background: transparent; color: var(--ink-55); transform: none; }
.ch__btn .gap { margin-left: 0.6em; font-size: 12px; color: var(--ink-55); font-style: italic; }
