/* ═══ Оболочка телефона: капсула, поля, клавиатура ═══════════════════════════
 *
 * Отдельный файл и подключается ТОЛЬКО из `web.html`. Это не вкусовщина:
 * `css/pwa.css` и `css/alpha2.css` рядом подключает и `index.html`, то есть
 * окно настольной программы. Всё, что здесь написано, окна не касается вовсе
 * — ни одной строкой, ни при каком размере окна. Откат — снять одну строку
 * из `web.html`.
 *
 * Файл идёт ПОСЛЕ `pwa.css`, поэтому переопределения работают по порядку, а
 * не за счёт `!important` и не за счёт раздутых селекторов.
 *
 * # Что здесь решается
 *
 * 1. Геометрия низа лежит в одном месте. До этого файла высота капсулы была
 *    записана числами в трёх независимых местах: `84px` (отступ ленты в
 *    alpha2.css), `76px` (полоса сообщений в pwa.css) и `96px` (кнопка
 *    «снять» в роликах). Три числа про один и тот же предмет расходятся
 *    молча: подвинули капсулу — два из трёх остались на месте.
 * 2. Клавиатура iPhone. `interactive-widget=resizes-content` из `web.html`
 *    там не работает (см. `js/viewport.js`), и всё прибитое к низу уходит под
 *    клавиатуру. Здесь это разбирается по `--kb`.
 * 3. Область вокруг капсулы остаётся прозрачной. Капсула плавает над лентой,
 *    сплошной полки внизу нет — но там, где текст проходит под ней, он должен
 *    растворяться, а не упираться в край.
 */

/* ── Геометрия низа: одно число на всю оболочку ───────────────────────────── */

:root {
  /* Зона нажатия. 48 точек — не пожелание, а нижняя граница: палец меньше не
   * попадает, и это одинаково верно для всех четырёх пунктов. */
  --nav-btn: 48px;
  --nav-pad: 6px;
  /* Высота капсулы = кнопка + поля сверху и снизу.
   *
   * Она не растёт вместе с крупным текстом, и это не упущение: пункт капсулы
   * — строка, у неё `line-height: 1`, и при двукратном шрифте подпись в 23
   * точки всё ещё ниже кнопки в 48. Растёт капсула вширь, а не ввысь; ширину
   * разбирает `@media (max-width: 360px)` в alpha2.css. */
  --nav-h: calc(var(--nav-btn) + var(--nav-pad) * 2);
  /* Просвет между капсулой и низом экрана. Он же — та самая прозрачная
   * область: сквозь неё видно ленту, и это единственное, что там есть. */
  --nav-gap: 12px;

  /* Полоса жестов iPhone и вырез в альбомной ориентации. */
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);

  /* Клавиатура. Ноль по умолчанию и ноль навсегда, если `viewport.js` не
   * включён: без него оболочка обязана выглядеть как до него, а не поехать. */
  --kb: 0px;

  /* Сколько низа занято совсем: капсула, просвет под ней, безопасное поле.
   * Всё, что стоит внизу, отмеряет себя отсюда и больше ниоткуда. */
  --nav-space: calc(var(--nav-h) + var(--nav-gap) + var(--safe-b));
}

/* Клавиатура вылезла — капсулы на экране нет, и место под неё не держим:
 * пустая полоса в 70 точек над клавиатурой съедает ровно ту строку, ради
 * которой человек и открыл поле ввода. */
:root[data-kb="1"] {
  --nav-space: 0px;
}

/* ── Боковые поля: своё поле ленты ИЛИ вырез ─────────────────────────────────
 *
 * Широкий случай стоит ЗДЕСЬ, до узкого, а не после: у обоих правил
 * специфичность одна и та же (0,1,0), и решает порядок в файле. Поставь их
 * наоборот — и 20 точек планшета перебили бы 12 точек телефона на самом
 * телефоне. */
.social-page {
  padding-left: max(20px, var(--safe-l));
  padding-right: max(20px, var(--safe-r));
}

