/* Кондуит — оформление.
   Палитра типов задач — проверенный категориальный набор (8 слотов),
   светлая и тёмная темы заданы отдельными шагами, а не автоматической инверсией. */

:root {
  color-scheme: light dark;

  /* Непрозрачная поверхность осталась как запас: ею подменяется стекло там,
     где браузер не умеет размывать подложку, и там, где сквозь панель ничего
     просвечивать не должно. */
  --surface: #ffffff;
  --plane: #dde1ee;
  --ink: #0e0e14;
  --ink-2: #45454f;
  --ink-muted: #7c7c88;
  --grid: rgba(11, 11, 11, 0.10);
  --axis: rgba(11, 11, 11, 0.22);
  --border: rgba(255, 255, 255, 0.7);
  --border-strong: rgba(11, 11, 11, 0.16);
  --wash: rgba(255, 255, 255, 0.45);

  /* Подложка тихих кнопок — пилюль без рамки. На тёмной теме это белая вуаль,
     на светлой — чернильная: белое по белому не видно вовсе, и пилюля сливалась
     с панелью. У кнопки без рамки подложка и есть её граница, поэтому она
     обязана читаться в обеих темах. */
  --quiet: rgba(11, 11, 11, 0.055);
  --quiet-on: rgba(11, 11, 11, 0.10);

  --good: #067a3e;
  --bad: #d23b53;

  /* Матовое стекло. Панель — это заливка с прозрачностью плюс размытие того,
     что под ней; толщину даёт светлая грань поверху, а не рамка. */
  --pane: rgba(255, 255, 255, 0.64);
  --pane-2: rgba(255, 255, 255, 0.84);
  /* Две грани: светлая сверху и тёмная снизу. Вместе они читаются как толщина
     стекла — без них панель остаётся просто светлым прямоугольником. */
  --pane-edge: rgba(255, 255, 255, 1);
  --pane-edge-low: rgba(11, 11, 11, 0.05);
  /* Косой блик поверх панели: то, чем стекло отличается от заливки. */
  --sheen: rgba(255, 255, 255, 0.34);
  /* Одно значение на весь сайт. Если размытие где-то окажется дорогим —
     достаточно поставить здесь none, и стекло станет просто прозрачным. */
  --pane-blur: blur(18px);

  /* Пятна на подложке. Они лежат неподвижным слоем под всей страницей: двигать
     их нельзя — размытие панелей пересчитывалось бы каждый кадр.

     Цвета в них нет: это чистый свет. Он и подчёркивает стекло — сквозь панель
     видно, что под ней светлее, а по краям темнее. */
  --glow-1: rgba(255, 255, 255, 0.80);
  --glow-2: rgba(255, 255, 255, 0.55);
  --glow-3: rgba(255, 255, 255, 0.38);

  /* Цвета разделов — набор красок, а не круг оттенков: берлинская лазурь,
     киноварь, бутылочная зелень, охра, тирский пурпур, морская волна, баклажан
     и графит. Ни один не сидит на чистом спектральном тоне, и это главное: у
     краски тон всегда чуть сбит в сторону — синий уходит в зелень, красный в
     землю, — отчего она и выглядит краской, а не заливкой из палитры.

     Восьмой нарочно нейтральный. Ряд из восьми цветных ярлыков утомляет, а
     графит в нём работает паузой — приём старый и надёжный.

     Привязки «геометрия оранжевая» больше нет: цвет ничего не значит сам по
     себе, он только отличает раздел от раздела, и порядок в наборе выбран по
     тому, как тона живут рядом, а не по темам.

     Одним значением цвет раздела не описать: линия значка, заливка плашки и свет
     в её углу решают разные задачи. Отсюда три переменные на раздел.

     Выводить заливку из цвета линии пробовали дважды — и оба раза получалась не
     та глубина. Плашки, которые нравятся («Место», «Самый ценный плюс»,
     листок), собраны иначе: у них цвет задан прямо, глубоким и плотным, а свет
     в углу — другого, более светлого тона. Здесь то же самое, только восемь раз.

     --sN — линия значка, различается по темам: на светлой тёмная, на тёмной
     светлая. --fN — заливка плашки, глубокая. --gN — свет в углу, светлый тон
     той же семьи. */
  --s1: #1f5673;   /* берлинская лазурь */
  --s2: #b4442c;   /* киноварь */
  --s3: #2d6a45;   /* бутылочная зелень */
  --s4: #97701a;   /* охра */
  --s5: #8d2f63;   /* тирский пурпур */
  --s6: #167a74;   /* морская волна */
  --s7: #5b3f8f;   /* баклажан */
  --s8: #55606e;   /* графит */

  --f1: rgba(14, 48, 68, 0.94);
  --f2: rgba(112, 34, 20, 0.92);
  --f3: rgba(20, 58, 38, 0.94);
  --f4: rgba(86, 62, 12, 0.94);
  --f5: rgba(82, 20, 58, 0.92);
  --f6: rgba(10, 64, 62, 0.94);
  --f7: rgba(48, 30, 84, 0.92);
  --f8: rgba(38, 44, 54, 0.94);

  --g1: rgba(120, 205, 235, 0.40);
  --g2: rgba(255, 175, 130, 0.38);
  --g3: rgba(150, 225, 165, 0.34);
  --g4: rgba(255, 214, 140, 0.36);
  --g5: rgba(255, 155, 205, 0.34);
  --g6: rgba(125, 235, 220, 0.34);
  --g7: rgba(185, 155, 240, 0.36);
  --g8: rgba(190, 205, 225, 0.30);

  /* Разрыв между «решено» и «нет» намеренно большой: часть браузеров на
     телефонах затемняет крупные заливки по-своему, и слабую разницу такое
     затемнение стирает совсем. */
  /* Клетка кондуита. Пустая — заметная заливка с обводкой, решённая — плотная
     заливка обратной яркости со знаком поверх. В каждой теме пара «пустая /
     решённая» строится одинаково, только в разные стороны: в светлой решённая
     темнее фона, в тёмной — светлее. */
  --cell-on: #171727;
  --cell-off: rgba(18, 18, 52, 0.07);
  --cell-edge: rgba(11, 11, 11, 0.12);
  --cell-ink: #ffffff;
  /* пустой квадрат шкалы — свой цвет, а не цвет пустой клетки кондуита:
     в кондуите он почти сливается с подложкой намеренно, в шкале должен
     быть виден, иначе не поймёшь, из чего доля */
  --meter-off: rgba(11, 11, 11, 0.13);

  --admin: #7b3fd6;
  /* Корона — заливка, а не текст, поэтому золото берём чистое и тёплое.
     Прежний #9a7000 на светлом читался болотным: слишком мало красного. */
  --leader: #c9891c;
  --accent-hi: #8a6400;
  --accent-wash: rgba(138, 100, 0, 0.07);

  /* Два радиуса на весь интерфейс: крупный для карточек и панелей, мелкий для
     полей, клеток и квадратных кнопок. Круглые кнопки — отдельно, 999px. */
  --radius: 20px;
  --radius-sm: 12px;
  --tap: 44px;

  /* Цвет текста на плотной заливке цвета чернил: в светлой теме белый, в
     тёмной — почти чёрный. Нужен выбранной вкладке и всему, что залито ink. */
  --ink-inv: #ffffff;

  /* Две ступени высоты. Тень мягкая, широкая и слегка синеватая — под стеклом
     чёрная тень выглядит грязью. */
  --shadow-1: 0 1px 2px rgba(16, 16, 44, .05), 0 10px 26px -14px rgba(16, 16, 44, .30);
  --shadow-2: 0 2px 8px rgba(16, 16, 44, .07), 0 28px 64px -28px rgba(16, 16, 44, .45);

  /* Стекло — только для полосы вкладок и плавающих панелей: под ними проезжает
     содержимое, там эффект и виден. На карточках и в кондуите его нет — размытие
     под длинной таблицей стоит плавности прокрутки, а текст на нём теряется. */
  /* Линия тетрадной клетки на подложке. */
  --paper: rgba(11, 11, 11, .07);
  --paper-step: 30px;

  /* Заголовок сезона — единственный вывернутый блок на странице. На светлой теме
     он тёмный и работает как якорь для взгляда; на тёмной — чуть светлее
     подложки, потому что белое пятно во весь экран вечером бьёт по глазам.
     Заливка плоская: то, что переживает любую принудительную тёмную тему. */
  /* Полоска доли в строке рейтинга. */
  --bar: rgba(11, 11, 11, .085);

  /* Стекло кнопки. Панель под ней уже полупрозрачна, поэтому кнопке довольно
     одного шага плотности — плюс светлая грань поверху и косой блик, те же три
     вещи, из которых собрана сама панель. Дальше всё различие между кнопками
     только в размере и в том, чем они показывают состояние. */
  /* Плотные плашки. Единственные вывернутые блоки на странице: белый текст на
     цвете там, где всё остальное — чернила по светлому. Заливка плотная
     нарочно, 0.82 против 0.6 у панели: сквозь неё клетка почти не видна, и
     плашка читается как предмет, а не как окно. Стеклом её оставляют косой
     блик и светлая грань — те же, что у панели; пятно второго цвета из угла и
     есть то, что отличает её от простой краски.

     Приём работает, только пока таких блоков мало. Список мест, где он
     разрешён, ведётся в README, и новое появляется вместо старого. */
  --solid-edge: rgba(255, 255, 255, 0.26);
  --solid-dim: rgba(255, 255, 255, 0.70);
  --cold-bg: rgba(38, 30, 110, 0.82);
  --cold-glow: rgba(120, 200, 255, 0.50);
  --warm-bg: rgba(122, 38, 26, 0.82);
  --warm-glow: rgba(255, 196, 120, 0.48);

  /* Красная — удаление. Своя, а не --bad: у --bad есть вторая работа, он красит
     текст и рамки, и делать его вдобавок заливкой под белыми буквами значит
     выбирать один цвет на две задачи с разными требованиями к контрасту. */
  --danger-bg: rgba(178, 30, 54, 0.94);
  --danger-glow: rgba(255, 170, 130, 0.55);
  /* Листок серии и вопросы зачёта. Тон сине-зелёный: разделом листок не
     является, и цвет ему нужен свой. */
  --sheet-bg: rgba(15, 76, 92, 0.94);
  --sheet-glow: rgba(120, 220, 235, 0.44);

  /* Ответы зачёта — другой цвет, чем вопросы: на одной странице лежат две стопки
     файлов, и разница между ними должна быть видна раньше, чем прочитан
     заголовок. */
  --ans-bg: rgba(52, 34, 96, 0.94);
  --ans-glow: rgba(190, 160, 255, 0.40);

  /* Архив — задачники прошлых лет. Свой цвет, потому что вкладка своя: зелёный
     не спорит ни с бирюзовыми вопросами, ни с фиолетовыми ответами зачёта,
     а по смыслу это вообще другая стопка — не к чему вести, а что перебирать. */
  --arch-bg: rgba(22, 74, 58, 0.94);
  --arch-glow: rgba(130, 232, 180, 0.42);

  /* Красный в знаке — единственный, который не значит ничего, кроме самого
     знака: он часть логотипа и потому живёт отдельно от палитры разделов. */
  --font-ui: "Golos Text", "Segoe UI Variable Text", system-ui, -apple-system,
             "Segoe UI", Roboto, sans-serif;
  --font-display: "Golos Text", "Segoe UI Variable Display", system-ui,
                  -apple-system, "Segoe UI", Roboto, sans-serif;

  --mark-red: #e0241f;

  /* Заливка нарочно полупрозрачная: сквозь кнопку должна быть видна клетка,
     иначе это не стекло, а белая карточка. Почти непрозрачную пробовали — она
     читалась контрастно и мертво. Работу рамки при этом делает рамка. */
  --glass: rgba(255, 255, 255, 0.58);
  --glass-on: rgba(255, 255, 255, 0.86);
  --glass-edge: rgba(11, 11, 11, 0.15);
  --glass-top: rgba(255, 255, 255, 0.95);
  --glass-sheen: rgba(255, 255, 255, 0.55);
  /* Тень под кнопкой. Прежде у неё была только внутренняя грань поверху, и на
     стеклянной панели кнопка лежала в одной плоскости с ней — отсюда и
     ощущение плоского и дешёвого. Две тени: близкая держит край, дальняя
     отрывает от панели. */
  --btn-near: rgba(16, 16, 44, 0.10);
  --btn-far: rgba(16, 16, 44, 0.30);
}

