
/* ============================================================================
   SWEAT EQUITY — direction 07, BROADCAST.
   Every colour below was checked against WCAG before it was used. The text
   colours (--t1/--t2/--t3) clear 4.5:1 on every ground in this file, the worst
   pair being --t3 on --panel3 at 5.66:1. Red is split in two: --red is the only
   red allowed to carry text (4.90:1 at its worst), --redFill is the only red
   allowed to sit behind white (6.92:1). The bright --redDot is a graphic only.
   ========================================================================== */
:root{
  --bg:#05101c;        /* base */
  --bar:#071523;       /* status band + channel bar + ticker */
  --panel:#0c1f31;     /* cards */
  --panel2:#123049;    /* your row, raised rows */
  --panel3:#16395a;    /* chips on raised rows */
  --line:#1d3d5c; --line2:#15304a;
  --t1:#ffffff; --t2:#c6d9ea; --t3:#9db6cd;
  --gold:#ffc53d; --gold2:#e0a92c; --onGold:#231800; --goldWash:#241c07;
  --red:#ff8080; --redFill:#b3141b; --redDot:#ff5a5a; --redWash:#2a1016;
  --green:#3ddc84; --onGreen:#04180c; --greenWash:#0b2418;
  --blue:#6cb6ff;
  --disp:'Archivo','Helvetica Neue',Helvetica,Arial,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,'SF Mono',Menlo,Consolas,monospace;
  --ease:cubic-bezier(.2,.9,.25,1);
  --W:393px; --H:852px;
  /* In the prototype these were a drawn iPhone's status bar and home indicator,
     62px and 34px of reserved nothing. On a real device they are the safe-area
     insets, and in a browser tab they are zero — so the chrome sits flush at the
     top instead of below a band that is pretending to be a status bar. */
  --band:env(safe-area-inset-top, 0px);
  --chan:44px;   /* channel bar */
  --tabs:58px;   /* tab bar */
  --home:env(safe-area-inset-bottom, 0px);
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0;height:100%;overscroll-behavior:none}
body{
  background:#03080f;
  min-height:100dvh;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--disp);
  /* Tabular figures inherit to every number in the app so nothing jitters as
     values roll. Belt and braces: the modern property and the raw feature. */
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;
  -webkit-font-smoothing:antialiased;
}
/* Form controls take `font` from the UA stylesheet, which resets
   font-variant-numeric back to normal — and most of this app's numbers live
   inside <button> rows. Without this the table digits would change width as
   they update, which is the loudest amateur tell there is. */
button,input,select,textarea{
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;
}
/* The prototype was a drawn phone on a dark page. The shipped app IS the phone:
   it fills the viewport, and only on a screen big enough to hold the whole
   frame does it go back to being a 393x852 object with a shadow under it. */
#app{
  position:relative;width:100%;max-width:var(--W);height:100dvh;overflow:hidden;
  background:var(--bg);color:var(--t1);
}
@media (min-width:460px) and (min-height:900px){
  #app{height:var(--H);box-shadow:0 0 0 1px #12283c, 0 40px 90px rgba(0,0,0,.7)}
}

