/* ====================================================================
   tables.ninja — витрина платформы TN Services
   Мир: «Рабочий чертёж» (бриф направления — apps/gantt/.../layout.tsx).

   Из мира чертежа берётся ДИСЦИПЛИНА, а не костюм: вес линии несёт
   информацию, состояние читается без цвета, паспорт живёт в штампе
   в углу листа, числа моноширинные. Бумажной текстуры и карандашного
   зерна здесь нет намеренно.

   Красный карандаш — ОДНО значение на весь сайт: отклонение. Им
   помечен список «что у вас не сходится» и больше ничто.

   Значения ниже — собственная шкала ВИТРИНЫ, а не токены языка:
   tokens.css задаёт плотность рабочего экрана (кегль данных 13 px),
   и переносить её на страницу, которую читают, нельзя. Общее с языком —
   гарнитуры, графитовая шкала и правило «одна поверхность, линии».
   ==================================================================== */

/* --- ГАРНИТУРЫ ------------------------------------------------------
   ОБЪЯВЛЕНИЯ ЗДЕСЬ БОЛЬШЕ НЕТ (RUN-1, 21.08.2026). Четыре объявления гарнитур
   переехали в язык — packages/design/tokens/fonts.css, — а сюда
   приезжают копией `make site-fonts` вместе с самими файлами.
   Страницы подключают /fonts.css первым листом.

   Почему копией, а не ссылкой: витрина живёт в объектном хранилище
   отдельным доменом отказа, и тянуть стиль из чужого места значит
   поставить её доступность в зависимость от прода — ровно то, чего
   раздельные контуры и избегают. Расхождение копии с языком ловит
   `make site-fonts-check`.                                        */

/* --- ЛИСТ -----------------------------------------------------------
   Светлая тема — «белая печать». Тёмная — «синька», и она НЕ инверсия:
   на синьке линии светлые по синему грунту, как в цианотипии.       */

:root{
  --paper:#fbfbfa;
  --paper-2:#f4f4f2;
  --ink:#1b1b1a;
  --ink-2:#4a4a46;
  --ink-3:#6c6c68;
  --rule:#e3e3df;
  --rule-strong:#c9c9c4;
  --graphite:#3d3d3a;
  --pencil:#a52a24;          /* отклонение. Одно значение, других нет */
  --focus:#2f5bd0;
  --block:#1b1b1a;           /* поверхность главного действия */
  --block-ink:#fbfbfa;
  --block-hover:#000000;

  --font-text:"Golos Text",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  --font-mark:"Martian Mono",ui-monospace,SFMono-Regular,Menlo,monospace;

  --sheet:1000px;
  --measure:34em;
  --pad:clamp(20px,5vw,64px);
  color-scheme:light dark;
}

@media (prefers-color-scheme:dark){
  :root{
    --paper:#10243a;
    --paper-2:#16304a;
    --ink:#eaf0f6;
    --ink-2:#c2d3e2;
    --ink-3:#a8bdd0;
    --rule:#2c4661;
    --rule-strong:#3f5f7e;
    --graphite:#cddced;
    --pencil:#ff8f7d;        /* тот же смысл, кегль контраста на синьке */
    --focus:#8fb6ff;
    --block:#eaf0f6;
    --block-ink:#10243a;
    --block-hover:#ffffff;
  }
}

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

html{
  -webkit-text-size-adjust:100%;
  scrollbar-color:var(--rule-strong) transparent;
}

body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--font-text);
  font-size:18px;
  line-height:1.6;
  font-synthesis-weight:none;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

::selection{background:var(--ink);color:var(--paper)}

:focus-visible{
  outline:2px solid var(--focus);
  outline-offset:3px;
  border-radius:1px;
}

/* --- ЛИСТ И ЕГО РАМКА ----------------------------------------------
   Рамка чертежа существует только там, где для неё есть поле:
   на узком экране лист занимает окно целиком и рамка исчезает,
   а не поджимается к тексту.                                       */

.sheet{
  max-width:var(--sheet);
  margin:0 auto;
  padding:0 var(--pad);
}
@media (min-width:1080px){
  .sheet{
    border-inline:1px solid var(--rule-strong);
  }
}

/* --- ШАПКА ЛИСТА ----------------------------------------------------
   Одна строка: марка слева, навигация справа. Липкая, потому что
   действие «войти» обязано быть под рукой на длинной странице.     */