/* Тёмная тема — свой набор шагов под тёмную подложку, а не инверсия светлой.
   Пока страница объявляла «только светлая», браузер затемнял её сам и портил
   цвета; со своим набором мы решаем это сами. */
@media (prefers-color-scheme: dark) {
  :root {
    --surface: #15151c;
    --plane: #06060b;
    --ink: #ffffff;
    --ink-2: #c2c2d0;
    --ink-muted: #8b8b9c;
    --grid: rgba(255, 255, 255, 0.10);
    --axis: rgba(255, 255, 255, 0.26);
    --border: rgba(255, 255, 255, 0.13);
    --border-strong: rgba(255, 255, 255, 0.26);
    --wash: rgba(255, 255, 255, 0.07);
    --quiet: rgba(255, 255, 255, 0.075);
    --quiet-on: rgba(255, 255, 255, 0.15);
    --good: #34d17f;
    --bad: #ff7a90;

    --pane: rgba(38, 38, 52, 0.60);
    --pane-2: rgba(24, 24, 36, 0.86);
    --pane-edge: rgba(255, 255, 255, 0.24);
    --pane-edge-low: rgba(0, 0, 0, 0.28);
    --sheen: rgba(255, 255, 255, 0.07);
    --glow-1: rgba(255, 255, 255, 0.11);
    --glow-2: rgba(255, 255, 255, 0.07);
    --glow-3: rgba(255, 255, 255, 0.08);

    /* Линия значка на тёмной подложке светлее, чем на светлой, а не темнее:
       прежний набор был темнее светлого, и цвета сливались с фоном. */
    --s1: #62aecd;
    --s2: #e8836a;
    --s3: #6fb98a;
    --s4: #d9ac4f;
    --s5: #d76aa4;
    --s6: #46bdb4;
    --s7: #9b81dc;
    --s8: #a3b0c2;

    /* Заливка плашки на тёмной подложке чуть светлее и прозрачнее: панель под
       ней тёмная, и та же глубина, что на светлой теме, дала бы провал. */
    --f1: rgba(24, 68, 92, 0.86);
    --f2: rgba(140, 46, 28, 0.86);
    --f3: rgba(30, 78, 52, 0.88);
    --f4: rgba(108, 80, 18, 0.88);
    --f5: rgba(104, 28, 74, 0.86);
    --f6: rgba(18, 84, 80, 0.88);
    --f7: rgba(64, 42, 112, 0.86);
    --f8: rgba(54, 62, 76, 0.88);

    --g1: rgba(120, 205, 235, 0.30);
    --g2: rgba(255, 175, 130, 0.28);
    --g3: rgba(150, 225, 165, 0.26);
    --g4: rgba(255, 214, 140, 0.28);
    --g5: rgba(255, 155, 205, 0.26);
    --g6: rgba(125, 235, 220, 0.26);
    --g7: rgba(185, 155, 240, 0.28);
    --g8: rgba(190, 205, 225, 0.24);

    --cell-on: #e6e2ff;
    --cell-off: rgba(255, 255, 255, 0.07);
    --cell-edge: rgba(255, 255, 255, 0.14);
    --cell-ink: #14141f;
    --meter-off: rgba(255, 255, 255, 0.12);

    --admin: #c48cff;
    --leader: #f0c34c;
    --accent-hi: #e3b23c;
    --accent-wash: rgba(227, 178, 60, 0.12);

    /* На тёмном тень работает слабее, поэтому она глубже, а грань стекла —
       светлая: именно она и читается как толщина. */
    --ink-inv: #08080e;
    --shadow-1: 0 1px 2px rgba(0, 0, 0, .5), 0 10px 28px -14px rgba(0, 0, 0, .75);
    --shadow-2: 0 2px 8px rgba(0, 0, 0, .55), 0 28px 64px -28px rgba(0, 0, 0, .9);
    --paper: rgba(255, 255, 255, .055);
    /* На тёмной подложке плашка светлее, а не темнее: тёмное на тёмном
       пропадает. Прозрачность выше — под ней есть что показать. Красная тоже
       темнее светлой темы: на --bad (он тут розовый) белые буквы не читаются. */
    --solid-edge: rgba(255, 255, 255, 0.20);
    --solid-dim: rgba(255, 255, 255, 0.66);
    --cold-bg: rgba(58, 48, 142, 0.74);
    --cold-glow: rgba(120, 200, 255, 0.34);
    --warm-bg: rgba(140, 54, 38, 0.74);
    --warm-glow: rgba(255, 196, 120, 0.32);
    --danger-bg: rgba(190, 44, 66, 0.94);
    --danger-glow: rgba(255, 190, 150, 0.38);
    --sheet-bg: rgba(20, 88, 106, 0.90);
    --sheet-glow: rgba(120, 220, 235, 0.30);
    --ans-bg: rgba(64, 44, 116, 0.88);
    --ans-glow: rgba(190, 160, 255, 0.30);
    --arch-bg: rgba(30, 88, 68, 0.88);
    --arch-glow: rgba(130, 232, 180, 0.30);

    --mark-red: #ff4f42;

    /* Тёмную лунку вместо светлой вуали пробовали — кнопка становилась дырой в
       панели. Вуаль вернулась, но ощутимо плотнее прежней, а держат кнопку не
       заливкой: ободом в четверть белого и тенью под ней. */
    --glass: rgba(255, 255, 255, 0.11);
    --glass-on: rgba(255, 255, 255, 0.21);
    --glass-edge: rgba(255, 255, 255, 0.26);
    --glass-top: rgba(255, 255, 255, 0.10);
    --glass-sheen: rgba(255, 255, 255, 0.06);
    --btn-near: rgba(0, 0, 0, 0.40);
    --btn-far: rgba(0, 0, 0, 0.70);
    --bar: rgba(255, 255, 255, .11);
  }
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

html {
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  /* Место под полосу прокрутки держим всегда. Без этого на короткой вкладке
     («Темы») полоса пропадает, окно становится шире на её толщину, и вся
     страница дёргается вбок при каждом переключении. */
  scrollbar-gutter: stable;
}

/* Синий прямоугольник при касании складывается из двух вещей: подсветки самого
   касания и выделения текста внутри кнопки. Гасим обе, но оставляем видимую
   рамку для клавиатуры. */
button, .chip, .tab, .mark, .cal-day, .picker-btn, a.ghost-btn {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

:focus:not(:focus-visible) { outline: none; }

html, body {
  margin: 0;
  padding: 0;
}

/* Весь фон — клетка и свет — задан у самого html закреплённой заливкой. Это не
   слой поверх страницы и не фон её тела, а фон окна: он не прокручивается
   вместе с содержимым и не пересчитывается, когда на телефоне появляется и
   исчезает адресная строка. Закреплённым слоем (position: fixed) этого не
   добиться — такой слой браузер как раз и двигает вслед за окном.

   Рисунок при этом простой — две линии и три пятна, — поэтому закреплённая
   заливка обходится дёшево: перерисовывать при прокрутке почти нечего. */
html {
  background-color: var(--plane);
  background-image:
    linear-gradient(var(--paper) 1px, transparent 1px),
    linear-gradient(90deg, var(--paper) 1px, transparent 1px),
    radial-gradient(58% 46% at 8% -8%, var(--glow-1), transparent 64%),
    radial-gradient(52% 42% at 96% 6%, var(--glow-2), transparent 62%),
    radial-gradient(60% 50% at 62% 104%, var(--glow-3), transparent 64%);
  background-attachment: fixed;
  background-size:
    var(--paper-step) var(--paper-step),
    var(--paper-step) var(--paper-step),
    auto, auto, auto;
  background-position: -1px -1px, -1px -1px, 0 0, 0 0, 0 0;
}

/* Гарнитура своя и лежит рядом, в assets/fonts. Не по прихоти: сайт целиком
   русский, а системные интерфейсные шрифты рисуют кириллицу как приложение к
   латинице. Golos Text рисовалась от кириллицы, и на здешних словах — вроде
   «Комбинаторная геометрия» — это видно сразу.

   Файлов два, по диапазонам: кириллический берётся всегда, латинский только
   когда на странице попадётся латиница. Оба переменные, 400–700 в одном файле,
   поэтому насыщенность ничего не стоит. Стороннего запроса нет — файлы свои.

   Стопки всё равно две: пока шрифт летит (или не долетел вовсе), крупное и
   мелкое подхватывают разные системные начертания, а не одно на всё. */
@font-face {
  font-family: "Golos Text";
  src: url("fonts/golos-cyrillic.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: "Golos Text";
  src: url("fonts/golos-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  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;
}

body {
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 15px;
  line-height: 1.45;
  -webkit-text-size-adjust: 100%;
}

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

   Клетка почти прозрачна: она задаёт масштаб и материал, а не рисунок. */
.wrap {
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 16px 64px;
}

/* ── шапка ─────────────────────────────────────────────── */

.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 24px 0 16px;
}

/* Знак: «МЦ» набором и «:re» рисунком. Рисунком, а не шрифтом, нарочно —
   начертание в знаке заданное, и подбирать под него гарнитуру, которая на чужом
   телефоне окажется другой, бессмысленно.

   Обе части стоят на одной строке обычным потоком, а не флексом: у встроенного
   рисунка нижний край и так ложится на базовую линию строки, и низ виewBox
   поставлен ровно по базовой линии букв — от этого «МЦ» и «re» стоят на одной
   линии сами, без подгонки отступами. */
.brand-box {
  display: block;
  font-family: var(--font-display);
  font-size: 58px;
  line-height: 1;
  white-space: nowrap;
}

/* Полужирное против тонкого знака — контраст нарочный: «МЦ» читается словом,
   «:re» знаком при нём, и вместе они не сливаются в одну надпись. */
.brand-mc {
  font-size: 1em;
  font-weight: 600;
  letter-spacing: -0.005em;
  margin-right: 0.28em;
}

/* Размер и сдвиг заданы в em от кегля шапки: «e» в знаке выходит ниже строки,
   и низ рисунка базовой линии не равен. Сдвигаем рисунок вниз ровно на этот
   свес — тогда на базовую линию «МЦ» встаёт строка «r», как и должно. В em,
   чтобы на узком экране всё уехало вместе, одним изменением кегля. */
.brand-re {
  height: 0.870em;
  width: auto;
  vertical-align: -0.109em;
}

/* Тонкая линия одной толщины на всё: так рисуют геометрические гротески, и
   знак собран по тому же правилу. Торцы срезаны прямо — скруглённые сделали бы
   его мягче, чем он есть.

   «r» и «e» стоят на одной базовой линии и одного роста — как обычные буквы.
   Круг выходит за строку сверху и снизу ровно на пол-единицы: это оптический
   вынос, без которого круглая буква рядом с прямой кажется мельче её. Разводить
   их по росту пробовали дважды, и оба раза выходило криво — строка читалась не
   набором, а тремя предметами, поставленными рядом.

   Своё у знака — толстые точки: они заметно толще линии букв, и это
   единственное место, где пропорции нарочно не типографские. */
.brand-re path {
  fill: none;
  stroke: currentColor;
  stroke-width: 2.5;
  /* Перекладина «e» и его дуга — один контур: раздельными они давали на стыке
     торчащий уголок, потому что плоский торец перекладины приходился на место,
     где дуга уже уходит вертикально. */
  stroke-linejoin: round;
}

.re-ink { fill: currentColor; }
.re-red { fill: var(--mark-red); }

/* В редакторе знак тот же, поэтому его страницу помечает ромб — тот же знак и
   цвет, что у админа в списке. Без него две страницы не различить с одного
   взгляда, а перепутать их дорого. */
body.is-editor .brand-box::after {
  content: "◆";
  margin-left: 0.22em;
  font-size: 0.37em;
  color: var(--admin);
  vertical-align: 0.72em;
}

.spacer { flex: 1; }

/* Поле числа без стрелок-крутилок: номер дня вводят с клавиатуры, а на узком
   поле крутилки съедают половину ширины. */
input[type="number"] { -moz-appearance: textfield; }

input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Полоса вкладок — плавающая пилюля: она не приклеена к краю экрана, а висит
   над содержимым, и под ней всё проезжает. Это единственное место вместе с
   карточками, где размытие и правда что-то показывает.

   Если backdrop-filter недоступен, остаётся плотная заливка: полоса просто
   перестаёт быть прозрачной, ничего не разъезжается. */
.tabs {
  position: sticky;
  top: 10px;
  z-index: 30;
  display: flex;
  gap: 2px;
  margin: 0 0 18px;
  padding: 4px;
  border: 1px solid var(--pane-edge);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--shadow-2), inset 0 1px 0 var(--pane-edge);
  overflow-x: auto;
  scrollbar-width: none;
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .tabs {
    background: var(--pane-2);
    -webkit-backdrop-filter: var(--pane-blur);
    backdrop-filter: var(--pane-blur);
  }
}

.tabs::-webkit-scrollbar { display: none; }

/* Вес шрифта у выбранной вкладки не меняется: от смены веса меняется ширина,
   и соседние вкладки съезжают при каждом переключении. Выбранная опознаётся
   цветом и подчёркиванием, ширина остаётся той же. */
.tab {
  appearance: none;
  background: none;
  border: 0;
  border-radius: 999px;
  color: var(--ink-muted);
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  padding: 8px 15px;
  flex: none;
  cursor: pointer;
  white-space: nowrap;
  transition: color .16s ease, background-color .16s ease;
}

.tab:hover { color: var(--ink-2); }
.tab:focus { outline: none; }

.tab:focus-visible {
  outline: 2px solid var(--s1);
  outline-offset: -2px;
}

/* Указатель один на всю полосу и переезжает с вкладки на вкладку, а не
   загорается на каждой отдельно. Положение и ширину ему задаёт скрипт — по
   месту самой вкладки, поэтому он верен при любой ширине экрана и любой
   длине подписей.

   Пока ширина не задана, указателя попросту нет: он не выскакивает из угла
   при первой отрисовке. */
.tabs::before {
  content: "";
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 0;
  width: var(--thumb-w, 0);
  transform: translateX(var(--thumb-x, 0));
  border-radius: 999px;
  background: var(--ink);
  pointer-events: none;
  transition: transform .38s cubic-bezier(.22, .8, .24, 1),
              width .38s cubic-bezier(.22, .8, .24, 1);
}

/* первая установка — без переезда: указателю неоткуда ехать */
.tabs.no-anim::before { transition: none; }

.tab { position: relative; z-index: 1; }

/* Заливку выбранной вкладки рисует указатель, самой вкладке остаётся цвет. */
.tab[aria-selected="true"] { color: var(--ink-inv); }

/* ── карточки и фильтры ────────────────────────────────── */

/* Панель матового стекла. Собрана из четырёх вещей: полупрозрачной заливки,
   размытия подложки, светлой грани поверху (она и читается как толщина) и
   мягкой тени под низом.

   Размытие объявлено отдельным правилом с проверкой: где его нет, панель
   становится плотной, и страница остаётся читаемой — просто плоской. */
.card,
.tile,
.table-wrap,
.conduit-split {
  /* Заливка и блик заданы порознь: подкраска ниже меняет только цвет, а блик
     остаётся на месте. */
  background-color: var(--surface);
  background-image: linear-gradient(147deg, var(--sheen), transparent 44%);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow:
    var(--shadow-1),
    inset 0 1px 0 var(--pane-edge),
    inset 0 -1px 0 var(--pane-edge-low);
}

/* Размытие подложки осталось только у полосы вкладок: под ней проезжает
   содержимое, и там оно правда работает. У панелей его нет — под ними лежит
   ровный свет и клетка, размывать нечего, а платить приходилось на каждом
   кадре и заново при каждой вставке панели в страницу. Прозрачность, грани и
   блик стекло держат и без него. */
.card,
.tile,
.table-wrap,
.conduit-split { background-color: var(--pane); }

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

   Цвет приходит двумя переменными, так что плашку можно направить куда угодно,
   не трогая правило. Разрешённые места перечислены в README. */
.solid,
.lik-row,
.thanks,
.chip.cat[aria-pressed="true"],
.icon-btn.del,
.icon-btn.danger,
.primary-btn.danger {
  position: relative;
  overflow: hidden;
  border-color: var(--solid-edge);
  background-color: var(--solid-bg);
  background-image:
    linear-gradient(142deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0) 46%);
  box-shadow: var(--shadow-2), inset 0 1px 0 var(--solid-edge);
  color: #fff;
}

/* Пятно уходит под содержимое отрицательным слоем: у кнопки удаления внутри
   голый крестик, и поднимать его нечем — а так поднимать и не нужно. */
.solid::after,
.lik-row::after,
.thanks::after,
.chip.cat[aria-pressed="true"]::after,
.icon-btn.del::after,
.icon-btn.danger::after,
.primary-btn.danger::after {
  content: "";
  position: absolute;
  z-index: -1;
  top: -58%;
  right: -14%;
  width: 66%;
  padding-bottom: 66%;
  border-radius: 50%;
  background: radial-gradient(circle, var(--solid-glow), transparent 68%);
  pointer-events: none;
}

.solid.cold { --solid-bg: var(--cold-bg); --solid-glow: var(--cold-glow); }
.solid.warm { --solid-bg: var(--warm-bg); --solid-glow: var(--warm-glow); }

/* Подписи на плашке — приглушённый белый, а не серый: серый по цветному
   читается грязью. */
.solid .tile-label,
.solid .tile-note,
.lik-row .lik-meta { color: var(--solid-dim); }

.thanks > * { position: relative; }

.card { padding: 14px 16px; }

/* Подсветка блока. Пятно света лежит в самой панели, ещё одним слоем заливки,
   а не отдельным элементом поверх: тот требовал обрезки по краю и своего слоя
   на каждую панель, а рисовал ровно то же.

   Сейчас свет белый. Когда понадобится цвет, менять придётся одну переменную:
   у блока свой слот оттенка. */
/* карточка-предупреждение: данные не потеряны, но и не считаются */
.card.warn { border-color: var(--accent-hi); background: var(--accent-wash); }

.warn-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--accent-hi);
  margin-bottom: 6px;
}

