/* =========================================================================
 * bf-glass.css — DOM side of Blastforce Liquid Glass
 * -------------------------------------------------------------------------
 * Pairs with bf-glass.js. Two modes, and the page markup is identical in both:
 *
 *   html.bf-glass-gpu   the shader draws the pane, so the element itself must
 *                       carry NO background and NO border — anything painted
 *                       here would sit on top of the refraction and flatten it.
 *   html.bf-glass-css   no WebGPU (or lite / reduced transparency): a solid
 *                       fill with the same geometry. Not a supported target.
 *
 * Also carries .bf-ico — the small rounded-square icon tile, drawn with real
 * SVG glyphs. Same shape language as the iOS Settings rows.
 * ========================================================================= */

#bf-glass-canvas {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: -1;
    pointer-events: none;
    display: block;
}

/* ── the surface ──────────────────────────────────────────────────────────── */
.bf-glass {
    position: relative;
    isolation: isolate;
}

/* bf-glass-top is overlay-only mode: the page keeps its own background and its
   own CSS glass, and only the floating panes the renderer draws have to stop
   painting a fill of their own. */
html.bf-glass-gpu .bf-glass,
html.bf-glass-top .bf-glass {
    background: transparent !important;
    border-color: transparent !important;
    /* The shader owns the rim and the contact shading; a CSS shadow on top of it
       reads as a second, offset edge. */
    box-shadow: none !important;
}

/* A pane drawn BEHIND the page has its frost done in the shader, in the same
   pass, on the same backdrop. A pane drawn OVER the page cannot: no shader can
   sample the page it covers, so the element carries the frost itself and the
   shader draws only what CSS has no way to — the rim, the shade, the hairline
   and the tint held in them. bf-glass.js writes the filter inline from the
   surface's own blur/saturate/brightness, so both paths mean the same thing. */
html.bf-glass-gpu .bf-glass:not(.bf-glass-over),
html.bf-glass-top .bf-glass:not(.bf-glass-over) {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
}

/* Everything in the page body already sits on shader glass, so a second,
   per-element blur only costs a compositor pass and flattens the refraction
   under it. The lens (.bf-lens) and the overlay pass (.bf-glass-over) are the
   two places backdrop-filter IS the material, so they keep it. Overlay-only
   pages (html.bf-glass-top, e.g. the live match page) are untouched. */
html.bf-glass-gpu .main-content *:not(.bf-lens):not(.bf-glass-over),
html.bf-glass-gpu .main-content *::before,
html.bf-glass-gpu .main-content *::after {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
}

/* The page background must not paint over the canvas. */
html.bf-glass-gpu body { background: transparent; }
html.bf-glass-gpu .bg-grid,
html.bf-glass-gpu .ambient-blob,
html.bf-glass-gpu .aurora { display: none !important; }

/* No WebGPU is not a supported target: a plain solid fill, no blur. */
html.bf-glass-css .bf-glass {
    background: #16141c;
    border: 1px solid rgba(255, 255, 255, 0.07);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}

/* Content has to sit above the pane the canvas draws behind it. */
.bf-glass > * { position: relative; z-index: 1; }

/* ── the pointer sheen ─────────────────────────────────────────────────────
   A reflection on the FACE of a lensed pane that follows the pointer. Two
   parts, because a real pane shows both: a broad, very soft wash across the
   glass, and a bright point that runs along the RIM where the edge turns
   toward the light. The rim is the half you actually read as glass.

   The rim's own specular — the fixed overhead one the material pass bakes — is
   untouched and stays untouched. This sits on top of it and is deliberately
   about a quarter of its strength: a highlight that chases the cursor hard is
   the giveaway of an imitation, and the whole point is that it registers only
   once the pointer is already there.

   Driven by --bf-sx / --bf-sy (set per frame by bf-glass.js) and gated behind
   .bf-sheen-lit, which the same code puts on the surface under the pointer, so
   an untouched pane costs nothing at all. */
.bf-sheen {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 3;
    opacity: 0;
    transition: opacity 0.38s cubic-bezier(0.32, 0.72, 0, 1);
    background: radial-gradient(
        220px 220px at var(--bf-sx, 50%) var(--bf-sy, 0%),
        rgba(255, 255, 255, calc(var(--bf-sheen, 0.1) * 0.5)) 0%,
        rgba(255, 255, 255, 0) 70%);
}
.bf-sheen-lit > .bf-sheen { opacity: 1; }

/* The rim half: the same gradient, masked to a hairline ring so only the edge
   nearest the pointer lights up. mask-composite cuts the content box out of
   the padding box, which leaves exactly the border band. */
