/* ============================================================
   лента по электронике — тема «electronics»
   один файл, чистый CSS, без сборки, без CSS для JS.
   шрифты системные. внешних запросов нет ни одного.
   тема светлая; тёмная описана, но выключена — см. ниже.
   радиус 0 везде. ни одной тени, ни одного градиента.
   адаптив без брейкпоинтов: clamp() + flex-wrap.
   ============================================================ */

/* ── шрифты ────────────────────────────────────────────────────────────────
 *
 * ДО ЭТОГО ТЕМА НЕ ВОЗИЛА НИ ОДНОГО ШРИФТА, И ЭТО БЫЛА ОШИБКА.
 *
 * Объявлено было `Helvetica Neue` — которого на Windows нет вовсе. То есть
 * лента рисовалась Arial у одних, Helvetica Neue у других, и вся сдержанность
 * темы, которая держится на пропорциях, зависела от того, с какой машины
 * пришёл читатель.
 *
 * Golos Text нарисован в «Паратайпе» под кириллицу, а не приделал её к
 * латинице. Для ленты, где текст русский и длинный, это решает.
 *
 * Файл ВАРИАТИВНЫЙ: 400 и 600, которые просит тема, лежат в одном, и веса
 * между ними тоже. Поэтому файлов четыре, а не восемь.
 *
 * `font-display: swap` намеренно: пока шрифт едет, текст читается системным.
 * Пустая страница в ожидании шрифта — плохой обмен для ленты заметок.
 *
 * Подмножества те же, что у остальных шрифтов проекта. Русскому читателю
 * приедут кириллица и латиница — около 60 КБ; расширенные не приедут вовсе,
 * пока в тексте не встретится знак из них.
 */
