/* ═══════════════════════════════════════════════════════════════════
   Liquid Glass — core component library         v2 2026-08-10
   ═══════════════════════════════════════════════════════════════════
   THE DEFAULT LOOK. One place for the reusable glass components so any
   page can pick them up with a class — no per-page CSS.

   How the system layers (all already live):
     1. Hero background  — objects/background/heroes/settings.json
        ("sitewide": true → PageWrap::pagewrapnavbarbs sets --hero-bg-url
        on every wrapped page, rotating hourly).
     2. site-background.css — frosts #pw-content and EVERY .card inside
        it automatically; tunable via --glass-* vars; per-page opt-out
        via webqueryini.glassstyle or $GLOBALS['_glassstyle']
        ('none' = transparent container + frosted cards).
     3. THIS FILE — the component classes: headers, chips, pills,
        buttons, tiles, dashboard cards. Loaded site-wide by PageWrap
        beside site-background.css.

   ───────────────────────────────────────────────────────────────────
   v2 — WHY THE MATERIAL CHANGED (read before thinning it again)

   v1 painted a 10–30% white veil and set color:var(--bs-body-color)
   (near-black). Nothing bounded what sat behind it, so readability was
   whatever the hourly hero photo happened to be. Measured across the
   16-image hero pool, the darkest sample of the band where .glass-header
   sits ran from luminance 0.000 to 0.405 — and body text on it scored
   between 1.12:1 and 7.38:1. ELEVEN OF SIXTEEN HEROES PUT IT BELOW THE
   4.5:1 AA floor; the worst was 1.12:1, which is text you cannot see.
   Dark mode escaped only because --hero-bg-dark paints an 0.82 scrim
   under the photo. Light mode never got one. Oak, 2026-08-10: "the top
   glass divs are not readable, the text is not clear."

   The fix has two halves and BOTH are load-bearing:

     1. --glass-backdrop CLAMPS the backdrop. contrast() below 100% pulls
        the photo toward mid-grey and brightness() lifts (light) or drops
        (dark) it, so an arbitrary hero can no longer drag the surface to
        black or blow it to white. This is what makes a FIXED ink colour
        safe on a surface whose background is a photograph nobody chose.
     2. --glass-alpha-* is the veil on top. Text-bearing surfaces get a
        floor; pure decoration may stay thin.

   With both, the same worst-case hero measures 7.06:1 and all 16 pass.

   Tune the alphas to taste. Do NOT delete the contrast()/brightness()
   clamp and do NOT drop a text-bearing surface below --glass-alpha-medium
   — that is precisely the v1 bug. The rest of this codebase already
   reached the same conclusion by hand: site-background.css pins tables at
   0.82/0.92 and the mobile container at 0.94 for exactly this reason. The
   component classes here were the ones left thin.

   Skill doc: db/seeds/skill_docs/liquid-glass-contrast-floor.md
   ─────────────────────────────────────────────────────────────────── */

:root {
    /* The clamp + blur applied to whatever is BEHIND a glass surface. */
    --glass-backdrop: blur(18px) saturate(135%) contrast(62%) brightness(116%);
    /* Veil colour, as bare channels so components can pick their own alpha. */
    --glass-tint: 255, 255, 255;

    --glass-alpha-thick:  0.66;   /* headers, toolbars — body text sits here  */
    --glass-alpha-medium: 0.56;   /* tiles, pills, chips — short labels       */

    --glass-edge:       rgba(255, 255, 255, 0.55);
    --glass-edge-inner: rgba(255, 255, 255, 0.45);
    --glass-sheen:      rgba(255, 255, 255, 0.32);
    --glass-drop:       0 4px 24px rgba(0, 0, 0, 0.12);
    /* Backing under an outline button so its border+ink stop competing with
       the photo. See the button section at the bottom. */
    --glass-btn-backing: rgba(255, 255, 255, 0.58);
    /* Tab bar (.glass-tabs): the selected tab is a brighter LENS on the strip. */
    --glass-tab-lens:  rgba(255, 255, 255, 0.92);
    --glass-tab-hover: rgba(255, 255, 255, 0.42);
    --glass-tab-ink:   var(--bs-primary-text-emphasis);
}

