/* ==========================================================================
   Braidwood Sports, depth and motion layer. Loaded after app.css on every page.
   Colour, depth and animation only: it never changes the layout (sizes, order and spacing stay as designed).
   Every colour comes from a token in tokens.css, so light and dark both work. Motion is finite (no endless
   CSS animation in the app) and is switched off for people who ask for reduced motion.
   Owner: shell lane.
   ========================================================================== */

/* ---- Fonts and type ------------------------------------------------------ */
.page-title, .section-title, .pub-title, .dialog__title, .sheet__title, .empty__title, .signin__brand,
.tile__value, .side-nav__brand, .top-bar__title, .join-legend, h1, h2, h3 {
  font-family: var(--font-display); font-optical-sizing: auto; letter-spacing: -.012em;
}
.page-title, .pub-title { font-weight: 800; letter-spacing: -.02em; }
.tile__value { font-weight: 800; letter-spacing: -.02em; }
::selection { background: var(--selected-bg); color: var(--text); }
* { scrollbar-width: thin; scrollbar-color: var(--control-line) transparent; }

/* ---- The page: deep colour with soft light, never a flat fill ---------------- */
body { background: var(--page); }
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background: var(--page-mesh);
}
.pub, .app { position: relative; }
.pub { background: transparent; }

/* ---- Surfaces: lit from above, hairline edge, soft layered shadow ------------ */
.card, .list, .tile, .attention-item, .status-block, .empty, .error-panel, .skeleton__row, .pub-steps,
.panel {
  background: var(--grad-card);
  box-shadow: var(--edge-light), var(--ring), var(--shadow-1);
}
.panel { background: var(--panel); }
.list, .tile, .attention-item, .status-block, .card { border-radius: var(--r-lg); }
.dialog, .sheet, .tip__body {
  background: var(--grad-card); border: 1px solid var(--glass-line);
  box-shadow: var(--edge-light), var(--shadow-3);
}
.sheet { border-bottom: 0; }
@media (hover: hover) and (pointer: fine) {
  a.row:hover, button.row:hover, .nav-list__link:hover { background: var(--selected-bg); }
}

/* ---- Cards you can press lift towards you ---------------------------------- */
.tile, .attention-item, .join-plan, .mem-card {
  transition: transform var(--dur-3) var(--ease-out), box-shadow var(--dur-3) var(--ease-out), border-color var(--dur-2) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  a.tile:hover, a.attention-item:hover, .join-plan:hover {
    transform: translateY(-3px);
    box-shadow: var(--edge-light), 0 0 0 1px var(--glow-cyan), 0 14px 34px -10px var(--glow), var(--shadow-2);
  }
}
a.tile:active, a.attention-item:active { transform: translateY(0) scale(.99); }

/* ---- 3D tilt (fx.js sets --rx --ry --mx --my while a pointer is over a [data-tilt] or .tile) ---------- */
.tile, [data-tilt] { position: relative; }
@media (hover: hover) and (pointer: fine) {
  .tile, [data-tilt] {
    transform: perspective(900px) translateY(var(--lift, 0px)) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
    transform-style: preserve-3d; will-change: transform;
  }
  .tile[data-tilting], [data-tilt][data-tilting] { transition: transform 60ms linear, box-shadow var(--dur-3) var(--ease-out); --lift: -3px; }
  .tile::after, [data-tilt]::after {
    content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0;
    background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 0%), var(--glare), transparent 65%);
    transition: opacity var(--dur-3) var(--ease);
  }
  .tile[data-tilting]::after, [data-tilt][data-tilting]::after { opacity: 1; }
}

/* ---- Buttons ----------------------------------------------------------------- */
.btn { position: relative; overflow: hidden; isolation: isolate;
  transition: background var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease), transform var(--dur-2) var(--ease-spring), box-shadow var(--dur-3) var(--ease-out); }
.btn:active { transform: scale(.975); }
.btn--primary {
  background: var(--grad-brand); color: var(--on-primary);
  box-shadow: var(--edge-light), 0 8px 22px -8px var(--glow);
}
.btn--primary:hover { background: var(--grad-brand-hover); box-shadow: var(--edge-light), 0 12px 28px -8px var(--glow); }
.btn--primary::after { /* a single sheen sweep when the pointer arrives */
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; translate: -120% 0;
  background: linear-gradient(105deg, transparent 30%, var(--glare) 50%, transparent 70%);
}
@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover::after { translate: 120% 0; transition: translate 700ms var(--ease-out); }
  .btn--primary:hover { transform: translateY(-1px); }
  .btn--primary:active { transform: scale(.975); }
}
.btn--secondary { background: var(--secondary-bg); box-shadow: var(--edge-light), var(--ring); }
.btn--outline:hover { background: var(--secondary-bg); }
.btn--danger { box-shadow: var(--edge-light), 0 8px 22px -10px var(--danger-fill); }

/* ---- Inputs ------------------------------------------------------------------- */
.input, .select, .textarea, .search__input {
  box-shadow: inset 0 1px 2px rgba(0,0,0,.06);
  transition: border-color var(--dur-2) var(--ease), box-shadow var(--dur-3) var(--ease-out), background var(--dur-2) var(--ease);
}
.input:focus-visible, .select:focus-visible, .textarea:focus-visible, .search__input:focus-visible {
  box-shadow: 0 0 0 4px var(--glow-cyan);
}

/* ---- Chips and segmented choices ---------------------------------------------- */
.chip { transition: background var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease), transform var(--dur-2) var(--ease-spring); }
.chip:active { transform: scale(.96); }
.chip[aria-pressed="true"], .seg__opt input:checked + span { background: var(--selected-bg); box-shadow: 0 0 18px -6px var(--glow); }
.chip__count { background: var(--grad-brand); }
.seg__opt span { transition: background var(--dur-2) var(--ease); }