@font-face {
    font-family: 'Golos Text';
    font-style: normal;
    font-weight: 400 900;
    font-display: swap;
    src: url('/assets/fonts/golos-text-cyrillic.woff2') format('woff2');
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
    font-family: 'Golos Text';
    font-style: normal;
    font-weight: 400 900;
    font-display: swap;
    src: url('/assets/fonts/golos-text-cyrillic-ext.woff2') format('woff2');
    unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
    font-family: 'Golos Text';
    font-style: normal;
    font-weight: 400 900;
    font-display: swap;
    src: url('/assets/fonts/golos-text-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Golos Text';
    font-style: normal;
    font-weight: 400 900;
    font-display: swap;
    src: url('/assets/fonts/golos-text-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Служебный слой. Файл уже лежит в проекте — им набрана админка, и своей
   кириллицей он отличается от системных Consolas и Menlo, которые у разных
   людей разные. */
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 400 500;
    font-display: swap;
    src: url('/assets/fonts/jetbrains-mono-cyrillic.woff2') format('woff2');
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 400 500;
    font-display: swap;
    src: url('/assets/fonts/jetbrains-mono-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


:root {
  /*
   * Только светлая — и это решение, а не недоделка.
   *
   * `light dark` здесь стояло, и системные элементы — полосы прокрутки, поля
   * ввода, выпадающие списки — переключались вслед за настройкой ОС. Пока
   * тёмная тема не выбрана осознанно, это значит, что часть посетителей видит
   * сайт иначе, чем видит его владелец, и разговор «а у меня по-другому»
   * начинается с выяснения, у кого какая система.
   *
   * Тёмная палитра ниже не удалена: она описана и проверена, просто не
   * включается сама. Вернуть — заменить условие у блока на
   * `@media (prefers-color-scheme: dark)` и `light` на `light dark` здесь.
   */
  color-scheme: light;

  --bg:    #eef1f5;
  --fg:    #1a2230;
  --mut:   #56637a;
  --hair:  #d3d9e2;
  --plate: #e4e9f0;
  --acc:   #3b82f6;
  /* Чёрный вокруг кадра в полноэкранном режиме. Не часть палитры и не меняется
     с темой: это отсутствие света вокруг видео, а не цвет интерфейса. Имя ему
     дано, чтобы в плеере не осталось ни одного значения без названия. */
  --void:  #000;

  --sans: "Golos Text", "Helvetica Neue", Helvetica, "Segoe UI", Arial, system-ui, sans-serif;

  /* ── типографика ──────────────────────────────────────────────────────
     До этой правки в теме было семнадцать разных кеглей на две страницы:
     11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15, 16, 18, 21, 26 и четыре clamp.
     Пять из них приходились на один и тот же служебный слой — разница в
     полпикселя, которую никто не различит, но которая гарантирует, что
     следующая правка добавит восемнадцатый.

     Референс живёт на четырёх ступенях. У нас ролей больше: пак ответил на
     отсутствие предметной съёмки слоем технической аннотации, и он настоящий.
     Поэтому ступеней десять — но каждая названа, и одиннадцатую теперь надо
     заводить осознанно. */
  --t-micro:   13px;   /* подпись под кадром — мельче не бывает         */
  --t-label:   15px;   /* служебный слой: метки, крошки, подписи блоков */
  --t-data:    17px;   /* моноширинные данные: таблица, код, полосы     */
  --t-small:   18px;   /* вспомогательный текст гротеском              */
  --t-body:    21px;   /* основной текст                               */
  --t-lead:    26px;   /* подзаголовок раздела                         */
  --t-quote:   clamp(24px, 2.4vw, 32px);
  --t-title:   clamp(24px, 2.6vw, 36px);
  --t-head:    clamp(30px, 4vw, 56px);
  --t-display: clamp(56px, 7.4vw, 104px);

  /* Межстрочных было девять. Стало четыре — по назначению, а не по вкусу. */
  --lh-display: 0.86;
  --lh-tight:   1.1;
  --lh-snug:    1.3;
  --lh-body:    1.5;
  --lh-code:    1.6;   /* коду нужен воздух: в моноширинном строка плотнее */

  /* Разрядка служебного слоя гуляла от 0.02 до 0.07em без причины. */
  --ls-label:   0.06em;
  --ls-tight:  -0.02em;
  --ls-display: -0.045em;

  --mono: "JetBrains Mono", ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "DejaVu Sans Mono", monospace;

  /* шаг: 4 8 14 22 34 52 72 104 */
  --s1: 4px;  --s2: 8px;  --s3: 14px; --s4: 22px;
  --s5: 34px; --s6: 52px; --s7: 72px; --s8: 104px;

  --pad-y: clamp(18px, 3.4vw, 44px);
  --pad-x: clamp(16px, 3.6vw, 52px);
  --gap-col: clamp(16px, 3vw, 40px);
  --col-index: clamp(88px, 11vw, 168px);
}

/*
 * Тёмная палитра. Сейчас НЕ ВКЛЮЧАЕТСЯ автоматически: условие ждёт явного
 * `data-theme="dark"` на корне, а его никто не ставит. Значения сохранены —
 * они выверены по эталону дизайна, и выбрасывать их, чтобы через месяц
 * подбирать заново, было бы расточительством.
 */
:root[data-theme="dark"] {
  :root {
    --bg:    #0d1219;
    --fg:    #dfe6ef;
    --mut:   #93a1b5;
    --hair:  #2a3547;
    --plate: #141b25;
    --acc:   #5b9bff;
  }
}

/* ---------- база ---------- */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 400 var(--t-small)/var(--lh-body) var(--sans);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;              /* страница вбок не едет никогда */
  overflow-wrap: break-word;
}

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

a { color: inherit; text-decoration: none; }
a:hover { color: var(--acc); }

h1, h2, h3, p, ul, figure, pre, table { margin: 0; }
ul { padding: 0; list-style: none; }

button { font: inherit; border-radius: 0; }

.wrap {
  /* Колонка по центру страницы, как на самом teenage.engineering: содержимое
     стоит серединой экрана, а не жмётся к левому краю. Ширина подобрана по
     референсу — там колонка занимает около трёх пятых широкого экрана. */
  max-width: 1180px;
  margin: 0 auto;
  padding: var(--pad-y) var(--pad-x) var(--s7);
}

/* служебный моноширинный слой — всё в нижнем регистре */
.mono {
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: var(--ls-label);
  color: var(--mut);
  text-transform: lowercase;
}
.num { font-variant-numeric: tabular-nums; }
.strong { font-weight: 400; border-bottom: 1px solid var(--acc); }

/* ---------- шапка сайта ---------- */

.site-head {
  display: flex; flex-wrap: wrap;
  gap: 18px 32px; align-items: baseline; justify-content: space-between;
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--hair);
}
.site-head__brand { display: flex; flex-wrap: wrap; gap: 6px 18px; align-items: baseline; }
.site-head__name { font-size: var(--t-small); }                 /* имя — с прописной */
.site-head__tag  { font-family: var(--mono); font-size: var(--t-label); color: var(--mut); letter-spacing: var(--ls-label); }

.nav { display: flex; flex-wrap: wrap; gap: 4px 20px; align-items: baseline; font-size: var(--t-label); color: var(--mut); }
.nav__link.is-current { color: var(--fg); border-bottom: 1px solid var(--fg); padding-bottom: 1px; }

.index-bar {
  display: flex; flex-wrap: wrap; gap: 6px 24px;
  padding-top: 10px;
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--mut);
}
.index-bar__last { margin-left: auto; }

/* ---------- лента ---------- */

.feed { margin-top: clamp(28px, 5vw, 72px); }

.entry {
  display: flex; flex-wrap: wrap; gap: var(--gap-col);
  padding: var(--s4) 0 var(--s5);
  border-top: 1px solid var(--hair);
}

.entry__index { flex: 0 0 auto; width: var(--col-index); }
.entry__num {
  font-family: var(--mono);
  font-size: var(--t-display);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
}
.entry__flag { display: flex; align-items: center; gap: 7px; margin-top: 12px; }
.entry__dot  { width: 7px; height: 7px; background: var(--acc); }
.entry__note { font-family: var(--mono); font-size: var(--t-label); color: var(--mut); letter-spacing: var(--ls-label); margin-top: 12px; }

.entry__body { flex: 1 1 340px; min-width: 0; max-width: 640px; }
/* Запись, показанная в ленте целиком. Меру и верхний отступ задаёт лента, а не
   страница записи: там `.prose` открывает статью и отбивается от шапки, здесь
   она идёт сразу под заголовком. */
.entry__full { margin-top: 14px; }
/* Меру и верхний отступ задаёт лента, а не страница записи: там `.prose`
   открывает статью и отбивается от шапки, здесь она идёт сразу под заголовком
   и живёт в колонке ленты. */
.entry__full .prose { padding-top: 0; max-width: none; }
.entry__title {
  display: block;
  /*
   * Полужирный — единственный тяжёлый элемент на светлой странице.
   *
   * Было 400: пак объяснял это тем, что заголовки «не жирные, а просто
   * крупные». На короткой странице так и есть, но на длинной прокрутке лента
   * теряет опорные точки — глазу не за что зацепиться, и записи сливаются в
   * ровное полотно. У референса вес и кегль работают вместе, у нас работал
   * только кегль.
   *
   * Подзаголовки внутри текста (`prose h2`) остаются лёгкими намеренно: стань
   * они тоже полужирными, начали бы спорить с заголовком записи.
   */
  font-weight: 600;
  font-size: var(--t-title);
  line-height: var(--lh-tight); letter-spacing: var(--ls-tight);
  text-wrap: pretty;
}
.entry__deck { margin-top: 12px; color: var(--mut); max-width: 46ch; text-wrap: pretty; }

.entry__meta {
  flex: 0 1 156px; min-width: 120px;
  display: flex; flex-direction: column; gap: 5px;
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--mut);
}
.entry__date { color: var(--fg); }

