/* ===========================================================================
   SAPPHIRESPORTZ — THE BROADCAST CONTROL ROOM
   ---------------------------------------------------------------------------
   One visual thesis, and every choice below answers to it:

     This is the instrument panel of a franchise league. Measured, precise,
     built to be READ. Data carries scoreboard authority. Sapphire light is a
     SIGNAL — live, yours, hot — never decoration.

   Franchise players read box scores, cap sheets and dev traits for fun. So
   the craft budget goes into legibility and hierarchy, not chrome: tabular
   numerals everywhere digits stack, one honest depth model, container guides
   that reveal structure, and motion only where it explains something.

   Depth is three levels and no more:
     ground   the page itself
     surface  panels and cards sit on it
     raised   things that float above the page (chat, slip, dropdowns)
   On a near-black ground a big soft drop shadow does nothing — elevation is
   read from a top highlight, a hairline ring and a tight lift. That is the
   dark-UI translation of layered elevation, not a copy of the light-UI one.
   =========================================================================== */

:root {
  /* --- ground & surfaces --- */
  --ground:        #05080F;
  --ground-2:      #070C18;
  --surface:       rgba(10, 18, 38, 0.72);
  --surface-solid: #0B1222;
  --surface-hi:    rgba(16, 28, 58, 0.85);
  --raised:        rgba(8, 13, 28, 0.98);

  /* --- ink --- */
  --ink:        #E8EEFC;
  --ink-strong: #FFFFFF;
  --ink-muted:  #93A0BE;
  --ink-dim:    #5E6C8E;

  /* --- sapphire: the signal colour --- */
  --sap:      #2F6BFF;
  --sap-lift: #5B8BFF;
  --sap-soft: #8FB0FF;
  --sap-pale: #C3D4FF;
  /* The same four as channels, for the alphas (build 587). A league's look
     (app/look.py) overrides these with its own primary, so every hairline,
     tint and glow on the site follows the colour the league chose. */
  --sap-rgb:   47, 107, 255;
  --lift-rgb:  91, 139, 255;
  --soft-rgb:  143, 176, 255;
  --line-rgb:  97, 138, 255;
  --glow-rgb:  30, 62, 140;
  --glow-a:    0.28;
  /* BUILD 597: the keys' own colours. These ARE the hand-tuned sapphire the
     button layer used to write as literals, so a default league is unchanged
     to the digit; app/look.py tokens() overrides them for a league that has
     changed its colours (derived from its primary and ground) and sets
     --on-sap to dark ink when the primary is too light for white text. */
  --key-face-top: #5486FF;
  --key-face-bot: #2A62F0;
  --key-ring-rgb: 20, 50, 140;
  --sap-deep:     #1B3FA8;
  --deep-rgb:     20, 45, 120;
  --hi-rgb:       120, 160, 255;
  --key-top-hi:   #1C2C55;
  --key-bot-hi:   #111C3A;
  --sap-night:    #12224A;
  --on-sap:       #FFFFFF;
  --ground-rgb: 5, 8, 15;
  --ground-top: #060A16;

  /* --- meaning colours (never used as "series 4") --- */
  --gold:  #FFD98A;   /* money, markets, fantasy */
  --gold-2:#C8A552;
  --good:  #6BDB8F;
  --bad:   #FF8E8E;
  --hot:   #FF5A5A;   /* live */
  --pink:  #FF8EC8;   /* the social wire */
  --violet:#B983FF;   /* 2K, the court, the member guide */
  --sport-2k:#FF9B4A; /* the 2K identity accent, formalized (build 200) — was 19 scattered #FF9B4A literals across 6 templates */

  /* --- lines: one ladder, used consistently --- */
  /* THE FEW THE TEMPLATES NEEDED AND THE SYSTEM DID NOT HAVE.
     Found while token-ising the instrument pages for the machined skin: 438
     hard-coded colours across twelve templates, and all but these five already
     had a token waiting for them. The system was complete; nothing used it. */
  --ink-soft:      #C6D2EE;              /* between --ink and --ink-muted */
  --amber:         #FFB86B;              /* trading, the block, the desk */
  --wash:          rgba(15, 27, 62, 0.5);/* the header gradient on a page top */
  --surface-deep:  rgba(10, 18, 38, 0.9);
  --ground-0:      rgba(5, 8, 15, 0);    /* the transparent end of a gradient */

  --line:        rgba(var(--line-rgb), 0.14);
  --line-2:      rgba(var(--line-rgb), 0.22);
  --line-3:      rgba(var(--line-rgb), 0.34);
  --guide:       rgba(var(--line-rgb), 0.10);
  --guide-mark:  rgba(var(--line-rgb), 0.42);

  /* the sport identity accent — Madden's default is just the site's own
     blue; [data-sport="nba2k"] below overrides all four for the 2K side. */
  --sport-accent:   var(--sap);
  --sport-accent-2: var(--sap-lift);
  --sport-line:     var(--line-2);
  --sport-line-3:   var(--line-3);

  /* --- elevation, dark-UI style --- */
  --lift-1: 0 1px 0 0 rgba(255,255,255,0.045) inset,
            0 0 0 1px rgba(var(--line-rgb), 0.14),
            0 2px 6px rgba(2,5,14,0.5);
  --lift-2: 0 1px 0 0 rgba(255,255,255,0.07) inset,
            0 0 0 1px rgba(var(--line-rgb), 0.20),
            0 10px 24px -8px rgba(2,5,14,0.75),
            0 28px 60px -28px rgba(2,5,14,0.9);
  --lift-3: 0 1px 0 0 rgba(255,255,255,0.09) inset,
            0 0 0 1px rgba(var(--line-rgb), 0.28),
            0 18px 40px -12px rgba(2,5,14,0.8),
            0 48px 90px -40px rgba(0,0,0,0.95);
  --glow-sap:  0 0 0 1px rgba(var(--sap-rgb), 0.55), 0 6px 22px -4px rgba(var(--sap-rgb), 0.35);
  --glow-gold: 0 0 0 1px rgba(255,217,138,0.6), 0 6px 20px -4px rgba(200,165,82,0.3);

  /* --- shape --- */
  --r-sm: 8px; --r: 12px; --r-lg: 16px; --r-xl: 22px;

  /* --- layout --- */
  --container: 1440px;
  --pad: clamp(14px, 4vw, 48px);

  /* --- motion: human easing, no bounce on serious UI --- */
  --ease:     cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  /* --t-slow (420ms) lived here and had no users left after the two dead
     width transitions went. Two overlapping scales — fast/normal/slow and
     the semantic one below — is one scale too many, and the semantic one
     is the one that says WHY. */
  --t-fast: 120ms; --t: 220ms;
  /* THE MOTION LADDER, named so a new rule picks a rung instead of a number.
     Four durations and two curves, and everything on the site uses one of
     them. The ceiling is deliberate: past ~500ms a UI stops feeling responsive
     and starts feeling like it is thinking. --t-press is separate and the
     shortest of all, because a control somebody hits fifty times a session
     must never look like lag. */
  --t-press:   110ms;   /* the depress under a finger      */
  --t-control: 180ms;   /* a toggle, a tab, a hover state  */
  --t-panel:   260ms;   /* a popover, a sheet, a dropdown  */
  --t-section: 520ms;   /* a block of the page arriving    */

  /* --- type --- */
  --f-body: 'Archivo', 'Segoe UI', system-ui, sans-serif;
  --f-cond: 'Barlow Condensed', 'Arial Narrow', sans-serif;
}

/* ===========================================================================
   THE SPORT'S OWN COLOUR — build 200.
   ---------------------------------------------------------------------------
   data-sport has sat on <body> since build 119 with nothing reading it. The
   2K side of the site already had its own identity colour — orange, #FF9B4A —
   scattered as a literal across 19 places because every 2K-only template just
   hardcoded it. This turns that into two real tokens so the two games stay
   visually distinct on the shared chrome (the league crest ring, every section
   rule) without a parallel design system: Madden pages are simply the site's
   own sapphire blue, unmarked, because blue is already what SapphireSportz is;
   the 2K side gets the hardwood-orange accent it already used everywhere else.
   =========================================================================== */
[data-sport="nba2k"] {
  --sport-accent:   var(--sport-2k);
  --sport-accent-2: #FFB37A;
  --sport-line:     rgba(255, 155, 74, 0.22);
  --sport-line-3:   rgba(255, 155, 74, 0.34);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--f-body);
  background: var(--ground);
  color: var(--ink);
  /* A single cool wash from the top-left, so the page has a light source and
     panels have something to sit against. Fixed so it never scroll-jitters. */
  background-image:
    radial-gradient(120% 80% at 8% -8%, rgba(var(--glow-rgb), var(--glow-a)) 0%, rgba(var(--glow-rgb), 0) 58%),
    radial-gradient(90% 60% at 100% 0%, rgba(var(--sap-rgb), 0.10) 0%, rgba(var(--sap-rgb), 0) 55%);
  background-attachment: fixed;
  background-repeat: no-repeat;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--sap-soft); text-decoration: none; transition: color var(--t-fast) var(--ease); }
a:hover { color: var(--sap-pale); }
.cond { font-family: var(--f-cond); }

/* Every digit that stacks in a column lines up. On a stats site this is not a
   nicety — a scoreboard whose numbers wobble reads as amateur. */
