/* ============================================================================
 * liquid-glass.css
 * ----------------------------------------------------------------------------
 * Apple Liquid Glass language for FireNotify, second pass — fixing the three
 * problems from the first attempt:
 *
 *   1. Pure-white body backdrop made glass invisible (nothing to refract).
 *      This file paints a soft, multi-tone gradient under everything so
 *      backdrop-filter has actual colour content to refract over.
 *
 *   2. Surface alphas were too low (0.62 light). Text floated unreadably.
 *      Now: 0.78 standard / 0.86 strong / 0.55 subtle. Frosted glass is
 *      more opaque than clear glass — text legibility is non-negotiable.
 *
 *   3. Blur was too weak at 22px. Pushed to 30px standard / 40px strong,
 *      with saturate(180-220%) so glass picks up colour from the backdrop.
 *
 * THIS IS THE ONLY FILE THAT DEFINES DESIGN TOKENS. Per-page CSS files
 * reference --fn-* / --lg-* but never redefine them. Old definitions
 * inside individual PHP files have been removed.
 *
 * Load order:
 *   1. liquid-glass.css   (tokens, body, utilities)
 *   2. <per-page>.css     (page-specific styles using these tokens)
 * ========================================================================= */


/* ─────────────────────────────────────────────────────────────────────────
 * 1. BASE TOKENS — brand identity & layout
 * ──────────────────────────────────────────────────────────────────────── */
:root {
    --fn-brand:        #313a46;
    --fn-brand-soft:   rgba(49, 58, 70, .10);
    --fn-brand-softer: rgba(49, 58, 70, .06);
    --fn-accent:       #B03A2E;
    --fn-accent-soft:  rgba(176, 58, 46, .10);
    --fn-header-bg:    var(--fn-brand);

    /* Top-chrome height — initial value used until the JS in
       index.php measures #fnTopChrome and rewrites this var. Was
       11rem when the chrome held both the hero AND a status bar
       below it (badge + count chips). The status bar is gone, so
       the chrome is now just the hero island: ~4rem of content
       inside the rounded card. 5rem leaves a small buffer for
       borders/shadows so the page-host's calc'd padding-top is
       correct on first paint, before the ResizeObserver fires. */
    --fn-tabbar-h:        4.5rem;
    --fn-top-chrome-h:    5rem;
    --fn-safe-top:        max(env(safe-area-inset-top, 0px), .75rem);
    --fn-safe-bottom:     max(env(safe-area-inset-bottom, 0px), .5rem);
}

@media (hover: none) and (pointer: coarse) {
    :root {
        --fn-safe-top: max(env(safe-area-inset-top, 0px), 2.75rem);
    }
}


/* ─────────────────────────────────────────────────────────────────────────
 * 2. LIGHT THEME — surface palette + glass tokens
 * ──────────────────────────────────────────────────────────────────────── */
