/* ==========================================
   @layer base — layout belongs to the base layer (header, nav, tabs,
   sticky chrome). Below components/features in the cascade so individual
   feature rules can still decorate layout children without fighting.
   See index.html <head> for the full layer stack declaration.
   ========================================== */
@layer base {

/* ==========================================
   GALLERY SECTION
   ========================================== */

.gallery-section {
    height: 100%;
    width: 100%;
    display: block;
    overflow-x: hidden;
    overflow-y: auto;
    animation: fadeIn 0.5s ease;
}

@media (min-width: 768px) {
    .gallery-section {
        scrollbar-gutter: stable;
    }
}

.gallery-section.lock-layout {
    display: flex;
    flex-direction: column;
    height: 100vh;
    height: 100dvh;
    overflow: hidden !important;
}

/* Sync tab scroll override no longer needed — all non-game tabs scroll naturally */

/* GLOBAL SCROLL LOCK - Applied to body/html */
.lock-scroll {
    overflow: hidden !important;
    height: 100vh !important;
    height: 100dvh !important;
    position: fixed;
    width: 100%;
    touch-action: none;
    -webkit-overflow-scrolling: none;
}

.gallery-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--spacing-xl);
    padding-bottom: var(--spacing-lg);
    border-bottom: 1px solid rgba(var(--secondary-rgb),0.2);
    flex-wrap: wrap;
    gap: var(--spacing-md);
}

/* Modern Gallery Header — sticky app chrome that keeps navigation reachable */
.gallery-header-modern {
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Extend visual area into the status bar region so the header background
       (gradient + blurred chrome from children) covers the notch / Dynamic
       Island area — matches iOS 26 app convention. env() is 0 on non-iOS. */
    padding: env(safe-area-inset-top) 0 0;
    margin-bottom: 0;
    flex-shrink: 0;
    position: sticky;
    top: 0;
    overflow: visible;
    z-index: 50;
}

.header-logo-row {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    padding: 8px var(--spacing-md);
}

.header-left,
.header-right {
    display: flex;
    align-items: center;
    gap: var(--spacing-xs);
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 100;
}

.header-left {
    left: var(--spacing-md);
    justify-content: flex-start;
}

.header-right {
    right: var(--spacing-md);
    justify-content: flex-end;
}

.gallery-header-modern .logo-modern {
    font-size: clamp(1.8rem, 6vw, 2.8rem);
    text-align: center;
    pointer-events: none;
    z-index: 1;
}

/* ============================================================
   SUBTLE TAB-INFO BUTTON
   ------------------------------------------------------------
   Barely visible by default — 0.2 opacity, no background. User
   must actively look for it to notice. On hover: fades in to
   full visibility with a soft glow. One button per page; its
   modal content changes based on the active tab (populated in
   gallery.js `openTabInfoModal`).
   ============================================================ */
/* Only render on the Sync tab — other tabs are self-explanatory, the
   extra icon was clutter. Display toggled via body[data-active-tab]. */
.sfx-tab-info-btn { display: none; }
body[data-active-tab="sync"] .sfx-tab-info-btn {
    width: 22px;
    height: 22px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: 50%;
    color: var(--text-muted);
    cursor: pointer;
    opacity: 0.2;
    transition: opacity 0.25s ease, color 0.2s ease, transform 0.2s ease, background 0.2s ease;
    -webkit-tap-highlight-color: transparent;
}
.sfx-tab-info-btn:hover,
.sfx-tab-info-btn:focus-visible {
    opacity: 0.92;
    color: var(--primary);
    background: rgba(var(--primary-rgb), 0.08);
    transform: scale(1.1);
    outline: none;
}
.sfx-tab-info-btn svg {
    width: 14px;
    height: 14px;
    display: block;
}

/* Tab-info modal */
.sfx-tab-info-modal {
    position: fixed;
    inset: 0;
    z-index: 11000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    animation: sfxTabInfoFade 0.2s ease;
}
.sfx-tab-info-modal.hidden { display: none; }
@keyframes sfxTabInfoFade { from { opacity: 0; } to { opacity: 1; } }
.sfx-tab-info-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}
.sfx-tab-info-card {
    position: relative;
    width: 100%;
    max-width: 440px;
    max-height: 80vh;
    overflow-y: auto;
    padding: 24px 26px 22px;
    background: linear-gradient(160deg, rgba(20, 14, 38, 0.97), rgba(12, 8, 24, 0.98));
    border: 1px solid rgba(var(--primary-rgb), 0.35);
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5),
                0 0 32px rgba(var(--primary-rgb), 0.15);
    animation: sfxTabInfoPop 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes sfxTabInfoPop {
    from { transform: scale(0.9); opacity: 0; }
    to { transform: scale(1); opacity: 1; }
}
/* Wave 16 — head row centers the title; close floats absolutely top-right
   so the title can occupy the full width without competing for space. */
.sfx-tab-info-head {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    margin-bottom: 14px;
}
.sfx-tab-info-title {
    font-size: 1.1rem;
    font-weight: 700;
    margin: 0;
    text-align: center;
    flex: 0 0 auto;
    background: linear-gradient(135deg, var(--primary), var(--secondary));
    background-clip: text;
    -webkit-background-clip: text;
    color: var(--primary);
    -webkit-text-fill-color: transparent;
}
.sfx-tab-info-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.04);
    border: none;
    border-radius: 50%;
    color: rgba(255, 255, 255, 0.6);
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.18s ease, color 0.18s ease, transform 0.18s ease;
    flex-shrink: 0;
}
.sfx-tab-info-close:hover {
    background: rgba(var(--secondary-rgb), 0.2);
    color: var(--secondary);
    transform: rotate(90deg);
}
.sfx-tab-info-body {
    color: var(--text-secondary);
    font-size: 0.88rem;
    line-height: 1.55;
    margin-bottom: 18px;
}
.sfx-tab-info-body p { margin: 0 0 10px; }
.sfx-tab-info-body p:last-child { margin-bottom: 0; }
.sfx-tab-info-body ul {
    list-style: none;
    padding-left: 0;
    margin: 8px 0;
}
.sfx-tab-info-body ul li {
    position: relative;
    padding-left: 16px;
    margin-bottom: 4px;
}
.sfx-tab-info-body ul li::before {
    content: '•';
    color: var(--primary);
    font-weight: 700;
    position: absolute;
    left: 2px;
}
.sfx-tab-info-body kbd {
    display: inline-block;
    padding: 1px 6px;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 4px;
    font-family: 'SF Mono', Menlo, monospace;
    font-size: 0.74rem;
    color: var(--text-secondary);
}
.sfx-tab-info-body strong {
    color: var(--text-primary);
    font-weight: 600;
}
.sfx-tab-info-gotit {
    display: block;
    width: 100%;
    padding: 10px;
    background: linear-gradient(135deg, var(--primary), var(--secondary));
    color: #fff;
    border: none;
    border-radius: 10px;
    font-family: inherit;
    font-size: 0.86rem;
    font-weight: 600;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.2s ease;
}
.sfx-tab-info-gotit:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 18px rgba(var(--primary-rgb), 0.35);
}

/* Hide the info button in sync fullscreen — header is already hidden, but
   belt-and-braces in case of layout changes. */
body.media-fs-active .sfx-tab-info-btn {
    display: none !important;
}

.gallery-header-modern .logout-btn {
    padding: var(--spacing-sm);
    font-size: 1.25rem;
    background: transparent;
    border: 1px solid rgba(var(--secondary-rgb),0.2);
    border-radius: var(--radius-md);
    opacity: 0.6;
    transition: background var(--transition-normal), background-color var(--transition-normal), border-color var(--transition-normal), box-shadow var(--transition-normal), color var(--transition-normal), filter var(--transition-normal), opacity var(--transition-normal), transform var(--transition-normal);
}

