/* ══════════════════════════════════════════════════════════════════════════════
   ARE5 — ВИЗУАЛЬНЫЙ РЕГИСТР. Единственный источник стиля для всех страниц.

   Зачем один файл: в прошлой версии стиль был размазан по трём CSS и 828
   хардкодам цвета, поэтому каждая правка расползалась и страницы разъезжались.
   Здесь всё — токены, типографика, компоненты. Правка темы = правка :root.

   Регистр: строгий enterprise. Ориентиры — Anduril, Palantir Blueprint, Apple.
   Правила, которые держат всё:
     ЦВЕТ      несёт статус и действие, а не украшение
     ГЛУБИНА   тональная ступень + волосяная линия, НЕ тени и не свечения
     ЖИВОСТЬ   на границах и ховерах, НЕ на заливках
     РАДИУСЫ   8px на контенте против капсулы на контролах — это подпись
     ДИСПЛЕЙ   light-вес на крупном кегле = собранность, а не крик
   ══════════════════════════════════════════════════════════════════════════ */

:root{
  /* ─── Поверхности: тёплый песочный (утверждено на живом) ─── */
  --bg:#EFEDE9;            /* канва */
  --s1:#F6F5F2;            /* поверхность над канвой */
  --s2:#FBFAF8;            /* приподнятое */
  --sunken:#E9E6E1;        /* утопленное: шапки таблиц, полосы */

  /* ─── Текст ─── */
  --ink:#16191D;           /* заголовки — графит, не чёрный */
  --ink-2:#4E555E;         /* основной текст */
  --ink-3:#5F666E;         /* подписи, мета (4.97:1 — проходит AA) */

  /* ─── Линии и акценты ─── */
  --line:0,0,0;            /* волосяные линии: графит с малой альфой */
  --warm:166,92,36;        /* тёплая нота ховеров — взята из эмблемы */

  /* ─── Геометрия ─── */
  --r:8px;                 /* контент */
  --r-sm:4px;              /* мелкие элементы */
  --pill:999px;            /* контролы */

  /* ─── Шрифты ─── */
  --fh:'Switzer','Inter',system-ui,-apple-system,sans-serif;
  --fb:'Inter',system-ui,-apple-system,'Segoe UI',sans-serif;
  --fm:'JetBrains Mono',ui-monospace,monospace;

  /* ─── Ритм ─── */
  --wrap:1200px;
  --pad:40px;
}

*{box-sizing:border-box}
html{background:var(--bg); scroll-behavior:smooth}
body{
  margin:0; background:var(--bg); color:var(--ink-2);
  font-family:var(--fb); font-size:15px; line-height:1.6;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}

/* ─── Фон: гекс-сетка (тот же паттерн, что в продукте AIO) + мягкий верхний свет ─── */
body::before{
  content:''; position:fixed; inset:0; z-index:0; pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100.8' height='86.4'%3E%3Cpath d='M50.4 0 L100.8 25.2 L100.8 61.2 L50.4 86.4 L0 61.2 L0 25.2 Z' fill='none' stroke='%2364748b' stroke-width='1' opacity='0.15'/%3E%3C/svg%3E");
  background-repeat:repeat; background-size:126px 108px;
}
body::after{
  content:''; position:fixed; inset:0; z-index:0; pointer-events:none;
  background:radial-gradient(120% 70% at 50% -10%, rgba(255,255,255,.55), transparent 58%);
}
.page{position:relative; z-index:1}
.container{max-width:var(--wrap); margin:0 auto; padding:0 var(--pad)}

/* ═══ ШАПКА ═══ */
header.site{
  position:sticky; top:0; z-index:30;
  background:rgba(239,237,233,.84); backdrop-filter:blur(14px);
  border-bottom:1px solid rgba(var(--line),.08);
}
.bar{display:flex; align-items:center; height:64px; gap:14px}
/* ═══ ЛОКАП БРЕНДА — wordmark, без фигурного знака (решение Chat 737) ═══
   ARE плотно · линия-разделитель на базовой линии в высоту прописных · 5 тише по весу и цвету.
   Оптические компенсации (выведены глазами Влада, не на глаз в коде):
   · зазоры у линии АСИММЕТРИЧНЫ (слева больше, справа меньше): у «E» правая кромка —
     прямой штрих на всю высоту, у «5» слева штрих только в верхней трети → при равных
     отступах пятёрка «отваливается» от линии;
   · кегль пятёрки +4%: цифры рисуются ниже высоты прописных, меньший вес добавляет к этому;
   · утолщение .32px: нужен вес между 500 и 600, которого у Switzer нет.
     text-stroke не кроссбраузерный — это прогрессивное улучшение, fallback = чистый 600. */
.brand{display:inline-flex; align-items:baseline; text-decoration:none; white-space:nowrap;
  font-family:var(--fh); color:var(--ink); line-height:1}
/* Кегль согласован с кнопкой в баре: текст кнопки 13px × межстрочный 1.62 ≈ 21px высоты строки.
   Высота прописных Switzer = .72em, значит 29px × .72 ≈ 21px — буквы и текст кнопки встают
   в один оптический ряд, вертикальные отступы в баре получаются одинаковыми. */
/* На 29px трекинг −.03em давал −0.87px между буквами — на крупном кегле они начинали
   сцепляться. Ослаблено до −.018em: плотность остаётся, слипания нет.
   margin-left у «5» снят: обводка .32px расширяет глиф наружу и уже придвигает его к линии,
   отрицательный отступ поверх этого сажал пятёрку на линию. */
.brand .b1{font-weight:800; font-size:29px; letter-spacing:-.018em}
.brand .rule{display:inline-block; width:1.2px; background:rgba(var(--line),.26);
  font-size:29px; height:.72em; margin-left:6.6px; margin-right:4px}
.brand .b5{font-weight:600; font-size:30.2px; letter-spacing:-.01em; color:var(--ink-3);
  -webkit-text-stroke:.32px currentColor}
.brand .b2{font-family:var(--fm); font-size:10px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--ink-3); margin-left:15px}

/* ═══ ЛОКАП СТОЛБИКОМ — крупная форма: ARE|5 над TECHNOLOGIES, вписано в прямоугольник ═══
   Нижняя строка растянута трекингом до ширины верхней. ⚠️ letter-spacing добавляет отступ
   ПОСЛЕ последней буквы — гасим отрицательным margin-right, иначе строка визуально
   уезжает влево относительно ARE|5 при центрировании. */
.blk{display:inline-flex; flex-direction:column; align-items:center; text-decoration:none;
  font-family:var(--fh); color:var(--ink); line-height:1}
/* ⚠️ line-height:1 обязателен: от body наследуется 1.6, и строка с кеглем 116px занимала
   185px при высоте букв 83px — блок раздувался пустотой и «плавал» в колонке. */
.blk .l1{display:inline-flex; align-items:baseline; line-height:1}
.blk .l1 .b1{font-weight:800; font-size:2.9em; letter-spacing:-.03em}
.blk .l1 .rule{display:inline-block; width:1.3px; background:rgba(var(--line),.3);
  font-size:2.9em; height:.72em; margin-left:.115em; margin-right:.065em}
.blk .l1 .b5{font-weight:600; font-size:3.02em; letter-spacing:-.01em; color:var(--ink-3);
  -webkit-text-stroke:.4px currentColor; margin-left:-.012em}
/* Нижняя строка: кегль поднят, трекинг снижен — суммарная ширина та же, но буквы
   перестают выглядеть разбросанными. .92em×.6(моно)×12 + .22em×12 ≈ прежние 9.3em. */
.blk .l2{font-family:var(--fm); font-size:.92em; font-weight:500; letter-spacing:.22em;
  text-transform:uppercase; color:var(--ink-3); margin-top:.92em; margin-right:-.22em}
nav.main{margin-left:auto; display:flex; gap:30px}
nav.main a{
  font-size:13px; color:var(--ink-2); text-decoration:none;
  padding:4px 0; border-bottom:1px solid transparent; transition:.16s;
}
nav.main a:hover{color:var(--ink); border-bottom-color:rgba(var(--warm),.5)}
nav.main a[aria-current="page"]{color:var(--ink); border-bottom-color:rgba(var(--line),.35)}