.entry__figure { margin-top: var(--s4); }

/* артефакт 1: мини-таблица (запись 03) */
.minitab { max-width: 430px; font-family: var(--mono); font-size: var(--t-data); letter-spacing: 0; }
.minitab__row {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 6px 0; border-top: 1px solid var(--hair);
}
.minitab__row:last-child { border-bottom: 1px solid var(--hair); }
.minitab__row--head { color: var(--mut); font-size: var(--t-label); letter-spacing: var(--ls-label); }

/* артефакт 2: линейка полос (запись 02) */
.bars { max-width: 480px; border-top: 1px solid var(--hair); padding-top: 10px; }
.bar { display: flex; align-items: center; gap: 10px; padding: 2.5px 0; }
.bar__label { flex: 0 0 62px; font-family: var(--mono); font-size: var(--t-label); color: var(--mut); letter-spacing: var(--ls-label); }
.bar__track { flex: 1 1 auto; height: 7px; background: var(--plate); position: relative; }
.bar__fill  { position: absolute; inset: 0 auto 0 0; background: var(--fg); }
.bar__val   { flex: 0 0 54px; text-align: right; font-family: var(--mono); font-size: var(--t-data); }
.bars__note { border-top: 1px solid var(--hair); margin-top: 10px; padding-top: 6px; font-family: var(--mono); font-size: var(--t-label); color: var(--mut); letter-spacing: var(--ls-label); }