.gallery-header-modern .logout-btn:hover {
    opacity: 1;
    border-color: var(--accent-primary);
    background: var(--bg-glass);
}

.gallery-header-modern .session-status-btn {
    position: static;
    transform: none;
}

.logout-btn {
    padding: var(--spacing-sm) var(--spacing-md);
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--text-secondary);
    background: var(--bg-glass);
    border: 1px solid rgba(var(--secondary-rgb),0.3);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: background var(--transition-normal), background-color var(--transition-normal), border-color var(--transition-normal), box-shadow var(--transition-normal), color var(--transition-normal), filter var(--transition-normal), opacity var(--transition-normal), transform var(--transition-normal);
    -webkit-tap-highlight-color: transparent;
}

.logout-btn:hover,
.logout-btn:active {
    background: rgba(var(--secondary-rgb),0.2);
    color: var(--text-primary);
    border-color: var(--accent-primary);
}

/* ==========================================
   TAB NAVIGATION — Top centered pill
   ========================================== */

/* Liquid glass tab nav — Apple iOS 26 / macOS Tahoe language.
   Real Liquid Glass is MOSTLY INVISIBLE in the middle — the signature is
   the HAIRLINE RIM (a thin bright top edge + thin dark bottom edge) that
   makes the pill read as a thick curved glass capsule. Overall the pill
   is almost clear — the background bleeds through a very light tint.
   No sheen overlays, no ambient glow, no gradient fills.

   Layers:
   1. Barely-there rgba(255,255,255,0.045) base — lets content read through.
   2. Moderate backdrop blur + saturate for the "slightly lensed" look
      behind the glass. NOT brightness-boosted (that was the "too glowy"
      part — glass doesn't emit light, it refracts it).
   3. 0.5px hairline border — the visible edge of the disc.
   4. Inset top highlight (22% white, 1px) — the curved glass catching
      light from above. This is the signature bright top-rim.
   5. Inset bottom shadow (25% black, 1px) — the underside of the glass,
      where it casts a micro-shadow onto the content beneath.
   6. Inset 0.5px hairline rgba to hint at a second inner curve (double
      glass lens look).
   7. A minimal 0 1px 2px drop-shadow grounds the pill. NO big halo,
      NO theme-color glow. */
.content-nav {
    display: flex;
    justify-content: center;
    gap: 0;
    margin: 4px auto 6px;
    padding: 3px;
    /* Very subtle tint — mostly transparent; the glass is defined by its
       rim, not its fill. */
    background: rgba(255, 255, 255, 0.045);
    border-radius: 50px;
    /* Hairline border. 0.5px renders as device-pixel on @2x screens,
       which is the Apple hallmark. Falls back to 1px on standard-density
       displays (still thin). */
    border: 0.5px solid rgba(255, 255, 255, 0.14);
    backdrop-filter: blur(16px) saturate(175%);
    -webkit-backdrop-filter: blur(16px) saturate(175%);
    box-shadow:
        /* TOP INNER HIGHLIGHT — the "curved glass catches sky" bright line.
           This is the most important single layer; without it, no capsule. */
        inset 0 1px 0 rgba(255, 255, 255, 0.22),
        /* SECONDARY TOP RIM — a fainter second line just below the first
           hints at glass thickness (double-refraction of the top edge). */
        inset 0 1.5px 0.5px rgba(255, 255, 255, 0.06),
        /* BOTTOM INNER SHADOW — the underside of the glass, darker. This
           completes the "capsule" illusion. */
        inset 0 -1px 0 rgba(0, 0, 0, 0.22),
        /* Tiny drop shadow to ground the pill without glowing. */
        0 1px 2px rgba(0, 0, 0, 0.20);
    width: fit-content;
    min-width: 320px;
    position: relative;
    /* isolation so active-tab gradient pills stack cleanly inside the glass */
    isolation: isolate;
    overflow: visible;
}

/* Browsers without backdrop-filter (rare): darker opaque fallback so
   text + pill gradients stay readable. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .content-nav {
        background: rgba(12, 8, 24, 0.88);
    }
}

/* ----------------------------------------------------------------------
   SLIDING INDICATOR
   ----------------------------------------------------------------------
   A single absolutely-positioned pill that slides between tabs. JS sets
   `transform: translateX` and `width` from the active tab's offsetLeft /
   offsetWidth. iOS 26 Liquid Glass segmented-control pattern — same
   glass capsule rides the nav, selection slides rather than teleports.

   Geometry is STABLE: all tabs are equal-width on every breakpoint (no
   flex-grow on active, no padding growth, no label width tween). That
   guarantees offsetLeft / offsetWidth read correctly at click time AND
   keeps the browser from running layout for 5 tabs every frame of the
   transition — so the only thing animating is this single pill, on the
   compositor. That's where the "smooth slide" comes from.

   Curve: cubic-bezier(0.2, 0.9, 0.3, 1) at 0.32s — iOS-native "crisp
   ease-out". Fast-start, clean decelerate, no sluggish tail. The
   previous 0.55s ease-out-quart had a ~200ms tail that read as lag.
   ---------------------------------------------------------------------- */
.nav-indicator {
    position: absolute;
    top: 3px;
    bottom: 3px;
    left: 0;
    width: 0;
    border-radius: 40px;
    /* Second glass capsule — brighter tint so it reads as the lifted
       selection sitting inside the outer nav pill. */
    background: rgba(255, 255, 255, 0.09);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.26),
        inset 0 1.5px 0.5px rgba(255, 255, 255, 0.08),
        inset 0 -1px 0 rgba(0, 0, 0, 0.22),
        0 1px 2px rgba(0, 0, 0, 0.15);
    transition:
        transform 0.32s cubic-bezier(0.2, 0.9, 0.3, 1),
        width 0.32s cubic-bezier(0.2, 0.9, 0.3, 1);
    pointer-events: none;
    z-index: 0;
    will-change: transform, width;
}
/* `.no-transition` is applied on initial paint + window resize so the
   indicator JUMPS to position instead of sliding in from the left edge.
   JS removes the class on the next rAF once layout has settled. */
.nav-indicator.no-transition {
    transition: none !important;
}

.nav-tab {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    /* Phase 8.4 density: pad scales between comfortable (7px) and
       compact (~6px). Horizontal keeps steady so text doesn't reflow
       per-setting. */
    padding: calc(7px * var(--density-scale, 1)) 20px;
    /* Phase 8.7 touch target: the flex item is set to a 44×44 min size
       (the Apple / WCAG 2.1 AA standard) via a floor on the TAP area.
       Desktop pads still look correct because `flex:1 1 0` + tabs-sharing-
       the-row means actual widths are larger than the min. */
    min-height: 44px;
    /* EQUAL WIDTH on every breakpoint. flex-basis: 0 forces tabs to
       divide the nav width in proportion to flex-grow ONLY — and since
       every tab has the same flex-grow (1), they're all the same width.
       Active tab does NOT grow — the sliding pill handles "this is the
       selected one" visually. This is the iOS / macOS segmented-control
       geometry. */
    flex: 1 1 0;
    min-width: 0;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-muted);
    background: transparent;
    border: none;
    border-radius: 40px;
    cursor: pointer;
    /* Ensure the tab content paints above the indicator so the label +
       icon stay readable when the indicator slides under it. */
    position: relative;
    z-index: 1;
    /* ONLY color transitions on the tab. No flex, no padding, no width
       changes — that's the point: tab geometry is static, only the
       slide indicator (above) animates position. Color has the same
       curve + 0.3s so the accent snaps into the new tab on a matching
       cadence. */
    transition: color 0.3s cubic-bezier(0.2, 0.9, 0.3, 1);
    -webkit-tap-highlight-color: transparent;
    white-space: nowrap;
}


