/* Committed light design — the page stays white on any host theme. */
:root, :root[data-theme="dark"], :root[data-theme="light"]{
  color-scheme:light;
  --paper:#D5D5FF; --card:#FFFFFF; --card2:#F6F6FD;
  --ink:#181A42; --ink2:#3D4270; --muted:#565C8C;
  --line:#D3D5EF; --line2:#EAEBF8;
  --sky:#4FB3E8; --sky-deep:#1F7FC4; --sky-soft:#DCEFFB;
  --pink:#FF2E88; --pink-deep:#D80F68; --pink-soft:#FFE1EE;
  /* Divisions: A pink, BB/B2 sky, B purple. Held apart from the court and time
     palettes even where a hex repeats, so recolouring one can't move another. */
  --purple:#6742C9; --purple-soft:#E8E3FB;
  --live:#0E9B66; --live-soft:#D9F3E8;
  /* A draft season, which only a signed-in manager can see. Amber: not live
     green, not the pink that means "this is the thing". */
  --draft:#B45309; --draft-soft:#FDF0DC;
  /* Courts own colour on the overview and courtside. Six is enough for any
     day UVC runs. Today is the exception — see --slot-a below. */
  --court1:#1F7FC4; --court2:#D80F68; --court3:#6742C9;
  --court4:#0E7C8C; --court5:#155E86; --court6:#8A2E63;
  /* Today colours by start time instead: every game at 5:30 blue, every game
     at 7:00 purple, alternating from there. The app's blue and purple, held
     separately from the court palette so recolouring a court can't quietly
     restyle a time block. */
  --slot-a:#1F7FC4; --slot-b:#6742C9;
  --slot-a-soft:#DCEFFB; --slot-b-soft:#E8E3FB;
  /* Courtside is its own world: a dark purple ground, not the app's lavender. */
  --courtside:#241748;
  --court1-soft:#DCEFFB; --court2-soft:#FFE1EE; --court3-soft:#E8E3FB;
  --court4-soft:#DCF0F3; --court5-soft:#D9E7F5; --court6-soft:#F9E2EE;
  --shadow:0 1px 2px rgba(24,26,66,.06),0 8px 24px -12px rgba(24,26,66,.28);
  --shadow-lg:0 24px 70px -20px rgba(24,26,66,.5);
  --display:"Avenir Next Condensed","Avenir Next","Futura","Trebuchet MS",system-ui,sans-serif;
  --body:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
  --num:"SF Mono",ui-monospace,"Roboto Mono",Menlo,Consolas,monospace;
  --r:14px;
  /* The dock's own height, so anything that has to clear it measures from one
     number. --kb is what the on-screen keyboard covers, kept up to date by
     trackKeyboard() in app.js; it is 0px on every desktop. */
  --dock:55px;
  --kb:0px;
}
*{box-sizing:border-box}
body{
  margin:0; background:var(--paper); color:var(--ink);
  font-family:var(--body); font-size:15px; line-height:1.5;
  -webkit-font-smoothing:antialiased;
}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
/* No double-tap zoom anywhere; pinch is off via the viewport meta. */
html{touch-action:manipulation;-webkit-text-size-adjust:100%}
:focus-visible{outline:2.5px solid var(--pink);outline-offset:2px;border-radius:6px}
.wrap{max-width:1180px;margin:0 auto;padding:0 20px}

/* ---------- top bar ---------- */
.topbar{
  background:var(--paper);
  border-bottom:1px solid var(--line);
}
.topbar .wrap{display:flex;align-items:center;gap:18px;height:62px}
.mark{display:flex;align-items:center;text-decoration:none;color:inherit}
/* The rule carries the ramp, run through the app's purple rather than straight
   from sky to pink, which greys where those two hues cross. Two backgrounds do
   it: the ramp fills the border box, the paper fills the padding box, and the
   border is the sliver of ramp left showing between them. Which means the
   border colour has to stay transparent — give it one and the ramp disappears
   behind it. */
.marklock{
  display:inline-flex;align-items:center;gap:8px;padding:6px 11px;
  border:1.4px solid transparent;border-radius:10px;
  background:linear-gradient(var(--paper),var(--paper)) padding-box,
             linear-gradient(96deg,var(--sky-deep),var(--purple),var(--pink)) border-box;
}
/* Clipping the background to the glyph turns the emoji into a silhouette the
   wordmark's gradient can fill. A browser that won't clip a colour glyph just
   draws the emoji as itself, which is a fine place to land. */
.mark .uni{
  font-size:32px;line-height:1;
  background-image:linear-gradient(96deg,var(--sky-deep),var(--purple),var(--pink));
  -webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;
}
/* Both lines are one SVG text each, forced to the same measure with textLength.
   lengthAdjust stays at its default, so only the gaps stretch and the letters
   keep the shapes the face drew — spacingAndGlyphs would widen the letterforms
   themselves and it would stop being the app's type.

   The top line is set at twice the bottom one because UNICORN is seven
   characters against fifteen: at one size the short line needs roughly double
   the tracking to reach the same width and stops reading as a word. At 36 over
   18 both lines track at about .12em. */
/* A club's own logo in the unicorn's place (worker/brand.js), as tall as the
   wordmark beside it. */
.mark .logo{display:block;height:34px;width:auto}
.marklock svg{display:block;height:30px;width:auto}
.marklock text{font-family:var(--display);font-weight:700;fill:var(--ink)}
.marklock .m1{font-size:36px}
.marklock .m2{font-size:18px}

/* Not the live league. The class is set by the script in the page head, and the
   only thing it does is turn this strip on — the mark stays in its real colours,
   because judging those is the whole point of it. Grey and small: it should read
   as chrome you can check when you wonder, not as a warning. */
.devbar{display:none;margin:0}
html.notprod .devbar{
  display:block;background:var(--ink2);color:var(--paper);text-align:center;
  font-family:var(--display);font-size:9px;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;padding:2px 10px;opacity:.75;
}

.seasonpick{
  display:flex;align-items:center;gap:7px;padding:7px 14px;border-radius:999px;
  font-family:var(--display);font-size:12.5px;line-height:20px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink2);font-weight:700;white-space:nowrap;
}
/* Condensed all-caps beside the nav's body type sits a hair high on its own
   metrics; drop the label onto the same baseline as Today and Overview. */
.seasonpick>*{transform:translateY(1px)}
.seasonpick:hover{color:var(--ink);background:var(--line2)}
.seasonpick svg{opacity:.55}
.menu .tagline{display:block;font-family:var(--body);font-size:11.5px;letter-spacing:0;text-transform:none;color:var(--muted);font-weight:400;margin-top:1px}
.menu button[aria-current="true"] .tagline{color:var(--ink2)}
.topright{
  display:flex;align-items:center;gap:2px;margin-left:auto;
  padding:3px;background:var(--card);border:1px solid var(--line);
  border-radius:999px;box-shadow:var(--shadow);
}
.topdiv{width:1px;height:20px;background:var(--line);margin:0 5px;flex:none}
/* The signed-in manager's way back to their screen, in the picker's own dress. */
.mgrlink{
  display:flex;align-items:center;gap:7px;padding:7px 12px;border-radius:999px;text-decoration:none;
  font-family:var(--display);font-size:12.5px;line-height:20px;letter-spacing:.1em;
  text-transform:uppercase;font-weight:700;color:var(--pink-deep);white-space:nowrap;
}
.mgrlink:hover{background:var(--pink-soft)}
.mgrlink i{width:7px;height:7px;border-radius:50%;background:var(--live);box-shadow:0 0 0 3px var(--live-soft)}
.mgrlink[hidden],.topdiv[hidden]{display:none}
.seg{display:flex;gap:2px}
.seg button,.seg a{
  padding:7px 17px;border-radius:999px;font-size:13.5px;line-height:20px;font-weight:600;
  color:var(--ink2);transition:background .16s,color .16s;
}
.seg a{text-decoration:none}
.seg button[aria-current="page"],.seg a[aria-current="page"]{background:var(--ink);color:var(--paper)}
.seg button:hover:not([aria-current="page"]),.seg a:hover:not([aria-current="page"]){background:var(--line2)}

/* The date heading is the day picker. Nothing is drawn around it — a heading
   that big doesn't need a border to look pressable, and the chevron is the only
   thing that has to say so. */
.daytitle{margin:0}
.daytitle button{
  display:inline-flex;align-items:center;gap:11px;font:inherit;color:inherit;
  padding:0;margin:0;text-align:left;max-width:100%;
}
.daytitle button > span{overflow:hidden;text-overflow:ellipsis}
.daytitle svg{
  flex:none;opacity:.4;margin-top:.12em;
  transition:opacity .15s,transform .18s;
}
.daytitle button:hover svg{opacity:.75}
.daytitle button[aria-expanded="true"] svg{opacity:.75;transform:rotate(180deg)}
.daytitle button:focus-visible{outline-offset:4px}

/* ---------- shared bits ---------- */
.eyebrow{
  font-family:var(--display);font-size:11.5px;font-weight:600;letter-spacing:.19em;
  text-transform:uppercase;color:var(--muted);
}
h1,h2,h3{font-family:var(--display);font-weight:700;letter-spacing:-.005em;text-wrap:balance;margin:0}
h1{font-size:40px;line-height:1.04}
h2{font-size:23px}
h3{font-size:16px}
.chip{
  display:inline-flex;align-items:center;gap:5px;padding:2.5px 9px;border-radius:999px;
  font-size:11px;font-weight:700;letter-spacing:.06em;font-family:var(--display);
  border:1px solid transparent;text-transform:uppercase;
}
.chip.A{background:var(--pink-soft);color:var(--pink-deep)}
.chip.BB,
.chip.B2{background:var(--sky-soft);color:var(--sky-deep)}
.chip.B{background:var(--purple-soft);color:var(--purple)}
.chip.X{background:transparent;color:var(--muted);border-color:var(--line);border-style:dashed}
.chip.live{background:var(--live-soft);color:var(--live)}
.num{font-family:var(--num);font-variant-numeric:tabular-nums}

/* ---------- today ---------- */
/* The dock is fixed and floats clear of the bottom edge, so the page has to end
   above it: its own height, the gap under it, and room to breathe. Games pass
   under the glass on the way there, which is the point of the glass. */
main{padding:10px 0 calc(var(--dock) + 33px + env(safe-area-inset-bottom))}

/* ---------- a team's own sheet ---------- */
/* The standings row is the tap target, so it has to look like one. */
.divcard tbody tr[data-team]{cursor:pointer}
.divcard tbody tr[data-team]:hover{background:var(--card2)}
.divcard tbody tr.top[data-team]:hover{background:var(--pink-soft)}
.divcard .tm button{
  font:inherit;color:inherit;text-align:left;padding:0;width:100%;
}
.divcard .tm button:focus-visible{outline-offset:3px}

