/* Раскладка и адаптив.
 *
 * Ровно одна точка перелома — 900px:
 *
 *   уже  → телефон:    разделы в нижнем баре, слои 4 и 5 сменяют друг друга
 *   шире → компьютер:  разделы в боковом меню слева, слои 4 и 5 видны разом
 *
 * Разметка при этом одна и та же. Меняется только то, где стоит навигация
 * и сколько колонок в рабочей области — никаких отдельных мобильной и
 * десктопной версий, которые пришлось бы чинить дважды.
 */

.app {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;

  /* Атмосфера на слоях 2 и 3, где направление ещё не выбрано и --surface
     пустой. Внутри направления рабочая область накрывает это своим
     градиентом — он непрозрачный, так что слои не просвечивают друг
     через друга.
     Пятна берутся из переменных: в светлой прихожей они погашены, и
     жёстко вписанный сюда фиолет проступал бы сквозь белое поле. */
  background:
    radial-gradient(135% 80% at 58% -18%, var(--air-1) 0%, transparent 68%),
    radial-gradient(90% 55% at 2% 34%, var(--air-2) 0%, transparent 62%);
}

/* ---------- Слой 1: заставка ---------- */

.splash {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  /* Свет из центра — там, где знак. Переменной, а не значением: на
     светлой заставке это белое поле с еле заметным тёплым ядром. */
  background: var(--splash-bg);
  transition: opacity .6s var(--ease), visibility .6s;
}

.splash.is-hidden { opacity: 0; visibility: hidden; }

.splash__mark {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap);
}

/* Кольцо набрано двумя цветами семьи: баклажан и розовый. Раньше тут
   спорили фиолетовый и синий — два цвета из разных направлений. */
.splash__ring {
  width: 92px;
  height: 92px;
  border-radius: 50%;
  border: 2px solid transparent;
  border-top-color: var(--ring-1);
  border-right-color: var(--ring-2);
  animation: spin 1.15s var(--ease) infinite;
}

/* Надпись на заставке — рисунок, а не текст, поэтому задаётся ширина,
   а высота считается сама по пропорции. */
.splash__word {
  display: block;
  width: 212px;
  height: auto;
  /* Буквы берут цвет чернил: на тёмной заставке кремовые, на светлой —
     баклажановые. Две средние остаются цветными — они и есть знак. */
  color: var(--text);
  opacity: 0;
  animation: rise .9s var(--ease) .25s forwards;
}

@media (max-width: 380px) {
  .splash__word { width: 176px; }
}

.splash__sub {
  font-size: 13px;
  color: var(--text-faint);
  opacity: 0;
  animation: rise .9s var(--ease) .5s forwards;
}

.splash__ver {
  margin-top: 10px;
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-faint);
  opacity: 0;
  animation: rise .9s var(--ease) .62s forwards;
}

/* Номер сборки на главном экране: тем, кто в бете, надо уметь назвать
   версию, когда пишут об ошибке. Держим тихо, под плитками. */
/* Номер версии — сразу под ссылками подвала.
 *
 * Раньше между ними стояло 24 пикселя, а цвет был самым бледным из
 * возможных: на тёмном фоне подпись терялась совсем, и человек не видел
 * ни номера, ни того, что это бета. */
.app-ver {
  margin-top: 6px;
  text-align: center;
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-dim);
}

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- Экраны ---------- */

.screen { display: none; flex: 1; min-height: 0; }

/* Экран не подменяется, а входит: проявляется и чуть поднимается.
 *
 * Двадцать пикселей и треть секунды — этого хватает, чтобы глаз успел
 * заметить смену, и мало, чтобы начать ждать. Раньше экраны сменялись
 * мгновенно, и переход между разделами читался как перерисовка
 * страницы, а не как движение внутри приложения. */
.screen.is-active { display: flex; flex-direction: column; }

/* Анимируется содержимое экрана, а не сам экран.
 *
 * Внутри экрана лежит нижний бар с position: fixed, а трансформ на
 * предке отбирает у fixed точку отсчёта: бар начинает считать «низ» от
 * низа экрана, а не окна, и уезжает под содержимое — вниз страницы, где
 * его надо искать прокруткой. Поэтому трансформ висит на детях, а бар
 * остаётся в окне. */
.screen.is-active > .screen__inner,
.screen.is-active > .workspace {
  /* backwards, а не both: после входа анимация отпускает transform —
   * иначе пружина у края (js/components/spring.js) не могла бы двигать
   * содержимое: значение анимации сильнее любого стиля. */
  animation: screen-in .34s var(--ease-soft) backwards;
}

/* ---------- Раздел выезжает снизу (с 1.202) ----------
 *
 * Открыли раздел с главного — рабочая область поднимается из-за нижнего
 * края с мягкой пружиной, а главный экран на эти полсекунды остаётся
 * под ней (is-behind) и отступает вглубь. Нижний бар и кнопки висят
 * в экране отдельно, они просто проявляются. */