.warn-line {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 13px;
  padding: 3px 0;
}

.warn-where { color: var(--ink-2); }
.warn-ids { font-variant-numeric: tabular-nums; white-space: nowrap; }

.filters { margin-bottom: 14px; }

.filter-row + .filter-row {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--grid);
}

.filter-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 9px;
}

.filter-title {
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* ── материал кнопок ────────────────────────────────────
   Одна поверхность на всё, что нажимают: ярлык отбора, мелкое действие, кнопку
   редактора, квадратную кнопку, счётчик. Ни рамки, ни стекла, ни тени — только
   приглушённая подложка, и та своего цвета в каждой теме.

   Стекло с рамкой и грань поверху тут были и держались долго, но кончилось это
   тем, что кнопка спорила по весу с панелью, на которой лежит. Плотность
   осталась ровно там, где она что-то значит: у плашки раздела, у файла, у
   выбранной серии. Остальное — тихая подложка. */
.chip, .mini-btn, .ghost-btn, .icon-btn, .icon-pick, .step-btn {
  appearance: none;
  font: inherit;
  color: var(--ink-2);
  background-color: var(--quiet);
  background-image: none;
  border: 0;
  border-radius: 999px;
  box-shadow: none;
  cursor: pointer;
}

.chip:hover, .mini-btn:hover, .ghost-btn:hover,
.icon-btn:hover, .icon-pick:hover, .step-btn:hover {
  background-color: var(--quiet-on);
  color: var(--ink);
}

/* Мелкое действие рядом с названием раздела. Тем же капителем вразрядку оно
   набиралось раньше — и было неотличимо от подписи слева: два одинаковых слова
   в строке, из которых одно почему-то нажимается.

   Теперь разошлись по трём признакам сразу: название капителью вразрядку,
   действие — строчными и крупнее; название приглушено, действие в полную силу;
   у действия есть подложка, у названия нет. Подложка круглая и без рамки —
   этого хватает, чтобы она читалась кнопкой, и не хватает, чтобы спорить с
   ярлыками отбора под ней, у которых рамка есть. */
.mini-btn {
  border: 0;
  border-radius: 999px;
  background: var(--quiet);
  box-shadow: none;
  color: var(--ink-2);
  font-size: 12.5px;
  font-weight: 560;
  letter-spacing: -0.005em;
  line-height: 1;
  padding: 8px 12px;
  white-space: nowrap;
}

.mini-btn:hover { background: var(--quiet-on); color: var(--ink); }

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  /* Ярлыки отбора — скруглённые прямоугольники, а не пилюли: пилюли остались
     за полосой вкладок и мелкими действиями, и путать их незачем. */
  border-radius: 12px;
  /* Кегль и насыщенность подняты нарочно. На 13-м и обычном начертании ярлык
     читался как системный виджет: набор мелкий, светлый и без характера, а их
     на экране два десятка — из них и складывалось первое впечатление от
     страницы. Отрицательный трекинг на этом кегле делает главное: строка
     собирается в слово, а не рассыпается на буквы. */
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: -0.008em;
  color: var(--ink);
  padding: 8px 13px;
}

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

   Разница держится на заливке и цвете, но не на насыщенности шрифта: от смены
   насыщенности слово меняет ширину, и соседние ярлыки при каждом нажатии
   разъезжались. */
