/* ── Site-wide hero background with frosted-glass container ──  v=20260310e
   CSS vars --hero-bg-url / --hero-bg-dark injected by PageWrap.
   Container IDs: #pw-outer (buildGenericPage), #pw-content (pagewrapnavbarbs + wrapInContainer)
   IMPORTANT: #pw-outer contains the fixed navbar — it must NOT have
   backdrop-filter or it breaks position:fixed. Frost goes on #pw-content.
   Per-page tuning:
     1) webqueryini.glassstyle column: 'none' | 'light' | '' (default)
     2) $GLOBALS['_glassstyle'] = 'none'; in a page function
     3) Override --glass-opacity / --glass-blur / --glass-border-opacity /
        --glass-card-opacity in a <style> block to adjust or disable the frosted effect.
   ───────────────────────────────────────────────────────────────── */

/* ── Hero background as a FIXED COMPOSITING LAYER (all viewports) ──
   The photo used to sit on <body> with background-attachment:fixed. That is
   Chrome's documented scroll-repaint trigger: every scroll frame repaints the
   fixed background under each frosted (backdrop-filter) element, which is the
   choppy scrolling reported (#1066, Jonathan Annett). Fix: the photo lives on a
   real position:fixed <div id="hero-bg-mobile"> (injected by PageWrap/ModernLook
   at every width now, not just ≤991px) promoted to its OWN GPU layer — so
   scrolling composites over a static texture instead of repainting. The desktop
   frosted #pw-content/.card still frost the photo (verified: backdrop-filter
   blurs a fixed sibling div identically to a fixed body background). Mobile keeps
   its opaque container (iOS WebKit + readability), unchanged.
   The body itself no longer carries the image. */
body,
[data-bs-theme="dark"] body {
    background-color: transparent !important;
    background-image: none !important;
}

/* The fixed hero layer — same element the mobile branch already used, now global.
   Injected as <div id="hero-bg-mobile"> and prepended to <body>.
   z-index:-1 (#1068 hardening): the layer paints BEHIND ALL content — so it can
   never cover a panel that a page happens to render OUTSIDE #pw-content (which is
   the failure mode a z-index:0 hero would introduce site-wide, and what made the
   old mobile code lift #pw-content to z-index:1). At -1 no content needs lifting
   and nothing can be hidden, on any viewport. Frost still works: backdrop-filter
   blurs whatever is painted behind, including a z-index:-1 fixed div (verified by
   render). The pre-#1068 mobile comment worried z-index:-1 would sink below a
   "canvas background" — no such element exists in this codebase (grep-confirmed),
   and a map/WebGL <canvas> page manages its own stack, so -1 is safe there too. */
#hero-bg-mobile {
    display: block;
    position: fixed;
    inset: 0;
    z-index: -1;
    background: var(--hero-bg-url) center / cover no-repeat;
    pointer-events: none;
    /* Own static compositing layer → cheap scroll compositing (#1066). */
    transform: translateZ(0);
}
[data-bs-theme="dark"] #hero-bg-mobile {
    background-image: var(--hero-bg-dark);
}

/* Outer wrapper: transparent — navbar lives here, must not interfere */
#pw-outer {
    background: transparent !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
}

/* Also clear any stray .container background from Bootstrap or other sheets */
#pw-outer.container,
#pw-outer.container-fluid {
    background: transparent !important;
}

/* ── Tunable glass variables ──
   Pages can override these to control the frosted-glass effect:
     --glass-opacity   : container background alpha  (default 0.50 light / 0.18 dark)
     --glass-blur      : backdrop blur amount        (default 12px)
     --glass-border-opacity : border alpha           (default 0.35 light / 0.08 dark)
     --glass-card-opacity   : card background alpha  (default 0.72 light / 0.42 dark)
   Set all to 0 for fully transparent containers.

   LIGHT --glass-opacity WAS 0.28 (raised 2026-08-10). Text sitting directly
   on the container — a breadcrumb, an <h1>, anything not wrapped in a .card —
   scored 1.69:1 against the darkest hero in the pool, i.e. invisible. 0.50
   measures 5.58:1 on that same hero. Cards were never the problem (7.77:1 at
   0.72) and are unchanged, and dark mode was never the problem either
   (--hero-bg-dark already lays an 0.82 scrim under the photo), so only the
   light container moved. If you lower this again, re-measure — do not assume.
   Details: db/seeds/skill_docs/liquid-glass-contrast-floor.md */