.tbl, .tile .v, .scorecard .s, .rankn, .num, .stat-v, .wire-item b,
input[type="number"], .odds-btn .ob-line, td, th {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* Highlighting a stat to paste into Discord is something people do here every
   day. Left at the browser default it is a flat blue slab that belongs to
   nobody; in the signal colour it belongs to this site. */
::selection { background: rgba(var(--sap-rgb), 0.32); color: var(--ink-strong); }
::-moz-selection { background: rgba(var(--sap-rgb), 0.32); color: var(--ink-strong); }

/* Keyboard users get a real, visible ring everywhere. */
:focus-visible {
  outline: 2px solid var(--sap-lift);
  outline-offset: 2px;
  border-radius: 3px;
}

/* ===========================================================================
   CONTAINER GUIDES
   Two hairlines at the exact edges of the content container, with small marks
   where major sections meet them. They reveal the page's structure and give
   the whole thing a measured, instrument-panel feel. Behind everything, never
   clickable. Off on phones, where there is no room to spare.
   =========================================================================== */
body::before, body::after {
  content: "";
  position: fixed;
  top: 0; bottom: 0;
  width: 1px;
  background: var(--guide);
  pointer-events: none;
  z-index: 0;
}
/* WHERE EXACTLY. Two things were wrong with the first version and both are
   the kind you only see once you measure: on a 1920 monitor the guides sat
   240px from each edge while the content started at 281, so the lines ran 41px
   outside every panel and read as stray rules rather than as the edge of
   anything.
     1. They marked the container's BORDER box. .wrap is 1440 wide with 48px of
        its own padding, so the content edge — which is what a person sees, and
        the only edge worth drawing — is 48px further in. + var(--pad).
     2. 100vw INCLUDES THE SCROLLBAR. A percentage on a fixed element resolves
        against the viewport WITHOUT it, which is the same box .wrap centres
        itself in, so 100% and .wrap now agree by construction rather than by
        being off by fifteen pixels on every desktop with a visible scrollbar.
   max(0px, …) rather than max(var(--pad), …): below the container width the
   centring term goes negative, and the padding is added once at the end. */
body::before { left:  calc(max(0px, (100% - var(--container)) / 2) + var(--pad)); }
body::after  { right: calc(max(0px, (100% - var(--container)) / 2) + var(--pad)); }
@media (max-width: 900px) { body::before, body::after { display: none; } }

/* Section corner marks — opt in with class="marked" on a panel or section. */
.marked { position: relative; }
.marked::before, .marked::after {
  content: ""; position: absolute; width: 5px; height: 5px;
  background: var(--guide-mark); pointer-events: none;
}
.marked::before { top: -1px; left: -1px; }
.marked::after  { top: -1px; right: -1px; }

/* ---------------------------------------------------------------- masthead */
.masthead {
  display: flex; align-items: stretch; gap: 24px;
  padding: 0 var(--pad);
  background: rgba(6, 10, 20, 0.86);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 60;
  backdrop-filter: blur(14px) saturate(1.3);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
}

/* ===========================================================================
   THE EDGE UNDER THE HEADER — a graded blur, not a hard cut
   ---------------------------------------------------------------------------
   The masthead is translucent, so content slid under it and stopped dead at a
   1px line. That line is the tell: it says "two rectangles", where an app says
   "one surface with depth". The fix is the oldest trick in iOS — the blur does
   not switch on, it RAMPS: four strips stacked under the bar, each blurring
   harder and masked to its own band, so a row of numbers scrolling up softens
   through four stages before it reaches the edge.

   FOUR STEPS, NOT EIGHT. The canonical recipe uses eight stacked
   backdrop-filters. Eight composited blur layers pinned to the viewport is a
   real cost on the mid-range Androids half this league is holding, and past
   four the ramp is indistinguishable. Four buys the effect at half the price.

   It is `fixed` and `pointer-events: none`, and it sits BELOW the masthead's
   z-index and ABOVE the page, so it blurs the page and never the bar, and
   nothing in it can ever swallow a tap.
   =========================================================================== */
.edge-blur {
  /* IT HAS TO SIT BELOW THE STICKY STACK, and the stack is not a number I can
     write here. The masthead is one height on a desktop, another on a phone,
     and a third when the wordmark wraps; on a phone the scroller sits under it
     as a second bar. Pinned at top:0 the strip is simply BEHIND the masthead,
     which is exactly where the first version of this put it — invisible, and
     the softening I thought I was looking at was the bar's own flat blur.
     --stack-h is measured once on load and on resize, never per frame. */
  position: fixed; inset: var(--stack-h, 64px) 0 auto 0; height: 42px;
  z-index: 54; pointer-events: none;
}
.edge-blur > i {
  position: absolute; inset: 0; display: block;
}
.edge-blur > i:nth-child(1) {
  backdrop-filter: blur(1px); -webkit-backdrop-filter: blur(1px);
  -webkit-mask-image: linear-gradient(to top, transparent 0%, #000 30%, #000 55%, transparent 80%);
          mask-image: linear-gradient(to top, transparent 0%, #000 30%, #000 55%, transparent 80%);
}
.edge-blur > i:nth-child(2) {
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  -webkit-mask-image: linear-gradient(to top, transparent 25%, #000 55%, #000 75%, transparent 92%);
          mask-image: linear-gradient(to top, transparent 25%, #000 55%, #000 75%, transparent 92%);
}
.edge-blur > i:nth-child(3) {
  backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px);
  -webkit-mask-image: linear-gradient(to top, transparent 50%, #000 78%, #000 100%);
          mask-image: linear-gradient(to top, transparent 50%, #000 78%, #000 100%);
}
.edge-blur > i:nth-child(4) {
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  -webkit-mask-image: linear-gradient(to top, transparent 72%, #000 100%);
          mask-image: linear-gradient(to top, transparent 72%, #000 100%);
}
/* The strip only exists to soften what passes UNDER the bar. At the top of the
   page there is nothing under it, so it fades out — otherwise the first 34px
   of every page is blurred for no reason. `.scrolled` is set once, by one
   passive listener, and never measures layout. */
.edge-blur { opacity: 0; transition: opacity var(--t-control) linear; }
html.scrolled .edge-blur { opacity: 1; }
/* On a phone the header stack is masthead + scroller, so the strip sits under
   both rather than in the middle of them. */
@media (max-width: 900px) { .edge-blur { height: 32px; } }
/* backdrop-filter on a strip pinned to the viewport is the one thing here that
   costs battery. Somebody who has asked for less motion is usually asking for
   less of everything, so this goes with it. */
@media (prefers-reduced-motion: reduce) { .edge-blur { display: none; } }
html[data-motion="off"] .edge-blur { display: none; }

/* THE HEADER EARNS ITS LINE. At the very top of a page there is nothing above
   the content, so a border under the bar is drawing a division that isn't
   there. It appears once you are actually scrolled past something — the cue
   every native title bar gives and this one didn't. */
.masthead { transition: background var(--t-control) linear,
                        border-color var(--t-control) linear; }
html:not(.scrolled) .masthead { border-bottom-color: transparent; }
html.scrolled .masthead { background: rgba(6, 10, 20, 0.94); }

.brand { display: flex; align-items: center; gap: 11px; padding: 12px 0; }
.brand img {
  width: 40px; height: 40px; object-fit: contain;
  filter: drop-shadow(0 0 14px rgba(var(--sap-rgb), 0.45));
  transition: filter var(--t) var(--ease);
}
.brand:hover img { filter: drop-shadow(0 0 20px rgba(var(--lift-rgb), 0.7)); }
/* A league's own crest, beside the site's (build 119). Bounded and clipped:
   the file is a 512px square PNG the server wrote, but the box is what keeps
   a page's layout the same whatever is in it. */
.league-crest { display: flex; align-items: center; padding: 8px 0 8px 4px; flex: 0 0 auto;
  /* the sport's own accent (build 200) — a Madden league gets the site's
     usual blue border here; a 2K league gets the hardwood-orange one */
  border-left: 1px solid var(--sport-line-3, var(--line)); margin-left: 2px; padding-left: 12px; }
.league-crest img { width: 36px; height: 36px; object-fit: contain; border-radius: 8px;
  background: rgba(255,255,255,0.04); }
@media (max-width: 720px) { .league-crest img { width: 28px; height: 28px; } }
.wordmark {
  font-family: var(--f-cond); font-weight: 700; font-size: 20px;
  letter-spacing: 0.24em; color: var(--ink-strong); white-space: nowrap;
}
.wordmark b { color: var(--sap-lift); font-weight: 700; }
.nav { display: flex; align-items: stretch; flex-grow: 1; }
.navlink { position: relative; }
.navlink > a {
  display: flex; align-items: center; gap: 6px; padding: 22px 12px;
  color: #C7D2EA; font-weight: 600; font-size: 13px; letter-spacing: 0.12em;
  position: relative;
  /* A two-word tab ("THE BOOK", "MY TEAM") must never fold onto two lines and
     push the whole masthead taller — nine tabs is the most this bar carries. */
  white-space: nowrap;
}
/* The active rule grows from the centre instead of blinking on — the one
   place a nav needs to feel mechanical rather than instant. */
.navlink > a::after {
  /* Grows from the centre — the one place a nav should feel mechanical rather
     than instant. It used to do that by animating LEFT and RIGHT, which is two
     layout properties on the most-hovered element on the site. scaleX from a
     centre origin is the identical movement, on the compositor, and cannot
     make the header re-lay-out under a hover. */
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--sap);
  transform: scaleX(0); transform-origin: 50% 50%;
  transition: transform var(--t) var(--ease);
}
.navlink:hover > a, .navlink.active > a { color: var(--ink-strong); }
.navlink:hover > a::after, .navlink.active > a::after { transform: scaleX(1); }

.dd {
  display: none; position: absolute; top: 100%; left: 0; min-width: 230px;
  background: var(--surface-solid); z-index: 90;
  border: 1px solid var(--line-2); border-top: 2px solid var(--sap);
  border-radius: 0 0 var(--r) var(--r);
  box-shadow: var(--lift-3); padding: 8px 0;
  animation: dd-in var(--t) var(--ease-out);
  /* A MENU MUST NEVER BE TALLER THAN THE SCREEN. A dropdown closes when the
     pointer leaves it, so a link below the fold is a link nobody can reach —
     which is exactly what a 24-item ADMIN menu was on a laptop. Cap it at the
     viewport and let it scroll; the columns below keep it from needing to. */
  max-height: calc(100vh - 84px); overflow-y: auto; overscroll-behavior: contain;
}
@keyframes dd-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
/* A MENU MUST NEVER RUN OFF THE SCREEN either — navmenu.js measures the open
   menu against the viewport and sets --dd-shift when a wide, multi-column
   menu (LEAGUE's five columns) opens under a tab with less room to its right
   than the menu needs. left, not transform: the entrance animation above
   already owns transform, and a static transform here would be overwritten
   the instant that animation finishes. */
.dd.dd-shifted { left: var(--dd-shift, 0); }
.navlink:hover .dd { display: block; }
/* SIDE-BY-SIDE GROUPS. A section flagged `cols` lays its groups out as
   columns, so a menu is as tall as its LONGEST group rather than the sum of
   all of them. Each column keeps its own label at the top. */
.dd.cols { padding: 8px 6px; }
.navlink:hover .dd.cols { display: flex; align-items: flex-start; gap: 2px; }
/* BUILD 431: PLAY carries five groups. On a 1280 laptop five columns are wider
   than the glass, and no amount of sliding left (navmenu.js) can fit a menu
   wider than the window. So the columns wrap: the menu is capped at the
   viewport and a fifth column drops under the first, still in reach. */
.dd.cols { width: max-content; max-width: calc(100vw - 24px); flex-wrap: wrap; row-gap: 6px; }
.dd.cols .ddg { min-width: 215px; max-width: 290px; }
.dd.cols .ddg + .ddg { border-left: 1px solid var(--line-2); }
.dd.cols .ddg .lbl { white-space: nowrap; }
.dd a { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 290px; }
.dd a {
  display: block; padding: 10px 18px; color: #AAB8D8; font-size: 13px;
  font-weight: 500; border-left: 2px solid transparent;
  /* padding-left used to be in here, and it fired on every hover of every
     row of every dropdown — a layout property, animated, on the most-used
     interaction in the header. transform does the same 4px nudge on the
     compositor and cannot reflow the menu around it. */
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.dd a:hover {
  background: rgba(var(--sap-rgb), 0.12); color: var(--ink-strong);
  border-left-color: var(--sap); transform: translateX(4px);
}
.dd .lbl {
  padding: 10px 18px 4px; font-size: 10px; letter-spacing: 0.22em;
  color: var(--ink-dim); font-weight: 700;
}
.mast-cta { display: flex; align-items: center; gap: 14px; }

/* ----------------------------------------------------------- shared pieces */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  background: linear-gradient(135deg, var(--sap), var(--sap-deep));
  padding: 13px 24px; border-radius: var(--r-sm);
  box-shadow: 0 8px 22px -6px rgba(var(--sap-rgb), 0.55),
              0 0 0 1px rgba(var(--hi-rgb), 0.28) inset;
  color: var(--on-sap) !important; font-weight: 700; font-size: 14px;
  border: 0; cursor: pointer; font-family: inherit;
  transition: transform var(--t-fast) var(--ease),
              box-shadow var(--t) var(--ease), filter var(--t-fast) var(--ease);
}
.btn:hover { filter: brightness(1.08);
             box-shadow: 0 12px 30px -6px rgba(var(--sap-rgb), 0.65),
                         0 0 0 1px rgba(var(--hi-rgb), 0.4) inset; }
.btn:active { transform: translateY(1px); }
.btn.ghost {
  background: none; border: 1px solid var(--line-3); box-shadow: none;
  color: var(--sap-pale) !important;
}
.btn.ghost:hover { background: rgba(var(--sap-rgb), 0.1); border-color: var(--sap); filter: none; }

/* The panel. A gradient edge and an inner top highlight give it a real light
   source; both stay under 0.4 opacity so it reads as material, not shine. */
.panel {
  position: relative;
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    linear-gradient(150deg, rgba(255,255,255,0.16), rgba(var(--sap-rgb), 0.22) 46%,
                    rgba(255,255,255,0.04)) border-box;
  border: 1px solid transparent;
  border-radius: var(--r-lg);
  box-shadow: var(--lift-1);
  transition: box-shadow var(--t) var(--ease);
}
.panel-hd {
  display: flex; align-items: center; justify-content: space-between;
  padding: 15px 20px; border-bottom: 1px solid var(--line);
  font-family: var(--f-cond); font-weight: 800; font-style: italic;
  font-size: 17px; letter-spacing: 0.06em; color: var(--ink-strong);
  text-transform: uppercase;
}
.kicker {
  display: inline-block;
  font-size: 11px; font-weight: 700; letter-spacing: 0.2em;
  color: var(--sap-pale); text-transform: uppercase;
}
.dim { color: var(--ink-dim); }
.muted { color: var(--ink-muted); }
.h-italic {
  font-family: var(--f-cond); font-style: italic; font-weight: 800;
  text-transform: uppercase; color: var(--ink-strong);
  letter-spacing: -0.005em; line-height: 1.02;
}
.grad-text {
  background: linear-gradient(100deg, var(--sap-lift) 0%, var(--sap) 55%, var(--sap-bright, #7FA5FF) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--line-2); border-radius: 999px; padding: 5px 13px;
  font-size: 12px; color: var(--ink-muted); background: rgba(10, 18, 38, 0.5);
  transition: border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease),
              background var(--t-fast) var(--ease);
}
a.chip:hover, button.chip:hover { border-color: var(--line-3); color: var(--ink); }
.chip.on, .chip[aria-pressed="true"] { border-color: rgba(var(--sap-rgb), 0.7); color: var(--ink-strong);
           background: rgba(var(--sap-rgb), 0.18); }
.dev-badge-icon { width: 14px; height: 14px; display: block; flex-shrink: 0; }

.tile {
  background: var(--surface-hi); border: 1px solid var(--line-2);
  border-radius: var(--r); padding: 14px 16px;
  box-shadow: 0 1px 0 0 rgba(255,255,255,0.04) inset;
}
/* The number IS the content on a stat tile — give it broadcast weight. */
.tile .v {
  font-family: var(--f-cond); font-weight: 800; font-style: italic;
  font-size: 32px; line-height: 0.98; color: var(--ink-strong);
  letter-spacing: -0.01em;
}
.tile .l {
  font-size: 10.5px; letter-spacing: 0.16em; font-weight: 700;
  color: var(--ink-dim); text-transform: uppercase; margin-top: 4px;
}

.wrap { max-width: var(--container); margin: 0 auto; padding: 0 var(--pad);
        position: relative; z-index: 1; }

/* ------------------------------------------------------------------ tables */
.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.tbl th {
  text-align: left; padding: 9px 10px; font-size: 10.5px; letter-spacing: 0.16em;
  color: var(--ink-dim); border-bottom: 1px solid var(--line-2);
  font-weight: 700; text-transform: uppercase; white-space: nowrap;
}
.tbl td { padding: 11px 10px; border-bottom: 1px solid rgba(var(--line-rgb), 0.07);
          color: #C7D2EA; }
.tbl .num { text-align: right; }
.tbl tbody tr, .tbl tr { transition: background var(--t-fast) linear; }
.tbl tr:hover td { background: rgba(var(--sap-rgb), 0.07); color: var(--ink); }
.tbl tr:last-child td { border-bottom: none; }

/* Rank numerals read as architecture — quiet, mono-ish, never louder than the
   name beside them. */
.rankn {
  font-family: var(--f-cond); font-style: italic; font-weight: 800;
  font-size: 16px; color: #8FA6D8; letter-spacing: 0.02em;
}
.win { color: var(--good); font-weight: 700; }
.loss { color: var(--bad); font-weight: 700; }
.bar-track { flex-grow: 1; height: 8px; border-radius: 4px;
             background: rgba(var(--line-rgb), 0.12); overflow: hidden; }
/* NO TRANSITION. The width here is rendered once by the server and never
   changes again — nothing in any template or script writes to it — so the
   transition could not fire, and the one thing it could do was name a layout
   property in a stylesheet that promises not to animate layout. Deleted
   rather than converted to a transform: a bar that never moves does not need
   a technique for moving cheaply. */
.bar-fill { height: 8px; border-radius: 4px;
            background: linear-gradient(90deg, var(--sap), var(--sap-lift)); }

.footer {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 14px; padding: 26px var(--pad);
  border-top: 1px solid var(--line); font-size: 12px; font-weight: 600;
  position: relative; z-index: 1;
}
.footer a { color: #6B7A9C; margin-left: 24px; }

.scorecard { display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
.scorecard .row { display: flex; justify-content: space-between; align-items: center; }
.scorecard .s {
  font-family: var(--f-cond); font-weight: 800; font-size: 18px;
  color: var(--ink-strong); letter-spacing: 0.01em;
}
.avatar {
  border-radius: 50%; background: linear-gradient(135deg, var(--sap), var(--sap-night));
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--f-cond); font-weight: 700; color: #FFF;
  box-shadow: 0 0 0 1px rgba(var(--line-rgb), 0.35);
}

/* -------------------------------------------------------------- mobile nav */
.mobile-nav {
  display: none; gap: 4px; overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; padding: 0 10px; background: rgba(8, 13, 26, 0.95);
  border-bottom: 1px solid var(--line-2);
  position: sticky; top: 0; z-index: 55;
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  justify-content: safe center;
}
html { scroll-padding-top: 84px; }
[id] { scroll-margin-top: 84px; }
@media (max-width: 900px) {
  html { scroll-padding-top: 120px; }
  [id] { scroll-margin-top: 120px; }
}
.mobile-nav::-webkit-scrollbar { display: none; }
.mobile-nav a {
  flex-shrink: 0; padding: 12px 11px; font-size: 12px; font-weight: 700;
  letter-spacing: 0.06em; color: #AAB8D8; white-space: nowrap;
  border-bottom: 2px solid transparent;
}
.mobile-nav a.on { color: var(--ink-strong); border-bottom-color: var(--sap); }

/* ------------------------------------------------- the phone's full menu */
/* MENU sits first in the scroller and is styled as a control, not a link, so
   a thumb reads it as "there is more here" rather than as another destination
   that happens to be at the start of a list. */
.mn-more {
  flex-shrink: 0; padding: 12px 12px; font: inherit; font-size: 12px;
  font-weight: 800; letter-spacing: 0.08em; color: #FFF; background: none;
  border: 0; border-bottom: 2px solid transparent; cursor: pointer;
  white-space: nowrap;
}
.mn-more[aria-expanded="true"] { border-bottom-color: var(--sap); }
/* `hidden` MUST WIN HERE. The attribute's default is display:none from the UA
   stylesheet, and a class rule setting display:flex beats it on specificity —
   so the first version of this sheet rendered OPEN, full screen, over every
   page on every phone, swallowing taps meant for the page underneath. It was
   caught by driving a real browser, not by reading the CSS. */
.mn-sheet[hidden] { display: none !important; }

/* THE FINDER (build 83) — same trap, same fix. The layout lives on the class
   so that `hidden` actually hides it; the inline display:flex the first
   version carried beat the hidden attribute and the overlay sat over every
   page from load. */
.finder { position: fixed; inset: 0; z-index: 9000; background: rgba(3,6,14,0.72);
          backdrop-filter: blur(4px); display: flex; align-items: flex-start;
          justify-content: center; padding: 12vh 14px 0; }
.finder[hidden] { display: none !important; }
/* The hint row tells the truth about the device: keyboard words on a
   keyboard, "tap ✕" where there is no Escape key to press. */
.finder-touch { display: none; }
@media (hover: none), (max-width: 720px) {
  .finder-kb { display: none; }
  .finder-touch { display: inline; }
  .finder { padding-top: 6vh; }
}
.mn-sheet {
  position: fixed; inset: 0; z-index: 1400;
  background: rgba(3, 6, 14, 0.72);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  display: flex; align-items: flex-start; justify-content: center;
}
.mn-panel {
  animation: mn-in var(--t-control) var(--ease-out);
  width: 100%; max-width: 560px; max-height: 100dvh;
  display: flex; flex-direction: column;
  background: #070C18; border: 1px solid var(--line-2);
  border-top: 0; border-radius: 0 0 14px 14px;
}
.mn-head {
  display: flex; align-items: center; gap: 12px; padding: 14px 16px;
  border-bottom: 1px solid var(--line-2); position: sticky; top: 0;
  background: #070C18; z-index: 1;
}
.mn-head .kicker { flex-grow: 1; }
.mn-close {
  background: none; border: 0; color: #AAB8D8; font-size: 20px;
  line-height: 1; padding: 6px 10px; cursor: pointer; font: inherit;
}
/* The body scrolls, the head does not. -webkit-overflow-scrolling keeps the
   momentum flick on older iOS, where without it a long menu feels stuck. */
/* flex:none on both fixed rows. Without it the flex column hands all the
   height to .mn-body and squashes these two, which clipped the jump chips to
   half a line of text. */
.mn-head, .mn-jump { flex: none; }
.mn-jump {
  display: flex; align-items: center; gap: 4px; overflow-x: auto;
  scrollbar-width: none;
  padding: 8px 12px; border-bottom: 1px solid rgba(var(--line-rgb), 0.1);
  background: #070C18;
}
.mn-jump::-webkit-scrollbar { display: none; }
.mn-jump a {
  flex-shrink: 0; padding: 8px 11px; font-size: 10.5px; font-weight: 800;
  letter-spacing: 0.1em; color: #AAB8D8; white-space: nowrap;
  border: 1px solid var(--line-2); border-radius: 999px;
}
.mn-body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 8px 0 24px;
  scroll-padding-top: 8px;
}
.mn-sec { scroll-margin-top: 8px; }
.mn-sec { padding: 6px 0 10px; border-bottom: 1px solid rgba(var(--line-rgb), 0.08); }
.mn-sec:last-child { border-bottom: 0; }
.mn-sec-t {
  display: block; padding: 10px 16px 6px; font-family: var(--f-cond);
  font-size: 15px; font-weight: 800; letter-spacing: 0.1em; color: #FFF;
}
.mn-lbl {
  padding: 8px 16px 2px; font-size: 9.5px; font-weight: 800;
  letter-spacing: 0.16em; color: #6B7BA0;
}
/* 44px of thumb, which is the whole reason this is a sheet and not a longer
   scroller of 12px chips. */
.mn-i {
  display: block; padding: 12px 16px; font-size: 14px; font-weight: 600;
  color: #C3D0E8; min-height: 44px; box-sizing: border-box;
}
.mn-i:active { background: rgba(var(--sap-rgb), 0.14); }
/* MENU BELONGS WHEREVER THE DROPDOWNS DO NOT.
   This used to read 901px, on the reasoning that a desktop already has the
   dropdowns and MENU would be a second way to say the same thing. True — but
   the handover to the scrolling bar moved to 1000 (see THE MASTHEAD MUST FIT
   THE SCREEN below), and for the fifty minutes this was wrong, 901-1250px had
   no dropdowns AND no MENU: the only route to Admin, Settings and half the
   site was gone on exactly the laptop widths most people use. The two numbers
   are the same decision and have to be the same number. */
@media (min-width: 1001px) { .mn-more, .mn-sheet { display: none !important; } }
.mobile-nav a:hover { color: var(--ink-strong); }

/* The account menu is the one dropdown that must work on a phone: it is the
   only route to Team Center, Settings and Sign out. Tap toggles .open; hover
   still opens it where there is a pointer. */
.usermenu.open .usermenu-dd { display: block; }
/* A z-index on the dropdown alone CANNOT do this. `.masthead` is
   position:sticky with a z-index, which makes it a stacking context — every
   child is sealed inside it and can never rise above one of the masthead's
   own siblings, however large a number you write. The tour prompt and the
   chat bubble are exactly those siblings, at 999 and 900.
   So the MASTHEAD is what lifts, and only while the menu is open. */
.usermenu-dd { z-index: 1200; }
.masthead.menu-open { z-index: 1300; }
.umtrig { color: inherit; }
.usermenu.open .umtrig, .usermenu:hover .umtrig { color: var(--ink-strong); }

@media (max-width: 900px) {
  /* Everything EXCEPT the account menu — see above. It used to be caught by
     this blanket rule, which is why tapping your own avatar did nothing. */
  .nav, .dd:not(.usermenu-dd) { display: none !important; }
  .usermenu-dd { display: none; }
  .usermenu.open .usermenu-dd { display: block !important; }
  /* Bigger targets and a wider sheet — this is a thumb, not a mouse. */
  .usermenu-dd { min-width: 230px; max-width: calc(100vw - 24px); }
  .usermenu-dd a { padding: 14px 18px; font-size: 14px; }
  .u-name { display: none; }
  .mobile-nav { display: flex; }
  .masthead { gap: 12px; padding: 0 14px; }
  .mast-cta .btn { padding: 9px 14px; font-size: 12px; }
  .wordmark { font-size: 16px; letter-spacing: 0.16em; }
  .brand img { width: 32px; height: 32px; }
  .mobile-nav { top: 64px; justify-content: flex-start; }

  .wrap { padding-left: 14px; padding-right: 14px; }
  .panel { border-radius: var(--r); }
  .tbl { font-size: 12px; }
  .tbl th { padding: 7px 6px; font-size: 9.5px; letter-spacing: 0.1em; }
  .tbl td { padding: 9px 6px; }
  .tile .v { font-size: 26px; }
  .h-italic { letter-spacing: 0.01em; }
  .footer { padding: 20px 16px; font-size: 11px; }
  .footer a { margin-left: 14px; }
}

/* Horizontal scroller utility — score rails, results strips, chip rows. */
.hscroll { display: flex; overflow-x: auto; -webkit-overflow-scrolling: touch;
           scrollbar-width: none; gap: 12px; scroll-snap-type: x proximity; }
.hscroll::-webkit-scrollbar { display: none; }
.hscroll > * { scroll-snap-align: start; }
@media (max-width: 900px) {
  .grid-to-rail { display: flex !important; grid-template-columns: none !important;
                  overflow-x: auto; -webkit-overflow-scrolling: touch;
                  scrollbar-width: none; scroll-snap-type: x proximity; }
  .grid-to-rail::-webkit-scrollbar { display: none; }
  .grid-to-rail > * { flex: 0 0 210px; scroll-snap-align: start; }
}

/* ===========================================================================
   THE BOOK — sportsbook markets
   Gold is money here and nowhere else, so a selected pick is unmistakable.
   =========================================================================== */
.odds-btn {
  position: relative; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 2px; width: 100%;
  padding: 10px 8px; border-radius: var(--r); cursor: pointer;
  font-family: inherit; background: rgba(14, 24, 52, 0.85);
  border: 1px solid var(--line-3); color: var(--ink);
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease), transform 60ms var(--ease);
}
.odds-btn:hover { border-color: rgba(255,217,138,0.55); background: rgba(24,38,78,0.9); }
.odds-btn:active { transform: scale(0.98); }
.odds-btn .ob-side {
  font-size: 11px; font-weight: 700; color: #AEBBDD; letter-spacing: 0.03em;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.odds-btn .ob-line {
  font-family: var(--f-cond); font-weight: 800; font-style: italic;
  font-size: 20px; color: var(--gold); line-height: 1;
}
.odds-btn.on {
  border-color: var(--gold);
  background: linear-gradient(160deg, rgba(74,58,16,0.55), rgba(30,40,74,0.9));
  box-shadow: var(--glow-gold);
}
.odds-btn.on::after { content: '✓'; position: absolute; top: 4px; right: 7px;
                      font-size: 10px; color: var(--gold); }
.odds-btn.off { opacity: 0.45; }
/* build 491: each side's own price, and a game being played live */
.odds-btn .ob-odds { font-size: 11px; font-weight: 800; color: var(--gold); font-variant-numeric: tabular-nums; }
.odds-btn .ob-live { font-size: 8.5px; font-weight: 800; letter-spacing: 0.1em; color: #FF6B6B; }
.odds-btn.ob-livegame { border-color: rgba(255,90,90,0.45); }
.odds-btn.won { border-color: rgba(107,219,143,0.7);
                box-shadow: inset 0 0 0 1px rgba(107,219,143,0.4); }
.odds-btn.lost { opacity: 0.35; }
/*  Build 365: signed out. The line keeps its shape and its place -- it is
    what the reader was already reaching for -- and says what it wants. */
/*  Build 365: the quick stakes on the bet slip. Nobody should have to type
    a number to place a bet. */
.ps-quick-btn {
  font-family: inherit; font-size: 11px; font-weight: 800; letter-spacing: 0.06em;
  padding: 6px 10px; border-radius: 6px; cursor: pointer; color: var(--sap-pale);
  background: rgba(var(--sap-rgb), 0.10); border: 1px solid var(--line-3);
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.ps-quick-btn:hover { border-color: rgba(255,217,138,0.55); background: rgba(var(--sap-rgb), 0.20); }
.ps-quick-btn:active { transform: scale(0.96); }
a.odds-btn.odds-in { text-decoration: none; }
a.odds-btn.odds-in::after {
  content: 'SIGN IN'; position: absolute; top: 3px; right: 6px;
  font-size: 8.5px; font-weight: 800; letter-spacing: 0.12em;
  color: var(--sap-soft);
}
a.odds-btn.odds-in .ob-line { color: var(--sap-pale); }
a.odds-btn.odds-in:hover { border-color: rgba(var(--line-rgb), 0.6); }
.odds-btn[disabled] { cursor: default; }
.odds-btn[disabled]:hover { border-color: var(--line-3); background: rgba(14,24,52,0.85); }
.mkt-lbl { font-size: 9.5px; font-weight: 800; letter-spacing: 0.18em;
           color: #7E8BAD; margin-bottom: 6px; text-transform: uppercase; }

.game-card { padding: 0; overflow: hidden; }
.game-hd {
  display: flex; align-items: center; gap: 12px; padding: 13px 18px;
  background: linear-gradient(90deg, rgba(20,39,92,0.6), rgba(10,18,38,0.15));
  border-bottom: 1px solid var(--line);
}
.game-hd img { width: 34px; height: 34px; object-fit: contain;
               filter: drop-shadow(0 2px 6px rgba(0,0,0,0.5)); }
.game-hd .gh-team { display: flex; align-items: center; gap: 9px; min-width: 0; flex: 1; }
.game-hd .gh-name { font-family: var(--f-cond); font-weight: 800; font-style: italic;
                    font-size: 20px; color: var(--ink-strong); line-height: 1.05; }
.game-hd .gh-rec { font-size: 10px; color: var(--ink-muted); }
.split-bar { display: flex; height: 5px; border-radius: 3px; overflow: hidden;
             background: rgba(18,34,74,0.7); }
/* Same as .bar-fill: server-rendered once, so this transition never ran. */
.split-bar > * { }
.pp-card {
  /* Top-aligned, not centred: cards now carry a last-five plot of varying
     height, and centring made a card with no history render as a name
     floating in the middle of an empty box. */
  display: flex; align-items: flex-start; gap: 12px; padding: 11px 14px;
  background: rgba(10,18,38,0.55); border: 1px solid var(--line);
  border-radius: var(--r); transition: border-color var(--t-fast) var(--ease);
}
.pp-card:hover { border-color: var(--line-2); }
.pp-card img.face {
  width: 42px; height: 42px; border-radius: 50%; object-fit: cover;
  object-position: top; background: #14275C; border: 1px solid var(--line-3);
  flex-shrink: 0;
}
.slip-leg { display: flex; align-items: center; gap: 10px; padding: 7px 0;
            border-bottom: 1px dashed var(--line-2); font-size: 12px; }
.slip-x { background: none; border: none; color: var(--bad); cursor: pointer;
          font-size: 14px; padding: 0 4px; line-height: 1; font-family: inherit; }

/* --------------------------------------------------------- team page tabs */
.tabbar { display: flex; gap: 4px; overflow-x: auto; scrollbar-width: none;
          border-bottom: 1px solid var(--line-2); }
.tabbar::-webkit-scrollbar { display: none; }
.tabbtn {
  background: none; border: none; cursor: pointer; font-family: var(--f-cond);
  font-style: italic; font-weight: 800; font-size: 17px; letter-spacing: 0.06em;
  padding: 12px 16px; color: #7E8BAD; white-space: nowrap;
  border-bottom: 3px solid transparent;
  transition: color var(--t-fast) var(--ease), border-color var(--t) var(--ease);
}
.tabbtn:hover { color: #C6D2EE; }
.tabbtn.on { color: var(--ink-strong); border-bottom-color: var(--sap); }
.team-tab[hidden] { display: none !important; }

/* ------------------------------------------------------- walkthrough mode */
.gd-hi {
  position: relative !important; z-index: 1001 !important;
  box-shadow: 0 0 0 4px rgba(255,217,138,0.85), 0 0 34px rgba(255,217,138,0.35) !important;
  border-radius: var(--r);
}

/* ===========================================================================
   THE LIVE WIRE
   A seamless marquee with NO JavaScript: the track holds the item list twice
   and slides exactly -50%, so the loop point is invisible and there is no
   timer to drift, leak, or double up on a re-render. It stops for anyone who
   asks: hover, focus, reduced-motion, or the member's own Motion setting.
   =========================================================================== */
.wire {
  position: relative; display: flex; align-items: stretch; overflow: hidden;
  background: rgba(6, 10, 20, 0.95); border-bottom: 1px solid var(--line);
}
/* The edges fade instead of cutting, so items enter and leave the strip
   rather than popping at a hard boundary. */
.wire-marquee {
  flex: 1 1 auto; min-width: 0; overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 40px,
                      #000 calc(100% - 40px), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 40px,
              #000 calc(100% - 40px), transparent);
}
/* THE MARQUEE STARTS WHEN THE PAGE HAS SETTLED, AND ONLY WHILE IT IS ON SCREEN.
   It used to run from the first frame, forever. Two costs: Lighthouse never saw
   the page finish painting (Speed Index 19.8s on a page that was readable at
   1.4s), and on a phone the compositor kept working on a strip the reader had
   scrolled past. `.wire-live` is added by a small script once the page has
   loaded and settled, and removed when the wire leaves the viewport or the tab
   goes to the background. Nothing changes visually except that the ticker
   begins a beat after the page does — which reads as intentional. */
.wire-track { display: flex; width: max-content; align-items: stretch;
              animation: wire-slide var(--wire-time, 60s) linear infinite;
              animation-play-state: paused; }
.wire.wire-live .wire-track { animation-play-state: running; }
.wire .pulse { animation-play-state: paused; }
.wire.wire-live .pulse { animation-play-state: running; }
.wire:hover .wire-track, .wire:focus-within .wire-track { animation-play-state: paused; }
@keyframes wire-slide { from { transform: translate3d(0,0,0); }
                        to   { transform: translate3d(-50%,0,0); } }
.wire-item {
  flex-shrink: 0; display: flex; align-items: center; gap: 8px;
  padding: 9px 16px; border-right: 1px solid rgba(var(--line-rgb), 0.1);
  font-size: 12px; white-space: nowrap; color: #C6D2EE;
  transition: background var(--t-fast) linear, color var(--t-fast) linear;
}
.wire-item:hover { background: rgba(var(--sap-rgb), 0.1); color: var(--ink-strong); }
.wire-item b { color: var(--ink-strong); font-weight: 700; }
.wire-item img { width: 16px; height: 16px; object-fit: contain; }
.wire-tag {
  font-family: var(--f-cond); font-weight: 800; font-style: italic;
  font-size: 11px; letter-spacing: 0.1em; padding: 2px 7px; border-radius: 3px;
}
.wire-tag.final { color: var(--sap-soft); background: rgba(var(--line-rgb), 0.14); }
.wire-tag.next  { color: var(--gold); background: rgba(255,217,138,0.12); }
.wire-tag.move  { color: var(--good); background: rgba(107,219,143,0.12); }
.wire-tag.post  { color: var(--pink); background: rgba(255,142,200,0.12); }
.wire-tag.block { color: #FFB86B; background: rgba(255,184,107,0.14); }
/* The booth arguing. Its own colour because it is its own kind of thing —
   not a result, not a move, somebody's opinion about one. */
.wire-tag.take  { color: #C9A7FF; background: rgba(185,131,255,0.14); }
.wire-tag.leader { color: #C8A552; background: rgba(200,165,82,0.16); }
.wire-lead {
  flex: 0 0 auto; display: flex; align-items: center; gap: 7px;
  padding: 9px 14px; background: rgba(var(--sap-rgb), 0.16);
  border-right: 1px solid var(--line-2);
  font-family: var(--f-cond); font-weight: 800; font-style: italic;
  letter-spacing: 0.1em; font-size: 13px; color: var(--ink-strong); z-index: 2;
}
.wire-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--hot);
            box-shadow: 0 0 8px rgba(255,90,90,0.8); }
@keyframes wire-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }

/* ===========================================================================
   ONE PULSE, ONE MEANING, ONE OFF SWITCH
   ---------------------------------------------------------------------------
   Four separate elements used to declare `animation: wire-pulse ... infinite`
   for themselves. Four copies meant four places to remember the reduced-motion
   override and four chances to forget one — and one had been forgotten (the
   chat badge blinked forever even with motion turned off).
   Same choke-point rule as everywhere else in this codebase: one definition,
   one place to be right.

   The pulse now bottoms out at 0.35 instead of 0.25. A live marker that nearly
   disappears reads as a fault; one that dips and returns reads as a heartbeat.
   =========================================================================== */
.pulse { animation: wire-pulse 2s ease-in-out infinite; }
.pulse-slow { animation-duration: 2.6s; }

/* MOTION STOPS WHEN IT LEAVES THE SCREEN. Set by motion.js on anything that
   animates forever — the news ticker and the live markers. Paused rather than
   removed, so scrolling back finds it mid-beat instead of snapped to the
   start. */
.is-offscreen, .is-offscreen .wire-track { animation-play-state: paused !important; }

html[data-motion="off"] .pulse,
html[data-motion="off"] .wire-track { animation: none; }

/* ===========================================================================
   ENTRANCE MOTION
   One primitive, used everywhere: fade + a short rise, with a small stagger
   so a group of panels reads in order instead of arriving as a slab. It only
   ever runs once per element, it never moves layout, and anything that hasn't
   been revealed yet is still fully in the document for search and screen
   readers. If JS never runs, `.reveal` elements simply show — the visible
   state is the default and the hidden state is opt-in via .is-armed.
   =========================================================================== */
.reveal { opacity: 1; }
.reveal.is-armed { opacity: 0; transform: translate3d(0, 14px, 0); }
.reveal.is-in {
  opacity: 1; transform: none;
  /* --t-section is the token that was DEFINED for this and never used. Three
     of the four motion durations at the top of this file were dead: the scale
     was documented and the rules below it picked their own numbers, which is
     the same as not having a scale. */
  transition: opacity var(--t-section) var(--ease-out),
              transform var(--t-section) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}

html[data-motion="off"] .wire-track { animation: none !important; }
html[data-motion="off"] .wire-marquee { overflow-x: auto; }
html[data-motion="off"] .wire-dot { animation: none; }
html[data-motion="off"] .ssc-badge { animation: none !important; }
html[data-motion="off"] .reveal,
html[data-motion="off"] .reveal.is-armed { opacity: 1 !important; transform: none !important; }
html[data-motion="off"] .dd { animation: none; }

@media (prefers-reduced-motion: reduce) {
  .wire-track { animation: none !important; }
  .wire-marquee { overflow-x: auto; }
  .wire-dot { animation: none; }
  .reveal, .reveal.is-armed { opacity: 1 !important; transform: none !important; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* --------------------------------------------------------- compact density */
html[data-density="compact"] .tbl th,
html[data-density="compact"] .tbl td { padding-top: 5px; padding-bottom: 5px;
                                       font-size: 12.5px; }
html[data-density="compact"] .panel { padding: 14px 16px; }
html[data-density="compact"] .tile { padding: 10px 12px; }
html[data-density="compact"] .tile .v { font-size: 26px; }

/* ===========================================================================
   THE CHAT DOCK
   =========================================================================== */
#sschat { position: fixed; right: 18px; bottom: 18px; z-index: 900;
          display: flex; flex-direction: column; align-items: flex-end;
          gap: 10px; font-size: 13px; }
#sschat.floating { right: 18px; bottom: 18px; }
.ssc-bubble {
  display: flex; align-items: center; gap: 9px; cursor: pointer;
  background: linear-gradient(135deg, var(--sap), var(--sap-deep)); color: var(--on-sap);
  border: 0; border-radius: 999px; padding: 11px 18px; font-family: inherit;
  font-weight: 700; font-size: 13px; letter-spacing: 0.04em;
  box-shadow: 0 12px 30px -8px rgba(var(--deep-rgb), 0.8),
              0 0 0 1px rgba(var(--hi-rgb), 0.3) inset;
  transition: transform var(--t) var(--ease), filter var(--t-fast) var(--ease);
}
.ssc-bubble:hover { filter: brightness(1.1); transform: translateY(-2px); }
/* NO PULSE ON THIS ONE, DELIBERATELY.
   The unread badge sits in a fixed corner, which means it is on screen on
   every page for as long as the tab is open. A red badge carrying a number is
   already an unmissable signal; blinking it forever is the most nagging thing
   the interface could do, and it is the one piece of motion a reader cannot
   scroll away from. It arrives, it is red, it waits. */
.ssc-badge { background: var(--hot); color: #FFF; border-radius: 999px;
             min-width: 19px; padding: 1px 6px; font-size: 11px; font-weight: 800;
             text-align: center; box-shadow: 0 0 0 2px rgba(255,90,90,0.22); }
.ssc-panel {
  display: none; width: min(360px, calc(100vw - 28px)); height: min(460px, 62vh);
  flex-direction: column; background: var(--raised);
  border: 1px solid var(--line-3); border-radius: var(--r-lg);
  overflow: hidden; box-shadow: var(--lift-3);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
}
#sschat.open .ssc-panel { display: flex; animation: dd-in var(--t) var(--ease-out); }
#sschat.open .ssc-bubble { display: none; }
#sschat.floating .ssc-panel { resize: both; }
#sschat.floating .ssc-head { cursor: move; }
/* BUILD 598: THE STRIP NEVER GIVES WAY. .ssc-panel is a flex column and the
   log is the one part that should grow and shrink; the header, the room
   strip and the composer are `flex: none`, and the log has `min-height: 0`
   (a flex child's automatic minimum is its content, which is what let a busy
   Locker Room squash the room tabs to nothing). Holds at the floating
   panel's smallest dragged size too. */
.ssc-head { display: flex; align-items: center; gap: 9px; padding: 11px 14px; flex: none;
            background: rgba(20,36,80,0.7); border-bottom: 1px solid var(--line-2); }
.ssc-head b { font-family: var(--f-cond); font-size: 15px; letter-spacing: 0.14em;
              color: var(--ink-strong); font-weight: 700; }
.ssc-talking { font-size: 11px; color: var(--good); }
.ssc-close { margin-left: auto; color: var(--sap-soft); font-size: 20px; line-height: 1;
             background: none; border: 0; cursor: pointer; padding: 0 4px;
             font-family: inherit; }
.ssc-close:hover { color: var(--ink-strong); }
/* Build 312 — the room strip. Scrolls sideways rather than wrapping onto a
   second line, because the panel is short and a two-line tab strip eats the
   conversation it is there to organise. */
.ssc-rooms { display: flex; gap: 4px; padding: 7px 10px; overflow-x: auto; flex: none;
             background: rgba(14,26,58,0.6); border-bottom: 1px solid var(--line-3);
             scrollbar-width: none; }
.ssc-rooms::-webkit-scrollbar { display: none; }
.ssc-room { flex: none; background: none; border: 1px solid transparent;
            border-radius: 999px; padding: 4px 10px; font: inherit;
            font-size: 11.5px; color: var(--sap-soft); cursor: pointer;
            white-space: nowrap; position: relative; }
.ssc-room:hover { color: var(--ink-strong); }
.ssc-room.on { background: rgba(var(--lift-rgb), 0.2); border-color: rgba(var(--lift-rgb), 0.5);
               color: #FFF; font-weight: 700; }
.ssc-room .nu { display: inline-block; width: 6px; height: 6px; margin-left: 5px;
                border-radius: 50%; background: var(--good); vertical-align: middle; }
.ssc-log { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 12px 13px;
           display: flex; flex-direction: column; gap: 9px;
           overscroll-behavior: contain; }
.ssc-msg { background: rgba(14,24,50,0.7); border-radius: 9px; padding: 7px 10px;
           border-left: 2px solid var(--line-3); max-width: 100%; }
.ssc-msg.mine { border-left-color: var(--sap); background: rgba(24,44,96,0.6); }
.ssc-who { display: flex; align-items: baseline; gap: 7px; font-size: 10.5px; }
.ssc-who b { color: #C6D2EE; font-size: 11.5px; }
.ssc-who span { color: #6E7C9C; }
.ssc-del { margin-left: auto; color: var(--bad); font-size: 14px; line-height: 1;
           text-decoration: none; }
.ssc-body { font-size: 12.5px; color: var(--ink); margin-top: 3px; line-height: 1.5;
            word-wrap: break-word; overflow-wrap: anywhere; white-space: pre-wrap; }
.ssc-gif { max-width: 100%; max-height: 170px; border-radius: 7px; margin-top: 5px;
           display: block; }
.ssc-vid { max-width: 100%; max-height: 200px; border-radius: 7px; margin-top: 5px;
           display: block; background: var(--ground-2); }
/* A clip that plays in the room. 16:9, sized to the panel, so a chat window
   dragged narrow does not letterbox the video into a stripe. */
.ssc-embed { position: relative; padding-top: 56.25%; margin-top: 5px;
             border-radius: 7px; overflow: hidden; background: #060A16;
             max-width: 100%; }
.ssc-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%;
                    border: 0; }
.ssc-link { display: inline-block; margin-top: 4px; font-size: 11.5px;
            word-break: break-all; }
.ssc-foot { border-top: 1px solid var(--line-2); padding: 9px 11px; flex: none;
            background: rgba(10,17,35,0.8); }
/* BUILD 598: a player card in a message, drawn from his data now. */
.ssc-card { display: flex; gap: 10px; align-items: center; margin-top: 6px; padding: 8px 10px;
            border-radius: 9px; border: 1px solid var(--line-3); background: rgba(var(--sap-rgb), 0.08);
            color: var(--ink); text-decoration: none; max-width: 100%; }
.ssc-card:hover { border-color: var(--sap-lift); }
.ssc-card img { width: 40px; height: 40px; border-radius: 8px; object-fit: cover; flex: none; background: var(--ground-2); }
.ssc-card .cd-main { min-width: 0; flex: 1 1 auto; }
.ssc-card .cd-name { font-weight: 800; color: var(--ink-strong); font-size: 13px; white-space: nowrap;
                     overflow: hidden; text-overflow: ellipsis; }
.ssc-card .cd-sub { font-size: 11px; color: var(--ink-muted); }
.ssc-card .cd-rt { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 3px; }
.ssc-card .cd-rt span { font-size: 10.5px; color: var(--sap-pale); background: rgba(var(--line-rgb), 0.12);
                        border-radius: 5px; padding: 1px 5px; }
.ssc-card .cd-ovr { font-family: var(--f-cond); font-weight: 800; font-size: 22px; color: var(--ink-strong);
                    line-height: 1; text-align: center; flex: none; }
.ssc-card .cd-ovr small { display: block; font-size: 9px; letter-spacing: 0.14em; color: var(--ink-dim); }
.ssc-card.gone { color: var(--ink-dim); font-size: 12px; font-style: italic; background: none; }
.ssc-attach { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--sap-pale);
              margin-bottom: 6px; }
.ssc-attach button { background: none; border: 0; color: var(--ink-dim); cursor: pointer; font: inherit;
                     font-size: 14px; line-height: 1; padding: 0 3px; }
.ssc-pc button { display: flex; width: 100%; gap: 8px; align-items: baseline; text-align: left; }
.ssc-pc button small { color: var(--ink-dim); margin-left: auto; }
.ssc-row { display: flex; gap: 7px; }
.ssc-input { flex: 1 1 auto; background: rgba(10,18,38,0.9);
             border: 1px solid var(--line-3); color: var(--ink);
             border-radius: var(--r-sm); padding: 8px 11px; font-size: 12.5px;
             font-family: inherit; min-width: 0; }
.ssc-input:focus { outline: none; border-color: var(--sap);
                   box-shadow: 0 0 0 3px rgba(var(--sap-rgb), 0.18); }
.ssc-send { background: var(--sap); color: #FFF; border: 0; border-radius: var(--r-sm);
            padding: 8px 15px; font-weight: 700; font-size: 12.5px; cursor: pointer;
            font-family: inherit; transition: filter var(--t-fast) var(--ease); }
.ssc-send:hover { filter: brightness(1.12); }
.ssc-send:disabled { opacity: 0.5; cursor: default; }
.ssc-note { font-size: 11px; color: var(--sap-soft); min-height: 14px; margin-top: 5px; }
.ssc-hint { font-size: 10.5px; color: #6E7C9C; margin-top: 5px; }

/* --- @mentions ---------------------------------------------------------
   Somebody saying your name is not the same event as the room being busy, so
   it doesn't wear the same colour. The blue @ is any member; the red one is
   you, and it's the only thing in the dock that turns red. */
.ssc-at { color: var(--sap-soft); font-weight: 700; }
.ssc-at.me { color: #FFD9D9; background: rgba(255,90,90,0.18); font-weight: 800;
             border-radius: 4px; padding: 0 4px; }
.ssc-msg.at-me { border-left-color: var(--hot);
                 background: rgba(60,18,26,0.55);
                 box-shadow: inset 0 0 0 1px rgba(255,90,90,0.18); }
.ssc-badge.at { background: var(--hot); box-shadow: 0 0 0 3px rgba(255,90,90,0.22); }
#sschat.called .ssc-bubble {
  box-shadow: 0 12px 30px -8px rgba(120, 20, 40, 0.8),
              0 0 0 1px rgba(255,140,140,0.45) inset;
}
/* The autocomplete: a short list above the input, keyboard-first. */
.ssc-ac { display: flex; flex-direction: column; margin-bottom: 8px;
          border: 1px solid var(--line-3); border-radius: var(--r-sm);
          background: rgba(8,14,32,0.98); overflow: hidden; box-shadow: var(--lift-2); }
.ssc-ac button { background: none; border: 0; text-align: left; cursor: pointer;
                 font-family: inherit; font-size: 12.5px; color: #C6D2EE;
                 padding: 7px 11px; }
.ssc-ac button.on, .ssc-ac button:hover { background: rgba(var(--sap-rgb), 0.22);
                                          color: var(--ink-strong); }

@media (max-width: 620px) {
  #sschat { right: 12px; bottom: 68px; }
  .ssc-panel { height: min(420px, 58vh); }
}
@media print { #sschat, .wire { display: none; } }

/* ------------------------------------------------------ reputation pills */
.rep-pill { display: inline-block; font-size: 10.5px; font-weight: 700;
            padding: 2px 8px; border-radius: 999px; letter-spacing: 0.04em; }
.rep-pill.good { color: var(--good); background: rgba(107,219,143,0.14); }
.rep-pill.bad  { color: #FF9A9A; background: rgba(255,90,90,0.14); }
.rep-pill.neutral { color: var(--sap-soft); background: rgba(var(--line-rgb), 0.14); }
.rep-pill.expired { color: #6E7C9C; background: rgba(110,124,156,0.14);
                    text-decoration: line-through; }

/* ===========================================================================
   NEW PRIMITIVES — earned their place, each does a job nothing else did
   =========================================================================== */

/* A live marker. Used wherever something is genuinely happening now, so the
   pulse always means the same thing. */
.live-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%;
            background: var(--hot); box-shadow: 0 0 8px rgba(255,90,90,0.8); }
/* .live-dot carries `pulse` in the markup now — see ONE PULSE above. This
   selector stays as a belt-and-braces off switch for any older template that
   still declares its own. */
html[data-motion="off"] .live-dot { animation: none; }

/* Section rule with a label riding on it — replaces a bare heading floating
   above content, and shows where one block of the page ends and the next
   begins without wrapping everything in another card. */
.srule { display: flex; align-items: center; gap: 14px; margin: 26px 0 14px; }
.srule::after { content: ""; flex: 1 1 auto; height: 1px;
                /* sport-tinted on a league page (build 200); the generic blue
                   line-2 everywhere else, since --sport-line defaults to it */
                background: linear-gradient(90deg, var(--sport-line, var(--line-2)), transparent); }
.srule .t { font-family: var(--f-cond); font-weight: 800; font-style: italic;
            font-size: 19px; letter-spacing: 0.06em; color: var(--ink-strong);
            text-transform: uppercase; }
.srule .n { font-family: var(--f-cond); font-size: 12px; font-weight: 700;
            letter-spacing: 0.18em; color: var(--ink-dim); }

/* A big readout — the score, the balance, the level. Broadcast weight. */
.stat-v { font-family: var(--f-cond); font-weight: 800; font-style: italic;
          font-size: clamp(30px, 5vw, 46px); line-height: 0.94;
          color: var(--ink-strong); letter-spacing: -0.015em; }
.stat-l { font-size: 10.5px; font-weight: 700; letter-spacing: 0.18em;
          color: var(--ink-dim); text-transform: uppercase; }

/* Panel that carries a signal colour on its leading edge. */
.panel.sig-gold { border-left: 2px solid var(--gold); }
.panel.sig-good { border-left: 2px solid var(--good); }
.panel.sig-live { border-left: 2px solid var(--hot); }
.panel.sig-sap  { border-left: 2px solid var(--sap); }

/* Empty states should look intentional, not broken. */
.empty { padding: 26px 20px; text-align: center; color: var(--ink-muted);
         font-size: 13.5px; line-height: 1.6; }
.empty b { display: block; color: #C6D2EE; font-size: 15px; margin-bottom: 5px;
           font-weight: 700; }

/* ===========================================================================
   THE MASTHEAD MUST FIT THE SCREEN
   ---------------------------------------------------------------------------
   It did not. Measured on 8 September: a league page was 1703px wide at EVERY
   viewport — 423px of horizontal scroll on a 1280 laptop, 103px on a 1600
   monitor, 209px on a phone — and the marketing pages overflowed by 16px on a
   phone. One cause, and it was not a page: the masthead is a flex row of three
   groups (brand · nav · chips) and every one of them had been told never to
   shrink. So each chip added to that bar since — Find, Players, the three-way
   odds switcher, Tour — was paid for by the PAGE, in scroll, on every screen.
   Nobody had done anything wrong; the bar had simply outgrown the room and had
   no way to say so.

   WHAT YIELDS, AND IN WHICH ORDER. This is the part worth writing down,
   because "make it responsive" without an order is just hiding things until it
   fits. Nothing here is lost — every control that leaves the bar is somewhere
   else on the same screen:

     1. THE WORDS ON THE CHIPS go first. 🔎 Find, 👥 Players, 🧭 Tour and the
        odds switcher keep their icons and drop their labels. That is 180px for
        no function at all, and an icon with a title attribute is still a
        control somebody can find.
     2. FIND AND PLAYERS leave the bar. Find is the `/` key and the first item
        in ☰ MENU; Players is a tab in the nav and a link in the menu.
     3. THE TAB BAR TIGHTENS — less padding, less letter-spacing — before any
        tab is taken away, because a missing tab is a missing page.
     4. THE WHOLE DESKTOP NAV hands over to the phone bar, which SCROLLS and
        therefore cannot overflow anything. It carries every tab, plus Tour,
        plus the odds switcher.

   The brand, the account menu and the sign-in button never yield. They are how
   somebody knows where they are and how they get in.
   =========================================================================== */
.masthead { min-width: 0; }
/* flex-shrink: 0 was the bug. It is the line that turned "the header is a bit
   tight" into "every league page scrolls sideways". */
.mast-cta { min-width: 0; flex: 0 1 auto; }
.nav { min-width: 0; }

/* The chips' words, and the odds switcher's two dialects. Exactly one of .cw
   and .cn is ever on screen. */
.mast-cta .cn { display: none; }
.mn-odds { display: none; }

/* ===========================================================================
   HOW THE MASTHEAD GIVES WAY

   Marquis: "the window fits my 1440p monitor perfectly, but I notice on
   regular monitors that are 1080p ... the tabs up top being so jumbled that
   they can't even see the admin section. it gets jumbled up with following
   buttons (find, players, exchange, sportsbook, decimal)."

   Two separate faults, and the second is the one that actually hurt.

   THE BREAKPOINTS WERE SET FROM THE WRONG DESK. The first step down used to be
   1600px. A 1920-wide monitor is a ~1905px viewport, which is ABOVE that, so a
   1080p screen got the full-size bar with no compaction at all -- ten tabs,
   five chips and the account menu, laid out for a 2560px desk. Everything
   between 1600 and 2560 was a blind spot, and 1920 is the single most common
   monitor width there is.

   THE NAV OVERFLOWED INSTEAD OF YIELDING. Tabs are `white-space: nowrap` (a
   two-word tab must never fold and make the header taller) and `.nav` has
   `min-width: 0` with no overflow rule. So once the intrinsic width passed the
   container, the tabs did not shrink and did not clip -- they ran straight
   over `.mast-cta`. ADMIN is the LAST tab, so ADMIN is what lands under the
   chips. That is the jumble, and it is why the thing that disappears is
   always the one a commissioner needs.

   So the breakpoints below are raised, and a measuring guard
   (static/masthead.js) escalates past them when the guess is still wrong --
   a long league name, a browser zoomed to 125%, a wider font. Guessed pixel
   widths cannot cover every desk on the platform; measurement can, and the
   two are wired so the CSS handles the common case before the script has
   even run and the script only ever tightens further, never loosens.

   THE ORDER THINGS GO IS DELIBERATE. Chip words, then the chips themselves,
   then tab padding, and only then the whole bar hands over to the scrolling
   mobile nav. Navigation outlives decoration at every step, and the handover
   is a bar that physically cannot overflow however much goes in it.
   =========================================================================== */

/* LEVEL 1 — the chips say less. BUILD 431: the bar went from twelve tabs to
   four doors (PLAY / SCOUT / MY STUFF / LEAGUE, plus staff), so every step
   below moved down; the script still tightens further wherever the guess is
   short. The handover number and the MENU number above are one decision. */
@media (max-width: 1500px) {
  .mast-cta .cw { display: none; }
  .mast-cta .cn { display: inline; }
  .mast-cta { gap: 10px; }
}
html.mast-1 .mast-cta .cw { display: none; }
html.mast-1 .mast-cta .cn { display: inline; }
html.mast-1 .mast-cta { gap: 10px; }

/* LEVEL 2 — the optional chips leave. Find keeps its keyboard shortcut and
   lives in the mobile bar; Players is a tab away. Neither is navigation. */
@media (max-width: 1300px) {
  .mast-cta .mc-find, .mast-cta .mc-players, .mast-cta .mc-tour { display: none; }
  .masthead { gap: 16px; }
}
html.mast-2 .mast-cta .mc-find,
html.mast-2 .mast-cta .mc-players,
html.mast-2 .mast-cta .mc-tour { display: none; }
html.mast-2 .masthead { gap: 16px; }

/* LEVEL 3 — the tabs themselves tighten, which is the last thing that can be
   done without taking a tab away. */
@media (max-width: 1150px) {
  .navlink > a { padding-left: 8px; padding-right: 8px; letter-spacing: 0.05em; }
  .masthead { gap: 12px; }
  .wordmark { font-size: 17px; letter-spacing: 0.16em; }
}
html.mast-3 .navlink > a { padding-left: 8px; padding-right: 8px; letter-spacing: 0.05em; }
html.mast-3 .masthead { gap: 12px; }
html.mast-3 .wordmark { font-size: 17px; letter-spacing: 0.16em; }

/* LEVEL 4 — the handover. Below this the tab bar is the scrolling one, which
   is the only version of a nav that cannot push the page sideways however much
   goes in it. Nothing is lost here: the mobile bar carries every tab, ADMIN
   included, and the menu sheet carries every item under them. */
@media (max-width: 1000px) {
  .nav, .dd:not(.usermenu-dd) { display: none !important; }
  .mobile-nav { display: flex; top: 64px; justify-content: flex-start; }
  .mn-odds { display: inline-flex; }
  .mast-cta .odds-pick:not(.mn-odds), .mast-cta .mc-tour { display: none; }
  html { scroll-padding-top: 120px; }
  [id] { scroll-margin-top: 120px; }
}
html.mast-4 .nav, html.mast-4 .dd:not(.usermenu-dd) { display: none !important; }
html.mast-4 .mobile-nav { display: flex; top: 64px; justify-content: flex-start; }
html.mast-4 .mn-odds { display: inline-flex; }
html.mast-4 .mast-cta .odds-pick:not(.mn-odds),
html.mast-4 .mast-cta .mc-tour { display: none; }
html.mast-4 { scroll-padding-top: 120px; }
html.mast-4 [id] { scroll-margin-top: 120px; }

/* WHY THERE IS NO `overflow: hidden` BACKSTOP HERE, though it is the obvious
   thing to reach for. Both flex children of the masthead host
   absolutely-positioned dropdowns -- every tab menu inside `.nav`, the account
   menu inside `.mast-cta` -- and an ancestor with a clipping overflow clips
   those too, whatever the dropdown's own overflow says. Adding it would trade
   a jumbled bar for menus that open into a two-pixel slot, which is worse and
   much harder to notice in testing. The escalation above is the mechanism; it
   is allowed to be the only one.

   `overflow-x: clip` with `overflow-y: visible` is the one spelling that would
   not break the menus, and it is deliberately NOT used either: it is unsupported
   on older Safari, and a rule that silently does nothing on one browser is a
   backstop you believe in without having. The guard measures instead. */
/* The brand only yields when space is actually tight — on a wide screen the
   wordmark must never truncate, which it did when this was unconditional. */
.brand { flex-shrink: 0; }
@media (max-width: 900px) {
  .brand { min-width: 0; flex-shrink: 1; }
  .wordmark { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
}
@media (max-width: 640px) {
  .mast-cta .u-name { display: none; }
  .mast-cta { gap: 8px; }
  .brand { gap: 8px; }
}
@media (max-width: 420px) {
  .wordmark { font-size: 14px; letter-spacing: 0.1em; }
}

/* ---------------------------------------------------------------------------
   Form controls never widen the page. A <select> sizes itself to its LONGEST
   option by default, so one verbose choice ("Status — moves, trash talk…")
   was enough to push a phone layout sideways. Inputs with an inline min-width
   keep it (they wrap in their flex rows) but can no longer exceed the column.
   --------------------------------------------------------------------------- */
select, input, textarea, button { max-width: 100%; }
select { min-width: 0; text-overflow: ellipsis; }

/* ---------------------------------------------------------------------------
   First-visit tour nudge. On a wide screen it is a pill centred at the bottom.
   On a phone that pill had to share the bottom-right corner with the chat
   bubble AND squeeze a sentence next to a button — so the label wrapped one
   word per line and the two controls sat on top of each other. On small
   screens it moves to the top instead, where nothing else lives, and stacks.
   --------------------------------------------------------------------------- */
.gd-nudge {
  position: fixed; z-index: 999;
  /* Bottom-LEFT, not bottom-centre. Centred, it landed on top of whatever the
     page was actually showing — the ratings table header, a Book card, the
     contract ticker — on every screen. The chat bubble owns bottom-right, so
     this corner is the one spot that covers nothing. Still clears the sticky
     bet-slip bar on The Book. */
  bottom: 96px; left: 20px;
  width: min(380px, calc(100vw - 40px));
  display: flex; align-items: center; gap: 12px;
  background: var(--surface-solid); border: 1px solid rgba(var(--line-rgb), 0.45);
  border-radius: 999px; padding: 10px 10px 10px 20px;
  box-shadow: var(--lift-3); box-sizing: border-box;
}
.gd-nudge > span { flex: 1 1 auto; min-width: 0; font-size: 14px;
                   color: var(--ink); font-weight: 600; }
.gd-nudge-go { flex: 0 0 auto; white-space: nowrap; }
.gd-nudge-x  { flex: 0 0 auto; }

@media (max-width: 620px) {
  .gd-nudge {
    /* clears the masthead (64) + tab bar (44) + the wire strip (34) */
    top: 152px; bottom: auto; left: 10px;
    width: calc(100vw - 20px);
    border-radius: var(--r-lg);
    flex-wrap: wrap; padding: 14px 16px; gap: 10px;
  }
  .gd-nudge > span { flex: 1 1 100%; font-size: 14.5px; line-height: 1.4; }
  .gd-nudge-go { flex: 1 1 auto; justify-content: center; }
}

/* ==========================================================================
   BUILD 17 — the box score, the prop card, and colour that does a job
   ========================================================================== */

/* --- the two-hue SPLIT pair -----------------------------------------------
   A ticket split shows how many people are on each side. It is a PROPORTION,
   not a verdict — but it was painted --good / --bad, so every reader saw
   green and read "the smart side." Meaning colours are reserved (see the
   token block); this needed a categorical pair instead.

   Sapphire against bronze, validated on this surface rather than eyeballed:
   CVD separation ΔE 27.5 protan / 19.5 tritan against a target of 8, both
   inside the lightness band, both over 3:1 on the surface. Ticket counts stay
   printed under each end, so identity never rests on colour alone. */
:root {
  --split-a: var(--sap-lift);
  --split-b: #B08A3E;
}

.split {
  display: flex; gap: 2px; height: 5px; border-radius: 3px;
  overflow: hidden; background: rgba(var(--line-rgb), 0.10); margin-top: 6px;
}
.split > i { display: block; height: 100%; border-radius: 2px; }
.split > i.a { background: var(--split-a); }
.split > i.b { background: var(--split-b); }
.split-legend {
  display: flex; justify-content: space-between; gap: 8px;
  font-size: 9.5px; color: var(--ink-dim); margin-top: 3px;
}
.split-legend b { font-weight: 700; color: var(--ink-muted); }

/* --- rank tiles: the number already knew, the colour didn't say -----------
   #9 POINTS FOR and #19 POINTS ALLOWED rendered in the same grey. Rank in a
   32-team league is a DIVERGING scale around the middle, so it gets the
   diverging treatment: a warm pole, a cool pole, a neutral midfield. The rank
   text itself stays ink — the tint is on the tile edge and ground, so the
   number never has to be read through a colour. */
.tile.rk-elite { border-color: rgba(107,219,143,0.42);
                 background: linear-gradient(180deg, rgba(107,219,143,0.10), transparent 70%); }
.tile.rk-good  { border-color: rgba(107,219,143,0.24); }
.tile.rk-mid   { }
.tile.rk-poor  { border-color: rgba(255,142,142,0.24); }
.tile.rk-bad   { border-color: rgba(255,142,142,0.42);
                 background: linear-gradient(180deg, rgba(255,142,142,0.10), transparent 70%); }
.tile .rk-dot { display: inline-block; width: 5px; height: 5px; border-radius: 50%;
                margin-right: 5px; vertical-align: middle; background: var(--ink-dim); }
.tile.rk-elite .rk-dot, .tile.rk-good .rk-dot { background: var(--good); }
.tile.rk-poor  .rk-dot, .tile.rk-bad  .rk-dot { background: var(--bad); }

/* --- magnitude behind a ranked row ----------------------------------------
   Twelve net-worth figures from $38.7M to $9.0M, or 32 SRS ratings, are read
   as a SHAPE long before they are read as numbers. The bar is a recessive
   ground behind the row, never a mark competing with the digits, and it does
   not animate: this is data people are reading, and motion there hinders. */
.magrow { position: relative; }
.magrow > .mag {
  position: absolute; left: 0; top: 3px; bottom: 3px; z-index: 0;
  background: linear-gradient(90deg, rgba(var(--sap-rgb), 0.20), rgba(var(--sap-rgb), 0.05));
  border-radius: 0 3px 3px 0; pointer-events: none;
}
.magrow > .mag.neg {
  background: linear-gradient(90deg, rgba(255,142,142,0.05), rgba(255,142,142,0.18));
  border-radius: 3px 0 0 3px;
}
.magrow > * { position: relative; z-index: 1; }

/* --- the box score --------------------------------------------------------- */
.tbl.box { font-size: 12px; }
.tbl.box th { padding: 7px 8px; font-size: 9px; }
.tbl.box td { padding: 7px 8px; }
.tbl.boxteam td { padding: 7px 8px; font-size: 12.5px; }
.tbl.boxteam tr:hover td { background: none; }
.boxtabs { border-bottom: 1px solid var(--line); }
.boxtab {
  background: none; border: none; cursor: pointer; padding: 8px 12px;
  font-size: 10px; font-weight: 800; letter-spacing: 0.14em;
  color: #7E8BAD; white-space: nowrap; border-bottom: 2px solid transparent;
  transition: color var(--t-fast) var(--ease), border-color var(--t) var(--ease);
}
.boxtab:hover { color: #C6D2EE; }
.boxtab.on { color: var(--ink-strong); border-bottom-color: var(--sap); }
.boxsec[hidden] { display: none !important; }

/* --- did the line hit ------------------------------------------------------
   THIS is a verdict, so here the meaning colours are exactly right. */
.propline {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 7px 10px; border-radius: var(--r-sm);
  background: rgba(var(--line-rgb), 0.04); border: 1px solid var(--line);
}
.propline.settled { background: rgba(var(--line-rgb), 0.06); }
.verdict {
  font-size: 9.5px; font-weight: 800; letter-spacing: 0.08em;
  padding: 3px 7px; border-radius: 999px; white-space: nowrap;
}
.verdict.over  { color: #0A1A10; background: var(--good); }
.verdict.under { color: #1A0A0A; background: var(--bad); }
.verdict.push  { color: var(--ink-muted); background: rgba(var(--line-rgb), 0.14); }

/* --- the prop card, PrizePicks-style ---------------------------------------
   The last five games ARE the argument for the pick, so they go on the card
   instead of behind a disclosure. Bars are read against the posted line: at
   or above it fills sapphire, under it stays grey. A game that beat the line
   is also marked with a dot, so the read never depends on colour alone. */
.l5 {
  position: relative; display: flex; align-items: flex-end; gap: 3px;
  height: 38px; margin-top: 8px;
}
.l5 > span:not(.l5-line) {
  flex: 1 1 0; min-width: 0; position: relative; display: block;
  min-height: 2px;                 /* a zero game still shows it played */
  background: rgba(var(--line-rgb), 0.16); border-radius: 2px 2px 0 0;
}
.l5 > span.hit { background: var(--sap-lift); }
/* The posted line is drawn INSIDE the plot, anchored from the baseline the
   bars stand on. Placing it with margins outside the box looked right at one
   card height and drifted at every other. */
.l5-line {
  position: absolute; left: 0; right: 0; height: 0; z-index: 1;
  border-top: 1px dashed rgba(255,217,138,0.7); pointer-events: none;
}
.l5-line::after {
  content: "LINE"; position: absolute; right: 0; top: -9px;
  font-size: 7px; letter-spacing: 0.1em; font-weight: 700;
  color: rgba(255,217,138,0.75);
}
.l5-axis {
  display: flex; gap: 3px; margin-top: 3px;
  font-size: 8.5px; color: var(--ink-dim); letter-spacing: 0.02em;
}
.l5-axis > span { flex: 1 1 0; text-align: center; }
.l5-axis > span.hit { color: var(--sap-soft); font-weight: 700; }
.l5-head {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 9px; letter-spacing: 0.12em; font-weight: 700; color: var(--ink-dim);
}
.l5-hitrate { color: var(--ink-muted); letter-spacing: 0; font-size: 10px; }

/* --- press feedback ---------------------------------------------------------
   The one motion this build adds to high-frequency controls, and it is kept
   near-imperceptible on purpose: 0.985 over 110ms. Anything more on a control
   somebody hits fifty times a session reads as lag, not polish. */
@media (hover: hover) and (pointer: fine) {
  .btn:active, .odds-btn:active, .chip-btn:active, .boxtab:active,
  .tabbtn:active, button.press:active {
    transform: scale(0.985);
  }
}
/* AND ON A PHONE, WHICH IS WHERE THIS LEAGUE ACTUALLY LIVES.
   The rule above is gated to fine pointers, so until now a tap produced no
   feedback at all on the device most of these twenty-seven people use. A
   native app answers every touch; a web app that doesn't feels like a
   document. Slightly deeper than the mouse version because a fingertip covers
   the control it is pressing, and paired with a transparent tap highlight so
   the browser's own grey flash doesn't fight it. */
@media (hover: none) {
  .btn, .chip, .odds-btn, .chip-btn, .boxtab, .tabbtn, button.press,
  .mn-more, .mn-i, .ssc-bubble, .mobile-nav a {
    -webkit-tap-highlight-color: transparent;
  }
  .btn:active, .chip:active, .odds-btn:active, .chip-btn:active,
  .boxtab:active, .tabbtn:active, button.press:active,
  .mn-more:active, .ssc-bubble:active {
    transform: scale(0.97);
    transition-duration: 60ms;      /* down fast, settle back slow */
  }
  .mobile-nav a:active { opacity: 0.6; }
}
.btn, .odds-btn, .chip-btn, button.press {
  transition: transform 110ms var(--ease-out), background var(--t-fast) linear,
              border-color var(--t-fast) linear, color var(--t-fast) linear;
}

/* --- the score card is the game, so the card is the link ------------------
   The team names used to be the only links on a final, and they went to team
   pages — so the obvious click on a score took you somewhere that wasn't the
   game. The whole card is the recap link now; the crests still go to teams. */
.scorecard.linked { position: relative; transition: border-color var(--t) var(--ease),
                    transform var(--t) var(--ease-out), box-shadow var(--t) var(--ease); }
.scorecard.linked .cardlink::after {
  content: ""; position: absolute; inset: 0; z-index: 2; border-radius: inherit;
}
/* Every real link inside the card — team crests, highlight clips — rides
   ABOVE the card's overlay, so the overlay catches the empty space only. */
.scorecard.linked a:not(.cardlink) { position: relative; z-index: 3; }
@media (hover: hover) and (pointer: fine) {
  .scorecard.linked:hover { border-color: var(--line-3); transform: translateY(-1px);
                            box-shadow: var(--lift-2); }
  .scorecard.linked:hover .sc-go { color: var(--sap-soft); }
}
.sc-go { transition: color var(--t-fast) linear; }

@media (prefers-reduced-motion: reduce) {
  .scorecard.linked, .btn, .odds-btn, .chip-btn, button.press { transition: none; }
  .scorecard.linked:hover { transform: none; }
  .btn:active, .odds-btn:active, .chip-btn:active, .boxtab:active,
  .tabbtn:active, button.press:active, .chip:active, .mn-more:active,
  .ssc-bubble:active { transform: none; }
}
html[data-motion="off"] .scorecard.linked:hover { transform: none; box-shadow: var(--lift-1); }
html[data-motion="off"] .btn:active, html[data-motion="off"] .odds-btn:active,
html[data-motion="off"] button.press:active, html[data-motion="off"] .chip:active,
html[data-motion="off"] .mn-more:active,
html[data-motion="off"] .ssc-bubble:active { transform: none; }

/* --- a missing portrait should look like a player, not a hole --------------
   The harvester matches ~98% of a league, so a handful of men always render
   without a face — and hiding the image left a 26px gap in the name column
   that read as a broken row. A neutral bust keeps the column aligned and
   looks deliberate. The SVG is inline so it costs no request and cannot 404
   the way the portrait it stands in for just did. */
.pface-miss {
  visibility: visible !important;
  background-color: rgba(var(--line-rgb), 0.10);
  background-repeat: no-repeat;
  background-position: center 62%;
  background-size: 78%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23415890'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M12 14c-4.4 0-8 2.7-8 6v4h16v-4c0-3.3-3.6-6-8-6z'/%3E%3C/svg%3E");
}

/* --- the state of the league ----------------------------------------------
   Three cards under the crest. Sized so they read as a header strip rather
   than the page's first content block, and they collapse to one column on a
   phone instead of shrinking into unreadable slivers. */
.statestrip {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
}
.statecard {
  display: flex; align-items: center; gap: 12px; padding: 10px 16px;
  transition: border-color var(--t) var(--ease), transform var(--t) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .statecard:hover { border-color: var(--line-3); transform: translateY(-1px); }
}
@media (prefers-reduced-motion: reduce) {
  .statecard { transition: border-color var(--t) linear; }
  .statecard:hover { transform: none; }
}
html[data-motion="off"] .statecard:hover { transform: none; }

/* A prop with no history says so, and keeps the card's shape while it does. */
.l5-empty {
  margin-top: 10px; padding: 10px 0 12px;
  font-size: 10.5px; color: var(--ink-dim);
  border-top: 1px dashed var(--line);
}

/* ---------------------------------------------- THE BUILD IS OUT OF DATE ---
   Shown only when this tab's stamp no longer matches the server's. Bottom of
   the screen, above the phone's own bar, never over the nav — it is news, not
   an interruption. */
#build-stale {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 90; display: flex; align-items: center; gap: 10px;
  max-width: calc(100vw - 24px);
  padding: 9px 10px 9px 15px; border-radius: 12px;
  background: rgba(10, 18, 38, 0.94);
  border: 1px solid rgba(var(--line-rgb), 0.35);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(10px);
  color: #DCE6FF; font-size: 12.5px; font-weight: 600;
  animation: bs-in 260ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
#build-stale span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#build-stale .bs-go {
  flex: 0 0 auto; cursor: pointer; font: inherit; font-weight: 800;
  padding: 5px 12px; border-radius: 8px; border: 0; color: #061024;
  background: linear-gradient(135deg, var(--sap-bright, #7FA6FF), var(--sap-lift));
}
#build-stale .bs-x {
  flex: 0 0 auto; cursor: pointer; font: inherit; line-height: 1;
  padding: 5px 7px; border-radius: 8px; color: #8FA3CC;
  background: transparent; border: 1px solid rgba(var(--line-rgb), 0.22);
}
@keyframes bs-in { from { opacity: 0; transform: translate(-50%, 10px); }
                     to { opacity: 1; transform: translate(-50%, 0); } }
@media (prefers-reduced-motion: reduce) { #build-stale { animation: none; } }

/* ------------------------------------------- MESSAGES WAITING FOR YOU ------
   Rides the Messages link in every nav rendering. Hidden until there is a
   number, so an empty inbox costs no pixels. */
.dm-badge {
  display: inline-block; min-width: 17px; padding: 1px 5px; margin-left: 6px;
  border-radius: 9px; background: var(--sap-lift); color: #FFF;
  font-size: 10.5px; font-weight: 800; text-align: center; line-height: 1.45;
}


/* ------------------------------------------- TRADE ACTIONS ON A PHONE -----
   The approve/reject pair were 28px tall with 7px of padding, side by side in
   a wrapping row — fine for a mouse, mean for a thumb, and the two of them sat
   close enough together that "reject" was a plausible mis-tap on the one
   control in the app with no undo. On a narrow screen they go full width and
   get a real hit area. */
@media (max-width: 620px) {
  .tr-act, .tr-vote {
    flex: 1 1 100%;
    min-height: 44px;
    font-size: 13px !important;
    padding: 11px 16px !important;
  }
  .tr-act[data-action="void"] { flex: 0 0 auto; min-height: 34px; }
}

/* ---------------------------------------------------------- quick links --
   Seventeen destinations in one column, grouped rather than stacked. The
   heading is the thing you read; the links under it are the thing you scan.
   Deliberately quiet — this is a menu, not a feature. */
.ql-group { margin-top: 12px; }
.ql-group:first-of-type { margin-top: 6px; }
.ql-head {
  font-size: 9.5px; letter-spacing: 0.15em; font-weight: 800;
  color: var(--ink-dim); padding: 0 2px 5px;
  border-bottom: 1px solid var(--line);
}
.ql-link {
  display: flex; align-items: center; gap: 10px; min-width: 0;
  padding: 7px 6px; border-radius: 7px;
  font-size: 12.5px; font-weight: 600; color: #C6D2EE;
  text-decoration: none;
  transition: background var(--t) var(--ease), color var(--t) var(--ease),
              transform var(--t) var(--ease);
}
.ql-icon { flex: 0 0 auto; width: 18px; text-align: center; }
.ql-link:hover, .ql-link:focus-visible {
  background: rgba(var(--line-rgb), 0.10); color: var(--ink-strong);
  transform: translateX(2px);
}
@media (prefers-reduced-motion: reduce) { .ql-link:hover { transform: none; } }


/* ===========================================================================
   MOTION, PART TWO — the two primitives the system was missing.

   The token scale at the top of this file names four durations. Until now
   only --t-control was used; --t-press, --t-panel and --t-section were
   documented and dead. These rules spend them, and add nothing that is not
   doing one of the five jobs motion is allowed to do here: explain hierarchy,
   confirm an action, guide attention, keep continuity, signal craft.
   =========================================================================== */

/* --- 1. PRESS. The cheapest, most-missed feedback there is. ---------------
   Every button on this site currently changes colour on hover and does
   NOTHING under a finger. On a phone — where most of this league plays —
   hover does not exist, so the entire feedback vocabulary was invisible to
   them. One transform, 110ms, the token that was already named for it. */
.btn:active, .chip:active, button:not(:disabled):active,
a.tile:active, .ql-link:active {
  transform: scale(0.978);
  transition: transform var(--t-press) var(--ease);
}
.btn, .chip, a.tile, .ql-link { transition-property: background, border-color, color, transform, box-shadow; }

/* --- 2. CHOREOGRAPHY INSIDE A BLOCK --------------------------------------
   A panel arriving as one solid rectangle tells you a panel arrived. A panel
   whose heading lands first and whose rows follow tells you what to read and
   in what order — which is the entire point of hierarchy motion.

   Opt-in with data-anim on the children. Never applied by CSS alone: the
   armed state comes from motion.js, so a page whose JS never runs shows
   everything, exactly as before. */
.reveal.is-armed [data-anim] { opacity: 0; transform: translate3d(0, 8px, 0); }
.reveal.is-in [data-anim] {
  opacity: 1; transform: none;
  transition: opacity var(--t-panel) var(--ease-out),
              transform var(--t-panel) var(--ease-out);
  transition-delay: calc(var(--reveal-delay, 0ms) + var(--anim-i, 0) * 45ms + 90ms);
}

/* --- 3. NUMBERS THAT ARRIVE ----------------------------------------------
   This is a scoreboard. A number that counts up to its value is the one piece
   of motion on the site that is genuinely about the CONTENT rather than the
   container. It cannot reflow anything, because every digit stack here is
   already tabular. */
.roll { font-variant-numeric: tabular-nums; }

html[data-motion="off"] .reveal.is-armed [data-anim],
html[data-motion="off"] .reveal.is-in [data-anim] { opacity: 1 !important; transform: none !important; }

@media (prefers-reduced-motion: reduce) {
  .btn:active, .chip:active, button:active, a.tile:active, .ql-link:active { transform: none; }
  .reveal.is-armed [data-anim], .reveal.is-in [data-anim] { opacity: 1 !important; transform: none !important; }
}

/* The hero headline: three block lines, so each can be moved on its own.
   Identical to the two <br>s it replaced when nothing is animating. */
.hero-lines span { display: block; }

/* The landing page's entrance primitive. Same shape as .reveal, separate name
   because the hero is armed by landing-motion.js on load rather than by an
   observer on scroll — and because a class that means two things is a class
   somebody will eventually use for the wrong one.

   NEVER APPLIED BY CSS ALONE: .in-armed is only ever added by JS that has
   already decided it can remove it. */
.in { opacity: 1; }
.in.in-armed { opacity: 0; transform: translate3d(0, 16px, 0); }
.in:not(.in-armed) {
  opacity: 1; transform: none;
  transition: opacity var(--t-section) var(--ease-out),
              transform var(--t-section) var(--ease-out);
  transition-delay: var(--in-delay, 0ms);
}
html[data-motion="off"] .in,
html[data-motion="off"] .in.in-armed { opacity: 1 !important; transform: none !important; }
@media (prefers-reduced-motion: reduce) {
  .in, .in.in-armed { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* A broadcaster's portrait beside their byline. Small, square, and it never
   grows the row — the wire is a feed, not a gallery. */
.bc-face { display: inline-flex; flex: 0 0 auto; line-height: 0; }
.bc-face svg { width: 26px; height: 30px; border-radius: 6px;
               border: 1px solid var(--line-2); }

/* The booth's cards. The portrait is the thing you recognise, so it gets the
   size and the card gets out of its way. */
.bc-portrait { flex: 0 0 auto; line-height: 0; }
.bc-portrait svg { width: 58px; height: 68px; border-radius: 8px;
                   border: 1px solid var(--line-2); }

/* =========================================================================
   THE TEAM PLATE (build 133). One tactile object for both sports' Teams
   pages: a molded dark plaque with the franchise's two colours set in as an
   enamel band, a 1px reflective edge, stacked shadows for lift, and the
   abbreviation embossed into the surface. One material (soft-plastic on a
   dark housing), light from the top, shadow below. Hover lifts, press sinks.
   The premium is in the restraint: nothing glows, nothing bounces.
   ========================================================================= */
:root {
  --tp-top: #1C2130; --tp-mid: #151925; --tp-bottom: #0E1119;
  --tp-edge-top: rgba(255,255,255,.26); --tp-edge-bottom: rgba(5,8,18,.7);
  --tp-shadow: rgba(3,6,14,.55); --tp-highlight: rgba(255,255,255,.10);
}
.tp { position: relative; display: grid; grid-template-columns: 64px minmax(0,1fr) auto; gap: 12px; align-items: center;
  padding: 12px 14px 12px 12px; border-radius: 16px; border: 1px solid transparent; color: inherit; text-decoration: none;
  background: linear-gradient(180deg, var(--tp-top), var(--tp-mid) 52%, var(--tp-bottom)) padding-box,
              linear-gradient(180deg, var(--tp-edge-top), rgba(255,255,255,.06) 40%, var(--tp-edge-bottom)) border-box;
  box-shadow: 0 14px 28px var(--tp-shadow), 0 3px 8px rgba(3,6,14,.35), inset 0 1px 0 var(--tp-highlight), inset 0 -1px 0 rgba(0,0,0,.5);
  transition: transform var(--t-control) var(--ease-out), box-shadow var(--t-control) var(--ease-out); will-change: transform; }
.tp::before { /* the enamel band — the franchise's colours, set into the plate */
  content: ""; position: absolute; left: 12px; right: 12px; top: 0; height: 4px; border-radius: 0 0 4px 4px;
  background: linear-gradient(90deg, var(--a, #1F2A44), var(--b, #FF9B4A));
  box-shadow: inset 0 -1px 0 rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.28); }
.tp::after { /* the specular sheen across the top third */
  content: ""; position: absolute; inset: 1px 1px auto; height: 36%; border-radius: inherit; pointer-events: none;
  background: linear-gradient(180deg, rgba(255,255,255,.055), transparent); }
@media (hover: hover) and (pointer: fine) {
  .tp:hover { transform: translateY(-3px); box-shadow: 0 22px 36px var(--tp-shadow), 0 6px 12px rgba(3,6,14,.4), inset 0 1px 0 rgba(255,255,255,.14), inset 0 -1px 0 rgba(0,0,0,.5); }
}
.tp:active { transform: translateY(1px); transition-duration: var(--t-press);
  background: linear-gradient(180deg, var(--tp-bottom), var(--tp-mid) 50%, var(--tp-top)) padding-box,
              linear-gradient(180deg, rgba(5,8,18,.7), rgba(255,255,255,.18)) border-box;
  box-shadow: inset 0 4px 10px rgba(3,6,14,.6), inset 0 -1px 0 rgba(255,255,255,.08), 0 3px 8px rgba(3,6,14,.3); }
.tp:focus-visible { outline: 2px solid var(--sap-soft, var(--sap-soft)); outline-offset: 3px; }
.tp.mine { --tp-edge-top: rgba(255,170,90,.55); }
.tp-crest { width: 64px; height: 64px; display: grid; place-items: center; border-radius: 14px;
  background: radial-gradient(circle at 50% 30%, rgba(255,255,255,.08), rgba(0,0,0,.35));
  box-shadow: inset 0 2px 6px rgba(0,0,0,.55), inset 0 -1px 0 rgba(255,255,255,.06); }
.tp-crest img { width: 50px; height: 50px; object-fit: contain; filter: drop-shadow(0 3px 4px rgba(0,0,0,.6)); }
.tp-abbr { font-family: var(--f-cond); font-weight: 800; font-style: italic; font-size: 22px; letter-spacing: .02em; color: #D9E0F0;
  text-shadow: 0 1px 0 rgba(255,255,255,.14), 0 -1px 0 rgba(0,0,0,.6); }
.tp-name { font-family: var(--f-cond); font-weight: 800; font-style: italic; text-transform: uppercase; font-size: 17px; line-height: 1.05; color: #FFF;
  text-shadow: 0 1px 0 rgba(0,0,0,.6); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tp-sub { font-size: 12px; color: var(--ink-muted, #9AA6C0); margin-top: 3px; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.tp-sub .open { color: var(--ball-soft, #FFB070); font-weight: 700; }
.tp-rec { font-family: var(--f-cond); font-weight: 800; font-size: 20px; color: #E8EEFC; text-shadow: 0 1px 0 rgba(0,0,0,.6); padding: 4px 10px; border-radius: 10px;
  background: linear-gradient(180deg, rgba(0,0,0,.35), rgba(0,0,0,.15)); box-shadow: inset 0 2px 5px rgba(0,0,0,.55), inset 0 -1px 0 rgba(255,255,255,.05); }
.tp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; }

/* DIVISIONS AS COLUMNS (build 163). Marquis: "can we have the teams
   vertically stack per division?"

   The old grid flowed every team in a conference into one auto-fill run, so a
   four-team division wrapped three-and-one and the fourth team sat alone on a
   line under the wrong heading. A division is a standings table; it reads
   down, not across, and putting the four divisions side by side is the shape
   the competition actually has.

   The column is a real container with a rule down its left edge, so the four
   read as four things rather than as twelve teams with headings in them. */
.tp-divs { display: grid; gap: 16px; margin-top: 12px;
  grid-template-columns: repeat(auto-fit, minmax(min(272px, 100%), 1fr)); }
.tp-div { position: relative; padding-left: 14px;
  border-left: 1px solid rgba(var(--line-rgb), 0.16); }
.tp-div-hd { font-size: 10.5px; letter-spacing: 0.18em; text-transform: uppercase;
  font-weight: 800; color: #8FA3CC; padding-bottom: 9px; }
.tp-col { display: grid; gap: 8px; }
/* In a column the plate is a row: crest, name, record. Denser than the wide
   grid it came from, because four of them stack. */
.tp-col .tp { grid-template-columns: 52px minmax(0, 1fr) auto; gap: 10px;
  padding: 10px 12px 10px 10px; border-radius: 14px; }
.tp-col .tp-crest { width: 52px; height: 52px; border-radius: 12px;
  /* IMAGE FIRST: the crest sits in its own club colour rather than in a grey
     well, so the logo is anchored by the team's identity instead of floating
     on the plate. It is the only place on the page the club colour is allowed
     any area — everything else is a hairline. */
  background:
    radial-gradient(circle at 50% 25%, rgba(255,255,255,.14), rgba(0,0,0,.4)),
    linear-gradient(150deg, var(--a, #1F2A44), var(--b, #2A3348)); }
.tp-col .tp-crest img { width: 40px; height: 40px; }
.tp-col .tp-name { font-size: 15.5px; }
.tp-col .tp-rec { font-size: 17px; padding: 3px 8px; }
@media (max-width: 720px) { .tp-div { padding-left: 11px; } }
.tp-conf { font-family: var(--f-cond); font-weight: 800; font-style: italic; font-size: 24px; letter-spacing: .04em; margin: 22px 0 10px; }
@media (prefers-reduced-motion: reduce) { .tp, .tp:hover, .tp:active { transform: none; transition: none; } }
html[data-motion="off"] .tp, html[data-motion="off"] .tp:hover { transform: none; }

@keyframes mn-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .mn-panel { animation: none; } }
html[data-motion="off"] .mn-panel { animation: none; }
.gd-hi { transition: box-shadow 200ms var(--ease); }

/* ===========================================================================
   THE TASK PAGES (build 433) — every masthead tab opens a page of choices.
   ---------------------------------------------------------------------------
   The tiles, the section pages, the context strip, the new league home top
   and Money history. Ported from the owner-approved organization preview
   (D:\Sapphire UI\Organization-preview): molded navy plates with a real
   object on each, one title, one line. Gold only on money. Hover lifts a few
   pixels; nothing moves on its own; reduced motion turns the lift off.
   Everything is namespaced .mv- so the site's older .tile is untouched.
   =========================================================================== */
.mv-page { padding-top: 22px; padding-bottom: 56px; }
.mv-page .mv-ctx { margin-bottom: 20px; }

/* the context strip */
.mv-ctx { display: flex; align-items: center; gap: 16px; padding-bottom: 18px; border-bottom: 1px solid #28374f; }
.mv-ctx a { text-decoration: none; color: inherit; }
.mv-ctx-lg { display: flex; align-items: center; gap: 13px; min-width: 0; }
.mv-ctx-crest { width: 46px; height: 46px; object-fit: contain; flex: none; }
.mv-ctx b { display: block; font-family: var(--f-cond); font-weight: 800; font-size: 23px; line-height: 1.05; color: #FFF; text-transform: uppercase; letter-spacing: .01em; }
.mv-ctx span > span, .mv-ctx-team span, .mv-ctx-bal span { display: block; font-size: 11px; color: #92a6c6; margin-top: 3px; }
.mv-ctx-team { margin-left: auto; text-align: left; }
.mv-ctx-team b { font-size: 18px; }
.mv-ctx-bal { border-left: 1px solid #35435b; padding-left: 22px; margin-left: 4px; }
.mv-ctx-bal span { margin: 0 0 3px; }
.mv-ctx-bal b { color: #E6C989; font-size: 25px; }
.mv-ctx-lg:only-child { margin-right: auto; }
.mv-ctx .mv-ctx-lg + .mv-ctx-bal { margin-left: auto; }

.mv-back { display: inline-block; font-size: 12.5px; color: #b5c4dd; text-decoration: none; padding: 4px 0; }
.mv-back:hover { color: #FFF; }
.mv-head { margin: 18px 0 26px; }
.mv-kicker { font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase; color: #99abc9; font-weight: 700; }
.mv-title { font-family: var(--f-cond); font-weight: 800; font-size: clamp(34px, 5vw, 48px); line-height: 1.04; margin: 8px 0 8px; color: #FFF; text-transform: uppercase; letter-spacing: .005em; text-wrap: balance; }
.mv-blurb { font-size: 14.5px; line-height: 1.6; color: #aebdd6; margin: 0; max-width: 62ch; }

/* the tile */
.mv-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; }
.mv-tile { position: relative; display: block; height: 226px; padding: 24px; isolation: isolate; overflow: hidden;
  border-radius: 12px; border: 1px solid #3e5174; text-decoration: none; color: #edf2ff;
  background: linear-gradient(145deg, #243757, #101b30 50%, #0a1120);
  box-shadow: inset 0 2px 0 rgba(132,146,175,.27), inset 0 -5px 0 #030714, 0 10px 18px rgba(0,0,0,.33);
  transition: transform .18s var(--ease, ease), border-color .18s var(--ease, ease); }
.mv-tile::before { content: ''; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(125deg, transparent 20%, rgba(118,152,212,.07) 20.3%, transparent 21%, transparent 60%, rgba(161,191,255,.03) 60.2%, transparent 61%); }
.mv-tile:hover { transform: translateY(-4px); border-color: #b5c7eb; }
.mv-tile:focus-visible { outline: 3px solid #e7c478; outline-offset: 4px; }
.mv-tile.gold { background: linear-gradient(145deg, #3e3729, #1a2232 55%, #0a1120); border-color: #6d6044; }
.mv-tile.gold:hover { border-color: #e6c985; }
.mv-cap { position: absolute; left: 24px; right: 22px; bottom: 23px; display: block; }
.mv-h { display: block; font-family: var(--f-cond); font-weight: 800; font-size: 32px; line-height: 1; text-transform: uppercase; color: #FFF; margin-bottom: 7px; }
.mv-p { display: block; font-size: 13px; line-height: 1.5; color: #a5b4ce; max-width: 42ch; }
.mv-tag { position: absolute; top: 20px; right: 22px; font-size: 13px; color: #adc0df; }
.mv-tag.on { color: #dfc488; font-size: 12.5px; letter-spacing: .02em; }

/* the objects on the tiles */
.mv-obj { position: absolute; top: 20px; left: 29px; height: 100px; width: 110px; transform: rotate(-12deg) scale(.82); transform-origin: top left; filter: drop-shadow(9px 13px 7px rgba(0,0,0,.55)); }
.mv-plate { position: absolute; inset: 5px 16px; display: grid; place-items: center;
  background: linear-gradient(140deg, #91b8f6, #244d90 40%, #112f59); border: 2px solid #a8c4e9; border-radius: 12px;
  box-shadow: 5px 6px 0 #0a1835, 7px 8px 0 #375783; font-family: var(--f-cond); font-weight: 800; font-size: 50px; line-height: 1; color: #e8f2ff; }
.gold .mv-plate { background: linear-gradient(140deg, #ffe7a4, #a78948 50%, #4a3c22); border-color: #ffe6aa; color: #1b2436; box-shadow: 5px 6px 0 #3c321f, 7px 8px 0 #937e4e; }
.mv-ticket { border-radius: 4px; inset: 14px 5px; height: 65px; font-size: 34px; }
.mv-ticket::after { content: ''; position: absolute; border-left: 2px dashed #66532b; height: 80%; right: 19px; }
.mv-bars { display: flex; align-items: flex-end; gap: 8px; padding: 20px; transform: rotate(-8deg) scale(.82); }
.mv-bars i { width: 20px; background: linear-gradient(90deg, #587cae, #adccfa); box-shadow: 5px 5px 0 #142647; border: 1px solid #c8dfff; }
.mv-bars i:nth-child(1) { height: 30px; } .mv-bars i:nth-child(2) { height: 50px; } .mv-bars i:nth-child(3) { height: 76px; }
.mv-players .mv-plate { width: 57px; height: 76px; inset: auto; left: 3px; top: 16px; font-size: 27px; }
.mv-players .mv-plate + .mv-plate { left: 52px; top: 0; background: linear-gradient(140deg, #6d83b0, #202d4d); }

/* three tiles: the third runs the full width, object on the right */
.mv-grid.three .mv-tile:last-child { grid-column: 1 / -1; height: 170px; }
.mv-grid.three .mv-tile:last-child .mv-obj { left: auto; right: 36px; top: 30px; }
.mv-grid.three .mv-tile:last-child .mv-cap { right: 170px; bottom: 36px; }
.mv-grid.three .mv-tile:last-child .mv-tag { right: 22px; }

/* under the tiles */
.mv-foot { margin-top: 26px; padding-top: 20px; border-top: 1px solid #28374f; display: grid; gap: 14px; }
.mv-also { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: baseline; font-size: 12.5px; line-height: 1.6; }
.mv-also-k { font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase; color: #7f92af; font-weight: 700; margin-right: 4px; }
.mv-also a { color: #c3d1ea; text-decoration: none; border-bottom: 1px solid rgba(var(--soft-rgb), .25); }
.mv-also a:hover { color: #FFF; border-bottom-color: var(--sap-soft); }
.mv-also a.staff { color: #6BDB8F; }
.mv-also small { font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase; color: #6f8a78; }
.mv-note { font-size: 12px; color: #95a9c9; margin: 0; line-height: 1.6; }
.mv-search { width: min(360px, 100%); display: flex; gap: 10px; align-items: center; text-align: left; padding: 12px 14px;
  background: #0a1222; border: 1px solid #405775; color: #8fa0bd; border-radius: 7px; font: inherit; font-size: 13px; cursor: text; }
.mv-search:hover { border-color: #6b86b3; color: #c3d1ea; }

/* ---------------- the league home (build 433) ---------------- */
.mv-id { display: flex; align-items: center; gap: 18px; padding-top: 26px; flex-wrap: wrap; }
.mv-id-crest { width: 66px; height: 66px; object-fit: contain; flex: none; }
.mv-id h1 { font-family: var(--f-cond); font-weight: 800; font-size: clamp(34px, 5vw, 44px); line-height: 1; margin: 4px 0 5px; color: #FFF; text-transform: uppercase; }
.mv-id h1 span { color: #778ba9; font-size: .55em; margin-left: 4px; }
.mv-id p { margin: 0; font-size: 12.5px; color: #a5b4ce; display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center; }
.mv-id-r { margin-left: auto; display: flex; gap: 9px; flex-wrap: wrap; }
.mv-quiet { background: #111b2e; border: 1px solid #30405c; padding: 11px 15px; border-radius: 7px; font-size: 12px; color: #dfe7f6; text-decoration: none; }
.mv-quiet:hover { border-color: #5c75a0; color: #FFF; }
.mv-sechead { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin: 28px 0 13px; }
.mv-sechead h2 { font-family: var(--f-cond); font-weight: 800; font-size: 28px; margin: 0; color: #FFF; text-transform: uppercase; }
.mv-sechead span, .mv-sechead a { color: #98a9c4; font-size: 12px; text-decoration: none; }
.mv-four { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.mv-four .mv-tile { height: 230px; padding: 22px; }
.mv-four .mv-cap { left: 22px; right: 18px; }
.mv-four .mv-h { font-size: 29px; }
.mv-four .mv-p { font-size: 12px; }
.mv-four .mv-obj { transform: rotate(-12deg) scale(1); left: 26px; top: 20px; }
.mv-four .mv-bars { transform: rotate(-8deg); }
.mv-two { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 16px; }
.mv-row { display: flex; align-items: center; gap: 18px; padding: 17px 22px; border: 1px solid #354561; border-radius: 10px; text-decoration: none; color: #edf2ff;
  background: linear-gradient(110deg, #1d2d49, #101a2c); box-shadow: inset 0 1px rgba(255,255,255,.07), inset 0 -3px #030918; transition: border-color .18s; }
.mv-row:hover { border-color: #b5c7eb; }
.mv-row .sym { font-family: var(--f-cond); font-weight: 800; font-size: 34px; color: #d6bb7c; width: 38px; text-align: center; flex: none; }
.mv-row b { display: block; font-family: var(--f-cond); font-weight: 800; font-size: 24px; text-transform: uppercase; line-height: 1; }
.mv-row small { display: block; color: #a8b7cd; font-size: 12px; margin-top: 5px; }
.mv-row .end { margin-left: auto; color: #b1c0d9; }
.mv-status { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 28px; margin: 22px 0 6px; padding: 15px 4px; border-top: 1px solid #27344c; border-bottom: 1px solid #27344c; }
.mv-status a { font-size: 12.5px; color: #b3c0d6; text-decoration: none; }
.mv-status a strong { color: #ecd08c; margin-left: 7px; }
.mv-status a:hover { color: #FFF; }
.mv-status .tools { margin-left: auto; color: #d7e4fc; }
.mv-lower { display: grid; grid-template-columns: 1.65fr 1fr; gap: 30px; }
.mv-story { position: relative; display: block; padding: 25px; border: 1px solid #2d4162; border-radius: 10px; min-height: 184px; overflow: hidden; text-decoration: none; color: inherit;
  background: radial-gradient(ellipse at 90% 100%, #25477b, transparent 60%), linear-gradient(110deg, #162340, #0a1120); }
.mv-story:hover { border-color: #5c75a0; }
.mv-story .k { font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase; color: #ddc38d; font-weight: 700; }
.mv-story h3 { font-family: var(--f-cond); font-weight: 800; font-size: 34px; line-height: 1.04; margin: 12px 0; max-width: 420px; text-transform: uppercase; color: #FFF; }
.mv-story p { font-size: 12.5px; max-width: 360px; color: #a5b4ce; margin: 0 0 12px; line-height: 1.55; }
.mv-story .go { color: #e5c684; font-size: 12.5px; }
.mv-story .opp { position: absolute; right: 26px; top: 50%; transform: translateY(-50%); width: 120px; height: 120px; object-fit: contain; opacity: .16; }
.mv-scores { margin-top: 12px; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px 14px; color: #acb9ce; font-size: 11.5px; }
.mv-scores b { color: #FFF; }
.mv-scores a { color: #acb9ce; text-decoration: none; }
.mv-money { border-top: 1px solid #29374e; }
.mv-money a, .mv-money div { display: flex; justify-content: space-between; gap: 12px; padding: 15px 0; border-bottom: 1px solid #202c40; color: #cfdaeb; font-size: 12.5px; text-decoration: none; }
.mv-money small { display: block; color: #8fa0bd; font-size: 10.5px; margin-top: 6px; }
.mv-money .in { color: #a5d6b9; } .mv-money .out { color: #e2b0b0; }
.mv-around { margin-top: 36px; }

/* ---------------- money history ---------------- */
.mv-wal { display: flex; flex-wrap: wrap; gap: 14px 40px; align-items: flex-end; padding: 18px 0; border-top: 1px solid #28374f; border-bottom: 1px solid #28374f; }
.mv-wal span { display: block; font-size: 11px; color: #92a6c6; letter-spacing: .04em; }
.mv-wal b { display: block; font-family: var(--f-cond); font-weight: 800; font-size: 26px; color: #FFF; margin-top: 4px; }
.mv-wal-bal b { font-size: 38px; color: #E6C989; }
.mv-wal small { display: block; font-size: 11.5px; color: #8fa0bd; margin-top: 3px; }
.mv-wal .in { color: #a5d6b9; } .mv-wal .out { color: #e2b0b0; }
.mv-filters { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 16px; align-items: center; }
.mv-filters-gap { flex: 0 0 14px; }
.mv-line { display: flex; justify-content: space-between; gap: 14px; padding: 13px 0; border-bottom: 1px solid #202c40; }
.mv-line:last-child { border-bottom: 0; }
.mv-line b { font-size: 13.5px; color: #e3eaf7; }
.mv-line small { display: block; font-size: 11px; color: #8fa0bd; margin-top: 4px; }
.mv-line-r { text-align: right; flex: none; }
.mv-amt { font-family: var(--f-cond); font-weight: 800; font-size: 18px; color: #c3d1ea; }
.mv-amt.in { color: #a5d6b9; } .mv-amt.out { color: #e2b0b0; }

@media (max-width: 1000px) {
  .mv-four { grid-template-columns: 1fr 1fr; }
  .mv-lower { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .mv-ctx { gap: 10px; }
  .mv-ctx-team { display: none; }
  .mv-ctx-bal { margin-left: auto; padding-left: 14px; }
  .mv-ctx b { font-size: 19px; }
  .mv-grid, .mv-four { gap: 12px; }
  .mv-tile, .mv-four .mv-tile { height: 212px; padding: 16px; }
  .mv-cap, .mv-four .mv-cap { left: 15px; right: 12px; bottom: 17px; }
  .mv-h, .mv-four .mv-h { font-size: 23px; }
  .mv-p, .mv-four .mv-p { font-size: 11.5px; }
  .mv-obj, .mv-four .mv-obj { left: 15px; top: 16px; transform: rotate(-12deg) scale(.68); }
  .mv-bars, .mv-four .mv-bars { transform: rotate(-8deg) scale(.68); }
  .mv-tag { top: 13px; right: 13px; font-size: 11px; }
  .mv-grid.three .mv-tile:last-child { height: 156px; }
  .mv-grid.three .mv-tile:last-child .mv-cap { right: 96px; bottom: 24px; }
  .mv-grid.three .mv-tile:last-child .mv-obj { right: 4px; top: 26px; }
  .mv-two { grid-template-columns: 1fr; gap: 10px; }
  .mv-row { padding: 14px 16px; }
  .mv-id-r { display: none; }
  .mv-sechead { flex-wrap: wrap; }
  .mv-sechead > span { display: none; }
  .mv-id-crest { width: 50px; height: 50px; }
  .mv-status { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .mv-status .tools { margin: 0; }
}
@media (max-width: 360px) {
  .mv-grid { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .mv-tile { transition: none; } .mv-tile:hover { transform: none; }
}
html[data-motion="off"] .mv-tile:hover { transform: none; }

/* the progression chart (player page): fits its box at every width */
.pc { position: relative; height: var(--h); margin: 16px 2px 30px; }
.pc svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.pc-dot { position: absolute; width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; border-radius: 50%; background: var(--sap); border: 2px solid #05080F; box-sizing: content-box; }
.pc-num { position: absolute; z-index: 2; transform: translateX(-50%); font-size: 11px; font-weight: 700; color: #E8EEFC; line-height: 1; font-variant-numeric: tabular-nums; text-shadow: 0 0 3px #05080F, 0 0 3px #05080F; }
.pc.dense .pc-dot { width: 6px; height: 6px; margin: -3px 0 0 -3px; border-width: 1.5px; }
.pc-wk { position: absolute; top: calc(var(--h) + 8px); transform: translateX(-50%); font-size: 10px; color: #7f8faf; white-space: nowrap; }
.pc-num.first, .pc-wk.first { transform: translateX(-30%); }
.pc-num.last, .pc-wk.last { transform: translateX(-70%); }
.pc-wk.first { transform: none; } .pc-wk.last { transform: translateX(-100%); }
.pc-list { margin-top: 4px; font-size: 12px; }
.pc-list summary { cursor: pointer; color: var(--sap-soft); }
.pc-rows { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 8px; color: #a5b4ce; }
.pc-rows b { color: #FFF; }
@media (max-width: 640px) {
  .pc-num:not(.key), .pc-wk:not(.key) { display: none; }
}

.mv-court { margin: 4px 0 18px; }
.mv-court .mv-sechead { margin-top: 22px; }

/* the five tabs on the bar: words, not shouting */
body[data-tabs] .nav { gap: 2px; }
body[data-tabs] .nav .navlink > a { text-transform: none; font-family: var(--f-body); font-weight: 600; font-size: 13.5px; letter-spacing: 0; color: #aab8cf; }
body[data-tabs] .nav .navlink > a:hover { color: #FFF; }
body[data-tabs] .nav .navlink.active > a { color: #ecd093; }
body[data-tabs] .nav .navlink.active > a::after { background: #d6b66d; }
.mobile-nav a[aria-current="page"] { color: #ecd093; }

/* ===========================================================================
   THE CUT (build 430) — the whole site in the app's material.
   ---------------------------------------------------------------------------
   Build 413 gave the app a material: two navies a few steps apart so a plate
   reads as lit from above, a gradient rim, an inset lip, a long shadow, keys
   that travel when pressed. The site had a gradient edge on its panels and
   little else, and the two did not feel like one product. This layer re-cuts
   the site's shared surfaces — panel, tile, button, chip, input, table head,
   masthead — through the same tokens, so every page inherits it without a
   template changing. Contrast goes UP, not down: brighter ink, brighter
   support copy, darker floors. Gold stays money. Nothing glows.

   It sits before the machined skin on purpose: the instrument pages keep
   their own, deeper treatment and override whatever they need to.
   =========================================================================== */
:root {
  --plate-top: #111C38;
  --plate-bot: #0A1124;
  --key-top:   #18264A;
  --key-bot:   #0E1731;
  --rim:       rgba(var(--soft-rgb), 0.34);
  --rim-low:   rgba(var(--soft-rgb), 0.05);
  --lip:       rgba(255,255,255,0.07);
  --floor:     rgba(0,0,0,0.55);
  --ink-muted: #A3B0CE;
  --ink-dim:   #6F7E9F;
  --surface:        rgba(12, 21, 44, 0.86);
  --surface-hi:     rgba(17, 28, 56, 0.92);
  --line:   rgba(var(--soft-rgb), 0.12);
  --line-2: rgba(var(--soft-rgb), 0.20);
  --line-3: rgba(var(--soft-rgb), 0.34);
}
body {
  background-image:
    radial-gradient(120% 80% at 8% -8%, rgba(var(--glow-rgb), var(--glow-a)) 0%, rgba(var(--glow-rgb), 0) 58%),
    radial-gradient(90% 60% at 100% 0%, rgba(var(--sap-rgb), 0.10) 0%, rgba(var(--sap-rgb), 0) 55%),
    linear-gradient(180deg, var(--ground-top) 0%, var(--ground) 100%);
}
/* the plate: a molded fill inside a gradient rim, lit along the top */
.panel {
  background:
    linear-gradient(180deg, var(--plate-top) 0%, var(--plate-bot) 100%) padding-box,
    linear-gradient(180deg, var(--rim) 0%, var(--rim-low) 70%) border-box;
  border: 1px solid transparent;
  box-shadow: inset 0 1px 0 0 var(--lip), 0 18px 32px -20px rgba(0,0,0,0.75), 0 1px 2px rgba(0,0,0,0.4);
}
.tile {
  background: linear-gradient(180deg, var(--key-top) 0%, var(--key-bot) 100%);
  border: 1px solid var(--line-2);
  box-shadow: inset 0 1px 0 0 var(--lip), 0 10px 20px -14px rgba(0,0,0,0.7);
}
/* keys: a layered face with a bevel, and travel when pressed */
.btn {
  background: linear-gradient(180deg, var(--key-face-top) 0%, var(--key-face-bot) 100%);
  box-shadow: inset 0 1px 0 0 rgba(255,255,255,0.35), inset 0 -1px 0 0 rgba(0,0,0,0.25),
              0 8px 18px -10px rgba(0,0,0,0.9), 0 0 0 1px rgba(var(--key-ring-rgb),0.6);
  letter-spacing: 0.01em;
}
.btn:hover { filter: brightness(1.06);
             box-shadow: inset 0 1px 0 0 rgba(255,255,255,0.4), inset 0 -1px 0 0 rgba(0,0,0,0.25),
                         0 12px 24px -10px rgba(0,0,0,0.9), 0 0 0 1px rgba(var(--key-ring-rgb),0.7); }
.btn:active { transform: translateY(1.5px) scale(0.985);
              box-shadow: inset 0 1px 0 0 rgba(255,255,255,0.2), inset 0 2px 6px rgba(0,0,0,0.35), 0 0 0 1px rgba(var(--key-ring-rgb),0.6); }
.btn.ghost {
  background: linear-gradient(180deg, var(--key-top) 0%, var(--key-bot) 100%);
  border: 1px solid var(--line-3);
  box-shadow: inset 0 1px 0 0 var(--lip), 0 6px 14px -10px rgba(0,0,0,0.8);
  color: var(--ink) !important;
}
.btn.ghost:hover { background: linear-gradient(180deg, var(--key-top-hi) 0%, var(--key-bot-hi) 100%); border-color: var(--sap-lift); filter: none; }
/* chips: touchable, and pressed IN when on */
.chip {
  background: linear-gradient(180deg, var(--key-top) 0%, var(--key-bot) 100%);
  border: 1px solid var(--line-2);
  box-shadow: inset 0 1px 0 0 var(--lip);
  color: var(--ink-soft);
}
.chip.on, .chip[aria-pressed="true"] { background: linear-gradient(180deg, rgba(var(--sap-rgb),0.42) 0%, rgba(var(--sap-rgb),0.26) 100%);
           box-shadow: inset 0 2px 4px rgba(0,0,0,0.45), 0 0 0 1px rgba(var(--lift-rgb), 0.35); }
/* inputs: a recess, not a box */
.inp, input[type="text"], input[type="number"], input[type="search"], input[type="email"],
input[type="password"], input[type="date"], input[type="datetime-local"], select, textarea {
  background: linear-gradient(180deg, #060B18 0%, #0A1226 100%);
  border: 1px solid var(--line-2);
  border-radius: 9px;
  color: var(--ink);
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.5), inset 0 -1px 0 rgba(255,255,255,0.04);
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.inp:focus, input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--sap-lift);
  box-shadow: inset 0 2px 4px rgba(0,0,0,0.5), 0 0 0 3px rgba(var(--sap-rgb), 0.22);
}
/* quiet framing on tables */
.tbl th { color: var(--ink-muted); border-bottom: 1px solid var(--line-3); }
.tbl td { color: #D3DCF0; border-bottom: 1px solid rgba(var(--soft-rgb), 0.08); }
/* the shell: the masthead as the machined top edge of the page */
.masthead {
  background: linear-gradient(180deg, rgba(14,23,48,0.94) 0%, rgba(7,11,22,0.92) 100%);
  border-bottom: 1px solid var(--line-2);
  box-shadow: inset 0 -1px 0 0 rgba(255,255,255,0.04), 0 10px 30px -18px rgba(0,0,0,0.9);
}
.kicker { color: var(--sap-soft); }
.dim { color: var(--ink-dim); }
.muted { color: var(--ink-muted); }
@media (prefers-reduced-motion: reduce) { .btn:active { transform: none; } }

/* ===========================================================================
   THE MACHINED SKIN — the instrument pages as a device.
   app/machined.py holds the route list and the rule; this holds the material.

   VERSION THREE, and the first two earned their notes.

   v1 was a colour swap: "just look like you changed the shades." It also
   replaced .panel's background wholesale and killed the reflective border the
   base theme already had, so the skin was FLATTER than what it replaced.

   v2 gave the panel real depth and stopped there — which is bevelled panels on
   a flat page, not a page with depth.

   v3 is the mockup he approved, and it rests on two corrections:

   1. THE METAL IS SAPPHIRE STEEL, NOT GREY. Reading "instrument" as neutral
      graphite took the brand out of the material. Every neutral below is mixed
      toward var(--sap): blue-black steel, highlights carrying blue, shadows that
      are blue-black rather than grey-black. The brand IS the material.

   2. DEPTH IS A HIERARCHY OF PLANES, EACH A DIFFERENT MATERIAL:

        the room     out of focus, vignetted, atmosphere only — no edges
        the chassis  milled steel, sits in the room and casts onto it
        the glass    sunk into the chassis, lit from within, UNTOUCHABLE
        the deck     controls, proud of the chassis, the only pressable thing

      Marquis: "something that is to be only viewed should feel encased in
      glass or a screen of its own... the background should be just that, a
      background, an afterthought."

      You cannot press the glass and you cannot read the deck. On a phone that
      makes a mis-tap impossible rather than merely unlikely.

   AND IT NEEDED NO TEMPLATE CHANGES. I quoted two or three days for wrappers;
   the structure was already there under different names. .panel is the
   chassis, a <table> is the glass slab, and :has(> .chip) finds a control row
   and makes it a deck. Browsers without :has() lose the deck plate and keep
   the keys, which is a degradation nobody would notice.

   THREE DEPTHS, MAXIMUM, and table ROWS stay flat — a shadow on four hundred
   rows is the whole performance budget of a leaders page. No backdrop-filter
   anywhere: that is what makes tactile UI stutter on a mid-range phone.
   =========================================================================== */
body[data-skin="machined"] {
  /* THE ROOM */
  --ground:        #02040A;
  --ground-2:      #050A16;

  /* THE CHASSIS — blue-black steel */
  --steel-hi:      #202C46;
  --steel:         #131C2E;
  --steel-lo:      #080D18;
  --steel-edge:    rgba(140, 175, 255, 0.30);
  --steel-floor:   rgba(0, 3, 10, 0.85);

  --surface:       #131C2E;
  --surface-solid: #131C2E;
  --surface-hi:    rgba(32, 44, 70, 0.9);
  --surface-deep:  rgba(5, 10, 21, 0.92);
  --raised:        rgba(19, 28, 46, 0.98);
  --wash:          rgba(32, 44, 70, 0.55);
  --ground-0:      rgba(2, 4, 10, 0);

  /* ink keeps a faint blue, because the metal it sits on is blue */
  --ink:        #E8EEFC;
  --ink-soft:   #C6D2EE;
  --ink-muted:  #93A0BE;
  --ink-dim:    #5E6C8E;

  /* edges are bevels now, but blue-tinted bevels */
  --line:       rgba(140, 175, 255, 0.10);
  --line-2:     rgba(140, 175, 255, 0.15);
  --line-3:     rgba(140, 175, 255, 0.22);
  --guide:      rgba(140, 175, 255, 0.07);
  --guide-mark: rgba(140, 175, 255, 0.3);

  /* THE ROOM IS LIT AND HAS NO EDGES. Two soft blooms and a vignette, nothing
     to look at — which is what makes the chassis read as an object IN it
     rather than a rectangle ON it. */
  background-color: var(--ground);
  background-image:
    radial-gradient(1100px 700px at 22% -6%, rgba(var(--sap-rgb), 0.13), transparent 62%),
    radial-gradient(900px 600px at 88% 104%, rgba(var(--sap-rgb), 0.09), transparent 60%),
    radial-gradient(1400px 900px at 50% 45%, var(--ground-2), var(--ground) 74%);
  background-attachment: fixed;
}

/* ============================================================ THE CHASSIS == */
body[data-skin="machined"] .panel {
  position: relative;
  border: 1px solid transparent;
  border-radius: 24px;
  background:
    linear-gradient(180deg, var(--steel-hi) 0%, var(--steel) 20%,
                    var(--steel-lo) 100%) padding-box,
    linear-gradient(180deg, var(--steel-edge), rgba(140,175,255,0.05) 38%,
                    var(--steel-floor)) border-box;
  /* two shadows, because one object at one distance is all a single shadow
     describes, and this is sitting ON something */
  box-shadow:
    0 46px 74px -34px rgba(0, 2, 8, 0.92),
    0 14px 26px -10px rgba(0, 2, 8, 0.62),
    inset 0 2px 0 rgba(255, 255, 255, 0.055),
    inset 0 -2px 0 rgba(0, 0, 0, 0.7);
}
/* the fixings and the brushed grain, in one layer: four corner bolts as
   radial gradients, plus fine vertical striations meant to be felt */
body[data-skin="machined"] .panel::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none;
  background:
    radial-gradient(circle 3.5px at 13px 13px, #4A5B7C, #0B1120 78%, transparent 80%),
    radial-gradient(circle 3.5px at calc(100% - 13px) 13px, #4A5B7C, #0B1120 78%, transparent 80%),
    radial-gradient(circle 3.5px at 13px calc(100% - 13px), #4A5B7C, #0B1120 78%, transparent 80%),
    radial-gradient(circle 3.5px at calc(100% - 13px) calc(100% - 13px), #4A5B7C, #0B1120 78%, transparent 80%),
    repeating-linear-gradient(90deg, rgba(255,255,255,0.012) 0 1px, transparent 1px 3px);
}
/* the specular down the top of the metal */
body[data-skin="machined"] .panel::after {
  content: ""; position: absolute; inset: 1px; border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(255,255,255,0.05) 0%,
                              rgba(255,255,255,0.01) 24%, transparent 44%);
}
body[data-skin="machined"] .panel > * { position: relative; z-index: 1; }

/* =============================================================== THE GLASS == */
/* A <table> on an instrument page is a readout, so it becomes the display:
   sunk in, lit from behind, sealed under a sweep that runs at an angle nothing
   else uses — because a reflection does not share a light source with the
   material it lies on. Nothing in here is pressable and none of it looks it. */
body[data-skin="machined"] .panel table {
  border-collapse: separate;
  border-spacing: 0;
  border-radius: 14px;
  overflow: hidden;
  width: 100%;
  background-color: #050A15;
  background-image:
    linear-gradient(104deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.012) 15%,
                    transparent 32%, transparent 68%, rgba(255,255,255,0.02) 88%,
                    transparent 100%),
    repeating-linear-gradient(0deg, rgba(120,160,255,0.022) 0 1px, transparent 1px 3px),
    radial-gradient(120% 80% at 50% 0%, rgba(var(--sap-rgb), 0.10), transparent 66%),
    linear-gradient(180deg, #071022, #050A15 70%);
  box-shadow:
    inset 0 3px 14px rgba(0, 0, 0, 0.95),
    inset 0 1px 0 rgba(120, 160, 255, 0.2),
    inset 0 -1px 0 rgba(120, 160, 255, 0.08),
    0 1px 0 rgba(255, 255, 255, 0.05);
}
body[data-skin="machined"] .panel table th { padding-top: 14px; }
body[data-skin="machined"] .panel table th:first-child,
body[data-skin="machined"] .panel table td:first-child { padding-left: 16px; }
body[data-skin="machined"] .panel table th:last-child,
body[data-skin="machined"] .panel table td:last-child { padding-right: 16px; }

/* phosphor, not ink: a lit figure on a lit display */
body[data-skin="machined"] .panel table td { color: var(--ink-soft); }

/* ================================================================ THE DECK == */
/* Any row holding chips is a control deck: proud of the chassis, plated, and
   the only thing on the page that looks pressable. */
/* THE DECK WAS NEVER RENDERING. It required .panel ancestry, and every real
   control row on these pages sits OUTSIDE the panel, above it. Scoped to
   <main> instead so the masthead's own chips are untouched, and to a chip
   FOLLOWED BY a chip so an incidental single chip somewhere does not get
   plated as though it were a control bank. */
body[data-skin="machined"] main :has(> .chip + .chip) {
  padding: 12px 14px;
  border-radius: 15px;
  background: linear-gradient(180deg, #1A2438, #0C1220);
  box-shadow:
    inset 0 1px 0 rgba(160, 190, 255, 0.16),
    inset 0 -2px 0 rgba(0, 0, 0, 0.75),
    0 8px 16px -6px rgba(0, 0, 0, 0.55);
}

/* ================================================================ THE DIAL ==
   Marquis: "just make sure it makes sense."

   So: exactly one dial, and only because exactly one control on these pages is
   genuinely positional. The leaders WEEK selector is SEASON, 1, 2, 3 ... in
   order, with a current setting -- that is a rotary switch. The category row
   above it (PASSING, RUSHING, DEFENSE) is unordered, so it stays a bank of
   keys, which is what it is.

   NOT A KNOB, A DETENT TRACK. Eighteen weeks around a knob is unreadable; the
   honest mechanical form for a long ordered range is the tuning track in his
   own reference photo -- a recessed channel, tick marks, and the setting
   sitting in a lit notch under a pointer. It says where it is set while you
   are not touching it, which is the whole reason a dial feels mechanical and
   a row of pills does not. */
body[data-skin="machined"] .wk-dial {
  display: flex; gap: 4px; align-items: center; flex-wrap: wrap;
  padding: 14px 14px 16px;
  border-radius: 14px;
  background: linear-gradient(180deg, #05080F, #0A1120);
  box-shadow:
    inset 0 4px 10px rgba(0, 0, 0, 0.9),
    inset 0 -1px 0 rgba(140, 175, 255, 0.1),
    0 1px 0 rgba(255, 255, 255, 0.05);
  /* the tick marks, along the floor of the channel */
  background-image:
    linear-gradient(180deg, #05080F, #0A1120),
    repeating-linear-gradient(90deg,
      rgba(140,175,255,0.16) 0 1px, transparent 1px 34px);
  background-size: 100% 100%, 100% 7px;
  background-position: 0 0, 0 100%;
  background-repeat: no-repeat, repeat-x;
}
body[data-skin="machined"] .wk-dial .dim {
  font-family: ui-monospace, 'IBM Plex Mono', monospace;
  letter-spacing: 0.16em;
}
/* a detent: small, milled, and sunk slightly into the channel */
body[data-skin="machined"] .wk-dial .chip {
  position: relative;
  border-radius: 7px;
  padding: 6px 10px;
  box-shadow: 0 2px 0 rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.1);
}
/* the setting: lit notch, sapphire seam, and a pointer above it */
body[data-skin="machined"] .wk-dial .chip.set {
  transform: none;
  color: var(--ink-strong);
  background:
    linear-gradient(180deg, #0A1121, #1B2A47) padding-box,
    linear-gradient(180deg, rgba(0,0,0,0.85), rgba(120,160,255,0.4)) border-box;
  box-shadow:
    inset 0 3px 7px rgba(0,0,0,0.85),
    inset 0 0 0 1px rgba(var(--sap-rgb), 0.6),
    0 0 14px -2px rgba(var(--sap-rgb), 0.5);
}
body[data-skin="machined"] .wk-dial .chip.set::before {
  content: ""; position: absolute; left: 50%; top: -9px;
  margin-left: -4px; width: 0; height: 0;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid var(--sap-lift);
  filter: drop-shadow(0 0 4px rgba(var(--sap-rgb), 0.9));
}

/* THE KEYS. Raised, chamfered, lit along the top lip. Taken is pressed IN with
   a sapphire seam — nothing glows outward, because a board of forty glowing
   controls is a theme and not a machine. */
body[data-skin="machined"] .chip {
  border: 1px solid transparent;
  border-radius: 9px;
  color: var(--ink-soft);
  background:
    linear-gradient(180deg, #27324A, #131A29) padding-box,
    linear-gradient(180deg, rgba(170,200,255,0.34), rgba(0,0,0,0.7)) border-box;
  box-shadow: 0 3px 0 rgba(0,0,0,0.5), 0 5px 10px rgba(0,0,0,0.4),
              inset 0 1px 0 rgba(255,255,255,0.14);
  transition: transform 160ms var(--ease), box-shadow 160ms var(--ease),
              filter 160ms var(--ease);
}
body[data-skin="machined"] a.chip:hover,
body[data-skin="machined"] button.chip:hover { filter: brightness(1.15); }
body[data-skin="machined"] .chip.on,
body[data-skin="machined"] .chip.active,
body[data-skin="machined"] .chip[aria-pressed="true"] {
  transform: translateY(3px); color: var(--ink-strong);
  background:
    linear-gradient(180deg, #0A1121, #16233D) padding-box,
    linear-gradient(180deg, rgba(0,0,0,0.85), rgba(120,160,255,0.3)) border-box;
  box-shadow: inset 0 4px 9px rgba(0,0,0,0.9),
              inset 0 0 0 1px rgba(var(--sap-rgb), 0.55),
              inset 0 -1px 0 rgba(255,255,255,0.08);
}

/* CARVED, NOT PRINTED. On a dark material the emboss is a dark shadow BELOW
   the glyph and a whisper of light above — the reverse of the light-mode
   recipe, and what makes a label look milled into the panel. */
body[data-skin="machined"] .panel-hd,
body[data-skin="machined"] .kicker,
body[data-skin="machined"] .lbl {
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.8), 0 -1px 0 rgba(255, 255, 255, 0.06);
}

/* THE INSTRUMENT LABEL. A column header on a page you study is an instrument
   label; monospace is what makes it read as one, and on a page of numbers this
   lever does more than the hue does. Headers glow faintly because they are
   printed ON the display, not on the metal. */
body[data-skin="machined"] th,
body[data-skin="machined"] .kicker,
body[data-skin="machined"] .lbl {
  font-family: ui-monospace, 'IBM Plex Mono', SFMono-Regular, monospace;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: 0.82em;
}
body[data-skin="machined"] .panel table th {
  color: var(--ink-dim); text-shadow: none;
}

/* MEANING BEATS STATE, ALWAYS. A highlighted row must not repaint a green
   number blue: the one row a reader cares most about would be the one row
   whose colours stopped meaning anything. */
body[data-skin="machined"] .panel table td .good,
body[data-skin="machined"] .panel table td.good { color: var(--good); }
body[data-skin="machined"] .panel table td .bad,
body[data-skin="machined"] .panel table td.bad { color: var(--bad); }

/* Digits line up on a page whose job is comparison. */
body[data-skin="machined"] td,
body[data-skin="machined"] th,
body[data-skin="machined"] .num { font-variant-numeric: tabular-nums; }

/* Rows stay FLAT — three depths, and this is not one of them. */
body[data-skin="machined"] tbody tr { box-shadow: none; }
body[data-skin="machined"] tbody tr + tr td { border-top: 1px solid var(--guide); }

@media (prefers-reduced-motion: reduce) {
  body[data-skin="machined"] .chip { transition: none; }
  body[data-skin="machined"] .chip.on { transform: none; }
}

/* ===== THE MONEY LINE ======================================================
   A spread asks whether they cover; this asks whether they WIN, and the two
   move apart as the week goes on. So it does not look like the spread: no
   over/under pair, two team-shaped plates, an American price that is the room's
   number rather than a posted one, and the move since it opened printed under
   it so a reader can see the line breathing. Green up, bronze down — the same
   categorical pair the split bar uses, never the good/bad ramp, because a line
   moving toward a side is not good news, it is news. */
.ml-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.ml-btn {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 9px 8px 8px; border-radius: var(--r); text-decoration: none;
  background: linear-gradient(180deg, rgba(20,32,66,0.92), rgba(11,20,44,0.92));
  border: 1px solid var(--line-3); color: var(--ink);
  transition: border-color var(--t-fast) var(--ease),
              background var(--t-fast) var(--ease), transform 60ms var(--ease);
}
.ml-btn:hover { border-color: rgba(255,217,138,0.5); }
.ml-btn:active { transform: scale(0.985); }
.ml-team { font-size: 10.5px; font-weight: 700; color: #AEBBDD;
           letter-spacing: 0.03em; max-width: 100%; overflow: hidden;
           text-overflow: ellipsis; white-space: nowrap; }
.ml-price { font-family: var(--f-cond); font-weight: 800; font-style: italic;
            font-size: 21px; line-height: 1; color: var(--gold);
            font-variant-numeric: tabular-nums; }
.ml-sub { font-size: 9px; letter-spacing: 0.06em; color: #7E8BAD;
          font-variant-numeric: tabular-nums; }
.ml-sub.up { color: var(--good); }
.ml-sub.dn { color: #C89A52; }

/* ===== THE PRICE BAR =======================================================
   A market price IS a probability — 34¢ means the room thinks 34% — and a
   column of cents makes a reader do that translation in his head. The bar
   does it for him: it is the price, drawn. It sits behind the row rather than
   beside it so it costs no width on a phone, and it is quiet enough that the
   text on top of it is still the thing being read. */
.mk-bar {
  position: absolute; left: 0; top: 0; bottom: 0; z-index: 0;
  border-right: 1px solid rgba(var(--lift-rgb), 0.28);
  background: linear-gradient(90deg, rgba(30,58,138,0.30), rgba(var(--sap-rgb), 0.16));
  pointer-events: none;
}
.mk-bar.lead { background: linear-gradient(90deg, rgba(74,58,16,0.42), rgba(200,165,82,0.16));
               border-right-color: rgba(255,217,138,0.4); }
.mk-row, .mkt-line { position: relative; isolation: isolate; }
.mk-row > *:not(.mk-bar), .mkt-line > *:not(.mk-bar) { position: relative; z-index: 1; }

/* ===== THE GAME CARD, AS A DEVICE =========================================
   Marquis: "the layout is a bit confusing."

   It was six identical rounded plates in a grid — money line, spread and
   total all drawn as the same object, three different questions wearing one
   face. And the total printed its ONE number twice, once on each key.

   One material per mechanism, shaped like what it does, legend milled into a
   left rail instead of a heading stacked above it. Light from the top,
   shadow below, everywhere; nothing here is glass and nothing is glossy.
     ROCKER  money line — one housing, two faces, a seam down the middle.
     KEYS    spread — pressable, the handicap engraved big.
     GAUGE   total — a recessed readout with the number once, and two keys.  */

.mkt-stack { display: flex; flex-direction: column; gap: 10px; }

.mkt {
  display: grid; grid-template-columns: 46px 1fr; align-items: center;
  gap: 10px; min-height: 58px;
}
/* the legend, engraved into the chassis: cut in, never raised */
.mkt-rail {
  font-size: 8.5px; font-weight: 800; letter-spacing: 0.14em; line-height: 1.25;
  color: #6E7C9E; text-align: right; text-transform: uppercase;
  text-shadow: 0 1px 0 rgba(255,255,255,0.06), 0 -1px 0 rgba(0,0,0,0.55);
}
.mkt-none { font-size: 10.5px; color: #6E7C9E; padding: 8px 0; }
.keys { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }

/* ---- the rocker: a recessed housing with two proud faces --------------- */
.rocker {
  display: grid; grid-template-columns: 1fr 1fr; gap: 5px;
  padding: 5px; border-radius: 12px;
  /* the housing is CUT IN — it is the hole the switch sits in */
  background: linear-gradient(180deg, #05080F, #0A1122);
  box-shadow: inset 0 4px 10px rgba(0,0,0,0.9),
              inset 0 -1px 0 rgba(150,185,255,0.10),
              0 1px 0 rgba(255,255,255,0.05);
}
/* each face is PROUD of the housing, top-lit, and pressable */
.rock {
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: 7px 6px 6px; text-decoration: none; color: var(--ink);
  border: 1px solid transparent; border-radius: 9px;
  background:
    linear-gradient(180deg, #1B2740, #101A2E 62%, #0B1322) padding-box,
    linear-gradient(180deg, rgba(175,205,255,0.34), rgba(0,0,0,0.55)) border-box;
  box-shadow: 0 2px 5px rgba(0,0,0,0.55),
              inset 0 1px 0 rgba(200,222,255,0.16),
              inset 0 -1px 0 rgba(0,0,0,0.5);
  transition: box-shadow 180ms var(--ease), transform 160ms var(--ease),
              background 180ms var(--ease);
}
.rock:hover {
  background:
    linear-gradient(180deg, #23324F, #14203A 62%, #0D1729) padding-box,
    linear-gradient(180deg, rgba(255,217,138,0.5), rgba(0,0,0,0.55)) border-box;
}
/* pressing a rocker face tips it INTO the housing */
.rock:active {
  transform: translateY(1px);
  box-shadow: inset 0 3px 8px rgba(0,0,0,0.75),
              inset 0 -1px 0 rgba(200,222,255,0.12);
}
.rock-team {
  font-size: 10px; font-weight: 700; letter-spacing: 0.04em; color: #A9B8DC;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-shadow: 0 1px 0 rgba(0,0,0,0.6);
}
.rock-price {
  font-family: ui-monospace, 'IBM Plex Mono', 'SF Mono', monospace;
  font-size: 17px; font-weight: 700; line-height: 1.15; color: var(--gold);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 0 rgba(0,0,0,0.75), 0 0 16px rgba(255,217,138,0.20);
}
.rock-sub { font-size: 9px; color: #6E7C9E; font-variant-numeric: tabular-nums; }
.rock-sub.up { color: var(--good); }
.rock-sub.dn { color: #C89A52; }

/* ---- the gauge: the total's number, once, sunk into the face ----------- */
.gauge-row { display: grid; grid-template-columns: 62px 1fr; gap: 8px;
             align-items: center; }
.gauge {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 6px 4px 5px; border-radius: 9px;
  background: linear-gradient(180deg, #05080F, #0B1322);
  box-shadow: inset 0 3px 9px rgba(0,0,0,0.9), inset 0 -1px 0 rgba(150,185,255,0.10),
              0 1px 0 rgba(255,255,255,0.04);
}
.gauge b {
  font-family: var(--f-cond); font-style: italic; font-weight: 800;
  font-size: 21px; line-height: 1; color: var(--gold);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 14px rgba(255,217,138,0.28);
}
.gauge span { font-size: 8px; letter-spacing: 0.18em; color: #6E7C9E; margin-top: 2px; }
/* a key with no number of its own is a LABEL key: the word carries it */
.gauge-row .odds-btn .ob-side { font-size: 12.5px; font-weight: 800; letter-spacing: 0.08em; }
.gauge-row .odds-btn .ob-line:empty { display: none; }
.gauge-row .odds-btn { padding: 13px 8px; }

/* ---- the seam at the foot of the card ---------------------------------- */
.card-seam {
  margin-top: 12px; padding-top: 10px;
  border-top: 1px solid rgba(0,0,0,0.6);
  box-shadow: 0 -1px 0 rgba(150,185,255,0.08);
  display: flex; flex-direction: column; gap: 6px;
}
.sheet-sum {
  display: flex; align-items: baseline; gap: 8px; cursor: pointer;
  font-size: 9.5px; font-weight: 800; letter-spacing: 0.14em;
  color: #7E8BAD; text-transform: uppercase; list-style: none;
}
.sheet-sum::-webkit-details-marker { display: none; }
.sheet-sum::before { content: "▸"; font-size: 8px; color: #55618A; }
details[open] > .sheet-sum::before { content: "▾"; }
.sheet-of { color: #7E8BAD; }
.sheet-lean { font-size: 10px; letter-spacing: 0.06em; }

/* ===== THE RIG — a stat page as one instrument =============================
   Marquis: "it just looks like it got a new skin. It should be one tool that
   can toggle between the advanced metrics. Use the dial to raise the
   threshold for selected columns within the tool."

   Four stacked panels give the machined material four chassis to sit on, and
   four chassis on a page is a page, not a tool. A tool has ONE body: a
   nameplate cast into the top, a screen you cannot touch, and a deck you can.
   Everything else is the manual, and a manual lives under the machine.

   Depth is the same hierarchy the machined skin uses: room → chassis → glass
   → deck. The chassis is the only thing casting into the room; the glass is
   sunk into the chassis and is not pressable; the deck is proud of it and is
   the only thing that is.                                                    */

.rig {
  position: relative;
  border: 1px solid transparent;
  border-radius: 20px;
  padding: 0 0 16px;
  background:
    linear-gradient(180deg, #1A2540, #111A2D 46%, #0A1120) padding-box,
    linear-gradient(180deg, rgba(175,205,255,0.34), rgba(0,0,0,0.6)) border-box;
  box-shadow:
    0 26px 48px -14px rgba(0, 3, 12, 0.85),
    0 8px 18px rgba(0, 3, 12, 0.5),
    inset 0 1px 0 rgba(205, 226, 255, 0.16),
    inset 0 -1px 0 rgba(0, 0, 0, 0.55);
}
/* the four bolts that hold the face on */
.rig::before {
  content: ""; position: absolute; inset: 9px; border-radius: 14px;
  pointer-events: none;
  background:
    radial-gradient(circle at 0 0, rgba(190,215,255,0.5) 0 1.1px, rgba(0,0,0,0.55) 1.4px 2.4px, transparent 2.6px),
    radial-gradient(circle at 100% 0, rgba(190,215,255,0.5) 0 1.1px, rgba(0,0,0,0.55) 1.4px 2.4px, transparent 2.6px),
    radial-gradient(circle at 0 100%, rgba(190,215,255,0.5) 0 1.1px, rgba(0,0,0,0.55) 1.4px 2.4px, transparent 2.6px),
    radial-gradient(circle at 100% 100%, rgba(190,215,255,0.5) 0 1.1px, rgba(0,0,0,0.55) 1.4px 2.4px, transparent 2.6px);
}

/* ---- the nameplate: cast into the face, never printed on it ------------- */
.rig-plate {
  display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap;
  padding: 18px 22px 14px;
  border-bottom: 1px solid rgba(0,0,0,0.55);
  box-shadow: 0 1px 0 rgba(180,210,255,0.08);
}
.rig-name {
  font-family: var(--f-cond); font-style: italic; font-weight: 800;
  font-size: 30px; line-height: 1; letter-spacing: 0.01em;
  color: #C7D6F4;
  text-shadow: 0 1px 0 rgba(0,0,0,0.8), 0 -1px 0 rgba(205,226,255,0.14);
}
.rig-read {
  font-family: ui-monospace, 'IBM Plex Mono', monospace;
  font-size: 10px; letter-spacing: 0.14em; color: #6E7C9E;
}
.rig-read span { color: var(--gold); }
.rig-read i { color: #3D4767; font-style: normal; margin: 0 4px; }
.rig-read .warn { color: var(--amber); }

/* ---- the deck: the only pressable plane -------------------------------- */
.rig-deck { display: flex; flex-direction: column; gap: 8px; padding: 14px 16px 4px; }
.rig-modes, .rig-knobs { justify-content: flex-start; }
.rig-modes .chip { font-size: 10.5px; letter-spacing: 0.1em; }
.rig-pick { display: flex; align-items: center; gap: 6px; }
.rig-pick span { font-size: 8.5px; letter-spacing: 0.16em; color: #6E7C9E; }
.rig-pick select {
  font-size: 11px; padding: 5px 8px; border-radius: 7px; max-width: 190px;
  background: linear-gradient(180deg, #16213A, #0C1424);
  border: 1px solid rgba(150,185,255,0.22); color: var(--ink);
}
.rig-out {
  font-family: ui-monospace, 'IBM Plex Mono', monospace;
  font-size: 10.5px; letter-spacing: 0.08em; color: var(--gold);
  min-width: 15ch; font-variant-numeric: tabular-nums;
}

/* the knob: a milled slider running in the deck's own channel */
.rig-knob { -webkit-appearance: none; appearance: none; height: 22px;
            width: min(190px, 42vw); background: transparent; cursor: ew-resize; }
.rig-knob::-webkit-slider-runnable-track {
  height: 6px; border-radius: 3px;
  background: linear-gradient(180deg, #04070E, #0C1526);
  box-shadow: inset 0 2px 5px rgba(0,0,0,0.9), 0 1px 0 rgba(255,255,255,0.05);
}
.rig-knob::-moz-range-track {
  height: 6px; border-radius: 3px;
  background: linear-gradient(180deg, #04070E, #0C1526);
  box-shadow: inset 0 2px 5px rgba(0,0,0,0.9);
}
.rig-knob::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 15px; height: 20px; margin-top: -7px; border-radius: 4px;
  background:
    linear-gradient(180deg, #24314F, #131D31) padding-box,
    linear-gradient(180deg, rgba(190,215,255,0.5), rgba(0,0,0,0.6)) border-box;
  border: 1px solid transparent;
  box-shadow: 0 2px 5px rgba(0,0,0,0.6), inset 0 1px 0 rgba(210,230,255,0.28),
              inset 0 0 0 1px rgba(0,0,0,0.35);
  /* milling on the grip */
  background-image:
    linear-gradient(180deg, #24314F, #131D31),
    repeating-linear-gradient(90deg, rgba(190,215,255,0.22) 0 1px, transparent 1px 4px);
  background-blend-mode: normal, overlay;
}
.rig-knob::-moz-range-thumb {
  width: 15px; height: 20px; border-radius: 4px; border: 1px solid rgba(190,215,255,0.4);
  background: linear-gradient(180deg, #24314F, #131D31);
}

/* ---- the screen: sunk in, lit from within, not pressable --------------- */
.rig-screen { padding: 4px 16px 0; }
.rig-glass {
  border-radius: 12px; padding: 4px 2px; overflow-x: auto;
  background: linear-gradient(160deg, rgba(9,16,32,0.96), rgba(4,8,18,0.98));
  box-shadow: inset 0 3px 14px rgba(0,0,0,0.95),
              inset 0 -1px 0 rgba(150,185,255,0.09),
              0 1px 0 rgba(255,255,255,0.04);
}
.rig-glass table { width: 100%; }
.rig-pair { display: grid; gap: 14px;
            grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.rig-pair .kicker { margin: 6px 0 6px 10px; color: #7E8BAD; }

/* a row the floor has cut out: still legible, plainly not in the answer */
.rig-glass tr.off { opacity: 0.2; }
.rig-glass tr.off a { color: inherit; }

/* ---- the manual: under the machine, where a manual goes ---------------- */
.rig-manual { padding: 12px 4px 2px; max-width: 88ch; }
.rig-manual p { margin: 0 0 9px; font-size: 12.5px; line-height: 1.62;
                color: var(--ink-soft); }
.rig-manual p.fine { font-size: 11.5px; color: #8B98BC; }

.rig-why { margin-top: 18px; }
.rig-why > summary { cursor: pointer; font-size: 10px; font-weight: 800;
                     letter-spacing: 0.16em; color: #7E8BAD; }
.rig-why-body { margin-top: 4px; }

@media (max-width: 620px) {
  .rig-name { font-size: 24px; }
  .rig-out { min-width: 0; }
}

/* ===== THE DOOR ===========================================================
   The rendezvous board. Everything on it is somebody's own statement with a
   fuse on it, so the material is honest about that: a beacon counts down in
   front of you, and a burnt-out one goes grey rather than disappearing. */
.door-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 7px 0; border-bottom: 1px solid var(--guide); font-size: 12.5px;
}
.door-row b { color: var(--ink-strong); }
.door-left {
  margin-left: auto; font-family: ui-monospace, 'IBM Plex Mono', monospace;
  font-size: 10.5px; letter-spacing: 0.06em; color: var(--gold);
  font-variant-numeric: tabular-nums;
}
.door-left.out { color: #6E7C9E; }

/* the hour grid: seven rows of keys you can paint across */
.door-grid { display: flex; flex-direction: column; gap: 3px; margin: 8px 0 4px;
             overflow-x: auto; padding-bottom: 4px; touch-action: none; }
.dg-row { display: grid; grid-template-columns: 34px repeat(16, minmax(17px, 1fr));
          gap: 3px; align-items: center; min-width: 330px; }
.dg-head span { font-size: 8px; color: #6E7C9E; text-align: center;
                letter-spacing: 0.02em; }
.dg-day { font-size: 9.5px; font-weight: 800; letter-spacing: 0.1em;
          color: #7E8BAD; }
.dg-cell {
  height: 20px; border-radius: 4px; cursor: pointer; padding: 0;
  border: 1px solid rgba(150,185,255,0.14);
  background: linear-gradient(180deg, #101A2E, #0A1120);
  box-shadow: inset 0 1px 0 rgba(200,222,255,0.06);
  transition: background 140ms var(--ease), border-color 140ms var(--ease);
}
.dg-cell.on {
  border-color: rgba(var(--sap-rgb), 0.55);
  background: linear-gradient(180deg, #2E5CD8, #1B3A93);
  box-shadow: inset 0 1px 0 rgba(210,230,255,0.3), 0 0 10px -2px rgba(var(--sap-rgb), 0.6);
}

/* ===== THE LEAGUE SWITCHER ================================================
   Marquis: "make the ability to switch leagues more obvious."

   It was three levels down a menu, and nothing on any page said which league
   you were looking at — on a site where every table, roster and dollar figure
   is league-scoped. So it is a control in the masthead, and it does the two
   jobs in that order: it TELLS you where you are, then it lets you leave.

   A <details>, so it opens with no JavaScript and closes with Escape. */
.lg-pick { position: relative; flex: 0 1 auto; min-width: 0; }
.lg-pick > summary {
  display: flex; align-items: center; gap: 5px; cursor: pointer;
  list-style: none; padding: 5px 9px; border-radius: 8px; max-width: 30vw;
  border: 1px solid transparent;
  background:
    linear-gradient(180deg, rgba(26,37,64,0.95), rgba(14,22,42,0.95)) padding-box,
    linear-gradient(180deg, rgba(160,195,255,0.3), rgba(0,0,0,0.5)) border-box;
  box-shadow: 0 1px 3px rgba(0,0,0,0.45), inset 0 1px 0 rgba(200,222,255,0.12);
  transition: border-color var(--t-fast) var(--ease);
}
.lg-pick > summary::-webkit-details-marker { display: none; }
.lg-pick > summary:hover { border-color: rgba(255,217,138,0.45); }
.lg-now {
  font-size: 12px; font-weight: 800; letter-spacing: 0.02em; color: var(--sap-pale);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lg-caret { font-size: 9px; color: #7E8BAD; flex: 0 0 auto; }
.lg-pick[open] > summary { border-color: rgba(var(--line-rgb), 0.55); }

.lg-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 60;
  min-width: 232px; max-width: min(320px, 86vw); padding: 8px;
  border-radius: 12px; border: 1px solid rgba(var(--line-rgb), 0.28);
  background: linear-gradient(180deg, #101A2E, #08101F);
  box-shadow: 0 22px 44px -12px rgba(0,3,12,0.9), 0 4px 12px rgba(0,3,12,0.6);
}
.lg-lbl { font-size: 8.5px; font-weight: 800; letter-spacing: 0.18em;
          color: #6E7C9E; padding: 7px 8px 4px; }
.lg-row {
  display: flex; align-items: center; gap: 8px; padding: 8px 9px;
  border-radius: 8px; text-decoration: none; color: var(--ink);
  font-size: 12.5px; line-height: 1.3;
}
.lg-row b { color: var(--ink-strong); font-weight: 700; min-width: 0;
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lg-row:hover { background: rgba(var(--sap-rgb), 0.14); }
.lg-row.here { background: rgba(var(--sap-rgb), 0.1); }
.lg-tick { margin-left: auto; color: var(--gold); font-size: 9px; }
.lg-run { margin-left: auto; font-size: 9.5px; letter-spacing: 0.08em;
          color: var(--good); flex: 0 0 auto; }

@media (max-width: 700px) {
  .lg-pick > summary { max-width: 40vw; padding: 4px 7px; }
  .lg-now { font-size: 11px; }
}

/* A fixture the calendar did not have, written by a filed result. Quiet — it
   is provenance, not a warning: the schedule corrected itself, which is the
   system working. */
.ct-added { font-size: 9.5px; letter-spacing: 0.06em; color: #6BDB8F;
            margin-left: 5px; }

/* A GAME THE CONSOLE PLAYED. Grey, not red: a sim is not a fault, it is most
   of an 82-game MyNBA. It reads as a label because that is all it is -- the
   result counts everywhere, and the reader knows where it came from. */
.ct-sim { font-size: 9px; letter-spacing: 0.08em; text-transform: uppercase;
          color: var(--ink-dim); border: 1px solid var(--line-ct);
          border-radius: 4px; padding: 1px 4px; margin-left: 5px;
          vertical-align: 1px; }

/* ===== LOG A GAME — the door that needs no calendar =======================
   "2k seasons have no shape ... we needed a freeform way for them to get their
   games logged without an inaccurate calendar throwing everyone off."
   Two teams and a week. It asks nothing a fixture list would have to answer. */
.ct-log { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
          margin-top: 10px; }
.ct-log select {
  flex: 1 1 150px; min-width: 0; font: inherit; font-size: 12.5px;
  padding: 8px 9px; border-radius: 8px; color: var(--ink);
  background: linear-gradient(180deg, #16213A, #0C1424);
  border: 1px solid rgba(150,185,255,0.24);
}
.ct-log .ct-wk { display: flex; align-items: center; gap: 5px; font-size: 10px;
                 letter-spacing: 0.14em; color: #6E7C9E; text-transform: uppercase; }
.ct-log .ct-wk input {
  width: 58px; font: inherit; font-size: 12.5px; padding: 7px 8px;
  border-radius: 8px; color: var(--ink); text-align: center;
  background: linear-gradient(180deg, #16213A, #0C1424);
  border: 1px solid rgba(150,185,255,0.24);
}
/* in an open-play league this IS the main door, so it reads like one */
.ct-panel.ct-first { border-color: rgba(107,219,143,0.34);
                     box-shadow: 0 0 0 1px rgba(107,219,143,0.12) inset; }

/* ===== ONE 2K GAME, OPENED UP ============================================
   A played game is a door: the score is the link, because that is where a
   reader's eye already is when the question occurs to him. */
a.ct-score { text-decoration: none; border-radius: 6px; padding: 1px 4px;
             transition: background 160ms var(--ease); }
a.ct-score:hover { background: rgba(var(--sap-rgb), 0.16); }

.gm-score { display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
            margin-top: 10px; }
.gm-side { display: flex; align-items: center; gap: 11px; min-width: 0; }
.gm-side img { width: 44px; height: 44px; object-fit: contain; }
.gm-side b { font-family: var(--f-cond); font-style: italic; font-weight: 800;
             font-size: 40px; line-height: 1; color: #7E8BAD;
             font-variant-numeric: tabular-nums; }
.gm-side.won b { color: #FFF; text-shadow: 0 0 22px rgba(255,217,138,0.35); }
.gm-name { font-weight: 800; font-size: 15px; color: var(--ink-strong); }
.gm-sub { font-size: 9.5px; letter-spacing: 0.16em; color: #6E7C9E;
          text-transform: uppercase; }
.gm-side.home { flex-direction: row-reverse; text-align: right; }
.gm-at { color: #3D4767; font-size: 20px; }

.gm-stars { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.gm-star { display: flex; align-items: center; gap: 11px; padding: 9px 11px;
           border-radius: 10px; text-decoration: none; color: var(--ink);
           background: linear-gradient(180deg, rgba(20,32,66,0.7), rgba(11,20,44,0.7));
           border: 1px solid rgba(150,185,255,0.16); }
.gm-star:hover { border-color: rgba(255,217,138,0.4); }
.gm-star img { width: 34px; height: 34px; border-radius: 50%; object-fit: cover;
               object-position: top; background: #14275C; flex: 0 0 auto; }
.gm-star-n { font-weight: 700; color: var(--ink-strong); font-size: 13.5px; }
.gm-star-l { font-size: 11.5px; color: #A9B8DC; margin-top: 2px; }
.gm-gs { margin-left: auto; font-family: var(--f-cond); font-style: italic;
         font-weight: 800; font-size: 22px; color: var(--gold);
         font-variant-numeric: tabular-nums; }
.gm-tag { font-size: 8.5px; letter-spacing: 0.12em; font-weight: 800;
          padding: 2px 5px; border-radius: 4px; margin-left: 6px;
          color: #0B1220; background: var(--sap-soft); vertical-align: middle; }
.gm-tag.td { background: var(--gold); }

.gm-adv { width: 100%; }
.gm-adv .mid { text-align: center; color: #7E8BAD; font-size: 11.5px;
               font-weight: 600; white-space: nowrap; }
.gm-adv .n { font-variant-numeric: tabular-nums; font-size: 14px;
             color: var(--ink-soft); width: 32%; }
.gm-adv .n.best { color: var(--gold); font-weight: 800; }
.gm-adv tr td:first-child { text-align: left; }
.gm-adv tr td:last-child { text-align: right; }

.gm-box .n { font-variant-numeric: tabular-nums; }
.gm-box tr.gm-tot td { border-top: 1px solid rgba(150,185,255,0.22);
                       font-weight: 800; color: var(--ink-soft); }

/* ===========================================================================
   HOW THIS PAGE WORKS (build 197)
   One folded line under the masthead on every page that has a walkthrough;
   guide.js prints the tour's steps into it on a tap. The numbers are the
   walkthrough's order, which is a real sequence.
   =========================================================================== */
.howto { border-bottom: 1px solid var(--line); background: rgba(8, 13, 28, 0.6); }
.howto-hd {
  width: 100%; display: flex; align-items: center; gap: 12px;
  max-width: var(--container); margin: 0 auto; padding: 8px var(--pad);
  background: none; border: 0; cursor: pointer; color: var(--ink);
  font-family: inherit; text-align: left;
}
.howto-hd:focus-visible { outline: 2px solid var(--sap); outline-offset: -2px; }
.howto-k {
  font-family: var(--f-cond); font-weight: 800; font-style: italic; font-size: 14px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--sap-pale);
}
.howto-n { font-size: 12px; color: var(--ink-dim); }
.howto-tog {
  margin-left: auto; width: 8px; height: 8px; flex: 0 0 auto;
  border-right: 2px solid var(--sap-soft); border-bottom: 2px solid var(--sap-soft);
  transform: rotate(-135deg) translate(-2px, -2px);
  transition: transform var(--t-control) var(--ease);
}
.howto.folded .howto-tog { transform: rotate(45deg) translate(-2px, -2px); }
.howto-body { max-width: var(--container); margin: 0 auto; padding: 2px var(--pad) 14px; }
.howto.folded .howto-body { display: none; }
.howto-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 10px 22px; counter-reset: h;
}
.howto-step { font-size: 12.5px; line-height: 1.6; color: var(--ink-muted); padding-left: 26px; position: relative; }
.howto-step::before {
  counter-increment: h; content: counter(h);
  position: absolute; left: 0; top: -2px;
  font-family: var(--f-cond); font-weight: 800; font-style: italic; font-size: 20px; color: var(--sap-lift);
}
.howto-step b { display: block; color: var(--ink-strong); font-size: 13px; margin-bottom: 2px; }
.howto-step p { margin: 0; white-space: pre-line; }
.howto-foot { margin-top: 10px; font-size: 12px; }
.howto-foot a { color: var(--sap-soft); }
/*  Build 363: the how-to clip, when a page has one. Capped so it never
    dominates the strip on a desktop and never overflows a phone. */
.howto-clip { margin: 10px 0 0; max-width: 620px; }
.howto-clip video {
  width: 100%; display: block; border-radius: 10px;
  border: 1px solid var(--line2); background: #05080F;
}
.howto-clip figcaption {
  margin-top: 6px; font-size: 11.5px; letter-spacing: 0.04em;
  color: var(--ink-dim);
}
/* ===========================================================================
   THE CONFIRM SHEET — build 199.
   ---------------------------------------------------------------------------
   Replaces window.confirm() everywhere on the site (see app/static/confirm.js
   for the why). One themed <dialog>, entrance only — a decision the reader
   just made is not a moment to make them watch it leave.
   =========================================================================== */
.sap-sheet {
  border: none; padding: 0; background: transparent; color: inherit;
  max-width: 440px; width: calc(100% - 32px);
  overflow: visible;
}
.sap-sheet::backdrop { background: rgba(3, 5, 11, 0.74); backdrop-filter: blur(3px); }
.sap-sheet .sap-card {
  background: var(--surface-solid); border: 1px solid var(--line-3);
  border-radius: var(--r-lg); box-shadow: var(--lift-3);
  padding: 24px 26px 20px; margin: 0;
}
.sap-sheet[open] .sap-card { animation: sap-in var(--t-section) var(--ease-out); }
@keyframes sap-in {
  from { opacity: 0; transform: scale(0.96) translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.sap-card.is-leaving { transition: opacity 120ms var(--ease); opacity: 0; }
.sap-sheet-title {
  font-family: var(--f-cond); font-weight: 800; font-style: italic;
  font-size: 21px; letter-spacing: 0.01em; color: var(--ink-strong);
  margin-bottom: 8px;
}
.sap-sheet-body { font-size: 14px; line-height: 1.55; color: var(--ink-muted); white-space: pre-line; }
.sap-sheet-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }
.sap-sheet-actions .btn { padding: 11px 20px; font-size: 13px; }
.sap-sheet-ok.danger {
  background: linear-gradient(135deg, #E05A5A, #8E2A2A);
  box-shadow: 0 8px 22px -6px rgba(224, 90, 90, 0.5), 0 0 0 1px rgba(255,150,150,0.3) inset;
}
@media (prefers-reduced-motion: reduce) {
  .sap-sheet[open] .sap-card { animation: none; }
  .sap-card.is-leaving { transition: none; }
}
html[data-motion="off"] .sap-sheet[open] .sap-card { animation: none; }
html[data-motion="off"] .sap-card.is-leaving { transition: none; }
@media (max-width: 520px) {
  .sap-sheet { max-width: 92vw; }
  .sap-sheet-actions { flex-direction: column-reverse; }
  .sap-sheet-actions .btn { width: 100%; justify-content: center; }
}


/* SET YOUR AVAILABILITY (build 501) — top of the league home and its own page. */
.av-card { margin: 0 0 16px; border: 1px solid #354561; border-radius: 12px; background: linear-gradient(180deg, rgba(20,34,66,0.72), rgba(8,14,30,0.72)); }
.av-card.av-due { border-color: rgba(255,184,107,0.75); box-shadow: 0 0 0 1px rgba(255,184,107,0.18) inset; }
.av-fold > summary { list-style: none; display: flex; align-items: center; gap: 14px; padding: 15px 20px; cursor: pointer; }
.av-fold > summary::-webkit-details-marker { display: none; }
.av-fold > summary:focus-visible { outline: 2px solid var(--sap-soft); outline-offset: -2px; border-radius: 12px; }
.av-ico { font-size: 22px; line-height: 1; }
.av-head { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.av-head b { font-family: var(--f-cond); font-weight: 800; font-size: 22px; letter-spacing: 0.02em; text-transform: uppercase; color: #FFF; }
.av-head small { color: #98a9c4; font-size: 12.5px; }
.av-due .av-head small { color: #FFCF9A; }
.av-flag { flex: none; font-size: 11px; font-weight: 800; letter-spacing: 0.12em; padding: 5px 10px; border-radius: 999px; border: 1px solid rgba(107,219,143,0.6); color: #6BDB8F; }
.av-due .av-flag { border-color: rgba(255,184,107,0.8); color: #FFB86B; background: rgba(255,184,107,0.1); }
.av-body { padding: 0 20px 18px; display: flex; flex-direction: column; gap: 10px; }
.av-note { margin: 0; color: #C6D2EE; font-size: 13px; }
.av-scroll { overflow-x: auto; }
.av-grid { border-collapse: separate; border-spacing: 5px; }
.av-grid th { color: #98a9c4; font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-align: center; }
.av-grid th[scope="row"] { text-align: left; padding-right: 6px; white-space: nowrap; }
.av-c { width: 48px; height: 34px; border-radius: 7px; cursor: pointer; border: 1.5px solid rgba(var(--line-rgb), 0.2); background: rgba(6,11,24,0.8); color: #E8EEFC; font: inherit; position: relative; }
.av-c:hover { border-color: rgba(var(--soft-rgb), 0.6); }
.av-c:focus-visible { outline: 2px solid var(--sap-soft); outline-offset: 1px; }
.av-c.them::after { content: ""; position: absolute; top: 5px; right: 5px; width: 6px; height: 6px; border-radius: 50%; background: #FFB86B; }
.av-c.me { border-color: rgba(var(--lift-rgb), 0.85); background: rgba(var(--lift-rgb), 0.3); }
.av-c.me.them { border-color: rgba(107,219,143,0.9); background: rgba(107,219,143,0.28); }
.av-c.me.them::after { background: #6BDB8F; }
.av-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.av-row input { flex: 1 1 180px; min-width: 0; padding: 8px 10px; border-radius: 8px; border: 1px solid #354561; background: rgba(6,11,24,0.8); color: #E8EEFC; font: inherit; font-size: 13px; }
.av-key { color: #98a9c4; font-size: 11px; display: inline-flex; align-items: center; gap: 5px; }
.av-key .k { display: inline-block; width: 11px; height: 11px; border-radius: 3px; border: 1.5px solid; }
.av-key .k.me { border-color: rgba(var(--lift-rgb), 0.85); background: rgba(var(--lift-rgb), 0.3); }
.av-key .k.them { border-color: rgba(255,184,107,0.8); }
.av-key .k.both { border-color: rgba(107,219,143,0.9); background: rgba(107,219,143,0.28); margin-left: 4px; }
.av-msg { color: var(--sap-soft); font-size: 12px; }
.av-kick { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; padding-top: 10px; border-top: 1px dashed rgba(var(--line-rgb), 0.22); }
.av-lbl { color: #98a9c4; font-size: 10.5px; font-weight: 800; letter-spacing: 0.12em; }
.av-kick b.ok { color: #6BDB8F; } .av-kick b.wait { color: #FFB86B; }
.av-dim { color: #98a9c4; font-size: 12px; }
.av-more { color: var(--sap-soft); font-size: 12px; text-decoration: none; align-self: flex-start; }
@media (max-width: 520px) { .av-c { width: 38px; height: 32px; } .av-fold > summary { padding: 13px 14px; } .av-body { padding: 0 14px 16px; } .av-head b { font-size: 19px; } }

/* COLUMN CONTROLS (build 502) — static/tablectl.js on every table. */
.tc-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 8px; font-size: 12px; }
.tc-btn { font: inherit; font-size: 12px; font-weight: 700; color: #C6D2EE; background: rgba(10,18,38,0.7); border: 1px solid #354561; border-radius: 999px; padding: 5px 12px; cursor: pointer; }
.tc-btn:hover { border-color: var(--sap-soft); color: #FFF; }
.tc-btn:focus-visible, .tc-chip:focus-visible, .tc-th:focus-visible { outline: 2px solid var(--sap-soft); outline-offset: 1px; }
.tc-open[aria-expanded="true"] { border-color: var(--sap-soft); color: #FFF; }
.tc-chips { display: contents; }
.tc-chip { font: inherit; font-size: 12px; color: #E8EEFC; background: rgba(var(--lift-rgb), 0.22); border: 1px solid rgba(var(--lift-rgb), 0.6); border-radius: 999px; padding: 4px 10px; cursor: pointer; }
.tc-chip::after { content: " ×"; color: #98a9c4; }
.tc-count { color: var(--sap-soft); font-weight: 700; }
.tc-hint { color: #6f7f9c; font-size: 11px; margin-left: auto; }
.tc-form { flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px; border: 1px solid #354561; border-radius: 10px; background: rgba(6,11,24,0.8); }
.tc-form[hidden], .tc-form [hidden] { display: none !important; }
.tc-form select, .tc-form input { font: inherit; font-size: 13px; color: #E8EEFC; background: rgba(10,18,38,0.9); border: 1px solid #354561; border-radius: 8px; padding: 6px 8px; min-width: 0; }
.tc-form select { max-width: 100%; }
.tc-num { display: inline-flex; align-items: center; gap: 6px; }
.tc-num input { width: 80px; }
.tc-q { flex: 1 1 140px; }
.tc-dash { color: #98a9c4; }
.tc-th { cursor: pointer; user-select: none; white-space: nowrap; }
.tc-th:hover { color: #FFF; }
.tc-th.tc-on { color: var(--sap-soft); }
.tc-th[data-tcdir="desc"]::after { content: " ▼"; font-size: 0.8em; }
.tc-th[data-tcdir="asc"]::after { content: " ▲"; font-size: 0.8em; }
@media (max-width: 520px) { .tc-hint { display: none; } }

/* ---- YOUR TICKETS (build 513): one card per locked ticket ---- */
.tk-wrap { margin-bottom: 22px; }
.tk-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.tk-title { font-family: var(--f-cond, inherit); font-weight: 800; font-style: italic; font-size: 20px; color: var(--good); }
.tk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(330px, 100%), 1fr)); gap: 12px; }
.tk { padding: 13px 16px; border-radius: 14px; background: linear-gradient(135deg, rgba(20,60,35,0.26), var(--surface));
      box-shadow: inset 0 0 0 1px rgba(107,219,143,0.45), 0 0 26px rgba(107,219,143,0.08); }
.tk-cancelled { opacity: 0.6; background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); }
.tk-lost { background: linear-gradient(135deg, rgba(70,20,26,0.24), var(--surface)); box-shadow: inset 0 0 0 1px rgba(255,142,142,0.35); }
.tk-won { box-shadow: inset 0 0 0 1px rgba(255,217,138,0.6), 0 0 30px rgba(255,217,138,0.12); }
.tk-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tk-kind { font-size: 10.5px; font-weight: 800; letter-spacing: 0.14em; color: var(--ink-strong); }
.tk-money { margin-left: auto; text-align: right; }
.tk-money b { display: block; font-size: 18px; font-weight: 800; font-style: italic; color: var(--ink-strong); }
.tk-money small { font-size: 10.5px; font-weight: 800; }
.tk-win { color: var(--good); }
.tk-miss { color: var(--bad); }
.tk-legs { margin-top: 6px; }
.tk-leg { display: flex; align-items: baseline; gap: 8px; padding: 5px 0; border-bottom: 1px dashed rgba(107,219,143,0.15); font-size: 12.5px; flex-wrap: wrap; }
.tk-lab { font-weight: 800; color: var(--ink-strong); }
.tk-lab.hit { color: var(--good); } .tk-lab.miss { color: var(--bad); }
.tk-px { margin-left: auto; color: var(--gold); font-size: 11px; font-variant-numeric: tabular-nums; }
.tk-st { font-size: 9.5px; font-weight: 800; letter-spacing: 0.1em; }
.tk-st.wait { color: var(--amber); } .tk-st.hit { color: var(--good); } .tk-st.miss { color: var(--bad); } .tk-st.void { color: var(--ink-dim, #8a96b3); }
.tk-foot { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.tk-foot .btn { padding: 6px 14px; font-size: 11.5px; }
.tk-msg { font-size: 11px; flex-basis: 100%; }


/* ===========================================================================
   THE IDENTITY KIT (build 587) -- app/look.py
   Everything below keys off tokens that file derives, or body classes it
   emits. An untouched league has none of them and renders as before.
   =========================================================================== */
/* the wallpaper behind every page: fixed, faint, under everything */
.league-wall {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-size: cover; background-position: center top; background-repeat: no-repeat;
  opacity: 0.14;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 40%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 0%, #000 40%, transparent 100%);
}
/* the strip: who you are, under the bar, on every page */
.league-id {
  background: rgba(var(--ground-rgb), 0.6);
  border-bottom: 1px solid var(--line);
  background-size: cover; background-position: center;
}
.league-id-in {
  display: flex; align-items: center; gap: 14px; color: var(--ink);
  max-width: var(--container); margin: 0 auto; padding: 10px var(--pad); width: 100%; box-sizing: border-box;
}
.league-id-crest { width: 36px; height: 36px; object-fit: contain; border-radius: 8px; flex: 0 0 auto; }
.league-id-text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.league-id-name {
  font-weight: 800; font-style: italic; font-size: 22px; line-height: 1; letter-spacing: 0.5px;
  color: var(--ink-strong); text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.league-id-motto { font-size: 12px; color: var(--sap-pale); margin-top: 3px; }
.league-id-sport {
  font-family: var(--f-cond); font-weight: 700; font-size: 12px; letter-spacing: 1.2px;
  color: var(--ink-muted); border: 1px solid var(--line-2); border-radius: 999px; padding: 4px 10px; white-space: nowrap;
}
a.league-id-in:hover .league-id-name { color: var(--sap-pale); }
/* BUILD 592: the banner, whole, on the league home. A real <img> at 8:3 in a
   centred column capped at 1040px (so 390px tall at most): at 1440 and
   wider the hero stops there instead of running 1344px wide and 504px tall
   and pushing the page's own actions below the fold. Height is always
   width x 0.375 -- no fixed height, no clipping parent -- so every edge of
   the picture shows. object-fit: contain is for the fallback: a league
   with no banner of its own shows its wallpaper here, and a wallpaper
   uploaded since 591 is 16:9 -- it shows whole, centred, not stretched to
   8:3. A real banner is 8:3 and fills the box exactly. The identity row
   under it is aligned to the same column. */
.league-hero { --hero-max: 1040px; background: rgba(var(--ground-rgb), 0.6); padding: 16px var(--pad) 0; }
.league-hero-in { max-width: var(--hero-max); margin: 0 auto; }
.league-hero-img { display: block; width: 100%; height: auto; aspect-ratio: 1600 / 600; object-fit: contain; }
.league-id-home .league-id-in { max-width: calc(1040px + 2 * var(--pad)); padding-top: 12px; padding-bottom: 12px; }
.league-id-home .league-id-crest { width: 48px; height: 48px; }
.league-id-home .league-id-name { font-size: 30px; }
@media (max-width: 640px) { .league-id-name { font-size: 18px; } .league-id-home .league-id-name { font-size: 24px; } .league-id-sport { display: none; } }

/* FLAT: solid plates, no glass, no glow */
body.look-flat .panel, body.look-outlined .panel {
  background: var(--surface-solid); border: 1px solid var(--line-2); box-shadow: none;
}
body.look-flat .tile, body.look-outlined .tile,
body.look-flat .card, body.look-outlined .card {
  background: var(--surface-solid); box-shadow: none;
}
body.look-flat .masthead, body.look-outlined .masthead,
body.look-flat .wire, body.look-outlined .wire {
  background: var(--ground-2); backdrop-filter: none; -webkit-backdrop-filter: none;
}
body.look-flat .btn, body.look-outlined .btn { box-shadow: none; background-image: none; }
/* OUTLINED: flat, with the rules turned up */
body.look-outlined .panel, body.look-outlined .tile, body.look-outlined .card { border-color: var(--line-3); }
body.look-outlined .tbl th { border-bottom-color: var(--line-3); }
body.look-outlined .tbl td { border-bottom-color: var(--line-2); }


/* ===========================================================================
   THE SPORT MARK (build 589). Always on, beside the league's name in the
   masthead and in the switch list, independent of the league's own colours.
   Madden is the site's sapphire; 2K is the hardwood orange it already wore.
   =========================================================================== */
/* BUILD 593: the mark is the sport's own frame from the flair art, and the
   pill around it is fixed to the site's own sapphire (the stylesheet's root
   values, so a default league looks exactly as before) -- it read the
   league's look tokens until now, which put a crimson league's crimson on
   the one thing meant to say which game this is regardless of colours. */
.lg-sport {
  display: inline-flex; align-items: center; gap: 3px; flex: 0 0 auto;
  font-size: 11px; line-height: 1; padding: 2px 6px 2px 4px; border-radius: 999px;
  border: 1px solid rgba(91, 139, 255, 0.45); background: rgba(47, 107, 255, 0.14);
}
.lg-sport i { font-style: normal; font-family: var(--f-cond); font-weight: 700; font-size: 10px; letter-spacing: 0.12em; color: #C3D4FF; }
.lg-sport-img { display: block; width: 24px; height: 24px; object-fit: contain; flex: 0 0 auto; margin: -4px 0; }
.lg-row .lg-sport-img { width: 22px; height: 22px; margin: -3px 0; }
.lg-sport-nba2k { border-color: rgba(255, 155, 74, 0.5); background: rgba(255, 155, 74, 0.14); }
.lg-sport-nba2k i { color: #FFB37A; }
.lg-row .lg-sport { padding: 1px 4px; border: 0; background: none; }
/* a hairline of the sport's colour along the top of the bar on the 2K side */
body[data-sport="nba2k"] .masthead { box-shadow: inset 0 2px 0 0 rgba(255, 155, 74, 0.55); }
@media (max-width: 700px) { .lg-sport i { display: none; } }

/* ===========================================================================
   FLAIR (build 593) -- the nameplate, the emblem row and the avatar ring.
   Markup in templates/_flair.html; what is worn comes from app/flair.py.
   The art carries its own colours, so nothing here reads the league's look.
   =========================================================================== */
.fl-plate {
  position: relative; display: block; width: 100%; max-width: 420px;
  container-type: inline-size; line-height: 1;
}
.fl-plate-big { max-width: 560px; }
.fl-plate-art { display: block; width: 100%; height: auto; }
/* The open panel runs from about 28% to 91% of the plate's width and sits a
   little below the middle; the medallion owns the left. */
.fl-plate-name {
  position: absolute; left: 28%; right: 9%; top: 53%; transform: translateY(-50%);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font-family: var(--f-cond); font-weight: 800; font-style: italic;
  text-transform: uppercase; letter-spacing: 0.02em; color: #FFFFFF;
  font-size: clamp(12px, 6.4cqw, 40px);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 0 10px rgba(0, 0, 0, 0.55);
}
.fl-emblems { display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto; vertical-align: middle; }
.fl-emblems img { display: block; width: 32px; height: 32px; object-fit: contain; }
.fl-emblems-sm img { width: 22px; height: 22px; }
/* The ring is drawn OVER the picture (a team frame sits under it): every
   ring in the art has the same round opening, 25% to 75% of its size. */
.fl-ring { position: relative; display: inline-block; flex: 0 0 auto; }
.fl-ring-pic {
  position: absolute; left: 24%; top: 24%; width: 52%; height: 52%; border-radius: 50%;
  overflow: hidden; background: #1B2340; display: flex; align-items: center; justify-content: center;
}
.fl-ring-pic img { width: 100%; height: 100%; object-fit: cover; }
.fl-ring-pic b { font-family: var(--f-cond); font-style: italic; font-size: 13px; color: #C6D2EE; }
.fl-ring-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none; }

/* ---- Build 614: chat as a command center ---------------------------- */
.ssc-head .ssc-find { background: none; border: 0; color: var(--ink-muted); cursor: pointer; font-size: 13px; margin-left: auto; }
.ssc-extra { flex: none; max-height: 42%; overflow-y: auto; }
.ssc-extra:empty { display: none; }
.ssc-live, .ssc-pins, .ssc-games, .ssc-sched, .ssc-block, .ssc-findbox { padding: 6px 11px; border-bottom: 1px solid var(--line-2); }
.ssc-livecard { display: block; font-size: 11.5px; font-weight: 800; color: #FF8E8E; text-decoration: none; padding: 3px 0; }
.ssc-pin { font-size: 11.5px; color: var(--ink-muted); padding: 2px 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ssc-games { display: flex; gap: 6px; overflow-x: auto; }
.ssc-game { flex: none; background: rgba(var(--line-rgb), 0.12); border: 1px solid transparent; color: var(--ink-muted);
  border-radius: 999px; padding: 5px 10px; font: inherit; font-size: 11.5px; cursor: pointer; min-height: 32px; }
.ssc-game.on { border-color: var(--sap); color: var(--ink-strong); }
.ssc-game.mine { color: var(--ink-strong); }
.ssc-n { display: inline-block; min-width: 16px; padding: 0 4px; border-radius: 999px; background: var(--sap); color: #FFF; font-size: 10px; }
.ssc-n.at { background: var(--hot); }
.ssc-setting { display: block; font-size: 11px; color: var(--ink-muted); padding: 4px 11px; }
.ssc-kick { font-size: 12px; font-weight: 700; color: var(--ink-strong); }
.ssc-slot { font-size: 11.5px; padding: 2px 0; }
.ssc-sched .ssc-row, .ssc-cform .ssc-row { margin-top: 5px; flex-wrap: wrap; }
.ssc-sched input, .ssc-cform input, .ssc-cform select, .ssc-findq { flex: 1 1 120px; min-width: 0; background: rgba(10,18,38,0.9);
  border: 1px solid var(--line-2); color: var(--ink); border-radius: 7px; padding: 7px 9px; font: inherit; font-size: 12px; }
.ssc-sched button, .ssc-cform button, .ssc-bp button, .ssc-cact { background: rgba(var(--lift-rgb), 0.2); border: 1px solid rgba(var(--lift-rgb), 0.45);
  color: var(--ink-strong); border-radius: 7px; padding: 6px 10px; font: inherit; font-size: 11.5px; cursor: pointer; min-height: 32px; }
.ssc-block summary { font-size: 12px; font-weight: 700; cursor: pointer; padding: 3px 0; }
.ssc-bp { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; font-size: 11.5px; padding: 4px 0; }
.ssc-bp span { flex: 1 1 160px; min-width: 0; }
.ssc-offer { font-size: 11.5px; color: var(--sap-pale); }
.ssc-tool { flex: none; background: rgba(var(--line-rgb), 0.12); border: 1px solid var(--line-2); color: var(--ink-strong);
  border-radius: var(--r-sm); min-width: 36px; min-height: 36px; font: inherit; font-weight: 800; cursor: pointer; }
.ssc-cmd, .ssc-reply { margin-bottom: 6px; }
.ssc-reply { font-size: 11.5px; color: var(--sap-pale); }
.ssc-reply button { background: none; border: 0; color: var(--ink-dim); cursor: pointer; font: inherit; }
.ssc-clist { display: flex; flex-direction: column; max-height: 220px; overflow-y: auto; border: 1px solid var(--line-2); border-radius: 8px; }
.ssc-cpick { text-align: left; background: none; border: 0; border-bottom: 1px solid var(--line-2); color: var(--ink); padding: 8px 10px; font: inherit; font-size: 12px; cursor: pointer; }
.ssc-cpick small { color: var(--ink-dim); }
.ssc-cform { font-size: 12px; }
.ssc-wrong { color: #FFD98A; font-size: 11.5px; margin-top: 4px; }
.ssc-only { color: var(--ink-dim); font-size: 10.5px; margin-top: 4px; font-style: italic; }
.ssc-acts { margin-left: auto; display: inline-flex; gap: 2px; align-items: center; }
.ssc-acts .ssc-del { margin-left: 4px; }
.ssc-act { background: none; border: 0; color: var(--ink-dim); cursor: pointer; font-size: 12px; padding: 0 4px; min-height: 24px; }
.ssc-act:hover { color: var(--ink-strong); }
.ssc-edited { color: var(--ink-dim); font-style: italic; }
.ssc-msg.pinned { border-left-color: #FFD98A; }
.ssc-quote { font-size: 11px; color: var(--ink-muted); border-left: 2px solid var(--line-2); padding-left: 6px; margin-top: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ssc-reacts { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 3px; }
.ssc-reacts:empty { display: none; }
.ssc-rx, .ssc-rxpick { background: rgba(var(--line-rgb), 0.14); border: 1px solid transparent; border-radius: 999px; padding: 1px 7px;
  font: inherit; font-size: 11.5px; color: var(--ink); cursor: pointer; min-height: 26px; }
.ssc-rx.mine { border-color: var(--sap); }
.ssc-rxbox { display: flex; gap: 4px; margin-top: 4px; }
.ssc-result { margin-top: 5px; padding: 8px 10px; border-radius: 8px; border: 1px solid rgba(107,219,143,0.4); background: rgba(107,219,143,0.07); }
.ssc-result.bad { border-color: rgba(255,90,90,0.4); background: rgba(255,90,90,0.07); }
.ssc-result.private { border-style: dashed; }
.ssc-ctitle { font-weight: 800; color: var(--ink-strong); font-size: 12.5px; }
.ssc-camt { font-family: var(--f-cond); }
.ssc-cline { font-size: 12px; color: var(--ink); margin-top: 2px; }
.ssc-cacts { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.ssc-clink { display: inline-block; margin-top: 5px; font-size: 11.5px; color: var(--sap-pale); }
.ssc-hit { display: block; width: 100%; text-align: left; background: none; border: 0; color: var(--ink); font: inherit; font-size: 11.5px;
  padding: 5px 0; cursor: pointer; border-bottom: 1px solid var(--line-2); }
.ssc-hit small { color: var(--ink-dim); }

/* ---- Build 615: the GIF picker ---- */
.ssc-gifbox { max-height: 240px; overflow-y: auto; margin-top: 6px; }
.ssc-gifs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.ssc-gifpick { padding: 0; border: 0; background: none; cursor: pointer; border-radius: 6px; overflow: hidden; min-height: 60px; }
.ssc-gifpick img { width: 100%; height: 90px; object-fit: cover; display: block; }
.ssc-gifq { flex: 1 1 auto; background: rgba(10,18,38,0.9); border: 1px solid var(--line-2); color: var(--ink); border-radius: 7px; padding: 7px 9px; font: inherit; font-size: 12px; }