.nav-icon {
    font-size: 1.2rem;
    filter: grayscale(1);
    transition:
        filter 0.3s cubic-bezier(0.2, 0.9, 0.3, 1),
        color 0.3s cubic-bezier(0.2, 0.9, 0.3, 1);
    display: flex;
    align-items: center;
    line-height: 1;
}

.nav-tab .nav-icon svg {
    width: 18px;
    height: 18px;
    stroke: currentColor;
    transition: stroke 0.3s cubic-bezier(0.2, 0.9, 0.3, 1);
}

/* Hover State — very subtle, just a hint of glass so you know it's hoverable */
.nav-tab:not(.active):hover {
    background: rgba(255, 255, 255, 0.04);
    color: var(--text-primary);
}

.nav-tab:not(.active):hover .nav-icon {
    filter: grayscale(0.5);
}

/* ======================================================================
   LIQUID GLASS ACTIVE STATE — iOS 26 / macOS Tahoe
   ----------------------------------------------------------------------
   The active tab is a SECOND glass capsule nested inside the nav. It's
   slightly brighter than the nav base (so it reads as the lifted
   selection) with its own rim-highlight stack — making it look like a
   sub-capsule floating on top of the larger glass pill.

   The PILL FILL stays unified glass (iOS 26 convention — same glass for
   every tab). The LABEL + ICON, however, take per-tab ACCENT COLORS
   matching the identity of each tab: gold/primary for Media, sepia for
   Diary, rose for Therapy, teal for Games, violet/secondary for Sync.
   This restores the previous per-tab color language without going back
   to the Material-3 gradient fill.
   ====================================================================== */
.nav-tab.active {
    /* Background + box-shadow live on .nav-indicator so the glass pill
       SLIDES between tabs instead of each tab fading its own pill in/
       out. The active tab keeps only its weight + per-tab label color
       below — NO flex-grow, NO padding change, NO width change. Static
       geometry is what makes the slide feel right. */
    font-weight: 700;
}

.nav-tab.active .nav-icon {
    filter: grayscale(0);
}

/* ----------------------------------------------------------------------
   Per-tab accent colors for the active label + icon.
   ----------------------------------------------------------------------
   The pill fill stays uniform glass. The LABEL shows the full per-tab
   gradient via background-clip: text (the same gradients that used to
   fill the entire pill — Media's primary→deep-gold, Sync's violet-alt
   →dark-violet, etc). The ICON takes the dominant/first gradient stop
   as a solid color — CSS can't smoothly transition `stroke: url(#id)`
   between gradient refs, and at 18px a gradient on the 2px SVG stroke
   reads as a muddy color smear anyway. Solid icon + gradient label is
   both more legible AND transitions cleanly.

   The base `color` sets currentColor for the SVG (icons use
   stroke="currentColor"). The `.nav-label` override paints the gradient
   on top of the span and masks it to the text shape. */

/* Media — gold: var(--primary) → #f0a500 */
.nav-tab.active[data-tab="media"] {
    color: var(--primary);
}
.nav-tab.active[data-tab="media"] .nav-label {
    background: linear-gradient(135deg, var(--primary), #f0a500);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

/* Diary — sepia: #c9a84c → #8B7355 */
.nav-tab.active[data-tab="diary"] {
    color: #c9a84c;
}
.nav-tab.active[data-tab="diary"] .nav-label {
    background: linear-gradient(135deg, #c9a84c, #8B7355);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

/* Therapy — rose: #e8788a → #c44569 */
.nav-tab.active[data-tab="therapy"] {
    color: #e8788a;
}
.nav-tab.active[data-tab="therapy"] .nav-label {
    background: linear-gradient(135deg, #e8788a, #c44569);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

/* Games — teal: #06b6d4 → #0891b2 */
.nav-tab.active[data-tab="games"] {
    color: #06b6d4;
}
.nav-tab.active[data-tab="games"] .nav-label {
    background: linear-gradient(135deg, #06b6d4, #0891b2);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

/* Sync — violet: var(--secondary-alt) → var(--secondary-dark) */
.nav-tab.active[data-tab="sync"] {
    color: var(--secondary-alt);
}
.nav-tab.active[data-tab="sync"] .nav-label {
    background: linear-gradient(135deg, var(--secondary-alt), var(--secondary-dark));
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

/* ----------------------------------------------------------------------
   Mobile — stacked tabs, equal width, labels always visible
   ----------------------------------------------------------------------
   On phone we STACK the icon over the label (column layout) so all
   5 tabs can show their label without widening the tab box. Every tab
   is the same width — the active tab does not grow. Inactive labels
   are dimmed via opacity; active label is full bright. Because the tab
   geometry is static, the sliding indicator above reads clean offsets
   and glides smoothly between them.
   ---------------------------------------------------------------------- */
@media (max-width: 600px) {
    /* Give the header → nav → page a bit of breathing room so mobile doesn't feel crammed.
       Preserve env(safe-area-inset-top) so the tab nav clears the iOS Dynamic Island /
       status bar in PWA standalone mode — the earlier flat `padding: 6px …` override
       stripped that padding on mobile, which is why tabs rendered under the notch. */
    .gallery-header-modern {
        padding: calc(env(safe-area-inset-top, 0px) + 6px) var(--spacing-sm) 6px;
    }
    .header-logo-row {
        padding: 10px var(--spacing-sm) 8px;
    }
    .content-nav {
        min-width: auto;
        width: 95%;
        gap: 0;
        padding: 3px;
        margin-top: 10px;
        margin-bottom: 12px;
    }

    .nav-tab {
        flex-direction: column;
        /* Phase 8.7 touch target: was 6px 4px — now 8px 4px so the total
           tap area stays ≥ 44px when nav uses stacked icon+label layout.
           min-height inherits from the base rule (44px). */
        padding: 8px 4px;
        gap: 3px;
        font-size: 0.75rem;
        /* flex: 1 1 0 inherited from base — equal widths, no growing. */
    }

    .nav-tab .nav-label {
        font-size: 0.58rem;
        line-height: 1;
        /* Label is ALWAYS rendered at its full width; we just dim it
           when the tab is inactive. No max-width / flex tweens — the
           tab box stays the exact same size whether active or not.
           That's what keeps the indicator slide clean. */
        opacity: 0.55;
        transition: opacity 0.3s cubic-bezier(0.2, 0.9, 0.3, 1);
        max-width: none;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .nav-tab.active .nav-label {
        opacity: 1;
    }

    .nav-tab .nav-icon svg {
        width: 20px;
        height: 20px;
    }
}

/* breakpoint NOT snapped — part of the iOS 26 Liquid Glass nav rules
   (see CLAUDE.md). Keep @ 380 so the tighter nav padding only kicks in
   on small phones, not on phone-small ≤480. */
@media (max-width: 380px) {
    .nav-tab {
        /* Still hit the 44px floor by padding harder top/bottom —
           horizontal stays thin so 5 tabs fit narrow phones. */
        padding: 7px 2px;
    }
    .nav-tab .nav-icon svg {
        width: 18px;
        height: 18px;
    }
    .nav-tab .nav-label {
        font-size: 0.54rem;
    }
}

/* Tab Content */
.tab-content {
    display: none;
    height: auto;
    overflow: visible;
    /* Horizontal padding unchanged. Bottom padding adds env(safe-area-inset-bottom)
       so scrolled content clears the iOS home indicator; horizontal padding adds
       the left/right safe-area insets for landscape iPhones where the notch eats
       into the sides. env() resolves to 0 on non-iOS so desktop is unaffected. */
    padding:
        0
        calc(var(--spacing-md) + env(safe-area-inset-right, 0px))
        calc(var(--spacing-md) + env(safe-area-inset-bottom, 0px))
        calc(var(--spacing-md) + env(safe-area-inset-left, 0px));
    position: relative;
    z-index: 1;
}

/* Space between sticky header (with sub-tabs) and content grids */
#media-content {
    padding-top: var(--spacing-md);
}

.tab-content.active {
    display: block;
    /* Wave 13 follow-up: explicit opacity defense. The user reported
     * the diary still loaded transparent at start despite the prior
     * tabSlideIn opacity-fade removal. Some browser/cache combo was
     * still applying an opacity transition somewhere. Forcing
     * opacity:1 here with !important guarantees no transparency
     * during/after activation regardless of what other CSS or JS
     * tries to set. Background bg from layered .diary-container is
     * fully opaque (#0f0d1e in themed) so once this is locked, body
     * bg can never bleed through. */
    opacity: 1 !important;
    animation: tabSlideIn 0.35s ease-out both;
}

/* Diary, Sync — normal scrollable block flow */
#diary-content.active,
#sync-content.active {
    display: block;
    overflow: visible;
    height: auto;
}

/* Wave 13: kill the slide-in animation on Diary entirely. The user
 * reported persistent transparent-fade-in artifacts at the start of
 * every Diary tab activation (body's london-bg sentences visible
 * through the diary). Even after dropping opacity from tabSlideIn,
 * the GPU compositing during the transform animation interacted with
 * backdrop-filter on the editor-header in a way that caused brief
 * see-through rendering. Just disabling the animation solves it
 * completely — diary appears instantly at full opacity. */
#diary-content.active {
    animation: none !important;
}

/* Therapy — flex fill viewport in lock-layout (no scroll, fit screen) */
#therapy-content {
    display: none;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    overflow: hidden;
}

#therapy-content.active {
    display: flex;
}

.lock-layout #therapy-content {
    flex: 1;
}

/* Games — normal scrollable block flow like other tabs by default */
#games-content {
    display: none;
    height: auto;
    overflow: visible;
}

#games-content.active {
    display: block;
}

/* When a game is active, lock to viewport (flex, no scroll) */
#games-content.game-active {
    display: none;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    overflow: hidden;
}

#games-content.game-active.active {
    display: flex;
}