/* артефакт 3: матрица 8×8 (запись 01) */
.matrix-wrap { display: flex; flex-wrap: wrap; gap: 18px; align-items: flex-end; }
.matrix { display: grid; grid-template-columns: repeat(8, 13px); gap: 3px; }
.matrix__cell { width: 13px; height: 13px; background: var(--plate); }
.matrix__cell.is-l1 { background: var(--hair); }
.matrix__cell.is-l2 { background: var(--mut); }
.matrix__cell.is-l3 { background: var(--fg); }
.matrix__legend { display: flex; flex-direction: column; gap: 4px; font-family: var(--mono); font-size: var(--t-label); color: var(--mut); letter-spacing: var(--ls-label); }
.matrix__legend b { font-weight: 400; color: var(--fg); }

.feed-foot {
  display: flex; flex-wrap: wrap; gap: 8px 24px;
  border-top: 1px solid var(--hair); padding-top: 12px;
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--mut);
}
.feed-foot__right { margin-left: auto; }

/* ---------- запись ---------- */

.post__crumb { font-family: var(--mono); font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--mut); padding: clamp(22px, 4.2vw, 60px) 0 clamp(18px, 3vw, 34px); }
/* Кликаются не все сегменты: «лента» и рубрика ведут, номер записи и дата —
   нет. В теме ссылка по цвету неотличима от текста, поэтому различает их
   волосяная линия — та же, что под ссылками в тексте записи. Без неё узнать,
   что нажимается, можно только наведением, а на телефоне и наведения нет. */
.post__crumb a { border-bottom: 1px solid var(--hair); }
.post__crumb a:hover { border-color: var(--acc); }

.post__head { display: flex; flex-wrap: wrap; gap: var(--gap-col); align-items: flex-start; }
.post__index {
  flex: 0 0 auto; width: var(--col-index);
  font-family: var(--mono);
  font-size: var(--t-display); line-height: var(--lh-display); letter-spacing: var(--ls-display);
}
.post__headtext { flex: 1 1 380px; min-width: 0; max-width: 720px; }
.post__title {
  font-weight: 600;
  font-size: var(--t-head);
  line-height: var(--lh-tight); letter-spacing: var(--ls-tight); text-wrap: pretty;
}
.post__deck { margin-top: 16px; font-size: var(--t-body); color: var(--mut); max-width: 48ch; text-wrap: pretty; }

.post__meta {
  display: flex; flex-wrap: wrap; gap: 14px 36px;
  margin-top: clamp(24px, 4vw, 52px);
  padding: 12px 0;
  border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair);
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--mut);
}
.post__meta b { font-weight: 400; color: var(--fg); }

/* текст записи */
/* Мера в знаках, а не в пикселях: с выросшим кеглем 66ch стало бы шире самой
   колонки. Строка держится в тех же 66 знаках, просто буквы крупнее. */
.prose { max-width: 66ch; padding-top: clamp(28px, 4.4vw, 56px); }
/* Отбивка между абзацами — ровно одна строка основного текста.
   Померено на референсе: там зазор 20 px при интерлиньяже 20 px, то есть
   строка в строку. У нас стояло 18 px при строке в 31.5 — чуть больше
   половины, и абзацы слипались тем сильнее, чем крупнее был кегль. Через
   calc, а не числом: сдвинется кегль или интерлиньяж — отбивка пойдёт следом,
   и переписывать её не придётся. */
.prose > * + * { margin-top: calc(var(--t-body) * var(--lh-body)); }
.prose p  { font-size: var(--t-body); line-height: var(--lh-body); }
.prose h2 { font-size: var(--t-lead); font-weight: 400; letter-spacing: var(--ls-tight); line-height: var(--lh-tight); }
.prose ul { display: flex; flex-direction: column; gap: 9px; }
.prose li { display: flex; gap: 14px; font-size: var(--t-body); line-height: var(--lh-body); }
.prose li::before { content: "—"; flex: 0 0 auto; font-family: var(--mono); font-size: var(--t-micro); color: var(--mut); padding-top: 5px; }
.prose a { border-bottom: 1px solid var(--hair); }
.prose a:hover { border-color: var(--acc); }

.sect-label {
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--mut);
  text-transform: lowercase;
}
/* Раздел отбивается заметно больше абзаца, иначе граница раздела перестаёт
   читаться границей: 34 px против выросших 31.5 — это уже почти одно и то же. */
.prose > .sect-label { margin-top: var(--s6); margin-bottom: 10px; }
.prose > .sect-label + h2 { margin-top: 0; }