/* ── Капсула ──────────────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  /* Те же числа, что и раньше, но теперь из токенов: подвинуть капсулу можно
   * в одном месте, и лента с полосой сообщений подвинутся сами. */
  .a2-nav {
    bottom: calc(var(--nav-gap) + var(--safe-b));
    padding: var(--nav-pad);
    /* В альбомной ориентации вырез забирает край экрана, и капсула шириной
     * `100vw - 24px` заезжала под него половиной кнопки. */
    width: min(calc(100vw - 24px - var(--safe-l) - var(--safe-r)), 420px);
    /* Капсула — предмет, лежащий поверх ленты, а не полка, приклеенная к низу.
     * Разница видна ровно в тени: без неё она читается как вырезанная дыра. */
    box-shadow: var(--a2-nav-shadow), 0 8px 28px rgb(0 0 0 / .18);
  }

  /* ── Активный пункт ────────────────────────────────────────────────────────
   * Заливка + подпись + `aria-current` в разметке. Три признака вместо
   * одного: цвет не виден при цветовой слепоте, подпись не видна диктору,
   * `aria-current` не виден глазами. Порознь каждый из них кого-то теряет. */
  .a2-nav button.active {
    /* Шире, чем у неактивных: у активного есть подпись, и ей нужны поля. */
    padding: 0 12px;
    /* Тонкая обводка заливки. На светлой теме мягкая капсула активного пункта
     * почти совпадает по яркости с фоном самой навигации, и заливка пропадала
     * — оставалась одна подпись, а «выбранность» приходилось угадывать. */
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--a2-capsule-ink) 22%, transparent);
  }

  /* Нажатие видно сразу, не дожидаясь перерисовки: на телефоне между
   * касанием и сменой экрана проходит целый запрос к серверу, и без отклика
   * человек нажимает второй раз. */
  .a2-nav button:active { transform: scale(.94); }
  @media (prefers-reduced-motion: reduce) {
    .a2-nav button:active { transform: none; }
  }

  /* Лицо в пункте «Профиль» на активном пункте обводится акцентом — иначе
   * круглый снимок остаётся единственным пунктом без признака выбранности. */
  .a2-nav button.active .a2-ava {
    box-shadow: 0 0 0 2px var(--a2-capsule-ink);
  }

  /* ── Прозрачная область вокруг капсулы ──────────────────────────────────
   * Сплошной полки внизу нет и не будет: лента видна до самого края экрана.
   * Но текст, проходящий под капсулой, обязан растворяться, а не упираться в
   * её край — иначе последняя строка выглядит обрезанной, а не уходящей.
   *
   * Это заливка, которая ничего не ловит: `pointer-events: none`, и нажатие
   * проходит сквозь неё в ленту.
   *
   * ⭐ 02.09.2026: растворение стало вдвое короче и нигде не доходит до
   * сплошного цвета. Было `var(--bg) 0%` во всю ширину экрана на высоту
   * капсулы плюс двадцать точек — то есть непрозрачная полоса поперёк низа,
   * которая читалась как большая подложка под маленькой капсулой. Плавающий
   * предмет, приклеенный к плите, плавающим уже не выглядит.
   *
   * Теперь низ гасится до 72 %: строка, уходящая под капсулу, всё ещё
   * растворяется, но сквозь неё видно, что лента продолжается. Сама капсула
   * при этом получила настоящую тень (`shell.css`) — отделяет её от ленты
   * именно она, а не заливка вокруг. */
  .social::after {
    content: '';
    position: fixed;
    left: 0; right: 0; bottom: 0;
    height: calc(var(--nav-space) + 4px);
    z-index: 39;                 /* под капсулой (40), над лентой */
    pointer-events: none;
    background: linear-gradient(
      to top,
      color-mix(in srgb, var(--bg) 72%, transparent) 0%,
      color-mix(in srgb, var(--bg) 34%, transparent) 52%,
      color-mix(in srgb, var(--bg) 0%, transparent) 100%);
  }

  /* Клавиатура убрала капсулу — растворять больше нечего. */
  :root[data-kb="1"] .social::after { display: none; }

  /* Ролики идут по чёрному во весь экран. Растворять их в цвет ленты нельзя:
   * на светлой теме это белая полоса поперёк видео. */
  .social:has(.clips-wrap)::after {
    background: linear-gradient(to top, rgb(0 0 0 / .55) 0%, rgb(0 0 0 / 0) 100%);
  }

  /* ── Место под капсулой в ленте ───────────────────────────────────────── */

  /* Лента заканчивается выше капсулы, а не под ней: последняя запись должна
   * дочитываться целиком. Плюс 24 точки — чтобы её край не лип к капсуле. */
  .social-page { padding-bottom: calc(var(--nav-space) + 24px); }

  /* Боковые поля: своё поле ленты ИЛИ вырез, смотря что больше.
   *
   * Здесь чинится ошибка, которую видно только на поставленном приложении.
   * `pwa.css` задаёт в режиме ярлыка `padding-left: env(safe-area-inset-left)`
   * — голым значением, без своего поля. В книжной ориентации вырез слева
   * равен нулю, и это правило перебивало `padding: 12px` из `app.css`
   * буквальным нулём: записи упирались в самый край экрана. В браузерной
   * вкладке того же телефона поля оставались на месте, и разница между
   * вкладкой и ярлыком выглядела случайной поломкой.
   *
   * `max()` снимает вопрос: в книжной ориентации остаются свои 12 точек, в
   * альбомной — вырез, который всегда больше. */
  .social-page {
    padding-left: max(12px, var(--safe-l));
    padding-right: max(12px, var(--safe-r));
  }
}

