/*
   HumberSquash design system
   --------------------------
   Mobile-first. Single source of truth: CSS custom properties below.
   Layout: CSS Grid (12-col content grid + outer page grid).
   Breakpoints:
     - default      : phone (single column, stacked)
     - >=  720px    : tablet (sidebar + main, right rail wraps under main)
     - >= 1080px    : desktop (left rail | main | right rail, three columns)
*/

/* ------------------------------------------------------------------ */
/*  Tokens                                                            */
/* ------------------------------------------------------------------ */

:root {
    /* Brand palette — derived from the legacy site, with stronger contrast. */
    --hs-red:           #C0341E;
    --hs-red-dark:      #8E2515;
    --hs-red-soft:      #FBE9E5;
    --flame:            #FF5A36;   /* vibrant accent for active/hover energy */
    --flame-2:          #FF8A3D;
    --hs-blue:          #0E4D8B;
    --hs-blue-hover:    #073A6E;
    --hs-cream:         #FFF8DC;       /* table row highlight, from legacy #EDEEC0 */
    --hs-cream-border:  #E8DDA8;

    /* Surfaces & text */
    --bg:               #F5F4F1;
    --surface:          #FFFFFF;
    --surface-2:        #F5F5F5;
    --border:           #DCDCDC;
    --border-strong:    #BDBDBD;
    --text:             #222222;
    --text-muted:       #5A5A5A;

    /* Type */
    --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                 "Helvetica Neue", Arial, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    --fs-100:   0.8125rem;
    --fs-200:   0.9375rem;
    --fs-300:   1rem;
    --fs-400:   1.125rem;
    --fs-500:   1.375rem;
    --fs-600:   1.75rem;
    --fs-700:   2.125rem;
    --lh-tight: 1.25;
    --lh-body:  1.55;

    /* Space scale (4px base) */
    --sp-1: 0.25rem;
    --sp-2: 0.5rem;
    --sp-3: 0.75rem;
    --sp-4: 1rem;
    --sp-5: 1.5rem;
    --sp-6: 2rem;
    --sp-7: 3rem;
    --sp-8: 4rem;

    /* Radius / elevation */
    --radius-sm: 4px;
    --radius:    8px;
    --radius-lg: 12px;
    --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.06);
    --shadow:    0 2px 8px rgb(0 0 0 / 0.08);

    /* Layout */
    --content-max: 1320px;
}

/* ------------------------------------------------------------------ */
/*  Reset                                                             */
/* ------------------------------------------------------------------ */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; tab-size: 4; }
body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: var(--fs-300);
    line-height: var(--lh-body);
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; }

a {
    color: var(--hs-blue);
    text-decoration: underline;
    text-underline-offset: 2px;
}
a:hover  { color: var(--hs-blue-hover); }
a:focus-visible { outline: 2px solid var(--hs-blue); outline-offset: 2px; border-radius: 2px; }

h1, h2, h3, h4 { line-height: var(--lh-tight); margin: 0 0 var(--sp-4) 0; color: var(--hs-red); }
h1 { font-size: var(--fs-700); font-weight: 700; }
h2 { font-size: var(--fs-500); font-weight: 600; }
h3 { font-size: var(--fs-400); font-weight: 600; }
h4 { font-size: var(--fs-300); font-weight: 600; color: var(--text); }

p  { margin: 0 0 var(--sp-4) 0; }
ul, ol { padding-left: 1.25rem; margin: 0 0 var(--sp-4) 0; }
li + li { margin-top: var(--sp-1); }

/* ...but ONLY in prose. A list that has had its marker removed is not a bulleted list any more,
   it is a layout container - a nav bar, a set of link cards, a breadcrumb - and 4px of top
   margin on every item except the first is wrong in all of them.

   It was wrong in a way that took a while to find, because in a horizontal flex nav the symptom
   does not look like a margin at all: the first item has none, every other item has 4px, and
   under `align-items: stretch` that margin comes out of each neighbour's available height. The
   first pill computed 4px TALLER than its neighbours (28.79px against 24.79px) with identical
   padding, font and line-height, and nothing in the nav's own rules to explain it. The wrap
   point moving with the window width made it come and go.

   Each of these lists already resets `list-style`, `margin` and `padding` on the UL and stops
   there. The items need the same treatment, so it is stated once here rather than repeated.
   A new layout list belongs in this selector. */
.nav__list > li,
.nav__mega-list > li,
.subnav > li,
.linklist > li,
.team-list > li,
.breadcrumb ol > li { margin-top: 0; }
hr { border: 0; border-top: 1px solid var(--border); margin: var(--sp-5) 0; }

.visually-hidden {
    position: absolute !important; width: 1px; height: 1px; padding: 0;
    margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap;
    border: 0;
}

/* Skip link — first focusable element for keyboard users */
.skip-link {
    position: absolute; left: var(--sp-3); top: var(--sp-3);
    transform: translateY(-250%);
    background: var(--hs-red); color: #fff; padding: var(--sp-2) var(--sp-3);
    border-radius: var(--radius-sm); z-index: 1000; font-weight: 600;
    transition: transform .15s ease;
}
.skip-link:focus { transform: translateY(0); }

/* ------------------------------------------------------------------ */
/*  Page layout (CSS Grid)                                            */
/* ------------------------------------------------------------------ */

.page {
    display: grid;
    grid-template-rows: auto 1fr auto;
    min-height: 100vh;
}

.shell {
    width: 100%;
    max-width: var(--content-max);
    margin-inline: auto;
    padding-inline: var(--sp-3);   /* tight gutters on mobile; widened below */
}
/* More breathing room down the sides on tablet/desktop so content isn't squashed */
@media (min-width: 720px)  { .shell { padding-inline: var(--sp-6); } }
@media (min-width: 1080px) { .shell { padding-inline: var(--sp-7); } }

/* Header — "neon energy": one dark gradient bar (logo · nav · account actions)
   that lights up under the cursor, with a value (USP) strip beneath. */