[data-bs-theme="dark"] {
    --glass-backdrop: blur(18px) saturate(135%) contrast(70%) brightness(62%);
    --glass-tint: 26, 30, 35;

    --glass-alpha-thick:  0.64;
    --glass-alpha-medium: 0.56;

    --glass-edge:       rgba(255, 255, 255, 0.14);
    --glass-edge-inner: rgba(255, 255, 255, 0.10);
    --glass-sheen:      rgba(255, 255, 255, 0.10);
    --glass-drop:       0 4px 24px rgba(0, 0, 0, 0.38);
    /* DARK backing, not a white one. Lightening a button in dark mode pushes
       it toward the light emphasis ink sitting on it: measured on the
       brightest hero, a white 0.10 backing left btn-outline-danger at 4.41:1
       while a dark backing takes it to 6.29:1. */
    --glass-btn-backing: rgba(var(--glass-tint), 0.55);
    --glass-tab-lens:  rgba(255, 255, 255, 0.13);
    --glass-tab-hover: rgba(255, 255, 255, 0.06);
    /* NOT --bs-primary-text-emphasis (#6ea8fe): on the dark lens that measured
       4.14-4.41:1 across the hero pool, under AA on every hero. This is the
       same blue one tint lighter: 5.65:1 worst. */
    --glass-tab-ink:   #9ec5fe;
}

/* The sheen is a second BACKGROUND LAYER, not a ::before. A positioned
   pseudo-element paints above non-positioned children, so it washed the
   very text it was decorating; as a background layer it can only sit under
   content, and it needs no stacking-context surgery. */
.glass-header,
.glass-tabs,
.glass-tile,
.glass-pill,
.glass-chip {
    background-image:
        radial-gradient(120% 90% at 50% -25%, var(--glass-sheen), transparent 62%),
        linear-gradient(135deg,
            rgba(var(--glass-tint), calc(var(--glass-alpha-thick) + 0.06)),
            rgba(var(--glass-tint), var(--glass-alpha-thick)));
    backdrop-filter: var(--glass-backdrop);
    -webkit-backdrop-filter: var(--glass-backdrop);
}

/* ── Page header band — replaces bg-dark header slabs ─────────────── */
.glass-header {
    border: 1px solid var(--glass-edge);
    border-radius: var(--glass-radius, 12px);
    box-shadow: var(--glass-drop), inset 0 1px 0 var(--glass-edge-inner);
    color: var(--bs-body-color);
    padding: 1.25rem 1.5rem;
}
/* Muted text inside the band: take the colour token, but DROP the utility's
   own opacity. .opacity-75 on top of --bs-secondary-color (itself 75% alpha)
   double-mutes to ~56% ink — 3.9:1 on the new glass, still under AA. One
   level of muting is the design; two was an accident. */
.glass-header .text-light,
.glass-header .opacity-75,
.glass-header .opacity-50 {
    color: var(--bs-secondary-color) !important;
    opacity: 1 !important;
}

/* ── Status chip — one-line pill with live info (e.g. MCP connected) ─ */
.glass-chip {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.35rem 0.9rem;
    border-radius: 999px;
    font-size: 0.85rem;
    color: var(--bs-body-color);
    background-image:
        radial-gradient(120% 90% at 50% -25%, var(--glass-sheen), transparent 62%),
        linear-gradient(135deg,
            rgba(var(--glass-tint), calc(var(--glass-alpha-medium) + 0.06)),
            rgba(var(--glass-tint), var(--glass-alpha-medium)));
    border: 1px solid var(--glass-edge);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.10), inset 0 1px 0 var(--glass-edge-inner);
}

/* ── Pill link/button (role pills: Owner / Manager / Admin) ────────── */
.glass-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 1rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: none;
    color: var(--bs-body-color);
    background-image:
        radial-gradient(120% 90% at 50% -25%, var(--glass-sheen), transparent 62%),
        linear-gradient(135deg,
            rgba(var(--glass-tint), calc(var(--glass-alpha-medium) + 0.06)),
            rgba(var(--glass-tint), var(--glass-alpha-medium)));
    border: 1px solid var(--glass-edge);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.10), inset 0 1px 0 var(--glass-edge-inner);
    transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
.glass-pill:hover {
    color: var(--bs-body-color);
    border-color: rgba(128, 128, 128, 0.5);
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.16), inset 0 1px 0 var(--glass-edge-inner);
}

/* ── Stat tile — small number-over-label blocks ────────────────────── */
.glass-tile {
    background-image:
        radial-gradient(120% 90% at 50% -25%, var(--glass-sheen), transparent 62%),
        linear-gradient(135deg,
            rgba(var(--glass-tint), calc(var(--glass-alpha-medium) + 0.06)),
            rgba(var(--glass-tint), var(--glass-alpha-medium)));
    border: 1px solid var(--glass-edge);
    border-radius: 10px;
    box-shadow: inset 0 1px 0 var(--glass-edge-inner);
    color: var(--bs-body-color);
    padding: 0.5rem;
    text-align: center;
}