/* ═══ КНОПКИ ═══ */
.btn{
  display:inline-block; font-family:var(--fb); font-size:14px; font-weight:500;
  padding:11px 22px; border-radius:var(--pill); text-decoration:none;
  transition:.16s; border:1px solid transparent; cursor:pointer;
}
.btn-p{background:var(--ink); color:#FBFAF8}
.btn-p:hover{background:#0C0E11}
.btn-s{border-color:rgba(var(--line),.14); color:var(--ink-2); background:transparent}
.btn-s:hover{border-color:rgba(var(--warm),.35); color:var(--ink); background:rgba(var(--warm),.045)}
.btn-sm{font-size:13px; padding:8px 18px}

/* ═══ ТИПОГРАФИКА ═══ */
.kicker{
  font-size:12px; font-weight:600; letter-spacing:.09em; text-transform:uppercase;
  color:var(--ink-3); display:flex; align-items:center; gap:10px; margin:0 0 26px;
}
.kicker::before{content:''; width:22px; height:1px; background:rgba(var(--line),.16); flex:none}
h1{
  /* light на крупном кегле — собранность, не крик */
  font-family:var(--fh); font-weight:300; font-size:58px; line-height:1.06;
  letter-spacing:-.022em; margin:0 0 26px; max-width:18ch; color:var(--ink);
}
h1 em{font-style:normal; color:var(--ink-3)}
h2{font-family:var(--fh); font-weight:400; font-size:28px; letter-spacing:-.018em; margin:0; color:var(--ink)}
h3{font-family:var(--fh); font-weight:600; font-size:16px; letter-spacing:-.005em; margin:0 0 10px; color:var(--ink)}
.lede{font-size:17px; color:var(--ink-2); max-width:64ch; margin:0 0 38px; line-height:1.62}
p{margin:0 0 14px}
p:last-child{margin-bottom:0}
a{color:var(--ink)}

/* ═══ СЕКЦИИ ═══ */
.hero{padding:104px 0 84px; border-bottom:1px solid rgba(var(--line),.08)}
.hero-sm{padding:80px 0 56px; border-bottom:1px solid rgba(var(--line),.08)}

/* ═══ SPLIT-HERO: текст слева, знак справа (паттерн главной Crafty) ═══ */
/* Знак выровнен по ВЕРХНЕЙ линии букв заголовка, не по центру блока.
   Отступ считан по метрикам, а не подобран: kicker 12px×1.6 + margin 26px = 45px до строки h1,
   внутри строки h1 (58px, line-height 1.06) верх заглавных ниже верха строки на ≈12px.
   Итого верх букв h1 = 57px от верха текстового блока — на эту линию и ставим знак.
   У локапа вычитается его собственный внутренний отступ до верха букв (≈20px при кегле 116px). */
.hero-split{display:grid; grid-template-columns:1.35fr 1fr; gap:60px; align-items:start}
.hero-split .htext .lede{margin-bottom:0}
.hmark{display:block; width:100%; max-width:236px; height:auto; margin:57px auto 0; justify-self:center}
.hmark.wide{max-width:318px}   /* широкий локап (2:1+) — иначе по высоте выглядит мелким */
.hmark.sq{max-width:194px}     /* квадратный знак — на общей ширине был бы вдвое выше локапа */
/* наш локап столбиком в той же позиции hero — размер задаётся одним font-size */
/* Кегль выведен замером, не на глаз: знаки продуктов в этой же позиции дают в среднем
   277×162px, локап при 19.5px давал 143×67px — вдвое мельче. 40px → ≈294×137px,
   то есть в одном весе с ними (см. /tmp/audit_hero_marks.py). */
.hero-split .blk{font-size:40px; justify-self:center; margin-top:37px}
/* имя продукта без своего знака: одна строка, без растянутой подписи —
   у короткого слова («Ruby») подпись вышла бы шире имени и прямоугольник бы развалился */
.pblk .l1 .b1{font-size:2.6em; letter-spacing:-.02em}
@media(max-width:960px){
  .hero-split .blk{font-size:17px; justify-self:start; order:-1}
}
@media(max-width:960px){
  .hero-split{grid-template-columns:1fr; gap:30px}
  /* в одну колонку знак уходит наверх — выравнивание по строке заголовка больше не нужно */
  .hmark{order:-1; max-width:132px; margin:0}
  .hmark.wide{max-width:190px}
  .hmark.sq{max-width:104px}
  .hero-split .htext{order:1}
  .hero-split .blk{margin-top:0}
}
section{padding:88px 0; border-bottom:1px solid rgba(var(--line),.08)}
section.last{border-bottom:0}
.shead{display:flex; align-items:baseline; gap:18px; margin-bottom:44px}
.shead>div{flex:1; min-width:0}
.snum{font-family:var(--fm); font-size:11px; color:var(--ink-3); letter-spacing:.1em; padding-top:6px; flex:none}
.sdesc{font-size:15px; color:var(--ink-2); max-width:58ch; margin:8px 0 0; line-height:1.55}
.cta{display:flex; gap:12px; align-items:center; flex-wrap:wrap}

/* ═══ ЛОГО ПРОДУКТА В HERO (нормализация по высоте: локапы разных пропорций встают ровно) ═══ */
.plogo{display:block; height:62px; width:auto; margin:0 0 28px}
.plogo.sq{height:56px}          /* квадратный знак читается крупнее — гасим */
@media(max-width:860px){ .plogo{height:48px; margin-bottom:22px} .plogo.sq{height:44px} }

/* ═══ ЛОГО В РЕЕСТРЕ (.reg.logos — отдельная колонка-знак; обычный .reg не трогаем) ═══ */
.reg.logos .row{grid-template-columns:112px 146px 1fr 132px 40px}
.reg.logos .row>div:first-child{display:flex; align-items:center; justify-content:center}
.rlogo{display:block; height:38px; width:auto; max-width:104px; margin:0 auto}
.rlogo.sq{height:36px}
/* продукт без своего знака — ставим наш мини-локап ARE|5 (без дескриптора) */
.rmini{display:inline-flex; align-items:baseline; font-family:var(--fh); color:var(--ink)}
.rmini .b1{font-weight:800; font-size:21px; letter-spacing:-.03em}
.rmini .rule{display:inline-block; width:1px; background:rgba(var(--line),.26);
  font-size:21px; height:.72em; margin-left:4.4px; margin-right:2.5px}
.rmini .b5{font-weight:600; font-size:21.8px; letter-spacing:-.01em; color:var(--ink-3);
  -webkit-text-stroke:.3px currentColor; margin-left:-.5px}
@media(max-width:960px){ .reg.logos .row>div:first-child{justify-content:flex-start} }

/* ═══ ПЛИТКИ ═══ */
.grid-3{display:grid; grid-template-columns:repeat(3,1fr); gap:16px}
.grid-2{display:grid; grid-template-columns:repeat(2,1fr); gap:16px}
/* ⚠️ Переделано 20.08.2026 по замеру контраста, а не на глаз. Жалоба была «карточки
   приклеены, объёма нет», и причина оказалась не в тенях.

   Было: заливка = белый .78 сверху, уходящий в прозрачность к 64% высоты, поверх `--s1`.
   Контраст к канве по высоте карточки: верх 1.149 · середина 1.091 · НИЗ 1.072.
   Утопленная поверхность (`--sunken`) стоит от канвы на 1.065 — то есть низ поднятой
   карточки и вдавленная поверхность оказались на ОДНОМ расстоянии от фона, только с
   разных сторон. Глубина при этом читаться не может: книзу карточка растворялась в канве.
   Хуже того, разброс внутри карточки (1.149→1.072 = .077) был БОЛЬШЕ, чем весь прирост
   от наведения (1.091→1.141 = .050) — собственный градиент перекрывал ховер, поэтому
   наведение и не чувствовалось.

   Стало: РОВНАЯ поверхность на ступень выше канвы (`--s2` = 1.121 по всей высоте) +
   усиленная волосяная линия края (.05 → .085). На светлом фоне «поднято» читается краем,
   а не тенью — это ровно наше правило «глубина = тональная ступень + волосяная линия».
   Ховер уходит на чистый белый (1.169), ступень покой→ховер сохранена (+.048),
   а разброс внутри карточки теперь 0.000.

   ⛔ Тёплая нота на ховере убрана из ЗАЛИВКИ и оставлена только на канте: правило в шапке
   файла гласит «живость на границах и ховерах, НЕ на заливках», а прежний градиент
   `rgba(--warm,.045) 92%` был именно заливкой — то есть нарушал наш собственный регистр. */
.card{
  background:var(--s2);
  /* светлый стеклянный кант, как у карточки основателя: еле заметная обводка, ловит свет по краю */
  border:1px solid rgba(255,255,255,.55); border-radius:var(--r);
  padding:28px 24px 30px; transition:.18s;
  /* три слоя: волосяная линия для чёткости края на канве · парение · световой кант сверху.
     масштаб тени под сетку — карточки приподнимаются над канвой, а не «улетают». */
  box-shadow:
    0 0 0 1px rgba(22,25,29,.085),
    0 14px 30px -16px rgba(22,25,29,.30),
    inset 0 1px 0 rgba(255,255,255,.7);
}
.card:hover{
  background:#FFFFFF;
  border-color:rgba(255,255,255,.8);
  box-shadow:
    0 0 0 1px rgba(var(--warm),.22),
    0 22px 42px -18px rgba(22,25,29,.38),
    inset 0 1px 0 rgba(255,255,255,.8);
  transform:translateY(-3px);   /* лёгкий подъём при наведении */
}
.card p{font-size:15px; color:var(--ink-2); line-height:1.55}
.cdx{font-family:var(--fm); font-size:10px; color:var(--ink-3); letter-spacing:.12em; display:block; margin-bottom:16px}

/* ═══ РЕЕСТР (строки вместо плавающих карточек — язык систем, не витрин) ═══ */
.reg{border-top:1px solid rgba(var(--line),.08)}
.row{
  display:grid; grid-template-columns:170px 1fr 132px 40px; gap:24px; align-items:center;
  padding:24px 0; border-bottom:1px solid rgba(var(--line),.08);
  transition:.16s; text-decoration:none; color:inherit;
}
.row:hover{background:rgba(var(--warm),.03)}
.rname{font-family:var(--fh); font-weight:700; font-size:19px; letter-spacing:-.01em; color:var(--ink)}
.rsub{font-size:11px; color:var(--ink-3); letter-spacing:.1em; text-transform:uppercase; margin-top:3px}
.rdesc{font-size:15px; color:var(--ink-2); line-height:1.55}
.arrow{font-size:14px; color:var(--ink-3); text-align:right; transition:.16s}
.row:hover .arrow{color:var(--ink); transform:translateX(3px)}

/* ═══ СТАТУС-КАПСУЛЫ (цвет только как статус, всегда со словом) ═══ */
.pill{
  display:inline-block; font-family:var(--fm); font-size:10px; letter-spacing:.1em;
  text-transform:uppercase; padding:4px 11px; border-radius:var(--pill);
  border:1px solid rgba(var(--line),.14); color:var(--ink-2); white-space:nowrap;
}
.pill.live{color:var(--ink); border-color:rgba(var(--line),.24)}
.pill.dev{color:var(--ink-3)}

/* ═══ ТЕГИ ═══ */
.tags{display:flex; flex-wrap:wrap; gap:8px}
.tag{
  font-family:var(--fm); font-size:11px; letter-spacing:.04em; color:var(--ink-2);
  border:1px solid rgba(var(--line),.08); border-radius:var(--pill);
  padding:6px 13px; background:#fff; transition:.16s;
}
.tag:hover{color:var(--ink); border-color:rgba(var(--warm),.3); background:rgba(var(--warm),.04)}

/* ═══ ЛОГО-ОБЛАКО ═══
   Логотипы в своём цвете. Я сначала обесцветил их в серый ради строгости —
   Влад справедливо осадил: получилось невнятно. Логотип должен читаться,
   узнаваемость и есть его работа. Строгость держат сетка и подписи, а не
   обесцвечивание. */
/* Плитки и рамки сняты: логотипы лежат прямо на канве. Сетка с рамками давала
   торчащую линию справа и рваный последний ряд — flex с центрированием
   раскладывает любое количество ровно, без осиротевших ячеек. */
.cloud{
  display:flex; flex-wrap:wrap; justify-content:center;
  gap:14px 8px; padding:4px 0;
}
.chip{
  display:flex; flex-direction:column; align-items:center; justify-content:flex-start; gap:14px;
  flex:0 0 172px; padding:20px 8px;
  background:transparent; text-decoration:none; transition:.18s;
}
/* Фиксированная высота бокса под лого + центрирование: у логотипов разные
   пропорции (Stripe широкий, React квадратный), и без общего бокса подписи
   встают на разной высоте — ряд визуально «пляшет». */
.chip .mark{
  height:54px; display:flex; align-items:center; justify-content:center;
  width:100%; padding:0 4px;
}
.chip img{
  max-height:54px; max-width:100%; width:auto; height:auto; display:block;
  transition:transform .18s;
}
.chip:hover img{transform:scale(1.05)}
.chip span{
  font-size:12px; color:var(--ink-3); letter-spacing:.01em; text-align:center; line-height:1.35;
}
.chip:hover span{color:var(--ink-2)}
/* Заголовок группы над облаком. Раньше стоял 13px в одну строку с описанием —
   читался как мелкая подпись, хотя это заголовок блока. Теперь пара
   «заголовок + текст» в том же размере, что в карточках. */
.cloud-label{
  display:flex; flex-direction:column; gap:6px; margin:0 0 22px;
  padding-bottom:16px; border-bottom:1px solid rgba(var(--line),.08);
}
/* 16px — ровно как h3 в карточках. Один размер заголовка на всей странице,
   иначе группы начинают спорить с карточками за внимание. */
.cloud-label b{
  font-family:var(--fh); font-weight:600; font-size:16px; letter-spacing:-.005em; color:var(--ink);
}
.cloud-label span{font-size:15px; color:var(--ink-2); line-height:1.55; max-width:62ch}
.cloud-group{margin-bottom:48px}
.cloud-group:last-child{margin-bottom:0}

/* ═══ БЕЙДЖ УЧАСТИЯ (только там, где статус реально есть) ═══ */
.badge-row{
  display:flex; align-items:center; gap:22px; flex-wrap:wrap;
  background:var(--s1); border:1px solid rgba(var(--line),.08);
  border-radius:var(--r); padding:24px 26px;
}
.badge-row img{height:56px; width:auto; display:block}
/* 280px заставляют текст уйти на свою строку рядом со знаком — это намеренно.
   Но как ЖЁСТКОЕ требование они толкали страницу на узких телефонах: при окне 320px
   внутри контейнера остаётся меньше 280px даже на отдельной строке (замер: лишних 9px).
   min() делает значение потолком — поведение то же, сжатие разрешено.
   ⛔ Не `.txt{min-width:0}` в конце файла: тот селектор слабее `.badge-row .txt`
   и молча ничего не делал. Проверено замером, а не чтением. */
.badge-row .txt{flex:1; min-width:min(280px, 100%)}
.badge-row h3{margin-bottom:6px}
.badge-row p{font-size:14px; color:var(--ink-2); line-height:1.55}
/* ═══ БЛОК ОСНОВАТЕЛЯ — паттерн SplitSection с Crafty (testimonial с большим фото) ═══
   Раньше фото было заперто в край жёсткого прямоугольника — выходил мугшот.
   Здесь снимок ПЛАВАЕТ: скруглён, с мягкой тенью и волосяным кантом, и выходит за верх
   и низ карточки (отрицательные поля). Позади текста — крупный тихий знак кавычки.
   Это ровно наш общий компонент, просто перенесён в статические стили лендинга. */
.person-feature{
  position:relative; display:flex; align-items:center; gap:34px;
  /* стеклянная карточка — тот же приём, что в story/wishes на Crafty:
     полупрозрачный белый + размытие фона сквозь неё + светлый кант + глубокая тень.
     Гексы канвы просвечивают сквозь стекло, поэтому блок не «наклейка», а слой над страницей.
     Масштаб ужат ~25% относительно первой версии — блок был заметно крупнее соседних карточек. */
  background:rgba(255,255,255,.55);
  -webkit-backdrop-filter:blur(16px); backdrop-filter:blur(16px);
  border:1px solid rgba(255,255,255,.6);
  box-shadow:0 24px 48px -26px rgba(22,25,29,.5), inset 0 1px 0 rgba(255,255,255,.7);
  border-radius:16px;
  padding:30px 34px;
}
.person-feature .pf-photo{
  flex:0 0 285px;
  margin:-22px 0;                 /* фото выступает за карточку сверху и снизу — «плавает» */
  position:relative;
}
/* колонка держит ПРОПОРЦИЮ снимка (690×568) — тогда композиция видна целиком
   и знак ARE|5 справа не срезается обрезкой под высокую колонку */
.person-feature .pf-photo img{
  display:block; width:100%; height:auto; aspect-ratio:690/568;
  object-fit:cover; border-radius:16px;
  box-shadow:0 24px 50px -18px rgba(22,25,29,.4);
  border:1px solid rgba(255,255,255,.6);
  outline:1px solid rgba(var(--line),.06);
}
.person-feature .pf-body{position:relative; flex:1; margin:0}
/* крупный знак кавычки за текстом — подпись жанра, тихо, чтобы не спорить с буквами */
.person-feature .pf-body::before{
  content:'\201C'; position:absolute; top:-34px; left:-6px; z-index:0;
  font-family:var(--fh); font-weight:800; font-size:112px; line-height:1;
  color:rgba(var(--warm),.12); pointer-events:none;
}
.person-feature .pf-role{
  position:relative; font-family:var(--fm); font-size:11px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--ink-3); margin:0 0 11px;
}
.person-feature blockquote{
  position:relative; margin:0; font-family:var(--fh); font-weight:400;
  font-size:16px; line-height:1.5; letter-spacing:-.01em; color:var(--ink);
}
.person-feature figcaption{margin-top:16px}
.person-feature .pf-name{
  font-family:var(--fh); font-weight:600; font-size:16px; color:var(--ink);
}
.person-feature .pf-links{display:flex; gap:22px; margin-top:8px}
.person-feature .pf-links a{display:inline-flex; align-items:center; gap:7px; font-size:14px}
.person-feature .pf-links svg{width:16px; height:16px; flex:none; color:var(--ink-3)}
.person-feature .pf-links a:hover svg{color:rgba(var(--warm),1)}
@media (max-width:760px){
  .person-feature{flex-direction:column; align-items:stretch; gap:28px; padding:30px 24px}
  .person-feature .pf-photo{flex:none; margin:0; min-height:300px}
  .person-feature .pf-body::before{top:-30px; font-size:110px}
}
.badge-row.person .role{
  font-family:var(--fm); font-size:12px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink-3); margin-bottom:10px;
}

