/* ==========================================================================
   Band Battle -- public stylesheet
   Dark, high-contrast theme built for a music tournament. Mobile first.
   ========================================================================== */

/* Self-hosted, so no request ever leaves the visitor's browser for a font.
   swap = text shows immediately in the fallback and upgrades when ready. */
@font-face {
    font-family: "Great Vibes";
    src: url("../fonts/great-vibes-400.woff2") format("woff2");
    font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
    font-family: "Anton";
    src: url("../fonts/anton-400.woff2") format("woff2");
    font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
    font-family: "Rajdhani";
    src: url("../fonts/rajdhani-500.woff2") format("woff2");
    font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
    font-family: "Rajdhani";
    src: url("../fonts/rajdhani-600.woff2") format("woff2");
    font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
    font-family: "Rajdhani";
    src: url("../fonts/rajdhani-700.woff2") format("woff2");
    font-weight: 700; font-style: normal; font-display: swap;
}

:root {
    /* Every glow, border and highlight is derived from this one colour, so the
       whole site re-skins from the Settings screen. */
    --accent: #e93cac;
    --accent-rgb: 233, 60, 172;

    /* The violet half of the gradient. Every gradient in the design runs from
       --accent to --violet, which is what gives the whole site one voice. */
    --violet: #9b5cf6;
    --violet-rgb: 155, 92, 246;
    --grad: linear-gradient(100deg, var(--accent), var(--violet));

    /* Reserved for a crowned champion, so "won" never reads as "still open". */
    --crown: #ffc24d;
    --crown-rgb: 255, 194, 77;

    --font-script: "Great Vibes", "Segoe Script", cursive;
    --font-display: "Rajdhani", "Inter", "Segoe UI", system-ui, sans-serif;
    --font-title: "Anton", "Rajdhani", "Impact", sans-serif;

    /* Deep violet-black rather than neutral black: it makes the magenta read
       as light rather than as paint. */
    --bg: #0b0616;
    --bg-raised: #150c26;
    --bg-card: #1a1030;
    --bg-hover: #241640;

    --line: #3a2560;
    --line-soft: #2a1a47;

    --text: #f3eeff;
    --text-dim: #a99bc4;
    --text-faint: #7c6e99;

    --win: #35d07f;
    --warn: #f5a524;

    --radius: 14px;
    --radius-sm: 9px;
    --shadow: 0 14px 40px rgba(0, 0, 0, .55);

    /* Light is the material this design is built from. */
    --glow-sm:   0 0 8px  rgba(var(--accent-rgb), .35);
    --glow-md:   0 0 16px rgba(var(--accent-rgb), .30), 0 0 40px rgba(var(--accent-rgb), .13);
    --glow-lg:   0 0 26px rgba(var(--accent-rgb), .42), 0 0 70px rgba(var(--accent-rgb), .18);
    --glow-text: 0 0 16px rgba(var(--accent-rgb), .55);
    --edge:      inset 0 1px 0 rgba(255, 255, 255, .10);

    --wrap: 1180px;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    /* Stage lighting: two coloured beams washing in from either side, the way
       they fall across a stage, plus a haze low in the frame. */
    background:
        radial-gradient(900px 620px at 6% -60px,   rgba(var(--violet-rgb), .30), transparent 66%),
        radial-gradient(900px 620px at 94% -60px,  rgba(var(--accent-rgb), .26), transparent 66%),
        radial-gradient(1200px 400px at 50% 12%,   rgba(var(--accent-rgb), .12), transparent 72%),
        radial-gradient(1000px 500px at 50% 100%,  rgba(var(--violet-rgb), .10), transparent 70%),
        var(--bg);
    color: var(--text);
    font: 16px/1.6 "Inter", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* A faint haze over the whole page so flat panels sit in the same air as the
   stage lighting rather than looking pasted on. */
body::before {
    content: '';
    position: fixed; inset: 0; z-index: -1; pointer-events: none;
    background:
        radial-gradient(1px 1px at 20% 30%, rgba(255, 255, 255, .16), transparent),
        radial-gradient(1px 1px at 70% 18%, rgba(255, 255, 255, .12), transparent),
        radial-gradient(1px 1px at 44% 62%, rgba(255, 255, 255, .10), transparent),
        radial-gradient(1px 1px at 86% 74%, rgba(255, 255, 255, .12), transparent);
    background-size: 340px 340px, 420px 420px, 300px 300px, 380px 380px;
    opacity: .5;
}

main { flex: 1 0 auto; position: relative; }

h1, h2, h3, h4 {
    line-height: 1.2; margin: 0 0 .5em; font-weight: 700;
    font-family: var(--font-display); letter-spacing: .005em;
}
h1 { font-size: clamp(1.9rem, 5vw, 3rem); }
h2 { font-size: clamp(1.4rem, 3vw, 2rem); }
h3 { font-size: 1.18rem; }
p  { margin: 0 0 1rem; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

img { max-width: 100%; display: block; }

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 20px; }

.skip-link {
    position: absolute; left: -9999px; top: 0; z-index: 100;
    background: var(--accent); color: #fff; padding: 10px 16px; border-radius: 0 0 8px 0;
}
.skip-link:focus { left: 0; }

/* ------------------------------------------------------------------ header */

.site-header {
    border-bottom: 1px solid var(--line-soft);
    background: rgba(11, 6, 22, .88);
    backdrop-filter: blur(14px);
    position: sticky; top: 0; z-index: 40;
}
.site-header::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
    background: var(--grad); opacity: .55; pointer-events: none;
}
.site-header__inner {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; min-height: 66px;
}
.brand {
    display: flex; align-items: center; gap: 12px; position: relative;
    color: var(--text); font-weight: 800; letter-spacing: -.02em;
}
.brand:hover { text-decoration: none; }
/* The inline mark keeps its 112:48 shape, so it is set by height not width. */
.brand__mark {
    width: auto; height: 34px; flex-shrink: 0; display: block;
    filter: drop-shadow(0 0 12px rgba(var(--accent-rgb), .45));
}
@media (max-width: 560px) {
    .brand__mark { height: 28px; }
    /* The tagline wraps onto three lines at this width and pushes the whole
       header down for no gain -- the name alone is enough on a phone. */
    .brand__tag { display: none; }
    .brand__name { font-size: 1.15rem; }
}
.brand__text { display: flex; flex-direction: column; line-height: 1; }
.brand__name {
    font-family: var(--font-title); font-size: 1.32rem; font-weight: 400;
    text-transform: uppercase; letter-spacing: .015em; color: #fff;
    transform: skewX(-6deg); transform-origin: left;
}
.brand__name em {
    font-style: normal;
    background: var(--grad); -webkit-background-clip: text; background-clip: text;
    color: transparent; -webkit-text-fill-color: transparent;
}
.brand__tag {
    font-family: var(--font-display); font-size: .58rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: .28em; color: var(--text-faint);
    margin-top: 3px;
}

.site-nav { align-items: center; }
.site-nav a {
    font-family: var(--font-display); font-size: .96rem; font-weight: 600;
    letter-spacing: .02em; border-radius: 8px; padding: 8px 14px;
}
.site-nav a.is-here { color: #fff; }
.site-nav a.is-here::after {
    content: ''; display: block; height: 2px; margin-top: 5px; border-radius: 2px;
    background: var(--grad);
}

/* Search and the standing call to action live at the right of the bar. */
.header-tools { display: flex; align-items: center; gap: 12px; }
.site-search { position: relative; display: flex; align-items: center; }
.site-search svg {
    position: absolute; left: 13px; width: 15px; height: 15px;
    color: var(--text-faint); pointer-events: none;
}
.site-search input {
    font: inherit; font-size: .9rem; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line);
    border-radius: 999px; padding: 10px 16px 10px 36px; width: 190px;
    transition: border-color .15s ease, width .18s ease;
}
.site-search input::placeholder { color: var(--text-faint); }
.site-search input:focus {
    outline: none; border-color: rgba(var(--accent-rgb), .7); width: 230px;
    box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .14);
}
.btn--sm { padding: 10px 20px; font-size: .92rem; }

