/* THE CARD -- tonight's three to five bets, at the top of Gameday.
 *
 * ONE THING IS BIG ON EACH CARD and it is the instruction. Everything else
 * on the card is deliberately quieter than it: the rank, the label, the
 * teams, the reasoning, the note. A reader scanning the page at arm's length
 * should be able to read the bets and nothing else, which is the layout
 * answer to "it just looks like a lot of random numbers".
 *
 * COLOUR DISCIPLINE, unchanged from the rest of the system:
 *   --v-money   price advantage only. NOT used here -- a card is not a claim
 *               that the price is good, and colouring it that way would say
 *               so without a sentence to back it up.
 *   --v-live    analytical / live. The label chips use it at low saturation.
 *   --v-warn    caution, pending, unavailable. SPLIT uses it, because SPLIT
 *               means our own numbers disagree and the reader should weigh
 *               it lower -- that is exactly "know this".
 *   --v-win     settled wins only. Never here; nothing on this card is
 *               settled yet.
 */

.card2lede {
  margin: 0 0 var(--sp-8);
  font-family: var(--font-body);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--text-3);
  max-width: 62ch;
}
.card2lede--mute { color: var(--text-mute); font-size: 13.5px; }
/* Amber, per the system's own rule: know this. Not red -- a stale price is
   a caution, not a booked loss. */
.card2lede--warn { color: var(--v-warn-label); }

.card2grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: var(--sp-8);
  margin-bottom: var(--sp-10);
}
/* One column below 900px: these cards are read, not compared side by side,
   and a two-up grid at 420px makes the instruction line wrap twice. */
@media (max-width: 899px) {
  .card2grid { grid-template-columns: 1fr; gap: var(--sp-7); }
}

.card2 {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  padding: var(--sp-8) var(--sp-8) var(--sp-7);
  --r: 12px;
  background:
    linear-gradient(180deg, var(--v-fill-a), var(--v-fill-b)),
    var(--v-s1);
  border: 1px solid var(--v-edge);
}
/* The accent is a single hairline down the leading edge -- enough to sort
   the cards by strength at a glance, not enough to read as a status light. */
.card2::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--card2-accent, var(--v-edge));
}
.card2--strong { --card2-accent: var(--v-live); }
.card2--lean { --card2-accent: var(--v-live-2); }
.card2--slight { --card2-accent: rgba(255, 255, 255, .22); }
.card2--split { --card2-accent: var(--v-warn-2); }

.card2__top {
  display: flex;
  align-items: baseline;
  gap: var(--sp-5);
  flex-wrap: wrap;
}
.card2__rank {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: .04em;
  color: var(--text-2);
}
/* THE KNOWLEDGE GRADE (src/analysis/grade.py) now lives inside "View
 * breakdown" (GC-1, 2026-09-16), never in the visible top row -- a
 * reader's first look is the bet, not a letter grade. Mono, boxed, no
 * colour for A and B beyond the page's own text, muted for C and D -- a
 * letter is a fact about what we hold, not a call, so it gets no money
 * red. */
.card2__grade {
  padding: 2px 7px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .08em;
  color: var(--text-hi);
  border: 1px solid var(--edge-1);
  cursor: help;
}
.card2__grade--c, .card2__grade--d { color: var(--text-mute); }
.card2bd__grade { display: flex; align-items: baseline; gap: var(--sp-4); margin-top: var(--sp-5); }
.card2bd__grade-why { font-size: 13.5px; color: var(--text-3); }
.card2__time {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: .12em;
  color: var(--text-dim);
  white-space: nowrap;
}

/* THE KIND TAG (mergedBetCard) rides the top row beside the rank -- kept
 * here unchanged, still appended into .card2__top. */

/* CONDITION CHIPS -- the real facts behind a pick (lineup posted,
 * starters confirmed, provisional/locked), in words, from the shared
 * .chip classes (components.css), never a colour-only signal. */
.card2__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
}

/* PRICE AT BOOK · PUBLISHED TIME -- the second line of the compact
 * anatomy, one step down from the bet sentence. */
.card2__book {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: .04em;
  color: var(--text-3);
}