.pullquote { border-top: 1px solid var(--hair); margin-top: var(--s6); padding-top: 20px; }

/* ── выноски ──────────────────────────────────────────────────────────────
 *
 * `> [!tip]`, `> [!note]`, `> [!warning]` — то, что вставляют три кнопки
 * панели редактора. До этого на сайте они выходили обычной цитатой, в тексте
 * которой печаталось «[!tip]».
 *
 * Отличаются от цитаты полосой слева и подписью, а не заливкой: в теме нет ни
 * одной заливки, и первая же выбилась бы. Цвет полосы несёт единственный
 * смысл — насколько это срочно, — поэтому «внимание» единственное отходит от
 * общей палитры.
 */
.callout {
    border-left: 2px solid var(--hair);
    padding: 2px 0 2px 18px;
    margin-top: var(--s5);
}
.callout__label {
    font-family: var(--mono); font-size: var(--t-label);
    letter-spacing: var(--ls-label); color: var(--mut);
    text-transform: lowercase; padding-bottom: 6px;
}
.callout p { font-size: var(--t-body); line-height: var(--lh-body); }
.callout p + p { margin-top: calc(var(--t-body) * var(--lh-body)); }

/* Совет — акцент темы: это подсказка, а не тревога. */
.callout--tip { border-left-color: var(--acc); }
.callout--tip .callout__label { color: var(--acc); }

/* Заметка — тот же приглушённый слой, что у всей служебной разметки. */
.callout--note { border-left-color: var(--mut); }

/* Внимание — единственное место в теме, где появляется красный. Ровно
   поэтому он и читается: если бы он был ещё где-то, здесь он ничего бы не
   значил. */
.callout--warning { border-left-color: #9b2c22; }
.callout--warning .callout__label { color: #9b2c22; }
.pullquote__label { font-family: var(--mono); font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--mut); padding-bottom: 12px; }
.pullquote p { font-size: var(--t-quote); line-height: var(--lh-snug); letter-spacing: var(--ls-tight); max-width: 34ch; text-wrap: pretty; }

/* блоки во всю меру записи */
.block { max-width: 920px; padding-top: clamp(30px, 4.4vw, 52px); }
.block__head {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6px 20px;
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--mut);
  padding-bottom: var(--s2);
}
.block__foot {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6px 24px;
  font-family: var(--mono); font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--mut);
  padding-top: var(--s2);
}

/* картинки */
.figure { padding-top: clamp(30px, 4.4vw, 56px); }
.figure__frame { background: var(--plate); border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair); }
/* КАРТИНКА ПОКАЗЫВАЕТСЯ ЦЕЛИКОМ, А НЕ ОБРЕЗАЕТСЯ.
 *
 * Здесь стояла жёсткая высота с `object-fit: cover`, взятая из пака: там
 * снимки были подобранные и широкие, и полоса им шла. У личного блога снимки
 * с телефона — вертикальные, квадратные, какие вышли, — и полоса срезала им
 * верх и низ. Автор не мог этого ни увидеть заранее, ни поправить.
 *
 * Теперь высота своя, а обрезка — осознанный выбор автора: `"полоса"`. */
.figure__frame img { width: 100%; height: auto; display: block; }

/* Подпись под иллюстрацией — по центру, как в референсе: там она стоит
   серединой кадра, а не по его левому краю. Табличные и кодовые подписи это
   не трогает: у них две колонки, «что» слева и «чем» справа. */
.figure figcaption.block__foot,
.figure__col figcaption {
  justify-content: center;
  text-align: center;
}
/* «полоса» — прежнее поведение, теперь по требованию: широкий кадр
   постоянной высоты. Годится схемам и раскладкам, где важна полоса, а не
   пропорция снимка. */
.figure--band .figure__frame img { height: clamp(220px, 34vw, 460px); object-fit: cover; }

/* ПО УМОЛЧАНИЮ КАРТИНКА ИДЁТ ПО ШИРИНЕ ТЕКСТА.
 *
 * Раньше умолчанием была полная мера записи. Снимок, идущий внутри
 * рассуждения, чаще объясняет соседний абзац, чем открывает раздел, — а
 * широкий кадр посреди текста рвёт чтение: глаз, дойдя до его края,
 * возвращается не к той строке. */
.figure { max-width: 66ch; }

/* «широкая» — во всю меру записи, для кадра, который открывает раздел. */
.figure--full { max-width: none; }