/* ── Explicit glass card (for use OUTSIDE #pw-content, iframes, etc.;
      inside #pw-content plain .card already frosts automatically) ──── */
/* Card opacity is deliberately UNCHANGED from v1 (0.72 light / 0.42 dark).
   Measured, cards already cleared AA on every hero — 7.77:1 light, 10.96:1
   dark. Only the surfaces that failed were thickened; a card that reads fine
   stays as see-through as it was. */
.glass-card {
    background: rgba(255, 255, 255, var(--glass-card-opacity, 0.72)) !important;
    backdrop-filter: var(--glass-backdrop);
    -webkit-backdrop-filter: var(--glass-backdrop);
    border: 1px solid var(--glass-edge);
    border-radius: 10px;
    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.08), inset 0 1px 0 var(--glass-edge-inner);
}
[data-bs-theme="dark"] .glass-card {
    background: rgba(52, 58, 64, var(--glass-card-opacity, 0.42)) !important;
}

/* ── Dashboard card — icon + title + description grid tiles.
      Color identity via a top accent bar (--accent), not solid borders.
      Frost comes from #pw-content .card; this adds accent + hover lift. */
.glass-dash-card {
    --accent: var(--bs-primary);
    position: relative;
    overflow: hidden;
    border: 1px solid var(--glass-edge);
    transition: transform .2s ease, box-shadow .2s ease;
}
.glass-dash-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    background: linear-gradient(90deg, var(--accent), transparent 85%);
    opacity: 0.85;
}
.glass-dash-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.16), inset 0 1px 0 var(--glass-edge-inner);
}
.glass-dash-card .card-title { color: var(--bs-body-color); }

/* ── Tab bar — tabs as segments on one glass strip ─────────────────
   <ul class="nav glass-tabs" role="tablist"> holding Bootstrap's own
   .nav-link / data-bs-toggle="tab" buttons. Keep the .nav class: it is how
   Bootstrap's tab JS finds the group.

   Use it in place of .nav-tabs anywhere the tabs sit on the hero rather
   than inside a card. .nav-tabs draws a border meant for an OPAQUE page, so
   on the glass container every tab is a label floating on that hour's
   photo. The civil case view (crt,civilcomplaint,view; Oak, 2026-09-19:
   "the tabs are not visible under all circumstances") measured 2.32:1
   at worst. Across the 16-hero pool in light mode, 58 of its 208 tab
   labels fell under AA, and its selected tab's blue failed on every hero
   in dark mode. On this strip: 8.57:1 worst light, 5.65:1 worst dark,
   none under AA.

   The strip carries text, so it takes the thick veil and the clamp (the
   shared material group at the top of this file). Tabs WRAP to another
   row instead of scrolling sideways, so no tab is ever off-screen. */
.glass-tabs {
    gap: 0.25rem;
    padding: 0.3rem;
    margin-bottom: 0.75rem;
    border: 1px solid var(--glass-edge);
    border-radius: var(--glass-radius, 12px);
    box-shadow: var(--glass-drop), inset 0 1px 0 var(--glass-edge-inner);
}
.glass-tabs .nav-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.45rem 0.85rem;
    border: 1px solid transparent;
    border-radius: calc(var(--glass-radius, 12px) - 4px);
    background: transparent;
    color: var(--bs-body-color);
    font-size: 0.9rem;
    font-weight: 500;
    line-height: 1.25;
    white-space: nowrap;
}
.glass-tabs .nav-link:hover {
    background: var(--glass-tab-hover);
    color: var(--bs-emphasis-color);
}
/* An outline, not Bootstrap's box-shadow ring: the selected tab's lens owns
   box-shadow, and a ring painted there would vanish on the one tab a
   keyboard user most needs to see. Declared BEFORE .active so the lens
   keeps its shadow while focused. */
.glass-tabs .nav-link:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 1px;
    box-shadow: none;
}
.glass-tabs .nav-link.active {
    background: var(--glass-tab-lens);
    border-color: var(--glass-edge);
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.12), inset 0 1px 0 var(--glass-edge-inner);
    color: var(--glass-tab-ink);
    font-weight: 600;
}