.lock-layout #games-content.game-active {
    flex: 1;
}

@keyframes tabSlideIn {
    /* Wave 13 follow-up: dropped the `opacity: 0 → 1` fade. The
     * partial-opacity window during the 0.35s animation let the body's
     * radial-gradient bg bleed through the tab content (visible most
     * clearly on the Diary tab where the user reported "it loads
     * reddish/transparent first then settles to the dark theme"). With
     * opacity gone, tabs slide up from translateY(16px) into place at
     * full opacity from frame one — bg visible only when actually
     * intentional, not as a transition artifact. */
    from {
        transform: translateY(16px) scale(0.99);
    }
    to {
        transform: translateY(0) scale(1);
    }
}

@media (prefers-reduced-motion: reduce) {
    .tab-content.active { animation: none; }
}

/* ========== Skeleton Shimmer ========== */
.skeleton-card {
    border-radius: var(--radius-lg);
    overflow: hidden;
    background: var(--bg-card);
    border: 1px solid rgba(var(--secondary-rgb),0.1);
}

.skeleton-thumb {
    background: linear-gradient(135deg, #1a1a2e, #2d1f3d);
    position: relative;
    overflow: hidden;
}

.skeleton-thumb::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent 0%, rgba(var(--secondary-rgb),0.08) 40%, rgba(var(--primary-rgb),0.06) 60%, transparent 100%);
    animation: shimmer 1.5s ease-in-out infinite;
}

.skeleton-info {
    padding: var(--spacing-sm) var(--spacing-md);
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.skeleton-line {
    height: 12px;
    border-radius: 6px;
    background: rgba(var(--secondary-rgb),0.12);
    position: relative;
    overflow: hidden;
}

.skeleton-line::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent 0%, rgba(var(--secondary-rgb),0.1) 50%, transparent 100%);
    animation: shimmer 1.5s ease-in-out infinite;
}

.skeleton-line.wide { width: 80%; }
.skeleton-line.medium { width: 60%; }
.skeleton-line.short { width: 35%; }

@keyframes shimmer {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}

/* ----- Diary skeleton ------------------------------------------------ */
/* Minimal block-shaped placeholders inside #diary-blocks while the
   entry is being fetched. Respects the dual palette: parchment uses
   a warm cream-on-paper tint, themed mode uses the same shimmer
   tokens as the rest of the skeletons. The outer wrap is purely
   visual — it does NOT take pointer events (the editor below is
   still interactive once it paints). */
.diary-skeleton-overlay {
    position: absolute;
    inset: 16px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    pointer-events: none;
    z-index: 4;          /* below diary-blocks (z:5) so real content covers it */
    opacity: 0.92;
}
.diary-skeleton-block {
    border-radius: 10px;
    background: rgba(var(--secondary-rgb), 0.10);
    position: relative;
    overflow: hidden;
}
.diary-skeleton-block::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(var(--secondary-rgb), 0.10) 45%,
        rgba(var(--primary-rgb), 0.08) 60%,
        transparent 100%);
    animation: shimmer 1.6s ease-in-out infinite;
}
.diary-skeleton-block.tall { height: 110px; }
.diary-skeleton-block.short-h { height: 48px; }
.diary-skeleton-block.medium-h { height: 76px; width: 72%; }
.diary-skeleton-block.right { align-self: flex-end; width: 56%; }

/* Parchment palette overrides — warm paper-toned shimmer */
.diary-container[data-palette="parchment"] .diary-skeleton-block {
    background: rgba(120, 80, 40, 0.10);
}
.diary-container[data-palette="parchment"] .diary-skeleton-block::after {
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(120, 80, 40, 0.10) 45%,
        rgba(180, 130, 60, 0.10) 60%,
        transparent 100%);
}

/* ----- Games scoreboard skeleton ------------------------------------- */
/* Shown when entering a game container BEFORE the score row paints. */
.scoreboard-skeleton {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding: 10px 12px;
}
.scoreboard-skeleton .ssk-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px;
    border-radius: 14px;
    background: rgba(var(--secondary-rgb), 0.10);
    border: 1px solid rgba(var(--secondary-rgb), 0.14);
    min-width: 130px;
    position: relative;
    overflow: hidden;
}
.scoreboard-skeleton .ssk-card::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(var(--primary-rgb), 0.07) 50%,
        transparent 100%);
    animation: shimmer 1.5s ease-in-out infinite;
}
.scoreboard-skeleton .ssk-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: rgba(var(--primary-rgb), 0.18);
    flex-shrink: 0;
}
.scoreboard-skeleton .ssk-text {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1;
}
.scoreboard-skeleton .ssk-line {
    height: 10px;
    border-radius: 5px;
    background: rgba(var(--secondary-rgb), 0.16);
}
.scoreboard-skeleton .ssk-line.short { width: 50%; }
.scoreboard-skeleton .ssk-line.wide { width: 80%; }
.scoreboard-skeleton .ssk-divider {
    color: rgba(var(--primary-rgb), 0.55);
    font-weight: 800;
    font-size: 1.1rem;
}

/* Nav tab styles consolidated in the primary @media (max-width: 600px)
   block above — this section intentionally left empty to avoid rules
   conflicting across blocks. */
