/**
 * Skyny - Optimized Global Styles
 * Optimized: 2026-02-02
 */


/* ========================================
   1. DESIGN TOKENS (Base Variables)
   ======================================== */

/* --- Tabler icon alignment --- */
.ti {
    vertical-align: middle;
}

/* --- Video Elements Override (only decorative videos should hide native controls) --- */
video:not([controls])::-webkit-media-controls-enclosure {
    display: none !important;
}
video:not([controls])::-webkit-media-controls {
    display: none !important;
}
video {
    transform: translateZ(0);
    outline: none;
}

:root {
    /* Sunset sources match docs/marketing-launch-20261008/visual-review.json. */
    --brand-sunset-start: #4A4540;
    --brand-sunset-end: #675F56;
    --brand-sunset-cool: #5B5550;
    --brand-sunset-gold: #70675C;
    --brand-sunset-base: #5F5952;
    --brand-sunset-mid: #756D62;
    --brand-sunset-accent: #5B554E;
    /* A trace of the selected palette in the dark surface ladder. */
    --surface-accent-strength: 3%;
    --bg-night: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) var(--surface-accent-strength), #000000);
    --ambient-night-500: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) var(--surface-accent-strength), #575757);
    --ambient-night-600: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) var(--surface-accent-strength), #474747);
    --ambient-night-700: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) var(--surface-accent-strength), #393939);
    --lyrics-button-bg: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) 8%, var(--bg-elevated));
    --lyrics-button-art-opacity: .45;
    /* Shared chat component contract. Isolated SVG renderers resolve these
       same tokens through ChatPresentation; never maintain a second theme. */
    --chat-component-bg: var(--bg-elevated);
    --chat-component-radius: var(--radius-base);
    --chat-component-gap: var(--gap-sm);
    --chat-component-padding: calc(var(--gap-sm) * 2);
    --chat-control-radius: var(--radius-pill);
    --chat-control-bg: var(--bg-input);
    --chat-control-active: var(--surface-strong);
    --chat-control-inset: var(--gap-xs);
    --chat-control-height: calc(var(--artifact-control-size) + var(--chat-control-inset) * 2);
    --chart-label-size: var(--text-label);
    --chart-title-size: var(--text-card);
    --chart-stroke-width: 2px;
    --chart-plot-height: calc(var(--gap-sm) * 22);
    --chart-panel-width: calc(var(--gap-sm) * 36);
    --chart-grid: color-mix(in srgb, var(--text-muted) 16%, var(--chat-component-bg));
    --chart-series-1: #79aaff;
    --chart-series-2: #f3b75b;
    --chart-series-3: #65c9af;
    --chart-series-4: #b4a0ef;
    --chart-series-5: #ef91a8;
    --chart-series-6: #78c9dd;
    --chart-series-7: #d5c879;
    --chart-series-8: #bdafa1;
    --chart-scale-low: color-mix(in srgb, var(--chart-series-1) 15%, var(--chat-component-bg));
    --chart-scale-high: var(--chart-series-1);
    --chart-negative: var(--chart-series-5);
    --chart-positive: var(--chart-series-3);
/* --- Shared Metrics --- */
    --announcement-height: 3.25rem;
    --safe-area-top: 0px;
    --safe-area-bottom: env(safe-area-inset-bottom, 0px);
    --safe-area-inline: max(env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
    --media-preview-size: 3rem;
    /* Единый множитель скруглений (ползунок «Стили» в профиле). 1.1 = дефолт
       (зеркалит RADIUS_DEFAULT в theme.js), 0 = прямые углы, >1 = круглее.
       Масштабируется ВСЯ лестница радиусов разом — включая капсулы
       (--radius-pill) и круги (--radius-round): при scale=0 даже пилюли и
       кружки становятся квадратными. */
    --radius-scale: 1.1;
    /* Keep composited glass, media and animated surfaces on the stable rounded
       clipping path. Non-round corner-shape can lose clips during compositing
       in Chromium; CSS.supports alone cannot establish rendering stability.
       Corner sizes remain controlled by the shared radius tokens below. */
    --corner-shape-surface: round;
    --corner-shape-round: round;
    --radius-sm: calc(0.375rem * var(--radius-scale));
    --radius-md: calc(0.5rem * var(--radius-scale));
    --radius-base: calc(0.75rem * var(--radius-scale));
    --radius-lg: calc(1.5rem * var(--radius-scale));
    --radius-xl: calc(2rem * var(--radius-scale));
    --radius-2xl: calc(2.5rem * var(--radius-scale));
    --radius-3xl: calc(3rem * var(--radius-scale));
    /* Капсула: rem-значение (не 9999px), достаточное для полного скругления
       любого контрола ≤64px по меньшей стороне при scale=1, но уходящее в
       квадрат при scale→0. На широких пилюлях даёт капсулу, на квадратных
       icon-кнопках — круг. */
    --radius-pill: calc(2rem * var(--radius-scale));
    /* Круги (аватары, обложки, диск плеера, точки): 50% авто-подстраивается
       под размер элемента, а множитель уводит их в квадрат при scale→0. */
    --radius-round: calc(50% * var(--radius-scale));
    --radius-chat-tail: calc(4px * var(--radius-scale));
    --chat-radius: calc(1rem * var(--radius-scale));
    --chat-radius-xl: calc(1.25rem * var(--radius-scale));
    /* Схлопнутая высота композера: 40px контролы + 2×10px inset (.chat-input-zone).
       Единый источник для min-height зоны и pill-радиуса (= половина). */
    --chat-input-shell-min-height: calc(2.5rem + 2 * var(--composer-inset));
    /* TYPOGRAPHY: one shared scale for the UI, marketing and Tailwind.
       Noto covers Latin/Cyrillic/Greek; add script-specific Noto faces here
       when introducing another writing system. Font files are self-hosted.
       Keep the scale default in sync with ThemeService.FONT_DEFAULT. */
    --font-sans: 'Onest', 'Noto Sans', system-ui, sans-serif;
    --font-display: var(--font-sans);
    --font-editorial: 'Cormorant Garamond', 'Noto Serif', Georgia, serif;
    --font-mono: ui-monospace, 'Cascadia Code', 'SF Mono', Consolas, monospace;
    --font-scale: 0.95;
    --text-2xs: calc(0.7rem * var(--font-scale));
    --text-xs: calc(0.75rem * var(--font-scale));
    --text-sm: calc(0.875rem * var(--font-scale));
    --text-base: calc(1rem * var(--font-scale));
    --text-lg: calc(1.125rem * var(--font-scale));
    --text-xl: calc(1.25rem * var(--font-scale));
    --text-2xl: calc(1.5rem * var(--font-scale));
    --text-3xl: calc(1.875rem * var(--font-scale));
    --text-4xl: calc(2.25rem * var(--font-scale));
    --text-5xl: calc(2.75rem * var(--font-scale));
    --text-6xl: calc(3.25rem * var(--font-scale));
    --text-7xl: calc(4rem * var(--font-scale));
    --text-8xl: calc(5rem * var(--font-scale));
    --text-9xl: calc(6rem * var(--font-scale));
    --font-weight-thin: 100;
    --font-weight-extralight: 200;
    --font-weight-light: 300;
    --font-weight-display: 550;
    --font-weight-editorial: 500;
    --font-editorial-scale: 1.12;
    --font-weight-regular: 400;
    --font-weight-medium: 500;
    --font-weight-semibold: 600;
    --font-weight-bold: 700;
    --font-weight-extrabold: 800;
    --font-weight-black: 900;
    --font-style-normal: normal;
    --font-style-editorial: italic;
    --leading-none: 1;
    --leading-display: 1.1;
    --leading-tight: 1.2;
    --leading-snug: 1.35;
    --leading-normal: 1.5;
    --leading-relaxed: 1.65;
    --leading-loose: 1.8;
    --tracking-display: -0.035em;
    --tracking-editorial: -0.025em;
    --tracking-tight: -0.025em;
    --tracking-normal: 0;
    --tracking-wide: 0.025em;
    --tracking-wider: 0.06em;
    --tracking-eyebrow: 0.12em;
    --text-hero: clamp(var(--text-3xl), calc(6cqw * var(--font-scale)), var(--text-6xl));
    --text-feature: clamp(var(--text-3xl), calc(3.2cqw * var(--font-scale)), var(--text-5xl));
    --text-banner-title: clamp(var(--text-3xl), calc(3.8cqw * var(--font-scale)), var(--text-5xl));
    --text-banner-body: clamp(var(--text-base), calc(1.6cqw * var(--font-scale)), var(--text-lg));
    --text-banner-action: var(--text-base);
    --text-title: clamp(var(--text-2xl), calc(2.4vw * var(--font-scale)), var(--text-3xl));
    --text-section: clamp(var(--text-xl), calc(1.7vw * var(--font-scale)), var(--text-2xl));
    --text-dialog: var(--text-lg);
    --text-card: var(--text-base);
    --text-body: var(--text-sm);
    --text-chat: var(--text-base);
    --text-control: var(--text-sm);
    --text-label: calc(0.8125rem * var(--font-scale));
    --text-caption: var(--text-xs);
    --text-metric: clamp(var(--text-3xl), calc(3vw * var(--font-scale)), var(--text-4xl));
    /* Decorative SVG wordmark coordinates, independent of UI text scale. */
    --text-wordmark-mobile: 980px;
    --text-wordmark-desktop: 640px;
    /* One curve for interactive movement: gentle acceleration, a short settle,
       and no overshoot. Semantic aliases keep CSS and WAAPI in sync. */
    --motion-ease-premium: cubic-bezier(0.22, 0, 0.2, 1);
    --motion-ease-standard: var(--motion-ease-premium);
    --motion-ease-elastic: var(--motion-ease-premium);
    /* Departing surfaces accelerate out instead of lingering off-screen. */
    --motion-ease-exit: cubic-bezier(0.4, 0, 1, 1);
    /* Shared interactive timing: menus, drawers and navigation settle promptly. */
    --motion-duration-micro: 100ms;
    --motion-duration-popup: var(--motion-duration-micro);
    --motion-duration-fast: 140ms;
    --motion-duration-drawer: var(--motion-duration-shell);
    --motion-duration-shell: 200ms;
    --motion-duration-base: 220ms;
    --motion-duration-slow: 320ms;
    --motion-duration-dramatic: 500ms;
    /* Ambient examples deliberately move slower than interactive controls. */
    --motion-duration-ambient: 1800ms;
    --motion-duration-shimmer: 7000ms;
    /* One text-light recipe for karaoke and live statuses. */
    --text-shimmer-duration: var(--motion-duration-shimmer);
    --text-shimmer-ease: var(--motion-ease-linear);
    --text-shimmer-gradient: linear-gradient(90deg,
        var(--text-subtle) 0%, var(--text-muted) 35%,
        color-mix(in srgb, var(--text-muted) 55%, white) 50%,
        var(--text-muted) 65%, var(--text-subtle) 100%);
    --text-shimmer-shadow: 0 0 var(--gap-sm) color-mix(in srgb, var(--text-main) 25%, transparent);
    --motion-period-ai-call: 5600ms;
    --motion-period-ai-call-active: 3800ms;
    --motion-period-pulse: 1200ms;
    --motion-period-hint: 2400ms;
    --motion-period-glow: 4000ms;
    --motion-period-idle-glow: 6500ms;
    --motion-period-gradient: 9000ms;
    --motion-interval-example: 4800ms;
    --motion-period-spinner: 900ms;
    --motion-period-cursor: 800ms;
    --motion-period-dash: 700ms;
    --motion-period-twinkle: 5000ms;
    --motion-duration-highlight: 2200ms;
    --motion-period-marquee: 36s;
    --motion-period-marquee-long: 70s;
    --motion-period-showcase: 52s;
    --motion-ease-ambient: ease-in-out;
    --motion-ease-linear: linear;
    --transition: var(--motion-duration-base) var(--motion-ease-standard);
    --transition-fast: var(--motion-duration-fast) var(--motion-ease-standard);
    --transition-hover: var(--motion-duration-micro) var(--motion-ease-standard);
    --transition-slow: var(--motion-duration-slow) var(--motion-ease-premium);
    --motion-stagger-step: 40ms;
    --motion-duration-list: 280ms;
    --motion-ease-list: var(--motion-ease-premium);
    --motion-duration-gallery: 350ms;
    --motion-distance-content: 1rem;
    --motion-scale-surface: 0.96;
    /* The bounded artwork layer owns its blur, independent of the backdrop.
       Container units scale the effect with the cover, including the outro. */
    --music-cover-max-size: 22rem;
    --music-cover-ambience-blur: 18cqw;
    --music-cover-ambience-spread-inline: 2.2;
    --music-cover-ambience-spread-block: 1.8;
    --music-cover-ambience-offset-block: 14cqw;
    --music-cover-ambience-opacity: .6;
    --ambient-smoke-opacity: .82;
    --ambient-smoke-compact-opacity: .7;
    /* Rem counts shared by CSS bounds and FluidSmoke geometry. */
    --ambient-smoke-unit: 18;
    --ambient-smoke-outset: 9;
    --ambient-smoke-source-size: 4;
    --music-cover-ambience-falloff: radial-gradient(ellipse closest-side,
        rgb(0 0 0 / .85) 0%, rgb(0 0 0 / .6) 32%, rgb(0 0 0 / .25) 64%, transparent 100%);
    --music-player-subtitle-lines: 2;
    --music-lyrics-dialog-width: 40rem;
    --lyrics-ambience-outset: 50%;
    --lyrics-ambience-rest-y: 35%;
    --lyrics-ambience-rest-scale: .72;
    --lyrics-ambience-expanded-scale: .86;
    --lyrics-ambience-outro-scale: 1;
    --motion-fps-ambient: 30;
    --lyrics-countdown-lift: .34;
    --gap-2xs: 0.125rem;
    --gap-xs: 0.375rem;
    --gap-sm: 0.5rem;
    --artifact-control-size: calc(var(--gap-sm) * 4.5);
    --artifact-preview-min-height: calc(var(--gap-sm) * 36);
    --artifact-preview-max-height: calc(var(--gap-sm) * 56);
    --artifact-window-width: 64rem;
    --upload-source-width: calc(var(--gap-sm) * 14);
    --upload-source-height: calc(var(--gap-sm) * 5.5);
    --upload-source-art-size: calc(var(--gap-sm) * 3.5);
    --composer-inset: calc(var(--gap-sm) * 1.25);
    --composer-control-size: calc(var(--gap-sm) * 5);
    --modal-library-width: 27.5rem;
    --modal-art-height: calc(var(--gap-sm) * 15);
    --modal-art-header-height: calc(var(--gap-sm) * 11.5);
    --modal-content-pad: calc(var(--gap-sm) * 2);
    --slider-control-size: var(--composer-control-size);
    --slider-thumb-size: calc(var(--gap-sm) * 3.5);
    --slider-track-size: calc(var(--gap-sm) * 2.75);
    --slider-dot-size: calc(var(--gap-2xs) * 2);
    --slider-radius: calc(var(--radius-pill) * 2);
    --slider-fill: var(--primary-500);
    --slider-track: var(--surface-strong);
    --slider-thumb: var(--overlay-text);
    --slider-dot: color-mix(in srgb, var(--text-muted) 60%, transparent);
    --composer-source-width: calc(var(--gap-sm) * 11.5);
    --composer-rail-fade: calc(var(--gap-sm) * 2.5);
    /* Keep rem magnitudes numeric so ratios do not require typed CSS division. */
    --shell-header-slot-rem: 2.6;
    --shell-header-slot: calc(var(--shell-header-slot-rem) * 1rem);
    --shell-header-inset: calc(var(--gap-2xs) * 2);
    --shell-header-control-size: calc(var(--shell-header-slot) - 2 * var(--shell-header-inset));
    --shell-header-padding-block: 0.6rem;
    --shell-page-gap: calc(var(--gap-sm) * 1.5);
    --shell-page-gutter: max(calc(var(--gap-sm) * 1.5), var(--safe-area-inline));
    --shell-desktop-header-offset: calc(var(--shell-header-slot) + var(--shell-header-padding-block) * 2);
    /* Mobile symbol geometry and the shared compact desktop signature. */
    --brand-logo-size: 3rem;
    --brand-desktop-symbol-size: 2rem;
    --brand-desktop-name-size: var(--text-2xl);
    --brand-desktop-gap: calc(var(--gap-sm) * 1.25);
    /* Single source of truth for the horizontal inset on mobile shell pages.
       Used by .shell-mobile-header-host padding and the
       home cards container, so they all align to the same vertical edges. */
    --shell-mobile-gutter: max(0.75rem, var(--safe-area-inline));

    /* --- Glass Configuration --- */
    --blur-lg: 8px;  /* Standard Glass Panels */
    --glass-blur: var(--blur-lg);

    /* --- Progressive Blur Layers (soft + strong) --- */
    --progressive-blur-2: 2px;   /* Soft layer */
    --progressive-blur-3: 5px;   /* Sidebar glass alias source */
    --progressive-blur-4: 10px;  /* Strong layer */
    /* Single-value alias for components that only need one blur strength */
    --progressive-blur: var(--progressive-blur-3);
    --surface-fade-top-strong-mask: linear-gradient(to bottom, black 20%, transparent 65%);
    --surface-fade-top-tint-color: var(--bg-elevated);
    --surface-fade-top-tint-gradient: linear-gradient(to bottom, var(--surface-fade-top-tint-color) 20%, transparent 100%);
    --surface-fade-top-tint-opacity: 0.95;

    /* --- Base Palette (Static Colors) --- */
    --primary-500: #c8ff00;
    --primary-600: #b5e600;
    --primary-700: #a0cc00;
    --ambient-accent-500: #a1a1aa;
    --ambient-accent-600: #8c8c96;
    --ambient-accent-700: #71717a;
    --primary-10: color-mix(in srgb, var(--primary-500) 10%, transparent);
    --primary-20: color-mix(in srgb, var(--primary-500) 20%, transparent);
    --red-500: #ef4444; /* декоративный (admin badge--error); статус-UI нейтральный, без красного/зелёного */
    --promo-bg: var(--primary-500);
    --promo-text: #070707;
    --overlay-text: #ffffff;

    /* --- Derived Palette (color-mix tokens) --- */
    --promo-text-38: color-mix(in srgb, var(--promo-text) 38%, transparent);
    --primary-14: color-mix(in srgb, var(--primary-500) 14%, transparent);
    --primary-18: color-mix(in srgb, var(--primary-500) 18%, transparent);
    --primary-icon: color-mix(in srgb, var(--primary-500) 70%, var(--text-main));
    --text-main-5: color-mix(in srgb, var(--text-main) 5%, transparent);
    --text-main-6: color-mix(in srgb, var(--text-main) 6%, transparent);
    --text-main-18: color-mix(in srgb, var(--text-main) 18%, transparent);
    --bg-raised-55: color-mix(in srgb, var(--bg-raised) 55%, transparent);
    --bg-raised-75: color-mix(in srgb, var(--bg-raised) 75%, transparent);
    --bg-input-45: color-mix(in srgb, var(--bg-input) 45%, transparent);

    /* --- Theme Defaults (Dark Mode) --- */
    /* Палитра нативного UI (контролы, скроллбары, рамка) — тёмная по умолчанию.
       Одно значение, не пара: пара отдала бы выбор prefers-color-scheme ОС.
       Светлая тема переопределяет в [data-theme="prism-light"]; meta color-scheme
       в base.html зеркалит для первого paint. */
    color-scheme: dark;
    --bg-app: var(--bg-night);
    --bg-panel: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) var(--surface-accent-strength), #0c0c0d);
    --bg-input: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) var(--surface-accent-strength), #101010);
    --bg-elevated: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) var(--surface-accent-strength), #18181b);
    --bg-raised: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) var(--surface-accent-strength), #27272a);
    --bg-raised-hover: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) var(--surface-accent-strength), #3f3f46);
    /* Hover-разбел на непрозрачных поверхностях — из общей in-glass-шкалы (см. --surface-tint). */
    --bg-hover: color-mix(in srgb, var(--surface-tint) 8%, transparent);
    /* Стеклянная подложка: нейтральный film с лёгким подтоном палитры. */
    /* Higher opacity uses a darker source to preserve the surface brightness. */
    --chat-input-tint: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) var(--surface-accent-strength), #282828);
    --chat-input-bg: color-mix(in srgb, var(--chat-input-tint) 94%, transparent);
    --shell-tab-active-bg: var(--surface-active);
    /* Непрозрачный аналог стекла для производительного режима: та же читаемость
       без backdrop-blur. Ремапится на --chat-input-bg под [data-perf="lite"]. */
    --chat-input-solid: color-mix(in srgb, var(--prism-accent, var(--brand-sunset-accent)) var(--surface-accent-strength), #1c1c1e);

    --text-main: #ffffff;
    --text-muted: #a3a3a3;
    --text-subtle: #71717a;
    --text-inverse: #000000;
    --primary-text: #111111;

    /* Default chrome-icon color (theme-aware via --text-muted).
       Used by sidebar nav, chat-history avatars, social icons, etc. */
    --icon-default: var(--text-muted);
    --icon-hover: var(--text-main);

    /* Единая семантика ручек изменения размера. Цвета собираются из токенов
       текущей темы и остаются контрастными на поверхности панели. */
    --resize-handle-color: color-mix(in srgb, var(--text-muted) 70%, var(--bg-panel));
    --resize-handle-hover-color: color-mix(in srgb, var(--primary-500) 45%, var(--text-muted));
    --resize-handle-active-color: color-mix(in srgb, var(--primary-500) 72%, var(--text-main));

    /* ============================================================
       НЕЙТРАЛЬНЫЕ ПОВЕРХНОСТИ — контракт из 3 категорий
       (подробнее — .github/copilot-instructions.md):
         A. Сплошные на фоне темы — лестница --bg-* выше (тема-зависимы).
         B. Полупрозрачные ВНУТРИ стекла — шкала --surface-* от одного --surface-tint.
         C. Оверлеи НАД медиа — --overlay-* (чёрный скрим, НЕ зависят от темы).
       ============================================================ */

    /* B. In-glass translucent: один tint на тему + шкала через color-mix.
       В [data-theme="light"] флипается ТОЛЬКО --surface-tint. */
    --surface-tint: #ffffff;
    --surface-soft:   color-mix(in srgb, var(--surface-tint) 6%,  transparent); /* rest-плашка в стекле */
    --surface-active: color-mix(in srgb, var(--surface-tint) 10%, transparent); /* selected/active */
    --surface-strong: color-mix(in srgb, var(--surface-tint) 14%, transparent); /* hover/emphasis */
    /* Утопленные колодцы следуют тому же лёгкому подтону, что и тёмные поверхности. */
    --surface-dim: color-mix(in srgb, var(--bg-night) 20%, transparent);
    /* Контентные подложки — фиксированы (цвет диктует контент, не тема): */
    --surface-paper: #ffffff;   /* HTML-док, QR, платёжная картинка — нужен белый лист */
    --media-letterbox: #000000; /* чёрные поля под <video>/превью */
    /* Подложка под акцентным инлайн-текстом (ссылки, инлайн-код): в тёмной теме
       лайм читается сам, поэтому нейтральный серый чип; в светлой — тёмный
       пузырёк (см. переопределение в [data-theme="light"]), иначе лайма не видно. */
    --surface-accent: var(--surface-soft);

    /* C. Оверлеи над медиа (чёрный скрим + светлый текст; в [data-theme="light"] НЕ трогаем).
       Активная кнопка над медиа = bg:--overlay-text (#fff) + text:--primary-text (#111);
       текст/иконки над медиа = --overlay-text (объявлен в Base Palette выше). */
    --overlay-scrim: rgba(0, 0, 0, 0.4);
    --overlay-pill-bg-soft: rgba(0, 0, 0, 0.45);
    --overlay-pill-bg: rgba(0, 0, 0, 0.55);
    --overlay-pill-bg-strong: rgba(0, 0, 0, 0.72);
    --overlay-control-bg: rgba(255, 255, 255, 0.2); /* неактивная кнопка-контрол над медиа */
    /* Единые круглые действия поверх медиа, с поверхностью и текстом текущей темы. */
    --media-action-radius: 50%;
    --media-action-bg: color-mix(in srgb, var(--bg-elevated) 82%, transparent);
    --media-action-text: var(--text-main);

    /* Контрастные скримы для локальных оверлеев поверх медиа. */
    --overlay-backdrop: rgba(0, 0, 0, 0.6);
    --overlay-backdrop-soft: rgba(0, 0, 0, 0.5);
    /* Подложка именно МОДАЛОК строится из поверхности темы: тёмная призма
       затемняет тёмным, светлая — выбеливает белым. Медиа-скримы выше остаются
       чёрными в обеих темах ради контраста контролов поверх фото/видео. */
    --modal-backdrop: color-mix(in srgb, var(--bg-panel) 72%, transparent);
    --modal-backdrop-soft: color-mix(in srgb, var(--bg-panel) 52%, transparent);
    --spinner-track: color-mix(in srgb, var(--text-main) 18%, transparent);
    --spinner-mid: color-mix(in srgb, var(--text-main) 42%, transparent);
    --spinner-head: color-mix(in srgb, var(--text-main) 72%, transparent);

    /* --- Accent Gradient --- */
    --accent-cool: #3b82f6;
    --accent-warm: #ff7a00;
    --gradient-warm: #fb923c;
    /* CTA-градиент кнопок. Дефолт = историческая заливка .btn-primary; темы могут
       переопределять (см. [data-theme="prism"]). Правишь тут — меняются .btn-primary
       и .tg-footer-new-chat разом. */
    --gradient-primary: linear-gradient(135deg, var(--primary-600), var(--primary-500));
    /* Зернистость (grain) для акцентных градиентов — SVG-шум feTurbulence (ч/б, бесшовный тайл).
       Кладётся ВЕРХНИМ background-слоем над градиентом + background-blend-mode: overlay → «grainy
       gradient». Тайлится мелко (см. background-size у потребителей). Меняешь baseFrequency — зерно. */
    --prism-noise: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='150' height='150'><filter id='ng'><feTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/><feComponentTransfer><feFuncA type='linear' slope='0.28' intercept='-0.12'/></feComponentTransfer></filter><rect width='150' height='150' filter='url(%23ng)'/></svg>");
    /* Серый градиент заголовков: .hero-title (медиа) и h1 в чат-рендеринге. */
    --heading-gradient: linear-gradient(90deg, var(--text-main), var(--text-muted));

    /* --- Payment (SBP) --- */
    --sbp-stop-1: #7021d6;
    --sbp-stop-2: #d93568;

    /* --- Z-Index Layers --- */
    --z-dropdown: 9000;  /* In-flow дропдауны внутри своего stacking context (не порталы) */
    --z-backdrop: 60;  /* Sidebar/Menu overlay */
    --z-sidebar: 70;   /* Sidebar/Menu panel */
    --z-announcement: 8990; /* Modeless release cards yield to menus and every dialog. */
    --z-modal: 9999;
    --z-fullscreen-modal: 10000; /* Fullscreen overlays (generation detail, etc.) */
    --z-dialog-above-overlay: 10100; /* Dialogs stacked on top of fullscreen overlays (lightbox, camera angle) */
    /* ИНВАРИАНТ ПОПОВЕРОВ: body-порталы транзиентных поповеров (ctxMenu, plus-sheet
       с флайаутами, quote-бар) стоят ВЫШЕ любого статичного слоя (модалки, fullscreen,
       диалоги, кроме блокирующего system-dialog): поповер открывается кликом по триггеру, а кликабельный триггер по
       определению в верхнем интерактивном слое. Дефолт зашит в
       FloatingPanelService.buildFixedStyle — точечные подъёмы (бывший
       .dropdown-above-modal) не нужны и запрещены. */
    --z-popover: 10200;
    --z-system-dialog: 10250; /* Блокирующее подтверждение, в том числе из поповера. */
    --z-tooltip: 10300; /* Тултипы: пассивный (pointer-events:none) самый верхний слой */

    /* --- Shadows ---
       ЕДИНСТВЕННЫЙ источник теней-подъёмов: элементы берут var(--shadow-*), свои
       rgba-значения в компонентах запрещены (тема переопределяет токены, а не правила). */
    --shadow-color: var(--bg-night);
    --shadow-glass: 0 8px 32px 0 color-mix(in srgb, var(--shadow-color) 25%, transparent);
    --shadow-surface: 0 1px 2px color-mix(in srgb, var(--shadow-color) 18%, transparent);
    --shadow-dropdown: 0 16px 40px -24px color-mix(in srgb, var(--shadow-color) 60%, transparent);
    --shadow-icon: 0 6px 12px -6px color-mix(in srgb, var(--shadow-color) 40%, transparent);
    --shadow-modal: 0 24px 50px -28px color-mix(in srgb, var(--shadow-color) 70%, transparent);
    --shadow-inset: inset 0 1px 2px color-mix(in srgb, var(--shadow-color) 30%, transparent);
    --shadow-code: 0 4px 6px -1px color-mix(in srgb, var(--shadow-color) 10%, transparent);
    --shadow-lightbox: 0 16px 64px color-mix(in srgb, var(--shadow-color) 60%, transparent);
    /* Симметричный ореол плавающей пилюли композера (без смещения — читается и над,
       и под пилюлей). Отдельный токен: ни один из направленных токенов выше не даёт
       «парение» со всех сторон. */
    --shadow-composer: 0 0 4px color-mix(in srgb, var(--shadow-color) 30%, transparent), 0 0 30px color-mix(in srgb, var(--shadow-color) 50%, transparent);
    --glow-spotlight: rgba(255, 255, 255, 0.4);

    /* Static surface outlines are disabled. Animated spectra are independent. */
    --edge-width: 0px;
    --edge-gradient: none;

    /* --- Accent Glow / Ring (производные от --primary-500: перекрашиваются
       вместе с data-accent). Ring — hairline-кольцо инсетом (без сдвига layout),
       glow — мягкое внешнее свечение. Комбинируются: box-shadow: ring, glow. --- */
    --ring-accent-soft: inset 0 0 0 1px color-mix(in srgb, var(--primary-500) 40%, transparent);
    --ring-accent-strong: inset 0 0 0 1.5px color-mix(in srgb, var(--primary-500) 75%, transparent);
    --glow-accent-soft: 0 0 20px -4px var(--primary-20);
    --glow-accent-strong: 0 0 34px -6px color-mix(in srgb, var(--primary-500) 38%, transparent);
    /* Непрерывная лента композера: без прозрачных разрывов, с мягкими
       контрастными бликами для светлой и тёмной темы. */
    --composer-spectrum-stops:
        color-mix(in srgb, var(--primary-500) 62%, var(--bg-app)) 0deg,
        color-mix(in srgb, var(--primary-500) 78%, var(--bg-app)) 58deg,
        color-mix(in srgb, var(--primary-500) 62%, var(--text-main)) 112deg,
        color-mix(in srgb, var(--primary-500) 38%, var(--text-main)) 154deg,
        color-mix(in srgb, var(--primary-500) 74%, var(--bg-app)) 216deg,
        color-mix(in srgb, var(--primary-500) 56%, var(--text-main)) 278deg,
        color-mix(in srgb, var(--primary-500) 62%, var(--bg-app)) 360deg;

    /* --- Layout Grid (Page/App) --- */
    --layout-max-width: 64rem;
    --layout-pad-y: 2rem;
    --app-gutter-x: max(1rem, var(--safe-area-inline));      /* минимум 16px, с учётом safe area */
    --app-gutter-x-md: max(1.5rem, var(--safe-area-inline)); /* минимум 24px, с учётом safe area */
    --app-frame-inset-desktop: 12px; /* shared desktop inset for floating panels + docked input */
    --shell-secondary-panel-width: 18rem;
    --media-sidebar-width: 18rem;
    --media-sidebar-resize-gap: 0.75rem;
    --music-info-panel-min-width: 20rem; /* синхр. с MediaSidebarService.MUSIC_PANEL_MIN_WIDTH */

    /* Chat mobile composer gutters (closer to screen edges) */
    --chat-mobile-gutter-x: 0.5rem;

    /* Dialogs leave room for viewport edges, browser chrome and safe areas. */
    --drawer-max-h: min(calc(var(--app-viewport-height, 100dvh) * 0.88), calc(var(--app-viewport-height, 100dvh) - env(safe-area-inset-top, 0px) - 12px));
    --drawer-library-h: calc(var(--app-viewport-height, 100dvh) * 0.7);

}

/* --- Payment Outcome (benefit highlight) --- */
.payment-outcome-item.is-benefit {
    background: var(--surface-soft);
    box-shadow: 0 18px 30px -28px color-mix(in srgb, var(--primary-500) 28%, transparent);
}
.payment-outcome-item.is-benefit .payment-outcome-value {
    font-family: var(--font-display);
    font-size: var(--text-card);
    line-height: var(--leading-none);
    color: var(--text-main);
}

/* --- Subscription Plan Cards (featured) --- */
.subscription-plan-card.is-featured::before {
    content: '';
    position: absolute;
    inset: -18% auto auto 58%;
    width: 10rem;
    height: 10rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: radial-gradient(circle, color-mix(in srgb, var(--primary-18) 72%, transparent) 0%, transparent 72%);
    pointer-events: none;
}
.subscription-plan-card.is-featured .subscription-plan-action.btn-primary {
    box-shadow: 0 20px 34px -24px color-mix(in srgb, var(--primary-500) 42%, transparent);
}
.subscription-plan-slider__heading {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.45rem;
}
.subscription-plan-slider__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.26rem 0.55rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-muted);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
}

/* Старые одноцветные акценты удалены — теперь акцент = градиентная палитра ([data-accent] ниже,
   рядом с темами «Призма»). */

/* Safe-area env vars (only if supported) */
@supports (padding-top: env(safe-area-inset-top)) {
    :root {
        --safe-area-top: env(safe-area-inset-top);
    }
}

/* Announcement banner: collapses via max-height transition */
.global-announcement {
    position: relative;
    z-index: 90;
    isolation: isolate;
    overflow: hidden;
    box-sizing: border-box;
    max-height: calc(var(--announcement-height) + var(--safe-area-top));
    height: calc(var(--announcement-height) + var(--safe-area-top));
    padding-top: var(--safe-area-top);
    background: var(--bg-panel);
    color: var(--promo-text);
    border: 0;
    border-radius: 0;
    outline: 0;
    transition: max-height var(--motion-duration-base) var(--motion-ease-standard);
    box-shadow: none;
}

/* Края промо следуют поверхности темы, центр использует тот же токенный
   prism-градиент, что CTA. В светлой теме больше нет чёрной полосы по краям. */
.global-announcement::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background-color: var(--promo-bg);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 160px 160px, auto;
    background-blend-mode: overlay, normal;
    -webkit-mask-image: linear-gradient(90deg,
        transparent 0%, #000 24%, #000 76%, transparent 100%);
    mask-image: linear-gradient(90deg,
        transparent 0%, #000 24%, #000 76%, transparent 100%);
    pointer-events: none;
}

.global-announcement.closed {
    max-height: 0;
    /* Схлопываем и safe-area-полосу под чёлкой: без обнуления padding-top/фона iOS
       не перерисовывает клиппнутую зону и промо-пиксели остаются под статус-баром. */
    padding-top: 0;
    background: transparent;
    border: 0;
}

.global-announcement__inner {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    height: var(--announcement-height);
    width: 100%;
    padding: 0 3.25rem;
}

.global-announcement__text {
    font-size: var(--text-lg);
    font-weight: var(--font-weight-medium);
    line-height: var(--leading-none);
    text-align: center;
}

.global-announcement__close {
    position: absolute;
    right: 0.875rem;
    top: 50%;
    transform: translateY(-50%);
    width: 2rem;
    height: 2rem;
    border: 0;
    background: transparent;
    color: var(--text-main);
    opacity: 0.78;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    transition: opacity var(--transition-fast), background-color var(--transition-fast);
}

@media (hover: hover) {
    .global-announcement__close:hover {
        opacity: 1;
        background: color-mix(in srgb, var(--promo-text) 10%, transparent);
    }
}

.global-announcement__close:focus-visible {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--text-main) 62%, transparent);
}

@media (max-width: 767.98px) {
    :root {
        --announcement-height: 2.25rem;
    }

    .global-announcement__inner {
        padding: 0 2.75rem 0 0.75rem;
    }

    .global-announcement__text {
        font-size: var(--text-sm);
        line-height: var(--leading-tight);
    }

    .global-announcement__close {
        right: 0.5rem;
        width: 1.875rem;
        height: 1.875rem;
    }

    .global-announcement::before {
        -webkit-mask-image: linear-gradient(90deg,
            transparent 0%, #000 12%, #000 88%, transparent 100%);
        mask-image: linear-gradient(90deg,
            transparent 0%, #000 12%, #000 88%, transparent 100%);
    }
}

/* ========================================
   Subscription Banner (NS ULTRA)
   Единый компактный вид на всех ширинах (бывшая мобильная полоса):
   акцентная заливка bg + ::after-градиент, без сцены-звездопада.
   ======================================== */
.ultra-banner {
    position: relative;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    pointer-events: auto;
}

.ultra-banner__bg {
    position: absolute;
    inset: 0;
    overflow: hidden;
    background: var(--bg-panel);
}

.ultra-banner__bg::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    /* Тихий градиент из поверхности текущей темы: тёмный в тёмной призме,
       белый в светлой. Жёсткого чёрного слоя здесь быть не должно. */
    background:
        linear-gradient(105deg,
            color-mix(in srgb, var(--bg-panel) 96%, transparent) 0%,
            color-mix(in srgb, var(--bg-panel) 72%, transparent) 42%,
            transparent 72%);
}

.ultra-banner__content {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 0.875rem;
}

.ultra-banner__text {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
    text-align: left;
}

.ultra-banner__brand {
    font-family: var(--font-display);
    font-size: var(--text-base);
    font-weight: var(--font-weight-display);
    background-image: linear-gradient(90deg, var(--text-main), color-mix(in srgb, var(--text-main) 58%, transparent));
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    line-height: var(--leading-display);
    letter-spacing: var(--tracking-wider);
}

.ultra-banner__subtitle {
    max-width: 28rem;
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    color: var(--text-muted);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.ultra-banner__actions {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    margin-left: auto;
}

.ultra-banner__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: 0.5rem 0.875rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    /* Акцентная пилюля — наш --gradient-primary с зернистостью (как .btn-primary),
       читается в обеих темах. */
    background-color: var(--primary-500);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 160px 160px, auto;
    background-blend-mode: overlay, normal;
    color: var(--primary-text);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--transition-fast), transform var(--transition-fast), filter var(--transition-fast);
}

/* Единственная кнопка баннера «Оплата» → дропдаун (ctxMenu) с выбором «Выбрать
   тариф» / «Пополнить баланс». display:inline-flex наследует от .ultra-banner__btn. */
.ultra-banner__pay-trigger {
    gap: 0.375rem;
}

@media (min-width: 768px) {
    :root {
        --layout-pad-y: 3rem;
        --app-gutter-x: var(--app-gutter-x-md);
    }
}

/* --- Z-Index Utilities --- */
.z-dropdown { z-index: var(--z-dropdown) !important; }
.z-backdrop { z-index: var(--z-backdrop) !important; }
.z-sidebar  { z-index: var(--z-sidebar)  !important; }
.z-modal    { z-index: var(--z-modal)    !important; }
.z-popover  { z-index: var(--z-popover)  !important; }

/* Системное модальное окно (alert/confirm) должно всплывать поверх
   fullscreen overlay'ев (generation detail и т.п.), иначе диалог подтверждения
   удаления «прячется» за overlay'ем. См. fullscreen-dialog-stacking. */
#app-modal { z-index: var(--z-system-dialog); }

.chat-input-state-shell {
    transition: opacity var(--motion-duration-fast) var(--motion-ease-premium), transform var(--motion-duration-fast) var(--motion-ease-premium), box-shadow var(--transition), background-color var(--transition), border-radius var(--transition);
    will-change: transform;
}

/* ========================================
   2. ТЕМЫ — только «Призма» (тёмная по умолчанию = :root-override [data-theme="prism"])
   и «Призма светлая» [data-theme="prism-light"]. Старые dark/light удалены; их компонентные
   [data-theme="light"]-правила ниже инертны (ни один элемент не получает data-theme="light":
   старые значения мигрируются в призмы на резолве). Базой служит :root.
   ======================================== */

/* ════════════════════════════════════════════════════════════════════════════
   ТЕМА «ПРИЗМА» — сдержанные природные градиенты. Два варианта на ОБЩЕЙ базе:
   [data-theme="prism"] (тёмная, на чёрном) и [data-theme="prism-light"] (светлая, на белом).

   ТОКЕНОВАЯ АРХИТЕКТУРА (без хардкодов — меняешь источник, меняется ВЕЗДЕ):
     1. Спектральные ИСТОЧНИКИ (--prism-pink/lilac/cyan/gold/mint/yellow/hi + --prism-accent) —
        единственные «ручки» цвета. Хочешь другой акцент/градиент — правишь только их.
     2. Семантика СОБРАНА из источников: --gradient-primary (CTA/баннер), --composer-spectrum-stops
        (кольцо композера), --primary-500/600/700 (одиночный акцент из --prism-accent).
     3. Поверхности/текст/тени — в per-вариант блоках (тёмный/светлый), самодостаточны
        (не зависят от старых тем — их позже удалим).
   Палитра живёт ТОЛЬКО на CTA/баннере, кольце композера и плавающем градиенте загрузки;
   остальной хром использует приглушённый нейтральный акцент. ═════════════════════════ */
[data-theme="prism"],
[data-theme="prism-light"] {
    /* Default Sunset accent: the original muted taupe palette. */
    --prism-pink:   var(--brand-sunset-start);
    --prism-lilac:  var(--brand-sunset-end);
    --prism-cyan:   var(--brand-sunset-cool);
    --prism-gold:   var(--brand-sunset-gold);
    --prism-mint:   var(--brand-sunset-base);
    --prism-yellow: var(--brand-sunset-mid);
    --prism-hi:     var(--brand-sunset-accent);
    --prism-accent: var(--brand-sunset-accent);

    /* ── Семантика, СОБРАННАЯ из источников ── */
    --gradient-primary: linear-gradient(100deg, var(--prism-pink) 0%, var(--prism-lilac) 100%);
    /* Непрерывная нейтральная лента сохраняет характер выбранного акцента.
       Первый и последний цвета совпадают — на стыке нет шва или разрыва. */
    --composer-spectrum-stops:
        color-mix(in srgb, var(--prism-accent) 62%, var(--bg-app)) 0deg,
        color-mix(in srgb, var(--prism-accent) 78%, var(--bg-app)) 58deg,
        color-mix(in srgb, var(--prism-accent) 62%, var(--text-main)) 112deg,
        color-mix(in srgb, var(--prism-accent) 38%, var(--text-main)) 154deg,
        color-mix(in srgb, var(--prism-accent) 74%, var(--bg-app)) 216deg,
        color-mix(in srgb, var(--prism-accent) 56%, var(--text-main)) 278deg,
        color-mix(in srgb, var(--prism-accent) 62%, var(--bg-app)) 360deg;

    /* --primary-500 задаётся в блоке ТЕМЫ (тёмная — молочный из акцента; светлая — напрямую);
       600/700/20 — производные от него. */
    --primary-600: color-mix(in srgb, var(--primary-500) 86%, #000);
    --primary-700: color-mix(in srgb, var(--primary-500) 72%, #000);
    --primary-20:  color-mix(in srgb, var(--primary-500) 20%, transparent);

    /* Кольца/glow — мягкие, на акценте (интенсивность светлый вариант приглушит) */
    --ring-accent-soft: inset 0 0 0 1px color-mix(in srgb, var(--primary-500) 38%, transparent);
    --ring-accent-strong: inset 0 0 0 1.5px color-mix(in srgb, var(--primary-500) 70%, transparent);
    --glow-accent-soft: 0 0 20px -6px color-mix(in srgb, var(--primary-500) 28%, transparent);
    --glow-accent-strong: 0 0 32px -10px color-mix(in srgb, var(--primary-500) 38%, transparent);

    /* Приглушённые акценты тёмные — текст CTA всегда светлый. */
    --primary-text: var(--overlay-text);
    --promo-text: var(--primary-text);
    --promo-bg: var(--primary-500);   /* фолбэк; .global-announcement ниже кладёт градиент */
}

/* ── ПРИЗМА ТЁМНАЯ: почти чёрный холст и 3% выбранного акцента в поверхностях ── */
[data-theme="prism"] {
    color-scheme: dark;
    --bg-app: var(--bg-night);
    --bg-panel: color-mix(in srgb, var(--prism-accent) var(--surface-accent-strength), #0c0c0c);
    --bg-input: color-mix(in srgb, var(--prism-accent) var(--surface-accent-strength), #111111);
    --bg-elevated: color-mix(in srgb, var(--prism-accent) var(--surface-accent-strength), #181818);
    --bg-raised: color-mix(in srgb, var(--prism-accent) var(--surface-accent-strength), #242424);
    --bg-raised-hover: color-mix(in srgb, var(--prism-accent) var(--surface-accent-strength), #303030);
    --chat-input-tint: color-mix(in srgb, var(--prism-accent) var(--surface-accent-strength), #202020);
    --chat-input-bg: color-mix(in srgb, var(--chat-input-tint) 94%, transparent);
    --chat-input-solid: color-mix(in srgb, var(--prism-accent) var(--surface-accent-strength), #1c1c1c);

    --text-main: #ffffff;
    --text-muted: #a3a3a3;
    --text-subtle: #737373;
    --text-inverse: #000000;
    --surface-tint: #ffffff;            /* тёмное семейство: tint белый */

    /* Chrome-акцент на чёрном — МОЛОЧНЫЙ (осветляем тон палитры), чтобы не «наползал» цветом */
    --primary-500: color-mix(in srgb, var(--prism-accent) 62%, #fff);

    --shadow-glass: 0 8px 32px 0 color-mix(in srgb, var(--shadow-color) 45%, transparent);
    --shadow-dropdown: 0 16px 44px -22px color-mix(in srgb, var(--shadow-color) 80%, transparent);
    --shadow-modal: 0 24px 56px -26px color-mix(in srgb, var(--shadow-color) 85%, transparent);
}

/* ── ПРИЗМА СВЕТЛАЯ: КЛАССИЧЕСКАЯ светлая иерархия (R=G=B, без подтона). Страница — светло-серая;
   ПОДНЯТЫЕ поверхности (контейнеры/карточки/кнопки = panel/elevated/raised) — БЕЛЫЕ (контраст к
   серой странице, как в iOS/Telegram: кнопка на сером фоне = белая); утопленные поля
   (input/surface-dim) — светло-серые. Минимум токенов: только нужное, остальное берёт базу. */
[data-theme="prism-light"] {
    --lyrics-button-art-opacity: .16;
    --chart-series-1: #3266bc;
    --chart-series-2: #a96713;
    --chart-series-3: #257e69;
    --chart-series-4: #7c57b4;
    --chart-series-5: #b64469;
    --chart-series-6: #25788f;
    --chart-series-7: #807015;
    --chart-series-8: #796351;
    color-scheme: light;
    --bg-app: #eeeeee;                  /* страница — светло-серая (фон под белыми поверхностями) */
    --bg-panel: #ffffff;                /* контейнеры — белые */
    --bg-input: #f1f1f1;                /* утопленные поля/чипы — светло-серые */
    --bg-elevated: #ffffff;             /* поднятые карточки/кнопки — белые (поп на серой странице) */
    --bg-raised: #ffffff;               /* поднятые кнопки — белые */
    --bg-raised-hover: #efefef;         /* ховер поднятого — лёгкий серый */
    --chat-input-bg: rgba(255, 255, 255, 0.94);
    --shell-tab-active-bg: var(--bg-raised);
    --chat-input-solid: #ffffff;
    /* Модальные подложки в светлой теме именно осветляют страницу. Явные
       значения не дают отдельным body-порталам использовать тёмный fallback. */
    --modal-backdrop: rgba(255, 255, 255, 0.78);
    --modal-backdrop-soft: rgba(255, 255, 255, 0.58);

    /* Полупрозрачные серые (карточки списка / чипы / ghost / ховеры) — ЛЕГЧЕ дефолтных
       6/10/14/8%: серое-на-белом становится воздушнее, без «серый-серый». */
    --surface-soft: color-mix(in srgb, #000 4%, transparent);
    --surface-active: color-mix(in srgb, #000 7%, transparent);
    --surface-strong: color-mix(in srgb, #000 10%, transparent);
    --bg-hover: color-mix(in srgb, #000 5%, transparent);

    /* Текст — нейтральный (без фиолетового) */
    --text-main: #1a1a1a;
    --text-muted: #646464;
    --text-subtle: #8c8c8c;
    --text-inverse: #ffffff;

    --surface-tint: #000000;            /* светлое семейство: tint чёрный */
    /* Chrome-акцент на белом — НАПРЯМУЮ средний тон палитры (читаем тёмным текстом, виден на белом) */
    --primary-500: var(--prism-accent);
    /* Светлый инсет полей (поиск, тогглы и пр. на `bg-surface-dim`) — чистый светло-серый,
       а НЕ мутный base-0.2 (тёмное значение). Без него поля становятся грязно-серыми на белом. */
    --surface-dim: rgba(0, 0, 0, 0.06);

    /* Мягкие тени под белый фон (тяжёлые тёмные смотрятся грязно на свету) + дим-свечение акцента */
    --shadow-glass: 0 1px 3px color-mix(in srgb, var(--shadow-color) 6%, transparent);
    --shadow-inset: inset 0 1px 2px color-mix(in srgb, var(--shadow-color) 5%, transparent);
    --shadow-surface: 0 1px 2px color-mix(in srgb, var(--shadow-color) 5%, transparent);
    --shadow-dropdown: 0 12px 36px -8px color-mix(in srgb, var(--shadow-color) 12%, transparent);
    --shadow-icon: 0 1px 3px color-mix(in srgb, var(--shadow-color) 8%, transparent);
    --shadow-modal: 0 16px 48px -12px color-mix(in srgb, var(--shadow-color) 15%, transparent);
    /* Ореол композера на свету — шёпот, не пятно (пилюля и так белая на сером фоне). */
    --shadow-composer: 0 0 3px color-mix(in srgb, var(--shadow-color) 4%, transparent), 0 0 18px color-mix(in srgb, var(--shadow-color) 7%, transparent);
    --glow-spotlight: rgba(0, 0, 0, 0.2);
    --glow-accent-soft: 0 0 14px -6px var(--primary-20);
    --glow-accent-strong: 0 0 22px -8px color-mix(in srgb, var(--primary-700) 30%, transparent);
}

/* ========================================
   ПРОИЗВОДИТЕЛЬНЫЙ РЕЖИМ (data-perf="lite")
   Тумблер «Стили» в профиле. Цель — снять постоянную нагрузку от «стекла»:
   backdrop-filter при скролле промотирует слои и перерастеривает размытие
   каждый кадр. Здесь блюр не маскируется (blur(0px) всё равно создаёт слой),
   а ПОЛНОСТЬЮ отключается, а стеклянные поверхности переводятся на сплошную
   заливку (--chat-input-bg → непрозрачный --chat-input-solid), чтобы контент
   под ними не просвечивал. Правило активно только при включённом режиме;
   когда атрибута нет, ancestor-проверка отсекает селектор мгновенно.
   ======================================== */
/* Capture holds the outgoing layout only until the new one is ready. Entrances
   run on live elements afterwards, sharing the ShellMotion clock. */
::view-transition { pointer-events: none; }
::view-transition-group(root) { animation: none; }
::view-transition-old(root) {
    animation: none;
    display: none;
}
::view-transition-new(root) {
    animation: none;
}
@media (prefers-reduced-motion: reduce) {
    ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

:root[data-perf="lite"] {
    /* Стекло → сплошная заливка (единый токен покрывает ~все glass-поверхности). */
    --chat-input-bg: var(--chat-input-solid);
    /* Подстраховка для мест, читающих силу блюра из токена напрямую. */
    --glass-blur: 0px;
    --blur-lg: 0px;
    --progressive-blur-2: 0px;
    --progressive-blur-3: 0px;
    --progressive-blur-4: 0px;
}
:root[data-perf="lite"] *,
:root[data-perf="lite"] *::before,
:root[data-perf="lite"] *::after {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
}

/* Водяной знак: тёмная — нейтральный тёмно-серый; светлая — нейтральный светло-серый */
[data-theme="prism"] .bg-svg {
    --ambient-accent-500: var(--ambient-night-500);
    --ambient-accent-600: var(--ambient-night-600);
    --ambient-accent-700: var(--ambient-night-700);
}
[data-theme="prism-light"] .bg-svg {
    --ambient-accent-500: #9a9a9a;
    --ambient-accent-600: #868686;
    --ambient-accent-700: #707070;
}
[data-theme="prism-light"] :is(.bg-svg-desktop-letter, .bg-svg-mobile-letter) {
    /* На слегка сером фоне светлой темы ватермарк — БЕЛЫЙ (инверсия), но еле-еле —
       чтобы лишь проглядывался, не «в лоб». */
    fill: #ffffff;
    fill-opacity: 0.3;
}

/* Цветная часть announcement-баннера собирается из этих токенов в
   .global-announcement::before; сама поверхность остаётся тёмной по краям. */

/* Бордюры — только индивидуально, не дефолтным декором. Снимаем дефолтную рамку карточек
   главной в ОБЕИХ призмах. Тёмная: достаточно заливки (карточка светлее чёрного). Светлая
   (классический приём): вместо рамки — мягкая тень-подъём, иначе светло-серая карточка слилась бы. */
[data-theme="prism"] :is(.tile, .home-continue-card, .home-assistant-card) {
    box-shadow: none;
}
[data-theme="prism-light"] :is(.tile, .home-continue-card, .home-assistant-card) {
    box-shadow: var(--shadow-glass);
}

/* ════════════════════════════════════════════════════════════════════════════
   АКЦЕНТНЫЕ ПАЛИТРЫ — «цвет акцента» = выбор ГРАДИЕНТА. Каждая переопределяет
   спектральные ИСТОЧНИКИ → разом меняются CTA-градиент, кольцо/спектр композера,
   свечения и chrome-акцент. Дефолт — Sunset (в общем блоке выше). Идут ПОСЛЕ него →
   перебивают источники. Все сочетания намеренно приглушены и близки к природным материалам.
   Слот --prism-pink = тёплый конец CTA, --prism-lilac = холодный; --prism-accent —
   chrome-тон (средний, под белое; тёмная осветлит). ══════════════════════════════ */
[data-accent="iris"] {   /* однотонная графитовая олива */
    --prism-pink: #3F4430; --prism-lilac: #3F4430; --prism-cyan: #3F4430;
    --prism-gold: #3F4430; --prism-mint: #3F4430; --prism-yellow: #3F4430;
    --prism-accent: #3F4430;
    --prism-hi: #3F4430;
}
[data-accent="aurora"] { /* шалфей */
    --prism-pink: #485047; --prism-lilac: #626B5F; --prism-cyan: #59635B;
    --prism-gold: #555C50; --prism-mint: #697268; --prism-yellow: #5D665A;
    --prism-accent: #566057;
}
[data-accent="sunset"] { /* original muted taupe */
    --prism-pink: var(--brand-sunset-start);
    --prism-lilac: var(--brand-sunset-end);
    --prism-cyan: var(--brand-sunset-cool);
    --prism-gold: var(--brand-sunset-gold);
    --prism-mint: var(--brand-sunset-base);
    --prism-yellow: var(--brand-sunset-mid);
    --prism-hi: var(--brand-sunset-accent);
    --prism-accent: var(--brand-sunset-accent);
}
[data-accent="lagoon"] { /* минеральный сланец */
    --prism-pink: #40484A; --prism-lilac: #5B6567; --prism-cyan: #536063;
    --prism-gold: #4D5556; --prism-mint: #647073; --prism-yellow: #596164;
    --prism-accent: #505B5E;
}
[data-accent="orchid"] { /* дымчатый графит */
    --prism-pink: #49474B; --prism-lilac: #625F64; --prism-cyan: #57545A;
    --prism-gold: #5E595E; --prism-mint: #68656A; --prism-yellow: #5A575C;
    --prism-accent: #555258;
}

[data-theme="light"] .bg-svg {
    --ambient-accent-500: #767a86;
    --ambient-accent-600: #5f6470;
    --ambient-accent-700: #4a4f5b;
}

[data-theme="light"] :is(.bg-svg-desktop-letter, .bg-svg-mobile-letter) {
    /* На слегка сером фоне светлой темы ватермарк — БЕЛЫЙ (инверсия), но еле-еле. */
    fill: #ffffff;
    fill-opacity: 0.3;
}

/* Light mode: theme-specific class overrides */
[data-theme="light"] .icon-circle-primary {
    background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal;
    color: var(--primary-text);
}

[data-theme="light"] .icon-chip-primary {
    background-color: var(--surface-soft);
    color: var(--text-muted);
}

[data-theme="light"] .think-accordion {
    background-color: var(--bg-elevated);
    box-shadow: var(--shadow-surface);
}

/* Quiet message actions: selection is conveyed by icon color. */
.btn.chat-message-action-btn,
[data-theme] .btn.chat-message-action-btn:is(:hover, :active, :focus-visible) {
    background: transparent; border: 0; box-shadow: none; border-radius: 50%; corner-shape: var(--corner-shape-round);
}
.btn.chat-message-action-btn:hover { color: var(--text-main); }
.btn.chat-message-action-btn:focus-visible { outline: 2px solid var(--text-muted); outline-offset: -4px; }

[data-theme="light"] .upload-overlay {
    background-color: color-mix(in srgb, var(--bg-panel) 60%, transparent);
}

/* ========================================
   3. RESET & BASE
   ======================================== */
*, *::before, *::after {
    box-sizing: border-box;
}

/* Theme transitions are defaults. Component entrance/exit transitions must
   take precedence even when the document has an explicit theme. */
:where(html[data-theme] body,
       html[data-theme] .surface,
       html[data-theme] .modal-card,
       html[data-theme] .dropdown-panel,
       html[data-theme] .input-field) {
    transition: background-color var(--motion-duration-base) var(--motion-ease-standard),
                color var(--motion-duration-base) var(--motion-ease-standard),
                box-shadow var(--motion-duration-base) var(--motion-ease-standard);
}

html,
body {
    height: 100%;
    /* Динамический вьюпорт: dvh отслеживает сворачивание/разворот тулбара мобильных
       браузеров (Firefox), поэтому absolute;bottom:0-композеры садятся на истинный
       низ, а не «висят». Где динамического хрома нет (iOS PWA standalone / Android /
       десктоп) dvh == 100% → рендер идентичен. height:100% выше — фолбэк для движков
       без dvh. */
    height: 100dvh;
    margin: 0;
    padding: 0;
    scrollbar-gutter: stable;
    background-color: var(--bg-app);
    color: var(--text-main);
    font-family: var(--font-sans);
    line-height: var(--leading-normal);
}

body {
    font-size: var(--text-base);
    font-weight: var(--font-weight-regular);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background-color: var(--bg-app);
    position: relative;
}

/* Keep the document canvas in normal flow and full screen. Fixing body to the
   visual viewport shrinks the iOS standalone canvas below the status area.
   One internal flex frame owns the visible app; lists scroll inside it.
   No transform/contain: anchored popovers keep client coordinates. */
html.app-viewport {
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
    scrollbar-gutter: auto;
}
html.app-viewport.is-viewport-reduced { --safe-area-bottom: 0px; }
.app-viewport-frame,
.app-viewport :is([x-modal-stack], .fixed.inset-0, .drawer-viewport, #app-modal, .app-splash) {
    top: var(--app-viewport-top, 0px);
    left: var(--app-viewport-left, 0px);
    right: auto;
    bottom: auto;
    width: var(--app-viewport-width, 100%);
    height: var(--app-viewport-height, 100dvh);
}
body.app-viewport {
    display: block;
    height: auto;
    min-height: 100vh;
    overscroll-behavior: none;
    scrollbar-gutter: auto;
}
.app-viewport-frame {
    position: fixed;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    font-weight: var(--font-weight-display);
}

/* Выделение/копирование — как в ChatGPT/Claude: каркас приложения (сайдбар,
   рейл, шапки, кнопки, список чатов, модалки) не выделяется, копируется только
   контент — текст сообщений, код и поля ввода. Убирает «выделение всей страницы»
   и копирование навигации/кнопок; панель выделения браузера перестаёт всплывать
   над не-контентом. Публичные/legal-страницы (base.html без .app-root) не
   затронуты. Точечно вернуть выделение можно классом .selectable (реф-код и т.п.). */
.app-root {
    -webkit-user-select: none;
    user-select: none;
}
.app-root .markdown-render,
.app-root .code-block-wrapper,
.app-root input,
.app-root textarea,
.app-root select,
.app-root [contenteditable]:not([contenteditable="false"]),
.app-root .selectable {
    -webkit-user-select: text;
    user-select: text;
}

/* Inline background SVG — positioned behind all content */
.bg-svg {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
    pointer-events: none;
}
.bg-svg-base { fill: var(--bg-app); }
/* Glow ellipse behind the wordmark — brighter in dark theme so it actually
   reads against near-black --bg-app. Light theme keeps the original wash. */
.bg-svg-glow-stop-near { stop-opacity: 0.17; }
.bg-svg-glow-stop-mid  { stop-opacity: 0.10; }
[data-theme="light"] .bg-svg-glow-stop-near { stop-opacity: 0.12; }
[data-theme="light"] .bg-svg-glow-stop-mid  { stop-opacity: 0.07; }
.bg-svg-mobile-copy { display: none; }
.bg-svg-mobile-letter {
    font-family: var(--font-display);
    font-size: var(--text-wordmark-mobile);
    font-weight: var(--font-weight-display);
    line-height: var(--leading-none);
}
.bg-svg-desktop-letter {
    font-family: var(--font-display);
    font-size: var(--text-wordmark-desktop);
    font-weight: var(--font-weight-display);
    line-height: var(--leading-none);
}

@media (max-width: 767.98px) {
    .bg-svg-desktop-copy { display: none; }
    .bg-svg-mobile-copy { display: block; }
}

/* Native scrollbar appearance is shared in scrollbars.css. */

/*
 * CRITICAL: Visibility Helpers
 * We delegate .hidden to Tailwind to avoid !important conflicts with responsive display classes (e.g. hidden md:flex)
 */
[hidden], [x-cloak] { display: none !important; }

/* ========================================
   4. GLASS & COMPONENTS
   ======================================== */

/* --- Glass Blur (shared translucent panel style) --- */
.signin-card,
.chat-input-shell,
.media-viewer__tools,
.gallery-tool-surface,
.media-viewer__state-card > .media-viewer__tool,
.media-viewer__result-status > .media-viewer__tool,
.shell-mobile-chat-header-btn,
.shell-desktop-header__toggle,
.shell-user-pill,
.shell-user-pill--standalone,
.shell-mini-player--desktop,
.shell-mini-player__bubble,
.shell-mini-player__dismiss,
.tg-search-field,
.tg-history-clear,
.shell-tabs-frame {
    background-color: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
}

/* Auth fields tint their parent glass. Sidebar backgrounds own their paint:
   the rail is opaque, while secondary panels use one filtered ::before. */
.auth-btn,
.sidebar-shell {
    background-color: var(--chat-input-bg);
}

/* Solid dialogs avoid rasterizing backdrop blur during entrance animations. */
:is(.settings-panel, .payment-modal, .assistant-modal, .prompt-library-panel, .voice-modal, .modal-controls-panel) {
    background-color: var(--chat-input-solid);
}

/* Тень-подъём плавающей пилюли композера (чат/медиа/музыка/транскрипция) — отделяет её
   от ленты/сообщений. Симметричная (без смещения, `0 0`) — ровный ореол со всех сторон,
   как у парящей карточки. Слой на ::before, а не на самой пилюле, чтобы этот тёмный ambient
   СЛОЖИЛСЯ с её собственной box-shadow (--shadow-glass), а не заменил её (box-shadow из
   другого правила не аддитивен); z-index:-1 держит тень снаружи пилюли, не под её стеклом,
   inset:0 + наследуемый radius повторяют форму. Только композеры, не header-пилюли/табы/
   temp-pill из общей glass-группы выше. Переключатели над композером (Кадры/Референс,
   Простой/Продвинутый, выбор модели) подняты над этой тенью — см. z-index:2 ниже. */
.chat-input-main-shell::before,
.composer-state-layer--voice > .chat-input-shell::before,
.transcribe-composer-wrap .chat-input-shell::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    corner-shape: inherit;
    box-shadow: var(--shadow-composer);
    z-index: -1;
    pointer-events: none;
}

/* Переключатели-пилюли НАД композером (Кадры/Референс, Простой/Продвинутый, выбор модели
   транскрипции) сидят вплотную (~6px) над пилюлей, а её симметричная ::before-тень тянется
   вверх и без этого наслаивалась бы на них тёмным пятном. Поднимаем их НАД тенью: тень
   (z-index:-1 в контексте пилюли z-1) уходит за них. Позиционируем, чтобы z-index сработал. */
.generation-mode-selector,
.transcribe-models {
    position: relative;
    z-index: 2;
}

/* --- Specific Components --- */

.signin-floating-logo {
    top: 1.25rem;
    transition: top var(--motion-duration-base) var(--motion-ease-standard);
}

/* Signin bg is fixed (ignores flow), so logo needs explicit offset when banner is visible */
body[data-announcement-open="1"] .signin-floating-logo {
    top: calc(var(--announcement-height) + var(--safe-area-top) + 1.25rem);
}

/* Signin Card (glass-blur like chat input) */
.signin-card {
    box-shadow: var(--shadow-glass);
    transform: translateZ(0);
    backface-visibility: hidden;
}
@media (min-width: 640px) {
    .signin-card {
        height: 100%;
        border-radius: 0 var(--radius-2xl) var(--radius-2xl) 0 !important;
        corner-shape: var(--corner-shape-surface);
    }
}
@media (max-width: 639px) {
    .signin-card {
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        max-width: 100%;
        border-radius: var(--radius-xl) var(--radius-xl) 0 0 !important;
        corner-shape: var(--corner-shape-surface);
        padding: 1.25rem 1.25rem calc(env(safe-area-inset-bottom, 0.5rem) + 0.5rem);
    }

    .signin-floating-logo {
        top: 0.5rem;
    }
    body[data-announcement-open="1"] .signin-floating-logo {
        top: calc(var(--announcement-height) + var(--safe-area-top) + 0.5rem);
    }
}

/* ===== Шторка авторизации: сайдбар-оверлей поверх публичных страниц.
   Переиспользует карточку .signin-card (_auth_panel.html), но без полноэкранного
   фона — выезжает слева, страница видна за theme-aware подложкой. /login (signin.html)
   остаётся отдельной полноэкранной страницей. Разметка — _auth_overlay.html. */
.auth-overlay__scrim {
    position: fixed;
    inset: 0;
    z-index: 60;
    background: var(--modal-backdrop);
}

.auth-overlay__drawer {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 61;
    width: min(86vw, 360px);
    transform: translateX(0);
}
.auth-overlay__drawer.auth-drawer-moving {
    transition: transform var(--motion-duration-shell) var(--motion-ease-standard);
    will-change: transform;
}
.auth-overlay__drawer.auth-drawer-offscreen {
    transform: translateX(-100%);
}
/* Десктоп: боковая панель сидит ниже промо-баннера, чтобы он был виден сверху.
   (На мобиле шторка — нижний лист, ему смещение по top не нужно.) */
@media (min-width: 640px) {
    body[data-announcement-open="1"] .auth-overlay__drawer {
        top: calc(var(--announcement-height) + var(--safe-area-top));
    }
}

/* Внутри оверлея карточка просто заполняет drawer: гасим
   standalone-позиционирование .signin-card (fixed bottom-sheet / height:100%). */
.auth-overlay__card.signin-card {
    background-color: var(--chat-input-solid);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    position: relative !important;
    inset: auto !important;
    width: 100% !important;
    height: 100% !important;
    max-width: 100% !important;
    padding: 0 !important;
    overflow: hidden;
    border-radius: 0 var(--radius-2xl) var(--radius-2xl) 0 !important;
    corner-shape: var(--corner-shape-surface);
}

.auth-overlay__handle {
    position: absolute;
    inset: 0 0 auto;
    z-index: 2;
    display: flex;
    height: 1.5rem;
    align-items: flex-start;
    justify-content: center;
    padding-top: 0.5rem;
}
.auth-overlay__handle .drawer-handle {
    margin: 0;
}
@media (min-width: 640px) {
    .auth-overlay__handle {
        display: none;
    }
}

.auth-overlay__content {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    flex-direction: column;
    justify-content: center;
    overflow-y: auto;
    padding: 1.5rem;
}
@media (min-width: 640px) {
    .auth-overlay__content {
        padding: 1.75rem;
    }
}

/* Плавающий логотип «в шапке» (вне карточки, поверх затемнения) — как на /login.
   top и смещение под баннер берём из .signin-floating-logo. */
.auth-overlay__brand {
    position: fixed;
    left: 1.25rem;
    z-index: 62;
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--motion-duration-shell) var(--motion-ease-standard),
                visibility var(--motion-duration-shell) var(--motion-ease-standard);
}
.auth-overlay__brand.is-open {
    opacity: 1;
    visibility: visible;
}
.auth-overlay__close {
    position: absolute;
    top: 1.25rem;
    right: 1.25rem;
    z-index: 2;
    padding: 0.5rem;
}

/* Мобайл: шторка — нижний лист (как на странице /login), выезжает снизу. */
@media (max-width: 639px) {
    .auth-overlay__drawer {
        top: auto;
        left: 0;
        right: 0;
        bottom: 0;
        width: 100%;
        transform: translateY(0);
    }
    .auth-overlay__drawer.auth-drawer-offscreen {
        transform: translateY(100%);
    }
    .auth-overlay__card.signin-card {
        height: auto !important;
        max-height: 88dvh;
        border-radius: var(--radius-xl) var(--radius-xl) 0 0 !important;
        corner-shape: var(--corner-shape-surface);
    }
    .auth-overlay__content {
        padding-bottom: calc(1.5rem + var(--safe-area-bottom, 0px));
    }
    /* На мобиле закрытие — свайпом вниз / тапом по фону: крестик и логотип прячем.
       Для лого нужен двойной класс — иначе .site-logo (ниже по файлу) вернёт display:flex. */
    .auth-overlay__close,
    .auth-overlay__brand.site-logo {
        display: none;
    }
}

/* Auth Buttons (Signin) */
.site-logo {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--text-main);
    transition: var(--transition);
    text-decoration: none;
}
@media (hover: hover) {
    .site-logo:hover { opacity: 0.8; }
}
/* Единый знак бренда — один ассет через CSS-маску, перекрашивается currentColor
   (наследует цвет контейнера, т.е. тему). Источник: круглый знак favicon.svg
   (альфа-канал задаёт форму, цвет файла не важен). Размер — от контейнера.
   Заменяет инлайн-SVG по всему проекту. */
.brand-logo {
    display: block;
    flex-shrink: 0;
    background-color: currentColor;
    -webkit-mask: url("/static/media/favicon.svg") center / contain no-repeat;
            mask: url("/static/media/favicon.svg") center / contain no-repeat;
}

/* Широкий словесный знак (логотип «Skyny» целиком) для публичных страниц.
   Тот же приём CSS-маски + currentColor (тема-адаптивно). Ширину диктует
   aspect-ratio исходника (3103×507), высоту задаёт контейнер. */
.brand-wordmark {
    display: block;
    flex-shrink: 0;
    height: 1.6rem;
    aspect-ratio: 3103 / 507;
    background-color: currentColor;
    -webkit-mask: url("/static/media/%D0%BB%D0%BE%D0%B3%D0%BE.svg") left center / contain no-repeat;
            mask: url("/static/media/%D0%BB%D0%BE%D0%B3%D0%BE.svg") left center / contain no-repeat;
}
.brand-wordmark--sm { height: 1.4rem; }

/* Desktop branding shares the existing vector symbol and locally hosted font.
   Mobile headers keep their compact mark/wordmark and their own geometry. */
.brand-desktop {
    display: none;
    align-items: center;
    gap: var(--brand-desktop-gap);
    flex: 0 0 auto;
    white-space: nowrap;
}
.brand-desktop__symbol {
    width: var(--brand-desktop-symbol-size);
    height: var(--brand-desktop-symbol-size);
}
.brand-desktop__name {
    flex: 0 0 auto;
    font-family: var(--font-sans);
    font-size: var(--brand-desktop-name-size);
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-none);
    letter-spacing: var(--tracking-tight);
}
@media (min-width: 768px) {
    .brand-desktop { display: inline-flex; }
    .brand-mobile { display: none; }
}

.auth-btn {
    box-shadow: var(--shadow-glass);
    transition: var(--transition);
}
.auth-email-method-btn {
    background-color: var(--surface-active);
    color: var(--text-main);
}
@media (hover: hover) {
    .auth-btn:hover {
        background-color: var(--bg-hover);
    }
    .auth-email-method-btn:hover {
        background-color: var(--surface-strong);
    }
}
.auth-social-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    overflow: hidden;
    transition: var(--transition);
    cursor: pointer;
}
@media (hover: hover) {
    .auth-social-icon:hover {
        opacity: 0.8;
    }
}
.auth-social-icon img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}
.auth-divider {
    color: var(--text-subtle);
}

/* ── Способы входа в профиле (привязка провайдеров) ── */
/* .profile-info-card без собственных отступов (их дают ряды) — задаём свой
   padding, чтобы иконки/подсказка не прилипали к краям, как в остальных карточках. */
.auth-methods-card {
    padding: 1.1rem 1.25rem;
}
.auth-methods-row {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    flex-wrap: wrap;
}
/* Обёртка иконки: несёт бейдж-галочку СНАРУЖИ чипа. У .auth-social-icon
   overflow:hidden (обрезает img по кругу) — бейдж на самом чипе бы обрезался. */
.auth-method-item {
    position: relative;
    flex: 0 0 auto;
    line-height: 0;
}
/* Не привязан — обесцвечиваем и приглушаем; клик = привязать. */
.auth-method-chip.is-unlinked {
    filter: grayscale(1);
    opacity: 0.4;
}
@media (hover: hover) {
    .auth-method-chip.is-unlinked:hover {
        filter: grayscale(0.3);
        opacity: 0.85;
    }
}
.auth-method-check {
    position: absolute;
    right: -3px;
    bottom: -3px;
    width: 1.15rem;
    height: 1.15rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--gradient-primary);
    color: var(--primary-text);
    font-size: var(--text-2xs);
    box-shadow: none;
    pointer-events: none;
}
.auth-methods-hint {
    margin-top: 0.9rem;
    color: var(--text-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
}
/* Ряд «Пароль» / «Привязать почту» — горизонтальный (перебиваем column у .profile-info-row). */
.profile-info-row.auth-pw-row {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
}
.auth-pw-note {
    font-size: var(--text-xs);
    color: var(--text-muted);
}
.auth-pw-btn {
    padding: 0.4rem 0.85rem;
    font-size: var(--text-sm);
    flex: 0 0 auto;
}
.signin-glass-input {
    width: 100%;
    min-width: 0;
    background-color: var(--bg-input);
    box-shadow: var(--shadow-inset);
    color: var(--text-main);
    outline: none;
    border: none;
    transition: var(--transition);
}
.signin-glass-input::placeholder { color: var(--text-muted); opacity: 1; }
.signin-glass-input:focus-visible {
    box-shadow: var(--shadow-inset), 0 0 0 2px var(--text-muted);
}
.signin-glass-input[aria-invalid="true"] {
    box-shadow: var(--shadow-inset), 0 0 0 2px var(--text-main);
}
/* Browser autofill must use the same surface and text as ordinary fields. */
.signin-glass-input:is(:autofill, :-webkit-autofill) {
    -webkit-text-fill-color: var(--text-main);
    caret-color: var(--text-main);
    box-shadow: inset 0 0 0 1000px var(--bg-input);
}
.signin-glass-input:is(:autofill, :-webkit-autofill):focus-visible {
    box-shadow: inset 0 0 0 1000px var(--bg-input), 0 0 0 2px var(--text-muted);
}
.signin-field-label {
    display: block;
    text-align: left;
    margin-bottom: var(--gap-xs);
    color: var(--text-muted);
    font-size: var(--text-sm);
}
.signin-code-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--gap-sm); margin-top: var(--gap-sm); }
.signin-code-actions.hidden { display: none; }
.signin-text-button { color: var(--text-muted); font-size: var(--text-sm); text-decoration: underline; text-underline-offset: 3px; }
.signin-text-button:hover { color: var(--text-main); }
.signin-text-button:disabled { cursor: default; text-decoration: none; }
.signin-error { color: var(--text-main); overflow-wrap: anywhere; }
#email-subtitle, #footer-info-text { overflow-wrap: anywhere; }
.signin-card:not(.auth-overlay__card) { max-height: 100dvh; overflow-y: auto; }

/* Mobile drawers share --radius-xl with .chat-input-shell.shape. */
:is(.settings-panel, .model-modal, .assistant-modal, .prompt-library-panel, .voice-modal) {
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-modal);
}
@media (min-width: 640px) {
    :is(.settings-panel, .model-modal, .assistant-modal, .prompt-library-panel, .voice-modal) {
        border-radius: var(--radius-xl);
        corner-shape: var(--corner-shape-surface);
    }
}
/* Preview Iframe */
.preview-iframe { background-color: var(--bg-panel); }

/* Shape & Flex Utilities */
/* Tailwind radius utilities share the same curve contract as custom surfaces.
   Only radius size changes in their responsive variants. */
:is(.rounded, .rounded-sm, .rounded-md, .rounded-lg, .rounded-xl, .rounded-2xl, .rounded-3xl) {
    corner-shape: var(--corner-shape-surface);
}
:root .rounded-full { corner-shape: var(--corner-shape-round); }
.shape { border-radius: var(--radius-lg); corner-shape: var(--corner-shape-surface); }
.shape-pill { border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); }

/* Legacy surface marker: retain positioning, omit its static outline.
   Animated composer/drag frames use their own selectors below. */
.edge-gradient { position: relative; }
.edge-gradient::after {
    content: none;
}

/* Composer shells: slightly larger corner radius than generic .shape */
.chat-input-shell.shape { border-radius: var(--radius-xl); corner-shape: var(--corner-shape-surface); }
/* Pill-состояние композера: КОНЕЧНЫЙ радиус (половина схлопнутой высоты),
   а не --radius-pill — так transition плавно интерполирует заданное значение.
   Домножаем на --radius-scale, чтобы композер тоже слушал ползунок скруглений
   (при scale=1 = половина высоты = чистая капсула, при scale→0 = квадрат). */
.chat-input-shell.shape-pill { border-radius: calc(var(--chat-input-shell-min-height) / 2 * var(--radius-scale)); }
/* Иконка «стоп» внутри кнопки отправки: маленький скруглённый квадрат (не круг),
   радиус тоже слушает ползунок скруглений. */
.composer-stop-glyph { border-radius: var(--radius-sm); corner-shape: var(--corner-shape-surface); }
.text-2xs { font-size: var(--text-2xs); line-height: var(--leading-none); }

.flex-center { display: inline-flex; align-items: center; justify-content: center; }

/* Button Utilities */
/* Styled controls own their paint on every engine; native button bevels must
   not reappear in pressed/disabled states. Keyboard focus keeps its CSS ring. */
button,
input:is([type="button"], [type="submit"], [type="reset"]) {
    -webkit-appearance: none;
    appearance: none;
}
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--gap-sm);
    font-weight: var(--font-weight-medium);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    padding: 0.5rem 1rem;
    font-size: var(--text-control);
    transition:
        background-color var(--transition),
        color var(--transition),
        box-shadow var(--transition),
        opacity var(--transition-fast),
        filter var(--transition);
}
.btn-lg { padding: 0.75rem 1.5rem; font-size: var(--text-control); }
.btn-block { width: 100%; }
.btn-primary {
    background-color: var(--primary-500);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 160px 160px, auto;
    background-blend-mode: overlay, normal;    /* grainy gradient: шум overlay'ится на градиент */
    color: var(--primary-text);
}
.btn:active {
    filter: saturate(0.98);
}
.btn-secondary {
    background-color: var(--bg-elevated);
    color: var(--text-main);
}
.btn-ghost {
    background-color: var(--bg-input);
    color: var(--text-main);
}
.btn:disabled,
.btn.is-disabled {
    background-color: var(--bg-input);
    background-image: none;   /* сбрасываем градиент .btn-primary, иначе disabled выглядит активной */
    color: var(--text-muted);
    box-shadow: none;
    cursor: not-allowed;
}

/* Utility Classes */
.ff-display { font-family: var(--font-display); }
.text-legal  { font-size: var(--text-2xs); }
.btn-surface  { background-color: var(--bg-app); color: var(--text-main); }
/* Motion Utilities */
.motion {
    transition-property: transform, opacity, color, background-color, box-shadow, filter;
    transition-duration: var(--motion-duration-base);
    transition-timing-function: var(--motion-ease-premium);
}

/* Единый keyframe вращения 360° (спиннеры): скорость задаётся в animation-shorthand,
   не в keyframes, поэтому один блок обслуживает все спиннеры проекта. */
@keyframes spin-360 {
    to { transform: rotate(360deg); }
}

.loading-spinner {
    --spinner-size: 1.25rem;
    --spinner-thickness: 0.2rem;
    width: var(--spinner-size);
    height: var(--spinner-size);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    display: inline-block;
    background: conic-gradient(from 180deg, var(--spinner-head) 0deg, var(--spinner-mid) 220deg, var(--spinner-track) 285deg, transparent 330deg 360deg);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - var(--spinner-thickness)), var(--text-inverse) calc(100% - var(--spinner-thickness)));
    mask: radial-gradient(farthest-side, transparent calc(100% - var(--spinner-thickness)), var(--text-inverse) calc(100% - var(--spinner-thickness)));
    animation: spin-360 var(--motion-period-spinner) var(--motion-ease-linear) infinite;
}

.loading-spinner-xs {
    --spinner-size: 1rem;
    --spinner-thickness: 0.18rem;
}
.loading-spinner-sm { --spinner-size: 1.5rem; }

/* Surface */
.surface {
    background-color: var(--bg-panel);
    box-shadow: var(--shadow-surface);
}
.pager-btn {
    width: 2rem;
    height: 2rem;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background-color: var(--bg-app);
    color: var(--text-muted);
    transition: var(--transition);
}
@media (hover: hover) {
    .pager-btn:hover {
        color: var(--text-main);
    }
}
.dropdown-panel,
.model-flyout {
    background-color: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    box-shadow: var(--shadow-glass);
}

.dropdown-panel {
    position: absolute;
    z-index: var(--z-dropdown);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
}

/* Dropdown menus (unified look across the app)
   Apply via: class="dropdown-panel dropdown-menu ..." */
.dropdown-menu {
    display: flex;
    flex-direction: column;
    padding: 0.1875rem;
    max-height: min(60dvh, 13.4375rem, var(--floating-max-height, 100dvh));
    max-width: var(--floating-max-width, calc(100vw - 16px));
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;


}


.dropdown-menu__title {
    padding: 0.4375rem 0.75rem 0.3125rem;
    font-size: var(--text-2xs);
    line-height: var(--leading-tight);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--text-subtle);
}

/* Некликабельная строка-описание в дропдауне (item.kind === 'description'),
   например краткое описание коннектора над кнопкой «Настройки». */
.dropdown-menu__desc {
    padding: 0.125rem 0.75rem 0.375rem;
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    color: var(--text-muted);
}
.ui-note {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: calc(var(--gap-sm) * 3);
    height: calc(var(--gap-sm) * 3);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    color: var(--text-muted);
    font-size: var(--text-sm);
}
.ui-note:is(:hover, :focus-visible, [aria-expanded="true"]) {
    color: var(--text-main);
    background: var(--surface-soft);
}
.ui-note-panel { width: min(18rem, calc(100vw - 1rem)); }

/* Поле ввода — стеклянный фон-тинт, но БЕЗ собственного backdrop-filter: почти всегда
   лежит внутри стеклянной модалки/сайдбара, второй блюр дал бы двойной (категория B). */
.input-field {
    width: 100%;
    background-color: var(--chat-input-bg);
    box-shadow: var(--shadow-inset);
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    color: var(--text-main);
    transition: var(--transition);
    outline: none;
    border: none;
}
.input-field-ghost {
    background-color: transparent;
    color: var(--text-main);
    outline: none;
}

/* Глобальный tailwind `:focus-visible { outline: auto }` (outline-color:
   currentcolor = белый текст в тёмной теме) рисует белый focus-ring на
   ghost-инпутах — заметно в Firefox при вводе в медиа/музыка-композеры (в
   чат-textarea он гасится utility-классом `outline-none`). Перебиваем его
   правилом выше по специфичности; прозрачный outline вместо none остаётся
   видимым в forced-colors (a11y). Фокус и так виден по самой пилюле композера. */
.input-field-ghost:focus,
.input-field-ghost:focus-visible {
    outline: 2px solid transparent;
    outline-offset: 2px;
}

/* ── Нативные чекбоксы = переключатели (глобально): видимый нейтральный
      трек + светлый ползунок, включение
      заливает трек акцентом. appearance:none делает input нестилизуемым
      браузером, ::after-ползунок на таких инпутах поддержан всеми evergreen. ── */
input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    flex-shrink: 0;
    width: 2.1rem;
    height: 1.2rem;
    margin: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-strong);
    box-shadow: inset 0 0 0 1px var(--text-main-18);
    cursor: pointer;
    vertical-align: middle;
    transition: background var(--transition);
}

input[type="checkbox"]::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 0.15rem;
    width: 0.9rem;
    height: 0.9rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-paper);
    box-shadow: var(--shadow-surface);
    transform: translateY(-50%);
    transition: transform var(--transition);
}

input[type="checkbox"]:checked {
    background: var(--primary-500);
}

input[type="checkbox"]:checked::after {
    transform: translateY(-50%) translateX(0.9rem);
}

input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--primary-500);
    outline-offset: 2px;
}

input[type="checkbox"]:disabled {
    opacity: 0.5;
    cursor: default;
}

.service-card {
    transition: box-shadow var(--motion-duration-base) var(--motion-ease-standard), filter var(--transition), background-color var(--transition);
}
@media (hover: hover) {
    .service-card:hover {
        filter: saturate(1.04);
    }
}
/* Чип в стекле (категория B): полупрозрачная подложка, сквозь которую читается блюр. */
.surface-chip {
    background-color: var(--surface-active);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    transition: background-color var(--transition), box-shadow var(--transition), color var(--transition);
}
@media (hover: hover) {
    .surface-chip:hover {
        background-color: var(--surface-strong);
        box-shadow: var(--shadow-surface);
    }
}
/* ── Inline media params tabs ── */
.media-params-block {
    display: flex;
    flex-direction: column;
    gap: 0.32rem;
    width: 100%;
    min-width: 0;
}

.media-params-bar {
    display: flex;
    align-items: center;
    gap: 0.24rem;
    width: 100%;
    min-width: 0;
    padding: 0;
    background: transparent;
}

.media-params-bar__strip {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    align-content: flex-start;
    flex: 1 1 auto;
    min-width: 0;
    gap: 0.25rem;
    max-height: 2.4rem;
    overflow: hidden;
}

.media-params-bar__meta {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.28rem;
    flex: 0 0 auto;
    min-width: 0;
}

.media-params-bar__slot {
    position: relative;
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
}

.media-params-bar__slot.is-overflow {
    visibility: hidden;
    pointer-events: none;
}

/* Compact pills and expanded settings share the same surface states. */
.media-params-pill,
.media-setting-card {
    background: var(--surface-active);
    color: var(--text-main);
}

.media-params-pill,
.price-pill.media-composer-price__value {
    min-height: 2.4rem;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-display);
}

.price-pill.media-composer-price__value { padding: 0.44rem 1rem; }

.media-params-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.44rem;
    padding: 0.44rem 0.78rem;
    max-width: 12rem;
    border: none;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    white-space: nowrap;
    transition: background-color var(--transition), color var(--transition);
}

.media-params-pill__icon {
    flex-shrink: 0;
    font-size: var(--text-lg);
    color: var(--text-main);
}

.media-params-pill__icon.media-params-pill__icon--aspect-preview {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.05rem;
    height: 1.05rem;
    font-size: 0;
}

.media-params-pill__icon.media-params-pill__icon--aspect-preview::before {
    content: '';
    width: var(--aspect-preview-width, 0.9rem);
    height: var(--aspect-preview-height, 0.9rem);
    border-radius: calc(0.18rem * var(--radius-scale));
    box-shadow: inset 0 0 0 1.5px currentColor;
}

.media-params-pill__value {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

@media (hover: hover) {
    .media-params-pill:hover,
    .media-setting-card:hover,
    .chat-input-shell .btn.media-params-expanded__reset:hover {
        background: var(--surface-strong);
    }
}

.media-params-pill.is-open,
.media-setting-card--select.is-open {
    background: var(--surface-strong);
}

/* Toggle-переключатель в пилюле (вкл/выкл): тёмный «колодец»-трек + белый ползунок;
   при включении трек заливается акцентом (--primary-500), ползунок едет вправо.
   Сама пилюля фоном НЕ подсвечивается — состояние несёт только переключатель. */
.media-params-pill__switch {
    position: relative;
    flex-shrink: 0;
    width: 1.85rem;
    height: 1.05rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-dim);
    transition: background var(--transition);
}

.media-params-pill__switch::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 0.125rem;
    width: 0.8rem;
    height: 0.8rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--text-main);
    box-shadow: var(--shadow-surface);
    transform: translateY(-50%);
    transition: transform var(--transition);
}

.media-params-pill__switch.is-on {
    background: var(--primary-500);
}

.media-params-pill__switch.is-on::after {
    transform: translateY(-50%) translateX(0.8rem);
}

.media-params-bar__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.4rem;
    height: 2.4rem;
    padding: 0;
    border: none;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-active);
    color: var(--text-main);
    transition: background-color var(--transition), color var(--transition);
}

.media-params-bar__toggle i {
    font-size: var(--text-lg);
    transition: transform var(--motion-duration-shell) var(--motion-ease-standard);
}

.media-params-bar__toggle.is-open i {
    transform: rotate(180deg);
}

@media (hover: hover) {
    .media-params-bar__toggle:hover {
        background: var(--surface-strong);
    }
}

.media-params-bar__toggle:focus-visible {
    outline: none;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--primary-500) 28%, transparent);
}

.media-composer-price {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    gap: 0.3rem;
    color: var(--text-subtle);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    line-height: var(--leading-none);
    white-space: nowrap;
}

.media-composer-price__detail {
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    line-height: var(--leading-none);
    white-space: nowrap;
}

.media-params-expanded {
    display: grid;
    grid-template-rows: 0fr;
    opacity: 0;
    pointer-events: none;
    transition:
        grid-template-rows var(--motion-duration-base) var(--motion-ease-premium),
        opacity var(--motion-duration-fast) var(--motion-ease-premium);
}

.media-params-expanded.is-open {
    grid-template-rows: 1fr;
    opacity: 1;
    pointer-events: auto;
}

.media-params-expanded__inner {
    overflow: hidden;
    min-height: 0;
    padding-top: 0;
    transition: padding-top var(--motion-duration-fast) var(--motion-ease-premium);
}

.media-params-expanded.is-open .media-params-expanded__inner {
    padding-top: 0.4rem;
}

.media-params-expanded__footer {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.32rem;
}

.media-params-expanded__reset {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 var(--composer-control-size);
    width: var(--composer-control-size);
    height: var(--composer-control-size);
    padding: 0;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--text-subtle);
    cursor: pointer;
    transition: color var(--transition-fast), background-color var(--transition-fast);
}

.media-params-expanded__reset i {
    font-size: var(--text-base);
}

@media (hover: hover) {
    .media-params-expanded__reset:hover {
        color: var(--text-main);
        background-color: var(--surface-soft);
    }
}
.media-params-expanded__reset:focus-visible {
    outline: 2px solid var(--text-muted);
    outline-offset: -2px;
}

.media-params-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    width: 100%;
    align-items: stretch;
}

.media-params-grid__item {
    display: flex;
    min-width: 0;
    flex: 0 1 8.6rem;
    width: min(100%, 8.6rem);
    align-self: stretch;
}

.media-params-grid__item.is-compact {
    flex-basis: 7.8rem;
    width: min(100%, 7.8rem);
}

.media-params-grid__item.is-range {
    flex-basis: 10.6rem;
    width: min(100%, 10.6rem);
}

.media-params-grid__item.is-wide {
    flex-basis: 100%;
    width: 100%;
}

.media-composer-top-stack {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 0.32rem;
    /* Отступ под стрипом — НЕ margin здесь: это прямой ребёнок .composer-collapsible,
       margin не клипается grid-template-rows:0fr и залипает ~0.42rem до display:none
       (allow-discrete) → «дёрг вниз спустя миг» при смене Кадры↔Референс. Отступ живёт
       padding'ом внутри .media-frame-strip (в overflow:hidden-клипе → сворачивается в 0). */
}

/* Fields, including the prompt, share the capped scroll viewport on every width.
   The action row keeps its height in the dock. */
.media-composer-scroll-region {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* Keep the natural content height measurable after the scroll viewport is capped. */
.media-composer-scroll-content {
    flex: 0 0 auto;
    min-width: 0;
}

.media-composer-dock-region {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex-shrink: 0;
}
/* Swapping/hiding mic and send must not add/remove a control row mid-collapse.
   The dock owns this minimum; flex/grid distribute the editor space above it. */
.media-composer-dock-region .composer-toolbar {
    min-height: var(--composer-control-size);
}



.media-param-model-card {
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    background: color-mix(in srgb, var(--bg-panel) 68%, var(--bg-elevated) 32%);
    box-shadow: var(--shadow-surface);
}

.media-param-model-card {
    display: inline-flex;
    align-items: center;
    gap: 0.32rem;
    width: auto;
    max-width: 100%;
    flex: 0 0 auto;
    align-self: center;
    padding: 0.28rem 0.42rem;
    min-height: 2.16rem;
    border: none;
    color: var(--text-main);
    text-align: left;
    white-space: nowrap;
    transition: background-color var(--transition), box-shadow var(--transition);
}

.media-param-model-card--toolbar {
    max-width: min(42%, 14rem);
}

@media (hover: hover) {
    .media-param-model-card:hover {
        background-color: var(--bg-hover);
    }
}

.media-setting-card__header {
    display: flex;
    min-width: 0;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.5rem;
}

.media-setting-card__label {
    min-width: 0;
    overflow-wrap: anywhere;
    font-size: var(--text-2xs);
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-wide);
    font-weight: var(--font-weight-semibold);
    color: var(--text-subtle);
}

.media-param-model-card__icon {
    flex-shrink: 0;
}

.media-setting-card__value {
    font-size: var(--text-sm);
    line-height: var(--leading-tight);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
}

.media-param-model-card__name {
    font-size: var(--text-xs);
    line-height: var(--leading-tight);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    min-width: 0;
    max-width: 8rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

.media-setting-card__hint,
.generation-mode-btn__hint {
    font-size: var(--text-2xs);
    line-height: var(--leading-tight);
    color: var(--text-subtle);
    /* Подписи вроде «старт и финал» шире узкой пилюли — переносим до 2 строк
       вместо обрезки многоточием («старт и фи…»). */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

.media-param-model-card__price,
.media-setting-card__meta {
    flex-shrink: 0;
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
}

.media-param-model-card__chevron {
    flex-shrink: 0;
    font-size: var(--text-sm);
    color: var(--text-subtle);
}

.media-setting-card {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    width: 100%;
    height: 100%;
    gap: var(--gap-2xs);
    min-height: 0;
    padding: var(--gap-sm) calc(var(--gap-sm) * 1.5);
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    transition: background-color var(--transition), box-shadow var(--transition);
}

.media-params-grid__item.is-compact .media-setting-card__hint {
    display: none;
}

.media-params-grid__item.is-compact .media-setting-card__value,
.media-params-grid__item.is-compact .media-setting-card__meta {
    font-size: var(--text-xs);
}

.media-setting-card--select {
    display: flex;
    flex-direction: column;
    width: 100%;
    border: none;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    text-align: left;
    cursor: pointer;
    transition: background-color var(--transition);
}

.media-setting-card--toggle {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 0.56rem;
    cursor: pointer;
}

.media-setting-card__toggle-copy {
    display: flex;
    flex-direction: column;
    gap: 0.08rem;
    flex: 1 1 auto;
}

.media-setting-card__value {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.media-setting-card__chevron {
    flex-shrink: 0;
    color: var(--text-subtle);
    font-size: var(--text-base);
    transition: transform var(--motion-duration-shell) var(--motion-ease-standard);
}

.media-setting-card--select.is-open .media-setting-card__chevron {
    transform: rotate(180deg);
}

.media-setting-card--select:focus-visible {
    outline: none;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--primary-500) 28%, transparent);
}

.media-setting-card__field {
    width: 100%;
    min-height: 1.9rem;
    padding: 0.36rem 0.46rem;
    border: none;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-input);
    color: var(--text-main);
    outline: none;
    transition: box-shadow var(--transition), background-color var(--transition);
}

.media-setting-card__field::placeholder {
    color: var(--text-subtle);
}

.media-setting-card__field:focus {
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--primary-500) 28%, transparent);
}

.media-setting-card__field--textarea {
    min-height: 3.9rem;
    resize: vertical;
}

.media-setting-card__switch {
    position: relative;
    flex-shrink: 0;
    width: 2rem;
    height: 1.15rem;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-raised);
    transition: background-color var(--transition), transform var(--transition-fast);
}

.media-setting-card__switch.is-active {
    background: var(--primary-500);
}

.media-setting-card__switch-handle {
    position: absolute;
    top: 0.12rem;
    left: 0.12rem;
    width: 0.9rem;
    height: 0.9rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--text-inverse);
    box-shadow: var(--shadow-surface);
    transition: transform var(--transition-fast);
}

.media-setting-card__switch-handle.is-active {
    transform: translateX(0.82rem);
}

.media-setting-card__stack {
    display: flex;
    flex-direction: column;
    gap: 0.24rem;
    min-width: 0;
}

.media-composer-preview-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    align-items: center;
    padding: calc(var(--gap-sm) * 1.5) calc(var(--gap-sm) * 1.5) 0;
}

.media-composer-preview-card {
    width: var(--media-preview-size);
    height: var(--media-preview-size);
}

.media-composer-character {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    height: var(--media-preview-size);
    max-width: 100%;
    padding: 0 var(--gap-sm);
}
.media-composer-character__photo {
    width: calc(var(--media-preview-size) - 2 * var(--gap-sm));
    height: calc(var(--media-preview-size) - 2 * var(--gap-sm));
    object-fit: cover;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
}
.media-composer-character__name {
    min-width: 0;
    max-width: 12rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--text-label);
}
.media-composer-character__remove {
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    padding: 0;
}

.media-frame-strip {
    display: inline-flex;
    flex-wrap: wrap;
    gap: var(--gap-sm);
    align-items: center;
    max-width: 100%;
    padding: 0 0 var(--gap-sm);
}

.media-frame-tile {
    position: relative;
    flex: 0 0 auto;
    width: max(var(--upload-source-width), 7rem);
    min-width: 0;
}

.media-frame-tile:has(.has-media) {
    width: max(var(--upload-source-width), 9rem);
}

.media-frame-tile:is([data-media-frame-tile="start"], [data-media-frame-tile="end"]):has(.has-media) {
    width: max(var(--upload-source-width), 8rem);
}

/* Shared upload surface: frames, source audio, voices and references. */
.upload-source {
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: var(--gap-xs);
    width: var(--upload-source-width);
    height: var(--upload-source-height);
    min-height: var(--upload-source-height);
    padding: var(--gap-sm);
    border: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-main);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    line-height: var(--leading-tight);
    box-shadow: none;
    cursor: pointer;
    transition: background-color var(--transition-fast);
}
.upload-source-art {
    display: block;
    flex-shrink: 0;
    width: var(--upload-source-art-size);
    height: var(--upload-source-art-size);
    object-fit: contain;
}
.upload-source:focus-visible, .media-frame-strip__swap:focus-visible {
    outline: var(--gap-2xs) solid var(--prism-accent);
    outline-offset: var(--gap-2xs);
}
@media (hover: hover) { .upload-source:hover { background: var(--surface-strong); } }
.media-frame-tile__action {
    position: relative;
    display: flex;
    width: 100%;
    aspect-ratio: auto;
    overflow: hidden;
}

@media (hover: hover) {
    /* Surface feedback keeps the tile geometry stable. */
    .media-frame-tile__action:hover {
        background: var(--surface-strong);
    }
}

@media (prefers-reduced-motion: reduce) {
    .media-frame-tile__action { transition: none; }
}

/* «Конец» заблокирован, пока нет стартового кадра: приглушён, клик не работает
   (tooltip объясняет почему). disabled-атрибут не используем — он глушит hover,
   а tooltip должен показываться. */
.media-frame-tile__action.is-locked {
    cursor: not-allowed;
    color: var(--text-muted);
}

@media (hover: hover) {
    .media-frame-tile__action.is-locked:hover {
        background: var(--surface-soft);
    }
}

.media-frame-tile__preview {
    position: absolute;
    top: 50%;
    left: var(--gap-sm);
    transform: translateY(-50%);
    width: var(--upload-source-art-size);
    height: var(--upload-source-art-size);
    overflow: hidden;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
}
.media-frame-tile__media {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity var(--transition-fast);
}
.media-frame-tile__media.is-loaded {
    opacity: 1;
}

.media-frame-tile__upload {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: inherit;
    corner-shape: inherit;
    background: var(--overlay-backdrop-soft);
}
.media-frame-tile__preview-error {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    font-size: var(--text-base);
}

/* Compact upload chips: icon/thumbnail, label and remove action share one row. */
.media-frame-tile__empty {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: var(--gap-xs);
    padding: var(--gap-sm);
    pointer-events: none;
    color: inherit;
}

.media-frame-tile__text {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    line-height: var(--leading-snug);
}

.media-frame-tile__badge {
    position: absolute;
    left: calc(var(--upload-source-art-size) + var(--gap-sm) + var(--gap-xs));
    right: calc(var(--gap-sm) * 4.5);
    top: 50%;
    transform: translateY(-50%);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    color: var(--text-main);
}

.media-frame-tile__clear {
    position: absolute;
    top: 50%;
    right: calc(var(--gap-sm) * 0.5);
    transform: translateY(-50%);
    z-index: 3;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: calc(var(--gap-sm) * 3.5);
    height: calc(var(--gap-sm) * 4);
    border: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--text-muted);
    box-shadow: none;
    font-size: var(--text-sm);
    cursor: pointer;
}
.media-frame-tile .media-frame-tile__action:focus-visible,
.media-frame-tile .media-frame-tile__clear:focus-visible {
    outline-offset: -3px;
}

@media (hover: hover) {
    .media-frame-tile__clear:hover {
        background: color-mix(in srgb, var(--bg-panel) 78%, var(--bg-elevated));
    }
}

/* Frame swap shares the composer buttons' surface and interaction states. */
.media-frame-strip__swap {
    flex: 0 0 auto;
    width: var(--composer-control-size);
    height: var(--composer-control-size);
    padding: 0;
}

@media (min-width: 768px) {
    /* Upload tiles stay inside the composer on all viewport sizes. */
    .media-composer-top-stack {
        position: relative;
        z-index: 2;
        margin-top: 0;
    }

    /* Тень и hover-подъём карточек резал .media-composer-top-stack (overflow:hidden от
       правила коллапса .composer-collapsible > *). В ОТКРЫТОМ состоянии снимаем клип —
       тень видна целиком; при закрытии is-open снимается, базовый overflow:hidden
       возвращается и анимация сворачивания (grid-rows) клипает как надо. */
    .composer-collapsible.is-open > .media-composer-top-stack {
        overflow: visible;
    }
}

@media (max-width: 767px) {
    .media-params-bar__meta {
        gap: 0.24rem;
    }

    .media-params-pill,
    .price-pill.media-composer-price__value { min-height: 2.2rem; }

    .price-pill.media-composer-price__value { padding: 0.38rem 0.875rem; }

    .media-params-pill {
        padding: 0.38rem 0.62rem;
        gap: 0.38rem;
        max-width: 9.5rem;
        font-size: var(--text-sm);
    }

    .media-params-pill__icon {
        font-size: var(--text-base);
    }

    .media-params-pill__icon.media-params-pill__icon--aspect-preview {
        width: 0.98rem;
        height: 0.98rem;
    }

    .media-params-bar__toggle {
        width: 2.2rem;
        height: 2.2rem;
    }

    .media-params-bar__toggle i {
        font-size: var(--text-base);
    }

    .media-composer-price {
        gap: 0.28rem;
    }

    .media-params-grid {
        gap: 0.28rem;
    }

    .media-params-grid__item,
    .media-params-grid__item.is-compact {
        flex-basis: calc(50% - 0.18rem);
        width: calc(50% - 0.18rem);
    }

    .media-params-grid__item.is-range,
    .media-params-grid__item.is-wide {
        flex-basis: 100%;
        width: 100%;
    }

    .media-composer-top-stack {
        gap: 0.28rem;
        /* Отступ под стрипом — НЕ здесь: это прямой ребёнок .composer-collapsible,
           его margin не клипается grid-template-rows:0fr и залипает ~пару px до
           display:none (allow-discrete), давая «дёрг вниз спустя миг» при смене
           Кадры↔Референс. Отступ ушёл внутрь на .media-frame-strip (в overflow-клип). */
    }

    .media-param-model-card {
        max-width: calc(100% - 0.18rem);
        padding: 0.24rem 0.36rem;
        border-radius: var(--radius-lg);
        corner-shape: var(--corner-shape-surface);
    }

    .media-param-model-card--toolbar {
        max-width: 8.4rem;
    }

    .media-setting-card {
        border-radius: var(--radius-base);
        corner-shape: var(--corner-shape-surface);
    }

    .media-setting-card__field {
        min-height: 1.8rem;
        padding: 0.32rem 0.4rem;
    }

    .media-setting-card__field--textarea {
        min-height: 3.7rem;
    }

    :root { --media-preview-size: 2.75rem; }


}

/* ── Media Composer Layout ──
   Плоская структура: на mobile — flex column (селектор сверху, shell снизу).
   На desktop ≥1100px — flex row, селектор слева от shell'а. align-items: stretch
   гарантирует, что высота селектора всегда совпадает с высотой shell'а. */
.media-composer {
    display: flex;
    flex-direction: column;
    gap: var(--gap-xs);
    width: 100%;
    position: relative;
    z-index: 1;
}

.media-composer-shell {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: var(--gap-xs);
    min-width: 0;
    flex: 1 1 auto;
}

.music-tool-switch { display: flex; justify-content: center; flex: 0 0 auto; }
.music-tool-switch .transcribe-model:disabled { cursor: default; opacity: 0.5; }

/* Ambient motion for the group AI call; text and hit area stay still. */
.group-ai-call {
    --ai-call-period: var(--motion-period-ai-call);
    position: relative;
    isolation: isolate;
    overflow: hidden;
    color: var(--text-main);
    font-family: var(--font-sans);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text-main) 16%, transparent);
}
.group-ai-call::before {
    content: '';
    position: absolute;
    z-index: -1;
    inset: -80% -30%;
    pointer-events: none;
    background:
        radial-gradient(ellipse at 25% 55%, color-mix(in srgb, var(--text-main) 24%, transparent), transparent 48%),
        radial-gradient(ellipse at 75% 40%, color-mix(in srgb, var(--text-main) 12%, transparent), transparent 42%);
    animation: group-ai-call-flow var(--ai-call-period) var(--motion-ease-ambient) infinite;
}
.group-ai-call__icon {
    position: relative;
    isolation: isolate;
    animation: group-ai-call-breathe var(--ai-call-period) var(--motion-ease-ambient) infinite;
}
.group-ai-call__icon::before {
    content: '';
    position: absolute;
    z-index: -1;
    inset: -0.375rem;
    border-radius: 50%;
    corner-shape: var(--corner-shape-round);
    pointer-events: none;
    background: radial-gradient(circle, color-mix(in srgb, var(--text-main) 22%, transparent), transparent 70%);
    animation: group-ai-call-halo var(--ai-call-period) var(--motion-ease-ambient) infinite;
}
.group-ai-call.is-active {
    --ai-call-period: var(--motion-period-ai-call-active);
    background-color: var(--surface-strong);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text-main) 32%, transparent);
}
.group-ai-call:focus-visible {
    outline: 2px solid var(--text-main);
    outline-offset: 2px;
}
@keyframes group-ai-call-flow {
    0%, 100% { transform: translateX(-12%) rotate(-8deg); opacity: 0.55; }
    50% { transform: translateX(12%) rotate(8deg); opacity: 1; }
}
@keyframes group-ai-call-breathe {
    0%, 100% { transform: scale(0.94); }
    50% { transform: scale(1.06); }
}
@keyframes group-ai-call-halo {
    0%, 100% { transform: scale(0.8); opacity: 0.35; }
    50% { transform: scale(1.18); opacity: 0.9; }
}
@media (prefers-reduced-motion: reduce) {
    .group-ai-call::before,
    .group-ai-call__icon,
    .group-ai-call__icon::before { animation: none; }
}

/* Generic collapsible-секция внутри composer'а (chat и media):
   плавно разворачивается/сворачивается через grid-template-rows trick
   с эластичной кривой. Применяется к блокам, которые добавляются в DOM
   и иначе скачком увеличивают высоту поля (вложения, reply, frame strip и т.п.).
   Закрытое состояние выпадает из layout (display: none + allow-discrete),
   чтобы не оставлять паразитный gap во flex-родителе.

   ИНВАРИАНТ (вертикальный collapse): прямой ребёнок — ЧИСТЫЙ КЛИП, без
   собственных вертикальных padding/margin (py-, my- утилит). Грид-трек 0fr
   сжимает только контент-бокс клипа: паддинги и маргины прямого ребёнка НЕ
   сжимаются, висят остатком до конца транзишена и срубаются щелчком на
   display:none (allow-discrete) — «схлопывание в 2 этапа». Вертикальные
   отступы — уровнем глубже, внутрь overflow:hidden-клипа (прецеденты:
   reply-блок, хинты вложений, .media-frame-strip). Контент при leave
   замирает на последнем валидном значении (снапшот rSnap или aSnap,
   гейченый x-effect), не x-text от живого стейта. */
/* Measured content regions share one height animation. The existing inner
   clip is the natural-size probe; tools and other composer transitions stay
   independent. Do not combine this owner with grid/height transitions. */
.composer-size-region {
    min-height: 0;
    overflow: hidden;
}
.composer-size-region > * {
    display: flow-root;
    min-width: 0;
}
.music-source-region {
    margin-top: calc(-1 * var(--gap-sm, 0.75rem));
}
.music-source-region > .music-source-region__content {
    display: flex;
    flex-direction: column;
    gap: var(--gap-sm, 0.75rem);
    padding-top: var(--gap-sm, 0.75rem);
}

.composer-collapsible {
    display: grid;
    grid-template-rows: 1fr;
    opacity: 1;
    pointer-events: auto;
    transition-property: display, grid-template-rows, opacity;
    transition-duration: var(--motion-duration-base), var(--motion-duration-base), var(--motion-duration-fast);
    /* Плавно, без «отскока» — как у image/video «Все параметры» (.media-params-expanded).
       Раньше геометрия шла на --motion-ease-elastic (перелёт за 1 → пружина); единый
       premium делает все вертикальные схлопывания композеров одинаковыми. */
    transition-timing-function: var(--motion-ease-premium), var(--motion-ease-premium), var(--motion-ease-premium);
    transition-behavior: allow-discrete;
}
.composer-collapsible:not(.is-open) {
    display: none;
    grid-template-rows: 0fr;
    opacity: 0;
    pointer-events: none;
}
.composer-collapsible > * {
    min-height: 0;
    overflow: hidden;
}
@starting-style {
    .composer-collapsible.is-open {
        grid-template-rows: 0fr;
        opacity: 0;
    }
}

/* Мини-превью цитируемого изображения/видео в плашке «Ответ» композера
   (startAttachmentReply): файлы/аудио остаются иконкой + именем. */
.composer-reply-thumb {
    width: 34px;
    height: 34px;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    object-fit: cover;
    flex-shrink: 0;
}

/* Обёртка простого промпта в медиа-композере: тот же grid-rows коллапс, но БЕЗ
   @starting-style (иначе textarea «въезжала» бы на каждом маунте композера) и без
   display:none — закрытое прячет visibility (дискретный транзишен: hidden в конце
   закрытия, visible сразу при открытии; заодно фокус/клики в закрытом невозможны). */
.composer-prompt-collapsible {
    display: grid;
    grid-template-rows: 1fr;
    opacity: 1;
    visibility: visible;
    transition: grid-template-rows var(--motion-duration-base) var(--motion-ease-premium),
                opacity var(--motion-duration-fast) var(--motion-ease-premium),
                visibility var(--motion-duration-base);
}
.composer-prompt-collapsible:not(.is-open) {
    grid-template-rows: 0fr;
    opacity: 0;
    visibility: hidden;
}
.composer-prompt-collapsible > * {
    min-height: 0;
    overflow: hidden;
}
/* Carry the card's available height through the collapse clip to its body.
   A closed section consumes no free space; footer height stays intrinsic. */
.composer-prompt-collapsible--fill {
    flex: 0 0 auto;
    transition-property: grid-template-rows, opacity, visibility, flex-grow;
    transition-duration: var(--motion-duration-base), var(--motion-duration-fast), var(--motion-duration-base), var(--motion-duration-base);
    transition-timing-function: var(--motion-ease-premium);
}
.composer-prompt-collapsible--fill.is-open { flex-grow: 1; }
.composer-prompt-collapsible--fill > * { display: flex; flex-direction: column; }

/* Соло-аудио вложение в чат-композере: редактор волны + кнопка × (вместо чипа). */
.composer-audio-wave {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding-top: 0.25rem;
}
.composer-audio-wave__editor { flex: 1; min-width: 0; }
.composer-audio-wave__del {
    flex-shrink: 0;
    width: 2rem; height: 2rem;
    display: flex; align-items: center; justify-content: center;
    border: none; padding: 0;
    background: transparent;
    color: var(--text-muted);
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    cursor: pointer;
    transition: color var(--transition), background-color var(--transition);
}
@media (hover: hover) {
    .composer-audio-wave__del:hover { color: var(--text-main); background: var(--surface-strong); }
}

/* Пилы в ГОРИЗОНТАЛЬНОМ ряду params-row схлопываются ТОЛЬКО по ширине
   (grid-columns) и opacity. Высота ряда пилам не принадлежит ни в одном
   состоянии — ей владеет обёртка .chat-input-params-rowslot (см. layout-секцию
   композера): rows-анимация пилы в flex-ряду сжимала её вертикально при полной
   ширине, а пер-пильные фазовые задержки читались «лесенкой»/фризом.
   Отрицательный margin-right в закрытом состоянии компенсирует flex-gap ряда —
   display:none не даёт скачка и на ширину gap. Easing premium (не elastic):
   овершут по ширине на выходе читается как дрожь.
   Единый темп композера: геометрия — base/premium, прозрачность — fast/premium,
   НИКАКИХ transition-delay. display = base (allow-discrete из базового правила):
   узел покидает поток ровно в момент, когда ширина доехала до нуля. */
.chat-input-params-row > .composer-collapsible {
    grid-template-rows: 1fr;
    grid-template-columns: 1fr;
    transition-property: display, grid-template-columns, opacity, margin-right;
    transition-duration: var(--motion-duration-base), var(--motion-duration-base), var(--motion-duration-fast), var(--motion-duration-base);
    transition-timing-function: var(--motion-ease-premium);
}
.chat-input-params-row > .composer-collapsible:not(.is-open) {
    grid-template-rows: 1fr;   /* высоту не отдаём никогда — см. комментарий выше */
    grid-template-columns: 0fr;
    margin-right: calc(var(--params-row-gap) * -1);
}
.chat-input-params-row > .composer-collapsible > * {
    min-width: 0;
    white-space: nowrap;       /* без переноса лейбла на середине анимации (скачок высоты) */
    /* bg/shadow/color — как у базового .surface-chip (этот блок его перебивает). */
    transition: padding var(--motion-duration-base) var(--motion-ease-premium),
                background-color var(--transition), box-shadow var(--transition), color var(--transition);
}
/* Остаточная ширина схлопнутой пилы — собственные паддинги чипа (px-3):
   grid 0fr зажимает только трек, padding-box остаётся ~1.5rem, и в момент
   display:none соседние пилы прыгали влево на эту ширину. Зануляем паддинги
   по той же кривой — пила доезжает ровно до нулевой ширины. Только при
   открытой шторке (.has-params): при её закрытии пила в hold-open остаётся
   полноразмерной (см. правило ниже). */
.chat-input-state-stack.has-params .chat-input-params-row > .composer-collapsible:not(.is-open) > * {
    padding-left: 0;
    padding-right: 0;
}
@starting-style {
    .chat-input-params-row > .composer-collapsible.is-open {
        grid-template-columns: 0fr;
        margin-right: calc(var(--params-row-gap) * -1);
        opacity: 0;
    }
    /* Зеркало для входа: паддинги растут вместе с треком — без стартового 24px-попа. */
    .chat-input-state-stack.has-params .chat-input-params-row > .composer-collapsible.is-open > * {
        padding-left: 0;
        padding-right: 0;
    }
}

/* Инлайн width-collapse ВНЕ params-row (чип ассистента в контролс-баре):
   та же механика, что у пил ряда — постоянный узел, ширина+fade+padding,
   leave-анимация при снятии; высоту не трогаем (бар фиксированной высоты).
   Отрицательный margin-right закрытого состояния компенсирует gap-1 (0.25rem)
   flex-ряда контролов. */
.composer-collapsible--inline {
    display: grid;
    grid-template-columns: 1fr;
    min-width: 0;
    opacity: 1;
    pointer-events: auto;
    transition-property: display, grid-template-columns, opacity, margin-right;
    transition-duration: var(--motion-duration-base), var(--motion-duration-base), var(--motion-duration-fast), var(--motion-duration-base);
    transition-timing-function: var(--motion-ease-premium);
    transition-behavior: allow-discrete;
}
.composer-collapsible--inline > * {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    transition: padding var(--motion-duration-base) var(--motion-ease-premium);
}
.composer-collapsible--inline:not(.is-open) {
    display: none;
    grid-template-columns: 0fr;
    margin-right: -0.25rem;
    opacity: 0;
    pointer-events: none;
}
.composer-collapsible--inline:not(.is-open) > * {
    padding-left: 0;
    padding-right: 0;
}
@starting-style {
    .composer-collapsible--inline.is-open {
        grid-template-columns: 0fr;
        margin-right: -0.25rem;
        opacity: 0;
    }
    .composer-collapsible--inline.is-open > * {
        padding-left: 0;
        padding-right: 0;
    }
}

/* Шторка params закрывается (снята последняя пила → у стека ушёл .has-params):
   пилы внутри держим на полной ширине и непрозрачными — закрывающаяся шторка
   сама клипает их одним движением, без гонки двух схлопываний. display уходит
   в none по концу собственного transition (allow-discrete, base) — ровно когда
   шторка (тоже base) закрылась. */
.chat-input-state-stack:not(.has-params) .chat-input-params-row > .composer-collapsible:not(.is-open) {
    grid-template-columns: 1fr;
    margin-right: 0;
    opacity: 1;
}
@media (max-width: 767px) {
    /* Активный ассистент держит шторку открытой и без params — рядом с его
       чипом пилы схлопываются по ширине как обычно. */
    .chat-input-state-stack.has-mobile-assistant:not(.has-params) .chat-input-params-row > .composer-collapsible:not(.is-open) {
        grid-template-columns: 0fr;
        margin-right: calc(var(--params-row-gap) * -1);
        opacity: 0;
    }
    .chat-input-state-stack.has-mobile-assistant .chat-input-params-row > .composer-collapsible:not(.is-open) > * {
        padding-left: 0;
        padding-right: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .composer-collapsible,
    .composer-prompt-collapsible,
    .chat-input-params-row > .composer-collapsible,
    .chat-input-params-row > .composer-collapsible > *,
    .composer-collapsible--inline,
    .composer-collapsible--inline > *,
    .chat-input-state-stack,
    .chat-input-state-stack::before,
    .chat-input-params-shell,
    .chat-input-params-rowslot,
    .chat-input-params-shell .ultra-banner { transition: none; }
}

/* Shared composer geometry motion for assistant activation / multiline. */
.composer-input-stack {
    transition: padding var(--motion-duration-base) var(--motion-ease-premium);
}

@media (prefers-reduced-motion: reduce) {
    .composer-input-stack { transition: none; }
}

@media (min-width: 1100px) {
    .media-composer.has-modes {
        flex-direction: row;
        align-items: stretch;
        gap: 0.42rem;
    }
}

/* One moving selection surface using the shared control motion tokens.
   Absolute positioning preserves grid/flex sizing, including vertical modes. */
[x-segmented] {
    position: relative;
    isolation: isolate;
    --segment-active-bg: var(--surface-strong);
}
[x-segmented].profile-tabs { --segment-active-bg: var(--bg-raised); }
[x-segmented].model-category-tabs { --segment-active-bg: var(--surface-active); }
[x-segmented] > .segment-indicator {
    position: absolute;
    left: 0;
    top: 0;
    z-index: -1;
    pointer-events: none;
    background: var(--segment-active-bg);
    visibility: hidden;
}
[x-segmented].has-segment-indicator > .segment-indicator {
    visibility: visible;
    transition: transform var(--motion-duration-base) var(--motion-ease-premium),
                width var(--motion-duration-base) var(--motion-ease-premium),
                height var(--motion-duration-base) var(--motion-ease-premium),
                border-radius var(--motion-duration-base) var(--motion-ease-premium);
}
[x-segmented].has-segment-indicator > :is(button, a) {
    background: transparent !important;
}
@media (prefers-reduced-motion: reduce) {
    [x-segmented].has-segment-indicator > .segment-indicator { transition: none; }
}

.generation-mode-selector {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(5.3rem, max-content));
    gap: var(--gap-2xs);
    width: fit-content;
    max-width: 100%;
    padding: var(--gap-xs);
    /* Капсульный сегментбар (эталон): pill-трей + pill-сегменты, активный
       --surface-strong, концентричный зазор --gap-xs. Трей стеклянный
       (--chat-input-bg + блюр) — бар автономный на странице, не в стекле. */
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    box-shadow: var(--shadow-glass);
}

@media (min-width: 1100px) {
    .media-composer.has-modes > .generation-mode-selector {
        flex: 0 0 5.15rem;
        width: 5.15rem;
        grid-template-columns: 1fr;
        grid-auto-rows: 1fr;
    }
}

.generation-mode-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.08rem;
    min-width: 0;
    min-height: 2rem;
    padding: 0.28rem 0.4rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--text-muted);
    border: none;
    cursor: pointer;
    text-align: center;
    transition: background-color var(--transition), color var(--transition);
}

.generation-mode-btn__label {
    width: 100%;
    font-size: var(--text-xs);
    line-height: var(--leading-tight);
    font-weight: var(--font-weight-semibold);
    color: currentColor;
    text-transform: none;
    text-align: center;
}

.generation-mode-btn__hint {
    width: 100%;
    text-align: center;
}

@media (hover: hover) {
    .generation-mode-btn:hover {
        background: var(--bg-hover);
        color: var(--text-main);
    }
}
.generation-mode-btn.active {
    background: var(--surface-strong);
    color: var(--text-main);
}

@media (max-width: 767px) {
    .generation-mode-selector {
        grid-template-columns: 1fr 1fr;
        width: 100%;
    }

    .generation-mode-btn {
        min-height: 1.9rem;
        padding: 0.24rem 0.34rem;
    }
}

/* ===== Музыкальный композер (Suno) — /music ===== */
.music-composer-layout { container: music-composer music-source-layout / inline-size; }
/* Fill the animated shell through the voice-layer wrapper. Without this,
   the new mode takes its natural height at once and the dock jumps before
   the surface catches up. Keep its bottom anchor even during expansion. */
.media-composer-normal-layer > .music-composer-layout {
    flex: 1 1 auto;
    justify-content: flex-end;
}
/* Mode changes have one height owner. Inner views switch to their final
   layout before the shell is measured; independent grid transitions would
   add two different trajectories and jump when interrupted. */
.has-composer-mode-size :is(.music-adv-collapsible, .composer-prompt-collapsible) {
    transition: none;
}
.has-composer-mode-size[data-composer-mode-transition] .media-composer-scroll-region {
    overflow-y: clip;
}
/* A mode swap measures the completed layout. Source rows must reach that
   layout with the fields; their own grid/width tweens would change its target
   after the outer height has already started moving. */
.has-composer-mode-size[data-composer-mode-transition] :is(.music-source-panel-row, .music-source-option) {
    transition: none;
}
.music-composer-layout > .music-composer-head { flex: 0 0 auto; }
.music-composer-layout > .media-composer-scroll-region { margin-top: var(--gap-sm); }
.music-composer-panel {
    display: flex;
    flex-direction: column;
    container: music-composer / inline-size;
    gap: var(--gap-sm, 0.75rem);
    width: 100%;
    padding-bottom: 0.25rem;
}
.landing-demo-music-composer .music-composer-panel { container-name: music-composer music-source-layout; }
/* Шапка: режим слева; очистка и версия справа.
   Меню версии — стандартный ctxMenu-портал, свой дропдаун не рисуем. */
/* Высота всех контролов шапки = 2.5rem — как у кнопок дока (w-10 h-10),
   верх и низ композера выглядят одной системой. */
.music-composer-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap-sm);
    min-height: var(--composer-control-size);
}
.music-composer-head__actions {
    display: flex;
    align-items: center;
    gap: var(--gap-xs);
    margin-left: auto;
    flex-shrink: 0;
}
.music-composer-head__sources {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    /* Wrap the group before squeezing its source pill into an empty sliver. */
    flex: 0 0 auto;
    min-width: 0;
    max-width: 100%;
    margin-inline-start: auto;
}
.music-composer-head__sources > .music-composer-head__actions { margin-left: 0; }
/* The simple music and sound headers share one control row. Let the source
   strip use its existing horizontal scroll when the desktop sidebar leaves
   less room; wrapping the whole group changes the empty page title's center. */
.music-composer-head--simple > .music-composer-head__sources { flex: 1 1 0; }
.music-composer-head--simple > .music-seg { flex: 0 0 auto; }
.music-head-icon {
    width: var(--composer-control-size);
    height: var(--composer-control-size);
    padding: 0;
    color: var(--text-muted);
}
.music-head-icon i { font-size: var(--text-xl); }
@media (hover: hover) { .music-head-icon:hover { color: var(--text-main); } }
.music-version-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--gap-xs);
    min-height: var(--composer-control-size);
    padding: 0 calc(var(--gap-sm) * 2);
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-active);
    color: var(--text-main);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    cursor: pointer;
    transition: background-color var(--transition);
}
.music-version-pill i { font-size: var(--text-sm); color: var(--text-subtle); }
.music-version-pill .model-chip-icon { width: 1.15rem; height: 1.15rem; }
@media (hover: hover) { .music-version-pill:hover { background: var(--surface-strong); } }

/* Fit the actual composer width (including narrow desktop panes), not the
   viewport. Keep full mode/version labels and the shared control height. */
.music-composer-head .music-seg {
    min-width: 0;
}
.music-composer-head .music-seg__btn {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.music-version-pill { white-space: nowrap; }
@container music-composer (max-width: 26rem) {
    .music-composer-head { gap: var(--gap-xs); }
    .music-composer-head__actions { gap: var(--gap-2xs); }
    .music-composer-head .music-seg .music-seg__btn { padding-inline: var(--gap-xs); }
    .music-composer-head .music-version-pill {
        padding-inline: var(--gap-xs);
        gap: var(--gap-2xs);
        font-size: var(--text-xs);
    }
}
@container music-composer (max-width: 20rem) {
    .music-composer-head { gap: var(--gap-2xs); }
    .music-composer-head .music-seg .music-seg__btn { padding-inline: calc(var(--gap-2xs) * 2); }
    .music-composer-head .music-version-pill .model-chip-icon { display: none; }
}

.music-composer-advanced {
    display: flex;
    flex-direction: column;
    gap: var(--gap-sm, 0.75rem);
}

/* Внешний коллапсибл продвинутого блока (живой, НЕ x-if — см. _music_composer.html):
   панель .music-composer-panel — flex-col с gap, а закрывающийся коллапсибл держит
   display до конца анимации (allow-discrete) → gap схлопнулся бы «щелчком» в самом
   конце. Закрытое состояние съедает gap отрицательным margin-top, транзишенимым
   вместе с высотой (зеркало приёма params-row). transition-property повторяет
   генерик .composer-collapsible + margin-top. */
.music-adv-collapsible {
    transition-property: display, grid-template-rows, opacity, margin-top;
    transition-duration: var(--motion-duration-base), var(--motion-duration-base), var(--motion-duration-fast), var(--motion-duration-base);
    transition-timing-function: var(--motion-ease-premium);
}
.music-adv-collapsible:not(.is-open) {
    margin-top: calc(-1 * var(--gap-sm, 0.75rem));
}
@starting-style {
    .music-adv-collapsible.is-open {
        margin-top: calc(-1 * var(--gap-sm, 0.75rem));
    }
}
/* The body is now independent of the pinned header. Keep its empty grid row
   in flow so sibling spacing does not jump at the end of a mode transition. */
.music-composer-layout .music-adv-collapsible {
    display: grid;
    margin-top: 0;
}
/* This modifier is declared after the shared reduced-motion rule. Keep its
   geometry/spacing transition disabled along with the simple prompt. */
@media (prefers-reduced-motion: reduce) {
    .music-adv-collapsible { transition: none; }
}
/* Продвинутый: «Текст песни» ‖ «Стиль» в две колонки (экономия высоты) */
.music-columns {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--gap-sm, 0.75rem);
    align-items: stretch;
}
@media (max-width: 767px) {
    .music-columns { grid-template-columns: 1fr; }
}

/* Плитки-источники (Продвинутый): «Аудио» / «Голос» — вместо «+» дока.
   В тон секциям (--surface-soft); бейдж «Новое» — общий .model-badge-new;
   точка-индикатор — прикреплённый референс / выбранный голос. */
.music-source-tiles {
    --upload-source-height: var(--composer-control-size);
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--gap-sm);
}
.music-seg, .music-source-tiles--header { --seg-gap: 0.15rem; }
.music-source-tiles--header {
    --upload-source-height: calc(var(--composer-control-size) - var(--seg-gap) * 2);
    display: none;
    flex: 0 0 auto;
    height: var(--composer-control-size);
    margin-inline-start: auto;
    gap: 0;
    padding: var(--seg-gap);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
}
.music-source-tiles--header > .music-source-tile {
    padding: 0 calc(var(--gap-sm) * 1.5);
    border-radius: max(0px, calc(var(--radius-pill) - var(--seg-gap)));
    corner-shape: var(--corner-shape-round);
    background: transparent;
}
/* A desktop composer can still be narrow beside an open sidebar. */
@media (min-width: 1100px) {
    @container music-source-layout (min-width: 40rem) {
        .music-source-tiles--header { display: grid; }
        .music-composer-head:not(.music-composer-head--simple) > .music-source-tiles--header + .music-composer-head__actions { margin-left: 0; }
        .music-composer-advanced > .music-source-tiles { display: none; }
    }
}
.music-source-tile {
    position: relative;
    width: 100%;
    min-width: 0;
}
@media (max-width: 390px) {
    .media-frame-strip { --upload-source-width: calc(var(--gap-sm) * 13); }
}
.media-frame-tile__action.is-locked .upload-source-art { opacity: .55; }
.music-source-tile i { font-size: var(--text-base); color: var(--text-muted); }
.music-source-tile .model-badge-new { text-transform: none; letter-spacing: var(--tracking-normal); }
@media (hover: hover) { .music-source-tile:hover { background: var(--surface-strong); } }
.music-source-tile__dot {
    position: absolute;
    top: 0.45rem;
    right: 0.45rem;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--primary-500);
}

/* The same source pill serves both modes. Each option retains its intrinsic
   measurement while its clipped wrapper animates down to zero. */
.music-source-panel-row {
    display: none;
    flex: 0 1 auto;
    grid-template-rows: 0fr;
    opacity: 0;
    min-width: 0;
    max-width: 100%;
    margin-inline-start: auto;
    transition: grid-template-rows var(--transition), opacity var(--transition-fast);
}
.music-source-panel-row.is-open { grid-template-rows: 1fr; opacity: 1; }
.music-source-panel-row:not(.is-open) { max-width: 0; }
.music-source-panel-clip { min-height: 0; min-width: 0; overflow: hidden; }
.music-source-panel {
    --seg-gap: 0.15rem;
    --upload-source-height: calc(var(--composer-control-size) - var(--seg-gap) * 2);
    display: flex;
    width: max-content;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
    padding: var(--seg-gap);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
}
.music-source-panel::-webkit-scrollbar { display: none; }
.music-source-option {
    display: flex;
    flex: 0 0 auto;
    width: 0;
    opacity: 0;
    overflow: hidden;
    visibility: hidden;
    transition: width var(--transition), opacity var(--transition-fast), visibility var(--transition);
}
.music-source-option.is-open { width: var(--music-source-width, 6rem); opacity: 1; visibility: visible; }
.music-source-option > .music-source-tile {
    flex: 0 0 auto;
    width: max-content;
    padding: 0 calc(var(--gap-sm) * 1.5);
    border-radius: max(0px, calc(var(--radius-pill) - var(--seg-gap)));
    corner-shape: var(--corner-shape-round);
    background: transparent;
    white-space: nowrap;
}
@media (min-width: 1100px) {
    .music-source-panel-row { display: grid; }
}
@media (prefers-reduced-motion: reduce) {
    .music-source-panel-row, .music-source-option { transition: none; }
}

.music-section {
    display: flex;
    flex-direction: column;
    gap: var(--gap-xs, 0.5rem);
    min-width: 0;   /* grid/flex-элемент держит ширину колонки, а не растёт по содержимому (скролл чипов) */
    padding: 0.75rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);   /* верхнеуровневая плашка = радиус карточек (.shape) */
    background: var(--surface-soft);
}
.music-section--row {
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--gap-sm, 0.75rem);
    align-items: flex-end;
}
/* Resize handles provide their own bottom clearance inside editor cards. */
.music-columns > .music-section { padding-bottom: 0; }
.music-columns .music-section__hint { padding-bottom: 0.75rem; }
.music-section__head {
    display: flex;
    flex-shrink: 0;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap-sm, 0.75rem);
}
.music-section__head--lyrics {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
}
.music-section__head--lyrics > .music-seg {
    grid-column: 3;
    grid-row: 1;
}
.music-section__title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
}
.music-section__head .music-section__title,
.music-section__head .music-seg__btn { white-space: nowrap; }
.music-section__head--editor {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--gap-2xs) var(--gap-xs);
    min-height: 2.5rem;
}
.music-section:has(> .music-section__head--editor) { container-type: inline-size; }
.music-section__head--editor .music-section__title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.music-section__meta {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--gap-sm);
    min-height: 2rem;
}
@container (min-width: 18.5rem) {
    .music-section__head--lyrics.music-section__head--editor { grid-template-columns: minmax(0, 1fr) auto auto; }
    .music-section__head--editor .music-section__meta { grid-column: 3; grid-row: 1; }
}
.music-field-tools { display: flex; align-items: center; gap: 0.125rem; }
.music-field-tools__button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1.5rem;
    height: 1.875rem;
    padding: 0;
    border: 0;
    background: transparent;
    box-shadow: none;
    color: var(--text-main);
    font-size: var(--text-lg);
    cursor: pointer;
}
.music-field-tools__button:disabled { opacity: 0.3; cursor: default; }
.music-field-tools__button:hover:not(:disabled),
.music-field-tools__button[aria-expanded="true"] { color: var(--text-main); }
.music-field-library-modal {
    display: flex;
    flex-direction: column;
    width: 100%;
    overflow: hidden;
}
@media (min-width: 640px) {
    .music-field-library-modal { max-width: calc(var(--gap-sm) * 50); }
}
.music-field-library__head {
    gap: var(--gap-sm);
    padding: calc(var(--gap-sm) * 2) calc(var(--gap-sm) * 2) var(--gap-sm);
}
.music-field-library__body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    gap: var(--gap-sm);
    padding: 0 calc(var(--gap-sm) * 2) calc(var(--gap-sm) * 2);
}
.music-field-library__search { flex-shrink: 0; }
.music-field-library__body > .modal-form-footer { padding-inline: 0; }
.music-field-library__search input { min-width: 0; font-size: var(--text-sm); }
.music-field-library__search:focus-within { background: var(--surface-soft); }
.music-field-library__list {
    min-height: 0;
    max-height: min(calc(var(--gap-sm) * 40), calc(var(--drawer-max-h) - var(--gap-sm) * 18));
    overflow-y: auto;
    overscroll-behavior: contain;
}
.music-field-library__item {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: var(--gap-sm);
    width: 100%;
    min-width: 0;
    padding: var(--gap-sm);
    border: 0;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    text-align: left;
    color: var(--text-main);
    background: transparent;
    cursor: pointer;
}
.music-field-library__item:hover, .music-field-library__item:focus-visible { background: var(--surface-soft); }
.music-field-library__item > i { font-size: var(--text-lg); color: var(--text-muted); }
.music-field-library__content { display: grid; min-width: 0; gap: var(--gap-2xs); }
.music-field-library__content strong {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
}
.music-field-library__preview { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; white-space: pre-line; overflow-wrap: anywhere; color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-normal); }
.music-field-library__content time { font-size: var(--text-2xs); color: var(--text-subtle); }
.music-field-library__message { padding: var(--gap-sm); color: var(--text-muted); font-size: var(--text-sm); }
.music-editor-bottom { display: grid; align-items: center; min-height: 1.25rem; grid-column: 1 / -1; }
.music-editor-bottom > * { grid-area: 1 / 1; }
.music-editor-bottom > .music-counter { justify-self: end; }
.music-section__hint {
    font-size: var(--text-xs);
    color: var(--text-muted);
}

/* Мини-сегментбар (Свой текст / Инструментал, вокал) */
.music-seg {
    display: inline-flex;
    gap: 0.15rem;
    padding: var(--seg-gap);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-dim);
}
/* Шапка композера: сегмент лежит прямо на стекле — полупрозрачная подложка
   вместо тёмного скрима (пузырёк .active и так полупрозрачный --surface-strong). */
.music-composer-head .music-seg {
    min-height: var(--composer-control-size);
    background: var(--surface-soft);
}
.music-seg__btn {
    min-height: 1.7rem;   /* + трей 0.15rem×2 = 2rem, в тон .music-chip */
    padding: 0 0.7rem;
    border: none;
    /* Концентрическое вложение в .music-seg (внешний − зазор). */
    border-radius: max(0px, calc(var(--radius-pill) - var(--seg-gap, 0.15rem)));
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    cursor: pointer;
    transition: background-color var(--transition), color var(--transition);
}
.music-seg__btn.active {
    background: var(--surface-strong);
    color: var(--text-main);
}
.music-seg--icons {
    --seg-gap: 0px;
    flex-shrink: 0;
    height: var(--composer-control-size);
}
.music-seg--icons > .music-seg__btn {
    display: grid;
    place-items: center;
    /* An explicit width also participates in intrinsic grid/flex sizing.
       With flex-basis alone Firefox sized the parent to the glyphs, letting
       the second fixed-size button paint outside its segment and editor. */
    flex: 0 0 auto;
    width: var(--composer-control-size);
    min-height: 0;
    padding: 0;
    font-size: var(--text-lg);
}
@media (hover: hover) {
    .music-seg__btn:hover { color: var(--text-main); }
}

.music-editor-modes {
    display: flex;
    flex-direction: column;
    flex: 1 0 auto;
    min-width: 0;
    /* Alternative collapsed states must not create gaps at the card level. */
}
.music-editor-body {
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 1 0 auto;
    min-width: 0;
    gap: var(--gap-xs);
}
.music-editor-footer {
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
    min-width: 0;
    gap: var(--gap-xs);
}
/* Float editor actions over the field; only the resize/counter row remains
   below it. Bottom text padding lets the final line scroll clear of controls. */
.music-editor-body:has(.lyrics-prompt-tools) {
    --music-editor-action-inset: calc(var(--gap-sm) * 1.5);
    gap: 0;
}
.music-editor-body:has(.lyrics-prompt-tools) > :is(.music-lyrics__area, .music-style__area) {
    padding-bottom: calc(var(--composer-control-size) + var(--gap-xs) + var(--music-editor-action-inset));
}
.music-editor-body:has(.lyrics-prompt-tools) > .music-editor-footer {
    position: relative;
    z-index: 1;
    margin-top: calc(-1 * (var(--composer-control-size) + var(--music-editor-action-inset)));
    pointer-events: none;
}
.music-editor-body > .music-editor-footer :is(button, .lyrics-prompt-panel, .composer-scroll-hint-host, .ui-resize-handle) {
    pointer-events: auto;
}
.music-editor-body:has(.lyrics-prompt-tools) .music-editor-footer :is(.lyrics-prompt-trigger, .music-chip) {
    background-color: color-mix(in srgb, var(--bg-raised) 85%, var(--text-main));
}
/* The whole AI panel stays visible while its compact slot expands or closes.
   The mode wrapper still clips when the lyrics editor itself collapses. */
/* Keep :has() on the named target. A relational ancestor followed by `> *`
   puts all descendants in the browser's shared :has invalidation set, so even
   unrelated karaoke clock text changes can restyle the entire document. */
.composer-prompt-collapsible--fill.is-open > .composer-prompt-collapsible__content:has(.lyrics-prompt-tools) { overflow: visible; }
.music-editor-footer:has(> .lyrics-prompt-tools) { row-gap: 0; }
.music-editor-footer > .lyrics-prompt-tools { padding: 0; }
.music-lyrics__area,
.music-full-lyrics__area {
    flex: 1 0 auto;
    height: auto;
    width: 100%;
    min-height: 8rem;
    resize: none;   /* вместо нативного уголка — пилюля-ручка .ui-resize-handle снизу */
    padding: var(--gap-sm) 0;
}

.music-style__area {
    width: 100%;
    flex: 1 1 auto;
    height: auto;
    min-height: 3rem;
    resize: none;   /* ресайз — пилюлей-ручкой под полем */
    padding: var(--gap-sm) 0;
    white-space: pre-wrap;
    overflow-x: hidden;
    overflow-y: auto;
}

/* Пилюля-ручка вертикального ресайза (x-resize-handle) — язык ручек панелей:
   горизонтальная полоска по центру под полем, тянуть вверх/вниз. touch-action:
   none отдаёт жест ресайзу целиком (не скроллу композера). */
.ui-resize-handle {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.25rem 0;
    cursor: ns-resize;
    touch-action: none;
}
.ui-resize-handle::before {
    content: '';
    width: 3.5rem;
    height: 0.3rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--resize-handle-color);
    transition: background-color var(--transition);
}
@media (hover: hover) { .ui-resize-handle:hover::before { background: var(--resize-handle-hover-color); } }
.ui-resize-handle.is-resizing::before { background: var(--resize-handle-active-color); }
/* Footer contents remain in normal flow, including the entire resize handle. */
.music-editor-footer .music-chips { margin-top: 0; }
/* Keep style suggestions aligned with the compact lyrics action. */
.music-editor-footer > .composer-scroll-hint-host { padding-block: 0; }
.music-editor-footer--style { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; }
.music-editor-footer--style > .ui-resize-handle,
.music-editor-footer--style > .lyrics-prompt-tools[data-open="true"] { grid-column: 1 / -1; }
.music-editor-footer--style:has(.lyrics-prompt-tools[data-open="true"]) > .composer-scroll-hint-host { display: none; }
.music-adv-field > .ui-resize-handle { margin-bottom: -0.35rem; }
/* Подсказки стиля — один ряд с горизонтальной прокруткой. Десктоп — «зажать и тянуть»
   мышью (x-drag-scroll, драг только после порога сдвига → клик по чипу не ломается),
   палец — нативная прокрутка по обеим осям, чтобы вертикальный жест уходил композеру.
   Прижат к низу секции (margin-top: auto). Скроллбар скрыт —
   вместо него у активного края маска-затухание (data-fade). Клик добавляет жанр. */
.music-chips {
    display: flex;
    flex-wrap: nowrap;
    justify-content: safe center;   /* по центру, при переполнении — от начала */
    gap: var(--gap-2xs, 0.35rem);
    margin-top: auto;   /* прижать ряд к низу секции */
    min-width: 0;       /* иначе flex-элемент растянулся бы по содержимому, а не скроллил */
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    touch-action: auto;
    cursor: grab;       /* хинт «ленту можно тянуть» (на чипах — pointer, он перебивает) */


}

.music-chips.is-grabbing { cursor: grabbing; user-select: none; }
/* Затухание края там, где ещё есть скрытые подсказки (маска по содержимому, не по фону —
   работает в любой теме). data-fade выставляет x-drag-scroll по позиции скролла. */
:is(.music-chips, .lyrics-prompt-suggestions)[data-fade="right"] {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2.25rem), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 2.25rem), transparent);
}
:is(.music-chips, .lyrics-prompt-suggestions)[data-fade="left"] {
    -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 2.25rem), transparent);
            mask-image: linear-gradient(to left, #000 calc(100% - 2.25rem), transparent);
}
:is(.music-chips, .lyrics-prompt-suggestions)[data-fade="both"] {
    -webkit-mask-image: linear-gradient(to right, transparent, #000 2.25rem, #000 calc(100% - 2.25rem), transparent);
            mask-image: linear-gradient(to right, transparent, #000 2.25rem, #000 calc(100% - 2.25rem), transparent);
}
/* Style suggestions use the standard composer control size and text token. */
.music-chip {
    flex: 0 0 auto;
    min-height: var(--composer-control-size);
    padding: 0 calc(var(--gap-sm) * 1.5);
    font-size: var(--text-control);
    white-space: nowrap;
    cursor: pointer;
}
.music-chip.is-selected {
    background: var(--surface-strong);
    color: var(--text-main);
    box-shadow: none;
}

.music-field {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    flex: 1 1 8rem;
    min-width: 0;
}
.music-field__label {
    font-size: var(--text-xs);
    color: var(--text-muted);
}
.music-field__input {
    width: 100%;
    padding: 0.4rem 0.5rem;
    resize: none;   /* ресайз — пилюлей-ручкой под полем */
}

/* «Ещё» — аккордеон со слайдерами влияния и исключаемыми стилями */
.music-section--more {
    padding: 0.35rem 0.75rem;
    gap: 0;   /* без flex-gap до шторки: gap не анимируется и схлопнулся бы дискретно
                 на display:none в конце (рывок ~6px). Отступ переехал внутрь шторки —
                 в padding .music-adv-grid, чтобы гаснуть вместе с grid-rows. */
}
.music-more-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap-sm, 0.75rem);
    width: 100%;
    padding: 0.4rem 0;
    border: none;
    background: transparent;
    cursor: pointer;
}
.music-more-toggle__chevron {
    color: var(--text-subtle);
    transition: transform var(--transition);
}
.music-more-toggle__chevron.is-open { transform: rotate(180deg); }
/* Прямой ребёнок .composer-collapsible — только клип-хост схлопывания: БЕЗ своих
   паддингов, иначе grid-template-rows:0fr не доедет до нуля (min-height:0 зануляет
   контент, но padding остаётся полом → шторка застревает на ~высоте паддинга и
   дёргается на display:none). Вертикальные отступы — внутри, на .music-adv-grid. */
.music-more-body {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

/* Слайдер на токенах: утопленный трек + контрастный бегунок (без бордеров) */
.music-range {
    appearance: none;
    -webkit-appearance: none;
    width: 100%;
    height: 1.05rem;
    margin: 0;
    background: transparent;
    cursor: pointer;
}
/* Дорожка — видимый токен (--surface-strong: белый 14% в тёмной / чёрный 10% в
   светлой), НЕ --surface-dim (чёрный 20% → невидим на чёрном --bg-app).
   Прошедшая часть — НЕЙТРАЛЬНЫЙ цвет (не accent): WebKit — градиент трека по
   --range-fill (ставится инлайн из playerProgressPct); Firefox — нативный
   ::-moz-range-progress. */
.music-range::-webkit-slider-runnable-track {
    height: 0.3rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: linear-gradient(
        to right,
        var(--text-secondary, var(--text-muted)) var(--range-fill, 0%),
        var(--surface-strong) var(--range-fill, 0%)
    );
}
.music-range::-moz-range-track {
    height: 0.3rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-strong);
}
.music-range::-moz-range-progress {
    height: 0.3rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--text-secondary, var(--text-muted));
}
.music-range::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 0.95rem;
    height: 0.95rem;
    margin-top: -0.325rem;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--text-main);
    box-shadow: var(--shadow-surface);
}
.music-range::-moz-range-thumb {
    width: 0.95rem;
    height: 0.95rem;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--text-main);
    box-shadow: var(--shadow-surface);
}
.music-range:focus-visible { outline: none; box-shadow: var(--ring-accent-soft); border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); }

/* Счётчик длины — в правом углу шапки секции, напротив заголовка */
.music-counter {
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    font-variant-numeric: tabular-nums;
    min-width: 4ch;
    text-align: right;
    flex-shrink: 0;
    white-space: nowrap;
}

/* Запись с микрофона («+» → Записать аудио) */
.music-rec-row {
    display: flex;
    flex-wrap: wrap;
    min-width: 0;
    align-items: center;
    gap: var(--gap-xs, 0.5rem);
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
}
.music-rec-dot {
    flex-shrink: 0;
    width: 0.55rem;
    height: 0.55rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--primary-500);
    animation: music-rec-pulse var(--motion-period-pulse) var(--motion-ease-ambient) infinite;
}
@keyframes music-rec-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
}
@media (prefers-reduced-motion: reduce) { .music-rec-dot { animation: none; } }
.music-rec-time {
    flex-shrink: 0;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    font-variant-numeric: tabular-nums;
}
.music-rec-wave {
    display: block;
    flex: 1 1 0;
    min-width: 0;
    width: 0;
    height: 2.75rem;
}
.music-rec-wave__canvas { display: block; width: 100%; height: 100%; }
.music-rec-hint { flex-basis: 100%; font-size: var(--text-xs); color: var(--text-muted); }
.music-rec-row .music-rec-action {
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    padding: 0;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-lg);
}

/* Карточка референс-аудио: имя + действие (кавер/продолжить/вокал/бит) */
.music-ref-card {
    display: flex;
    flex-direction: column;
    gap: var(--gap-xs, 0.5rem);
    padding: 0.6rem 0.75rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
}
.music-ref-card__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text-main);
    font-size: var(--text-sm);
}
.music-ref-card__head i.ti-music { color: var(--text-muted); }
.music-ref-card__name { flex: 1; min-width: 0; }
.music-ref-card__head button {
    flex-shrink: 0;
    display: inline-flex;
    padding: 0.2rem;
    border: none;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
}
@media (hover: hover) { .music-ref-card__head button:hover { color: var(--text-main); } }
.music-ref-card__ops {
    align-self: flex-start;
    flex-shrink: 0;
    height: var(--composer-control-size);
    max-width: 100%;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
}
.music-ref-card__ops > .music-seg__btn { flex-shrink: 0; white-space: nowrap; }
.music-ref-card__cover {
    flex-shrink: 0;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    object-fit: cover;
}

/* === Редактор волны (обрезка/точка продолжения) === */
.music-wave {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.music-wave__status {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text-muted);
    font-size: var(--text-sm);
    padding: 0.35rem 0;
}
.music-wave__canvas {
    display: block;
    width: 100%;
    height: 3.75rem;
    border-radius: var(--radius-sm, 0.5rem);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
    cursor: pointer;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
}
.music-wave__timeline {
    position: relative;
    --wave-handle-size: var(--slider-thumb-size);
}
.music-wave__handle,
.music-wave__cursor {
    position: absolute;
    pointer-events: none;
    transform: translateX(-50%);
}
.music-wave__handle {
    width: var(--wave-handle-size);
    height: var(--wave-handle-size);
    left: clamp(calc(var(--wave-handle-size) / 2), var(--wave-position), calc(100% - var(--wave-handle-size) / 2));
    top: calc(50% - var(--wave-handle-size) / 2);
    border-radius: var(--slider-radius);
    background: var(--primary-500);
    display: grid;
    place-items: center;
}
.music-wave__handle::after {
    content: '';
    width: var(--slider-dot-size);
    height: var(--slider-dot-size);
    border-radius: var(--slider-radius);
    background: var(--primary-text);
}
.music-wave__cursor {
    left: clamp(1px, var(--wave-position), calc(100% - 1px));
    inset-block: 0;
    width: 2px;
    background: var(--slider-fill);
    box-shadow: 0 0 0 1px var(--bg-panel);
}
.music-wave__position {
    margin-inline-start: auto;
    color: var(--text-main);
    font-variant-numeric: tabular-nums;
}
.music-wave__fallback {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}
.music-wave__slider { width: 100%; }
.music-wave__labels {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text-muted);
    font-size: var(--text-sm);
}
.music-wave__time b { color: var(--text-main); font-weight: var(--font-weight-semibold); }
.music-wave__span { color: var(--text-subtle); font-variant-numeric: tabular-nums; }

/* Верхние обозначения над волной (KEEP/RECREATE-стиль). overflow-hidden — страховка:
   узкий REMOVE у самого края не вылезает за контейнер (текст в нём гасится в разметке). */
.music-wave__legend { position: relative; height: 1.4rem; overflow: hidden; }
.music-wave__legend-split { display: flex; gap: 0.25rem; height: 100%; }
.wave-tag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    height: 100%;
    padding: 0 0.6rem;
    box-sizing: border-box;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
.wave-tag--keep { background: var(--primary-500); color: var(--text-main); }
.wave-tag--recreate { flex: 1 1 auto; background: var(--surface-dim); color: var(--text-muted); }
.wave-tag--range { position: absolute; top: 0; }
/* Отбрасываемые края (REMOVE) — приглушённая штриховка, как в референсе. */
.wave-tag--remove {
    position: absolute;
    top: 0;
    color: var(--text-subtle);
    background-color: var(--surface-dim);
    background-image: repeating-linear-gradient(45deg,
        transparent 0 4px,
        color-mix(in srgb, var(--text-subtle) 16%, transparent) 4px 6px);
}
.music-wave__legend-range { position: absolute; inset: 0; }
.music-wave__play {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--composer-control-size);
    height: var(--composer-control-size);
    border: none;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-strong);
    color: var(--text-main);
    cursor: pointer;
}
@media (hover: hover) { .music-wave__play:hover { background: var(--surface-hover, var(--surface-strong)); } }

/* Модалки «Голоса/персоны/визард» переведены на общий drawer-modal (.voice-modal —
   в группах :is() c settings/model/assistant): teleport, ScrollLock/ModalStack,
   backdrop + .drawer-viewport + свайп, drawer-enter/leave. Бывший бесхозный
   .music-persona-modal* удалён — структура и анимации теперь единые. */

.music-persona-empty { padding: 0.6rem 0.5rem; font-size: var(--text-xs); color: var(--text-muted); text-align: center; }

.music-active-chip {
    display: inline-flex; align-items: center; gap: 0.375rem;
    box-sizing: border-box; height: var(--composer-control-size); min-width: 0; max-width: 100%;
    flex: 0 0 auto;
    padding: 0 0.125rem 0 0.5rem; font-size: 0.8125rem; line-height: 1.25rem;
}
/* A zero-height flex break moves only the chip to a new row without stretching it. */
.music-composer-head--persona { justify-content: flex-start; row-gap: 0; }
.music-composer-head.persona-wrap::after { content: ''; order: 1; flex-basis: 100%; }
.music-composer-head.persona-wrap .music-active-chip { order: 2; margin-top: var(--gap-sm); }
.music-active-chip .assistant-chip__glyph { width: 1.25rem; height: 1.25rem; font-size: 0.9375rem; }
.music-active-chip__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.music-active-chip__name > span { display: inline-block; }
.music-active-chip button {
    background: transparent; border: none; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round);
    color: var(--text-muted); cursor: pointer; display: inline-flex;
    align-items: center; justify-content: center; flex: 0 0 1.75rem;
    width: 1.75rem; height: 1.75rem; padding: 0; font-size: 1rem;
}
.music-active-chip button:focus-visible, .music-voice-notice button:focus-visible {
    outline: 2px solid var(--text-muted); outline-offset: 2px;
}
.music-voice-notice { padding: 0.625rem 0.75rem; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); background: var(--surface-soft); }
.music-composer-head > .music-voice-notice {
    order: 3;
    flex: 0 0 100%;
    min-width: 0;
    margin-top: var(--gap-sm);
}
.music-voice-notice p { margin: 0; font-size: var(--text-xs); line-height: 1.5; color: var(--text-muted); }
.music-voice-notice__actions { display: flex; flex-wrap: wrap; gap: 0.375rem; margin-top: 0.5rem; }
.music-voice-notice button {
    min-height: 2rem; padding: 0.25rem 0.625rem; border: 0; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round);
    background: var(--surface-active); color: var(--text-main); font: inherit; font-size: var(--text-xs); cursor: pointer;
}

/* ============================================================
   Продвинутые настройки: тумблеры + сегментные слайдеры (7 стопов)
   ============================================================ */
/* Десктоп — пары в ряд (2 колонки): Голос+Режим текста, Креативность+Влияние стиля.
   Вес аудио и Негативные теги — на всю ширину. Мобайл (<768) — в столбик. */
.music-adv-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.3rem;
    align-items: stretch;   /* парные ряды одинаковой высоты */
    /* Отступы шторки — здесь, а не на клип-хосте .music-more-body (см. коммент там),
       чтобы padding гас вместе с grid-rows, а не оставался полом. top = бывший
       flex-gap секции (--gap-xs) + внутренние 0.25rem. */
    padding: calc(var(--gap-xs) + 0.25rem) 0 0.4rem;
}
.music-adv-row--wide { grid-column: 1 / -1; }
@media (max-width: 767px) {
    .music-adv-grid { grid-template-columns: 1fr; }
}

/* Каждая опция — компактный ряд-карточка (в тон Suno): подпись слева, контрол
   справа, всё в одну строку. Утопленная заливка (--surface-dim) отделяет ряды от
   плашки секции (--surface-soft); контролы внутри — светлее ряда, чтобы читались. */
.music-adv-row {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    min-height: 2.85rem;   /* единая высота всех рядов (сегментные = слайдерные) */
    padding: 0.3rem 0.65rem;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-dim);
}
.music-adv-row > .music-field__label,
.music-adv-field > .music-field__label {
    flex: 0 0 auto;
    font-size: var(--text-sm);
    color: var(--text-main);
}
/* Сегмент-тумблер (Муж/Жен, Ручной/Авто) прижат вправо; трек прозрачный на ряду —
   как у Suno видна только активная пилюля. */
.music-adv-row .music-seg {
    margin-left: auto;
    background: transparent;
}
.music-seg--compact .music-seg__btn { min-height: 1.9rem; padding: 0 0.9rem; }

/* Поле-карточка (Негативные теги) — в тон рядам: подпись + textarea */
.music-adv-field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.45rem 0.65rem 0.55rem;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-dim);
}
.music-title-field {
    gap: var(--gap-sm);
    padding: var(--gap-2xs);
    padding-inline-start: calc(var(--gap-sm) * 1.5);
}
.music-title-input {
    flex: 1;
    min-width: 0;
    padding: 0;
}
.music-title-edit {
    flex: 0 0 var(--composer-control-size);
    width: var(--composer-control-size);
    height: var(--composer-control-size);
    padding: 0;
    border-radius: max(0px, calc(var(--radius-base) - var(--gap-2xs)));
    corner-shape: var(--corner-shape-surface);
    color: var(--text-muted);
    font-size: var(--text-lg);
}

/* ============================================================
   Единый бегунок (.ui-slider) — единый стиль range по всему проекту.
   Заполненная дорожка, круглые отметки шагов и круглый бегунок. Разметку
   задаёт макрос components/_ui_slider.html — стиль правим ТУТ в одном месте. */

/* Ряд: [подпись] | линейка (растягивается) | [бейдж значения] */
/* Shared filled range: native input interaction, decorative track and step dots. */
.ui-slider-row {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    width: 100%;
}
.ui-slider-row.is-disabled { opacity: 0.5; }
.ui-slider-row > .ui-slider__label {
    flex: 0 0 auto;
    font-size: var(--text-sm);
    color: var(--text-main);
}
.ui-slider {
    flex: 1 1 auto;
    min-width: var(--slider-thumb-size);
    position: relative;
    height: var(--slider-control-size);
}
.ui-slider::before {
    content: '';
    position: absolute;
    inset-inline: 0;
    top: 50%;
    height: var(--slider-track-size);
    transform: translateY(-50%);
    border-radius: var(--slider-radius);
    background: linear-gradient(to right, var(--slider-fill) var(--pos, 0%), var(--slider-track) var(--pos, 0%));
    pointer-events: none;
}
.ui-slider__ticks {
    position: absolute;
    inset-block: 0;
    inset-inline: calc(var(--slider-thumb-size) / 2);
    pointer-events: none;
}
.ui-slider__ticks > span {
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    width: var(--slider-dot-size);
    height: var(--slider-dot-size);
    border-radius: var(--slider-radius);
    background: var(--slider-dot);
}
.ui-slider__input {
    position: relative;
    z-index: 1;
    appearance: none;
    -webkit-appearance: none;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    background: transparent;
    cursor: pointer;
    border-radius: var(--slider-radius);
}
.ui-slider__input::-webkit-slider-runnable-track { height: var(--slider-track-size); background: transparent; border: none; }
.ui-slider__input::-moz-range-track { height: var(--slider-track-size); background: transparent; border: none; }
.ui-slider__input::-moz-range-progress { background: transparent; }
.ui-slider__input::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: var(--slider-thumb-size);
    height: var(--slider-thumb-size);
    margin-top: calc((var(--slider-track-size) - var(--slider-thumb-size)) / 2);
    border-radius: var(--slider-radius);
    border: none;
    background: var(--slider-thumb);
    box-shadow: var(--shadow-surface);
    cursor: grab;
}
.ui-slider__input::-moz-range-thumb {
    width: var(--slider-thumb-size);
    height: var(--slider-thumb-size);
    border-radius: var(--slider-radius);
    border: none;
    background: var(--slider-thumb);
    box-shadow: var(--shadow-surface);
    cursor: grab;
}
.ui-slider__input:active::-webkit-slider-thumb { cursor: grabbing; }
.ui-slider__input:active::-moz-range-thumb { cursor: grabbing; }
.ui-slider__input:focus-visible { outline: var(--gap-2xs) solid var(--slider-fill); outline-offset: var(--gap-2xs); }
.ui-slider__input:disabled { cursor: not-allowed; }
.ui-slider:has(.ui-slider__input:disabled)::before { filter: saturate(0); }

/* Optional current value and reset action. */
.ui-slider__value {
    flex: 0 0 auto;
    min-width: 2.5rem;
    text-align: right;
    border: none;
    background: transparent;
    padding: 0.15rem 0.35rem;
    border-radius: var(--radius-sm, 0.4rem);
    corner-shape: var(--corner-shape-surface);
    font-size: var(--text-xs);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
button.ui-slider__value {
    cursor: pointer;
    transition: color var(--transition), background-color var(--transition);
}
button.ui-slider__value:disabled { cursor: default; }
@media (hover: hover) {
    button.ui-slider__value:not(:disabled):hover { color: var(--text-main); background: var(--surface-strong); }
}

/* ============================================================
   Галерея «Голоса и персоны»
   ============================================================ */
.voices-modal {
    position: relative;
    width: 100%;
    height: min(var(--drawer-library-h), var(--drawer-max-h));
}
@media (min-width: 640px) {
    .voices-modal { max-width: var(--modal-library-width); height: min(36rem, var(--drawer-max-h)); }
}
.voices-modal__body {
    position: relative;
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: var(--gap-sm);
    min-height: 0;
    padding: 0 var(--modal-content-pad) var(--modal-content-pad);
    overflow-y: auto;
    overscroll-behavior: contain;
}
.voices-modal__body > * { flex-shrink: 0; }
.voices-modal__body > .voices-list { flex: 1 0 auto; overflow: visible; }
.voices-modal__tabs { align-self: stretch; }
.voices-modal__tabs .music-seg__btn { flex: 1; }
.voices-modal__search {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    padding: 0 var(--gap-sm);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-dim);
    color: var(--text-muted);
}
.voices-modal__search input { flex: 1; min-width: 0; padding: var(--gap-sm) 0; background: transparent; font-size: var(--text-sm); }
.voices-modal__hint { font-size: var(--text-xs); color: var(--text-muted); }

.voices-list {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2xs);
    flex: 1;
    min-height: 0;   /* заполняет тело drawer'а и скроллится внутри, без фикс-высоты */
    overflow-y: auto;
}

/* All voice-library rows use the same pill shape in every interactive state. */
.voice-create,
.voice-item {
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    transition: background-color var(--transition);
}
.voice-create {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    padding: var(--gap-xs);
    background: transparent;
    border: none;
    color: var(--text-main);
    font-size: var(--text-sm);
    cursor: pointer;
}
@media (hover: hover) { .voice-create:hover { background: var(--bg-hover); } }
.voice-create:focus-visible,
.voice-item:has(:focus-visible) { background: var(--bg-hover); }
.voice-create__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--composer-control-size);
    height: var(--composer-control-size);
    flex: 0 0 auto;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-strong);
    color: var(--text-main);
    font-size: var(--text-lg);
}
.voice-create__icon--accent {
    background-image: var(--prism-noise), var(--gradient-primary);
    color: var(--primary-text);
}
.voice-create__label { flex: 1; text-align: left; }
.voice-badge-new,
.voice-wizard__beta {
    padding: var(--gap-2xs) var(--gap-sm);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-image: var(--prism-noise), var(--gradient-primary);
    color: var(--primary-text);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--tracking-wide);
}

.voice-item {
    display: flex;
    align-items: center;
}
.voice-item.is-active { background: var(--surface-active); }
@media (hover: hover) { .voice-item:hover { background: var(--bg-hover); } }
.voice-item__pick {
    flex: 1;
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    min-width: 0;
    padding: var(--gap-xs);
    background: transparent;
    border: none;
    color: var(--text-main);
    text-align: left;
    cursor: pointer;
    border-radius: inherit;
    corner-shape: var(--corner-shape-round);
}
/* Дот персоны как у ассистентов, но компактнее (двойной класс — каскад) */
.chat-input-assistant-dot.voice-item__dot { order: 0; width: var(--composer-control-size); height: var(--composer-control-size); }
.chat-input-assistant-dot.voice-item__dot .ti { font-size: var(--text-base); }
.voice-item__body { display: flex; flex-direction: column; min-width: 0; }
.voice-item__name { font-size: var(--text-sm); color: var(--text-main); }
.voice-item__sub { font-size: var(--text-xs); color: var(--text-muted); }
.voice-item__actions { display: flex; align-items: center; gap: var(--gap-2xs); padding-right: var(--gap-xs); }
.voice-item__act {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--composer-control-size);
    height: var(--composer-control-size);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    padding: var(--gap-xs);
    background: transparent;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
}
.voice-item__act.is-fav { color: var(--danger); }
@media (hover: hover) {
    .voice-item__act:hover { color: var(--text-main); }
    .voice-item__act.is-fav:hover { color: var(--danger); }
}
.voice-track__cover {
    width: 2.25rem;
    height: 2.25rem;
    flex: 0 0 auto;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    object-fit: cover;
}

/* ============================================================
   Визард «Создать голос»
   ============================================================ */
.voice-wizard__progress { display: flex; gap: 0.4rem; }
.voice-wizard__seg {
    flex: 1;
    height: 0.35rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-dim);
    transition: background-image var(--transition), background-color var(--transition);
}
.voice-wizard__seg.is-active { background-image: var(--prism-noise), var(--gradient-primary); }
.voice-wizard__body {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    flex: 1;
    min-height: 0;   /* тело шага заполняет drawer между прогрессом и футером */
    overflow-y: auto;
}
/* Базовый .music-field рассчитан на горизонтальные ряды (flex: 1 1 8rem). В
   вертикальных телах модалок это раздувает поля по высоте и гонит пустоту (имя-поле
   → дропзона). В .voice-modal поля держат натуральную высоту. */
.voice-modal .music-field { flex: 0 0 auto; }
.voice-wizard__body--center { align-items: center; justify-content: center; min-height: 9rem; text-align: center; }

.voice-dropzone {
    position: relative;   /* хост бегущей рамки .shell-idle-glow::before (как у композера чата) */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 1.15rem;
    border-radius: var(--radius-lg, 1rem);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-dim);
    text-align: center;
}
.voice-dropzone__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-strong);
    color: var(--text-main);
    font-size: var(--text-lg);
}
.voice-dropzone__title { font-weight: var(--font-weight-semibold); color: var(--text-main); }
.voice-dropzone__hint { font-size: var(--text-xs); color: var(--text-muted); }
.voice-dropzone__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.5rem; margin-top: 0.15rem; }
/* Серые пилюли (как surface-chip), а не прозрачный ghost — читаются в тёмной теме. */
.voice-dropzone__actions .btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    background: var(--surface-active);
    color: var(--text-main);
}

.voice-consent { display: flex; flex-direction: column; gap: 0.65rem; }
.voice-consent__row {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    font-size: var(--text-xs);
    color: var(--text-secondary, var(--text-muted));
    cursor: pointer;
}
.voice-consent__row input { margin-top: 0.15rem; flex: 0 0 auto; }

/* Подсказки — простой текст с иконкой (без плашек); на десктопе в ряд, на мобиле в столбик. */
.voice-tips { display: flex; flex-direction: column; gap: 0.35rem; }
@media (min-width: 640px) {
    .voice-tips { flex-direction: row; gap: 0.9rem; }
    .voice-tips > .voice-tip { flex: 1 1 0; min-width: 0; }
}
.voice-tip {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: var(--text-xs);
    color: var(--text-muted);
}
.voice-tip .ti { flex: 0 0 auto; color: var(--primary-500, var(--text-muted)); }

/* Язык проверочной фразы — пилюля в шапке поля имени (surface-chip + наш ctxMenu). */
.voice-name-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.voice-lang-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.6rem;
    font-size: var(--text-xs);
    color: var(--text-main);
    cursor: pointer;
}
.voice-lang-pill__chev { color: var(--text-muted); font-size: 0.85em; }
/* Мини-флаг страны языка — круглый (circle-flags), заполняет кругляшек целиком. */
.voice-flag {
    flex: 0 0 auto;
    width: 1.15rem;
    height: 1.15rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    object-fit: cover;
    display: block;
}

.voice-phrase {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.85rem;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-dim);
}
.voice-phrase--wait,
.voice-phrase--error { flex-direction: row; align-items: center; gap: 0.6rem; }
.voice-phrase--error { color: var(--danger); }
.voice-phrase__label { font-size: var(--text-xs); color: var(--text-muted); }
.voice-phrase__text {
    margin: 0;
    font-size: var(--text-base);
    font-weight: var(--font-weight-medium);
    color: var(--text-main);
    line-height: var(--leading-snug);
}
.voice-phrase__error { font-size: var(--text-xs); color: var(--danger); }

/* Язык выбирается пилюлей .voice-lang-pill через общий ctxMenu (портал на --z-popover,
   поверх drawer'а) — бывший in-flow .voice-select* удалён. */
@media (hover: hover) { .music-active-chip button:hover { color: var(--danger); } }

/* ===== Лента музыки: строки-треки (визуал = .tg-chat-row истории чатов +
   круглая обложка трека). Раскладка/фон/скругление строки — Tailwind-классы
   в _music_track_row.html (те же, что у чатов); здесь — обложка/бейджи/меню. ===== */
.music-feed-list { display: flex; flex-direction: column; gap: 0.25rem; }

.music-row__cover {
    padding: 0;
    border: 0;
    position: relative;
    flex-shrink: 0;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);   /* круглая, как иконка чата (.tg-chat-icon) */
    overflow: hidden;
    background: var(--bg-elevated);
}
.music-row__open {
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
}
.music-row__cover:focus-visible, .music-row__open:focus-visible {
    outline: 2px solid var(--text-muted);
    outline-offset: 2px;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
}
.music-row__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.music-row__img--fallback {
    display: flex; align-items: center; justify-content: center;
    color: var(--text-muted); font-size: var(--text-xl);
}
.music-row__badge-play {
    position: absolute; inset: 0; margin: auto;
    width: 1.7rem; height: 1.7rem;
    display: flex; align-items: center; justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-dim); color: var(--overlay-text); font-size: var(--text-sm);
    opacity: 0; transition: opacity var(--transition);
}
.music-row:hover .music-row__badge-play,
.music-row.is-playing .music-row__badge-play { opacity: 1; }
.music-row__cover .music-row__loading {
    position: absolute;
    inset: 0;
    padding: 0;
    border-radius: inherit;
    corner-shape: inherit;
}

.music-eq { display: inline-flex; align-items: flex-end; gap: 2px; height: 0.75rem; }
.music-eq span {
    width: 2px;
    height: 100%;
    border-radius: calc(1px * var(--radius-scale));
    background: currentColor;
    transform-origin: bottom;
    animation: music-eq-bounce var(--motion-period-pulse) var(--motion-ease-ambient) infinite;
}
.music-eq span:nth-child(2) { animation-delay: calc(var(--motion-period-pulse) * 0.125); }
.music-eq span:nth-child(3) { animation-delay: calc(var(--motion-period-pulse) * 0.25); }
@keyframes music-eq-bounce {
    0%, 100% { transform: scaleY(0.3); }
    50% { transform: scaleY(1); }
}
@media (prefers-reduced-motion: reduce) {
    .music-eq span { animation: none; transform: scaleY(0.7); }
}

/* === Хедер-плеер (_mini_player.html) ===
   Стеклянный бар (фон/блюр/тень — из общей glass-группы выше, высота/радиус как у
   .shell-user-pill), раскладка — чистый flex. Десктоп: растянут между кнопкой
   сайдбара и профилем (обложка · мета · контролы · таймлайн · громкость · … ·
   скачать · ✕). Мобайл: пилюля от лого до профиля (диск · мета · ⏮ ⏭ ✕); при
   скролле мета/extras сжимаются в ноль и бар схлопывается в кружок-диск у профиля —
   см. морф-медиазапрос. Поверхность кликабельна (панель трека / переход на /music). */
.shell-mini-player {
    --shell-player-icon-size: var(--text-base);
    display: inline-flex;
    align-items: center;
    gap: 0.1rem;
    height: var(--shell-header-slot);
    padding: var(--shell-header-inset);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    overflow: hidden;
    flex: 0 0 auto;
    cursor: pointer;
}

/* Десктоп-бар: flex-межслой абсолютной шапки (pointer-events:none у контейнера —
   возвращаем кликабельность). basis 0 (НЕ auto): бар забирает только остаток
   между кнопкой сайдбара и профилем — длинная мета (nowrap) не раздувает basis и
   не выдавливает соседей. overflow:visible — внутри абсолютный попап громкости. */
.shell-mini-player--desktop {
    flex: 1 1 0;
    min-width: 0;
    /* Fill the space left by navigation, group members and the profile pill. */
    max-width: none;
    pointer-events: auto;
    overflow: visible;
    gap: 0.35rem;
    padding-inline: var(--shell-header-inset);
    /* Контейнер для деградации по СОБСТВЕННОЙ ширине (узкий десктоп / открытая
       панель трека жмут середину шапки): без этого фикс-кнопки переполняли бы
       пилюлю и налезали на профиль. inline-size containment безопасен: ширину
       бару и так задаёт внешний flex (basis 0), не контент. */
    container-type: inline-size;
}
/* В компактном баре сохраняем место названию рядом с короткой дорожкой. */
@container (max-width: 42rem) {
    /* Повышенная специфичность перекрывает базовый flex-basis ниже. */
    .shell-mini-player.shell-mini-player--desktop .shell-mini-player__meta {
        flex-basis: 10rem;
    }
}
/* Тесно (<34rem): дорожке остаётся <6rem — перемотка вырождается, прячем таймлайн. */
@container (max-width: 34rem) {
    .shell-mini-player--desktop .shell-mini-player__opt-timeline { display: none; }
}
/* Совсем тесно (<22rem): остаётся ядро диск·мета·⏮▶⏭·✕ — громкость/«…»/скачать
   доступны в панели трека и нижних плеерах. */
@container (max-width: 22rem) {
    .shell-mini-player--desktop .shell-mini-player__opt { display: none; }
}
@container (max-width: 16rem) {
    .shell-mini-player--desktop .shell-mini-player__meta { display: none; }
}
@container (max-width: 11rem) {
    .shell-mini-player.shell-mini-player--desktop .shell-mini-player__ctrl { display: none; }
}
/* Правая группа (громкость · «…» · скачать · ✕) прижата к правому краю ЦЕЛИКОМ:
   авто-маржин на её первом элементе (громкости) — при живом таймлайне (flex:1)
   он инертен, при скрытом таймлайне свободное место остаётся МЕЖДУ транспортом
   и правой группой. Когда __opt скрыты (<22rem), роль переходит к ✕. */
.shell-mini-player--desktop .shell-mini-player__volume { margin-left: auto; }
@container (max-width: 22rem) {
    .shell-mini-player--desktop .shell-mini-player__close { margin-left: auto; }
}

/* Мобайл-бар: растянут от лого до профиля; basis 0 — лого и пилюля профиля
   получают свои ширины первыми, бар занимает ровно остаток. margin-left:auto
   прижимает к профилю, когда max-width (морф-схлопывание) меньше остатка.
   container-type — деградация по собственной ширине, как у десктоп-бара. */
.shell-mini-player--mobile {
    position: relative;
    touch-action: pan-y pinch-zoom;
    flex: 1 1 0;
    min-width: 0;
    margin-left: auto;
    container-type: inline-size;
    padding: 0;
    /* Keep the swipe clip rounded so the bubble's shadow cannot paint a square
       behind the collapsed disc. The shared player radius follows its width. */
}
.shell-mini-player__bubble {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: inherit;
    width: 100%;
    min-width: 0;
    height: 100%;
    padding: var(--shell-header-inset);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    overflow: hidden;
    flex-shrink: 0;
}
.shell-mini-player__dismiss {
    position: absolute;
    inset-block: 0;
    right: 0;
    width: min(2.6rem, 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 50%;
    corner-shape: var(--corner-shape-round);
    color: var(--text-main);
    font-size: var(--text-lg);
    opacity: 0;
    pointer-events: none;
}
.shell-mini-player--mobile[data-swipe-direction="right"] .shell-mini-player__dismiss { right: auto; left: 0; }
.app-root .shell-mini-player--mobile.is-swipe-active > .shell-mini-player__bubble {
    translate: var(--player-swipe-x, 0px) 0;
    pointer-events: none;
}
.shell-mini-player--mobile.is-swipe-active .shell-mini-player__dismiss {
    opacity: var(--player-swipe-progress, 0);
    scale: calc(.8 + var(--player-swipe-progress, 0) * .2);
}
.app-root .shell-mini-player--mobile.is-swipe-returning > * {
    transition: translate var(--transition), opacity var(--transition), scale var(--transition);
}
.shell-mini-player--mobile.is-swipe-committed { pointer-events: none; }
.shell-mini-player__dismiss:focus-visible {
    opacity: 1;
    pointer-events: auto;
    outline: 2px solid var(--text-muted);
    outline-offset: -2px;
    z-index: 2;
}
@media (prefers-reduced-motion: reduce) {
    .app-root .shell-mini-player--mobile.is-swipe-returning > * { transition: none; }
}
/* Preserve complete, equal controls rather than squeezing their glyphs. */
@container (max-width: 15rem) {
    .shell-mini-player--mobile :is(.shell-mini-player__prev, .shell-mini-player__next) { display: none; }
}
@container (max-width: 10rem) {
    .shell-mini-player.shell-mini-player--mobile .music-lyrics-button { display: none; }
}

/* Диск = обложка-кнопка play/pause (круглая, в размер аватара профиля = slot-0.5). */
.shell-mini-player__disc {
    position: relative;
    flex: 0 0 auto;
    display: inline-flex;
    width: var(--shell-header-control-size);
    height: var(--shell-header-control-size);
    padding: 0;
    border: none;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    overflow: hidden;
    background: var(--bg-elevated);
    cursor: pointer;
    -webkit-appearance: none;
            appearance: none;
}
.shell-mini-player__cover { position: absolute; inset: 0; display: block; }
.shell-mini-player__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.shell-mini-player__fallback {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: var(--text-muted); font-size: var(--text-base);
}
/* Скрим по всему диску + светлый значок поверх обложки (эквалайзер — currentColor). */
.shell-mini-player__glyph {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    background: var(--overlay-scrim);
    color: var(--overlay-text);
    font-size: var(--text-sm);
}

/* Мета: название + подзаголовок, узкие line-height — две строки в слот 2.6rem. */
.shell-mini-player__meta {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
}
.shell-mini-player--desktop .shell-mini-player__meta {
    flex: 1.4 1 15rem;
}
.shell-mini-player--mobile .shell-mini-player__meta {
    flex: 1 1 0;
}
.shell-mini-player--mobile .shell-mini-player__prev { margin-left: auto; }

/* The demo is a metadata slot, so the existing transport keeps its geometry. */
.music-demo-banner {
    position: relative;
    align-self: stretch;
    flex: 1.4 1 15rem;
    min-width: 0;
    margin-block: calc(-1 * var(--shell-header-inset));
    margin-right: 0;
    border-radius: 0;
    overflow: hidden;
    color: var(--text-main);
}
.music-demo-banner__surface {
    display: block;
    position: relative;
    width: 100%;
    height: 100%;
    min-height: var(--shell-header-slot);
    text-align: left;
    cursor: pointer;
    background: transparent;
}
.music-demo-banner__slide {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-duration-base) var(--motion-ease-premium);
}
.music-demo-banner__slide.is-current { opacity: 1; }
.music-demo-banner__art {
    position: absolute;
    inset: 0 12% 0 auto;
    width: 48%;
    height: 100%;
    object-fit: cover;
    object-position: right center;
    mask-image: linear-gradient(90deg, transparent, #000 24%, #000 80%, transparent);
    opacity: .7;
}
.music-demo-banner__copy {
    position: relative;
    display: block;
    min-width: 0;
    padding: 0 1rem 0 .35rem;
    max-width: 100%;
    font-size: var(--text-sm);
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.music-demo-banner__title {
    font-size: inherit;
    font-weight: var(--font-weight-semibold);
}
.music-demo-banner__description {
    font-size: inherit;
    font-weight: var(--font-weight-regular);
    color: var(--text-muted);
}
.music-demo-banner__navigation {
    position: absolute;
    right: .7rem;
    bottom: .15rem;
    display: flex;
    align-items: center;
}
.music-demo-banner__dot {
    width: 1rem;
    height: .7rem;
    padding: .25rem;
    background: transparent;
    cursor: pointer;
}
.music-demo-banner__dot::after {
    content: '';
    display: block;
    height: .15rem;
    background: var(--text-muted);
    border-radius: var(--radius-pill);
    opacity: .45;
}
.music-demo-banner__dot[aria-pressed="true"]::after { opacity: 1; background: var(--text-main); }
[data-theme="prism-light"] .music-demo-banner__art { opacity: .16; }
/* A demo sentence needs more reading space than the ordinary track title. */
@container (max-width: 48rem) {
    .shell-mini-player--desktop.is-demo .shell-mini-player__opt-timeline { display: none; }
}
@container (max-width: 34rem) {
    .shell-mini-player--desktop .music-demo-banner { flex: 1 1 0; }
    .shell-mini-player--desktop.is-demo .shell-mini-player__opt { display: none; }
    .music-demo-banner__copy { padding-right: 1rem; }
    .music-demo-banner__navigation { right: .3rem; }
}
@container (max-width: 16rem) {
    .music-demo-banner__copy { font-size: var(--text-xs); }
    .music-demo-banner__copy { padding-left: .6rem; }
    .music-demo-banner__dot { display: none; }
}
@media (prefers-reduced-motion: reduce) {
    .music-demo-banner__slide { transition: none; }
}

.shell-mini-player__meta [x-overflow-marquee] > span {
    display: block;
    width: max-content;
    min-width: 100%;
    /* Leave breathing room at both endpoints of the moving label. */
    padding-inline: var(--gap-sm);
}
.shell-mini-player__meta [data-marquee-overflow="true"] {
    text-overflow: clip;
}
.shell-mini-player__title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    line-height: var(--leading-tight);
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.shell-mini-player__subtitle {
    font-size: var(--text-xs);
    line-height: var(--leading-tight);
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Боковые кнопки ⏮/⏭, «…», скачать и ✕ — иконки в тон контролов шапки. */
.shell-mini-player__ctrl,
.shell-mini-player__close {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--shell-header-control-size);
    height: var(--shell-header-control-size);
    padding: 0;
    border: none;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-base);
    text-decoration: none;
    transition: color var(--transition);
}
.shell-mini-player__ctrl:disabled { opacity: 0.35; cursor: default; }
.shell-mini-player .shell-mini-player__utility {
    background-color: var(--surface-soft);
    border-radius: var(--radius-round);
    color: var(--text-main);
    transition: background-color var(--transition), color var(--transition);
}
@media (hover: hover) {
    .shell-mini-player .shell-mini-player__utility:not(:disabled):hover { background-color: var(--surface-strong); }
}
@media (hover: hover) {
    .shell-mini-player__ctrl:not(:disabled):hover,
    .shell-mini-player__close:hover { color: var(--text-main); }
}

/* Play — CTA-уровень (grain-градиент, как в прежнем нижнем баре), диаметр диска. */
.shell-mini-player__play {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--shell-header-control-size);
    height: var(--shell-header-control-size);
    padding: 0;
    border: none;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
    color: var(--primary-text);
    box-shadow: var(--shadow-icon);
    font-size: var(--text-base);
    cursor: pointer;
}
.shell-mini-player__play:disabled { opacity: 0.35; cursor: default; }
.shell-mini-player :is(.shell-mini-player__ctrl, .shell-mini-player__play, .shell-mini-player__close, .shell-mini-player__dismiss) > .ti {
    display: inline-grid;
    place-items: center;
    flex: 0 0 auto;
    width: 1em;
    height: 1em;
    font-size: var(--shell-player-icon-size);
    line-height: 1;
}

/* Таймлайн растёт вместе с названием, с ограничением ширины на больших экранах. */
.shell-mini-player__timeline {
    flex: 1 1 12rem;
    max-width: 22rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
    padding-inline: 0.35rem;
}
.shell-mini-player__time {
    flex-shrink: 0;
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    font-variant-numeric: tabular-nums;
}
.shell-mini-player__progress { flex: 1; min-width: 0; }

/* Громкость (десктоп): попап с вертикальным слайдером раскрывается ВНИЗ из шапки. */
.shell-mini-player__volume {
    position: relative;
    display: flex;
    align-items: center;
    flex: 0 0 auto;
}
.shell-mini-player__volume-pop {
    position: absolute;
    top: calc(100% + 0.5rem);
    left: 50%;
    /* translate, НЕ transform: x-transition анимирует transform (scale) и
       перебивал бы центрирование (тот же приём, что у нижнего бара). */
    translate: -50% 0;
    z-index: 40;
    padding: 0.65rem 0.45rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-elevated);
    box-shadow: var(--shadow-glass);
}

.music-row__badge {
    flex-shrink: 0; padding: 0.05rem 0.4rem; border-radius: var(--radius-sm); corner-shape: var(--corner-shape-surface);
    background: var(--surface-active); color: var(--text-secondary, var(--text-muted));
    font-size: var(--text-2xs); font-weight: var(--font-weight-semibold); text-transform: lowercase;
}
.music-row__badge--danger { background: color-mix(in srgb, var(--danger) 20%, transparent); color: var(--danger); }

/* Меню действий строки/плеера — стандартный ctxMenu-портал (см. base_app.html):
   вне app-root, иммунен к transform/filter предков (сайдбар с will-change
   ломал position:fixed — меню улетало за экран). */

/* Музыка: композер всегда прижат к низу — тот же docked-паттерн, что у
   фото/видео (hero центрируется в result-area, спец-позиционирования нет). */

/* Keep the hero mounted and in flow: fading must not feed back into dock sizing.
   Hide before the composer expands; reveal after its collapse. CSS reverses an
   interrupted transition from the current opacity, without queued JS callbacks.
   ShellMotion still owns route entry on the title/description children. */
.media-empty-state {
    opacity: 1;
    transform: translateY(0);
    visibility: visible;
    transition: opacity var(--motion-duration-list) var(--motion-ease-list) var(--motion-duration-base),
                transform var(--motion-duration-list) var(--motion-ease-list) var(--motion-duration-base),
                visibility 0s;
}
.media-empty-state.is-music-advanced {
    opacity: 0;
    transform: translateY(calc(-1 * var(--motion-distance-content)));
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--motion-duration-fast) var(--motion-ease-standard),
                transform var(--motion-duration-fast) var(--motion-ease-standard),
                visibility 0s var(--motion-duration-fast);
}
@media (prefers-reduced-motion: reduce) {
    .media-empty-state,
    .media-empty-state.is-music-advanced { transition: none; }
}

/* ===== Нижний плеер (/music) — постоянный бар, ТОЛЬКО мобайл <1100: in-flow в
   доке истории (.music-mobile-dock, см. ниже). Десктоп ≥1100 обслуживает
   хедер-плеер (.shell-mini-player--desktop) — отдельного дока и подъёма
   композера больше нет. ===== */
.music-player {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.55rem 0.75rem;
    margin-top: 0.5rem;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    background: var(--chat-input-bg);
    backdrop-filter: blur(var(--glass-blur));
    -webkit-backdrop-filter: blur(var(--glass-blur));
    box-shadow: var(--shadow-glass);
    /* Деградация по собственной ширине (как у хедер-плеера): на узких барах
       дорожке сика не остаётся полезной длины. */
    container-type: inline-size;
}
/* Второй ряд меты: обёртка нейтральна (contents) — .__metabar/.__clock ложатся
   прямыми детьми колонки .__meta. База (планшет ≥43rem): текст-часы .__clock, а сик —
   в отдельной .__timeline. Телефон (<43rem): вместо текста — компактная дорожка
   сика .__metabar (см. @container ниже). */
.music-player__nowplaying { display: contents; }
.music-player__metabar {
    display: none;
    align-items: center;
    gap: 0.4rem;
    min-width: 0;
    margin-top: 0.15rem;
}
.music-player__metabar .music-player__progress { flex: 1; min-width: 0; }
/* Узко (<43rem, телефоны): отдельный полноразмерный таймлайн прячем (мета забирает
   ширину), а под названием показываем компактную дорожку сика .__metabar вместо
   текста-часов — «полоска хронометража» прямо там, где шёл отсчёт. */
@container (max-width: 43rem) {
    .music-player .music-player__timeline { display: none; }
    .music-player .music-player__metabar { display: flex; }
    .music-player .music-player__clock { display: none; }
}
.music-player__cover {
    flex-shrink: 0;
    width: 2.5rem;
    height: 2.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);   /* круглая, в пару к обложкам ленты */
    overflow: hidden;
    background: var(--bg-elevated);
    color: var(--text-muted);
}
.music-player__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.music-player__meta {
    display: flex;
    flex-direction: column;
    min-width: 0;
    width: 9rem;
    flex-shrink: 0;
}
.music-player__title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.music-player__subtitle {
    font-size: var(--text-xs);
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Хронометраж во второй строке (вместо промпта): моноширинные цифры — секунды
   тикают без дёрганья ширины. */
.music-player__clock { font-variant-numeric: tabular-nums; }
.music-player__controls { display: flex; align-items: center; gap: 0.15rem; flex-shrink: 0; }
.music-player__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-base);
    cursor: pointer;
    transition: color var(--transition), background-color var(--transition);
}
.music-player__btn:disabled { opacity: 0.35; cursor: default; }
@media (hover: hover) {
    .music-player__btn:not(:disabled):hover { color: var(--text-main); background: var(--surface-soft); }
}
/* Play — CTA-уровень: grain-градиент (как .icon-circle-primary) */
.music-player__btn--play {
    width: 2.5rem;
    height: 2.5rem;
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
    color: var(--primary-text);
    box-shadow: var(--shadow-icon);
    font-size: var(--text-lg);
}
.music-player__timeline {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}
.music-player__time {
    flex-shrink: 0;
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    font-variant-numeric: tabular-nums;
}
.music-player__progress { flex: 1; min-width: 0; }
/* Вертикальный слайдер громкости — живёт в попапе хедер-плеера
   (.shell-mini-player__volume-pop); у мобильного нижнего бара громкости нет. */
.music-range--vertical {
    writing-mode: vertical-lr;
    direction: rtl;
    width: 1.05rem;
    height: 6.5rem;
}
.music-range--vertical::-webkit-slider-runnable-track {
    width: 0.3rem;
    height: 100%;
}
.music-range--vertical::-webkit-slider-thumb {
    margin-top: 0;
    margin-left: -0.325rem;
}
.music-range--vertical::-moz-range-track {
    width: 0.3rem;
    height: 100%;
}

@media (max-width: 767px) {
    /* Одна строка как на desktop (урезанная): обложка · мета · контролы · таймлайн.
       Прежде таймлайн переносился на второй ряд (flex-wrap + flex-basis:100%). */
    .music-player { gap: 0.5rem; padding: 0.5rem 0.6rem; }
    .music-player__meta { flex: 1 1 4rem; width: auto; min-width: 0; }
    .music-player__timeline { flex: 2 1 0; min-width: 0; }
}
@media (max-width: 1099.98px) {
    /* Обложка/мета мини-бара — тап-зона разворота фуллскрин-плеера */
    .music-player__cover,
    .music-player__meta { cursor: pointer; }
}

/* ===== Аудио-карточка-плеер (_audio_player_card.html, компонент audioCard) —
   самодостаточный плеер в ленте чата и треде транскрипции. Композирует примитивы
   .music-range / .music-eq / .music-row__badge; вид правится здесь. ===== */
.audio-card {
    --audio-card-cover-size: 2.75rem;
    --audio-card-padding-block: 0.5rem;
    --audio-card-control-size: var(--artifact-control-size);
    --generation-radius: var(--radius-xl);
    --generation-background: var(--bg-hover);
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: min(24rem, 100%);
    min-height: calc(max(var(--audio-card-cover-size), var(--audio-card-control-size) + 2 * var(--chat-control-inset)) + 2 * var(--audio-card-padding-block));
    padding: var(--audio-card-padding-block) 0.65rem;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-hover);
}
.audio-card__cover {
    position: relative;
    flex-shrink: 0;
    width: var(--audio-card-cover-size);
    height: var(--audio-card-cover-size);
    border: none;
    padding: 0;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    overflow: hidden;
    background: var(--bg-elevated);
    color: var(--overlay-text);
    cursor: pointer;
}
.audio-card__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.audio-card__badge-play {
    position: absolute; inset: 0; margin: auto;
    width: 1.7rem; height: 1.7rem;
    display: flex; align-items: center; justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-dim);
    color: var(--overlay-text);
    font-size: var(--text-sm);
}
.audio-card__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.audio-card__meta { display: flex; align-items: center; gap: 0.4rem; min-width: 0; }
.audio-card__title {
    min-width: 0;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    color: var(--text-main);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.audio-card__stamp { flex-shrink: 0; font-size: var(--text-2xs); color: var(--text-subtle); }
.audio-card__subtitle {
    font-size: var(--text-xs);
    color: var(--text-muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.audio-card__timeline { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.audio-card__t {
    flex-shrink: 0;
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    font-variant-numeric: tabular-nums;
}
.audio-card__progress { flex: 1; min-width: 0; }
.audio-card__action {
    flex-shrink: 0;
    width: 2rem; height: 2rem;
    display: inline-flex; align-items: center; justify-content: center;
    border: none; padding: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    transition: color var(--transition), background-color var(--transition);
}
@media (hover: hover) {
    .audio-card__action:hover { color: var(--text-main); background: var(--surface-soft); }
    .audio-card__cover:hover .audio-card__badge-play { background: var(--surface-strong); }
}

/* ===== Кастомный видео-плеер (_video_player.html, компонент videoPlayer) —
   контролы поверх <video> без нативного chrome. Лента чата + транскрипция.
   Композирует .music-range / .music-range--vertical. ===== */
.video-player {
    position: relative;
    display: inline-block;
    max-width: min(28rem, 100%);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    background: #000;   /* подложка видео — как у нативного плеера */
    line-height: 0;
}
.video-player__media {
    display: block;
    width: 100%;
    height: auto;
    max-height: 70vh;
    cursor: pointer;
}
.video-player__big-play {
    position: absolute; inset: 0; margin: auto;
    width: 3.5rem; height: 3.5rem;
    display: flex; align-items: center; justify-content: center;
    border: none; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round);
    background: var(--overlay-scrim);
    color: var(--overlay-text);
    font-size: var(--text-2xl); cursor: pointer;
    -webkit-backdrop-filter: blur(var(--progressive-blur-2)); backdrop-filter: blur(var(--progressive-blur-2));
    transition: background-color var(--transition);
}
@media (hover: hover) {
    .video-player__big-play:hover { background: color-mix(in srgb, var(--overlay-scrim) 130%, #000); }
}
.video-player__bar {
    position: absolute; left: 0; right: 0; bottom: 0;
    display: flex; align-items: center; gap: 0.35rem;
    padding: 0.45rem 0.55rem;
    line-height: normal;
    background: linear-gradient(to top, var(--overlay-scrim), transparent);
    opacity: 0; transition: opacity var(--transition);
}
.video-player:not(.is-playing) .video-player__bar { opacity: 1; }
@media (hover: hover) {
    .video-player:hover .video-player__bar { opacity: 1; }
}
.video-player__btn {
    flex-shrink: 0;
    width: 2rem; height: 2rem;
    display: inline-flex; align-items: center; justify-content: center;
    border: none; padding: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--overlay-text);
    font-size: var(--text-base); cursor: pointer;
    transition: background-color var(--transition);
}
@media (hover: hover) {
    .video-player__btn:hover { background: color-mix(in srgb, var(--overlay-text) 22%, transparent); }
}
.video-player__t {
    flex-shrink: 0;
    font-size: var(--text-2xs);
    color: var(--overlay-text);
    font-variant-numeric: tabular-nums;
}
.video-player__progress { flex: 1; min-width: 0; }
.video-player__volume { display: flex; align-items: center; flex-shrink: 0; }
.video-player__volume-pop {
    position: absolute;
    bottom: calc(100% + 0.5rem);
    left: 50%;
    translate: -50% 0;
    z-index: 5;
    padding: 0.65rem 0.45rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-elevated);
    box-shadow: var(--shadow-glass);
}
@media (max-width: 767px) {
    .video-player__volume { display: none; }   /* громкость на мобиле — системная */
}

/* ===== Панель информации о треке (десктоп ≥1100), _music_track_panel.html —
   встроенная колонка ВНУТРИ единого media-шелла (делит стеклянную подложку с
   историей, без своей карты/тени). Ширина ведётся из JS (musicPanelDisplayWidth:
   заполняет остаток до maxWidth сайдбара, история ужимается при нехватке; закрыта
   → 0), анимируется транзишеном. overflow скрывает контент при коллапсе; __scroll
   не уже минимума (min-width) — клипается, не рефлоу-ится в кашу. is-open — тонкий
   левый разделитель внутри общей подложки. ===== */
.music-info-panel {
    flex: none;
    overflow: hidden;
    transition: width var(--motion-duration-base) var(--motion-ease-premium);
}
.music-info-panel.is-open {
    box-shadow: none;
}
.music-info-panel.is-resizing {
    transition: none;   /* drag истории меняет панель инверсно — следуем мгновенно */
}
.music-info-panel__scroll {
    width: 100%;
    min-width: var(--music-info-panel-min-width);
    padding: 0.875rem 0.875rem 1.25rem;
}
/* The scene owns paint order; ambience stays behind artwork and text. Only
   the bounded cover copy is blurred, with no animation of its filter. */
.music-cover-scene { isolation: isolate; }
.music-cover-glow {
    position: absolute;
    top: 50%; left: 50%;
    z-index: -1;
    width: var(--music-cover-size, 100%);
    max-width: var(--music-cover-max-size);
    aspect-ratio: 1;
    container-type: inline-size;
    transform: translate(-50%, -50%);
    opacity: var(--music-cover-ambience-opacity);
    pointer-events: none;
    user-select: none;
}
.music-cover-glow::before {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--music-cover-image) center / cover no-repeat;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    filter: blur(var(--music-cover-ambience-blur));
    /* A continuous falloff avoids the opaque plateau/ring of a 70% hard stop.
       The cover-sized raster is blurred once, then spread below the artwork;
       the enclosing surface clips its extent, with artwork/text above it. */
    transform: translateY(var(--music-cover-ambience-offset-block))
        scale(var(--music-cover-ambience-spread-inline), var(--music-cover-ambience-spread-block));
    -webkit-mask-image: var(--music-cover-ambience-falloff);
    mask-image: var(--music-cover-ambience-falloff);
}
[data-theme="prism-light"] { --music-cover-ambience-opacity: .3; }
.music-info-panel__coverwrap { position: relative; }
.music-info-panel__cover {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--radius-2xl);
    corner-shape: var(--corner-shape-surface);
}
.music-info-panel__cover--fallback {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-elevated);
    color: var(--text-muted);
    font-size: var(--text-4xl);
}
.music-info-panel__close {
    position: absolute;
    top: 0.625rem;
    right: 0.625rem;
    width: 2.25rem;
    height: 2.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--overlay-backdrop-soft);
    color: var(--overlay-text);
    font-size: var(--text-base);
    cursor: pointer;
    transition: background-color var(--transition);
}
@media (hover: hover) {
    .music-info-panel__close:hover { background: var(--overlay-backdrop); }
}
/* Плеер в панели — зеркало первого экрана мобильного фуллскрина
   (общие классы music-player-full__*), компактные размеры под колонку ~20rem. */
.music-info-panel__subtitle { margin-top: 0.25rem; }
.music-info-panel .music-player-full__timeline { margin-top: 0.875rem; }
.music-info-panel .music-player-full__controls { gap: 0.5rem; margin-top: 0.625rem; }
.music-info-panel .music-player-full__ctrl {
    width: 2.5rem;
    height: 2.5rem;
    font-size: var(--text-xl);
}
.music-info-panel .music-player-full__ctrl--mode {
    width: 2.25rem;
    height: 2.25rem;
    font-size: var(--text-base);
}
.music-info-panel .music-player-full__ctrl--play {
    width: 3.25rem;
    height: 3.25rem;
    font-size: var(--text-2xl);
}
/* Служебный ряд под контролами: версия/дата слева, скачать/«…» справа. */
.music-info-panel__iconbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-base);
    cursor: pointer;
    text-decoration: none;
    transition: color var(--transition), background-color var(--transition);
}
.music-info-panel__iconbtn--first { margin-left: auto; }
@media (hover: hover) {
    .music-info-panel__iconbtn:hover { background: var(--surface-soft); color: var(--text-main); }
}
.music-info-panel__title {
    margin-top: 0.875rem;
    font-size: var(--text-xl);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    line-height: var(--leading-tight);
}
.music-info-panel__meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.375rem;
    font-size: var(--text-xs);
    color: var(--text-subtle);
}
.music-info-panel__remix {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    width: 100%;
    height: 2.75rem;
    margin-top: 0.875rem;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-main);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
    transition: background-color var(--transition);
}
@media (hover: hover) {
    .music-info-panel__remix:hover { background: var(--surface-strong); }
}

/* ===== Карточки информации о треке (_music_track_info.html) — общие для
   десктоп-панели и развёрнутого мобильного плеера. Без бордюров:
   отделение заливкой (--surface-dim). ===== */
.music-info-cards {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    margin-top: 0.875rem;
}
/* Карточка: --surface-soft (белый 6% в тёмной / чёрный 4% в светлой) — видима на
   обеих темах; НЕ --surface-dim (чёрный 20% → невидим на чёрном --bg-app). Вложенные
   интерактивные элементы поднимаются на --surface-strong, чтобы читаться на карточке. */
.music-info-card {
    display: flex;
    flex-direction: column;
    gap: var(--gap-sm);
    min-width: 0;
    padding: 0.875rem;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
}
.music-info-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
}
.music-info-card__icon-btn {
    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-base);
    cursor: pointer;
    transition: color var(--transition), background-color var(--transition);
}
@media (hover: hover) {
    .music-info-card__icon-btn:hover { color: var(--text-main); background: var(--surface-strong); }
}
.music-info-card__text {
    margin-top: 0.5rem;
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--text-secondary, var(--text-muted));
    overflow-wrap: anywhere;
}
.music-info-card > .music-info-card__text { margin: 0; }
.music-info-card__head > span { min-width: 0; overflow-wrap: anywhere; }
.music-info-card__text--lyrics { white-space: pre-wrap; }
.music-info-card__reuse {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 2.75rem;
    padding: var(--gap-sm) calc(var(--gap-sm) * 1.5);
    margin-top: auto;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-strong);
    color: var(--text-main);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    text-align: center;
    overflow-wrap: anywhere;
    cursor: pointer;
    transition: filter var(--transition);
}
@media (hover: hover) {
    .music-info-card__reuse:hover { filter: brightness(1.12); }
}
.music-info-card__chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap-xs);
    min-width: 0;
}
.music-info-chip {
    min-width: 0;
    max-width: 100%;
    overflow-wrap: anywhere;
    padding: 0.25rem 0.625rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-strong);
    color: var(--text-secondary, var(--text-muted));
    font-size: var(--text-xs);
}
.music-info-ref {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    width: 100%;
    min-width: 0;
    margin-top: auto;
}
.music-info-ref--playable {
    padding: 0.5rem;
    border: none;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-strong);
    text-align: left;
    cursor: pointer;
    transition: filter var(--transition);
}
@media (hover: hover) {
    .music-info-ref--playable:not(:disabled):hover { filter: brightness(1.12); }
}
.music-info-ref--playable:disabled { cursor: default; }
.music-info-ref__cover {
    flex-shrink: 0;
    width: 2.5rem;
    height: 2.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    overflow: hidden;
    background: var(--bg-elevated);
    color: var(--text-muted);
}
.music-info-ref__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.music-info-ref__meta { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.music-info-ref__title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.music-info-ref__subtitle {
    font-size: var(--text-xs);
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.music-info-ref__play { flex-shrink: 0; color: var(--text-muted); font-size: var(--text-sm); }
.music-info-created {
    padding: 0.25rem 0.25rem 0;
    font-size: var(--text-xs);
    color: var(--text-subtle);
}

/* ===== Музыка, мобайл <1100 — паттерн чатов: фуллскрин-история + нижний док
   (футер «Новый трек»/поиск/корзина + мини-плеер), композер — отдельный
   экран поверх (generate.html). ===== */
@media (max-width: 1099.98px) {
    /* Лента уезжает под плавающую мобильную шапку (как чаты/главная) */
    .music-mobile-shell .sidebar-history-fade {
        padding-top: var(--shell-mobile-header-offset);
        /* Fade layers belong behind controls, never on their scroll ancestor. */
        -webkit-mask-image: none;
        mask-image: none;
    }

    /* === СЛАЙД список↔композер — МЕХАНИКА ЧАТОВ 1:1 ===
       Список — статичный ПРОЗРАЧНЫЙ нижний слой (фон рисует body, как у списка
       чатов), при открытом композере прячется visibility (как
       .tg-sidebar-mobile-hidden). Экран композера (hero + док) слайдится ПОВЕРХ
       справа, как окно чата (.tg-content-hidden). Hero всегда flex — перебивает
       генерик display:none (.is-mobile-feed/-history): display рвал бы transition
       слайда; на невидимость в режиме списка работает transform. Перекрытие в
       момент слайда «назад» маскирует каскад строк (стартуют с opacity:0). */
    .app-root[data-page-category='music'] .media-page .generation-result-area {
        display: flex;
        z-index: 15;   /* над списком (10), под доком (20) */
    }
    .app-root[data-page-category='music'] .music-mobile-shell {
        position: absolute;
        inset: 0;
        z-index: 10;
    }
    .app-root[data-page-category='music'] .media-page.is-music-composer-open .music-mobile-shell {
        visibility: hidden;
        pointer-events: none;
    }
    /* Закрытый композер — экран уведён вправо за кадр (аналог .tg-content-hidden). */
    .app-root[data-page-category='music'] .media-page:not(.is-music-composer-open) .generation-result-area,
    .app-root[data-page-category='music'] .media-page:not(.is-music-composer-open) .chat-input-docked {
        transform: translateX(100%);
        pointer-events: none;
    }
    /* Транзишен слайда — за гейтом первого кадра (.music-nav-ready, ставит JS
       двойным rAF); до взвода глушим и .motion дока (он транзишенит transform),
       иначе первая отрисовка «проезжала» бы. Гейт снимается и на смене категории
       (mediaApp.switchCategory): .media-page переживает soft-switch, и живой
       транзишен увозил бы док вбок при входе в музыку.
       will-change здесь НЕ ставим: transform-транзишен и так уходит на композитор,
       а постоянный will-change держал бы два больших слоя (в т.ч. предка стеклянной
       пилюли с backdrop-filter) промотированными всё время жизни страницы. */
    .app-root[data-page-category='music'] .media-page:not(.music-nav-ready) .chat-input-docked {
        transition: none;
    }
    /* Only the pane slides. Its reserve follows the composer's measured height
       directly; a second padding animation would lag behind that geometry. */
    .app-root[data-page-category='music'] .media-page.music-nav-ready .generation-result-area {
        transition: transform var(--motion-duration-base) var(--motion-ease-premium);
    }
    .app-root[data-page-category='music'] .media-page.music-nav-ready .chat-input-docked {
        transition: transform var(--motion-duration-base) var(--motion-ease-premium);
    }

    /* Экран композера музыки: док — стандартный absolute-оверлей снизу (generic
       .media-page.is-mobile-history ниже), hero центрируется в result-area над
       резервом --input-height — как у остальных медиа-страниц. In-flow вариант
       (position:relative) убран: при капе высоты пилюли лист с обвязкой (тумблер
       + отступы) превышал страницу, и flex выталкивал низ композера за экран. */

    /* Нижний док: футер (центрированная пилюля) + мини-плеер. Плавающий: равные
       минимальные отступы по бокам и снизу + safe-area (как композеры). */
    .music-mobile-dock {
        --surface-fade-top-tint-color: var(--bg-app);
        position: sticky;
        bottom: 0;
        z-index: 20;
        flex-shrink: 0;
        pointer-events: none;
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
        padding: 0.25rem var(--composer-edge-gap) calc(var(--composer-edge-gap) + var(--composer-sab));
    }
    .music-mobile-dock > :not(.surface-edge-fade) { position: relative; pointer-events: auto; }
    .music-mobile-dock > .surface-edge-fade { top: calc(-4 * var(--gap-sm)); }
    /* Мини-плеер = плавающая пилюля (как композеры на мобиле): скругление со всех
       сторон + тень; safe-area ушла на внешний нижний отступ дока
       (.music-mobile-dock), поэтому внутренний padding-bottom вернулся к базовому. */
    .music-mobile-dock .music-player {
        margin-top: 0;
        border-radius: var(--radius-xl);
        corner-shape: var(--corner-shape-surface);
        box-shadow: var(--shadow-glass);
    }
    /* Мини-плеер = урезанная версия desktop: «···» и «Скачать» скрыты (эти действия
       есть в карточке трека). Скоуп .music-mobile-dock (док рендерится <1100) ловит
       и портрет, и ландшафт телефона; громкость уже скрыта <1100 выше. */
    .music-mobile-dock .music-player__more,
    .music-mobile-dock .music-player__download {
        display: none;
    }

    /* Футер-бар: как у чатов на мобиле, но на всём диапазоне <1100
       (chat-правила заперты в @media ≤767.98). Специфичность 0,2,0 —
       перебивает базовые display:none у .tg-footer-search/.tg-footer-trash. */
    .music-footer-bar { width: fit-content; max-width: 100%; margin-inline: auto; }
    .music-footer-bar .tg-footer-search,
    .music-footer-bar .tg-footer-trash { display: flex; }
    .music-footer-bar .tg-footer-new-chat {
        flex: 0 0 auto;
        width: 7.8125rem; /* «+ Новый трек» — фикс-ширина для плавного схлопа до «+» */
        gap: 0.5rem;
        padding-inline: 0.875rem;
        overflow: hidden;
        white-space: nowrap;
        transition: width var(--motion-duration-shell) var(--motion-ease-premium),
                    padding-inline var(--motion-duration-shell) var(--motion-ease-premium),
                    gap var(--motion-duration-shell) var(--motion-ease-premium);
    }
    .music-footer-bar .tg-footer-new-chat.is-compact {
        width: 2.75rem;
        padding-inline: 0;
        gap: 0;
    }

}

/* ===== Полноэкранный плеер (мобайл <1100, _music_player_expanded.html) —
   механика Suno: слайд снизу, первый экран — плеер, скролл вниз — детали
   генерации. Живёт постоянно (x-show нет): is-open анимирует в обе стороны. ===== */
.music-player-full {
    --music-player-header-inset: 0.625rem;
    --music-player-header-fade: 1.25rem;
    position: fixed;
    inset: 0;
    z-index: var(--z-fullscreen-modal);
    background: var(--bg-app);
    color: var(--text-main);
    transform: translateY(100%);
    visibility: hidden;
    transition: transform var(--motion-duration-slow) var(--motion-ease-premium),
                visibility 0s linear var(--motion-duration-slow);
}
.music-player-full.is-open {
    transform: none;
    visibility: visible;
    transition: transform var(--motion-duration-slow) var(--motion-ease-premium);
}
.music-player-full__scroll {
    position: relative;
    z-index: 0;
    height: 100%;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.music-player-full__stage {
    min-height: 100%;
    /* Keep the scaled cover glow out of the parent's horizontal scroll area. */
    overflow-x: clip;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Reserve the floating header's logo, insets and the device safe area. */
    padding: calc(var(--brand-logo-size) + 2 * var(--music-player-header-inset) + env(safe-area-inset-top)) 1.25rem 0.875rem;
}
/* Keep nested card controls below one header surface, including during scroll. */
.music-player-full__header {
    position: absolute;
    inset: 0 0 auto;
    z-index: 1;
    isolation: isolate;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap-sm);
    padding: calc(var(--music-player-header-inset) + env(safe-area-inset-top)) 1rem var(--music-player-header-inset);
    pointer-events: none;
}
.music-player-full__header::before {
    content: '';
    position: absolute;
    inset: 0;
    bottom: calc(-1 * var(--music-player-header-fade));
    z-index: -1;
    background: linear-gradient(to bottom, var(--bg-app) calc(100% - var(--music-player-header-fade)), transparent);
    pointer-events: none;
}
.music-player-full__logo {
    flex-shrink: 0;
    width: var(--brand-logo-size);
    height: var(--brand-logo-size);
    color: var(--text-main);
    pointer-events: none;
}
.music-player-full__logo > .brand-mobile {
    width: 100%;
    height: 100%;
}
@media (min-width: 768px) {
    .music-player-full__logo {
        display: flex;
        align-items: center;
        width: auto;
    }
}
/* The controls remain interactive above the header's decorative fade. */
.music-player-full__topbar {
    display: flex;
    flex-shrink: 0;
    align-items: center;
    gap: 0.5rem;
    pointer-events: auto;
}
.music-player-full__iconbtn {
    width: 40px;
    height: 40px;
    border: none;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-elevated);
    color: var(--text-main);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--text-xl);
    cursor: pointer;
    transition: background var(--transition-fast), transform var(--transition-fast);
}
.music-player-full__iconbtn:hover  { background: var(--bg-raised); transform: scale(1.05); }
.music-player-full__iconbtn:active { transform: scale(0.96); }
.music-player-full__coverwrap {
    --music-cover-size: min(78vw, var(--music-cover-max-size));
    position: relative;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem 0;
    min-height: 0;
}
.music-player-full__cover {
    width: var(--music-cover-size);
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--radius-2xl);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-glass);
}
.music-player-full__cover--fallback {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-elevated);
    color: var(--text-muted);
    font-size: var(--text-6xl);
}
.music-player-full__meta {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.music-player-full__title {
    font-size: var(--text-xl);
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-tight);
}
.music-info-panel__title, .music-player-full__title {
    display: block;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.music-player-full__subtitle {
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    /* Reserve the metadata slot so the transport stays still between songs. */
    min-height: calc(var(--text-sm) * var(--leading-normal) * var(--music-player-subtitle-lines));
    color: var(--text-muted);
    display: -webkit-box;
    -webkit-line-clamp: var(--music-player-subtitle-lines);
    line-clamp: var(--music-player-subtitle-lines);
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.music-player-full__timeline { width: 100%; margin-top: 1rem; }
.music-player-full__progress { width: 100%; }
.music-player-full__times {
    display: flex;
    justify-content: space-between;
    margin-top: 0.25rem;
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    font-variant-numeric: tabular-nums;
}
.music-player-full__controls {
    max-width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.25rem;   /* пять кнопок (shuffle · prev · play · next · repeat) */
    margin-top: 0.875rem;
}
.music-player-full__ctrl {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--text-main);
    font-size: var(--text-2xl);
    cursor: pointer;
    transition: color var(--transition);
}
.music-player-full__ctrl:disabled { opacity: 0.35; }
/* Shuffle / repeat — компактнее и приглушённее основных транспортных кнопок;
   активный режим подсвечивается accent-токеном (--primary-500). */
.music-player-full__ctrl--mode {
    width: 2.5rem;
    height: 2.5rem;
    color: var(--text-subtle);
    font-size: var(--text-xl);
    transition: color var(--transition), background-color var(--transition);
}
/* Активный режим — акцент + мягкая акцентная подложка: один цвет (бледная
   сирень --primary-500) на тёмном фоне сливался с белыми соседями, и тоггл
   выглядел «не работающим». */
.music-player-full__ctrl--mode.is-active {
    color: var(--primary-500);
    background: color-mix(in srgb, var(--primary-500) 16%, transparent);
}
/* Play — CTA-уровень: grain-градиент (как .music-player__btn--play) */
.music-player-full__ctrl--play {
    width: 4.25rem;
    height: 4.25rem;
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
    color: var(--primary-text);
    box-shadow: var(--shadow-icon);
    font-size: var(--text-3xl);
}
.music-player-full__more {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.125rem;
    margin-top: 1.25rem;
    color: var(--text-subtle);
    font-size: var(--text-xs);
}
.music-player-full__details {
    max-width: 40rem;
    margin: 0 auto;
    padding: 0 1rem calc(1.5rem + var(--safe-area-bottom, 0px));
}


.icon-circle-primary {
    background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal;
    color: var(--primary-text);
    box-shadow: var(--shadow-icon);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
}
.icon-chip-primary {
    background-color: var(--surface-soft);
    color: var(--text-muted);
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.overlay-backdrop,
.payment-backdrop { background-color: var(--modal-backdrop); }
.overlay-backdrop-soft { background-color: var(--modal-backdrop-soft); }

/* Bottom Drawer (Шторка) */
/* Gesture cancellation returns the dragged panel and scrim to rest. The shared
   enter/leave classes below select the timing while Alpine changes visibility. */
[x-drawer-swipe] {
    transition: transform var(--motion-duration-drawer) var(--motion-ease-premium);
}

/* The home slot has its final geometry before the library arrives. Do not show
   an empty-track layout for a frame before replacing it with the demo banner. */
.shell-mini-player.is-library-loading { pointer-events: none; }
.shell-mini-player.is-library-loading > * { visibility: hidden; }
/* The dialog itself receives programmatic focus without an input-style ring.
   Keyboard focus remains visible on every interactive control inside it. */
[x-drawer-swipe][tabindex="-1"]:focus { outline: none; }
.overlay-backdrop, .payment-backdrop {
    transition: opacity var(--motion-duration-drawer) var(--motion-ease-premium);
}
.drawer-viewport {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    pointer-events: none;
}
@media (min-width: 640px) {
    .drawer-viewport {
        align-items: center;
        padding: var(--app-gutter-x);
    }
    :root { --drawer-max-h: min(calc(var(--app-viewport-height, 100dvh) * 0.88), calc(var(--app-viewport-height, 100dvh) - 2 * var(--app-gutter-x))); }
}

/* Drawer panels — max-height tied to a single token */
:is(.settings-panel, .model-modal, .payment-modal, .assistant-modal, .prompt-library-panel, .voice-modal) {
    max-height: var(--drawer-max-h);
}
@media (min-width: 640px) {
    .model-modal { max-height: min(75vh, 680px); }
    /* Каталог ассистентов/пресетов — ФИКСИРОВАННЫЙ габарит: высоту панели задаёт
       сайдбар категорий, а теги/карточки догружаются ПОСЛЕ открытия — auto-высота
       прыгала «отскоком» вокруг центра (и на каждой смене категории). */
    .prompt-library-panel { height: min(680px, var(--drawer-max-h)); }
}
.drawer-handle {
    position: relative;
    width: 40px;
    height: 4px;
    background: var(--bg-raised);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    flex-shrink: 0;
    margin: 12px auto 0;
    cursor: grab;
}
.drawer-handle::before {
    content: '';
    position: absolute;
    inset: -10px -20px;
}
@media (min-width: 640px) {
    .drawer-handle { display: none; }
}

/* Swipe-to-dismiss: Only the drag handle should prevent vertical scroll by default.
   The rest of the drawer needs native vertical scrolling. */
@media (max-width: 639px) {
    .drawer-handle { touch-action: none; }
}

/* The panel reserves the safe area once; normal-flow content/footers only
   add their ordinary spacing. The model selector's absolute tray owns its
   own edge, as does the composer's attachment sheet. */
@media (max-width: 639px) {
    :is(.settings-panel, .payment-modal, .assistant-modal, .prompt-library-panel, .voice-modal),
    .profile-settings-card {
        padding-bottom: var(--safe-area-bottom, 0px);
    }
}

/* ══════════════════════════════════════════════
   COMPOSER PLUS SHEET — шторка кнопки «+»
   Mobile: full-width bottom-sheet (как .settings-panel).
   Desktop: floating panel рядом с триггером (inline-стиль из стора).
   ══════════════════════════════════════════════ */
.composer-plus-sheet-viewport {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    pointer-events: none;
}
@media (min-width: 640px) {
    .composer-plus-sheet-viewport {
        display: block;
    }
}

.composer-plus-sheet {
    --sheet-radius: var(--radius-xl);
    --sheet-pad: var(--gap-sm);
    --sheet-bottom-pad: max(var(--sheet-pad), var(--safe-area-bottom, 0px));
    position: relative;
    isolation: isolate;
    width: 100%;
    min-width: 0;
    min-height: 0;
    max-height: var(--drawer-max-h, 90vh);
    display: flex;
    flex-direction: column;
    background: var(--chat-input-solid);
    border-radius: var(--sheet-radius) var(--sheet-radius) 0 0;
    box-shadow: var(--shadow-glass);
    /* Верх 0: на мобиле трей отступает от верхней кромки своим margin-top
       (= --sheet-pad), чтобы offset от угла панели был равномерным. */
    padding: 0 var(--sheet-pad) var(--sheet-bottom-pad);
    /* This surface clips the inner views but is never a scroll container.
       Focusing a clipped tab must scroll its tab strip, not the whole sheet. */
    overflow: clip;
}



@media (min-width: 640px) {
    .composer-plus-sheet {
        --sheet-bottom-pad: var(--sheet-pad);
        width: 20rem;
        max-width: calc(100vw - 24px);
        max-height: min(var(--drawer-max-h), var(--floating-max-height, 100dvh), 32rem);
        border-radius: var(--sheet-radius);
        padding: var(--sheet-pad);
        /* Скролл живёт на __list внутри __stage — panel сам ничего
           не прокручивает, иначе появятся вложенные скроллы. */
    }
}

.composer-plus-sheet__content {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.composer-plus-sheet__slide:not(.is-menu) > .composer-plus-sheet__content { overflow: hidden; }
.composer-plus-sheet__header {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    gap: var(--gap-xs);
    padding: var(--gap-xs) var(--gap-xs) 0;
}
.composer-plus-sheet__title {
    flex: 1;
    min-width: 0;
    margin: 0;
    font-size: var(--text-base);
    font-weight: var(--font-weight-semibold);
}

.composer-plus-sheet__tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, calc(5 * var(--text-xs) + 2 * var(--gap-2xs))), 1fr));
    align-items: stretch;
    padding: var(--gap-xs);
    gap: var(--gap-2xs);
    flex-shrink: 0;
}

/* Мобильная шторка телепортируется в body: светлая тема выбеливает фон,
   тёмная — затемняет его через тот же модальный токен. */
.composer-plus-sheet__backdrop {
    background-color: var(--modal-backdrop);
}

.composer-plus-sheet__tile {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    /* Компактный сегмент: глиф + подпись, плотные отступы (метрики таб-бара). */
    gap: calc(2 * var(--gap-2xs));
    padding: var(--gap-sm) var(--gap-2xs);
    background: transparent;
    color: var(--text-main);
    border: 0;
    border-radius: max(0px, calc(var(--sheet-radius) - var(--sheet-pad)));
    corner-shape: var(--corner-shape-surface);
    transition: color var(--transition), background-color var(--transition), transform var(--transition);
}
@media (hover: hover) {
    .composer-plus-sheet__tile:not(.is-locked):hover {
        color: var(--text-main);
        background-color: var(--bg-hover);
    }
}
.composer-plus-sheet__tile:active {
    transform: scale(0.97);
    background-color: var(--surface-active);
}

.composer-plus-sheet__tile-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--gap-2xs);
    font-size: var(--text-xl);
    color: inherit;
}

.composer-plus-sheet__tile-label {
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    color: inherit;
    line-height: var(--leading-display);
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

/* Muted tokens alone convey availability. The lock shares the icon row so
   larger type never puts it on top of the attachment glyph. */
.composer-plus-sheet__tile.is-locked .composer-plus-sheet__tile-icon,
.composer-plus-sheet__tile.is-locked .composer-plus-sheet__tile-label {
    color: var(--text-muted);
}
.composer-plus-sheet__tile-lock {
    flex-shrink: 0;
    font-size: var(--text-xs);
    color: var(--text-muted);
}

.composer-plus-sheet__list {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    margin-top: 0.75rem;
    /* Скролл всегда здесь, а не на panel/stage — корректно работает и на
       мобильной bottom-sheet, и на desktop floating-панели. flex:1 + min-h:0
       позволяет списку сжаться до доступного пространства slide'а. */
    overflow-y: auto;
    overscroll-behavior: contain;
    flex: 1 1 auto;
    min-height: 0;
}
/* В root-слайде список теперь первый (плитки уехали вниз) — верхний зазор
   даёт padding панели, свой margin-top убираем. В sub-слайде список идёт
   под sub-header'ом, там margin-top нужен. */
.composer-plus-sheet__stage > .composer-plus-sheet__slide:first-child .composer-plus-sheet__list {
    margin-top: 0;
}

.composer-plus-sheet__item {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    gap: var(--gap-sm);
    width: 100%;
    min-width: 0;
    padding: var(--gap-xs) var(--gap-sm);
    border-radius: max(0px, calc(var(--sheet-radius) - var(--sheet-pad)));
    corner-shape: var(--corner-shape-surface);
    text-align: left;
    color: var(--text-main);
    transition: background-color var(--transition);
}
@media (hover: hover) {
    .composer-plus-sheet__item:hover { background-color: var(--bg-hover); }
}
.composer-plus-sheet__item.is-active { background-color: var(--bg-raised-75); }
[data-theme="light"] .composer-plus-sheet__item.is-active { background-color: var(--bg-raised); }

.composer-plus-sheet__item-icon {
    flex-shrink: 0;
    width: 2.25rem;
    height: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: var(--bg-raised-55);
    color: var(--text-main);
    font-size: var(--text-lg);
}
/* Когда внутри иконки оригинальный brand-SVG модели — даём небольшой
   внутренний отступ, чтобы лого не упиралось в края кружка. */
.composer-plus-sheet__item-icon > .model-icon-content {
    width: 72%;
    height: 72%;
}
[data-theme="light"] .composer-plus-sheet__item-icon { background-color: var(--bg-input); }

.composer-plus-sheet__item-body {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
    flex: 1 1 auto;
}

.composer-plus-sheet__item-label {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-tight);
    color: var(--text-main);
    overflow-wrap: anywhere;
}

.composer-plus-sheet__item-desc {
    font-size: var(--text-2xs);
    line-height: var(--leading-tight);
    color: var(--text-muted);
}

/* Вторая строка под лейблом: provider-текст + чипы-иконки возможностей.
   Чипы дают визуальные маркеры (референс, dynamic pricing, multi-input
   и т.п.) без накопления плейн-текста вроде «· ↻ референс». */
.composer-plus-sheet__item-sub {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    min-width: 0;
    flex-wrap: wrap;
    row-gap: 0.125rem;
}
.composer-plus-sheet__item-caps {
    display: inline-flex;
    align-items: center;
    gap: 0.1875rem;
}
.composer-plus-sheet__item-cap {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.125rem;
    height: 1.125rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: var(--bg-raised-55);
    color: var(--text-muted);
    font-size: var(--text-xs);
    transition: background-color var(--transition), color var(--transition);
}
.composer-plus-sheet__item.is-active .composer-plus-sheet__item-cap {
    color: var(--text-main);
    background-color: var(--surface-soft);
}
[data-theme="light"] .composer-plus-sheet__item-cap {
    background-color: var(--bg-input);
}

.composer-plus-sheet__item-check {
    flex-shrink: 0;
    color: var(--text-main);
    font-size: var(--text-base);
}

/* Недоступная функция (замок) в списке: приглушаем, гасим hover, значок справа. */
.composer-plus-sheet__item.is-locked {
    cursor: help;
}
.composer-plus-sheet__item.is-locked .composer-plus-sheet__item-label,
.composer-plus-sheet__item.is-locked .composer-plus-sheet__item-icon {
    color: var(--text-muted);
}
@media (hover: hover) {
    .composer-plus-sheet__item.is-locked:hover { background-color: transparent; }
}
.composer-plus-sheet__item-lock {
    flex-shrink: 0;
    margin-left: auto;
    padding-left: 0.5rem;
    color: var(--text-subtle);
    font-size: var(--text-base);
}

/* Текст поповера-предупреждения (locked/forced функция). */
.composer-plus-sheet__note {
    /* Горизонтальный inset = padding заголовка (.dropdown-menu__title, 0.75rem),
       чтобы текст ноты и заголовок шли по одному левому краю. */
    margin: 0.25rem 0.75rem 0.125rem;
    max-width: 16rem;
    font-size: var(--text-2xs);
    line-height: var(--leading-snug);
    color: var(--text-muted);
}

.composer-plus-sheet__gallery-title {
    margin: var(--gap-sm) 0 0;
    text-align: center;
    font-family: var(--font-editorial);
    font-size: var(--text-2xl);
    font-weight: var(--font-weight-editorial);
    line-height: var(--leading-snug);
}
.media-viewer__input-deleted {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: var(--gap-xs);
    width: 100%;
    height: 100%;
    font-size: var(--text-2xs);
    white-space: normal;
    color: var(--text-muted);
}

.composer-plus-sheet__library-tabs {
    display: flex;
    justify-content: flex-start;
    gap: calc(var(--gap-sm) * 2);
    overflow-x: auto;

    flex-shrink: 0;
    padding: var(--gap-sm) calc(var(--gap-sm) * 3) 0 0;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--gap-sm) * 3), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - var(--gap-sm) * 3), transparent);
}
.composer-plus-sheet__library-tab {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    gap: var(--gap-2xs);
}

.composer-plus-sheet__library-tabs [role="tab"] {
    flex: 0 0 auto;
    padding: var(--gap-xs) 0;
    font-family: var(--font-editorial);
    font-size: var(--text-xl);
    font-weight: var(--font-weight-editorial);
    color: var(--text-muted);
    transition: color var(--motion-duration-fast) var(--motion-ease-premium);
}
.composer-plus-sheet__library-tabs [role="tab"][aria-selected="true"] { color: var(--text-main); }
.composer-plus-sheet__gallery-cell { position: relative; min-width: 0; }
.composer-plus-sheet__gallery-cell > .composer-plus-sheet__gallery-thumb { width: 100%; display: block; }
.composer-plus-sheet__gallery-thumb:disabled { opacity: 0.45; cursor: default; }
.composer-plus-sheet__material-menu {
    position: absolute;
    top: var(--gap-xs);
    right: var(--gap-xs);
    background: var(--chat-input-bg);
    width: var(--artifact-control-size);
    height: var(--artifact-control-size);
}
@media (hover: hover) and (pointer: fine) {
    .composer-plus-sheet__gallery-cell > :is(.composer-plus-sheet__material-menu, .composer-plus-sheet__character-badge) {
        opacity: 0;
        pointer-events: none;
        transition: opacity var(--motion-duration-fast) var(--motion-ease-premium), background-color var(--transition);
    }
    .composer-plus-sheet__gallery-cell:is(:hover, :focus-within, :has([aria-expanded="true"])) > :is(.composer-plus-sheet__material-menu, .composer-plus-sheet__character-badge) {
        opacity: 1;
        pointer-events: auto;
    }
}
.composer-plus-sheet__gallery-name {
    position: absolute;
    inset: auto 0 0;
    padding: var(--gap-xs);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    background: var(--chat-input-bg);
    font-size: var(--text-xs);
}
/* Mobile libraries share a stable viewport across tabs and loading states. */
.composer-plus-sheet.is-library {
    --drawer-library-h: 82dvh;
    --library-width: 32rem;
    --library-height: 40rem;
    height: min(var(--drawer-library-h), var(--drawer-max-h));
    max-height: min(var(--drawer-max-h), var(--floating-max-height, 100dvh));
    /* The gallery reaches the panel's rounded clip. Only the floating actions
       own the bottom inset, so no rectangular padding strip cuts the photos. */
    padding-bottom: 0;
}
.composer-plus-sheet.is-library[data-library-tab="gallery"] {
    --library-width: 30rem;
}
@media (min-width: 640px) {
    .composer-plus-sheet__library-tabs {
        justify-content: space-evenly;
        gap: 0;
        padding-inline: 0;
        -webkit-mask-image: none;
        mask-image: none;
    }
    .composer-plus-sheet.is-library {
        width: min(var(--library-width), calc(100vw - 24px));
        height: min(var(--library-height), var(--drawer-library-h), var(--drawer-max-h));
    }
    .is-library .composer-plus-sheet__gallery { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .is-library[data-library-tab="gallery"] .composer-plus-sheet__gallery { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.composer-plus-sheet__gallery-thumb > .media-viewer__input-deleted { position: absolute; inset: 0; }

/* Условия загрузки под кнопками; ошибки остаются в содержимом галереи. */
.composer-plus-sheet__caption,
.composer-plus-sheet__library-error {
    margin: 0.5rem 0.25rem 0;
    font-size: var(--text-2xs);
    line-height: var(--leading-snug);
    color: var(--text-muted);
    text-align: center;
}

/* Галерея сгенерированного в «+»-листе — плотный грид миниатюр (замена подписи).
   Скроллится внутри листа; квадратные плитки, cover. */
.composer-plus-sheet__gallery-wrap {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}
.composer-plus-sheet__gallery {
    display: grid;
    flex: 1 1 auto;
    min-height: 0;
    align-content: start;
    /* minmax(0,1fr): без него 1fr = minmax(auto,1fr) и широкие картинки распирают
       колонки в неравные → неравные квадраты и «наслаивание». */
    grid-template-columns: repeat(3, minmax(0, 1fr));   /* строго 3 в ряд, равные */
    gap: var(--sheet-pad);
    margin: var(--sheet-pad) 0 0;
    padding: 0;
    max-height: calc(15rem + var(--floating-tray-height, 0px));
    overflow-y: auto;
    overscroll-behavior: contain;
}
.is-library .composer-plus-sheet__gallery {
    --scroll-edge-size: var(--gap-sm);
    margin-top: 0;
    max-height: none;
}
.is-library .composer-plus-sheet__gallery-empty {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    justify-content: center;
}
/* Desktop character shelves can fit their content; mobile keeps the sheet height. */
@media (min-width: 640px) {
    .composer-plus-sheet.is-library[data-library-tab="characters"] { height: auto; }
}
.is-library[data-library-tab="characters"] .composer-plus-sheet__gallery {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}
.is-library[data-library-tab="characters"] :is(.composer-plus-sheet__gallery-confirm-wrap, .composer-plus-sheet__gallery-sentinel) {
    display: none;
}
.composer-plus-sheet__character-create,
.collection-create-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--gap-xs);
    aspect-ratio: 6 / 5;
    min-width: 0;
    min-height: 0;
    padding: var(--gap-xs);
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-input);
    color: var(--text-muted);
    font-size: var(--text-base);
    font-weight: var(--font-weight-medium);
    transition: background-color var(--transition), color var(--transition);
}
.composer-plus-sheet__character-create > i,
.collection-create-card > i {
    font-size: var(--text-3xl);
    line-height: var(--leading-none);
}
@media (hover: hover) {
    .composer-plus-sheet__character-create:hover,
    .collection-create-card:hover {
        background: var(--bg-hover);
        color: var(--text-main);
    }
}
.composer-plus-sheet__character-create:focus-visible,
.collection-create-card:focus-visible {
    outline: 2px solid var(--text-main);
    outline-offset: -2px;
}
.composer-plus-sheet__character-badge {
    position: absolute;
    top: var(--gap-sm);
    right: var(--gap-sm);
    display: grid;
    place-items: center;
    width: var(--artifact-control-size);
    height: var(--artifact-control-size);
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background: var(--overlay-pill-bg);
    color: var(--overlay-text);
    font-size: var(--text-lg);
}
.composer-plus-sheet__gallery-thumb {
    position: relative;
    /* Квадрат через padding-хак (пуленепробиваемо, не зависит от aspect-ratio на
       кнопке): height:0 + padding-bottom:100% от ширины колонки. */
    height: 0;
    padding-bottom: 100%;
    min-width: 0;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    /* Мягкий плейсхолдер под миниатюрой: виден, пока фото грузится (без «сломанной»
       иконки и белых краёв при быстром скролле); загруженное фото (cover) его
       полностью перекрывает, поэтому у готовых плиток карточки не видно. */
    background: var(--surface-soft);
    cursor: pointer;
}
/* Медиа абсолютом внутри квадрата: видео и битые картинки не задают высоту сами,
   поэтому плитки не наслаиваются друг на друга — ряд ровный. */
.composer-plus-sheet__gallery-img,
.composer-plus-sheet__gallery-fallback {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}
.composer-plus-sheet__gallery-img {
    object-fit: cover;
    display: block;
    opacity: 0;
    transition: opacity var(--motion-duration-base) var(--motion-ease-premium);
}
.composer-plus-sheet__gallery-img.is-loaded { opacity: 1; }
@starting-style {
    .composer-plus-sheet__gallery-img.is-loaded { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .composer-plus-sheet__gallery-img { transition: none; }
}
.composer-plus-sheet__gallery-thumb.is-character {
    padding-bottom: calc(100% * 5 / 6);
    text-align: left;
}
.composer-plus-sheet__gallery-thumb.is-character > .composer-plus-sheet__gallery-name {
    padding: calc(var(--gap-sm) * 3) var(--gap-sm) var(--gap-sm);
    background: linear-gradient(transparent, var(--overlay-pill-bg-strong));
    color: var(--overlay-text);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
}
/* Скелетоны первой загрузки: квадрат той же метрики, что и плитки (padding-hack),
   мягкий пульс. Держат высоту грида → панель не «прыгает» при догрузке. */
.composer-plus-sheet__gallery-skeleton {
    height: 0;
    padding-bottom: 100%;
    min-width: 0;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
    animation: composer-plus-sheet-skeleton var(--motion-period-pulse) var(--motion-ease-ambient) infinite;
}
@keyframes composer-plus-sheet-skeleton {
    0%, 100% { opacity: 0.45; }
    50% { opacity: 0.8; }
}
@media (prefers-reduced-motion: reduce) {
    .composer-plus-sheet__gallery-skeleton { animation: none; }
}
/* Sentinel бесконечной ленты: невидимый маркер на всю ширину у низа скролл-грида. */
.composer-plus-sheet__gallery-sentinel {
    grid-column: 1 / -1;
    height: 1px;
}
.composer-plus-sheet__gallery-fallback {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    font-size: var(--text-xl);
}
/* Selection is indicated by the numbered overlay, without an outline. */
.composer-plus-sheet__gallery-thumb.is-selected::before,
.composer-plus-sheet__gallery-thumb:hover::before {
    content: none;
}
/* Номер соответствует порядку вложений, переданному провайдеру. */
.composer-plus-sheet__gallery-check {
    position: absolute;
    top: 50%;
    left: 50%;
    width: calc(var(--gap-sm) * 3.5);
    height: calc(var(--gap-sm) * 3.5);
    transform: translate(-50%, -50%) scale(0.85);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition-fast), transform var(--transition-fast);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
    color: var(--primary-text);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    font-variant-numeric: tabular-nums;
    z-index: 3;
}
.composer-plus-sheet__gallery-check.is-visible {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}
.composer-plus-sheet__gallery-empty {
    margin: 0.75rem 0.25rem 0.25rem;
    text-align: center;
    font-size: var(--text-2xs);
    color: var(--text-muted);
}
/* Кнопка «Прикрепить» — переиспользует .btn.btn-primary (CTA-градиент + правильный
   цвет текста --primary-text + hover); рядом — отдельная кнопка удаления. */
.composer-plus-sheet__gallery-confirm {
    flex: 1;
    min-width: 0;
    min-height: var(--composer-control-size);
}
.composer-plus-sheet__gallery-reset {
    flex: 0 0 auto;
    width: var(--composer-control-size);
    min-height: var(--composer-control-size);
    padding: 0;
    color: var(--text-muted);
    font-size: var(--text-lg);
}
.composer-plus-sheet__gallery-reset:is(:hover, :focus-visible) {
    color: var(--text-main);
}
.composer-plus-sheet__gallery-confirm-wrap {
    display: grid;
    flex-shrink: 0;
    margin-top: auto;
    grid-template-rows: 0fr;
    opacity: 0;
    transition: opacity var(--transition-slow);
}
.composer-plus-sheet__gallery-confirm-wrap.is-open {
    grid-template-rows: 1fr;
    opacity: 1;
    margin-bottom: var(--gap-sm);
}
.is-library .composer-plus-sheet__gallery-confirm-wrap {
    transition: grid-template-rows var(--transition-slow), opacity var(--transition-slow);
}
.composer-plus-sheet__gallery-confirm-inner {
    display: flex;
    gap: var(--gap-sm);
    min-height: 0;
    overflow: hidden;
    pointer-events: auto;
}
@media (prefers-reduced-motion: reduce) {
    .composer-plus-sheet__gallery-check,
    .composer-plus-sheet__gallery-confirm-wrap,
    .is-library .composer-plus-sheet__gallery-confirm-wrap { transition: none; }
}

/* Тонкая разделительная полоска внутри items (item.divider === true).
   Отделяет, например, «Настройки» от секции активных режимов. */
.composer-plus-sheet__divider {
    border: 0;
    flex-shrink: 0;
    height: 1px;
    margin: 0.375rem 0.5rem;
    background-color: var(--bg-raised-55);
}
[data-theme="light"] .composer-plus-sheet__divider {
    background-color: var(--bg-raised);
}
.composer-plus-sheet__section {
    padding: var(--gap-sm);
    margin-top: var(--gap-xs);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    font-weight: var(--font-weight-medium);
    color: var(--text-muted);
}

.composer-plus-sheet__item-meta {
    flex-shrink: 0;
    margin-left: auto;
    padding-left: 0.5rem;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.composer-plus-sheet__item.is-active .composer-plus-sheet__item-meta {
    color: var(--text-main);
}
.composer-plus-sheet__item.is-active .composer-plus-sheet__item-icon {
    background-color: var(--surface-soft);
    color: var(--text-main);
}

/* Chevron у строк с подменю */
.composer-plus-sheet__item-chev {
    flex-shrink: 0;
    margin-left: auto;
    padding-left: 0.25rem;
    color: var(--text-subtle);
    font-size: var(--text-base);
}
/* Если у строки уже есть meta, chevron идёт после, без margin-left:auto */
.composer-plus-sheet__item-meta + .composer-plus-sheet__item-chev {
    margin-left: 0.375rem;
    padding-left: 0;
}

/* Only the active view participates in layout; the shared controller morphs the panel. */
.composer-plus-sheet__stage {
    position: relative;
    display: grid;
    grid-template-areas: "main";
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
    /* The rounded panel clips transitions; inner bounds must not cut shadows. */
    overflow: visible;
    flex: 1 1 auto;
    min-height: 0;
}
.composer-plus-sheet__slide {
    position: absolute;
    inset: 0;
    grid-area: main;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: visible;
    opacity: 0;
    visibility: hidden;
    transform: translateX(1rem);
    transition: opacity var(--transition), transform var(--transition-slow), visibility var(--transition-slow);
}
.composer-plus-sheet__slide:first-child { transform: translateX(-1rem); }
.composer-plus-sheet__slide.is-active {
    position: relative;
    opacity: 1;
    visibility: visible;
    transform: none;
}
/* Scroll to the rounded panel edge, underneath the floating action tray. */
.composer-plus-sheet__slide[data-floating-tray-host] {
    --floating-tray-inset: 0px;
    --floating-tray-height: 0px;
}
.composer-plus-sheet__slide.is-menu > .composer-plus-sheet__content {
    padding-bottom: calc(var(--floating-tray-height, 0px) + var(--gap-sm));
    scroll-padding-bottom: calc(var(--floating-tray-height, 0px) + var(--gap-sm));
}
.composer-plus-sheet__gallery {
    --scroll-edge-space-end: calc(var(--floating-tray-height, 0px) + var(--gap-sm));
    scroll-padding-bottom: var(--scroll-edge-space-end);
}
.composer-plus-sheet__gallery-empty { padding-bottom: var(--floating-tray-height, 0px); }
.composer-plus-sheet .floating-tray__surface { border-radius: max(0px, calc(var(--sheet-radius) - var(--sheet-pad))); }
.composer-plus-sheet .floating-tray { padding-bottom: 0; }
.composer-plus-sheet.is-library .floating-tray { padding-bottom: var(--sheet-bottom-pad); }
.composer-plus-sheet .floating-tray__stack { gap: 0; }
.composer-plus-sheet__caption {
    position: relative;
    flex-shrink: 0;
    margin: 0 var(--gap-xs) var(--gap-sm);
}
/* A broad fade continues to the panel edge, without a stripe below the text.
   The tray's stacking context keeps this layer behind all of its controls. */
.floating-tray .composer-plus-sheet__caption::before {
    --caption-fade-size: calc(var(--composer-control-size) + 2 * var(--gap-sm));
    content: "";
    position: absolute;
    inset: calc(-1 * var(--caption-fade-size)) calc(-1 * (var(--sheet-pad) + var(--gap-xs))) calc(-1 * var(--floating-tray-height, 0px));
    z-index: -1;
    background: linear-gradient(to bottom,
        transparent,
        color-mix(in srgb, var(--chat-input-solid) 3%, transparent) calc(var(--caption-fade-size) * .15),
        color-mix(in srgb, var(--chat-input-solid) 16%, transparent) calc(var(--caption-fade-size) * .3),
        color-mix(in srgb, var(--chat-input-solid) 50%, transparent) calc(var(--caption-fade-size) * .5),
        color-mix(in srgb, var(--chat-input-solid) 84%, transparent) calc(var(--caption-fade-size) * .7),
        color-mix(in srgb, var(--chat-input-solid) 97%, transparent) calc(var(--caption-fade-size) * .85),
        var(--chat-input-solid) var(--caption-fade-size));
    pointer-events: none;
}
.composer-plus-sheet__slide.is-menu .composer-plus-sheet__list {
    flex: 0 0 auto;
    overflow: visible;
}
@media (prefers-reduced-motion: reduce) {
    .composer-plus-sheet__slide { transition: none; }
}

/* Sub-header (back + title) */
.composer-plus-sheet__sub-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0.25rem 0.5rem;
}
.composer-plus-sheet__back {
    width: 2rem;
    height: 2rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    color: var(--text-muted);
    transition: background-color var(--transition), color var(--transition);
}
@media (hover: hover) {
    .composer-plus-sheet__back:hover {
        background-color: var(--bg-hover);
        color: var(--text-main);
    }
}
.composer-plus-sheet__sub-title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Horizontal slide-анимации для push-view внутри stage.
   Используются как x-transition:enter/leave классы. */
@keyframes sheet-slide-in-right {
    from { opacity: 0; transform: translateX(8%); }
    to   { opacity: 1; transform: translateX(0); }
}
@keyframes sheet-slide-out-right {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(8%); }
}
@keyframes sheet-slide-in-left {
    from { opacity: 0; transform: translateX(-8%); }
    to   { opacity: 1; transform: translateX(0); }
}
@keyframes sheet-slide-out-left {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(-8%); }
}
.sheet-slide-from-right { animation: sheet-slide-in-right  var(--motion-duration-base) var(--motion-ease-premium) both; }
.sheet-slide-to-right   { animation: sheet-slide-out-right var(--motion-duration-fast) var(--motion-ease-exit)    both; }
.sheet-slide-from-left  { animation: sheet-slide-in-left   var(--motion-duration-base) var(--motion-ease-premium) both; }
.sheet-slide-to-left    { animation: sheet-slide-out-left  var(--motion-duration-fast) var(--motion-ease-exit)    both; }

/* ─── Desktop hover/click flyout — отдельная панель сбоку.
   Габариты как у dropdown'а, но со стеклянным фоном шторки. */
.composer-plus-sheet--flyout {
    position: fixed;
    width: 18rem;
    /* Высоту держим в пределах ~5-6 видимых элементов: иначе flyout
       с длинным списком (image-picker) при anchor'е у нижнего края
       viewport-а смещается вверх _fitPosition'ом и перекрывает родителя. */
    max-height: min(20rem, var(--floating-max-height, calc(100dvh - 2 * var(--app-gutter-x))));
    padding: 0.3125rem;
    /* Скролл — на внутреннем __list, не на самом flyout, чтобы не было
       двух вложенных скролл-областей. */
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.composer-plus-sheet--flyout .composer-plus-sheet__list {
    margin-top: 0;
    gap: 0.125rem;
}
.composer-plus-sheet--flyout .composer-plus-sheet__item {
    padding: 0.4375rem 0.625rem;
    gap: 0.5rem;
}
.composer-plus-sheet--flyout .composer-plus-sheet__item-icon {
    width: 1.5rem;
    height: 1.5rem;
    font-size: var(--text-xs);
}
.composer-plus-sheet--flyout .composer-plus-sheet__item-label {
    font-size: var(--text-sm);
}
.composer-plus-sheet--flyout .composer-plus-sheet__item-desc {
    font-size: var(--text-2xs);
}
.composer-plus-sheet--flyout .composer-plus-sheet__item-meta {
    font-size: var(--text-xs);
    padding-left: 0.375rem;
}
.composer-plus-sheet--flyout .composer-plus-sheet__item-cap {
    width: 1rem;
    height: 1rem;
    font-size: var(--text-2xs);
}
.composer-plus-sheet--flyout .composer-plus-sheet__item-sub {
    gap: 0.25rem;
}
@media (max-width: 639px) {
    /* На мобиле flyout не нужен — sub-view внутри панели заменяет его. */
    .composer-plus-sheet--flyout { display: none !important; }
}



/* ══════════════════════════════════════════════
   УНИВЕРСАЛЬНЫЕ АНИМАЦИИ ШТОРОК / МОДАЛОВ
   Чтобы изменить анимацию ВСЕХ шторок — редактируй только здесь.
   Мобайл (< 640px) : слайд снизу вверх
   Десктоп (≥ 640px): scale + translate
   Непрозрачные диалоги мягко проявляются на десктопе; на мобильном
   панель выезжает снизу. Затемнение использует тот же такт открытия.
   ══════════════════════════════════════════════ */
@media (max-width: 639px) {
    .drawer-closed { transform: translateY(100%); }
}
@media (min-width: 640px) {
    .drawer-closed { opacity: 0; transform: scale(0.95) translateY(8px); }
}
.composer-plus-sheet__flyout-content {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}
.drawer-open { opacity: 1; transform: none; }
.backdrop-closed { opacity: 0; }
.backdrop-open { opacity: 1; }

/* x-bind="drawerMotion" / x-bind="backdropMotion" own both endpoints.
   Preserve the compositor layer for the whole transition, including reversal.
   Clear both endpoint classes after completion, including rapid reversal. */
.drawer-enter { transition: transform var(--motion-duration-drawer) var(--motion-ease-premium), opacity var(--motion-duration-drawer) var(--motion-ease-premium) !important; }
.drawer-leave { transition: transform var(--motion-duration-fast) var(--motion-ease-exit), opacity var(--motion-duration-fast) var(--motion-ease-exit) !important; }
.drawer-enter, .drawer-leave { will-change: transform; }
[data-overlay-exiting] { pointer-events: none !important; }
/* The departing scrim continues to absorb clicks until the page is uncovered. */
.overlay-backdrop[data-overlay-exiting], .payment-backdrop[data-overlay-exiting],
.media-viewer[data-overlay-exiting] { pointer-events: auto !important; }
.backdrop-enter { transition: opacity var(--motion-duration-drawer) var(--motion-ease-standard) !important; }
.backdrop-leave { transition: opacity var(--motion-duration-fast) var(--motion-ease-exit) !important; }

/* Local surfaces share the drawer clock/reversal lifecycle. They do not wait
   for unrelated dialogs to close and never move layout-owned dimensions. */
.surface-fade-enter, .surface-scale-enter { transition: opacity var(--motion-duration-base) var(--motion-ease-premium), transform var(--motion-duration-base) var(--motion-ease-premium); }
.surface-fade-leave, .surface-scale-leave { transition: opacity var(--motion-duration-fast) var(--motion-ease-exit), transform var(--motion-duration-fast) var(--motion-ease-exit); }
.surface-fade-closed, .surface-scale-closed { opacity: 0; }
.surface-fade-open, .surface-scale-open { opacity: 1; }
.surface-scale-enter, .surface-scale-leave { transform-origin: right center; }
.surface-scale-closed { transform: scale(var(--motion-scale-surface)); }
.surface-scale-open { transform: none; }
@media (prefers-reduced-motion: reduce) {
    .surface-fade-enter, .surface-fade-leave, .surface-scale-enter, .surface-scale-leave { transition: none; }
}

/* Shared popup entrance (dropdowns, flyouts, popovers). */
@keyframes popup-in {
    from { transform: scale(0.9); }
    to   { transform: scale(1); }
}
.popup-enter { animation: popup-in var(--motion-duration-popup) var(--motion-ease-premium) both; }
.popover-enter {
    transition: opacity var(--motion-duration-popup) var(--motion-ease-premium), transform var(--motion-duration-popup) var(--motion-ease-premium);
}
.popover-leave {
    transition: opacity var(--motion-duration-popup) var(--motion-ease-exit), transform var(--motion-duration-popup) var(--motion-ease-exit);
}
.popover-closed { opacity: 0; transform: scale(var(--motion-scale-surface)); }
.popover-open { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
    .popover-enter, .popover-leave { transition: none; }
}

@keyframes popup-retarget-in {
    from { transform: translateY(0.125rem) scale(0.985); }
    to   { transform: translateY(0) scale(1); }
}
.popup-retarget { animation: popup-retarget-in var(--motion-duration-popup) var(--motion-ease-standard) both; }

/* Fade enter/leave (lightboxes, fullscreen overlays) */
@keyframes fade-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }
.fade-enter { animation: fade-in  var(--motion-duration-base) var(--motion-ease-standard) both; }
.fade-leave { animation: fade-out var(--motion-duration-fast) var(--motion-ease-exit) both; }

/* Step transition (payment wizard, multi-step flows) */
@keyframes step-in  { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
@keyframes step-out { from { opacity: 1; transform: translateY(0);   } to { opacity: 0; transform: translateY(-3px); } }
.step-enter { animation: step-in  var(--motion-duration-drawer) var(--motion-ease-premium) both; }
.step-leave { animation: step-out var(--motion-duration-fast)   var(--motion-ease-exit)    both; }

/* Content slide-up (empty states, hero sections) */
@keyframes content-up-in  { from { opacity: 0; transform: translateY(var(--motion-distance-content)); } to { opacity: 1; transform: translateY(0); } }
@keyframes content-up-out { from { opacity: 1; transform: translateY(0);    } to { opacity: 0; transform: translateY(calc(-1 * var(--motion-distance-content))); } }
.content-up-enter { animation: content-up-in  var(--motion-duration-slow) var(--motion-ease-premium) both; }
.content-up-leave { animation: content-up-out var(--motion-duration-fast) var(--motion-ease-exit)    both; }

/* A mounted subview enters once; the enclosing dialog keeps its own motion. */
.dialog-view-enter { animation: step-in var(--motion-duration-drawer) var(--motion-ease-premium) both; }

/* A keyframe transition owns its entire lifetime. Alpine otherwise waits for
   an unrelated theme/hover transition instead of the animation's duration. */
.popup-enter, .popup-retarget, .fade-enter, .fade-leave,
.step-enter, .step-leave, .content-up-enter, .content-up-leave,
.sheet-slide-from-right, .sheet-slide-to-right,
.sheet-slide-from-left, .sheet-slide-to-left, .dialog-view-enter {
    transition: none !important;
}

@media (prefers-reduced-motion: reduce) {
    .drawer-enter, .drawer-leave, .backdrop-enter, .backdrop-leave,
    .popup-enter, .popup-retarget, .fade-enter, .fade-leave,
    .step-enter, .step-leave, .content-up-enter, .content-up-leave,
    .sheet-slide-from-right, .sheet-slide-to-right,
    .sheet-slide-from-left, .sheet-slide-to-left, .dialog-view-enter {
        animation: none !important;
        transition: none !important;
    }
    [x-drawer-swipe], .media-viewer, .media-viewer__stage > .media-viewer__loading {
        transition: none !important;
    }
}

/* CSS fallback for surfaces outside base_app (for example admin support). */
@keyframes stagger-in {
    from { opacity: 0; transform: translateY(16px); }
    to { opacity: 1; transform: translateY(0); }
}
.stagger-enter .stagger-item { animation: stagger-in var(--motion-duration-list) var(--motion-ease-list) both; }
.stagger-enter .stagger-item:nth-child(1) { animation-delay: 0ms; }
.stagger-enter .stagger-item:nth-child(2) { animation-delay: calc(var(--motion-stagger-step) * 1); }
.stagger-enter .stagger-item:nth-child(3) { animation-delay: calc(var(--motion-stagger-step) * 2); }
.stagger-enter .stagger-item:nth-child(4) { animation-delay: calc(var(--motion-stagger-step) * 3); }
.stagger-enter .stagger-item:nth-child(5) { animation-delay: calc(var(--motion-stagger-step) * 4); }
.stagger-enter .stagger-item:nth-child(6) { animation-delay: calc(var(--motion-stagger-step) * 5); }
.stagger-enter .stagger-item:nth-child(7) { animation-delay: calc(var(--motion-stagger-step) * 6); }
.stagger-enter .stagger-item:nth-child(8) { animation-delay: calc(var(--motion-stagger-step) * 7); }
.stagger-enter .stagger-item:nth-child(9) { animation-delay: calc(var(--motion-stagger-step) * 8); }
.stagger-enter .stagger-item:nth-child(10) { animation-delay: calc(var(--motion-stagger-step) * 9); }
.stagger-enter .stagger-item:nth-child(11) { animation-delay: calc(var(--motion-stagger-step) * 9); }
.stagger-enter .stagger-item:nth-child(12) { animation-delay: calc(var(--motion-stagger-step) * 9); }
@media (prefers-reduced-motion: reduce) {
    .stagger-enter .stagger-item { animation: none; }
}

/* App lists are scheduled after data readiness by ShellMotion. */
.shell-motion-preparing #app-shell-root :is([data-motion], .stagger-item, .home-inspiration-card) {
    visibility: hidden;
}
.shell-motion-preparing #app-shell-root [data-motion-glass] {
    /* Visible descendants cannot bypass the route's pre-animation hold. */
    clip-path: inset(50%);
}

/* ══════════════════════════════════════════════
   IN-APP PUSH NOTIFICATIONS (сверху)
   ══════════════════════════════════════════════ */
.notif-container {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: var(--z-fullscreen-modal);
    display: flex;
    flex-direction: column;
    align-items: center;
    pointer-events: none;
    padding: env(safe-area-inset-top, 0px) 12px 0;
    /* spacing between items via margin-bottom (animatable per-item) */
}

.notif-push {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    max-width: 420px;
    margin-bottom: 8px;
    padding: calc(var(--gap-sm) * 2.25) calc(var(--gap-sm) * 2);
    background: var(--bg-elevated);
    border-radius: var(--radius-2xl);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-glass);
    pointer-events: auto;
    cursor: pointer;
    text-decoration: none;
    color: var(--text-main);
    -webkit-user-select: none;
    user-select: none;
    overflow: hidden;
    box-sizing: border-box;
    /* entrance — starts off-screen */
    transform: translateY(-120%);
    opacity: 0;
    transition:
        transform      var(--motion-duration-slow) var(--motion-ease-premium),
        opacity        var(--motion-duration-base) var(--motion-ease-standard),
        height         var(--motion-duration-base) var(--motion-ease-premium),
        margin-bottom  var(--motion-duration-base) var(--motion-ease-premium),
        padding-top    var(--motion-duration-base) var(--motion-ease-premium),
        padding-bottom var(--motion-duration-base) var(--motion-ease-premium);
}

/* Notifications and detail popovers share the same glass surface in every context. */
.notif-push:not(.notif-push--bottom),
.notif-push--details {
    background: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
}

.notif-push-visible {
    transform: translateY(12px);
    opacity: 1;
}

.notif-push-hiding {
    transform: translateY(-120%);
    opacity: 0;
    margin-bottom: 0;
    padding-top: 0;
    padding-bottom: 0;
    pointer-events: none;
    /* height обнуляется инлайн-стилем из JS — после фиксации актуальной высоты */
}

.notif-push:active {
    transform: translateY(12px) scale(0.98);
}

.notif-push-icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal;
    color: var(--primary-text);
    font-size: var(--text-xl);
}

/* Structured model details use the shared notification surface. */
.notif-container--details {
    z-index: var(--z-popover);
    padding-top: max(var(--gap-sm), env(safe-area-inset-top, 0px));
}
.notif-container--anchored {
    right: auto;
    width: min(23rem, calc(100vw - 1rem));
    padding: 0;
}
.notif-push--details {
    position: relative;
    align-items: flex-start;
    max-width: 23rem;
    max-height: calc(100dvh - 2rem - env(safe-area-inset-top, 0px));
    overflow-y: auto;
    overscroll-behavior: contain;
    cursor: default;
    user-select: text;
    -webkit-user-select: text;
    padding: calc(var(--gap-sm) * 2);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    transform: none;
    margin: 0;
}
.notif-push--details.notif-push-visible,
.notif-push--details:active { transform: none; }
.notif-push--details .notif-push-text {
    margin-top: calc(var(--gap-sm) * 2);
    line-height: var(--leading-normal);
    display: block;
    overflow: visible;
    white-space: normal;
    overflow-wrap: anywhere;
    -webkit-line-clamp: unset;
}
.notif-push--details .notif-push-close {
    position: absolute;
    top: var(--gap-sm);
    right: var(--gap-sm);
    width: 1.5rem;
    height: 1.5rem;
    min-width: 1.5rem;
    border: 0;
    padding: 0;
    font-size: var(--text-base);
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
}
.notif-detail-heading {
    display: flex;
    align-items: center;
    gap: calc(var(--gap-sm) * 2);
}
.notif-detail-heading:not(:has(.notif-detail-badges)) .notif-push-title {
    padding-right: calc(var(--gap-sm) * 3);
}
.notif-detail-summary { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.notif-detail-highlight {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2xs);
    margin-top: calc(var(--gap-sm) * 2);
}
.notif-detail-highlight strong {
    color: var(--text-main);
    font-size: var(--text-2xl);
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-tight);
    font-variant-numeric: tabular-nums;
}
.notif-detail-highlight > span {
    color: var(--text-muted);
    font-size: var(--text-xs);
}
.notif-detail-fields {
    display: grid;
    gap: var(--gap-sm);
    margin: calc(var(--gap-sm) * 2) 0 0;
    padding: 0;
    font-size: var(--text-caption);
    line-height: var(--leading-snug);
}
.notif-detail-fields > div { display: flex; justify-content: space-between; gap: var(--gap-sm); }
.notif-detail-fields dt { color: var(--text-muted); }
.notif-detail-fields dd { margin: 0; text-align: right; color: var(--text-main); font-variant-numeric: tabular-nums; }
.notif-detail-fields--chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap-xs);
    font-size: var(--text-xs);
}
.notif-detail-fields--chips > div {
    align-items: center;
    gap: var(--gap-xs);
    padding: var(--gap-xs) var(--gap-sm);
    background: var(--surface-soft);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
}
.notif-detail-fields--chips dd { font-weight: var(--font-weight-medium); }
.notif-detail-badges {
    display: grid;
    grid-template-columns: repeat(var(--detail-icon-columns, 4), 2.5rem);
    flex-shrink: 0;
    gap: var(--gap-xs);
    margin-left: auto;
    margin-top: calc(var(--gap-sm) * 3);
}
.notif-detail-badges > span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    /* Capability controls are circles, independent of panel corner settings. */
    border-radius: 50%;
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    cursor: help;
    color: var(--text-muted);
    font-size: var(--text-caption);
}
.notif-detail-badges .ti { font-size: var(--text-xl); flex-shrink: 0; }
.notif-detail-badges > span:is(:hover, :focus-visible) { background: var(--surface-active); color: var(--text-main); }
.notif-detail-badges > span:focus-visible { outline: 2px solid var(--text-muted); outline-offset: 2px; }
.notif-push--details .notif-push-body { container-type: inline-size; }
@container (max-width: 18rem) {
    .notif-detail-badges { grid-template-columns: repeat(2, 2.5rem); }
}

.notif-push-body {
    flex: 1;
    min-width: 0;
}

.notif-push-title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-snug);
    color: var(--text-main);
}

.notif-push-text {
    font-size: var(--text-xs);
    color: var(--text-muted);
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.notif-push-arrow {
    flex-shrink: 0;
    color: var(--text-subtle);
    font-size: var(--text-base);
    opacity: .6;
}

/* Compact toast: текст-пилюля без иконки/шеврона, ужимается по контенту */
.notif-push--toast {
    width: auto;
    max-width: min(calc(100vw - 24px), 420px);
    padding: calc(var(--gap-sm) * 1.75) calc(var(--gap-sm) * 2.25);
    gap: 0;
}

.notif-push--toast .notif-push-body {
    flex: 0 1 auto;
    text-align: center;
}

.notif-push--toast .notif-push-title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
}

/* Постоянный push (напр. «доступно обновление»): тело не кликабельно целиком —
   действие только через кнопку/свайп, поэтому и курсор обычный. */
.notif-push--persistent {
    cursor: default;
}

.notif-push--persistent:active {
    transform: translateY(12px);
}

/* Кнопка-действие внутри push'а («Обновить»). Тот же акцент, что у иконки. */
.notif-push-action {
    display: inline-flex;
    align-items: center;
    margin-top: 8px;
    padding: 5px 14px;
    border: none;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
    color: var(--primary-text);
    font-family: inherit;
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-tight);
    cursor: pointer;
    pointer-events: auto;
    -webkit-user-select: none;
    user-select: none;
    transition:
        transform var(--motion-duration-base) var(--motion-ease-standard),
        filter    var(--motion-duration-base) var(--motion-ease-standard);
}

.notif-push-action:active {
    transform: scale(0.96);
}

@media (hover: hover) {
    .notif-push-action:hover {
        filter: brightness(1.06);
    }
}

/* Update uses the same surface, type, spacing and radius scales as the shell. */
.notif-push--update {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    width: 100%;
    max-width: 30rem;
    gap: calc(var(--gap-sm) * 1.5);
    padding: calc(var(--gap-sm) * 2);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--chat-input-bg);
    box-shadow: var(--shadow-dropdown);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
}
.notif-push--update .notif-push-text {
    margin: 0;
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    white-space: normal;
    overflow-wrap: anywhere;
}
.notif-push--update .notif-push-action {
    flex-shrink: 0;
    justify-content: center;
    min-height: 2.75rem;
    margin: 0;
    padding: var(--gap-sm) calc(var(--gap-sm) * 2);
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
}
@media (max-width: 479px) {
    .notif-push--update { grid-template-columns: minmax(0, 1fr); }
    .notif-push--update .notif-push-action { grid-column: 1 / -1; width: 100%; }
}
.notif-push-close {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: var(--shell-header-slot);
    height: var(--shell-header-slot);
    padding: 0;
    border: 0;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-base);
    cursor: pointer;
}
.notif-push-close:hover { background: var(--bg-hover); color: var(--text-main); }
.notif-push :is(button, a):focus-visible { outline: var(--gap-2xs) solid var(--prism-accent); outline-offset: var(--gap-2xs); }
.notif-push.notif-push-hiding { padding-block: 0; }

/* Нижний стек (постоянный push обновления «снизу»): отдельный контейнер, чтобы
   не конфликтовать с эфемерными тостами сверху. Анимация входа/выхода — зеркало. */
.notif-container--bottom {
    top: auto;
    bottom: 0;
    justify-content: flex-end;
    padding: 0 12px calc(var(--safe-area-bottom, 0px) + 12px);
}

.notif-push--bottom {
    transform: translateY(120%);
}

.notif-push--bottom.notif-push-visible {
    transform: translateY(-12px);
}

.notif-push--bottom.notif-push-hiding {
    transform: translateY(120%);
}

.notif-push--bottom.notif-push--persistent:active {
    transform: translateY(-12px);
}

/* ══════════════════════════════════════════════ */

.overlay-scrim { background-color: var(--overlay-scrim); }
.overlay-icon { background-color: var(--surface-dim); color: var(--text-main); }
@media (hover: hover) {
    .overlay-icon:hover,
    .hover-text-danger:hover {
        color: var(--text-main);
    }
}
.dropdown-item-danger,
.text-danger {
    color: var(--text-main);
}
.upload-overlay { background-color: var(--overlay-backdrop-soft); }
.accent-glow { background-color: var(--surface-soft); }
.text-success,
.icon-success { color: var(--text-main); }
.accent-gradient-text {
    background-image: linear-gradient(90deg, var(--primary-500), var(--accent-cool));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}
.accent-strip { background-color: var(--text-muted); }
.icon-contrast { background-color: var(--primary-text); }

.voice-recording-title {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    line-height: var(--leading-none);
    font-weight: var(--font-weight-display);
    letter-spacing: var(--tracking-wider);
    text-transform: uppercase;
    /* Typography only; .text-shimmer owns the shared text-light effect. */
}

@media (max-width: 767px) {
    .voice-recording-title {
        font-size: var(--text-base);
    }
}

/* Model Selector */
.model-chip,
.modal-close-btn-bg,
.camera-icon-box {
    background-color: var(--bg-input);
}

.model-chip {
    color: var(--text-muted);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    padding: 0.375rem 0.75rem;
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    display: inline-flex;
    align-items: center;
    gap: var(--gap-xs);
    white-space: nowrap;
    flex-shrink: 0;
    transition: background-color var(--transition), color var(--transition), box-shadow var(--transition), filter var(--transition);
}
@media (hover: hover) {
    .model-chip:hover {
        background-color: var(--surface-active);
        box-shadow: var(--shadow-surface);
    }
}
.model-chip-active { background-color: var(--text-main); color: var(--text-inverse); }
.model-chip-icon {
    width: 0.875rem;
    height: 0.875rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.model-icon-content {
    display: block;
    width: 100%;
    height: 100%;
    color: currentColor;
}

/* Neutral icon tiles on glass share a translucent surface in the dark theme.
   Keep the existing light-theme surfaces and colored artwork untouched. */
:root:not([data-theme="prism-light"]):not([data-theme="light"]) :is(
    .model-icon-box, .tg-chat-icon, .assistant-icon, .profile-avatar,
    .chat-access-avatar--fallback, .mention-item-icon, .camera-icon-box,
    .composer-plus-sheet__item-icon, .chat-input-assistant-create__icon,
    .payment-state-icon, .media-viewer__fallback-icon, .wf-side-item__icon,
    .sup-intro__icon, .music-player-full__iconbtn, .icon-contrast,
    .profile-settings-btn,
    .tg-pick-thumb, .tg-draft__thumb, .sup-pending-thumb, .icon-surface,
    .dropdown-menu .dropdown-item > i, .dropdown-menu .dropdown-item > .dropdown-item-glyph
) { background-color: var(--surface-soft); }
:root:not([data-theme="prism-light"]):not([data-theme="light"]) .music-player-full__iconbtn:hover {
    background-color: var(--surface-active);
}
.model-icon-content > svg,
.model-icon-content > span {
    display: block;
    width: 100%;
    height: 100%;
}
.model-icon-content > svg {
    fill: currentColor;
}

/* Section Headers */
.model-section-header {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: var(--gap-xs);
    padding: 0.4375rem 0.5rem 0.3125rem;
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-bold);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}
.model-section-icon-popular { color: var(--accent-warm); }

/* Popular Model Card */
.model-popular-card {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    padding: 0.5rem;
    /* Вложенная карточка-ряд: на ступень ниже контейнера (флайаут/модалка =
       --radius-lg) — внутреннее скругление меньше внешнего, читается как вложенное.
       --radius-pill (капсула) тут давал угол круглее рамки. */
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    cursor: pointer;
    transition: background-color var(--transition), transform var(--motion-duration-micro) var(--motion-ease-standard);
}
@media (hover: hover) {
    .model-popular-card:hover { background-color: var(--bg-hover); }
}
.model-popular-card:active { transform: scale(0.99); }
.model-popular-card-active { background-color: var(--surface-active); }
/* Подложка логотипа модели — единый компонент карточек (popular + group).
   Единственный источник размера — --model-icon-size; padding выводится из
   него, поэтому глиф во всех карточках занимает одинаковую внутреннюю
   область. Круглая (квадрат + radius-round = аватар): на 100% скругления — круг,
   при меньшем --radius-scale корректно уходит в скруглённый квадрат МЕНЬШЕ рамки
   карточки (--radius-pill тут давал угол круглее карточки). overflow:hidden режет
   глиф по форме. */
.model-icon-box {
    --model-icon-size: 2.5rem;
    width: var(--model-icon-size);
    height: var(--model-icon-size);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: calc(var(--model-icon-size) * 0.2);
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    overflow: hidden;
    background-color: var(--bg-elevated);
    color: var(--text-main);
}
.model-popular-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}
.model-popular-select {
    display: flex;
    align-items: center;
    gap: calc(var(--gap-sm) * 1.5);
    flex: 1 1 auto;
    min-width: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    text-align: left;
    font: inherit;
    cursor: pointer;
}
.model-popular-description {
    font-size: var(--text-2xs);
    line-height: var(--leading-snug);
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.model-description-text {
    display: block;
    min-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}
.model-popular-description[data-marquee-overflow="true"] { text-overflow: clip; }
.model-popular-description[data-marquee-overflow="true"] .model-description-text {
    width: max-content;
    overflow: visible;
}
.model-popular-select:focus-visible,
.model-popular-price:focus-visible,
.model-flyout-show-all:focus-visible {
    outline: var(--gap-2xs) solid var(--text-muted);
    outline-offset: var(--gap-2xs);
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
}
.model-popular-name {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    min-width: 0;            /* чтобы имя-truncate могло сжиматься */
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    line-height: var(--leading-tight);
}
/* Бейдж не сжимается — сжимается (обрезается) только имя. */
.model-badge-new { flex-shrink: 0; }
.price-pill,
.model-popular-price {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    color: var(--text-main);
    gap: 0;
    padding: var(--gap-xs) var(--gap-sm);
    border: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-active);
    white-space: nowrap;
    cursor: pointer;
    transition: background-color var(--transition-fast), color var(--transition-fast);
}
:is(.price-pill, .model-popular-price):hover,
:is(.price-pill, .model-popular-price)[aria-expanded="true"] { background: var(--surface-strong); color: var(--text-main); }
.price-pill .ti,
.model-popular-price .ti {
    font-size: var(--text-sm);
    width: 1em;
    min-width: 0;
    flex-shrink: 0;
    margin-left: var(--gap-xs);
    overflow: hidden;
    opacity: 1;
    transition: width var(--motion-duration-fast) var(--motion-ease-premium),
        margin-left var(--motion-duration-fast) var(--motion-ease-premium),
        opacity var(--motion-duration-fast) var(--motion-ease-standard);
}
@media (hover: hover) and (pointer: fine) {
    :is(.model-popular-price, .media-composer-price__value):not(:hover):not(:focus-visible):not([aria-expanded="true"]) .ti {
        width: 0;
        margin-left: 0;
        opacity: 0;
    }
}
@media (prefers-reduced-motion: reduce) {
    .price-pill, .price-pill .ti, .model-popular-price, .model-popular-price .ti { transition: none; }
}

.price-pill:focus-visible { outline: 2px solid var(--text-muted); outline-offset: 2px; }
.dropdown-menu.dropdown-menu--model-rows {
    width: min(18rem, calc(100vw - 1rem));
    max-height: min(60dvh, 24rem);
    padding: 0.1875rem;
}
.dropdown-menu.music-actions-menu {
    width: max-content;
    max-width: min(18rem, calc(100vw - 1rem));
    min-width: 0;
}
.dropdown-priced-row {
    flex-shrink: 0;
    min-height: 2.625rem;
    padding: 0.4375rem 0.5rem;
    gap: var(--gap-sm);
}
.dropdown-priced-row .model-popular-select { gap: var(--gap-sm); }
.dropdown-priced-row .model-icon-box { --model-icon-size: 1.75rem; }
.dropdown-priced-row .model-popular-name { overflow-wrap: anywhere; }
.dropdown-priced-row.dropdown-item-danger :is(.model-popular-name, .model-icon-box) { color: inherit; }

/* New-model badge */
.model-badge-new {
    display: inline-flex;
    align-items: center;
    padding: 0.0625rem 0.4375rem;
    background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    /* 10px — меньше любого token'а (--text-2xs = 11.2px), бэйджу хочется
       быть чуть мельче окружающего текста. Оставлено хардкодом сознательно. */
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-bold);
    color: var(--primary-text);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    line-height: var(--leading-snug);
}

/* Group Card (All models section) */
.model-popular-name .model-badge-new {
    font-family: var(--font-sans);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-light);
    text-transform: none;
    letter-spacing: var(--tracking-normal);
}
.modal-illustrated .modal-header-title {
    font-family: var(--font-editorial);
    font-weight: var(--font-weight-editorial);
    font-size: clamp(var(--text-2xl), calc(8.8cqw * var(--font-scale)), var(--text-3xl));
}
.modal-art {
    position: absolute;
    inset: 0 0 auto;
    width: 100%;
    height: var(--modal-art-height);
    object-fit: cover;
    object-position: center;
    pointer-events: none;
    user-select: none;
    opacity: .85;
    -webkit-mask-image: linear-gradient(to bottom, var(--text-main) 45%, transparent);
    mask-image: linear-gradient(to bottom, var(--text-main) 45%, transparent);
}
.modal-illustrated .modal-art-header {
    position: relative;
    container-type: inline-size;
    min-height: var(--modal-art-header-height);
    gap: var(--gap-sm);
    margin: 0 0 var(--gap-sm);
    padding-inline: var(--modal-content-pad);
    flex-shrink: 0;
}
.modal-art-header > .flex { flex-shrink: 0; }
.modal-art-header .modal-header-close {
    width: var(--composer-control-size);
    height: var(--composer-control-size);
    font-size: var(--text-xl);
    background: var(--surface-active);
    color: var(--text-main);
}
:root[data-theme="prism-light"] .modal-art { opacity: .16; }
.model-group-card {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    padding: 0.5rem;
    /* Как .model-popular-card: на ступень ниже контейнера (см. коммент там). */
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    cursor: pointer;
    transition: background-color var(--transition), transform var(--motion-duration-micro) var(--motion-ease-standard);
}
@media (hover: hover) {
    .model-group-card:hover {
        background-color: var(--bg-hover);
    }
}
.model-group-card:active { transform: scale(0.99); }
.model-group-card-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.0625rem;
}
.model-group-card-name {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
}
.model-group-card-meta {
    font-size: var(--text-xs);
    color: var(--text-subtle);
}
.model-group-card-chevron {
    flex-shrink: 0;
    color: var(--text-subtle);
    font-size: var(--text-lg);
    margin-left: auto;
    opacity: 0.5;
    transition: opacity var(--transition), transform var(--transition);
}
@media (hover: hover) {
    .model-group-card:hover .model-group-card-chevron {
        opacity: 1;
        transform: translateX(2px);
    }
}

/* Flyout Popover (desktop only, fixed-position portal outside modal) */
.model-flyout {
    contain: layout style;
    position: fixed;
    /* Let the flex rows determine the width from names, badges and prices. */
    width: max-content;
    max-width: calc(100vw - 1rem);
    /* Дизайн-максимум 24rem, но не выше вьюпорта (−1rem на отступы сверху/снизу):
       длинный список групп скроллится внутри .model-flyout-scroll. Раньше этот
       клампинг считался в JS — теперь живёт в CSS, JS позицию не трогает. */
    max-height: min(24rem, calc(100vh - 1rem));
    overflow: hidden;
    padding: 0.25rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    z-index: calc(var(--z-modal) + 1);
    pointer-events: auto;
    display: flex;
    flex-direction: column;
}
.model-flyout-scroll {
    padding-block: var(--scroll-edge-size);
    flex: 1;
    overflow-y: auto;
    overscroll-behavior-y: none;
    min-height: 0;
    /* The renderer owns row offsets; anchoring to a recycled node would move
       the viewport when that same node receives another model. */
    overflow-anchor: none;
}
.model-flyout [data-motion-list] { position: relative; }
.model-flyout-show-all {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: var(--gap-xs);
    flex-shrink: 0;
    padding: var(--gap-sm);
    border: 0;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-caption);
    cursor: pointer;
}
.model-flyout-content {
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
    width: max-content;
    max-width: calc(100vw - 1.5rem);
    max-height: min(23.5rem, calc(100vh - 1.5rem));
    min-height: 0;
}
.model-modal__search {
    transition: max-height var(--motion-duration-base) var(--motion-ease-premium),
                margin-bottom var(--motion-duration-base) var(--motion-ease-premium),
                opacity var(--motion-duration-fast) var(--motion-ease-standard);
}
@media (prefers-reduced-motion: reduce) {
    .model-modal .model-modal__search,
    .model-modal .model-modal__slide--root { transition: none; }
}
.model-flyout-show-all:hover { background: var(--bg-hover); color: var(--text-main); }
.model-flyout .model-popular-info {
    flex: 1 1 auto;
}
.model-flyout .model-popular-card {
    /* Windowed list geometry is shared with ModelListService.geometry().
       Fixed two-line rows keep the scroll range stable, including large text. */
    block-size: calc(3.5rem * max(1, var(--font-scale)));
}
@media (max-width: 639px) {
    .model-flyout { display: none !important; }
}

.model-modal {
    isolation: isolate;
    background: var(--chat-input-solid);
}

/* Natural content sizes the panel up to its CSS cap. Flex allocates the visible
   scroll area; the push slide shares that area without resizing the root slide. */
.model-modal__stage {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.model-modal__slide {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
/* Push-слайд — абсолютно поверх root'а. Root не прячется через
   display:none (иначе stage коллапсит до 0), а уезжает влево +
   opacity:0 через is-pushed. На десктопе push скрыт sm:hidden. */
.model-modal__slide--push {
    position: absolute;
    inset: 0;
}
.model-modal__slide--root {
    transition: transform var(--motion-duration-fast) var(--motion-ease-exit),
                opacity var(--motion-duration-fast) var(--motion-ease-exit);
}
.model-modal__slide--root.is-pushed {
    transition-duration: var(--motion-duration-base);
    transition-timing-function: var(--motion-ease-premium);
    transform: translateX(-8%);
    opacity: 0;
    pointer-events: none;
}
.model-modal__scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior-y: none;
    overflow-anchor: none;
    padding-bottom: calc(var(--floating-tray-height, 6rem) + var(--gap-sm));
    scroll-padding-bottom: calc(var(--floating-tray-height, 6rem) + var(--gap-sm));
}

/* Внутренние элементы push-слайда (header/back/icon/title). Bg-фон самой
   push-вьюхи нет: она живёт в общей стеклянной поверхности .model-modal
   через __slide--push, без отдельного --bg-panel-слоя поверх root'а. */
.model-modal__push-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    flex-shrink: 0;
}
/* Круглая стеклянная кнопка «назад» в детальных видах модалок (список моделей,
   коннекторы) — как у кнопки прокрутки чата (.scroll-to-bottom-btn):
   --shell-header-slot + chat-input-bg + glass-blur + shadow-glass. */
.model-modal__push-back,
.modal-header-back {
    width: var(--shell-header-slot);
    height: var(--shell-header-slot);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: var(--surface-active);
    box-shadow: var(--shadow-glass);
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    transition: background-color var(--transition), color var(--transition);
}
@media (hover: hover) {
    .model-modal__push-back:hover,
    .modal-header-back:hover {
        background-color: var(--bg-hover);
        color: var(--text-main);
    }
}
.composer-model-selector {
    height: 2.5rem;
    padding-inline-start: 0.875rem;
    padding-inline-end: 1.125rem;
    gap: 0.5rem;
    font-size: var(--text-sm);
}

.composer-model-selector .model-chip-icon {
    width: 1.3125rem;
    height: 1.3125rem;
}

.composer-model-selector__name {
    min-width: 0;
    max-width: 12rem;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-display);
}

@media (max-width: 1099.98px) {
    .composer-model-selector {
        padding-inline-start: 0.75rem;
        padding-inline-end: 0.875rem;
        gap: 0.375rem;
    }

    .composer-model-selector .model-chip-icon {
        width: 1.1875rem;
        height: 1.1875rem;
    }

    .composer-model-selector__name {
        max-width: 10rem;
    }
}

/* Floating footer contract: only the inset tray paints a background. */
.floating-tray {
    position: absolute;
    inset: auto 0 0;
    z-index: 2;
    padding: var(--floating-tray-inset, var(--gap-sm));
    padding-bottom: max(var(--floating-tray-inset, var(--gap-sm)), var(--safe-area-bottom, 0px));
    pointer-events: none;
}
.floating-tray__stack { display: flex; flex-direction: column; gap: var(--gap-xs); }
.floating-tray__surface {
    background-color: var(--chat-input-solid);
    box-shadow: var(--shadow-glass);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    pointer-events: auto;
}

/* Model Category Tabs */
.model-category-tabs {
    display: flex;
    align-items: stretch;
    padding: var(--gap-xs);
    gap: var(--gap-2xs);
}
:root:not([data-theme="prism-light"]):not([data-theme="light"]) :is(.floating-tray__surface, .notif-push--details) {
    box-shadow: var(--shadow-lightbox);
}
.model-category-tab {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    padding: 0.5rem 0.25rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-semibold);
    color: var(--text-muted);
    text-decoration: none;
    transition: color var(--transition), background-color var(--transition);
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
}
.model-category-art {
    width: 1.75rem;
    height: 1.75rem;
    object-fit: contain;
    flex-shrink: 0;
}
@media (min-width: 640px) {
    .model-category-tab {
        gap: 0.3125rem;
        padding: 0.5rem 0.5rem;
        font-size: var(--text-xs);
    }
}
@media (hover: hover) {
    .model-category-tab:not(.model-category-tab-active):hover {
        color: var(--text-main);
        background-color: var(--bg-hover);
    }
}
.model-category-tab-active {
    color: var(--text-main);
    background-color: var(--surface-active);
}

/* Под-табы модалки (underline, без пузырька): «Нейросети / Инструменты» в разделе картинок.
   На всю ширину — каждый таб flex:1, текст по центру, подчёркивание под активным. */
.model-subtabs {
    display: flex;
    align-items: stretch;
    margin-bottom: var(--gap-sm);
    border-bottom: 0;
}
.model-subtab {
    flex: 1;
    text-align: center;
    padding: 0.5rem 0.25rem;
    margin-bottom: -1px; /* активный бордер перекрывает нижнюю линию контейнера */
    background: transparent;
    border: none;
    border-bottom: 0;
    color: var(--text-muted);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    cursor: pointer;
    transition: color var(--transition), border-color var(--transition);
}
.model-subtab:hover {
    color: var(--text-main);
}
.model-subtab--active {
    color: var(--text-main);
    border-bottom-color: transparent;
}

/* Payment Modal */
.payment-modal {
    background: var(--bg-panel);
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-modal);
}
@media (min-width: 640px) {
    .payment-modal {
        border-radius: var(--radius-lg);
        corner-shape: var(--corner-shape-surface);
    }
}

/* Платёжный iframe Т-Кассы — cross-origin фрейм; SDK сам отчитывает
   высоту своего <iframe> через postMessage('resize'), поэтому ВЛАДЕЛЕЦ
   размера — SDK, мы только даём ширину и срезаем углы. min-height тут
   создаёт пустое пространство при коротких шагах формы (OTP/3-DS) и
   дёргает лейаут на мобайле при изменениях высоты — не задаём. */
.payment-iframe {
    width: 100%;
    border: 0;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
}
@media (max-width: 639px) {
    /* На мобайле — шторка во весь экран минус safe-area, без скруглений. */
    .payment-modal { max-height: 94vh; }
    .payment-iframe { border-radius: 0; }
}
.payment-flow-hero {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    padding: var(--gap-sm) 0;
    background: transparent;
    box-shadow: none;
    margin-bottom: calc(var(--gap-sm) * 2);
}
.payment-flow-copy {
    flex: 1;
    min-width: 0;
}
.payment-flow-kicker,
.payment-outcome-eyebrow {
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}
.payment-flow-kicker {
    margin-bottom: 0.35rem;
}
.payment-flow-title {
    font-family: var(--font-display);
    font-size: var(--text-card);
    line-height: var(--leading-none);
    color: var(--text-main);
}
.payment-flow-caption {
    margin-top: 0.25rem;
    font-size: var(--text-body);
    line-height: var(--leading-normal);
    color: var(--text-muted);
}
.payment-flow-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.45rem 0.75rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    white-space: nowrap;
}
.payment-amount-shell,
.payment-outcome-card,
.payment-inline-toggle,
.payment-method-card,
.payment-status-card {
    background: color-mix(in srgb, var(--bg-panel) 42%, var(--bg-elevated));
}

.payment-amount-shell,
.payment-inline-toggle,
.payment-method-card,
.payment-status-card {
    box-shadow: none;
}
.payment-amount-shell,
.payment-outcome-card {
    padding: 0.85rem;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
}
.payment-amount-label {
    font-size: var(--text-label);
    color: var(--text-muted);
    letter-spacing: var(--tracking-normal);
}
.payment-amount-controls {
    display: grid;
    container-type: inline-size;
    grid-template-columns: 2.75rem minmax(0, 1fr) 2.75rem;
    align-items: center;
    gap: var(--gap-sm);
    margin-top: calc(var(--gap-sm) * 1.5);
}
.payment-amount-step {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    padding: 0;
    border: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-active);
    color: var(--text-main);
    font-size: var(--text-2xl);
    line-height: var(--leading-none);
    cursor: pointer;
    transition: background-color var(--transition-fast), transform var(--transition-fast);
}
.payment-amount-step:disabled {
    color: var(--text-subtle);
    background: var(--surface-soft);
    cursor: default;
}
.payment-amount-step:focus-visible,
.payment-amount-input:focus-visible {
    outline: 2px solid var(--primary-500);
    outline-offset: 3px;
}
@media (hover: hover) {
    .payment-amount-step:hover:not(:disabled) {
        background: var(--surface-strong);
    }
}
.payment-amount-step:active:not(:disabled) {
    transform: scale(0.96);
}
.payment-amount-input {
    flex: 0 1 auto;
    width: 3ch;
    min-width: 1ch;
    max-width: 100%;
    padding: 0;
    margin: 0;
    border: 0;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    background: transparent;
    font: inherit;
    font-variant-numeric: lining-nums tabular-nums;
    text-align: right;
    color: var(--text-main);
}
.payment-quick-amounts {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.45rem;
    margin-top: 0.75rem;
}
.payment-quick-amount {
    padding: 0.48rem 0.8rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: color-mix(in srgb, var(--bg-panel) 42%, var(--bg-elevated));
    color: var(--text-main);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    transition: background-color var(--transition), color var(--transition), transform var(--transition-fast);
}
@media (hover: hover) {
    .payment-quick-amount:hover {
        transform: translateY(-1px);
        background: var(--surface-strong);
    }
}
.payment-quick-amount.is-active {
    background: var(--primary-500);
    color: var(--text-inverse);
    box-shadow: var(--shadow-surface);
}
.payment-outcome-card {
    margin-top: 0.85rem;
}
.payment-outcome-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
    margin-top: 0.6rem;
}
.payment-outcome-item {
    padding: 0.72rem 0.78rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: color-mix(in srgb, var(--bg-elevated) 66%, transparent);
}
.payment-outcome-label {
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    margin-bottom: 0.3rem;
}
.payment-outcome-value {
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
}

/* Scrollable source/tool rail; model and submission stay visible beside it. */
.composer-toolbar { display: flex; align-items: center; gap: var(--gap-xs); min-width: 0; }
.composer-toolbar__viewport { flex: 1 1 0; min-width: 0; }
.composer-scroll-hint-host { position: relative; min-width: 0; }
.composer-scroll-hint { display: none; }
@media (max-width: 767px) {
    .composer-scroll-hint:not([hidden]) {
        position: absolute;
        top: 50%;
        z-index: 2;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 1.25rem;
        height: 2.25rem;
        padding: 0;
        border: 0;
        background: none;
        color: var(--text-main);
        transform: translateY(-50%);
        pointer-events: none;
    }
    .composer-scroll-hint--right { right: 0; --hint-direction: 1; }
    .composer-scroll-hint--left { left: 0; --hint-direction: -1; }
    .composer-scroll-hint i { font-size: 1rem; opacity: 0.6; animation: composer-scroll-nudge var(--motion-period-hint) var(--motion-ease-ambient) infinite var(--pane-ambient-play-state, running); }
}
@keyframes composer-scroll-nudge {
    0%, 100% { transform: translateX(calc(var(--hint-direction) * -1px)); opacity: 0.35; }
    50% { transform: translateX(calc(var(--hint-direction) * 2px)); opacity: 0.7; }
}
@media (prefers-reduced-motion: reduce) {
    .composer-scroll-hint i { animation: none; }
}
.composer-toolbar__rail {
    flex: 1 1 0;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;

    cursor: grab;
    scroll-padding-inline: var(--composer-rail-fade);
}

.composer-toolbar__rail.is-grabbing { cursor: grabbing; user-select: none; }
.composer-toolbar__rail:focus-visible { outline: 2px solid var(--primary-500); outline-offset: -2px; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.composer-toolbar__track { display: flex; align-items: center; gap: var(--gap-xs); width: max-content; min-width: 100%; }
.composer-toolbar__track > * { flex: 0 0 auto; }
.composer-toolbar__rail[data-fade="right"] { mask-image: linear-gradient(to right, #000 calc(100% - var(--composer-rail-fade)), transparent); }
.composer-toolbar__rail[data-fade="left"] { mask-image: linear-gradient(to right, transparent, #000 var(--composer-rail-fade)); }
.composer-toolbar__rail[data-fade="both"] { mask-image: linear-gradient(to right, transparent, #000 var(--composer-rail-fade), #000 calc(100% - var(--composer-rail-fade)), transparent); }
.composer-toolbar__fixed { display: flex; align-items: center; justify-content: flex-end; gap: var(--gap-xs); flex: 0 0 auto; max-width: 50%; min-width: 0; position: relative; z-index: 1; }
.composer-toolbar__fixed > .btn { flex-shrink: 0; }
.composer-toolbar__fixed .composer-model-selector { flex-shrink: 1; min-width: 0; max-width: 100%; }
.composer-toolbar__fixed .composer-model-selector__name { min-width: 0; }

/* Advanced music keeps one primary action in the dock. The clear control keeps
   its shape while its negative margin releases space to the submit button. */
.music-toolbar--advanced > .composer-toolbar__viewport { display: none; }
@media (max-width: 1099.98px) {
    .music-toolbar--advanced > .composer-toolbar__viewport {
        display: block;
        flex: 0 0 var(--composer-control-size);
    }
}
.music-toolbar--advanced > .composer-toolbar__fixed {
    flex: 1 1 0;
    max-width: none;
    gap: 0;
}
.music-toolbar--advanced .composer-submit {
    flex: 1 1 0;
    width: auto;
    min-width: 0;
    gap: var(--gap-sm);
}
.music-composer-clear {
    flex: 0 0 var(--composer-control-size);
    width: var(--composer-control-size);
    height: var(--composer-control-size);
    padding: 0;
    margin-inline-start: calc(-1 * var(--composer-control-size));
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: scale(var(--motion-scale-surface));
    transition: margin-inline-start var(--transition-fast),
                opacity var(--transition-fast), transform var(--transition-fast),
                visibility 0s var(--motion-duration-fast);
}
.music-composer-clear.is-visible {
    margin-inline-start: var(--gap-xs);
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: none;
    transition-delay: 0s;
}
@media (prefers-reduced-motion: reduce) {
    .music-composer-clear { transition: none; }
}
.composer-toolbar__track .media-frame-strip {
    --upload-source-width: var(--composer-source-width);
    --upload-source-height: var(--composer-control-size);
    --upload-source-art-size: calc(var(--gap-sm) * 3);
    flex-wrap: nowrap;
    max-width: none;
    padding: 0;
    gap: var(--gap-xs);
}
.composer-toolbar__track .btn { flex-shrink: 0; }
.payment-summary { background: transparent; padding: var(--gap-sm) 0 0; border-radius: 0; }
.payment-summary .payment-outcome-grid { display: flex; flex-direction: column; gap: var(--gap-sm); margin: 0; }
.payment-summary .payment-outcome-item { display: flex; align-items: baseline; justify-content: space-between; gap: var(--gap-sm); padding: 0; background: transparent; border-radius: 0; }
.payment-summary .payment-outcome-label { font-size: var(--text-caption); text-transform: none; letter-spacing: var(--tracking-normal); margin: 0; }
.payment-summary .payment-outcome-value { font-size: var(--text-caption); font-weight: var(--font-weight-medium); text-align: right; }
.payment-inline-toggle {
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    padding: 0.85rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    cursor: pointer;
}
.payment-method-card {
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
    transition: background-color var(--transition), box-shadow var(--transition), transform var(--transition-fast);
}
@media (hover: hover) {
    .payment-method-card:hover:not(:disabled) {
        background: var(--surface-strong);
        box-shadow: var(--shadow-surface);
    }
}
/* Идёт создание платежа: гасим карточку и убираем hover-эффект,
   курсор-прогресс сигналит, что запрос в работе. */
.payment-method-card:disabled {
    opacity: 0.55;
    cursor: progress;
    box-shadow: none;
}
/* Выбранный способ автосписания (bind_setup) и основная кнопка оплаты
   сохранённым способом «в один клик» — одинаковая primary-подсветка. */
.payment-method-card.is-active,
.payment-method-card-primary {
    background: color-mix(in srgb, var(--primary-10) 70%, var(--bg-elevated));
    box-shadow: none;
}
.payment-status-card {
    padding: 1rem;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
}
.payment-status-card-blocked {
    background: linear-gradient(180deg, color-mix(in srgb, var(--bg-elevated) 94%, var(--primary-10)) 0%, var(--bg-elevated) 100%);
}
.payment-state-icon {
    width: 3rem;
    height: 3rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: color-mix(in srgb, var(--bg-raised) 86%, transparent);
}
.payment-note {
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: var(--leading-normal);
    text-align: center;
}
@media (max-width: 640px) {
    .payment-flow-hero {
        flex-direction: column;
        border-radius: var(--radius-xl);
        corner-shape: var(--corner-shape-surface);
    }

    .payment-flow-badge {
        align-self: flex-start;
    }

    .payment-outcome-grid {
        grid-template-columns: 1fr;
    }

    .payment-amount-shell,
    .payment-status-card {
        border-radius: var(--radius-xl);
        corner-shape: var(--corner-shape-surface);
    }
}
/* === Автоплатежи: поля порога/суммы, привязка карты/СБП === */
.autopay-body {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    /* Те же внутренние отступы, что у .profile-info-row — контент не
       прилипает к краям карточки и выровнен с рядами выше. */
    padding: 0.85rem 1.25rem;
}
/* Ряд способа автосписания: инфо слева (вертикальный стек), «Настроить»
   справа. Квалифицируем .profile-info-row — иначе его flex-direction:column
   (объявлен ниже по файлу) перебил бы row. Управление — только в модале. */
.profile-info-row.autopay-method-row {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}
.autopay-method-info {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
/* Компактная pill-кнопка (НЕ profile-secondary-btn: та на мобайле width:100%). */
.autopay-configure-btn {
    flex-shrink: 0;
    padding: 0.5rem 0.9rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: color-mix(in srgb, var(--bg-panel) 42%, var(--bg-elevated));
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    white-space: nowrap;
}
@media (hover: hover) {
    .autopay-configure-btn:hover { background-color: var(--bg-hover); }
}
/* Вложенный блок деталей опции «Автопополнение» (поля порога/суммы + сноски).
   Отступ сверху отделяет его от галочки/панели выше (раньше прилегал вплотную),
   лёгкий левый отступ показывает вложенность; ритм — едиными токенами. */
.autopay-fields-group {
    margin-top: var(--gap-sm);
    padding-left: var(--gap-sm);
    display: flex;
    flex-direction: column;
    gap: var(--gap-sm);
}
.autopay-fields {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--gap-sm);
}
.autopay-field {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    min-width: 0;
}
.autopay-field-label {
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}
.autopay-input-wrap {
    position: relative;
    display: flex;
    align-items: center;
}
.autopay-input {
    width: 100%;
    min-width: 0;
    padding: 0.6rem 1.9rem 0.6rem 0.75rem; /* справа место под знак ₽ */
    background: var(--bg-input);
    color: var(--text-main);
    border: 0;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    font-size: var(--text-base);
    font-weight: var(--font-weight-semibold);
    transition: border-color var(--transition), box-shadow var(--transition), opacity var(--transition);
}
.autopay-input:focus {
    outline: none;
    border-color: transparent;
    box-shadow: none;
}
.autopay-input:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}
.autopay-input-suffix {
    position: absolute;
    right: 0.7rem;
    font-size: var(--text-sm);
    color: var(--text-subtle);
    pointer-events: none;
}
.autopay-actions {
    display: flex;
    gap: 0.6rem;
}
.autopay-actions .btn { flex: 1 1 0; }
@media (max-width: 480px) {
    .autopay-fields { grid-template-columns: 1fr; }
    .autopay-actions { flex-direction: column; }
}

/* Status Tokens */
.success-pill { color: var(--text-main); background-color: var(--surface-soft); }

/* Payment method icons */
/* Converts black SVG to neutral --text-muted color */
.payment-card-icon {
    filter: brightness(0) invert(0.65);
}

/* Base row-style items (dropdown entries) */
.dropdown-item {
    width: 100%;
    min-height: 2.375rem;
    padding: 0.4375rem 0.75rem;
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    /* Концентрично панели (--radius-lg) минус её padding. */
    border-radius: max(0px, calc(var(--radius-lg) - 0.25rem));
    corner-shape: var(--corner-shape-surface);
    transition: background-color var(--transition), color var(--transition), opacity var(--transition), filter var(--transition);
    text-align: left;
    color: var(--text-main);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
}

.dropdown-item.is-selected {
    background-color: var(--bg-hover);
}

@media (hover: hover) {
    .dropdown-item:hover { background-color: var(--bg-hover); }
}

/* Индикатор подменю (drill-down): шеврон вправо у пунктов-категорий. */
.dropdown-item__chevron {
    margin-left: auto;
    opacity: 0.45;
    font-size: 0.95em;
}

.dropdown-menu .dropdown-item > i,
.dropdown-menu .dropdown-item > .dropdown-item-glyph,
.mention-item-icon {
    width: 1.75rem;
    height: 1.75rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: var(--bg-input);
    overflow: hidden;
    font-size: var(--text-sm);
}

.dropdown-menu .dropdown-item > i {
    color: var(--text-main);
}

/* Бренд-иконка коннектора (фирменный SVG) — в пилах, пунктах меню и «+»-листе.
   `.connector-glyph` (img) рендерится через x-html; контейнер задаёт размер бокса. */
.connector-glyph {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}
.connector-pill-glyph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 1.25rem;
    height: 1.25rem;
    font-size: var(--text-lg); /* размер Tabler-фоллбэка (text-lg) */
}
.dropdown-menu .dropdown-item > .dropdown-item-glyph > .connector-glyph {
    width: 70%;
    height: 70%;
}

/* Фирменная group-иконка модели (лого Suno и т.п.) в глифе пункта меню: масштаб
   до 70% — как у коннекторов, иначе SVG заполняет глиф БЕЗ отступов (у круглых
   лого вроде Suno особенно заметно). group.icon приходит как <span style="width:
   100%..."> — инлайн width перебиваем transform (не width/height). БЕЗ префикса
   .dropdown-menu: ctxMenu-портал не оборачивается в него (пункты в .contents от
   x-for). Единый механизм для всех меню моделей, без пер-пунктового хардкода. */
.dropdown-item-glyph > span,
.dropdown-item-glyph > svg {
    transform: scale(0.7);
}

.dropdown-menu .dropdown-item > i.dropdown-item__aspect-icon {
    position: relative;
    font-size: 0;
}

.dropdown-menu .dropdown-item > i.dropdown-item__aspect-icon::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--aspect-preview-width, 0.95rem);
    height: var(--aspect-preview-height, 0.95rem);
    transform: translate(-50%, -50%);
    border-radius: calc(0.18rem * var(--radius-scale));
    box-shadow: inset 0 0 0 1.5px currentColor;
}

.dropdown-menu .dropdown-item-danger > i {
    background-color: var(--surface-soft);
    color: var(--text-main);
}
@media (hover: hover) {
    .hover-danger-blur:hover,
    .danger-blur { background-color: var(--surface-soft); }
}

/* Chat error retry banner */
.chat-error-banner {
    background-color: var(--surface-soft);
}

/* Layout helpers */
.app-edge-gutters { padding-inline: var(--app-gutter-x); }

/* Плавный хендофф «чёлки» баннер→шапка: --app-safe-top интерполирует 0↔env за тот
   же тайминг, что max-height баннера (.global-announcement) — шапка всплывает без
   рывка вниз. @property делает кастом-проперти анимируемой; движки без @property её
   игнорируют → мгновенный флип (прежнее поведение, без регресса). */
@property --app-safe-top {
    syntax: '<length>';
    inherits: true;
    initial-value: 0px;
}

.app-root {
    --shell-mobile-header-offset: 0px;
    /* One content inset, measured from the visible header controls. The header's
       bottom padding is already empty space, so do not add it a second time. */
    --shell-content-top: calc(var(--shell-desktop-header-offset) - var(--shell-header-padding-block) + var(--shell-page-gap));
    /* «Хедерный» safe-area сверху: обычно системный inset, но при ОТКРЫТОМ
       баннере-объявлении → 0 (баннер in-flow сам съедает safe-area-top; иначе на
       iOS PWA двойной отступ сверху = баннер + хедер; на Android inset=0, баг скрыт). */
    --app-safe-top: env(safe-area-inset-top, 0px);
    /* Равный минимальный отступ плавающих композеров/плеера по бокам и снизу (mobile). */
    --composer-edge-gap: var(--app-gutter-x);
    --mobile-action-width: calc(var(--composer-control-size) * 8);
    --mobile-action-height: calc(var(--composer-control-size) + var(--gap-sm) * 3);
    --mobile-action-radius: calc(var(--mobile-action-height) / 2 * var(--radius-scale));
    --mobile-action-bg: var(--bg-panel);
    --mobile-action-lift: calc(var(--gap-sm) * 2);
    --mobile-action-bottom: calc(var(--composer-edge-gap) + var(--mobile-action-lift) + var(--composer-sab));
    /* Мягкий свет от края с обеих сторон, без контурной обводки. */
    --mobile-action-glow: inset 0 0 calc(var(--gap-sm) * 5) color-mix(in srgb, var(--primary-500) 32%, transparent),
        inset 0 0 calc(var(--gap-sm) * 2) color-mix(in srgb, var(--primary-500) 14%, transparent),
        var(--glow-accent-soft);
    /* The shell already ends above the keyboard. A second keyboard/safe-area
       inset would lift the composer twice and leave an empty bottom strip. */
    --composer-sab: 0px;
    /* The header changes only at the collapse/expand thresholds. CSS owns the
       transition; steady scrolling does not update an inherited progress value. */
    --hm: 0;
    /* Длительность плавного схлопывания шапки (гасится при prefers-reduced-motion). */
    --shell-morph-dur: var(--motion-duration-shell);
}
/* Схлопнутое состояние — конечный морф целиком (ShellHeaderService ставит класс на
   первом движении вниз, снимает у самого верха). Переход анимируют transition'ы. */
.app-root.is-shell-collapsed { --hm: 1; }

@media (prefers-reduced-motion: reduce) {
    .app-root { --shell-morph-dur: 1ms; }
}

/* Баннер-объявление in-flow уже отступил на safe-area-top → хедер НЕ добавляет его
   повторно (иначе двойной верхний отступ на iOS PWA). */
body[data-announcement-open="1"] .app-root {
    --app-safe-top: 0px;
}

/* Транзишн включаем только после первичной отрисовки (класс ставит announcement.js
   через 2×rAF), иначе стартовый флип env→0 при открытии баннера анимировался бы на
   загрузке. Дальше — плавный хендофф при закрытии баннера пользователем. */
body.announcement-ready .app-root {
    transition: --app-safe-top var(--motion-duration-base) var(--motion-ease-standard);
}

@media (max-width: 767.98px) {
    .app-root {
        --shell-page-gutter: var(--shell-mobile-gutter);
        --app-gutter-x: var(--shell-page-gutter);
        /* The measured host includes its bottom padding. Reserve one page gap
           from the visible controls, as on desktop, without counting it twice. */
        --shell-content-top: calc(var(--shell-mobile-header-offset) - var(--gap-sm) + var(--shell-page-gap));
    }
    /* Fixed app viewports scroll inside their pages. Do not reserve an empty
       desktop scrollbar beside the whole mobile shell. */
    html, body { scrollbar-gutter: auto; }

    .app-root .chat-messages-list,
    .app-root .transcribe-thread-content,
    .app-root .sidebar-section-pad {
        padding-inline: var(--shell-page-gutter);
    }
    .app-root .tg-panel-list {
        padding-top: var(--shell-content-top);
    }
    .app-root .tg-panel-header > .shell-history-search {
        padding-top: 0;
        padding-inline: var(--shell-page-gutter);
        padding-bottom: var(--shell-page-gap);
    }
    .app-root .tg-panel-list > .shell-history-content {
        padding-top: 0;
        padding-inline: var(--shell-page-gutter);
    }
    .app-root .transcribe-sidebar__list {
        --scroll-edge-space-start: var(--shell-content-top);
        padding-top: var(--shell-content-top);
        padding-inline: var(--shell-page-gutter);
    }
    .app-root .music-mobile-shell .sidebar-history-fade,
    .app-root .media-page.is-mobile-feed .media-mobile-history .sidebar-history-fade,
    .app-root .generation-result-area {
        padding-top: var(--shell-content-top);
    }
    .app-root .sidebar-generation-feed { margin-top: 0; }
    .app-root .builder-page.builder-page {
        padding-top: var(--shell-content-top);
        padding-inline: var(--shell-page-gutter);
    }
    .app-root .wf-start-screen {
        padding-top: var(--shell-content-top);
        padding-inline: var(--shell-page-gutter);
    }
    .app-root .media-empty-state { padding-inline: var(--shell-page-gutter); }
    .app-root .profile-page { max-width: none; }
    .app-root .support-page :is(.sup-scroll, .sup-intro) {
        padding-inline: var(--shell-page-gutter);
    }
    .app-root .support-page .sup-chat__head--user {
        padding: 0 var(--shell-page-gutter) var(--shell-page-gap);
    }
    .app-root[data-page-key='chat'],
    .app-root[data-page-key='profile'],
    .app-root[data-page-key='prices'] {
        --shell-mobile-header-offset: calc(var(--app-safe-top) + 3.65rem);
    }

    .app-root[data-page-key='home'],
    .app-root[data-page-key='image'],
    .app-root[data-page-key='video'],
    .app-root[data-page-key='music'] {
        --shell-mobile-header-offset: calc(var(--app-safe-top) + 6.9rem);
    }

    .app-root[data-page-key='chats'],
    .app-root[data-page-key='workflows'],
    .app-root[data-page-key='transcription'] {
        --shell-mobile-header-offset: calc(var(--app-safe-top) + 6.9rem);
    }

    /* Открытый редактор сценариев: полный shell-хедер сменяется компактным
       баром (_mobile_wf_header) — оффсет как у chat/prices/profile. */
    .app-root[data-page-key='workflows']:has(.wf-sidebar--editor-open) {
        --shell-mobile-header-offset: calc(var(--app-safe-top) + 3.65rem);
    }

    /* Музыка: открытый композер-экран «Новый трек» — полный shell-хедер
       сменяется компактным баром (_mobile_music_header), оффсет как у чата. */
    /* Компактный бар показан только когда композер + ЕСТЬ треки (is-music-compact-hdr).
       Пустой композер оставляет полный shell-хедер → офсет 6.9rem (дефолт), не 3.65. */
    .app-root[data-page-key='music']:has(.media-page.is-music-compact-hdr) {
        --shell-mobile-header-offset: calc(var(--app-safe-top) + 3.65rem);
    }

    /* Транскрипция: активный/сохранённый тред — компактный хедер (как chat).
       Стартовый composer без истории несёт data-mheader='shell' → дефолтный
       офсет полного shell-хедера (6.9rem) выше. */
    .app-root[data-page-key='transcription']:has(.transcribe-shell[data-mheader='thread']) {
        --shell-mobile-header-offset: calc(var(--app-safe-top) + 3.65rem);
    }
}

.app-with-overlay-header {
    padding-top: var(--shell-content-top);
}

.generation-result-area {
    padding-top: var(--shell-mobile-header-offset);
}

.generation-result-area {
    scroll-padding-bottom: calc(var(--input-height, 0px) + 1rem);
}

.chat-view-switching {
    visibility: hidden;
}

.page-container {
    max-width: var(--layout-max-width);
    margin: 0 auto;
    padding: var(--layout-pad-y) var(--app-gutter-x);
}

.page-container--pricing {
    max-width: 82rem;
    /* +safe-area снизу: карточки тарифов не режутся home-indicator'ом на iOS. */
    padding-bottom: calc(var(--layout-pad-y) + var(--safe-area-bottom, 0px));
}

/* The app scroller owns the header clearance; public pricing keeps its layout. */
.app-with-overlay-header > .page-container {
    padding-top: 0;
}

.hero-title {
    font-family: var(--font-display);
    font-weight: var(--font-weight-display);
    margin-bottom: 1rem;
    font-size: var(--text-3xl);
    background-image: var(--heading-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}
@media (min-width: 768px) {
    .hero-title { font-size: var(--text-4xl); }
}
.section-title { font-size: var(--text-title); font-family: var(--font-display); font-weight: var(--font-weight-display); color: var(--text-main); }
.section-subtitle { color: var(--text-muted); }

/* Sidebar shell */
.sidebar-shell {
    transition-property: transform, opacity, background-color, box-shadow;
    transition-duration: var(--motion-duration-base);
    transition-timing-function: var(--motion-ease-premium);
    /* Слой уже промоутится через translateZ(0) ниже — отдельный will-change избыточен. */
    transform: translateZ(0);
    backface-visibility: hidden;
    overflow: hidden;
}

.sidebar-section-pad {
    padding-inline: 0.75rem;
}

.sidebar-item-pad {
    padding-inline: 0.75rem;
}

.sidebar-history-list {
    display: flex;
    flex-direction: column;
    gap: 0.0625rem;
}

.sidebar-generation-feed {
    gap: var(--gap-sm);
    margin-top: var(--gap-sm);
    overflow: hidden;
    border-radius: 0 var(--radius-xl) var(--radius-xl) 0;
    corner-shape: var(--corner-shape-surface);
}

/* Stable masonry: CSS provides a normal grid fallback; JS positions tiles with an
   exact gap and keeps their column assignment while intrinsic media sizes arrive. */
.sidebar-generation-feed.is-image {
    --sidebar-gallery-min-column-width: 12rem;
    --sidebar-gallery-columns: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 12rem), 1fr));
    gap: var(--gap-sm);
    align-items: start;
}

.sidebar-generation-feed.is-image.is-masonry-mounted {
    position: relative;
    display: block;
}

.sidebar-generation-feed.is-image.is-masonry-mounted:not(.is-masonry-ready) {
    visibility: hidden;
}

.sidebar-generation-feed.is-image > .sidebar-generation-entry {
    min-width: 0;
    content-visibility: visible;
    contain-intrinsic-size: none;
}

.sidebar-generation-feed.is-image.is-masonry-mounted > .sidebar-generation-entry {
    position: absolute;
    margin: 0;
}

.sidebar-history-entry {
    padding-block: 0.125rem;
}

.sidebar-generation-entry {
    padding-block: 0;
    content-visibility: auto;
    contain-intrinsic-size: 17rem;
}

.app-root[data-page-category='image'] .sidebar-generation-entry {
    min-width: 0;
    contain-intrinsic-size: 15rem;
}

.sidebar-generation-preview {
    /* The feed owns its outer right corners; individual tiles stay square. */
    --generation-radius: 0px;
    position: relative;
    width: 100%;
    container-type: inline-size;
}

.sidebar-generation-preview-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: var(--bg-elevated);
    border-radius: inherit;
    corner-shape: inherit;
}

.sidebar-generation-media {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;

}

/* x-image-surface enables the backdrop after decode and clips object-fit
   margins. Opaque pixels cover it; unloaded/failed images have no checkerboard. */
.media-checkerboard.has-image-surface {
    --media-checker-size: 1.25rem;
    /* Raised and elevated are both white in the light theme; use the inset base. */
    background-color: var(--bg-input);
    background-image:
        linear-gradient(45deg, var(--bg-raised) 25%, transparent 25%, transparent 75%, var(--bg-raised) 75%),
        linear-gradient(45deg, var(--bg-raised) 25%, transparent 25%, transparent 75%, var(--bg-raised) 75%);
    background-size: var(--media-checker-size) var(--media-checker-size);
    background-position: 0 0, calc(var(--media-checker-size) / 2) calc(var(--media-checker-size) / 2);
    clip-path: var(--media-surface-clip, none);
}

/* Boot keeps geometry measurable while fonts, Alpine bindings and header slots
   settle. Only ShellMotion reveals the first frame and starts its entrances. */
.shell-booting #app-shell-root { opacity: 0; pointer-events: none; }
.shell-booting #app-shell-root *,
.shell-booting #app-shell-root *::before,
.shell-booting #app-shell-root *::after { transition: none !important; }

.sidebar-generation-preview-frame.is-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
}

.media-card-actions {
    position: absolute;
    top: var(--gap-sm);
    right: var(--gap-sm);
    display: flex;
    flex-direction: column;
    gap: var(--gap-sm);
    z-index: 1;
}
.media-card-actions > .media-card-action {
    position: relative;
    inset: auto;
    flex-shrink: 0;
}

.media-card-action {
    position: absolute;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    backdrop-filter: blur(var(--glass-blur));
    -webkit-backdrop-filter: blur(var(--glass-blur));
}

/* Крупные действия медиа-карточки (Отправить/Удалить) — общий примитив
   лент (/image, /video, сайдбар) и галереи главной: вертикальный столбик у
   правого верхнего края. */
.media-card-action {
    top: var(--gap-sm);
    right: var(--gap-sm);
    width: calc(var(--gap-sm) * 5.5);
    height: calc(var(--gap-sm) * 5.5);
    padding: 0;
    border: 0;
    border-radius: var(--media-action-radius);
    background: var(--media-action-bg);
    color: var(--media-action-text);
    box-shadow: var(--shadow-icon);
    opacity: 0;
    pointer-events: none;
    transition:
        opacity var(--motion-duration-base) var(--motion-ease-standard),
        color var(--motion-duration-base) var(--motion-ease-standard),
        background-color var(--motion-duration-base) var(--motion-ease-standard),
        transform var(--motion-duration-base) var(--motion-ease-standard);
}

.media-card-action i {
    font-size: var(--text-base);
}

/* Thumbnail controls must fit even a short landscape preview. */
.sidebar-generation-preview .media-card-actions {
    top: var(--gap-xs);
    right: var(--gap-xs);
    flex-direction: row;
    gap: var(--gap-xs);
}

.sidebar-generation-preview .media-card-action {
    width: clamp(1.75rem, 14cqw, 2rem);
    height: clamp(1.75rem, 14cqw, 2rem);
}

.sidebar-generation-preview .media-card-action i {
    font-size: 1rem;
    line-height: 1;
}

@media (pointer: coarse) {
    .sidebar-generation-preview .media-card-action {
        width: 2.75rem;
        height: 2.75rem;
    }
}

.media-card-action--download { top: auto; bottom: var(--gap-sm); }
.media-viewer__result-frame .media-card-action { opacity: 1; pointer-events: auto; }
.media-card-action:focus-visible { outline: 2px solid var(--media-action-text); outline-offset: 2px; opacity: 1; pointer-events: auto; }
@media (hover: hover) {
    .media-card-action:hover { background: var(--bg-raised); }
}

@media (hover: hover) {
    .sidebar-generation-entry:hover .media-card-action,
    .sidebar-generation-entry:focus-within .media-card-action {
        opacity: 1;
        pointer-events: auto;
    }

}

@media (hover: none) {
    .media-card-action {
        opacity: 1;
        pointer-events: auto;
    }
}

.sidebar-block + .sidebar-block {
    margin-top: 1rem;
}

.sidebar-nav {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}

/* Sidebar navigation items (section switcher) */
.sidebar-nav-item {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem 0.625rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    color: var(--text-muted);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    transition: background-color var(--transition), color var(--transition);
    cursor: pointer;
    text-decoration: none;
}
@media (hover: hover) {
    .sidebar-nav-item:hover { color: var(--text-main); }
}
.sidebar-nav-item.active { color: var(--text-main); font-weight: var(--font-weight-bold); }
.sidebar-nav-disabled { opacity: 0.4; pointer-events: none; cursor: default; }

.sidebar-nav-item > span {
    font-family: var(--font-sans);
    font-size: var(--text-lg);
    font-weight: var(--font-weight-regular);
    letter-spacing: var(--tracking-normal);
}

/* Shared desktop shell rail */
.shell-rail {
    --shell-rail-width: 12rem;
    --shell-rail-collapsed-width: 3.75rem;
    --shell-rail-slot-size: 2.25rem;
    --shell-rail-label-size: var(--text-base);
    width: var(--shell-rail-width);
    background: linear-gradient(
        180deg,
        color-mix(in srgb, var(--bg-panel) 92%, black) 0%,
        color-mix(in srgb, var(--bg-app) 70%, var(--bg-panel)) 100%
    );
    z-index: 12;
    overflow: visible;
}

[data-theme="light"] .shell-rail {
    background: var(--chat-input-bg);
}

.shell-rail.is-collapsed {
    width: var(--shell-rail-collapsed-width);
}

.shell-rail__header {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 0.5rem;
    padding-top: 1rem;
    padding-bottom: 1rem;
}

.shell-rail.is-collapsed .shell-rail__header {
    justify-content: center;
    padding-bottom: 1rem;
}

.shell-rail__face {
    width: 1.85rem;
    height: 1.85rem;
    flex-shrink: 0;
}

.shell-rail__logo {
    width: 100%;
    height: var(--shell-rail-slot-size);
    min-width: 0;
    flex: 1 1 auto;
    justify-content: flex-start;
}
.shell-rail__logo .brand-desktop {
    min-width: 0;
    flex-shrink: 1;
    overflow: hidden;
}
.shell-rail__logo .brand-desktop__name {
    transition: opacity var(--motion-duration-shell) var(--motion-ease-premium);
}
.shell-rail.is-collapsed .brand-desktop__name {
    opacity: 0;
}
@media (prefers-reduced-motion: reduce) {
    .shell-rail__logo .brand-desktop__name { transition: none; }
}

.shell-rail .sidebar-section-pad {
    padding-inline: 0.75rem;
}

.shell-rail .sidebar-block + .sidebar-block {
    margin-top: 0.625rem;
}

.shell-rail__nav {
    gap: 0.0625rem;
}

.shell-rail .sidebar-nav-item,
.shell-rail .sidebar-nav-disabled,
.shell-rail__profile-trigger {
    flex: none;
    width: 100%;
    min-height: var(--shell-rail-slot-size);
    margin-inline: 0;
    padding: 0.125rem 0.25rem;
    justify-content: flex-start;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
}

.shell-rail .sidebar-nav-item > span,
.shell-rail .sidebar-nav-disabled > span,
.shell-rail__profile-copy {
    display: block;
    line-height: var(--leading-snug);
}

.shell-rail .sidebar-nav-item i,
.shell-rail .sidebar-nav-disabled i,
.shell-rail__profile-trigger i {
    font-size: var(--text-base);
}

/* Align navigation icons with the logo and divider. */
.shell-rail__nav .sidebar-nav-item,
.shell-rail__nav .sidebar-nav-disabled {
    min-height: var(--shell-rail-slot-size);
    padding-left: 0;
}

.shell-rail .sidebar-nav-item > span,
.shell-rail .sidebar-nav-disabled > span {
    font-size: var(--shell-rail-label-size);
}

@media (min-width: 1100px) {
    .shell-rail__nav .sidebar-nav-item {
        min-height: calc(var(--gap-sm) * 4);
        gap: var(--gap-sm);
        padding-block: 0;
    }

    .shell-rail .shell-rail__nav .material-nav-icon {
        width: calc(var(--gap-sm) * 3);
        height: calc(var(--gap-sm) * 3);
        flex-basis: calc(var(--gap-sm) * 3);
    }
}

/* «Чаты» + плоская иконка «новый чат» справа (без контейнера). Видна в развёрнутом
   рейле (десктоп/средние экраны), скрыта в свёрнутом. */
.shell-rail-nav-row {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.shell-rail-nav-row .sidebar-nav-item {
    flex: 1;
    min-width: 0;
}

.shell-rail-nav-new {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: var(--shell-rail-slot-size);
    min-height: 1.875rem;
    color: var(--text-muted);
    cursor: pointer;
    transition: color var(--transition);
}

.shell-rail-nav-new i {
    font-size: var(--text-lg);
}

.shell-rail.is-collapsed .shell-rail-nav-new {
    display: none;
}

/* Свёрнутый рейл: «Чаты» снова центрированный квадрат-слот (без растяжения flex). */
.shell-rail.is-collapsed .shell-rail-nav-row {
    justify-content: center;
}

.shell-rail.is-collapsed .shell-rail-nav-row .sidebar-nav-item {
    flex: none;
}

.shell-rail.is-collapsed .sidebar-nav-item,
.shell-rail.is-collapsed .sidebar-nav-disabled,
.shell-rail.is-collapsed .shell-rail__profile-trigger {
    width: var(--shell-rail-slot-size);
    height: var(--shell-rail-slot-size);
    min-height: 0;
    margin-inline: auto;
    padding: 0;
    justify-content: center;
}

.shell-rail.is-collapsed .sidebar-nav-item > span,
.shell-rail.is-collapsed .sidebar-nav-disabled > span,
.shell-rail.is-collapsed .shell-rail__profile-copy {
    display: none;
}

.shell-rail .sidebar-nav-item.active,
.shell-rail__profile-trigger.active {
    color: var(--text-main);
    font-weight: var(--font-weight-bold);
    background-color: transparent;
    box-shadow: none;
}

.shell-rail__middle {
    display: flex;
    flex: 1;
    min-height: 0;
    flex-direction: column;
    padding-bottom: 0.375rem;
}

/* История страницы в slot рейла (shell-rail__middle). Одна разметка (иконка +
   __title) обслуживает оба состояния: средние экраны / развёрнутый рейл — с
   названием; свёрнутый десктоп-рейл (.is-collapsed) — только иконка (как подписи
   навигации скрываются). «+ Новый» закреплён сверху, список скроллится. */
.shell-rail-history {
    display: flex;
    flex: 1;
    min-height: 0;
    flex-direction: column;
    gap: 0.1875rem;
}

.shell-rail-history-list {
    display: flex;
    flex: 1;
    min-height: 0;
    flex-direction: column;
    gap: 0.0625rem;
    overflow-y: auto;
    padding: 0.0625rem 0;

}


.shell-rail-history-item,
.shell-rail-history-new {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    min-height: var(--shell-rail-slot-size);
    padding: 0.125rem 0.4375rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background-color: transparent;
    color: var(--text-muted);
    cursor: pointer;
    text-align: left;
    flex-shrink: 0;
}

.shell-rail-history-new {
    color: var(--text-main);
    transition: background-color var(--transition), color var(--transition);
}

.shell-rail-history-item.is-active {
    color: var(--text-main);
}

.shell-rail-history-item__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    flex-shrink: 0;
    overflow: hidden;
}

.shell-rail-history-item__icon svg {
    width: 1.25rem;
    height: 1.25rem;
}

.shell-rail-history-new .shell-rail-history-item__icon {
    color: var(--text-main);
}

.shell-rail-history-item__title {
    flex: 1;
    min-width: 0;
    font-size: var(--text-sm);
    line-height: var(--leading-none);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Свёрнутый десктоп-рейл: центрируем иконку в слот, прячем названия (зеркало
   правил навигации .shell-rail.is-collapsed .sidebar-nav-item). */
.shell-rail.is-collapsed .shell-rail-history-item,
.shell-rail.is-collapsed .shell-rail-history-new {
    width: var(--shell-rail-slot-size);
    margin-inline: auto;
    padding: 0;
    gap: 0;
    justify-content: center;
}

.shell-rail.is-collapsed .shell-rail-history-item__title {
    display: none;
}

/* Обёртка элемента истории: переключает строку ↔ инлайн-переименование. */
.shell-rail-history-row {
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
}

/* Три точки действий в элементе истории рейла (средние экраны / развёрнутый рейл).
   В свёрнутом icon-rail не рендерятся (гейт в шаблоне). */
.shell-rail-history-actions {
    display: flex;
    align-items: center;
    flex-shrink: 0;
}

.shell-rail-history-action-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.625rem;
    height: 1.625rem;
    flex-shrink: 0;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    color: var(--text-muted);
    transition: color var(--transition), background-color var(--transition);
}

/* Shared history surfaces: selection remains visible, hover adds emphasis. */
:is(.tg-chat-row, .music-row, .wf-side-item, .shell-rail-history-item) {
    transition: background-color var(--transition-hover), color var(--transition-hover);
}
.tg-chat-row,
.music-row { background-color: var(--bg-hover); }
:is(.tg-chat-row, .music-row, .wf-side-item, .shell-rail-history-item):is(.is-active, .is-playing, .is-selected) {
    background-color: var(--surface-active);
}
@media (hover: hover) {
    :is(.tg-chat-row, .music-row, .wf-side-item, .shell-rail-history-item):hover {
        background-color: var(--surface-strong);
    }
}
:is(.tg-chat-row, .music-row, .wf-side-item, .shell-rail-history-item):is(:focus-visible, :has(:focus-visible)) {
    background-color: var(--surface-strong);
}

/* History actions retain their hit area; only their reserved space collapses. */
[data-history-row] {
    --history-action-size: 1.75rem;
    --history-action-gap: calc(var(--gap-xs) * 2);
}
.shell-rail-history-item[data-history-row] {
    --history-action-size: 1.625rem;
    --history-action-gap: var(--gap-sm);
}
[data-history-row] > [data-history-actions] { flex-shrink: 0; }
@media (min-width: 1100px) and (hover: hover) and (pointer: fine) {
    [data-history-row] > [data-history-actions] {
        margin-inline-start: calc(-1 * (var(--history-action-size) + var(--history-action-gap)));
        opacity: 0;
        pointer-events: none;
        transition: margin-inline-start var(--motion-duration-fast) var(--motion-ease-premium),
                    opacity var(--transition-fast), color var(--transition), background-color var(--transition);
    }
    [data-history-row]:is(:hover, :focus-within, :has([aria-expanded="true"])) > [data-history-actions] {
        margin-inline-start: 0;
        opacity: 1;
        pointer-events: auto;
    }
}
@media (prefers-reduced-motion: reduce) {
    :is(.tg-chat-row, .music-row, .wf-side-item, .shell-rail-history-item),
    [data-history-row] > [data-history-actions] { transition: none; }
}

@media (hover: hover) {
    .shell-rail-history-action-btn:hover {
        color: var(--text-main);
        background-color: var(--bg-hover);
    }
}

/* Инлайн-переименование в рейле. */
.shell-rail-history-rename {
    padding: 0.125rem 0;
}
.shell-rail-history-rename__input {
    width: 100%;
    padding: 0.3125rem 0.5rem;
    font-size: var(--text-sm);
}

.shell-rail__footer {
    margin-top: auto;
    padding-bottom: 1rem;
    display: flex;
    flex-direction: column;
}

.shell-rail__footer .sidebar-block + .sidebar-block {
    margin-top: 0.875rem;
}

.shell-rail__socials {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

.shell-rail__social {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    flex: 0 0 auto;
    border: none;
    background: transparent;
    padding: 0;
    cursor: pointer;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    transition: opacity var(--transition);
}

.shell-rail__social-icon {
    display: block;
    width: 100%;
    height: 100%;
    background-color: var(--icon-default);
    -webkit-mask: var(--social-icon-url) center / contain no-repeat;
    mask: var(--social-icon-url) center / contain no-repeat;
    transition: background-color var(--transition);
}

.shell-rail__social:hover .shell-rail__social-icon {
    background-color: var(--icon-hover);
}

.shell-rail.is-collapsed .shell-rail__socials {
    display: none;
}

.shell-rail__copyright {
    font-size: var(--text-2xs);
    line-height: var(--leading-snug);
    color: var(--text-subtle);
}

.shell-rail.is-collapsed .shell-rail__copyright,
.shell-rail.is-collapsed .shell-rail__footer .sidebar-divider {
    display: none;
}

.shell-rail__profile-trigger {
    gap: 0.375rem;
    align-items: center;
    min-width: 0;
    background-color: color-mix(in srgb, var(--bg-elevated) 94%, var(--bg-panel));
    box-shadow: 0 0.75rem 2rem color-mix(in srgb, var(--bg-app) 45%, transparent);
    transition: background-color var(--transition), color var(--transition), box-shadow var(--transition);
}

.shell-rail__profile-copy {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0;
    min-width: 0;
}

.shell-rail__profile-label {
    display: block;
    font-size: var(--shell-rail-label-size);
    line-height: var(--leading-snug);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.shell-rail__profile-trigger.active {
    background-color: color-mix(in srgb, var(--bg-raised) 88%, var(--bg-elevated));
    box-shadow: 0 1rem 2.5rem color-mix(in srgb, var(--bg-app) 58%, transparent);
}

@media (hover: hover) {
    .shell-rail-history-item:hover { color: var(--text-main); }
    .shell-rail-history-new:hover {
        color: var(--text-main);
        background-color: var(--bg-hover);
    }

    .shell-rail-nav-new:hover {
        color: var(--text-main);
    }

    .shell-rail__profile-trigger:hover {
        color: var(--text-main);
    }
}

/* Sidebar divider */
.sidebar-divider {
    height: 1px;
    background-color: transparent;
    margin: 0;
    flex-shrink: 0;
}

/* Sidebar as a full-height panel flush to the left edge, rounded on the right only.
   No margin-top needed: app-div already starts below the in-flow announcement banner. */
@media (min-width: 768px) {
    .sidebar-shell.sidebar-inset {
        margin: 0;
        height: 100%;
        border-radius: 0 var(--radius-2xl) var(--radius-2xl) 0;
        corner-shape: var(--corner-shape-surface);
        box-shadow: var(--shadow-glass);
        overflow: hidden;
    }

    .shell-rail.sidebar-inset {
        overflow: visible;
    }

    .shell-rail.sidebar-inset.shell-rail-has-panel {
        border-radius: 0;
        box-shadow: none;
        border-right: 0;
    }
}

/* ══════════════════════════════════════════════════
   TELEGRAM-STYLE SIDEBAR (tg-*)
   Desktop: icon rail + history panel (side by side)
   Mobile: full-screen chat list
   ══════════════════════════════════════════════════ */

/* Container: flex row holding rail + panel */
.tg-sidebar {
    display: flex;
    flex-direction: row;
    height: 100%;
    flex-shrink: 0;
    z-index: 10;
    overflow: hidden;
}

/* Mobile: sidebar takes full width, is the "main" screen */
@media (max-width: 767.98px) {
    .tg-sidebar {
        width: 100%;
        flex-shrink: 1;
        min-width: 0;
    }

    /* Stack: list underneath, chat slides over it */
    .app-shell-body {
        position: relative;
        /* Both children are absolute — body needs explicit sizing */
        height: 100%;
        min-height: 0;
    }
    .tg-sidebar {
        position: absolute;
        inset: 0;
        z-index: 1;
    }
    .app-shell-body > .sidebar-page {
        position: absolute;
        inset: 0;
        z-index: 2;
    }

    /* Enable transition only after first paint (class added by JS) */
    .app-shell-body.mobile-nav-ready > .sidebar-page {
        transition: transform var(--motion-duration-base) var(--motion-ease-premium);
        will-change: transform;
    }

    /* List always stays in place */
    .tg-sidebar-mobile-hidden {
        visibility: hidden;
        pointer-events: none;
    }
    /* Chat hidden = off-screen right */
    .tg-content-hidden {
        transform: translateX(100%);
        pointer-events: none;
    }
}

/* Desktop: fixed-width sidebar */
@media (min-width: 768px) {
    .tg-sidebar {
        width: auto;
        overflow: visible;
    }
    /* Content area always visible on desktop */
    .tg-content-hidden {
        display: flex !important;
    }
}

/* Средние экраны (768–1099.98px): пристыкованная панель истории скрыта — история
   едет в slot рейла (shell-rail__middle). .transcribe-sidebar/.wf-sidebar несут
   утилиту .flex (tailwind грузится ПОСЛЕ styles.css), поэтому их display:none
   пишем двойным классом, чтобы выиграть тай-брейк каскада. */
@media (min-width: 768px) and (max-width: 1099.98px) {
    .tg-sidebar {
        display: none;
    }

    .transcribe-sidebar.shell-secondary-panel,
    .wf-sidebar.shell-secondary-panel {
        display: none;
    }
}

/* ── Shared secondary shell panels (chat history + media generations) ── */
.tg-panel,
.shell-secondary-panel {
    overflow: hidden;
    position: relative;
}

.shell-secondary-panel.sidebar-shell {
    background-color: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}

/* Glass background on pseudo-element so panel doesn't create containing block for fixed children */
.tg-panel::before,
.shell-secondary-panel::before {
    content: '';
    position: absolute;
    inset: 0;
    background-color: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    z-index: 0;
    border-radius: inherit;
    corner-shape: inherit;
}

.tg-panel > *,
.shell-secondary-panel > * {
    position: relative;
    z-index: 1;
}

@media (max-width: 767.98px) {
    .tg-panel {
        width: 100%;
    }
    /* Mobile: body paints --bg-app; the shell header owns the top edge gradient.
       Only the bounded controls retain glass. */
    .tg-panel::before,
    .shell-secondary-panel::before {
        content: none;
    }

    .tg-panel-header .surface-edge-fade--top {
        display: none;
    }
    /* Блюр-бэкдроп отключён на мобиле → sticky-хедер поиска должен быть
       НЕПРОЗРАЧНЫМ в тон фона сайдбара (--bg-app), иначе строки списка
       просвечивают сквозь поле и кнопки. */
    .tg-panel-header {
        background-color: var(--bg-app);
    }

    .tg-panel-list {
        padding-top: var(--shell-mobile-header-offset);
    }
}

@media (min-width: 768px) {
    .tg-panel,
    .shell-secondary-panel {
        width: var(--shell-secondary-panel-width);
        flex: 0 0 var(--shell-secondary-panel-width);
        border-radius: 0 var(--radius-2xl) var(--radius-2xl) 0;
        corner-shape: var(--corner-shape-surface);
        box-shadow: var(--shadow-glass);
    }
}

.app-root[data-shell-kind='media'] {
    --media-sidebar-width: 18rem;
}

/* Единый media-шелл (история + встроенная панель трека): ширина по содержимому
   (сумма колонок), а НЕ фикс 18rem из общего @media .shell-secondary-panel-правила.
   Двойная специфичность (0,2,0) бьёт то правило независимо от порядка. */
[data-media-sidebar-shell].shell-secondary-panel {
    width: auto;
    flex: 0 0 auto;
}

/* Ширина истории/панели анимируется при ПРОГРАММНОЙ смене (открытие/закрытие
   панели: syncLayout ужимает историю и растит панель до maxWidth). Полный список
   свойств переопределяет .sidebar-shell/.motion, добавляя width/flex-basis (идиома
   как у .chat-input-state-stack). is-resizing снимает транзишен на время drag'а —
   бегунок следует за курсором мгновенно, без инерции. */
[data-media-sidebar] {
    transition-property: transform, opacity, background-color, box-shadow, width, flex-basis;
    transition-duration: var(--motion-duration-base);
    transition-timing-function: var(--motion-ease-premium);
}
[data-media-sidebar].is-resizing {
    transition: none;
}

.media-sidebar-resize-zone {
    display: none;
    position: relative;
    flex: 0 0 var(--media-sidebar-resize-gap);
    width: var(--media-sidebar-resize-gap);
    align-items: center;
    justify-content: center;
    cursor: ew-resize;
    z-index: calc(var(--z-sidebar) + 1);
}

.media-sidebar-resize-zone::before {
    content: '';
    width: 0.25rem;
    height: 3rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--resize-handle-color);
    box-shadow: none;
    transition:
        background-color var(--motion-duration-fast) var(--motion-ease-standard),
        box-shadow var(--motion-duration-fast) var(--motion-ease-standard);
}

@media (hover: hover) {
    .media-sidebar-resize-zone:hover::before {
        background: var(--resize-handle-hover-color);
        box-shadow: none;
    }
}

.media-sidebar-resize-zone.is-active::before {
    background: var(--resize-handle-active-color);
    box-shadow: none;
}

/* Внешний ползунок — сиблинг стеклянного шелла; обёртка резервирует место для него.
   Отрицательный left-margin в полгапа сажает пилюлю ровно на правую кромку панели
   (наполовину над стеклом, наполовину в зазоре) — «снаружи», без обрезки скруглением. */
.media-sidebar-resize-zone--outer {
    margin-left: calc(var(--media-sidebar-resize-gap) / -2);
}

@media (min-width: 1100px) {
    .app-root[data-shell-kind='media'] {
        --shell-secondary-panel-width: var(--media-sidebar-width);
    }

    .media-sidebar-resize-zone {
        display: flex;
    }

    /* Keep each panel's content at its final width while its outer box closes.
       CSS reverses interrupted transitions from the current frame; no remount,
       text wrapping or independent collapse timer is needed. */
    .app-root [data-shell-panel] {
        width: var(--shell-panel-width, var(--shell-secondary-panel-width));
        flex: 0 0 auto;
        min-width: 0;
        overflow: hidden;
    }

    .app-root .media-sidebar-shell-outer {
        width: calc(var(--shell-panel-width) + var(--media-sidebar-resize-gap) / 2);
    }

    .app-root :is(.transcribe-sidebar, .wf-sidebar)[data-shell-panel] > * {
        width: var(--shell-secondary-panel-width);
        min-width: var(--shell-secondary-panel-width);
    }

    .app-root .shell-rail,
    .app-root [data-shell-panel] {
        transition: none;
    }

    .app-root.shell-panels-ready .shell-rail,
    .app-root.shell-panels-ready [data-shell-panel] {
        transition: width var(--motion-duration-shell) var(--motion-ease-premium),
                    visibility 0s;
    }

    .app-root[data-shell-panels-collapsed='true'] [data-shell-panel] {
        width: 0;
        visibility: hidden;
        pointer-events: none;
        transition-delay: 0s, var(--motion-duration-shell);
    }

    .app-root.shell-panels-ready [data-shell-panel].is-resizing {
        transition: none;
    }

    /* Keep icons anchored while the rail changes width. Centering against the
       animated rail made them sweep sideways on every reversal. */
    .shell-rail.is-collapsed .shell-rail__header,
    .shell-rail.is-collapsed .shell-rail-nav-row {
        justify-content: flex-start;
    }

    .shell-rail.is-collapsed .sidebar-nav-item,
    .shell-rail.is-collapsed .sidebar-nav-disabled {
        margin-inline: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .app-root.shell-panels-ready .shell-rail,
    .app-root.shell-panels-ready [data-shell-panel] {
        transition: none;
    }
}

/* Panel header & footer — sticky with gradient-only edge fades. */
.tg-panel-header,
.tg-panel-footer {
    position: sticky;
    z-index: 20;
    flex-shrink: 0;
    background-color: transparent;
}
.tg-panel-header { top: 0; }
.tg-panel-footer {
    bottom: 0;
    padding-top: 2rem;
}

/* Edge shading never samples or blurs the content behind it. Glass belongs
   to the bounded control surfaces, not to the surrounding fade. */
.surface-edge-fade {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
}

.surface-edge-fade--top {
    background: var(--surface-fade-top-tint-gradient);
    opacity: var(--surface-fade-top-tint-opacity);
}

.surface-edge-fade--bottom {
    background: linear-gradient(to top, var(--surface-fade-top-tint-color) 20%, transparent 100%);
    opacity: var(--surface-fade-top-tint-opacity);
}

/* Mobile panel is transparent over body --bg-app — fade into that token
   so the bottom gradient stays tonally aligned with the page background. */
@media (max-width: 767.98px) {
    .surface-edge-fade--bottom {
        background: linear-gradient(to top, var(--bg-app) 20%, transparent 100%);
    }
}

/* Search and delete are bounded glass surfaces; the edge fade stays unfiltered. */
.tg-search-field { border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); }
/* Search field */
.tg-search-field input {
    /* The field owns its tint and focus ring; its rounded parent owns glass. */
    background-color: var(--bg-input);
    border: none;
    transition: background-color var(--transition), box-shadow var(--transition);
}
.tg-search-field input:focus {
    background-color: var(--bg-input);
    box-shadow: 0 0 0 2px var(--primary-20);
}

/* Search and history actions sit on glass; preserve light-theme surfaces. */
:root:not([data-theme="prism-light"]):not([data-theme="light"]) :is(
    .tg-search-field input, .tg-footer-search, .tg-history-clear, .tg-footer-icon-btn
) {
    background-color: var(--surface-soft);
}
:root:not([data-theme="prism-light"]):not([data-theme="light"]) :is(
    .tg-search-field input:focus, .tg-footer-search:focus-within,
    .tg-history-clear:active, .tg-footer-icon-btn:active, .tg-footer-icon-btn-active
) {
    background-color: var(--surface-active);
}
@media (hover: hover) {
    :root:not([data-theme="prism-light"]):not([data-theme="light"]) :is(
        .tg-history-clear:hover, .tg-footer-icon-btn:hover
    ) {
        background-color: var(--surface-strong);
    }
}

.tg-chat-icon {
    width: 2.75rem;
    height: 2.75rem;
    padding: 0.5rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--bg-elevated);
    color: var(--text-muted);
    flex-shrink: 0;
    overflow: hidden;
}
.tg-chat-icon svg {
    width: 100%;
    height: 100%;
}

/* ── Bottom Action Bar ── */
.tg-footer-bar {
    /* Матовое стекло: контейнер блюрит фон (по правилам — стекло на контейнере,
       вложенные контролы лишь тинтуют). На мобиле панельный ::before-блюр снят,
       поэтому бар обязан фростить сам. */
    background-color: var(--bg-hover);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    padding: 0.375rem;
}

.tg-footer-new-chat {
    height: 2.75rem;
    padding-inline: 1rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background-color: var(--primary-500);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 160px 160px, auto;
    background-blend-mode: overlay, normal;
    color: var(--primary-text);
    border: none;
    cursor: pointer;
    transition: filter var(--transition), transform var(--transition);
    white-space: nowrap;
}
@media (hover: hover) {
    .tg-footer-new-chat:hover { filter: saturate(1.08) brightness(1.03); }
}
.tg-footer-new-chat:active { transform: scale(0.97); }

@media (max-width: 767.98px) {
    /* Бар по содержимому и по центру; ширину ведёт ОДНА анимация — width поля поиска
       (бар как fit-content растёт следом). Без flex-grow на баре → без дёрганья. */
    .tg-footer-bar {
        width: fit-content;
        max-width: 100%;
        margin-inline: auto;
    }

    /* «Новый чат»: фикс. ширина (не растёт/не сжимается флексом) — чтобы плавно
       схлопываться до «+» при раскрытии поиска (width-анимация синхронна с полем).
       Двойной селектор обязателен: Tailwind .flex-1 (для десктопа) грузится ПОСЛЕ
       styles.css и при равной специфичности перебивал бы flex. */
    .tg-footer-bar .tg-footer-new-chat {
        flex: 0 0 auto;
        width: 7.8125rem; /* «+ Новый чат» — под фикс-метку, для плавного схлопа */
        gap: 0.5rem;
        padding-inline: 0.875rem;
        overflow: hidden;
        white-space: nowrap;
        transition: width var(--motion-duration-shell) var(--motion-ease-premium),
                    padding-inline var(--motion-duration-shell) var(--motion-ease-premium),
                    gap var(--motion-duration-shell) var(--motion-ease-premium);
    }
    /* Раскрытый поиск → кнопка схлопывается до «+» (иконки), отдавая ширину полю. */
    .tg-footer-bar .tg-footer-new-chat.is-compact {
        width: 2.75rem;
        padding-inline: 0;
        gap: 0;
    }

    /* Поиск и корзина переезжают в нижний бар (на десктопе они в шапке панели).
       Двойной селектор: базовое .tg-footer-search{display:none} объявлено ниже по
       файлу и при равной специфичности перебило бы display:flex (тай-брейк порядком). */
    .tg-footer-bar .tg-footer-search {
        display: flex;
    }
    .tg-footer-bar .tg-footer-trash {
        display: flex;
    }

    /* Поиск перенесён в нижний бар → верхнюю шапку-поиск прячем. */
    .tg-chat-search-header {
        display: none;
    }

    /* Временный и групповой чат на мобиле живут в шапке чата (_mobile_chat_header) —
       в подвале списка кнопки убираем, чтобы не дублировать. Двойной селектор:
       .tg-footer-icon-btn{display:flex} объявлен ниже по файлу и при равной
       специфичности перебил бы одиночный класс (тай-брейк по порядку). */
    .tg-footer-bar .tg-footer-temp-btn,
    .tg-footer-bar .tg-footer-group-btn {
        display: none;
    }
}

.tg-footer-icon-btn {
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    display: flex;
    align-items: center;
    justify-content: center;
    /* In-glass: полупрозрачный колодец-кнопка (--surface-dim), не сплошной --bg-input. */
    background-color: var(--surface-dim);
    color: var(--text-muted);
    border: none;
    cursor: pointer;
    flex-shrink: 0;
    transition: background-color var(--transition), color var(--transition);
}
@media (hover: hover) {
    .tg-footer-icon-btn:hover {
        background-color: var(--surface-strong);
        color: var(--text-main);
    }
}
.tg-footer-icon-btn-active {
    background-color: var(--surface-soft);
    color: var(--text-main);
}

/* ── Свёрнутый поиск в нижнем баре (мобайл) ──
   По умолчанию (десктоп) скрыт — поиск/корзина живут в шапке панели. На мобиле
   показывается (media-блок выше). Иконка → анимированно разворачивается в поле:
   ширину тянет .tg-footer-search, бар (width:fit-content) растёт следом; only this
   элемент flex-сжимается, поэтому занимает ровно остаток после корзины и «Новый чат». */
.tg-footer-search,
.tg-footer-trash {
    display: none;
}

.tg-footer-search {
    align-items: center;
    height: 2.75rem;
    flex: 0 0 auto; /* ширину задаём явным width (не флексом) — анимируется только она */
    width: 2.75rem; /* свёрнут — квадрат-иконка */
    min-width: 0;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    /* In-glass: полупрозрачный колодец (--surface-dim), не сплошной --bg-input. */
    background-color: var(--surface-dim);
    overflow: hidden;
    cursor: text;
    transition: width var(--motion-duration-shell) var(--motion-ease-premium);
}
.tg-footer-search.is-expanded {
    /* Раскрыт — занимает всё, кроме корзины (≈2.75rem), схлопнутой «+»-кнопки
       (≈2.75rem) и отступов. 9rem подобрано под эти фикс-элементы, чтобы ничего
       не переполнялось и поиск забирал максимум ширины. */
    width: calc(100vw - 9rem);
    cursor: default;
}
.tg-footer-search__icon {
    flex: 0 0 2.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    font-size: var(--text-lg);
}
.tg-footer-search__input {
    flex: 1 1 auto;
    min-width: 0;
    height: 100%;
    background: transparent;
    border: none;
    outline: none;
    color: var(--text-main);
    font-size: var(--text-sm);
    padding-right: 0.25rem;
}
.tg-footer-search__input::placeholder {
    color: var(--text-muted);
}
.tg-footer-search__clear {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2.75rem;
    color: var(--text-muted);
}
@media (hover: hover) {
    .tg-footer-search__clear:hover { color: var(--text-main); }
}

/* ── Результаты поиска по сообщениям (вместо списка чатов) ──
   Без «пузыря»-контейнера: плоская строка, подложка только на hover (десктоп). */
.tg-search-result {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    width: 100%;
    padding: 0.5rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background-color: transparent;
    text-align: left;
    cursor: pointer;
    transition: background-color var(--transition);
}
@media (hover: hover) {
    .tg-search-result:hover { background-color: var(--bg-hover); }
}
.tg-search-result__icon {
    flex: 0 0 1.75rem;
    width: 1.75rem;
    height: 1.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 0.125rem;
    color: var(--text-muted);
    overflow: hidden;
}
.tg-search-result__icon svg {
    width: 100%;
    height: 100%;
}
.tg-search-result__body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}
.tg-search-result__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.tg-search-result__title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tg-search-result__date {
    flex-shrink: 0;
    font-size: var(--text-xs);
    color: var(--text-subtle);
}
.tg-search-result__snippet {
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    color: var(--text-muted);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.msg-search-mark {
    background-color: var(--surface-soft);
    color: var(--text-main);
    border-radius: calc(0.25rem * var(--radius-scale));
    padding: 0 0.1rem;
}

/* Подсветка сообщения при переходе из результата поиска. */
.msg-search-highlight {
    animation: msgSearchPulse var(--motion-duration-highlight) var(--motion-ease-premium);
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
}
@keyframes msgSearchPulse {
    0%, 100% { background-color: transparent; box-shadow: none; }
    12%, 55% {
        background-color: var(--primary-10);
        box-shadow: 0 0 0 2px var(--primary-20);
    }
}

.chat-input-shell,
.shell-mobile-chat-header-btn,
.shell-desktop-header__toggle,
.shell-user-pill,
.shell-user-pill--standalone,
.shell-mini-player--desktop,
.shell-mini-player__bubble,
.shell-mini-player__dismiss,
.shell-tabs-frame {
    box-shadow: var(--shadow-glass);
    transform: translateZ(0);
    backface-visibility: hidden;
}

/* Header controls own geometry and interaction; their decorative ::before owns
   glass. Foreground content has its own stacking context above that surface. */
.shell-mobile-header-host :is(.shell-mobile-chat-header-btn, .shell-user-pill,
    .shell-user-pill--standalone, .shell-tabs-frame,
    .shell-mini-player__bubble, .shell-mini-player__dismiss) {
    position: relative;
    isolation: isolate;
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    transform: none;
    -webkit-backface-visibility: visible;
    backface-visibility: visible;
}
.shell-mobile-header-host :is(.shell-mobile-chat-header-btn, .shell-user-pill,
    .shell-user-pill--standalone, .shell-tabs-frame,
    .shell-mini-player__bubble, .shell-mini-player__dismiss)::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    corner-shape: inherit;
    background: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    pointer-events: none;
}
.shell-mobile-header-host :is(.shell-mobile-chat-header-btn, .shell-user-pill,
    .shell-user-pill--standalone, .shell-tabs-frame,
    .shell-mini-player__bubble, .shell-mini-player__dismiss) > :not(.shell-tabs-edge) {
    position: relative;
    z-index: 0;
}
.shell-mobile-header-host .shell-mobile-chat-header-btn-active::before {
    background: var(--surface-soft);
}
.shell-mobile-header-host .shell-mini-player__dismiss {
    position: absolute;
}

.system-modal-card {
    position: relative; /* якорь для .system-modal-close */
    width: min(92vw, 22.5rem);
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1.125rem;
    transform: translateZ(0);
    backface-visibility: hidden;
}

.music-track-settings { max-width: 54rem; }
.music-track-settings__workspace { display: grid; grid-template-columns: 14rem minmax(0, 1fr); flex: 1; min-height: 0; padding: 1.5rem; gap: 2rem; }
.music-track-settings__identity { min-width: 0; padding-top: .25rem; }
.music-track-settings__artwork { position: relative; margin-bottom: 1.75rem; }
.music-track-settings__preview { aspect-ratio: 1; overflow: hidden; display: grid; place-items: center; border-radius: var(--radius-xl); corner-shape: var(--corner-shape-surface); background: var(--surface-soft); color: var(--text-subtle); font-size: var(--text-5xl); box-shadow: var(--shadow-glass); }
.music-track-settings__preview img, .music-track-settings__choice img, .music-track-settings__art-tile img { width: 100%; height: 100%; object-fit: cover; }
.music-track-settings__cover-edit { position: absolute; bottom: .625rem; right: .625rem; display: grid; place-items: center; width: 2.25rem; height: 2.25rem; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); background: var(--overlay-backdrop); color: var(--overlay-text); font-size: var(--text-base); }
.music-track-settings__eyebrow { font-size: var(--text-2xs); letter-spacing: .14em; color: var(--text-subtle); }
.music-track-settings__identity h3 { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: var(--font-weight-semibold); line-height: 1.15; letter-spacing: -.025em; margin: .5rem 0 .75rem; overflow-wrap: anywhere; }
.music-track-settings__facts { display: flex; gap: .75rem; font-size: var(--text-xs); color: var(--text-muted); }
.music-track-settings__facts span + span::before { content: '·'; margin-right: .75rem; color: var(--text-subtle); }
.music-track-settings__quick-actions { display: flex; gap: .5rem; margin-top: 1.25rem; }
.music-track-settings__quick-actions .surface-chip { display: inline-flex; align-items: center; width: 2.5rem; height: 2.5rem; padding: 0; justify-content: center; font-size: var(--text-lg); }
.music-track-settings__main { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.music-track-settings__tabs { flex-shrink: 0; margin-bottom: 1.5rem; }
.music-track-settings__tabs .music-seg__btn { flex: 1; display: flex; align-items: center; justify-content: center; gap: .625rem; min-height: 2.75rem; white-space: nowrap; }
.music-track-settings__tab-art { width: 2rem; height: 2rem; flex-shrink: 0; object-fit: contain; opacity: .75; transition: opacity var(--transition-fast); }
.music-track-settings__tabs .active .music-track-settings__tab-art,
.music-track-settings__tabs button:hover .music-track-settings__tab-art { opacity: 1; }
.music-track-settings__body { min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 1.5rem; padding: 0 .25rem .75rem; height: 28rem; }
.music-track-settings__body:has(.music-track-settings__tool-grid) { height: min(40rem, calc(100dvh - 17rem)); }
.music-track-settings__section { display: flex; flex-direction: column; gap: 1.25rem; min-width: 0; }
.music-track-settings__heading h3 { font-size: var(--text-xl); letter-spacing: -.025em; font-weight: var(--font-weight-semibold); color: var(--text-main); line-height: 1.2; }
.music-track-settings__heading p { font-size: var(--text-xs); line-height: 1.5; color: var(--text-muted); margin-top: .5rem; }
.music-track-settings__title-field .music-field__input { font-size: var(--text-2xl); letter-spacing: -.03em; font-weight: var(--font-weight-medium); }
.music-track-settings .music-field__input { background: var(--surface-soft); border-radius: var(--radius-lg); corner-shape: var(--corner-shape-surface); padding: .75rem; }
.music-track-settings textarea.music-field__input { min-height: 5.5rem; resize: vertical; }
.music-track-settings__collection-head { display: flex; justify-content: space-between; align-items: center; gap: .5rem; margin-bottom: .5rem; }
.music-track-settings__choices { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .625rem; padding: .25rem; }
.music-track-settings__choice { position: relative; aspect-ratio: 1; overflow: hidden; border-radius: var(--radius-lg); corner-shape: var(--corner-shape-surface); }
.music-track-settings__choice[aria-pressed="true"] { outline: 2px solid var(--text-main); outline-offset: 2px; }
.music-track-settings__choice > .ti-check { position: absolute; bottom: .375rem; right: .375rem; background: var(--text-main); color: var(--text-inverse); border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); padding: .2rem; }
.music-track-settings__choice--create { font-size: var(--text-xs); line-height: var(--leading-tight); }
.music-track-settings__choice--create > i { font-size: var(--text-2xl); }
.music-track-settings__visual-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .875rem; }
.music-track-settings__feature { display: flex; flex-direction: column; min-width: 0; border-radius: var(--radius-xl); corner-shape: var(--corner-shape-surface); background: var(--surface-soft); padding: 1rem; }
.music-track-settings__visual-art { position: relative; height: 8.5rem; display: grid; place-items: center; isolation: isolate; }
.music-track-settings__art-tile { width: 6.25rem; height: 6.25rem; border-radius: var(--radius-lg); corner-shape: var(--corner-shape-surface); display: grid; place-items: center; position: relative; background: var(--bg-raised); color: var(--text-muted); box-shadow: var(--shadow-glass); }
.music-track-settings__art-tile img { border-radius: inherit; corner-shape: inherit; }
.music-track-settings__visual-art--cover .music-track-settings__art-tile { transform: rotate(-8deg); }
.music-track-settings__visual-art--cover::before { content: ''; position: absolute; width: 6.25rem; height: 6.25rem; border-radius: var(--radius-lg); corner-shape: var(--corner-shape-surface); transform: translate(.625rem, -.25rem) rotate(9deg); background: var(--surface-strong); }
.music-track-settings__art-tile > .ti { font-size: var(--text-3xl); }
.music-track-settings__art-badge { position: absolute; right: .25rem; bottom: .625rem; padding: .375rem .5rem; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); background: var(--bg-raised); font-size: var(--text-2xs); color: var(--text-main); }
.music-track-settings__visual-art--video .music-track-settings__art-tile { width: 100%; height: 6rem; overflow: hidden; }
.music-track-settings__visual-art--video .music-track-settings__art-tile img { opacity: .6; }
.music-track-settings__visual-art--video .ti { position: absolute; font-size: var(--text-xl); background: var(--overlay-backdrop); color: var(--overlay-text); width: 2.5rem; height: 2.5rem; display: grid; place-items: center; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); }
.music-track-settings__feature-copy { padding: .625rem .125rem 1rem; }
.music-track-settings__feature-copy h4 { font-weight: var(--font-weight-semibold); font-size: var(--text-base); color: var(--text-main); }
.music-track-settings__feature-copy p { font-size: var(--text-2xs); color: var(--text-muted); margin-top: .25rem; }
.music-track-settings__create-row { display: flex; align-items: center; gap: .75rem; margin-top: auto; padding-top: .25rem; }
.music-track-settings .music-track-settings__generate {
    display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
    flex: 1; min-width: 0; min-height: 2.875rem; padding: .5rem .875rem .5rem .5rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface); font-size: var(--text-sm); font-weight: var(--font-weight-semibold);
    box-shadow: inset 0 1px 0 var(--surface-strong), 0 3px 8px -4px var(--surface-dim);
}
.music-track-settings .music-track-settings__generate:disabled { box-shadow: none; }
.music-track-settings .music-track-settings__generate:focus-visible { outline: 2px solid var(--text-main); outline-offset: 3px; }
@media (hover: hover) {
    .music-track-settings .music-track-settings__generate:hover:not(:disabled) { box-shadow: var(--ring-accent-soft), var(--glow-accent-soft); }
}
.music-track-settings__generate-icon {
    display: grid; place-items: center; width: 1.875rem; height: 1.875rem; flex-shrink: 0;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface); background: var(--surface-dim); font-size: var(--text-base);
}
.music-track-settings__create-price { flex-shrink: 0; min-width: 6em; text-align: right; color: var(--text-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; white-space: nowrap; }
.music-track-settings__disclosure { display: flex; align-items: center; gap: .625rem; text-align: left; font-size: var(--text-xs); color: var(--text-muted); padding: .5rem 0; }
.music-track-settings__disclosure span { flex: 1; }
.music-track-settings__video-fields, .music-track-settings__bounds { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .75rem; }
.music-track-settings__editor-toolbar { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
.music-track-settings__editor-toolbar > strong { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.music-track-settings__tool-grid { display: grid; grid-template-columns: repeat(5, minmax(3rem, 1fr)); gap: .25rem; overflow-x: auto; overscroll-behavior-x: contain; padding: .125rem; }
.music-track-settings__tool-grid .surface-chip { display: flex; flex-direction: column; justify-content: center; align-items: center; gap: .375rem; min-height: 3.5rem; padding: .375rem .125rem; font-size: var(--text-2xs); text-align: center; border-radius: var(--radius-lg); corner-shape: var(--corner-shape-surface); }
.music-track-settings__tool-grid .ti { font-size: var(--text-xl); }
.music-track-settings__tool-grid [aria-pressed="true"], .music-track-settings__compare [aria-pressed="true"], .music-track-settings__speed-presets [aria-pressed="true"] { background: var(--primary-500); color: var(--primary-text); }
.music-track-settings__tool-grid button:focus-visible, .music-track-settings__edit-steps button:focus-visible { outline: 2px solid var(--text-main); outline-offset: 2px; }
.music-track-settings__edit-history { display: flex; align-items: center; gap: .25rem; flex-shrink: 0; }
.music-track-settings__edit-history .surface-chip { display: grid; place-items: center; width: 2.75rem; height: 2.75rem; padding: 0; font-size: var(--text-base); background: transparent; }
.music-track-settings__edit-history .surface-chip:disabled { opacity: .35; cursor: default; }
.music-track-settings__edit-steps { display: flex; gap: .375rem; padding: .125rem; margin: 0; list-style: none; overflow-x: auto; overscroll-behavior-x: contain; }
.music-track-settings__edit-steps li { flex-shrink: 0; }
.music-track-settings__edit-steps button { display: inline-flex; align-items: center; gap: .375rem; min-height: 2.75rem; padding: .375rem .625rem; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); background: var(--surface-soft); font-size: var(--text-xs); color: var(--text-muted); white-space: nowrap; }
.music-track-settings__edit-steps button[aria-pressed="true"] { background: var(--surface-active); color: var(--text-main); box-shadow: inset 0 0 0 1px var(--primary-500); }
.music-track-settings__edit-steps button > span:first-child { color: var(--text-subtle); font-variant-numeric: tabular-nums; }
.music-track-settings__edit-steps .ti { font-size: var(--text-xs); opacity: .6; }
.music-track-settings__apply-row { display: flex; gap: .5rem; }
.music-track-settings__apply-row > .music-track-settings__apply { flex: 1; min-width: 0; width: auto; }
.music-track-settings__apply-row > .music-track-settings__cancel-edit { flex: 0 0 2.75rem; width: 2.75rem; padding: 0; }
.music-track-settings__compare, .music-track-settings__speed-presets { display: flex; align-items: center; gap: .375rem; }
.music-track-settings__compare { margin-left: auto; gap: .125rem; padding: .125rem; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); background: var(--surface-soft); }
.music-track-settings__compare .surface-chip, .music-track-settings__speed-presets .surface-chip { min-height: 2.75rem; min-width: 2.75rem; padding: .375rem .625rem; font-size: var(--text-xs); }
.music-track-settings__speed-presets { flex-wrap: wrap; }
.music-track-settings__precision summary { display: flex; align-items: center; justify-content: space-between; gap: .5rem; min-height: 2.75rem; cursor: pointer; list-style: none; color: var(--text-muted); font-size: var(--text-xs); }
.music-track-settings__precision summary::-webkit-details-marker { display: none; }
.music-track-settings__precision summary > span { display: inline-flex; align-items: center; gap: .5rem; }
.music-track-settings__precision[open] summary > .ti { transform: rotate(180deg); }
.music-track-settings__precision[open] > div { margin-top: .5rem; }
.music-track-settings__precision summary:focus-visible { outline: 2px solid var(--text-main); outline-offset: 2px; border-radius: var(--radius-md); corner-shape: var(--corner-shape-surface); }
.music-track-settings__editor { gap: .75rem; }
.music-track-settings__trim .music-wave__timeline { border-radius: var(--radius-lg); corner-shape: var(--corner-shape-surface); overflow: hidden; }
.music-track-settings__trim .music-wave__timeline:has(:focus-visible) { outline: 2px solid var(--text-main); outline-offset: 2px; }
.music-track-settings__trim .music-wave__canvas { height: 4.5rem; border-radius: inherit; corner-shape: inherit; outline: none; }
.music-track-settings__trim.is-fade .music-wave__canvas { height: 5.5rem; }
.music-track-settings__fade-overlay { position: absolute; inset: 0; pointer-events: none; }
.music-track-settings__fade-overlay svg { width: 100%; height: 100%; overflow: visible; }
.music-track-settings__fade-overlay polygon { fill: var(--primary-500); opacity: .12; }
.music-track-settings__fade-overlay polyline { fill: none; stroke: var(--primary-500); stroke-width: 2; }
.music-track-settings__fade-handle { position: absolute; top: 0; bottom: 0; width: 44px; transform: translateX(-50%); pointer-events: auto; touch-action: none; cursor: ew-resize; display: flex; flex-direction: column; align-items: center; justify-content: space-between; padding: 0; color: var(--primary-text); }
.music-track-settings__fade-handle::before { content: ''; position: absolute; inset: 0; width: 2px; margin-inline: auto; background: var(--primary-500); }
.music-track-settings__fade-handle--in { bottom: 50%; padding-top: .5rem; }
.music-track-settings__fade-handle--out { top: 50%; flex-direction: column-reverse; padding-bottom: .5rem; }
.music-track-settings__fade-handle > span, .music-track-settings__fade-handle > i { z-index: 1; background: var(--primary-500); border-radius: var(--radius-md); corner-shape: var(--corner-shape-surface); }
.music-track-settings__fade-handle > span { padding: .125rem .25rem; white-space: nowrap; font-size: var(--text-2xs); line-height: 1; font-variant-numeric: tabular-nums; }
.music-track-settings__fade-handle > i { padding: .125rem; font-size: var(--text-sm); }
.music-track-settings__fade-handle:focus-visible { outline: 2px solid var(--text-main); outline-offset: 2px; border-radius: var(--radius-md); corner-shape: var(--corner-shape-surface); }
.music-track-settings__apply { gap: .375rem; min-height: 2.75rem; padding-inline: .5rem; font-size: var(--text-xs); }
.music-track-settings__effect { display: flex; flex-direction: column; gap: .75rem; }
.music-track-settings__effect .ui-slider-row { width: 100%; }
.music-track-settings__result-controls { display: flex; align-items: center; gap: .625rem; }
.music-track-settings__result-controls .music-wave__play { width: 2.75rem; height: 2.75rem; }
.music-track-settings__result-time { display: flex; flex-direction: column; gap: .125rem; font-variant-numeric: tabular-nums; }
.music-track-settings__result-time > span { font-size: var(--text-xs); color: var(--text-muted); }
.music-track-settings__result-time strong { display: inline-flex; align-items: baseline; gap: .25rem; font-size: var(--text-sm); font-weight: 600; white-space: nowrap; }
.music-track-settings__export { flex-shrink: 0; gap: .375rem; min-height: 2.75rem; padding: .625rem .75rem; }
.music-track-settings__trim.is-whole-track .music-wave__handle { display: none; }
.music-track-settings__trim.is-whole-track .music-wave__legend { display: none; }
.music-track-settings__trim.is-remove-section .wave-tag--range { background: var(--surface-active); color: var(--text-muted); }
.music-track-settings__trim.is-remove-section .wave-tag--remove { background: var(--primary-500); color: var(--primary-text); }
.music-track-settings__trim { padding: .875rem; border-radius: var(--radius-xl); corner-shape: var(--corner-shape-surface); background: var(--surface-soft); display: flex; flex-direction: column; gap: .75rem; }
.music-track-settings__trim .music-wave { margin-top: 0; }
.music-track-settings__bounds .music-field__input { font-variant-numeric: tabular-nums; font-size: var(--text-lg); }
.music-track-settings__hint { font-size: var(--text-2xs); color: var(--text-subtle); display: flex; align-items: center; gap: .375rem; }
.music-track-settings__trim > .music-track-settings__hint { justify-content: center; }
.music-track-settings__results { gap: .5rem; }
.music-track-settings__results .music-track-settings__collection-head { margin-bottom: .25rem; }
.music-track-settings__result { display: flex; align-items: center; gap: .625rem; padding: .625rem; min-height: 4.25rem; background: var(--surface-soft); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.music-track-settings__result-open { display: flex; align-items: center; gap: .75rem; flex: 1; min-width: 0; text-align: left; color: var(--text-main); }
.music-track-settings__result-open > span:last-child { min-width: 0; }
.music-track-settings__result strong { display: block; font-size: var(--text-xs); font-weight: var(--font-weight-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.music-track-settings__result small { display: block; font-size: var(--text-2xs); color: var(--text-muted); margin-top: .2rem; }
.music-track-settings__result img, .music-track-settings__glyph { width: 3rem; height: 3rem; flex-shrink: 0; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); object-fit: cover; }
.music-track-settings__glyph { display: grid; place-items: center; background: var(--surface-active); font-size: var(--text-xl); }
.music-track-settings__result > .surface-chip { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; padding: 0; flex-shrink: 0; }
.music-track-settings .music-track-settings__footer { flex-direction: row; align-items: center; justify-content: flex-end; gap: 1rem; padding: 1rem 1.5rem; background: var(--surface-soft); }
.music-track-settings__footer > .music-track-settings__hint { margin-right: auto; }
.music-track-settings .music-track-settings__footer > .btn { width: auto; min-width: 8rem; }
@media (max-width: 680px) {
    .music-track-settings.is-audio .music-track-settings__identity { grid-template-columns: 3rem minmax(0, 1fr); gap: .625rem; }
    .music-track-settings.is-audio .music-track-settings__identity-copy { display: flex; align-items: center; gap: .5rem; min-width: 0; }
    .music-track-settings.is-audio .music-track-settings__identity h3 { flex: 1; min-width: 0; margin: 0; font-size: var(--text-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .music-track-settings.is-audio .music-track-settings__facts, .music-track-settings.is-audio .music-track-settings__eyebrow { display: none; }
    .music-track-settings.is-audio .music-track-settings__quick-actions { flex-shrink: 0; margin: 0; gap: 0; }
    .music-track-settings.is-audio .music-track-settings__quick-actions .surface-chip { width: 2.75rem; height: 2.75rem; background: transparent; }
    .music-track-settings.is-audio .music-track-settings__cover-edit { width: 2.75rem; height: 2.75rem; inset: auto; top: 0; right: 0; background: transparent; color: var(--overlay-text); }
    .music-track-settings.is-audio .music-track-settings__cover-edit .ti { filter: drop-shadow(0 1px 2px var(--overlay-backdrop)); }
    .music-track-settings.is-audio .music-track-settings__workspace { gap: .875rem; }
    .music-track-settings.is-audio .music-track-settings__tabs { margin-bottom: .75rem; }
    .music-track-settings__workspace { display: flex; flex-direction: column; gap: 1.25rem; padding: 1rem; overflow-y: auto; }
    .music-track-settings__identity { display: grid; grid-template-columns: 6rem minmax(0, 1fr); gap: 1rem; align-items: center; }
    .music-track-settings__artwork { margin: 0; }
    .music-track-settings__identity h3 { font-size: var(--text-lg); margin: .25rem 0 .375rem; }
    .music-track-settings__eyebrow { display: none; }
    .music-track-settings__facts { font-size: var(--text-2xs); }
    .music-track-settings__quick-actions { margin-top: .625rem; }
    .music-track-settings__quick-actions .surface-chip { width: 2rem; height: 2rem; font-size: var(--text-base); }
    .music-track-settings__cover-edit { bottom: .25rem; right: .25rem; width: 1.75rem; height: 1.75rem; }
    .music-track-settings__main { flex-shrink: 0; }
    .music-track-settings__tabs { margin-bottom: 1.25rem; }
    .music-track-settings__tabs .music-seg__btn { gap: .375rem; padding-inline: .5rem; }
    .music-track-settings__tab-art { width: 1.75rem; height: 1.75rem; }
    .music-track-settings__body { height: auto; overflow: visible; padding: 0 .125rem; }
    .music-track-settings__body:has(.music-track-settings__tool-grid) { height: auto; }
    .music-track-settings__heading h3 { font-size: var(--text-lg); }
    .music-track-settings__visual-grid { gap: .625rem; }
    .music-track-settings__feature { padding: .75rem; }
    .music-track-settings__create-row { flex-direction: column; align-items: stretch; gap: .625rem; }
    .music-track-settings .music-track-settings__generate { width: 100%; padding-inline: .5rem; }
    .music-track-settings__create-price { min-width: 0; text-align: center; font-size: var(--text-2xs); }
    .music-track-settings__visual-art { height: 7rem; }
    .music-track-settings__art-tile, .music-track-settings__visual-art--cover::before { width: 5rem; height: 5rem; }
    .music-track-settings__visual-art--video .music-track-settings__art-tile { height: 5rem; }
    .music-track-settings__feature-copy h4 { font-size: var(--text-sm); }
    .music-track-settings__feature-copy p { min-height: 2.5em; }
    .music-track-settings .music-track-settings__footer { padding: .875rem 1rem; }
    .music-track-settings__footer > .music-track-settings__hint { max-width: 50%; }
}

.system-modal-body {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.system-modal-title {
    font-family: var(--font-display);
    font-size: var(--text-dialog);
    font-weight: var(--font-weight-display);
    line-height: var(--leading-display);
    color: var(--text-main);
}
.system-modal-title.hidden,
.system-modal-message.hidden,
.system-modal-chips.hidden,
.system-modal-icon.hidden,
.system-modal-price.hidden { display: none; }

.system-modal-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-active);
    color: var(--text-main);
    font-size: 1.5rem;
}

.system-modal-price {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
}

.system-modal-message {
    color: var(--text-muted);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    white-space: pre-wrap;
    max-width: 100%;
}

.system-modal-input {
    width: 100%;
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    border: 0;
    background: var(--bg-input);
    color: var(--text-main);
    font-size: var(--text-base);
    outline: none;
    transition: border-color var(--transition-fast);
}
.system-modal-input:focus {
    border-color: transparent;
}
.system-modal-input::placeholder {
    color: var(--text-subtle);
}

/* Крестик закрытия — только choices-режим (appChoice), вместо кнопки «Отмена». */
.system-modal-close {
    position: absolute;
    top: 0.625rem;
    right: 0.625rem;
    width: 2rem;
    height: 2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: transparent;
    color: var(--text-muted);
    cursor: pointer;
    transition: background-color var(--transition), color var(--transition);
}
@media (hover: hover) {
    .system-modal-close:hover {
        background-color: var(--bg-hover);
        color: var(--text-main);
    }
}
/* Заголовок не заезжает под крестик. */
.system-modal--closable .system-modal-title {
    padding-right: 2.25rem;
}

/* Кнопки — вертикальным стеком (primary сверху, отмена снизу), на всю ширину. */
.system-modal-actions {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
}
.system-modal-actions .btn {
    width: 100%;
    justify-content: center;
}
/* «Тихая» кнопка — сливается с фоном карточки (без своего фона/обводки). */
.system-modal-actions .btn-modal-flat {
    background-color: transparent;
    color: var(--text-main);
}

/* Чипы для перечисления (напр. «модель не поддерживает: …»). */
.system-modal-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}
.system-modal-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.3rem 0.625rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: var(--bg-raised);
    color: var(--text-main);
    font-size: var(--text-sm);
    line-height: var(--leading-display);
    max-width: 100%;
}
.system-modal-chip > span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.system-modal-chip > i {
    font-size: var(--text-base);
    color: var(--text-muted);
}

@media (max-width: 640px) {
    .system-modal-card {
        width: min(92vw, 26rem);
        gap: 1rem;
        padding: 1rem;
    }
}

/* ── Idle Glow: animated border shimmer when input is empty ── */
@property --glow-angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}

@property --glow-opacity {
    syntax: '<number>';
    initial-value: 0.5;
    inherits: false;
}

.shell-idle-glow::before,
.chat-input-zone.is-drag-over::after,
.media-composer-shell.is-drag-over .chat-input-main-shell::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    corner-shape: inherit;
    padding: 1px;
    background: conic-gradient(from var(--glow-angle), var(--composer-spectrum-stops));
    -webkit-mask:
        linear-gradient(#fff 0 0) content-box,
        linear-gradient(#fff 0 0);
    mask:
        linear-gradient(#fff 0 0) content-box,
        linear-gradient(#fff 0 0);
    -webkit-mask-composite: destination-out;
    mask-composite: exclude;
    pointer-events: none;
    z-index: 2;
    --glow-angle: 0deg;
    --glow-opacity: 0.58;
    opacity: var(--glow-opacity);
}

/* Композер движется постоянно и спокойно; hover не меняет его скорость или яркость.
   На небольших вспомогательных элементах анимация остаётся только по взаимодействию. */
.chat-input-zone.shell-idle-glow::before {
    animation: shell-glow-spin var(--motion-period-idle-glow) var(--motion-ease-linear) infinite var(--pane-ambient-play-state, running);
}

.shell-idle-glow:not(.chat-input-zone):hover::before,
.shell-idle-glow:not(.chat-input-zone):focus-within::before,
.chat-input-zone.is-drag-over::after,
.media-composer-shell.is-drag-over .chat-input-main-shell::after {
    animation: shell-glow-spin var(--motion-period-glow) var(--motion-ease-linear) infinite var(--pane-ambient-play-state, running);
}

/* Drag-over: та же вращающаяся грань, но ярче — сигнал зоны сброса. Idle-glow и
   пунктир временного чата глушим, чтобы грань не двоилась. */
.chat-input-zone.is-drag-over::after,
.media-composer-shell.is-drag-over .chat-input-main-shell::after {
    --glow-opacity: 0.9;
}
.chat-input-zone.is-drag-over.shell-idle-glow::before {
    opacity: 0;
}
.chat-input-zone.is-drag-over.shell-temp-dash > .temp-dash-frame {
    display: none;
}

@keyframes shell-glow-spin {
    to { --glow-angle: 360deg; }
}

/* Во время shell-навигации (класс .is-navigating на <html> ставит unpoly-config
   на время анимации входа) замораживаем анимируемый conic-gradient idle-glow:
   он репейнтит 60fps и крадёт кадры у трансформа перехода. В покое не влияет. */
:is(.is-navigating, .shell-entering) .shell-idle-glow::before {
    animation-play-state: paused;
}

/* These effects animate paint properties even behind an open modal. Let the
   foreground interaction own the frame; resume when the last modal closes. */
.has-modal #app-shell-root .shell-idle-glow::before,
.has-modal #app-shell-root .text-shimmer,
.has-modal #app-shell-root .agent-status.is-active,
.has-modal #app-shell-root .music-eq span,
.has-modal #app-shell-root .composer-scroll-hint i,
.has-modal #app-shell-root .shell-user-pill__balance.is-refreshing {
    animation-play-state: paused;
}

/* Opacity/visibility leave voice controls mounted; stop their paint clock
   until the voice state actually owns the composer. */
.composer-state-switch:not(.is-voice-active) .composer-state-layer--voice .text-shimmer,
.has-modal #app-shell-root .history-action-surface::after,
.has-modal #app-shell-root .composer-example__ink,
:is(.is-navigating, .shell-entering) #app-shell-root .history-action-surface::after,
:is(.is-navigating, .shell-entering) #app-shell-root .composer-example__ink {
    animation-play-state: paused;
}
.motion-suspended *,
.motion-suspended *::before,
.motion-suspended *::after {
    animation-play-state: paused !important;
}

/* Offscreen panes remain mounted to preserve drafts and their slide transition.
   A transform/visibility alone does not suspend their CSS animation clocks.
   Use the layout's state/breakpoints and only pause decorative loops. Entrances,
   loading/data handling and the pane's own slide retain their normal lifecycle. */
@media (max-width: 767.98px) {
    .tg-content-hidden, .tg-sidebar-mobile-hidden {
        --pane-ambient-play-state: paused;
    }
}
@media (max-width: 1099.98px) {
    .app-root[data-page-category='music'] .media-page:not(.is-music-composer-open) .chat-input-docked,
    .app-root[data-page-category='music'] .media-page.is-music-composer-open .music-mobile-shell {
        --pane-ambient-play-state: paused;
    }
}
#media-composer-content[aria-hidden='true'] {
    --pane-ambient-play-state: paused;
}

@media (prefers-reduced-motion: reduce) {
    .shell-idle-glow::before,
    .chat-input-zone.shell-idle-glow::before,
    .shell-idle-glow:not(.chat-input-zone):hover::before,
    .shell-idle-glow:not(.chat-input-zone):focus-within::before { animation: none; opacity: 0.3; }
    .chat-input-zone.is-drag-over::after,
    .media-composer-shell.is-drag-over .chat-input-main-shell::after { animation: none; opacity: 0.9; }
}

/* (Убрано) mobile clip-path inset(0 0 1px 0) на .shell-idle-glow::before — он
   срезал нижнюю кромку свечения. Композеры теперь плавают (gap снизу), кромка
   видна целиком как на desktop, клип больше не нужен. */

/* ── Temp Chat Dash: бегущий пунктир (marching ants) по периметру композера
   во временном чате. Заменяет idle-glow на пустом экране (см. биндинг в
   _composer_text.html). SVG-обводка со stroke-dasharray даёт ровные штрихи
   одинаковой длины по всему периметру — в отличие от conic-маски, которая на
   широкой пилюле «плыла» и не читалась как пунктир. Пунктир — фирменный знак
   temp-чата (ср. stroke-dasharray иконки в _temp_chat_icon.html). */
.temp-dash-frame {
    display: none;
    position: absolute;
    inset: 1px; /* стоит чуть внутри пилюли, как ring у idle-glow */
    /* <svg> — replaced-элемент: без явных размеров он откатывается к дефолтным
       300×150px и не тянется по inset. Поэтому размер задаём явно. */
    width: calc(100% - 2px);
    height: calc(100% - 2px);
    overflow: visible;
    pointer-events: none;
    z-index: 2;
}
.shell-temp-dash > .temp-dash-frame { display: block; }

.temp-dash-frame rect {
    fill: none;
    stroke: var(--text-muted);
    stroke-width: 1.5;
    stroke-dasharray: 5 6;
    stroke-linecap: round;
    animation: temp-dash-march var(--motion-period-dash) var(--motion-ease-linear) infinite var(--pane-ambient-play-state, running);
}

/* Сдвиг на один цикл «штрих+пробел» (5+6) → штрихи плавно бегут по контуру. */
@keyframes temp-dash-march {
    to { stroke-dashoffset: -11; }
}

@media (prefers-reduced-motion: reduce) {
    .temp-dash-frame rect { animation: none; }
}

.chat-input-state-host {
    /* Вычеты/добавки радиуса шторки МАСШТАБИРУЕМ вместе с --radius-scale: фикс. rem
       при малом скруглении съедал бо́льшую долю радиуса (при 0 уходил в минус) →
       верх секции рассинхронивался с пилюлей композера. Теперь пропорция постоянна. */
    --chat-params-curtain-radius: calc(var(--radius-xl) - 0.25rem * var(--radius-scale));
    --chat-params-curtain-bottom-radius: calc(var(--chat-params-curtain-radius) + 0.5rem * var(--radius-scale));
    --chat-params-curtain-top-pad: 0.5rem;
    --chat-params-curtain-x-pad: 0.5rem;
    --chat-params-curtain-overlap: 0.625rem;
    --chat-params-curtain-bottom-pad: calc(var(--chat-params-curtain-top-pad) + var(--chat-params-curtain-overlap));
    display: flex;
    flex-direction: column;
    position: relative;
    z-index: 1;
}

.chat-input-state-shell {
    min-height: var(--chat-input-shell-min-height);
}

/* Input zone: единый padding для всех дочерних элементов внутри формы.
   Absolute-позиционированные controls ссылаются на padding-box,
   поэтому inset: 0 автоматически совпадает с padding content'а. */
.chat-input-zone {
    padding: var(--composer-inset); /* 10px */
    min-height: var(--chat-input-shell-min-height); /* 40px buttons + padding */
    border-radius: inherit;
    corner-shape: inherit;
}

/* Drag-n-drop на композер: пока над зоной тянут файл/элемент истории, рисуем
   вращающуюся грань (кольцо ::after выше). Нейтральный фрост-оверлей
   .composer-drop-hint ниже сам размывает/затемняет зону — отдельная акцентная
   заливка не нужна. .is-drag-over ставит AttachmentsService на чат- и медиа-композере. */

/* Оверлей-подсказка «Перетащите сюда» — по центру зоны сброса, поверх контента,
   но прозрачный для событий (drop проходит в зону). Нейтральные тона + сильный блюр. */
.composer-drop-hint {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    border-radius: inherit;
    corner-shape: inherit;
    pointer-events: none;
    z-index: 3;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    background-color: color-mix(in srgb, var(--bg-panel) 74%, transparent);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
}
.composer-drop-hint i {
    font-size: var(--text-lg);
    color: var(--text-muted);
}

.composer-state-switch {
    --composer-view-inset: 0px;
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}

/* Reserve updates affect only the scroller, never its message descendants or
   the composer. The fallback in older engines is still scoped to that box. */
@property --composer-height {
    syntax: '<length>';
    inherits: false;
    initial-value: 0px;
}

@property --input-height {
    syntax: '<length>';
    inherits: false;
    initial-value: 0px;
}

.chat-input-zone.composer-state-switch {
    --composer-view-inset: var(--composer-inset);
}

.composer-state-switch > .composer-state-layer {
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
    min-height: 0;
    width: 100%;
    min-width: 0;
    overflow: visible;
    opacity: 1;
    visibility: visible;
    transform: none;
    transform-origin: bottom center;
    transition:
        opacity var(--motion-duration-fast) var(--motion-ease-premium),
        transform var(--motion-duration-fast) var(--motion-ease-premium),
        visibility 0s;
}

.composer-state-layer__inner {
    min-height: 0;
    min-width: 0;
}

.composer-state-switch.is-voice-active > .composer-state-layer--normal,
.composer-state-switch:not(.is-voice-active) > .composer-state-layer--voice {
    position: absolute;
    /* Match the in-flow content box, including padding. Otherwise switching
       to absolute positioning jumps 10px and reflows the outgoing draft. */
    inset-inline: var(--composer-view-inset);
    bottom: var(--composer-view-inset);
    width: auto;
    opacity: 0;
    visibility: hidden;
    transform: scale(var(--motion-scale-surface));
    transition: opacity var(--transition-fast), transform var(--transition-fast),
                visibility 0s var(--motion-duration-fast);
    pointer-events: none;
    z-index: 0;
}

.composer-state-switch.is-voice-active > .composer-state-layer--voice,
.composer-state-switch:not(.is-voice-active) > .composer-state-layer--normal {
    position: relative;
    opacity: 1;
    visibility: visible;
    transform: none;
    pointer-events: auto;
    z-index: 1;
}

.composer-voice-controls {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gap-sm);
    min-height: calc(var(--composer-control-size) + var(--gap-2xs) * 2);
}
.composer-voice-controls--padded { padding: var(--gap-sm); }
.composer-voice-controls__status {
    flex: 1;
    min-width: 0;
    text-align: center;
    /* Keep the light on the ink's intrinsic width, not the entire flex lane. */
    padding-block: var(--gap-sm);
}
.composer-voice-controls__button {
    display: grid;
    place-items: center;
    flex: 0 0 var(--composer-control-size);
    width: var(--composer-control-size);
    height: var(--composer-control-size);
    padding: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
}

.chat-input-state-stack {
    display: flex;

    flex-direction: column;
    gap: 0;
    /* The parameter tint fades independently; keep the shared composer shadow
       on the shell so it also remains visible with parameters closed. */
    box-shadow: var(--shadow-glass), var(--shadow-composer);
    /* Keep the glass blur on its own rounded layer. Combining backdrop-filter
       with the expanding stack's outer shadows can rasterize a solid rectangle
       below the composer in Chromium when parameter chips are enabled. */
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    /* An opacity will-change creates a backdrop root and prevents ::after from
       sampling the page behind this shell, including the collapsed state. */
    will-change: transform;
    /* Перебивает .motion (там нет padding/border-radius): рост/схлопывание
       шторки params двигает верх стека синхронно с .chat-input-params-shell
       (fast/premium — единый темп геометрии композера), иначе padding-top
       прыгает мгновенно. Остальные свойства — как в .motion. */
    transition: padding-top var(--motion-duration-fast) var(--motion-ease-premium),
                border-radius var(--motion-duration-base) var(--motion-ease-premium),
                transform var(--motion-duration-base) var(--motion-ease-premium),
                opacity var(--motion-duration-base) var(--motion-ease-premium),
                background-color var(--motion-duration-base) var(--motion-ease-premium),
                box-shadow var(--motion-duration-base) var(--motion-ease-premium);
}

.chat-input-state-stack::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    corner-shape: inherit;
    z-index: -2;
    pointer-events: none;
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
}

/* Тонировка шторки — на ::before с opacity-переходом: background-image
   (градиент) не интерполируется и при снятии .has-params исчезал скачком в
   первом же кадре, до схлопывания шторки. Базовый фон у стека есть всегда,
   а размытие вынесено на ::after отдельно от теней. */
.chat-input-state-stack::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    corner-shape: inherit;
    box-shadow: none;
    background: linear-gradient(180deg, color-mix(in srgb, var(--bg-elevated) 88%, transparent), color-mix(in srgb, var(--bg-input) 84%, transparent));
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-duration-fast) var(--motion-ease-premium);
}

[data-theme="light"] .chat-input-state-stack::before {
    background: linear-gradient(180deg, color-mix(in srgb, var(--bg-raised) 94%, transparent), color-mix(in srgb, var(--bg-elevated) 88%, transparent));
}

.chat-input-state-stack.has-params {
    padding-top: var(--chat-params-curtain-top-pad);
    border-radius: var(--chat-params-curtain-radius) var(--chat-params-curtain-radius) var(--chat-params-curtain-bottom-radius) var(--chat-params-curtain-bottom-radius);
    corner-shape: var(--corner-shape-surface);
    transform: translateZ(0);
    backface-visibility: hidden;
}

.chat-input-state-stack.has-params::before {
    opacity: 1;
}

.chat-input-params-shell {
    min-width: 0;
    position: relative;
    z-index: 0;
    display: grid;
    grid-template-rows: 0fr;
    opacity: 0;
    padding: 0;
    margin-bottom: 0;
    pointer-events: none;
    transition: grid-template-rows var(--motion-duration-fast) var(--motion-ease-premium),
                opacity var(--motion-duration-fast) var(--motion-ease-premium),
                padding var(--motion-duration-fast) var(--motion-ease-premium),
                margin-bottom var(--motion-duration-fast) var(--motion-ease-premium);
}

.chat-input-state-stack.has-params .chat-input-params-shell {
    grid-template-rows: 1fr;
    opacity: 1;
    padding: 0 var(--chat-params-curtain-x-pad) var(--chat-params-curtain-bottom-pad);
    margin-bottom: calc(var(--chat-params-curtain-overlap) * -1);
    pointer-events: auto;
}

/* Inner wrapper — единственный grid-child shell'а. Объединяет row+banner
   в одну схлопывающуюся единицу: при закрытии шторки grid-rows 0fr зажимает
   всё содержимое (включая баннер). Padding/margin остаются на shell, чтобы
   inner не давал ненулевого min-content в close state. */
.chat-input-params-inner {
    min-height: 0;
    overflow: hidden;
}

.chat-input-assistants-host {
    width: 100%;
    min-width: 0;
    margin-bottom: 0.625rem;
    max-height: 8rem;
    opacity: 1;
    overflow: hidden;
    transition:
        max-height var(--motion-duration-fast) var(--motion-ease-premium),
        margin-bottom var(--motion-duration-fast) var(--motion-ease-premium),
        opacity var(--motion-duration-fast) var(--motion-ease-premium);
}

.chat-input-assistants-strip {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 0;
    min-width: 0;
    /* верт. padding нужен под бейдж .chat-input-assistant-dot__status,
       который висит на bottom: -1px и иначе клиппится overflow-y */
    padding: 0.25rem 0;
    overflow-x: auto;
    overflow-y: hidden;

}


.chat-input-assistant-create {
    order: 1;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.6875rem;
    height: 2.875rem;
    min-height: 0;
    min-width: max-content;
    max-width: 100%;
    padding: 0.25rem 1rem 0.25rem 0.25rem;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: color-mix(in srgb, var(--bg-raised) 84%, transparent);
    color: var(--text-main);
    transition:
        transform var(--motion-duration-fast) var(--motion-ease-premium),
        background var(--motion-duration-fast) var(--motion-ease-standard),
        box-shadow var(--motion-duration-fast) var(--motion-ease-standard);
}

.chat-input-assistant-create__icon {
    position: relative;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: calc(2.875rem - 0.5rem);
    height: calc(2.875rem - 0.5rem);
    border: none;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: color-mix(in srgb, var(--bg-raised) 84%, transparent);
    color: var(--text-main);
}

.chat-input-assistant-create__icon .ti {
    font-size: var(--text-xl);
}

.chat-input-assistant-create__label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    white-space: nowrap;
}

.chat-input-assistant-dot {
    order: 3;
    position: relative;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.875rem;
    height: 2.875rem;
    border: none;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: color-mix(in srgb, var(--bg-raised) 84%, transparent);
    color: var(--text-main);
    box-shadow: var(--shadow-surface);
    transition:
        background var(--motion-duration-fast) var(--motion-ease-standard),
        box-shadow var(--motion-duration-fast) var(--motion-ease-standard);
}

.chat-input-assistant-dot .ti {
    font-size: var(--text-xl);
}

.chat-input-assistant-dot__avatar {
    /* Фото заполняет рамку и повторяет её форму (border-radius: inherit) — при
       любом --radius-scale (круг на 100%, скруглённый квадрат на меньших) углы
       фото совпадают с рамкой и не вылезают. Тонкое внутреннее кольцо между фото
       и краем — через inset box-shadow (следует за той же формой). */
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
    corner-shape: inherit;
    display: block;
    box-shadow: none;
}

.chat-input-assistant-dot__fallback {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-none);
}

.chat-input-assistant-dot__status {
    position: absolute;
    right: -0.0625rem;
    bottom: -0.0625rem;
    width: 1rem;
    height: 1rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal;
    color: var(--primary-text);
    box-shadow: none;
}

.chat-input-assistant-dot.is-active {
    background: linear-gradient(
        180deg,
        color-mix(in srgb, var(--primary-10) 72%, var(--bg-raised)) 0%,
        color-mix(in srgb, var(--primary-10) 34%, var(--bg-panel)) 100%
    );
    box-shadow:
        0 10px 24px -18px color-mix(in srgb, var(--primary-500) 36%, transparent);
}

.chat-input-assistant-dot-create {
    color: var(--text-main);
}

.chat-input-assistant-dot-all {
    order: 2;
    color: var(--text-muted);
}

@media (hover: hover) {
    .chat-input-assistant-create:hover {
        background: color-mix(in srgb, var(--bg-panel) 92%, transparent);
    }

    .chat-input-assistant-dot:hover {
        background: color-mix(in srgb, var(--bg-panel) 92%, transparent);
    }

    .chat-input-assistant-dot.is-active:hover {
        background: linear-gradient(
            180deg,
            color-mix(in srgb, var(--primary-10) 84%, var(--bg-raised)) 0%,
            color-mix(in srgb, var(--primary-10) 44%, var(--bg-panel)) 100%
        );
    }
}

/* Чип ассистента: mobile-вариант — пила в params-row, desktop — width-collapse
   узел в контролс-баре. Прячем ОБЁРТКУ-collapsible, а не кнопку: скрытая кнопка
   внутри видимой grid-обёртки оставляла бы ghost-слот в flex-gap ряда. */
@media (min-width: 768px) {
    .chat-input-params-row > .composer-collapsible.assistant-pill-mobile { display: none; }
}
@media (max-width: 767px) {
    .composer-collapsible--inline.assistant-pill-desktop { display: none; }
    .chat-input-state-stack.has-mobile-assistant {
        padding-top: var(--chat-params-curtain-top-pad);
        border-radius: var(--chat-params-curtain-radius) var(--chat-params-curtain-radius) var(--chat-params-curtain-bottom-radius) var(--chat-params-curtain-bottom-radius);
        corner-shape: var(--corner-shape-surface);
        transform: translateZ(0);
        backface-visibility: hidden;
    }
    /* Плёнка шторки — общий ::before стека (см. desktop-вариант выше). */
    .chat-input-state-stack.has-mobile-assistant::before {
        opacity: 1;
    }
    .chat-input-state-stack.has-mobile-assistant .chat-input-params-shell {
        grid-template-rows: 1fr;
        opacity: 1;
        padding: 0 var(--chat-params-curtain-x-pad) var(--chat-params-curtain-bottom-pad);
        margin-bottom: calc(var(--chat-params-curtain-overlap) * -1);
        pointer-events: auto;
    }
}

/* Единственный владелец ВЫСОТЫ ряда пил. Пилы анимируют только ширину
   (см. .chat-input-params-row > .composer-collapsible), а вертикальное место
   под ряд выдаёт/забирает этот slot: ряд без видимых чипов схлопывается, когда
   шторку держит открытой что-то ещё (ultra-banner / ассистент на мобиле).
   При закрытии самой шторки slot держится открытым — клипает шторка, одним
   движением. Темп — base/premium, как у всей геометрии композера. */
.chat-input-params-rowslot {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows var(--motion-duration-base) var(--motion-ease-premium);
}
.chat-input-state-stack.has-params:not(.has-active-chips) .chat-input-params-rowslot {
    grid-template-rows: 0fr;
}

.chat-input-params-row {
    /* Токен gap: его же (с минусом) использует margin-компенсация схлопнутой
       пилы (.composer-collapsible:not(.is-open)). Как gap-1 у модели и микрофона. */
    --params-row-gap: 0.25rem;
    display: flex;
    flex-wrap: wrap;
    gap: var(--params-row-gap);
    min-height: 0;
    overflow: hidden;
}

.chat-input-params-shell .surface-chip {
    background: var(--surface-active);
    box-shadow: none;
    /* Единая высота пил ряда (py-1.5 + крестик 24px = 36px): у пил без
       крестика (forced-thinking) контент ниже, и ряд проседал скачком,
       когда такая пила оставалась последней. */
    min-height: 2.25rem;
}

/* Зазор между chips и баннером — только если в ряду есть ВИДИМЫЕ чипы
   (hasComposerChips: пилы режимов; чип ассистента считается только на мобиле —
   на десктопе он в нижнем контролс-баре, и зазор давал пустой «резерв» над
   баннером). Темп = base/premium — зазор уезжает синхронно со схлопыванием
   .chat-input-params-rowslot, баннер движется одним движением, без фаз. */
.chat-input-params-shell .ultra-banner {
    transition: margin-top var(--motion-duration-base) var(--motion-ease-premium);
}
.chat-input-state-stack.has-active-chips .ultra-banner {
    margin-top: 0.5rem;
}

@media (hover: hover) {
    .chat-input-params-shell .surface-chip:hover {
        background: var(--surface-strong);
    }
}

.chat-input-params-shell .surface-chip.assistant-chip,
.surface-chip.assistant-chip {
    background: var(--surface-active);
}

/* Лидирующий аватар-слот в пиле ассистента: круглый контейнер для иконки
   или буквы-фоллбэка (первая буква имени), как у верхних дотов ассистентов.
   Размер задаётся утилитами (w-7/h-7 desktop, w-6/h-6 mobile). */
.assistant-chip__glyph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: color-mix(in srgb, var(--bg-raised) 84%, transparent);
    color: var(--text-main);
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-none);
}

@media (hover: hover) {
    .chat-input-params-shell .surface-chip.assistant-chip:hover,
    .surface-chip.assistant-chip:hover {
        background: var(--surface-strong);
    }
}

.media-composer-warning-slot {
    padding: var(--gap-sm) var(--gap-sm) 0;
}
.media-composer-notice-region {
    flex: 0 0 auto;
    visibility: visible;
    transition: visibility 0s;
}
.media-composer-notice-region[aria-hidden="true"] {
    visibility: hidden;
    transition-delay: var(--motion-duration-base);
}
@media (prefers-reduced-motion: reduce) {
    .media-composer-notice-region[aria-hidden="true"] { transition-delay: 0s; }
}

@media (max-width: 767px) {
    .chat-input-state-host {
        --chat-params-curtain-radius: calc(var(--radius-lg) - 0.125rem * var(--radius-scale));
        --chat-params-curtain-bottom-radius: calc(var(--chat-params-curtain-radius) + 0.25rem * var(--radius-scale));
        --chat-params-curtain-top-pad: 0.4375rem;
        --chat-params-curtain-x-pad: 0.4375rem;
        --chat-params-curtain-overlap: 0.5rem;
        --chat-params-curtain-bottom-pad: calc(var(--chat-params-curtain-top-pad) + var(--chat-params-curtain-overlap));
    }

    .chat-input-params-row {
        flex-wrap: nowrap;
        overflow-x: auto;
        overflow-y: hidden;

        /* Горизонтальный скролл пил режется не жёсткой прямой у края контейнера,
           а мягко растворяется — это «уважает» скругление окна композера. Затухание
           видно только при переполнении: когда пилы помещаются, у правого края
           пусто и маска ни на что не влияет. */
        scroll-padding-inline: 1.75rem;
    }

    .chat-input-params-row[data-fade="right"] { mask-image: linear-gradient(to right, #000 calc(100% - 1.75rem), transparent); }
    .chat-input-params-row[data-fade="left"] { mask-image: linear-gradient(to right, transparent, #000 1.75rem); }
    .chat-input-params-row[data-fade="both"] { mask-image: linear-gradient(to right, transparent, #000 1.75rem, #000 calc(100% - 1.75rem), transparent); }


    .chat-input-assistant-dot {
        width: 2.75rem;
        height: 2.75rem;
    }

    .chat-input-assistant-create {
        flex: 0 0 auto;
        height: 2.75rem;
        min-height: 0;
        min-width: max-content;
        padding: 0.25rem 0.875rem 0.25rem 0.25rem;
    }

    .chat-input-assistant-create__icon {
        width: calc(2.75rem - 0.5rem);
        height: calc(2.75rem - 0.5rem);
    }

    /* Реальные флекс-элементы скролл-ряда — обёртки .composer-collapsible
       (чип внутри них) и прямой чип ассистента. Без 0 0 auto на обёртках
       пилюли сжимаются/переносят текст вместо горизонтального скролла. */
    .chat-input-params-shell .surface-chip,
    .chat-input-params-row > .composer-collapsible {
        flex: 0 0 auto;
    }
}

/* Ghost-кнопки в стеклянном инпуте (категория B) — полупрозрачные; tint делает их
   тема-зависимыми сам, поэтому отдельный [data-theme="light"]-дубль больше не нужен. */
.chat-input-shell .btn.btn-ghost {
    background-color: var(--surface-active);
}


/* Enhance prompt button */
.enhance-btn {
    color: var(--text-muted);
    transition: color var(--transition-fast),
                background-color var(--transition-fast);
}

@media (hover: hover) {
    .enhance-btn:hover {
        color: var(--text-main);
    }
}

.enhance-btn-active {
    color: var(--text-main);
}

/* Modal Card */
.modal-card,
.system-modal-card {
    background-color: var(--chat-input-solid);
    box-shadow: var(--shadow-glass);
}

.modal-card {
    max-height: var(--drawer-max-h);
    border-radius: var(--radius-2xl);
    corner-shape: var(--corner-shape-surface);
    position: relative;
    width: 100%;
    max-width: 500px;
    transform: scale(0.96);
    transition: transform var(--transition-slow), opacity var(--transition), box-shadow var(--transition);
}

@media (max-width: 640px) {
    .modal-card { width: 95% !important; padding: 1.5rem !important; }
    .auth-social-icon { width: 3.5rem; height: 3.5rem; }
}

/* --- Chat Elements --- */

/* Пузырёк юзера — полупрозрачный токен БЕЗ backdrop-filter: лежит над плоским фоном чата,
   блюр там почти ничего не давал, но стоил перфа при скролле множества сообщений. */
.chat-bubble-user {
    background-color: var(--chat-input-bg);
    color: var(--text-main);
    border-radius: var(--chat-radius-xl);
    corner-shape: var(--corner-shape-surface);
    border-bottom-right-radius: var(--radius-chat-tail);
    font-size: var(--text-base);
    box-shadow: var(--shadow-glass);
}

/* User Bubble Markdown Reset */
.chat-bubble-user p { margin: 0; }
.chat-bubble-user > *:first-child { margin-top: 0; }
.chat-bubble-user > *:last-child { margin-bottom: 0; }

.chat-message-body { min-width: 0; max-width: 100%; }
.chat-message-body--assistant { width: 100%; }
.chat-message-column--assistant {
    --chat-avatar-size: 2.25rem;
    --chat-status-indent: calc(var(--chat-avatar-size) + var(--gap-sm) * 2);
    position: relative;
}
.chat-assistant-header {
    display: flex;
    align-items: center;
    gap: calc(var(--gap-sm) * 2);
    width: 100%;
    min-height: var(--chat-avatar-size);
    margin-bottom: var(--gap-sm);
}
.chat-assistant-avatar { width: var(--chat-avatar-size); height: var(--chat-avatar-size); }
/* Live statuses use the column as their containing block. All answer content
   keeps its natural full-width position below the header. */
.chat-message-column--assistant .chat-bubble-ai { position: static; }
.agent-flow__item:has(> .is-header-status) { display: contents; }
.chat-message-column--assistant .is-header-status {
    position: absolute;
    top: 0;
    left: var(--chat-status-indent);
    right: 0;
    min-height: var(--chat-avatar-size);
    margin: 0;
    display: flex;
    align-content: center;
    align-items: center;
}
.chat-message-body--user { padding: calc(var(--gap-sm) * 2); display: flex; flex-direction: column; gap: var(--gap-sm); }
.chat-message-column.has-attachments { width: var(--chat-attachment-width, 38rem); }
.chat-message-column.has-attachments .chat-message-body { width: 100%; }
.chat-message-body__text { min-width: 0; overflow-wrap: anywhere; }
.chat-message-body--user .chat-file-card { width: 100%; background: transparent; padding: 0; }
.chat-message-body--user .chat-file-card__header { padding: 0; }

/* Ordered rows own layout; players and file cards only fill their slot. */
.chat-msg-attachments { display: flex; flex-direction: column; gap: var(--gap-sm); width: 100%; min-width: 0; margin: 0; container-type: inline-size; container-name: sent-attachments; }
.chat-message-body--assistant > .chat-msg-attachments { margin-bottom: var(--gap-sm); }
.chat-attachment-row { display: flex; flex-wrap: wrap; gap: var(--gap-sm); min-width: 0; }
.chat-attachment { position: relative; min-width: 0; max-width: 100%; flex: 1 1 100%; }
.chat-attachment-row--audio > .chat-attachment { flex-basis: 17rem; }
.chat-attachment-row--image:not(.is-single) > .chat-attachment { flex-basis: calc((100% - var(--gap-sm)) / 2); }
.chat-attachment .audio-card, .chat-attachment .chat-file-card { width: 100%; }
.chat-attachment .audio-card__cover:not(:has(.audio-card__img)) .audio-card__badge-play { background: transparent; color: var(--text-main); }
.chat-attachment__visual { position: relative; width: 100%; aspect-ratio: var(--attachment-ratio, 4 / 3); max-height: 26rem; min-height: 8rem; border-radius: var(--radius-lg); corner-shape: var(--corner-shape-surface); overflow: hidden; background: var(--bg-hover); }
.chat-attachment-row--image:not(.is-single) .chat-attachment__visual { aspect-ratio: 4 / 3; }
.chat-attachment__open { display: block; width: 100%; height: 100%; padding: 0; border: 0; cursor: pointer; }
.chat-attachment .chat-msg-attachment-thumb { display: block; width: 100%; height: 100%; max-width: 100%; object-fit: cover; }
.chat-attachment-row.is-single .chat-msg-attachment-thumb { object-fit: contain; }
.chat-attachment-row.is-single .chat-attachment__visual { background: transparent; }
.chat-attachment__actions { position: absolute; top: var(--gap-sm); right: var(--gap-sm); z-index: 3; display: flex; gap: var(--gap-2xs); }
.chat-attachment__action { display: inline-flex; align-items: center; justify-content: center; width: 2.25rem; height: 2.25rem; padding: 0; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round); font-size: var(--text-lg); }
.chat-attachment__loading { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; color: var(--text-muted); font-size: var(--text-xs); }
.chat-attachment__error { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--gap-sm); padding: 3.5rem var(--gap-sm) var(--gap-sm); background: var(--bg-elevated); color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-snug); text-align: center; }
.chat-attachment__error .btn { min-height: 2.75rem; padding-inline: var(--gap-sm); }
.chat-attachment__open:focus-visible { outline: 2px solid var(--primary-500); outline-offset: -3px; }
.audio-card__error { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-sm); font-size: var(--text-xs); color: var(--text-muted); }
.audio-card__error button { text-decoration: underline; min-height: 2rem; }

/* Compact video has a dedicated seek row and never hides touch controls. */
.video-player.is-compact { display: block; width: 100%; max-width: 100%; aspect-ratio: var(--attachment-ratio, 4 / 3); max-height: 28rem; min-height: 12rem; background: var(--media-letterbox); }
.video-player.is-compact .video-player__big-play { top: 3rem; bottom: 5rem; }
.video-player.is-compact .video-player__media { width: 100%; height: 100%; max-height: none; object-fit: contain; }
.video-player.is-compact .video-player__bar { display: grid; grid-template-columns: 2.25rem auto 1fr auto auto 2.25rem; gap: var(--gap-2xs) var(--gap-sm); opacity: 1; }
.video-player.is-compact .video-player__progress { grid-column: 1 / -1; grid-row: 1; width: 100%; min-height: 1.5rem; }
.video-player.is-compact .video-player__progress::-webkit-slider-runnable-track { background: linear-gradient(to right, var(--overlay-text) var(--range-fill, 0%), color-mix(in srgb, var(--overlay-text) 30%, transparent) var(--range-fill, 0%)); }
.video-player.is-compact .video-player__progress::-moz-range-track { background: color-mix(in srgb, var(--overlay-text) 30%, transparent); }
.video-player.is-compact .video-player__progress::-moz-range-progress { background: var(--overlay-text); }
.video-player.is-compact .video-player__progress::-webkit-slider-thumb { background: var(--overlay-text); }
.video-player.is-compact .video-player__progress::-moz-range-thumb { background: var(--overlay-text); }
.video-player.is-compact .video-player__bar > .video-player__btn:first-child { grid-column: 1; grid-row: 2; }
.video-player.is-compact .video-player__t { grid-row: 2; }
.video-player.is-compact .video-player__t:nth-of-type(1) { grid-column: 2; }
.video-player.is-compact .video-player__t:nth-of-type(2) { grid-column: 4; }
.video-player.is-compact .video-player__volume { grid-column: 5; grid-row: 2; }
.video-player.is-compact .video-player__bar > .video-player__btn:last-child { grid-column: 6; grid-row: 2; }
.video-player:focus-within .video-player__bar { opacity: 1; }
@container sent-attachments (min-width: 30rem) {
    .chat-attachment-row--image:not(.is-single) > .chat-attachment { flex-basis: calc((100% - 2 * var(--gap-sm)) / 3); }
}
@container sent-attachments (max-width: 22rem) {
    .chat-attachment .audio-card { gap: var(--gap-sm); }
    .video-player.is-compact .video-player__volume { display: none; }
}
@media (pointer: coarse) {
    .chat-attachment__action, .chat-attachment .audio-card__action, .chat-attachment .chat-file-card__action,
    .video-player.is-compact .video-player__btn { width: 2.75rem; height: 2.75rem; }
    .video-player.is-compact .video-player__bar { grid-template-columns: 2.75rem auto 1fr auto auto 2.75rem; }
    .chat-attachment__actions .attachment-quote-btn { opacity: 1; }
}

.chat-bubble-ai {
    background-color: transparent;
    color: var(--text-main);
    padding-left: 0;
    font-size: var(--text-base);
}

/* ── Разделитель смены модели в ленте (маркер role='model_switch') ──
   Раскладку контейнера задают утилиты в шаблоне (flex/gap/max-w); здесь — только
   собственные части, чтобы не конкурировать с Tailwind по каскаду. */
.chat-model-divider__rule {
    flex: 1 1 auto;
    height: 1px;
    background: var(--surface-strong);
}
.chat-model-divider__chip {
    flex: 0 0 auto;
    font-size: var(--text-xs);
    line-height: var(--leading-none);
}
.chat-model-divider__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1rem;
    height: 1rem;
}
.chat-model-divider__icon :is(svg, img) {
    width: 100%;
    height: 100%;
    object-fit: contain;
}
.chat-model-divider__glyph {
    font-size: var(--text-base);
    color: var(--text-subtle);
}
.chat-model-divider__label {
    font-weight: var(--font-weight-medium);
    white-space: nowrap;
    color: var(--text-muted);
}
.chat-model-divider--switch { display: flex; flex-direction: column; align-items: center; gap: var(--gap-xs); padding-block: var(--gap-sm); text-align: center; }
.chat-model-divider--switch .chat-model-divider__chip { display: flex; align-items: center; justify-content: center; gap: var(--gap-xs); font-size: var(--text-xs); }
.chat-model-divider--switch .chat-model-divider__label { white-space: normal; font-weight: var(--font-weight-regular); }
.chat-model-divider__note { color: var(--text-subtle); font-size: var(--text-xs); line-height: var(--leading-snug); text-wrap: balance; }

/* Compact thumbnails for support chat. Sent chat attachments override these
   dimensions inside .chat-attachment; their row owns the geometry. */
.chat-msg-attachment-thumb {
    width: 6.5rem;
    height: 6.5rem;
    max-width: 100%;
    object-fit: cover;
    display: block;
}

@media (min-width: 768px) {
    .chat-msg-attachment-thumb {
        width: 7.5rem;
        height: 7.5rem;
    }
}

.chat-file-list { display: flex; flex-wrap: wrap; gap: 0.625rem; margin-top: 1rem; width: 100%; min-width: 0; max-width: 100%; }
.chat-file-card { --generation-radius: var(--radius-base); display: flex; flex-direction: column; width: 24rem; max-width: 100%; min-width: 0; padding: 0; gap: 0; overflow: hidden; border: 0; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); background: var(--bg-elevated); color: var(--text-main); }
.chat-file-card__header { display: flex; align-items: center; flex: 0 0 auto; width: 100%; min-width: 0; gap: var(--gap-sm); padding: calc(var(--gap-sm) * .5) var(--gap-sm); }
.chat-file-card__open { display: flex; align-items: center; flex: 1; min-width: 0; min-height: var(--artifact-control-size); gap: var(--gap-sm); text-align: left; border-radius: var(--radius-sm); corner-shape: var(--corner-shape-surface); }
.file-format-icon { display: block; width: 1.75rem; height: 1.75rem; flex: 0 0 1.75rem; object-fit: contain; }
.chat-file-card__text { display: block; min-width: 0; }
.chat-file-card__name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-xs); font-weight: var(--font-weight-medium); line-height: var(--leading-snug); color: var(--text-main); }
.chat-file-card__actions { display: flex; flex: 0 0 auto; gap: var(--gap-2xs); }
.chat-file-card__action { display: inline-flex; align-items: center; justify-content: center; width: var(--artifact-control-size); height: var(--artifact-control-size); border-radius: var(--radius-sm); corner-shape: var(--corner-shape-surface); color: var(--text-muted); font-size: var(--text-lg); }
.chat-file-card__action:hover { color: var(--text-main); background: var(--bg-hover); }
.chat-file-card button:focus-visible { outline: 2px solid var(--primary-500); outline-offset: -2px; }
.chat-media-gallery { display: flex; flex-wrap: nowrap; align-items: flex-start; gap: 0.625rem; width: 100%; min-width: 0; max-width: 100%; margin-top: 1rem; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity;cursor: grab; user-select: none; }

.chat-media-gallery.is-dragging { cursor: grabbing; scroll-snap-type: none; }
.chat-media-gallery.is-single { cursor: default; overflow: visible; }
.chat-media-gallery__item { flex: 0 0 13rem; min-width: 0; scroll-snap-align: start; }
.chat-media-gallery__frame { position: relative; width: 100%; height: 10rem; overflow: hidden; border-radius: var(--radius-lg); corner-shape: var(--corner-shape-surface); background: transparent; }
.chat-media-gallery__open { display: block; width: 100%; height: 100%; cursor: inherit; }
.chat-media-gallery__open img, .chat-media-gallery__open video { display: block; width: 100%; height: 100%; object-fit: cover; }
.chat-media-gallery__quote, .chat-media-gallery__share, .chat-media-gallery__play { z-index: 2; }
.chat-media-gallery__quote { position: absolute; top: 0.5rem; right: 0.5rem; display: flex; align-items: center; justify-content: center; width: 1.875rem; height: 1.875rem; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round); }
.chat-media-gallery__share { position: absolute; top: 0.5rem; right: 2.625rem; display: grid; place-items: center; width: 1.875rem; height: 1.875rem; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round); }
.chat-media-gallery__play { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: grid; place-items: center; width: 2.5rem; height: 2.5rem; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round); background: rgb(0 0 0 / 45%); color: #fff; }
.chat-media-gallery__status, .chat-media-gallery__load-error { display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 0.625rem; padding: 1rem; color: var(--text-muted); font-size: var(--text-xs); text-align: center; overflow-wrap: anywhere; }
.chat-media-gallery__frame.gen-loading--chat { padding: 0; }
.chat-media-gallery__frame.is-loaded { border: 0; background: transparent; }
.chat-media-gallery__frame .gen-loading__label { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
.chat-media-gallery.is-single .chat-media-gallery__item { flex: 0 1 28rem; max-width: 100%; }
.chat-media-gallery.is-single .chat-media-gallery__frame { width: fit-content; max-width: 100%; height: auto; min-height: 0; }
.chat-media-gallery.is-single .chat-media-gallery__frame:not(.is-loaded) { width: 100%; aspect-ratio: var(--generation-aspect, 1); min-height: 9rem; }
.chat-media-gallery__load-error { position: absolute; inset: 0; z-index: 1; overflow: auto; }
.chat-media-gallery.is-single .chat-media-gallery__open { width: fit-content; max-width: 100%; height: auto; border-radius: inherit; corner-shape: inherit; }
.chat-media-gallery.is-single .chat-media-gallery__open img, .chat-media-gallery.is-single .chat-media-gallery__open video { width: auto; height: auto; max-width: 100%; max-height: 70vh; object-fit: contain; border-radius: inherit; corner-shape: inherit; }
.chat-media-gallery__open:focus-visible { outline: 2px solid var(--prism-accent); outline-offset: 3px; }
.chat-file-card.is-interactive { width: 100%; }
.chat-artifact-preview { position: relative; width: 100%; min-height: 0; }
.chat-artifact-preview iframe { display: block; width: 100%; height: clamp(var(--artifact-preview-min-height), 48dvh, var(--artifact-preview-max-height)); border: 0; border-radius: 0; background: var(--bg-elevated); color-scheme: normal; }
.chat-file-card:fullscreen { width: 100%; height: 100%; border: 0; border-radius: 0; padding: 0; background: var(--bg-elevated); }
.chat-file-card:fullscreen .chat-artifact-preview { display: flex; flex-direction: column; flex: 1; }
.chat-file-card:fullscreen iframe { flex: 1; height: 0; min-height: 0; }
.shared-asset-page { display: flex; flex-direction: column; width: 100%; height: 100dvh; margin: 0; overflow: hidden; background: var(--bg-base, #101010); color: var(--text-main); font-family: var(--font-sans); }
.shared-asset-header { display: flex; align-items: center; flex: 0 0 auto; gap: 1.25rem; padding: 0.875rem 1.25rem; background: var(--bg-elevated); }
.shared-asset-brand { font-size: var(--text-lg); font-weight: var(--font-weight-semibold); text-decoration: none; }
.shared-asset-header h1 { flex: 1; min-width: 0; margin: 0; font-size: var(--text-sm); font-weight: var(--font-weight-medium); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.shared-asset-actions { display: flex; align-items: center; gap: 0.5rem; }
.shared-asset-actions a, .shared-asset-actions button { display: flex; align-items: center; gap: 0.5rem; padding: 0.625rem; border: 0; border-radius: var(--radius-md); corner-shape: var(--corner-shape-surface); background: transparent; color: var(--text-main); font: inherit; font-size: var(--text-xs); text-decoration: none; cursor: pointer; }
.shared-asset-actions a:hover, .shared-asset-actions button:hover { background: var(--bg-hover); }
.shared-asset-stage { display: flex; align-items: center; justify-content: center; flex: 1; min-height: 0; width: 100%; }
.shared-asset-stage iframe { display: block; width: 100%; height: 100%; border: 0; background: #fff; }
.shared-asset-stage img, .shared-asset-stage video { max-width: 100%; max-height: 100%; object-fit: contain; }
.shared-asset-stage audio { width: min(90%, 36rem); }
.shared-asset-fallback { text-align: center; }
.shared-asset-attribution { padding: 0.625rem 1rem; text-align: center; font-size: var(--text-2xs); color: var(--text-muted); }
.shared-asset-attribution a { text-decoration: underline; }
.shared-asset-fallback a { display: inline-block; padding: 1rem; text-decoration: underline; }
.shared-asset-notice { position: fixed; bottom: 1.5rem; left: 50%; transform: translateX(-50%); padding: 0.75rem 1rem; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); background: var(--bg-elevated); color: var(--text-main); font-size: var(--text-xs); }
.shared-asset-page.is-expanded .shared-asset-brand, .shared-asset-page.is-expanded h1 { display: none; }
.shared-asset-page.is-expanded .shared-asset-header { position: absolute; z-index: 2; top: 0.5rem; right: 0.5rem; padding: 0.25rem; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
@media (max-width: 767px) {
    .chat-media-gallery__item { flex-basis: 10.5rem; }
    .chat-media-gallery__frame { height: 8.5rem; }
    .chat-file-card { padding: 0.625rem; gap: 0.25rem; }
    .chat-file-card__open { gap: 0.5rem; }
    .chat-artifact-preview iframe { height: 20rem; }
    .shared-asset-header { gap: 0.75rem; padding: 0.625rem; }
    .shared-asset-actions span { display: none; }
}

/* Streaming cursor — blinking caret at end of AI response */
@keyframes cursor-blink {
    0%, 100% { opacity: 1; }
    50% { opacity: 0; }
}

.is-streaming .markdown-render > :last-child::after,
.is-streaming .markdown-render:empty::after {
    content: '';
    display: inline-block;
    width: 2.5px;
    height: 1.1em;
    background: var(--primary);
    vertical-align: text-bottom;
    border-radius: calc(1px * var(--radius-scale));
    margin-left: 1px;
    animation: cursor-blink var(--motion-period-cursor) steps(2) infinite var(--pane-ambient-play-state, running);
}

/* ========================================
   5. MARKDOWN CONTENT
   ======================================== */
.markdown-content {
    font-size: var(--text-chat);
    line-height: var(--leading-relaxed);
    color: var(--text-main);
    overflow-wrap: anywhere;
    word-break: break-word;
}

.markdown-table-wrap {
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    margin: 0.75rem 0;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
}

/* Фавиконка сайта перед текстом ссылки (вставляется в link_open, markdown.js).
   Размер в em — масштабируется со шрифтом ссылки. */
.md-link-favicon {
    display: inline-block;
    width: 1em;
    height: 1em;
    margin-right: 0.3em;
    vertical-align: -0.15em;
    border-radius: calc(0.2em * var(--radius-scale));
    object-fit: contain;
}

.markdown-content table {
    width: max-content;
    min-width: 100%;
    border-collapse: collapse;
    table-layout: auto;
    font-size: var(--text-base);
}

.markdown-content th,
.markdown-content td {
    padding: 0.55rem 0.75rem;
    text-align: left;
    vertical-align: top;
    overflow-wrap: normal;
    word-break: normal;
    hyphens: none;
}

.markdown-content th {
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    background-color: var(--bg-input);
}

.markdown-content tr:nth-child(even) td {
    background-color: var(--bg-input-45);
}

.markdown-content .katex-display {
    overflow-x: auto;
    overflow-y: hidden;
    padding: 0.125rem 0;
}

/* 1. Normalize spacing for common block elements */
.markdown-content p, .markdown-content ul, .markdown-content ol,
.markdown-content blockquote, .markdown-content pre {
    margin-top: 0.75rem;
    margin-bottom: 0.75rem;
}

/* 2. Kill outer margins to fit bubble padding perfectly */
.markdown-content > :first-child { margin-top: 0 !important; }
.markdown-content > :last-child { margin-bottom: 0 !important; }

/* If markdown is injected into a wrapper element (e.g. x-html), normalize its first/last block margins too */
.markdown-content .markdown-render > :first-child { margin-top: 0 !important; }
.markdown-content .markdown-render > :last-child { margin-bottom: 0 !important; }

/* Headings */
.markdown-content h1,
.markdown-content h2,
.markdown-content h3 {
    color: var(--text-main);
    margin-top: 1.5rem;
    margin-bottom: 0.5rem;
    font-weight: var(--font-weight-display);
    line-height: var(--leading-snug);
}
.markdown-content h1 {
    color: var(--text-main);
    padding-bottom: 0.5rem;
    font-size: var(--text-2xl);
}
.markdown-content h2 {
    font-size: var(--text-xl);
}
.markdown-content h3 {
    font-size: var(--text-lg);
}
.markdown-content a {
    color: var(--text-main);
    background: var(--surface-accent);
    padding: 0.125rem 0.375rem;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    text-decoration: none;
    /* подложка корректно переносится на новую строку */
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
}
.markdown-content ul,
.markdown-content ol {
    padding-left: 1.5rem;
}
.markdown-content ul { list-style-type: disc; }
.markdown-content ol { list-style-type: decimal; }
.markdown-content blockquote {
    position: relative;
    background-color: var(--bg-input);
    border-radius: var(--chat-radius-xl);
    corner-shape: var(--corner-shape-surface);
    padding: 0.75rem 1rem 0.75rem 1.25rem;
    margin: 1rem 0;
    overflow: hidden; /* To clip content to rounded corners */
}

.markdown-content hr {
    border: 0;
    height: 1px;
    background-color: var(--bg-raised);
    margin: 1.1rem 0;
}

[data-theme="light"] .markdown-content hr {
    background-color: var(--text-main-18);
}

/* Prevent long code/lines from widening the whole chat layout */
.markdown-content pre {
    max-width: 100%;
    overflow-x: auto;
    min-width: 0;
}

.markdown-content blockquote pre {
    max-width: 100%;
}

/* Rounded colored bar on the left */
.markdown-content blockquote::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 4px;
    background: linear-gradient(180deg, var(--text-main), var(--text-muted));
    opacity: 1;
}

/* Inline Code */
.markdown-content code {
    background: var(--surface-accent);
    color: var(--text-main);
    padding: 0.125rem 0.375rem;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    font-family: var(--font-mono);
    font-size: var(--text-sm);
}
.markdown-content pre code {
    background: transparent; padding: 0; color: inherit;
}

/* Think Block (Chain of thought) */
.think-accordion {
    background: var(--bg-input);
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    margin-bottom: 1rem;
    overflow: hidden;
}
.think-summary {
    padding: 0.75rem;
    cursor: pointer;
    color: var(--text-muted);
    font-size: var(--text-sm);
}
@media (hover: hover) {
    .think-summary:hover { background: var(--bg-hover); }
}
.think-content {
    padding: 1rem;
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.think-mode-shell {
    width: 100%;
    border-radius: var(--chat-radius);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    background-color: var(--chat-input-bg);
    box-shadow: var(--shadow-glass);
}

.think-mode-header {
    min-height: 2.25rem;
    background-color: transparent;
}

.think-mode-content {
    background-color: transparent;
}

/* Таймлайн этапов размышления: вертикальная линия с точками слева. */
.think-timeline {
    padding: 0.625rem 0.875rem 0.75rem;
}

.think-step {
    position: relative;
    padding-left: 1.25rem;
    padding-bottom: 0.875rem;
}

.think-step:last-child {
    padding-bottom: 0;
}

/* Соединительная линия — за точкой, до следующего этапа. */
.think-step::before {
    content: "";
    position: absolute;
    left: 0.28rem;
    top: 0.35rem;
    height: 100%;
    width: 1.5px;
    background: color-mix(in srgb, var(--text-subtle) 35%, transparent);
}

.think-step:last-child::before {
    display: none;
}

.think-step__dot {
    position: absolute;
    left: 0;
    top: 0.25rem;
    width: 0.625rem;
    height: 0.625rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: color-mix(in srgb, var(--text-subtle) 50%, transparent);
    /* кольцо цветом фона «гасит» линию под точкой */
    box-shadow: none;
}

/* Активный этап — тот, что пишется прямо сейчас. */
.think-step--active .think-step__dot {
    background: var(--primary-500);
    box-shadow: none;
}

.think-step__title {
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    margin-bottom: 0.125rem;
}

.think-step__text {
    font-size: var(--text-xs);
    font-family: var(--font-mono);
    color: var(--text-muted);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    word-break: break-word;
    line-height: var(--leading-normal);
}

/* Лента ответа ассистента: хронологические сегменты reasoning | action | text.
   Согласована с .think-step (таймлайн размышлений) по визуальному языку. */
.agent-flow {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 100%;
    min-width: 0;
}

/* Reasoning is rendered in a nested flex/grid message layout. Keep every
   level shrinkable so long model tokens cannot widen the mobile bubble. */
.agent-flow__item,
.agent-flow__reasoning,
.agent-flow__reasoning-body,
.think-timeline,
.think-step,
.think-step__body {
    max-width: 100%;
    min-width: 0;
}

/* Текстовый сегмент — markdown; отступ между соседними блоками. */
.agent-flow__text:not(:first-child) {
    margin-top: 0.25rem;
}

/* Медиа- и post-сегменты — заметнее текста, дышат сверху в ленте. */
.agent-flow__media,
.agent-flow__post {
    margin-top: 0.5rem;
}

/* Удалённая генерация в ленте чата — компактная плашка вместо битого файла
   (зеркало .tg-draft--gone для постов). Только токены. */
.agent-flow__media-gone {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.875rem;
    font-size: var(--text-xs);
    color: var(--text-muted);
    background-color: var(--bg-elevated);
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
}

/* ── Карточка-черновик поста в Telegram (.tg-draft) ──────────────────────
   Нейтральный «модный» вид в духе Telegram: скруглённый пузырёк, тонкая
   акцентная полоса слева, шапка с аватаром-логотипом. Только токены. */
.tg-draft {
    position: relative;
    padding: 0.875rem 0.875rem 0.875rem 1.125rem;
    background-color: var(--bg-elevated);
    border-radius: var(--chat-radius);
    corner-shape: var(--corner-shape-surface);
    box-shadow: none;
    transition: var(--transition);
}
.tg-draft.is-busy {
    opacity: 0.6;
    pointer-events: none;
}
/* Акцентная полоса слева — фирменный лайм. */
.tg-draft__bar {
    position: absolute;
    left: 0.5rem;
    top: 0.875rem;
    bottom: 0.875rem;
    width: 3px;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: var(--text-muted);
}

.tg-draft__head {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin-bottom: 0.75rem;
}
.tg-draft__avatar {
    flex: 0 0 auto;
    width: 1.75rem;
    height: 1.75rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: color-mix(in srgb, var(--text-main) 7%, transparent);
}
.tg-draft__avatar img {
    width: 1.05rem;
    height: 1.05rem;
    object-fit: contain;
}
.tg-draft__head-text {
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: var(--leading-tight);
}
.tg-draft__title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
}
.tg-draft__channel {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: var(--text-xs);
    color: var(--text-muted);
}
.tg-draft__channel i { font-size: var(--text-xs); }

/* Медиа поста — превью-плитки. */
.tg-draft__media {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}
.tg-draft__thumb {
    position: relative;
    width: 4rem;
    height: 4rem;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    background-color: var(--bg-raised);
}
.tg-draft__thumb img,
.tg-draft__thumb-file {
    width: 100%;
    height: 100%;
    cursor: pointer;
}
.tg-draft__thumb img { object-fit: cover; }
.tg-draft__thumb-file {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    font-size: var(--text-xl);
}
.tg-draft__thumb-load {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--overlay-pill-bg-soft);
}
.tg-draft__thumb-x {
    position: absolute;
    top: 0.25rem;
    right: 0.25rem;
    width: 1.25rem;
    height: 1.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: var(--overlay-pill-bg);
    color: var(--overlay-text);
    font-size: var(--text-2xs);
}
.tg-draft__thumb-x:hover { background-color: var(--overlay-pill-bg-strong); }
/* Плитка добавления фото — пунктирная, в духе «+» композера. */
.tg-draft__add {
    width: 4rem;
    height: 4rem;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    font-size: var(--text-xl);
    background-color: transparent;
    box-shadow: none;
    transition: var(--transition);
}
.tg-draft__add:hover {
    color: var(--text-main);
    box-shadow: none;
}

/* Текст черновика / правки. */
.tg-draft__text {
    padding: 0.5rem 0.75rem;
    font-size: var(--text-sm);
    resize: none;
    margin-bottom: 0.625rem;
}
.tg-draft__published-text {
    font-size: var(--text-sm);
    color: var(--text-main);
    white-space: pre-wrap;
    word-break: break-word;
    margin-bottom: 0.625rem;
}
.tg-draft__hint {
    display: flex;
    align-items: flex-start;
    gap: 0.375rem;
    font-size: var(--text-xs);
    color: var(--text-muted);
    margin-bottom: 0.625rem;
}
.tg-draft__hint i { margin-top: 0.05rem; flex: 0 0 auto; }

/* Ряд действий. */
.tg-draft__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}
.tg-draft__btn {
    height: 2.25rem;
    padding-left: 1rem;
    padding-right: 1rem;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}
.btn-ghost.tg-draft__btn { font-weight: var(--font-weight-medium); }
.tg-draft__chip {
    height: 2.25rem;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0 0.75rem;
    font-size: var(--text-sm);
}

/* Удалённый пост — компактная нейтральная плашка. */
.tg-draft--gone {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.875rem;
    font-size: var(--text-xs);
    color: var(--text-muted);
    background-color: var(--bg-elevated);
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    box-shadow: none;
}

/* Превью-миниатюра в выпадайке «Из чата» (composerPlusSheet item iconHtml). */
.tg-pick-thumb {
    width: 1.5rem;
    height: 1.5rem;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    object-fit: cover;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: var(--bg-raised);
    color: var(--text-muted);
}
.tg-pick-thumb--file { font-size: var(--text-sm); }

/* Reasoning-сегмент — компактный сворачиваемый блок. */
.agent-flow__reasoning {
    margin: 0.375rem 0;
}

.agent-flow__reasoning-toggle {
    display: inline-flex;
    max-width: 100%;
    min-width: 0;
    align-items: center;
    gap: 0.375rem;
    padding: 0.125rem 0;
    background: none;
    border: none;
    cursor: pointer;
    font-size: var(--text-xs);
    color: var(--text-muted);
}

.agent-flow__reasoning-toggle:hover {
    color: var(--text-main);
}

.agent-flow__reasoning-tokens {
    color: var(--text-subtle);
}

/* Контейнер раскрытого reasoning — лишь обёртка для таймлайна .think-step.
   Без pre-wrap/font-mono: за вид этапов отвечают сам таймлайн и .think-step__text
   (иначе pre-wrap превращает отступы разметки в пустые вертикальные зазоры). */
.agent-flow__reasoning-body {
    margin-top: 0.25rem;
}

.agent-actions { min-width: 0; margin: 0.375rem 0; }
.agent-actions__toggle {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    max-width: 100%;
    padding: 0.125rem 0;
    text-align: left;
    color: var(--text-muted);
    background: none;
    border: 0;
    cursor: pointer;
}
.agent-actions__toggle > .agent-status {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.agent-actions__toggle > :not(.agent-status) { flex-shrink: 0; }
.agent-actions__toggle:hover { color: var(--text-main); }
.agent-actions__count { color: var(--text-subtle); font-size: var(--text-xs); }
.agent-actions__history { margin-top: var(--gap-sm); }
.agent-actions__history > ol { list-style: none; }
.agent-actions__history .agent-step { margin: 0; }

/* ── Унифицированный статус-лейбл ленты: размышления / действия / поиск ──
   Один шрифт во всех состояниях (sm, semibold). Активный — перелив (.is-active,
   см. общий shimmer-rule ниже); завершённый — тот же шрифт, просто серый. Без
   иконок-маркеров: активность показывают перелив лейбла и крутящееся лого. */
.agent-status {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-subtle);
}

/* Action-сегмент: статус-лейбл + краткая сводка (домены поиска и т.п.). */
.agent-step {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.125rem 0.5rem;
    margin: 0.375rem 0;
    line-height: var(--leading-normal);
}
.agent-step > span { min-width: 0; max-width: 100%; overflow-wrap: anywhere; }

.agent-step__summary {
    font-size: var(--text-xs);
    color: var(--text-subtle);
}

/* Краткий итог завершённого шага («Готово» / «найдено N» / «Ошибка»). Нейтральный,
   без красного/зелёного (см. --red-500 у токенов). Отделён точкой от детали/лейбла. */
.agent-step__result {
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    color: var(--text-muted);
}
.agent-step__result::before {
    content: "·";
    margin-right: 0.5rem;
    color: var(--text-subtle);
}

/* Text illumination has its own clock, separate from the large ambient clouds.
   Semantic status states opt into the same recipe without animating idle text. */
.text-shimmer,
.agent-status.is-active,
.shell-user-pill__balance.is-refreshing {
    background-image: var(--text-shimmer-gradient);
    background-size: 200% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: var(--text-muted);
    text-shadow: var(--text-shimmer-shadow);
    animation: text-shimmer var(--text-shimmer-duration) var(--text-shimmer-ease) infinite var(--pane-ambient-play-state, running);
}
.text-shimmer { display: inline-block; max-width: 100%; }
.agent-status.is-active { width: fit-content; max-width: 100%; }
@keyframes text-shimmer {
    0%, 100% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
}
:root[data-theme="prism-light"] {
    --text-shimmer-gradient: linear-gradient(90deg,
        var(--text-muted) 0%, var(--text-main) 35%,
        color-mix(in srgb, var(--text-main) 80%, var(--prism-accent)) 50%,
        var(--text-main) 65%, var(--text-muted) 100%);
    --text-shimmer-shadow: none;
}
@media (prefers-reduced-motion: reduce), (forced-colors: active) {
    .text-shimmer, .agent-status.is-active, .shell-user-pill__balance.is-refreshing {
        animation: none;
        background: none;
        -webkit-text-fill-color: currentColor;
        text-shadow: none;
    }
}

/* ========================================
   6. CODE BLOCKS
   ======================================== */
.code-block-wrapper {
    border-radius: var(--chat-radius-xl);
    corner-shape: var(--corner-shape-surface);
    margin: 0.5rem 0;
    overflow: hidden;
     position: relative;
    box-shadow: var(--shadow-code);
    display: flex;
    flex-direction: column;
    max-width: 100%;
    min-width: 0;
}

.code-block-wrapper pre {
    margin: 0;
    padding: 0.75rem 1rem 0.25rem 1rem;
    overflow-x: auto;
    background: transparent;
    box-shadow: none;
    border-radius: 0;
    max-width: 100%;
    min-width: 0;
    box-sizing: border-box;
}

.code-block-wrapper code {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
}

/* Media-composer dynamic spacer (chat composer in normal flow doesn't need it). */
.input-spacer {
    height: var(--input-height, 0px);
}
/* The composer owns size motion. Its spacer reflects that live geometry,
   without a second easing clock that also moves the centered page title. */

/* ── Chat page layout ──
   Единая flex-колонка чата. Активное состояние: composer — absolute-overlay
   с glass-fade поверх скролл-области; сообщения скроллятся под ним, последнее
   сообщение помещается выше композера через padding-bottom = --composer-height.
   Пустое состояние: composer в нормальном flow, родитель центрирует/прижимает
   его, #chat-container скрыт через x-show.

   Один источник правды по высоте композера — CSS-переменная --composer-height,
   которую ResizeObserver в scroll.js пишет на .chat-page при каждом изменении
   габаритов dock'а (цитата, multiline, params). Никакого Alpine state, никаких
   магических констант. */
.chat-page {
    min-width: 0;
    position: relative;
    --composer-height: 0px;
}

.chat-page > #chat-container {
    flex: 1 1 auto;
    scrollbar-gutter: stable;
    /* Scroll pinning reads this padding through _chatTopInset. */
    padding-top: var(--shell-content-top);
}

.chat-page > #chat-container > [x-ref='messagesList'] {
    display: flow-root;
    padding-top: 0;
}

/* Alpine templates are DOM siblings but not visual rows. Space only actual
   messages, otherwise the first row gains a phantom margin above the page. */
.chat-messages-list > .chat-message-wrap + :is(.chat-message-wrap, .chat-typing-indicator) {
    margin-top: calc(var(--gap-sm) * 4);
}


/* Entrance сообщений — два слоя с разным владением:
   • Вход в чат (открытие/переключение) — волна по ВИДИМОМУ ОКНУ (~30 узлов):
     класс .messages-list-enter взводит chat.js:_armMessagesEnter ровно на
     длительность keyframe. Безусловный слой [data-msg-id]{animation:...}
     удалён — он играл на каждом узле при любой гидрации, а с окном рендера
     ещё и переигрывал бы волну на каждом скролл-догрузе старых сообщений.
   • Живые аппенды (отправка/приём) — WAAPI chat.js:_animateMessageEnter. */
@keyframes chat-message-enter {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
}

.messages-list-enter [data-msg-id],
.messages-list-enter .transcribe-msg {
    animation: chat-message-enter var(--motion-duration-base) var(--motion-ease-premium);
}

@media (prefers-reduced-motion: reduce) {
    .messages-list-enter [data-msg-id],
    .messages-list-enter .transcribe-msg {
        animation: none;
    }
}

.chat-page.is-empty {
    /* Резервируем место под mobile overlay header — в empty контейнер скрыт,
       и без этого composer налезал бы на header. На desktop var == 0. */
    padding-top: var(--shell-mobile-header-offset);
}

.chat-page.is-empty > #chat-container {
    display: none;
}

/* Активное состояние: composer overlay'ит сообщения. Dock — пустая
   позиционная обёртка без визуальных эффектов: ни фона, ни тени, ни blur.
   Всё видимое стекло живёт внутри pill'а (.chat-input-shell). Прозрачная
   зона dock'а пропускает wheel/touch к scroll-области позади; форма внутри
   получает .pointer-events-auto. */
.chat-page:not(.is-empty) > .chat-composer-dock {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 5;
    pointer-events: none;
}

.chat-page:not(.is-empty) > #chat-container {
    padding-bottom: var(--composer-height);
}

/* Композер базовый: padding'и сохраняются и для empty (in-flow), и для
   active (absolute overlay). Высота снимается ResizeObserver'ом по факту. */
.chat-composer-dock {
    padding-top: 1rem;
    padding-bottom: 0;
}

/* Same empty-chat advisory on both layouts, without duplicating live regions.
   Keep the mobile input dock at the bottom; only the notice moves above it. */
.chat-composer-content {
    display: flex;
    flex-direction: column;
}

.chat-composer-content > .chat-input-state-host { order: 1; }

.chat-model-cost-notice-motion {
    --cost-notice-slide: -100%;
    order: 2;
    align-self: center;
    max-width: 100%;
}

@media (min-width: 768px) {
    .chat-model-cost-notice-motion {
        /* Advisory is independent of the centered composer geometry. Its
           reveal must not move the input as the notice gains/loses height. */
        position: absolute;
        top: 100%;
        inset-inline: 0;
        width: max-content;
        margin-inline: auto;
    }
}

.chat-model-cost-notice-slot {
    /* No independent mount animation: ShellMotion reveals this together with
       the input. Keep a zero-height grid when closed so later state changes
       can slide normally without display:none / @starting-style re-entry. */
    visibility: visible;
    transition-property: visibility, grid-template-rows, opacity;
}

.chat-model-cost-notice-slot:not(.is-open) {
    display: grid;
    visibility: hidden;
}

@starting-style {
    .chat-model-cost-notice-slot.is-open {
        grid-template-rows: 1fr;
        opacity: 1;
    }
}

.chat-model-cost-notice {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    max-width: 100%;
    margin-top: 1rem;
    padding: 0.75rem 1rem;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
    color: var(--text-muted);
    text-align: left;
    transform: translateY(0);
    transition: transform var(--motion-duration-base) var(--motion-ease-premium);
}

.chat-model-cost-notice-slot:not(.is-open) .chat-model-cost-notice {
    transform: translateY(var(--cost-notice-slide));
}

.chat-model-cost-notice__icon {
    display: grid;
    place-items: center;
    flex: 0 0 2rem;
    width: 2rem;
    height: 2rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-main);
    font-size: var(--text-lg);
}

.chat-model-cost-notice__text {
    min-width: 0;
    margin: 0;
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    overflow-wrap: anywhere;
}

@media (max-width: 767px) {
    .chat-model-cost-notice-motion {
        --cost-notice-slide: 100%;
        order: 0;
        width: 100%;
    }
    .chat-model-cost-notice {
        margin-top: 0;
        margin-bottom: 1.25rem;
        padding: 0.75rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .chat-model-cost-notice { transition: none; }
}

@media (min-width: 768px) {
    .chat-composer-dock {
        padding-bottom: var(--app-frame-inset-desktop);
    }
}

@media (max-width: 767px) {
    /* Пустой стейт (welcome, до первого сообщения) прижимаем к низу ТЕМ ЖЕ
       absolute-оверлеем, что и активный чат — НЕ in-flow justify-content:flex-end.
       На реальных мобильных Firefox/Safari (динамическая адресная строка) in-flow
       flex-end dock отрывается от истинного низа и «висит в воздухе», а absolute
       bottom:0 прижат надёжно (A/B от юзера: активный чат, где dock уже absolute,
       НЕ висит; пустой, где flex-end, — висит). Headless-движки баг не
       воспроизводят (нет адресной строки), поэтому фикс = зеркалить рабочий
       absolute-паттерн. padding-bottom наследует базовые 0 (как активный dock) —
       без скачка пилюли после первого сообщения. pointer-events НЕ гасим: за
       пустым dock'ом нет скроллера (в отличие от активного), чипы/бренд кликаются. */
    .chat-page.is-empty > .chat-composer-dock {
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 5;
    }

    /* Композер на mobile — плавающая пилюля: равные минимальные отступы по бокам
       и снизу (не edge-to-edge), скругление со всех сторон. Снизу + safe-area,
       чтобы на iOS сохранялся клиренс над home-indicator (Android env=0 → ровно gap). */
    .chat-composer-dock {
        padding-bottom: calc(var(--composer-edge-gap) + var(--composer-sab));
    }

    .chat-composer-dock.app-edge-gutters {
        padding-inline: var(--composer-edge-gap);
    }

    .chat-composer-dock > .max-w-3xl {
        max-width: 100%;
        padding-inline: 0;
    }
}

/* Empty-state композер: desktop — центрирован с воздухом снизу (in-flow).
   Mobile-прижатие — absolute bottom:0 в блоке @media (max-width:767px) выше
   (тот же паттерн, что активный чат; in-flow flex-end «висел в воздухе»). */
@media (min-width: 768px) {
    .chat-page.is-empty {
        justify-content: center;
    }

    .chat-page.is-empty > .chat-composer-dock {
        padding-bottom: 5rem;
    }
}

@media (max-width: 767px) {
    /* .chat-page.is-empty на mobile прижимает композер через absolute-dock
       (блок @media выше), а не justify-content — flex-end здесь был бы мёртв. */
    .chat-mobile-sheet {
        background-color: transparent;
        border-radius: 0;
        box-shadow: none;
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }

    /* Двойной класс (0,2,0) перебивает utility `pb-0` на доке из шаблона
       (_composer_media.html) — одноклассовый .chat-mobile-sheet проиграл бы tailwind
       pb-0 (позже в каскаде). Плавающая пилюля: минимальный gap по бокам и снизу
       + safe-area. */
    .chat-mobile-sheet.app-edge-gutters {
        padding-inline: var(--composer-edge-gap);
        padding-bottom: calc(var(--composer-edge-gap) + var(--composer-sab));
    }

    .chat-mobile-sheet > .max-w-3xl {
        max-width: 100%;
        padding-inline: 0;
    }

    /* Кап высоты композера + внутренний скролл вынесены наружу этого @media
       (применяются на всех ширинах) — см. блок «Composer height cap» ниже. */

    /* Все композеры на mobile — плавающие пилюли со скруглением со ВСЕХ сторон
       (падают на базовое .chat-input-shell.shape = var(--radius-xl)). Прежний
       sheet-look (скруглён только верх, квадратный низ, edge-to-edge) убран. */
}

/* Hidden transition layers can extend below the page. Clip that overflow without
   creating another scroll container that focus/scrollIntoView can move. */
.media-page { overflow: clip; }

/* === Composer height cap (все ширины) ===
   Медиа-композер докнут снизу и растёт вверх. Кап высоты пилюли = вьюпорт минус
   реальный docking-инсет снизу, хром формы и мобильную шапку сверху. Лишние поля
   прокручиваются внутри scroll-region. Док с кнопками остаётся прижат снизу
   (flex-shrink:0).
   Раньше кап был только на mobile (75dvh) → на десктопе композер рос без потолка и
   его верх срезал overflow:hidden у <main>. */
.chat-input-docked .chat-input-main-shell {
    /* Базис — высота контейнера (.media-page), которую mediaApp пишет в
       --composer-cap-basis; фолбэк 100dvh (до первого замера / вне медиа-страницы).
       Контейнерный базис учитывает in-flow баннер над шеллом (main начинается не от
       y=0), поэтому верх композера упирается в верх .media-page, а не режется. */
    max-height: calc(var(--composer-cap-basis, 100dvh) - var(--composer-bottom-reserved, 0px) - var(--composer-top-reserved, 0px));
}

/* Flex-цепочка: scroll-region тянется и скроллит, dock-region прижат снизу.
   Инертна, пока контент влезает (кап не достигнут). Скоуп — .chat-input-docked
   (ВСЕ ширины), не только мобильный лист: раньше на десктопе цепочки не было —
   scroll-region не сжимался (нет min-height:0), overflow:auto капнутого композера
   не давал скролла, и «внутри не прокручивалось» при упоре в верх. */
.chat-input-docked .chat-input-zone {
    min-height: 0;
    flex: 1 1 auto;
}

.chat-input-docked .media-composer-normal-layer {
    flex: 1 1 auto;
    min-height: 0;
}

.chat-input-docked .media-composer-scroll-region {
    flex: 1 1 auto;
    min-height: 0;
}

/* Внутренний скролл включаем ТОЛЬКО когда композер реально закапан (высота контента
   превысила потолок пилюли — mediaApp ставит .is-composer-capped). Иначе overflow:auto
   срезал бы «выступающие» элементы, которые нарочно вылезают вверх за коробку
   scroll-region (media-composer-top-stack с margin-top:-88px — плитки кадров
   Старт/Конец/Аудио у видео). Вне капа overflow остаётся visible → они видны целиком. */
.chat-input-docked.is-composer-capped .media-composer-scroll-region {
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Тянем область прокрутки к самому верху пилюли: отрицательный margin убирает
       мёртвую зону composer-inset над скроллом (из-за неё контент обрезался на ~10px
       РАНЬШЕ края карточки), а равный padding-top возвращает отступ ВНУТРЬ прокрутки —
       поэтому в покое верхний контент не жмётся к краю, а маска гасит его ровно у кромки
       при прокрутке (в покое зона маски = пустой padding, контент не затемняется). */
    margin-top: calc(-1 * var(--composer-inset));
    padding-top: var(--composer-inset);
    /* Снизу симметрично: буфер padding-bottom (пустой у самого низа) + затухание —
       контент гаснет у дока при прокрутке, но ПОСЛЕДНЯЯ строка (когда докручено донизу)
       остаётся в чёткой зоне, т.к. под ней пустой буфер. */
    padding-bottom: var(--composer-inset);
    --scroll-edge-size: var(--composer-inset);
}
.chat-input-docked.is-composer-capped .music-composer-layout > .media-composer-scroll-region {
    margin-top: calc(var(--gap-sm) - var(--composer-inset));
}

/* === Кап высоты ЧАТ-композера (докнутый и empty-state) ===
   У чата капа не было вовсе: огромный вставленный текст растил пилюлю за пределы
   страницы — верх уезжал под шапку/баннер, низ с кнопками «уплывал» за экран.
   Базис пишет resizeChatInput (ui.js) в --composer-cap-basis на .chat-page
   (учитывает in-flow баннер над шеллом), фолбэк 100dvh. min-height:0 по цепочке —
   textarea (свой overflow-y:auto) сжимается и скроллит внутри. Селектор скоуплен
   .chat-page — медиа-композер (.media-page) живёт правилом .chat-input-docked выше. */
.chat-page .chat-input-main-shell {
    max-height: calc(var(--composer-cap-basis, 100dvh) - 1.25rem);
    min-height: 0;
}
.chat-page .chat-input-zone {
    min-height: 0;
}

/* Chat input docking: avoid Tailwind bottom-* conflicts by using a semantic class.
   Используется только media composer (`_composer_media.html` — absolute-режим). */

.chat-input-docked {
    bottom: 0;
    /* Резервы для капа высоты (см. .chat-input-main-shell max-height ниже):
       снизу — реальный docking-инсет, сверху — хром над пилюлей (0 по умолчанию,
       у музыки — ряд «Создать музыку / Создать звук»). Мобильные формы также
       резервируют шапку shell; этот резерв не является padding композера. */
    /* Реально зарезервированное снизу = gap плавающей пилюли + safe-area (совпадает
       с padding-bottom дока), чтобы кап высоты не лез в нижний зазор. Desktop ниже
       переопределяет на --app-frame-inset-desktop. */
    --composer-bottom-reserved: calc(var(--composer-edge-gap) + var(--composer-sab));
    --composer-header-reserved: 0px;
    --composer-chrome-reserved: 0px;
    --composer-top-reserved: calc(var(--composer-header-reserved) + var(--composer-chrome-reserved));
}

/* У музыки над пилюлей стоит ряд «Создать музыку / Создать звук» —
   резервируем его высоту вместе с pt-4 листа (16px + ряд ~40px = 56px), чтобы
   при упоре в верх он оставался целиком виден, а не срезался кромкой контейнера. */
.app-root[data-page-category='music'] .chat-input-docked {
    --composer-chrome-reserved: 3.5rem;
}

@media (max-width: 767.98px) {
    /* The shell owns the header height. Every media form scrolls below it;
       overflow never changes the stacking order of the page. */
    .media-mobile-composer-sheet {
        --composer-header-reserved: var(--shell-mobile-header-offset);
    }
}

@media (min-width: 768px) {
    .chat-input-docked {
        bottom: var(--app-frame-inset-desktop);
        --composer-bottom-reserved: var(--app-frame-inset-desktop);
    }
}

.media-composer-toggle,
.media-composer-reopen,
.media-composer-morph-surface { display: none; }

@media (max-width: 1099.98px) {
    .media-mobile-composer-sheet.is-mobile-collapsible {
        --media-composer-handle-size: calc(var(--composer-control-size) + var(--gap-xs));
        --media-composer-button-width: var(--mobile-action-width);
        --media-composer-button-height: var(--mobile-action-height);
        --media-composer-button-lift: var(--mobile-action-lift);
        --media-composer-morph-duration: var(--motion-duration-shell);
        --composer-chrome-reserved: calc(var(--media-composer-handle-size) + var(--gap-sm));
        --composer-bottom-reserved: calc(var(--composer-edge-gap) + var(--composer-sab));
        padding-top: var(--composer-chrome-reserved);
        padding-bottom: var(--composer-bottom-reserved);
    }
    /* The real fields keep their geometry and draft throughout the morph.
       Only this shared glass surface changes size; native CSS transitions can
       reverse from any frame without timers, snapshots or stale measurements. */
    .is-mobile-collapsible .media-composer-morph-surface {
        display: block;
        position: absolute;
        bottom: 0;
        left: 50%;
        transform: translateX(-50%);
        width: 100%;
        height: 100%;
        pointer-events: none;
    }
    .media-page.composer-anim-ready .is-mobile-collapsible .media-composer-morph-surface {
        transition: width var(--media-composer-morph-duration) var(--motion-ease-premium),
                    height var(--media-composer-morph-duration) var(--motion-ease-premium),
                    bottom var(--media-composer-morph-duration) var(--motion-ease-premium),
                    border-radius var(--media-composer-morph-duration) var(--motion-ease-premium),
                    background-color var(--media-composer-morph-duration) var(--motion-ease-standard);
    }
    .is-mobile-collapsed .media-composer-morph-surface {
        width: min(100%, var(--media-composer-button-width));
        height: var(--media-composer-button-height);
        bottom: var(--media-composer-button-lift);
        border-radius: var(--mobile-action-radius);
        background-color: var(--mobile-action-bg);
    }
    .is-mobile-collapsible .chat-input-main-shell {
        background: transparent;
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }
    .is-mobile-collapsible .chat-input-main-shell::before { display: none; }
    .is-mobile-collapsible .media-composer-morph-surface::before {
        content: '';
        position: absolute;
        inset: 0;
        border-radius: inherit;
        corner-shape: inherit;
        box-shadow: var(--shadow-composer);
        z-index: -1;
        pointer-events: none;
    }
    .is-mobile-collapsible .media-composer-morph-surface::after {
        content: '';
        position: absolute;
        inset: 0;
        border-radius: inherit;
        corner-shape: inherit;
        box-shadow: var(--mobile-action-glow);
        opacity: 0;
        pointer-events: none;
        transition: opacity var(--motion-duration-fast) var(--motion-ease-standard);
    }
    .is-mobile-collapsed .media-composer-morph-surface::after {
        opacity: 1;
    }
    .is-mobile-collapsed .media-composer-morph-surface::before {
        box-shadow: var(--glow-accent-strong);
        will-change: opacity;
        animation: media-composer-glow var(--motion-period-glow) var(--motion-ease-ambient) infinite var(--pane-ambient-play-state, running);
    }
    .is-mobile-collapsible > .media-composer-toggle {
        display: flex;
        position: absolute;
        top: 0;
        left: 50%;
        transform: translateX(-50%);
        width: var(--media-composer-handle-size);
        height: var(--media-composer-handle-size);
        min-height: var(--media-composer-handle-size);
        padding: 0;
        border-radius: 50%;
        corner-shape: var(--corner-shape-round);
        background: var(--chat-input-bg);
        box-shadow: none;
        pointer-events: auto;
        touch-action: manipulation;
        transition: opacity var(--motion-duration-fast) var(--motion-ease-standard),
                    visibility var(--motion-duration-fast) var(--motion-ease-standard);
    }
    .media-composer-toggle > .ti {
        display: flex;
        align-items: center;
        justify-content: center;
        width: calc(var(--gap-sm) * 3);
        height: calc(var(--gap-sm) * 3);
    }
    .is-mobile-collapsible > .media-composer-reopen {
        display: flex;
        position: absolute;
        bottom: calc((100% - var(--composer-chrome-reserved) + var(--composer-bottom-reserved) - var(--media-composer-button-height)) / 2);
        left: 50%;
        transform: translateX(-50%);
        z-index: 2;
        width: min(calc(100% - var(--composer-edge-gap) * 2), var(--media-composer-button-width));
        height: var(--media-composer-button-height);
        min-height: var(--media-composer-button-height);
        gap: calc(var(--gap-sm) * 1.5);
        padding: 0 var(--gap-sm);
        border-radius: var(--mobile-action-radius);
        background: transparent;
        color: var(--text-main);
        font-size: var(--text-base);
        font-weight: var(--font-weight-semibold);
        white-space: nowrap;
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
        touch-action: manipulation;
        transition: bottom var(--media-composer-morph-duration) var(--motion-ease-premium),
                    opacity var(--media-composer-morph-duration) var(--motion-ease-standard),
                    visibility var(--media-composer-morph-duration) var(--motion-ease-standard);
    }
    .is-mobile-collapsed > .media-composer-reopen {
        bottom: calc(var(--composer-bottom-reserved) + var(--media-composer-button-lift));
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
    }
    .media-composer-reopen > .ti { font-size: var(--text-xl); line-height: var(--leading-none); }
    .is-mobile-collapsible .chat-input-main-shell,
    .is-mobile-collapsible .generation-mode-selector {
        transition: opacity var(--motion-duration-fast) var(--motion-ease-standard),
                    visibility var(--motion-duration-drawer) var(--motion-ease-standard);
    }
    .is-mobile-collapsible .generation-mode-selector {
        transition: max-height var(--motion-duration-fast) var(--motion-ease-premium),
                    padding-top var(--motion-duration-fast) var(--motion-ease-premium),
                    padding-bottom var(--motion-duration-fast) var(--motion-ease-premium),
                    opacity var(--motion-duration-fast) var(--motion-ease-standard),
                    visibility var(--motion-duration-drawer) var(--motion-ease-standard);
    }
    .is-mobile-collapsed > .media-composer-toggle,
    .is-mobile-collapsed .chat-input-main-shell,
    .is-mobile-collapsed .generation-mode-selector,
    .is-mobile-content-pending .chat-input-main-shell,
    .is-mobile-content-pending .generation-mode-selector {
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
    }
    .is-mobile-collapsed > #media-composer-content { pointer-events: none; }
    /* Reversing a partial close must not leave fading fields over a small surface. */
    .is-mobile-content-pending:not(.is-mobile-collapsed) .chat-input-main-shell,
    .is-mobile-content-pending:not(.is-mobile-collapsed) .generation-mode-selector {
        transition: none;
    }
}

@keyframes media-composer-glow {
    0%, 100% { opacity: .5; }
    50% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .media-page.composer-anim-ready .is-mobile-collapsible .media-composer-morph-surface,
    .is-mobile-collapsible > .media-composer-toggle,
    .is-mobile-collapsible > .media-composer-reopen,
    .is-mobile-collapsible .chat-input-main-shell,
    .is-mobile-collapsible .generation-mode-selector { transition: none; }
    .is-mobile-collapsible .media-composer-morph-surface::after { animation: none; transition: none; }
    .is-mobile-collapsible .media-composer-morph-surface::before { animation: none; will-change: auto; }
}

/* === Медиа-страница <1100px: чат-паттерн (композер-оверлей, лента под ним) ===
   Десктоп-сайдбар (≥1100) исчезает, и тот же фид (_generation_feed.html) монтируется
   секцией-контентом. Композер — absolute-оверлей снизу (как .chat-composer-dock):
   прозрачная обёртка с pointer-events:none, всё стекло в пилюле; лента/result-area
   скроллятся ПОД ним и блюрятся стеклом пилюли. Лента получает нижний паддинг = высоте
   композера (--input-height, его ведёт ResizeObserver в mediaApp), чтобы последние
   карточки выходили из-под него. Scoped под .media-page.is-mobile-*. */
@media (max-width: 1099.98px) {
    /* Композер-оверлей снизу (перебивает sticky <768 и оставляет absolute 768–1100). */
    .media-page.is-mobile-history .media-mobile-composer-sheet {
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        padding-inline: var(--composer-edge-gap);
        padding-bottom: var(--composer-edge-gap);
        --composer-bottom-reserved: var(--composer-edge-gap);
    }

    /* The feed and expanded composer share the same edges throughout the
       mobile layout, including tablets. The desktop 48rem form cap belongs
       only to the layout with a separate history sidebar (>=1100px). */
    .media-page.is-mobile-history .media-mobile-composer-sheet > #media-composer-content {
        max-width: none;
    }

    .media-page.is-mobile-history .sidebar-section-pad {
        padding-inline: var(--composer-edge-gap);
    }

    /* Лента скроллится под композером-оверлеем — низ = высоте композера. */
    /* Офсет под мобильную шапку — на самом СКРОЛЛЕРЕ ленты (а не на секции), чтобы
       контент уезжал ПОД шапку (как чаты/главная), без пустой полосы под свёрнутой
       шапкой. Низ — резерв под композер. */
    .media-page.is-mobile-feed .media-mobile-history .sidebar-history-fade {
        padding-top: var(--shell-mobile-header-offset);
        padding-bottom: var(--input-height, 0px);
    }

    /* Пустой стейт / ошибка: тот же паттерн, что у ленты — сам скроллер резервирует
       место под композер-оверлей (--input-height), поэтому центрированный заголовок
       стоит МЕЖДУ шапкой и композером и не уезжает под него. In-flow desktop-spacer
       тут не нужен — он только для docked-композера на ≥1100. */
    .media-page.is-mobile-history .generation-result-area {
        padding-bottom: var(--input-height, 0px);
    }
    /* Reserve the measured composer height directly, as on desktop. */
    .media-page.is-mobile-history .media-generation-input-spacer {
        display: none;
    }

    /* Прячем десктопный hero, ТОЛЬКО когда есть лента генераций (is-mobile-feed).
       Пусто / всё удалено → hero остаётся (как было изначально). */
    .media-page.is-mobile-feed .generation-result-area {
        display: none;
    }

    /* Image-лента на мобайле: максимум 2 колонки (планшет / крупный телефон),
       без «3 в ряд». На узких телефонах (<480px) — 1 колонка (ниже). Desktop-сайдбар
       не трогаем — число колонок там выбирает auto-fill grid. */
    .media-page.is-mobile-history .sidebar-generation-feed.is-image {
        --sidebar-gallery-columns: 2;
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .media-page.is-mobile-history .sidebar-generation-feed {
        border-radius: var(--radius-xl);
        corner-shape: var(--corner-shape-surface);
    }
}

/* Узкие телефоны (<480px): image-лента в одну колонку — крупнее превью. */
@media (max-width: 479.98px) {
    .media-page.is-mobile-history .sidebar-generation-feed.is-image {
        --sidebar-gallery-columns: 1;
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Scroll-to-bottom FAB */
.scroll-to-bottom-btn {
    position: absolute;
    /* Справа по композеру (правый край inputArea), а не по центру, с небольшим
       отступом от края. */
    right: 0.5rem;
    bottom: calc(100% + 0.5rem);
    z-index: 1;
    /* Размер и стекло — как у кнопок временного чата (.shell-mobile-chat-header-btn):
       --shell-header-slot + chat-input-bg + glass-blur + shadow-glass. */
    width: var(--shell-header-slot);
    height: var(--shell-header-slot);
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    color: var(--text-muted);
    cursor: pointer;
    box-shadow: var(--shadow-glass);
    transition: color var(--transition-fast),
                background var(--transition-fast),
                box-shadow var(--transition-fast);
}

@media (hover: hover) {
    .scroll-to-bottom-btn:hover {
        color: var(--text-main);
        background: var(--bg-raised);
        box-shadow: var(--shadow-icon);
    }
}

/* Force transparent background for HLJS to respect our glass panel */
.code-block-wrapper .hljs {
    background: transparent !important;
}

/* Preview Area */
.code-block-preview {
    padding: 1rem;
    background: var(--bg-panel);
    color: var(--text-main);
    min-height: 120px;
    max-width: 100%;
}
.code-block-preview iframe { width: 100%; border: none; height: 100%; min-height: 300px; }

/* Footer (Integrated look) */
.code-block-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.5rem 1rem 0.75rem 1rem;
    background: transparent;
    margin-top: 0;
    font-family: var(--font-sans);
}

/* Language Label (Left side) */
.footer-lang {
    font-size: var(--text-xs);
    font-weight: var(--font-weight-bold);
    color: var(--text-muted);
    text-transform: lowercase;
}

/* Actions (Right side) */
.footer-actions {
    display: flex;
    align-items: center;
    gap: 0.625rem;
}

/* Copy Button */
.footer-btn {
    background: transparent; color: var(--text-muted); cursor: pointer; padding: 0.25rem;
    transition: background-color var(--transition), color var(--transition), filter var(--transition); display: flex; align-items: center; justify-content: center;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
}
@media (hover: hover) {
    .footer-btn:hover { color: var(--text-main); background: var(--bg-hover); }
}
.footer-btn svg { width: 18px; height: 18px; }

/* Quote-button работает только в полноценном чате (нужен chatApp.startReply
   под #app-shell-root). На статичных страницах вроде shared-чата приложения
   нет — скрываем кнопку, чтобы клик не выглядел как баг (no-op). */
body:not(:has(> #app-shell-root)) .quote-btn,
body:not(:has(> #app-shell-root)) .attachment-quote-btn,
body:not(:has(> #app-shell-root)) .selection-quote-bar { display: none !important; }

/* Кнопка «Цитировать» поверх image/video-вложений в сообщениях. Стеклянное
   оформление, чтобы читалось поверх любого фона. На touch-устройствах
   (`hover: none`) видна всегда; на десктопе появляется только при hover'е
   на контейнер группы, чтобы не загромождать. */
.attachment-quote-btn {
    background: var(--overlay-pill-bg);
    color: var(--overlay-text);
    backdrop-filter: blur(var(--glass-blur)); /* samples the media behind the control */
    -webkit-backdrop-filter: blur(var(--glass-blur));
    border: 0;
    cursor: pointer;
    opacity: 1;
}
@media (hover: hover) {
    .attachment-quote-btn { opacity: 0; }
    .group\/att:hover .attachment-quote-btn,
    .group\/att:focus-within .attachment-quote-btn,
    .attachment-quote-btn:focus-visible { opacity: 1; }
    .attachment-quote-btn:hover { background: var(--overlay-pill-bg-strong); }
}
.attachment-quote-btn:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* Плавающий бар «Цитировать выделенное» над текстовым выделением в чате. */
.selection-quote-bar {
    pointer-events: auto;
    animation: selection-quote-fade-in var(--motion-duration-fast) var(--motion-ease-premium);
}
@keyframes selection-quote-fade-in {
    from { opacity: 0; transform: translateY(2px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* View Toggle (Pill Style) */
.view-toggle {
    display: flex;
    align-items: center;
    /* Капсульный сегментбар (эталон): pill-трей + pill-сегменты, активный
       --surface-strong. Трей — recessed --bg-input. */
    gap: var(--gap-2xs);
    padding: var(--gap-xs);
    background: var(--bg-input);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
}

.toggle-option {
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    padding: 0.35rem 0.85rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    cursor: pointer;
    transition: color var(--transition), background-color var(--transition), box-shadow var(--transition), filter var(--transition);
}

@media (hover: hover) {
    .toggle-option:hover:not(.active) {
        color: var(--text-main);
        background: var(--bg-hover);
    }
}

.toggle-option.active {
    background-color: var(--surface-strong);
    color: var(--text-main);
}
/* Utility: Remove spinners from number inputs */
.input-no-spinners::-webkit-outer-spin-button,
.input-no-spinners::-webkit-inner-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}
.input-no-spinners {
    -moz-appearance: textfield;
    appearance: textfield;
}

@media (prefers-reduced-motion: reduce) {
    html:focus-within {
        scroll-behavior: auto;
    }

    .motion,
    .btn,
    .sidebar-shell,
    .service-card,
    .surface-chip,
    .model-chip,
    .dropdown-item,
    .overlay-icon,
    .toggle-option,
    .footer-btn,
    .loading-spinner,
    .modal-card,
    .input-spacer {
        animation: none !important;
        transition: none !important;
        transform: none !important;
    }
}

/* Sidebar: history fades at top and bottom while scrolling */
.sidebar-history-fade {
    --scroll-edge-size: calc(var(--gap-sm) * 3);
}

/* ─── Custom Tooltips (floating, rendered via JS) ─── */
.app-tooltip {
    position: fixed;
    padding: 4px 10px;
    background: var(--bg-elevated);
    color: var(--text-main);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    line-height: var(--leading-snug);
    white-space: nowrap;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-glass);
    pointer-events: none;
    visibility: hidden;
    opacity: 0;
    transform: scale(0.96);
    transition: opacity var(--motion-duration-micro) var(--motion-ease-standard), transform var(--motion-duration-micro) var(--motion-ease-standard), visibility 0s linear var(--motion-duration-micro);
    z-index: var(--z-tooltip);
}
.app-tooltip.visible {
    visibility: visible;
    opacity: 1;
    transform: scale(1);
    transition-delay: 0s;
}

.app-tooltip--dropdown {
    max-width: min(17rem, calc(100vw - 1rem));
    padding: var(--gap-sm) calc(var(--gap-sm) * 1.5);
    white-space: normal;
    background: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
}

@media (hover: none), (pointer: coarse) {
    .app-tooltip:not(.app-tooltip--dropdown) {
        display: none !important;
    }

    .hover-reveal-actions,
    .hover-reveal-action {
        opacity: 1 !important;
        pointer-events: auto !important;
    }

    .hover-delete-overlay {
        opacity: 1 !important;
        align-items: flex-start;
        justify-content: flex-end;
        padding: 0.25rem;
        background: linear-gradient(180deg, var(--overlay-backdrop-soft) 0%, transparent 58%);
    }

    .hover-delete-overlay .overlay-icon {
        box-shadow: var(--shadow-surface);
    }

    .hover-reveal-overlay {
        opacity: 1 !important;
        background: linear-gradient(
            180deg,
            color-mix(in srgb, var(--overlay-scrim) 88%, transparent) 0%,
            transparent 36%,
            color-mix(in srgb, var(--overlay-backdrop) 92%, transparent) 100%
        );
    }
}

/* One surface for desktop sidebar actions and their mobile counterparts.
   Only glow opacity breathes; geometry remains owned by each layout. */
.tg-footer-bar.history-action-surface {
    position: relative;
    isolation: isolate;
    border-radius: var(--mobile-action-radius);
    background-color: var(--mobile-action-bg);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}
/* This footer is outside the workflow list scroller; only its panel owns glass. */
.wf-sidebar .tg-footer-bar {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}
.history-action-surface::before,
.history-action-surface::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    corner-shape: inherit;
    pointer-events: none;
}
.history-action-surface::before { box-shadow: var(--mobile-action-glow); }
.history-action-surface::after {
    box-shadow: var(--glow-accent-strong);
    animation: media-composer-glow var(--motion-period-glow) var(--motion-ease-ambient) infinite var(--pane-ambient-play-state, running);
}
.history-action-surface > * { position: relative; z-index: 1; }
.history-action-surface .tg-footer-new-chat {
    background: transparent;
    color: var(--text-main);
}
/* Mobile dimensions match the collapsed media composer. */
@media (max-width: 1099.98px) {
    .tg-footer-bar.mobile-action-pill {
        --mobile-action-control: calc(var(--mobile-action-height) - var(--gap-sm) * 2);
        width: var(--mobile-action-width);
        max-width: 100%;
        height: var(--mobile-action-height);
        min-height: var(--mobile-action-height);
        margin-inline: auto;
        padding: var(--gap-sm);
        gap: var(--gap-sm);
    }
    .mobile-action-pill .tg-footer-search,
    .mobile-action-pill .tg-footer-icon-btn,
    .mobile-action-pill .tg-footer-new-chat {
        height: var(--mobile-action-control);
        width: var(--mobile-action-control);
        border-radius: calc(var(--mobile-action-control) / 2 * var(--radius-scale));
    }
    .mobile-action-pill .tg-footer-search__icon { flex-basis: var(--mobile-action-control); }
    .mobile-action-pill .tg-footer-new-chat,
    .mobile-action-pill .tg-footer-search.is-expanded {
        width: calc(100% - var(--mobile-action-control) * 2 - var(--gap-sm) * 2);
    }
    .mobile-action-pill .tg-footer-new-chat.is-compact { width: var(--mobile-action-control); }
    .mobile-action-pill .tg-footer-new-chat:only-child { width: 100%; }
    .mobile-action-dock.mobile-action-dock {
        padding-inline: var(--composer-edge-gap);
        padding-bottom: var(--mobile-action-bottom);
    }
    .music-mobile-dock {
        gap: var(--gap-sm);
    }
}
@media (prefers-reduced-motion: reduce) {
    .history-action-surface::after { animation: none; }
}
[data-perf="lite"] .history-action-surface::after { animation: none; }

/* === Camera Cube === */

/* Scene wrapper — sets perspective */
.cube-perspective {
    --camera-cube-size: calc(var(--gap-sm) * 25);
    --camera-cube-edge-blur: calc(var(--gap-sm) * 3);
    --camera-cube-edge-color: color-mix(in srgb, var(--primary-500) 80%, transparent);
    width: var(--camera-cube-size);
    height: var(--camera-cube-size);
    perspective: calc(var(--camera-cube-size) * 3.5);
}

/* The rotating box */
.cube-body {
    position: relative;
    width: 100%;
    height: 100%;
    transform-style: preserve-3d;
    transition: transform var(--transition-fast);
    cursor: grab;
}
.cube-body:active { cursor: grabbing; }
.cube-body.is-dragging { transition: none; }
@media (prefers-reduced-motion: reduce) {
    .cube-body { transition: none; }
}

/* Each face */
.cube-face {
    position: absolute;
    inset: 0;
    background: var(--overlay-backdrop-soft);
    -webkit-backdrop-filter: blur(var(--progressive-blur-2));
    backdrop-filter: blur(var(--progressive-blur-2));
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    box-shadow: var(--glow-accent-soft);
}
.cube-face::after {
    content: '';
    position: absolute;
    inset: 0;
    /* Feather toward the face interior; do not draw a solid wireframe. */
    box-shadow: inset 0 0 var(--camera-cube-edge-blur) var(--camera-cube-edge-color);
    pointer-events: none;
}

/* Transforms — half of 200px = 100px */
.cube-face--front  { transform: translateZ(calc(var(--camera-cube-size) / 2)); }
.cube-face--back   { transform: rotateY(180deg) translateZ(calc(var(--camera-cube-size) / 2)); }
.cube-face--left   { transform: rotateY(-90deg) translateZ(calc(var(--camera-cube-size) / 2)); }
.cube-face--right  { transform: rotateY(90deg)  translateZ(calc(var(--camera-cube-size) / 2)); }
.cube-face--top    { transform: rotateX(90deg)  translateZ(calc(var(--camera-cube-size) / 2)); }
.cube-face--bottom { transform: rotateX(-90deg) translateZ(calc(var(--camera-cube-size) / 2)); }

/* Face label pill */
.cube-face-label {
    background: var(--bg-panel);
    color: var(--text-main);
    padding: var(--gap-2xs) calc(var(--gap-sm) * 1.25);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-bold);
    letter-spacing: var(--tracking-wider);
    line-height: var(--leading-relaxed);
}

/* Controls card */
.cube-controls-card {
    background: var(--bg-panel);
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    padding: 20px 22px 16px;
    width: 100%;
    max-width: 380px;
    box-shadow: var(--shadow-modal);
}

/* === Unified Media Viewer (fullscreen) === */

.media-viewer {
    cursor: default;
    --viewer-space: calc(var(--gap-sm) * 2);
    --viewer-control-size: calc(var(--gap-sm) * 5.5);
    position: fixed;
    inset: 0;
    z-index: var(--z-fullscreen-modal);
    background: var(--bg-app);
    color: var(--text-main);
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.composer-camera {
    --camera-control-size: max(calc(var(--composer-control-size) + var(--gap-sm)), calc(var(--text-control) * var(--leading-normal) + 2 * var(--gap-sm)));
}
.composer-camera__preview {
    position: relative;
    min-height: 0;
    width: 100%;
    aspect-ratio: var(--camera-aspect-ratio, 4 / 3);
    flex: 1 1 auto;
    overflow: hidden;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-input);
}
.composer-camera__preview video {
    /* Intrinsic video dimensions must not outgrow a height-constrained sheet. */
    position: absolute;
    inset: 0;
    display: block;
    margin: auto;
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 100%;
    aspect-ratio: var(--camera-aspect-ratio, 4 / 3);
    border-radius: inherit;
    corner-shape: var(--corner-shape-surface);
    object-fit: contain;
}
.composer-camera__preview video.is-mirrored { transform: scaleX(-1); }
.composer-camera__message {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--modal-content-pad);
    margin: 0;
    color: var(--text-muted);
    background: var(--bg-input);
    font-size: var(--text-sm);
    text-align: center;
}
.composer-camera__actions {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    gap: var(--gap-sm);
    padding-top: var(--gap-sm);
}
.composer-camera__actions > .btn {
    min-height: var(--camera-control-size);
    line-height: var(--leading-normal);
}
.composer-camera__flip {
    flex: 0 0 var(--camera-control-size);
    width: var(--camera-control-size);
    height: var(--camera-control-size);
    padding: 0;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-xl);
}
.composer-camera__capture {
    flex: 1;
    min-width: 0;
    padding: var(--gap-sm) var(--modal-content-pad);
}
.composer-camera > .composer-plus-sheet__caption {
    margin: var(--gap-sm) var(--gap-xs) 0;
}

/* The shared overlay clock owns opacity and x-show removes the closed surface
   from rendering. An invisible fixed fullscreen layer must not survive exit. */
.media-viewer.backdrop-enter {
    transition-duration: var(--motion-duration-gallery) !important;
}

/* Controls float above zoomed media; only the viewport clips the enlarged photo. */
.media-viewer__header,
.media-viewer__toolbar {
    position: relative;
    z-index: 1;
    isolation: isolate;
    background: transparent;
    pointer-events: none;
}
.media-viewer__header-actions,
.media-viewer__tools { pointer-events: auto; }
.media-viewer:not(.media-viewer--document) > .media-viewer__header::before,
.media-viewer:not(.media-viewer--document) > .media-viewer__toolbar::before {
    content: '';
    position: absolute;
    inset-inline: 0;
    z-index: -1;
    pointer-events: none;
}
.media-viewer:not(.media-viewer--document) > .media-viewer__header::before {
    top: 0;
    bottom: calc(var(--viewer-space) * -1);
    background: linear-gradient(to bottom, var(--bg-app), transparent);
}
.media-viewer:not(.media-viewer--document) > .media-viewer__toolbar::before {
    top: calc(var(--viewer-space) * -1);
    bottom: 0;
    background: linear-gradient(to top, var(--bg-app), transparent);
}

.media-viewer__logo {
    justify-self: start;
    width: var(--viewer-control-size);
    height: var(--viewer-control-size);
    color: var(--text-main);
    pointer-events: none;
}
.media-viewer__logo > .brand-mobile {
    width: 100%;
    height: 100%;
}
@media (min-width: 768px) {
    .media-viewer__logo {
        display: flex;
        align-items: center;
        width: auto;
    }
}

/* Шапка */
.media-viewer__header {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr);
    align-items: center;
    gap: var(--viewer-space);
    padding: calc(var(--gap-sm) + env(safe-area-inset-top)) var(--viewer-space) var(--gap-sm);
    flex-shrink: 0;
}
.media-viewer__meta {
    display: flex;
    flex-direction: column;
    gap: var(--gap-2xs);
    min-width: 0;
    text-align: center;
}
.media-viewer__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-sm); font-weight: var(--font-weight-semibold); color: var(--text-main); }
.media-viewer__date  { font-size: var(--text-xs); color: var(--text-subtle); }

.media-viewer__header-actions {
    display: flex;
    justify-self: end;
    align-items: center;
    gap: var(--gap-sm);
    flex-shrink: 0;
}

.media-viewer__close,
.media-viewer__nav,
.media-viewer .media-card-action {
    flex-shrink: 0;
    width: var(--viewer-control-size);
    height: var(--viewer-control-size);
    padding: 0;
    border: 0;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    box-shadow: var(--shadow-icon);
    isolation: isolate;
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--text-xl);
    transition: background-color var(--transition-fast), color var(--transition-fast);
}
.media-viewer__close {
    position: relative;
    --viewer-control-bg: var(--surface-soft);
    color: var(--icon-default);
}
/* Keep the foreground outside the filtered surface. A gesture changes only
   image transforms; it must not destroy/recreate the controls' glass layers. */
.media-viewer :is(.media-viewer__close, .media-viewer__nav, .media-card-action)::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    corner-shape: inherit;
    background: var(--viewer-control-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    transition: background-color var(--transition-fast);
    pointer-events: none;
}
.media-viewer :is(.media-viewer__close, .media-viewer__nav, .media-card-action) > * {
    position: relative;
    z-index: 0;
}
/* Document actions occupy a separate row over the viewer's solid background. */
.media-viewer--document .media-viewer__close::before {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}
/* Controls directly over media keep the theme-independent contrast palette. */
.media-viewer__nav,
.media-viewer .media-card-action {
    --viewer-control-bg: var(--overlay-pill-bg);
    color: var(--overlay-text);
}
@media (hover: hover) {
    .media-viewer__close:hover {
        --viewer-control-bg: var(--surface-strong);
        color: var(--icon-hover);
    }
    .media-viewer__nav:hover,
    .media-viewer .media-card-action:hover { --viewer-control-bg: var(--overlay-pill-bg-strong); }
}
.media-viewer__close:active {
    --viewer-control-bg: var(--surface-active);
    color: var(--icon-hover);
}
.media-viewer__nav:active,
.media-viewer .media-card-action:active {
    --viewer-control-bg: var(--overlay-text);
    color: var(--primary-text);
}
.media-viewer :is(button, [role="button"], [tabindex="0"]):focus-visible {
    outline: 2px solid currentColor;
    outline-offset: var(--gap-2xs);
}

/* Канвас (медиа по центру). */
.media-viewer__body {
    position: relative;
    z-index: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
    flex: 1;
    min-height: 0;
    min-width: 0;
    /* Move the workspace as one surface; leave image transforms to zoom.
       CSS transitions reverse in place when the viewer is reopened mid-exit. */
    transform: translateY(var(--motion-distance-content));
    transition: transform var(--motion-duration-fast) var(--motion-ease-exit);
}
.media-viewer--open > .media-viewer__body {
    transform: none;
    transition-duration: var(--motion-duration-gallery);
    transition-timing-function: var(--motion-ease-premium);
}
.media-viewer__body--details {
    /* Center the photo and description together; reserve room for edge arrows. */
    grid-template-columns: minmax(0, calc((100dvh - 10rem) * var(--viewer-aspect, 1))) clamp(18rem, 26vw, 25rem);
    justify-content: center;
    padding-inline: calc(var(--viewer-control-size) + var(--viewer-space));
}
.media-viewer__body--details.media-viewer__body--group {
    grid-template-columns: minmax(0, 1fr) clamp(18rem, 26vw, 25rem);
}
.media-viewer__canvas {
    grid-area: 1 / 1;
    position: relative;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-inline: var(--viewer-space);
    padding-block: var(--gap-sm);
}
/* Generation glow fades outside the media area; do not crop it at the canvas edge. */
.media-viewer__canvas--generating,
.media-viewer--zoomed .media-viewer__canvas,
.media-viewer--zoom-motion .media-viewer__canvas:not(.media-viewer__canvas--group) { overflow: visible; }
.media-viewer__media {
    display: block;
    width: min(100cqw, calc(100cqh * var(--media-aspect)));
    height: min(100cqh, calc(100cqw / var(--media-aspect)));
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    box-shadow: none;
    /* Navigation replaces a decoded frame in place. Transform belongs to zoom. */
    transition: none;
    transform-origin: center center;
    position: relative;
    z-index: 1;
}

/* A group is a scrollable gallery. Image gestures belong only to the single view. */
.media-viewer__canvas.media-viewer__canvas--group {
    display: block;
    overflow: hidden;
}
.media-viewer__group {
    position: relative;
    width: 100%;
    height: 100%;
    container-type: size;
}
.media-viewer__results {
    display: flex;
    align-items: center;
    gap: calc(var(--gap-sm) * 2);
    width: 100%;
    height: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;

}

.media-viewer__result {
    margin: 0;
    min-width: 0;
    flex: 0 0 auto;
    width: min(85cqw, calc(100cqh * var(--result-aspect)));
    scroll-snap-align: start;
}
.media-viewer__group::before,
.media-viewer__group::after {
    content: '';
    position: absolute;
    inset-block: 0;
    width: calc(var(--gap-sm) * 14);
    z-index: 2;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--transition-fast);
}
.media-viewer__group::before { left: 0; background: linear-gradient(to right, var(--bg-app), transparent); }
.media-viewer__group::after { right: 0; background: linear-gradient(to left, var(--bg-app), transparent); }
.media-viewer__group.can-prev::before,
.media-viewer__group.can-next::after { opacity: 1; }
.media-viewer__group-prev { left: var(--viewer-space); }
.media-viewer__group-next { right: var(--viewer-space); }
.media-viewer__result-frame {
    position: relative;
    width: 100%;
    overflow: hidden;
    background: transparent;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
}
.media-viewer__result-open {
    display: block;
    width: 100%;
    height: 100%;
    touch-action: pan-y pinch-zoom;
    object-fit: contain;
    cursor: pointer;
    user-select: none;
    -webkit-user-drag: none;
    box-shadow: none;
    filter: none;
    opacity: 0;
}
.media-viewer__result-open.is-loaded { opacity: 1; }
.media-viewer__result-status {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--gap-sm);
    padding: calc(var(--gap-sm) * 2);
    text-align: center;
    color: var(--text-muted);
    font-size: var(--text-sm);
}
.media-viewer__result-status.media-viewer__loading { padding: 0; }
.media-viewer__result-status.media-viewer__loading .gen-loading { width: 100%; height: 100%; min-height: 0; background: transparent; }
@media (min-width: 768px) {
    .media-viewer__result-open { touch-action: pan-x pinch-zoom; }
}
@media (max-width: 767.98px) {
    .media-viewer__canvas.media-viewer__canvas--group {
        overflow-y: auto;
        overscroll-behavior-y: contain;
        touch-action: pan-y pinch-zoom;
        scrollbar-gutter: stable;
    }
    .media-viewer__group { height: auto; container-type: normal; }
    .media-viewer__results { flex-direction: column; height: auto; overflow: visible; scroll-snap-type: none; }
    .media-viewer__result { width: 100%; }
    .media-viewer__group::before, .media-viewer__group::after,
    .media-viewer__group-prev, .media-viewer__group-next { display: none; }
}

/* Общий контейнер медиа и фирменного индикатора загрузки. */
.media-viewer__stage {
    container-type: size;
    position: relative;
    width: 100%;
    height: 100%;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}
@media (min-width: 768px) {
    .media-viewer__body--details .media-viewer__stage { justify-content: flex-end; }
}
.media-viewer__canvas:not(.media-viewer__canvas--group) { z-index: 1; }
.media-viewer--zoomed .media-viewer__stage {
    transform: translate(var(--viewer-center-x, 0px), var(--viewer-center-y, 0px));
}
.media-viewer--zoom-motion:not(.media-viewer--gesturing) .media-viewer__stage {
    transition: transform var(--motion-duration-base) var(--motion-ease-premium);
}
.media-viewer--zoom-tap:not(.media-viewer--gesturing) .media-viewer__image {
    transition: transform var(--motion-duration-base) var(--motion-ease-premium);
}
.media-viewer__stage .media-viewer__media,
.media-viewer__stage .media-viewer__audio,
.media-viewer__stage .media-viewer__iframe,
.media-viewer__stage .media-viewer__fallback,
.media-viewer__stage .media-viewer__state-card { pointer-events: auto; }

/* Превью появляется после декодирования, без второго слоя картинки. */
.media-viewer__media.is-loading { opacity: 0; }
/* Изображение управляется жестами (Pointer Events): отдаём ему весь тач,
   запрещаем нативный drag/выделение. */
.media-viewer__image {
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    -webkit-user-drag: none;
}

.media-viewer__audio { width: 100%; max-width: 32rem; }

.media-viewer__iframe {
    width: 100%;
    height: 70vh;
    max-width: 64rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-elevated);
}

/* One flat document workspace, without a second framed window. */
.media-viewer--document { justify-content: flex-start; align-items: stretch; padding: calc(var(--gap-sm) + env(safe-area-inset-top)) var(--gap-sm) var(--safe-area-bottom, 0px); background: var(--bg-app); backdrop-filter: none; }
.media-viewer--document .media-viewer__logo { display: none; }
.media-viewer--document .media-viewer__header { width: 100%; grid-template-columns: minmax(0, 1fr) auto; gap: var(--gap-sm); padding: calc(var(--gap-sm) * .5) var(--gap-sm); background: transparent; border-radius: 0; }
.media-viewer--document .media-viewer__meta { padding: 0 var(--gap-sm); text-align: left; }
.media-viewer--document .media-viewer__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-xs); font-weight: var(--font-weight-medium); }
.media-viewer--document .media-viewer__header-actions { gap: var(--gap-2xs); }
.media-viewer__document-controls { display: none; }
.media-viewer--document .media-viewer__header:has(.document-toolbar) { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); }
.media-viewer--document .media-viewer__document-controls:not(:empty) {
    display: block;
    min-width: 0;
    pointer-events: auto;
    font-size: var(--text-xs);
}
.media-viewer__document-controls .document-toolbar { width: max-content; min-width: 100%; padding: 0; }
.media-viewer--document .media-viewer__close { width: var(--artifact-control-size); height: var(--artifact-control-size); border-radius: 50%; corner-shape: var(--corner-shape-round); --viewer-control-bg: var(--surface-soft); font-size: var(--text-lg); color: var(--text-muted); }
.media-viewer--document .media-viewer__close:hover { color: var(--text-main); --viewer-control-bg: var(--bg-hover); transform: none; }
.media-viewer--document .media-viewer__body { width: 100%; flex: 1; min-height: 0; }
.media-viewer--document .media-viewer__canvas { width: 100%; padding: 0; mask-image: none; -webkit-mask-image: none; background: transparent; border-radius: 0; }
.media-viewer--document .media-viewer__iframe { height: 100%; max-width: none; border: 0; border-radius: 0; color-scheme: normal; }
.media-viewer--file .media-viewer__body { flex-basis: calc(var(--gap-sm) * 28); }
@media (max-width: 640px) {
    .media-viewer--document { padding-inline: var(--gap-sm); }
    .media-viewer--document .media-viewer__header:has(.document-toolbar) { grid-template-columns: minmax(0, 1fr) auto; }
    .media-viewer--document .media-viewer__document-controls { grid-column: 1 / -1; grid-row: 2; }
    .media-viewer__document-controls .document-toolbar { width: 100%; min-width: 0; flex-wrap: wrap; gap: var(--gap-sm); }
}

.media-viewer__fallback {
    max-width: 28rem;
    margin: 0 auto;
    text-align: center;
    color: var(--text-main);
}
.media-viewer__fallback-icon {
    width: 3.5rem;
    height: 3.5rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-elevated);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 1rem;
    font-size: var(--text-2xl);
    color: var(--text-muted);
}

.media-viewer__state-card {
    width: min(100%, 520px);
    background: var(--bg-elevated);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-modal);
    padding: 24px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
}

.media-viewer__error-frame,
.media-viewer__loading .media-viewer__generation-frame {
    position: relative;
    width: min(100cqw, calc(100cqh * var(--media-aspect)), 520px);
    flex: none;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    pointer-events: auto;
}
.generation-error {
    position: absolute;
    inset: 0;
    container-type: inline-size;
    overflow: auto;
    display: flex;
    background: transparent;
    color: var(--text-main);
    text-align: center;
    padding: calc(var(--gap-sm) * 3);
}
.generation-error__content {
    margin: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--gap-sm);
    max-width: 32rem;
    min-width: 0;
}
.generation-error__icon {
    width: clamp(3rem, 22cqw, 6rem);
    height: auto;
    object-fit: contain;
    flex-shrink: 0;
}
.generation-error__title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
}
.generation-error__message {
    font-size: var(--text-xs);
    color: var(--text-muted);
    overflow-wrap: anywhere;
}

/* Errors retain the pending frame; long details scroll inside it. */
.sidebar-generation-preview .generation-error {
    width: 100%;
    padding: calc(var(--gap-sm) * 3) clamp(calc(var(--gap-sm) * 2), 8cqw, calc(var(--gap-sm) * 3));
}

.sidebar-generation-preview .generation-error__content {
    width: 100%;
    gap: calc(var(--gap-sm) * 1.5);
}

.generation-surface .generation-error__icon {
    width: 2rem;
    height: 2rem;
}

.sidebar-generation-preview .generation-error__title {
    line-height: var(--leading-snug);
    overflow-wrap: anywhere;
}

.sidebar-generation-preview .generation-error__message {
    line-height: var(--leading-normal);
}

@media (pointer: coarse) {
    .sidebar-generation-preview .generation-error {
        padding-top: 3.5rem;
    }
}

/* Loading status. Only live generation mounts the branded glow inside it. */
.media-viewer__loading {
    /* Оверлей по центру канваса (а не flex-сосед медиа — иначе спиннер встаёт
       СБОКУ от грузящегося <img> в row-флексе). Спиннер крутится ровно там, где
       появится фото, и фото заменяет его на месте. pointer-events:none — клики
       проходят к канвасу (закрытие по фону). */
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.85rem;
    pointer-events: none;
    color: var(--overlay-text);
}

/* CSS owns the inner fade: cancelling nested Alpine transitions during rapid
   close/open otherwise rejects the parent hide promise. */
.media-viewer__stage > .media-viewer__loading {
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--motion-duration-fast) var(--motion-ease-standard),
                visibility 0s var(--motion-duration-fast);
}
.media-viewer__stage > .media-viewer__loading.is-active {
    opacity: 1;
    visibility: visible;
    transition-delay: var(--motion-duration-fast), 0s;
}

/* Тёмный оверлей → светлый спиннер независимо от темы (токены спиннера завязаны
   на --text-main, который в светлой теме тёмный и был бы невидим на чёрном). */

/* Стрелки навигации по коллекции */
.media-viewer__nav {
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
}
.media-viewer__nav--prev  { left: var(--viewer-space); }
.media-viewer__nav--next  { right: var(--viewer-space); }

/* One responsive description panel for every generated media type. */
.media-viewer__details {
    grid-area: 1 / 2 / -1 / 3;
    display: flex;
    min-width: 0;
    min-height: 0;
    flex-direction: column;
    padding: calc(var(--gap-sm) * 3) var(--gap-sm);
    overflow: hidden;
}
.media-viewer__details { position: relative; z-index: 0; }
.media-viewer--zoom-motion .media-viewer__details {
    /* Match shared content/step motion: short travel plus fade, not a full-panel slide. */
    transition: transform var(--motion-duration-base) var(--motion-ease-premium),
                opacity var(--motion-duration-fast) var(--motion-ease-standard),
                visibility 0s;
}
.media-viewer__details.is-zoomed {
    transform: translateX(calc(-1 * var(--motion-distance-content)));
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}
.media-viewer--zoom-motion .media-viewer__details.is-zoomed {
    transition-duration: var(--motion-duration-fast), var(--motion-duration-fast), 0s;
    transition-timing-function: var(--motion-ease-exit);
    transition-delay: 0s, 0s, var(--motion-duration-fast);
}
.media-viewer__prompt {
    display: flex;
    flex: 0 1 auto;
    min-height: 0;
    flex-direction: column;
    gap: calc(var(--gap-sm) * 2);
    margin: 0;
    font-size: var(--text-base);
    line-height: var(--leading-normal);
}
.media-viewer__prompt-heading { display: flex; align-items: center; justify-content: space-between; gap: var(--gap-sm); flex-shrink: 0; }
.media-viewer__prompt-scroll,
.media-viewer__properties-scroll {
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior-y: contain;

}

.media-viewer__prompt-scroll { cursor: pointer; }
.media-viewer__prompt-scroll.has-more {
    mask-image: linear-gradient(to bottom, #000 calc(100% - min(25%, var(--gap-sm) * 4)), transparent);
}
.media-viewer__prompt-scroll:focus-visible { outline: var(--gap-2xs) solid var(--primary-500); outline-offset: var(--gap-2xs); }
.media-viewer__prompt-close {
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--motion-duration-fast) var(--motion-ease-standard), visibility 0s var(--motion-duration-fast);
}
.media-viewer__properties {
    display: grid;
    grid-template-rows: 1fr;
    flex: 0 0 auto;
    min-height: 0;
    max-height: 60%;
    transition: grid-template-rows var(--motion-duration-base) var(--motion-ease-premium),
                opacity var(--motion-duration-fast) var(--motion-ease-standard),
                transform var(--motion-duration-base) var(--motion-ease-premium),
                visibility 0s;
}
.media-viewer__properties-content { display: grid; gap: calc(var(--gap-sm) * 3); padding-top: calc(var(--gap-sm) * 3); }
.media-viewer__details.is-reading .media-viewer__prompt { flex-grow: 1; }
.media-viewer__details.is-reading .media-viewer__prompt-scroll { cursor: text; }
.media-viewer__details.is-reading .media-viewer__prompt-close { opacity: 1; visibility: visible; transition-delay: 0s; }
.media-viewer__details.is-reading .media-viewer__properties {
    grid-template-rows: 0fr;
    opacity: 0;
    visibility: hidden;
    transform: translateY(var(--motion-distance-content));
    transition-timing-function: var(--motion-ease-exit);
    transition-delay: 0s, 0s, 0s, var(--motion-duration-base);
}
.media-viewer__prompt-label {
    margin: 0;
    font-family: var(--font-editorial);
    font-size: var(--text-4xl);
    font-weight: var(--font-weight-editorial);
    line-height: var(--leading-display);
    color: var(--text-main);
}
.media-viewer__prompt-text { white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text-main); }
.media-viewer__pills { display: flex; flex-shrink: 0; flex-wrap: wrap; gap: var(--gap-sm); }
.media-viewer__pill {
    display: inline-flex;
    align-items: center;
    gap: var(--gap-sm);
    max-width: 100%;
    padding: calc(var(--gap-sm) * 1.5) calc(var(--gap-sm) * 2);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-raised);
    color: var(--text-main);
    font-size: var(--text-base);
    font-weight: var(--font-weight-medium);
    line-height: var(--leading-normal);
    overflow-wrap: anywhere;
}
.media-viewer__pill i { font-size: var(--text-lg); }
.media-viewer__inputs { display: grid; flex-shrink: 0; gap: var(--gap-sm); }
.media-viewer__input-list { display: flex; flex-wrap: wrap; gap: var(--gap-sm); }
.media-viewer__input { position: relative; padding: 0; overflow: hidden; }
.media-viewer__input img,
.media-viewer__input video { width: 100%; height: 100%; object-fit: cover; }
.media-viewer__input-badge {
    position: absolute; bottom: 0; inset-inline: 0;
    padding: var(--gap-2xs); background: var(--overlay-pill-bg); color: var(--overlay-text);
    font-size: var(--text-2xs); line-height: var(--leading-tight);
}
@media (max-width: 767.98px) {
    .media-viewer__header { grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--gap-sm); }
    .media-viewer__body--details,
    .media-viewer__body--details.media-viewer__body--group { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) clamp(calc(var(--gap-sm) * 24), 44%, calc(var(--gap-sm) * 44)); padding-inline: 0; }
    .media-viewer__details { grid-area: 2 / 1; padding: var(--gap-sm) var(--viewer-space); }
    .media-viewer__properties-content { gap: var(--viewer-space); padding-top: var(--gap-sm); }
    .media-viewer__details.is-zoomed { transform: translateY(calc(-1 * var(--motion-distance-content))); }
    .media-viewer__prompt { gap: var(--gap-sm); font-size: var(--text-sm); }
    .media-viewer__prompt-label { font-size: var(--text-2xl); }
    .media-viewer__pill { padding: var(--gap-sm) calc(var(--gap-sm) * 1.5); font-size: var(--text-sm); }
}

@media (prefers-reduced-motion: reduce) {
    .media-viewer,
    .media-viewer--open { transition: none; }
    .media-viewer > .media-viewer__body { transition: none; transform: none; }
    .media-viewer__properties,
    .media-viewer__details.is-reading .media-viewer__properties,
    .media-viewer__prompt-close,
    .media-viewer--zoom-motion:not(.media-viewer--gesturing) .media-viewer__stage,
    .media-viewer--zoom-motion .media-viewer__details,
    .media-viewer--zoom-motion .media-viewer__details.is-zoomed,
    .media-viewer--zoom-tap:not(.media-viewer--gesturing) .media-viewer__image { transition: none; }
}

/* Тулбар инструментов (снизу; скачивание — в меню «⋯» шапки) */
.media-viewer__toolbar {
    /* Full-width sibling of the workspace: tools stay centered on the screen. */
    flex-shrink: 0;
    display: flex;
    justify-content: center;
    padding: var(--gap-sm) var(--viewer-space) calc(var(--gap-sm) + var(--safe-area-bottom, 0px));
}
/* Shared composer glass above the transparent footer gradient. */
.media-viewer__tools {
    --media-viewer-tool-icon-size: calc(var(--gap-sm) * 4);
    display: flex;
    /* Не переносим в 2 ряда: при нехватке ширины кнопки скроллятся по
       горизонтали внутри трея. safe center — центрируем, когда влезает, но
       при переполнении прижимаем к началу (иначе левые кнопки не докрутить).
       Скроллбар скрыт (как у прочих скролл-зон проекта). */
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;

    align-items: stretch;
    justify-content: safe center;
    gap: var(--gap-sm);
    max-width: 100%;
    padding: var(--gap-xs);
    box-shadow: var(--shadow-glass);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-2xs);
}

.media-viewer__tools > .media-viewer__tool {
    width: auto;
    min-width: calc(var(--gap-sm) * 8);
    display: grid;
    grid-template-rows: var(--media-viewer-tool-icon-size) auto;
    justify-items: center;
    align-content: center;
    padding: var(--gap-sm) calc(var(--gap-sm) * 1.5);
    gap: calc(var(--gap-2xs) * 2);
    text-align: center;
}
.media-viewer__tools > .media-viewer__tool > span { white-space: nowrap; }
.media-viewer__tool {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: var(--gap-xs);
    min-width: calc(var(--gap-sm) * 8);
    flex-shrink: 0;
    padding: var(--gap-sm) calc(var(--gap-sm) * 1.5);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    color: var(--text-main);
    font-size: var(--text-2xs);
    line-height: var(--leading-display);
    transition: background-color var(--transition-fast), color var(--transition-fast);
}
.media-viewer__tools > .media-viewer__tool { background: transparent; }
.media-viewer__tool i        { font-size: var(--text-xl); color: inherit; }
.media-viewer__tool-icon { width: var(--media-viewer-tool-icon-size, calc(var(--gap-sm) * 4.5)); height: var(--media-viewer-tool-icon-size, calc(var(--gap-sm) * 4.5)); object-fit: contain; flex-shrink: 0; display: block; }
@media (hover: hover) {
    .media-viewer__tools > .media-viewer__tool:hover:not(:disabled) { background: var(--surface-strong); }
    .media-viewer__state-card > .media-viewer__tool:hover,
    .media-viewer__result-status > .media-viewer__tool:hover { background-color: var(--chat-input-solid); }
}
.media-viewer__tools > .media-viewer__tool:active:not(:disabled) { background: var(--surface-active); }
.media-viewer__tool:disabled {
    background: var(--surface-soft);
    color: var(--text-muted);
    box-shadow: none;
    cursor: not-allowed;
}



/* ========================================
   PROFILE PAGE
   ======================================== */

/* ── Layout ── */
.profile-page {
    max-width: 680px;
    margin: 0 auto;
    padding: 0 var(--shell-page-gutter) calc(4rem + var(--safe-area-bottom, 0px));
}

/* ── Версия приложения (низ страницы, страховочный hard-reload) ── */
.profile-version {
    margin-top: 2rem;
    text-align: center;
}

.profile-version-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.25rem 0.625rem;
    border: none;
    background: transparent;
    color: var(--text-subtle);
    font-family: inherit;
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-wide);
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    cursor: pointer;
    transition: color var(--motion-duration-base) var(--motion-ease-standard);
}

@media (hover: hover) {
    .profile-version-btn:hover {
        color: var(--text-muted);
    }
}

@media (min-width: 1180px) {
    .profile-page {
        max-width: 56rem;
    }
    /* Десктоп: шапка чуть крупнее, аватар/кнопки растут синхронно. */
    .profile-header {
        --profile-avatar-size: 4rem;
        gap: 1.25rem;
    }
    .profile-name { font-size: var(--text-2xl); }
    .profile-id { font-size: var(--text-sm); }
    .profile-settings-btn { font-size: var(--text-xl); }
}

/* ── Header ── */
.profile-header {
    /* Единый размер: аватар и круглые кнопки-иконки равны ему. */
    --profile-avatar-size: 3.5rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.25rem;
}
.profile-header-left {
    display: flex;
    align-items: center;
    gap: 1rem;
    min-width: 0;
}
.profile-avatar {
    width: var(--profile-avatar-size);
    height: var(--profile-avatar-size);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    object-fit: cover;
    flex-shrink: 0;
    background: var(--bg-raised);
}
.profile-name {
    font-size: var(--text-xl);
    font-weight: var(--font-weight-bold);
    color: var(--text-main);
    line-height: var(--leading-tight);
}
.profile-id {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    font-size: var(--text-xs);
    color: var(--text-subtle);
    margin-top: 0.2rem;
    cursor: default;
}
.profile-id-copy {
    color: var(--text-subtle);
    cursor: pointer;
    padding: 0.1rem;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    transition: color var(--transition);
    line-height: var(--leading-none);
}
@media (hover: hover) {
    .profile-id-copy:hover { color: var(--text-muted); }
}

/* ── Settings button (gear icon) ── */
.profile-settings-btn {
    width: var(--profile-avatar-size);
    height: var(--profile-avatar-size);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-raised);
    border: none;
    color: var(--text-muted);
    font-size: var(--text-lg);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background var(--transition), color var(--transition);
}
@media (hover: hover) {
    .profile-settings-btn:hover {
        background: var(--bg-hover);
        color: var(--text-main);
    }
}

/* ── Settings modal overlay (шторка) ── */
.profile-settings-overlay {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    z-index: var(--z-modal);
}
@media (min-width: 640px) {
    .profile-settings-overlay {
        align-items: center;
        padding: 1rem;
    }
}
.profile-settings-card {
    position: relative;
    max-height: calc(100dvh - 24px);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--bg-panel);
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-modal);
    width: 100%;
    max-width: 100%;
    padding: 0 1.5rem 1.5rem;
    padding-bottom: calc(1.5rem + var(--safe-area-bottom, 0px));
}
@media (min-width: 640px) {
    .profile-settings-card {
        border-radius: var(--radius-2xl);
        corner-shape: var(--corner-shape-surface);
        max-width: 420px;
        padding: 1.5rem;
    }
}

.profile-settings-field {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    margin-bottom: 1rem;
}
.profile-settings-label {
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}
.profile-settings-field .input-field {
    color: var(--text-main);
}

/* ── Balance card ── */
.profile-balance-card {
    margin-bottom: 1.25rem;
}
.profile-balance-layout {
    display: grid;
    grid-template-columns: minmax(0, 1.65fr) minmax(18rem, 0.95fr);
    gap: 0.85rem;
    align-items: stretch;
}
.profile-balance-eyebrow-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
}
.profile-balance-eyebrow {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}
.profile-status-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.32rem 0.65rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    background: var(--bg-raised);
    color: var(--text-muted);
}
.profile-status-pill.is-active {
    background: var(--surface-soft);
    color: var(--text-main);
}
.profile-status-pill.is-inactive {
    background: var(--bg-raised);
    color: var(--text-muted);
}
.profile-balance-summary-card,
.profile-balance-wallet-card {
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-surface);
    padding: 1.1rem 1.2rem;
}
.profile-balance-summary-card {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    background: var(--bg-elevated);
}
.profile-balance-summary-main {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
}
.profile-balance-plan-name {
    font-size: var(--text-title);
    font-weight: var(--font-weight-display);
    letter-spacing: var(--tracking-display);
    line-height: var(--leading-none);
    color: var(--text-main);
    text-wrap: balance;
    max-width: 10ch;
}
.profile-balance-amount {
    font-size: var(--text-metric);
    font-weight: var(--font-weight-display);
    color: var(--text-main);
    line-height: var(--leading-none);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
@media (min-width: 768px) {
    .profile-balance-plan-name,
    .profile-balance-amount {
        font-family: var(--font-display);
    }
}
.profile-balance-caption {
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--text-muted);
    max-width: 36rem;
}
.profile-balance-summary-meta {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.65rem;
    margin-top: auto;
}
.profile-balance-meta-item {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.8rem 0.9rem;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
}
.profile-balance-meta-label {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}
.profile-balance-meta-value {
    font-size: var(--text-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    line-height: var(--leading-tight);
}
.profile-balance-meta-note {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    line-height: var(--leading-snug);
}
.profile-balance-wallet-card {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    background: var(--bg-elevated);
}
.profile-balance-wallet-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}
.profile-balance-wallet-label {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}
.profile-balance-wallet-icon {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal;
    color: var(--primary-text);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--text-lg);
    flex-shrink: 0;
}
.profile-balance-wallet-main {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}
.profile-balance-wallet-note {
    font-size: var(--text-sm);
    color: var(--text-muted);
}
.profile-balance-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: stretch;
    margin-top: auto;
}
.profile-topup-btn {
    padding: 0.6rem 1rem;
    font-size: var(--text-control);
    font-weight: var(--font-weight-medium);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    white-space: nowrap;
    flex-shrink: 0;
    text-transform: none;
    letter-spacing: var(--tracking-normal);
    min-width: 0;
    flex: 1 1 10rem;
}
.profile-secondary-btn {
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: color-mix(in srgb, var(--bg-panel) 42%, var(--bg-elevated));
    box-shadow: none;
}
.profile-balance-actions .profile-secondary-btn {
    flex: 1 1 100%;
    width: 100%;
    min-width: 0;
    min-height: calc(var(--gap-sm) * 6);
    padding: calc(var(--gap-sm) * 1.5);
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    background-color: var(--surface-soft);
    line-height: var(--leading-tight);
    text-align: center;
    text-wrap: balance;
}
.profile-balance-actions .profile-secondary-btn:focus-visible {
    outline: 2px solid var(--primary-500);
    outline-offset: 3px;
}
@media (hover: hover) {
    .profile-secondary-btn:hover {
        background-color: var(--bg-hover);
        box-shadow: none;
    }
    .profile-balance-actions .profile-secondary-btn:hover {
        background-color: var(--surface-strong);
    }
}
.profile-balance-lock-note {
    margin-top: 0.75rem;
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    color: var(--text-muted);
}

/* Balance and checkout share compact, token-driven controls. */
.profile-balance-wallet {
    display: grid;
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
    align-items: center;
    gap: calc(var(--gap-sm) * 3) calc(var(--gap-sm) * 5);
    padding: calc(var(--gap-sm) * 3);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-elevated);
    box-shadow: none;
}
.profile-balance-wallet__main { display: grid; gap: var(--gap-sm); min-width: 0; }
.profile-balance-wallet__amount {
    font-family: var(--font-display);
    font-size: var(--text-metric);
    font-weight: var(--font-weight-display);
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-display);
    font-variant-numeric: lining-nums tabular-nums;
    overflow-wrap: anywhere;
}
.profile-topup-label, .profile-balance-wallet__note {
    font-size: var(--text-label);
    line-height: var(--leading-normal);
    color: var(--text-muted);
    margin: 0;
}
.profile-balance-wallet__panel { display: grid; gap: var(--gap-sm); min-width: 0; }
.profile-balance-wallet__title {
    margin: 0;
    font-family: var(--font-display);
    font-weight: var(--font-weight-display);
    font-size: var(--text-card);
    line-height: var(--leading-snug);
    letter-spacing: var(--tracking-tight);
}
.profile-topup-methods { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap-sm); width: 100%; }
.profile-topup-method {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    min-height: calc(var(--gap-sm) * 6);
    padding: calc(var(--gap-sm) * 1.5);
    border: 0;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
    color: var(--text-main);
    font-size: var(--text-control);
    font-weight: var(--font-weight-medium);
    line-height: var(--leading-tight);
    cursor: pointer;
    transition: background var(--transition-fast);
}
.profile-topup-method > img { width: calc(var(--gap-sm) * 3); height: calc(var(--gap-sm) * 3); object-fit: contain; }
.profile-topup-method > .ti { font-size: var(--text-xl); }
.profile-topup-method .profile-topup-method__arrow { margin-left: auto; font-size: var(--text-sm); color: var(--text-muted); }
.profile-topup-method:focus-visible { outline: 2px solid var(--primary-500); outline-offset: 3px; }
@media (hover: hover) {
    .profile-topup-method:hover { background: var(--surface-strong); }
}
@media (max-width: 639px) {
    .profile-balance-wallet { grid-template-columns: minmax(0, 1fr); padding: calc(var(--gap-sm) * 2); gap: calc(var(--gap-sm) * 3); }
}
.payment-amount-value {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: var(--gap-xs);
    min-width: 0;
    font-family: var(--font-display);
    font-size: clamp(var(--text-xl), 10cqw, var(--text-metric));
    font-weight: var(--font-weight-display);
    line-height: var(--leading-tight);
}
.payment-amount-currency {
    flex: 0 0 auto;
    font-size: 0.65em;
    color: var(--text-muted);
}
.payment-options { margin-top: calc(var(--gap-sm) * 2); font-size: var(--text-label); color: var(--text-muted); }
.payment-autopay-toggle { display: flex; justify-content: space-between; align-items: center; gap: calc(var(--gap-sm) * 1.5); min-height: calc(var(--gap-sm) * 5); padding: var(--gap-sm) 0; background: transparent; border-radius: 0; color: var(--text-main); font-size: var(--text-sm); cursor: pointer; }
.payment-autopay-toggle input[type="checkbox"] {
    width: 2.75rem;
    height: 1.5rem;
}
.payment-autopay-toggle input[type="checkbox"]::after {
    left: 0.1875rem;
    width: 1.125rem;
    height: 1.125rem;
}
.payment-autopay-toggle input[type="checkbox"]:checked::after {
    transform: translateY(-50%) translateX(1.25rem);
}
.payment-method-card.is-preferred { background: var(--surface-strong); }
.payment-method-card.is-preferred .ti-chevron-right { color: var(--text-main); }

@media (max-width: 1120px) {
    .profile-balance-layout {
        grid-template-columns: 1fr;
    }

    .profile-balance-plan-name {
        max-width: 100%;
    }
}

@media (max-width: 720px) {
    .profile-balance-summary-meta {
        grid-template-columns: 1fr;
    }
}
/* ── Tabs ── */
.profile-tabs,
.shell-tabs {
    /* --seg-gap = отступ вкладок от края контейнера; наследуется вкладками и
       используется для концентрического внутреннего радиуса (см. .profile-tab). */
    --seg-gap: 0.3rem;
    display: flex;
    gap: 0.3rem;
    padding: var(--seg-gap);
    /* One controlled strip for shell/profile navigation. The clip remains
       scrollable by pointer, wheel, focus and selection through drag-scroll;
       it does not create an asynchronous native scroll backing on iOS. */
    overflow: hidden;
    touch-action: pan-y pinch-zoom;
    scroll-behavior: smooth;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
}

.profile-tabs {
    background: var(--bg-elevated);
    margin: 1rem 0;
}


.shell-tabs-frame {
    --shell-tabs-edge-width: calc(var(--gap-sm) * 3);
    position: relative;
    min-width: 0;
    isolation: isolate;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    /* The nav itself owns scrolling and its rounded clip. Clipping this glass
       parent again leaves a second scroll/paint boundary around the text. */
}
.shell-tabs {
    --seg-gap: var(--shell-header-inset);
    margin: 0;
    position: relative;
    isolation: isolate;
    scroll-padding-inline: var(--shell-tabs-edge-width);
}
/* The edge hints belong to the morphing surface, outside its scrolling strip.
   No extra backdrop filter or animation clock is needed. */
.shell-tabs-edge {
    position: absolute;
    inset-block: 0;
    width: var(--shell-tabs-edge-width);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1;
    color: var(--text-main);
    font-size: var(--text-base);
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--shell-morph-dur) var(--motion-ease-standard);
}
.shell-tabs-edge--start {
    left: 0;
    border-start-start-radius: inherit;
    border-end-start-radius: inherit;
    background: linear-gradient(to right, var(--chat-input-solid) 65%, transparent);
}
.shell-tabs-edge--end {
    right: 0;
    border-start-end-radius: inherit;
    border-end-end-radius: inherit;
    background: linear-gradient(to left, var(--chat-input-solid) 65%, transparent);
}
.shell-tabs-frame[data-scroll-edges~="start"] > .shell-tabs-edge--start,
.shell-tabs-frame[data-scroll-edges~="end"] > .shell-tabs-edge--end { opacity: 1; }
.shell-tab-indicator {
    position: absolute;
    left: 0;
    pointer-events: none;
    z-index: -1;
    border-radius: max(0px, calc(var(--radius-pill) - var(--seg-gap, 0.3rem)));
    corner-shape: var(--corner-shape-round);
    background: var(--shell-tab-active-bg);
}
@media (prefers-reduced-motion: reduce) {
    .shell-tabs, .profile-tabs { scroll-behavior: auto; }
    .shell-tabs-edge { transition: none; }
}

.profile-tab,
.shell-tab {
    flex-shrink: 0;
    /* Концентрическое вложение: внутренний радиус = радиус контейнера − зазор.
       На капсулах (scale=1) незаметно, но когда ползунок скруглений уводит пилюли
       в скруглённый прямоугольник — угол вкладки идёт параллельно углу контейнера. */
    border-radius: max(0px, calc(var(--radius-pill) - var(--seg-gap, 0.3rem)));
    corner-shape: var(--corner-shape-round);
    font-weight: var(--font-weight-regular);
    color: var(--text-subtle);
    cursor: pointer;
    transition: color var(--transition);
    border: none;
    background: transparent;
    white-space: nowrap;
}
.profile-tab { transition: background var(--transition), color var(--transition); }
/* Shell selection has one painter. Before hydration the active button supplies
   the fallback; after placement ShellHeaderService owns the moving indicator.
   A background transition on the button would keep the fallback alive while
   the indicator moves, painting a second selection on each replaced header. */
.shell-tabs:not(.has-tab-indicator) .shell-tab.is-active {
    background: var(--shell-tab-active-bg);
}
/* Профильные табы = тот же размер/стиль, что и основное меню (.shell-tab),
   и сохраняются такими на десктопе (не ужимаются). */
.profile-tab,
.shell-tab {
    padding: 0.58rem 1.12rem;
    font-size: var(--text-lg);
    text-decoration: none;
}
@media (hover: hover) {
    .profile-tab:hover,
    .shell-tab:hover { color: var(--text-muted); }
}
.profile-tab.is-active,
.shell-tab.is-active {
    color: var(--text-main);
}
.profile-tab.is-active { background: var(--bg-raised); }

.shell-tab.is-disabled {
    opacity: 0.35;
    pointer-events: none;
}

/* One mask fades a canvas-coloured layer; a raised-surface midpoint or a
   second alpha gradient can leave a visible band over an empty page. */
.shell-mobile-header-host,
.shell-desktop-header {
    --header-scrim-tail: 2.75rem;
    --surface-fade-top-strong-mask: linear-gradient(to bottom, black 0, black 14%, transparent 62%);
    --surface-fade-top-tint-gradient: linear-gradient(var(--bg-app), var(--bg-app));
    --surface-fade-top-tint-opacity: 1;
}

/* ── Shell Mobile Header ── */
.shell-mobile-header-host {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: var(--z-backdrop);
    /* overflow VISIBLE (не hidden): растушёвка-хвост уходит НИЖЕ коробки хоста
       через ::before/::after (bottom: -tail), НЕ увеличивая измеряемую высоту
       хоста — а её shellHeader.js кладёт в --shell-mobile-header-offset (offset
       контента). Раньше padding-block-end раздувал высоту → лишний отступ до
       контента. Плюс без клипа overflow:hidden нет 1px-полосы на границе. */
    overflow: visible;
    padding-block-start: calc(var(--app-safe-top) + 0.55rem);
    padding-block-end: var(--gap-sm);
    padding-inline: var(--shell-mobile-gutter);
    background: transparent;
    pointer-events: none;
}

.shell-mobile-header-host > [data-header-variant] { display: none; }
.shell-mobile-header-host[data-header-mode="shell"] > [data-header-variant="shell"],
.shell-mobile-header-host[data-header-mode="chat"] > [data-header-variant="chat"],
.shell-mobile-header-host[data-header-mode="draft"] > :is([data-header-variant="shell"], [data-header-variant="chat"]),
.shell-mobile-header-host[data-header-mode="workflow"] > [data-header-variant="workflow"],
.shell-mobile-header-host[data-header-mode="transcription"] > [data-header-variant="transcription"],
.shell-mobile-header-host[data-header-mode="music"] > [data-header-variant="music"] { display: block; }

.shell-mobile-header-host::before,
.shell-mobile-header-host::after {
    content: '';
    position: absolute;
    inset: 0;
    /* Хвост растушёвки уходит ниже коробки хоста — есть разбег под табами, но высота
       хоста (= offset контента) не растёт. Маска доводит его до нуля. */
    bottom: calc(-1 * var(--header-scrim-tail, 2.75rem));
    pointer-events: none;
    z-index: 0;
}

.shell-mobile-header-host::before {
    content: none;
}

.shell-mobile-header-host::after,
.shell-desktop-header::before {
    background: var(--surface-fade-top-tint-gradient);
    opacity: var(--surface-fade-top-tint-opacity);
    -webkit-mask-image: var(--surface-fade-top-strong-mask);
    mask-image: var(--surface-fade-top-strong-mask);
}

.app-root > .app-shell-body {
    position: relative;
    z-index: 0;
}

.shell-mobile-header-host > * {
    position: relative;
    z-index: 1;
    pointer-events: auto;
}

.shell-mobile-header,
.shell-mobile-chat-header,
.shell-mobile-page-header {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}

.shell-mobile-header-top,
.shell-mobile-chat-header-bar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.shell-mobile-chat-header-bar--draft {
    padding-top: 0.45rem;
}

.shell-mobile-header-top {
    justify-content: space-between;
}

.shell-mobile-header-brand {
    /* Логотип мобильной шапки привязан к высоте пилюли профиля
       (--shell-header-slot) — равны и зависимы: меняешь слот → меняются оба.
       --brand-logo-size здесь НЕ используем (он общий для рейла/вьюера/signin). */
    width: var(--shell-header-slot);
    height: var(--shell-header-slot);
    min-width: var(--shell-header-slot);
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    color: var(--text-main);
}

.shell-mobile-header-logo-icon {
    display: block;
    width: 100%;
    height: 100%;
    flex-shrink: 0;
}

.shell-mobile-chat-header-btn {
    width: var(--shell-header-slot);
    height: var(--shell-header-slot);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    color: var(--text-main);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    border: none;
    flex-shrink: 0;
    cursor: pointer;
}

.shell-mobile-chat-header-btn-active {
    background: var(--surface-soft);
    color: var(--text-main);
}

.shell-mobile-chat-header-copy {
    min-width: 0;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.08rem;
}

.shell-mobile-chat-header-eyebrow {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

.shell-mobile-chat-header-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--text-sm);
    color: var(--text-main);
    font-weight: var(--font-weight-semibold);
}

.shell-mobile-chat-header-actions {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    flex-shrink: 0;
}

@media (max-width: 767.98px) {
    .sidebar-top-offset {
        top: var(--shell-mobile-header-offset);
        height: calc(100% - var(--shell-mobile-header-offset));
    }
}

/* ── Desktop shell header: the edge fade belongs to the floating header itself. ── */
.shell-desktop-header {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 20;
    align-items: center;
    justify-content: space-between;
    gap: var(--shell-page-gap);
    padding: var(--shell-header-padding-block) var(--shell-page-gutter);
    background: transparent;
    pointer-events: none;
}
.shell-desktop-header::before {
    content: '';
    position: absolute;
    inset: 0;
    bottom: calc(-1 * var(--header-scrim-tail));
    z-index: -1;
    pointer-events: none;
}

.shell-desktop-header__left,
.shell-desktop-header__right {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    min-width: 0;
    flex-shrink: 0;
    pointer-events: auto;
}

.shell-desktop-header__left:empty { display: none; }
/* Keep the profile on the right even when navigation and the player are hidden. */
.shell-desktop-header__right { margin-inline-start: auto; }
.shell-desktop-header.has-player .group-header--desktop { flex: 0 1 auto; max-width: min(32%, 24rem); }

.shell-desktop-header__toggle {
    width: var(--shell-header-slot);
    height: var(--shell-header-slot);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    color: var(--text-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    cursor: pointer;
    transition: background-color var(--transition), color var(--transition);
}

/* Shared user pill: balance + avatar in one rounded container.
   Размер пилюли задаётся через --shell-header-slot, всё внутри derived от него:
   balance растягивается по высоте, profile — quadratic через aspect-ratio,
   avatar полностью заполняет profile. Никаких явных размеров на детях.
   Внутренний padding даёт аватару визуальный inset от каёмки пилюли — чтобы
   круп аватар-картинки не казался «упёртым» в curve cap'а пилюли. */
.shell-user-pill {
    display: inline-flex;
    align-items: stretch;
    gap: 0;
    height: var(--shell-header-slot);
    padding: var(--shell-header-inset);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    border: none;
    -webkit-appearance: none;
    appearance: none;
    font: inherit;
    color: inherit;
    cursor: pointer;
    transition: background-color var(--transition);
}

.shell-user-pill__balance {
    display: inline-flex;
    align-items: center;
    padding: 0 0.4rem 0 0.75rem;
    color: var(--text-main);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    text-decoration: none;
    white-space: nowrap;
    flex-shrink: 0;
    background: transparent;
    transition: color var(--transition);
}

/* Кнопка «Пополнить» вместо суммы: нулевой баланс без тарифа (см. showTopupPill()).
   CTA-градиент темы с шумом (следует за data-accent), как .btn-primary. Высота — во
   всю внутреннюю высоту пилюли (align-items:stretch), т.е. как у аватарки; справа —
   отступ от аватарки. Клик по пилюле ведёт в профиль как обычно; аватар остаётся. */
.shell-user-pill__balance--topup {
    display: flex;
    align-items: center;
    padding: 0 0.7rem;
    margin-right: 0.3rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    color: var(--primary-text);
    font-weight: var(--font-weight-bold);
    background-color: var(--primary-500);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
}

.shell-user-pill__profile {
    position: relative;
    flex: 0 0 auto;
    /* Явная ширина: Safari не выводит её из aspect-ratio, когда высота
       приходит через align-items: stretch — без width аватар коллапсится
       в полоску, и balance визуально наезжает. */
    width: var(--shell-header-control-size);
    aspect-ratio: 1;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    overflow: hidden;
    background: transparent;
    text-decoration: none;
    border: none;
    cursor: pointer;
    transition: background-color var(--transition);
}

.shell-user-pill--standalone {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: var(--shell-header-slot);
    width: var(--shell-header-slot);
    color: var(--text-main);
}

/* ── Групповой чат в шапке (desktop + mobile) ──
   Участники живут прямо в ряду шапки (в один рост с кнопкой сворачивания на десктопе
   и с логотипом/профилем на мобиле) — без отдельной полосы над лентой (та рисовала
   чёрный кант и резала верх сообщений). Заголовок + аватары; лишние участники
   скроллятся вправо, край затухает маской. Скругления — только токены. */
.group-header {
    --group-avatar-size: var(--shell-header-slot);
    --group-avatar-step: calc(var(--group-avatar-size) * .62);
    display: flex;
    align-items: center;
    gap: var(--gap-xs);
    flex: 1 1 auto;
    min-width: 0;
    pointer-events: auto;
}
.group-header__people { min-width: 0; flex: 0 1 auto; overflow: hidden; }
.group-header.is-expanded .group-header__people { overflow-x: auto; }
.group-header__track {
    position: relative;
    height: var(--group-avatar-size);
    width: calc(var(--group-avatar-size) + (var(--stack-count) - 1) * var(--group-avatar-step));
    transition: width var(--motion-duration-base) var(--motion-ease-premium);
}
.group-header.is-expanded { --group-avatar-step: calc(var(--group-avatar-size) + var(--gap-sm)); }
.group-header.is-expanded .group-header__track {
    width: calc(var(--group-avatar-size) + (var(--member-count) - 1) * var(--group-avatar-step));
}
.group-header__chip {
    position: absolute;
    inset: 0 auto auto 0;
    width: var(--group-avatar-size);
    height: var(--group-avatar-size);
    padding: var(--gap-2xs);
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-app);
    color: var(--text-main);
    transform: translateX(calc(var(--member-index) * var(--group-avatar-step)));
    transition: transform var(--motion-duration-base) var(--motion-ease-premium),
                opacity var(--motion-duration-fast) var(--motion-ease-standard);
}
.group-header__chip.is-stacked-away { opacity: 0; pointer-events: none; visibility: hidden; }
.group-header__avatar { display: block; width: 100%; height: 100%; border-radius: inherit; corner-shape: inherit; object-fit: cover; background: var(--bg-elevated); }
.group-header__avatar--fallback { display: grid; place-items: center; color: var(--text-muted); font-size: var(--text-sm); font-weight: var(--font-weight-medium); text-transform: uppercase; }
.group-header__presence { position: absolute; inset: auto var(--gap-2xs) var(--gap-2xs) auto; width: var(--gap-sm); height: var(--gap-sm); border-radius: var(--radius-round); corner-shape: var(--corner-shape-round); background: var(--primary-500); box-shadow: 0 0 0 var(--gap-2xs) var(--bg-app); }
.group-header__action, .group-header__expand {
    display: inline-flex; align-items: center; justify-content: center;
    flex-shrink: 0; gap: var(--gap-2xs); height: var(--group-avatar-size);
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round); color: var(--text-muted);
    transition: background-color var(--transition-fast), color var(--transition-fast);
}
.group-header__action { width: var(--group-avatar-size); margin-inline-start: auto; background: var(--chat-input-bg); font-size: var(--text-lg); }
.group-header__expand { padding-inline: var(--gap-xs); font-size: var(--text-xs); }
.group-header__expand i { transition: transform var(--motion-duration-base) var(--motion-ease-premium); }
.group-header__expand .is-reversed { transform: rotate(180deg); }
@media (hover: hover) {
    .group-header__action:hover, .group-header__expand:hover { color: var(--text-main); background: var(--surface-strong); }
    .group-header__chip:hover .group-header__avatar { background: var(--surface-active); }
}
.group-header button:focus-visible { outline: none; box-shadow: inset 0 0 0 var(--gap-2xs) var(--primary-500); }
@media (prefers-reduced-motion: reduce) {
    .group-header__track, .group-header__chip, .group-header__expand i { transition: none; }
}

/* Group creation event: one heading, description and invitation action. */
.group-invite-cta {
    padding: calc(var(--gap-sm) * 3) calc(var(--gap-sm) * 2);
}
.group-invite-cta__copy { display: flex; flex-direction: column; gap: var(--gap-xs); }
.group-invite-cta__description { color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-snug); }
.group-invite-cta .btn:disabled { background: var(--surface-soft); color: var(--text-muted); }

/* Индикатор «печатает…» в ленте групп-чата: три пульсирующие точки + текст. */
.chat-typing-indicator { padding: 0.15rem 0; }
.chat-typing-dots { display: inline-flex; align-items: center; gap: 3px; flex-shrink: 0; }
.chat-typing-dots span {
    width: 5px;
    height: 5px;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background-color: var(--text-muted);
    animation: chat-typing-bounce var(--motion-period-pulse) infinite var(--motion-ease-ambient) both var(--pane-ambient-play-state, running);
}
.chat-typing-dots span:nth-child(2) { animation-delay: calc(var(--motion-period-pulse) * 0.125); }
.chat-typing-dots span:nth-child(3) { animation-delay: calc(var(--motion-period-pulse) * 0.25); }
@keyframes chat-typing-bounce {
    0%, 80%, 100% { transform: translateY(0); opacity: 0.4; }
    40% { transform: translateY(-3px); opacity: 1; }
}

/* Аватар-«мордашка»: нейтральный минималистичный SVG-смайл с объёмом (3D-шар) и
   нативной SMIL-анимацией (см. components/_user_avatar_face.html). Заменяет фото
   пользователя в шелле (шапки + рейл); реальное фото — только в профиле
   (.profile-avatar). SVG рисует и шар, и лицо сам; масштабируется под контейнер. */
.user-avatar-face {
    display: block;
    isolation: isolate; /* blend-mode свечения замыкаем внутри SVG */
    -webkit-user-select: none;
    user-select: none;
}
/* Стопы сферы: блик → база → затенённый край. Оттенки выводим из нейтрального
   --bg-raised (тема dark/light переключается сама). Первый stop-color — фолбэк для
   браузеров без color-mix: сфера просто станет плоским нейтральным кругом. */
.user-avatar-face .uaf-stop-hi {
    stop-color: var(--bg-raised);
    stop-color: color-mix(in srgb, var(--bg-raised) 76%, #fff);
}
.user-avatar-face .uaf-stop-base { stop-color: var(--bg-raised); }
.user-avatar-face .uaf-stop-lo {
    stop-color: var(--bg-raised);
    stop-color: color-mix(in srgb, var(--bg-raised) 70%, #000);
}
/* Верхний глянец — мягкое белое пятно, тающее в прозрачность. */
.user-avatar-face .uaf-stop-gloss   { stop-color: #fff; stop-opacity: 0.20; }
.user-avatar-face .uaf-stop-gloss-0 { stop-color: #fff; stop-opacity: 0; }
/* Краевое свечение = стопы НАШЕГО --gradient-primary (--prism-pink → --prism-hi →
   --prism-lilac, следуют за data-accent): лёгкая дуга у одного края, гаснет к другому;
   ездит по кругу в такт наклону лица. Маска-кольцо держит центр чистым. Подсветка
   слабая (лишь слегка). Тёмная тема — screen (свет), светлая — multiply (тонирует). */
.user-avatar-face .uaf-glow-1 { stop-color: var(--prism-pink);  stop-opacity: 0.36; }
.user-avatar-face .uaf-glow-2 { stop-color: var(--prism-hi);    stop-opacity: 0.22; }
.user-avatar-face .uaf-glow-3 { stop-color: var(--prism-lilac); stop-opacity: 0.08; }
.user-avatar-face .uaf-glow-4 { stop-color: var(--prism-lilac); stop-opacity: 0; }
.user-avatar-face .uaf-glow { mix-blend-mode: screen; }
[data-theme="prism-light"] .user-avatar-face .uaf-glow { mix-blend-mode: multiply; }

/* Черты лица — нейтральный приглушённый тон. */
.user-avatar-face .uaf-eye { fill: var(--text-muted); }
.user-avatar-face .uaf-mouth { stroke: var(--text-muted); fill: none; }

/* ============================================================
   Mascot scene — брендовый маскот (SVG-лицо .user-avatar-face) на ночном
   звездопаде. Фон страницы входа (/login) и баннера NS ULTRA вместо статичных
   фото. Разметка/кометы — components/_mascot_scene.html. Всё на нативном SVG
   (SMIL-кометы + CSS-мерцание) — без JS/видео, стабильно и легко.
   Сцена всегда «ночная» в ОБЕИХ темах: цвета из --prism-* / --overlay-text
   (тема-константы); сфера — нейтральный серый из --overlay-text+black, НЕ из
   --bg-raised, поэтому в светлой теме не выцветает. Блок стоит ПОСЛЕ
   .user-avatar-face, чтобы scoped-оверрайды стопов лица выигрывали каскад
   при равной специфичности (tailwind тут ни при чём — свои классы).
   ============================================================ */
.mascot-scene {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
}
.mascot-scene__sky {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}
/* Фон сцены = тот же ватермарк SKYNY (_background_svg.html: --bg-app + ambient-
   свечение + слово SKYNY). Снимаем боевой position:fixed — держим в границах сцены.
   Небо-сцена (звёзды/кометы) — прозрачная SVG поверх, поэтому SKYNY проглядывается.
   Сцена ВСЕГДА «ночная» (тёмная) в ОБЕИХ темах: маскот/звёзды/текст/кнопка заточены
   под тёмное, а в светлой теме тема-зависимый фон делал баннер/логин грязно-серыми.
   Поэтому форсим тёмные значения фон-токенов независимо от data-theme (главный фон
   приложения при этом остаётся тема-зависимым — это отдельный экземпляр .bg-svg). */
.mascot-scene .bg-svg {
    position: absolute;
    --bg-app: var(--bg-night);
    --ambient-accent-500: var(--ambient-night-500);
    --ambient-accent-600: var(--ambient-night-600);
    --ambient-accent-700: var(--ambient-night-700);
}
/* Ватермарк СЦЕНЫ — всегда тихий свет на чёрном (сцена ночная). Гасим и градиент
   (тёмная тема), и белую заливку из светлой темы апп-фона (там она нужна, тут бьёт
   в глаза). Держим один тон в обеих темах. */
.mascot-scene :is(.bg-svg-desktop-letter, .bg-svg-mobile-letter) {
    fill: var(--overlay-text);
    fill-opacity: 0.1;
}
/* Комета — тонкий реалистичный след: длинный слабый хвост, ярко только у головы. */
.mascot-scene .ms-comet-0 { stop-color: var(--overlay-text); stop-opacity: 0; }
.mascot-scene .ms-comet-1 { stop-color: var(--overlay-text); stop-opacity: 0.05; }
.mascot-scene .ms-comet-2 { stop-color: var(--overlay-text); stop-opacity: 0.45; }
.mascot-scene .ms-comet-3 { stop-color: var(--overlay-text); stop-opacity: 0.9; }
.mascot-scene .ms-comet-head { fill: var(--overlay-text); }
.mascot-scene .ms-comet-glow { fill: var(--overlay-text); opacity: 0.35; }

/* Звёзды — крошечные (как настоящие), разной яркости (--o), тихое мерцание. */
.mascot-scene .ms-star {
    fill: var(--overlay-text);
    opacity: var(--o, 0.3);
    animation: ms-twinkle var(--motion-period-twinkle) var(--motion-ease-ambient) infinite;
}
@keyframes ms-twinkle {
    0%, 100% { opacity: calc(var(--o, 0.3) * 0.2); }
    50%      { opacity: var(--o, 0.3); }
}

/* Маскот поверх неба. Сфера — нейтральный серый орб (тема-независимо), освещён
   сверху, чтобы читался на ночном небе; свечение всегда screen (в светлой теме
   базовое .user-avatar-face даёт multiply — гасим). */
.mascot-scene__char {
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(150px, 30vmin, 260px);
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
}
.mascot-scene__face {
    width: 100%;
    height: 100%;
    position: relative;
    z-index: 1;
    /* Лёгкое свечение от самого маскота — мягкий ореол вокруг орба (в дополнение к
       световой лужице под ним), чтобы орб выглядел «светящимся», не плоским. */
    filter: drop-shadow(0 0 18px color-mix(in srgb, var(--prism-lilac) 16%, transparent));
}
.mascot-scene__face .uaf-stop-hi   { stop-color: color-mix(in srgb, var(--overlay-text) 58%, black); }
.mascot-scene__face .uaf-stop-base { stop-color: color-mix(in srgb, var(--overlay-text) 30%, black); }
.mascot-scene__face .uaf-stop-lo   { stop-color: color-mix(in srgb, var(--overlay-text) 11%, black); }
.mascot-scene__face .uaf-eye   { fill: color-mix(in srgb, var(--overlay-text) 82%, black); }
.mascot-scene__face .uaf-mouth { stroke: color-mix(in srgb, var(--overlay-text) 82%, black); }
/* Свет ТОЛЬКО под маскотом — мягкая световая лужица у основания (не вокруг него). */
.mascot-scene__char::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 5%;
    width: 64%;
    height: 22%;
    transform: translateX(-50%);
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: radial-gradient(50% 50% at 50% 50%, color-mix(in srgb, var(--prism-lilac) 26%, transparent) 0%, transparent 72%);
    filter: blur(7px);
    z-index: 0;
    pointer-events: none;
}
/* Собственное акцентное свечение лица (верхняя дуга) гасим — свет только снизу. */
.mascot-scene__face .uaf-glow { display: none; }

/* Уважаем reduced-motion: гасим мерцание и убираем летящие кометы (само лицо —
   SMIL, как и везде в шелле, оставляем). Небо + маскот + ореол остаются статикой. */
@media (prefers-reduced-motion: reduce) {
    .mascot-scene .ms-star { animation: none; opacity: 0.5; }
    .mascot-scene .ms-comet { display: none; }
}

/* В шапке SVG заполняет круглый слот .shell-user-pill__profile. */
.shell-user-pill__face {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

@media (hover: hover) {
    .shell-desktop-header__toggle:hover {
        background: var(--bg-raised);
        color: var(--text-main);
    }

    .shell-user-pill:hover {
        background: var(--bg-raised);
    }
}

/* ── Unpoly progress bar ── */
.up-progress-bar {
    background-image: var(--gradient-primary);
}

/* Shell enter animation теперь через WAAPI (unpoly-config.js animateContentEnter,
   element.animate) — без форс-reflow и класс-хака. reduced-motion гвардится в JS. */

/* ── Tab panels ── */
.profile-panel { display: none; }
.profile-panel.is-active { display: block; }

/* ── Info block (Общее) ── */
.profile-info-card,
.profile-sessions-card,
.profile-history-card,
.profile-referral-card {
    background: var(--bg-elevated);
    box-shadow: var(--shadow-surface);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
}

.profile-info-card,
.profile-history-card,
.profile-referral-card {
    margin-bottom: 1rem;
}

.profile-info-card,
.profile-sessions-card,
.profile-history-card {
    overflow: hidden;
}
.payment-iframe--pending { max-height: 0; visibility: hidden; }
.payment-header-main { display: flex; align-items: center; gap: var(--gap-sm); min-width: 0; }
.payment-header-main .modal-header-title { min-width: 0; }
.payment-header-main .payment-header-back { flex-shrink: 0; }
.payment-step { padding-top: var(--gap-sm); }
.payment-bank-context { display: flex; align-items: center; gap: var(--gap-sm); min-height: calc(var(--gap-sm) * 5); margin-bottom: var(--gap-sm); font-size: var(--text-control); color: var(--text-muted); }
.payment-bank-context > .ti { font-size: var(--text-xl); }
.payment-bank-context > img { width: calc(var(--gap-sm) * 3); height: calc(var(--gap-sm) * 3); object-fit: contain; }
.payment-bank-context > span { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.payment-bank-context > strong { font-weight: var(--font-weight-medium); color: var(--text-main); white-space: nowrap; }
.payment-inline-status { display: flex; align-items: center; gap: calc(var(--gap-sm) * 1.5); min-height: calc(var(--gap-sm) * 8); padding: var(--gap-sm) 0; font-size: var(--text-body); color: var(--text-muted); }
.payment-inline-status .loading-spinner { flex-shrink: 0; margin: 0; }
.payment-feedback { display: flex; align-items: flex-start; gap: var(--gap-sm); padding: calc(var(--gap-sm) * 2) 0; font-size: var(--text-body); line-height: var(--leading-normal); color: var(--text-muted); }
.payment-feedback > .ti { font-size: var(--text-xl); flex-shrink: 0; }
.payment-feedback p { margin: 0; overflow-wrap: anywhere; }
.payment-bank-actions { display: flex; align-items: center; gap: var(--gap-sm); margin: var(--gap-sm) 0 calc(var(--gap-sm) * 1.5); }
.payment-bank-link { display: flex; align-items: center; justify-content: center; gap: var(--gap-sm); width: 100%; min-width: 0; min-height: calc(var(--gap-sm) * 6); font-size: var(--text-control); line-height: var(--leading-normal); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.payment-retry { width: calc(var(--gap-sm) * 6); height: calc(var(--gap-sm) * 6); padding: 0; flex-shrink: 0; font-size: var(--text-xl); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.payment-qr { display: grid; justify-items: center; gap: calc(var(--gap-sm) * 1.5); padding-top: var(--gap-sm); }
.payment-qr__image { display: block; width: calc(var(--gap-sm) * 26); max-width: 100%; height: auto; aspect-ratio: 1; object-fit: contain; padding: var(--gap-sm); background: var(--surface-paper); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.payment-result { display: grid; justify-items: center; gap: var(--gap-sm); padding: calc(var(--gap-sm) * 2) 0 calc(var(--gap-sm) * 3); text-align: center; }
.payment-result__icon { font-size: var(--text-3xl); color: var(--text-muted); }
.payment-result h4 { margin: 0; font-family: var(--font-display); font-size: var(--text-dialog); font-weight: var(--font-weight-display); line-height: var(--leading-tight); }
.payment-result .payment-note { max-width: 34ch; margin: 0; }
.payment-result-actions { display: grid; gap: var(--gap-sm); }
.payment-result-actions .btn { min-height: calc(var(--gap-sm) * 6); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.profile-info-row {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.85rem 1.25rem;
    box-shadow: none;
}
.profile-info-row:last-child { box-shadow: none; }
.profile-info-label {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}
.profile-info-value {
    font-size: var(--text-sm);
    color: var(--text-main);
    word-break: break-all;
}

/* ── Section heading inside panel ── */
.profile-section-title {
    font-size: var(--text-card);
    font-weight: var(--font-weight-display);
    color: var(--text-main);
    margin-bottom: 0.75rem;
}

/* ── Sessions ── */
.profile-session-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.85rem 1.25rem;
    box-shadow: none;
    transition: background var(--transition);
}
.profile-session-row:last-child { box-shadow: none; }
@media (hover: hover) {
    .profile-session-row:hover { background: var(--bg-hover); }
}
.profile-session-device {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    color: var(--text-main);
}
.profile-session-meta {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    margin-top: 0.15rem;
    display: flex;
    gap: var(--gap-sm);
    flex-wrap: wrap;
}
.profile-session-current {
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    background: var(--surface-soft);
    padding: 0.15rem 0.5rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
}
.profile-session-end-btn {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    box-shadow: none;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    padding: 0.25rem 0.65rem;
    background: transparent;
    cursor: pointer;
    white-space: nowrap;
    transition: color var(--transition), box-shadow var(--transition), background var(--transition);
    flex-shrink: 0;
}
@media (hover: hover) {
    .profile-session-end-btn:hover {
        color: var(--text-main);
        box-shadow: none;
        background: var(--surface-soft);
    }
}

/* ── Analytics chart ── */
.profile-analytics-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1rem;
}
.profile-month-nav {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
}
.profile-month-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    box-shadow: none;
    border: none;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    text-decoration: none;
    transition: background var(--transition), color var(--transition);
    font-size: var(--text-sm);
}
@media (hover: hover) {
    .profile-month-btn:hover { background: var(--bg-raised); color: var(--text-main); }
}
.profile-month-btn.is-disabled {
    opacity: 0.3;
    pointer-events: none;
}
.profile-month-label {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    color: var(--text-main);
    min-width: 7rem;
    text-align: center;
}

.profile-chart-card {
    background: var(--bg-elevated);
    box-shadow: var(--shadow-surface);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    padding: 1.25rem 1.25rem 0.75rem;
    margin-bottom: 1rem;
}
.profile-chart-bars {
    display: flex;
    align-items: flex-end;
    gap: 2px;
    height: 80px;
}
.profile-chart-bar-wrap {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    height: 100%;
    justify-content: flex-end;
}
.profile-chart-bar {
    width: 100%;
    height: var(--bar-h, 2px);
    min-height: 2px;
    border-radius: calc(2px * var(--radius-scale)) calc(2px * var(--radius-scale)) 0 0;
    background-image: var(--gradient-primary);
    opacity: 0.7;
    transition: opacity var(--transition);
}
@media (hover: hover) {
    .profile-chart-bar:hover { opacity: 1; }
}
.profile-chart-bar.is-zero {
    background: var(--bg-raised);
    opacity: 1;
    min-height: 3px;
}
.profile-chart-footer {
    display: flex;
    justify-content: space-between;
    margin-top: 0.4rem;
    font-size: var(--text-2xs);
    color: var(--text-subtle);
}
.profile-analytics-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--gap-sm);
    padding: 2rem 1rem;
    color: var(--text-subtle);
    font-size: var(--text-sm);
}
.profile-empty-icon {
    font-size: var(--text-3xl);
    opacity: 0.4;
}

/* ── History list ── */
.profile-history-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1.25rem;
    box-shadow: none;
    gap: 0.75rem;
}
.profile-history-item:last-child { box-shadow: none; }
.profile-history-left {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}
.profile-history-top {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    flex-wrap: wrap;
}
.profile-history-type {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    color: var(--text-main);
}
.profile-history-model-chip {
    font-size: var(--text-2xs);
    padding: 0.1rem 0.5rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-raised);
    color: var(--text-subtle);
    white-space: nowrap;
    max-width: 160px;
    overflow: hidden;
    text-overflow: ellipsis;
}
.profile-history-meta {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-size: var(--text-xs);
    color: var(--text-subtle);
}
.profile-history-meta-item {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}
.profile-history-amount {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    white-space: nowrap;
    flex-shrink: 0;
}
.profile-history-amount.is-expense { color: var(--text-main); }
.profile-history-amount.is-income { color: var(--text-main); }

/* ── Referral panel ── */
.profile-referral-card {
    padding: 1.25rem 1.5rem;
}
.profile-ref-link-row {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    background: var(--bg-raised);
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    padding: 0.5rem 0.75rem;
    margin-top: 0.5rem;
    overflow: hidden;
}
.profile-ref-link-text {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--text-xs);
    color: var(--text-subtle);
}
.profile-ref-copy-btn {
    flex-shrink: 0;
    font-size: var(--text-xs);
    padding: 0.25rem 0.65rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-main);
    border: none;
    cursor: pointer;
    transition: background var(--transition);
    white-space: nowrap;
}
@media (hover: hover) {
    .profile-ref-copy-btn:hover { background: var(--surface-strong); }
}
.profile-ref-stat {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    font-size: var(--text-sm);
    color: var(--text-muted);
    margin-top: 1rem;
}
.profile-ref-stat strong { color: var(--text-main); }

/* ── Pager ── */
.profile-pager {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem;
    box-shadow: none;
}
.profile-pager-text {
    font-size: var(--text-xs);
    color: var(--text-subtle);
}

/* ── Danger zone ── */
/* ── Styles tab: Theme & Accent picker ── */
.profile-theme-row {
    position: relative;
    display: flex;
    gap: 0.25rem;
    padding: 0.2rem;
    /* Утопленный трек на карточке контролов (--bg-elevated), чтобы сегмент читался. */
    background: var(--bg-input);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
}
/* Инлайн-ряд «метка — сегмент»: фикс. ширина сегмента, кнопки остаются равными
   (flex:1) → скользящий thumb (50%) попадает точно под активную. */
.profile-styles__group--inline .profile-theme-row {
    flex: 0 0 auto;
    width: 13.5rem;
}
/* Скользящая подложка активной темы — плавный переход вместо резкой смены фона
   («смена тёмной/светлой выглядела ужасно»). Ширина = половина ряда за вычетом
   двух паддингов и одного гэпа; сдвиг на вторую позицию = её ширина + гэп. */
.profile-theme-thumb {
    position: absolute;
    z-index: 0;
    top: 0.2rem;
    left: 0.2rem;
    width: calc((100% - 0.65rem) / 2);
    height: calc(100% - 0.4rem);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-raised);
    box-shadow: var(--shadow-surface);
    pointer-events: none;
    transition: transform var(--motion-duration-shell) var(--motion-ease-premium);
}
.profile-theme-row.is-second .profile-theme-thumb {
    transform: translateX(calc(100% + 0.25rem));
}
.profile-theme-btn {
    position: relative;
    z-index: 1;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 0.45rem 0.5rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    border: none;
    background: transparent;
    color: var(--text-subtle);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
    transition: color var(--transition);
}
@media (hover: hover) {
    .profile-theme-btn:not(.is-active):hover { color: var(--text-muted); }
}
.profile-theme-btn.is-active {
    color: var(--text-main);
}
.profile-accent-row {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.profile-styles__group--inline .profile-accent-row {
    flex: 0 1 auto;
    justify-content: flex-end;
}
.profile-accent-swatch {
    width: 2rem;
    height: 2rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-image: var(--prism-noise), var(--swatch);   /* свотч = grainy-ГРАДИЕНТ палитры */
    background-size: 64px 64px, cover;
    background-blend-mode: overlay, normal;
    border: none;
    cursor: pointer;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform var(--transition), box-shadow var(--transition);
}
@media (hover: hover) {
    .profile-accent-swatch:hover { transform: scale(1.1); }
}
.profile-accent-swatch.is-active {
    /* кольцо градиентом не сделать (box-shadow ждёт цвет) → нейтральное контрастное;
       внутренний зазор = цвет карточки контролов (--bg-elevated). */
    box-shadow: none;
}
.profile-accent-check {
    color: var(--primary-text);
    font-size: var(--text-sm);
    line-height: var(--leading-none);
}

/* ══════════════════════════════════════════════
   РАЗДЕЛ «СТИЛИ»: живое превью + компактные контролы
   ══════════════════════════════════════════════ */
/* Превью собрано из БОЕВЫХ токенов (радиусы, стекло + блюр, акцентный грейни-
   градиент, текст-шкала), поэтому тема/акцент/скругление/шрифт/перф применяются
   к нему вживую сами — вся настройка каскадит с атрибутов и scale-множителей html. */
.style-preview {
    position: relative;
    height: 160px;
    margin-bottom: 1rem;
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    box-shadow: var(--shadow-glass);
    isolation: isolate;
}
/* Обои под стеклом = настоящий фон приложения (_background_svg.html): тёмный
   --bg-app + нейтральный ватермарк SKYNY + мягкое серое свечение. Блюру композера
   есть что размывать, а превью читается как реальная страница. */
.style-preview__wall {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    background-color: var(--bg-app);
}
/* Переиспользованный .bg-svg внутри превью: снимаем боевой position:fixed (он
   привязал бы фон к вьюпорту, а не к рамке превью) — держим в границах обоев. */
.style-preview .bg-svg {
    position: absolute;
}
.style-preview__msgs {
    position: relative;
    z-index: 1;
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.4rem;
}
.style-preview__bubble {
    max-width: 76%;
    padding: 0.5rem 0.75rem;
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    border-radius: var(--chat-radius);
    corner-shape: var(--corner-shape-surface);
}
.style-preview__bubble--in {
    align-self: flex-start;
    background: var(--bg-elevated);
    color: var(--text-main);
    border-bottom-left-radius: var(--radius-chat-tail);
}
.style-preview__bubble--out {
    align-self: flex-end;
    color: var(--primary-text);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 110px 110px, cover;
    background-blend-mode: overlay, normal;
    border-bottom-right-radius: var(--radius-chat-tail);
}
.style-preview__composer {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.35rem 0.35rem 0.85rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    box-shadow: var(--shadow-glass);
}
.style-preview__field {
    flex: 1;
    font-size: var(--text-xs);
    color: var(--text-subtle);
}
.style-preview__send {
    flex-shrink: 0;
    width: 1.75rem;
    height: 1.75rem;
    display: grid;
    place-items: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    color: var(--primary-text);
    font-size: var(--text-base);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 90px 90px, cover;
    background-blend-mode: overlay, normal;
}

/* Единая карточка контролов «Стилей»: та же поверхность и разделители рядов, что
   у карточек вкладки «Общее» (--bg-elevated + --shadow-surface + --radius-lg,
   inset -1px --bg-raised). Полная ширина панели — как остальные карточки профиля
   (не узкая «мобильная» колонка). */
.profile-styles {
    display: flex;
    flex-direction: column;
    background: var(--bg-elevated);
    box-shadow: var(--shadow-surface);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
}
.profile-styles__group {
    padding: 0.9rem 1.25rem;
    box-shadow: none;
}
/* Нижний разделитель гасим только у последней КАРТОЧКИ (перф-режим). Группы
   внутри парных рядов — не прямые последние дети .profile-styles, свои
   разделители держат. */
.profile-styles > .profile-styles__group:last-child { box-shadow: none; }

/* Парный ряд контролов: на узких — вертикальный стек (каждая группа держит свой
   горизонтальный разделитель, вид как раньше); на широком профиле (≥1180px, где
   .profile-page раскрывается до 56rem) — две равные колонки в одну линию с
   вертикальным разделителем между половинами. */
.profile-styles__row {
    display: flex;
    flex-direction: column;
}
@media (min-width: 1180px) {
    .profile-styles__row {
        flex-direction: row;
        align-items: stretch;
    }
    .profile-styles__row > .profile-styles__group {
        flex: 1 1 0;
        min-width: 0;
    }
    /* Левая половина: свой нижний разделитель (общий низ ряда) + правый (между
       колонками). Правая половина нижний держит из базового правила. */
    .profile-styles__row > .profile-styles__group:first-child {
        box-shadow: none;
    }
}
/* Заголовок ряда = компактная метка настройки (не крупный заголовок панели). */
.profile-styles__group .profile-section-title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    margin-bottom: 0.7rem;
}
/* Ряд «метка слева — контрол справа» (тема, акцент). */
.profile-styles__group--inline {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}
.profile-styles__group--inline .profile-section-title {
    margin-bottom: 0;
    white-space: nowrap;
}
/* Шапка ряда со слайдером/тумблером: метка + значение/тумблер в одну строку. */
.profile-styles__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    min-height: 1.5rem;
    margin-bottom: 0.7rem;
}
.profile-styles__head .profile-section-title {
    margin-bottom: 0;
}
.profile-styles__scale-labels {
    display: flex;
    justify-content: space-between;
    margin-top: 0.45rem;
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    color: var(--text-subtle);
}
.profile-styles__hint {
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    color: var(--text-muted);
    opacity: 0.7;
}

/* Токеновый тумблер профиля (knob = --surface-paper). Пилюльный трек не
   зависит от --radius-scale (капсула), knob — круг. */
.profile-toggle {
    position: relative;
    flex-shrink: 0;
    width: 2.75rem;
    height: 1.5rem;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-input);
    cursor: pointer;
    transition: background var(--transition);
}
.profile-toggle.is-on {
    background: var(--primary-500);
}
.profile-toggle__knob {
    position: absolute;
    top: 0.125rem;
    left: 0.125rem;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-paper);
    box-shadow: var(--shadow-glass);
    transition: transform var(--transition);
}
.profile-toggle.is-on .profile-toggle__knob {
    transform: translateX(1.25rem);
}

/* ══════════════════════════════════════════════
   PROMPT LIBRARY MODAL (Assistants / Presets)
   ══════════════════════════════════════════════ */
/* Sidebar */
.prompt-library-sidebar {
    border-right: 0;
}
.prompt-library-tag {
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    color: var(--text-muted);
    transition: background var(--transition), color var(--transition);
    cursor: pointer;
}
@media (hover: hover) {
    .prompt-library-tag:hover {
        background: var(--bg-elevated);
        color: var(--text-main);
    }
}
.prompt-library-tag-active {
    background: var(--surface-soft);
    color: var(--text-main);
}

/* Selected chat assistant. */
.prompt-library-card-active {
    background: var(--bg-raised);
}

/* ── Utility: mono text ── */
.profile-mono {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
}

/* ── Referral hint ── */
.profile-ref-hint {
    font-size: var(--text-sm);
    color: var(--text-muted);
}

/* ── Analytics header title resets margin ── */
.profile-analytics-header .profile-section-title {
    margin: 0;
}

/* ── History meta icons ── */
.profile-history-meta-item i {
    font-size: var(--text-2xs);
}

/* ── Промокод: минималистичный центрированный ввод (крупный текст + кнопка) ── */
.profile-panel--promo.is-active {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 50vh;
}
.promo-claim {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.75rem;
    width: 100%;
}
.promo-claim__input {
    width: 100%;
    border: none;
    background: transparent;
    text-align: center;
    font-family: var(--font-display);
    font-weight: var(--font-weight-display);
    /* Нижняя граница 1.5rem (не 2rem): длинный placeholder «Введите промокод»
       у однострочного input не переносится и на узких экранах вылезал за вьюпорт. */
    font-size: clamp(var(--text-2xl), calc(7vw * var(--font-scale)), var(--text-6xl));
    line-height: var(--leading-display);
    color: var(--text-main);
    padding: 0;
    max-width: 100%;
}
.promo-claim__input::placeholder { color: var(--text-muted); opacity: 1; }
.promo-claim__input:focus { outline: none; }
/* Кнопка всегда в потоке (резервирует место) — при вводе блок не «прыгает»;
   до ввода просто скрыта по прозрачности. */
.promo-claim__btn { transition: opacity var(--transition); }
.promo-claim__btn.is-empty { opacity: 0; pointer-events: none; }

/* ── Mobile ── */
@media (max-width: 480px) {
    .profile-tabs { gap: 0.2rem; --seg-gap: 0.24rem; }
    .shell-tabs { gap: 0.2rem; }
    .profile-tab,
    .shell-tab { padding: 0.52rem 0.98rem; font-size: var(--text-base); }
    .profile-header { gap: 0.75rem; }
    .profile-balance-layout { gap: 0.75rem; }
    .profile-balance-summary-card,
    .profile-balance-wallet-card { padding: 1rem; }
    .profile-topup-btn { width: 100%; }
    .profile-secondary-btn { width: 100%; }
    .profile-balance-plan-name { font-size: var(--text-title); }
    .profile-balance-amount { font-size: var(--text-metric); }
    :root { --shell-mobile-gutter: max(0.625rem, var(--safe-area-inline)); }
    .shell-mobile-header-host {
        padding-block-start: calc(var(--app-safe-top) + 0.45rem);
        /* Разбег под табами даёт не padding (он бы раздул высоту = offset контента),
           а хвост ::before/::after ниже коробки (см. базовое правило). Высоту хоста
           держим минимальной. */
        padding-block-end: 0.45rem;
    }
}

/* ══════════════════════════════════════════════════════════════
    PRICES PAGE — pricing-focused layout
    ══════════════════════════════════════════════════════════════ */
.subscription-showcase,
.subscription-reference-layout,
.subscription-plan-grid {
    display: grid;
    gap: 0.6rem;
}

.subscription-showcase-main,
.subscription-account-card,
.subscription-plan-card,
.prices-calculator-card,
.subscription-reference-card,
.prices-group-card,
.subscription-faq-item {
    position: relative;
    overflow: hidden;
}

.subscription-showcase {
    grid-template-columns: 1fr;
}

.subscription-showcase-main {
    padding: clamp(0.9rem, 1.5vw, 1.15rem);
    border-radius: var(--radius-2xl);
    corner-shape: var(--corner-shape-surface);
    background:
        radial-gradient(circle at top right, color-mix(in srgb, var(--primary-500) 14%, transparent) 0%, transparent 34%),
        linear-gradient(180deg, color-mix(in srgb, var(--bg-elevated) 97%, var(--primary-10)) 0%, color-mix(in srgb, var(--bg-elevated) 100%, var(--bg-panel)) 100%);
    box-shadow: 0 22px 46px -40px color-mix(in srgb, var(--primary-500) 28%, transparent), var(--shadow-surface);
}

.subscription-showcase-main::before {
    content: "";
    position: absolute;
    inset: auto -10% -30% 45%;
    height: 16rem;
    background: radial-gradient(circle, color-mix(in srgb, var(--primary-500) 16%, transparent) 0%, transparent 70%);
}

.subscription-showcase-head,
.subscription-section-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.55rem;
}

.subscription-showcase-kicker,
.subscription-section-kicker,
.subscription-reference-card__eyebrow,
.subscription-account-card__eyebrow,
.subscription-path-card__eyebrow {
    display: inline-flex;
    align-items: center;
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: var(--tracking-eyebrow);
    color: var(--text-subtle);
}

.subscription-status-pill,
.subscription-account-card__pill,
.subscription-plan-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    padding: 0.28rem 0.58rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    white-space: nowrap;
}

.subscription-status-pill.is-active,
/* Статус-пилюли — НЕЙТРАЛЬНЫЕ (не красим акцентом-«пурпуром»): «активно» = плотная серая
   поверхность, «без тарифа/free» = тихая полупрозрачная серая. Акцент бережём для CTA. */
.subscription-account-card__pill.is-active {
    background: var(--bg-raised);
    color: var(--text-main);
}
/* «Рекомендуем» — намеренный маркетинговый хайлайт, оставляем акцентным. */
.subscription-plan-badge.is-recommended {
    background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal;
    color: var(--primary-text);
}

.subscription-status-pill.is-free,
.subscription-account-card__pill.is-free,
.subscription-plan-badge.is-free {
    background: var(--surface-soft);
    color: var(--text-muted);
}

.subscription-status-pill.is-inactive,
.subscription-account-card__pill.is-inactive {
    background: color-mix(in srgb, var(--bg-panel) 46%, var(--bg-elevated));
    color: var(--text-muted);
}

.subscription-plan-badge.is-current {
    background: var(--surface-soft);
    color: var(--text-main);
}

.subscription-showcase-title {
    position: relative;
    z-index: 1;
    max-width: 9ch;
    margin-top: 0.55rem;
    font-family: var(--font-display);
    font-size: var(--text-title);
    line-height: var(--leading-none);
    color: var(--text-main);
}

.subscription-showcase-copy {
    position: relative;
    z-index: 1;
    max-width: 34rem;
    margin-top: 0.55rem;
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: color-mix(in srgb, var(--text-muted) 92%, var(--text-main));
}

.subscription-path-grid {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
    margin-top: 0.85rem;
}

.subscription-path-card {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    min-height: 13.75rem;
    padding: 0.8rem;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    background: color-mix(in srgb, var(--bg-panel) 46%, var(--bg-elevated));
    box-shadow: none;
}

.subscription-path-card.is-primary {
    background: linear-gradient(180deg, color-mix(in srgb, var(--bg-elevated) 92%, var(--primary-14)) 0%, color-mix(in srgb, var(--bg-elevated) 98%, var(--primary-10)) 100%);
    box-shadow: 0 20px 40px -36px color-mix(in srgb, var(--primary-500) 24%, transparent);
}

.subscription-path-card__title {
    font-family: var(--font-display);
    font-size: var(--text-card);
    line-height: var(--leading-none);
    color: var(--text-main);
}

.subscription-path-card__copy {
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--text-muted);
}

.subscription-path-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: auto;
}

.subscription-path-card__chip,
.subscription-plan-offer-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.28rem 0.58rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: color-mix(in srgb, var(--bg-panel) 40%, var(--bg-elevated));
    color: var(--text-main);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-semibold);
}

.subscription-path-card__action {
    align-self: flex-start;
    margin-top: 0.45rem;
}

.subscription-showcase-side {
    display: grid;
    gap: 0.6rem;
}

.subscription-account-card,
.subscription-plan-card,
.prices-calculator-card,
.subscription-reference-card,
.prices-group-card,
.subscription-faq-item {
    background: linear-gradient(180deg, color-mix(in srgb, var(--bg-elevated) 97%, var(--primary-10)) 0%, var(--bg-elevated) 100%);
    box-shadow: 0 18px 36px -34px color-mix(in srgb, var(--text-main) 20%, transparent), var(--shadow-surface);
}

.subscription-account-card,
.subscription-plan-card,
.prices-calculator-card,
.subscription-reference-card {
    padding: 0.8rem;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
}

.subscription-account-card h2 {
    font-family: var(--font-display);
    font-size: var(--text-section);
    line-height: var(--leading-none);
    color: var(--text-main);
}

.subscription-account-card__grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.45rem;
    margin-top: 0.65rem;
}

.subscription-account-card__metric {
    padding: 0.55rem 0.65rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: color-mix(in srgb, var(--bg-panel) 36%, transparent);
}

.subscription-account-card__metric span {
    display: block;
    margin-bottom: 0.35rem;
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    color: var(--text-subtle);
}

.subscription-account-card__metric strong {
    font-size: var(--text-sm);
    color: var(--text-main);
    line-height: var(--leading-snug);
}

.subscription-account-card__note,
.subscription-plan-copy,
.subscription-plan-footnote,
.subscription-reference-card__header p,
.subscription-reference-point span,
.subscription-section-copy,
.subscription-faq-content {
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    color: var(--text-muted);
}

.subscription-account-card__note {
    margin-top: 0.6rem;
}

.subscription-reference-card__header h3 {
    margin-top: 0.35rem;
    color: var(--text-main);
    font-family: var(--font-display);
    font-size: var(--text-card);
    line-height: var(--leading-none);
    margin-bottom: 0.35rem;
}

.subscription-section-head {
    margin-bottom: 0.7rem;
}

.subscription-section-title {
    font-family: var(--font-display);
    font-weight: var(--font-weight-display);
    color: var(--text-main);
}

.subscription-section-head--plans {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    text-align: center;
    margin-bottom: 0.85rem;
}

.subscription-section-title--plans {
    font-size: var(--text-title);
    line-height: var(--leading-none);
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    max-width: none;
}

.subscription-section-copy {
    max-width: 32rem;
}

.subscription-section-copy--plans {
    max-width: 42rem;
    margin: 0 auto;
    font-size: var(--text-base);
    line-height: var(--leading-normal);
}

.subscription-period-shell {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.7rem;
    margin-top: 0.75rem;
    padding: 0.65rem 0.75rem;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    background: color-mix(in srgb, var(--bg-panel) 36%, var(--bg-elevated));
    box-shadow: none;
}

.subscription-period-shell--plans {
    width: 100%;
    max-width: 31rem;
    margin: 0 auto 1rem;
    padding: 0;
    justify-content: center;
    background: transparent;
    box-shadow: none;
}

.subscription-period-toolbar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.7rem;
    flex-direction: column;
    width: 100%;
}

.subscription-period-switcher {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding-left: 2.2rem;
}

.subscription-period-toggle {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--gap-2xs);
    padding: var(--gap-xs);
    /* Капсульный сегментбар (эталон): pill-трей + pill-сегменты, активный
       --surface-strong. Трей — recessed --bg-input на сплошной странице. */
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-input);
    min-width: min(100%, 25rem);
}

.subscription-period-toggle__btn {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 10rem;
    padding: 0.95rem 1.55rem;
    border: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-control);
    font-weight: var(--font-weight-bold);
    letter-spacing: var(--tracking-tight);
    white-space: nowrap;
    transition: background-color var(--transition), color var(--transition), transform var(--transition-fast), box-shadow var(--transition);
}

@media (hover: hover) {
    .subscription-period-toggle__btn:hover {
        transform: translateY(-1px);
    }
}

.subscription-period-toggle__btn.is-active {
    background: var(--surface-strong);
    color: var(--text-main);
}

.subscription-period-discount {
    position: absolute;
    left: 0;
    top: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 5.75rem;
    padding: 0.7rem 0.95rem;
    border-radius: max(0px, calc(var(--radius-lg) - 0.5rem));
    corner-shape: var(--corner-shape-surface);
    background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal;
    color: var(--primary-text);
    font-size: var(--text-caption);
    font-weight: var(--font-weight-bold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    transform: translate(-10%, -52%) rotate(-13deg);
    box-shadow: 0 18px 28px -20px color-mix(in srgb, var(--primary-500) 70%, transparent);
}

.subscription-plan-grid {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
}

.subscription-plan-card {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    position: relative;
    overflow: hidden;
}

.subscription-plan-card.is-featured {
    background: linear-gradient(180deg, color-mix(in srgb, var(--bg-elevated) 88%, var(--primary-18)) 0%, color-mix(in srgb, var(--bg-elevated) 94%, var(--primary-10)) 56%, color-mix(in srgb, var(--bg-elevated) 98%, var(--primary-10)) 100%);
    box-shadow: 0 28px 58px -42px color-mix(in srgb, var(--primary-500) 38%, transparent), var(--shadow-surface);
    transform: translateY(-0.16rem);
}

.subscription-plan-card.is-featured .subscription-plan-kicker {
    color: color-mix(in srgb, var(--primary-600) 72%, var(--text-main));
}

.subscription-plan-card.is-featured .subscription-plan-slider {
    background: var(--surface-soft);
    box-shadow: 0 20px 38px -34px color-mix(in srgb, var(--primary-500) 34%, transparent);
}

.subscription-plan-card.is-featured .subscription-plan-slider__value {
    color: color-mix(in srgb, var(--primary-600) 68%, var(--text-main));
}

.subscription-plan-card.is-featured .subscription-plan-slider__mark.is-active {
    color: color-mix(in srgb, var(--primary-600) 82%, var(--text-main));
}

.subscription-plan-card.is-current {
    box-shadow: 0 18px 40px -34px color-mix(in srgb, var(--text-main) 20%, transparent), var(--shadow-surface);
}

.subscription-plan-card.is-free {
    background: linear-gradient(180deg, color-mix(in srgb, var(--bg-elevated) 98%, var(--bg-panel)) 0%, var(--bg-elevated) 100%);
}

.subscription-plan-badges {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.35rem;
}

.subscription-plan-kicker {
    margin-bottom: 0.2rem;
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    color: var(--text-subtle);
}

.subscription-plan-title {
    font-family: var(--font-display);
    font-size: var(--text-card);
    line-height: var(--leading-none);
    color: var(--text-main);
}

.subscription-plan-price {
    font-family: var(--font-display);
    font-size: var(--text-metric);
    line-height: var(--leading-none);
    color: var(--text-main);
}

.subscription-plan-price-line {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.15rem;
    /* Перечёркнутая старая цена — ОТДЕЛЬНОЙ строкой под текущей ценой. Стабильно при
       смене суммы (карточка не «прыгает») и не обрезает длинные годовые суммы. */
}

.subscription-plan-price-current {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
}

.subscription-plan-price-current span,
.subscription-plan-price > span {
    display: inline-block;
    margin-top: 0;
    font-family: var(--font-sans);
    font-size: var(--text-xs);
    color: var(--text-muted);
}

.subscription-plan-price-old {
    display: inline-block;
    font-family: var(--font-sans);
    font-size: var(--text-card);
    font-weight: var(--font-weight-display);
    line-height: var(--leading-none);
    color: var(--text-subtle);
    text-decoration: line-through;
    text-decoration-thickness: 0.08em;
    text-decoration-color: color-mix(in srgb, var(--text-subtle) 72%, transparent);
}

.subscription-plan-slider {
    display: grid;
    gap: 0.65rem;
    padding: 0.75rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: linear-gradient(180deg, color-mix(in srgb, var(--bg-panel) 32%, var(--bg-elevated)) 0%, color-mix(in srgb, var(--bg-panel) 18%, transparent) 100%);
    box-shadow: none;
}

.subscription-plan-slider__top {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 0.65rem;
}

.subscription-plan-slider__eyebrow {
    display: inline-flex;
    align-items: center;
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    color: var(--text-subtle);
}

.subscription-plan-slider__hint {
    margin-top: 0.18rem;
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    color: var(--text-muted);
    max-width: 18rem;
}

.subscription-plan-slider__value {
    font-family: var(--font-display);
    font-size: var(--text-card);
    line-height: var(--leading-none);
    color: var(--text-main);
    text-align: right;
    white-space: nowrap;
}

.subscription-plan-slider__value span {
    font-family: var(--font-sans);
    font-size: var(--text-xs);
    color: var(--text-muted);
}

.subscription-plan-slider__marks {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 0.25rem;
}

.subscription-plan-slider__mark {
    border: 0;
    padding: 0;
    background: transparent;
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-semibold);
    color: var(--text-subtle);
    text-align: center;
    cursor: pointer;
    transition: color var(--transition-fast), transform var(--transition-fast);
}

@media (hover: hover) {
    .subscription-plan-slider__mark:hover,
    .subscription-plan-slider__mark.is-active {
        color: var(--text-main);
    }
}

@media (hover: hover) {
    .subscription-plan-slider__mark:hover {
        transform: translateY(-1px);
    }
}

.subscription-plan-offer-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-top: -0.05rem;
}

.subscription-plan-rate-note {
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    color: var(--text-muted);
}

.subscription-plan-offer-chip {
    background: var(--surface-soft);
    color: var(--text-main);
}

.subscription-plan-metrics,
.subscription-reference-points {
    display: grid;
    gap: 0.45rem;
}

.subscription-plan-metrics {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.subscription-plan-metric,
.subscription-reference-point {
    padding: 0.6rem 0.7rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: color-mix(in srgb, var(--bg-panel) 34%, transparent);
}

.subscription-plan-metric {
    display: block;
    gap: 0;
    font-size: var(--text-2xs);
    color: var(--text-muted);
}

.subscription-plan-metric span {
    display: block;
    margin-bottom: 0.18rem;
}

.subscription-plan-metric strong,
.subscription-reference-point strong {
    color: var(--text-main);
    font-weight: var(--font-weight-semibold);
    font-size: var(--text-sm);
}

.subscription-plan-features {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.45rem;
}

.subscription-plan-features li {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    color: var(--text-muted);
}

.subscription-plan-features i {
    margin-top: 0.05rem;
    color: var(--text-muted);
}

.subscription-reference-layout {
    grid-template-columns: 1fr;
}

.prices-calculator-card,
.subscription-reference-card {
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
}

.subscription-reference-card__header {
    margin-bottom: 0.8rem;
}

.prices-calc-inner {
    background: color-mix(in srgb, var(--bg-panel) 42%, var(--bg-raised));
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    padding: 0.85rem;
}

.prices-calculator-card {
    margin-bottom: 0;
}

.subscription-models-stack {
    display: grid;
    /* Keep wide price tables inside their own horizontal scrollers. */
    grid-template-columns: minmax(0, 1fr);
    gap: 0.5rem;
}

.subscription-faq-section {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
}

.subscription-faq-header {
    max-width: 48rem;
}

.subscription-faq-list {
    display: grid;
    gap: 0.5rem;
}

.subscription-faq-summary {
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.8rem;
    padding: 0.8rem 0.9rem;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}

.subscription-faq-summary::-webkit-details-marker {
    display: none;
}

@media (hover: hover) {
    .subscription-faq-summary:hover {
        background: var(--bg-hover);
    }
}

.subscription-faq-question {
    font-size: var(--text-base);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    line-height: var(--leading-snug);
}

.subscription-faq-toggle {
    width: 2rem;
    height: 2rem;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: color-mix(in srgb, var(--bg-panel) 38%, var(--bg-elevated));
    color: var(--text-main);
}

.subscription-faq-icon-minus {
    display: none;
}

.subscription-faq-item[open] .subscription-faq-toggle {
    background: var(--surface-soft);
    color: var(--text-main);
}

.subscription-faq-item[open] .subscription-faq-summary {
    background: color-mix(in srgb, var(--bg-panel) 18%, var(--bg-elevated));
}

.subscription-faq-item[open] .subscription-faq-icon-plus {
    display: none;
}

.subscription-faq-item[open] .subscription-faq-icon-minus {
    display: inline-block;
}

.subscription-faq-content {
    padding: 0 0.9rem 0.85rem;
}

.subscription-faq-content p + p {
    margin-top: 0.6rem;
}

.prices-group-card {
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
}

.prices-group-header {
    display: flex;
    align-items: center;
    gap: var(--gap-sm);
    padding: 0.7rem 0.95rem;
    background: color-mix(in srgb, var(--bg-panel) 40%, transparent);
}

.prices-group-header h2 {
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

@media (min-width: 980px) {
    .subscription-showcase {
        grid-template-columns: minmax(18rem, 0.82fr) minmax(0, 1.2fr);
    }

    .subscription-showcase-side {
        order: 1;
    }

    .subscription-showcase-main {
        order: 2;
    }

    .subscription-reference-layout {
        grid-template-columns: minmax(0, 1.15fr) minmax(18rem, 0.85fr);
    }
}

@media (min-width: 1280px) {
    .subscription-plan-grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

@media (max-width: 760px) {
    .subscription-path-grid {
        grid-template-columns: 1fr;
    }

    .subscription-period-shell {
        flex-direction: column;
        align-items: flex-start;
    }

    .subscription-period-shell--plans {
        align-items: stretch;
        padding: 0;
    }

    .subscription-period-toolbar {
        align-items: center;
        gap: 0.65rem;
    }

    .subscription-period-switcher {
        width: min(100%, 24rem);
        padding: 1.25rem 0 0;
    }

    .subscription-period-toggle {
        width: 100%;
        min-width: 0;
    }

    .subscription-period-discount {
        /* Над кнопкой «Год» (годовой = со скидкой), ближе к левому краю — чтобы было
           понятно, к чему относится скидка (а не по центру над обеими кнопками). */
        left: 0;
        top: 0;
        transform: translate(-4%, -30%) rotate(-10deg);
    }

    .subscription-section-head,
    .subscription-showcase-head,
    .subscription-account-card__top,
    .subscription-plan-top {
        flex-direction: column;
        align-items: flex-start;
    }

    .subscription-section-head--plans {
        align-items: center;
    }

    .subscription-plan-badges {
        justify-content: flex-start;
    }

    .subscription-section-copy--plans {
        font-size: var(--text-sm);
    }
}

@media (max-width: 640px) {
    .subscription-showcase-main,
    .subscription-account-card,
    .subscription-path-card,
    .subscription-plan-card,
    .prices-calculator-card,
    .subscription-reference-card,
    .prices-group-card,
    .subscription-faq-item {
        border-radius: var(--radius-lg);
        corner-shape: var(--corner-shape-surface);
    }

    .subscription-account-card,
    .subscription-path-card,
    .subscription-plan-card,
    .prices-calculator-card,
    .subscription-reference-card,
    .subscription-showcase-main {
        padding: 0.95rem;
    }

    .subscription-showcase-title {
        max-width: none;
        font-size: var(--text-title);
    }

    .subscription-section-title--plans {
        font-size: var(--text-title);
    }

    .subscription-period-switcher {
        width: 100%;
    }

    .subscription-period-toggle__btn {
        min-width: 0;
        padding: 0.9rem 1rem;
        font-size: var(--text-control);
    }

    .subscription-period-discount {
        min-width: 5rem;
        padding: 0.6rem 0.8rem;
        font-size: var(--text-caption);
    }

    .subscription-plan-slider {
        padding: 0.7rem;
    }

    .subscription-plan-slider__top {
        flex-direction: column;
        align-items: flex-start;
    }

    .subscription-plan-slider__value {
        text-align: left;
    }

    .subscription-account-card__grid {
        grid-template-columns: 1fr;
    }

    .subscription-plan-metrics {
        grid-template-columns: 1fr;
    }

    .subscription-path-card {
        min-height: auto;
    }

    .subscription-path-card__action {
        align-self: stretch;
    }

    .subscription-faq-summary {
        padding: 0.9rem;
        gap: 0.75rem;
    }

    .subscription-faq-question {
        font-size: var(--text-base);
    }

    .subscription-faq-toggle {
        width: 2.15rem;
        height: 2.15rem;
    }

    .subscription-faq-content {
        padding: 0 0.9rem 0.9rem;
    }
}
.prices-group-icon {
    width: 1rem;
    height: 1rem;
    flex-shrink: 0;
    overflow: hidden;
    color: var(--text-subtle);
}
.prices-group-icon svg {
    display: block;
    width: 100%;
    height: 100%;
}

/* ── Column headers ── */
.prices-thead th {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    font-weight: var(--font-weight-medium);
    padding: 0.45rem 1.25rem;
    box-shadow: none;
}
.prices-thead th:not(:first-child) { text-align: right; white-space: nowrap; }

/* ── Data rows — identical to .profile-history-item ── */
.prices-table-row {
    box-shadow: none;
    transition: background var(--transition);
}
.prices-table-row:last-child { box-shadow: none; }
@media (hover: hover) {
    .prices-table-row:hover { background: var(--bg-hover); }
}
.prices-table-row td {
    padding: 0.75rem 1.25rem;
    font-size: var(--text-sm);
    color: var(--text-main);
}
.prices-table-row td:not(:first-child) { text-align: right; white-space: nowrap; }

/* ========================================
   ASSISTANTS PAGE
   ======================================== */

/* ── Card ── */
.assistant-card {
    background: var(--surface-soft);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    padding: 1rem;
    cursor: pointer;
    transition: background var(--transition), box-shadow var(--transition);
}
@media (hover: hover) {
    .assistant-card:hover {
        background: var(--surface-active);
        box-shadow: var(--shadow-icon);
    }
}

/* ── Handle badge (static) ── */
.handle-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.1rem 0.45rem;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-medium);
    color: var(--text-subtle);
    background: var(--bg-raised);
    white-space: nowrap;
    line-height: var(--leading-snug);
}

/* ── Icon circle ── */
.assistant-icon {
    width: 3.5rem;
    height: 3.5rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-elevated);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

/* ── Tag piills ── */
.assistant-tag {
    display: inline-flex;
    align-items: center;
    padding: 0.125rem 0.5rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-medium);
    color: var(--text-muted);
    background: var(--bg-raised);
}

/* ── Capability badge (иконка + подпись встроенных режимов) ── */
.assistant-cap-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.4375rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-medium);
    color: var(--text-muted);
    background: var(--bg-raised);
    white-space: nowrap;
    line-height: var(--leading-tight);
}
.assistant-cap-badge .ti {
    font-size: var(--text-xs);
}

/* ── Mention Dropdown ── */
/* Потолок высоты и скролл наследуются от .dropdown-menu — как у всех меню. */
.mention-dropdown {
    padding: 0.25rem;
}

.mention-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    padding: 1rem 0.75rem;
    color: var(--text-muted);
    text-align: center;
}
.mention-empty-icon {
    font-size: var(--text-3xl);
    line-height: var(--leading-none);
    opacity: 0.7;
}
.mention-empty-text {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
}

/* ========================================
   MODAL UTILITY CLASSES (camera-angle, etc.)
   ======================================== */
.modal-fullscreen-bg {
    background: var(--bg-app);
    z-index: var(--z-dialog-above-overlay);
}

.modal-blurred-backdrop {
    opacity: 0.15;
}

.camera-modal-backdrop {
    opacity: 0.4;
}

.modal-image-rounded {
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-modal);
}

/* ── Modal header (unified) ── */
.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
}

/* Fullscreen-модалки (камера «Углы», переосвещение) монтируются ВНЕ .app-root,
   поэтому --app-safe-top там не резолвится — берём сырой env() (как .media-viewer).
   Без этого верхние контролы уходят под чёлку, нижние кнопки — под home-indicator.
   env=0 вне iOS → прежние отступы (1.25rem/1.5rem = снятые pt-5/pb-6/pb-5). */
.modal-fullscreen-bg > .modal-header,
.modal-controls-panel > .modal-header {
    padding-top: calc(1.25rem + env(safe-area-inset-top));
}

.modal-fullscreen-footer {
    padding-bottom: calc(1.5rem + var(--safe-area-bottom, 0px));
}

.modal-controls-panel > .modal-fullscreen-footer {
    padding-bottom: calc(1.25rem + var(--safe-area-bottom, 0px));
}

/* Form actions sit against the drawer edge, outside its scrolling fields. */
.modal-form-layout {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    margin: 0;
}
.modal-form-footer {
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
    gap: var(--gap-sm);
    padding: var(--gap-sm);
}
.modal-form-footer .btn {
    width: 100%;
    min-height: calc(var(--gap-sm) * 6);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
}

.modal-header-title {
    font-family: var(--font-display);
    font-size: var(--text-dialog);
    font-weight: var(--font-weight-display);
    color: var(--text-main);
}

.modal-header-close {
    width: 2rem;
    height: 2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    font-size: var(--text-lg);
    line-height: var(--leading-none);
    transition: background var(--transition), color var(--transition);
}
@media (hover: hover) {
    .modal-header-close:hover {
        background: var(--bg-hover);
        color: var(--text-main);
    }
}

/* Group settings use the same spacing, surfaces and controls as the composer. */
.chat-access-panel { --access-control-size: var(--composer-control-size); width: min(100%, calc(var(--gap-sm) * 58)); max-width: calc(var(--gap-sm) * 58); }
.chat-access-header { align-items: center; padding: calc(var(--gap-sm) * 3) calc(var(--gap-sm) * 3) calc(var(--gap-sm) * 2); }
.chat-access-header .modal-header-title { font-size: var(--text-lg); line-height: var(--leading-tight); }
.chat-access-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: var(--scroll-edge-size) calc(var(--gap-sm) * 3) calc(var(--gap-sm) * 3); }
#chat-access-modal .chat-access-panel:focus { outline: none; }
.chat-access-content { display: flex; flex-direction: column; gap: calc(var(--gap-sm) * 3); }
.chat-access-section { min-width: 0; }
.chat-access-section__head { display: flex; align-items: center; gap: var(--gap-sm); }
.chat-access-section__title { color: var(--text-main); font-size: var(--text-xs); font-weight: var(--font-weight-medium); line-height: var(--leading-snug); }
.chat-access-title-row, .chat-access-link-result { display: flex; align-items: center; gap: var(--gap-xs); margin-top: var(--gap-sm); min-width: 0; }
.chat-access-input {
    flex: 1 1 auto; min-width: 0; width: 100%; min-height: var(--access-control-size);
    padding: var(--gap-sm) calc(var(--gap-sm) * 1.5); border: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round); background: var(--surface-soft); color: var(--text-main); font-size: var(--text-sm);
}
.chat-access-input[readonly] { color: var(--text-muted); }
.chat-access-invite-controls { display: flex; flex-wrap: wrap; gap: var(--gap-sm); }
.chat-access-panel .chat-access-button {
    min-height: var(--access-control-size); padding: var(--gap-sm) calc(var(--gap-sm) * 2);
    border: 0; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); background: var(--surface-soft);
    color: var(--text-main); font-size: var(--text-sm); box-shadow: none;
}
.chat-access-invite-btn { flex: 1 1 auto; }
.chat-access-panel .chat-access-invite-reset-btn { background: transparent; color: var(--text-muted); padding-inline: var(--gap-sm); font-size: var(--text-xs); }
.chat-access-panel .chat-access-link-action { padding-inline: var(--gap-sm); font-size: var(--text-xs); }
.chat-access-start-btn { width: 100%; min-height: var(--access-control-size); margin-top: calc(var(--gap-sm) * 3); }
.chat-access-note { margin-top: var(--gap-sm); color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-relaxed); }
.chat-access-member-row { display: flex; align-items: center; gap: var(--gap-sm); min-width: 0; padding-block: var(--gap-sm); }
.chat-access-members { margin-top: var(--gap-sm); }
.chat-access-row-copy { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; gap: var(--gap-2xs); }
.chat-access-row-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-main); font-size: var(--text-sm); line-height: var(--leading-snug); }
.chat-access-row-meta, .chat-access-count { color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-snug); }
.chat-access-icon-btn {
    display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
    width: var(--access-control-size); height: var(--access-control-size); border-radius: var(--radius-round); corner-shape: var(--corner-shape-round);
    color: var(--text-muted); background: transparent; font-size: var(--text-lg);
    transition: background-color var(--transition-fast), color var(--transition-fast);
}
.chat-access-avatar { width: var(--access-control-size); height: var(--access-control-size); flex-shrink: 0; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round); object-fit: cover; }
.chat-access-avatar--fallback { display: grid; place-items: center; background: var(--surface-soft); color: var(--text-muted); font-size: var(--text-sm); text-transform: uppercase; }
.chat-access-choice-group { display: flex; gap: var(--gap-2xs); padding: var(--gap-2xs); margin-top: var(--gap-sm); border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); background: var(--surface-soft); }
.chat-access-choice {
    flex: 1 1 0; min-width: 0; min-height: var(--access-control-size); padding: var(--gap-sm);
    border-radius: max(0px, calc(var(--radius-pill) - var(--gap-2xs)));
    corner-shape: var(--corner-shape-round); color: var(--text-muted); font-size: var(--text-xs);
    transition: background-color var(--transition-fast), color var(--transition-fast);
}
.chat-access-choice.is-active { background: var(--surface-active); color: var(--text-main); }
.chat-access-exit { width: 100%; }
.chat-access-error { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-sm); padding-block: var(--gap-sm); color: var(--text-main); font-size: var(--text-sm); }
.chat-access-panel button:disabled { opacity: .5; cursor: wait; }
#chat-access-modal .chat-access-panel :is(button, input):focus { outline: none; box-shadow: none; }
.chat-access-panel .chat-access-input:focus,
.chat-access-panel button:focus-visible { background-color: var(--surface-strong); }
@media (hover: hover) {
    .chat-access-panel .chat-access-button:hover:not(:disabled),
    .chat-access-icon-btn:hover:not(:disabled) { color: var(--text-main); background: var(--surface-strong); }
}
@media (max-width: 639px) {
    .chat-access-panel { max-width: none; max-height: min(var(--drawer-max-h), 92dvh); }
    .chat-access-header { padding: calc(var(--gap-sm) * 2); }
    .chat-access-scroll { padding: 0 calc(var(--gap-sm) * 2) calc(var(--gap-sm) * 2); }
}

.modal-icon-xl {
    font-size: var(--text-xl);
    color: var(--text-main);
}

.modal-title-xl {
    font-family: var(--font-display);
    color: var(--text-main);
    font-weight: var(--font-weight-display);
    font-size: var(--text-xl);
}

.modal-close-btn-bg {
    color: var(--text-muted);
}
@media (hover: hover) {
    .modal-close-btn-bg:hover {
        background: var(--bg-raised);
    }
}

.modal-icon-sm {
    font-size: var(--text-sm);
}

.modal-icon-xs {
    font-size: var(--text-xs);
}

.modal-icon-lg {
    font-size: var(--text-lg);
}

.modal-label-subtle {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    font-weight: var(--font-weight-medium);
}

.modal-hint-subtle {
    font-size: var(--text-xs);
    color: var(--text-subtle);
}

.modal-hint-sm {
    font-size: var(--text-sm);
    color: var(--text-subtle);
}

/* Camera Angle Modal */
.camera-icon-box {
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
}

.camera-subtitle {
    color: var(--text-subtle);
    font-size: var(--text-xs);
    margin-top: 2px;
}

.camera-no-select {
    -webkit-user-select: none;
    user-select: none;
}

.camera-slider-label {
    font-size: var(--text-xs);
    color: var(--text-muted);
    font-weight: var(--font-weight-medium);
    letter-spacing: var(--tracking-wide);
}

/* Match chat entry typography, including its toolbar-aligned line box. */
.composer-text-input {
    font-size: var(--text-base);
    line-height: calc(var(--composer-control-size) - 1rem);
}
/* ComposerInputService owns measured height. Native field-sizing would also
   resize on placeholder changes and compete with the shared motion. */
[x-composer-input], [x-composer-input\.chat] { field-sizing: fixed; }
.composer-input-stack { transition: padding-bottom var(--transition); }
@media (prefers-reduced-motion: reduce) {
    .composer-input-stack { transition: none; }
}

/* ── Единый потолок авторастущих textarea композеров: ровно 7 текстовых строк
   (+ вертикальные padding'и поля), дальше — внутренний скролл. Иначе большой
   текст (вставка/черновик) растил пилюлю по-разному в разных сценариях и мог
   утащить её под шапку. lh-единица берёт живой line-height поля; первая строка
   каждого правила — px/rem-фолбэк для браузеров без lh. Кап высоты самой
   пилюли (--composer-cap-basis) остаётся страховкой для низких окон. ── */
textarea.chat-prompt-area {      /* One text row + py-2 matches the toolbar controls. */
    max-height: 184px;
    max-height: calc(7lh + 1rem);
}
.media-prompt-area {             /* Seven lines with py-1.5 padding. */
    max-height: 170px;
    max-height: calc(7lh + 0.75rem);
}

/* ===== TILE — переиспользуемая навигационная плитка =====
   Не привязана к главной: задумана для раскатки по проекту. Простая
   скруглённая форма, hairline-кольцо инсетом (без border — нет сдвига layout),
   ambient-засветка угла и иконка в круге со свечением акцента.
   Все цвета — токены: data-accent перекрашивает кольцо/свечение сам. */
.tile {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.7rem;
    padding: 1.25rem 1rem;
    background: var(--bg-elevated);
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    box-shadow: none;
    color: var(--text-main);
    text-decoration: none;
    text-align: center;
    overflow: hidden;
    transition: transform var(--transition-fast);
}

/* Ambient-засветка верхнего угла (как у featured-тарифа, но инсетом). */
.tile::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(110% 85% at 82% -12%, var(--primary-10), transparent 58%);
}

.tile__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3.4rem;
    height: 3.4rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-2xl);
    color: var(--primary-text);
    background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal;
    box-shadow: var(--glow-accent-soft);
    transition: box-shadow var(--transition);
}

.tile__label {
    font-family: var(--font-display);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-display);
    line-height: var(--leading-tight);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

.tile__sublabel {
    font-size: var(--text-xs);
    color: var(--text-subtle);
    line-height: var(--leading-snug);
}

.tile__badge {
    position: absolute;
    top: 0.65rem;
    right: 0.65rem;
    padding: 0.15rem 0.45rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal;
    color: var(--primary-text);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-bold);
    letter-spacing: var(--tracking-wide);
}

/* Квадратная плитка-инструмент (сетка 2x2 / 4x1). */
.tile--quick {
    aspect-ratio: 1 / 0.92;
}

@media (min-width: 768px) {
    /* Десктоп: компактные плитки в один ряд (5 колонок). Высота — по контенту,
       а не растянутый квадрат; меньше иконка/паддинг/гэп → карточки ниже. */
    .tile--quick {
        aspect-ratio: auto;
    }
    .tile--quick .tile__icon {
        width: 3rem;
        height: 3rem;
        font-size: var(--text-xl);
    }
}

@media (hover: hover) {
    .tile:hover {
        transform: translateY(-3px);
        color: var(--text-main);
    }
    .tile:hover .tile__icon {
        box-shadow: var(--glow-accent-strong);
    }
}

/* Тач-фидбек: лёгкое сжатие вместо hover-лифта. */
.tile:active {
    transform: scale(0.97);
    transition-duration: var(--motion-duration-micro);
}

/* ===== HOME HERO & QUICK ACCESS ===== */

.home-scroll {
    display: flex;
    flex-direction: column;
}

/* Shared mobile header tint follows the existing shell collapse state. */
@media (max-width: 767.98px) {
    .app-root .shell-mobile-header-host::after {
        opacity: var(--hm, 0);
    }
}

/* Home section primitives; editorial layouts are in home.css. */
.home-section {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

.home-section__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding-inline: var(--app-gutter-x);
}

/* Заголовки секций — uppercase-кикеры в языке плиток (.tile__label). */
.home-section__title {
    font-size: var(--text-base);
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    color: var(--text-main);
    margin: 0;
}

.home-section__more {
    flex-shrink: 0;
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
    color: var(--text-muted);
    text-decoration: none;
    transition: color var(--transition-fast);
}

.home-section__more:hover {
    color: var(--text-main);
}

/* Горизонтальный ряд со snap; боковые отступы = gutter. */
.home-section__rail {
    display: flex;
    gap: 0.75rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--app-gutter-x);
    padding-inline: var(--app-gutter-x);
    padding-bottom: 0.25rem;
}

.home-section__rail > * {
    scroll-snap-align: start;
    flex: 0 0 auto;
}

/* ── Карточка «Продолжить» ── */
.home-continue-card {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    width: 15rem;
    padding: 0.95rem 1.05rem;
    background: var(--bg-elevated);
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    box-shadow: none;
    color: var(--text-main);
    text-decoration: none;
    transition: transform var(--transition-fast), background-color var(--transition-fast);
}

.home-continue-card:hover {
    transform: translateY(-2px);
    background: var(--bg-raised);
}

/* Шапка: иконка модели + имя + capability-чипы («модель и её параметры»). */
.home-continue-card__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.home-continue-card__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    flex-shrink: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
    box-shadow: none;
    color: var(--primary-text);
    font-size: var(--text-lg);
}

.home-continue-card__logo {
    display: block;
    width: 1.1rem;
    height: 1.1rem;
}

.home-continue-card__model {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: var(--font-weight-semibold);
    font-size: var(--text-xs);
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.home-continue-card__chips {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    flex-shrink: 0;
}

.home-continue-card__chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-muted);
    font-size: var(--text-xs);
}

.home-continue-card__title {
    font-weight: var(--font-weight-semibold);
    font-size: var(--text-sm);
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.home-continue-card__preview {
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: var(--leading-snug);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ── Карточка ассистента ── */
.home-assistant-card {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    width: 13.5rem;
    padding: 1rem 1.1rem 1.15rem;
    background: var(--bg-elevated);
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    box-shadow: none;
    color: var(--text-main);
    text-decoration: none;
    transition: transform var(--transition-fast), background-color var(--transition-fast);
}

.home-assistant-card:hover {
    transform: translateY(-2px);
    background: var(--bg-raised);
}

.home-assistant-card__avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    overflow: hidden;
    background: var(--surface-soft);
    box-shadow: none;
    color: var(--primary-text);
    font-size: var(--text-xl);
}

.home-assistant-card__avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.home-assistant-card__name {
    font-weight: var(--font-weight-semibold);
    font-size: var(--text-sm);
    color: var(--text-main);
}

.home-assistant-card__desc {
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: var(--leading-snug);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ── Инструменты: сетка плиток (.tile--quick) ── */
.home-tools {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.85rem;
    padding-inline: var(--app-gutter-x);
}

@media (min-width: 768px) {
    .home-tools {
        grid-template-columns: repeat(5, 1fr);
    }
}

/* ── Морф мобильной шапки (scroll-linked, сегмент --hm 0→1) — УНИФИЦИРОВАНО для
   всех страниц с полной shell-шапкой (главная, медиа, чаты/сценарии/транскрипция
   в режиме списка). Прогресс пишет ShellHeaderService (см. [data-shell-scroll]).
   Финал — ОДИН консистентный ряд: меню-пилюля слева + кружок-аватар справа той же
   высоты. Хореография: табы поднимаются на строку брэнда (по центру пилюли
   профиля) и подбирают правый край, освобождая место аватару; брэнд растворяется
   ПОД приехавшим меню (табы выше по z); у пилюли схлопывается баланс (остаётся
   аватар) и она подрастает до высоты меню (transform scale). Шапка — absolute-
   оверлей: морф не трогает layout страницы. Глассовая подложка пилюли и «воздух»
   сверху — только на главной (пилюля лежит над hero-артом). */
@media (max-width: 767.98px) {
    /* Heights share numeric rem magnitudes. Dividing length by length makes
       grow (and every dependent radius, padding and transform) invalid in
       browsers without typed CSS arithmetic, even when --hm is zero. */
    .app-root {
        --shell-tabs-h-rem: 3.45;
        --shell-tabs-h: calc(var(--shell-tabs-h-rem) * 1rem);
        --shell-pill-grow: calc(var(--shell-tabs-h-rem) / var(--shell-header-slot-rem) - 1);
    }

    /* База отступа сверху (без --hm-терма) — оставляем 0.55rem, как было: это
       правило перебивает мобильный override (0.45rem), иначе шапка уедет вверх на
       1.6px. «Воздух» при сворачивании даёт transform на .shell-mobile-header ниже. */
    .app-root .shell-mobile-header-host {
        padding-block-start: calc(var(--app-safe-top) + 0.55rem);
    }

    /* Плавность БИНАРНОГО морфа: --hm флипается 0↔1 мгновенно (класс), а конкретные
       свойства, вычисляемые из него, доводятся одним CSS-переходом (--motion-duration-shell).
       Так морф идёт целиком в конечное состояние за один плавный проход, без покадрового
       пересчёта на скролле. Свойства перечислены явно (не `all`), чтобы не ловить чужие. */
    .app-root .shell-mobile-header,
    .app-root .shell-mobile-header-host::after,
    .app-root .shell-mobile-header-brand,
    .app-root .shell-mobile-header .shell-tabs-frame,
    .app-root .shell-mobile-header-top,
    .app-root .shell-mobile-header-top .shell-user-pill,
    .app-root .shell-mobile-header-top .shell-user-pill--standalone,
    .app-root .shell-user-pill__balance,
    .app-root .shell-mini-player--mobile,
    .app-root .shell-mini-player--mobile .shell-mini-player__extra,
    .app-root .shell-mini-player--mobile .shell-mini-player__ctrl {
        transition:
            transform var(--shell-morph-dur) var(--motion-ease-standard),
            opacity var(--shell-morph-dur) var(--motion-ease-standard),
            margin-right var(--shell-morph-dur) var(--motion-ease-standard),
            max-width var(--shell-morph-dur) var(--motion-ease-standard),
            width var(--shell-morph-dur) var(--motion-ease-standard),
            gap var(--shell-morph-dur) var(--motion-ease-standard),
            padding-left var(--shell-morph-dur) var(--motion-ease-standard),
            padding-right var(--shell-morph-dur) var(--motion-ease-standard),
            color var(--shell-morph-dur) var(--motion-ease-standard);
    }

    /* «Больше воздуха сверху по ходу морфа»: раньше анимировали padding-block-start
       хоста (LAYOUT → reflow каждый кадр). Теперь тот же сдвиг делает transform на
       контенте шапки (компоновщик, без reflow) — и высота хоста больше не дышит на
       скролле (= стабильный --shell-mobile-header-offset). */
    .app-root .shell-mobile-header {
        transform: none;
    }
    .app-root.is-shell-collapsed .shell-mobile-header {
        transform: translateY(0.4rem);
    }

    /* Брэнд тает в первые ~60% хода и уходит под меню (без z — табы выше). */
    .app-root .shell-mobile-header-brand {
        opacity: calc(1 - clamp(0, calc(var(--hm, 0) * 1.6), 1));
        transform: scale(calc(1 - var(--hm, 0) * 0.15));
        transform-origin: left center;
    }
    .app-root.is-shell-collapsed .shell-mobile-header-brand {
        pointer-events: none;
    }

    /* Табы: вверх до ОДНОЙ высоты с пилюлей профиля. Сдвиг считается по геометрии,
       а не магической константой: центр табов совмещаем с центром пилюли. Верхний
       ряд высотой --shell-header-slot (бренд = пилюля), его центр на slot/2 от верха;
       табы лежат ниже на (slot + gap 0.55rem), их центр — ещё на tabs-h/2 ниже.
       Итого подъём = slot/2 + 0.55rem + tabs-h/2 → ряд встаёт ровно (без отрыва
       пилюли от верха при упёртых в край табах). Поджатие справа — аватар в ряд. */
    .app-root .shell-mobile-header .shell-tabs-frame {
        position: relative;
        z-index: 1;
        transform: none;
        /* Резерв справа = визуальная ширина кружка-профиля (tabs-h) + гэп 0.5rem —
           единый (уменьшенный) отступ финального ряда (как gap .shell-mobile-header-top
           ниже; было 0.75rem — по просьбе юзера свёрнутый ряд плотнее). */
        margin-right: calc(var(--hm, 0) * (var(--shell-tabs-h) + 0.5rem));
    }
    .app-root.is-shell-collapsed .shell-mobile-header .shell-tabs-frame {
        transform: translateY(calc((var(--shell-header-slot) / 2 + 0.55rem + var(--shell-tabs-h) / 2) * -1));
    }
    /* Keep the same visible inset as the profile/player while they scale.
       The menu height stays fixed, so the morph does not shift page content. */
    .app-root .shell-mobile-header .shell-tabs {
        --seg-gap: calc(var(--shell-header-inset) * (1 + var(--hm, 0) * var(--shell-pill-grow)));
        height: var(--shell-tabs-h);
    }

    /* Меню (табы) уезжает влево под пару «кружок плеера + профиль»: обе в свёрнутом
       = масштаба tabs-h, резерв = 2×tabs-h + ДВА гэпа по 0.5rem — отступы
       меню↔плеер и плеер↔профиль одинаковые и плотнее. Резерв следует за
       видимостью плеера в верхнем ряду, включая постоянный плеер главной. */
    .app-root .shell-mobile-header .shell-mobile-header-top.has-player + .shell-tabs-frame {
        margin-right: calc(var(--hm, 0) * (2 * var(--shell-tabs-h) + 1rem));
    }

    /* Мобайл: при схлопывании растянутый бар теряет мету и extras (⏮/⏭/✕), его
       max-width сжимается от 100% до слота (остаётся диск-кружок; margin-left:auto
       из базового правила прижимает его к профилю) и он МАСШТАБИРУЕТСЯ как профиль
       (подрастает до высоты меню — --shell-pill-grow, origin right center): кружок
       равен аватару. margin-right компенсирует рост профиля влево, чтобы пилюли
       НЕ наслаивались. */
    .app-root .shell-mini-player--mobile {
        position: relative;
        z-index: 2;                 /* над табами (z:1) во время морфа, как профиль-пилюля */
        gap: calc((1 - var(--hm, 0)) * 0.1rem);
        max-width: calc((1 - var(--hm, 0)) * 100% + var(--hm, 0) * var(--shell-header-slot));
        transform: none;
        transform-origin: right center;
    }
    /* CSS transitions own transient compositor promotion. Idle controls do not
       retain a forced transform layer when a modal covers and reveals them. */
    .app-root.is-shell-collapsed .shell-mini-player--mobile {
        transform:
            translateX(calc(-1 * var(--shell-pill-grow, 0) * var(--shell-header-slot)))
            scale(calc(1 + var(--shell-pill-grow, 0)));
    }
    .app-root .shell-mini-player--mobile .shell-mini-player__extra {
        opacity: calc(1 - clamp(0, calc(var(--hm, 0) * 1.6), 1));
        overflow: hidden;
        white-space: nowrap;
    }
    .app-root .shell-mini-player--mobile :is(.shell-mini-player__ctrl, .shell-mini-player__play).shell-mini-player__extra {
        width: calc((1 - var(--hm, 0)) * var(--shell-header-control-size));
        max-width: calc((1 - var(--hm, 0)) * var(--shell-header-control-size));
        height: var(--shell-header-control-size);
    }
    /* Мета бара сжимается в ноль (max-width % → 0, паддинги → 0; opacity — общий
       __extra выше). Свёрнутый бар = паддинг 0.25×2 + диск (slot−0.5) = слот. */
    .app-root .shell-mini-player--mobile .shell-mini-player__meta {
        max-width: calc((1 - var(--hm, 0)) * 100%);
    }

    .app-root .shell-mobile-header-top {
        position: relative;
        pointer-events: none;   /* прозрачный ряд не должен глушить тапы по табам */
        /* Свёрнутый ряд плотнее (по просьбе юзера): flex-gap диск↔профиль ужимается
           0.75→0.5rem по ходу морфа (--hm). transform-компенсация плеера держит
           итоговый гэп = flex-gap, поэтому уменьшение gap = уменьшение зазора без
           наложения. В развёрнутом виде (hm=0) — прежние 0.75rem. */
        gap: calc(0.75rem - var(--hm, 0) * 0.25rem);
    }
    .app-root .shell-mobile-header-top > * {
        pointer-events: auto;
    }
    .app-root .shell-mobile-header-top.has-player {
        gap: calc(0.375rem + var(--hm, 0) * 0.125rem);
    }

    /* Пилюля профиля: к концу морфа подрастает до высоты меню — финальный ряд
       одной высоты (фон/блюр — только на главной, см. выше). */
    .app-root .shell-mobile-header-top :is(.shell-user-pill, .shell-user-pill--standalone) {
        position: relative;
        z-index: 2;
        transform: none;
        transform-origin: right center;
    }
    .app-root.is-shell-collapsed .shell-mobile-header-top :is(.shell-user-pill, .shell-user-pill--standalone) {
        transform: scale(calc(1 + var(--shell-pill-grow)));
    }

    /* Баланс схлопывается — от профиля остаётся только аватар (пилюля → круг;
       overflow: hidden у пилюли прячет текст по ходу). Старт — от натуральной
       ширины текста (--pill-balance-w меряет ShellHeaderService.measurePillBalance),
       поэтому контейнер худеет линейно с первого пикселя хода, а не в конце. */
    .app-root .shell-user-pill__balance {
        max-width: calc((1 - var(--hm, 0)) * var(--pill-balance-w, 9rem));
        padding-left: calc((1 - var(--hm, 0)) * 0.75rem);
        padding-right: calc((1 - var(--hm, 0)) * 0.4rem);
        opacity: calc(1 - clamp(0, calc(var(--hm, 0) * 1.8), 1));
    }

    /* Mobile top-up matches the avatar's square slot. Its width and gap
       collapse together; text measurement must not squeeze the ruble button. */
    .app-root .shell-user-pill__balance--topup {
        width: var(--shell-header-control-size);
        max-width: calc((1 - var(--hm, 0)) * var(--shell-header-control-size));
        padding: 0;
        justify-content: center;
        line-height: 1;
        border-radius: var(--radius-round);
        margin-right: calc((1 - var(--hm, 0)) * 0.3rem);
    }
}

/* Узкие экраны: табы компактнее (см. медиа 480 у .shell-tab) — пересчёт цели. */
@media (max-width: 480px) {
    .app-root {
        /* Both the height and profile/player scale follow this one size. */
        --shell-tabs-h-rem: 3.02;
    }
}

/* Home cards share ShellMotion with histories; never animate their scroll parent. */

@media (prefers-reduced-motion: reduce) {
    .tile,
    .home-continue-card,
    .home-assistant-card {
        transition: none !important;
    }
}

/* Decorative landing glow; generation progress uses GenerationMotion. */
.landing-glow-host::before {
    --ambient-glow-shape: 38% 62% 54% 46% / 42% 34% 66% 58%;
    --ambient-glow-conic: conic-gradient(from 132deg at 48% 58%,
            transparent 0deg,
            color-mix(in srgb, var(--primary-500) 48%, transparent) 38deg,
            transparent 88deg,
            color-mix(in srgb, var(--accent-cool) 32%, transparent) 148deg,
            transparent 212deg,
            color-mix(in srgb, var(--primary-600) 42%, transparent) 286deg,
            transparent 360deg);
    --ambient-glow-near: radial-gradient(ellipse 68% 22% at 18% 54%,
            color-mix(in srgb, var(--primary-500) 50%, transparent) 0%,
            transparent 72%);
    --ambient-glow-far: radial-gradient(ellipse 58% 20% at 78% 46%,
            color-mix(in srgb, var(--accent-cool) 32%, transparent) 0%,
            transparent 70%);
    --ambient-glow-wash: linear-gradient(104deg,
            transparent 12%,
            color-mix(in srgb, var(--primary-500) 30%, transparent) 32%,
            transparent 48%,
            color-mix(in srgb, var(--gradient-warm) 22%, transparent) 62%,
            color-mix(in srgb, var(--accent-cool) 26%, transparent) 76%,
            transparent 92%);
}
.landing-glow-host::before {
    content: '';
    position: absolute;
    inset: -10rem 0 -4.5rem;
    border-radius: var(--ambient-glow-shape);
    background-image: var(--ambient-glow-conic), var(--ambient-glow-near), var(--ambient-glow-far), var(--ambient-glow-wash);
    background-size: 170% 160%, 122% 112%, 130% 116%, 180% 140%;
    background-position: 0% 52%, 7% 58%, 92% 42%, 100% 48%;
    filter: blur(52px) saturate(1.15);
    opacity: 0;
    pointer-events: none;
    transform: translate3d(0, 0.85rem, 0) scale(0.96) rotate(-2deg);
    transform-origin: 50% 100%;
    transition: opacity var(--motion-duration-shell) var(--motion-ease-standard);
    contain: paint;
    z-index: 0;
}

/* Isolated smoke surface; volume changes never invalidate form descendants. */
.composer-voice-glow {
    --ambient-smoke-texture: url('/static/media/effects/ambient-smoke-outflow.png');
    --accent-cool: var(--prism-cyan);
    --gradient-warm: var(--prism-gold);
    position: absolute;
    inset-inline: calc(var(--ambient-smoke-outset) * -1rem);
    bottom: calc(var(--ambient-smoke-outset) * -1rem);
    height: calc((var(--ambient-smoke-unit) + var(--ambient-smoke-outset)) * 1rem);
    pointer-events: none;
    z-index: 0;
    opacity: 0;
    transition: opacity var(--motion-duration-fast) linear;
}
/* Textured fallback covers unavailable GPU contexts and reduced motion. */
.composer-voice-glow::before,
.music-lyrics__light::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(110deg, var(--primary-500), var(--accent-cool), var(--gradient-warm));
    -webkit-mask: var(--ambient-smoke-texture) center / 100% 100% no-repeat;
    mask: var(--ambient-smoke-texture) center / 100% 100% no-repeat;
    /* A prepared fallback cloud must not flash before live smoke ignites. */
    opacity: 0;
}
[data-smoke-fallback]::before { opacity: .7; }
[data-smoke-ready]:not([data-smoke-fallback])::before { opacity: 0; }
.ambient-smoke-canvas {
    position: absolute; inset: 0; width: 100%; height: 100%;
    display: block; pointer-events: none; opacity: 0;
}
[data-smoke-ready]:not([data-smoke-fallback]) > .ambient-smoke-canvas { opacity: 1; }
.is-recording > .composer-voice-glow {
    /* Keep the entire contour visible even when the microphone is silent. */
    opacity: var(--ambient-smoke-opacity);
    /* Audio drives the canvas flow and light without restyling the form. */
}

@keyframes chat-input-gradient-flow {
    0%   { background-position: 0% 52%, 7% 58%, 92% 42%, 100% 48%; }
    50%  { background-position: 100% 48%, 93% 42%, 8% 58%, 0% 52%; }
    100% { background-position: 0% 52%, 7% 58%, 92% 42%, 100% 48%; }
}

@media (prefers-reduced-motion: reduce) {
    .landing-glow-host.is-glowing::before,
    .landing-track.is-playing::before {
        animation: none;
    }

    .gen-loading--chat .gen-loading__media {
        transition: opacity var(--motion-duration-fast) var(--motion-ease-standard);
        transform: none;
        filter: none;
    }

    .composer-state-switch > .composer-state-layer {
        transition: none;
    }

}

/* Shared frame for every generated file. Loading supplies motion only;
   success and failure keep their geometry independently of the animation. */
.generation-surface {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    border-radius: var(--generation-radius, var(--radius-lg));
    corner-shape: var(--corner-shape-surface);
    background: var(--generation-background, var(--bg-elevated));
}
.generation-file-state {
    display: flex;
    align-items: center;
    justify-content: center;
}
.generation-file-state > .gen-loading__label { padding: 0 1rem; text-align: center; }
.audio-card.generation-file-state .generation-error { padding: var(--audio-card-padding-block) 1rem; }
.audio-card.generation-file-state .generation-error__content {
    display: grid;
    grid-template-columns: 1.5rem minmax(0, 1fr);
    gap: 0.1rem 0.6rem;
    width: 100%;
    margin: auto;
    text-align: left;
}
.audio-card.generation-file-state .generation-error__icon { grid-row: 1 / 3; width: 1.5rem; height: 1.5rem; align-self: center; }
.audio-card.generation-file-state .generation-error__title { font-size: var(--text-xs); }
.audio-card.generation-file-state .generation-error__message { font-size: var(--text-2xs); line-height: var(--leading-snug); }
.generation-surface .gen-loading__label {
    max-width: 100%;
    color: var(--text-secondary);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    overflow-wrap: anywhere;
}
.chat-file-card .gen-loading__label {
    min-width: 0;
    padding: 0;
    text-align: left;
    font: inherit;
    font-size: var(--text-xs);
    font-weight: var(--font-weight-medium);
    line-height: var(--leading-snug);
    letter-spacing: normal;
    text-transform: none;
}
.chat-file-card .gen-loading__label .text-shimmer { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.chat-file-card.generation-surface .chat-file-card__header { position: relative; z-index: 1; }
.chat-file-card .generation-error { padding: calc(var(--gap-sm) * .5) var(--gap-sm); }
.chat-file-card .generation-error__content {
    display: grid;
    grid-template-columns: 1.75rem minmax(0, 1fr);
    gap: 0 var(--gap-sm);
    width: 100%;
    max-width: none;
    text-align: left;
}
.chat-file-card .generation-error__icon { grid-row: 1 / 3; width: 1.75rem; height: 1.75rem; }
.chat-file-card .generation-error__title { font-size: var(--text-xs); }
.chat-file-card .generation-error__message { font-size: var(--text-2xs); }

/* Shared loading layout; GenerationMotion owns all generation animation. */
.generation-surface,
.gen-loading {
    --accent-cool: var(--prism-cyan);
}
.gen-loading {
    position: relative;
    width: 100%;
    min-height: 9rem;            /* запас, когда aspect-ratio не задан (чат) */
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;            /* Clip the shared smoke to the frame. */
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: color-mix(in srgb, var(--bg-elevated) 55%, transparent);
    isolation: isolate;
}

/* Landing retains its decorative palette. */
:is([data-theme="prism"], [data-theme="prism-light"]) .landing-glow-host::before {
    background-image:
        conic-gradient(from 132deg at 48% 58%,
            transparent 0deg,
            color-mix(in srgb, var(--prism-pink) 52%, transparent) 38deg,
            transparent 92deg,
            color-mix(in srgb, var(--prism-cyan) 42%, transparent) 150deg,
            transparent 214deg,
            color-mix(in srgb, var(--prism-lilac) 48%, transparent) 286deg,
            transparent 360deg),
        radial-gradient(ellipse 68% 22% at 18% 54%,
            color-mix(in srgb, var(--prism-pink) 52%, transparent) 0%, transparent 72%),
        radial-gradient(ellipse 58% 20% at 78% 46%,
            color-mix(in srgb, var(--prism-lilac) 46%, transparent) 0%, transparent 70%),
        linear-gradient(104deg,
            transparent 12%,
            color-mix(in srgb, var(--prism-gold) 30%, transparent) 32%,
            transparent 48%,
            color-mix(in srgb, var(--prism-mint) 24%, transparent) 62%,
            color-mix(in srgb, var(--prism-cyan) 30%, transparent) 76%,
            transparent 92%);
}

.gen-loading__label {            /* + класс .voice-recording-title в разметке */
    position: relative;
    z-index: 1;
    text-align: center;
    padding: 0 1rem;
}

/* Sidebar thumbnails inherit the shared frame's corners and aspect ratio. */
.gen-loading--thumb { border-radius: inherit; corner-shape: inherit; min-height: 0; }
.gen-loading--thumb > .gen-loading__label {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: grid;
    place-items: center;
    max-width: 100%;
    padding: 0 1rem;
    font-size: var(--text-xs);
    white-space: normal;
    pointer-events: none;
}
/* Compact music covers use the same smoke without a text label. */
.gen-loading--bare {
    min-height: 0;
    height: 100%;
    border-radius: inherit;
    corner-shape: inherit;
}

/* Shared smoke stays within each generation frame. */
/* The label follows the same visibility and activity gate as the smoke. */
.gen-loading__label .text-shimmer { animation-play-state: paused; }
[data-generation-animating] .gen-loading__label .text-shimmer {
    animation-play-state: var(--pane-ambient-play-state, running);
}
.generation-motion {
    position: absolute;
    inset: 0;
    overflow: hidden;
    border-radius: inherit;
    corner-shape: inherit;
    z-index: 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--motion-duration-gallery) var(--motion-ease-standard);
    /* The host clips the cloud at its real edges, without an inset fade. */
}
.generation-motion.is-active { opacity: var(--ambient-smoke-opacity); }
[data-generation-profile="compact"] > .generation-motion.is-active { opacity: var(--ambient-smoke-compact-opacity); }
.generation-motion:not(.is-active) { visibility: hidden; transition: none; }
.generation-motion > canvas {
    display: block;
    width: 100%;
    height: 100%;
}
@media (prefers-reduced-motion: reduce) {
    .generation-motion { transition: none; }
}

/* ── Reveal: результат проявляется поверх свечения ──
   Свечение остаётся фоном кадра, медиа фейдится поверх по факту загрузки
   (@load / @loadeddata добавляет .is-loaded на контейнер). Нет пустого бокса. */
.gen-loading__media {
    position: relative;
    z-index: 1;
    display: block;
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 70vh;
    border-radius: inherit;
    corner-shape: inherit;
    opacity: 0;
    transition: opacity var(--motion-duration-gallery) var(--motion-ease-standard);
}
.gen-loading.is-loaded .gen-loading__media { opacity: 1; }

/* The frame remains visible throughout generation and result loading. */
.gen-loading--chat {
    background: var(--bg-elevated);
    overflow: hidden;
}
.gen-loading--chat .gen-loading__media {
    transform: scale(0.94);
    filter: blur(10px);
    transition: opacity var(--motion-duration-base) var(--motion-ease-premium),
                transform var(--motion-duration-slow) var(--motion-ease-premium),
                filter var(--motion-duration-slow) var(--motion-ease-premium);
}
.gen-loading--chat.is-loaded .gen-loading__media {
    transform: scale(1);
    filter: blur(0);
}
/* После загрузки контейнер сжимается ровно по фото (слева), без пустых полей —
   бокс = картинка, кнопки садятся в её угол. */
.gen-loading--chat.is-loaded {
    display: inline-block;
    min-height: 0;
    vertical-align: top;
}

@media (prefers-reduced-motion: reduce) {
    .chat-media-gallery .gen-loading__media { transition: none; transform: none; filter: none; }
}

.agent-flow__web-image {
    display: inline-flex;
    max-width: min(100%, 42rem);
    flex-direction: column;
    align-items: flex-start;
    gap: 0.45rem;
}

.agent-flow__media-source {
    display: inline-flex;
    max-width: 100%;
    align-items: center;
    gap: 0.2rem;
    color: var(--text-muted);
    font-size: var(--text-xs);
    line-height: var(--leading-snug);
    text-decoration: none;
}

.agent-flow__media-source:hover {
    color: var(--text-main);
    text-decoration: underline;
}

.md-external-image-link {
    display: inline-flex;
    align-items: center;
    min-height: 2rem;
    padding: 0.35rem 0.7rem;
    border: 0;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    color: var(--text-muted);
    text-decoration: none;
}

.md-external-image-link:hover {
    color: var(--text-main);
    border-color: transparent;
}

/* ════════════════════════════════════════════════════════════════
   LEGAL PAGES (/policy, /privacy)
   ════════════════════════════════════════════════════════════════ */
.legal-page {
    position: relative;
    z-index: 1;
    flex: 1 1 0%;
    min-height: 0;
    width: 100%;
    background: var(--bg-app);
    color: var(--text-main);
    overflow-y: auto;
}

.legal-page__header {
    display: flex;
    align-items: center;
    padding: 1rem 2.5rem;
    background: transparent;
}

.legal-page__brand {
    display: inline-flex;
    align-items: center;
    color: var(--text-main);
    text-decoration: none;
    transition: color var(--transition);
}

.legal-page__brand:hover {
    color: var(--text-main);
}

.legal-page__brand-icon {
    width: var(--brand-logo-size);
    height: var(--brand-logo-size);
    display: block;
}

.legal-page__article {
    width: 100%;
    padding: 2rem 2.5rem 6rem;
    line-height: var(--leading-relaxed);
    font-size: var(--text-base);
}

.legal-page__article h1 {
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    line-height: var(--leading-tight);
    font-weight: var(--font-weight-display);
    margin-bottom: 0.5rem;
}

.legal-page__article h2 {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    line-height: var(--leading-snug);
    font-weight: var(--font-weight-display);
    margin: 2.25rem 0 1rem;
    color: var(--text-main);
}

.legal-page__article p {
    margin: 0 0 0.65rem;
    color: var(--text-muted);
}

.legal-page__article p b,
.legal-page__article p strong {
    color: var(--text-main);
    font-weight: var(--font-weight-semibold);
}

.legal-page__article a {
    color: var(--text-main);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.legal-page__article a:hover {
    color: var(--text-main);
}

.legal-page__meta {
    color: var(--text-subtle);
    font-size: var(--text-xs);
    margin-bottom: 2rem !important;
}

@media (max-width: 640px) {
    .legal-page__header {
        padding: 0.85rem 1.25rem;
    }
    .legal-page__article {
        padding: 1.5rem 1.25rem 5rem;
        font-size: var(--text-sm);
    }
    .legal-page__article h1 {
        font-size: var(--text-2xl);
    }
    .legal-page__article h2 {
        font-size: var(--text-lg);
    }
}

/* ════════════════════════════════════════════════════════════════
   COOKIE CONSENT BANNER
   ════════════════════════════════════════════════════════════════ */
.cookie-banner {
    position: fixed;
    left: 50%;
    bottom: 1rem;
    transform: translate(-50%, calc(100% + 2rem));
    width: min(36rem, calc(100vw - 1.5rem));
    z-index: 9999;
    color: var(--text-main);
    /* Кант — градиентный (.edge-gradient в шаблоне) вместо сплошного 1px. */
    transition: transform var(--motion-duration-base) var(--motion-ease-premium);
}

.cookie-banner--visible {
    transform: translate(-50%, 0);
}

.cookie-banner__inner {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.85rem 1rem;
    flex-wrap: wrap;
}

.cookie-banner__text {
    flex: 1 1 16rem;
    margin: 0;
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    color: var(--text-muted);
}

.cookie-banner__link {
    color: var(--text-main);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.cookie-banner__accept {
    flex: 0 0 auto;
    padding: 0.55rem 1.1rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    border: none;
    background: var(--text-main);
    color: var(--bg-app);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    cursor: pointer;
    transition: opacity var(--transition);
}

.cookie-banner__accept:hover {
    opacity: 0.85;
}

@media (max-width: 480px) {
    .cookie-banner__inner {
        padding: 0.75rem 0.85rem;
    }
    .cookie-banner__accept {
        flex: 1 0 100%;
    }
}

/* PWA splash overlay (markup всегда в DOM, см. _app_splash.html) — здесь
   только дефолтный off-state. Все активные стили живут в pwa.css, который
   подключается условно через media="(display-mode: standalone), ...". */
.app-splash {
    display: none;
}

/* ════════════════════════════════════════════════════════════════
   СЦЕНАРИИ (/workflows) — нод-редактор.
   Канвас — vendored Drawflow (css/vendor/drawflow.min.css задаёт только
   механику/геометрию), здесь его темизация токенами ядра + layout страницы.
   ════════════════════════════════════════════════════════════════ */

/* ── Сайдбар-список (анатомия и поверхности — как строки истории чатов) ── */
.wf-side-item {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 0.75rem;
    border-radius: var(--radius-xl);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-hover);
    cursor: pointer;
}

/* Мобайл: списки историй (чаты/транскрипция/сценарии) — полноэкранный экран без
   сплит-вида. Активный элемент НЕ подсвечиваем: иначе после открытия и возврата
   «назад» прошлый пункт остаётся гореть как активный. На десктопе подсветка нужна
   (виден сплит), поэтому правило только под мобильным брейкпоинтом. */
@media (max-width: 767.98px) {
    .tg-chat-row.is-active { background-color: var(--bg-hover); }
    .wf-side-item.is-active { background: transparent; }
}

.wf-side-item__icon {
    width: 2.75rem;
    height: 2.75rem;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-elevated);
    color: var(--text-muted);
}

.wf-side-item__body {
    min-width: 0;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
}

.wf-side-item__name {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.wf-side-item__meta {
    font-size: var(--text-xs);
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Индикатор автозапуска: точка primary, выключен — прозрачная. */
.wf-side-item__dot {
    width: 0.45rem;
    height: 0.45rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    flex-shrink: 0;
    background: transparent;
}

.wf-side-item__dot.is-on {
    background: var(--primary-500);
}

.wf-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex-shrink: 0;
    padding: 0.15rem 0.6rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-muted);
    font-size: var(--text-2xs);
    white-space: nowrap;
}

/* Бейдж статуса прогона в строке тулбара — глассовый, в высоту кластеров.
   Должен идти ДО --active: у запущенного рана primary-заливка поверх гласса. */
.wf-badge--float {
    height: 2.75rem;
    padding-inline: 0.9rem;
    background-color: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    box-shadow: var(--shadow-glass);
}

.wf-badge--active {
    background: var(--surface-soft);
    color: var(--text-main);
}

/* ── Layout редактора: канвас = фон страницы, всё управление — overlay ── */
.wf-editor {
    position: relative;
    flex: 1;
    min-height: 0;
}

/* Канвас без обёртки-контейнера: точечная сетка прямо на фоне страницы,
   под глассовыми панелями сайдбаров; тулбар и панели плавают поверх. */
.wf-canvas-host {
    position: absolute;
    inset: 0;
    background-image: radial-gradient(var(--surface-soft) 1px, transparent 1px);
    background-size: 22px 22px;
}

/* Тулбар-оверлей: глассовые кластеры в одну линию с кнопкой «Нод» внутри канваса.
   pointer-events только на кластерах — пустые зоны строки не перехватывают канвас. */
.wf-topbar {
    position: absolute;
    top: 0.75rem;
    left: 0.75rem;
    right: 0.75rem;
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    pointer-events: none;
}

.wf-topbar > * {
    pointer-events: auto;
}

/* Desktop: по углам absolute-оверлей shell-desktop-header (слева шеврон панели,
   справа пилюля профиля) — выравниваемся по его строке и не заезжаем под пилюли. */
@media (min-width: 768px) {
    .wf-topbar {
        top: var(--shell-header-padding-block);
        left: 4rem;
        right: 13rem;
    }
    /* Canvas tools share the top row only while no track is shown. */
    .shell-content-column:has(> .shell-desktop-header.has-player) .wf-topbar {
        top: var(--shell-content-top);
        left: var(--shell-page-gutter);
        right: var(--shell-page-gutter);
    }
}

.wf-top-group {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.25rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    box-shadow: var(--shadow-glass);
}

/* Кнопки внутри глассового кластера — прозрачные круги (рецепт shell-desktop-header__toggle). */
.wf-top-group .btn-ghost {
    background-color: transparent;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
}

.wf-top-group .btn-ghost:disabled {
    background-color: transparent;
}

/* Зум-кластер канваса — глассовая пилюля в правом нижнем углу
   (на мобилке поднята над кнопкой «Запустить»). */
.wf-zoom {
    position: absolute;
    right: 0.75rem;
    bottom: 0.75rem;
    z-index: 10;
}

@media (max-width: 767.98px) {
    .wf-zoom {
        bottom: calc(var(--safe-area-bottom, 0px) + 4.4rem);
    }
}

/* AI-ассистент: плавающая панель-промпт у нижнего края канваса (по центру),
   глассовый стиль как у .wf-panel. */
.wf-assistant {
    position: absolute;
    left: 50%;
    bottom: 0.75rem;
    transform: translateX(-50%);
    z-index: 12;
    width: min(34rem, calc(100% - 1.5rem));
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 0.85rem 1rem;
    background-color: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    box-shadow: var(--shadow-glass);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
}

.wf-assistant__head {
    display: flex;
    align-items: center;
    gap: 0.45rem;
}

.wf-assistant__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}

/* Чип-контрол связи: шестерёнка ПОСТОЯННО видна в середине каждой линии
   (живёт внутри precanvas — пан/зум отслеживает его transform). */
.wf-edge-chip {
    position: absolute;
    transform: translate(-50%, -50%);
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.65rem;
    height: 1.65rem;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-elevated);
    box-shadow: var(--shadow-icon);
    color: var(--text-subtle);
    font-size: var(--text-sm);
    cursor: pointer;
    transition: color var(--transition), box-shadow var(--transition);
}

.wf-edge-chip:hover {
    color: var(--text-main);
    box-shadow: var(--shadow-surface);
}

/* Штрих-кривая сцепки при перетаскивании нода («отпусти — соединю»):
   форма как у связей Drawflow, бегущий пунктир. */
.wf-snap-line {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 9;
    display: none;
    overflow: visible;
}

.wf-snap-line path {
    fill: none;
    stroke: var(--primary-500);
    stroke-width: 2.5px;
    stroke-dasharray: 7 6;
    stroke-linecap: round;
    opacity: 0.85;
    animation: wf-snap-dash var(--motion-period-dash) var(--motion-ease-linear) infinite;
}

@keyframes wf-snap-dash {
    to { stroke-dashoffset: -13; }
}

/* Кнопка вставки переменной у шаблонизируемых полей панели нода. */
.wf-field__label--row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.wf-var-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    color: var(--text-subtle);
    transition: color var(--transition), background-color var(--transition);
}

.wf-var-btn:hover {
    color: var(--text-main);
    background: var(--surface-soft);
}

/* Секретный URL вебхука в панели параметров. */
.wf-webhook-url {
    display: block;
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
    font-size: var(--text-2xs);
    color: var(--text-muted);
    word-break: break-all;
}

/* Точка несохранённых изменений на кнопке «Сохранить». */
.wf-dirty-dot {
    position: absolute;
    top: 0.3rem;
    right: 0.3rem;
    width: 0.45rem;
    height: 0.45rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: var(--primary-500);
}

/* Кнопка добавления нода — глассовая пилюля в строке тулбара, меню — ctxMenu. */
.wf-canvas-add {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    height: 2.75rem;
    padding-inline: 1rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background-color: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    box-shadow: var(--shadow-glass);
    color: var(--text-main);
    transition: background-color var(--transition);
}

@media (hover: hover) {
    .wf-canvas-add:hover {
        background-color: var(--surface-strong);
    }
}

.wf-canvas-add i {
    color: var(--text-main);
}

.wf-settings__title {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    margin-bottom: 0.5rem;
}

.wf-settings__subtitle {
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--text-muted);
    margin: 0.75rem 0 0.4rem;
}

.wf-field {
    display: block;
    margin-bottom: 0.75rem;
}

/* Чекбокс-поле: контрол и лейбл в одну строку. */
.wf-field--row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
}

.wf-field--row .wf-field__label {
    margin-bottom: 0;
}

.wf-field__label {
    display: block;
    font-size: var(--text-xs);
    color: var(--text-muted);
    margin-bottom: 0.3rem;
}

.wf-field__help {
    display: block;
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    margin-top: 0.3rem;
}

/* Триггер-кнопка дропдауна (поля-селекты панели настроек) — поверх .input-field. */
.wf-select {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.wf-select__icon {
    width: 1.15rem;
    height: 1.15rem;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.wf-select__icon svg {
    width: 100%;
    height: 100%;
}

.wf-select__label {
    min-width: 0;
    flex: 1;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.wf-hint {
    margin-top: 0.75rem;
    padding: 0.6rem 0.75rem;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
    font-size: var(--text-2xs);
    color: var(--text-muted);
    line-height: var(--leading-normal);
    word-break: break-word;
}

.wf-hint--warn {
    background: var(--surface-soft);
    color: var(--text-main);
}

.wf-hint__title {
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    margin-bottom: 0.2rem;
}

.wf-hint code {
    background: var(--bg-input);
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    padding: 0 0.25rem;
}

/* ── Единая overlay-панель (настройки нода / параметры сценария / история):
   плавающая глассовая карточка поверх канваса (рецепт dropdown-panel). ── */
.wf-panel {
    position: absolute;
    top: 4rem;
    right: 0.75rem;
    bottom: 0.75rem;
    width: min(22rem, calc(100% - 1.5rem));
    background-color: var(--chat-input-solid);
    box-shadow: var(--shadow-glass);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    display: flex;
    flex-direction: column;
    z-index: 20;
}

.wf-panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1rem 0.25rem;
    flex-shrink: 0;
}

.wf-panel__head .wf-settings__title {
    margin-bottom: 0;
}

.wf-panel__body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 0.5rem 1rem 1rem;
}

/* Обёртка полей панели: fieldset, чтобы :disabled (read-only мобилка) нативно
   гасил все вложенные контролы. Сбрасываем юзер-агент стили. */
.wf-panel-fields {
    border: none;
    margin: 0;
    padding: 0;
    min-width: 0;
}

.wf-run-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.5rem 0.4rem;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    text-align: left;
}

.wf-run-row:hover {
    background: var(--surface-soft);
}

/* Статусы — нейтральная палитра ядра (без красного/зелёного): активное —
   primary, остальное — поверхности; см. комментарий у --red-500. */
.wf-run-row__status {
    font-size: var(--text-2xs);
    padding: 0.1rem 0.5rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-muted);
    white-space: nowrap;
}

.wf-status--running { background: var(--surface-soft); color: var(--text-main); }
.wf-status--succeeded { background: var(--surface-active); color: var(--text-main); }
.wf-status--failed { background: var(--text-main-6); color: var(--text-main); }

.wf-step {
    padding: 0.5rem 0;
    border-bottom: 0;
}

.wf-step__output {
    font-size: var(--text-2xs);
    color: var(--text-muted);
    margin-top: 0.25rem;
    white-space: pre-wrap;
    word-break: break-word;
}

/* Превью медиа-результата шага в истории запусков */
.wf-step__media {
    display: block;
    max-width: 100%;
    max-height: 220px;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    margin-top: 0.35rem;
}

.wf-spin {
    animation: spin-360 var(--motion-period-spinner) var(--motion-ease-linear) infinite;
}

/* ── Темизация Drawflow токенами ядра (без бордеров — заливка + тень,
   состояния — кольца box-shadow) ── */
.wf-canvas-host .drawflow .drawflow-node {
    background: var(--bg-elevated);
    border: none;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    color: var(--text-main);
    width: 200px;
    min-height: 0;
    padding: 0;
    box-shadow: var(--shadow-surface);
    transition: box-shadow var(--motion-duration-fast) var(--motion-ease-standard);
}

.wf-canvas-host .drawflow .drawflow-node.selected {
    background: var(--bg-elevated);
    box-shadow: var(--shadow-surface);
}

.wf-canvas-host .drawflow .drawflow-node .input,
.wf-canvas-host .drawflow .drawflow-node .output {
    width: 12px;
    height: 12px;
    background: var(--text-subtle);
    border: none;
    transition: background-color var(--transition);
}

.wf-canvas-host .drawflow .drawflow-node .input {
    left: -7px;
}

.wf-canvas-host .drawflow .drawflow-node .output {
    right: -7px;
}

/* Типизированные порты (advisory): цвет по типу данных потока. Связи НЕ
   блокируются — это лишь визуальная подсказка. text-порты остаются дефолтным
   --text-subtle (см. .input/.output выше); audio опущен — media-нод воркфлоу
   отдаёт только image/video. Правила стоят ДО :hover, чтобы наведение
   по-прежнему подсвечивало порт. */
.wf-canvas-host .drawflow .drawflow-node.wf-out-image .output { background: var(--accent-cool); }
.wf-canvas-host .drawflow .drawflow-node.wf-out-video .output { background: var(--accent-warm); }
.wf-canvas-host .drawflow .drawflow-node.wf-out-mixed .output { background: var(--primary-500); }
.wf-canvas-host .drawflow .drawflow-node.wf-in-mixed .input { background: var(--primary-500); }

.wf-canvas-host .drawflow .drawflow-node .input:hover,
.wf-canvas-host .drawflow .drawflow-node .output:hover {
    background: var(--primary-500);
}

/* Подписи веток фильтра у выходных портов («Да» сверху, «Нет» снизу) */
.wf-canvas-host .drawflow .drawflow-node.wf-kind-filter .output::after {
    position: absolute;
    left: calc(100% + 4px);
    top: 50%;
    transform: translateY(-50%);
    font-size: var(--text-2xs);
    color: var(--text-subtle);
    pointer-events: none;
}

.wf-canvas-host .drawflow .drawflow-node.wf-kind-filter .output_1::after {
    content: 'Да';
}

.wf-canvas-host .drawflow .drawflow-node.wf-kind-filter .output_2::after {
    content: 'Нет';
}

.wf-canvas-host .drawflow .connection .main-path {
    stroke: var(--text-subtle);
    stroke-width: 2.5px;
}

.wf-canvas-host .drawflow .connection .main-path:hover,
.wf-canvas-host .drawflow .connection .main-path.selected {
    stroke: var(--primary-500);
}

.wf-canvas-host .drawflow-delete {
    background: var(--bg-raised);
    border: none;
    box-shadow: var(--shadow-icon);
    color: var(--text-main);
    line-height: var(--leading-none);
}

/* Содержимое нода (наш html внутри drawflow_content_node) */
.wf-node {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.65rem 0.75rem;
}

.wf-node__icon {
    width: 2rem;
    height: 2rem;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
    color: var(--text-main);
    font-size: var(--text-base);
}

/* Фирменная иконка группы модели внутри нода (svg из каталога). */
.wf-node__icon svg {
    width: 1.15rem;
    height: 1.15rem;
}

.wf-kind-trigger .wf-node__icon {
    background: var(--surface-soft);
}

.wf-node__text {
    min-width: 0;
    flex: 1;
}

.wf-node__title {
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Чипы на лице ноды: модель + ключевые параметры (разрешение/соотношение/
   длительность, размышления/поиск и т.п.) — как в нод-канвасе референса. */
.wf-node__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-top: 0.15rem;
}

.wf-node__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    max-width: 100%;
    padding: 0.05rem 0.35rem;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
    color: var(--text-subtle);
    font-size: var(--text-2xs);
    line-height: var(--leading-normal);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.wf-node__chip i {
    font-size: 0.85em;
    flex-shrink: 0;
}

.wf-node__state {
    width: 0.55rem;
    height: 0.55rem;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    flex-shrink: 0;
    background: transparent;
    transition: background var(--motion-duration-fast) var(--motion-ease-standard);
}

/* Статусы прогона на нодах (классы вешает workflowsApp.applyNodeStatus) */
.wf-canvas-host .drawflow-node.wf-node-running {
    box-shadow: 0 0 0 3px var(--primary-14), var(--shadow-surface);
}

.wf-canvas-host .drawflow-node.wf-node-running .wf-node__state {
    background: var(--primary-500);
    animation: wf-pulse var(--motion-period-pulse) var(--motion-ease-ambient) infinite;
}

.wf-canvas-host .drawflow-node.wf-node-done .wf-node__state {
    background: var(--primary-500);
}

.wf-canvas-host .drawflow-node.wf-node-failed {
    box-shadow: var(--shadow-surface);
}

.wf-canvas-host .drawflow-node.wf-node-failed .wf-node__state {
    background: var(--text-subtle);
}

.wf-canvas-host .drawflow-node.wf-node-skipped {
    opacity: 0.45;
}

@keyframes wf-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
}

/* ── Живые ноды (ai_text/media): инлайн-промпт + ▶ + результат на карточке ── */
.wf-canvas-host .drawflow .drawflow-node:has(.wf-node--live) {
    width: 264px;
}

.wf-node--live {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.6rem 0.65rem;
}

.wf-node--live .wf-node__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.wf-node--live .wf-node__title {
    flex: 1;
    min-width: 0;
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.wf-node__live-result {
    min-height: 3.25rem;
    max-height: 12rem;
    overflow-y: auto;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
    padding: 0.5rem 0.55rem;
}

.wf-node__live-ph {
    color: var(--text-subtle);
    font-size: var(--text-2xs);
    text-align: center;
    padding: 0.5rem 0;
}

.wf-node__live-text {
    width: 100%;
    color: var(--text-main);
    font-size: var(--text-2xs);
    line-height: var(--leading-normal);
    white-space: pre-wrap;
    word-break: break-word;
}

.wf-node__live-media {
    display: block;
    margin: 0 auto;
    max-width: 100%;
    max-height: 11rem;
    object-fit: contain;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
}

.wf-node__live-row {
    display: flex;
    align-items: flex-end;
    gap: 0.4rem;
}

.wf-node__live-prompt {
    flex: 1;
    min-width: 0;
    resize: none;
    border: none;
    outline: none;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    padding: 0.45rem 0.55rem;
    background: var(--surface-soft);
    color: var(--text-main);
    font-size: var(--text-2xs);
    line-height: var(--leading-normal);
    font-family: inherit;
}

.wf-node__live-prompt::placeholder { color: var(--text-muted); }

.wf-node__live-run {
    flex-shrink: 0;
    width: 2rem;
    height: 2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal;
    color: var(--primary-text);
    transition: background var(--transition), color var(--transition);
}

@media (hover: hover) {
    .wf-node__live-run:hover { background-image: var(--prism-noise), var(--gradient-primary); background-size: 120px 120px, auto; background-blend-mode: overlay, normal; color: var(--primary-text); }
}

.wf-node__live-model {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    align-self: flex-start;
    max-width: 100%;
    height: 1.75rem;
    padding: 0 0.55rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-subtle);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-semibold);
    transition: background var(--transition), color var(--transition);
}

.wf-node__live-model span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (hover: hover) {
    .wf-node__live-model:hover { background: var(--surface-strong); color: var(--text-main); }
}

/* Нижняя строка живой карточки: модель + чипы управляемых параметров модели. */
.wf-node__live-params {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
}

.wf-node__live-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    max-width: 100%;
    height: 1.75rem;
    padding: 0 0.5rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-subtle);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-semibold);
    white-space: nowrap;
    transition: background var(--transition), color var(--transition);
}

.wf-node__live-chip > span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.wf-node__live-chip > i { font-size: 0.85em; opacity: 0.7; }

.wf-node__live-chip.is-on {
    background: var(--surface-soft);
    color: var(--text-main);
}

@media (hover: hover) {
    .wf-node__live-chip:hover { background: var(--surface-strong); color: var(--text-main); }
    .wf-node__live-chip.is-on:hover { background: var(--surface-strong); color: var(--text-main); color: var(--primary-text); }
}

.wf-node__live-model .wf-node__live-bolt { color: var(--text-muted); }
.wf-node__live-model > .ti-chevron-down { font-size: 0.85em; opacity: 0.6; }

/* Иконки действий нода — прижаты вправо, проявляются при наведении/выборе нода. */
.wf-node__live-actions {
    display: flex;
    align-items: center;
    gap: 0.1rem;
    margin-left: auto;
    opacity: 0;
    transition: opacity var(--transition);
}

.drawflow-node:hover .wf-node__live-actions,
.drawflow-node.selected .wf-node__live-actions { opacity: 1; }

.wf-node__live-act {
    flex-shrink: 0;
    width: 1.6rem;
    height: 1.6rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    color: var(--text-subtle);
    transition: background var(--transition), color var(--transition);
}

@media (hover: hover) {
    .wf-node__live-act:hover { background: var(--surface-strong); color: var(--text-main); }
    .wf-node__live-act--danger:hover { background: var(--danger-bg, var(--surface-strong)); color: var(--danger); }
}

/* ── Канвас-ноды ввода: Текст / Файл / Заметка ── */
.wf-canvas-host .drawflow .drawflow-node:has(.wf-node--input),
.wf-canvas-host .drawflow .drawflow-node:has(.wf-node--note) {
    width: 230px;
}

.wf-node--input {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.6rem 0.65rem;
}

.wf-node--input .wf-node__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.wf-node--input .wf-node__title {
    flex: 1;
    min-width: 0;
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.wf-node__input-text,
.wf-node__note-text {
    width: 100%;
    resize: none;
    border: none;
    outline: none;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    padding: 0.45rem 0.55rem;
    background: var(--surface-soft);
    color: var(--text-main);
    font-size: var(--text-2xs);
    line-height: var(--leading-normal);
    font-family: inherit;
}

.wf-node__input-text::placeholder,
.wf-node__note-text::placeholder { color: var(--text-muted); }

/* Заметка — стикер: только поле, без шапки/портов, мягкий акцент. */
.wf-node--note { padding: 0.4rem; }
.wf-node__note-text {
    background: var(--surface-soft);
    min-height: 4rem;
}

/* Файл — превью загруженного медиа или кнопка загрузки. */
.wf-node__file {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.wf-node__file-upload {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    min-height: 3.5rem;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    border: 0;
    background: var(--surface-soft);
    color: var(--text-subtle);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-semibold);
    transition: background var(--transition), color var(--transition);
}

.wf-node__file-media {
    display: block;
    width: 100%;
    max-height: 9rem;
    object-fit: contain;
    border-radius: var(--radius-sm);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
}

.wf-node__file-audio { width: 100%; }

.wf-node__file-replace {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    max-width: 100%;
    padding: 0.25rem 0.4rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-soft);
    color: var(--text-subtle);
    font-size: var(--text-2xs);
}

.wf-node__file-replace span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (hover: hover) {
    .wf-node__file-upload:hover { background: var(--surface-strong); color: var(--text-main); }
    .wf-node__file-replace:hover { background: var(--surface-strong); color: var(--text-main); }
}

/* ══ Мобильный контракт list⇄detail — ОБЩИЙ ПРИМИТИВ (полный контракт — в
   copilot-instructions «Мобильный контракт list⇄detail»; эталон — чаты).
   Список (aside) несёт .shell-list-pane + модификаторы состояния; деталь —
   следующий сиблинг .sidebar-page. Слои ПРОЗРАЧНЫЕ (фон рисует body), деталь
   слайдится поверх, список при открытой детали прячется visibility. Гейт
   первого кадра --nav-ready взводит JS через rAF после первого рендера.
   position/z-index задаются ЗДЕСЬ, а не утилитами relative/z-* на aside
   (tailwind позже styles.css + z-утилиты с !important — перебьют). Каскад
   карточек на возврате — ремаунтом списка (x-if-гейт shouldMount*), не CSS.
   Блок стоит НИЖЕ базовых правил панелей (.shell-secondary-panel и т.п.,
   position:relative) — одноклассовый layout-селектор выигрывает порядком. ══ */
@media (max-width: 767.98px) {
    .shell-list-pane {
        width: 100%;
        flex: 1 1 auto;
        border-radius: 0;
        box-shadow: none;
        position: absolute;
        inset: 0;
        z-index: 1;
    }
    /* Деталь = сиблинг .sidebar-page (страницы шелла) либо любой сиблинг с
       явным классом .shell-detail-pane (двухпанельные страницы вне шелла —
       поддержка/админ-инбокс). */
    .shell-list-pane ~ :is(.sidebar-page, .shell-detail-pane) {
        position: absolute;
        inset: 0;
        z-index: 2;
    }
    .shell-list-pane.shell-list-pane--nav-ready ~ :is(.sidebar-page, .shell-detail-pane) {
        transition: transform var(--motion-duration-base) var(--motion-ease-premium);
        will-change: transform;
    }
    /* Деталь закрыта — экран уведён вправо за кадр (зеркало .tg-content-hidden). */
    .shell-list-pane:not(.shell-list-pane--detail-open) ~ :is(.sidebar-page, .shell-detail-pane) {
        transform: translateX(100%);
        pointer-events: none;
    }
    /* Деталь открыта — список спрятан (зеркало .tg-sidebar-mobile-hidden). */
    .shell-list-pane.shell-list-pane--detail-open {
        visibility: hidden;
        pointer-events: none;
    }
}

/* position/z-index — здесь, не утилитами relative/z-sidebar на <aside> (см.
   контракт list⇄detail: утилиты перебивали бы мобильный absolute-слайд).
   Только ≥768: на мобиле position/z даёт примитив .shell-list-pane выше. */
@media (min-width: 768px) {
    .wf-sidebar {
        position: relative;
        z-index: var(--z-sidebar);
    }
}

@media (max-width: 767.98px) {
    /* Мобильная механика «список ⇄ редактор» — общий примитив .shell-list-pane
       (контракт list⇄detail): слайд редактора поверх, visibility-скрытие списка,
       ремаунт-каскад строк. Прежний display:none-toggle переключал экраны без
       анимации. Классы состояния вешает _sidebar_workflows.html
       (--detail-open при открытом редакторе И при пустом списке-герое). */

    /* Мобильный тулбар = бейдж статуса + «Запустить» по центру снизу (зона
       большого пальца); назад/действия живут в компактном хедере. */
    .wf-topbar {
        top: auto;
        left: var(--shell-page-gutter);
        right: var(--shell-page-gutter);
        bottom: calc(var(--composer-edge-gap) + var(--composer-sab));
        justify-content: center;
    }

    /* Панель — нижняя шторка под компактным хедером. */
    .wf-panel {
        top: auto;
        left: var(--shell-page-gutter);
        right: var(--shell-page-gutter);
        bottom: 0.5rem;
        width: auto;
        max-height: calc(100dvh - var(--shell-mobile-header-offset) - 1.5rem);
    }
}

/* ===== Транскрипция (/transcription) ===== */

/* Композер — absolute-overlay поверх ленты (как чат/медиа): лента скроллится
   ПОД ним, а не обрезается у его верха. Высоту пишет ResizeObserver
   (transcriptionApp) в --composer-height; лента резервирует её снизу.
   Обёртка прозрачна и pointer-events:none — wheel/touch проходят к ленте позади;
   видимые контролы (пилюли + поле) получают pointer-events:auto. */
.transcribe-content { --composer-height: 0px; }
.transcribe-thread-scroll { padding-bottom: var(--composer-height); }
.transcribe-thread-scroll > .transcribe-thread-content { padding-top: 0; }
.transcribe-composer-wrap {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 5;
    pointer-events: none;
}
.transcribe-composer-wrap > * { pointer-events: auto; }

@media (max-width: 767px) {
    /* Те же равные минимальные отступы плавающей пилюли, что у остальных композеров
       (перебиваем tailwind px-3/pb-4 из шаблона специфичностью 0,2,0). pt-1 не трогаем. */
    .transcribe-content .transcribe-composer-wrap {
        padding-inline: var(--composer-edge-gap);
        padding-bottom: calc(var(--composer-edge-gap) + var(--composer-sab));
    }
}

/* Сегмент-пилюли выбора модели (в композере чата) */
.transcribe-models {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    padding: 0.25rem;
    /* Стекло как у нижнего композера (.chat-input-shell) — лента скроллится
       под контейнером пилюль, поэтому фон полупрозрачный с блюром, не сплошной. */
    background-color: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
}
.transcribe-model {
    padding: 0.5rem 1.1rem;
    border: none;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    color: var(--text-muted);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    cursor: pointer;
    transition: background-color var(--transition), color var(--transition);
}
@media (hover: hover) {
    .transcribe-model:hover { color: var(--text-main); }
}
.transcribe-model.is-active {
    background: var(--surface-strong);
    color: var(--text-main);
}

/* Компактные пилюли модели в чат-композере */
.transcribe-models--sm { padding: 0.18rem; }
.transcribe-models--sm .transcribe-model {
    padding: 0.32rem 0.8rem;
    font-size: var(--text-xs);
}

/* ── Сайдбар истории тредов ── каркас/ширина/скругление/стекло стандартные
   (shell-secondary-panel + sidebar-inset, вынесен ВНЕ <main> как остальные
   сайдбары); внутренняя раскладка — Tailwind-классами на <aside>, но position/
   z-index — ЗДЕСЬ: утилиты relative/z-sidebar (tailwind после styles.css,
   z-sidebar ещё и !important) перебивали мобильный absolute-слайд list⇄thread. */
.transcribe-shell { position: relative; }
.transcribe-sidebar {
    position: relative;
    z-index: var(--z-sidebar);
}
.transcribe-sidebar__list {
    /* Shared edge fading must preserve the space below the overlay header. */
    --scroll-edge-space-start: calc(var(--shell-mobile-header-offset, 0px) + 0.75rem);
    --scroll-edge-space-end: 0.75rem;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    /* padding-top включает offset мобильного shell-хедера (на десктопе offset = 0).
       Свой shorthand-padding иначе затирал бы .app-with-overlay-header. */
    padding: calc(var(--shell-mobile-header-offset, 0px) + 0.75rem) 0.5rem 0.75rem;
}
.transcribe-sidebar__footer {
    flex-shrink: 0;
    padding: 0.75rem;
}
.transcribe-sidebar__del {
    background: none;
    border: none;
    cursor: pointer;
    transition: color var(--transition), background-color var(--transition);
}
@media (hover: hover) {
    .transcribe-sidebar__del:hover {
        color: var(--text-main);
        background: var(--surface-soft);
    }
}

/* Мобайл: список ⇄ тред — единый принцип list⇄detail (как чат/саппорт):
   оба слоя absolute в .app-shell-body (он position:relative на мобиле, см.
   tg-блок), тред слайдит ПОВЕРХ списка transform'ом. Прежний display-toggle
   переключал панели без анимации. Гейт .transcribe-nav-ready взводится в init
   (rAF после первого рендера) — стартовый вид без «проезда», первый переход
   уже анимирован. */
@media (max-width: 767.98px) {
    .transcribe-sidebar {
        width: 100%;
        flex: 1 1 auto;
        border-radius: 0;
        box-shadow: none;
        position: absolute;
        inset: 0;
        z-index: 1;
    }
    /* Тред едет поверх списка. Фона нет — как у окна чата: слои прозрачные,
       фон (ватермарк) рисует body; список при открытом треде прячется
       visibility (см. ниже, зеркало .tg-sidebar-mobile-hidden), перекрытие в
       момент слайда «назад» маскирует каскад строк (стартуют с opacity:0). */
    .transcribe-sidebar ~ .sidebar-page {
        position: absolute;
        inset: 0;
        z-index: 2;
    }
    .transcribe-sidebar.transcribe-nav-ready ~ .sidebar-page {
        transition: transform var(--motion-duration-base) var(--motion-ease-premium);
        will-change: transform;
    }
    /* Режим списка: тред уезжает вправо. */
    .transcribe-sidebar:not(.transcribe-sidebar--thread-open) ~ .sidebar-page {
        transform: translateX(100%);
        pointer-events: none;
    }
    /* Режим треда: список спрятан (как .tg-sidebar-mobile-hidden у чатов). */
    .transcribe-sidebar.transcribe-sidebar--thread-open {
        visibility: hidden;
        pointer-events: none;
    }
}

/* Прикреплённое вложение в композере (ждёт отправки) — без обёртки-контейнера.
   Аудио → редактор волны, видео → кастомный плеер (оба в .transcribe-staged__fill);
   сырые <audio>/<video> убраны. */
.transcribe-staged {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}
/* Обёртка плеера/редактора в staged-области (аудио-волна или видео-плеер) —
   тянется на свободную ширину, × остаётся справа. min-width:0 — чтобы canvas/
   видео корректно ужимались. */
.transcribe-staged__fill { flex: 1; min-width: 0; }

/* Плавное разворачивание прикреплённого вложения (grid-трюк, как в композере) */
.transcribe-collapse {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows var(--motion-duration-base) var(--motion-ease-premium);
}
.transcribe-collapse.is-open {
    grid-template-rows: 1fr;
}
.transcribe-collapse__inner {
    overflow: hidden;
    min-height: 0;
}

/* Пилюля стоимости рядом с кнопкой отправки */
.transcribe-cost-pill {
    flex-shrink: 0;
    padding: 0.25rem 0.7rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-strong);
    color: var(--text-main);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    white-space: nowrap;
}
.transcribe-staged__del {
    flex-shrink: 0;
    width: 2rem;
    height: 2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-muted);
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    transition: color var(--transition), background-color var(--transition);
}
@media (hover: hover) {
    .transcribe-staged__del:hover {
        color: var(--text-main);
        background: var(--surface-strong);
    }
}

/* Текст распознанного сообщения */
.transcribe-msg-text {
    white-space: pre-wrap;
    word-break: break-word;
    font-size: var(--text-sm);
    line-height: var(--leading-relaxed);
    color: var(--text-main);
}

/* ============================================================
   Конструктор компонентов/сайтов (/builder)
   ============================================================ */
/* +safe-area снизу под сеткой библиотеки (env=0 вне iOS → тот же pb-16=4rem).
   Двойной класс перебивает tailwind-утилиту pb-16 (она позже в каскаде). */
.builder-page.builder-page {
    padding-bottom: calc(4rem + var(--safe-area-bottom, 0px));
}

.builder-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 1rem;
}

.builder-card {
    display: flex;
    flex-direction: column;
    background: var(--bg-elevated);
    border: 0;
    border-radius: var(--radius-lg, 0.75rem);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    transition: border-color var(--transition);
}
.builder-card:hover {
    border-color: transparent;
}

.builder-card-frame {
    position: relative;
    height: 160px;
    background: var(--surface-paper);
    cursor: pointer;
    overflow: hidden;
    border-bottom: 0;
}
.builder-card-preview {
    width: 100%;
    height: 100%;
    border: 0;
    pointer-events: none;     /* клики идут на карточку (открыть редактор) */
    background: var(--surface-paper);
}
.builder-card-busy {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--bg-panel) 65%, transparent);
}

.builder-card-body {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.625rem 0.75rem;
}

.builder-badge {
    font-size: var(--text-2xs);
    padding: 0.1rem 0.4rem;
    border-radius: var(--radius-sm, 0.375rem);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-raised);
    color: var(--text-muted);
    white-space: nowrap;
}
.builder-badge--soft {
    background: var(--surface-soft);
    color: var(--text-main);
}

.builder-card-ai {
    padding: 0.625rem 0.75rem;
    border-top: 0;
    background: var(--bg-panel);
}

.builder-input {
    width: 100%;
    background: var(--bg-panel);
    border: 0;
    border-radius: var(--radius-md, 0.5rem);
    corner-shape: var(--corner-shape-surface);
    padding: 0.4rem 0.6rem;
    color: var(--text-main);
    font-size: var(--text-sm);
}
.builder-input:focus {
    outline: none;
    border-color: transparent;
}

.builder-toolbar {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0.875rem;
    border-bottom: 0;
    background: var(--bg-panel);
}
.builder-name { flex: 0 1 260px; font-weight: var(--font-weight-semibold); }
.builder-select { flex: 0 0 auto; width: auto; }

.builder-editor {
    flex: 1;
    display: grid;
    grid-template-columns: 1fr 1fr;
    min-height: 0;
    overflow: hidden;
}
.builder-pane {
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding: 0.75rem;
    overflow: hidden;
}
.builder-pane--code { border-right: 0; }
.builder-pane-label {
    font-size: var(--text-xs);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    margin-bottom: 0.35rem;
}
.builder-code {
    width: 100%;
    flex: 1;
    min-height: 80px;
    resize: none;
    background: var(--bg-panel);
    border: 0;
    border-radius: var(--radius-md, 0.5rem);
    corner-shape: var(--corner-shape-surface);
    padding: 0.6rem;
    color: var(--text-main);
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
}
.builder-code--css { flex: 0 0 34%; }

.builder-preview-host {
    flex: 1;
    min-height: 0;
    border: 0;
    border-radius: var(--radius-md, 0.5rem);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    background: var(--surface-paper);
}
.builder-preview-frame {
    width: 100%;
    height: 100%;
    border: 0;
    background: var(--surface-paper);
}
.builder-ai {
    margin-top: 0.625rem;
    padding-top: 0.625rem;
    border-top: 0;
}

.builder-spin {
    display: inline-block;
    animation: spin-360 var(--motion-period-spinner) var(--motion-ease-linear) infinite;
}

/* Переключатель Код/Визуально + холст GrapesJS (Фаза 2) */
.builder-modeswitch {
    display: inline-flex;
    gap: 2px;
    padding: 2px;
    background: var(--bg-elevated);
    border: 0;
    border-radius: var(--radius-md, 0.5rem);
    corner-shape: var(--corner-shape-surface);
}
.builder-modeswitch button {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.3rem 0.6rem;
    border-radius: var(--radius-sm, 0.375rem);
    corner-shape: var(--corner-shape-surface);
    font-size: var(--text-xs);
    color: var(--text-muted);
    transition: background var(--transition), color var(--transition);
}
.builder-modeswitch button.is-active {
    background: var(--bg-raised);
    color: var(--text-main);
}

.builder-gjs-wrap {
    flex: 1;
    min-height: 0;
    display: flex;
}
.builder-gjs-host {
    --gjs-main-font: var(--font-sans);
    --gjs-font-size: var(--text-sm);
    --gjs-font-size-s: var(--text-xs);
    flex: 1;
    min-height: 0;
    width: 100%;
}
.builder-card-frame--site {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-elevated);
    cursor: pointer;
}

/* Импорт из OpenPencil — модалка (Фаза 4) */
.builder-modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: var(--modal-backdrop);
}
.builder-modal {
    width: 100%;
    max-width: 640px;
    max-height: calc(100dvh - 2rem);
    overflow-y: auto;
    background: var(--bg-elevated);
    border: 0;
    border-radius: var(--radius-lg, 0.75rem);
    corner-shape: var(--corner-shape-surface);
    padding: 1.25rem;
    box-shadow: var(--shadow-modal);
}
/* Публикация на сабдомене (Фаза 5) */
.builder-slug-row { display: flex; align-items: stretch; }
.builder-slug-row .builder-input {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}
.builder-slug-suffix {
    display: flex;
    align-items: center;
    padding: 0 0.6rem;
    background: var(--bg-raised);
    color: var(--text-muted);
    border: 0;
    border-left: 0;
    border-radius: 0 var(--radius-md, 0.5rem) var(--radius-md, 0.5rem) 0;
    corner-shape: var(--corner-shape-surface);
    font-size: var(--text-sm);
    white-space: nowrap;
}
.builder-publish-live {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.55rem 0.7rem;
    background: var(--bg-panel);
    border: 0;
    border-radius: var(--radius-md, 0.5rem);
    corner-shape: var(--corner-shape-surface);
    min-width: 0;
}
.builder-live-dot {
    width: 7px;
    height: 7px;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: var(--primary-500);
}

/* Свой домен (Фаза 6): секция в модалке публикации */
.builder-domain {
    border-top: 0;
    padding-top: 0.9rem;
}
.builder-domain-dns {
    margin-top: 0.5rem;
    padding: 0.55rem 0.7rem;
    background: var(--bg-panel);
    border-radius: var(--radius-md, 0.5rem);
    corner-shape: var(--corner-shape-surface);
}
.builder-domain-dns code {
    color: var(--text-main);
    background: var(--bg-raised);
    padding: 0.05rem 0.32rem;
    border-radius: var(--radius-sm, 0.375rem);
    corner-shape: var(--corner-shape-surface);
    font-size: var(--text-2xs);
}

@media (max-width: 767.98px) {
    .builder-editor { grid-template-columns: 1fr; overflow-y: auto; }
    .builder-pane--code { border-right: 0; border-bottom: 0; }
    .builder-name { flex: 1 1 auto; }
}

/* === ЧАТ ТЕХПОДДЕРЖКИ (пользовательская сторона /support) === */
.support-page {
    display: grid;
    grid-template-columns: 300px 1fr;
    gap: var(--shell-page-gap);
    height: 100%;
    min-height: 0;
    /* The shared scroller reserves the header above both columns, including
       the ticket list underneath a full-width player. */
    padding: 0 var(--shell-page-gutter) var(--shell-page-gap);
}
.support-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-height: 0;
    overflow-y: auto;
}
/* Кнопка «Новое обращение» закреплена вверху списка при прокрутке (тикеты уезжают
   под неё; кнопка непрозрачная — CTA-градиент, поэтому перекрывает). */
.support-new-btn { width: 100%; position: sticky; top: 0; z-index: 2; flex-shrink: 0; }
.support-ticket {
    text-align: left;
    padding: 0.75rem;
    border-radius: var(--radius-base);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-elevated);
    cursor: pointer;
    border: none;
    color: var(--text-main);
}
.support-ticket.is-active { background: var(--bg-raised); }
.support-ticket__row { display: flex; align-items: baseline; gap: 0.5rem; }
.support-ticket__subject { font-weight: var(--font-weight-semibold); font-size: var(--text-sm); flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.support-ticket__time { flex-shrink: 0; font-size: var(--text-2xs); color: var(--text-subtle); }
.support-ticket__preview { margin-top: 0.15rem; font-size: var(--text-xs); color: var(--text-subtle); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.support-ticket__meta { font-size: var(--text-xs); color: var(--text-subtle); display: flex; gap: 0.5rem; align-items: center; margin-top: 0.35rem; }
.support-unread-dot { width: 8px; height: 8px; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round); background: var(--primary-500); display: inline-block; }

/* Единый чат поддержки (.sup-*) — общий для клиента (/support) и оператора (админка). */
/* Без коробки-контейнера: чат flush с фоном страницы, как AI-чат. На /support фон
   страницы виден сквозь; в админке карточку даёт .admin-card.sup-chat (см. admin.css). */
.sup-chat {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}
.sup-chat__inner { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.sup-chat__head {
    padding: 0.85rem 1rem;
    border-bottom: 0;
}
.sup-chat__head--admin { display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; }
/* Пользовательская шапка: кнопка «назад» (мобильный) + заголовок/поле темы. */
.sup-chat__head--user { display: flex; align-items: center; gap: 0.6rem; }
.sup-chat__head--user .sup-subject,
.sup-chat__head--user .sup-chat__title { width: auto; flex: 1 1 auto; min-width: 0; }
.sup-back {
    flex: 0 0 auto;
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border: none; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round);
    background: var(--bg-elevated); color: var(--text-main);
    cursor: pointer; font-size: var(--text-lg); line-height: var(--leading-none);
    transition: background var(--transition);
}
.sup-back:hover { background: var(--bg-raised); }
.sup-chat__title { font-weight: var(--font-weight-semibold); display: flex; align-items: center; gap: 0.6rem; }
.sup-chat__sub { font-size: var(--text-xs); }
.sup-status-pill { font-size: var(--text-2xs); padding: 0.1rem 0.55rem; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); background: var(--bg-raised); color: var(--text-muted); font-weight: var(--font-weight-medium); }
.sup-subject { width: 100%; }
.sup-admin-controls { display: flex; gap: 0.5rem; align-items: center; }

.sup-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 1.25rem 1rem; }

.sup-system {
    font-size: var(--text-xs); color: var(--text-subtle);
    background: var(--bg-raised); padding: 0.25rem 0.85rem; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round);
    text-align: center;
}

.sup-typing { display: flex; align-items: center; gap: 0.5rem; color: var(--text-subtle); font-size: var(--text-sm); }
.sup-typing__dots { display: inline-flex; gap: 3px; }
.sup-typing__dots span { width: 6px; height: 6px; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round); background: var(--text-subtle); animation: sup-typing-bounce var(--motion-period-pulse) var(--motion-ease-ambient) infinite; }
.sup-typing__dots span:nth-child(2) { animation-delay: calc(var(--motion-period-pulse) * 0.125); }
.sup-typing__dots span:nth-child(3) { animation-delay: calc(var(--motion-period-pulse) * 0.25); }
@keyframes sup-typing-bounce {
    0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
    30% { opacity: 1; transform: translateY(-3px); }
}

/* Вложения в пузыре: картинки через .chat-msg-attachment-thumb (класс чата), файлы — чип. */
.sup-att { display: block; color: inherit; text-decoration: none; }
.sup-att__file { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.4rem 0.65rem; background: rgba(127,127,127,0.18); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); font-size: var(--text-sm); }

/* Композер — пилюля на классе чата chat-input-shell + shape-pill (см. _support_chat_body). */
/* Композер в потоке (снизу колонки), СТАБИЛЬНО: без оверлея/ResizeObserver/динамического
   паддинга — раньше это дёргало поле при отправке. Отступы как у стандартного дока:
   верх 1rem, бок --app-gutter-x, низ = десктопный frame-inset / мобильная safe-area;
   на мобиле — общие отступы плавающих композеров. */
.sup-composer-dock { padding: 1rem var(--app-gutter-x) 0; }
@media (min-width: 768px) {
    .sup-composer-dock { padding-bottom: var(--app-frame-inset-desktop); }
}
@media (max-width: 767.98px) {
    .sup-composer-dock {
        padding-inline: var(--composer-edge-gap);
        padding-bottom: calc(var(--composer-edge-gap) + var(--composer-sab));
    }
    .sup-composer-dock > .max-w-3xl { max-width: 100%; padding-inline: 0; }
}
/* Сообщения прижаты к низу ленты (к полю) — при малом числе нет пустого разрыва, при
   переполнении лента прокручивается штатно. margin-top:auto (а не justify-content:
   flex-end, который режет верх при скролле). Только пользовательская сторона. */
.support-page .sup-scroll { display: flex; flex-direction: column; }
.support-page .sup-scroll > * { margin-top: auto; }
.sup-composer-pill { display: flex; align-items: flex-end; gap: 0.25rem; padding: 0.3rem; }
/* The shared input sizer grows support drafts to the same seven-line cap. */
.sup-input { padding: 0.55rem 0.4rem; max-height: 174px; max-height: calc(7lh + 1.1rem); overflow-y: auto; color: var(--text-main); }
.sup-input::placeholder { color: color-mix(in srgb, var(--text-muted) 60%, transparent); }

.sup-pending-thumb { position: relative; background: var(--bg-raised); }
.sup-pending-thumb__del {
    position: absolute; top: 2px; right: 2px;
    width: 20px; height: 20px; display: grid; place-items: center;
    border: none; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round);
    background: var(--overlay-pill-bg); color: var(--overlay-text); cursor: pointer;
}
.support-empty { margin: auto; color: var(--text-subtle); text-align: center; padding: 2rem; }

/* Приветствие + быстрые темы в пустом окне нового обращения. */
.sup-intro { width: 100%; max-width: 48rem; margin: 0 auto; padding: 1.25rem 1rem 0; }
.sup-intro__greeting { display: flex; gap: 0.75rem; align-items: flex-start; }
.sup-intro__icon {
    flex: 0 0 auto; width: 2.25rem; height: 2.25rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round); background: var(--bg-elevated); color: var(--text-main); font-size: var(--text-lg);
}
.sup-intro__title { font-weight: var(--font-weight-semibold); margin-bottom: 0.15rem; }
.sup-intro__text { font-size: var(--text-sm); color: var(--text-subtle); line-height: var(--leading-normal); }
.sup-intro__topics { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.85rem; }
.sup-topic-chip {
    padding: 0.35rem 0.85rem; border: none; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round);
    background: var(--bg-elevated); color: var(--text-main);
    font-size: var(--text-sm); cursor: pointer; transition: background var(--transition);
}
.sup-topic-chip:hover { background: var(--bg-raised); }
.sup-topic-chip.is-active { background: color-mix(in srgb, var(--primary-500) 20%, var(--bg-elevated)); }

@media (max-width: 767.98px) {
    /* Слайд «история → чат» — общий примитив .shell-list-pane (контракт
       list⇄detail, механика чатов 1:1): слои прозрачные, чат слайдится поверх,
       список прячется visibility. Классы вешают support.html и
       admin/support_inbox.html; здесь — только посадка контейнера/паддинги. */
    .support-page { position: relative; padding: 0; grid-template-columns: 1fr; }
    .support-list { padding: 0 var(--shell-page-gutter) var(--shell-page-gap); max-height: none; }
}

/* Кнопка «Поддержка» в футере рейла — справа от триггера «Профиль».
   align-items:stretch → кружок берёт высоту пузыря «Профиль» (какой бы она ни
   была), aspect-ratio:1 держит его квадратным → radius-pill даёт ровный круг
   той же высоты. Так они всегда одной высоты и выровнены по ширине контейнера. */
.shell-rail__profile-row { display: flex; align-items: stretch; gap: 0.5rem; }
.shell-rail__profile-row .shell-rail__profile-trigger { flex: 1 1 auto; min-width: 0; }
.shell-rail__support-btn {
    flex: 0 0 auto;
    /* Ровный квадрат размером со слот рейла = высоте пузыря «Профиль» (36px).
       aspect-ratio на flex-элементе не давал квадрат (ширина падала до размера
       глифа ~19px → «сжатая» иконка), поэтому задаём обе стороны явно. */
    width: var(--shell-rail-slot-size);
    height: var(--shell-rail-slot-size);
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--bg-elevated);
    color: var(--text-muted);
    text-decoration: none;
    font-size: var(--text-xl);
    line-height: var(--leading-none);
    transition: background var(--transition), color var(--transition);
}
.shell-rail__support-btn { position: relative; }
.shell-rail__support-btn > i { display: block; line-height: var(--leading-none); }
.shell-rail__support-btn:hover { background: var(--bg-raised); color: var(--text-main); }
/* Бейдж непрочитанного — точка в углу кнопки. */
.shell-rail__support-badge {
    position: absolute; top: 4px; right: 4px;
    width: 9px; height: 9px; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round);
    background: var(--primary-500);
    box-shadow: none;
}
/* Активная страница — только заливкой, без акцентного цвета (в тон нейтральному
   пузырю «Профиль», а не фирменной ирис-пилюлей). */
.shell-rail__support-btn.is-active { background: var(--bg-raised); color: var(--text-main); }

/* reduced-motion: гейт-слайды list⇄detail (чат/музыка/поддержка)
   мгновенны, без transition. Эти транзишены взводятся
   JS-классами (*-nav-ready) уже ПОСЛЕ первого кадра,
   поэтому глушим именно их — функциональные grid-коллапсы композера не
   трогаем. Блок в конце файла: при равной специфичности с правилами-взводами
   побеждает каскадом. */
@media (prefers-reduced-motion: reduce) {
    .app-root[data-page-category='music'] .media-page.music-nav-ready .generation-result-area,
    .app-root[data-page-category='music'] .media-page.music-nav-ready .chat-input-docked,
    .app-shell-body.mobile-nav-ready > .sidebar-page,
    .transcribe-sidebar.transcribe-nav-ready ~ .sidebar-page,
    .shell-list-pane.shell-list-pane--nav-ready ~ :is(.sidebar-page, .shell-detail-pane) {
        transition: none;
    }
}

/* ═══════════════ Индикатор офлайна ═══════════════
   Плавающая пилюля, а НЕ in-flow баннер: body — flex-column 100vh, и второй
   in-flow баннер сдавил бы контент (та же ловушка, что у промо-баннера).
   Состояние держит Alpine.store('net'); атрибут [data-offline] на <html> ставит
   OfflineService — по нему же гасятся действия, требующие сети. */
.offline-pill {
    position: fixed;
    left: 50%;
    top: calc(env(safe-area-inset-top, 0px) + 0.75rem);
    z-index: var(--z-dropdown);
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: calc(var(--gap-sm) * 1.5) calc(var(--gap-sm) * 2);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--chat-input-bg);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    color: var(--text-main);
    box-shadow: var(--shadow-glass);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
    width: max-content;
    max-width: calc(100vw - 1.5rem);
    box-sizing: border-box;
    line-height: var(--leading-normal);
    text-align: center;
    pointer-events: none;
    /* Скрыт по умолчанию: показывается только при [data-offline]. Уводим ВВЕРХ
       за кадр, а не в display:none — иначе появление нельзя анимировать. */
    transform: translate(-50%, calc(-100% - 1.5rem));
    opacity: 0;
    transition: transform var(--motion-duration-base) var(--motion-ease-premium),
                opacity var(--motion-duration-base) var(--motion-ease-premium);
}

/* Промо-баннер лежит в потоке и держит верх страницы: пилюля обязана встать под
   ним, иначе перекрывает его текст. #global-announcement рендерится только когда
   анонс активен, поэтому смещение вешаем через :has, а не безусловно. */
body:has(#global-announcement) .offline-pill {
    top: calc(env(safe-area-inset-top, 0px) + var(--announcement-height) + 0.75rem);
}

[data-offline] .offline-pill {
    transform: translate(-50%, 0);
    opacity: 1;
}

.offline-pill__dot {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--text-muted);
    flex-shrink: 0;
}

/* Действия, которым нужна сеть: гасим, пока её нет. Курсор и клики снимает
   сам disabled — здесь только визуал. */
[data-offline] [data-requires-network] {
    opacity: 0.4;
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    .offline-pill { transition: none; }
}

/* ============================================================================
   LANDING — публичный SEO-лендинг (гостевой «/», templates/landing.html).
   Полностью на токенах, без бордеров (иерархия — заливкой/тенью/типографикой).
   ========================================================================== */

.landing-page {
    display: block;
    scroll-behavior: smooth;
    /* Страховка от горизонтального скролла: декоративные full-bleed слои
       (лента, свечения, marquee) не должны растягивать скролл-контейнер. */
    overflow-x: clip;
    /* Ширина контентной колонки и fluid-поля — страница дышит на широких
       экранах; мобильные карусели блидят до края через ту же переменную.
       Колонка флексом растягивается по ширине экрана и фиксируется на
       огромных мониторах (кап 104rem). */
    --landing-max: min(94vw, 104rem);
    --landing-pad: clamp(1.25rem, 4vw, 4rem);
    /* Высота sticky-шапки: карусель наверху уезжает под неё этим значением,
       чтобы верхний край изображений сразу оказался под стеклом и блюрился. */
    --landing-header-h: 4.5rem;
}

/* --- Шапка: sticky-стекло (блюрит карусель под собой сразу, без скролла) --- */
.landing-header {
    position: sticky;
    top: 0;
    z-index: 40;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.85rem 1.25rem;
    background: var(--chat-input-bg);
    backdrop-filter: blur(var(--glass-blur));
    transition: background var(--motion-duration-base) var(--motion-ease-standard),
                box-shadow var(--motion-duration-base) var(--motion-ease-standard);
}

.landing-header.is-scrolled {
    box-shadow: var(--shadow-glass);
}

.landing-header__nav {
    display: none;
    align-items: center;
    gap: 1.5rem;
}

.landing-header__nav a {
    color: var(--text-muted);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    transition: color var(--motion-duration-fast) var(--motion-ease-standard);
}

.landing-header__nav a:hover { color: var(--text-main); }

/* Правая группа действий: приглушённый «Войти» + акцентный CTA (как в примерах). */
.landing-header__actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-shrink: 0;
}

.landing-header__login {
    color: var(--text-muted);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    padding: 0.5rem 0.85rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: transparent;
    transition: color var(--motion-duration-fast) var(--motion-ease-standard),
                background var(--motion-duration-fast) var(--motion-ease-standard);
}

.landing-header__login:hover {
    color: var(--text-main);
    background: var(--surface-soft);
}

.landing-header__cta {
    padding: 0.5rem 1.15rem;
    font-size: var(--text-sm);
    font-weight: var(--font-weight-bold);
}

@media (min-width: 768px) {
    .landing-header { padding: 1rem 2rem; }
    .landing-header__nav { display: flex; }
    .landing-header__cta { padding: 0.55rem 1.4rem; }
}

/* Мобильная шапка: сжимаем словесный знак и действия, чтобы CTA
   «Начать бесплатно» не срезался за правым краем на узких экранах. */
@media (max-width: 767.98px) {
    .landing-header {
        padding: 0.7rem 1rem;
        gap: 0.5rem;
    }
    .landing-header .brand-wordmark { height: 1.3rem; }
    .landing-header__actions { gap: 0.35rem; }
    .landing-header__login { padding: 0.45rem 0.6rem; }
    .landing-header__cta {
        padding: 0.5rem 0.9rem;
        font-size: var(--text-xs);
    }
}

/* Самые узкие экраны: дублирующий «Войти» скрываем — CTA ведёт
   в то же окно авторизации, где есть вход. */
@media (max-width: 430px) {
    .landing-header__login { display: none; }
}

/* --- Общие элементы секций --- */
.landing-section,
.landing-hero,
.landing-final {
    max-width: var(--landing-max);
    margin: 0 auto;
    padding: clamp(3.5rem, 9vh, 7rem) var(--landing-pad) 0;
}

.landing-eyebrow {
    font-family: var(--font-display);
    font-size: var(--text-xs);
    font-weight: var(--font-weight-display);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 0.85rem;
}

.landing-h2 {
    font-size: var(--text-title);
    font-weight: var(--font-weight-display);
    line-height: var(--leading-display);
    letter-spacing: var(--tracking-normal);
    /* Тот же серо-белый градиент, что над композером (.hero-title / markdown h1). */
    background-image: var(--heading-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

.landing-section__lead {
    margin-top: 1rem;
    max-width: 38rem;
    color: var(--text-muted);
    font-size: var(--text-base);
    line-height: var(--leading-normal);
}

.landing-section__actions {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
    margin-top: 2rem;
}

.landing-cta-main {
    padding: 0.9rem 2.25rem;
    font-weight: var(--font-weight-bold);
    font-size: var(--text-base);
}

.landing-attribution {
    font-size: var(--text-xs);
    color: var(--text-subtle);
}

/* --- 01 Hero --- */
/* Мобайл и десктоп используют одну композицию: галерея лежит фоном под
   композером, а бегущая строка остаётся у нижнего края hero. */
.landing-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    text-align: center;
    padding-top: clamp(1.5rem, 4vh, 3rem);
    padding-bottom: clamp(0.75rem, 2vh, 1.5rem);
    gap: clamp(1.5rem, 4vh, 2.5rem);
}

/* Общий showcase-backdrop для hero и /login. Позиционирование слоя едино,
   full-bleed-смещение нужно только внутри ограниченного landing hero. */
.showcase-backdrop {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 100%;
    max-width: none;
    height: auto;
    margin: 0;
    z-index: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    pointer-events: none;
}
.landing-hero > .showcase-backdrop {
    left: calc(50% - 50vw);
    width: 100vw;
}
/* Два scrim-слоя складываются по альфе. Значения ниже дают около 83% общего
   затемнения в центре вместо прежних 95%, поэтому фото читаются, а стекло
   композера по-прежнему отделяет текст от изображения. */
.showcase-backdrop::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 1;
    background:
        radial-gradient(68% 62% at 50% 52%,
            color-mix(in srgb, var(--bg-app) 76%, transparent),
            color-mix(in srgb, var(--bg-app) 52%, transparent) 58%,
            color-mix(in srgb, var(--bg-app) 24%, transparent) 100%),
        linear-gradient(to bottom,
            color-mix(in srgb, var(--bg-app) 44%, transparent),
            color-mix(in srgb, var(--bg-app) 20%, transparent) 32%,
            color-mix(in srgb, var(--bg-app) 56%, transparent));
}

/* Десктоп: hero = ровно первый экран, слоями. Галерея — затемнённый фон на
   весь hero, композер наслаивается поверх по центру, бегущая строка снизу.
   Высота = 100% скролл-контейнера (а не 100svh), поэтому hero сам
   подстраивается под наличие/отсутствие верхнего баннера — ничего не сползает.
   overflow:hidden НЕ ставим: дропдауны композера открываются вверх и не должны
   срезаться, а ленты клипуют себя сами (.landing-strip / .landing-marquee). */
@media (min-width: 768px) {
    .landing-hero {
        position: relative;
        height: 100%;
        margin-top: calc(-1 * var(--landing-header-h));
        padding-top: 0;
        padding-bottom: clamp(0.6rem, 1.6vh, 1.1rem);
        justify-content: flex-end;
        gap: 0;
    }
    .landing-hero .landing-composer-host {
        position: relative;
        z-index: 2;
        flex: 1 1 auto;
        display: flex;
        flex-direction: column;
        justify-content: center;
        margin: 0 auto;
    }
    .landing-hero .landing-marquee {
        position: relative;
        z-index: 2;
        flex: 0 0 auto;
    }
}

/* Бегущая строка моделей: чистый CSS-луп (трек = 2 копии ленты, сдвиг -50%).
   Прижата к низу hero, full-bleed. */
.landing-marquee {
    width: 100vw;
    max-width: 100vw;
    margin-left: calc(50% - 50vw);
    overflow: hidden;
    margin-top: 0;
    /* Растушёвка краёв */
    mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}

.landing-marquee__track {
    display: inline-flex;
    gap: 0.6rem;
    padding-right: 0.6rem;
    white-space: nowrap;
    width: max-content;
    animation: landing-marquee var(--motion-period-marquee) var(--motion-ease-linear) infinite;
}

.landing-marquee__item {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.45rem 1.1rem;
    background: var(--surface-soft);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-family: var(--font-display);
    font-size: var(--text-sm);
    color: var(--text-muted);
    flex-shrink: 0;
}
.landing-marquee__logo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.05rem;
    height: 1.05rem;
    flex-shrink: 0;
}
.landing-marquee__logo :is(svg, span, img) { width: 100%; height: 100%; }

@keyframes landing-marquee {
    to { transform: translateX(-50%); }
}

/* --- 02 Showcase: masonry на CSS-колонках (как лента /image) --- */
.landing-masonry {
    margin-top: 2.5rem;
    columns: 2;
    column-gap: 0.75rem;
}

@media (min-width: 640px) { .landing-masonry { columns: 3; } }
@media (min-width: 1100px) { .landing-masonry { columns: 4; } }

.landing-masonry__item {
    position: relative;
    break-inside: avoid;
    margin-bottom: 0.75rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    background: var(--bg-panel);
}

.landing-masonry__item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform var(--motion-duration-base) var(--motion-ease-premium);
}

.landing-masonry__caption {
    position: absolute;
    inset: auto 0 0 0;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 1.75rem 0.85rem 0.75rem;
    background: linear-gradient(180deg, transparent, var(--overlay-scrim));
    opacity: 0;
    transition: opacity var(--motion-duration-fast) var(--motion-ease-standard);
    pointer-events: none;
}

.landing-masonry__item:hover img { transform: scale(1.03); }
.landing-masonry__item:hover .landing-masonry__caption { opacity: 1; }

.landing-masonry__model {
    font-family: var(--font-display);
    font-size: var(--text-2xs);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--overlay-text);
    opacity: 0.75;
}

.landing-masonry__prompt {
    font-size: var(--text-xs);
    color: var(--overlay-text);
    line-height: var(--leading-snug);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* --- 03 Направления --- */
.landing-directions {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.75rem;
    margin-top: 2.5rem;
}

@media (min-width: 640px) { .landing-directions { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .landing-directions { grid-template-columns: repeat(4, 1fr); } }

.landing-direction {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    padding: 1.5rem 1.35rem;
    background: var(--bg-panel);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-glass);
}

.landing-direction__icon,
.landing-feature__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-xl);
    color: var(--primary-text);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
}

.landing-direction__title { font-size: var(--text-lg); font-weight: var(--font-weight-bold); color: var(--text-main); }
.landing-direction__desc { font-size: var(--text-sm); color: var(--text-muted); line-height: var(--leading-normal); flex: 1; }

.landing-direction__models {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.landing-direction__models li {
    padding: 0.28rem 0.7rem;
    background: var(--surface-soft);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-size: var(--text-xs);
    color: var(--text-muted);
    white-space: nowrap;
}

.landing-direction__more { opacity: 0.6; }

.landing-badge-new {
    font-style: var(--font-style-normal);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-bold);
    letter-spacing: var(--tracking-wider);
    color: var(--text-main);
}

/* --- 04 Видео-стена --- */
.landing-video-wall {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.75rem;
    margin-top: 2.5rem;
}

@media (min-width: 768px) { .landing-video-wall { grid-template-columns: repeat(3, 1fr); } }

.landing-video-tile {
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    background: var(--media-letterbox);
    aspect-ratio: 16 / 9;
}

.landing-video-tile video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* --- 05 Музыка --- */
.landing-music {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.6rem;
    margin-top: 2.5rem;
}

@media (min-width: 768px) { .landing-music { grid-template-columns: repeat(2, 1fr); } }

.landing-track {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding: 0.75rem 0.9rem;
    background: var(--bg-panel);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-glass);
}

.landing-track__cover {
    width: 3.25rem;
    height: 3.25rem;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    object-fit: cover;
    flex-shrink: 0;
}

.landing-track__meta {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
    flex: 1;
}

.landing-track__title {
    font-weight: var(--font-weight-semibold);
    color: var(--text-main);
    font-size: var(--text-sm);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-transform: capitalize;
}

.landing-track__model { font-size: var(--text-xs); color: var(--text-subtle); }

.landing-track__play {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.6rem;
    height: 2.6rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    color: var(--primary-text);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
    flex-shrink: 0;
    transition: transform var(--motion-duration-fast) var(--motion-ease-standard);
}

.landing-track__play:hover { transform: scale(1.06); }

/* --- 06 Суперсилы --- */
.landing-features {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.75rem;
    margin-top: 2.5rem;
}

@media (min-width: 640px) { .landing-features { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .landing-features { grid-template-columns: repeat(3, 1fr); } }

.landing-feature {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    padding: 1.5rem 1.35rem;
    background: var(--bg-panel);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-glass);
}

.landing-feature__badge {
    position: absolute;
    top: 1.25rem;
    right: 1.25rem;
    padding: 0.22rem 0.65rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-family: var(--font-display);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-display);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--primary-text);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
}

.landing-feature__title { font-size: var(--text-lg); font-weight: var(--font-weight-bold); color: var(--text-main); }
.landing-feature__desc { font-size: var(--text-sm); color: var(--text-muted); line-height: var(--leading-normal); }

/* --- 07 Тарифы --- */
.landing-plans {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.75rem;
    margin-top: 2.5rem;
}

@media (min-width: 640px) { .landing-plans { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .landing-plans { grid-template-columns: repeat(4, 1fr); } }

.landing-plan {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 1.75rem 1.4rem 1.4rem;
    background: var(--bg-panel);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-glass);
}

.landing-plan.is-highlight {
    background: var(--bg-elevated);
    box-shadow: var(--shadow-glass);
}

.landing-plan__ribbon {
    position: absolute;
    top: -0.7rem;
    left: 50%;
    transform: translateX(-50%);
    padding: 0.25rem 0.9rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-family: var(--font-display);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-display);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--primary-text);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
    white-space: nowrap;
}

.landing-plan__name { font-size: var(--text-lg); font-weight: var(--font-weight-bold); color: var(--text-main); }
.landing-plan__tagline { font-size: var(--text-xs); color: var(--text-subtle); }

.landing-plan__price {
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    font-weight: var(--font-weight-display);
    color: var(--text-main);
    margin: 0.4rem 0;
    white-space: nowrap;
}

.landing-plan__price span {
    font-size: var(--text-sm);
    font-weight: var(--font-weight-regular);
    color: var(--text-muted);
}

.landing-plan__bullets {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    flex: 1;
    margin-bottom: 1rem;
}

.landing-plan__bullets li {
    position: relative;
    padding-left: 1.3rem;
    font-size: var(--text-sm);
    color: var(--text-muted);
    line-height: var(--leading-normal);
}

.landing-plan__bullets li::before {
    content: "✓";
    position: absolute;
    left: 0;
    color: var(--text-main);
    font-weight: var(--font-weight-bold);
}

.landing-plan__cta { width: 100%; padding: 0.7rem 1rem; font-weight: var(--font-weight-semibold); }

.landing-plans__note {
    margin-top: 1.5rem;
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.landing-plans__note a {
    color: var(--text-main);
    font-weight: var(--font-weight-semibold);
}

/* Оплата по факту (wallet-mode) — равноправный второй режим, широкая панель */
.landing-payg {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    margin-top: 1.5rem;
    padding: 1.75rem 1.5rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-elevated);
    box-shadow: var(--shadow-glass);
}

@media (min-width: 768px) {
    .landing-payg {
        flex-direction: row;
        align-items: center;
        gap: 2.5rem;
        padding: 2rem 2.25rem;
    }
}

.landing-payg__main { flex: 1; min-width: 0; }

.landing-payg__eyebrow {
    font-family: var(--font-display);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--text-subtle);
    margin-bottom: 0.4rem;
}

.landing-payg__title {
    font-size: var(--text-lg);
    font-weight: var(--font-weight-bold);
    color: var(--text-main);
}

.landing-payg__desc {
    margin-top: 0.5rem;
    font-size: var(--text-sm);
    color: var(--text-muted);
    line-height: var(--leading-normal);
    max-width: 34rem;
}

.landing-payg__points {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    flex-shrink: 0;
}

.landing-payg__points li {
    position: relative;
    padding-left: 1.3rem;
    font-size: var(--text-sm);
    color: var(--text-muted);
    white-space: nowrap;
}

.landing-payg__points li::before {
    content: "✓";
    position: absolute;
    left: 0;
    color: var(--text-main);
    font-weight: var(--font-weight-bold);
}

.landing-payg__cta {
    padding: 0.75rem 1.6rem;
    font-weight: var(--font-weight-semibold);
    flex-shrink: 0;
    align-self: flex-start;
}

@media (min-width: 768px) {
    .landing-payg__cta { align-self: center; }
}

/* --- 08 Сравнение --- */
.landing-compare {
    margin-top: 2.5rem;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    overflow: hidden;
    background: var(--bg-panel);
    box-shadow: var(--shadow-glass);
}

.landing-compare__head,
.landing-compare__row {
    display: grid;
    grid-template-columns: 1.2fr 1fr 1fr;
    gap: 0.75rem;
    padding: 0.9rem 1.25rem;
    font-size: var(--text-sm);
}

.landing-compare__head {
    font-family: var(--font-display);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-wider);
    text-transform: uppercase;
    color: var(--text-subtle);
    background: var(--surface-soft);
}

.landing-compare__row:nth-child(odd) { background: var(--surface-soft); }
.landing-compare__row span:first-child { color: var(--text-main); font-weight: var(--font-weight-semibold); }
.landing-compare__brand { color: var(--text-main); }
.landing-compare__them { color: var(--text-subtle); }

@media (max-width: 639.98px) {
    .landing-compare__head, .landing-compare__row {
        grid-template-columns: 1fr;
        gap: 0.25rem;
    }
    .landing-compare__head span:not(:first-child) { display: none; }
    .landing-compare__brand::before { content: "Skyny: "; color: var(--text-subtle); font-weight: var(--font-weight-regular); }
    .landing-compare__them::before { content: "Отдельно: "; }
}

/* --- 09 Шаги --- */
.landing-steps {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.75rem;
    margin-top: 2.5rem;
    counter-reset: none;
}

@media (min-width: 768px) { .landing-steps { grid-template-columns: repeat(3, 1fr); } }

.landing-step {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    padding: 1.5rem 1.35rem;
    background: var(--bg-panel);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-glass);
}

.landing-step__num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    font-family: var(--font-display);
    font-weight: var(--font-weight-display);
    color: var(--primary-text);
    background-image: var(--prism-noise), var(--gradient-primary);
    background-size: 120px 120px, auto;
    background-blend-mode: overlay, normal;
}

.landing-step__title { font-size: var(--text-base); font-weight: var(--font-weight-bold); color: var(--text-main); }
.landing-step p { font-size: var(--text-sm); color: var(--text-muted); line-height: var(--leading-normal); }

/* --- 10 FAQ (нативный details/summary — SEO-извлекаемо, ноль JS) --- */
.landing-faq {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-top: 2.5rem;
    max-width: 46rem;
}

.landing-faq__item {
    background: var(--bg-panel);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    box-shadow: var(--shadow-glass);
    overflow: hidden;
}

.landing-faq__item summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.1rem 1.35rem;
    font-weight: var(--font-weight-semibold);
    font-size: var(--text-sm);
    color: var(--text-main);
    cursor: pointer;
    list-style: none;
}

.landing-faq__item summary::-webkit-details-marker { display: none; }

.landing-faq__item summary i {
    flex-shrink: 0;
    color: var(--text-subtle);
    transition: transform var(--motion-duration-fast) var(--motion-ease-standard);
}

.landing-faq__item[open] summary i { transform: rotate(180deg); }

.landing-faq__item > p {
    padding: 0 1.35rem 1.2rem;
    font-size: var(--text-sm);
    color: var(--text-muted);
    line-height: var(--leading-relaxed);
}

/* --- 11 Финальный CTA --- */
.landing-final {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 1.25rem;
    padding-bottom: 2rem;
}

.landing-final .landing-section__lead { margin-top: 0; }

@media (prefers-reduced-motion: reduce) {
    .landing-page { scroll-behavior: auto; }
    .landing-marquee__track { animation: none; }
    .landing-header,
    .landing-masonry__item img,
    .landing-track__play { transition: none; }
}

/* Cursor-spotlight: мягкая подсветка за курсором (desktop only, --mx/--my из JS).
   inset СТРОГО в границах hero по горизонтали: отрицательный right у absolute-слоя
   растягивал бы scrollWidth скролл-контейнера (горизонтальный скролл). */
@media (pointer: fine) {
    .landing-hero {
        position: relative;
    }
    .landing-hero::before {
        content: '';
        position: absolute;
        inset: -4rem 0 0;
        background: radial-gradient(38rem circle at var(--mx, 50%) var(--my, 30%),
            color-mix(in srgb, var(--primary-500) 7%, transparent), transparent 70%);
        pointer-events: none;
    }
}

/* Guest-студия лендинга: пять поверхностей на боевых composer-классах. Здесь
   только hero-композиция, переключение surface и ограничение высокой музыки. */
.landing-composer-host {
    width: 100%;
    max-width: 48rem;
    margin: auto;
}

.landing-composer-host[data-landing-studio]:not([data-landing-studio="ready"])
    > :not(.landing-hero__title):not(.landing-composer-fallback),
.landing-composer-host[data-landing-studio="ready"] > .landing-composer-fallback {
    display: none;
}

.landing-composer-fallback {
    display: grid;
    gap: calc(var(--gap-sm) * 2);
    padding: calc(var(--gap-sm) * 3);
    color: var(--text-muted);
    text-align: center;
}

.landing-hero__title {
    position: relative;
    z-index: 2;
    margin: 0 auto clamp(0.75rem, 2vh, 1.15rem);
    color: var(--text-main);
    font-size: clamp(var(--text-2xl), calc(3.2vw * var(--font-scale)), var(--text-5xl));
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-display);
    letter-spacing: var(--tracking-display);
    text-align: center;
    text-wrap: balance;
    text-shadow: 0 2px 24px color-mix(in srgb, var(--bg-app) 88%, transparent);
}

.landing-hero__title span {
    color: var(--primary-400);
}

.landing-prices-public,
.landing-solution-hero {
    padding-top: clamp(4.5rem, 10vh, 8rem);
}

.landing-solution-models {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: 0.65rem;
    margin-top: 2rem;
    padding: 0;
    list-style: none;
}

.landing-solution-models li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    min-width: 0;
    padding: 0.9rem 1rem;
    border: 0;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--surface-soft);
    color: var(--text-main);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
}

.landing-solution-related {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 1rem;
    margin-top: 2rem;
}

.landing-solution-related .landing-direction {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    min-height: 10rem;
}
/* Лёгкий optical scale: production max-w-3xl уже даёт нужную ширину. */
@media (min-width: 768px) {
    .landing-composer-host {
        transform: scale(1.03);
        transform-origin: center center;
    }
}

.landing-composer-branding {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.42rem;
    margin: 0 auto clamp(0.75rem, 2vh, 1.15rem);
    width: min(100%, 40rem);
    text-align: center;
}

.landing-composer-branding__button {
    display: inline-flex;
    align-items: center;
    gap: 0.68rem;
    max-width: 100%;
    padding: 0.35rem 0.55rem;
    border: 0;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: color-mix(in srgb, var(--chat-input-bg) 72%, transparent);
    color: var(--text-main);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    box-shadow: var(--shadow-glass);
    cursor: pointer;
    transition: background-color var(--transition), transform var(--transition);
}

@media (hover: hover) {
    .landing-composer-branding__button:hover {
        background: var(--chat-input-bg);
        transform: translateY(-1px);
    }
}

.landing-composer-branding__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    flex: 0 0 auto;
    border-radius: var(--radius-round);
    corner-shape: var(--corner-shape-round);
    background: var(--surface-strong);
    color: var(--text-main);
}
.landing-composer-branding__icon :is(.model-icon-content, svg, img) {
    width: 1.35rem;
    height: 1.35rem;
}
.landing-composer-branding__icon > i { font-size: var(--text-xl); }

.landing-composer-branding__copy {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    min-width: 0;
    text-align: left;
}
.landing-composer-branding__eyebrow {
    color: var(--text-subtle);
    font-size: var(--text-2xs);
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-display);
    letter-spacing: var(--tracking-wider);
    text-transform: uppercase;
}
.landing-composer-branding__title {
    max-width: min(60vw, 26rem);
    overflow: hidden;
    color: var(--text-main);
    font-size: var(--text-card);
    font-weight: var(--font-weight-display);
    line-height: var(--leading-tight);
    text-overflow: ellipsis;
    white-space: nowrap;
}
.landing-composer-branding__switch {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    flex: 0 0 auto;
    color: var(--text-subtle);
}
.landing-composer-branding__subtitle {
    max-width: 36rem;
    color: var(--text-muted);
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
}

.landing-composer-stage,
.landing-composer-surface {
    width: 100%;
    min-width: 0;
}
.landing-composer-surface { position: relative; }
.landing-composer-enter {
    animation: landing-composer-surface-in var(--motion-duration-base) var(--motion-ease-premium) both;
}
@keyframes landing-composer-surface-in {
    from { opacity: 0; transform: translateY(0.4rem) scale(0.992); }
    to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .landing-composer-enter { animation: none; }
}

/* В hero composer не докнут к shell, поэтому даём scroll-cap явно. Dock остаётся
   снаружи scroll-region — textarea и CTA всегда доступны, как в production. */
.landing-composer-host :is(.landing-demo-media-composer, .landing-demo-music-composer) .media-composer-scroll-region {
    max-height: min(34vh, 18rem);
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.landing-composer-host .landing-demo-music-composer .media-composer-scroll-region {
    max-height: min(40vh, 23rem);
}

/* Production frame tiles intentionally overhang the composer by 5.5rem. The
   landing studio has its own scroll container, so that overhang would be clipped;
   keep the complete upload cards inside the landing scroll viewport instead. */
.landing-composer-host .landing-demo-media-composer
    .composer-collapsible.is-open > .media-composer-top-stack {
    min-height: auto;
    overflow: visible;
}
@media (min-width: 768px) {
    .landing-composer-host .landing-demo-media-composer
        .composer-collapsible.is-open > .media-composer-top-stack {
        margin-top: 0;
    }
}

.landing-demo-param-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.35rem;
}
.landing-composer-host .landing-demo-setting {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 0.45rem;
    min-width: 0;
    padding: 0.48rem 0.58rem;
    border: 0;
    color: var(--text-main);
    text-align: left;
    cursor: pointer;
}
.landing-composer-host .landing-demo-setting > i { flex: 0 0 auto; color: var(--text-muted); }
.landing-composer-host .landing-demo-setting > span {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    align-items: flex-start;
    min-width: 0;
    text-align: left;
}
.landing-composer-host .landing-demo-setting b,
.landing-composer-host .landing-demo-setting small {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.landing-composer-host .landing-demo-setting b {
    font-size: var(--text-xs);
    font-weight: var(--font-weight-semibold);
}
.landing-composer-host .landing-demo-setting small {
    color: var(--text-subtle);
    font-size: var(--text-2xs);
}

.landing-demo-transcription__formats {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.35rem 0.8rem;
    margin-top: 0.65rem;
    color: var(--text-subtle);
    font-size: var(--text-2xs);
}
.landing-demo-transcription__formats :is(span, button) {
    display: inline-flex;
    align-items: center;
    gap: 0.28rem;
}
.landing-demo-transcription__formats button {
    border: 0;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
}
@media (hover: hover) {
    .landing-demo-transcription__formats button:hover { color: var(--text-main); }
}

/* Пятый пункт есть только у landing studio; production drawer остаётся 4-tab. */
.model-category-tabs--studio { gap: 0.1rem; }
.model-category-tabs--studio .model-category-tab { padding-inline: 0.2rem; }

/* Мобайл: та же слоистая композиция, что на desktop. Hero снимает ограничение
   94vw, а боковой inset композера совпадает с боевым композером ЛК (8px). */
@media (max-width: 767.98px) {
    .landing-hero {
        position: relative;
        width: 100%;
        max-width: 100%;
        min-height: calc(100% - var(--landing-header-h));
        padding: 0 var(--composer-edge-gap, var(--chat-mobile-gutter-x))
                 var(--composer-edge-gap, var(--chat-mobile-gutter-x));
        justify-content: flex-end;
        gap: 0;
    }
    .landing-hero .landing-composer-host {
        position: relative;
        z-index: 2;
        flex: 1 1 auto;
        display: flex;
        flex-direction: column;
        justify-content: center;
        margin: 0 auto;
    }
    .landing-hero__title {
        font-size: clamp(var(--text-3xl), calc(7.5vw * var(--font-scale)), var(--text-4xl));
    }
    .landing-hero .landing-marquee {
        position: relative;
        z-index: 2;
        flex: 0 0 auto;
    }
    .landing-composer-branding {
        gap: 0.3rem;
        margin-bottom: 0.65rem;
    }
    .landing-composer-branding__button {
        gap: 0.48rem;
        padding: 0.28rem 0.42rem;
    }
    .landing-composer-branding__icon {
        width: 2rem;
        height: 2rem;
    }
    .landing-composer-branding__subtitle {
        max-width: 22rem;
        font-size: var(--text-xs);
        line-height: var(--leading-snug);
    }
    .landing-composer-host :is(.landing-demo-media-composer, .landing-demo-music-composer) .media-composer-scroll-region {
        max-height: min(31vh, 15rem);
    }
    .landing-demo-param-grid { grid-template-columns: 1fr; }
    .landing-demo-setting:nth-child(n+3) { display: none; }
    .model-category-tabs--studio .model-category-tab {
        gap: 0.16rem;
        padding-inline: 0.08rem;
        font-size: var(--text-2xs);
    }
}

/* Лента ассистентов затухает у правого края (как в ЛК), а не обрезается жёстко. */
.landing-composer-host .chat-input-assistants-host {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 2.5rem), transparent);
    mask-image: linear-gradient(90deg, #000 calc(100% - 2.5rem), transparent);
}

.landing-glow-host::before {
    /* Компактный ореол под пилюлю (база задаёт композерные -10rem).
       Горизонтальный inset ОТРИЦАТЕЛЬНЫЙ + contain:none — иначе базовый
       contain:paint + inset:0 срезал бы 52px-blur ровно по краю оболочки
       (жёсткий обрез слева/справа). Композер отцентрован с широким боковым
       полем, за край вьюпорта ореол не вылезает. */
    inset: -3rem -3.5rem -2.5rem;
    contain: none;
    z-index: -1;
}

.landing-glow-host.is-glowing::before,
.landing-track.is-playing::before {
    opacity: 0.65;
    animation: chat-input-gradient-flow var(--motion-period-gradient) var(--motion-ease-ambient) infinite;
}

/* --- v2: Full-bleed диагональная лента (галерея-зона hero, самый верх) --- */
.landing-strip {
    overflow: hidden;
    padding: 0;
}

.landing-strip__tilt {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    transform: rotate(-3deg) scale(1.08);
}

.landing-strip__row { overflow: hidden; }

.landing-strip__track {
    display: inline-flex;
    gap: 0.75rem;
    padding-right: 0.75rem;
    width: max-content;
    animation: landing-marquee var(--motion-period-marquee-long) var(--motion-ease-linear) infinite;
    will-change: transform;
}

.landing-strip__row--reverse .landing-strip__track {
    animation-direction: reverse;
}

.landing-strip.is-paused .landing-strip__track {
    animation-play-state: paused;
}

.landing-strip__track img {
    height: clamp(8.5rem, 20vh, 12.5rem);
    width: auto;
    border-radius: var(--radius-md);
    corner-shape: var(--corner-shape-surface);
    object-fit: cover;
    flex-shrink: 0;
}

/* Landing hero: the curved viewport stays fixed behind the composer while two
   identical image sequences move through it. The mask is full-height at the
   sides and compressed in the centre, so motion never breaks the bow. */
.landing-hero > .curved-showcase {
    --curved-rail-width: 122vw;
    --curved-gap: 0.35rem;
    position: absolute;
    inset: 0 auto 0 calc(50% - 50vw);
    z-index: 0;
    display: block;
    width: 100vw;
    height: auto;
    margin: 0;
    overflow: hidden;
}

.curved-showcase__rail {
    position: absolute;
    top: clamp(4.5rem, 10vh, 7rem);
    bottom: clamp(2.75rem, 7vh, 4.5rem);
    left: 50%;
    width: var(--curved-rail-width);
    overflow: hidden;
    transform: translateX(-50%);
    -webkit-clip-path: polygon(
        0 0, 14% 3.5%, 29% 7%, 43% 9.5%, 57% 9.5%, 71% 7%, 86% 3.5%, 100% 0,
        100% 100%, 86% 96.5%, 71% 93%, 57% 90.5%, 43% 90.5%, 29% 93%, 14% 96.5%, 0 100%
    );
    clip-path: polygon(
        0 0, 14% 3.5%, 29% 7%, 43% 9.5%, 57% 9.5%, 71% 7%, 86% 3.5%, 100% 0,
        100% 100%, 86% 96.5%, 71% 93%, 57% 90.5%, 43% 90.5%, 29% 93%, 14% 96.5%, 0 100%
    );
}

.curved-showcase__track {
    display: flex;
    width: max-content;
    height: 100%;
    animation: curved-showcase-scroll var(--motion-period-showcase) var(--motion-ease-linear) infinite;
    will-change: transform;
}

.curved-showcase__sequence {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    flex: 0 0 var(--curved-rail-width);
    width: var(--curved-rail-width);
    height: 100%;
    gap: var(--curved-gap);
    padding-right: var(--curved-gap);
    box-sizing: border-box;
}

.curved-showcase__card {
    position: relative;
    min-width: 0;
    height: 100%;
    overflow: hidden;
    background: var(--bg-panel);
    box-shadow: 0 22px 46px -34px color-mix(in srgb, var(--primary-500) 28%, transparent);
}

.curved-showcase__card img {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
    filter: saturate(0.94) contrast(1.03);
}

@keyframes curved-showcase-scroll {
    to { transform: translateX(-50%); }
}

.curved-showcase.is-paused .curved-showcase__track { animation-play-state: paused; }

/* Side vignette + a denser central scrim directly behind the composer. */
.curved-showcase::after {
    background:
        radial-gradient(ellipse 47% 50% at 50% 48%,
            color-mix(in srgb, var(--bg-app) 92%, transparent) 0%,
            color-mix(in srgb, var(--bg-app) 83%, transparent) 45%,
            color-mix(in srgb, var(--bg-app) 40%, transparent) 72%,
            transparent 100%),
        linear-gradient(90deg,
            var(--bg-app) 0%,
            color-mix(in srgb, var(--bg-app) 78%, transparent) 5%,
            transparent 17%,
            transparent 83%,
            color-mix(in srgb, var(--bg-app) 78%, transparent) 95%,
            var(--bg-app) 100%),
        linear-gradient(180deg,
            color-mix(in srgb, var(--bg-app) 58%, transparent) 0%,
            transparent 21%,
            transparent 76%,
            color-mix(in srgb, var(--bg-app) 74%, transparent) 100%);
}

@media (max-width: 767.98px) {
    .landing-hero > .curved-showcase {
        --curved-rail-width: 210vw;
        --curved-gap: 0.3rem;
    }

    .curved-showcase__rail {
        top: 4.75rem;
        bottom: 3.25rem;
    }

    .curved-showcase::after {
        background:
            radial-gradient(ellipse 66% 50% at 50% 48%,
                color-mix(in srgb, var(--bg-app) 93%, transparent) 0%,
                color-mix(in srgb, var(--bg-app) 82%, transparent) 48%,
                color-mix(in srgb, var(--bg-app) 32%, transparent) 78%,
                transparent 100%),
            linear-gradient(90deg,
                color-mix(in srgb, var(--bg-app) 86%, transparent) 0%,
                transparent 12%, transparent 88%,
                color-mix(in srgb, var(--bg-app) 86%, transparent) 100%),
            linear-gradient(180deg,
                color-mix(in srgb, var(--bg-app) 62%, transparent) 0%,
                transparent 20%, transparent 74%,
                color-mix(in srgb, var(--bg-app) 78%, transparent) 100%);
    }
}

/* --- v2: Scroll-reveal (stagger-delay проставляет landing.js инлайном) --- */
[data-reveal] {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity var(--motion-duration-base) var(--motion-ease-premium),
                transform var(--motion-duration-base) var(--motion-ease-premium);
}

[data-reveal].is-inview {
    opacity: 1;
    transform: none;
}

/* --- v2: Интерактив галереи и видео --- */
.landing-masonry__item { cursor: pointer; }

.landing-masonry__item:focus-visible,
.landing-video-tile:focus-visible {
    outline: 2px solid var(--primary-500);
    outline-offset: 2px;
}

.landing-video-tile {
    position: relative;
    cursor: pointer;
}

.landing-video-tile__badge {
    position: absolute;
    right: 0.6rem;
    bottom: 0.6rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--overlay-pill-bg);
    color: var(--overlay-text);
    font-size: var(--text-base);
    pointer-events: none;
}

/* --- v2: Эквалайзер играющего трека --- */
.landing-track { position: relative; isolation: isolate; }

.landing-eq {
    display: none;
    align-items: flex-end;
    gap: 2px;
    height: 0.8rem;
    margin-left: 0.45rem;
    vertical-align: middle;
}

.landing-track.is-playing .landing-eq { display: inline-flex; }

.landing-eq i {
    width: 3px;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--text-main);
    animation: landing-eq-bounce var(--motion-period-pulse) var(--motion-ease-ambient) infinite;
}

.landing-eq i:nth-child(1) { height: 45%; animation-delay: 0s; }
.landing-eq i:nth-child(2) { height: 90%; animation-delay: calc(var(--motion-period-pulse) * 0.125); }
.landing-eq i:nth-child(3) { height: 60%; animation-delay: calc(var(--motion-period-pulse) * 0.25); }
.landing-eq i:nth-child(4) { height: 80%; animation-delay: calc(var(--motion-period-pulse) * 0.375); }

@keyframes landing-eq-bounce {
    0%, 100% { transform: scaleY(0.5); }
    50%      { transform: scaleY(1); }
}

/* --- v2: Мобильная раскладка — свайп-карусели вместо длинных стопок ---
   Гриды карточек и галерея превращаются в горизонтальные ленты со scroll-snap,
   уходящие под края экрана (нативный мобильный паттерн, а не «версия для слепых»
   из гигантских карточек в столбик). Скроллбар скрыт, свайп — системный. */
@media (max-width: 639.98px) {
    .landing-directions,
    .landing-features,
    .landing-plans,
    .landing-steps,
    .landing-video-wall,
    .landing-masonry {
        display: flex;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        gap: 0.75rem;
        margin-left: calc(-1 * var(--landing-pad));
        margin-right: calc(-1 * var(--landing-pad));
        padding: 0.25rem var(--landing-pad) 0.9rem;

        -webkit-overflow-scrolling: touch;
    }


    .landing-direction,
    .landing-feature,
    .landing-plan,
    .landing-step {
        flex: 0 0 76vw;
        max-width: 19rem;
        scroll-snap-align: start;
        scroll-margin-left: var(--landing-pad);
    }

    .landing-video-tile {
        flex: 0 0 78vw;
        max-width: 22rem;
        scroll-snap-align: start;
        scroll-margin-left: var(--landing-pad);
    }

    /* Галерея — лента фиксированной высоты: ширину плитки задаёт её aspect-ratio */
    .landing-masonry {
        columns: auto;
        scroll-snap-type: x proximity;
    }

    .landing-masonry__item {
        flex: 0 0 auto;
        height: 15rem;
        width: auto;
        /* Кап ширины: широкая 16:9-плитка занимала весь экран и прятала край
           следующей — а видимый «хвост» соседа и есть аффорданс свайпа. */
        max-width: 84vw;
        margin-bottom: 0;
        scroll-snap-align: start;
        scroll-margin-left: var(--landing-pad);
    }

    .landing-masonry__item img { object-fit: cover; }

    /* Внутри карусели карточки не играют в reveal: горизонтально-невидимые
       элементы не пересекают вьюпорт и оставались бы прозрачными до свайпа. */
    .landing-directions > [data-reveal],
    .landing-features > [data-reveal],
    .landing-plans > [data-reveal],
    .landing-steps > [data-reveal],
    .landing-video-wall > [data-reveal],
    .landing-masonry > [data-reveal] {
        opacity: 1;
        transform: none;
        transition: none;
    }

    /* Компактная мобильная типографика — плотнее, современнее */
    .landing-section__lead { font-size: var(--text-sm); }
    .landing-marquee__item { padding: 0.35rem 0.85rem; font-size: var(--text-xs); }
    .landing-strip__track img { height: 7.5rem; }
    .landing-payg__points li { white-space: normal; }
}

/* --- v2: Лайтбокс примеров --- */
.landing-lightbox {
    position: fixed;
    inset: 0;
    z-index: var(--z-fullscreen-modal, 9000);
    display: grid;
    place-items: center;
    padding: 1rem;
}

.landing-lightbox__backdrop {
    position: absolute;
    inset: 0;
    background: var(--modal-backdrop);
}

.landing-lightbox__panel {
    position: relative;
    display: flex;
    flex-direction: column;
    max-width: 56rem;
    width: 100%;
    max-height: 88dvh;
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    background: var(--bg-panel);
    box-shadow: var(--shadow-glass);
    overflow: hidden;
}

.landing-lightbox__close {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.4rem;
    height: 2.4rem;
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round);
    background: var(--overlay-control-bg);
    color: var(--overlay-text);
    font-size: var(--text-lg);
    transition: transform var(--motion-duration-fast) var(--motion-ease-standard);
}

.landing-lightbox__close:hover { transform: scale(1.07); }

.landing-lightbox__media {
    display: grid;
    place-items: center;
    background: var(--media-letterbox);
    min-height: 14rem;
}

.landing-lightbox__media img,
.landing-lightbox__media video {
    max-width: 100%;
    max-height: 62dvh;
    object-fit: contain;
    display: block;
}

.landing-lightbox__caption {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 1rem;
    padding: 1rem 1.25rem 1.15rem;
}

.landing-lightbox__model {
    font-family: var(--font-display);
    font-size: var(--text-xs);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--text-subtle);
    width: 100%;
}

.landing-lightbox__prompt {
    flex: 1;
    min-width: 12rem;
    font-size: var(--text-sm);
    color: var(--text-muted);
    line-height: var(--leading-normal);
}

.landing-lightbox__cta {
    padding: 0.6rem 1.4rem;
    font-weight: var(--font-weight-semibold);
    flex-shrink: 0;
}

@media (prefers-reduced-motion: reduce) {
    .landing-strip__track,
    .curved-showcase__track,
    .landing-eq i { animation: none; }
    [data-reveal] { transition: none; }
    [data-reveal] { opacity: 1; transform: none; }
    .landing-hero::before { display: none; }
}

/* Shared illustration for empty histories, galleries and data lists. */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--gap-sm);
    min-width: 0;
    padding: calc(var(--gap-sm) * 2);
    text-align: center;
    color: var(--text-muted);
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
}
.empty-state--compact { font-size: var(--text-xs); }
.empty-state--compact .generation-empty-illustration { width: calc(var(--gap-sm) * 10); }
.generation-history-empty { padding: 24px 16px; min-height: 180px; }
.generation-empty-illustration { display: block; width: calc(var(--gap-sm) * 14); max-width: 75%; height: auto; aspect-ratio: 1; object-fit: contain; }
.generation-empty-label { margin: var(--gap-sm) 0 0; color: var(--text-muted); font-size: var(--text-sm); line-height: var(--leading-snug); }

/* Transparent assistant illustrations. */
img[src*="/avatar_assistants/v3/"] {
    object-fit: contain;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
}
.chat-input-assistant-dot:has(img[src*="/avatar_assistants/v3/"]) {
    background: transparent;
    box-shadow: none;
}
.chat-input-assistant-dot:has(img[src*="/avatar_assistants/v3/"]) img { padding: 3px; }
.chat-input-assistant-dot.is-active:has(img[src*="/avatar_assistants/v3/"]) {
    background: var(--primary-10);
    box-shadow: none;
}
.chat-input-assistant-dot:has(img[src*="/avatar_assistants/v3/"]):hover { background: var(--bg-hover); }

/* Static Tailwind rings are replaced by a surface tint. Keep keyboard focus,
   actual icon strokes, animated spectrum masks and loading effects intact. */
:root [class*="ring-"]:not(:focus-visible) {
    --tw-ring-shadow: 0 0 transparent;
    --tw-ring-offset-shadow: 0 0 transparent;
}
:root :is([class~="ring-1"], [class~="ring-2"], [class~="ring-4"]):not(:focus-visible) {
    background-color: var(--primary-10);
}
body :is(a, button, summary, [tabindex]):not(input):not(textarea):not(select):not([contenteditable]):not(.chat-prompt-area):not(.input-field-ghost):not([x-drawer-swipe][tabindex="-1"]):focus-visible {
    outline: 2px solid var(--primary-500);
    outline-offset: 3px;
}
/* Text entry is indicated by the caret; clicking a field must not add a ring. */
body :is(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]), textarea, select, [contenteditable="true"]):is(:focus, :focus-visible) {
    outline: 2px solid transparent;
    outline-offset: -2px;
    --tw-ring-shadow: 0 0 transparent;
    --tw-ring-offset-shadow: 0 0 transparent;
}
/* Composer text fields use the caret as their focus indicator. An outer
   outline is clipped by the input shell and appears as a horizontal divider.
   Transparent outlines remain available to forced-colors accessibility modes. */
.chat-prompt-area:focus-visible {
    outline: 2px solid transparent;
    outline-offset: -2px;
}

/* Character editor and knowledge manager: readable forms on both drawer sizes. */
.character-dialog { max-width: 460px; }
.character-form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; overflow-y: auto; gap: 20px; padding: 20px 24px 24px; }
.character-form > .character-field { flex-shrink: 0; }
.character-field { display: flex; flex-direction: column; gap: 8px; }
.character-field-label, .knowledge-label { font-size: var(--text-sm); font-weight: var(--font-weight-medium); color: var(--text-main); }
.character-field-hint, .knowledge-hint { margin: 0; color: var(--text-muted); font-size: var(--text-xs); line-height: 1.5; }
.character-field .input-field { min-height: 44px; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.character-photo { display: flex; align-items: center; gap: 16px; width: 100%; padding: 16px; background: var(--surface-soft); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); text-align: left; transition: background var(--transition); }
.character-photo:hover:not(:disabled) { background: var(--surface-active); }
.character-photo-preview { position: relative; display: flex; align-items: center; justify-content: center; flex: 0 0 72px; height: 88px; overflow: hidden; border-radius: var(--radius-sm); corner-shape: var(--corner-shape-surface); background: var(--surface-active); color: var(--text-muted); font-size: var(--text-2xl); }
.character-photo-preview img { width: 100%; height: 100%; object-fit: cover; }
.character-photo-progress { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: var(--overlay-backdrop-soft); color: var(--surface-paper); }
.character-photo-copy { display: flex; flex: 1; flex-direction: column; gap: 6px; min-width: 0; }
.character-photo-copy strong { font-size: var(--text-sm); color: var(--text-main); font-weight: var(--font-weight-medium); }
.character-photo-copy > span { font-size: var(--text-xs); color: var(--text-muted); line-height: 1.5; }
.character-photo-icon { color: var(--text-muted); font-size: var(--text-lg); }
.knowledge-dialog { max-width: 560px; }
.knowledge-body { padding: 20px 24px 24px; }
.knowledge-screen { display: flex; flex-direction: column; gap: 20px; }
.knowledge-description { margin: 0; font-size: var(--text-sm); color: var(--text-muted); line-height: 1.6; }
.knowledge-steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 0; padding: 0; list-style: none; }
.knowledge-steps li { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; font-size: var(--text-xs); line-height: 1.5; color: var(--text-muted); }
.knowledge-steps li > span:first-child { display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; flex-shrink: 0; border-radius: var(--radius-pill); corner-shape: var(--corner-shape-round); background: var(--surface-active); color: var(--text-main); }
.knowledge-create { display: flex; flex-direction: column; gap: 8px; }
.knowledge-create-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
.knowledge-dialog .input-field { width: 100%; min-width: 0; padding: 12px; font-size: var(--text-sm); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.knowledge-dialog .btn { min-height: 44px; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); font-size: var(--text-sm); }
.knowledge-empty { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 28px 16px; text-align: center; color: var(--text-muted); background: var(--surface-soft); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); font-size: var(--text-sm); line-height: 1.5; }
.knowledge-empty > .ti { font-size: var(--text-2xl); }
.knowledge-empty strong { color: var(--text-main); font-weight: var(--font-weight-medium); }
.knowledge-empty > span:last-child { max-width: 340px; font-size: var(--text-xs); }
.knowledge-list { display: flex; flex-direction: column; gap: 10px; }
.knowledge-list:empty { display: none; }
.knowledge-base-card { min-width: 0; padding: 12px; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); background: var(--surface-soft); }
.knowledge-base-card.is-connected { background: var(--primary-10); }
.knowledge-base-open { display: flex; align-items: center; width: 100%; gap: 12px; padding: 4px; text-align: left; border-radius: var(--radius-sm); corner-shape: var(--corner-shape-surface); }
.knowledge-base-icon { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; flex-shrink: 0; border-radius: var(--radius-sm); corner-shape: var(--corner-shape-surface); background: var(--surface-active); color: var(--text-muted); font-size: var(--text-xl); }
.knowledge-base-copy { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.knowledge-base-copy strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-main); font-size: var(--text-sm); font-weight: var(--font-weight-medium); }
.knowledge-base-copy > span, .knowledge-base-open > .ti { color: var(--text-muted); font-size: var(--text-xs); }
.knowledge-base-actions { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 10px; }
.knowledge-connect { display: inline-flex; align-items: center; justify-content: flex-start; gap: 8px; min-height: 40px; padding: 8px 10px; border-radius: var(--radius-sm); corner-shape: var(--corner-shape-surface); font-size: var(--text-xs); line-height: 1.4; text-align: left; color: var(--text-main); background: var(--surface-active); }
.knowledge-connect.is-connected { color: var(--text-main); background: var(--primary-10); }
.knowledge-connect.is-connected > .ti { color: var(--primary-500); }
.knowledge-connect .ti { font-size: var(--text-base); flex-shrink: 0; }
.knowledge-row-actions { display: flex; flex-shrink: 0; gap: 2px; }
.knowledge-icon-button { display: inline-flex; align-items: center; justify-content: center; width: 36px; min-height: 40px; flex-shrink: 0; border-radius: var(--radius-sm); corner-shape: var(--corner-shape-surface); color: var(--text-muted); font-size: var(--text-base); }
.knowledge-icon-button:disabled { opacity: 0.5; cursor: not-allowed; }
@media (hover: hover) {
    .knowledge-base-open:hover, .knowledge-icon-button:hover:not(:disabled) { background: var(--surface-active); color: var(--text-main); }
    .knowledge-connect:hover { filter: brightness(1.15); }
}
.knowledge-rename { display: flex; align-items: center; gap: 4px; }
.knowledge-delete-confirm { margin-top: 10px; padding: 12px; background: var(--surface-active); border-radius: var(--radius-sm); corner-shape: var(--corner-shape-surface); }
.knowledge-delete-confirm p { margin: 0 0 12px; font-size: var(--text-sm); color: var(--text-main); }
.knowledge-form-actions { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 8px; }
.knowledge-connection { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; padding: 16px; background: var(--surface-soft); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.knowledge-connection.is-connected { background: var(--primary-10); }
.knowledge-connection p { margin: 0; font-size: var(--text-xs); line-height: 1.5; color: var(--text-muted); }
.knowledge-section-heading { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.knowledge-section-heading h3, .knowledge-note-form h3 { font-size: var(--text-sm); color: var(--text-main); font-weight: var(--font-weight-semibold); }
.knowledge-section-heading > span { font-size: var(--text-xs); color: var(--text-muted); }
.knowledge-section-heading > button { margin-left: auto; }
.knowledge-add-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 8px; }
.knowledge-add-actions .btn { padding-inline: 10px; }
.knowledge-note-form { display: flex; flex-direction: column; gap: 10px; padding: 16px; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); background: var(--surface-soft); }
.knowledge-note-form textarea { min-height: 120px; resize: vertical; }
.knowledge-item { display: flex; align-items: flex-start; gap: 10px; padding: 12px; background: var(--surface-soft); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.knowledge-item-icon { padding-top: 8px; color: var(--text-muted); font-size: var(--text-lg); }
.knowledge-item-copy { flex: 1; min-width: 0; padding-top: 4px; }
.knowledge-item-copy > strong { display: block; overflow-wrap: anywhere; color: var(--text-main); font-size: var(--text-sm); font-weight: var(--font-weight-medium); }
.knowledge-item-status { display: flex; align-items: center; flex-wrap: wrap; gap: 5px; margin-top: 5px; color: var(--text-muted); font-size: var(--text-xs); }
.knowledge-item-status.is-ready { color: var(--text-muted); }
.knowledge-item-status.is-ready > .ti { color: var(--primary-500); }
.knowledge-item-status.is-error { color: var(--danger); }
.knowledge-item-copy .knowledge-hint { margin-top: 6px; }
.knowledge-notice { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; padding: 12px; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); background: var(--surface-active); font-size: var(--text-sm); color: var(--text-main); }
@media (max-width: 380px) {
    .character-form, .knowledge-body { padding-inline: 20px; }
    .character-photo { gap: 12px; padding: 12px; }
    .character-photo-preview { flex-basis: 56px; height: 72px; }
    .character-photo-icon { display: none; }
    .knowledge-create-row, .knowledge-add-actions { grid-template-columns: 1fr; }
    .knowledge-steps { gap: 8px; }
    .knowledge-base-card, .knowledge-item { padding: 10px; }
    .knowledge-item .knowledge-row-actions { flex-direction: column; }
}

/* Shared page footer. Composer workspaces do not mount this component. */
.site-footer {
    position: relative;
    z-index: 1;
    container-type: inline-size;
    flex: 0 0 auto;
    width: 100%;
    margin-top: 40px;
    padding: 36px clamp(20px, 3vw, 48px) 24px;
    color: var(--text-muted);
    background: var(--bg-app);
    box-shadow: none;
    font-size: var(--text-xs);
    line-height: var(--leading-relaxed);
}
.site-footer a { color: var(--text-muted); text-decoration: none; }
.site-footer a:hover { color: var(--text-main); }
.site-footer--full { background: var(--surface-soft); }
.site-footer a.site-footer__create { display: inline-flex; align-items: center; justify-content: space-between; gap: 20px; min-height: 40px; margin-top: 16px; padding: 8px 12px; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); color: var(--text-main); font-size: var(--text-xs); font-weight: var(--font-weight-medium); background: var(--surface-active); }
.site-footer__create .ti { font-size: var(--text-base); transition: transform var(--motion-duration-fast) var(--motion-ease-standard); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
    .site-footer__create:hover .ti { transform: translate(2px, -2px); }
}
.site-footer :is(a, summary):focus-visible { outline: 2px solid var(--primary-500); outline-offset: 4px; border-radius: var(--radius-sm); corner-shape: var(--corner-shape-surface); }
.site-footer__grid { display: grid; grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr)); gap: 24px 40px; max-width: 80rem; margin-inline: auto; }
.site-footer__brand { display: inline-flex; margin-bottom: 8px; }
.site-footer .site-footer__tagline { color: var(--text-main); font-size: var(--text-base); line-height: var(--leading-snug); letter-spacing: var(--tracking-tight); }
.site-footer__description { max-width: 240px; margin-top: 8px; }
.site-footer__column { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 0; }
.site-footer__column h2 { margin: 0 0 10px; font-size: var(--text-xs); font-weight: var(--font-weight-semibold); color: var(--text-main); }
.site-footer__column a { display: inline-flex; align-items: center; min-height: 32px; padding-block: 4px; overflow-wrap: anywhere; }
.site-footer__column .ti { margin-left: 3px; }
.site-footer__bottom { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 16px 24px; max-width: 80rem; margin: 28px auto 0; }
.site-footer__copyright { display: flex; flex-direction: column; gap: 8px; font-size: var(--text-2xs); }
.site-footer__socials { display: flex; gap: 8px; }
.site-footer__socials a { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); background: var(--surface-active); font-size: var(--text-lg); }
.site-footer__company { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px 16px; color: var(--text-muted); font-size: var(--text-2xs); }
.site-footer.site-footer--compact { z-index: 30; display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 40px; margin: 0; padding: 0 20px; }
.site-footer__disclosure summary { display: flex; align-items: center; gap: 8px; min-height: 40px; cursor: pointer; list-style: none; }
.site-footer__disclosure summary::-webkit-details-marker { display: none; }
.site-footer__disclosure summary:focus-visible { outline-offset: -2px; }
.site-footer__disclosure[open] summary { color: var(--text-main); }
.site-footer__disclosure[open] summary .ti { transform: rotate(180deg); }
.site-footer__quick { display: flex; gap: 20px; }
.site-footer__quick a { display: inline-flex; align-items: center; min-height: 40px; }
.site-footer__panel { position: absolute; inset: auto 8px calc(100% + 4px); max-height: min(65dvh, 500px); overflow-y: auto; overscroll-behavior: contain; padding: 28px; border-radius: var(--radius-lg); corner-shape: var(--corner-shape-surface); background: var(--bg-panel); box-shadow: 0 12px 40px var(--modal-backdrop); }
@container (max-width: 760px) {
    .site-footer__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px 20px; }
    .site-footer__about { grid-column: 1 / -1; }
    .site-footer__brand { margin-bottom: 4px; }
    .site-footer__description { max-width: none; }
}
@container (max-width: 460px) {
    .site-footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .site-footer__column:last-child { grid-column: 1 / -1; }
    .site-footer__panel { padding: 24px 20px; }
    .site-footer__company { flex-direction: column; justify-content: flex-start; }
    .site-footer__column a { padding-block: 6px; }
}
@media (max-width: 767.98px) {
    .site-footer { margin-top: 32px; padding-top: 32px; padding-bottom: max(24px, var(--safe-area-bottom, 0px)); }
}

/* The frame reserves its aspect ratio while media decodes. The image fades in
   independently of the card entrance, including slow loads and cached returns. */
.sidebar-generation-media { opacity: 0; transition: opacity var(--motion-duration-base) var(--motion-ease-premium); }
.sidebar-generation-media.is-loaded { opacity: 1; }
.sidebar-generation-media.is-restored { transition: none; }
@media (prefers-reduced-motion: reduce) {
    .sidebar-generation-media { transition: none; }
}
.media-input-warning {
    padding: calc(var(--gap-sm) * 1.5) calc(var(--gap-sm) * 2);
    color: var(--text-main);
    background: var(--surface-strong);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
    font-size: var(--text-label);
    line-height: 1.45;
}
.media-composer-preview-card.has-input-error {
    outline: 2px solid var(--text-muted);
    outline-offset: -2px;
}

.music-feature-tools { display: flex; flex-direction: column; gap: var(--gap-sm, 0.5rem); min-width: 0; }
.music-composer-head--sounds {
    display: grid;
    grid-template-columns: minmax(var(--composer-control-size), 1fr) auto;
    align-items: center;
}
.music-composer-head--sounds::after { display: none; }
.music-composer-head--sounds > .music-composer-head__sources { grid-column: 2; grid-row: 1; }
/* x-show finishes after the sound strip mounts. Both left-hand controls own
   the same cell during that handoff, so an implicit second row cannot appear. */
.music-composer-head--sounds > .music-seg { grid-column: 1; grid-row: 1; }
.music-sound-bar { grid-column: 1; grid-row: 1; width: auto; min-width: 0; }
.music-sound-bar .media-params-bar__strip { min-height: var(--composer-control-size); max-height: var(--composer-control-size); }
.music-sound-bar .media-params-bar__toggle {
    flex: 0 0 var(--composer-control-size);
    width: var(--composer-control-size);
    height: var(--composer-control-size);
}
.music-sound-bar .media-params-pill { flex-shrink: 0; max-width: none; }
.music-sound-bar .media-params-pill,
.music-sound-settings .media-params-pill { min-height: var(--composer-control-size); }
.music-sound-settings__grid { display: flex; flex-wrap: wrap; gap: var(--gap-xs); }
.music-sound-settings__item { min-width: 0; }
@container music-composer (max-width: 32rem) {
    .music-sound-settings__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr)); }
    .music-sound-settings .media-params-pill {
        width: 100%;
        min-width: 0;
        max-width: 100%;
        gap: var(--gap-2xs);
        padding-inline: var(--gap-sm);
        font-size: var(--text-xs);
    }
    .music-sound-settings .media-params-pill__switch { margin-left: auto; }
}
.music-sound-tempo {
    flex: 1 0 100%;
    min-width: 0;
    padding: var(--gap-sm);
    margin-top: var(--gap-xs);
    background: var(--bg-input);
    border-radius: var(--radius-lg);
    corner-shape: var(--corner-shape-surface);
}
.music-sound-counter { display: flex; align-items: center; padding-inline: var(--gap-sm); }
.music-sound-counter .music-counter { text-align: start; }
.music-section__head--editor.is-instrumental { grid-template-columns: minmax(0, 1fr) auto; }
.music-section__head--editor.is-instrumental .music-section__meta { grid-column: 2; grid-row: 1; }
.music-feature-tools > .music-chips { flex-wrap: wrap; }
.music-feature-tools .music-chip[aria-pressed="true"] { background: var(--surface-soft); color: var(--text-main); }
.music-mashup { display: flex; flex-direction: column; gap: var(--gap-sm, 0.5rem); min-width: 0; }
.music-track-drop-zone { position: relative; display: flex; flex-direction: column; gap: var(--gap-sm, 0.5rem); min-width: 0; border-radius: var(--radius-md); corner-shape: var(--corner-shape-surface); }
.music-track-drop-empty { position: relative; }
.music-track-drop-hint {
    position: absolute;
    inset: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--gap-sm);
    padding: calc(var(--gap-sm) * 2);
    border: 2px dashed var(--text-muted);
    border-radius: inherit;
    corner-shape: inherit;
    background: color-mix(in srgb, var(--bg-panel) 82%, transparent);
    color: var(--text-main);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-semibold);
    text-align: center;
    pointer-events: none;
}

/* Intrinsic content is measured separately from the animated dialog surface. */
#app-modal { container-type: size; }
#app-modal .system-modal-card {
    width: auto;
    max-width: 100%;
    flex-shrink: 0;
    padding: 0;
    gap: 0;
    overflow: hidden;
}
#app-modal .system-modal-content {
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
    gap: 1rem;
    padding: 1.125rem;
    width: min(var(--system-modal-width, 22.5rem), 100cqw);
    max-height: 100cqh;
}
#app-modal[data-variant="media-notice"] { --system-modal-width: 30rem; }
#app-modal[data-variant="media-notice"] .system-modal-title { font-family: var(--font-editorial); font-weight: var(--font-weight-medium); font-size: calc(var(--text-dialog) * var(--font-editorial-scale)); line-height: var(--leading-snug); }
#app-modal .system-modal-body { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
#app-modal .system-modal-actions { flex-shrink: 0; }

/* Media admission uses the shared dialog layout. */
#app-modal[data-variant="media-notice"] .system-modal-actions .btn {
    min-height: 3.25rem;
    white-space: normal;
}

.system-modal-selection-feedback {
    color: var(--text-muted);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    white-space: pre-line;
}

.system-modal-model-action { display: flex; flex-wrap: wrap; align-items: stretch; gap: var(--gap-sm); padding: var(--gap-sm); min-width: 0; border-radius: var(--radius-lg); corner-shape: var(--corner-shape-surface); background: var(--bg-raised); color: var(--text-main); }
.system-modal-model-action[hidden] { display: none; }
.system-modal-model-action button { border: 0; font-family: inherit; font-size: var(--text-sm); color: inherit; cursor: pointer; min-height: 3rem; border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.system-modal-model-action__confirm { flex: 1 1 min-content; min-width: 0; text-align: left; padding: var(--gap-sm); font-weight: var(--font-weight-semibold); }
.system-modal-model-action__picker { display: flex; align-items: center; gap: var(--gap-sm); flex: 0 1 auto; min-width: 0; max-width: 100%; padding: var(--gap-sm); background: var(--surface-active); }
.system-modal-model-action__picker .model-icon-content { width: 1.5rem; height: 1.5rem; flex: 0 0 1.5rem; }
.system-modal-model-action__name { flex: 1; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-sm); }
.system-modal-model-action button:disabled { opacity: .65; cursor: wait; }
.system-modal-model-action button:focus-visible { outline: 2px solid var(--primary-500); outline-offset: -2px; }
.system-modal-model-action button:not(:disabled):hover { background: var(--surface-strong); }
.system-modal-model-menu { width: min(24rem, calc(100vw - 2rem)); max-height: min(22rem, calc(100dvh - 2rem)); overflow-y: auto; overscroll-behavior: contain; }
.system-modal-model-menu .model-popular-select { min-height: 2.75rem; }
.system-modal-selection-feedback .system-modal-actions { margin-top: 0.75rem; }
.system-modal-chip[aria-pressed] {
    position: relative;
    cursor: pointer;
    min-height: 2.75rem;
    padding-left: 1.625rem;
    border: 0;
    appearance: none;
    font-family: inherit;
}
.system-modal-chip[aria-pressed="true"] { background: var(--surface-active); color: var(--text-main); }
.system-modal-chip[aria-pressed="true"]::before { content: '✓'; position: absolute; left: 0.625rem; }
.system-modal-chip[aria-pressed]:disabled { cursor: wait; opacity: 0.65; }
@media (hover: hover) {
    .system-modal-chip[aria-pressed]:not(:disabled):hover { background: var(--bg-hover); }
}
.music-track-drop-hint.is-active { border-color: var(--primary-500); background: color-mix(in srgb, var(--primary-500) 14%, var(--bg-panel)); }
.music-mashup-card { display: flex; flex-direction: column; gap: var(--gap-sm, 0.5rem); padding-top: var(--gap-md, 0.75rem); border-top: 1px solid var(--surface-strong); min-width: 0; }
.music-mashup-add { display: flex; align-items: center; justify-content: center; gap: var(--gap-sm, 0.5rem); padding: var(--gap-lg, 1rem); border: 1px solid color-mix(in srgb, var(--text-main) 18%, transparent); border-radius: var(--radius-xl); corner-shape: var(--corner-shape-surface); min-height: 4.5rem; }
.music-feature-tools input[type="number"], .music-adv-row input[type="number"] { width: 7rem; max-width: 100%; }
.music-feature-tools select, .music-adv-row select { max-width: 100%; min-width: 0; }
.music-lyrics-controller { --lyrics-prepare-factor: 2; }
.music-lyrics__request { display: flex; flex-direction: column; gap: var(--gap-lg); }
.music-lyrics__request .modal-form-footer { padding-inline: 0; }
.music-lyrics__request-intro { display: flex; align-items: center; min-height: calc(var(--gap-sm) * 12); }
.music-lyrics__request-intro > .music-info-card__text { width: 68%; }
.music-lyrics__request-backdrop { position: absolute; inset: 0; z-index: 0; isolation: isolate; background: var(--prism-accent); pointer-events: none; user-select: none; }
/* Keep the photo's light and texture; take its colour directly from the accent.
   Rotating the baked-in gold hue cannot reproduce the theme's neutral palette. */
.music-lyrics__request-backdrop img { width: 100%; height: 100%; object-fit: cover; object-position: right center; mix-blend-mode: luminosity; }
.music-lyrics__request-backdrop::after {
    content: ''; position: absolute; inset: 0;
    background:
        linear-gradient(90deg, color-mix(in srgb, var(--chat-input-solid) 96%, transparent), color-mix(in srgb, var(--chat-input-solid) 92%, transparent) 55%, color-mix(in srgb, var(--chat-input-solid) 55%, transparent) 75%, transparent),
        linear-gradient(0deg, color-mix(in srgb, var(--chat-input-solid) 90%, transparent), transparent 55%);
}
.music-lyrics { --lyrics-height: calc(var(--gap-sm) * 28); min-width: 0; container: music-lyrics / inline-size; }
.music-lyrics__toolbar { display: grid; grid-template-columns: auto auto; align-items: start; justify-content: center; gap: var(--gap-sm); margin-top: calc(var(--gap-sm) * 2); }
.music-lyrics__toolbar .transcribe-models { min-width: 0; flex-wrap: nowrap; gap: calc(var(--gap-xs) / 2); padding: calc(var(--gap-xs) / 2); }
.music-lyrics__toolbar .music-karaoke { display: contents; }
.music-karaoke { display: flex; flex-direction: column; align-items: center; gap: var(--gap-sm); min-width: 0; max-width: 100%; }
.music-karaoke .transcribe-models { max-width: 100%; }
.music-karaoke .transcribe-model { min-height: 44px; white-space: nowrap; }
.music-karaoke__action { display: inline-flex; align-items: center; justify-content: center; gap: var(--gap-xs); }
.music-karaoke__label { display: inline-flex; align-items: center; justify-content: center; gap: var(--gap-xs); min-width: 0; }
.music-karaoke__label > .ti { flex-shrink: 0; }
.music-karaoke__price { font-size: var(--text-xs); color: var(--text-muted); white-space: nowrap; }
/* Card actions share the content edges and sit below the heading/body.
   A price may wrap inside its segment, without splitting the control's row. */
.music-info-card > .music-karaoke { align-items: stretch; width: 100%; margin-top: auto; }
.music-info-card .music-karaoke .transcribe-models { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }
.music-info-card .music-karaoke .transcribe-model { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--gap-xs); min-width: 0; padding-inline: var(--gap-sm); white-space: normal; }
.music-info-card .music-karaoke__status { max-width: 100%; }
.music-karaoke__status > span { min-width: 0; overflow-wrap: anywhere; }
.music-karaoke__status > :is(.ti, button) { flex-shrink: 0; }
.music-karaoke__status { display: none; align-items: center; justify-content: center; gap: var(--gap-sm); max-width: 28rem; font-size: var(--text-sm); color: var(--text-muted); text-align: center; text-wrap: balance; }
.music-karaoke__status.is-visible { display: flex; }
.music-karaoke__status button { min-width: 44px; min-height: 44px; }
/* Notices use the scene's existing space. An idle status has no layout box;
   arriving messages cannot resize the dialog or move its transport. */
.music-lyrics__scene { position: relative; display: grid; grid-template-rows: minmax(0, 1fr) auto; height: var(--lyrics-height); min-height: 0; }
.music-lyrics__scene > .music-lyrics__request { grid-area: 1 / 1; min-height: 0; height: 100%; display: flex; flex-direction: column; justify-content: center; overflow-y: auto; }
.music-lyrics__body { grid-area: 1 / 1; position: relative; min-height: 0; height: 100%; }
.music-lyrics__status { min-height: 0; transform: translateY(0); transition: transform var(--lyrics-transition-duration, var(--motion-duration-dramatic)) var(--motion-ease-premium), opacity var(--motion-duration-dramatic) var(--motion-ease-premium); }
.music-lyrics__status .music-karaoke__status { max-width: 100%; max-height: calc(var(--lyrics-height) / 3); overflow-y: auto; }
.music-lyrics__status .music-karaoke__status.is-visible { margin-top: var(--gap-sm); }
.music-lyrics-modal.is-outro .music-lyrics__status { transform: translateY(var(--lyrics-status-outro-y, 0px)); }
.music-lyrics__body > :not(.music-lyrics__generation) { transition: opacity var(--motion-duration-base) var(--motion-ease-standard); }
.music-lyrics-modal.is-generating-karaoke .music-lyrics__body > :not(.music-lyrics__generation) { opacity: 0; }
.music-lyrics__generation { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--gap-sm); padding: var(--gap-sm); opacity: 0; transform: translateY(calc(var(--motion-distance-content) / 2)); pointer-events: none; text-align: center; color: var(--text-muted); font-size: var(--text-sm); transition: opacity var(--motion-duration-base) var(--motion-ease-standard), transform var(--motion-duration-base) var(--motion-ease-premium); }
.music-lyrics__generation > .ti { font-size: var(--text-2xl); color: var(--text-main); }
.music-lyrics__generation-title { font-size: var(--text-xl); color: var(--text-main); font-weight: var(--font-weight-display); }
.music-lyrics-modal.is-generating-karaoke .music-lyrics__generation { opacity: 1; transform: translateY(0); }
.music-lyrics-modal.is-generating-karaoke .music-lyrics__ambience { opacity: 1; }
.music-lyrics-modal.is-generating-karaoke .music-lyrics__light-anchor--rest { opacity: 1; transform: translateY(0) scaleX(var(--lyrics-ambience-rest-scale)); }
.music-lyrics-modal.is-generating-karaoke .music-lyrics__light { opacity: var(--lyrics-ambience-strength, .9); }
.music-karaoke__status.is-busy > .ti { animation: karaoke-breathe var(--motion-period-hint) var(--motion-ease-ambient) infinite; }
@keyframes karaoke-breathe { 50% { opacity: .35; transform: scale(.85); } }
@media (prefers-reduced-motion: reduce) {
    .music-lyrics__body > :not(.music-lyrics__generation), .music-lyrics__generation, .music-lyrics__status { transition: none; }
    .music-karaoke__status.is-busy > .ti { animation: none; }
}
.music-lyrics__body { overflow: hidden; overflow: clip; }
.music-lyrics__karaoke { height: 100%; position: relative; overflow: hidden; overflow: clip; }
.music-lyrics__sentence { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; opacity: var(--lyrics-presence, 0); pointer-events: none; transform: translateY(calc((1 - var(--lyrics-enter, 0)) * var(--lyrics-height) * .34)) scale(calc(.78 + .22 * var(--lyrics-enter, 0))); }
.music-lyrics__sentence:is(.is-current, .is-next, .is-finishing, .is-releasing) { will-change: transform, opacity; }
.music-lyrics__ambience {
    --accent-cool: var(--prism-cyan);
    --gradient-warm: var(--prism-gold);
    /* This full-dialog surface is the only visible smoke clip. */
    position: absolute; inset: 0; pointer-events: none; z-index: 0; contain: paint;
    opacity: 0;
    transition: opacity var(--lyrics-transition-duration, var(--motion-duration-dramatic)) var(--motion-ease-premium);
}
.music-lyrics__ambience.is-visible { opacity: 1; }
/* One simulation follows the scene with a compositor transform. Its buffers
   and phase survive countdown, outro and full-text changes. */
.music-lyrics__light-anchor {
    position: absolute; inset: 0;
    transition: transform var(--lyrics-transition-duration, var(--motion-duration-dramatic)) var(--motion-ease-premium), opacity var(--lyrics-transition-duration, var(--motion-duration-dramatic)) var(--motion-ease-premium);
}
.music-lyrics__light-anchor--rest { opacity: 1; transform: translateY(var(--lyrics-ambience-rest-y)) scaleX(var(--lyrics-ambience-rest-scale)); }
.music-lyrics__ambience.is-countdown .music-lyrics__light-anchor--rest { transform: translateY(var(--lyrics-ambience-countdown-y, 0px)) scaleX(var(--lyrics-ambience-expanded-scale)); }
.music-lyrics__ambience.is-outro .music-lyrics__light-anchor--rest { transform: translateY(0) scaleX(var(--lyrics-ambience-outro-scale)); }
.music-lyrics__light {
    --ambient-smoke-texture: url('/static/media/effects/ambient-smoke-karaoke.png');
    position: absolute;
    /* Keep the simulation's outflow/fade outside the dialog even at the
       narrowest anchor scale and its lowest resting position. */
    inset: calc(-1 * var(--lyrics-ambience-outset)); transform-origin: center;
    opacity: calc(var(--lyrics-ambience-strength, 1) * .9);
    transform: none;
    /* Audio drives the fluid solver; CSS bounds and opacity remain stable. */
    transition: none;
}
.music-lyrics__light[data-smoke-fallback]::after {
    content: '';
    position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(110deg, var(--primary-500), var(--accent-cool), var(--gradient-warm));
    -webkit-mask: var(--ambient-smoke-texture) center / 100% 100% no-repeat;
    mask: var(--ambient-smoke-texture) center / 100% 100% no-repeat;
}
.music-lyrics__light[data-smoke-fallback]::before,
.music-lyrics__light[data-smoke-fallback]::after {
    /* The texture predates the enlarged GPU outflow field. Keep its visible
       cloud at dialog scale instead of stretching it into an opaque wash. */
    -webkit-mask-size: 55% 55%; mask-size: 55% 55%;
    opacity: .42;
    animation: karaoke-smoke-drift var(--motion-period-gradient) var(--motion-ease-ambient) infinite alternate paused;
}
.music-lyrics__light[data-smoke-fallback]::after {
    animation-name: karaoke-smoke-counterflow;
    animation-duration: var(--motion-period-idle-glow);
    opacity: .28;
}
.music-lyrics__light[data-smoke-fallback][data-smoke-running]::before,
.music-lyrics__light[data-smoke-fallback][data-smoke-running]::after { animation-play-state: running; }
@keyframes karaoke-smoke-drift {
    from { transform: translate(-2%, 1%) rotate(-5deg) scale(.94, .90); }
    to { transform: translate(2%, -2%) rotate(5deg) scale(1.06, 1.12); }
}
@keyframes karaoke-smoke-counterflow {
    from { transform: translate(2%, -1%) rotate(8deg) scale(1.04, .92); }
    to { transform: translate(-2%, 2%) rotate(-6deg) scale(.96, 1.14); }
}
@media (prefers-reduced-motion: reduce) {
    .music-lyrics__light[data-smoke-fallback]::before { animation: none; transform: none; }
    .music-lyrics__light[data-smoke-fallback]::after { content: none; }
}
[data-theme="prism"] .music-lyrics__light[data-smoke-fallback]::before,
[data-theme="prism"] .music-lyrics__light[data-smoke-fallback]::after {
    /* Match the live shader's luminous pigment on dark surfaces. A raw dark
       theme token made the fallback much fainter than the GPU simulation. */
    background: linear-gradient(110deg,
        color-mix(in srgb, var(--primary-500) 25%, white),
        color-mix(in srgb, var(--accent-cool) 25%, white),
        color-mix(in srgb, var(--gradient-warm) 25%, white));
}
.music-lyrics__sentence p { margin: 0; max-width: 100%; text-wrap: balance; font-family: var(--font-display); font-weight: var(--font-weight-display); font-size: var(--text-lg); line-height: var(--leading-relaxed); text-align: center; overflow-wrap: anywhere; color: var(--text-subtle); }
.music-lyrics__lines { width: 100%; min-width: 0; }
.music-lyrics__karaoke .music-lyrics__lines { --lyrics-dissolve: var(--lyrics-release, 0); opacity: calc(1 - var(--lyrics-release, 0)); transform: translateY(calc(var(--lyrics-height) * -.2 * var(--lyrics-release, 0))); }
.music-lyrics__karaoke :is(.music-lyrics__lines, .music-lyrics__lead) {
    mask-image: linear-gradient(to right, transparent calc(var(--lyrics-dissolve, 0) * 50% - 10%), #000 calc(var(--lyrics-dissolve, 0) * 50%), #000 calc(100% - var(--lyrics-dissolve, 0) * 50%), transparent calc(110% - var(--lyrics-dissolve, 0) * 50%));
}
.music-lyrics__lines .music-lyrics__aside { margin-top: var(--gap-sm); font-size: var(--text-sm); font-weight: var(--font-weight-regular); color: var(--text-muted); }
.music-lyrics__sentence .is-spoken { color: var(--text-muted); }
.music-lyrics__word { position: relative; display: inline-block; vertical-align: baseline; max-width: 100%; white-space: pre-wrap; transition: color min(var(--lyrics-transition-duration, var(--motion-duration-dramatic)), var(--motion-duration-slow)) var(--motion-ease-premium); }
.music-lyrics__main .music-lyrics__ending { display: block; width: 100%; margin-top: var(--gap-sm); text-align: center; opacity: var(--lyrics-tail-opacity, 1); }
.music-lyrics__ending > .music-lyrics__word-text { display: inline-block; }
.music-lyrics__ending > :is(.music-lyrics__word-text, .music-lyrics__glow) { white-space: nowrap; letter-spacing: normal; }
/* Move each letter and its highlight as one layer. A full-width text-clipped
   overlay over separately transformed letters can leave detached glyph ink. */
.music-lyrics__glyph { position: relative; display: inline-block; white-space: pre; transform: translate3d(calc(var(--lyrics-glyph-offset) * (var(--lyrics-glyph-base, 0px) + var(--lyrics-glyph-travel, 0px) * var(--lyrics-spread, 0))), 0, 0); }
.music-lyrics__glyph > .music-lyrics__glow::before { content: attr(data-glyph); }
.music-lyrics__sentence:is(.is-current, .is-finishing) .music-lyrics__glyph { will-change: transform; }
.music-lyrics__lead { display: inline-block; max-width: 100%; --lyrics-dissolve: calc(1 - var(--lyrics-lead-opacity, 1)); opacity: var(--lyrics-lead-opacity, 1); }
.music-lyrics__glow { position: absolute; inset: 0; opacity: 0; pointer-events: none; user-select: none; transition: opacity min(var(--lyrics-transition-duration, var(--motion-duration-dramatic)), var(--motion-duration-slow)) var(--motion-ease-premium); }
.music-lyrics .music-word-active .music-lyrics__glow { opacity: 1; }
.music-lyrics__pause { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; opacity: 0; color: var(--text-subtle); font-family: var(--font-editorial); font-size: var(--text-5xl); font-weight: var(--font-weight-editorial); line-height: var(--leading-tight); font-variant-numeric: lining-nums tabular-nums; pointer-events: none; transform: translateY(0); transition: opacity var(--lyrics-transition-duration, var(--motion-duration-dramatic)) var(--motion-ease-premium), transform var(--lyrics-transition-duration, var(--motion-duration-dramatic)) var(--motion-ease-premium); }
.music-lyrics__pause.is-visible { opacity: 1; }
.music-lyrics__countdown-number { display: inline-block; opacity: calc(1 - var(--lyrics-countdown-fade, 0)); transform: translateY(calc(var(--lyrics-height) * -1 * var(--lyrics-countdown-lift) * var(--lyrics-countdown-fade, 0))); }
.music-lyrics .music-lyrics__glow { animation-play-state: paused; }
/* Only the highlighted word needs a shimmer animation. Creating a paused
   animation for every word stalls mounting and switching a long lyric sheet. */
.music-lyrics .music-lyrics__word:not(.music-word-active) .music-lyrics__glow { animation-name: none; }
.music-lyrics.is-playing[data-mode="karaoke"] .music-lyrics__sentence:is(.is-current, .is-finishing) .music-word-active .music-lyrics__glow,
.music-lyrics.is-playing[data-mode="full"] .music-lyrics__full .music-word-active .music-lyrics__glow { animation-play-state: running; }
.music-lyrics__full { height: 100%; overflow-y: auto; overflow-wrap: anywhere; color: var(--text-muted); font-size: var(--text-sm); line-height: var(--leading-relaxed); }
.music-lyrics__full p { margin: 0; }
.music-lyrics__full .music-lyrics__lines { margin-bottom: calc(var(--gap-sm) * 2); }
.music-lyrics-modal { position: relative; isolation: isolate; width: min(100%, var(--music-lyrics-dialog-width)); max-height: calc(100dvh - var(--gap-sm) * 6); overflow: hidden; overflow: clip; padding: calc(var(--gap-sm) * 3); }
.music-lyrics-modal > :not(.music-lyrics__ambience, .music-lyrics__request-backdrop) { position: relative; z-index: 1; }
.music-lyrics__header { gap: calc(var(--gap-sm) * 1.5); }
.music-lyrics__heading { display: flex; align-items: center; gap: calc(var(--gap-sm) * 1.5); flex: 1; min-width: 0; }
.music-lyrics__cover { position: relative; display: block; flex: 0 0 auto; width: calc(var(--gap-sm) * 6); height: calc(var(--gap-sm) * 6); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); }
.music-lyrics__cover > img { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; corner-shape: inherit; }
.music-lyrics__heading > .modal-header-title { min-width: 0; font-size: var(--text-xl); line-height: var(--leading-snug); }
.music-lyrics__heading > :is(.music-lyrics__cover, .modal-header-title) { transform-origin: top left; transform: translate(0, 0) scale(1); transition: transform var(--lyrics-transition-duration, var(--motion-duration-dramatic)) var(--motion-ease-premium); }
.music-lyrics-modal.is-outro .music-lyrics__cover { transform: translate(var(--lyrics-cover-outro-x, 0px), var(--lyrics-cover-outro-y, 0px)) scale(var(--lyrics-cover-outro-scale, 1)); }
.music-lyrics-modal.is-outro .music-lyrics__heading > .modal-header-title { transform: translate(var(--lyrics-title-outro-x, 0px), var(--lyrics-title-outro-y, 0px)); }
.music-lyrics__header .modal-header-close { flex-shrink: 0; }
.music-lyrics-overlay { z-index: var(--z-dialog-above-overlay); }
.music-lyrics--expanded { --lyrics-height: min(45dvh, 24rem); }
.music-lyrics--expanded .music-lyrics__sentence p { font-size: clamp(var(--text-2xl), calc((1rem + 2vw) * var(--font-scale)), var(--text-3xl)); line-height: var(--leading-snug); }
.music-lyrics--expanded .music-lyrics__sentence .music-lyrics__aside { font-size: var(--text-lg); line-height: var(--leading-normal); }
.music-lyrics--expanded .music-lyrics__pause { font-size: min(calc(var(--lyrics-height) * .3), clamp(var(--text-7xl), calc(8vw * var(--font-scale)), var(--text-8xl))); line-height: 1; color: var(--text-muted); }
.music-lyrics--expanded .music-lyrics__full { font-size: var(--text-lg); }
.music-lyrics--expanded .music-lyrics__toolbar { margin-top: calc(var(--gap-sm) * 2); }
.music-lyrics__toolbar .transcribe-model { font-size: var(--text-xs); line-height: var(--leading-snug); min-height: 2rem; padding: var(--gap-xs) var(--gap-sm); white-space: nowrap; }
.music-lyrics__playback { display: flex; flex-direction: column; gap: var(--gap-sm); margin-top: calc(var(--gap-sm) * 2); color: var(--text-muted); font-size: var(--text-sm); font-variant-numeric: tabular-nums; transform: translateY(0); transition: transform var(--lyrics-transition-duration, var(--motion-duration-dramatic)) var(--motion-ease-premium), opacity var(--motion-duration-dramatic) var(--motion-ease-premium); }
.music-lyrics__playback.is-outro { transform: translateY(var(--lyrics-player-outro-y, calc(var(--lyrics-height) * -.5 - 50% - var(--gap-sm) * 2))); }
.music-lyrics__timeline { min-width: 0; width: 100%; }
.music-lyrics__timeline .music-range { display: block; width: 100%; }
.music-lyrics__times { display: flex; justify-content: space-between; gap: var(--gap-xs); margin-top: var(--gap-xs); font-size: var(--text-sm); line-height: var(--leading-snug); }
.music-lyrics__modes { display: flex; align-items: center; justify-content: center; gap: clamp(var(--gap-xs), 2vw, calc(var(--gap-sm) * 2)); }
.music-lyrics__modes .music-player-full__ctrl { flex-shrink: 0; width: 2.75rem; height: 2.75rem; font-size: var(--text-xl); }
.music-lyrics__modes .music-player-full__ctrl--play { width: clamp(3.75rem, 12vw, 4.25rem); height: clamp(3.75rem, 12vw, 4.25rem); font-size: var(--text-3xl); }
.music-lyrics__heading, .music-lyrics__toolbar { transition: opacity var(--motion-duration-dramatic) var(--motion-ease-premium); }
.music-lyrics-modal.controls-collapsed [data-lyrics-controls] { opacity: 0; pointer-events: none; }
@container music-lyrics (max-width: 36rem) {
    .music-lyrics__toolbar { gap: var(--gap-xs); }
    .music-lyrics__toolbar .transcribe-model { padding-inline: calc(var(--gap-xs) / 2); }
    .music-lyrics__toolbar .music-karaoke__label > .ti { display: none; }
}
@media (max-height: 700px) {
    .music-lyrics--expanded { --lyrics-height: min(32dvh, 12rem); }
    .music-lyrics--expanded .music-lyrics__toolbar { margin-top: var(--gap-sm); }
}
@media (prefers-reduced-motion: reduce) {
    .music-lyrics__sentence, .music-lyrics__pause, .music-lyrics span { transition: none; }
    .music-lyrics .text-shimmer { animation: none; }
    .music-lyrics__glyph, .music-lyrics__sentence { transform: none; will-change: auto; }
    .music-lyrics__sentence:not(.is-current):not(.is-finishing):not(.is-releasing), .music-lyrics__sentence.is-awaiting { visibility: hidden; }
    .music-lyrics__karaoke :is(.music-lyrics__lines, .music-lyrics__lead) { mask-image: none; }
    .music-lyrics__karaoke .music-lyrics__lines, .music-lyrics__countdown-number { transform: none; }
    .music-lyrics__ambience, .music-lyrics__light-anchor { transition: none; }
    .music-lyrics__heading, .music-lyrics__toolbar, .music-lyrics__playback, .music-lyrics__heading > :is(.music-lyrics__cover, .modal-header-title) { transition: none; }
}
.music-ref-card__ops { max-width: 100%; overflow-x: auto; }

.music-lyrics-button { position: relative; isolation: isolate; overflow: hidden; }
.music-lyrics-button__art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 70% 40%; filter: grayscale(1); mix-blend-mode: luminosity; opacity: var(--lyrics-button-art-opacity); mask-image: linear-gradient(90deg, transparent 35%, #000 90%); pointer-events: none; }
.music-lyrics-button > :is(.music-lyrics-button__mark, .music-lyrics-button__label) { position: relative; z-index: 1; }
.music-lyrics-button__mark { font-size: var(--text-sm); font-weight: var(--font-weight-semibold); line-height: 1; }
.music-lyrics-button__label { display: none; }
.music-player-full__topbar .music-lyrics-button,
.music-info-panel__meta .music-lyrics-button,
.shell-mini-player--desktop .music-lyrics-button {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--gap-xs);
    width: auto; min-width: 2.75rem; min-height: 2.75rem; padding-inline: var(--gap-sm);
    border-radius: var(--radius-pill);
    corner-shape: var(--corner-shape-round); background: var(--lyrics-button-bg); color: var(--text-main);
    font-size: var(--text-sm); font-weight: var(--font-weight-semibold);
}
.shell-mini-player--desktop .music-lyrics-button {
    /* Match the inset play button instead of the full player's larger controls. */
    height: var(--shell-header-control-size);
    min-height: 0;
    min-width: var(--shell-header-control-size);
    padding-inline: calc(var(--gap-sm) * 1.5);
}
.music-player-full__topbar .music-lyrics-button__label,
.music-info-panel__meta .music-lyrics-button__label,
.shell-mini-player--desktop .music-lyrics-button__label { display: inline; }
.music-player__controls .music-lyrics-button,
.shell-mini-player--mobile .music-lyrics-button { display: inline-flex; background: var(--lyrics-button-bg); color: var(--text-main); }
.music-lyrics-button[aria-pressed="true"] { color: var(--primary-500); background: color-mix(in srgb, var(--primary-500) 18%, var(--bg-panel)); }
@container (max-width: 34rem) {
    .shell-mini-player--desktop .music-lyrics-button__label { display: none; }
    .shell-mini-player--desktop .music-lyrics-button { width: var(--shell-header-control-size); padding-inline: 0; }
}
/* Data visualizations in Markdown. Source remains available on render failure. */
.md-visual { margin: calc(var(--gap-sm) * 3) 0; padding: var(--chat-component-padding); border: 0; background: var(--chat-component-bg); border-radius: var(--chat-component-radius); corner-shape: var(--corner-shape-surface); min-width: 0; max-width: 100%; container-type: inline-size; }
.md-visual-toolbar, .md-table-controls, .md-table-footer { display: flex; align-items: center; gap: var(--gap-sm); color: var(--text-muted); font-size: var(--text-caption); }
.md-visual-toolbar { flex-wrap: wrap; margin-bottom: var(--gap-sm); }
.md-visual-toolbar > span { margin-right: auto; font-size: var(--text-label); font-weight: var(--font-weight-medium); }
.md-visual button { display: inline-flex; align-items: center; justify-content: center; gap: var(--gap-xs); font-family: var(--font-sans); font-size: var(--text-caption); font-weight: var(--font-weight-medium); line-height: var(--leading-normal); color: var(--text-muted); background: transparent; border: 0; box-shadow: none; border-radius: var(--chat-control-radius); cursor: pointer; min-height: var(--artifact-control-size); padding: var(--gap-xs) var(--gap-sm); transition: color var(--transition-fast), background-color var(--transition-fast); }
.md-visual button:hover:not(:disabled) { background: var(--bg-hover); color: var(--text-main); }
.md-visual button[aria-pressed="true"] { color: var(--text-main); background: var(--bg-input); }
.md-visual button:disabled { opacity: .35; cursor: default; }
.md-visual button:focus-visible, .md-table-search:focus-within { outline: 2px solid var(--text-muted); outline-offset: 2px; }
.md-visual-source { margin: var(--gap-sm) 0 0; padding: calc(var(--gap-sm) * 2); border: 0; background: var(--bg-input); border-radius: var(--radius-base); max-height: calc(var(--gap-sm) * 50); overflow: auto; color: var(--text-main); font-size: var(--text-control); }
.md-visual-source[hidden], .md-table-pagination[hidden] { display: none; }
.md-visual-output { min-height: calc(var(--gap-sm) * 6); color: var(--text-muted); overflow: auto; }
.md-visual-frame { display: block; width: 100%; height: calc(var(--gap-sm) * 38); border: 0; background: transparent; }
.md-visual-frame.is-loading { visibility: hidden; position: absolute; inset: 0; }
.md-visual-output { position: relative; }
.md-visual[aria-busy="true"] .md-visual-output { overflow: hidden; }
.md-visual-loading { padding: var(--gap-sm) 0; }
.md-table-controls { margin: 0 0 calc(var(--gap-sm) * 2); }
.md-table-search { display: flex; align-items: center; gap: var(--gap-sm); width: min(100%,calc(var(--gap-sm) * 44)); min-width: 0; min-height: var(--chat-control-height); box-sizing: border-box; padding: var(--gap-sm) calc(var(--gap-sm) * 2); background: var(--chat-control-bg); border-radius: var(--chat-control-radius); }
.md-table-search input { width: 100%; min-width: 0; padding: 0; border: 0; box-shadow: none; outline: none; background: transparent; color: var(--text-main); font-family: var(--font-sans); font-size: var(--text-control); line-height: var(--leading-normal); }
.md-table-search input::placeholder { color: var(--text-muted); }
.md-visual .markdown-table-wrap { margin: 0; border: 0; border-radius: 0; }
.md-visual table { width: max-content; min-width: 100%; border: 0; border-collapse: separate; border-spacing: 0 var(--gap-2xs); font-size: var(--text-control); }
.md-visual th, .md-visual td { padding: calc(var(--gap-sm) * 1.5); vertical-align: middle; text-align: left; border: 0; }
.md-visual th { background: transparent; color: var(--text-muted); font-weight: var(--font-weight-medium); white-space: nowrap; }
.md-visual th .md-table-sort { padding: 0; min-height: var(--artifact-control-size); font-size: inherit; text-align: left; justify-content: flex-start; }
.md-visual .md-table-sort svg { opacity: 0; transition: opacity var(--transition-fast); }
.md-visual .md-table-sort:hover svg, .md-visual th[aria-sort="ascending"] svg, .md-visual th[aria-sort="descending"] svg { opacity: 1; }
.md-visual th[aria-sort="ascending"], .md-visual th[aria-sort="descending"] { color: var(--text-main); }
.md-visual tbody td { color: var(--text-main); background: transparent; line-height: var(--leading-relaxed); max-width: calc(var(--gap-sm) * 48); }
.md-visual tr:nth-child(even) td { background: var(--bg-input-45); }
.md-visual tbody tr:hover td { background: var(--bg-hover); }
.md-visual tbody tr[data-selected="true"] td { background: var(--text-main-6); }
.md-visual tbody td:first-child { border-radius: var(--radius-md) 0 0 var(--radius-md); }
.md-visual tbody td:last-child { border-radius: 0 var(--radius-md) var(--radius-md) 0; }
.md-visual th:first-child, .md-visual td:first-child { width: calc(var(--gap-sm) * 5); padding-inline: var(--gap-sm); }
.md-visual .md-table-select { width: calc(var(--gap-sm) * 2.5); min-height: calc(var(--gap-sm) * 2.5); padding: var(--gap-2xs); background: var(--text-main-6); border-radius: var(--radius-round); }
.md-visual .md-table-select svg { opacity: 0; }
.md-visual .md-table-select[aria-checked="true"], .md-visual .md-table-select[aria-checked="mixed"] { background: var(--text-main); color: var(--bg-app); }
.md-visual .md-table-select[aria-checked="true"] svg, .md-visual .md-table-select[aria-checked="mixed"] svg { opacity: 1; }
.md-table-footer { flex-wrap: wrap; margin-top: var(--gap-sm); min-height: var(--artifact-control-size); }
.md-table-selection-count { color: var(--text-main); }
.md-table-pagination { display: flex; align-items: center; gap: var(--gap-xs); margin-left: auto; }
.md-table-pagination button { width: var(--artifact-control-size); padding: var(--gap-xs); }
@container (max-width: 420px) {
    .md-table-search { width: 100%; }
    .md-visual th, .md-visual td { padding: var(--gap-sm); }
}

/* Shared action capsule for every chat result, with the app's native menu. */
.chat-tool-actions, .chat-file-card { --chat-tool-control-size: var(--artifact-control-size); }
.chat-file-card__header { min-height: calc(var(--chat-tool-control-size) + var(--chat-control-inset) * 2 + var(--gap-sm)); }
.chat-tool-actions, .chat-file-card__actions {
    display: inline-flex; align-items: center; flex: 0 0 auto; gap: var(--gap-2xs);
    padding: var(--chat-control-inset); border: 0; border-radius: var(--chat-control-radius);
    corner-shape: var(--corner-shape-round); background: var(--chat-control-bg); box-shadow: none;
}
.chat-tool-actions > button, .md-visual .chat-tool-actions > button, .chat-file-card__actions > button {
    display: inline-flex; align-items: center; justify-content: center;
    width: var(--chat-tool-control-size); height: var(--chat-tool-control-size); min-height: var(--artifact-control-size);
    padding: 0; border: 0; border-radius: var(--radius-round); corner-shape: var(--corner-shape-round);
    background: var(--chat-control-active); color: var(--text-muted); box-shadow: none; cursor: pointer;
    transition: background-color var(--transition-fast), color var(--transition-fast);
}
.chat-tool-actions > button:hover, .md-visual .chat-tool-actions > button:hover, .chat-file-card__actions > button:hover { background: var(--bg-hover); color: var(--text-main); }
.chat-tool-actions > button:focus-visible { outline: 2px solid var(--text-muted); outline-offset: 2px; }
.chat-tool-actions svg { width: calc(var(--gap-sm) * 2.5); height: calc(var(--gap-sm) * 2.5); flex: none; }
.chat-tool-actions i { font-size: var(--text-lg); }
.chat-media-gallery__actions { position: absolute; bottom: var(--gap-sm); right: var(--gap-sm); z-index: 2; }
.chat-tool-menu { position: fixed; inset: auto; margin: 0; min-width: calc(var(--gap-sm) * 25); max-width: calc(100vw - var(--gap-sm) * 2); border: 0; background: var(--bg-elevated); color: var(--text-main); }
.chat-tool-menu .dropdown-item { width: 100%; font-family: var(--font-sans); text-align: left; border: 0; }
.chat-control-menu .dropdown-item { border-radius: var(--chat-control-radius); }
.chat-control-menu .dropdown-item.is-selected { background: var(--chat-control-active); }
.chat-control-icon { width: calc(var(--gap-sm) * 2.5); height: calc(var(--gap-sm) * 2.5); flex: none; }
.chat-control-round { display: inline-flex; align-items: center; justify-content: center; flex: none; width: var(--artifact-control-size); height: var(--artifact-control-size); border-radius: var(--radius-round); background: var(--chat-control-active); }
.chat-tool-feedback { font-size: var(--text-caption); color: var(--text-muted); }
.code-block-wrapper { margin-block: calc(var(--gap-sm) * 3); border: 0; background: var(--bg-elevated); border-radius: var(--radius-base); corner-shape: var(--corner-shape-surface); box-shadow: none; }
.code-block-footer { padding: var(--gap-sm) calc(var(--gap-sm) * 2) calc(var(--gap-sm) * 2); gap: var(--gap-sm); }
.code-block-wrapper pre { background: transparent; border: 0; padding: calc(var(--gap-sm) * 2); border-radius: 0; }
.code-block-preview { padding: calc(var(--gap-sm) * 2); background: transparent; }
.markdown-content :is(.code-block-wrapper,.md-visual) + * { margin-top: calc(var(--gap-sm) * 3); }
.agent-flow__item > :is(.agent-flow__text,.agent-flow__visual,.chat-file-list,.agent-flow__media,.agent-flow__post),
.agent-flow__gallery > .chat-media-gallery { margin-block: 0; }
.agent-flow__item:not(:has(> .is-header-status)) ~ .agent-flow__item:has(> :is(.agent-flow__text,.agent-flow__visual,.chat-file-list,.agent-flow__gallery,.agent-flow__media,.agent-flow__post)),
.agent-flow__item:has(> :is(.agent-flow__text,.agent-flow__visual)) + .agent-flow__item { margin-top: calc(var(--gap-sm) * 3); }
:is(.md-visual,.code-block-wrapper):is(:fullscreen,.is-expanded) {
    display: flex; flex-direction: column; width: 100%; height: 100%; max-width: none; min-width: 0;
    margin: 0; padding: calc(var(--gap-sm) * 3); border: 0; border-radius: 0; box-sizing: border-box;
    background: var(--bg-elevated); color: var(--text-main); overflow: auto;
}
:is(.md-visual,.code-block-wrapper).is-expanded { position: fixed; inset: 0; width: 100vw; height: 100dvh; }
:is(.md-visual,.code-block-wrapper)::backdrop { background: var(--bg-app); }
.md-visual:is(:fullscreen,.is-expanded) .md-visual-output { flex: 1; min-height: 0; }
.md-visual:is(:fullscreen,.is-expanded) .md-visual-frame { height: 100% !important; }
.code-block-wrapper:is(:fullscreen,.is-expanded) > pre:not(.hidden), .code-block-wrapper:is(:fullscreen,.is-expanded) .code-block-preview:not(.hidden) { flex: 1; min-height: 0; overflow: auto; }
.code-block-wrapper:is(:fullscreen,.is-expanded) .preview-iframe { height: 100%; }
@media (pointer: coarse) {
    .audio-card { --audio-card-control-size: calc(var(--gap-sm) * 5.5); }
    .chat-tool-actions, .chat-file-card { --chat-tool-control-size: calc(var(--gap-sm) * 5.5); }
}

/* Terminal response notice shares the chat surfaces, without an extra border. */
.chat-response-notice {
    display: flex; align-items: flex-start; gap: var(--gap-sm);
    padding: calc(var(--gap-sm) * 2); margin-block: var(--gap-sm);
    border-radius: var(--radius-xl); background: var(--bg-elevated);
    color: var(--text-main); font-size: var(--text-sm); line-height: 1.55;
    overflow-wrap: anywhere;
}
.chat-response-notice > i { flex: none; margin-top: .15em; color: var(--text-muted); }
.chat-response-notice strong { display: block; font-weight: 500; }
.chat-response-notice p { margin: var(--gap-2xs) 0 0; color: var(--text-muted); }

/* Chat content and interaction primitives: same surface, scale and focus rules. */
.markdown-content .md-disclosure {
    margin-block: calc(var(--chat-component-gap) * 3);
    padding: 0;
    background: transparent;
    color: var(--text-main);
    border: 0;
    border-radius: var(--chat-component-radius);
    corner-shape: var(--corner-shape-surface);
    min-width: 0;
    overflow-wrap: anywhere;
}
.markdown-content :is(.md-callout, .md-disclosure-body) > :first-child { margin-top: 0; }
.markdown-content :is(.md-callout, .md-disclosure-body) > :last-child { margin-bottom: 0; }
.chat-question { --chat-control-bg: var(--bg-elevated); width: 100%; max-width: 40rem; margin-block: var(--chat-component-padding); box-sizing: border-box; color: var(--text-main); font-size: var(--text-control); overflow-wrap: anywhere; }
.chat-question h3 { margin: 0; font-size: var(--text-control); font-weight: var(--font-weight-semibold); line-height: var(--leading-snug); }
.chat-question .chat-question-description { margin: var(--gap-xs) 0 0; white-space: pre-wrap; color: var(--text-muted); font-size: var(--text-label); line-height: var(--leading-normal); }
.chat-question form { margin-top: calc(var(--chat-component-gap) * 1.5); }
.chat-question fieldset { display: flex; align-items: stretch; flex-wrap: wrap; gap: var(--chat-component-gap); margin: 0; padding: 0; border: 0; min-width: 0; }
.chat-question-fields { display: contents; }
.chat-question-fields:empty { display: none; }
.chat-question-field { display: grid; grid-template-rows: 1fr auto; flex: 1 1 10rem; gap: 0; min-width: 0; box-sizing: border-box; min-height: var(--chat-control-height); padding: var(--chat-control-inset) var(--chat-component-padding); background: var(--chat-control-bg); border-radius: var(--chat-control-radius); }
.chat-question-field--date { flex-basis: 11rem; }
.chat-question-field > :is(label,span) { font-size: var(--text-caption); font-weight: var(--font-weight-medium); color: var(--text-muted); line-height: var(--leading-normal); }
.chat-question-optional { margin-inline-start: var(--chat-component-gap); color: var(--text-muted); font-size: var(--text-caption); font-weight: var(--font-weight-regular); }
.chat-question-field > input {
    width: 100%; min-width: 0; box-sizing: border-box; font: inherit; line-height: var(--leading-normal); color: var(--text-main);
    background: transparent; border: 0; border-radius: 0; outline: none; padding: 0; min-height: 1.5em; color-scheme: inherit;
}
.chat-question-field:has(> input:focus-visible) { outline: 2px solid var(--text-muted); outline-offset: 2px; }
.chat-question-field--choices { flex-basis: 100%; display: flex; align-items: center; flex-wrap: wrap; gap: var(--chat-component-gap); background: transparent; padding: 0; }
.chat-question-options { display: flex; flex-wrap: wrap; gap: var(--chat-control-inset); min-width: 0; padding: var(--chat-control-inset); border-radius: var(--chat-control-radius); background: var(--chat-control-bg); }
.chat-question-options label { position: relative; display: inline-flex; min-width: 0; cursor: pointer; }
.chat-question-options input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; margin: 0; cursor: inherit; }
.chat-question-options span { padding: var(--gap-sm) calc(var(--chat-component-gap) * 1.5); border-radius: var(--chat-control-radius); background: transparent; color: var(--text-muted); font-size: var(--text-label); line-height: var(--leading-normal); transition: background-color var(--transition-fast), color var(--transition-fast); }
.chat-question-options input:checked + span { background: var(--chat-control-active); color: var(--text-main); }
.chat-question-options input:focus-visible + span { outline: 2px solid var(--text-muted); outline-offset: 2px; }
.chat-question-options input:disabled { cursor: default; }
.chat-question-actions { display: inline-flex; align-self: center; flex: none; gap: var(--chat-control-inset); margin: 0; padding: var(--chat-control-inset); background: var(--chat-control-bg); border-radius: var(--chat-control-radius); }
.chat-question-actions button { display: inline-flex; align-items: center; justify-content: center; gap: var(--chat-component-gap); font: inherit; font-size: var(--text-label); font-weight: var(--font-weight-medium); min-height: var(--artifact-control-size); padding: var(--gap-xs) calc(var(--chat-component-gap) * 1.5); border: 0; border-radius: var(--chat-control-radius); background: transparent; color: var(--text-main); cursor: pointer; }
.chat-question-actions .chat-component-primary { background: var(--chat-control-active); color: var(--text-main); }
.chat-question-actions .chat-question-send { width: var(--artifact-control-size); height: var(--artifact-control-size); padding: 0; border-radius: var(--radius-round); }
.chat-question-field--picker { padding: var(--chat-control-inset); }
.chat-question-field--picker > button { display: flex; align-items: center; gap: var(--chat-component-gap); width: 100%; min-width: 0; padding: 0; border: 0; border-radius: var(--chat-control-radius); background: transparent; color: var(--text-main); cursor: pointer; font: inherit; text-align: left; }
.chat-question-picker-text { display: grid; flex: 1; min-width: 0; padding-inline-start: calc(var(--chat-component-padding) - var(--chat-control-inset)); }
.chat-question-picker-text > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: var(--leading-normal); }
.chat-question-picker-label { color: var(--text-muted); font-size: var(--text-caption); }
.chat-question-actions button:hover:not(:disabled) { opacity: .8; }
.chat-question button:focus-visible, .md-disclosure summary:focus-visible { outline: 2px solid var(--text-main); outline-offset: 3px; }
.chat-question fieldset:disabled { opacity: .7; }
.chat-question .chat-question-status { margin: var(--chat-component-gap) 0 0; color: var(--text-muted); font-size: var(--text-caption); }
.chat-question-status:empty { display: none; }
.chat-question-error { color: var(--text-main); font-size: var(--text-control); }
.chat-question-receipt { display: flex; flex-wrap: wrap; gap: var(--chat-component-gap) var(--chat-component-padding); margin-block: var(--chat-component-gap) 0; }
.chat-question-receipt > div { display: flex; gap: var(--gap-xs); min-width: 0; }
.chat-question-receipt dt { color: var(--text-muted); }
.chat-question-receipt dt::after { content: ':'; }
.chat-question-receipt dd { margin: 0; }
.markdown-content .md-callout { margin-block: var(--chat-component-padding); padding: 0; border: 0; background: transparent; color: var(--text-muted); font-size: var(--text-control); line-height: var(--leading-relaxed); }
.markdown-content .md-callout-title { display: inline; margin-inline-end: var(--chat-component-gap); color: var(--text-main); font-weight: var(--font-weight-medium); }
.markdown-content .md-disclosure summary { width: fit-content; max-width: 100%; box-sizing: border-box; padding: var(--chat-component-gap) var(--chat-component-padding); border-radius: var(--chat-control-radius); background: var(--bg-elevated); cursor: pointer; font-size: var(--text-control); font-weight: var(--font-weight-medium); }
.md-disclosure-body { margin-top: var(--chat-component-padding); }
.markdown-content li.md-task-item { list-style: none; }
.md-task-check { color: var(--text-muted); }
.markdown-content .footnotes { font-size: var(--text-control); color: var(--text-muted); margin-top: var(--chat-component-padding); }
.markdown-content .footnotes-sep { border: 0; margin-block: var(--chat-component-padding); }
.markdown-content .footnote-ref { font-size: var(--text-caption); }

/* Status remains visible without perpetual movement when motion is reduced. */
@media (prefers-reduced-motion: reduce) {
    .loading-spinner, .wf-spin, .builder-spin, .sup-typing__dots span,
    .chat-typing-dots span, .wf-canvas-host .drawflow-node.wf-node-running .wf-node__state,
    :root .animate-spin, :root .animate-pulse, :root .animate-bounce {
        animation: none;
    }
}
/* The shell remains inert until its component can be constructed safely. */
#app-shell-root[data-app-bootstrap="pending"] > :not([data-app-bootstrap-status]),
#app-shell-root[data-app-bootstrap="failed"] > :not([data-app-bootstrap-status]) {
    display: none !important;
}
.app-bootstrap-status {
    display: none;
    flex: 1;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    gap: 1rem;
    padding: var(--app-gutter-x, 1rem);
    text-align: center;
}
.app-bootstrap-status p { max-width: 34rem; color: var(--text-muted); }
#app-shell-root[data-app-bootstrap="failed"] > .app-bootstrap-status { display: flex; }
