/* Friar Breaks — visual identity
   ============================================================================
   Sampled from the logo artwork itself (Friar Breaks.jpg), which supersedes the
   earlier numbers taken from a compressed video frame:

     #582D00  the brown of the plate     (48.7% of the mark's own pixels)
     #FDBD04  the gold of the border     (31.6%)
     #FCFAE0  the cream of the "Breaks" script
     #F0DBBC  the friar's skin tone
     #331A01  the dark shadow behind the script

   The first version of this file used #542A02 and #F5C20E, sampled from the stream
   overlay in the pptx. Those were close but they were a JPEG of a video of the mark;
   these come from the mark.

   The San Diego Padres' official pair (#2F241D brown, #FFC425 gold) is the same
   scheme and was used as a sanity check. Where they differ this follows the mat:
   the stream brown is warmer and more saturated than the Padres' near-black brown,
   and the gold is fractionally deeper than theirs.

   The browns below are a RAMP, not the single #582D00. A whole interface painted in
   the mat's brown is too light to read cream text against for long, so the surfaces
   run darker and #582D00 survives as the mid-tone used for rules and the field motif.

   Every text colour here was measured against its background. The lowest is
   cream-faint at 6.84:1 on the page and 5.97:1 on a card, both above the 4.5:1 that
   WCAG AA asks for body text; cream itself is 17.85:1. Nothing here is decorative to
   the point of being unreadable, which matters most on the claims sheet during a
   live break.
   ========================================================================== */

:root{
  /* Surfaces: darkest at the back, lifting toward the reader. */
  --brown-950:#1A0F05;   /* page */
  --brown-900:#241505;   /* sunken: table stripes, inputs */
  --brown-850:#2E1B07;   /* card */
  --brown-800:#3A2208;   /* raised: buttons, chips */
  --brown-700:#4C2D0B;   /* rules and borders */
  --brown-600:#6B4415;   /* hover borders */
  --brown-field:#582D00; /* the brown of the plate, from the logo artwork */

  /* Gold: the stripe colour, plus one lighter and one deeper. */
  --gold:#FDBD04;
  --gold-hi:#FFD24A;
  --gold-lo:#C79A0B;
  --gold-soft:#F0DBBC;   /* the friar's skin tone, the logo's soft neutral */
  --gold-deep:#4A3306;   /* the accent as a SURFACE: pending pills, warning panels */

  /* Ink. */
  --cream:#FCFAE0;
  --cream-dim:#D9CFA8;
  --cream-faint:#A99B72;
  --ink-on-gold:#1A0F05;

  /* Status. Warm-shifted so they sit in the brown world instead of on top of it. */
  --ok:#7FD3A0;
  --ok-deep:#173A25;     /* ok as a SURFACE, the way --gold-deep is for the accent */
  --warn:#FDBD04;
  --bad:#F09A90;

  --radius:9px;
  --plate:polygon(0 0, 100% 0, 100% 55%, 50% 100%, 0 55%);  /* home plate */
}

*{box-sizing:border-box}
body{
  margin:0; background:var(--brown-950); color:var(--cream);
  font:15px/1.55 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  /* A very faint plate-shaped wash behind the page, echoing the mat without
     competing with anything on top of it. */
  background-image:radial-gradient(ellipse 900px 520px at 50% -140px,
                   rgba(84,42,2,.55), transparent 70%);
  background-repeat:no-repeat;
}
a{color:var(--gold-hi);text-decoration-color:rgba(245,194,14,.35);text-underline-offset:2px}
a:hover{text-decoration-color:var(--gold)}

/* --- header ------------------------------------------------------------- */
header.top{
  display:flex;align-items:center;gap:16px;padding:10px 20px;
  background:linear-gradient(180deg,var(--brown-field),var(--brown-900));
  border-bottom:2px solid var(--gold);
}
header.top .brand{display:flex;align-items:center;gap:10px;text-decoration:none}
/* The real mark, cut out of the supplied artwork. This replaced a CSS home plate with
   a system-cursive "Breaks" — a decent stand-in, but the actual script, the plate and
   the swinging friar are the identity and no font stack was going to reproduce them.
   The white page behind the original was removed by flood-filling from the corners
   rather than keying on white, because the script lettering is white too and a colour
   key would have eaten it. */
/* Big enough that "FRIAR" is legible. At 38px the block caps above the script turned
   to mush and the mark read as an anonymous blob. */
.brandmark{height:46px;width:auto;display:block}
header.top nav{margin-left:auto;display:flex;gap:15px;align-items:center;flex-wrap:wrap}
header.top nav a{color:var(--cream-dim);text-decoration:none;font-size:13.5px}
header.top nav a:hover{color:var(--gold-hi)}

main{max-width:1120px;margin:0 auto;padding:24px 20px 64px}
h1{font-size:24px;margin:0 0 4px;letter-spacing:-.2px}
h2{font-size:17px;margin:26px 0 10px;color:var(--cream)}
.sub{color:var(--cream-faint);font-size:14px;margin:0 0 18px}

/* --- surfaces ----------------------------------------------------------- */
.card{
  background:var(--brown-850);border:1px solid var(--brown-700);
  border-radius:var(--radius);padding:16px;margin-bottom:14px;
}
table{width:100%;border-collapse:collapse;font-size:14px}
th,td{text-align:left;padding:8px 9px;border-bottom:1px solid var(--brown-700);vertical-align:middle}
th{color:var(--gold-soft);font-weight:700;font-size:11.5px;text-transform:uppercase;letter-spacing:.7px}
tbody tr:hover{background:rgba(84,42,2,.35)}