/* Очень высокий снимок в ленте — беда: он выталкивает следующую запись за
   экран, и лента перестаёт быть лентой. Ограничиваем высотой окна, ширину
   при этом не трогаем — пропорция сохраняется. */
.figure__frame img { max-height: 88vh; object-fit: contain; }
.figure__pair { display: flex; flex-wrap: wrap; gap: clamp(12px, 2vw, 24px); padding-top: clamp(20px, 3vw, 34px); }
.figure__col  { flex: 1 1 300px; min-width: 0; }
.figure__col .figure__frame img { height: clamp(160px, 20vw, 260px); }

/* таблица замеров — прокручивается внутри себя */
.table-scroll { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }
.datatable {
  border-collapse: collapse; width: 100%; min-width: 560px;
  font-family: var(--mono); font-size: var(--t-data); font-variant-numeric: tabular-nums;
}
.datatable th {
  font-weight: 400; text-align: right; white-space: nowrap;
  font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--mut);
  padding: 8px 18px; border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair);
}
.datatable td { text-align: right; padding: 9px 18px; border-bottom: 1px solid var(--hair); white-space: nowrap; }
.datatable th:first-child, .datatable td:first-child { text-align: left; padding-left: 0; }
.datatable th:last-child,  .datatable td:last-child  { padding-right: 0; }
.datatable tr:last-child td { border-bottom: 0; }
.datatable .is-tolerance td { color: var(--mut); }
.datatable .is-over { color: var(--acc); }     /* единственное место, где акцент в числах */

/* блок кода */
.code {
  background: var(--plate);
  border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.code pre { padding: 16px 18px; font-family: var(--mono); font-size: var(--t-data); line-height: var(--lh-code); white-space: pre; }

/*
 * СЕКЦИЯ ИЗ ПАКА ДИЗАЙНА, перенесена целиком.
 *
 * Правится не здесь: обновится пак — берём новую секцию, а не сверяем правку
 * за правкой. Значения размеров и порогов — часть контракта плеера, а не вкус.
 *
 * Своё в ней ровно одно, и это вынужденно: `--void` вместо `#000` у заливки
 * полного экрана. По приёмке в плеере не должно остаться ни одного цвета без
 * имени, а чёрный вокруг кадра — не часть палитры и не меняется с темой.
 */

/* ============================================================
   встроенное видео, свой плеер
   состояние живёт в атрибуте [data-state] на .player:
   idle → buffering → playing → paused → ended
   плюс [data-bar="off"] — панель ушла по бездействию.
   js только переставляет эти атрибуты и ширину заполнения;
   ни одного стиля из js.
   роли: i пуск/пауза + шкала (обведены, интерактивны)
         ii текущее время (цвет текста)
         iii длительность, полный экран, кодек (приглушены)
   ============================================================ */

.player { position: relative; border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair); background: var(--plate); }
.player__stage { position: relative; width: 100%; aspect-ratio: 16 / 9; overflow: hidden; }
.player__stage video { width: 100%; height: 100%; object-fit: cover; cursor: pointer; }

/* --- панель: состав ролей --- */
.player__bar {
  position: absolute; inset: auto 0 0 0;
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 8px clamp(8px, 1.6vw, 14px);
  padding: 10px clamp(8px, 1.6vw, 12px);
  background: var(--bg); border-top: 1px solid var(--hair);
  transition: opacity 140ms linear;
}
.player__bar > * { min-width: 0; }
.player__btn {
  flex: 0 0 auto; width: 38px; height: 38px; padding: 0;
  border: 1px solid var(--hair); background: var(--bg); color: var(--fg);
  font-family: var(--mono); font-size: 12px; line-height: 1; cursor: pointer;
}
.player__btn:hover, .player__full:hover { border-color: var(--acc); color: var(--acc); }
.player__time { flex: 0 0 auto; font-family: var(--mono); font-size: 11px; font-variant-numeric: tabular-nums; color: var(--fg); }   /* роль ii */
.player__dur  { flex: 0 0 auto; font-family: var(--mono); font-size: 11px; font-variant-numeric: tabular-nums; color: var(--mut); } /* роль iii */
.player__track { flex: 1 1 60px; min-width: 40px; height: 38px; display: flex; align-items: center; cursor: pointer; position: relative; }
.player__rail { width: 100%; height: 3px; background: var(--hair); position: relative; transition: height 120ms linear; }
.player__buf  { position: absolute; inset: 0 auto 0 0; width: 0; background: var(--mut); }   /* загружено вперёд */
.player__fill { position: absolute; inset: 0 auto 0 0; width: 0; background: var(--acc); }   /* пройдено — единственный акцент */
.player__full {
  flex: 0 1 auto; height: 38px; padding: 0 clamp(6px, 1.4vw, 12px);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  border: 1px solid var(--hair); background: var(--bg); color: var(--mut);
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.06em; cursor: pointer;
}