/* ---- Avatars: a colour of their own (fx.js sets --h from the name) ---------------- */
.avatar {
  /* A solid colour under the gradient (its far end), so the initials always have a known background behind them. */
  background: linear-gradient(140deg, hsl(var(--h, 160) var(--avatar-sat) var(--avatar-l1)), hsl(calc(var(--h, 160) + 38) var(--avatar-sat) var(--avatar-l2))) hsl(calc(var(--h, 160) + 38) var(--avatar-sat) var(--avatar-l2));
  color: var(--avatar-text); box-shadow: 0 0 0 2px var(--glass-line), 0 4px 12px -4px var(--glow);
}

/* ---- Navigation ---------------------------------------------------------------- */
.bottom-nav {
  background: var(--glass); border-top: 1px solid var(--glass-line);
  -webkit-backdrop-filter: blur(20px) saturate(1.5); backdrop-filter: blur(20px) saturate(1.5);
  box-shadow: 0 -10px 30px -12px rgba(0,0,0,.25);
}
.nav-item { transition: color var(--dur-2) var(--ease); }
.nav-item__icon { transition: background var(--dur-3) var(--ease), box-shadow var(--dur-3) var(--ease), transform var(--dur-3) var(--ease-spring); }
.nav-item:active .nav-item__icon { transform: scale(.9); }
.nav-item[aria-current="page"] .nav-item__icon {
  background: var(--grad-brand); color: var(--on-primary);
  box-shadow: 0 6px 16px -6px var(--glow); animation: bw-pop var(--dur-4) var(--ease-spring);
}
.nav-badge { box-shadow: 0 0 0 2px var(--panel), 0 2px 8px -2px var(--bad-line); }
.top-bar {
  background: var(--glass); border-bottom: 1px solid var(--glass-line);
  -webkit-backdrop-filter: blur(20px) saturate(1.5); backdrop-filter: blur(20px) saturate(1.5);
}
/* overflow stays visible so the crest's glow is never cut into a box (Grant, 18 Oct 2026): the name and page lines trim themselves. */
.top-bar__title { display: flex; align-items: center; gap: var(--sp-2); overflow: visible; }
.top-bar__logo { flex: none; display: inline-flex; font-size: 15px; }
.top-bar__title-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
@media (min-width: 768px) {
  .side-nav { background: var(--grad-side); border-right: 1px solid var(--glass-line); box-shadow: 8px 0 40px -24px rgba(0,0,0,.35); }
  .side-nav__brand { padding-top: var(--sp-1); gap: var(--sp-3); font-size: var(--fs-lg); font-weight: 800; }
  .side-nav .nav-item { position: relative; transition: background var(--dur-2) var(--ease), color var(--dur-2) var(--ease), transform var(--dur-3) var(--ease-out); }
  .side-nav .nav-item:hover { background: var(--selected-bg); transform: translateX(3px); }
  .side-nav .nav-item[aria-current="page"] { background: linear-gradient(90deg, var(--selected-bg), transparent 110%); box-shadow: inset 0 0 0 1px var(--glass-line); }
  .side-nav .nav-item[aria-current="page"]::before {
    content: ""; position: absolute; left: -12px; top: 22%; bottom: 22%; width: 4px; border-radius: 0 4px 4px 0;
    background: var(--grad-brand); box-shadow: 0 0 14px var(--glow);
  }
  .side-nav .nav-item[aria-current="page"] .nav-item__icon { color: var(--accent-text); }
}

/* ---- Theme button (top bar, side navigation, public pages) ------------------------------------- */
.theme-btn {
  position: relative; flex: none; width: var(--tap); height: var(--tap); border-radius: var(--r-pill); display: grid; place-items: center;
  border: 1px solid var(--glass-line); background: var(--glass); color: var(--text); cursor: pointer;
  box-shadow: var(--edge-light); transition: transform var(--dur-3) var(--ease-spring), box-shadow var(--dur-3) var(--ease-out);
}
.theme-btn:hover { box-shadow: var(--edge-light), 0 0 18px -4px var(--glow); }
.theme-btn:active { transform: scale(.92) rotate(-12deg); }
.theme-btn > span { position: absolute; inset: 0; display: grid; place-items: center; transition: transform var(--dur-4) var(--ease-spring), opacity var(--dur-3) var(--ease); }
.theme-btn svg { width: 22px; height: 22px; }
/* the icon shown is the one you would switch TO: a sun in dark, a moon in light */
.theme-btn .theme-btn__moon { opacity: 0; transform: rotate(-70deg) scale(.4); }
.theme-btn[aria-pressed="true"] .theme-btn__sun { opacity: 1; transform: none; }
.theme-btn[aria-pressed="true"] .theme-btn__moon { opacity: 0; transform: rotate(-70deg) scale(.4); }
.theme-btn[aria-pressed="false"] .theme-btn__sun { opacity: 0; transform: rotate(70deg) scale(.4); }
.theme-btn[aria-pressed="false"] .theme-btn__moon { opacity: 1; transform: none; }
.theme-btn .theme-btn__sun { color: var(--gold); }
.theme-btn .theme-btn__moon { color: var(--cyan); }
.top-bar__theme { margin-left: auto; }
.side-nav__brand-row { display: flex; align-items: center; gap: var(--sp-2); padding-right: var(--sp-1); }
.side-nav__brand-row .side-nav__brand { flex: 1; min-width: 0; }

/* ---- Status: the colour comes from components.css; here only the red states glow a little ----------- */
.p-pill--failed, .p-pill--arrears { box-shadow: 0 0 14px -6px var(--bad-line); }
.p-pill--paid { box-shadow: 0 0 12px -7px var(--ok-line); }