/* ═══ СПИСКИ ФАКТОВ ═══ */
.facts{display:grid; gap:0; border-top:1px solid rgba(var(--line),.08)}
.fact{
  display:grid; grid-template-columns:200px 1fr; gap:24px;
  padding:16px 0; border-bottom:1px solid rgba(var(--line),.08);
}
.fact dt{font-size:13px; color:var(--ink-3); letter-spacing:.02em}
.fact dd{margin:0; font-size:15px; color:var(--ink)}

/* ═══ ПАРТНЁРЫ ═══ */
.partners{display:grid; grid-template-columns:repeat(2,1fr); gap:16px}
.partner{
  display:flex; gap:20px; align-items:flex-start;
  background:var(--s1); border:1px solid rgba(var(--line),.08);
  border-radius:var(--r); padding:24px; transition:.18s;
}
.partner:hover{border-color:rgba(var(--warm),.28); background:var(--s2)}
.partner .logo{flex:none; width:96px; display:flex; align-items:center; justify-content:center}
.partner .logo img{max-width:96px; height:auto; display:block}
.partner h3{margin-bottom:6px}
.partner p{font-size:14px; color:var(--ink-2); line-height:1.55}

/* ═══ БОКОВОЕ СОДЕРЖАНИЕ (страницы продуктов) ═══ */
.split{display:grid; grid-template-columns:1fr 320px; gap:56px; align-items:start}
.aside{
  background:var(--s1); border:1px solid rgba(var(--line),.08);
  border-radius:var(--r); padding:24px; position:sticky; top:96px;
}
.aside h3{font-size:12px; font-weight:600; letter-spacing:.09em; text-transform:uppercase; color:var(--ink-3); margin-bottom:14px}

/* ═══ ПОДВАЛ ═══ */
footer.site{padding:52px 0 64px}
.fbar{display:flex; align-items:center; gap:14px; flex-wrap:wrap}
/* локап в подвале — тише хедера; пропорции те же, кегль ниже */
.fbrand .b1{font-size:16px; letter-spacing:-.022em}
.fbrand .rule{font-size:16px; margin-left:3.6px; margin-right:2.1px}
.fbrand .b5{font-size:16.7px}
.fbar .sp{margin-left:auto}
.fbar a{color:var(--ink-3); text-decoration:none; font-size:12px; margin-left:22px}
.fbar a:hover{color:var(--ink)}
.copy{font-size:12px; color:var(--ink-3)}

/* ═══ АДАПТИВ ═══ */
@media (max-width:960px){
  :root{--pad:22px}
  h1{font-size:40px; max-width:100%}
  .grid-3,.grid-2,.partners{grid-template-columns:1fr}
  .split{grid-template-columns:1fr; gap:32px}
  .aside{position:static}
  .row{grid-template-columns:1fr; gap:8px}
  .reg.logos .row{grid-template-columns:1fr; gap:10px}
  .row .arrow{display:none}
  .fact{grid-template-columns:1fr; gap:4px}
  nav.main{display:none}
  section{padding:60px 0}
  .hero{padding:72px 0 56px}
}



/* ═══ УЗКИЕ ТЕЛЕФОНЫ (≤400px) ═══
   Ниже 960px меню скрыто, в шапке остаются знак и кнопка. При окне 320px внутренняя
   ширина контейнера ≈280px, а знак с подписью «TECHNOLOGIES» плюс кнопка требуют больше —
   кнопка уходила за край на 11px и тянула прокрутку всей страницы (замер: главная, 320px).

   Снимаем ВТОРУЮ СТРОКУ подписи, а не масштабируем локап: у знака выверенные оптические
   компенсации (асимметричные зазоры у линии, кегль пятёрки +4%, обводка), и подгонять их
   кеглем под телефон значило бы ломать то, что настраивалось глазами. Без подписи знак
   читается как ARE|5 — этого достаточно, а «Technologies» есть в подвале и в заголовке окна. */
@media(max-width:400px){
  .brand .b2{display:none}
}


/* ══════════════════════════════════════════════════════════════════════════════
   FEED|5 — РЕЕСТР ПУБЛИКАЦИЙ И СТРАНИЦА СТАТЬИ

   Жанр: научная публикация, не блог. Отсюда все решения ниже.

   Что взято из блога Crafty: только СТРУКТУРА (шапка → визуал → тело с пул-квотой
   справа → источники → автор). Цветовые приёмы НЕ взяты: там вид держат янтарные
   и фиолетовые градиенты плюс ring-свечения, а у нас в шапке этого файла записано
   «цвет несёт статус, глубину даёт тональная ступень и волосяная линия, живость —
   на границах». Градиент-заливка и свечение противоречат всем трём строкам, поэтому
   три разных бокса Crafty (highlight / outro / tribute) сведены к ОДНОМУ приёму
   `.callout`: линия слева + ступень поверхности. Отличаются кеглем и воздухом.

   Что НЕ переносилось сознательно:
   · `goldenTicket` / `Startup Bible` / `⬡ In our stack` — бейджи тиров конструктора
     сайтов. У публикации их нет.
   · механизм `:strike` (логотип, перечёркнутый двумя красными линиями). Технически
     красив и очень соблазнителен для текста про хайп, но это визуальное «врут»
     без источника и без права на ответ — против нашего правила двух регистров.
   · реакции и комментарии: бекенда нет, счётчик считал бы ноль. Под текстом,
     который требует источник к каждому числу, фальшивый счётчик дороже, чем польза.
     Их место занимают SOURCES + ATTESTER + REVISION.
   ══════════════════════════════════════════════════════════════════════════ */