.chip[aria-pressed="false"] {
  background-color: transparent;
  background-image: none;
  box-shadow: none;
  border-color: var(--glass-edge);
  color: var(--ink-muted);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

.chip[aria-pressed="false"] .dot,
.chip[aria-pressed="false"] .ic { opacity: .28; }

/* Выбор одного из вариантов — не фильтр: невыбранное здесь не «исключено»,
   поэтому не зачёркивается и стекла не теряет. Выбранное обводится жирнее.

   День исключён: на вкладке рейтинга он отбор, на вкладке серий — выбор, но
   человек-то видит одну и ту же кнопку, и выглядеть в двух местах по-разному
   она не должна. Общий вид взят от отбора, без стекла. */
.chip.pick[aria-pressed="false"]:not(.day) {
  color: var(--ink-2);
  background-color: var(--quiet);
  text-decoration: none;
}

.chip.pick[aria-pressed="false"] .dot,
.chip.pick[aria-pressed="false"] .ic { opacity: 1; }

/* Раздел и день исключены нарочно. Раздел и в выборе темы задачи остаётся
   цветной плашкой — тот же предмет, что и в отборе на сайте. День же чернильный,
   и без исключения он белым не становился: у правила выбора три класса против
   двух у правила дня, и оно перебивало его независимо от порядка в файле. */
.chip.pick[aria-pressed="true"]:not(.cat):not(.day) {
  background-color: var(--quiet-on);
  color: var(--ink);
}

/* кнопка серии: номер и дата. Серий за год набирается много, поэтому кнопка
   плотная — иначе выбор занимает пол-экрана. */
.chip.day {
  flex-direction: column;
  gap: 0;
  min-width: 46px;
  padding: 5px 8px;
  border-radius: 14px;
  font-variant-numeric: tabular-nums;
}

/* гробарий — одиночная кнопка, дата ему не нужна */
.chip.day.wide { flex-direction: row; padding: 9px 16px; border-radius: 13px; }
.chip.day.wide b { font-size: 13.5px; }

.chip.day b { font-size: 13px; font-weight: 620; line-height: 1.2; }
.chip.day small { font-size: 9.5px; line-height: 1.15; opacity: .72; letter-spacing: -0.02em; }

/* Светлая грань поверху здесь снята нарочно: на чернильной заливке она
   читалась бликом поперёк кнопки, будто по ней провели пальцем. На стекле она
   уместна, на плотной краске — нет. Тень снизу остаётся, кнопка не проваливается
   в страницу. */
.chip[aria-pressed="true"].day {
  background: var(--ink);
  color: var(--ink-inv);
  border-color: var(--ink);
  box-shadow: 0 1px 2px var(--btn-near), 0 5px 12px -7px var(--btn-far);
}

/* Невыбранная серия — сплошная рамка, без пунктира и без стекла: одинаково и в
   отборе рейтинга, и в списке серий. Пунктир пробовался и читался как «серия
   испорчена», хотя означал всего лишь «не в счёте». */
.chip.day[aria-pressed="false"] {
  text-decoration: none;
  border-style: solid;
  color: var(--ink-muted);
}

/* На кнопке серии номер сверху, дата подписью снизу. */
.chip.day b { color: var(--ink); }

/* У выбранного дня подложка тёмная, и цвет буквы на ней теряется. Ничего не
   пропадает: буква и есть пометка, цвет к ней только добавка. */
.chip[aria-pressed="true"].day b { color: inherit; }

/* Ярлык раздела — такая же плотная плашка, как «Место» в карточке ученика: тот
   же глубокий цвет, тот же косой блик, то же светлое пятно в углу, тот же белый
   текст. Заливка и свет приходят прямо из палитры (--fN и --gN), а не выводятся
   из цвета значка: выводить пробовали, и глубины так не получалось.

   Плашек таких четыре из двадцати, между ними стоят неподкрашенные подразделы —
   поэтому ряд не рябит. */
.chip.cat[aria-pressed="true"] {
  --solid-bg: var(--fill);
  --solid-glow: var(--lift);
}

/* Значок на плашке белеет вместе с текстом: цветной по цветному пропадает. */
.chip.cat .ic { color: var(--accent); }
.chip.cat[aria-pressed="true"] .ic { color: #fff; }

/* темы: раздел и его подразделы */
.tgroup {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  margin-top: 8px;
}

.chip.cat {
  font-family: var(--font-display);
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -0.02em;
  padding: 10px 16px;
  border-radius: 15px;
}
/* Раздел, у которого включена часть подразделов. Пунктирная рамка тут была и
   на плотной плашке выглядела дырой в краске. Теперь это третья ступень между
   выключенным и включённым: не плашка, а стекло, подкрашенное тем же цветом.
   Ступени читаются с одного взгляда — перечёркнуто, подкрашено, залито.

   Пятна в углу у полутона нет: свет принадлежит плашке, а полутон ею ещё не
   стал. */
.chip.cat.partial[aria-pressed="true"] {
  /* Подкрашивается цветом линии, а не заливки: заливка глубокая, и в малой доле
     от неё остаётся серость, а не тон. */
  background-color: color-mix(in srgb, var(--accent) 22%, var(--glass));
  background-image: linear-gradient(158deg, var(--glass-sheen), transparent 62%);
  border-color: color-mix(in srgb, var(--accent) 42%, var(--glass-edge));
  color: var(--ink);
  box-shadow:
    inset 0 1px 0 var(--glass-top),
    0 1px 2px var(--btn-near),
    0 5px 12px -7px var(--btn-far);
}

.chip.cat.partial[aria-pressed="true"]::after { content: none; }
.chip.cat.partial[aria-pressed="true"] .ic { color: var(--accent); }

.chip-count {
  font-size: 11px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

.chip[aria-pressed="true"].cat .chip-count { color: var(--ink-muted); }

.subs { display: flex; flex-wrap: wrap; gap: 6px; }

/* Тихая пилюля. Один вид на три места: подраздел, «что считаем» и мелкие
   действия («все», «ни одной»). Ни рамки, ни стекла, ни тени — только пилюля на
   приглушённой подложке.

   Стекло с рамкой и тенью у них было от раздела, и зря: раздел это плотная
   цветная плашка, а остальное ему подчинено — одинаковый материал ставил их
   вровень. Теперь три уровня видно сразу: плашка, пилюля, подпись.

   Отличает подраздел от прочих тихих кнопок только цветной значок темы: он и
   держит связь со своим разделом. */
.chip.sub,
.chip.quiet {
  border: 0;
  border-radius: 999px;
  background-color: var(--quiet);
  background-image: none;
  box-shadow: none;
  color: var(--ink-2);
  font-size: 12.5px;
  font-weight: 560;
  letter-spacing: -0.005em;
  padding: 8px 13px;
}

/* У подраздела слева значок, и отступ с этой стороны меньше на его ширину. */
.chip.sub { gap: 6px; padding-left: 11px; }

.chip.sub[aria-pressed="true"],
.chip.quiet[aria-pressed="true"] { color: var(--ink); }

.chip.sub:hover,
.chip.quiet:hover { background-color: var(--quiet-on); color: var(--ink); }

/* Выключённая — та же пилюля без подложки и перечёркнутая. Общее правило
   выключенного ярлыка гасит заливку и так, но подложка тут своя, и гасить её
   нужно отдельно. */
.chip.sub[aria-pressed="false"],
.chip.quiet[aria-pressed="false"] {
  background-color: transparent;
  color: var(--ink-muted);
}

/* ── значки тем ─────────────────────────────────────────
   Рисунок лежит в спрайте (assets/icons.js), здесь только размер и толщина
   линии. Цвет значок берёт от текста, поэтому красится обычным color — и встаёт
   ровно туда, где раньше стоял цветной кружок, с тем же цветом раздела.

   Ни fill, ни stroke селектором внутрь <use> не достать, зато они наследуются:
   заданные здесь, они доходят до содержимого символа сами. */
.ic {
  width: 15px;
  height: 15px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* У подраздела значок мельче — разница в размере держит уровни списка так же,
   как её держал разный размер кружков. Линия при этом чуть толще: на мелком
   размере тонкая тает. */
.chip.sub .ic,
.pline.sub .ic,
.subline-name .ic { width: 13px; height: 13px; stroke-width: 1.9; }

/* Кружок остался там, где он и есть кружок, а не знак темы: выбор цвета
   раздела в редакторе. */
.dot {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  flex: none;
}

.summary {
  margin-top: 12px;
  padding-top: 11px;
  border-top: 1px solid var(--grid);
  color: var(--ink-2);
  font-size: 13px;
}

.summary b { font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }

/* ── плитки ────────────────────────────────────────────── */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}

.tile { padding: 12px 14px; }

.tile-label {
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 5px;
}

.tile-value {
  font-family: var(--font-display);
  font-size: 31px;
  font-weight: 640;
  letter-spacing: -0.035em;
  line-height: 1.1;
}

.tile-note {
  font-size: 12px;
  color: var(--ink-muted);
  margin-top: 2px;
}

/* Плитка, отмечающая достижение: половина задач и выше. Заливки у неё больше
   нет — панели на странице все до одной одинаковы, и одна золотая посреди
   пятёрки выбивалась бы ровно так же, как выбивалась прежняя подкраска.
   Достижение сказано самим числом и рамкой, а это и есть то, что читают. */
.tile.hi { border-color: var(--accent-hi); }

.tile.hi .tile-value { color: var(--accent-hi); }
.tile.hi .tile-label { color: var(--accent-hi); opacity: .85; }

/* ── таблицы ───────────────────────────────────────────── */

.table-wrap { overflow-x: auto; }

table.data {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

/* Колонки с числами закреплены по ширине, имя забирает остаток. При обычной
   раскладке ширина столбца зависит от самого длинного числа в нём, и таблица
   переезжала при каждом переключении фильтра. */
table.data.fixed { table-layout: fixed; }
table.data.fixed th.rank { width: 54px; }
table.data.fixed th.c-score { width: 74px; }
table.data.fixed th.c-tasks { width: 66px; }
table.data.fixed th.c-avg { width: 82px; }

table.data.fixed td.name {
  overflow: hidden;
  text-overflow: ellipsis;
}

table.data th {
  text-align: right;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding: 10px 12px;
  border-bottom: 1px solid var(--grid);
  white-space: nowrap;
}

table.data th.left, table.data td.left { text-align: left; }

table.data td {
  text-align: right;
  padding: 9px 12px;
  border-bottom: 1px solid var(--grid);
  white-space: nowrap;
}

table.data tbody tr:last-child td { border-bottom: 0; }

table.data tfoot td {
  border-top: 1px solid var(--axis);
  border-bottom: 0;
  color: var(--ink-2);
  font-weight: 560;
}

table.data tfoot .name { color: var(--ink-muted); font-weight: 600; }
table.data tbody tr:hover td { background: var(--wash); }
table.data tr.clickable { cursor: pointer; }

.rank {
  width: 1%;
  color: var(--ink-muted);
  font-size: 13px;
  white-space: nowrap;
}

.rank-top .rank-num { color: var(--ink); font-weight: 700; }
/* первое место — единственное золотое пятно в таблице */
.rank-1 .rank-num { color: var(--leader); }

.name { font-weight: 500; }

/* Полоска доли: сколько человек взял от своего потолка. Тонкая линия по низу
   ячейки, а не заливка за именем: заливка читалась пятном под текстом, а линия
   складывается по всей таблице в маленькую диаграмму. */
table.data td.name { position: relative; }

.rowbar {
  position: absolute;
  left: 12px;
  bottom: 4px;
  height: 3px;
  border-radius: 999px;
  background: var(--axis);
  pointer-events: none;
}

/* У первого места полоска золотая — то же пятно, что и у его номера. */
.rank-1 + td.name .rowbar { background: var(--leader); }

table.data td.name .name-box { position: relative; }

/* Счёт — то, ради чего таблицу открывают, и между 31 у плитки и 15 у текста
   не стояло ничего. Теперь стоит он. */
.score {
  font-family: var(--font-display);
  font-weight: 620;
  font-size: 19px;
  letter-spacing: -0.02em;
}

.muted { color: var(--ink-muted); }

/* подпись в самом низу карточки — тем же шрифтом, что и всё остальное */
.egg {
  margin: 26px 0 8px;
  text-align: center;
  font-size: 13.5px;
  letter-spacing: 0.06em;
  color: var(--ink);
  opacity: 0.5;
}

/* Раньше все заливки здесь были плоскими: Samsung Internet в принудительной
   тёмной теме гасил именно градиенты. Сайт смотрят в Chrome, и это правило
   снято — градиенты и размытие используются свободно. Плоскими остались клетки
   кондуита и кружки тем: там важна не красота, а то, чтобы разница между
   «решено» и «нет» читалась с одного взгляда. */

/* ── кондуит ───────────────────────────────────────────── */

/* Кондуит — две таблицы бок о бок: фамилии не прокручиваются, клетки
   прокручиваются. Высоты строк заданы жёстко, иначе половинки разъедутся. */
/* Черта под шапкой проведена по всей панели, а не по таблице: у таблицы она
   обрывалась посреди стекла, потому что таблица уже панели. Высота шапки задана
   переменной и берётся отсюда же — иначе черта разъедется со строкой заголовков
   при первом же изменении её высоты. */
.conduit-split::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: var(--head-h);
  height: 1px;
  background: var(--grid);
  pointer-events: none;
}

/* Черты подвала — «Решили» и «Вес» — тем же способом, что и черта заголовков.
   Своими границами у tfoot они доходили только до края таблицы: на широком
   экране половины стоят посередине, справа и слева остаётся поле, и линии
   обрывались на пустом месте, тогда как верхняя шла от края до края.

   Рисуются двумя слоями фона, отмеренными от низа панели: снизу вверх — строка
   «Вес», над ней «Решили». Высота строки подвала одна на обе и вынесена в
   переменную, иначе черты разъедутся со строками при первой же её правке. */
.conduit-split {
  --foot-row: 24px;
}

.conduit-split::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  pointer-events: none;
  background:
    linear-gradient(var(--grid), var(--grid))
      left 0 bottom var(--foot-row) / 100% 1px no-repeat,
    linear-gradient(var(--grid), var(--grid))
      left 0 bottom calc(var(--foot-row) * 2) / 100% 1px no-repeat;
}

/* Обе половины стоят посередине панели, а не прижаты влево. Растягивать
   таблицу клеток во всю ширину пробовали: восемь столбцов разъезжались до
   семидесяти пяти пунктов при знаке плюса в тридцать восемь, и сетка переставала
   читаться сеткой. Пустота осталась, но теперь она поровну с двух сторон — а
   такая читается полем, а не обрывом.

   Когда столбцов много и они не помещаются, прокрутка работает как прежде:
   половина с клетками сжимается до доступного, автоматические отступы обнуляются
   сами. */
.conduit-split {
  --head-h: 40px;
  position: relative;
  display: flex;
  align-items: stretch;
  justify-content: center;
  overflow: hidden;
}

table.conduit.names {
  flex: none;
  border-right: 1px solid var(--grid);
}

.conduit-scroll {
  flex: 0 1 auto;
  min-width: 0;
  overflow-x: auto;
}

table.conduit thead th { height: 40px; }
table.conduit tbody td { height: 38px; }
table.conduit tfoot td { height: 26px; }

table.conduit {
  border-collapse: separate;
  border-spacing: 0;
  font-variant-numeric: tabular-nums;
}

table.conduit th, table.conduit td {
  padding: 0;
  font-size: 12px;
  font-weight: 400;
}

table.conduit th.pname, table.conduit td.pname {
  background: transparent;
  text-align: left;
  padding: 0 12px 0 14px;
  white-space: nowrap;
  font-size: 15px;
  min-width: 176px;
  max-width: 176px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* столбец фамилий оформлен как в рейтинге: тот же кегль, вес и отбивка */
table.conduit tbody td.pname {
  height: 32px;
  font-weight: 500;
  color: var(--ink);
  padding: 0 14px;
}

table.conduit thead th.pname,
table.conduit tfoot td.pname {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* Имя со значками: сам текст ужимается, значки — никогда. Оба значка могут
   стоять рядом, если админ вышел на первое место. */
.name-box {
  display: flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
}

.name-box .nm {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.badge-admin {
  flex: none;
  font-style: normal;
  font-size: 0.82em;
  line-height: 1;
  color: var(--admin);
}

/* Корона нарисована обрезкой прямоугольника, а не взята символом: символьные
   короны есть не во всех телефонных шрифтах и выпадают в пустой квадрат.
   Силуэт простой — пять зубцов, читается на 9 пикселях. */
.badge-leader {
  flex: none;
  width: 11px;
  height: 9px;
  background: var(--leader);
  clip-path: polygon(0 100%, 0 20%, 25% 52%, 50% 0, 75% 52%, 100% 20%, 100% 100%);
}

/* Шапка без заливки и без своей черты: и то и другое обрывалось посреди стекла,
   потому что таблица уже панели. Заливка была нужна, когда столбец с номерами
   задач был липким и под него подъезжали строки; липкость убрали давно. Черту
   теперь ведёт сама панель, во всю ширину. */
table.conduit thead th {
  height: var(--head-h);
  vertical-align: bottom;
}

.phead {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding-bottom: 6px;
  width: 38px;
}

.phead-id {
  font-size: 11.5px;
  color: var(--ink-2);
  letter-spacing: -0.02em;
}

/* задача без темы: номер приглушён, полоска под ним серая */
.phead-id.untyped { color: var(--ink-muted); }

/* Полоска под номером задачи говорила только раздел — цветом. Значок говорит
   ещё и подраздел, а места занимает столько же: столбец широкий, 38px. */
.phead .ic { width: 14px; height: 14px; }

/* Клетка одинакова на сайте и в редакторе: размер выбран под палец, но и
   читается на просмотре лучше мелкой. min-width обязателен — без него браузер
   сжимает столбцы, когда таблица шире экрана. */
td.cell {
  width: 38px;
  min-width: 38px;
  height: 38px;
  text-align: center;
  position: relative;
  z-index: 0;
}

/* Клетка кондуита. Плюс — настоящий знак, а не белая полоска поверх тёмного
   квадрата: браузеры с принудительной тёмной темой инвертируют цвета сами, и
   конструкция «фон плюс накладка» под инверсией теряет контраст. Текст же
   инвертируется вместе с фоном, поэтому знак виден в любой теме.

   Обводка пустой клетки задана внутренней тенью, а не рамкой: рамка меняет
   размер коробки, и клетка дёргалась бы при простановке плюса. */
.mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  margin: 0 auto;
  font-size: 19px;
  font-weight: 700;
  line-height: 1;
  color: transparent;
  background: var(--cell-off);
  box-shadow: inset 0 0 0 1px var(--cell-edge);
}

.mark.on {
  background: var(--cell-on);
  color: var(--cell-ink);
  box-shadow: none;
}

/* Кондуит смотрят, а не трогают: имена не выделяются и не отзываются нигде,
   клетки — везде, кроме редактора. Прокрутка вбок остаётся: касание достаётся
   прокручиваемой обёртке, а не таблице внутри неё. */
.conduit-split {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  cursor: default;
}

table.conduit.names,
table.conduit.cells:not(.edit) { pointer-events: none; }

/* Граница остаётся распоркой, но не рисуется: саму черту ведёт ::before
   панели, во всю её ширину. Пока граница была видимой, черт получалось две —
   короткая внутри таблицы и длинная поверх поля, и шли они впритык друг к
   другу, потому что фон псевдоэлемента отсчитывается от padding-box, а у
   панели есть своя нижняя граница в пиксель. Убирать `border-top` совсем
   нельзя: на нём стоит высота строк подвала. */
table.conduit tfoot td {
  border-top: 1px solid transparent;
  text-align: center;
  color: var(--ink-muted);
  font-size: 11px;
  height: 24px;
}

table.conduit tfoot td.pname {
  text-align: left;
  color: var(--ink-muted);
  font-size: 11.5px;
}

table.conduit tfoot tr.weights td { color: var(--ink-2); font-weight: 560; }

/* ── прочее ────────────────────────────────────────────── */

.section-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 22px 0 10px;
}

/* Заголовок раздела и подпись под ним расходятся по кеглю сильно и нарочно:
   на этом контрасте и держится вся страница, других украшений у неё нет. */
.section-title {
  font-family: var(--font-display);
  font-size: 21px;
  font-weight: 650;
  letter-spacing: -0.025em;
  white-space: nowrap;
}

/* Имя ученика — заголовок его страницы, а не подпись к блоку. */
.section-head.big { align-items: center; margin-top: 6px; }
.section-head.big .section-title {
  font-size: 31px;
  font-weight: 700;
  letter-spacing: -0.035em;
}

.section-note { font-size: 12.5px; color: var(--ink-muted); }

.type-name { display: inline-flex; align-items: center; gap: 9px; }
.type-name b { font-weight: 620; }
.tblock { padding-bottom: 4px; }

/* блок темы: заголовок, полоса, строки подразделов */
.tblock { padding: 11px 0; border-bottom: 1px solid var(--grid); }
.tblock:first-child { padding-top: 2px; }
.tblock:last-child { border-bottom: 0; padding-bottom: 2px; }

/* Вкладка тем — единственное место, где текст мелким быть не должен: по нему
   тыкают пальцем и по нему же сверяют разметку задач. */
.tblock-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
  min-height: 34px;   /* с кнопкой удаления и без неё — одна высота */
  font-size: 17px;
}

.subline {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 6px 0 0;
  font-size: 15px;
  color: var(--ink);
}

/* В строке подраздела теперь два предмета: кнопка со значком и название.
   Обрезание длинного названия многоточием переехало на сам текст: у гибкой
   строки оно не сработало бы, текст в ней — безымянный кусок между
   предметами. */
.subline-name { display: flex; align-items: center; gap: 9px; min-width: 0; }
/* Обрезание длинного текста многоточием. Стоит на самом тексте, а не на
   строке, которая его держит: строка эта — гибкий контейнер со значком слева,
   а в нём текст лежит безымянным куском, и до безымянного text-overflow не
   достаёт. Обрезка тогда происходит, но многоточия не рисуется — слово просто
   обрывается на середине буквы.

   Отсюда правило: там, где рядом с текстом стоит значок, текст заворачивается
   в свой span с этим классом. */
.ell {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Кнопка выбора значка: сам значок и есть её содержимое. Рамка взята заметная,
   а не бликовая: бликовая (--border) на светлой теме сливается с карточкой, и
   двадцать таких кнопок выглядели бы просто рядом значков — нажать их никто бы
   не догадался. Заливки при этом нет: два десятка залитых квадратов в столбец
   зарябили бы список. */
.icon-pick {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex: none;
  padding: 0;
}

.icon-pick.open { background-color: var(--ink); color: var(--ink-inv); }

/* Ярлык в россыпи значков — без подписи: значок и выбирают глазами, а два
   десятка названий рядом превратили бы россыпь в список. */
.chip.icon-chip { padding: 7px 10px; }
.subline-val { font-variant-numeric: tabular-nums; white-space: nowrap; }

.confirm {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

.mini-btn.danger { color: var(--bad); border-color: var(--bad); }

/* Шкала решаемости — ряд мелких блоков вместо одной широкой заливки: крупную
   плоскую заливку принудительная тёмная тема телефона гасит, мелкую оставляет.
   Незакрашенные блоки заодно показывают, из чего доля считается. */
.meter {
  display: flex;
  gap: 2px;
  align-items: center;
}

/* Размер квадрата задан жёстко, а не долей ширины: шкалы должны быть одной
   длины во всех строках, иначе их не сравнить взглядом. */
.meter > i {
  flex: none;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--meter-off);
}

/* шкала подтемы мельче шкалы раздела, но делений столько же */
.meter.small > i { width: 7px; height: 7px; }

/* Строка «название — шкала — счёт». Шкала и счёт имеют жёсткую ширину, имя
   забирает остаток — поэтому шкала стоит на одном месте во всех строках, как
   бы ни звалась тема. Отступ подтемы сделан внутри её колонки имени, а не
   отступом строки: иначе он сдвинул бы и шкалу. */
.pline {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 108px 54px;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  max-width: 430px;
}

.pline.sub .pline-name { padding-left: 14px; }

.pline-name {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  font-weight: 560;
}

.pline.sub .pline-name {
  font-weight: 400;
  font-size: 12.5px;
  color: var(--ink-2);
}

.pline-val {
  font-size: 12.5px;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

td .date { margin-left: 8px; font-size: 12px; }

.type-val {
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  font-size: 13px;
  white-space: nowrap;
}

.series-mini {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
}

.smini {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 6px 9px;
  font-size: 12.5px;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.smini b { color: var(--ink); font-weight: 600; }

.tip {
  position: fixed;
  z-index: 40;
  pointer-events: none;
  background: var(--ink);
  color: var(--surface);
  font-size: 12px;
  line-height: 1.35;
  padding: 6px 9px;
  border-radius: var(--radius-sm);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
  max-width: 220px;
  opacity: 0;
  transition: opacity .1s;
}

.tip.show { opacity: 1; }

.foot {
  margin-top: 26px;
  padding-top: 14px;
  border-top: 1px solid var(--grid);
  color: var(--ink-muted);
  font-size: 12.5px;
}

/* ── движение ───────────────────────────────────────────
   Анимируется только смена раздела и отклик на касание. Перерисовка от
   фильтра ничего не анимирует: таблица мигала бы на каждый чип. */

@keyframes rise {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

@keyframes fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Смена экрана. Содержимое уходит и приходит целиком, одним слоем: и уход, и
   приход — это одна прозрачность и один сдвиг на всём #main сразу. Поэлементное
   появление отсюда убрано нарочно — на списке в три десятка строк оно читалось
   не как оживление, а как отрисовка на глазах. Шапка, полоса вкладок и
   указатель в движении не участвуют: они живые элементы страницы и остаются на
   месте, пока под ними меняется содержимое.

   Уход короткий и с разгоном, приход длиннее и с торможением: тогда смена
   читается как одно движение вперёд, а не как две одинаковые половины.

   Направление сдвига задаёт скрипт: открытие карточки, возврат из неё и смена
   вкладки двигаются по-разному, но правило на всех одно. */
#main.leaving {
  opacity: 0;
  transform: translateY(var(--out-dy, 0));
  transition: opacity .08s ease-in, transform .08s ease-in;
}

@keyframes screenIn {
  from { opacity: 0; transform: translateY(var(--in-dy, 8px)); }
  to { opacity: 1; transform: none; }
}

#main.entering { animation: screenIn .26s cubic-bezier(.22, .8, .24, 1) both; }


.banner { animation: rise .2s ease-out both; }

/* Плитки и плашки в статистике ученика — данные, а не кнопки: ни отклика на
   касание, ни подъёма под курсором, чтобы не звали нажать. */
.card { transition: border-color .16s ease; }

/* Отклик на касание. На телефоне подсветка касания погашена нарочно, поэтому
   без этого кнопки кажутся мёртвыми: нажал — и ничего. Сжатие берём
   преобразованием, оно не трогает разметку и ничего не сдвигает вокруг. */
.chip, .ghost-btn, .primary-btn, .icon-btn, .mini-btn, .icon-pick,
.tab, .cal-day, .cal-nav, .banner-close, .picker-btn,
.step-btn, .step-val, .wchip {
  transition: background-color .14s ease, color .14s ease,
              border-color .14s ease, opacity .14s ease;
}

/* Класс ставится на нажатие из скрипта, анимация доигрывает сама. Через
   :active на телефоне это не работает: браузер придерживает состояние, пока
   не убедится, что палец не поехал прокручивать. */
@keyframes tap {
  0% { transform: scale(.92); }
  100% { transform: scale(1); }
}

@keyframes tapRow {
  0% { background: var(--wash); }
  100% { background: transparent; }
}

/* Класс продублирован нарочно: иначе первые полсекунды после смены раздела
   отклик глушился бы анимацией входа, у которой вес селектора выше. */
.tap.tap { animation: tap .19s cubic-bezier(.2, .8, .3, 1); }

/* строку рейтинга не сжимаем — по ширине экрана это выглядит рывком; вместо
   этого она отзывается подсветкой */
tr.clickable.tap.tap { animation: none; }
tr.clickable.tap td { animation: tapRow .4s ease-out; }

table.conduit.edit .mark { transition: background-color .14s ease; }


table.data tbody tr { transition: background-color .12s ease; }
.mark { transition: background-color .14s ease; }
.bar { transition: width .25s cubic-bezier(.2, .7, .3, 1); }
.meter > i { transition: background-color .16s ease; }

.tip { animation: fade .12s ease-out both; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-delay: 0ms !important;
    transition-duration: .01ms !important;
  }
}

/* ── редактор ───────────────────────────────────────────── */

.field { display: flex; flex-direction: column; gap: 4px; }

.field-label {
  font-size: 11.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.input {
  appearance: none;
  font: inherit;
  font-size: 15px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  min-height: 40px;
  min-width: 0;
}

.input:focus { outline: 2px solid var(--s1); outline-offset: -1px; }
.input.short { max-width: 120px; }
/* Узкое поле — номер: ширина задаётся классом, а не местом в строке. По месту
   было нельзя: у выходного и матбоя номера нет, и 110 пикселей доставались
   дате — она переносилась на три строки. */
.frow.top > .field.narrow { flex: 0 0 110px; }
.input.tiny { width: 62px; text-align: center; font-variant-numeric: tabular-nums; }
select.input { padding-right: 6px; }

.frow {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px;
}

.frow.gap { margin-top: 10px; align-items: center; }

/* когда в строке раскрыт календарь, соседние поля не должны прилипать к его низу */
.frow.top { align-items: flex-start; }
.frow.top > .field { flex: 1 1 190px; }

.primary-btn {
  appearance: none;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--surface);
  border-radius: 999px;
  font: inherit;
  font-size: 14px;
  font-weight: 560;
  padding: 9px 18px;
  min-height: 40px;
  cursor: pointer;
}

/* Вторичное действие: «+ задача», «+ пункт», «+ гроб», «Выбрать pdf»,
   «Запомнить». Своих стилей у этой кнопки не было вовсе — в редакторе она
   рисовалась системной серой кнопкой браузера, шрифтом Arial и рамкой outset.

   От ярлыка отбора её отличает вес: ярлык — то, что выбирают, кнопка — то, что
   делают, и делают пальцем. Отсюда 40 в высоту, как у поля ввода и у главной
   кнопки: в строке редактора они стоят рядом и должны стоять вровень. */
.ghost-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  color: var(--ink);
  font-size: 14px;
  font-weight: 560;
  line-height: 1;
  padding: 9px 17px;
  min-height: 40px;
  white-space: nowrap;
}

.ghost-btn:disabled { opacity: .38; cursor: default; }
.ghost-btn:disabled:hover { background-color: var(--quiet); }

/* Плюс — отдельный знак, а не первый символ подписи: крупнее текста и тише по
   цвету, поэтому читается как знак действия, а «задача» остаётся словом. Он же
   держит все кнопки добавления одним рядом: глаз ловит столбик плюсов. */
.ghost-btn.add::before {
  content: "+";
  font-size: 19px;
  font-weight: 400;
  line-height: 1;
  color: var(--ink-muted);
  margin-top: -2px;
}

.ghost-btn.add:hover::before { color: var(--ink); }

.primary-btn:disabled { opacity: .45; cursor: default; }

.ghost-btn.danger { color: var(--bad); border-color: var(--bad); }

.icon-btn {
  font-size: 17px;
  line-height: 1;
  width: 34px;
  min-height: 34px;
}

.icon-btn:hover { color: var(--bad); border-color: var(--bad); }

/* Кнопки удаления залиты красным целиком — на телефоне наведения нет вовсе, и
   цвет должен быть виден сразу, до нажатия. Плашка у них та же, что у плиток:
   плотная заливка, косой блик, тёплое пятно в углу. На кнопке в 34 пикселя
   пятно занимает верхний угол и читается бликом — красное от этого выглядит
   раскалённым, а не крашеным, что удалению как раз к лицу. */
.icon-btn.del, .icon-btn.danger, .primary-btn.danger {
  --solid-bg: var(--danger-bg);
  --solid-glow: var(--danger-glow);
}

.icon-btn.del:hover, .icon-btn.danger:hover,
.primary-btn.danger:hover {
  color: #fff;
  border-color: var(--solid-edge);
  filter: brightness(1.08);
}

/* «передумал» — стрелка нарисована в svg, а не рамками и не символом:
   и рамочная, и шрифтовая на части телефонов не показывались вовсе */
.icon-btn.back { color: var(--ink-2); }
.icon-btn.back:hover { color: var(--ink); border-color: var(--border-strong); }
.icon-btn svg { display: block; margin: 0 auto; }

/* Квадратная кнопка добавления стоит в строке рядом с полем ввода, поэтому и
   ростом с него: 34 против 40 читались как случайность. Крестик удаления при
   этом остаётся 34 — он живёт в столбце таблицы, ширина которого задана. */
.icon-btn.add {
  color: var(--ink-2);
  font-size: 19px;
  width: 40px;
  min-height: 40px;
}
.icon-btn.add:hover { color: var(--ink); border-color: var(--border-strong); }

/* поле ввода занимает строку, кнопка стоит с краю */
.frow.gap > .input { flex: 1; min-width: 0; }

.prow-wrap { padding: 7px 0; border-bottom: 1px solid var(--grid); }

.prow {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr) auto 34px;
  align-items: center;
  gap: 8px;
}

.chip.day.has-draft { position: relative; }

.chip.day.has-draft::after {
  content: "";
  position: absolute;
  top: 4px;
  right: 5px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--s2);
}

/* у гроба правится только число, буква Г — подпись слева от поля, буква
   пункта — справа, поэтому колонка шире, чем у задачи серии */
.prow.grave { grid-template-columns: 80px minmax(0, 1fr) auto 34px; }
.prow.grave.part { grid-template-columns: 92px minmax(0, 1fr) auto 34px; }

/* спрошено удаление: на месте крестика два бокса — «удалить» и «передумал» */
.prow.asking { grid-template-columns: 62px minmax(0, 1fr) auto 76px; }
.prow.grave.asking { grid-template-columns: 80px minmax(0, 1fr) auto 76px; }
.prow.grave.part.asking { grid-template-columns: 92px minmax(0, 1fr) auto 76px; }

.grave-id {
  display: flex;
  align-items: center;
  gap: 4px;
}

.grave-pre {
  font-size: 15px;
  font-weight: 560;
  color: var(--ink-2);
}

/* буква пункта — подпись, а не поле: её правят через «+ пункт», не руками */
.grave-post {
  font-size: 15px;
  font-weight: 560;
  color: var(--ink-2);
}

.chip.day.new { border-style: dashed; }

/* день заведён здесь и на сайт ещё не уехал */
.chip.day.local { border-style: dashed; border-color: var(--accent-hi); }
.chip.day.local b { color: var(--accent-hi); }

/* день помечен к удалению: уедет с ближайшим сохранением, касание возвращает */
.chip.day.gone { border-color: var(--bad); border-style: dashed; }
.chip.day.gone b { color: var(--bad); text-decoration: line-through; }
.chip.day.gone small { color: var(--bad); opacity: 1; }

.ghost-btn.danger:hover { background: var(--wash); }
.chip.day.new b { font-size: 15px; }

table.conduit thead th:not(.pname):not(.pcount) {
  width: 38px;
  min-width: 38px;
}

/* В редакторе клетка — кнопка. Сжатие при нажатии безопасно: фамилии живут в
   отдельной таблице, наехать на них клетке нечем. */
table.conduit.edit .mark {
  appearance: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

/* Простановка плюса: короткое сжатие с лёгким перелётом обратно. Одна
   величина, одно свойство — этого хватает, чтобы касание чувствовалось. */
@keyframes markOn {
  0% { transform: scale(.7); }
  55% { transform: scale(1.08); }
  100% { transform: scale(1); }
}

@keyframes markOff {
  0% { transform: scale(.86); }
  100% { transform: scale(1); }
}

table.conduit.edit .mark.pop { animation: markOn .22s cubic-bezier(.2, .8, .3, 1); }
table.conduit.edit .mark.drop { animation: markOff .16s ease-out; }

/* Ширина задана и итоговым столбцам тоже: без неё они плавали от того, какое
   число в них попало, и правый край кондуита гулял от серии к серии. */
table.conduit .pcount {
  width: 56px;
  min-width: 56px;
  text-align: center;
  font-size: 11px;
  color: var(--ink-muted);
  padding: 0 8px;
  border-left: 1px solid var(--grid);
  font-variant-numeric: tabular-nums;
}

table.conduit tbody .pcount { font-size: 12px; }
table.conduit .pcount.total { color: var(--ink); font-weight: 600; }

/* карточка сохранения */
.savecard {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
}

/* Карточка не должна менять размер, когда одна кнопка сменяется двумя: обычная
   кнопка ниже основной на восемь пикселей, и от этого карточка подпрыгивала. */
.savecard.center {
  justify-content: center;
  flex-wrap: wrap;
  min-height: 68px;
}

.savecard-main { flex: 1; min-width: 0; }
.savecard-title { font-size: 14px; }
.savecard-note { font-size: 12.5px; color: var(--ink-muted); margin-top: 2px; }

/* свои выпадающие меню вместо системных */
.picker-btn {
  appearance: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  min-height: 40px;
  padding: 8px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition: border-color .14s ease, background-color .14s ease;
}

.picker-btn.open { border-color: var(--ink); }
.picker-btn:active { transform: scale(.99); }

.picker-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.picker-caret { color: var(--ink-muted); font-size: 11px; flex: none; }

.chooser {
  margin: 8px 0 2px;
  padding: 10px;
  border: 1px solid var(--grid);
  border-radius: var(--radius);
  background: var(--plane);
  animation: rise .16s ease-out both;
}

.chooser .subs-row { margin-top: 8px; }

.datefield { position: relative; min-width: 190px; }

.calendar {
  margin-top: 8px;
  padding: 10px;
  border: 1px solid var(--grid);
  border-radius: var(--radius);
  background: var(--plane);
  animation: rise .16s ease-out both;
}

.cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.cal-title { font-size: 14px; font-weight: 560; }

.cal-nav {
  appearance: none;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink-2);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 16px;
  line-height: 1;
  width: 34px;
  height: 34px;
  cursor: pointer;
}

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 3px;
}