.tstats{display:flex;gap:22px;flex-wrap:wrap;padding:2px 19px 16px}
.tstat{display:flex;flex-direction:column}
.tstat .v{font-family:var(--num);font-size:19px;font-weight:700;line-height:1.15}
.tstat .k{font-family:var(--display);font-size:9.5px;letter-spacing:.15em;text-transform:uppercase;color:var(--muted)}

.tsect{padding:14px 19px;border-top:1px solid var(--line2);display:flex;flex-direction:column;gap:9px}
.tnone{margin:0;font-size:13.5px;color:var(--muted)}

.tgames{display:flex;flex-direction:column}
.tgame{
  display:flex;align-items:baseline;gap:11px;width:100%;text-align:left;
  padding:9px 9px 9px 11px;border-radius:8px;border-bottom:1px solid var(--line2);
  border-left:3px solid transparent;
}
.tgame:last-child{border-bottom:0}
.tgame:hover{background:var(--card2)}
.tgame .when{font-family:var(--num);font-size:11px;color:var(--muted);flex:none;width:46px}
.tgame .who{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px}
.tgame .sc{margin-left:auto;display:flex;gap:9px;font-family:var(--num);font-size:11.5px;color:var(--muted);flex:none}
.tgame .sc s{text-decoration:none}
.tgame .sc s.w{font-weight:700;color:var(--ink)}
/* A shade up from the line colour: a whole column of dots at --line reads as
   damage rather than as an empty set waiting to be filled. */
.tgame .sc s.e{color:color-mix(in srgb,var(--muted) 35%,var(--line))}
/* The next match is the line the season has reached. Green is already the app's
   colour for live and current, and it marks how far along the list you are. */
.tgame.next{background:var(--live-soft);border-left-color:var(--live)}
.tgame.next:hover{background:var(--live-soft)}
.tgame.next .when{color:var(--live);font-weight:700}
.tgame.next .who{font-weight:600}

/* ---------- bottom tabs ---------- */
/* A dock at every width: as wide as its three labels and no wider, floated clear
   of the bottom edge. Fixed, which the top bar deliberately isn't — this one is
   thumb-height, and the schedule runs to a whole season, so nav that scrolls away
   is nav you have to go back for. Below the scoresheet (100) and courtside (150)
   on purpose; both should cover it.

   left:0;right:0 with margin-inline:auto, never left:50%: a fixed element with
   auto width shrinks to fit the space from its left edge to the viewport's, so
   left:50% would hand it half the screen to lay out in.

   Four tabs, each with its name: a 300px pill on a 375px screen. Measured in
   design/dock-four.html and chosen by the owner over icons-only — plenty of
   the apps in her pocket run four named tabs, and a name beats a guess. */
/* The dock floats 14px clear of the bottom edge, and the shadow has to be spent
   before it gets there. A shadow that reaches past the window is cut off flat by
   the edge, and on iOS that shows as a hard grey line under the pill.

   How far a shadow reaches past the box: offset-y + blur/2 + spread. Every one
   below is inside 5px against that 14px gap — plus whatever the home indicator
   adds — so all of them are at zero well before the window ends. Change these
   and check that sum. */
.tabs{
  position:fixed;left:0;right:0;bottom:calc(14px + env(safe-area-inset-bottom));
  z-index:50;margin-inline:auto;width:fit-content;
  display:flex;gap:2px;padding:3px;border-radius:999px;
  background:var(--card);
  border:1px solid color-mix(in srgb,var(--ink) 13%,transparent);
  /* Two shadows, not one: a tight dark edge to lift it off whatever it's over,
     and a wider soft one for the height. A single large blur reads as haze. */
  box-shadow:0 2px 6px rgba(24,26,66,.10), 0 5px 14px -8px rgba(24,26,66,.34);
}
/* Glass, only where the browser can actually blur — without the blur a
   see-through bar just looks like a rendering fault, so that case keeps the
   solid card above. Three things make it glass rather than frost: the fill is
   thin at 48%, saturation runs past 1 so the courts behind bloom instead of
   going grey, and a specular rim — bright along the top edge, dimmer along the
   bottom — makes it read as lit rather than tinted.

   The fill is flat, not a top-to-bottom sheen. A sheen is the usual way to fake
   thickness, but the page under it is lavender, so the thin end let the paper
   through and the bar picked up a purple cast that slid as you scrolled. */
@supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .tabs{
    border:0;
    background:color-mix(in srgb,var(--card) 48%,transparent);
    -webkit-backdrop-filter:blur(26px) saturate(220%) brightness(1.07);
    backdrop-filter:blur(26px) saturate(220%) brightness(1.07);
    /* Same rim and edge as before; only the drop is smaller, so it ends inside
       the page instead of being cut off flat by the bottom of the window. */
    box-shadow:
      inset 0 1px 0 0 rgba(255,255,255,.92),
      inset 0 -1px 0 0 rgba(255,255,255,.32),
      0 0 0 1px rgba(24,26,66,.07),
      0 2px 6px rgba(24,26,66,.09),
      0 5px 14px -8px rgba(24,26,66,.40);
  }
}
/* Asked for less of this, get a solid bar. */
@media (prefers-reduced-transparency:reduce){
  .tabs{
    background:var(--card);
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }
}

.tabs button,.tabs a{
  padding:7px 20px;border-radius:999px;
  display:flex;flex-direction:column;align-items:center;gap:1px;
  font-family:var(--display);font-size:9.5px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted);transition:background .15s,color .15s;
}
.tabs a{text-decoration:none}
.tabs button svg,.tabs a svg{stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
/* Solid, against thin material. This is the one thing on the bar that has to be
   readable without looking, and a second piece of glass wasn't. */
.tabs button[aria-current="page"],.tabs a[aria-current="page"]{color:var(--pink-deep);background:var(--paper)}
.tabs button:focus-visible,.tabs a:focus-visible{outline-offset:-3px}
/* Condensed all-caps carries no descender, so its ink sits above the middle of
   its own line box: centring the boxes leaves the label reading high under a
   geometrically centred icon. Measured at 0.75px for this size — a round 1px
   overshoots the other way. The season picker makes the same correction. */
.tabs button > span,.tabs a > span{transform:translateY(0.75px)}
/* Courtside owns the whole screen; nothing of the app shows through. */
html.courtside-open .tabs{display:none}

/* With a mouse there is room to set the label beside its icon, and a hover state
   to earn. The material is the same at every width — one dock, one language. */
@media (min-width:820px){
  .tabs{bottom:18px}
  .tabs button,.tabs a{flex-direction:row;gap:8px;padding:8px 18px;font-size:11px}
  .tabs button:hover:not([aria-current="page"]),.tabs a:hover:not([aria-current="page"]){background:var(--line2);color:var(--ink2)}
}
.dayhead{display:flex;flex-wrap:wrap;align-items:flex-end;gap:12px 20px;margin-bottom:6px}
.dayhead>div{min-width:0}
.dayhead h1{font-size:clamp(27px,3.4vw,40px);white-space:nowrap}
.dayhead .daypill{margin-left:auto;margin-bottom:4px}
.rulestrip{
  margin:14px 0 0;font-size:12px;color:var(--ink2);
  display:flex;flex-wrap:wrap;gap:3px 14px;align-items:center;
}
.rulestrip strong{font-family:var(--display);letter-spacing:.13em;text-transform:uppercase;font-size:10.5px;color:var(--muted)}

/* ---------- filters ---------- */
.filters{
  display:flex;flex-wrap:wrap;gap:8px;align-items:center;
  margin:16px 0 14px;padding:8px;border-radius:12px;
  background:var(--card);border:1px solid var(--line);box-shadow:var(--shadow);
}
.filters select{
  font:inherit;font-size:13.5px;font-weight:600;color:var(--ink);
  padding:7px 10px;border-radius:9px;border:1px solid var(--line);
  background:var(--card2);max-width:210px;
}
.filters .refresh{
  margin-left:auto;
  width:32px;height:32px;flex:none;border-radius:9px;border:1px solid var(--line);
  background:var(--card2);display:grid;place-items:center;color:var(--ink2);
  transition:background .14s,color .14s;
}
.filters .refresh:hover{background:var(--card);color:var(--ink)}
.filters .refresh svg{display:block}
.filters .refresh.spin svg{animation:spin .7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){.filters .refresh.spin svg{animation:none;opacity:.5}}

/* ---------- one chronological list for the day ---------- */
.today{max-width:700px}
.daylist{display:grid;gap:8px}
.nextcol{margin-top:44px}

/* On a wide screen the day's games and the weeks ahead sit side by side, with
   the date header spanning both. Below this the two stack, phone-first. */
@media(min-width:1040px){
  .today{max-width:1120px}
  .todaygrid{
    display:grid;grid-template-columns:minmax(0,1fr) 350px;
    gap:26px;align-items:start;
  }
  .nextcol{margin-top:0}
  .nextcol h2{font-size:20px}
}

/* A game card is a slot on the gym board: a solid coloured slate carries the time
   and court, the body carries the match. Three channels, three treatments —
   colour means time block, letterform means division, green means in play.
   Colour meant court until 2026-08-16; it reads better as the wave of games
   starting together, and the court is written on the slate regardless. */
.game{
  display:grid;grid-template-columns:70px 1fr;width:100%;text-align:left;
  padding:0;align-items:stretch;justify-items:stretch;
  background:var(--card);border:1px solid var(--line);border-radius:11px;
  overflow:hidden;box-shadow:var(--shadow);
  transition:transform .12s,box-shadow .12s;
}
.game:hover{transform:translateY(-1px);box-shadow:0 2px 3px rgba(24,26,66,.07),0 14px 30px -14px rgba(24,26,66,.42)}
/* A match still waiting on a result has nothing to open, so it doesn't lift
   or offer a cursor. Same treatment the bracket nodes and event cards give it. */
.game.tbd{cursor:default;opacity:.85}
.game.tbd:hover{transform:none;box-shadow:var(--shadow)}

.game .slate{
  background:var(--slot-a);color:#fff;
  display:grid;place-content:center;text-align:center;padding:10px 4px;gap:2px;
}
.game.tb .slate{background:var(--slot-b)}
.game .slate b{
  font-family:var(--num);font-size:13px;font-weight:600;line-height:1;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;
}
/* Everything in one colour block starts at the same time, so down a column the
   court is the only thing that changes. Weight alone marks which part of the
   line that is — same size, same colour as its label. */
.game .slate .crt{
  display:flex;align-items:baseline;justify-content:center;gap:4px;
  font-family:var(--display);font-size:9.5px;letter-spacing:.13em;
  text-transform:uppercase;opacity:.88;
}
.game .slate .crt i{font-style:normal;font-weight:700}

.game .body{padding:9px 13px 11px;min-width:0}
.game .hd{display:flex;align-items:center;gap:8px;margin-bottom:5px;min-height:18px}
.game .divi{display:inline-flex;align-items:baseline;gap:6px}
.game .divi em{
  font-style:normal;font-family:var(--display);font-size:10px;
  letter-spacing:.17em;text-transform:uppercase;color:var(--muted);
}
.game .divi b{
  font-family:var(--display);font-size:12.5px;font-weight:700;letter-spacing:.1em;
  color:var(--ink);border-bottom:2px solid var(--ink);padding-bottom:1px;line-height:1;
}
.game .divi b.x{color:var(--ink2);border-bottom-style:dotted;border-color:var(--ink2)}
.game .sp{
  margin-left:auto;font-family:var(--display);font-size:10.5px;font-weight:700;
  letter-spacing:.15em;text-transform:uppercase;color:var(--muted);white-space:nowrap;
}
.game .sp.on{color:var(--live)}
.game .sp.soon{color:var(--muted);opacity:.75}

.game .row{display:flex;align-items:baseline;gap:10px;min-width:0}
.game .row+.row{margin-top:1px}
.game .nm{min-width:0;font-weight:500;font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.game .row.win .nm{font-weight:700;color:var(--ink)}
.game .row.lose .nm{font-weight:500;color:var(--muted)}
.game .row.mine .nm{color:var(--pink-deep)}
/* Same bargain as the grid: the three sets keep their width and the name
   gives way, never the other way round. */
.game .sc{margin-left:auto;flex:none;display:flex;gap:9px;font-family:var(--num);font-size:13.5px;font-variant-numeric:tabular-nums;color:var(--ink2)}
.game .sc s{text-decoration:none;width:22px;text-align:right}
.game .sc s.w{font-weight:700;color:var(--ink)}
.game .sc s.e{color:var(--line)}

.sub{margin-top:44px}
.wkstrip{display:grid;gap:12px;margin-top:16px}
.wkcard{background:var(--card);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);overflow:hidden}
.wkcard>header{display:flex;align-items:center;gap:12px;padding:12px 17px;border-bottom:1px solid var(--line2)}
.wkcard>header h3{font-size:15px}
.wkcard>header .when{font-size:12.5px;color:var(--muted);font-family:var(--num)}
.wkcard>header .cnt{margin-left:auto;font-size:12px;color:var(--muted)}
.mini{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:1px;background:var(--line2)}
.mini button{
  display:grid;grid-template-columns:auto 1fr;gap:11px;align-items:center;text-align:left;
  padding:10px 17px;background:var(--card);transition:background .14s;
}
.mini button:hover{background:var(--card2)}
.mini .tm{font-family:var(--num);font-size:12px;color:var(--muted);white-space:nowrap}
.mini .mu{font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mini .ct{
  font-style:normal;font-family:var(--display);font-size:9.5px;font-weight:700;
  letter-spacing:.08em;padding:1.5px 5px;border-radius:5px;margin-right:7px;
}
/* Coming up follows the same rule: the chip says which court, its colour says
   which time block. */
.ct.ta{background:var(--slot-a-soft);color:var(--slot-a)}
.ct.tb{background:var(--slot-b-soft);color:var(--slot-b)}
.empty{padding:22px 17px;color:var(--muted);font-size:13.5px;text-align:center}
.morewk{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  width:100%;text-align:left;padding:14px 17px;font-size:13.5px;color:var(--ink2);
}
.morewk .go{font-weight:600;color:var(--pink-deep);white-space:nowrap}
.morewk:hover{background:var(--card2)}
.morewk small{display:block;margin-top:4px;font-size:12.5px;color:var(--muted)}
/* The next-games column is narrow, so the wrap-up card stacks its line and its
   way out rather than fighting for room on one row. */
.seasondone{flex-direction:column;align-items:flex-start;gap:10px;padding:16px 17px}
.seasondone .go{white-space:normal}

/* ---------- season calendar ---------- */
.calwrap{
  margin-top:20px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r);box-shadow:var(--shadow);overflow-x:auto;
}
.cal{display:grid}
.cal .hcell{
  position:sticky;top:0;z-index:2;background:var(--card);
  padding:11px 12px 10px;border-bottom:1.5px solid var(--line);border-left:1px solid var(--line2);
}
/* The corner pins both ways: it's the only cell that overlaps the header row
   and the time column, so it outranks both. */
.cal .hcell.gutter{border-left:0;left:0;z-index:4}
.cal .hcell .wk{font-family:var(--display);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--muted)}
.cal .hcell .dy{font-family:var(--display);font-size:17px;font-weight:700;margin-top:1px}
.cal .hcell.now{box-shadow:inset 0 -3px 0 var(--pink)}
.cal .hcell.now .dy{color:var(--pink-deep)}
/* Sticky, because the grid now opens partway along: start times have to stay
   readable from any week rather than only from week 1. Needs its own background
   — the slots would otherwise slide underneath it in view. */