/* THE ONE VISIBLE REASON SENTENCE -- the rest of `why` moves into the
 * breakdown; this line reads slightly larger than the breakdown's own
 * reasoning so it still reads as the headline reason, not a footnote. */
.card2__whyline--lead {
  font-size: 15px;
  color: var(--text-hi);
  border-top: none;
  padding-top: 0;
}

/* RANK 1 -- the flagship pick on the card gets the --edge-hi treatment
 * (a brighter leading edge), never a louder label -- there is no more
 * STRONG/LEAN/SPLIT chip to carry that distinction. */
.card2--rank1 { --card2-accent: var(--edge-hi, var(--v-live)); }
.card2--rank1::before { width: 3px; }

/* THE BREAKDOWN -- everything a reader does not need at a glance: the
 * market and our own numbers, the break-even the price demands, the rest
 * of the reasoning, the alternate bet, the knowledge grade and its
 * legend, and the link to the full matchup. */
.card2bd__figures { display: flex; flex-direction: column; gap: var(--sp-3); margin: 0 0 var(--sp-5); }
.card2bd__figure {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: .02em;
  color: var(--text-2);
}
.card2bd__why {
  margin: 0 0 var(--sp-4);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-3);
}

/* THE INSTRUCTION. The largest type on the screen, on purpose. */
.card2__bet {
  margin: 0;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 34px;
  font-weight: 800;
  line-height: .98;
  letter-spacing: -.01em;
  color: var(--text-hi);
}
@media (max-width: 899px) {
  .card2__bet { font-size: 30px; }
}

.card2__matchup {
  display: flex;
  align-items: baseline;
  gap: var(--sp-5);
  flex-wrap: wrap;
}
.card2__teams {
  font-family: var(--font-display);
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: .1em;
  color: var(--text-2);
}
.card2__book {
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: .1em;
  color: var(--text-faint);
}

/* PLAYER PROPS ON THE CARD, 2026-09-12 -- one meta line per prop pick
   (player, team, matchup, book) in place of the game picks' two-piece
   .card2__matchup, since a prop pick names a person as well as a game. */
.card2__meta {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: .06em;
  color: var(--text-dim);
}

.card2__why {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--v-edge);
}
.card2__whyline {
  margin: 0;
  font-family: var(--font-body);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--text-2);
}

/* The alternative bet. Deliberately quieter than the instruction above it
   -- same family, two steps down in weight -- because it is offered and not
   recommended, and a reader skimming must not come away with two picks on
   one game. */
.card2__alt {
  display: flex;
  align-items: baseline;
  gap: var(--sp-5);
  padding: var(--sp-4) var(--sp-5);
  border-left: 2px solid var(--v-edge);
  background: rgba(255, 255, 255, .02);
}
.card2__alt-label {
  flex: none;
  font-family: var(--font-display);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .2em;
  color: var(--text-dim);
}
.card2__alt-body {
  display: flex;
  align-items: baseline;
  gap: var(--sp-4);
  flex-wrap: wrap;
}
.card2__alt-bet {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: .01em;
  color: var(--text-2);
}
.card2__alt-book {
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: .1em;
  color: var(--text-dim);
}

/* THE MERGED CARD (web/js/card.js's mergedBetCard), 2026-09-14 -- ALL bets
   ranked together, game picks, totals and player props alike, not just
   moneylines. Same card2 shell as every card above; the only new visual is
   this small kind tag riding the top row beside the rank and label, so a
   reader can tell a MONEYLINE from a TOTAL or a PLAYER PROP without
   reading the bet sentence first. Neutral border, no fill -- it is a
   category, not a call. */
.card2__kind {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .1em;
  color: var(--text-dim);
  border: 1px solid var(--v-edge, var(--edge-1));
  padding: 2px 6px;
  white-space: nowrap;
}
/* LINEUP NOT POSTED used to be a trailing chip here (`.card2__kind--warn`),
   appended LAST in `.card2__top` -- 11px, the smallest text on the card,
   and one more flex item `.card2__top`'s own wrap could drop onto a second
   line and lose entirely. An Opus checker caught it 2026-09-14: not
   unmissable. It is now its own line above the bet sentence, in
   `.card2lede--warn` above (web/js/card.js's `lineupNotPostedWarning`) --
   no chip variant needed here any more. */