.cal-wd {
  text-align: center;
  font-size: 11px;
  color: var(--ink-muted);
  padding-bottom: 2px;
}

.cal-empty { height: 36px; }

.cal-day {
  appearance: none;
  border: 1px solid transparent;
  background: var(--surface);
  color: var(--ink);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 13.5px;
  font-variant-numeric: tabular-nums;
  height: 36px;
  cursor: pointer;
  transition: background-color .12s ease, color .12s ease;
}

.cal-day:hover { background: var(--wash); }
.cal-day.today { border-color: var(--border-strong); }

.cal-day.sel {
  background: var(--ink);
  color: var(--surface);
  border-color: var(--ink);
  font-weight: 600;
}

.cal-foot {
  display: flex;
  justify-content: space-between;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--grid);
}

.color-chip { padding: 8px 12px; }

.banner {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 11px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  font-size: 13.5px;
  margin-bottom: 14px;
}

.banner.good { border-color: var(--good); color: var(--ink); }
.banner.bad { border-color: var(--bad); color: var(--ink); }
.banner > span { flex: 1; min-width: 0; }

.banner-close {
  appearance: none;
  border: 0;
  background: none;
  color: var(--ink-muted);
  font: inherit;
  font-size: 16px;
  line-height: 1;
  padding: 0 2px;
  cursor: pointer;
}