.cal .tcell{
  position:sticky;left:0;z-index:1;background:var(--card);
  border-top:1px solid var(--line2);padding:8px 9px 0 0;text-align:right;
  font-family:var(--num);font-size:11px;color:var(--muted);
}
.cal .slot{
  border-top:1px solid var(--line2);border-left:1px solid var(--line2);
  /* minmax(0,1fr), not the default auto track: an auto track can never be
     narrower than its item's min-content, so one long team name pushed its
     block out to 314px inside a 180px column and shoved the whole week sideways.
     At minmax(0,...) the block takes the column's width and the name ellipsises
     inside it, which is what the ellipsis was there for. */
  padding:5px;display:grid;grid-template-columns:minmax(0,1fr);gap:4px;min-height:74px;
  /* Packed to the top rather than stretched: without this the blocks shared out
     whatever height the tallest cell in the row happened to need, so the same
     match was a different size in every column. */
  align-content:start;
}
/* One height for all of them, so a court with nothing on it takes the same room
   as a court with a match — the column then reads as the day's shape. */
.cal .ev{min-height:60px}
.cal .ev.empty{color:var(--muted);background:var(--card2);border-style:dashed;border-left-color:var(--line)}
.cal .ev.empty .n{color:var(--muted)}
.cal .bye{
  border-left:1px solid var(--line2);border-top:1px solid var(--line2);
  display:flex;align-items:center;justify-content:center;
  background:repeating-linear-gradient(135deg,transparent,transparent 7px,var(--line2) 7px,var(--line2) 8px);
}
.cal .bye span{
  writing-mode:vertical-rl;font-family:var(--display);font-size:11px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--muted);background:var(--card);padding:10px 3px;border-radius:6px;
}
.ev{
  display:block;width:100%;text-align:left;border-radius:8px;padding:6px 8px 6px 9px;
  border:1px solid var(--line2);border-left:3px solid var(--muted);background:var(--card2);
  transition:transform .12s,box-shadow .12s;line-height:1.28;
}
.ev:hover{transform:translateY(-1px);box-shadow:var(--shadow)}
/* The overview marks division, not court. Reading a week is reading who plays
   whom, and the court is written inside the block anyway. These are the colours
   the division chips already use, so the two agree. A cross-division game takes
   the lower of its two divisions. */
.ev.A{border-left-color:var(--pink-deep)}
.ev.BB,
.ev.B2{border-left-color:var(--sky-deep)}
.ev.B{border-left-color:var(--purple)}
.ev.c5{border-left-color:var(--court5)}
.ev.c6{border-left-color:var(--court6)}
.ev .top{
  display:flex;align-items:center;gap:5px;font-family:var(--num);font-size:9.5px;
  color:var(--muted);text-transform:uppercase;letter-spacing:.05em;
}
/* The top line is court, bracket, division. The court and the division are
   short and never give way; the bracket is a name the manager typed and can be
   any length, so it is capped — it is the least of the three, and letting it
   have the room pushed the division off the line. */
.ev .top > span{white-space:nowrap}
.ev .top .bk{
  max-width:7.5em;overflow:hidden;text-overflow:ellipsis;
  border-left:1px solid var(--line);padding-left:5px;
}
.ev .top .d{margin-left:auto;flex:none;white-space:nowrap;font-family:var(--display);font-weight:700;letter-spacing:.08em;color:var(--ink2)}
/* The score is fixed furniture and the name is what gives way. Without
   flex:none the two shrink in proportion to their own widths, so a name long
   enough to need the ellipsis also squeezed the score until "23 9 0" wrapped
   onto a second line, which made that block taller than every other block in
   the row. min-width:0 lets the name shrink past its longest word. */
.ev .p{display:flex;gap:6px;font-size:11.5px;margin-top:2px}
.ev .p .n{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ev .p.win .n{font-weight:700}
.ev .p.lose .n{color:var(--muted)}
.ev .p .s{margin-left:auto;flex:none;white-space:nowrap;font-family:var(--num);font-size:10.5px;color:var(--muted)}
.ev.tbd{border-left-color:var(--line);opacity:.75;cursor:default}

/* ---------- divisions ---------- */
.divgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:20px;margin-top:18px;align-items:start}
.divcard{background:var(--card);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);overflow:hidden}
.divcard>header{display:flex;align-items:center;gap:11px;padding:14px 17px;border-bottom:1px solid var(--line)}
.divcard>header h3{font-size:19px;letter-spacing:.04em}
.divcard.A>header{background:linear-gradient(180deg,var(--pink-soft),transparent)}
.divcard.BB>header,
.divcard.B2>header{background:linear-gradient(180deg,var(--sky-soft),transparent)}
.divcard.B>header{background:linear-gradient(180deg,var(--purple-soft),transparent)}
.divcard>header .n{margin-left:auto;font-size:12px;color:var(--muted)}
table{width:100%;border-collapse:collapse;font-size:13.5px}
th{
  font-family:var(--display);font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--muted);font-weight:600;text-align:right;padding:8px 10px;border-bottom:1px solid var(--line2);
}
th:first-child,th:nth-child(2){text-align:left}
td{padding:9px 10px;border-bottom:1px solid var(--line2);text-align:right;font-family:var(--num);font-variant-numeric:tabular-nums;font-size:12.5px}
tr:last-child td{border-bottom:0}
td.rk{width:30px;color:var(--muted);text-align:left}
td.tm{text-align:left;font-family:var(--body);font-size:14px;font-weight:600}
td.tm small{display:block;font-weight:400;font-size:11.5px;color:var(--muted);font-family:var(--body)}
tr.top td.rk{color:var(--pink);font-weight:700}
td.pd.pos{color:var(--live)} td.pd.neg{color:var(--muted)}

/* ---------- modal ---------- */
/* Padding, not height: the sheet is centred in whatever the keyboard leaves,
   and max-height:100% then keeps it inside that. */