/* --- 01 до включения: панели нет, шкале нечего показывать --- */
.player__start {
  position: absolute; left: 12px; bottom: 12px;
  width: 44px; height: 44px; padding: 0;
  border: 1px solid var(--hair); background: var(--bg); color: var(--fg);
  font-family: var(--mono); font-size: 13px; line-height: 1; cursor: pointer;
}
.player__start:hover { border-color: var(--acc); color: var(--acc); }
.player__badge {
  position: absolute; right: 12px; bottom: 12px;
  padding: 4px 7px; background: var(--bg); border: 1px solid var(--hair);
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.06em; color: var(--mut);
}
.player:not([data-state="idle"]) .player__start,
.player:not([data-state="idle"]) .player__badge { display: none; }
.player[data-state="idle"] .player__bar { display: none; }

/* --- 02 загрузка: процент вместо длительности, пуск без контраста --- */
.player[data-state="buffering"] .player__btn { color: var(--mut); }
.player[data-state="buffering"] .player__fill { width: 0 !important; }
.player__buflabel { display: none; flex: 0 0 auto; font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.06em; color: var(--mut); }
.player[data-state="buffering"] .player__buflabel { display: block; }
.player[data-state="buffering"] .player__dur { display: none; }

/* --- 04 панель ушла: остаётся волосяная линия прогресса --- */
.player__hair { position: absolute; inset: auto 0 0 0; height: 3px; background: var(--hair); opacity: 0; transition: opacity 140ms linear; }
.player__hair > i { position: absolute; inset: 0 auto 0 0; width: 0; background: var(--acc); }
.player[data-bar="off"] .player__bar { opacity: 0; pointer-events: none; }
.player[data-bar="off"] .player__hair { opacity: 1; }
/* пауза и конец панель не прячут никогда */
.player[data-state="paused"] .player__bar,
.player[data-state="ended"] .player__bar { opacity: 1; pointer-events: auto; }
.player[data-state="paused"] .player__hair,
.player[data-state="ended"] .player__hair { opacity: 0; }

/* --- 06 наведение и 08 фокус: цель растёт, когда в неё целятся --- */
.player__track:hover .player__rail,
.player__track:focus-visible .player__rail { height: 7px; }
.player__track:focus-visible { outline: 1px solid var(--acc); outline-offset: 2px; }
.player__btn:focus-visible, .player__full:focus-visible, .player__start:focus-visible { outline: 1px solid var(--acc); outline-offset: 2px; }
.player__bubble {
  position: absolute; bottom: 28px; left: 0; transform: translateX(-50%);
  display: none; padding: 3px 6px;
  background: var(--bg); border: 1px solid var(--hair);
  font-family: var(--mono); font-size: 10px; font-variant-numeric: tabular-nums; color: var(--fg);
  white-space: nowrap; pointer-events: none;
}
.player__track:hover .player__bubble { display: block; }

/* --- 07 конец: кадр гасится фоном страницы, а не темнотой --- */
.player__end { position: absolute; inset: 0; display: none; align-items: center; justify-content: center; gap: var(--s3); }
.player__end::before { content: ""; position: absolute; inset: 0; background: var(--bg); opacity: 0.84; }
.player__end > * { position: relative; }
.player[data-state="ended"] .player__end { display: flex; }
.player__replay {
  width: 44px; height: 44px; padding: 0;
  border: 1px solid var(--hair); background: var(--bg); color: var(--fg);
  font-family: var(--mono); font-size: 15px; cursor: pointer;
}
.player__endnote { font-family: var(--mono); font-size: 11px; letter-spacing: 0.06em; color: var(--mut); }

/* --- 09 во весь экран: те же роли, цели крупнее --- */
.player:fullscreen { border: 0; background: var(--void); }
.player:fullscreen .player__stage { height: 100vh; aspect-ratio: auto; }
.player:fullscreen .player__stage video { object-fit: contain; }
.player:fullscreen .player__bar { padding: 14px; }
.player:fullscreen .player__btn { width: 48px; height: 48px; font-size: 14px; }
.player:fullscreen .player__track { height: 44px; }
.player:fullscreen .player__rail { height: 4px; }
.player:fullscreen .player__time, .player:fullscreen .player__dur { font-size: 13px; }