/* ── Шапка: одна на все экраны ───────────────────────────────────────────────
 *
 * Шапка приклеена к верху (`position: sticky` в app.css) и полупрозрачна с
 * размытием. На iPhone с ярлыка страница идёт ПОД строку состояния — так
 * велит `black-translucent` в `web.html`, — и высоту строки надо вернуть
 * руками, иначе заголовок ленты лезет под часы.
 *
 * `pwa.css` уже делает это в `@media (display-mode: standalone)`. Здесь было
 * добавлено второе условие — `data-standalone` от `viewport.js`: iOS до 16.4
 * отвечал на `display-mode: standalone` неверно, а ярлыки, поставленные на тех
 * версиях, живут на телефонах до сих пор.
 *
 * ⭐ 02.09.2026: условий не осталось вовсе — правило стало безусловным.
 *
 * Оба признака отвечают на вопрос «ярлык это или вкладка», а шапке нужен ответ
 * на другой: «есть ли сверху занятая полоса». Отвечает на него сам браузер,
 * числом `env(safe-area-inset-top)`, и ответ у него честнее любого признака:
 *
 *   • в книжной вкладке Safari сверху стоит своя панель, страница начинается
 *     под ней, и вырез равен **нулю** — правило ничего не прибавляет, поля
 *     не удваиваются, вкладка выглядит ровно как выглядела;
 *   • у ярлыка вырез равен высоте строки состояния — и шапка её учитывает;
 *   • остаются случаи, где ни один признак не срабатывает, а вырез есть:
 *     Safari во весь экран, iPadOS со своими режимами окон, ярлык на старой
 *     iOS, до которого `navigator.standalone` не дожил. Раньше в каждом из
 *     них заголовок ленты стоял под часами.
 *
 * Условие, которое обязано совпасть с числом, но живёт отдельно от него, —
 * это лишний повод разойтись. Спрашиваем число.
 *
 * Признак `data-standalone` остаётся: его читают другие правила и сценарии,
 * и снимать его этот срез не собирался.
 *
 * ⚠️ `:root` перед именем — не украшение специфичности, а необходимость.
 * `shell.css` ниже по списку задаёт шапке телефона и стола поля **сокращённой
 * записью** (`padding: 0 12px`, `padding: 0 24px`), а она обнуляет и
 * `padding-top`. Прежнее правило переживало это за счёт `[data-standalone]`;
 * снявшись с признака, оно потеряло бы вес и вместе с ним — верхнее поле.
 * `:root` возвращает ровно тот же вес, ничего не утверждая о ярлыке. */
:root .social-head {
  height: calc(var(--head) + var(--safe-t));
  padding-top: var(--safe-t);
}

/* Просили меньше прозрачности — отдаём честную заливку.
 *
 * Спрашиваем именно `prefers-reduced-transparency`, а не
 * `prefers-reduced-motion`: это разные просьбы разных людей. Полупрозрачная
 * шапка с размытием мешает тем, кому трудно отделить текст от того, что под
 * ним просвечивает, — и никак не связана с движением на экране. */
@media (prefers-reduced-transparency: reduce) {
  .social-head { backdrop-filter: none; background: var(--bg); }
  /* Растворение над капсулой снимаем совсем, а не делаем непрозрачным:
   * градиент — это и есть тот самый эффект прозрачности, а сплошная плашка на
   * его месте закрыла бы собой ленту, которая под капсулой продолжает
   * прокручиваться. Убрать — честнее, чем закрасить. */
  .social::after { display: none; }
}

/* ── Клавиатура ──────────────────────────────────────────────────────────────
 *
 * Всё ниже — про один случай: человек печатает. Высоту клавиатуры меряет
 * `js/viewport.js` и кладёт в `--kb`; здесь только последствия. */

/* Капсулы во время печати нет. Она не нужна: переключать раздел посреди
 * набора текста никто не собирается, а места она забирает ровно столько,
 * сколько занимает строка, которую человек пишет.
 *
 * `visibility`, а не `display: none`: скрытый через `display` элемент теряет
 * место в порядке обхода, и диктор перестаёт находить навигацию совсем.
 * `visibility: hidden` убирает её и из обхода тоже, но обратимо и без
 * перекладки страницы. */