/* ═══ РЕЕСТР ПУБЛИКАЦИЙ ═══
   Строки, а не плитки с обложками: плитка — язык витрины, где глаз идёт за картинкой,
   а строка — язык списка работ, где первым читается ЧТО измерено. Базовые `.reg`/`.row`
   уже есть выше; здесь только то, чего у них нет — строка провенанса. */
/* ⚠️ Поверхность НЕ своя: публикация — это `.card` (SSOT). Здесь только раскладка стопки
   и сброс ссылки. Сначала я собирался завести отдельный `.pub-card` со своим стеклом —
   это был бы второй компонент для той же задачи, и правку объёма пришлось бы делать
   дважды. Влад остановил: чиним `.card`, и объём появляется на всех страницах сразу. */
.pub{display:grid; gap:22px}

/* ═══ КАРТОЧКА ПУБЛИКАЦИИ = приём карточки основателя, ЗЕРКАЛЬНО ═══
   Влад: «стиль карточки один в один, только мою морду заменить на римский знак, и справа».
   Поэтому здесь НЕ новый компонент, а `.person-feature` + модификатор: стекло с размытием,
   плавающая фигура, выходящая за края, крупная кавычка за текстом — всё оттуда.

   Почему кавычка тут честна, а не украшение: в карточке стоит ОТРЫВОК из статьи, то есть
   текст действительно цитируется. Была бы там наша аннотация — кавычку пришлось бы снять.

   ⚠️ Обязательные сбросы для знака. У `.person-feature .pf-photo img` задано
   `aspect-ratio:690/568`, `object-fit:cover`, радиус 16, своя тень, рамка и обводка — это
   верно для СНИМКА, но гекс с такими правилами превратился бы в обрезанный прямоугольник
   с тенью по краю. Снимаем всё поимённо, иначе наследование сработает молча. */
.pub-feature{
  display:flex; align-items:center; gap:34px;
  text-decoration:none; color:inherit;
  transition:border-color .18s, box-shadow .18s, transform .18s;
}
/* ═══ ПЛИТА ПОД ЗНАК ═══
   У карточки основателя снимок лежит в оформленной плите: скругление 16, светлый кант,
   волосяная обводка, своя тень — и потому занимает СВОЁ место, а не висит на стекле.
   Знак получает такую же плиту. Это и просьба Влада, и польза на будущее: внутри плиты
   можно менять саму фигуру, не трогая раскладку карточки.
   ⚠️ Оформление стоит на КОНТЕЙНЕРЕ, а у снимка оно на `img`. Причина: наш знак — SVG с
   прозрачным фоном, и тень с радиусом на нём обвели бы сам гекс по контуру вместо плиты.
   Пропорция та же, что у снимка (690/568), чтобы плита читалась как родственная. */
.pub-feature .pf-photo{
  flex:0 0 236px; margin:-30px 0; padding:22px;
  aspect-ratio:690/568;
  display:flex; align-items:center; justify-content:center;
  background:var(--sunken);
  border-radius:16px;
  border:1px solid rgba(255,255,255,.6);
  outline:1px solid rgba(var(--line),.06);
  box-shadow:0 24px 50px -18px rgba(22,25,29,.4);
}
/* ⚠️ Причина того провала была НЕ в знаке, а в тексте: у `.pub-sub` стоит `max-width:62ch`,
   а колонка внутри широкой карточки почти вдвое шире — текст кончался, знак стоял у правого
   края, между ними дыра. Внутри этой карточки ограничение снимаем: колонку задаёт сама
   карточка, и мера строки получается из её ширины, а не из второго независимого правила.
   ⛔ В теле СТАТЬИ мера остаётся (68ch): там 8000 слов подряд, и там она работает. Здесь же
   отрывок в четыре строки — для него потолок в 62ch создавал дыру, а не читаемость. */
.pub-feature .pub-sub,
.pub-feature .pub-title{max-width:none}
.pub-feature .pf-photo img{
  /* ⛔ Сбросы обязательны и поимённо. У `.person-feature .pf-photo img` задано
     `aspect-ratio:690/568`, `object-fit:cover`, радиус 16, тень, рамка и обводка — верно для
     снимка, но гекс с этими правилами стал бы обрезанным прямоугольником с тенью по краю.
     Наследование сработало бы молча, поэтому снимаем каждое. */
  width:auto; height:100%; max-width:100%;
  aspect-ratio:auto; object-fit:contain;          /* ⛔ не cover: гекс нельзя обрезать */
  border:0; outline:0; box-shadow:none;
  border-radius:0; background:none;
}
/* Ссылка обязана отзываться. Тень и кант — как у `.card:hover`, чтобы карточки на сайте
   реагировали одинаково; тёплая нота только на канте, не заливкой. */
.pub-feature:hover{
  border-color:rgba(var(--warm),.35);
  box-shadow:0 30px 56px -26px rgba(22,25,29,.5), inset 0 1px 0 rgba(255,255,255,.8);
  transform:translateY(-2px);
}
.pub-feature:hover .pub-title{color:#0C0E11}
/* Верхняя строка карточки: индекс выпуска слева, дата справа — как номер и год у статьи
   в журнале.
   ⚠️ История этих трёх строк стоит комментария. Сначала они были снесены заменой региона
   (лежали между его границами), потом восстановлены вставкой по `index('.pub-title{')` —
   а первое вхождение этой строки оказалось ВНУТРИ составного селектора
   `.pub-feature:hover .pub-title{...}`, и вставка разрезала его пополам. В итоге `.pub-top`
   получил `display:flex` только под наведением, а `.pub-title{color}` осиротел и красил
   заголовок всегда. Дата при этом не уходила вправо: без flex авто-отступ на инлайновом
   `<span>` ничего не делает.
   ⇒ Урок: искать место вставки по подстроке селектора нельзя — она встречается внутри
   более длинных селекторов. Резать только по границам правил. */
.pub-top{display:flex; align-items:baseline; gap:14px; margin-bottom:12px}
.pub-ix{font-family:var(--fm); font-size:10px; letter-spacing:.12em; text-transform:uppercase; color:var(--ink-3)}
.pub-date{margin-left:auto; font-family:var(--fm); font-size:10px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--ink-3)}
.pub-feature:hover .pub-prov .sp{color:var(--ink)}
/* ⚠️ Кавычка сдвинута вправо и вниз против карточки основателя: там она стоит над
   строкой роли, а здесь над строкой «Note I · дата», которая набрана мелким моно —
   при прежних -34px кавычка налезала на неё. */
.pub-feature .pf-body::before{top:-26px; left:-2px; font-size:96px}
@media(max-width:760px){
  /* в узком окне знак уходит ПОД текст: две колонки оставляли строке меньше 40 знаков */
  .pub-feature{flex-direction:column; align-items:flex-start; gap:20px; padding:26px 22px}
  .pub-feature .pf-photo{flex:none; width:104px; margin:0}
}

.pub-title{font-family:var(--fh); font-weight:600; font-size:23px; letter-spacing:-.015em;
  color:var(--ink); margin:0 0 8px; max-width:34ch; line-height:1.25}
.pub-sub{font-size:15px; color:var(--ink-2); line-height:1.55; max-width:62ch; margin:0}
/* ⭐ Строка провенанса — то, чего нет ни у одного блога. Блог показывает время чтения,
   мы показываем, ЧЕМ и КОГДА мерили. Это наш регистр в одну строку, поэтому она
   отделена волосяной линией: читается как подпись под работой, а не как теги. */
.pub-prov{
  display:flex; flex-wrap:wrap; align-items:center; gap:8px 18px;
  margin-top:16px; padding-top:13px; border-top:1px solid rgba(var(--line),.07);
  font-family:var(--fm); font-size:11px; letter-spacing:.03em; color:var(--ink-3);
}
.pub-prov b{font-weight:500; color:var(--ink-2)}
.pub-prov .sp{margin-left:auto}
.pub-row:hover .pub-prov .sp{color:var(--ink)}

/* ═══ СТАТЬЯ: ОБЁРТКА И МЕРА СТРОКИ ═══
   Кегль тела 17px против 15px основного текста сайта, и это не вкус. На страницах-витринах
   абзац короткий, здесь — 8000+ слов подряд: при 15px строка в 68 знаков даёт мелкий
   плотный массив, глаз теряет строку на возврате. 17px/1.72 и мера 68ch — это ~66-70 знаков,
   тот же коридор, который независимо выбран в блоге Crafty (max-w-xl ≈ 65-70) и в нашем
   `.lede` (64ch). Три раза сошлось — значит попадание, а не предпочтение. */
.art{padding:0 0 92px}
.art-wrap{max-width:var(--wrap); margin:0 auto; padding:0 var(--pad)}
/* Кегль 18px, а не 17: айтрекинг на 104 участниках (Rello, Pielot, Marcos, CHI 2016)
   даёт рост читаемости И понимания до 18, дальше плато, а после 22 субъективная
   оценка падает. Интерлиньяж 1.7 — при 18px это 30.6px; крайности (0.8 и 1.8 от
   кегля) в том же замере ухудшали понимание, у лидеров рынка в CSS доминирует 1.5,
   но у них строка короче нашей.
   ⚠️ `max-width` оставлен как страховка: сетка уже задаёт 68ch, но статья может
   встать и вне сетки (узкий экран), и тогда мера обязана держаться сама. */
.art-body{max-width:68ch; font-size:18px; line-height:1.7; color:var(--ink-2)}
.art-body>*:first-child{margin-top:0}
.art-body h2{
  font-family:var(--fh); font-weight:400; font-size:27px; letter-spacing:-.018em;
  color:var(--ink); margin:58px 0 18px; line-height:1.22; max-width:30ch;
}
/* h3 внутри тела: 17px как у текста, отличается весом и цветом — на длинном тексте
   лишняя ступень кегля дробит массив на «много заголовков». */
.art-body h3{font-family:var(--fh); font-weight:600; font-size:17px; color:var(--ink); margin:34px 0 10px}
.art-body p{margin:0 0 20px}
.art-body strong{font-weight:600; color:var(--ink)}
.art-body a{color:var(--ink); text-decoration:underline; text-decoration-color:rgba(var(--warm),.45);
  text-underline-offset:3px; text-decoration-thickness:1px}
.art-body a:hover{text-decoration-color:rgba(var(--warm),1)}
.art-body ul,.art-body ol{margin:0 0 20px; padding-left:0; list-style:none}
.art-body ol{counter-reset:li}
/* Пункт списка: маркер моноширинный и тише текста — список читается как перечень,
   а не как продолжение абзаца. Отступ 26px = ширина маркера + воздух. */