#screen-domains.is-behind {
  display: flex;
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
#screen-domains.is-behind > .screen__inner {
  animation: home-behind .56s cubic-bezier(.2, .8, .25, 1) both;
  margin-top: var(--behind-scroll, 0px);
}
#screen-workspace.is-rising { position: relative; z-index: 1; }
.screen.is-active.is-rising > .workspace {
  animation: app-rise .56s cubic-bezier(.18, .9, .22, 1.02) backwards;
  box-shadow: 0 -18px 50px rgba(0, 0, 0, .45);
  border-radius: 28px 28px 0 0;
  overflow: hidden;
}
.screen.is-rising > .tabbar,
.screen.is-rising > .dock,
.screen.is-rising > .quickbar,
.screen.is-rising > .fab { animation: app-bars-in .4s ease .26s backwards; }

#screen-domains.is-returning > .screen__inner {
  animation: home-back .42s cubic-bezier(.2, .8, .25, 1) backwards;
}

@keyframes app-rise {
  from { transform: translateY(100vh); }
  to   { transform: none; }
}
@keyframes home-behind {
  from { transform: none; opacity: 1; filter: none; }
  to   { transform: scale(.93); opacity: .55; filter: blur(1px); }
}
@keyframes home-back {
  from { transform: scale(.93); opacity: .4; }
  to   { transform: none; opacity: 1; }
}
@keyframes app-bars-in {
  /* translate, а не transform: у «+» transform занят центровкой. */
  from { opacity: 0; translate: 0 14px; }
}

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

/* Кому анимации мешают — тому их нет. Это не украшение поверх
   содержимого, а подсказка о движении; человеку, который её отключил,
   подсказка не нужна. */
@media (prefers-reduced-motion: reduce) {
  .screen.is-active > .screen__inner,
  .screen.is-active > .workspace { animation: none; }
  .tabbar__pill { transition: none; }
  .tabbar__pill.is-moving { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .16); }
}

.screen__inner {
  width: 100%;
  max-width: 1320px;
  margin: 0 auto;
  /* Сверху добавляем безопасную зону: на iPhone там вырез и часы, и без
   * этого отступа заголовок уезжает под них. На остальных устройствах
   * зона нулевая, и ничего не меняется.
   *
   * В Telegram env() молчит — свою зону клиент отдаёт сам, через
   * contentSafeAreaInset (см. watchSafeArea в app.js). Берём большее из
   * двух: в браузере работает env(), внутри Telegram — переменная. */
  padding: calc(var(--gap-lg)
                + max(env(safe-area-inset-top, 0px), var(--tg-safe-top, 0px)))
           var(--gap) var(--gap-lg);
  flex: 1;
}

/* ---------- Слой 3: главный экран (иконки — в конце файла) ---------- */

/* Экран становится точкой отсчёта для слоёв, а содержимое поднимается
   над ними. */
#screen-domains { position: relative; }
#screen-domains > .screen__inner { position: relative; z-index: 1; }

.domains {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

/* Главный экран — колонка на всю высоту: заголовок и колода сверху,
   подвал прижат к низу. Между ними воздух, а не текст, — ссылки на
   условия не должны стоять вплотную к карточкам, будто продолжают их. */
#screen-domains > .screen__inner {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  /* Подвал опущен к самому краю: под ним только полоса жестов и
     немного воздуха, а не пустое поле в два пальца. */
  padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)
                       + var(--tg-safe-bottom, 0px));
}

#screen-domains .app-foot { margin-top: auto; }

/* На компьютере стопка не должна растягиваться во всю ширину окна:
   карта в полтора метра шириной перестаёт быть картой. */
@media (min-width: 900px) {
  #screen-domains > .screen__inner { max-width: 760px; }
}

/* ---------- Слои 4 и 5 ---------- */

/* Рабочая область.
 *
 * Дерево навигации отдаёт --surface одним плоским цветом — так и должно
 * быть: сервер присылает данные, а не оформление, и знать про радиальные
 * градиенты ему незачем. Атмосферу направления рисует уже CSS, кладя
 * свет поверх этого цвета. Меняется раздел — меняется цвет под светом,
 * и весь экран переодевается сам. */
.workspace {
  display: flex;
  flex: 1;
  min-height: 0;
  background:
    radial-gradient(135% 74% at 58% -16%, var(--air-1) 0%, transparent 68%),
    radial-gradient(90% 50% at 2% 36%, var(--air-2) 0%, transparent 62%),
    /* Затемнение поверх подложки. Подложка — из данных навигации, и она
       же красит плитку на главном; внутри же нужно темнее, чем на
       плитке: там поверх лежат карточки и цифры. Слой даёт это, не
       трогая цвет в данных. */
    linear-gradient(var(--surface-shade), var(--surface-shade)),
    var(--surface);
  transition: background .5s var(--ease-soft);
}

/* «Рассвет» — единственный набор с собственным фоном.
 *
 * У всех остальных фон собирается одинаково: два пятна света поверх
 * подложки направления. Этого хватает, пока фон — один цвет с подсветкой.
 * Здесь же нужен переход через весь экран, от персика в левом верхнем
 * углу до лаванды в правом нижнем, а пятна стоят в своих местах и
 * растягивать их под один набор значило бы сдвинуть свет во всех
 * остальных. Поэтому набор кладёт свой градиент поверх — и на прихожей,
 * и внутри направления, чтобы переход не обрывался на границе экранов. */
