@layer base {
/* Оформление серверных страниц «Ритма»: вход, экран после входа, «Люди и доступ».
   Все значения — из tokens.css, ни одного цвета мимо переменных. Инлайновых стилей
   нет по двум причинам сразу: значение мимо токена не переопределится тёмной темой
   и разъедется с макетом молча, а на живом адресе оно ещё и не применится — там
   действует `style-src 'self'`.

   История этой строки стоит того, чтобы её знать. 05.09 я написал здесь, что CSP
   не существует, — и ошибся: заголовок отдаёт NPM перед приложением, а проверял я
   `localhost:8010` на самой ВМ, то есть ЗА прокси, где его и не может быть.
   Проверять политику надо с внешнего адреса; изнутри её не видно, и «не вижу»
   там не значит «нет».

   Экраны по макету (доска, календарь, прогресс) сюда не входят: это отдельная
   работа со своим стеком фронта. */

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

   Псевдоэлементами, а не `scrollbar-width`: стандартное свойство даёт тонкую
   полосу, но стрелки в Chrome остаются, а как только оно задано, псевдоэлементы
   на этом элементе перестают действовать. Поэтому стандартное свойство — только
   для Firefox, который псевдоэлементов не знает. Там, где полосу прячут совсем
   (карусель календаря, ряды чипов), у элемента своё правило, и оно сильнее. */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

/* Прозрачная рамка с обрезкой фона по содержимому даёт ползунку поля: он не
   липнет к краю и не задевает скруглённый угол шторки. */
::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  background-clip: content-box;
  border: 2px solid transparent;
  border-radius: 999px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--text-muted);
  background-clip: content-box;
}

::-webkit-scrollbar-button,
::-webkit-scrollbar-corner {
  display: none;
}

@supports (-moz-appearance: none) {
  html {
    scrollbar-width: thin;
    scrollbar-color: var(--line-strong) transparent;
  }
}

/* Браузерная подсветка по тапу (синий прямоугольник на всю строку) — это не
   наше состояние: на раскрытии мысли она вспыхивала на пол-экрана. Нажатие
   показываем сами — :active у кнопок и фон у строки (ritm#106). */