.art-body li{position:relative; padding-left:26px; margin-bottom:12px}
.art-body ul>li::before{
  content:''; position:absolute; left:8px; top:.72em; width:4px; height:4px;
  border-radius:50%; background:rgba(var(--line),.3);
}
.art-body ol>li::before{
  counter-increment:li; content:counter(li) '.'; position:absolute; left:0; top:0;
  font-family:var(--fm); font-size:13px; color:var(--ink-3);
}
.art-body hr{border:0; border-top:1px solid rgba(var(--line),.1); margin:44px 0 24px}

/* ═══ ВЫНОСКА — ОДИН приём вместо трёх боксов Crafty ═══
   Линия слева + тональная ступень. Ни градиента, ни свечения: глубину даёт поверхность
   на ступень выше канвы, как у `.card` и `.aside`. Тёплая нота в линии — та же, что
   в ховерах кнопок и строк, поэтому выноска не выглядит вставкой из другого макета. */
.callout{
  margin:30px 0; padding:20px 24px; background:var(--s1);
  border-left:2px solid rgba(var(--warm),.5); border-radius:0 var(--r) var(--r) 0;
}
.callout p{margin:0 0 12px}
.callout p:last-child{margin-bottom:0}
.callout.quiet{background:rgba(var(--warm),.045); border-left-color:rgba(var(--line),.28)}
/* сильная выноска — ключевое утверждение раздела: кегль на ступень выше тела, вес light,
   по тому же правилу, что h1 на витрине (крупный кегль тихим весом = собранность) */
.callout.strong p{font-family:var(--fh); font-weight:400; font-size:20px; line-height:1.45;
  letter-spacing:-.012em; color:var(--ink)}
/* угасающие строки (приём tribute у Crafty): каждая следующая тише предыдущей.
   Держим на opacity, а не на четырёх цветах — цвет у нас несёт статус. */
.callout.fade p{font-family:var(--fh); font-weight:600; font-size:20px; line-height:1.4;
  letter-spacing:-.012em; color:var(--ink); margin:0 0 4px}
.callout.fade p:nth-child(2){opacity:.72}
.callout.fade p:nth-child(3){opacity:.48}
.callout.fade p:nth-child(4){opacity:.3}

/* ═══ КОД И ЗАМЕРЫ В ТЕЛЕ ═══
   Замер печатается моноширинным блоком, а не абзацем: цифра в моно читается как показание
   прибора, и её нельзя спутать с утверждением автора. Утопленная поверхность (`--sunken`)
   вместо рамки — тот же приём, что у шапок таблиц. */
.art-body pre{
  margin:26px 0; padding:20px 22px; background:var(--sunken); border-radius:var(--r);
  border:1px solid rgba(var(--line),.07); overflow-x:auto;
  font-family:var(--fm); font-size:13px; line-height:1.62; color:var(--ink);
}
.art-body code{font-family:var(--fm); font-size:.88em; color:var(--ink);
  background:rgba(var(--line),.05); padding:2px 5px; border-radius:var(--r-sm)}
.art-body pre code{background:none; padding:0; font-size:inherit}

/* ═══ РИСУНОК — блока картинки в рефе НЕТ, добавлен здесь ═══
   Подпись обязательна и содержит источник: рисунок в публикации — такое же утверждение,
   как фраза, и подчиняется тому же правилу провенанса. Поэтому `figcaption` не
   декоративная подпись, а поле с адресом замера. */
.fig{margin:34px 0; max-width:none}
.fig img,.fig svg{display:block; width:100%; height:auto; border-radius:var(--r);
  border:1px solid rgba(var(--line),.08); background:var(--s2)}
.fig figcaption{
  margin-top:11px; padding-left:2px; font-size:13px; line-height:1.5; color:var(--ink-3);
}
.fig figcaption b{font-family:var(--fm); font-size:11px; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-3); font-weight:500; margin-right:8px}
/* широкий рисунок выходит за меру строки — схема с двумя кривыми в 68ch нечитаема */
.fig.wide{width:min(100%, 940px)}

/* ═══ ИСТОЧНИКИ ═══
   Нумерованный список ссылок на месте, где у блога стоят комментарии. Кегль ниже тела:
   это аппарат статьи, а не текст. Ширина шире меры строки — url длинные. */
.sources{margin-top:64px; padding-top:34px; border-top:1px solid rgba(var(--line),.1)}
.sources h2{font-family:var(--fh); font-weight:400; font-size:22px; letter-spacing:-.015em;
  color:var(--ink); margin:0 0 6px}
.sources .note{font-size:13px; color:var(--ink-3); margin:0 0 24px; max-width:70ch}
.sources ol{margin:0; padding-left:0; list-style:none; counter-reset:src; max-width:86ch}
.sources li{
  position:relative; padding-left:38px; margin-bottom:13px;
  font-size:14px; line-height:1.55; color:var(--ink-2);
}
.sources li::before{
  counter-increment:src; content:counter(src); position:absolute; left:0; top:1px;
  min-width:26px; text-align:right;
  font-family:var(--fm); font-size:11px; color:var(--ink-3);
}
.sources a{color:var(--ink); text-decoration:underline;
  text-decoration-color:rgba(var(--line),.25); text-underline-offset:2px}
.sources a:hover{text-decoration-color:rgba(var(--warm),1)}
/* пометка коммерческого интереса источника — включая наш собственный */
.sources .int{font-family:var(--fm); font-size:10px; letter-spacing:.06em; color:var(--ink-3);
  display:block; margin-top:3px}

/* ═══ РЕВИЗИЯ ═══
   Дата правки видна, потому что мы будем править. Публикация без ревизии делает вид,
   что не менялась, — это то же число без даты замера. */
.revision{
  margin-top:44px; padding:18px 22px; background:var(--s1); border-radius:var(--r);
  border:1px solid rgba(var(--line),.08);
  font-family:var(--fm); font-size:11px; line-height:1.7; letter-spacing:.03em; color:var(--ink-3);
}
.revision b{font-weight:500; color:var(--ink-2)}

/* ═══ ОТВЕТ АВТОРУ — вместо бутафорских комментариев ═══ */
.reply{margin-top:34px; display:flex; align-items:center; gap:16px; flex-wrap:wrap}
.reply p{margin:0; font-size:14px; color:var(--ink-2); max-width:52ch}

/* ═══ ШАПКА СТАТЬИ: сплит — текст слева, визуал справа ═══
   Раскладка Влада. У Crafty заголовок во всю ширину, а под ним картинка 2:1 — читатель
   сначала получает украшение и только потом суть. Здесь суть и визуал стоят рядом.
   Опирается на выверенный `.hero-split` выше: визуал выровнен по верхней линии букв
   заголовка (57px, считано по метрикам kicker+h1, а не подобрано на глаз). */
.art-head{padding:72px 0 46px; border-bottom:1px solid rgba(var(--line),.08); margin-bottom:46px}
.art-head h1{font-size:50px; max-width:22ch; margin-bottom:20px}
.art-head .lede{font-size:18px; max-width:58ch; margin-bottom:26px}
/* мета-строка шапки: дата · время чтения · объём. Моно и тихо — это паспорт работы. */
.art-meta{
  display:flex; flex-wrap:wrap; align-items:center; gap:7px 16px;
  font-family:var(--fm); font-size:11px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--ink-3);
}
.art-meta .dot{width:3px; height:3px; border-radius:50%; background:rgba(var(--line),.22); flex:none}

/* ═══ ТЕЛО + ПУЛ-КВОТА СПРАВА ═══
   Пул-квота стоит справа и липнет при прокрутке — как у Crafty (col-5, sticky). Под неё
   уже есть `.aside` (sticky top:96px), здесь только сетка и типографика цитаты.
   ⚠️ 1fr для колонки цитаты, а не фиксированные 320px: тело держит меру 68ch само,
   и на широком окне фиксированная колонка оставляла бы пустой коридор между ними. */
/* ⚠️ Колонка текста = РОВНО мера строки, а не доля от контейнера.
   Было `1.62fr`: колонка выходила 658px, а `max-width:68ch` резал текст до 585px —
   73px пустовали ВНУТРИ колонки, и правая полоса недополучала их же.
   Дробные доли тут вообще неуместны: мера строки задаётся ЗНАКАМИ, а не процентом
   от окна, иначе при другой ширине окна она молча уезжает.
   ⛔ Меру НЕ расширяем: по обзору литературы (Visible Language) и Dyson & Haselgrove
   лучшее ПОНИМАНИЕ даёт 55-75 знаков; 95 читаются быстрее, но не понятнее, и длинные
   строки читатели стабильно называют наименее удобными. 68ch уже в норме. */
.art-grid{display:grid; grid-template-columns:minmax(0,68ch) minmax(240px,1fr);
  gap:56px; align-items:start}
.art-quote{position:sticky; top:96px}
.art-quote blockquote{
  margin:0; padding-left:22px; border-left:2px solid rgba(var(--warm),.5);
  font-family:var(--fh); font-weight:400; font-size:19px; line-height:1.42;
  letter-spacing:-.012em; color:var(--ink);
}
.art-quote figcaption{margin-top:16px; padding-left:24px}
.art-quote .qname{font-family:var(--fh); font-weight:600; font-size:14px; color:var(--ink)}
.art-quote .qrole{font-family:var(--fm); font-size:10px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-3); margin-top:3px}

@media (max-width:1080px){
  /* цитата уходит под текст: при сужении она сжимается в 3-4 слова на строку и
     перестаёт читаться как цитата */
  .art-grid{grid-template-columns:1fr; gap:38px}
  .art-quote{position:static; max-width:62ch}
}
@media (max-width:960px){
  .art-head{padding:52px 0 34px; margin-bottom:34px}
  .art-head h1{font-size:34px; max-width:100%}
  .art-head .lede{font-size:17px}
  .art-body{font-size:16px; line-height:1.68; max-width:100%}
  .art-body h2{font-size:23px; margin:44px 0 14px}
  .art-body pre{font-size:12px; padding:16px 16px}
  .fig.wide{width:100%}
  .pub-title{font-size:20px; max-width:100%}
  .pub-prov .sp{margin-left:0}
}


/* ═══ КАРТОЧКА СО ЗНАКОМ В ШАПКЕ ═══
   Просьба Влада: знак в шапке не должен висеть на канве голым — он получает такую же
   поверхность, как портрет основателя на company.html. Своего стекла НЕ заводим: это
   `.card` плюс центрирование, поэтому объём и ховер приходят из общего компонента.
   ⚠️ padding перебивает карточный (28/24/30): у знака воздух считается от букв, а не
   от текстового блока, иначе локап прижимается к верхнему канту. */