/* ---------- chrome ---------- */
#band{position:absolute;top:0;left:0;right:0;height:var(--band);background:var(--bar);z-index:40}
#chan{
  position:absolute;top:var(--band);left:0;right:0;height:var(--chan);background:var(--bar);
  display:flex;align-items:center;gap:8px;padding:0 6px 0 14px;z-index:40;
  border-bottom:1px solid var(--line2);
}
.wordmark{font-stretch:125%;font-weight:900;font-size:13px;letter-spacing:.13em;color:var(--t1);white-space:nowrap}
.wordmark b{color:var(--gold);font-weight:900}
.chan-title{
  font-stretch:112%;font-weight:800;font-size:14px;letter-spacing:.02em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;
}
.chan-sp{flex:1}
.livepill{
  display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 9px;border-radius:4px;
  background:var(--redFill);color:#fff;font-size:10px;font-weight:900;letter-spacing:.16em;flex:none;
}
.livepill i{width:6px;height:6px;border-radius:50%;background:#fff;animation:blip 1.6s infinite}
@keyframes blip{0%,55%{opacity:1}70%,100%{opacity:.25}}
.iconbtn{
  width:44px;height:44px;display:grid;place-items:center;background:none;border:0;padding:0;
  color:var(--t2);cursor:pointer;flex:none;border-radius:8px;
}
.iconbtn:active{background:var(--panel2);color:var(--t1)}
.backbtn{
  height:44px;min-width:44px;display:inline-flex;align-items:center;gap:4px;padding:0 8px 0 2px;
  background:none;border:0;color:var(--gold);font-family:var(--disp);font-weight:800;font-size:12px;
  letter-spacing:.1em;cursor:pointer;flex:none;
}
.backbtn:active{opacity:.6}

/* ---------- screen host ---------- */
#viewport{
  position:absolute;top:calc(var(--band) + var(--chan));left:0;right:0;
  bottom:calc(var(--tabs) + var(--home));overflow:hidden;display:flex;flex-direction:column;
}
#view{flex:1;display:flex;flex-direction:column;min-height:0}
.scroll{flex:1;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
.scroll::-webkit-scrollbar{width:0;height:0}
.pad{padding:0 16px}
.padb{height:20px}
.enter-tab{animation:enterTab .34s var(--ease) both}
.enter-push{animation:enterPush .34s var(--ease) both}
@keyframes enterTab{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes enterPush{from{opacity:0;transform:translateX(22px)}to{opacity:1;transform:none}}

/* ---------- tab bar ---------- */
#tabs{
  position:absolute;left:0;right:0;bottom:var(--home);height:var(--tabs);
  background:var(--bar);border-top:1px solid var(--line2);display:flex;z-index:30;
}
.tab{
  flex:1;min-width:0;background:none;border:0;padding:0;cursor:pointer;position:relative;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  color:var(--t3);font-family:var(--disp);
}
.tab i{position:absolute;top:0;left:14%;right:14%;height:3px;background:var(--gold);transform:scaleX(0);transition:transform .3s var(--ease)}
.tab span{font-size:9.5px;font-weight:800;letter-spacing:.09em}
.tab[aria-selected="true"]{color:var(--gold)}
.tab[aria-selected="true"] i{transform:scaleX(1)}
.tab:active{background:#0b1e2f}
#home{position:absolute;left:0;right:0;bottom:0;height:var(--home);background:var(--bar);z-index:30}

/* ---------- type ---------- */
.disp{font-stretch:125%;font-weight:800;letter-spacing:-.022em;line-height:1.02;margin:0}
.d34{font-size:34px}.d28{font-size:28px}.d22{font-size:22px}.d46{font-size:46px}
.k{font-size:10.5px;font-weight:800;letter-spacing:.15em;color:var(--t3);text-transform:uppercase;margin:0}
.k.gold{color:var(--gold)}.k.red{color:var(--red)}.k.green{color:var(--green)}
.p{font-size:13.5px;line-height:1.5;color:var(--t2);margin:0}
.p.sm{font-size:12.5px;color:var(--t3);line-height:1.45}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
.gold{color:var(--gold)}.red{color:var(--red)}.green{color:var(--green)}.dim{color:var(--t3)}.t2{color:var(--t2)}

/* ---------- section headers ---------- */
/* 22px was not enough air when nine sections were competing on one screen. With
   the duplicated ones moved to the FIXTURES tab, the extra space reads as calm
   rather than as a gap. */
.sect{display:flex;align-items:center;gap:9px;margin:30px 0 11px}
.sect .k{white-space:nowrap}
.sect .ln{flex:1;height:1px;background:var(--line2)}

/* ---------- hero ---------- */
.hero{position:relative;padding:16px 16px 0;background:
  radial-gradient(120% 90% at 80% -10%, #14416b 0%, rgba(20,65,107,0) 60%),
  linear-gradient(165deg,#0b2136 0%,#082033 46%,var(--bg) 100%);
  border-bottom:1px solid var(--line2);overflow:hidden}
.hero::after{ /* broadcast diagonal, purely decorative */
  content:"";position:absolute;right:-40px;top:-30px;width:150px;height:230px;
  background:linear-gradient(180deg,rgba(255,197,61,.14),rgba(255,197,61,0));
  transform:skewX(-18deg);pointer-events:none}
.hero .kickrow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;position:relative;z-index:1}
.hero h1{margin:8px 0 0;position:relative;z-index:1}
.metarow{display:flex;gap:0;margin:12px 0 0;border-top:1px solid var(--line2);position:relative;z-index:1}
.metacell{flex:1;padding:10px 0 12px;border-right:1px solid var(--line2)}
.metacell:last-child{border-right:0}
.metacell .v{font-family:var(--mono);font-size:17px;font-weight:600;color:var(--t1);line-height:1}
.metacell .l{font-size:9.5px;font-weight:800;letter-spacing:.12em;color:var(--t3);margin-top:5px}
.prog{height:4px;background:#0a2137;border-radius:2px;overflow:hidden;position:relative;z-index:1}
/* scaleX rather than width, for the same reason as .bugprog: a transition on
   width is a layout animation and this one sits on the busiest screen. */
.prog i{display:block;height:100%;width:100%;background:var(--gold);border-radius:2px;
  transform-origin:left;transition:transform .6s var(--ease)}

/* ---------- the scorebug, now a STORY BAR ---------------------------------
   This is the one graphic the client singled out. It is the same bar it always
   was — it just cycles now, through stories generated from real state, instead
   of advancing once and stopping forever.

   Every base style here is the FINISHED state. The entrance is added by a
   .swap class after the element is in the DOM, so if the compositor never
   delivers a frame the bar is still fully readable. Nothing here animates
   opacity for the same reason: a timeline frozen at keyframe zero holds
   opacity:0 forever, while a frozen transform just leaves text sitting 12px
   to the left of where it belongs.
   ------------------------------------------------------------------------ */
.bugwrap{position:relative;z-index:2;margin:14px -16px 0;width:calc(100% + 32px)}
.bug{
  position:relative;display:flex;align-items:stretch;width:100%;text-align:left;
  background:linear-gradient(90deg,#0f2c47,#0b2137);border:0;border-top:1px solid var(--line);
  padding:0;cursor:pointer;font-family:var(--disp);min-height:64px;color:var(--t1);
  touch-action:pan-y;   /* so a horizontal drag is ours and a vertical one still scrolls */
}
.bug .stripe{width:6px;background:var(--gold);flex:none;transform-origin:left}
.bug.red .stripe{background:var(--redFill)}
.bug.green .stripe{background:var(--green)}
.bug .bd{flex:1;min-width:0;padding:10px 12px 11px}
.bug .kline{display:flex;align-items:center;gap:7px}
.bug .k{display:block}
.bug .chv{display:grid;place-items:center;padding:0 10px 0 4px;color:var(--t3);flex:none}
.bug .bh{display:block;font-stretch:112%;font-size:17px;font-weight:800;letter-spacing:-.01em;margin-top:3px;color:var(--t1)}
.bug .bs{display:block;font-size:11.5px;color:var(--t2);margin-top:3px;line-height:1.35}
.bug:active .bd{opacity:.7}
.bug.swap .stripe{animation:bugbar .3s var(--ease) both}
.bug.swap .bd{animation:bugbody .34s var(--ease) both}
@keyframes bugbar{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes bugbody{from{transform:translateX(-12px)}to{transform:none}}
/* "HELD" is not decoration — it is the app telling you that your touch stopped
   the rotation, which is otherwise an invisible state change. */
.bughold{
  height:17px;padding:0 6px;border-radius:3px;flex:none;
  background:var(--panel3);color:var(--t1);font-size:8.5px;font-weight:900;letter-spacing:.1em;
  display:inline-flex;align-items:center;
}
/* The five-second advance, drawn. Decorative and aria-hidden: this is the one
   thing in the file allowed to rest at its START value, because a progress
   line frozen at zero costs the reader nothing.

   It animates scaleX, NOT width. Width is a layout property: animating it runs
   layout and paint on every frame, for five seconds, for every story, for as
   long as the app is open — which is the single most expensive thing this file
   used to do and the first place to look for the jitter the client reported on
   a phone. scaleX is composited and costs nothing per frame. */
.bugprog{height:2px;background:#0a2137;overflow:hidden}
.bugprog i{display:block;height:100%;width:100%;background:var(--gold2);
  transform:scaleX(0);transform-origin:left;will-change:transform}
.bugprog.run i{animation:bugprog 5s linear both}
@keyframes bugprog{from{transform:scaleX(0)}to{transform:scaleX(1)}}
/* Dots are real controls, so they are 44px tall whatever the dot looks like. */
.bugdots{display:flex;background:var(--bar);border-bottom:1px solid var(--line2)}
.bugdots button{
  flex:1;min-width:0;min-height:44px;background:none;border:0;padding:0;cursor:pointer;
  display:grid;place-items:center;
}
.bugdots button u{display:block;width:7px;height:7px;border-radius:50%;background:#3c5e82}
.bugdots button[aria-current="true"] u{background:var(--gold);box-shadow:0 0 0 3px rgba(255,197,61,.18)}
.bugdots button:active u{background:var(--t2)}

/* ---------- cards & rows ---------- */
.card{background:var(--panel);border:1px solid var(--line2);border-radius:12px;padding:14px}
.card.gold{background:var(--goldWash);border-color:#4a3a10}
.card.red{background:var(--redWash);border-color:#5a2028}
.card.green{background:var(--greenWash);border-color:#154a2e}
.rowbtn{
  display:flex;align-items:center;gap:12px;width:100%;min-height:60px;padding:11px 13px;
  background:var(--panel);border:1px solid var(--line2);border-radius:12px;color:var(--t1);
  font-family:var(--disp);text-align:left;cursor:pointer;margin-bottom:10px;
}
.rowbtn:active{background:var(--panel2);transform:scale(.988)}
.rowbtn .grow{flex:1;min-width:0}
/* Rows are <button>s, so their innards are spans. Make the ones that stack
   behave like blocks rather than relying on invalid div-inside-span nesting. */
.rowbtn .nm{display:block;font-size:15px;font-weight:700;letter-spacing:-.01em}
.rowbtn .sub{display:block;font-size:11.5px;color:var(--t3);margin-top:3px;line-height:1.35}
.rowbtn .k{display:block}
.chev{color:var(--t3);flex:none}

/* ---------- avatars ---------- */
.av{
  border-radius:50%;display:grid;place-items:center;flex:none;
  font-family:var(--disp);font-weight:900;font-stretch:112%;letter-spacing:.02em;color:#fff;
}
.av.s{width:34px;height:34px;font-size:12px}
.av.m{width:44px;height:44px;font-size:14px}
.av.l{width:78px;height:78px;font-size:26px}
.av.ring{box-shadow:0 0 0 2px var(--bg),0 0 0 4px var(--gold)}

/* ---------- month track (what replaced the W-L form guide) ----------------
   The old guide was W-L-W-W-L where "W" had been quietly redefined as a
   top-three finish, because with one winner per fixture a literal guide reads
   L-L-L-L-L for five people out of six. Over a nine-fixture season that fudge
   at least had length behind it. Over FOUR fixtures it says nothing at all.

   So: one slot per fixture in the month, in calendar order, carrying the
   actual finishing position. Settled slots are filled, the live ones are
   outlined and show where you stand right now, and a fixture that has not
   opened is an empty slot — which is information too, because it is how much
   of the month is still to play for.
   ------------------------------------------------------------------------ */
.trk{display:flex;gap:3px}
.trk b{
  width:19px;height:19px;border-radius:3px;display:grid;place-items:center;
  font-size:10.5px;font-weight:900;line-height:1;font-family:var(--disp);
  font-variant-numeric:tabular-nums;
}
.trk b.done{background:var(--panel3);color:#fff}
.trk b.win{background:var(--gold);color:var(--onGold)}
.trk b.live{background:none;box-shadow:inset 0 0 0 1px var(--gold);color:var(--gold)}
.trk b.alive{background:none;box-shadow:inset 0 0 0 1px var(--green);color:var(--green)}
.trk b.soon{background:none;box-shadow:inset 0 0 0 1px var(--line);color:var(--t3)}

/* ---------- league table ---------- */
.thead{display:flex;align-items:center;padding:0 13px 7px;gap:12px}
.thead .k{flex:1}
.trow{
  display:flex;align-items:center;gap:11px;width:100%;min-height:62px;padding:9px 13px;
  background:none;border:0;border-top:1px solid var(--line2);color:var(--t1);
  font-family:var(--disp);text-align:left;cursor:pointer;
}
.trow:last-child{border-bottom:1px solid var(--line2)}
.trow.me{background:var(--panel2)}
.trow:active{background:var(--panel3)}
.trow .pos{width:20px;font-family:var(--mono);font-size:14px;color:var(--t3);flex:none}
.trow.me .pos{color:var(--gold)}
.trow .grow{flex:1;min-width:0}
.trow .nm{font-size:15.5px;font-weight:700;letter-spacing:-.012em;display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0}
.trow .l2{display:flex;align-items:center;gap:8px;margin-top:5px}
.trow .l2 span{font-size:10.5px;font-weight:700;letter-spacing:.06em;color:var(--t3);white-space:nowrap}
.trow .pts{display:block;font-family:var(--mono);font-size:21px;font-weight:600;flex:none;text-align:right;min-width:34px}
.trow .delta{display:block;font-family:var(--mono);font-size:10.5px;color:var(--gold);text-align:right;margin-top:3px}
.movein{animation:movein .5s var(--ease) both}
@keyframes movein{from{opacity:0;transform:translateX(-16px)}to{opacity:1;transform:none}}

/* ---------- leaderboard (fixture) ---------- */
.lb{border-top:1px solid var(--line2)}
.lbh{display:flex;align-items:center;padding:0 13px 7px;gap:8px}
.lbr{display:flex;align-items:center;gap:8px;width:100%;min-height:52px;padding:8px 13px;
  background:none;border:0;border-bottom:1px solid var(--line2);color:var(--t1);
  font-family:var(--disp);text-align:left;cursor:pointer}
.lbr.me{background:var(--panel2)}
.lbr:active{background:var(--panel3)}
.lbr .pos{width:18px;font-family:var(--mono);font-size:13px;color:var(--t3);flex:none}
.lbr.me .pos{color:var(--gold)}
.lbr .nm{flex:1;min-width:0;font-size:14.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lbr .raw{width:46px;text-align:right;font-family:var(--mono);font-size:12.5px;color:var(--t2);flex:none}
.lbr .hcp{width:38px;text-align:right;font-family:var(--mono);font-size:12px;flex:none;color:var(--t3)}
.lbr .hcp.on{color:var(--gold)}
.lbr .tot{width:54px;text-align:right;font-family:var(--mono);font-size:16px;font-weight:600;flex:none}
.colh{font-size:9px;font-weight:800;letter-spacing:.1em;color:var(--t3);text-align:right}

/* ---------- chips / tags ---------- */
.tag{
  display:inline-flex;align-items:center;gap:5px;height:20px;padding:0 7px;border-radius:4px;
  font-size:9.5px;font-weight:900;letter-spacing:.1em;white-space:nowrap;
}
.tag.gold{background:var(--gold);color:var(--onGold)}
.tag.red{background:var(--redFill);color:#fff}
.tag.green{background:var(--green);color:var(--onGreen)}
.tag.slate{background:var(--panel3);color:var(--t1)}
.tag.hollow{background:none;border:1px solid var(--line);color:var(--t2)}

/* ---------- buttons ---------- */
.btn{
  display:flex;align-items:center;justify-content:center;gap:8px;width:100%;min-height:52px;
  border-radius:11px;border:1px solid transparent;font-family:var(--disp);font-stretch:112%;
  font-weight:900;font-size:14px;letter-spacing:.09em;cursor:pointer;padding:8px 14px;
  transition:transform .12s var(--ease),filter .12s var(--ease);
}
.btn:active{transform:scale(.975)}
.btn.primary{background:var(--gold);color:var(--onGold)}
.btn.primary:active{filter:brightness(.9)}
.btn.ghost{background:var(--panel);color:var(--t1);border-color:var(--line)}
.btn.ghost:active{background:var(--panel2)}
.btn.danger{background:var(--redFill);color:#fff}
.btn.sm{min-height:44px;font-size:12px}
.sticky{
  padding:10px 16px 12px;background:linear-gradient(180deg,rgba(5,16,28,0),var(--bg) 34%);
  border-top:1px solid var(--line2);flex:none;
}
.sticky .note{font-size:11px;color:var(--t3);text-align:center;margin-top:8px}

/* ---------- segmented ---------- */
.seg{display:flex;background:var(--panel);border:1px solid var(--line2);border-radius:10px;padding:3px;gap:3px}
.seg button{
  flex:1;min-height:44px;border:0;border-radius:8px;background:none;color:var(--t2);cursor:pointer;
  font-family:var(--disp);font-weight:800;font-size:11.5px;letter-spacing:.09em;
}
.seg button[aria-pressed="true"]{background:var(--gold);color:var(--onGold)}
.seg button:active{opacity:.8}

/* ---------- ticker ---------- */
/* 44px, not 34: the ticker is a control (tapping it pauses the crawl, which
   WCAG 2.2.2 requires of anything that moves for more than five seconds) and a
   control has to be reachable by a thumb. */
.ticker{
  flex:none;height:44px;background:var(--bar);border-top:1px solid var(--line2);
  display:flex;align-items:center;overflow:hidden;position:relative;cursor:pointer;
  /* Its repaints are its own business: without this, a 46s crawl invalidates
     the region behind it on every frame. */
  contain:paint;
}
.ticker .lead{
  flex:none;height:100%;display:flex;align-items:center;padding:0 10px;background:var(--redFill);
  color:#fff;font-size:9.5px;font-weight:900;letter-spacing:.14em;z-index:2;
}
.tk-mask{flex:1;overflow:hidden;position:relative;height:100%}
.tk-track{display:flex;align-items:center;height:100%;white-space:nowrap;width:max-content;
  animation:tick 46s linear infinite;will-change:transform}
.ticker.paused .tk-track{animation-play-state:paused}
.tk-track em{
  font-style:normal;font-size:11.5px;font-weight:700;letter-spacing:.06em;color:var(--t2);
  padding:0 14px;display:inline-flex;align-items:center;gap:8px;
}
.tk-track em::before{content:"";width:4px;height:4px;border-radius:50%;background:var(--gold);flex:none}
@keyframes tick{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* ---------- transient lower third ---------- */
/* Sits in the lower third of the frame, where a lower third belongs, and clear
   of both the ticker and any sticky primary action. */
#l3{
  position:absolute;left:0;right:16px;bottom:calc(var(--tabs) + var(--home) + 96px);z-index:35;
  display:flex;pointer-events:none;opacity:0;
}
#l3.on{pointer-events:auto}
#l3 .bar{width:8px;background:var(--gold);flex:none;transform:scaleY(0);transform-origin:bottom;
  will-change:transform}
#l3 .bd{
  flex:1;min-width:0;background:linear-gradient(90deg,#0e2b46 0%,#0b2036 100%);
  border:1px solid var(--line);border-left:0;padding:10px 13px;
  clip-path:inset(0 100% 0 0);box-shadow:0 12px 28px rgba(0,0,0,.5);
}
#l3.on{opacity:1}
#l3.on .bar{animation:l3bar .26s var(--ease) both}
#l3.on .bd{animation:l3body .4s var(--ease) .12s both}
#l3.off .bar{animation:l3bar .22s var(--ease) reverse both}
#l3.off .bd{animation:l3body .26s var(--ease) reverse both}
@keyframes l3bar{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes l3body{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}
#l3 .h{font-stretch:112%;font-size:16px;font-weight:800;letter-spacing:-.01em;margin-top:3px}
#l3 .s{font-size:11.5px;color:var(--t2);margin-top:3px;line-height:1.35}

/* ---------- wipe transition ---------- */
/* visibility:hidden at rest is load-bearing, not belt-and-braces.
   The bars rest at translateX(-102%), which is 102% of EACH BAR'S OWN
   width - and each bar is a third of the screen. So only the first one
   clears the viewport; bars 2 and 3 shift left by one bar-width and sit
   there covering two thirds of the app. It is invisible during the intro
   because #intro (z-index 60) is on top, so the app looks perfect and
   then 'breaks at the end' when the intro clears. */
#wipe{position:absolute;inset:0;z-index:45;pointer-events:none;display:flex;visibility:hidden}
#wipe u{flex:1;background:var(--gold);transform:translateX(-102%) skewX(-8deg);display:block;
  will-change:transform}
#wipe u:nth-child(2){background:#0e3a63}
#wipe u:nth-child(3){background:var(--redFill)}
#wipe.run{pointer-events:auto;visibility:visible}
#wipe.run u{animation:wipe .40s var(--ease) both}
/* Stagger halved from .035/.07. The three bars sit side by side, each covering a
   THIRD of the screen, so the screen is only fully hidden while all three are
   simultaneously at translateX(0). At the old timings bar one began leaving
   (220ms) BEFORE bar three had arrived (250ms) — there was no such moment, and
   the repaint underneath was always partly in view. */
#wipe.run u:nth-child(2){animation-delay:.02s}
#wipe.run u:nth-child(3){animation-delay:.04s}
/* Hold widened 45–55% to 40–66%. Covered: bar1 160–264ms, bar2 180–284,
   bar3 200–304 — so all three overlap from 200ms to 264ms. That 64ms is the
   only safe place to rebuild the screen, and transition() now paints at 205. */
@keyframes wipe{
  0%{transform:translateX(-102%) skewX(-8deg)}
  40%{transform:translateX(0) skewX(-8deg)}
  66%{transform:translateX(0) skewX(-8deg)}
  100%{transform:translateX(102%) skewX(-8deg)}
}

/* ---------- the matchday intro (signature moment) ---------- */
#intro{position:absolute;inset:0;z-index:60;background:var(--bg);overflow:hidden}
#intro .ibar{position:absolute;top:-8%;height:116%;width:150%;left:-25%;
  transform:translateX(-115%) skewX(-11deg);will-change:transform}
/* GATED BEHIND .play / .out, AND THAT IS THE WHOLE BUG FIX.
 *
 * These used to be bare `animation:` declarations, which start the instant the
 * stylesheet is parsed. So the entire 1.6s intro ran ONCE during module load —
 * unwatched, competing with script evaluation — and then runIntro() restarted
 * every one of them by hand after `await openData()`. The visible result was the
 * intro starting, jumping back to zero and replaying; and when the Supabase
 * import off the CDN was slow, a full intro followed by a blank dark screen
 * followed by the replay. Reported as "loading into the app is the worst of all"
 * and it was the accurate description.
 *
 * Now: nothing moves until JS adds .play, and the exit is a separate .out phase
 * the app triggers when the data is actually ready — so the animation can never
 * finish before the app behind it does. .out must stay BELOW .play here: equal
 * specificity, so source order is what lets it win. */
/* The colours are UNGATED and live on their own line, deliberately. They were
   originally bundled into the same rule as the animation; splitting that rule
   into .play/.out phases dropped all three backgrounds and the bars swept
   through invisibly for one deploy. Appearance does not belong in a rule that
   exists to control timing. */
#intro .b1{background:#0e3a63}
#intro .b2{background:var(--redFill)}
#intro .b3{background:var(--bg)}
#intro.play .b1{animation:iIn .42s var(--ease) both}
#intro.play .b2{animation:iIn .42s var(--ease) .06s both}
#intro.play .b3{animation:iIn .42s var(--ease) .12s both}
#intro.out  .b1{animation:iOut .40s var(--ease) both}
#intro.out  .b2{animation:iOut .40s var(--ease) .05s both}
#intro.out  .b3{animation:iOut .40s var(--ease) .10s both}
@keyframes iIn{from{transform:translateX(-115%) skewX(-11deg)}to{transform:translateX(-25%) skewX(-11deg)}}
/* iOut starts where iIn's `both` fill left the bar, so the two phases join with
   no jump even though they are now separate animations. */
@keyframes iOut{from{transform:translateX(-25%) skewX(-11deg)}to{transform:translateX(115%) skewX(-11deg)}}
#intro .iwrap{position:absolute;left:26px;right:26px;top:44%;transform:translateY(-50%)}
#intro .il{overflow:hidden}
#intro .il span{
  display:block;font-stretch:125%;font-weight:900;font-size:47px;letter-spacing:-.035em;line-height:.94;
  transform:translateY(105%);will-change:transform;
}
#intro .il2 span{color:var(--gold)}
#intro.play .il1 span{animation:iUp .44s var(--ease) .34s both}
#intro.play .il2 span{animation:iUp .44s var(--ease) .44s both}
#intro.out  .il1 span{animation:iDown .32s var(--ease) both}
#intro.out  .il2 span{animation:iDown .32s var(--ease) .05s both}
@keyframes iUp{from{transform:translateY(105%)}to{transform:translateY(0)}}
@keyframes iDown{from{transform:translateY(0)}to{transform:translateY(-105%)}}
#intro .irule{height:3px;background:var(--gold);margin:14px 0 12px;transform:scaleX(0);transform-origin:left}
#intro.play .irule{animation:iRule .5s var(--ease) .66s both}
#intro.out  .irule{animation:iRuleOut .3s var(--ease) both}
@keyframes iRule{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes iRuleOut{from{transform:scaleX(1);transform-origin:right}to{transform:scaleX(0);transform-origin:right}}
#intro .imeta{
  font-size:12px;font-weight:800;letter-spacing:.22em;color:var(--t2);opacity:0;
}
#intro.play .imeta{animation:iFade .4s var(--ease) .82s both}
#intro.out  .imeta{animation:iFadeOut .26s var(--ease) both}
@keyframes iFade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes iFadeOut{from{opacity:1}to{opacity:0}}
#intro.gone{display:none}

/* ---------- sheets ---------- */
/* The scrim starts below the status band and the sheet stops short of it, so
   even a full-height sheet never paints into the 62px reserved at the top. */
#scrim{position:absolute;top:var(--band);left:0;right:0;bottom:0;background:rgba(2,8,15,.72);z-index:50;opacity:0;pointer-events:none;transition:opacity .26s var(--ease)}
#scrim.on{opacity:1;pointer-events:auto}
.sheet{
  position:absolute;left:0;right:0;bottom:0;z-index:52;background:var(--bg);
  border-top:2px solid var(--gold);border-radius:16px 16px 0 0;
  max-height:calc(100% - var(--band) - 18px);display:flex;flex-direction:column;
  transform:translateY(102%);transition:transform .34s var(--ease);box-shadow:0 -18px 44px rgba(0,0,0,.6);
}
.sheet.on{transform:none}
.sheeth{display:flex;align-items:center;gap:10px;padding:12px 8px 12px 16px;border-bottom:1px solid var(--line2);flex:none}
.sheeth .grow{flex:1;min-width:0}
.sheetb{overflow-y:auto;padding:14px 16px 4px;flex:1;min-height:0}
.sheetf{padding:12px 16px 16px;border-top:1px solid var(--line2);flex:none;background:var(--bg)}

/* ---------- log sheet ---------- */
.bignum{display:flex;align-items:baseline;justify-content:center;gap:10px;padding:6px 0 2px}
.bignum .v{font-family:var(--mono);font-size:58px;font-weight:600;line-height:1;letter-spacing:-.03em}
.bignum .u{font-size:15px;font-weight:800;letter-spacing:.14em;color:var(--t3)}
.stepper{display:flex;align-items:center;gap:10px;margin-top:10px}
.stepper button{
  width:52px;height:52px;border-radius:12px;background:var(--panel);border:1px solid var(--line);
  color:var(--t1);display:grid;place-items:center;cursor:pointer;flex:none;
}
.stepper button:active{background:var(--panel2)}
.slider{flex:1;height:52px;display:flex;align-items:center}
input[type=range]{
  -webkit-appearance:none;appearance:none;width:100%;height:44px;background:transparent;cursor:pointer;margin:0;
}
input[type=range]::-webkit-slider-runnable-track{height:6px;background:var(--panel3);border-radius:3px}
input[type=range]::-moz-range-track{height:6px;background:var(--panel3);border-radius:3px}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;width:28px;height:28px;border-radius:50%;background:var(--gold);
  margin-top:-11px;border:3px solid var(--bg);box-shadow:0 2px 8px rgba(0,0,0,.5);
}
input[type=range]::-moz-range-thumb{
  width:28px;height:28px;border-radius:50%;background:var(--gold);border:3px solid var(--bg);
}
.chips{display:flex;gap:8px;margin-top:10px}
.chips button{
  flex:1;min-height:46px;border-radius:10px;background:var(--panel);border:1px solid var(--line2);
  color:var(--t1);font-family:var(--mono);font-size:14px;cursor:pointer;
}
.chips button[aria-pressed="true"]{border-color:var(--gold);background:var(--goldWash);color:var(--gold)}
.chips button:active{background:var(--panel2)}
.conseq{margin-top:14px;border:1px solid var(--line2);border-radius:11px;overflow:hidden}
.conseq div{
  display:flex;align-items:flex-start;gap:9px;padding:10px 12px;font-size:12.5px;line-height:1.4;
  border-bottom:1px solid var(--line2);color:var(--t2);background:var(--panel);
}
.conseq div:last-child{border-bottom:0}
.conseq div.hit{background:var(--goldWash);color:var(--t1);font-weight:600}
.conseq div.hit .mk{color:var(--gold)}
.conseq .mk{flex:none;margin-top:1px;color:var(--t3)}

/* ---------- toast ---------- */
#toast{
  position:absolute;left:16px;right:16px;bottom:calc(var(--tabs) + var(--home) + 54px);z-index:58;
  background:var(--panel2);border:1px solid var(--line);border-radius:11px;padding:12px 14px;
  font-size:12.5px;color:var(--t1);line-height:1.4;opacity:0;transform:translateY(14px);
  transition:opacity .24s var(--ease),transform .24s var(--ease);pointer-events:none;
}
#toast.on{opacity:1;transform:none}

/* ---------- misc ---------- */
.statgrid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.stat{background:var(--panel);border:1px solid var(--line2);border-radius:11px;padding:12px}
.stat .v{font-family:var(--mono);font-size:24px;font-weight:600;line-height:1}
.stat .l{font-size:9.5px;font-weight:800;letter-spacing:.12em;color:var(--t3);margin-top:6px}
.kv{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:11px 0;border-bottom:1px solid var(--line2)}
.kv:last-child{border-bottom:0}
.kv .l{font-size:12.5px;color:var(--t2)}
.kv .v{font-family:var(--mono);font-size:14px;font-weight:500;flex:none}
.bars{display:flex;align-items:flex-end;gap:5px;height:78px}
.bars .b{flex:1;display:flex;flex-direction:column;justify-content:flex-end;height:100%;gap:5px}
.bars .b u{display:block;background:var(--panel3);border-radius:3px 3px 0 0;transition:height .5s var(--ease)}
.bars .b.on u{background:var(--gold)}
.bars .b em{font-style:normal;font-family:var(--mono);font-size:9.5px;color:var(--t3);text-align:center}
.msg{display:flex;gap:9px;margin-bottom:10px}
.msg .bub{background:var(--panel);border:1px solid var(--line2);border-radius:11px;padding:9px 11px;flex:1;min-width:0}
.msg .who{font-size:11px;font-weight:800;letter-spacing:.06em;color:var(--gold);margin-bottom:3px}
.msg .tx{font-size:13px;line-height:1.42;color:var(--t1);word-wrap:break-word}
.msg .wh{font-size:10px;color:var(--t3);margin-top:4px}
.compose{display:flex;gap:8px;align-items:center;margin-top:4px}
.compose input{
  flex:1;min-width:0;height:48px;border-radius:11px;background:var(--panel);border:1px solid var(--line);
  color:var(--t1);padding:0 13px;font-family:var(--disp);font-size:13.5px;
}
.compose input::placeholder{color:var(--t3)}
.compose button{width:48px;height:48px;border-radius:11px;background:var(--gold);border:0;color:var(--onGold);display:grid;place-items:center;cursor:pointer;flex:none}
.compose button:active{filter:brightness(.9)}
.check{display:flex;gap:11px;padding:13px 0;border-bottom:1px solid var(--line2);align-items:flex-start}
.check:last-child{border-bottom:0}
.check .mk{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;flex:none;margin-top:1px}
.check .mk.bad{background:var(--redFill);color:#fff}
.check .mk.good{background:var(--green);color:var(--onGreen)}
.check .t{font-size:13px;font-weight:700}
.check .d{font-size:11.5px;color:var(--t2);margin-top:3px;line-height:1.4}
.stamp{
  display:inline-block;border:3px solid var(--red);color:var(--red);border-radius:6px;
  padding:5px 12px;font-stretch:112%;font-weight:900;font-size:20px;letter-spacing:.1em;
  transform:rotate(-6deg);
}
/* ---------- the written report / round-up ---------- */
.prose p{font-size:14.5px;line-height:1.62;color:var(--t1);margin:0 0 11px}
.prose p:last-child{margin-bottom:0}
.prose p b{color:var(--gold);font-weight:800}
.prose p.lede{font-stretch:112%;font-size:17px;font-weight:700;line-height:1.44;letter-spacing:-.01em}
.byline{font-size:10px;font-weight:800;letter-spacing:.14em;color:var(--t3);text-transform:uppercase}
.movers{border-top:1px solid var(--line2)}
.mover{display:flex;align-items:center;gap:10px;padding:10px 0;border-bottom:1px solid var(--line2)}
.mover .nm{flex:1;min-width:0;font-size:14px;font-weight:600}
.mover .wk{font-family:var(--mono);font-size:13px;color:var(--t2);width:56px;text-align:right;flex:none}
.mover .mv{font-family:var(--mono);font-size:12.5px;width:46px;text-align:right;flex:none}

/* ---------- switches (notification settings) ---------- */
.swrow{
  display:flex;align-items:flex-start;gap:12px;width:100%;min-height:64px;padding:13px;
  background:var(--panel);border:1px solid var(--line2);border-radius:12px;color:var(--t1);
  font-family:var(--disp);text-align:left;cursor:pointer;margin-bottom:8px;
}
.swrow:active{background:var(--panel2)}
.swrow .grow{flex:1;min-width:0}
.swrow .tn{display:block;font-size:14.5px;font-weight:700}
.swrow .ts{display:block;font-size:12px;color:var(--t2);margin-top:4px;line-height:1.42}
.sw{width:48px;height:28px;border-radius:14px;background:var(--panel3);flex:none;position:relative;
    transition:background .2s var(--ease);margin-top:2px}
.sw i{position:absolute;top:3px;left:3px;width:22px;height:22px;border-radius:50%;background:var(--t2);
      transition:transform .2s var(--ease),background .2s var(--ease)}
.swrow[aria-checked="true"] .sw{background:var(--gold)}
.swrow[aria-checked="true"] .sw i{transform:translateX(20px);background:var(--onGold)}

/* ---------- the tie ballot ---------- */
.pick{
  display:flex;gap:11px;align-items:flex-start;width:100%;min-height:64px;padding:12px 13px;
  background:var(--panel);border:1px solid var(--line2);border-radius:12px;color:var(--t1);
  font-family:var(--disp);text-align:left;cursor:pointer;margin-bottom:8px;
}
.pick[aria-pressed="true"]{border-color:var(--gold);background:var(--goldWash)}
.pick .mk{width:22px;height:22px;border-radius:50%;border:2px solid var(--line);flex:none;margin-top:1px;
          display:grid;place-items:center;color:var(--goldWash)}
.pick[aria-pressed="true"] .mk{border-color:var(--gold);color:var(--gold)}
.pick .pn{display:block;font-size:15px;font-weight:700}
.pick .ps{display:block;font-size:12px;color:var(--t2);margin-top:4px;line-height:1.4}

/* ---------- the money-mode banner ---------- */
/* The one thing the money screen must say without being asked is which of the
   three settlement models this season is running. It is the first block on the
   screen and it is repeated in miniature anywhere else money is quoted. */
.mode{display:flex;align-items:flex-start;gap:11px;padding:13px;background:var(--panel2);
      border:1px solid var(--line);border-radius:12px}
.mode .grow{flex:1;min-width:0}
.modeline{display:inline-flex;align-items:center;gap:6px;height:20px;padding:0 7px;border-radius:4px;
          background:var(--panel3);color:var(--t1);font-size:9.5px;font-weight:900;letter-spacing:.1em;white-space:nowrap}

.potwrap{position:relative;padding:20px 16px 0;background:
  radial-gradient(90% 60% at 50% 0%, #2a1f05 0%, rgba(42,31,5,0) 62%),
  linear-gradient(180deg,#0d2740 0%,var(--bg) 62%);min-height:100%}
.an1{animation:enterTab .4s var(--ease) both}
.an2{animation:enterTab .4s var(--ease) .1s both}
.an3{animation:enterTab .4s var(--ease) .2s both}
.an4{animation:enterTab .4s var(--ease) .3s both}
.an5{animation:enterTab .4s var(--ease) .4s both}
.pop{animation:pop .5s var(--ease) both}
@keyframes pop{from{opacity:0;transform:scale(.72)}to{opacity:1;transform:none}}

/* ---------- reduced motion: cut everything to near zero ---------- */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-delay:0ms!important;
    animation-iteration-count:1!important;transition-duration:.01ms!important;
  }
  .tk-track{animation:none!important;transform:none!important}
  .tk-mask{overflow-x:auto}
  /* No auto-advance under reduced motion, so the progress line would be a lie.
     The dots become the only way the bar moves — see bugStart(). */
  .bugprog{display:none}
  #intro .il span{transform:none!important}
  #intro .irule{transform:scaleX(1)!important}
  #intro .imeta{opacity:1!important}
}

/* ==========================================================================
   PORT ADDITIONS — everything below this line did not exist in the prototype,
   because the prototype had no other people in it.

   Three things the real app needs that a single-file mock did not: a way in
   (sign in), a way to say which backend you are on (the connection line), and
   something to show a crew whose season has not started yet.
   ========================================================================== */

/* ---------- the way in ---------- */
.gate{padding:26px 20px 20px;min-height:100%;display:flex;flex-direction:column;
  background:radial-gradient(120% 70% at 80% -10%, #14416b 0%, rgba(20,65,107,0) 58%),
             linear-gradient(170deg,#0b2136 0%,#082033 44%,var(--bg) 100%)}
.gate .lede{font-size:14px;line-height:1.55;color:var(--t2);margin:10px 0 0}
.field{margin-top:18px}
.field label{display:block;font-size:10.5px;font-weight:800;letter-spacing:.15em;
  color:var(--t3);text-transform:uppercase;margin-bottom:8px}
.field input{
  width:100%;min-height:52px;background:#061524;border:1px solid var(--line);
  border-radius:11px;color:var(--t1);padding:0 14px;font-family:var(--disp);
  font-size:16px;   /* 16px or iOS Safari zooms the whole app on focus */
  font-weight:600;
}
.field input::placeholder{color:#5b7a96}
.field input:focus{outline:2px solid var(--gold);outline-offset:1px;border-color:transparent}
.gate .err{color:var(--red);font-size:13px;line-height:1.4;margin:10px 2px 0;min-height:17px}
.gate .foot{margin-top:auto;padding-top:22px;font-size:11.5px;line-height:1.6;color:var(--t3)}
.whoami{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}
.whoami button{
  min-height:44px;padding:0 13px;border-radius:10px;background:var(--panel);
  border:1px solid var(--line2);color:var(--t1);font-family:var(--disp);
  font-size:13px;font-weight:700;cursor:pointer;display:inline-flex;align-items:center;gap:8px;
}
.whoami button:active{background:var(--panel2)}

/* ---------- which backend you are on ----------
   It is a fact about the app, not a decoration, so it is readable text and not
   only a coloured dot: "local only" and "live" behave completely differently
   and a person who cannot tell which they are on cannot trust either. */
.conn{display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 8px;border-radius:4px;
  background:var(--panel3);color:var(--t2);font-size:9px;font-weight:900;letter-spacing:.11em;
  white-space:nowrap;flex:none}
.conn i{width:6px;height:6px;border-radius:50%;background:var(--t3);flex:none}
.conn.live{background:var(--greenWash);color:var(--green);box-shadow:inset 0 0 0 1px #154a2e}
.conn.live i{background:var(--green)}
.conn.off{background:var(--goldWash);color:var(--gold);box-shadow:inset 0 0 0 1px #4a3a10}
.conn.off i{background:var(--gold)}

/* ---------- an empty season ---------- */
.empty{padding:30px 8px;text-align:center}
.empty .ttl{font-stretch:112%;font-size:19px;font-weight:800;letter-spacing:-.01em}
.empty .sub{font-size:13px;line-height:1.55;color:var(--t2);margin-top:8px}
.spin{display:inline-block;width:15px;height:15px;border-radius:50%;
  border:2px solid rgba(255,197,61,.25);border-top-color:var(--gold);animation:spin .8s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion: reduce){ .spin{animation-duration:1.6s!important} }