/* --- controls ----------------------------------------------------------- */
input,select,textarea,button{
  font:inherit;color:var(--cream);background:var(--brown-900);
  border:1px solid var(--brown-700);border-radius:6px;padding:7px 9px;
}
input:focus,select:focus,textarea:focus{outline:2px solid var(--gold);outline-offset:-1px}
button{cursor:pointer;background:var(--brown-800);transition:border-color .12s,filter .12s}
button:hover{border-color:var(--gold-lo)}
button.primary{background:var(--gold);color:var(--ink-on-gold);border-color:var(--gold);font-weight:750}
button.primary:hover{filter:brightness(1.08)}
button.danger{border-color:#6B2F27;color:var(--bad);background:var(--brown-900)}
button.danger:hover{border-color:var(--bad)}
button:disabled{opacity:.42;cursor:not-allowed}
label{display:block;font-size:11.5px;color:var(--cream-faint);margin-bottom:4px;
  text-transform:uppercase;letter-spacing:.7px}
.row{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end}
.row>div{flex:1;min-width:130px}

/* --- chips and messages -------------------------------------------------- */
.pill{display:inline-block;padding:2px 9px;border-radius:999px;font-size:11px;
  font-weight:750;text-transform:uppercase;letter-spacing:.6px}
.pill.open,.pill.paid{background:var(--ok-deep);color:var(--ok)}
.pill.draft{background:var(--brown-800);color:var(--cream-faint)}
.pill.live,.pill.claimed{background:var(--gold-deep);color:var(--gold)}
.pill.closed{background:#3A1E1B;color:var(--bad)}
.muted{color:var(--cream-dim)} .dim{color:var(--cream-faint)}
.ok{color:var(--ok)} .warn{color:var(--warn)} .bad{color:var(--bad)}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px}
.err{background:#3A1E1B;border:1px solid #6B2F27;color:#F5B5AC;padding:10px 12px;
  border-radius:6px;margin:10px 0;font-size:14px}
.notice{background:var(--ok-deep);border:1px solid #2C6344;color:#A6E3C0;padding:10px 12px;
  border-radius:6px;margin:10px 0;font-size:14px}

/* --- wizard -------------------------------------------------------------- */
.steps{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:18px}
.steps .s{flex:1;min-width:112px;padding:9px 11px;border-radius:8px;
  background:var(--brown-900);border:1px solid var(--brown-700);
  font-size:12.5px;color:var(--cream-faint)}
.steps .s .n{display:inline-block;width:19px;height:19px;line-height:19px;text-align:center;
  border-radius:50%;background:var(--brown-800);margin-right:7px;font-size:11px;color:var(--cream-dim)}
.steps .s.on{border-color:var(--gold);color:var(--cream);background:var(--brown-850)}
.steps .s.on .n{background:var(--gold);color:var(--ink-on-gold);font-weight:800}
.steps .s.done .n{background:var(--ok);color:#06210F}
.step{display:none} .step.on{display:block}
.opts{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:9px}
.opt{border:1px solid var(--brown-700);border-radius:8px;padding:11px 12px;cursor:pointer;
  background:var(--brown-900)}
.opt:hover{border-color:var(--gold-lo)}
.opt.sel{border-color:var(--gold);background:#3A2A08}
.opt .t{font-weight:700;font-size:14px}
.opt .d{color:var(--cream-faint);font-size:12.5px;margin-top:3px}

/* --- numbers ------------------------------------------------------------- */
.calc{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:9px;margin-top:12px}
.calc .k{background:var(--brown-900);border:1px solid var(--brown-700);border-radius:8px;padding:11px}
.calc .k .lbl{font-size:10.5px;color:var(--cream-faint);text-transform:uppercase;letter-spacing:.7px}
.calc .k .v{font-size:20px;font-weight:700;margin-top:3px}
.calc .k.hero{border-color:var(--gold);background:#3A2A08}
.calc .k.hero .v{color:var(--gold)}
.wizfoot{display:flex;gap:10px;margin-top:18px;padding-top:15px;border-top:1px solid var(--brown-700)}
.wizfoot .sp{margin-left:auto}

/* --- the selector -------------------------------------------------------- */
.teams{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:8px}
/* Selector cards are themed to the team: the frame at full strength, a colour band
   carrying the logo and the name, and a lightly tinted body.
   The split is not decoration, it is where the text is. Measured across all 124 teams:
     - body tint at 10%  -> faintest text 4.79:1, clears AA
     - body tint at 14%  -> 4.34:1, fails (worst case the Spurs' silver, which LIGHTENS
       the card rather than darkening it)
   So strong colour goes where there is no small text, and the band's ink is chosen per
   team — 105 take white, 19 take dark, and five colours are nudged a few percent until
   they clear 4.5:1. See data/team_colors.py band_for(). */
.team{
  border:2px solid var(--team, var(--brown-700));
  border-radius:9px; background:var(--brown-850);
  /* Ignored by anything without color-mix, which then keeps the flat card above. */
  background:color-mix(in srgb, var(--team, var(--brown-850)) 10%, var(--brown-850));
  transition:transform .1s, box-shadow .12s; overflow:hidden;
}
.team:hover{transform:translateY(-1px);box-shadow:0 3px 14px rgba(0,0,0,.4)}
.team.taken{opacity:.55;filter:saturate(.5)}
.team .band{
  display:flex;align-items:center;gap:9px;padding:7px 10px;
  background:var(--band, var(--brown-800)); color:var(--ink, var(--cream));
}
/* Every badge sits on a light chip. A drop-shadow halo was tried first and was not
   enough: the Yankees' navy on a navy band, the Padres' brown on brown and the Pirates'
   black on black all vanished completely, while the lighter badges looked fine — so the
   bug read as "some logos are missing" rather than "some logos are invisible". A logo
   is drawn to sit on white and cannot be recoloured per team, so the reliable answer is
   to give it white to sit on. */
.team .band .logo-chip{
  flex:0 0 30px; width:30px; height:30px; border-radius:50%;
  background:#FFFFFF; display:flex; align-items:center; justify-content:center;
  box-shadow:0 0 0 1px rgba(0,0,0,.18);
}
.team .band .logo{width:24px;height:24px;object-fit:contain;display:block}
.team .band .n{font-weight:700;font-size:13.5px;line-height:1.2;flex:1}
/* The spot number after a draw. Kept, small, because people still call spots by number
   during a live break even once the team is what matters. */
.spot-tag{
  font-weight:600;font-size:10.5px;letter-spacing:.4px;opacity:.72;
  padding:1px 5px;border-radius:4px;background:rgba(0,0,0,.22);white-space:nowrap;
}
.team .body .owner{margin-top:2px;color:#3E372F}
.team .band .p{font-weight:750;font-size:14px;white-space:nowrap}
/* teams.color_secondary is stored but deliberately not rendered: the card already
   carries the primary in three places (frame, band, ring) and a second team colour on
   top stops reading as an accent and starts reading as noise. It is there for whoever
   wants it later.

   The lower half of a card is white, so the Claim button reads as a physical control
   rather than an outline floating on a tinted panel. Everything in here therefore has to
   flip to dark ink — cream on white is 1.5:1 and would have been unreadable.
   The ring is the team's colour, but NOT always the raw one: seven of the 124 are too
   light to see against white (the Spurs' silver at 1.60:1, the Bruins' gold at 1.73),
   so ring_for() darkens those until they clear 3:1 — what WCAG asks of a non-text
   interface element. A ring nobody can see is just a missing button. */
.team .body{padding:10px 11px 12px;background:#FFFFFF}
.team .o{font-size:12px;color:#5B534A;margin-top:0}
/* 4.74:1 on the claim box. The obvious grey (#8A8178) sits at 3.82:1 — under AA, and
   this is the line that says a spot's team has not been drawn yet, which is exactly the
   thing a buyer needs to read before committing money. */
.team .body .dim{color:#79726A}
.team .body button{
  width:100%;margin-top:9px;padding:8px;
  /* Filled with the band colour and lettered in the band's ink, so the button reads as
     the same object as the team's banner above it. That pairing is already guaranteed
     to clear 4.5:1 by band_for() — the ink is chosen per team precisely so this works
     on all 124, including the nineteen that need dark lettering.
     The 3px ring stays, in ring_for()'s colour: for most teams it matches the fill and
     simply reads as a solid button, and for the seven whose colour is too light against
     white it is a shade darker and gives the button an edge it would otherwise lack. */
  background:var(--band, var(--brown-800));
  border:3px solid var(--ring, var(--brown-700));
  color:var(--ink, var(--cream));
  font-weight:750;letter-spacing:.3px;font-size:14px;
}
.team .body button:hover{filter:brightness(1.12)}
.team .body button:active{filter:brightness(.94)}
.team.taken .body{background:#EFEAE3}
.bar{height:7px;background:var(--brown-900);border-radius:4px;overflow:hidden;margin:8px 0;
  border:1px solid var(--brown-700)}
.bar i{display:block;height:100%;background:linear-gradient(90deg,var(--gold-lo),var(--gold))}

/* Password fields carry a confirm box and a reveal toggle. A mistyped password on the
   admin create form makes an account nobody can get into; on the change and reset forms
   it locks you out of your own. Both are silent at the moment they happen and only
   surface later, at the worst time. */
.pw-wrap{position:relative}
.pw-wrap input{width:100%;padding-right:52px}
.pw-wrap .reveal{
  position:absolute;right:6px;top:50%;transform:translateY(-50%);
  background:none;border:0;color:var(--cream-faint);font-size:11.5px;
  text-transform:uppercase;letter-spacing:.6px;cursor:pointer;padding:4px 6px;
}
.pw-wrap .reveal:hover{color:var(--gold-hi)}
.pw-match{font-size:12px;margin-top:5px;min-height:16px}

/* The break header, themed to the league the break is for. A mixer blends both leagues
   left to right, so an MLB+NFL break announces itself before a word is read.
   No league badge: the workbook had none, and drawing an approximation of a league's
   trademarked mark would be worse than the plain wordmark used here. Drop real files
   into static/leagues/ and wire them if they turn up.
   Ink is chosen by the same band_for() rule the cards use, so the title always carries
   on whatever the league's colour is. */
.hero{
  border-radius:12px; padding:20px 22px 18px; margin-bottom:18px;
  background:var(--brown-850);
  background:linear-gradient(135deg, var(--a, var(--brown-field)),
                             var(--b, var(--brown-800)) 78%);
  color:var(--hink, var(--cream));
  border:1px solid rgba(0,0,0,.35);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.14);
}
.hero h1{margin:6px 0 3px; color:inherit}
.hero .hero-sub{margin:0 0 12px; font-size:13.5px; opacity:.92}
.hero .hero-note{
  margin:0 0 12px; font-size:13.5px; padding:7px 11px; border-radius:7px;
  background:rgba(0,0,0,.24);
}
.hero-marks{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
/* League marks sit on a light chip for the same reason the team badges do, and it is
   worse here: the hero IS the league's colour, so an MLB mark on MLB navy and an NHL
   mark on NHL black are the logo painted on itself. Checked by compositing each mark
   over its own hero colour before wiring this — all four lost their shape. */
.league-chip{
  display:inline-flex;align-items:center;justify-content:center;
  height:38px;padding:5px 11px;border-radius:8px;background:#FFFFFF;
  box-shadow:0 1px 3px rgba(0,0,0,.3);
}
.league-chip img{height:26px;width:auto;display:block}
.hero-league{
  font-size:11px; font-weight:800; letter-spacing:2.4px; text-transform:uppercase;
  padding:3px 9px; border-radius:5px;
  background:rgba(255,255,255,.16); border:1px solid rgba(255,255,255,.28);
}
/* The fill bar sits ON the hero now, so it needs its own contrast rather than the
   page's — a translucent white track reads on any league colour. */
.hero .bar{background:rgba(0,0,0,.3);border-color:rgba(255,255,255,.2)}
.hero .bar i{background:rgba(255,255,255,.85)}

/* "Create an account" is the one nav item a signed-out visitor is looking for, so it
   is the only one that reads as a button rather than a link. */
.navcta{
  color:var(--gold-hi) !important; border:1px solid var(--gold-lo);
  padding:4px 10px; border-radius:6px;
}
.navcta:hover{background:var(--gold); color:var(--ink-on-gold) !important;
  border-color:var(--gold)}

.signup-cta{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  flex-wrap:wrap; border-color:var(--gold-lo);
}
.signup-cta .sub{margin:0; font-size:13.5px}

/* The breaks listing carries each break's league colours, the same as its own page.
   Before this every break was an identical brown card and the only way to tell an MLB
   break from an NFL one was to read the label. */
.breaklist{display:grid;grid-template-columns:repeat(auto-fill,minmax(310px,1fr));gap:12px}
.breakcard{
  display:block;text-decoration:none;color:inherit;border-radius:12px;overflow:hidden;
  border:1px solid var(--brown-700);background:var(--brown-850);
  transition:transform .1s, box-shadow .12s;
}
.breakcard:hover{transform:translateY(-2px);box-shadow:0 6px 20px rgba(0,0,0,.45)}
.breakcard-head{
  padding:14px 16px 15px; color:var(--hink, var(--cream));
  background:var(--brown-field);
  background:linear-gradient(135deg, var(--a, var(--brown-field)),
                             var(--b, var(--brown-800)) 78%);
}
.breakcard-title{font-size:17px;font-weight:700;margin-top:9px;line-height:1.25}
.breakcard-sub{font-size:12.5px;opacity:.9;margin-top:2px}
.breakcard-body{padding:12px 16px 14px}
.breakcard-fill{font-size:13px;color:var(--cream-dim);margin-top:2px}
/* On the listing the bar sits on the card, not on a league colour, so it keeps the
   site's gold rather than the translucent white the hero needs. */
.breakcard .bar{background:var(--brown-900);border-color:var(--brown-700)}
.breakcard .bar i{background:linear-gradient(90deg,var(--gold-lo),var(--gold))}

/* Sticky "review and pay" bar. Fixed to the bottom because the selector is long — on a
   30-team break the way to proceed would otherwise be below the fold at the exact moment
   someone has decided to buy. */
.cartbar{
  position:fixed;left:0;right:0;bottom:0;z-index:40;
  display:flex;align-items:center;justify-content:center;gap:16px;flex-wrap:wrap;
  padding:11px 20px;background:var(--brown-900);
  border-top:2px solid var(--gold);box-shadow:0 -6px 22px rgba(0,0,0,.45);
}
.cartbar span{font-size:14px}
/* The bar covers the end of the page, so give the content room to clear it. */
body:has(.cartbar) main{padding-bottom:96px}

/* QR codes: the SVG carries its own mm dimensions, which render tiny. Override to
   something a phone camera can actually read across a table. */
.qr{margin:10px auto 6px;width:172px;height:172px;background:#FFFFFF;
  border-radius:8px;padding:7px;display:flex;align-items:center;justify-content:center}
.qr svg{width:100%;height:100%;display:block}

/* --- brand page ---------------------------------------------------------- */
.swatches{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:10px}
.sw{border:1px solid var(--brown-700);border-radius:8px;overflow:hidden;background:var(--brown-850)}
.sw .chip{height:64px}
.sw .meta{padding:8px 10px;font-size:12px}
.sw .meta b{display:block;font-size:12.5px}
.sw .meta code{color:var(--cream-faint);font-size:11.5px}

/* --- the draw, step by step ---------------------------------------------
   Two columns on a desktop, one on a phone. The lists are shown in full: the page
   exists so somebody can follow the draw, and a summarised list is exactly what it
   is meant to replace. */
.steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
       gap:16px;align-items:start;margin-top:16px}
.steps h2{margin:0 0 10px}
/* NOT `.step`: that is the wizard's, and it is `display:none` until the step is the
   one being filled in. Reusing the name here rendered all eight cards into the page
   and showed none of them. */
.dstep{margin-bottom:12px}
.dstep-h{font-size:12px;letter-spacing:.06em;text-transform:uppercase;
         color:var(--gold);margin-bottom:8px}
.dstep-list{margin:0;padding-left:26px;line-height:1.6;font-size:13.5px;
            color:var(--cream-dim)}
.dstep-list li::marker{color:var(--cream-faint);font-variant-numeric:tabular-nums}

/* --- past breaks --------------------------------------------------------
   A thumbnail grid. auto-fill rather than auto-fit so a channel with two videos does
   not stretch them across the whole page like a hero. */
.replays{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));
         gap:14px;margin-top:16px}
.replay{display:block;text-decoration:none;color:var(--cream);
        border:1px solid var(--brown-700);border-radius:var(--radius);overflow:hidden;
        background:var(--brown-850)}
.replay img{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover}
.replay-noimg{aspect-ratio:16/9;display:flex;align-items:center;justify-content:center;
              background:var(--brown-900);color:var(--gold-lo);font-size:34px}
.replay-meta{padding:10px 12px;display:flex;flex-direction:column;gap:3px}
.replay-meta b{font-size:14px;line-height:1.35}
.replay-meta .dim{font-size:12.5px}
.replay:hover,.replay:focus-visible{border-color:var(--gold-lo)}

/* The play facade. A button, not a link: it does something on this page rather than
   going somewhere, and the difference matters to whoever is using a keyboard. */
.replay-play{
  display:block;position:relative;width:100%;padding:0;border:0;background:none;
  cursor:pointer;line-height:0;border-radius:0;
}
.replay-play:focus-visible{outline:2px solid var(--gold);outline-offset:-2px}
.replay-badge{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:52px;height:52px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:rgba(0,0,0,.62);color:var(--cream);font-size:19px;line-height:1;
  padding-left:3px;  /* the glyph is optically left-heavy inside a circle */
  transition:background .12s,transform .12s;
}
.replay-play:hover .replay-badge{background:var(--gold);color:var(--ink-on-gold)}
.replay-play:hover .replay-badge,.replay-play:focus-visible .replay-badge{
  transform:translate(-50%,-50%) scale(1.06);
}
.replay span.replay-noimg{display:flex;width:100%}
/* Same box the thumbnail occupied, so swapping one for the other moves nothing. */
.replay iframe{display:block;width:100%;aspect-ratio:16/9;height:auto;border:0}
@media (prefers-reduced-motion:reduce){
  .replay-badge,.replay-play:hover .replay-badge{transition:none;transform:translate(-50%,-50%)}
}

/* The line under a datetime field saying what it means in the reader's own zone.
   The fields used to be labelled "(UTC)" and to mean it, which asks a breaker to do
   arithmetic at eight in the evening with a camera running. */
.tzhint{font-size:12px;color:var(--gold-lo);margin-top:5px;min-height:16px}

/* The Post Office suggested a change and the buyer has to choose. Deliberately not
   styled as an error — the suggestion is usually right, and it is a question. */
.confirmaddr{border-left:3px solid var(--gold-lo);margin:14px 0}
.addrdiff{width:auto;font-size:13.5px}
.addrdiff th{text-transform:capitalize;color:var(--cream-faint);font-weight:600;
             padding-right:16px}
.addrdiff td{padding-right:16px}
.addrdiff td.ok{color:var(--ok)}

/* The eBay market column. The figure is a button because clicking it fills the box
   price — the fastest route through a hundred products with no SRP. */
.market{font-size:13px}
.market .dim{font-size:11.5px;margin-top:2px}
button.linkish{background:none;border:none;padding:0;color:var(--gold);
               font:inherit;font-weight:700;cursor:pointer;text-decoration:underline;
               text-underline-offset:2px}
button.linkish:hover{color:var(--gold-hi)}

/* The payment preview on Setup: what a buyer actually sees, with real money in it.
   A payment screen described in prose is one nobody checks until a customer is
   looking at it. */
.payopts{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px}
.payopt{border:1px solid var(--brown-700);border-radius:var(--radius);padding:12px;
        background:var(--brown-900)}
.payopt-head{display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;
             align-items:baseline;margin-bottom:9px;font-size:13px}
.payopt-qr svg{width:100%;height:auto;background:#fff;border-radius:6px;padding:6px}
.payopt-none{font-size:13px;color:var(--cream-dim);line-height:1.5}

/* The post writer, under the break sheet. */
.modal-post{padding:0 14px 14px;border-top:1px solid var(--brown-700)}
.modal-post[hidden]{display:none}
.modal-post label{margin-top:11px}
.modal-post textarea{width:100%;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
                     font-size:12.5px;line-height:1.55;resize:vertical}
.modal-post input{width:100%}
.postbar{display:flex;gap:7px;flex-wrap:wrap;align-items:center;padding-top:12px}
.postbar button{padding:4px 11px;font-size:12.5px}
.postbar button.on{background:var(--gold);color:var(--ink-on-gold);
                   border-color:var(--gold)}
.postbar .dim{margin-left:auto;font-size:12px;font-variant-numeric:tabular-nums}

/* A saved shipping address on the account screen. */
.addrrow{display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;
         padding:11px 0;border-bottom:1px solid var(--brown-700)}
.addrrow:last-child{border-bottom:none}
.addrrow .pill{margin-left:6px}

/* --- the pay clock ------------------------------------------------------
   Sits above the page on every buyer view, because the moment it matters is the moment
   they have navigated away from the break they claimed on. */
.paybar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
        padding:9px 20px;background:var(--brown-800);
        border-bottom:1px solid var(--brown-700);font-size:13.5px}
.paybar-clock{font-size:19px;font-weight:700;color:var(--gold);
              font-variant-numeric:tabular-nums;min-width:62px}
.paybar-text{color:var(--cream-dim)}
.paybar a{margin-left:auto}
.paybar.urgent{background:#4A1A12;border-bottom-color:#7A2A1E}
.paybar.urgent .paybar-clock{color:var(--bad)}

/* --- the draw controls --------------------------------------------------
   A row of its own rather than cells in the action grid. Those cells are sized for a
   button plus a sentence; a label, a number box and a hint stacked inside one came out
   a different height from its neighbours, and the label wrapped while the box did not. */
.drawrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
         gap:12px 16px;align-items:end;margin-top:14px;padding-top:13px;
         border-top:1px solid var(--brown-700)}
.drawfield{display:flex;flex-direction:column;gap:6px;min-width:0}
.drawfield label{margin:0;font-size:12.5px;line-height:1.35;color:var(--cream-dim);
                 white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.drawfield input{width:100%}
.drawnote{grid-column:1/-1;margin:0;font-size:12.5px;line-height:1.5;
          color:var(--cream-faint)}

/* --- the break-sheet viewer ---------------------------------------------
   Shown before it is saved, so a wrong title is caught here instead of in a
   Downloads folder. */
.modal{position:fixed;inset:0;z-index:60;display:flex;align-items:center;
       justify-content:center;padding:20px}
.modal[hidden]{display:none}
.modal-back{position:absolute;inset:0;background:rgba(10,6,2,.78)}
.modal-box{position:relative;max-width:min(94vw,1000px);max-height:92vh;display:flex;
           flex-direction:column;background:var(--brown-850);
           border:1px solid var(--brown-600);border-radius:var(--radius);
           box-shadow:0 18px 60px rgba(0,0,0,.6)}
.modal-head{display:flex;align-items:center;gap:12px;padding:12px 14px;
            border-bottom:1px solid var(--brown-700)}
.modal-head b{font-size:14px}
.modal-head button{margin-left:auto;padding:3px 10px;line-height:1.2}
.modal-body{padding:14px;overflow:auto;background:var(--brown-900)}
.modal-body img{display:block;max-width:100%;height:auto;margin:0 auto;
                border-radius:6px}
.modal-foot{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:12px 14px;
            border-top:1px solid var(--brown-700);font-size:12.5px}
.modal-foot #sheetmsg{margin-left:auto;font-size:12.5px}

/* --- the countdown on a published, unopened break ------------------------
   Replaces the fill bar, which would otherwise read "0 of 30 taken" and say something
   misleading about a break nobody could have bought into yet. */
.countdown{display:flex;flex-direction:column;gap:2px;padding:2px 0 4px}
.cd-label{font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;
          color:var(--cream-faint)}
.cd-clock{font-size:21px;font-weight:700;color:var(--gold);
          font-variant-numeric:tabular-nums}
.breaktime{margin-top:7px;font-size:12.5px;color:var(--cream-dim)}
.breaktime span{color:var(--cream);font-weight:600}
.pill.scheduled{background:var(--brown-800);color:var(--gold);
                border-color:var(--gold-lo)}

/* --- the quantity chooser -----------------------------------------------
   Replaces the grid on an undrawn Random break. It is one decision, so it gets one
   card and the decision sits in the middle of it. */
.chooser{margin-top:14px}
.ch-head{display:flex;justify-content:space-between;align-items:baseline;gap:12px;
         flex-wrap:wrap;font-size:17px}
.ch-head b{font-size:24px;color:var(--gold)}
.ch-price{font-size:19px;font-weight:700}
.ch-pick{display:flex;gap:11px;align-items:center;flex-wrap:wrap;margin-top:14px}
.ch-pick label{margin:0;white-space:nowrap}
.ch-pick select{width:auto;min-width:78px}
.ch-total{font-size:19px;font-weight:700;color:var(--gold);
          font-variant-numeric:tabular-nums}

/* --- break admin: the action area ---------------------------------------
   A grid, not a wrapping flex row, so that a control and the line explaining it can
   never be separated by a line break. auto-fit with a minimum means one column on a
   phone and as many as fit on a desktop, with no breakpoint to keep in step.

   The buttons stretch to their cell rather than sizing to their label: "Randomize"
   beside "Mark break complete" made a ragged row of five different widths, and on a
   phone a full-width target is easier to hit than a tidy one. */
.acts{display:grid;grid-template-columns:repeat(auto-fit,minmax(212px,1fr));
      gap:12px;margin-top:14px;align-items:start}
.act{display:flex;flex-direction:column;gap:6px}
.act button{width:100%}
.act .hint{font-size:12.5px;line-height:1.45;color:var(--cream-faint)}
.act .hint .mono{color:var(--cream-dim)}

/* The three views of a break. Each needs a sentence saying which one it is, and a
   sentence does not belong in a row of middot-separated links. */
.views{display:grid;grid-template-columns:repeat(auto-fit,minmax(212px,1fr));
       gap:10px;margin-top:16px;padding-top:15px;border-top:1px solid var(--brown-700)}
.views a{display:flex;flex-direction:column;gap:3px;padding:11px 13px;
         border:1px solid var(--brown-700);border-radius:var(--radius);
         background:var(--brown-900);text-decoration:none;color:var(--cream)}
.views a b{font-size:13.5px;color:var(--gold)}
.views a span{font-size:12.5px;line-height:1.45;color:var(--cream-faint)}
.views a:hover,.views a:focus-visible{border-color:var(--gold-lo);background:var(--brown-800)}

@media (max-width:640px){
  main{padding:16px 13px 48px}
  header.top{padding:9px 13px;gap:10px}
  header.top nav{gap:11px}
  .brandmark{height:36px}

  /* The schedule row: full-width stacked fields rather than four flex
     children fighting over one line. */
  .row>div{flex:1 1 100%}
}

/* --- the live-break screen ----------------------------------------------
   Read across a room, at a glance, while both hands are full. Everything here is
   bigger than the rest of the site on purpose: the failure this screen prevents is
   handing a card to the wrong person, and it is prevented by the name being legible
   from further away than a claims-sheet table row.

   The team's colour is a 6px edge, never a fill — the same rule as the selector cards.
   Measured there: a filled card drops cream text to about 3:1, and five of the 124
   teams are pale enough to invert it entirely. */
body.lv main{max-width:1480px}

.lv-head{display:flex;align-items:flex-start;gap:26px;flex-wrap:wrap;margin-bottom:12px}
.lv-head h1{font-size:28px}
.lv-counts{display:flex;gap:22px;margin-left:auto}
.lv-counts div{text-align:right}
.lv-counts b{display:block;font-size:30px;line-height:1;color:var(--gold);
             font-variant-numeric:tabular-nums}
.lv-counts small{color:var(--cream-faint);font-size:11.5px;letter-spacing:.04em;
                 text-transform:uppercase}
.lv-links{display:flex;gap:14px;align-self:center;font-size:14px}

.lv-filter{
  width:100%;font-size:20px;padding:13px 16px;margin:6px 0 14px;
  background:var(--brown-900);border:1px solid var(--brown-700);border-radius:var(--radius);
  color:var(--cream);
}
.lv-filter::placeholder{color:var(--cream-faint);font-size:17px}

.lv-rows{display:flex;flex-direction:column;gap:7px}
.lv-row{
  /* The team's colour arrives from the payload as an inline --band. An undrawn Random
     spot has no team and so sets nothing, which is exactly the case the fallback is
     for: without it the rule renders an empty custom property and the edge disappears
     rather than falling back to gold. */
  background:var(--brown-850);border:1px solid var(--brown-700);
  border-left:6px solid var(--band, var(--gold-lo));
  border-radius:var(--radius);padding:12px 16px;cursor:pointer;
}
/* The highlighted row is the one Enter acts on, so it is marked by a gold ring rather
   than a tint: a tint competes with the team's own colour edge, and on the pale teams
   it stopped reading as "selected" at all. */
.lv-row.on{border-color:var(--gold);box-shadow:inset 0 0 0 1px var(--gold)}
.lv-top{display:flex;align-items:center;gap:18px}

.lv-team{display:flex;align-items:center;gap:12px;min-width:0;flex:1}
.lv-team .n{font-size:26px;font-weight:750;letter-spacing:-.3px;line-height:1.15;
            overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lv-logo{
  width:40px;height:40px;flex:none;border-radius:7px;background:#fff;
  display:flex;align-items:center;justify-content:center;padding:3px;
}
.lv-logo img{max-width:100%;max-height:100%;object-fit:contain;display:block}
.lv-tag{color:var(--cream-faint);font-size:12.5px;font-family:ui-monospace,SFMono-Regular,
        Menlo,monospace;flex:none}

.lv-owner{display:flex;align-items:center;gap:10px;flex:none;text-align:right}
.lv-owner .who{font-size:24px;font-weight:700;color:var(--cream)}
.lv-owner .who.none{color:var(--cream-faint);font-weight:500;font-style:italic;font-size:19px}
.lv-unpaid{background:#4A3306;color:var(--gold);border-radius:999px;padding:3px 11px;
           font-size:12px;font-weight:700;white-space:nowrap}
.lv-unconfirmed{background:var(--brown-800);color:var(--cream-dim);border-radius:999px;
                padding:3px 11px;font-size:12px;white-space:nowrap}

.lv-hits{display:flex;flex-wrap:wrap;gap:7px;align-items:center;margin-top:10px;
         padding-top:10px;border-top:1px solid var(--brown-700)}
.lv-hit{display:inline-flex;align-items:center;gap:6px;background:var(--brown-900);
        border:1px solid var(--brown-700);border-radius:999px;padding:4px 6px 4px 13px;
        font-size:14.5px}
.lv-x{background:none;border:none;color:var(--cream-faint);font-size:16px;line-height:1;
      padding:0 5px;cursor:pointer}
.lv-x:hover{color:var(--bad)}
.lv-cardbox{
  flex:1;min-width:260px;font-size:16px;padding:8px 12px;
  background:var(--brown-900);border:1px solid var(--gold);border-radius:var(--radius);
  color:var(--cream);
}
.lv-help{color:var(--cream-faint);font-size:13px;margin-top:16px}
.lv-help b{color:var(--cream-dim);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}

/* --- the hit reel on the front page ---------------------------------------
   A frame, not a full-bleed banner. These are photographs of single cards, mostly
   portrait, taken on a phone under a desk lamp — they look like something on a wall
   and nothing like a hero image, so the frame is sized for the card and the mat around
   it does the work. */
.reel{margin:0 0 26px}
.reel-frame{
  position:relative;
  background:
    radial-gradient(ellipse 70% 60% at 50% 40%, rgba(253,189,4,.10), transparent 70%),
    var(--brown-900);
  border:1px solid var(--brown-700);
  border-top:3px solid var(--gold);
  border-radius:var(--radius);
  height:345px;
  display:flex;align-items:center;justify-content:center;
  overflow:hidden;
}
.reel-slide{
  display:none;margin:0;
  width:100%;height:100%;
  flex-direction:column;align-items:center;justify-content:center;gap:8px;
  padding:14px 58px 11px;
}
.reel-slide.on{display:flex}
/* contain, never cover: a cropped card is a card with its corner cut off, and the
   corner is where the numbering is. */
.reel-slide img{
  max-width:100%;max-height:100%;min-height:0;
  width:auto;height:auto;object-fit:contain;
  border-radius:5px;
  box-shadow:0 6px 22px rgba(0,0,0,.55);
}
.reel-slide figcaption{
  text-align:center;flex:none;line-height:1.35;
}
.reel-slide figcaption b{font-size:15px;display:block}
.reel-slide figcaption span{color:var(--cream-faint);font-size:12.5px}

.reel-arrow{
  position:absolute;top:50%;transform:translateY(-50%);
  width:38px;height:52px;padding:0;
  font-size:24px;line-height:1;color:var(--cream-dim);
  background:rgba(26,15,5,.62);border:1px solid var(--brown-700);border-radius:var(--radius);
}
.reel-arrow:hover{color:var(--gold);border-color:var(--gold-lo)}
.reel-arrow.prev{left:9px} .reel-arrow.next{right:9px}

.reel-dots{display:flex;gap:7px;justify-content:center;margin-top:11px}
.reel-dot{
  width:9px;height:9px;padding:0;border-radius:50%;
  background:var(--brown-700);border:1px solid var(--brown-600);
}
.reel-dot.on{background:var(--gold);border-color:var(--gold)}

@media (max-width:640px){
  .reel-frame{height:255px}
  .reel-slide{padding:14px 46px 12px}
}

/* --- the panel's Hits screen --------------------------------------------- */
.hit-add{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap}
.hit-add label{display:flex;flex-direction:column;gap:5px;font-size:12px;
               color:var(--cream-faint);letter-spacing:.03em;text-transform:uppercase}
.hit-add input{min-width:280px}
.hit-add select{min-width:210px}
.hit-thumb{
  width:74px;height:74px;object-fit:cover;border-radius:6px;
  border:1px solid var(--brown-700);display:block;
}

/* Clicking a card chip on the live screen corrects it, so it has to look clickable —
   the × beside it already is, and a chip where half is interactive and half is not is
   worse than one where neither is. */
.lv-hit-text{cursor:text;border-bottom:1px dotted transparent}
.lv-hit:hover .lv-hit-text{border-bottom-color:var(--cream-faint)}
.hit-edit-row td{background:var(--brown-900);border-top:none}

/* --- money going out ------------------------------------------------------
   The wizard mixes two kinds of number: what a break COSTS you and what it CHARGES a
   buyer. They look identical in a table and they are not remotely the same thing, and
   confusing them is the mistake that costs money on a live break rather than an awkward
   moment. Costs get their own tinted panel and a label saying so. */
.costbox{
  background:color-mix(in srgb, var(--brown-field) 22%, var(--brown-900));
  border:1px solid var(--brown-700);
  border-left:3px solid var(--gold-lo);
  border-radius:var(--radius);
  padding:14px 16px 16px;
  position:relative;
}
/* A flat fallback first, for anything without color-mix. Without it the panel is
   transparent and the whole distinction silently disappears. */
@supports not (background: color-mix(in srgb, red 50%, blue)){
  .costbox{background:#2A1A08}
}
.costbox-tag{
  font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--gold-lo);font-weight:700;margin-bottom:9px;
}
.costbox table{margin-top:2px}

/* The colour picker and its hex box, which are two views of one value. */
.pickrow{display:flex;gap:7px;align-items:center;margin-top:4px}
.pickrow input[type=color]{width:38px;height:30px;padding:2px;border-radius:6px;
                           background:var(--brown-900);border:1px solid var(--brown-700);
                           cursor:pointer}
.hexbox{width:96px;text-transform:uppercase;font-size:12.5px;padding:5px 7px}

/* --- a settings panel ----------------------------------------------------
   LIGHTER than the cards around it, where .costbox is darker. The two are doing
   opposite jobs and should not look alike: a cost box is money going out of the
   breaker's pocket and wants to feel heavy, while these are configuration — set once,
   changed rarely, and standing apart from the queue of parcels above them so that the
   page reads as "work to do" and then "the numbers behind it".

   Raised rather than tinted with a hue, because a second coloured panel next to the
   cost box would read as a second kind of warning. */
.setbox{
  background:color-mix(in srgb, var(--cream) 7%, var(--brown-800));
  border:1px solid var(--brown-600);
  border-left:3px solid var(--cream-faint);
}
@supports not (background: color-mix(in srgb, red 50%, blue)){
  .setbox{background:#4A3312}
}
.setbox-tag{
  font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--cream-faint);font-weight:700;margin-bottom:9px;
}
.setbox h2{color:var(--cream)}

/* --- the guides ----------------------------------------------------------
   Two long documents — one for the breaker, one for buyers — that people read once
   properly and then come back to for a single answer. So they carry a contents list
   that jumps, worked examples with real numbers rather than "e.g. $X", and diagrams
   that show the actual states this app has rather than a generic flow. */
.g-toc{
  display:flex;flex-wrap:wrap;gap:7px;margin:0 0 22px;
}
.g-toc a{
  font-size:13px;padding:5px 11px;border-radius:999px;text-decoration:none;
  background:var(--brown-850);border:1px solid var(--brown-700);color:var(--cream-dim);
}
.g-toc a:hover{border-color:var(--gold-lo);color:var(--gold-hi)}

.g-sec{scroll-margin-top:14px}
.g-sec h2{display:flex;align-items:baseline;gap:10px}
.g-sec h2 .n{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px;
  color:var(--gold-lo);flex:none;
}

/* A worked example. Real numbers, because "cost ÷ spots" is not the part anybody is
   stuck on — the part they are stuck on is what it looks like with a discount and tax
   in it. */
.g-sample{
  background:var(--brown-900);border:1px solid var(--brown-700);
  border-left:3px solid var(--ok);
  border-radius:var(--radius);padding:13px 15px;margin:14px 0;
}
.g-sample .lbl{
  font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--ok);font-weight:700;margin-bottom:8px;
}
.g-sample table{font-size:14px;width:auto;min-width:min(420px,100%)}
.g-sample td{padding:3px 18px 3px 0;border:none;vertical-align:baseline}
.g-sample td.v{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-variant-numeric:tabular-nums;text-align:right;
}
.g-sample tr.tot td{border-top:1px solid var(--brown-700);padding-top:7px;font-weight:700}

.g-fig{margin:16px 0;overflow-x:auto}
.g-fig svg{display:block;min-width:560px;max-width:100%;height:auto}
.g-fig figcaption{
  font-size:12.5px;color:var(--cream-faint);margin-top:7px;line-height:1.45;
}

/* A warning that is worth stopping for, not decoration. Used sparingly. */
.g-warn{
  background:#3A1E1B;border:1px solid #6B2F27;border-radius:var(--radius);
  padding:12px 14px;margin:14px 0;color:#F5C9C2;font-size:14.5px;
}
.g-warn b{color:#FFD9D2}

.g-keys{display:flex;flex-wrap:wrap;gap:8px 18px;margin:12px 0;font-size:14px}
.g-keys kbd{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;
  background:var(--brown-800);border:1px solid var(--brown-600);
  border-bottom-width:2px;border-radius:4px;padding:2px 7px;color:var(--cream);
}

/* ==========================================================================
   The demo bar.

   Every themed token, so a tenant demo in someone else's colours still looks like
   part of their site rather than a strip of somebody else's brand across the top.
   Sticky, because the one thing it has to do is be true on the page the reader is
   actually looking at — somebody arriving on a break sheet from a link needs to know
   what they are looking at as much as somebody who came in through the front door.
   ========================================================================== */
.demobar{
  position:sticky; top:0; z-index:60;
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  padding:10px 20px; font-size:13.5px; line-height:1.5;
  background:var(--gold-deep); color:var(--cream);
  border-bottom:1px solid var(--gold-lo);
}
.demobar b{color:var(--gold-hi)}
.demobar span{flex:1; min-width:260px; color:var(--cream-dim)}
.demobar form{margin:0}
.demobar button{padding:6px 12px; font-size:13px}
.demobar .demoback{color:var(--gold-hi); white-space:nowrap; text-decoration:none}
.demobar .demoback:hover{text-decoration:underline}
@media (max-width:640px){
  .demobar{padding:9px 14px; font-size:12.5px}
}

/* ==========================================================================
   The Overview's view bar.

   One row. Each button shows one section of the page and hides the rest — the page is
   long, and jumping to an anchor leaves you looking at six other subjects underneath
   the one you asked for. Each carries its own count, so the row also answers "is there
   anything waiting" without scrolling.
   ========================================================================== */
.viewbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:18px 0 22px}
.viewbar .viewbtn{
  display:inline-flex; align-items:center; gap:7px;
  padding:7px 13px; border-radius:7px; text-decoration:none; cursor:pointer;
  font:inherit; font-size:13.5px; line-height:1.2; white-space:nowrap;
  background:var(--brown-800); color:var(--cream);
  border:1px solid var(--brown-700);
}
.viewbar .viewbtn:hover{border-color:var(--brown-600); color:var(--gold-hi)}
/* The view you are looking at. Reads as pressed rather than merely hovered, because
   "which section am I seeing" has to be answerable from across the desk. */
.viewbar .viewbtn.on{
  background:var(--gold-deep); border-color:var(--gold-lo); color:var(--gold-hi);
}
.viewbar .viewbtn.plain{margin-left:auto; color:var(--cream-dim)}
/* The count. Tabular figures so a row of them does not jitter as they change. */
.viewbar .vn{
  font:600 11.5px/1 ui-monospace,SFMono-Regular,Menlo,monospace;
  font-variant-numeric:tabular-nums;
  padding:3px 6px; border-radius:5px;
  background:var(--brown-900); color:var(--cream-dim);
}
.viewbar .vn.warn{background:var(--gold-deep); color:var(--gold-hi)}

/* Sortable headings. The arrow is on the column being sorted and nowhere else. */
table.sortable thead th[data-sort]{cursor:pointer; user-select:none}
table.sortable thead th[data-sort]:hover{color:var(--gold-hi)}
table.sortable thead th.asc::after{content:" \25B2"; font-size:9px; color:var(--gold)}
table.sortable thead th.desc::after{content:" \25BC"; font-size:9px; color:var(--gold)}

@media (max-width:700px){
  .viewbar{gap:6px}
  .viewbar .viewbtn{padding:6px 10px; font-size:12.5px}
  .viewbar .viewbtn.plain{margin-left:0}
}