:root {
    --glass-opacity: 0.50;
    --glass-blur: 12px;
    --glass-border-opacity: 0.35;
    --glass-card-opacity: 0.72;
    --glass-shadow-opacity: 0.08;
    --glass-radius: 12px;
}
[data-bs-theme="dark"] {
    --glass-opacity: 0.18;
    --glass-border-opacity: 0.08;
    --glass-card-opacity: 0.42;
    --glass-shadow-opacity: 0.25;
}

/* ── Frosted-glass on inner content container ──
   The backdrop-filter CLAMPS the photo behind it (contrast below 100% pulls it
   toward mid-grey, brightness lifts it) so a fixed ink colour is safe over any
   hero. The literal is a fallback for pages that load this sheet without
   liquid-glass.css (e.g. login) — when both load, liquid-glass.css owns the
   token and this inherits it. */
#pw-content {
    background: rgba(255, 255, 255, var(--glass-opacity)) !important;
    backdrop-filter: var(--glass-backdrop, blur(12px) saturate(135%) contrast(62%) brightness(116%));
    -webkit-backdrop-filter: var(--glass-backdrop, blur(12px) saturate(135%) contrast(62%) brightness(116%));
    border-radius: var(--glass-radius);
    margin-top: 0.75rem;
    margin-bottom: 2rem;
    padding: 1rem 1.5rem 1.5rem;
    box-shadow: 0 2px 24px rgba(0, 0, 0, var(--glass-shadow-opacity));
    border: 1px solid rgba(255, 255, 255, var(--glass-border-opacity));
}
[data-bs-theme="dark"] #pw-content {
    background: rgba(33, 37, 41, var(--glass-opacity)) !important;
    border-color: rgba(255, 255, 255, var(--glass-border-opacity));
    box-shadow: 0 2px 24px rgba(0, 0, 0, var(--glass-shadow-opacity));
}

/* ── Cards: frosted glass ──
   Cards get their own backdrop-filter so they frost individually against
   the background — works whether the container is frosted or transparent.
   Nested cards (.card .card) and modal cards are excluded. */
#pw-content .card {
    background: rgba(255, 255, 255, var(--glass-card-opacity)) !important;
    backdrop-filter: var(--glass-backdrop, blur(12px) saturate(135%) contrast(62%) brightness(116%));
    -webkit-backdrop-filter: var(--glass-backdrop, blur(12px) saturate(135%) contrast(62%) brightness(116%));
    border: 1px solid rgba(255, 255, 255, 0.35);
    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.06),
                inset 0 1px 0 rgba(255, 255, 255, 0.25);
    border-radius: 10px;
}
[data-bs-theme="dark"] #pw-content .card {
    background: rgba(52, 58, 64, var(--glass-card-opacity)) !important;
    border-color: rgba(255, 255, 255, 0.08);
    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.2),
                inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

/* Card headers: slightly more opaque for visual separation.
   Exclude headers with explicit bg colors (inline or Bootstrap utilities) via :not() */
#pw-content .card > .card-header:not([style*="background-color"]):not(.bg-primary):not(.bg-secondary):not(.bg-success):not(.bg-danger):not(.bg-info):not(.bg-warning) {
    background: rgba(255, 255, 255, 0.25) !important;
    border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
[data-bs-theme="dark"] #pw-content .card > .card-header:not([style*="background-color"]):not(.bg-primary):not(.bg-secondary):not(.bg-success):not(.bg-danger):not(.bg-info):not(.bg-warning) {
    background: rgba(255, 255, 255, 0.06) !important;
    border-bottom-color: rgba(255, 255, 255, 0.06);
}
/* Card headers with explicit background colors: disable frost so solid color shows */
#pw-content .card > .card-header[style*="background-color"],
#pw-content .card > .card-header.bg-primary,
#pw-content .card > .card-header.bg-secondary,
#pw-content .card > .card-header.bg-success,
#pw-content .card > .card-header.bg-danger,
#pw-content .card > .card-header.bg-info,
#pw-content .card > .card-header.bg-warning {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
}

/* Dropdowns inside frosted cards: backdrop-filter creates a stacking context
   on each card, so a dropdown in one card can't paint above a sibling card.
   Elevate the card when its dropdown is open. Also covers popovers & tooltips. */
#pw-content .card:has(.dropdown-menu.show),
#pw-content .card:has(.popover),
#pw-content .card:has([aria-expanded="true"]) {
    z-index: 10;
    position: relative;
}

/* Nested cards: no double-frost */
#pw-content .card .card {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
    border-color: rgba(255, 255, 255, 0.15);
}
[data-bs-theme="dark"] #pw-content .card .card {
    border-color: rgba(255, 255, 255, 0.05);
}