.head{
  position:sticky; top:0; z-index:10;
  background:var(--paper);
  border-bottom:1px solid var(--rule);
}
.head-in{
  max-width:var(--sheet); margin:0 auto; padding:14px var(--pad);
  display:flex; align-items:baseline; gap:24px;
}
.mark{
  font-family:var(--font-mark);
  font-size:13px; font-weight:600; font-stretch:78%;
  letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink); text-decoration:none; border:0;
  white-space:nowrap;
}
.head-nav{margin-left:auto; display:flex; gap:clamp(14px,3vw,26px); align-items:baseline}
.head-nav a{
  font-family:var(--font-mark);
  font-size:11px; font-weight:500; font-stretch:75%;
  letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink-3); text-decoration:none;
  padding-bottom:2px; border-bottom:1px solid transparent;
}
.head-nav a:hover{color:var(--ink); border-bottom-color:var(--ink)}
.head-nav a.here{color:var(--ink); border-bottom-color:var(--ink)}

/* Вход и регистрация прижаты к правому краю и отделены от разделов
   листа: это не навигация по странице, а два действия над аккаунтом.
   Разделитель — вертикальная волосяная линия, тот же приём, что
   делит графы штампа. */
.head-acts{
  display:flex; align-items:center; gap:14px; margin-left:24px;
  padding-left:24px; border-left:1px solid var(--rule);
}
.head-acts .login{
  font-family:var(--font-mark);
  font-size:11px; font-weight:500; font-stretch:75%;
  letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink-3); text-decoration:none;
  padding-bottom:2px; border-bottom:1px solid transparent;
  white-space:nowrap;
}
.head-acts .login:hover{color:var(--ink); border-bottom-color:var(--ink)}

/* На телефоне разделы листа из шапки уходят: страница читается одной
   прокруткой, и ссылка на секцию там не экономит ничего. Два действия
   над аккаунтом остаются — именно их ищут глазами. */
@media (max-width:639px){
  .head-nav{display:none}
  .head-acts{margin-left:auto; padding-left:0; border-left:0}
}

/* --- ТИПОГРАФИКА ----------------------------------------------------
   Иерархия читается кеглем с расстояния — правило, поднятое
   из отклонённого кандидата, а не украшение.                       */

h1,h2,h3{margin:0; font-weight:700; line-height:1.08; letter-spacing:-0.028em; text-wrap:balance}
h1{font-size:clamp(38px,6.4vw,66px)}
h2{font-size:clamp(26px,3.6vw,38px); line-height:1.12}
h3{font-size:clamp(20px,2.4vw,24px); font-weight:650; line-height:1.2; letter-spacing:-0.02em}

p{margin:0 0 20px; max-width:var(--measure)}
p:last-child{margin-bottom:0}

.lead{font-size:clamp(19px,2.1vw,23px); line-height:1.5; color:var(--ink-2); max-width:32em}
.note{font-size:16px; color:var(--ink-3); max-width:38em}
.strong{color:var(--ink); font-weight:600}

a{
  color:var(--ink);
  text-decoration:underline;
  text-decoration-thickness:1px;
  text-underline-offset:3px;
  text-decoration-color:var(--rule-strong);
  transition:text-decoration-thickness .12s linear, text-decoration-color .12s linear;
}
a:hover{text-decoration-thickness:2px; text-decoration-color:var(--ink)}

/* Имя изделия в заголовке — ссылка на его лист. Подчёркивание
   появляется только при наведении: постоянная линия под 34-м кеглем
   спорит с волосяными линиями листа и читается как ошибка набора. */
a.plain{color:inherit; text-decoration:none}
a.plain:hover{
  text-decoration:underline; text-decoration-thickness:2px;
  text-underline-offset:6px; text-decoration-color:var(--ink);
}

/* Подпись-надпись чертежа: моноширинная, узкая, прописными.
   Живёт слева от содержания или под ним, но НИКОГДА не над
   заголовком в роли надзаголовка.                                  */
.label{
  font-family:var(--font-mark);
  font-size:11px; font-weight:500; font-stretch:75%;
  letter-spacing:.13em; text-transform:uppercase;
  color:var(--ink-3);
  line-height:1.45;
}
.num{font-family:var(--font-mark); font-variant-numeric:tabular-nums; font-stretch:82%}