/* ========================================
   GALLERY HEADER — fit session btn
   ======================================== */
/* header layout handled above */

/* ========================================
   MOBILE LAYOUT FIXES — prevent overlapping
   ======================================== */
@media (max-width: 480px) {
    .gallery-header-modern {
        /* Preserve env(safe-area-inset-top) for iOS PWA — see ≤600px block above. */
        padding: calc(env(safe-area-inset-top, 0px) + 8px) var(--spacing-xs) 6px;
    }

    .header-logo-row {
        padding: 10px var(--spacing-sm) 6px;
    }

    .gallery-header-modern .logo-modern {
        font-size: clamp(1.2rem, 5vw, 1.6rem);
    }

    .gallery-header-modern .logo-image {
        height: clamp(36px, 8vw, 50px);
    }

    .gallery-header-modern .session-status-btn {
        font-size: 0.6rem;
        padding: 3px 8px;
        width: 82px;
        gap: 4px;
    }

    .gallery-header-modern .logout-btn {
        font-size: 0.9rem;
        padding: 3px 6px;
    }

    .header-left,
    .header-right {
        min-width: 50px;
    }

    .content-nav {
        min-width: 0;
        width: 95%;
        padding: 3px;
        margin-top: 10px;
        margin-bottom: 12px;
    }

    /* .nav-tab padding handled in the primary @media (max-width: 600px)
       block — don't override here, it conflicts with the stacked layout. */

    /* Game scoreboards */
    .score-card {
        padding: var(--spacing-sm);
    }

    .score-avatar {
        width: 35px;
        height: 35px;
    }

    .score-name {
        font-size: 0.75rem;
    }

    .score-vs {
        font-size: 0.9rem;
        padding: 0 var(--spacing-xs);
    }

    /* Game picker cards */
    .game-pick-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: var(--spacing-sm);
    }

    .game-pick-card {
        padding: var(--spacing-sm);
    }

    /* Chat sidebar */
    .chat-sidebar {
        width: 100% !important;
        max-width: 100% !important;
    }

    /* Session overlay */
    .session-overlay-content {
        width: 98%;
        padding: var(--spacing-sm);
    }

    .role-cards {
        flex-direction: row !important;
        align-items: stretch !important;
        justify-content: center !important;
        gap: 8px !important;
    }

    .role-card {
        width: 48% !important;
        padding: 10px !important;
    }

    /* TTT grid */
    .ttt-cell {
        width: 70px;
        height: 70px;
    }

    /* CF board */
    .cf-cell {
        width: 36px;
        height: 36px;
    }

    /* RPS */
    .rockpaperscissors-battle-layout {
        gap: var(--spacing-sm);
    }

    .rockpaperscissors-choice-btn {
        padding: var(--spacing-sm);
    }

    .rockpaperscissors-emoji {
        font-size: 1.8rem;
    }
}

/* Presence indicator — persistent bar below header */
.presence-indicator {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    font-size: 0.8rem;
    color: #e0d0f0;
    padding: 0.35rem 0.75rem;
    background: linear-gradient(135deg, rgba(var(--secondary-dark-rgb),0.25), rgba(var(--secondary-alt-rgb),0.15));
    border-bottom: 1px solid rgba(var(--secondary-alt-rgb),0.2);
    text-align: center;
    width: 100%;
    animation: presenceFadeIn 0.3s ease;
}

.presence-indicator.hidden {
    display: none;
}

.presence-indicator strong {
    color: #c4a0ff;
}

@keyframes presenceFadeIn {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: translateY(0); }
}

/* ========================================
   WATCH SUB-TABS (Movies / Shows toggle)
   ======================================== */
/* Unified sub-tab pill design (Watch, Diary, etc.) */
/* Only show media sub-tabs when media tab is active */
#media-sub-tabs {
    display: none;
}
body[data-active-tab="media"] #media-sub-tabs {
    display: flex;
}

/* ========================================
   SUB-NAV (Movies / Shows / Books)
   ----------------------------------------
   SOTA sliding-underline pattern (Apple TV+ / HBO Max / Material 3).
   - Transparent container → keeps main nav as the only "chrome"
   - Text + icon per tab with muted inactive, themed active
   - Animated gradient indicator slides between tabs
   - Themes fully via --primary / --secondary
   ======================================== */
.content-sub-tabs {
    display: inline-flex;
    justify-content: center;
    align-items: stretch;
    gap: 4px;
    margin: 6px auto 0;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: 0;
    width: fit-content;
    position: relative;
    box-shadow: none;
    overflow: visible;
    /* Updated by JS on tab change: drives .content-sub-tabs-indicator */
    --sub-ind-x: 0px;
    --sub-ind-w: 0px;
}

/* Diary sub-tabs don't exist anymore; keep the selector neutral */
#diary-content > .content-sub-tabs {
    margin: 0;
}

.content-sub-tab {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 9px 16px 11px;
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.2px;
    color: var(--text-muted);
    background: transparent;
    border: none;
    border-radius: 10px 10px 0 0;
    cursor: pointer;
    position: relative;
    transition: color 0.22s ease, background 0.22s ease, transform 0.18s ease;
    -webkit-tap-highlight-color: transparent;
    outline: none;
}

.content-sub-tab .sub-tab-icon {
    width: 14px;
    height: 14px;
    opacity: 0.65;
    transition: opacity 0.22s ease, transform 0.22s ease, color 0.22s ease;
    flex-shrink: 0;
}

.content-sub-tab:hover:not(.active) {
    color: var(--text-primary);
    background: rgba(255, 255, 255, 0.04);
}
.content-sub-tab:hover:not(.active) .sub-tab-icon {
    opacity: 1;
}

.content-sub-tab:focus-visible {
    box-shadow: 0 0 0 2px rgba(var(--primary-rgb), 0.5);
}

.content-sub-tab.active {
    color: var(--primary);
}
.content-sub-tab.active .sub-tab-icon {
    opacity: 1;
    color: var(--primary);
    transform: scale(1.08);
    filter: drop-shadow(0 0 4px rgba(var(--primary-rgb), 0.5));
}

/* Pressed feedback */
.content-sub-tab:active:not(.active) {
    transform: translateY(1px);
}

/* The sliding indicator — one gradient bar that follows the active tab.
   Positioned absolutely within the container; x/w set via CSS vars from JS. */
.content-sub-tabs-indicator {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2.5px;
    width: var(--sub-ind-w);
    transform: translateX(var(--sub-ind-x));
    background: linear-gradient(90deg,
        var(--primary) 0%,
        var(--secondary) 55%,
        var(--primary) 100%);
    border-radius: 3px 3px 0 0;
    pointer-events: none;
    box-shadow:
        0 0 8px rgba(var(--primary-rgb), 0.55),
        0 0 18px rgba(var(--secondary-rgb), 0.25);
    opacity: 0;
    transition:
        transform 0.38s cubic-bezier(0.4, 0, 0.2, 1),
        width 0.38s cubic-bezier(0.4, 0, 0.2, 1),
        opacity 0.22s ease;
}

/* Once JS has measured the active tab, reveal */
.content-sub-tabs[data-ind-ready] .content-sub-tabs-indicator {
    opacity: 1;
}

/* Search-trigger button — sits flush at the end of the sub-nav with a subtle
   visual separator to signal it's a different "kind" of control. */