.veil{
  position:fixed;inset:0;z-index:100;display:flex;align-items:center;justify-content:center;
  padding:18px 18px calc(18px + var(--kb));
  background:color-mix(in srgb,var(--ink) 55%,transparent);backdrop-filter:blur(5px);
  animation:fade .16s ease-out;
}
@keyframes fade{from{opacity:0}}
@keyframes rise{from{opacity:0;transform:translateY(14px) scale(.985)}}
.sheet{
  width:min(660px,100%);max-height:100%;overflow-y:auto;background:var(--card);
  border-radius:20px;box-shadow:var(--shadow-lg);border:1px solid var(--line);
  animation:rise .2s cubic-bezier(.2,.8,.3,1);
}
@media(prefers-reduced-motion:reduce){.veil,.sheet{animation:none}}
.sheet>header{display:flex;align-items:flex-start;gap:12px;padding:17px 19px 13px}
.sheet>header .info .eyebrow{display:block}
.sheet>header .info b{font-family:var(--display);font-size:19px;font-weight:700}
/* The captain reads as a person, not as a label: sentence case, and the name
   carries the weight rather than the word "Captain". */
.sheet>header .info .capname{
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  font-size:13px;color:var(--muted);margin-top:4px;
}
.sheet>header .info .capname .bit{display:inline-flex;align-items:center;gap:7px}
.sheet>header .info .capname em{font-style:normal;font-weight:600;color:var(--ink2)}
.sheet>header .x{margin-left:auto;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;color:var(--muted)}
.sheet>header .x:hover{background:var(--line2);color:var(--ink)}

/* ---------- record mode: the two teams, then plain number entry ---------- */
.matchup{display:grid;gap:8px;padding:2px 19px 0}
.tline{
  display:flex;align-items:center;gap:11px;padding:9px 12px;border-radius:12px;
  border:1.5px solid transparent;width:100%;font:inherit;color:inherit;text-align:left;
}
.tline .go{margin-left:auto;flex:none;opacity:.35}
.tline:hover .go{opacity:.75}
.tline.a{background:var(--sky-soft);border-color:color-mix(in srgb,var(--sky) 38%,transparent)}
.tline.b{background:var(--pink-soft);border-color:color-mix(in srgb,var(--pink) 38%,transparent)}
.tline .rk{
  font-family:var(--display);font-size:16px;font-weight:700;letter-spacing:-.02em;
  min-width:32px;text-align:center;
}
.tline.a .rk{color:var(--sky-deep)} .tline.b .rk{color:var(--pink-deep)}
.tline .who{min-width:0}
.tline .who b{display:block;font-size:15.5px;font-weight:700;line-height:1.2}
.tline .who small{display:block;font-size:12px;color:var(--ink2);margin-top:1px}

.entry{margin:16px 19px 0;border:1px solid var(--line);border-radius:13px;overflow:hidden}
.erow{
  display:grid;grid-template-columns:96px 1fr 1fr;gap:8px;align-items:center;
  padding:8px 11px;border-top:1px solid var(--line2);
}
.erow:first-child{border-top:0}
.erow.ehead{padding:8px 11px 6px;background:var(--card2)}
.erow.ehead .en{
  font-family:var(--display);font-size:11px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted);text-align:center;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.erow .elabel{font-family:var(--display);font-size:13px;font-weight:700;letter-spacing:.05em}
.erow .elabel small{display:block;font-family:var(--body);font-size:11px;font-weight:400;letter-spacing:0;color:var(--muted)}
.erow.off{opacity:.45}
.erow .ena{font-size:12px;color:var(--muted);text-align:center}
.erow.etotal{background:var(--card2);border-top:1.5px solid var(--line)}
.erow.etotal .etw{
  text-align:center;font-family:var(--num);font-size:16px;font-weight:700;
  font-variant-numeric:tabular-nums;
}
.scorebox{
  width:100%;font-family:var(--num);font-size:22px;font-weight:600;text-align:center;
  padding:7px 4px;border-radius:10px;border:1.5px solid var(--line);background:var(--card);
  color:var(--ink);font-variant-numeric:tabular-nums;-moz-appearance:textfield;
}
.scorebox::-webkit-outer-spin-button,
.scorebox::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.scorebox:focus{outline:none;border-color:var(--ink);box-shadow:0 0 0 3px color-mix(in srgb,var(--ink) 12%,transparent)}
.scorebox.edited{border-color:var(--pink);background:var(--pink-soft)}
.dirtyflag{font-size:12px;font-weight:600;color:var(--pink-deep);white-space:nowrap}
.btn.primary[disabled]{opacity:.4;cursor:not-allowed}
.btn.primary[disabled]:hover{opacity:.4}
.scorebox::placeholder{color:var(--line)}
.savednote{margin:0;padding:0 19px 18px;font-size:11.5px;color:var(--muted);line-height:1.35}
.btn.tocourtside{display:inline-flex;align-items:center;gap:8px;margin-right:auto}
.btn.tocourtside svg{opacity:.7}

/* ---------- courtside: full screen, landscape, thumb-sized targets ---------- */
.csmode{
  position:fixed;inset:0;z-index:150;background:var(--courtside);color:#fff;
  overscroll-behavior:none;touch-action:manipulation;
}
html.courtside-open,
html.courtside-open body{background:var(--courtside);overscroll-behavior:none}

/* Two halves, edge to edge. Nothing between them but the fold. */
.csboard{position:absolute;inset:0;display:grid;grid-template-columns:1fr 1fr;background:var(--courtside)}
.cshalf{
  display:grid;grid-template-rows:auto minmax(0,1fr) auto;justify-items:center;
  align-items:center;color:#fff;transition:filter .08s;
  padding:max(4.5vh,52px) 6px 3.5vh;
}
/* Colour is the side of the screen, never the team — see courtsideMarkup. */
.cshalf.lt{background:var(--court1)}
.cshalf.rt{background:var(--court2)}
.cshalf:active{filter:brightness(1.12)}
.cshalf[aria-disabled="true"]{filter:saturate(.5) brightness(.85)}
.csname{
  font-family:var(--display);font-size:clamp(15px,3vh,24px);font-weight:700;
  letter-spacing:.02em;padding:0 12px;text-align:center;line-height:1.05;
  max-width:94%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  opacity:.94;
}
.csscore{
  font-family:var(--display);font-size:min(64vh,44vw);font-weight:700;
  line-height:.78;letter-spacing:-.05em;font-variant-numeric:tabular-nums;
  display:flex;align-items:center;justify-content:center;
}
.cshalf .cssets{font-size:clamp(10px,1.6vh,13px);opacity:.66;letter-spacing:.05em}

/* Controls float over the board rather than stealing a row from it. */
/* The board bleeds under the notch on purpose; the controls must not. Only the
   buttons take the safe-area inset, so colour still reaches every edge. */
.csbar{
  position:absolute;top:0;left:0;right:0;display:flex;align-items:flex-start;
  gap:10px;pointer-events:none;
  padding:calc(10px + env(safe-area-inset-top)) calc(14px + env(safe-area-inset-right))
          0 calc(14px + env(safe-area-inset-left));
}
.csbar > *{pointer-events:auto}
.csbar .sp{margin-left:auto;display:flex;gap:6px;align-items:center}
.csbtn{
  display:grid;place-items:center;min-width:38px;height:38px;padding:0 11px;
  border-radius:11px;background:rgba(0,0,0,.28);color:#fff;font-size:14px;font-weight:600;
  backdrop-filter:blur(6px);
}
.csbtn:hover{background:rgba(0,0,0,.42)}
.csnav{display:flex;gap:5px}
.cssetbtn{
  min-width:34px;height:38px;padding:0 8px;border-radius:11px;
  background:rgba(0,0,0,.28);color:rgba(255,255,255,.72);backdrop-filter:blur(6px);
  font-family:var(--display);font-size:12.5px;font-weight:700;line-height:1;
  display:grid;place-items:center;gap:1px;
}
.cssetbtn i{display:block;font-style:normal;font-family:var(--num);font-size:9px;opacity:.85}
.cssetbtn[aria-pressed="true"]{background:#fff;color:var(--courtside)}
.cssetbtn[disabled]{opacity:.32}

.csfoot{
  position:absolute;left:0;right:0;bottom:0;display:flex;align-items:center;gap:12px;
  pointer-events:none;
  padding:0 calc(14px + env(safe-area-inset-right))
          calc(12px + env(safe-area-inset-bottom)) calc(14px + env(safe-area-inset-left));
}
.csfoot > *{pointer-events:auto}
.csfoot .csset{
  flex:1;text-align:center;font-family:var(--display);font-size:11px;
  letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.62);
  text-shadow:0 1px 3px rgba(0,0,0,.35);
}
/* The swipe has no button to advertise it, so the footer says so once, quietly
   enough that the score still owns the screen. */
.csfoot .csset b{
  display:block;font-weight:400;font-size:10px;letter-spacing:.12em;
  color:rgba(255,255,255,.42);margin-top:3px;
}
.csrotate{display:none}
@media (orientation:portrait) and (max-width:860px){
  .csrotate{
    display:flex;align-items:center;justify-content:center;position:absolute;
    left:0;right:0;bottom:54px;pointer-events:none;
  }
  .csrotate span{
    font-size:11.5px;color:#fff;background:rgba(0,0,0,.35);
    padding:5px 12px;border-radius:999px;backdrop-filter:blur(6px);
  }
  .csscore{font-size:min(34vh,42vw)}
}
@media(prefers-reduced-motion:reduce){.cshalf:active{transform:none}}

/* Sticky, because the sheet scrolls: with the keyboard up there is room for
   the sets or for the buttons, not both, and hunting for Save is what the
   phone made you do. It sits on the paper it covers, so the note underneath
   passes behind it rather than showing through. */
.sheet>footer{
  position:sticky;bottom:0;z-index:2;background:var(--card);
  display:flex;flex-wrap:wrap;gap:9px;align-items:center;padding:16px 19px 6px;
}
/* Drawn on the row itself rather than as a border, so it stays put while the
   sets scroll behind it. */
