/* ─────────────────────────────────────────────────────
   GLOBETROTTERS THEME - mobile-first rebuild
   Royal Blue #003DA5 · Red #CC2200 · Yellow #F5C800 · White
   Carried over from the original design; layout rebuilt around a bottom
   nav + floating share action instead of the old top-tab bar, see DESIGN.md
───────────────────────────────────────────────────── */
:root {
  --blue:     #003DA5;
  --blue2:    #1a52c4;
  --blue-lt:  #dce8ff;
  --blue-bg:  #f0f5ff;
  --red:      #CC2200;
  --red-lt:   #fff0ee;
  --yellow:   #F5C800;
  --yellow3:  #c8a200;
  --yellow-lt:#fffbe0;
  --white:    #ffffff;
  --off:      #f5f6fb;
  --grey:     #edf0f7;
  --grey2:    #d8dce8;
  --grey3:    #9098b8;
  --text:     #0c1230;
  --text2:    #323d6a;
  --text3:    #6870a0;
  --green-w:  #00963a;
  --green-lt: #e6f7ed;
  --shadow:   0 2px 14px rgba(0,30,100,0.09);
  --shadow2:  0 6px 28px rgba(0,30,100,0.14);
  --r:        12px;
  --fd: 'Anton', sans-serif;
  --fc: 'Barlow Condensed', sans-serif;
  --fb: 'Barlow', sans-serif;
}
*{margin:0;padding:0;box-sizing:border-box;}
/* Every clickable control gets a pointer cursor and SOME visible feedback
   on hover/press, app-wide - a lot of individual buttons only ever had
   their own one-off style (padding/colour/border) with no cursor or hover
   rule of their own, which on desktop/trackpad testing especially reads as
   "is this even clickable?" (Neville, Aug 2026). button:not(:disabled) as
   the base case catches every <button> in the app including ones that
   only use inline styles, so nothing needs to be touched individually or
   remembered on every future button that gets added - .btn-primary/
   .btn-secondary layer a slightly stronger, branded hover on top of that
   base for the two workhorse classes used almost everywhere. Kept subtle
   (transform/brightness, no colour reflow) so it doesn't fight each
   button's own specific styling.  */
button:not(:disabled),[role="button"],.name-btn,.honour-board-row[draggable="true"]{cursor:pointer;}
button:not(:disabled):hover{filter:brightness(0.97);}
button:not(:disabled):active{transform:scale(0.97);}
button:disabled{cursor:not-allowed;opacity:0.5;}
button{transition:filter 0.12s ease,transform 0.08s ease,background 0.15s ease;}
.btn-primary:hover:not(:disabled){filter:brightness(1.12);}
.btn-secondary:hover:not(:disabled){background:var(--blue-bg);}
html{font-size:16px;}
/* overflow-x:hidden as a defensive safety net - this is a single-column,
   mobile-first layout (see DESIGN.md) that never intentionally needs
   horizontal scroll anywhere except .subtab-row's own deliberate
   overflow-x:auto (unaffected by this, since it's scoped to itself). If
   ANY element anywhere ever overflows its container width - the exact
   .parsed-row bug just fixed, or some other one not yet found - this
   stops it from turning the WHOLE PAGE horizontally scrollable (which is
   what actually made that bug look like "the review queue isn't cropped
   to the screen" - the row's content wasn't just spilling past its own
   box, the entire body was scrolling to accommodate it). Content that
   overflows now gets clipped instead, which is always the safer failure
   mode for a phone screen. */
body{background:var(--off);color:var(--text);font-family:var(--fb);min-height:100vh;padding-bottom:64px;overflow-x:hidden;}
/* iPhones with a home-indicator (no physical home button) reserve a gap
   at the very bottom of the screen for the system swipe-up gesture -
   env(safe-area-inset-bottom) is how a page finds out how big that gap
   is on the actual device (0 on phones that don't need one). Without
   this, the fixed bottom-nav's icons/labels sit flush against - and can
   get visually cropped by - that system area on notched/home-indicator
   iPhones. The fallback 0px keeps this a no-op on devices that don't
   support env() at all. */

/* Team-colour stripe - a small brand touch straight off the brand board,
   sits above the header like a finish-line ribbon. */