/* День, который ждёт: только что сохранённый или только что удалённый. Сайт
   переразворачивается около минуты, и до тех пор правка по нему ушла бы мимо
   данных — поэтому кнопка заперта и приглушена целиком, включая букву. */
.chip.day.pending {
  border-style: dotted;
  color: var(--ink-muted);
}

.chip.day.pending b { color: var(--ink-muted); }

/* ── цена задачи ───────────────────────────────────────── */

/* Цена в строке задачи. Приглушённая — считается формулой, плотная и в рамке
   цвета отличия — задана вручную: разницу видно, не открывая панель. */
.wchip {
  appearance: none;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink-muted);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  min-width: 38px;
  min-height: 34px;
  padding: 0 6px;
  cursor: pointer;
}

.wchip:hover { background: var(--wash); border-color: var(--border-strong); }

.wchip.on {
  color: var(--accent-hi);
  border-color: var(--accent-hi);
  background: var(--accent-wash);
}

/* Ряд кнопок: по десять по краям, по одному внутри, число посередине. Числа
   на телефоне не набирают, а дотянуться до любой разумной цены хватает. */
.wrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex-wrap: wrap;
}

.step-btn.wide { width: auto; padding: 0 10px; font-size: 14px; }

.wfoot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid var(--grid);
}