html {
  -webkit-tap-highlight-color: transparent;
  /* Мобильный Chrome сам увеличивает шрифт в блоках, ширина которых ему кажется
     маленькой, и пересчитывает это при смене содержимого — на переходе между
     разделами размер текста заметно дёргался (ritm#118). Размеры у нас заданы
     токенами, «помогать» не нужно. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* Рост органа управления считается вместе с рамкой и отступами: без этого поле
   с рамкой на пиксель выше кнопки без неё, и ряд «плавает» (ritm#106). */
button,
input,
select,
textarea,
.button,
.mini,
.chip {
  box-sizing: border-box;
}

/* Приложение-оболочка (ritm#128): страница не прокручивается, прокручивается
   экран внутри неё. Так нижнее меню и панель захвата перестают быть «прибитыми
   к окну»: в Safari на iOS такие элементы на доли секунды позиционируются от
   «большого» вьюпорта — без панелей браузера — и потом поправляются, отчего
   уезжают вниз и возвращаются. В раскладке оболочки пересчитывать нечего. */
html {
  height: 100%;
  /* Страница не прокручивается вовсе — говорим об этом прямо. Раньше это
     держалось только на `overflow: hidden` у body, а он до окна доходит
     передачей: если браузер её не сделает или высота разойдётся на пиксель
     из-за масштаба страницы, у окна появляются свои полосы прокрутки —
     светлые системные по краям (ritm#138). */
  overflow: hidden;
}

body {
  height: 100%;
  display: flex;
  flex-direction: column;
  /* Панель захвата стоит от низа оболочки. */
  position: relative;
  /* Прокрутка живёт внутри экрана, а не у страницы. */
  overflow: hidden;
  margin: 0;
  /* Страница не короче экрана (ritm#118): когда новый раздел оказывался ниже
     старого, браузер убирал и возвращал свою нижнюю панель, а вместе с ней
     прыгало наше меню. svh — «маленькая» высота окна: она не меняется, когда
     панель браузера появляется. */
  min-height: 100svh;
  /* Место под полосу прокрутки страницы больше не нужно: страница не
     прокручивается вовсе, прокручивается экран внутри неё (ritm#128). */
  background: var(--bg-page);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: var(--text-md);
  line-height: var(--leading-normal);
}

/* Мини-приложение на весь экран (ritm#366, класс ставит tg.js): оболочка
   уходит под строку состояния и кнопки Telegram («Закрыть», «⋯») — отступ
   сверху по вырезу экрана и кнопкам, которые сообщает клиент; нижнему меню —
   полоса «домой». Вне полноэкранного режима класса нет, отступов тоже.
   `--tg-top` — вся занятая Telegram высота сверху, одна на оболочку, шторки и
   выбор (ritm#482): верх каждого слоя считается от неё, а не своим числом. */
:root.tg-full {
  --tg-top: calc(var(--tg-safe-top, 0px) + var(--tg-content-top, 0px));
}

.tg-full body {
  box-sizing: border-box;
  padding-top: var(--tg-top);
}

.tg-full .tabbar {
  padding-bottom: var(--tg-safe-bottom, 0px);
}

.page,
.center {
  max-width: 44rem;
  margin: 0 auto;
  padding: var(--space-6) var(--space-4) var(--space-8);
}

/* Заглушка входа (ritm#104): знак, имя и одна строка о состоянии. Пустой
   тёмный экран с одной надписью человек читает как поломку. */
.center.gate {
  align-items: center;
  text-align: center;
  gap: var(--space-2);
}

.logo-box {
  fill: var(--accent-soft);
  stroke: var(--accent);
  stroke-width: 1.5;
}

.logo-bars {
  stroke: var(--accent);
}

.gate h1 {
  margin: 0;
}

.gate-line {
  margin: 0;
  font-size: var(--text-md);
}

.gate .widget {
  margin-top: var(--space-4);
}

/* Запасной путь входа (ritm#326): подпись и кнопка «Открыть в Telegram» —
   под местом виджета, столбиком по центру. */
.gate-fallback {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

.gate-fallback p {
  margin: 0;
}

.center {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  max-width: 26rem;
}

h1 {
  font-size: var(--text-2xl);
  font-weight: var(--weight-semibold);
  margin: 0 0 var(--space-2);
}

h2 {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  margin: var(--space-7) 0 var(--space-3);
}

p {
  margin: 0 0 var(--space-3);
}

.muted {
  color: var(--text-secondary);
}

.small {
  font-size: var(--text-sm);
}

.num {
  font-variant-numeric: tabular-nums;
}

.widget {
  margin: var(--space-4) 0;
  min-height: 44px;
}

/* Кнопка Telegram рисуется в своей рамке, и тему она берёт от той страницы, в
   которую вставлена. Пока схема не была объявлена, рамка шла за системной темой
   и на светлом приложении получалась тёмной (ritm#143). Схема указана и здесь
   явно: страница входа открывается и до того, как отработает переключатель
   темы. */
[data-theme="light"] .widget iframe {
  color-scheme: light;
}

[data-theme="dark"] .widget iframe {
  color-scheme: dark;
}

/* Сообщения — фактом, без восклицательных знаков: тон задан макетом. */
.notice {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  margin: 0 0 var(--space-4);
}

.notice-bad {
  background: var(--status-bad-soft);
  color: var(--status-bad);
}

.notice-warn {
  background: var(--status-warn-soft);
  color: var(--status-warn);
}

/* Кнопки — глаголами, зона нажатия не меньше 44px (макет, «Доступность»). */
.button {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-weight: var(--weight-medium);
  text-decoration: none;
  cursor: pointer;
}

/* `display: inline-flex` сильнее браузерного `[hidden] { display: none }`:
   без этой пары спрятанная кнопка всё равно рисуется (ritm#145). */
.button[hidden] {
  display: none;
}

.button:active {
  background: var(--accent-pressed);
}

.button-quiet {
  background: var(--surface-raised);
  color: var(--text);
  border-color: var(--line-strong);
}

.button:focus-visible,
input:focus-visible,
select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.row {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  flex-wrap: wrap;
  margin-top: var(--space-5);
}

.inline {
  display: inline;
}

.form {
  display: grid;
  gap: var(--space-3);
  max-width: 22rem;
}

.form label {
  display: grid;
  gap: var(--space-1);
  color: var(--text-secondary);
  font-size: var(--text-sm);
}

.form .check {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  color: var(--text);
  font-size: var(--text-md);
}

input,
select {
  min-height: 44px;
  padding: 0 var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--text);
  font: inherit;
}

fieldset {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-3) var(--space-2);
}