.content-sub-search {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: 6px;
    padding: 7px 10px 9px;
    background: transparent;
    border: none;
    border-radius: 10px;
    color: var(--text-muted);
    cursor: pointer;
    position: relative;
    transition: color 0.22s ease, background 0.22s ease, transform 0.18s ease;
    -webkit-tap-highlight-color: transparent;
    outline: none;
}
.content-sub-search::before {
    /* vertical divider between the tabs and the search icon */
    content: '';
    position: absolute;
    left: -6px;
    top: 25%;
    bottom: 25%;
    width: 1px;
    background: rgba(255,255,255,0.08);
}
.content-sub-search svg {
    width: 15px;
    height: 15px;
    transition: transform 0.2s ease;
}
.content-sub-search:hover {
    color: var(--primary);
    background: rgba(var(--primary-rgb), 0.08);
}
.content-sub-search:hover svg {
    transform: scale(1.1);
}
.content-sub-search:focus-visible {
    box-shadow: 0 0 0 2px rgba(var(--primary-rgb), 0.5);
}

/* Search-input field: morphs OUT of the search button on the right edge,
   growing left to fill the sub-tabs container. Content inside fades in after
   the width animation gets going (reads like "button → pill → typable"). */
.content-sub-search-field {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    width: 38px;                     /* starts matching the search button */
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 12px;
    backdrop-filter: blur(0px);
    opacity: 0;
    pointer-events: none;
    overflow: hidden;
    box-shadow: 0 0 0 rgba(var(--primary-rgb), 0);
    box-sizing: border-box;
    transform: translateY(0);
    /* Two-phase transition: width grows first, skin (bg/border/shadow) fades
       in slightly after so the pill "solidifies" as it expands. */
    transition:
        width 0.42s cubic-bezier(0.34, 1.56, 0.64, 1),   /* slight overshoot = snappy pill */
        padding 0.42s cubic-bezier(0.34, 1.56, 0.64, 1),
        background 0.3s ease 0.12s,
        border-color 0.3s ease 0.12s,
        box-shadow 0.3s ease 0.12s,
        backdrop-filter 0.3s ease 0.12s,
        opacity 0.15s ease;
}
.content-sub-search-icon {
    width: 14px;
    height: 14px;
    color: var(--primary);
    flex-shrink: 0;
    margin-left: 4px;
}
#media-search-input {
    flex: 1;
    min-width: 0;
    background: transparent;
    border: none;
    outline: none;
    color: var(--text-primary);
    font-family: inherit;
    font-size: 0.86rem;
    font-weight: 500;
    padding: 6px 2px;
    letter-spacing: 0.15px;
}
#media-search-input::placeholder {
    color: var(--text-muted);
    opacity: 0.7;
}
/* Hide the default "x" clear button WebKit adds to search inputs — we ship our own */
#media-search-input::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
}
.content-sub-search-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    background: rgba(255,255,255,0.04);
    border: none;
    border-radius: 50%;
    color: var(--text-muted);
    cursor: pointer;
    flex-shrink: 0;
    transition:
        background 0.18s ease,
        color 0.18s ease,
        transform 0.28s cubic-bezier(0.34, 1.56, 0.64, 1),
        opacity 0.24s ease;
}
.content-sub-search-close svg {
    width: 13px;
    height: 13px;
}
/* Hover: only applies when in active search state (close is hidden otherwise).
   Uses a child transform so it composes cleanly with the enter-animation
   transform on the parent container. */
.content-sub-search-close:hover {
    background: rgba(var(--secondary-rgb), 0.2);
    color: var(--secondary);
}
.content-sub-search-close:hover svg {
    transform: rotate(90deg);
}
.content-sub-search-close svg {
    transition: transform 0.24s ease;
}

/* ─── SEARCH MODE TRANSITION ────────────────────────────────────────
   Forward (opening): tabs stagger-out quickly, search field morphs from the
   right edge (where the button was) to fill the container, inner content
   fades in last.
   Reverse (closing): inner content fades first, field contracts back to the
   right, tabs stagger-IN with reverse order (books returns first).
   ==================================================================== */

/* Tabs + indicator + button — default state carries HIGH transition-delays
   so on reverse (closing) each tab waits for the field to contract before
   slotting back in. The nth-child reverse-stagger makes books return first. */
.content-sub-tab {
    transition:
        color 0.22s ease,
        background 0.22s ease,
        transform 0.32s cubic-bezier(0.34, 1.56, 0.64, 1),
        opacity 0.22s ease;
}
.content-sub-tabs:not([data-search-active]) .content-sub-tab:nth-child(1) { transition-delay: 0.36s; }  /* movies — last to return */
.content-sub-tabs:not([data-search-active]) .content-sub-tab:nth-child(2) { transition-delay: 0.3s; }
.content-sub-tabs:not([data-search-active]) .content-sub-tab:nth-child(3) { transition-delay: 0.24s; }  /* books — first to return */
.content-sub-tabs:not([data-search-active]) .content-sub-search { transition-delay: 0.42s; }
.content-sub-tabs:not([data-search-active]) .content-sub-tabs-indicator {
    transition-delay: 0.5s, 0.5s, 0s;   /* transform/width wait; opacity from earlier rule */
}

/* Search mode active: kick tabs out with forward stagger + field morphs in */
.content-sub-tabs[data-search-active] .content-sub-tab {
    opacity: 0;
    pointer-events: none;
    transform: translateY(-10px) scale(0.88);
}
.content-sub-tabs[data-search-active] .content-sub-tab:nth-child(1) { transition-delay: 0s; }    /* movies — first to leave */
.content-sub-tabs[data-search-active] .content-sub-tab:nth-child(2) { transition-delay: 0.05s; }
.content-sub-tabs[data-search-active] .content-sub-tab:nth-child(3) { transition-delay: 0.1s; }  /* books — last to leave */

.content-sub-tabs[data-search-active] .content-sub-search {
    opacity: 0;
    pointer-events: none;
    transform: scale(0);
    transition-delay: 0s;
}
.content-sub-tabs[data-search-active] .content-sub-tabs-indicator {
    opacity: 0;
    transform: translateX(var(--sub-ind-x)) scaleX(0);
    transform-origin: right center;
    transition-delay: 0s;
}

/* Field expands + skins itself */
.content-sub-tabs[data-search-active] .content-sub-search-field {
    opacity: 1;
    pointer-events: auto;
    width: 100%;
    padding: 4px 8px;
    background: rgba(15, 10, 30, 0.9);
    border-color: rgba(var(--primary-rgb), 0.35);
    backdrop-filter: blur(8px);
    box-shadow:
        0 6px 24px rgba(var(--primary-rgb), 0.2),
        0 0 0 1px rgba(var(--primary-rgb), 0.1);
    transition:
        width 0.42s cubic-bezier(0.34, 1.56, 0.64, 1) 0.12s,  /* wait for tabs to start fading */
        padding 0.42s cubic-bezier(0.34, 1.56, 0.64, 1) 0.12s,
        background 0.3s ease 0.22s,
        border-color 0.3s ease 0.22s,
        box-shadow 0.3s ease 0.22s,
        backdrop-filter 0.3s ease 0.22s,
        opacity 0.15s ease 0.12s;
}

/* Inner content (icon, input) reveals after the field is ~half-open.
   Close button handled separately (it gets a rotate+scale entrance). */