/* ---- Tiles: figures in brand colour ----------------------------------------------------------------- */
.tile__value { background: var(--grad-text); -webkit-background-clip: text; background-clip: text; color: var(--accent-text); -webkit-text-fill-color: transparent; }
.tile--alert .tile__value { background: none; color: var(--bad-fg); }
.tile--attention { border-left-color: var(--gold); }
.tile::before { /* a short bar of brand colour above each figure */
  content: ""; position: absolute; left: var(--sp-4); top: 0; width: 28px; height: 3px; border-radius: 0 0 3px 3px;
  background: var(--grad-brand); box-shadow: 0 0 12px var(--glow);
}
.tile--attention::before { background: var(--grad-gold); box-shadow: 0 0 12px var(--gold); }
.tile--alert::before { background: var(--bad-line); box-shadow: 0 0 12px var(--bad-line); }
.attention-item__count { background: var(--grad-brand); color: var(--on-primary); box-shadow: 0 4px 12px -4px var(--glow); }
.pub-badge { box-shadow: 0 0 0 6px var(--glass-line), 0 10px 30px -8px var(--glow); }
.empty__icon { background: var(--grad-card); box-shadow: var(--ring), 0 8px 24px -8px var(--glow-cyan); }
.empty__icon--ok { background: var(--ok-bg); box-shadow: 0 0 0 6px var(--glass-line), 0 10px 26px -8px var(--glow); }
.error-panel { border-left-color: var(--gold); }

/* ---- Sign-in and public pages: the logo takes the stage -------------------------------------------------- */
.pub-top { background: var(--glass); border-bottom: 1px solid var(--glass-line);
  -webkit-backdrop-filter: blur(20px) saturate(1.5); backdrop-filter: blur(20px) saturate(1.5); position: sticky; top: 0; z-index: var(--z-nav); }
/* Sign-in: the bar only holds the theme switch. The logo is centred with the form. */
.pub-top--gate { background: transparent; border-bottom: 0; box-shadow: none; position: absolute; inset: 0 0 auto 0;
  -webkit-backdrop-filter: none; backdrop-filter: none; }
.pub--gate .pub-main { padding-top: calc(56px + env(safe-area-inset-top)); }
.pub--gate .pub-foot__in { justify-content: center; }
.pub--gate .pub-foot__brand { max-width: 100%; justify-content: center; text-align: center; }
@media (max-width: 520px) {
  .pub--gate .pub-foot__brand { flex-direction: column; }
}
.pub-top__logo { width: 32px; height: 32px; flex: none; filter: drop-shadow(0 2px 8px var(--glow)); }
.pub-crest { background: var(--grad-brand); color: var(--on-primary); box-shadow: 0 6px 16px -6px var(--glow); }
.pub-foot { background: var(--glass); }
.pub-foot__brand { display: inline-flex; align-items: center; gap: var(--sp-2); }
.pub-foot__logo { width: 22px; height: 22px; }
.pub-top__end { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }
.join-plan:has(input:checked), .join-plan[aria-checked="true"] { box-shadow: 0 0 0 1px var(--accent-text), 0 14px 34px -14px var(--glow); }
.signin { position: relative; overflow: visible; }
/* Flex, not grid: a grid item sizes to the picture's full width (the file is much wider than it is drawn), so the
   lockup sat on the left of the form. An explicit width keeps the drawn size, and the column centres that box. */
.signin__hero { display: flex; flex-direction: column; align-items: center; gap: var(--sp-3); text-align: center; }
.signin__hero > a,
.signin__hero > .brand,
.signin__hero .brand--stacked { display: block; width: min(200px, 100%); max-width: 100%; line-height: 0; }
.signin__brand { background: var(--grad-text); -webkit-background-clip: text; background-clip: text; color: var(--accent-text); -webkit-text-fill-color: transparent; font-weight: 800; font-size: var(--fs-xl); }
@media (min-width: 768px) {
  .signin, .mem-signin { background: var(--grad-card); border: 1px solid var(--glass-line); box-shadow: var(--edge-light), 0 30px 80px -30px var(--glow), var(--shadow-3); }
}
/* One size for every sign-in lockup: wide enough to read, narrow enough to sit inside the form on a phone. */
.signin__hero .brand--stacked .brand__img { width: 100%; height: auto; max-width: 100%; }
/* The floating theme control sits in the top corner. On a narrow phone the lockup starts below it. */
@media (max-width: 420px) {
  .app--bare .signin { margin-top: calc(var(--sp-9) + env(safe-area-inset-top)); }
}