.card2__meaning {
  margin: 0;
  font-family: var(--font-body);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--text-mute);
}
.card2--split .card2__meaning { color: var(--v-warn-label); }

.card2__actions { margin-top: auto; padding-top: var(--sp-4); }

/* PHONE FLOOR (GC-5, 2026-09-16): no text inside a compact pick card
 * computes under 15px at <=899px -- raised here rather than lowered
 * anywhere at desktop width. */
@media (max-width: 899px) {
  .card2lede,
  .card2lede--mute,
  .card2__rank,
  .card2__book,
  .card2__meta,
  .card2bd__figure,
  .card2bd__why,
  .card2bd__grade-why,
  .card2note__body,
  .card2note__body--mute,
  .card2rec__meta,
  .card2rec__body,
  .card2rec__link { font-size: 15px; }
  .card2__whyline { font-size: 15px; }
}

/* THE RECORD. Sits between the picks and the standing note, because it is
   the reason to believe the picks and it belongs where a reader is still
   looking. Wins and losses in the same weight -- a record that renders its
   wins larger is a record making an argument. */
.card2rec {
  --r: 10px;
  padding: var(--sp-7) var(--sp-8);
  margin-bottom: var(--sp-7);
  background: var(--v-s1);
  border: 1px solid var(--v-edge);
}
.card2rec__label {
  display: block;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .2em;
  color: var(--text-mute);
  margin-bottom: var(--sp-4);
}
.card2rec__figures {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: var(--sp-6);
  flex-wrap: wrap;
}
.card2rec__wl {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 800;
  letter-spacing: .02em;
  color: var(--text-hi);
}
.card2rec__meta {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: .06em;
  color: var(--text-3);
}
.card2rec__body {
  margin: var(--sp-4) 0 0;
  font-family: var(--font-body);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--text-mute);
  max-width: 68ch;
}
.card2rec__warn {
  margin: var(--sp-4) 0 0;
  font-family: var(--font-body);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--v-warn-label);
}
.card2rec__link {
  display: inline-block;
  margin-top: var(--sp-5);
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: .06em;
  color: var(--v-live-label);
}
.card2rec__link:hover { color: var(--v-live); }

/* The standing note. Rendered on every card set, never dismissible, and
   never smaller than the reasoning above it -- it is the sentence that keeps
   the whole surface honest. */
.card2note {
  --r: 10px;
  padding: var(--sp-7) var(--sp-8);
  background: var(--v-s2);
  border: 1px solid var(--v-edge);
}
.card2note__label {
  display: block;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .2em;
  color: var(--text-mute);
  margin-bottom: var(--sp-4);
}
.card2note__body {
  margin: 0 0 var(--sp-4);
  font-family: var(--font-body);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--text-3);
  max-width: 72ch;
}
.card2note__body--mute { color: var(--text-mute); font-size: 13.5px; margin-bottom: 0; }
.card2note__warn {
  margin: var(--sp-5) 0 0;
  font-family: var(--font-body);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--v-warn-label);
}

.card2empty {
  padding: var(--sp-10) var(--sp-9);
  --r: 12px;
  background: var(--v-s1);
  border: 1px solid var(--v-edge);
}
.card2empty__label {
  display: block;
  font-family: var(--font-display);
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: .2em;
  color: var(--v-warn-label);
  margin-bottom: var(--sp-5);
}
.card2empty__body {
  margin: 0 0 var(--sp-8);
  font-family: var(--font-display);
  font-style: italic;
  font-size: 26px;
  font-weight: 700;
  line-height: 1.05;
  color: var(--text-hi);
  max-width: 24ch;
}
.card2empty__actions { display: flex; gap: var(--sp-5); flex-wrap: wrap; }