.content-sub-search-field > :not(.content-sub-search-close) {
    opacity: 0;
    transform: translateX(12px);
    transition:
        opacity 0.24s ease,
        transform 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.content-sub-tabs[data-search-active] .content-sub-search-field > :not(.content-sub-search-close) {
    opacity: 1;
    transform: translateX(0);
}
.content-sub-tabs[data-search-active] .content-sub-search-field > :nth-child(1) { transition-delay: 0.28s; }  /* icon */
.content-sub-tabs[data-search-active] .content-sub-search-field > :nth-child(2) { transition-delay: 0.34s; }  /* input */

/* Close button: rotate + scale entrance. transition defined on the base rule. */
.content-sub-search-close {
    opacity: 0;
    transform: translateX(12px) rotate(-90deg) scale(0.7);
}
.content-sub-tabs[data-search-active] .content-sub-search-close {
    opacity: 1;
    transform: translateX(0) rotate(0deg) scale(1);
    transition-delay: 0.4s;
}

/* Give the sub-tabs container a real min-width while search is active so the
   field has room to breathe on narrow screens. */
.content-sub-tabs[data-search-active] {
    min-width: min(420px, 92vw);
    transition: min-width 0.42s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.content-sub-tabs:not([data-search-active]) {
    transition: min-width 0.3s ease 0.3s;  /* shrink back only after tabs return */
}

/* Mobile: tighter spacing, hide icons only on the smallest screens */
/* breakpoint snap 560px -> 768px (Phase 7.6 ladder) */
@media (max-width: 768px) {
    .content-sub-tab {
        padding: 8px 12px 10px;
        font-size: 0.78rem;
        gap: 6px;
    }
    .content-sub-tab .sub-tab-icon {
        width: 13px;
        height: 13px;
    }
    .content-sub-tabs[data-search-active] {
        min-width: 88vw;
    }
}
/* breakpoint snap 380px -> 480px (Phase 7.6 ladder) */
@media (max-width: 480px) {
    .content-sub-tab {
        padding: 8px 10px 10px;
        font-size: 0.74rem;
    }
    .content-sub-tab .sub-tab-icon {
        display: none;
    }
    #media-search-input { font-size: 0.82rem; }
}

/* ========================================
   SEARCH RESULTS — type badge per-card + empty state
   ======================================== */
.search-result-type {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 3;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 7px;
    background: rgba(10, 6, 20, 0.72);
    border: 1px solid rgba(var(--primary-rgb), 0.35);
    border-radius: 6px;
    color: var(--primary);
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.8px;
    text-transform: uppercase;
    backdrop-filter: blur(4px);
    text-shadow: 0 1px 2px rgba(0,0,0,0.5);
}
.search-result-type svg {
    width: 10px;
    height: 10px;
}

/* Initial state — shown after the search button is clicked but before the
   user types anything. Warm introduction with quick-access chips. */
/* Force-hide the three sibling grids when search is active so nothing
   can leak through (renderMovieCards etc. never touch display, but this
   is defense against future additions that might). */
#media-content.search-mode > #movies-grid,
#media-content.search-mode > #shows-grid,
#media-content.search-mode > #books-grid {
    display: none !important;
}

.search-initial-state {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 48px 20px 80px;
    opacity: 1;                         /* explicit end state */
    animation: searchInitialFadeIn 0.45s ease-out;
}
.search-initial-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 34px 28px 26px;
    /* Solid dark glass — readable against any theme (crimson, ocean, matrix...) */
    background:
        linear-gradient(160deg,
            rgba(20, 14, 38, 0.72),
            rgba(12, 8, 24, 0.82)),
        linear-gradient(135deg,
            rgba(var(--primary-rgb), 0.14),
            rgba(var(--secondary-rgb), 0.1));
    background-blend-mode: overlay;
    border: 1.5px solid rgba(var(--primary-rgb), 0.45);
    border-radius: 20px;
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    max-width: 460px;
    width: 100%;
    box-shadow:
        0 12px 40px rgba(0, 0, 0, 0.45),
        0 0 28px rgba(var(--primary-rgb), 0.22),
        inset 0 1px 0 rgba(255, 255, 255, 0.06);
    position: relative;
    overflow: hidden;
}
/* Subtle moving gradient sheen behind the card content */
.search-initial-card::before {
    content: '';
    position: absolute;
    inset: -50%;
    background: conic-gradient(from 0deg,
        transparent 0deg,
        rgba(var(--primary-rgb), 0.16) 90deg,
        transparent 180deg,
        rgba(var(--secondary-rgb), 0.14) 270deg,
        transparent 360deg);
    animation: searchInitialSpin 14s linear infinite;
    pointer-events: none;
    opacity: 0.55;
    z-index: 0;
}
.search-initial-card > * {
    position: relative;
    z-index: 1;
}
.search-initial-icon-wrap {
    position: relative;
    width: 54px;
    height: 54px;
    display: grid;
    place-items: center;
    margin-bottom: 14px;
    border-radius: 50%;
    background: radial-gradient(circle,
        rgba(var(--primary-rgb), 0.25),
        rgba(var(--primary-rgb), 0.05));
}
.search-initial-icon {
    width: 26px;
    height: 26px;
    color: var(--primary);
    filter: drop-shadow(0 0 6px rgba(var(--primary-rgb), 0.45));
}
.search-initial-sparkle {
    position: absolute;
    top: -4px;
    right: -6px;
    width: 16px;
    height: 16px;
    color: var(--secondary);
    animation: searchInitialSparkle 2.8s ease-in-out infinite;
    filter: drop-shadow(0 0 4px rgba(var(--secondary-rgb), 0.7));
}
.search-initial-title {
    font-size: 1.2rem;
    font-weight: 700;
    margin-bottom: 4px;
    /* Fallback color first (in case background-clip:text fails somewhere);
       then the gradient text override */
    color: var(--primary);
    background: linear-gradient(135deg, var(--primary), var(--secondary));
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    text-shadow: 0 0 22px rgba(var(--primary-rgb), 0.35);
}
.search-initial-sub {
    font-size: 0.86rem;
    color: var(--text-muted);
    margin-bottom: 18px;
}
.search-initial-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: center;
    margin-bottom: 18px;
    max-width: 380px;
}
.search-initial-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(var(--primary-rgb), 0.22);
    border-radius: 100px;
    color: var(--text-secondary);
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 500;
    cursor: pointer;
    transition:
        background 0.2s ease,
        border-color 0.2s ease,
        color 0.2s ease,
        transform 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}
.search-initial-chip:hover {
    background: rgba(var(--primary-rgb), 0.14);
    border-color: rgba(var(--primary-rgb), 0.55);
    color: var(--primary);
    transform: translateY(-1px);
}
.search-initial-chip:active {
    transform: translateY(0);
}
.search-initial-chip .chip-dot {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--secondary);
    flex-shrink: 0;
}
.search-initial-tip {
    font-size: 0.72rem;
    color: var(--text-muted);
    opacity: 0.65;
    letter-spacing: 0.3px;
}
.search-initial-tip kbd {
    display: inline-block;
    padding: 1px 6px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 4px;
    font-family: 'SF Mono', Menlo, monospace;
    font-size: 0.7rem;
    color: var(--text-secondary);
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
}
@keyframes searchInitialFadeIn {
    from { opacity: 0; transform: translateY(12px) scale(0.98); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes searchInitialSpin {
    to { transform: rotate(360deg); }
}
@keyframes searchInitialSparkle {
    0%, 100% { opacity: 0.4; transform: scale(0.9) rotate(0deg); }
    50% { opacity: 1; transform: scale(1.15) rotate(180deg); }
}

.search-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 60px 20px 80px;
    text-align: center;
    animation: searchEmptyFadeIn 0.35s ease-out both;
}
.search-empty-icon {
    width: 48px;
    height: 48px;
    color: var(--text-muted);
    opacity: 0.5;
    margin-bottom: 18px;
}
.search-empty-title {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 6px;
}
.search-empty-title #search-empty-query {
    color: var(--primary);
    font-weight: 700;
}
.search-empty-sub {
    font-size: 0.85rem;
    color: var(--text-muted);
}
@keyframes searchEmptyFadeIn {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}