.site-header {
    position: relative;
    color: #fff;
    background: radial-gradient(140% 220% at 0% 0%, var(--header-from, #3c130c) 0%, var(--header-mid, #1c1310) 55%, var(--header-to, #130d0c) 100%);
    border-bottom: 3px solid var(--hs-red);
}
.site-header::before {                      /* cursor-follow glow */
    content: "";
    position: absolute; inset: 0;
    pointer-events: none;
    background: radial-gradient(340px 150px at var(--mx, 12%) 0%, color-mix(in srgb, var(--flame, #FF5A36) 30%, transparent), transparent 70%);
    transition: background .2s ease;
}

.header-bar {
    position: relative; z-index: 5;   /* above the USP bar so mega dropdowns overlay it */
    display: flex; align-items: center; gap: var(--sp-4);
    padding-block: var(--sp-3);
}

/* Logo chip. White by default, because the squash mark was drawn for paper and needs a light
   ground to read on the dark bar — but a logo that already carries its own background wants no
   chip at all, so the backdrop is a theme setting and "transparent" drops the padding and the
   shadow with it (both emitted together, so they cannot disagree). */
.brand {
    display: inline-flex; align-items: center; flex: none; text-decoration: none;
    background: var(--logo-backdrop, #fff);
    border-radius: 10px;
    padding: var(--logo-chip, 6px 12px);
    box-shadow: var(--logo-shadow, var(--shadow-sm));
}
.brand__logo { display: block; height: 40px; width: auto; }
@media (min-width: 720px) { .brand__logo { height: 58px; } }

/* Account / sign-out actions (e-commerce style icon buttons) */
.header-actions { display: flex; align-items: center; gap: 4px; flex: none; padding-left: var(--sp-2); }
.uitem-form { margin: 0; }
.uitem {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 8px 13px; border-radius: 11px; border: 1px solid transparent;
    font: inherit; font-size: var(--fs-300); font-weight: 600; cursor: pointer;
    color: rgba(255,255,255,.82); background: transparent; text-decoration: none;
    transition: background-color .2s, color .2s, transform .18s ease, box-shadow .2s;
}
.uitem svg { width: 19px; height: 19px; flex: none; }
.uitem:hover { background: rgba(255,255,255,.09); color: #fff; transform: translateY(-1px); }
/* Glows derive from the theme, never from a literal.
   These four box-shadows were written as rgba(255,90,54,...) and rgba(255,138,61,...) - which
   are exactly --flame and --flame-2 spelled out - so the pill took the site's palette while the
   halo around it stayed squash orange on every other site. A second league could set its whole
   palette and still be ringed in somebody else's brand. color-mix keeps the alpha without
   restating the colour. */
.uitem--primary {
    color: #fff; background: linear-gradient(90deg, var(--hs-red), var(--flame));
    box-shadow: 0 8px 22px -10px color-mix(in srgb, var(--flame, #FF5A36) 85%, transparent);
}
.uitem--primary:hover { color: #fff; border-color: #fff; transform: translateY(-1px); }

/* USP / value strip */
.usp-bar { position: relative; z-index: 1; background: rgba(0,0,0,.28); border-top: 1px solid rgba(255,255,255,.08); }
.usp { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px 56px;
       padding-block: 11px; font-size: .82rem; font-weight: 600; color: rgba(255,255,255,.9); }
.usp .u { display: inline-flex; align-items: center; gap: 10px; }
.usp svg { width: 18px; height: 18px; flex: none; color: var(--flame-2); }

/* Primary navigation — sits in the dark header bar, pushed to the right.
   Mobile: collapses behind a toggle into a full-width dropdown. Desktop:
   inline pills with a flame-gradient active state and mega dropdowns. */
.nav { margin-left: auto; }
.nav__list { list-style: none; margin: 0; padding: 0; }
.nav__link {
    display: block; text-decoration: none; font-weight: 600;
    color: rgba(255,255,255,.78); padding: 10px 14px; border-radius: 9px;
    transition: color .2s ease, background-color .2s ease, box-shadow .25s ease;
}
.nav__link:hover { color: #fff; background: rgba(255,255,255,.08); }
.nav__link[aria-current="page"] {
    color: #fff; background: linear-gradient(90deg, var(--hs-red), var(--flame));
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--flame-2, #FF8A3D) 45%, transparent),
                0 8px 24px -8px color-mix(in srgb, var(--flame, #FF5A36) 70%, transparent);
}

.nav__mega-list { list-style: none; margin: 0; padding: 0; }
.nav__mega-list a {
    display: block; text-decoration: none; color: rgba(255,255,255,.82);
    padding: 9px 14px; border-radius: 8px; font-size: var(--fs-200);
}
.nav__mega-list a:hover { background: rgba(255,255,255,.09); color: #fff; }
.nav__mega-list a[aria-current="page"] { color: #fff; font-weight: 600; }

.nav__toggle {
    display: inline-flex; align-items: center; gap: var(--sp-2); margin-left: auto;
    padding: var(--sp-2) var(--sp-3);
    background: transparent; color: #fff; border: 1px solid rgba(255,255,255,.45);
    border-radius: var(--radius-sm); font-weight: 600; cursor: pointer;
}
.nav__toggle-icon, .nav__toggle-icon::before, .nav__toggle-icon::after {
    content: ""; display: block; width: 18px; height: 2px; background: #fff;
}
.nav__toggle-icon { position: relative; }
.nav__toggle-icon::before { position: absolute; top: -6px; left: 0; }
.nav__toggle-icon::after  { position: absolute; top:  6px; left: 0; }

/* Mobile: dropdown menu hidden until toggled */
.nav__list { display: none; }
@media (max-width: 719px) {
    .nav__list {
        position: absolute; left: 0; right: 0; top: 100%; z-index: 60;
        background: var(--header-mid, #1c1310); border-top: 1px solid rgba(255,255,255,.12);
        padding: 8px 16px 14px; box-shadow: 0 20px 40px -16px rgba(0,0,0,.7);
    }
    .nav--open .nav__list { display: block; }
    .nav__item { display: block; }
    .nav__link { padding: 12px 12px; }
    .nav__mega-list a { padding-left: var(--sp-5); }
    .header-actions .uitem span { display: none; }   /* icon-only to save room */
    .header-actions .uitem { padding: 8px; }

    /* Mobile nav = accordion: sections collapse; only level 1 shows by default. */
    .nav__item--has-menu > .nav__link {
        display: flex; align-items: center; justify-content: space-between;
    }
    .nav__item--has-menu > .nav__link::after {
        content: ""; width: .5em; height: .5em; margin-left: var(--sp-3); opacity: .85;
        border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
        transform: rotate(45deg); transition: transform .2s ease;
    }
    .nav__item--has-menu.is-open > .nav__link::after { transform: rotate(-135deg); }
    .nav__item--has-menu > .nav__mega { display: none; }
    .nav__item--has-menu.is-open > .nav__mega { display: block; }

    /* USP strip: show 2 at a time (JS rotates them on a timer). */
    .usp { justify-content: center; gap: 8px 22px; font-size: .78rem; }
}
@media (min-width: 720px) {
    .nav__toggle { display: none; }
    /* The uneven pill heights were NOT caused here - the cause was the prose rule
       `li + li { margin-top }` reaching into the nav, and it is fixed at source near the top of
       this file. This comment used to blame `align-items: stretch`, which was wrong, and is
       corrected rather than deleted because the wrong explanation is the instructive part: a
       4px margin on every item except the first showed up as the FIRST item computing 4px
       taller, which looks like anything but a margin.

       These three rules stand on their own merits. `center` rather than `stretch` so an item's
       height never depends on its neighbours; `min-height: 44px` because that is the minimum
       comfortable touch target and a nav item should clear it whatever the font settings do. */
    .nav__list { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
    .nav__item { position: relative; display: flex; align-items: center; }
    .nav__link { display: flex; align-items: center; min-height: 44px; }
    .nav__mega {
        position: absolute; top: 100%; left: 0; min-width: 230px; z-index: 50;
        background: var(--header-mid, #1c1310); border: 1px solid rgba(255,255,255,.1);
        border-radius: 0 0 12px 12px; box-shadow: 0 20px 44px -18px rgba(0,0,0,.7);
        padding: 8px;
        opacity: 0; visibility: hidden; transform: translateY(-6px);
        transition: opacity .15s ease, transform .15s ease, visibility .15s;
    }
    .nav__item--has-menu:hover > .nav__mega,
    .nav__item--has-menu:focus-within > .nav__mega {
        opacity: 1; visibility: visible; transform: none;
    }
    .nav__mega-list a { white-space: nowrap; }
}

/* Main grid: stacks on mobile, left rail + main content from >=720.
   No right-hand column — any .right-rail content wraps full-width underneath,
   so the main content keeps the full width on wide screens. */
.main-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--sp-3);
    padding-block: var(--sp-4);
    align-items: start;     /* cards size to their content, don't stretch full width */
    align-content: start;   /* pack rows at the top — don't centre/space them in the tall main area */
}
/* Let grid items shrink below content width so wide tables scroll INSIDE their
   panel (via .table-wrap) instead of stretching the page sideways. */
.main-grid > * { min-width: 0; }

@media (min-width: 720px) {
    .main-grid { grid-template-columns: 220px 1fr; padding-block: var(--sp-5); gap: var(--sp-3); }
    .main-grid > .right-rail { grid-column: 1 / -1; } /* right rail wraps under, full width */

    /* A standalone article (no side rail) fills the whole content width;
       when a left rail is present the article sits in the second column so
       it doesn't get trapped in the narrow 220px rail track. */
    .main-grid > .article { grid-column: 1 / -1; }
    .main-grid > .left-rail ~ .article { grid-column: 2; }
    .main-grid > .breadcrumb { grid-column: 1 / -1; }
}

/* Content card — used by article and side panels.
   Two variants:
     .card        — padded body (default, suits prose & link lists)
     .card--flush — body extends to the card edges (suits subnav rows)
*/
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--sp-5);
    box-shadow: var(--shadow-sm);
    overflow: hidden;            /* keeps inset shadows & row hovers within radius */
}
.card + .card { margin-top: var(--sp-4); }
/* Mobile: no cards at all — content runs full-width as stacked sections, so a
   data-heavy site reclaims every pixel. Tables still scroll inside .table-wrap. */
@media (max-width: 719px) {
    .card {
        background: transparent; border: 0; border-radius: 0; box-shadow: none;
        padding: var(--sp-4) 0; overflow: visible;
    }
    .card + .card { margin-top: 0; border-top: 1px solid var(--border); }
}
.card--flush { padding: 0; }

.card__title {
    margin: 0 0 var(--sp-3);
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.card--flush .card__title {
    margin: 0;
    padding: var(--sp-4) var(--sp-5) var(--sp-3);
    border-bottom: 1px solid var(--border);
}

/* Sidebar nav (left rail) — clean continuous list, no chunky blocks. */
.subnav {
    list-style: none;
    margin: 0;
    padding: var(--sp-1) 0;
    display: block;
}
.subnav li + li > a { border-top: 1px solid var(--border); }
.subnav a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-5);
    color: var(--text);
    text-decoration: none;
    font-weight: 500;
    box-shadow: inset 0 0 0 0 var(--hs-red);   /* animatable left bar */
    transition: background-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.subnav a::after {
    content: "›";
    font-size: 1.1em;
    line-height: 1;
    color: currentColor;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity .15s ease, transform .15s ease;
}
.subnav a:hover {
    background: var(--surface-2);
    color: var(--hs-red);
}
.subnav a:hover::after { opacity: 0.6; transform: translateX(0); }
.subnav a[aria-current="page"] {
    background: var(--hs-red-soft);
    color: var(--hs-red);
    font-weight: 600;
    box-shadow: inset 3px 0 0 0 var(--hs-red);
}
.subnav a[aria-current="page"]::after { opacity: 1; transform: translateX(0); }

/* Right rail link list — quiet, underline-on-hover */
.linklist { list-style: none; margin: 0; padding: 0; }
.linklist li + li { margin-top: 2px; }
.linklist a {
    display: inline-block;
    color: var(--hs-blue);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    padding-block: 2px;
    transition: border-color .15s ease, color .15s ease;
}
.linklist a:hover {
    color: var(--hs-blue-hover);
    border-bottom-color: currentColor;
}

/* Division jump links (player rankings) */
.div-jump { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-3); }
.div-jump a {
    display: inline-block;
    padding: 4px 14px;
    border: 1px solid var(--border);
    border-radius: 999px;
    text-decoration: none;
    color: var(--hs-blue);
    font-size: var(--fs-200);
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.div-jump a:hover { background: var(--hs-red-soft); border-color: var(--hs-red); color: var(--hs-red); }

/* Breadcrumb — inline so every crumb sits on one baseline */
.breadcrumb { font-size: var(--fs-200); line-height: 1.5; }
.breadcrumb ol { list-style: none; margin: 0; padding: 0; }
.breadcrumb li { display: inline; }
.breadcrumb li + li::before { content: "›"; margin: 0 0.45rem; color: var(--text-muted); }
.breadcrumb a { color: var(--hs-blue); text-decoration: none; }
.breadcrumb a:hover { text-decoration: underline; }
.breadcrumb [aria-current="page"] { color: var(--text-muted); }

/* Article body */
.article > h1:first-child,
.article > h2:first-child { margin-top: 0; }
.article blockquote {
    margin: var(--sp-4) 0;
    padding: var(--sp-3) var(--sp-4);
    border-left: 4px solid var(--hs-red);
    background: var(--hs-red-soft);
    border-radius: 0 var(--radius) var(--radius) 0;
    font-style: italic;
}
.article blockquote p { margin: 0; }

/* Tables — keep the legacy cream feel, but cleaner */
.table-wrap { overflow-x: auto; }     /* mobile-safe horizontal scroll */
table.results,
table.standings {
    width: 100%; border-collapse: collapse; font-size: var(--fs-200);
}
table.results th, table.standings th,
table.results td, table.standings td {
    padding: var(--sp-2) var(--sp-3); text-align: left;
    border-bottom: 1px solid var(--cream-border, var(--border));
}
table.results thead th,
table.standings thead th {
    background: var(--hs-red);
    color: #fff;
    font-weight: 600;
    text-align: left;
    border-bottom: 0;
}
table.results tbody tr:nth-child(odd),
table.standings tbody tr:nth-child(odd) {
    background: var(--hs-cream);
}
/* Row hover has its own colour, and its own TEXT colour with it. It used to be a hardcoded
   #FFF1A8 here and --hs-red-soft in the admin tables — borrowing that worked until a site set
   the soft brand colour to something dark, at which point a hovered row turned dark under link
   text still coloured for a pale ground and stopped being readable. */
table.results tbody tr:hover,
table.standings tbody tr:hover {
    background: var(--row-hover, #FFF1A8);
    color: var(--row-hover-text, inherit);
}
table.results tbody tr:hover a,
table.standings tbody tr:hover a { color: var(--row-hover-text, inherit); }
table.results th.score, table.results td.score,
table.standings th.num, table.standings td.num {
    text-align: right; font-variant-numeric: tabular-nums;
}

/* Form pips (recent results) and Next-fixture badge */
.form-line { display: inline-flex; gap: 3px; }
.form-pip {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.3rem; height: 1.3rem; border-radius: 4px;
    font-size: 0.72rem; font-weight: 700; color: #fff;
}
.form-pip--w { background: #2e7d32; }
.form-pip--d { background: #9e9e9e; }
.form-pip--l { background: var(--hs-red); }
.next-cell { white-space: nowrap; }
.next-badge { display: inline-flex; align-items: center; gap: .4rem; font-size: var(--fs-200); }
.next-ha {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.3rem; height: 1.3rem; border-radius: 50%;
    background: var(--surface-2); border: 1px solid var(--border);
    font-size: 0.7rem; font-weight: 700; color: var(--text-muted);
}

/* Section heading — sits above grids of cards, doesn't need its own card */
.section-heading {
    margin: var(--sp-6) 0 var(--sp-4);
    padding-bottom: var(--sp-2);
    border-bottom: 2px solid var(--hs-red);
    color: var(--text);
    font-size: var(--fs-500);
}

.muted { color: var(--text-muted); }
.muted.small,
.small.muted,
.small { font-size: var(--fs-200); }
.lead { font-size: var(--fs-400); color: var(--text-muted); }

/* Champion cards — division winners hero. Mobile 1-col → tablet 2-col → desktop 4-col. */
.champions-grid {
    display: grid;
    gap: var(--sp-4);
    grid-template-columns: 1fr;
    margin-bottom: var(--sp-5);
}
@media (min-width: 540px) { .champions-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1080px) { .champions-grid { grid-template-columns: repeat(4, 1fr); } }

.champion {
    position: relative;
    background: linear-gradient(180deg, #fff 0%, var(--hs-red-soft) 100%);
    border: 1px solid var(--hs-cream-border);
    border-top: 4px solid var(--hs-red);
    border-radius: var(--radius);
    padding: var(--sp-5) var(--sp-4) var(--sp-4);
    text-align: center;
    box-shadow: var(--shadow-sm);
}
.champion__division {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--hs-red);
    margin-bottom: var(--sp-2);
}
.champion__trophy {
    display: block;
    font-size: 2rem;
    line-height: 1;
    margin-bottom: var(--sp-2);
    filter: saturate(1.1);
}
.champion__name {
    margin: 0 0 var(--sp-2);
    color: var(--text);
    font-size: var(--fs-500);
    line-height: 1.2;
}
.champion__line {
    margin: 0 0 var(--sp-3);
    color: var(--text-muted);
    font-size: var(--fs-200);
}
.champion__line strong { color: var(--text); }
.champion__line .dot { color: var(--border-strong); margin: 0 0.25em; }
.champion__points {
    margin: 0;
    font-size: var(--fs-700);
    font-weight: 800;
    color: var(--hs-red);
    line-height: 1;
}
.champion__points span {
    font-size: var(--fs-300);
    font-weight: 500;
    color: var(--text-muted);
    margin-left: 0.25em;
}
.champion .badge {
    position: absolute;
    top: var(--sp-3); right: var(--sp-3);
    background: var(--hs-red); color: #fff;
    padding: 2px 8px; border-radius: 999px;
    font-size: 0.7rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.05em;
}
.champion--undefeated {
    border-top-color: #B8860B;       /* gold */
}

/* Player of the season cards — same grid, lighter look */
.players-grid {
    display: grid;
    gap: var(--sp-4);
    grid-template-columns: 1fr;
    margin-bottom: var(--sp-5);
}
@media (min-width: 540px)  { .players-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1080px) { .players-grid { grid-template-columns: repeat(4, 1fr); } }

.player-card {
    padding: var(--sp-4);
    text-align: left;
}
.player-card__division {
    display: inline-block;
    font-size: 0.7rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--hs-red);
    margin-bottom: var(--sp-1);
}
.player-card__name {
    margin: 0 0 2px;
    color: var(--text);
    font-size: var(--fs-400);
}
.player-card__team {
    margin: 0 0 var(--sp-3);
    color: var(--text-muted);
    font-size: var(--fs-200);
}
.player-card__stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--sp-2);
    margin: 0;
    padding-top: var(--sp-3);
    border-top: 1px solid var(--border);
    font-size: var(--fs-100);
}
.player-card__stats > div { text-align: center; }
.player-card__stats dt {
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 0.65rem;
    margin-bottom: 2px;
}
.player-card__stats dd {
    margin: 0;
    color: var(--text);
    font-weight: 700;
    font-size: var(--fs-300);
    font-variant-numeric: tabular-nums;
}

/* Standings: highlight the leader row */
table.standings tbody tr.winner {
    background: var(--hs-red-soft);
    font-weight: 600;
}
table.standings tbody tr.winner td:first-child::after {
    content: " ★";
    color: var(--hs-red);
}
table.standings tbody tr.winner:hover {
    background: var(--hs-red-soft, #FFD9CF);
}

/* Forms */
.form { display: grid; gap: var(--sp-4); }
.form label { font-weight: 600; color: var(--text); display: block; margin-bottom: var(--sp-1); }
.form input[type="text"],
.form input[type="email"],
.form input[type="number"],
.form input[type="password"],
.form select,
.form textarea {
    width: 100%; padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: #fff;
}
.form input:focus,
.form select:focus,
.form textarea:focus {
    outline: 2px solid var(--hs-blue); outline-offset: 1px; border-color: var(--hs-blue);
}

.btn {
    display: inline-block; padding: var(--sp-2) var(--sp-5);
    background: var(--hs-red); color: #fff;
    border: 0; border-radius: var(--radius-sm);
    font-weight: 600; cursor: pointer;
    text-decoration: none;
}
.btn:hover { background: var(--hs-red-dark); color: #fff; }
.btn--ghost { background: transparent; color: var(--hs-red); border: 1px solid var(--hs-red); }
.btn--ghost:hover { background: var(--hs-red-soft); color: var(--hs-red-dark); }

/* Footer */
/* Footer — dark, to cohere with the header; flame accents on socials + signup. */
.site-footer {
    background: linear-gradient(180deg, var(--footer-from, #1c1310) 0%, var(--footer-to, #130d0c) 100%);
    color: var(--footer-text, #C9C2BD);
    border-top: 3px solid var(--hs-red);
    margin-top: var(--sp-6);
}
.site-footer a { color: var(--footer-link, #E7E1DC); text-decoration: none; }
.site-footer a:hover { color: #fff; }
.site-footer h4 {
    color: #fff; font-size: .8rem; letter-spacing: .12em; text-transform: uppercase;
    margin: 0 0 var(--sp-3);
}

.footer-grid {
    display: grid; gap: var(--sp-5) var(--sp-6);
    grid-template-columns: 1fr;
    padding-block: var(--sp-6);
}
@media (min-width: 600px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 980px) { .footer-grid { grid-template-columns: 1.5fr 1fr 1fr 1.6fr; } }

.footer-brand p { margin: 0 0 var(--sp-3); color: var(--footer-muted, #A89F98); font-size: var(--fs-200); max-width: 32ch; }
.brand--footer {
    /* Same chip as the header's, from the same setting. It was a second hardcoded #fff, so
       setting the logo backdrop to transparent cleared the white box at the top of the page
       and left an identical one at the bottom. */
    background: var(--logo-backdrop, #fff); box-shadow: var(--logo-shadow, none);
    border-radius: 12px; padding: 10px 16px; display: inline-flex; margin-bottom: var(--sp-4);
}
.brand--footer .brand__logo { height: 76px; width: auto; display: block; max-width: 100%; }

.footer-col .linklist a { color: var(--footer-text, #C9C2BD); }
.footer-col .linklist a:hover { color: #fff; }
.linklist--row { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); }

/* social icons */
.socials { display: flex; gap: 10px; }
.social {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 50%;
    border: 1px solid rgba(255,255,255,.22); color: var(--footer-link, #E7E1DC);
    transition: background .2s, border-color .2s, color .2s, transform .18s ease, box-shadow .2s;
}
.social svg { width: 18px; height: 18px; }
.social:hover {
    color: #fff; transform: translateY(-2px); border-color: transparent;
    background: linear-gradient(135deg, var(--hs-red), var(--flame));
    box-shadow: 0 8px 20px -8px color-mix(in srgb, var(--flame, #FF5A36) 70%, transparent);
}

/* newsletter signup */
.newsletter-form { display: grid; gap: var(--sp-2); max-width: 22rem; }
.newsletter-form input {
    width: 100%; padding: 10px 12px; font: inherit;
    border: 1px solid rgba(255,255,255,.18); border-radius: 8px;
    background: rgba(255,255,255,.06); color: #fff;
}
.newsletter-form input::placeholder { color: var(--footer-muted, #9a918b); }
.newsletter-form input:focus { outline: 2px solid var(--flame); outline-offset: 1px; border-color: transparent; }
.btn--flame {
    width: 100%; border: 0; color: #fff;
    background: linear-gradient(90deg, var(--hs-red), var(--flame));
    box-shadow: 0 8px 20px -10px color-mix(in srgb, var(--flame, #FF5A36) 80%, transparent);
}
.btn--flame:hover { filter: brightness(1.06); transform: translateY(-1px); }

/* bottom bar */
.footer-bottom { border-top: 1px solid rgba(255,255,255,.1); }
.footer-bottom__inner {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: var(--sp-2) var(--sp-4); padding-block: var(--sp-4);
    font-size: var(--fs-100); color: var(--footer-muted, #8C837D);
}
.footer-bottom__inner p { margin: 0; }
.footer-bottom a { color: var(--footer-muted, #8C837D); }
.footer-bottom a:hover { color: #fff; }

/* Print */
@media print {
    .site-header, .site-footer, .left-rail, .right-rail { display: none; }
    .main-grid { grid-template-columns: 1fr; }
    .card { border: 0; box-shadow: none; padding: 0; }
}

/* Forms — contact form etc. */
.form { display: grid; gap: var(--sp-4); max-width: 38rem; margin-top: var(--sp-4); }
.form__row { display: grid; gap: var(--sp-1); }
.form__row label { font-weight: 600; font-size: var(--fs-200); }
/* Checkboxes and radios are excluded deliberately. This rule stretched them to the full width
   of the grid cell and gave them a text field's padding, which rendered the box adrift in the
   middle of the row with its label shoved to the far edge and wrapping. A tick box is not a
   field you type into: it keeps its intrinsic size and sits immediately left of its words. */
.form input:not([type="checkbox"]):not([type="radio"]),
.form textarea {
    width: 100%;
    padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: #fff;
}
.form select {
    width: 100%;
    padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: #fff;
    font: inherit;
}
.form input:focus,
.form select:focus,
.form textarea:focus { outline: 2px solid var(--hs-blue); outline-offset: 1px; border-color: var(--hs-blue); }
.form textarea { resize: vertical; }

/* Result entry form */
.result-form select,
.result-form input[type="date"] {
    width: 100%;
    max-width: 28rem;
    padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: #fff;
    font: inherit;
}
.result-form select:focus,
.result-form input:focus { outline: 2px solid var(--hs-blue); outline-offset: 1px; border-color: var(--hs-blue); }
.rubber__players { display: grid; gap: var(--sp-3); margin-bottom: var(--sp-4); }
@media (min-width: 560px) { .rubber__players { grid-template-columns: 1fr 1fr; } }
.games-input { display: flex; flex-wrap: wrap; gap: var(--sp-4); }
.game-input { display: flex; flex-direction: column; gap: 4px; }
.game-input__no { font-size: var(--fs-100); color: var(--text-muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; }
.game-input__scores { display: flex; align-items: center; gap: 10px; }

/* The row scored by different rules from the ones above it. A padel rubber's last row is a
   championship tie-break to 10 played to two clear, not a third set, so its heading is longer
   than "Set 2" and carries the rule underneath: a captain about to type 6-4 has to be able to
   read that BEFORE typing it, not learn it from a refusal afterwards. Darkened rather than
   coloured, because nothing here is an error. None of it fires for squash — SquashParFormat
   returns one constant label, no detail and no decider. */
.game-input--decider .game-input__no { color: var(--text); }
.game-input__rule {
    display: block;
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
    color: var(--text-muted);
}

/* Entering a scorecard is 8 to 40 taps on a phone at a club, so these are sized as touch
   targets rather than as text inputs: 3.25rem wide and one padding unit tall was hard to hit.
   4.75rem and a 2.75rem minimum height clears the usual 44px guidance with room to spare, and
   the larger type makes a mistyped score visible without leaning in. */
.game-input__scores input {
    width: 4.75rem; min-height: 2.75rem; text-align: center;
    padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font: inherit; font-size: 1.15rem; font-variant-numeric: tabular-nums;
}
.game-input__scores input:focus { outline: 2px solid var(--hs-blue); outline-offset: 1px; border-color: var(--hs-blue); }

/* An out-of-range score is shown WHILE typing. min/max on a number input only bite on submit,
   so the field looked as though it accepted anything and only complained after the whole card
   had been filled in. :invalid also catches a non-numeric entry. Not applied until the field
   has been touched, or every empty box would be red on arrival. */
.game-input__scores input:user-invalid {
    border-color: var(--hs-red, #a8202f);
    background: color-mix(in srgb, var(--hs-red, #a8202f) 7%, transparent);
}

/* Hide the spin buttons: on a scorecard they sit exactly where a thumb lands and nudge a
   score by one, and every browser draws them differently. Keyboard arrows still work. */
.game-input__scores input::-webkit-outer-spin-button,
.game-input__scores input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.game-input__scores input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.game-input__sep { color: var(--text-muted); font-weight: 600; }
.field-error { color: var(--hs-red); font-size: var(--fs-100); }
.form__errors:not(:empty) {
    color: var(--hs-red);
    background: var(--hs-red-soft);
    border: 1px solid var(--hs-red);
    border-radius: var(--radius);
    padding: var(--sp-3);
}
.form__errors ul { margin: 0; padding-left: 1.2em; }
/* ASP.NET validation summary renders even when valid — hide it until there are errors */
.validation-summary-valid { display: none; }

.btn {
    display: inline-block;
    background: var(--hs-red);
    color: #fff;
    border: 0;
    border-radius: var(--radius);
    padding: var(--sp-3) var(--sp-5);
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    transition: background-color .15s ease;
}
.btn:hover { background: var(--hs-red-hover, #a83232); }
.btn--ghost {
    background: transparent;
    color: var(--hs-red);
    border: 1px solid var(--hs-red);
}
.btn--ghost:hover { background: var(--hs-red-soft); }

/* Honeypot — visually and from-AT hidden, but still in the DOM for bots */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Expandable team-result match rows */
.match {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    margin-bottom: var(--sp-3);
    background: var(--surface);
}
.match[open] { box-shadow: var(--shadow-sm); }
.match__summary {
    list-style: none;
    cursor: pointer;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--sp-2) var(--sp-4);
    padding: var(--sp-3) var(--sp-4);
}
.match__summary::-webkit-details-marker { display: none; }
.match__summary::before {
    content: "▸";
    color: var(--hs-red);
    transition: transform .15s ease;
}
.match[open] .match__summary::before { content: "▾"; }
.match__summary:hover { background: var(--surface-2); }
.match__date { min-width: 6.5rem; color: var(--text-muted); font-size: var(--fs-200); }
.match__teams { flex: 1 1 auto; }
.match__score { margin: 0 var(--sp-1); color: var(--hs-red); }
.match__meta { font-size: var(--fs-100); }
.match__detail { border-top: 1px solid var(--border); padding: var(--sp-2) var(--sp-3) var(--sp-3); }
table.rubbers { width: 100%; border-collapse: collapse; font-size: var(--fs-200); }
table.rubbers th, table.rubbers td { padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--border); text-align: left; }
table.rubbers .score { text-align: right; white-space: nowrap; }
table.rubbers .num { text-align: center; width: 2rem; color: var(--text-muted); }
.winner-cell { font-weight: 600; }
.win-tag {
    display: inline-block;
    background: var(--hs-red);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
    border-radius: var(--radius-sm);
    padding: 0 6px;
    margin-left: 4px;
}
.games { color: var(--text-muted); font-weight: 400; margin-left: var(--sp-2); }

/* Highlight the filtered team in the fixtures table */
table.results td.is-team { font-weight: 700; color: var(--hs-red); }

/* News list */
.news-item { padding-block: var(--sp-4); border-top: 1px solid var(--border); }
.news-item:first-of-type { border-top: 0; }
.news-item__date { color: var(--text-muted); font-size: var(--fs-100); margin: 0 0 var(--sp-1); }
/* Bodies are sanitised HTML from the editor, so no pre-line: block elements
   provide their own spacing and pre-line would double it. */
.news-item__body > :first-child { margin-top: 0; }
.news-item__body > :last-child { margin-bottom: 0; }
.news-item__body h2 { font-size: var(--fs-400); margin: var(--sp-4) 0 var(--sp-1); }
.news-item__body h3 { font-size: var(--fs-300); margin: var(--sp-3) 0 var(--sp-1); }
.news-item__body h4 { font-size: var(--fs-200); margin: var(--sp-3) 0 var(--sp-1); }
.news-item__body ul,
.news-item__body ol { padding-left: 1.4rem; margin: var(--sp-2) 0; }
.news-item__body li { margin: .25rem 0; }
.news-item__body blockquote {
    margin: var(--sp-2) 0;
    padding: var(--sp-1) var(--sp-3);
    border-left: 3px solid var(--border);
    color: var(--text-muted);
}
.news-item__body img { max-width: 100%; height: auto; display: block; margin: var(--sp-3) 0; }
.news-item__body hr { border: 0; border-top: 1px solid var(--border); margin: var(--sp-4) 0; }
.news-item__body table { border-collapse: collapse; width: 100%; margin: var(--sp-3) 0; }
.news-item__body th,
.news-item__body td { border: 1px solid var(--border); padding: .4rem .6rem; text-align: left; }

/* Clubs & Teams — single panel, one section per club */
.club { padding-top: var(--sp-4); margin-top: var(--sp-4); border-top: 1px solid var(--border); }
.club h2 { margin: 0 0 var(--sp-2); }
.team-list { list-style: none; margin: var(--sp-2) 0 0; padding: 0; }
.team-list li { padding: var(--sp-2) 0; }
.team-list li + li { border-top: 1px solid var(--border); }

/* Visually-hidden (screen-reader only) */
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Search field */
.search { position: relative; max-width: 26rem; }
.search__input {
    width: 100%;
    padding: var(--sp-3) var(--sp-4) var(--sp-3) 2.75rem;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    font-size: var(--fs-300);
    color: var(--text);
    box-shadow: var(--shadow-sm);
    transition: border-color .15s ease, box-shadow .15s ease;
    appearance: none;
}
.search__input::placeholder { color: var(--text-muted); }
.search__input:hover { border-color: var(--border-strong); }
.search__input:focus {
    outline: none;
    border-color: var(--hs-blue);
    box-shadow: 0 0 0 3px rgb(14 77 139 / 0.15);
}
.search::before {
    content: "";
    position: absolute;
    left: 0.95rem; top: 50%;
    width: 1.05rem; height: 1.05rem;
    transform: translateY(-50%);
    background-color: var(--text-muted);
    pointer-events: none;
    -webkit-mask: var(--search-icon) center / contain no-repeat;
    mask: var(--search-icon) center / contain no-repeat;
    --search-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");
}

/* External-link & document (PDF/Word/Excel) indicators.
   Automatic: any absolute http(s) link gets an "external" arrow; any link to a
   document gets a document icon. Icons are masked to currentColor so they
   match the link colour (white in the nav, blue in body text).
   The `i` flag makes the extension match case-insensitive, so an uppercase
   .PDF or .XLSX gets an icon too. */
a[href^="http://"]::after,
a[href^="https://"]::after,
a[href$=".pdf" i]::after,
a[href$=".doc" i]::after,
a[href$=".docx" i]::after,
a[href$=".xls" i]::after,
a[href$=".xlsx" i]::after {
    content: "";
    display: inline-block;
    width: 0.85em;
    height: 0.85em;
    margin-left: 0.3em;
    vertical-align: -0.05em;
    background-color: currentColor;
    -webkit-mask: var(--link-icon) center / contain no-repeat;
    mask: var(--link-icon) center / contain no-repeat;
}
a[href^="http://"]::after,
a[href^="https://"]::after {
    --link-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3Cpolyline points='15 3 21 3 21 9'/%3E%3Cline x1='10' y1='14' x2='21' y2='3'/%3E%3C/svg%3E");
}
a[href$=".pdf" i]::after,
a[href$=".doc" i]::after,
a[href$=".docx" i]::after,
a[href$=".xls" i]::after,
a[href$=".xlsx" i]::after {
    --link-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3Cline x1='16' y1='13' x2='8' y2='13'/%3E%3Cline x1='16' y1='17' x2='8' y2='17'/%3E%3Cline x1='10' y1='9' x2='8' y2='9'/%3E%3C/svg%3E");
}
/* Don't draw an icon on image links, the brand logo, or social icon buttons.
   (a.social beats the a[href^="https://"] external-link rule on specificity.) */
a:has(> img)::after,
.brand::after,
a.social::after { content: none !important; }

/* Print */
@media print {
    .site-header, .site-footer, .left-rail, .right-rail { display: none; }
    .main-grid { grid-template-columns: 1fr; }
    .card { border: 0; box-shadow: none; padding: 0; }
}

/* Reduced-motion respect */
@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; animation: none !important; }
}

/* ==================================================================== */
/*  ===== Admin =====                                                   */
/*  Dense, professional back-office presentation layer.                 */
/*  Scoped under `.admin` (the page <article>). Its navigation is the   */
/*  header bar's own .nav rules. Reuses the site's existing tokens —    */
/*  no second palette. Presentation only; no markup logic depends on    */
/*  these rules. Public pages are untouched (nothing here is global).   */
/* ==================================================================== */

/* ---- Page shell -------------------------------------------------- */
.admin { color: var(--text); }
.admin > h1 { margin-bottom: var(--sp-2); }
.admin > h1 + .muted { margin-top: 0; }
.admin h2 {
    font-size: var(--fs-400);
    color: var(--text);
    margin: 0 0 var(--sp-3);
    padding-bottom: var(--sp-2);
    border-bottom: 2px solid var(--hs-red);
}
.admin .card { padding: var(--sp-4) var(--sp-5); }
@media (max-width: 719px) { .admin .card { padding: var(--sp-4) 0; } }
.admin .card > h1:first-child,
.admin .card > h2:first-child { margin-top: 0; }

/* Card / section header: title on the left, optional actions on the right */
.admin .card__head {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: var(--sp-3); flex-wrap: wrap;
    margin-bottom: var(--sp-3);
}
.admin .card__head .card__title,
.admin .card__head h2 { margin: 0; padding: 0; border: 0; }
.admin .card__head p { margin: 0; }

/* ---- Buttons: compact, auto-width, never full-bleed -------------- */
.admin .btn,
.left-rail .btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .35rem;
    width: auto;
    padding: .42rem .85rem;
    border-radius: var(--radius-sm);
    font-size: var(--fs-200);
    font-weight: 600;
    line-height: 1.25;
    white-space: nowrap;
    vertical-align: middle;
}
.admin .btn:focus-visible,
.left-rail .btn:focus-visible { outline: 2px solid var(--hs-blue); outline-offset: 2px; }

/* Primary = filled brand red (inherits global .btn colours) */
.admin .btn--primary { background: var(--hs-red); color: #fff; }

/* Secondary / ghost recoloured to a calm neutral so the red primary leads */
.admin .btn--ghost,
.left-rail .btn--ghost {
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border-strong);
}
.admin .btn--ghost:hover,
.left-rail .btn--ghost:hover {
    background: var(--surface-2);
    border-color: var(--text-muted);
    color: var(--text);
}

/* Danger = ghost red, only warms up on hover */
.admin .btn--danger {
    background: var(--surface);
    color: var(--hs-red);
    border: 1px solid var(--border-strong);
}
.admin .btn--danger:hover {
    background: var(--hs-red-soft);
    border-color: var(--hs-red);
    color: var(--hs-red-dark);
}

/* Size + icon variants */
.admin .btn--sm { padding: .3rem .6rem; font-size: var(--fs-100); }
.admin .btn--icon {
    padding: 0; width: 1.85rem; height: 1.85rem; font-size: 1rem; line-height: 1;
}

/* ---- Toolbars / inline action clusters --------------------------- */
.admin .row-actions,
.admin .form__actions {
    display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
}
.admin .row-actions { gap: .35rem; }
.admin .row-actions form { display: inline-flex; gap: .35rem; margin: 0; }

/* Per-user actions read as one cluster that wraps, not a single line that overflows. A user row
   can carry six of them - impersonate, approver, sign out everywhere, new claim code, delete -
   and on a laptop they pushed the table sideways. Wrapping keeps every action reachable without
   a horizontal scroll, and aligning to the start stops a wrapped last button sitting alone on
   the right where it reads as a different control. */
.admin td .row-actions { justify-content: flex-start; row-gap: .35rem; }
.admin td form[method="post"] { flex-wrap: wrap; }
/* A form's action row is a right-aligned toolbar, not a stretched button */
.admin .form__actions { justify-content: flex-end; margin-top: var(--sp-3); }

/* ---- Forms: tighter rhythm, consistent field height -------------- */
.admin .form { gap: var(--sp-3); max-width: 46rem; }
.admin .form__row { gap: 4px; }
.admin .form label,
.admin .field > label {
    font-size: var(--fs-100);
    font-weight: 700;
    letter-spacing: .02em;
    color: var(--text-muted);
    margin: 0;
}
/* checkbox / radio rows read as a normal inline label, not a heading */
.admin .form label:has(input[type="checkbox"]),
.admin .form label:has(input[type="radio"]),
.admin .check {
    display: inline-flex; align-items: center; gap: .45rem;
    font-size: var(--fs-200); font-weight: 600; color: var(--text);
    text-transform: none; letter-spacing: 0;
}

/* Visual field styling (no width here — width is set per-context below so
   fixed-width inputs like the score boxes keep their own sizing). */
.admin input:not([type]),
.admin input[type="text"],
.admin input[type="email"],
.admin input[type="number"],
.admin input[type="password"],
.admin input[type="url"],
.admin input[type="date"],
.admin select,
.admin textarea {
    padding: .4rem .6rem;
    font-size: var(--fs-200);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: #fff;
    color: var(--text);
}
.admin textarea { resize: vertical; line-height: var(--lh-body); }
/* Full-width inside stacked field contexts only */
.admin .form input[type="text"],
.admin .form input[type="email"],
.admin .form input[type="number"],
.admin .form input[type="password"],
.admin .form input[type="url"],
.admin .form input[type="date"],
.admin .form select,
.admin .form textarea,
.admin .field > input,
.admin .field > select,
.admin .field > textarea,
.admin .editor-row__fields input[type="text"],
.admin .editor-row__fields textarea { width: 100%; }
.admin input:focus,
.admin select:focus,
.admin textarea:focus {
    outline: 2px solid var(--hs-blue); outline-offset: 1px; border-color: var(--hs-blue);
}

/* Field building blocks */
.admin .field { display: grid; gap: 3px; min-width: 0; }
.admin .field--inline { grid-auto-flow: column; align-items: center; gap: .45rem; }
.admin .field--inline > label { white-space: nowrap; }
/* width utilities need to out-specify the input[type=…] rule above */
.admin input.input--xs,
.admin select.input--xs { width: 4.5rem; }
.admin input.input--sm,
.admin select.input--sm { width: 8rem; }

/* A select whose options are NAMES, not numbers.
   This one was on .input--xs - 4.5rem, the width meant for a two-digit score box - so a list of
   "Team (Club)" options rendered as "- ca" and the placeholder overflowed the control entirely.
   It sizes to its content instead, with a floor wide enough to read the longest club name and a
   ceiling so one long entry cannot push the row's buttons off the table. */
.admin select.input--pick {
    width: auto;
    min-width: 13rem;
    max-width: 22rem;
}

/* Two (or more) related fields on one row */
.admin .field-row {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3);
}
@media (max-width: 560px) { .admin .field-row { grid-template-columns: 1fr; } }

/* ---- List editors as compact rows (coaches, club news, USPs) ----- */
.admin .editor-list { display: grid; gap: var(--sp-2); margin: 0 0 var(--sp-4); }
.admin .editor-row {
    display: grid; gap: var(--sp-2);
    padding: var(--sp-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
}
.admin .editor-row__fields { display: grid; gap: var(--sp-2); margin: 0; }
.admin .editor-row__foot {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--sp-3); flex-wrap: wrap;
}
.admin .editor-row__foot .row-actions { margin-left: auto; }

/* Compact single-line row for icon+text pairs (Appearance USPs) */
.admin .inline-row {
    display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap;
}
.admin .inline-row select { width: auto; flex: 0 0 auto; }
.admin .inline-row input[type="text"],
.admin .inline-row input { flex: 1 1 16rem; }

/* ---- Data tables: calm, dense, light headers --------------------- */
.admin table.standings,
.admin table.results { font-size: var(--fs-200); }
.admin table.standings thead th,
.admin table.results thead th {
    background: var(--surface-2);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: var(--fs-100);
    font-weight: 700;
    border-bottom: 1px solid var(--border);
}
.admin table.standings th,
.admin table.results th,
.admin table.standings td,
.admin table.results td {
    padding: .45rem .6rem;
    vertical-align: middle;
    border-bottom: 1px solid var(--border);
}
/* replace the legacy cream zebra with a quiet neutral one */
.admin table.standings tbody tr:nth-child(odd),
.admin table.results tbody tr:nth-child(odd) { background: transparent; }
.admin table.standings tbody tr:nth-child(even),
.admin table.results tbody tr:nth-child(even) { background: var(--surface-2); }
/* The admin tables keep their own former literal as the var() fallback, so a site that has not
   set a hover colour renders exactly as it did. */
.admin table.standings tbody tr:hover,
.admin table.results tbody tr:hover {
    background: var(--row-hover, #FBE9E5);
    color: var(--row-hover-text, inherit);
}
.admin table.standings tbody tr:hover a,
.admin table.results tbody tr:hover a { color: var(--row-hover-text, inherit); }
.admin table td form { margin: 0; }
.admin table td input[type="date"] { min-width: 9rem; }

/* status tags used in queues */
.admin .tag {
    display: inline-block; padding: 1px 8px; border-radius: 999px;
    font-size: var(--fs-100); font-weight: 700; letter-spacing: .02em;
}
.admin .tag--ok { background: #E5F3E6; color: #1f7a24; }
.admin .tag--muted { background: var(--surface-2); color: var(--text-muted); }
.admin .tag--warn { background: var(--hs-red-soft); color: var(--hs-red-dark); }

/* alerts (some pages already emit .alert markup) */
.admin .alert {
    margin: 0 0 var(--sp-4); padding: var(--sp-3) var(--sp-4);
    border-radius: var(--radius-sm); font-size: var(--fs-200);
    border: 1px solid transparent;
}
.admin .alert--ok { background: #E5F3E6; color: #1f7a24; border-color: #bfe1c1; }
.admin .alert--error { background: var(--hs-red-soft); color: var(--hs-red-dark); border-color: var(--hs-red); }
.admin .alert--error:empty { display: none; }

/* Contrast warning under a colour swatch (Appearance). The colour is a literal,
   not a brand token: this text has to stay readable precisely when the palette
   being edited is the problem. Empty until the page script fills it in. */
.admin .contrast-warn {
    margin: 2px 0 0;
    font-size: var(--fs-100);
    font-weight: 600;
    color: #9C2415;
}
.admin .contrast-warn:empty { display: none; }

/* The admin's own navigation is no longer a left rail: inside /admin the header bar
   renders the admin sections through the same .nav / .nav__mega rules as the public
   nav (see _Layout + Services/AdminNav.cs), so there is nothing to style here. The
   .left-rail rules above stay because the public home page still uses one. */


/* A tick box sits at the start of its row, at its own size, with the words beside it. The
   label is the flex container (see the :has rule above), so this only has to stop the input
   growing and keep it from being dragged down by a wrapped second line of text. */
.form input[type="checkbox"],
.form input[type="radio"] {
    flex: none;
    width: auto;
    margin: 0;
    align-self: start;
    accent-color: var(--hs-red);
}
.admin .form label:has(input[type="checkbox"]),
.admin .form label:has(input[type="radio"]) {
    justify-content: flex-start;
    align-items: start;
    cursor: pointer;
}