/* ═══════════════════════════════════════════════════════════════════
   OUTLINE BUTTONS ON GLASS
   ═══════════════════════════════════════════════════════════════════
   Bootstrap's outline buttons are transparent fill + mid-tone ink
   (btn-outline-secondary #6c757d, btn-outline-info #0dcaf0). That ink is
   chosen to sit on an OPAQUE white page. On a translucent surface over a
   photo it disappears: measured on the worst hero, #6c757d scored 2.15:1
   and #0dcaf0 scored 1.12:1 — Oak, 2026-08-10, "outline buttons don't
   show up well." Adding backing alone is not enough (2.15 → 3.39:1, still
   under AA); the INK has to change too.

   So on any glass surface an outline button gets:
     - a translucent backing, so the border and label stop competing with
       the photo directly, and
     - Bootstrap 5.3's own --bs-*-text-emphasis token as its ink, which is
       the same hue darkened for exactly this purpose (8.3:1 measured).

   Hover/active are left to Bootstrap: the variant still fills with its
   solid colour and flips to the correct hover ink. Only the resting state
   is restyled, so nothing about the interaction changes.

   Scope covers #pw-content because a .card is translucent too — an
   outline button on a 0.80 card over a dark photo measures 2.77:1, so
   "it's inside a card, it's fine" was never true either. */

:where(.glass-header, .glass-card, .glass-tile, .glass-chip, #pw-content) [class*="btn-outline-"] {
    --bs-btn-bg: var(--glass-btn-backing);
    --bs-btn-border-color: currentColor;
    backdrop-filter: blur(6px) saturate(115%);
    -webkit-backdrop-filter: blur(6px) saturate(115%);
}

:where(.glass-header, .glass-card, .glass-tile, .glass-chip, #pw-content) .btn-outline-primary   { --bs-btn-color: var(--bs-primary-text-emphasis); }
:where(.glass-header, .glass-card, .glass-tile, .glass-chip, #pw-content) .btn-outline-secondary { --bs-btn-color: var(--bs-secondary-text-emphasis); }
:where(.glass-header, .glass-card, .glass-tile, .glass-chip, #pw-content) .btn-outline-success   { --bs-btn-color: var(--bs-success-text-emphasis); }
:where(.glass-header, .glass-card, .glass-tile, .glass-chip, #pw-content) .btn-outline-danger    { --bs-btn-color: var(--bs-danger-text-emphasis); }
:where(.glass-header, .glass-card, .glass-tile, .glass-chip, #pw-content) .btn-outline-warning   { --bs-btn-color: var(--bs-warning-text-emphasis); }
:where(.glass-header, .glass-card, .glass-tile, .glass-chip, #pw-content) .btn-outline-info      { --bs-btn-color: var(--bs-info-text-emphasis); }
:where(.glass-header, .glass-card, .glass-tile, .glass-chip, #pw-content) .btn-outline-dark      { --bs-btn-color: var(--bs-emphasis-color); }
:where(.glass-header, .glass-card, .glass-tile, .glass-chip, #pw-content) .btn-outline-light     { --bs-btn-color: var(--bs-body-color); }

/* A disabled outline button must still read as disabled, not just faint. */
:where(.glass-header, .glass-card, #pw-content) [class*="btn-outline-"]:disabled,
:where(.glass-header, .glass-card, #pw-content) [class*="btn-outline-"].disabled {
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: var(--bs-border-color);
}

/* Bare links dropped straight onto the header band (breadcrumbs, "back to…")
   inherit the same problem as outline ink. --bs-link-color is tuned for an
   opaque page; on glass take the emphasis tone. */
.glass-header a:not(.btn):not(.badge):not(.glass-pill) {
    color: var(--bs-link-color);
    text-underline-offset: 0.2em;
}
[data-bs-theme="light"] .glass-header a:not(.btn):not(.badge):not(.glass-pill),
:root:not([data-bs-theme="dark"]) .glass-header a:not(.btn):not(.badge):not(.glass-pill) {
    color: var(--bs-primary-text-emphasis);
}

/* ── Reduced transparency / reduced motion ──
   Users who ask the OS for less transparency get a solid surface. The look
   degrades to "flat card", which is the correct degradation — the content
   is the point, the frost is not. */
@media (prefers-reduced-transparency: reduce) {
    :root { --glass-alpha-thick: 0.97; --glass-alpha-medium: 0.95; --glass-backdrop: none; }
    [data-bs-theme="dark"] { --glass-alpha-thick: 0.97; --glass-alpha-medium: 0.95; }
}
@media (prefers-reduced-motion: reduce) {
    .glass-pill, .glass-dash-card, .glass-tabs .nav-link { transition: none; }
    .glass-pill:hover, .glass-dash-card:hover { transform: none; }
}