/* ---------------------------------------------------------------------
 * THE RECORD PAGE (#/record-card, web/js/cardrecord.js) -- the full
 * receipts ledger, as opposed to the one-paragraph .card2rec summary
 * above. Lives in this file rather than screens.css because it is
 * thematically and functionally part of THE CARD, not a sibling screen:
 * same ledger, same wording rules, same reader.
 *
 * TOKEN DIALECT MATCHES THE REST OF THIS FILE, not screens.css's: prose
 * and neutral figures use the V1 --text-* scale (.card2rec__wl,
 * .card2note__body do the same above), and only the win/loss/warn SIGNAL
 * colours reach into the V2 --v-* family, because V1 never defined a
 * settled-win green or a caution amber at all.
 *
 * .ov2-table / .ov2-table-wrap (screens.css) and .day-settle (screens.css)
 * are reused as-is for the day-by-day table, so a WIN/LOSS/PUSH chip can
 * never look different between this page and the paper ledger's own
 * Results screen. The one new chip variant below, .day-settle--void, is a
 * state the paper ledger never needed (a postponed game, not an
 * undecided position).
 * ------------------------------------------------------------------- */

.crp-screen { padding: var(--sp-9) var(--gutter-desktop) var(--sp-15); display: flex; flex-direction: column;
  gap: var(--sp-9); }
.crp-intro { margin: 0; max-width: 68ch; font-size: 14.5px; line-height: 1.55; color: var(--text-3); }

.crp-headline { padding: var(--sp-9) var(--sp-10); }
.crp-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: var(--sp-8); }
.crp-stat { display: flex; flex-direction: column; gap: var(--sp-3); }
.crp-stat__label {
  font-family: var(--font-display); font-size: 12.5px; font-weight: 800; letter-spacing: .14em;
  color: var(--text-mute);
}
/* SAME size, SAME weight for every stat here, wins and losses included --
   this file's own module comment above and cardrecord.js's docstring both
   say why. Only the FIGURE's colour carries meaning (pos/neg/warn/absent);
   nothing here is made visually louder than anything else. */
.crp-stat__figure {
  font-family: var(--font-display); font-style: italic; font-size: clamp(24px, 2.6vw, 32px);
  font-weight: 800; line-height: 1; color: var(--text-hi);
}
.crp-stat__figure--pos { color: var(--v-win-lit); }
/* A loss is a fact, not a warning to flash red at the reader (GC-5,
 * 2026-09-16) -- neutral, same treatment as the settled LOSS chip. */
.crp-stat__figure--neg { color: var(--text-hi); }
.crp-stat__figure--warn { color: var(--v-warn-label); }
.crp-stat__figure--absent { font-style: normal; color: var(--text-ghost); }

.crp-voids { margin: 0; max-width: 68ch; font-size: 13.5px; line-height: 1.5; color: var(--text-mute); }

.crp-chain { padding: var(--sp-7) var(--sp-8); }
.crp-chain__label {
  display: block; font-family: var(--font-display); font-size: 13px; font-weight: 800;
  letter-spacing: .18em; color: var(--text-mute); margin-bottom: var(--sp-4);
}
.crp-chain__body { margin: 0; max-width: 72ch; font-size: 14.5px; line-height: 1.55; color: var(--text-3); }
.crp-chain__warn { margin: 0; max-width: 72ch; font-size: 14.5px; line-height: 1.55; color: var(--v-warn-label); }
.crp-chain__detail { margin-top: var(--sp-4); font-size: 13px; color: var(--text-mute); }
.crp-chain__detail summary { cursor: pointer; }

.crp-days { display: flex; flex-direction: column; gap: var(--sp-8); }
.crp-day { padding: var(--sp-7); display: flex; flex-direction: column; gap: var(--sp-5); }
.crp-day__head { display: flex; align-items: baseline; gap: var(--sp-5); flex-wrap: wrap; }
.crp-day__date {
  font-family: var(--font-display); font-style: italic; font-size: 17px; font-weight: 800; color: var(--text-hi);
}
.crp-day__record { font-family: var(--font-mono); font-size: 14.5px; color: var(--text-2); }
.crp-day__voids { font-family: var(--font-mono); font-size: 13px; color: var(--v-warn-label); }
.crp-day__net { margin-left: auto; font-family: var(--font-mono); font-size: 14.5px; font-weight: 700; color: var(--text-2); }
.crp-day__net--pos { color: var(--v-win-lit); }
.crp-day__net--neg { color: var(--text-hi); }
.crp-day__hash {
  margin: 0; font-family: var(--font-mono); font-size: 12.5px; letter-spacing: .01em; color: var(--text-ghost);
  word-break: break-all;
}