/* --- СЕКЦИИ: ОДНА ПОВЕРХНОСТЬ, РАЗДЕЛЁННАЯ ЛИНИЯМИ ------------------
   Не россыпь плиток. Плитка — остров со своими отступами; из островов
   складывается ощущение случайности (принцип 4 языка).             */

section{
  padding:clamp(56px,8vw,104px) 0;
  border-top:1px solid var(--rule-strong);
  /* Шапка липкая: без запаса якорь #products уезжает под неё. */
  scroll-margin-top:72px;
}
section > h2{margin-bottom:clamp(28px,4vw,44px)}

.hero{padding:clamp(52px,9vw,116px) 0 clamp(48px,7vw,88px); border-top:0}
.hero h1{margin-bottom:28px; max-width:14em}
.hero .lead{margin-bottom:36px}

/* --- ДЕЙСТВИЯ -------------------------------------------------------
   Главное действие — графитовый блок, а не цветная пилюля: цвет
   в этом языке занят смыслом, а не привлечением внимания.          */

.acts{display:flex; flex-wrap:wrap; gap:12px; align-items:center}
.btn{
  display:inline-block;
  font-family:var(--font-mark);
  font-size:12px; font-weight:600; font-stretch:80%;
  letter-spacing:.1em; text-transform:uppercase;
  padding:15px 26px; border-radius:2px;
  text-decoration:none; border:1px solid var(--block);
  transition:background-color .14s linear, color .14s linear, border-color .14s linear;
}
.btn-sm{padding:9px 15px; font-size:11px; letter-spacing:.09em}
.btn-solid{background:var(--block); color:var(--block-ink)}
.btn-solid:hover{background:var(--block-hover); border-color:var(--block-hover)}
.btn-line{background:transparent; color:var(--ink); border-color:var(--rule-strong)}
.btn-line:hover{border-color:var(--ink)}

/* --- ОТКЛОНЕНИЯ: ЕДИНСТВЕННОЕ МЕСТО КРАСНОГО КАРАНДАША -------------- */

.dev{list-style:none; margin:0; padding:0; max-width:44em}
.dev li{
  display:grid; grid-template-columns:22px 1fr; gap:16px; align-items:start;
  padding:18px 0; border-top:1px solid var(--rule);
  font-size:clamp(17px,1.9vw,19px); line-height:1.5;
}
.dev li:first-child{border-top:0; padding-top:0}
.dev svg{width:14px; height:14px; margin-top:.42em; color:var(--pencil); flex:none}

/* --- ПРОДУКТЫ -------------------------------------------------------
   Спецификация листа, а не витрина карточек: слева графа с родом,
   платформой и состоянием, справа — само изделие.                  */

.spec{border-top:1px solid var(--rule-strong)}
.item{
  display:grid; gap:clamp(18px,3vw,40px);
  padding:clamp(34px,5vw,56px) 0;
  border-bottom:1px solid var(--rule);
}
@media (min-width:860px){
  .item{grid-template-columns:190px 1fr}
}
.item-meta{display:flex; flex-direction:column; gap:10px}
.item-meta .state{
  display:inline-flex; align-items:center; gap:8px;
  font-family:var(--font-mark); font-size:11px; font-weight:600; font-stretch:75%;
  letter-spacing:.12em; text-transform:uppercase; color:var(--ink);
}
.item-meta .state::before{
  content:""; width:9px; height:9px; flex:none;
  border:1.5px solid var(--ink); border-radius:50%;
}
/* Состояние читается формой ДО цвета (D-229): открытое — залитый круг,
   строящееся — полый, и подпись словом стоит рядом в обоих случаях. */
.item-meta .state.open::before{background:var(--ink)}

.item h3{font-size:clamp(26px,3.2vw,34px); margin-bottom:16px}
.item .what{font-size:clamp(17px,1.9vw,19px); color:var(--ink-2); max-width:36em; margin-bottom:26px}

.asks{list-style:none; margin:0 0 28px; padding:0; max-width:40em; border-top:1px solid var(--rule)}
.asks li{
  padding:11px 0; border-bottom:1px solid var(--rule);
  font-size:16px; line-height:1.45; color:var(--ink);
}

.shot{margin:0 0 26px}
.shot img{display:block; width:100%; height:auto; border:1px solid var(--rule-strong)}
.shot figcaption{margin-top:10px; font-family:var(--font-mark); font-size:11px;
  font-stretch:75%; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-3)}