/* ========================================
   DRAWING CANVAS TAB
   ======================================== */
.draw-container {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    gap: 0;
}

/* Solo / Together mode bar */
.draw-mode-bar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding: 10px 16px;
    background: rgba(0, 0, 0, 0.35);
    border-bottom: 1px solid rgba(var(--secondary-rgb),0.15);
    flex-wrap: wrap;
}

.draw-mode-toggle {
    display: flex;
    gap: 4px;
    padding: 3px;
    background: rgba(0, 0, 0, 0.3);
    border-radius: 30px;
    border: 1px solid rgba(var(--secondary-rgb),0.2);
}

.draw-mode-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 7px 20px;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-muted);
    background: transparent;
    border: none;
    border-radius: 24px;
    cursor: pointer;
    transition: background 0.25s ease, background-color 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease, color 0.25s ease, filter 0.25s ease, opacity 0.25s ease, transform 0.25s ease;
    -webkit-tap-highlight-color: transparent;
}

.draw-mode-btn:hover:not(.active) {
    color: var(--text-primary);
    background: rgba(255, 255, 255, 0.05);
}

.draw-mode-btn.active {
    color: #fff;
    background: linear-gradient(135deg, var(--primary), var(--primary-light));
    font-weight: 700;
    box-shadow: 0 2px 12px rgba(var(--primary-rgb),0.35);
}

.draw-mode-btn.active svg {
    stroke: #fff;
}

.draw-mode-btn[data-mode="online"].active {
    background: linear-gradient(135deg, var(--secondary), #c47ed4);
    color: #fff;
    box-shadow: 0 2px 12px rgba(var(--secondary-rgb),0.4);
}

.draw-mode-btn[data-mode="online"].active svg {
    stroke: #fff;
}

/* Online status indicator */
.draw-online-status {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.8rem;
    color: var(--text-secondary);
    animation: fadeIn 0.3s ease;
}

.draw-online-status.hidden {
    display: none;
}

.draw-status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.draw-status-dot.connected {
    background: #2ed573;
    box-shadow: 0 0 8px rgba(46, 213, 115, 0.6);
    animation: pulse-dot 2s ease infinite;
}

.draw-status-dot.waiting {
    background: var(--primary);
    box-shadow: 0 0 8px rgba(var(--primary-rgb),0.5);
    animation: pulse-dot 1.5s ease infinite;
}

.draw-status-dot.offline {
    background: var(--text-muted);
}

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

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

@media (max-width: 480px) {
    .draw-mode-btn {
        padding: 6px 14px;
        font-size: 0.78rem;
    }
    .draw-mode-bar {
        padding: 8px 10px;
        gap: 10px;
    }
}

.draw-toolbar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid rgba(var(--secondary-rgb),0.25);
    flex-wrap: wrap;
    z-index: 5;
}

.draw-tools-group {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
}

.draw-separator {
    width: 1px;
    height: 28px;
    background: rgba(var(--secondary-rgb),0.3);
    flex-shrink: 0;
}

/* Tool Buttons */
.draw-tool {
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(var(--secondary-rgb),0.2);
    border-radius: var(--radius-md);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.2s ease, background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, color 0.2s ease, filter 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
    -webkit-tap-highlight-color: transparent;
}

.draw-tool:hover {
    background: rgba(255, 255, 255, 0.12);
    color: var(--text-primary);
    border-color: rgba(var(--secondary-rgb),0.4);
}

.draw-tool.active {
    background: linear-gradient(135deg, rgba(var(--primary-rgb),0.2), rgba(var(--secondary-rgb),0.2));
    border-color: var(--accent-primary);
    color: var(--accent-primary);
    box-shadow: 0 0 12px rgba(var(--primary-rgb),0.2);
}

/* Color Picker */
.draw-color-picker {
    position: relative;
    width: 36px;
    height: 36px;
}

.draw-color-picker input[type="color"] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.draw-color-preview {
    width: 36px;
    height: 36px;
    border-radius: var(--radius-md);
    border: 2px solid rgba(255, 255, 255, 0.3);
    background: var(--primary);
    pointer-events: none;
    transition: border-color 0.2s;
}

.draw-color-picker:hover .draw-color-preview {
    border-color: rgba(255, 255, 255, 0.6);
}

/* Quick Colors */
.draw-quick-colors {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
}

.draw-quick-color {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    transition: background 0.2s ease, background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, color 0.2s ease, filter 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
    -webkit-tap-highlight-color: transparent;
}

.draw-quick-color:hover {
    transform: scale(1.2);
}

.draw-quick-color.active {
    border-color: var(--text-primary);
    box-shadow: 0 0 8px rgba(255, 255, 255, 0.3);
}

/* Size & Opacity Sliders */
.draw-size-label {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--text-secondary);
    font-size: 0.8rem;
    cursor: default;
}

.draw-size-icon {
    font-size: 0.9rem;
    color: var(--text-muted);
}

.draw-size-slider {
    -webkit-appearance: none;
    appearance: none;
    width: 70px;
    height: 4px;
    background: rgba(var(--secondary-rgb),0.3);
    border-radius: 2px;
    outline: none;
}

.draw-size-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    background: linear-gradient(135deg, var(--primary), var(--primary-light));
    border-radius: 50%;
    cursor: pointer;
    box-shadow: 0 0 6px rgba(var(--primary-rgb),0.4);
}

.draw-size-slider::-moz-range-thumb {
    width: 14px;
    height: 14px;
    background: linear-gradient(135deg, var(--primary), var(--primary-light));
    border-radius: 50%;
    cursor: pointer;
    border: none;
    box-shadow: 0 0 6px rgba(var(--primary-rgb),0.4);
}

.draw-size-val {
    min-width: 28px;
    text-align: center;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
    font-size: 0.75rem;
}

/* Action Buttons (undo, redo, clear, save) */
.draw-actions {
    gap: 6px;
}

.draw-action {
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(var(--secondary-rgb),0.2);
    border-radius: var(--radius-md);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.2s ease, background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, color 0.2s ease, filter 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
    -webkit-tap-highlight-color: transparent;
}

.draw-action:hover {
    background: rgba(255, 255, 255, 0.12);
    color: var(--text-primary);
    border-color: rgba(var(--secondary-rgb),0.4);
}

.draw-action:active {
    transform: scale(0.92);
}

#draw-clear:hover {
    border-color: rgba(239, 68, 68, 0.5);
    color: #ff6b6b;
}

#draw-save:hover {
    border-color: rgba(46, 213, 115, 0.5);
    color: #2ed573;
}

/* Canvas */
.draw-canvas-wrapper {
    flex: 1;
    min-height: 0;
    position: relative;
    background: #1a1525;
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    overflow: hidden;
    cursor: crosshair;
}

.draw-canvas-wrapper canvas {
    display: block;
    width: 100%;
    height: 100%;
    touch-action: none;
}

/* Mobile draw adjustments */
/* breakpoint snap 600px -> 768px (Phase 7.6 ladder) */
@media (max-width: 768px) {
    .draw-toolbar {
        padding: 8px 10px;
        gap: 8px;
    }
    .draw-tool {
        width: 32px;
        height: 32px;
    }
    .draw-action {
        width: 30px;
        height: 30px;
    }
    .draw-quick-color {
        width: 18px;
        height: 18px;
    }
    .draw-size-slider {
        width: 50px;
    }
    .draw-separator {
        display: none;
    }
}

.draw-sub-content {
    display: none;
    flex-direction: column;
    height: calc(100% - 48px);
    min-height: 0;
}

.draw-sub-content.active {
    display: flex;
}

/* Diary styles moved to diary.css */

} /* end @layer base */