/* V2 day: fills sit apart from the picks, under their own heading (cardrecord.js dayRows). */
.crp-day__group--fills { margin-top: var(--sp-4); padding-top: var(--sp-5); border-top: 1px dashed var(--v-edge, var(--edge-1)); }

.crp-pick-bet { display: flex; flex-direction: column; gap: 2px; max-width: 320px; }
.crp-pick-bet__text { font-size: 14.5px; font-weight: 600; color: var(--text-2); }
.crp-pick-bet__label { font-family: var(--font-mono); font-size: 12px; letter-spacing: .1em; color: var(--text-dim); }
/* PLAYER PROPS ON THE CARD, 2026-09-12 -- marks a prop row on the same
   table the game picks use (cardrecord.js's pickRow(pick, "prop")). Same
   size and weight as .crp-pick-bet__label; a border instead of colour so it
   reads as a category tag, not a result. */
.crp-pick-bet__kind {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .12em;
  color: var(--text-dim);
  border: 1px solid var(--v-edge, var(--edge-1));
  padding: 1px 5px;
}
.crp-pick-result { white-space: nowrap; }
.crp-pick-reason, .crp-pick-score {
  margin: 3px 0 0; font-family: var(--font-mono); font-size: 12.5px; color: var(--text-mute); white-space: normal;
}
.crp-figure--pos { color: var(--v-win-lit); }
.crp-figure--neg { color: var(--text-hi); }

/* VOID -- grey/outline like PUSH rather than amber: a void is not a
   caution about this PAGE, it is a fact about a game that did not finish.
   Amber here would visually cry wolf on what is, most nights, a routine
   postponement. */
.day-settle--void {
  background: rgba(255, 255, 255, .07); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .2); color: var(--text-3);
}

.crp-disclaimer { margin: 0; max-width: 72ch; font-size: 13.5px; line-height: 1.55; color: var(--text-mute); }

@media (max-width: 899px) {
  .crp-screen { padding: var(--sp-7) var(--gutter-mobile) var(--sp-13); gap: var(--sp-7); }
  .crp-stats { grid-template-columns: repeat(2, 1fr); gap: var(--sp-6); }
  .crp-headline { padding: var(--sp-7); }
  .crp-day__net { margin-left: 0; }

  /* UNDO screens.css's "V2-23 mobile spec" rule for THIS table only. That
     rule is a BARE `.ov2-table` selector (table-layout:fixed, columns 2/3
     forced to 56px, column 4 hidden outright) written for the odds
     board's specific book/price layout -- and, being unscoped, it silently
     hits every other reuse of .ov2-table too. Found 2026-09-10 by looking
     at this page at 375px: column 4 here is BOOK, which is exactly the
     kind of thing a "receipts" page cannot let quietly vanish on a phone.
     Higher specificity than the original (two classes vs. one) so this
     wins regardless of stylesheet order. Scrolls instead, via the SAME
     .ov2-table-wrap overflow-x:auto every .ov2-table already carries --
     this just stops fighting it with a forced 100%-fixed width first. */
  .crp-day .ov2-table { table-layout: auto; width: auto; min-width: 600px; }
  .crp-day .ov2-table th:nth-child(4), .crp-day .ov2-table td:nth-child(4) { display: table-cell; width: auto; }
  .crp-day .ov2-table th:nth-child(2), .crp-day .ov2-table th:nth-child(3),
  .crp-day .ov2-table td:nth-child(2), .crp-day .ov2-table td:nth-child(3) { width: auto; }
}

/* A PHONE SHOWS THE BET AND WHAT HAPPENED WITHOUT A SIDEWAYS SCROLL.
   Measured 2026-10-01 at 390px: the bet column took 260 of the 326 visible
   pixels, so the result column ran 34px past the edge (the final score
   under "Won" / "Lost" was clipped) and the price was off-screen. The bet
   wraps in a narrower column instead; book and return are still there, one
   swipe to the right. Nothing is hidden. */
