@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("/fonts/inter/inter-cyrillic-ext-wght-normal.woff2")
    format("woff2");
  unicode-range:
    U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F,
    U+FE2E-FE2F;
}
@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("/fonts/inter/inter-cyrillic-wght-normal.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("/fonts/inter/inter-latin-ext-wght-normal.woff2") format("woff2");
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
    U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("/fonts/inter/inter-latin-wght-normal.woff2") format("woff2");
  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;
}
@font-face {
  font-family: "Inter Variable";
  font-style: italic;
  font-display: swap;
  font-weight: 100 900;
  src: url("/fonts/inter/inter-cyrillic-ext-wght-italic.woff2")
    format("woff2");
  unicode-range:
    U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F,
    U+FE2E-FE2F;
}
@font-face {
  font-family: "Inter Variable";
  font-style: italic;
  font-display: swap;
  font-weight: 100 900;
  src: url("/fonts/inter/inter-cyrillic-wght-italic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Inter Variable";
  font-style: italic;
  font-display: swap;
  font-weight: 100 900;
  src: url("/fonts/inter/inter-latin-ext-wght-italic.woff2") format("woff2");
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
    U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: "Inter Variable";
  font-style: italic;
  font-display: swap;
  font-weight: 100 900;
  src: url("/fonts/inter/inter-latin-wght-italic.woff2") format("woff2");
  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;
}
:root {
  --ui-bg: #dbe3ff;
  --ui-card: rgba(255, 255, 255, 0.62);
  --ui-surface-highlight: 0 1px 0 rgba(255, 255, 255, 0.28) inset;
  --ui-card-raised: rgba(255, 255, 255, 0.78);
  --ui-card-selected: #fff;
  --ui-count-bg: rgba(255, 255, 255, 0.6);
  --ui-text: #0c1230;
  --ui-text-2: #222c57;
  --ui-hint: rgba(12, 18, 48, 0.58);
  --ui-section-header: rgba(12, 18, 48, 0.52);
  --ui-separator: rgba(12, 18, 48, 0.12);
  --ui-accent: #2449f2;
  --ui-accent-strong: #0434e8;
  --ui-accent-text: #ffffff;
  --ui-accent-soft: rgba(36, 73, 242, 0.14);
  --ui-pro: #ff7a0f;
  /* Цвета маскота Fid для ярких плашок: лайм с тёмным текстом и оранжевый. */
  --ui-lime: #d4e62a;
  --ui-lime-ink: #11140a;
  --ui-flame: #ff7a0f;
  --ui-destructive: #ff3b30;
  --ui-confirm: #34c759;
  /* Розовый, а не системный зелёный (2026-08-01, просьба юзера). Раньше
     розовым был только тумблер на экране генерации, точечным правилом, —
     ограничение стояло из-за тумблеров чужого React-бандла, а бандл с 31 июля
     не грузится вообще. Значит, цвет можно держать в одном месте, здесь.
     Через var(--ui-accent), а не копией кода: тёмная тема задаёт свой акцент,
     и тумблер обязан ехать вместе с ним. */
  --ui-switch-on: var(--ui-accent);
  --ui-switch-thumb: #f4f6ff;
  --ui-fill: rgba(120, 120, 128, 0.1);
  --ui-fill-2: rgba(120, 120, 128, 0.16);
  --ui-fill-3: rgba(120, 120, 128, 0.22);
  --ui-hover: rgba(0, 0, 0, 0.035);
  --ui-press: rgba(0, 0, 0, 0.07);
  /* Поверхности, которые раньше были прописаны цветом (07.09.2026, тёмная
     тема): поле поиска, стекло листов, светлая пружинка, кнопка «инфо» на
     кадре, слой ожидания плитки, точки в нём, плашка таббара без blur. */
  --ui-field-bg: #f4f6ff;
  --ui-sheet-bg: rgba(233, 236, 250, 0.9);
  --ui-pop-light: rgba(244, 246, 254, 0.6);
  --ui-pop-light-source: rgba(244, 246, 254, 0.5);
  --ui-glass-btn: rgba(240, 243, 253, 0.62);
  --ui-wait-bg: rgba(255, 255, 255, 0.5);
  --ui-wait-dot: rgba(12, 18, 48, 0.22);
  /* Точки площадки расширения (08.09.2026: в тёмной были слишком тёмные). */
  --ui-expand-dot: rgba(12, 18, 48, 0.16);
  --ui-tabbar-fallback: rgba(255, 255, 255, 0.6);
  --ui-seg-active: #ffffff;
  --ui-dash: rgba(12, 18, 48, 0.22);
  --ui-dash-strong: rgba(12, 18, 48, 0.25);
  /* Стекло нижних панелей (таббар, панель запуска, магазин) и его блик. */
  --ui-glass-panel: rgba(225, 231, 253, 0.9);
  --ui-shop-track: rgba(194, 204, 240, 0.45);
  --ui-shop-thumb: var(--ui-glass-panel);
  --ui-glass-panel-soft: rgba(225, 231, 253, 0.82);
  --ui-glass-glow: #fdfdff;
  --ui-glass-thumb: rgba(106, 112, 138, 0.17);
  --ui-glass-thumb-edge: rgba(255, 255, 255, 0.35);
  --ui-glass-thumb-edge-2: rgba(255, 255, 255, 0.2);
  --ui-glass-thumb-ring: rgba(255, 255, 255, 0.18);
  /* Захват таббара: панель почти непрозрачная, ползунок чуть светлее. */
  --ui-glass-panel-hold: rgba(247, 248, 254, 0.92);
  --ui-glass-thumb-hold: rgba(249, 250, 255, 0.13);
  /* Верхние плашки на вуали (баланс, профиль): подложка и приглушённый текст. */
  --ui-pill-bg: rgba(12, 18, 48, 0.13);
  --ui-pill-ink: rgba(12, 18, 48, 0.55);
  --ui-pill-ink-soft: rgba(12, 18, 48, 0.5);
  /* Подложка картинок, пока они не загрузились (карточки стилей, превью
     истории, реферальные блоки, редактор), и их волосяная кромка. */
  --ui-media-bg: #ffffff;
  --ui-media-ring: rgba(255, 255, 255, 0.25);
  --ui-media-soft: rgba(255, 255, 255, 0.6);
  --ui-media-shot: linear-gradient(160deg, rgba(255, 255, 255, 0.72), var(--ui-accent-soft));
  /* Кнопки «отмена» под листом, стрелки рейлов, бейдж расширения. */
  --ui-sheet-cancel: rgba(233, 236, 250, 0.9);
  --ui-sheet-cancel-press: rgba(241, 243, 252, 0.95);
  --ui-rail-arrow: rgba(233, 236, 250, 0.92);
  /* Иконка и плейсхолдер поиска, инициалы аватара, шеврон строк профиля. */
  --ui-ink-soft: rgba(12, 18, 48, 0.45);
  --ui-ink-faint: rgba(12, 18, 48, 0.32);
  /* Полупрозрачные белые подложки на светлом фоне (документы, редактор). */
  --ui-white-veil: rgba(255, 255, 255, 0.5);
  --ui-white-veil-strong: rgba(255, 255, 255, 0.9);
  /* Боковое меню широкого экрана (айпад/десктоп): подложка светлее полотна. */
  --ui-sidebar-bg: color-mix(in srgb, #fff 62%, var(--ui-bg));
  --ui-sidebar-border: rgba(12, 18, 48, 0.06);
  /* Волосяная линия под верхней вуалью (граница панели и экрана). */
  --ui-veil-edge: rgba(12, 18, 48, 0.1);
  /* СТЕКЛО ЛИСТОВ (08.09.2026, по образцу экшн-шита iOS 26 из Framework7 v9,
     значения сняты с их computed-стилей). Подложка, стопка внутренних теней,
     которая и рисует «стекло по краям», и разделитель пунктов. */
  /* 0.75 → 0.82 и размытие 18.5 → 15px в светлой («чуть слабее прозрачность и
     размытие», 08.09.2026); тёмная не менялась. */
  --ui-sheet-glass-bg: rgba(255, 255, 255, 0.82);
  --ui-sheet-blur: 15px;
  --ui-sheet-glass-shadow:
    inset -1px -1px 0 -0.5px #fff,
    inset 1px 1px 0 -0.5px #fff,
    inset 3px 3px 10px -3px #ddd,
    inset -3px -3px 10px -3px #ddd,
    inset 0 0 5px 1px #fff,
    inset 0 0 0 0.5px rgba(0, 0, 0, 0.25),
    inset 0 0 24px rgba(0, 0, 0, 0.1),
    0 0 25px rgba(0, 0, 0, 0.2);
  --ui-sheet-divider: rgba(0, 0, 0, 0.2);
  --ui-radius-card: 22px;
  --ui-radius-field: 14px;
  --ui-radius-pill: 999px;
  /* Режимы GPT-image 2.5 в плитке модели (Sunburst / Flare), см. .impito-model-cap. */
  --ui-mode-sun: #e07a1f;
  --ui-mode-flare: #7c5cd6;
  --ui-font-apple:
    system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial,
    sans-serif;
  --ui-font-inter:
    "Inter Variable", "Inter", system-ui, -apple-system, BlinkMacSystemFont,
    "Roboto", "Helvetica Neue", "Segoe UI", Arial, sans-serif;
  --ui-font: var(--ui-font-apple);
  --ui-font-display: var(--ui-font);
  --ui-ease: cubic-bezier(0.25, 0.1, 0.25, 1);
  --ui-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ui-ease-nav: cubic-bezier(0.33, 1, 0.68, 1);
  --ui-dur: 0.18s;
  --ui-dur-screen: 0.42s;
  --ui-safe-top: 0px;
  --ui-safe-bottom: 0px;
  --ui-fullscreen-top: 0px;
  /* Высота верхней вуали (body:before) — ЕДИНСТВЕННАЯ ручка «выше/ниже панель».
     Пропорциональная часть с множителем 0.906 (−20%, +10%, +3%, 2026-07-28) не
     тронута: именно она подобрана под нативные кнопки Telegram (Close/⌄/⋯) и
     заголовок экрана. Множитель стоит СНАРУЖИ min(), чтобы обе ветки (обычная и
     потолок в 3×) менялись одинаково.
     Сверху добавлена АБСОЛЮТНАЯ полоса `--ui-veil-pill-row` (2026-07-30, просьба
     юзера «сделай панель чуть больше»): в ней и только в ней живёт плашка с
     токенами. Добавка абсолютная, а не процент, потому что плашка фиксированной
     высоты — при масштабировании она то не влезала бы, то болталась.
     Вынесено в переменную, потому что от низа вуали позиционируется
     .impito-token-pill. */
  /* Пропорциональная часть вуали вынесена отдельно: её переопределяет режим
     `impito-flat-top` (Telegram Desktop, где нативных инсетов нет вовсе). */
  --ui-veil-base: calc(
    min(
        var(--ui-fullscreen-top) * 1.5 + var(--ui-veil-extra, 5px) +
          var(--ui-veil-platform, 0px),
        var(--ui-fullscreen-top) * 3
      ) * 0.906
  );
  --ui-veil-pill-row: 22px;
  /* Насколько плашка залезает ВЫШЕ кромки пропорциональной части вуали
     (2026-07-30, «подними вплотную под кнопку»). Считано по скриншоту юзера
     (375pt / 3x): низ нативной кнопки ⌄⋯ на ≈97px, плашка стояла на 122 —
     зазор был 25px. Подъём на 14px оставляет ≈8px. Это единственная ручка
     зазора; если на другом устройстве плашка полезет на кнопку — уменьшать. */
  --ui-veil-pill-lift: 15px;
  --ui-veil-height: calc(var(--ui-veil-base) + var(--ui-veil-pill-row));
  --ui-keyboard: 0px;
  --ui-cta-bar-height: 84px;
  --ui-accent-ink: #1d3fe0;
  --ui-accent-ink-strong: #0434e8;
}
html[data-font-platform="apple"] {
  --ui-font: var(--ui-font-apple);
  --ui-font-display: var(--ui-font);
}
html[data-font-platform="inter"] {
  --ui-font: var(--ui-font-inter);
  --ui-font-display: var(--ui-font);
  /* Android veil is 10px taller on both screens; iPhone keeps the base size. */
  --ui-veil-platform: 10px;
}
[data-theme="dark"] {
  /* ТЁМНАЯ ТЕМА, вариант A «графит с розовым» (07.09.2026, выбор владельца по
     макету ~/Desktop/impito_dark_theme_mockup.html): почти чёрный с еле
     заметным сливовым оттенком, карточки — белое стекло 7%, розовый акцент
     прежний. Тему ставит boot_head.js по выбору в профиле или по Telegram. */
  color-scheme: dark;
  --ui-bg: #0a0e20;
  --ui-card: rgba(255, 255, 255, 0.07);
  --ui-surface-highlight: none;
  --ui-card-raised: rgba(255, 255, 255, 0.12);
  --ui-card-selected: var(--ui-accent-soft);
  --ui-count-bg: rgba(255, 255, 255, 0.08);
  --ui-text: #eef1ff;
  --ui-text-2: #dbe0f7;
  --ui-hint: rgba(238, 241, 255, 0.55);
  --ui-section-header: rgba(238, 241, 255, 0.5);
  --ui-separator: rgba(255, 255, 255, 0.1);
  --ui-accent: #4566ff;
  --ui-accent-strong: #6a85ff;
  --ui-accent-soft: rgba(69, 102, 255, 0.22);
  --ui-destructive: #ff453a;
  --ui-fill: rgba(255, 255, 255, 0.08);
  --ui-fill-2: rgba(255, 255, 255, 0.12);
  --ui-fill-3: rgba(255, 255, 255, 0.16);
  --ui-hover: rgba(255, 255, 255, 0.06);
  --ui-press: rgba(255, 255, 255, 0.1);
  --ui-field-bg: rgba(255, 255, 255, 0.08);
  --ui-sheet-bg: rgba(22, 28, 54, 0.92);
  --ui-pop-light: rgba(32, 40, 72, 0.72);
  --ui-pop-light-source: rgba(32, 40, 72, 0.62);
  --ui-glass-btn: rgba(22, 28, 54, 0.62);
  --ui-wait-bg: rgba(255, 255, 255, 0.06);
  --ui-wait-dot: rgba(255, 255, 255, 0.22);
  --ui-expand-dot: rgba(255, 255, 255, 0.32);
  --ui-tabbar-fallback: rgba(22, 28, 54, 0.72);
  --ui-mode-sun: #ffa94d;
  --ui-mode-flare: #b39cff;
  --ui-seg-active: rgba(255, 255, 255, 0.16);
  --ui-dash: rgba(255, 255, 255, 0.22);
  --ui-dash-strong: rgba(255, 255, 255, 0.28);
  --ui-glass-panel: rgba(22, 28, 54, 0.88);
  --ui-shop-track: rgba(255, 255, 255, 0.04);
  --ui-shop-thumb: rgba(255, 255, 255, 0.1);
  --ui-glass-panel-soft: rgba(22, 28, 54, 0.8);
  --ui-glass-glow: #252e55;
  /* Ползунок таббара: 0.12 → 0.06 («слишком светлый», 07.09.2026), кромки
     приглушены. */
  --ui-glass-thumb: rgba(255, 255, 255, 0.06);
  /* Ползунок таббара в покое БЕЗ обводки (08.09.2026, «в афк состоянии
     какая-то обводка»): кромки и кольцо прозрачные, остаётся только заливка. */
  --ui-glass-thumb-edge: transparent;
  --ui-glass-thumb-edge-2: transparent;
  --ui-glass-thumb-ring: transparent;
  --ui-glass-panel-hold: rgba(30, 37, 66, 0.94);
  --ui-glass-thumb-hold: rgba(255, 255, 255, 0.09);
  --ui-pill-bg: rgba(255, 255, 255, 0.14);
  /* Текст плашек полностью белый (просьба юзера 07.09.2026). */
  --ui-pill-ink: #fff;
  --ui-pill-ink-soft: #fff;
  /* Бегунок тумблера без белого «блика»: приглушённый светлый (07.09.2026). */
  --ui-switch-thumb: #c8cfec;
  --ui-media-bg: #141a35;
  --ui-media-ring: rgba(255, 255, 255, 0.05);
  --ui-media-soft: rgba(255, 255, 255, 0.08);
  --ui-media-shot: linear-gradient(160deg, rgba(255, 255, 255, 0.12), var(--ui-accent-soft));
  --ui-sheet-cancel: rgba(32, 40, 72, 0.92);
  --ui-sheet-cancel-press: rgba(42, 51, 88, 0.95);
  --ui-rail-arrow: rgba(32, 40, 72, 0.92);
  --ui-ink-soft: rgba(238, 241, 255, 0.5);
  --ui-ink-faint: rgba(238, 241, 255, 0.35);
  --ui-white-veil: rgba(255, 255, 255, 0.08);
  --ui-white-veil-strong: rgba(255, 255, 255, 0.16);
  --ui-sidebar-bg: color-mix(in srgb, #fff 5%, var(--ui-bg));
  --ui-sidebar-border: rgba(255, 255, 255, 0.08);
  /* В тёмной теме тёмная линия сливалась с фоном (08.09.2026) — белая 12%. */
  --ui-veil-edge: rgba(255, 255, 255, 0.12);
  --ui-sheet-glass-bg: rgba(50, 50, 50, 0.5);
  --ui-sheet-blur: 18.5px;
  --ui-sheet-glass-shadow:
    inset -2px -2px 0.5px -2.5px rgba(255, 255, 255, 0.4),
    inset 3px 3px 0.5px -3.5px rgba(255, 255, 255, 0.4),
    inset 2px 2px 0.5px -2px #262626,
    inset -2px -2px 0.5px -2px #262626,
    inset 0 0 5px 1px #141414,
    inset 0 0 0 1px rgba(255, 255, 255, 0.15),
    inset 0 0 10px rgba(255, 255, 255, 0.075),
    inset 0 0 24px rgba(255, 255, 255, 0.05),
    0 0 25px rgba(0, 0, 0, 0.15);
  --ui-sheet-divider: rgba(255, 255, 255, 0.15);
  --ui-accent-text: #ffffff;
  --ui-accent-ink: #7f97ff;
  --ui-accent-ink-strong: #7f97ff;
}
/* Стекло листов в тёмной теме задаётся токенами --ui-sheet-glass-* выше. */
/* БЕЛЫХ INSET-КРОМОК В ТЁМНОЙ ТЕМЕ НЕТ (07.09.2026, «инсет кромки убирай»).
   На светлом стекле они рисуют блик по краю панели, на тёмном — светлый
   ободок. Оставлены только внешние тени, перекрашенные в чёрный. */
[data-theme="dark"] .impito-style-submit__inner,
[data-theme="dark"] .impito-top-toast__panel,
html[data-theme="dark"][data-font-platform="apple"] .impito-tabbar {
  box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.35);
}
/* ТАББАР В ТЁМНОЙ ТЕМЕ — СТЕКЛО КАК У ТАББАРА TELEGRAM iOS 26 (08.09.2026,
   скриншот юзера: «эффект этого стекла, обводочка беленькая»). Тёмно-серая
   полупрозрачная подложка с сильным размытием (контент за панелью читается
   размытым), белая волосяная обводка по периметру и блик сверху. */
/* ТОЛЬКО ANDROID/ПРОЧИЕ (08.09.2026, «на айфоне и макбуке верни панель с
   0a6e2b4»): на apple таббар в тёмной теме остаётся прежним — подложка
   --ui-glass-panel, лёгкий туман 1.15px и тёмная обводка (правило выше).
   Снаружи — только тень. Обводка и блики лежат на :before ниже: inset-тени
   самого nav закрывались его же :before со стеклом («блики нихуя не видно»). */
:root[data-theme="dark"]:not([data-font-platform="apple"]) .impito-tabbar {
  /* Ровно как на 89373cd (08.09.2026, «верни как было»): обводка и блики на
     самом nav, внешняя тень. */
  box-shadow:
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.24),
    inset 0 1px 0 -0.5px rgba(255, 255, 255, 0.55),
    inset 0 -1px 0 -0.5px rgba(255, 255, 255, 0.32),
    0 10px 28px rgba(0, 0, 0, 0.35);
}
/* ЗАХВАТ В ТЁМНОЙ ТЕМЕ БЕЗ «НЕОНА» (08.09.2026, скриншот юзера: фиолетовые
   цвета при удержании). В светлой захват подсвечивает пункты brightness(1.55),
   кладёт белую тень под текст, насыщает подложку ползунка saturate(200%), а на
   apple ещё рисует хроматические кромки (розовая/синяя) на ползунке — на
   тёмном всё это складывалось в фиолетовое свечение. Здесь всё выключено,
   ползунок получает только белую волосяную обводку. Специфичность через
   :root[...] выше платформенных правил apple. */
:root[data-theme="dark"] .impito-tabbar.is-dragging .impito-tabbar__item {
  filter: none;
}
:root[data-theme="dark"] .impito-tabbar.is-dragging .impito-tabbar__icon,
:root[data-theme="dark"] .impito-tabbar.is-dragging .impito-tabbar__label {
  text-shadow: none;
}
:root[data-theme="dark"]:not(.impito-lg-refract)
  .impito-tabbar.is-dragging
  .impito-tabbar__thumb {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
:root[data-theme="dark"].impito-lg-active .impito-tabbar__thumb:after,
:root[data-theme="dark"] .impito-tabbar.is-dragging .impito-tabbar__thumb:after {
  box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.14);
}
/* iPhone/Mac: радужная кромка ползунка в захвате, как в светлой теме, но
   контрастнее (08.09.2026, «обводку радужную как на светлой, цвет на тёмной
   чуть контрастнее»). Те же четыре цветные inset-тени, что у apple-правила в
   светлой, альфы подняты примерно в полтора раза, плюс белое кольцо. */
:root[data-theme="dark"][data-font-platform="apple"].impito-lg-active
  .impito-tabbar__thumb:after,
:root[data-theme="dark"][data-font-platform="apple"]
  .impito-tabbar.is-dragging
  .impito-tabbar__thumb:after {
  box-shadow:
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.22),
    inset 0 0 10px -6px rgba(0, 0, 0, 0.4),
    inset 2px 0 2.5px -1.5px rgba(0, 51, 255, 0.52),
    inset -2px 0 2.5px -1.5px rgba(0, 168, 255, 0.46),
    inset 0 2px 2.5px -1.5px rgba(64, 102, 255, 0.34),
    inset 0 -2px 2.5px -1.5px rgba(0, 190, 255, 0.3);
}
/* Как на 89373cd: стекло только там, где нет преломления impito-lg-refract
   (на Android с преломлением панель остаётся базовой), и не на apple. */
:root[data-theme="dark"]:not([data-font-platform="apple"]):not(.impito-lg-refract)
  .impito-tabbar:before {
  background: rgba(58, 50, 56, 0.62);
  -webkit-backdrop-filter: blur(22px) saturate(1.5);
  backdrop-filter: blur(22px) saturate(1.5);
}

[data-theme="dark"] .impito-tabbar.is-dragging .impito-tabbar__thumb {
  box-shadow:
    0 17px 36px rgba(0, 0, 0, 0.3),
    0 2px 7px rgba(0, 0, 0, 0.15);
}
[data-theme="dark"] .impito-sheet__cancel,
[data-theme="dark"] .impito-style-search {
  box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.25);
}
[data-theme="dark"] .impito-expand-badge,
[data-theme="dark"] .impito-rail-arrow {
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3);
}
[data-theme="dark"] .impito-viewer-pop--light .impito-viewer-pop__menu {
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.35);
}
/* Чёрный логотип OpenAI на тёмном фоне не виден — инвертируем только его;
   остальные значки моделей цветные. */
[data-theme="dark"] .impito-param__logo img[src*="gpt15"],
[data-theme="dark"] .impito-sheet__option-emoji[src*="gpt15"],
[data-theme="dark"] .impito-param__logo img[src*="grok"],
[data-theme="dark"] .impito-sheet__option-emoji[src*="grok"] {
  filter: invert(1);
}
html {
  -webkit-tap-highlight-color: transparent;
  background: var(--ui-bg);
}
.ui-page {
  width: min(100%, 560px);
  margin: 0 auto;
  padding: calc(14px + var(--ui-safe-top)) 0 calc(32px + var(--ui-safe-bottom));
  font-family: var(--ui-font);
  color: var(--ui-text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
.ui-page * {
  box-sizing: border-box;
}
/* Подложка под весь вьюпорт: если нативный фон вебвью слетел в белый
   (iOS после expand), резиновый оверскролл всё равно остаётся розовым. */
body:after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--ui-bg);
  pointer-events: none;
}
body:before {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
  height: var(--ui-veil-height);
  pointer-events: none;
  /* Плоская матовая шапка вместо градиентного растворения (2026-07-28, как в
     настройках iOS): ровная подложка + блюр + волосяная линия снизу.
     Подложка держит 88% непрозрачности не «на глаз»: iOS первые кадры после
     reload рисует слой ещё без backdrop-filter, и прозрачное стекло дало бы
     белую вспышку — та же причина, что у розового тумана таббара. */
  background: color-mix(in srgb, var(--ui-bg) 80%, transparent);
  -webkit-backdrop-filter: blur(6px) saturate(140%);
  backdrop-filter: blur(6px) saturate(140%);
  box-shadow: 0 0.5px 0 var(--ui-veil-edge);
}
.ui-fade-bottom:before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -34px;
  bottom: 0;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    transparent 0%,
    color-mix(in srgb, var(--ui-bg) 30%, transparent) 30%,
    color-mix(in srgb, var(--ui-bg) 78%, transparent) 56%,
    var(--ui-bg) 80%
  );
}
.ui-page-head {
  padding: 18px 22px 14px;
}
.ui-page-title {
  margin: 0;
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
}
.ui-page-sub {
  margin: 5px 0 0;
  color: var(--ui-hint);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.35;
}
.ui-section {
  margin-bottom: 24px;
}
.ui-section-header {
  display: block;
  margin: 0 0 9px;
  padding: 0 22px;
  color: var(--ui-section-header);
  font-size: 13px;
  font-weight: 510;
  letter-spacing: 0.02em;
  line-height: 1.2;
}
.ui-section-footer {
  display: block;
  margin: 9px 0 0;
  padding: 0 22px;
  color: var(--ui-hint);
  font-size: 13px;
  line-height: 1.35;
}
.ui-section--accent .ui-section-header {
  color: var(--ui-accent-ink);
}
.ui-section--accent .ui-card {
  background: var(--ui-accent-soft);
}
.ui-card {
  margin: 0 12px;
  overflow: visible;
  border-radius: var(--ui-radius-card);
  /* No backdrop-filter here: iOS composites backdrop-filter elements over a
     blank (white) backdrop during page-load/route animations, flashing the
     cards white. Plain translucent paint over the page gradient looks the
     same and composites correctly in every frame. */
  background: var(--ui-card);
  box-shadow: var(--ui-surface-highlight);
}
.ui-row {
  position: relative;
  display: flex;
  width: 100%;
  align-items: center;
  gap: 14px;
  min-height: 54px;
  padding: 13px 18px;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
}
.ui-row + .ui-row:before {
  content: "";
  position: absolute;
  top: 0;
  left: 18px;
  right: 0;
  height: 1px;
  background: var(--ui-separator);
  transform: scaleY(0.5);
  transform-origin: top;
  transition: opacity var(--ui-dur) var(--ui-ease);
}
.ui-row--interactive {
  cursor: pointer;
}
.ui-row--interactive:after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: var(--ui-press);
  opacity: 0;
  transition: opacity var(--ui-dur) var(--ui-ease);
  pointer-events: none;
}
/* The card keeps overflow: visible, so round the press highlight on the
   edge rows — otherwise its square corners poke past the card radius. */
.ui-row--interactive:first-child:after {
  border-top-left-radius: var(--ui-radius-card);
  border-top-right-radius: var(--ui-radius-card);
}
.ui-row--interactive:last-child:after {
  border-bottom-left-radius: var(--ui-radius-card);
  border-bottom-right-radius: var(--ui-radius-card);
}
@media (hover: hover) {
  .ui-row--interactive:hover:after {
    background: var(--ui-hover);
    opacity: 1;
  }
}
.ui-row--interactive:active:after {
  background: var(--ui-press);
  opacity: 1;
}
.ui-row--interactive:active:before,
.ui-row--interactive:active + .ui-row:before {
  opacity: 0;
}
@media (hover: hover) {
  .ui-row--interactive:hover:before,
  .ui-row--interactive:hover + .ui-row:before {
    opacity: 0;
  }
}
.ui-row-before,
.ui-row-body,
.ui-row-after {
  position: relative;
  z-index: 1;
}
.ui-row-press {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 0;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.ui-row--actionable > .ui-row-before,
.ui-row--actionable > .ui-row-body,
.ui-row--actionable > .ui-row-after {
  pointer-events: none;
}
.ui-row-before {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  color: var(--ui-accent-ink);
}
.ui-row-body {
  display: flex;
  min-width: 0;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 2px;
}
.ui-row-overline {
  color: var(--ui-hint);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.2;
}
.ui-row-title {
  color: var(--ui-text);
  font-size: 17px;
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1.3;
}
.ui-row--accent .ui-row-title {
  color: var(--ui-accent-ink);
}
.ui-row-subtitle {
  color: var(--ui-hint);
  font-size: 13.5px;
  font-weight: 400;
  line-height: 1.3;
}
.ui-row-after {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 8px;
  color: var(--ui-hint);
  font-size: 17px;
  white-space: nowrap;
}
.ui-row-value {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--ui-text);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.ui-modelpicker-head {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.ui-row--locked {
  opacity: 0.5;
}
.ui-modelpicker-lock {
  color: var(--ui-pro);
  font-size: 13px;
  font-weight: 600;
}
.ui-modelpicker-check {
  display: inline-flex;
  color: var(--ui-accent-ink);
}
/* Без этой строки `display: inline-flex` перебивает браузерное правило для
   атрибута hidden, и галочка горит сразу у всех вариантов (02.08.2026, экран
   режимов реставрации). Так же обслужены .impito-sheet, .impito-camera и
   .impito-style-more — правило на каждый класс, общего сброса в проекте нет. */
.ui-modelpicker-check[hidden] {
  display: none;
}
.ui-amount {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--ui-text);
  font-size: 23px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.ui-amount svg,
.ui-row-value svg {
  color: var(--ui-accent-ink);
  flex: 0 0 auto;
}
.ui-submit {
  padding: 8px 22px 0;
}
.ui-field {
  display: block;
  width: 100%;
  min-height: 92px;
  padding: 15px 18px;
  border: 0;
  outline: none;
  background: none;
  color: var(--ui-text);
  font-family: var(--ui-font);
  font-size: 17px;
  line-height: 1.45;
  resize: none;
}
.ui-field--short {
  min-height: 66px;
}
.ui-field--input {
  min-height: 0;
}
.ui-field::placeholder {
  color: var(--ui-hint);
  opacity: 1;
}
/* КАРЕТКА — НАШИМ АКЦЕНТОМ, А НЕ СИСТЕМНОЙ (02.09.2026, просьба юзера).
   По умолчанию мигающая палочка берёт цвет текста (в iOS — системный синий),
   и на розовом фоне она читается как чужая деталь. Правило одно на все поля
   разом: промпт, поиск стилей, промокод, любое будущее — иначе про новое поле
   каждый раз придётся вспоминать отдельно.
   Именно caret-color, а не color: цвет самого текста не трогаем. */
input,
textarea,
[contenteditable] {
  caret-color: var(--ui-accent);
}
.ui-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 40px;
  padding: 0 20px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-accent);
  color: var(--ui-accent-text);
  cursor: pointer;
  font-family: var(--ui-font);
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  transition:
    background var(--ui-dur) var(--ui-ease),
    transform var(--ui-dur) var(--ui-ease),
    opacity var(--ui-dur) var(--ui-ease);
}
@media (hover: hover) {
  .ui-button:hover:not(:disabled) {
    background: var(--ui-accent-strong);
  }
}
.ui-button:active:not(:disabled) {
  transform: scale(0.97);
}
.ui-button:disabled {
  cursor: default;
  opacity: 0.5;
}
.ui-button--large {
  width: 100%;
  height: 52px;
  font-size: 17px;
}
.ui-button--tinted {
  background: var(--ui-accent-soft);
  color: var(--ui-accent-ink);
}
@media (hover: hover) {
  .ui-button--tinted:hover:not(:disabled) {
    background: var(--ui-accent-soft);
    filter: brightness(0.96);
  }
}
.ui-cta {
  position: relative;
  padding: 1.6px;
  border-radius: var(--ui-radius-pill);
  background: linear-gradient(
    110deg,
    #7d95ff 0%,
    #aebdff 25%,
    #7d95ff 50%,
    #aebdff 75%,
    #7d95ff 100%
  );
  background-size: 280% 100%;
  animation: ui-shimmer 5s linear infinite;
  transition: padding var(--ui-dur) var(--ui-ease);
}
.ui-cta > .ui-button {
  width: 100%;
}
.ui-cta--off {
  padding: 0;
  background: none;
  animation: none;
}
.ui-cta-spacer {
  height: calc(var(--ui-cta-bar-height, 84px) + var(--ui-keyboard));
}
.ui-cta-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 50;
  padding: 14px 12px calc(14px + var(--ui-safe-bottom));
  pointer-events: none;
  transform: translateY(
    min(0px, var(--ui-safe-bottom, 0px) - var(--ui-keyboard, 0px))
  );
  transition: transform 0.28s var(--ui-ease-nav);
  will-change: transform;
}
.ui-cta-bar-inner {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(100%, 560px);
  margin: 0 auto;
  pointer-events: auto;
}
.ui-cta-bar-inner .ui-notice {
  margin-top: 0;
  margin-bottom: 9px;
}
@keyframes ui-shimmer {
  to {
    background-position: 280% 0;
  }
}
.ui-icon-button {
  display: inline-grid;
  width: 38px;
  height: 38px;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ui-hint);
  cursor: pointer;
  transition:
    background var(--ui-dur) var(--ui-ease),
    color var(--ui-dur) var(--ui-ease),
    transform var(--ui-dur) var(--ui-ease);
}
@media (hover: hover) {
  .ui-icon-button:hover {
    background: var(--ui-hover);
  }
}
.ui-icon-button:active {
  transform: scale(0.9);
}
.ui-draglist {
  position: relative;
  margin: 0 12px 24px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
}
.ui-draglist-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 54px;
  padding: 13px 16px 13px 6px;
  transition: transform var(--ui-dur) var(--ui-ease);
}
.ui-draglist-row + .ui-draglist-row:before {
  content: "";
  position: absolute;
  top: 0;
  left: 46px;
  right: 0;
  height: 1px;
  background: var(--ui-separator);
  transform: scaleY(0.5);
  transform-origin: top;
  transition: opacity var(--ui-dur) var(--ui-ease);
}
.ui-draglist[data-dragging] .ui-draglist-row:before {
  opacity: 0;
}
.ui-draglist-row--lifted {
  z-index: 5;
  background: var(--ui-card-raised);
  border-radius: 14px;
  box-shadow: 0 8px 22px #00000038;
  transition: none;
}
.ui-drag-handle {
  display: inline-grid;
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  margin: -2px 0;
  place-items: center;
  color: var(--ui-hint);
  cursor: grab;
  touch-action: none;
}
.ui-drag-handle:active {
  cursor: grabbing;
}
.ui-chip {
  display: inline-flex;
  max-width: 100%;
  height: 36px;
  align-items: center;
  padding: 0 15px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-fill);
  color: var(--ui-text);
  cursor: pointer;
  font-family: var(--ui-font);
  font-size: 15px;
  font-weight: 500;
  white-space: nowrap;
  transition:
    background var(--ui-dur) var(--ui-ease),
    color var(--ui-dur) var(--ui-ease),
    transform var(--ui-dur) var(--ui-ease);
}
@media (hover: hover) {
  .ui-chip:hover {
    background: var(--ui-fill-2);
  }
}
.ui-chip:active {
  transform: scale(0.95);
}
.ui-chip__label {
  overflow: hidden;
  max-width: 240px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ui-chip--active {
  background: var(--ui-accent);
  color: var(--ui-accent-text);
  font-weight: 600;
}
@media (hover: hover) {
  .ui-chip--active:hover {
    background: var(--ui-accent-strong);
  }
}
.ui-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  padding: 14px 18px 16px;
}
.ui-wheel {
  position: relative;
  overflow: hidden;
  margin: 8px 0 2px;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 26%,
    #000 74%,
    transparent 100%
  );
  mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 26%,
    #000 74%,
    transparent 100%
  );
}
.ui-wheel:active {
  cursor: grabbing;
}
.ui-wheel-track {
  will-change: transform;
}
.ui-wheel-item {
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: 700px;
}
.ui-wheel-item-inner {
  color: var(--ui-text);
  font-size: 26px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  backface-visibility: hidden;
  will-change: transform, opacity;
}
.ui-wheel-band {
  position: absolute;
  left: 16px;
  right: 16px;
  border-radius: 12px;
  background: var(--ui-fill);
  pointer-events: none;
}
.ui-wheel-presets {
  display: flex;
  gap: 8px;
  padding: 4px 16px 16px;
}
.ui-wheel-preset {
  display: inline-flex;
  flex: 1 1 0;
  min-width: 0;
  height: 34px;
  align-items: center;
  justify-content: center;
  padding: 0 6px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-fill);
  color: var(--ui-text);
  cursor: pointer;
  font-family: var(--ui-font);
  font-size: 15px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  transition:
    background var(--ui-dur) var(--ui-ease),
    color var(--ui-dur) var(--ui-ease),
    transform var(--ui-dur) var(--ui-ease);
}
@media (hover: hover) {
  .ui-wheel-preset:hover {
    background: var(--ui-fill-2);
  }
  .ui-wheel-preset--active:hover {
    background: var(--ui-accent-soft);
    filter: brightness(0.96);
  }
}
.ui-wheel-preset:active {
  transform: scale(0.94);
}
.ui-wheel-preset--active {
  background: var(--ui-accent-soft);
  color: var(--ui-accent-ink);
  font-weight: 600;
}
.ui-spinner {
  display: inline-block;
  width: 20px;
  height: 20px;
  color: var(--ui-hint);
  animation: ui-spin 0.85s linear infinite;
}
.ui-spinner-track {
  opacity: 0.22;
}
.ui-button .ui-spinner {
  width: 18px;
  height: 18px;
  color: inherit;
}
@keyframes ui-spin {
  to {
    transform: rotate(360deg);
  }
}
.ui-notice {
  margin: 12px 22px 0;
  color: var(--ui-hint);
  font-family: var(--ui-font);
  font-size: 14px;
  line-height: 1.4;
  text-align: center;
}
.ui-notice--error {
  color: var(--ui-destructive);
}
.ui-overlay {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: #0006;
  animation: ui-fade 0.2s var(--ui-ease);
  font-family: var(--ui-font);
  color: var(--ui-text);
}
.ui-overlay,
.ui-overlay * {
  box-sizing: border-box;
}
.ui-overlay--bottom {
  align-items: flex-end;
  padding: 0;
}
@keyframes ui-fade {
  0% {
    opacity: 0;
  }
}
.ui-modal {
  width: min(100%, 360px);
  padding: 22px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  backdrop-filter: saturate(180%) blur(18px);
  box-shadow: var(--ui-surface-highlight);
  animation: ui-pop 0.24s var(--ui-ease-out);
}
.ui-modal-title {
  margin: 0 0 12px;
  color: var(--ui-text);
  font-size: 19px;
  font-weight: 700;
  text-align: center;
}
.ui-modal-actions {
  display: flex;
  gap: 10px;
  margin-top: 18px;
}
.ui-modal-actions > * {
  flex: 1 1 0;
}
@keyframes ui-pop {
  0% {
    opacity: 0;
    transform: scale(0.94);
  }
}
.ui-sheet {
  display: flex;
  width: 100%;
  max-height: 80vh;
  flex-direction: column;
  padding: 8px 0 calc(12px + var(--ui-safe-bottom));
  border-radius: 20px 20px 0 0;
  background: var(--ui-card);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  backdrop-filter: saturate(180%) blur(18px);
  box-shadow: var(--ui-surface-highlight);
  animation: ui-slide-up 0.28s var(--ui-ease-out);
}
.ui-sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 20px 10px;
}
.ui-sheet-title {
  color: var(--ui-text);
  font-size: 17px;
  font-weight: 700;
}
.ui-sheet-body {
  overflow-y: auto;
  padding: 0 8px 4px;
}
@keyframes ui-slide-up {
  0% {
    transform: translateY(100%);
  }
}
.ui-checkbox {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  cursor: pointer;
}
.ui-checkbox-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.ui-checkbox-box {
  display: inline-grid;
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  place-items: center;
  border-radius: 7px;
  background: var(--ui-fill);
  color: transparent;
  transition:
    background var(--ui-dur) var(--ui-ease),
    color var(--ui-dur) var(--ui-ease);
}
.ui-checkbox-input:checked + .ui-checkbox-box {
  background: var(--ui-accent);
  color: var(--ui-accent-text);
}
.ui-checkbox-input:disabled + .ui-checkbox-box {
  opacity: 0.5;
}
.ui-checkbox-label {
  min-width: 0;
  color: var(--ui-text);
  font-size: 16px;
  line-height: 1.3;
}
.ui-switch {
  position: relative;
  flex: 0 0 auto;
  width: 70px;
  height: 31px;
  padding: 0;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background-color: var(--ui-fill-3);
  cursor: pointer;
  transition: background-color var(--ui-dur) var(--ui-ease);
}
/* Мгновенная установка состояния: ставится на один кадр, когда тумблер
   приводят в соответствие с ответом сервера, а не рукой пользователя.
   Гасим переход и у самого тумблера, и у бегунка — он живёт на :after. */
.ui-switch.is-instant,
.ui-switch.is-instant:after {
  transition: none;
}
.ui-switch:after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 43px;
  height: 27px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-switch-thumb);
  /* ТЕНИ ПОД БЕГУНКОМ НЕТ (2026-08-06, «убери тень за ползунком, везде с этим
     ползунком»). Была `0 1px 3px #0003`. Правило одно на все переключатели —
     и в шапке профиля, и на экране согласия, и в карточках генерации, так что
     точечных исключений заводить не надо. Не путать с бегунком КАЧЕСТВА
     (`.impito-quality__thumb`): у того своя тень, она подбиралась отдельно
     десятком правок и здесь ни при чём. */
  transform: translate3d(0, 0, 0);
  backface-visibility: hidden;
  will-change: transform;
  transition: transform var(--ui-dur) var(--ui-ease);
}
/* Сквиркл бегунка: путь считает squircle.js по размерам ::after. */
.ui-switch:after {
  clip-path: var(--sq-after, none);
}
.ui-switch--on {
  background-color: var(--ui-switch-on);
}
.ui-switch--on:after {
  transform: translate3d(23px, 0, 0);
}
.ui-switch:disabled,
.ui-switch[aria-disabled="true"] {
  cursor: default;
  opacity: 0.5;
}
/* МИНИ-ТУМБЛЕР для чипа под полем промпта (07.09.2026, просьба юзера
   «маленький ползуночек когда пишешь промпт»). Те же пропорции и цвета, что у
   большого, только 42×24: бегунок 24×20 и ход 14px. Обычный .ui-switch рядом с
   однострочным полем 44px выглядел бы как второй такой же ряд настроек. */
.ui-switch--mini {
  width: 42px;
  height: 24px;
}
.ui-switch--mini:after {
  width: 24px;
  height: 20px;
}
.ui-switch--mini.ui-switch--on:after {
  transform: translate3d(14px, 0, 0);
}
.ui-segmented {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-fill);
}
.ui-segment {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 32px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: none;
  color: var(--ui-hint);
  cursor: pointer;
  font-family: var(--ui-font);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  transition:
    background var(--ui-dur) var(--ui-ease),
    color var(--ui-dur) var(--ui-ease);
}
.ui-segment--active {
  background: var(--ui-card);
  color: var(--ui-text);
  box-shadow: 0 1px 3px #0000001f;
}
.ui-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 8px 24px 22px;
  text-align: center;
}
.ui-hero-emoji {
  display: flex;
  width: 144px;
  height: 144px;
  align-items: center;
  justify-content: center;
  font-size: 116px;
  line-height: 1;
  animation: ui-hero-emoji-in 0.5s var(--ui-ease-out) both;
}
.ui-hero-emoji > * {
  animation: ui-hero-float 4s ease-in-out 0.5s infinite;
}
.ui-hero-emoji canvas,
.ui-hero-emoji svg,
.ui-hero-emoji img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.ui-emoji-img {
  display: block;
  object-fit: contain;
  -webkit-user-drag: none;
  -webkit-user-select: none;
  user-select: none;
  pointer-events: none;
}
.ui-hero-title {
  margin: 16px 0 0;
  color: var(--ui-text);
  font-family: var(--ui-font-display);
  font-size: 36px;
  font-weight: var(--ui-weight-bold);
  letter-spacing: var(--ui-tracking-title);
  line-height: var(--ui-leading-tight);
  animation: ui-hero-rise 0.42s var(--ui-ease-out) 0.06s both;
}
.ui-hero-sub {
  margin: 10px 0 0;
  max-width: 32ch;
  color: var(--ui-hint);
  font-size: var(--ui-size-row);
  line-height: var(--ui-leading-normal);
  animation: ui-hero-rise 0.42s var(--ui-ease-out) 0.12s both;
}
@keyframes ui-hero-emoji-in {
  0% {
    opacity: 0;
    transform: scale(0.5) translateY(10px);
  }
}
@keyframes ui-hero-float {
  0%,
  to {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-7px);
  }
}
@keyframes ui-hero-rise {
  0% {
    opacity: 0;
    transform: translateY(10px);
  }
}
.ui-screen {
  animation-duration: var(--ui-dur-screen);
  animation-timing-function: var(--ui-ease-nav);
  animation-fill-mode: both;
}
.ui-screen--fwd {
  animation-name: ui-screen-in-fwd;
}
.ui-screen--back {
  animation-name: ui-screen-in-back;
}
@keyframes ui-screen-in-fwd {
  0% {
    opacity: 0;
    transform: translate(26px);
  }
}
@keyframes ui-screen-in-back {
  0% {
    opacity: 0;
    transform: translate(-26px);
  }
}
.ui-debug-overlay {
  position: fixed;
  right: 12px;
  top: calc(12px + var(--ui-safe-top));
  z-index: 120;
  display: flex;
  box-sizing: border-box;
  width: min(260px, calc(100vw - 24px));
  flex-direction: column;
  gap: 9px;
  padding: 10px;
  border: 1px solid var(--ui-separator);
  border-radius: 16px;
  background: var(--ui-card);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  backdrop-filter: saturate(180%) blur(18px);
  box-shadow: 0 14px 36px color-mix(in srgb, var(--ui-text) 16%, transparent);
  color: var(--ui-text);
  font-family: var(--ui-font);
}
.ui-debug-overlay,
.ui-debug-overlay * {
  box-sizing: border-box;
}
.ui-debug-overlay--compact {
  width: auto;
  min-width: 148px;
  gap: 4px;
  padding: 8px 9px;
}
.ui-debug-overlay__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.ui-debug-overlay__title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.2;
}
.ui-debug-overlay__summary {
  color: var(--ui-hint);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}
.ui-debug-overlay__body {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.ui-debug-overlay__field {
  display: grid;
  gap: 4px;
  color: var(--ui-hint);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
  line-height: 1.2;
  text-transform: uppercase;
}
.ui-debug-overlay__select {
  width: 100%;
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--ui-separator);
  border-radius: 10px;
  outline: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background: var(--ui-fill);
  color: var(--ui-text);
  cursor: pointer;
  font-family: var(--ui-font);
  font-size: 13px;
  font-weight: 600;
}
.ui-debug-overlay__button {
  display: inline-flex;
  min-height: 28px;
  align-items: center;
  justify-content: center;
  padding: 0 10px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-fill);
  color: var(--ui-text);
  cursor: pointer;
  font-family: var(--ui-font);
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  transition:
    background var(--ui-dur) var(--ui-ease),
    color var(--ui-dur) var(--ui-ease),
    opacity var(--ui-dur) var(--ui-ease),
    transform var(--ui-dur) var(--ui-ease);
}
.ui-debug-overlay__button--primary {
  width: 100%;
  background: var(--ui-accent);
  color: var(--ui-accent-text);
}
@media (hover: hover) {
  .ui-debug-overlay__button:hover:not(:disabled) {
    background: var(--ui-fill-2);
  }
  .ui-debug-overlay__button--primary:hover:not(:disabled) {
    background: var(--ui-accent-strong);
  }
}
.ui-debug-overlay__button:active:not(:disabled) {
  transform: scale(0.96);
}
.ui-debug-overlay__button:disabled {
  cursor: default;
  opacity: 0.55;
}
@media (max-width: 420px) {
  .ui-debug-overlay {
    right: 10px;
    top: calc(10px + var(--ui-safe-top));
    width: min(240px, calc(100vw - 20px));
  }
  .ui-debug-overlay--compact {
    width: auto;
    max-width: calc(100vw - 20px);
  }
}
@media (prefers-reduced-motion: reduce) {
  .ui-cta,
  .ui-overlay,
  .ui-modal,
  .ui-sheet {
    animation: none;
  }
  .ui-hero-emoji,
  .ui-hero-emoji > *,
  .ui-hero-title,
  .ui-hero-sub,
  .ui-screen {
    animation: none !important;
  }
  .ui-cta-bar {
    transition: none;
  }
}
html,
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  background: var(--ui-bg);
  font-family: var(--ui-font);
  overflow-x: hidden;
}
#root {
  min-height: 100vh;
  min-height: 100svh;
}
.ui-page {
  padding-bottom: calc(116px + var(--ui-safe-bottom));
}
.ui-cta-bar {
  bottom: calc(80px + var(--ui-safe-bottom));
}
.ui-cta-spacer {
  height: calc(var(--ui-cta-bar-height, 84px) + 88px + var(--ui-keyboard));
}
/* ДОРОЖКА ПЕРЕКЛЮЧАТЕЛЯ — ЭТО ТА ЖЕ ПАНЕЛЬ. Раньше у неё был свой плоский
   фон, и получалось, что стекло на ползунке есть, а показывать ему нечего:
   под ним ровная розовая заливка вместо стеклянной панели, отсюда «серо и
   мёртво» (18.08.2026). Теперь она живёт по правилам таббара — туман, блики,
   волосяная обводка, свечение при захвате, — а своё у неё только размер. */
.impito-tabbar {
  position: fixed;
  left: 50%;
  /* 6 → 4px (08.09.2026, «таббар совсем чуть ниже»). */
  bottom: calc(4px + var(--ui-safe-bottom));
  z-index: 80;
  display: flex;
  align-items: stretch;
  width: min(calc(100% - 48px), 504px);
  height: 67px;
  /* Боковые поля больше вертикальных: ползунок шире слота на 10% (THUMB_SLOT_K
     в index.html), и этот перехлёст должен помещаться у крайних вкладок. */
  padding: 5px 9px;
  border: 0;
  border-radius: 34px;
  overflow: visible;
  background: transparent;
  /* Без внешней тени (2026-07-28, просьба юзера) — остались только внутренние
     блики стекла. Панель генерации/оплаты (.impito-style-submit__inner) с
     2026-07-30 живёт по тем же правилам: своя тень убрана, обводка та же.
     Первая строка — волосяная тёмная обводка
     0.5px (на 2x/3x экранах это ровно 1 физический пиксель, тоньше не бывает);
     сделана box-shadow, а не border, чтобы не влезать в геометрию панели. */
  box-shadow:
    0 0 0 0.5px rgba(12, 18, 48, 0.22),
    inset 0 1.2px 1px -0.5px rgba(255, 255, 255, 0.5),
    inset 0 -1px 1px -0.5px rgba(255, 255, 255, 0.22),
    inset 1px 0 1px -0.5px rgba(255, 255, 255, 0.3),
    inset -1px 0 1px -0.5px rgba(255, 255, 255, 0.3),
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.15);
  font-family: var(--ui-font);
  transform: translateX(-50%);
  transition: transform 0.08s var(--ui-ease);
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}
.impito-tabbar:before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  /* Pink-tinted fog: WebKit composites backdrop-filter a few frames late
     after a reload, so the bare fog must already match the final glass
     color or the bar flashes white on iOS. */
  background: var(--ui-glass-panel);
  -webkit-backdrop-filter: blur(1px) saturate(118%);
  backdrop-filter: blur(1px) saturate(118%);
  pointer-events: none;
}
.impito-tabbar:after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  background: var(--ui-glass-glow);
  opacity: var(--impito-panel-glow, 0);
  pointer-events: none;
}
.impito-tabbar,
.impito-tabbar * {
  box-sizing: border-box;
}
/* ПОЛЗУНКИ МАГАЗИНА ЖИВУТ ПО ЭТИМ ЖЕ ПРАВИЛАМ (18.08.2026). Юзер просил
   «точно такой же, как у нижней панели» — значит и покой, и захват, и отскок
   берём отсюда, а не собираем похожее рядом. Своя у них только геометрия,
   она переопределена в блоке магазина ниже. */
.impito-tabbar__thumb {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 3;
  --impito-thumb-scale: 1;
  width: 76px;
  height: 57px;
  border-radius: 999px;
  overflow: hidden;
  /* Idle: нейтрально-серая пилюля (как в таббаре Telegram) — серость даётся
     подложкой, а не десатурацией фона: thumb лежит НАД иконками (z 3 > 2),
     сильный saturate() убил бы розовый цвет активной иконки. */
  /* Плотность 0.12 → 0.16 → 0.20 → 0.17 (28–29.08.2026): цвет тот же, меняется
     только насыщенность подложки. */
  background: var(--ui-glass-thumb);
  -webkit-backdrop-filter: saturate(92%) brightness(0.99);
  backdrop-filter: saturate(92%) brightness(0.99);
  /* Без внешней тени в покое (2026-07-28) — остались только внутренние блики
     стекла; тень в захвате живёт в правиле .is-dragging и не тронута. */
  box-shadow:
    inset 0 1px 1px -0.5px var(--ui-glass-thumb-edge),
    inset 0 -1px 1px -0.5px var(--ui-glass-thumb-edge-2),
    inset 0 0 0 0.5px var(--ui-glass-thumb-ring);
  opacity: 0;
  transform: translate3d(5px, 5px, 0) scale(var(--impito-thumb-scale, 1));
  /* Переезд ползунка по обычному нажатию медленнее на 20% (2026-07-30):
     0.4s → 0.48s. Кривые не менялись, тайминги захвата (.is-dragging) тоже. */
  transition:
    transform 0.48s cubic-bezier(0.22, 1, 0.36, 1),
    width 0.48s cubic-bezier(0.22, 1, 0.36, 1),
    height 0.48s cubic-bezier(0.3, 1.25, 0.4, 1),
    opacity 0.12s var(--ui-ease),
    background-color 0.16s var(--ui-ease),
    box-shadow 0.16s var(--ui-ease);
  will-change: transform;
  pointer-events: none;
}
.impito-tabbar__thumb:after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  box-shadow:
    inset 0 0 10px -6px rgba(12, 18, 48, 0.33),
    inset 0 1px 2px rgba(12, 18, 48, 0.12);
  opacity: 0;
  transition: opacity 0.25s var(--ui-ease);
  pointer-events: none;
}
html.impito-lg-active .impito-tabbar__thumb:after,
.impito-tabbar.is-dragging .impito-tabbar__thumb:after {
  opacity: 1;
}
.impito-tabbar__thumb.is-bounce {
  animation: impito-thumb-bounce 0.6s cubic-bezier(0.34, 1.56, 0.5, 1);
}
@keyframes impito-thumb-bounce {
  0% {
    scale: 1 0.9;
  }
  35% {
    scale: 1 1.08;
  }
  68% {
    scale: 1 0.97;
  }
  100% {
    scale: 1 1;
  }
}
.impito-tabbar:not(.is-ready) .impito-tabbar__thumb {
  visibility: hidden;
  opacity: 0;
  transition: none;
}
.impito-tabbar.is-ready .impito-tabbar__thumb {
  visibility: visible;
  opacity: 1;
}
.impito-tabbar.is-dragging {
  transform: translateX(-50%) scale(1.045);
}
.impito-tabbar.is-dragging:before {
  background: var(--ui-glass-panel-hold);
  -webkit-backdrop-filter: blur(1px) saturate(130%) brightness(1.03);
  backdrop-filter: blur(1px) saturate(130%) brightness(1.03);
}
.impito-tabbar.is-dragging .impito-tabbar__thumb {
  --impito-thumb-scale: 1;
  background: var(--ui-glass-thumb-hold);
  -webkit-backdrop-filter: saturate(200%);
  backdrop-filter: saturate(200%);
  box-shadow:
    0 17px 36px rgba(12, 18, 48, 0.19),
    0 2px 7px rgba(12, 18, 48, 0.075),
    inset 0 1px 1px -0.5px rgba(255, 255, 255, 0.55),
    inset 0 -1px 1px -0.5px rgba(255, 255, 255, 0.3),
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.3);
  /* Никаких width/height-транзишенов в захвате: карта преломления печётся под
     размер БОКСА, поэтому анимация бокса оставляла стекло на старом размере и
     потом резко перещёлкивала. Бокс встаёт мгновенно, рост даёт transform
     (sizeSx/sizeSy в jellyTick) — линза растёт вместе с ползунком. */
  transition:
    background-color 0.12s var(--ui-ease),
    box-shadow 0.12s var(--ui-ease),
    opacity 0.12s var(--ui-ease);
}
.impito-tabbar__item {
  position: relative;
  z-index: 2;
  display: inline-flex;
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  padding: 5px 1px 4px;
  border: 0;
  border-radius: 29px;
  background: transparent;
  color: var(--ui-text);
  cursor: pointer;
  font: inherit;
  -webkit-tap-highlight-color: transparent;
  transition:
    color 0.2s var(--ui-ease),
    transform 0.2s var(--ui-ease),
    filter 0.18s var(--ui-ease);
}
.impito-tabbar.is-dragging .impito-tabbar__item {
  filter: brightness(calc(1.55 + var(--impito-panel-glow, 0) * 1.4));
}
.impito-tabbar.is-dragging .impito-tabbar__item.is-hot {
  color: var(--ui-accent-strong);
}
.impito-tabbar.is-dragging .impito-tabbar__item.is-active:not(.is-hot) {
  color: var(--ui-text);
}
.impito-tabbar.is-dragging .impito-tabbar__icon,
.impito-tabbar.is-dragging .impito-tabbar__label {
  text-shadow: 0 0 8px rgba(255, 255, 255, 0.55);
}
/* В ПОКОЕ АКТИВНАЯ ВКЛАДКА ЛЕЖИТ ПОВЕРХ ПОЛЗУНКА (29.08.2026). Ползунок стоит
   выше иконок (z 3 > 2) — это нужно для линзы при перетаскивании, но в покое
   его подложка и фильтр гасят цвет активного значка: сколько ни правь цвет,
   он остаётся тусклым, потому что смотрит сквозь стекло. Поднимаем только
   выбранную вкладку и только когда палец не на панели — во время перетаскивания
   всё возвращается, иначе линза перестанет искажать иконку. */
.impito-tabbar:not(.is-dragging) .impito-tabbar__item.is-active {
  z-index: 4;
}
.impito-tabbar__item.is-active {
  background: transparent;
  /* Светлее общего акцента: #4f6bd9 → #617add → #7187e0, два раза по 10%
     белого, затем +10% насыщенности → #6c84e6, и ещё +10% белого → #7b91e9
     (29.08.2026, уже после того как активная вкладка встала поверх ползунка и
     цвет наконец стало видно), и ещё +10% насыщенности → #758dee. Светлота и
     тон прежние, и ещё +5% белого → #7c93ef, затем −20% яркости → #6375bf.
     ИТОГ: #2144d1 — значение назвал сам юзер 29.08.2026, подбор окончен.
     Переменную не трогаем, она общая для всей аппы. */
  color: var(--ui-accent-ink-strong);
  box-shadow: none;
}
.impito-tabbar:not(.is-dragging) .impito-tabbar__item:active {
  transform: scale(0.98);
}
.impito-tabbar__icon {
  display: block;
  /* Иконки и подписи таббара +10% (2026-07-28, просьба юзера). */
  height: 26.4px;
  font-size: 25.3px;
  font-weight: 760;
  letter-spacing: 0;
  line-height: 0.96;
  /* Было translateY(2px) — иконка сидела ниже центра. Подняли на два пикселя
     (просьба юзера 22.08.2026, «прям чуть»). Ручка одна, крутить только её. */
  transform: translateY(0);
}
/* Значок непросмотренных генераций на вкладке истории. Вид системный, как у
   iOS и у самого Telegram: красный кружок с белой цифрой у правого верхнего
   угла иконки. Обводка цветом панели — иначе на стекле красный сливается с
   тем, что просвечивает снизу.
   Кнопка вкладки уже `position: relative`, отдельного контейнера не нужно. */
.impito-tabbar__badge {
  position: absolute;
  /* Придвинут к иконке ещё раз, 23.08 (просьба юзера «процентов на 15»):
     считали от вылета кружка за угол иконки, вышло по 2px по каждой оси —
     1px → 3px вниз и +3px → +1px вбок. Верх кружка теперь почти вровень с
     верхом иконки, как в таббаре iOS. */
  top: 3px;
  /* От центра кнопки вправо: иконка 26.4px, её правый край — центр + 13.2.
     Значок должен цепляться за угол иконки, а не висеть рядом (просьба юзера
     23.08.2026, «как на айосе»), поэтому он частично наезжает на иконку. */
  left: calc(50% + 1px);
  z-index: 3;
  display: block;
  /* 22 → 18px (просьба юзера 23.08.2026, «чуть меньше»). Ровно системный
     размер значка непрочитанных в iOS и в самом Telegram. Кольца по кругу
     нет — кружок сплошной красный, розовое кольцо не возвращать. */
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-destructive);
  color: #ffffff;
  font-family: var(--ui-font);
  /* 13px при кружке 18px (просьба юзера 23.08.2026). Начертание вернули на
     400: вес 500 пробовали в тот же вечер и юзер его отбраковал — на красном
     жирные цифры выглядят тяжело. Крутить размер, вес не трогать. */
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  line-height: 18px;
  text-align: center;
  pointer-events: none;
}
.impito-tabbar__badge[hidden] {
  display: none;
}

.impito-tabbar__label {
  display: block;
  max-width: 100%;
  overflow: hidden;
  /* 11.5 → 11px, «чуть поменьше». На узких экранах (медиазапрос ниже) подпись
     и так была 11px — теперь размер одинаковый везде. */
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1;
  text-overflow: ellipsis;
  transform: translateY(3px);
  white-space: nowrap;
}
@media (max-width: 390px) {
  .impito-tabbar {
    width: min(calc(100% - 36px), 504px);
    height: 64px;
    padding: 4px 8px;
    border-radius: 32px;
  }
  .impito-tabbar__item {
    border-radius: 28px;
  }
  .impito-tabbar__icon {
    height: 25.3px;
    font-size: 24.2px;
  }
  .impito-tabbar__icon svg {
    width: 25.3px;
    height: 25.3px;
  }
  .impito-tabbar__glyph {
    width: 32.9px;
    height: 32.9px;
    margin: -3.8px auto;
  }
  /* Подпись здесь больше не переопределяется: общий размер уже 11px. */
}
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .impito-tabbar {
    background: var(--ui-tabbar-fallback);
  }
  .impito-tabbar:before {
    background: transparent;
  }
  .impito-tabbar__thumb {
    background: rgba(176, 166, 173, 0.42);
  }
}
html.impito-lg-refract .impito-tabbar:before {
  -webkit-backdrop-filter: url(#impito-lg-refraction);
  backdrop-filter: url(#impito-lg-refraction);
}
/* В ПОКОЕ url()-фильтра НЕТ (2026-07-30). Он висел всегда, а нулевой scale
   смещения гасил только результат — сама цепочка (блюр + saturate + три
   feDisplacementMap + композиты) всё равно считалась каждый кадр, пока ползунок
   едет между вкладками 0.48s. Отсюда рывки при обычном нажатии. */
html.impito-lg-refract .impito-tabbar .impito-tabbar__thumb {
  -webkit-backdrop-filter: saturate(92%) brightness(0.99);
  backdrop-filter: saturate(92%) brightness(0.99);
}
/* :not(apple) обязателен: иначе это правило перебило бы сброс фильтра у
   ползунка на apple (там своё стекло на псевдослоях). */
html.impito-lg-refract.impito-lg-active:not([data-font-platform="apple"])
  .impito-tabbar
  .impito-tabbar__thumb,
html.impito-lg-refract .impito-tabbar.is-dragging .impito-tabbar__thumb {
  -webkit-backdrop-filter: url(#impito-lg-thumb);
  backdrop-filter: url(#impito-lg-thumb);
}
@media (prefers-reduced-motion: reduce) {
  .impito-tabbar,
  .impito-tabbar__thumb,
  .impito-tabbar__item {
    transition: none;
  }
}

/* Prompt styles reuse the existing page, card, row, media and button objects. */
body.impito-prompt-styles-active #root {
  display: none;
}
body.impito-prompt-styles-active .ui-cta-bar {
  display: none;
}
#impito-prompt-styles {
  min-height: 100vh;
  min-height: 100svh;
}
.impito-styles-page .ui-page-head {
  padding-top: 28px;
}
.impito-style-chips {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.impito-style-chips::-webkit-scrollbar {
  display: none;
}
.impito-style-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin: 0 12px;
}
.impito-style-more {
  display: block;
  min-width: 164px;
  margin: 16px auto 0;
}
.impito-style-more[hidden] {
  display: none;
}
.impito-style-card {
  position: relative;
  display: block;
  min-width: 0;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: var(--ui-radius-card);
  aspect-ratio: 3 / 4;
  /* БЕЛАЯ, А НЕ СЕРАЯ ЗАЛИВКА. Это то, что видно, ПОКА КАРТИНКА НЕ ЗАГРУЗИЛАСЬ.
     Прежний var(--ui-fill) — серый налёт поверх розовой страницы, и на скролле
     плитки читались как грязные пятна (17.08.2026, юзер поймал скриншотом).
     Белое читается как «тут скоро будет картинка», а не как ошибка. */
  background: var(--ui-media-bg);
  color: inherit;
  cursor: pointer;
  font: inherit;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
  /* Внешней тени НЕТ (2026-07-31, просьба юзера) — как у таббара и нижних
     панелей действия. Осталась только внутренняя волосяная кромка: она рисует
     край карточки поверх картинки, без неё светлые снимки сливаются с фоном. */
  box-shadow: inset 0 0 0 0.5px var(--ui-media-ring);
  animation: impito-card-in 0.5s var(--ui-ease-out) backwards;
  transition: transform 0.18s var(--ui-ease);
}
.impito-style-card:active {
  transform: scale(0.97);
}
@keyframes impito-card-in {
  from {
    opacity: 0;
    transform: translateY(16px) scale(0.96);
  }
}
.impito-style-card__image,
.impito-style-card__placeholder {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.impito-style-card__placeholder {
  display: grid;
  place-items: center;
  background: var(--ui-fill-2);
  font-size: 46px;
}
.impito-style-card__overlay {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 36px 14px 13px;
  background: linear-gradient(
    180deg,
    rgba(12, 18, 48, 0) 0%,
    rgba(12, 18, 48, 0.52) 58%,
    rgba(12, 18, 48, 0.74) 100%
  );
}
.impito-style-card__kicker {
  overflow: hidden;
  color: rgba(255, 255, 255, 0.72);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.impito-style-card__name {
  display: -webkit-box;
  overflow: hidden;
  color: #fff;
  font-size: 16px;
  font-weight: 650;
  line-height: 1.22;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
.impito-style-detail__head {
  display: block;
  padding: 16px 22px 18px;
}
.impito-style-detail__head .ui-page-sub {
  margin: 0 0 6px;
  font-size: 14px;
}
.impito-style-detail__head .ui-page-title {
  max-width: 100%;
  font-size: 30px;
  line-height: 1.06;
  overflow-wrap: anywhere;
  text-wrap: balance;
}
.impito-style-gallery {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 0;
}
.impito-style-gallery .impito-style-detail__image {
  height: 190px;
  border-radius: calc(var(--ui-radius-card) * 0.72);
}
.impito-style-gallery .impito-style-detail__image:first-child {
  grid-column: 1 / -1;
  height: auto;
  max-height: 520px;
  border-radius: var(--ui-radius-card);
}
.impito-style-pager {
  position: relative;
}
.impito-style-pager__track {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.impito-style-pager__track::-webkit-scrollbar {
  display: none;
}
.impito-style-pager__slide {
  flex: 0 0 100%;
  scroll-snap-align: center;
  scroll-snap-stop: always;
}
.impito-style-pager__slide .impito-style-detail__image {
  width: 100%;
  max-width: none;
  aspect-ratio: 3 / 4;
  max-height: 520px;
  object-fit: cover;
  border-radius: var(--ui-radius-card);
}
.impito-style-pager__badge {
  position: absolute;
  top: 12px;
  right: 24px;
  z-index: 2;
  padding: 5px 11px;
  border-radius: 999px;
  background: rgba(12, 18, 48, 0.45);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  backdrop-filter: blur(10px) saturate(140%);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
/* Отступ от промпта до референсов: 24 → 21.6 → 18 → 14px (28.08.2026). Только
   у этой секции — остальные интервалы на экране остаются прежними.
   С 07.09.2026 референсы стоят ВЫШЕ промпта (просьба юзера), и те же 12px
   теперь стоят между референсами и промптом, а прежние 12px промпта — между
   промптом и плитками параметров: три верхних блока держатся одним ритмом. */
.impito-prompt-section.ui-section {
  margin-bottom: 12px;
}
.impito-photo-page > [data-photo-section].ui-section {
  margin-bottom: 12px;
}
/* Плитки параметров ближе к ползунку качества: 24 → 16 → 14px (07.09.2026,
   просьба юзера «чуть меньше», затем «совсем чуть-чуть меньше»). */
.impito-params.ui-section {
  margin-bottom: 14px;
}

/* Поле промпта на экране генерации РАСТЁТ ПОД ТЕКСТ: начинается низким, тянется
   до потолка, дальше листается (просьба юзера 28.08.2026). Высоту ставит
   скрипт, здесь только границы. Отдельный класс, а не общее правило: на экране
   стилей то же поле фиксированной высоты и без скрипта — сняв там высоту, мы
   схлопнули бы его до двух строк навсегда. */
.impito-style-prompt.impito-prompt-autogrow.ui-field {
  height: auto;
  /* Одна строка и минимум воздуха вокруг: пустое поле не должно занимать
     экран (28.08.2026, дважды «сделай ещё меньше»). Ниже уже не опустить —
     упрёмся в саму строку текста. Вертикальные поля 16 → 11px, иначе высоту
     держали бы они, а не содержимое. */
  /* Высота одной строки — 44px: столько же, сколько у кнопок и строк списка,
     и ровно рекомендованный минимум для касания. По дороге пробовали 50, 40,
     34, 32, 28 и 26 — 26 оказалось «пизда какая-то» (28.08.2026), меньше 44
     смысла нет.
     ВЕРТИКАЛЬНОЕ ЦЕНТРИРОВАНИЕ ОДНОЙ СТРОКИ. У textarea нет ни flex, ни
     align-items, поэтому строке задана высота, равная внутренней: 44px минус
     поля по 10px. Как только строк становится больше, правило ниже (.is-tall)
     возвращает обычный множитель. */
  height: 44px;
  min-height: 44px;
  max-height: 220px;
  /* Рост под текст — переходом, а не скачком (просьба юзера 28.08.2026).
     Радиус едет вместе с высотой: он меняется ровно в тот момент, когда текст
     переходит на вторую строку. */
  transition:
    height 0.18s var(--ui-ease),
    border-radius 0.18s var(--ui-ease);
  padding: 10px 18px;
  font-size: 16px;
  line-height: 24px;
  /* Таблетка, пока строка одна. Радиус в 999px движок режет до половины
     высоты, поэтому торцы остаются полукруглыми сами собой. */
  border-radius: var(--ui-radius-pill);
}
/* ПЛЕЙСХОЛДЕР С АКЦЕНТНЫМ ПЕРВЫМ СЛОВОМ (02.09.2026, просьба юзера).
   Родной `::placeholder` — один текстовый узел, покрасить в нём отдельное
   слово нечем. Поэтому он прозрачный, но НА МЕСТЕ: по нему работает
   `:placeholder-shown` ниже и его читает скринридер, — а видимый текст рисует
   слой рядом с полем.

   Геометрия повторена вручную и обязана совпадать с полем: те же поля
   10px/18px, тот же кегль 16px и та же строка 24px, иначе подсказка поедет
   относительно курсора. Меняешь одно — правь и второе. */
.impito-prompt-card {
  position: relative;
}
.impito-style-prompt.impito-prompt-autogrow::placeholder {
  color: transparent;
}
.impito-prompt-ph {
  position: absolute;
  top: 10px;
  right: 18px;
  left: 18px;
  display: none;
  overflow: hidden;
  color: var(--ui-hint);
  font-size: 16px;
  line-height: 24px;
  /* Слой лежит поверх поля, но касания и выделение достаются полю. */
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* Показываем ровно тогда, когда поле пустое. Никакого js: `:placeholder-shown`
   гаснет на первом же введённом символе и возвращается, когда текст стёрли. */
.impito-style-prompt.impito-prompt-autogrow:placeholder-shown + .impito-prompt-ph {
  display: block;
}
.impito-prompt-ph b {
  color: var(--ui-accent-ink);
  font-weight: inherit;
}
/* Текст перешёл на вторую строку — возвращаем карточный радиус: у высокого
   поля полукруглые торцы читаются как овал. Класс ставит скрипт вместе с
   высотой. */
.impito-style-prompt.impito-prompt-autogrow.ui-field.is-tall {
  border-radius: 22px;
  /* Многострочный текст — обычный интерлиньяж. Центрирование одной строки
     высотой строки (см. выше) здесь только растащило бы абзац. */
  line-height: 1.3;
}
.impito-style-prompt.ui-field {
  height: 220px;
  min-height: 220px;
  max-height: 220px;
  padding: 16px 18px;
  overflow-y: auto;
  font-size: 14.5px;
  line-height: 1.45;
  resize: none;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
.impito-style-prompt-actions {
  display: flex;
  padding: 10px 12px 0;
}
.impito-style-edit.ui-button {
  height: 38px;
  padding-inline: 18px;
}
.impito-style-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.impito-style-section-head .ui-section-header:last-child {
  color: var(--ui-hint);
  font-weight: 400;
}
/* Заголовок «референсы» ближе к самой ленте: 9 → 5px нижнего поля, вместе с
   верхним полем ленты (тоже 5px) получается ровно 10px (28.08.2026). */
[data-photo-section] .impito-style-section-head .ui-section-header {
  margin-bottom: 5px;
}

/* ЛЕНТА РЕФЕРЕНСОВ — ОДНА СТРОКА С ГОРИЗОНТАЛЬНЫМ ЛИСТАНИЕМ (10.08.2026,
   просьба юзера). Была сетка с переносом: пятый референс уезжал на второй ряд и
   двигал вниз всё, что под ним. Теперь строка одна и никогда не переносится —
   `flex` + `overflow-x: auto`, у плиток `flex: 0 0 <ширина>`, чтобы их не жало
   под ширину экрана.

   ПЛИТКИ ФИКСИРОВАННОЙ ШИРИНЫ, А НЕ `1fr` (та же дата, «сделай на 20% меньше»).
   Было `minmax(92px, 1fr)`: 92px — только минимум, а дальше колонки тянулись на
   всю строку, и на 375px выходило три плитки по 109px. Через минимум размер так
   не убавить — растяжка всё равно вернула бы 109px. Поэтому ширина задана
   прямо: 87px = 109 − 20%. Радиусы пересчитаны в той же пропорции (18 →
   14.5px), иначе на уменьшённом квадрате углы читаются заметно круглее.

   ХВОСТ СЛЕДУЮЩЕЙ ПЛИТКИ ПОЛУЧАЕТСЯ САМ, ПОДГОНЯТЬ НИЧЕГО НЕ НАДО. Считается
   так: 12px отступ + плюс 87 + 12 + «вставить» 43.5 + 12 + плитки по 87 через
   12. На экране 375px третья плитка начинается на 364.5 — то есть выглядывает
   ровно на 10.5px. Это и есть просьба «чтобы чуть-чуть торчала следующая».
   Пока лента помещается целиком, не торчит ничего — и правильно, листать
   нечего. `scroll-snap` СОЗНАТЕЛЬНО НЕ ВКЛЮЧЁН: ширины в ленте разные (плюс
   87, «вставить» 43.5, фото 87), и обязательная привязка дёргала бы ленту к
   разнокалиберным точкам.

   `padding-top: 9px` — не про воздух, а про крестик удаления: он торчит на 7px
   выше плитки, а у скролл-контейнера `overflow-y` перестаёт быть `visible` и
   срезал бы его. В padding контейнера крестик попадает и остаётся целым. */
.impito-style-photos {
  --ui-ref-tile: 87px;
  display: flex;
  gap: 12px;
  /* Справа НЕ padding, а отступ у последней плитки (ниже). Причина известная:
     часть вебвью на WebKit не учитывает правый padding у флексового
     скролл-контейнера, и в конце ленты последняя плитка липла бы к кромке
     экрана вместе со своим крестиком. Отступ у элемента считают все. */
  padding: 5px 0 0 12px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}
.impito-style-photos::-webkit-scrollbar {
  display: none;
}
.impito-style-photos > * {
  flex: 0 0 var(--ui-ref-tile);
}
.impito-style-photos > :last-child {
  margin-right: 12px;
}
.impito-style-photo {
  position: relative;
  display: block;
}
.impito-style-photo img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 14.5px;
  object-fit: cover;
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.08);
}
.impito-style-photo__remove {
  position: absolute;
  top: -7px;
  right: -7px;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 2px solid var(--ui-bg);
  border-radius: 50%;
  background: rgba(12, 18, 48, 0.78);
  color: #fff;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-style-photo__remove svg {
  width: 11px;
  height: 11px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}
.impito-style-photo-add {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  padding: 0;
  border: 1.5px dashed var(--ui-dash);
  border-radius: 14.5px;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-style-photo-add:active {
  background: var(--ui-press);
}
/* Файл тащат в окно — плюс подсвечивается, чтобы было видно, куда он упадёт.
   Класс вешает photo_picker.js на саму сетку, а не на плитку: плитки в ней
   перерисовываются при каждом добавлении. */
.impito-style-photos.is-drop-target .impito-style-photo-add {
  border-color: var(--ui-accent-strong);
  background: var(--ui-press);
}
/* Кружок с плюсом ужат в той же пропорции, что и плитка (40 → 32px, значок
   18 → 14.5px): оставить прежний — и он занял бы почти весь уменьшённый
   квадрат, вместо аккуратной цели по центру получилась бы кнопка в рамке. */
.impito-style-photo-add span {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--ui-dash-strong);
  border-radius: 50%;
  color: var(--ui-accent-strong);
}
/* «ВСТАВИТЬ» — РОВНО ПОЛОВИНА ПЛИТКИ ПО ШИРИНЕ (10.08.2026, «представь, что
   кнопку референса поделили пополам по вертикали, вот она такого размера»).
   Высота остаётся полной: `align-items` у ленты по умолчанию `stretch`, а
   `aspect-ratio: 1` здесь снят — иначе квадрат пересилил бы половинную ширину и
   кнопка вышла бы вдвое ниже соседей. Пунктир, радиус и кружок со значком —
   те же, что у плюса, класс `.impito-style-photo-add` оставлен на кнопке
   намеренно: это одна и та же кнопка «добавить», просто другим способом. */
/* Селектор нарочно с родителем: правило выше (`.impito-style-photos > *`) имеет
   ту же вес-категорию, и без этого ширина держалась бы только на порядке строк
   в файле.
   Ширина: половина плитки + 15%, потом ещё +5% (11.08.2026, две просьбы
   подряд). 1.15 × 1.05 = 1.2075, то есть 52.5px при плитке 87. Записано
   формулой, а не числом, чтобы связь с размером плитки не терялась: поменяешь
   `--ui-ref-tile` — кнопка поедет следом. */
.impito-style-photos .impito-style-photo-paste {
  flex-basis: calc(var(--ui-ref-tile) / 2 * 1.2075);
  aspect-ratio: auto;
}
.impito-style-photo-add svg {
  width: 14.5px;
  height: 14.5px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  /* Для плюса безразлично — у него нет углов, — а планшетке «вставить» без
     этого острые стыки на скруглениях. */
  stroke-linejoin: round;
}
.impito-style-photos-count.ui-section-header {
  color: var(--ui-hint);
  font-weight: 400;
  font-feature-settings: "tnum" 1;
  font-variant-numeric: tabular-nums;
}
/* Перебор длины промпта. Цвет тот же, что у «удалить» и прочих отказов, — по
   нему сразу понятно, что кнопка погасла именно из-за этого. */
.impito-style-photos-count.is-over {
  color: var(--ui-destructive);
  font-weight: 590;
}
.impito-style-upload__input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.impito-style-detail.ui-page {
  /* +18px по той же просьбе, что и у генерации: 62 → 80. */
  padding-top: calc(80px + var(--ui-safe-top));
  padding-bottom: calc(184px + var(--ui-safe-bottom));
}
.impito-style-submit.ui-submit {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(82px + var(--ui-safe-bottom));
  z-index: 70;
  padding: 0;
  pointer-events: none;
}
/* Переключатель «токены / подписка» вписан В ТЕ ЖЕ ПРАВИЛА, что и нижняя
   панель (18.08.2026, просьба сделать «дотошную копию по спецэффектам»).
   Именно общий селектор, а не копия значений: стекло тут собрано из шести
   теней, тумана на :before и двух платформенных вариантов размытия — копия
   разъехалась бы при первой же правке панели. Размеры и раскладку переопределяю
   отдельным правилом ниже, всё остальное приезжает отсюда. */
/* Стекло нижней панели общее С БЕГУНКОМ переключателя, а не с его дорожкой
   (18.08.2026). Сам переключатель теперь плоский, как на референсе: светлая
   дорожка, а «стеклом» выглядит только та половина, что выбрана.
   Именно общий селектор, а не копия значений: эффект собран из шести теней,
   тумана на :before и двух платформенных вариантов размытия — копия
   разъехалась бы при первой же правке панели. Раскладку бегунка
   переопределяю ниже, всё остальное приезжает отсюда. */
.impito-style-submit__inner {
  position: relative;
  display: grid;
  grid-template-columns: max-content max-content minmax(0, 1fr);
  align-items: center;
  gap: 6px;
  width: min(calc(100% - 48px), 504px);
  height: 67px;
  margin: 0 auto;
  padding: 0 10px;
  border-radius: 34px;
  background: transparent;
  /* Внешней тени НЕТ (2026-07-30, просьба юзера) — как и у таббара, остались
     только внутренние блики стекла. Первая строка — та же волосяная тёмная
     обводка 0.5px, что у таббара: на 2x/3x это ровно 1 физический пиксель.
     Именно box-shadow, а не border — border с `box-sizing: border-box` съел бы
     внутреннюю высоту и сдвинул содержимое панели. */
  box-shadow:
    0 0 0 0.5px rgba(12, 18, 48, 0.22),
    inset 0 1.2px 1px -0.5px rgba(255, 255, 255, 0.5),
    inset 0 -1px 1px -0.5px rgba(255, 255, 255, 0.22),
    inset 1px 0 1px -0.5px rgba(255, 255, 255, 0.3),
    inset -1px 0 1px -0.5px rgba(255, 255, 255, 0.3),
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.15);
  pointer-events: auto;
}
/* Реставрация и улучшение качества: одно фото за запрос, счётчика количества
   на панели нет. Без этого третья колонка сетки осталась бы пустой, а кнопка
   встала бы в середину панели (02.08.2026). */
.impito-style-submit__inner--duo {
  grid-template-columns: max-content minmax(0, 1fr);
}
.impito-style-submit__inner:before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  /* Same pink-tinted fog as the tabbar (anti white-flash on iOS reload). */
  background: var(--ui-glass-panel);
  -webkit-backdrop-filter: blur(1px) saturate(118%);
  backdrop-filter: blur(1px) saturate(118%);
  pointer-events: none;
}
html.impito-lg-refract .impito-style-submit__inner:before {
  -webkit-backdrop-filter: url(#impito-lg-refraction);
  backdrop-filter: url(#impito-lg-refraction);
}
.impito-style-cost,
.impito-style-quantity,
.impito-style-generate {
  position: relative;
  z-index: 1;
}
.impito-style-cost {
  display: flex;
  width: 56px;
  min-width: 56px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding-left: 4px;
}
.impito-style-cost__value {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  color: var(--ui-text);
  white-space: nowrap;
}
.impito-style-cost__value strong {
  font-size: 19px;
  font-weight: 650;
  font-feature-settings: "tnum" 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1;
}
.impito-style-cost__value span {
  color: var(--ui-hint);
  font-size: 11px;
  font-weight: 500;
  line-height: 1;
}
.impito-style-quantity {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.impito-style-count {
  display: grid;
  place-items: center;
  min-width: 44px;
  height: 40px;
  border-radius: 11px;
  background: var(--ui-count-bg);
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.12);
  color: var(--ui-text);
  font-size: 16px;
  font-weight: 600;
  font-feature-settings: "tnum" 1;
  font-variant-numeric: tabular-nums;
}
.impito-style-stepper {
  display: inline-flex;
  align-items: center;
  height: 40px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-fill);
}
.impito-style-stepper__button {
  display: grid;
  place-items: center;
  width: 46px;
  height: 40px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ui-text);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-style-stepper__button:first-of-type {
  border-radius: 999px 0 0 999px;
}
.impito-style-stepper__button:last-of-type {
  border-radius: 0 999px 999px 0;
}
.impito-style-stepper__button:active {
  background: rgba(12, 18, 48, 0.1);
}
.impito-style-stepper__button:disabled {
  cursor: default;
  opacity: 0.3;
}
.impito-style-stepper__button svg {
  display: block;
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}
.impito-style-stepper__divider {
  width: 1px;
  height: 18px;
  background: var(--ui-separator);
}
.impito-style-generate {
  display: inline-flex;
  min-width: 0;
  height: 40px;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-accent);
  color: var(--ui-accent-text);
  font: inherit;
  font-size: clamp(11.5px, 3.3vw, 14px);
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* Цвет и текст переходят плавно, но быстро: кнопка загорается, как только
     в промпте появился текст, и это должно читаться как отклик, а не как
     перекраска (21.08.2026). Трансформация оставлена как была. */
  transition:
    transform 0.15s var(--ui-ease),
    background-color 0.18s var(--ui-ease),
    color 0.18s var(--ui-ease);
}
.impito-style-generate:active {
  transform: scale(0.97);
}
/* Недоступная кнопка обязана ВЫГЛЯДЕТЬ недоступной. Экраны реставрации и
   улучшения качества открываются именно в этом состоянии — пока не добавлено
   фото, обрабатывать нечего, — и розовая кнопка, которая просто не нажимается,
   читалась бы как поломка. Тем же стилем гаснет кнопка генерации при переборе
   лимита промпта (02.08.2026). */
.impito-style-generate:disabled {
  background: var(--ui-accent-soft);
  color: var(--ui-hint);
  cursor: default;
}
.impito-style-generate:disabled:active {
  transform: none;
}
.impito-style-generate span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.impito-style-generate svg {
  display: block;
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.impito-sheet {
  position: fixed;
  inset: 0;
  z-index: 120;
  /* Открытый лист не должен прокручивать страницу под собой (09.09.2026,
     «почему я могу листать панель»): жесты по подложке гасим, панель
     прокручивается сама и не передаёт прокрутку документу. */
  touch-action: none;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 0 10px calc(10px + var(--ui-safe-bottom));
}
.impito-sheet[hidden] {
  display: none;
}
.impito-sheet__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(12, 18, 48, 0.28);
  opacity: 0;
  transition: opacity 0.2s var(--ui-ease);
}
.impito-sheet__panel {
  position: relative;
  display: flex;
  width: min(100%, 504px);
  max-height: calc(100% - 16px);
  flex-direction: column;
  gap: 8px;
  margin: 0 auto;
  /* ПАНЕЛЬ НЕ РЕЖЕТ СОДЕРЖИМОЕ. Прокрутка длинного листа живёт в группе
     (ниже), а не здесь: overflow на панели (09.09.2026, «лист под таббаром»)
     обрезал внешнюю тень группы (`0 0 25px` в --ui-sheet-glass-shadow) по
     прямоугольнику панели — в уголках за скруглением оставались тёмные
     «ушки» (скриншот владельца с iPhone, светлая тема). */
  opacity: 0;
  transform: translateY(24px);
  transition:
    transform 0.22s var(--ui-ease-out),
    opacity 0.18s var(--ui-ease);
}
.impito-sheet.is-open .impito-sheet__backdrop {
  opacity: 1;
}
.impito-sheet.is-open .impito-sheet__panel {
  opacity: 1;
  transform: translateY(0);
}
.impito-sheet__group {
  /* Скругление режет содержимое, по вертикали группа прокручивается сама,
     когда лист выше экрана (панель — flex-колонка с max-height, поэтому
     min-height: 0 обязателен, иначе группа не ужимается). Прокрутка внутри
     группы, а не на панели — чтобы не резать внешнюю тень (см. панель). */
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  /* ФАКТУРА ЭКШН-ШИТА iOS 26 (08.09.2026, просьба юзера: «оставляем нашу
     менюшку 1 в 1 по анимациям и функционалу, меняем только фактуру»).
     Радиус 32, белое стекло 75% с размытием 16px и насыщенностью 1.8,
     стопка внутренних теней в токене — она и даёт блик по кромке. */
  border-radius: 32px;
  background: var(--ui-sheet-glass-bg);
  /* Размытие — токен: светлая 15px, тёмная 18.5px (08.09.2026). */
  -webkit-backdrop-filter: saturate(1.8) blur(var(--ui-sheet-blur));
  backdrop-filter: saturate(1.8) blur(var(--ui-sheet-blur));
  box-shadow: var(--ui-sheet-glass-shadow);
}
.impito-sheet__option {
  display: block;
  width: 100%;
  height: 54px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ui-accent-strong);
  font: inherit;
  font-size: 17px;
  font-weight: 500;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-sheet__option + .impito-sheet__option {
  border-top: 0.5px solid var(--ui-sheet-divider);
}
.impito-sheet__option:active {
  background: var(--ui-press);
}
.impito-sheet__cancel {
  display: block;
  width: 100%;
  height: 54px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-sheet-cancel);
  -webkit-backdrop-filter: blur(2px) saturate(145%);
  backdrop-filter: blur(2px) saturate(145%);
  /* Тот же розовый, что у вариантов выше (2026-07-31, просьба юзера): чёрный
     жирный текст выбивался из листа. */
  color: var(--ui-accent-strong);
  font: inherit;
  font-size: 17px;
  font-weight: 640;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  box-shadow:
    0 18px 44px rgba(12, 18, 48, 0.22),
    0 3px 10px rgba(12, 18, 48, 0.09),
    inset 0 1.2px 1px -0.5px rgba(255, 255, 255, 0.5),
    inset 0 -1px 1px -0.5px rgba(255, 255, 255, 0.22),
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.15);
}
.impito-sheet__cancel:active {
  background: var(--ui-sheet-cancel-press);
}
body.impito-camera-open {
  overflow: hidden;
}
.impito-camera {
  position: fixed;
  inset: 0;
  z-index: 160;
  display: flex;
  padding:
    calc(8px + var(--ui-safe-top))
    0
    calc(8px + var(--ui-safe-bottom));
  background: #000;
}
.impito-camera[hidden] {
  display: none;
}
.impito-camera__panel {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) 108px;
  width: min(100%, 504px);
  height: 100%;
  min-height: 0;
  margin: 0 auto;
}
.impito-camera__head {
  display: flex;
  min-height: 44px;
  align-items: center;
  justify-content: center;
  padding: 0 0 6px;
}
.impito-camera__title {
  color: rgba(255, 255, 255, 0.92);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.impito-camera__view {
  position: relative;
  display: grid;
  width: 100%;
  max-width: 100%;
  max-height: 100%;
  min-height: 0;
  aspect-ratio: 3 / 4;
  margin: auto;
  overflow: hidden;
  place-items: center;
  align-self: center;
  border-radius: 20px;
  background: #111;
}
.impito-camera__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.impito-camera__video.is-mirrored {
  transform: scaleX(-1);
}
.impito-camera__video[hidden] {
  display: none;
}
.impito-camera__status {
  max-width: 280px;
  padding: 18px;
  color: rgba(255, 255, 255, 0.78);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.35;
  text-align: center;
}
.impito-camera__status[hidden] {
  display: none;
}
.impito-camera__status.is-error {
  color: #fff;
}
.impito-camera__controls {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0 12px;
}
.impito-camera__shutter {
  display: grid;
  width: 74px;
  height: 74px;
  padding: 5px;
  place-items: center;
  border: 4px solid rgba(255, 255, 255, 0.95);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.impito-camera__shutter span {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.12s var(--ui-ease);
}
.impito-camera__shutter:active span {
  transform: scale(0.88);
}
.impito-camera__shutter:disabled {
  cursor: default;
  opacity: 0.42;
}
.impito-camera__flip {
  display: grid;
  place-items: center;
  justify-self: center;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-camera__flip:active {
  background: rgba(255, 255, 255, 0.24);
}
.impito-camera__flip:disabled {
  cursor: default;
  opacity: 0.35;
}
.impito-camera__flip svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
html[data-font-platform="apple"] .impito-tabbar:before,
html[data-font-platform="apple"] .impito-style-submit__inner:before {
  -webkit-backdrop-filter: blur(1.15px) saturate(120%);
  backdrop-filter: blur(1.15px) saturate(120%);
}
/* WebKit не умеет SVG-фильтры в backdrop-filter, поэтому на apple стекло у
   ползунка своё: слой размытия (:before) + слой обводки с хроматикой (:after).
   Селектор специально длиннее refract-правила (и идёт ниже по файлу): иначе
   `backdrop-filter: url(#impito-lg-thumb)` перебил бы сброс на apple.
   `isolation: isolate` — не косметика: элемент с backdrop-filter в WebKit
   уезжает в собственный композиторский слой и начинает игнорировать порядок
   z-index, из-за чего обводка и хроматика оказывались то над размытием, то под
   ним. Свой контекст наложения + промоушен обоих слоёв через translateZ(0)
   фиксируют порядок. */
/* Класс ползунка повторён намеренно: правилу нужно перебить и drag-вариант
   refract (`.is-dragging` даёт ту же специфичность), иначе на apple в захвате
   тихо возвращается url()-фильтр — в WebKit он не рисуется, но стоит денег. */
html[data-font-platform="apple"]
  .impito-tabbar
  .impito-tabbar__thumb.impito-tabbar__thumb {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  isolation: isolate;
}
/* Размытие живёт в отдельном слое с кольцевой маской: в центре пилюли она
   прозрачна (иконка остаётся резкой), к краю набирает силу. Слой отдельный,
   потому что маска нужна только размытию, а не всему ползунку. */
html[data-font-platform="apple"] .impito-tabbar__thumb:before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  transform: translateZ(0);
  /* В покое слоя нет вообще (2026-07-30): маскированный слой внутри едущей
     пилюли — это отдельная композиция с маской на каждый кадр переезда, и на
     iOS это заметно дороже, чем сам переезд. Включается вместе с фильтром. */
  display: none;
  -webkit-mask-image: radial-gradient(
    ellipse closest-side at 50% 50%,
    transparent 0 42%,
    rgba(0, 0, 0, 0.5) 72%,
    #000 100%
  );
  mask-image: radial-gradient(
    ellipse closest-side at 50% 50%,
    transparent 0 42%,
    rgba(0, 0, 0, 0.5) 72%,
    #000 100%
  );
  pointer-events: none;
}
/* Сам фильтр — только на удержании: в покое он не нужен и дорого стоит,
   подложка пересчитывается каждый кадр, пока пилюля едет. */
html[data-font-platform="apple"].impito-lg-active
  .impito-tabbar__thumb:before,
html[data-font-platform="apple"]
  .impito-tabbar.is-dragging
  .impito-tabbar__thumb:before {
  display: block;
  -webkit-backdrop-filter: blur(7px) saturate(92%);
  backdrop-filter: blur(7px) saturate(92%);
}
/* Обводка пилюли на удержании — СВОЯ и постоянная. Юзер видел её то с
   обводкой, то без: кромка размывающего слоя подхватывала то границу панели
   (пилюля выше панели на 8px), то чистый фон за её краем, и «обводка»
   появлялась только когда под ней было что размывать. Своя линия лежит выше
   размытия (:after z-index 1 против :before 0) и не зависит от того, что под
   пилюлей. Тут же хроматика: тёплая кайма слева, холодная справа — имитация
   дисперсии, которую на Android даёт SVG-линза. */
html[data-font-platform="apple"] .impito-tabbar__thumb:after {
  /* Обводка и хроматика обязаны лежать НАД размытием при любом раскладе:
     свой слой (translateZ) + z-index выше, чем у :before. */
  z-index: 2;
  transform: translateZ(0);
}
html[data-font-platform="apple"].impito-lg-active .impito-tabbar__thumb:after,
html[data-font-platform="apple"]
  .impito-tabbar.is-dragging
  .impito-tabbar__thumb:after {
  box-shadow:
    inset 0 0 0 0.5px rgba(12, 18, 48, 0.16),
    inset 0 0 10px -6px rgba(12, 18, 48, 0.33),
    inset 0 1px 2px rgba(12, 18, 48, 0.12),
    inset 2px 0 2.5px -1.5px rgba(0, 51, 255, 0.34),
    inset -2px 0 2.5px -1.5px rgba(0, 168, 255, 0.3),
    inset 0 2px 2.5px -1.5px rgba(64, 102, 255, 0.22),
    inset 0 -2px 2.5px -1.5px rgba(0, 190, 255, 0.2);
}
/* Тот же захват без стекла читался как неоновая подсветка букв: яркость 1.55
   плюс белый text-shadow на светло-розовом фоне. На apple глушим. */
/* Вкладки НЕ поднимаем над ползунком (пробовали z-index: 4 — стало «ничего не
   изменилось»): внутри панели за пилюлей лежит только плотный туман :before,
   размывать в нём нечего, и единственный контрастный объект в backdrop'е —
   как раз иконка с подписью. Они должны оставаться под ползунком, как на
   Android под линзой. */
html[data-font-platform="apple"] .impito-tabbar.is-dragging .impito-tabbar__item {
  filter: brightness(calc(1.12 + var(--impito-panel-glow, 0) * 0.5));
}
html[data-font-platform="apple"] .impito-tabbar.is-dragging .impito-tabbar__icon,
html[data-font-platform="apple"] .impito-tabbar.is-dragging .impito-tabbar__label {
  text-shadow: none;
}
.impito-style-sticky {
  position: fixed;
  top: 0;
  left: 50%;
  z-index: 60;
  width: min(100%, 560px);
  /* Верхнее поле: не меньше высоты вуали плюс просвет. Иначе поиск и чипсы
     налезали на пилюли профиля и баланса — они позиционируются от вуали, а
     шапка каталога считалась только от safe-top и про них не знала
     (2026-07-30, баг с устройства). max() оставляет старое поведение там, где
     вуаль низкая.
     Нижнее поле 30 → 12px: раньше внизу был градиентный хвост, и 30px уходили
     на растворение. У плоской панели этот запас читается как пустая полоса
     стекла под чипсами. */
  padding: max(calc(56px + var(--ui-safe-top)), calc(var(--ui-veil-height) + 8px))
    0 12px;
  /* Схлопывается вместе с панелью: при скролле вниз --ui-veil-pill-row
     обнуляется, шапка подтягивается вверх. */
  transition: padding-top 0.28s var(--ui-ease);
  /* Полупрозрачное матовое стекло — тот же рецепт, что у вуали body:before на
     главной и у тумана таббара, вместо непрозрачной розовой плашки с градиентом
     (2026-07-30, просьба юзера «как в других везде»).
     Подложка 80% не «на глаз»: iOS первые кадры после reload рисует слой ещё
     без backdrop-filter, ниже 70% будет белая вспышка. */
  background: color-mix(in srgb, var(--ui-bg) 80%, transparent);
  -webkit-backdrop-filter: blur(6px) saturate(140%);
  backdrop-filter: blur(6px) saturate(140%);
  /* Волосяная линия снизу вместо растворения: 0.5px = один физический пиксель
     на 2x/3x. Именно box-shadow, а не border — border съел бы внутреннюю
     высоту и сдвинул поиск с чипсами. */
  box-shadow: 0 0.5px 0 rgba(12, 18, 48, 0.1);
  transform: translateX(-50%);
}
/* Пока на экране шапка каталога, общая вуаль body:before выключена: они лежат
   друг на друге в верхней полосе, и две подложки по 80% давали там ~96% —
   заметно плотнее остальной панели, плюс лишний слой с backdrop-filter поверх
   скроллящегося каталога. Селектор через :has() намеренно: у экрана детали
   стиля своей шапки нет, и вуаль там нужна. Если браузер не знает :has(),
   правило просто игнорируется и остаётся прежнее поведение. */
body:has(.impito-style-sticky):before {
  display: none;
}
.impito-style-sticky__title {
  position: absolute;
  top: calc(var(--ui-safe-top) + 11px);
  left: 72px;
  right: 72px;
  text-align: center;
  /* Заголовок шапки: 19 → 15.2 → 16.4px (−20%, потом +8%), интерлиньяж следом. */
  font-size: 16.4px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 23px;
  color: var(--ui-text);
}
.impito-style-sticky .ui-section {
  margin-bottom: 12px;
}
.impito-style-sticky .ui-section:last-child {
  margin-bottom: 0;
}
.impito-styles-page.ui-page {
  /* Значение ставит prompt_styles.js по НАСТОЯЩЕЙ высоте шапки: она зависит от
     вуали, а та — от инсетов Telegram, и константой не выражается. Фолбэк здесь
     на случай, если скрипт не успел (первый кадр) или измерение не удалось. */
  padding-top: var(--ui-catalog-top, calc(98px + var(--ui-safe-top)));
}
.impito-styles-page .ui-page-head {
  padding-top: 0;
  visibility: hidden;
}
.impito-style-search {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  height: 44px;
  margin: 0 12px;
  padding: 0 16px;
  border-radius: var(--ui-radius-pill);
  /* НЕПРОЗРАЧНАЯ ЗАЛИВКА (17.08.2026, просьба юзера). До этого стояло
     rgba(255,255,255,0.5): задумка была «поле на стеклянной шапке, а не
     наклеенный сверху блок», но на деле сквозь него просвечивали карточки
     каталога — при скролле под строкой поиска ехали чужие заголовки.
     Цвет тот же, что у плиток в истории: белый с розоватым оттенком.
     Своего backdrop-filter тут НЕТ намеренно: подложку уже размыла шапка,
     второй фильтр внутри неё — лишний композиторский слой поверх
     скроллящегося каталога, на iOS это дорого. */
  background: var(--ui-field-bg);
  box-shadow:
    0 0 0 0.5px rgba(12, 18, 48, 0.1),
    inset 0 1.2px 1px -0.5px rgba(255, 255, 255, 0.5),
    inset 0 -1px 1px -0.5px rgba(255, 255, 255, 0.22),
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.15);
  cursor: text;
}
.impito-style-search svg {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  fill: none;
  stroke: var(--ui-ink-soft);
  stroke-width: 1.8;
  stroke-linecap: round;
}
.impito-style-search input {
  min-width: 0;
  height: 100%;
  flex: 1;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ui-text);
  font: inherit;
  font-size: 17px;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}
.impito-style-search input::placeholder {
  color: var(--ui-ink-soft);
}
.impito-style-search input::-webkit-search-decoration {
  display: none;
}
.impito-style-chips {
  padding: 0 12px;
}
.impito-style-empty {
  grid-column: 1 / -1;
  margin: 0;
  padding: 30px 0;
  color: var(--ui-hint);
  font-size: 15px;
  text-align: center;
}
#impito-prompt-styles main[data-anim="fade"] {
  animation: impito-page-in 0.3s var(--ui-ease-out);
}
#impito-prompt-styles main[data-anim="push"] {
  animation: impito-push-in 0.34s var(--ui-ease-nav);
}
#impito-prompt-styles main[data-anim="pop"] {
  animation: impito-pop-in 0.3s var(--ui-ease-nav);
}
@keyframes impito-page-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}
@keyframes impito-push-in {
  from {
    opacity: 0.15;
    transform: translateX(64px);
  }
}
@keyframes impito-pop-in {
  from {
    opacity: 0.15;
    transform: translateX(-48px);
  }
}
#impito-prompt-styles .ui-chip {
  transition:
    transform 0.15s var(--ui-ease),
    background-color 0.2s var(--ui-ease),
    color 0.2s var(--ui-ease);
}
#impito-prompt-styles .ui-chip:active {
  transform: scale(0.94);
}
.impito-style-submit__inner {
  animation: impito-submit-in 0.4s var(--ui-ease-out) 0.05s backwards;
}
@keyframes impito-submit-in {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
}
.impito-style-count.is-pop {
  animation: impito-count-pop 0.26s var(--ui-ease-out);
}
@keyframes impito-count-pop {
  35% {
    transform: scale(1.16);
  }
}
.impito-style-photo img {
  transition:
    opacity 0.32s var(--ui-ease),
    transform 0.32s var(--ui-ease);
}
.impito-style-photo.is-loading {
  border-radius: 18px;
  background: var(--ui-white-veil);
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.08);
}
.impito-style-photo.is-loading img {
  opacity: 0;
  transform: scale(1.05);
}
.impito-style-photo__spinner {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 22px;
  height: 22px;
  margin: -11px 0 0 -11px;
  border: 2.5px solid rgba(12, 18, 48, 0.14);
  border-radius: 50%;
  border-top-color: var(--ui-accent-strong);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s var(--ui-ease);
}
.impito-style-photo.is-loading .impito-style-photo__spinner {
  opacity: 1;
  animation: impito-spin 0.8s linear infinite;
}
@keyframes impito-spin {
  to {
    transform: rotate(360deg);
  }
}
.impito-style-photo__remove {
  transition: opacity 0.2s var(--ui-ease);
}
.impito-style-photo.is-loading .impito-style-photo__remove {
  opacity: 0;
  pointer-events: none;
}
.impito-style-photo.is-repainting {
  animation: impito-photo-repaint 0.06s linear;
}
@keyframes impito-photo-repaint {
  from {
    opacity: 0.99;
    transform: translateZ(0);
  }
  to {
    opacity: 1;
    transform: translateZ(0);
  }
}
.impito-style-photo.is-removing {
  animation: impito-tile-out 0.18s var(--ui-ease) forwards;
  pointer-events: none;
}
@keyframes impito-tile-out {
  to {
    opacity: 0;
    transform: scale(0.82);
  }
}
.impito-style-photo,
.impito-style-photo-add {
  animation: impito-tile-in 0.24s var(--ui-ease-out);
}
@keyframes impito-tile-in {
  from {
    opacity: 0;
    transform: scale(0.94);
  }
}
.impito-camera {
  opacity: 0;
  transition: opacity 0.22s var(--ui-ease);
}
.impito-camera.is-open {
  opacity: 1;
}
@media (max-width: 380px) {
  .impito-style-grid {
    gap: 10px;
  }
  .impito-style-card__name {
    font-size: 15px;
  }
  .impito-style-detail__head .ui-page-title {
    font-size: 28px;
  }
}
@media (max-width: 390px) {
  .impito-style-generate svg {
    display: none;
  }
}
/* На 375px кнопке доставалось 108px, а «генерировать» на живом размере шрифта
   (clamp даёт 12.4px) требует ~111px — подпись обрезалась многоточием. Цена и
   счётчик занимают `max-content`, поэтому единственный запас — поля самой
   кнопки. 12 → 8px хватает (замер 2026-07-31). Экраны от 390px не тронуты. */
@media (max-width: 380px) {
  .impito-style-generate {
    padding: 0 8px;
  }
}
@media (max-width: 390px) {
  .impito-style-submit__inner {
    width: min(calc(100% - 36px), 504px);
    height: 64px;
  }
}
@media (max-width: 350px) {
  .impito-style-submit__inner {
    gap: 5px;
    padding: 0 8px;
  }
  .impito-style-cost {
    width: 50px;
    min-width: 50px;
    padding-left: 2px;
  }
  .impito-style-count {
    min-width: 40px;
  }
  .impito-style-stepper__button {
    width: 40px;
  }
  .impito-style-generate {
    padding: 0 9px;
  }
  .impito-style-photos {
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 10px;
  }
}
.ui-hero {
  padding: 40px 16px 26px;
}
.ui-hero-emoji {
  width: 128px;
  height: 128px;
}
.ui-hero-emoji:has(.set-hero-mascot) {
  position: relative;
  width: 288px;
  height: 288px;
  animation: none;
}
.ui-hero-emoji:has(.set-hero-mascot):before {
  content: none;
  display: none;
}
.set-hero-mascot {
  animation: none !important;
  transform: none !important;
  -webkit-user-drag: none;
  -webkit-user-select: none;
  user-select: none;
  pointer-events: none;
}
.ui-hero:has(.set-hero-mascot) {
  padding-top: 32px;
}
.ui-hero-emoji:has(.set-hero-mascot) + .ui-hero-title {
  display: none;
  margin-top: 0;
}
.ui-hero-title {
  margin: 14px 0 0;
  color: var(--ui-text);
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
  text-wrap: balance;
}
.ui-hero-sub {
  margin: 8px 0 0;
  max-width: 40ch;
  color: var(--ui-hint);
  font-size: 15px;
  line-height: 1.4;
  text-align: center;
  text-wrap: pretty;
}
.set-center {
  display: flex;
  min-height: 70vh;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 0 24px;
}
.set-status {
  color: var(--ui-hint);
  font-size: var(--ui-size-row, 17px);
  text-align: center;
}
.set-trailing {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
}
.set-value {
  overflow: hidden;
  max-width: 190px;
  color: var(--ui-hint);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.set-chevron {
  display: inline-flex;
  color: var(--ui-separator-strong);
}
.set-dismiss {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin: -4px -2px -4px 2px;
  padding: 0;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: none;
  color: var(--ui-hint);
  cursor: pointer;
  pointer-events: auto;
}
.set-dismiss:active {
  background: var(--ui-press);
}
@media (hover: hover) {
  .set-dismiss:hover {
    background: var(--ui-hover);
  }
}
.set-style-apply {
  display: block;
  width: 100%;
  margin: -13px 0;
  padding: 13px 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.set-style-apply:active {
  opacity: 0.55;
}
.set-options {
  display: flex;
  flex-direction: column;
  padding: 2px 8px 4px;
}
.set-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 50px;
  padding: 12px 14px;
  border: 0;
  border-radius: 14px;
  background: none;
  color: var(--ui-text);
  cursor: pointer;
  font-family: var(--ui-font);
  font-size: var(--ui-size-row, 17px);
  text-align: left;
  transition: background var(--ui-dur) var(--ui-ease);
}
.set-option:active {
  background: var(--ui-press);
}
.set-option-label {
  min-width: 0;
  flex: 1 1 auto;
}
.set-option-check {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--ui-accent-ink);
}
.set-option-check--anim {
  opacity: 0;
  transform: scale(0.5);
  transition:
    opacity var(--ui-dur) var(--ui-ease),
    transform var(--ui-dur) var(--ui-ease-out);
}
.set-option-check--anim.set-option-check--on {
  opacity: 1;
  transform: scale(1);
}
@media (prefers-reduced-motion: reduce) {
  .set-option-check--anim {
    transition: none;
  }
}
.set-tz-offset {
  flex: 0 0 auto;
  color: var(--ui-hint);
  font-variant-numeric: tabular-nums;
  font-size: 14px;
}
.set-detail-desc {
  max-width: 34ch;
  margin: 6px auto 18px;
  padding: 0 22px;
  color: var(--ui-hint);
  font-size: 15px;
  line-height: 1.4;
  text-align: center;
}
.set-media {
  padding: 0 12px;
  margin-bottom: 20px;
}
.set-media-img,
.set-media-video {
  display: block;
  width: 100%;
  max-width: min(100%, 440px);
  margin-inline: auto;
  border-radius: var(--ui-radius-card);
  object-fit: cover;
}
.set-viz {
  padding: 0 12px;
  margin-bottom: 20px;
}
.set-viz-prev {
  display: block;
  width: 100%;
  max-width: min(100%, 440px);
  margin-inline: auto;
  aspect-ratio: 1080 / 504;
  overflow: hidden;
  border-radius: var(--ui-radius-card);
  background: var(--ui-fill);
}
.set-biz-item {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 18px;
}
.set-biz-item + .set-biz-item {
  border-top: 1px solid var(--ui-separator);
}
.set-biz-label {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--ui-text);
  font-size: 17px;
  letter-spacing: -0.01em;
}
.set-biz-item .ui-segmented {
  display: flex;
  width: 100%;
}
.set-biz-item .ui-segment {
  flex: 1 1 0;
  min-width: 0;
}
.set-option-check--confirm {
  color: var(--ui-confirm);
  animation: set-tz-confirm-pop var(--ui-dur) var(--ui-ease-out) both;
}
.set-option-check--confirm svg path {
  stroke-dasharray: 24;
  animation: set-tz-confirm-draw 0.24s var(--ui-ease-out) both;
}
@keyframes set-tz-confirm-pop {
  0% {
    opacity: 0;
    transform: scale(0.6);
  }
  60% {
    transform: scale(1.08);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
@keyframes set-tz-confirm-draw {
  0% {
    stroke-dashoffset: 24;
  }
  to {
    stroke-dashoffset: 0;
  }
}
.set-tz-picker .ui-row,
.set-tz-picker .ui-field {
  transition:
    opacity var(--ui-dur) var(--ui-ease),
    background-color var(--ui-dur) var(--ui-ease);
}
.set-tz-picker--confirming {
  pointer-events: none;
}
.set-tz-picker--confirming .ui-field,
.set-tz-picker--confirming .ui-row:not(:has(.set-option-check--confirm)) {
  opacity: 0.4;
}
.set-tz-picker--confirming .ui-row:has(.set-option-check--confirm) {
  background-color: color-mix(in srgb, var(--ui-confirm) 14%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .set-option-check--confirm {
    animation: none;
  }
  .set-option-check--confirm svg path {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
    animation: none;
  }
  .set-tz-picker .ui-row,
  .set-tz-picker .ui-field {
    transition: none;
  }
}
.set-stream {
  padding: 0 12px;
  margin-bottom: 20px;
  pointer-events: none;
}
.set-stream-pair {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  max-width: min(100%, 440px);
  margin-inline: auto;
  overflow: hidden;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
}
.set-stream-divider {
  position: absolute;
  top: 12px;
  bottom: 12px;
  left: 50%;
  width: 1px;
  background: var(--ui-separator);
  transform: translate(-50%) scaleX(0.5);
}
.set-stream-col {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 14px 10px;
}
.set-stream-cap {
  color: var(--ui-hint);
  font-size: 12px;
  font-weight: 590;
  text-align: center;
}
.set-stream-cap--on {
  color: var(--ui-accent-ink);
}
.set-stream-thread {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.set-stream-msg {
  max-width: 88%;
  padding: 6px 9px;
  border-radius: 14px;
  font-size: 13px;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.set-stream-msg--out {
  align-self: flex-end;
  border-bottom-right-radius: 5px;
  background: var(--ui-accent);
  color: var(--ui-accent-text);
}
.set-stream-msg--in {
  position: relative;
  align-self: flex-start;
  border-bottom-left-radius: 5px;
  background: var(--ui-fill-2);
  color: var(--ui-text);
  transition: background-color var(--ui-dur) var(--ui-ease);
}
.set-stream-msg--pending {
  background: transparent;
}
.set-stream-ghost {
  visibility: hidden;
}
.set-stream-live {
  position: absolute;
  top: 6px;
  right: 9px;
  bottom: 6px;
  left: 9px;
  transition: opacity var(--ui-dur) var(--ui-ease);
}
.set-stream-pair[data-phase="reset"] .set-stream-live {
  opacity: 0;
}
.set-stream-pair[data-phase="reset"] .set-stream-msg--in {
  background: transparent;
}
.set-stream-dots {
  display: inline-flex;
  height: 1.3em;
  align-items: center;
  gap: 4px;
}
.set-stream-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ui-hint);
  animation: set-stream-blink 1.2s var(--ui-ease) infinite;
}
.set-stream-dot:nth-child(2) {
  animation-delay: 0.16s;
}
.set-stream-dot:nth-child(3) {
  animation-delay: 0.32s;
}
.set-stream-delta {
  animation: set-stream-grow var(--ui-dur) var(--ui-ease-out);
}
.set-stream-cursor {
  color: currentColor;
  white-space: pre;
}
.set-stream-answer {
  display: block;
}
.set-stream-answer--dump {
  animation: set-stream-dump 0.3s var(--ui-ease-out);
}
@keyframes set-stream-blink {
  0%,
  80%,
  to {
    opacity: 0.3;
    transform: translateY(0);
  }
  40% {
    opacity: 1;
    transform: translateY(-1px);
  }
}
@keyframes set-stream-grow {
  0% {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes set-stream-dump {
  0% {
    opacity: 0;
    transform: translateY(10px) scale(0.96);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}
@media (prefers-reduced-motion: reduce) {
  .set-stream-dot,
  .set-stream-delta,
  .set-stream-answer--dump {
    animation: none;
  }
  .set-stream-live {
    transition: none;
  }
}
.set-fw {
  padding: 0 12px;
  margin-bottom: 20px;
  pointer-events: none;
}
.set-fw-card {
  display: flex;
  max-width: min(100%, 440px);
  flex-direction: column;
  gap: 8px;
  margin-inline: auto;
  padding: 14px 12px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
}
.set-fw-thread {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.set-fw-msg {
  max-width: 88%;
  padding: 6px 9px;
  border-radius: 14px;
  font-size: 13px;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.set-fw-msg--out {
  align-self: flex-end;
  border-bottom-right-radius: 5px;
  background: var(--ui-accent);
  color: var(--ui-accent-text);
}
.set-fw-msg--in {
  align-self: flex-start;
  border-bottom-left-radius: 5px;
  background: var(--ui-fill-2);
  color: var(--ui-text);
}
.set-fw-buttons {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 2px;
}
.set-fw-btn {
  padding: 8px 10px;
  border-radius: 10px;
  background: var(--ui-accent-soft);
  color: var(--ui-accent-ink);
  font-size: 13px;
  font-weight: 510;
  line-height: 1.25;
  text-align: center;
}
.set-br {
  padding: 0 12px;
  margin-bottom: 20px;
  pointer-events: none;
}
.set-br-card {
  display: flex;
  max-width: min(100%, 440px);
  flex-direction: column;
  gap: 8px;
  margin-inline: auto;
  padding: 14px 12px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
}
.set-br-burst {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
}
.set-br-msg {
  max-width: 88%;
  padding: 6px 9px;
  border-radius: 14px;
  font-size: 13px;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.set-br-msg--out {
  align-self: flex-end;
  border-bottom-right-radius: 5px;
  background: var(--ui-accent);
  color: var(--ui-accent-text);
}
.set-br-msg--in {
  align-self: flex-start;
  border-bottom-left-radius: 5px;
  background: var(--ui-fill-2);
  color: var(--ui-text);
}
.set-ps {
  padding: 0 12px;
  margin-bottom: 20px;
  pointer-events: none;
}
.set-ps-card {
  display: flex;
  max-width: min(100%, 440px);
  flex-direction: column;
  gap: 8px;
  margin-inline: auto;
  padding: 14px 12px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
}
.set-ps-pinned {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
  padding-left: 10px;
  border-left: 2px solid var(--ui-accent);
}
.set-ps-cap {
  color: var(--ui-accent-ink);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
}
.set-ps-text {
  color: var(--ui-text);
  font-size: 13px;
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.set-ps-seg {
  animation: set-ps-in var(--ui-dur) var(--ui-ease-out);
}
.set-ps-sep {
  color: var(--ui-hint);
}
.set-ps-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 10px;
  border-radius: 10px;
  background: var(--ui-accent-soft);
  color: var(--ui-accent-ink);
  font-size: 13px;
  font-weight: 510;
  line-height: 1.25;
  animation: set-ps-in var(--ui-dur) var(--ui-ease-out);
}
@keyframes set-ps-in {
  0% {
    opacity: 0;
    transform: translateY(3px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .set-ps-seg,
  .set-ps-btn {
    animation: none;
  }
}
.set-rc {
  padding: 0 12px;
  margin-bottom: 20px;
  pointer-events: none;
}
.set-rc-card {
  display: flex;
  max-width: min(100%, 440px);
  flex-direction: column;
  gap: 6px;
  margin-inline: auto;
  padding: 14px 12px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
}
.set-rc-msg {
  max-width: 88%;
  padding: 6px 9px;
  border-radius: 14px;
  font-size: 13px;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.set-rc-msg--out {
  align-self: flex-end;
  border-bottom-right-radius: 5px;
  background: var(--ui-accent);
  color: var(--ui-accent-text);
}
.set-rc-msg--in {
  align-self: flex-start;
  border-bottom-left-radius: 5px;
  background: var(--ui-fill-2);
  color: var(--ui-text);
}
.set-rc-receipt {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 3px 6px;
}
.set-rc-amount {
  font-weight: 590;
}
.set-rc-parts {
  color: var(--ui-hint);
}
:root {
  --template-color-bg: #0c0b0a;
  --template-color-sand-1: #141312;
  --template-color-sand-2: #1c1b19;
  --template-color-sand-3: #2a2825;
  --template-color-border: #2a2825;
  --template-color-border-strong: #3a3835;
  --template-color-text: #f2efe8;
  --template-color-text-muted: #c8c2b8;
  --template-color-icon: #9a9590;
  --template-color-accent: #5a5650;
  --template-color-accent-warm: #d4a853;
  --template-color-accent-olive: #c4842f;
  --template-color-overlay-55: rgba(0, 0, 0, 0.55);
  --template-color-overlay-45: rgba(0, 0, 0, 0.45);
  --template-color-overlay-35: rgba(0, 0, 0, 0.35);
  --template-color-overlay-25: rgba(0, 0, 0, 0.25);
  --template-color-surface-glass: rgba(28, 27, 25, 0.9);
  --template-color-surface-accent-soft: rgba(212, 168, 83, 0.08);
  --template-color-surface-accent: rgba(212, 168, 83, 0.15);
  --template-color-focus: rgba(212, 168, 83, 0.5);
  --template-shadow-strong: 0 12px 40px rgba(0, 0, 0, 0.6);
  --template-shadow-soft: 0 10px 24px rgba(0, 0, 0, 0.2);
  --bg-color: var(--template-color-bg);
  --text-color: var(--template-color-text);
  --text-secondary: var(--template-color-text-muted);
  --mid-gray: var(--template-color-icon);
  --light-gray: var(--template-color-border-strong);
  --separator-color: var(--template-color-border);
  --icon-color: var(--template-color-icon);
  --accent-blue: var(--template-color-accent);
  --accent-yellow: var(--template-color-accent-warm);
  --accent-green: var(--template-color-accent-olive);
  --sand-1: var(--template-color-sand-1);
  --sand-2: var(--template-color-sand-2);
  --sand-3: var(--template-color-sand-3);
  --dialog-bg: var(--template-color-bg);
  --dialog-panel: var(--template-color-sand-1);
  --bubble-out: var(--template-color-accent);
  --bubble-text: var(--template-color-text);
}
.loading-spinner {
  border-color: var(--template-color-border);
  border-top-color: var(--template-color-border-strong);
}
.media-placeholder.media-image {
  background: linear-gradient(
    135deg,
    var(--template-color-sand-1),
    var(--template-color-sand-3)
  );
}
button:focus-visible,
.dialog-item:focus-visible {
  outline: 2px solid var(--template-color-focus);
}

/* ── Profile tab (?section=profile) — reuses page/card/row/button objects ── */
.impito-tabbar__icon svg {
  /* Stroke-based icons (Lucide/Tabler) carry their presentation attributes
     inline — CSS only sizes them. */
  display: block;
  width: 26.4px;
  height: 26.4px;
  margin: 0 auto;
}
/* ПРЕМИУМ-ЭМОДЗИ ВМЕСТО SVG (08.09.2026, юзер прислал пять custom_emoji_id).
   Превью стикеров — белые монохромные силуэты на прозрачном (проверено по
   пикселям), поэтому в светлой теме их не видно как есть. Рисуем через
   mask-image с заливкой currentColor: цвет берётся у пункта таббара — тёмный/
   белый по теме, розовый у активного, как у прежних svg. Анимации (.json,
   3–5 КБ каждая) лежат рядом в emoji/ на будущее. */
.impito-tabbar__glyph {
  display: block;
  /* +30% к прежним 26.4px (08.09.2026, «сделай иконки больше на 30
     процентов»): 34.3px. Бокс .impito-tabbar__icon остаётся 26.4px высотой,
     маска выступает за него вверх/вниз симметрично через отрицательные поля,
     чтобы подпись не съехала. */
  width: 34.3px;
  height: 34.3px;
  margin: -3.95px auto;
  background: currentColor;
  -webkit-mask: var(--tab-glyph) center / contain no-repeat;
  mask: var(--tab-glyph) center / contain no-repeat;
}
/* Главная и история заменены (08.09.2026, вторая пара id от юзера):
   ✏️ 6026080811277621020 и 📁 6021375494216226506; прежние домик и песочные
   часы остаются в emoji/ на случай отката. */
.impito-tabbar__item[data-impito-tab="home"] {
  --tab-glyph: url("/settings/emoji/tab-home2-6026080811277621020.webp?v=impito-tab-emoji3-20260908");
}
.impito-tabbar__item[data-impito-tab="gens"] {
  --tab-glyph: url("/settings/emoji/tab-history2-6021375494216226506.webp?v=impito-tab-emoji3-20260908");
}
.impito-tabbar__item[data-impito-tab="styles"] {
  --tab-glyph: url("/settings/emoji/tab-styles-6025877040849229884.webp?v=impito-tab-emoji-20260908");
}
.impito-tabbar__item[data-impito-tab="shop"] {
  --tab-glyph: url("/settings/emoji/tab-shop-6030664675253820292.webp?v=impito-tab-emoji-20260908");
}
.impito-tabbar__item[data-impito-tab="profile"] {
  --tab-glyph: url("/settings/emoji/tab-profile-6024039683904772353.webp?v=impito-tab-emoji-20260908");
}
#impito-profile {
  min-height: 100vh;
  min-height: 100svh;
}
#impito-profile main[data-anim="fade"] {
  animation: impito-page-in 0.3s var(--ui-ease-out);
}
#impito-profile main[data-anim="push"] {
  animation: impito-push-in 0.34s var(--ui-ease-nav);
}
#impito-profile main[data-anim="pop"] {
  animation: impito-pop-in 0.3s var(--ui-ease-nav);
}
.impito-profile-page.ui-page {
  /* Clear the top veil (Telegram Back/⌄/⋯ live there) on fullscreen phones,
     fall back to a sane header offset elsewhere. */
  padding-top: calc(
    max(
        var(--ui-fullscreen-top) * 1.5 + var(--ui-veil-platform, 0px),
        56px + var(--ui-safe-top)
      ) + 12px
  );
  padding-bottom: calc(120px + var(--ui-safe-bottom));
}
.impito-profile-heading {
  position: fixed;
  top: calc(var(--ui-safe-top) + 11px);
  left: 72px;
  right: 72px;
  z-index: 60;
  overflow: hidden;
  color: var(--ui-text);
  /* Заголовок шапки: 19 → 15.2 → 16.4px (−20%, потом +8%), интерлиньяж следом. */
  font-size: 16.4px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 23px;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.impito-profile-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 4px 22px 24px;
  text-align: center;
}
.impito-profile-avatar {
  position: relative;
  display: flex;
  width: 96px;
  height: 96px;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border-radius: 50%;
  background: var(--ui-media-bg);
}
.impito-profile-avatar__img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
}
.impito-profile-avatar__initials {
  color: var(--ui-ink-soft);
  font-size: 38px;
  font-weight: 600;
  letter-spacing: 0.01em;
  user-select: none;
}
.impito-profile-avatar__person {
  display: flex;
  color: rgba(12, 18, 48, 0.35);
}
.impito-profile-avatar__person svg {
  width: 44px;
  height: 44px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.impito-profile-name {
  margin: 12px 0 0;
  color: var(--ui-text);
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
  overflow-wrap: anywhere;
}
.impito-profile-id {
  /* Раньше 1px — ID подпирал строку @юзернейма. Юзернейм убрали (2026-07-31),
     ID встал прямо под именем, поэтому отступ вернули к нормальному. */
  margin: 5px 0 0;
  padding: 3px 8px;
  border: 0;
  background: none;
  color: var(--ui-hint);
  cursor: pointer;
  font-family: var(--ui-font);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.35;
  font-variant-numeric: tabular-nums;
  -webkit-tap-highlight-color: transparent;
  transition: opacity var(--ui-dur) var(--ui-ease);
}
.impito-profile-id:active {
  opacity: 0.55;
}
/* Премиум-эмодзи Telegram вместо обычного символа: картинка, а не текст,
   поэтому у контейнера font-size ни на что не влияет — размер задаёт сам
   `img` ниже. Оба варианта уживаются: где эмодзи остался текстом, работает
   прежний font-size. */
.impito-glyph-emoji {
  display: block;
  width: 28px;
  height: 28px;
  object-fit: contain;
  /* Перетаскивание картинки пальцем по экрану выглядит как поломка строки. */
  pointer-events: none;
  -webkit-user-drag: none;
}
.impito-home-ref__icon .impito-glyph-emoji {
  width: 26px;
  height: 26px;
}
.impito-profile-glyph {
  display: flex;
  width: 30px;
  height: 30px;
  align-items: center;
  justify-content: center;
  font-size: 23px;
  line-height: 1;
  user-select: none;
}
.impito-profile-row .ui-row-after {
  color: var(--ui-ink-faint);
}
/* Строка с переключателем выше остальных: под заголовком идёт пояснение, и
   иконка обязана держаться по центру блока, а не прыгать к первой строке. */
.impito-profile-row--switch {
  align-items: center;
}
.impito-profile-row--switch .ui-row-body {
  padding-right: 6px;
}
/* Документ, прочитанный из профиля. Своей прокрутки у него нет — страница
   профиля скроллится целиком, поэтому это обычная карточка с текстом. */
.impito-legal-doc {
  padding: 16px;
}
.impito-legal-doc .impito-legal__h:first-of-type {
  margin-top: 0;
}
.impito-profile-chevron {
  width: 8px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.1;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.impito-profile-ext {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.impito-profile-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 58px 34px 40px;
  text-align: center;
}
.impito-profile-empty__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 56px;
  line-height: 1;
  user-select: none;
}
.impito-profile-empty__title {
  margin: 18px 0 0;
  color: var(--ui-text);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.impito-profile-empty__sub {
  margin: 7px 0 0;
  max-width: 300px;
  color: var(--ui-hint);
  font-size: 14.5px;
  line-height: 1.45;
}
.impito-profile-empty__cta {
  margin-top: 22px;
  height: 46px;
  padding: 0 26px;
  font-size: 16px;
}
.impito-profile-reflink .ui-row-title {
  overflow: hidden;
  font-size: 15.5px;
  font-variant-numeric: tabular-nums;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.impito-profile-copy {
  display: flex;
  width: 34px;
  height: 34px;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: var(--ui-accent-soft);
  color: var(--ui-accent-ink);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    background var(--ui-dur) var(--ui-ease),
    color var(--ui-dur) var(--ui-ease),
    transform var(--ui-dur) var(--ui-ease);
}
.impito-profile-copy:active {
  transform: scale(0.92);
}
.impito-profile-copy.is-done {
  background: rgba(52, 199, 89, 0.16);
  color: var(--ui-confirm);
}
.impito-profile-copy svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.impito-profile-ref-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 2px 12px 0;
}
/* Профиль: пополнение баланса (пакеты токенов) */
.impito-profile-page[data-page="topup"],
.impito-profile-page[data-page="shop"] {
  padding-bottom: calc(196px + var(--ui-safe-bottom));
}
/* Остальные подстраницы профиля: запас под таббар. Без него нижняя кнопка
   уезжает ПОД панель и становится ненажимаемой — на рефералке так пряталась
   «скопировать ссылку» (22.08.2026, скриншот юзера). Панель ~82px, плюс
   воздух. */
.impito-profile-page.impito-profile-subpage:not([data-page="topup"]):not([data-page="shop"]) {
  padding-bottom: calc(124px + var(--ui-safe-bottom));
}
/* Экран генерации фото (photo.js). Верх — как у профиля (вылет из-под вуали с
   нативными кнопками Telegram), низ — запас под фиксированную панель с ценой и
   кнопкой: она стоит на 82px + safe-bottom и сама высотой 67px. */
/* ВЕРХНИЙ ОТСТУП +18px НА ВСЕХ ГЕНЕРАЦИОННЫХ ЭКРАНАХ (16.08.2026).
   Было +12, и содержимое сидело вплотную к верхней панели — заметнее всего на
   реставрации и улучшении, где сразу под заголовком идёт плотный ряд плиток.
   Сперва добавку поставили только этим двум экранам и на 14px, юзер посмотрел
   на устройстве: «маловато, сделай 18 и везде». Отсюда 12 + 18 = 30.
   ПОЧЕМУ ЧИСЛО, А НЕ ИЗМЕРЕНИЕ ПАНЕЛИ: высота верхней панели зависит от того,
   развёрнута она или схлопнута, а формула ниже её реальную высоту не меряет.
   Правильно было бы мерить и класть в переменную — но это правка всех экранов
   разом. Пока крутится одно число, и оно здесь. */
.impito-photo-page.ui-page {
  padding-top: calc(
    max(
        var(--ui-fullscreen-top) * 1.5 + var(--ui-veil-platform, 0px),
        56px + var(--ui-safe-top)
      ) + 30px
  );
  padding-bottom: calc(184px + var(--ui-safe-bottom));
}
/* Своего правила у чипсов этого экрана нет намеренно: базовый `.ui-chips` уже
   переносит их на вторую строку (моделей шесть, в одну строку не влезают) и
   держит отступы дизайн-системы. Класс `.impito-photo-chips` оставлен как
   зацепка на будущее. */

/* ── Формат кадра карточками (2026-07-31) ──
   Вместо чипсов «1:1 / 9:16 / …» — карточки в духе каталога, и внутри каждой
   настоящий кадр этой пропорции: белое поле с пунктирным контуром. Пропорцию
   задаёт inline-стиль от значения (`aspect-ratio: 9/16` и т.д.), а какая
   сторона упирается в карточку — считает js: горизонтальные и квадратные по
   ширине, вертикальные по высоте. */
/* Форматов стало 11 (2026-07-31) — сеткой они занимали три ряда, поэтому это
   лента с горизонтальным листанием, как подборки на главной: те же зазор,
   хвост следующей карточки и привязка. Ширина карточки своя: у неё фиксированная
   пропорция 3:4, и три штуки на экран здесь были бы неоправданно крупными. */
/* ── Формат внутри листа (14.08.2026) ──────────────────────────────────────
   Раньше лента форматов была отдельной секцией на странице и брала боковые
   поля от неё. В листе поля свои, а заголовок секции пропал вместе с секцией —
   поэтому он вернулся сюда, внутрь группы, иначе лист открывался без единой
   подписи и было непонятно, что вообще выбирают.
   Рейл внутри листа НЕ должен добавлять свои 12px по бокам: у группы уже есть
   собственные поля, и вместе они давали двойной отступ. */
.impito-ratio-sheet {
  padding: 14px 0 16px;
}
/* ВСЕ ФОРМАТЫ СРАЗУ, А НЕ ОДНА ПРОКРУЧИВАЕМАЯ СТРОКА (14.08.2026, просьба
   юзера). В листе горизонтальный рейл был вдвойне неудачен: лист и так
   выезжает снизу, и внутри него ещё одна прокрутка — человек видел четыре
   карточки из одиннадцати и не понимал, что есть остальные.
   Четыре колонки, а не три: при 375px это 74px на карточку, и все одиннадцать
   укладываются в три ряда без прокрутки. Три колонки дали бы четыре ряда, и
   лист занял бы пол-экрана. */
.impito-ratio-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  padding: 0 18px;
}
.impito-ratio-grid .impito-ratio {
  width: auto;
}
/* Три формата у расширения — три колонки, а не четыре с пустой ячейкой
   (03.09.2026, просьба юзера). */
.impito-ratio-grid--three {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.impito-ratio-rail {
  --ui-rail-gap: 8px;
  --ui-rail-peek: 18px;
  display: flex;
  gap: var(--ui-rail-gap);
  overflow-x: auto;
  padding: 0 12px;
  scrollbar-width: none;
  scroll-padding-right: 12px;
  scroll-padding-left: calc(var(--ui-rail-gap) + var(--ui-rail-peek));
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.impito-ratio-rail::-webkit-scrollbar {
  display: none;
}
.impito-ratio-rail .impito-ratio {
  width: 82px;
  flex: 0 0 auto;
  scroll-snap-align: start;
}
.impito-ratio {
  display: flex;
  aspect-ratio: 3 / 4;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 10px 6px;
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.08);
  color: var(--ui-text);
  cursor: pointer;
  font: inherit;
  -webkit-tap-highlight-color: transparent;
  transition:
    transform 0.15s var(--ui-ease),
    background-color 0.2s var(--ui-ease),
    color 0.2s var(--ui-ease);
}
.impito-ratio:active {
  transform: scale(0.96);
}
.impito-ratio__frame {
  display: block;
  max-width: 74%;
  /* Ограничения с обеих сторон: у 16:9 ширина упирается первой, у 9:16 —
     высота, и без пары max-* кадр вылезал бы за карточку. */
  max-height: 64%;
  border: 1.5px dashed rgba(12, 18, 48, 0.38);
  border-radius: 5px;
  background: #fff;
}
.impito-ratio__label {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  line-height: 1;
}
.impito-ratio.is-active {
  background: var(--ui-accent);
  color: var(--ui-accent-text);
}
.impito-ratio.is-active .impito-ratio__frame {
  border-color: rgba(255, 255, 255, 0.9);
  background: rgba(255, 255, 255, 0.96);
}

/* «авто» в ленте форматов: пропорции у него нет, поэтому в кадре звёздочка —
   «какой получится». */
.impito-ratio__frame--auto {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ui-accent-ink);
}
/* Звезда «авто». Размер 78% → 62% (−20%, 2026-07-31). Форма мягкая: лучи —
   вогнутые кубические кривые, а кончики скруглены обводкой того же цвета с
   round-соединениями — прежняя угловатая звезда юзеру не понравилась.
   Обводка здесь не контур, а инструмент скругления: цвет у неё тот же, что и
   заливка, поэтому фигура остаётся сплошной. */
.impito-ratio__frame--auto svg {
  width: 62%;
  height: 62%;
  fill: currentColor;
}
.impito-ratio.is-active .impito-ratio__frame--auto {
  color: var(--ui-accent-strong);
}

/* ── Качество ползунком (2026-07-31) ──
   Вместо трёх кнопок — шкала «меньше → больше». Дорожка, заливка и бегунок —
   СВОИ элементы, а нативный `input[type=range]` лежит поверх прозрачным: он
   по-прежнему ловит касания, тянется и работает с клавиатуры, но рисовать его
   псевдоэлементами нельзя — ни трансформировать бегунок, ни повесить на него
   слои стекла. Поэтому вид целиком на своих узлах, поведение — на нативном.
   Подложки-карточки под ползунком нет: он лежит прямо на фоне экрана. */
.impito-quality {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 22px;
}
.impito-quality__cap {
  flex: 0 0 auto;
  color: var(--ui-hint);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
}
/* Высота с запасом снизу: там ряд делений, он ПОД дорожкой, а не на ней. */
.impito-quality__slider {
  position: relative;
  display: block;
  min-width: 0;
  height: 34px;
  flex: 1 1 auto;
}
/* WEBGL-СТЕКЛО КАПСУЛЫ (только apple, 04.09.2026): канвас во весь слайдер,
   над дорожкой и под DOM-капсулой; вне капсулы прозрачный. Рисует
   quality_slider.js, пока капсула в стекле. На остальных платформах —
   display: none, там работает SVG-преломление через backdrop-filter. */
.impito-quality__gl {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: none;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
html[data-font-platform="apple"] .impito-quality__gl {
  display: block;
}
/* Капсула над канвасом; пока стекло рисует канвас, её собственная подложка
   прозрачная (в `.is-holding` она и так transparent, `.is-glass` держит это
   и на спаде надувания после отпускания). */
.impito-quality__thumb {
  z-index: 2;
}
.impito-quality__thumb.is-glass {
  --thumb-fill: transparent;
}
.impito-quality__thumb::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--thumb-fill);
  clip-path: var(--sq, none);
  transition: background-color 0.16s var(--ui-ease);
}
/* Дорожка тоньше на 20% (8 → 6.4px, 2026-08-05, просьба юзера «сделай палку
   тоньше примерно на 20 процентов»). `top` пересчитан так, чтобы ВЕРТИКАЛЬНЫЙ
   ЦЕНТР остался на 14px — на нём же стоит центр бегунка, и от него отмерены
   деления. Менять высоту, не трогая top, значит увести дорожку вверх.

   ПЕРЕХОДОВ ЗДЕСЬ НЕТ НАМЕРЕННО. `top`, `height`, `left` и `right` дорожки
   пишет покадрово js — это резинка на упорах (см. `QUALITY_OVER_*` в
   generate.js/restore.js). Любой transition на этих свойствах дрался бы с
   покадровой анимацией ровно так же, как дрался бы transform у бегунка.
   Числа 10.8/6.4 продублированы в js константами `QUALITY_TRACK_H` и
   `QUALITY_AXIS_Y` — меняешь тут, меняй и там. */
.impito-quality__track {
  position: absolute;
  top: 10.8px;
  right: 0;
  left: 0;
  overflow: hidden;
  height: 6.4px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-fill-2);
}
.impito-quality__fill {
  display: block;
  height: 100%;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-accent);
}
/* Деления — ПОД дорожкой, отдельным рядом, как в системном слайдере. Боковые
   поля равны половине ширины бегунка (18.47px при ширине 36.94), иначе крайние
   точки не совпадают с его центром в крайних положениях. Меняешь ширину
   бегунка — обязательно меняй и это число, и `QUALITY_THUMB_W` в generate.js и
   restore.js: три места, одна величина. */
.impito-quality__ticks {
  position: absolute;
  top: 30px;
  /* 18.47 → 19.39 → 18.43: бегунок +5%, затем −5% со всех сторон
     (04.09.2026); поля — половина его ширины. */
  right: 18.43px;
  left: 18.43px;
  display: flex;
  justify-content: space-between;
  pointer-events: none;
}
.impito-quality__ticks i {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: rgba(12, 18, 48, 0.2);
}
/* Прозрачность КАЖДОЙ точки пишет js покадрово: гаснет ровно та, которую
   накрыла раздутая капсула, остальные остаются на месте (2026-08-05). Поэтому
   никакого transition здесь быть не должно — он дрался бы с покадровой
   записью, как и везде у этого ползунка. */
/* Бегунок — капсула той же формы, что кнопка переключателя (радиус пилюли, та
   же тень). Размер: 43x27 → 34x27 («менее длинным») → −20% = 27x22 → 40.5x23.1
   (2026-08-05: «по высоте на 5% выше, в полтора раза длиннее» — по системному
   слайдеру iOS со скриншота юзера) → 32.4x22.64 (в тот же день: «ебать он
   длинный», −20% по длине и −2% по высоте) → 38.88x27.17 (тогда же, крупный
   скриншот рядом с эпловским: «форму повторил идеально, но он маленький,
   процентов на 20 больше» — обе стороны ×1.2) → 36.94x25.81 (финальная подгонка
   того же дня: −5% по обеим сторонам).
   `top` пересчитан от прежнего центра 14px: 14 − 25.81/2 = 1.1. Так меняющийся
   бегунок растёт и убывает вверх-вниз симметрично, а дорожка и деления остаются
   на своих местах. Запас сверху невелик: замер — бегунок занимает 1.1…26.91
   при контейнере 34px и делениях на 30px. Ещё прибавка по высоте — и придётся
   растить `.impito-quality__slider`, иначе бегунок полезет на деления.
   Позицию и «желе» (растяжение по скорости, надувание при удержании) считает
   js и кладёт в transform, поэтому здесь никаких переходов на transform —
   иначе они дрались бы с покадровой анимацией. */
.impito-quality__thumb {
  position: absolute;
  /* 36.94×25.81 → 38.79×25.81 («длиннее на 5%») → 36.85×24.52 («уменьши на
     5% со всех сторон»), 04.09.2026. top держит центр на 14px. */
  top: 1.75px;
  left: 0;
  width: 36.85px;
  height: 24.52px;
  border-radius: var(--ui-radius-pill);
  /* ЗАЛИВКА ЖИВЁТ НА ::before (08.09.2026, сквиркл): форму режет clip-path, а
     он отрезал бы внешнюю тень; поэтому тень остаётся на самом бегунке, а
     заливка со сквирклом — на псевдослое. Цвет — через --thumb-fill. */
  --thumb-fill: var(--ui-switch-thumb);
  background: transparent;
  /* В покое — ТОЛЬКО внешняя тень, больше ничего. Волосяная обводка
     `inset 0 0 0 0.5px` убрана 2026-08-05: на крупном скриншоте рядом с
     эпловским бегунком юзер увидел её как лишний контур («убери мини-обводку,
     оставь онли тень»), и он прав — у системного слайдера капсула держится на
     одной тени. В состоянии `is-holding` обводка ОСТАЁТСЯ и трогать её там
     нельзя: подложка на удержании прозрачная, и без контура стеклянная пилюля
     просто исчезнет. Тень ВНУТРИ СВЕРХУ здесь тоже НЕ нужна: она часть стекла
     и появляется только на удержании (2026-07-31, просьба юзера — в покое она
     читалась как грязь на белой капсуле).

     Тень переделана 2026-08-05 «как у эпла»: не одна жёсткая полоска под
     кромкой, а два слоя — плотный контактный и широкий мягкий. Радиус размытия
     3 → 9px выбран по площади: юзер просил, чтобы тень занимала места втрое
     больше, а ореол вокруг капсулы растёт как (w+b)(h+b) − w·h, и при 40.5×23.1
     утроение даёт ровно b ≈ 8.4 ≈ 9. Цвет НЕ трогали — тот же чёрный, что был
     в `#0003`.

     Затем в тот же день: «эффект слабее в 2 раза, площадь оставь». Поэтому
     РАЗМЫТИЕ И СМЕЩЕНИЯ НЕ ТРОГАЛИ ВООБЩЕ (они и есть площадь), пополам делится
     только альфа: 0.22 → 0.11 и 0.1 → 0.05. Это единственная ручка силы тени:
     уменьшишь размытие — уедет площадь, за которую юзер держится отдельно.

     И финально: «тень ВОКРУГ ВСЕГО ползунка, площадь +20%». Смещение по Y
     обнулено — при `y = 3` и размытии 9 сверху оставалось 1.5px ореола, а снизу
     7.5px, и тень читалась как «под капсулой», а не «вокруг». Теперь ореол
     одинаков со всех сторон. Размытие 9 → 11px посчитано по той же формуле
     `(w+b)(h+b) − w·h`: при 36.94×25.81 это даёт +20% к прежнему ореолу.
     Альфы не трогали — просьба была про площадь, а не про силу.
     А вот следом («для афк ползунка сделай тень сильнее на 20 процентов»)
     трогали РОВНО альфы и ничего больше: 0.05 → 0.06 и 0.11 → 0.132. Площадь
     при этом обязана остаться прежней — она подбиралась отдельным требованием
     двумя правками раньше. */
  box-shadow:
    0 0 2.4px rgba(0, 0, 0, 0.06),
    0 0 11px rgba(0, 0, 0, 0.132);
  pointer-events: none;
  transform-origin: 50% 50%;
  transition:
    box-shadow 0.16s var(--ui-ease),
    background-color 0.16s var(--ui-ease);
  will-change: transform;
}
/* Стекло при удержании: чистая кромка системного слайдера — обводка, тень
   вдоль всей кромки и тень под верхней. РАЗМЫТИЯ НЕТ намеренно — юзер попросил
   без него, и backdrop-filter здесь не заводится вовсе: это самая дорогая часть
   эффекта, а бегунок ездит покадрово.

   ХРОМАТИЧЕСКОЙ АБЕРРАЦИИ БОЛЬШЕ НЕТ (2026-08-05). Четыре цветных слоя
   (`rgb(0, 51, 255)` слева, `rgba(0,168,255)` справа и пара сверху/снизу) были
   перенесены сюда с ползунка таббара, но на скриншоте рядом с эпловским
   слайдером юзер увидел их как толстый розово-голубой кант и забраковал:
   «смотри какую хуйню сделал ты, спизди 1 в 1 (кроме цвета)». У системного
   слайдера кант нейтральный. Слои удалены, остались только три тени в нашем
   тоне `rgb(16, 21, 43)` — «кроме цвета» относится именно к этому: рецепт
   эпловский, оттенок наш, серый оттуда не тащим. */
.impito-quality__thumb.is-holding {
  /* Подложка ПРОЗРАЧНАЯ. Пробовали дважды и оба раза откатили: ровную молочную
     `rgba(240, 242, 252, 0.44)` (31.07, «нужен чистый прозрачный кадр») и
     вертикальный градиент `rgba(255,255,255,.14 → .5)` (05.08, «ты че нахуй
     сделал? убери эту хуйню»). Не возвращать ни в каком виде — тело капсуле
     даёт тень под ней, а не заливка внутри.
     Размытия тоже нет намеренно — `backdrop-filter` не объявлен вовсе: это
     самая дорогая часть эффекта, а бегунок ездит покадрово. */
  --thumb-fill: transparent;
  /* ТЕНЬ ВНУТРИ — ПОЛУМЕСЯЦ ПОД ВЕРХНЕЙ КРОМКОЙ, А НЕ ЗАЛИВКА СИЛУЭТА.
     Этот слой переделывали трижды, и все три промаха стоит помнить:
     1. `inset 0 0 6px` без смещения — кольцо по ВСЕМУ периметру. Забраковано:
        «есть ебанная тень ползунка вокруг обводки внутри».
     2. Слоя нет вовсе — капсула превращается в голую дырку с контуром.
     3. `::before` с залитым силуэтом, сдвинутым вниз (попытка показать тень на
        дорожке сквозь стекло). Забраковано: «ты взял весь ползунок нахуярил,
        оно как пончик должно быть».
     Правильное — направленный inset со СМЕЩЕНИЕМ ВНИЗ и отрицательным spread:
     он рисует дугу вдоль верхней кромки и сходит на нет к середине. Именно так
     выглядит стекло на референсе, и именно это юзер называет «пончиком»:
     затемнение идёт по кромке, а середина остаётся чистой.
     Ключ — spread: без него (`inset 0 3px 6px`) тень расползается по всей
     капсуле и получается ровно тот самый залитый силуэт.

     КАК ЕГО КРУТИТЬ (2026-08-05, «более выраженным: площадь +10%, сила +10%»).
     Глубина полумесяца считается как `смещение + размытие/2 + spread`, где
     spread отрицательный и потому вычитается: было `3 + 6/2 − 2 = 4px`, стало
     `3 + 6.8/2 − 2 = 4.4px`, ровно +10%. То есть ПЛОЩАДЬ крутится размытием,
     а СИЛА — альфой (0.3 → 0.33). Смещение и spread не трогать: смещение
     задаёт, что дуга именно сверху, а spread — что она не расползается.

     ОБВОДКА ЗДЕСЬ 0.34px, А НЕ 0.5px КАК В ПОКОЕ, И ЭТО НЕ ОПЕЧАТКА. В захвате
     js раздувает бегунок до `scale(1.462)`, и вместе с ним масштабируется
     толщина линии: объявленные 0.5px рисуются как 0.73px — отсюда и жалоба
     «обводка жирнючая сука», хотя число то же, что в покое. 0.5 / 1.462 = 0.34
     возвращает ей на экране ровно ту же толщину, что у спокойного бегунка.
     Меняешь `QUALITY_GRAB` — пересчитывай и это число.
     Сила обводки — только альфа: 0.26 → 0.24 (2026-08-06, «совсем чуть чуть
     светлее»). Толщину 0.34px при этом не трогать — она привязана к
     `QUALITY_GRAB`, а не к тому, насколько контур тёмный.
     Тень под капсулой ослаблялась на 20% ДВАЖДЫ подряд: альфы 0.26 → 0.21 →
     0.168 и 0.12 → 0.096 → 0.077, затем ещё на 15% (2026-08-06): 0.168 → 0.143
     и 0.077 → 0.065. Геометрия ни разу не тронута — за форму «силуэта»
     отвечает соотношение смещения и размытия, а не сила. */
  /* 04.09.2026 (просьба юзера, по скрину рядом с iOS): обводка вдвое тоньше
     (0.34 → 0.17px), но темнее (0.24 → 0.62); плюс два белых блика ВНУТРИ у
     верхней и нижней стенки (`inset 0 ±1px`), как на эпловской капсуле.
     Полумесяц под верхней кромкой и внешние тени не тронуты. */
  box-shadow:
    0 5px 5px rgba(12, 18, 48, 0.143),
    0 9px 14px rgba(12, 18, 48, 0.065),
    inset 0 0 0 0.17px rgba(12, 18, 48, 0.62),
    /* верхний блик −10% (0.8 → 0.72), нижний как был (04.09.2026) */
    inset 0 1px 0 -0.1px rgba(255, 255, 255, 0.72),
    inset 0 -1px 0 -0.1px rgba(255, 255, 255, 0.7),
    /* полумесяц: площадь +7% (размытие 6.8 → 7.4, по формуле 3 + b/2 − 2),
       сила −7% (0.33 → 0.307) — 04.09.2026 */
    inset 0 3px 7.4px -2px rgba(12, 18, 48, 0.307);
}
/* СТЕКЛО С ИСКАЖЕНИЕМ — ТОЛЬКО ANDROID/WINDOWS (2026-08-05, просьба юзера).
   Настоящее преломление фона под капсулой, `backdrop-filter: url()` со своим
   SVG-фильтром (собирается в index.html, `#impito-lg-quality`).

   ГДЕ РАБОТАЕТ. Класс `impito-lg-refract` ставит скрипт линзы, а он сам
   запускается только при `Chrome/` в UA — то есть на iOS/WKWebView его нет в
   принципе (WebKit ссылку на SVG-фильтр в backdrop-filter не рисует, см.
   комментарий у таббара). `:not([data-font-platform="apple"])` добивает случай
   Chrome на маке. Итого остаются ровно Android и Windows.

   ТОЛЬКО НА УДЕРЖАНИИ. В покое фильтра нет вовсе — не «нулевой scale», а
   именно нет: цепочка (блюр + saturate + displacement + композиты) считается
   каждый кадр, пока капсула едет, и в покое это чистая трата. Та же грабля уже
   ловилась на ползунке таббара.

   АБЕРРАЦИИ НЕТ — фильтр собран с `aberrationChannels(0)`, один канал.
   ТЕНЬ ВЫШЕ ИСКАЖЕНИЯ и доделывать для этого ничего не пришлось:
   backdrop-filter обрезается по border-box капсулы, а тени рисуются поверх
   результата как часть элемента; внешняя тень вообще лежит за рамкой. */
html.impito-lg-refract:not([data-font-platform="apple"])
  .impito-quality__thumb.is-holding {
  -webkit-backdrop-filter: url(#impito-lg-quality);
  backdrop-filter: url(#impito-lg-quality);
}
/* ТЁМНАЯ ТЕМА, УДЕРЖАНИЕ: тот же прозрачный кадр с контуром и тенями, что и в
   светлой, только заливка белая на 12% (просьба юзера 08.09.2026: «просто
   прозрачность понизь до 88»). Геометрию и раздувание не трогаем. */
[data-theme="dark"] .impito-quality__thumb.is-holding {
  /* 0.12 → 0.07 («прозрачность 93», 08.09.2026). */
  --thumb-fill: rgba(255, 255, 255, 0.07);
  /* Контур в тёмной теме мягче: вместо тёмного кольца и белых бликов 0.7 —
     белое кольцо 30% и блики 22%, тени чёрные. Светлая тема не тронута. */
  box-shadow:
    0 5px 5px rgba(0, 0, 0, 0.2),
    0 9px 14px rgba(0, 0, 0, 0.1),
    inset 0 0 0 0.17px rgba(255, 255, 255, 0.3),
    inset 0 1px 0 -0.1px rgba(255, 255, 255, 0.22),
    inset 0 -1px 0 -0.1px rgba(255, 255, 255, 0.2),
    inset 0 3px 7.4px -2px rgba(0, 0, 0, 0.3);
}
/* Нативный input: прозрачный, но живой — он и есть область касания. */
.impito-quality__range {
  position: absolute;
  z-index: 2;
  top: 0;
  right: 0;
  left: 0;
  width: 100%;
  height: 28px;
  margin: 0;
  padding: 0;
  border: 0;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  cursor: pointer;
}
.impito-quality__range::-webkit-slider-runnable-track {
  height: 8px;
  background: transparent;
}
.impito-quality__range::-moz-range-track {
  height: 8px;
  background: transparent;
}
.impito-quality__range::-webkit-slider-thumb {
  width: 27px;
  height: 22px;
  margin-top: -7px;
  border: 0;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  opacity: 0;
}
.impito-quality__range::-moz-range-thumb {
  width: 27px;
  height: 22px;
  border: 0;
  background: transparent;
  opacity: 0;
}

/* Строка выбора модели — копия строки настроек бандла: эмодзи слева, название с
   подписью, значение и шеврон справа (2026-07-31, просьба юзера со скриншотом
   «модель фото · Nano 2 ›»). Сама `.ui-row` уже есть, здесь только эмодзи,
   значение и шеврон. */
/* Вместо цветного эмодзи — монохромный знак в акценте: эмодзи выбивался из
   набора (системный глиф не перекрашивается и всегда ярче остального ряда),
   2026-07-31. */
.impito-photo-row__icon {
  display: inline-flex;
  width: 26px;
  height: 26px;
  align-items: center;
  justify-content: center;
  color: var(--ui-accent-ink);
}
.impito-photo-row__icon svg {
  width: 100%;
  height: 100%;
}
/* Тумблер этого экрана был первым розовым — с 2026-08-01 розовые все, цвет
   задан общей переменной --ui-switch-on, и точечное правило здесь больше не
   нужно. */
.impito-photo-row__value {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--ui-hint);
  font-size: 17px;
}
/* Строка без шеврона: параметр зафиксирован моделью и не нажимается. Отступ
   справа тот же, что съедал бы шеврон, — иначе значения в карточке не
   выстраиваются в одну колонку. */
.impito-photo-row__value--static {
  padding-right: 8px;
}

/* ПЛИТКИ ПАРАМЕТРОВ: «модель фото» и «соотношение сторон» стоят в один ряд как
   две карточки (07.09.2026, просьба юзера со своим макетом). Слева большой
   логотип модели или рамка кадра, справа сверху выбранное значение жирным,
   ниже подпись, у правого края шеврон из прежних строк. Остальные параметры
   остаются строками в обычной .ui-card под сеткой.
   Сетка — auto-fit: одна плитка (видео без выбора формата) растягивается на
   всю ширину, две делят ряд поровну. Отступ 12px совпадает с полями .ui-card. */
.impito-params__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  gap: 10px;
  margin: 0 12px;
}
.impito-params__grid + .ui-card {
  margin-top: 10px;
}
.impito-param {
  position: relative;
  display: flex;
  min-width: 0;
  min-height: 62px;
  align-items: center;
  gap: 8px;
  /* Поля ужаты до 11/9px, а не 18px как у строки: в плитке шириной ~178px
     иначе не помещаются «GPT-image 2» и шеврон в одну строку. */
  padding: 13px 9px 13px 11px;
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
  box-shadow: var(--ui-surface-highlight);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    transform 0.12s var(--ui-ease),
    background-color 0.12s var(--ui-ease);
}
.impito-param:active {
  background: var(--ui-card-raised);
  transform: scale(0.97);
}
.impito-param__logo {
  display: inline-flex;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  align-items: center;
  justify-content: center;
  color: var(--ui-accent-ink);
}
.impito-param__logo img {
  display: block;
  width: 32px;
  height: 32px;
}
.impito-param__logo svg {
  width: 30px;
  height: 30px;
}
.impito-param__body {
  display: flex;
  min-width: 0;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 3px;
}
.impito-param__value {
  overflow: hidden;
  color: var(--ui-text);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* Длинное название модели («Nano Banana 2») в половинной плитке: на 375px
   ему не хватало 10px и оно резалось многоточием (03.10.2026). */
.impito-param__value--long {
  font-size: 13.5px;
  letter-spacing: -0.03em;
}
/* Подпись переносится: «соотношение сторон» в одну строку не влезает даже
   мелким кеглем, а обрезать её многоточием хуже, чем дать вторую строку. */
.impito-param__title {
  color: var(--ui-hint);
  font-size: 11.5px;
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.impito-param__chevron {
  flex: 0 0 auto;
  width: 7px;
  height: 12px;
  margin-left: auto;
  color: var(--ui-hint);
  opacity: 0.55;
}

/* ЧИП «ИИ УЛУЧШЕНИЕ» — В ШАПКЕ СЕКЦИИ «ПРОМПТ», справа (07.09.2026, вариант 5
   из макета, выбор юзера; до этого был строкой под полем). Наследует поля и
   нижний отступ .ui-section-header, чтобы стоять вровень с заголовком слева;
   молния акцентом, подпись цветом подсказки, мини-тумблер. */
.impito-prompt-boost.ui-section-header {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--ui-hint);
  font-weight: 400;
}
/* Перебор лимита под полем, у правого края («−94», красным через is-over);
   обычного счётчика нет с 07.09.2026 (просьба юзера). Отступ сверху 6px, нижнее
   поле заголовка снято, иначе промпт отъезжал бы от плиток на лишние 9px. */
.impito-prompt-foot {
  display: flex;
  justify-content: flex-end;
  margin-top: 6px;
}
.impito-prompt-foot .ui-section-header {
  margin-bottom: 0;
}
/* Строка есть только при переборе лимита («−94»); свой display: flex иначе
   перебил бы браузерное [hidden]. */
.impito-prompt-foot[hidden] {
  display: none;
}
.impito-prompt-boost__bolt {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  color: var(--ui-accent-ink);
}
.impito-prompt-boost__label {
  white-space: nowrap;
}
/* Плитка видео-референса: та же рамка, что у фото, плюс подпись с длиной
   ролика — по ней сразу видно, уложился он в лимит или нет. */
/* Размеры задаёт сама плитка, а не ролик: у `<video>` без метаданных
   внутренний размер нулевой, и плитка схлопывалась вместе с крестиком. Здесь
   те же 1:1 и то же скругление, что у фото-превью. */
.impito-video-ref video {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 18px;
  background: rgba(12, 18, 48, 0.06);
  object-fit: cover;
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.08);
}
.impito-video-ref__badge {
  position: absolute;
  bottom: 6px;
  left: 6px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(8, 10, 20, 0.55);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.01em;
  pointer-events: none;
}
/* Модель без референсов: вместо пустой сетки — объяснение. */
.impito-style-photos-note {
  margin: 0;
  /* Тот же отступ 22px, что у заголовка секции: иначе текст висит у самого
     края экрана, а подпись над ним — с отбивкой. */
  padding: 0 22px;
  color: var(--ui-hint);
  font-size: 15px;
  line-height: 1.35;
}
/* ВЫЕЗД ЛИСТА ПРОМОКОДА — КАК СИСТЕМНЫЙ ЛИСТ iOS (16.08.2026, просьба юзера).
   Общий лист приложения только чуть приподнимается (translateY 24px) и
   проявляется — этого хватало меню выбора, но для полноэкранной панели читается
   как «моргнуло», а не «выехало снизу».
   Здесь панель едет ОТ САМОГО НИЗА (100% собственной высоты) на кривой
   cubic-bezier(0.32, 0.72, 0, 1) — это общепринятое приближение эппловской
   пружины для листов: быстрый старт, длинное мягкое торможение, без отскока.
   Прозрачность НЕ анимируем вместе с движением: на системных листах панель
   непрозрачна с первого кадра, а затухание добавляет ощущение «всплытия»,
   которого у Apple нет. Гасим только затемнение фона.
   Скрытие после закрытия ждёт 420мс — ровно длительность перехода; со старыми
   220мс панель исчезала бы, не доехав.
   ОСТАЛЬНЫЕ ЛИСТЫ (модель, формат, источник фото) НЕ ТРОГАЛИ: их юзер уже
   принял, и менять им ощущение заодно — не то, о чём просили. */
/* ВРЕМЯ ВЫЕЗДА — ОДНО НА ВСЕ ТРИ ЛИСТА (промокод, модель, формат).
   Раньше у модели и формата стояли свои 0.42с «чтобы побыстрее», но юзер
   сравнил вживую и выбрал плавность (17.08.2026). Держим их одним селектором,
   а не тремя одинаковыми блоками: копии разъедутся при первой же правке. */
.impito-promo-sheet .impito-sheet__panel,
.impito-about-sheet .impito-sheet__panel,
.impito-save-sheet .impito-sheet__panel,
.impito-model-sheet .impito-sheet__panel,
.impito-format-sheet .impito-sheet__panel {
  opacity: 1;
  /* СДВИГ БОЛЬШЕ 100%, И ЭТО НЕ ЗАПАС «НА ГЛАЗОК». У листа снизу отступ
     10px + безопасная зона, панель стоит НАД ним. Сдвинешь ровно на 100%
     собственной высоты — её верх встанет туда, где был низ, и полоса высотой
     с этот отступ ОСТАНЕТСЯ НА ЭКРАНЕ. Потом её сносит `hidden`, и это видно
     как «кусочек панели моргнул» (16.08.2026, жалоба юзера на концовку
     закрытия). Прибавляем сам отступ и ещё 4px на скругление. */
  transform: translateY(calc(100% + 14px + var(--ui-safe-bottom)));
  /* 0.42с и кривая с крутым стартом (0.32, 0.72) читались как «выстрел»
     (16.08.2026, «слишком резко вылетает»). Стало 0.6с, и старт заметно
     положе: наклон в начале 2.0 вместо 2.25, а конец такой же мягкий.
     Быстрее не делать — именно длинное торможение и создаёт ощущение веса. */
  transition: transform 0.6s cubic-bezier(0.3, 0.6, 0.1, 1);
}
.impito-promo-sheet.is-open .impito-sheet__panel,
.impito-about-sheet.is-open .impito-sheet__panel,
.impito-save-sheet.is-open .impito-sheet__panel,
.impito-model-sheet.is-open .impito-sheet__panel,
.impito-format-sheet.is-open .impito-sheet__panel {
  transform: translateY(0);
}
/* Затемнение тянется почти столько же, сколько едет панель. По умолчанию у
   листов оно 0.2с — фон темнел рывком и был уже чёрным, когда панель ещё в
   пути, отчего движение и казалось резче, чем есть. */
.impito-promo-sheet .impito-sheet__backdrop,
.impito-about-sheet .impito-sheet__backdrop,
.impito-save-sheet .impito-sheet__backdrop,
.impito-model-sheet .impito-sheet__backdrop,
.impito-format-sheet .impito-sheet__backdrop {
  /* Плотнее общих 0.28: панель тут светлая и во весь экран, при слабом
     затемнении граница с фоном терялась (17.08.2026). */
  background: rgba(12, 18, 48, 0.34);
  /* КОРОЧЕ ВЫЕЗДА НАРОЧНО, И ЭТО НЕ НЕБРЕЖНОСТЬ. Стекло панели размывает то,
     что за ней, — то есть само затемнение. Пока затемнение меняется, источник
     размытия меняется тоже, и движку приходится пересчитывать его каждый кадр.
     Дав затемнению закончиться раньше, мы оставляем последнюю треть выезда с
     уже неподвижной картинкой под панелью: пересчитывать нечего, и «обрывчик»
     в конце ловить неоткуда. */
  transition: opacity 0.4s var(--ui-ease);
}
@media (prefers-reduced-motion: reduce) {
  .impito-promo-sheet .impito-sheet__panel,
  .impito-about-sheet .impito-sheet__panel,
  .impito-save-sheet .impito-sheet__panel,
  .impito-model-sheet .impito-sheet__panel,
  .impito-format-sheet .impito-sheet__panel {
    transition: none;
  }
}

/* ── Ввод промокода: строка + лист (16.08.2026, референс от юзера) ─────────
   Было: поле ввода прямо в секции и под ним широкая кнопка «использовать» —
   два постоянных элемента ради действия, которым пользуются раз в жизни.
   Стало как на референсе: одна строка «ввести промокод», по тапу — лист.
   Цвет НЕ синий, как в референсе, а наш акцентный: это тот же розовый, что у
   кнопок, и другого фирменного тут быть не может. */
.impito-promo-row {
  width: 100%;
}
.impito-promo-row__label {
  color: var(--ui-accent-strong);
  font-weight: 600;
}
/* Шеврон у этой строки нейтральный, как у остальных рядов настроек: красить
   его в акцент вслед за текстом — перебор, строка начинает кричать. */
.impito-promo-row .impito-photo-row__chevron {
  color: var(--ui-hint);
}
.impito-promo-panel {
  /* Нижнее поле 16 → 14: часть тех самых «минус 5% высоты» (17.08.2026).
     Высота набрана из четырёх мест, поджимать одно на 15px нельзя — либо
     эмодзи станет мелким, либо кнопка прилипнет к краю. */
  padding: 18px 18px 14px;
  /* СВОЙ СЛОЙ НА ВСЁ ВРЕМЯ ЖИЗНИ. Без этого браузер создаёт слой на старте
     перехода и выбрасывает в конце — на этой границе кадр и «щёлкает». */
  will-change: transform, backdrop-filter;
  backface-visibility: hidden;
  /* Радиус больше общего карточного (22px): на референсе углы заметно мягче, а
     панель тут крупная — на такой площади 22px читаются как почти прямой угол.
     30 → 32px по просьбе «ещё процентов на восемь» (16.08.2026). */
  border-radius: 32px;
  /* СТЕКЛО: полупрозрачная подложка и размытие того, что за панелью
     (17.08.2026 — то же, что вернули листу моделей).
     Здесь размытие сильнее, чем у листа моделей (6px против 2px), и это не
     разнобой: панель промокода почти во весь экран и почти пустая, сквозь
     слабое размытие под ней читался бы текст страницы и мешал бы коду.
     ПРО АНИМАЦИЮ. Размытие подложки и длинный выезд дружат плохо: пока панель
     едет, движок считает размытие приближённо, а на последнем кадре
     пересчитывает начисто — виден щелчок в конце. Именно из-за этого панель
     раньше и сделали непрозрачной. Чтобы стекло не вернуло рывок, слой
     закреплён через `will-change` выше — там и transform, и backdrop-filter:
     второе просит движок считать размытие живым на всём выезде, а не
     доводить его одним кадром в конце (17.08.2026, «небольшой обрывчик»).
     И НЕ ДОБАВЛЯЙ СЮДА `transform: translateZ(0)` ДЛЯ СЛОЯ, как это сделано у
     листа моделей. Там стекло на вложенной группе, а трансформ выезда — на
     панели, это разные элементы. Здесь панель и есть стекло: второй transform
     на ней либо перебьёт выезд, либо (как сейчас, по специфичности) молча не
     применится — и то и другое хуже, чем ничего. */
  /* Та же фактура, что у листов (стекло iOS 26, 08.09.2026, «примени на
     окошко промокод»). */
  background: var(--ui-sheet-glass-bg);
  -webkit-backdrop-filter: saturate(1.8) blur(var(--ui-sheet-blur));
  backdrop-filter: saturate(1.8) blur(var(--ui-sheet-blur));
  /* Блик по кромке: верхняя грань светлее нижней — стекло читается освещённым
     сверху, а не просто обведённым. Значения те же, что у листа моделей. */
  box-shadow: var(--ui-sheet-glass-shadow);
  text-align: center;
}
/* Шапка и крестик общие с листом выбора модели (17.08.2026): юзер просил
   «1 в 1 как в промокоде». Именно общий селектор, а не копия значений —
   копия разъедется при первой же правке одной из панелей. */
.impito-promo-panel__head,
.impito-sheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.impito-promo-panel__title,
.impito-sheet__title {
  color: var(--ui-text);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
/* Крестик — круг с заливкой, как у референса, но на нашей подложке. */
.impito-promo-panel__close,
.impito-sheet__close {
  display: grid;
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--ui-fill-2);
  color: var(--ui-text-2);
  cursor: pointer;
  place-items: center;
  -webkit-tap-highlight-color: transparent;
}
.impito-promo-panel__close svg,
.impito-sheet__close svg {
  width: 15px;
  height: 15px;
}
.impito-promo-panel__close:active,
.impito-sheet__close:active {
  background: var(--ui-fill-3);
}
/* Место под эмодзи держим фиксированным: анимация приезжает позже статичной
   картинки, и без заданной высоты панель дёрнулась бы в момент подмены. */
/* Блок с эмодзи ужат: было 88px картинки и по 26/22px полей — панель выходила
   заметно выше референса. Стало 72px и 16/12px. Высота задана жёстко нарочно:
   анимация приезжает позже статичной картинки, и без неё панель дёргалась бы
   в момент подмены. */
.impito-promo-panel__art {
  display: grid;
  height: 72px;
  /* 16/12 → 9/8. Ужимаем ПОЛЯ, а не саму картинку: размер эмодзи оставлен
     72px, иначе анимация заметно потеряет в весе. Значения подобраны под
     замер: с ними панель ровно на 5% ниже прежней, что и просили. */
  margin: 7px 0 8px;
  place-items: center;
}
.impito-promo-panel__art img,
.impito-promo-panel__lottie {
  width: 72px;
  height: 72px;
}
/* Поле кода: крупные разрежённые буквы по центру, как на референсе. Своей
   рамки нет — её роль играет пунктир под полем. */
.impito-promo-panel__field {
  width: 100%;
  /* Это и есть просвет между кодом и пунктиром: 12 → 10px, «совсем чуть
     чуть» (17.08.2026). Меньше не стоит — хвосты у Р и Д начнут задевать
     линию. */
  padding: 0 0 10px;
  border: 0;
  background: transparent;
  color: var(--ui-text);
  font-family: var(--ui-font);
  /* Крупнее и плотнее шапки нарочно: это главная строка панели, ради неё
     лист и открывают (17.08.2026). 660, а не 700 — Inter переменный, вес
     берётся ровно указанный, и 700 на разрежённых заглавных уже тяжелит. */
  font-size: 25.5px;
  font-weight: 660;
  letter-spacing: 0.22em;
  /* Разрядка добавляет пробел и справа от последней буквы — сдвигаем строку
     на половину, иначе центр оптически уезжает влево. */
  text-indent: 0.22em;
  text-align: center;
  text-transform: uppercase;
}
.impito-promo-panel__field::placeholder {
  color: var(--ui-hint);
  opacity: 0.55;
}
.impito-promo-panel__field:focus {
  outline: none;
}
/* Пунктир КОРОЧЕ ПАНЕЛИ, а не во всю ширину: на референсе он примерно под
   длину кода и держит его, а растянутый до краёв читается как разделитель
   секции, а не как поле ввода. */
.impito-promo-panel__rule {
  display: block;
  width: min(100%, 236px);
  margin: 0 auto;
  /* ПУНКТИР НАРИСОВАН ГРАДИЕНТОМ, А НЕ `border: dashed`, И ЭТО ВЫНУЖДЕННО.
     У бордюра рисунок штрихов считает сам движок, отдельными свойствами его
     не задать — «штрихи крупнее на 20%» пришлось бы выражать через толщину.
     А толщину нельзя: `2.4px` браузер округляет обратно до 2px (проверено
     замером computed style, dpr 2), то есть правка просто не применилась бы.
     Числа не на глаз: прежний `2px dashed` отрисован в canvas и промерен по
     пикселям — штрих 6.67px, просвет 3.33px. Плюс 20% даёт 8px и 4px при
     толщине 2.4px, что и стоит ниже. Меняешь толщину — пересчитай и их,
     иначе пропорция штриха поедет. */
  height: 2.4px;
  background-image: repeating-linear-gradient(
    to right,
    var(--ui-separator) 0 8px,
    transparent 8px 12px
  );
}
.impito-promo-panel__note {
  min-height: 16px;
  margin: 8px 0 0;
  color: var(--ui-hint);
  font-size: 13.5px;
  line-height: 1.3;
}
.impito-promo-panel__note.is-ok {
  color: var(--ui-confirm);
}
.impito-promo-panel__note.is-error {
  color: var(--ui-destructive);
}
.impito-promo-panel__submit {
  width: 100%;
  margin-top: 10px;
}
/* Погасшая кнопка не должна выглядеть нажимаемой: пока код не введён, она
   ровно такая же серая, как на референсе. */
.impito-promo-panel__submit[disabled] {
  background: var(--ui-fill-2);
  color: var(--ui-hint);
  box-shadow: none;
  pointer-events: none;
}
/* Ответ кнопки «вставить». Идёт ПОСЛЕ правила выше намеренно: у элемента оба
   класса, а там стоит `margin: 0` — переставишь местами, и отбивка пропадёт.
   Мельче основного текста секции: это реплика на нажатие, а не постоянная
   подпись. */
.impito-style-paste-note {
  margin-top: 8px;
  font-size: 13px;
}
.impito-photo-row__chevron {
  width: 8px;
  height: 14px;
  flex: 0 0 auto;
  color: var(--ui-hint);
  opacity: 0.7;
}
/* Выбранная модель в листе — акцентом, чтобы было видно, что уже стоит. */
.impito-sheet__option.is-active {
  color: var(--ui-accent-strong);
  font-weight: 600;
}
/* ── Строка модели: имя слева, пояснение справа (11.08.2026, просьба юзера) ──
   Модификатор, а НЕ правка базового `.impito-sheet__option`: тот же класс
   носят пункты листа выбора источника фото («сделать фото», «из галереи»,
   «файлы»), и им нужна прежняя строка по центру.
   Высота уходит в `min-height`: пояснение на узком экране переносится на две
   строки, и жёсткие 54px обрезали бы вторую. */
.impito-sheet__option--model {
  display: flex;
  min-height: 54px;
  height: auto;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 11px 18px;
  text-align: left;
}
.impito-sheet__option-name {
  flex: 0 0 auto;
}
/* Значок модели — тот же премиум-эмодзи, что на кнопке в боте (картинкой,
   см. model_emoji.js). Пара «значок + название» живёт в своей обёртке, иначе
   `space-between` строки растащила бы их по разным краям. */
.impito-sheet__option-lead {
  display: flex;
  flex: 0 1 auto;
  min-width: 0;
  align-items: center;
  gap: 9px;
}
.impito-sheet__option-emoji {
  flex: 0 0 auto;
  width: 21px;
  height: 21px;
  object-fit: contain;
  /* Значок не должен ловить долгий тап «сохранить изображение»: он часть
     кнопки, а не картинка, которую тут кто-то собирался разглядывать. */
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
}
/* Пояснение НЕ наследует цвет и жирность строки: у выбранной модели имя
   становится акцентным и полужирным, а подпись обязана остаться спокойной —
   иначе выбранный пункт превращается в два одинаково громких куска текста. */
/* ПОТОЛОК ШИРИНЫ — ЧТОБЫ ПЕРЕНОС НЕ ЗАВИСЕЛ ОТ ДЛИНЫ ИМЕНИ МОДЕЛИ.
   Без него место под пояснение = «остаток строки», и одно и то же по смыслу
   пояснение ведёт себя по-разному: у «Nano Banana Pro» имя длинное, остаток
   узкий, текст переносится на две строки; у короткого «Flux Max» остаток
   широкий, и такое же пояснение вытягивается в одну длинную строку через весь
   экран (11.08.2026, юзер увидел это на своём телефоне — на 375px оба
   переносятся, а на 402px расходятся). 175px подобраны замером: длинные
   пояснения про редактирование переносятся на две строки на ЛЮБОЙ ширине, а
   короткие («меньше всего цензуры», «как Pro, только дешевле») остаются в одну
   строку. Меняешь тексты — перепроверяй на 402px, там запас меньше всего. */
/* ── Плитки моделей в листе выбора (09.09.2026, макет юзера) ──────────────
   Вместо строк «значок · название · пояснение» — сетка 2×3 плоских плиток.
   Плитка носит `.impito-param` (та же, что кнопки «модель фото» и «формат»
   на экране): радиус, фон, сквиркл (squircle.js) и нажатие берутся оттуда,
   здесь только размеры под сетку. Разметка — model_cards.js, одна на три
   листа (генерация, стиль, настройки профиля).
   Ряды одной высоты: `align-items: stretch` + `height: 100%` у плитки, а
   высота ряда — по самой высокой плитке (пояснение в две строки). */
.impito-model-cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  padding: 4px 12px 14px;
  align-items: stretch;
}
.impito-model-card.impito-param {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 72px;
  align-items: center;
  gap: 8px;
  /* Плитка вдвое уже экранной кнопки — поля ужаты, иначе «Nano Banana Pro»
     переносится на две строки. */
  padding: 9px 8px 9px 11px;
}
.impito-model-card .impito-param__logo {
  width: 28px;
  height: 28px;
}
.impito-model-card .impito-param__logo img {
  width: 26px;
  height: 26px;
  object-fit: contain;
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
}
/* Название и пояснение ПЕРЕНОСЯТСЯ, а не режутся многоточием: в плитке
   шириной ~170px «Nano Banana Pro» и «отличная для редактирования» иначе
   обрезались бы. */
.impito-model-card .impito-param__value {
  white-space: normal;
  font-size: 13.5px;
  letter-spacing: -0.015em;
  line-height: 1.1;
}
.impito-model-card .impito-param__title {
  margin-top: 2px;
  font-size: 11px;
  line-height: 1.2;
  white-space: normal;
}
/* ВЫДЕЛЕНИЯ ТЕКУЩЕЙ МОДЕЛИ НЕТ НАМЕРЕННО (юзер, 09.09.2026): класс
   `is-active` экраны ставят ради aria, но плитка его не рисует. */
/* Заглушка «список ещё не загрузился» — не кнопка, курсор обычный. */
.impito-sheet__option--static {
  cursor: default;
}

/* ТЁМНАЯ ТЕМА (09.09.2026, владелец: «кнопочки чуть сливаются»): плитки,
   широкая плитка и капсулы в листе моделей на 5% плотнее общего --ui-card
   (0.07 → 0.12) / --ui-fill (0.08 → 0.13), размытие листа на 7% сильнее
   (18.5 → 19.8px). Только лист моделей, остальные карточки прежние. */
[data-theme="dark"] .impito-model-card.impito-param,
[data-theme="dark"] .impito-model-pair {
  background: rgba(255, 255, 255, 0.12);
}
[data-theme="dark"] .impito-model-cap {
  background: rgba(255, 255, 255, 0.13);
}
[data-theme="dark"] .impito-model-sheet {
  --ui-sheet-blur: 19.8px;
}

/* ── Широкая плитка модели с двумя режимами (макет GPT-image 2.5,
   09.09.2026, вариант A). Оформление готово заранее: сама модель и её режимы
   Sunburst / Flare подключаются бэкендом отдельно, фронт ничего не
   подставляет. Разметка, под которую написаны правила:
     <div class="impito-model-cards">
       <div class="impito-model-pair">
         <span class="impito-model-pair__head">
           <span class="impito-param__logo"><img …></span>
           <span class="impito-param__body">
             <span class="impito-param__value">GPT-image 2.5</span>
             <span class="impito-param__title">самая лучшая модель</span>
           </span>
         </span>
         <button class="impito-model-cap impito-model-cap--sun" type="button">
           <span class="impito-model-cap__name">Sunburst</span><small>лучше</small>
         </button>
         <button class="impito-model-cap impito-model-cap--flare" type="button">
           <span class="impito-model-cap__name">Flare</span><small>быстрее</small>
         </button>
       </div>
       …обычные плитки…
     </div>
   Капсулы — две кнопки, а не переключатель: выделенного состояния нет,
   тап по капсуле выбирает модель с режимом, как тап по обычной плитке. */
.impito-model-pair {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  padding: 9px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
  box-shadow: var(--ui-surface-highlight);
}
.impito-model-pair__head {
  display: flex;
  grid-column: 1 / -1;
  min-height: 28px;
  align-items: center;
  gap: 8px;
  padding-left: 2px;
}
.impito-model-pair__head .impito-param__logo {
  width: 28px;
  height: 28px;
}
.impito-model-pair__head .impito-param__logo img {
  width: 26px;
  height: 26px;
}
.impito-model-pair__head .impito-param__value {
  white-space: normal;
  font-size: 13.5px;
  letter-spacing: -0.015em;
  line-height: 1.1;
}
.impito-model-pair__head .impito-param__title {
  margin-top: 2px;
  font-size: 11px;
  line-height: 1.2;
  white-space: normal;
}
.impito-model-cap {
  display: flex;
  min-height: 36px;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 0 8px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-fill);
  color: var(--ui-text);
  font: inherit;
  letter-spacing: -0.01em;
  line-height: 1;
}
.impito-model-cap__name {
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1;
}
.impito-model-cap small {
  color: var(--ui-hint);
  font-size: 11.5px;
  font-weight: 400;
  line-height: 1;
}
/* Цвета режимов — токены ниже в :root и [data-theme="dark"]: Sunburst
   тёплый оранжевый, Flare сиреневый, подобраны под розовый акцент. */
.impito-model-cap--sun .impito-model-cap__name {
  color: var(--ui-mode-sun);
}
.impito-model-cap--flare .impito-model-cap__name {
  color: var(--ui-mode-flare);
}

/* ── Стекло листов модели и формата ───────────────────────────────────────
   Время выезда у них общее с промокодом и задано выше — здесь только вид.
   Scope нужен: классы `.impito-sheet*` общие, на них живут и другие листы
   (выбор в разделе «стили»), у которых прежний короткий выезд на 24px. */
.impito-model-sheet .impito-sheet__group,
.impito-format-sheet .impito-sheet__group {
  /* Радиус как у промокода. */
  border-radius: 32px;
  /* СТЕКЛО ОСТАЁТСЯ: полупрозрачный фон и размытие подложки — как на прежней
     панели (17.08.2026, юзер прислал скриншот старой и попросил вернуть).
     Значения не свои, а унаследованные от базового `.impito-sheet__group`,
     тут они не переопределяются вовсе — переписывать их копией значило бы
     развести две панели при первой же правке базовой.
     ВАЖНО ПРО АНИМАЦИЮ. Размытие подложки и длинный выезд дружат плохо: пока
     панель едет, движок считает размытие приближённо, а на последнем кадре
     пересчитывает начисто — и это видно как щелчок в конце. На промокоде мы
     от этого ушли, сделав панель непрозрачной, но здесь стекло важнее. Чтобы
     щелчка не было, слой у панели закреплён заранее (`will-change` ниже), и
     сама группа тоже вынесена в свой слой — тогда движок не заводит и не
     выбрасывает его на границах перехода.
     Если рывок всё же вернётся — виновато именно размытие, и выбор будет
     между ним и гладкой концовкой. */
  transform: translateZ(0);
  /* Просим движок считать размытие живым на всё время, а не «как-нибудь, а в
     конце начисто»: именно тот доводочный кадр и читается как обрывчик. */
  will-change: backdrop-filter;
  /* Тени и блик — из базового `.impito-sheet__group` (фактура iOS 26, 08.09.2026). */
}
.impito-model-sheet .impito-sheet__panel,
.impito-format-sheet .impito-sheet__panel {
  /* Свой слой на всё время жизни: иначе браузер заводит его на старте
     перехода и выбрасывает в конце, и на этой границе кадр щёлкает. */
  will-change: transform;
  backface-visibility: hidden;
}
/* ── Режимы реставрации и улучшения: карточки со снимком ──────────────────
   Раньше режимы лежали строками прямо на экране. Стало как на референсе от
   юзера (17.08.2026): одна строка «режим» открывает лист, а в нём — квадратные
   снимки в ряд, под каждым название и кружок выбора.
   Число колонок приходит из js через переменную: в реставрации три режима, в
   улучшении два, и ряд должен заполняться целиком в обоих случаях. */
/* Исходник над рядом режимов. Крупнее карточек НАМЕРЕННО: по плитке в 111px
   не понять, что было на фото, а без этого сравнивать результаты не с чем.
   Ширина в процентах, а не числом: в реставрации панель делится на три
   карточки, в улучшении на две, и фиксированный размер выглядел бы случайным
   в одном из двух случаев. */
.impito-mode-source {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 14px 18px 0;
}
.impito-mode-source__shot {
  display: grid;
  /* 52%/176px не годились: в улучшении карточки сами по 172px, и исходник
     выходил больше их всего на 2% — то есть визуально не выделялся вовсе
     (17.08.2026, померено). При 68% он крупнее карточки вдвое в реставрации
     и в треть в улучшении, то есть заметно больше в обоих разделах. */
  width: min(68%, 240px);
  aspect-ratio: 1 / 1;
  border-radius: 16.8px;
  background: var(--ui-media-shot);
  color: var(--ui-hint);
  box-shadow: inset 0 0 0 0.5px var(--ui-separator);
  place-items: center;
  overflow: hidden;
}
.impito-mode-source__shot svg {
  width: 26%;
  height: 26%;
}
.impito-mode-source__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Подпись приглушена относительно названий режимов: это ярлык, а не вариант,
   на который можно нажать. */
.impito-mode-source__name {
  color: var(--ui-hint);
  font-size: 13px;
  font-weight: 510;
  letter-spacing: 0.02em;
}
.impito-mode-grid {
  display: grid;
  grid-template-columns: repeat(var(--impito-mode-cols, 3), minmax(0, 1fr));
  gap: 10px;
  padding: 12px 18px 18px;
}
.impito-modecard {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
/* Снимок. ЗАГЛУШКА: настоящих примеров «до/после» пока нет, стоит иконка на
   мягкой подложке. Появятся примеры — сюда встанет <img> с тем же
   `aspect-ratio`, и остальное менять не придётся. */
.impito-modecard__shot {
  display: grid;
  width: 100%;
  /* Строго квадрат, как просили. Через aspect-ratio, а не через padding-hack:
     высота тогда не зависит от того, что внутри — картинка, иконка или ничего. */
  aspect-ratio: 1 / 1;
  /* 16 → 16.8px: «на пять процентов сильнее» (17.08.2026). */
  border-radius: 16.8px;
  background: var(--ui-media-shot);
  color: var(--ui-hint);
  box-shadow: inset 0 0 0 0.5px var(--ui-separator);
  place-items: center;
  overflow: hidden;
}
.impito-modecard__shot svg {
  width: 30%;
  height: 30%;
}
.impito-modecard__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Выбранная карточка обведена акцентом. Обводка нарисована тенью, а не border:
   border добавил бы 2px к ширине снимка, и соседние карточки в ряду стали бы
   разного размера — заметно именно при переключении. */
.impito-modecard.is-active .impito-modecard__shot {
  box-shadow: inset 0 0 0 2px var(--ui-accent);
}
.impito-modecard__name {
  color: var(--ui-text);
  font-size: 13.5px;
  font-weight: 590;
  line-height: 1.25;
  text-align: center;
}
/* Кружок выбора. Невыбранный НЕ прячем, а показываем пустой обводкой: убери
   его — карточки станут разной высоты, и ряд поедет при каждом переключении. */
.impito-modecard__mark {
  display: grid;
  width: 22px;
  height: 22px;
  flex: 0 0 auto;
  border-radius: 50%;
  color: transparent;
  box-shadow: inset 0 0 0 1.8px var(--ui-separator);
  place-items: center;
  transition:
    background-color var(--ui-dur) var(--ui-ease),
    box-shadow var(--ui-dur) var(--ui-ease),
    color var(--ui-dur) var(--ui-ease);
}
.impito-modecard__mark svg {
  width: 13px;
  height: 13px;
}
.impito-modecard.is-active .impito-modecard__mark {
  background: var(--ui-accent);
  color: var(--ui-accent-text);
  box-shadow: none;
}
.impito-modecard:active .impito-modecard__shot {
  opacity: 0.82;
}
/* Верхний отступ теперь даёт шапка, а не сама группа — иначе они сложатся и
   заголовок уедет от края вдвое дальше, чем у остальных панелей. */
.impito-format-sheet .impito-ratio-sheet {
  padding: 0 0 16px;
}
/* Шапка листа. Отступ слева тот же 18px, что у строк с моделями, — заголовок
   встаёт ровно над их текстом. */
.impito-sheet__head {
  padding: 14px 18px 10px;
}
/* Первая строка модели идёт сразу под шапкой, и разделитель между ними нужен
   такой же, как между самими строками: без него шапка сливается со списком. */
.impito-sheet__head + .impito-sheet__option {
  border-top: 0.5px solid var(--ui-separator);
}
.impito-sheet__option-note {
  min-width: 0;
  max-width: 175px;
  color: var(--ui-hint);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.25;
  text-align: right;
}
.impito-topup-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin: 0 12px;
}
/* Хиро-баланс в стиле iOS (Battery/Screen Time): подпись → крупное число → единица */
.impito-topup-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 6px 22px 2px;
  text-align: center;
}
.impito-topup-hero__label {
  color: var(--ui-hint);
  font-size: 13px;
  font-weight: 510;
  letter-spacing: 0.02em;
  line-height: 1.2;
}
.impito-topup-hero__value {
  margin-top: 2px;
  color: var(--ui-text);
  font-size: 44px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
  line-height: 1.05;
}
.impito-topup-hero__unit {
  margin-top: 1px;
  color: var(--ui-hint);
  font-size: 14px;
  line-height: 1.3;
}
.impito-topup-custom.ui-card {
  margin-top: 10px;
}
/* Поле своего количества — «таблетка», а не карточка (17.08.2026, просьба
   юзера). Радиус 999px не рисует круг буквой: движок сам обрезает его до
   половины высоты, поэтому торцы всегда ровно полукруглые, какой бы высоты
   поле ни стало. */
.impito-topup-custom {
  border-radius: var(--ui-radius-pill);
}
.impito-topup-custom__field {
  font-variant-numeric: tabular-nums;
  /* Боковые поля больше прежних 18px: у «таблетки» левый торец — дуга шириной
     примерно в половину высоты, и текст, поставленный по старому отступу,
     оптически залезал бы на закругление. */
  padding-left: 24px;
  padding-right: 24px;
}
.impito-topup-promo.ui-card {
  margin-top: 10px;
  /* «Таблетка», как у поля своего количества выше (17.08.2026). 999px не
     рисует круг буквой — движок режет радиус до половины высоты, поэтому
     торцы остаются полукруглыми при любой высоте строки. */
  border-radius: var(--ui-radius-pill);
}
/* ПОДСВЕТКА НАЖАТИЯ ТОЖЕ ДОЛЖНА СТАТЬ ТАБЛЕТКОЙ. Она рисуется отдельным слоем
   поверх строки, а карточка у нас с `overflow: visible` — базовое правило даёт
   этому слою обычный карточный радиус 22px, и при нажатии его углы вылезли бы
   за скругление. */
.impito-topup-promo .impito-promo-row:after {
  border-radius: var(--ui-radius-pill);
}
/* Боковые поля больше прежних 18px: у «таблетки» торец — дуга шириной примерно
   в половину высоты, и текст со стрелкой по старому отступу оптически
   наезжали бы на закругление. */
.impito-topup-promo .impito-promo-row {
  padding-left: 24px;
  padding-right: 24px;
}
/* Кнопка активации промокода. Вид — та же `.ui-button--large`, что у «поделиться
   ссылкой» на экране рефералов: один и тот же жест должен выглядеть одинаково.
   Но `--large` тянет ширину в 100%, а секция горизонтальных полей не имеет, и
   кнопка упиралась в края экрана, пока поля над ней стоят с отступом
   (01.08.2026, юзер прислал скрин). Поэтому свои поля 12px — ровно те же, что
   у `.ui-card`, — и `display: flex`, чтобы кнопка занимала остаток ширины, а не
   сжималась под текст. */
.impito-topup-promo__apply {
  display: flex;
  /* Именно calc, а не `width: auto`: у элемента <button> автоширина считается
     по содержимому, а не по контейнеру, и кнопка сжималась до слова. 24px —
     это ровно два поля по 12px, так что правый край совпадает с карточками. */
  width: calc(100% - 24px);
  height: 46px;
  margin: 10px 12px 0;
  font-size: 16px;
}
/* Ответ по промокоду. Цветом отличаем удачу от отказа: человек жмёт кнопку и
   обязан сразу понять, зачислилось что-то или нет. */
.impito-topup-promo__note {
  margin: 8px 0 0;
  min-height: 18px;
}
.impito-topup-promo__note.is-ok {
  color: var(--ui-confirm);
}
.impito-topup-promo__note.is-error {
  color: var(--ui-destructive);
}
/* ── СКИДКА ПО ПРОМОКОДУ ────────────────────────────────────────────────────
   До 06.08.2026 промокод не менял на экране НИЧЕГО: он уходил на сервер, а в
   ответ появлялась серая строчка «скидка 20% — применится при оплате». Юзер:
   «я использовал промокод, и хуй пойми чо изменилось». Теперь цена честно
   пересчитывается на карточках и в итоговой панели, старая — зачёркивается.

   ЗАЧЁРКИВАНИЕ СВОЁ, А НЕ `text-decoration: line-through`, И ЭТО ГЛАВНОЕ
   РЕШЕНИЕ ЗДЕСЬ. Декорация текста не анимируется ничем: она либо есть, либо
   нет. А нужен именно жест — линия ПРОВОДИТСЯ по старой цене в тот момент,
   когда код приняли. Отдельный `::after` с `transform: scaleX()` и
   `transform-origin: left` даёт ровно это и стоит один композиторский слой.
   Оба элемента inline-BLOCK намеренно: у строчных `transform` не действует, а
   без него не будет ни выезда новой цены, ни самой линии. */
.impito-price-was {
  position: relative;
  display: inline-block;
  margin-right: 5px;
  color: var(--ui-hint);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Страховка от грабли, на которую мы уже наступали в форме промокодов админки:
   у элемента с `display` из авторского правила атрибут `hidden` перестаёт
   работать, и «скрытый» узел остаётся видимым. */
.impito-price-was[hidden] {
  display: none;
}
.impito-price-was::after {
  content: "";
  position: absolute;
  top: 50%;
  right: -1px;
  left: -1px;
  height: 1.3px;
  border-radius: 1px;
  background: currentColor;
  transform: scaleX(1);
  transform-origin: left center;
}
.impito-price-now {
  display: inline-block;
  color: var(--ui-accent-ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.impito-topup-pack__price .impito-price-was {
  font-size: 13px;
}
/* Плашка активной скидки. Стоит НАД пакетами: человек должен прочитать
   «промокод применён» ровно перед тем, как увидит перечёркнутые цены, —
   иначе связь между двумя фактами не читается. */
.impito-promo-live {
  margin-bottom: 14px;
}
.impito-promo-live__card {
  display: flex;
  align-items: center;
  margin: 0 12px;
  gap: 12px;
  padding: 12px 14px;
  border-radius: var(--ui-radius-card);
  /* Обводки нет (16.08.2026, просьба юзера). Была волосяная розовая линия
     `inset 0 0 0 1px` — на розовом фоне она читалась как лишний контур вокруг
     и без того заметной плашки. Форму держит сама заливка `--ui-accent-soft`,
     она темнее фона страницы и края видны без всякой линии. */
  background: var(--ui-accent-soft);
}
.impito-promo-live__badge {
  flex: 0 0 auto;
  padding: 5px 10px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-accent);
  color: var(--ui-accent-text);
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  line-height: 1;
}
.impito-promo-live__body {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
}
.impito-promo-live__title {
  overflow: hidden;
  color: var(--ui-text);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.impito-promo-live__sub {
  color: var(--ui-hint);
  font-size: 12.5px;
  line-height: 1.25;
}
/* Причина новой цены в итоговой панели. Акцентом — это единственная строка,
   которая объясняет, откуда взялась сумма меньше прежней. */
.impito-topup-meta__savings.is-promo {
  color: var(--ui-accent-ink);
  font-weight: 600;
}
/* СТАРАЯ ЦЕНА В ПАНЕЛИ СТОИТ НАД НОВОЙ, А НЕ РЯДОМ, И ЭТО ВЫНУЖДЕННО. Панель —
   грид из трёх колонок в 339px на iPhone. Строкой в ряд «1 200 ₽ 960 ₽»
   занимала 119px вместо 62px, колонка кнопки схлопывалась до 79px при её
   собственных 115px, и «пополнить» наезжала на строки «100 токенов» и
   «промокод −20%» (замер на стенде 06.08.2026). Столбиком блок цены остаётся
   прежней ширины, и панель не разъезжается ни на одном размере пакета. */
.impito-topup-total__was {
  margin-right: 0;
  font-size: 11.5px;
  line-height: 1.15;
}
/* ── Момент применения ─────────────────────────────────────────────────────
   Всё ниже включается ТОЛЬКО классом `is-promo-in`/`is-arriving`, который js
   вешает в момент активации кода. На обычной загрузке экрана (скидка уже
   действует со вчера) анимаций нет вовсе — цены просто нарисованы новыми, и
   это правильно: применять нечего, жест уже произошёл когда-то раньше. */
.impito-promo-live.is-arriving {
  animation: impito-promo-in 0.42s var(--ui-ease-out) both;
}
.impito-promo-live.is-arriving .impito-promo-live__badge {
  animation: impito-promo-badge 0.46s var(--ui-ease-out) 0.08s both;
}
@keyframes impito-promo-in {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
}
@keyframes impito-promo-badge {
  from {
    opacity: 0;
    transform: scale(0.6);
  }
}
/* Карточки гасят старую цену волной слева направо — `--pack-index` приходит
   инлайном из разметки. Волна, а не одновременный щелчок: шесть одинаковых
   зачёркиваний в один кадр читаются как сбой перерисовки, а с задержкой в
   45мс — как одно движение по сетке. */
.impito-topup-pack.is-promo-in .impito-price-was {
  animation: impito-price-dim 0.42s var(--ui-ease) both;
  animation-delay: calc(var(--pack-index, 0) * 45ms + 60ms);
}
.impito-topup-pack.is-promo-in .impito-price-was::after {
  animation: impito-strike 0.42s var(--ui-ease-out) both;
  animation-delay: calc(var(--pack-index, 0) * 45ms + 60ms);
}
.impito-topup-pack.is-promo-in .impito-price-now,
/* Строка «за токен» едет ВМЕСТЕ с новой ценой, хотя текст в ней js меняет
   сразу. Ключ — `both`: во время задержки держится кадр `from`, то есть
   прозрачность 0. Без этого правила на полсекунды повисало бы «9 ₽ за токен»
   под ещё не зачёркнутыми «2 250 ₽» — две цифры из разных миров в одной
   карточке. */
.impito-topup-pack.is-promo-in .impito-topup-pack__per {
  animation: impito-price-in 0.44s var(--ui-ease-out) both;
  animation-delay: calc(var(--pack-index, 0) * 45ms + 190ms);
}
.impito-topup-total.is-promo-in .impito-price-was {
  animation: impito-price-in 0.4s var(--ui-ease-out) both;
}
.impito-topup-total.is-promo-in .impito-price-was::after {
  animation: impito-strike 0.42s var(--ui-ease-out) 0.1s both;
}
@keyframes impito-strike {
  from {
    transform: scaleX(0);
  }
}
@keyframes impito-price-dim {
  from {
    color: var(--ui-text);
  }
}
@keyframes impito-price-in {
  from {
    opacity: 0;
    transform: translateX(-6px);
  }
}

/* ── Магазин: переключатель «токены / подписка» ───────────────────────────
   Эффекты стекла приезжают из правил нижней панели (см. выше), здесь только
   размер и раскладка: панель — широкая пилюля на 67px, переключателю нужна
   компактная на 46px и в две равные доли. */
/* Цены, которые пересчитываются счётчиком. `inline-block` нужен для того,
   чтобы к ним применялся svg-фильтр смаза как к блоку, а не по строчным
   кускам. */
[data-sub-price],
[data-card-price],
[data-topup-price],
[data-pack-price] {
  display: inline-block;
}

/* Смена раздела магазина: содержимое проявляется, а не подменяется рывком.
   ТОЛЬКО ПРОЗРАЧНОСТЬ. Трансформа здесь быть НЕ ДОЛЖНО: внутри этого блока
   лежит нижняя панель с `position: fixed`, а любой элемент с трансформом
   становится для фиксированных потомков точкой отсчёта вместо экрана — панель
   отцеплялась и уезжала в поток вместе со скроллом (18.08.2026, юзер прислал
   скриншот). Тем же вредны filter, perspective, will-change на них и
   `contain: paint`.
   `fill-mode` тоже убран: с `both` анимация остаётся применённой и после
   окончания, то есть блок держал бы трансформ навсегда. */
@keyframes impito-shop-swap {
  from {
    opacity: 0;
  }
}
[data-shop-body].is-swapped {
  animation: impito-shop-swap 0.32s var(--ui-ease-out);
}
@media (prefers-reduced-motion: reduce) {
  [data-shop-body].is-swapped {
    animation: none;
  }
}

/* ── Рефералы ──────────────────────────────────────────────────────────────
   Раскладка с референса юзера (18.08.2026): крупное число, под ним заголовок,
   ниже пояснение, а под карточкой — плитки со статистикой.
   ЦВЕТА НАШИ: карточка белая, никакого контрастного синего с референса. Число
   красим акцентом — это единственное цветное пятно на экране.
   Награда НЕ зашита во фронт: приходит с сервера из той же настройки, что
   стоит в админке, иначе показанное и начисленное разошлись бы. */
.impito-ref-hero {
  position: relative;
  display: grid;
  justify-items: start;
  gap: 6px;
  margin: 0 12px;
  /* Правое поле больше остальных: там висит эмодзи, и текст не должен под него
     подлезать. */
  padding: 22px 116px 20px 20px;
  border-radius: 26px;
  background: var(--ui-media-bg);
  overflow: hidden;
}
/* Эмодзи в свободном углу карточки. Абсолютом, а не колонкой в сетке: текст
   переносится по своей ширине, и колонка гуляла бы вместе с ним. */
.impito-ref-hero__art {
  position: absolute;
  top: 18px;
  right: 14px;
  display: grid;
  width: 92px;
  height: 92px;
  place-items: center;
  pointer-events: none;
}
.impito-ref-hero__art img,
.impito-ref-hero__lottie {
  width: 92px;
  height: 92px;
}
.impito-ref-hero__value {
  display: flex;
  align-items: baseline;
  gap: 9px;
  color: var(--ui-accent-strong);
}
.impito-ref-hero__value strong {
  font-size: 52px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.035em;
  line-height: 1;
}
.impito-ref-hero__value span {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.impito-ref-hero__title {
  color: var(--ui-text);
  font-size: 24px;
  font-weight: 750;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.impito-ref-hero__sub {
  margin-top: 2px;
  color: var(--ui-text-2);
  font-size: 14.5px;
  line-height: 1.35;
}
/* Плитки статистики. Их две, а не три: рублей и партнёрского баланса у нас
   нет — начисляем токенами. */
.impito-ref-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  /* Нижние 24px — ТЕ ЖЕ, что у обычной секции. Задав `margin: 0 12px`, я стёр
     их вместе с боковыми, и заголовок «твоя ссылка» прилипал сверху
     (18.08.2026). Пишем все четыре стороны явно. */
  margin: 0 12px 24px;
}
/* Содержимое по центру: число и подпись стоят друг под другом, и выравнивать
   их по-разному нельзя — подпись уехала бы от своей цифры. */
.impito-ref-stat {
  display: grid;
  justify-items: center;
  gap: 3px;
  padding: 14px 16px;
  border-radius: 22px;
  background: var(--ui-media-bg);
  text-align: center;
}
.impito-ref-stat__value {
  color: var(--ui-text);
  font-size: 26px;
  font-weight: 750;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1.05;
}
.impito-ref-stat__label {
  color: var(--ui-hint);
  font-size: 13.5px;
  line-height: 1.2;
}

/* ── Переключатель магазина ────────────────────────────────────────────────
   ПРОСТОЙ И САМОСТОЯТЕЛЬНЫЙ. Раньше он тянул стиль и физику из таббара —
   стекло, линзу, захват пальцем, отскок. По итогу это и выглядело чужеродно,
   и постоянно ловило чужую геометрию, поэтому 18.08.2026 всё это убрано, а
   правила переписаны с нуля: плоская дорожка, плоский ползунок, один переезд.
   Ничего отсюда не наследуется и никуда не наследует — трогать можно смело.

   Уже во всю ширину в полтора раза: во всю ширину переключатель читался как
   ещё одна панель, а он — выбор внутри экрана. Через min(), а не фиксированной
   шириной: на узких экранах поля по краям важнее точной доли. */
.impito-shop-seg {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  box-sizing: border-box;
  width: min(calc((100% - 24px) / 1.5), 336px);
  margin: 0 auto 14px;
  padding: 4px;
  border-radius: var(--ui-radius-pill);
  /* ЦВЕТ ИЗ ТОЙ ЖЕ ГАММЫ, ЧТО У НИЖНЕЙ ПАНЕЛИ, а не серый (18.08.2026).
     Прежний rgba(120,120,128,…) — нейтральная серость, и поверх розовой
     страницы она читалась грязноватой.
     18.08.2026 дорожку сделали светлой, а ползунок плотнее; 28.08.2026 юзер
     попросил поменять обратно — теперь плотная дорожка и светлая выбранная
     доля. */
  background: var(--ui-shop-track);
}
.impito-shop-tabs {
  height: 46px;
}
.impito-subs-term {
  height: 38px;
  margin-bottom: 12px;
}
/* Ползунок ровно в половину дорожки и ровно по её высоте за вычетом полей.
   Все размеры от box-sizing дорожки, поэтому ни при какой ширине экрана он не
   вылезет за край — прежняя версия это делала регулярно. */
.impito-shop-thumb {
  position: absolute;
  top: 4px;
  left: 4px;
  z-index: 0;
  width: calc(50% - 4px);
  height: calc(100% - 8px);
  border-radius: var(--ui-radius-pill);
  /* Светлее дорожки — цвет нижней панели: выбранная доля выступает вперёд.
     Чистый белый пробовали 28.08.2026, юзер забраковал. */
  background: var(--ui-shop-thumb);
  transform: translate3d(0, 0, 0);
  /* Длиннее и мягче прежних 0.28с: короткий переезд с резким торможением
     читался как рывок. Кривая с длинным хвостом — та же, что у ползунка
     таббара, там она подбиралась под тот же жест. */
  transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
/* Переезд — атрибутом на дорожке. Сдвиг на 100% собственной ширины: доли
   одинаковые, значит вторая позиция ровно в ширину ползунка. */
.impito-shop-seg[data-index="1"] .impito-shop-thumb {
  transform: translate3d(100%, 0, 0);
}
@media (prefers-reduced-motion: reduce) {
  .impito-shop-thumb {
    transition: none;
  }
}
/* Подпись строго в одну строку и по центру доли. Раньше «−5%» уходило на
   вторую строку, кнопка становилась выше соседней, и текст переставал стоять
   по центру — со стороны это читалось как кривая вёрстка (18.08.2026). */
/* FLEX, А НЕ GRID, И ЭТО ГЛАВНОЕ В ЭТОМ ПРАВИЛЕ. У грида каждый ребёнок —
   отдельная ячейка, поэтому «−5%» лежал ОТДЕЛЬНОЙ СТРОКОЙ под «3 месяца»
   (18.08.2026, юзер жаловался дважды). `white-space: nowrap` тут бессилен: он
   запрещает перенос ВНУТРИ строки, а это были два разных элемента сетки.
   Заодно чинится центровка: у грида с двумя ячейками текст стоял по центру
   двухстрочного блока, то есть выше середины кнопки. */
.impito-shop-seg__btn {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  white-space: nowrap;
  border: 0;
  padding: 0;
  background: none;
  color: var(--ui-text-2);
  font: inherit;
  font-size: 15.5px;
  font-weight: 590;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--ui-dur) var(--ui-ease);
}
.impito-shop-seg__btn.is-active {
  color: var(--ui-text);
  font-weight: 650;
}

/* ── Магазин: карточки подписок ───────────────────────────────────────────
   Карточка на всю ширину — «одна кнопка подписки как две кнопки токенов»
   (18.08.2026). Внутри строго два столбца: слева что даём, справа цена. */
.impito-subs-grid {
  display: grid;
  gap: 10px;
  margin: 0 12px;
}
/* Карточка подписки. Раскладка с референса юзера (18.08.2026): сверху имя и
   цена, под именем плашка выгоды, ниже два столбца цифр.
   БЕЗ ОБВОДКИ, БЕЗ ГАЛОЧКИ И БЕЗ ЛИНИЙ ПОД ЦИФРАМИ — это отдельная просьба.
   Выбранная карточка отличается только плотностью подложки. */
.impito-subs-card {
  position: relative;
  display: grid;
  gap: 8px;
  padding: 13px 16px 14px;
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background var(--ui-dur) var(--ui-ease);
}
/* Выбранная карточка: белая в светлой теме, акцентная в тёмной.
   Заливка выделяет выбор без обводки. */
.impito-subs-card.is-active {
  background: var(--ui-card-selected);
}
.impito-subs-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
/* Имя и ярлык в одной строке: ярлык раньше висел над верхним краем карточки
   и вместе с плашкой выгоды давал два бейджа подряд. Инлайном он не стоит
   ни пикселя высоты. */
.impito-subs-card__title {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.impito-subs-card__tag {
  padding: 3px 8px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-accent);
  color: var(--ui-accent-text);
  font-size: 11px;
  font-weight: 650;
  line-height: 1.15;
  white-space: nowrap;
}
.impito-subs-card__tag--confirm {
  background: var(--ui-lime);
  color: var(--ui-lime-ink);
}
.impito-subs-card__name {
  color: var(--ui-text);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.1;
}
.impito-subs-card__price {
  display: grid;
  justify-items: end;
  gap: 1px;
  text-align: right;
}
.impito-subs-card__was {
  color: var(--ui-hint);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  text-decoration: line-through;
}
.impito-subs-card__now {
  color: var(--ui-text);
  font-size: 20px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.015em;
  line-height: 1.1;
}
.impito-subs-card__per {
  color: var(--ui-hint);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}
/* Плашка выгоды. В нашей гамме это акцент на мягкой подложке — зелёный с
   референса в палитре не живёт. */
.impito-subs-card__badge {
  justify-self: start;
  padding: 3px 9px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-accent-soft);
  color: var(--ui-accent-strong);
  font-size: 13px;
  font-weight: 650;
  line-height: 1.15;
}
.impito-subs-card__stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}
.impito-subs-card__stat {
  display: grid;
  gap: 2px;
}
.impito-subs-card__value {
  color: var(--ui-text);
  font-size: 23px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1.05;
}
.impito-subs-card__label {
  color: var(--ui-text-2);
  font-size: 13px;
  line-height: 1.2;
}

/* Срок подписки. Тот же вид, что у вкладок, но мельче: это выбор внутри
   раздела, а не переключение разделов. */
/* Срок мельче вкладок: это выбор внутри раздела, а не переключение разделов. */
.impito-subs-term .impito-shop-seg__btn {
  font-size: 14px;
}
/* Отступ даёт gap кнопки, свой margin тут только сдвинул бы текст с центра. */
.impito-subs-term__off {
  color: var(--ui-accent-strong);
  font-weight: 650;
}

/* Плитки «генерировать» — те же карточки 3:4, что и в каталоге стилей.
   ЦВЕТНЫХ ПОДЛОЖЕК ПОД НИМИ БОЛЬШЕ НЕТ. Раньше у каждой был свой градиент
   (розовый, фиолетовый, зелёный), и пока картинка не загрузилась, экран
   пестрел разноцветными прямоугольниками — юзер поймал это скриншотом
   17.08.2026. Теперь подложка одна на все карточки и белая, задана в
   `.impito-style-card`. */
.impito-topup-pack {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 13px 14px 12px;
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
  color: var(--ui-text);
  cursor: pointer;
  font-family: var(--ui-font);
  text-align: left;
  -webkit-tap-highlight-color: transparent;
  transition:
    background var(--ui-dur) var(--ui-ease),
    transform var(--ui-dur) var(--ui-ease);
}
.impito-topup-pack:active {
  transform: scale(0.97);
}
.impito-topup-pack.is-active {
  background: var(--ui-card-selected);
}
.impito-topup-pack__tag {
  position: absolute;
  top: 11px;
  right: 11px;
  max-width: calc(100% - 58px);
  overflow: hidden;
  padding: 4px 9px;
  border-radius: var(--ui-radius-pill);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.impito-topup-pack__tag--accent {
  background: var(--ui-accent);
}
.impito-topup-pack__tag--confirm {
  background: var(--ui-lime);
  color: var(--ui-lime-ink);
}
.impito-topup-pack__off {
  color: var(--ui-accent-ink);
  font-size: 12.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  line-height: 1.2;
}
.impito-topup-pack__tokens {
  margin-top: 10px;
  font-size: 27px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1.05;
}
.impito-topup-pack__unit {
  color: var(--ui-hint);
  font-size: 12.5px;
  line-height: 1.35;
}
.impito-topup-pack__price {
  margin-top: 9px;
  font-size: 15.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}
.impito-topup-pack__per {
  margin-top: 1px;
  color: var(--ui-hint);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  line-height: 1.35;
}
.impito-topup-submit__inner .impito-topup-total {
  width: auto;
  min-width: 0;
  padding-left: 10px;
}
/* Цена в одну строку: «1 200 ₽», а не число над валютой */
.impito-topup-total .impito-style-cost__value {
  flex-direction: row;
  align-items: baseline;
  gap: 4px;
}
.impito-topup-total .impito-style-cost__value strong {
  font-size: 20px;
}
.impito-topup-total .impito-style-cost__value span {
  font-size: 15px;
}
.impito-topup-submit__inner .impito-style-generate {
  height: 38px;
  justify-self: end;
  padding: 0 18px;
  font-size: 15px;
}
.impito-topup-meta {
  position: relative;
  z-index: 1;
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 3px;
  padding: 0 4px;
}
.impito-topup-meta__tokens {
  color: var(--ui-text);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.15;
  white-space: nowrap;
}
.impito-topup-meta__savings {
  color: var(--ui-hint);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  white-space: nowrap;
}
.impito-topup-submit__inner .is-swap {
  animation: impito-topup-swap 0.26s var(--ui-ease-out);
}
@keyframes impito-topup-swap {
  from {
    opacity: 0.15;
    transform: translateY(5px);
  }
}

/* ── Вкладка «История» ──
   Полки как в каталоге стилей: жирный чёрный заголовок с шевроном, под ним
   три строки в колонке, дальше листается вбок и справа выглядывает следующая
   (2026-07-31, просьба юзера). Белой панели под строками нет — она визуально
   спорила с полками и «ломала» ощущение ленты. */
.impito-hist-section {
  /* 26 → 18px (03.09.2026, «уменьши чуть-чуть расстояние между
     подпунктами»). */
  margin-bottom: 18px;
}
/* Первый заголовок упирался в верхнюю панель — отводим его вниз. */
.impito-hist-section:first-of-type {
  margin-top: 10px;
}
/* Заголовки полок истории — нашим розовым, тем же, что у кнопки «расширить»
   и ползунков (03.09.2026, просьба юзера). Только в истории: в каталоге
   стилей те же полки остаются чёрными. Шеврон берёт currentColor и красится
   вместе с текстом. */
.impito-hist-section .impito-cat-rail__head {
  color: var(--ui-accent-strong);
}
/* `--ui-accent-strong`, а не `--ui-accent`: светлый показался юзеру бледным,
   взят тот же, что у ника в приветствии на главной (03.09.2026). */
.impito-hist-section .impito-cat-rail__title {
  color: var(--ui-accent-strong);
}
.impito-hist-rail {
  /* Ручки те же, что у полок каталога и рейлов главной. */
  align-content: start;
  --ui-rail-gap: 8px;
  --ui-rail-peek: 18px;
  /* ЗАЗОР ТОЛЬКО ПО ГОРИЗОНТАЛИ — МЕЖДУ КОЛОНКАМИ (23.08.2026, просьба юзера).
     Здесь легко ошибиться: `gap` в гриде задаёт ОБА зазора сразу, и попытка
     раздвинуть колонки одним `gap` раздвинула ещё и строки внутри колонки —
     полка растянулась по вертикали. Поэтому две отдельные ручки:
     `--ui-rail-gap` — между строками (8px, не трогать),
     `--ui-hist-col-gap` — между колонками.
     Он же решает то, ради чего сюда лезли: при снапе предыдущая колонка
     заканчивается на `--ui-hist-start − --ui-hist-col-gap`, и пока отступ не
     БОЛЬШЕ зазора, слева не видно НИЧЕГО — само, без обрезки. Резать нельзя:
     обрезка рубит превью соседней карточки пополам (пробовали, забраковано). */
  --ui-hist-col-gap: 26px;
  /* Левое поле полки, 26 → 22 → 19px (23.08.2026, «слишком вправо вышла»,
     потом «ещё чуть-чуть»). Держать НЕ БОЛЬШЕ --ui-hist-col-gap, иначе слева
     полезет хвост предыдущей колонки. */
  --ui-hist-start: 19px;
  display: grid;
  /* Колонка шириной ровно во всю видимую область полки: строка длинная, и
     «три в ряд» тут не годится — из колонки должен выглядывать только край
     следующей. Сам «край» набирается полем справа (см. padding ниже), а не
     вычитанием из ширины колонки. ЭТО ВАЖНО ДЛЯ СНАПА: поле справа равно
     `зазор + выступ`, поэтому ПОСЛЕДНЯЯ колонка докручивается ровно до той же
     точки, что и все остальные. Пока справа стояли те же 12px, что и всюду,
     последней колонке не хватало места доехать: полка упиралась в конец,
     mandatory-снап откатывал её назад, и хвост предыдущей колонки лез
     слева — «у видео свайп как будто старый» (замечание юзера 23.08.2026).
     Заметно это было только там, где колонок мало. */
  grid-auto-columns: 100%;
  grid-auto-flow: column;
  /* 3 → 2 строки в колонке (03.09.2026, просьба юзера «по 2 фотки в
     каждом ряду»). */
  grid-template-rows: repeat(2, auto);
  row-gap: var(--ui-rail-gap);
  column-gap: var(--ui-hist-col-gap);
  overflow-x: auto;
  /* ЛЕВОЕ ПОЛЕ РАВНО scroll-padding-left. Было 12px против 26px — нетронутая
     полка стояла левее, чем та же полка после первого пролистывания, и
     содержимое дёргалось вбок на ровном месте (замечание юзера 23.08.2026).
     Держать эти два значения равными; менять — только вместе. */
  padding: 0 calc(var(--ui-hist-col-gap) + var(--ui-rail-peek)) 0
    var(--ui-hist-start);
  scrollbar-width: none;
  scroll-padding-left: var(--ui-hist-start);
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
}
.impito-hist-rail::-webkit-scrollbar {
  display: none;
}
.impito-hist-empty {
  margin: 0;
  padding: 2px 22px 0;
  color: var(--ui-hint);
  font-size: 14px;
}
/* Без панели-подложки: юзер попросил вместо карточек тонкие серые разделители,
   как в списках Apple Music. Строка — просто строка на фоне экрана. */
.impito-hist-row {
  --ui-hist-thumb: 64px;
  --ui-hist-gap: 12px;
  position: relative;
  display: flex;
  width: 100%;
  align-items: center;
  padding: 7px 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  gap: var(--ui-hist-gap);
  scroll-snap-align: start;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}
/* Линия идёт ТОЛЬКО под текстом, под превью её нет — как в списках Apple Music
   (2026-07-31, замечание юзера). Поэтому псевдоэлемент со сдвигом на ширину
   превью, а не border у всей строки. */
.impito-hist-row::after {
  position: absolute;
  right: 0;
  bottom: 0;
  left: calc(var(--ui-hist-thumb) + var(--ui-hist-gap));
  height: 0.5px;
  background: rgba(12, 18, 48, 0.12);
  content: "";
}
.impito-hist-row:active {
  opacity: 0.55;
}
/* Последняя строка в колонке полки и в конце списка — без линии снизу.
   В полке поток по колонкам, поэтому «последняя» — каждая третья. */
.impito-hist-rail .impito-hist-row:nth-child(3n)::after,
.impito-hist-list .impito-hist-row:last-child::after {
  display: none;
}
/* Референсы в карточке генерации: ряд квадратных превью, листается вбок, если
   их больше трёх. Заглушка `is-gone` — копии в служебной группе больше нет
   (сообщение удалили, отправка не удалась): показываем знак, а не битую
   картинку. */
.impito-gen-refs {
  display: flex;
  overflow-x: auto;
  padding: 0 19px;
  gap: 8px;
  scrollbar-width: none;
}
.impito-gen-refs::-webkit-scrollbar {
  display: none;
}
.impito-gen-refs__item {
  display: flex;
  overflow: hidden;
  width: 84px;
  height: 84px;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  border-radius: 14px;
  background: rgba(12, 18, 48, 0.06);
}
.impito-gen-refs__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.impito-gen-refs__item.is-gone {
  color: rgba(12, 18, 48, 0.32);
  font-family: var(--ui-font);
  font-size: 22px;
  font-weight: 600;
}

/* Действия в один ряд. Поля те же 12px, что у карточек, поэтому края совпадают
   со всем остальным на экране. */
.impito-gen-actions {
  display: flex;
  /* Нижнее поле ОБЯЗАТЕЛЬНО перечислять: сокращённая запись обнуляет
     margin-bottom секции, и следующий заголовок прилипает к кнопкам.
     24 → 12px (28.08.2026): столько же, сколько между промптом и
     референсами, — интервалы на экране стали одинаковыми. */
  margin: 0 12px 12px;
  gap: 10px;
}
.impito-gen-actions .ui-button {
  width: auto;
  flex: 1 1 0;
  margin: 0;
}
/* «Повторить» — полупрозрачная заливка без обводки (просьба юзера
   28.08.2026: обводку пробовали, забраковал). */
.impito-gen-actions__repeat {
  border: 0;
  background: var(--ui-accent-soft);
  color: var(--ui-accent-ink);
}
/* Под курсором подложка становится розовой, а текст оставался розовым и
   пропадал (03.09.2026, скриншот юзера с компьютера). На наведении — белый,
   как у соседней «сохранить». Только для устройств с курсором. */
@media (hover: hover) {
  .impito-gen-actions__repeat:hover {
    background: var(--ui-accent);
    color: var(--ui-accent-text);
  }
}

/* Экран карточки начинается НИЖЕ вуали, с запасом. Формула профильная, плюс
   30px: на карточке первым идёт сам кадр, без заголовка секции, который на
   других экранах и создаёт этот воздух.
   СЕЛЕКТОР ВАЖЕН. Сначала было просто `[data-page="gen"]` — специфичность
   ниже, чем у `.impito-profile-page.ui-page`, и правило не применялось вовсе
   (28.08.2026, «вверх ты нихуя не починил»). */
.impito-profile-page.ui-page[data-page="gen"] {
  padding-top: calc(
    max(
        var(--ui-fullscreen-top) * 1.5 + var(--ui-veil-platform, 0px),
        56px + var(--ui-safe-top)
      ) + 42px
  );
}

/* В карточке генерации промпт и референсы стоят ближе друг к другу, чем
   обычные секции: 24 → 12px (28.08.2026, то же расстояние, что на экране
   генерации). */
.impito-gen-prompt-section.ui-section {
  margin-bottom: 12px;
}

/* Кнопка «инфо» в правом верхнем углу кадра. В углу ЭКРАНА место занято
   плашкой баланса, поэтому подробности живут на самой картинке — как значок
   поверх фото в галерее. Стекло, а не заливка: под кнопкой произвольный кадр,
   и любая сплошная плашка на светлом снимке выглядит наклейкой. */
.impito-gen-detail__shot {
  position: relative;
  display: inline-flex;
  max-width: 100%;
}
.impito-gen-info {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  display: grid;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--ui-glass-btn);
  -webkit-backdrop-filter: blur(10px) saturate(1.3);
  backdrop-filter: blur(10px) saturate(1.3);
  box-shadow: 0 0 0 0.5px rgba(12, 18, 48, 0.16);
  color: var(--ui-text);
  cursor: pointer;
  place-items: center;
  -webkit-tap-highlight-color: transparent;
}
.impito-gen-info svg {
  width: 19px;
  height: 19px;
}
.impito-gen-info:active {
  opacity: 0.65;
}
/* У заявок без кадра рамка не inline — кнопку крепим к самой заглушке. */
.impito-gen-detail__missing {
  position: relative;
}

/* Лист сохранения: пункты крупными строками с подписью — что именно получит
   человек. Раньше это был системного вида список с «отменой» снизу, который
   выбивался из остальных листов (28.08.2026). */
.impito-save-panel__rows {
  display: flex;
  margin-top: 14px;
  flex-direction: column;
}
.impito-save-panel__option {
  display: flex;
  padding: 14px 2px;
  border: 0;
  background: transparent;
  color: var(--ui-text);
  cursor: pointer;
  flex-direction: column;
  gap: 3px;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.impito-save-panel__option + .impito-save-panel__option {
  border-top: 0.5px solid rgba(12, 18, 48, 0.12);
}
.impito-save-panel__option:active {
  opacity: 0.6;
}
.impito-save-panel__label {
  color: var(--ui-accent-strong);
  font-family: var(--ui-font);
  font-size: 17px;
  font-weight: 600;
}
.impito-save-panel__hint {
  color: var(--ui-hint);
  font-family: var(--ui-font);
  font-size: 13px;
}

/* Лист подробностей: та же стеклянная панель, что у промокода, поэтому все
   эффекты и выезд берутся оттуда. Своё здесь только содержимое. */
.impito-about-panel {
  padding-bottom: 6px;
}
.impito-about-panel__rows {
  margin-top: 14px;
}
/* Строка «название — значение». Разделитель только между строками и только под
   текстом, как в списках Apple Music: под последней его нет. */
.impito-about-panel__rows .ui-row {
  padding: 13px 2px;
}
.impito-about-panel__rows .ui-row + .ui-row {
  border-top: 0.5px solid rgba(12, 18, 48, 0.12);
}
.impito-about-panel__rows .ui-row-title {
  font-size: 16px;
}
.impito-about-panel__rows .impito-gen-detail__value {
  font-size: 16px;
  text-align: right;
}

/* Экран «все генерации»: обычный вертикальный список. Левое поле то же, что у
   полок (`--ui-hist-start`, 19px), — раньше здесь было 16px, и строки на
   экране «все видео» стояли не по той же линии, что на экране истории
   (замечание юзера 23.08.2026). Менять вместе с полками. */
.impito-hist-list {
  padding: 0 19px;
}
/* Идущие и упавшие строки тоже открываются (03.09.2026) — курсор только у
   скелета остаётся обычным. */
.impito-hist-row.is-skeleton {
  cursor: default;
}
/* ── Пейджер списка раздела (03.09.2026) ──
   Стрелки и номера в одной пилюле-подложке `--ui-fill`, как счётчик
   количества на генерации; активная страница — розовая, как выбранный
   формат. Под пилюлей — строка «страница N из M · всего K». */
.impito-hist-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin: 18px 19px 0;
}
.impito-hist-pager__pages {
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 0 4px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-fill);
}
.impito-hist-pager__page,
.impito-hist-pager__arrow {
  display: grid;
  place-items: center;
  min-width: 34px;
  height: 32px;
  padding: 0 8px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: transparent;
  color: var(--ui-text);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color 0.2s var(--ui-ease),
    color 0.2s var(--ui-ease),
    transform 0.15s var(--ui-ease);
}
.impito-hist-pager__page:active,
.impito-hist-pager__arrow:active {
  transform: scale(0.94);
}
.impito-hist-pager__page.is-active {
  background: var(--ui-accent);
  color: var(--ui-accent-text);
}
.impito-hist-pager__arrow {
  width: 40px;
  height: 40px;
  background: var(--ui-fill);
}
.impito-hist-pager__arrow svg {
  width: 9px;
  height: 15px;
}
.impito-hist-pager__arrow:disabled {
  opacity: 0.35;
  cursor: default;
  transform: none;
}
.impito-hist-pager__gap {
  min-width: 22px;
  color: var(--ui-hint);
  text-align: center;
  font-weight: 600;
}
.impito-hist-pager__meta {
  margin: 10px 0 0;
  color: var(--ui-hint);
  text-align: center;
  font-size: 13px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
/* Карточка идущей и упавшей генерации: та же заглушка, что у «файл не
   сохранён», только с крутилкой или восклицательным знаком. */
.impito-gen-detail__missing-icon .impito-hist-row__spinner {
  width: 26px;
  height: 26px;
}
/* Коробка иконки 26×26 (см. `.impito-gen-detail__missing-icon`): кегль 30
   в неё не влезал, и знак висел криво (03.09.2026, замечание юзера). */
.impito-gen-detail__missing-icon--failed {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  color: var(--ui-accent-strong);
  font-size: 22px;
  font-weight: 700;
  line-height: 1;
}
/* Текст заглушки не должен заходить под кнопку «о генерации» справа: у неё
   абсолютное положение, и длинная первая строка ложилась под неё
   (03.09.2026, поймано на карточке идущей генерации). */
.impito-gen-detail__missing .impito-gen-detail__missing-text {
  padding-right: 44px;
}
.impito-hist-row__thumb {
  position: relative;
  display: flex;
  overflow: hidden;
  width: var(--ui-hist-thumb);
  height: var(--ui-hist-thumb);
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  border-radius: 13px;
  /* Белая с розоватым оттенком, а не серая (17.08.2026). Прежний серый налёт
     поверх розовой страницы выглядел грязным пятном — та же правка, что у
     карточек на главной. */
  background: var(--ui-media-bg);
}
.impito-hist-row__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* «Фотка тёмная размытая и кружочек-индикатор» — просьба юзера. */
/* Пока генерируется — та же белая с розоватым оттенком плитка, что и пустая.
   Раньше здесь лежал розовый градиент, придавленный `brightness(0.62)`, и
   выходил тёмно-фиолетовый квадрат (17.08.2026, юзер поймал скриншотом).
   ФИЛЬТР УБРАН НАСОВСЕМ, а не подкручен: `filter` красит элемент ЦЕЛИКОМ,
   вместе с крутилкой внутри — вернёшь его, и она погаснет вслед за фоном. */
.impito-hist-row__thumb.is-running {
  background: var(--ui-media-bg);
}
/* Крутилка перекрашена вслед за плиткой: белая на белом просто не видна. */
.impito-hist-row__spinner {
  width: 19px;
  height: 19px;
  border: 2.2px solid var(--ui-accent-soft);
  border-radius: 50%;
  border-top-color: var(--ui-accent);
  animation: impito-gen-spin 0.9s linear infinite;
}
@keyframes impito-gen-spin {
  to {
    transform: rotate(360deg);
  }
}
/* Розовый и по центру (03.09.2026): у знака была высота строки шрифта, и он
   висел чуть выше середины; с line-height 1 и явным центрированием стоит
   ровно. */
.impito-hist-row__thumb.is-failed {
  display: grid;
  place-items: center;
  color: var(--ui-accent-strong);
  font-size: 22px;
  font-weight: 700;
  line-height: 1;
}
.impito-hist-row__body {
  display: flex;
  min-width: 0;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 3px;
}
/* Промпт — одной строкой с многоточием: юзер просил показывать только часть. */
.impito-hist-row__title {
  overflow: hidden;
  color: var(--ui-text);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.impito-hist-row__meta {
  overflow: hidden;
  color: var(--ui-hint);
  font-size: 12.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Красная точка «ещё не смотрел» — то же, что число на вкладке, только в
   строке. Стоит вплотную к шеврону: отрицательное поле гасит общий `gap`
   строки (12px), иначе точка висела бы посреди пустоты. У строк с ошибкой
   шеврона нет, и точка встаёт на его место — так и задумано. */
.impito-hist-row__dot {
  width: 5px;
  height: 5px;
  flex: 0 0 auto;
  border-radius: 50%;
  margin-right: calc(6px - var(--ui-hist-gap));
  background: var(--ui-destructive);
}
.impito-hist-row__after {
  display: flex;
  width: 10px;
  height: 16px;
  flex: 0 0 auto;
  color: rgba(12, 18, 48, 0.25);
}
.impito-hist-row__after svg {
  width: 10px;
  height: 16px;
}
.impito-hist-row.is-skeleton .impito-hist-row__body {
  height: 32px;
  border-radius: 10px;
  background: rgba(120, 108, 117, 0.1);
}

/* Лист выбора формата скачивания */
.impito-gen-sheet {
  position: fixed;
  z-index: 190;
  inset: 0;
}
.impito-gen-sheet__backdrop {
  position: absolute;
  background: rgba(6, 9, 20, 0.32);
  inset: 0;
}
.impito-gen-sheet__body {
  position: absolute;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 14px calc(18px + var(--ui-safe-bottom));
  border-radius: var(--ui-radius-card) var(--ui-radius-card) 0 0;
  background: var(--ui-bg);
  inset: auto 0 0 0;
  animation: impito-sheet-up var(--ui-dur, 0.22s) var(--ui-ease, ease) both;
}
@keyframes impito-sheet-up {
  from {
    transform: translateY(12%);
    opacity: 0;
  }
}
.impito-gen-sheet__group {
  display: flex;
  overflow: hidden;
  flex-direction: column;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
}
.impito-gen-sheet__index {
  padding: 10px 14px 2px;
  color: var(--ui-hint);
  font-size: 12px;
}
/* Строка листа. Раньше это была только ссылка `<a>`; с появлением отправки в
   чат часть строк стала `<button>`, и им нужен сброс — иначе браузер рисует
   свою рамку и фон. */
.impito-gen-sheet__row {
  display: flex;
  width: 100%;
  align-items: center;
  padding: 13px 14px;
  border: 0;
  background: none;
  color: var(--ui-text);
  font-family: inherit;
  font-size: 15px;
  gap: 12px;
  text-align: left;
  text-decoration: none;
}
.impito-gen-sheet__row:active {
  background: rgba(12, 18, 48, 0.05);
}
.impito-gen-sheet__icon {
  display: flex;
  width: 22px;
  height: 22px;
  color: var(--ui-accent-ink);
}
.impito-gen-sheet__icon svg {
  width: 22px;
  height: 22px;
}

/* ── Карточка одной генерации ─────────────────────────────────────────────
   Кадр во всю ширину, под ним одно главное действие, дальше параметры и
   промпт. Порядок именно такой: на этот экран приходят посмотреть результат,
   а не читать характеристики. */
/* Поля по бокам — те же 12px, что у `.ui-card`: раньше кадр и кнопка шли от
   края до края, а карточка параметров под ними была с отступом, и экран
   выглядел собранным из разных кусков. */
/* Нижнее поле задаём ЯВНО: сокращённая запись `margin: 0 12px` обнуляла
   `margin-bottom: 24px` из `.ui-section`, и кнопка прилипала к кадру. */
.impito-gen-detail__frame {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  /* Отступ до кнопок: 26 → 18px (28.08.2026). Чуть больше остальных 12px
     намеренно — кадр это главное на экране, и ему нужен воздух. */
  margin: 0 12px 18px;
}
/* Коробка подстраивается под кадр, а не кадр под коробку. Раньше стояло
   `width: 100%` + `max-height` + `object-fit: contain`: потолок высоты сжимал
   коробку, пропорция переставала совпадать с картинкой, и `contain` дорисовывал
   пустые поля по бокам — выглядело как кривая вёрстка. Теперь размеры
   ограничены сверху, но считаются по самому изображению: полей не бывает
   никогда, а вертикальный кадр не занимает пол-экрана. */
/* Тап по кадру открывает просмотр (07.09.2026) — курсор об этом говорит. */
.impito-gen-detail__image:not(.impito-gen-detail__image--empty) {
  cursor: zoom-in;
}
.impito-gen-detail__image {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 54vh;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
}
/* Заявка без файла: компактная строка вместо пустого квадрата во весь экран. */
.impito-gen-detail__missing {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 12px;
  padding: 16px 18px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
}
.impito-gen-detail__missing-icon {
  display: flex;
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  color: var(--ui-hint);
}
.impito-gen-detail__missing-icon svg {
  width: 26px;
  height: 26px;
}
.impito-gen-detail__missing-text {
  margin: 0;
  color: var(--ui-hint);
  font-size: 14px;
  line-height: 1.35;
}
/* Заглушка на время загрузки: та же серая заливка, что у скелетона строк
   истории (.impito-hist-row.is-skeleton), чтобы два состояния загрузки на
   одном экране выглядели одинаково. */
.impito-gen-detail__image.is-skeleton {
  width: 100%;
  aspect-ratio: 1;
  background: rgba(120, 108, 117, 0.1);
}
/* Точки-переключатели кадров: у заявки на несколько картинок результат один,
   а кадров много — листаем ими, а не отдельным экраном. */
.impito-gen-detail__pager {
  display: flex;
  gap: 7px;
}
.impito-gen-detail__dot {
  width: 7px;
  height: 7px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(12, 18, 48, 0.22);
  transition: background 0.18s ease, transform 0.18s ease;
}
.impito-gen-detail__dot.is-active {
  background: var(--ui-accent);
  transform: scale(1.25);
}
.impito-gen-detail__save {
  width: calc(100% - 24px);
  margin: 0 12px;
}
.impito-gen-detail__prompt.is-empty {
  color: var(--ui-hint);
}
.impito-gen-detail__value {
  color: var(--ui-hint);
  font-size: 16px;
}
/* Правый край: у заголовка секции свои 22px внутреннего поля, а у кнопки их
   не было — текст упирался в кромку экрана и обрезался. Поле повторяем, чтобы
   «промпт» и «копировать» стояли на одинаковых отступах от краёв. */
.impito-gen-detail__copy {
  margin-bottom: 9px;
  padding: 0 22px 0 10px;
  border: 0;
  background: none;
  color: var(--ui-accent-strong);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}
.impito-gen-detail__copy:active {
  opacity: 0.55;
}
/* Промпт бывает длинный (у стилей — под две тысячи знаков), поэтому переносим
   по словам и не режем: это единственное место, где юзер может его прочитать
   целиком. */
.impito-gen-detail__prompt {
  margin: 0;
  padding: 14px;
  color: var(--ui-text);
  font-size: 15px;
  line-height: 1.42;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
/* Подтверждение действия. Над таббаром, живёт около двух секунд.
   Появление и уход — ОДНОЙ анимацией на всю жизнь плашки, без переключения
   классов: переход по `opacity`, навешиваемый сразу после вставки узла, в
   вебвью не всегда успевает зарегистрировать начальное состояние и застревает
   на полупрозрачности. Keyframes такого поведения не имеют. */
.impito-gen-toast {
  position: fixed;
  z-index: 210;
  bottom: calc(96px + var(--ui-safe-bottom));
  left: 50%;
  max-width: calc(100% - 48px);
  padding: 11px 18px;
  transform: translate(-50%, 0);
  border-radius: 999px;
  background: rgba(6, 9, 20, 0.88);
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  animation: impito-toast 2.4s ease both;
  pointer-events: none;
}
@keyframes impito-toast {
  0% {
    transform: translate(-50%, 10px);
    opacity: 0;
  }
  8%,
  88% {
    transform: translate(-50%, 0);
    opacity: 1;
  }
  100% {
    transform: translate(-50%, 6px);
    opacity: 0;
  }
}

/* ── Замок мини-аппы (правила не приняты / открыто не из Telegram) ──
   Накладка кроет ВСЁ, включая таббар (z-index 80) — иначе по вкладкам можно
   было бы гулять мимо замка. Экран под ней остаётся отрендеренным: после
   принятия правил накладка просто снимается, без перезагрузки. */
.impito-gate {
  position: fixed;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  inset: 0;
  background: var(--ui-bg);
  /* Плавное появление: замок прилетает после ответа сервера, и без этого он
     возникал бы рывком поверх уже нарисованного экрана. */
  animation: impito-gate-in var(--ui-dur, 0.22s) var(--ui-ease, ease) both;
}
@keyframes impito-gate-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
.impito-gate__card {
  display: flex;
  width: 100%;
  max-width: 340px;
  flex-direction: column;
  align-items: center;
  padding: 26px 22px 22px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
  box-shadow: 0 0 0 0.5px rgba(12, 18, 48, 0.14);
  text-align: center;
}
/* Маскот Fid на пустых экранах и сообщениях (02.10.2026). Картинки с
   прозрачным фоном, поэтому одинаково ложатся на светлую и тёмную тему. */
.impito-mascot {
  display: block;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}
.impito-mascot--gate {
  width: 132px;
  height: 132px;
  margin: -8px auto 6px;
}
.impito-mascot--consent {
  width: 92px;
  height: 92px;
  margin: -6px 0 4px -6px;
}
.impito-mascot--empty {
  width: 140px;
  height: 140px;
  margin: 0 auto;
}
.impito-mascot--small {
  width: 96px;
  height: 96px;
  margin: 0 auto 6px;
}
.impito-style-empty p {
  margin: 0;
}
.impito-sidebar__mascot {
  width: 46px;
  height: 46px;
  margin-right: 6px;
  align-self: center;
}
.impito-gate__icon {
  display: flex;
  width: 54px;
  height: 54px;
  align-items: center;
  justify-content: center;
  margin-bottom: 14px;
  border-radius: 50%;
  background: rgba(36, 73, 242, 0.14);
  color: var(--ui-accent-ink);
}
.impito-gate__icon svg {
  width: 26px;
  height: 26px;
}
.impito-gate__title {
  margin: 0;
  color: var(--ui-text);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.25;
}
.impito-gate__text {
  margin: 8px 0 0;
  color: var(--ui-hint);
  font-size: 14px;
  line-height: 1.4;
}
.impito-gate__actions {
  display: flex;
  width: 100%;
  flex-direction: column;
  gap: 8px;
  margin-top: 18px;
}
/* Полная пилюля. Специфичность взята с запасом не для красоты: на главной
   действует `body.impito-home-active .ui-button` с карточным радиусом (0,2,1),
   и правило послабее проигрывало — угол читался как «полуквадрат»
   (2026-07-31, замечание юзера). */
.impito-gate .impito-gate__actions .ui-button {
  border-radius: 999px;
}
/* ── Экран принятия документов (редакция 2.0) ─────────────────────────────
   Обычный замок — короткая карточка по центру. Экран согласия длинный, и
   центрирование загоняло его верх под панель Telegram с кнопками Close/⌄/⋯.
   Поэтому здесь: прижим к верху, отступ по той же формуле, что у страниц
   приложения, и прокрутка ВСЕЙ накладки, а не карточки внутри неё —
   вложенный скролл на телефоне ловится пальцем через раз. */
/* Блочный контейнер, а НЕ флекс. Базовый `.impito-gate` — флекс-строка, и с
   `align-items: stretch` карточка растягивалась на высоту экрана вместо того,
   чтобы расти под содержимое: на экранах пониже (Samsung, 360×780) ей
   доставалось 614px при нужных 846, фон обрывался, а блок рекламы и кнопка
   вылезали наружу (01.08.2026, баг нашёл юзер). Блоку такое не грозит —
   карточка занимает столько, сколько нужно, а прокручивается сам оверлей.

   Верхний отступ: 76px — это высота шапки Telegram с кнопкой «Закрыть».
   Раньше стояло 56px, и на Android, где инсеты приходят нулевыми, заголовок
   карточки уезжал под панель. */
.impito-gate--consent {
  display: block;
  overflow-y: auto;
  padding: calc(
      max(
          var(--ui-fullscreen-top) * 1.5 + var(--ui-veil-platform, 0px),
          76px + var(--ui-safe-top)
        ) + 12px
    )
    12px calc(28px + var(--ui-safe-bottom));
  -webkit-overflow-scrolling: touch;
}
.impito-gate__card--consent {
  /* Глобального сброса box-sizing в проекте нет: без этой строки ширина 100%
     считается ПЛЮС внутренние поля, и карточка вылезала за правый край. */
  box-sizing: border-box;
  width: 100%;
  max-width: 440px;
  margin: 0 auto;
  /* Единое поле со всех сторон — блоки внутри тянутся на всю ширину, поэтому
     левый и правый край у заголовка, документов, галок и кнопки совпадают. */
  padding: 20px;
  text-align: left;
}
/* `flex-shrink: 0` обязателен: карточка — колоночный флекс, и её дети по
   умолчанию ужимаются. Блок документов с `overflow: hidden` из-за этого
   обрезался на середине второй строки. */
.impito-gate__card--consent > * {
  align-self: stretch;
  flex-shrink: 0;
}
/* Документы — строки-карточки, как настройки в аппе. Открываются ДО принятия
   (ТЗ v2.0, п. 4.5): читать можно, не давая доступа к балансу и истории. */
.impito-gate__docs {
  display: flex;
  overflow: hidden;
  flex-direction: column;
  margin-top: 16px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-white-veil);
}
.impito-gate__doc {
  display: flex;
  align-items: center;
  padding: 12px 14px;
  border: 0;
  background: none;
  gap: 12px;
  text-align: left;
}
.impito-gate__doc + .impito-gate__doc {
  box-shadow: inset 0 0.5px 0 rgba(12, 18, 48, 0.1);
}
.impito-gate__doc:active {
  background: rgba(12, 18, 48, 0.04);
}
.impito-gate__doc-icon {
  display: flex;
  width: 22px;
  height: 22px;
  flex: 0 0 auto;
  color: var(--ui-accent-ink);
}
.impito-gate__doc-icon svg {
  width: 22px;
  height: 22px;
}
.impito-gate__doc-body {
  display: flex;
  min-width: 0;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 1px;
}
.impito-gate__doc-title {
  color: var(--ui-text);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.25;
}
.impito-gate__doc-sub {
  color: var(--ui-hint);
  font-size: 12px;
}
.impito-gate__doc-chevron {
  width: 8px;
  height: 14px;
  flex: 0 0 auto;
  color: var(--ui-hint);
  opacity: 0.7;
}
/* Два обязательных пункта. Каждый — отдельная строка с отдельной галкой,
   объединять их в одну нельзя (ТЗ v2.0, п. 1.4). */
.impito-gate__checks {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 18px;
}
.impito-gate__check {
  display: flex;
  align-items: flex-start;
  padding: 0;
  border: 0;
  background: none;
  gap: 11px;
  text-align: left;
}
.impito-gate__box {
  display: grid;
  width: 22px;
  height: 22px;
  flex: 0 0 auto;
  margin-top: 1px;
  border-radius: 7px;
  background: rgba(12, 18, 48, 0.08);
  box-shadow: inset 0 0 0 1.5px rgba(12, 18, 48, 0.16);
  color: transparent;
  place-items: center;
  transition:
    background 0.16s var(--ui-ease, ease),
    box-shadow 0.16s var(--ui-ease, ease);
}
.impito-gate__box svg {
  width: 13px;
  height: 13px;
}
.impito-gate__check.is-on .impito-gate__box {
  background: var(--ui-accent);
  box-shadow: none;
  color: #fff;
}
.impito-gate__check-text {
  color: var(--ui-text);
  font-size: 14px;
  line-height: 1.4;
}
.impito-gate__check-text b {
  font-weight: 600;
}
/* Реклама — НЕобязательна и выключена по умолчанию (ТЗ v2.0, п. 1.5).
   Визуально отделена от обязательных пунктов, чтобы её не читали как третье
   условие доступа. */
.impito-gate__optional {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 18px;
  padding: 12px 14px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-white-veil);
}
.impito-gate__optional-body {
  display: flex;
  min-width: 0;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 2px;
}
.impito-gate__optional-title {
  color: var(--ui-text);
  font-size: 15px;
  font-weight: 500;
}
.impito-gate__optional-sub {
  color: var(--ui-hint);
  font-size: 12.5px;
  line-height: 1.35;
}
.impito-gate__error {
  margin: 14px 0 0;
  color: var(--ui-accent-strong);
  font-size: 13px;
  line-height: 1.35;
}
/* Кнопка неактивна, пока не стоят обе обязательные галки (ТЗ v2.0, п. 1.6). */
.impito-gate .impito-gate__actions .ui-button[disabled] {
  opacity: 0.4;
  pointer-events: none;
}
.impito-gate__support {
  margin-top: 12px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ui-hint);
  font-size: 13px;
  text-align: center;
}

/* ── Чтение документа прямо в приложении ──────────────────────────────────
   PDF внутри мини-аппы неудобен: он уводит во внешний просмотрщик и рвёт
   сценарий принятия. Поэтому текст показывается своим экраном — с шапкой,
   кнопкой возврата и обычной прокруткой. */
.impito-legal {
  display: flex;
  width: 100%;
  height: 100%;
  flex-direction: column;
  align-self: stretch;
}
.impito-legal__head {
  position: relative;
  display: flex;
  height: 46px;
  flex: 0 0 auto;
  align-items: center;
  gap: 10px;
  margin-top: calc(
    max(
      var(--ui-fullscreen-top) * 1.5 + var(--ui-veil-platform, 0px),
      56px + var(--ui-safe-top)
    ) - 24px
  );
}
.impito-legal__back {
  display: grid;
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--ui-white-veil);
  color: var(--ui-accent-strong);
  place-items: center;
}
.impito-legal__back svg {
  width: 11px;
  height: 18px;
}
.impito-legal__head-title {
  min-width: 0;
  overflow: hidden;
  color: var(--ui-text);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.impito-legal__scroll {
  overflow-y: auto;
  flex: 1 1 auto;
  margin-top: 10px;
  padding: 16px 16px calc(24px + var(--ui-safe-bottom));
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
  -webkit-overflow-scrolling: touch;
}
.impito-legal__meta {
  margin: 0 0 14px;
  color: var(--ui-hint);
  font-size: 12.5px;
  line-height: 1.35;
}
.impito-legal__h {
  margin: 20px 0 8px;
  color: var(--ui-text);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.3;
}
.impito-legal__h:first-of-type {
  margin-top: 4px;
}
.impito-legal__sub {
  margin: 16px 0 6px;
  color: var(--ui-text);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
}
.impito-legal__p {
  margin: 0 0 9px;
  color: var(--ui-text);
  font-size: 14px;
  line-height: 1.5;
}
/* Маркер рисуем псевдоэлементом, а не списком: у документа встречаются
   абзацы на несколько строк, и висячий отступ должен держаться сам. */
.impito-legal__li {
  position: relative;
  margin: 0 0 9px;
  padding-left: 16px;
  color: var(--ui-text);
  font-size: 14px;
  line-height: 1.5;
}
.impito-legal__li::before {
  position: absolute;
  top: 0;
  left: 2px;
  color: var(--ui-accent-ink);
  content: "•";
}

/* Скролл страницы под замком не нужен: он создаёт ощущение, что до контента
   всё-таки можно дотянуться. */
html.impito-gate-open,
html.impito-gate-open body {
  overflow: hidden;
}

/* ── Главная (?section отсутствует) ──
   home.js вставляет #impito-home перед #root. С 2026-07-31 чужой React-бандл
   на главной не монтируется вообще, #root пустой, поэтому вся страница — наша.
   Отсюда и нижний отступ: раньше его держала страница бандла, а у нашей стоял
   padding-bottom: 0, и без бандла последний рейл уезжал бы под таббар. */
/* Пустой #root добавлял на главной РОВНО ОДИН экран пустоты внизу: бандл сюда
   давно не монтируется, детей у него нет, а глобальный min-height: 100svh
   остался — 812 из 1257 пикселей прокрутки на iPhone уходили в никуда
   (2026-08-01, замерено). Остальные экраны — стили, профиль, генерация,
   генерации — вешают класс `impito-prompt-styles-active`, который #root
   прячет; главная была единственной, где его никто не снимал. */
body.impito-home-active #root {
  display: none;
}

body.impito-home-active .impito-home-page {
  /* Тот же вылет из-под верхней вуали, что у профиля: там живут нативные
     Back/⌄/⋯ Telegram. */
  padding-top: calc(
    max(
        var(--ui-fullscreen-top) * 1.5 + var(--ui-veil-platform, 0px),
        56px + var(--ui-safe-top)
      ) + 12px
  );
  padding-bottom: calc(116px + var(--ui-safe-bottom));
}

/* Ни карточки, ни маскота — только приветствие крупным заголовком экрана
   (2026-07-31, решение юзера). Панель с персонажем занимала четверть первого
   экрана и ничего не сообщала; теперь страница начинается с контента.
   Отступ слева тот же 22px, что у заголовков секций ниже, — заголовок и
   «генерировать» стоят на одной вертикали. */
.impito-home-hero.ui-section {
  margin: 0 0 30px;
  /* Верхний отступ от панели с «Главная»: при 2px заголовок вплотную подходил
     к её нижней кромке. */
  padding: 18px 22px 0;
}
/* 30px/700 — та же ступень, что у `.ui-page-title` на других экранах, и на
   треть крупнее заголовков секций (22px): иерархия «страница → раздел»
   держится размером, без второго цвета и без подложки. */
.impito-home-hero__hi {
  display: block;
  max-width: 100%;
  overflow: hidden;
  margin: 0;
  color: var(--ui-text);
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.1;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Имя акцентом: в строке из двух слов оно и есть смысл, «привет» — служебное. */
.impito-home-hero__name {
  color: var(--ui-accent-strong);
}

.impito-home-rail-section.ui-section {
  /* 22 → 16px: «чуть сократи расстояние между категории/новые/популярное»
     (03.09.2026). Подписи под карточками и так добавили секциям высоты. */
  margin-bottom: 16px;
}
.impito-home-rail__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  /* Под крупным заголовком нужно больше воздуха, чем под меткой 13px. */
  margin: 0 0 11px;
  padding: 0 22px;
}
/* Крупный тёмный заголовок секции в духе iOS (2026-07-31, «сверху чёрный жирный
   текст, сделай так же над карточками»): им подписаны «генерировать» и «стили».
   Серая метка 13px/510 осталась только у чужого бандла ниже — там
   это `.ui-section-header`, и его вид не трогаем.
   Класс намеренно СВОЙ, а не `.ui-section-header`: таббар ищет секции по ТЕКСТУ
   этого класса (labels «фото»/«видео» в index.html), и лишние заголовки в общем
   пуле — готовая ловушка. */
.impito-home-rail__title {
  min-width: 0;
  overflow: hidden;
  color: var(--ui-text);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Подзаголовок полки внутри раздела: «новые», «популярное». Раньше они были
   такими же крупными, как «генерировать», и читались как равные ему разделы —
   отсюда путаница (2026-07-31, просьба юзера). Теперь это мелкая серая метка,
   а вес держит общий заголовок «стили» над ними. */
.impito-home-rail__title--sub {
  color: var(--ui-section-header);
  font-size: 13px;
  font-weight: 510;
  letter-spacing: 0.02em;
}
/* Между заголовком раздела и первой полкой воздуха нужно меньше: подпись мелкая
   и иначе висит в пустоте. Сверху наоборот — отбивка от ленты «генерировать»,
   иначе «стили» прилипают к карточкам над ними (2026-07-31, просьба юзера). */
/* Отступ над заголовком задаётся ПАДДИНГОМ самого заголовка, а лента выше
   обнулена: два margin-а схлопываются в больший, и щель просто не уменьшалась
   бы правкой одного из них. */
.impito-home-rail-section.impito-home-create-section {
  margin-bottom: 0;
}
.impito-home-group.ui-section {
  margin-top: 0;
  padding-top: 12px;
  margin-bottom: 6px;
}
.impito-home-group .impito-home-rail__head {
  margin-bottom: 0;
}
.impito-home-rail__all {
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ui-accent-strong);
  cursor: pointer;
  font-family: var(--ui-font);
  /* 13 → 15px: рядом с меткой 13px размер совпадал, а рядом с заголовком 22px
     ссылка выглядела потерянной (2026-07-31, следствие смены заголовков). */
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.2;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.impito-home-rail__all:active {
  opacity: 0.6;
}
/* Ширина карточки в любом рейле: три карточки влезают целиком, четвёртая
   выглядывает на --ui-rail-peek (2026-07-31, просьба юзера). Раньше стояла
   константа 132px, и на 375px кроме трёх карточек торчал почти весь кусок
   четвёртой.
   Откуда `+ 12px`: проценты в ширине считаются от СОДЕРЖИМОГО рейла, то есть
   уже без обоих его полей по 12px. А место перед первой карточкой занимает
   только левое поле — правое возвращаем обратно. Если менять `padding` рейла,
   править и эту константу.
   Формула на всю строку: 12 (левое поле) + 3 карточки + 3 зазора + хвост
   четвёртой = ширина экрана. */
:root {
  /* ХВОСТ ДОЛЖЕН ТОРЧАТЬ ОДИНАКОВО С ОБЕИХ СТОРОН (16.08.2026, «почему
     асимметрично, сделай симметрично»). Старая формула вычитала хвост ОДИН
     раз, поэтому слева выглядывало 18px, а справа 4px — на глаз перекос.
     Замер до правки на 375px: слева 18.0, справа 4.0.

     Теперь ширина считается просто: содержимое минус внутренние зазоры,
     делённое на число карточек. Симметрию даёт не она, а ПОЛЯ РЕЙЛА: `padding`
     и `scroll-padding` с обеих сторон равны «зазор + хвост». Тогда прилипшая
     карточка встаёт на ту же отметку, от которой отсчитывается правый край, и
     хвосты выходят одинаковыми. Меняешь одно — правь и второе. */
  /* ПОЛОЖЕНИЕ В ПОКОЕ И ПРИЛИПАНИЕ — ДВЕ РАЗНЫЕ ВЕЛИЧИНЫ, И ПУТАТЬ ИХ НЕЛЬЗЯ.
     Сначала я сделал симметрию, подняв `padding` рейла до «зазор + хвост» — и
     хвосты сошлись, но в покое ВСЯ лента уехала вправо на 14px и разошлась с
     заголовками секций (16.08.2026, юзер заметил сразу).
     Правильно так: `padding` (то есть где стоит первая карточка при открытии)
     остаётся прежним — 12px, как было всегда. За симметрию отвечает
     `scroll-padding`, оно задаёт, куда карточка ПРИЛИПАЕТ при прокрутке, и на
     покой не влияет вовсе.
     Ширина карточки выводится из обоих: (ширина рейла + два поля − две точки
     прилипания − внутренние зазоры) / N. Замер: первая карточка в покое на
     12px, хвосты после прокрутки 18/18 — на 320, 375, 402 и на планшете. */
  --ui-rail-edge: 12px;
  --ui-rail-card-3up: calc(
    (
        100% + var(--ui-rail-edge, 12px) * 2 -
          (var(--ui-rail-gap, 8px) + var(--ui-rail-peek, 18px)) * 2 -
          var(--ui-rail-gap, 8px) * 2
      ) / 3
  );
  --ui-rail-card-4up: calc(
    (
        100% + var(--ui-rail-edge, 12px) * 2 -
          (var(--ui-rail-gap, 8px) + var(--ui-rail-peek, 18px)) * 2 -
          var(--ui-rail-gap, 8px) * 3
      ) / 4
  );
}
.impito-home-rail {
  /* Две ручки этого рейла, крутить только их:
     --ui-rail-gap  — зазор между карточками;
     --ui-rail-peek — ширина «хвоста» предыдущей карточки, который остаётся
                      торчать слева, когда рейл встал на карточку (2026-07-30,
                      просьба юзера «как в Apple Music»).
     Механика хвоста: `scroll-snap-align: start` прижимает левый край карточки
     не к кромке рейла, а к кромке его snapport — а её и сдвигает
     `scroll-padding-left`. Правый край предыдущей карточки оказывается на
     (padding − gap) от кромки, то есть ровно на --ui-rail-peek. Раньше
     scroll-padding был равен gap, разница выходила нулевой — и хвоста не было
     вовсе. */
  --ui-rail-gap: 8px;
  --ui-rail-peek: 18px;
  --ui-rail-card: var(--ui-rail-card-3up);
  display: flex;
  gap: var(--ui-rail-gap);
  overflow-x: auto;
  /* Боковой padding вместо margin: иначе первая и последняя карточка липнут к
     кромке экрана при скролле рейла. ЭТО И ЕСТЬ ПОЛОЖЕНИЕ В ПОКОЕ — трогать
     нельзя, лента разойдётся с заголовками секций. За симметрию хвостов
     отвечает scroll-padding ниже. */
  padding: 0 var(--ui-rail-edge);
  scrollbar-width: none;
  scroll-padding-right: calc(var(--ui-rail-gap) + var(--ui-rail-peek));
  scroll-padding-left: calc(var(--ui-rail-gap) + var(--ui-rail-peek));
  /* Именно mandatory, а не proximity: при proximity браузер прилипает только
     если остановились рядом с точкой, и хвост слева получался лотереей. */
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
}
.impito-home-rail::-webkit-scrollbar {
  display: none;
}
.impito-home-rail__card {
  width: var(--ui-rail-card);
  flex: 0 0 auto;
  scroll-snap-align: start;
}

/* ── Витрина каталога по категориям (вкладка «все») ──
   2026-07-31, просьба юзера: вместо сплошной кучи карточек — полка на каждую
   тему, заголовок жирным с шевроном (тап = открыть категорию целиком), внутри
   ДВА ряда карточек с горизонтальным листанием.
   Полка живёт по тем же правилам, что рейлы главной (зазор, хвост предыдущей
   карточки, привязка) — отличие одно: раскладка не в строку, а в колонки по
   два ряда. */
.impito-cat-section {
  margin-bottom: 26px;
}
.impito-cat-rail__head {
  display: flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  margin: 0 0 11px;
  padding: 0 22px;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-cat-rail__head:active {
  opacity: 0.6;
}
.impito-cat-rail__title {
  min-width: 0;
  overflow: hidden;
  color: var(--ui-text);
  font-family: var(--ui-font);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Шеврон приглушён и мельче заголовка — как в iOS: он подсказка «тут есть
   продолжение», а не самостоятельная кнопка. */
.impito-cat-rail__chevron {
  width: 11px;
  height: 18px;
  flex: 0 0 auto;
  margin-top: 1px;
  color: var(--ui-hint);
}
.impito-cat-rail {
  /* Ручки те же, что у рейлов главной. */
  --ui-rail-gap: 8px;
  --ui-rail-peek: 18px;
  --ui-rail-card: var(--ui-rail-card-3up);
  display: grid;
  /* Два ряда, поток по колонкам: карточки заполняют сначала верх и низ одной
     колонки, потом следующую. Именно grid, а не flex-wrap — wrap в
     горизонтальном скроллере переносит по ширине вьюпорта, а не по двум рядам. */
  grid-auto-columns: var(--ui-rail-card);
  grid-auto-flow: column;
  grid-template-rows: repeat(2, auto);
  gap: var(--ui-rail-gap);
  overflow-x: auto;
  /* Поля те же, что у рейла главной: положение в покое, не симметрия. */
  padding: 0 var(--ui-rail-edge);
  scrollbar-width: none;
  scroll-padding-right: calc(var(--ui-rail-gap) + var(--ui-rail-peek));
  scroll-padding-left: calc(var(--ui-rail-gap) + var(--ui-rail-peek));
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
}
/* Короткие подборки (до 4 карточек) — один ряд: два ряда из трёх карточек дают
   полторы колонки и выглядят обрубком. */
.impito-cat-rail--single {
  grid-template-rows: auto;
}
.impito-cat-rail::-webkit-scrollbar {
  display: none;
}
.impito-cat-rail .impito-style-card {
  /* Ширину задаёт колонка сетки — карточка просто занимает её целиком. */
  width: 100%;
  scroll-snap-align: start;
}
/* Карточка узкая (132px против 171px в сетке) — подписи на шаг мельче, иначе
   название в два клампа съедает половину картинки. Те же значения, что у
   рейлов главной. */
.impito-cat-rail .impito-style-card__overlay {
  padding: 28px 11px 10px;
}
.impito-cat-rail .impito-style-card__name {
  font-size: 14px;
}
/* Кикер тут выключен: в подборке категории он повторял бы её название на каждой
   из 12 карточек, прямо под заголовком с этим же словом. На главной кикер
   остаётся — там подборки смешанные, и категория действительно что-то говорит. */
.impito-cat-rail .impito-style-card__kicker {
  display: none;
}
/* Единый радиус на главной (2026-07-30, «одинаковый радиус везде, включая
   кнопки, как у менюшки настроек»). Карточки, плитки и герой уже жили на
   --ui-radius-card (22px) — из общего ряда выбивалась только кнопка. Правило
   ограничено главным экраном: на остальных экранах кнопки-пилюли остаются.
   ВАЖНО про геометрию: у кнопки высота 40px, а браузер обрезает радиус до
   половины меньшей стороны — то есть рисует 20px. Разница с пилюлей на такой
   высоте почти незаметна; чтобы угол читался как у карточки, кнопку пришлось бы
   делать выше, а этого юзер не просил. */
body.impito-home-active .ui-button {
  border-radius: var(--ui-radius-card);
}
.impito-home-rail__card .impito-style-card__overlay {
  padding: 28px 11px 10px;
}
/* Рейл «генерировать»: названия — одиночные слова, переносить их некуда, а
   самое длинное («реставрация») на 14px не влезало в карточку 103px и
   обрезалось. Замерено: 14px → 99px текста, 13px → 92px, 12px → 85px при 87px
   поля (это уже с урезанным боковым padding). Отсюда 12px + padding 8px —
   меньше не нужно, больше не влезает. */
.impito-home-create .impito-style-card__overlay {
  padding-right: 8px;
  padding-left: 8px;
}
.impito-home-create .impito-style-card__name {
  font-size: 12px;
}
/* Карточка рейла узкая (132px против 171px в каталоге) — заголовок и кикер на
   шаг мельче, иначе название в два клампа занимает половину карточки. */
.impito-home-rail__card .impito-style-card__name {
  font-size: 14px;
}
.impito-home-rail__card .impito-style-card__kicker {
  font-size: 11px;
}

/* ── КАРТОЧКИ ГЛАВНОЙ: ТЕКСТ ПОД ФОТО (03.09.2026, выбор юзера по макету) ──
   Раньше название лежало на фото под тёмным градиентом — на розовом фоне
   карточки читались как чёрные прямоугольники. Теперь карточка — колонка:
   сверху чистое фото 3:4 со скруглением, под ним кикер и название нашими
   цветами. У фото лёгкая розовая тонировка (multiply), чтобы пёстрые превью
   не спорили с палитрой; у плиток с маскотом (`--art`) тонировки нет — они и
   так в палитре. Плитки «генерировать» не тронуты: у них своя разметка. */
.impito-home-card.impito-style-card {
  display: flex;
  flex-direction: column;
  aspect-ratio: auto;
  overflow: visible;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  text-align: left;
}
.impito-home-card__shot {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border-radius: var(--ui-radius-card);
  background: var(--ui-media-bg);
  box-shadow: inset 0 0 0 0.5px var(--ui-media-ring);
}
.impito-home-card__shot .impito-style-card__image {
  filter: saturate(0.9) contrast(0.98);
}
.impito-home-card__shot::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(36, 73, 242, 0.16);
  mix-blend-mode: multiply;
  pointer-events: none;
}
.impito-home-card--art .impito-home-card__shot .impito-style-card__image {
  filter: none;
}
.impito-home-card--art .impito-home-card__shot::after {
  display: none;
}
.impito-home-card__caption {
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* Слева 2 → 8px: «текст чуть правее относительно карточки» (03.09.2026). */
  padding: 7px 2px 0 8px;
  min-width: 0;
}
.impito-home-card__kicker {
  overflow: hidden;
  color: var(--ui-hint);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.impito-home-card__name {
  display: -webkit-box;
  overflow: hidden;
  color: var(--ui-text);
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.18;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
/* У категорий название стоит первым, счётчик под ним. */
.impito-home-card__name + .impito-home-card__kicker {
  margin-top: 1px;
}
.impito-home-card:active .impito-home-card__shot {
  transform: scale(0.97);
  transition: transform 0.15s var(--ui-ease);
}
/* Те же карточки в каталоге стилей и у плиток «генерировать» (03.09.2026,
   просьба юзера «сделай то же самое и во вкладке стили»). В подборке
   категории кикер спрятан, как и раньше: он повторял бы название категории
   под её же заголовком. В сетке каталога карточка шире — шрифт на шаг крупнее.
   У плиток «генерировать» одно слово — без клампа на две строки. */
.impito-cat-rail .impito-home-card__kicker {
  display: none;
}
.impito-style-grid .impito-home-card__name {
  font-size: 15px;
}
/* Рейл «генерировать» — прокручиваемый контейнер, а прокрутка режет всё, что
   выходит за его высоту хотя бы на долю пикселя. Высота плитки дробная
   (3:4 от ширины колонки), и нижняя кромка со скруглением попадала под нож
   (03.09.2026, «дно чуть-чуть обрезается»). Запас в 2px снизу, а отступ
   секции уменьшен на те же 2px — ритм не меняется. */
.impito-home-rail.impito-home-create {
  padding-bottom: 2px;
  margin-bottom: -2px;
}
/* Плитки «генерировать»: слово внутри плитки, белым, по центру нижнего края.
   Лёгкая тень — только чтобы буквы не растворялись на светлом участке, если
   картинка окажется светлее обычного. */
.impito-home-create .impito-home-card__label {
  position: absolute;
  right: 6px;
  bottom: 11px;
  left: 6px;
  overflow: hidden;
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.01em;
  line-height: 1.1;
  text-align: center;
  text-overflow: ellipsis;
  text-shadow: 0 1px 2px rgba(12, 18, 48, 0.2);
  white-space: nowrap;
  pointer-events: none;
}

/* ── Плашка с токенами в правом нижнем углу верхней вуали ──
   Живёт на всех экранах: вуаль общая, и баланс логично видеть везде.
   Прижата к НИЗУ вуали через --ui-veil-height, а не к safe-top: сверху там
   нативные кнопки Telegram (Close / ⌄ / ⋯) и заголовок экрана, плашка обязана
   оставаться под ними при любой высоте панели.
   Обводки нет намеренно (просьба юзера) — только полупрозрачная заливка и
   размытие. Свой backdrop-filter поверх вуали даёт второй фильтрованный слой,
   но он крошечный и статичный, в отличие от масок внутри едущей пилюли. */
/* Метрики сняты с нативной кнопки Telegram (⌄ ⋯) по скриншотам юзера (375pt,
   3x): ширина ≈ 74px, высота ≈ 30px, правый отступ ≈ 15px (не 12). Юзер
   сравнил вживую и сказал «длиннее и чуть уже» — плашка была 32px высотой и
   ~57px шириной, то есть на 2px выше и заметно короче кнопки. Отсюда
   `min-width` под ширину кнопки и высота 30px. */
.impito-token-pill {
  position: fixed;
  /* Отсчёт от кромки пропорциональной части вуали (= низ вуали минус
     добавленная полоса), минус подъём. Внизу под плашкой остаётся 4px вуали:
     22px полосы = 18px плашки, вылезшей ниже кромки, плюс просвет. */
  top: calc(
    var(--ui-veil-height) - var(--ui-veil-pill-row) - var(--ui-veil-pill-lift)
  );
  right: 16px;
  /* Выше вуали (40) и заголовка (60), ниже таббара (80). */
  z-index: 61;
  display: inline-flex;
  align-items: center;
  /* В потоке остаётся ТОЛЬКО число — монета и плюс выведены из потока и висят у
     кромок. За счёт этого и симметричных полей центр числа совпадает с центром
     плашки при любом значении (просьба юзера: «цифра ровно по центру панели»),
     а не центр группы «монета + число». */
  justify-content: center;
  /* min-width, а не width: с четырёхзначным балансом плашка должна растягиваться,
     а не обрезать цифры. 74 → 72px (2026-07-30, «короче на 2px») — на 2px уже
     нативной кнопки. */
  min-width: 72px;
  /* 30 → 28 → 29px (2026-07-30, «узже на 2px», затем «шире на 1px»). В словаре
     юзера «длиннее/короче» — это ширина, «шире/узже» — высота. */
  height: 29px;
  /* Поля СИММЕТРИЧНЫЕ и равны зоне монеты/плюса: только так центр числа
     совпадает с центром плашки и при этом число не может залезть ни на монету,
     ни на плюс — они оба вне потока и ширину не занимают. Растёт плашка тоже
     симметрично, число остаётся в центре. Значение = отступ фланга (7px) + его
     бокс (18px) + просвет 3px. На короткие значения не влияет: там ширину
     держит min-width. */
  padding: 0 28px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  /* Темнее (просьба юзера): было rgba(255,255,255,0.42) — почти белая плашка.
     Теперь тёмная подложка цветом текста на малой альфе: поверх розовой вуали
     это даёт тот же приглушённый мокко-тон, что у нативной кнопки.
     Альфа: 0.10 → 0.12 («чуть темнее») → 0.08 («светлее на 4%») → 0.10
     («темнее на 2%», 2026-07-30). Считается не на глаз, а через композит поверх
     розовой вуали по красному каналу `247*(1-a) + 43*a`: при 0.08 это 231,
     −2% = 226.4, обратная подстановка даёт a ≈ 0.101. Заодно это ровно +2 пункта
     альфы — оба чтения «на N процентов» сходятся. Это ручка тона. */
  /* 0.10 → 0.11 → 0.13 (04.09.2026, просьбы юзера). Токен: в тёмной теме
     подложка светлая, иначе плашка сливается с вуалью. */
  background: var(--ui-pill-bg);
  /* Блюр 6 → 18px (2026-07-30, «сильнее в 3 раза»). На самой вуали разница
     сдержанная — её подложка и так 80% и уже размыта; сильнее это читается там,
     где под плашкой едет контент (шапка каталога, карточки под ней). */
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  backdrop-filter: blur(18px) saturate(140%);
  font-family: var(--ui-font);
  font-size: 14.5px;
  font-weight: 650;
  letter-spacing: -0.01em;
  line-height: 1;
  white-space: nowrap;
  /* Тап ведёт в магазин (просьба юзера 2026-07-30), поэтому плашка кликабельна.
     До этого стояло pointer-events: none, чтобы не перехватывать тапы у
     нативных кнопок Telegram — сейчас от них 8px зазора и она ниже, так что
     риск только визуальной близости. */
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* `top` здесь обязателен. Он считается от высоты вуали, а та меняется при
     смене режима шапки — без перехода пилюли телепортировались на новое место,
     пока панель ехала плавно (31.08.2026, замечание юзера: «кнопка баланса и
     имя появляются резко, а панель при этом двигается»). 150мс — столько же,
     сколько длится смена экрана в роутере. */
  transition:
    opacity 150ms var(--ui-ease),
    transform 150ms var(--ui-ease),
    top 150ms var(--ui-ease);
}
.impito-token-pill:active,
.impito-profile-pill:active {
  transform: scale(0.94);
}
/* Монета и плюс — оба вне потока, оба центрированы по вертикали одинаково
   (top: 50% + translateY), поэтому лежат на одном уровне с числом и друг с
   другом. Это иконки, а не глифы: у SVG нет расхождения между базовой линией и
   математической осью, из-за которого текстовый «+» казался выше цифры. */
.impito-token-pill__coin,
.impito-token-pill__plus {
  position: absolute;
  top: 50%;
  display: block;
  transform: translateY(-50%);
}
/* Одинаковые боксы и одинаковые отступы от кромок — иначе воздух слева до
   монеты и справа до плюса разъезжается. Оба SVG нарисованы так, чтобы ink
   заполнял свой viewBox почти целиком, поэтому равные отступы дают равный
   визуальный воздух. */
.impito-token-pill__coin,
.impito-token-pill__plus {
  width: 18px;
  height: 18px;
}
.impito-token-pill__coin {
  left: 7px;
  /* 04.09.2026: вернули серый (см. число). */
  color: var(--ui-pill-ink-soft);
}
.impito-token-pill__plus {
  right: 7px;
  /* Акцент — тот же цвет, что у кнопки «пополнить» (.ui-button). Заливка кружка
     идёт через fill="currentColor" внутри svg. */
  color: var(--ui-accent-ink);
}
.impito-token-pill__coin svg,
.impito-token-pill__plus svg {
  display: block;
  width: 100%;
  height: 100%;
}
.impito-token-pill__value {
  /* Серый вместо --ui-text; альфа 0.58 (--ui-hint) → 0.55 (2026-07-30,
     «светлее на 5%»): композит текста поверх плашки по красному каналу
     227*(1-a) + 43*a при 0.58 даёт 120, +5% = 126, обратная подстановка даёт
     a ≈ 0.548. Это ручка яркости текста. */
  /* 04.09.2026: число было белым, вечером вернули серый как раньше (просьба
     юзера «сделай серый как был»). */
  color: var(--ui-pill-ink);
  font-variant-numeric: tabular-nums;
}

/* ── Пилюля профиля слева на верхней вуали ──
   Аватар 32px + имя, тап ведёт в профиль. Стоит на одном уровне с плашкой
   баланса: вертикальные центры выровнены, поэтому у неё свой сдвиг −1.5px
   (высота 32 против 29 у плашки баланса). Подложка, размытие и радиус — те же,
   чтобы читались как одна пара элементов. */
.impito-profile-pill {
  position: fixed;
  /* +0.5px, чтобы вертикальный центр совпал с плашкой баланса: у неё высота 29,
     здесь 28. */
  top: calc(
    var(--ui-veil-height) - var(--ui-veil-pill-row) - var(--ui-veil-pill-lift) +
      0.5px
  );
  /* Левый край выровнен по нативной кнопке Close над ним: при 16px аватар стоял
     на 2–3px левее неё (замечено юзером на устройстве). Поля нет, поэтому
     `left` — это сразу левая кромка аватара. */
  left: 19px;
  z-index: 61;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 46%;
  /* Высота больше визуального контента (аватар 16px): бокс держит комфортную
     цель тапа, а подложки у него нет. */
  height: 28px;
  padding: 0;
  border: 0;
  /* Ни подложки, ни размытия, ни обводки — только аватар и имя (просьба юзера). */
  background: transparent;
  cursor: pointer;
  font-family: var(--ui-font);
  -webkit-tap-highlight-color: transparent;
  /* `top` здесь обязателен. Он считается от высоты вуали, а та меняется при
     смене режима шапки — без перехода пилюли телепортировались на новое место,
     пока панель ехала плавно (31.08.2026, замечание юзера: «кнопка баланса и
     имя появляются резко, а панель при этом двигается»). 150мс — столько же,
     сколько длится смена экрана в роутере. */
  transition:
    opacity 150ms var(--ui-ease),
    transform 150ms var(--ui-ease),
    top 150ms var(--ui-ease);
}
.impito-profile-pill__avatar {
  position: relative;
  overflow: hidden;
  /* 32 → 16px (просьба юзера «в 2 раза меньше»). */
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--ui-fill-2);
}
.impito-profile-pill__avatar img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.impito-profile-pill__avatar.is-fallback {
  display: grid;
  place-items: center;
  background: var(--ui-accent-soft);
  color: var(--ui-accent-strong);
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
}
.impito-profile-pill__name {
  /* Цвет ниже — токен плашек: в тёмной теме имя почти белое, иначе не читалось. */
  min-width: 0;
  overflow: hidden;
  color: var(--ui-pill-ink);
  font-size: 14.5px;
  font-weight: 650;
  letter-spacing: -0.01em;
  line-height: 1;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Схлопывание верхней панели при скролле вниз ──
   Класс ставит скролл-слушатель в index.html. Идея: вниз — панель возвращается
   в состояние «как было до плашки баланса и профиля», обе пилюли растворяются;
   вверх (и на самом верху) — возвращаются.
   Механика: обнуляется ТОЛЬКО добавленная полоса --ui-veil-pill-row, а
   пропорциональная часть вуали не трогается. За счёт этого схлопнутая панель
   байт-в-байт равна прежней, а `top` у пилюль (veil − row − lift) не меняется:
   они гаснут на месте, без рывка. Анимируется height у body:before — переход
   разовый, на переключение состояния, а не на каждый кадр скролла. */
html.impito-topbar-collapsed {
  --ui-veil-pill-row: 0px;
}
body:before {
  /* Та же длительность, что у пилюль: панель и то, что на ней лежит, обязаны
     двигаться одним движением. */
  transition: height 150ms var(--ui-ease);
}
html.impito-topbar-collapsed .impito-token-pill,
html.impito-topbar-collapsed .impito-profile-pill,
/* Профиль и магазин: там аватар с балансом есть в самом экране, пилюли сверху
   не нужны. Раньше их гасил js через `display: none` — то есть мгновенно, без
   всякого перехода, хотя панель под ними ехала плавно. Теперь тот же путь, что
   у схлопнутой шапки: гаснут и уходят вверх вместе с панелью. */
html.impito-topbar-plain .impito-token-pill,
html.impito-topbar-plain .impito-profile-pill {
  opacity: 0;
  /* Небольшой подъём заодно: пилюли «испаряются» вверх, к панели. */
  transform: translateY(-4px);
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  body:before,
  .impito-style-sticky,
  .impito-token-pill,
  .impito-profile-pill {
    transition: none;
  }
}
/* ── Первый кадр: панель не «выезжает» ──
   Вся геометрия вуали считается от --ui-fullscreen-top, а его выставляет js уже
   ПОСЛЕ первой отрисовки: модули грузятся как type="module" (то есть отложенно),
   да и сами инсеты Telegram отдаёт асинхронно, отдельными событиями. До этого
   момента переменная равна 0, вуаль вырождена в тонкую полоску, и когда
   приходит настоящий инсет, `transition: height` честно анимирует рост — панель
   выезжала сверху вниз при каждом заходе на экран (2026-07-30, видео с
   устройства).
   Класс `impito-boot` ставится в <head> ДО первого кадра и снимается скриптом в
   index.html, когда высота панели перестала меняться. Внутри класса нет ничего,
   кроме подмены переходов: раскладка не трогается, поэтому на готовом экране
   поведение прежнее.
   Переходы не выключены совсем, а сведены к одному `opacity`. Так высота и
   поля в это время меняются МГНОВЕННО (панель не едет), но остаётся чем
   проявить её целиком — см. `impito-panel-hold` ниже. */
html.impito-boot body:before,
html.impito-boot .impito-style-sticky,
html.impito-boot .impito-token-pill,
html.impito-boot .impito-profile-pill,
html.impito-boot .impito-profile-heading {
  transition: opacity 0.24s var(--ui-ease);
}
@media (prefers-reduced-motion: reduce) {
  /* Должно стоять ПОСЛЕ правила выше: специфичность равная, решает порядок. */
  html.impito-boot body:before,
  html.impito-boot .impito-style-sticky,
  html.impito-boot .impito-token-pill,
  html.impito-boot .impito-profile-pill,
  html.impito-boot .impito-profile-heading {
    transition: none;
  }
}
/* ── Панель проявляется целиком, а не по кускам ──
   Стекло вуали рисуется из css сразу, а заголовок, поиск и чипсы монтирует js
   уже после загрузки модулей. Получалась лесенка: сначала пустая панель, через
   мгновение в ней появлялся текст (2026-07-30, «сначала панель загрузилась,
   потом текст по центру — не гармонично»).
   Поэтому СОДЕРЖИМОЕ панели держится прозрачным, пока оно не готово, и
   проявляется одним движением. Класс снимает скрипт в index.html, когда в DOM
   появился заголовок экрана И высота панели устоялась.
   САМО СТЕКЛО В ЭТОТ СПИСОК НЕ ВХОДИТ, И ЭТО ПРИНЦИПИАЛЬНО. Первая версия
   держала прозрачной и вуаль тоже — тогда сквозь пустое место просвечивал
   контент страницы, и юзер увидел «текст за панелью при анимации прогрузки».
   Вуаль (`body:before`) и шапка каталога (`.impito-style-sticky`) — это и есть
   подложка, она обязана быть на месте с первого кадра. Шапка каталога вдобавок
   монтируется вместе со своим содержимым, одним куском, — прятать её незачем.
   Именно opacity, а не visibility/display: элементы всё это время занимают своё
   место, поэтому проявление ничего не двигает. */
html.impito-panel-hold .impito-profile-heading,
html.impito-panel-hold .impito-token-pill,
html.impito-panel-hold .impito-profile-pill {
  opacity: 0;
}
/* Экран профиля — панель классическая: ни пилюль сверху (их там не создаёт
   скрипт), ни добавленной полосы под них. Класс ставится в index.html по
   ?section=profile. */
html.impito-topbar-plain {
  --ui-veil-pill-row: 0px;
}
/* Схлопнутая шапка каталога подтягивается ВЫШЕ низа вуали, а не на 8px ниже:
   в этом состоянии пилюль нет, и запас под них превращался в пустую полосу
   между нативными кнопками и поиском (2026-07-30, «там пиздец места есть»).
   `−14px` возвращает поиск примерно к исходному `56px + safe-top` — значению,
   с которым экран жил до появления пилюль; max() не даёт уехать выше него. */
html.impito-topbar-collapsed .impito-style-sticky {
  padding-top: max(
    calc(56px + var(--ui-safe-top)),
    calc(var(--ui-veil-height) - 14px)
  );
}

/* На Android (флаг data-font-platform="inter", ставится в <head> по
   Telegram.WebApp.platform / UA) нативные кнопки Telegram стоят ближе к правой
   кромке, чем на iOS. Из-за этого плашка баланса, подогнанная по iOS-метрикам
   (right: 16px), уходила левее кнопки ⌄⋯ над ней. Сдвиг ровно на 4px вправо,
   iOS не затронут. Это отдельная ручка: если разъедется на другом Android —
   крутить только её. */
html[data-font-platform="inter"] .impito-token-pill {
  /* 16 → 12 → 8px: после первого сдвига юзер сказал «маловато», добавили ещё 4px. */
  right: 8px;
}

/* ── Telegram Desktop: нативных инсетов нет ──
   На десктопе кнопки Close/⋯ живут в хроме окна Telegram, ВНЕ вебвью, и
   `--ui-fullscreen-top` равен 0. Пропорциональная часть вуали от него и
   считается, поэтому вырождалась в 0: панель оставалась высотой в одну
   добавленную полосу (22px), пилюли уезжали на `top: -15px` за верхнюю кромку,
   а заголовок экрана оставался без подложки прямо над контентом.
   Класс ставит скрипт в index.html, когда инсет нулевой. Мобильные значения
   при этом не затронуты вообще — правило живёт только в этом режиме.
   Числа: база 34px + полоса 22px = вуаль 56px; подъём 22px даёт пилюлям
   top 12px и низ 41px, то есть они внутри вуали, а заголовок (11..34) накрыт. */
html.impito-flat-top {
  /* База 34 → 45px: в СЖАТОМ состоянии вуаль равна ровно базе, а заголовок
     экрана занимает 11..34, то есть сверху оставалось 11px, а снизу 0 — панель
     выглядела обрезанной по тексту (2026-07-30, замечено на компе). 45 = 34 + 11
     даёт симметричные 11px сверху и снизу.
     Подъём 22 → 33px компенсирует это ровно настолько, чтобы пилюли остались на
     прежнем месте: их top = база − подъём = 12px, как и было. */
  --ui-veil-base: 45px;
  --ui-veil-pill-lift: 33px;
}
/* Полоса под пилюли на десктопе уже: 11px вместо 22. Так развёрнутая панель
   остаётся прежней высоты (45 + 11 = 56), а сжимается на меньшую величину.
   Оба `:not()` обязательны: правила схлопывания и классической панели
   (`--ui-veil-pill-row: 0`) стоят ВЫШЕ по файлу, и без исключений это правило
   перебивало бы их по специфичности — на компе панель перестала бы сжиматься,
   а в магазине и профиле оставалась бы полоса под несуществующие пилюли. */
html.impito-flat-top:not(.impito-topbar-collapsed):not(.impito-topbar-plain) {
  --ui-veil-pill-row: 11px;
}

/* Лист «не хватает токенов» и ошибки генерации — на той же основе, что лист
   скачивания в истории. */
.impito-balance-sheet__title {
  margin: 0;
  padding: 16px 16px 4px;
  color: var(--ui-text);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-align: center;
}
.impito-balance-sheet__sub {
  margin: 0;
  padding: 0 16px 16px;
  color: var(--ui-hint);
  font-size: 14px;
  line-height: 1.35;
  text-align: center;
}

/* ── Панель администратора ──
   Тот же язык, что у остальных экранов: карточки, строки, свитчи. */
.impito-admin__loading {
  padding: 24px 16px;
  color: var(--ui-hint);
  font-size: 14px;
  text-align: center;
}
.impito-admin-stat {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 11px 14px;
  gap: 12px;
}
.impito-admin-stat + .impito-admin-stat {
  border-top: 0.5px solid rgba(12, 18, 48, 0.08);
}
.impito-admin-stat--stack {
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
}
.impito-admin-stat__label {
  color: var(--ui-hint);
  font-size: 14px;
}
.impito-admin-stat__value {
  color: var(--ui-text);
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.impito-admin-stat__error {
  color: var(--ui-text);
  font-size: 12.5px;
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.impito-admin-form {
  display: flex;
  flex-direction: column;
  padding: 14px;
  gap: 10px;
}
.impito-admin-form__row {
  display: flex;
  gap: 8px;
}
.impito-admin-input {
  width: 100%;
  padding: 11px 12px;
  border: 0;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.72);
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.12);
  color: var(--ui-text);
  font-family: var(--ui-font);
  font-size: 15px;
}
.impito-admin-input:focus {
  outline: none;
  box-shadow: inset 0 0 0 1px var(--ui-accent);
}
.impito-admin-input--area {
  resize: none;
}
.impito-admin-hint {
  margin: 0;
  color: var(--ui-hint);
  font-size: 12.5px;
  line-height: 1.35;
}
/* Цены моделей. Название слева, узкое поле справа: строк полтора десятка, и
   поле во всю ширину растянуло бы список на два экрана. Изменённая строка
   подсвечивается — иначе перед нажатием «сохранить» не видно, что уедет. */
.impito-admin-price {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.impito-admin-price__label {
  color: var(--ui-text);
  font-size: 15px;
}
.impito-admin-price .impito-admin-input {
  flex: 0 0 auto;
  width: 86px;
  padding: 8px 10px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.impito-admin-price .impito-admin-input.is-changed {
  box-shadow: inset 0 0 0 1px var(--ui-accent);
}
/* История рассылок. Карточка на запись: дата и тип сверху, текст посередине,
   счётчики и действие снизу. Текст в одну строку с многоточием — превью
   хранится обрезанным до 300 символов, и разворачивать тут нечего. */
.impito-admin-bc + .impito-admin-bc {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 0.5px solid rgba(12, 18, 48, 0.08);
}
.impito-admin-bc__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.impito-admin-bc__when {
  color: var(--ui-text);
  font-size: 15px;
  font-weight: 600;
}
.impito-admin-bc__kind {
  color: var(--ui-hint);
  font-size: 12.5px;
}
.impito-admin-bc__text {
  margin: 4px 0 8px;
  color: var(--ui-hint);
  font-size: 13px;
  line-height: 1.35;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
.impito-admin-bc__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.impito-admin-bc__foot .ui-button {
  flex: 0 0 auto;
  padding: 7px 14px;
  font-size: 13px;
}
.impito-admin-hint--audience {
  margin-top: -2px;
}

/* Переключатель аудитории. Два состояния, между ними пропасть по смыслу:
   «всем» — сервисное, «по согласию» — рекламное. Поэтому не выпадающий
   список, а видимый выбор с числами получателей. */
.impito-admin-seg {
  display: flex;
  padding: 3px;
  border-radius: 14px;
  background: rgba(12, 18, 48, 0.06);
  gap: 3px;
}
.impito-admin-seg__item {
  display: flex;
  flex: 1 1 0;
  align-items: center;
  justify-content: center;
  padding: 9px 8px;
  border: 0;
  border-radius: 11px;
  background: transparent;
  color: var(--ui-hint);
  font-family: var(--ui-font);
  font-size: 14px;
  font-weight: 600;
  gap: 6px;
  transition:
    background var(--ui-dur) var(--ui-ease),
    color var(--ui-dur) var(--ui-ease);
}
.impito-admin-seg__item.is-active {
  background: var(--ui-card);
  box-shadow: 0 1px 3px rgba(12, 18, 48, 0.12);
  color: var(--ui-text);
}
.impito-admin-seg__count {
  color: var(--ui-hint);
  font-size: 12.5px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.impito-admin-seg__item.is-active .impito-admin-seg__count {
  color: var(--ui-accent-ink);
}

/* Панель оформления. Кнопки квадратные и одинаковые: они читаются как один
   инструмент, а не как разрозненные действия. */
/* Сетка, а не флекс: при флексе десятая кнопка уезжала на вторую строку одна,
   и панель читалась как сломанная. Колонки тянутся по ширине карточки. */
.impito-admin-tools {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(30px, 1fr));
  gap: 5px;
}
.impito-admin-tool {
  display: grid;
  width: 100%;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.72);
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.12);
  color: var(--ui-text);
  font-family: var(--ui-font);
  font-size: 15px;
  place-items: center;
  transition: background var(--ui-dur) var(--ui-ease);
}
.impito-admin-tool:active {
  background: var(--ui-accent-soft, rgba(51, 84, 214, 0.14));
}

/* Предпросмотр. Показывает ровно те теги, что уйдут в Telegram — чтобы
   «жирный + курсив» проверялся глазами до отправки, а не после. */
.impito-admin-preview {
  padding: 11px 12px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.55);
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.1);
}
.impito-admin-preview__label {
  display: block;
  margin-bottom: 5px;
  color: var(--ui-hint);
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.impito-admin-preview__body {
  color: var(--ui-text);
  font-size: 15px;
  line-height: 1.4;
  overflow-wrap: anywhere;
}
.impito-admin-preview__body code,
.impito-admin-preview__body pre {
  padding: 1px 4px;
  border-radius: 6px;
  background: rgba(12, 18, 48, 0.08);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13.5px;
}
.impito-admin-preview__body pre {
  display: block;
  margin: 6px 0;
  padding: 8px 10px;
  white-space: pre-wrap;
}
.impito-admin-preview__body blockquote {
  margin: 6px 0;
  padding-left: 10px;
  border-left: 3px solid var(--ui-accent);
}
.impito-admin-preview__link {
  color: var(--ui-accent-ink);
  text-decoration: underline;
}
/* Скрытый текст: в Telegram он закрашен до нажатия — так и показываем. */
.impito-admin-preview__spoiler {
  border-radius: 4px;
  background: rgba(12, 18, 48, 0.55);
  color: transparent;
}

.impito-gate__diag {
  margin: 10px 0 0;
  color: var(--ui-hint);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  opacity: 0.7;
}

/* Лист «платёж создан»: тот же лист, что у выбора модели, только с текстом. */
.impito-pay-sheet__title {
  margin: 0;
  padding: 16px 18px 4px;
  color: var(--ui-text);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-align: center;
}
.impito-pay-sheet__text {
  margin: 0;
  padding: 0 18px 16px;
  color: var(--ui-hint);
  font-size: 14px;
  line-height: 1.35;
  text-align: center;
}


/* ── ПЛАНШЕТЫ ──────────────────────────────────────────────────────────────
   Вся вёрстка выше писалась под телефон: колонка страницы 560px, рейлы по три
   карточки, панели с потолком 504px. На планшете это выглядело брошенным —
   узкая полоса содержимого посередине и по 230px розовой пустоты с каждой
   стороны, а нижняя панель на фоне этой полосы читалась как «овер вытянутая»
   (12.08.2026, скриншот юзера с айпада).

   ЧТО ДЕЛАЕМ И ЧЕГО НЕ ДЕЛАЕМ. Не растягиваем телефонную раскладку на всю
   ширину — от карточек в пол-экрана лучше не станет. Вместо этого даём колонке
   вырасти умеренно, а освободившееся место отдаём ПОД ЛИШНИЕ КАРТОЧКИ: рейлы
   переходят на четыре в ряд, сетки — на три колонки. Плитки при этом остаются
   примерно телефонного размера, просто их больше.

   ПОРОГ 700px ловит и планшеты, и телефон в альбомной ориентации — там ровно
   та же беда с пустыми полями.

   Панели (таббар и панель генерации) наоборот СУЖАЕМ: 504px на широком экране
   разносит пять вкладок так далеко друг от друга, что панель читается как
   растянутая. 420px возвращает плотность, близкую к телефонной, и всё равно
   шире, чем на телефоне (там она 327px при экране 375). */
@media (min-width: 700px) {
  .ui-page {
    width: min(100%, 760px);
  }
  .impito-home-rail,
  .impito-cat-rail {
    --ui-rail-card: var(--ui-rail-card-4up);
  }
  .impito-style-grid,
  .impito-style-gallery,
  .impito-topup-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .impito-tabbar,
  .impito-style-submit__inner {
    width: min(calc(100% - 48px), 420px);
  }
}

/* Подпись-указатель под референсом: @Image1 / @Video1.
   Показывается только у моделей с @-синтаксисом (Seedance) — разметку
   ставит generate.js, здесь только оформление. */
.impito-ref-handle {
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.35;
  color: var(--ui-text-muted, rgba(0, 0, 0, 0.45));
}

/* Подпись-указатель на плитке референса: @Image1 и т.д. Оформление один в один
   с бейджем длительности у видео-референса, чтобы обе метки читались как одна
   система. Рисуется только у моделей с @-синтаксисом. */
.impito-style-photo__handle {
  position: absolute;
  bottom: 6px;
  left: 6px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(8, 10, 20, 0.55);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.01em;
  pointer-events: none;
}

/* Точки-деления у ползунка ДЛИТЕЛЬНОСТИ не рисуем: там 26 значений, и рябь из
   точек читалась как мусор под дорожкой (просьба юзера, 21.08.2026).
   У качества деления остаются — там их три-четыре, и они помогают. */
[data-duration-host] .impito-quality__ticks {
  display: none;
}

/* Текст ошибки в листе: тот же ритм, что у пунктов меню — крупнее прежнего и
   с нормальными полями. Раньше сообщение рисовалось заголовком балансового
   листа и липло к краям (21.08.2026). */
.impito-error-sheet__text {
  margin: 0;
  padding: 14px 18px 16px;
  color: var(--ui-text);
  font-size: 16px;
  line-height: 1.4;
  text-align: left;
}

/* Кнопка «закрыть» — ВНУТРИ листа, отдельной строкой под текстом, как пункты
   в остальных листах. Снаружи она уезжала под таббар и читалась как чужая
   (21.08.2026). Разделитель отбивает её от сообщения. */
.impito-error-sheet__close {
  border-top: 0.5px solid var(--ui-separator);
}

/* Заголовок экрана строго по центру верхней панели — ТОЛЬКО там, где мышь
   (десктопные клиенты). На телефоне его высоту ставит скрипт инлайном от
   нативного инсета Telegram, и трогать её нельзя: она подогнана под кнопки
   клиента. На компьютере инсета нет, скрипт кладёт 11px от верха, и текст
   стоял в верхней части панели, а не по её центру (21.08.2026).
   Считаем от высоты самой вуали: (высота − интерлиньяж 23px) / 2.
   `!important` вынужденно — перебиваем инлайновый стиль скрипта. */
@media (pointer: fine) {
  .impito-profile-heading {
    top: calc((var(--ui-veil-height) - 23px) / 2) !important;
  }
}

/* ── Главная: блоки, добавленные 21.08.2026 ──────────────────────────────
   Своей вёрстки у них нет — всё на пресетах (`.impito-style-card` в рейле,
   строка истории, `.ui-card` + `.ui-row`). Здесь только две мелочи, которых
   в пресетах не было. */
.impito-home-active-section {
  /* Строка истории идёт сразу под приветствием: свой отступ ей нужен, потому
     что `.impito-hist-list` рассчитан на экран, где над ним заголовок. */
  padding-top: 2px;
}
.impito-home-ref__icon {
  display: flex;
  width: 28px;
  height: 28px;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  line-height: 1;
}

/* ── Окно «генерируется», выезжающее сверху (22.08.2026) ──────────────────
   Форма и эффекты — ровно те же, что у листа выбора модели
   (.impito-sheet__group): подложка, размытие, радиус, тень. Второго языка
   всплывающих окон в аппе быть не должно.
   Отличие одно: приезжает сверху и не перекрывает работу — под ним можно
   продолжать набирать промпт. Поэтому ни фона-затемнения, ни перехвата
   нажатий у него нет. */
.impito-top-toast {
  position: fixed;
  /* 6 → 12px: «чуть-чуть ниже» (03.09.2026, просьба юзера). */
  top: calc(var(--ui-veil-height) + 12px);
  left: 0;
  right: 0;
  z-index: 130;
  display: flex;
  justify-content: center;
  padding: 0 10px;
  pointer-events: none;
}
.impito-top-toast__panel {
  display: flex;
  /* BORDER-BOX ОБЯЗАТЕЛЕН. Правило `.ui-page *` действует только внутри
     страницы, а окно живёт прямо в body — значит по умолчанию content-box, и
     `width: 100%` складывалось с полями 16px, вылезая за края экрана
     (28.08.2026, скриншот юзера с окном «изображение готово»). */
  box-sizing: border-box;
  width: min(100%, 504px);
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  border-radius: var(--ui-radius-card);
  /* Стекло, а не плотная подложка (просьба юзера 22.08.2026): сквозь окно
     видно экран, поэтому оно читается как всплывшее поверх, а не как кусок
     интерфейса. Тон розовый — тот же, что у таббара. */
  background: var(--ui-glass-panel-soft);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  backdrop-filter: blur(14px) saturate(150%);
  /* ТЕНИ НЕТ. Вместо неё волосяная тёмная обводка 0.5px — ровно та же, что у
     таббара и панели генерации (на экранах 2x/3x это один физический пиксель,
     тоньше не бывает). Блики внутрь — оттуда же, они и дают ощущение стекла. */
  box-shadow:
    0 0 0 0.5px rgba(12, 18, 48, 0.22),
    inset 0 1.2px 1px -0.5px rgba(255, 255, 255, 0.5),
    inset 0 -1px 1px -0.5px rgba(255, 255, 255, 0.22),
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.15);
  opacity: 0;
  /* Живее прежнего: окно не просто съезжает, а слегка проскакивает вниз и
     возвращается — кривая с выбросом (y > 1). Плюс еле заметное «раздутие»
     по масштабу, от него движение читается упругим, а не линейным. */
  transform: translateY(-26px) scale(0.94);
  transition:
    transform 0.44s cubic-bezier(0.22, 1.42, 0.36, 1),
    opacity 0.22s var(--ui-ease);
  /* Нажатия ловит только сама панель — чтобы её можно было смахнуть. */
  pointer-events: auto;
  touch-action: none;
}
.impito-top-toast.is-open .impito-top-toast__panel {
  opacity: 1;
  transform: translateY(0) scale(1);
}
.impito-top-toast__body {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
}
.impito-top-toast__title {
  color: var(--ui-text);
  font-family: var(--ui-font);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.impito-top-toast__sub {
  color: var(--ui-hint);
  font-family: var(--ui-font);
  font-size: 13px;
  line-height: 1.25;
}
/* Кружок-крутилка: тот же приём, что у спиннера в истории — кольцо с
   прозрачным сектором. */
.impito-top-toast__spinner {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  border: 2px solid var(--ui-accent-soft);
  border-top-color: var(--ui-accent);
  border-radius: 50%;
  animation: impito-top-toast-spin 0.8s linear infinite;
}
/* Ошибка — то же окно, другой знак. Кружок один в один как у неудавшейся
   строки в истории (`.impito-hist-row__thumb.is-failed`): человек уже видел
   его там, и второй раз объяснять не нужно. */
.impito-top-toast__mark {
  display: flex;
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--ui-destructive);
  color: #ffffff;
  font-family: var(--ui-font);
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
}
.impito-top-toast.is-error .impito-top-toast__title {
  color: var(--ui-destructive);
}
/* Окно «изображение готово»: слева превью, справа заголовок и промпт. */
.impito-top-toast__thumb {
  display: block;
  overflow: hidden;
  width: 40px;
  height: 40px;
  flex: 0 0 auto;
  border-radius: 10px;
  background: rgba(12, 18, 48, 0.06);
}
.impito-top-toast__thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Промпт — РОВНО одна строка с многоточием (просьба юзера 23.08.2026). Без
   этого длинный запрос растягивал окно на пол-экрана. Работает только вместе
   с `min-width: 0` у __body: без него флекс-ребёнок не даёт себя сжать и
   многоточие не появляется вовсе. */
.impito-top-toast.has-thumb .impito-top-toast__title,
.impito-top-toast.has-thumb .impito-top-toast__sub {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.impito-top-toast.is-tappable .impito-top-toast__panel {
  cursor: pointer;
}
.impito-top-toast.is-tappable .impito-top-toast__panel:active {
  opacity: 0.75;
}
@keyframes impito-top-toast-spin {
  to {
    transform: rotate(360deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .impito-top-toast__panel {
    transition: opacity 0.2s var(--ui-ease);
    transform: none;
  }
  .impito-top-toast__spinner {
    animation-duration: 2.4s;
  }
}

/* САМО МЕНЮ. По умолчанию скрыто — показывает его только медиа-запрос выше,
   поэтому на телефоне разметка просто лежит мёртвым грузом и ни на что не
   влияет. */
.impito-sidebar {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 90;
  display: none;
  width: var(--impito-sidebar-w, 244px);
  flex-direction: column;
  box-sizing: border-box;
  /* ВЕРХНИЙ ОТСТУП ЗАВИСИТ ОТ КЛИЕНТА, И ЭТО ВАЖНО.
     На макбуке кнопки Telegram (закрыть, ⌄, ⋯) живут в хроме окна, ВНЕ вебвью,
     и меню спокойно начинается от самого верха. На айпаде аппа открыта на весь
     экран, те же кнопки лежат ПОВЕРХ страницы — и накрывали логотип
     (31.08.2026, скриншот юзера). Отступ берём от `--ui-fullscreen-top`: это и
     есть высота полосы, которую занимают нативные кнопки. На десктопе она
     ноль, поэтому там ничего не съедет. */
  padding: calc(6px + var(--ui-fullscreen-top, 0px)) 12px 18px;
  overflow-y: auto;
  /* По той же причине, что и у экранов: иначе меню тоже елозит вбок. */
  overflow-x: hidden;
  /* ПРОКРУТКА ТОЛЬКО ВНУТРИ ПАНЕЛИ. Без этого жест в зоне меню, дойдя до края
     списка, подхватывал документ и тащил всю страницу. */
  overscroll-behavior: contain;
  border-right: 1px solid var(--ui-sidebar-border);
  /* ФОН СПЛОШНОЙ, БЕЗ ПРОЗРАЧНОСТИ И РАЗМЫТИЯ — намеренно. Полупрозрачная
     подложка на оттяжке просвечивала уезжающий контент, и в панели мелькало
     содержимое страницы. Заодно это и есть «другой цвет»: панель светлее
     полотна. */
  background: var(--ui-sidebar-bg);
}

/* ЗАПАС ФОНА ЗА КРАЯМИ ЭКРАНА. Резиновая оттяжка WebKit двигает весь слой
   вместе с `position: fixed` — панель уезжает, и в освободившейся полосе
   проглядывает полотно страницы. Лечим подложкой, которая на 240px больше
   панели сверху и снизу: тянуть по-прежнему можно, а показаться из-под неё
   уже нечему. Это `::before`, а не padding, чтобы не трогать прокрутку
   списка. */
.impito-sidebar:before {
  content: "";
  /* Именно fixed, а не absolute: абсолютная подложка своими -240px снизу
     увеличивала прокручиваемую высоту САМОЙ панели, и под меню появлялась
     пустая полоса, которую можно было листать в никуда. Fixed в прокрутке
     не участвует вовсе, а при резиновой оттяжке едет вместе со слоем — то
     есть по-прежнему прикрывает просвет. */
  position: fixed;
  z-index: -1;
  top: -240px;
  bottom: -240px;
  left: 0;
  width: var(--impito-sidebar-w, 244px);
  background: inherit;
}

/* Логотип кликабельный — уводит на главную. Именно кнопка, а не обработчик на
   картинке: так работают и клавиатура, и озвучка экрана. */
.impito-sidebar__logo-btn {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
}

.impito-sidebar__logo-btn:active {
  opacity: 0.75;
}

.impito-sidebar__logo {
  display: block;
  width: 152px;
  max-width: calc(100% - 16px);
  height: auto;
  margin: 2px 0 2px 10px;
}

/* Логотип Fid текстом (02.10.2026): цвет идёт за темой, отдельной картинки
   под тёмную не нужно. Лаймовая точка — цвет маскота. */
.impito-sidebar__wordmark {
  display: inline-flex;
  align-items: flex-end;
  gap: 4px;
  margin: 2px 0 2px 10px;
  color: var(--ui-accent-strong);
  font-family: var(--ui-font-display);
  font-size: 44px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
}
.impito-sidebar__wordmark-dot {
  width: 11px;
  height: 11px;
  margin-bottom: 6px;
  border-radius: 50%;
  background: var(--ui-lime);
}

.impito-sidebar__inner {
  display: flex;
  flex: 1 0 auto;
  flex-direction: column;
  gap: 20px;
  /* Ровно на пиксель выше панели — этого хватает, чтобы у меню появилась своя
     резиновая оттяжка, отдельная от оттяжки основного полотна. Вместе с
     `overscroll-behavior: contain` на панели получается то, что просил юзер:
     тянешь меню — едет меню, тянешь контент — едет контент. */
  min-height: calc(100% + 1px);
}

.impito-sidebar__group {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.impito-sidebar__caption {
  margin: 0 0 6px;
  padding: 0 10px;
  color: var(--ui-hint);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.impito-sidebar__item {
  display: flex;
  align-items: center;
  gap: 12px;
  box-sizing: border-box;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  /* Максимальный радиус — просьба юзера: пункт читается как пилюля. */
  border-radius: 999px;
  background: transparent;
  color: var(--ui-text);
  font-family: inherit;
  font-size: 15px;
  /* Тоньше, чем было (600): просьба юзера. */
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition:
    background 150ms var(--ui-ease),
    color 150ms var(--ui-ease);
}

.impito-sidebar__item:hover {
  background: var(--ui-hover);
}

.impito-sidebar__item.is-active {
  background: var(--ui-accent);
  color: #fff;
}

.impito-sidebar__item:active {
  transform: scale(0.985);
}

/* Значок непросмотренных — РОВНО ТОТ ЖЕ, что на вкладке истории в таббаре.
   Размеры, цвет и начертание скопированы оттуда один в один, своих чисел
   здесь быть не должно: `--ui-destructive` — тот самый красный, 18×18 — тот
   самый системный размер, а вес 400 стоит не случайно. В таббаре про него
   написано прямым текстом: вес 500 пробовали и юзер его отбраковал, на
   красном жирные цифры выглядят тяжело. Крутить размер, вес не трогать.
   Отличие одно: здесь значок не абсолютный, а прижат к правому краю пункта. */
.impito-sidebar__badge {
  margin-left: auto;
  display: block;
  /* КРУГ ДЕРЖИТСЯ И НА ДВУХ ЦИФРАХ. В таббаре значок 18px с полями по 5px:
     одна цифра даёт круг, а две растягивают его в овал — на телефоне это не
     мешает, значок там маленький и висит на иконке. Здесь он стоит в строке
     меню, и юзер попросил круг (31.08.2026: «на айпаде круглый, а на маке вот
     такая хуйня» — на маке было двузначное число). Поэтому 20px в обе стороны
     и поля всего 2px: «16» при шрифте 13px занимает ~15px и спокойно влезает
     внутрь круга. Растянуться значок может только на «99+», и это правильно —
     обрезать число хуже, чем потерять форму на трёхзначном.
     Цвет, шрифт и вес — те же, что в таббаре, их не трогаем. */
  min-width: 20px;
  height: 20px;
  padding: 0 2px;
  box-sizing: border-box;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-destructive);
  color: #ffffff;
  font-family: var(--ui-font);
  font-size: 13px;
  font-weight: 400;
  /* Моноширинные цифры: иначе ширина значка гуляет от числа к числу, а на
     разных платформах ещё и по-разному. */
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  line-height: 20px;
  text-align: center;
  pointer-events: none;
}

.impito-sidebar__badge[hidden] {
  display: none;
}

.impito-sidebar__icon {
  display: flex;
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
}

.impito-sidebar__icon svg {
  width: 100%;
  height: 100%;
}

@media (prefers-reduced-motion: reduce) {
  .impito-sidebar__item {
    transition: none;
  }
}

/* ─────────────────────────── ШИРОКИЙ ЭКРАН: БОКОВОЕ МЕНЮ ───────────────────
   Возвращено 31.08.2026 по просьбе юзера. Первая версия (21.08) была снесена
   целиком; там же в хендоффе записаны грабли, они здесь учтены.

   УСЛОВИЕ — ИМЕННО СООТНОШЕНИЕ СТОРОН, а не «пк против мобилки» (просьба
   юзера). Ширина как единственный порог не работает: окно мини-аппы в Telegram
   Desktop открывается узким, и 1100px в нём не наступает никогда. Берём
   альбомную ориентацию плюс порог по ширине: 1000px отсекает и планшет в
   портрете, и телефон, повёрнутый набок (у самых больших моделей там ~950px).

   ПОРОГА ПО ВЫСОТЕ ЗДЕСЬ БЫТЬ НЕ ДОЛЖНО. Сначала стояло `min-height: 600px` —
   и раскладка разваливалась на планшете, стоило открыть клавиатуру: в
   `<meta viewport>` включён `interactive-widget=resizes-content`, окно
   честно ужимается по высоте, условие переставало выполняться, и аппа
   сваливалась в мобильный вид прямо во время набора текста (01.09.2026,
   скриншот юзера). Ширина при этом не меняется — на неё и опираемся.

   Всё внутри одного медиа-запроса: на телефоне ни одно из этих правил не
   существует, поэтому сломать мобильную раскладку нечем. */
@media (min-aspect-ratio: 1/1) and (min-width: 1000px) {
  :root {
    --impito-sidebar-w: 244px;
  }

  /* ПИЛЮЛИ ВЫШЕ НА 6px. `lift` — готовая ручка «насколько плашка залезает выше
     кромки вуали», но задавать её надо в ОБОИХ режимах: базовое значение 15px
     живёт в `:root`, а десктопный `html.impito-flat-top` переопределяет его на
     33px и по специфичности выигрывает у `:root` внутри этого медиа-запроса.
     Поэтому пишем оба, каждое плюс шесть. */
  :root {
    --ui-veil-pill-lift: 21px;
    /* Панель ещё чуть ниже (просьба юзера). Было +5px, стало −12px: вуаль
       теряет ~15px высоты, пилюли и заголовок едут вместе с ней. На макбуке
       база вуали задана числом в `html.impito-flat-top`, туда это слагаемое не
       входит — там ничего не изменится. */
    --ui-veil-extra: -16.4px;
  }

  html.impito-flat-top {
    --ui-veil-pill-lift: 39px;
  }

  /* Заголовок экрана двигаем трансформом, а не `top`: top ему ставит скрипт
     инлайном, и перебить его можно было бы только `!important`. */
  .impito-profile-heading {
    transform: translateY(-6px) !important;
  }

  .impito-sidebar {
    display: flex;
  }


  /* Таббар и боковое меню — одно и то же, показываем что-то одно. */
  .impito-tabbar {
    display: none;
  }

  /* ГРАБЛЯ ИЗ ПРОШЛОГО ЗАХОДА: вуаль, заголовок экрана и пилюли
     позиционированы от края ОКНА, а не от контента. Каждый нужно сдвинуть на
     ширину меню — иначе они лягут под него. */
  body:before {
    left: var(--impito-sidebar-w);
  }

  .impito-profile-heading {
    left: calc(var(--impito-sidebar-w) + 72px);
  }

  .impito-profile-pill {
    left: calc(var(--impito-sidebar-w) + 16px);
  }

  /* СТРЕЛКИ ЛЕНТ (03.09.2026, rail_arrows.js) — только здесь, в широкой
     раскладке с мышью. Пилюля как у стрелок пейджера истории, висит по краям
     ленты на уровне центра картинок, видна при наведении на секцию; на
     краях ленты соответствующая стрелка скрыта (hidden ставит js). */
  .impito-rail-section--arrows {
    position: relative;
  }
  .impito-rail-arrow {
    position: absolute;
    z-index: 5;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--ui-rail-arrow);
    -webkit-backdrop-filter: blur(6px) saturate(140%);
    backdrop-filter: blur(6px) saturate(140%);
    box-shadow:
      0 6px 18px rgba(12, 18, 48, 0.16),
      inset 0 0 0 0.5px rgba(255, 255, 255, 0.5);
    color: var(--ui-text);
    cursor: pointer;
    opacity: 0;
    transform: translateY(-50%);
    transition:
      opacity 0.15s var(--ui-ease),
      background-color 0.15s var(--ui-ease),
      color 0.15s var(--ui-ease);
  }
  .impito-rail-arrow[hidden] {
    display: none;
  }
  .impito-rail-section--arrows:hover .impito-rail-arrow,
  .impito-rail-arrow:focus-visible {
    opacity: 1;
  }
  /* Без обводки и кольца при наведении и после клика (03.09.2026, просьба
     юзера): ни блика по кромке, ни браузерного outline. */
  .impito-rail-arrow:hover {
    background: var(--ui-accent);
    color: var(--ui-accent-text);
    box-shadow: none;
  }
  .impito-rail-arrow:focus,
  .impito-rail-arrow:focus-visible {
    outline: none;
  }
  .impito-rail-arrow:active {
    transform: translateY(-50%) scale(0.94);
  }
  .impito-rail-arrow svg {
    width: 9px;
    height: 15px;
  }
  .impito-rail-arrow--prev {
    left: 6px;
  }
  .impito-rail-arrow--prev svg {
    transform: scaleX(-1);
  }
  .impito-rail-arrow--next {
    right: 6px;
  }

  /* ШАПКА НА КОМПЬЮТЕРЕ: только выравнивание по одной оси (03.09.2026).
     Увеличение (+50% пилюли, +30% заголовок) юзер посмотрел и отменил —
     размеры прежние. Осталось выравнивание: пилюли были на 5px выше центра
     заголовка (замер при 1280×800: центр заголовка 25.5px, пилюль 20.5px).
     Состояния скрытия и :active повторяют сдвиг, иначе пилюля прыгала бы. */
  :root {
    --impito-pc-pill-shift: 5px;
  }
  .impito-token-pill,
  .impito-profile-pill {
    transform: translateY(var(--impito-pc-pill-shift, 0px));
  }
  .impito-token-pill:active,
  .impito-profile-pill:active {
    transform: translateY(var(--impito-pc-pill-shift, 0px)) scale(0.94);
  }
  html.impito-topbar-collapsed .impito-token-pill,
  html.impito-topbar-plain .impito-token-pill,
  html.impito-topbar-collapsed .impito-profile-pill,
  html.impito-topbar-plain .impito-profile-pill {
    transform: translateY(calc(var(--impito-pc-pill-shift, 0px) - 4px));
  }

  /* ПРОКРУТКА РАЗДЕЛЬНАЯ, И ЭТО ЕДИНСТВЕННЫЙ СПОСОБ.
     Резиновая оттяжка WebKit двигает ВЕСЬ слой вместе с `position: fixed` —
     поэтому, пока скроллером остаётся документ, любое движение в области
     контента таскало и боковое меню. Ни `fixed`, ни `overscroll-behavior`
     этого не лечат: лечится только тем, чтобы документ не прокручивался
     вовсе. Поэтому здесь скроллер — САМ ЭКРАН, а документ прибит.
     `window.scrollY` и `window.scrollTo` после этого перестают работать, на
     них опираются экраны и роутер — им подставлен прокси, см. router.js. */
  html,
  body {
    height: 100%;
    overflow: hidden;
  }

  body {
    /* padding больше не нужен: экраны позиционируются от края меню сами. */
    padding-left: 0;
  }

  #impito-home,
  #impito-prompt-styles,
  #impito-profile,
  #impito-generations,
  #impito-photo,
  #impito-video,
  #impito-restore,
  #impito-enhance,
  #impito-expand,
  #impito-editor {
    /* ИМЕННО `absolute`, А НЕ `fixed`. Оба дают одно и то же положение: документ
       здесь не прокручивается (`html, body { overflow: hidden }`), и абсолютный
       элемент считается от того же прямоугольника, что и фиксированный. Но
       `fixed` создаёт stacking context, и заголовок экрана — он `fixed` с
       z-index 60 — оказывался заперт внутри экрана, а тот рисуется как z:0,
       то есть НИЖЕ вуали (z-index 40). Отсюда размытый текст, просвечивающий
       сквозь панель. У `absolute` с `z-index: auto` своего контекста нет,
       и заголовок снова поднимается над вуалью. */
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: var(--impito-sidebar-w);
    overflow-y: auto;
    /* ТОЛЬКО ВВЕРХ-ВНИЗ. Задать одну ось мало: по спецификации, если одна ось
       перестала быть `visible`, вторая сама становится `auto` — и экран начинал
       ездить вбок вслед за полками и широкими карточками. */
    overflow-x: hidden;
    /* Своя пружина у контента, отдельная от пружины меню. */
    overscroll-behavior: contain;
  }

  /* НА ВЕСЬ ЭКРАН. На телефоне колонка 560px и по центру, на 700px+ — 760px;
     здесь она распускается во всю доступную ширину, ради этого всё и
     затевалось. Нижний отступ меньше: таббара внизу больше нет. */
  /* УЖЕ ПО ГОРИЗОНТАЛИ, ВЫСОТА НЕТРОНУТА (просьба юзера 01.09.2026).
     Первая попытка была через `zoom` — он ужимал всё разом, включая высоту
     строк и шрифты, и юзер это отбраковал. Здесь просто сужаем колонку: по
     бокам становится больше воздуха, а сами элементы остаются прежнего
     размера. 85% = минус 15%, как и просили. */

  .ui-page {
    /* Ширина полотна: 85%. Ужимали до 76%, но после перехода на две колонки
       левая часть стала тесной — юзер попросил вернуть (01.09.2026). */
    width: 85%;
    max-width: none;
    margin: 0 auto;
    /* ОБЯЗАТЕЛЬНО. Глобальное `border-box` в проекте стоит на `.ui-page *`, то
       есть на потомках, а сам `.ui-page` остаётся content-box — эта грабля
       записана ещё с прошлого захода на десктоп. Без него ширина 100% плюс
       боковые поля давали лишние 64px, контент вылезал за экран и его можно
       было таскать вбок. */
    box-sizing: border-box;
    padding: calc(14px + var(--ui-safe-top)) 32px 40px;
  }


  /* ─── ЭКРАН ГЕНЕРАЦИИ: ДВЕ КОЛОНКИ ───
     На широком экране всё в одну колонку выглядело пустовато, а лента
     референсов ещё и листалась вбок, хотя места вокруг вагон. Поэтому: слева
     промпт и параметры, справа сверху — референсы, сеткой по две плитки в ряд
     и с ростом ВНИЗ (просьба юзера 01.09.2026).
     Раскладку держит grid: промпт занимает первую ячейку левой колонки,
     референсы — первую ячейку правой, всё остальное укладывается слева друг
     под другом само. Заголовок экрана, нижняя панель и модалки — fixed, они из
     потока сетки выпадают и на неё не влияют. */
  .impito-photo-page {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 248px;
    gap: 0 28px;
    align-items: start;
  }

  .impito-photo-page > * {
    grid-column: 1;
    min-width: 0;
  }

  .impito-photo-page > [data-photo-section] {
    grid-column: 2;
    /* РАСТЯГИВАЕМ НА ВСЕ СТРОКИ, А НЕ СТАВИМ В ПЕРВУЮ. Иначе высокая колонка
       референсов задирает высоту первой строки, и параметры слева отъезжают
       от промпта вниз — между ними зияло 99px пустоты (01.09.2026, юзер:
       «там ебать места»). Растянутый элемент высоту строк не диктует, и левая
       колонка укладывается сама по себе. Лишние неявные строки нулевые, ряды
       не раздвигают. */
    grid-row: 1 / span 99;
    align-self: start;
  }

  /* Референсы больше не лента: сетка два в ряд, растёт вниз. */
  .impito-photo-page > [data-photo-section] .impito-style-photos {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    overflow: visible;
    padding: 5px 0 0;
  }

  /* У последней плитки в ленте свой правый отступ — в сетке он лишний. */
  .impito-photo-page > [data-photo-section] .impito-style-photos > * {
    margin-right: 0;
  }


  /* МАГАЗИН. Пакеты — три в ряд, всё остальное (своё количество, промокод,
     сноски) обычным потоком под ними. Пробовали разложить в две колонки, с
     вводом справа — юзер забраковал (01.09.2026), вернули как было. */
  .impito-topup-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  /* Подписки: три карточки в ряд (было по одной). */
  .impito-subs-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }


  /* ПЕРЕКЛЮЧАТЕЛЬ НА 10% МЕНЬШЕ (просьба юзера 01.09.2026). Меняем все четыре
     числа сразу, иначе бегунок перестанет вписываться в дорожку:
     70×31 → 63×28, бегунок 43×27 → 39×24, сдвиг 23 → 20.
     Сдвиг посчитан, а не прикинут: ширина − бегунок − поля с двух сторон,
     то есть 63 − 39 − 4 = 20. Правишь размер — пересчитывай его следом. */
  .ui-switch {
    width: 63px;
    height: 28px;
  }

  .ui-switch:after {
    width: 39px;
    height: 24px;
  }

  .ui-switch--on:after {
    transform: translate3d(20px, 0, 0);
  }

  /* МИНИ-ТУМБЛЕР (улучшение запроса) НА ШИРОКОМ ЭКРАНЕ ОСТАЁТСЯ МИНИ. Правило
     выше стоит позже базового `.ui-switch--mini` и при равной специфичности
     перебивало его: на айпаде/ПК тумблер раздувался до 63×28 с бегунком 39×24
     (08.09.2026, скриншот юзера). Возвращаем размеры мини-варианта. */
  .ui-switch--mini {
    width: 42px;
    height: 24px;
  }
  .ui-switch--mini:after {
    width: 24px;
    height: 20px;
  }
  .ui-switch--mini.ui-switch--on:after {
    transform: translate3d(14px, 0, 0);
  }


  /* ИСТОРИЯ: ПОЛКИ В ДВЕ КОЛОНКИ (просьба юзера 01.09.2026). Разделов стало
     четыре — фото, видео, апскейл, реставрация, — и в один столбец они
     растягивались на весь экран пустотой. Кладём их 2×2.
     Целимся по `[data-page="gens"]`, а не по классу страницы: тот же
     `impito-profile-page` носят профиль, магазин и карточка генерации, и сетка
     поехала бы у них тоже. Заголовок экрана — fixed, из потока сетки выпадает
     и на неё не влияет. */
  .impito-profile-page[data-page="gens"] {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    /* 24 → 56px (01.09.2026, «сделай расстояние между ними чуть больше»).
       Полки листаются вбок каждая сама по себе, и на узком зазоре правая
       начиналась там же, где заканчивалась левая, — две ленты читались как
       одна сплошная. */
    gap: 0 56px;
    align-items: start;
  }

  /* ОДИНОЧНЫЕ БЛОКИ — НА ОБЕ КОЛОНКИ (07.09.2026, «хули слева, а не по
     центру»): заглушка «пока пусто», короткая пустая строка раздела, список
     раздела и его пагинация — иначе они вставали в левую колонку сетки. */
  .impito-profile-page[data-page="gens"] .impito-profile-empty,
  .impito-profile-page[data-page="gens"] .impito-hist-empty,
  .impito-profile-page[data-page="gens"] .impito-hist-list,
  .impito-profile-page[data-page="gens"] .impito-hist-pager,
  .impito-profile-page[data-page="gens"] .impito-hist-pager__meta {
    grid-column: 1 / -1;
  }

  /* ХВОСТ СЛЕДУЮЩЕЙ КОЛОНКИ УБИРАЕМ ИМЕННО ЗДЕСЬ (01.09.2026, «это выглядит
     довольно странно»). На телефоне выглядывающий край — единственная
     подсказка, что полку можно листать, и там он полезен. На широком экране
     полок четыре, и каждая показывала справа обрезок чужой карточки: четыре
     белых прямоугольника посреди пустой страницы, ни на что не похожие.
     Листать полку можно по-прежнему, а «показать всё» открывает заголовок.
     ПОЛЕ СПРАВА ОБЯЗАНО ОСТАТЬСЯ РАВНЫМ ЗАЗОРУ между колонками: на нём держится
     снап (см. большой комментарий у `.impito-hist-rail`). Ноль здесь — только
     у выступа. */
  .impito-profile-page[data-page="gens"] .impito-hist-rail {
    --ui-rail-peek: 0px;
  }

  /* РАЗДЕЛИТЕЛЬ — РОВНО ПО ТЕКСТУ, А НЕ ДО КРАЯ СТРОКИ (01.09.2026, «полоски
     как будто из воздуха появляются»). Слева он и так начинается там, где
     начинается текст, а справа тянулся до самого края колонки и повисал в
     пустоте за шевроном — на узком экране это незаметно, на широком строка
     втрое длиннее. Отступ 22px = шеврон (10px) + зазор строки (12px), то есть
     линия кончается там же, где кончается текст. */
  .impito-profile-page[data-page="gens"] .impito-hist-row::after {
    right: calc(10px + var(--ui-hist-gap));
  }

  /* Полки и сетки на широком экране дышат свободнее. */
  .impito-style-grid,
  .impito-style-gallery {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  /* ШАПКА КАТАЛОГА СТИЛЕЙ — ВО ВСЮ ОБЛАСТЬ КОНТЕНТА.
     Сначала я просто сдвинул её центр на половину ширины меню, оставив
     шириной 760px. Получился полупрозрачный островок посреди экрана: он висел
     поверх карточек, сквозь него всё просвечивало, и читалось это как поломка
     (01.09.2026, замечание юзера). На узком экране шапка занимает всю ширину —
     здесь должна вести себя так же, только считаться от края меню.
     `transform: none` обязателен: в базе стоит `translateX(-50%)` под
     центровку, а мы теперь растягиваем по краям. */
  .impito-style-sticky {
    left: var(--impito-sidebar-w);
    right: 0;
    width: auto;
    transform: none;
  }

  /* Фон шапки — во всю ширину, а её содержимое держим колонкой по центру,
     иначе поиск растягивается на весь экран и выглядит нелепо. */
  .impito-style-sticky > * {
    width: min(100%, 760px);
    margin-left: auto;
    margin-right: auto;
  }

  /* КРОМЕ ЛЕНТЫ КАТЕГОРИЙ — ей отдаём всю ширину. Она листается вбок, и в
     колонке 760px в неё влезало три-четыре чипса, остальные приходилось
     докручивать (01.09.2026, просьба юзера). Поиск при этом остаётся прежним.
     Чипсы — последний блок шапки, поэтому `:last-child`. */
  .impito-style-sticky > *:last-child {
    width: 100%;
    max-width: none;
  }

  /* НИЖНЯЯ ПАНЕЛЬ. Двигаем КОНТЕЙНЕР, а не внутренний блок: контейнер fixed
     и растянут `left: 0; right: 0`, а внутри всё центруется через
     `margin: 0 auto`. Я сперва сдвинул внутренний — а он `position: relative`,
     и `left` просто утащил его вправо за край экрана вместе с кнопкой
     «генерировать» (01.09.2026, скриншот юзера с планшета).
     Заодно поднимаем панель ниже: 82px снизу — это запас под таббар, которого
     в широкой раскладке нет. */
  .impito-style-submit.ui-submit {
    left: var(--impito-sidebar-w);
    /* Выше над нижним краем — просьба юзера. */
    bottom: calc(56px + var(--ui-safe-bottom));
  }

  /* Панель генерации крупнее на 30%: на широком экране она терялась внизу.
     `zoom` здесь безопасен — внутри неё нет ничего фиксированного. */
  .impito-style-submit__inner {
    zoom: 1.3;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   РАСШИРЕНИЕ ФОТО — площадка (03.09.2026, оболочка)
   Белое поле выбранного соотношения, на нём фото, которое таскают пальцем.
   Размеры площадки пишет js (`fitStage` в expand.js): пропорция и потолок по
   высоте считаются вместе с положением фото и сборкой референса, а css такой
   связки не даёт. Остальное на экране — общие детали (пикер, ползунок,
   `.ui-card`, лист форматов), своих правил у них здесь нет.
   ══════════════════════════════════════════════════════════════════════════ */
.impito-expand-stage-wrap {
  padding: 5px 12px 0;
}
.impito-expand-stage {
  position: relative;
  overflow: hidden;
  margin: 0 auto;
  border-radius: var(--ui-radius-card);
  /* НЕ БЕЛАЯ (просьба юзера 03.09): нежно-розовая, как карточка настроек и
     бегунок ползунка, и на ней сетка из мелких серых точек — «вайб рабочей
     площадки». Белым остаётся сам референс, который уходит нейросети; здесь
     это только рабочее поле. Точки — radial-gradient, шаг 12px, чуть заметные.
     Тени под площадкой нет (та же просьба). */
  background-color: var(--ui-card);
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.1);
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
/* Сетка точек — ТОЛЬКО когда фото уже лежит (просьба юзера 03.09): пустая
   площадка остаётся гладкой, с пунктирной подсказкой внутри. */
/* Сетка рисуется псевдоэлементом с `background-repeat: space`: раскладываются
   только ЦЕЛЫЕ плитки, поэтому у стен площадки нет половинок точек
   (03.09.2026, замечание юзера). Псевдоэлемент отступает от краёв на 5px. */
.impito-expand-stage.has-photo::before {
  content: "";
  position: absolute;
  inset: 5px;
  background-image: radial-gradient(
    circle at center,
    var(--ui-expand-dot) 0.9px,
    transparent 1.4px
  );
  background-size: 12px 12px;
  background-repeat: space;
  pointer-events: none;
}
.impito-expand-stage.has-photo .impito-expand-stage__photo {
  cursor: grab;
}
.impito-expand-stage.is-dragging .impito-expand-stage__photo {
  cursor: grabbing;
}
.impito-expand-stage__photo {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  /* Тень отделяет фото от белого поля там, где у самого фото светлые края. */
  filter: drop-shadow(0 2px 10px rgba(12, 18, 48, 0.18));
  /* Таскают за само фото: палец на пустом поле площадки прокручивает
     страницу как обычно. */
  pointer-events: auto;
  touch-action: none;
  will-change: transform;
}
.impito-expand-stage__photo[hidden] {
  display: none;
}
/* Переезд только программный (тумблер «по центру»); под пальцем и ползунком
   класса нет — фото идёт ровно за жестом. */
.impito-expand-stage__photo.is-settling {
  transition:
    transform 0.3s var(--ui-ease-out),
    width 0.3s var(--ui-ease-out),
    height 0.3s var(--ui-ease-out);
}
.impito-expand-stage__empty {
  position: absolute;
  inset: 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1.5px dashed rgba(12, 18, 48, 0.22);
  border-radius: calc(var(--ui-radius-card) - 8px);
  color: var(--ui-hint);
  font-size: 13px;
  font-weight: 500;
  text-align: center;
  pointer-events: none;
}
.impito-expand-stage__empty[hidden] {
  display: none;
}
.impito-expand-stage__empty svg {
  width: 28px;
  height: 28px;
  opacity: 0.55;
}
.impito-expand-note {
  padding-top: 8px;
}
/* Ползунок размера: шаг 1%, делений 91 — точки под дорожкой прячем, иначе
   это сплошной пунктир (просьба юзера 03.09). Сам модуль их всё равно
   рисует и меряет по ним ход бегунка, поэтому именно display: none у ряда,
   а не отказ от разметки. */
[data-expand-scale-host] .impito-quality__ticks,
[data-editor-scale-host] .impito-quality__ticks {
  display: none;
}

/* Направляющие магнитов: линия в цвет кнопки «расширить», появляется в
   момент прилипания и гаснет с концом жеста. Лежит НАД фото. Край площадки
   у линии обрезается overflow-ом ровно наполовину — на краю видна тонкая
   полоса, в центре полная. */
/* Пунктир и тоньше (03.09, просьба юзера): линия — это border у элемента
   нулевой толщины, фона нет. */
.impito-expand-guide {
  position: absolute;
  z-index: 2;
  pointer-events: none;
}
.impito-expand-guide[hidden] {
  display: none;
}
.impito-expand-guide--v {
  top: 0;
  bottom: 0;
  width: 0;
  border-left: 1.2px dashed var(--ui-accent);
  margin-left: -0.6px;
}
.impito-expand-guide--h {
  left: 0;
  right: 0;
  height: 0;
  border-top: 1.2px dashed var(--ui-accent);
  margin-top: -0.6px;
}
/* Ручка поворота (03.09.2026): кружок на ножке над верхним краем фото, как в
   Figma. Позиции пишет js трансформом; ножка — линия от края фото к кружку,
   её длину и угол тоже считает js. Только для мыши — на телефоне узлы
   остаются скрытыми (js их не показывает). */
.impito-expand-rotor {
  position: absolute;
  top: -7px;
  left: -7px;
  z-index: 4;
  width: 14px;
  height: 14px;
  padding: 0;
  border: 2px solid var(--ui-accent);
  border-radius: 50%;
  background: var(--ui-glass-btn);
  box-shadow: 0 2px 8px rgba(12, 18, 48, 0.22);
  cursor: grab;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0s, box-shadow 0.15s var(--ui-ease);
}
.impito-expand-rotor:hover {
  box-shadow: 0 0 0 4px rgba(36, 73, 242, 0.18), 0 2px 8px rgba(12, 18, 48, 0.22);
}
.impito-expand-stage.is-rotating .impito-expand-rotor {
  cursor: grabbing;
  box-shadow: 0 0 0 5px rgba(36, 73, 242, 0.24), 0 2px 8px rgba(12, 18, 48, 0.22);
}
.impito-expand-rotor[hidden] {
  display: none;
}
.impito-expand-rotor-stem {
  position: absolute;
  top: -0.75px;
  left: 0;
  z-index: 3;
  height: 1.5px;
  background: var(--ui-accent);
  transform-origin: 0 50%;
  pointer-events: none;
}
.impito-expand-rotor-stem[hidden] {
  display: none;
}
/* Бейдж щипка: размер и угол, как пилюля. Прилипшее значение — розовым. */
.impito-expand-badge {
  position: absolute;
  top: 10px;
  left: 50%;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-rail-arrow);
  -webkit-backdrop-filter: blur(2px) saturate(145%);
  backdrop-filter: blur(2px) saturate(145%);
  box-shadow: 0 6px 18px rgba(12, 18, 48, 0.16), inset 0 0 0 0.5px rgba(255, 255, 255, 0.4);
  color: var(--ui-text);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  transform: translateX(-50%);
  pointer-events: none;
}
.impito-expand-badge[hidden] {
  display: none;
}
.impito-expand-badge b {
  font-weight: 640;
}
.impito-expand-badge b.is-snapped {
  color: var(--ui-accent-ink);
}
.impito-expand-badge i {
  width: 1px;
  height: 12px;
  background: var(--ui-separator);
}

/* ПОЛОСА ПРОКРУТКИ СПРЯТАНА ВО ВСЕЙ АППЕ (03.09, просьба юзера: «справа
   палочка, которая показывает, где листаешь»). На телефоне скроллится документ,
   на широком экране — узел экрана (см. блок «ШИРОКИЙ ЭКРАН»), поэтому правило
   и на html/body, и на самих экранах. Прокрутка при этом остаётся, пропадает
   только индикатор. Вернуть — удалить этот блок. */
html,
body,
[id^="impito-"],
.impito-sidebar {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
html::-webkit-scrollbar,
body::-webkit-scrollbar,
[id^="impito-"]::-webkit-scrollbar,
.impito-sidebar::-webkit-scrollbar {
  display: none;
  width: 0;
  height: 0;
}

/* ══════════════════════════════════════════════════════════════════════════
   РЕДАКТОР — слои и отметка области (03.09.2026, оболочка). Площадка,
   магниты, направляющие, бейдж и ручка поворота — классы расширения
   (`.impito-expand-*`), здесь только своё: слои, маска, полоса слоёв,
   поле «что сделать», лист слоя.
   ══════════════════════════════════════════════════════════════════════════ */
.impito-editor-layers-host {
  position: absolute;
  inset: 0;
}
.impito-editor-layer {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  transform-origin: center;
  will-change: transform;
  -webkit-user-drag: none;
  touch-action: none;
}
.impito-editor-layer[hidden] {
  display: none;
}
.impito-editor-layer {
  cursor: grab;
}
.impito-editor-stage.is-dragging .impito-editor-layer {
  cursor: grabbing;
}
/* Активный слой — тонкая розовая рамка. outline едет вместе с transform. */
.impito-editor-layer.is-active {
  outline: 2px solid var(--ui-accent);
  outline-offset: -1px;
}
/* Холст отметки лежит НАД слоями и принимает касания только в режиме
   области; иначе он прозрачен для указателя, и слои таскаются как обычно. */
.impito-editor-mask {
  position: absolute;
  inset: 0;
  z-index: 3;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.impito-editor-stage.is-mask-mode .impito-editor-mask {
  pointer-events: auto;
  touch-action: none;
  cursor: crosshair;
}
.impito-editor-stage.is-mask-mode .impito-editor-layer {
  pointer-events: none;
}
/* Площадка и колонка слоёв рядом: площадка слева, колонка 48px справа.
   Колонка сверху вниз = от верхнего слоя к нижнему, как в редакторах. */
.impito-editor-wrap {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.impito-editor-wrap .impito-editor-stage {
  flex: 0 0 auto;
  margin: 0;
}
.impito-editor-side {
  display: flex;
  flex: 0 0 84px;
  flex-direction: column;
  gap: 10px;
  width: 84px;
  max-height: 440px;
  overflow-y: auto;
  scrollbar-width: none;
}
.impito-editor-side::-webkit-scrollbar {
  display: none;
}
/* 48 → 60px («очень маленькие»), без обводки и без кольца у активной —
   активную выделяет розовый номер (04.09, просьба юзера). Перестановка:
   у плиток переход по transform — соседи уступают место плавно, у поднятой
   перехода нет, она едет ровно за пальцем. */
.impito-editor-tile,
.impito-editor-tile__add {
  position: relative;
  flex: 0 0 84px;
  width: 84px;
  height: 84px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: pan-y;
  transition: transform 0.16s var(--ui-ease-out);
}
.impito-editor-tile img {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 14px;
  object-fit: cover;
  transition: opacity 0.15s var(--ui-ease);
  pointer-events: none;
  -webkit-user-drag: none;
  user-select: none;
}
.impito-editor-tile.is-lifting {
  z-index: 5;
  transition: none;
  touch-action: none;
}
.impito-editor-tile.is-lifting img {
  box-shadow: 0 10px 24px rgba(12, 18, 48, 0.28);
}
.impito-editor-tile.is-hidden img {
  opacity: 0.35;
}
.impito-editor-tile__name {
  position: absolute;
  top: 3px;
  left: 3px;
  min-width: 14px;
  padding: 0 4px;
  border-radius: 7px;
  background: rgba(12, 18, 48, 0.55);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
  line-height: 14px;
  text-align: center;
  pointer-events: none;
}
.impito-editor-tile.is-active .impito-editor-tile__name {
  background: var(--ui-accent);
}
.impito-editor-tile__name {
  font-size: 12px;
  line-height: 20px;
  min-width: 20px;
  border-radius: 10px;
  top: 4px;
  left: 4px;
}
/* Кнопки истории «назад/вперёд» в шапке секции площадки: две круглые
   пилюли на подложке `--ui-fill`, неактивная полупрозрачная. */
/* История — слева, сразу за заголовком, а не у правого края (04.09). */
.impito-editor-head {
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
}
.impito-editor-count {
  color: var(--ui-hint);
  font-weight: 500;
}
.impito-editor-history {
  display: inline-flex;
  gap: 6px;
}
.impito-editor-history__btn {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--ui-fill);
  color: var(--ui-text);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-editor-history__btn svg {
  width: 16px;
  height: 16px;
}
.impito-editor-history__btn:disabled {
  opacity: 0.35;
  cursor: default;
}
/* Фото к запросу: одна плитка, как референс в пикере. */
.impito-editor-ref-head {
  margin-top: 12px;
}
.impito-editor-ref {
  --ui-ref-tile: 87px;
  display: flex;
  padding: 5px 0 0 12px;
}
.impito-editor-ref .impito-style-photo,
.impito-editor-ref .impito-style-photo-add {
  width: var(--ui-ref-tile);
  flex: 0 0 var(--ui-ref-tile);
}
/* ── ЭКРАН УЧАСТКА (04.09.2026) ──
   Тёмный экран поверх редактора: сверху «назад», подпись, картинка по
   центру, снизу панель, которая выезжает, когда участок выбран; картинка
   при этом плавно уезжает вверх (transform, не высота). */
.impito-editor-area {
  position: fixed;
  inset: 0;
  z-index: 110;
  display: flex;
  flex-direction: column;
  /* КЛАССИЧЕСКИЙ ВЕРХ (04.09, ночь, просьба юзера): экран лежит НИЖЕ вуали
     (z 40), заголовка «Редактор» (z 60) и плашек профиля/баланса (z 61) —
     они общие для всех экранов; своя шапка с названием скрыта. Отступ
     сверху — под вуаль. Снизу виден таббар, панель стоит над ним. */
  z-index: 1;
  padding-top: calc(var(--ui-veil-height) + 4px);
  /* Не новый экран, а затемнённый и размытый редактор под ним (04.09). */
  /* Без затемнения и размытия — обычный розовый фон страницы, тёмный
     текст (просьба юзера 04.09, вечер). */
  background: var(--ui-bg);
  color: var(--ui-text);
  opacity: 0;
  transition: opacity 0.22s var(--ui-ease);
}
/* Своя шапка («назад» + название) не нужна: назад — кнопка Telegram,
   название — общий заголовок в вуали. !important — ниже по файлу у шапки
   свой display: flex. */
.impito-editor-area__top {
  display: none !important;
}
/* Таббар в редакторе не показываем (просьба юзера 04.09): панель стоит у
   самого низа. Класс на body ставит editor.js, пока экран активен. */
body.impito-editor-area-open .impito-tabbar {
  display: none;
}
.impito-editor-area[hidden] {
  display: none;
}
.impito-editor-area.is-open {
  opacity: 1;
}
body.impito-editor-area-open {
  overflow: hidden;
}
.impito-editor-area__top {
  position: relative;
  display: flex;
  align-items: center;
  height: 48px;
  padding: 0 8px;
}
.impito-editor-area__back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 36px;
  padding: 0 12px 0 8px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: rgba(12, 18, 48, 0.08);
  color: var(--ui-text);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-editor-area__back svg {
  width: 8px;
  height: 14px;
}
.impito-editor-area__title {
  position: absolute;
  left: 50%;
  /* В 2 раза крупнее (просьба юзера 04.09). */
  font-size: 32px;
  font-weight: 700;
  transform: translateX(-50%);
  pointer-events: none;
}
.impito-editor-area__hint {
  margin: 10px 24px 0;
  color: var(--ui-hint);
  font-size: 17px;
  text-align: center;
  transition: opacity 0.2s var(--ui-ease);
}
.impito-editor-area__stage {
  /* Выше панели: тень листа не ложится на фото/плитку (просьба юзера 04.09).
     Сама стадия тапы не ловит (иначе перекрывала верхний ряд плиток панели —
     баг 04.09), ловит только фото внутри. */
  position: relative;
  z-index: 2;
  pointer-events: none;
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  align-items: center;
  justify-content: center;
  transition: transform 0.4s cubic-bezier(0.3, 0.6, 0.1, 1);
  will-change: transform;
}
/* Клавиатура открыта: никаких переходов — панель и картинка следуют за
   вьюпортом мгновенно, иначе анимация отстаёт и дёргается (04.09). */
.impito-editor-area.is-typing .impito-editor-area__stage,
.impito-editor-area.is-typing .impito-editor-area__panel {
  transition: none;
}
/* Под фото не осталось места (клавиатура) — прячем, чтобы не лезло на
   панель (04.09, баг на Android). */
.impito-editor-area.is-cramped .impito-editor-area__stage {
  opacity: 0;
  pointer-events: none;
}
.impito-editor-area__pic {
  pointer-events: auto;
  position: relative;
  overflow: hidden;
  border-radius: 18px;
  /* Без тени и чёрной подложки — фон экрана теперь светлый (04.09). */
  background: transparent;
  box-shadow: none;
  transition: transform 0.4s cubic-bezier(0.3, 0.6, 0.1, 1);
}
.impito-editor-area__pic img {
  display: block;
  width: 100%;
  height: 100%;
  -webkit-user-drag: none;
  user-select: none;
}
.impito-editor-area__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  touch-action: none;
  cursor: crosshair;
}
/* Панель снизу: спрятана за краем, выезжает, когда участок выбран. */
.impito-editor-area__panel {
  position: absolute;
  z-index: 1;
  right: 0;
  bottom: 0;
  left: 0;
  transform: translateY(calc(100% + 24px));
  transition: transform 0.4s cubic-bezier(0.3, 0.6, 0.1, 1);
  will-change: transform;
}
.impito-editor-area.is-chosen .impito-editor-area__panel {
  transform: translateY(0);
}
/* Картинка уезжает вверх и чуть ужимается, освобождая место панели. */
.impito-editor-area.is-chosen .impito-editor-area__stage {
  /* Сдвиг и масштаб считает скрипт (`fitAreaChosen`) по высоте панели. */
  transform: translateY(var(--impito-area-shift, -9vh)) scale(var(--impito-area-scale, 0.8));
}
/* Панель — наш нижний лист (как `.impito-gen-sheet__body`): розовый фон
   страницы, скругление сверху, внутри «сборная солянка» с экрана фото:
   секция «промпт» с растущим полем и акцентным плейсхолдером, секция
   «референс» с плиткой, розовая кнопка. Радиусы — карточные (04.09). */
.impito-editor-area__sheet {
  /* border-box ОБЯЗАТЕЛЬНО: со стандартным content-box ширина 100% плюс
     поля 14px давала лист на 28px шире экрана, и всё содержимое уезжало
     вправо (04.09, «куда-то вправо уходит»). */
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 0;
  width: min(100%, 560px);
  margin: 0 auto;
  /* Сверху воздуха больше: заголовок «промпт» не липнет к кромке (04.09). */
  padding: 24px 14px calc(14px + var(--ui-safe-bottom));
  /* Скругление крупнее карточного — под радиус экрана телефона (04.09). */
  border-radius: 48px 48px 0 0;
  background: var(--ui-bg);
  box-shadow: 0 -12px 40px rgba(12, 18, 48, 0.28);
  color: var(--ui-text);
}
.impito-editor-area__section.ui-section {
  margin: 0 0 12px;
}
/* Поле ниже, чем на экране фото: под ним ещё референс и кнопка. */
.impito-editor-area__sheet .impito-style-prompt.impito-prompt-autogrow.ui-field {
  max-height: 120px;
}
/* Длинный плейсхолдер переносится на вторую строку и в пустом поле высотой
   в одну строку показывал бы полосу прокрутки. */
.impito-editor-area__sheet .impito-style-prompt.impito-prompt-autogrow:placeholder-shown {
  overflow: hidden;
}
.impito-editor-area__ref {
  --ui-ref-tile: 72px;
  /* Плитка в одну линию с полем промпта (отступ карточки 12px). */
  padding: 5px 0 0 12px;
}
.impito-editor-area__go-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 12px;
}
.impito-editor-area__go-row .impito-style-quantity {
  flex: 0 0 auto;
  gap: 5px;
}
/* Счётчик компактнее, чтобы «генерировать · 2 токена» влезло на 390px. */
.impito-editor-area__go-row .impito-style-count {
  min-width: 36px;
}
.impito-editor-area__go-row .impito-style-stepper__button {
  width: 34px;
}
.impito-editor-area__go-row .impito-editor-area__go {
  padding: 0 10px;
  font-size: 14px;
}
.impito-editor-area__go {
  flex: 1 1 auto;
  min-width: 0;
  height: 52px;
  font-size: 15px;
}
/* «Отправлено» под кнопкой — ссылка в историю. */
.impito-editor-area__sent {
  margin: 8px 12px 0;
  color: var(--ui-accent-strong);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  text-align: center;
}
.impito-editor-area__sent[hidden] {
  display: none;
}
/* «Редактировать область» на экране редактора — буквально розовая кнопка.
   Обычного размера и по центру, не во всю ширину («огромная и касается
   стенок» — 04.09): отступы от края как у карточек (12px). */
.impito-editor-area-btn {
  display: flex;
  width: max-content;
  max-width: calc(100% - 24px);
  height: 44px;
  margin: 0 auto;
  padding: 0 24px;
  font-size: 14px;
}
.impito-editor-area-btn svg {
  width: 20px;
  height: 20px;
}
.impito-editor-area-sub {
  margin: 8px 4px 0;
  color: var(--ui-hint);
  font-size: 13px;
  text-align: center;
}

/* Кружок-превью кисти по центру площадки: белый, диаметр = кисть, край
   размывается фильтром по мягкости. Показывается на 0.7с при движении
   ползунков. */
.impito-editor-brush-preview {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 4;
  border-radius: 50%;
  background: var(--ui-white-veil-strong);
  box-shadow: 0 0 0 1px rgba(12, 18, 48, 0.18);
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.impito-editor-brush-preview[hidden] {
  display: none;
}
/* Глаз — в правом нижнем углу плитки, своя кнопка. */
.impito-editor-tile__eye {
  position: absolute;
  right: 3px;
  bottom: 3px;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--ui-white-veil-strong);
  color: var(--ui-text);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-editor-tile__eye svg {
  width: 15px;
  height: 15px;
}
.impito-editor-tile.is-hidden .impito-editor-tile__eye {
  color: var(--ui-hint);
}
.impito-editor-tile__add {
  border: 1.5px dashed rgba(12, 18, 48, 0.22);
  border-radius: 14px;
  color: var(--ui-accent-ink);
  display: grid;
  place-items: center;
}
.impito-editor-tile__add svg {
  width: 20px;
  height: 20px;
}
/* Сегмент «закрасить пальцем / обвести рамкой» внутри карточки шага 2:
   две пилюли в подложке `--ui-fill`, активная — розовая. */
.impito-editor-tools {
  display: flex;
  gap: 4px;
  margin: 10px 12px 0;
  padding: 4px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-fill);
}
.impito-editor-seg-row {
  display: block;
  padding: 10px 12px 12px;
}
.impito-editor-seg {
  margin: 0;
}
.impito-editor-seg .impito-editor-tool {
  flex-direction: row;
  gap: 6px;
  padding: 9px 6px;
  font-size: 12px;
}
.impito-editor-seg .impito-editor-tool svg {
  width: 16px;
  height: 16px;
}
.impito-editor-tool {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  min-width: 0;
  padding: 7px 2px 6px;
  border: 0;
  border-radius: calc(var(--ui-radius-card) - 4px);
  background: transparent;
  color: var(--ui-text);
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color 0.15s var(--ui-ease),
    color 0.15s var(--ui-ease);
}
.impito-editor-tool svg {
  width: 20px;
  height: 20px;
}
.impito-editor-tool.is-active {
  background: var(--ui-accent);
  color: var(--ui-accent-text);
}
.impito-editor-tool:disabled {
  opacity: 0.4;
  cursor: default;
}
.impito-editor-note {
  padding-top: 8px;
}
/* Лист слоя: ползунок прозрачности сверху, действия строками. */
.impito-editor-sheet__slider {
  padding: 4px 0 6px;
}
.impito-editor-sheet__actions {
  border-top: 0.5px solid var(--ui-separator);
}
.impito-editor-sheet__actions .impito-sheet__option:disabled {
  opacity: 0.4;
  cursor: default;
}
.impito-editor-sheet__danger {
  color: var(--ui-destructive);
}
/* Поле «что сделать с областью» — карточка с textarea в наших цветах. */
.impito-editor-prompt-card {
  padding: 0;
}
.impito-editor-prompt {
  display: block;
  width: 100%;
  min-height: 84px;
  padding: 12px 14px;
  border: 0;
  border-radius: var(--ui-radius-card);
  background: transparent;
  color: var(--ui-text);
  caret-color: var(--ui-accent);
  font: inherit;
  font-size: 16px;
  line-height: 1.4;
  resize: none;
  outline: none;
}
.impito-editor-prompt::placeholder {
  color: var(--ui-hint);
}
/* Превью в листе: картинка и маска рядом, маска на клетчатом фоне. */
.impito-editor-preview__pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 8px;
  background: transparent;
  box-shadow: none;
}
.impito-editor-preview__pair img {
  width: 100%;
  max-height: 40vh;
  object-fit: contain;
  border-radius: 12px;
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.12);
}
.impito-editor-preview__pair img[data-editor-preview-mask] {
  background:
    linear-gradient(45deg, rgba(12, 18, 48, 0.12) 25%, transparent 25%, transparent 75%, rgba(12, 18, 48, 0.12) 75%),
    linear-gradient(45deg, rgba(12, 18, 48, 0.12) 25%, transparent 25%, transparent 75%, rgba(12, 18, 48, 0.12) 75%);
  background-size: 16px 16px;
  background-position: 0 0, 8px 8px;
  max-height: 24vh;
}
.impito-editor-preview__pair img[hidden] {
  display: none;
}

/* Лист «так уйдёт нейросети»: референс целиком, на клетчатой подложке, чтобы
   белое поле было видно как поле, а не сливалось с панелью. */
.impito-expand-preview {
  padding: 0 0 14px;
}
.impito-expand-preview__shot {
  margin: 4px 18px 0;
  border-radius: 12px;
  overflow: hidden;
  background:
    linear-gradient(45deg, rgba(12, 18, 48, 0.08) 25%, transparent 25%, transparent 75%, rgba(12, 18, 48, 0.08) 75%),
    linear-gradient(45deg, rgba(12, 18, 48, 0.08) 25%, transparent 25%, transparent 75%, rgba(12, 18, 48, 0.08) 75%);
  background-size: 16px 16px;
  background-position: 0 0, 8px 8px;
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.12);
}
.impito-expand-preview__shot img {
  display: block;
  width: 100%;
  max-height: 52vh;
  object-fit: contain;
}
.impito-expand-preview__meta {
  margin: 10px 18px 0;
  color: var(--ui-hint);
  font-size: 13px;
  font-weight: 500;
  text-align: center;
}

/* ── РЕДАКТОР, ПРОСТАЯ КОНЦЕПЦИЯ (04.09.2026) ──
   Одно фото → экран участка. Площадки/слоёв больше нет; старые классы
   `.impito-editor-*` выше остаются для истории. */
.impito-editor-photo {
  overflow: hidden;
  padding: 0;
  background: var(--ui-media-bg);
}
.impito-editor-photo img {
  display: block;
  width: 100%;
  max-height: 46vh;
  object-fit: contain;
  -webkit-user-drag: none;
  user-select: none;
}
.impito-editor-page .impito-editor-area-btn {
  margin-top: 12px;
}
/* Секция пикера не display:none, а невидимая и вне потока: с display:none
   iOS рисовал всплывашку выбора файла сдвоенной (баг WebKit, 04.09).
   Инпуты остаются «в документе», якорь всплывашки — центр экрана. */
.impito-editor-picker {
  position: fixed;
  top: 40%;
  left: 50%;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}
/* Большая плитка добавления фото (экран без фото). */
.impito-editor-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: calc(100% - 24px);
  aspect-ratio: 4 / 5;
  max-height: 56vh;
  margin: 0 12px;
  padding: 0;
  border: 2px dashed rgba(36, 73, 242, 0.55);
  border-radius: var(--ui-radius-card);
  background: var(--ui-white-veil);
  color: var(--ui-text);
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.15s var(--ui-ease), background-color 0.18s var(--ui-ease);
}
.impito-editor-drop:active {
  transform: scale(0.985);
  background: var(--ui-white-veil-strong);
}
.impito-editor-drop__icon {
  display: flex;
  width: 72px;
  height: 72px;
  align-items: center;
  justify-content: center;
  margin-bottom: 6px;
  border-radius: 50%;
  background: var(--ui-glass-btn);
  color: var(--ui-accent-ink);
}
.impito-editor-drop__icon svg {
  width: 30px;
  height: 30px;
}
.impito-editor-drop__title {
  font-size: 17px;
  font-weight: 600;
}
.impito-editor-drop__sub {
  color: var(--ui-hint);
  font-size: 13.5px;
}
.impito-editor-replace.ui-button {
  display: flex;
  width: max-content;
  height: 38px;
  margin: 10px auto 0;
  padding-inline: 18px;
}
/* Плашка снизу: цена + кнопка, без счётчика количества. */
.impito-editor-submit {
  justify-content: space-between;
}
.impito-editor-submit .impito-style-generate {
  flex: 1 1 auto;
  max-width: 220px;
  height: 44px;
}
/* Действия — ровная сетка 3×2 одинаковых плиток с иконкой и подписью
   (чипы разной ширины смотрелись криво — 04.09, вечер). */
.impito-editor-area__actions {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 0 12px;
}
.impito-editor-action {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  height: 60px;
  padding: 0 6px;
  border: 0;
  /* Скругление сильнее (просьба юзера 04.09) — карточный радиус. */
  border-radius: var(--ui-radius-card);
  background: var(--ui-glass-btn);
  color: var(--ui-text);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color 0.18s var(--ui-ease),
    color 0.18s var(--ui-ease),
    transform 0.15s var(--ui-ease);
}
/* Подсказка выбранного действия — одной строкой под сеткой, место
   зарезервировано, чтобы панель не прыгала. */
.impito-editor-area__action-hint[hidden] {
  display: none;
}
.impito-editor-area__action-hint {
  min-height: 16px;
  margin: 8px 12px 0;
  color: var(--ui-hint);
  font-size: 12.5px;
  line-height: 16px;
  text-align: center;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.impito-editor-action svg {
  width: 21px;
  height: 21px;
  color: var(--ui-accent-ink);
}
.impito-editor-action:active {
  transform: scale(0.96);
}
.impito-editor-action.is-active {
  background: var(--ui-accent);
  color: var(--ui-accent-text);
}
.impito-editor-action.is-active svg {
  color: var(--ui-accent-text);
}
/* Фото-пример — наш пунктирный квадратик СЛЕВА от поля пожеланий, той же
   высоты, что строка поля (44px); поле занимает остальное. */
.impito-editor-area__input-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0 12px;
}
.impito-editor-area__ref.impito-editor-ref {
  --ui-ref-tile: 44px;
  flex: 0 0 auto;
  padding: 0;
}
.impito-editor-area__ref .impito-style-photo-add,
.impito-editor-area__ref .impito-style-photo {
  width: 44px;
  height: 44px;
  flex: 0 0 44px;
}
.impito-editor-area__ref .impito-style-photo-add,
.impito-editor-area__ref .impito-style-photo img {
  border-radius: 14px;
}
.impito-editor-area__ref .impito-style-photo img {
  width: 44px;
  height: 44px;
  object-fit: cover;
}
.impito-editor-area__ref .impito-style-photo__remove {
  top: -6px;
  right: -6px;
  width: 20px;
  height: 20px;
}
.impito-editor-area__prompt-card.ui-card {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  /* Карточка прозрачная и без полей: белая таблетка — само поле, и оно
     border-box, чтобы 44px были полной высотой, как у квадратика слева. */
  padding: 0;
  background: transparent;
  box-shadow: none;
}
.impito-editor-area__prompt-card .impito-style-prompt.impito-prompt-autogrow.ui-field {
  box-sizing: border-box;
  background: var(--ui-field-bg);
}

/* ── Экран участка = весь редактор (04.09, вечер) ──
   Без фото: в слоте фото — большая пунктирная плитка «добавь фото», панель
   снизу приглушена; в шапке справа «другое фото». */
.impito-editor-area__pic.is-empty {
  overflow: visible;
  background: transparent;
  box-shadow: none;
}
/* `display:block` у картинки перебивал атрибут hidden — пустая картинка
   занимала место, и плитка уезжала под панель (04.09). */
.impito-editor-area__pic img[hidden],
.impito-editor-area__pic canvas[hidden] {
  display: none;
}
/* Плитка «добавь фото» — как пустая площадка расширения: нежно-розовая
   карточка, внутри серый пунктир, иконка и подпись (просьба юзера 04.09). */
.impito-editor-area__empty {
  /* border-box: с content-box поля 12px делали плитку на 24px шире слота,
     и она вылезала вправо (04.09, «уехала вправо»). */
  box-sizing: border-box;
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  padding: 12px;
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.1);
  color: var(--ui-hint);
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.15s var(--ui-ease);
}
.impito-editor-area__empty:active {
  transform: scale(0.985);
}
.impito-editor-area__empty-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  height: 100%;
  border: 1.5px dashed rgba(12, 18, 48, 0.22);
  border-radius: calc(var(--ui-radius-card) - 8px);
  font-size: 13px;
  font-weight: 500;
  text-align: center;
}
.impito-editor-area__empty-inner svg {
  width: 28px;
  height: 28px;
  opacity: 0.55;
}
.impito-editor-area__file {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: pointer;
  font-size: 0;
}
/* Без фото гаснет только основной блок панели (действия, пожелания, запуск);
   панель по-прежнему листается, а результаты ниже открываются по тапу
   (07.09, просьба юзера). */
.impito-editor-area__panel.is-disabled .impito-editor-area__main {
  opacity: 0.55;
  pointer-events: none;
}
/* Обёртка фото: нужна, чтобы крестик мог висеть ЗА краем фото (сам
   `.impito-editor-area__pic` режет всё по своему скруглению). */
.impito-editor-area__picwrap {
  position: relative;
  flex: 0 0 auto;
}
/* Крестик «убрать фото» — за правым верхним углом фото, крупный. */
.impito-editor-area__remove {
  position: absolute;
  z-index: 4;
  top: -14px;
  right: -14px;
  display: flex;
  width: 42px;
  height: 42px;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--ui-glass-btn);
  color: var(--ui-text);
  box-shadow: 0 3px 10px rgba(12, 18, 48, 0.2), inset 0 0 0 0.5px rgba(12, 18, 48, 0.08);
  cursor: pointer;
  pointer-events: auto;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.15s var(--ui-ease);
}
.impito-editor-area__remove[hidden] {
  display: none;
}
.impito-editor-area__remove svg {
  width: 20px;
  height: 20px;
}
.impito-editor-area__remove:active {
  transform: scale(0.92);
}
/* Иконка «поменять фото» в углу фото (04.09): круг 34px, поверх канваса.
   Не используется с 04.09 (заменена крестиком за фото), правила оставлены. */
.impito-editor-area__swap {
  position: absolute;
  z-index: 3;
  top: 8px;
  right: 8px;
  display: flex;
  width: 34px;
  height: 34px;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--ui-glass-btn);
  color: var(--ui-text);
  box-shadow: 0 2px 8px rgba(12, 18, 48, 0.18);
  cursor: pointer;
  pointer-events: auto;
  -webkit-tap-highlight-color: transparent;
}
.impito-editor-area__swap[hidden] {
  display: none;
}
.impito-editor-area__swap svg {
  width: 18px;
  height: 18px;
}
.impito-editor-area__swap:active {
  transform: scale(0.94);
}
.impito-editor-area__swapfile {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: pointer;
  font-size: 0;
}
.impito-editor-area__replace {
  position: absolute;
  right: 12px;
  height: 34px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--ui-radius-pill);
  background: rgba(12, 18, 48, 0.08);
  color: var(--ui-text);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-editor-area__replace[hidden] {
  display: none;
}

/* ── РЕДАКТОР НА ПК (04.09.2026, просьба юзера): слева меню, дальше большой
   квадрат-площадка, справа панель «что сделать» колонкой. Тот же медиа-запрос,
   что у всей широкой раскладки. impito-editor-area — ПК. ── */
@media (min-aspect-ratio: 1/1) and (min-width: 1000px) {
  /* Не поверх меню: экран участка живёт внутри #impito-editor (он absolute с
     left = ширина меню), а не поверх всего окна. */
  .impito-editor-area {
    position: absolute;
    inset: 0;
    /* Ниже вуали (40) и заголовка (60): «Редактор» в вуали должен быть виден. */
    z-index: 1;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 420px;
    grid-template-rows: auto auto minmax(0, 1fr);
    column-gap: 28px;
    /* Сверху место под общий заголовок экрана в вуали («Редактор», как у
       остальных экранов ПК); своя шапка с «назад» здесь не нужна. */
    padding: 76px 32px 28px;
    overflow: hidden;
  }
  .impito-editor-area__top {
    display: none;
  }
  .impito-editor-area__hint {
    grid-column: 1;
    margin: 4px 0 0;
  }
  .impito-editor-area__stage {
    grid-column: 1;
    grid-row: 3;
    /* Подгонка под панель снизу здесь не нужна — колонки не пересекаются. */
    transform: none !important;
    opacity: 1 !important;
  }
  .impito-editor-area.is-cramped .impito-editor-area__stage {
    opacity: 1 !important;
  }
  /* Панель — правая колонка, статичная, без выезда снизу. */
  .impito-editor-area__panel {
    grid-column: 2;
    grid-row: 2 / 4;
    position: static;
    align-self: start;
    transform: none !important;
    transition: none;
  }
  .impito-editor-area__sheet {
    width: 100%;
    padding: 18px 16px 18px;
    border-radius: var(--ui-radius-card);
    background: var(--ui-white-veil);
    box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.08);
  }
  .impito-editor-area__go-row .impito-editor-area__go {
    font-size: 15px;
  }
}

/* ── ПРОМО-КАРТОЧКА НА ГЛАВНОЙ «новый режим: редактор фото» (04.09.2026) ──
   Широкая карточка на розовой картинке с маскотом слева; текст и кнопка —
   в пустой правой части картинки. Временная, прячется крестиком. */
.impito-home-promo-section.ui-section {
  margin: 0 0 18px;
}
.impito-home-promo {
  position: relative;
  display: block;
  overflow: hidden;
  margin: 0 12px;
  border-radius: var(--ui-radius-card);
  background: #4769f1;
  color: #fff;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.15s var(--ui-ease);
}
.impito-home-promo:active {
  transform: scale(0.985);
}
.impito-home-promo__bg {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: 200px;
  object-fit: cover;
  object-position: left center;
  -webkit-user-drag: none;
  user-select: none;
}
.impito-home-promo__text {
  position: absolute;
  top: 50%;
  right: 16px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 56%;
  transform: translateY(-50%);
  text-align: left;
  text-shadow: 0 1px 6px rgba(20, 40, 120, 0.35);
}
.impito-home-promo__kicker {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.85;
}
.impito-home-promo__title {
  margin-top: 2px;
  font-size: 21px;
  font-weight: 800;
  line-height: 1.1;
}
.impito-home-promo__sub {
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.3;
  opacity: 0.92;
}
.impito-home-promo__cta {
  display: inline-flex;
  align-items: center;
  height: 34px;
  margin-top: 12px;
  padding: 0 16px;
  border-radius: var(--ui-radius-pill);
  background: #fff;
  color: #4663d8;
  font-size: 13.5px;
  font-weight: 700;
  text-shadow: none;
}
/* Баннер с названием Fid. Синий градиент — фирменный цвет с аватара бота,
   он же фон картинки, поэтому без файла карточка не выглядит пустой. */
.impito-home-promo--brand {
  min-height: 168px;
  background: linear-gradient(135deg, #0434e8 0%, #2449f2 62%, #4a6bff 100%);
}
.impito-home-promo--brand .impito-home-promo__bg[hidden] {
  display: none;
}
.impito-home-promo__title--brand {
  font-size: 40px;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
}
/* Маскот на картинке занимает левую половину — текст не должен на него
   наезжать. */
.impito-home-promo--brand .impito-home-promo__text {
  right: 14px;
  width: 48%;
}
.impito-home-promo--brand .impito-home-promo__cta {
  color: #0434e8;
}
.impito-home-promo__close {
  position: absolute;
  top: 10px;
  right: 10px;
  display: flex;
  width: 28px;
  height: 28px;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.22);
  color: #fff;
}
.impito-home-promo__close svg {
  width: 11px;
  height: 11px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}
@media (min-width: 700px) {
  .impito-home-promo__bg {
    max-height: 240px;
  }
  .impito-home-promo__title {
    font-size: 26px;
  }
  .impito-home-promo__title--brand {
    font-size: 48px;
  }
  .impito-home-promo__sub {
    font-size: 15px;
  }
}

/* Durable generation receipt recovery, shared by every launch screen. */
.impito-generation-recovery {
  width: min(88vw, 420px);
  box-sizing: border-box;
  border: 0;
  border-radius: 24px;
  padding: 28px;
  background: var(--ui-card);
  color: var(--template-color-text, #202126);
  font-family: inherit;
}
.impito-generation-recovery::backdrop { background: rgb(0 0 0 / 45%); }
.impito-generation-recovery h2 { margin: 0 0 16px; font-size: 22px; }
.impito-generation-recovery p { line-height: 1.5; }
.impito-generation-recovery button { width: 100%; margin-top: 12px; }

/* ═══ ЛЕНТА РЕЗУЛЬТАТОВ НА ЭКРАНЕ ГЕНЕРАЦИИ ФОТО (07.09.2026, просьба юзера) ═══
   Две колонки плиток под ползунком качества: новые — сверху слева, старые
   уезжают ниже. Плитка держит пропорцию через padding-bottom от переменной
   --r (ширина/высота): смена --r анимируется обычным переходом, а
   aspect-ratio в вебвью анимируется не везде. Логика — photo_results.js. */
.impito-results {
  /* Чуть воздуха между ползунком качества и снимками (07.09.2026, «слишком
     близко»): 24px нижнего поля секции качества + 12px здесь. */
  margin: 12px 12px 0;
}
.impito-results[hidden] {
  display: none;
}
.impito-results__cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  align-items: start;
}
.impito-results__col {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 10px;
}
.impito-result {
  --r: 1;
  position: relative;
  display: block;
  width: 100%;
  height: 0;
  padding: 0 0 calc(100% / var(--r));
  overflow: hidden;
  border: 0;
  border-radius: 18px;
  background: var(--ui-card);
  box-shadow: inset 0 0 0 0.5px rgba(12, 18, 48, 0.08);
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: padding-bottom 0.6s cubic-bezier(0.3, 0.7, 0.2, 1);
}
.impito-result.is-done:active {
  transform: scale(0.98);
}
.impito-result__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.45s var(--ui-ease);
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.impito-result__img.is-loaded {
  opacity: 1;
}
/* СЛОЙ ОЖИДАНИЯ: точечная текстура и три мягких пятна (мятное, сиреневое,
   небесное), медленно плавающих по площади — как в присланном юзером видео,
   только чуть заметнее и с нежным градиентом. Пятна — псевдоэлементы с
   радиальным градиентом и своими траекториями; текстура — мелкая сетка точек. */
.impito-result__wait {
  position: absolute;
  inset: 0;
  overflow: hidden;
  /* Вся площадь чуть подкрашена, чтобы пустых углов не было: мятный,
     небесный и сиреневый по диагонали поверх белёсой подложки. */
  background:
    linear-gradient(
      135deg,
      rgba(196, 240, 220, 0.35) 0%,
      rgba(200, 228, 255, 0.3) 50%,
      rgba(222, 208, 255, 0.35) 100%
    ),
    var(--ui-wait-bg);
  opacity: 0;
  transition: opacity 0.5s var(--ui-ease);
  pointer-events: none;
}
.impito-result.is-pending .impito-result__wait {
  opacity: 1;
}
.impito-result.is-done .impito-result__wait {
  opacity: 0;
  transition-delay: 0.25s;
}
/* Точки мельче и светлее, и ПРОЯВЛЯЮТСЯ ПЯТНОМ, которое само плавает по
   плитке (как на присланном видео): маска — мягкий круг, её положение едет
   по кругу, остальная сетка почти не видна. */
.impito-result__dots {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(var(--ui-wait-dot) 0.45px, transparent 0.9px);
  background-size: 4px 4px;
  -webkit-mask-image: radial-gradient(circle, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.35) 38%, rgba(0, 0, 0, 0.08) 62%, transparent 78%);
  mask-image: radial-gradient(circle, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.35) 38%, rgba(0, 0, 0, 0.08) 62%, transparent 78%);
  -webkit-mask-size: 180% 180%;
  mask-size: 180% 180%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  animation: impito-dots-drift 8s ease-in-out infinite;
}
@keyframes impito-dots-drift {
  0% { -webkit-mask-position: 0% 0%; mask-position: 0% 0%; opacity: 0.55; }
  30% { -webkit-mask-position: 100% 30%; mask-position: 100% 30%; opacity: 0.9; }
  60% { -webkit-mask-position: 60% 100%; mask-position: 60% 100%; opacity: 0.7; }
  85% { -webkit-mask-position: 0% 70%; mask-position: 0% 70%; opacity: 0.9; }
  100% { -webkit-mask-position: 0% 0%; mask-position: 0% 0%; opacity: 0.55; }
}
/* Пятна больше плитки и тусклее: каждое покрывает больше половины площади,
   цвета приглушены — нежно, без «пустых» углов (07.09.2026, просьба юзера). */
.impito-result__glow {
  position: absolute;
  width: 125%;
  aspect-ratio: 1;
  border-radius: 50%;
  filter: blur(18px);
  opacity: 0.75;
  will-change: transform;
}
.impito-result__glow--a {
  top: -35%;
  left: -30%;
  background: radial-gradient(circle, rgba(184, 236, 212, 0.75) 0%, rgba(184, 236, 212, 0) 66%);
  animation: impito-glow-a 7s ease-in-out infinite;
}
.impito-result__glow--b {
  right: -35%;
  bottom: -30%;
  background: radial-gradient(circle, rgba(214, 200, 250, 0.75) 0%, rgba(214, 200, 250, 0) 66%);
  animation: impito-glow-b 8s ease-in-out infinite;
}
.impito-result__glow--c {
  top: 15%;
  left: 5%;
  width: 100%;
  background: radial-gradient(circle, rgba(196, 226, 250, 0.7) 0%, rgba(196, 226, 250, 0) 66%);
  animation: impito-glow-c 9s ease-in-out infinite;
}
@keyframes impito-glow-a {
  0% { transform: translate(0, 0) scale(1); }
  35% { transform: translate(45%, 25%) scale(1.1); }
  70% { transform: translate(10%, 60%) scale(0.95); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes impito-glow-b {
  0% { transform: translate(0, 0) scale(1); }
  40% { transform: translate(-45%, -20%) scale(1.08); }
  75% { transform: translate(-15%, -55%) scale(0.92); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes impito-glow-c {
  0% { transform: translate(0, 0) scale(0.95); }
  30% { transform: translate(-30%, 20%) scale(1.1); }
  65% { transform: translate(25%, -25%) scale(1); }
  100% { transform: translate(0, 0) scale(0.95); }
}
/* Ошибка: плитка остаётся в сетке, тап уводит в историю к деталям. */
.impito-result__fail {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 12px;
  color: var(--ui-hint);
  font-size: 13px;
  text-align: center;
}
.impito-result.is-error .impito-result__fail {
  display: flex;
}
.impito-result.is-error {
  background: var(--ui-white-veil);
}
@media (prefers-reduced-motion: reduce) {
  .impito-result__glow,
  .impito-result__dots {
    animation: none;
  }
}

/* ═══ ПРОСМОТР СНИМКА ═══
   Тёмный экран поверх всего (ниже листов 120 и тостов 130, выше таббара 80).
   Кадр по центру, щипок-зум и перетаскивание — pointer events в модуле,
   поэтому touch-action: none. Сверху круглые «инфо» и «сохранить» на манер
   .impito-gen-info из истории; снизу три действия с подписями. Тап по кадру
   прячет и возвращает кнопки. */
.impito-viewer {
  --viewer-dim: 1;
  position: fixed;
  inset: 0;
  z-index: 115;
  display: flex;
  flex-direction: column;
  background: rgba(0, 0, 0, var(--viewer-dim));
  opacity: 0;
  transition: opacity 0.2s var(--ui-ease);
}
.impito-viewer[hidden] {
  display: none;
}
.impito-viewer.is-open {
  opacity: 1;
}
body.impito-viewer-open {
  overflow: hidden;
}
.impito-viewer__stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}
.impito-viewer__img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  transform-origin: center center;
  will-change: transform;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  pointer-events: none;
}
.impito-viewer__top,
.impito-viewer__bottom {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 2;
  display: flex;
  transition:
    opacity 0.2s var(--ui-ease),
    transform 0.2s var(--ui-ease);
}
/* Верхние кнопки — сразу под шапкой Telegram, без запаса контента страницы
   (07.09.2026, «подними повыше»). */
.impito-viewer__top {
  top: 0;
  justify-content: flex-end;
  gap: 10px;
  padding: calc(max(var(--ui-fullscreen-top) * 1.5 + var(--ui-veil-platform, 0px), 56px + var(--ui-safe-top)) - 10px) 16px 0;
}
/* Три равные колонки: значки стоят по центрам колонок, а не «как получится»
   от разной длины подписей (07.09.2026, «снизу криво стоят»). */
.impito-viewer__bottom {
  bottom: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  justify-items: center;
  padding: 18px 8px calc(22px + var(--ui-safe-bottom));
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.55) 100%);
}
.impito-viewer.is-chrome-hidden .impito-viewer__top {
  opacity: 0;
  transform: translateY(-12px);
  pointer-events: none;
}
.impito-viewer.is-chrome-hidden .impito-viewer__bottom {
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
}
.impito-viewer__round {
  display: grid;
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  -webkit-backdrop-filter: blur(12px) saturate(1.3);
  backdrop-filter: blur(12px) saturate(1.3);
  box-shadow: inset 0 0 0 0.5px rgba(255, 255, 255, 0.22);
  color: #fff;
  cursor: pointer;
  place-items: center;
  -webkit-tap-highlight-color: transparent;
}
.impito-viewer__round svg {
  width: 22px;
  height: 22px;
}
.impito-viewer__round:active {
  background: rgba(255, 255, 255, 0.3);
}
.impito-viewer__action {
  display: flex;
  flex: 0 1 auto;
  min-width: 0;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 0;
  border: 0;
  background: none;
  color: #fff;
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-viewer__action:active .impito-viewer__round {
  background: rgba(255, 255, 255, 0.3);
}
.impito-viewer__label {
  max-width: 108px;
  overflow: hidden;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.15;
  text-align: center;
  white-space: nowrap;
  text-overflow: ellipsis;
  opacity: 0.92;
}

/* Листы внутри просмотра — общие .impito-sheet, свои только строки. */
.impito-results-sheet__rows {
  padding: 4px 18px 14px;
}
.impito-results-row {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  padding: 11px 0;
  font-size: 15px;
}
.impito-results-row + .impito-results-row {
  border-top: 0.5px solid var(--ui-separator);
}
.impito-results-row__label {
  flex: 0 0 auto;
  color: var(--ui-hint);
}
.impito-results-row__value {
  min-width: 0;
  color: var(--ui-text);
  font-weight: 600;
  text-align: right;
  overflow-wrap: anywhere;
}
.impito-results-row--prompt {
  flex-direction: column;
  gap: 4px;
}
.impito-results-row--prompt .impito-results-row__value {
  display: -webkit-box;
  overflow: hidden;
  font-weight: 400;
  text-align: left;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 6;
}
.impito-results-sheet__empty {
  margin: 0;
  padding: 14px 18px 18px;
  color: var(--ui-hint);
  font-size: 15px;
}
/* ВСПЛЫВАЮЩЕЕ МЕНЮ «ИЗМЕНИТЬ РАЗМЕР» (07.09.2026, видео юзера из галереи
   iOS): тёмное стекло вырастает из кнопки с пружинкой. Точку роста ставит
   скрипт (transform-origin в центр кнопки), здесь — вид и переход. */
.impito-viewer-pop {
  position: absolute;
  inset: 0;
  z-index: 3;
}
.impito-viewer-pop[hidden] {
  display: none;
}
.impito-viewer-pop__backdrop {
  position: absolute;
  inset: 0;
}
.impito-viewer-pop__menu {
  position: absolute;
  right: 12px;
  bottom: 120px;
  min-width: 232px;
  padding: 6px 0;
  border-radius: 22px;
  background: rgba(44, 44, 46, 0.72);
  -webkit-backdrop-filter: blur(24px) saturate(1.6);
  backdrop-filter: blur(24px) saturate(1.6);
  box-shadow:
    0 18px 44px rgba(0, 0, 0, 0.45),
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.14);
  color: #fff;
  opacity: 0;
  transform: scale(0.25);
  transform-origin: 100% 100%;
  transition:
    transform 0.34s cubic-bezier(0.34, 1.45, 0.64, 1),
    opacity 0.16s var(--ui-ease);
  will-change: transform, opacity;
}
.impito-viewer-pop.is-open .impito-viewer-pop__menu {
  opacity: 1;
  transform: scale(1);
}
.impito-viewer-pop__item {
  display: flex;
  width: 100%;
  min-height: 46px;
  align-items: center;
  gap: 14px;
  padding: 0 18px;
  border: 0;
  background: none;
  color: #fff;
  font: inherit;
  font-size: 16px;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-viewer-pop__item + .impito-viewer-pop__item {
  border-top: 0.5px solid rgba(255, 255, 255, 0.14);
}
.impito-viewer-pop__item:active {
  background: rgba(255, 255, 255, 0.12);
}
.impito-viewer-pop__item.is-active {
  color: rgba(255, 255, 255, 0.55);
}
.impito-viewer-pop__frame {
  display: inline-flex;
  width: 22px;
  height: 22px;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
}
.impito-viewer-pop__box {
  display: block;
  border: 1.6px solid currentColor;
  border-radius: 4px;
}
.impito-viewer-pop__label {
  white-space: nowrap;
}
/* Двухстрочный пункт (сохранить): подпись и пояснение, как в листе истории. */
.impito-viewer-pop__item--two {
  min-height: 56px;
  padding-top: 8px;
  padding-bottom: 8px;
}
.impito-viewer-pop__text {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
}
.impito-viewer-pop__hint {
  color: rgba(255, 255, 255, 0.58);
  font-size: 12.5px;
  white-space: nowrap;
}
.impito-viewer-pop__frame svg {
  width: 20px;
  height: 20px;
}
/* Верхнее меню растёт вниз из кнопки «сохранить»/«инфо». */
.impito-viewer-pop--top .impito-viewer-pop__menu {
  top: 120px;
  bottom: auto;
  transform-origin: 100% 0%;
}
/* В истории меню живёт на обычной странице: контейнер фиксированный на весь
   экран, чтобы тап мимо закрывал, а меню считалось от viewport. */
.impito-viewer-pop--fixed {
  position: fixed;
  z-index: 110;
}
/* «Инфо»: пары ключ–значение на тёмном стекле, без промпта. */
.impito-viewer-pop__menu--info {
  min-width: 248px;
  padding: 4px 0;
}
.impito-viewer-pop__row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 18px;
  font-size: 15px;
}
.impito-viewer-pop__row + .impito-viewer-pop__row {
  border-top: 0.5px solid rgba(255, 255, 255, 0.14);
}
.impito-viewer-pop__key {
  flex: 0 0 auto;
  color: rgba(255, 255, 255, 0.6);
}
.impito-viewer-pop__val {
  min-width: 0;
  color: #fff;
  font-weight: 600;
  text-align: right;
  white-space: nowrap;
}
/* СВЕТЛОЕ МЕНЮ — для истории (07.09.2026, просьба юзера «в истории белую
   менюшку»): то же стекло, что у панелей аппы, цвета из токенов. В просмотре
   результата на чёрном фоне остаётся тёмное. */
/* Прозрачнее, чем панели (0.86 → 0.6), и размытие сильнее: на розовом фоне
   с мелким текстом плотное стекло выглядело просто плашкой (07.09, «где
   размытие»). */
.impito-viewer-pop--light .impito-viewer-pop__menu {
  background: var(--ui-pop-light);
  -webkit-backdrop-filter: blur(28px) saturate(1.8);
  backdrop-filter: blur(28px) saturate(1.8);
  box-shadow:
    0 18px 44px rgba(12, 18, 48, 0.22),
    inset 0 0 0 0.5px rgba(255, 255, 255, 0.7);
  color: var(--ui-text);
}
.impito-viewer-pop--light .impito-viewer-pop__row + .impito-viewer-pop__row,
.impito-viewer-pop--light .impito-viewer-pop__item + .impito-viewer-pop__item {
  border-top-color: var(--ui-separator);
}
.impito-viewer-pop--light .impito-viewer-pop__key {
  color: var(--ui-hint);
}
.impito-viewer-pop--light .impito-viewer-pop__val,
.impito-viewer-pop--light .impito-viewer-pop__item {
  color: var(--ui-text);
}
.impito-viewer-pop--light .impito-viewer-pop__item:active {
  background: var(--ui-press);
}
.impito-viewer-pop__empty {
  margin: 0;
  padding: 12px 18px;
  color: rgba(255, 255, 255, 0.7);
  font-size: 15px;
}


/* ═══ КАТАЛОГ СТИЛЕЙ: ВИТРИНА + ТЕГИ-ФИЛЬТРЫ (07.09.2026, выбор юзера по макету:
   оформление B, фильтры C). Логика — prompt_styles.js. ═══ */
/* Поле поиска с токенами выбранных тегов и кнопкой фильтров (только значок). */
.impito-style-search--tags {
  height: auto;
  min-height: 44px;
  flex-wrap: wrap;
  gap: 6px;
  padding: 5px 8px 5px 14px;
}
.impito-style-search--tags input {
  min-width: 80px;
  height: 34px;
  flex: 1 1 80px;
}
.impito-sc-token {
  display: inline-flex;
  height: 30px;
  flex: 0 0 auto;
  align-items: center;
  gap: 4px;
  padding: 0 4px 0 11px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-accent);
  color: #fff;
  font-size: 13.5px;
  font-weight: 600;
}
/* Крестик — svg по центру круга, а не текстовый «×» (тот сидел криво). */
.impito-sc-token__x {
  display: grid;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.22);
  color: #fff;
  cursor: pointer;
  place-items: center;
  -webkit-tap-highlight-color: transparent;
}
.impito-sc-token__x svg {
  display: block;
  width: 11px;
  height: 11px;
}
.impito-sc-filter {
  display: grid;
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  margin-left: auto;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ui-ink-soft);
  cursor: pointer;
  place-items: center;
  -webkit-tap-highlight-color: transparent;
}
.impito-sc-filter svg {
  width: 20px;
  height: 20px;
}
.impito-sc-filter.is-on {
  color: var(--ui-accent-strong);
}
.impito-sc-filter:active {
  opacity: 0.6;
}

/* Заголовок полки: «все ›» справа мелким. */
.impito-sc-more {
  margin-left: auto;
  color: var(--ui-accent-strong);
  font-size: 13.5px;
  font-weight: 600;
}
.impito-cat-rail__head--static {
  cursor: default;
}
.impito-cat-rail__head--static:active {
  opacity: 1;
}

/* Герой популярного: широкая карточка с подписью на градиенте. Пропорция
   4:3, а не 16:10 (07.09.2026, «менее сжатой»): превью стилей портретные, и в
   узкой полосе от кадра оставалась одна середина. */
.impito-sc-hero {
  position: relative;
  display: block;
  width: calc(100% - 24px);
  margin: 0 12px 10px;
  padding: 0;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-media-soft);
  cursor: pointer;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.impito-sc-hero:active {
  transform: scale(0.985);
}
.impito-sc-hero__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Лица в портретных превью ближе к верху — держим верхнюю треть. */
  object-position: center 30%;
}
.impito-sc-hero__ov {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 44px 16px 14px;
  background: linear-gradient(180deg, rgba(12, 18, 48, 0) 0%, rgba(12, 18, 48, 0.72) 100%);
  color: #fff;
}
.impito-sc-hero__kicker {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  opacity: 0.9;
  text-transform: uppercase;
}
.impito-sc-hero__kicker svg {
  width: 13px;
  height: 13px;
}
.impito-sc-hero__title {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.15;
}

/* Бейдж на карточке: огонёк популярного или «новое». */
.impito-sc-badge {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 1;
  display: inline-flex;
  height: 22px;
  align-items: center;
  gap: 3px;
  padding: 0 8px;
  border-radius: var(--ui-radius-pill);
  background: rgba(12, 18, 48, 0.5);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
}
.impito-sc-badge svg {
  width: 12px;
  height: 12px;
}
.impito-sc-badge--new {
  background: rgba(36, 73, 242, 0.92);
}
.impito-home-card__shot {
  position: relative;
}

/* Теги на карточке результатов: выбранные подсвечены. */
.impito-sc-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 2px;
}
.impito-sc-tag {
  padding: 2px 7px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-accent-soft);
  color: var(--ui-accent-strong);
  font-size: 11px;
  line-height: 1.3;
  white-space: nowrap;
}
.impito-sc-tag.is-on {
  background: var(--ui-accent);
  color: #fff;
}

/* Плитки тегов: обложка с тёмным градиентом слева, имя и счётчик. */
.impito-sc-tagtiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin: 0 12px;
}
.impito-sc-tagtile {
  position: relative;
  height: 76px;
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: 18px;
  background: var(--ui-media-soft);
  cursor: pointer;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.impito-sc-tagtile:active {
  transform: scale(0.97);
}
.impito-sc-tagtile__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.9);
}
.impito-sc-tagtile__ov {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: 0 12px;
  background: linear-gradient(90deg, rgba(12, 18, 48, 0.66), rgba(12, 18, 48, 0.15));
  color: #fff;
}
.impito-sc-tagtile__name {
  overflow: hidden;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.15;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.impito-sc-tagtile__count {
  font-size: 11px;
  opacity: 0.85;
}

/* Шапка результатов: сортировка (тап открывает фильтры) и счётчик. */
.impito-sc-results-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}
.impito-sc-results-head__sort {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ui-accent-strong);
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-sc-results-head__sort .ui-section-header {
  padding-right: 0;
  color: var(--ui-accent-strong);
}
.impito-sc-results-head__sort svg {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
  opacity: 0.8;
}

/* Лист фильтров: сортировка, группы тегов, кнопки внизу. */
.impito-filter-sheet__body {
  max-height: min(60vh, 520px);
  padding: 4px 18px 8px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
/* Секции листа: формат → время года → повод → остальное. Подпись группы
   мелкая серым, чипсы одного ростa, счётчик у чипса приглушён. */
.impito-filter-sheet__section + .impito-filter-sheet__section {
  margin-top: 14px;
}
.impito-filter-sheet__label {
  margin: 0 0 8px;
  color: var(--ui-hint);
  font-size: 13px;
}
.impito-filter-sheet__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.impito-filter-sheet__chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.impito-filter-sheet__count {
  opacity: 0.55;
  font-size: 12px;
  font-weight: 500;
}
.ui-chip--active .impito-filter-sheet__count {
  opacity: 0.8;
}
.impito-filter-sheet__foot {
  display: flex;
  gap: 8px;
  padding: 10px 18px 18px;
}
.impito-filter-sheet__reset {
  flex: 0 0 auto;
}
.impito-filter-sheet__apply {
  flex: 1 1 auto;
}


/* ═══ ЭКРАН СТИЛЯ В ДИЗАЙНЕ ЭКРАНА ФОТО (07.09.2026) ═══ */
.impito-style-detail__tags {
  margin-top: 8px;
}
.impito-style-detail .impito-style-detail__head {
  padding-bottom: 14px;
}
.impito-style-detail > [data-photo-section].ui-section {
  margin-bottom: 12px;
}
/* «Редактировать» — ссылка в шапке секции промпта, как «копировать» в истории. */
.impito-style-detail__edit {
  padding-right: 22px;
  border: 0;
  background: none;
  color: var(--ui-accent-strong);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-style-detail__edit:active {
  opacity: 0.6;
}

/* «Пружинка» сортировки в каталоге: растёт из строки слева, поэтому левый
   край по кнопке (координаты ставит скрипт), пункт с галочкой. */
.impito-viewer-pop--start .impito-viewer-pop__menu {
  min-width: 232px;
}
.impito-viewer-pop__check {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  margin-left: auto;
  opacity: 0;
}
.impito-viewer-pop__item.is-active .impito-viewer-pop__check {
  opacity: 1;
}
/* В светлом меню активный пункт не гасится, его отмечает галочка. */
.impito-viewer-pop--light .impito-viewer-pop__item.is-active {
  color: var(--ui-text);
}
.impito-viewer-pop--light .impito-viewer-pop__check {
  color: var(--ui-accent-strong);
}


/* ═══ ЛЕНТА РЕЗУЛЬТАТОВ ВБОК (редактор, 07.09.2026) ═══
   Плитки одной высоты, ширина по пропорции; листается вбок. */
.impito-results--rail {
  margin: 14px 0 0;
}
.impito-results__rail {
  display: flex;
  gap: 8px;
  padding: 0 12px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.impito-results__rail::-webkit-scrollbar {
  display: none;
}
.impito-result--rail {
  --rail-h: 96px;
  flex: 0 0 auto;
  width: calc(var(--rail-h) * var(--r));
  min-width: 56px;
  max-width: 220px;
  height: var(--rail-h);
  padding: 0;
  border-radius: 14px;
  transition: width 0.6s cubic-bezier(0.3, 0.7, 0.2, 1);
}

/* ═══ МЕНЮ «ДОБАВИТЬ ФОТО» — светлая пружинка из кнопки (Android), как
   меню «инфо» в истории: текстовые строки без иконок. ═══ */
.impito-viewer-pop--source .impito-viewer-pop__menu {
  min-width: 232px;
  /* Размытие мягче, чем у «инфо» в истории (07.09, просьба юзера «послабее
     для фото»); история и сортировка каталога остаются на 28px. */
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
  /* Прозрачнее на 20% (07.09, просьба юзера): 0.7 → 0.5. */
  background: var(--ui-pop-light-source);
}

/* ═══ ПАНЕЛЬ РЕДАКТОРА ЛИСТАЕТСЯ К РЕЗУЛЬТАТАМ (07.09.2026) ═══
   Высоту ставит fitSheetHeight по основному блоку; блок результатов лежит
   ниже и открывается листанием. Магнит: обычное положение и начало
   результатов — точки привязки. */
.impito-editor-area__sheet.is-scrollable {
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-snap-type: y mandatory;
  /* Магнит держит верхнее поле панели: без этого основной блок прилипал к
     самой кромке, и «что сделать» уезжало под скругление (07.09, «стоит
     криво»). */
  scroll-padding-top: 24px;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.impito-editor-area__sheet.is-scrollable::-webkit-scrollbar {
  display: none;
}
.impito-editor-area__main {
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.impito-editor-area__results {
  /* Начинается ЗА нижним полем панели: в обычном положении не выглядывает
     (07.09, «результаты видно, когда просто менюшка открыта»). */
  margin-top: calc(14px + var(--ui-safe-bottom));
  padding-top: 4px;
  scroll-snap-align: start;
}
.impito-editor-area__results[hidden] {
  display: none;
}
.impito-editor-area__results .impito-results {
  margin-top: 0;
}
/* Заголовок «результаты» с той же линией, что у секций панели. */
.impito-editor-area__results-head .ui-section-header {
  margin-bottom: 8px;
}
/* Значение справа в строке профиля («оформление: тёмная»), перед шевроном. */
.impito-profile-row__value {
  margin-right: 8px;
  color: var(--ui-hint);
  font-size: 15px;
}
.impito-profile-row .ui-row-after {
  display: inline-flex;
  align-items: center;
}

/* ── УГАСАНИЕ ПОД ТАББАРОМ (08.09.2026, по образцу нижней панели Framework7 v9) ──
   Два слоя в фиксированной полосе внизу экрана, под плавающей пилюлей таббара:
   ::before — лёгкое размытие 3px с маской-градиентом (внизу полное, кверху
   сходит на нет — «прогрессивный блюр»), ::after — градиент от цвета фона к
   прозрачному. Тапы пропускает. На широком экране таббара нет — полосы тоже. */
.impito-bottom-fade {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 79;
  /* 103 → 69px и вдвое слабее (08.09.2026, «по площади в 1.5 раза меньше и
     в 2 раза слабее»): размытие 3 → 1.5px, градиент на половинной плотности. */
  height: calc(69px + var(--ui-safe-bottom));
  pointer-events: none;
}
.impito-bottom-fade::before,
.impito-bottom-fade::after {
  content: "";
  position: absolute;
  inset: 0;
}
.impito-bottom-fade::before {
  -webkit-backdrop-filter: blur(1.5px);
  backdrop-filter: blur(1.5px);
  -webkit-mask-image: linear-gradient(to top, #000 50%, transparent 100%);
  mask-image: linear-gradient(to top, #000 50%, transparent 100%);
}
.impito-bottom-fade::after {
  opacity: 0.5;
  background: linear-gradient(
    to top,
    var(--ui-bg) 0%,
    color-mix(in srgb, var(--ui-bg) 72%, transparent) 42%,
    transparent 100%
  );
}
@media (min-aspect-ratio: 1/1) and (min-width: 1000px) {
  .impito-bottom-fade {
    display: none;
  }
}

/* ── КОРЕНЬ ПРОФИЛЯ: ШАПКА В СТРОКУ И ПЛИТКИ (08.09.2026, вариант «плитки» из
   ~/Desktop/impito_profile_mockup.html; юзер: без цветных квадратов и свечений,
   наш тумблер). Плитки — те же карточки, что .ui-card: подложка --ui-card,
   радиус карточки, без теней; значки контурные акцентом. ── */
.impito-profile-hero--row {
  flex-direction: row;
  align-items: center;
  gap: 14px;
  /* Боковые поля как у карточек (.ui-card: margin 0 12px + внутренние 16px):
     шапка и плитки стояли впритык к краям экрана (08.09.2026, скриншот юзера). */
  margin: 0 12px;
  padding: 2px 6px 18px;
  text-align: left;
}
/* Мельче (08.09.2026, «с масштабом проебался»): аватар 56 → 46, имя 20 → 18,
   баланс 22 → 19. */
.impito-profile-hero--row .impito-profile-avatar {
  width: 46px;
  height: 46px;
  flex: 0 0 auto;
}
.impito-profile-hero--row .impito-profile-avatar__initials {
  font-size: 18px;
}
.impito-profile-hero--row .impito-profile-avatar__person svg {
  width: 24px;
  height: 24px;
}
.impito-profile-hero__text {
  display: flex;
  min-width: 0;
  flex: 1 1 auto;
  flex-direction: column;
  align-items: flex-start;
}
.impito-profile-hero--row .impito-profile-name {
  margin: 0;
  font-size: 18px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.impito-profile-hero--row .impito-profile-id {
  margin: 1px 0 0;
  padding: 2px 0;
  font-size: 13px;
}
.impito-profile-hero__balance {
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  align-items: flex-end;
  padding: 4px 2px;
  border: 0;
  background: none;
  color: var(--ui-text);
  font-family: var(--ui-font);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-profile-hero__balance strong {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.impito-profile-hero__balance span {
  color: var(--ui-hint);
  font-size: 12px;
}
.impito-profile-hero__balance:active {
  opacity: 0.6;
}
.impito-profile-tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin: 0 12px 18px;
}
/* Плитки компактнее (08.09.2026): 112 → 88px высоты, поля 16 → 13px, значок
   26 → 22px, заголовок 16 → 15px. */
.impito-profile-tile {
  display: flex;
  min-height: 88px;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
  padding: 13px 14px 12px;
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-card);
  box-shadow: var(--ui-surface-highlight);
  color: var(--ui-text);
  font-family: var(--ui-font);
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    transform 0.16s var(--ui-ease),
    background-color 0.16s var(--ui-ease);
}
.impito-profile-tile:active {
  transform: scale(0.97);
  background: var(--ui-card-raised);
}
.impito-profile-tile__glyph {
  display: flex;
  width: 24px;
  height: 24px;
  align-items: center;
  justify-content: center;
  color: var(--ui-accent-strong);
}
.impito-profile-tile__glyph svg {
  width: 22px;
  height: 22px;
}
.impito-profile-tile__text {
  display: flex;
  min-width: 0;
  max-width: 100%;
  flex-direction: column;
  gap: 2px;
}
.impito-profile-tile__title {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.impito-profile-tile__sub {
  overflow: hidden;
  color: var(--ui-hint);
  font-size: 12px;
  line-height: 1.3;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Контурные значки в строках корня (тумблер, поддержка, правила, админка). */
.impito-profile-glyph svg {
  width: 22px;
  height: 22px;
  color: var(--ui-accent-strong);
}

/* ── СМЕНА КАДРОВ ПРОФИЛЯ (08.09.2026): старый гаснет, новый проявляется. ── */
.impito-page-leave {
  opacity: 0;
  transition: opacity 0.11s var(--ui-ease);
  pointer-events: none;
}
.impito-page-enter {
  /* БЕЗ fill-mode (09.09.2026, скриншоты юзера с Android: лист настроек
     уезжал ПОД таббар). Заполненная анимация оставляла на <main> контекст
     наложения с z-index auto, и листы внутри него (z 120) рисовались ниже
     таббара (z 80). Без заливки после 200мс контекста нет. Стартовый кадр
     задан явно, вспышки не будет. */
  animation: impito-page-in 0.2s var(--ui-ease-out);
}
@keyframes impito-page-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .impito-page-enter {
    animation: none;
  }
}

/* ── СТРАНИЦА «НАСТРОЙКИ» КАРТОЧКАМИ (08.09.2026): каждая карточка во всю
   ширину, как у темы; слева заголовок/значение/подпись, справа шеврон или
   тумблер; сброс — круглая кнопка в заголовке группы. ── */
.impito-set-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-right: 16px;
}
.impito-set-head .ui-section-header {
  margin-bottom: 0;
}
.impito-set-head {
  margin-bottom: 9px;
}
.impito-set-reset {
  display: grid;
  width: 32px;
  height: 32px;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--ui-card);
  color: var(--ui-accent-strong);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.16s var(--ui-ease);
}
.impito-set-reset svg {
  width: 17px;
  height: 17px;
}
.impito-set-reset:active {
  transform: rotate(-40deg) scale(0.94);
}
.impito-set-tile {
  grid-column: 1 / -1;
  min-height: 0;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  padding: 13px 16px 13px 16px;
}
.impito-set-tile__main {
  display: flex;
  min-width: 0;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 3px;
}
.impito-set-tile__head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.impito-set-tile__head .impito-profile-tile__glyph {
  width: 22px;
  height: 22px;
}
.impito-set-tile__head .impito-profile-tile__glyph svg {
  width: 20px;
  height: 20px;
}
.impito-set-tile__title {
  color: var(--ui-hint);
  font-size: 13px;
  font-weight: 500;
}
.impito-set-tile__value {
  display: block;
  overflow: hidden;
  color: var(--ui-text);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.impito-set-tile__aside {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  color: var(--ui-ink-faint);
}
.impito-set-tile__aside .impito-profile-chevron {
  width: 10px;
  height: 17px;
}
div.impito-set-tile {
  cursor: default;
}
div.impito-set-tile:active {
  transform: none;
  background: var(--ui-card);
}

/* ── ШАПКА МАГАЗИНА В СТРОКУ (08.09.2026): баланс слева, премиум-стикер
   справа. ── */
.impito-topup-hero--row {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 2px 14px 2px 22px;
  text-align: left;
}
.impito-topup-hero__text {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
}
.impito-topup-hero__art {
  position: relative;
  display: grid;
  width: 96px;
  height: 96px;
  flex: 0 0 auto;
  place-items: center;
  pointer-events: none;
}
.impito-topup-hero__art img {
  display: block;
  width: 88px;
  height: 88px;
}
.impito-topup-hero__lottie {
  width: 96px;
  height: 96px;
}

/* ── ВЫБОР ТЕМЫ МИНИ-ЭКРАНАМИ (08.09.2026, как в Системных настройках macOS).
   Три превью 4:3: подложка темы, полоска шапки, две «карточки», розовая
   «кнопка». Выбранное — в акцентной рамке, подпись под ним жирнее. ── */
.impito-set-theme {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 13px 16px 14px;
}
.impito-theme-pick {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.impito-theme-pick__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ui-hint);
  font-family: var(--ui-font);
  font-size: 12.5px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.impito-theme-pick__item.is-active {
  color: var(--ui-text);
  font-weight: 600;
}
.impito-theme-pick__preview {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 12px;
  box-shadow: inset 0 0 0 1px var(--ui-separator);
  transition:
    box-shadow 0.18s var(--ui-ease),
    transform 0.18s var(--ui-ease);
}
.impito-theme-pick__item.is-active .impito-theme-pick__preview {
  box-shadow:
    inset 0 0 0 2px var(--ui-accent),
    0 0 0 2px color-mix(in srgb, var(--ui-accent) 35%, transparent);
}
.impito-theme-pick__item:active .impito-theme-pick__preview {
  transform: scale(0.96);
}
.impito-theme-pick__preview--light {
  background: #dbe3ff;
}
.impito-theme-pick__preview--dark {
  background: #0a0e20;
}
.impito-theme-pick__preview--system {
  background: linear-gradient(105deg, #dbe3ff 0 50%, #0a0e20 50% 100%);
}
.impito-theme-pick__bar,
.impito-theme-pick__card,
.impito-theme-pick__btn {
  position: absolute;
  left: 12%;
  right: 12%;
  border-radius: 4px;
}
.impito-theme-pick__bar {
  top: 10%;
  height: 10%;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.62);
}
.impito-theme-pick__card {
  height: 17%;
  background: rgba(255, 255, 255, 0.62);
}
.impito-theme-pick__card:nth-of-type(2) {
  top: 28%;
}
.impito-theme-pick__card:nth-of-type(3) {
  top: 50%;
}
.impito-theme-pick__preview--dark .impito-theme-pick__bar,
.impito-theme-pick__preview--dark .impito-theme-pick__card {
  background: rgba(255, 255, 255, 0.1);
}
.impito-theme-pick__preview--system .impito-theme-pick__bar,
.impito-theme-pick__preview--system .impito-theme-pick__card {
  background: linear-gradient(105deg, rgba(255, 255, 255, 0.62) 0 50%, rgba(255, 255, 255, 0.1) 50% 100%);
}
.impito-theme-pick__btn {
  bottom: 10%;
  height: 12%;
  border-radius: 999px;
  background: #2449f2;
}
.impito-theme-pick__label {
  line-height: 1.2;
  text-align: center;
}

/* ── ПАНЕЛЬ ЗАПУСКА В ТЁМНОЙ ТЕМЕ (08.09.2026, «выглядит грязно»): почти
   непрозрачная подложка и нормальное размытие вместо тумана 1px, сквозь
   который просвечивал контент; элементы контрастнее примерно на 7%
   («цвета чуть более выраженными, менее прозрачным»). :root[...] — выше
   платформенного правила apple с blur 1.15px. Светлая тема прежняя. ── */
:root[data-theme="dark"] .impito-style-submit__inner:before {
  background: rgba(36, 38, 46, 0.96);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  backdrop-filter: blur(14px) saturate(1.3);
}
:root[data-theme="dark"] .impito-style-submit__inner .impito-style-count {
  background: rgba(255, 255, 255, 0.15);
}
:root[data-theme="dark"] .impito-style-submit__inner .impito-style-stepper {
  background: rgba(255, 255, 255, 0.14);
}
:root[data-theme="dark"] .impito-style-generate {
  background: var(--ui-accent-strong);
}
:root[data-theme="dark"] .impito-style-generate:disabled {
  background: rgba(36, 73, 242, 0.3);
  color: rgba(236, 238, 246, 0.72);
}