@media (max-width: 1100px) { .site-search input { width: 150px; } }
@media (max-width: 900px)  { .site-search { display: none; } }

.site-nav { display: flex; gap: 6px; flex-wrap: wrap; }
.site-nav a {
    color: var(--text-dim); font-size: .93rem; font-weight: 600;
    padding: 8px 13px; border-radius: 999px;
}
.site-nav a:hover { color: var(--text); background: var(--bg-hover); text-decoration: none; }

/* -------------------------------------------------------------------- hero */

/* The hero sits inside a targeting frame: four corner brackets and a soft
   orb of light behind the title. */
/* Full-bleed stage. The owner can upload a photo in Settings; until then the
   backdrop is built from gradients -- coloured beams from the rig, a haze at
   floor level and a dark vignette so the text stays readable over either. */
/* No isolation here: it makes the hero its own stacking context, which is what
   stopped the stats strip below from painting over its lower edge. The stage
   layer is already scoped by this element's own positioning. */
.hero {
    position: relative; text-align: center;
    padding: 58px 20px 58px; margin-bottom: 26px;
    overflow: hidden;
}
/* The stage itself: the instrument groups lifted from the client's artwork,
   anchored to the outer edges with the middle left clear for the title. If the
   owner uploads their own photo in Settings it replaces both of these. */
/* Explicit 0-above-nothing rather than a negative z-index: negative layers
   depend on which ancestor happens to form a stacking context, which is
   exactly the sort of thing that breaks when the layout is touched later.

   The stage is the client's own artwork, full width: guitars stage left,
   drums and bass stage right, smoke along the floor. Its top edge fades into
   the same colour as the backdrop below, so whatever height the hero runs at,
   the photo pins to the bottom and the seam never shows. */
.hero__stage {
    position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background-color: #150a28;
    background-image: url("../image/hero-stage.webp");
    background-position: center bottom;
    background-size: 100% auto;
    background-repeat: no-repeat;
}
/* An uploaded photo takes over completely rather than sitting behind ours. */
.hero__stage[style*="background-image"] {
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
}

/* Four beams from the lighting rig, angled in from both wings, plus the lamps
   themselves picked out along the top edge.
   The softness is built into the colour stops rather than applied with
   filter: blur(). A blur over a layer this size has to be re-rasterised on
   every paint, which is slow on the phones most of the voting comes from. */
.hero__stage::before {
    content: ''; position: absolute; inset: 0;
    /* The photo carries its own beams now; these only bridge the very top. */
    opacity: .55;
    background:
        conic-gradient(from 194deg at 8% -6%, transparent 0deg,
            rgba(var(--violet-rgb), .22) 4deg, rgba(var(--violet-rgb), .62) 12deg,
            rgba(var(--violet-rgb), .18) 21deg, transparent 29deg),
        conic-gradient(from 205deg at 29% -6%, transparent 0deg,
            rgba(90, 150, 255, .18) 3deg, rgba(90, 150, 255, .48) 10deg,
            rgba(90, 150, 255, .14) 17deg, transparent 24deg),
        conic-gradient(from 131deg at 71% -6%, transparent 0deg,
            rgba(var(--accent-rgb), .18) 3deg, rgba(var(--accent-rgb), .50) 10deg,
            rgba(var(--accent-rgb), .14) 17deg, transparent 24deg),
        conic-gradient(from 142deg at 92% -6%, transparent 0deg,
            rgba(var(--accent-rgb), .22) 4deg, rgba(var(--accent-rgb), .64) 12deg,
            rgba(var(--accent-rgb), .18) 21deg, transparent 29deg),
        radial-gradient(closest-side, rgba(205, 170, 255, .95), transparent) 8% 0 / 110px 62px no-repeat,
        radial-gradient(closest-side, rgba(140, 185, 255, .80), transparent) 29% 0 / 92px 52px no-repeat,
        radial-gradient(closest-side, rgba(255, 140, 220, .80), transparent) 71% 0 / 92px 52px no-repeat,
        radial-gradient(closest-side, rgba(255, 130, 210, .95), transparent) 92% 0 / 110px 62px no-repeat;
}

/* A light vignette so the title always has something dark behind it. The
   photo brings its own smoke and floor light, so this stays restrained --
   heavier and the artwork the client sent would disappear again. */
.hero__stage::after {
    content: ''; position: absolute; inset: 0;
    background:
        radial-gradient(680px 300px at 50% 38%, rgba(11, 6, 22, .5), rgba(11, 6, 22, .14) 58%, transparent 78%),
        linear-gradient(180deg,
            rgba(11, 6, 22, .4) 0%, rgba(11, 6, 22, .1) 22%,
            transparent 42%, transparent 86%, rgba(11, 6, 22, .5) 100%);
}
/* Named explicitly rather than ".hero > *": that selector has the same
   specificity as .hero__stage and, coming later, would cancel its absolute
   positioning and drop the stage out of the page entirely. */
.hero > .wrap { position: relative; z-index: 2; }
.hero__frame { display: none; }