:root[data-kb="1"] .a2-nav {
  visibility: hidden;
  pointer-events: none;
}

/* Полоса сообщений («вышло обновление», «нет сети», подсказка про ярлык).
 * Она стоит НАД капсулой, а при открытой клавиатуре — над клавиатурой:
 * сообщение, спрятанное за клавиатурой, не сообщение. */
.pwa-bar {
  bottom: calc(var(--nav-space) + var(--kb) + 8px);
  /* Боковые поля учитывают вырез: в альбомной ориентации полоса заезжала под
   * него левым краем. */
  left: calc(12px + var(--safe-l));
  right: calc(12px + var(--safe-r));
  transition: bottom var(--mid) ease;
}
@media (prefers-reduced-motion: reduce) {
  .pwa-bar { transition: none; }
}

/* Всплывающие сообщения. В app.css они стоят на 22 точках от низа — то есть
 * ровно под капсулой, которая их и закрывала. */
@media (max-width: 900px) {
  .toasts {
    bottom: calc(var(--nav-space) + var(--kb) + 16px);
  }
}

/* Лист студии создания. Прибит к низу экрана, и клавиатура накрывала его
 * целиком вместе с полем ввода: человек печатал вслепую. */
.a2-studio {
  bottom: var(--kb);
  /* `--vh` — реальная высота видимой части экрана от `viewport.js`. Считать
   * от `100vh` на iPhone нельзя: там `vh` меряется по экрану без адресной
   * строки, и лист вырастает выше окна. */
  max-height: min(90vh, calc(var(--vh, 100vh) - 24px));
  transition: bottom var(--mid) ease;
}
/* Безопасное поле снизу нужно, пока внизу полоса жестов. Когда там
 * клавиатура — полосы нет, и поле превращается в пустой отступ. */
:root[data-kb="1"] .a2-studio { padding-bottom: 0; }
@media (prefers-reduced-motion: reduce) {
  .a2-studio { transition: none; }
}

/* Окна публикации, настроек, подтверждений. Они выровнены по центру экрана, и
 * при открытой клавиатуре нижняя половина окна — вместе с кнопкой «Опубликовать»
 * — оказывалась под ней. Отдаём окну только видимую часть экрана. */
@media (max-width: 900px) {
  .modal-veil {
    bottom: var(--kb);
    /* Поля меньше: на 320 точках стандартные 20 с каждой стороны — это шестая
     * часть ширины экрана.
     *
     * Бока считаются от выреза: в альбомной ориентации окно левым краем
     * заезжало под «чёлку», и первым под неё уходил заголовок. `max()`, а не
     * голое `env()`, — в книжной ориентации вырез равен нулю, и голое значение
     * обнулило бы поля совсем. */
    padding: 12px max(12px, var(--safe-r)) 12px max(12px, var(--safe-l));
  }
  .modal {
    max-height: min(80vh, calc(var(--vh, 100vh) - var(--kb) - 24px));
  }

  /* С открытой клавиатурой окно садится к низу оставшейся полоски.
   * Центрировать его там нельзя: у окна сверху заголовок, и по центру он
   * уезжает под шапку, а кнопка внизу — под клавиатуру.
   *
   * Без клавиатуры окно остаётся там, где было, — по центру. Двигать его
   * просто потому, что экран узкий, незачем: это ничего не чинит. */
  :root[data-kb="1"] .modal-veil { align-items: end; }
}

/* ── Ролики: капсула не должна ничего закрывать ──────────────────────────────
 *
 * Ролики идут во весь экран своим слоем и `.social-page` не пользуются, то
 * есть отступ снизу до них не доходил. Подписи, кнопки и полоса времени стояли
 * на 28 точках от низа — под капсулой, которая занимает первые 70.
 * Кнопка «снять» отмеряла себя от собственного числа 96 и разъезжалась с
 * капсулой при любом её изменении. */
@media (max-width: 900px) {
  .clip-author,
  .clip-actions {
    bottom: calc(var(--nav-space) + 16px);
  }
  /* Подпись не должна залезать под столбик кнопок справа. */
  .clip-author { left: calc(14px + var(--safe-l)); right: calc(88px + var(--safe-r)); }
  .clip-actions { right: calc(6px + var(--safe-r)); }

  /* Полоса времени — вплотную над капсулой: это единственное, чему там место. */
  .clip-progress { bottom: var(--nav-space); }

  /* «Снять ролик» — над подписью, а не поверх неё. */
  .clip-new {
    bottom: calc(var(--nav-space) + 84px);
    right: calc(14px + var(--safe-r));
  }
}