/* ⚠️ Подложка СНЯТА (20.08, решение Влада). Сначала знак сидел на `.card` — это лечило
   плоскость шапки, но белый прямоугольник под буквами спорил с самим знаком: марка должна
   лежать НА канве, чтобы гекс-паттерн просвечивал, ровно как корпоративный локап на
   остальных страницах. Карточки остаются у КОНТЕНТА (публикация, правила) — там поверхность
   несёт работу, а под марку она не нужна.
   ⇒ здесь только раскладка и оптическое выравнивание, никакой поверхности. */
.mark-card{
  display:flex; flex-direction:column; align-items:center; justify-self:center;
  text-align:center; gap:14px;
  /* ⭐ Вертикаль — СЕТКОЙ, а не отступом. Прежде здесь стоял выверенный `margin-top:46px`,
     и это была скрытая мина: подобранное число верно ровно для текущей длины заголовка и
     лида, а изменится текст — знак поедет, и никто не поймёт почему.
     `.hero-split` выставлен в `align-items:start`, поэтому переопределяем только себя:
     знак центрируется по вертикальной середине текстового блока — так же, как по
     горизонтали его центрирует `justify-self`. Формулировка Влада: «верх, низ — края,
     и середина центр, так же как мы по горизонтали равняем».
     ⇒ Тронется текст — центровка пересчитается сама. */
  align-self:center;
  /* Сдвиг вправо: колонка знака шире самого знака, и при чистом центрировании он смотрелся
     прижатым к тексту. При `justify-self:center` левый отступ сдвигает на эту величину. */
  margin-left:34px;
}
@media(max-width:960px){
  /* в одну колонку сдвиг вправо превращается в перекос — снимаем */
  .mark-card{margin-left:0; align-self:auto}
}
.mark-card .blk{font-size:34px}
/* ⚠️ Обязательно: кегль знака задаётся ЗДЕСЬ, а не инлайном в разметке. Правило
   `.mark-vs .blk{font-size:1em}` лежит ниже в файле и при равной весомости перебивает
   строку выше — без этой строки знак унаследовал бы 15px от body и съёжился. */
.mark-card .mark-vs{font-size:34px}
/* подпись под знаком: что это за раздел. Моно и тихо — как `.l2` у основного локапа. */
.mark-card .mc-note{
  font-family:var(--fm); font-size:10px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-3); line-height:1.5; max-width:24ch;
}

/* ═══ ЗНАК WORD|5 vs PROD|5 — ЛЕСТНИЦА ═══
   Раскладка Влада, набросок дословно:
       WORD|5
             vs
        PROD|5
   Три ступени по диагонали, «vs» вынесено вправо между полюсами. Это афишный приём
   (постер матча), и он работает лучше столбика со стрелкой: стрелка говорит «переход»,
   а нам нужно «противостояние» — расхождение между сказанным и отгруженным и есть тема.

   Почему не по центру: центрированная пара читается как два равных бренда в одном лого.
   Лестница задаёт направление чтения сверху-слева вниз-вправо, и «vs» попадает в оптический
   центр композиции, а не висит подписью.

   Все отступы в `em` от кегля знака — блок масштабируется одним `font-size`, как `.blk`. */
/* ══════════════════════════════════════════════════════════════════════════════
   ЗНАК WORD|5 vs PROD|5 — ИЗОЛИРОВАННЫЙ БЛОК, ОДНА РУЧКА

   Решение Влада: не ковыряться в общем лейауте, а замкнуть знак в свой контейнер.
   Правильно — и вот путь, которым сюда пришли, чтобы никто не пошёл им заново.

   Что было не так. Я трижды крутил отступы против НЕВИДИМОЙ КОРОБКИ: строка текста
   всегда выше своих букв, потому что шрифт добавляет полулиньяж — половину сверху,
   половину снизу. У прописных выносных элементов вниз нет, поэтому нижняя половина
   выглядит пустой прибавкой к отступу. Симметричные .92em давали видимую асимметрию,
   а отрицательное поле подвал не убрало, а натянуло PROD поверх него.

   ⛔ ОТВЕРГНУТО: `text-box: trim-both cap alphabetic`. Свойство существует и звучит
   ровно как лечение, но по резолюции CSS Working Group оно **не меняет вклад инлайна
   в высоту строки** — обрезает только область покраски (csswg-drafts#10834). Буквы у нас
   инлайны внутри `inline-flex`, значит высота не сожмётся. Вторая резолюция добивает:
   обрезка не заходит дальше края атомарного инлайна, а разделитель `|` у нас
   `display:inline-block` — то есть именно атомарный инлайн (csswg-drafts#11472).
   ⇒ Для ЭТОГО знака свойство бесполезно. Проверено по первоисточнику, а не по памяти.

   ✅ ЧТО РАБОТАЕТ: `line-height`, равный доле высоты прописных. У Switzer она .72em и уже
   записана в шапке этого файла. При `line-height:.72` коробка строки становится равна
   буквам, а полулиньяж ПО ОПРЕДЕЛЕНИЮ делится пополам — значит буквы выступают за коробку
   одинаково сверху и снизу. Асимметрия исчезает структурно, метрики шрифта не нужны,
   поддержка — везде.

   ⇒ Крутить ОДНО число: --gap. Больше значений знака нигде нет.
      ориентир: .40em тесно · .50em сейчас · .70em свободно
   ══════════════════════════════════════════════════════════════════════════ */
.mark-vs{
  /* РУЧКИ 1 и 2 — воздух, РАЗДЕЛЬНО сверху и снизу от связки.
     ⚠️ Я сводил их в одну и был неправ. Коробки строк действительно равны высоте прописных,
     но ЧЕРНИЛА внутри каждой коробки сидят на своей высоте: верхняя строка — Switzer с
     цифрой на 3.02em, связка — моноширинный со своими метриками. Равный зазор между
     КОРОБКАМИ даёт неравный зазор между БУКВАМИ. Поэтому два значения — это не костыль,
     а следствие того, что строки набраны разными шрифтами.
     Верхнее больше нижнего по замеру глазами Влада: «тянуть WORD вверх, воздуха чуть
     больше, чтобы было как внизу». */
  --gap-top:.62em;    /* WORD|5 → VS */
  --gap-bottom:.5em;  /* VS → PROD|5 */
  --cap:.72;          /* доля высоты прописных у Switzer — из шапки файла */
  /* РУЧКА 2 — ОПТИЧЕСКОЕ ПОЛОЖЕНИЕ БУКВ «vs» внутри своего места.
     Влад поймал глазами то, чего я не видел: «дело не в низе и верхе, а в середине самой vs».
     Механика: прописные стоят от базовой линии вверх до высоты прописных, а место под
     выносные вниз остаётся пустым НИЖЕ базовой линии. Коробка строки центрируется по области
     содержимого, куда этот пустой подвал входит ⇒ чернила сидят ВЫШЕ центра своей коробки,
     и связка липнет к верхнему слову, сколько ни правь зазор. Зазором это не лечится в
     принципе — потому три предыдущие попытки и мимо.
     ⚠️ Вторая моя ошибка, признаю здесь же: `.72` — доля прописных у SWITZER, а «vs» набрано
     МОНОШИРИННЫМ. У него своя доля и свои ascent/descent, я их не мерил ⇒ ниже приближение.
     Сдвиг сделан через `position:relative`, а НЕ отступом: относительное смещение не участвует
     в раскладке, поэтому зазоры остаются симметричными и две ручки не мешают друг другу.
     ориентир: .04em выше · .09em сейчас · .16em ниже */
  --vs-shift:.09em;
  display:inline-flex; flex-direction:column; align-items:center;
  /* ⛔ `gap` НЕ используется: он одинаков с обеих сторон по определению, а нам нужны разные.
     Воздух задан полями связки — она одна, значит два поля описывают оба зазора. */
  /* изоляция: внутренняя типографика знака не зависит от страницы и не влияет на соседей */
  contain:layout style;
}
/* Коробка строки = высота прописных. Работает и для строки знака, и для «vs»:
   у каждой считается от СВОЕГО кегля, поэтому пропорция сохраняется на любом масштабе. */
.mark-vs .blk{font-size:1em; line-height:var(--cap)}
.mark-vs .l1{line-height:var(--cap)}
.mark-vs .vs{
  font-family:var(--fm); font-weight:500; font-size:.92em; line-height:var(--cap);
  letter-spacing:.22em; text-transform:uppercase; color:var(--ink-3);
  /* ⚠️ та же компенсация, что у `.l2`: трекинг добавляет отступ ПОСЛЕ последней буквы,
     и без гашения центрированное «vs» съезжает влево на эту величину. */
  /* воздух с обеих сторон — двумя раздельными значениями. Правый край гасит трекинг. */
  margin:var(--gap-top) -.22em var(--gap-bottom) 0;
  /* оптическая посадка — вне раскладки, зазоры не трогает */
  position:relative; top:var(--vs-shift);
}
/* ⭐ Кегль «vs» НЕ придуман. Прежде здесь стоял Switzer курсивом на .4em — моя выдумка,
   и на 18px она вырождалась в блоху сбоку. Правильное число выведено из пропорции самого
   знака: подпись `.l2` относится к высоте прописных верхней строки как .92/(2.9×.72) ≈ 0.44.
   Ставим тот же кегль .92em — тот, которым набрано TECHNOLOGIES. Отсюда же вес 500, моно,
   трекинг .22em, капс и цвет `--ink-3`: связка — элемент ВТОРОГО уровня, а второй уровень
   у нас уже описан. Не изобретаем то, что решено в главном локапе. */
/* ⛔ Прозрачность верхнего полюса СНЯТА. В знаке со «vs» пригашенная сторона читается как
   «проигравший», то есть лого начинает утверждать вывод до текста. Пусть утверждает статью,
   а знак только ставит вопрос. Равный вес честнее и композиционно устойчивее. */

/* ⚠️ ОПТИКА ЛОКАПОВ НА «D» — требует твоего глаза, значения ниже поставлены расчётом.
   Выверенные зазоры `.blk` выведены под «E» перед линией: правая кромка «E» — прямой штрих
   на всю высоту, поэтому слева от линии зазор больше, справа меньше. У `PROD` и `WORD`
   последняя буква «D»: её правая кромка КРУГЛАЯ, в точке касания линии она отходит внутрь,
   и при том же зазоре линия визуально «отваливается» от буквы. Компенсация: левый зазор
   уменьшен с .115em до .086em (−25%), потому что круглая кромка сама создаёт видимый воздух. */
.blk.lk-d .l1 .rule{margin-left:.086em; margin-right:.062em}
/* трекинг ослаблен: в «PROD»/«WORD» подряд идут O и D — два круглых знака, и при −.03em
   они начинали слипаться сильнее, чем «ARE» */
.blk.lk-d .l1 .b1{letter-spacing:-.022em}

