/*
    Single source of truth for design tokens — colors, shadows, radii, button
    gradients, tab/pill active states, etc. Both light and dark themes.
    Imported by Shared's app.css for Web/MAUI; linked directly by WebAdmin's
    App.razor so all three projects share the same colors and dark/light
    behavior. WebAdmin keeps its admin-specific tokens (sidebar width, header
    height, font-family) in admin.css.
*/

/* ====== DESIGN TOKENS ====== */
:root {
    --safe-area-top: env(safe-area-inset-top, 0px);
    --safe-area-bottom: env(safe-area-inset-bottom, 0px);
    /* --safe-area-bottom divided by the active display-zoom. EVERY fixed bottom
       bar (.bottom-nav + page action/footer/input bars) must use this instead
       of raw --safe-area-bottom: the inset is a physical device dimension, so
       when displayScaleManager's CSS zoom on <html> scales the page at >1, the
       raw inset inflates and the bar grows taller than the main nav. Dividing
       keeps the gesture-bar gap physical so all bottom bars stay the same
       height. See MainLayout.razor.css .bottom-nav for the original note. */
    --safe-area-bottom-fixed: calc(var(--safe-area-bottom) / var(--app-zoom, 1));
    --blue-primary: #1565C0;
    --blue-primary-rgb: 21, 101, 192;
    --blue-dark: #0D2137;
    --blue-light: #4A90D9;
    --blue-accent: #2196F3;
    --blue-pale: #E8F1FB;
    --bg-cream: #EFEFEF;
    --bg-page: #FAFAFA;
    --bg-white: #FFFFFF;
    /* A surface that sits ABOVE --bg-white. Used by the selectable-row trough
       behind the category pills and the filter chips.

       Light mode has nowhere to go above #FFFFFF, so it stays white and the
       trough is separated by its edge instead (it carries --shadow-card, the
       same hairline plus contact the cards use). Dark mode DOES have room and
       needs it: --bg-white #1A1E24 on a --bg-page #111418 is a 9/255 step,
       which does not read as a container at all. Measured, not eyeballed. */
    --bg-raised: #FFFFFF;
    /* A tonal block sitting ON a white card: the unselected date and time chips.
       It cannot be --bg-page, which is #FAFAFA and only a 5/255 step from white,
       so on a card it reads as nothing at all. Measured, not guessed. */
    --bg-sunken: #EDF0F4;
    --text-primary: #0D2137;
    --text-secondary: #5A6978;
    /* Was #9EAAB6, which measured 2.37:1 on white — below the 4.5:1 WCAG AA needs for text
       this size. It carried every card's supporting line AND, via .nav-item + currentColor,
       the label and icon of every unselected bottom-nav destination, so the app's primary
       navigation was its faintest element. #67737F measures 4.84:1 and is still clearly
       lighter than --text-secondary (5.63:1), so the hierarchy this token exists to create
       survives. Don't lighten it back without re-measuring. */
    --text-muted: #67737F;
    --border: #C0C8D0;
    --border-strong: #A0AAB4;
    --green-badge: #16A34A;
    --green-light: #ECFDF5;
    --green-wa: #25D366;
    --orange-badge: #EA580C;
    --orange-light: #FFF7ED;
    --red: #EF4444;
    --red-light: #FEF2F2;
    --yellow: #EAB308;
    --yellow-light: #FEFCE8;
    /* Text-on-light-fill yellow, the sibling --green-badge/--orange-badge already had.
       --yellow itself is only 1.9:1 on white (4.5:1 required), so it can never be text in
       light mode; this amber reads 4.9:1 on white and 4.8:1 on --yellow-light. Dark mode
       flips to the bright --yellow, which is 12.5:1 there. */
    --yellow-badge: #A16207;
    /* Stacked shadows — Android WebView renders large single-blur shadows
       with visible banding on dark surfaces. Multiple smaller blurs hide it. */
    --shadow-sm: 0 1px 1px rgba(13,33,55,0.04), 0 1px 2px rgba(13,33,55,0.04);
    --shadow-md: 0 1px 2px rgba(13,33,55,0.05), 0 2px 4px rgba(13,33,55,0.04), 0 4px 8px rgba(13,33,55,0.03);
    --shadow-lg: 0 2px 4px rgba(13,33,55,0.06), 0 4px 8px rgba(13,33,55,0.05), 0 8px 16px rgba(13,33,55,0.04);
    --shadow-card: 0 1px 2px rgba(13,33,55,0.06), 0 2px 4px rgba(13,33,55,0.04), 0 0 0 1px rgba(13,33,55,0.08);
    /* Two shadows named by what they LOOK like, so a theme can point the role
       token (--shadow-card) at either without either value having to be
       restated per theme. --shadow-hairline is today's card shadow, kept under
       its own name because things that must stay hairline (the pill trough)
       still need it after --shadow-card has been repointed. --shadow-float is
       the deeper layered drop the floating header and nav already use. */
    --shadow-hairline: 0 1px 2px rgba(13,33,55,0.06), 0 2px 4px rgba(13,33,55,0.04), 0 0 0 1px rgba(13,33,55,0.08);
    --shadow-float: 0 2px 6px rgba(13,33,55,0.10), 0 12px 28px -8px rgba(13,33,55,0.30);
    /* A small raised container (the pill and chip trough), separated WITHOUT a        drawn edge. --shadow-hairline ends in 0 0 0 1px, a zero-blur spread, and        that is a hard line with a real pixel size: at display zoom 1.2 or 1.4 it        lands on a fractional row and Chromium smears it across two, so it reads        heavier and darker than a hairline should. On the trough's top edge, right        above the pills, that came out as a visible bar. It stood out because the        capsule theme had removed every other drawn edge, leaving this one alone.         Same failure family as the --btn-sheen note above: anything with a 1px        size is at the mercy of the display scale. Blur has no such size, so these        three layers do the separating instead, pitched a little stronger because        a white trough on a #FAFAFA page is only a 5/255 step on its own. */     --shadow-raised: 0 1px 2px rgba(13,33,55,0.07), 0 3px 8px -2px rgba(13,33,55,0.10), 0 8px 18px -8px rgba(13,33,55,0.16);
    /* The two stops of a lit --blue-pale: same tint with light falling from
       above. Used by the card tag ("Hari Ini" / "Besok") under capsule. */
    --blue-pale-top: #F2F7FE;
    --blue-pale-bottom: #DCE9F8;
    /* The same lighting as a translucent overlay, for the tinted status badges
       (Admin and Agent .badge: green, red, orange, yellow, muted) that have no
       per-colour top and bottom stops. Painted over the badge's own tint, it
       lands on the two blue-pale stops above to the pixel: 45 percent white over
       #E8F1FB is #F2F7FD, and 6 percent of the ink (#1565C0) over it is #DCE9F8.
       currentColor is the badge's ink, so one pair serves every colour. Dark
       mode below lights the top with the ink instead of white, which is what
       --blue-pale-top does there (#27405C is bluer than #1A2D42, not whiter). */
    --lit-overlay-top: rgba(255,255,255,0.45);
    --lit-overlay-bottom: color-mix(in srgb, currentColor 6%, transparent);
    --chat-bubble-start: #1565C0;
    --chat-bubble-end: #2196F3;
    --mono-bg: rgba(107,114,128,0.12);
    --mono-fg: #374151;
    --purple-light: rgba(139,127,216,0.12);
    --purple-badge: #8B7FD8;
    --teal-light: rgba(20,184,166,0.12);
    --teal-badge: #14B8A6;
    --rose-light: rgba(244,114,182,0.12);
    --rose-badge: #EC4899;
    --amber-light: rgba(245,158,11,0.12);
    /* Every use of this pairs the badge colour with --amber-light behind it, and #D97706
       on that tint measured 2.91:1 — under the 4.5:1 floor for text this size. One step
       deeper clears it at 4.61:1 and still reads as amber. */
    --amber-badge: #B45309;
    --sug-bg: rgba(232,241,251,0.95);
    --sug-border: rgba(21,101,192,0.12);
    --sug-label: #5A6978;
    --sug-text: #0D2137;
    --sug-icon: #1565C0;
    --sug-hover: rgba(21,101,192,0.08);
    --sug-active: rgba(21,101,192,0.14);
    --radius: 16px;
    --radius-sm: 12px;
    --radius-xs: 8px;
    --nav-height: 64px;
    --header-bar-height: 40px;
    /* Bottom inset that slide-up modals must respect. Default = just the
       device safe-area (modal flush to screen bottom on pages without a
       bottom-nav, e.g. AuthLayout sub-pages). The body:has() override
       below kicks in when the page renders a .bottom-nav or .app-bottom-bar
       so the modal stops above them and they remain visible. */
    --modal-bottom-offset: var(--safe-area-bottom-fixed);
    --header-grad-start: #0D2137;
    --header-grad-mid: #1565C0;
    --header-grad-end: #4A90D9;
    --header-avatar-border: #0D2137;
    --btn-active-bg: #0D2137;
    --toast-bg: #0D2137;

    /* Button gradients — light mode keeps the bright primary colors. Dark mode
       overrides below soften them (navy / moss / maroon) so the eye isn't
       hammered by saturated red/green/blue against a black surface. */
    --btn-primary-start: #1565C0;
    --btn-primary-end: #2196F3;
    --btn-primary-shadow: rgba(21,101,192,0.3);
    --btn-success-start: #16A34A;
    --btn-success-end: #22C55E;
    --btn-success-shadow: rgba(22,163,74,0.3);
    --btn-danger-start: #DC2626;
    --btn-danger-end: #EF4444;
    --btn-danger-shadow: rgba(220,38,38,0.3);

    /* Capsule buttons (2026-09-06). --btn-sheen is the highlight along the top of
       a filled button, which is what makes a pill read as a raised object rather
       than a coloured blob; --btn-contact is the tight neutral contact shadow
       under it. The glow tokens above own the wide coloured falloff.

       --btn-sheen is a GRADIENT STOP, not a 1px inset shadow, and that is the
       whole point (corrected 2026-09-07). As an inset hairline at 45% it drew a
       hard white line: this app runs zoom: 1.1 on <html>, so a 1px feature
       renders as 1.1 physical pixels and smears across two rows as a pale band.
       Measured on the real button, the top row came out #85C5F8 against a
       #2A99F2 fill, which together with the anti-aliased bottom edge read as a
       border around the pill rather than a highlight on it. A gradient stop has
       no pixel size, so it survives any display scale. Same failure family as
       the AppHeader hairline note; do not put this back as an inset. */
    /* SUPERSEDED by --sheen-layer below, which is the only thing that should
       paint a sheen now. Kept because the note above records why this must
       never go back to being a 1px inset shadow, and because a bare colour is
       still the right token to derive a new sheen curve from. Do not use it as
       a two-stop ramp again: that is what produced the band. */
    --btn-sheen: rgba(255,255,255,0.22);
    /* The sheen as a whole LAYER, not just its top stop.

       It used to be written inline as `var(--btn-sheen) 0%, transparent 45%`,
       and that straight ramp is what put a visible hard band across the top of
       every filled control. The reason is a slope break, not a colour: down the
       middle of a selected pill the green channel fell about 100 units per unit
       of height above the 45% stop and 49 below it, and a 2x kink in an
       otherwise smooth ramp is exactly what the eye reads as an edge (a Mach
       band). It showed worst on a 34px pill, where the whole ramp is 15px.

       The stops below decay geometrically instead, and the last segment is
       tuned to arrive at roughly -52, which is the base gradient's own -49. The
       two slopes meet instead of colliding, so there is nothing to see. Measured
       profile: -99, -84, -67, -58, -52.

       Do not flatten this back into two stops. */
    --sheen-layer: linear-gradient(180deg,
        rgba(255,255,255,0.20) 0%,
        rgba(255,255,255,0.115) 16%,
        rgba(255,255,255,0.055) 34%,
        rgba(255,255,255,0.020) 56%,
        rgba(255,255,255,0.005) 78%,
        rgba(255,255,255,0) 100%);
    --btn-contact: rgba(13,33,55,0.10);

    /* Active state for tab segments + filter pills. Light mode keeps the bright
       brand blue; dark mode overrides below mute it to a navy that doesn't burn
       against dark surfaces. */
    --tab-active-bg: var(--blue-primary);
    --tab-active-shadow: rgba(21,101,192,0.25);

    /* The tab strip that rides inside the blue header (Aktivitas, Notifikasi).
       A lit white trough: white at the top edge, dimming to blue-pale at the
       bottom, so the light falls on it from the same direction as on the header
       and the brand pill it holds. Chosen 2026-09-11 from six troughs; the ink
       is the idle tab text, a deep blue rather than grey so the strip stays one
       family with the band around it. Dark mode swaps in a raised-to-sunken ramp
       below; "white" there is not white. */
    --header-tabs-fill: linear-gradient(180deg, #FFFFFF 0%, #EAF2FB 100%);
    --header-tabs-ink: #3B5A7A;

    /* The icon tile on the chat context card under capsule: a white disc lit
       from above, standing in the card's sunken trough. Light and dark ramps
       here; ui-theme.css decides whether the tile is used at all. */
    --ctx-tile-fill: linear-gradient(180deg, #FFFFFF 0%, #EEF4FB 100%);

    /* The chevron a native <select> shows once its OS arrow is stripped. This is
       the one chevron that cannot be an <Icon>: a background-image is a document
       of its own, so it reaches neither the component nor the --icon-* tokens,
       and therefore carries its own sheen and shade stops (the same path drawn
       three times). Kept in step with ic-chevron-bawah in IconDefs.razor by
       hand; there is no way to share the geometry. One token so that the
       customer app, Admin and Agent draw the same arrow: a select takes
       `appearance: none`, right padding for the arrow, and this as its
       background-image at 14px, right 12px center. Not themed: the grey stroke
       sits on a tonal field in both modes. */
    --select-chevron: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24'><defs><linearGradient id='s' x1='0' y1='0' x2='0' y2='1'><stop offset='0' stop-color='%23ffffff' stop-opacity='.40'/><stop offset='.34' stop-color='%23ffffff' stop-opacity='.104'/><stop offset='1' stop-color='%23ffffff' stop-opacity='0'/></linearGradient><linearGradient id='d' x1='0' y1='0' x2='0' y2='1'><stop offset='0' stop-color='%23061A2E' stop-opacity='0'/><stop offset='.64' stop-color='%23061A2E' stop-opacity='.040'/><stop offset='1' stop-color='%23061A2E' stop-opacity='.220'/></linearGradient></defs><g fill='none' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path stroke='%236B7280' d='M5.2 9.4 12 16.2l6.8-6.8'/><path stroke='url(%23s)' d='M5.2 9.4 12 16.2l6.8-6.8'/><path stroke='url(%23d)' d='M5.2 9.4 12 16.2l6.8-6.8'/></g></svg>");
}

/* ====== DARK MODE ====== */
[data-theme="dark"] {
    --chat-bubble-start: #0A2A4A;
    --chat-bubble-end: #143D6B;
    --mono-bg: rgba(156,163,175,0.18);
    --mono-fg: #D1D5DB;
    --purple-light: rgba(139,127,216,0.18);
    --purple-badge: #A89CE5;
    --teal-light: rgba(20,184,166,0.18);
    --teal-badge: #2DD4BF;
    --rose-light: rgba(244,114,182,0.18);
    --rose-badge: #F472B6;
    --amber-light: rgba(245,158,11,0.18);
    --amber-badge: #FBBF24;
    --sug-bg: rgba(42,58,82,0.9);
    --sug-border: rgba(91,159,230,0.18);
    --sug-label: rgba(200,216,232,0.5);
    --sug-text: rgba(226,232,240,0.9);
    --sug-icon: rgba(91,159,230,0.7);
    --sug-hover: rgba(91,159,230,0.1);
    --sug-active: rgba(91,159,230,0.18);
    --blue-primary: #5B9FE6;
    --blue-primary-rgb: 91, 159, 230;
    --blue-dark: #C8D8E8;
    --blue-light: #6BADE6;
    --blue-accent: #5BADE6;
    --blue-pale: #1A2D42;
    --bg-cream: #13161B;
    --bg-page: #111418;
    --bg-white: #1A1E24;
    /* Lifted clear of --bg-white here, unlike light mode. See the light block. */
    --bg-raised: #242A33;
    --bg-sunken: #252B33;
    --text-primary: #E2E8F0;
    --text-secondary: #A0AEC0;
    /* Was #5A6978— 2.97:1 on --bg-white (#1A1E24), the dark-mode half of the same defect
       described on the light token above. #8794A3 measures 5.42:1. */
    --text-muted: #8794A3;
    --border: #2D3748;
    --border-strong: #4A5568;
    --green-badge: #48BB78;
    --green-light: #1A2E22;
    --green-wa: #25D366;
    --orange-badge: #ED8936;
    --orange-light: #2D2215;
    --red: #FC8181;
    --red-light: #2D1B1B;
    --yellow: #F6E05E;
    --yellow-light: #2D2A15;
    --yellow-badge: #F6E05E;
    /* Dark mode: keep drop shadow subtle (small Y offset) + add symmetric
       glow so the card edge is visible all around, not just bottom-right.
       Pure drop-shadow on dark surfaces looks asymmetric like a hovering
       UFO; halo + tiny drop reads more like Material elevation. */
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.20), 0 0 4px rgba(0,0,0,0.14);
    --shadow-md: 0 1px 2px rgba(0,0,0,0.24), 0 2px 4px rgba(0,0,0,0.18), 0 0 8px rgba(0,0,0,0.16);
    --shadow-lg: 0 2px 4px rgba(0,0,0,0.28), 0 4px 8px rgba(0,0,0,0.20), 0 0 16px rgba(0,0,0,0.16);
    --shadow-card: 0 1px 2px rgba(0,0,0,0.25), 0 0 8px rgba(0,0,0,0.16), 0 0 0 1px rgba(255,255,255,0.05);
    --shadow-hairline: 0 1px 2px rgba(0,0,0,0.25), 0 0 8px rgba(0,0,0,0.16), 0 0 0 1px rgba(255,255,255,0.05);
    --shadow-float: 0 2px 6px rgba(0,0,0,0.45), 0 12px 28px -8px rgba(0,0,0,0.75);
    /* Dark already separates by colour (#242A33 on #111418), so this only has to
       seat the trough rather than outline it. */
    --shadow-raised: 0 1px 2px rgba(0,0,0,0.35), 0 3px 10px -2px rgba(0,0,0,0.45), 0 8px 20px -8px rgba(0,0,0,0.55);
    --blue-pale-top: #27405C;
    --blue-pale-bottom: #172433;
    --lit-overlay-top: color-mix(in srgb, currentColor 14%, transparent);
    --lit-overlay-bottom: rgba(0,0,0,0.12);
    --header-grad-start: #0A0F18;
    --header-grad-mid: #122244;
    --header-grad-end: #1A3358;
    --header-avatar-border: #1A1E24;
    --btn-active-bg: #2D4A6F;
    --toast-bg: #2D3748;

    /* Button gradients for dark mode — toned down from light-mode saturation
       to avoid harshness on dark surfaces, BUT enough chroma supaya warnanya
       (hijau, merah) jelas terbaca semantic-nya. Sebelumnya terlalu muted —
       hijau jadi gray-greenish, merah jadi brown. */
    --btn-primary-start: #1E3A5F;
    --btn-primary-end: #2D5283;
    --btn-primary-shadow: rgba(50,90,140,0.35);
    --btn-success-start: #16803D;
    --btn-success-end: #1FA653;
    --btn-success-shadow: rgba(34,180,90,0.40);
    --btn-danger-start: #B83A3A;
    --btn-danger-end: #D04545;
    --btn-danger-shadow: rgba(208,69,69,0.40);

    /* Keep in lock-step with the [data-theme="system"] copy below. */
    --btn-sheen: rgba(255,255,255,0.10);
    /* Same curve, alphas scaled by the dark/light --btn-sheen ratio (0.10/0.22). */
    --sheen-layer: linear-gradient(180deg,
        rgba(255,255,255,0.090) 0%,
        rgba(255,255,255,0.052) 16%,
        rgba(255,255,255,0.025) 34%,
        rgba(255,255,255,0.009) 56%,
        rgba(255,255,255,0.002) 78%,
        rgba(255,255,255,0) 100%);
    --btn-contact: rgba(0,0,0,0.35);

    /* Muted tab/pill active for dark mode. */
    --tab-active-bg: #2D4A6F;
    --tab-active-shadow: rgba(45,74,111,0.35);

    --header-tabs-fill: linear-gradient(180deg, #2A313B 0%, #1E2732 100%);
    --header-tabs-ink: #A9C4E4;
    --ctx-tile-fill: linear-gradient(180deg, #2E3641 0%, #232A33 100%);

    color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
    [data-theme="system"] {
        --chat-bubble-start: #0A2A4A;
        --chat-bubble-end: #143D6B;
        --mono-bg: rgba(156,163,175,0.18);
        --mono-fg: #D1D5DB;
        --purple-light: rgba(139,127,216,0.18);
        --purple-badge: #A89CE5;
        --teal-light: rgba(20,184,166,0.18);
        --teal-badge: #2DD4BF;
        --rose-light: rgba(244,114,182,0.18);
        --rose-badge: #F472B6;
        --amber-light: rgba(245,158,11,0.18);
        --amber-badge: #FBBF24;
        --sug-bg: rgba(42,58,82,0.9);
        --sug-border: rgba(91,159,230,0.18);
        --sug-label: rgba(200,216,232,0.5);
        --sug-text: rgba(226,232,240,0.9);
        --sug-icon: rgba(91,159,230,0.7);
        --sug-hover: rgba(91,159,230,0.1);
        --sug-active: rgba(91,159,230,0.18);
        --blue-primary: #5B9FE6;
    --blue-primary-rgb: 91, 159, 230;
        --blue-dark: #C8D8E8;
        --blue-light: #6BADE6;
        --blue-accent: #5BADE6;
        --blue-pale: #1A2D42;
        --bg-cream: #13161B;
        --bg-page: #111418;
        --bg-white: #1A1E24;
        --bg-raised: #242A33;
    --bg-sunken: #252B33;   /* keep in lock-step with the [data-theme="dark"] block above */
        --text-primary: #E2E8F0;
        --text-secondary: #A0AEC0;
        --text-muted: #8794A3;   /* keep in lock-step with the [data-theme="dark"] block above */
        --border: #2D3748;
        --border-strong: #4A5568;
        --green-badge: #48BB78;
        --green-light: #1A2E22;
        --green-wa: #25D366;
        --orange-badge: #ED8936;
        --orange-light: #2D2215;
        --red: #FC8181;
        --red-light: #2D1B1B;
        --yellow: #F6E05E;
        --yellow-light: #2D2A15;
        --yellow-badge: #F6E05E;
        --shadow-sm: 0 1px 2px rgba(0,0,0,0.20), 0 0 4px rgba(0,0,0,0.14);
        --shadow-md: 0 1px 2px rgba(0,0,0,0.24), 0 2px 4px rgba(0,0,0,0.18), 0 0 8px rgba(0,0,0,0.16);
        --shadow-lg: 0 2px 4px rgba(0,0,0,0.28), 0 4px 8px rgba(0,0,0,0.20), 0 0 16px rgba(0,0,0,0.16);
        --shadow-card: 0 1px 2px rgba(0,0,0,0.25), 0 0 8px rgba(0,0,0,0.16), 0 0 0 1px rgba(255,255,255,0.05);
    --shadow-hairline: 0 1px 2px rgba(0,0,0,0.25), 0 0 8px rgba(0,0,0,0.16), 0 0 0 1px rgba(255,255,255,0.05);
    --shadow-float: 0 2px 6px rgba(0,0,0,0.45), 0 12px 28px -8px rgba(0,0,0,0.75);
    /* Dark already separates by colour (#242A33 on #111418), so this only has to
       seat the trough rather than outline it. */
    --shadow-raised: 0 1px 2px rgba(0,0,0,0.35), 0 3px 10px -2px rgba(0,0,0,0.45), 0 8px 20px -8px rgba(0,0,0,0.55);
    --blue-pale-top: #27405C;
    --blue-pale-bottom: #172433;
    --lit-overlay-top: color-mix(in srgb, currentColor 14%, transparent);
    --lit-overlay-bottom: rgba(0,0,0,0.12);
        --header-grad-start: #0A0F18;
        --header-grad-mid: #122244;
        --header-grad-end: #1A3358;
        --header-avatar-border: #1A1E24;
        --btn-active-bg: #2D4A6F;
        --toast-bg: #2D3748;

        --btn-primary-start: #1E3A5F;
        --btn-primary-end: #2D5283;
        --btn-primary-shadow: rgba(50,90,140,0.35);
        --btn-success-start: #16803D;
        --btn-success-end: #1FA653;
        --btn-success-shadow: rgba(34,180,90,0.40);
        --btn-danger-start: #B83A3A;
        --btn-danger-end: #D04545;
        --btn-danger-shadow: rgba(208,69,69,0.40);

        /* Keep in lock-step with the [data-theme="dark"] block above. */
        --btn-sheen: rgba(255,255,255,0.10);
    /* Same curve, alphas scaled by the dark/light --btn-sheen ratio (0.10/0.22). */
    --sheen-layer: linear-gradient(180deg,
        rgba(255,255,255,0.090) 0%,
        rgba(255,255,255,0.052) 16%,
        rgba(255,255,255,0.025) 34%,
        rgba(255,255,255,0.009) 56%,
        rgba(255,255,255,0.002) 78%,
        rgba(255,255,255,0) 100%);
        --btn-contact: rgba(0,0,0,0.35);

        --tab-active-bg: #2D4A6F;
        --tab-active-shadow: rgba(45,74,111,0.35);

        --header-tabs-fill: linear-gradient(180deg, #2A313B 0%, #1E2732 100%);
        --header-tabs-ink: #A9C4E4;
        --ctx-tile-fill: linear-gradient(180deg, #2E3641 0%, #232A33 100%);

        color-scheme: dark;
    }
}

/* ══════════════════════════════════════════════════════════════════════════════
   ICONS  (Icon.razor + IconDefs.razor)

   The two gradients an icon's sheen and shade layers point at, and the two
   shadows that sit under it. Only the light/dark half of the decision lives
   here. WHETHER an icon is raised at all is a UI-theme question and sits in
   ui-theme.css next to every other component's look, so classic can keep the
   flat icon set without this file knowing about it.

   Dark mode is not an inversion. A raised object on a dark surface catches MORE
   light on its lit side, not less, so the sheen stays strong and it is the
   shade and the contact shadow that deepen. Inverting the pair instead makes
   the icon look pressed into the page rather than sitting on it.

   These are gradient stops, never a 1px inset: <html> runs zoom: 1.1 and a
   feature with a pixel size smears across two rows. See the --btn-sheen note
   further up this file, which records the same failure.
   ══════════════════════════════════════════════════════════════════════════════ */
:root {
    --icon-sheen-src: url(#icSheen);
    --icon-shade-src: url(#icShade);
    --icon-contact-src: rgba(13,33,55,0.20);
    --icon-contact-soft-src: rgba(13,33,55,0.13);
}

[data-theme="dark"] {
    --icon-sheen-src: url(#icSheenDark);
    --icon-shade-src: url(#icShadeDark);
    --icon-contact-src: rgba(0,0,0,0.55);
    --icon-contact-soft-src: rgba(0,0,0,0.40);
}

@media (prefers-color-scheme: dark) {
    [data-theme="system"] {
        --icon-sheen-src: url(#icSheenDark);
        --icon-shade-src: url(#icShadeDark);
        --icon-contact-src: rgba(0,0,0,0.55);
        --icon-contact-soft-src: rgba(0,0,0,0.40);
    }
}

/* ══════════════════════════════════════════════════════════════════════════════
   BOTTOM NAV BACKDROP  (capsule only; classic sets --nav-backdrop to none)

   The brightness() term is the whole reason this works, and it is what the first
   glass experiment was missing. A translucent nav composites the blurred content
   behind it into its own surface, which drags the surface toward whatever passed
   under and drops the contrast of the 10.5px nav labels. brightness() pushes that
   backdrop back toward the nav's own end of the scale BEFORE it composites, so
   the surface stays put and the labels keep their contrast.

   Light lifts (1.3), dark sinks (0.7). Not an inversion for its own sake: each
   theme pushes the backdrop toward its own surface colour.

   Measured on /lowongan at 390px, worst label contrast across four scroll
   positions, sampling real rendered pixels either side of each label:

       fill    backdrop                              light   dark
       100%    none  (the old opaque nav)             4.79    5.36
        78%    blur+saturate, no brightness           4.32    ----   FAILED 4.5
        84%    blur+saturate, no brightness           4.46    ----   FAILED 4.5
        76%    blur+saturate+brightness (this)        4.75    5.30

   So the glass now costs 0.04 of contrast in light and 0.06 in dark against a
   fully opaque bar, while being genuinely see-through. Without brightness() it
   cost 0.47 and broke the 4.5 floor, which is the legibility failure that got
   the first attempt reverted.

   If either number ever drops below 4.5 again, raise the fill percentage in
   ui-theme.css before touching the filter; the curve above is close to linear.
   ══════════════════════════════════════════════════════════════════════════════ */
:root {
    --nav-backdrop-src: blur(24px) saturate(1.5) brightness(1.3);
}

[data-theme="dark"] {
    --nav-backdrop-src: blur(24px) saturate(1.4) brightness(0.7);
}

@media (prefers-color-scheme: dark) {
    [data-theme="system"] {
        --nav-backdrop-src: blur(24px) saturate(1.4) brightness(0.7);
    }
}

/* ══════════════════════════════════════════════════════════════════════════════
   BOTTOM NAV STATE PILL  (capsule only; classic paints its own on the bar)

   The selection and hover pill sits BEHIND the nav's glass, so this colour is not
   what anyone sees. It is blurred, saturated, brightened and then covered by 76
   percent of the surface fill before it reaches the eye, which is why the alpha
   here looks far too strong written down.

   Light and dark need different alphas because the backdrop filter pulls in
   opposite directions: light brightens the pill by 1.3 and washes it out, dark
   darkens it by 0.7 and swallows it. Each value is the deepest its side can carry
   with the nav label still clearing 4.5:1 on top of it. Method and the full curve
   are in ui-theme.css beside --nav-hover-bg.
   ══════════════════════════════════════════════════════════════════════════════ */
:root {
    --nav-state-bg-src: rgba(var(--blue-primary-rgb), 0.70);
}

[data-theme="dark"] {
    --nav-state-bg-src: rgba(var(--blue-primary-rgb), 0.70);
}

@media (prefers-color-scheme: dark) {
    [data-theme="system"] {
        --nav-state-bg-src: rgba(var(--blue-primary-rgb), 0.70);
    }
}