.sheet>footer::before{
  content:"";position:absolute;left:0;right:0;top:0;height:1px;background:var(--line2);
}
.sheet>footer .note{font-size:11.5px;color:var(--muted);margin-right:auto;max-width:290px;line-height:1.35}
.btn{padding:9px 17px;border-radius:10px;font-size:13.5px;font-weight:600;border:1px solid var(--line)}
.btn:hover{background:var(--card2)}
.btn.primary{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.btn.primary:hover{opacity:.9;background:var(--ink)}
@media(max-width:520px){
  /* Keep the wordmark and the nav pill on one line: buy width back from the
     gutter, the gap and the control padding before anything wraps. */
  .wrap{padding:0 14px}
  .topbar .wrap{gap:10px}
  .mark .uni{font-size:30px}
  .marklock{gap:7px;padding:5px 10px}
  .marklock svg{height:28px}
  .seg button,.seg a{padding:6px 12px;font-size:12.5px}
  .topdiv{margin:0 3px}
  .seasonpick{padding:6px 9px;font-size:11px;letter-spacing:.05em;gap:5px}
  .mgrlink{padding:6px 9px;font-size:11px;letter-spacing:.05em}
  #seasonname{max-width:34vw;overflow:hidden;text-overflow:ellipsis}

  /* One row: the team select gives up whatever the refresh button needs. */
  .filters{flex-wrap:nowrap;gap:6px;padding:6px}
  .filters select{flex:1 1 0;min-width:0;max-width:none;padding:7px 6px;font-size:12.5px}
  .filters .refresh{width:30px;height:30px;flex:none}

  .sheet>footer .note{display:none}
  .erow{grid-template-columns:74px 1fr 1fr;gap:6px}
  /* Both buttons on one row, Save on the right where Save always goes. Full
     width for courtside pushed Save onto a second row, and with a keyboard up
     the second row is the one you can't see. The unsaved count takes the line
     above rather than a share of the width. */
  .sheet>footer{flex-wrap:wrap;gap:8px 16px}
  .sheet>footer .dirtyflag{flex-basis:100%;order:-1}
  .sheet>footer .dirtyflag:empty{display:none}
  /* Sized to its label, the way it is on desktop, with the leftover space
     falling between the two buttons — margin-right:auto on the base rule is
     what puts it there. Capped at fit-content but with flex-basis 0, because a
     flex line breaks on an item's natural width before it will shrink one, and
     at 320px that put Save on a row of its own. Asking for nothing means the
     label gives up characters instead. */
  .btn.tocourtside{flex:1 1 0;min-width:0;max-width:fit-content}
  .btn.tocourtside svg{flex:none}
  .btn.tocourtside .lbl{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .topbar .wrap{height:auto;padding-top:10px;padding-bottom:10px;flex-wrap:wrap}
  h1{font-size:31px}
}

/* ---------- the Scrimmy mark ---------- */
/* The platform's wordmark: black mono type and one coral dot, a fifth of a
   letter after the word. The dot is the ball, and the one friend who said yes.
   Both the gap and the dot are sized from the type, so the mark keeps its
   proportions at every size it is set. design/scrimmy-quiet.html. */
.scrimmy{
  font-family:"Rubik Mono One",ui-monospace,monospace;letter-spacing:.02em;line-height:1;
  color:#141414;display:inline-flex;align-items:baseline;gap:.22em;white-space:nowrap;text-decoration:none;
}
/* Centred on the capitals, not on the line box: the letters run from the
   baseline to the cap height, about .7em in this face, and a box with no text
   sits on the baseline, so lifting a .5em dot by .1em puts its middle on theirs. */
.scrimmy i{width:.5em;height:.5em;border-radius:50%;background:#FF6B5A;flex:none;position:relative;top:-.1em}

/* ---------- the foot of the page ---------- */
/* Above the dock, which is fixed and would otherwise cover it: the page's
   bottom padding already clears the dock, so the footer only has to sit inside
   it. The Scrimmy mark is the one thing on the league's pages in the
   platform's colours — it names whose software this is, quietly. */
.foot{margin-top:56px;padding:0 0 calc(var(--dock) + 30px + env(safe-area-inset-bottom))}
.foot .wrap{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 18px;padding-top:14px;border-top:1px solid var(--line);font-size:12.5px;color:var(--muted)}
.powered{display:inline-flex;align-items:baseline;gap:4px;color:inherit;text-decoration:none}
.powered:hover .scrimmy span{text-decoration:underline;text-underline-offset:3px}
.foot .scrimmy{font-size:12px}
.footlink{font-weight:600;color:var(--ink2);text-decoration:none}
.footlink:hover{color:var(--pink-deep);text-decoration:underline;text-underline-offset:3px}
/* Sign out is a button (it does something rather than going somewhere) in a
   link's clothes, the same on the league pages and the manager's screen. */
button.footlink{border:0;background:none;padding:0;font:inherit;font-weight:600;cursor:pointer}
/* main already leaves room for the dock; the footer takes that room instead. */
main{padding-bottom:0}

/* ---------- day picker ---------- */
.menu{
  position:absolute;z-index:60;background:var(--card);border:1px solid var(--line);
  border-radius:13px;box-shadow:var(--shadow-lg);padding:6px;min-width:238px;
}
.menu button{display:flex;width:100%;gap:10px;align-items:center;padding:8px 11px;border-radius:9px;font-size:13.5px;text-align:left}
.menu button:hover{background:var(--card2)}
.menu button[aria-current="true"]{background:var(--sky-soft);font-weight:600}
/* "● now" is two words to a flex layout and it will break between them once a
   long discipline wraps the tagline. It holds its width and stays on one line;
   the tagline is the part with room to give. */
.menu button .r{
  margin-left:auto;flex-shrink:0;white-space:nowrap;
  font-size:11.5px;color:var(--muted);font-family:var(--num);
}
.menu button > span:first-child{min-width:0}
.menu button .r.draft{color:var(--draft);font-weight:700}
/* The pill says so too while a draft is open, so a manager can't forget the
   page they are looking at is one nobody else can see. */
.seasonpick.isdraft::before{
  content:"Draft";font-size:10px;letter-spacing:.14em;padding:1px 6px;border-radius:999px;
  background:var(--draft);color:#fff;transform:translateY(1px);
}
/* Marks the week the league is actually on, which is not always the one being viewed. */
.menu .nowdot{
  display:inline-block;width:7px;height:7px;border-radius:50%;
  background:var(--live);vertical-align:middle;margin-left:7px;
}
.menu hr{border:0;border-top:1px solid var(--line2);margin:5px 4px}

/* ---------- toast ---------- */
#toast{
  position:fixed;left:50%;transform:translate(-50%,14px);
  /* Above the dock, which it used to land on top of, and above the keyboard,
     since saving a set is now something you do with one open. */
  bottom:calc(var(--dock) + 26px + var(--kb) + env(safe-area-inset-bottom));
  z-index:200;max-width:min(420px,calc(100vw - 32px));
  padding:11px 16px;border-radius:11px;font-size:13.5px;font-weight:500;
  background:var(--ink);color:var(--paper);box-shadow:var(--shadow-lg);
  opacity:0;pointer-events:none;transition:opacity .18s,transform .18s;
}
#toast.show{opacity:1;transform:translate(-50%,0)}
#toast.bad{background:var(--pink-deep);color:#fff}
#toast.good{background:var(--live);color:#fff}
@media(prefers-reduced-motion:reduce){#toast{transition:none}}

/* Venue links on the overview: a strip that reads as part of the at-a-glance
   line above it, since it answers the same kind of question. */
.rulestrip.venues{margin-top:6px}
.rulestrip.venues a{color:var(--sky-deep);font-weight:600}

/* ---------- a playoff day ---------- */
/* One section per bracket, a band per round — a bracket is read as rounds, and
   the day is only ever part of one. */
.playoffday{display:grid;gap:18px;margin-top:14px}
.pobracket{display:grid;gap:9px}
.pobracket > .eyebrow{margin-bottom:-2px}
.rndband{display:flex;align-items:center;gap:10px}
.rndband .nm{
  font-family:var(--display);font-size:11px;font-weight:700;letter-spacing:.15em;
  text-transform:uppercase;color:var(--muted);white-space:nowrap;
}
.rndband .rule{flex:1;height:1px;background:var(--line)}
/* A side still waiting on a result has nothing to score and nobody to bold. */
.game .row.waiting .nm{color:var(--muted);font-style:italic}

/* ---------- a playoff match card ---------- */
/* Drawn by match-card.js and used on both screens: the manager builds brackets
   out of these and the league reads one. Styled once, here, for the same reason
   the markup is written once. */
.node{
  position:relative;background:var(--card);border:1px solid var(--line);border-radius:10px;
  padding:6px 9px 8px;display:grid;gap:5px;width:100%;
  font:inherit;color:inherit;text-align:left;cursor:pointer;
}
.node:hover{border-color:var(--purple);background:var(--card2)}
.node:focus-visible{outline:2px solid var(--purple);outline-offset:2px}
.nhd{
  display:flex;align-items:center;gap:5px;
  font-family:var(--num);font-size:9.5px;color:var(--muted);
  text-transform:uppercase;letter-spacing:.05em;
}
.nhd .mno{font-family:var(--display);font-weight:700;letter-spacing:.08em;color:var(--ink2)}
.nhd .badge{margin-left:auto}
.nft .crtname{text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin-right:6px}
.nrow{display:grid;gap:2px;min-width:0}
.nmv{font-size:11.5px;color:var(--ink2);padding-left:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nft{
  display:flex;align-items:center;gap:4px;border-top:1px solid var(--line2);
  padding-top:5px;font-size:10.5px;color:var(--ink2);
}
.nft.none{color:var(--pink-deep)}
.src{
  display:inline-flex;align-items:center;gap:5px;padding:3px 9px 3px 7px;border-radius:7px;
  font-size:11.5px;line-height:1.35;white-space:nowrap;
  border:1px solid var(--line);background:var(--card2);color:var(--ink2);
}
.src .gl{font-size:10px;line-height:1;opacity:.75}
.src.seed{background:var(--purple-soft);border-color:var(--purple-soft);color:var(--purple)}
/* Neutral, both of them. Green read as "this side won" about a match nobody has
   played, and pink as "lost" — the words Winner and Loser already say which
   result is being waited on, and the arrow says it at a glance. Only a seed
   keeps a colour, because it is a different kind of thing: a position in the
   standings rather than a result still to come. */
.src.win,.src.lose{background:var(--card2);border-color:var(--line);color:var(--ink2)}
.sdchip .rk,.src .rk{
  font-size:10.5px;color:var(--muted);background:var(--card2);
  border-radius:5px;padding:1px 5px;margin-left:1px;
}
.src .rk{background:rgba(255,255,255,.6)}
.nhd .badge{
  display:inline-grid;place-items:center;min-width:16px;height:16px;padding:0 4px;
  border-radius:5px;background:var(--pink-soft);color:var(--pink-deep);
  font-size:10px;font-weight:700;
}
.src.broken{
  background:var(--pink-soft);border-color:var(--pink-deep);color:var(--pink-deep);
}

/* ---------- the brackets, under the week grid ---------- */
/* The grid answers when you're playing; the tree answers who you get if you
   win. Different questions, so it sits below rather than inside a column. */
.brackets{margin-top:34px}
.brackets h2{font-size:clamp(22px,2.6vw,30px);margin-top:4px}
.tree{background:var(--card);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);margin-top:16px;overflow:hidden}
.treehd{
  display:flex;align-items:baseline;gap:9px;padding:13px 17px;border-bottom:1px solid var(--line);
  font-family:var(--display);font-size:17px;font-weight:700;
}
.treehd b{color:var(--purple)}
.treehd .cnt{margin-left:auto;font-family:var(--num);font-size:11px;color:var(--muted);font-weight:400}
.rungs{display:flex;gap:26px;overflow-x:auto;padding:16px 17px 20px}
.rungs .rung{flex:none;width:196px;display:flex;flex-direction:column;gap:9px}
.rungs .rhd{
  font-family:var(--display);font-size:10px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--muted);padding-bottom:3px;border-bottom:1px solid var(--line);
}
.rungs .rinner{display:flex;flex-direction:column;justify-content:space-around;gap:9px;flex:1}
/* The blocks in a tree are the same `.ev` the week grid draws — nothing of
   their own beyond sitting in a column. */
.rungs .ev{width:100%}
.ev .p .n.waiting{color:var(--muted);font-style:italic}
/* The pill sits above the team it names, not beside it: a name gets the card's
   full width that way instead of whatever the pill leaves. The score rides with
   the name, on the right, once there is one. */
.node .nline{display:flex;align-items:baseline;gap:8px;min-width:0}
.node .nline .nmv{flex:1;min-width:0}
.node .nmv.win{font-weight:700;color:var(--ink)}
.node .nsc.win{color:var(--ink2)}
.node .nsc{
  font-family:var(--num);font-size:11px;color:var(--muted);
  letter-spacing:.04em;white-space:nowrap;
}
.node.tbd{cursor:default;opacity:.85}
.node.tbd:hover{border-color:var(--line);background:var(--card)}

/* The wires between a match and the one it feeds. Drawn by ladder.js once the
   columns are laid out, because their heights are what the elbow is made of. */
.rungs{position:relative}
.wires{position:absolute;inset:0;pointer-events:none;z-index:0}
.wires path{fill:none;stroke:var(--line);stroke-width:1.5}
.rungs .rung{position:relative;z-index:1}
/* The way between the grid and the tree, in both directions. */
.tolink{
  font-family:var(--display);font-size:11px;font-weight:700;letter-spacing:.06em;
  color:var(--pink-deep);background:none;border:0;padding:2px 0;cursor:pointer;white-space:nowrap;
}
.tolink:hover{text-decoration:underline}
.cal .hcell.playoffs .wk{color:var(--pink-deep)}
.cal .hcell.playoffs{background:linear-gradient(180deg,var(--pink-soft),transparent)}

/* A playoff day is a door, not a column. Its matches run on hours the season
   does not, and drawing them here would make every ordinary week carry rows it
   has no business in — for a day the bracket answers better anyway, because
   it says who you play next as well as when. */
.cal .door{
  border-top:1px solid var(--line2);border-left:1px solid var(--line2);
  padding:5px;display:grid;
}
.doorbtn{
  display:grid;align-content:center;justify-items:center;gap:5px;text-align:center;
  width:100%;height:100%;padding:16px 12px;border:0;border-radius:10px;cursor:pointer;
  font:inherit;color:var(--ink);
  background:linear-gradient(180deg,var(--pink-soft),var(--card));
}
.doorbtn b{font-family:var(--display);font-size:17px}
.doorbtn span{font-size:12px;color:var(--muted)}
.doorbtn .go{
  font-family:var(--display);font-size:11px;font-weight:700;
  letter-spacing:.06em;color:var(--pink-deep);margin-top:3px;
}
.doorbtn:hover .go{text-decoration:underline}

/* ---------- the dock with Info: four named tabs ---------- */
/* A little less side padding than three tabs had, so the fourth name fits
   inside 375px with room either side. */
/* And a floor on width: a tab sized to its own word made Info a narrow pill
   with the icon squeezed inside it, next to Game Day's wide one. */
@media (max-width:819px){
  .tabs button,.tabs a{padding:7px 13px;min-width:66px}
}
/* The way up out of the leagues, at the foot of the picker and set apart. */
.menu button.all{color:var(--pink-deep);border-top:2px solid var(--line);border-radius:0 0 9px 9px;margin-top:4px}
.menu button.all[aria-current="true"]{background:var(--pink-soft)}

/* ---------- the information pages ---------- */
/* One column, phone first. Nothing sits on the lavender but headings — every
   sentence is in a white card, so there is no contrast to manage line by line. */
.infopage{max-width:700px}
.infopage h1{font-size:clamp(27px,3.4vw,40px);margin-top:2px}
.infopage > .eyebrow{display:block;margin-bottom:2px}
.ih2{font-family:var(--display);font-size:17px;font-weight:700;margin-top:20px}
/* A manager's way from a box Setup draws to where it is changed: top right,
   on the heading's line, or in the card's corner where there is no heading. */
.ih2:has(.setuplink){display:flex;align-items:baseline;gap:10px}
.setuplink{margin-left:auto;font-family:var(--body);font-size:12.5px;font-weight:700;color:var(--sky-deep);text-decoration:none;letter-spacing:0}
.setuplink:hover{text-decoration:underline;text-underline-offset:3px}
/* The league card has no heading, so its link gets a line of its own above it,
   where the other boxes carry theirs; inside the card it ran into the first line. */
.ih2.setuprow{display:flex;margin-top:0}
@media (min-width:1040px){ .gh > .ih2.setuprow{margin-top:12px} .gh > .setuprow + .icard.hero{margin-top:6px} }
.icard{margin-top:9px;background:var(--card);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow);overflow:hidden}
.icard .ib{padding:12px 14px;font-size:13.5px;color:var(--ink2)}
.icard .ib b{display:block;color:var(--ink);font-weight:700;font-size:14.5px}
.icard .ib+.ib{border-top:1px solid var(--line2)}
.icard .ib a{color:var(--sky-deep);font-weight:600}
.icard .ib p{margin:0} .icard .ib p+p{margin-top:8px}
.icard .cnt{float:right;font-family:var(--num);font-size:11.5px;color:var(--muted);text-transform:capitalize}
.icard.hero .ib{padding:14px 15px 15px}
.icard.hero .ib .headline{font-family:var(--display);font-size:25px;line-height:1.05;margin-bottom:4px}
.icard .eyebrow{display:block;margin-bottom:3px}
.icard .eyebrow i{font-style:normal;color:var(--pink-deep)}
/* Ink, not the link blue: it is a fact about the league, not something to tap. */
.soon{color:var(--ink);font-weight:600;margin-bottom:6px;font-size:13.5px}
.lead{font-size:14px;color:var(--ink2);margin:0}
.facts4{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-top:12px}
.facts4 .f{background:var(--card2);border-radius:9px;padding:8px 6px;text-align:center}
.facts4 .v{font-family:var(--display);font-size:20px;font-weight:700;line-height:1;color:var(--ink)}
.facts4 .k{font-family:var(--display);font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);margin-top:3px}
.ibtns{display:flex;gap:8px;margin-top:12px}
.ibtns .btn{
  flex:1;display:inline-flex;align-items:center;justify-content:center;text-align:center;
  text-decoration:none;padding:10px 8px;font-size:13.5px;font-weight:700;
  background:var(--card2);color:var(--ink2);
}
.ibtns .btn.primary{background:var(--ink);color:var(--paper)}
.ibtns .btn[disabled]{opacity:.5;cursor:default}
.under{font-size:11.5px;color:var(--muted);text-align:center;margin-top:7px}
/* A button on its own is the size of its words, not the card. Two share the
   row and fill it, because on a phone each needs a thumb's width; one that
   fills it reads as the page's whole point, and See schedule is not. */