/* ═══ ЗНАК КАК КАРТИНКА ═══
   Знак собирается КОНТУРАМИ скриптом `aio-enterprise/scripts/build_mark_word_vs_prod.py`
   и лежит в `assets/marks/word-vs-prod.svg`. Правки геометрии — там, а не здесь.
   Почему ушли с CSS-локапа именно для этого знака: вертикаль в CSS считается по коробкам
   строк, а у Switzer буквы занимают 0.680 em при высоте строки 1.230 em — то есть 45%
   строки пустота, и распределяет её браузер. Отступами эту пустоту не убрать, обрезка
   `text-box` для инлайнов вклад в высоту не меняет. В SVG базовые линии стоят по
   координатам, зазор считается от края чернил, поэтому воздух сверху и снизу равен
   по построению (расхождение 0.0000).
   ⚠️ Правила `.mark-vs` выше стали неиспользуемыми. Оставлены до утверждения знака как
   путь отхода; после «ок» — снять, иначе это мёртвый код. */
/* Масштаб знака — одно число. 340px против прежних 300: при 300 знак читался легче
   корпоративного локапа на соседних страницах, хотя несёт три строки вместо одной. */
.mark-img{display:block; width:100%; max-width:340px; height:auto}

/* ═══ ЗНАК ВЫПУСКА В ШАПКЕ СТАТЬИ ═══
   Гекс с римской цифрой — своя марка у каждой статьи (`build_mark_note.py`). Уже, чем
   знак раздела: там три строки в ширину, здесь одна фигура, и на 340px гекс выглядел бы
   тяжелее заголовка. */
.mark-img.mark-note{max-width:158px}

/* ═══ ТАБЛИЦА В ТЕЛЕ СТАТЬИ ═══
   Язык реестра, а не сетки: волосяные линии между строками, шапка на утопленной
   поверхности — тот же приём, что у `.reg` и у шапок таблиц в остальных страницах.
   ⛔ Без вертикальных линий и без зебры: и то, и другое рисует решётку, а решётка
   спорит с гекс-паттерном канвы. */
.art-table{
  width:100%; border-collapse:collapse; margin:28px 0;
  font-size:15px; line-height:1.5;
}
.art-table th{
  text-align:left; padding:11px 14px; background:var(--sunken);
  font-family:var(--fm); font-size:11px; font-weight:500; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-3);
  border-bottom:1px solid rgba(var(--line),.1);
}
.art-table td{
  padding:13px 14px; color:var(--ink-2); vertical-align:top;
  border-bottom:1px solid rgba(var(--line),.07);
}
.art-table tr:hover td{background:rgba(var(--warm),.03)}
/* ⚠️ таблица шире меры строки — иначе колонки сжимаются до двух слов и читать нечего */
.art-body .art-table{width:min(100%, 860px)}
@media(max-width:960px){
  .art-table{font-size:14px; display:block; overflow-x:auto; white-space:nowrap}
}

/* ══════ СТАТЬЯ FEED: смысловые блоки, карты мысли, путь ══════
   Перенесено из песочницы `feed/_proto-tone-a` 20.08.2026. Каждое решение — от замера,
   а не от вкуса; замеры указаны рядом. Правила идут в конце файла, потому что часть их
   перекрывает ранние (сетка, ширина контейнера, отступы заголовков).                    */

/* ── Сетка 70/30 и ширина. Замер: 1ch у Inter при 18px = 11.36px ⇒ при контейнере 1320
   текст получает 829px = 73ch (норма 55-75, идеал Bringhurst 66).
   ⛔ Второй ограничитель меры снят: `max-width:68ch` резал колонку до 772px, и доля
   выходила 68/32 вместо заявленных 70/30 — один факт должен жить в одном месте.
   ⚠️ Расширяем ТОЛЬКО контейнер статьи: `.bar` (навбар) и `.fbar` (футер) исключены,
   шапка сайта утверждена и её трогать нельзя.                                          */
.container:not(.bar):not(.fbar){max-width:1320px}
.art-grid{grid-template-columns:minmax(0,70fr) minmax(0,30fr)}
.art-grid .art-body{max-width:none}

/* ⛔ Гасим `scroll-behavior:smooth` из начала файла: он действует и на переход к хэшу ПРИ
   ЗАГРУЗКЕ, из-за чего страница «прыгала» — открывалась сверху и тут же уезжала вниз через
   всё тело. Плавность на клик даёт scrollIntoView в скрипте, опция JS сильнее этого правила. */
html{scroll-behavior:auto}

/* ⛔ ЯКОРЯ. Навбар `sticky; top:0` высотой 65px, а `scroll-margin-top` не был задан — по
   спецификации браузер ставит цель перехода вплотную к верху окна, и шапка её накрывала.
   Ссылки работали, но приводили к заголовку, скрытому под навбаром. 88px = 65 + 23 воздуха. */
.art-body h2[id], .sblock[id], .src-list[id]{scroll-margin-top:88px}

/* ── БЛОК СМЫСЛА (уровень 1). Границы авторские: h2 / h3 / --- уже стоят в тексте.
   Единый зазор `--pad-in` держит и периметр блока, и промежутки между картами: раньше
   было три разных числа (36 по бокам, 32 сверху, 12 между) и карты «болтались в рамке». */
:root{--sblock-bg:#F7F5F1; --mind-bg:#FFFFFF; --pad-in:12px}
.sblock{position:relative; background:var(--sblock-bg); border:1px solid rgba(255,255,255,.55);
  border-radius:10px; padding:var(--pad-in); margin:0;
  box-shadow:0 1px 2px rgba(22,25,29,.04), 0 0 0 1px rgba(22,25,29,.055)}
.sblock>*:last-child{margin-bottom:0}
.sblock>.mind:last-child{margin-bottom:0}
.sblock-n{position:absolute; left:-2px; top:-11px; font-family:var(--fm); font-size:10px;
  letter-spacing:.14em; color:var(--ink-3); background:var(--sblock-bg); padding:0 6px}
.sblock>h2{margin-top:0}
.sblock>h3{margin-top:0}
/* абзац вне карты обязан стоять на той же вертикали, что текст внутри карт */
.sblock>p{padding:0 18px; margin-bottom:var(--pad-in)}

/* ── КАРТА МЫСЛИ (уровень 2). Границы тоже авторские: жирный зачин или дата — то, чем
   автор сам открывает мысль. Замер: 37 карт, одна зацепка на 99 слов (было на 289;
   у Anthropic 78, Cloudflare 103, NVIDIA 116).
   ⚠️ Тень с ОТРЫВОМ, а не прижатая: замер показал, что «сероватость» давал не фон
   (разница #FFFEFC → #FFFFFF всего 0.83% яркости), а тень в 1px без рассеивания.
   ⛔ Значения активной кнопки навигации (0 3px 8px / .09) целиком не взяты — она на ОДИН
   выделенный элемент, а карт 37: на всех сразу это грохот.                              */
.mind{background:var(--mind-bg); border-radius:7px; padding:14px 18px;
  margin:0 0 var(--pad-in);
  box-shadow:0 2px 5px rgba(22,25,29,.055), 0 0 0 1px rgba(22,25,29,.10)}
.mind>*:first-child{margin-top:0}
.mind>*:last-child{margin-bottom:0}
.mind p+p{margin-top:14px}
/* ⭐ ВТЯЖКА первой строки — книжная норма: глаз, дойдя до конца абзаца, получает
   физическую метку начала следующего и не ищет её заново.
   ⚠️ Считаем ПОРЯДОК, а не соседство: `p+p` пропускал 13 абзацев — те, что идут после
   списка или выноски, то есть там, где метка нужнее всего. */
.mind p:not(:first-of-type){text-indent:1.15em}

/* ── ШАПКА ВСТУПЛЕНИЯ: первая фраза статьи в роли заголовка раздела. Гарнитура и кегль
   как у h2 — роль та же. Точка в конце остаётся: это фраза автора, а не наш заголовок.
   ⛔ Моно-вставка на дате здесь снята: в заголовочной гарнитуре она читалась сбоем. */
.blead{font-family:var(--fh); font-weight:400; font-size:27px; line-height:1.24;
  letter-spacing:-.018em; color:var(--ink); padding:0 18px; margin:0 0 var(--pad-in)}
.blead strong{font-weight:500}
.mono-d{font-family:var(--fm); font-size:.88em; letter-spacing:.01em}

/* ── ВЁРСТКА ВНУТРИ КАРТ — язык из нашего же рендерера Crafty (ArticleContent.tsx).
   Замер того рендерера: 105 пунктов в 15 статьях, 96% с жирным лидом, воздух между
   пунктами 32px. Пункт там — мини-блок, а не строка перечня; у нас было 12px.
   ⛔ Смысловые иконки у каждого пункта (shield-check, layers, code…) не перенесены:
   набора иконок на лендинге нет, это отдельный ассет-слой. Вместо иконки — наш гекс,
   тот же знак, что в треке и на швах: язык один, ассет уже есть.                        */
.mind ul, .mind ol{margin:18px 0 6px; padding-left:0; list-style:none}
.mind li{position:relative; padding-left:30px; margin-bottom:26px; line-height:1.62}
.mind li:last-child{margin-bottom:6px}
.mind ul>li::before{
  content:''; position:absolute; left:2px; top:.52em; width:11px; height:12px;
  background:rgba(var(--warm),.85);
  -webkit-clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);
  clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);
}
/* нумерованный список сохраняет цифру: там порядок несёт смысл */
.mind ol{counter-reset:mli}
.mind ol>li{counter-increment:mli}
.mind ol>li::before{content:counter(mli); position:absolute; left:0; top:.06em;
  font-family:var(--fm); font-size:11px; font-weight:500; color:var(--ink-3);
  width:20px; text-align:right}
.mind li>strong:first-child{font-weight:600; color:var(--ink)}

/* ── ВЫНОСКА: полоса слева + лёгкая заливка (приём `highlight` из рендерера Crafty).
   ⚠️ Оттенок ослаблен: в одной карте бывает ТРИ выноски (раздел «Prompts are not
   controls»), и заметность каждой умножается — заливка .055 отличалась от белого на 7.3%
   яркости, текст между пятнами терялся. Теперь 3.2%, полоса с .9 до .42.               */
.mind .callout, .art-body .callout{
  margin:20px 0; padding:15px 18px 15px 20px;
  border-left:2px solid rgba(var(--warm),.42);
  border-radius:0 8px 8px 0; background:rgba(var(--warm),.022);
  font-size:16.5px; line-height:1.6;
}
.mind .callout p:last-child, .art-body .callout p:last-child{margin-bottom:0}