/* Tables: opaque for readability over frosted glass */
#pw-content .table {
    --bs-table-bg: rgba(255, 255, 255, 0.82);
}
#pw-content .table thead th {
    background: rgba(255, 255, 255, 0.92);
    border-bottom-color: rgba(0, 0, 0, 0.15);
}
#pw-content .table tbody tr:hover {
    --bs-table-hover-bg: rgba(255, 255, 255, 0.95);
}
#pw-content .table-striped > tbody > tr:nth-of-type(odd) > * {
    --bs-table-striped-bg: rgba(245, 245, 245, 0.85);
}
[data-bs-theme="dark"] #pw-content .table {
    --bs-table-bg: rgba(33, 37, 41, 0.82);
}
[data-bs-theme="dark"] #pw-content .table thead th {
    background: rgba(52, 58, 64, 0.92);
    border-bottom-color: rgba(255, 255, 255, 0.1);
}
[data-bs-theme="dark"] #pw-content .table tbody tr:hover {
    --bs-table-hover-bg: rgba(52, 58, 64, 0.95);
}
[data-bs-theme="dark"] #pw-content .table-striped > tbody > tr:nth-of-type(odd) > * {
    --bs-table-striped-bg: rgba(40, 44, 48, 0.85);
}

/* ── Dark theme + a contextual table row = a LIGHT ISLAND ──
   Bootstrap's .table-warning/.table-secondary/... set a FIXED light background
   in both themes (that is how the variants are defined — they are not
   theme-aware). Everything painted on them, though, IS theme-aware: in dark
   mode .text-body-secondary resolves to a light grey and .btn-outline-* to a
   light ink, so a muted cell or a button on an "overdue" row goes
   light-on-light and disappears. Seen on wo,workorders: the city under an
   address and the "direct" mode cell vanished on every overdue row.

   Inside such a row, force the LIGHT-theme inks back. Scoped to tbody rows so
   it cannot touch a themed surface elsewhere. */
[data-bs-theme="dark"] .table > :not(caption) > tr:is(.table-primary, .table-secondary, .table-success, .table-info, .table-warning, .table-danger, .table-light) {
    --bs-table-color: #212529;
}
[data-bs-theme="dark"] .table > :not(caption) > tr:is(.table-primary, .table-secondary, .table-success, .table-info, .table-warning, .table-danger, .table-light) :is(.text-body-secondary, .text-muted, small, em) {
    color: rgba(33, 37, 41, 0.72) !important;
}
[data-bs-theme="dark"] .table > :not(caption) > tr:is(.table-primary, .table-secondary, .table-success, .table-info, .table-warning, .table-danger, .table-light) a:not(.btn):not(.badge) {
    color: #0a58ca;
}
/* Outline buttons on a light island take the LIGHT emphasis inks + a white
   backing, not the dark-theme ones the glass rule would otherwise hand them. */
[data-bs-theme="dark"] .table > :not(caption) > tr:is(.table-primary, .table-secondary, .table-success, .table-info, .table-warning, .table-danger, .table-light) [class*="btn-outline-"] {
    --bs-btn-bg: rgba(255, 255, 255, 0.72);
    --bs-btn-color: #0a3070;
    --bs-btn-border-color: currentColor;
    --bs-btn-hover-color: #fff;
}

/* DataTables controls: opaque backgrounds */
#pw-content .dataTables_wrapper .dataTables_filter input,
#pw-content .dataTables_wrapper .dataTables_length select {
    background-color: rgba(255, 255, 255, 0.88);
}
[data-bs-theme="dark"] #pw-content .dataTables_wrapper .dataTables_filter input,
[data-bs-theme="dark"] #pw-content .dataTables_wrapper .dataTables_length select {
    background-color: rgba(33, 37, 41, 0.88);
}

/* ── iOS WebKit: scroll panels inside a backdrop-filter ancestor ──
   Safari/WebKit (all iOS browsers) blanks the contents of an
   overflow:scroll/auto element when an ancestor (#pw-content or a .card)
   uses backdrop-filter — the panel renders empty/invisible while the rest
   of the page is fine. Blink (Chrome) is unaffected, which is why it only
   shows on iPhone. Fix: promote such panels to their own compositing layer
   with translateZ so they paint independently of the frosted ancestor.
   Targets the shared post-it panels (id^="postitnotes") and any element
   carrying an inline overflow style (the pattern that legacy renderers use).
   translateZ(0) is a no-op layer hint everywhere else. */
#pw-content [id^="postitnotes"],
#pw-content [style*="overflow:auto"],
#pw-content [style*="overflow: auto"],
#pw-content [style*="overflow:scroll"],
#pw-content [style*="overflow: scroll"] {
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
}

