/* Cascade layers — the ONE place that fixes precedence. Later layer wins,
   whatever the selector length or !important inside it. */
@layer base, components, pages, utils;

@layer base {
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        /* Kill the default grey/blue square overlay on tap (iOS/Android).
           Buttons and links have their own hover/active styling. */
        -webkit-tap-highlight-color: transparent;
    }

    :root {
        --text: #1a1a2e;
        --text-secondary: rgba(26, 26, 46, 0.5);
        --text-tertiary: rgba(26, 26, 46, 0.25);
        --glass: rgba(255, 255, 255, 0.45);
        --glass-border: rgba(255, 255, 255, 0.6);
        --accent: #6c5ce7;
        --accent-deep: #5346c8;    /* pressed state of accent-filled controls */

        /* ─── Design tokens ───────────────────────────────────────────────────
           Canonical values extracted from the outfit-detail and outfit-builder
           modals (the visual reference for the project). New surfaces should
           compose these tokens; legacy rules above keep their literal values
           and migrate opportunistically. See styleguide.html for live examples.
        */

        /* Typography */
        --font-body: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
        --font-heading: 'Space Grotesk', sans-serif;
        --font-2xs: 9px;
        /* stamp labels (uppercase + high tracking) */
        --font-xs: 11px;
        /* uppercase mini-labels (chip-row-label, form-section-label) */
        --font-sm: 13px;
        /* chip text, item names, search/nav */
        --font-base: 15px;
        /* body, toast, CTA labels */
        --font-lg: 20px;
        /* subhead, builder title */
        --font-xl: 28px;
        /* display, outfit-detail title */
        --font-2xl: 32px;
        /* page-section heading (pricing, legal h1) */
        --font-3xl: 36px;
        /* page hero (studio-title) */
        --font-4xl: 38px;
        /* landing-anim display (step-badge) */

        --weight-medium: 500;
        --weight-semibold: 600;
        --weight-bold: 700;

        --tracking-label: 0.08em;
        /* uppercase mini-labels */
        --tracking-tight: -0.01em;
        /* large display headings */

        --leading-tight: 1.2;
        /* headings, builder title */
        --leading-base: 1.5;
        /* body copy in paragraphs */

        /* Spacing — 2/4-step scale, matches gap/padding values used in reference modals */
        --space-2xs: 4px;
        --space-xs: 6px;
        --space-sm: 8px;
        --space-md: 10px;
        --space-base: 12px;
        --space-lg: 14px;
        --space-xl: 16px;
        --space-2xl: 20px;
        --space-3xl: 24px;
        --space-4xl: 28px;

        /* Radii */
        --radius-2xs: 6px;
        --radius-xs: 10px;
        --radius-sm: 14px;
        --radius-md: 18px;
        --radius: 24px;
        /* default — modals, large cards */
        --radius-pill: 999px;

        /* Layout — page content widths */
        --container-wide: 1080px;
        /* main app, landing, pricing */
        --container: 720px;
        /* default contained sections */
        --container-narrow: 620px;
        /* focused inner blocks */

        /* Motion */
        --dur-fast: 0.15s;
        --dur-base: 0.2s;
        --dur-slow: 0.3s;
        --ease: ease;

        /* Accent alpha scale — 6 discrete tiers. Snap any new usage to one of
           these instead of inventing new alphas. Semantic aliases below preserve
           legacy names; new code can reference the numeric tokens directly. */
        --accent-05: rgba(108, 92, 231, 0.05);
        --accent-10: rgba(108, 92, 231, 0.10);
        --accent-15: rgba(108, 92, 231, 0.15);
        --accent-25: rgba(108, 92, 231, 0.25);
        --accent-35: rgba(108, 92, 231, 0.35);
        --accent-50: rgba(108, 92, 231, 0.50);

        /* Semantic aliases — keep for readability where role > opacity matters */
        --accent-soft: var(--accent-10);
        --accent-strong: var(--accent-15);
        --accent-glow: var(--accent-25);

        /* Warm accent — soft pink for secondary actions on cool/lavender BG.
           Used where outline-purple buttons would visually blend into the gradient
           (Style Scan, Change plan, All outfits, AI pick, etc.). */
        --ai: #f5b8d0;
        --ai-soft: rgba(245, 184, 208, 0.16);
        --ai-text: #a04a70;

        /* Surfaces & lines */
        --hairline: rgba(0, 0, 0, 0.06);
        /* toolbar/footer dividers */
        --overlay: rgba(17, 21, 34, 0.55);
        /* image-action background, confirm scrim */
        --overlay-strong: rgba(17, 21, 34, 0.78);

        /* Status */
        --danger: #dc4e5e;
        --save: #1aa45a;        /* primary "save to wardrobe" green (flat-lay result) */
        --save-deep: #0f7a3d;   /* saved state (deeper green) */
        --save-10: rgba(26, 164, 90, 0.10);   /* idle tint of the outline save button */

        /* Shadows */
        --shadow-card: 0 4px 16px rgba(0, 0, 0, 0.06);
        --shadow-cta: 0 4px 20px var(--accent-glow);
        --shadow-cta-lg: 0 10px 30px var(--accent-25);
        --shadow-cta-hi: 0 8px 32px var(--accent-35);

        /* Z-index ladder */
        --z-nav: 100;
        --z-modal: 1000;
        --z-confirm: 1100;
        --z-toast: 9999;

        /* Image aspect ratio — FALLBACK only. The canon lives in config/ai.py
           (FLATLAY_ASPECT_RATIO, shared with the AI prompts); /config.js overrides
           this token from it on every page load, so change it THERE. This value just
           covers the first paint and the pages that don't load /config.js. */
        --aspect-flat-lay: 3 / 4;
    }

    html {
        /* Always-on scrollbar track, even when content fits the viewport. Without
           this the scrollbar appears/disappears per page/load on Windows, shifting
           centered content by ~15px. scrollbar-gutter:stable is NOT enough: it only
           stabilizes in-flow layout, while position:fixed elements (.navbar pill)
           center against the viewport, which still shrinks by the scrollbar width —
           the bar visibly drifted between scrolling pages (wardrobe/studio) and
           short ones (stylist/profile) during page transitions. The gutter is still
           needed for modal scroll-locks: lockPageScroll() sets inline
           overflow:hidden, and the reserved gutter keeps in-flow layout put. */
        overflow-y: scroll;
        scrollbar-gutter: stable;
        /* Горизонтальный клип живёт ЗДЕСЬ, не на body. Как только html получил
           свой overflow-y (строка выше), overflow с body перестаёт пропагироваться
           на viewport — body становится клип-контейнером и ломает position:sticky
           у всех потомков (скроллителлинг-карта лендинга залипала намертво). На
           корневом элементе overflow применяется к viewport'у, sticky живёт. */
        overflow-x: hidden;
    }

    body {
        font-family: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
        color: var(--text);
        min-height: 100dvh;
        -webkit-font-smoothing: antialiased;
        /* Deepest fallback only. The mesh gradient itself now lives on .bg — a real
           position:fixed layer (see below) — instead of here via
           background-attachment:fixed. attachment:fixed is buggy on mobile: it lags
           the address-bar collapse and flashes an unpainted strip. A fixed-positioned
           element doesn't have that problem. This solid colour just guarantees no
           white ever shows behind everything. */
        background-color: #e8eaf3;
        /* НЕ вешать сюда overflow-x:hidden — убьёт position:sticky (см. html выше). */
    }

    .bg {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        /* height pinned to the LARGEST viewport (toolbar collapsed) instead of
           inset:0. On mobile the address bar hides on scroll-start, growing the
           viewport; with inset:0 the fixed layer's bottom chased that change and
           the vmax-sized blobs visibly jumped. 100lvh keeps the layer full-height
           in the collapsed state always, so nothing is revealed mid-scroll.
           On desktop lvh == vh, so this is a no-op there. */
        height: 100lvh;
        z-index: -1;
        overflow: hidden;
        /* The base mesh gradient (moved here from body). Painting it on this
           position:fixed layer is the correct way to pin a background to the
           viewport on mobile — no background-attachment:fixed glitch, no strip. */
        /* Calmer, lighter palette: airy base (#ea–#f2) with soft lilac/pink/teal
           glows instead of the old saturated mesh. Structure + transform-only
           animation kept (already mobile-optimized). */
        background:
            radial-gradient(circle at 14% 10%, rgba(190, 180, 238, 0.55), transparent 40%),
            radial-gradient(circle at 88% 12%, rgba(246, 205, 223, 0.50), transparent 42%),
            radial-gradient(circle at 76% 78%, rgba(178, 216, 238, 0.42), transparent 44%),
            radial-gradient(circle at 18% 86%, rgba(198, 206, 240, 0.40), transparent 42%),
            linear-gradient(-45deg, #edeff7, #f1ecf5, #eaeff8, #eef3f8, #f2eef6, #eaeff8);
    }

    .blob {
        position: absolute;
        border-radius: var(--radius-pill);
        filter: blur(150px);
        will-change: transform;
        opacity: 0.42;
        z-index: 1;
    }

    .bg::before {
        content: '';
        position: absolute;
        inset: -30%;
        background: conic-gradient(from 210deg at 50% 50%,
                rgba(178, 207, 246, 0.42),
                rgba(199, 230, 242, 0.36),
                rgba(208, 196, 224, 0.32),
                rgba(188, 226, 238, 0.4),
                rgba(212, 204, 224, 0.26),
                rgba(170, 202, 242, 0.42),
                rgba(178, 207, 246, 0.42));
        filter: blur(120px) saturate(1.05);
        opacity: 0.5;
        mix-blend-mode: soft-light;
        animation: bgSpectrumFloat 45s ease-in-out infinite alternate;
        animation-delay: var(--bg-spectrum-delay, 0s);
        pointer-events: none;
        z-index: 2;
    }

    .bg::after {
        content: '';
        position: absolute;
        inset: 0;
        background: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.62' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
        opacity: 0.035;
        z-index: 3;
        pointer-events: none;
    }

    /* Blobs slow-drift around their 4-corner placement (transform-only, see the
       mobile-heat note below). The per-page restart issue keyframes once caused is
       avoided via negative animation-delay vars (--bg-blob-*-delay), set in JS so
       each load starts mid-cycle rather than snapping to frame 0. */
    .blob-1 {
        width: 76vmax;
        height: 76vmax;
        top: -32%;
        left: -25%;
        background: rgba(198, 190, 242, 0.40);
        transform: translate(16vw, 16vh) scale(1.1);
        animation: blobDriftOne 32s ease-in-out infinite alternate;
        animation-delay: var(--bg-blob-one-delay, 0s);
    }

    .blob-2 {
        width: 66vmax;
        height: 66vmax;
        bottom: -26%;
        right: -25%;
        background: rgba(245, 202, 224, 0.32);
        transform: translate(-14vw, -13vh) scale(1.12);
        animation: blobDriftTwo 38s ease-in-out infinite alternate-reverse;
        animation-delay: var(--bg-blob-two-delay, 0s);
    }

    .blob-3 {
        width: 60vmax;
        height: 60vmax;
        top: 34%;
        right: -20%;
        background: rgba(182, 216, 236, 0.30);
        transform: translate(-12vw, -10vh) scale(1.08);
        animation: blobDriftThree 34s ease-in-out infinite alternate;
        animation-delay: var(--bg-blob-three-delay, 0s);
    }

    .blob-4 {
        width: 58vmax;
        height: 58vmax;
        bottom: -4%;
        left: -20%;
        background: rgba(200, 208, 242, 0.30);
        transform: translate(14vw, -8vh) scale(1.1);
        animation: blobDriftFour 42s ease-in-out infinite alternate-reverse;
        animation-delay: var(--bg-blob-four-delay, 0s);
    }

    /* Mobile heat fix: blurred layers are expensive to re-rasterize. Animating
       `translate` only moves the cached blurred texture on the compositor (cheap);
       animating `scale`/`rotate` forces a full re-raster of the huge blurred
       surface every frame (GPU pinned → phone heats up). So scale is held CONSTANT
       per keyframe (same visual size, no re-raster) and rotate is dropped. The
       drift path and sizes are visually identical to before. */
    @keyframes bgSpectrumFloat {
        0% {
            transform: translate3d(-2%, -1%, 0) scale(1);
            opacity: 0.62;
        }

        50% {
            transform: translate3d(3%, 2%, 0) scale(1);
            opacity: 0.86;
        }

        100% {
            transform: translate3d(1.5%, -2.5%, 0) scale(1);
            opacity: 0.7;
        }
    }

    @keyframes blobDriftOne {
        0% {
            transform: translate(16vw, 16vh) scale(1.1);
        }

        50% {
            transform: translate(22vw, 12vh) scale(1.1);
        }

        100% {
            transform: translate(13vw, 20vh) scale(1.1);
        }
    }

    @keyframes blobDriftTwo {
        0% {
            transform: translate(-14vw, -13vh) scale(1.12);
        }

        50% {
            transform: translate(-20vw, -17vh) scale(1.12);
        }

        100% {
            transform: translate(-10vw, -10vh) scale(1.12);
        }
    }

    @keyframes blobDriftThree {
        0% {
            transform: translate(-12vw, -10vh) scale(1.08);
        }

        50% {
            transform: translate(-18vw, -6vh) scale(1.08);
        }

        100% {
            transform: translate(-8vw, -14vh) scale(1.08);
        }
    }

    @keyframes blobDriftFour {
        0% {
            transform: translate(14vw, -8vh) scale(1.1);
        }

        50% {
            transform: translate(20vw, -13vh) scale(1.1);
        }

        100% {
            transform: translate(10vw, -5vh) scale(1.1);
        }
    }

    @keyframes bounce {

        0%,
        20%,
        50%,
        80%,
        100% {
            transform: translate3d(-50%, 0, 0);
        }

        40% {
            transform: translate3d(-50%, -6px, 0);
        }

        60% {
            transform: translate3d(-50%, -3px, 0);
        }
    }


    /* When the tab is backgrounded, freeze all looping animations so the GPU can
       idle (set on <html> via the visibilitychange handler in studio.js). */

    /* Decorative background only: freeze the blurred blobs + conic soft-light glow
       once they're scrolled out of view (content covers them) or the tab is hidden,
       so the GPU isn't re-blending huge blurred layers nobody can see. Toggled on
       <html> by the pauseBackgroundWhenAway() handler in utils.js. Purely a perf
       gate — no visible change, since it only fires when the background isn't shown. */
    /* The decorative background is just the soft base gradient (.bg) everywhere now.
       The richer MOVING layers — 4 blurred drifting blobs, the soft-light conic glow,
       the noise grain — are switched OFF app-wide: composited every frame they were a
       constant GPU/battery cost, and stacked with the landing's always-on ribbon they
       caused the scroll micro-stutter. The static gradient keeps the exact same colour
       palette; only the slow colour-drift is gone. To bring the motion back, delete
       this single rule. */
    .blob,
    .bg::before,
    .bg::after {
        display: none;
    }

    html.bg-still .blob,
    html.bg-still .bg::before {
        animation-play-state: paused;
    }

    /* ============ NAVBAR ============ */
    .navbar {
        position: fixed;
        top: 24px;
        left: 0;
        right: 0;
        z-index: 100;
        display: flex;
        justify-content: center;
        padding: 0 24px;
    }

    .nav-logo {
        font-family: var(--font-heading);
        font-size: 16px;
        font-weight: 700;
        color: var(--text);
        text-decoration: none;
        /* Echo the hero wordmark (stretch + tight tracking) but keep the stretch
           mild so the letters grow near-proportionally and read at the same
           height as the menu items. inline-block + left origin keep the visual
           box aligned with the real box (no scaleX tilt). Vertical centering
           with the nav links is handled by the flex align on .nav-inner. */
        display: inline-block;
        transform: scaleX(1.08);
        transform-origin: left center;
        letter-spacing: -0.01em;
    }

    .nav-inner {
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        padding: 10px 28px 10px 28px;
        gap: 28px;
        border-radius: var(--radius-pill);
        background: rgba(255, 255, 255, 0.55);
        border: 1px solid rgba(255, 255, 255, 0.5);
        backdrop-filter: blur(24px);
        -webkit-backdrop-filter: blur(24px);
        box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
    }

    .nav-links {
        display: flex;
        gap: 32px;
    }

    .nav-right {
        display: flex;
        align-items: center;
        gap: 10px;
    }

    .nav-links a {
        text-decoration: none;
        color: rgba(26, 26, 46, 0.7);
        font-size: var(--font-sm);
        font-weight: 500;
        transition: color 0.2s;
        display: inline-flex;
        flex-direction: column;
        align-items: center;
    }

    /* Invisible bold ghost of the label (data-label, set by i18n.js applyLang):
       reserves the ACTIVE (bold) width so the centered nav pill keeps identical
       geometry regardless of which page is active — the pill stays one width across
       pages instead of resizing to the longest bold label. */
    .nav-links a::after {
        content: attr(data-label);
        font-weight: 700;
        height: 0;
        overflow: hidden;
        visibility: hidden;
    }

    .nav-links a:hover {
        color: var(--text);
    }

    .nav-links a.active {
        color: var(--text);
        font-weight: 700;
    }

    .nav-avatar {
        width: 32px;
        height: 32px;
        border-radius: var(--radius-pill);
        display: flex;
        align-items: center;
        justify-content: center;
        color: #5b618a;
        cursor: pointer;
        text-decoration: none;
        transition: all 0.2s;
    }

    .nav-avatar:hover,
    .nav-avatar.active {
        color: var(--text);
    }

    /* Signed-in accent — auth.js updateAuthUI toggles this on session changes. */
    .nav-avatar.logged-in {
        background: var(--accent-soft);
        color: var(--accent);
    }

    /* ============ MOBILE TAB BAR ============
       Bottom navigation for phones. Desktop keeps the top .navbar; on mobile the top
       bar is hidden and this floating glass pill takes over. 5 slots: 2 tabs, a raised
       center FAB (quick flat-lay add), 2 tabs. Markup lives in each app page's <body>.
       v1 — visual is still being iterated. */
    .tabbar { display: none; }

    @media (max-width: 600px) {
        /* Top bar gives way to the bottom bar on phones. */
        .navbar { display: none; }

        .tabbar {
            display: flex;
            align-items: center;
            justify-content: space-around;
            position: fixed;
            left: 12px;
            right: 12px;
            bottom: calc(12px + env(safe-area-inset-bottom, 0px));
            z-index: 100;
            padding: 8px 8px;
            border-radius: 22px;
            background: rgba(255, 255, 255, 0.62);
            border: 1px solid rgba(255, 255, 255, 0.6);
            backdrop-filter: blur(24px);
            -webkit-backdrop-filter: blur(24px);
            box-shadow: 0 6px 28px rgba(0, 0, 0, 0.1);
        }

        .tabbar-item {
            flex: 1;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 3px;
            padding: 4px 0;
            text-decoration: none;
            color: rgba(26, 26, 46, 0.5);
            font-size: 10px;
            font-weight: 600;
            letter-spacing: 0.01em;
            transition: color 0.2s;
        }

        .tabbar-item svg {
            width: 22px;
            height: 22px;
        }

        .tabbar-item.active {
            color: var(--accent);
        }

        /* Raised center action — quick add (deep-links to Studio flat-lay).
           Same floating button as the original circle, just a squircle now. */
        .tabbar-fab {
            flex-shrink: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            width: 52px;
            height: 52px;
            margin: -22px 6px 0;
            border-radius: 16px;
            background: linear-gradient(135deg, var(--accent), #5c79ef);
            color: #fff;
            box-shadow: 0 6px 20px var(--accent-35);
            transition: transform 0.2s;
        }

        .tabbar-fab:active {
            transform: scale(0.94);
        }

        .tabbar-fab svg {
            width: 26px;
            height: 26px;
        }

        /* Keep page content clear of the floating bar. */
        .studio-container {
            padding-bottom: 96px;
        }
    }

    /* Compact language label — reused by the .btn-fab demo in the styleguide. */
    .lang-current-label {
        display: block;
        font-size: var(--font-xs);
        font-weight: 600;
        line-height: 1;
        letter-spacing: 0.04em;
        transform: translateY(-2px);
    }

    @media (max-width: 600px) {
        .nav-links {
            display: none;
        }

        .navbar {
            top: 12px;
            padding: 0 12px;
        }

        .nav-inner {
            justify-content: center;
            padding: 6px 14px;
            gap: 16px;
        }

        .nav-right {
            position: static;
            gap: 6px;
            margin-left: 0;
        }

        .nav-avatar {
            width: 28px;
            height: 28px;
        }

        .nav-avatar svg {
            width: 14px;
            height: 14px;
        }

        .feature-page {
            padding-top: 90px;
        }

        .studio-title {
            font-size: var(--font-lg);
        }

        .studio-sub {
            font-size: var(--font-sm);
            margin-bottom: 16px;
        }

        /* Scale down the whole workspace proportionally */
        .feature-section {
            transform: scale(0.55);
            transform-origin: top center;
            margin-bottom: -30%;
        }

        .hero {
            padding: 60px 16px 40px;
        }

        h1 {
            font-size: clamp(80px, 22vw, 100px);
            transform: scaleX(1.35);
            margin-bottom: 16px;
        }

        .hero-tagline {
            font-size: clamp(14px, 4.8vw, 19px);
            letter-spacing: -0.3px;
            white-space: nowrap;
        }

        /* RU tagline is longer than EN — drop its size a notch so it still fits on
           one line at this breakpoint instead of overflowing. EN keeps its size. */
        html[data-lang="ru"] .hero-tagline {
            font-size: clamp(12px, 4.6vw, 18px);
        }

        .hero-cta {
            padding: 14px 32px;
            font-size: var(--font-base);
            margin-top: 24px;
        }
    }

    /* ============ HERO ============ */
    .hero {
        /* svh (small viewport height), NOT dvh. dvh recomputes live as the mobile
           address bar collapses mid-scroll, growing the hero and shoving content —
           the page appeared to "jerk back" on the first downward scroll. svh is the
           fixed small-viewport value, so the hero never resizes during scroll.
           On desktop svh == vh, so no change there. */
        min-height: 100svh;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        text-align: center;
        padding: 80px 24px 48px;
        position: relative;
    }

    h1 {
        font-family: 'Space Grotesk', sans-serif;
        font-size: clamp(72px, 18vw, 200px);
        font-weight: 700;
        letter-spacing: -0.02em;
        transform: scaleX(1.3);
        color: rgba(26, 26, 46, 0.55);
        text-transform: uppercase;
        line-height: 0.85;
        user-select: none;
        margin-bottom: 24px;
    }

    .hero-tagline {
        font-size: clamp(28px, 5vw, 48px);
        font-weight: 700;
        letter-spacing: -1px;
        line-height: 1.15;
        color: rgba(26, 26, 46, 0.6);
    }

    /* RU tagline uses per-word capitals (to mirror EN Title Case). Enforced in CSS
       so it's robust to translation-string edits and stale caches; EN is untouched,
       keeping its lowercase "of". */
    html[data-lang="ru"] .hero-tagline {
        text-transform: capitalize;
    }

    .hero-tagline em {
        font-style: normal;
        background: linear-gradient(to right,
                #6c5ce7 40%,
                #ebd0f0 48%,
                #ffffff 50%,
                #ebd0f0 52%,
                #6c5ce7 60%);
        background-size: 200% auto;
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        animation: textShimmer 6s linear infinite;
        display: inline-block;
    }

    @keyframes textShimmer {
        0% {
            background-position: 200% center;
        }

        100% {
            background-position: -200% center;
        }
    }

    .hero-cta {
        display: inline-flex;
        align-items: center;
        gap: 10px;
        margin-top: 32px;
        padding: 16px 38px;
        border-radius: var(--radius-pill);
        background: rgba(255, 255, 255, 0.8);
        border: 1.5px solid rgba(255, 255, 255, 0.95);
        color: #1a1a2e;
        backdrop-filter: blur(20px);
        -webkit-backdrop-filter: blur(20px);
        font-family: inherit;
        font-size: var(--font-base);
        font-weight: 600;
        cursor: pointer;
        text-decoration: none;
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
        transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
    }

    .hero-cta svg {
        width: 18px;
        height: 18px;
        color: #bd5e8f;
        transition: color 0.3s, transform 0.3s;
    }

    /* Hover effects only on real pointers — on touchscreens :hover "sticks" after
       a tap (button stays lifted/recolored) until the next interaction elsewhere. */
    @media (hover: hover) {
        .hero-cta:hover {
            transform: translateY(-2px);
            background: #f5eefc;
            border-color: rgba(108, 92, 231, 0.6);
            color: #6c5ce7;
            box-shadow: 0 8px 24px rgba(108, 92, 231, 0.25), 0 8px 24px rgba(189, 94, 143, 0.15);
        }

        .hero-cta:hover svg {
            color: #bd5e8f;
            transform: translateX(4px);
        }
    }

    .hero-cta:active {
        transform: scale(0.97);
    }

    .hero-scroll-hint {
        display: block;
        position: absolute;
        bottom: 28px;
        left: 50%;
        transform: translateX(-50%);
        color: rgba(0, 0, 0, 0.2);
        animation: bounce 2s ease-in-out infinite;
    }

    /* ============ PRICING ============ */
    .pricing-section {
        max-width: var(--container-wide);
        margin: 0 auto;
        padding: 80px 24px 48px;
        text-align: center;
    }

    .pricing-title {
        font-family: var(--font-heading);
        font-size: var(--font-2xl);
        margin-bottom: 28px;
    }

    .pricing-grid {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        gap: 14px;
        align-items: stretch;
    }

    .pricing-card {
        position: relative;
        display: flex;
        flex-direction: column;
        padding: 28px 20px 24px;
        border-radius: var(--radius);
        background: rgba(255, 255, 255, 0.45);
        border: 1px solid rgba(255, 255, 255, 0.65);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        text-align: left;
        transition: transform 0.2s, box-shadow 0.2s;
    }

    .pricing-card:hover {
        transform: translateY(-3px);
        box-shadow: 0 8px 28px var(--accent-10);
    }

    .pricing-card-accent {
        background: rgba(255, 255, 255, 0.6);
        border-color: var(--accent-35);
        box-shadow: 0 4px 20px var(--accent-10);
    }

    .pricing-card-badge {
        position: absolute;
        top: -10px;
        left: 50%;
        transform: translateX(-50%);
        padding: 3px 14px;
        border-radius: var(--radius-pill);
        background: linear-gradient(135deg, var(--accent), #5c79ef);
        color: white;
        font-size: var(--font-xs);
        font-weight: 700;
        letter-spacing: 0.03em;
        text-transform: uppercase;
    }

    .pricing-card-name {
        font-size: var(--font-base);
        font-weight: 700;
        letter-spacing: 0.03em;
        text-transform: uppercase;
        color: var(--text-secondary);
        margin-bottom: 8px;
    }

    .pricing-card-price {
        font-family: var(--font-heading);
        font-size: var(--font-2xl);
        font-weight: 700;
        color: var(--text);
        margin-bottom: 16px;
    }

    .pricing-card-price span {
        font-size: var(--font-base);
        font-weight: 500;
        color: var(--text-secondary);
    }

    .pricing-perks {
        list-style: none;
        padding: 0;
        margin: 0 0 20px;
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 8px;
    }

    .pricing-perks li {
        font-size: var(--font-sm);
        color: var(--text-secondary);
        padding-left: 18px;
        position: relative;
    }

    .pricing-perks li::before {
        content: '✓';
        position: absolute;
        left: 0;
        color: var(--accent);
        font-weight: 700;
        font-size: var(--font-sm);
    }

    /* Plan-select buttons — landing-only polish layered over the shared .btn system.
       Scoped to .pricing-card-btn so app-wide buttons stay untouched. Free/Plus/Pro
       use .btn-ai (glassy outline → fills on hover); Max (Popular) uses .btn-primary
       (gradient fill matching the badge). */
    .pricing-card-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        height: 48px;
        margin-top: auto;
        border-radius: var(--radius-pill);
        font-size: var(--font-base);
        font-weight: 700;
        letter-spacing: 0.01em;
        text-decoration: none;
        cursor: pointer;
        transition: transform 0.2s, box-shadow 0.2s, background 0.2s,
            border-color 0.2s, color 0.2s, filter 0.2s;
    }

    .pricing-card-btn.btn-ai {
        background: rgba(255, 255, 255, 0.7);
        border: 1.5px solid var(--accent-35);
        color: var(--accent);
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
    }

    .pricing-card-btn.btn-ai:hover:not(:disabled) {
        background: var(--accent);
        border-color: var(--accent);
        color: #fff;
        transform: translateY(-2px);
        box-shadow: 0 8px 22px var(--accent-25);
    }

    .pricing-card-btn.btn-primary {
        background: linear-gradient(135deg, var(--accent), #5c79ef);
        border: none;
        color: #fff;
        box-shadow: 0 6px 20px var(--accent-25);
    }

    .pricing-card-btn.btn-primary:hover:not(:disabled) {
        transform: translateY(-2px);
        box-shadow: 0 10px 28px var(--accent-35);
        filter: brightness(1.06);
    }

    @media (max-width: 700px) {
        .pricing-grid {
            display: flex;
            overflow-x: auto;
            scroll-snap-type: x mandatory;
            gap: 16px;
            padding: 16px 24px 32px 24px;
            margin: 0 -24px;
            scroll-padding-left: 24px;
            -ms-overflow-style: none;
            scrollbar-width: none;
        }

        .pricing-grid::-webkit-scrollbar {
            display: none;
        }

        .pricing-card {
            width: 245px;
            flex-shrink: 0;
            scroll-snap-align: center;
        }
    }

    /* ============ SITE FOOTER (landing only) ============
       Marketing footer for index.html. App-pages don't include this — legal
       links live in profile.html via .prof-legal instead. */
    .site-footer {
        margin-top: 30px;
        padding: 24px 24px 40px;
        text-align: center;
        color: var(--text-secondary);
    }

    .site-footer-inner {
        max-width: var(--container);
        margin: 0 auto;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 8px;
    }

    .site-footer-brand {
        font-family: 'Space Grotesk', 'Inter', sans-serif;
        font-size: var(--font-lg);
        font-weight: 700;
        letter-spacing: 1px;
        color: var(--text);
        text-decoration: none;
    }

    .site-footer-tagline {
        font-size: var(--font-sm);
        color: var(--text-secondary);
        margin-bottom: 10px;
    }

    .site-footer-links {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 14px;
        margin-bottom: 12px;
        flex-wrap: wrap;
        font-size: var(--font-sm);
    }

    .site-footer-links a {
        color: var(--text-secondary);
        text-decoration: none;
        transition: color 0.2s;
    }

    .site-footer-links a:hover {
        color: var(--text);
    }

    .site-footer-divider {
        color: var(--text-tertiary);
    }

    .site-footer-copyright {
        font-size: var(--font-sm);
        color: var(--text-tertiary);
        letter-spacing: 0.3px;
    }

    /* ============ PROFILE LEGAL ROW ============
       Page-level footer for profile.html — Privacy/Terms reachable from
       the app without polluting other working pages. Sits at the bottom of
       the viewport via the sticky-footer pattern: body becomes flex column,
       the footer's `margin-top: auto` pushes it to the bottom regardless
       of how short the content is. */
    body.profile-body {
        display: flex;
        flex-direction: column;
    }

    .prof-legal {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        gap: 10px;
        flex-wrap: wrap;
        font-size: var(--font-sm);
        color: var(--text-tertiary);
    }

    .prof-legal a {
        color: var(--text-secondary);
        text-decoration: none;
        transition: color 0.2s;
    }

    .prof-legal a:hover {
        color: var(--text);
    }

    .prof-legal-sep {
        color: var(--text-tertiary);
    }

    /* ============ LEGAL PAGES (privacy.html / terms.html) ============
       Обе языковые версии лежат в разметке; дефолт — RU, EN включается по
       html[data-lang="en"] (ставит i18n.js до рендера). */
    .legal-en {
        display: none;
    }

    html[data-lang="en"] .legal-ru {
        display: none;
    }

    html[data-lang="en"] .legal-en {
        display: block;
    }

    .legal-page {
        max-width: var(--container);
        margin: 0 auto;
        padding: 140px 24px 80px;
        color: var(--text);
    }

    /* Сброс героического h1 лендинга (uppercase + scaleX + прозрачный цвет) —
       на юр-страницах заголовок в типографике диалогов. */
    .legal-page h1 {
        font-family: 'Space Grotesk', 'Inter', sans-serif;
        font-size: var(--font-2xl);
        font-weight: 700;
        letter-spacing: -0.5px;
        text-transform: none;
        transform: none;
        color: var(--text);
        line-height: 1.2;
        margin-bottom: 14px;
    }

    .legal-page h2 {
        font-size: var(--font-lg);
        font-weight: 600;
        margin: 32px 0 12px;
    }

    .legal-date {
        font-size: var(--font-sm);
        color: var(--text-secondary);
        margin-bottom: 28px;
    }

    .legal-page ul {
        margin: 0 0 14px 20px;
        padding: 0;
        font-size: var(--font-base);
        line-height: 1.7;
        color: var(--text-secondary);
    }

    .legal-page li {
        margin-bottom: 8px;
    }

    .legal-page a {
        color: var(--accent);
    }

    .legal-page p {
        font-size: var(--font-base);
        line-height: 1.7;
        color: var(--text-secondary);
        margin-bottom: 14px;
    }

    .legal-back {
        display: inline-block;
        margin-top: 32px;
        color: var(--accent);
        text-decoration: none;
        font-size: var(--font-base);
        font-weight: 500;
    }

    .legal-back:hover {
        text-decoration: underline;
    }

    /* ============================================================================
       AUTH MODAL (shared) — moved here from app.css.
       auth.js injects the sign-in overlay into EVERY page, and the landing uses it
       too: the guest "Get Started" CTA opens it inline (auth.js initAuthGate), and
       password-reset links redirect back to /index.html and open it in recovery
       mode. The landing loads only this file (not app.css), so these styles must
       live here or the modal renders unstyled/visible at the bottom of the page.
       Single source of truth — NOT duplicated in app.css.
       ========================================================================== */

    @keyframes fadeIn {
        from { opacity: 0; }
        to   { opacity: 1; }
    }

    @keyframes authSlideUp {
        from {
            opacity: 0;
            transform: translateY(20px) scale(0.97);
        }

        to {
            opacity: 1;
            transform: translateY(0) scale(1);
        }
    }

    .auth-overlay {
        position: fixed;
        inset: 0;
        z-index: 1000;
        background: rgba(0, 0, 0, 0.4);
        backdrop-filter: blur(6px);
        -webkit-backdrop-filter: blur(6px);
        display: flex;
        align-items: center;
        justify-content: center;
        animation: fadeIn 0.2s;
    }

    .auth-overlay.hidden {
        display: none;
    }

    .auth-modal {
        position: relative;
        width: 380px;
        max-width: 90vw;
        padding: 40px 36px 32px;
        border-radius: var(--radius);
        background: rgba(255, 255, 255, 0.82);
        border: 1px solid rgba(255, 255, 255, 0.5);
        backdrop-filter: blur(32px);
        -webkit-backdrop-filter: blur(32px);
        box-shadow:
            0 8px 32px var(--accent-10),
            0 24px 64px rgba(0, 0, 0, 0.10);
        animation: authSlideUp 0.35s cubic-bezier(0.16, 1, 0.3, 1);
    }

    /* Phones: the desktop sizing reads as oversized. Scale the whole modal down
       proportionally (width, padding, logo, headings, controls) so it stays
       compact and usable. Compound selectors beat the base .modal-sm rules. */
    @media (max-width: 480px) {
        .auth-overlay .auth-modal {
            max-width: 300px;
            padding: 22px 22px 20px;
        }

        .auth-modal .auth-logo {
            width: 40px;
            height: 40px;
            margin-bottom: 12px;
            font-size: var(--font-base);
        }

        .auth-modal .auth-title {
            font-size: var(--font-lg);
        }

        .auth-modal .auth-subtitle {
            font-size: var(--font-sm);
            margin-bottom: 16px;
        }

        .auth-modal .auth-form {
            gap: 10px;
        }

        .auth-modal .auth-input {
            padding: 11px 14px;
        }

        .auth-modal .auth-google {
            padding: 10px 14px;
            margin-bottom: 10px;
        }

        .auth-modal .auth-submit {
            padding: 12px;
        }
    }

    .auth-logo {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 52px;
        height: 52px;
        margin: 0 auto 16px;
        border-radius: var(--radius-sm);
        background: linear-gradient(135deg, var(--accent), #8b7cf8);
        box-shadow: 0 4px 16px var(--accent-glow);
        font-size: var(--font-lg);
        color: white;
    }

    .auth-title {
        font-size: var(--font-xl);
        font-weight: 700;
        text-align: center;
        margin-bottom: 6px;
        color: var(--text);
    }

    .auth-subtitle {
        text-align: center;
        font-size: var(--font-base);
        color: var(--text-secondary);
        margin-bottom: 24px;
    }

    .auth-form {
        display: flex;
        flex-direction: column;
        gap: 12px;
    }

    .auth-input {
        padding: 14px 16px;
        border-radius: var(--radius-sm);
        border: 1.5px solid rgba(0, 0, 0, 0.08);
        background: rgba(245, 245, 247, 0.7);
        font-size: var(--font-base);
        font-family: inherit;
        color: var(--text);
        outline: none;
        transition: all 0.2s;
    }

    .auth-input:focus {
        border-color: var(--accent);
        background: rgba(255, 255, 255, 0.9);
        box-shadow: 0 0 0 3px var(--accent-10);
    }

    .auth-input::placeholder {
        color: var(--text-tertiary);
    }

    /* Password input + show/hide eye toggle */
    .auth-pass-wrap {
        position: relative;
        display: flex;
    }

    .auth-pass-input {
        flex: 1;
        padding-right: 44px;
        /* room for the toggle button */
    }

    .auth-pass-toggle {
        position: absolute;
        right: 4px;
        top: 50%;
        transform: translateY(-50%);
        width: 36px;
        height: 36px;
        border: none;
        background: transparent;
        color: var(--text-tertiary);
        cursor: pointer;
        border-radius: var(--radius-xs);
        display: inline-flex;
        align-items: center;
        justify-content: center;
        transition: color 0.15s, background 0.15s;
    }

    .auth-pass-toggle:hover {
        color: var(--accent);
        background: var(--accent-10);
    }

    .auth-input-error {
        border-color: var(--danger) !important;
        background: rgba(220, 78, 94, 0.04) !important;
        animation: authShake 0.35s;
    }

    .auth-error {
        font-size: var(--font-sm);
        color: var(--danger);
        text-align: center;
        padding: 6px 12px;
        border-radius: var(--radius-xs);
        background: rgba(220, 78, 94, 0.06);
        animation: fadeIn 0.2s;
    }

    .auth-error.hidden {
        display: none;
    }

    .auth-error.auth-error-success {
        color: #1f8a4f;
        background: rgba(31, 138, 79, 0.08);
    }

    .auth-bottom {
        display: flex;
        align-items: center;
        margin-top: 18px;
        gap: 12px;
    }

    .auth-bottom[data-mode="signin"] {
        justify-content: space-between;
    }

    .auth-bottom[data-mode="signup"] {
        justify-content: center;
    }

    .auth-back {
        position: absolute;
        top: 14px;
        left: 14px;
        width: 32px;
        height: 32px;
        display: flex;
        align-items: center;
        justify-content: center;
        background: rgba(0, 0, 0, 0.04);
        border: none;
        border-radius: var(--radius-xs);
        color: var(--text-secondary);
        cursor: pointer;
        transition: all 0.2s;
    }

    .auth-back:hover {
        background: rgba(0, 0, 0, 0.08);
        color: var(--text);
    }

    .auth-bottom .auth-switch {
        margin: 0;
    }

    .auth-forgot {
        background: none;
        border: none;
        padding: 0;
        font-size: var(--font-sm);
        color: var(--text-secondary);
        cursor: pointer;
        font-family: inherit;
    }

    .auth-forgot:hover {
        color: var(--accent);
        text-decoration: underline;
    }

    .auth-forgot.hidden,
    .auth-pass-wrap.hidden,
    .auth-input.hidden,
    .auth-switch.hidden,
    .auth-divider.hidden,
    .auth-google.hidden {
        display: none !important;
    }

    .auth-google {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 10px;
        width: 100%;
        padding: 12px 16px;
        margin-bottom: 14px;
        border-radius: var(--radius-sm);
        border: 1.5px solid rgba(0, 0, 0, 0.10);
        background: white;
        color: var(--text);
        font-size: var(--font-base);
        font-weight: 500;
        font-family: inherit;
        cursor: pointer;
        transition: all 0.2s;
    }

    .auth-google:hover {
        background: rgba(245, 245, 247, 0.9);
        border-color: rgba(0, 0, 0, 0.18);
    }

    .auth-google:disabled {
        opacity: 0.5;
        cursor: default;
    }

    .auth-divider span {
        padding: 0 8px;
    }

    @keyframes authShake {

        0%,
        100% {
            transform: translateX(0);
        }

        20% {
            transform: translateX(-6px);
        }

        40% {
            transform: translateX(6px);
        }

        60% {
            transform: translateX(-4px);
        }

        80% {
            transform: translateX(4px);
        }
    }

    .auth-submit {
        padding: 14px;
        border-radius: var(--radius-sm);
        border: none;
        background: linear-gradient(135deg, var(--accent), #8b7cf8);
        color: white;
        font-size: var(--font-base);
        font-weight: 600;
        font-family: inherit;
        cursor: pointer;
        transition: all 0.25s;
        box-shadow: 0 4px 16px var(--accent-glow);
        margin-top: 4px;
    }

    .auth-submit:hover {
        transform: translateY(-2px);
        box-shadow: 0 6px 20px var(--accent-35);
    }

    .auth-submit:disabled {
        opacity: 0.5;
        cursor: default;
        transform: none;
        box-shadow: none;
    }

    .auth-divider {
        display: flex;
        align-items: center;
        gap: 12px;
        margin: 6px 0 2px;
        color: var(--text-tertiary);
        font-size: var(--font-sm);
    }

    .auth-divider::before,
    .auth-divider::after {
        content: '';
        flex: 1;
        height: 1px;
        background: rgba(0, 0, 0, 0.08);
    }

    .auth-switch {
        text-align: center;
        margin-top: 20px;
        font-size: var(--font-sm);
        color: var(--text-secondary);
    }

    .auth-switch-btn {
        background: none;
        border: none;
        color: var(--accent);
        font-weight: 600;
        font-size: var(--font-sm);
        cursor: pointer;
        font-family: inherit;
    }

    .auth-switch-btn:hover {
        text-decoration: underline;
    }

    /* Cross-document View Transitions removed: navigation is now instant/native.
       The page entrance is driven per-element on the live DOM instead (data-enter,
       see app.css) so the pill/toolbar/content ease in individually while the
       nav/tab bar stays pinned. */

}

/* utils — the last layer, so these win over every component rule regardless of
   selector length. Motion-reduction and .hidden must never be overridable. */
@layer utils {

    @media (prefers-reduced-motion: reduce) {

        *,
        *::before,
        *::after {
            animation-duration: 0.001ms !important;
            animation-iteration-count: 1 !important;
            transition-duration: 0.001ms !important;
        }
    }

    /* Backgrounded tab: freeze looping animations so the GPU can idle (set on
       <html> by the visibilitychange handler in studio.js). */
    html.anim-paused *,
    html.anim-paused *::before,
    html.anim-paused *::after {
        animation-play-state: paused !important;
    }

    .hidden {
        display: none !important;
    }
}