[data-theme="dawn"] .app,
[data-theme="dawn"] .workspace {
  background: linear-gradient(118deg,
    #FFD7BE 0%, #FBD2D8 34%, #F0D1EE 62%, #D3C3F8 100%);
}

/* «Пион» — свой переход по той же причине: светлому полю одного
   цвета с пятнами не хватает глубины. Румяный розовый сверху, коралл
   внизу слева, ягодный отлив справа. */
[data-theme="peony"] .app,
[data-theme="peony"] .workspace {
  background:
    radial-gradient(80% 40% at 100% 0%, rgba(214, 60, 130, .22) 0%, transparent 70%),
    radial-gradient(90% 50% at 0% 100%, rgba(255, 170, 140, .45) 0%, transparent 70%),
    linear-gradient(170deg, #FFF0F2 0%, #FCDDE6 45%, #F8CEDC 100%);
}

/* Боковое меню: скрыто на телефоне, показано на компьютере */
.sidebar { display: none; }

.workspace__main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  /* + 32px воздуха и ещё 76px под «+» и чат внизу (с 1.166 они есть в
   * каждом разделе): иначе последняя карточка пряталась бы под ними. */
  padding-bottom: calc(var(--tabbar-h)
                       + max(env(safe-area-inset-bottom, 0px), var(--tg-safe-bottom, 0px))
                       + 108px);
}

/* Нижний бар: только телефон.
 *
 * Плавающая стеклянная капсула, а не полоса во всю ширину. Полоса делит
 * экран надвое и отрезает нижний край содержимого; капсула лежит поверх
 * него, и видно, что страница продолжается под ней.
 *
 * Стекло тут не украшение: под баром проезжает содержимое, и размытие
 * оставляет от него цветное пятно вместо читаемого текста. Без размытия
 * пришлось бы делать панель непрозрачной, а это снова полоса.
 */
/* Полноэкранный режим Telegram: над содержимым нет ничего, кроме часов
   и круглых кнопок клиента. Они висят поверх правого верхнего угла, и
   шапка экрана должна оставить им место — иначе название раздела
   оказывается под кнопкой «закрыть». */
:root[data-fullscreen] .page-head { padding-right: 96px; }

.tabbar {
  position: fixed;
  left: 12px;
  right: 12px;
  /* От большей из двух безопасных зон: браузерной (env) и той, что
     сообщает сам Telegram (--tg-safe-bottom, см. app.js). Внутри
     Telegram env() — ноль, и без второй бар ложился на полосу жестов.
     Плюс шестнадцать пикселей воздуха — столько же держит сам Telegram
     между своей панелью и краем. */
  bottom: calc(max(env(safe-area-inset-bottom, 0px), var(--tg-safe-bottom, 0px)) + 16px);
  z-index: 30;
  height: var(--tabbar-h);
  display: flex;
  align-items: stretch;
  gap: 8px;
}

/* Капсула разделов. */
.tabbar__deck {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: stretch;
  gap: 2px;
  padding: 5px;
  border-radius: 100px;

  background: var(--bar);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--glass-shadow), inset 0 1px 0 var(--glass-light);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);

  /* Бар листается вбок: разделов бывает и четыре, и восемь, а прятать
   * лишние под кнопку «Ещё» — значит уводить половину направления в
   * окно поверх экрана. Полосу прокрутки убираем: она съела бы место
   * подписей, а что список продолжается, видно по обрезанной краем
   * вкладке. */
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

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

.tabbar__item {
  /* Ширина по подписи, а не поровну на всех: подложка активной вкладки
   * должна охватывать и значок, и слово целиком. При равных долях
   * длинные подписи вылезали за свою капсулу и висели по бокам от неё.
   * Разделы, которые не поместились, уезжают за край — капсула
   * листается. */
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 0 13px;
  border-radius: 100px;
  color: var(--text-faint);
  font-size: 10.5px;
  font-weight: 550;
  white-space: nowrap;
  transition: color .2s var(--ease), background .2s var(--ease);
}

.tabbar__item svg { width: 21px; height: 21px; }

/* Активная вкладка — капсула внутри капсулы, как у Telegram.
 * Одним цветом текста тут не обойтись: на стекле подсвеченная подпись
 * читается слабее, чем на плотном фоне, и подложка возвращает ей вес. */
.tabbar__item.is-active { color: var(--accent); }

/* Та самая подложка. Одна на всю капсулу: переезжает под новую вкладку,
   а не вспыхивает на ней. Плавность здесь не для красоты — она
   показывает, откуда и куда перешёл человек, и это единственное, что
   отличает переход от подмены экрана. */
.tabbar__pill {
  position: absolute;
  top: 5px;
  bottom: 5px;
  left: 0;
  width: 0;
  border-radius: 100px;
  opacity: 0;
  pointer-events: none;
  /* Точка отсчёта — левый край: переезд считает сдвиг и растяжение
     независимо, левый край задаёт translateX, ширину — scaleX. */
  transform-origin: left center;
  /* Браузер держит подложку на своём слое и не перерисовывает капсулу
     под ней на каждом кадре. */
  will-change: transform;

  /* Линза, а не плашка.
   *
   * Настоящее стекло на экране выдают три вещи: оно светлее того, что
   * под ним (свет проходит и собирается), у него есть ребро (тонкая
   * светлая кромка, где преломление сильнее всего) и блик сверху. Всё
   * это здесь есть, и ничего сверх: заливка почти прозрачная, форму
   * держит кромка. */
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .10) 0%, rgba(255, 255, 255, .03) 100%),
    var(--glass-pill);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, .16),
    inset 0 1.5px 0 rgba(255, 255, 255, .22),
    inset 0 -1px 0 rgba(255, 255, 255, .05);
  backdrop-filter: brightness(1.14) saturate(1.25);
  -webkit-backdrop-filter: brightness(1.14) saturate(1.25);

  /* Переезд ведёт скрипт (см. movePill в nav.js): капля растягивается
     в полёте, а такое CSS-переходом не описать. Здесь только
     проявление. */
  transition: opacity .3s var(--ease);
}

