/* AUTO-GENERATED by tools/css_modular.py build
 * Do not edit this file directly — your changes will be overwritten.
 * Source lives in pinked-web/css/sections/_00…_12.css
 */
/* ============================================
   Pinked & Owned — Velvet Noir
   Complete game stylesheet
   ============================================ */

/* ============================================
   1. CSS VARIABLES
   ============================================ */
:root {
    /* Backgrounds */
    --bg-deep: #08060c;
    --bg: #0e0b14;
    --bg-warm: #140f1e;
    --bg-panel: #1a1428;
    --bg-choice: #1c1630;
    --bg-choice-hover: #261e3c;
    --bg-card: #18132a;
    --bg-card-hover: #201a34;
    --bg-overlay: rgba(8, 6, 12, 0.92);

    /* Borders */
    --border: #2e2242;
    --border-glow: #6e3c7a;
    --border-selected: #e478b8;

    /* Accent colors */
    --rose: #e88cb8;
    --rose-bright: #f4a0cc;
    --orchid: #c470e0;
    --gold: #e8c860;

    /* Text */
    --text: #ddd4ec;
    --text-soft: #d4cae6; /* between --text and --text-body — editor sub-headers. Was referenced undefined in _01/_05/_12. */
    --text-body: #c8beda;
    --text-dim: #a89ab8;
    --text-faint: #968bac; /* Audit D33: was #706480 (~3.4:1 fail AA on bg-card). #968bac ~5:1 AA pass, keeps hierarchy under text-dim. */

    /* Stat colors */
    --energy: #5cd89c;
    --energy-low: #d8a040;
    --energy-crit: #d86050;
    --arousal: #e06878;
    --masc: #5888cc;
    --fem: #e478b8;
    --sub: #a880e0;
    --shame: #c09060;

    /* Functional */
    --green: #5cd89c;
    --red: #e06060;
    --orange: #e0a050;
    --shadow-color: rgba(0, 0, 0, 0.5);
    --glow-rose: rgba(228, 140, 184, 0.15);

    /* Layout */
    --topbar-height: 60px;
    /* Audit D38: symmetric panels. Was 270/250 (asymmetric). 240/240 reads
       as balanced and saves 40px of total chrome at default zoom. */
    --left-column-width: 240px;
    --right-column-width: 268px;

    /* Z-Index Layer Map */
    --z-background: 0;
    --z-panel-glow: 1;
    --z-ui: 10;
    --z-topbar: 50;
    --z-drawer-backdrop: 99;
    --z-drawer: 100;
    --z-overlay-backdrop: 199;
    --z-overlay: 200;
    --z-modal: 500;
    --z-vignette: 9998;
    --z-grain: 10000;

    /* Audit D30: above-grain layer for toasts/notifs + image-viewer overlays
       that must sit above pause overlay + grain texture. Was 10001/10100/11000
       sprinkled across the codebase; these tokens normalize the ladder. */
    --z-toast: 10001;
    --z-image-viewer: 10100;
    --z-modal-top: 11000;
    --z-achievement-toast: 11001;

    /* Legacy aliases (referenced by existing code) */
    --overlay-z: var(--z-overlay);
    --backdrop-z: var(--z-overlay-backdrop);

    /* Backdrop Blur Scale */
    --blur-sm: 8px;
    --blur-md: 12px;
    --blur-lg: 16px;

    /* Typography */
    --font-size-base: 16px;

    /* Overlay/popup readability scale (v0.2.5.7.6 — driven by Font Size +
       UI Scale settings sliders via settings.js). 1.0 = native. Applied as
       `zoom` on inner overlay containers (.overlay-box / .phone-frame /
       tooltips) so popups respect the readability sliders. zoom ON inner
       container ≠ position:fixed root, so no clipping bug. */
    --overlay-zoom: 1;

    /* Screen Edge Buffer (v0.2.8, player ask) — manual left/right dead zone
       for camera cutouts / Android gesture zones in landscape. Driven by the
       settings slider via settings.js (_applyEdgeBuffer, PnO_EdgeBuffer).
       Consumed on body as max(var(--edge-buffer), env(safe-area-inset-*)). */
    --edge-buffer: 0px;

    /* Transitions */
    --ease-out: cubic-bezier(0.4, 0, 0.2, 1);
    --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);

    /* Aliases (used by newer UI components) */
    --accent: var(--rose);
    --accent-dim: rgba(228, 140, 184, 0.08);
    --text-muted: var(--text-dim);
    --bg-lighter: var(--bg-panel);

    /* ─── Pink Rationing (v0.2.4) ───────────────────────────
       Pink (--rose) is reserved for THREE meanings only:
         1. Player Presentation stat (Fem fill, --fem)
         2. Narrative milestone highlights and Continue button
         3. Primary call-to-action moments
       Every other "accent" state uses --accent-soft (orchid/purple).
       Do not introduce new var(--rose) uses without checking. */
    --accent-soft: var(--orchid);             /* hover, focus, secondary highlights */
    --accent-soft-dim: rgba(196, 112, 224, 0.10);
    --border-hover: var(--orchid);            /* replaces var(--rose) on hover borders */

    /* Design tokens */
    --radius-sm: 6px;
    --radius-md: 8px;
    --radius-lg: 12px;
    --radius-xl: 14px;
    --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.35);
    --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.45);
}


/* ============================================
   2. RESET + BASE STYLES + FONTS
   ============================================ */
*, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
    height: 100%;
    background: var(--bg-deep);
    color: var(--text);
    font-family: 'DM Sans', 'PingFang SC', 'Microsoft YaHei', 'Noto Sans SC', 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', 'Twemoji Mozilla', sans-serif;
    overflow: hidden;
    -webkit-text-size-adjust: none;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* Mobile gesture hardening: single-tap, scroll, pinch and pan all keep
       working; only double-tap-zoom and the long-press callout are dropped.
       Those two gestures (double tap-and-hold) trigger a hard freeze on
       Chromium 147/148 Android WebView and the game uses neither. Pure
       defensive mitigation for an upstream browser regression.
       Foundby:Mist v0.2.7.3.1 (Galaxy Tab S9 Ultra). */
    touch-action: manipulation;
    -webkit-touch-callout: none;
}

body {
    display: flex;
    flex-direction: column;
    height: 100dvh;
    padding-top: env(safe-area-inset-top, 0px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    /* Left/right: OS safe-area OR the user's manual Edge Buffer setting,
       whichever is larger. Android WebViews report 0 for landscape camera
       cutouts, so the manual buffer is the only reliable dead zone there
       (player ask 0.2.7.6.1, Pixel 9 pinhole camera). */
    padding-left: max(var(--edge-buffer, 0px), env(safe-area-inset-left, 0px));
    padding-right: max(var(--edge-buffer, 0px), env(safe-area-inset-right, 0px));
    background:
        radial-gradient(ellipse at 50% 20%, rgba(100, 40, 80, 0.06) 0%, transparent 60%),
        radial-gradient(ellipse at 80% 80%, rgba(60, 30, 100, 0.04) 0%, transparent 50%),
        var(--bg-deep);
}

a { color: var(--rose); text-decoration: none; }
a:hover { color: var(--rose-bright); }

/* ============================================
   VELVET NOIR 2.0 — Visual Polish Pass
   Luxury, depth, micro-interactions
   ============================================ */

/* Richer body atmosphere — subtle vignette + warmer glow */
body::after {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: var(--z-vignette);
    background: radial-gradient(ellipse at center, transparent 50%, rgba(4, 2, 8, 0.35) 100%);
}

/* Overlay header — gradient underline */
.overlay-header::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 10%;
    right: 10%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(228, 140, 184, 0.2), rgba(196, 112, 224, 0.15), transparent);
}

/* Choice button — top highlight line */
.choice-btn::after {
    content: '';
    position: absolute;
    top: 0;
    left: 15%;
    right: 15%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(196, 112, 224, 0.08), transparent);
    pointer-events: none;
}

@keyframes dramatic-pulse {
    0%, 100% { box-shadow: 0 0 20px rgba(228, 140, 184, 0.06); }
    50% { box-shadow: 0 0 30px rgba(228, 140, 184, 0.15); }
}

/* scaleX optimization only for single-fill bars (not dual-fill presentation bar) */
.stat-fill:not(.masc-fill):not(.fem-fill) {
    transform-origin: left center;
    will-change: transform;
}

/* Save slot row — data-present accent */
.save-slot-row.save-slot-has-data .slot-label {
    color: var(--rose-bright);
}

/* Topbar — frosted glass */
.topbar {
    backdrop-filter: blur(var(--blur-md));
    -webkit-backdrop-filter: blur(var(--blur-md));
    background: rgba(8, 6, 12, 0.85);
}

/* Left/right panels — subtle inner glow at top */
.left-column::before, .right-column::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 60px;
    background: linear-gradient(180deg, rgba(140, 60, 100, 0.03), transparent);
    pointer-events: none;
    z-index: 1;
}

/* Character panel name — luxury letter spacing */
.char-panel-name {
    letter-spacing: 3px;
    text-shadow: 0 0 20px rgba(228, 140, 184, 0.12);
}

@keyframes gradient-flow {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}
@keyframes separator-pulse {
    0%, 100% { opacity: 0.3; }
    50% { opacity: 0.7; }
}

/* Cards — inner top shimmer line */
.card::before {
    height: 2px !important;
    background: linear-gradient(90deg, transparent 20%, rgba(228, 140, 184, 0.12) 50%, transparent 80%) !important;
}
.card.selected::before {
    background: linear-gradient(90deg, transparent 10%, var(--rose) 50%, transparent 90%) !important;
    opacity: 0.5;
}

/* Phone overlay — subtle inner shadow for depth */
.phone-box {
    box-shadow:
        0 16px 48px rgba(0, 0, 0, 0.6),
        inset 0 0 40px rgba(0, 0, 0, 0.15) !important;
}

/* Webshop products — hover lift */
.webshop-product {
    transition: all 0.25s var(--ease-out) !important;
}
.webshop-product:hover:not(.webshop-maxed) {
    transform: translateY(-3px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}

/* Tutorial hint — glass morphism override */
.tutorial-hint {
    backdrop-filter: blur(var(--blur-lg)) !important;
    -webkit-backdrop-filter: blur(var(--blur-lg)) !important;
}

/* Language popup buttons — hover glow */
.language-popup-btn:hover {
    box-shadow: 0 0 20px rgba(228, 140, 184, 0.1);
    transform: translateX(4px);
}
.language-popup-btn {
    transition: all 0.2s var(--ease-out) !important;
}

/* Streaming header — live badge neon pulse */
.stream-badge-live {
    animation: live-neon 2s ease-in-out infinite;
    text-shadow: 0 0 6px rgba(232, 80, 80, 0.5);
}
@keyframes live-neon {
    0%, 100% { box-shadow: 0 0 4px rgba(232, 80, 80, 0.3), 0 0 10px rgba(232, 80, 80, 0.1); }
    50% { box-shadow: 0 0 12px rgba(232, 80, 80, 0.6), 0 0 24px rgba(232, 80, 80, 0.2), inset 0 0 6px rgba(232, 80, 80, 0.1); }
}

/* Image modal — cinematic letterbox feel */
#image-modal {
    backdrop-filter: blur(var(--blur-sm));
    -webkit-backdrop-filter: blur(var(--blur-sm));
}

/* ============================================
   END VELVET NOIR 2.0
   ============================================ */

/* C1: Global focus states for keyboard/accessibility */
button:focus-visible, a:focus-visible, select:focus-visible,
.choice-btn:focus-visible, .card:focus-visible, [tabindex]:focus-visible {
    outline: 2px solid var(--rose);
    outline-offset: 2px;
    box-shadow: 0 0 12px rgba(228, 140, 184, 0.2);
}

/* M1: Firefox scrollbar styling */
* { scrollbar-width: thin; scrollbar-color: rgba(140, 100, 180, 0.3) transparent; }

/* C4: Empty state fallbacks for dynamically populated containers */
#shop-items:empty::after, #achievement-grid:empty::after,
#gallery-grid:empty::after, #history-content:empty::after,
#journal-content:empty::after {
    content: '...';
    display: block; text-align: center; padding: 32px;
    color: var(--text-faint); font-size: 12px; font-style: italic;
}

button {
    font-family: inherit;
    border: none;
    background: none;
    cursor: pointer;
    color: inherit;
}

input, textarea, select {
    font-family: inherit;
    color: var(--text);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 8px;
    outline: none;
    transition: border-color 0.25s, box-shadow 0.25s;
}

input:focus, textarea:focus {
    border-color: var(--rose);
    box-shadow: 0 0 12px rgba(232, 140, 184, 0.1);
}

input::placeholder, textarea::placeholder {
    color: var(--text-faint);
}

::-webkit-scrollbar { width: 4px; }
::-webkit-scrollbar-thumb { background: rgba(140, 100, 180, 0.3); border-radius: 2px; }
::-webkit-scrollbar-track { background: transparent; }

.hidden { display: none !important; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }


/* ============================================
   3. FILM GRAIN OVERLAY
   ============================================ */
.grain-overlay {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: var(--z-grain);
    opacity: 0.008;
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='5' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.7'/%3E%3C/svg%3E");
    background-size: 256px;
}


/* ============================================
   4. SCREEN MANAGEMENT
   ============================================ */
.screen {
    display: none;
    width: 100%;
    height: 100%;
    flex-direction: column;
    position: relative;
    animation: screen-fade-in 0.4s ease both;
}

.screen.active {
    display: flex;
}

@keyframes screen-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

.screen-transition-out {
    animation: screen-fade-out 0.3s ease both;
}

@keyframes screen-fade-out {
    from { opacity: 1; }
    to { opacity: 0; }
}


/* ============================================
   5. MAIN MENU
   ============================================ */
#screen-main-menu {
    align-items: center;
    /* Use flex-start + margin:auto on .menu-layout instead of justify-content:center.
       On mobile where the menu (title + 4 buttons + settings + CTA buttons) can
       exceed the viewport, justify-content:center pushes the top content above
       the scroll origin, making New Game / Continue unreachable — only Quick
       Start stays visible. margin:auto still centers when content fits, but
       collapses to 0 when scrolling is needed so the top stays reachable. */
    justify-content: flex-start;
    overflow-y: auto;
    background:
        radial-gradient(ellipse at 50% 30%, rgba(140, 60, 100, 0.08) 0%, transparent 60%),
        radial-gradient(ellipse at 30% 80%, rgba(80, 40, 140, 0.06) 0%, transparent 50%),
        var(--bg-deep);
}

.menu-layout {
    display: flex;
    gap: 48px;
    max-width: 900px;
    width: 100%;
    padding: 40px 24px;
    align-items: flex-start;
    /* Vertically centers when content fits, falls through to top-aligned
       scrolling when content overflows (see #screen-main-menu comment). */
    margin: auto;
}

.menu-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 24px;
}

.menu-logo-area {
    text-align: center;
    margin-bottom: 12px;
}

.menu-title {
    font-family: 'Crimson Pro', Georgia, serif;
    font-size: 48px;
    font-weight: 600;
    letter-spacing: 4px;
    line-height: 1.1;
    position: relative;
    background: linear-gradient(90deg, var(--rose) 0%, var(--rose-bright) 40%, #fff 50%, var(--rose-bright) 60%, var(--rose) 100%);
    background-size: 200% auto;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: title-shimmer 8s ease-in-out infinite;
}
.menu-title::after {
    content: 'Pinked & Owned';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    text-shadow: 0 0 40px rgba(232, 140, 184, 0.15);
    -webkit-text-fill-color: transparent;
    background: none;
    pointer-events: none;
    z-index: -1;
}
@keyframes title-shimmer {
    0%, 100% { background-position: 200% center; }
    50% { background-position: 0% center; }
}

.menu-title-amp {
    color: var(--orchid);
    font-style: italic;
    -webkit-text-fill-color: var(--orchid);
}

.menu-subtitle {
    font-family: 'DM Sans', sans-serif;
    font-style: normal;
    color: var(--text-faint);
    font-size: 10px;
    margin-top: 10px;
    letter-spacing: 3px;
    text-transform: uppercase;
}
.menu-subtitle::after {
    content: '\2014 \2726 \2014';
    display: block;
    margin-top: 12px;
    color: var(--text-faint);
    letter-spacing: 6px;
    font-size: 10px;
}

.menu-buttons {
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 280px;
}

.btn-menu-primary {
    height: 52px;
    background: linear-gradient(135deg, #4a2040 0%, #703060 50%, #5c2848 100%);
    border: 1px solid rgba(228, 140, 184, 0.2);
    border-radius: 10px;
    color: #eedce8;
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    transition: all 0.25s var(--ease-out);
    position: relative;
    overflow: hidden;
    box-shadow: 0 2px 12px rgba(112, 48, 96, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

.btn-menu-primary::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.04), transparent);
    transform: translateX(-100%);
    transition: transform 0.4s ease;
}

.btn-menu-primary:hover::before { transform: translateX(100%); }
.btn-menu-primary:hover {
    box-shadow: 0 6px 24px rgba(128, 56, 112, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.08);
    border-color: rgba(228, 140, 184, 0.35);
    transform: translateY(-1px);
}
.btn-menu-primary:active { transform: scale(0.98); }

.btn-menu-secondary {
    height: 44px;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text-dim);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 1px;
    transition: all 0.2s ease;
}
.btn-menu-secondary:hover {
    border-color: var(--border-glow);
    color: var(--text);
}
.btn-quick-start {
    font-size: 12px;
    height: 40px;
    opacity: 0.85;
    letter-spacing: 1.5px;
    text-transform: uppercase;
}
.btn-quick-start:hover { opacity: 1; border-color: var(--accent-soft); }
.btn-hint {
    font-size: 10px;
    opacity: 0.65;
    font-style: italic;
    text-transform: none;
    letter-spacing: 0.3px;
    margin-left: 6px;
    color: var(--accent-soft);
}

.menu-footer-buttons {
    display: flex;
    gap: 10px;
    width: 280px;
}

.btn-menu-ghost {
    flex: 1;
    height: 40px;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text-dim);
    font-size: 12px;
    letter-spacing: 0.5px;
    transition: all 0.2s ease;
}
.btn-menu-ghost:hover {
    border-color: var(--rose);
    color: var(--text);
}

/* ============================================
   CTA Buttons (Patreon, Discord) — full-width, two-line, branded
   ============================================ */
.btn-cta {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    padding: 12px 16px;
    border-radius: 12px;
    text-decoration: none;
    position: relative;
    overflow: hidden;
    cursor: pointer;
    border: 1px solid rgba(255, 255, 255, 0.08);
    transition: transform 0.25s var(--ease-out), box-shadow 0.25s ease, border-color 0.25s ease;
    isolation: isolate;
}
.btn-cta:hover {
    transform: translateY(-2px);
    border-color: rgba(255, 255, 255, 0.2);
}

.btn-cta-icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.18);
    border-radius: 50%;
    font-size: 22px;
    line-height: 1;
    color: #fff;
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
}
.btn-cta-icon svg {
    width: 22px;
    height: 22px;
    fill: currentColor;
    display: block;
}

.btn-cta-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    text-align: left;
    flex: 1;
    min-width: 0;
}
.btn-cta-main {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.3px;
    line-height: 1.2;
    color: #fff;
}
.btn-cta-sub {
    font-size: 10px;
    font-weight: 400;
    line-height: 1.35;
    letter-spacing: 0.1px;
    color: rgba(255, 255, 255, 0.82);
}

/* Diagonal shine sweep on hover */
.btn-cta-shine {
    position: absolute;
    top: 0;
    left: -120%;
    width: 70%;
    height: 100%;
    background: linear-gradient(110deg, transparent 0%, rgba(255, 255, 255, 0.22) 50%, transparent 100%);
    pointer-events: none;
    transition: left 0.7s ease;
    z-index: 1;
}
.btn-cta:hover .btn-cta-shine {
    left: 130%;
}

/* Patreon variant — coral/rose gradient with pulsing heart */
.btn-cta-patreon {
    background: linear-gradient(135deg, #f96854 0%, #e04442 55%, #c8333f 100%);
    box-shadow:
        0 4px 16px rgba(249, 104, 84, 0.28),
        inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
.btn-cta-patreon:hover {
    box-shadow:
        0 10px 30px rgba(249, 104, 84, 0.5),
        inset 0 1px 0 rgba(255, 255, 255, 0.3);
}
.btn-cta-patreon .btn-cta-icon {
    color: #fff5f0;
    text-shadow: 0 0 8px rgba(255, 255, 255, 0.5);
    animation: cta-heart-pulse 2.4s ease-in-out infinite;
}
@keyframes cta-heart-pulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.1); }
}

/* SubscribeStar variant — amber/gold gradient, the adult-friendly twin of
   the Patreon CTA. Brand gold is #d9a020 (matches the landing-page
   section-subscribestar accent). Base of the gradient is kept deep enough
   that the 82%-white sub line clears WCAG contrast; a text-shadow on the
   labels backs that up over the lighter top-left of the diagonal. Shadow is
   a touch softer than Patreon's so Patreon stays the primary CTA. */
.btn-cta-subscribestar {
    background: linear-gradient(135deg, #e6b53e 0%, #c4901c 52%, #9c6f12 100%);
    box-shadow:
        0 3px 14px rgba(217, 160, 32, 0.24),
        inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.btn-cta-subscribestar:hover {
    box-shadow:
        0 9px 28px rgba(217, 160, 32, 0.44),
        inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
.btn-cta-subscribestar .btn-cta-main,
.btn-cta-subscribestar .btn-cta-sub {
    text-shadow: 0 1px 2px rgba(74, 48, 0, 0.5);
}
.btn-cta-subscribestar .btn-cta-icon {
    color: #fff8e8;
    text-shadow: 0 0 8px rgba(255, 240, 200, 0.5);
}

/* Discord variant — Blurple gradient */
.btn-cta-discord {
    background: linear-gradient(135deg, #5865f2 0%, #4752c4 55%, #3c45a5 100%);
    box-shadow:
        0 4px 16px rgba(88, 101, 242, 0.28),
        inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
.btn-cta-discord:hover {
    box-shadow:
        0 10px 30px rgba(88, 101, 242, 0.5),
        inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

/* Lovense variant — pink/magenta gradient. Audit D46: was over-prominent
   on the main menu (same visual weight as Patreon despite being optional
   Patreon-only haptics). De-saturated and de-emphasized to read as a
   secondary CTA below Patreon/Discord. Pulse animation removed — Patreon
   is the primary monetization CTA and shouldn't compete with a feature
   activation. */
.btn-cta-lovense {
    background: linear-gradient(135deg, rgba(232, 90, 156, 0.45) 0%, rgba(180, 60, 120, 0.55) 55%, rgba(140, 40, 100, 0.65) 100%);
    box-shadow:
        0 2px 10px rgba(232, 90, 156, 0.16),
        inset 0 1px 0 rgba(255, 255, 255, 0.14);
    opacity: 0.88;
}
.btn-cta-lovense:hover {
    opacity: 1;
    box-shadow:
        0 4px 16px rgba(232, 90, 156, 0.3),
        inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.btn-cta-lovense .btn-cta-icon {
    color: #fff5fa;
    /* Audit D46: removed cta-wave-pulse animation — competed visually with
       the Patreon heart-pulse and there's no functional reason to throb. */
}
/* Tiny Patreon-exclusive badge in the corner so non-patrons understand
   why the button is here before they click. */
.btn-cta-lovense::after {
    content: 'PATREON';
    position: absolute;
    top: 6px;
    right: 10px;
    font-size: 8px;
    font-weight: 800;
    letter-spacing: 0.08em;
    color: rgba(255, 255, 255, 0.85);
    background: rgba(0, 0, 0, 0.25);
    padding: 2px 6px;
    border-radius: 4px;
    pointer-events: none;
    z-index: 2;
}

/* Menu Sidebar */
.menu-sidebar {
    width: 340px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.sidebar-section {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 16px;
}

.sidebar-header {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    color: var(--rose);
    margin-bottom: 12px;
}

.whats-new-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    /* Audit D45: was 200px on a 350px-wide sidebar but no inner max-height
       on items, so 8088px of content dumped into a 200px box (3% visible).
       Added a clear viewport + scroll affordance + fade-out hint at bottom. */
    max-height: 360px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(228, 140, 184, 0.3) transparent;
    position: relative;
    mask-image: linear-gradient(to bottom, black 0, black calc(100% - 24px), transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, black 0, black calc(100% - 24px), transparent 100%);
}
.whats-new-list::-webkit-scrollbar { width: 6px; }
.whats-new-list::-webkit-scrollbar-thumb { background: rgba(228, 140, 184, 0.3); border-radius: 3px; }

.whats-new-item {
    font-family: 'Crimson Pro', serif;
    font-size: 13px;
    color: var(--text-body);
    line-height: 1.5;
    padding-left: 10px;
    border-left: 2px solid var(--border);
}

.whats-new-item .tag {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    color: var(--orchid);
    font-weight: 500;
}

.release-progress { text-align: center; }
.release-progress-bar {
    height: 6px;
    background: rgba(30, 28, 45, 0.8);
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 6px;
}
.release-progress-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--orchid), var(--rose));
    border-radius: 3px;
    transition: width 0.5s var(--ease-out);
}
.version-label {
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    color: var(--text-faint);
}

/* Settings button when standing alone (Patreon CTA pulled into its own row) */
.btn-settings-full {
    width: 100%;
}

/* Support CTAs (Patreon + SubscribeStar) — tight vertical pair, constrained
   to the 280px menu-button column width so they line up with New Game /
   Continue / Settings above and below. The 8px inner gap (vs the 24px
   .menu-main gap) keeps the two payment options reading as one block. */
.menu-support-ctas {
    width: 280px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.menu-support-ctas > .btn-cta {
    width: 100%;
}

/* Menu settings inline */
.menu-settings {
    width: 280px;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 16px;
}
.settings-header {
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    color: var(--rose);
    margin-bottom: 12px;
}


/* ============================================
   6. CHARACTER EDITOR
   ============================================ */
#screen-character-editor {
    align-items: center;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    background:
        radial-gradient(ellipse at 50% 10%, rgba(100, 40, 80, 0.07) 0%, transparent 50%),
        var(--bg-deep);
}

.editor-container {
    width: 100%;
    max-width: 480px;
    padding: 16px 16px 32px;
    position: relative;
}

/* Audit D32: Editor exit-affordance — top-left "Back to menu" button. */
.btn-editor-exit {
    position: absolute;
    top: 12px;
    left: 12px;
    min-height: 44px;
    padding: 8px 14px;
    background: rgba(46, 34, 66, 0.55);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text-body);
    font-family: 'DM Sans', sans-serif;
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.2s, border-color 0.2s, color 0.2s;
    z-index: 5;
}
.btn-editor-exit:hover {
    background: rgba(46, 34, 66, 0.85);
    border-color: var(--border-glow);
    color: var(--text);
}
.btn-editor-exit:focus-visible {
    outline: 2px solid var(--rose);
    outline-offset: 2px;
}

/* Progress dots */
.progress-dots {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin-bottom: 20px;
}

.dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--border);
    transition: all 0.3s ease;
}
.dot.active {
    background: var(--rose);
    box-shadow: 0 0 8px rgba(232, 140, 184, 0.4);
    transform: scale(1.2);
    animation: dot-pulse 1.5s ease-in-out infinite;
}
.dot.done { background: var(--orchid); transform: scale(1); }

@keyframes dot-pulse {
    0%, 100% { transform: scale(1.2); box-shadow: 0 0 8px rgba(232, 140, 184, 0.4); }
    50%      { transform: scale(1.4); box-shadow: 0 0 14px rgba(232, 140, 184, 0.6); }
}

/* Phases */
.phase {
    display: none;
}
.phase.active { display: block; animation: phase-enter-right 0.3s ease both; }

/* Directional phase transitions (driven by JS classes) */
.phase.phase-enter-right { animation: phase-enter-right 0.3s ease both; }
.phase.phase-enter-left  { animation: phase-enter-left 0.3s ease both; }
.phase.phase-exit-left   { display: block; animation: phase-exit-left 0.15s ease both; }
.phase.phase-exit-right  { display: block; animation: phase-exit-right 0.15s ease both; }

@keyframes phase-enter-right {
    from { opacity: 0; transform: translateX(40px); }
    to   { opacity: 1; transform: translateX(0); }
}
@keyframes phase-enter-left {
    from { opacity: 0; transform: translateX(-40px); }
    to   { opacity: 1; transform: translateX(0); }
}
@keyframes phase-exit-left {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(-30px); }
}
@keyframes phase-exit-right {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(30px); }
}

.phase-header {
    text-align: center;
    margin-bottom: 24px;
}

.editor-title {
    font-family: 'DM Sans', sans-serif;
    color: var(--rose);
    letter-spacing: 1.5px;
    font-weight: 600;
    font-size: 22px;
    margin-bottom: 6px;
}
/* The heading is given tabindex=-1 and focused on each phase change purely to
   move SR focus + announce the step — it's not an interactive target, so it
   must not render a visible focus ring for mouse users. */
.editor-title:focus,
.editor-title:focus-visible { outline: none; }

.subtitle {
    font-family: 'Crimson Pro', serif;
    font-style: italic;
    color: var(--text-dim);
    font-size: 14px;
}

/* Audit D24: trait-counter pill in the Pick-2-Traits phase header. */
.trait-counter {
    display: inline-block;
    margin-top: 10px;
    padding: 4px 14px;
    font-family: 'DM Mono', monospace;
    font-size: 12px;
    color: var(--text-dim);
    background: rgba(46, 34, 66, 0.5);
    border: 1px solid var(--border);
    border-radius: 12px;
    letter-spacing: 0.5px;
    transition: color 0.2s ease, background 0.2s ease, border-color 0.2s ease;
}
.trait-counter-ready {
    color: var(--gold);
    background: rgba(232, 200, 96, 0.14);
    border-color: rgba(232, 200, 96, 0.45);
}
.trait-counter #trait-counter-num {
    font-weight: 700;
    color: var(--rose);
}
.trait-counter-ready #trait-counter-num {
    color: var(--gold);
}

/* Audit D24: Continue button visible-but-disabled when prerequisites unmet. */
.btn-next[disabled], .btn-next[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
    filter: grayscale(0.4);
}

/* Fields */
.field { margin-bottom: 16px; }
.field label {
    display: block;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-dim);
    margin-bottom: 5px;
}
/* F5 (2026-05-26): inline hint below empty name inputs so the placeholder
   isn't misinterpreted as a forced default. Hides once the input has content. */
.field .field-hint {
    display: block;
    margin-top: 4px;
    font-size: 11px;
    font-style: italic;
    color: var(--text-muted, rgba(255,255,255,0.45));
    transition: opacity 0.2s;
}
.field input:not(:placeholder-shown) + .field-hint { opacity: 0.3; }
.field input[type="text"],
.field input[type="email"] {
    width: 100%;
    height: 44px;
    padding: 0 14px;
    font-size: 15px;
}
.field textarea {
    width: 100%;
    height: auto;
    padding: 10px 14px;
    font-size: 15px;
    resize: vertical;
}

/* Card grid — real 2-col CSS grid so perk-category-header's grid-column:1/-1
   actually spans a row (no-op under the old flex) and odd card counts left-align
   cleanly instead of stranding a centered orphan. */
.card-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
    margin-bottom: 20px;
}

.card {
    width: auto;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 14px 10px 12px;
    cursor: pointer;
    text-align: center;
    position: relative;
    overflow: hidden;
    transition: all 0.2s ease;
}
.card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 20%;
    right: 20%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(196, 112, 224, 0.15), transparent);
    pointer-events: none;
}
.card:hover {
    background: var(--bg-card-hover);
    border-color: #4a3460;
    transform: translateY(-2px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
}
.card:active { transform: scale(0.97); }
.card.selected {
    border-color: var(--border-selected);
    background: #241630;
    box-shadow: 0 0 20px rgba(228, 120, 184, 0.15), inset 0 0 20px rgba(228, 120, 184, 0.03);
    animation: card-select 0.3s ease;
}

@keyframes card-select {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.04); }
    100% { transform: scale(1); }
}

/* F6: brief flash on the OLDEST trait card when a 3rd trait click
   FIFO-swaps it out. Without this the deselect was silent and players
   couldn't tell which trait got replaced. */
.card.trait-dropped {
    animation: card-dropped 0.45s ease-out;
}
@keyframes card-dropped {
    0%   { transform: scale(1); box-shadow: 0 0 20px rgba(228, 120, 184, 0.5); border-color: rgba(228, 120, 184, 0.7); }
    100% { transform: scale(0.97); box-shadow: none; }
}
.card.dimmed {
    opacity: 0.25;
    pointer-events: none;
    filter: grayscale(0.5);
}

/* MASC_ROUTE: Master intensity cards greyed while the masculine route is
   picked (it runs as Independent). Unlike .dimmed these STAY clickable —
   clicking a greyed Master card cancels the masc route and selects it. */
.card-locked {
    opacity: 0.4;
    filter: grayscale(0.7);
}
.card-locked:hover {
    opacity: 0.6;
    filter: grayscale(0.4);
}

/* Thumbnail background on cards (editor backgrounds + traits) */
.card-with-thumb {
    padding-top: 100px;
}
.card-thumb {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 90px;
    background-size: cover;
    background-position: center 30%;
    border-radius: 9px 9px 0 0;
    /* Bespoke character art was muddy at 0.6 over the dark card. Raise resting
       legibility — the bottom fade (::after) keeps the title readable below. */
    opacity: 0.82;
    filter: saturate(1.08) contrast(1.04);
    transition: opacity 0.3s ease, filter 0.3s ease;
    overflow: hidden;
}
/* <img> fallback variant (character-editor.js uses an img tag so it can
   swap .webp -> .png when the primary 404s in dev mode). */
.card-thumb-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 30%;
    display: block;
}
.card-thumb::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 40px;
    background: linear-gradient(to bottom, transparent, var(--bg-card));
    pointer-events: none;
}
.card-with-thumb:hover .card-thumb { opacity: 0.95; }
.card-with-thumb.selected .card-thumb { opacity: 1; filter: saturate(1.15) contrast(1.05); }

/* Editor section divider + subtitle */
.editor-section-divider {
    width: 60%;
    max-width: 300px;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--border), transparent);
    margin: 16px auto 0;
}
/* Eyebrow tier — matches .pacing-title so the editor reads as one type ramp
   (DM Sans / uppercase / rose) instead of mixing a serif near-white heading in. */
.editor-subtitle {
    font-family: 'DM Sans', sans-serif;
    font-size: 13px;
    font-weight: 600;
    color: var(--rose);
    text-align: center;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    margin: 0 0 12px 0;
}

/* Framed sub-decision block — Phase 2 stacks four distinct questions
   (Intensity / Girlfriend / Masc-path / Orientation); boxing each one keeps
   them from reading as one long undifferentiated scroll. */
.editor-subsection {
    background: rgba(20, 14, 30, 0.45);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 14px 12px 6px;
    margin-bottom: 14px;
}
.editor-subsection > .card-grid { margin-bottom: 8px; }

/* ── Content Preferences (0.3, CONTENT_TOGGLES) — vertical toggle list ── */
.editor-subtitle-note { font-size: 12px; color: #9a91b4; margin: -6px 0 14px; line-height: 1.4; }
.pref-list { display: block; }
.pref-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 13px 4px; border-bottom: 1px solid var(--border); text-align: left; }
.pref-row:last-child { border-bottom: none; }
.pref-row:first-child { border-top: 1px solid var(--border); }
.pref-info { flex: 1; min-width: 0; }
.pref-name { font-size: 14px; font-weight: 600; color: var(--text); }
.pref-desc { font-size: 12px; color: #9a91b4; margin-top: 4px; line-height: 1.45; }
.pref-placeholder .pref-name { color: #6b6480; font-style: italic; font-weight: 500; letter-spacing: 0.5px; }
.pref-patreon { color: #ff66c4; font-size: 11px; font-weight: 600; }
.toggle-switch input:disabled + .toggle-slider { opacity: 0.4; cursor: default; }
.editor-subsection > .card-grid:last-child { margin-bottom: 0; }

/* Editor optional storyline toggles */
.editor-toggles {
    margin: 20px auto 0;
    max-width: 480px;
    padding: 0 10px;
}
.editor-toggle-title {
    font-family: 'DM Sans', sans-serif;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 1.5px;
    margin-bottom: 10px;
}
.editor-toggle {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 12px 14px;
    cursor: pointer;
    transition: border-color 0.2s ease;
}
.editor-toggle:hover { border-color: var(--accent-soft); }
.editor-toggle input[type="checkbox"] {
    width: 18px;
    height: 18px;
    accent-color: var(--rose);
    margin-top: 2px;
    flex-shrink: 0;
}
.editor-toggle-label {
    font-family: 'DM Sans', sans-serif;
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    display: block;
}
.editor-toggle-desc {
    font-family: 'Crimson Pro', serif;
    font-size: 11px;
    font-style: italic;
    color: var(--text-dim);
    line-height: 1.4;
    display: block;
    margin-top: 3px;
}
.card-with-thumb .card-icon { display: none; }

.card-icon { font-size: 26px; margin-bottom: 8px; filter: saturate(0.85); line-height: 1; }
.card-icon img { width: 48px; height: 48px; object-fit: contain; border-radius: 8px; }
.card-name { font-size: 12px; font-weight: 600; color: var(--text); margin-bottom: 5px; letter-spacing: 0.3px; }
.card-desc { font-family: 'Crimson Pro', serif; font-size: 11px; font-style: italic; color: var(--text-dim); line-height: 1.45; }
.card-bonus {
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    color: var(--green);
    margin-top: 8px;
    padding-top: 6px;
    border-top: 1px solid rgba(46, 34, 66, 0.5);
}

.card-check {
    position: absolute;
    top: 6px;
    right: 8px;
    font-size: 14px;
    color: var(--rose);
    display: none;
    text-shadow: 0 0 6px rgba(232, 140, 184, 0.5);
}
.card.selected .card-check { display: block; }

/* Recommended badge — used on intensity / background / preset cards.
   Sits at the top-left so it doesn't collide with the .card-check
   selected-mark at top-right. Pink pill, low contrast on the card
   background so it nudges without shouting. */
.card-recommended {
    position: absolute;
    top: 6px;
    left: 8px;
    padding: 2px 8px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--bg-deep, #120e1c);
    background: linear-gradient(135deg, var(--rose, #e88cb8), #d472a8);
    border-radius: 10px;
    box-shadow: 0 2px 6px rgba(228, 140, 184, 0.35);
    z-index: 1;
}

/* Synergy / Difficulty */
.synergy {
    text-align: center;
    font-family: 'Crimson Pro', serif;
    font-size: 13px;
    font-style: italic;
    color: var(--rose);
    min-height: 22px;
    margin-bottom: 8px;
    padding: 6px 12px;
    opacity: 0.9;
}
.difficulty {
    text-align: center;
    font-family: 'DM Mono', monospace;
    font-size: 12px;
    font-weight: 500;
    margin-bottom: 16px;
    letter-spacing: 1px;
}
.diff-easy { color: var(--green); }
.diff-normal { color: var(--gold); }
.diff-hard { color: var(--orange); }
.diff-challenge { color: var(--red); text-shadow: 0 0 8px rgba(224, 96, 96, 0.3); }

/* Empty readouts shouldn't reserve space or render an empty pill. */
.synergy:empty, .difficulty:empty { display: none; }

/* Synergy = a soft pink card that animates in only when populated (was plain
   centered text next to the polished trait-counter pill). */
.synergy:not(:empty) {
    background: rgba(228, 140, 184, 0.07);
    border: 1px solid rgba(228, 140, 184, 0.18);
    border-radius: 10px;
    padding: 8px 14px;
    max-width: 360px;
    margin: 0 auto 12px;
    opacity: 1;
    animation: synergy-in 0.35s ease both;
}
@keyframes synergy-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Difficulty = a centered pill so the readout reads as a deliberate badge. */
.difficulty:not(:empty) {
    width: fit-content;
    margin-left: auto;
    margin-right: auto;
    padding: 4px 14px;
    border-radius: 12px;
    background: rgba(46, 34, 66, 0.45);
    border: 1px solid var(--border);
}

/* === Intensity phase (Phase 2) === ported from the build-excluded editor.css
   so the live build finally styles these. --blue was undefined → --masc. */
.intensity-detail {
    text-align: center;
    font-family: 'Crimson Pro', serif;
    font-size: 13px;
    font-style: italic;
    color: var(--text-dim);
    line-height: 1.55;
    min-height: 34px;
    max-width: 420px;
    margin: 4px auto 0;
    padding: 6px 10px;
}
.intensity-warning {
    text-align: center;
    font-family: 'DM Mono', monospace;
    font-size: 11px;
    color: var(--orange);
    margin-top: 6px;
    letter-spacing: 0.5px;
}
.intensity-warning:empty { display: none; }

/* Per-intensity color-coded selected border — restores the green→red
   difficulty signal the dead editor.css used to provide. */
#intensity-grid .card.selected[data-intensity-id="0"] { border-color: var(--green); box-shadow: 0 0 16px rgba(92, 216, 156, 0.18), inset 0 0 16px rgba(92, 216, 156, 0.04); }
#intensity-grid .card.selected[data-intensity-id="1"] { border-color: var(--masc);  box-shadow: 0 0 16px rgba(88, 136, 204, 0.18), inset 0 0 16px rgba(88, 136, 204, 0.04); }
#intensity-grid .card.selected[data-intensity-id="2"] { border-color: var(--gold);  box-shadow: 0 0 16px rgba(232, 200, 96, 0.18), inset 0 0 16px rgba(232, 200, 96, 0.04); }
#intensity-grid .card.selected[data-intensity-id="3"] { border-color: var(--red);   box-shadow: 0 0 16px rgba(224, 96, 96, 0.22), inset 0 0 16px rgba(224, 96, 96, 0.05); }

/* Orientation has 3 short (thumb-less) options — 3-across reads cleaner than
   a 2-col grid with a stranded third card. */
#orientation-lean-grid { grid-template-columns: repeat(3, 1fr); }

/* Preview card */
/* The final review is the wizard's payoff — frame it as a collectible
   character card: soft gradient, rose glow, and a bounce-in reveal. */
.preview-card {
    background: linear-gradient(160deg, var(--bg-card-hover), var(--bg-card));
    border: 1px solid var(--border-selected);
    border-radius: 16px;
    padding: 26px 22px;
    margin-bottom: 20px;
    text-align: center;
    position: relative;
    overflow: hidden;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.45), 0 0 30px rgba(228, 120, 184, 0.10), inset 0 0 30px rgba(228, 120, 184, 0.04);
    animation: preview-reveal 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes preview-reveal {
    from { opacity: 0; transform: translateY(18px) scale(0.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
.preview-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 10%;
    right: 10%;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--rose), transparent);
    opacity: 0.4;
}
/* Nameplate — the player's name as a framed crest, the focal point of the card. */
.preview-name {
    display: inline-block;
    font-size: 24px;
    color: var(--rose-bright, var(--rose));
    font-weight: 700;
    letter-spacing: 3px;
    text-transform: uppercase;
    margin-bottom: 8px;
    padding: 4px 20px 6px;
    background: linear-gradient(135deg, rgba(228, 140, 184, 0.14), rgba(196, 112, 224, 0.10));
    border: 1px solid rgba(228, 140, 184, 0.28);
    border-radius: 10px;
    text-shadow: 0 0 14px rgba(228, 140, 184, 0.35);
}
.preview-divider { height: 1px; background: linear-gradient(90deg, transparent, var(--border), transparent); margin: 14px 0; }
.preview-detail { font-family: 'Crimson Pro', serif; font-size: 14px; color: var(--text-dim); line-height: 1.7; margin-bottom: 4px; }
.preview-detail strong { color: var(--text); font-family: 'DM Sans', sans-serif; font-size: 13px; }
.preview-stats { font-family: 'DM Mono', monospace; font-size: 12px; color: var(--text); line-height: 1.8; }
/* Echoed 2-trait synergy line — reinforces the build identity at commit time. */
.preview-synergy {
    font-family: 'Crimson Pro', serif;
    font-style: italic;
    font-size: 13px;
    color: var(--rose);
    line-height: 1.5;
    margin: 6px auto 0;
    max-width: 320px;
    opacity: 0.92;
}

/* Pacing-Note inside Trait/Perk card */
.card-pacing-note {
    margin-top: 6px;
    padding: 5px 8px;
    border-left: 2px solid;
    font-family: 'Crimson Pro', serif;
    font-size: 11px;
    font-style: italic;
    line-height: 1.35;
    border-radius: 3px;
}
.card-pacing-note.pacing-fast { color: #f3a3d8; border-left-color: #f3a3d8; background: rgba(243, 163, 216, 0.08); }
.card-pacing-note.pacing-slow { color: #a3d8f3; border-left-color: #a3d8f3; background: rgba(163, 216, 243, 0.08); }

/* Pacing-Mode card on Preview phase */
.pacing-mode-card {
    background: rgba(20, 12, 22, 0.6);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 18px 20px;
    margin: 18px 0;
}
.pacing-title { font-family: 'DM Sans', sans-serif; font-size: 14px; letter-spacing: 2px; color: var(--rose); text-transform: uppercase; margin: 0 0 4px 0; }
.pacing-subtitle { font-family: 'Crimson Pro', serif; font-size: 13px; color: var(--text-dim); font-style: italic; margin: 0 0 14px 0; }
.pacing-options { display: flex; flex-direction: column; gap: 8px; }
/* Audit D31: pacing Recommended badge — matches .card-recommended style. */
.pacing-option { position: relative; }
.pacing-recommended {
    position: absolute;
    top: 6px;
    right: 8px;
    padding: 2px 8px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--bg-deep, #120e1c);
    background: linear-gradient(135deg, var(--rose, #e88cb8), #d472a8);
    border-radius: 10px;
    box-shadow: 0 2px 6px rgba(228, 140, 184, 0.35);
    z-index: 1;
}
.pacing-option {
    display: grid;
    grid-template-columns: 28px 18px 1fr auto;
    grid-template-rows: auto auto;
    grid-column-gap: 10px;
    align-items: center;
    padding: 10px 12px;
    background: rgba(0,0,0,0.3);
    border: 1px solid rgba(228, 140, 184, 0.1);
    border-radius: 8px;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}
.pacing-option:hover { border-color: rgba(228, 140, 184, 0.4); background: rgba(0,0,0,0.5); }
.pacing-option input[type=radio] { grid-column: 1; grid-row: 1 / span 2; accent-color: var(--rose); }
.pacing-option .pacing-emoji { grid-column: 2; grid-row: 1 / span 2; font-size: 18px; text-align: center; }
.pacing-option .pacing-name { grid-column: 3; grid-row: 1; font-family: 'DM Sans', sans-serif; font-size: 14px; color: var(--text); font-weight: 600; }
.pacing-option .pacing-len { grid-column: 4; grid-row: 1; font-family: 'DM Mono', monospace; font-size: 11px; color: var(--rose); letter-spacing: 0.5px; }
.pacing-option .pacing-desc { grid-column: 3 / span 2; grid-row: 2; font-family: 'Crimson Pro', serif; font-size: 12px; color: var(--text-dim); line-height: 1.4; margin-top: 3px; }
.pacing-option:has(input:checked) { border-color: var(--rose); background: rgba(180, 90, 130, 0.12); }
.pacing-option.pacing-default .pacing-name::after { content: ' ✓'; color: var(--rose); }

/* Pacing 2.0 story-length slider (PACING_RETUNE.md) — replaces the 4 radios. */
.pacing-slider-wrap { padding: 4px 2px 2px; }
#pacing-slider {
    -webkit-appearance: none; appearance: none;
    width: 100%; height: 6px; border-radius: 999px; outline: none;
    background: linear-gradient(90deg, rgba(243,163,216,0.45), var(--rose), rgba(163,216,243,0.45));
    margin: 6px 0 4px; cursor: pointer;
}
#pacing-slider::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 22px; height: 22px; border-radius: 50%;
    background: var(--rose); border: 3px solid #1a1122;
    box-shadow: 0 0 0 1px var(--rose), 0 2px 6px rgba(0,0,0,0.5); cursor: pointer;
}
#pacing-slider::-moz-range-thumb {
    width: 22px; height: 22px; border-radius: 50%;
    background: var(--rose); border: 3px solid #1a1122;
    box-shadow: 0 0 0 1px var(--rose); cursor: pointer;
}
.pacing-slider-readout {
    display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 8px 0 6px;
}
.pacing-slider-num { font-family: 'DM Mono', monospace; }
.pacing-slider-days { font-size: 26px; font-weight: 700; color: var(--rose); }
.pacing-slider-unit { font-size: 13px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 1px; }
.pacing-slider-weeks { font-family: 'DM Mono', monospace; font-size: 12px; color: var(--text-dim); }
.pacing-slider-zone { margin-left: auto; font-family: 'DM Sans', sans-serif; font-size: 14px; font-weight: 600; color: var(--text); }
.pacing-slider-wrap .pacing-desc {
    font-family: 'Crimson Pro', serif; font-size: 13px; color: var(--text-dim);
    line-height: 1.4; margin: 2px 0 0; min-height: 34px;
}

.skip-setup-option {
    display: grid;
    grid-template-columns: 28px 18px 1fr;
    grid-column-gap: 10px;
    align-items: center;
    padding: 10px 12px;
    margin-top: 12px;
    background: rgba(0,0,0,0.3);
    border: 1px dashed rgba(228, 140, 184, 0.2);
    border-radius: 8px;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}
.skip-setup-option:hover { border-color: rgba(228, 140, 184, 0.5); background: rgba(0,0,0,0.5); }
.skip-setup-option input[type=checkbox] { grid-column: 1; grid-row: 1 / span 2; accent-color: var(--rose); }
.skip-setup-option .skip-emoji { grid-column: 2; grid-row: 1 / span 2; font-size: 18px; text-align: center; }
.skip-setup-option .skip-name { grid-column: 3; grid-row: 1; font-family: 'DM Sans', sans-serif; font-size: 13px; color: var(--text); font-weight: 600; }
.skip-setup-option .skip-desc { grid-column: 3; grid-row: 2; font-family: 'Crimson Pro', serif; font-size: 12px; color: var(--text-dim); line-height: 1.4; margin-top: 3px; }
.skip-setup-option:has(input:checked) { border-style: solid; border-color: var(--rose); background: rgba(180, 90, 130, 0.12); }
.skip-setup-option .skip-warn {
    grid-column: 3;
    grid-row: 3;
    margin-top: 6px;
    padding: 6px 10px;
    background: rgba(228, 140, 100, 0.08);
    border-left: 2px solid #d99060;
    border-radius: 4px;
    font-family: 'Crimson Pro', serif;
    font-size: 11px;
    color: #d99060;
    line-height: 1.4;
    display: none;
}
.skip-setup-option:has(input:checked) .skip-warn { display: block; }

/* Editor buttons */
.btn-next, .btn-start {
    display: block;
    width: 100%;
    height: 48px;
    background: linear-gradient(135deg, #5c2848, #803870);
    border: 1px solid rgba(228, 140, 184, 0.2);
    border-radius: 10px;
    color: #eedce8;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    transition: all 0.2s ease;
    position: relative;
    overflow: hidden;
}
.btn-next::before, .btn-start::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.04), transparent);
    transform: translateX(-100%);
    transition: transform 0.4s ease;
}
.btn-next:hover::before, .btn-start:hover::before { transform: translateX(100%); }
.btn-next:hover, .btn-start:hover {
    box-shadow: 0 4px 20px rgba(128, 56, 112, 0.3);
    border-color: rgba(228, 140, 184, 0.35);
}
.btn-next:active, .btn-start:active { transform: scale(0.98); }

.btn-start {
    background: linear-gradient(135deg, #7c3060, #a04888);
    height: 52px;
    font-size: 15px;
    animation: btn-start-pulse 2s ease-in-out infinite;
}

@keyframes btn-start-pulse {
    0%, 100% { box-shadow: 0 0 12px rgba(160, 72, 136, 0.3); }
    50%      { box-shadow: 0 0 24px rgba(228, 140, 184, 0.5), 0 0 48px rgba(160, 72, 136, 0.2); }
}

.btn-back {
    display: block;
    width: 100%;
    height: 40px;
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text-dim);
    font-size: 12px;
    letter-spacing: 0.5px;
    margin-top: 8px;
    transition: all 0.2s ease;
}
.btn-back:hover { border-color: var(--accent-soft); color: var(--text); }

/* Busy/disabled state for the final CTA (re-entrancy guard turns it busy). */
.btn-start[disabled], .btn-start[aria-disabled="true"] {
    opacity: 0.65;
    cursor: progress;
    animation: none;
    filter: grayscale(0.25);
}

/* Sticky per-phase action bar — keeps Continue/Back/Start reachable on tall
   phases (Phase 2 ~1400px, Phase 5) instead of stranded below the fold. Sticks
   to the bottom of #screen-character-editor, the scroll container. */
.phase-actions {
    position: sticky;
    bottom: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 18px;
    padding: 12px 0 calc(10px + env(safe-area-inset-bottom, 0px));
    background: linear-gradient(180deg, rgba(8, 6, 12, 0) 0%, var(--bg-deep) 32%, var(--bg-deep) 100%);
}
.phase-actions .btn-back {
    width: auto;
    flex: 0 0 auto;
    min-width: 88px;
    height: 48px;
    margin-top: 0;
    padding: 0 18px;
}
.phase-actions .btn-next,
.phase-actions .btn-start {
    flex: 1 1 auto;
    margin-top: 0;
}

/* Completed-step dots get a soft orchid glow so progress reads at a glance. */
.progress-dots .dot.done {
    background: var(--orchid);
    box-shadow: 0 0 6px rgba(196, 112, 224, 0.45);
}

/* Respect reduced-motion: drop the editor's animations/transitions but keep
   all selected/hover/focus end states intact. */
@media (prefers-reduced-motion: reduce) {
    #screen-character-editor *,
    #screen-character-editor *::before,
    #screen-character-editor *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}


/* ============================================


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Perk Cards + typing cursor
   ============================================ */
/* ============================================
   P1: Perk Cards (Editor)
   ============================================ */
.perk-category-header {
    grid-column: 1 / -1; font-weight: 700; font-size: 14px;
    color: var(--accent); padding: 8px 0 4px; border-bottom: 1px solid var(--border);
    margin-top: 8px;
}
.perk-card.dimmed { opacity: 0.4; pointer-events: none; }
.perk-points-display {
    font-size: 14px; color: var(--accent); font-weight: 600;
    margin-top: 6px;
}
.perk-no-points {
    grid-column: 1 / -1; text-align: center; padding: 24px 16px;
    color: var(--text-dim); font-size: 14px; line-height: 1.6;
    border: 1px dashed var(--border); border-radius: 8px;
}
/* Hardship perks (0.2.9): clearly-negative red styling so a handicap perk reads
   as a drawback at a glance (player ask: "die sollten klar negativ ersichtlich
   sein"). */
.perk-card.perk-hardship {
    border-color: #d84040;
    background: linear-gradient(180deg, rgba(180, 50, 50, 0.16), rgba(180, 50, 50, 0.05));
}
.perk-card.perk-hardship.selected {
    border-color: #ff5a5a;
    box-shadow: 0 0 0 2px rgba(255, 90, 90, 0.45);
}
.perk-card.perk-hardship .card-name { color: #ff8a8a; }
.card-bonus-hardship {
    color: #ff6b6b; font-weight: 700; letter-spacing: 0.06em;
    text-transform: uppercase; font-size: 11px;
}
/* Perk-step tabs: Perks (positive) / Handicaps (negative), 0.2.9 */
.perk-tabs {
    display: flex; gap: 8px; justify-content: center; margin: 4px 0 14px;
}
.perk-tab {
    flex: 0 1 auto; padding: 8px 22px; border-radius: 999px; cursor: pointer;
    font-weight: 600; font-size: 14px; background: transparent;
    color: var(--text-dim); border: 1px solid var(--border);
    transition: background .15s, color .15s, border-color .15s;
}
.perk-tab:hover { color: var(--text); border-color: var(--accent); }
.perk-tab.active { background: var(--accent); color: #fff; border-color: var(--accent); }
/* Handicaps tab active = red, reinforcing "negative" at a glance */
#perk-tab-handicaps.active { background: #d84040; border-color: #ff5a5a; color: #fff; }

/* Typing effect cursor */
.typing-active::after {
    content: '\2588'; color: var(--accent); animation: blink-cursor 0.7s step-end infinite;
}
@keyframes blink-cursor { 50% { opacity: 0; } }


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Language Selection Popup + Settings select
   ============================================ */
/* ============================================
   Language Selection Popup (first visit)
   ============================================ */
.language-popup { z-index: var(--z-vignette); }
.language-popup-box {
    max-width: 420px; text-align: center; padding: 28px 24px;
}
.language-popup-header {
    margin-bottom: 20px;
}
.language-popup-icon { font-size: 36px; display: block; margin-bottom: 8px; }
.language-popup-header h2 {
    font-size: 18px; font-weight: 700; color: var(--text);
    margin: 0; line-height: 1.4;
}
.language-popup-grid {
    display: flex; flex-direction: column; gap: 8px;
}
.language-popup-btn {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 16px; border-radius: 8px;
    background: var(--bg-lighter); border: 1px solid var(--border);
    color: var(--text); font-size: 15px; cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}
.language-popup-btn:hover {
    background: var(--accent-dim); border-color: var(--accent);
}
.lang-flag { font-size: 24px; }
.lang-name { font-weight: 600; }

/* Settings select dropdown (pause menu) */
.settings-select {
    background: var(--bg-lighter); color: var(--text);
    border: 1px solid var(--border); border-radius: 6px;
    padding: 4px 8px; font-size: 13px; cursor: pointer;
    min-width: 120px;
}
.settings-select:focus { border-color: var(--accent); outline: none; }


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Changelog tag badges
   ============================================ */
/* ============================================
   FIX: Changelog — tag badges with color backgrounds (matches Unity)
   ============================================ */
.whats-new-item {
    display: grid !important;
    grid-template-columns: auto 1fr;
    gap: 4px 8px;
    padding: 5px 10px !important;
    border-left: none !important;
    background: rgba(20, 15, 30, 0.3);
    border-radius: 6px;
    align-items: start;
}
.whats-new-item .tag-col {
    display: flex;
    flex-direction: column;
    gap: 2px;
    grid-row: 1;
    grid-column: 1;
}
.whats-new-item .tag {
    font-size: 8px !important;
    font-weight: 700 !important;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 1px 5px;
    border-radius: 3px;
    background: rgba(196, 112, 224, 0.15);
    white-space: nowrap;
    text-align: center;
    line-height: 1.4;
}
.whats-new-item .whats-new-text {
    grid-row: 1;
    grid-column: 2;
}
.whats-new-list {
    max-height: 350px !important;
    gap: 3px !important;
}


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Mood Splash + Loading + keyboard focus + fonts
   ============================================ */
/* ── Mood Splash (pre-menu atmospheric intro) ── */
.mood-splash {
    position: fixed;
    top: 0; left: 0;
    width: 100%; height: 100%;
    z-index: var(--z-vignette);
    background: #030208;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    overflow: hidden;
}
.mood-splash.hidden { display: none; }

.mood-splash-vignette {
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse at 50% 50%,
        transparent 30%,
        rgba(3, 2, 8, 0.6) 60%,
        rgba(3, 2, 8, 0.95) 100%);
    z-index: 1;
}

.mood-splash-silhouette {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 300px;
    height: 70%;
    background: linear-gradient(180deg,
        transparent 0%,
        rgba(232, 140, 184, 0.02) 20%,
        rgba(232, 140, 184, 0.04) 40%,
        rgba(196, 112, 224, 0.03) 60%,
        rgba(232, 140, 184, 0.06) 80%,
        rgba(232, 140, 184, 0.08) 100%);
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 500'%3E%3Cellipse cx='100' cy='60' rx='28' ry='35'/%3E%3Cpath d='M72 90 Q60 180 65 280 Q68 350 55 500 L145 500 Q132 350 135 280 Q140 180 128 90 Z'/%3E%3C/svg%3E");
    mask-size: contain;
    mask-repeat: no-repeat;
    mask-position: bottom center;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 500'%3E%3Cellipse cx='100' cy='60' rx='28' ry='35'/%3E%3Cpath d='M72 90 Q60 180 65 280 Q68 350 55 500 L145 500 Q132 350 135 280 Q140 180 128 90 Z'/%3E%3C/svg%3E");
    -webkit-mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-position: bottom center;
    opacity: 0;
    animation: splash-silhouette-in 3s ease-out 0.5s forwards;
    z-index: 0;
}

.mood-splash-content {
    position: relative;
    z-index: 2;
    text-align: center;
    opacity: 0;
    animation: splash-text-in 2s ease-out 0.8s forwards;
}

.mood-splash-text {
    font-family: 'Crimson Pro', Georgia, serif;
    font-style: italic;
    font-size: 28px;
    font-weight: 400;
    color: #e88cb8;
    letter-spacing: 2px;
    text-shadow: 0 0 40px rgba(232, 140, 184, 0.25),
                 0 0 80px rgba(232, 140, 184, 0.1);
    line-height: 1.4;
}

.mood-splash-skip {
    font-family: 'DM Sans', sans-serif;
    font-size: 12px;
    color: rgba(136, 124, 160, 0.5);
    letter-spacing: 1px;
    margin-top: 48px;
    opacity: 0;
    animation: splash-skip-in 0.6s ease-out 1s forwards;
}

@keyframes splash-silhouette-in {
    from { opacity: 0; transform: translateX(-50%) scale(0.95); }
    to   { opacity: 1; transform: translateX(-50%) scale(1); }
}

@keyframes splash-text-in {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes splash-skip-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@media (max-width: 767px) {
    .mood-splash-text { font-size: 22px; letter-spacing: 1px; }
    .mood-splash-silhouette { width: 200px; }
}

/* Loading screen */
.loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: var(--z-vignette);
    transition: opacity 0.5s ease;
    background: radial-gradient(ellipse at 50% 30%, rgba(140, 60, 100, 0.08) 0%, transparent 60%),
                radial-gradient(ellipse at 30% 80%, rgba(80, 40, 140, 0.06) 0%, transparent 50%),
                #08060c;
}
.loading-title {
    font-family: 'Crimson Pro', Georgia, serif;
    font-size: 48px;
    font-weight: 600;
    color: #e88cb8;
    letter-spacing: 4px;
    text-shadow: 0 0 40px rgba(232, 140, 184, 0.15);
    line-height: 1.1;
    text-align: center;
}
.loading-title-amp {
    color: #c470e0;
    font-style: italic;
}
.loading-subtitle {
    font-family: 'Crimson Pro', serif;
    font-style: italic;
    color: #887ca0;
    font-size: 16px;
    margin-top: 8px;
    letter-spacing: 2px;
    margin-bottom: 32px;
}
.loading-bar-track {
    width: 280px;
    height: 12px;
    background: rgba(20, 18, 35, 0.9);
    border-radius: 6px;
    overflow: hidden;
    box-shadow: inset 0 2px 4px rgba(0,0,0,0.5), 0 0 1px rgba(228, 140, 184, 0.1);
    position: relative;
}
.loading-bar-fill {
    width: 0%;
    height: 100%;
    border-radius: 6px;
    background: linear-gradient(90deg, var(--rose, #e88cb8) 0%, #e88cb8 50%, #c06898 100%);
    box-shadow: 0 0 12px rgba(228, 140, 184, 0.35);
    position: relative;
    transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.loading-bar-fill::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 6px;
    background: linear-gradient(180deg, rgba(255,255,255,0.18) 0%, transparent 55%);
}
@keyframes loading-shimmer {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(200%); }
}
.loading-bar-fill::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 50%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.15), transparent);
    animation: loading-shimmer 1.8s ease-in-out infinite;
}
.loading-bar-glow {
    position: absolute;
    top: 50%;
    right: -1px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--rose, #e88cb8);
    transform: translateY(-50%);
    box-shadow: 0 0 10px rgba(228, 140, 184, 0.5), 0 0 20px rgba(228, 140, 184, 0.2);
    border: 2px solid rgba(255,255,255,0.2);
}
.loading-pct {
    font-family: 'DM Mono', monospace;
    color: var(--rose, #e88cb8);
    font-size: 12px;
    font-weight: 600;
    margin-top: 12px;
    letter-spacing: 1px;
    text-shadow: 0 0 8px rgba(228, 140, 184, 0.2);
}
.loading-label {
    color: var(--text-faint);
    font-size: 12px;
    margin-top: 8px;
    text-align: center;
    min-height: 16px;
}
/* Keyboard focus indicators */
.choice-btn:focus-visible {
    outline: 2px solid var(--rose);
    outline-offset: 2px;
}
.action-btn:focus-visible {
    outline: 2px solid var(--rose);
    outline-offset: 2px;
}
button:focus-visible {
    outline: 2px solid var(--orchid);
    outline-offset: 2px;
}
a:focus-visible {
    outline: 2px solid var(--orchid);
    outline-offset: 2px;
}

/* Font display fallback */
@font-face {
    font-family: 'DM Sans';
    font-display: swap;
}
@font-face {
    font-family: 'Crimson Pro';
    font-display: swap;
}
@font-face {
    font-family: 'DM Mono';
    font-display: swap;
}

/* ═══════════════════════════════════════════════════════════════════════
   Archetype quick-start entry screens (0.3.1 editor rework)
   Two sections (#phase-archetype / #phase-archetype-confirm) OUTSIDE the
   .phase list. Visibility: #screen-character-editor.editor-mode-entry shows
   the .editor-entry.active section and hides the wizard + progress dots.
   ═══════════════════════════════════════════════════════════════════════ */
.editor-entry { display: none; }
.editor-entry.active { display: block; animation: phase-enter-right 0.3s ease both; }
.editor-mode-entry .phase,
.editor-mode-entry .phase.active { display: none; }
.editor-mode-entry .progress-dots { display: none; }
/* The hidden dots normally clear the absolute "Back to menu" pill — keep the
   entry headings from rendering underneath it (both breakpoints). */
.editor-mode-entry .editor-entry { margin-top: 48px; }

.archetype-grid { align-items: stretch; }

.archetype-card {
    position: relative;
    display: flex;
    flex-direction: column;
    text-align: left;
}
.archetype-card .card-name { font-size: 17px; margin-top: 2px; }
.archetype-tagline {
    font-style: italic;
    color: var(--rose);
    margin: 2px 0 8px;
}
.archetype-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: auto; /* pin chip row to the card bottom across the grid row */
}
.archetype-chips-recap {
    justify-content: center;
    margin: 0 0 14px;
}
.archetype-chip {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg-deep);
    color: var(--text-dim);
    font-size: 11px;
    line-height: 1.6;
    white-space: nowrap;
}
.archetype-chip-hot {
    border-color: var(--rose);
    color: var(--rose);
}
/* Difficulty chip reuses the wizard pill palette classes */
.archetype-chip.archetype-chip-diff-easy      { color: var(--green); border-color: var(--green); }
.archetype-chip.archetype-chip-diff-normal    { color: var(--text); }
.archetype-chip.archetype-chip-diff-hard      { color: var(--gold); border-color: var(--gold); }
.archetype-chip.archetype-chip-diff-challenge { color: var(--orchid); border-color: var(--orchid); }
/* Tappable recap chips on the confirm screen */
button.archetype-chip-link { cursor: pointer; }
button.archetype-chip-link:hover,
button.archetype-chip-link:focus-visible {
    border-color: var(--rose);
    color: var(--text);
}

/* KEPT PET severity badge — sibling of .card-recommended, opposite corner */
.archetype-warn {
    position: absolute;
    top: 8px;
    left: 8px;
    padding: 1px 8px;
    border-radius: 999px;
    background: rgba(180, 60, 60, 0.18);
    border: 1px solid rgba(220, 110, 110, 0.6);
    color: #e08a8a;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    z-index: 2;
}

.archetype-card-custom {
    justify-content: center;
    text-align: center;
    border-style: dashed;
}
.archetype-card-custom .card-icon { font-size: 28px; }

.archetype-last-build-chip {
    display: inline-block;
    margin: 0 auto 12px;
    padding: 4px 14px;
    border-radius: 999px;
    border: 1px solid var(--rose);
    /* --accent-soft is SOLID orchid (token semantics, _00-base.css) — rose
       text on it is 1.3:1. The dim translucent sibling keeps text readable. */
    background: var(--accent-soft-dim);
    color: var(--rose);
    font-size: 13px;
    cursor: pointer;
}
#archetype-last-build { text-align: center; }

/* Confirm screen */
.partner-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 6px 0 12px;
}
.partner-chip {
    padding: 7px 16px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--text-dim);
    font-size: 14px;
    cursor: pointer;
}
.partner-chip.selected {
    border-color: var(--rose);
    background: var(--accent-soft-dim);
    color: var(--text);
}
.partner-chip:focus-visible { outline: 2px solid var(--rose); outline-offset: 2px; }

.archetype-perk-pill {
    display: inline-block;
    margin: 4px 0 0;
    padding: 6px 14px;
    border-radius: 999px;
    border: 1px solid var(--gold);
    background: rgba(212, 175, 55, 0.12);
    color: var(--gold);
    font-size: 13px;
    cursor: pointer;
}

.archetype-confirm-actions { margin-top: 18px; }
.archetype-customize-row {
    margin-top: 10px;
    text-align: center;
}
.btn-customize {
    background: none;
    border: none;
    color: var(--text-dim);
    text-decoration: underline;
    cursor: pointer;
    font-size: 13px;
    padding: 4px 8px;
}
.btn-customize:hover, .btn-customize:focus-visible { color: var(--rose); }
.archetype-more-hint { display: block; margin-top: 4px; color: var(--text-faint); }

/* Phone (2-column card grid inherits from .phone .editor-card rules).
   Keep chips readable at the narrow width. */
.phone .archetype-chip { font-size: 10px; padding: 0 6px; }
.phone .archetype-card .card-name { font-size: 15px; }
/* ============================================
   7. TOP BAR
   ============================================ */
#topbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 10px;
    background: var(--bg-warm);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
    height: var(--topbar-height);
    position: relative;
    z-index: var(--z-topbar);
}

#topbar::after {
    content: '';
    position: absolute;
    bottom: -1px;
    left: 10%;
    right: 10%;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--rose), transparent);
    opacity: 0.4;
}

.topbar-left, .topbar-right {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}

/* Mobile topbar safe-area padding */
@media (max-width: 767px) {
    #topbar {
        padding-top: max(5px, env(safe-area-inset-top));
        padding-left: max(6px, env(safe-area-inset-left));
        padding-right: max(6px, env(safe-area-inset-right));
    }
}

.topbar-center {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-grow: 1;
    justify-content: center;
}

.topbar-logo {
    display: flex;
    align-items: center;
    gap: 2px;
    flex-shrink: 0;
    transition: filter 0.2s ease, transform 0.2s ease;
}
.topbar-logo img {
    width: 50px;
    height: 50px;
    object-fit: contain;
}
.topbar-logo:hover {
    filter: saturate(1.15) brightness(1.08);
    transform: scale(1.03);
}

.mobile-sidebar-toggles {
    display: none;
    gap: 4px;
}

.topbar-btn {
    width: 34px;
    height: 34px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--bg-panel);
    color: var(--text-dim);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: color 0.2s, border-color 0.2s, background 0.2s;
}
.topbar-btn:hover { color: var(--accent-soft); border-color: var(--border-glow); }
.topbar-btn:active { background: #221a34; transform: scale(0.95); }

/* Image-based topbar buttons (gen_ui_icons.py topbar group).
   The icon's own dark frame already provides the button shape, so the
   button's own border/background are removed. */
.topbar-btn.has-img {
    width: 50px;
    height: 50px;
    background: transparent;
    border: none;
    padding: 0;
    overflow: hidden;
}
.topbar-btn.has-img img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 8px;
    transition: filter 0.2s ease, transform 0.2s ease;
    filter: saturate(0.95);
}
.topbar-btn.has-img:hover img {
    filter: saturate(1.15) brightness(1.08);
    transform: scale(1.06);
}
.topbar-btn.has-img:hover {
    background: transparent;
    border: none;
}

/* Undo button — uses the .topbar-btn.has-img base styling (matches
   settings / bug-report / feedback icons) plus a small badge counter
   showing remaining snapshots. Hidden when the snapshot stack is empty.
   Override `overflow: visible` so the absolute-positioned badge isn't
   clipped by the parent's icon-mask overflow rule. Vertical divider on
   the left visually separates the button from the logo group. */
.topbar-btn.btn-undo,
.topbar-btn.has-img.btn-undo {
    position: relative;
    overflow: visible;
    margin-left: 8px;
    padding-left: 10px;
}
.btn-undo::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    width: 1px;
    height: 28px;
    background: linear-gradient(180deg,
        transparent 0%,
        rgba(180, 140, 200, 0.45) 30%,
        rgba(180, 140, 200, 0.45) 70%,
        transparent 100%);
    pointer-events: none;
}
.btn-undo .undo-badge {
    position: absolute;
    top: -2px;
    right: -4px;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    background: linear-gradient(180deg, #ff6da3, #c84680);
    color: #fff;
    border: 1.5px solid rgba(20, 12, 30, 0.9);
    border-radius: 9px;
    font-family: 'DM Mono', monospace;
    font-size: 12px;
    font-weight: 800;
    line-height: 15px;
    text-align: center;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6),
                0 0 8px rgba(255, 110, 170, 0.35);
    pointer-events: none;
    z-index: 2;
}
.btn-undo.hidden { display: none; }

.day-display {
    font-family: 'DM Mono', monospace;
    font-size: 14px;
    font-weight: 600;
    color: rgba(215, 200, 232, 0.88);
    white-space: nowrap;
    letter-spacing: 0.5px;
    text-align: center;
    line-height: 1.15;
    padding: 4px 12px;
    border-radius: 8px;
    /* Calmer than before: no bright gradient, matte dark panel */
    background: rgba(18, 12, 28, 0.55);
    border: 1px solid rgba(90, 70, 120, 0.3);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3);
    transition: border-color 0.6s ease, background 0.6s ease;
}
.day-weekday {
    display: block;
    font-size: 9px;
    color: var(--text-faint);
    letter-spacing: 1px;
    text-transform: uppercase;
    margin-top: 1px;
}
/* Episodic act label — subtle text under day display. Cursor:help on
   hover signals the contextual tooltip (title attr set by _updateDay). */
.day-act {
    display: block;
    font-family: 'Crimson Pro', serif;
    font-size: 8px;
    font-style: italic;
    color: var(--orchid);
    opacity: 0.6;
    letter-spacing: 0.3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100px;
    cursor: help;
    border-bottom: 1px dotted rgba(224, 176, 240, 0.35);
    transition: opacity 0.4s ease;
}

/* ============================================
   Weekly Calendar Strip (read-only forward visibility)
   - Desktop: 7 inline cells between day-display and time-slots
   - Mobile: hidden inline; day-display becomes a dropdown trigger
     that opens .week-strip-popover with the same content
   Markers: $ on RentDueDay, ♥ on Saturday (gated on GF active)
   ============================================ */
.week-strip {
    display: flex;
    gap: 2px;
    align-items: stretch;
    padding: 2px;
    border-radius: 8px;
    background: rgba(18, 12, 28, 0.4);
    border: 1px solid rgba(90, 70, 120, 0.25);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.25);
    flex-shrink: 0;
}
.week-strip-cell {
    position: relative;
    min-width: 30px;
    padding: 4px 5px 5px;
    border-radius: 5px;
    text-align: center;
    font-family: 'DM Mono', monospace;
    color: rgba(180, 160, 200, 0.55);
    background: transparent;
    border: 1px solid transparent;
    line-height: 1;
    transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}
.week-strip-cell .ws-wd {
    font-size: 9px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--text-faint);
    margin-bottom: 3px;
    opacity: 0.85;
}
.week-strip-cell .ws-num {
    font-size: 13px;
    font-weight: 600;
    color: inherit;
}
.week-strip-cell.past {
    opacity: 0.35;
}
.week-strip-cell.current {
    background: linear-gradient(180deg, rgba(232, 200, 96, 0.18), rgba(232, 200, 96, 0.06));
    border-color: rgba(232, 200, 96, 0.5);
    color: rgba(240, 215, 140, 0.95);
    box-shadow: 0 0 0 1px rgba(232, 200, 96, 0.2);
}
.week-strip-cell.current .ws-wd {
    color: rgba(240, 215, 140, 0.85);
    opacity: 1;
}
.week-strip-cell .ws-markers {
    position: absolute;
    top: 1px;
    right: 2px;
    display: flex;
    gap: 1px;
    line-height: 1;
    pointer-events: none;
}
.week-strip-cell .ws-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    display: inline-block;
    box-shadow: 0 0 4px currentColor;
}
.week-strip-cell .ws-dot-rent {
    background: #ffcb5c;
    color: #ffcb5c;
}
.week-strip-cell .ws-dot-weekend {
    background: #f56aa3;
    color: #f56aa3;
}
.week-strip-cell.past .ws-dot {
    box-shadow: none;
    opacity: 0.5;
}

/* Mobile dropdown variant — fixed-position popover anchored under topbar.
   On desktop this stays .hidden; mobile media query swaps inline strip
   out and reveals this when day-display is clicked. */
.week-strip-popover {
    display: none;
}
.week-strip-popover.open {
    display: block;
    position: fixed;
    top: var(--topbar-height, 60px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 200;
    background: rgba(22, 14, 32, 0.96);
    border: 1px solid rgba(180, 140, 220, 0.35);
    border-radius: 10px;
    padding: 10px 12px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
    min-width: 280px;
    backdrop-filter: blur(8px);
}
.week-strip-popover-inner {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 3px;
}
.week-strip-popover-inner .week-strip-cell {
    min-width: 0;
    padding: 6px 2px 7px;
}
.week-strip-popover-inner .week-strip-cell .ws-wd { font-size: 9px; }
.week-strip-popover-inner .week-strip-cell .ws-num { font-size: 14px; }
.week-strip-popover-legend {
    display: flex;
    justify-content: center;
    gap: 12px;
    margin-top: 8px;
    font-size: 10px;
    color: var(--text-faint);
    letter-spacing: 0.3px;
}
.week-strip-popover-legend .lg-dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    margin-right: 4px;
    vertical-align: middle;
}

/* day-display becomes a button on mobile (clickable). Reset button defaults. */
button.day-display {
    cursor: default;
    font: inherit;
    line-height: 1.15;
}

.time-slots {
    display: flex;
    border-radius: 6px;
    overflow: hidden;
    border: 1px solid var(--border);
    position: relative;
}

/* Desktop: toggle button is hidden — all four slots always visible.
   Activated by the ≤768 media query below. */
.time-slots-toggle {
    display: none;
}

.time-seg {
    padding: 9px 16px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--text-faint);
    background: var(--bg);
    cursor: pointer;
    text-align: center;
    transition: background 0.5s ease, color 0.5s ease, text-shadow 0.5s ease;
    border-right: 1px solid var(--border);
    position: relative;
    flex: 1;
}
.time-seg:last-child { border-right: none; }

.time-seg.active {
    /* Quieter active state: subtle tint + thin underline instead of bright gradient */
    background: rgba(232, 200, 96, 0.08);
    color: rgba(240, 215, 140, 0.92);
    text-shadow: none;
    box-shadow: inset 0 -2px 0 rgba(232, 200, 96, 0.55);
}
.time-seg.active::after {
    content: '';
    position: absolute;
    bottom: 3px;
    left: 50%;
    transform: translateX(-50%);
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: var(--gold);
    box-shadow: 0 0 3px rgba(232, 200, 96, 0.6);
    animation: pulse-dot 2.4s ease-in-out infinite;
    opacity: 0.65;
}

.time-seg.past {
    opacity: 0.4;
    pointer-events: none;
}
.time-seg:hover:not(.active):not(.past) {
    background: rgba(100, 60, 140, 0.15);
    color: var(--text-dim);
}

@keyframes pulse-dot {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.3; }
}

/* ── Time-of-day color transitions ── */
/* Time-of-day tints: keep the tone-variation signal but tone it way down.
   Each active slot gets a soft colour fill + matching underline; no shouty
   gradient fills anymore. */
.time-morning #topbar { border-bottom-color: rgba(200, 160, 80, 0.4); transition: border-color 0.6s ease; }
.time-morning .topbar-logo { color: rgb(240, 200, 120); }
.time-morning .time-seg.active {
    background: rgba(255, 220, 100, 0.08);
    color: rgba(255, 220, 140, 0.92);
    text-shadow: none;
    box-shadow: inset 0 -2px 0 rgba(255, 220, 100, 0.55);
}
.time-morning .time-seg.active::after { background: rgb(255, 220, 100); box-shadow: 0 0 3px rgba(255, 220, 100, 0.55); }

.time-lunch #topbar { border-bottom-color: rgba(180, 140, 80, 0.4); transition: border-color 0.6s ease; }
.time-lunch .topbar-logo { color: rgb(230, 190, 130); }
.time-lunch .time-seg.active {
    background: rgba(240, 210, 100, 0.08);
    color: rgba(240, 215, 140, 0.92);
    text-shadow: none;
    box-shadow: inset 0 -2px 0 rgba(240, 210, 100, 0.55);
}
.time-lunch .time-seg.active::after { background: rgb(240, 210, 100); box-shadow: 0 0 3px rgba(240, 210, 100, 0.55); }

.time-evening #topbar { border-bottom-color: rgba(200, 100, 60, 0.4); transition: border-color 0.6s ease; }
.time-evening .topbar-logo { color: rgb(240, 150, 100); }
.time-evening .time-seg.active {
    background: rgba(255, 160, 80, 0.1);
    color: rgba(255, 180, 130, 0.92);
    text-shadow: none;
    box-shadow: inset 0 -2px 0 rgba(255, 160, 80, 0.55);
}
.time-evening .time-seg.active::after { background: rgb(255, 160, 80); box-shadow: 0 0 3px rgba(255, 160, 80, 0.55); }

.time-night #topbar { border-bottom-color: rgba(60, 50, 120, 0.4); transition: border-color 0.6s ease; }
.time-night .topbar-logo { color: rgb(140, 120, 200); }
.time-night .time-seg.active {
    background: rgba(150, 130, 220, 0.1);
    color: rgba(175, 155, 230, 0.92);
    text-shadow: none;
    box-shadow: inset 0 -2px 0 rgba(150, 130, 220, 0.55);
}
.time-night .time-seg.active::after { background: rgb(150, 130, 220); box-shadow: 0 0 3px rgba(150, 130, 220, 0.55); }

/* ── Time-of-day ambient body overlay ── */
body.time-morning::before { content:''; position:fixed; inset:0; pointer-events:none; z-index:0; background:radial-gradient(ellipse at 50% 30%, rgba(200,160,60,0.03), transparent 70%); }
body.time-afternoon::before { content:''; position:fixed; inset:0; pointer-events:none; z-index:0; }
body.time-evening::before { content:''; position:fixed; inset:0; pointer-events:none; z-index:0; background:radial-gradient(ellipse at 50% 50%, rgba(180,100,40,0.03), transparent 70%); }
body.time-night::before { content:''; position:fixed; inset:0; pointer-events:none; z-index:0; background:radial-gradient(ellipse at 50% 70%, rgba(40,30,100,0.04), transparent 70%); }

.btn-wait {
    width: 28px;
    height: 28px;
    border-radius: 6px;
    background: rgba(100, 60, 140, 0.2);
    border-color: rgba(100, 60, 140, 0.3);
    color: var(--orchid);
}
.btn-wait:hover {
    background: rgba(100, 60, 140, 0.35);
    color: var(--rose-bright);
}

.topbar-money, .topbar-energy {
    display: flex;
    align-items: center;
    gap: 3px;
}
.money-icon {
    font-family: 'DM Mono', monospace;
    font-weight: 600;
    color: var(--gold);
    font-size: 12px;
}
.money-value {
    font-family: 'DM Mono', monospace;
    font-size: 12px;
    color: var(--gold);
    font-weight: 500;
}
.energy-bolt { flex-shrink: 0; }
.energy-value {
    font-family: 'DM Mono', monospace;
    font-size: 12px;
    color: var(--energy);
    font-weight: 500;
}
.energy-value.low { color: var(--energy-low); }
.energy-value.critical { color: var(--energy-crit); }


/* ============================================
   8. MINI STATS STRIP
   ============================================ */
.stats-strip {
    display: none; /* shown on phone or when left panel collapsed */
    align-items: center;
    gap: 10px;
    padding: 4px 10px;
    background: var(--bg-deep);
    border-bottom: 1px solid rgba(46, 34, 66, 0.5);
    flex-shrink: 0;
}
.stats-strip.visible { display: flex; }

.mini-stat {
    display: flex;
    align-items: center;
    flex-grow: 1;
    gap: 5px;
}

.stat-icon {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    font-weight: 600;
    flex-shrink: 0;
    width: 14px;
    text-align: center;
    opacity: 0.7;
}
.energy-icon { color: var(--energy); }
.arousal-icon { color: var(--arousal); }
.sub-icon { color: var(--sub); }

.stat-num {
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    color: var(--text-dim);
    min-width: 18px;
    text-align: right;
}
.fem-num { color: var(--fem); }
/* UX-09: tiny tier-pill rendered as ::after on the fem stat-num.
   data-tier is set by stats.js _setFemMasc(). Hidden on phones (no room). */
.fem-num[data-tier]::after {
    content: attr(data-tier);
    display: inline-block;
    margin-left: 4px;
    padding: 1px 4px;
    font-size: 8px;
    font-weight: 700;
    line-height: 1;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--fem);
    background: rgba(228, 140, 184, 0.12);
    border: 1px solid rgba(228, 140, 184, 0.35);
    border-radius: 3px;
    vertical-align: middle;
}
body.phone .fem-num[data-tier]::after { display: none; }

.stat-money {
    font-family: 'DM Mono', monospace;
    font-size: 11px;
    color: var(--gold);
    font-weight: 500;
    flex-shrink: 0;
    letter-spacing: 0.5px;
}

.mini-bar {
    flex-grow: 1;
    height: 6px;
    border-radius: 3px;
    background: rgba(20, 18, 35, 0.9);
    overflow: hidden;
    position: relative;
    box-shadow: inset 0 1px 2px rgba(0,0,0,0.4);
}
.dual-bar { display: flex; }

.mini-fill {
    height: 100%;
    border-radius: 3px;
    transition: width 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
    position: relative;
}
.mini-fill::after {
    content: '';
    position: absolute;
    top: 0;
    left: -50%;
    width: 50%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.1), transparent);
    animation: shimmer 3s ease-in-out infinite;
}

.energy-fill {
    background: linear-gradient(90deg, var(--energy) 0%, #40c880 50%, #3ab870 100%);
    box-shadow: 0 0 10px rgba(92, 216, 156, 0.3);
}
.energy-fill.low { background: linear-gradient(90deg, var(--energy-low), #c89030); box-shadow: 0 0 10px rgba(200, 144, 48, 0.3); }
.energy-fill.critical { background: linear-gradient(90deg, var(--energy-crit), #c84040); box-shadow: 0 0 10px rgba(200, 64, 64, 0.3); }

.arousal-fill {
    background: linear-gradient(90deg, #c85060 0%, var(--arousal) 50%, #e06878 100%);
    box-shadow: 0 0 10px rgba(224, 104, 120, 0.3);
}
.masc-fill {
    background: linear-gradient(90deg, var(--masc) 0%, #6898d8 60%, #5888c8 100%);
    border-radius: 6px 0 0 6px;
    box-shadow: 0 0 8px rgba(80, 128, 200, 0.2);
}
/* Transformation Ladder: Fem "becoming" fill is GREEN (0-100). Once green hits
   100 the pink .fem-pink-fill overlay fills the same track a second time for the
   100-200 "deepening" pink-overflow zone (see stats.js _updatePresentationBar). */
.fem-fill {
    background: linear-gradient(90deg, #2f9e6a 0%, #52c98a 60%, #6ee0a2 100%);
    border-radius: 0 6px 6px 0;
    box-shadow: 0 0 8px rgba(95, 217, 143, 0.25);
}
.fem-pink-fill {
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 0;
    background: linear-gradient(90deg, #d870a8 0%, var(--fem) 60%, #f0a0cc 100%);
    box-shadow: 0 0 12px rgba(232, 140, 184, 0.45);
    border-radius: 6px;
    z-index: 3;
    transition: width 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
    pointer-events: none;
}
.sub-fill {
    background: linear-gradient(90deg, #9070c8 0%, var(--sub) 50%, #b090e0 100%);
    box-shadow: 0 0 10px rgba(168, 128, 224, 0.3);
}
.shame-fill {
    background: linear-gradient(90deg, #8b6040 0%, #c89060 50%, #d8a070 100%);
    box-shadow: 0 0 10px rgba(180, 120, 70, 0.3);
}

@keyframes shimmer {
    0% { left: -50%; }
    100% { left: 150%; }
}
/* ============================================
   9. THREE-COLUMN GAME LAYOUT
   ============================================ */
.main-content {
    display: flex;
    flex: 1;
    overflow: hidden;
    position: relative;
}

/* Left column */
.left-column {
    width: var(--left-column-width);
    flex-shrink: 0;
    background: linear-gradient(180deg, var(--bg-warm), var(--bg-deep));
    border-right: 1px solid var(--border);
    overflow-y: auto;
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    position: relative;
    transition: width 0.3s var(--ease-out), margin-left 0.3s var(--ease-out);
}
/* Base collapsed state — overridden by detailed rules below */

/* Right column */
.right-column {
    width: var(--right-column-width);
    flex-shrink: 0;
    background: linear-gradient(180deg, var(--bg-warm), var(--bg-deep));
    border-left: 1px solid var(--border);
    /* 2026-06-19: the column itself no longer scrolls — .char-panel-scroll
       (the content wrapper) owns the vertical scroll, and .char-panel-footer
       is a fixed bottom toolbar OUTSIDE it. overflow:hidden keeps the footer
       pinned; .collapsed re-enables overflow:visible for the peek-tab. */
    overflow: hidden;
    padding: 10px 14px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    position: relative;
    transition: width 0.3s var(--ease-out), margin-right 0.3s var(--ease-out);
}
/* Content scroll region — fills the column between header chrome and the
   fixed footer; min-height:0 lets it shrink below content height so the
   inner content (tall nude sprite stack, character slots) scrolls here while
   the footer stays put. */
.char-panel-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    gap: 6px;
    position: relative;   /* anchor for .char-img-controls overlay */
}
/* Image stage (0.2.9): relative wrapper so the eye/play controls overlay the
   top-right of the figure. Doll + nude swap inside it; status badges sit
   underneath. Fills the scroll region so the figure gets the height the old
   Nude·Clothed tab row used to take. */
.char-image-stage {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
/* Eye (show-nude) + play/pause (animate) — overlaid top-right of the image. */
.char-img-controls {
    position: absolute;
    top: 8px; right: 8px;
    z-index: 6;
    display: flex; gap: 6px;
}
.char-img-btn {
    width: 32px; height: 32px; border-radius: 50%;
    background: rgba(0, 0, 0, 0.5); border: 1px solid rgba(255, 255, 255, 0.25);
    color: #fff; font-size: 14px; line-height: 1; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
    transition: background 0.15s;
}
.char-img-btn:hover { background: rgba(228, 120, 184, 0.55); }
.char-img-btn.active { background: rgba(228, 120, 184, 0.8); border-color: #e478b8; }

/* 0.2.9: combined side-panel tabs (Char / Stats / Hints — left column merged in) */
.panel-tabs {
    display: flex;
    gap: 4px;
    padding: 6px 8px 5px;
    border-bottom: 1px solid var(--border);
    flex: 0 0 auto;
}
.panel-tab {
    flex: 1;
    min-height: 32px;
    padding: 5px 4px;
    background: rgba(20, 15, 30, 0.5);
    border: 1px solid rgba(46, 34, 66, 0.4);
    border-radius: 6px;
    color: var(--text-faint);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.3px;
    cursor: pointer;
    transition: all 0.2s ease;
}
.panel-tab:hover { border-color: var(--border-glow); color: var(--text); }
.panel-tab.active {
    background: rgba(100, 60, 140, 0.2);
    border-color: var(--orchid);
    color: var(--text);
}
/* Tab panes: only the active one shows. The active pane fills the scroll region
   so the Char doll-stage still stretches; Stats/Hints content flows + scrolls. */
.tab-pane { display: none; }
.tab-pane.active {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    gap: 6px;
}
/* Journal tab: review-overlay shortcuts (Journal / Log / Gallery / Achievements)
   below the hints list. */
.journal-links {
    display: flex;
    gap: 8px;
    justify-content: center;
    flex-wrap: wrap;
    padding: 10px 4px 4px;
    margin-top: 6px;
    border-top: 1px solid var(--border);
}
.journal-links .action-icon-only {
    width: 46px;
    height: 46px;
}

/* Base collapsed state — overridden by detailed rules below */

/* Center panel */
.center-panel {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    position: relative;
    overflow: hidden;
}

/* Cap story content to a comfortable reading width even with both
   side panels open. Without this the prose flows across the full
   center column (can exceed 90ch) and the eye has to travel too far. */
.center-panel .story-content,
.center-panel .choices-grid {
    max-width: 720px;
    margin: 0 auto;
    width: 100%;
}

/* Expanded mode (when panels collapsed) */
.center-panel.panels-expanded .story-content {
    max-width: 720px;
    margin: 0 auto;
}
.center-panel.panels-expanded .story-text {
    font-size: calc(var(--font-size-base, 16px) + 1px);
}
.center-panel.panels-expanded .choices-grid {
    max-width: 760px;
    margin: 0 auto;
}

/* Collapse buttons — vertically centered tab on panel edge */
.btn-collapse {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 16px;
    height: 48px;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    color: var(--text-faint);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10;
    transition: all 0.2s var(--ease-out);
    padding: 0;
    font-size: 10px;
    cursor: pointer;
}
.btn-collapse:hover {
    color: var(--rose);
    border-color: var(--border-glow);
    background: var(--bg-card-hover);
    width: 20px;
}
.btn-collapse-left {
    right: -1px;
    border-radius: 0 6px 6px 0;
    border-left: none;
}
.btn-collapse-right {
    left: -1px;
    border-radius: 6px 0 0 6px;
    border-right: none;
}

/* When collapsed, keep collapse buttons visible via overflow exception */
.left-column.collapsed { overflow: visible; width: 0; padding: 0; margin-left: -1px; border-right: none; }
.left-column.collapsed > *:not(.btn-collapse) { display: none; }
.left-column.collapsed .btn-collapse-left {
    right: -18px;
    background: var(--bg-warm);
    border: 1px solid var(--border);
    border-left: none;
    border-radius: 0 6px 6px 0;
    height: 56px;
    width: 18px;
}

.right-column.collapsed { overflow: visible; width: 0; padding: 0; margin-right: -1px; border-left: none; }
.right-column.collapsed > *:not(.btn-collapse) { display: none; }

/* foundby:CutieLvr. `.collapsed` (desktop collapse, persisted via
 * PanelCollapseLeft) and `.user-expanded` (scene-mode / narrow re-open) are
 * independent classes. Opening a column that still carried `.collapsed`
 * restored its width via user-expanded but `.collapsed > * { display:none }`
 * kept every child hidden, so the sidebar opened EMPTY (and survived restart
 * because the collapse flag persists). user-expanded must fully reveal the
 * column + its children and win over a leftover collapsed state. Placed after
 * the .collapsed rules so equal-specificity selectors win on source order. */
.left-column.user-expanded {
    width: var(--left-column-width); padding: 14px 16px; margin-left: 0;
    overflow-y: auto; border-right: 1px solid var(--border);
}
.right-column.user-expanded {
    width: var(--right-column-width); padding: 10px 14px; margin-right: 0;
    overflow-y: auto; border-left: 1px solid var(--border);
}
.left-column.user-expanded > *:not(.btn-collapse),
.right-column.user-expanded > *:not(.btn-collapse) {
    display: revert; opacity: 1; visibility: visible;
}
/* display:revert (noetig gegen .collapsed display:none) degradiert alle
   Kinder zu block - Flex-Container explizit wiederherstellen. Inline
   display:none aus setPanelMode (Tab-System) gewinnt weiterhin. */
/* 2026-06-19: content moved inside .char-panel-scroll, so these target
   grandchildren via the descendant combinator now (footer + scroll wrapper
   stay direct children and still match). display:revert from the `> *` rule
   above lands the wrapper as block — re-assert flex on it too. */
.right-column.user-expanded > .char-panel-scroll,
.right-column.user-expanded .char-image-stage,
.right-column.user-expanded .char-panel-footer,
.right-column.user-expanded .doll-status-row {
    display: flex;
}
.right-column.user-expanded .doll-status-row.hidden { display: none; }

.right-column.collapsed .btn-collapse-right {
    left: -18px;
    background: var(--bg-warm);
    border: 1px solid var(--border);
    border-right: none;
    border-radius: 6px 0 0 6px;
    height: 56px;
    width: 18px;
}

/* ─── Scene-Mode (v0.2.4) ─────────────────────────────────────
   Narrative scenes (not hub maps) auto-collapse sidebars and hide
   the redundant stats-strip so the story panel breathes.
   The collapse buttons remain — user can still expand manually.
   Hub mode (location maps) uses default layout. */
body.scene-mode .left-column:not(.user-expanded) {
    width: 0;
    padding: 0;
    margin-left: -1px;
    border-right: none;
    overflow: visible;
}
/* F40: fade children out instead of display:none so the column collapse
 * reads as smooth. Column width already transitions 0.3s above; opacity
 * + visibility follow the same curve. visibility: hidden at the end
 * keeps screen readers + tab order honest while allowing the fade. */
body.scene-mode .left-column:not(.user-expanded) > *:not(.btn-collapse) {
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease-out, visibility 0s linear 0.2s;
}
body.scene-mode .left-column:not(.user-expanded) .btn-collapse-left {
    right: -18px;
    background: var(--bg-warm);
    border: 1px solid var(--border);
    border-left: none;
    border-radius: 0 6px 6px 0;
    height: 56px;
    width: 18px;
}
body.scene-mode .right-column:not(.user-expanded) {
    width: 0;
    padding: 0;
    margin-right: -1px;
    border-left: none;
    overflow: visible;
}
/* F40: see left-column comment above */
body.scene-mode .right-column:not(.user-expanded) > *:not(.btn-collapse) {
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease-out, visibility 0s linear 0.2s;
}
body.scene-mode .right-column:not(.user-expanded) .btn-collapse-right {
    left: -18px;
    background: var(--bg-warm);
    border: 1px solid var(--border);
    border-right: none;
    border-radius: 6px 0 0 6px;
    height: 56px;
    width: 18px;
}

/* ── Discoverable re-open handle (foundby:CutieLvr) ──────────────────
   The collapsed peek-tab was an 18px sliver players couldn't find, so the
   sidebars read as "gone for good". Widen + pink-tint it, flip the chevron to
   point outward ("open"), and apply identically to BOTH the manual .collapsed
   (hub) and scene-mode states so the affordance is the same everywhere.
   user-expanded is persisted in JS so the panels don't re-vanish each scene.
   Mobile/tablet use the topbar drawer toggles instead (see _07-responsive). */
.left-column.collapsed .btn-collapse-left,
body.scene-mode .left-column:not(.user-expanded) .btn-collapse-left {
    width: 26px;
    height: 72px;
    right: -26px;
    background: linear-gradient(90deg, var(--bg-warm), rgba(232, 140, 184, 0.22));
    border: 1px solid var(--rose, #e88cb8);
    border-left: none;
    box-shadow: 2px 0 14px rgba(232, 140, 184, 0.5);
    z-index: 50;
}
.right-column.collapsed .btn-collapse-right,
body.scene-mode .right-column:not(.user-expanded) .btn-collapse-right {
    width: 26px;
    height: 72px;
    left: -26px;
    background: linear-gradient(270deg, var(--bg-warm), rgba(232, 140, 184, 0.22));
    border: 1px solid var(--rose, #e88cb8);
    border-right: none;
    box-shadow: -2px 0 14px rgba(232, 140, 184, 0.5);
    z-index: 50;
}
.left-column.collapsed .btn-collapse-left svg,
.right-column.collapsed .btn-collapse-right svg,
body.scene-mode .left-column:not(.user-expanded) .btn-collapse-left svg,
body.scene-mode .right-column:not(.user-expanded) .btn-collapse-right svg {
    transform: scaleX(-1);
    width: 15px;
    height: 15px;
}
/* Scene-Mode: side panels collapse but stats stay visible up top.
   Slightly enlarged so the player can read them at a glance during narrative.
   Mobile already shows the strip at its own size — only enlarge on desktop. */
body.scene-mode .stats-strip {
    display: flex !important;
}
body.scene-mode:not(.phone) .stats-strip {
    padding: 7px 14px;
    gap: 14px;
}
body.scene-mode:not(.phone) .stats-strip .mini-bar {
    height: 9px;
    border-radius: 4px;
}
body.scene-mode:not(.phone) .stats-strip .stat-num {
    font-size: 12px;
    min-width: 22px;
}
body.scene-mode:not(.phone) .stats-strip .stat-icon {
    font-size: 11px;
    width: 16px;
    opacity: 0.9;
}
body.scene-mode:not(.phone) .stats-strip .stat-money {
    font-size: 13px;
}

/* Stats panel: Arousal/Sub/Shame always visible alongside primary stats.
   The collapsible toggle was removed in 0.2.3 — re-add once we have more
   than 5 stat bars to actually warrant the fold. */
.stats-secondary { display: block; padding-top: 4px; }


.panel-section-header {
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: rgba(232, 140, 184, 0.88);
    margin-bottom: 12px;
    text-align: center;
    padding: 6px 0 8px 0;
    /* Soft divider under the header — clearer panel section chunking */
    border-bottom: 1px solid rgba(228, 140, 184, 0.22);
}
/* Hints header keeps left-aligned because it has the badge + toggle on the right side */
.panel-section-header.hints-header { text-align: left; }

.panel-divider {
    height: 1px;
    background: linear-gradient(90deg, var(--border), transparent 80%);
    margin: 8px 0;
}

/* Sub-group label under a panel divider — tiny caption that names the
   next chunk of rows ("Economy", "Status"). Keeps the stats panel
   scannable without introducing a heavy H2. */
.panel-subgroup-label {
    font-size: 9px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.15em;
    color: rgba(200, 180, 220, 0.45);
    margin: -4px 0 4px;
    padding-left: 2px;
}


/* ============================================
   10. LEFT PANEL: STATS, ACTIONS, TRAVEL
   ============================================ */
.stats-panel {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.stat-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Icon + text-label wrap — the label is the short stat name, sitting under
   the painted glow icon (added 2026-04-20). Onboarding clarity without
   losing the icon's visual identity. */
.stat-icon-wrap {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 0;
    flex-shrink: 0;
    width: 44px;
}
.stat-icon-label {
    font-size: 9px;
    line-height: 1.1;
    color: var(--text-dim);
    text-align: center;
    letter-spacing: 0.3px;
    text-transform: uppercase;
    margin-top: -2px;
    opacity: 0.75;
}

/* Stats panel icon labels (replaces .stat-name text in 0.2.3).
   Painted glow icons sit in place of "Energy"/"Arousal"/etc. text. */
.stat-icon-img {
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    object-fit: contain;
    filter: drop-shadow(0 0 4px rgba(255, 80, 180, 0.4));
    transition: filter 0.18s ease, transform 0.18s ease;
}
.stat-row:hover .stat-icon-img {
    filter: drop-shadow(0 0 6px rgba(255, 80, 180, 0.6));
    transform: scale(1.06);
}
.presentation-labels .stat-icon-img {
    width: 32px;
    height: 32px;
}

.stat-name {
    font-size: 12px;
    color: var(--text-dim);
    flex-shrink: 0;
    min-width: 78px;
    font-weight: 500;
}

.stat-bar {
    flex-grow: 1;
    height: 12px;
    border-radius: 6px;
    background: rgba(20, 18, 35, 0.9);
    overflow: hidden;
    position: relative;
    box-shadow: inset 0 2px 4px rgba(0,0,0,0.4), 0 0 1px rgba(140, 100, 180, 0.1);
}

.stat-fill {
    height: 100%;
    border-radius: 6px;
    transition: width 0.4s var(--ease-out);
    position: relative;
    box-shadow: inset 0 -1px 2px rgba(0, 0, 0, 0.3);
    /* Slight saturation bump makes the per-stat fill colours pop on dark panels
       without adding shouty glows. Per-stat shadows live in _02-topbar.css. */
    filter: saturate(1.12);
}
/* Glass highlight on fill */
.stat-fill::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 6px;
    background: linear-gradient(180deg, rgba(255,255,255,0.15) 0%, transparent 55%);
    pointer-events: none;
}
/* Shimmer sweep */
.stat-fill::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 50%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.12), transparent);
    animation: loading-shimmer 3s ease-in-out infinite;
}

.stat-val {
    font-family: 'DM Mono', monospace;
    font-size: 14px;
    font-weight: 700;
    color: rgba(245, 230, 255, 0.95);
    min-width: 28px;
    text-align: right;
    /* Subtle text-shadow keeps the number legible over the glow of the filling bar */
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

/* Presentation dual bar */
.stat-row-presentation {
    flex-direction: column;
    align-items: stretch;
    gap: 3px;
}
.presentation-labels {
    display: flex;
    justify-content: space-between;
}
.masc-label { color: var(--masc); font-size: 11px; }
.fem-label { color: var(--fem); font-size: 11px; }
.presentation-track {
    display: flex;
    position: relative;
    height: 12px;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(20, 18, 35, 0.9);
    box-shadow: inset 0 2px 4px rgba(0,0,0,0.4), 0 0 1px rgba(140, 100, 180, 0.1);
}
.tier-marker {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    background: rgba(255, 255, 255, 0.2);
    pointer-events: none;
    z-index: 2;
}
.presentation-values {
    display: flex;
    justify-content: space-between;
}
.masc-val { color: var(--masc); font-size: 11px; }
.fem-tier-label {
    font-size: 9px; font-weight: 600; text-align: center;
    color: var(--fem); opacity: 0.7; letter-spacing: 0.5px;
    text-transform: uppercase; margin-top: 1px;
}
.fem-val { color: var(--fem); font-size: 11px; }

/* Money */
.money-row { justify-content: space-between; }
.money-val {
    font-family: 'DM Mono', monospace;
    color: var(--gold);
    font-size: 18px;
    font-weight: 500;
    text-shadow: 0 0 12px rgba(232, 200, 96, 0.15);
    transition: color 0.3s ease;
}
.money-val.tick-up { color: var(--green); }
.money-val.tick-down { color: var(--red); }

/* Money sub-indicators: allowance cap + rent reminder (Owner route) */
.money-extra {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: -2px 0 4px 0;
    padding-left: 2px;
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    line-height: 1.3;
    letter-spacing: 0.3px;
    opacity: 0.75;
}
.money-extra.hidden { display: none; }
.money-extra-line {
    color: var(--text-muted, rgba(255,255,255,0.55));
}
.money-extra-line.hidden { display: none; }
.money-extra-allowance::before {
    content: '◆ ';
    color: var(--gold);
    opacity: 0.6;
}
.money-extra-rent::before {
    content: '⌂ ';
    color: var(--gold);
    opacity: 0.6;
}
.money-extra-rent.due-soon { color: var(--red); opacity: 0.95; }

/* Status icons */
.status-icons {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    padding-top: 4px;
}
.status-icon {
    width: 28px;
    height: 28px;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 600;
    transition: opacity 0.3s ease;
}
.status-dirty { background: rgba(60, 100, 140, 0.3); color: #6aa8d8; border: 1px solid rgba(106, 168, 216, 0.3); }
.status-drunk { background: rgba(140, 120, 40, 0.3); color: var(--gold); border: 1px solid rgba(232, 200, 96, 0.3); }
.status-tired { background: rgba(80, 60, 120, 0.3); color: var(--sub); border: 1px solid rgba(168, 128, 224, 0.3); }
.status-makeup { background: rgba(60, 140, 80, 0.3); color: var(--green); border: 1px solid rgba(92, 216, 156, 0.3); }
.status-aroused { background: rgba(140, 50, 60, 0.3); color: var(--arousal); border: 1px solid rgba(224, 104, 120, 0.3); }

/* Actions */
.actions-panel {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.actions-primary {
    display: flex;
    gap: 6px;
}

.action-btn {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 40px;
    background: var(--bg-choice);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text);
    font-size: 13px;
    font-weight: 500;
    transition: all 0.2s ease;
    position: relative;
}
.action-btn:hover {
    background: var(--bg-choice-hover);
    border-color: var(--border-glow);
    transform: translateY(-1px);
}
.action-btn:active { transform: scale(0.97); }
.action-btn svg { opacity: 0.7; }

.action-phone { position: relative; }
.action-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    background: var(--arousal);
    color: white;
    font-size: 9px;
    font-weight: 700;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 0 0 rgba(255, 111, 181, 0.7);
    animation: action-badge-pulse 1.6s ease-in-out infinite;
}
.action-badge.hidden { animation: none; }
@keyframes action-badge-pulse {
    0%   { box-shadow: 0 0 0 0    rgba(255, 111, 181, 0.65), 0 0 6px  rgba(255, 111, 181, 0.55); }
    50%  { box-shadow: 0 0 0 8px  rgba(255, 111, 181, 0),    0 0 14px rgba(255, 111, 181, 0.85); }
    100% { box-shadow: 0 0 0 0    rgba(255, 111, 181, 0),    0 0 6px  rgba(255, 111, 181, 0.55); }
}
/* U-01 v0.2.5: subtle glow on parent button when unread count > 0.
   Selector targets the parent <button> when its #phone-badge child lacks .hidden. */
.action-btn:has(#phone-badge:not(.hidden)) {
    filter: drop-shadow(0 0 6px rgba(255, 111, 181, 0.45));
}

.btn-actions-more {
    height: 26px;
    background: transparent;
    border: 1px solid rgba(46, 34, 66, 0.5);
    border-radius: 6px;
    color: var(--text-faint);
    font-size: 10px;
    letter-spacing: 0.5px;
    transition: all 0.2s ease;
    width: 100%;
}
.btn-actions-more:hover { color: var(--text-dim); border-color: var(--border); }

/* Icon-only action buttons (matches Unity). 76px is the CAP, not a fixed
   size: 3 buttons x 76px + 2x6px gap = 240px, wider than the left column's
   inner width minus padding — the third button (settings) stuck ~16px out
   of the panel. Shrink evenly, keep square via aspect-ratio (2026-06-10). */
.action-icon-only {
    width: 76px;
    max-width: 76px;
    height: auto;
    aspect-ratio: 1 / 1;
    min-width: 0;
    flex: 1 1 0;
    padding: 0;
}
.action-icon-only svg { opacity: 0.8; }
.action-icon-only:hover svg { opacity: 1; }

/* Image-based action icons (replaces inline SVGs, generated via Imagen 4.0) */
.action-icon-only.has-img {
    background: transparent;
    border: none;
    padding: 0;
    overflow: visible;
}
.action-icon-only.has-img img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 8px;
    transition: filter 0.2s ease, transform 0.2s ease;
    filter: saturate(0.95);
}
.action-icon-only.has-img:hover img {
    filter: saturate(1.15) brightness(1.08);
    transform: scale(1.04);
}
.action-icon-only.has-img:hover {
    background: transparent;
    border: none;
}

.actions-secondary {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.actions-secondary .action-icon-only {
    width: 60px;
    height: 60px;
    min-width: 60px;
}
.action-sm {
    flex: 1 1 45%;
    height: 32px;
    font-size: 11px;
}

/* Quick Travel */
.travel-panel {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.travel-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.travel-btn {
    flex: 1 1 30%;
    min-width: 60px;
    height: 32px;
    background: rgba(20, 15, 30, 0.6);
    border: 1px solid rgba(46, 34, 66, 0.4);
    border-radius: 6px;
    color: var(--text-dim);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.3px;
    transition: all 0.2s ease;
}
.travel-btn:hover {
    background: rgba(100, 60, 140, 0.15);
    border-color: var(--border-glow);
    color: var(--text);
}
.travel-btn:active { transform: scale(0.96); }
.travel-btn.disabled {
    opacity: 0.3;
    pointer-events: none;
}


/* Hints panel (inline in left sidebar) */
.hints-panel { padding: 0 12px; }
.hints-header {
    display: flex;
    align-items: center;
    gap: 6px;
}
.hints-count-badge {
    background: var(--orchid);
    color: white;
    font-size: 9px;
    font-weight: 700;
    padding: 1px 5px;
    border-radius: 8px;
    min-width: 14px;
    text-align: center;
}
.btn-panel-toggle {
    margin-left: auto;
    background: none;
    border: none;
    color: var(--text-faint);
    cursor: pointer;
    padding: 2px;
}
.hints-rent {
    font-size: 11px;
    color: var(--arousal);
    padding: 4px 0;
    cursor: pointer;
}
.hints-list {
    max-height: 180px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.hints-subtitle {
    font-size: 9px;
    color: var(--text-faint);
    font-style: italic;
    padding: 0 4px 2px;
    letter-spacing: 0.3px;
}
.hint-item {
    font-size: 11px;
    color: var(--text-dim);
    padding: 5px 8px;
    background: rgba(20, 15, 30, 0.3);
    border-radius: 6px;
    transition: all 0.15s ease;
    display: flex;
    align-items: flex-start;
    gap: 6px;
}
.hint-item .hint-text {
    flex: 1 1 auto;
    min-width: 0;
    cursor: pointer;
}
.hint-item.hint-clickable {
    cursor: pointer;
    border: 1px solid transparent;
}
.hint-item.hint-clickable:hover {
    background: rgba(40, 30, 60, 0.4);
    color: var(--text);
    border-color: rgba(196, 112, 224, 0.2);
}

/* Dismiss (×) button — only visible on hints with priority > 0 (Master
   orders + rent warnings stay mandatory). Hover darkens; click persists
   the hint's text hash in localStorage for 48h. */
.hint-dismiss {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    padding: 0;
    border: none;
    background: rgba(100, 80, 120, 0.2);
    color: var(--text-faint);
    border-radius: 3px;
    font-size: 13px;
    line-height: 14px;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
    opacity: 0.4;
}
.hint-item:hover .hint-dismiss {
    opacity: 0.9;
}
.hint-dismiss:hover {
    background: rgba(224, 104, 120, 0.35);
    color: var(--text);
}

/* Character panel additions */
/* (0.2.9: .char-view-toggle / .char-toggle-btn — the Nude·Clothed tab bar —
   were removed; the eye button is the sole dressed⇄nude toggle.) */
.char-slot-row {
    display: flex;
    gap: 4px;
}
.char-slot.half {
    flex: 1;
    min-width: 0;
}

.char-panel-footer {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    align-items: flex-start;
    gap: 12px;
    padding: 8px 12px;
    border-top: 1px solid var(--border);
    /* Owner 2026-06-07: Bug-Report/Feedback unter ALLEN Panel-Tabs sichtbar.
       2026-06-19 (report: "buttons inbetween the nude static pics"): the footer
       was position:sticky inside the SCROLLING column with a transparent-top
       gradient, so in short/landscape windows the body sprites scrolled UNDER it
       and showed THROUGH the icons. Now it's a fixed bottom row OUTSIDE
       .char-panel-scroll (flex:0 0 auto) — always visible, never overlapping,
       solid background. */
    flex: 0 0 auto;
    background: var(--bg-deep);
}
.char-footer-btn {
    flex: 1;
    height: 28px;
    background: rgba(20, 15, 30, 0.4);
    border: 1px solid rgba(46, 34, 66, 0.3);
    border-radius: 6px;
    color: var(--text-faint);
    font-size: 10px;
    transition: all 0.2s ease;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}
.char-footer-btn:hover { border-color: var(--border); color: var(--text-dim); }

/* Image-based char footer buttons (bug report + feedback) — match the
   action_bar phone/wardrobe button size. Label sits below the icon. */
.char-footer-btn.has-img {
    background: transparent;
    border: none;
    height: auto;
    padding: 0;
    overflow: visible;
    flex-direction: column;
    gap: 4px;
    color: var(--text-dim);
}
.char-footer-btn.has-img img {
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: 8px;
    transition: filter 0.2s ease, transform 0.2s ease;
    filter: saturate(0.95);
}
.char-footer-label {
    white-space: nowrap;   /* "BUG REPORT" nicht umbrechen - gleiche Knopfhoehe */
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-dim);
    transition: color 0.18s ease;
}
.char-footer-btn.has-img:hover {
    background: transparent;
    border: none;
    color: var(--rose);
}
.char-footer-btn.has-img:hover img {
    filter: saturate(1.15) brightness(1.08);
    transform: scale(1.06);
}
.char-footer-btn.has-img:hover .char-footer-label {
    color: var(--rose);
}

/* Nude view sprite grid */
.nude-view {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 4px 12px;
    /* Fill the column like .paper-doll-box does for the dressed view — without
       this the nude clip sized to its own width:100% box and read as
       "compressed in height" next to the height-filling paper doll
       (foundby:Anne-Sophie 0.2.8). */
    flex: 1 1 auto;
    min-height: 300px;
}
/* Animated nude clip (transparent VP9 cutout, 600x920 portrait) fills the
   panel height and crops its transparent side margins, mirroring
   .paper-doll-layer's object-fit:cover so both views frame the figure
   identically. The JS sets inline width + border-radius only, so height /
   object-fit / flex come from here. */
.nude-view video {
    /* Width-anchored so the figure scales WITH the UI scale, not against it.
       Previously flex:1 1 auto + height:100% pinned the clip to the column
       HEIGHT, which shrinks under CSS `zoom` as the fixed-px toggle chrome
       grows — so at higher UI scale the figure got SMALLER (inverse scaling,
       foundby:Scoot 0.2.8.4). width:100% + height:auto sizes the clip from the
       column WIDTH (which scales correctly with zoom); max-height:100% caps it
       so a short window never overflows the column. */
    flex: 0 0 auto;
    width: 100%;
    height: auto;
    max-height: 100%;
    /* 2026-06-15 (foundby:Scoot): contain, not cover, so the figure's legs are
       never cropped off the bottom — mirrors .paper-doll-layer. Thin side
       margins when the column is wider than the clip's 600x920 portrait. */
    object-fit: contain;
    object-position: center top;
}
/* NUDE_STILLS.md: paper-doll nude base still. Reuses .paper-doll-layer
   (object-fit:contain, absolute inset:0) so the static nude view frames the
   figure identically to the dressed doll — and fills the column height like
   .nude-view video does (override .paper-doll's height:100%, which doesn't
   resolve as a flex child). */
.nude-view .nude-doll-still {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    height: auto;
}
/* Cross-fade between clothed/nude view (NSFW reveal polish) */
.char-fade-out {
    opacity: 0 !important;
    transition: opacity 0.2s ease-out;
    pointer-events: none;
}
.char-fade-in {
    animation: char-reveal-in 0.45s ease-out;
}
@keyframes char-reveal-in {
    from { opacity: 0; transform: translateY(4px); filter: blur(2px); }
    to   { opacity: 1; transform: translateY(0);   filter: blur(0);   }
}
/* Breathing animation on upper body slot */
.nude-slot:first-child img,
.char-slot:first-child .char-slot-image img {
    animation: breathe 4s ease-in-out infinite;
}
@keyframes breathe {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.008) translateY(-0.5px); }
}

.nude-animate-btn {
    margin-top: 6px; padding: 4px 10px; border-radius: 6px;
    background: rgba(228, 120, 184, 0.1); border: 1px solid rgba(228, 120, 184, 0.3);
    color: var(--fem); font-size: 10px; font-weight: 600; cursor: pointer;
    align-self: center; transition: background 0.2s;
}
.nude-animate-btn:hover { background: rgba(228, 120, 184, 0.25); }
.nude-slot {
    width: 100%;
    min-height: 80px;
    overflow: hidden;
}

/* Status icon additions — HRT mood swings */
.status-hrt { background: rgba(232, 140, 184, 0.15); color: #e88cb8; border: 1px solid rgba(232, 140, 184, 0.3); }
/* Compound buff — chastity + feminine */
.buff-icon { background: rgba(228, 120, 184, 0.15); color: var(--fem); border: 1px solid rgba(228, 120, 184, 0.3); }

/* ============================================

/* Status-Badges ueber dem Paper-Doll (Extensions-Laufzeit etc.) */
.doll-status-row {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
    padding: 2px 12px 0;
}
.doll-status-row.hidden { display: none; }
.doll-status-badge {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.4px;
    color: var(--rose, #e91e63);
    background: rgba(233, 30, 99, 0.12);
    border: 1px solid rgba(233, 30, 99, 0.35);
    border-radius: 10px;
    padding: 2px 10px;
}

/* (0.2.9: .char-panel-head — the name + Nude·Clothed tab header — was removed.
   The right panel is now a headless single image stage.) */
/* ============================================
   11. STORY CONTENT
   ============================================ */
.story-scroll {
    flex-grow: 1;
    overflow-y: auto;
    padding: 16px 20px;
    scroll-behavior: smooth;
    -webkit-overflow-scrolling: touch;
    position: relative;
    box-shadow: inset 0 8px 16px rgba(0,0,0,0.15);
}
.story-scroll::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    opacity: 0.4;
    background: radial-gradient(circle at 20% 30%, rgba(196,112,224,0.03) 0%, transparent 40%),
                radial-gradient(circle at 80% 70%, rgba(228,140,184,0.02) 0%, transparent 35%);
    animation: ambient-drift 25s ease-in-out infinite alternate;
}
@keyframes ambient-drift {
    from { transform: translate(0, 0) scale(1); }
    to { transform: translate(10px, -10px) scale(1.05); }
}
.story-scroll > * {
    position: relative;
    z-index: 1;
}

.story-content > * {
    margin-bottom: 14px;
    animation: text-fade-in 0.4s ease both;
}

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

.story-content > *:nth-child(1) { animation-delay: 0s; }
.story-content > *:nth-child(2) { animation-delay: 0.05s; }
.story-content > *:nth-child(3) { animation-delay: 0.1s; }
.story-content > *:nth-child(4) { animation-delay: 0.15s; }
.story-content > *:nth-child(5) { animation-delay: 0.2s; }
.story-content > *:nth-child(n+6) { animation-delay: 0.25s; }

/* Scroll-append: section separator between old and new content */
.story-section-separator {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 24px 6%;
    animation: separator-in 0.5s ease-out both;
}
.story-section-separator::before,
.story-section-separator::after {
    content: '';
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg,
        transparent 0%,
        var(--orchid) 50%,
        var(--rose) 50%,
        var(--orchid) 70%,
        transparent 100%);
    opacity: 0.3;
}
.story-section-separator::after {
    background: linear-gradient(270deg,
        transparent 0%,
        var(--orchid) 50%,
        var(--rose) 50%,
        var(--orchid) 70%,
        transparent 100%);
    opacity: 0.3;
}
.story-section-label {
    font-family: 'Crimson Pro', serif;
    font-style: italic;
    font-size: 12px;
    color: var(--text-faint);
    white-space: nowrap;
    letter-spacing: 1px;
    text-transform: lowercase;
}
@keyframes separator-in {
    from { opacity: 0; transform: scaleX(0.3); }
    to { opacity: 1; transform: scaleX(1); }
}

/* Scroll-append: new section content slides in */
.story-section-new > .info-card,
.story-section-new > .dialogue-card,
.story-section-new > .story-image-wrapper {
    animation: section-card-in 0.4s ease-out both;
}
@keyframes section-card-in {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}

/* Scroll-append: collapsed old content (DOM management) */
.story-collapsed {
    display: none;
}
.story-collapsed-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px 16px;
    margin: 8px auto;
    font-family: 'DM Sans', sans-serif;
    font-size: 11px;
    color: var(--text-faint);
    background: rgba(20, 15, 30, 0.6);
    border: 1px solid var(--border);
    border-radius: 12px;
    cursor: pointer;
    transition: color 0.2s, border-color 0.2s;
}
.story-collapsed-toggle:hover {
    color: var(--text-dim);
    border-color: var(--orchid);
}
.story-collapsed.expanded {
    display: block;
    opacity: 0.6;
}

/* Info text — narrator prose. Designed to read like a book column: capped at
   72ch (I1), ornament-lead (I4), with drop-cap on scene openers (I2). */
.info-card {
    background: rgba(16, 12, 24, 0.85);
    border-radius: 8px;
    padding: 14px 18px 14px 32px;  /* extra left-pad reserves space for ornament */
    position: relative;
    box-shadow: -4px 0 16px rgba(196, 112, 224, 0.06);
    animation: cardSlideIn 0.3s ease-out both;
    opacity: 0.7;
    transition: opacity 0.4s ease;
    /* I1: reading-friendly column width, centred in the story panel */
    max-width: min(72ch, 88%);
    margin: 10px auto;
}
.info-card.card-active { opacity: 1; }

/* Long-text hint (Pablito 2026-05-05): cards over 1500 chars get a faint
   "Space / scroll to skip" badge in the bottom-right corner so the player
   knows they can speed past the wall-of-text instead of waiting through
   the typing animation. Only shown while the card is the active beat. */
.info-card.long-card.card-active::after {
    content: '⏭ Space / scroll to skip';
    position: absolute;
    right: 10px;
    bottom: 6px;
    font-size: 10px;
    font-family: 'Inter', system-ui, sans-serif;
    letter-spacing: 0.4px;
    color: rgba(228, 200, 240, 0.55);
    pointer-events: none;
    opacity: 0;
    animation: longCardHintFadeIn 0.6s ease-out 1.2s forwards;
}
@keyframes longCardHintFadeIn {
    from { opacity: 0; transform: translateY(2px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* I4: Narrator ornament (fleuron) — AI-generated 4-petal rose (Imagen 4.0,
   tools/gen_fleuron.py variant B). Signals "this is the narrator speaking"
   with a literary symbol. Low opacity so it doesn't compete with the prose. */
.info-card::before {
    content: '';
    position: absolute;
    top: 12px;
    left: 6px;
    width: 22px;
    height: 22px;
    background: url('../assets/images/UI/narrator_ornament.png') center/contain no-repeat;
    opacity: 0.55;
    /* Shift the pink ornament towards warm gold so it reads as a
       typographic punctuation mark, not as an interactive pink UI pill. */
    filter: hue-rotate(-80deg) saturate(0.65) brightness(1.15);
    pointer-events: none;
    transition: opacity 0.4s ease;
}
.info-card.card-active::before { opacity: 0.85; }

/* I2: Drop-cap on the first info-card of a scene — after a location header
   or a section separator. Reads like a chapter opening. */
.story-location-header + .info-card .info-text::first-letter,
.story-section-separator + .info-card .info-text::first-letter {
    font-family: 'Crimson Pro', Georgia, serif;
    font-size: 2.8em;
    font-weight: 600;
    font-style: normal;
    float: left;
    line-height: 0.88;
    padding: 4px 10px 0 0;
    margin-top: 2px;
    color: var(--rose);
    text-shadow: 0 2px 8px rgba(228, 120, 184, 0.22);
}

/* Separator line after images before next DIALOGUE card (info-cards now use
   the voice-over treatment in I5 — no separator needed there). */
.story-image-wrapper + .dialogue-card::before {
    content: '';
    display: block;
    width: 60%;
    height: 1px;
    background: rgba(140, 100, 180, 0.15);
    margin: 0 auto 12px;
}

/* I5: Info-card directly after an image = voice-over, not a card.
   Drops all card chrome (background, ornament, padding-left) so the
   narrator's line reads as a bridge between image and next beat. */
.story-image-wrapper + .info-card {
    background: transparent;
    box-shadow: none;
    padding: 6px 18px 6px 14px;
    margin-top: -2px;
    max-width: min(68ch, 82%);
}
.story-image-wrapper + .info-card::before {
    display: none;
}
.story-image-wrapper + .info-card .info-text {
    /* A little lighter + letter-spaced for the voice-over feel */
    opacity: 0.92;
    letter-spacing: 0.3px;
}

.story-text,
.info-text {
    font-family: 'Crimson Pro', Georgia, serif;
    font-size: var(--font-size-base, 16px);
    line-height: 1.75;
    letter-spacing: 0.2px;
    color: var(--text-body);
    /* Audit D06+D27 (CR-1): drop italic on narrator prose (reading-loop fatigue
       at 16px italic-serif), keep upright. Dialogue card stays upright too;
       speaker styling differentiates without italic. Shadow softened from
       2-layer halo to single readable drop. */
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='5' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.015'/%3E%3C/svg%3E");
    background-size: 256px;
}

.story-text {
    border-left: 2px solid rgba(196, 112, 224, 0.3);
    padding-left: 14px;
    padding-top: 2px;
    padding-bottom: 2px;
    transition: border-left-color 0.4s ease;
}

/* ── Per-location accent color on story text border ── */
.story-area-bar .story-text { border-left-color: rgba(200, 150, 60, 0.4); }
.story-area-park .story-text { border-left-color: rgba(80, 180, 100, 0.4); }
.story-area-club .story-text { border-left-color: rgba(220, 80, 140, 0.4); }
.story-area-mall .story-text { border-left-color: rgba(80, 180, 200, 0.4); }
.story-area-beach .story-text { border-left-color: rgba(100, 180, 220, 0.4); }
.story-area-gym .story-text { border-left-color: rgba(100, 140, 200, 0.4); }
.story-area-clinic .story-text { border-left-color: rgba(80, 200, 160, 0.4); }
.story-area-salon .story-text { border-left-color: rgba(200, 140, 180, 0.4); }
.story-area-spa .story-text { border-left-color: rgba(180, 120, 160, 0.4); }
.story-area-office .story-text { border-left-color: rgba(120, 130, 160, 0.4); }

/* Dialogue — chat-bubble style: portrait + speech bubble with tail */
.dialogue-card {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    margin: 10px 0;
    position: relative;
    animation: cardSlideIn 0.3s ease-out both;
    opacity: 0.7;
    transition: opacity 0.4s ease;
    /* The card itself has NO background — the .dialogue-body is the bubble */
    background: transparent;
    border: none;
    padding: 0;
}
.dialogue-card.card-active { opacity: 1; }
@keyframes cardSlideIn {
    from { transform: translateY(10px); opacity: 0; }
    to { transform: translateY(0); opacity: 1; }
}

/* The speech bubble itself lives on .dialogue-body */
.dialogue-card .dialogue-body {
    position: relative;
    padding: 10px 16px 11px 16px;
    background: linear-gradient(135deg, rgba(26, 18, 38, 0.92), rgba(18, 14, 28, 0.88));
    border: 1px solid rgba(60, 44, 82, 0.45);
    border-radius: 14px;
    border-top-left-radius: 4px; /* tail side, squared corner */
    box-shadow:
        0 4px 14px rgba(0, 0, 0, 0.4),
        0 0 0 1px rgba(196, 112, 224, 0.04) inset;
    /* Chat-style max-width: 68ch for readable line length, capped at 82%
       of the card width so portrait + tail + gap stay proportional. Info-cards
       (narrator text) are untouched and keep the full panel width, which
       creates a clear visual split between "narration" and "dialogue".
       min-width gives short lines ("Yes.") visual body so they don't collapse
       into tiny nubs — keeps the rhythm calm across bubble sizes. */
    max-width: min(68ch, 82%);
    min-width: min(240px, 82%);
    flex: 0 1 auto;
}
/* Bubble tail — small triangle pointing at the portrait */
.dialogue-card .dialogue-body::before {
    content: '';
    position: absolute;
    left: -7px;
    top: 14px;
    width: 0;
    height: 0;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
    border-right: 8px solid rgba(60, 44, 82, 0.45);
    filter: drop-shadow(-1px 0 0 rgba(26, 18, 38, 0.92));
}
/* Player dialogue — tinted bubble + strong border, tail stays on the left
   like every other speaker so reading flow is uninterrupted. */
.dialogue-card[data-speaker="player"] .dialogue-body {
    background: linear-gradient(135deg, rgba(24, 32, 58, 0.92), rgba(16, 22, 44, 0.88));
    border-color: rgba(91, 141, 217, 0.45);
    border-left: 3px solid #5b8dd9;
}
.dialogue-card[data-speaker="player"] .dialogue-body::before {
    border-right-color: rgba(91, 141, 217, 0.45);
}
/* Per-speaker tail colour (matches existing border-left accent colours) */
.dialogue-card[data-speaker="master"] .dialogue-body { border-color: rgba(155, 89, 182, 0.4); }
.dialogue-card[data-speaker="master"] .dialogue-body::before { border-right-color: rgba(155, 89, 182, 0.4); }
.dialogue-card[data-speaker="girlfriend"] .dialogue-body { border-color: rgba(232, 140, 184, 0.4); }
.dialogue-card[data-speaker="girlfriend"] .dialogue-body::before { border-right-color: rgba(232, 140, 184, 0.4); }
.dialogue-card[data-speaker="bully"] .dialogue-body { border-color: rgba(224, 80, 80, 0.4); }
.dialogue-card[data-speaker="bully"] .dialogue-body::before { border-right-color: rgba(224, 80, 80, 0.4); }
.dialogue-card[data-speaker="sugardaddy"] .dialogue-body { border-color: rgba(232, 200, 96, 0.4); }
.dialogue-card[data-speaker="sugardaddy"] .dialogue-body::before { border-right-color: rgba(232, 200, 96, 0.4); }
.dialogue-card[data-speaker="dominic"] .dialogue-body { border-color: rgba(196, 144, 96, 0.4); }
.dialogue-card[data-speaker="dominic"] .dialogue-body::before { border-right-color: rgba(196, 144, 96, 0.4); }

/* Consecutive same-speaker bubbles: hide tail + portrait (compact threading) */
.dialogue-card.same-speaker { margin-top: -2px; }
.dialogue-card.same-speaker .dialogue-portrait { visibility: hidden; }
.dialogue-card.same-speaker .dialogue-body::before { display: none; }
.dialogue-card.same-speaker .dialogue-body { border-top-left-radius: 14px; }
.dialogue-card.same-speaker .dialogue-name { display: none; }

/* Speaker accent colors on dialogue cards */
.dialogue-card[data-speaker="master"] { border-left-color: #9b59b6; }
.dialogue-card[data-speaker="girlfriend"] { border-left-color: #e88cb8; }
.dialogue-card[data-speaker="player"] { border-left-color: #5b8dd9; }
.dialogue-card[data-speaker="bully"] { border-left-color: #e05050; }
.dialogue-card[data-speaker="sugardaddy"] { border-left-color: #e8c860; }
.dialogue-card[data-speaker="dominic"] { border-left-color: #c49060; }
.dialogue-card[data-speaker="camille"] { border-left-color: #b0a0c0; }
.dialogue-card[data-speaker="patrick"] { border-left-color: #6080d0; }
.dialogue-card[data-speaker="stranger"] { border-left-color: #808080; }

/* Player dialogue — left-aligned like everyone else (narrative flow > chat metaphor).
   Differentiated by strong blue border + bubble tint + "YOU" label colour. */
.dialogue-card[data-speaker="player"] .dialogue-name {
    color: #7ba4e0;
    letter-spacing: 1.8px;
}

.dialogue-portrait {
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: var(--bg-panel);
    border: 2px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    overflow: hidden;
    box-shadow: 0 0 10px rgba(196, 112, 224, 0.15);
}
/* Portrait ring colors matching speaker */
.dialogue-card[data-speaker="master"] .dialogue-portrait { border-color: #9b59b6; }
.dialogue-card[data-speaker="girlfriend"] .dialogue-portrait { border-color: #e88cb8; }
.dialogue-card[data-speaker="player"] .dialogue-portrait { border-color: #5b8dd9; }
.dialogue-card[data-speaker="bully"] .dialogue-portrait { border-color: #e05050; }
.dialogue-card[data-speaker="sugardaddy"] .dialogue-portrait { border-color: #e8c860; }

.dialogue-portrait img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: opacity 0.4s ease;
}
/* Crossfade on portrait src change (triggered by JS adding .portrait-swap) */
.dialogue-portrait img.portrait-swap {
    animation: portrait-crossfade 0.5s ease;
}
@keyframes portrait-crossfade {
    0% { opacity: 0; transform: scale(0.92); }
    100% { opacity: 1; transform: scale(1); }
}
.dialogue-portrait-letter {
    font-size: 18px;
    font-weight: 600;
    color: var(--rose);
}

.dialogue-body { flex: 1; min-width: 0; }

.dialogue-name {
    font-family: 'DM Sans', sans-serif;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    color: var(--rose);
    margin-bottom: 4px;
    opacity: 0.85;
}

.dialogue-text {
    font-family: 'Crimson Pro', Georgia, serif;
    font-size: var(--font-size-base, 15px);
    line-height: 1.7;
    color: var(--text-body);
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
/* Dialogue ships its quotes as part of the Ink text — adding CSS
   pseudo-element quotes produced double-wrapped strings like ""He's fine."".
   Keep the rules empty in case we ever want a typographic outer-quote
   treatment again, but without rendering any extra characters. */

/* Story images */
/* Location header in story area */
.story-location-header {
    padding: 6px 12px;
    margin-bottom: 8px;
    border-left: 3px solid var(--accent);
    opacity: 0.7;
}
.story-location-name {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
}

.story-image-wrapper {
    text-align: center;
    margin: 14px 0;
    position: relative;
    isolation: isolate;
    transition: all 0.4s ease;
}

/* ─── Shot Vocabulary (#11a) ──────────────────────────────────
   Shot tags from Ink (#shot:wide|close|hero|detail) reframe the
   story image without changing the asset. wide is default; close
   tightens to a narrower band; hero takes more vertical room and
   adds letterboxing; detail is small and inset. */
.story-image-wrapper.shot-wide {
    /* default — full panel width, normal aspect */
}
.story-image-wrapper.shot-close {
    max-width: 65%;
    margin: 18px auto;
}
.story-image-wrapper.shot-close .story-image {
    border-radius: 8px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6), 0 0 60px rgba(196, 112, 224, 0.08);
}
.story-image-wrapper.shot-hero {
    /* Audit D49: was margin: 22px -16px with max-width: calc(100% + 32px).
       That -16px each side bled the hero image INTO the panel-collapse
       gutter on desktop, clipping the collapse buttons. Pull the bleed
       back so the hero stays inside the story panel. The cinematic feel
       still comes from the gradient + shadow, not from edge-to-edge. */
    margin: 22px 0;
    max-width: 100%;
    padding: 14px 0;
    background: linear-gradient(180deg, transparent, rgba(0,0,0,0.35) 12%, rgba(0,0,0,0.35) 88%, transparent);
    border-radius: 8px;
}
.story-image-wrapper.shot-hero .story-image {
    width: 100%;
    max-height: 70vh;
    /* contain (not cover) — never crop a hero image. The cinematic feel
       comes from the dark gradient backdrop + inset shadow, not from
       filling the frame edge-to-edge. Needed because in Scene Mode the
       side panels collapse and the story panel gets wide enough that
       cover would chop the top/bottom off square character shots. */
    object-fit: contain;
    border-radius: 0;
    box-shadow: 0 12px 48px rgba(0, 0, 0, 0.7);
}
.story-image-wrapper.shot-hero::after {
    box-shadow: inset 0 0 80px rgba(0,0,0,0.55);
}
.story-image-wrapper.shot-detail {
    max-width: 38%;
    margin: 16px auto 18px auto;
}
.story-image-wrapper.shot-detail .story-image {
    border-radius: 6px;
    box-shadow: 0 4px 18px rgba(0, 0, 0, 0.5);
}
.video-play-btn {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.6);
    border: 2px solid rgba(255, 255, 255, 0.5);
    color: #fff;
    font-size: 24px;
    cursor: pointer;
    z-index: 5;
    transition: background 0.2s;
}
.video-play-btn:hover { background: rgba(155, 89, 182, 0.7); }

/* Video controls overlay (Pause + Skip) */
.video-controls {
    position: absolute;
    bottom: 12px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 6px;
    z-index: 5;
    opacity: 0;
    transition: opacity 0.2s ease;
}
.story-image-wrapper:hover .video-controls { opacity: 1; }
/* Always visible on touch devices */
@media (hover: none) { .video-controls { opacity: 0.8; } }

.video-ctrl-btn {
    background: rgba(0, 0, 0, 0.55);
    border: 1px solid rgba(255, 255, 255, 0.15);
    color: var(--text);
    padding: 5px 14px;
    border-radius: 8px;
    font-size: 12px;
    cursor: pointer;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    transition: background 0.15s;
}
.video-ctrl-btn:hover { background: rgba(155, 89, 182, 0.4); }

.story-image-wrapper::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 4px;
    /* Cinematic vignette: corners darkened + subtle radial */
    box-shadow: inset 0 0 60px rgba(0,0,0,0.55), inset 0 0 120px rgba(0,0,0,0.25);
    background:
        radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,0.18) 100%);
    pointer-events: none;
    z-index: 1;
    will-change: transform;
    mix-blend-mode: multiply;
}
/* Hero shots get a stronger vignette to feel letterboxed */
.story-image-wrapper.shot-hero::after {
    box-shadow: inset 0 0 100px rgba(0,0,0,0.7), inset 0 0 200px rgba(0,0,0,0.35);
    background:
        radial-gradient(ellipse at center, transparent 45%, rgba(0,0,0,0.3) 100%);
}

/* ─── Cinema Mode (body.cinema-hero) ──────────────────────────────
   Active while a #shot:hero image is the current featured asset AND
   scene-mode is enabled. Clears on any subsequent non-hero shot or on
   STORY_CLEAR (location change). Drives:
   - backdrop dim under center column for letterbox feel
   - hero wrapper expands to the full story panel width
   - slight scale-in + subtle Ken-Burns on the hero image itself
   - hides the stats-strip to let the shot breathe (panels already
     collapsed by scene-mode) */
body.cinema-hero:not(.scene-mode-disabled) .story-image-wrapper.shot-hero {
    margin: 28px -32px;
    max-width: calc(100% + 64px);
    padding: 20px 0;
    background: linear-gradient(180deg,
        rgba(0,0,0,0.65) 0%,
        rgba(0,0,0,0.45) 10%,
        rgba(0,0,0,0.45) 90%,
        rgba(0,0,0,0.65) 100%);
    animation: cinema-letterbox-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
}
body.cinema-hero:not(.scene-mode-disabled) .story-image-wrapper.shot-hero .story-image {
    /* D6: cap hero height so the narration card below always peeks above the
       fold (the text sliver is the "scroll down" signal). Story-First first-
       timers previously got a full-bleed 82vh image with the text pushed
       entirely below the fold and auto-scroll off by default. */
    max-height: min(70vh, calc(100vh - 220px));
    animation: cinema-hero-reveal 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
    box-shadow:
        0 20px 80px rgba(0, 0, 0, 0.85),
        0 0 120px rgba(196, 112, 224, 0.12);
}
body.cinema-hero:not(.scene-mode-disabled) .story-image-wrapper.shot-hero::after {
    box-shadow: inset 0 0 160px rgba(0,0,0,0.85), inset 0 0 300px rgba(0,0,0,0.45);
    background:
        radial-gradient(ellipse at center, transparent 40%, rgba(0,0,0,0.45) 100%);
}
/* Collapse buttons must float above the expanded hero image (which has
   negative side margins that would otherwise occlude them). Let the user
   always pop a panel open mid-hero-shot — agency beats immersion. */
body.cinema-hero:not(.scene-mode-disabled) .left-column .btn-collapse-left,
body.cinema-hero:not(.scene-mode-disabled) .right-column .btn-collapse-right {
    z-index: 20;
    opacity: 0.85;
    transition: opacity 0.25s ease, background 0.2s ease;
}
body.cinema-hero:not(.scene-mode-disabled) .left-column .btn-collapse-left:hover,
body.cinema-hero:not(.scene-mode-disabled) .right-column .btn-collapse-right:hover {
    opacity: 1;
}

/* ─── Option A: Soft-Exit from Cinema when a panel is manually expanded ──
   If the user clicks open the stats/inventory panel during a hero shot,
   drop the cinematic bleed-out (-32px side margins, 82vh cap) back to the
   plain shot-hero styling so the panel doesn't slice through the frame.
   The body.cinema-hero class stays (vignette + breadcrumb dim remain) so
   re-closing the panel snaps right back into full cinema. */
body.cinema-hero:has(#left-column.user-expanded) .story-image-wrapper.shot-hero,
body.cinema-hero:has(#right-column.user-expanded) .story-image-wrapper.shot-hero {
    margin: 22px -16px;
    max-width: calc(100% + 32px);
    padding: 14px 0;
    /* Restore the default shot-hero gradient (not the heavier cinema one) */
    background: linear-gradient(180deg, transparent, rgba(0,0,0,0.35) 12%, rgba(0,0,0,0.35) 88%, transparent);
    animation: none;
}
body.cinema-hero:has(#left-column.user-expanded) .story-image-wrapper.shot-hero .story-image,
body.cinema-hero:has(#right-column.user-expanded) .story-image-wrapper.shot-hero .story-image {
    max-height: 70vh;
    animation: none;
    box-shadow: 0 12px 48px rgba(0, 0, 0, 0.7);
}
body.cinema-hero:has(#left-column.user-expanded) .story-image-wrapper.shot-hero::after,
body.cinema-hero:has(#right-column.user-expanded) .story-image-wrapper.shot-hero::after {
    box-shadow: inset 0 0 100px rgba(0,0,0,0.7), inset 0 0 200px rgba(0,0,0,0.35);
}
/* Gentle motion on the image itself — subtle pull-in, not distracting */
@keyframes cinema-hero-reveal {
    0%   { opacity: 0; transform: scale(0.97); filter: blur(6px); }
    100% { opacity: 1; transform: scale(1);    filter: blur(0); }
}
@keyframes cinema-letterbox-in {
    0%   { opacity: 0; }
    100% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    body.cinema-hero:not(.scene-mode-disabled) .story-image-wrapper.shot-hero,
    body.cinema-hero:not(.scene-mode-disabled) .story-image-wrapper.shot-hero .story-image {
        animation: none;
    }
}
/* Detail shots: less vignette — small images already feel framed */
.story-image-wrapper.shot-detail::after {
    box-shadow: inset 0 0 30px rgba(0,0,0,0.4);
    background: none;
}

/* ─── Time-of-Day Color Grading ──────────────────────────────────
   Uses the existing body.time-* classes set by stats._updateTimeSlot:
     .time-morning   (0) — cool bluish dawn, slightly desaturated
     .time-afternoon (1) — neutral, full saturation
     .time-evening   (2) — warm golden hour
     .time-night     (3) — cooler + darker, heavy contrast
   The filter stacks on top of .story-image's base brightness(.95) saturate(.92).
   Numbers are intentionally gentle — this is grading, not a filter app. */
body.time-morning .story-image {
    filter: brightness(0.92) saturate(0.85) hue-rotate(-4deg);
}
body.time-afternoon .story-image {
    filter: brightness(0.98) saturate(0.95);
}
body.time-evening .story-image {
    filter: brightness(0.94) saturate(1.05) sepia(0.08) hue-rotate(-3deg);
}
body.time-night .story-image {
    filter: brightness(0.82) saturate(0.88) contrast(1.06) hue-rotate(4deg);
}
body.time-morning .story-video,
body.time-morning .story-video-frame   { filter: brightness(0.92) saturate(0.85); }
body.time-afternoon .story-video,
body.time-afternoon .story-video-frame { filter: brightness(0.98) saturate(0.95); }
body.time-evening .story-video,
body.time-evening .story-video-frame   { filter: brightness(0.94) saturate(1.05) sepia(0.08); }
body.time-night .story-video,
body.time-night .story-video-frame     { filter: brightness(0.82) saturate(0.88) contrast(1.06); }

@media (prefers-reduced-motion: reduce) {
    body.time-morning .story-image,
    body.time-evening .story-image,
    body.time-night .story-image {
        filter: brightness(0.95) saturate(0.92);
    }
}
.story-image-wrapper.loading {
    min-height: 200px;
    border-radius: 4px;
}
.story-image-placeholder {
    width: 100%;
    border-radius: 4px;
    overflow: hidden;
}
.story-image-placeholder svg {
    width: 100%;
    height: auto;
    display: block;
}
@keyframes shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

.story-image-divider {
    height: 1px;
    background: rgb(50, 42, 72);
    opacity: 0.5;
    margin: 0 40px;
}

.story-image {
    width: 100%;
    max-height: 700px;
    object-fit: contain;
    border-radius: 6px;
    cursor: pointer;
    box-shadow:
        0 4px 20px rgba(0, 0, 0, 0.5),
        0 0 40px rgba(100, 40, 80, 0.08);
    animation: image-reveal 0.6s ease both;
    /* Subtle tint to integrate AI images with dark UI palette */
    filter: brightness(0.95) saturate(0.92);
}

@keyframes image-reveal {
    from { opacity: 0; transform: scale(0.96); filter: blur(4px); }
    to { opacity: 1; transform: scale(1); filter: blur(0); }
}

/* Save load blur-in effect */
.game-load-reveal {
    animation: load-reveal 0.6s ease both;
}
@keyframes load-reveal {
    from { opacity: 0.3; filter: blur(6px); }
    to { opacity: 1; filter: blur(0); }
}

/* Story videos */
.story-video {
    width: 100%;
    max-height: 700px;
    border-radius: 4px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
    filter: brightness(0.95) saturate(0.92);
}
/* Isolated playback frame (BUG_PATTERNS § 106): hosts a silent story clip in
   its own throwaway document so releasing it frees Chromium's decoded-frame
   pool. Visually a drop-in for .story-video — the inner <video> is
   width/height 100% + object-fit contain; JS sets the real aspect-ratio on
   loadedmetadata. */
.story-video-frame {
    width: 100%;
    max-height: 700px;
    aspect-ratio: 1 / 1;
    border: 0;
    display: block;
    border-radius: 4px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
    filter: brightness(0.95) saturate(0.92);
}
/* Generic video fade-in (char panel, gallery modal, expanded video).
   Add `.video-fade-in` to any <video>; toggle `.is-loaded` on `loadeddata`. */
video.video-fade-in,
iframe.video-fade-in {
    opacity: 0;
    background: var(--bg-deep);
    transition: opacity 0.4s ease-out;
}
video.video-fade-in.is-loaded,
iframe.video-fade-in.is-loaded { opacity: 1; }
/* Video loading placeholder — blurred poster frame */
.video-placeholder-blur {
    width: 100%;
    max-height: 700px;
    border-radius: 4px;
    object-fit: contain;
    filter: blur(12px) brightness(0.7) saturate(0.5);
    transform: scale(1.05); /* hide blur edge artifacts */
    transition: opacity 0.4s ease;
}
.story-image-wrapper.video-loading {
    overflow: hidden;
}
.story-image-wrapper.video-loading .story-video,
.story-image-wrapper.video-loading .story-video-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0;
    transition: opacity 0.5s ease;
}
.story-image-wrapper.video-loaded .story-video,
.story-image-wrapper.video-loaded .story-video-frame {
    opacity: 1;
    position: relative;
}
.story-image-wrapper.video-loaded .video-placeholder-blur {
    display: none;
}

/* Typing indicator */
.typing-indicator {
    display: flex;
    gap: 4px;
    padding: 8px 16px;
    align-items: center;
}
.typing-indicator.hidden { display: none; }
.typing-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--text-faint);
    animation: typing-pulse 1s ease-in-out infinite;
}
.typing-dot:nth-child(2) { animation-delay: 0.15s; }
.typing-dot:nth-child(3) { animation-delay: 0.3s; }

@keyframes typing-pulse {
    0%, 100% { opacity: 0.3; transform: scale(0.8); }
    50% { opacity: 1; transform: scale(1); }
}

/* Scroll indicator */
.scroll-indicator {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    color: var(--text-faint);
    animation: scroll-bounce 2s ease-in-out infinite;
    z-index: 5;
    padding: 4px;
    background: rgba(8, 6, 12, 0.6);
    border-radius: 50%;
}
.scroll-indicator.hidden { display: none; }

@keyframes scroll-bounce {
    0%, 100% { transform: translateX(-50%) translateY(0); }
    50% { transform: translateX(-50%) translateY(4px); }
}

/* Stream header */
.stream-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 16px;
    background: rgba(200, 40, 60, 0.1);
    border-bottom: 1px solid rgba(200, 40, 60, 0.2);
    flex-shrink: 0;
}
.stream-header.hidden { display: none; }
.stream-status { display: flex; align-items: center; gap: 6px; }
.stream-live-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #e04040;
    animation: pulse-dot 1.5s ease-in-out infinite;
}
.stream-live-text {
    font-size: 11px;
    font-weight: 700;
    color: #e04040;
    letter-spacing: 1px;
}
.stream-stats {
    display: flex;
    gap: 16px;
    font-family: 'DM Mono', monospace;
    font-size: 11px;
    color: var(--text-dim);
}


/* ============================================
   12. CHOICES PANEL
   ============================================ */
.choices-panel {
    flex-shrink: 0;
    max-height: 40vh;
    overflow-y: auto;
    background: var(--bg-deep);
    padding: 8px 8px 6px;
    -webkit-overflow-scrolling: touch;
    position: relative;
}

/* Scroll-append mode: choices always inline in story, never in fixed panel */
.choices-panel {
    display: none !important;
}

.choices-panel::before {
    content: '';
    position: absolute;
    top: 0;
    left: 8%;
    right: 8%;
    height: 2px;
    background: linear-gradient(90deg,
        transparent 5%,
        var(--orchid) 25%,
        var(--rose) 50%,
        var(--orchid) 75%,
        transparent 95%);
    background-size: 200% 100%;
    opacity: 0.7;
    animation: gradient-flow 4s linear infinite, separator-pulse 4s ease-in-out infinite;
}

/* "Click to continue" indicator — replaces single Continue buttons */
.continue-indicator {
    text-align: center;
    padding: 16px 0 12px;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
}
.continue-btn {
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0.6px;
    padding: 14px 48px;
    min-height: 48px;
    min-width: 220px;
    background: linear-gradient(180deg, rgba(228, 140, 184, 0.28), rgba(196, 112, 224, 0.22));
    border: 1px solid rgba(228, 140, 184, 0.55);
    color: rgba(248, 228, 240, 0.95);
    border-radius: 10px;
    box-shadow: 0 6px 18px rgba(196, 112, 224, 0.18), 0 0 0 1px rgba(228, 140, 184, 0.08);
    opacity: 1;
    transition: background 0.2s, box-shadow 0.25s, transform 0.1s;
    /* UX-02: subtle glow-pulse so users see "this is the active CTA" not just
       "another button". Keeps the existing ▼ pulse for motion, adds a slow
       border-shimmer for ambient attention on long story beats. */
    animation: continue-glow 2.4s ease-in-out infinite;
}
@keyframes continue-glow {
    0%, 100% { box-shadow: 0 6px 18px rgba(196, 112, 224, 0.18), 0 0 0 1px rgba(228, 140, 184, 0.08); }
    50%      { box-shadow: 0 6px 22px rgba(196, 112, 224, 0.32), 0 0 0 1px rgba(228, 140, 184, 0.22); }
}
/* Mobile: full-width tap target */
body.mobile .continue-btn,
body.phone .continue-btn {
    min-width: 0;
    width: calc(100% - 24px);
    min-height: 56px;
    font-size: 16px;
}
.continue-btn:hover {
    background: linear-gradient(180deg, rgba(228, 140, 184, 0.42), rgba(196, 112, 224, 0.34));
    box-shadow: 0 8px 24px rgba(196, 112, 224, 0.28), 0 0 0 1px rgba(228, 140, 184, 0.2);
}
.continue-btn:active {
    transform: translateY(1px);
    box-shadow: 0 3px 10px rgba(196, 112, 224, 0.18);
}
.continue-pulse {
    display: inline-block;
    color: var(--text-faint);
    font-size: 12px;
    animation: continue-bob 2s ease-in-out infinite;
    margin-left: 6px;
    vertical-align: middle;
}
.continue-kbd-hint {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 6px;
    border-radius: 3px;
    background: rgba(0, 0, 0, 0.25);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.5px;
    color: var(--text-faint);
    vertical-align: middle;
}
body.mobile .continue-kbd-hint,
body.phone .continue-kbd-hint,
body.touch .continue-kbd-hint { display: none; }
@keyframes continue-bob {
    0%, 100% { transform: translateY(0); opacity: 0.3; }
    50% { transform: translateY(4px); opacity: 0.6; }
}

/* Inline choices (desktop): rendered inside story-content */
#choices-inline {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid rgba(46, 34, 66, 0.3);
}

.choices-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    padding: 0 2px;
}

/* Choice buttons.
   50% basis with flex-grow: 1 so every row holds exactly 2 buttons AND
   each button stretches to fill half the container. Earlier revisions
   mixed grow values and min-widths which produced uneven rows (thumb
   rows narrow, text rows wide). Now both thumb and text-only rows
   align to the same outer edge. */
.choice-btn {
    flex: 1 1 calc(50% - 3px);
    min-height: 46px;
    max-width: calc(50% - 3px);
    padding: 8px 10px;
    background: linear-gradient(145deg, rgba(28, 22, 48, 0.9), rgba(20, 16, 36, 0.95));
    border: 1px solid rgba(46, 34, 66, 0.6);
    border-radius: 8px;
    color: var(--text);
    font-family: 'DM Sans', sans-serif;
    font-size: 12.5px;
    font-weight: 500;
    text-align: center;
    white-space: normal;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    position: relative;
    overflow: hidden;
    transition: all 0.2s ease;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    /* Entrance animation handled by GSAP */
}

.choice-btn::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 7px;
    background: radial-gradient(ellipse at 50% 0%, rgba(196, 112, 224, 0.04), transparent 70%);
    pointer-events: none;
}

.choice-btn:hover {
    background: var(--bg-choice-hover);
    border-color: rgba(196, 112, 224, 0.3);
    box-shadow:
        0 4px 20px rgba(196, 112, 224, 0.1),
        0 0 40px rgba(228, 140, 184, 0.04),
        inset 0 0 20px rgba(228, 140, 184, 0.03);
    transform: translateY(-2px);
}

.choice-btn:active {
    background: #2a2040;
    border-color: var(--rose);
    transform: scale(0.97);
    box-shadow: 0 0 20px rgba(228, 140, 184, 0.15), inset 0 1px 8px rgba(228, 140, 184, 0.08);
}

/* Dramatic choice (full-width) */
.choice-btn.dramatic {
    flex-basis: 100%;
    background: linear-gradient(135deg, rgba(140, 50, 80, 0.2), rgba(100, 40, 140, 0.15));
    border-color: rgba(228, 140, 184, 0.3);
    box-shadow: 0 0 20px rgba(228, 140, 184, 0.08);
    font-size: 13.5px;
    font-weight: 600;
    min-height: 52px;
    animation: dramatic-pulse 3s ease-in-out infinite;
}
.choice-btn.dramatic::before {
    background: radial-gradient(ellipse at 50% 0%, rgba(228, 140, 184, 0.08), transparent 70%);
}
.choice-btn.dramatic:hover {
    border-color: var(--rose);
    box-shadow:
        0 0 40px rgba(232, 140, 184, 0.12),
        0 0 80px rgba(196, 112, 224, 0.06);
}

/* ── Choice urgency visual tinting ── */
.choice-btn.choice-auto-sleep { border-color: rgba(80, 60, 160, 0.4); background: linear-gradient(135deg, rgba(40, 30, 80, 0.3), var(--bg-choice)); }
.choice-btn.choice-exhaust { border-color: rgba(200, 140, 60, 0.4); background: linear-gradient(135deg, rgba(100, 60, 20, 0.2), var(--bg-choice)); }

/* Navigation choices (smaller, 2-col) */
.choice-btn.nav-choice {
    min-height: 36px;
    font-size: 11px;
    padding: 6px 8px;
    background: rgba(14, 11, 20, 0.6);
    border-color: rgba(46, 34, 66, 0.4);
}
.choice-btn.nav-choice:hover {
    background: rgba(40, 30, 60, 0.5);
}

/* Disabled choices — distinct from "interactive but pending"; player must
   instantly read this as "you can see why this exists, but not now". */
.choice-btn.disabled,
.choice-btn[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
    filter: grayscale(0.7);
    background: linear-gradient(145deg, rgba(22, 18, 34, 0.6), rgba(16, 13, 26, 0.7));
    border-color: rgba(60, 50, 80, 0.45);
    border-left: 2px dashed rgba(140, 120, 170, 0.5);
    /* Audit D22 fix: was `pointer-events: none` here which killed hover-
       tooltip + native `title` reach on touch. JS click-handler is only
       bound to enabled choices (choices.js:197) so allowing pointer-events
       cannot trigger the action — it just lets the disabled-reason +
       tooltip stay reachable. */
}
.choice-btn.disabled .choice-text { color: var(--text-dim); }
.choice-btn.disabled .choice-number { opacity: 0.5; }
.choice-btn.disabled:hover {
    background: linear-gradient(145deg, rgba(28, 22, 42, 0.65), rgba(20, 16, 30, 0.75));
    border-color: rgba(140, 120, 170, 0.55);
    border-left-color: rgba(196, 160, 220, 0.7);
    box-shadow: none;
    transform: none;
}
.choice-btn.disabled .choice-disabled-reason {
    font-size: 11px;
    color: var(--text-dim);
    font-style: italic;
    margin-top: 3px;
}

/* Cost badges */
/* Choice hover stat preview */
.choice-hover-tip {
    position: fixed; z-index: var(--z-modal); pointer-events: none;
    /* Readability scale combined with the existing position-translate.
       transform-origin top so the tip grows downward away from the choice
       button. translate(-50%, -100%) keeps it anchored above the cursor. */
    transform: translateX(-50%) translateY(-100%) scale(var(--overlay-zoom, 1));
    transform-origin: center bottom;
    background: rgba(14, 11, 20, 0.95);
    border: 1px solid rgba(228, 140, 184, 0.2);
    border-radius: 6px; padding: 5px 10px;
    font-family: 'DM Mono', monospace; font-size: 10px;
    color: var(--text-dim); white-space: nowrap;
    box-shadow: 0 4px 12px rgba(0,0,0,0.5);
}
.choice-hover-tip.has-breakdown {
    padding: 6px 11px;
}
.choice-hover-tip .choice-hover-breakdown {
    margin-top: 3px;
    padding-top: 3px;
    border-top: 1px dashed rgba(228, 140, 184, 0.18);
    font-size: 9px;
    color: var(--text-faint);
}

.choice-badges {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
    justify-content: center;
}

.choice-badge {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    font-weight: 500;
    padding: 1px 5px;
    border-radius: 4px;
    letter-spacing: 0.3px;
    white-space: nowrap;
    flex-shrink: 0;
}

.badge-energy {
    background: rgba(92, 216, 156, 0.15);
    color: var(--energy);
    border: 1px solid rgba(92, 216, 156, 0.2);
}
/* Energy cost modified by hidden multipliers (Arousal penalty, HRT
   irritable, Comfort, Drunk). The number on the badge is the effective
   cost; the tooltip carries the breakdown. Tinted amber so the player
   notices the badge differs from the raw #energy:N tag. */
.badge-energy.badge-energy-modified {
    background: rgba(224, 160, 80, 0.18);
    color: var(--orange);
    border-color: rgba(224, 160, 80, 0.3);
}
.badge-time {
    background: rgba(232, 200, 96, 0.15);
    color: var(--gold);
    border: 1px solid rgba(232, 200, 96, 0.2);
}
.badge-fem {
    background: rgba(228, 120, 184, 0.15);
    color: var(--fem);
    border: 1px solid rgba(228, 120, 184, 0.2);
}
.badge-sub {
    background: rgba(168, 128, 224, 0.15);
    color: var(--sub);
    border: 1px solid rgba(168, 128, 224, 0.2);
}
.badge-shame {
    background: rgba(192, 144, 96, 0.15);
    color: var(--shame);
    border: 1px solid rgba(192, 144, 96, 0.2);
}
.badge-arousal {
    background: rgba(224, 104, 120, 0.15);
    color: var(--arousal);
    border: 1px solid rgba(224, 104, 120, 0.2);
}
.badge-warn {
    background: rgba(224, 160, 80, 0.2);
    color: var(--orange);
    border: 1px solid rgba(224, 160, 80, 0.3);
    font-weight: 600;
}

/* End-of-scene fleuron — quiet centered ornament that sits between the
   last narrative line and the choice buttons. Uses the same 4-petal rose
   PNG as the narrator info-card but centered, smaller, and dimmer so it
   reads as a scene-terminator mark, not as content. Shown only when the
   choice has a cost/image (real narrative ending), hidden on plain
   navigation hubs where there's no "end" to signal. */
.scene-end-fleuron {
    width: 100%;
    height: 24px;
    margin: 18px auto 8px;
    background: url('../assets/images/UI/narrator_ornament.png') center/18px 18px no-repeat;
    opacity: 0.38;
    filter: hue-rotate(-80deg) saturate(0.6) brightness(1.1);
    pointer-events: none;
    animation: scene-fleur-in 0.5s ease-out;
}
@keyframes scene-fleur-in {
    0%   { opacity: 0; transform: scale(0.7); }
    100% { opacity: 0.38; transform: scale(1); }
}

/* Icon-based stat badges — replaces the old "+8 A" / "+1 Fem" text form
   so the stat is identified by its glyph (same art as the STATS panel). */
.badge-with-icon {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 5px 1px 3px;
}
.badge-icon {
    width: 12px;
    height: 12px;
    object-fit: contain;
    flex-shrink: 0;
    image-rendering: auto;
}

/* Stat Preview toggle (PnO_StatPreview): hides character-drift stat previews
   so new players roleplay instead of optimize. Energy/Time/Warnings stay
   visible because they communicate gameplay gating, not character drift.
   Audit D35: arousal was leaking through (only fem/sub/shame were hidden,
   but +arousal: previews exposed a drift stat). Now fully consistent. */
body.hide-stat-previews .badge-fem,
body.hide-stat-previews .badge-sub,
body.hide-stat-previews .badge-shame,
body.hide-stat-previews .badge-arousal {
    display: none;
}

.choice-text {
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ── Choice thumbnail images (#choiceimg: tag) ── */
.choice-btn.has-thumb {
    flex-direction: row;
    align-items: stretch;
    justify-content: flex-start;
    text-align: left;
    padding: 0;
    /* Override base .choice-btn's overflow:hidden so thumbnail cards can
       grow vertically when text wraps + badges stack below. .choice-thumb
       still has its own overflow:hidden + border-radius for the rounded
       image corner, so the visual remains clean. Pre-v0.2.7 this rule had
       `height: 80px` + the inherited `overflow: hidden` which clipped 4-
       badge thumbnail choices regardless of badge DOM placement. */
    overflow: visible;
    min-height: 80px;
    /* Match the 2-per-row basis from the base rule so thumbnail rows
       fill the container the same way text-only rows do. The old
       `flex: 0 1 calc(33.33% - 4px); min-width: 250px` combo produced
       narrower thumbnail rows on wide desktops (user report
       2026-04-20: "die oben sind zu kurz, unten lang"). */
    flex: 1 1 calc(50% - 3px);
    min-width: 0;
    position: relative;
}
.choice-btn.has-thumb::before {
    display: none;
}
.choice-btn.has-thumb::after {
    display: none;
}
.choice-thumb {
    width: 100px;
    flex-shrink: 0;
    overflow: hidden;
    border-radius: 8px 0 0 8px;
}
.choice-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: brightness(0.75);
    transition: filter 0.2s;
}
.choice-btn.has-thumb:hover .choice-thumb img {
    filter: brightness(1);
}
/* Text + badges wrapper: fill remaining space, center vertically */
.choice-content-wrap {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 6px 0;
    overflow: hidden;
}
.choice-btn.has-thumb .choice-text {
    padding: 0 14px;
    -webkit-line-clamp: unset;
    -webkit-box-orient: unset;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    min-width: 0;
    font-size: 14px;
    font-weight: 600;
    word-break: break-word;
    line-height: 1.3;
}
/* Badges for thumbnail choices: stacked below text inside contentWrap.
   Pre-v0.2.7 they were appended inline INSIDE .choice-text — which has
   overflow:hidden — so when text wrapped to 3+ lines on mobile the badges
   scrolled off-card (Laser Hair Removal "missing cost/stats" report). */
.choice-badges-inline {
    display: flex !important;
    gap: 4px;
    margin: 4px 14px 0;
    flex-wrap: wrap;
}
.choice-badges-inline .choice-badge {
    font-size: 10px;
    padding: 3px 7px;
}
.choice-btn.has-thumb .choice-disabled-reason {
    padding: 2px 14px 0;
    min-width: 0;
    word-break: break-word;
    white-space: normal;
    font-size: 11px;
    line-height: 1.25;
    color: var(--text-dim);
    font-style: italic;
    max-height: 2.6em;
    overflow: hidden;
}

/* Disabled thumbnail: stronger desaturate to match the muted card body */
.choice-btn.has-thumb.disabled .choice-thumb img {
    filter: brightness(0.45) grayscale(0.75);
}

.choices-grid.choices-disabled .choice-btn {
    pointer-events: none;
    opacity: 0.6;
}

.choices-grid.choices-pending {
    opacity: 0.4;
    pointer-events: none;
    filter: blur(1px);
    transition: opacity 0.3s ease, filter 0.3s ease;
}

/* Choice number badge — anchored to the top-left corner of the button
   as a keybinding hint. Hotkeys 1-9 are bound in choices.js _bindKeyboard;
   this badge is purely the visual cue. */
.choice-number {
    position: absolute;
    top: 6px;
    left: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 5px;
    background: rgba(228, 140, 184, 0.18);
    border: 1px solid rgba(228, 140, 184, 0.28);
    color: rgba(240, 200, 220, 0.95);
    font-size: 11px;
    font-weight: 700;
    font-family: 'DM Mono', monospace;
    line-height: 1;
    z-index: 2;
    pointer-events: none;
    transition: background 0.2s ease, border-color 0.2s ease;
}
.choice-btn:hover .choice-number {
    background: rgba(228, 140, 184, 0.3);
    border-color: rgba(228, 140, 184, 0.5);
}
/* Keyboard-navigation highlight (ArrowUp/Down move it; ENTER confirms).
   Space is intentionally NOT a confirm key, so it can never auto-select the
   first/consent choice. The highlighted choice's number badge also brightens
   to reinforce the 1-9 number-key shortcut. */
.choice-btn.choice-kb-active {
    outline: 2px solid var(--rose, #e48cb8);
    outline-offset: 2px;
    box-shadow: 0 0 0 4px rgba(228, 140, 184, 0.22);
    border-color: rgba(228, 140, 184, 0.6);
}
.choice-btn.choice-kb-active .choice-number {
    background: rgba(228, 140, 184, 0.55);
    border-color: rgba(228, 140, 184, 0.85);
    color: #fff;
}
/* Button-level left-padding reserves space for the absolute badge so text
   never collides with it. Keeps centered text visually balanced. */
.choice-btn:not(.has-thumb) {
    padding-left: 34px;
    padding-right: 34px;  /* symmetric so centered text stays on button centre */
}
/* Thumbnail buttons: badge overlays the thumbnail corner — give it a dark
   backdrop so it stays readable against any image. */
.choice-btn.has-thumb .choice-number {
    background: rgba(18, 12, 26, 0.78);
    border-color: rgba(228, 140, 184, 0.45);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

/* Dead-end return button */
.choice-btn.return-btn {
    flex-basis: 100%;
    background: rgba(100, 50, 60, 0.15);
    border-color: rgba(200, 80, 80, 0.2);
    color: var(--text-dim);
    font-style: italic;
}


/* ============================================


/* ============================================
   #color: tag styling (v0.2.6 — data-color attribute applied by
   choices.js _createChoiceButton). 'safeword' is the only fully-styled
   value; 'pink' and 'resist' remain latent (no CSS) for backwards
   compatibility — they've been in Ink without rendering for ages.
   ============================================ */

/* Safeword — amber border + ⚠ prefix. Used in Kennel scenes (Mira's
   sessions, v0.2.6 Kink Deep-Dive). Player can ALWAYS exit a session
   via this choice; small shame penalty, no relationship penalty. */
.choice-btn[data-color="safeword"] {
    border-color: rgba(220, 188, 140, 0.55);
    background: linear-gradient(135deg, rgba(80, 60, 30, 0.18), var(--bg-choice));
    color: rgba(238, 220, 170, 0.92);
}
.choice-btn[data-color="safeword"]:hover:not(.disabled):not(:disabled) {
    border-color: rgba(232, 200, 120, 0.85);
    background: linear-gradient(135deg, rgba(110, 80, 40, 0.28), var(--bg-choice));
    box-shadow: 0 0 14px rgba(220, 180, 110, 0.18);
}
.choice-btn[data-color="safeword"] .choice-text::before {
    content: "⚠ ";
    color: rgba(232, 188, 120, 0.95);
    font-weight: 700;
    margin-right: 2px;
}

/* Audit D21: Choice-card tier-variants. Pink + resist were latent; both now
   rendered so the player gets a visual hint about consequence type.
   - pink:    fem-leaning choice (#color:pink in Ink — escalation, soft path)
   - resist:  push-back choice (#color:resist — Sub-cost reduction beat) */
.choice-btn[data-color="pink"] {
    border-color: rgba(228, 140, 184, 0.55);
    background: linear-gradient(135deg, rgba(120, 50, 90, 0.18), var(--bg-choice));
}
.choice-btn[data-color="pink"]:hover:not(.disabled):not(:disabled) {
    border-color: rgba(232, 160, 200, 0.85);
    background: linear-gradient(135deg, rgba(150, 65, 110, 0.28), var(--bg-choice));
    box-shadow: 0 0 14px rgba(228, 140, 184, 0.18);
}
.choice-btn[data-color="pink"] .choice-text::before {
    content: "\2665 ";
    color: rgba(232, 160, 200, 0.95);
    font-weight: 700;
    margin-right: 2px;
}

.choice-btn[data-color="resist"] {
    border-color: rgba(120, 160, 220, 0.55);
    background: linear-gradient(135deg, rgba(40, 70, 110, 0.20), var(--bg-choice));
    color: rgba(200, 220, 245, 0.92);
}
.choice-btn[data-color="resist"]:hover:not(.disabled):not(:disabled) {
    border-color: rgba(160, 195, 240, 0.85);
    background: linear-gradient(135deg, rgba(60, 100, 150, 0.28), var(--bg-choice));
    box-shadow: 0 0 14px rgba(120, 160, 220, 0.18);
}
.choice-btn[data-color="resist"] .choice-text::before {
    content: "\21ba ";
    color: rgba(160, 195, 240, 0.95);
    font-weight: 700;
    margin-right: 2px;
}

/* Tier-variants driven by data-tier attribute (set when stat-gain crosses
   thresholds — see choices.js stat-gain decoration). Latent until JS sets
   data-tier: choices.js can opt-in by checking choice.femGain >= 3 etc. */
.choice-btn[data-tier="high-fem"] {
    border-left: 3px solid var(--fem);
}
.choice-btn[data-tier="high-sub"] {
    border-left: 3px solid var(--sub);
}
.choice-btn[data-tier="dramatic"] {
    border-left: 3px solid var(--gold);
    box-shadow: 0 0 10px rgba(232, 200, 96, 0.12);
}
/* ============================================
   13. RIGHT PANEL: CHARACTER
   ============================================ */
.character-slots {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.char-slot {
    display: flex;
    align-items: center;
    gap: 12px;
    background: rgba(20, 15, 30, 0.4);
    border: 1px solid rgba(46, 34, 66, 0.4);
    border-radius: 10px;
    padding: 10px 14px;
    min-height: 72px;
    transition: transform 0.2s ease, border-color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
}
.char-slot:hover {
    border-color: rgba(196, 112, 224, 0.4);
    background: rgba(30, 22, 45, 0.55);
    transform: translateY(-1px);
    box-shadow: 0 6px 18px rgba(155, 89, 182, 0.18);
}

.char-slot-image {
    /* Portrait-ish ratio (4:5) — outfit items read as "how you look today",
       not as tiny inventory thumbnails. Fixed width keeps row alignment,
       height scales taller so full garments aren't cropped to a square. */
    width: 60px;
    height: 76px;
    border-radius: 8px;
    background: rgba(30, 28, 45, 0.6);
    overflow: hidden;
    flex-shrink: 0;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35), inset 0 0 0 1px rgba(196, 112, 224, 0.08);
}
.char-slot-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.char-slot-label {
    font-size: 13px;
    color: var(--text-dim);
    font-weight: 500;
    line-height: 1.3;
}

/* Accessory row */
.accessory-row {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

.acc-slot {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    width: 48px;
}

.acc-slot-image {
    width: 40px;
    height: 40px;
    border-radius: 6px;
    background: rgba(30, 28, 45, 0.6);
    border: 1px solid rgba(46, 34, 66, 0.3);
    overflow: hidden;
}
.acc-slot-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.acc-slot-label {
    font-size: 8px;
    color: var(--text-faint);
    text-align: center;
    letter-spacing: 0.3px;
}
/* Hide empty image box and enlarge label for icon-less accessories */
.acc-slot-image:empty {
    display: none;
}
.acc-slot-image:empty + .acc-slot-label {
    font-size: 10px;
    background: rgba(30, 28, 45, 0.6);
    border: 1px solid rgba(46, 34, 66, 0.3);
    border-radius: 6px;
    padding: 4px 6px;
    min-width: 40px;
    line-height: 1.3;
    color: var(--text-soft);
}

/* Nude toggle */
.btn-nude-toggle {
    width: 100%;
    height: 34px;
    background: rgba(20, 15, 30, 0.4);
    border: 1px solid rgba(46, 34, 66, 0.4);
    border-radius: 8px;
    color: var(--text-dim);
    font-size: 11px;
    font-weight: 500;
    transition: all 0.2s ease;
    margin-top: 4px;
}
.btn-nude-toggle:hover {
    border-color: var(--border-glow);
    color: var(--rose);
}
.btn-nude-toggle.active {
    background: rgba(228, 120, 184, 0.1);
    border-color: var(--rose);
    color: var(--rose);
}


/* ============================================


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Character panel item sizing
   ============================================ */
/* ============================================
   FIX: Character panel items — larger images, compact names
   ============================================ */
.char-slot {
    flex-direction: column !important;
    align-items: center !important;
    gap: 0 !important;
    padding: 4px !important;
    min-height: auto !important;
    width: fit-content !important;
    align-self: center !important;
}
.character-slots {
    align-items: center !important;
}
.char-slot-row {
    justify-content: center !important;
}
.char-slot-image {
    width: auto !important;
    min-width: 80px !important;
    max-width: 100% !important;
    height: 96px !important;
    border-radius: 6px !important;
    background: transparent !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}
.char-slot-placeholder {
    font-size: 11px !important;
    color: var(--text-faint) !important;
    opacity: 0.6;
    font-style: italic;
    letter-spacing: 0.5px;
}
.char-slot-image img {
    height: 100% !important;
    width: auto !important;
    max-width: 100% !important;
    object-fit: contain !important;
    display: block;
}
.char-slot-info {
    padding: 2px 4px 0;
}
.char-slot-label {
    font-size: 8px !important;
    text-align: center;
}
.char-slot-item-name {
    font-size: 10px !important;
    text-align: center;
}
.char-slot-empty {
    font-size: 10px !important;
    text-align: center;
}
/* Half-width slots (legwear/feet, front/back) get smaller images */
.char-slot.half .char-slot-image {
    height: 64px !important;
}
/* Accessory row: slightly bigger */
.acc-slot {
    width: 56px;
}
.acc-slot-image {
    width: 48px !important;
    height: 48px !important;
}

/* ============================================

/* ============ Paper Doll (dressed preview, PAPER_DOLL.md Phase 3) ============ */
.paper-doll-box {
    /* Owner 2026-06-07: Doll groesser via object-fit:cover - die
       2:3-Quelle hat breite transparente Seitenraender (stehende Figur
       ~45% Breite). Box greift den freien Platz (flex), Layer fuellen
       die HOEHE, nur leere Seiten werden weggeschnitten. max-height
       deckelt, damit Kopf/Fuesse nicht clippen. */
    flex: 1 1 auto;
    min-height: 300px;
    /* kein max-height: Box fuellt die Spalte (Desktop: kein Leerraum,
       Phone: gross). Footer ist position:sticky -> bleibt sichtbar,
       auch wenn die hohe Doll die Spalte ueber die Falz schiebt. */
    margin: 6px 0 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.paper-doll {
    position: relative;
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    max-height: none;
    /* right-column is a column flexbox; without this the box (whose only
       children are absolutely positioned imgs, min-content height 0)
       absorbs ALL the flex shrink and collapses to ~20px - die
       .paper-doll-box min-height:300px schuetzt jetzt davor, daher darf
       die Box schrumpfen, um in die Spalte zu passen (Fuesse nicht mehr
       hinter dem Sticky-Footer). Wardrobe-Pane hat eigene shrink:0 in _08. */
    flex-shrink: 1;
    margin: 0 auto;
    border-radius: 10px;
    overflow: hidden;
    background: radial-gradient(ellipse at 50% 30%, rgba(233, 30, 99, 0.08), transparent 70%);
}
.paper-doll:empty {
    display: none;
}
.paper-doll-layer {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* 2026-06-15 (foundby:Scoot): object-fit:cover cropped the figure's legs
       off the bottom (box ends up shorter than the 2:3 source). contain shows
       the WHOLE figure every time; the trade is thin transparent side margins
       when the column is wider than 2:3. All layers share source dimensions,
       so contain scales them identically and registration is preserved. */
    object-fit: contain;
    object-position: center top;
    pointer-events: none;
}
/* Worn-but-hidden gear chips (plug / cage / belt) — the dressed view can't
   show Front/Back intimate items, so flag them in the top-right corner.
   Owner 2026-06-09. Rendered by paper-doll.js as an overlay inside the
   .paper-doll mount (survives the per-render innerHTML wipe). */
.doll-worn-indicators {
    position: absolute;
    top: 6px;
    left: 6px;                  /* 0.2.9: moved from right to clear the eye/play overlay */
    z-index: 5;                 /* layers have z:auto; positioned+z floats above */
    display: flex;
    flex-direction: column;
    gap: 5px;
    pointer-events: none;       /* chips opt back in for the hover title */
}
.doll-worn-chip {
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    background: rgba(22, 9, 18, 0.62);
    border: 1px solid rgba(233, 30, 99, 0.55);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
    pointer-events: auto;
}
.doll-worn-chip img {
    width: 78%;
    height: 78%;
    object-fit: contain;
    pointer-events: none;
}
/* ============================================
   14. OVERLAYS
   ============================================ */
.overlay-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(8, 6, 12, 0.88);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    z-index: var(--backdrop-z);
    transition: opacity 0.3s ease;
}
.overlay-backdrop.hidden {
    display: none;
}

.overlay {
    position: fixed;
    inset: 0;
    z-index: var(--overlay-z);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    animation: overlay-in 0.3s var(--ease-out) both;
}
.overlay.hidden { display: none; }

@keyframes overlay-in {
    from { opacity: 0; transform: translateY(12px) scale(0.98); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

.overlay-out {
    animation: overlay-out 0.25s ease both;
}
@keyframes overlay-out {
    from { opacity: 1; transform: translateY(0) scale(1); }
    to { opacity: 0; transform: translateY(8px) scale(0.98); }
}

.overlay-box {
    background: linear-gradient(180deg, var(--bg-warm), var(--bg-deep));
    border: 1px solid rgba(140, 100, 180, 0.12);
    border-radius: 14px;
    width: 100%;
    /* Zoom-aware viewport bound — divide the layout max-height by the
       current UI Scale so the rendered (post-transform) visual height
       stays inside 85vh / 100dvh regardless of --overlay-zoom value.
       Pre-fix, transform: scale grew the visual box beyond the static
       85vh cap, pushing form bottoms (Submit, toggles, action rows)
       below the viewport edge. Foundby:v0.2.6.7 player reports —
       "anonymous analytics button seems out of bounds", "Feedback
       window cut off", "Settings nearly cut off at bottom". */
    max-height: calc(min(85vh, 100dvh - 40px) / var(--overlay-zoom, 1));
    overflow-y: auto;
    position: relative;
    box-shadow:
        0 16px 48px rgba(0, 0, 0, 0.6),
        0 0 1px rgba(228, 140, 184, 0.15),
        inset 0 1px 0 rgba(255, 255, 255, 0.03);
    /* Readability scaling — driven by Font Size + UI Scale sliders.
       transform: scale() (not `zoom`) because Chromium's non-standard
       `zoom` property doesn't accept CSS var() values reliably. Origin
       center-center so the visual box stays viewport-bounded when
       zoom > 1 — the previous `center top` design kept the header
       anchored but let the scaled bottom extend off-screen, hiding the
       action area. Combined with the zoom-aware max-height above the
       box now fits inside the visible viewport at any zoom level. */
    transform: scale(var(--overlay-zoom, 1));
    transform-origin: center center;
}

/* Keyframes scale OFF the user's --overlay-zoom so the entry animation
   ends at the slider-chosen scale instead of always 1.0 (which would
   "pop" up to the user-chosen scale after the animation finishes). */
@keyframes overlaySlideIn {
    from { transform: scale(calc(0.95 * var(--overlay-zoom, 1))) translateY(8px); opacity: 0; }
    to { transform: scale(var(--overlay-zoom, 1)) translateY(0); opacity: 1; }
}
.overlay:not(.hidden) .overlay-box {
    animation: overlaySlideIn 0.25s ease-out;
}
@keyframes overlaySlideOut {
    from { transform: scale(var(--overlay-zoom, 1)); opacity: 1; }
    to { transform: scale(calc(0.95 * var(--overlay-zoom, 1))); opacity: 0; }
}
.overlay.overlay-out .overlay-box {
    animation: overlaySlideOut 0.2s ease-in;
}

.overlay-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    border-bottom: none;
    position: sticky;
    top: 0;
    background: linear-gradient(180deg, var(--bg-warm), rgba(20, 15, 30, 0.95));
    z-index: 1;
    border-radius: 14px 14px 0 0;
}
.overlay-header h2 {
    font-size: 15px;
    font-weight: 600;
    color: var(--rose);
    letter-spacing: 1px;
    text-transform: uppercase;
}

.btn-overlay-close {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: rgba(46, 34, 66, 0.4);
    color: var(--text-dim);
    font-size: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s ease;
}
.btn-overlay-close:hover { background: rgba(200, 80, 80, 0.3); color: var(--text); }

/* Floating close button (top-right, shared across overlays) */
.overlay-close-float {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(200, 60, 60, 0.15);
    border: 1px solid rgba(200, 60, 60, 0.3);
    color: rgba(220, 80, 80, 0.9);
    font-size: 22px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10;
    transition: all 0.2s ease;
    line-height: 1;
}
.overlay-close-float:hover {
    background: rgba(200, 60, 60, 0.35);
    color: #fff;
    border-color: rgba(220, 80, 80, 0.5);
    transform: scale(1.1);
}

/* Per-overlay sizes */
.pause-box { max-width: 480px; }
.shop-box { max-width: 880px; display: flex; flex-direction: column; }
.wardrobe-box { max-width: 920px; }
.achievement-box { max-width: 700px; }
.gallery-box { max-width: 75vw; }
.journal-box { max-width: 600px; }
.history-box { max-width: 560px; }
/* phone-box: base fallback — mobile (<=767px) forces 100%, desktop (>=768px)
 * narrows to 420px. The explicit min() caps horizontal overflow if some
 * future tablet-width breakpoint slips through both queries. */
.phone-box { max-width: min(500px, 90vw); min-height: 600px; }

/* Phone: phone overlay fills screen edge-to-edge */
@media (max-width: 767px) {
    /* Specificity bump (.overlay-box.phone-box) so this beats the
       _07-responsive.css `.overlay-box { max-height: 92vh/zoom }` rule
       that ships AFTER us in the compiled file. Cascade-order alone
       would otherwise let the 92vh override win. */
    .overlay-box.phone-box {
        max-width: 100%;
        width: 100%;
        min-height: auto;
        /* Zoom-aware so the scaled visual stays inside the viewport at
           any --overlay-zoom value. Pre-fix, 100vh × zoom 1.4 overflowed
           by 40vh and pushed phone-bottom nav off-screen on mobile. */
        max-height: calc(100vh / var(--overlay-zoom, 1));
        border-radius: 0;
        margin: 0;
    }
    /* align-items: center (not stretch) so max-height caps the phone-box
       on mobile when --overlay-zoom > 1. With stretch the flex item
       fills the parent (100vh) regardless of max-height, then the
       transform: scale grew it past viewport. center keeps it bounded. */
    .overlay-phone { padding: 0; align-items: center; }
    .overlay-box { font-size: 13px; }
    .slot-info { font-size: 12px; }
}

/* Desktop: phone centered modal (same as mobile) */
@media (min-width: 768px) {
    .overlay-phone .phone-box {
        max-width: 420px;
        /* min-height + max-height both scale-aware so the box stays inside
           the viewport at any --overlay-zoom. min(600px, ...) caps the
           layout-min so a zoomed-up viewport doesn't fight max-height. */
        min-height: min(600px, calc(85vh / var(--overlay-zoom, 1)));
        max-height: calc(85vh / var(--overlay-zoom, 1));
        animation: phone-pop-in 0.3s var(--ease-out) both;
    }
    .overlay-phone.overlay-out .phone-box {
        animation: phone-pop-out 0.25s ease both;
    }
    body.phone-active .overlay-backdrop {
        background: rgba(8, 6, 12, 0.5);
        backdrop-filter: blur(2px);
        -webkit-backdrop-filter: blur(2px);
    }
}

@keyframes phone-pop-in {
    from { transform: scale(0.92) translateY(20px); opacity: 0; }
    to { transform: scale(1) translateY(0); opacity: 1; }
}
@keyframes phone-pop-out {
    from { transform: scale(1) translateY(0); opacity: 1; }
    to { transform: scale(0.92) translateY(20px); opacity: 0; }
}
.bugreport-box { max-width: 440px; }
.feedback-box { max-width: 480px; }
.settings-box { max-width: 440px; }
.settings-content { padding: 20px 28px; }

/* Welcome / Feedback / Bugreport overlay-box overrides are no longer
   needed — the zoom-aware max-height + transform-origin: center center
   apply globally on .overlay-box (see the top of this file). The fix
   covers all overlays in one place. Foundby:v0.2.6.7 player reports
   "anonymous analytics button seems out of bounds", "Feedback window
   cut off", "Settings nearly cut off at bottom". */

/* Onboarding profile picker — first-run UI choice between Story-First / Stats-Visible / Skip.
   Studio Review Task #9. Shows once before character editor on New Game. */
.overlay-onboarding .onboarding-box {
    max-width: 540px;
    padding: 32px 36px 28px;
    background: linear-gradient(160deg, rgba(28, 22, 48, 0.96), rgba(20, 16, 36, 0.98));
    border: 1px solid rgba(228, 140, 184, 0.22);
    border-radius: 14px;
    box-shadow: 0 16px 48px rgba(0,0,0,0.45);
}
.onboarding-header { text-align: center; margin-bottom: 22px; }
.onboarding-header h2 {
    margin: 0 0 8px;
    font-size: 22px;
    font-weight: 600;
    color: #f6e2ee;
    letter-spacing: 0.01em;
}
.onboarding-subtitle {
    margin: 0;
    color: var(--text-dim);
    font-size: 13px;
    line-height: 1.5;
}
.onboarding-options { display: flex; flex-direction: column; gap: 10px; }
.onboarding-option {
    text-align: left;
    padding: 14px 18px;
    background: rgba(28, 22, 42, 0.65);
    border: 1px solid rgba(228, 140, 184, 0.2);
    border-radius: 10px;
    color: var(--text);
    cursor: pointer;
    transition: all 0.18s ease;
    font-family: inherit;
}
.onboarding-option:hover {
    background: rgba(40, 30, 58, 0.85);
    border-color: rgba(228, 140, 184, 0.55);
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(228, 140, 184, 0.16);
}
.onboarding-option-title {
    font-size: 14px;
    font-weight: 600;
    color: #f6e2ee;
    margin-bottom: 4px;
    letter-spacing: 0.02em;
}
.onboarding-option-desc {
    font-size: 12px;
    color: var(--text-dim);
    line-height: 1.45;
}
.onboarding-option-skip { opacity: 0.78; }
.onboarding-option-skip:hover { opacity: 1; }

/* Pause overlay */
.pause-content { padding: 20px 28px; }

/* Tabbed pause panel: split long settings list into Saves + Settings */
.pause-tabs {
    display: flex;
    gap: 4px;
    margin: -4px -4px 16px;
    padding: 4px;
    background: rgba(14, 11, 20, 0.55);
    border-radius: 8px;
}
.pause-tab-btn {
    flex: 1;
    padding: 8px 14px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 6px;
    color: var(--text-dim);
    font-family: 'DM Sans', sans-serif;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    cursor: pointer;
    transition: all 0.15s ease;
}
.pause-tab-btn:hover {
    color: var(--text);
    background: rgba(228, 140, 184, 0.08);
}
.pause-tab-btn.active {
    color: #fff;
    background: rgba(228, 140, 184, 0.18);
    border-color: rgba(228, 140, 184, 0.35);
    box-shadow: 0 1px 4px rgba(228, 140, 184, 0.18);
}
.pause-tab-panel { display: none; }
.pause-tab-panel.active { display: block; }

/* Names tab (rename MC masc+fem / Master / GF / Bar mid-game) */
.names-tab-hint {
    font-size: 0.82rem;
    color: var(--text-muted, #b9a8c4);
    line-height: 1.45;
    margin: 0 0 16px;
}
.names-field { margin-bottom: 12px; }
.names-field label {
    display: block;
    font-size: 0.8rem;
    color: var(--text-muted, #b9a8c4);
    margin-bottom: 5px;
}
.names-field input {
    width: 100%;
    box-sizing: border-box;
    padding: 9px 12px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 8px;
    background: rgba(0, 0, 0, 0.28);
    color: var(--text, #f3e9f7);
    font-size: 0.95rem;
}
.names-field input:focus {
    outline: none;
    border-color: var(--accent, #e85d9c);
}
.names-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 18px;
}
.names-feedback {
    font-size: 0.85rem;
    color: var(--accent-2, #5cd89c);
}

/* Section headers inside the Pause/Settings overlay — Audit D41: bumped
   the visual weight so 13 toggles read as 3 clear groups instead of one
   long stream. Sticky-ish header band with a small dot prefix. */
.settings-section-header {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--rose);
    margin: 16px 0 10px;
    padding: 6px 12px 6px 18px;
    background: rgba(228, 140, 184, 0.08);
    border-left: 3px solid rgba(228, 140, 184, 0.65);
    border-radius: 0 6px 6px 0;
    position: relative;
}
.settings-section-header:first-child { margin-top: 4px; }
/* Save slot list — per-slot Save/Load buttons */
.save-slot-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 12px;
    /* 6 manual + 1 auto rows can overflow the overlay on short viewports
       (mobile landscape, 768x600 laptop). Scope scroll to the list itself
       so the secondary buttons + community CTAs + pause footer stay
       reachable without scrolling the whole overlay. */
    max-height: 52vh;
    overflow-y: auto;
    /* Slight gutter so the inner scrollbar doesn't sit flush against the
       slot rows on Chromium/WebKit. */
    padding-right: 4px;
}
.save-slot-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 8px;
    transition: border-color 0.2s ease;
}
.save-slot-row.save-slot-has-data { border-color: rgba(92, 216, 156, 0.25); }
.save-slot-row[data-slot="-1"] { border-left: 3px solid var(--accent); }
.slot-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.slot-label { font-size: 12px; font-weight: 600; color: var(--text); }
.slot-info { font-size: 11px; color: var(--text-dim); display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.slot-info .slot-name { color: var(--text); font-weight: 600; }
.slot-info .slot-day { color: var(--gold); font-family: 'DM Mono', monospace; font-size: 10px; }
.slot-info .slot-timestamp { width: 100%; color: var(--text-faint); font-size: 10px; font-family: 'DM Mono', monospace; }
/* Audit D15: path-indicator pill. Each route gets its own colour family so a
   glance distinguishes Independent vs Roommate vs Landlord vs Owner saves. */
.slot-path-pill {
    font-size: 10px;
    font-weight: 700;
    padding: 2px 7px;
    border-radius: 10px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border: 1px solid;
}
.slot-path-independent { color: #b4d7f5; border-color: rgba(180, 215, 245, 0.45); background: rgba(80, 120, 180, 0.18); }
.slot-path-roommate    { color: #c0b0e0; border-color: rgba(180, 160, 220, 0.45); background: rgba(120, 90, 180, 0.18); }
.slot-path-landlord    { color: #e8c860; border-color: rgba(232, 200, 96, 0.45); background: rgba(160, 120, 40, 0.18); }
.slot-path-owner       { color: #e88cb8; border-color: rgba(232, 140, 184, 0.55); background: rgba(180, 60, 120, 0.22); }
.slot-stat-pill {
    font-size: 10px;
    padding: 2px 6px;
    border-radius: 8px;
    font-family: 'DM Mono', monospace;
    background: rgba(46, 34, 66, 0.5);
    border: 1px solid var(--border);
}
.slot-stat-fem { color: var(--fem); }
.slot-stat-sub { color: var(--sub); }
.slot-actions { display: flex; gap: 6px; flex-shrink: 0; margin-left: 10px; }
.slot-btn {
    padding: 6px 14px;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s ease;
    border: 1px solid;
}
.slot-btn-save {
    background: rgba(92, 40, 72, 0.3);
    border-color: rgba(228, 140, 184, 0.2);
    color: var(--rose);
}
.slot-btn-save:hover { background: rgba(92, 40, 72, 0.5); border-color: rgba(228, 140, 184, 0.4); }
.slot-btn-load {
    background: rgba(40, 72, 92, 0.3);
    border-color: rgba(140, 184, 228, 0.2);
    color: #8cb8e4;
}
.slot-btn-load:hover { background: rgba(40, 72, 92, 0.5); border-color: rgba(140, 184, 228, 0.4); }
.slot-btn-export {
    background: rgba(60, 60, 80, 0.3);
    border-color: rgba(180, 180, 200, 0.2);
    color: var(--text-dim);
}
.slot-btn-export:hover { background: rgba(60, 60, 80, 0.5); border-color: rgba(180, 180, 200, 0.4); }
.slot-btn-delete {
    background: rgba(60, 60, 80, 0.25);
    border-color: rgba(180, 180, 200, 0.18);
    color: var(--text-dim);
    padding: 6px 9px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.slot-btn-delete:hover { background: rgba(150, 45, 60, 0.45); border-color: rgba(224, 96, 122, 0.6); color: #ffb3c0; }
.slot-btn-delete svg { display: block; }
.slot-btn:disabled { opacity: 0.3; pointer-events: none; }

.pause-actions {
    display: flex;
    gap: 8px;
    margin-bottom: 10px;
}
.btn-pause-action {
    flex: 1;
    height: 40px;
    background: linear-gradient(135deg, #5c2848, #803870);
    border: 1px solid rgba(228, 140, 184, 0.2);
    border-radius: 8px;
    color: #eedce8;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.5px;
    transition: all 0.2s ease;
}
.btn-pause-action:hover {
    box-shadow: 0 2px 12px rgba(128, 56, 112, 0.3);
}

.pause-secondary {
    display: flex;
    gap: 8px;
    margin-bottom: 8px;
}
.btn-pause-secondary {
    flex: 1;
    height: 34px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 6px;
    color: var(--text-dim);
    font-size: 11px;
    transition: all 0.2s ease;
}
.btn-pause-secondary:hover { border-color: var(--border-glow); color: var(--text); }
/* Primary action button in the pause overlay (e.g. Save Names) — filled accent,
   clearly clickable (the secondary buttons are ghost-styled). */
.btn-pause-primary {
    height: 38px;
    padding: 0 22px;
    background: var(--accent, #e85d9c);
    border: 1px solid var(--accent, #e85d9c);
    border-radius: 8px;
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s ease;
}
.btn-pause-primary:hover { filter: brightness(1.08); box-shadow: 0 0 12px rgba(232, 93, 156, 0.35); }
.btn-pause-primary:active { transform: translateY(1px); }
.btn-quit { border-color: rgba(200, 80, 80, 0.2); }
.btn-quit:hover { border-color: rgba(200, 80, 80, 0.5); color: var(--red); }

/* Audit D14: Pause menu community CTAs. Two-up grid, brand-tinted, opens
   external. min-height 44 (D08 sweep). focus-visible ring. */
.pause-community {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin: 12px 0 4px;
}
.pause-community-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    padding: 8px 12px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    text-align: center;
    transition: transform 0.15s ease, box-shadow 0.2s ease, border-color 0.2s ease;
    border: 1px solid;
    cursor: pointer;
}
.pause-cta-patreon {
    background: linear-gradient(135deg, #f1583a, #e35b30);
    border-color: rgba(255, 130, 90, 0.55);
    color: #fff;
    box-shadow: 0 2px 10px rgba(241, 88, 58, 0.18);
}
.pause-cta-patreon:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(241, 88, 58, 0.32);
}
.pause-cta-discord {
    background: linear-gradient(135deg, #5865f2, #4752c4);
    border-color: rgba(120, 130, 250, 0.55);
    color: #fff;
    box-shadow: 0 2px 10px rgba(88, 101, 242, 0.18);
}
.pause-cta-discord:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(88, 101, 242, 0.32);
}
.pause-community-cta:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

.pause-settings {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 8px;
}
.pause-footer {
    display: flex;
    gap: 8px;
    /* Sticky to the bottom of the scrollable overlay-box so Endgame Progress
     * + Report Bug + Quit stay visible even when the Settings tab + Lovense
     * Toys section push the content past the viewport on tall-pixel-short
     * displays (1080p, 21:9 ultrawide). The 2-col adaptive grid above was
     * authored before pause tabs split Audio/Display/Notifications into a
     * tab panel, so its .pause-settings / .settings-row selectors stopped
     * matching (no longer direct children of .pause-content) and the
     * single-column fallback hit the same overflow it was supposed to fix.
     * Foundby:synaps97 v0.2.6.7 2026-05-22. */
    position: sticky;
    bottom: 0;
    background: linear-gradient(180deg, transparent, var(--bg-deep) 16px);
    padding: 18px 0 4px;
    margin-top: -6px;
    z-index: 3;
}

/* ── Lovense Toys section (Patreon-gated, injected by lovenseSettings.js) ── */
.pause-lovense {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 8px;
}
.pause-lovense .settings-header-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 4px 0 2px;
}
.pause-lovense .settings-header {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text);
    margin: 0;
}
.pause-lovense .settings-badge {
    font-size: 9px;
    padding: 2px 8px;
    border-radius: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 700;
}
.pause-lovense .settings-badge-patreon {
    color: #ff8aa8;
    background: rgba(255, 138, 168, 0.12);
    border: 1px solid rgba(255, 138, 168, 0.3);
}
.lovense-status-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 0;
    font-size: 11px;
}
.lovense-status-label {
    color: var(--text-dim);
    min-width: 80px;
}
.lovense-status-value {
    font-weight: 600;
    flex: 1;
}
.lovense-status-on  { color: #5cd89c; }
.lovense-status-off { color: var(--text-faint); }

.lovense-actions {
    display: flex;
    gap: 8px;
    margin-bottom: 4px;
}
.btn-lovense-action {
    flex: 1;
    height: 30px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 6px;
    color: var(--text-dim);
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s ease;
}
.btn-lovense-action:hover {
    border-color: var(--border-glow);
    color: var(--text);
}
.btn-lovense-danger {
    border-color: rgba(200, 80, 80, 0.25);
}
.btn-lovense-danger:hover {
    border-color: rgba(200, 80, 80, 0.55);
    color: var(--red);
}

/* ── QR pairing modal ── */
.overlay-lovense-qr {
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.78);
    z-index: var(--z-image-viewer); /* above pause overlay */
}
.lovense-qr-box {
    max-width: 400px;
    width: 92%;
    padding: 20px;
}
.lovense-qr-body {
    padding: 12px 4px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    align-items: center;
    text-align: center;
}
.lovense-qr-instructions {
    font-size: 12px;
    color: var(--text-dim);
    line-height: 1.5;
    margin: 0;
}
.lovense-qr-image-wrap {
    position: relative;
    width: 260px;
    height: 260px;
    background: rgba(10, 8, 18, 0.6);
    border: 1px solid var(--border);
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-faint);
    font-size: 11px;
    flex-direction: column;
    gap: 10px;
}
.lovense-qr-image {
    width: 240px;
    height: 240px;
    object-fit: contain;
    border-radius: 8px;
    background: #fff;
    padding: 8px;
}
.lovense-qr-code {
    position: absolute;
    bottom: 6px;
    font-size: 10px;
    color: var(--text-faint);
    font-family: monospace;
}
.lovense-qr-spinner {
    width: 22px;
    height: 22px;
    border: 2px solid rgba(255, 138, 168, 0.25);
    border-top-color: #ff8aa8;
    border-radius: 50%;
    animation: lovense-spin 0.8s linear infinite;
}
@keyframes lovense-spin {
    to { transform: rotate(360deg); }
}
.lovense-qr-note {
    font-size: 10px;
    color: var(--text-faint);
    margin: 0;
    line-height: 1.4;
}
.lovense-qr-error {
    font-size: 11px;
    color: var(--red);
    margin: 0;
    min-height: 14px;
}

/* ── 2-column pause overlay layout when Toys section is injected ──
 *
 * The Phase 2b Toys section adds a full sub-panel (status, 3 action
 * buttons, intensity slider, 2 category toggles) which pushes the
 * stacked pause overlay past the 85vh cap on 1080p monitors — bottom
 * of the box (Report Bug + Quit) gets cut off.
 *
 * Fix: when .pause-lovense is present (Patreon only — free builds
 * don't inject the section, so they keep the narrow single-column
 * layout), widen the overlay box to 760px and split .pause-content
 * into a 2-column grid. Save slots / export-import / dividers /
 * footer still span both columns. Settings sliders + misc toggles
 * sit in col 1. Toys section sits in col 2, aligned to the top.
 *
 * :has() guard means this is a one-off CSS-only adaptation with
 * no JS coordination — if the section is ever removed or conditionally
 * hidden, the layout automatically falls back to single-column.
 */
/* Audit D37: was 900px which clipped iPad Portrait (768-899 → single-column,
   no 2-col on a clearly tablet-sized device). Lowered to 768px so iPad and
   small tablets get the 2-col layout. */
@media (min-width: 768px) {
    .pause-box:has(.pause-lovense) {
        max-width: 760px;
    }
    .pause-content:has(> .pause-lovense) {
        display: grid;
        grid-template-columns: 1fr 1fr;
        column-gap: 28px;
        row-gap: 4px;
        grid-auto-flow: row dense;
    }
    /* Default: every direct child spans both columns (save slots,
     * pause-secondary, dividers, footer). Specific classes below
     * override this to sit in col 1 or col 2. */
    .pause-content:has(> .pause-lovense) > * {
        grid-column: 1 / -1;
    }
    .pause-content:has(> .pause-lovense) > .pause-settings,
    .pause-content:has(> .pause-lovense) > .settings-row {
        grid-column: 1;
    }
    .pause-content:has(> .pause-lovense) > .pause-lovense {
        /* Span enough rows of col 2 to sit alongside pause-settings
         * + the 4 loose settings-row children (reduce-motion,
         * scene-mode, image-voting, language). grid-auto-flow: dense
         * backfills the col 2 gap from those rows. align-self: start
         * anchors it to the top of its row block so the Toys header
         * aligns with BGM Volume on the left. */
        grid-column: 2;
        grid-row: span 5;
        align-self: start;
    }
    /* Hide the divider that sits at the top of .pause-lovense (part
     * of its own markup) when in 2-column mode — it's visually weird
     * to have a horizontal rule at the top of col 2 where there's
     * nothing above it. The outer grid-column gap already provides
     * enough visual separation. */
    .pause-content:has(> .pause-lovense) > .pause-lovense > .panel-divider:first-child {
        display: none;
    }
}

/* Settings rows (shared) */
.settings-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
}
/* Text label only — exclude the inner .toggle-switch label so toggles
   don't get stretched to 80px wide. */
.settings-row > label:not(.toggle-switch) {
    font-size: 11px;
    color: var(--text-dim);
    /* Long labels (Cloud Save Sync + hint) must SHRINK/wrap instead of
       pushing the toggle out of the narrow menu panel. The old block set
       min-width:0 then overrode itself with min-width:80px + flex-shrink:0
       (BUG_PATTERNS §6 class), so the label never shrank. 80px floor keeps
       short labels readable; no flex-grow, so rows that already fit keep
       their exact current layout (slider rows etc. untouched). */
    flex: 0 1 auto;
    min-width: 80px;
    line-height: 1.25;
}
/* Sub-line hint inside a settings label (e.g. "no videos", "hides sidebars on images"). */
.settings-row .settings-hint {
    display: block;
    font-size: 9px;
    font-weight: 400;
    color: var(--text-faint);
    opacity: 0.75;
    letter-spacing: 0.02em;
    margin-top: 1px;
    text-transform: none;
}
/* Right-align toggles in their row so all controls line up on the right edge. */
.settings-row > .toggle-switch {
    margin-left: auto;
}

/* ============================================
   Cloud Save Sync — settings block (menu + pause)
   ============================================ */
.cloudsync-block { display: block; }
.cloudsync-block.hidden { display: none; }
.cloudsync-status {
    font-size: 10px;
    line-height: 1.4;
    color: var(--text-faint);
    padding: 2px 0 6px 2px;
    letter-spacing: 0.02em;
}
.cloudsync-status-off { color: var(--text-faint); }
.cloudsync-status-ok { color: var(--energy); }
.cloudsync-status-error { color: var(--accent); }
.cloudsync-panel {
    padding: 8px 10px 10px;
    margin: 0 0 8px;
    border: 1px solid rgba(180, 160, 210, 0.2);
    border-radius: 8px;
    background: rgba(40, 28, 62, 0.35);
}
.cloudsync-code-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}
.cloudsync-code-label {
    font-size: 10px;
    color: var(--text-dim);
    flex-shrink: 0;
}
.cloudsync-code {
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 11px;
    color: var(--rose);
    background: rgba(0, 0, 0, 0.3);
    border-radius: 5px;
    padding: 3px 7px;
    word-break: break-all;
    flex: 1;
    user-select: all;
}
.cloudsync-code-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 6px;
}
.cloudsync-mini-btn {
    font-size: 10px;
    padding: 5px 10px;
    min-height: 28px;
    border: 1px solid rgba(228, 140, 184, 0.4);
    border-radius: 6px;
    background: rgba(50, 34, 76, 0.5);
    color: var(--text-body);
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}
.cloudsync-mini-btn:hover:not(:disabled) {
    background: rgba(228, 140, 184, 0.18);
    border-color: var(--border-glow);
}
.cloudsync-mini-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.cloudsync-code-warn {
    font-size: 9px;
    color: var(--text-faint);
    line-height: 1.45;
    margin: 0 0 10px;
}
.cloudsync-adopt { margin: 8px 0 6px; }
.cloudsync-adopt-label {
    display: block;
    font-size: 10px;
    color: var(--text-dim);
    margin-bottom: 4px;
}
.cloudsync-adopt-input {
    width: 100%;
    box-sizing: border-box;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 11px;
    padding: 7px 8px;
    border: 1px solid rgba(180, 160, 210, 0.3);
    border-radius: 6px;
    background: rgba(0, 0, 0, 0.3);
    color: var(--text);
    text-transform: lowercase;
}
.cloudsync-adopt-input:focus {
    outline: none;
    border-color: var(--border-glow);
}
.cloudsync-adopt-feedback {
    font-size: 10px;
    line-height: 1.6;
    margin: 5px 0;
    min-height: 14px;
    word-break: break-word;
}
.cloudsync-adopt-feedback-error { color: var(--accent); }
.cloudsync-word {
    display: inline-block;
    padding: 1px 4px;
    border-radius: 4px;
    margin: 1px;
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.cloudsync-word-ok {
    color: var(--energy);
    background: rgba(120, 200, 140, 0.12);
}
.cloudsync-word-bad {
    color: #ff9aa8;
    background: rgba(220, 90, 90, 0.16);
    text-decoration: underline wavy;
}
.cloudsync-adopt-go { margin-top: 4px; }
.cloudsync-delete-btn {
    display: block;
    width: 100%;
    margin-top: 6px;
    font-size: 11px;
    padding: 8px 12px;
    min-height: 32px;
    border: 1px solid rgba(220, 120, 120, 0.45);
    border-radius: 6px;
    background: rgba(196, 80, 80, 0.12);
    color: #ffd0d0;
    cursor: pointer;
    transition: background 0.15s;
}
.cloudsync-delete-btn:hover { background: rgba(196, 80, 80, 0.24); }

/* Cloud Save Sync — per-slot badge + lock hint (in the save-slot rows). */
.slot-cloud-badge {
    display: inline-block;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.03em;
    padding: 1px 6px;
    border-radius: 8px;
    margin-left: 2px;
    vertical-align: middle;
    cursor: help;
}
.slot-cloud-badge[hidden] { display: none; }
.slot-cloud-synced {
    color: var(--energy);
    background: rgba(120, 200, 140, 0.14);
    border: 1px solid rgba(120, 200, 140, 0.3);
}
.slot-cloud-locked {
    color: #e0b870;
    background: rgba(224, 184, 112, 0.12);
    border: 1px solid rgba(224, 184, 112, 0.3);
}

/* GSAP-style custom slider */
.gsap-slider {
    flex: 1;
    position: relative;
    height: 20px;
    cursor: pointer;
}
.gsap-slider__native {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
    z-index: 3;
    margin: 0;
}
.gsap-slider__track {
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    height: 7px;
    transform: translateY(-50%);
    background: linear-gradient(180deg, rgba(10, 8, 20, 0.95) 0%, rgba(28, 22, 42, 0.9) 100%);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 999px;
    overflow: hidden;
    box-shadow:
        inset 0 2px 4px rgba(0, 0, 0, 0.5),
        0 1px 0 rgba(255, 255, 255, 0.04);
}
.gsap-slider__progress {
    position: absolute;
    inset: 0;
    border-radius: 999px;
    transform-origin: left center;
    background: linear-gradient(90deg, #c06898 0%, var(--rose) 55%, #f0a8cc 100%);
    box-shadow:
        0 0 10px rgba(228, 140, 184, 0.45),
        inset 0 1px 0 rgba(255, 255, 255, 0.25);
}
.gsap-slider__progress::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 999px;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.22) 0%, transparent 55%);
    pointer-events: none;
}
.gsap-slider__thumb {
    position: absolute;
    top: 50%;
    width: 13px;
    height: 13px;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 30%, #fff 0%, #f6c3da 45%, var(--rose) 100%);
    border: 1px solid rgba(255, 255, 255, 0.5);
    transform: translate(-50%, -50%);
    box-shadow:
        0 0 8px rgba(228, 140, 184, 0.55),
        0 1px 3px rgba(0, 0, 0, 0.45),
        inset 0 1px 0 rgba(255, 255, 255, 0.5);
    z-index: 2;
    pointer-events: none;
    transition: box-shadow 0.2s ease, width 0.15s ease, height 0.15s ease;
}
.gsap-slider:hover .gsap-slider__thumb {
    width: 15px;
    height: 15px;
    box-shadow:
        0 0 14px rgba(228, 140, 184, 0.75),
        0 2px 6px rgba(0, 0, 0, 0.45),
        inset 0 1px 0 rgba(255, 255, 255, 0.6);
}
.gsap-slider__marker {
    position: absolute;
    bottom: calc(100% + 2px);
    transform: translateX(-50%);
    background: var(--bg-panel);
    border: 1px solid var(--rose);
    border-radius: 4px;
    padding: 2px 6px;
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    font-weight: 600;
    color: var(--rose);
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    z-index: 4;
    box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
.gsap-slider__marker::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 4px solid transparent;
    border-top-color: var(--rose);
}

.settings-value {
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    color: var(--text-faint);
    min-width: 40px;
    text-align: right;
}

/* Journal tabs */
.journal-tabs {
    display: flex;
    border-bottom: 1px solid var(--border);
}
.journal-tab {
    flex: 1;
    padding: 10px;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-dim);
    letter-spacing: 0.5px;
    border-bottom: 2px solid transparent;
    transition: all 0.2s ease;
}
.journal-tab:hover { color: var(--text); }
.journal-tab.active {
    color: var(--rose);
    border-bottom-color: var(--rose);
}
.journal-content { padding: 16px 20px; }

/* Phone overlay */
.phone-frame {
    background: linear-gradient(180deg, var(--bg-warm), var(--bg-deep));
    border: 1px solid var(--border);
    border-radius: 14px;
    width: 100%;
    max-width: 480px;
    height: 760px;
    max-height: calc(92vh / var(--overlay-zoom, 1));
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.phone-body {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
    padding: 8px;
}
.phone-title {
    font-size: 14px;
    color: var(--rose);
    letter-spacing: 0.5px;
    flex: 1;
    text-align: center;
    font-weight: 600;
}
.phone-back-btn, .phone-close-btn {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: rgba(46, 34, 66, 0.4);
    border: none;
    color: var(--text-dim);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 16px;
    transition: all 0.2s ease;
}
.phone-back-btn:hover, .phone-close-btn:hover { color: var(--rose); background: rgba(66, 44, 96, 0.6); }

/* Phone Gallery */
.gallery-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 4px;
    padding: 4px;
}
.gallery-cell {
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: 4px;
    cursor: pointer;
}
.gallery-cell img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.2s ease;
}
.gallery-cell:hover img { transform: scale(1.05); }
.gallery-expand-overlay {
    position: fixed;
    inset: 0;
    background: rgba(4, 2, 8, 0.92);
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    animation: overlaySlideIn 0.2s ease both;
}
.gallery-expand-img {
    max-width: 90vw;
    max-height: 80vh;
    object-fit: contain;
    border-radius: 8px;
    box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6);
}
.gallery-expand-name {
    margin-top: 12px;
    font-family: 'DM Sans', sans-serif;
    font-size: 12px;
    color: var(--text-faint);
    text-transform: capitalize;
}

/* Phone app grid */
.phone-app-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    padding: 16px;
}
/* Narrow phones (<400px) can't fit 4 cells per row without clipping labels.
   Drop to 3 cols and tighten cell padding. */
@media (max-width: 400px) {
    .phone-app-grid {
        grid-template-columns: repeat(3, 1fr);
        gap: 10px;
        padding: 12px;
    }
    .phone-app-cell, .phone-app-btn { padding: 6px; }
    .phone-app-label, .phone-app-name {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 100%;
    }
}
.phone-app-cell, .phone-app-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 8px;
    border-radius: 10px;
    background: rgba(20, 15, 30, 0.4);
    border: 1px solid transparent;
    color: var(--text);
    font-size: 10px;
    cursor: pointer;
    transition: all 0.2s ease;
}
.phone-app-btn:hover { border-color: var(--border-glow); background: rgba(40, 30, 60, 0.4); }
.phone-app-icon { font-size: 24px; position: relative; }
.phone-app-label, .phone-app-name { font-size: 10px; color: var(--text-dim); }

.phone-app-cell, .phone-app-btn { overflow: visible; }
.phone-app-badge {
    position: absolute;
    top: -6px;
    right: -6px;
    background: #22c55e;
    color: white;
    font-size: 10px;
    font-weight: 700;
    min-width: 16px;
    height: 16px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 4px;
    animation: badgePulse 0.3s ease-out;
}
@keyframes badgePulse {
    from { transform: scale(0); }
    50% { transform: scale(1.2); }
    to { transform: scale(1); }
}

.phone-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-warm);
    border-radius: 14px 14px 0 0;
}
.phone-header h2 {
    font-size: 14px;
    color: var(--rose);
    letter-spacing: 0.5px;
    flex: 1;
    text-align: center;
}
.btn-phone-nav {
    /* Audit D29: was 28x28 (sub-WCAG hit target). */
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: rgba(46, 34, 66, 0.4);
    color: var(--text);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s ease;
}
.btn-phone-nav:hover { color: var(--rose); background: rgba(46, 34, 66, 0.6); }
.btn-phone-nav:focus-visible { outline: 2px solid var(--rose); outline-offset: 2px; }

.phone-contact-list {
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.phone-contact-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.2s ease;
}
.phone-contact-row:hover { background: rgba(40, 30, 60, 0.4); }

.phone-chat-view { padding: 12px; }
.phone-chat-view.hidden { display: none; }
.phone-chat-messages {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 400px;
    overflow-y: auto;
    margin-bottom: 12px;
}
.phone-chat-replies {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* Shop grid (legacy stub — see section 24 for full shop styles) */

/* Wardrobe */
.wardrobe-presets {
    display: flex;
    gap: 6px;
    padding: 8px 16px;
    border-bottom: 1px solid var(--border);
}
.wardrobe-tabs {
    display: flex;
    border-bottom: 1px solid var(--border);
    padding: 0 16px;
}
.wardrobe-content { padding: 16px; }

/* Achievement grid */
.achievement-categories {
    display: flex;
    flex-shrink: 0;
    flex-wrap: wrap;
    padding: 12px 16px;
    gap: 10px;
    border-bottom: 1px solid var(--border);
}
.achievement-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    grid-auto-rows: minmax(140px, auto);
    align-content: start;
    gap: 10px;
    padding: 16px;
}

/* Gallery */
.gallery-box { max-width: 75vw; max-height: calc(80vh / var(--overlay-zoom, 1)); display: flex; flex-direction: column; overflow: hidden; }
.gallery-frame { display: flex; flex-direction: column; overflow: hidden; flex: 1; position: relative; }
.gallery-header {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 16px; border-bottom: 1px solid var(--border);
}
.gallery-title { font-size: 14px; font-weight: 600; color: var(--rose); flex: 1; }
.gallery-count { font-size: 11px; color: var(--text-faint); }
.gallery-close-btn {
    width: 36px; height: 36px; border-radius: 50%;
    background: rgba(46,34,66,0.5); border: 1px solid rgba(255,255,255,0.08);
    color: var(--text-dim); font-size: 20px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: all 0.2s ease; flex-shrink: 0;
}
.gallery-close-btn:hover { background: rgba(200, 80, 80, 0.3); color: var(--text); border-color: rgba(200,80,80,0.3); }
.gallery-tabs {
    display: flex; padding: 8px 12px; gap: 4px;
    border-bottom: 1px solid var(--border); overflow-x: auto; flex-shrink: 0;
}
.gallery-tab {
    padding: 4px 10px; border-radius: 6px; font-size: 11px; font-weight: 500;
    background: transparent; border: 1px solid transparent; color: var(--text-faint); cursor: pointer;
    white-space: nowrap; transition: all 0.2s ease;
}
.gallery-tab:hover { color: var(--text); border-color: var(--border); }
.gallery-tab-active { color: var(--rose); border-color: var(--rose); background: rgba(200,100,160,0.1); }
.gallery-grid-scroll {
    overflow-y: auto; flex: 1;
}
.gallery-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 8px; padding: 12px;
}
.gallery-cell {
    min-height: 120px; border-radius: 8px; overflow: hidden;
    background: rgba(30, 28, 45, 0.3);
    border: 1px solid rgba(46,34,66,0.3); cursor: pointer; transition: all 0.2s ease;
}
.gallery-cell:hover { border-color: var(--border-glow); transform: translateY(-2px); }
.gallery-cell img.gallery-thumb {
    width: 100%; height: 90px; object-fit: cover; display: block;
}
.gallery-cell-name {
    font-size: 9px; color: var(--text-faint); padding: 4px 6px;
    text-overflow: ellipsis; overflow: hidden; white-space: nowrap;
}
.gallery-cell-new { border-color: rgba(228, 120, 184, 0.5); box-shadow: 0 0 8px rgba(228, 120, 184, 0.2); }
.gallery-empty {
    grid-column: 1/-1;
    text-align: center;
    padding: 48px 24px;
    color: var(--text-dim);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    max-width: 460px;
    margin: 0 auto;
}
.gallery-empty-icon {
    font-size: 48px;
    opacity: 0.4;
    margin-bottom: 4px;
}
.gallery-empty-title {
    font-size: 16px;
    font-weight: 600;
    color: var(--text);
    letter-spacing: 0.3px;
}
.gallery-empty-hint {
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-dim);
    font-family: 'Crimson Pro', serif;
    font-style: italic;
}

/* Video cells: play-icon overlay on the static-PNG thumbnail. */
.gallery-cell { position: relative; }
.gallery-cell-video { border-color: rgba(140, 100, 200, 0.4); }
.gallery-cell-play {
    position: absolute; top: 6px; right: 6px;
    width: 22px; height: 22px; border-radius: 50%;
    background: rgba(20, 18, 30, 0.78); color: rgba(230, 220, 245, 0.95);
    display: flex; align-items: center; justify-content: center;
    font-size: 10px; line-height: 1; pointer-events: none;
    box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.gallery-tab-videos { color: rgba(220, 200, 245, 0.85); }
.gallery-tab-videos.gallery-tab-active { color: rgba(220, 200, 245, 1); border-color: rgba(140, 100, 200, 0.6); background: rgba(110, 80, 180, 0.12); }

/* Variant toggles in the fullscreen gallery viewer. */
.gallery-viewer-variant-toggles {
    display: flex; gap: 12px; margin-top: 10px;
    padding: 8px 14px; border-radius: 999px;
    background: rgba(20, 18, 30, 0.55); backdrop-filter: blur(4px);
    font-family: 'DM Mono', monospace; font-size: 11px;
    color: rgba(230, 220, 245, 0.9);
}
.gallery-viewer-variant-toggle {
    display: flex; align-items: center; gap: 5px;
    cursor: pointer; user-select: none;
    transition: opacity 0.15s ease;
}
.gallery-viewer-variant-toggle input[type="checkbox"] {
    accent-color: rgba(228, 120, 184, 0.95);
    cursor: pointer;
}
.gallery-viewer-variant-toggle.is-disabled {
    opacity: 0.35; cursor: not-allowed;
}
.gallery-viewer-variant-toggle.is-disabled input { cursor: not-allowed; }
.gallery-viewer-variant-toggle:hover:not(.is-disabled) { color: rgba(255, 240, 250, 1); }
/* Fullscreen viewer */
.gallery-viewer {
    position: fixed; inset: 0; z-index: var(--z-vignette); background: rgba(0,0,0,0.9);
    display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.gallery-viewer-media { max-width: 90vw; max-height: 90vh; object-fit: contain; border-radius: 8px; }
/* § 106 playback frame variant (see image-modal note) */
iframe.gallery-viewer-media { width: min(90vw, 1024px); height: min(75vh, 1024px); border: 0; background: transparent; }
.gallery-viewer-media-wrap { position: relative; display: flex; flex-direction: column; align-items: center; }
.gallery-viewer-label {
    margin-top: 8px; font-size: 11px; color: rgba(255,255,255,0.5);
    font-family: 'DM Mono', monospace; letter-spacing: 0.5px;
}
.gallery-viewer-close {
    position: absolute; top: 16px; right: 16px; width: 40px; height: 40px;
    border-radius: 50%; background: rgba(200,60,60,0.3); border: 1px solid rgba(200,60,60,0.4);
    color: rgba(220,80,80,0.9); font-size: 22px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: all 0.2s ease;
}
.gallery-viewer-close:hover { background: rgba(200,60,60,0.5); color: #fff; }
.gallery-viewer-nav {
    position: absolute; top: 50%; transform: translateY(-50%);
    width: 44px; height: 44px; border-radius: 50%;
    background: rgba(0,0,0,0.5); border: 1px solid rgba(255,255,255,0.15);
    color: white; font-size: 28px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: all 0.2s ease;
}
.gallery-viewer-nav:hover { background: rgba(228,140,184,0.3); border-color: rgba(228,140,184,0.4); }
.gallery-viewer-prev { left: 16px; }
.gallery-viewer-next { right: 16px; }

/* Journal content */
.journal-box { max-width: 600px; max-height: calc(80vh / var(--overlay-zoom, 1)); display: flex; flex-direction: column; }
.journal-content { flex: 1; overflow-y: auto; padding: 12px 16px; }
.journal-category-header {
    font-family: 'Crimson Pro', serif;
    font-size: 13px;
    font-weight: 600;
    color: var(--rose);
    text-transform: uppercase;
    letter-spacing: 2px;
    margin: 16px 0 8px;
    padding-bottom: 4px;
    border-bottom: 1px solid rgba(228, 140, 184, 0.15);
}
.journal-category-header:first-child { margin-top: 0; }
.journal-progress-shortcut { margin: 0 0 12px; }
.journal-progress-shortcut-btn {
    width: 100%;
    padding: 8px 12px;
    background: rgba(228, 140, 184, 0.08);
    border: 1px solid rgba(228, 140, 184, 0.25);
    border-radius: 8px;
    color: var(--rose);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s, border-color .15s;
}
.journal-progress-shortcut-btn:hover {
    background: rgba(228, 140, 184, 0.18);
    border-color: rgba(228, 140, 184, 0.5);
}
/* Note: legacy .journal-progress-card-* rules removed. Journal Progress tab
 * now renders via the shared progress-card component (.completion-card-*).
 * Phase 5 of the storylines consolidation, 2026-05-20. */
.journal-stat-row {
    display: flex; justify-content: space-between; padding: 8px 0;
    border-bottom: 1px solid rgba(46,34,66,0.3); font-size: 12px; color: var(--text-dim);
}
.journal-stat-val { color: var(--rose); font-weight: 600; }

/* Achievement content */
.achievement-box { max-width: 600px; max-height: calc(80vh / var(--overlay-zoom, 1)); display: flex; flex-direction: column; }
.achievement-cat-btn {
    flex-shrink: 0;
    padding: 10px 20px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    background: rgba(20, 15, 30, 0.5);
    border: 1px solid rgba(140, 100, 180, 0.25);
    color: var(--text-dim);
    cursor: pointer;
    white-space: nowrap;
    transition: all 0.18s ease;
    letter-spacing: 0.2px;
}
.achievement-cat-btn:hover {
    color: var(--text);
    border-color: rgba(228, 140, 184, 0.5);
    background: rgba(28, 22, 42, 0.7);
}
.achievement-cat-btn.active {
    color: var(--rose);
    border-color: var(--rose);
    background: rgba(200, 100, 160, 0.15);
    box-shadow: 0 0 12px rgba(228, 140, 184, 0.2);
}
.achievement-progress-header { padding: 12px 16px; font-size: 12px; color: var(--text-dim); }
.achievement-progress-bar { height: 6px; background: rgba(46,34,66,0.4); border-radius: 3px; overflow: hidden; margin-top: 6px; }
.achievement-progress-fill { height: 100%; background: var(--orchid); border-radius: 3px; }
#achievement-grid { padding: 0 16px 16px; overflow-y: auto; flex: 1; }
/* v1 .achievement-card / .achievement-icon / .achievement-name styles removed.
   Replaced by the grid-card design at line ~6366 (display:grid container with
   centered icon-on-top, title + desc below). The two definitions used to
   conflict and made cards look broken. */

/* History */
.history-box { max-width: 600px; max-height: calc(80vh / var(--overlay-zoom, 1)); display: flex; flex-direction: column; }
.history-content {
    padding: 16px 20px;
    max-height: 70vh;
    overflow-y: auto;
}

/* Bug report */
.bugreport-form { padding: 16px 20px; }
.bugreport-status {
    font-size: 12px;
    padding: 4px 0;
    min-height: 20px;
}
.bugreport-status.success { color: var(--green); }
.bugreport-status.error { color: var(--red); }


/* First-time UI tooltips */
.first-time-tip {
    position: fixed;
    max-width: 260px;
    padding: 10px 14px;
    background: rgba(20, 12, 35, 0.95);
    border: 1px solid var(--rose);
    border-radius: 10px;
    box-shadow: 0 4px 24px rgba(228, 140, 184, 0.15), 0 0 40px rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(8px);
    z-index: 500;
    animation: tip-in 0.4s var(--ease-bounce) both;
    /* Readability scale */
    transform: scale(var(--overlay-zoom, 1));
    transform-origin: center top;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.first-time-tip-text {
    font-family: 'DM Sans', sans-serif;
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-body);
}
.first-time-tip-close {
    align-self: flex-end;
    font-family: 'DM Sans', sans-serif;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--rose);
    background: none;
    border: 1px solid rgba(228, 140, 184, 0.3);
    border-radius: 4px;
    padding: 3px 12px;
    cursor: pointer;
    transition: background 0.2s;
}
.first-time-tip-close:hover { background: rgba(228, 140, 184, 0.1); }
.first-time-tip.fade-out { animation: notif-out 0.4s ease both; }
@keyframes tip-in {
    from { opacity: 0; transform: translateY(-6px) scale(0.95); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

/* ============================================
   15. NOTIFICATIONS + TOASTS
   ============================================ */
.stat-notifications {
    position: fixed;
    top: 60px;
    left: 260px;
    right: 240px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    pointer-events: none;
    z-index: 300;
}

.stat-notification {
    font-family: 'DM Sans', sans-serif;
    font-size: 13px;
    font-weight: 600;
    padding: 4px 14px;
    border-radius: 6px;
    background: rgba(20, 15, 30, 0.9);
    border: 1px solid var(--border);
    backdrop-filter: blur(4px);
    animation: notif-in 0.3s var(--ease-bounce) both;
    white-space: nowrap;
}

/* Show-Don't-Tell: narrative flavor text before stat numbers */
.stat-flavor-text {
    font-family: 'Crimson Pro', serif;
    font-style: italic;
    font-size: 14px;
    color: var(--text-dim);
    padding: 3px 16px;
    animation: flavor-in 0.5s ease both;
    white-space: nowrap;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
}
.stat-flavor-text.fade-out {
    animation: notif-out 0.6s ease both;
}
@keyframes flavor-in {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 0.85; transform: translateY(0); }
}

.stat-notification.fade-out {
    animation: notif-out 0.5s ease both;
}

@keyframes notif-in {
    from { opacity: 0; transform: translateY(-8px) scale(0.9); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes notif-out {
    from { opacity: 1; transform: translateY(0); }
    to { opacity: 0; transform: translateY(-12px); }
}

.notif-energy { color: var(--energy); border-color: rgba(92, 216, 156, 0.2); }
.notif-arousal { color: var(--arousal); border-color: rgba(224, 104, 120, 0.2); }
.notif-fem { color: var(--fem); border-color: rgba(228, 120, 184, 0.2); }
.notif-sub { color: var(--sub); border-color: rgba(168, 128, 224, 0.2); }
.notif-money { color: var(--gold); border-color: rgba(232, 200, 96, 0.2); }
.notif-shame { color: var(--shame); border-color: rgba(192, 144, 96, 0.2); }
.notif-error { color: #ff6b6b; border-color: rgba(255, 107, 107, 0.3); white-space: normal; max-width: 400px; }

/* Inline stat deltas — bigger, stat-coloured, with glow for readability */
.stat-delta-inline {
    position: absolute;
    right: -2px;
    top: -10px;
    font-family: 'DM Sans', 'DM Mono', monospace;
    font-size: 15px;
    font-weight: 800;
    letter-spacing: 0.3px;
    pointer-events: none;
    /* Soft outline so the number stays legible against any bar fill */
    text-shadow:
        0 0 2px rgba(0,0,0,0.85),
        0 0 6px rgba(0,0,0,0.6),
        0 2px 4px rgba(0,0,0,0.45);
    /* Animation driven by GSAP */
}
/* Generic fallback (covers stats without a specific colour mapping) */
.stat-delta-inline-positive { color: var(--green); }
.stat-delta-inline-negative { color: var(--red); }
/* Stat-specific colours — override the generic pos/neg when both classes
   apply (CSS later rule wins at equal specificity, but these are equal,
   so stat class must be added LAST on the element — handled in JS). */
.stat-delta-inline.delta-fem     { color: var(--fem);     text-shadow: 0 0 2px rgba(0,0,0,0.85), 0 0 10px rgba(228,120,184,0.55), 0 2px 4px rgba(0,0,0,0.45); }
.stat-delta-inline.delta-sub     { color: var(--sub);     text-shadow: 0 0 2px rgba(0,0,0,0.85), 0 0 10px rgba(168,128,224,0.55), 0 2px 4px rgba(0,0,0,0.45); }
.stat-delta-inline.delta-arousal { color: var(--arousal); text-shadow: 0 0 2px rgba(0,0,0,0.85), 0 0 10px rgba(224,104,120,0.55), 0 2px 4px rgba(0,0,0,0.45); }
.stat-delta-inline.delta-energy  { color: var(--energy);  text-shadow: 0 0 2px rgba(0,0,0,0.85), 0 0 10px rgba(92,216,156,0.55),  0 2px 4px rgba(0,0,0,0.45); }
.stat-delta-inline.delta-shame   { color: var(--shame);   text-shadow: 0 0 2px rgba(0,0,0,0.85), 0 0 10px rgba(192,144,96,0.55),  0 2px 4px rgba(0,0,0,0.45); }
.stat-delta-inline.delta-money   { color: var(--gold);    text-shadow: 0 0 2px rgba(0,0,0,0.85), 0 0 10px rgba(232,200,96,0.55),  0 2px 4px rgba(0,0,0,0.45); }
/* Negative deltas get the stat colour but desaturated — still readable as "this stat lost" */
.stat-delta-inline-negative.delta-fem,
.stat-delta-inline-negative.delta-sub,
.stat-delta-inline-negative.delta-arousal,
.stat-delta-inline-negative.delta-energy,
.stat-delta-inline-negative.delta-shame,
.stat-delta-inline-negative.delta-money {
    filter: saturate(0.65) brightness(0.9);
}

/* Stat glow on change */
.stat-glow-positive {
    animation: stat-glow-pos 0.6s ease both;
}
.stat-glow-negative {
    animation: stat-glow-neg 0.6s ease both;
}
@keyframes stat-glow-pos {
    0% { box-shadow: inset 0 0 12px rgba(92, 216, 156, 0.4); }
    100% { box-shadow: none; }
}
@keyframes stat-glow-neg {
    0% { box-shadow: inset 0 0 12px rgba(224, 104, 120, 0.4); }
    100% { box-shadow: none; }
}
/* Fem tier shimmer at 25/50/75 milestones */
.fem-tier-shimmer {
    animation: fem-shimmer 1.2s ease both;
}
@keyframes fem-shimmer {
    0% { box-shadow: inset 0 0 20px rgba(228, 120, 184, 0.6), 0 0 12px rgba(228, 120, 184, 0.3); }
    50% { box-shadow: inset 0 0 30px rgba(228, 120, 184, 0.3), 0 0 20px rgba(228, 120, 184, 0.15); }
    100% { box-shadow: none; }
}

/* Shame blush on character panel at 50/75/90 */
.shame-blush {
    animation: shame-blush 1.5s ease both;
}
@keyframes shame-blush {
    0% { box-shadow: inset 0 0 40px rgba(224, 104, 120, 0.2); }
    100% { box-shadow: none; }
}

.stat-glow-arousal { animation: stat-glow-arousal 0.6s ease both; }
@keyframes stat-glow-arousal {
    0% { box-shadow: inset 0 0 14px rgba(228, 120, 184, 0.5); }
    100% { box-shadow: none; }
}

/* Stat tooltips */
.stat-tooltip {
    position: fixed;
    /* Readability scale composed with the centering translateX(-50%). */
    transform: translateX(-50%) scale(var(--overlay-zoom, 1));
    transform-origin: center top;
    max-width: 280px;
    padding: 8px 12px;
    font-size: 11px;
    line-height: 1.4;
    white-space: pre-line;
    color: var(--text);
    background: rgba(20, 15, 30, 0.95);
    border: 1px solid var(--border-glow);
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
    z-index: var(--z-modal);
    pointer-events: none;
    contain: layout style;
    will-change: transform, opacity;
    animation: tooltip-in 0.15s ease both;
    white-space: pre-line;
}

@keyframes tooltip-in {
    from { opacity: 0; transform: translateX(-50%) translateY(-4px) scale(var(--overlay-zoom, 1)); }
    to { opacity: 1; transform: translateX(-50%) translateY(0) scale(var(--overlay-zoom, 1)); }
}

/* Achievement toast */
.achievement-toast {
    position: fixed;
    top: 16px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 20px;
    background: linear-gradient(135deg, rgba(40, 30, 60, 0.95), rgba(60, 40, 80, 0.95));
    border: 1px solid var(--gold);
    border-radius: 10px;
    box-shadow: 0 4px 24px rgba(232, 200, 96, 0.15);
    z-index: 400;
    animation: toast-in 0.4s var(--ease-bounce) both;
    backdrop-filter: blur(var(--blur-sm));
}
.achievement-toast.hidden { display: none; }
.achievement-toast.fade-out { animation: toast-out 0.4s ease both; }

@keyframes toast-in {
    from { opacity: 0; transform: translateX(-50%) translateY(-20px); }
    to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
@keyframes toast-out {
    from { opacity: 1; transform: translateX(-50%) translateY(0); }
    to { opacity: 0; transform: translateX(-50%) translateY(-16px); }
}

/* Global toast (purchases, dares, equips) */
.pno-toast {
    position: fixed;
    bottom: 24px;
    right: 24px;
    background: rgba(20, 15, 35, 0.95);
    border: 1px solid rgba(196, 112, 224, 0.3);
    color: var(--text);
    padding: 10px 20px;
    border-radius: 8px;
    font-family: 'DM Sans', sans-serif;
    font-size: 13px;
    font-weight: 500;
    z-index: 9999;
    pointer-events: none;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    animation: pno-toast-in 0.4s var(--ease-bounce) both;
    max-width: 320px;
    /* Readability scaling — applied AFTER the entry animation finishes;
       during animation the keyframes own `transform` so toast pops to its
       slider-scaled size at the end. Acceptable since toasts are short-lived. */
    transform: scale(var(--overlay-zoom, 1));
    transform-origin: bottom right;
}
.pno-toast.fade-out { animation: pno-toast-out 0.4s ease both; }
.pno-toast.toast-info { border-color: rgba(92, 216, 156, 0.3); }
.pno-toast.toast-warn { border-color: rgba(232, 200, 96, 0.3); color: var(--gold); }

/* Audit D04: Achievement-unlock toast. Distinct from regular toast — gold
   trophy icon, larger, multi-line, dismissible via click-into-overlay.
   Bottom-right stack so multiple unlocks in the same tick don't overlap.
   pointer-events: auto so click-to-open works. */
.pno-achievement-toast {
    position: fixed;
    bottom: 24px;
    right: 24px;
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 280px;
    max-width: 360px;
    padding: 14px 18px;
    background: linear-gradient(135deg, rgba(40, 28, 14, 0.96), rgba(20, 15, 30, 0.96));
    border: 1px solid rgba(232, 200, 96, 0.55);
    border-radius: 10px;
    color: var(--text);
    font-family: 'DM Sans', sans-serif;
    z-index: 9999;
    cursor: pointer;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: 0 6px 24px rgba(0,0,0,0.55), 0 0 32px rgba(232, 200, 96, 0.18);
    animation: pno-toast-in 0.5s var(--ease-bounce) both;
    transform-origin: bottom right;
}
.pno-achievement-toast:hover {
    border-color: rgba(232, 200, 96, 0.85);
    box-shadow: 0 6px 28px rgba(0,0,0,0.6), 0 0 40px rgba(232, 200, 96, 0.28);
}
.pno-achievement-toast.fade-out { animation: pno-toast-out 0.4s ease both; }
.pno-achievement-toast-icon {
    font-size: 32px;
    flex-shrink: 0;
    line-height: 1;
    filter: drop-shadow(0 2px 4px rgba(232, 200, 96, 0.5));
}
.pno-achievement-toast-body { flex: 1; min-width: 0; }
.pno-achievement-toast-eyebrow {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    color: var(--gold);
    font-weight: 700;
    margin-bottom: 2px;
}
.pno-achievement-toast-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--text);
    line-height: 1.3;
}
.pno-achievement-toast-desc {
    font-size: 12px;
    color: var(--text-dim);
    line-height: 1.4;
    margin-top: 4px;
}
/* Stack multiple unlocks. Each new toast nudges the previous one up. */
.pno-achievement-toast ~ .pno-achievement-toast { bottom: calc(24px + 90px); }
.pno-achievement-toast ~ .pno-achievement-toast ~ .pno-achievement-toast { bottom: calc(24px + 180px); }
@keyframes pno-toast-in {
    from { opacity: 0; transform: translateY(16px) scale(0.95); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes pno-toast-out {
    from { opacity: 1; transform: translateY(0); }
    to { opacity: 0; transform: translateY(-12px); }
}

.toast-icon {
    width: 32px;
    height: 32px;
    background: rgba(232, 200, 96, 0.15);
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
}
.toast-title {
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--gold);
    display: block;
}
.toast-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    display: block;
}

/* SMS notification (slide-in) */
.sms-notification {
    position: fixed;
    top: 60px;
    right: 12px;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    background: linear-gradient(135deg, rgba(40, 30, 60, 0.95), rgba(30, 20, 50, 0.95));
    border: 1px solid var(--border-glow);
    border-radius: 10px;
    cursor: pointer;
    z-index: 350;
    max-width: 280px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
    transform: translateX(340px);
    transition: transform 0.35s var(--ease-out);
    backdrop-filter: blur(var(--blur-sm));
}
.sms-notification.hidden { display: none; }
.sms-notification.visible, .sms-notification.sms-notif-show { transform: translateX(0); }
.sms-notification.fade-out, .sms-notification.sms-notif-hide {
    transform: translateX(340px);
    transition: transform 0.35s ease;
}

.sms-notif-icon { color: var(--rose); flex-shrink: 0; }
.sms-notif-avatar {
    width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: 15px; font-weight: 700; color: #fff;
    box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
}
.sms-notif-avatar.sms-avatar-img {
    background: transparent !important;
    overflow: hidden;
}
.sms-notif-avatar.sms-avatar-img img {
    width: 100%; height: 100%; object-fit: cover; border-radius: 50%;
}
.sms-notif-content { min-width: 0; flex: 1; }
.sms-notif-sender, .sms-notif-name { font-size: 12px; font-weight: 600; color: var(--rose); display: block; }
.sms-notif-preview {
    font-size: 11px;
    color: var(--text-dim);
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-top: 1px;
}
/* NPC-colored left accent on SMS notification cards */
.sms-notification[data-npc="master"] { border-left: 3px solid #9b59b6; }
.sms-notification[data-npc="girlfriend"] { border-left: 3px solid #e88cb8; }
.sms-notification[data-npc="sugar"] { border-left: 3px solid #c89620; }
.sms-notification[data-npc="bully"] { border-left: 3px solid #c83232; }
.sms-notification[data-npc="fan"] { border-left: 3px solid #6e46aa; }
.sms-notification[data-npc="dating"] { border-left: 3px solid #c8466e; }
.sms-notification[data-npc="vip"] { border-left: 3px solid #aa8228; }


/* ============================================
   16. IMAGE MODAL
   ============================================ */
.image-modal {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    background: rgba(8, 6, 12, 0.95);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    backdrop-filter: blur(var(--blur-sm));
    animation: overlay-in 0.3s ease both;
}
.image-modal.hidden { display: none; }
.image-modal-img {
    max-width: 95%;
    max-height: 95%;
    object-fit: contain;
    border-radius: 4px;
    box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6);
}
/* § 106 playback frame variant: an iframe has no intrinsic size — give it
   the modal's full stage; the frame-internal video object-fit:contains into
   it with a transparent letterbox. */
iframe.image-modal-img {
    width: 95%;
    height: 95%;
    border: 0;
    background: transparent;
    box-shadow: none;
}
.image-modal-close {
    position: absolute;
    top: 16px;
    right: 16px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: rgba(40, 30, 60, 0.6);
    color: var(--text);
    font-size: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s ease;
}
.image-modal-close:hover { background: rgba(200, 80, 80, 0.4); }

.image-modal-counter {
    position: absolute;
    top: 16px;
    left: 16px;
    color: white;
    font-size: 14px;
    background: rgba(0, 0, 0, 0.5);
    padding: 4px 10px;
    border-radius: 12px;
    pointer-events: none;
    z-index: 1;
}

/* Image vote bar */
.image-vote-bar {
    position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%);
    display: flex; gap: 12px; background: rgba(0,0,0,0.7); padding: 8px 16px;
    border-radius: 20px; backdrop-filter: blur(var(--blur-sm));
}
.vote-btn {
    font-size: 20px; background: none; border: none; cursor: pointer;
    opacity: 0.6; transition: all 0.2s ease; padding: 4px 8px;
}
.vote-btn:hover { opacity: 1; transform: scale(1.2); }
.vote-btn.voted { opacity: 1; transform: scale(1.3); }
.vote-up.voted { filter: drop-shadow(0 0 6px rgba(255,100,100,0.6)); }
.vote-down.voted { filter: drop-shadow(0 0 6px rgba(100,100,255,0.6)); }

/* ============================================
   17. SHARED BUTTON STYLES
   ============================================ */
.btn-primary {
    height: 44px;
    width: 100%;
    background: linear-gradient(135deg, #5c2848, #803870);
    border: 1px solid rgba(228, 140, 184, 0.2);
    border-radius: 8px;
    color: #eedce8;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.5px;
    transition: all 0.2s ease;
}
.btn-primary:hover {
    box-shadow: 0 4px 16px rgba(128, 56, 112, 0.3);
    border-color: rgba(228, 140, 184, 0.35);
}
.btn-primary:active { transform: scale(0.98); }

.btn-secondary {
    height: 40px;
    width: 100%;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text-dim);
    font-size: 12px;
    transition: all 0.2s ease;
}
.btn-secondary:hover { border-color: var(--border-glow); color: var(--text); }


/* ============================================
   18. ANIMATIONS + TRANSITIONS
   ============================================ */
/* Location crossfade */
.story-transition-out {
    animation: content-fade-out 0.25s ease both;
}
@keyframes content-fade-out {
    from { opacity: 1; }
    to { opacity: 0; }
}

/* Character panel reactions */
.char-slot.arousal-pulse {
    animation: arousal-border-pulse 1.5s ease-in-out infinite;
}
@keyframes arousal-border-pulse {
    0%, 100% { border-color: rgba(46, 34, 66, 0.4); }
    50% { border-color: rgba(224, 104, 120, 0.5); }
}

.char-slot.shame-blush {
    animation: shame-flash 0.6s ease;
}
@keyframes shame-flash {
    0% { background: rgba(200, 80, 80, 0.15); }
    100% { background: rgba(20, 15, 30, 0.4); }
}

.char-slot.fem-shimmer {
    animation: fem-shimmer-anim 0.8s ease;
}
@keyframes fem-shimmer-anim {
    0% { border-color: rgba(228, 120, 184, 0.6); box-shadow: 0 0 12px rgba(228, 120, 184, 0.2); }
    100% { border-color: rgba(46, 34, 66, 0.4); box-shadow: none; }
}

/* Hotspot idle pulse */
.hotspot-pulse {
    animation: hotspot-glow 2s ease-in-out infinite;
}
@keyframes hotspot-glow {
    0%, 100% { border-color: rgba(46, 34, 66, 0.4); }
    50% { border-color: rgba(196, 112, 224, 0.4); }
}


/* Inner Monologue Overlay — introspective text over story image */
.monologue-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(8, 6, 12, 0.65);
    backdrop-filter: blur(2px);
    z-index: 5;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.6s ease;
}
.monologue-overlay.visible { opacity: 1; }
.monologue-text {
    font-family: 'Crimson Pro', serif;
    font-style: italic;
    font-size: 18px;
    line-height: 1.8;
    color: rgba(221, 212, 236, 0.9);
    text-align: center;
    max-width: 70%;
    padding: 20px 30px;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
    letter-spacing: 0.3px;
}


/* ============================================


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Morning Routine Planner
   ============================================ */
/* ============================================
   Morning Routine Planner
   ============================================ */
.planner-box { max-width: 400px; }
.planner-content { padding: 4px 16px 16px; }
.planner-section { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.planner-toggle-row {
    padding: 10px 14px;
    background: rgba(30, 24, 50, 0.6);
    border: 1px solid var(--border);
    border-radius: 8px;
    transition: border-color 0.2s ease;
}
.planner-toggle-row:has(input:checked) {
    border-color: rgba(228, 140, 184, 0.3);
    background: rgba(228, 140, 184, 0.06);
}
.planner-toggle-row:has(input:disabled) {
    opacity: 0.4;
    border-color: transparent;
}
.planner-toggle-row label { display: flex; align-items: center; gap: 10px; font-size: 13px; cursor: pointer; }
.planner-toggle-row input[type="checkbox"] { accent-color: var(--rose); width: 18px; height: 18px; cursor: pointer; flex-shrink: 0; }
.planner-toggle-row input[type="checkbox"]:disabled { opacity: 0.3; cursor: not-allowed; }
.planner-summary {
    text-align: center; font-size: 12px; color: var(--text-dim);
    padding: 10px; background: rgba(20, 16, 36, 0.5);
    border: 1px solid var(--border); border-radius: 8px; margin-bottom: 14px;
}
.planner-actions { display: flex; gap: 10px; justify-content: center; padding: 0 8px; }
.planner-actions .btn-primary { flex: 1; }
.planner-actions .btn-pause-secondary {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    line-height: 1.2;
    padding-top: 8px;
    padding-bottom: 8px;
}
.planner-skip-hint {
    font-size: 10px;
    opacity: 0.6;
    font-style: italic;
    text-transform: none;
    letter-spacing: 0.3px;
}

/* ============================================
   CREDITS OVERLAY
   Triggered from main menu footer.
   ============================================ */
.credits-overlay {
    background: rgba(8, 6, 12, 0.88);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.credits-box {
    max-width: 720px;
    padding: 32px 36px 28px;
    text-align: center;
}
.credits-close {
    position: absolute;
    top: 12px;
    right: 14px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: rgba(20, 16, 36, 0.6);
    border: 1px solid var(--border);
    color: var(--text-dim);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    transition: all 0.2s ease;
}
.credits-close:hover {
    color: var(--text);
    border-color: var(--rose);
}

.credits-header {
    margin-bottom: 28px;
    padding-bottom: 20px;
    border-bottom: 1px solid rgba(228, 140, 184, 0.12);
}
.credits-title {
    font-family: 'Cormorant Garamond', serif;
    font-size: 38px;
    font-weight: 500;
    margin: 0 0 6px;
    color: var(--rose);
    letter-spacing: 1px;
}
.credits-subtitle {
    font-size: 13px;
    color: var(--text-dim);
    margin: 0;
    font-style: italic;
}

.credits-section {
    margin-bottom: 32px;
    text-align: left;
}
.credits-section:last-of-type { margin-bottom: 16px; }
.credits-section-title {
    font-family: 'Cormorant Garamond', serif;
    font-size: 22px;
    font-weight: 500;
    color: var(--text);
    margin: 0 0 8px;
    text-align: center;
    letter-spacing: 0.5px;
}
.credits-section-sub {
    font-size: 12px;
    color: var(--text-faint);
    text-align: center;
    margin: 0 0 18px;
    font-style: italic;
}

/* Special Thanks cards (hero treatment) */
.credits-special { display: flex; flex-direction: column; gap: 14px; }
.credits-card {
    padding: 18px 20px;
    border-radius: 12px;
    background: linear-gradient(135deg, rgba(228, 140, 184, 0.08), rgba(140, 100, 180, 0.05));
    border: 1px solid rgba(228, 140, 184, 0.18);
    text-align: center;
}
.credits-card-art {
    background: linear-gradient(135deg, rgba(228, 140, 184, 0.12), rgba(180, 120, 200, 0.06));
    border-color: rgba(228, 140, 184, 0.25);
}
.credits-card-translate {
    background: linear-gradient(135deg, rgba(140, 180, 200, 0.08), rgba(228, 140, 184, 0.05));
    border-color: rgba(160, 180, 220, 0.18);
}
.credits-card-names {
    font-family: 'Cormorant Garamond', serif;
    font-size: 24px;
    font-weight: 600;
    color: var(--rose);
    margin-bottom: 4px;
    letter-spacing: 0.5px;
}
.credits-card-role {
    font-size: 13px;
    color: var(--text);
    text-transform: uppercase;
    letter-spacing: 1.5px;
    margin-bottom: 8px;
    opacity: 0.85;
}
.credits-card-blurb {
    font-size: 13px;
    color: var(--text-dim);
    font-style: italic;
    line-height: 1.5;
}

/* Bug Hunter buckets */
.credits-bucket { margin-bottom: 18px; }
.credits-bucket:last-child { margin-bottom: 0; }
.credits-bucket-title {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 1.8px;
    color: var(--accent-soft);
    margin: 0 0 10px;
    text-align: center;
    opacity: 0.75;
}
.credits-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: center;
}
.credits-chip {
    display: inline-block;
    padding: 5px 11px;
    background: rgba(228, 140, 184, 0.08);
    border: 1px solid rgba(228, 140, 184, 0.15);
    border-radius: 14px;
    font-size: 12px;
    color: var(--text);
    transition: all 0.2s ease;
}
/* Heavier emphasis for top buckets */
.credits-bucket:first-of-type .credits-chip {
    background: linear-gradient(135deg, rgba(228, 140, 184, 0.22), rgba(140, 100, 180, 0.12));
    border-color: rgba(228, 140, 184, 0.4);
    font-size: 14px;
    padding: 7px 14px;
    font-weight: 500;
}
.credits-bucket:nth-of-type(2) .credits-chip {
    background: rgba(228, 140, 184, 0.14);
    border-color: rgba(228, 140, 184, 0.25);
    font-size: 13px;
}
.credits-chip:hover {
    background: rgba(228, 140, 184, 0.2);
    border-color: var(--rose);
}

/* Community section */
.credits-community { text-align: center; }
.credits-community-text {
    font-size: 14px;
    color: var(--text);
    margin: 6px 0;
    line-height: 1.5;
}
.credits-cta-row {
    display: flex;
    gap: 12px;
    justify-content: center;
    margin-top: 16px;
    flex-wrap: wrap;
}
.credits-cta {
    display: inline-block;
    padding: 10px 22px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    transition: all 0.2s ease;
    letter-spacing: 0.5px;
}
.credits-cta-patreon {
    background: linear-gradient(135deg, #f96854, #e8526b);
    color: white;
    border: 1px solid rgba(255, 255, 255, 0.1);
}
.credits-cta-patreon:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 16px rgba(249, 104, 84, 0.35);
}
.credits-cta-discord {
    background: linear-gradient(135deg, #5865f2, #4752c4);
    color: white;
    border: 1px solid rgba(255, 255, 255, 0.1);
}
.credits-cta-discord:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 16px rgba(88, 101, 242, 0.35);
}

.credits-footer {
    margin-top: 20px;
    padding-top: 18px;
    border-top: 1px solid rgba(228, 140, 184, 0.1);
    text-align: center;
}
.credits-tech {
    font-size: 11px;
    color: var(--text-faint);
    margin: 0 0 8px;
}
.credits-thanks {
    font-family: 'Cormorant Garamond', serif;
    font-size: 18px;
    color: var(--rose);
    margin: 0;
    font-style: italic;
    letter-spacing: 0.5px;
}

@media (max-width: 540px) {
    .credits-box { padding: 24px 20px 22px; }
    .credits-title { font-size: 30px; }
    .credits-section-title { font-size: 19px; }
    .credits-card-names { font-size: 20px; }
}
/* ============================================
   19. RESPONSIVE — DESKTOP (1200px+)
   ============================================ */
@media (min-width: 1200px) {
    /* Choice basis stays at ~50% (from the base .choice-btn rule in
       section _04) so thumbnail + no-thumbnail rows lock to exactly
       2-per-row regardless of which variant they use. The old 30%
       basis produced a "2/2/3" grid whenever a scene mixed thumbnail
       and text-only choices — thumb rows wrapped at 2 (min-width 250
       beats the 30% basis), text rows packed 3 because no min-width
       clamped them. Uniform 2-col grid fixes that. Revert to 30%
       basis only when all choices are nav-style text (handled below
       by the `.nav-grid` class, if/when re-introduced). */
    .story-text, .info-text, .dialogue-text { font-size: calc(var(--font-size-base, 15px) + 1px); line-height: 1.85; }
    .story-scroll { padding: 20px 32px; }
    .choices-panel { padding: 10px 14px 8px; }
}


/* ============================================
   20. RESPONSIVE — TABLET (768px - 1199px)
   ============================================ */

/* Large tablets / small laptops (1024-1199px): narrower panels */
@media (max-width: 1199px) and (min-width: 1024px) {
    :root {
        /* Audit D38: was 220/200 (asymmetric). 220/220 stays symmetric. */
        --left-column-width: 220px;
        --right-column-width: 220px;
    }
    .stat-name { min-width: 65px; font-size: 11px; }
    .stat-val { font-size: 11px; }
    .choice-btn { flex-basis: 45%; }
    .menu-layout { flex-direction: column; align-items: center; gap: 24px; }
    .menu-sidebar { width: 100%; max-width: 400px; }
}

/* Small tablets (768-1023px): collapse side panels by default */
@media (max-width: 1023px) and (min-width: 768px) {
    :root {
        --left-column-width: 200px;
        --right-column-width: 190px;
    }

    .menu-layout { flex-direction: column; align-items: center; gap: 24px; }
    .menu-sidebar { width: 100%; max-width: 400px; }

    .mobile-sidebar-toggles { display: flex; }

    /* Auto-collapse panels on small tablets — story gets full width.
       :not(.user-expanded) so the topbar toggle (toggleLeftPanel adds
       user-expanded) can actually re-open a panel here. Without the guard the
       panels were UNRECOVERABLE at 768-1023px — the width:0 + overflow:hidden
       fired even when the player asked to re-open, and the edge peek-tab was
       clipped. foundby:CutieLvr (sidebars "gone and won't come back").
       :not(.drawer-open) — a phone whose CSS viewport lands in THIS tablet
       band (low-DPR / Samsung "Display size", e.g. SM-A546E portrait ~771px
       CSS while window.innerWidth < 768 → body.phone) opens the right panel
       as an 85% overlay DRAWER (.drawer-open). Without this exemption the
       tablet child-hide below fired on that open drawer, leaving every tab +
       the Phone/Wardrobe/Menu action bar + Bug Report footer invisible — the
       panel rendered as a black void with only the collapse chevron. Rotating
       to landscape (wider CSS → desktop band, no collapse rule) "fixed" it,
       which is how the player found the bug button. foundby:numberundead/Jamie
       (A54 Android 16, 0.2.9.0.4): "the banner is empty". */
    .left-column:not(.user-expanded):not(.drawer-open) { width: 0; padding: 0; overflow: hidden; border-right: none; }
    .left-column:not(.user-expanded):not(.drawer-open) > *:not(.btn-collapse) { display: none; }
    .right-column:not(.user-expanded):not(.drawer-open) { width: 0; padding: 0; overflow: hidden; border-left: none; }
    .right-column:not(.user-expanded):not(.drawer-open) > *:not(.btn-collapse) { display: none; }
    /* overflow-y:auto (NOT visible) so a tall sidebar SCROLLS instead of
       spilling its lower content (hints + the Phone/Wardrobe action buttons
       at the foot of the left column) off the bottom of the viewport with no
       way to reach it. This bites hard at effective widths < 1024px combined
       with a short logical height — e.g. a 1920x1080 screen at Windows 200%
       display-scaling / Electron Ctrl++ zoom renders ~960x500 logical, which
       lands in this tablet breakpoint. With overflow:visible the stats showed
       but the phone was unreachable. foundby:CutieLvr 0.2.7.3 (PC, "sidebar
       opens, no phone, can't scroll"). */
    .left-column.user-expanded { width: var(--left-column-width); overflow-y: auto; overflow-x: hidden; }
    .right-column.user-expanded { width: var(--right-column-width); overflow-y: auto; overflow-x: hidden; }

    .stat-name { min-width: 60px; font-size: 10px; }
    .stat-val { font-size: 10px; }
    .choice-btn { flex-basis: 48%; }

    /* Hide the inline 7-day week strip at tablet width too (it's already
       hidden < 768px). At ~960px logical — a 1920x1080 screen at 200% Windows
       scaling — the full desktop topbar (logos + toggles + day + 228px week
       strip + time slots + wait + menu) is ~994px wide and overflowed the
       960px viewport, clipping the top-right Menu/Settings button off-screen.
       The strip is redundant: the Day button opens the same week popover.
       foundby:CutieLvr 0.2.7.3 (top-right button cut off). */
    .week-strip { display: none; }
}


/* ============================================
   21. RESPONSIVE — PHONE (<768px)
   ============================================ */
@media (max-width: 767px) {
    :root {
        --topbar-height: 42px;
    }

    /* C12 (2026-04-20): at tablet/mobile width the 4-button time-slot strip
       steals ~120 px of topbar width. Collapse to just the active slot +
       a chevron toggle that expands the rest as a dropdown. Adds 1 extra
       tap for slot-switch but frees the topbar for Day/icons. */
    .time-slots-toggle {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 22px;
        border: none;
        border-left: 1px solid var(--border);
        background: var(--bg);
        color: var(--text-faint);
        cursor: pointer;
        padding: 0;
        transition: background 0.15s ease, transform 0.2s ease;
    }
    .time-slots-toggle:hover { background: rgba(232, 200, 96, 0.08); color: var(--gold); }
    .time-slots.expanded .time-slots-toggle svg { transform: rotate(180deg); }

    /* Collapsed state: only the active slot visible */
    .time-slots:not(.expanded) .time-seg:not(.active) { display: none; }

    /* foundby player 0.2.7.5.1 (Pixel 9 portrait): in the collapsed mobile state
       only the active slot shows, and the global <=420px rule shrank it to 9.5px
       so the time-of-day was effectively invisible. Since only ONE slot renders
       collapsed, give it readable size + a clear tinted pill. Higher specificity
       than `.time-seg { font-size: 9.5px }` so it wins at every phone width. */
    /* Player report 0.2.7.6.1 (Pixel 9 portrait): when the center column is
       squeezed, .time-slots (flex-shrink:1, min-width:0) shrinks but the
       active pill (min-width:max-content) does NOT — it overflowed the
       container and ran UNDERNEATH the Skip-Time button painted after it
       ("time of day blocked by Skip Time", unfixable via UI scale because
       zoom preserves relative geometry). Clip at the container edge instead
       so the label truncates gracefully and the button stays clear. */
    .time-slots:not(.expanded) {
        overflow: hidden;
    }
    .time-slots:not(.expanded) .time-seg.active {
        display: inline-flex;
        align-items: center;
        font-size: 12.5px;
        font-weight: 600;
        padding: 4px 10px;
        min-width: max-content;
        letter-spacing: 0.2px;
        border-radius: 10px;
        background: rgba(232, 200, 96, 0.16);
        color: rgba(245, 222, 150, 0.98);
        /* 0.2.8 (foundby:DEVILJOKÉR): the base .time-seg `flex: 1` + the
           row's default align-items:stretch blew the pill up to the full
           container height (39px, poking 1px past the 42px topbar) and it
           sat 3px from the #day-display label — reads as "day and time
           merged" on narrow portrait phones, day not legible, mis-taps
           between week-popover and time-dropdown. Center it at content
           height and give it breathing room from the day label. The 44px
           tap-target rule (_11-fixes-onboarding.css .time-seg) is what
           forced the stretch — the collapsed pill sits next to the ~25px
           day button, so 28px keeps the pair visually consistent while
           staying comfortably tappable. Spec:
           mobile-uiscale-location-geometry.spec.js (topbar test). */
        flex: 0 0 auto;
        align-self: center;
        margin-left: 8px;
        /* Same breathing room toward the Skip-Time button as margin-left
           gives toward the day label (player report 0.2.7.6.1). */
        margin-right: 8px;
        min-height: 28px;
        height: auto;
    }

    /* Expanded state: non-active slots escape the topbar's overflow:hidden
       via position:fixed and stack as a dropdown. JS anchors them to the
       toggle button via CSS variables set on the .time-slots element. */
    .time-slots.expanded {
        position: relative;
        overflow: visible;
    }
    .time-slots.expanded .time-seg {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .time-slots.expanded .time-seg:not(.active) {
        position: fixed;
        left: var(--ts-expand-left, 50%);
        width: var(--ts-expand-width, 90px);
        background: var(--bg);
        border: 1px solid var(--border);
        z-index: 900;
        padding: 8px 8px;
        border-radius: 4px;
        box-shadow: 0 4px 10px rgba(0,0,0,0.5);
    }
    .time-slots.expanded .time-seg[data-slot="1"] { top: calc(var(--ts-expand-top, 48px) + 0px); }
    .time-slots.expanded .time-seg[data-slot="2"] { top: calc(var(--ts-expand-top, 48px) + 32px); }
    .time-slots.expanded .time-seg[data-slot="3"] { top: calc(var(--ts-expand-top, 48px) + 64px); }

    /* Main menu */
    .menu-layout {
        flex-direction: column;
        align-items: center;
        gap: 20px;
        padding: 24px 16px;
    }
    .menu-title { font-size: 36px; }
    .menu-sidebar { width: 100%; max-width: 360px; }
    .menu-buttons { width: 100%; max-width: 300px; }
    .menu-footer-buttons { width: 100%; max-width: 300px; flex-direction: column; }
    /* Keep the support CTAs + inline settings panel on the SAME column width
       as the buttons so the whole stack lines up (they were fixed 280px while
       the buttons grew to 300px on phones — a 20px ragged edge). */
    .menu-support-ctas { width: 100%; max-width: 300px; }
    .menu-settings { width: 100%; max-width: 300px; box-sizing: border-box; }

    /* Character editor */
    .editor-container { max-width: 100%; padding: 12px 12px 24px; }
    /* card-grid is display:grid now — width must stay auto so cards fill their
       column rather than shrinking to 46% of it (the old flex value). */
    .card { width: auto; }
    /* Clear the absolute "Back to menu" button so it doesn't collide with the
       progress dots on narrow screens. */
    .editor-container .progress-dots { margin-top: 46px; }
    .btn-editor-exit { font-size: 12px; padding: 8px 10px; }

    /* Game layout — single column */
    .mobile-sidebar-toggles { display: flex; }

    .main-content { flex-direction: column; }

    .left-column {
        display: none;
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
        width: 85%;
        max-width: 300px;
        z-index: var(--z-drawer);
        box-shadow: 4px 0 24px rgba(0, 0, 0, 0.5);
    }
    .left-column.drawer-open { display: flex; }

    .right-column {
        display: none;
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        width: 85%;
        max-width: 280px;
        z-index: var(--z-drawer);
        box-shadow: -4px 0 24px rgba(0, 0, 0, 0.5);
    }
    .right-column.drawer-open { display: flex; }

    .center-panel { width: 100%; }

    /* Stats strip always visible on phone */
    .stats-strip { display: flex; }

    /* Story */
    .story-scroll { padding: 10px 12px; }
    /* UX-08: 14px on phone matches mobile-readability spec for ~414px width (~75 char/line). */
    .story-text, .info-text, .dialogue-text { font-size: 14px; line-height: 1.7; }

    /* Responsive images — constrain on mobile to reduce rendering cost */
    .story-image {
        max-height: 50vh;
    }
    .story-video,
    .story-video-frame {
        max-height: 50vh;
    }
    .story-image-wrapper {
        margin: 10px 0;
    }
    .story-image-divider {
        margin: 0 20px;
    }

    /* Choices: stack vertically on phone, 48px min touch target */
    .choice-btn { flex-basis: 100%; min-height: 48px; }
    .choice-btn.nav-choice { flex-basis: 48%; min-height: 48px; }
    /* Thumbnail choices on mobile: full width, slightly smaller */
    .choice-btn.has-thumb { flex-basis: 100%; min-height: 72px; }
    .choice-thumb { width: 72px; }
    .choice-btn.has-thumb .choice-text { font-size: 13px; padding: 0 10px; }

    /* Topbar compact — must fit in viewport */
    #topbar { gap: 4px; padding: 5px 6px; overflow: hidden; }
    .topbar-left, .topbar-right { flex-shrink: 0; gap: 4px; }
    /* Owner 2026-06-07: Mobile-Topbar entschlacken - das Menue-Zahnrad ist
       jetzt redundant (Settings sitzt in beiden Side-Drawer-Menues: links
       als 3. Primary-Action, rechts im Char-Panel-Footer). */
    body.phone .topbar-right > #btn-settings { display: none; }
    .topbar-center { flex-shrink: 1; overflow: hidden; min-width: 0; gap: 3px; }
    .topbar-logo { display: none; }
    .topbar-money, .topbar-energy { font-size: 11px; }
    .time-seg { padding: 5px 8px; font-size: 11px; }
    .day-display {
        font-size: 11px;
        padding: 2px 8px;
        background: rgba(46, 34, 66, 0.4);
        border-color: rgba(110, 60, 122, 0.25);
        box-shadow: none;
    }
    .day-weekday { font-size: 9px; }

    /* Prevent horizontal scroll on mobile */
    body { overflow-x: hidden; }

    /* Overlays full-width */
    .overlay { padding: 8px; }
    .overlay-box {
        border-radius: 10px;
        /* Zoom-aware so the visual box stays inside the viewport at any
           UI Scale on mobile too (see base rule in _06-overlays.css). */
        max-height: calc(92vh / var(--overlay-zoom, 1));
    }
    .phone-box { min-height: auto; }

    /* Notifications — account for safe-area on notched phones so the top
       row of stat/SMS notifications doesn't sit underneath the notch.
       Pre-fix on Android/iOS with a notch + tall topbar, the notification
       was anchored at a fixed 80/90px from viewport edge, which the
       safe-area-padded topbar (in _02-topbar.css) overlapped.
       foundby:VPS player 0.2.6.7. */
    .stat-notifications {
        left: 8px;
        right: 8px;
        top: calc(90px + env(safe-area-inset-top, 0px));
    }

    /* SMS notification full-width */
    .sms-notification {
        top: calc(80px + env(safe-area-inset-top, 0px));
        right: 8px;
        left: 8px;
        max-width: none;
    }

    /* Phone sidebar backdrop — see consolidated rule below */

    /* Slightly smaller portraits on mobile */
    .dialogue-portrait { width: 42px; height: 42px; }
    .dialogue-portrait-letter { font-size: 16px; }
}

/* Very small phones — redesigned topbar for readability */
@media (max-width: 420px) {
    .menu-title { font-size: 28px; }
    /* Audit D28: was 11px (sub-readable). 13px is min for body text on small
       phones — Apple HIG min 11pt @ 1x = 14.7px, Material 12sp = 14px. */
    .choice-btn { font-size: 13px; padding: 8px 10px; line-height: 1.45; }
    /* Audit D07+D08: bumped from 34/36 to 44 (WCAG 2.5.5 target-size AAA).
       Settings + Menu icons were unreachable thumb-zone on phones <420px. */
    .topbar-btn { width: 44px; height: 44px; }
    /* Image-based topbar buttons (has-img) override default 50px size on phones */
    .topbar-btn.has-img { width: 44px; height: 44px; }
    /* Logo: keep the 3-letter lockup but shrink so the timebar fits */
    .topbar-logo img { width: 30px; height: 30px; }
    .topbar-logo { gap: 0; }
    #topbar { gap: 4px; padding: 4px 6px; }
    .topbar-left, .topbar-right { gap: 3px; }
    .topbar-center { gap: 2px; flex-wrap: nowrap; min-width: 0; }
    .time-slots { flex-shrink: 1; min-width: 0; }
    .time-seg { padding: 4px 2px; font-size: 9.5px; letter-spacing: 0; flex: 1 1 0; min-width: 0; }
    .day-display {
        font-size: 11px;
        padding: 2px 6px;
        white-space: nowrap;
        background: transparent;
        border: none;
        box-shadow: none;
        flex-shrink: 0;
    }
    .day-weekday { display: none; }
    .day-act { display: none; }

    /* Mobile: hide inline strip — opens as popover via .day-display click */
    .week-strip { display: none; }
    button.day-display {
        cursor: pointer;
        background: rgba(18, 12, 28, 0.55);
        border: 1px solid rgba(180, 140, 220, 0.35);
        position: relative;
    }
    button.day-display::after {
        content: '▾';
        display: inline-block;
        margin-left: 4px;
        font-size: 9px;
        color: var(--orchid);
        opacity: 0.75;
    }
    button.day-display[aria-expanded="true"]::after {
        content: '▴';
    }

    /* Further constrain images on very small screens */
    .story-image { max-height: 40vh; }
    .story-video, .story-video-frame { max-height: 40vh; }
}


/* ============================================
   Mobile Location List (replaces hotspot maps on <768px)
   ============================================ */
.location-mobile-list {
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 0;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    /* Override ALL desktop map styles */
    position: static !important;
    aspect-ratio: unset !important;
    /* Fill the available mobile viewport below the topbar/strip
       so the card grid never sits on a big black dead-space below it.
       svh is the "small viewport" unit — safer on iOS than vh when
       the URL bar is visible.
       0.2.8 (foundby:DEVILJOKÉR, Android portrait): two geometry fixes.
       (a) Divide 100svh by --overlay-zoom: since Chromium ~128 viewport
       units are NOT divided by an ancestor's CSS `zoom`, so at UI scale
       S > 1 the list rendered S x 100svh tall — taller than the screen,
       clipped by the parent, and its own content was shorter than the
       min-height so overflow-y:auto had nothing to scroll ("stuck").
       The px terms (topbar + chrome) scale WITH zoom, so only the svh
       term needs the division. (b) Subtraction raised 24px → 40px: the
       real chrome above the list is ~35px (measured 77px list top minus
       42px topbar at Pixel-6 portrait); 24px left the list 9px taller
       than the viewport at 100% scale — unscrollable, the bottom card
       row clipped. Spec: mobile-uiscale-location-geometry.spec.js. */
    min-height: calc(100svh / var(--overlay-zoom, 1) - var(--topbar-height, 60px) - 40px) !important;
    height: auto !important;
    max-height: none;
    border-radius: 10px;
}
/* The buttons block still flexes to fill the list (keeps the dark themed
   background covering the viewport), but the card grid inside MUST pack
   its rows at the top: the grid default `align-content: stretch`
   distributed 2-3 card rows across the whole stretched container — giant
   voids between rows, 346px-tall cards (design ~150px), thumbs reading
   as "cut in half", tap targets displaced. 0.2.8, foundby:DEVILJOKÉR. */
.location-mobile-buttons { flex: 1 1 auto; align-content: start; }
.location-mobile-header {
    font-size: 16px;
    font-weight: 700;
    color: var(--rose);
    text-align: center;
    padding: 12px 16px 8px;
    text-transform: uppercase;
    letter-spacing: 1px;
}
.location-mobile-thumb {
    width: 100%;
    min-height: 120px;
    height: 120px !important;
    background-size: cover;
    background-position: center;
    border-radius: 0;
    opacity: 0.7;
    margin-bottom: 8px;
    flex-shrink: 0;
}
.location-mobile-buttons {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 0 12px 12px;
}
.location-mobile-btn {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 14px 16px;
    background: rgba(20, 15, 35, 0.6);
    border: 1px solid rgba(46, 34, 66, 0.4);
    border-radius: 10px;
    color: var(--text);
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
    min-height: 48px;
}
.location-mobile-btn:active {
    background: rgba(40, 25, 60, 0.8);
    border-color: var(--orchid);
}
.location-mobile-btn.disabled {
    opacity: 0.55;
    pointer-events: none;
}
/* Disabled card: greyscale thumb + locked hint, so the state reads
   intentionally blocked (not broken) at a glance. */
.location-mobile-btn.disabled .location-mobile-btn-thumb {
    filter: grayscale(1) brightness(0.5);
}
.location-mobile-btn.disabled .location-mobile-btn-label {
    color: var(--text-faint);
}
.location-mobile-btn.has-reason {
    position: relative;
}
.location-mobile-btn.has-reason::before {
    content: '🔒';
    position: absolute;
    top: 6px;
    left: 6px;
    font-size: 13px;
    opacity: 0.8;
    z-index: 2;
}
.location-mobile-btn-reason {
    display: block;
    padding: 0 10px 6px;
    text-align: center;
    font-size: 10px;
    font-style: italic;
    color: rgba(200, 180, 220, 0.7);
    letter-spacing: 0.2px;
}
.location-mobile-btn:not(.has-thumb) .location-mobile-btn-reason {
    padding: 0;
    margin-left: 8px;
}
/* Mobile location buttons: 2-col card grid with image + label */
.location-mobile-buttons {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: 6px;
}
.location-mobile-btn.has-thumb {
    flex-direction: column;
    padding: 0;
    overflow: hidden;
    min-height: auto;
    align-items: stretch;
}
.location-mobile-btn-thumb {
    width: 100%;
    height: 80px;
    background-size: cover;
    background-position: center;
    flex-shrink: 0;
    border-radius: 10px 10px 0 0;
    filter: brightness(0.65) saturate(0.85);
    transition: filter 0.2s;
}
.location-mobile-btn:active .location-mobile-btn-thumb {
    filter: brightness(0.9) saturate(1);
}
.location-mobile-btn.has-thumb .location-mobile-btn-label {
    padding: 8px 10px;
    text-align: center;
    font-size: 12.5px;
}
.location-mobile-btn.has-thumb .location-mobile-btn-cost {
    padding: 0 10px 6px;
    text-align: center;
    display: block;
}
.location-mobile-btn.has-thumb .location-mobile-btn-indicator {
    position: absolute;
    top: 6px;
    right: 6px;
    background: rgba(232, 140, 184, 0.9);
    width: 18px;
    height: 18px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    color: #fff;
}

/* Buttons without thumb: span full width as list items */
.location-mobile-btn:not(.has-thumb) {
    grid-column: 1 / -1;
}

.location-mobile-btn-label { flex: 1; }
.location-mobile-btn-cost {
    font-size: 10px;
    color: var(--text-faint);
    font-family: 'DM Mono', monospace;
}
.location-mobile-btn-indicator {
    color: var(--rose);
    font-weight: 700;
    font-size: 14px;
}
.location-mobile-btn-extra {
    border-style: dashed;
    opacity: 0.7;
}

/* ============================================
   22. DEVICE CLASS OVERRIDES
   ============================================ */
/* Applied via JS: body.mobile, body.tablet, body.phone */
body.mobile .mobile-sidebar-toggles { display: flex; }
body.mobile .choice-btn { min-height: 44px; }
body.mobile .choice-btn.has-thumb { min-height: 80px; } /* thumbnail cards keep desktop baseline so badges fit below text */
body.mobile .action-btn { min-height: 40px; }
body.mobile .travel-btn { min-height: 36px; }

/* UX-01: disabled-reason prominenter auf touch (kein hover-tooltip).
   Without this, players rage-tap disabled buttons and assume the UI is broken. */
body.mobile .choice-btn.disabled .choice-disabled-reason,
body.touch .choice-btn.disabled .choice-disabled-reason {
    font-size: 12px;
    font-style: normal;
    color: rgba(228, 140, 184, 0.85);
    margin-top: 4px;
    line-height: 1.3;
}
body.mobile .choice-btn.disabled .choice-disabled-reason::before,
body.touch .choice-btn.disabled .choice-disabled-reason::before {
    content: '🔒 ';
    margin-right: 2px;
}

body.phone .left-column {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: 85%;
    max-width: 300px;
    z-index: var(--z-drawer);
}
body.phone .right-column {
    display: none;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 85%;
    max-width: 280px;
    z-index: var(--z-drawer);
}
body.phone .left-column.drawer-open { display: flex; }
body.phone .right-column.drawer-open { display: flex; }

/* Mobile YOU drawer: pack the equipment slots into a 2-col grid so
   more slots are visible above the fold, and shrink the BR/Feedback
   footer to an icon-only strip (they still exist, just compact). */
body.phone .right-column.drawer-open .character-slots {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px;
}
/* Tab-System (2026-06-07): inline display:none aus setPanelMode muss
   das Phone-Grid schlagen koennen - daher KEIN !important mehr oben;
   im Icons-Tab setzt JS display:'' und das Grid greift wieder. */
body.phone .right-column.drawer-open .character-slots[style*="display: none"] {
    display: none;
}
body.phone .right-column.drawer-open .char-slot {
    min-height: 64px;
    padding: 6px 8px;
    gap: 6px;
    flex-direction: column;
    text-align: center;
}
body.phone .right-column.drawer-open .char-slot-image {
    width: 100%;
    height: 60px;
}
/* Intimate + legwear/feet rows already come as horizontal pairs — keep
   them on a single grid track so the pair reads together. */
body.phone .right-column.drawer-open .char-slot-row {
    grid-column: 1 / -1;
    display: flex;
    gap: 6px;
}
body.phone .right-column.drawer-open .char-panel-footer {
    padding: 6px 8px;
    gap: 6px;
}
/* Owner 2026-06-07: 24px-Icons waren am Handy nicht drueckbar -
   Touch-Target >=48px (Android-Guideline), Label bleibt dran. */
body.phone .right-column.drawer-open .char-footer-btn.has-img {
    height: auto;
    min-height: 64px;
    min-width: 64px;
    padding: 4px;
}
body.phone .right-column.drawer-open .char-footer-btn .char-footer-label {
    font-size: 9px;
}
body.phone .right-column.drawer-open .char-footer-btn img {
    width: 44px;
    height: 44px;
}
/* 0.2.9: combined-panel tabs — bigger touch targets in the drawer */
body.phone .right-column.drawer-open .panel-tab { min-height: 40px; font-size: 12px; }

/* Scene-mode collapses side columns to width:0 on desktop; when the
   column is opened as a mobile drawer, we need to win that specificity
   battle and actually show its width. Match the scene-mode selector
   and add .drawer-open so it's 0,3,1 vs the 0,2,1 collapse rule. */
body.phone.scene-mode .left-column.drawer-open:not(.user-expanded) {
    width: 85%;
    max-width: 300px;
    overflow-y: auto;
}
body.phone.scene-mode .right-column.drawer-open:not(.user-expanded) {
    width: 85%;
    max-width: 280px;
    overflow-y: auto;
}
body.phone.scene-mode .left-column.drawer-open:not(.user-expanded) > *,
body.phone.scene-mode .right-column.drawer-open:not(.user-expanded) > * {
    display: revert;
    opacity: 1;
    visibility: visible;
}
/* display:revert degradiert Flex-Container zu block (Desktop-Pendant in
   _03) - Layout-Container im Phone-Drawer explizit wiederherstellen.
   Inline display:none aus setPanelMode (Tab-System) gewinnt weiterhin.
   2026-06-19: head/accessory/doll-status/slots moved inside .char-panel-scroll
   -> descendant combinator; footer + scroll wrapper stay direct children. */
body.phone.scene-mode .right-column.drawer-open:not(.user-expanded) > .char-panel-scroll,
body.phone.scene-mode .right-column.drawer-open:not(.user-expanded) .char-image-stage,
body.phone.scene-mode .right-column.drawer-open:not(.user-expanded) .char-panel-footer,
body.phone.scene-mode .right-column.drawer-open:not(.user-expanded) .doll-status-row {
    display: flex;
}
body.phone.scene-mode .right-column.drawer-open:not(.user-expanded) .doll-status-row.hidden {
    display: none;
}
body.phone .stats-strip { display: flex; }

/* Phone sidebar backdrop — see consolidated rule in §Phone Sidebar Backdrop */
/* ============================================
   23. WARDROBE OVERLAY — INTERNALS
   ============================================ */

/* Wardrobe banner (matches shop storefront style) */
.wardrobe-banner {
    position: relative;
    height: 90px;
    background: linear-gradient(135deg, rgba(140, 60, 120, 0.3) 0%, rgba(80, 40, 100, 0.2) 50%, rgba(30, 20, 50, 0.6) 100%);
    border-radius: var(--radius-lg, 14px) var(--radius-lg, 14px) 0 0;
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 0 24px;
    border-bottom: 1px solid rgba(228, 140, 184, 0.15);
    overflow: hidden;
}
.wardrobe-banner::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgba(8, 6, 12, 0.5) 0%, transparent 60%);
    pointer-events: none;
}
.wardrobe-banner-icon {
    font-size: 36px;
    z-index: 1;
    filter: drop-shadow(0 2px 8px rgba(228, 140, 184, 0.3));
}
.wardrobe-banner-text { z-index: 1; }
.wardrobe-banner-title {
    font-size: 22px;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
    letter-spacing: 0.5px;
}
.wardrobe-banner-sub {
    font-size: 12px;
    color: var(--text-dim);
    margin-top: 2px;
}

/* Wardrobe frame — relative for floating close button */
.wardrobe-frame { position: relative; }

/* Preset bar */
.wardrobe-presets {
    display: flex;
    gap: 6px;
    padding: 8px 16px;
    border-bottom: 1px solid var(--border);
    background: rgba(14, 11, 20, 0.4);
}
.preset-slot {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    height: 32px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 6px;
    color: var(--text-dim);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.3px;
    cursor: pointer;
    transition: all 0.2s ease;
    position: relative;
    overflow: hidden;
}
.preset-slot::before {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse at 50% 0%, rgba(196, 112, 224, 0.03), transparent 70%);
    pointer-events: none;
}
.preset-slot:hover { border-color: var(--border-glow); color: var(--text); }
.preset-slot.has-data { border-color: rgba(92, 216, 156, 0.25); }
.preset-slot.has-data:hover { border-color: rgba(92, 216, 156, 0.5); }
.preset-slot-empty { color: var(--text-faint); font-style: italic; }

/* Wardrobe preset pill buttons */
.wardrobe-preset-btn {
    padding: 4px 12px;
    border-radius: 12px;
    background: rgba(60, 40, 80, 0.6);
    border: 1px solid var(--border);
    color: var(--text);
    font-size: 11px;
    cursor: pointer;
    transition: background 0.15s;
}
.wardrobe-preset-btn:hover {
    background: rgba(80, 50, 110, 0.8);
}
.wardrobe-preset-saved {
    border-color: rgba(92, 216, 156, 0.25);
}
.wardrobe-preset-saved:hover {
    border-color: rgba(92, 216, 156, 0.5);
}
.wardrobe-preset-menu-btn {
    padding: 4px 6px;
    border-radius: 8px;
    background: rgba(60, 40, 80, 0.3);
    border: 1px solid transparent;
    color: var(--text-dim);
    font-size: 13px;
    cursor: pointer;
    line-height: 1;
    margin-left: -4px;
}
.wardrobe-preset-menu-btn:hover {
    background: rgba(80, 50, 110, 0.6);
    color: var(--text);
}
.wardrobe-preset-menu {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 4px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.5);
    z-index: var(--z-modal);
    min-width: 120px;
}
.wardrobe-preset-option {
    padding: 6px 12px;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--text);
    font-size: 11px;
    cursor: pointer;
    text-align: left;
}
.wardrobe-preset-option:hover {
    background: rgba(140, 100, 200, 0.2);
}
.wardrobe-preset-delete {
    color: #e85c5c;
}
.wardrobe-preset-delete:hover {
    background: rgba(232, 92, 92, 0.15);
}
.wardrobe-preset-add {
    background: rgba(196, 112, 224, 0.15);
    border-color: var(--orchid);
    color: var(--orchid);
    font-weight: 600;
}
.wardrobe-preset-add:hover {
    background: rgba(196, 112, 224, 0.3);
}
.wardrobe-presets-label {
    font-size: 10px;
    color: var(--text-dim);
    letter-spacing: 0.5px;
    text-transform: uppercase;
    align-self: center;
    margin-right: 4px;
}

/* Slot tabs (scrollable strip) */
.wardrobe-tabs {
    display: flex;
    border-bottom: 1px solid var(--border);
    padding: 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    background: rgba(14, 11, 20, 0.3);
}
.wardrobe-tabs::-webkit-scrollbar { display: none; }

.wardrobe-tab {
    flex-shrink: 0;
    padding: 10px 16px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-faint);
    border-bottom: 2px solid transparent;
    transition: all 0.2s ease;
    white-space: nowrap;
    cursor: pointer;
    position: relative;
}
.wardrobe-tab:hover { color: var(--text-dim); }
.wardrobe-tab.active,
.wardrobe-tab.wardrobe-tab-active {
    color: var(--rose);
    border-bottom-color: var(--rose);
}
.wardrobe-tab.wardrobe-tab-equipped {
    color: var(--text-dim);
}
.wardrobe-tab.wardrobe-tab-equipped::after {
    content: '';
    position: absolute;
    top: 6px;
    right: 4px;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--green);
    box-shadow: 0 0 4px rgba(92, 216, 156, 0.4);
}
.wardrobe-tab .tab-equipped-dot {
    position: absolute;
    top: 6px;
    right: 4px;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--green);
    box-shadow: 0 0 4px rgba(92, 216, 156, 0.4);
}

/* Split layout: equipped item left, item list right */
.wardrobe-content {
    display: flex;
    gap: 0;
    min-height: 360px;
    max-height: 65vh;
    padding: 0;
}

.wardrobe-equipped {
    width: 200px;
    flex-shrink: 0;
    padding: 16px;
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    background: rgba(14, 11, 20, 0.3);
    overflow-y: auto;
}
.equipped-label {
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    color: var(--text-faint);
}
.equipped-item-card {
    width: 100%;
    background: var(--bg-card);
    border: 1px solid rgba(92, 216, 156, 0.25);
    border-radius: 10px;
    padding: 12px;
    text-align: center;
    position: relative;
}
.equipped-item-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 15%;
    right: 15%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(92, 216, 156, 0.2), transparent);
}
.equipped-item-image {
    width: 80px;
    height: 80px;
    margin: 0 auto 8px;
    border-radius: 8px;
    background: rgba(30, 28, 45, 0.6);
    overflow: hidden;
    border: 1px solid rgba(46, 34, 66, 0.4);
}
.equipped-item-image img { width: 100%; height: 100%; object-fit: contain; }
.equipped-item-name {
    font-size: 11px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 4px;
}
.equipped-item-buffs {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    color: var(--green);
    line-height: 1.5;
}
.equipped-empty {
    width: 100%;
    padding: 20px;
    text-align: center;
    color: var(--text-faint);
    font-size: 11px;
    font-style: italic;
    border: 1px dashed rgba(46, 34, 66, 0.4);
    border-radius: 10px;
}
.btn-unequip {
    width: 100%;
    margin-top: 6px;
    height: 28px;
    font-size: 10px;
    color: var(--text-dim);
    border: 1px solid rgba(200, 80, 80, 0.2);
    border-radius: 6px;
    transition: all 0.2s ease;
    background: transparent;
}
.btn-unequip:hover { border-color: rgba(200, 80, 80, 0.5); color: var(--red); }

/* Wardrobe search */
.wardrobe-search {
    width: 100%;
    padding: 8px 12px;
    margin-bottom: 10px;
    background: rgba(30, 20, 45, 0.8);
    border: 1px solid var(--border);
    border-radius: 6px;
    color: var(--text);
    font-size: 13px;
    outline: none;
    box-sizing: border-box;
}
.wardrobe-search:focus {
    border-color: var(--accent);
}
.wardrobe-search::placeholder {
    color: var(--text-faint);
}

/* Item list grid */
.wardrobe-items {
    flex: 1;
    padding: 14px;
    overflow-y: auto;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 10px;
    align-content: start;
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}

.wardrobe-item-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 12px 10px;
    text-align: center;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.2s var(--ease-out), background 0.2s var(--ease-out);
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}
.wardrobe-item-card::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 9px;
    background: radial-gradient(ellipse at 50% 0%, rgba(196, 112, 224, 0.03), transparent 70%);
    pointer-events: none;
}
.wardrobe-item-card:hover {
    border-color: var(--border-glow);
    background: var(--bg-card-hover);
    transform: scale(1.05);
    box-shadow: 0 4px 16px rgba(196, 112, 224, 0.2);
}
.wardrobe-item-card.equipped {
    border-color: rgba(92, 216, 156, 0.35);
    background: rgba(30, 60, 40, 0.15);
}
.wardrobe-item-card.equipped::after {
    content: '\2713';
    position: absolute;
    top: 4px;
    right: 4px;
    font-size: 8px;
    font-weight: 700;
    color: var(--green);
    background: rgba(20, 40, 30, 0.8);
    padding: 1px 5px;
    border-radius: 3px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

.wardrobe-item-image,
.wardrobe-item-icon {
    width: 64px;
    height: 64px;
    margin: 0 auto 6px;
    border-radius: 8px;
    background: linear-gradient(135deg, rgba(30, 28, 45, 0.6), rgba(20, 16, 32, 0.8));
    border: 1px solid rgba(46, 34, 66, 0.3);
    overflow: hidden;
    flex-shrink: 0;
}
.wardrobe-item-image img,
.wardrobe-item-icon img { width: 100%; height: 100%; object-fit: contain; }

/* JS uses wardrobe-item-equipped, CSS also has .equipped */
.wardrobe-item-card.wardrobe-item-equipped {
    border-color: rgba(92, 216, 156, 0.35);
    background: rgba(30, 60, 40, 0.15);
}

/* Item card internal layout */
.wardrobe-item-info { flex: 1; min-width: 0; }
.wardrobe-item-actions { margin-top: 6px; }

.wardrobe-btn {
    width: 100%;
    height: 32px;
    font-size: 11px;
    font-weight: 600;
    border-radius: 6px;
    transition: all 0.2s var(--ease-out);
    letter-spacing: 0.3px;
    cursor: pointer;
}
.wardrobe-btn-equip {
    background: linear-gradient(135deg, rgba(92, 40, 72, 0.5), rgba(128, 56, 112, 0.4));
    border: 1px solid rgba(228, 140, 184, 0.15);
    color: var(--rose-bright);
}
.wardrobe-btn-equip:hover {
    border-color: rgba(228, 140, 184, 0.3);
    box-shadow: 0 2px 8px rgba(128, 56, 112, 0.3);
}
.wardrobe-btn-unequip {
    background: transparent;
    border: 1px solid rgba(200, 80, 80, 0.2);
    color: var(--text-dim);
}
.wardrobe-btn-unequip:hover { border-color: rgba(200, 80, 80, 0.5); color: var(--red); }
.wardrobe-btn-discard {
    background: transparent;
    border: 1px solid rgba(200, 80, 80, 0.15);
    color: var(--text-dim);
    font-size: 9px;
    padding: 3px 8px;
    opacity: 0.6;
}
.wardrobe-btn-discard:hover { border-color: rgba(200, 80, 80, 0.5); color: var(--red); opacity: 1; }

/* "Owned" status pill for owned-only Item-slot consumables (dildo, journal,
   hypno USB, rope set) — these do nothing when equipped, so they show this
   instead of a no-op Equip button. */
.wardrobe-owned-label {
    display: inline-block;
    font-size: 9px;
    padding: 3px 8px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 4px;
    color: var(--text-faint);
    background: rgba(255, 255, 255, 0.03);
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

/* Discard confirmation modal */
.wardrobe-discard-confirm {
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.7);
    z-index: var(--z-toast);
    display: flex; align-items: center; justify-content: center;
    backdrop-filter: blur(3px);
}
.wardrobe-discard-box {
    background: var(--bg-panel);
    border: 1px solid rgba(200, 80, 80, 0.3);
    border-radius: 10px;
    padding: 20px 24px;
    max-width: 340px;
    text-align: center;
}
.wardrobe-discard-title {
    font-family: var(--font-heading);
    font-size: 16px;
    color: var(--red);
    margin-bottom: 10px;
}
.wardrobe-discard-text {
    font-size: 12px;
    color: var(--text-dim);
    margin-bottom: 16px;
    line-height: 1.5;
}
.wardrobe-discard-actions {
    display: flex;
    gap: 10px;
    justify-content: center;
}
.wardrobe-btn-cancel {
    background: transparent;
    border: 1px solid var(--border-subtle);
    color: var(--text-dim);
}
.wardrobe-btn-cancel:hover { border-color: var(--text-dim); color: var(--text-primary); }
.wardrobe-btn-discard-confirm {
    background: rgba(200, 60, 60, 0.3);
    border: 1px solid rgba(200, 80, 80, 0.4);
    color: var(--red);
}
.wardrobe-btn-discard-confirm:hover { background: rgba(200, 60, 60, 0.5); }

.wardrobe-btn-disabled { opacity: 0.3; pointer-events: none; }

/* Outfit name / rename input modal (replaces window.prompt — Electron-safe) */
.wardrobe-name-modal {
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.7);
    z-index: var(--z-toast);
    display: flex; align-items: center; justify-content: center;
    backdrop-filter: blur(3px);
}
.wardrobe-name-box {
    background: var(--bg-panel);
    border: 1px solid var(--border-glow);
    border-radius: 10px;
    padding: 20px 24px;
    max-width: 340px;
    width: calc(100% - 48px);
    text-align: center;
}
.wardrobe-name-title {
    font-family: var(--font-heading);
    font-size: 16px;
    color: var(--rose-bright);
    margin-bottom: 14px;
}
.wardrobe-name-input {
    width: 100%;
    padding: 9px 12px;
    margin-bottom: 16px;
    background: rgba(30, 20, 45, 0.8);
    border: 1px solid var(--border);
    border-radius: 6px;
    color: var(--text);
    font-size: 14px;
    outline: none;
    box-sizing: border-box;
    text-align: center;
}
.wardrobe-name-input:focus { border-color: var(--accent); }
.wardrobe-name-input::placeholder { color: var(--text-faint); }
.wardrobe-name-actions {
    display: flex;
    gap: 10px;
    justify-content: center;
}
.wardrobe-btn-name-confirm {
    background: linear-gradient(135deg, rgba(92, 40, 72, 0.5), rgba(128, 56, 112, 0.4));
    border: 1px solid rgba(228, 140, 184, 0.3);
    color: var(--rose-bright);
}
.wardrobe-btn-name-confirm:hover { box-shadow: 0 2px 8px rgba(128, 56, 112, 0.3); }

.wardrobe-equipped-badge {
    font-size: 8px;
    font-weight: 700;
    color: var(--green);
    background: rgba(20, 40, 30, 0.6);
    padding: 1px 5px;
    border-radius: 3px;
    margin-left: 6px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

.wardrobe-buff-badge {
    display: inline-block;
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    padding: 1px 4px;
    border-radius: 3px;
    margin-right: 3px;
    margin-top: 2px;
}
.wardrobe-buff-femininity { color: var(--fem); background: rgba(228, 120, 184, 0.1); }
.wardrobe-buff-submissiveness { color: var(--sub); background: rgba(168, 128, 224, 0.1); }
.wardrobe-buff-allure { color: var(--orchid); background: rgba(196, 112, 224, 0.1); }
.wardrobe-buff-comfort { color: var(--green); background: rgba(92, 216, 156, 0.1); }
.wardrobe-buff-arousal { color: var(--arousal); background: rgba(224, 104, 120, 0.1); }

.wardrobe-item-set {
    font-size: 8px;
    color: var(--gold);
    margin-top: 3px;
    font-style: italic;
}

.wardrobe-empty {
    grid-column: 1 / -1;
    text-align: center;
    padding: 30px 20px;
    color: var(--text-faint);
    font-family: 'Crimson Pro', serif;
    font-style: italic;
    font-size: 13px;
}
.wardrobe-item-name {
    font-size: 12px;
    font-weight: 600;
    color: var(--text);
    line-height: 1.3;
    margin-bottom: 3px;
}
.wardrobe-item-buffs {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    color: var(--text-dim);
    line-height: 1.5;
}
.wardrobe-item-buffs .buff-positive { color: var(--green); }
.wardrobe-item-buffs .buff-negative { color: var(--red); }
.wardrobe-items-empty {
    grid-column: 1 / -1;
    text-align: center;
    padding: 40px 20px;
    color: var(--text-faint);
    font-family: 'Crimson Pro', serif;
    font-style: italic;
    font-size: 14px;
}

/* Set bonus indicator */
.wardrobe-set-bonus, .wardrobe-set-badge {
    margin: 0 16px 12px;
    padding: 10px 14px;
    background: linear-gradient(135deg, rgba(232, 200, 96, 0.06), rgba(196, 112, 224, 0.04));
    border: 1px solid rgba(232, 200, 96, 0.2);
    border-radius: 8px;
    animation: set-bonus-flash 0.6s ease both;
}
.wardrobe-set-name { font-weight: 600; font-size: 12px; color: var(--gold); display: block; }

/* Set equip flash animation */
.set-equip-flash {
    animation: set-equip-glow 1.2s ease both !important;
}
@keyframes set-equip-glow {
    0% { box-shadow: 0 0 0 rgba(232, 200, 96, 0); border-color: rgba(232, 200, 96, 0.2); }
    30% { box-shadow: 0 0 20px rgba(232, 200, 96, 0.4); border-color: rgba(232, 200, 96, 0.6); background: rgba(232, 200, 96, 0.1); }
    100% { box-shadow: 0 0 0 rgba(232, 200, 96, 0); border-color: rgba(232, 200, 96, 0.2); }
}

/* Set equip toast notification */
.set-equip-toast {
    position: fixed;
    bottom: 80px;
    left: 50%;
    transform: translateX(-50%);
    background: linear-gradient(135deg, rgba(30, 25, 45, 0.95), rgba(40, 30, 55, 0.95));
    border: 1px solid rgba(232, 200, 96, 0.4);
    border-radius: 10px;
    padding: 10px 20px;
    font-size: 13px;
    font-weight: 600;
    color: var(--gold);
    z-index: 600;
    box-shadow: 0 4px 20px rgba(0,0,0,0.5), 0 0 12px rgba(232, 200, 96, 0.15);
    pointer-events: none;
    white-space: nowrap;
}
.set-toast-icon { font-size: 16px; margin-right: 4px; }

/* Set preview (stat delta on Apply hover) */
.set-preview {
    display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; padding-top: 6px;
    border-top: 1px dashed rgba(232, 200, 96, 0.15);
}
.set-preview.hidden { display: none; }
.set-preview-stat {
    font-family: 'DM Mono', monospace; font-size: 10px; padding: 2px 6px;
    border-radius: 4px;
}
.set-preview-stat.buff-pos { background: rgba(92, 216, 156, 0.12); color: var(--energy); border: 1px solid rgba(92, 216, 156, 0.2); }
.set-preview-stat.buff-neg { background: rgba(220, 80, 80, 0.12); color: var(--red); border: 1px solid rgba(220, 80, 80, 0.2); }
.set-preview-flag { font-size: 10px; color: var(--gold); opacity: 0.7; font-style: italic; }

/* Wardrobe item hover preview */
.wardrobe-preview-tooltip {
    position: fixed; z-index: 600; pointer-events: none;
    background: rgba(20, 15, 30, 0.95); border: 1px solid var(--border-glow);
    border-radius: 8px; padding: 8px; box-shadow: 0 4px 16px rgba(0,0,0,0.5);
    animation: tooltip-in 0.15s ease both; max-width: 140px; text-align: center;
    /* Readability scaling — see BUG_PATTERNS § 47 for the zoom-vs-transform
       reason. transform-origin top-center keeps anchored tooltips growing
       toward the bottom of the screen, away from their hover target. */
    transform: scale(var(--overlay-zoom, 1));
    transform-origin: center top;
}
.wardrobe-preview-tooltip img { width: 120px; height: 120px; object-fit: contain; border-radius: 4px; }
.wardrobe-preview-tooltip div { font-size: 10px; color: var(--text); margin-top: 4px; font-weight: 600; }
.wardrobe-set-bonus span { font-size: 10px; color: var(--text-muted); }
@keyframes set-bonus-flash {
    0% { box-shadow: 0 0 16px rgba(232, 200, 96, 0.4); }
    100% { box-shadow: none; }
}
.set-bonus-name {
    font-size: 11px;
    font-weight: 600;
    color: var(--gold);
    letter-spacing: 0.5px;
    margin-bottom: 2px;
}
.set-bonus-desc {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    color: var(--text-dim);
}


/* ============================================
   24. SHOP OVERLAY — COMPLETE REDESIGN
   ============================================ */

/* ── Shop Frame ─────────────────────────────── */
.shop-frame {
    display: flex;
    flex-direction: column;
    max-height: 85vh;
    position: relative;
}

/* ── Shop Header ────────────────────────────── */
.shop-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px 18px;
    background: linear-gradient(135deg,
        color-mix(in srgb, var(--shop-color, var(--rose)) 18%, var(--bg-deep)),
        color-mix(in srgb, var(--shop-color, var(--rose)) 8%, var(--bg)));
    border-bottom: 1px solid color-mix(in srgb, var(--shop-color, var(--rose)) 25%, transparent);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    position: relative;
    overflow: hidden;
}
.shop-header::after {
    content: '';
    position: absolute;
    bottom: 0; left: 10%; right: 10%; height: 1px;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--shop-color, var(--rose)) 30%, transparent), transparent);
}
.shop-header-icon {
    width: 44px; height: 44px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--shop-color, var(--rose)) 12%, var(--bg-card));
    border: 1px solid color-mix(in srgb, var(--shop-color, var(--rose)) 25%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    overflow: hidden;
    flex-shrink: 0;
}
.shop-header-icon img {
    width: 100%; height: 100%;
    object-fit: cover;
    border-radius: 9px;
}
.shop-header-name {
    flex: 1;
    font-size: 16px;
    font-weight: 700;
    color: var(--text);
    letter-spacing: 0.5px;
    margin: 0;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.shop-money {
    font-family: 'DM Mono', monospace;
    font-size: 14px;
    font-weight: 600;
    color: var(--gold);
    text-shadow: 0 0 12px rgba(232, 200, 96, 0.2);
    padding: 4px 12px;
    background: rgba(232, 200, 96, 0.08);
    border: 1px solid rgba(232, 200, 96, 0.15);
    border-radius: 20px;
    white-space: nowrap;
}
.shop-close-btn {
    width: 36px; height: 36px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.08);
    color: var(--text-dim);
    font-size: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s ease;
    flex-shrink: 0;
}
.shop-close-btn:hover {
    background: rgba(200, 80, 80, 0.25);
    color: var(--text);
    border-color: rgba(200, 80, 80, 0.3);
}

/* ── Shop Filters (slot tabs) ──────────────── */
.shop-filters {
    display: flex;
    gap: 2px;
    padding: 6px 14px;
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    background: rgba(0, 0, 0, 0.15);
    scrollbar-width: none;
    grid-column: 1 / -1;
}
.shop-filters::-webkit-scrollbar { display: none; }
.shop-filter-tab {
    flex-shrink: 0;
    padding: 6px 12px;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-faint);
    border-radius: 6px;
    transition: all 0.2s ease;
    cursor: pointer;
    white-space: nowrap;
}
.shop-filter-tab:hover {
    color: var(--text-dim);
    background: rgba(255, 255, 255, 0.04);
}
.shop-filter-tab.active {
    color: var(--shop-color, var(--rose));
    background: color-mix(in srgb, var(--shop-color, var(--rose)) 10%, transparent);
}

/* ── Items Container (2-column grid) ────────── */
.shop-items {
    flex: 1;
    overflow-y: auto;
    padding: 14px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    align-content: start;
    min-height: 0;
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}

/* ── Item Card (horizontal layout) ─────────── */
.shop-item-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px 18px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 10px;
    transition: all 0.2s var(--ease-out);
    position: relative;
    overflow: hidden;
    min-height: 110px;
}
.shop-item-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; bottom: 0;
    width: 3px;
    background: var(--shop-color, var(--rose));
    opacity: 0;
    transition: opacity 0.2s ease;
    border-radius: 3px 0 0 3px;
}
.shop-item-card:hover {
    border-color: var(--border-glow);
    background: var(--bg-card-hover);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
}
.shop-item-card:hover::before { opacity: 1; }

/* Owned state */
.shop-item-card.shop-item-owned {
    opacity: 0.55;
}
.shop-item-card.shop-item-owned:hover {
    opacity: 0.7;
}

/* Locked state */
.shop-item-card.shop-item-locked {
    opacity: 0.4;
}
.shop-item-card.shop-item-locked:hover {
    transform: none;
    box-shadow: none;
    border-color: var(--border);
    background: var(--bg-card);
}
.shop-item-card.shop-item-locked::before { display: none; }

/* ── Item Icon ─────────────────────────────── */
.shop-item-icon {
    width: 76px;
    height: 76px;
    border-radius: 10px;
    background: linear-gradient(135deg, rgba(30, 28, 45, 0.6), rgba(20, 16, 32, 0.8));
    border: 1px solid rgba(46, 34, 66, 0.4);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    flex-shrink: 0;
    font-size: 28px;
}
/* Shop item hover preview */
.shop-preview-tooltip {
    position: fixed; z-index: 600; pointer-events: none;
    background: linear-gradient(180deg, var(--bg-warm, #1a1228), var(--bg-deep, #0e0b14));
    border: 1px solid rgba(228, 140, 184, 0.2);
    border-radius: 10px; padding: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.5);
    /* Readability scale */
    transform: scale(var(--overlay-zoom, 1));
    transform-origin: center top;
}
.shop-preview-tooltip img {
    width: 120px; height: 120px; object-fit: contain; border-radius: 6px; display: block;
}

.shop-item-icon img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* ── Item Info ─────────────────────────────── */
.shop-item-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.shop-item-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    line-height: 1.3;
}
.shop-item-slot {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    font-weight: 500;
    color: var(--text-faint);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.shop-item-buffs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.shop-buff-badge {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: 4px;
    line-height: 1.5;
    white-space: nowrap;
}
.shop-buff-femininity { color: var(--fem); background: rgba(228, 120, 184, 0.1); }
.shop-buff-submissiveness { color: var(--sub); background: rgba(168, 128, 224, 0.1); }
.shop-buff-allure { color: var(--gold); background: rgba(232, 200, 96, 0.1); }
.shop-buff-comfort { color: var(--green); background: rgba(92, 216, 156, 0.1); }
.shop-buff-arousal { color: var(--arousal); background: rgba(224, 104, 120, 0.1); }
.shop-item-desc {
    font-family: 'Crimson Pro', serif;
    font-size: 11px;
    color: var(--text-dim);
    font-style: italic;
    line-height: 1.4;
}

/* ── Item Actions (price + button) ─────────── */
.shop-item-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    flex-shrink: 0;
    min-width: 80px;
}
.shop-item-price {
    font-family: 'DM Mono', monospace;
    font-size: 14px;
    font-weight: 700;
    color: var(--gold);
    text-shadow: 0 0 10px rgba(232, 200, 96, 0.15);
    white-space: nowrap;
}
.shop-item-owned-label {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    font-weight: 700;
    color: var(--green);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 2px 8px;
    background: rgba(92, 216, 156, 0.08);
    border-radius: 4px;
}
.shop-item-req-label {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    font-weight: 600;
    color: #e06878;
    text-align: right;
    line-height: 1.4;
}

/* ── Shop Buttons ──────────────────────────── */
.shop-btn {
    padding: 6px 16px;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.3px;
    cursor: pointer;
    transition: all 0.2s ease;
    border: 1px solid transparent;
    white-space: nowrap;
}
.shop-btn-buy {
    background: linear-gradient(135deg, rgba(92, 40, 72, 0.7), rgba(148, 56, 112, 0.6));
    border-color: rgba(228, 140, 184, 0.2);
    color: var(--rose-bright);
}
.shop-btn-buy:hover {
    background: linear-gradient(135deg, rgba(112, 50, 88, 0.85), rgba(168, 66, 128, 0.75));
    border-color: rgba(228, 140, 184, 0.35);
    box-shadow: 0 2px 10px rgba(148, 56, 112, 0.3);
}
.shop-btn-buy:active { transform: scale(0.96); }
.shop-btn-equip {
    background: rgba(92, 216, 156, 0.1);
    border-color: rgba(92, 216, 156, 0.2);
    color: var(--green);
}
.shop-btn-equip:hover {
    background: rgba(92, 216, 156, 0.18);
    border-color: rgba(92, 216, 156, 0.35);
}
.shop-btn-disabled {
    opacity: 0.4;
    cursor: default;
    pointer-events: none;
}

/* ── Empty State ───────────────────────────── */
.shop-empty {
    grid-column: 1 / -1;
    text-align: center;
    padding: 40px 20px;
    color: var(--text-faint);
    font-style: italic;
    font-family: 'Crimson Pro', serif;
    font-size: 14px;
}

/* ── Storefront Banner ─────────────────────── */
.shop-storefront {
    position: relative;
    height: 120px;
    overflow: hidden;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.shop-storefront img {
    width: 100%; height: 100%;
    object-fit: cover;
    filter: brightness(0.75) saturate(1.1);
}
.shop-storefront-overlay {
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgba(8, 6, 12, 0.85) 0%, rgba(8, 6, 12, 0.3) 40%, transparent 70%);
    display: flex;
    align-items: flex-end;
    padding: 14px 20px;
}
.shop-storefront-title {
    font-size: 24px;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.7), 0 0 30px rgba(0, 0, 0, 0.4);
    letter-spacing: 0.8px;
}
/* Compact header below banner — no top radius, subtle */
.shop-header-compact {
    border-radius: 0;
    padding: 10px 18px;
    background: rgba(8, 6, 12, 0.6);
    border-top: none;
}

/* ── Mobile ────────────────────────────────── */
@media (max-width: 600px) {
    .shop-items { grid-template-columns: 1fr; }
    .shop-item-card { padding: 10px; gap: 10px; }
    .shop-item-icon { width: 48px; height: 48px; }
    .shop-item-name { font-size: 12px; }
    .shop-item-actions { min-width: 70px; }
    .shop-header { padding: 12px 14px; }
    .shop-header-icon { width: 36px; height: 36px; }
    .shop-header-name { font-size: 14px; }
    .shop-storefront { height: 80px; }
    .shop-storefront-title { font-size: 18px; }

    /* Wardrobe mobile */
    .wardrobe-box { max-width: 100%; width: 95%; }
    .wardrobe-banner { height: 60px; padding: 0 14px; }
    .wardrobe-banner-title { font-size: 16px; }
    .wardrobe-banner-icon { font-size: 24px; }
    .wardrobe-tabs { flex-wrap: wrap; gap: 2px; padding: 6px 8px; }
    .wardrobe-tab { font-size: 10px; padding: 4px 6px; }
    /* Single scroll container on mobile: the grid grows to content and the
       already-scrolling .overlay-box (92vh, zoom-corrected) is the sole
       scroll path. A nested 50vh scroll region under the stacked paper-doll
       pane trapped touch scroll-chaining on FF-Android, leaving bottom items'
       equip buttons unreachable. Matches .shop-items + desktop wardrobe.
       BUG_PATTERNS §90 (nested-scroll variant), foundby VPS Android player. */
    .wardrobe-items { max-height: none; overflow-y: visible; }
    .wardrobe-presets { flex-wrap: wrap; gap: 4px; padding: 6px 10px; }
    .wardrobe-item-card { padding: 8px; gap: 8px; }
    .wardrobe-item-icon { width: 40px; height: 40px; }
}


/* ============================================
   25. CHARACTER PANEL — ENHANCED SLOTS
   ============================================ */

/* Slot items with equip indicator + hover glow */
.char-slot {
    display: flex;
    align-items: center;
    gap: 10px;
    background: rgba(20, 15, 30, 0.4);
    border: 1px solid rgba(46, 34, 66, 0.4);
    border-radius: 8px;
    padding: 8px 10px;
    min-height: 48px;
    transition: all 0.25s ease;
    position: relative;
    overflow: hidden;
}
.char-slot::before {
    content: '';
    position: absolute;
    top: 0;
    left: 10%;
    right: 10%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(196, 112, 224, 0.06), transparent);
    pointer-events: none;
}
.char-slot:hover {
    border-color: var(--border);
    background: rgba(30, 22, 45, 0.5);
    cursor: pointer;
}

/* Rich item tooltip (character panel slot hover) */
.item-tooltip {
    position: fixed;
    z-index: var(--z-modal);
    background: linear-gradient(180deg, var(--bg-warm, #1a1228), var(--bg-deep, #0e0b14));
    border: 1px solid rgba(228, 140, 184, 0.25);
    border-radius: 10px;
    padding: 12px;
    min-width: 160px;
    max-width: 220px;
    box-shadow: 0 8px 32px rgba(0,0,0,0.6), 0 0 16px rgba(228, 140, 184, 0.08);
    pointer-events: none;
    text-align: center;
}
.item-tooltip-img {
    width: 120px;
    height: 120px;
    object-fit: contain;
    border-radius: 8px;
    background: rgba(20, 16, 36, 0.6);
    border: 1px solid rgba(46, 34, 66, 0.5);
    margin: 0 auto 8px;
    display: block;
}
.item-tooltip-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text, #d4c8e0);
    margin-bottom: 2px;
}
.item-tooltip-slot {
    font-size: 10px;
    color: var(--text-faint, #665a78);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: 6px;
}
.item-tooltip-buffs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    justify-content: center;
}
.item-tooltip-buff {
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    padding: 2px 6px;
    border-radius: 4px;
}
.item-tooltip-buff.buff-pos {
    background: rgba(92, 216, 156, 0.12);
    color: var(--energy, #5cd89c);
    border: 1px solid rgba(92, 216, 156, 0.2);
}
.item-tooltip-buff.buff-neg {
    background: rgba(220, 80, 80, 0.12);
    color: var(--red, #dc5050);
    border: 1px solid rgba(220, 80, 80, 0.2);
}

.char-slot.feminine {
    border-color: rgba(228, 120, 184, 0.2);
}
.char-slot.feminine::before {
    background: linear-gradient(90deg, transparent, rgba(228, 120, 184, 0.1), transparent);
}
.char-slot.set-active {
    border-color: rgba(232, 200, 96, 0.3);
    box-shadow: 0 0 8px rgba(232, 200, 96, 0.1);
}
.char-slot.set-active::before {
    background: linear-gradient(90deg, transparent, rgba(232, 200, 96, 0.06), transparent);
}

.char-slot-image {
    width: 40px;
    height: 40px;
    border-radius: 6px;
    background: rgba(30, 28, 45, 0.6);
    overflow: hidden;
    flex-shrink: 0;
    border: 1px solid rgba(46, 34, 66, 0.3);
    display: flex;
    align-items: center;
    justify-content: center;
}
.char-slot-image img { width: 100%; height: 100%; object-fit: cover; }
.char-slot-placeholder {
    font-size: 16px;
    opacity: 0.3;
}

.char-slot-info {
    flex: 1;
    min-width: 0;
}
.char-slot-label {
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-faint);
    margin-bottom: 1px;
}
.char-slot-item-name {
    font-size: 11px;
    color: var(--text);
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.char-slot-empty {
    font-size: 11px;
    color: var(--text-faint);
    font-style: italic;
}


/* ============================================


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Webshop Style
   ============================================ */
/* ============================================
   Webshop Style — Amazon-inspired (Apartment + Stream shops)
   Matches Unity ApartmentShopController.cs layout
   ============================================ */
/* Minimal header for webshop types (apartment/stream) — only shows money */
.shop-header-minimal {
    justify-content: flex-end;
    padding: 8px 18px;
    min-height: auto;
}
/* Amazon-dark header banner */
.webshop-banner {
    display: flex; align-items: center; gap: 12px;
    padding: 14px 16px 10px; margin-bottom: 0;
    background: rgb(19, 25, 33);
    border-radius: 8px 8px 0 0;
    grid-column: 1 / -1;
}
.webshop-banner-icon { font-size: 28px; }
.webshop-banner-title { font-size: 20px; font-weight: 700; color: #fff; letter-spacing: 1px; }
.webshop-banner-sub { font-size: 11px; color: #c8c8c8; margin-left: 8px; }
/* Section sub-headers between product groups (e.g. Decor, Expansions on shop_apartment) */
.webshop-section-header {
    padding: 14px 16px 6px;
    background: rgb(235, 235, 235);
    grid-column: 1 / -1;
}
.webshop-section-title { font-size: 16px; font-weight: 700; color: #0f1111; letter-spacing: 0.4px; }
.webshop-section-sub { font-size: 11px; color: #565656; margin-top: 2px; }
/* Locked decor/expansion cards — distinguishable from sold-out (.webshop-maxed) */
.webshop-locked { opacity: 0.75; }
.webshop-locked .webshop-product-img { filter: grayscale(0.5); }
/* Decorative search bar (Amazon-style) */
.webshop-search {
    display: flex; align-items: center; height: 30px; margin: 8px 16px 12px;
    background: #fff; border-radius: 6px; overflow: hidden;
    grid-column: 1 / -1;
}
.webshop-search-text {
    flex: 1; font-size: 12px; color: #8c8c8c; padding-left: 10px;
    font-family: 'DM Sans', sans-serif;
}
.webshop-search-btn {
    width: 36px; height: 30px;
    background: #febd69; border: none; cursor: default;
    display: flex; align-items: center; justify-content: center;
    font-size: 14px;
}
/* Product grid — white cards (Amazon style) */
.webshop-grid {
    /* grid-auto-rows: auto (not min-content) — min-content lets iOS/iPad Safari
       mis-size the flex card row to just the non-shrinkable 120px image and clip
       the info. auto is content-driven and robust across engines. */
    display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: auto; gap: 12px;
    padding: 12px;
    background: rgb(235, 235, 235);
    border-radius: 0 0 8px 8px;
    /* NO own max-height / overflow scroll. When the apartment shop stacks
       multiple .webshop-grid sections inside the parent .shop-items (which is
       ALREADY a flex:1 overflow-y:auto scroll container), giving each grid its
       own scroll makes it a nested scroll-container grid-item. The outer grid's
       `auto` row then collapses it to ~88px while its 277px cards overflow, and
       the opaque section headers / sibling grids paint OVER the card info →
       cards look image-only. Single scroll on .shop-items only. (foundby iPad player) */
    grid-column: 1 / -1;
}
.webshop-product {
    /* No overflow:hidden on the card itself — if a browser ever collapses the
       card height (iOS min-content quirk) the name/price/button must overflow
       VISIBLY, never be clipped away. Corner rounding moves to .webshop-product-img. */
    background: #fff; border-radius: 8px;
    border: 1px solid #dcdcdc; transition: border-color 0.15s, box-shadow 0.15s;
    display: flex; flex-direction: column;
}
.webshop-product:hover:not(.webshop-maxed) {
    border-color: #ffa942;
    box-shadow: 0 2px 8px rgba(255, 169, 66, 0.2);
}
.webshop-maxed { opacity: 0.55; }
.webshop-product-img {
    height: 120px; min-height: 80px; display: flex; align-items: center; justify-content: center;
    font-size: 42px; background: #f5f5f5;
    overflow: hidden; border-bottom: 1px solid #eee;
    flex-shrink: 0; border-radius: 8px 8px 0 0;
}
.webshop-product-img img {
    width: 100%; height: 100%; object-fit: cover;
}
.webshop-product.webshop-just-bought {
    animation: purchase-flash 0.5s ease both;
}
@keyframes purchase-flash {
    0% { box-shadow: 0 0 20px rgba(80, 180, 80, 0.5); border-color: #50b450; background: #f5fff5; }
    100% { box-shadow: none; border-color: #dcdcdc; background: #fff; }
}
.webshop-product-info { padding: 10px; flex: 1; display: flex; flex-direction: column; }
.webshop-product-name { font-weight: 700; font-size: 13px; margin-bottom: 2px; color: #0f1111; }
.webshop-product-tier { font-size: 14px; color: #ffa942; margin-bottom: 4px; }
.webshop-product-desc { font-size: 11px; color: #565656; line-height: 1.3; margin-bottom: 6px; flex: 1; }
.webshop-product-price { font-size: 18px; font-weight: 700; color: #0f1111; margin-bottom: 8px; }
.webshop-product-price::before { content: ''; font-size: 12px; vertical-align: top; }
.webshop-owned-badge { font-size: 12px; color: #50b450; font-weight: 600; }
.webshop-buy-btn {
    width: 100%; padding: 10px 7px; border-radius: 20px; border: 1px solid #d5b169; cursor: pointer;
    font-size: 13px; font-weight: 600; color: #0f1111;
    background: linear-gradient(180deg, #f7dfa5, #f0c14b);
    transition: background 0.15s;
    min-height: 38px;
    margin-top: auto;
    flex-shrink: 0;
}
.webshop-buy-btn:hover { background: linear-gradient(180deg, #f0c14b, #e8a930); }
.webshop-buy-disabled {
    /* Audit D43: was a flat light-grey button identical to its own gradient.
       Distinct disabled affordance: cross-hatch background, muted red text
       reading "blocked" rather than "just out of money". */
    background:
        repeating-linear-gradient(
            45deg,
            #1c1830 0px,
            #1c1830 4px,
            #221a30 4px,
            #221a30 8px
        );
    color: #b88080;
    cursor: not-allowed;
    border-color: rgba(180, 80, 80, 0.35);
    font-style: italic;
}
@media (max-width: 767px) {
    .webshop-grid { grid-template-columns: 1fr; gap: 10px; }
    .webshop-product { flex-direction: row; }
    .webshop-product-img { width: 90px; height: auto; min-height: 90px; border-bottom: none; border-right: 1px solid #eee; border-radius: 8px 0 0 8px; }
    .webshop-buy-btn { min-height: 48px; font-size: 14px; padding: 10px; }
}
@media (max-width: 480px) {
    .webshop-product-img { width: 80px; }
}

/* ============================================

/* ============ Wardrobe paper-doll live preview ============ */
/* Split row: doll column left, item grid right (owner 2026-06-06) */
.wardrobe-split {
    display: flex;
    align-items: stretch;
    min-height: 0;
}
.wardrobe-split .wardrobe-items {
    flex: 1;
    min-width: 0;
}
.wardrobe-doll-pane {
    width: 190px;
    flex-shrink: 0;
    padding: 12px 10px;
    border-right: 1px solid var(--border);
    background: rgba(14, 11, 20, 0.3);
    display: flex;
    align-items: flex-start;
    justify-content: center;
}
.wardrobe-doll-pane.paper-doll {
    /* Frame the full 2:3 figure deterministically. Without a bounded aspect the
       pane height tracked the (stretch) item-grid height; when the grid was
       short (< ~285px at the 190px pane width) object-fit:cover went
       width-driven and object-position:center top cropped everything below the
       head — "paper doll not showing past the tip of the head" (foundby:VPS
       0.2.8.0.1, Windows). 2:3 box + 190px width = exact cover fit, whole
       figure, no crop. align-self:flex-start stops the row stretch from
       overriding the height back to the grid's. */
    align-self: flex-start;
    aspect-ratio: 2 / 3;
    height: auto;
    max-height: 72vh;
}
/* Worn-gear chips ride smaller in the narrower wardrobe preview pane. */
.wardrobe-doll-pane .doll-worn-indicators { top: 4px; right: 4px; gap: 4px; }
.wardrobe-doll-pane .doll-worn-chip { width: 26px; height: 26px; border-radius: 7px; }
@media (max-width: 860px) {
    /* Mobil (Owner 2026-06-07): Doll als kompakter Streifen UEBER dem Grid
       statt ausgeblendet - beide Systeme muessen auch mobil funktionieren. */
    .wardrobe-split { flex-direction: column; }
    .wardrobe-doll-pane {
        width: 100%;
        padding: 8px;
        border-right: none;
        border-bottom: 1px solid var(--border);
        justify-content: center;
    }
    .wardrobe-doll-pane.paper-doll {
        width: 100%;
        height: 200px;
        max-height: 200px;
        aspect-ratio: auto;
    }
    /* The compact 200px mobile strip is a wide-short box (e.g. 363x200 on a
       Pixel 6a). object-fit:cover + object-position top on the 2:3 doll then
       crops to the head — only ~37% of the dressed figure shows, everything
       below the chest is gone ("clothing view bugged", foundby:VPS 0.2.8.2
       Android). contain fits the WHOLE figure into the strip, centered; all
       doll layers share one canvas so they stay aligned. */
    .wardrobe-doll-pane.paper-doll .paper-doll-layer {
        object-fit: contain;
    }
}
/* ============================================
   26. PHONE OVERLAY — CHAT INTERNALS
   ============================================ */

/* Contact list entries */
.phone-contact-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.2s ease;
    position: relative;
}
.phone-contact-row:hover { background: rgba(40, 30, 60, 0.4); }
.phone-contact-row:active { background: rgba(50, 38, 72, 0.5); }

.phone-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 700;
    flex-shrink: 0;
}
.phone-avatar.avatar-master { background: rgba(168, 128, 224, 0.25); color: var(--sub); border: 1px solid rgba(168, 128, 224, 0.3); }
.phone-avatar.avatar-girlfriend { background: rgba(228, 140, 184, 0.2); color: var(--rose); border: 1px solid rgba(228, 140, 184, 0.3); }
.phone-avatar.avatar-sugardaddy { background: rgba(232, 200, 96, 0.2); color: var(--gold); border: 1px solid rgba(232, 200, 96, 0.3); }
.phone-avatar.avatar-bully { background: rgba(224, 96, 96, 0.2); color: var(--red); border: 1px solid rgba(224, 96, 96, 0.3); }
.phone-avatar.avatar-viewer { background: rgba(88, 136, 204, 0.2); color: var(--masc); border: 1px solid rgba(88, 136, 204, 0.3); }
.phone-avatar.avatar-unknown { background: rgba(46, 34, 66, 0.4); color: var(--text-faint); border: 1px solid var(--border); }

.phone-contact-info { flex: 1; min-width: 0; }
.phone-contact-name { font-size: 12px; font-weight: 600; color: var(--text); }
.phone-contact-preview { font-size: 10px; color: var(--text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.phone-unread-badge {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--rose);
    color: white;
    font-size: 9px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    box-shadow: 0 0 6px rgba(232, 140, 184, 0.4);
}

/* Chat messages */
.phone-chat-bubble {
    max-width: 80%;
    padding: 8px 12px;
    border-radius: 12px;
    font-size: 12px;
    line-height: 1.5;
    position: relative;
    animation: text-fade-in 0.25s ease both;
}
.phone-chat-bubble.npc {
    background: rgba(40, 30, 60, 0.6);
    border: 1px solid rgba(46, 34, 66, 0.5);
    align-self: flex-start;
    border-bottom-left-radius: 4px;
    color: var(--text-body);
}
.phone-chat-bubble.player {
    background: rgba(92, 40, 72, 0.3);
    border: 1px solid rgba(228, 140, 184, 0.15);
    align-self: flex-end;
    border-bottom-right-radius: 4px;
    color: var(--rose-bright);
}
.phone-chat-bubble.npc.master { border-color: rgba(168, 128, 224, 0.25); }
.phone-chat-bubble.npc.girlfriend { border-color: rgba(228, 140, 184, 0.2); }
.phone-chat-bubble.npc.sugardaddy { border-color: rgba(232, 200, 96, 0.2); }
.phone-chat-bubble.npc.bully { border-color: rgba(224, 96, 96, 0.2); }

.phone-chat-bubble img {
    max-width: 100%;
    border-radius: 8px;
    margin-top: 4px;
    cursor: pointer;
}

.phone-day-separator {
    text-align: center;
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-faint);
    padding: 8px 0;
    position: relative;
}
.phone-day-separator::before,
.phone-day-separator::after {
    content: '';
    position: absolute;
    top: 50%;
    height: 1px;
    width: 30%;
    background: var(--border);
}
.phone-day-separator::before { left: 0; }
.phone-day-separator::after { right: 0; }

/* Chat reply buttons (both class names for compatibility) */
.phone-reply-btn, .sms-reply-btn {
    width: 100%;
    padding: 10px 14px;
    background: rgba(200, 80, 160, 0.1);
    border: 1px solid rgba(200, 80, 160, 0.25);
    border-radius: 18px;
    color: var(--rose-bright);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
    transition: all 0.2s ease;
}
.phone-reply-btn:hover, .sms-reply-btn:hover {
    background: rgba(200, 80, 160, 0.25);
    border-color: rgba(200, 80, 160, 0.5);
    transform: translateY(-1px);
}
.sms-reply-bar {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 10px 12px;
    border-top: 1px solid rgba(46, 34, 66, 0.3);
    margin-top: 8px;
}

/* Typing indicator in chat */
.phone-typing {
    display: flex;
    gap: 3px;
    padding: 6px 12px;
    align-items: center;
    align-self: flex-start;
}
.phone-typing-dot {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--text-faint);
    animation: typing-pulse 1s ease-in-out infinite;
}
.phone-typing-dot:nth-child(2) { animation-delay: 0.15s; }
.phone-typing-dot:nth-child(3) { animation-delay: 0.3s; }

/* ── AppStore (extracted from phone.js inline styles) ── */
.appstore-list {
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.appstore-empty {
    text-align: center;
    color: var(--text-faint);
    padding: 32px 16px;
    font-size: 12px;
}
.appstore-row {
    display: flex;
    align-items: center;
    gap: 14px;
    background: rgba(20, 15, 30, 0.5);
    border: 1px solid rgba(46, 34, 66, 0.4);
    border-radius: 10px;
    padding: 12px;
}
.appstore-row.is-patreon-locked { opacity: 0.6; }
.appstore-divider {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 8px 0 2px;
    color: var(--text-faint);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 1.2px;
}
.appstore-divider::before,
.appstore-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: linear-gradient(to right, transparent, rgba(120, 90, 160, 0.35), transparent);
}
.appstore-divider-label {
    flex-shrink: 0;
    padding: 0 4px;
    opacity: 0.7;
}
.appstore-icon-img {
    width: 56px;
    height: 56px;
    border-radius: 10px;
    flex-shrink: 0;
}
.appstore-icon-emoji { font-size: 28px; }
.appstore-info { flex: 1; }
.appstore-name { font-size: 13px; font-weight: 600; color: var(--text); }
.appstore-desc { font-size: 10px; color: var(--text-faint); }
.appstore-req { font-size: 9px; color: #e88cb8; margin-top: 2px; }
.appstore-install-btn {
    padding: 6px 14px;
    border-radius: 6px;
    border: none;
    color: white;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    background: var(--orchid);
    transition: opacity 0.2s ease, background 0.2s ease;
}
.appstore-install-btn.is-installed {
    background: rgba(92, 216, 156, 0.3);
    opacity: 0.5;
    cursor: default;
}
.appstore-install-btn.is-patreon-locked {
    background: rgba(255, 107, 157, 0.2);
    color: #ff6b9d;
    opacity: 0.7;
    cursor: default;
}
.appstore-install-btn.is-req-locked {
    background: rgba(100, 100, 100, 0.3);
    opacity: 0.4;
    cursor: default;
}
.appstore-row.is-coming-soon { opacity: 0.55; }
.appstore-install-btn.is-coming-soon {
    background: rgba(100, 80, 140, 0.3);
    color: rgba(255, 255, 255, 0.55);
    opacity: 0.6;
    cursor: default;
}

/* ── Dating action buttons (extracted from phone.js inline styles) ── */
.dating-action-area { padding: 4px 8px 8px 48px; }
.dating-meet-btn {
    padding: 6px 14px;
    border-radius: 8px;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    background: var(--orchid);
    border: 1px solid rgba(160, 96, 208, 0.3);
    color: white;
    transition: opacity 0.2s ease;
}
.dating-meet-btn.is-locked {
    background: rgba(160, 96, 208, 0.08);
    border-color: rgba(160, 96, 208, 0.15);
    color: var(--text-faint);
    cursor: default;
    opacity: 0.6;
}
.dating-stage-locked {
    font-size: 10px;
    color: var(--rose);
    font-style: italic;
}


/* ============================================
   MOBILE — Phone overlay scaling for actual phones
   ============================================ */
@media (max-width: 767px) {
    .phone-contact-row { padding: 10px 10px; font-size: 13px; }
    .phone-chat-bubble { max-width: 90%; font-size: 13px; }
    .phone-chat-input { font-size: 14px; }
    .appstore-row { padding: 10px; }
    .appstore-icon { width: 48px; height: 48px; }
    .appstore-info { font-size: 13px; }
    .phone-app-label, .phone-app-name { font-size: 12px; }
    .dating-stage-locked { font-size: 11px; }
    .phone-header { font-size: 15px; padding: 10px 12px; }
}

/* ============================================


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Phone App Views
   ============================================ */
.phone-app-view { padding: 12px; }
.phone-app-header {
    display: flex; gap: 10px; align-items: center;
    padding: 12px; border-radius: 8px; margin-bottom: 12px;
}
.phone-app-view-icon { font-size: 28px; }
.phone-app-view-name { font-weight: 700; font-size: 16px; }
.phone-app-view-desc { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
/* HypnoMind session grid — the whole card is the button (thumb-choice style) */
.hm-session-card { transition: transform 0.12s ease, filter 0.12s ease, border-color 0.12s ease; }
.hm-session-card:not(.locked):hover { border-color: rgba(196, 112, 224, 0.7) !important; filter: brightness(1.1); }
.hm-session-card:not(.locked):hover img { filter: brightness(1.05) !important; }
.hm-session-card:not(.locked):active { transform: scale(0.97); }
.phone-app-features { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.phone-app-feature-row {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 12px; background: var(--bg-lighter); border-radius: 6px;
    font-size: 13px;
}
.phone-app-feature-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.phone-app-notice {
    text-align: center; color: var(--text-muted); font-size: 12px;
    padding: 12px; border: 1px dashed var(--border); border-radius: 8px;
    line-height: 1.5;
}


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Dating App Cards (GrindrR)
   ============================================ */
/* ============================================
   Dating App Cards (GrindrR/FlirtR)
   ============================================ */
.dating-profile-card {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 12px; border-radius: 8px; cursor: pointer;
    background: var(--bg-lighter); border: 1px solid var(--border);
    margin-bottom: 6px; transition: background 0.15s;
}
.dating-profile-card:hover:not(.dating-locked) { background: var(--accent-dim); }
.dating-locked { opacity: 0.5; cursor: default; }
.dating-patreon { border-left: 3px solid #e8c860; }
.dating-avatar { width: 40px; height: 40px; border-radius: 50%; overflow: hidden; flex-shrink: 0; background: var(--bg); display: flex; align-items: center; justify-content: center; }
.dating-avatar img { width: 100%; height: 100%; object-fit: cover; }
.dating-avatar-letter { font-size: 18px; font-weight: 700; color: var(--text-muted); }
.dating-profile-info { flex: 1; min-width: 0; }
.dating-name { font-weight: 600; font-size: 13px; }
.dating-bio { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
.dating-stage { font-size: 16px; }
.dating-patreon-badge { font-size: 10px; background: #e8c860; color: #000; padding: 1px 5px; border-radius: 4px; margin-left: 4px; }

/* GrindrR home screen */
.grindr-home-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 12px 0;
}
.grindr-home-btn {
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    padding: 20px 10px; background: var(--bg-lighter); border: 1px solid var(--border);
    border-radius: 10px; cursor: pointer; transition: all 0.2s;
    color: var(--text); font-size: 12px; font-weight: 600;
}
.grindr-home-btn:hover { border-color: var(--border-glow); background: rgba(160, 96, 208, 0.1); }
.dating-hearts { font-size: 12px; letter-spacing: 2px; margin-top: 4px; }
.dating-status { font-size: 10px; color: var(--text-muted); margin-top: 2px; }
.dating-gate { color: var(--rose); font-style: italic; }
.dating-msg { font-size: 10px; color: var(--text-faint); font-style: italic; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 200px; }
.dating-stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
.dating-stat-card { background: var(--bg-lighter); border-radius: 8px; padding: 12px; text-align: center; }
.dating-stat-value { font-size: 20px; font-weight: 700; color: var(--accent); }
.dating-stat-label { font-size: 11px; color: var(--text-muted); margin-top: 4px; }

/* Swipe Cards */
.swipe-header { display: flex; justify-content: space-between; align-items: center; padding: 8px 4px; font-size: 13px; font-weight: 600; }
.swipe-card-container { position: relative; overflow: hidden; }
.swipe-card { background: var(--bg-lighter); border-radius: 10px; overflow: hidden; transition: transform 0.25s ease, opacity 0.25s ease; }
.swipe-card.swipe-left { transform: translateX(-120%) rotate(-8deg); opacity: 0; }
.swipe-card.swipe-right { transform: translateX(120%) rotate(8deg); opacity: 0; }
.swipe-photo { height: 180px; background: var(--bg); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.swipe-photo img { width: 100%; height: 100%; object-fit: cover; }
.swipe-info { padding: 12px; }
.swipe-name { font-weight: 700; font-size: 16px; }
.swipe-bio { font-size: 12px; color: var(--text-muted); margin-top: 4px; }
.swipe-actions { display: flex; justify-content: center; gap: 20px; padding: 12px; }
.swipe-btn { width: 48px; height: 48px; border-radius: 50%; border: 2px solid var(--border); background: var(--bg); font-size: 20px; cursor: pointer; transition: transform 0.15s; }
.swipe-btn:hover { transform: scale(1.1); }
.swipe-match { text-align: center; padding: 40px 20px; }

/* FlirtR Profile Select */
.flintr-profile-select { padding: 12px 0; }
.flintr-profile-option { width: 100%; text-align: left; cursor: pointer; background: var(--bg-lighter); border: 1px solid var(--border); transition: border-color 0.2s; }
.flintr-profile-option:hover:not(.dating-locked) { border-color: var(--accent-soft); }

/* FlirtR Humiliation Messages */
.flintr-messages { margin-top: 12px; }
.flintr-msg-header { font-size: 12px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px; margin-bottom: 6px; padding: 0 4px; }
.flintr-msg-card { display: flex; align-items: center; gap: 8px; padding: 10px 12px; background: var(--bg-lighter); border-radius: 8px; margin-bottom: 4px; cursor: pointer; border: 1px solid transparent; transition: border-color 0.2s; }
.flintr-msg-card:hover { border-color: var(--border-glow); }
.flintr-msg-sender { font-size: 12px; font-weight: 600; white-space: nowrap; min-width: 80px; }
.flintr-msg-preview { font-size: 11px; color: var(--text-muted); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flintr-msg-tier { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap; }

/* FlirtR match chat */
.flintr-match-chat { margin-top: 12px; text-align: left; }
.flintr-chat-bubble {
    padding: 8px 12px; border-radius: 12px; font-size: 12px; line-height: 1.4;
    max-width: 85%; animation: choice-stagger 0.4s ease both;
}
.flintr-chat-them {
    background: rgba(40, 30, 60, 0.8); color: var(--text); border: 1px solid var(--border);
    border-bottom-left-radius: 4px;
}

/* OnlyFems */
.of-passive-income { text-align: center; font-size: 12px; color: var(--green); margin: 8px 0; font-weight: 600; }
.of-withdraw-btn {
    display: block; width: 100%; padding: 8px; margin: 6px 0 4px;
    background: rgba(196, 112, 224, 0.15); color: #c470e0; border: 1px solid rgba(196, 112, 224, 0.3);
    border-radius: 6px; font-size: 12px; font-weight: 600; cursor: pointer; transition: background 0.2s;
}
.of-withdraw-btn:hover { background: rgba(196, 112, 224, 0.3); }

/* Social Feed */
.social-feed-post { background: var(--bg-lighter); border-radius: 8px; padding: 10px 12px; margin-bottom: 6px; }
.social-post-header { margin-bottom: 4px; }
.social-post-user { font-weight: 600; font-size: 12px; color: var(--accent); }
.social-post-text { font-size: 13px; line-height: 1.4; }
.social-post-footer { font-size: 11px; color: var(--text-muted); margin-top: 6px; }


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Phone frame + SMS bubbles
   ============================================ */
/* ============================================
   FIX: Phone — larger frame, looks like a phone device
   ============================================ */
.phone-frame {
    max-width: 480px !important;
    height: 760px !important;
    /* Zoom-aware viewport bound (matches .overlay-box in _06-overlays.css):
       the frame is transform:scale(--overlay-zoom)'d below, so the LAYOUT
       max-height must be divided by the zoom or the rendered box grows past
       the viewport at UI-scale > 1 and the bottom (with the message list)
       is clipped off-screen with no way to scroll to it. foundby:vobreco. */
    max-height: calc(92vh / var(--overlay-zoom, 1));
    border-radius: 32px !important;
    border: 3px solid #3a2e50 !important;
    box-shadow:
        0 0 0 1px rgba(80, 60, 120, 0.3),
        0 20px 60px rgba(0, 0, 0, 0.7),
        inset 0 0 30px rgba(0, 0, 0, 0.1) !important;
    position: relative;
    overflow: hidden;
    /* Readability scaling — see .overlay-box comment in _06-overlays.css */
    transform: scale(var(--overlay-zoom, 1));
    /* center center (NOT center top): the frame is vertically centered in the
       viewport by the overlay container, so a center-top origin scales the box
       DOWNWARD only and pushes its bottom (app content + home bar) off-screen
       at UI-scale > 1 — with no scroll to reach it, because .phone-body's
       internal scroll only spans the un-scaled layout height. Measured at
       zoom 1.4 on an 800px viewport: center-top clipped the bottom 73px;
       center-center keeps the whole frame on-screen with symmetric ~32px
       margins. Same fix the generic .overlay-box already carries (its 0.2.6.7
       comment documents the identical center-top → center-center change).
       foundby:Lawfromchaos 0.2.8.1 ("UI increased, can't fully see the phone
       even when scrolling"). */
    transform-origin: center center;
}
/* Phone notch */
.phone-frame::before {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 140px;
    height: 24px;
    background: #1a1428;
    border-radius: 0 0 18px 18px;
    z-index: 5;
    border: 1px solid rgba(46, 34, 66, 0.4);
    border-top: none;
}
/* Phone camera dot inside notch */
.phone-frame::after {
    content: '';
    position: absolute;
    top: 6px;
    left: 50%;
    transform: translateX(-50%);
    width: 8px;
    height: 8px;
    background: #2a2040;
    border-radius: 50%;
    border: 1px solid rgba(80, 60, 120, 0.4);
    z-index: 6;
}
/* Phone header adjusted for notch */
.phone-header {
    padding: 30px 16px 10px !important;
    border-radius: 28px 28px 0 0 !important;
}
/* Phone body — fixed size, scrolls internally */
.phone-body {
    min-height: 0 !important;
    padding: 8px 12px !important;
    overflow-y: auto !important;
}
/* Phone home bar at bottom */
.phone-frame > .phone-body::after {
    content: '';
    display: block;
    width: 100px;
    height: 4px;
    background: rgba(200, 180, 230, 0.3);
    border-radius: 2px;
    margin: 16px auto 8px;
}
/* Phone app grid: bigger icons */
.phone-app-grid {
    gap: 16px !important;
    padding: 20px 16px !important;
}
.phone-app-icon {
    font-size: 32px !important;
}
.phone-app-name {
    font-size: 11px !important;
}
.phone-app-cell {
    padding: 12px 8px !important;
    border-radius: 14px !important;
}

/* Audit D42: phone-app-grid was 4-col cramped at 414px viewport. Drop to
   3-col + tighter gap on narrow phones, give icons more breathing room. */
@media (max-width: 480px) {
    .phone-app-grid {
        grid-template-columns: repeat(3, 1fr) !important;
        gap: 12px !important;
        padding: 14px 10px !important;
    }
    .phone-app-icon { font-size: 28px !important; }
    .phone-app-cell { padding: 10px 6px !important; }
}

/* Audit D20: mobile-landscape phone overlay — was unplayable, phone-box
   ate the whole viewport with no orientation media query. In landscape the
   phone shrinks + centers, and the topbar still has room. */
@media (max-width: 900px) and (orientation: landscape) {
    .phone-box {
        max-height: 90dvh !important;
        max-width: 380px !important;
        margin: 0 auto;
    }
    .phone-app-grid {
        gap: 10px !important;
        padding: 10px !important;
    }
    .phone-app-icon { font-size: 24px !important; }
    .phone-app-name { font-size: 10px !important; }
    .phone-app-cell { padding: 8px 6px !important; border-radius: 10px !important; }
}
/* ── SMS Contact List — iMessage style thread overview ── */
.sms-contact-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 4px 0;
}
.sms-contact-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    cursor: pointer;
    border-radius: 8px;
    transition: background 0.15s;
}
.sms-contact-row:hover {
    background: rgba(255, 255, 255, 0.05);
}
.sms-contact-row.sms-unread {
    background: rgba(228, 140, 184, 0.08);
}
.sms-contact-avatar {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    font-weight: 700;
    color: #fff;
}
.sms-contact-avatar.sms-avatar-img {
    background: transparent !important;
    overflow: hidden;
}
.sms-contact-avatar.sms-avatar-img img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
}
.sms-contact-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.sms-contact-name {
    font-size: 14px;
    font-weight: 600;
    color: #e4d0e8;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sms-contact-preview {
    font-size: 12px;
    color: #887ca0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sms-unread .sms-contact-name {
    color: #fff;
}
.sms-unread .sms-contact-preview {
    color: #e48cb8;
}
.sms-unread-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #e48cb8;
    flex-shrink: 0;
}
.sms-empty {
    text-align: center;
    color: #887ca0;
    padding: 40px 20px;
    font-size: 14px;
}

/* ── SMS Bubbles — iMessage style (matches Unity _10-phone-sms.uss) ── */
.sms-bubble {
    max-width: 75%;
    padding: 8px 14px;
    border-radius: 18px;
    font-size: 13px;
    line-height: 1.5;
    animation: text-fade-in 0.25s ease both;
    margin-bottom: 2px;
}

/* NPC bubbles: light background, left-aligned, left color accent */
.sms-bubble:not(.sms-bubble-player) {
    background: rgba(240, 238, 245, 0.92);
    color: #1e1e23;
    align-self: flex-start;
    border-bottom-left-radius: 4px;
    border-left: 3px solid rgba(160, 152, 178, 0.6);
}

/* Player bubbles: pink, right-aligned */
.sms-bubble-player {
    background: linear-gradient(135deg, #c850a0, #a040c0);
    color: #fff;
    align-self: flex-end;
    border-bottom-right-radius: 4px;
    text-align: right;
}

/* NPC color accents — left border tint per NPC */
.sms-bubble-master { border-left-color: #9b59b6 !important; }
.sms-bubble-girlfriend { border-left-color: #e88cb8 !important; }
.sms-bubble-sugar { border-left-color: #c89620 !important; }
.sms-bubble-bully { border-left-color: #c83232 !important; }
.sms-bubble-fan { border-left-color: #6e46aa !important; }
.sms-bubble-unknown { border-left-color: #505055 !important; }
.sms-bubble-dating { border-left-color: #c8466e !important; }
.sms-bubble-vip { border-left-color: #aa8228 !important; }
.sms-bubble-default { border-left-color: rgba(180, 180, 185, 0.5) !important; }

/* Bubble text */
.sms-bubble-text {
    font-size: 13px;
    line-height: 1.5;
}
.sms-bubble-player .sms-bubble-text {
    color: #fff;
}

/* Bubble images (MMS) */
.sms-bubble-image {
    max-width: 200px;
    border-radius: 12px;
    margin-bottom: 4px;
    cursor: pointer;
}

/* File attachment row (smsfile) — paperclip + filename + tap-to-view hint.
   Distinct from MMS image bubbles: an MMS shows the picture inline, an
   smsfile shows a tappable file-row that opens the resolved image in the
   fullscreen overlay. Used for "open the file" affordances where the
   sender (Sasha audio file, Hypno teaser) is sending a non-photo asset. */
.sms-bubble-file {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 10px 12px;
    margin: 0;
    background: rgba(46, 34, 66, 0.45);
    border: 1px solid rgba(140, 100, 200, 0.35);
    border-radius: 10px;
    color: inherit;
    text-align: left;
    cursor: pointer;
    font: inherit;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.sms-bubble-file:hover,
.sms-bubble-file:focus-visible {
    background: rgba(70, 50, 100, 0.55);
    border-color: rgba(180, 140, 230, 0.55);
    outline: none;
}
.sms-bubble-file-icon {
    flex: 0 0 auto;
    font-size: 20px;
    line-height: 1;
}
.sms-bubble-file-meta {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1 1 auto;
    min-width: 0;
}
.sms-bubble-file-name {
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 12px;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sms-bubble-file-hint {
    font-size: 10px;
    color: var(--text-faint);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    opacity: 0.75;
}
.sms-bubble-file-caption {
    margin-top: 6px;
}

/* Text-bubble [goto:] CTA — appended under the message text when an SMS
   contains a forced-event link. Reuses the file-bubble visual language
   (subtle violet panel) so players recognize it as a tappable affordance.
   foundby:adyyxy v0.2.7 — Day 60+ permanent-chastity SMS used to dead-end. */
.sms-bubble-goto {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    margin-top: 8px;
    padding: 8px 12px;
    background: rgba(46, 34, 66, 0.45);
    border: 1px solid rgba(180, 140, 230, 0.45);
    border-radius: 8px;
    color: inherit;
    text-align: left;
    cursor: pointer;
    font: inherit;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.sms-bubble-goto:hover,
.sms-bubble-goto:focus-visible {
    background: rgba(70, 50, 100, 0.6);
    border-color: rgba(220, 170, 250, 0.7);
    outline: none;
}
.sms-bubble-goto-icon {
    flex: 0 0 auto;
    font-size: 13px;
    color: var(--rose);
}
.sms-bubble-goto-label {
    flex: 1 1 auto;
    font-size: 11px;
    color: var(--text);
    text-transform: uppercase;
    letter-spacing: 0.8px;
}

/* Fullscreen MMS viewer — opened on tap of an .sms-bubble-image. Sits above
   every other overlay (pause is 10000, character editor is 10001) so it's
   always reachable from inside the phone. */
.sms-image-viewer {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal-top);
    background: rgba(0, 0, 0, 0.92);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: zoom-out;
    padding: 24px;
    box-sizing: border-box;
    animation: smsViewerFadeIn 0.18s ease-out;
}
.sms-image-viewer img {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    border-radius: 8px;
    box-shadow: 0 12px 48px rgba(0, 0, 0, 0.6);
    object-fit: contain;
}
.sms-image-viewer-close {
    position: absolute;
    top: 12px;
    right: 16px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    border: none;
    font-size: 20px;
    line-height: 36px;
    cursor: pointer;
    transition: background 0.15s ease;
}
.sms-image-viewer-close:hover {
    background: rgba(255, 255, 255, 0.22);
}
@keyframes smsViewerFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Chat header — avatar + name (iMessage style) */
.sms-chat-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-bottom: 1px solid rgba(46, 34, 66, 0.3);
}
.sms-chat-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 700;
    color: #fff;
}
.sms-chat-avatar.sms-avatar-img {
    background: transparent !important;
    overflow: hidden;
}
.sms-chat-avatar.sms-avatar-img img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
}
.sms-chat-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--text);
}

/* Chat container — ensure flex column for alignment */
.sms-chat-container {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 8px 4px;
}
/* F45: empty-thread placeholder */
.sms-chat-empty {
    text-align: center;
    font-size: 12px;
    font-style: italic;
    color: var(--text-faint);
    padding: 32px 16px;
}

/* Day separator in chat */
.sms-day-separator {
    text-align: center;
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-faint);
    padding: 10px 0 4px;
}


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: CompletionApp (Progress + People + NPC Profile)
   ============================================ */
/* ============================================
   CompletionApp — Progress & People phone app
   ============================================ */

/* Tab bar */
.completion-tab-bar {
    display: flex;
    gap: 0;
    border-bottom: 1px solid rgba(46, 34, 66, 0.6);
    margin: 0 0 2px 0;
}
.completion-tab {
    flex: 1;
    text-align: center;
    padding: 10px 0;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s;
    border-bottom: 2px solid transparent;
    color: var(--text-faint);
}
.completion-tab-active {
    color: var(--orchid);
    border-bottom-color: var(--orchid);
}

/* Spoiler toggle */
.completion-spoiler-row {
    padding: 4px 14px 2px 14px;
    display: flex;
    justify-content: flex-end;
}
.completion-spoiler-toggle {
    font-size: 9px;
    color: var(--text-faint);
    cursor: pointer;
    padding: 3px 8px;
    border-radius: 4px;
    background: rgba(46, 34, 66, 0.3);
    transition: all 0.2s;
}
.completion-spoiler-toggle:hover {
    color: var(--orchid);
    background: rgba(46, 34, 66, 0.5);
}
.completion-spoiler-active {
    color: var(--orchid);
    background: rgba(100, 50, 140, 0.2);
}

/* Scroll container */
.completion-scroll {
    flex: 1;
    overflow-y: auto;
    padding: 4px 0;
}

/* Cards */
.completion-card {
    background: rgba(20, 15, 30, 0.5);
    border: 1px solid rgba(46, 34, 66, 0.4);
    border-radius: 8px;
    padding: 10px 14px;
    margin: 0 12px 6px 12px;
}
.completion-card-hidden {
    opacity: 0.5;
    background: rgba(15, 10, 25, 0.4);
    border-color: rgba(46, 34, 66, 0.2);
}
.completion-card-complete {
    border-color: rgba(92, 216, 156, 0.3);
}
/* Multi-path sub-cards: indented to show they belong to the storyline above */
.completion-card-path {
    margin-left: 24px;
    border-left: 2px solid rgba(228, 140, 184, 0.25);
}
.completion-card-pending {
    border-color: rgba(228, 184, 92, 0.35);
    background: rgba(30, 25, 15, 0.4);
}
.completion-card-pending .completion-wide-fill { background: rgba(228, 184, 92, 0.4); }
.completion-card-locked {
    opacity: 0.45;
    filter: saturate(0.4);
    border-color: rgba(46, 34, 66, 0.3);
}
.completion-card-locked .completion-storyline-name { text-decoration: line-through; }
.completion-card-locked .completion-wide-fill { background: rgba(120, 120, 120, 0.4); }
.completion-card-overall {
    background: rgba(30, 20, 50, 0.6);
    border-color: rgba(100, 50, 140, 0.3);
    border-radius: 10px;
    padding: 12px 14px;
    margin: 8px 12px 4px 12px;
}
.completion-card-finances {
    border-color: rgba(46, 34, 66, 0.4);
}
.completion-card-title {
    font-size: 11px;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 6px;
}
.completion-overall-title {
    color: var(--orchid);
    margin-bottom: 8px;
}

/* Wide progress rows (overall card) */
.completion-wide-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 2px;
}
.completion-wide-label {
    font-size: 10px;
    color: var(--text-body);
}
.completion-wide-pct {
    font-size: 10px;
    font-weight: 600;
    color: var(--text-dim);
}
.completion-wide-track {
    height: 5px;
    background: rgba(46, 34, 66, 0.4);
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 6px;
}
.completion-wide-fill {
    height: 100%;
    border-radius: 3px;
    transition: width 0.3s;
}

/* Progress row (profile) */
.completion-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 4px;
}
.completion-row-label {
    font-size: 10px;
    color: var(--text-body);
}
.completion-row-value {
    font-size: 10px;
    color: var(--text-dim);
}
.completion-progress-track {
    height: 5px;
    background: rgba(46, 34, 66, 0.4);
    border-radius: 3px;
    overflow: hidden;
    margin-top: 4px;
}
.completion-progress-fill {
    height: 100%;
    border-radius: 3px;
    transition: width 0.3s;
}

/* Category header */
.completion-cat-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px 14px 2px 14px;
}
.completion-cat-count {
    font-size: 9px;
    color: var(--text-dim);
}

/* Section titles */
.completion-section-title {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-faint);
    padding: 6px 14px 4px 14px;
}
.completion-section-title-patreon {
    color: #d88040;
}
.completion-section-title-new {
    color: #c470e0;
}

/* Storyline card elements */
.completion-storyline-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 4px;
}
.completion-storyline-header-left {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 1;
    min-width: 0;
}
.completion-storyline-name {
    font-size: 12px;
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.completion-storyline-badge {
    font-size: 10px;
    color: var(--text-faint);
    flex-shrink: 0;
}
.completion-badge-hidden {
    padding: 2px 6px;
    border-radius: 4px;
    background: rgba(46, 34, 66, 0.3);
    color: var(--text-faint);
}
.completion-badge-complete {
    padding: 2px 6px;
    border-radius: 4px;
    background: rgba(92, 216, 156, 0.15);
    color: var(--green);
}
.completion-badge-pending {
    padding: 2px 6px;
    border-radius: 4px;
    background: rgba(228, 184, 92, 0.18);
    color: rgba(228, 184, 92, 0.95);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.completion-badge-locked {
    padding: 2px 6px;
    border-radius: 4px;
    background: rgba(120, 120, 120, 0.18);
    color: rgba(180, 180, 180, 0.85);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.completion-badge-warning {
    color: #e8a030;
    font-size: 12px;
    margin-left: 2px;
}
.completion-storyline-desc {
    font-size: 10px;
    color: var(--text-body);
    margin-bottom: 4px;
}
.completion-storyline-hint {
    font-size: 9px;
    color: var(--text-faint);
    font-style: italic;
}

/* Milestone chips */
.completion-milestone-row {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
    margin-bottom: 4px;
}
.completion-milestone-chip {
    font-size: 8px;
    padding: 2px 5px;
    border-radius: 3px;
    background: rgba(46, 34, 66, 0.3);
    color: var(--text-faint);
}
.completion-milestone-chip-done {
    background: rgba(92, 216, 156, 0.15);
    color: var(--green);
}
.completion-milestone-chip-next {
    background: rgba(196, 112, 224, 0.15);
    color: var(--orchid);
}

/* Warning text */
.completion-warning-text {
    font-size: 9px;
    color: #e8a030;
    margin-bottom: 2px;
}

/* Spoiler text */
.completion-spoiler-text {
    font-size: 9px;
    color: var(--text-dim);
    font-style: italic;
    padding: 4px 0;
    line-height: 1.4;
}

/* Finance rows */
.completion-finance-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 4px;
}
.completion-finance-row-sub {
    font-size: 9px;
    margin-bottom: 2px;
}
.completion-finance-row-sub .completion-row-label,
.completion-finance-row-sub .completion-row-value {
    font-size: 9px;
    color: var(--text-dim);
}
.completion-finance-value {
    font-size: 11px;
    font-weight: 600;
}
.completion-finance-value-good {
    color: var(--green);
}
.completion-value-danger {
    color: #e05050;
}
.completion-value-warning {
    color: #e8a030;
}

/* ── People Tab ── */

/* Filter toggle */
.completion-filter-toggle {
    font-size: 9px;
    color: var(--text-faint);
    cursor: pointer;
    padding: 4px 14px;
}
.completion-filter-toggle:hover {
    color: var(--orchid);
}

/* Filter row */
.completion-filter-row {
    padding: 4px 14px;
    margin-bottom: 6px;
}

/* Filter tag pills */
.completion-filter-tag {
    display: inline-block;
    font-size: 8px;
    padding: 2px 6px;
    border-radius: 10px;
    background: rgba(46, 34, 66, 0.3);
    color: var(--text-faint);
    cursor: pointer;
    transition: all 0.2s;
    margin: 1px;
}
.completion-filter-tag:hover {
    background: rgba(100, 50, 140, 0.3);
    color: var(--orchid);
}
.completion-filter-tag-active {
    background: rgba(196, 112, 224, 0.25);
    color: var(--orchid);
    border: 1px solid rgba(196, 112, 224, 0.4);
}

/* People grid */
.completion-people-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    padding: 4px 12px 8px 12px;
}

/* People cell */
.completion-people-cell {
    cursor: pointer;
    transition: transform 0.15s, box-shadow 0.15s;
    border-radius: 10px;
    overflow: hidden;
    background: rgba(20, 15, 30, 0.6);
    border: 1px solid rgba(46, 34, 66, 0.4);
}
.completion-people-cell:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
    border-color: rgba(100, 50, 140, 0.4);
}

/* Portrait container */
.completion-people-portrait {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    background: rgba(30, 20, 50, 0.5);
}
.completion-people-portrait-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.completion-people-portrait-fallback {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 32px;
    font-weight: 700;
    color: white;
}
.completion-people-portrait-locked {
    filter: grayscale(100%);
    opacity: 0.5;
}

/* Name + tags overlay at bottom of portrait */
.completion-people-overlay {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 20px 6px 6px 6px;
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.75));
}
.completion-people-name {
    font-size: 11px;
    font-weight: 600;
    color: white;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.completion-people-tag-row {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    margin-top: 2px;
}
.completion-people-tag {
    font-size: 7px;
    padding: 1px 4px;
    border-radius: 3px;
    background: rgba(255, 255, 255, 0.15);
    color: rgba(255, 255, 255, 0.8);
}

/* Patreon badge (top-right of portrait) */
.completion-patreon-badge {
    position: absolute;
    top: 4px;
    right: 4px;
    font-size: 7px;
    padding: 1px 4px;
    border-radius: 3px;
    background: rgba(200, 100, 40, 0.8);
    color: white;
    font-weight: 600;
    z-index: 2;
}

/* Warning badge (top-left of portrait) */
.completion-people-warn-badge {
    position: absolute;
    top: 4px;
    left: 4px;
    font-size: 14px;
    color: #e8a030;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
    z-index: 2;
}

/* Mini progress bar under portrait */
.completion-people-mini-bar {
    height: 3px;
    background: rgba(46, 34, 66, 0.4);
    overflow: hidden;
}
.completion-people-mini-fill {
    height: 100%;
    transition: width 0.3s;
}

/* ── Fullscreen NPC Profile ── */

.completion-profile-hero {
    position: relative;
    width: 100%;
    height: 200px;
    overflow: hidden;
    background: rgba(30, 20, 50, 0.5);
}
.completion-profile-hero-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.completion-profile-gradient {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 30px 12px 10px 12px;
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
}
.completion-profile-name {
    font-size: 16px;
    font-weight: 700;
    color: white;
}
.completion-profile-role {
    font-size: 10px;
    color: rgba(255, 255, 255, 0.7);
    margin-top: 2px;
}
.completion-profile-close {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.5);
    color: white;
    font-size: 14px;
    cursor: pointer;
    z-index: 3;
    transition: background 0.2s;
}
.completion-profile-close:hover {
    background: rgba(0, 0, 0, 0.8);
}
.completion-profile-body {
    padding: 10px 14px;
}
.completion-profile-tag-row {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 10px;
}
.completion-profile-tag {
    font-size: 9px;
    padding: 2px 8px;
    border-radius: 10px;
    background: rgba(100, 70, 140, 0.25);
    color: var(--text-dim);
}
.completion-profile-tag-patreon {
    background: rgba(200, 100, 40, 0.2);
    color: #d88040;
}
.completion-profile-section {
    margin-bottom: 10px;
}
.completion-profile-section-title {
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-faint);
    margin-bottom: 4px;
}
.completion-profile-status {
    font-size: 10px;
    color: var(--text-body);
    margin-bottom: 8px;
}
.completion-profile-hint {
    font-size: 10px;
    color: var(--text-body);
    font-style: italic;
    margin-bottom: 6px;
}
.completion-profile-warning {
    font-size: 10px;
    color: #e8a030;
    margin-bottom: 6px;
}

/* Achievements tab */
.completion-filter-pill {
    cursor: pointer;
    padding: 4px 10px;
    border-radius: 12px;
    background: rgba(40, 30, 60, 0.5);
    color: var(--text-body);
    font-size: 11px;
    border: 1px solid rgba(80, 60, 110, 0.4);
    transition: background 0.12s, color 0.12s;
}
.completion-filter-pill:hover { background: rgba(60, 40, 90, 0.6); }
.completion-filter-pill-active {
    background: rgba(192, 128, 64, 0.25);
    color: #e8a030;
    border-color: rgba(192, 128, 64, 0.5);
}
.completion-ach-section { margin: 8px 12px; }
.completion-ach-heading {
    font-size: 11px;
    color: var(--text-faint);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin: 12px 0 4px 2px;
}
.completion-ach-row {
    display: flex;
    gap: 8px;
    align-items: flex-start;
    padding: 6px 8px;
    border-radius: 6px;
    background: rgba(20, 15, 30, 0.5);
    border: 1px solid rgba(46, 34, 66, 0.3);
    margin-bottom: 4px;
}
.completion-ach-unlocked {
    background: rgba(60, 40, 30, 0.45);
    border-color: rgba(192, 128, 64, 0.35);
}
.completion-ach-locked { opacity: 0.55; }
.completion-ach-icon { font-size: 16px; min-width: 22px; text-align: center; }
.completion-ach-unlocked .completion-ach-icon { color: #e8a030; }
.completion-ach-text { flex: 1; }
.completion-ach-title { font-size: 12px; color: var(--text-body); font-weight: 600; }
.completion-ach-unlocked .completion-ach-title { color: #f0c070; }
.completion-ach-desc { font-size: 10px; color: var(--text-faint); margin-top: 2px; }
/* ============================================
   27. ACHIEVEMENT OVERLAY — CARDS
   ============================================ */

/* Dead `.achievement-cat-tab` styles removed — JS only uses `.achievement-cat-btn`. */

.achievement-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 10px;
    text-align: center;
    position: relative;
    transition: all 0.2s ease;
    overflow: hidden;
}
.achievement-card::before {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse at 50% 0%, rgba(196, 112, 224, 0.03), transparent 70%);
    pointer-events: none;
}
.achievement-card.unlocked {
    border-color: rgba(232, 200, 96, 0.3);
}
.achievement-card.unlocked::after {
    content: '';
    position: absolute;
    top: 0;
    left: 20%;
    right: 20%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(232, 200, 96, 0.3), transparent);
}
.achievement-card.locked {
    opacity: 0.62;
    filter: grayscale(0.3);
}
.achievement-card.hidden-locked {
    opacity: 0.35;
}

.achievement-icon {
    width: 56px;
    height: 56px;
    margin: 0 auto 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.achievement-icon img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    filter: drop-shadow(0 0 6px rgba(255, 80, 180, 0.5));
    transition: filter 0.18s ease, transform 0.18s ease;
}
.achievement-card:hover .achievement-icon img {
    filter: drop-shadow(0 0 10px rgba(255, 120, 200, 0.75));
    transform: scale(1.08);
}
.achievement-card.locked .achievement-icon img {
    filter: drop-shadow(0 0 4px rgba(180, 140, 220, 0.35)) grayscale(0.55) brightness(0.85);
}
.achievement-title {
    font-size: 11px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 3px;
    line-height: 1.3;
}
.achievement-desc {
    font-size: 10px;
    color: var(--text-dim);
    line-height: 1.35;
}
.achievement-card.hidden-locked .achievement-title,
.achievement-card.hidden-locked .achievement-desc { color: var(--text-faint); }


/* ============================================
   28. GALLERY OVERLAY — THUMBNAILS
   ============================================ */

.gallery-cat-tab {
    flex-shrink: 0;
    padding: 7px 12px;
    font-size: 10px;
    font-weight: 600;
    color: var(--text-faint);
    border: 1px solid var(--border);
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.2s ease;
    background: transparent;
}
.gallery-cat-tab:hover { border-color: var(--border-glow); color: var(--text-dim); }
.gallery-cat-tab.active { border-color: var(--orchid); color: var(--orchid); background: rgba(196, 112, 224, 0.06); }

.gallery-thumb {
    aspect-ratio: 16 / 10;
    border-radius: 6px;
    overflow: hidden;
    cursor: pointer;
    position: relative;
    border: 1px solid rgba(46, 34, 66, 0.3);
    transition: all 0.2s ease;
    background: rgba(20, 15, 30, 0.5);
}
.gallery-thumb:hover {
    border-color: var(--border-glow);
    transform: scale(1.03);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}
.gallery-thumb img { width: 100%; height: 100%; object-fit: cover; }

.gallery-thumb.locked {
    opacity: 0.2;
    filter: blur(3px) grayscale(0.6);
    pointer-events: none;
}
.gallery-thumb.locked::after {
    content: '?';
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    font-weight: 700;
    color: var(--text-faint);
    background: rgba(8, 6, 12, 0.3);
}

.gallery-count {
    text-align: center;
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    color: var(--text-faint);
    padding: 8px;
}


/* ============================================
   29. HISTORY OVERLAY — LOG ENTRIES
   ============================================ */

.history-entry {
    padding: 6px 0;
    border-bottom: 1px solid rgba(46, 34, 66, 0.2);
}
.history-entry:last-child { border-bottom: none; }

.history-speaker {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--rose);
    margin-bottom: 2px;
    opacity: 0.8;
}
.history-text {
    font-family: 'Crimson Pro', serif;
    font-size: 14px;
    line-height: 1.6;
    color: var(--text-body);
}
.history-divider {
    text-align: center;
    font-size: 9px;
    color: var(--text-faint);
    padding: 8px 0;
    letter-spacing: 2px;
}


/* ============================================
   30. LOCATION VIEWS — INTERACTIVE MAPS
   ============================================ */

.location-view-root {
    margin-bottom: 12px;
    width: 100%;
}
.location-view-root.hidden { display: none; }
.location-container {
    position: relative;
    width: 100%;
    min-height: 450px;
    aspect-ratio: 16 / 9;
    border-radius: 10px;
    overflow: hidden;
    background: var(--bg-card);
    border: 1px solid var(--border);
}
/* Background: FULLY VISIBLE like Unity (no blur, no dimming) */
.location-bg {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    border-radius: 8px;
}

/* Hotspots: INVISIBLE by default, glow on hover (Unity style) */
.location-hotspot {
    position: absolute;
    transform: translate(-50%, -50%);
    /* Audit D10: was min-height 40 (sub-WCAG 2.5.5). 44 is AAA target-size. */
    min-width: 60px;
    min-height: 44px;
    padding: 10px 12px;
    background-color: rgba(200, 150, 255, 0.0);
    border: 2px solid rgba(255, 200, 255, 0.0);
    border-radius: 10px;
    color: rgb(255, 245, 255);
    font-size: 12px;
    font-weight: 600;
    text-align: center;
    cursor: pointer;
    transition: all 0.25s ease;
    z-index: 3;
}
.location-hotspot:hover {
    border-color: var(--loc-primary, rgba(255, 180, 230, 0.85));
    background-color: rgba(255, 200, 255, 0.12);
    transform: translate(-50%, -50%) scale(1.04);
    box-shadow: 0 0 12px rgba(200, 120, 220, 0.3);
}
/* Audit D10: keyboard focus ring (was missing — a11y SC 2.4.7). */
.location-hotspot:focus-visible {
    outline: 3px solid var(--rose);
    outline-offset: 2px;
    background-color: rgba(255, 200, 255, 0.14);
    border-color: var(--rose);
}
.location-hotspot:focus-visible .location-hotspot-label {
    background-color: rgba(80, 30, 100, 0.92);
    border-color: var(--rose);
}
/* Mobile bottom-sheet for location hotspots.
   Like .location-popover this is appended to document.body, so the `zoom`
   the Text/Interface Size slider puts on #screen-game-view doesn't reach it
   and its text looked un-scaled (small) next to the zoomed map at high UI
   Scale on mobile. It's full-width, so we can't scale it like the popover
   without overflowing horizontally — instead anchor it bottom-centre, shrink
   the layout width by --overlay-zoom, then scale(--overlay-zoom) back to full
   width. transform-origin bottom centre keeps the sheet pinned to the bottom
   edge; the closed-state translateY is multiplied by --overlay-zoom so it
   still slides fully off-screen at any scale. */
.location-bottom-sheet {
    position: fixed; bottom: 0; left: 50%; right: auto; z-index: 400;
    width: calc(100vw / var(--overlay-zoom, 1));
    background: rgba(20, 15, 30, 0.97); border-top: 1px solid var(--border-glow);
    border-radius: 16px 16px 0 0; padding: 16px 20px 24px;
    transform-origin: bottom center;
    transform: translateX(-50%) translateY(calc(100% * var(--overlay-zoom, 1))) scale(var(--overlay-zoom, 1));
    transition: transform 0.3s var(--ease-out);
    backdrop-filter: blur(var(--blur-md));
    max-height: calc(85vh / var(--overlay-zoom, 1));
    display: flex;
    flex-direction: column;
}
.location-bottom-sheet.bottom-sheet-open {
    transform: translateX(-50%) translateY(0) scale(var(--overlay-zoom, 1));
}
.bottom-sheet-handle { width: 32px; height: 4px; background: var(--border); border-radius: 2px; margin: 0 auto 12px; }
.bottom-sheet-title { font-size: 16px; font-weight: 700; color: var(--text); margin-bottom: 6px; }
.bottom-sheet-cost { font-size: 12px; color: var(--text-muted); margin-bottom: 8px; }
.bottom-sheet-badges { display: flex; gap: 4px; margin-bottom: 12px; }
.bottom-sheet-go {
    width: 100%; padding: 10px; border-radius: 8px; font-size: 14px; font-weight: 600;
    background: rgba(196, 112, 224, 0.2); border: 1px solid rgba(196, 112, 224, 0.4);
    color: var(--accent); cursor: pointer; margin-bottom: 8px;
}
.bottom-sheet-cancel {
    width: 100%; padding: 8px; border-radius: 8px; font-size: 12px;
    background: none; border: 1px solid var(--border); color: var(--text-dim); cursor: pointer;
}

.location-hotspot-activity {
    position: absolute; top: -4px; left: -4px;
    font-size: 10px; color: var(--fem); pointer-events: none;
    animation: pulse-dot 2s ease-in-out infinite;
}
.location-hotspot-portrait {
    position: absolute; bottom: -8px; left: 50%; transform: translateX(-50%);
    width: 24px; height: 24px; border-radius: 50%;
    object-fit: cover; border: 2px solid var(--border-glow);
    pointer-events: none; box-shadow: 0 2px 6px rgba(0,0,0,0.4);
}
.location-hotspot-num {
    position: absolute; top: -6px; right: -6px;
    width: 16px; height: 16px; border-radius: 50%;
    background: rgba(20, 15, 30, 0.9); border: 1px solid var(--border-glow);
    font-size: 9px; font-weight: 700; color: var(--gold);
    display: flex; align-items: center; justify-content: center;
    pointer-events: none;
}
.location-hotspot:hover .location-hotspot-label {
    background-color: rgba(80, 30, 100, 0.85);
}
.location-hotspot:active {
    transform: translate(-50%, -50%) scale(0.97);
    background-color: rgba(180, 100, 200, 0.25);
    border-color: rgba(255, 220, 255, 1.0);
}

/* Disabled hotspots: barely visible outline hint */
.location-hotspot-disabled {
    opacity: 0.35;
    pointer-events: none;
    border-color: rgba(255, 200, 255, 0.08);
}

/* Locked hotspots: requirement not met, show reason clearly */
.location-hotspot-disabled.location-hotspot-locked {
    opacity: 0.85;
    pointer-events: auto;
    cursor: not-allowed;
    filter: none;
    border-color: rgba(255, 120, 180, 0.4);
    background: rgba(60, 20, 40, 0.7);
    /* Audit D10: was ballooning to 308x61 because label+reason are nowrap.
       Cap width and wrap the reason so locked pins don't overlap each other
       or eat half the map. Label stays nowrap (short), reason wraps. */
    max-width: 200px;
    white-space: normal;
}
.location-hotspot-locked .location-hotspot-label {
    opacity: 0.7;
    text-decoration: line-through;
    text-decoration-color: rgba(255, 150, 200, 0.5);
    white-space: nowrap;
    max-width: 180px;
    overflow: hidden;
    text-overflow: ellipsis;
}
.location-hotspot-reason {
    display: block;
    font-size: 11px;
    color: #ffaad0; /* Audit D10: was #ff80c0 (~3.8:1 fail AA). Now ~6.5:1. */
    margin-top: 3px;
    letter-spacing: 0;
    font-weight: 600;
    text-shadow: 0 1px 3px rgba(0,0,0,0.9);
    line-height: 1.3;
    white-space: normal;
    max-width: 180px;
}

/* Idle pulse on active hotspots */
.location-hotspot-pulse {
    animation: hotspot-pulse 3s ease-in-out infinite;
    border-color: rgba(255, 200, 255, 0.15);
}
@keyframes hotspot-pulse {
    0%, 100% { border-color: rgba(255, 200, 255, 0.1); }
    50% { border-color: rgba(255, 200, 255, 0.35); }
}

/* Label: always visible with dark bg pill for readability */
.location-hotspot-label {
    display: block;
    font-size: 12px;
    font-weight: 700;
    color: rgb(255, 245, 255);
    padding: 3px 10px;
    background-color: rgba(30, 15, 40, 0.7);
    /* Thin pink hairline at rest so the label reads as an interactive pill,
       not just as text painted on the map. Stronger tint on hover below. */
    border: 1px solid rgba(228, 140, 184, 0.25);
    border-radius: 6px;
    text-shadow: 0 1px 3px rgba(0,0,0,0.9), 0 0 6px rgba(0,0,0,0.5);
    -webkit-text-stroke: 0.3px rgba(0,0,0,0.3);
    white-space: nowrap;
    transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.25s ease;
}
.location-hotspot:hover .location-hotspot-label {
    background-color: rgba(80, 30, 100, 0.9);
    border-color: rgba(228, 140, 184, 0.75);
    box-shadow: 0 0 14px rgba(228, 140, 184, 0.35);
}
.location-hotspot-cost {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    color: rgba(255,255,255,0.6);
    margin-top: 2px;
    display: block;
    text-shadow: 0 1px 2px rgba(0,0,0,0.8);
}

/* Activity indicator "!" badge on hotspots with multiple actions */
.location-hotspot-indicator {
    position: absolute;
    top: -6px;
    left: -6px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: rgba(196, 112, 224, 0.85);
    border: 1px solid rgba(255, 200, 255, 0.6);
    font-size: 10px;
    font-weight: 800;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    animation: indicator-pulse 2s ease-in-out infinite;
    z-index: 5;
}
@keyframes indicator-pulse {
    0%, 100% { transform: scale(1); background: rgba(196, 112, 224, 0.85); }
    50% { transform: scale(1.15); background: rgba(220, 140, 255, 0.95); }
}

/* ── NPC Portraits (Apartment map) ── */
.location-npc-portrait {
    position: absolute;
    transform: translate(0, -50%);
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    z-index: 10;
    padding: 4px 10px 4px 4px;
    border-radius: 24px;
    background: rgba(20, 15, 30, 0.7);
    border: 1px solid rgba(255, 200, 255, 0.2);
    backdrop-filter: blur(var(--blur-sm));
    transition: background 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}
.location-npc-portrait:hover {
    background: rgba(80, 30, 100, 0.85);
    border-color: rgba(255, 200, 255, 0.5);
    transform: translate(0, -50%) scale(1.05);
}
.location-npc-portrait-img {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid rgba(255, 200, 255, 0.4);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
    flex-shrink: 0;
}
.location-npc-portrait-label {
    font-size: 11px;
    font-weight: 600;
    color: rgba(255, 245, 255, 0.9);
    white-space: nowrap;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
    max-width: 140px;
    overflow: hidden;
    text-overflow: ellipsis;
}
.location-npc-portrait .location-hotspot-num {
    position: absolute;
    top: -6px;
    right: -6px;
}
.location-npc-portrait-pulse {
    animation: npc-portrait-pulse 2.4s ease-in-out infinite;
}
@keyframes npc-portrait-pulse {
    0%, 100% { border-color: rgba(255, 200, 255, 0.2); box-shadow: 0 2px 8px rgba(0,0,0,0.3); }
    50% { border-color: rgba(255, 200, 255, 0.5); box-shadow: 0 2px 12px rgba(160, 100, 200, 0.3); }
}
.location-npc--master { }
.location-npc--girlfriend { }

/* Popover panel (desktop) — appears next to hotspot.
   It is appended to document.body with position:fixed (see locations.js
   _showPopover / _showNpcPopover), so the `zoom` that the Text/Interface
   Size slider applies to #screen-game-view does NOT reach it. Without the
   transform below the popover renders at 1x while the rest of the UI is at
   the user's scale — at 200% its text looked tiny next to the zoomed map.
   Scale it by --overlay-zoom (the same var every other body-mounted overlay
   uses; BUG_PATTERNS § 47). transform-origin is `top left` for the common
   left-anchored case; JS flips it to `top right` when the popover is
   right-anchored so it grows away from the pin instead of off-screen.
   max-height keeps a tall (many-action) popover scrollable at high zoom. */
.location-popover {
    background: rgba(20, 15, 30, 0.96);
    border: 1px solid rgba(255, 200, 255, 0.2);
    border-radius: 10px;
    padding: 8px;
    min-width: 180px;
    max-width: 260px;
    backdrop-filter: blur(var(--blur-lg));
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6), 0 0 12px rgba(160, 100, 200, 0.15);
    transform: scale(var(--overlay-zoom, 1));
    transform-origin: top left;
    max-height: calc(90vh / var(--overlay-zoom, 1));
    overflow-y: auto;
    animation: popover-in 0.15s ease-out;
}
/* Keep scale fixed at --overlay-zoom across the whole entrance so the rAF
   off-screen correction in JS measures the true (scaled) height. */
@keyframes popover-in {
    from { opacity: 0; transform: translateY(-4px) scale(var(--overlay-zoom, 1)); }
    to { opacity: 1; transform: translateY(0) scale(var(--overlay-zoom, 1)); }
}
.location-popover-title {
    font-size: 13px;
    font-weight: 700;
    color: rgba(255, 245, 255, 0.9);
    padding: 4px 8px 6px;
    border-bottom: 1px solid rgba(255, 200, 255, 0.1);
    margin-bottom: 4px;
}
.location-popover-item {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    width: 100%;
    padding: 7px 8px;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: rgba(255, 245, 255, 0.85);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s ease;
    text-align: left;
}
.location-popover-item:hover {
    background: rgba(160, 100, 220, 0.2);
}
.location-popover-item:active {
    background: rgba(160, 100, 220, 0.35);
}
.location-popover-item--main {
    font-weight: 700;
}
.location-popover-item--disabled {
    opacity: 0.6;
    cursor: not-allowed;
}
.location-popover-reason {
    width: 100%;
    font-size: 10px;
    color: #ff9ed0;
    font-weight: 500;
    margin-top: -2px;
    padding-left: 26px;
}
.bottom-sheet-action-reason {
    display: block;
    font-size: 11px;
    color: #ff9ed0;
    font-weight: 500;
    margin-top: 2px;
}
.location-popover-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: rgba(20, 15, 30, 0.9);
    border: 1px solid rgba(255, 200, 255, 0.25);
    font-size: 10px;
    font-weight: 700;
    color: var(--gold, #d4a855);
    flex-shrink: 0;
}
.location-popover-text {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.location-popover-meta {
    display: flex;
    gap: 4px;
    align-items: center;
    width: 100%;
    padding-left: 26px;
    margin-top: -2px;
}
.location-popover-cost {
    font-family: 'DM Mono', monospace;
    font-size: 9px;
    color: rgba(255, 255, 255, 0.5);
}

/* Mobile bottom-sheet: action list variant (multi-choice) */
.bottom-sheet-actions {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 12px;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
.bottom-sheet-action {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
    padding: 10px 12px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    background: rgba(196, 112, 224, 0.12);
    border: 1px solid rgba(196, 112, 224, 0.3);
    color: var(--text, #f5f0ff);
    cursor: pointer;
    transition: background 0.15s ease;
}
.bottom-sheet-action:hover {
    background: rgba(196, 112, 224, 0.25);
}
.bottom-sheet-action:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.bottom-sheet-action-label { flex: 1; text-align: left; }
.bottom-sheet-action-cost {
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    color: rgba(255, 255, 255, 0.5);
}

/* Per-location color accents */
.location-container { --loc-primary: rgba(200, 150, 255, 0.6); }
.location-container[data-location="Home"]   { --loc-primary: rgba(160, 136, 224, 0.6); }
.location-container[data-location="Bar"]    { --loc-primary: rgba(220, 140, 60, 0.6); }
.location-container[data-location="Park"]   { --loc-primary: rgba(92, 216, 120, 0.6); }
.location-container[data-location="Beach"]  { --loc-primary: rgba(100, 200, 240, 0.6); }
.location-container[data-location="Club"]   { --loc-primary: rgba(180, 80, 220, 0.6); }
.location-container[data-location="Mall"]   { --loc-primary: rgba(200, 180, 140, 0.6); }
.location-container[data-location="Salon"]  { --loc-primary: rgba(232, 140, 184, 0.6); }
.location-container[data-location="Gym"]    { --loc-primary: rgba(220, 140, 60, 0.6); }
.location-container[data-location="Clinic"] { --loc-primary: rgba(60, 180, 200, 0.6); }

/* Location name overlay */
.location-name {
    position: absolute;
    top: 10px;
    left: 14px;
    font-size: 15px;
    font-weight: 700;
    color: rgba(255, 245, 255, 0.9);
    z-index: 4;
    text-shadow: 0 1px 4px rgba(0,0,0,0.8), 0 0 8px rgba(0,0,0,0.5);
    letter-spacing: 0.5px;
}

/* Unmatched choices below map */
.location-extra-choices {
    padding: 8px 16px;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.location-choice-btn {
    font-size: 11px !important;
    padding: 6px 12px !important;
}


/* ============================================
   31. COMPUTER DESKTOP + BROWSER
   ============================================ */

/* Streaming overlay — flex-sibling of #story in .center-panel.
   Same clip risk as velvet_work / bar minigame: parent has overflow:hidden
   so a tall streaming UI (chat + viewer list + action buttons + tips) can
   push content below the viewport on short screens. Internal scroll keeps
   everything reachable.

   v0.2.6.5 chat-layout rework (foundby player report — chat shrinks story):
   - Desktop (≥1024px): split into .stream-main (flex 1) + .stream-chat-rail
     (240px fixed) flex-row. Chat lives in its own column → story column gets
     full width back, no longer competes with chat content height.
   - Mobile (<1024px): chat absolutely positioned overlay (top of streaming-
     overlay), default collapsed via .stream-chat-collapsed (only toggle row
     visible). Expanded shows chat as 30vh overlay over story content, doesn't
     displace flex siblings. */
.streaming-overlay {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* Desktop layout: Twitch-style flex-row with chat sidebar. */
@media (min-width: 1024px) {
    .streaming-overlay {
        display: flex;
        flex-direction: row;
        align-items: stretch;
        overflow-y: hidden;
    }
    .streaming-overlay .stream-main {
        flex: 1 1 auto;
        min-width: 0;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
    .streaming-overlay .stream-chat-rail {
        flex: 0 0 240px;
        max-width: 240px;
        display: flex;
        flex-direction: column;
        background: rgba(14, 11, 20, 0.55);
        border-left: 1px solid var(--border);
        min-height: 0;
    }
    .streaming-overlay .stream-chat-rail .stream-chat-header {
        padding: 8px 12px;
        flex: 0 0 auto;
    }
    .streaming-overlay .stream-chat-rail #stream-chat {
        flex: 1 1 auto;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        padding: 6px 10px 10px;
    }
}

/* Mobile/tablet layout: chat is an absolute overlay anchored to top of
   streaming-overlay. Default collapsed = just toggle row, expanded = 30vh
   overlay with internal scroll. Story column stays flex-sized regardless.

   The toggle is the existing #stream-chat-toggle inside .stream-chat-header
   (streaming.js _buildUI line 389-391). It already toggles .hidden on the
   chat list. We layer additional .stream-chat-collapsed state on the rail
   container so the header stays visible while the message list collapses. */
@media (max-width: 1023px) {
    .streaming-overlay .stream-chat-rail {
        position: absolute;
        top: var(--stream-header-height, 64px);
        right: 0;
        left: 0;
        z-index: 12;
        background: rgba(14, 11, 20, 0.92);
        border-bottom: 1px solid var(--border);
        max-height: 30vh;
        display: flex;
        flex-direction: column;
        backdrop-filter: blur(4px);
        -webkit-backdrop-filter: blur(4px);
    }
    .streaming-overlay .stream-chat-rail.stream-chat-collapsed {
        max-height: 32px;
    }
    .streaming-overlay .stream-chat-rail.stream-chat-collapsed #stream-chat {
        display: none;
    }
    /* Header gets button-like affordance on mobile so players know the
       collapsed bar is tappable. Subtle gold-tinted gradient + top/bottom
       borders set it apart from the stream body; chevron on the right
       rotates between ▾ (expanded) and ▸ (collapsed, rotated -90deg). */
    .streaming-overlay .stream-chat-rail .stream-chat-header {
        padding: 8px 14px;
        flex: 0 0 auto;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: space-between;
        background: linear-gradient(180deg, rgba(232, 200, 96, 0.08) 0%, rgba(14, 11, 20, 0.4) 100%);
        border-top: 1px solid rgba(232, 200, 96, 0.18);
        border-bottom: 1px solid rgba(232, 200, 96, 0.10);
        transition: background 0.2s;
    }
    .streaming-overlay .stream-chat-rail .stream-chat-header:active {
        background: linear-gradient(180deg, rgba(232, 200, 96, 0.18) 0%, rgba(14, 11, 20, 0.6) 100%);
    }
    .streaming-overlay .stream-chat-rail .stream-chat-header::after {
        content: '\25BE'; /* down-pointing triangle */
        color: var(--text-dim);
        font-size: 14px;
        line-height: 1;
        margin-left: 8px;
        transition: transform 0.2s ease;
    }
    .streaming-overlay .stream-chat-rail.stream-chat-collapsed .stream-chat-header::after {
        transform: rotate(-90deg);
        color: var(--gold);
    }
    /* Pulse the chevron when there are new unread messages on collapsed
       state so the indicator catches the eye even before the player looks
       directly at the bar. */
    .streaming-overlay .stream-chat-rail.stream-chat-collapsed .stream-chat-header:has(.stream-chat-badge:not(.hidden))::after {
        animation: chat-chevron-pulse 1.8s ease-in-out infinite;
    }
    @keyframes chat-chevron-pulse {
        0%, 100% { transform: rotate(-90deg) scale(1); }
        50%      { transform: rotate(-90deg) scale(1.25); }
    }
    .streaming-overlay .stream-chat-rail #stream-chat {
        flex: 1 1 auto;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        padding: 6px 10px 10px;
    }
}

/* Computer overlay — fills the center column */
.computer-overlay {
    position: absolute;
    inset: 0;
    z-index: 10;
    overflow: hidden;
}

/* Desktop mode — starfield wallpaper + app icon grid */
.computer-desktop {
    position: relative;
    width: 100%;
    height: 100%;
    background: rgb(14, 10, 28);
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.desktop-stars {
    position: absolute;
    inset: 0;
    pointer-events: none;
}
.desktop-star {
    position: absolute;
    border-radius: 50%;
    background: rgba(200, 190, 230, 0.5);
}
.desktop-star-twinkle {
    animation: star-twinkle 3s ease-in-out infinite;
}
@keyframes star-twinkle {
    0%, 100% { opacity: 0.3; }
    50% { opacity: 0.9; }
}

/* Desktop app icon grid (centered) */
.desktop-icon-area {
    position: relative;
    z-index: 2;
    flex: 1;
    display: grid;
    grid-template-columns: repeat(auto-fill, 110px);
    gap: 12px;
    padding: 28px;
    align-content: start;
    justify-content: center;
}
.desktop-app-icon {
    width: 110px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    transition: all 0.2s ease;
    padding: 12px 6px;
    border-radius: 10px;
}
.desktop-app-icon:hover { background: rgba(100, 80, 160, 0.15); }
.desktop-app-icon:active { transform: scale(0.93); }
.desktop-app-icon-img {
    width: 72px;
    height: 72px;
    border-radius: 14px;
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 32px;
    transition: all 0.2s ease;
}
.desktop-app-icon:hover .desktop-app-icon-img {
    border-color: var(--border-glow);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
    transform: translateY(-2px);
}
.desktop-app-name {
    font-size: 11px;
    color: var(--text-dim);
    text-align: center;
    line-height: 1.2;
    max-width: 64px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}

/* Desktop X-close button */
.desktop-close-btn {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 10;
    width: 28px;
    height: 28px;
    border-radius: 6px;
    background: rgba(40, 30, 60, 0.4);
    color: var(--text-faint);
    font-size: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s ease;
}
.desktop-close-btn:hover { background: rgba(200, 60, 60, 0.4); color: var(--text); }

/* Taskbar */
.desktop-taskbar {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 44px;
    z-index: 5;
    background: linear-gradient(180deg, rgba(20, 15, 30, 0.95), rgba(14, 10, 24, 0.98));
    border-top: 1px solid rgba(46, 34, 66, 0.5);
    display: flex;
    align-items: center;
    padding: 0 10px;
    gap: 8px;
    backdrop-filter: blur(var(--blur-sm));
    -webkit-backdrop-filter: blur(var(--blur-sm));
}
.taskbar-start {
    padding: 4px 12px;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 600;
    color: var(--gold);
    transition: all 0.2s;
    display: flex;
    align-items: center;
    gap: 4px;
}
.taskbar-start:hover { background: rgba(100, 80, 160, 0.2); }
.taskbar-start-icon { font-size: 10px; }
/* Porn category grid */
.porn-grid-header {
    display: flex; align-items: center; gap: 8px;
    font-size: 18px; font-weight: 700; color: #d86050;
    padding: 16px 20px 8px;
}
.porn-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 12px; padding: 8px 20px 16px;
}
.porn-tile {
    background: var(--bg-lighter); border-radius: 10px; overflow: hidden;
    border: 1px solid var(--border); cursor: pointer; transition: all 0.2s;
}
.porn-tile:hover { transform: translateY(-2px); box-shadow: 0 4px 16px rgba(0,0,0,0.4); border-color: var(--border-glow); }
.porn-tile-preview {
    height: 100px; display: flex; align-items: center; justify-content: center;
    overflow: hidden;
}
.porn-tile-info { padding: 8px 10px; }
.porn-tile-name { font-size: 13px; font-weight: 700; }
.porn-tile-desc { font-size: 10px; color: var(--text-muted); }
.porn-tile-views { font-size: 9px; color: var(--text-faint); margin-top: 2px; }
.porn-back-btn {
    display: block; margin: 8px auto 16px; padding: 6px 16px;
    background: none; border: 1px solid var(--border); border-radius: 6px;
    color: var(--text-dim); font-size: 11px; cursor: pointer;
}
.porn-back-btn:hover { border-color: var(--border-glow); color: var(--text); }

.taskbar-windows { display: flex; gap: 4px; flex: 1; }
.taskbar-window-btn {
    padding: 2px 8px; border-radius: 3px; font-size: 10px;
    background: rgba(40, 30, 60, 0.6); border: 1px solid rgba(60, 50, 80, 0.5);
    color: var(--text-dim); cursor: default;
}
.taskbar-window-active { background: rgba(60, 40, 90, 0.8); color: var(--text); border-color: rgba(100, 70, 140, 0.5); }
.taskbar-tray { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.taskbar-divider {
    width: 1px;
    height: 24px;
    background: rgba(46, 34, 66, 0.5);
}
.taskbar-clock {
    margin-left: auto;
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    color: var(--text-dim);
}
.taskbar-power {
    font-size: 14px;
    color: var(--text-dim);
    padding: 4px 8px;
    border-radius: 4px;
    transition: all 0.2s;
}
.taskbar-power:hover { background: rgba(200, 60, 60, 0.2); color: var(--red); }

/* Start menu popup */
.start-menu, .desktop-start-menu {
    position: absolute;
    bottom: 48px;
    left: 10px;
    z-index: 10;
    background: linear-gradient(180deg, var(--bg-warm), var(--bg-deep));
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 6px;
    min-width: 160px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
    animation: overlay-in 0.2s ease both;
}
.start-menu.hidden, .desktop-start-menu.hidden { display: none; }
.start-menu-item {
    width: 100%;
    padding: 8px 12px;
    border-radius: 6px;
    font-size: 12px;
    color: var(--text-dim);
    text-align: left;
    display: flex;
    align-items: center;
    gap: 8px;
    transition: all 0.15s;
}
.start-menu-item:hover { background: rgba(100, 80, 160, 0.15); color: var(--text); }
.start-menu-item .power-icon { color: var(--red); }
.start-menu-divider { height: 1px; background: var(--border); margin: 4px 8px; }

/* Browser container — fills parent, flex column */
.computer-browser {
    position: relative;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    background: var(--bg-deep);
}

/* Browser chrome bar (tabs + address + close) */
.browser-chrome {
    background: var(--bg-warm);
    border-bottom: 1px solid var(--border);
    padding: 8px 12px;
    flex-shrink: 0;
    position: relative;
}
.browser-tabs, .browser-tab-bar {
    display: flex;
    gap: 4px;
    margin-bottom: 6px;
}
.browser-tab {
    padding: 4px 12px;
    font-size: 10px;
    border-radius: 6px 6px 0 0;
    background: rgba(20, 15, 30, 0.5);
    border: 1px solid var(--border);
    border-bottom: none;
    color: var(--text-dim);
    display: flex;
    align-items: center;
    gap: 4px;
}
.browser-tab.active { background: var(--bg-panel); color: var(--text); }
.browser-tab-icon { font-size: 10px; }
.browser-tab-name { font-size: 10px; }
.browser-address-bar, .browser-address {
    width: 100%;
    height: 28px;
    background: rgba(14, 11, 20, 0.6);
    border: 1px solid rgba(46, 34, 66, 0.4);
    border-radius: 6px;
    padding: 0 10px;
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    color: var(--text-faint);
    display: flex;
    align-items: center;
    gap: 6px;
}
.browser-address-lock { font-size: 10px; opacity: 0.5; }
.browser-address-text { font-size: 10px; color: var(--text-faint); }
.browser-close-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: rgba(46, 34, 66, 0.4);
    color: var(--text-faint);
    font-size: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
    z-index: 5;
}
.browser-close-btn:hover { background: rgba(200, 60, 60, 0.4); color: var(--text); }

/* Browser content area (scrollable) */
.browser-content {
    flex: 1;
    overflow-y: auto;
    padding: 16px;
}

/* Website cards in browser mode — grid layout */
.browser-card-grid, .browser-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 10px;
}
.browser-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 14px 10px;
    text-align: center;
    cursor: pointer;
    transition: all 0.2s ease;
}
.browser-card:hover {
    border-color: var(--border-glow);
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.browser-card-icon { font-size: 24px; margin-bottom: 6px; }
.browser-card-info { }
.browser-card-name { font-size: 11px; font-weight: 600; color: var(--text); margin-bottom: 2px; }
.browser-card-url { font-family: 'DM Mono', monospace; font-size: 8px; color: var(--text-faint); }

/* Computer UI: disabled state */
.desktop-app-icon.disabled,
.browser-card.disabled,
.porn-tile.disabled {
    opacity: 0.35;
    pointer-events: none;
    filter: grayscale(0.3);
}
.computer-disabled-reason {
    font-size: 8px;
    color: var(--text-faint);
    margin-top: 2px;
    text-align: center;
    line-height: 1.2;
}

/* Computer UI: cost badges */
.computer-badges {
    display: flex;
    gap: 3px;
    flex-wrap: wrap;
    justify-content: center;
    margin-top: 4px;
}


/* ============================================
   32. STREAMING CHAT OVERLAY
   ============================================ */

.stream-chat-container {
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: 220px;
    background: rgba(14, 11, 20, 0.9);
    border-left: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    z-index: 10;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
.stream-chat-container.hidden { display: none; }

.stream-chat-header {
    padding: 8px 12px;
    border-bottom: 1px solid var(--border);
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-dim);
}

.stream-chat-toggle {
    background: none; border: none; color: var(--text-dim); font-size: 10px;
    font-weight: 600; text-transform: uppercase; letter-spacing: 1px;
    cursor: pointer; padding: 0; position: relative;
}
.stream-chat-toggle:hover { color: var(--text); }
.stream-chat-badge {
    display: inline-block; background: var(--rose); color: #fff; font-size: 9px;
    padding: 1px 5px; border-radius: 8px; margin-left: 4px; font-weight: 700;
}

.stream-chat-messages {
    flex: 1;
    overflow-y: auto;
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.stream-chat-msg {
    font-size: 11px;
    line-height: 1.4;
    padding: 2px 0;
    animation: text-fade-in 0.2s ease both;
}
.stream-chat-name {
    font-weight: 600;
    margin-right: 4px;
}
.stream-chat-name.hype { color: var(--gold); }
.stream-chat-name.regular { color: var(--orchid); }
.stream-chat-name.normal { color: var(--text-dim); }

/* Chat bubbles (JS class names) */
.stream-chat-bubble { padding: 2px 0; font-size: 12px; line-height: 1.3; }
.stream-chat-enter { animation: chat-slide-in 0.2s ease both; }
@keyframes chat-slide-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }
.stream-chat-username { font-weight: 600; margin-right: 4px; }
.stream-chat-message { color: var(--text-body); }
.stream-chat-tip-msg { background: rgba(232, 200, 96, 0.08); padding: 2px 6px; border-radius: 4px; border-left: 2px solid var(--gold); }
.stream-chat-tip-msg .stream-chat-message { color: var(--gold); }
.stream-chat-badge-regular { font-size: 10px; margin-right: 2px; }
.stream-chat-text { color: var(--text-body); }

/* Floating tip animation */
.stream-tip-float {
    position: absolute;
    font-family: 'DM Mono', monospace;
    font-size: 14px;
    font-weight: 700;
    color: var(--gold);
    text-shadow: 0 0 8px rgba(232, 200, 96, 0.4);
    pointer-events: none;
    animation: tip-float 2s ease both;
    z-index: 20;
}
@keyframes tip-float {
    0% { opacity: 0; transform: translateY(0) scale(0.8); }
    20% { opacity: 1; transform: translateY(-10px) scale(1.1); }
    100% { opacity: 0; transform: translateY(-60px) scale(0.9); }
}

/* ============================================


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Porn grid + browser chrome
   ============================================ */
/* ============================================
   FIX: Porn grid on computer — large category tiles
   ============================================ */
.porn-grid {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 14px !important;
    padding: 16px 20px !important;
}
.porn-tile {
    border-radius: 12px !important;
    overflow: hidden;
    cursor: pointer;
    transition: all 0.2s ease;
    border: 1px solid rgba(46, 34, 66, 0.4) !important;
    background: rgba(20, 15, 30, 0.6) !important;
}
.porn-tile:hover {
    border-color: var(--border-glow) !important;
    transform: translateY(-3px) !important;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5) !important;
}
.porn-tile-preview {
    width: 100% !important;
    height: 140px !important;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background: rgba(15, 10, 25, 0.6);
}
.porn-tile-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.porn-tile-info {
    padding: 10px 12px !important;
}
.porn-tile-name {
    font-size: 14px !important;
    font-weight: 700 !important;
}
.porn-tile-desc {
    font-size: 11px;
    color: var(--text-dim);
    margin-top: 2px;
}
.porn-tile-views {
    font-size: 10px;
    color: var(--text-faint);
    margin-top: 4px;
}
.porn-grid-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 20px;
    font-size: 18px;
    font-weight: 700;
    color: var(--text);
    border-bottom: 1px solid var(--border);
    background: rgba(15, 10, 25, 0.4);
}

/* Inline browser chrome (injected into story-content for porn viewing immersion) */
.browser-chrome-inline {
    background: #1e1a2c;
    border: 1px solid var(--border);
    border-radius: 10px 10px 0 0;
    margin: -16px -20px 14px;
    overflow: hidden;
    animation: text-fade-in 0.3s ease both;
}
.bci-tabs {
    display: flex;
    align-items: center;
    padding: 6px 10px 0;
    gap: 2px;
    background: #16121e;
}
.bci-tab {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 6px 14px;
    background: #1e1a2c;
    border-radius: 8px 8px 0 0;
    font-size: 11px;
    color: var(--text-dim);
}
.bci-tab.active {
    color: var(--text);
    background: #262040;
}
.bci-tab-icon { font-size: 12px; }
.bci-tab-name { font-weight: 500; }
.bci-tab-plus {
    padding: 4px 8px;
    font-size: 14px;
    color: var(--text-faint);
    cursor: default;
}
.bci-address {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px 8px;
    background: #262040;
    border-top: 1px solid rgba(46, 34, 66, 0.3);
}
.bci-lock { font-size: 10px; opacity: 0.5; }
.bci-url {
    font-family: 'DM Mono', monospace;
    font-size: 11px;
    color: var(--text-dim);
    background: rgba(15, 12, 22, 0.6);
    padding: 3px 10px;
    border-radius: 4px;
    flex: 1;
}

/* Compact choice buttons inside browser (porn viewing) */
.browser-compact-choices {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 20px 16px;
    border-top: 1px solid var(--border);
}
.browser-compact-btn {
    flex: 1 1 auto;
    min-width: 120px;
    padding: 10px 16px;
    background: var(--bg-choice);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
    text-align: center;
}
.browser-compact-btn:hover {
    background: var(--bg-choice-hover);
    border-color: var(--border-glow);
    transform: translateY(-1px);
}
.browser-compact-btn.disabled {
    opacity: 0.35;
    pointer-events: none;
}

/* Story content embedded inside browser (porn viewing) */
.browser-story-embed {
    padding: 16px 20px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.browser-story-embed .story-image-wrapper {
    max-height: 320px;
    border-radius: 8px;
    overflow: hidden;
}
.browser-story-embed .story-image-wrapper img,
.browser-story-embed .story-image {
    width: 100%;
    max-height: 320px;
    object-fit: contain;
    border-radius: 8px;
    display: block;
}
.browser-story-embed .story-text,
.browser-story-embed .dialogue-card,
.browser-story-embed .info-card {
    font-size: 14px;
    line-height: 1.6;
    color: var(--text-body);
}
.porn-back-btn {
    display: block;
    margin: 12px auto;
    padding: 8px 20px;
    background: rgba(46, 34, 66, 0.4);
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--text-dim);
    font-size: 12px;
    cursor: pointer;
    transition: all 0.2s ease;
}
.porn-back-btn:hover {
    color: var(--text);
    border-color: var(--border-glow);
}

/* ============================================
   ENDGAME PROGRESS PANEL (F04)
   Shows player progress vs each ending gate.
   ============================================ */
.overlay-endgame-progress .eg-box {
    max-width: 640px;
    width: 92vw;
}
.overlay-endgame-progress .eg-body {
    padding: 16px 20px 8px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.overlay-endgame-progress .eg-footer {
    padding: 8px 20px 18px;
}
.overlay-endgame-progress .eg-hint {
    font-size: 11.5px;
    color: var(--text-dim);
    font-style: italic;
    margin: 0;
    text-align: center;
}

.eg-card {
    background: rgba(46, 34, 66, 0.35);
    border: 1px solid rgba(200, 140, 180, 0.18);
    border-radius: 10px;
    padding: 12px 14px;
    transition: border-color 0.2s;
}
.eg-card-closed {
    opacity: 0.55;
    border-color: rgba(180, 60, 60, 0.25);
}
.eg-card-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 2px;
}
.eg-card-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--rose);
    letter-spacing: 0.5px;
    margin: 0;
    text-transform: uppercase;
}
.eg-card-progress {
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 11px;
    color: var(--text-dim);
}
.eg-card-tagline {
    font-size: 11.5px;
    font-style: italic;
    color: var(--text-dim);
    margin-bottom: 4px;
}
/* Audit D48: path-imagery flavour line. Reads as story, sits between the
   tagline (one-liner) and the requirement list (numbers). */
.eg-card-flavour {
    font-family: 'Crimson Pro', serif;
    font-size: 12.5px;
    color: var(--text-body);
    line-height: 1.5;
    margin-bottom: 10px;
    padding-left: 8px;
    border-left: 2px solid rgba(196, 112, 224, 0.25);
}
.eg-card-e1 .eg-card-flavour { border-left-color: rgba(232, 140, 184, 0.35); }
.eg-card-e2 .eg-card-flavour { border-left-color: rgba(120, 160, 220, 0.35); }
.eg-card-e3 .eg-card-flavour { border-left-color: rgba(232, 200, 96, 0.35); }
.eg-card-closed-note {
    font-size: 11px;
    color: rgba(220, 110, 110, 0.85);
    margin-bottom: 8px;
    padding: 4px 8px;
    background: rgba(180, 60, 60, 0.1);
    border-radius: 4px;
}
.eg-card-bar {
    height: 4px;
    background: rgba(0, 0, 0, 0.35);
    border-radius: 2px;
    overflow: hidden;
    margin-bottom: 10px;
}
.eg-card-bar-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--rose), var(--accent-soft, #c08aa8));
    transition: width 0.3s ease;
}
.eg-card-rows {
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.eg-row {
    display: grid;
    grid-template-columns: 22px 1fr auto;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    padding: 2px 0;
}
.eg-row-icon {
    color: var(--text-muted, #6c7590);
    font-size: 13px;
    text-align: center;
}
.eg-icon-ok {
    color: var(--accent-soft, #98d4a8);
}
.eg-row-label {
    color: var(--text-dim);
}
.eg-row-val {
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 11.5px;
    color: var(--text-muted, #6c7590);
}
.eg-val-ok {
    color: var(--accent-soft, #98d4a8);
}
.eg-val-pending {
    color: var(--text-dim);
}

/* ============================================
   ENDSCREEN OVERLAY (run summary on ending)
   ============================================ */
.overlay-endscreen {
    z-index: 12000;
}
.overlay-endscreen .es-box {
    max-width: 680px;
    width: 92vw;
    margin: 0 auto;
    max-height: 92vh;
    overflow-y: auto;
    padding: 0;
    background: linear-gradient(180deg, rgba(28, 18, 38, 0.98), rgba(38, 24, 56, 0.98));
    border: 1px solid rgba(200, 140, 180, 0.35);
    border-radius: 14px;
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6),
                0 0 36px rgba(232, 140, 184, 0.18) inset;
}
.overlay-endscreen .es-hero {
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #000;
    border-radius: 14px 14px 0 0;
    overflow: hidden;
    position: relative;
}
.overlay-endscreen .es-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(0,0,0,0) 55%, rgba(28, 18, 38, 0.9) 100%);
    pointer-events: none;
}
.overlay-endscreen .es-hero-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.overlay-endscreen .es-body {
    padding: 18px 26px 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}
.overlay-endscreen .es-title-block {
    text-align: center;
    margin-top: -6px;
}
.overlay-endscreen .es-tagline {
    font-size: 12px;
    font-style: italic;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 1.5px;
    margin-bottom: 4px;
}
.overlay-endscreen .es-title {
    font-family: 'Crimson Pro', serif;
    font-size: 36px;
    font-weight: 600;
    color: var(--rose);
    margin: 0;
    letter-spacing: 1px;
    text-shadow: 0 2px 14px rgba(232, 140, 184, 0.25);
}
.overlay-endscreen .es-summary {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px 18px;
    padding: 14px 16px;
    background: rgba(46, 34, 66, 0.35);
    border: 1px solid rgba(200, 140, 180, 0.18);
    border-radius: 10px;
}
.overlay-endscreen .es-stat-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 10px;
    font-size: 13px;
}
.overlay-endscreen .es-stat-label {
    color: var(--text-dim);
}
.overlay-endscreen .es-stat-value {
    font-family: ui-monospace, "SF Mono", Menlo, monospace;
    color: var(--rose);
    font-weight: 600;
}
.overlay-endscreen .es-thanks {
    font-family: 'Crimson Pro', serif;
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--text-body);
    text-align: center;
    padding: 0 4px;
}
.overlay-endscreen .es-thanks p {
    margin: 6px 0;
}
.overlay-endscreen .es-community {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: -4px;
}
@media (min-width: 540px) {
    .overlay-endscreen .es-community {
        flex-direction: row;
    }
}
.overlay-endscreen .es-cta {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 14px;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.3px;
    border-radius: 8px;
    text-decoration: none;
    transition: transform 0.1s, box-shadow 0.2s, border-color 0.2s;
    cursor: pointer;
}
.overlay-endscreen .es-cta:hover {
    transform: translateY(-1px);
}
.overlay-endscreen .es-cta-icon {
    font-size: 15px;
    line-height: 1;
}
.overlay-endscreen .es-cta-discord {
    background: rgba(88, 101, 242, 0.18);
    color: #c8d0ff;
    border: 1px solid rgba(88, 101, 242, 0.45);
}
.overlay-endscreen .es-cta-discord:hover {
    background: rgba(88, 101, 242, 0.28);
    border-color: rgba(88, 101, 242, 0.7);
    box-shadow: 0 4px 14px rgba(88, 101, 242, 0.25);
}
.overlay-endscreen .es-cta-patreon {
    background: rgba(232, 90, 124, 0.16);
    color: #ffd0dc;
    border: 1px solid rgba(232, 90, 124, 0.45);
}
.overlay-endscreen .es-cta-patreon:hover {
    background: rgba(232, 90, 124, 0.26);
    border-color: rgba(232, 90, 124, 0.7);
    box-shadow: 0 4px 14px rgba(232, 90, 124, 0.25);
}
.overlay-endscreen .es-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 4px;
}
.overlay-endscreen .es-btn {
    width: 100%;
    padding: 13px 16px;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.4px;
    border-radius: 9px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    color: white;
    cursor: pointer;
    transition: transform 0.1s, box-shadow 0.2s, filter 0.2s;
}
.overlay-endscreen .es-btn:hover {
    transform: translateY(-1px);
    filter: brightness(1.1);
}
/* Continue Playing — rose, the "stay in your world" choice */
.overlay-endscreen .es-btn-continue {
    background: linear-gradient(180deg, var(--rose), #b25a8a);
    box-shadow: 0 6px 18px rgba(232, 140, 184, 0.3);
}
/* New Game — amber/gold, the "fresh run + perks reward" choice */
.overlay-endscreen .es-btn-restart {
    background: linear-gradient(180deg, #e89a4c, #b56a2a);
    box-shadow: 0 6px 18px rgba(232, 154, 76, 0.28);
}
/* Main Menu — violet, the "stepping back" choice */
.overlay-endscreen .es-btn-menu {
    background: linear-gradient(180deg, #8a6dc8, #5a3f8c);
    box-shadow: 0 6px 18px rgba(138, 109, 200, 0.28);
}
@media (min-width: 640px) {
    .overlay-endscreen .es-actions {
        flex-direction: row;
    }
    .overlay-endscreen .es-btn {
        flex: 1;
    }
}
/* ============================================
   11. MISC POLISH — residual fixes
   ============================================ */
/* ============================================
   C3: Mobile touch target fixes (44px minimum)
   Audit D08 (2026-05-11): comment claimed 44 but the values were 36-40.
   Brought every control up to WCAG 2.5.5 AAA (44x44) — covers the systemic
   touch-target finding for the mobile breakpoint. char-footer-btn font
   bumped from 11px to 13px to match D28 readability fix.
   ============================================ */
@media (max-width: 767px) {
    .actions-secondary .action-icon-only { width: 44px; height: 44px; min-width: 44px; }
    .btn-actions-more { min-height: 44px; padding: 10px 14px; }
    .char-toggle-btn { min-height: 44px; }
    .char-footer-btn { min-height: 44px; padding: 8px 12px; font-size: 13px; }
    .time-seg { padding: 10px 10px; min-height: 44px; }
    .btn-wait { width: 44px; height: 44px; }
    .btn-phone-nav { width: 44px; height: 44px; }
    .wardrobe-btn { min-height: 44px; }
    .btn-unequip { min-height: 44px; }

    /* Disable vignette overlay on mobile (GPU perf) */
    body::after { display: none; }
}

/* ============================================
   H4: Missing hover/active states
   ============================================ */
.save-slot-btn {
    transition: all 0.2s var(--ease-out);
}
.save-slot-btn:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-sm);
}
.hints-rent:hover {
    border-color: var(--border-glow);
    background: rgba(100, 60, 140, 0.08);
}
.dot {
    cursor: pointer;
    transition: all 0.2s ease;
}
.dot:hover { transform: scale(1.3); }

/* ============================================
   L6: Stat shimmer — only on change (not infinite)
   ============================================ */
.stat-fill::after {
    animation: none !important;
}
.stat-fill.shimmer::after {
    animation: stat-shimmer 1.5s ease 2 !important;
}
@keyframes stat-shimmer {
    0% { background-position: -100% 0; }
    100% { background-position: 200% 0; }
}

/* ============================================
   M7: Choice animation easing
   ============================================ */
.story-content > * {
    animation-timing-function: var(--ease-out) !important;
}
@media (max-width: 480px) { .webshop-grid { grid-template-columns: 1fr; } }

/* ============================================
   Streaming Action Intensity on Choice Buttons
   ============================================ */
.choice-btn.stream-action-safe { border-left: 3px solid #5cd89c; }
.choice-btn.stream-action-spicy { border-left: 3px solid #e8c860; }
.choice-btn.stream-action-extreme { border-left: 3px solid #e06878; }
.choice-btn.stream-action-collab { border-left: 3px solid #c470e0; }

.stream-action-icon {
    width: 22px;
    height: 22px;
    vertical-align: middle;
    margin-right: 4px;
    margin-left: 2px;
    flex-shrink: 0;
    object-fit: contain;
    opacity: 0.9;
}

/* ============================================
   Combined Welcome modal: 18+ verification + privacy opt-ins.
   Replaces the legacy age-warning + analytics-consent overlays.
   Layout: icon + title + 18+ body, divider, privacy body + toggles,
   then primary/secondary action row.
   ============================================ */
.welcome-modal { z-index: var(--z-modal, 1000); }
.welcome-modal.hidden { display: none; }
.welcome-modal-box {
    max-width: 480px;
    padding: 32px 32px 28px;
    background: linear-gradient(165deg, rgba(32, 22, 48, 0.98), rgba(18, 14, 28, 0.98));
    border: 1px solid rgba(228, 140, 184, 0.4);
    border-radius: 14px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.65), 0 0 40px rgba(196, 112, 224, 0.12);
    text-align: center;
}
.welcome-modal-icon {
    font-size: 44px;
    font-weight: 700;
    color: var(--rose, #e88cb8);
    margin-bottom: 10px;
    text-shadow: 0 0 20px rgba(232, 140, 184, 0.3);
    letter-spacing: 1px;
}
.welcome-modal-box h2 {
    margin: 0 0 14px;
    font-family: 'Crimson Pro', Georgia, serif;
    font-size: 22px;
    color: var(--rose, #e88cb8);
    letter-spacing: 0.5px;
}
.uiscale-modal-icon { letter-spacing: 0; }
/* First-launch display-size prompt: slider row with A/A size marks. */
.uiscale-prompt-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 4px 0 6px;
}
.uiscale-prompt-mark {
    color: var(--rose, #e88cb8);
    font-weight: 700;
    flex-shrink: 0;
    line-height: 1;
}
.uiscale-prompt-small { font-size: 13px; }
.uiscale-prompt-big { font-size: 26px; }
.uiscale-slider {
    flex: 1;
    -webkit-appearance: none;
    appearance: none;
    height: 6px;
    border-radius: 3px;
    background: rgba(232, 140, 184, 0.22);
    outline: none;
    cursor: pointer;
}
.uiscale-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--rose, #e88cb8);
    box-shadow: 0 0 10px rgba(232, 140, 184, 0.5);
    cursor: pointer;
}
.uiscale-slider::-moz-range-thumb {
    width: 20px;
    height: 20px;
    border: none;
    border-radius: 50%;
    background: var(--rose, #e88cb8);
    box-shadow: 0 0 10px rgba(232, 140, 184, 0.5);
    cursor: pointer;
}
.uiscale-prompt-value {
    text-align: center;
    font-weight: 600;
    color: rgba(220, 210, 235, 0.92);
    margin-bottom: 16px;
    font-size: 15px;
}
.welcome-modal-text {
    margin: 0 0 18px;
    font-family: 'Crimson Pro', Georgia, serif;
    font-size: 14px;
    line-height: 1.65;
    color: rgba(220, 210, 235, 0.92);
    text-align: left;
}
.welcome-modal-divider {
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(228, 140, 184, 0.35), transparent);
    margin: 4px 0 16px;
}
.welcome-modal-privacy {
    margin: 0 0 12px;
    font-size: 13px;
    line-height: 1.55;
    color: rgba(200, 192, 220, 0.85);
    text-align: left;
}
.welcome-modal-toggles {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 0 0 22px;
    text-align: left;
}
.welcome-modal-toggle {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border: 1px solid rgba(180, 160, 210, 0.25);
    border-radius: 8px;
    background: rgba(40, 28, 62, 0.5);
    cursor: pointer;
    font-size: 13px;
    line-height: 1.4;
    color: rgba(220, 210, 235, 0.92);
    transition: background 0.15s, border-color 0.15s;
}
.welcome-modal-toggle:hover {
    background: rgba(50, 34, 76, 0.6);
    border-color: rgba(228, 140, 184, 0.4);
}
.welcome-modal-toggle input[type="checkbox"] {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    accent-color: var(--rose, #e88cb8);
    cursor: pointer;
}
.welcome-modal-actions {
    display: flex;
    gap: 10px;
    justify-content: center;
}
.welcome-modal-actions .btn-primary,
.welcome-modal-actions .btn-secondary {
    flex: 1 1 50%;
    padding: 12px 14px;
    font-size: 14px;
    font-weight: 600;
}
.welcome-modal-actions .btn-primary:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    filter: grayscale(0.4);
}

/* Cloud Save Sync — Art. 9 consent modal (reuses .welcome-modal chrome). */
#cloudsync-consent-modal .welcome-modal-box {
    position: relative;
}
.cloudsync-consent-x {
    position: absolute;
    top: 12px;
    right: 12px;
}
.cloudsync-consent-privacy-link {
    text-align: left;
    font-size: 12px;
    margin: 0 0 18px;
}
.cloudsync-consent-privacy-link a {
    color: var(--rose, #e88cb8);
    text-decoration: underline;
}

/* ============================================
   Export-clipboard overlay (Android WebView fallback when
   navigator.share is unavailable). Big textarea with the JSON,
   Copy + Close buttons. Player pastes into Files / Drive / email.
   ============================================ */
.overlay-export-clipboard { z-index: var(--z-modal, 1000); }
.overlay-export-clipboard.hidden { display: none; }
.export-clipboard-box {
    max-width: 540px;
    width: 92vw;
    padding: 24px 24px 20px;
    background: linear-gradient(165deg, rgba(32, 22, 48, 0.98), rgba(18, 14, 28, 0.98));
    border: 1px solid rgba(228, 140, 184, 0.4);
    border-radius: 14px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.65), 0 0 40px rgba(196, 112, 224, 0.12);
}
.export-clipboard-box h2 {
    margin: 0 0 10px;
    font-family: 'Crimson Pro', Georgia, serif;
    font-size: 20px;
    color: var(--rose, #e88cb8);
}
.export-clipboard-hint {
    margin: 0 0 14px;
    font-size: 13px;
    line-height: 1.5;
    color: rgba(220, 210, 235, 0.88);
}
.export-clipboard-hint code {
    padding: 1px 5px;
    background: rgba(60, 40, 90, 0.6);
    border-radius: 3px;
    font-family: 'Menlo', monospace;
    font-size: 12px;
}
.export-clipboard-text {
    width: 100%;
    height: 240px;
    padding: 10px;
    margin-bottom: 14px;
    border: 1px solid rgba(180, 160, 210, 0.35);
    border-radius: 8px;
    background: rgba(12, 8, 22, 0.85);
    color: var(--text, #e2d8ee);
    font-family: 'Menlo', 'Consolas', monospace;
    font-size: 11px;
    line-height: 1.45;
    resize: none;
}
.export-clipboard-actions {
    display: flex;
    gap: 10px;
}
.export-clipboard-actions .btn-primary,
.export-clipboard-actions .btn-secondary {
    flex: 1 1 50%;
    padding: 11px 14px;
    font-size: 14px;
    font-weight: 600;
}
/* ============================================
   INLINE STAT POPUP (floating +3 Fem near story area)
   ============================================ */
.inline-stat-popup {
    position: fixed;
    left: 50%;
    top: 40%;
    transform: translateX(-50%);
    font-family: 'DM Sans', sans-serif;
    font-size: 14px;
    font-weight: 700;
    pointer-events: none;
    /* Animation driven by GSAP */
    z-index: var(--z-topbar);
    text-shadow: 0 2px 8px rgba(0,0,0,0.5);
}
.inline-stat-popup.popup-fem { color: var(--fem); }
.inline-stat-popup.popup-sub { color: var(--sub); }
.inline-stat-popup.popup-arousal { color: var(--arousal); }
.inline-stat-popup.popup-energy { color: var(--energy); }
.inline-stat-popup.popup-money { color: var(--gold); }
.inline-stat-popup.popup-shame { color: var(--shame); }

/* ============================================
   ACHIEVEMENT TOAST UPGRADE (golden shimmer)
   ============================================ */
.achievement-toast {
    overflow: hidden;
}
.achievement-toast::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 10px;
    background: linear-gradient(90deg, transparent, rgba(232, 200, 96, 0.12), transparent);
    background-size: 200% 100%;
    animation: golden-shimmer 2s ease infinite;
    pointer-events: none;
}
@keyframes golden-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* ============================================
   DAY TRANSITION OVERLAY
   ============================================ */
.day-transition {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 300;
    pointer-events: none;
    background: rgba(8,6,12,0.7);
    /* Animation driven by GSAP timeline */
}
.day-transition-text {
    font-family: 'Crimson Pro', serif;
    font-size: 36px;
    color: var(--rose);
    letter-spacing: 6px;
    text-transform: uppercase;
    text-shadow: 0 0 40px rgba(228,140,184,0.3);
}

/* ============================================
   Gallery Group Headers
   ============================================ */
.gallery-group-header {
    grid-column: 1 / -1;
    font-size: 11px;
    color: var(--orchid);
    text-transform: uppercase;
    letter-spacing: 1px;
    padding: 12px 0 4px;
    border-top: 1px solid rgba(196, 112, 224, 0.15);
    margin-top: 8px;
}
.gallery-group-header:first-child {
    border-top: none;
    margin-top: 0;
}

/* ============================================
   Changelog Version Groups
   ============================================ */
.changelog-version-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    margin: 4px 0 0;
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-dim);
    border-radius: 6px;
    transition: background 0.15s ease;
    user-select: none;
}
.changelog-version-header:hover { background: rgba(255,255,255,0.04); }
.changelog-version-header.expanded { color: var(--rose); }
.changelog-chevron { font-size: 10px; min-width: 12px; text-align: center; }
.changelog-date { font-size: 10px; color: var(--text-faint); font-weight: 400; }
.changelog-count {
    font-size: 9px; color: var(--text-faint); background: rgba(255,255,255,0.06);
    padding: 1px 6px; border-radius: 8px; margin-left: auto;
}
.changelog-version-body { padding: 0 0 8px; }
.tag-extra {
    font-size: 9px !important;
    padding: 1px 5px !important;
    border-radius: 3px;
    font-weight: 500;
}

/* ============================================
   Phone Sidebar Backdrop
   Created/removed dynamically by layout.js.
   Covers .main-content; topbar blocked via
   .drawer-open pointer-events rule below.
   ============================================ */
.phone-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0,0,0,0.5);
    z-index: var(--z-drawer-backdrop);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    cursor: pointer;
}

/* Block topbar + stats-strip clicks while drawer is open (mobile only) */
body.phone .drawer-open > #topbar {
    pointer-events: none;
}
body.phone .drawer-open > #topbar .btn-mobile-toggle {
    pointer-events: auto;
}
body.phone .drawer-open > #stats-strip {
    pointer-events: none;
}

/* ============================================
   Arousal Breathing Animations
   ============================================ */
@keyframes arousal-pulse {
    0%, 100% { opacity: 0.7; transform: scale(1); }
    50% { opacity: 1; transform: scale(1.02); }
}
@keyframes arousal-glow {
    0%, 100% { box-shadow: 0 0 4px rgba(232, 100, 140, 0.2); }
    50% { box-shadow: 0 0 12px rgba(232, 100, 140, 0.5); }
}
.arousal-breathing {
    animation: arousal-pulse 3s ease-in-out infinite;
}
.arousal-glow {
    animation: arousal-glow 2.5s ease-in-out infinite;
}

/* (Tutorial hint styles consolidated above — see "Progressive Onboarding" section) */

/* ============================================
   Cheat Console (Patreon)
   ============================================ */
.cheat-console-box {
    max-width: 400px;
    background: var(--bg-deep);
    border: 1px solid var(--orchid);
    border-radius: 12px;
    padding: 20px;
}
.cheat-console-box h3 {
    color: var(--rose);
    font-size: 14px;
    margin: 0 0 12px;
}
.cheat-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}
.cheat-row label {
    font-size: 11px;
    color: var(--text-dim);
    min-width: 90px;
}
.cheat-row input, .cheat-row select {
    flex: 1;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.1);
    border-radius: 4px;
    color: var(--text-soft);
    padding: 4px 8px;
    font-size: 11px;
}
.cheat-row button {
    padding: 4px 12px;
    background: var(--orchid);
    color: #fff;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 11px;
}
.cheat-row button:hover { background: var(--rose); }

/* ============================================
   Toggle Switch (Settings)
   ============================================ */
.toggle-switch {
    position: relative;
    display: inline-block;
    width: 36px;
    min-width: 36px;   /* flex containers must never squash the switch */
    flex-shrink: 0;    /* (narrow settings columns crushed it to ~9px)  */
    height: 20px;
    cursor: pointer;
}
.toggle-switch input { opacity: 0; width: 0; height: 0; }
.toggle-slider {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(255,255,255,0.1);
    border-radius: 20px;
    transition: background 0.2s ease;
}
.toggle-slider::before {
    content: '';
    position: absolute;
    width: 16px; height: 16px;
    left: 2px; bottom: 2px;
    background: var(--text-dim);
    border-radius: 50%;
    transition: transform 0.2s ease, background 0.2s ease;
}
.toggle-switch input:checked + .toggle-slider { background: var(--orchid); }
.toggle-switch input:checked + .toggle-slider::before {
    transform: translateX(16px);
    background: #fff;
}

/* ============================================
   Time-of-Day Theming (matches Unity _03-game-topbar.uss)
   ============================================ */

/* Morning — warm gold accent */
.time-morning .top-bar { border-bottom-color: rgba(200, 160, 80, 0.6); }
.time-morning .game-title { color: rgb(240, 200, 120); }

/* Lunch — softer gold, default feel */
.time-lunch .top-bar { border-bottom-color: rgba(180, 140, 80, 0.4); }
.time-lunch .game-title { color: rgb(230, 190, 130); }

/* Evening — sunset orange */
.time-evening .top-bar { border-bottom-color: rgba(200, 100, 60, 0.6); }
.time-evening .game-title { color: rgb(240, 150, 100); }
.time-evening .panel,
.time-evening .side-panel { background-color: rgba(20, 18, 28, 0.95); }
.time-evening .story-panel { background-color: rgba(18, 14, 24, 0.9); }

/* Night — deep blue/purple */
.time-night .top-bar {
    background-color: rgba(12, 10, 22, 0.95);
    border-bottom-color: rgba(60, 50, 120, 0.6);
}
.time-night .game-title { color: rgb(140, 120, 200); }
.time-night .panel,
.time-night .side-panel {
    background-color: rgba(16, 14, 26, 0.95);
    border-color: rgba(35, 30, 55, 0.5);
}
.time-night .story-panel { background-color: rgba(14, 12, 24, 0.95); }
.time-night .choice-btn { border-color: rgba(40, 35, 60, 0.5); }

/* Location map time overlays */
.map-time-overlay {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    pointer-events: none;
    transition: background-color 0.5s ease;
    border-radius: inherit;
}
.time-morning .map-time-overlay { background-color: rgba(0, 0, 0, 0); }
.time-lunch .map-time-overlay { background-color: rgba(180, 130, 40, 0.08); }
.time-evening .map-time-overlay { background-color: rgba(200, 100, 20, 0.22); }
.time-night .map-time-overlay { background-color: rgba(20, 10, 50, 0.45); }

/* ============================================
   Accessibility: Reduced Motion
   ============================================ */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    .grain-overlay, .vignette-overlay {
        display: none !important;
    }
}


/* ============================================
   MIGRATED FROM _11-fixes-onboarding: Tutorial Hints — Progressive Onboarding
   ============================================ */
/* ============================================
   Tutorial Hints — Progressive Onboarding
   ============================================ */
.tutorial-hint {
    position: fixed;
    top: 60px;
    left: 50%;
    /* Readability scale composed with the existing translateX(-50%)
       centering. transform-origin top so the bubble grows downward. */
    transform: translateX(-50%) scale(var(--overlay-zoom, 1));
    transform-origin: center top;
    max-width: 420px;
    width: 90%;
    padding: 12px 16px 12px 36px;
    /* Retint: info-blue/teal palette so tutorial bubbles never collide
       with the pink stats rail behind them. */
    background: linear-gradient(135deg, rgba(30, 45, 75, 0.96), rgba(22, 32, 55, 0.96));
    border: 1px solid rgba(130, 180, 230, 0.4);
    border-radius: 10px;
    color: var(--text, #e0e8f2);
    font-size: 13px;
    line-height: 1.5;
    z-index: 300;
    backdrop-filter: blur(var(--blur-md));
    -webkit-backdrop-filter: blur(var(--blur-md));
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.5), 0 0 40px rgba(130, 180, 230, 0.14);
    animation: tutorial-slide-in 0.4s ease-out;
    cursor: pointer;
    transition: opacity 0.4s ease, transform 0.4s ease;
}
.tutorial-hint::before {
    content: '\1F4A1';
    position: absolute;
    left: 12px;
    top: 12px;
    font-size: 14px;
}
.tutorial-hint:hover {
    border-color: rgba(130, 180, 230, 0.65);
}
/* Retint inline pills to blue family so they read as info, not as
   pink CTAs. Counter and skip-all carry the same shift. */
.tutorial-dismiss {
    background: rgba(130, 180, 230, 0.18);
    border-color: rgba(130, 180, 230, 0.35);
    color: rgba(210, 225, 245, 0.95);
}
.tutorial-dismiss:hover {
    background: rgba(130, 180, 230, 0.3);
}
.tutorial-counter {
    background: rgba(130, 180, 230, 0.15);
    border-color: rgba(130, 180, 230, 0.3);
    color: rgba(200, 220, 240, 0.9);
}
.tutorial-anchor-pulse {
    animation: tutorial-pulse-blue 1.5s ease-in-out infinite !important;
}
@keyframes tutorial-pulse-blue {
    0%, 100% { box-shadow: 0 0 0 0 rgba(130, 180, 230, 0); }
    50% { box-shadow: 0 0 12px 4px rgba(130, 180, 230, 0.45); }
}

/* Anchored tooltip — positioned by JS near a UI element. Override the
   parent .tutorial-hint translateX(-50%) but KEEP the readability scale. */
.tutorial-hint-anchored {
    transform: scale(var(--overlay-zoom, 1));
    transform-origin: center top;
    width: auto;
    min-width: 220px;
}

/* Arrow pointing up (tooltip below anchor) */
.tutorial-arrow-up::after {
    content: '';
    position: absolute;
    top: -6px;
    left: var(--arrow-left, 50%);
    transform: translateX(-50%);
    border-left: 7px solid transparent;
    border-right: 7px solid transparent;
    border-bottom: 7px solid rgba(228, 140, 184, 0.35);
}
/* Arrow pointing down (tooltip above anchor) */
.tutorial-arrow-down::after {
    content: '';
    position: absolute;
    bottom: -6px;
    left: var(--arrow-left, 50%);
    transform: translateX(-50%);
    border-left: 7px solid transparent;
    border-right: 7px solid transparent;
    border-top: 7px solid rgba(228, 140, 184, 0.35);
}

/* Dismiss button — Audit D03 fix: was pink-on-pink (1.00:1, invisible). The
   intent retint at the top of this section is blue; sizing block kept here. */
.tutorial-dismiss {
    display: inline-block;
    margin-left: 12px;
    padding: 8px 14px;
    min-height: 44px;
    min-width: 44px;
    box-sizing: border-box;
    /* Audit D03 + D08: was 11px (sub-readable) + sub-44 hit target. */
    background: rgba(130, 180, 230, 0.22);
    border: 1px solid rgba(180, 215, 245, 0.65);
    border-radius: 6px;
    color: #ffffff;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    vertical-align: middle;
    transition: background 0.2s, border-color 0.2s;
}
.tutorial-dismiss:hover {
    background: rgba(130, 180, 230, 0.36);
    border-color: rgba(200, 225, 250, 0.85);
}
.tutorial-dismiss:focus-visible {
    outline: 2px solid #b4d7f5;
    outline-offset: 2px;
}

/* Queue position counter — tiny pill showing "1/3", "2/3", … */
.tutorial-counter {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 7px;
    background: rgba(160, 128, 224, 0.15);
    border: 1px solid rgba(160, 128, 224, 0.3);
    border-radius: 10px;
    color: rgba(200, 180, 240, 0.85);
    font-family: 'DM Mono', monospace;
    font-size: 10px;
    vertical-align: middle;
    letter-spacing: 0.5px;
}

/* Skip-all button — secondary action. Audit D08: was 10px font + sub-44 hit. */
.tutorial-skip-all {
    display: inline-block;
    margin-left: 6px;
    padding: 8px 12px;
    min-height: 44px;
    box-sizing: border-box;
    background: transparent;
    border: 1px solid rgba(200, 200, 220, 0.45);
    border-radius: 6px;
    color: rgba(220, 220, 235, 0.92);
    font-size: 12px;
    cursor: pointer;
    vertical-align: middle;
    transition: color 0.2s, border-color 0.2s, background 0.2s;
}
.tutorial-skip-all:hover {
    color: #ffffff;
    border-color: rgba(220, 220, 235, 0.75);
    background: rgba(180, 180, 200, 0.12);
}
.tutorial-skip-all:focus-visible {
    outline: 2px solid #b4d7f5;
    outline-offset: 2px;
}

/* Pulse highlight on the anchor element */
.tutorial-anchor-pulse {
    animation: tutorial-pulse 1.5s ease-in-out infinite !important;
    box-shadow: 0 0 0 0 rgba(228, 140, 184, 0.4);
}
@keyframes tutorial-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(228, 140, 184, 0); }
    50% { box-shadow: 0 0 12px 4px rgba(228, 140, 184, 0.4); }
}

/* Keyframes multiply scale by --overlay-zoom so the entry animation
   ends at the slider-chosen scale (no "pop" after animation ends). */
@keyframes tutorial-slide-in {
    from { opacity: 0; transform: translateX(-50%) translateY(-10px) scale(var(--overlay-zoom, 1)); }
    to { opacity: 1; transform: translateX(-50%) translateY(0) scale(var(--overlay-zoom, 1)); }
}
.tutorial-hint-anchored { animation: tutorial-anchor-in 0.35s ease-out; }
@keyframes tutorial-anchor-in {
    from { opacity: 0; transform: translateY(-6px) scale(var(--overlay-zoom, 1)); }
    to { opacity: 1; transform: translateY(0) scale(var(--overlay-zoom, 1)); }
}

/* ============================================
   U-06 v0.2.5 — Fem-tier-up FX
   Small local particle burst from the Fem stat-row + centered toast
   reveal of the new tier name. Triggered on crossing 25/50/75 from
   stats.js _spawnTierParticles + _showTierUpToast.
   No SFX (per user spec — visual-only celebration).
   ============================================ */
.tier-particles {
    position: fixed;
    pointer-events: none;
    z-index: 9000;
}
.tier-particle {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: radial-gradient(circle, #ffb3d9 0%, #ff6fb5 60%, transparent 100%);
    box-shadow: 0 0 6px rgba(255, 111, 181, 0.9), 0 0 12px rgba(255, 111, 181, 0.5);
    opacity: 0;
    transform: translate(-50%, -50%);
    animation: tier-particle-burst 1.2s cubic-bezier(.2,.7,.3,1) forwards;
    animation-delay: var(--delay, 0ms);
}
@keyframes tier-particle-burst {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
    20%  { opacity: 1; transform: translate(-50%, -50%) scale(1.0); }
    100% {
        opacity: 0;
        transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--dy, 0px))) scale(0.6);
    }
}

.tier-up-toast {
    position: fixed;
    left: 50%;
    top: 38%;
    transform: translate(-50%, -50%) scale(0.9);
    z-index: 9100;
    pointer-events: none;
    text-align: center;
    padding: 16px 36px 14px;
    border-radius: 14px;
    background: linear-gradient(135deg, rgba(45, 20, 40, 0.92) 0%, rgba(70, 30, 65, 0.92) 100%);
    border: 1px solid rgba(255, 111, 181, 0.5);
    box-shadow: 0 0 30px rgba(255, 111, 181, 0.45), 0 6px 24px rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(8px);
    opacity: 0;
    transition: opacity 0.45s ease-out, transform 0.45s cubic-bezier(.2,1.4,.4,1);
    font-family: 'DM Sans', sans-serif;
}
.tier-up-toast.show {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}
.tier-up-toast.hide {
    opacity: 0;
    transform: translate(-50%, -50%) scale(1.04);
    transition: opacity 0.5s ease-in, transform 0.5s ease-in;
}
.tier-up-label {
    font-size: 11px;
    letter-spacing: 4px;
    font-weight: 700;
    color: rgba(255, 179, 217, 0.85);
    text-transform: uppercase;
    margin-bottom: 4px;
}
.tier-up-name {
    font-size: 28px;
    font-weight: 700;
    color: #ffd5e8;
    text-shadow: 0 0 12px rgba(255, 111, 181, 0.7);
    letter-spacing: 1.5px;
    line-height: 1.1;
}