/* --- ДВУХКОЛОНОЧНАЯ ОПИСЬ -------------------------------------------
   Слева имя, справа что за ним стоит. Живёт на странице услуг
   («что остаётся у вас»). На витрине этим приёмом был набран раздел
   «Правила, по которым это сделано» — он убран 21.08.2026: правила
   визуального языка написаны словами разработчика, а стояли в слоте,
   где читателю нужна улика. Две живые строки из пяти вплавлены
   в блок «Кто это делает», остальное было манифестом.              */

.rules{border-top:1px solid var(--rule)}
.rule-row{
  display:grid; gap:6px 40px; padding:22px 0; border-bottom:1px solid var(--rule);
}
@media (min-width:760px){
  .rule-row{grid-template-columns:minmax(220px,1fr) 2fr; gap:0 40px; align-items:baseline}
}
.rule-row b{font-weight:650; font-size:17px; letter-spacing:-0.01em}
.rule-row span{color:var(--ink-2); font-size:16px; line-height:1.5}

/* --- УСЛУГИ: ТОТ ЖЕ ПРИЁМ, ЧТО У ПРОДУКТОВ -------------------------- */

.jobs{list-style:none; margin:0; padding:0; border-top:1px solid var(--rule)}
.jobs li{
  display:grid; gap:4px 40px; padding:20px 0; border-bottom:1px solid var(--rule);
}
@media (min-width:760px){
  .jobs li{grid-template-columns:minmax(200px,1fr) 2fr; gap:0 40px; align-items:baseline}
}
.jobs b{font-weight:650; font-size:17px}
.jobs span{color:var(--ink-2); font-size:16px; line-height:1.5}

/* --- ЛЕСТНИЦА ШАГОВ -------------------------------------------------
   Номер здесь несёт информацию: это порядок, а не украшение.       */

ol.steps{list-style:none; margin:0; padding:0; counter-reset:s; border-top:1px solid var(--rule)}
ol.steps li{
  counter-increment:s; position:relative;
  padding:22px 0 22px 52px; border-bottom:1px solid var(--rule);
  max-width:44em;
}
ol.steps li::before{
  content:counter(s,decimal-leading-zero);
  position:absolute; left:0; top:24px;
  font-family:var(--font-mark); font-size:12px; font-weight:600; font-stretch:75%;
  letter-spacing:.08em; color:var(--ink-3);
}
/* Последний шаг не подчёркивается: следом идёт блок со своей верхней
   линией, и две линии подряд читаются как пустая строка таблицы. */
ol.steps li:last-child{border-bottom:0}
ol.steps b{display:block; margin-bottom:4px; font-weight:650}
ol.steps span{color:var(--ink-2); font-size:16px; line-height:1.5}

/* --- ХРОНОЛОГИЯ ----------------------------------------------------- */

.tl{list-style:none; margin:0; padding:0; border-top:1px solid var(--rule); max-width:44em}
.tl li{
  display:grid; gap:2px 28px; padding:14px 0; border-bottom:1px solid var(--rule);
  font-size:16px;
}
@media (min-width:620px){
  .tl li{grid-template-columns:150px 1fr; gap:0 28px; align-items:baseline}
}
.tl .yr{font-family:var(--font-mark); font-size:12px; font-stretch:78%;
  font-variant-numeric:tabular-nums; letter-spacing:.06em; color:var(--ink-3); white-space:nowrap}

/* --- ИМЕНА КОМПАНИЙ -------------------------------------------------
   Сетка ячеек, а не облако пилюль и не строка с подчёркиваниями:
   пилюля — та же плитка, только меньше, а подчёркивание под каждым
   именем даёт обрубки разной длины и читается как брак печати.     */

.names{
  display:grid; grid-template-columns:repeat(auto-fill,minmax(148px,1fr));
  margin:0 0 20px; padding:0; list-style:none;
  border-top:1px solid var(--rule); border-left:1px solid var(--rule);
}
.names li{
  font-family:var(--font-mark); font-size:12px; font-weight:500; font-stretch:78%;
  letter-spacing:.08em; text-transform:uppercase; color:var(--ink);
  padding:13px 14px;
  border-bottom:1px solid var(--rule); border-right:1px solid var(--rule);
}

/* --- ЗНАК РУБЛЯ -----------------------------------------------------
   U+20BD нет ни в одном из четырёх подмножеств канона — ни в Golos
   Text, ни в Martian Mono. До правки канона знак приходит системным
   шрифтом, и без выравнивания он мельчит рядом с чертёжными цифрами.
   Требование на исправление — docs/ТЗ-материалы-продуктов.md, пункт 7. */