/* В полёте ребро ярче, и по краям проступает радуга: у настоящей линзы
   на кромке цвета расходятся, и Telegram это показывает ровно в
   движении. Оттенки — из семьи акцента, а не произвольные, чтобы в
   монохромном направлении радуга не стала мультфильмом. */
.tabbar__pill.is-moving {
  box-shadow:
    inset 0 0 0 1.5px rgba(255, 255, 255, .34),
    inset 0 2px 0 rgba(255, 255, 255, .28),
    inset 2px 0 0 color-mix(in oklab, var(--accent) 55%, transparent),
    inset -2px 0 0 color-mix(in oklab, var(--accent) 35%, #7cc4ff);

  /* В полёте стекло проще, чем в покое.
   *
   * `backdrop-filter` пересчитывает всё, что под подложкой, на каждом
   * кадре — на телефоне это и есть та самая неплавность. Стоит
   * движению закончиться, фильтр возвращается: смотрят на подложку
   * стоящую, а не летящую. */
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* Значок стоит на своей оси: прыжок при посадке масштабирует его из
   центра, а не из угла. */
.tabbar__item > span:first-child {
  display: grid;
  place-items: center;
  transform-origin: center;
}

/* Появляется, только когда встала на место: иначе первый кадр показывал
   бы её в левом углу капсулы, откуда она потом уезжала бы к вкладке. */
.tabbar__pill.is-ready { opacity: 1; }

/* Курсор на вкладке, где уже стоишь, не обещает перехода. */
.tabbar__item:disabled,
.sidebar__item:disabled { cursor: default; }

/* Выход к выбору направления.
 *
 * Отдельной круглой кнопкой сбоку, а не пунктом в ряду: это шаг наружу,
 * а не раздел. Раньше он стоял последним в общем ряду и ловил промахи
 * пальцем при листании — а промах здесь стоит выхода из раздела.
 */
.tabbar__exit {
  flex: 0 0 auto;
  width: var(--tabbar-h);
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: var(--text-dim);

  background: var(--bar);
  border: 1px solid var(--glass-edge);
  box-shadow: var(--glass-shadow), inset 0 1px 0 var(--glass-light);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  transition: color .2s var(--ease);
}

.tabbar__exit:hover { color: var(--text); }

/* Направление с одним разделом: капсулы нет, остаётся только выход.
   Кнопку прижимаем вправо — туда же, где она стоит всегда, чтобы палец
   не искал её в новом месте при переходе между направлениями. */
.tabbar--single { justify-content: flex-end; }

/* Бар — полоса во всю ширину, а видна в нём с 1.175 одна кнопка
   «домой». Пустая часть полосы ловила нажатия и закрывала собой то, что
   стоит в том же ряду: воду, «+ Еда» и чат в питании (1.178). Нажатия
   проходят сквозь бар, ловят их только его кнопки. */
.tabbar { pointer-events: none; }
.tabbar > * { pointer-events: auto; }
.tabbar__exit svg { width: 22px; height: 22px; }

/* ---------- Компьютер ---------- */

@media (min-width: 900px) {
  .workspace__main {
    /* Нижнего бара нет, но «+» и чат внизу остались (с 1.166). */
    padding-bottom: 100px;
    overflow-y: auto;
  }

  .tabbar { display: none; }

  /* Боковое меню прижато к окну, а не к содержимому.
   *
   * Без этого оно растягивалось по высоте рабочей области: на экране
   * финансов та почти вдвое выше окна, и «Сменить направление», прижатое
   * к низу меню, оказывалось далеко за нижним краем экрана. Человек видел
   * меню без последнего пункта и не догадывался, что тот есть.
   *
   * align-self убирает растягивание, sticky держит меню на месте, пока
   * рабочая область прокручивается. Длинный список разделов прокрутится
   * внутри самого меню. */
  .sidebar {
    display: flex;
    flex-direction: column;
    width: var(--sidebar-w);
    flex-shrink: 0;
    align-self: flex-start;
    position: sticky;
    top: 0;
    height: 100vh;
    height: 100dvh;
    border-right: 1px solid var(--line-soft);
    /* Вуаль, отделяющая меню от рабочей области. Переменной, а не
       чёрным значением: на светлых наборах чёрная плёнка превращала
       тёплый фон в серый. */
    background: var(--sidebar-veil, rgba(0, 0, 0, .24));
    padding: var(--gap) var(--gap-sm);
    gap: var(--gap-xs);
    overflow-y: auto;
  }

  .sidebar__brand {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    padding: var(--gap-sm) var(--gap-sm) var(--gap);
    font-weight: 700;
    letter-spacing: -.01em;
  }

  .sidebar__logo {
    width: 30px;
    height: 30px;
    border-radius: 9px;
    background: var(--accent);
    display: grid;
    place-items: center;
    color: var(--on-accent);
    flex-shrink: 0;
  }

  .sidebar__group { margin-top: var(--gap); }

  .sidebar__item {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 10px 12px;
    border-radius: var(--r-sm);
    color: var(--text-dim);
    font-size: 14px;
    font-weight: 550;
    width: 100%;
    text-align: left;
    transition: background .18s var(--ease), color .18s var(--ease);
  }

  .sidebar__item svg { width: 18px; height: 18px; flex-shrink: 0; }
  .sidebar__item:hover { background: var(--card); color: var(--text); }

  .sidebar__item.is-active {
    background: var(--accent-soft);
    color: var(--text);
  }

  .sidebar__foot {
    margin-top: auto;
    padding-top: var(--gap-sm);
    border-top: 1px solid var(--line-soft);
  }

  /* На широком экране рабочая область — сетка карточек, как на
   * референсных дашбордах. Слои 4 и 5 живут одновременно. */
  .finance-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: var(--gap-lg);
    align-items: start;
  }

  .screen__inner { padding: var(--gap-lg) var(--gap-lg); }
}

@media (min-width: 1240px) {
  .finance-grid { grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); }
}