.wnote { font-size: 12.5px; color: var(--ink-muted); }

.mini-btn:disabled { opacity: .4; cursor: default; }

.mini-btn:disabled:hover { color: var(--ink-muted); background: var(--quiet); }

/* ── гроборешения ──────────────────────────────────────── */

/* Счётчик надбавки вместо поля ввода: числового поля здесь нет вовсе.
   Системное привело бы с собой клавиатуру на пол-экрана и крутилки, а
   надбавку всё равно ставят по одному баллу — двух кнопок довольно. */
.stepper {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
}

.step-btn {
  font-size: 19px;
  line-height: 1;
  width: 34px;
  min-height: 34px;
}

.step-btn:disabled { opacity: .35; cursor: default; }

.step-btn:disabled:hover { color: var(--ink-2); background-color: var(--quiet); }

/* Показание, а не кнопка: нажимать на само число некуда. Ноль приглушён,
   поставленное — нет, так с одного взгляда видно, кому баллы уже дописаны. */
.step-val {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink-muted);
  border-radius: var(--radius-sm);
  font-size: 15px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
  min-width: 56px;
  min-height: 34px;
  padding: 0 8px;
}

.step-val.on { color: var(--ink); border-color: var(--border-strong); }

/* Цена решения забирает остаток строки, поэтому крестик стоит у правого края
   на одном месте во всех блоках. */
.solution-price {
  display: flex;
  align-items: baseline;
  gap: 7px;
  flex: 1;
  min-width: 0;
  white-space: nowrap;
}