/* --- 10 телефон: полный экран сжимается до значка, длительность уходит --- */
@media (max-width: 460px) {
  .player__full { width: 38px; padding: 0; justify-content: center; }
  .player__full span { display: none; }
  .player__full::after { content: "\2922"; font-size: 12px; }
  .player__dur { display: none; }
}

/*
 * ЗНАКИ ПЛЕЕРА — НАШ БЛОК, НЕ ПАКОВЫЙ.
 *
 * Пак ставит на кнопки текстовые глифы: `▶`, `❚❚`, `↻`, `⤢`. Рисует их
 * операционная система, и они разные — `▶` где-то узкий, где-то широкий, а
 * `⤢` местами не нарисован вовсе. Ради этого знаки и заказывались, и в паке
 * они пришли, но подключены не были.
 *
 * Подключены маской по `data-state`, а не подменой текста: скрипт продолжает
 * писать глиф, мы его только прячем кеглем. Драться со скриптом за
 * `textContent` значило бы, что при следующем переносе пака он снова победит.
 * А ещё глиф остаётся запасным видом, если файл знака не отдастся.
 *
 * `aria-label` кнопки скрипт обновляет сам — доступное имя от прятанья текста
 * не страдает.
 */
.player__btn, .player__start, .player__replay { font-size: 0; }
.player__btn::before, .player__start::before, .player__replay::before {
  content: "";
  display: block; width: 22px; height: 22px; margin: 0 auto;
  background-color: currentColor;
  -webkit-mask: var(--glyph) center / 22px 22px no-repeat;
  mask: var(--glyph) center / 22px 22px no-repeat;
}
.player__start,
.player[data-state="idle"] .player__btn,
.player[data-state="paused"] .player__btn { --glyph: url("/assets/themes/electronics/img/icon-play.svg"); }
.player[data-state="playing"] .player__btn,
.player[data-state="buffering"] .player__btn { --glyph: url("/assets/themes/electronics/img/icon-pause.svg"); }
.player__replay,
.player[data-state="ended"] .player__btn { --glyph: url("/assets/themes/electronics/img/icon-replay.svg"); }

/* На узком экране подпись «во весь экран» не помещается, и пак подставляет
   вместо неё глиф. Тот же знак, но настоящий. */
@media (max-width: 460px) {
  .player__full::after {
    content: "";
    display: block; width: 18px; height: 18px; margin: 0 auto;
    background-color: currentColor;
    -webkit-mask: url("/assets/themes/electronics/img/icon-fullscreen.svg") center / 18px 18px no-repeat;
    mask: url("/assets/themes/electronics/img/icon-fullscreen.svg") center / 18px 18px no-repeat;
  }
}

/* Картинка, которой нет: браузер показал бы свой сломанный значок — чужой и
   тревожный там, где ничего страшного не случилось. */
.prose img { background: var(--plate); }

/* полоса ключевых кадров */
.strip { display: flex; gap: 6px; padding-top: 10px; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.strip__item { flex: 0 0 auto; width: 132px; }
.strip__frame { background: var(--plate); border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair); }
.strip__frame img { width: 132px; height: 74px; object-fit: cover; }
.strip__t { font-family: var(--mono); font-size: var(--t-micro); color: var(--mut); letter-spacing: var(--ls-label); padding-top: 5px; font-variant-numeric: tabular-nums; }

/* подвал записи */
.post__nav {
  max-width: 920px; display: flex; flex-wrap: wrap; gap: 18px 40px; justify-content: space-between;
  margin-top: clamp(36px, 5vw, 72px); border-top: 1px solid var(--hair); padding-top: var(--s3);
}
.post__nav-prev { flex: 1 1 220px; min-width: 0; }
.post__nav-prev a { font-size: var(--t-small); line-height: var(--lh-snug); display: block; }
.post__nav-links { flex: 0 1 200px; display: flex; flex-direction: column; gap: 5px; font-family: var(--mono); font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--mut); }

/* печать: волосяные линии переживают, плеер и полоса кадров — нет */
@media print {
  body { background: #fff; color: #000; }
  .player__bar, .strip, .nav, .feed-foot { display: none; }
}