/* ---------- Общие блоки страницы ---------- */

.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  padding: var(--gap) 0 var(--gap-lg);
}

.page-head__title { display: flex; flex-direction: column; gap: 3px; }

/* Шестерёнка оформления — справа в шапке главного экрана
 * (components/stylegear.js). В разделах её больше нет: настройка одна
 * на всё приложение и живёт на прихожей.
 *
 * Правило ниже осталось от прежней раскладки, где кнопка стояла слева:
 * шапка растаскивает детей по краям, и с третьим ребёнком название
 * оказалось бы посередине. */
.page-head--gear .page-head__title,
/* Шапка с кнопкой «назад»: заголовок прижат к ней, а не разведён с ней
   по краям экрана — иначе имя уезжает вправо и читается как отдельная
   надпись, а не как название того, куда ты зашёл. */
.page-head--back .page-head__title { margin-right: auto; }

.stylegear__hint {
  font-size: 12.5px;
  color: var(--text-dim);
  line-height: 1.45;
  margin-bottom: 6px;
}

/* Язык — тем же окном, ниже цвета (components/stylegear.js, js/i18n.js).
   Три кнопки в ряд: языков всегда три, и выпадающий список ради трёх
   строк — лишний жест и лишний экран. */
.stylegear__title {
  margin: 16px 0 6px;
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.stylegear__langs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  margin-bottom: 8px;
}

.stylegear__lang { padding: 10px 4px; font-size: 13px; }

.stylegear__lang.is-on {
  cursor: default;
  color: var(--text);
  font-weight: 600;
  border-color: var(--text);
}

/* Рабочая область раздела: столбик блоков на телефоне, две колонки на
 * компьютере (правило для широкого экрана — выше, в медиазапросе).
 *
 * Зазор нужен именно здесь: на телефоне колонки складываются в один
 * столбик, и без него нижняя карточка первой колонки сходилась вплотную
 * с верхней карточкой второй — «Что съедено» ложилось на «Воду». */
.finance-grid {
  display: flex;
  flex-direction: column;
  gap: var(--gap-lg);
}

.stack { display: flex; flex-direction: column; gap: var(--gap); }

/* Между соседними карточками воздуха больше, чем между строками внутри
 * них. Шестнадцати пикселей не хватало: карточки одного тона, с тонкой
 * границей, и на телефоне читались как одна длинная — «Что съедено»
 * зрительно ложилось на «Воду». */
.stack > .card + .card { margin-top: 8px; }

/* Карточки прямо в экране (без .stack) шли вплотную — «Мои друзья» и
 * «Ссылка для друга» сливались в одну. Тот же воздух, что в .stack: 24px. */
.screen__inner > .card + .card { margin-top: var(--gap-lg); }

.row { display: flex; align-items: center; gap: var(--gap-sm); }
.row--between { justify-content: space-between; }
.spacer { flex: 1; }

/* ---------- Перелистывание разделов ---------- */

/* Раздел не подменяется, а проезжает.
 *
 * Сторона зависит от того, куда человек пошёл по ленте разделов: дальше
 * по списку — содержимое уезжает влево, назад — вправо. Это то же
 * движение, что делает палец при свайпе, и оно отвечает на вопрос «где
 * я теперь» без единой подписи.
 *
 * Анимация висит на .workspace__main, а не на самом #feature-root:
 * трансформ отбирает точку отсчёта у вложенных элементов с
 * position: fixed, и плавающая панель питания уехала бы вниз страницы.
 */
/* Тот же темп, что у подложки в нижнем баре (340 мс, см. nav.js): два
   движения — приезд раздела и переезд подложки — должны читаться как
   одно. Раньше содержимое успевало встать за четверть секунды, а
   подложка ехала ещё столько же, и переход выглядел рваным.

   Кривая с длинным хвостом: содержимое трогается быстро и подъезжает
   мягко, без рывка в конце. Смещение меньше прежнего — 18 пикселей
   вместо 26: на телефоне длинный заезд читается как подёргивание. */
/* Без `both`.
 *
 * Раньше стояло `both`, и это была мина: заливка назад держит первый
 * кадр — а в нём прозрачность ноль. Пока анимация идёт, всё правильно,
 * но если браузер её не запустил (вкладку свернули, окно ушло в фон,
 * телефон приберёг батарею), экран так и оставался невидимым — раздел
 * открыт, а на месте него пустота. Конечный кадр и так совпадает с
 * обычным состоянием, держать его заливкой незачем. */