.bf-sheen::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 1.25px;
    background: radial-gradient(
        260px 260px at var(--bf-sx, 50%) var(--bf-sy, 0%),
        rgba(255, 255, 255, calc(var(--bf-sheen, 0.1) * 4.2)) 0%,
        rgba(255, 255, 255, 0) 62%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
}

@media (prefers-reduced-motion: reduce) {
    .bf-sheen { display: none; }
}

/* ── icon tiles ───────────────────────────────────────────────────────────── */
.bf-ico {
    width: 30px;
    height: 30px;
    border-radius: 9px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: #fff;
    position: relative;
    background: linear-gradient(180deg, var(--ico-a, #8b5cf6), var(--ico-b, #6d28d9));
    box-shadow:
        0 2px 7px rgba(0, 0, 0, 0.5),
        inset 0 1px 0 rgba(255, 255, 255, 0.28),
        inset 0 -1px 0 rgba(0, 0, 0, 0.22);
}
.bf-ico svg {
    width: 17px;
    height: 17px;
    display: block;
    stroke: currentColor;
    fill: none;
    stroke-width: 1.9;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.bf-ico--sm { width: 24px; height: 24px; border-radius: 7px; }
.bf-ico--sm svg { width: 14px; height: 14px; }
.bf-ico--lg { width: 38px; height: 38px; border-radius: 11px; }
.bf-ico--lg svg { width: 21px; height: 21px; }

/* Flat variant — no tile, just the glyph, for dense rows where 30px squares
   would turn the list into a colour chart. */
.bf-ico--bare {
    background: none;
    box-shadow: none;
    width: auto;
    height: auto;
    border-radius: 0;
}

/* Tile palette. Named after what they mean, not what colour they are, so a
   theme change never leaves `.bf-ico--blue` painting something green. */
.bf-ico--violet  { --ico-a: #a78bfa; --ico-b: #7c3aed; }
.bf-ico--magenta { --ico-a: #e879f9; --ico-b: #a21caf; }
.bf-ico--pink    { --ico-a: #fb7185; --ico-b: #be123c; }
.bf-ico--blue    { --ico-a: #60a5fa; --ico-b: #1d4ed8; }
.bf-ico--cyan    { --ico-a: #38bdf8; --ico-b: #0369a1; }
.bf-ico--green   { --ico-a: #4ade80; --ico-b: #15803d; }
.bf-ico--amber   { --ico-a: #fbbf24; --ico-b: #b45309; }
.bf-ico--red     { --ico-a: #fb7185; --ico-b: #b91c1c; }
.bf-ico--slate   { --ico-a: #94a3b8; --ico-b: #475569; }

/* ── motion ────────────────────────────────────────────────────────────────
   Liquid Glass moves on springs, and content does not slide in — it *emerges*
   through the surface: it scales up the last few percent, un-blurs, and fades,
   with each child a beat behind the one above. Sliding panels and linear fades
   are the two things that immediately read as "not Apple", so neither appears
   here.

   --bf-ease   the standard sheet/segment curve: fast out of the gate, long
               settle, no overshoot. Used for anything that changes size.
   --bf-spring a real damped spring with a small overshoot, for things that snap
               into a new position (the segmented thumb).
   ------------------------------------------------------------------------- */
:root {
    --bf-ease:   cubic-bezier(0.32, 0.72, 0, 1);
    --bf-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --bf-spring: linear(
        0, 0.0088 1.7%, 0.0353 3.5%, 0.1384 7.1%, 0.3021 10.9%, 0.5107 15.1%,
        0.7331 19.6%, 0.9302 24.1%, 1.0396 27.6%, 1.0821 30.4%, 1.0961 33.4%,
        1.0844 37.3%, 1.0288 45.5%, 1.0007 52.4%, 0.9959 60%, 1);
    --bf-dur: 520ms;
    --bf-dur-fast: 300ms;
}

@keyframes bf-emerge {
    from { opacity: 0; transform: translateY(10px) scale(0.972); filter: blur(7px); }
    to   { opacity: 1; transform: none;                          filter: blur(0); }
}

/* Applied by BFGlass.morph() to the container whose content just changed. */
.bf-emerge > * {
    animation: bf-emerge var(--bf-dur) var(--bf-ease) both;
}
/* The stagger is what makes a list read as one object arriving rather than
   several. Beyond the eighth row it stops growing — a long list should not take
   a second and a half to finish appearing. */
.bf-emerge > *:nth-child(1) { animation-delay: 0ms; }
.bf-emerge > *:nth-child(2) { animation-delay: 45ms; }
.bf-emerge > *:nth-child(3) { animation-delay: 90ms; }
.bf-emerge > *:nth-child(4) { animation-delay: 130ms; }
.bf-emerge > *:nth-child(5) { animation-delay: 165ms; }
.bf-emerge > *:nth-child(6) { animation-delay: 195ms; }
.bf-emerge > *:nth-child(7) { animation-delay: 220ms; }
.bf-emerge > *:nth-child(n+8) { animation-delay: 240ms; }

/* Rows inside a pane get the same treatment one level down, so a card's own
   contents arrive after the card itself. */
.bf-emerge-rows > * {
    animation: bf-emerge var(--bf-dur-fast) var(--bf-ease) both;
}
.bf-emerge-rows > *:nth-child(2) { animation-delay: 40ms; }
.bf-emerge-rows > *:nth-child(3) { animation-delay: 75ms; }
.bf-emerge-rows > *:nth-child(4) { animation-delay: 105ms; }
.bf-emerge-rows > *:nth-child(n+5) { animation-delay: 130ms; }

/* Press: glass compresses, it does not change colour. */
.bf-glass-press { transition: transform 0.34s var(--bf-ease); }
.bf-glass-press:active { transform: scale(0.978); }

@media (prefers-reduced-motion: reduce) {
    .bf-emerge > *, .bf-emerge-rows > * { animation: none; }
    .bf-glass-press { transition: none; }
}

/* ── inline expansion ──────────────────────────────────────────────────────
   BFGlass.expand(): a control growing into a panel where it stands, with the
   layout moving out of its way rather than the panel being drawn over it.
   Both classes are put on by the library and taken off again when it closes. */

/* The pane clips its content while it is smaller than the content is. */
.bf-expanded { overflow: hidden; }

/* The motion writes width, height, corner and the host's gap on every frame.
   A `transition: all` on the host would chase those writes one curve behind
   and turn a single motion into two. */
.bf-expand-host { transition: none !important; }

/* ── the travelling highlight ──────────────────────────────────────────────
   BFGlass.highlight(): one capsule of glass lying IN a pane, moving between
   the rows of a list. Inserted as the container's first child, so it paints
   under the rows and its backdrop is the pane itself — glass on glass.

   --bf-hl-p is the material's own presence, written per frame by the library.
   The tint rides it rather than the element's opacity: opacity would fade the
   refraction out as a picture, and a surface appearing is a surface thickening. */
.bf-hl {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
    border-radius: 16px;
    border: 1px solid transparent;
    pointer-events: none;
    z-index: 0;
    will-change: left, top, height;
    background-color: rgb(255 255 255 / calc(0.055 * var(--bf-hl-p, 0)));
}

/* The selected row also carries its section's colour — pooled under the top
   edge the way light pools in a dish, not painted flat across the capsule.

   On a pseudo-element, and not on background-image, because background-image
   on a lensed surface IS the material pass: bf-glass.js writes it inline and
   an accent put there would be overwritten on the next rebuild. */
.bf-hl.is-sel::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    opacity: var(--bf-hl-p, 0);
    background: radial-gradient(125% 150% at 50% -10%,
        var(--bf-hl-accent, transparent) 0%, transparent 70%);
}

.bf-hl.is-hover { background-color: rgb(255 255 255 / calc(0.032 * var(--bf-hl-p, 0))); }

/* ── the overlay canvas ────────────────────────────────────────────────────
   The renderer's second canvas. The first one sits at z-index -1 and draws
   content panes BEHIND the page; this one sits above the page and draws the
   panes that float over it — the ones whose shape changes every frame, which
   a baked backdrop-filter cannot do because its raster is its geometry.

   Everything outside a floating pane is alpha 0, so the page is untouched. */
#bf-glass-top {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 2147483000;
    pointer-events: none;
    display: block;
}

/* A surface drawn on that canvas has its glass painted OVER the page, so its
   own contents have to out-rank the canvas or they would be buried under their
   own pane. This is the one place on the site where a five-digit z-index is
   the correct answer rather than a symptom. */
/* Two classes deep on purpose: the element's own stylesheet almost certainly
   sets `position: relative` on it at one class, and a lifted pane that is not
   fixed is a pane sitting wherever the document flow last left it. */
.bf-glass.bf-glass-over,
.bf-glass-over {
    position: fixed;
    z-index: 2147483001;
}
.bf-glass-over > * { position: relative; z-index: 1; }