@media (max-width: 520px) {
  .crp-day .ov2-table { min-width: 520px; }
  .crp-day .ov2-table .crp-pick-bet { max-width: 150px; }
  .crp-day .ov2-table th, .crp-day .ov2-table td { padding-left: var(--sp-4); padding-right: var(--sp-4); }
}

/* =====================================================================
 * THE CALENDAR (web/js/cardrecord.js's `calendar`)
 *
 * Asked for directly: a month grid anyone can click through to see the
 * verifiable wins. Three day states that must be distinguishable at a
 * glance and without relying on colour alone -- a graded day carries its
 * W-L as text, a pending day says PENDING, an empty day carries nothing.
 * ===================================================================*/
.crp-calwrap { display: flex; flex-direction: column; gap: var(--sp-7); }
.crp-cal__legend {
  margin: 0; max-width: 68ch; font-size: 14.5px; line-height: 1.55;
  color: var(--text-3);
}
.crp-cal { display: flex; flex-direction: column; gap: var(--sp-5); }
.crp-cal__title {
  margin: 0; font-size: 15px; font-weight: 800; letter-spacing: .14em;
  text-transform: uppercase; color: var(--text-2);
}
.crp-cal__grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 6px;
}
.crp-cal__dow {
  font-size: 12px; font-weight: 800; letter-spacing: .12em;
  color: var(--text-5); text-align: center; padding-bottom: 2px;
}
.crp-cal__pad { min-height: 62px; }
.crp-cal__day {
  min-height: 62px; padding: 6px 7px; display: flex; flex-direction: column;
  gap: 2px; border: 1px solid var(--line, rgba(255,255,255,.08));
  background: rgba(255,255,255,.015);
}
.crp-cal__num { font-size: 12px; font-weight: 700; color: var(--text-5); }
.crp-cal__figure {
  font-family: var(--font-display, inherit); font-weight: 800;
  font-size: 17px; line-height: 1.1; color: var(--text-hi);
}
.crp-cal__note {
  font-size: 12px; font-weight: 700; letter-spacing: .06em;
  color: var(--text-4);
}
.crp-cal__day--empty { opacity: .32; }
.crp-cal__day--pending { border-color: rgba(255,255,255,.16); }
.crp-cal__day--graded { background: rgba(255,255,255,.04); }
/* Colour REINFORCES the W-L already written in the cell; it never carries
   the meaning alone. */
.crp-cal__day--pos { border-color: var(--pos, #2fbf71); }
.crp-cal__day--neg { border-color: var(--neg, #e5484d); }
.crp-cal__note--pos { color: var(--pos, #2fbf71); }
.crp-cal__note--neg { color: var(--neg, #e5484d); }
.crp-cal__day--link { cursor: pointer; }
.crp-cal__day--link:hover,
.crp-cal__day--link:focus-visible {
  background: rgba(255,255,255,.08); outline: none;
}
/* Where a calendar click lands, so the jump is visible rather than silent. */
.crp-day--flash { outline: 2px solid var(--accent, #35c3f3); outline-offset: 2px; }

@media (max-width: 640px) {
  /* "CHECK THIS PRICE YOURSELF" is a 375px-wide nowrap button inside a
     card that clips overflow: on a phone its last word was cut off
     (measured 2026-09-12, right edge at 408px of 375). Fill the card and
     let it wrap. */
  .card2__actions .btn {
    width: 100%; box-sizing: border-box; white-space: normal;
    text-align: center; padding: 13px 16px; font-size: 15px; letter-spacing: .1em;
  }
  .crp-cal__grid { gap: 4px; }
  .crp-cal__day, .crp-cal__pad { min-height: 54px; }
  .crp-cal__day { padding: 5px 4px; }
  .crp-cal__figure { font-size: 15px; }
  /* A 375px phone gives each square about 46px. At the desktop size the
     units line ran past the edge and "+0.54u" lost its u -- a clipped
     number on the page whose whole job is that the numbers are checkable. */
  .crp-cal__note { font-size: 11px; letter-spacing: 0; }
  .crp-cal__num { font-size: 11px; }
}