/* ── ЗАГОЛОВКИ: отступ сверху вдвое больше, чем снизу — приём и у нас (mt-16 при mt-6),
   и у Palantir. Заголовок притягивается к СВОЕМУ тексту, а не висит между блоками.
   ⚠️ h3 поднят 17 → 20px: подзаголовок был МЕЛЬЧЕ текста, который озаглавливает, и
   держался только весом — там, где подразделов подряд четыре, они читались как жирные
   абзацы, а не как ступень.                                                            */
.art-body h2{margin:0 0 12px}
.art-body h3{font-size:20px; margin:34px 0 12px}

/* ── ЗНАК-ШОВ между блоками смысла. Зазор 34px: при 22px границы читались, но глаз не
   успевал отдохнуть. Воздух до и после равный — иначе знак «прилипает» к одному блоку и
   читается как его подпись, а не как граница.                                          */
.dvd{display:flex; align-items:center; gap:16px; margin:34px 0}
.dvd-line{flex:1; height:1px; background:rgba(var(--line),.12)}
.dvd-hex{width:22px; height:23px; display:block; flex:none; overflow:visible}

/* ── ПРАВАЯ ПОЛОСА: комментарий сверху, путь под ним, sticky на обёртке.
   ⚠️ `align-items:start` у сетки обязателен, иначе sticky не работает: растянутый на всю
   высоту элемент прилипать не может — ему некуда двигаться внутри своей ячейки.         */
.art-rail{position:sticky; top:88px}
.track{margin-top:26px}
.tr-head{font-family:var(--fm); font-size:9px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--ink-3); margin:0 0 12px 2px}
/* Предел высоты: на окне ниже ~800px полоса не влезает, sticky прижимается и низ трека
   обрезается молча. Теперь трек прокручивается сам, а скрипт держит активную станцию в виду. */
/* ⛔ `overflow-x:hidden` задан ЯВНО. По спецификации при `overflow-y:auto` вторая ось со
   значением `visible` трактуется как `auto` — то есть горизонтальная полоса появлялась сама,
   без нашего участия: вертикальная полоса отнимает ширину, содержимое становится на пиксель
   шире, и браузер рисует ещё и горизонтальную. Замер: scrollWidth 346 при clientWidth 345 на
   трёх ширинах из четырёх — ровно тонкая полоса под станциями.
   ⚠️ `scrollbar-gutter:stable` держит место под полосу заранее, чтобы её появление не дёргало
   ширину станций при прокрутке. */
.tr-body{position:relative; max-height:calc(100vh - 340px);
  overflow-y:auto; overflow-x:hidden; scrollbar-gutter:stable;
  overscroll-behavior:contain; scrollbar-width:thin; padding-right:2px}
/* линия пути проходит по центру гексов, иначе «протыкает» станции не по оси */
.tr-line{position:absolute; left:25px; top:14px; bottom:14px; width:1px;
  background:rgba(var(--line),.16)}
/* ⭐ Каждая станция — карта. ⚠️ Карту у самого трека при этом СНЯЛИ: иначе вышло бы три
   уровня вложенности (полоса → карта трека → карта станции), а в статье их два.         */
.tr-st{display:flex; align-items:flex-start; gap:11px; padding:9px 11px; margin-bottom:7px;
  text-decoration:none; position:relative; color:var(--ink-3);
  background:var(--mind-bg); border-radius:7px;
  box-shadow:0 1px 2px rgba(22,25,29,.03), 0 0 0 1px rgba(22,25,29,.07);
  transition:color .16s, box-shadow .18s, transform .18s, background .16s}
.tr-st:last-child{margin-bottom:0}
.tr-hex{width:23px; height:24px; flex:none; display:block; margin-top:1px}
.tr-hex-s{padding:6px 0}
/* ⚠️ `overflow-wrap:anywhere` — заголовки разделов авторские, в них попадаются длинные
   неразрывные куски («out-of-band», arXiv-номера). Без переноса такое слово расширяет
   станцию и снова включает горизонтальный скролл, теперь уже по содержимому. */
.tr-t{font-size:12.5px; line-height:1.34; color:inherit; padding-top:4px;
  overflow-wrap:anywhere}
/* три состояния: впереди лежит ровно · пройдено легло глубже · сейчас приподнялось */
.tr-st.is-past{color:rgba(22,25,29,.40); background:#FAF8F5;
  box-shadow:inset 0 1px 2px rgba(22,25,29,.04), 0 0 0 1px rgba(22,25,29,.05)}
.tr-st:hover{color:var(--ink-2); transform:translateX(2px)}
.tr-st.is-on{color:var(--ink); background:#FFFFFF; transform:translateX(3px);
  box-shadow:0 3px 8px rgba(22,25,29,.09), 0 0 0 1px rgba(22,25,29,.13)}
.tr-st.is-on .tr-t{font-weight:600}

/* ── КОД И ТАБЛИЦА: внутренний скролл законен и намеренный.
   Код переносить нельзя — перенос меняет смысл строки, поэтому у `<pre>` остаётся
   прокрутка по горизонтали. Но она не должна цеплять страницу: `overscroll-behavior-x`
   не даёт жесту прокрутки внутри блока уехать на документ (на трекпаде и на телефоне это
   выглядит как «страницу дёрнуло в сторону»).
   ⚠️ Замер 20.08.2026: три блока кода и одна таблица шире колонки — на 900px это +138 и
   +30 пикселей. Это не дефект вёрстки, это природа содержимого. */
.art-body pre, .art-body .art-table{overscroll-behavior-x:contain}
/* у самого документа горизонтальной прокрутки быть не должно ни при каких обстоятельствах:
   один вылезший элемент иначе сдвигает всю страницу, и причину потом ищут долго */
body{overflow-x:hidden}

/* ── список источников как раздел статьи */
.src-list{margin:0; padding-left:0; list-style:none; counter-reset:sl}
.src-list li{position:relative; padding-left:34px; margin-bottom:13px; counter-increment:sl;
  font-size:14px; line-height:1.55; color:var(--ink-2)}
.src-list li::before{content:counter(sl); position:absolute; left:0; top:.1em;
  font-family:var(--fm); font-size:11px; color:var(--ink-3); width:24px; text-align:right}
.src-list .int{display:block; font-family:var(--fm); font-size:10.5px; color:var(--ink-3);
  letter-spacing:.02em; margin-top:2px}

/* ── узкие экраны: путь уходит под текст, карты теряют лишние поля */
@media (max-width:1080px){
  .art-rail{position:static}
  .tr-body{max-height:none; overflow:visible}
}
@media (max-width:960px){
  .container:not(.bar):not(.fbar){max-width:100%}
  .sblock{border-radius:8px}
  .blead{font-size:22px}
  .mind{padding:12px 14px}
  .sblock>p{padding:0 14px}
  .blead{padding:0 14px}
  .mind li{margin-bottom:20px}
  .dvd{margin:26px 0}
}

/* ═══ КАРТОЧКА ПРОДУКТА — тот же приём, что `.person-feature` ═══
   Продукты были строками таблицы (`a.row`): единственные ссылки в блоке, а на вид — текст.
   Здесь они становятся карточками с той же стеклянной поверхностью, что у карточки
   основателя, и знак продукта так же ВЫСТУПАЕТ за край, а не заперт в рамке.
   ⛔ Своих значений тени и стекла не вводим — повторяем компонент, иначе через месяц
   получим два похожих, но разных объёма на одном сайте. */
.prod-card{
  position:relative; display:flex; align-items:center; gap:30px;
  background:rgba(255,255,255,.55);
  -webkit-backdrop-filter:blur(16px); backdrop-filter:blur(16px);
  border:1px solid rgba(255,255,255,.6);
  box-shadow:0 24px 48px -26px rgba(22,25,29,.5), inset 0 1px 0 rgba(255,255,255,.7);
  border-radius:16px;
  padding:26px 30px;
  margin-bottom:22px;
  text-decoration:none; color:inherit;
  transition:transform .18s, box-shadow .18s, border-color .18s;
}
.prod-card:last-child{margin-bottom:0}
/* ссылка обязана отзываться: карточка чуть поднимается, тень уходит глубже */
.prod-card:hover{
  transform:translateY(-2px);
  border-color:rgba(255,255,255,.8);
  box-shadow:0 30px 56px -26px rgba(22,25,29,.55), 0 0 0 1px rgba(var(--warm),.22),
             inset 0 1px 0 rgba(255,255,255,.75);
}
/* знак продукта: колонка фиксированной ширины, выступает за карточку сверху и снизу —
   ровно как снимок основателя (`margin:-22px 0`) */
.prod-card .pc-mark{
  flex:0 0 132px; margin:-20px 0; position:relative;
  display:flex; align-items:center; justify-content:center;
  background:var(--s2);
  border:1px solid rgba(255,255,255,.6);
  outline:1px solid rgba(var(--line),.06);
  border-radius:14px; padding:22px 16px; min-height:104px;
  box-shadow:0 20px 40px -18px rgba(22,25,29,.34);
}
.prod-card .pc-mark img{display:block; width:100%; height:auto; max-height:46px; object-fit:contain}
/* у Ruby знака нет — стоит вордмарк ARE|5, как и было в строке */
.prod-card .pc-mark .rmini{display:inline-flex; align-items:baseline; font-family:var(--fh)}
.prod-card .pc-body{flex:1; min-width:0}
.prod-card .pc-head{display:flex; align-items:baseline; gap:12px; margin-bottom:4px}
.prod-card .pc-name{font-family:var(--fh); font-weight:600; font-size:21px; color:var(--ink);
  letter-spacing:-.014em}
.prod-card .pc-sub{font-family:var(--fm); font-size:10px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--ink-3)}
.prod-card .pc-desc{font-size:15px; line-height:1.58; color:var(--ink-2); margin:8px 0 14px}
.prod-card .pc-foot{display:flex; align-items:center; gap:14px}
.prod-card .arrow{margin-left:auto; color:var(--ink-3); transition:transform .18s, color .18s}
.prod-card:hover .arrow{color:var(--ink); transform:translateX(3px)}

@media (max-width:760px){
  .prod-card{flex-direction:column; align-items:flex-start; gap:18px; padding:22px}
  .prod-card .pc-mark{flex:none; width:112px; margin:-14px 0 0}
}

/* блок «что внутри» в карточке продукта: отбит волосяной линией, кегль на ступень ниже
   описания — это второй уровень чтения, для того, кто уже заинтересовался */
.prod-card .pc-inside{
  margin:14px 0 16px; padding-top:14px;
  border-top:1px solid rgba(var(--line),.12);
}
.prod-card .pc-inside .pc-lbl{
  display:block; font-family:var(--fm); font-size:9.5px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--ink-3); margin-bottom:7px;
}
.prod-card .pc-inside p{font-size:14px; line-height:1.62; color:var(--ink-2); margin:0}
.prod-card .pc-inside em{font-style:normal; font-weight:600; color:var(--ink)}