/* ---- Sheets, dialogs, toasts: springy arrival ------------------------------------------------------------- */
.scrim { -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.sheet { animation: bw-sheet-spring var(--dur-4) var(--ease-spring); }
@media (min-width: 768px) { .sheet { animation: bw-dialog-spring var(--dur-4) var(--ease-spring); } }
.toast { animation: bw-sheet-spring var(--dur-4) var(--ease-spring); border: 1px solid var(--toast-line); box-shadow: var(--shadow-3); }
.sheet__grip { background: var(--grad-brand); opacity: .8; }
.sheet-action { transition: background var(--dur-2) var(--ease), transform var(--dur-3) var(--ease-out); }
.sheet-action:hover { transform: translateX(3px); }

/* ---- Entrance: each screen rises into place, one block after another ------------------------------------ */
.main > *, .pub-main > * { animation: bw-fade-in var(--dur-4) var(--ease-out) both; } /* opacity only: a transform on an ancestor would move fixed bars inside the screen */
.main > :nth-child(2), .pub-main > :nth-child(2) { animation-delay: 60ms; }
.main > :nth-child(3), .pub-main > :nth-child(3) { animation-delay: 120ms; }
.main > :nth-child(4), .pub-main > :nth-child(4) { animation-delay: 180ms; }
.main > :nth-child(n+5), .pub-main > :nth-child(n+5) { animation-delay: 240ms; }
.tiles > .tile { animation: bw-rise var(--dur-4) var(--ease-out) both; }
.tiles > .tile:nth-child(2) { animation-delay: 70ms; } .tiles > .tile:nth-child(3) { animation-delay: 140ms; } .tiles > .tile:nth-child(4) { animation-delay: 210ms; }
.signin__hero, .signin > form { animation: bw-rise var(--dur-4) var(--ease-out) both; }
.signin > form { animation-delay: 120ms; }

/* ---- Loading: a slow sheen across the placeholders ------------------------------------------------------------ */
.skeleton__dot, .skeleton__line, .skeleton__pill {
  background-image: linear-gradient(100deg, transparent 20%, var(--glare) 50%, transparent 80%); background-size: 220% 100%; background-repeat: no-repeat;
  animation: bw-sheen 1.4s linear infinite;
}

@keyframes bw-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes bw-rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@keyframes bw-pop { 0% { transform: scale(.7); } 60% { transform: scale(1.12); } 100% { transform: scale(1); } }
@keyframes bw-sheet-spring { from { transform: translateY(40px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes bw-dialog-spring { from { transform: translateY(14px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes bw-sheen { from { background-position: 160% 0; } to { background-position: -60% 0; } }

/* ---- Reduced motion: everything lands instantly, nothing tilts or sweeps ---------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; animation-delay: 0ms !important; animation-iteration-count: 1 !important; transition-duration: 1ms !important; }
  .tile, [data-tilt] { transform: none !important; }
  .btn--primary::after { display: none; }
}

/* ---- floating theme button (sign-in: no top bar) ---- */
.theme-float { position: fixed; top: calc(var(--sp-3) + env(safe-area-inset-top)); right: var(--sp-3); z-index: var(--z-nav); }
.top-bar .theme-btn { margin-left: auto; }
.top-bar .theme-btn + .top-bar__action { margin-left: 0; }

/* ---- Sticky tool bars: nothing behind them at rest, so no box shows over the page glow (Grant, 18 Oct 2026). Once pinned
   (.is-stuck, from pinWhenStuck in core/ui.js) they sit on glass so the rows scrolling under them blur away. ---- */
.list-tools, .pay-tools { background: transparent; transition: background-color var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease); }
.list-tools.is-stuck, .pay-tools.is-stuck {
  background: var(--glass); box-shadow: 0 1px 0 var(--glass-line);
  -webkit-backdrop-filter: blur(16px) saturate(1.4); backdrop-filter: blur(16px) saturate(1.4);
}
.los-unlock__bar { background: var(--glass); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); border-top-color: var(--glass-line); }

/* ---- High-contrast / forced-colours: gradient text and glow fall back to plain system colours ---- */
@media (forced-colors: active) {
  .tile__value, .signin__brand, .side-nav__wordmark { background: none; color: CanvasText; -webkit-text-fill-color: currentColor; }
  .btn--primary, .attention-item__count, .nav-item[aria-current="page"] .nav-item__icon, .pub-crest { background: ButtonFace; color: ButtonText; border: 1px solid ButtonText; }
  body::before { display: none; }
}
/* The Last One Standing trophy is the one gold icon in the navigation */
.nav-item[data-nav="los"] .nav-item__icon svg { color: var(--gold); }
.nav-item[data-nav="los"][aria-current="page"] .nav-item__icon svg { color: var(--accent-text); }
.bottom-nav .nav-item[data-nav="los"][aria-current="page"] .nav-item__icon svg { color: var(--on-primary); }

/* Gradient fills keep a plain colour underneath (older browsers, forced colours, and anything that reads the colour) */
.btn--primary, .pub-crest, .attention-item__count, .chip__count { background-color: var(--primary); }
.nav-item[aria-current="page"] .nav-item__icon { background-color: var(--primary); }

/* ============================ THE LOGO ============================================================
   Grant's 2026 logo (15 Oct 2026; docs/BRAND.md), as outlined SVGs: a version for dark backgrounds (silver lettering, bright
   mint) and one for light backgrounds (navy lettering, deeper green), swapped with the theme. public/img/brand/v2/:
     .brand            on one line: braidwood-horizontal-on-dark / -on-light
     .brand--stacked   the B above the name: braidwood-stacked-on-dark / -on-light (sign-in, 404)
     .brand--mark      the B alone: braidwood-mark-on-dark / -on-light (tight spaces, 32px and up)
   Size it with font-size: the one-line logo is 2.4em tall (13.6em wide, about as wide as the old two-line logo). */
.brand { display: inline-flex; align-items: center; text-decoration: none; line-height: 0; font-size: 1rem; }
.brand__img { display: block; height: 2.4em; width: auto; max-width: 100%; }
.brand--stacked .brand__img { height: 6.2em; }
.brand--mark .brand__img { height: 2.4em; }
.brand__img--light { display: none; }
:root[data-theme="light"] .brand__img--dark { display: none; }
:root[data-theme="light"] .brand__img--light { display: block; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .brand__img--dark { display: none; }
  :root:not([data-theme="dark"]) .brand__img--light { display: block; }
}

/* the brand in each place it appears */
.side-nav__brand { display: block; min-width: 0; flex: none; } /* top-aligned: the menu follows straight after; Club settings and Account stay at the foot */
.side-nav__brand .brand { display: block; }
.side-nav__brand .brand__img { width: 100%; height: auto; max-width: 230px; }
.side-nav__brand-row { flex-wrap: wrap; row-gap: var(--sp-2); }
.side-nav__brand-row .side-nav__brand { flex: 1 1 100%; }
.pub-top .brand { font-size: .85rem; }
@media (max-width: 479px) { .pub-top .brand { font-size: .66rem; } }
.pub-foot .brand { font-size: .66rem; }

/* ---- the club's own look: its logo, a bigger name, and a glow in its colour that fades into the page (dark: into navy, light: into white) */
:root { --club-c: var(--club, var(--primary)); }
.side-nav { background:
  radial-gradient(130% 34% at 0% 0%, color-mix(in srgb, var(--club-c) 30%, transparent), transparent 70%),
  var(--grad-side, var(--surface)); }
/* Dark and Light: one full-width row under the logo, each half centred with its icon. Small to look at, still 44px tall to tap. */
.theme-pair { display: flex; gap: 4px; align-self: stretch; margin: 2px 0 var(--sp-3); padding: 3px; border-radius: var(--r-pill, 999px);
  background: color-mix(in srgb, var(--text) 5%, transparent); border: 1px solid var(--line); }
.theme-pair__btn { flex: 1 1 0; display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 44px; margin: -6px 0; padding: 0 8px;
  border: 0; border-radius: var(--r-pill, 999px); background: transparent; color: var(--text-2);
  font: inherit; font-size: var(--fs-sm, .875rem); font-weight: 600; cursor: pointer; transition: color .15s; }
.theme-pair__btn > span, .theme-pair__btn > svg { pointer-events: none; }
.theme-pair__btn svg { width: 16px; height: 16px; flex: none; }
.theme-pair__btn[data-mode="dark"] svg { color: #8fb4ff; }
:root[data-theme="light"] .theme-pair__btn[data-mode="dark"] svg { color: #3f63c9; }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) .theme-pair__btn[data-mode="dark"] svg { color: #3f63c9; } }
:root[data-theme="light"] .theme-pair__btn[data-mode="light"] svg { color: #c98a0b; }
.theme-pair__btn[data-mode="light"] svg { color: #f2b53a; }
.theme-pair__btn:hover { color: var(--text); }
.theme-pair__btn[aria-pressed="true"] { color: var(--text);
  background: linear-gradient(180deg, color-mix(in srgb, var(--raised) 80%, #fff 8%), var(--raised)) no-repeat center / 100% 32px; }
.theme-pair__btn:focus-visible { outline: 2px solid var(--focus, var(--primary)); outline-offset: -4px; }
.side-nav__clubcard { display: flex; align-items: center; gap: var(--sp-3); padding: 0 var(--sp-1) var(--sp-4); min-width: 0; }
.side-nav__clubcard .side-nav__club { padding: 0; margin: 0; font-family: var(--font-display); font-size: 1.2rem; font-weight: 800; line-height: 1.15; color: var(--text);
  overflow-wrap: break-word; hyphens: manual; min-width: 0; } /* between words only: never "Carrickshor / e FC" (Grant, 22 Oct 2026) */
.club-logo { flex: none; width: var(--cs, 56px); height: var(--cs, 56px); object-fit: contain; border-radius: 14px;
  filter: drop-shadow(0 0 14px color-mix(in srgb, var(--club-c) 70%, transparent)) drop-shadow(0 0 3px color-mix(in srgb, var(--club-c) 50%, transparent)); }
/* A club with no logo: its initials on a tile in its colour (Braidwood green when it has chosen none), with a lit edge and the same glow. */
.club-crest { flex: none; display: grid; place-items: center; width: var(--cs, 48px); height: var(--cs, 48px); border-radius: calc(var(--cs, 48px) * .27);
  font-family: var(--font-display, inherit); font-size: calc(var(--cs, 48px) * .36); font-weight: 800; letter-spacing: .02em; line-height: 1; user-select: none;
  color: var(--club-on, var(--on-primary)); background-color: var(--club-c);
  background-image: linear-gradient(145deg, color-mix(in srgb, var(--club-c) 78%, #fff), var(--club-c) 52%, color-mix(in srgb, var(--club-c) 72%, #000));
  position: relative; box-shadow: inset 0 1px 0 rgb(255 255 255 / .35), inset 0 -6px 10px rgb(0 0 0 / .14); }
/* The tile's glow is its own layer (a shadow on ::after, outside the tile only), so it can breathe by opacity and size alone, which the
   browser animates on the graphics chip with no repaint. Static by default; moving only for people who have not asked for less motion. */
.club-crest::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: 0 0 18px color-mix(in srgb, var(--club-c) 45%, transparent); }
@media (prefers-reduced-motion: no-preference) {
  .club-crest::after { animation: club-glow-breathe 5s ease-in-out infinite; }
  /* A logo (a picture) casts its glow with a drop-shadow that follows its outline, so there the colour and spread of that same shadow
     ease in and out by a small amount. Same slow 5 second loop, so the two kinds of club mark breathe together. */
  .club-logo { animation: club-logo-breathe 5s ease-in-out infinite; }
}
@keyframes club-glow-breathe { 0%, 100% { opacity: .7; transform: scale(1); } 50% { opacity: 1; transform: scale(1.07); } }
@keyframes club-logo-breathe {
  0%, 100% { filter: drop-shadow(0 0 14px color-mix(in srgb, var(--club-c) 70%, transparent)) drop-shadow(0 0 3px color-mix(in srgb, var(--club-c) 50%, transparent)); }
  50% { filter: drop-shadow(0 0 18px color-mix(in srgb, var(--club-c) 90%, transparent)) drop-shadow(0 0 3px color-mix(in srgb, var(--club-c) 50%, transparent)); }
}
/* ---- A club's own colours: the frame, never the controls ----------------------------------------------------------------------------
   The club's colour is its identity. It paints the frame: the bar beside the current menu item and the glow round the crest
   (.has-club-colour), and, with .club-frame (the pages members see always; the admin app while CLUB_COLOURS_IN_APP is on), the phone's
   top bar, the band behind the crest in the side menu, a tint down the menu and the join page band. Buttons, chosen options, headings and
   links stay Braidwood green for every club, and status colours are never the club's, so Approve never looks like Failed (Grant,
   17 Oct 2026). The colours come from the club palette and core/club-colour.js picks the shade for each theme (the bar shows at 3:1 on
   every surface, text on a band reads at 4.5:1). Light first, then dark (the two dark blocks match). */
:root.has-club-colour { --club-mark: var(--cl-mark); --club-wash: var(--cl-wash); --club-edge: var(--cl-edge); --club-accent: var(--cl-accent); }
@media (prefers-color-scheme: dark) {
  :root.has-club-colour:not([data-theme="light"]) { --club-mark: var(--cd-mark); --club-wash: var(--cd-wash); --club-edge: var(--cd-edge); --club-accent: var(--cd-accent); }
}
:root.has-club-colour[data-theme="dark"] { --club-mark: var(--cd-mark); --club-wash: var(--cd-wash); --club-edge: var(--cd-edge); --club-accent: var(--cd-accent); }

/* The club's second colour as an accent (Grant, 19 Oct 2026, mock-up 3 "Accent headings"): a short bar under each section heading and along
   the top of each figure tile, in --club-accent (club-colour.js: the second colour, or the main one when there is none, at 3:1 on every
   surface). Only a bar: the heading words, buttons and statuses keep their own colours. */
.has-club-colour .sec__t { padding-bottom: 10px; background: linear-gradient(var(--club-accent), var(--club-accent)) no-repeat left bottom / 36px 4px; }
.has-club-colour .subsec__t { padding-bottom: 8px; background: linear-gradient(var(--club-accent), var(--club-accent)) no-repeat left bottom / 28px 3px; }
.has-club-colour .stat { box-shadow: inset 0 4px 0 var(--club-accent); }
/* The icon tiles beside list rows wear the club's colour (Grant, 22 Oct 2026: "the icons here would look cool if they were also themed"):
   Club settings, the Last One Standing games list and the membership types on the join page and My membership. Decoration only, never a
   control: --club-mark is the shade of the club's colour that is 3:1 on every surface in this theme (club-colour.js), with a faint tint of
   it behind. Section headings, buttons and statuses stay Braidwood green. */
.has-club-colour :is(.set-ico, .los-game__ico, .mem-t__ico) { color: var(--club-mark); background: color-mix(in srgb, var(--club-mark) 14%, transparent); }

/* The member's header as a band in the club's colours (Grant, 19 Oct 2026, mock-up A): the main colour, a stripe of the second colour along
   its foot, the avatar ringed in it and the crest faint in the corner. The Status and Payment tags sit straight on the band: each has its own
   solid background, so they keep their own colours exactly (the dark tray behind them is gone, Grant, 19 Oct 2026). */
.club-frame .mm-who { position: relative; overflow: hidden; padding: var(--sp-4); border-radius: var(--r-lg); color: var(--club-on);
  background: linear-gradient(160deg, var(--club) 0%, var(--club-end) 100%); box-shadow: inset 0 -5px 0 var(--club-2), inset 0 0 0 1px var(--club-edge); }
.club-frame .mm-who::after { content: ""; position: absolute; right: -24px; top: -24px; width: 150px; height: 150px; pointer-events: none;
  background: var(--club-logo, none) no-repeat center / contain; opacity: .16; }
.club-frame .mm-who > * { position: relative; z-index: 1; }
.club-frame .mm-who .page-title { color: var(--club-on); }
.club-frame .mm-who > .avatar { box-shadow: 0 0 0 3px var(--club-2); }
.club-frame .mm-who__tags { color: var(--club-on); }
.club-frame .mm-who__mem { color: var(--club-on); }
.club-frame .mm-who .mm-rel { color: var(--club-on); text-decoration-color: color-mix(in srgb, var(--club-on) 60%, transparent); }

/* The current menu item: a neutral highlight and a thin bar in the club colour (on the left in the side menu, along the top of the phone's
   tab). Only the bar is the club's, so a red club never has a red block beside the red attention number. */
.has-club-colour .nav-item[aria-current="page"] .nav-item__icon { background: var(--secondary-bg); color: var(--text); box-shadow: none; }
.has-club-colour .bottom-nav .nav-item[aria-current="page"]::before { content: ""; position: absolute; top: 0; left: 22%; right: 22%; height: 3px;
  border-radius: 0 0 3px 3px; background: var(--club-mark); }
.has-club-colour .nav-item[data-nav="los"][aria-current="page"] .nav-item__icon svg { color: var(--gold); }
@media (min-width: 768px) {
  .has-club-colour .side-nav .nav-item[aria-current="page"] { background: linear-gradient(90deg, var(--secondary-bg), transparent 110%); }
  .has-club-colour .side-nav .nav-item[aria-current="page"]::before { background: var(--club-mark); box-shadow: none; }
  .has-club-colour .side-nav .nav-item[aria-current="page"] .nav-item__icon { color: var(--text); }
}

/* A band in the club colour: its text in the colour that reads on it, a gentle gradient that only moves further from that text colour, and
   a fine edge when it would otherwise melt into the page (white on light, black on dark). */
.club-frame .top-bar {
  color: var(--club-on); background: linear-gradient(160deg, var(--club) 0%, var(--club-end) 100%);
  box-shadow: inset 0 0 0 1px var(--club-edge);
}
/* On a band the crest's glow (and the initials tile) take the band's text colour, since the club colour would vanish into the band: a soft
   white halo on red, a dark one on amber, still breathing. */
.club-frame .top-bar { --club-c: var(--club-on); }
.club-frame .top-bar .club-crest { color: var(--club); background-image: none; }

/* The phone's top bar is the band: the club's name and the page in the band's text colour, and its buttons on their own solid chips. */
.club-frame .top-bar { border-bottom: 0; -webkit-backdrop-filter: none; backdrop-filter: none; }
.club-frame .top-bar__clubname, .club-frame .top-bar__page, .club-frame .top-bar__title-text { color: var(--club-on); }
/* The light/dark button on a club's top bar (the app's and the members' pages), and the bar's other buttons (Switch club, Account), are
   see-through: their icon or words and a ring in the bar's own text colour, so the bar shows through them and they stay clear on every club
   colour (Grant, 18 Oct 2026). The usual gold sun and cyan moon would
   vanish on a yellow, amber or sky blue bar, so on a club's bar both are the text colour: --club-on on the club's band (chosen to read on it
   at 4.5:1, core/club-colour.js), the menu's light text on the members' dark top bar. */
.club-frame .top-bar .theme-btn, .club-frame .top-bar .btn { --bar-ink: var(--club-on); }
.club-frame .pub-top .theme-btn { --bar-ink: var(--text); }
.club-frame .top-bar .theme-btn, .club-frame .pub-top .theme-btn, .club-frame .top-bar .btn { background: transparent; box-shadow: none;
  color: var(--bar-ink); border: 1.5px solid color-mix(in srgb, var(--bar-ink) 70%, transparent); }
.club-frame .top-bar .btn:hover { background: color-mix(in srgb, var(--bar-ink) 12%, transparent); }
.club-frame .top-bar .theme-btn .theme-btn__sun, .club-frame .top-bar .theme-btn .theme-btn__moon,
.club-frame .pub-top .theme-btn .theme-btn__sun, .club-frame .pub-top .theme-btn .theme-btn__moon { color: var(--bar-ink); }
.club-frame .top-bar :focus-visible { outline-color: var(--club-on); }

/* The whole menu in the club's colours (Grant, 18 Oct 2026: "the whole thing is supposed to be themed"): on a computer the side menu, on a
   phone the tab bar, and the top bar of the pages members see, are a gradient from near black at the left edge to the club colour at the
   right edge, where the page picks the colour up and lets it fade (option A of the mock-ups, Grant 18 Oct 2026, with the dark end made
   darker). Light text, in light and dark alike. The club colour is at most 34% of the mix, so even a white or yellow club keeps the menu
   text at 4.5:1 or better (test/unit/club-palette.test.js). The current item is filled with the club colour itself, in the colour that
   reads on it, with a fine light ring so a navy or black club still shows, and a soft glow. The tokens are set again inside the menu, so
   everything in it (the theme pair, badges, the account line) reads on the dark gradient. */
.club-frame .side-nav, .club-frame .bottom-nav, .club-frame .pub-top {
  --club-night: #02050E;
  color-scheme: dark;
  --text: #F4F7FC; --text-2: #D5DEEE; --text-3: #BAC6DC; --text-body: #E3E9F5;
  --line: rgba(255,255,255,.14); --control-line: rgba(255,255,255,.4);
  --secondary-bg: rgba(255,255,255,.10); --secondary-hover: rgba(255,255,255,.16);
  --card: rgba(255,255,255,.07); --raised: rgba(255,255,255,.12); --panel: transparent;
  --accent-text: #5CE6A0; /* the dark theme's own green: links stay Braidwood green, readable on the dark menu */
  color: var(--text);
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--club) 5%, var(--club-night)) 0%,
    color-mix(in srgb, var(--club) 16%, var(--club-night)) 55%,
    color-mix(in srgb, var(--club) 34%, var(--club-night)) 100%);
  border-color: transparent;
}
.club-frame .side-nav .nav-item, .club-frame .bottom-nav .nav-item { color: var(--text-2); }
.club-frame .side-nav .nav-item:hover { background: rgba(255,255,255,.08); color: var(--text); }
/* the current item: filled with the club colour */
.club-frame .side-nav .nav-item[aria-current="page"] {
  background: linear-gradient(160deg, var(--club) 0%, var(--club-end) 100%); color: var(--club-on);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.3), 0 0 24px color-mix(in srgb, var(--club) 55%, transparent);
}
.club-frame .side-nav .nav-item[aria-current="page"]::before { display: none; }
.club-frame .side-nav .nav-item[aria-current="page"] .nav-item__icon,
.club-frame .side-nav .nav-item[aria-current="page"] .nav-item__icon svg,
.club-frame .side-nav .nav-item[aria-current="page"] svg { color: var(--club-on); background: none; }
.club-frame .bottom-nav .nav-item[aria-current="page"] { color: var(--text); }
.club-frame .bottom-nav .nav-item[aria-current="page"]::before { display: none; }
.club-frame .bottom-nav .nav-item[aria-current="page"] .nav-item__icon {
  background: linear-gradient(160deg, var(--club) 0%, var(--club-end) 100%); color: var(--club-on);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.3), 0 0 18px color-mix(in srgb, var(--club) 55%, transparent);
}
.club-frame .bottom-nav .nav-item[aria-current="page"] .nav-item__icon svg { color: var(--club-on); }

/* On the dark menu the Braidwood logo and the Dark/Light icons are always their on-dark versions, in light theme too. */
:root.club-frame .side-nav .brand__img--dark, :root.club-frame .pub-top .brand__img--dark { display: block; }
:root.club-frame .side-nav .brand__img--light, :root.club-frame .pub-top .brand__img--light { display: none; }
:root.club-frame .side-nav .theme-pair__btn[data-mode="dark"] svg { color: #8fb4ff; }
:root.club-frame .side-nav .theme-pair__btn[data-mode="light"] svg { color: #f2b53a; }

/* The side menu's club card: frosted glass over the gradient, the club's crest in its own colour (Grant's mock-up, 18 Oct 2026). */
@media (min-width: 768px) {
  .club-frame .side-nav__clubcard { margin: var(--sp-1) 0 var(--sp-3); padding: var(--sp-3); border-radius: var(--r-lg);
    background: linear-gradient(135deg, rgba(255,255,255,.16), rgba(255,255,255,.05));
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.16), 0 10px 26px rgba(0,0,0,.28); }
  .club-frame .side-nav__clubcard .side-nav__club { color: var(--text); }
}

/* The phone's top bar, like the join page band in the hero: the sport's pitch drawn faintly in the band's text colour. */
.club-frame .top-bar { position: sticky; overflow: hidden; }
.club-frame .top-bar::after { content: ""; position: absolute; right: -24px; bottom: -16px; width: 190px; aspect-ratio: 400 / 260; pointer-events: none;
  opacity: .16; background: var(--club-on); -webkit-mask: var(--sport-pitch, url("/img/sports/football.svg")) center / 100% 100% no-repeat;
  mask: var(--sport-pitch, url("/img/sports/football.svg")) center / 100% 100% no-repeat; }
.club-frame .top-bar > * { position: relative; z-index: 1; }

/* The pages members see: their top bar is the same dark gradient as the admin menu (in the menu block above), with no rule under it. */
.club-frame .pub-top { border-bottom: 0; }
/* the page itself picks up a faint wash of the club colour at the top */
.has-club-colour body { background-image: radial-gradient(90% 50% at 15% -10%, color-mix(in srgb, var(--club-c) 18%, transparent), transparent 65%); background-attachment: fixed; }
/* In the club frame the page carries the colour too (option A, Grant 18 Oct 2026). On a phone a glow from the top, under the club's top bar;
   on a computer the page picks the colour up where the side menu ends and lets it fade, with a glow in the top left corner and a fainter one
   top right, so there is no line between the menu and the page. Softer in light than in dark. Behind the content only: cards, forms and
   statuses keep their own colours. */
:root.club-frame { --club-glow: 24%; --club-glow-edge: 18%; }
@media (prefers-color-scheme: dark) { :root.club-frame:not([data-theme="light"]) { --club-glow: 46%; --club-glow-edge: 32%; } }
:root.club-frame[data-theme="dark"] { --club-glow: 46%; --club-glow-edge: 32%; }
.club-frame body { background-image: linear-gradient(180deg, color-mix(in srgb, var(--club) var(--club-glow-edge), transparent) 0px, transparent 380px),
  radial-gradient(160% 70% at 50% 0%, color-mix(in srgb, var(--club) var(--club-glow), transparent), transparent 78%);
  background-attachment: fixed; }
@media (min-width: 768px) {
  .club-frame body { background-image:
    linear-gradient(90deg, color-mix(in srgb, var(--club) var(--club-glow-edge), transparent) var(--side-nav-w), transparent calc(var(--side-nav-w) + 240px)),
    radial-gradient(90% 80% at 0% 0%, color-mix(in srgb, var(--club) var(--club-glow), transparent), transparent 70%),
    radial-gradient(55% 40% at 100% 0%, color-mix(in srgb, var(--club-end) 16%, transparent), transparent 70%); }
  /* the pages members see have no side menu: the glow comes down from their top bar instead */
  .club-frame body:has(.pub) { background-image:
    radial-gradient(90% 70% at 0% 0%, color-mix(in srgb, var(--club) var(--club-glow), transparent), transparent 70%),
    radial-gradient(55% 40% at 100% 0%, color-mix(in srgb, var(--club-end) 16%, transparent), transparent 70%); }
}
/* the pages members see paint their own background, which would hide the glow */
.club-frame .pub { background: transparent; }
.pub-top .club-logo, .pub-top .club-crest { --cs: 44px; border-radius: 10px; }
/* phone top bar: the club's logo and name, the page under it */
.top-bar__clublogo { --cs: 44px; border-radius: 10px; } /* as big as the bar comfortably holds (Grant, 18 Oct 2026: it was too small) */
.top-bar__stack { display: grid; min-width: 0; line-height: 1.15; }
.top-bar__clubname { font-family: var(--font-display); font-weight: 800; font-size: 1rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.top-bar__page { font-size: var(--fs-xs, .75rem); font-weight: 600; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.club-tab__brand { display: flex; justify-content: center; padding: var(--sp-2) 0 var(--sp-4); font-size: 1.05rem; }
/* phones: Switch club is a round icon button beside the theme button, so the club name keeps the room */
@media (max-width: 599px) {
  .top-bar__switch:has(.top-bar__switch-text) { width: 44px; min-width: 44px; height: 44px; padding: 0; justify-content: center; border-radius: 50%; }
  .top-bar__switch-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

/* A short window (a laptop zoomed in, Grant, 22 Oct 2026): the side menu tightens so every item still fits without scrolling. Tap targets stay 44px. */
@media (min-width: 768px) and (max-height: 760px) {
  .side-nav { gap: 0; padding-top: var(--sp-2); padding-bottom: var(--sp-2); }
  .side-nav .nav-item { min-height: 44px; padding-top: 0; padding-bottom: 0; }
  .side-nav__brand { padding-top: 0; padding-bottom: 0; }
  .theme-pair { margin-bottom: var(--sp-1); }
  .side-nav__clubcard { padding-bottom: var(--sp-1); }
  .side-nav__clubcard .club-logo, .side-nav__clubcard .club-tile { --cs: 40px; }
  .side-nav__label { padding-top: var(--sp-2); }
  .side-nav__foot { padding-top: var(--sp-1); gap: 0; }
}