.team-stripe{height:6px;background:repeating-linear-gradient(90deg,#003DA5 0px,#003DA5 30px,#F5C800 30px,#F5C800 33px,#CC2200 33px,#CC2200 63px,#F5C800 63px,#F5C800 66px);}

.site-header{background:var(--blue);padding:12px 16px 10px;color:#fff;position:relative;overflow:hidden;box-shadow:0 4px 20px rgba(0,20,80,0.3);}
.site-header::before{content:'';position:absolute;inset:0;background:repeating-linear-gradient(-55deg,transparent 0px,transparent 18px,rgba(255,255,255,0.05) 18px,rgba(255,255,255,0.05) 36px);pointer-events:none;}
.header-row{display:flex;justify-content:space-between;align-items:center;position:relative;z-index:1;}
.brand-title{font-family:var(--fd);font-size:1.5rem;letter-spacing:2px;}
.brand-sub{font-family:var(--fc);font-size:0.6rem;letter-spacing:2px;color:rgba(255,255,255,0.6);margin-top:2px;text-transform:uppercase;}
.week-pill{background:var(--red);color:#fff;font-family:var(--fd);font-size:0.85rem;letter-spacing:1px;padding:5px 12px;border-radius:7px;white-space:nowrap;}
.balance-row{display:flex;justify-content:space-between;align-items:baseline;margin-top:8px;position:relative;z-index:1;}
.bb-label{font-family:var(--fc);font-size:0.58rem;color:rgba(255,255,255,0.5);letter-spacing:2px;text-transform:uppercase;}
.bb-val{font-family:var(--fd);font-size:1.3rem;color:var(--yellow);letter-spacing:1px;}
.bb-delta{font-family:var(--fc);font-size:0.62rem;color:#7dffaa;}

.balance-goal-row{margin-top:6px;position:relative;z-index:1;}
.balance-goal-track{width:100%;height:6px;background:rgba(255,255,255,0.18);border-radius:3px;overflow:hidden;}
.balance-goal-fill{height:100%;background:var(--yellow);border-radius:3px;transition:width 0.4s ease;}
.balance-goal-label{font-family:var(--fc);font-size:0.58rem;color:rgba(255,255,255,0.65);letter-spacing:0.5px;margin-top:4px;}
.cutoff-pill{margin-top:8px;font-family:var(--fc);font-size:0.6rem;letter-spacing:1px;color:rgba(255,255,255,0.75);background:rgba(255,255,255,0.12);display:inline-block;padding:4px 10px;border-radius:6px;position:relative;z-index:1;}
.cutoff-pill.urgent{background:var(--red);color:#fff;}
.cutoff-pill:empty{display:none;}
.header-clock{margin-top:8px;font-family:var(--fc);font-size:0.58rem;letter-spacing:1.5px;color:rgba(255,255,255,0.55);position:relative;z-index:1;text-transform:uppercase;}

main{max-width:520px;margin:0 auto;padding:14px 12px calc(24px + env(safe-area-inset-bottom, 0px));}
.page{display:none;}
.page.active{display:block;}

.card{background:#fff;border-radius:var(--r);box-shadow:var(--shadow);padding:16px 18px;margin-bottom:14px;border:1px solid var(--grey2);}
.card-title{font-family:var(--fd);font-size:1rem;letter-spacing:2px;color:var(--blue);margin-bottom:12px;display:flex;align-items:center;justify-content:space-between;gap:8px;}
.ct-sub{font-family:var(--fc);font-size:0.58rem;color:var(--text3);letter-spacing:1px;font-weight:400;}

/* paste-zone (Aug 2026) - Neville: "can we have a box to click to obtain a
   cursor or something similar before i Ctrl+v - seems weired to Cntrl+V in
   the app with nothing selected." The actual paste target is still the real
   text input inside (mobile paste only works on genuine editable fields via
   the OS text-selection menu - a plain focusable div won't offer Paste on
   iOS/Android), just visibly boxed so it's obvious where to click first and
   whether it's actively focused. :focus-within lights up the whole box the
   moment the inner input has focus, whether from auto-focus on open or a
   manual click. */
.paste-zone{display:flex;align-items:center;gap:8px;border:1.5px dashed var(--grey2);border-radius:8px;padding:2px 10px;flex:1;min-width:180px;transition:border-color .15s,background .15s;}
.paste-zone:focus-within{border-color:var(--green-w);background:rgba(0,150,58,0.05);}
.paste-zone-icon{font-size:0.95rem;flex-shrink:0;opacity:0.6;}
.paste-zone-input{flex:1;border:none;background:transparent;padding:8px 0;font-size:0.76rem;outline:none;min-width:120px;}

.chairman-note{background:linear-gradient(135deg,var(--blue-bg) 0%,#fff 100%);border-left:4px solid var(--blue);border-radius:0 10px 10px 0;padding:12px 16px;font-size:0.84rem;line-height:1.6;color:var(--text2);font-style:italic;margin-bottom:14px;}
.chairman-by{font-family:var(--fc);font-size:0.6rem;color:var(--blue);letter-spacing:2px;font-style:normal;font-weight:600;margin-top:8px;}

.stats-row{display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));gap:8px;margin-bottom:14px;}
.stat-box{background:var(--blue-bg);border:1px solid var(--blue-lt);border-radius:10px;padding:10px;text-align:center;}
.stat-val{font-family:var(--fd);font-size:1.4rem;color:var(--blue);}
.stat-lbl{font-family:var(--fc);font-size:0.54rem;letter-spacing:1px;color:var(--text3);text-transform:uppercase;margin-top:2px;}

.mega-wrap{background:linear-gradient(135deg,#001d5e 0%,var(--blue) 100%);border-radius:var(--r);padding:16px 18px;margin-bottom:14px;color:#fff;}
.mega-title{font-family:var(--fd);font-size:1.05rem;letter-spacing:2px;color:var(--yellow);margin-bottom:10px;display:flex;justify-content:space-between;}
.mega-row{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:10px;}
.mega-lbl{font-size:0.55rem;letter-spacing:2px;color:rgba(255,255,255,0.5);text-transform:uppercase;}
.mega-val{font-family:var(--fd);font-size:1.6rem;color:var(--yellow);}
.mega-target{font-size:0.62rem;color:rgba(255,255,255,0.6);letter-spacing:1px;margin-top:6px;}
.mega-target.in-range{color:#7dffaa;}
.mega-target.out-range{color:#ff9d8a;}

/* Hot seat graphic (Aug 2026) - electric chair with this week's Mega
   Multi nominee's initials, per Neville's "mock one up in chat first"
   request. .hotseat-initials is positioned by the EXACT measured percent
   coordinates of the singlet's white circle in electric-chair.png
   (49.95% across, 46.93% down - see the pixel-analysis this was built
   from) so it stays correctly centered on the jersey at any render width,
   not just whatever size the source PNG happened to be. */
.hotseat-wrap{display:flex;flex-direction:column;align-items:center;margin-top:12px;}
.hotseat-chair{position:relative;width:120px;height:150px;margin-top:6px;}
.hotseat-chair-img{width:100%;display:block;}
.hotseat-initials{position:absolute;left:49.95%;top:46.93%;transform:translate(-50%,-50%);font-family:var(--fd);font-weight:700;font-size:0.85rem;color:var(--blue);letter-spacing:0.5px;}
/* #221 - WINNER/DEAD payoff images, once the week's Mega Multi resolves.
   Different native aspect ratios to the chair PNG (and to each other), so
   object-fit:cover + a fixed box (matching the chair's own rendered
   height) keeps the hot seat slot a stable size either way instead of the
   card jumping taller/shorter depending on which result shows. */
.hotseat-result-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:8px;display:block;}

/* Mega Multi resolved-state stamp - static (not animated) win/bust
   moment per the brand board's "hotseat" mockups, shown once every leg
   has a result. */
.mega-stamp{margin-top:12px;text-align:center;font-family:var(--fd);letter-spacing:2px;padding:10px 0 2px;}
.mega-stamp-win{color:var(--yellow);font-size:1.5rem;text-shadow:0 0 20px rgba(245,200,0,0.65);}
.mega-stamp-bust{color:#ff5a3c;font-size:1.15rem;text-shadow:0 0 16px rgba(204,34,0,0.55);}
.mega-stamp-sub{display:block;font-family:var(--fc);font-size:0.58rem;letter-spacing:2px;color:rgba(255,255,255,0.55);text-transform:uppercase;margin-top:2px;}

.bet-row{display:flex;align-items:center;gap:10px;padding:10px 4px;border-bottom:1px solid var(--grey);}
.bet-row:last-child{border-bottom:none;}
.bet-time-block{text-align:center;flex-shrink:0;min-width:50px;}
.bet-time{font-family:var(--fd);font-size:0.9rem;color:var(--blue);}
.bet-date{font-family:var(--fc);font-size:0.52rem;color:var(--text3);letter-spacing:1px;text-transform:uppercase;}
.bet-punter{font-family:var(--fd);font-size:1.05rem;flex-shrink:0;width:28px;}
/* #216 - "on behalf of" provenance, sitting with the row's other secondary
   detail (date/summary) rather than crammed into the fixed-width punter
   column above. */
.bet-added-by{font-family:var(--fc);font-size:0.56rem;letter-spacing:0.5px;color:var(--text3);flex-shrink:0;background:var(--grey1,#eef0f5);border-radius:4px;padding:2px 6px;margin-left:6px;}
.bet-info{flex:1;min-width:0;}
.bet-desc{font-size:0.8rem;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.bet-event{font-family:var(--fc);font-size:0.6rem;color:var(--text3);letter-spacing:1px;}
.bet-odds{font-family:var(--fd);font-size:1.1rem;color:var(--text2);flex-shrink:0;}
.bet-status{font-family:var(--fd);font-size:0.66rem;font-weight:400;letter-spacing:1.5px;flex-shrink:0;padding:2px 8px;border-radius:4px;border:1.5px solid transparent;transform:rotate(-3deg);display:inline-block;}
.bs-pending{background:var(--grey);color:var(--text3);font-family:var(--fc);font-size:0.56rem;letter-spacing:1px;transform:none;border:none;}
.bs-won{background:var(--green-lt);color:var(--green-w);border-color:var(--green-w);}
.bs-lost{background:var(--red-lt);color:var(--red);border-color:var(--red);}
/* Scratched/postponed (#158) - deliberately neutral (not red/green, since
   it's not a result) but still visually distinct from the plain PENDING
   grey so it reads as "needs a reload", not "still waiting". */
.bs-void{background:#eef0f5;color:var(--grey3);font-family:var(--fc);font-size:0.56rem;letter-spacing:1px;transform:none;border:1.5px dashed var(--grey3);}
.status-selected-won{background:var(--green-w) !important;color:#fff !important;border-color:var(--green-w) !important;}
.status-selected-lost{background:var(--red) !important;color:#fff !important;border-color:var(--red) !important;}
.status-selected-void{background:var(--grey3) !important;color:#fff !important;border-color:var(--grey3) !important;}

/* My Bets "bet types this cycle" indicator */
.shot-badge{font-family:var(--fd);font-size:0.72rem;letter-spacing:0.5px;padding:5px 11px;border-radius:14px;border:1.5px solid var(--grey2);}
.shot-badge.shot-open{background:var(--green-lt);color:var(--green-w);border-color:var(--green-w);}
.shot-badge.shot-locked{background:#eef0f5;color:var(--grey3);border-color:var(--grey2);text-decoration:line-through;opacity:0.75;}
.live-link{background:var(--green-lt);color:var(--green-w);border-radius:6px;padding:4px 7px;font-size:0.56rem;letter-spacing:1px;text-decoration:none;flex-shrink:0;white-space:nowrap;}

/* Mega Multi expandable card on the Dashboard - see betRowHTML()'s
   is_mega_bet branch. Legs are visually nested (indent + gold left rail)
   under the combined row they belong to. */
.mega-bet-row{cursor:pointer;}
.mega-expand-chevron{display:inline-block;transition:transform 0.15s ease;}
.mega-legs-detail{padding-left:12px;margin:0 0 6px 24px;border-left:2px solid var(--yellow3);}
.mega-leg-row{padding:8px 4px;}
.mega-leg-row .bet-desc{font-weight:500;}

/* Odds/stake/full-description detail rows (#157) - reuses .mega-legs-detail
   as the expand/collapse container for a plain (non-multi) bet too, just
   filled with key-value pairs instead of leg rows. */
.bet-detail-row{display:flex;justify-content:space-between;align-items:baseline;gap:10px;padding:6px 4px;font-size:0.76rem;color:var(--text);border-bottom:1px dashed var(--grey2);}
/* A description containing one long unbroken token (a bare URL, a run-on
   word with no spaces) would otherwise push this row's right-hand side
   past the edge of the card on a narrow phone screen instead of wrapping
   - the summary-line versions of this text already truncate with an
   ellipsis (.bet-desc/.bet-summary-sm above), but this expanded detail
   row is meant to show the FULL text, so it needs to wrap instead. */
.bet-detail-row > span:last-child{overflow-wrap:anywhere;min-width:0;}
.bet-detail-row:last-child{border-bottom:none;}
.bet-detail-lbl{font-family:var(--fc);font-size:0.58rem;letter-spacing:1.5px;color:var(--text3);flex-shrink:0;}

/* Two-line Dashboard row (#164) - TIME/PUNTER/TITLE/STATUS on top, DATE +
   the parsed bet summary underneath, so the summary always has its own
   full-width line to breathe on rather than fighting the status badge for
   space. See betRowTopHTML() in app.js - shared by every bet-row variant
   (single/multi/mega) so all three read the same way at a glance. */
.bet-row-2{display:flex;flex-direction:column;gap:3px;padding:10px 4px;border-bottom:1px solid var(--grey);cursor:pointer;}
.bet-row-2:last-child{border-bottom:none;}
.bet-row-top{display:flex;align-items:center;gap:10px;}
.bet-title{flex:1;min-width:0;font-size:0.8rem;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.bet-row-sub{display:flex;align-items:baseline;gap:8px;padding-left:60px;}
.bet-date-sm{font-family:var(--fc);font-size:0.56rem;color:var(--text3);letter-spacing:1px;text-transform:uppercase;flex-shrink:0;}
.bet-summary-sm{flex:1;min-width:0;font-family:var(--fc);font-size:0.64rem;color:var(--text3);letter-spacing:0.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}

/* #211 - "this event's date/time has already passed" signal, distinct from
   .bet-row-void above (that means the WAGER itself is void; this just means
   the CLOCK has - the bet's still fully live/actionable, W/L/V and all).
   Purely visual on the time/date text only, same restrained touch as the
   void treatment above. */
.bet-time.bet-date-past,
.bet-date-sm.bet-date-past{text-decoration:line-through;opacity:0.6;}

/* Voided bet row (#190) - once VOID's reload/bye choice fires, the OLD
   bet stays visible (so there's a clear record of what happened) but
   reads unmistakably "done, not actionable" via strike-through + dimming,
   rather than just a grey VOID badge easy to miss at a glance. Deliberately
   only touches the title/summary/punter text, not the whole row, so the
   TIME/DATE columns stay legible for anyone scanning down the list. */
.bet-row-void .bet-title,
.bet-row-void .bet-summary-sm,
.bet-row-void .bet-punter{text-decoration:line-through;opacity:0.5;}
.bet-row-void .bet-status{opacity:0.7;}

/* VOID…/choice UI (#190) - lives inside the tap-to-expand detail panel
   (.mega-legs-detail) alongside the odds/stake rows, replacing the old
   always-visible lone V button. Clicking VOID… swaps it for the two real
   outcomes in place - same toggle-swap idiom as USE BYE/REMOVE BYE DOUBLE
   elsewhere in My Bets, just scoped to this row instead of a whole panel. */
.void-choice-wrap{margin-top:8px;padding-top:8px;border-top:1px dashed var(--grey2);}
.void-choice-options{display:flex;flex-wrap:wrap;align-items:center;gap:8px;}
.void-choice-options.hidden{display:none;}
.void-choice-hint{flex-basis:100%;font-family:var(--fc);font-size:0.6rem;letter-spacing:0.5px;color:var(--text3);}

/* DOUBLE STAKE (2X).../choice (Aug 2026) - Neville: "this double up is
   unnecessary... resulting in a $40 bet." Same reveal idiom as VOID…
   above - USE BANKED BYE / USE POWERPLAY only appear once a punter has
   BOTH available and taps to choose, rather than as two always-on
   buttons that read like they might stack (they can't - a bet only ever
   gets doubled once, by one source or the other). */
.double-choice-wrap{margin-top:8px;}
.double-choice-options{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:6px;}
.double-choice-options.hidden{display:none;}
.double-choice-hint{flex-basis:100%;font-family:var(--fc);font-size:0.6rem;letter-spacing:0.5px;color:var(--text3);}

/* Per-leg redesign (#164) - LEG N / summary / INDIVIDUAL STAKE columns,
   matching the same layout language as the ODDS/COMBINED row above them
   (see legDetailRowHTML() in app.js). A leg's own description can run
   long (e.g. "Leg 2/2 · Nth Queensland Cowboys @1.96 Line vs Sydney
   Roosters...") so it gets its own truncate-with-tap-to-expand rather
   than wrapping the whole row taller by default. */
.leg-row{padding:7px 4px;border-bottom:1px dashed var(--grey2);}
.leg-row:last-child{border-bottom:none;}
.leg-row-top{display:flex;align-items:center;gap:8px;}
.leg-num{font-family:var(--fc);font-size:0.56rem;letter-spacing:1px;color:var(--yellow3);flex-shrink:0;width:38px;}
.leg-summary{flex:1;min-width:0;font-size:0.74rem;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;}
.leg-summary.expanded{white-space:normal;overflow:visible;text-overflow:clip;}
.leg-stake-lbl{font-family:var(--fc);font-size:0.54rem;letter-spacing:1px;color:var(--text3);flex-shrink:0;text-align:right;}
.leg-stake-val{font-family:var(--fd);font-size:0.8rem;color:var(--text2);flex-shrink:0;min-width:44px;text-align:right;}

/* #211 - inline per-leg ODDS input (personal multi/parlay legs whose odds
   weren't picked up automatically - see megaLegRowHTML()/
   saveLegOddsFromInput()). Deliberately small/plain, sitting right where
   the read-only figure normally shows. */
.leg-odds-input{font-family:var(--fd);font-size:0.78rem;color:var(--text2);width:56px;text-align:right;border:1px solid var(--grey2);border-radius:6px;padding:3px 6px;}

/* Outside-betting-window warning (#166) - a non-blocking heads-up on a
   Dashboard row whose parsed dt_iso falls outside the club's usual
   Thu-Mon fixture span for that week, most likely a date-parsing slip. */
.bet-window-warn{margin:4px 4px 0;padding:5px 8px;background:var(--yellow-lt);border:1px solid var(--yellow3);border-radius:6px;font-family:var(--fc);font-size:0.6rem;letter-spacing:0.3px;color:var(--yellow3);line-height:1.4;}

/* NEXT UP banner on the timetable */
.next-up{background:linear-gradient(135deg,var(--red) 0%,#a31b00 100%);color:#fff;border-radius:var(--r);padding:14px 16px;margin-bottom:14px;}
.next-up-lbl{font-family:var(--fc);font-size:0.6rem;letter-spacing:3px;color:rgba(255,255,255,0.7);margin-bottom:4px;}
.next-up-desc{font-family:var(--fd);font-size:1.05rem;letter-spacing:0.5px;}
.next-up-meta{font-family:var(--fc);font-size:0.68rem;color:rgba(255,255,255,0.8);margin-top:4px;}
.next-up-actions{display:flex;gap:8px;margin-top:10px;}
.next-up-actions button, .next-up-actions a{background:rgba(255,255,255,0.15);border:1px solid rgba(255,255,255,0.3);color:#fff;border-radius:7px;padding:7px 12px;font-family:var(--fc);font-size:0.68rem;letter-spacing:1px;text-decoration:none;}

/* BOTTOM NAV - primary navigation, mobile-first */
.bottom-nav{position:fixed;bottom:0;left:0;right:0;background:#fff;border-top:1px solid var(--grey2);display:flex;box-shadow:0 -2px 12px rgba(0,20,80,0.08);z-index:50;padding-bottom:env(safe-area-inset-bottom, 0px);}
.nav-btn{flex:1;text-align:center;padding:8px 0 9px;color:var(--grey3);background:none;border:none;cursor:pointer;font-family:var(--fb);}
.nav-btn.active{color:var(--blue);}
.nav-icon{font-size:18px;display:block;}
.nav-lbl{font-size:0.55rem;letter-spacing:0.5px;margin-top:2px;display:block;}

.fab-share{position:fixed;bottom:calc(76px + env(safe-area-inset-bottom, 0px));right:16px;width:54px;height:54px;border-radius:27px;background:var(--red);border:none;color:#fff;font-size:26px;box-shadow:var(--shadow2);z-index:51;cursor:pointer;transition:transform 0.15s ease;}
.fab-share.open{transform:rotate(45deg);}

.fab-menu{position:fixed;bottom:calc(140px + env(safe-area-inset-bottom, 0px));right:16px;display:flex;flex-direction:column;gap:8px;align-items:flex-end;z-index:51;}
.fab-menu-item{background:#fff;color:var(--blue);border:1.5px solid var(--blue);border-radius:20px;padding:9px 16px;font-family:var(--fd);font-size:0.75rem;letter-spacing:0.3px;box-shadow:var(--shadow2);white-space:nowrap;cursor:pointer;}

/* Share sheet + generic bottom sheet overlay */
.sheet-overlay{position:fixed;inset:0;background:rgba(0,0,0,0.45);z-index:100;display:none;align-items:flex-end;}
.sheet-overlay.open{display:flex;}
.sheet{background:#fff;width:100%;border-radius:16px 16px 0 0;padding:18px;max-height:80vh;overflow-y:auto;transition:transform 0.25s ease;touch-action:pan-y;}
.sheet-handle{width:36px;height:4px;background:var(--grey2);border-radius:2px;margin:0 auto 14px;}

.name-selector{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px;}
.name-btn{background:#fff;border:1.5px solid var(--grey2);border-radius:8px;padding:6px 10px;font-family:var(--fd);font-size:0.9rem;color:var(--text2);display:inline-flex;align-items:center;}
.name-btn.active{background:var(--blue);border-color:var(--blue);}

/* Singlet-style avatar - "member singlets" from the brand board: a
   two-colour half/half background (deterministic per punter code, see
   avatarHTML() in app.js) behind the code, standing in for a proper
   punter-chosen colour pair until there's a picker UI for that. */
.singlet-avatar{flex-shrink:0;box-shadow:0 2px 6px rgba(0,0,0,0.25);vertical-align:middle;}

.swatch-row{display:flex;gap:8px;flex-wrap:wrap;}
.swatch{width:32px;height:32px;border-radius:50%;border:2px solid var(--grey2);cursor:pointer;flex-shrink:0;}
.swatch.selected{border-color:var(--text);box-shadow:0 0 0 2px #fff,0 0 0 4px var(--text);}

/* Mega Multi win/bust animation overlay */
.mega-anim-overlay{position:fixed;inset:0;background:rgba(12,18,48,0.94);z-index:300;display:none;flex-direction:column;align-items:center;justify-content:center;gap:16px;cursor:pointer;padding:20px;box-sizing:border-box;}
.mega-anim-overlay.open{display:flex;}
.mega-anim-overlay img,.mega-anim-overlay video{width:220px;max-width:80vw;max-height:40vh;border-radius:20px;box-shadow:0 20px 60px rgba(0,0,0,0.5);object-fit:cover;}
.mega-anim-caption{font-family:var(--fd);font-size:1.8rem;letter-spacing:2px;color:#fff;text-align:center;}
.mega-anim-tap{font-family:var(--fc);font-size:0.6rem;letter-spacing:2px;color:rgba(255,255,255,0.5);}

/* Big-win confetti burst (Aug 2026) - Neville: "we just had a huge win!
   also, add some animations." Fires immediately for whoever taps WON, on
   top of the existing per-shot-type clip a bet's owner sees later in My
   Bets - a lightweight placeholder for Neville's eventual plan of a
   curated .mp4 catalog of classic sporting moments. Pointer-events:none
   so it never blocks the tap that triggered it or anything underneath. */
.confetti-canvas{position:fixed;inset:0;z-index:310;pointer-events:none;}
.confetti-banner{position:fixed;top:38%;left:50%;transform:translate(-50%,-40%) scale(0.7);opacity:0;font-family:var(--fd);font-size:2.4rem;letter-spacing:2px;color:var(--yellow);text-shadow:0 2px 0 rgba(0,0,0,0.4),0 0 30px rgba(245,200,0,0.55);z-index:311;pointer-events:none;transition:transform 0.35s cubic-bezier(.34,1.56,.64,1),opacity 0.35s ease;text-align:center;width:90vw;}
.confetti-banner.confetti-banner-in{transform:translate(-50%,-50%) scale(1);opacity:1;}

/* Opening login animation - a true full-bleed takeover (unlike the
   boxed Mega Multi/bet-result overlay above), since it's a one-off
   moment meant to fill the whole screen like the sports-network idents
   it's modelled on. */
.login-anim-overlay{position:fixed;inset:0;background:#000;z-index:400;display:none;align-items:center;justify-content:center;}
.login-anim-overlay.open{display:flex;}
/* Video starts invisible - the overlay's own solid #000 background is what
   shows during the gap between the overlay opening and the video actually
   having a decoded frame to paint (some browsers briefly show nothing/a
   flash of whatever's underneath a <video> tag before its first frame is
   ready). app.js adds .ready once the browser reports a frame is available
   (loadeddata), so what the person sees is a deliberate fade FROM the
   black overlay INTO the video, never a hard cut or a peek of the app. */
.login-anim-overlay video{width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity 0.45s ease;}
.login-anim-overlay video.ready{opacity:1;}
.login-anim-skip{position:absolute;bottom:max(24px,env(safe-area-inset-bottom));left:50%;transform:translateX(-50%);font-family:var(--fc);font-size:0.6rem;letter-spacing:2px;color:rgba(255,255,255,0.6);}

.ladder-row{display:flex;align-items:center;gap:10px;padding:8px 4px;border-bottom:1px solid var(--grey);}
.lr-rank{font-family:var(--fd);font-size:1.2rem;color:var(--text3);width:26px;text-align:center;}
.lr-name{font-family:var(--fd);font-size:1rem;flex:1;}
.lr-fname{font-family:var(--fc);font-size:0.6rem;color:var(--text3);display:block;}
.lr-roi{font-family:var(--fc);font-size:0.75rem;font-weight:600;width:48px;text-align:right;}
.roi-pos{color:var(--green-w);} .roi-neg{color:var(--red);} .roi-neu{color:var(--text3);}
.rank-range{font-family:var(--fc);font-size:0.58rem;color:var(--text3);letter-spacing:0.5px;}
/* Standings ladder "what's left in the tank" icon strip (Aug 2026) -
   Neville: "indication of bet types remaining, bye remaining and power
   play remaining. happy to go with icons for this." Compact version of
   .shot-badge for inline use in a dense ladder row. */
.finish-icons{display:flex;gap:4px;margin-top:3px;flex-wrap:wrap;}
.fi-badge{font-family:var(--fc);font-size:0.52rem;letter-spacing:0.3px;padding:2px 5px;border-radius:8px;border:1px solid var(--grey2);white-space:nowrap;}
.fi-badge.fi-open{background:var(--green-lt);color:var(--green-w);border-color:var(--green-w);}
.fi-badge.fi-locked{background:#eef0f5;color:var(--grey3);border-color:var(--grey2);opacity:0.7;}

/* Mega Multi leg picker - event-time gating (Aug 2026) - Neville: "if an
   event has already passed... they can no longer add that bet to their
   multi." Dims a not-yet-picked row whose event has started, with a small
   STARTED tag explaining the disabled checkbox. */
.mega-leg-expired{opacity:0.55;}
.mega-leg-expired-tag{font-family:var(--fc);font-size:0.52rem;letter-spacing:0.5px;color:var(--grey3);border:1px solid var(--grey2);border-radius:8px;padding:1px 5px;margin-left:4px;white-space:nowrap;}

.minutes-entry{background:var(--off);border-left:3px solid var(--blue);border-radius:0 8px 8px 0;padding:10px 14px;margin-bottom:8px;font-size:0.82rem;line-height:1.6;color:var(--text2);}
.minutes-date{font-family:var(--fc);font-size:0.6rem;color:var(--blue);letter-spacing:2px;font-weight:600;text-transform:uppercase;margin-bottom:4px;}

/* Sub-tab strip - used both for Standings (Cycle/FY/All-Time) and Club
   Life (Trips/Socials/Minutes). Same visual language as .name-btn so it
   doesn't need its own new pattern in the user's mental model. */
.subtab-row{display:flex;gap:8px;margin-bottom:12px;overflow-x:auto;}
.subtab-btn{flex:1;white-space:nowrap;background:#fff;border:1.5px solid var(--grey2);border-radius:8px;padding:8px 10px;font-family:var(--fc);font-size:0.68rem;letter-spacing:1px;color:var(--text2);cursor:pointer;}
.subtab-btn.active{background:var(--blue);border-color:var(--blue);color:#fff;}
.subtab-panel{display:none;}
.subtab-panel.active{display:block;}

.honour-row{display:flex;align-items:center;gap:10px;padding:8px 4px;border-bottom:1px solid var(--grey);}

/* Player Profile sheet - sport-by-sport bet breakdown bars */
.sport-row{margin-bottom:12px;}
.sport-row-top{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:4px;}
.sport-name{font-family:var(--fd);font-size:0.95rem;color:var(--text);}
.sport-count{font-family:var(--fc);font-size:0.62rem;color:var(--text3);letter-spacing:0.5px;}
.sport-bar-track{background:var(--grey);border-radius:5px;height:8px;overflow:hidden;}
.sport-bar-fill{background:linear-gradient(90deg,var(--blue),var(--blue2));height:100%;border-radius:5px;}
.honour-fy{font-family:var(--fc);font-size:0.6rem;color:var(--blue);letter-spacing:1px;width:66px;flex-shrink:0;}
.honour-name{font-family:var(--fd);font-size:0.95rem;flex:1;}
.honour-note{font-family:var(--fc);font-size:0.68rem;color:var(--text3);display:block;}

/* APPOINTMENTS/POSITIONS honour board - modelled directly on a real
   wood-grain club honour board (gold engraved lettering on timber),
   see #118. A warm brown gradient + faint repeating-linear-gradient
   grain lines (same subtle-overlay technique as .site-header::before)
   stands in for a wood texture without needing an image asset. */
.honour-board{border-radius:var(--r);overflow:hidden;box-shadow:var(--shadow2);margin-bottom:14px;}
.honour-board-banner{background:linear-gradient(160deg,#8a5a2b 0%,#6b4420 100%);padding:16px 18px 14px;text-align:center;position:relative;}
.honour-board-banner::before{content:'';position:absolute;inset:0;background:repeating-linear-gradient(100deg,transparent 0px,transparent 5px,rgba(0,0,0,0.06) 5px,rgba(0,0,0,0.06) 6px);pointer-events:none;}
.honour-board-club{font-family:var(--fd);font-size:1.5rem;letter-spacing:1.5px;color:var(--yellow);text-shadow:0 1px 0 rgba(0,0,0,0.35);position:relative;}
.honour-board-title{font-family:var(--fc);font-size:0.85rem;letter-spacing:5px;color:var(--yellow-lt);margin-top:2px;position:relative;}
.honour-board-body{background:linear-gradient(160deg,#a9713d 0%,#7a4f26 100%);padding:14px 16px 18px;position:relative;}
.honour-board-body::before{content:'';position:absolute;inset:0;background:repeating-linear-gradient(100deg,transparent 0px,transparent 5px,rgba(0,0,0,0.045) 5px,rgba(0,0,0,0.045) 6px);pointer-events:none;}
.honour-board-founder-row{font-family:var(--fc);font-size:0.72rem;letter-spacing:2px;color:var(--yellow-lt);text-align:center;margin-bottom:14px;position:relative;display:flex;align-items:center;justify-content:center;}
.honour-board-founder-row span{font-family:var(--fd);color:var(--yellow);letter-spacing:1px;margin-left:6px;}
.honour-board-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:18px;position:relative;}
.honour-board-col-title{font-family:var(--fc);font-size:0.66rem;letter-spacing:2px;color:var(--yellow);border-bottom:1.5px solid rgba(245,200,0,0.4);padding-bottom:6px;margin-bottom:6px;text-align:center;}
/* Fixed 2-column grid rather than flex+justify-content:center - centering
   each row independently meant the FY/date prefix drifted left or right
   depending on that row's own name length, so nothing lined up between
   rows. A grid keeps the date column and name column each at a consistent
   position all the way down, like a real engraved board. */
.honour-board-row{display:grid;grid-template-columns:52px 1fr;gap:8px;padding:3px 0 3px 4px;font-family:var(--fc);font-size:0.74rem;color:var(--yellow-lt);cursor:pointer;}
.honour-board-row[draggable="true"]{cursor:grab;}
.honour-board-row-fy{color:var(--yellow);text-align:right;}
.honour-board-row-name{font-family:var(--fd);letter-spacing:0.5px;color:var(--yellow-lt);text-align:left;}
.honour-board-row.dragging{opacity:0.4;}
.honour-board-row-empty{grid-template-columns:1fr;justify-items:center;cursor:default;color:rgba(255,251,224,0.55);font-style:italic;}

/* Same fix as .parsed-row above - a Feature Request's text is free-typed
   by a punter (can run long) and this row also carries a REVIEWED/TABLED/
   REOPEN .btn-row alongside it; without wrap+min-width:0 a long request
   would push those buttons off past the edge of a phone screen instead of
   the .btn-row's own margin-top:10px ever getting the chance to place it
   on its own line underneath, which was clearly the original intent. */
.todo-item{display:flex;align-items:flex-start;flex-wrap:wrap;gap:9px;padding:9px 10px;background:var(--off);border:1px solid var(--grey2);border-radius:8px;margin-bottom:6px;}
.todo-dot{width:8px;height:8px;border-radius:50%;background:var(--red,#c0392b);flex-shrink:0;margin-top:5px;}
.todo-text{flex:1 1 140px;min-width:0;font-size:0.78rem;line-height:1.3;overflow-wrap:break-word;}
.todo-hint{display:block;font-size:0.65rem;color:rgba(20,20,20,0.55);margin-top:2px;letter-spacing:0.3px;}

.setup-ta{width:100%;background:var(--off);border:1.5px solid var(--grey2);border-radius:10px;padding:12px;font-family:var(--fc);font-size:0.78rem;color:var(--text);resize:vertical;min-height:130px;outline:none;}
.btn-row{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px;}
.btn-primary{background:var(--blue);color:#fff;border:none;border-radius:8px;padding:10px 18px;font-family:var(--fd);font-size:0.85rem;letter-spacing:1px;}
.btn-secondary{background:#fff;color:var(--blue);border:1.5px solid var(--blue);border-radius:8px;padding:10px 18px;font-family:var(--fd);font-size:0.85rem;letter-spacing:1px;}
/* flex-wrap:wrap (was nowrap by default) - a review-queue row can carry a
   punter code, a long raw share caption, an OPEN link, PLACED checkbox,
   ATTACH CONFIRMATION and DEL all at once. Without wrap, and without
   .pr-desc having a min-width below its own text's natural width (the
   classic flexbox gotcha - flex:1 alone doesn't let an item shrink past
   its content unless min-width is also set), a long caption refused to
   shrink and pushed the action buttons straight off the right edge of a
   phone screen instead of wrapping underneath. */
.parsed-row{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:8px 10px;background:var(--off);border:1px solid var(--grey2);border-radius:8px;margin-bottom:5px;}
.parsed-edit{border:1px solid var(--grey2);border-radius:6px;padding:6px 8px;font-size:0.76rem;background:#fff;color:inherit;font-family:inherit;}
.pr-punter-input{width:78px;flex-shrink:0;}
.pr-desc-input{flex:1 1 160px;min-width:120px;}
.pr-odds-input{width:66px;}
.pr-sport-input{width:96px;}
.pr-date-input,.pr-time-input{width:80px;}
.parsed-row-flag{border-color:var(--red);background:var(--red-lt);}
.pr-punter{font-family:var(--fd);font-size:0.9rem;width:30px;flex-shrink:0;}
.pr-desc{flex:1 1 140px;min-width:0;font-size:0.78rem;overflow-wrap:break-word;}
.pr-odds{font-family:var(--fc);font-size:0.72rem;color:var(--green-w);font-weight:600;}
.bets-feed-list{max-height:280px;overflow-y:auto;display:flex;flex-direction:column;gap:6px;padding-right:2px;}
.feed-msg{display:flex;gap:8px;align-items:flex-start;}
.feed-msg-bubble{background:var(--off);border:1px solid var(--grey2);border-radius:10px;padding:7px 10px;max-width:78%;}
.feed-msg.own{flex-direction:row-reverse;}
.feed-msg.own .feed-msg-bubble{background:var(--blue);color:#fff;border-color:var(--blue);}
.feed-msg-top{display:flex;gap:6px;align-items:baseline;margin-bottom:2px;}
.feed-msg-punter{font-family:var(--fd);font-size:0.78rem;}
.feed-msg-time{font-family:var(--fc);font-size:0.55rem;letter-spacing:0.5px;color:var(--text3);}
.feed-msg.own .feed-msg-time{color:rgba(255,255,255,0.7);}
.feed-msg-del{margin-left:auto;background:none;border:none;color:var(--text3);font-size:1rem;line-height:1;padding:0 2px;cursor:pointer;}
.feed-msg.own .feed-msg-del{color:rgba(255,255,255,0.7);}
.feed-msg-del:hover{color:var(--red, #c0392b);}
.feed-msg-text{font-size:0.82rem;word-break:break-word;}
.submission-window-banner{background:#fff4d6;border:1.5px solid #e0b84c;color:#5c4a0a;border-radius:10px;padding:10px 14px;font-size:0.82rem;margin-bottom:12px;}
.sport-guess-row{display:flex;gap:6px;align-items:center;}
.feed-msg-text a{color:inherit;text-decoration:underline;}
.pick-check{width:18px;height:18px;flex-shrink:0;}
.placed-toggle{display:flex;align-items:center;gap:4px;font-family:var(--fc);font-size:0.58rem;letter-spacing:0.5px;color:var(--text3);flex-shrink:0;white-space:nowrap;}
.placed-toggle input{width:14px;height:14px;}
.no-link{font-family:var(--fc);font-size:0.54rem;letter-spacing:0.5px;color:var(--grey3);flex-shrink:0;white-space:nowrap;}

.sub-count{font-family:var(--fd);font-size:1.1rem;color:var(--blue);letter-spacing:1px;margin-bottom:8px;}
.sub-grid{display:flex;flex-wrap:wrap;gap:6px;}
.sub-chip{font-family:var(--fd);font-size:0.8rem;letter-spacing:1px;padding:5px 10px;border-radius:6px;border:1.5px solid var(--grey2);color:var(--text3);}
.sub-chip.sub-confirmed{background:var(--green-lt);border-color:var(--green-w);color:var(--green-w);}
.sub-chip.sub-pending{background:var(--yellow-lt);border-color:var(--yellow3);color:var(--yellow3);}
.sub-chip.sub-missing{background:var(--red-lt);border-color:var(--red);color:var(--red);}
/* #216 - deliberately sitting this week out, distinct from sub-missing
   (which reads as "hasn't gotten to it yet") - neutral grey/blue rather
   than red, since a bye isn't a problem to chase up. */
.sub-chip.sub-bye{background:var(--grey1,#eef0f5);border-color:var(--grey2);color:var(--text3);}
.sub-powerplay,.sub-bye-flag{margin-left:3px;font-size:0.85rem;letter-spacing:0;}

.hidden{display:none !important;}
.empty{text-align:center;padding:28px 14px;color:var(--text3);font-family:var(--fc);font-size:0.72rem;letter-spacing:1px;border:1.5px dashed var(--grey2);border-radius:var(--r);background:var(--off);}
.empty-icon{width:16px;height:16px;border-radius:4px;background:var(--grey);margin:0 auto 10px;}

.toast{position:fixed;bottom:72px;left:50%;transform:translateX(-50%) translateY(80px);background:var(--text);color:#fff;border-radius:10px;padding:10px 18px;font-family:var(--fc);font-size:0.72rem;letter-spacing:1px;z-index:9999;transition:transform 0.3s;white-space:nowrap;}
.toast.show{transform:translateX(-50%) translateY(0);}

.install-banner{background:var(--yellow-lt);border:1px solid rgba(200,160,0,0.3);border-radius:10px;padding:10px 14px;margin-bottom:14px;display:flex;justify-content:space-between;align-items:center;gap:10px;font-size:0.78rem;color:#7a5c00;}

/* ─────────────────────────────────────────────────────
   LOGIN SCREEN
───────────────────────────────────────────────────── */
.login-screen{position:fixed;inset:0;background:linear-gradient(160deg,var(--blue) 0%,#001d5e 100%);z-index:200;display:flex;align-items:center;justify-content:center;padding:24px;}
.login-screen.hidden{display:none;}
.login-card{width:100%;max-width:360px;background:#fff;border-radius:18px;padding:32px 26px 26px;box-shadow:var(--shadow2);text-align:center;}
.login-logo{font-family:var(--fd);font-size:1.9rem;letter-spacing:2px;color:var(--blue);}
.login-sub{font-family:var(--fc);font-size:0.62rem;letter-spacing:2px;color:var(--text3);text-transform:uppercase;margin-top:2px;margin-bottom:26px;}
.login-btn-passkey{width:100%;background:var(--blue);color:#fff;border:none;border-radius:10px;padding:15px 16px;font-family:var(--fd);font-size:1rem;letter-spacing:1px;display:flex;align-items:center;justify-content:center;gap:9px;box-shadow:var(--shadow);cursor:pointer;}
.login-btn-passkey:active{background:var(--blue2);}
.login-passkey-icon{font-size:1.15rem;}
.login-divider{display:flex;align-items:center;gap:10px;margin:20px 0 16px;font-family:var(--fc);font-size:0.62rem;letter-spacing:1px;color:var(--text3);text-transform:uppercase;}
.login-divider::before,.login-divider::after{content:'';flex:1;height:1px;background:var(--grey2);}
.login-form{display:flex;flex-direction:column;gap:10px;}
.login-form input{width:100%;background:var(--off);border:1.5px solid var(--grey2);border-radius:9px;padding:12px 13px;font-family:var(--fb);font-size:0.88rem;color:var(--text);outline:none;}
.login-form input:focus{border-color:var(--blue);}
.login-btn-password{width:100%;margin-top:2px;}
.login-error{min-height:18px;margin-top:12px;font-family:var(--fc);font-size:0.68rem;letter-spacing:0.5px;color:var(--red);}
.login-help-link{margin-top:6px;font-family:var(--fc);font-size:0.68rem;letter-spacing:0.5px;color:var(--blue);text-decoration:underline;cursor:pointer;}

/* Sheets opened FROM the login screen (self-service signup, and the
   post-login "set up Face ID?" nudge) need to sit ABOVE .login-screen's
   z-index:200 - .sheet-overlay's shared default is only z-index:100,
   which is correct for sheets opened from inside the logged-in app, but
   would render these two invisibly BEHIND the login card otherwise. */
#selfServiceSheet, #passkeySetupSheet{z-index:220;}

.account-btn{background:rgba(255,255,255,0.14);border:1px solid rgba(255,255,255,0.25);color:#fff;width:32px;height:32px;border-radius:8px;font-size:15px;line-height:1;cursor:pointer;}

.passkey-row{display:flex;align-items:center;gap:8px;padding:9px 10px;background:var(--off);border:1px solid var(--grey2);border-radius:8px;margin-bottom:6px;}
.passkey-row-info{flex:1;min-width:0;}
.passkey-row-label{font-size:0.8rem;font-weight:600;color:var(--text);}
.passkey-row-meta{font-family:var(--fc);font-size:0.6rem;color:var(--text3);letter-spacing:0.5px;margin-top:1px;}
.passkey-row-del{background:none;border:none;color:var(--red);font-family:var(--fc);font-size:0.62rem;letter-spacing:1px;padding:5px 8px;flex-shrink:0;cursor:pointer;}

/* SEASON AUDIT (Aug 2026) - week-by-week bet/bye/missing grid, Treasurer
   tab - see loadSeasonAudit()/renderSeasonAudit() in app.js. Horizontally
   scrollable since cycle_weeks (9, sometimes 10) runs past a phone's
   width; punter code column pinned via sticky so it stays readable while
   scrolling through the week columns. */
.audit-grid-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:0 -18px;padding:0 18px;}
.audit-grid{border-collapse:collapse;width:100%;font-family:var(--fc);}
.audit-grid th,.audit-grid td{padding:6px 4px;text-align:center;border-bottom:1px solid var(--grey);white-space:nowrap;}
.audit-grid th{color:var(--text3);font-weight:600;letter-spacing:0.5px;text-transform:uppercase;font-size:0.54rem;}
.audit-grid td:first-child,.audit-grid th:first-child{position:sticky;left:0;background:#fff;text-align:left;font-weight:700;color:var(--blue);padding-right:10px;box-shadow:2px 0 4px rgba(0,0,0,0.05);}
.audit-cell{display:inline-block;min-width:38px;padding:4px 3px;border-radius:6px;font-size:0.62rem;letter-spacing:0.5px;font-weight:600;}
.audit-cell-bet{border:none;font-family:var(--fc);cursor:pointer;}
.audit-cell-bet:hover{filter:brightness(0.95);}
/* Won/lost/pending (Aug 2026) - Neville: "would be good to have successful
   bets marked as green, lost as red as well so we get who's got what at a
   glance." Pending keeps the old neutral blue since the result isn't in
   yet - not a win or a loss. */
.audit-cell-bet-won{background:var(--green-lt);color:var(--green-w);}
.audit-cell-bet-lost{background:var(--red-lt);color:var(--red);}
.audit-cell-bet-pending{background:var(--blue-bg);color:var(--blue);}
.audit-cell-bye{background:var(--blue-bg);color:var(--blue);}
.audit-cell-future{background:var(--grey);color:var(--grey3);}
.audit-cell-missing{background:var(--red-lt);color:var(--red);}
.audit-missing-actions{display:flex;flex-direction:column;gap:3px;margin-top:3px;}
.audit-mark-bye{display:block;font-size:0.5rem;letter-spacing:0.5px;background:none;border:1px dashed var(--red);color:var(--red);border-radius:5px;padding:2px 3px;cursor:pointer;font-family:var(--fc);width:100%;}
.audit-mark-bye:hover{background:var(--red-lt);}
/* MEGA column (Aug 2026) - Neville: "can we get a column after week 10 in
   the audit screen that has room for mega multi upload too please?
   obviously this is only 1 per person." A left divider sets it apart from
   the weekly grid, since it isn't just one more week slot. */
.audit-cell-mega-col{border-left:2px solid var(--yellow3);padding-left:8px !important;}
.audit-legend{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:10px;font-family:var(--fc);font-size:0.58rem;color:var(--text3);letter-spacing:0.5px;}
.audit-legend span{display:inline-flex;align-items:center;gap:4px;}
.audit-legend i{width:9px;height:9px;border-radius:3px;display:inline-block;}
/* Powerplay-not-taken warning (Aug 2026) - Neville: "warning for not
   having taken powerplay should also be there as well." Sits next to the
   punter's code in the sticky first column. */
.audit-pp-warning{display:inline-block;margin-left:5px;font-size:0.6rem;cursor:default;}

@media(min-width:600px){ main{max-width:600px;} }