.price-label {
  font-size: 11.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.price-val {
  font-size: 16px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
}

/* Слагаемые набраны мельче и приглушены: итог должен читаться первым. */
.price-sum {
  font-style: normal;
  font-size: 12.5px;
  font-weight: 400;
  color: var(--ink-muted);
}

/* ── гробарий на сайте ─────────────────────────────────── */

/* Гроб и под ним те, кто его взял. Номер отбит от темы, как в кондуите номер
   задачи от полоски: сначала опознают гроб, потом читают, чей он. */
.grave-head {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 6px;
}

.grave-num {
  font-size: 15px;
  font-weight: 620;
  font-variant-numeric: tabular-nums;
}

.grave-theme {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  font-size: 12.5px;
  color: var(--ink-2);
}

/* Имя ужимается, цена — никогда: по ней и сравнивают строки между собой. */
.grave-line {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 10px;
  padding: 4px 0 4px 14px;
}

.grave-who { min-width: 0; font-size: 15px; font-weight: 500; }

.grave-val {
  font-variant-numeric: tabular-nums;
  font-weight: 620;
  white-space: nowrap;
}

.grave-sum {
  font-style: normal;
  font-weight: 400;
  font-size: 12.5px;
  color: var(--ink-muted);
}

/* «пока никто», «ни одной» — держим отступ строки с именем, чтобы пустой блок
   не выглядел короче взятого и список не рвался. */
.block-none {
  padding: 4px 0 4px 14px;
  font-size: 13px;
  color: var(--ink-muted);
}

/* ── ликбезы ───────────────────────────────────────────── */

/* Вся строка — кнопка скачивания: на телефоне целиться в маленькую ссылку
   рядом с названием неудобно, а другого действия у строки и нет. */
/* Строка с файлом — вся кнопка целиком: сюда заходят с одной целью, забрать
   листок, и другого действия у строки нет. Поэтому она и плашка, а не строка
   списка: на экране это единственное, за чем сюда пришли, и выглядеть оно
   должно как предмет, который берут. */
.lik-row {
  --solid-bg: var(--sheet-bg);
  --solid-glow: var(--sheet-glow);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: var(--tap);
  padding: 12px 14px;
  margin-bottom: 8px;
  border-radius: var(--radius-sm);
  text-decoration: none;
  cursor: pointer;
}

.lik-row.lik-ans {
  --solid-bg: var(--ans-bg);
  --solid-glow: var(--ans-glow);
}

.lik-row.lik-arch {
  --solid-bg: var(--arch-bg);
  --solid-glow: var(--arch-glow);
}

.lik-row > * { position: relative; }
.lik-row:last-child { margin-bottom: 0; }
.lik-row:hover { filter: brightness(1.08); }

.lik-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.lik-title {
  font-size: 15px;
  font-weight: 560;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lik-meta { font-size: 12px; color: var(--ink-muted); }

/* Посвящение на вкладке зачёта. Плашка тёплая — та же, что у «Самого ценного
   плюса»: благодарность и должна быть тёплой. Стоит между вопросами и ответами
   нарочно — читается ровно перед тем, за что благодарят. */
.thanks {
  --solid-bg: var(--warm-bg);
  --solid-glow: var(--warm-glow);
  padding: 16px 18px;
  border-radius: var(--radius);
  margin-bottom: 14px;
  font-size: 14.5px;
  line-height: 1.5;
}

.thanks b { font-weight: 620; }

/* Стрелка вместо слова «скачать». Слово объясняло то, что и так очевидно:
   строка одна, действие у неё одно, и заходят сюда ровно за ним. Стрелка на
   плашке занимает угол и не спорит с названием файла. */
.lik-get {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  font-size: 17px;
  line-height: 1;
  color: #fff;
  border: 1px solid var(--solid-edge);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
}

/* ── зачёт: подтемы ────────────────────────────────────── */

/* Подтемы перечислены все, включая те, к которым ответа ещё нет: экран должен
   отвечать не только «что есть», но и «сколько осталось». Готовая подтема
   отличается кнопкой, неготовая — подписью вместо неё; строка одна и та же,
   поэтому список читается ровно, а не рвётся на две стопки. */
/* Названия разделов зачёта длинные — «IV. Комбинаторика и теория
   вероятностей». Общий заголовок раздела набран в одну строку нарочно, но там
   он короткий; здесь запрет на перенос выталкивал подпись за край экрана
   и давал горизонтальную прокрутку на телефоне. Снимаем его только своим. */
.zt-part-head .section-title { white-space: normal; min-width: 0; }
.zt-part-head .section-note { flex: none; }

.zt-topic { border-bottom: 1px solid var(--grid); }
.zt-topic:last-child { border-bottom: 0; }

.zt-head {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: var(--tap);
  padding: 9px 2px;
  cursor: pointer;
  list-style: none;
}

/* Родной треугольник <details> убран в обоих движках: вместо него своя
   галочка, которая поворачивается. */
.zt-head::-webkit-details-marker { display: none; }
.zt-head { -webkit-tap-highlight-color: transparent; }

.zt-head::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  margin: 0 1px;
  border-right: 1.6px solid var(--ink-muted);
  border-bottom: 1.6px solid var(--ink-muted);
  transform: rotate(-45deg);
  transition: transform .16s ease;
}

.zt-topic[open] > .zt-head::before { transform: rotate(45deg); }

.zt-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.zt-line {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.zt-code {
  flex: none;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
}

.zt-title {
  font-size: 14.5px;
  font-weight: 560;
  color: var(--ink);
  min-width: 0;
}

.zt-meta {
  font-size: 11.5px;
  color: var(--ink-muted);
  padding-left: 30px;
}

/* Кнопка скачивания у подтемы — тот же фиолетовый, что у ответов зачёта:
   это они и есть. Архив прошлых лет красится своим цветом, см. --arch-bg. */
.zt-get {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  font-size: 16px;
  line-height: 1;
  text-decoration: none;
  color: #fff;
  border-radius: 999px;
  background: var(--ans-bg);
  box-shadow: inset 0 1px 0 var(--solid-edge);
}

.zt-get:hover { filter: brightness(1.12); }

/* Подтема без ответа — приглушённая строка: список идёт ровно, но глаз сразу
   отделяет готовое от незакрытого, не читая подписи. */
.zt-empty .zt-title { color: var(--ink-2); font-weight: 500; }

.zt-qs {
  margin: 0 0 10px;
  padding: 2px 0 0 30px;
  list-style: none;
}

.zt-q {
  display: flex;
  gap: 8px;
  padding: 3px 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-2);
}

.zt-qcode {
  flex: none;
  font-variant-numeric: tabular-nums;
  font-size: 11.5px;
  color: var(--ink-muted);
  padding-top: 1px;
  min-width: 34px;
}

.zt-qtext { min-width: 0; }

/* Формулы приходят готовой разметкой со стороны сборки: библиотеки для них
   на этой странице нет, и заводить её ради двух десятков коротких выражений
   незачем. Курсив отделяет их от текста вопроса. */
.zt-qtext .m { font-style: italic; }
.zt-qtext .m sup,
.zt-qtext .m sub { font-style: normal; font-size: 0.75em; }

@media (max-width: 560px) {
  .zt-meta, .zt-qs { padding-left: 0; }
  .zt-qcode { min-width: 30px; }
  .zt-title { font-size: 14px; }
}

/* ── плюсы по сериям ───────────────────────────────────── */

/* Шапка серии: номер с датой слева, итоги справа. Итоги набраны мелко — они
   подпись к списку, а не он сам. */
.dblock-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 7px;
}

.dblock-name { font-size: 15px; font-weight: 620; }

.dblock-date {
  margin-left: 8px;
  font-size: 12.5px;
  font-weight: 400;
  color: var(--ink-muted);
}

.dblock-val {
  flex: none;
  font-size: 12.5px;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}


@media (max-width: 560px) {
  .prow { grid-template-columns: 48px minmax(0, 1fr) auto 32px; column-gap: 6px; }
  .prow.grave { grid-template-columns: 66px minmax(0, 1fr) auto 32px; }
  .prow.grave.part { grid-template-columns: 78px minmax(0, 1fr) auto 32px; }
  .prow.asking { grid-template-columns: 48px minmax(0, 1fr) auto 76px; }
  .prow.grave.asking { grid-template-columns: 66px minmax(0, 1fr) auto 76px; }
  .prow.grave.part.asking { grid-template-columns: 78px minmax(0, 1fr) auto 76px; }
  /* на телефоне чип цены ужимаем: место нужнее названию темы */
  .wchip { min-width: 32px; padding: 0 4px; font-size: 12.5px; }
  .input.tiny { width: 48px; }
  .datefield { min-width: 0; }
  .step-val { min-width: 48px; }
}

@media (max-width: 560px) {
  .wrap { padding: 0 12px 48px; }
  .brand-box { font-size: 46px; }
  .section-title { font-size: 19px; }
  .section-head.big .section-title { font-size: 27px; }
  .tile-value { font-size: 27px; }
  table.data td, table.data th { padding: 9px 6px; }


  /* На телефоне числовым колонкам оставляем ровно столько, сколько нужно их
     заголовкам и значениям, остальное отдаём имени: обрезанная фамилия хуже
     тесной колонки с числом. */
  table.data.fixed th { font-size: 10.5px; }
  table.data.fixed th.rank { width: 38px; }
  table.data.fixed th.c-score { width: 56px; }
  table.data.fixed th.c-tasks { width: 52px; }
  table.data.fixed th.c-avg { width: 64px; }
  table.data.fixed td.name { font-size: 13.5px; }
  .pline { gap: 8px; }
  table.conduit th.pname, table.conduit td.pname {
    min-width: 118px;
    font-size: 13px;
    padding: 0 8px 0 10px;
  }
}

/* Строка с числом посередине: имя — сколько плюсов — крестик. Обычная строка
   подраздела двухколоночная, здесь колонок три. */
.subline.wide { grid-template-columns: 1fr auto auto; }

/* У файла зачёта колонок четыре: к имени, размеру и крестику добавилась отметка
   «вопросы». */
.subline.wide.four { grid-template-columns: 1fr auto auto auto; }
.subline.wide .subline-val { color: var(--ink-2); font-size: 13.5px; }
.subline .badge { margin-left: 8px; }

/* Системное поле выбора файла спрятано: у него чужая подпись и вид, который не
   подчинить. Нажимает его наша кнопка. */
.hidden-file {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Мелкая пометка у названия: «упр.» у упражнения, «новый» у ещё не уехавшего
   файла. Не кнопка и не ссылка — просто подпись, поэтому без рамки. */
.badge {
  font-style: normal;
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--ink-muted);
  vertical-align: 1px;
}

/* Имя ученика правится на месте, поэтому это поле ввода, а выглядеть должно
   строкой списка: рамка появляется только при касании. */
.input.flat {
  border-color: transparent;
  background: none;
  padding-left: 0;
  min-height: 34px;
}

.input.flat:focus { border-color: var(--border-strong); padding-left: 10px; }
.name-edit { display: flex; align-items: center; gap: 6px; min-width: 0; }
.name-edit .input { flex: 1; min-width: 0; }

/* «не был» рядом с номером серии: не ошибка и не тревога, просто факт. */
.dblock-miss {
  margin-left: 8px;
  font-size: 12px;
  font-weight: 400;
  color: var(--ink-muted);
}

/* Клетка посещаемости. Она говорит «был», а не «сделал», поэтому и выглядит
   иначе: кружок поменьше вместо квадрата со знаком. Цвет тот же — столбец не
   должен перетягивать взгляд на себя, плюсы в кондуите важнее.

   Пустая строка сама по себе двусмысленна: то ли ничего не решил, то ли его не
   было; этот столбец и отвечает на вопрос. */
.mark.att {
  width: 20px;
  height: 20px;
  border-radius: 999px;
}

/* Столбец посещаемости отделён от счётного такой же линией, как и он сам. */
table.conduit .patt { border-left: 1px solid var(--grid); }

/* Дата выдачи стоит рядом с номером серии, и места ей остаётся немного: своя
   основа ширины, иначе строка переносится и номер занимает её целиком. */
.frow.top > .field.date { flex: 1 1 150px; }

/* ── переходы между экранами ───────────────────────────── */

/* Движение выключается системной настройкой — она не про красоту. */
@media (prefers-reduced-motion: reduce) {
  .tabs::before { transition: none; }
  #main.leaving { transition: none; }
}
}

/* Подсветка столбца в кондуите. Касание номера задачи гасит остальные: «кто
   взял эту» — самый частый вопрос, а вести глазами по строке неудобно.
   Гасим прозрачностью, а не цветом: цвет здесь занят под темы. */
table.conduit.cells .phead-cell { cursor: pointer; }

table.conduit.cells.has-hot td.cell:not(.hot) .mark,
table.conduit.cells.has-hot th:not(.hot) .phead,
table.conduit.cells.has-hot tfoot td:not(.hot) { opacity: .25; }

/* На большом экране кондуит крупнее. Раньше он был рассчитан только под палец
   на телефоне и на мониторе выглядел миниатюрой в углу панели: клетка в 38
   пунктов, фамилия обрезана на десятом знаке. Здесь места вдоволь — и клетка
   растёт, и фамилия помещается целиком. Обе таблицы поднимаются в высоте
   вместе: разъедься они хоть на пиксель, строки перестанут совпадать. */
@media (min-width: 1000px) {
  table.conduit th.pname, table.conduit td.pname {
    min-width: 264px;
    max-width: 264px;
  }

  .conduit-split { --head-h: 56px; }
  table.conduit tbody td { height: 48px; }
  td.cell { height: 48px; width: 52px; min-width: 52px; }
  table.conduit thead th:not(.pname):not(.pcount) { width: 52px; min-width: 52px; }

  .mark {
    width: 40px;
    height: 40px;
    font-size: 24px;
  }

  /* Значок темы в шапке столбца — четырнадцать пунктов на телефоне и двадцать
     здесь: он стоит под номером задачи и на большом экране в прежнем размере
     терялся точкой. */
  .phead { gap: 7px; width: 52px; }
  .phead .ic { width: 20px; height: 20px; }
  .phead-id { font-size: 13px; }

  table.conduit tbody .pcount { font-size: 13px; }
  table.conduit .pcount { width: 62px; min-width: 62px; }
}