.ibtns.one .btn,.ibtns .btn:only-child{flex:0 1 auto;min-width:180px;max-width:100%;padding:10px 22px}
.ibtns:has(.btn:only-child){justify-content:center}
.ibtns.one{justify-content:flex-start}

/* The division card from /teams, with the description under its header and a
   status where the standings will be once sets are played. */
.infopage .divcard{margin-top:9px}
.divcard .desc{padding:10px 15px 11px;font-size:13.5px;color:var(--ink2);border-bottom:1px solid var(--line2)}
.divcard th.right{text-align:right}
td.st{font-family:var(--display);font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--live);font-weight:700}
td.st.pending{color:var(--muted)}
/* Five teams and a row that opens the rest. The card grows in place; nothing navigates. */
.divcard tr.more{display:none}
.divcard.open tr.more{display:table-row}
.showall{
  display:flex;align-items:center;justify-content:center;gap:7px;width:100%;
  padding:10px 13px;border-top:1px solid var(--line2);font-size:13px;font-weight:700;color:var(--pink-deep);
}
.showall:hover{background:var(--card2)}
.showall i{
  width:7px;height:7px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:rotate(45deg) translate(-2px,-2px);transition:transform .18s;
}
.divcard.open .showall i{transform:rotate(225deg) translate(-1px,-1px)}

/* Questions: native details, one row each, a chevron that turns — the same
   mark the picker uses, so open and closed read without a legend. */
.faq details+details{border-top:1px solid var(--line2)}
.faq summary{
  list-style:none;cursor:pointer;padding:11px 13px;font-size:13.5px;font-weight:700;color:var(--ink);
  display:flex;justify-content:space-between;align-items:center;gap:10px;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:"";width:8px;height:8px;flex:none;margin-right:3px;
  border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
  transform:rotate(45deg) translate(-2px,-2px);transition:transform .18s;
}
.faq details[open] summary::after{transform:rotate(225deg) translate(-1px,-1px)}
.faq .a{padding:0 13px 12px;font-size:13.5px;color:var(--ink2)}
.faq .a p{margin:0} .faq .a p+p{margin-top:8px}

/* Polaroids: square crop, white frame, a few degrees of tilt and one line of
   caption in a hand. The treatment does the work, so any phone snapshot of six
   people in a gym reads as a wall of moments. */
/* The strip scrolls sideways, and a scroller clips the other way too — so the
   padding is the room the tilt, the tape and the shadow need, and the margins
   give it back so the frames still sit where the card would. */