.hero__eyebrow {
    display: inline-block; text-transform: uppercase; letter-spacing: .42em;
    font-family: var(--font-display); font-size: .82rem; font-weight: 700;
    color: var(--accent); margin-bottom: 6px; padding-left: .42em;
    /* The artwork's eyebrow samples rosier than the raw accent. */
    color: color-mix(in srgb, var(--accent) 66%, #ffd2e6 34%);
    text-shadow: 0 0 20px rgba(var(--accent-rgb), .8);
}

/* The masthead. Gradient-filled heavy display type, slightly skewed, with a
   dark rim so it holds up over a photograph. */
.hero h1 {
    font-family: var(--font-title); font-weight: 400;
    font-size: clamp(3rem, 11.5vw, 7.4rem); line-height: .94;
    /* Tight tracking and a stronger slant, to match the artwork. */
    letter-spacing: -.012em; margin: 0 0 -.02em;
    text-transform: uppercase; transform: skewX(-9deg);
    color: #fff; white-space: nowrap;
}

/* The gradient lives on each letter, not on the heading. A letter that is
   transformed or filtered paints in its own context, so a gradient clipped to
   text on the parent never reaches it -- the whole title comes out invisible.
   Because the fill runs top-to-bottom, per-letter looks identical to one
   gradient across the word. */
.hero__letter {
    display: inline-block;
    /* Also set statically, so the arc survives if animations never run --
       reduced-motion, an old browser, or the animation being removed later. */
    transform: translateY(var(--lift, 0em)) rotate(var(--tilt, 0deg));
    /* Two layers clipped to the glyphs. The top one is a speckle in the page's
       own background colour, so the dots read as pinholes worn through the
       letter -- the distressed, sprayed edge the artwork has. Painted normally
       rather than blended, because blend modes wash out to nothing over a
       gradient this bright. */
    /* Colours sampled from the client's artwork, not chosen by eye. The fill
       stays pale all the way down -- white into lilac into orchid -- and the
       depth comes from dark speckle punched through the lower half, exactly
       how the artwork gets its worn, sprayed look. Three speckle layers at
       tilings that never align, so no halftone grid appears. */
    background-image:
        repeating-radial-gradient(circle at 0 0,
            rgba(255, 255, 255, .4) 0 .7px, transparent .7px 2.6px),
        repeating-radial-gradient(circle at 62% 38%,
            rgba(255, 255, 255, .24) 0 .6px, transparent .6px 3.9px),
        repeating-radial-gradient(circle at 31% 72%,
            rgba(26, 9, 46, .42) 0 .9px, transparent .9px 3.2px),
        linear-gradient(180deg,
            #ffffff 0%,
            #faf0fc 32%,
            #f7dcfa 50%,
            #f4c3fa 64%,
            #f2a8fb 78%,
            #f09bfb 90%,
            #e094f2 100%);
    background-size: 3.3px 4.1px, 6.7px 5.3px, 5.3px 6.7px, 100% 100%;
    -webkit-background-clip: text; background-clip: text;
    color: transparent; -webkit-text-fill-color: transparent;
    /* Saturation pushed up so the magenta stays vivid over the dark stage,
       and the shadow kept tight so it darkens the edge rather than the face
       of the letter. */
    filter: saturate(1.18)
            drop-shadow(0 0 22px rgba(var(--accent-rgb), .55))
            drop-shadow(0 3px 10px rgba(0, 0, 0, .55));
    animation:
        letter-in .62s cubic-bezier(.2, .9, .25, 1.06) calc(var(--i, 0) * .055s) both,
        letter-shine 5.5s ease-in-out calc(1.6s + var(--i, 0) * .07s) 3;
}
/* Letters drop in one after another. Only opacity and transform move, which
   the compositor can handle without re-laying-out the page. */
/* The end state has to restate the arc, not "transform: none" -- the animation
   fills forwards, so anything it leaves out would flatten the curve again. */
@keyframes letter-in {
    from {
        opacity: 0;
        transform: translateY(calc(var(--lift, 0em) + .34em))
                   scale(.88) rotate(calc(var(--tilt, 0deg) - 4deg));
    }
    to {
        opacity: 1;
        transform: translateY(var(--lift, 0em)) rotate(var(--tilt, 0deg));
    }
}

/* A highlight then travels along the word, one letter behind the next.
   Deliberately finite: these are gradient-clipped letters carrying two drop
   shadows, so each frame is an expensive repaint. Three passes catch the eye
   on arrival, then it settles rather than draining a phone battery all visit. */
@keyframes letter-shine {
    0%, 88%, 100% { filter: saturate(1.18)
                            drop-shadow(0 0 22px rgba(var(--accent-rgb), .55))
                            drop-shadow(0 3px 10px rgba(0, 0, 0, .55)); }
    94%           { filter: saturate(1.18) brightness(1.35)
                            drop-shadow(0 0 32px rgba(255, 255, 255, .8))
                            drop-shadow(0 3px 10px rgba(0, 0, 0, .55)); }
}

/* Tucked right under the title, the way it sits in the artwork: smaller,
   letterspaced wide, in the artwork's sampled lavender. */
.hero__sub {
    font-family: var(--font-display); font-weight: 600;
    font-size: clamp(.95rem, 1.4vw, 1.24rem); letter-spacing: .13em;
    color: #c391ec; margin: 2px 0 16px;
    text-shadow: 0 2px 12px rgba(0, 0, 0, .7);
}
.hero p {
    color: #e4dff0; max-width: 620px; margin: 0 auto 1.5rem;
    font-size: .98rem; font-weight: 600; letter-spacing: .14em;
    text-shadow: 0 2px 12px rgba(0, 0, 0, .75);
}
.hero .btn { font-size: 1.08rem; padding: 16px 34px; }

@media (max-width: 700px) {
    /* Below this the title would run off the edge, so let it wrap. */
    .hero h1 { white-space: normal; }
}

.section { padding: 26px 0 46px; }

/* Section headings are a marker, the label, then a rule running to the edge. */
.section__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap; margin-bottom: 22px;
}
.section__head h2 {
    margin: 0; display: flex; align-items: center; gap: 12px;
    font-size: clamp(.92rem, 2vw, 1.06rem); font-weight: 700;
    text-transform: uppercase; letter-spacing: .24em; color: var(--accent);
    text-shadow: var(--glow-text); white-space: nowrap;
}
.section__head h2::before {
    content: ''; width: 9px; height: 9px; flex-shrink: 0;
    background: var(--accent); transform: rotate(45deg);
    box-shadow: 0 0 10px rgba(var(--accent-rgb), .9);
}
.section__head h2::after {
    content: ''; display: block; width: clamp(40px, 34vw, 620px); height: 1px;
    background: linear-gradient(90deg, rgba(var(--accent-rgb), .55), transparent);
}
.section__head p { margin: 0; color: var(--text-dim); font-size: .93rem; }

/* ------------------------------------------------------------------ pieces */

.badge {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 11px; border-radius: 999px;
    font-size: .74rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
    border: 1px solid var(--line); color: var(--text-dim); background: var(--bg-raised);
    white-space: nowrap;
}
.badge--live {
    color: var(--accent); border-color: rgba(var(--accent-rgb), .55);
    background: rgba(var(--accent-rgb), .1);
    box-shadow: var(--glow-sm); text-shadow: var(--glow-text);
}
.badge--done { color: var(--win); border-color: rgba(53, 208, 127, .4); background: rgba(53, 208, 127, .1); }
.badge--soon { color: var(--warn); border-color: rgba(245, 165, 36, .4); background: rgba(245, 165, 36, .1); }

.badge--live::before {
    content: ''; width: 7px; height: 7px; border-radius: 50%;
    background: var(--accent); animation: pulse 1.8s ease-in-out infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

/* Chamfered corners rather than a pill, a lit border, and a bloom underneath.
   Deliberately not clip-path: it would crop the focus ring and the glow, and
   a button nobody can see focus on is worse than a slightly softer corner. */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 9px;
    padding: 13px 26px; border-radius: 999px; border: 0;
    font: inherit; font-family: var(--font-display); font-weight: 700;
    font-size: 1.02rem; cursor: pointer; text-align: center;
    color: #fff; letter-spacing: .015em;
    /* Deeper than --grad on purpose: the artwork's pill runs all the way down
       to a saturated blue-violet (#7316ec sampled), where the shared gradient
       stays lighter for borders and bars. */
    background: linear-gradient(100deg, var(--accent) 0%, #b307c9 52%, #7c1bee 100%);
    box-shadow:
        0 0 22px rgba(var(--accent-rgb), .40),
        0 0 54px rgba(var(--violet-rgb), .22),
        var(--edge), 0 8px 22px rgba(0, 0, 0, .5);
    transition: transform .12s ease, filter .12s ease, box-shadow .18s ease;
}
.btn:hover {
    filter: brightness(1.08); text-decoration: none; transform: translateY(-2px);
    box-shadow:
        0 0 30px rgba(var(--accent-rgb), .55),
        0 0 76px rgba(var(--violet-rgb), .30),
        var(--edge), 0 12px 30px rgba(0, 0, 0, .55);
}
.btn:active { transform: translateY(0); }
.btn:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

.btn--ghost {
    background: rgba(var(--accent-rgb), .05);
    border-color: rgba(var(--accent-rgb), .38); color: var(--text);
    box-shadow: none;
}
.btn--ghost:hover {
    background: rgba(var(--accent-rgb), .12);
    border-color: rgba(var(--accent-rgb), .75);
    box-shadow: var(--glow-sm); filter: none;
}
.btn--block { display: flex; width: 100%; }

.notice {
    border: 1px solid var(--line); border-left: 3px solid var(--accent);
    background: var(--bg-raised); border-radius: var(--radius-sm);
    padding: 16px 18px; color: var(--text-dim); margin: 0 0 22px;
}
.notice strong { color: var(--text); }

.empty {
    text-align: center; padding: 64px 20px; color: var(--text-dim);
    border: 1px dashed var(--line); border-radius: var(--radius); background: var(--bg-raised);
}

/* --------------------------------------------------------- tournament list */

.card-grid {
    display: grid; gap: 18px;
    grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
}

.t-card {
    display: flex; flex-direction: column; gap: 12px;
    background: var(--bg-card); border: 1px solid var(--line);
    border-radius: var(--radius); padding: 22px; color: var(--text);
    position: relative;
    transition: border-color .15s ease, transform .15s ease, box-shadow .18s ease;
}
.t-card::before {
    content: ''; position: absolute; top: -1px; left: -1px; width: 14px; height: 14px;
    border: 2px solid rgba(var(--accent-rgb), .5); border-right: 0; border-bottom: 0;
    border-radius: var(--radius) 0 0 0; pointer-events: none;
}
.t-card:hover {
    border-color: rgba(var(--accent-rgb), .55); transform: translateY(-2px);
    text-decoration: none; box-shadow: var(--glow-md);
}
.t-card h3 { margin: 0; font-size: 1.18rem; }
.t-card__meta { color: var(--text-faint); font-size: .87rem; margin: 0; }
.t-card__foot { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.t-card__champion { color: var(--crown); font-weight: 700; font-size: .9rem; }

/* A finished tournament is marked in the second colour so it never reads as
   something you can still vote in. */
.t-card--done::before { border-color: rgba(var(--crown-rgb), .5); }
.t-card--done:hover {
    border-color: rgba(var(--crown-rgb), .55);
    box-shadow: 0 0 16px rgba(var(--crown-rgb), .28), 0 0 40px rgba(var(--crown-rgb), .12);
}
.t-card--done .t-card__cta { color: var(--crown); }

.t-card__cta {
    font-family: var(--font-display); font-weight: 700; font-size: .8rem;
    text-transform: uppercase; letter-spacing: .16em; color: var(--accent);
}

/* ------------------------------------------------------------- vote section */

.round-bar {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
    background: var(--bg-raised); border: 1px solid var(--line-soft);
    border-radius: var(--radius); padding: 18px 22px; margin-bottom: 24px;
}
.round-bar__title { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.round-bar__title h2 { margin: 0; font-size: 1.3rem; }
.round-bar__timer { text-align: right; }
.round-bar__timer .label {
    display: block; font-size: .72rem; text-transform: uppercase; letter-spacing: .13em;
    color: var(--text-faint); font-weight: 800;
}
.round-bar__timer .value { font-size: 1.22rem; font-weight: 800; font-variant-numeric: tabular-nums; }

.vote-grid {
    display: grid; gap: 18px;
    grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
}

.vs-card {
    background:
        linear-gradient(180deg, rgba(var(--accent-rgb), .045), transparent 120px),
        var(--bg-card);
    border: 1px solid var(--line); border-radius: var(--radius);
    overflow: hidden; display: flex; flex-direction: column;
    position: relative;
    box-shadow: 0 10px 34px rgba(0, 0, 0, .45);
}

/* HUD corner brackets. Two pseudo-elements give opposite corners, which is
   enough to read as a targeting frame without four extra elements. */
.vs-card::before, .vs-card::after {
    content: ''; position: absolute; width: 15px; height: 15px;
    border: 2px solid rgba(var(--accent-rgb), .55); pointer-events: none; z-index: 2;
}
.vs-card::before { top: 0; left: 0; border-right: 0; border-bottom: 0; border-radius: var(--radius) 0 0 0; }
.vs-card::after { bottom: 0; right: 0; border-left: 0; border-top: 0; border-radius: 0 0 var(--radius) 0; }

.vs-card.is-live { border-color: rgba(var(--accent-rgb), .3); box-shadow: var(--glow-md), 0 10px 34px rgba(0, 0, 0, .45); }
.vs-card__head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 18px; border-bottom: 1px solid var(--line-soft);
    font-size: .76rem; font-weight: 800; letter-spacing: .1em;
    text-transform: uppercase; color: var(--text-faint);
}
.vs-card__body { display: flex; flex-direction: column; }

/* The grid lives on an inner wrapper, not on the button itself: browsers apply
   their own layout rules to button contents and quietly ignore display:grid. */
.side {
    display: block; width: 100%; margin: 0; padding: 0; position: relative;
    background: none; border: 0; border-radius: 0;
    color: var(--text); font: inherit; text-align: left;
    -webkit-appearance: none; appearance: none;
    transition: background .13s ease;
}
button.side { cursor: pointer; }
.side + .side { border-top: 1px solid var(--line-soft); }
button.side:hover:not(:disabled) { background: var(--bg-hover); }
.side:disabled { cursor: default; }
.side:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.side__inner {
    display: grid; grid-template-columns: 52px minmax(0, 1fr) auto;
    align-items: center; gap: 14px; padding: 16px 18px;
    position: relative; z-index: 1;
}

/* The percentage bar. A lit leading edge makes it read as a charge meter
   rather than a flat block of colour. */
.side__fill {
    position: absolute; inset: 0; width: 0; z-index: 0;
    background: linear-gradient(90deg, rgba(var(--accent-rgb), .26), rgba(var(--accent-rgb), .07));
    border-right: 1px solid rgba(var(--accent-rgb), .9);
    box-shadow: 0 0 16px rgba(var(--accent-rgb), .35);
    transition: width .5s cubic-bezier(.2, .8, .3, 1);
    pointer-events: none;
}
.side.is-winner .side__fill {
    background: linear-gradient(90deg, rgba(53, 208, 127, .26), rgba(53, 208, 127, .06));
    border-right-color: rgba(53, 208, 127, .9);
    box-shadow: 0 0 16px rgba(53, 208, 127, .35);
}

.avatar {
    width: 52px; height: 52px; border-radius: 12px; object-fit: cover;
    background: var(--bg-hover); border: 1px solid var(--line);
    display: flex; align-items: center; justify-content: center;
    font-weight: 800; color: var(--text-faint); font-size: .95rem; letter-spacing: .02em;
    flex-shrink: 0;
}

.side__name { font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; min-width: 0; }
.side__seed { display: block; font-size: .74rem; color: var(--text-faint); font-weight: 600; margin-top: 2px; }
/* "Listen" buttons under each matchup. Kept out of the vote button rather than
   inside it -- a link nested in a button is invalid markup, and tapping to
   listen must never be mistaken for casting a vote. */
.listen {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 6px 12px 6px 9px; border-radius: 999px;
    border: 1px solid var(--line); background: var(--bg-raised);
    font-size: .76rem; font-weight: 700; color: var(--text-dim);
    text-decoration: none; white-space: nowrap;
    transition: border-color .14s ease, color .14s ease, background .14s ease;
}
.listen:hover, .listen:focus-visible {
    color: var(--text); border-color: var(--accent); background: var(--bg-hover);
}
.listen__icon { width: 15px; height: 15px; flex-shrink: 0; color: var(--accent); }
.listen__name { max-width: 15ch; overflow: hidden; text-overflow: ellipsis; }
.listen__where {
    font-size: .68rem; font-weight: 600; color: var(--text-faint);
    padding-left: 7px; border-left: 1px solid var(--line);
}

.side__stat { text-align: right; min-width: 62px; }
.side__pct { font-weight: 800; font-size: 1.06rem; font-variant-numeric: tabular-nums; }
.side__count { display: block; font-size: .74rem; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.side__pick {
    font-size: .7rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em;
    color: var(--accent);
}
.side.is-winner .side__pct { color: var(--win); }

.vs-card__foot {
    padding: 11px 18px; border-top: 1px solid var(--line-soft);
    font-size: .82rem; color: var(--text-faint);
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    min-height: 44px;
}
.vs-card__msg { color: var(--text-dim); }
.vs-card__links { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }

@media (max-width: 560px) {
    .vs-card__foot { flex-direction: column; align-items: stretch; gap: 9px; }
    .vs-card__links { justify-content: flex-start; }
    .listen { flex: 1 1 auto; justify-content: center; }
}
.vs-card__msg.is-error { color: var(--warn); }
.vs-card__msg.is-ok { color: var(--win); }

.vs-card.is-voted { border-color: rgba(var(--accent-rgb), .38); }
.vs-card.is-locked .side { cursor: default; }

/* ---------------------------------------------------------------- champion */

.champion {
    text-align: center; padding: 52px 24px; margin-bottom: 30px;
    border: 1px solid rgba(var(--accent-rgb), .45); border-radius: var(--radius);
    background:
        radial-gradient(620px 260px at 50% 0, rgba(var(--accent-rgb), .26), transparent 72%),
        var(--bg-raised);
    box-shadow: var(--glow-md), 0 16px 50px rgba(0, 0, 0, .55);
    position: relative; overflow: hidden;
}
/* Concentric rings behind the champion, the centrepiece motif of this style. */
.champion::before {
    content: ''; position: absolute; left: 50%; top: 0; width: 460px; height: 460px;
    margin-left: -230px; margin-top: -250px; border-radius: 50%;
    border: 1px solid rgba(var(--accent-rgb), .15);
    box-shadow: 0 0 0 34px rgba(var(--accent-rgb), .035), 0 0 0 35px rgba(var(--accent-rgb), .085);
    pointer-events: none;
}
.champion > * { position: relative; z-index: 1; }
.champion__label {
    text-transform: uppercase; letter-spacing: .22em; font-size: .74rem;
    font-weight: 800; color: var(--accent); margin-bottom: 12px;
    text-shadow: var(--glow-text);
}
.champion__name {
    font-size: clamp(1.8rem, 5vw, 2.8rem); margin: 0 0 6px;
    text-shadow: 0 0 28px rgba(var(--accent-rgb), .45);
}
.champion__avatar {
    width: 96px; height: 96px; border-radius: 50%; margin: 0 auto 18px;
    object-fit: cover; border: 2px solid rgba(var(--accent-rgb), .6);
    display: flex; align-items: center; justify-content: center;
    font-size: 2rem; font-weight: 800; color: var(--accent); background: var(--bg-card);
    box-shadow: var(--glow-lg);
}

/* ----------------------------------------------------------------- bracket */

/* The whole tree sits on its own panel, a shade lighter than the page, with a
   pool of light behind the middle where the prize sits. */
.bracket-shell {
    /* Fallback only: the renderer overrides this inline per tournament size. */
    --col: 236px;
    margin-top: 12px; padding: 18px 14px 8px;
    border: 1px solid var(--line-soft); border-radius: 20px;
    background:
        radial-gradient(620px 300px at 50% 58%, rgba(var(--violet-rgb), .16), transparent 70%),
        linear-gradient(180deg, rgba(23, 13, 43, .78), rgba(16, 9, 31, .78));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .04);
}

/* The bracket breaks out of the content column and uses the full window. */
.bracket-wide { width: 100%; padding: 0 20px; }

.round-tabs { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 12px; margin-bottom: 8px; }
.round-tabs button {
    flex: 0 0 auto; padding: 8px 17px; border-radius: 999px;
    border: 1px solid transparent; background: transparent; color: var(--text-dim);
    font: inherit; font-family: var(--font-display);
    font-size: .92rem; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.round-tabs button:hover { color: var(--text); }
.round-tabs button.is-active {
    background: rgba(var(--accent-rgb), .16); border-color: rgba(var(--accent-rgb), .8);
    color: #fff; box-shadow: var(--glow-sm);
}

/* The open round's column, lit from below like a live channel. */
.bracket__round.is-open .bracket__round-name,
.bracket__center.is-open .bracket__round-name {
    text-shadow: var(--glow-text);
    border-bottom-color: rgba(var(--accent-rgb), .6);
    box-shadow: 0 1px 10px -2px rgba(var(--accent-rgb), .7);
}

/* No "--col" declaration here on purpose. The width is set inline on
   .bracket-shell and inherited down; declaring it on .bracket as well would
   beat that inherited value and silently discard the per-size widths the
   renderer calculates. The default lives on the shell instead. */
.bracket {
    display: flex; overflow-x: auto; align-items: stretch;
    padding: 8px 2px 22px; scrollbar-width: thin;

    /* Centre a small bracket in the window. "safe" keeps the left-hand rounds
       reachable when a 64-band tree is wider than the screen -- plain centring
       would push them off where they cannot be scrolled back to. */
    justify-content: safe center;
}
.bracket::-webkit-scrollbar { height: 9px; }
.bracket::-webkit-scrollbar-thumb { background: var(--line); border-radius: 9px; }

.bracket__side { display: flex; }

.bracket__round { display: flex; flex-direction: column; flex: 0 0 var(--col); width: var(--col); }
.bracket__round-name {
    text-align: center; font-size: .72rem; font-weight: 800; letter-spacing: .1em;
    text-transform: uppercase; color: var(--text-faint); padding-bottom: 12px;
    border-bottom: 1px solid var(--line-soft); margin-bottom: 10px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bracket__round.is-open .bracket__round-name,
.bracket__center.is-open .bracket__round-name { color: var(--accent); }

/* The two finalist columns carry the same label as the centre. Hidden rather
   than removed, so the columns keep the same height and stay aligned. */
.bracket__side--left  .bracket__round:last-child  .bracket__round-name,
.bracket__side--right .bracket__round:first-child .bracket__round-name { visibility: hidden; }

.bracket__slot { flex: 1 1 0; display: flex; align-items: center; position: relative; padding: 6px 18px; }

/* Connector lines.
   Every slot takes an equal share of its column's height, so a round-2 slot
   spans exactly the two round-1 slots feeding it: their centres land at 25%
   and 75% of its height, which is what the vertical line joins. */

/* --- left half: rounds run outwards-in, left to right --- */
.bracket__side--left .bracket__round:not(:first-child) .bracket__slot::before {
    content: ''; position: absolute; left: 0; top: 50%; width: 18px;
    border-top: 2px solid rgba(var(--violet-rgb), .8);
}
.bracket__side--left .bracket__round:not(:first-child) .bracket__slot::after {
    content: ''; position: absolute; left: 0; top: 25%; height: 50%;
    border-left: 2px solid rgba(var(--violet-rgb), .8);
}
.bracket__side--left .bracket__game::after {
    content: ''; position: absolute; left: 100%; top: 50%; width: 18px;
    border-top: 2px solid rgba(var(--violet-rgb), .8);
}

/* --- right half: mirrored, so its columns are drawn in reverse order --- */
.bracket__side--right .bracket__round:not(:last-child) .bracket__slot::before {
    content: ''; position: absolute; right: 0; top: 50%; width: 18px;
    border-top: 2px solid rgba(var(--violet-rgb), .8);
}
.bracket__side--right .bracket__round:not(:last-child) .bracket__slot::after {
    content: ''; position: absolute; right: 0; top: 25%; height: 50%;
    border-right: 2px solid rgba(var(--violet-rgb), .8);
}
.bracket__side--right .bracket__game::before {
    content: ''; position: absolute; right: 100%; top: 50%; width: 18px;
    border-top: 2px solid rgba(var(--violet-rgb), .8);
}

/* --- the middle: the prize, and the champion beneath it ---
   Both sit in normal flow, centred as a pair. They were absolutely positioned
   before, which let the champion box land on top of the final card. */
.bracket__center {
    position: relative; flex: 0 0 var(--col); width: var(--col);
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    padding: 0 10px;
}
.bracket__center .bracket__round-name { width: 100%; }

/* The lines reaching in from each half meet the middle. */
.bracket__center::before,
.bracket__center::after {
    content: ''; position: absolute; top: 50%; width: 12px;
    border-top: 2px solid rgba(var(--violet-rgb), .8);
}
.bracket__center::before { left: 0; }
.bracket__center::after  { right: 0; }

.bracket__champion {
    position: relative; width: 100%;
    display: flex; align-items: center; justify-content: center; gap: 8px;
    border: 1px solid rgba(var(--violet-rgb), .75); border-radius: 14px;
    padding: 15px 10px; text-align: center;
    background: linear-gradient(180deg, rgba(var(--violet-rgb), .24), rgba(26, 16, 48, .96));
    box-shadow: 0 0 26px rgba(var(--violet-rgb), .45), 0 8px 22px rgba(0, 0, 0, .5);
}
.bracket__champion-text { min-width: 0; }
.bracket__champion-title {
    display: block; font-family: var(--font-display); font-weight: 700;
    font-size: 1.06rem; line-height: 1.24; color: #fff;
    text-shadow: 0 0 16px rgba(var(--violet-rgb), .6);
}
.bracket__laurel {
    width: 19px; height: 40px; flex-shrink: 0;
    color: rgba(var(--violet-rgb), .9);
}
.bracket__laurel--r { transform: scaleX(-1); }
.bracket__champion.is-crowned {
    border-style: solid; border-color: rgba(53, 208, 127, .55);
    background: rgba(53, 208, 127, .08);
    box-shadow: 0 0 18px rgba(53, 208, 127, .28);
}
.bracket__champion-label {
    display: block; font-size: .64rem; font-weight: 800; letter-spacing: .14em;
    text-transform: uppercase; color: var(--text-faint); margin-bottom: 3px;
}
.bracket__champion.is-crowned .bracket__champion-label { color: var(--win); }
.bracket__champion-name {
    display: block; font-size: .86rem; font-weight: 700; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* One outlined box per matchup with the two bands stacked inside it and a
   hairline between, the way the artwork draws it. */
.bracket__game {
    position: relative; width: 100%;
    background: rgba(30, 18, 56, .88);
    border: 1px solid rgba(var(--violet-rgb), .32);
    border-radius: 10px;
    box-shadow: 0 3px 12px rgba(0, 0, 0, .38);
}

.bracket__team {
    display: grid; grid-template-columns: 22px minmax(0, 1fr) auto;
    gap: 9px; align-items: center;
    padding: 9px 11px; font-size: .85rem; position: relative;
    border-radius: 9px;
}
.bracket__team + .bracket__team { box-shadow: inset 0 1px 0 rgba(var(--violet-rgb), .22); }
.bracket__band {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
    font-weight: 600;
}

/* The seed sits on the outside of each half, as it does on a printed sheet. */
.bracket__side--right .bracket__team { grid-template-columns: auto minmax(0, 1fr) 22px; }
.bracket__side--right .bracket__seed { order: 3; text-align: right; }
.bracket__side--right .bracket__band { order: 2; }
.bracket__side--right .bracket__check,
.bracket__side--right .bracket__score { order: 1; }

/* At 32 and 64 bands the columns are too narrow to carry a percentage as well
   as a name, and the name is what people are looking for. The winner is still
   obvious from the green marker, exactly as on a printed bracket. */
.bracket.is-tight .bracket__team { padding: 7px 9px; font-size: .8rem; gap: 7px; }

/* The winning row is lit and ringed inside the matchup box, so it reads as the
   one going through without breaking the box apart. */
.bracket__team.is-winner {
    color: #fff; font-weight: 600;
    background: linear-gradient(180deg, rgba(var(--violet-rgb), .26), rgba(var(--violet-rgb), .10));
    box-shadow: inset 0 0 0 1.5px rgba(var(--violet-rgb), .95),
                0 0 16px rgba(var(--violet-rgb), .35);
}
.bracket__check {
    width: 17px; height: 17px; color: #fff; flex-shrink: 0;
    filter: drop-shadow(0 0 6px rgba(var(--violet-rgb), .9));
}
.bracket__team.is-winner-unused::before {
    content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--win);
}
.bracket__team.is-out { color: var(--text-dim); border-color: rgba(var(--violet-rgb), .2); }
.bracket__team.is-tbd {
    color: var(--text-faint); font-style: italic;
    background: rgba(26, 16, 48, .55);
    border-style: dashed; border-color: rgba(var(--violet-rgb), .28);
}
.bracket__score { font-variant-numeric: tabular-nums; color: var(--text-dim); font-size: .8rem; }

/* The seed number sits in its own tinted chip, as on a printed sheet. */
.bracket__seed {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 22px; height: 20px; padding: 0 5px; border-radius: 6px;
    background: rgba(var(--violet-rgb), .16);
    color: var(--text-dim); font-size: .72rem; font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.bracket__team.is-winner .bracket__seed { background: rgba(255, 255, 255, .18); color: #fff; }

/* ------------------------------------------------------------------ footer */

.site-footer {
    border-top: 1px solid var(--line-soft); margin-top: 40px;
    padding: 26px 0; color: var(--text-faint); font-size: .88rem;
}
.site-footer__inner { display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.site-footer p { margin: 0; }
.site-footer a { color: var(--text-dim); }

/* -------------------------------------------------------------- responsive */

/* On a phone the two halves cannot sit side by side, so the tabs take over and
   show one round at a time -- both halves of it, stacked. */
@media (max-width: 900px) {
    .bracket { display: block; overflow-x: visible; }
    .bracket__side { display: block; }
    .bracket__round,
    .bracket__center { display: none; width: auto; }
    .bracket__round.is-active,
    .bracket__center.is-active { display: block; }

    /* One heading per round, not one per half. */
    .bracket__side--right .bracket__round .bracket__round-name { display: none; }

    .bracket__slot,
    .bracket__final { padding: 5px 0; display: block; }

    .bracket__side--left .bracket__round .bracket__slot::before,
    .bracket__side--left .bracket__round .bracket__slot::after,
    .bracket__side--left .bracket__game::after,
    .bracket__side--right .bracket__round .bracket__slot::before,
    .bracket__side--right .bracket__round .bracket__slot::after,
    .bracket__side--right .bracket__game::before,
    .bracket__final::before,
    .bracket__final::after { display: none; }

    .bracket__champion { position: static; margin: 12px 0 0; left: auto; right: auto; }

    .round-bar__timer { text-align: left; }
}

/* On desktop the round pills are no longer a navigation control -- every round
   is on screen at once -- but the artwork keeps them as a legend across the
   top, so they stay visible and simply mark which round is being voted in. */
@media (min-width: 901px) {
    .round-tabs { justify-content: flex-end; padding-bottom: 16px; }
    .round-tabs button { pointer-events: none; }
}

@media (max-width: 560px) {
    .hero { padding: 38px 0 24px; }
    .vote-grid { grid-template-columns: 1fr; }
    .side__inner { grid-template-columns: 44px minmax(0, 1fr) auto; gap: 11px; padding: 14px; }
    .avatar { width: 44px; height: 44px; }
    .side__pct { font-size: .98rem; }
    .side__stat { min-width: 0; }
    .site-nav a { padding: 7px 10px; font-size: .87rem; }
    .round-bar { padding: 16px; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* -------------------------------------------------------- motion & contrast */

/* Anyone who has asked their system to reduce motion gets a still interface.
   The pulsing "live" dot in particular is exactly what that setting is for. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
        scroll-behavior: auto !important;
    }
}

/* Some people turn contrast up because glow and thin borders are hard to see.
   Honour that by trading the atmosphere for legibility. */
@media (prefers-contrast: more) {
    body::before { display: none; }
    :root {
        --line: #4d5f80;
        --text-dim: #c2cddd;
        --text-faint: #9aa8bf;
        --glow-sm: none; --glow-md: none; --glow-lg: none; --glow-text: none;
    }
}
/* ============================================================ home dashboard */

/* The stats strip that straddles the bottom of the hero. */
/* Sits inside the hero, over the photograph, as the artwork lays it out.
   The background is nearly opaque on its own rather than relying on
   backdrop-filter: over a stacking context some GPUs paint a blurred
   backdrop as fully transparent, which made the whole strip vanish once. */
.stats-bar {
    display: grid; grid-template-columns: repeat(4, 1fr);
    background: rgba(23, 13, 43, .97);
    border: 1px solid rgba(var(--violet-rgb), .35); border-radius: 18px;
    margin: 44px auto 0; max-width: 1000px; position: relative; z-index: 3;
    box-shadow: 0 12px 34px rgba(0, 0, 0, .5),
                inset 0 1px 0 rgba(255, 255, 255, .07);
    overflow: hidden;
}
@supports (backdrop-filter: blur(1px)) {
    .stats-bar { background: rgba(23, 13, 43, .86); backdrop-filter: blur(14px); }
}
.stat-cell {
    display: flex; align-items: center; gap: 14px; padding: 22px 24px;
}
.stat-cell + .stat-cell { border-left: 1px solid var(--line-soft); }
.stat-cell__icon {
    width: 34px; height: 34px; flex-shrink: 0; color: var(--violet);
    filter: drop-shadow(0 0 10px rgba(var(--violet-rgb), .65));
}
.stat-cell__value {
    font-family: var(--font-display); font-weight: 700; font-size: 1.5rem;
    line-height: 1.1; color: #fff;
}
.stat-cell__label { font-size: .82rem; color: var(--text-dim); }

@media (max-width: 860px) {
    .stats-bar { grid-template-columns: repeat(2, 1fr); margin-top: 30px; }
    .stat-cell:nth-child(3) { border-left: 0; }
    .stat-cell:nth-child(n+3) { border-top: 1px solid var(--line-soft); }
}
@media (max-width: 460px) {
    .stats-bar { grid-template-columns: 1fr; }
    .stat-cell + .stat-cell { border-left: 0; border-top: 1px solid var(--line-soft); }
}

/* The dashboard runs wider than the rest of the page, as it does in the
   artwork: the bracket needs the room, and the two side panels would be
   squeezed to nothing inside the normal 1180px column. */
.wrap--dash { max-width: 1520px; }

/* Three columns: leaderboard, bracket, live poll. */
.dash {
    display: grid; gap: 22px; align-items: start;
    grid-template-columns: 262px minmax(0, 1fr) 292px;
}
/* Grid items default to min-width:auto, so the bracket -- which is intrinsically
   1500px+ wide -- would push the whole grid past the edge of the page instead of
   scrolling inside its own column. */
.dash > * { min-width: 0; }
/* min-width:0 is what actually stops the bracket blowing the grid out; the
   bracket scrolls inside itself. No overflow:hidden here -- it would clip the
   view tabs' glow and, worse, their keyboard focus ring. */
@media (max-width: 1280px) { .dash { grid-template-columns: 250px minmax(0, 1fr); } .dash__right { grid-column: 1 / -1; } }
@media (max-width: 900px)  { .dash { grid-template-columns: 1fr; } .dash__left, .dash__right { grid-column: auto; } }

/* The bracket's column width is set inline on .bracket-shell; an explicit
   declaration here beats that inherited value, so the dashboard can run a
   tighter tree than the full-width tournament page.
   Not tighter than this, though: below about 180px the band names start
   truncating to "Metalli..." and the bracket stops being readable, which is
   worse than letting it scroll inside its column. */
.dash__mid .bracket { --col: 182px; }

/* The round pills above the tree already name every round, so per-column
   headings would just repeat them and eat vertical space. */
.dash__mid .bracket__round-name { display: none; }
.dash__mid .bracket-shell { padding: 14px 10px 4px; }

/* A visible but restrained scrollbar: the tree is wider than the column, and
   a hidden one leaves people unaware there is more to see. */
.dash__mid .bracket::-webkit-scrollbar { height: 10px; }
.dash__mid .bracket::-webkit-scrollbar-track { background: rgba(0, 0, 0, .25); border-radius: 10px; }
.dash__mid .bracket::-webkit-scrollbar-thumb {
    background: rgba(var(--violet-rgb), .5); border-radius: 10px;
}
.dash__mid .bracket::-webkit-scrollbar-thumb:hover { background: rgba(var(--violet-rgb), .75); }

.side-card {
    background: var(--bg-card); border: 1px solid var(--line);
    border-radius: 16px; padding: 18px; margin-bottom: 20px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
}
.side-card__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; margin-bottom: 16px;
}
.side-card__head h2 {
    margin: 0; font-family: var(--font-display); font-size: 1.06rem; font-weight: 700;
    display: flex; align-items: center; gap: 9px; color: var(--text);
    text-transform: none; letter-spacing: 0;
}
.side-card__head h2::before, .side-card__head h2::after { content: none; }
.side-card__icon { width: 19px; height: 19px; color: var(--accent); flex-shrink: 0; }
.side-card__more { font-size: .8rem; color: var(--text-dim); font-weight: 600; }

/* --- leaderboard --- */
.lb-row {
    display: grid; grid-template-columns: 26px 40px minmax(0, 1fr);
    gap: 11px; align-items: center; padding: 10px 8px;
    border-radius: 12px; color: var(--text);
}
.lb-row + .lb-row { margin-top: 2px; }
.lb-row:hover { background: var(--bg-hover); text-decoration: none; }
.lb-row--top { background: rgba(var(--accent-rgb), .07); border: 1px solid rgba(var(--accent-rgb), .22); }

.lb-rank {
    width: 26px; height: 26px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-family: var(--font-display); font-weight: 700; font-size: .82rem;
    background: var(--bg-hover); color: var(--text-dim); border: 1px solid var(--line);
}
.lb-row--top .lb-rank { background: var(--grad); color: #fff; border-color: transparent; }

.lb-art {
    width: 40px; height: 40px; border-radius: 9px; object-fit: cover;
    background: var(--bg-hover); border: 1px solid var(--line);
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: .78rem; color: var(--text-faint);
}
.lb-main { min-width: 0; }
.lb-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.lb-name { font-weight: 600; font-size: .92rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-pct { font-family: var(--font-display); font-weight: 700; font-size: .86rem; color: var(--text-dim); }
.lb-bar { height: 5px; border-radius: 3px; background: var(--bg-hover); margin-top: 6px; overflow: hidden; }
.lb-bar span { display: block; height: 100%; border-radius: 3px; background: var(--grad); }

/* --- live poll --- */
.poll-item + .poll-item { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line-soft); }
.poll-item__title { font-size: .87rem; font-weight: 600; margin: 0 0 9px; color: var(--text); }
.poll-bar { height: 7px; border-radius: 4px; background: var(--bg-hover); overflow: hidden; display: flex; }
.poll-bar span:first-child { background: var(--grad); }
.poll-bar span:last-child { background: rgba(var(--violet-rgb), .22); }
.poll-nums {
    display: flex; justify-content: space-between; margin-top: 6px;
    font-family: var(--font-display); font-weight: 700; font-size: .82rem;
}
.poll-nums .a { color: var(--accent); }
.poll-nums .b { color: var(--text-faint); }

.poll-cta {
    text-align: center; padding: 20px 16px; border-radius: 14px;
    background: linear-gradient(180deg, rgba(var(--accent-rgb), .10), rgba(var(--violet-rgb), .10));
    border: 1px solid var(--line);
}
.poll-cta h3 { font-size: 1rem; margin: 0 0 6px; font-family: var(--font-display); }
.poll-cta p { font-size: .84rem; color: var(--text-dim); margin: 0 0 14px; }
/* --------------------------------------------------------- search & about */

.wrap--narrow { max-width: 760px; }

.search-page { display: flex; gap: 10px; margin-bottom: 26px; flex-wrap: wrap; }
.search-page input {
    flex: 1 1 260px; font: inherit; font-size: 1rem; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line);
    border-radius: 999px; padding: 13px 20px;
}
.search-page input::placeholder { color: var(--text-faint); }
.search-page input:focus {
    outline: none; border-color: rgba(var(--accent-rgb), .7);
    box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .14);
}

.search-results { display: grid; gap: 10px; }
.search-hit {
    display: grid; grid-template-columns: 40px minmax(0, 1fr) auto;
    gap: 14px; align-items: center;
    background: var(--bg-card); border: 1px solid var(--line);
    border-radius: 14px; padding: 12px 16px; color: var(--text);
    transition: border-color .15s ease, transform .15s ease;
}
.search-hit:hover {
    text-decoration: none; transform: translateX(3px);
    border-color: rgba(var(--accent-rgb), .55);
}
.search-hit__main { min-width: 0; display: flex; flex-direction: column; }
.search-hit__name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-hit__where { font-size: .84rem; color: var(--text-dim); }
.search-hit__seed {
    font-family: var(--font-display); font-weight: 700; font-size: .8rem;
    color: var(--text-faint); white-space: nowrap;
}

.prose { color: var(--text-dim); font-size: 1.04rem; line-height: 1.75; }
.prose p { margin: 0 0 1.1rem; }
.prose p:first-child { color: var(--text); font-size: 1.12rem; }
/* -------------------------------------------------- bracket centrepiece */

/* The trophy sits above the final, glowing, on the axis both halves run to. */
.bracket__trophy {
    position: relative; width: 100%; height: 150px; margin-bottom: 14px;
    display: flex; align-items: center; justify-content: center;
    pointer-events: none;
}
/* The trophy is cut out to transparency now, so no dark pool is needed to
   hide a rectangle -- just the light it would throw: a warm spill pooling at
   the plinth and a softer halo around the cup. */
.bracket__trophy::before {
    content: ''; position: absolute; left: 50%; top: 50%;
    width: 250px; height: 220px; margin: -110px 0 0 -125px;
    background:
        radial-gradient(ellipse 34% 16% at 50% 86%, rgba(255, 186, 76, .42), transparent 72%),
        radial-gradient(ellipse 46% 46% at 50% 44%, rgba(255, 176, 70, .13), transparent 70%);
}
/* The waveform sits behind the cup and runs wider than it, the way the
   artwork frames the prize. */
/* Runs wider than the column so the bars bleed past the cup, as in the artwork. */
.bracket__wave {
    position: absolute; left: -22%; width: 144%; top: 50%;
    height: 56px; margin-top: -20px;
    color: rgba(var(--violet-rgb), .5);
    filter: drop-shadow(0 0 10px rgba(var(--violet-rgb), .55));
}
/* Gold, so the glow is gold: a violet halo round a gold cup reads as a
   colour clash rather than stage lighting. */
.bracket__cup {
    position: relative; width: auto; height: 124px;
    filter: drop-shadow(0 0 16px rgba(255, 186, 76, .5))
            drop-shadow(0 0 44px rgba(255, 170, 60, .28));
}
.bracket__trophy::after {
    content: ''; position: absolute; top: 50%; left: 50%;
    width: 210px; height: 210px; margin: -105px 0 0 -105px; border-radius: 50%;
    background: radial-gradient(circle, rgba(var(--violet-rgb), .22), transparent 64%);
    z-index: -1;
}

.bracket__champion {
    background: linear-gradient(180deg, rgba(var(--violet-rgb), .16), rgba(var(--accent-rgb), .10));
    border-color: rgba(var(--violet-rgb), .45);
}
.bracket__champion.is-crowned {
    border-style: solid; border-color: rgba(var(--crown-rgb), .6);
    background: linear-gradient(180deg, rgba(var(--crown-rgb), .18), rgba(var(--crown-rgb), .06));
    box-shadow: 0 0 22px rgba(var(--crown-rgb), .32);
}
.bracket__champion.is-crowned .bracket__champion-label { color: var(--crown); }

@media (max-width: 900px) {
    .bracket__trophy { position: static; margin: 0 0 10px; }
    .bracket__trophy::after { display: none; }
}

/* Percentage bars pick up the gradient too. */
.side__fill { background: linear-gradient(90deg, rgba(var(--accent-rgb), .34), rgba(var(--violet-rgb), .12)); }
.lb-row--top .lb-name { color: #fff; }
.round-tabs button.is-active {
    background: rgba(var(--violet-rgb), .18);
    border-color: rgba(var(--violet-rgb), .85);
    color: #fff;
    box-shadow: 0 0 14px rgba(var(--violet-rgb), .35);
}
/* ---------------------------------------------- dashboard view switcher */

/* Full Bracket / Live Results / Top Bands, as the artwork groups them. */
.view-tabs { display: flex; gap: 6px; margin-bottom: 16px; flex-wrap: wrap; }
.view-tabs button {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 10px 18px; border-radius: 999px; border: 1px solid transparent;
    background: transparent; color: var(--text-dim);
    font: inherit; font-family: var(--font-display);
    font-size: .96rem; font-weight: 600; cursor: pointer; white-space: nowrap;
    transition: color .14s ease, background .14s ease;
}
.view-tabs button svg { width: 17px; height: 17px; flex-shrink: 0; }
.view-tabs button:hover { color: var(--text); }
.view-tabs button.is-active {
    background: var(--grad); border-color: transparent; color: #fff;
    box-shadow: 0 0 18px rgba(var(--violet-rgb), .4);
}

.view-panel {
    border: 1px solid var(--line-soft); border-radius: 20px;
    background: linear-gradient(180deg, rgba(23, 13, 43, .78), rgba(16, 9, 31, .78));
    padding: 18px;
}

.live-row { display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 12px; align-items: center; }
.live-row + .live-row { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line-soft); }
.live-row__n {
    width: 26px; height: 26px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-family: var(--font-display); font-weight: 700; font-size: .8rem;
    background: var(--bg-hover); color: var(--text-dim); border: 1px solid var(--line);
}
.live-row__main { min-width: 0; }
.live-row__names {
    display: flex; justify-content: space-between; gap: 12px;
    font-size: .9rem; font-weight: 600; margin-bottom: 8px;
}
.live-row__names span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* --------------------------------------------------- dashboard toolbar */

/* Views on the left, rounds on the right, one row -- the artwork's layout. */
.dash-toolbar {
    display: flex; align-items: center; justify-content: space-between;
    gap: 18px; flex-wrap: wrap; margin-bottom: 16px;
}
.dash-toolbar .view-tabs { margin-bottom: 0; }

.round-legend { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.round-legend span {
    padding: 8px 15px; border-radius: 999px; border: 1px solid transparent;
    font-family: var(--font-display); font-size: .9rem; font-weight: 600;
    color: var(--text-dim); white-space: nowrap;
}
.round-legend span.is-active {
    background: rgba(var(--violet-rgb), .18);
    border-color: rgba(var(--violet-rgb), .85);
    color: #fff; box-shadow: 0 0 14px rgba(var(--violet-rgb), .35);
}

/* The dashboard bracket sits straight on the page, as in the artwork: no
   card around it, and its own round tabs would duplicate the legend above. */
.dash__mid .bracket-shell {
    border: 0; background: none; box-shadow: none;
    padding: 0; margin-top: 0;
}
@media (min-width: 901px) {
    .dash__mid .round-tabs { display: none; }
}
@media (max-width: 900px) {
    /* On phones the bracket's own tabs do the switching, so the legend goes. */
    .round-legend { display: none; }
}
/* ------------------------------------------------- tournament name */

/* The name of the tournament is the headline of the page: someone arriving
   from a shared link should know which one they are looking at at a glance. */
.tournament-name {
    margin: 0; font-family: var(--font-display); font-weight: 700;
    font-size: clamp(1.75rem, 3.6vw, 2.9rem); line-height: 1.1;
    letter-spacing: -.01em; color: #fff;
    text-shadow: 0 0 26px rgba(var(--accent-rgb), .35);
}
.round-bar__title { flex-direction: column; align-items: flex-start; gap: 10px; }
.round-bar__badges { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.round-bar { align-items: flex-end; }

@media (max-width: 700px) {
    .round-bar { align-items: flex-start; }
}

/* The champion's name is no longer the page heading -- the tournament is --
   but it keeps the same presence. */
p.champion__name { font-weight: 700; font-family: var(--font-display); }