.workspace__main.is-sliding-left { animation: slide-left .34s cubic-bezier(.22, .8, .28, 1); }
.workspace__main.is-sliding-right { animation: slide-right .34s cubic-bezier(.22, .8, .28, 1); }

@keyframes slide-left {
  from { opacity: 0; transform: translateX(18px); }
  to   { opacity: 1; transform: none; }
}

@keyframes slide-right {
  from { opacity: 0; transform: translateX(-18px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .workspace__main.is-sliding-left,
  .workspace__main.is-sliding-right { animation: none; }
}


/* ================= Главный экран — иконки разделов (с 1.174) =================
 *
 * Как экран телефона: обои, виджет «Сегодня», сетка иконок по четыре в
 * ряд и док внизу. Цвет каждой иконки — свой (--ic-a → --ic-b, значок
 * --ic-g), его ставит js/layers/domains.js из выбранного набора. */

#screen-domains { min-height: 100dvh; background: #0b0a18; color: #fff; }
#screen-domains[data-wall="night"], .gear-wall[data-wall="night"] {
  background:
    radial-gradient(120% 70% at 20% 0%, #3b2f9e 0%, transparent 60%),
    radial-gradient(90% 60% at 100% 100%, #0f6d75 0%, transparent 60%),
    #0b0a18;
}
#screen-domains[data-wall="dawn"], .gear-wall[data-wall="dawn"] {
  background: linear-gradient(160deg, #FFD7BE 0%, #FBD2D8 40%, #D3C3F8 100%);
}
#screen-domains[data-wall="forest"], .gear-wall[data-wall="forest"] {
  background:
    radial-gradient(120% 70% at 0% 0%, #3d5e48 0%, transparent 60%),
    radial-gradient(90% 60% at 100% 100%, #6b5b3a 0%, transparent 60%),
    #0f1512;
}
#screen-domains[data-wall="black"], .gear-wall[data-wall="black"] { background: #000; }
#screen-domains[data-wall="ocean"], .gear-wall[data-wall="ocean"] {
  background:
    radial-gradient(110% 70% at 80% 0%, #1d5fd1 0%, transparent 60%),
    radial-gradient(90% 60% at 0% 100%, #11a3b0 0%, transparent 60%),
    #051a22;
}
/* Обои растягиваются на высоту окна, а не содержимого: иначе на
   длинном экране свет уезжал бы вниз вместе с прокруткой. */
#screen-domains[data-wall] { background-attachment: fixed; }

/* Место под док: подвал и версия не должны прятаться под ним. */
#screen-domains > .screen__inner {
  padding-bottom: calc(118px + env(safe-area-inset-bottom, 0px) + var(--tg-safe-bottom, 0px));
}
#screen-domains .app-foot__link,
#screen-domains .app-foot__dot,
#screen-domains .app-ver { color: rgba(255, 255, 255, .55); }
#screen-domains.is-light { color: #2a2238; }
#screen-domains.is-light .app-foot__link,
#screen-domains.is-light .app-foot__dot,
#screen-domains.is-light .app-ver { color: rgba(42, 34, 56, .6); }

.home { display: flex; flex-direction: column; gap: 22px; padding-top: 10px; }

/* Виджет «Сегодня» — матовое стекло поверх обоев. */
.home-widget {
  padding: 16px 18px;
  border-radius: 26px;
  background: rgba(20, 18, 30, .42);
  border: 1px solid rgba(255, 255, 255, .08);
  -webkit-backdrop-filter: blur(22px);
  backdrop-filter: blur(22px);
}
.home-widget { position: relative; }
.home-widget__ver {
  position: absolute; top: 18px; right: 18px;
  font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: rgba(255, 255, 255, .45);
}
.is-light .home-widget__ver { color: rgba(42, 34, 56, .45); }
.home-widget__date {
  font-size: 12px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: rgba(255, 255, 255, .65);
}
.home-widget__title { font-size: 20px; font-weight: 800; margin: 2px 0 12px; }
.home-widget__row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.home-widget__cell {
  display: block; text-align: left; padding: 0; border: 0; background: none;
  font: inherit; font-size: 11.5px; color: rgba(255, 255, 255, .7); cursor: pointer;
  min-width: 0;
}
.home-widget__cell b {
  display: block; font-size: 16px; color: #fff; margin-bottom: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.is-light .home-widget { background: rgba(255, 255, 255, .45); border-color: rgba(255, 255, 255, .5); }
.is-light .home-widget__date,
.is-light .home-widget__cell { color: rgba(42, 34, 56, .65); }
.is-light .home-widget__cell b { color: #2a2238; }

/* Сетка: четыре в ряд на телефоне, шесть на широком экране. */
.app-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 20px 6px;
}
@media (min-width: 720px) {
  .app-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

.home-app {
  display: grid; justify-items: center; gap: 6px;
  padding: 0; border: 0; background: none; color: inherit; font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  user-select: none;
  touch-action: manipulation;
}
.home-app__name {
  max-width: 100%;
  font-size: 11.5px; font-weight: 600; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-shadow: 0 1px 4px rgba(0, 0, 0, .5);
}
.is-light .home-app__name { text-shadow: none; }

.app-icon {
  width: clamp(54px, 15.5vw, 64px);
  aspect-ratio: 1;
  border-radius: 24%;
  display: grid; place-items: center;
  background: linear-gradient(145deg, var(--ic-a, #8e8e93), var(--ic-b, #3a3a3c));
  color: var(--ic-g, #fff);
  box-shadow: 0 8px 18px -8px rgba(0, 0, 0, .7), inset 0 1px 0 rgba(255, 255, 255, .25);
  transition: transform .15s var(--ease), background .35s, color .35s;
}
.app-icon svg { width: 54%; height: 54%; stroke-width: 1.9; }
.app-icon--gray { --ic-a: #8e8e93; --ic-b: #3a3a3c; --ic-g: #fff; }

/* Стекло: подложка прозрачная, значок — светлым цветом набора. */
[data-icons="glass"] .app-icon:not(.app-icon--gray) {
  background: rgba(255, 255, 255, .14);
  color: var(--ic-t, var(--ic-a));
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18), 0 8px 18px -10px rgba(0, 0, 0, .6);
}
[data-icons="glass"].is-light .app-icon:not(.app-icon--gray) {
  background: rgba(255, 255, 255, .55);
  color: var(--ic-d, var(--ic-b));
}
/* Тёмные: чёрный квадрат, значок в цвет набора. */
[data-icons="dark"] .app-icon:not(.app-icon--gray) {
  background: #17161c;
  color: var(--ic-t, var(--ic-a));
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .06), 0 8px 18px -10px rgba(0, 0, 0, .7);
}

/* Перестановка: взятая иконка крупнее и идёт за пальцем без задержки,
   остальные чуть подрагивают — как на телефоне. */
.app-grid.is-reordering { touch-action: none; }
.home-app.is-dragging { position: relative; z-index: 5; transition: none; }
.home-app.is-dragging .app-icon { box-shadow: 0 16px 30px -10px rgba(0, 0, 0, .75); }
.app-grid.is-reordering > .home-app:not(.is-dragging) .app-icon { animation: app-wiggle .28s ease-in-out infinite alternate; }
@keyframes app-wiggle { from { transform: rotate(-2deg); } to { transform: rotate(2deg); } }
@media (prefers-reduced-motion: reduce) {
  .app-grid.is-reordering > .home-app .app-icon { animation: none; }
}

/* Док — стекло у нижнего края, четыре иконки без подписей. */
.app-dock {
  position: fixed;
  left: 50%;
  bottom: calc(10px + env(safe-area-inset-bottom, 0px) + var(--tg-safe-bottom, 0px));
  transform: translateX(-50%);
  width: min(calc(100% - 24px), 460px);
  z-index: 20;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  padding: 14px 16px;
  border-radius: 32px;
  background: rgba(255, 255, 255, .14);
  -webkit-backdrop-filter: blur(24px);
  backdrop-filter: blur(24px);
}
.app-dock .home-app__name { display: none; }
.is-light .app-dock { background: rgba(255, 255, 255, .4); }

/* ---------- Настройки: цвет каждого раздела ---------- */

.gear-apps {
  border-radius: 14px;
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--line-soft);
  overflow: hidden;
}
.gear-app + .gear-app { border-top: 1px solid var(--line-soft); }
.gear-app__row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 9px 12px; border: 0; background: none; color: var(--text);
  font: inherit; text-align: left; cursor: pointer;
}
.gear-app.is-open .gear-app__row { background: rgba(255, 255, 255, .05); }
.gear-app__name { flex: 1; font-size: 15px; }
.gear-app__value { color: var(--text-dim); font-size: 13.5px; }
.gear-app__chev { color: var(--text-faint); font-size: 16px; width: 12px; text-align: center; }

.app-icon--mini {
  width: 32px; border-radius: 8px; box-shadow: none; flex: none;
}
.app-icon--mini svg { stroke-width: 2; }

.gear-swatches {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px 6px;
  padding: 12px 12px 14px;
}
.gear-swatch {
  display: grid; justify-items: center; gap: 5px;
  padding: 4px 0; border: 0; border-radius: 12px; background: none;
  color: var(--text-dim); font: inherit; cursor: pointer;
}
.gear-swatch .app-icon--mini { width: 44px; border-radius: 11px; }
.gear-swatch.is-on .app-icon--mini { outline: 2.5px solid var(--text); outline-offset: 2px; }
.gear-swatch.is-on { color: var(--text); }
.gear-swatch__name { font-size: 11px; }
.gear-swatches__all {
  grid-column: 1 / -1; justify-self: start;
  padding: 4px 0; border: 0; background: none;
  color: var(--accent, #b07ac2); font: inherit; font-size: 13px; cursor: pointer;
}

.gear-walls { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 10px; }
.gear-wall {
  aspect-ratio: .56; border-radius: 12px; border: 0; cursor: pointer;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
  background-attachment: scroll !important;
}
.gear-wall.is-on { outline: 2.5px solid var(--text); outline-offset: 2px; }

/* ---------- С 1.178: без бокового меню и на компьютере ----------
 *
 * Разделы переключаются только с главного экрана — на телефоне и на
 * компьютере одинаково. Боковое меню со списком разделов убрано, а
 * вместо его «Сменить направление» на компьютере тоже стоит круглая
 * «домой» справа внизу, как на телефоне. Ширина меню обнулена: по ней
 * считались центр «+», чата и панели питания. */
@media (min-width: 900px) {
  :root { --sidebar-w: 0px; }
  .sidebar { display: none; }
  .tabbar { display: flex; }
}

/* ---------- Код для приложения (с 1.179) ---------- */
.transfer-code {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 10px 12px; border-radius: 14px;
  background: rgba(255, 255, 255, .05); border: 1px solid var(--line-soft);
}
.transfer-code__value {
  flex: 1 0 100%; text-align: center; padding: 4px 0 2px;
  font-size: 22px; font-weight: 700; letter-spacing: .14em; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.transfer-code__btn { flex: 1; padding: 9px 10px; font-size: 13px; }
.transfer-code__reset {
  margin-top: 6px; padding: 4px 0; border: 0; background: none;
  color: var(--text-dim); font: inherit; font-size: 13px; text-decoration: underline; cursor: pointer;
}

/* ---------- Цельный фон (с 1.211, см. syncBackdrop в app.js) ---------- */
#backdrop {
  position: fixed;
  /* Во весь экран и неподвижно: прокрутка и пружина двигают только
   * содержимое, фон под ним один и тот же. */
  inset: 0;
  z-index: -1;
  pointer-events: none;
  transition: background-color .5s var(--ease-soft);
}
body.has-backdrop .app { background: transparent; }
.bg-lifted { background: transparent !important; }

/* После въезда или возврата экран «осел»: никаких повторных проявлений,
 * когда снимаются классы анимации (1.228, см. show в app.js). */
.screen.is-active.is-settled > .screen__inner,
.screen.is-active.is-settled > .workspace { animation: none; }

/* ---------- Стрелка «на главный» (с 1.231) ----------
 *
 * Круглая «домой» снизу справа стала стрелкой в левом верхнем углу —
 * как в чате задач: она всегда перед глазами и не спорит с «+» и
 * строкой ввода внизу. Без шапки: только стрелка, она висит поверх и
 * не уезжает при прокрутке. Содержимое раздела начинается под ней. */
.tabbar {
  top: calc(max(env(safe-area-inset-top, 0px), var(--tg-safe-top, 0px)) + 12px);
  bottom: auto;
  left: var(--gap, 16px);
  right: auto;
  height: 42px;
}
.tabbar--single { justify-content: flex-start; }
.tabbar__exit { width: 42px; height: 42px; color: var(--text); }
.tabbar__exit svg { width: 20px; height: 20px; }
#screen-workspace #feature-root {
  padding-top: calc(var(--gap-lg) + 40px + max(env(safe-area-inset-top, 0px), var(--tg-safe-top, 0px)));
}
/* Задачи: название и «Чат | Список» встают в один ряд со стрелкой. */
#screen-workspace #feature-root:has(.tpage) {
  padding-top: calc(12px + max(env(safe-area-inset-top, 0px), var(--tg-safe-top, 0px)));
}
/* Вложенный экран со своей «Назад» (тренировка, упражнение, лента
 * операций…): две стрелки одна над другой путали — общая прячется, своя
 * ведёт на шаг назад, а оттуда общая — на главный (1.232). */
body:has(#feature-root .page-back) #tabbar { display: none; }
#screen-workspace #feature-root:has(.page-back) {
  padding-top: calc(var(--gap-lg) + max(env(safe-area-inset-top, 0px), var(--tg-safe-top, 0px)));
}
@media (min-width: 900px) {
  #screen-workspace #feature-root { padding-top: calc(var(--gap-lg) + 40px); }
  #screen-workspace #feature-root:has(.page-back) { padding-top: var(--gap-lg); }
  #screen-workspace #feature-root:has(.tpage) { padding-top: 12px; }
  /* На компьютере стрелка в углу окна, а раздел — по центру: место под неё у названия не нужно. */
  .tpage__head { padding-left: 0; }
}

/* «Быстро записать» на главном (1.255): круглая «+» справа в «Сегодня»,
   ряд чисел ужат, чтобы ничего под неё не заходило. */
.home-widget.has-quick .home-widget__row { padding-right: 58px; display: flex; gap: 18px; }
.home-widget.has-quick .home-widget__cell { flex: 0 1 auto; }
.home-widget__plus {
  position: absolute; right: 16px; top: 50%; transform: translateY(-38%);
  width: 48px; height: 48px; border-radius: 50%; border: 0; cursor: pointer;
  display: grid; place-items: center;
  background: var(--accent); color: var(--on-accent);
  box-shadow: 0 10px 22px -10px rgba(0, 0, 0, .7);
}
.home-widget__plus svg { width: 24px; height: 24px; stroke-width: 2.4; }
.home-widget__plus:active { transform: translateY(-38%) scale(.94); }
.quick-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; padding: 4px 2px 8px; }
.quick-tile { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: 13px 12px; border-radius: 18px; min-width: 0;
  border: 1px solid var(--line); background: var(--card); color: var(--text); text-align: left; cursor: pointer; font: inherit; }
.quick-tile b { font-size: 15px; margin-top: 6px; }
.quick-tile__emoji { font-size: 24px; line-height: 1; }
.quick-tile__sub { font-size: 11.5px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.quick-task__input { width: 100%; padding: 14px; border-radius: 14px; border: 1px solid var(--line); background: var(--card);
  color: var(--text); font: 500 16px var(--font); }
