/* Сброс, страница и оболочка приложения.

   Геометрия: высота — всегда полное окно, ширина выводится из высоты
   по пропорциям телефона, но не уже 390px и не шире 520px.

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

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

/* Обязательно: у шапки и меню задан display: flex, а он перебивает
   встроенное [hidden] { display: none }. Без этой строки скрытые
   элементы каркаса остаются на экране. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  background: var(--bg-page);
  color: var(--text);
  font-family: var(--font);
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
}

/* Подсветка вокруг колонки — чтобы поле по бокам на широком
   мониторе выглядело намеренным, а не пустым. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  background:
    radial-gradient(50vw 45vh at 72% -8%, var(--ambient-mid), transparent 70%);
  pointer-events: none;
}

.app {
  /* Поле сверху и снизу. На телефоне его нет, на мониторе задаётся ниже. */
  --gap: 0px;

  /* Колонка держит пропорции телефона и целиком помещается в окно.
     Ширину ограничивают три вещи: само окно, высота окна за вычетом
     поля, и потолок в 520px. Высота потом выводится из ширины —
     поэтому пропорция точная при любом размере окна, а прокрутки
     не возникает: содержимое размечено в долях ширины и уменьшается
     вместе с колонкой.

     Так было не всегда: раньше высота бралась от окна, а ширина
     ограничивалась снизу 390 пикселями. На низком окне колонка
     становилась короче телефона, содержимое переставало помещаться
     и уезжало под нижний край. */
  --frame: min(
    100vw,
    calc((100dvh - var(--gap) * 2) * var(--design-width) / var(--design-height)),
    520px);
  width: var(--frame);
  height: calc(var(--frame) * var(--design-height) / var(--design-width));
  container-type: inline-size;
  position: relative;
  /* Скругляем всегда. На телефоне, где колонка занимает окно целиком,
     углы приходятся на края устройства и скругления не видно —
     а на всём остальном колонка читается как экран телефона. */
  border-radius: var(--r-app);
  /* Полотно темнее шапки и нижней полосы: они всплывают над ним,
     а не растворяются в нём. Разницу держим на токенах — в тёмной
     теме полотно уходит вниз, в светлой поднимается вверх. */
  background: linear-gradient(135deg,
    var(--bg-page) 0%, var(--bg-app) 55%, var(--bg-page) 100%);
  border-inline: 1px solid var(--line-soft);
  box-shadow: 0 0 60px var(--app-shadow);
  overflow: hidden;
}

/* На мониторе колонку отодвигаем от верха и низа окна. Отступ важнее,
   чем кажется: прижатая к краям колонка выглядит куском страницы,
   а отодвинутая — экраном телефона, который видно целиком. */
@media (min-width: 540px) {
  .app { --gap: var(--app-gap); }
}

/* Содержимое поверх декоративного фона. */
.layout {
  position: relative;
  z-index: 10;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.screen {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Вертикаль и щипок оставляем браузеру, горизонталь забираем себе:
     свайп вправо у нас означает «назад», и браузер не должен трактовать
     его по-своему. Без pinch-zoom в списке пропала бы возможность
     приблизить текст. */
  touch-action: pan-y pinch-zoom;
  scrollbar-width: none;
  display: flex;
  flex-direction: column;
  /* По бокам почти без полей: колонка и так узкая, а её ширина —
     это ширина списков, карточек и кнопок. Воздух здесь стоит дороже
     того, что он отделяет; сверху и снизу он остаётся. */
  padding: var(--sp-6) var(--sp-1);
  animation: screen-in var(--base) var(--ease);
}

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

/* Заголовок экрана. Раньше он жил в шапке, теперь там кружок роли
   и номер аккаунта: место одно, и знать, каким аккаунтом смотришь,
   важнее. */
.screen__title {
  margin: 0 0 var(--sp-4);
  padding-inline: var(--sp-2);
  font-size: var(--fs-lg);
  font-weight: 750;
  letter-spacing: -.01em;
}

/* Шапка и меню скрываются атрибутом hidden — тогда отступ и безопасную
   зону берёт на себя сам экран, иначе содержимое прилипнет к краю. */
.layout:not(:has(.appbar:not([hidden]))) .screen {
  padding-top: calc(var(--sp-8) + env(safe-area-inset-top));
}

.layout:not(:has(.tabbar:not([hidden]))) .screen {
  padding-bottom: calc(var(--sp-6) + env(safe-area-inset-bottom));
}

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

/* Уважаем системную настройку «меньше движения»: гасим всё разом,
   чтобы не вспоминать об этом в каждом новом компоненте. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* Пустой экран кабинета. Разделы сняты до появления настоящих данных,
   и место под них держится само: без этого шапка с нижней полосой
   слиплись бы посередине. */
.plain {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

/* Кнопка, которой место внизу экрана: «выйти» не должна стоять
   первой строкой — на неё нажимают редко и намеренно. */
.plain__last { margin-top: auto; }