:root,
[data-bs-theme="light"] {
    --fn-body-bg:        #F3F6FB;
    --fn-card-bg:        #F5F5F7;
    --fn-card-border:    #E3E5E9;
    --fn-text:           #1F2328;
    --fn-text-muted:     #6B7280;
    --fn-tertiary-bg:    #EEF0F3;
    --fn-shadow:         rgba(0,0,0,.06);

    --fn-tabbar-bg:           #F5F5F7;
    --fn-tabbar-border:       #E3E5E9;
    --fn-tabbar-text:         #6B7280;
    --fn-tabbar-text-active:  #313a46;
    --fn-tabbar-indicator:    #313a46;

    /* ── Glass tokens ───────────────────────────────────────
       Higher alpha = more opaque, more readable; lower = glassier but
       text suffers. Tuned for legibility first. */
    --lg-surface:           rgba(255, 255, 255, 0.78);   /* cards, sheets */
    --lg-surface-strong:    rgba(255, 255, 255, 0.86);   /* modals, tabbar */
    --lg-surface-subtle:    rgba(255, 255, 255, 0.55);   /* inner controls */
    --lg-surface-toolbar:   rgba(245, 247, 251, 0.82);   /* status bar */

    --lg-edge:              rgba(255, 255, 255, 0.65);
    --lg-edge-strong:       rgba(255, 255, 255, 0.85);

    /* Divider — inner line between rows inside a card. Contrasts against
       the card surface, not against the page. First attempt used --lg-edge
       for both and inner dividers vanished. Separate token now. */
    --lg-divider:           rgba(15, 23, 42, 0.10);

    --lg-specular: linear-gradient(
        to bottom,
        rgba(255, 255, 255, 0.70) 0%,
        rgba(255, 255, 255, 0.18) 22%,
        rgba(255, 255, 255, 0.00) 48%
    );

    --lg-shadow:            0 1px 0 rgba(255,255,255,0.5) inset,
                            0 8px 24px -6px rgba(15, 23, 42, 0.18),
                            0 2px 6px -2px rgba(15, 23, 42, 0.08);
    --lg-shadow-strong:     0 1px 0 rgba(255,255,255,0.55) inset,
                            0 18px 40px -12px rgba(15, 23, 42, 0.28),
                            0 4px 12px -4px rgba(15, 23, 42, 0.14);

    --lg-hover:             rgba(49, 58, 70, 0.07);
    --lg-pressed:           rgba(49, 58, 70, 0.14);

    --lg-fill-primary:      linear-gradient(135deg, #3a4452 0%, #232a35 100%);
    --lg-fill-danger:       linear-gradient(135deg, #c84536 0%, #9c2e21 100%);
    --lg-fill-success:      linear-gradient(135deg, #1e9d72 0%, #15805c 100%);

    /* ── Tabbar — light mode ────────────────────────────────
       Surface: very translucent so the colourful body backdrop
       reads through (otherwise the bar looks like flat white).
       Pill: solid brand slate, white text/icons — high contrast,
       no ambiguity about which tab is active. */
    --lg-tabbar-surface:    rgba(255, 255, 255, 0.55);
    --lg-tabbar-pill-bg:    #313a46;
    --lg-tabbar-pill-fg:    #ffffff;
    --lg-tabbar-pill-shadow: 0 1px 0 rgba(255,255,255,0.20) inset,
                             0 2px 8px -2px rgba(15, 23, 42, 0.35),
                             0 3px 10px -4px rgba(49, 58, 70, 0.45);
    --lg-tabbar-shadow:     0 1px 0 rgba(255,255,255,0.55) inset,
                            0 14px 36px -10px rgba(15, 23, 42, 0.32),
                            0 4px 12px -4px rgba(15, 23, 42, 0.16);
}


/* ─────────────────────────────────────────────────────────────────────────
 * 3. DARK THEME — mirrored palette
 * ──────────────────────────────────────────────────────────────────────── */
[data-bs-theme="dark"] {
    --fn-body-bg:        #13161B;
    --fn-card-bg:        #23272C;
    --fn-card-border:    #2E343B;
    --fn-text:           #E6E8EB;
    --fn-text-muted:     #9099A4;
    --fn-tertiary-bg:    #2A2F35;
    --fn-shadow:         rgba(0,0,0,.3);

    --fn-tabbar-bg:           #23272C;
    --fn-tabbar-border:       #2E343B;
    --fn-tabbar-text:         #9099A4;
    --fn-tabbar-text-active:  #E6E8EB;
    --fn-tabbar-indicator:    #E6E8EB;

    --lg-surface:           rgba(35, 39, 46, 0.72);
    --lg-surface-strong:    rgba(35, 39, 46, 0.86);
    --lg-surface-subtle:    rgba(50, 55, 65, 0.50);
    --lg-surface-toolbar:   rgba(28, 32, 38, 0.80);

    --lg-edge:              rgba(255, 255, 255, 0.10);
    --lg-edge-strong:       rgba(255, 255, 255, 0.18);
    --lg-divider:           rgba(255, 255, 255, 0.12);

    --lg-specular: linear-gradient(
        to bottom,
        rgba(255, 255, 255, 0.16) 0%,
        rgba(255, 255, 255, 0.05) 24%,
        rgba(255, 255, 255, 0.00) 52%
    );

    --lg-shadow:            0 1px 0 rgba(255,255,255,0.06) inset,
                            0 8px 28px -6px rgba(0, 0, 0, 0.55),
                            0 2px 6px -2px rgba(0, 0, 0, 0.35);
    --lg-shadow-strong:     0 1px 0 rgba(255,255,255,0.08) inset,
                            0 22px 48px -14px rgba(0, 0, 0, 0.72),
                            0 4px 14px -4px rgba(0, 0, 0, 0.45);

    --lg-hover:             rgba(255, 255, 255, 0.07);
    --lg-pressed:           rgba(255, 255, 255, 0.14);

    --lg-fill-primary:      linear-gradient(135deg, #4a5462 0%, #303744 100%);
    --lg-fill-danger:       linear-gradient(135deg, #d04938 0%, #9c2e21 100%);
    --lg-fill-success:      linear-gradient(135deg, #1fa37a 0%, #128057 100%);

    /* ── Tabbar — dark mode ─────────────────────────────────
       Surface lighter than first pass (0.96 → 0.88) so it doesn't read
       as a black bar. Shadow drops the white inset-highlight that was
       creating a "reflection" line on top — pure dark glass now. */
    --lg-tabbar-surface:    rgba(28, 32, 38, 0.88);
    --lg-tabbar-pill-bg:    #3f4855;
    --lg-tabbar-pill-fg:    #ffffff;
    --lg-tabbar-pill-shadow: 0 1px 0 rgba(255,255,255,0.10) inset,
                             0 2px 8px -2px rgba(0, 0, 0, 0.50);
    --lg-tabbar-shadow:     0 14px 36px -10px rgba(0, 0, 0, 0.65),
                            0 4px 12px -4px rgba(0, 0, 0, 0.40);
}


/* ─────────────────────────────────────────────────────────────────────────
 * 4. THEME-INDEPENDENT — blur, radii, easing
 * ──────────────────────────────────────────────────────────────────────── */
:root {
    --lg-blur:              blur(30px) saturate(180%);
    --lg-blur-strong:       blur(40px) saturate(220%);
    --lg-blur-subtle:       blur(16px) saturate(160%);

    --lg-r-sm:              0.65rem;
    --lg-r-md:              1.00rem;
    --lg-r-lg:              1.35rem;
    --lg-r-xl:              1.75rem;
    --lg-r-pill:            999px;

    --lg-spring:            cubic-bezier(0.34, 1.56, 0.64, 1);
    --lg-ease:              cubic-bezier(0.22, 0.61, 0.36, 1);
    --lg-t-fast:            120ms;
    --lg-t-base:            240ms;
    --lg-t-slow:            420ms;
}


/* ─────────────────────────────────────────────────────────────────────────
 * 5. BODY BACKDROP — the colourful underlayer
 * Three pale colour pools on a cool-gray base give backdrop-filter
 * actual content to refract. background-attachment: fixed keeps the
 * wash anchored so glass always refracts the same thing.
 *
 * Scroll lock note (Marco, 2026-05): the html/body overflow:hidden
 * lock below is now OPT-IN via `html.fn-shell-lock`. It was global
 * before, which silently broke every admin page that happens to
 * load this stylesheet (accounts-admin.php, responses-config.php)
 * — those are normal scrolling documents and don't have an inner
 * scroll container the way the SPA shell does. On iPhone the lock
 * was completely freezing page scroll. The SPA shell (index.php)
 * still wants the lock so the tab carousel works correctly, so it
 * adds `class="fn-shell-lock"` to its <html>; every other page
 * leaves it off and scrolls normally.
 * ──────────────────────────────────────────────────────────────────────── */
html,
body {
    margin: 0;
}
html.fn-shell-lock,
html.fn-shell-lock body {
    height: 100%;
    width: 100%;
    overflow: hidden;
    overscroll-behavior: none;
}
@media (hover: none) and (pointer: coarse) {
    html.fn-shell-lock,
    html.fn-shell-lock body {
        position: relative;
        overflow: hidden;
        height: 100%;
    }
}

body {
    color: var(--fn-text);
    font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;

    /* Brand-derived backdrop. Top-left pool is pale slate-blue (from
       brand #313a46), bottom-right pool is pale red-coral (from accent
       #B03A2E). The diagonal warm-to-cool wash gives glass surfaces
       brand-coherent colour to refract over instead of generic pastels.
       Middle stays close to the base body colour so the wash never
       fights the content. */
    background-color: var(--fn-body-bg);
    background-image:
        radial-gradient(ellipse 80% 65% at 10% 5%,   rgba(120, 145, 195, 0.40), transparent 62%),
        radial-gradient(ellipse 80% 65% at 95% 100%, rgba(220, 130, 110, 0.32), transparent 62%);
    background-attachment: fixed;
    background-repeat: no-repeat;
    background-size: 100% 100%;
}

[data-bs-theme="dark"] body {
    /* Same diagonal arrangement, deeper colours so they read through
       the near-opaque tabbar without losing the dark-mode mood. */
    background-image:
        radial-gradient(ellipse 80% 65% at 10% 5%,   rgba(42, 62, 110, 0.65), transparent 62%),
        radial-gradient(ellipse 80% 65% at 95% 100%, rgba(110, 38, 32, 0.55), transparent 62%);
}

/* ─────────────────────────────────────────────────────────────────────────
 * Safe-area gentle shade — fades from a soft darkening at the very top
 * (where iOS draws time / wifi / battery in white) down to transparent.
 *
 * Per user feedback, the strip extends about 1.75rem BEYOND the safe-
 * area inset so the dark-to-transparent fade has room to blend
 * gracefully into the page background. Previously the strip ended at
 * exactly safe-top, which produced a visible horizontal line where the
 * gradient cut off. With the extra runway, the bottom of the fade
 * passes UNDER the floating chrome island (z-index 50 > our 1) and the
 * eye reads it as a soft glow rather than a banded edge.
 *
 * Gradient stops are weighted toward the top so the darkness sits
 * where iOS actually draws the white system glyphs; from ~40% downward
 * it tapers to a hint of tone, then fully transparent. Dark mode: the
 * whole strip blends in.
 * ──────────────────────────────────────────────────────────────────────── */
body::before {
    content: "";
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: calc(var(--fn-safe-top) + 1.75rem);
    /* Two layered gradients (first listed = top layer):
       1. Horizontal — adds ~0.18 alpha extra darkness on the right
          half of the safe-area, fading transparently from 55% across.
          iOS status indicators (cell signal, wifi, battery) live on
          the right and were getting washed out on light backdrops;
          the time on the left was already legible from the vertical
          gradient alone. This bumps just the right side.
       2. Vertical — top-down fade with stops concentrated in the
          upper third so the system glyphs stay legible, then a long
          smooth taper from ~35% down to 100% so the bottom edge
          disappears into the page rather than ending in a hard line. */
    background:
        linear-gradient(to right,
            transparent      0%,
            transparent      55%,
            rgba(15, 17, 21, 0.18) 100%),
        linear-gradient(to bottom,
            rgba(15, 17, 21, 0.70) 0%,
            rgba(15, 17, 21, 0.55) 25%,
            rgba(15, 17, 21, 0.20) 60%,
            rgba(15, 17, 21, 0.06) 85%,
            transparent           100%);
    z-index: 1;
    pointer-events: none;
}

/* Touch hygiene */
* {
    -webkit-tap-highlight-color: transparent;
    -webkit-touch-callout: none;
}
.fn-page-inner,
.fn-addr-stage {
    -webkit-user-select: text;
    user-select: text;
}
.fn-hero,
.fn-tabbar,
.fn-tab,
button {
    -webkit-user-select: none;
    user-select: none;
}


/* ─────────────────────────────────────────────────────────────────────────
 * 6. UTILITY CLASSES
 * ──────────────────────────────────────────────────────────────────────── */
.lg-glass {
    background-color: var(--lg-surface);
    backdrop-filter: var(--lg-blur);
    -webkit-backdrop-filter: var(--lg-blur);
    border: 1px solid var(--lg-edge);
    box-shadow: var(--lg-shadow);
}
.lg-glass--strong {
    background-color: var(--lg-surface-strong);
    backdrop-filter: var(--lg-blur-strong);
    -webkit-backdrop-filter: var(--lg-blur-strong);
    border: 1px solid var(--lg-edge-strong);
    box-shadow: var(--lg-shadow-strong);
}
.lg-glass--subtle {
    background-color: var(--lg-surface-subtle);
    backdrop-filter: var(--lg-blur-subtle);
    -webkit-backdrop-filter: var(--lg-blur-subtle);
    border: 1px solid var(--lg-edge);
}

.lg-specular {
    position: relative;
    isolation: isolate;
}
.lg-specular::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background-image: var(--lg-specular);
    pointer-events: none;
    z-index: 0;
}
.lg-specular > * { position: relative; z-index: 1; }

.lg-spring {
    transition: transform var(--lg-t-base) var(--lg-spring),
                box-shadow var(--lg-t-base) var(--lg-ease),
                background-color var(--lg-t-base) var(--lg-ease);
}
.lg-spring:active {
    transform: scale(0.97);
    transition: transform var(--lg-t-fast) var(--lg-ease);
}


/* ─────────────────────────────────────────────────────────────────────────
 * 7. ACCESSIBILITY FALLBACKS
 * iOS Settings > Accessibility > Reduce Transparency flips everything
 * to solid surfaces. Reduce Motion drops the spring transitions.
 * ──────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-transparency: reduce) {
    body {
        background-image: none;
        background-color: var(--fn-body-bg);
    }
    .lg-glass,
    .lg-glass--strong,
    .lg-glass--subtle,
    .fn-call-card,
    .fn-set-card,
    .fn-tabbar,
    .fn-confirm-card,
    .fn-carousel-arrow,
    .fn-segmented,
    .fn-set-select,
    .fn-offcanvas-panel {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
        background-color: var(--fn-card-bg) !important;
    }
    .fn-tabbar {
        background-color: var(--fn-tabbar-bg) !important;
    }
}

@media (prefers-reduced-motion: reduce) {
    .lg-spring,
    .lg-spring:active {
        transition-duration: 0ms !important;
        transform: none !important;
    }
}


/* ─────────────────────────────────────────────────────────────────────────
 * 8. WEBKIT — pin glass surfaces to their own compositing layer so
 * older WKWebView repaints them on scroll.
 * ──────────────────────────────────────────────────────────────────────── */
.lg-glass,
.lg-glass--strong,
.fn-call-card,
.fn-set-card,
.fn-tabbar,
.fn-confirm-card,
.fn-offcanvas-panel {
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
}