.polas{display:flex;gap:16px;overflow-x:auto;padding:16px 10px 36px;margin:-6px -10px -18px;scrollbar-width:none}
.polas::-webkit-scrollbar{display:none}
.pola{
  flex:none;width:146px;margin:0;background:#fff;padding:7px 7px 28px;position:relative;
  box-shadow:0 1px 2px rgba(24,26,66,.14),0 12px 28px -12px rgba(24,26,66,.5);transform:rotate(-2.4deg);
  cursor:pointer;text-align:left;transition:transform .15s;
}
.pola:hover{transform:rotate(0) translateY(-2px)}
.pola:focus-visible{outline-offset:3px}
.pola:nth-child(2n){transform:rotate(1.9deg)} .pola:nth-child(3n){transform:rotate(-.9deg)}
.pola .ph{display:block;aspect-ratio:1;border-radius:2px;background:var(--line2);overflow:hidden}
.pola .ph img{width:100%;height:100%;object-fit:cover;display:block}
.pola .cap{
  position:absolute;left:7px;right:7px;bottom:7px;text-align:center;
  font-family:"Marker Felt","Bradley Hand","Segoe Print",cursive;font-size:12px;color:#3A3A52;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.pola .tape{position:absolute;top:-9px;left:50%;width:50px;height:15px;margin-left:-25px;background:color-mix(in srgb,var(--paper) 72%,transparent);transform:rotate(-3deg)}

/* A photo at full size: the page goes dark and the picture takes what it can. */
.photoveil{padding:14px;background:color-mix(in srgb,var(--ink) 92%,transparent);cursor:zoom-out}
.lightbox{margin:0;display:flex;flex-direction:column;align-items:center;gap:10px;max-width:100%;max-height:100%}
.lightbox img{max-width:100%;max-height:calc(100vh - 80px);object-fit:contain;border-radius:6px;box-shadow:var(--shadow-lg)}
.lightbox figcaption{font-family:"Marker Felt","Bradley Hand","Segoe Print",cursive;font-size:15px;color:var(--paper)}
.lbx{position:absolute;top:calc(12px + env(safe-area-inset-top));right:14px;width:38px;height:38px;border-radius:50%;display:grid;place-items:center;background:rgba(255,255,255,.14);color:#fff}
.lbx:hover{background:rgba(255,255,255,.28)}

/* A league on the club page. */
.lg .hd{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:9px 13px 0}
.lg .fmt{font-family:var(--display);font-size:10px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--muted)}
.lg .fmt i{font-style:normal;color:var(--pink-deep)}
.lg .st{font-family:var(--display);font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);white-space:nowrap}
.lg .st.on{color:var(--live)} .lg .st.wait{color:var(--purple)}
.lg .nm{font-weight:700;font-size:16.5px;padding:2px 13px 0;color:var(--ink)}
.lg .when{font-size:13px;color:var(--ink2);padding:1px 13px 8px}
.lg .acts{display:flex;border-top:1px solid var(--line2)}
.lg .acts button{flex:1;text-align:center;padding:9px 6px;font-size:12.5px;font-weight:700;color:var(--ink2)}
.lg .acts button+button{border-left:1px solid var(--line2);color:var(--pink-deep)}
.lg .acts button:hover{background:var(--card2)}
.lg.past{opacity:.85}
.icard.pride{background:linear-gradient(90deg,var(--pink-soft),var(--purple-soft),var(--sky-soft));border-color:transparent;margin-top:14px}
.icard.pride .ib{color:var(--ink);font-weight:600}

/* On a wide screen the page is two columns: what Setup draws (the league card,
   where we play, the divisions) on the right, the manager's blocks on the
   left. Two screens of reading instead of five. The club page does the same
   with its leagues and blocks. */
/* On a phone the two wrappers fall away and the groups stack in reading
   order: the card, the venue, the divisions, the blocks. The DOM puts the
   right-hand column first so a wide screen reads the card before the rest. */
.igrid{display:flex;flex-direction:column}
.igrid .left,.igrid .right{display:contents}
.gh{order:1} .ga{order:2} .gb{order:3} .gc{order:4} .gp{order:5}
@media (min-width:1040px){
  .infopage{max-width:1120px}
  .igrid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:0 28px;align-items:start}
  /* Both wrappers named to row 1: the right one comes first in the DOM, and
     auto-placement would otherwise start the left one on the row after it. */
  .igrid .left{display:block;grid-area:1/1}
  .igrid .right{display:block;grid-area:1/2}
  .gh .icard.hero{margin-top:12px}
  .gc > .ih2:first-child,.gc > .eblk:first-child > .ih2{margin-top:12px}
}

/* The page's title, and Edit page beside it for a signed-in manager. */
.titlerow{display:flex;align-items:center;gap:12px}
.titlerow h1{flex:1;min-width:0}
.editpage{
  display:inline-flex;align-items:center;gap:6px;flex:none;padding:8px 13px;border-radius:999px;
  background:var(--ink);color:var(--paper);font-size:13px;font-weight:700;white-space:nowrap;
}
.editpage svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
@media (max-width:520px){ .editpage span{display:none} }

/* ---------- team sign-up ---------- */
/* The league card's spots line, from each division's limit. */
.spots{margin-top:12px}
.spots .nums{display:flex;justify-content:space-between;font-size:13px;margin-bottom:5px;color:var(--ink2)}
.spots .nums b{color:var(--ink);font-weight:700}
.spots .bar{height:6px;border-radius:3px;background:var(--card2);overflow:hidden}
.spots .bar i{display:block;height:100%;background:var(--ink);border-radius:3px}
td.st.confirmed{color:var(--live)}
td.st.pending,td.st.waitlisted{color:var(--muted)}