legend {
  color: var(--text-secondary);
  font-size: var(--text-sm);
}

/* Таблицы прокручиваются внутри себя: горизонтального скролла страницы быть не должно. */
.table {
  display: block;
  overflow-x: auto;
  width: 100%;
  border-collapse: collapse;
  margin-bottom: var(--space-4);
}

.table th,
.table td {
  text-align: left;
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

.table th {
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.foot {
  margin-top: var(--space-7);
  color: var(--text-muted);
  font-size: var(--text-xs);
}

/* Кегль полей на сенсорном вводе (ritm#291): не меньше 16px.
   WebKit на iOS сам увеличивает страницу, когда фокус уходит в поле мельче
   16px, — владелец видел это как «окошко шакалит и меняет масштабирование»:
   при 13px в «Описании» масштаб подскакивает на четверть, правый край уезжает
   за экран. Обратно iOS не откатывает, а откатывать нам нечем: страница не
   прокручивается вовсе (оболочка, ritm#128).
   Запретить масштабирование в `meta viewport` нельзя: в WKWebView, где и живёт
   мини-приложение, это отнимает и щипок руками. Значит — кегль.
   `!important` здесь по делу: у полей свои кегли в шести файлах, и правило
   обязано победить каждый, иначе зум вернётся там, где про него забыли. */
@media (pointer: coarse) {
  input,
  select,
  textarea {
    font-size: 16px !important;
  }

  /* Заголовочные поля и так крупнее 16px — им кегль оставляем. */
  .ctor-title {
    font-size: var(--text-lg) !important;
  }

  .task-h1-input {
    font-size: var(--text-xl) !important;
  }
}

/* «Люди и доступ»: занятое место — одним куском, число не отрывается от единицы
   и от потолка на узком экране (ritm#344). Пояс человека (ritm#532) — тоже:
   «Москва, UTC+3» не рвётся по запятой. */
.people-files,
.people-tz {
  white-space: nowrap;
}

/* Числа регулярной (ritm#346): счёт недели «1 / 3 на неделе», серия, пауза —
   рядом со значком повтора на «Дне», в «Задачах», на доске и «Регулярных».
   Подпись строки, а не действие: цветом подписи, табличными цифрами, одним
   куском. «Сегодня ещё нет» — охрой, как «серия под угрозой» в макете: день
   ещё идёт, тревоги нет, и красного тоже. Пауза — тише остального: дело стоит
   по решению человека, и считать его сейчас нечего. */
.reg-mark {
  flex: none;
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
  white-space: nowrap;
}

.reg-mark.is-open {
  color: var(--status-warn);
}

.reg-mark.is-paused {
  color: var(--text-muted);
}
}

/* Спрятанное прячется. Браузерное `[hidden] { display: none }` — правило того
   же веса, что любой класс с `display`, и проигрывает ему по порядку: так
   микрофон оставался в панели захвата, когда его уже подменили отправкой, а
   графы правила — в шторке (замечания владельца 10.09). Одно правило вместо
   починки каждого случая по отдельности.

   Слой — ui, а не base (ritm#340): важное объявление раннего слоя сильнее
   важного из позднего, и в base это правило перебило бы вид без скрипта в
   конструкторе (`html:not(.has-js) .rule-back[hidden] { display: block
   !important }`, constructor.css), который выигрывает у него специфичностью.

   Там же знак на странице входа: картинка знака — значок `.ic`, и общее правило
   значков (shell.css, слой ui) из слоя ui перебило бы размер знака из base при
   любой специфичности — знак входа сжался бы до 24 px. */
@layer ui {
[hidden] {
  display: none !important;
}

.gate .gate-logo .logo {
  width: 72px;
  height: 72px;
}
}