/* ── .gpu-layer utility ──
   Opt-in fix for the iOS/WebKit partial-paint bug: WebKit can leave an element
   in the DOM (solid, opacity 1, hit-testable) but UNPAINTED when a nearby
   element repaints — e.g. a PDF <object>/<video>/<canvas>/backdrop-filter
   sibling. Add class="gpu-layer" to a region whose buttons/content blank out
   on iPhone to force it onto its own compositing layer so it paints
   independently. (This is what DocActionLayout does for .dal-header/.dal-form.)
   translateZ(0) is a no-op everywhere it isn't needed. Do NOT slap it on huge
   containers or ones with position:fixed children — transform makes the element
   the containing block for fixed descendants and adds a stacking context. */
.gpu-layer {
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
}

/* ── Full-screen homepage overrides ──
   The alt-homepage and homepage-split are full-screen launchers that
   manage their own background. Disable frosted-glass on those pages. */
#pw-content:has(.alt-homepage),
#pw-content:has(.homepage-split),
#pw-content:has(.login-card) {
    background: transparent !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    border-radius: 0;
    margin: 0;
    padding: 0;
    box-shadow: none;
    border: none;
}

/* Modals + dropdowns: stay fully opaque */
.modal-content {
    background: var(--bs-modal-bg) !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
}

/* ── Mobile container tuning ──
   The hero layer (#hero-bg-mobile) and the content z-index lift are now GLOBAL
   (defined near the top of this sheet) — the fixed-layer approach that used to
   be mobile-only is what desktop uses too since #1066. This branch only carries
   what still differs on small screens: an OPAQUE container (iOS WebKit blanks
   content inside an overflow:scroll descendant of a backdrop-filter ancestor,
   and near-opaque is more readable on a phone), no container blur, tighter
   spacing. Desktop keeps the see-through frosted glass above this breakpoint. */
@media (max-width: 991px) {
    #pw-content {
        background: rgba(255, 255, 255, 0.92) !important;
        /* No backdrop-filter on mobile: the container is 92% opaque so the
           blur is invisible anyway, and on iOS WebKit a backdrop-filter
           ancestor makes content inside a descendant overflow:scroll/auto
           panel (e.g. #postitnotes, max-height+overflow:auto) render blank.
           Dropping it here removes that trigger. See scroll-panel rule below. */
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        border-radius: 0;
        margin-top: 0;
        margin-bottom: 0;
        padding: 0.5rem 0.75rem 1rem;
        border-left: none;
        border-right: none;
    }
    [data-bs-theme="dark"] #pw-content {
        background: rgba(33, 37, 41, 0.92) !important;
    }
    /* Universal mobile readability floor. A per-page glassstyle:none override
       emits `#pw-content{background:transparent!important}` AFTER this sheet,
       which defeats the 0.92 rule above (equal specificity, later source wins)
       and leaves the mobile container see-through over the hero photo — so bare
       content (breadcrumbs, <h1>, links not wrapped in a .card) vanishes into
       the image, worst on iOS where the photo is a real fixed layer. Re-assert
       an opaque surface with a HIGHER-specificity selector (`html #pw-content`,
       two selectors) that beats the single-ID inline override regardless of
       source order — so no page can be transparent-over-photo on mobile.
       Full-screen launchers (login/homepage) keep transparency via their own
       higher-specificity :has() rules, so this is a no-op there. Desktop is
       untouched: the see-through glass look only applies above this breakpoint. */
    html #pw-content {
        background: rgba(255, 255, 255, 0.94) !important;
        -webkit-backdrop-filter: none !important;
        backdrop-filter: none !important;
    }
    html[data-bs-theme="dark"] #pw-content {
        background: rgba(33, 37, 41, 0.94) !important;
    }
    /* Tighter spacing on mobile */
    #pw-content .container,
    #pw-content .container-fluid {
        padding-left: 8px;
        padding-right: 8px;
    }
    #pw-content .card {
        border-radius: 8px;
        margin-bottom: 0.75rem;
        /* Choppy-scroll fix (#1066, Jonathan Annett — reported at a 509px
           viewport, which lands in this ≤991px branch). The container here is
           already ~94% opaque, so a card's backdrop-filter frosts against an
           opaque surface = NO visible effect — but it still forces the GPU to
           re-blur the fixed #hero-bg-mobile behind every card on each scroll
           frame, which is the jank. Dropping it is visually a no-op and
           restores smooth scrolling. (Desktop >991px keeps its frosted cards —
           over the FIXED HERO LAYER now; the old body background-attachment:fixed
           jank was removed in the same #1066 pass, see the top of this sheet.) */
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
    }
}

/* ── Print ── */
@media print {
    body { background: #fff !important; }
    #pw-content, #pw-content .card { background: transparent !important; backdrop-filter: none !important; }
}