.rub{
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  font-size:.86em; font-weight:600; letter-spacing:0;
}

/* --- ЦЕНА ----------------------------------------------------------- */

.rate{
  font-family:var(--font-mark); font-stretch:80%; font-variant-numeric:tabular-nums;
  font-size:clamp(30px,4.6vw,46px); font-weight:600; letter-spacing:-0.01em;
  line-height:1.05; margin-bottom:14px;
}
.rate small{font-family:var(--font-text); font-size:19px; font-weight:400; color:var(--ink-3); letter-spacing:0}

/* --- КОНТАКТЫ ------------------------------------------------------- */

.contacts{list-style:none; margin:0; padding:0; border-top:1px solid var(--rule); max-width:34em}
.contacts li{padding:0; border-bottom:1px solid var(--rule)}
.contacts a{
  display:grid; grid-template-columns:110px 1fr; gap:20px; align-items:baseline;
  padding:16px 0; text-decoration:none; color:var(--ink);
}
.contacts a:hover .val{text-decoration:underline; text-decoration-thickness:2px; text-underline-offset:3px}
.contacts .val{font-size:17px}

/* --- ШТАМП ----------------------------------------------------------
   Паспорт листа прижат к нижнему правому углу, как на чертеже.
   Это единственное место, где страница называет себя целиком.      */

.stamp{
  margin-top:clamp(48px,7vw,96px);
  border-top:1px solid var(--rule-strong);
  display:flex; justify-content:flex-end;
}
.stamp-box{
  border:1px solid var(--rule-strong); border-top:0;
  display:grid; grid-template-columns:repeat(2,minmax(128px,1fr));
  width:100%;
}
@media (min-width:700px){
  .stamp-box{width:auto; grid-template-columns:repeat(4,minmax(128px,auto))}
}
.stamp-cell{
  padding:12px 18px 14px;
  border-left:1px solid var(--rule);
  border-top:1px solid var(--rule);
}
.stamp-cell:nth-child(-n+2){border-top:0}
@media (min-width:700px){
  .stamp-cell{border-top:0}
}
.stamp-cell:first-child{border-left:0}
@media (min-width:700px){
  .stamp-cell:first-child{border-left:0}
}
.stamp-cell .k{
  display:block; font-family:var(--font-mark); font-size:10px; font-weight:500; font-stretch:75%;
  letter-spacing:.14em; text-transform:uppercase; color:var(--ink-3); margin-bottom:5px;
}
.stamp-cell .v{
  font-family:var(--font-mark); font-size:13px; font-weight:600; font-stretch:80%;
  font-variant-numeric:tabular-nums; letter-spacing:.04em; color:var(--ink);
}
.stamp-cell .v a{color:inherit; text-decoration:none}
.stamp-cell .v a:hover{text-decoration:underline; text-decoration-thickness:2px; text-underline-offset:3px}

.colophon{
  padding:22px 0 clamp(40px,6vw,72px);
  font-size:14px; color:var(--ink-3); max-width:44em;
}

/* --- ЕДИНСТВЕННЫЙ АВТОРСКИЙ МОМЕНТ ----------------------------------
   Лист вычерчивается: верхняя линия проходит слева направо, следом
   поднимается содержание первого экрана. Один раз, при загрузке,
   из уже видимого состояния — не «появление из пустоты».           */

@media (prefers-reduced-motion:no-preference){
  html{scroll-behavior:smooth}
  .head{
    animation:draw .5s cubic-bezier(.16,1,.3,1) both;
  }
  .hero > *{
    animation:rise .62s cubic-bezier(.16,1,.3,1) both;
  }
  .hero > *:nth-child(1){animation-delay:.06s}
  .hero > *:nth-child(2){animation-delay:.13s}
  .hero > *:nth-child(3){animation-delay:.2s}
  .hero > *:nth-child(4){animation-delay:.27s}
  @keyframes draw{
    from{clip-path:inset(0 100% 0 0)}
    to{clip-path:inset(0 0 0 0)}
  }
  @keyframes rise{
    from{opacity:.001; transform:translateY(10px)}
    to{opacity:1; transform:none}
  }
}

/* --- ПЕЧАТЬ ---------------------------------------------------------- */

@media print{
  .head{position:static}
  .btn{border:1px solid #000; color:#000; background:transparent}
  a{text-decoration:none}
}