/* The form: the app's cards, with fields in them. */
.signup .lead{font-size:14px;color:var(--ink2);margin:4px 0 0}
.signup .icard .ib h4{font-family:var(--display);font-size:12px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin:0 0 6px}
.signup .f{display:block;margin-top:12px}
.signup .ib>.f:first-child,.signup .ib>h4+.f,.signup .two:first-child{margin-top:0}
.signup .f>span{display:block;font-family:var(--display);font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);margin-bottom:4px}
.signup input,.signup textarea{
  width:100%;box-sizing:border-box;font:inherit;font-size:16px;padding:10px 12px;
  border:1.5px solid var(--line);border-radius:9px;background:var(--card);color:var(--ink);
}
.signup textarea{resize:vertical;min-height:58px}
.signup .f.short input{width:90px}
.signup .two{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:12px}
.signup .two .f{margin-top:0}
.signup .hint{font-size:12.5px;color:var(--muted);margin-top:5px}
.signup .hint b{color:var(--ink)}
/* The division: one button per division, its spots on the button. */
.signup .seg{display:flex;gap:6px}
.signup .segopt{flex:1}
.signup .segopt input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.signup .segopt span{display:block;text-align:center;padding:8px 0 7px;border:1.5px solid var(--line);border-radius:9px;font-size:14px;font-weight:700;color:var(--ink);background:var(--card);cursor:pointer}
.signup .segopt span small{display:block;font-size:11px;font-weight:400;color:var(--muted);margin-top:1px}
.signup .segopt input:checked+span{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.signup .segopt.shut span{opacity:.45;cursor:not-allowed}
.signup .segopt input:checked+span small{color:rgba(255,255,255,.75)}
.signup .segopt input:focus-visible+span{outline:2.5px solid var(--pink);outline-offset:2px}
.signup .check{display:flex;gap:10px;align-items:flex-start;font-size:13.5px;line-height:1.4;color:var(--ink2)}
.signup .check input{width:20px;height:20px;margin:1px 0 0;accent-color:var(--ink);flex:none}
.signup .check a{color:var(--ink);font-weight:600}
/* The terms and the texting box sit one under the other, each its own answer. */
.signup .check + .check{margin-top:14px}
.signup .formerr{margin-top:12px;padding:10px 13px;border-radius:9px;background:var(--pink-soft);color:var(--pink-deep);font-size:13.5px;font-weight:600}
.signup .ibtns.one{margin-top:14px}
.signup .ibtns.one .btn{flex:1;max-width:none}
/* After the claim: the fee large, one button that opens Venmo filled in. */
.signup .fee{display:flex;align-items:baseline;gap:10px;margin:0 0 12px}
.signup .fee b{font-family:var(--display);font-size:34px;font-weight:700;line-height:1;color:var(--ink)}
.signup .fee span{color:var(--muted);font-size:13.5px}
.signup .ib a.venmo{display:flex;align-items:center;justify-content:center;gap:9px;background:#008CFF;color:#fff;font-weight:700;font-size:16px;padding:14px;border-radius:12px;text-decoration:none}
.signup .ib a.venmo:hover{background:#0077D9;color:#fff}
.signup .memo{display:flex;align-items:center;gap:8px;margin-top:6px;font-size:13.5px;background:var(--card2);border-radius:8px;padding:8px 10px}
.signup .memo span{font-family:var(--num);font-size:13px;flex:1;color:var(--ink)}
.signup .memo .copy{font-weight:700;color:var(--ink);font-size:12.5px;background:none;border:0;padding:0;cursor:pointer}
.signup .hint b{display:inline}
/* The form is one column at every width: a claim is filled on a phone, and on
   a desk a 560px column reads better than fields stretched across a screen. */
.infopage.signup{max-width:560px}
.signup .nodivs{margin-top:9px}

/* ================================================================ save bar */
/* One bar for every place edits collect and save together: the manager's
   schedule, rows and playoffs, and a page edited on the page. It sits where
   the dock does, and appears whenever there is something it could save.

   left:0;right:0 with margin-inline:auto, never left:50%. A fixed element with
   auto width shrinks to fit the space from its left edge to the viewport's, so
   left:50% gave it half the screen to work with and the label wrapped into a
   blob that read like a toast. */
.savebar{
  position:fixed;left:0;right:0;bottom:18px;z-index:60;
  margin-inline:auto;width:fit-content;
  display:flex;align-items:center;gap:14px;max-width:min(720px,calc(100vw - 24px));
  padding:11px 12px 11px 18px;border-radius:999px;
  background:var(--ink);color:var(--paper);box-shadow:var(--shadow-lg);
}
/* Nothing staged: still there, so it always shows where saving happens, but
   quiet enough not to read as something needing attention. */
.savebar.idle{background:var(--card);color:var(--muted);box-shadow:var(--shadow);border:1px solid var(--line)}
.savebar.idle b{color:var(--ink2)}
.savebar.idle .btn.primary{background:var(--line2);border-color:transparent;color:var(--muted);cursor:not-allowed}
.savebar.idle .btn:not(.primary){background:var(--card2);border-color:var(--line);color:var(--ink)}
.savebar b{font-family:var(--display);font-size:14px;letter-spacing:.02em;display:block}
.savebar small{font-size:11.5px;opacity:.75;display:block}
.savebar .btn{
  display:inline-flex;align-items:center;padding:7px 12px;font-size:12.5px;font-weight:600;border-radius:9px;
  border:1px solid transparent;background:rgba(255,255,255,.14);color:var(--paper);white-space:nowrap;
}
.savebar .btn:hover{background:rgba(255,255,255,.26);color:#fff}
.savebar .btn.primary{background:var(--paper);border-color:var(--paper);color:var(--ink)}
.savebar .btn.primary:hover{background:#fff;color:var(--ink)}
/* Room to scroll past the bar rather than under it. The foot is the last
   thing on the page, so it keeps clear of the bar. */
body.has-savebar .foot{padding-bottom:120px}
@media (max-width:560px){ body.has-savebar .foot{padding-bottom:170px} }
/* On a phone the pill becomes a block: the sentence gets its own line and the
   buttons share the one below, each half the width. Wrapping them inline left
   Discard stranded beside the text with Save dropped underneath it, which read
   as two unrelated controls. */
@media (max-width:560px){
  .savebar{
    left:10px;right:10px;bottom:10px;width:auto;max-width:none;
    border-radius:16px;flex-wrap:wrap;gap:10px;padding:13px 14px;
    padding-bottom:calc(13px + env(safe-area-inset-bottom));
  }
  .savebar span{flex:1 1 100%}
  .savebar small{opacity:.7}
  .savebar .btn{flex:1 1 0;justify-content:center}
  /* One button on its own takes the row. */
  .savebar.idle button.btn:only-of-type{flex:1 1 100%}
}
/* The toast sits above the dock, so a page with the bar instead lifts it
   clear of the bar's real height, which changes when the bar wraps. */
body.has-savebar #toast{
  bottom:calc(var(--savebar-h, 56px) + 32px + env(safe-area-inset-bottom));
}

/* ============================================== editing a page, on the page */
/* design/info-editing.html is the drawing. While editing, the dock gives way
   to the save bar the manager's screen uses, in the same place. */
html.editing .tabs,html.editing .editpage{display:none}
/* While typing on a phone the format bar is on the keyboard, and the save
   bar would sit on top of it. */
html.typing .savebar{display:none}
html.editing .gc{scroll-margin-top:12px}
/* Bold in the manager's words is bold, in the line; a card's own <b> is its
   title, which is why the plain rule above makes it a block. */
.icard .ib.md b,.icard .ib.md strong{display:inline;font-size:inherit;color:var(--ink)}

/* The half the manager's pages draw: faded, not editable here. A veil over
   each card rather than opacity on the column, so the links above them can
   stay at full strength. */
.igrid.editing .right :is(.icard,.divcard){position:relative;pointer-events:none}
.igrid.editing .right :is(.icard,.divcard)::after{content:"";position:absolute;inset:0;border-radius:inherit;background:color-mix(in srgb,var(--paper) 55%,transparent)}
/* Each box's "Edit in" link stays live: it is the way there. */
.igrid.editing .right .setuplink{pointer-events:auto}


/* The ? in a tip's circle is drawn, not typed. A typed one sits wherever the
   font's line box puts it, which is above the middle and differs by size; a
   drawn one is centred in the circle at every size. The character stays in
   the markup for screen readers; font-size:0 on the circle hides it. */
.tip::before{
  content:"";position:absolute;inset:-1px;background:currentColor;
  -webkit-mask:var(--qmark) center/100% no-repeat;mask:var(--qmark) center/100% no-repeat;
  --qmark:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 6.2a2 2 0 1 1 2.9 1.8c-.6.3-.9.8-.9 1.4' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/%3E%3Ccircle cx='8' cy='11.7' r='.9'/%3E%3C/svg%3E");
}

/* A block: an outline on hover, a solid one when selected, its kind on one
   corner and up, down and delete on the other. */
[contenteditable]{outline:none;-webkit-user-modify:read-write}
[contenteditable]:empty::before{content:attr(data-ph);color:var(--muted);opacity:.7;pointer-events:none}
.eblk{position:relative;border-radius:14px;padding:16px 8px 8px;margin:6px -8px 0;outline:1.5px dashed transparent;outline-offset:2px;transition:outline-color .12s;cursor:text}
.eblk > .ih2{margin-top:0}
@media (hover:hover){ .eblk:hover{outline-color:color-mix(in srgb,var(--sky-deep) 55%,transparent)} .eblk:hover .btag{display:block} }
.eblk.sel{outline:2px solid var(--sky-deep);background:color-mix(in srgb,var(--sky-soft) 35%,transparent)}
.btag{
  position:absolute;top:-11px;left:10px;display:none;font-family:var(--display);font-size:10px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;padding:3px 8px;border-radius:6px;background:var(--sky-deep);color:#fff;z-index:3;
}
.eblk.sel .btag{display:block}
.btool{position:absolute;top:-17px;right:10px;display:none;gap:2px;padding:3px;border-radius:10px;background:var(--ink);box-shadow:var(--shadow-lg);z-index:4}
.eblk.sel .btool{display:flex}
.btool button{width:34px;height:30px;border-radius:7px;display:grid;place-items:center;color:var(--paper)}
.btool button:hover{background:rgba(255,255,255,.16)}
.btool button:disabled{opacity:.3;cursor:default;background:none}
.btool button.del{color:#FF8DBD}
.btool svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.ih2.need,.addr input.need{box-shadow:0 0 0 2px var(--pink);border-radius:6px}
.eblk .rich{min-height:1.4em}

/* Questions while editing: every answer showing, each with a remove. */
.qe{padding:10px 13px 11px;position:relative}
.qe .q{font-size:13.5px;font-weight:700;color:var(--ink);padding-right:30px}
.qe .a{padding:4px 0 0;font-size:13.5px;color:var(--ink2)}
.qe+.qe{border-top:1px solid var(--line2)}
.eblk .rm{
  position:absolute;top:7px;right:8px;width:26px;height:26px;border-radius:7px;display:none;place-items:center;
  color:var(--pink-deep);background:var(--card2);border:1px solid var(--line);font-weight:700;font-size:15px;line-height:1;
}
.eblk.sel .rm{display:grid}
.addrow{display:none;width:100%;padding:10px 13px;border-top:1px solid var(--line2);text-align:left;font-size:13px;font-weight:700;color:var(--sky-deep)}
.eblk.sel .addrow{display:block}
.addrow:hover{background:var(--card2)}

/* Photos while editing: a remove on each frame, a caption typed on it, and a
   dashed frame that adds one. A frame still uploading is pale. */
.eblk .pola{cursor:default}
.eblk .pola .rm{top:-8px;right:-8px;border-radius:50%;z-index:2;box-shadow:var(--shadow)}
.eblk .pola .cap{min-height:17px;cursor:text}
.eblk .pola.pending .ph{opacity:.45}
.eblk .pola.pending::after{
  content:"";position:absolute;left:50%;top:42%;width:22px;height:22px;margin:-11px 0 0 -11px;border-radius:50%;
  border:2.5px solid var(--line);border-top-color:var(--sky-deep);animation:espin .8s linear infinite;
}
@keyframes espin{to{transform:rotate(360deg)}}
.pola.add{
  display:none;transform:none;border:2px dashed var(--line);background:transparent;box-shadow:none;padding:0;
  width:146px;height:178px;color:var(--sky-deep);font-weight:700;font-size:13px;place-items:center;
}
.eblk.sel .pola.add,.eblk .polas:not(:has(.pola:not(.add))) .pola.add{display:grid}

/* The + between blocks: a line and a button on hover with a mouse, the
   button always there on a phone. */
.eins{position:relative;height:22px;margin:4px 0 -6px;display:flex;align-items:center;justify-content:center}
.eins::before{content:"";position:absolute;left:0;right:0;top:50%;height:2px;background:var(--sky-deep);border-radius:2px;opacity:0;transition:opacity .12s}
.eins button{
  position:relative;width:26px;height:26px;border-radius:50%;display:grid;place-items:center;box-shadow:var(--shadow);
  background:var(--card);color:var(--sky-deep);border:1.5px solid var(--sky-deep);transition:opacity .12s,transform .12s;
}
.eins button svg{width:14px;height:14px;stroke:currentColor;stroke-width:2.4;stroke-linecap:round}
@media (hover:hover){
  .eins button{opacity:0;transform:scale(.8);background:var(--sky-deep);color:#fff;border:0}
  .eins:hover::before,.eins:hover button,.eins.open::before,.eins.open button{opacity:1;transform:none}
}
.eins.end{height:auto;margin-top:16px}
.eins.end::before{display:none}
.eins.end button,.eins.end:hover button{
  opacity:1;transform:none;width:100%;height:auto;border-radius:12px;padding:12px 16px;background:transparent;color:var(--sky-deep);
  border:1.5px dashed color-mix(in srgb,var(--sky-deep) 50%,transparent);box-shadow:none;font-weight:700;font-size:13px;display:flex;gap:6px;justify-content:center;
}

/* The format bar floats over a selection with a mouse, and sits on top of the
   keyboard on a phone, where a floating bar would land under a thumb. */
.efmt{position:fixed;z-index:70;display:none;align-items:center;gap:2px;padding:4px;border-radius:10px;background:var(--ink);box-shadow:var(--shadow-lg)}
.efmt.show{display:flex}
.efmt.docked{left:0;right:0;bottom:var(--kb);top:auto;border-radius:0;padding:6px 10px calc(6px + env(safe-area-inset-bottom));gap:6px}
.efmt button{min-width:36px;height:34px;border-radius:7px;color:var(--paper);font-weight:700;font-size:14px;display:grid;place-items:center;padding:0 9px}
.efmt button:hover{background:rgba(255,255,255,.14)}
.efmt button.on{background:var(--paper);color:var(--ink)}
.efmt button.i{font-style:italic;font-family:Georgia,serif}
.efmt svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.efmt input{width:220px;font:inherit;font-size:16px;padding:6px 9px;border-radius:7px;border:0;outline:none;background:#fff;color:var(--ink)}
.efmt.docked input{flex:1;width:auto}
.efmt .sep{width:1px;height:20px;background:rgba(255,255,255,.2);margin:0 3px}

/* Choosing what to add: a popover with a mouse, a sheet from the bottom on a phone. */
.epveil{position:fixed;inset:0;z-index:79;display:none}
.epveil.show{display:block}
.epop{position:fixed;z-index:80;background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow-lg);padding:12px;width:330px;display:none}
.epop.show{display:block}
@media (max-width:700px),(hover:none){
  .epveil.show{background:rgba(24,26,66,.35)}
  .epop.show{left:0;right:0;top:auto;bottom:0;width:auto;border-radius:18px 18px 0 0;padding:14px 14px calc(22px + env(safe-area-inset-bottom))}
}
.epop h4{margin:0 0 10px;font-family:var(--display);font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
.epop .kinds{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.epop .kind{display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px 6px 11px;border-radius:11px;border:1px solid var(--line);background:var(--card2);font-weight:700;font-size:13px;color:var(--ink)}
.epop .kind:hover{border-color:var(--sky-deep);background:var(--sky-soft)}
.epop .kind svg{width:30px;height:30px;stroke:var(--ink2);fill:none;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.epop .choose{width:100%;padding:12px;border-radius:10px;background:var(--ink);color:var(--paper);font-weight:700;font-size:14px}
.epop .lbl{font-family:var(--display);font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--muted);font-weight:700;margin:14px 0 5px}
.epop .addr{display:flex;gap:6px}
.epop .addr input{flex:1;min-width:0;font:inherit;font-size:16px;padding:8px 10px;border-radius:9px;border:1px solid var(--line);background:var(--card2);color:var(--ink)}
.epop .addr button{padding:8px 14px;border-radius:9px;background:var(--card2);border:1px solid var(--line);color:var(--ink);font-weight:700;font-size:13px}

