/* =====================================================================
   LARGE PRINT MODE — the accessibility scale layer for the word/letter
   dailies (Wise Word Finder, Anagram Ladder, Daily Decode, Mini Crossword).

   Engaged by feed/large-print.js setting `data-large-print="on"` on <html>
   (and, pre-paint, by the inline bootstrap in functions/_render.js doc()).

   LOADING: an @import from BOTH feed.css and post.css, preloaded in the SSR
   shell alongside word-find.css and board.css. It is deliberately NOT loaded on
   demand: the toggle button sits in four game toolbars at NORMAL size too, and
   a lazily-injected sheet left it rendering as a bare default browser button
   until the mode was first switched on — and made switching the mode back off
   leave a 1px trace in those toolbars. ~2KB gzipped, in flight with the other
   two sheets, so it costs no extra round trip.

   DESIGN NOTES — why this is not a zoom:
   - No `zoom` / `transform:scale()`. Those blur text, break hit-testing, and
     would wreck word-find's capsule math (which measures getBoundingClientRect
     and stores %). Everything here is a real type/size/spacing override, so
     letters stay crisp and taps land where they look.
   - It scales the WHOLE puzzle, not just the grid: timers, goal lines, the
     found-words list, toolbars, hint costs and status text all come up too. A
     grid that doubles while its labels stay at 11px has missed the point.
   - It is a SIZE axis only. The colour axis already exists as the free
     "High Contrast" scheme (feed/xp.js THEMES, localStorage fb-theme), so this
     sheet touches no palette tokens — the two compose instead of fighting.
     Everything below inherits --ink / --line / --crimson, so equipping High
     Contrast recolours large print for free.
   - Selectors mirror the original rule's shape prefixed with the attribute, so
     they out-specify the base rules they override (several base rules are
     three classes deep, e.g. `.dw-card .dc-actions .dc-hint`, which beats a
     naive two-part selector).
   ===================================================================== */

html[data-large-print="on"]{
  --lp-prose: 24px;    /* the quote / verse — the thing being read */
  --lp-body:  19px;    /* secondary reading text */
  --lp-label: 15px;    /* small labels: author, progress, status, hint cost */
  --lp-btn:   16px;    /* button text */
  --lp-tap:   52px;    /* min tap target — above the 44px floor, for shaky aim */
}

/* ---------------------------------------------------------------------
   SHARED PLAY SHELL (.dc-*) — used by Wise Word Finder and Daily Chess.
   Scoped to the word card so chess's compact bar is left alone.
   ------------------------------------------------------------------- */
html[data-large-print="on"] .dw-card .dc-timer{ font-size:30px }
/* the goal line is the CLEAR GOAL for the loop ("Find the 4 missing words") and
   sits at 11px uppercase by default — the single worst offender on the card at
   large sizes. Drop the uppercase too: all-caps is measurably harder to read at
   low vision because the word shape flattens. */
html[data-large-print="on"] .dw-card .dc-goal{
  font-size:17px; letter-spacing:.03em; text-transform:none }
html[data-large-print="on"] .dw-card .dc-flash{ font-size:17px; padding:4px 12px }
html[data-large-print="on"] .dw-card .dc-status{ font-size:17px }
html[data-large-print="on"] .dw-card .dc-play{ font-size:var(--lp-btn); min-height:var(--lp-tap); padding:12px 24px }

/* The word card's toolbar was deliberately shrunk to 11px ghost chips so the
   grid stays the focus (owner ask 2026-06-15). That trade is right at normal
   size and wrong here — in large print these are the controls a low-vision
   player most needs to find. Restore them to full-size, full-opacity buttons
   with a real border. Four classes deep to beat the base rule. */
html[data-large-print="on"] .dw-card .dc-actions{ gap:10px; margin:14px 0 4px }
html[data-large-print="on"] .dw-card .dc-actions .dc-hint,
html[data-large-print="on"] .dw-card .dc-actions .dc-reset{
  font-size:var(--lp-btn); font-weight:600; padding:11px 18px; border-radius:11px;
  min-height:var(--lp-tap); opacity:1;
  color:var(--ink); border:2px solid color-mix(in srgb, var(--line) 100%, transparent) }
html[data-large-print="on"] .dw-card .dc-actions .dc-hint-cost{ font-size:var(--lp-label); opacity:.85 }

/* ---------------------------------------------------------------------
   WISE WORD FINDER (.wf-*)
   ------------------------------------------------------------------- */
/* The play area's width formula caps at 520px. Lift the cap so a desktop grid
   genuinely gets bigger; the `min(100%, …)` in the base rule still keeps it
   inside the card, so phones are unaffected by this line (their win comes from
   the letter scaling below plus fullscreen). */
html[data-large-print="on"] .wf-grid-area{
  --wf-w:min(760px, max(440px, calc((var(--wfn,6) - 8) * 60px + 440px))) }

/* Letters: raise the clamp ceiling 22px → 42px AND the cell-fraction .56 → .68
   so the glyph fills more of its cell instead of floating in a big empty tile.
   font-weight 700 → 800 thickens the stroke, which is what actually helps a
   low-vision reader far more than size alone. */
html[data-large-print="on"] .wf-cell{
  font-weight:800;
  font-size:clamp(20px, calc(min(var(--wf-w, 440px), 92vw) / var(--wfn, 6) * .68), 42px) }
/* a touch more air between tiles so adjacent letters don't visually merge at size */
html[data-large-print="on"] .wf-grid{ gap:3px; padding:4px; border-radius:14px;
  border-width:3px }
html[data-large-print="on"] .wf-cell{ border-radius:6px }
/* the selected start cell and the trace need a heavier ring to read at size */
html[data-large-print="on"] .wf-cell.wf-start{ box-shadow:inset 0 0 0 5px #d9a514 }

/* The quote IS the found-words list here — each blank is a word to find, and it
   fills in as you find it. It has to scale with the grid or the player is
   reading 17px targets to hunt for 42px letters. */
html[data-large-print="on"] .wf-quote{
  font-size:var(--lp-prose); line-height:1.75; max-width:680px }
html[data-large-print="on"] .wf-intro{ font-size:var(--lp-label) }
html[data-large-print="on"] .wf-author{ font-size:var(--lp-body) }
/* thicker rule under each blank — a 2px underline under 24px text reads as a
   hairline; and the found/strike states need proportional weight too */
html[data-large-print="on"] .wf-blank{ border-bottom-width:3px; min-width:2.5ch }
html[data-large-print="on"] .wf-quote.wf-strike-on .wf-blank-filled{
  text-decoration-thickness:3px }

/* ---------------------------------------------------------------------
   ANAGRAM LADDER (.ag-*)
   ------------------------------------------------------------------- */
html[data-large-print="on"] .ag-h{ font-size:var(--lp-prose); line-height:1.35 }
html[data-large-print="on"] .ag-verse{ font-size:26px; line-height:1.6; border-left-width:4px; padding-left:18px }
html[data-large-print="on"] .ag-word.blank{ letter-spacing:.16em }
html[data-large-print="on"] .ag-author{ font-size:var(--lp-body) }
html[data-large-print="on"] .ag-progress{ font-size:var(--lp-label); letter-spacing:.04em }
html[data-large-print="on"] .ag-msg{ font-size:var(--lp-body) }
html[data-large-print="on"] .ag-done{ font-size:var(--lp-prose); line-height:1.55 }

/* Tiles and slots are the touch targets — 40×46 becomes 60×68. They will wrap
   to more rows on a phone, and that is the correct trade: an extra row costs
   nothing, a 36px tile costs a misfire. */
html[data-large-print="on"] .ag-slots{ gap:8px; min-height:68px }
html[data-large-print="on"] .ag-slot{ width:58px; height:66px; font-size:34px; border-radius:12px; border-width:3px }
html[data-large-print="on"] .ag-rack{ gap:9px }
html[data-large-print="on"] .ag-tile{ width:60px; height:68px; font-size:34px; border-radius:13px; border-width:2px }
html[data-large-print="on"] .ag-actions{ gap:10px; flex-wrap:wrap }
html[data-large-print="on"] .ag-btn,
html[data-large-print="on"] .ag-again{ font-size:var(--lp-btn); padding:12px 22px; min-height:var(--lp-tap) }
/* PHONES ARE WIDTH-BOUND, and honesty about that produces a better layout than
   wishful thinking. A ~390px screen fits seven tiles and no more, whatever the
   type size — the base sheet already shrinks them to 36px for exactly that
   reason. Pushing tiles to 54px here made a 7-letter day wrap 5+2, and a word
   whose SLOTS break across two lines is harder to read than one set in smaller
   type, which is the opposite of the point.
   So on phones large print buys HEIGHT and LETTER SIZE (the parts that are not
   width-constrained) and leaves the row intact: letters go 20px → 26px (+30%)
   and the target grows 36×44 → 42×56, still one clean row of seven. Tablets and
   desktop, which have the room, keep the full 60×68 treatment above. */
@media (max-width:480px){
  html[data-large-print="on"] .ag-slots,
  html[data-large-print="on"] .ag-rack{ gap:5px; justify-content:center }
  /* Width comes from the CONTAINER, not a magic number: a hard-coded px width
     orphans a tile onto its own row the moment the card's padding changes by a
     few pixels, and that lone tile is exactly what reads broken. This says
     "seven across, or 52px if there's room for more" and stays true at any card
     width. border-box so the slot's border doesn't push it back over. */
  html[data-large-print="on"] .ag-slot,
  html[data-large-print="on"] .ag-tile{
    box-sizing:border-box; width:min(52px, calc((100% - 30px) / 7));
    height:56px; font-size:26px }
  html[data-large-print="on"] .ag-slot{ border-width:2px }
  html[data-large-print="on"] .ag-slots{ min-height:56px }
}

/* ---------------------------------------------------------------------
   DAILY DECODE (.dd-*) — near-free on the shared seam
   ------------------------------------------------------------------- */
html[data-large-print="on"] .dd-h{ font-size:var(--lp-prose); line-height:1.35 }
html[data-large-print="on"] .dd-glyph{ font-size:30px }
html[data-large-print="on"] .dd-letter{ font-size:24px; height:26px; border-bottom-width:3px }
html[data-large-print="on"] .dd-punct{ font-size:28px }
html[data-large-print="on"] .dd-gap{ width:20px }
html[data-large-print="on"] .dd-prompt-glyph{ font-size:44px }
html[data-large-print="on"] .dd-prompt-q{ font-size:var(--lp-prose) }
html[data-large-print="on"] .dd-hop{ font-size:var(--lp-label) }
html[data-large-print="on"] .dd-progress{ font-size:var(--lp-label); letter-spacing:.04em }
html[data-large-print="on"] .dd-key{ width:52px; height:58px; font-size:26px; border-radius:12px }
html[data-large-print="on"] .dd-rack{ gap:8px }
/* the frequency fill scales with the key (it is a percentage of tile height), so
   only its caption needs the large-print size — but that caption is the ONLY
   thing on the card explaining what the shading means, so it must not stay 11px
   while everything around it grows. */
html[data-large-print="on"] .dd-freq-note{ font-size:var(--lp-label); line-height:1.4 }
html[data-large-print="on"] .dd-btn,
html[data-large-print="on"] .dd-again{ font-size:var(--lp-btn); padding:12px 22px; min-height:var(--lp-tap) }
html[data-large-print="on"] .dd-msg{ font-size:var(--lp-body) }
html[data-large-print="on"] .dd-done{ font-size:var(--lp-prose); line-height:1.55 }
html[data-large-print="on"] .dd-reveal{ font-size:var(--lp-body) }
html[data-large-print="on"] .dd-author{ font-size:var(--lp-body) }
@media (max-width:480px){
  html[data-large-print="on"] .dd-key{ width:48px; height:54px; font-size:24px }
  html[data-large-print="on"] .dd-rack{ gap:6px; justify-content:center }
}

/* ---------------------------------------------------------------------
   MINI CROSSWORD (.cw-*) — near-free on the shared seam
   ------------------------------------------------------------------- */
/* the grid is capped at 288px, which is small even at normal size */
html[data-large-print="on"] .cw-grid{ max-width:min(100%, 460px); gap:4px }
html[data-large-print="on"] .cw-cell input{ font-size:30px; font-weight:700 }
html[data-large-print="on"] .cw-cell{ border-width:2px }
html[data-large-print="on"] .cw-cell.cw-cur{ box-shadow:inset 0 0 0 4px var(--crimson) }
/* clues are the reading surface — 13px is the real barrier here, not the grid */
html[data-large-print="on"] .cw-clue{ font-size:var(--lp-body); line-height:1.45; min-height:var(--lp-tap) }
html[data-large-print="on"] .cw-clues-h{ font-size:var(--lp-label); letter-spacing:.04em }
html[data-large-print="on"] .cw-btn{ font-size:var(--lp-btn); min-height:var(--lp-tap); padding:11px 20px }
/* two clue columns at 19px is too narrow to read — go single-column much later */
@media (max-width:900px){
  html[data-large-print="on"] .cw-clues{ grid-template-columns:1fr; gap:12px }
}

/* ---------------------------------------------------------------------
   THE LANDING PAGES (the two `largePrint` hubs in functions/_hubs.js, served at
   /games/daily-large-print-word-search/ and -crossword). These render in large print
   themselves, so the hub's own prose has to come up with everything else — a
   page that promises big type and then serves 15px body copy is the broken
   promise this whole feature exists to fix.
   ------------------------------------------------------------------- */
/* Prose size is DERIVED from --reader-size (post.css: the A-/A+ control in
   feed/reader.js writes that token), so large print raises the token rather than
   overriding the rule. Two wins: it composes with the reader's own text-size
   preference instead of fighting a computed value, and a reader who has set an
   explicit size still beats us, because reader.js writes --reader-size inline on
   article.post and inline styles outrank a stylesheet. */
html[data-large-print="on"] article.post.hub{ --reader-size:21px; --reader-lh:1.75 }
html[data-large-print="on"] .post.hub .how-steps li{ font-size:20px; line-height:1.6 }
html[data-large-print="on"] .post.hub .how-steps li::before{ font-size:16px }
html[data-large-print="on"] .post.hub .hub-h2{ font-size:19px; letter-spacing:.06em }
html[data-large-print="on"] .post.hub .hub-h3{ font-size:23px }
html[data-large-print="on"] .post.hub .byline{ font-size:20px }
html[data-large-print="on"] .post.hub .hub-cta{ font-size:20px; min-height:60px; padding:14px 28px }
html[data-large-print="on"] .post.hub .hub-cta-note{ font-size:16px }
/* the note that explains the mode + carries the off switch. Column, not a row:
   the control reads as the thing you press about the sentence above it, and an
   icon button leading a paragraph made the sentence start on a picture. */
.hub-lp-note{ display:flex; flex-direction:column; align-items:center;
  gap:10px; margin:16px auto 0; max-width:52ch; font-size:14px; line-height:1.5;
  color:var(--ink-soft); text-align:center }
html[data-large-print="on"] .hub-lp-note{ font-size:18px; max-width:46ch }
/* on a prose page an icon alone has no toolbar to give it meaning, so this one
   instance shows its words (see the .lp-slot mount in feed/large-print.js) */
.lp-btn-label{ font-weight:600 }

/* ---------------------------------------------------------------------
   FOCUS — visible keyboard focus at a weight that survives the bigger type.
   The grids are keyboard-playable (roving tabindex), so this is load-bearing,
   not decoration.
   ------------------------------------------------------------------- */
html[data-large-print="on"] .wf-cell:focus-visible,
html[data-large-print="on"] .ag-tile:focus-visible,
html[data-large-print="on"] .ag-slot:focus-visible,
html[data-large-print="on"] .dd-key:focus-visible,
html[data-large-print="on"] .cw-cell input:focus-visible,
html[data-large-print="on"] .dc-hint:focus-visible,
html[data-large-print="on"] .dc-reset:focus-visible,
html[data-large-print="on"] .ag-btn:focus-visible,
html[data-large-print="on"] .dd-btn:focus-visible,
html[data-large-print="on"] .cw-btn:focus-visible,
html[data-large-print="on"] .lp-btn:focus-visible{
  outline:4px solid var(--crimson); outline-offset:3px; border-radius:6px }

/* ---------------------------------------------------------------------
   THE CONTROL ITSELF (.lp-btn) — a calm ghost chip that sits in whatever
   toolbar it is mounted into. Icon-first (owner preference), with an
   aria-label carrying the words. Deliberately NOT crimson at rest: it is a
   utility, not the primary action.
   ------------------------------------------------------------------- */
.lp-btn{ font:inherit; font-family:var(--ui); font-size:13px; font-weight:600; line-height:1;
  display:inline-flex; align-items:center; justify-content:center; gap:6px;
  min-width:40px; min-height:40px; padding:8px 12px; cursor:pointer;
  border-radius:10px; border:1px solid var(--line); background:transparent;
  color:var(--ink-soft); transition:.15s ease;
  touch-action:manipulation; -webkit-tap-highlight-color:transparent }
.lp-btn:hover{ color:var(--crimson); border-color:var(--crimson) }
.lp-btn .lp-ico{ display:block }
/* When mounted into a toolbar that has its own button shape, borrow that shape
   so the control doesn't read as a foreign object dropped into the row. Two
   classes, so this beats the bare .lp-btn radius above whatever the load order. */
.lp-btn.ag-btn, .lp-btn.dd-btn{ border-radius:999px }
/* These rows default to align-items:stretch, so the control's 40px minimum was
   quietly making every sibling button 1px taller the moment this sheet loaded —
   a feature that is switched OFF should leave no trace in the layout. Centring
   lets the control be the size it needs without resizing its neighbours. */
.ag-actions, .cw-actions, .dd-actions, .dw-card .dc-actions,
.mml-actions, .hq-actions, .am-actions{ align-items:center }
/* Mini Lineup, History Quiz and Art Match had the large-print SIZES from the
   day the sheet shipped but no way to switch the mode on from their own card,
   so for anyone who did not arrive by a ?large=1 link the styling was dead
   code — and the reader it is for is the least able to work around that. The
   first already had a toolbar (.mml-actions); the other two get one here. It is
   a plain right-aligned utility row and it must stay quiet: these two cards are
   a question with word chips and a grid of paintings, and neither wants a
   second thing competing with the answer for the eye. */
.hq-actions, .am-actions{ display:flex; justify-content:flex-end; gap:8px; margin-top:10px }
/* engaged state: filled, so "it's on" is obvious without reading anything */
.lp-btn[aria-pressed="true"]{ color:var(--crimson); border-color:var(--crimson);
  background:color-mix(in srgb, var(--crimson) 12%, transparent) }
/* in large print the control must obey its own rules */
html[data-large-print="on"] .lp-btn{ font-size:var(--lp-btn); min-height:var(--lp-tap);
  min-width:var(--lp-tap); padding:11px 16px; border-width:2px; color:var(--ink) }
html[data-large-print="on"] .lp-btn .lp-ico{ width:24px; height:24px }
@media (prefers-reduced-motion:reduce){ .lp-btn{ transition:none } }

/* ---------------------------------------------------------------------
   FULLSCREEN OVERLAY (.lp-fs) — the same contract as the Daily Dungeon's
   .nh-fs, kept generic so any card can wear it. On a phone this is where the
   real win is: the card stops being a 320px column inside a feed and becomes
   the whole screen, which is worth far more than any type bump.
   ------------------------------------------------------------------- */
html.lp-fs-lock, body.lp-fs-lock{ overflow:hidden }
/* z-index must beat the site's FIXED edge furniture, which sits at ~2147483000
   (the EXP pill, the notepad panel, the narration bar) — at a mere 9999 they
   all paint over the overlay, i.e. on desktop always, since native fullscreen's
   top layer only masks it on mobile. Same number the dungeon settled on.
   transform/box-shadow are pinned because the card is still a .feed-card and
   the global :hover lift would shift a fixed inset:0 overlay by 2px. */
.lp-fs{ position:fixed; inset:0; z-index:2147483200; margin:0; border:0; border-radius:0;
  transform:none; box-shadow:none; background:var(--paper); overflow-y:auto;
  display:block; max-width:none; width:auto;
  /* the notch and the home indicator must never cover a control */
  padding:calc(12px + env(safe-area-inset-top)) calc(12px + env(safe-area-inset-right))
          calc(16px + env(safe-area-inset-bottom)) calc(12px + env(safe-area-inset-left)) }
/* the grid should use the height it just gained, not stay pinned to a card width */
.lp-fs .wf-grid-area{ max-width:min(100%, 96vh) }
/* the exit control has to be findable without hunting: park it top-right, above
   the card's own content, with the same dot treatment the dungeon uses */
.lp-fs .lp-fs-btn{ position:fixed; top:calc(8px + env(safe-area-inset-top));
  right:calc(8px + env(safe-area-inset-right)); z-index:3 }
@media (prefers-reduced-motion:reduce){ .lp-fs{ transition:none } }

/* ---------------------------------------------------------------------
   FEED CHROME — the SHIPPED FOLLOW-UP. Large print scaled the puzzle CARDS
   and stopped at the card edge, so the furniture beside them stayed at its
   normal size. The notification pill is the one that matters: its dismiss
   button is a 38px target carrying a 19px glyph, offered to precisely the
   reader this mode exists for. The label goes up with the body text, the row
   becomes a full tap target, and the times sign gets the same 52px floor
   every other control in this sheet gets.
   These rules live HERE, not in feed.css, so the whole mode stays in one file
   and nothing is left behind when it is switched off.
   ------------------------------------------------------------------- */
html[data-large-print="on"] .notif-bar,
html[data-large-print="on"] .notif-label{ font-size:var(--lp-body); line-height:1.4 }
html[data-large-print="on"] .notif-item{ font-size:var(--lp-body); line-height:1.5;
  min-height:var(--lp-tap); padding:12px 16px; align-items:center }
html[data-large-print="on"] .notif-x{ width:var(--lp-tap); height:var(--lp-tap);
  font-size:30px; opacity:.75 }

/* ---------------------------------------------------------------------
   MINI LINEUP (.mml-*) — the strongest case on the site for this mode, and it
   was not covered. The logic grid is READ, not looked at: the clue under each
   suspect sets at .68rem (~11px) and the role word above it at .62rem (~10px),
   smaller than anything in the four games already here. Type scale is the
   whole game, so everything comes up together.
   ------------------------------------------------------------------- */
html[data-large-print="on"] .mml-h{ font-size:var(--lp-prose); line-height:1.35 }
html[data-large-print="on"] .mml-rule{ font-size:var(--lp-label); opacity:.9 }
html[data-large-print="on"] .mml-ledger{ font-size:var(--lp-label); gap:9px }
html[data-large-print="on"] .mml-chip{ font-size:var(--lp-btn); padding:10px 16px;
  min-height:var(--lp-tap); border-width:2px }
html[data-large-print="on"] .mml-bar-q{ font-size:var(--lp-body) }
html[data-large-print="on"] .mml-grid{ gap:9px }
html[data-large-print="on"] .mml-name{ font-size:var(--lp-body) }
html[data-large-print="on"] .mml-role{ font-size:var(--lp-label) }
/* all-caps at 10px is the worst reading shape on the card — the word flattens.
   Drop the uppercase as well as raising the size, exactly as .dc-goal does. */
html[data-large-print="on"] .mml-role-word{ font-size:var(--lp-label); text-transform:none;
  letter-spacing:.02em }
html[data-large-print="on"] .mml-clue{ font-size:17px; line-height:1.45; padding-top:6px }
html[data-large-print="on"] .mml-badge{ font-size:13px; opacity:.75 }
html[data-large-print="on"] .mml-face{ width:44px; height:44px }
html[data-large-print="on"] .mml-emoji{ font-size:32px; line-height:44px }
html[data-large-print="on"] .mml-msg{ font-size:var(--lp-body) }
html[data-large-print="on"] .mml-done{ font-size:var(--lp-prose); line-height:1.5 }
html[data-large-print="on"] .mml-actions{ gap:10px; flex-wrap:wrap }
/* A suspect card is a COLUMN of five short lines, so it grows in height rather
   than width — but two across at this size is unreadable on a phone. One per
   row there; the base grid keeps its own columns above that width. */
@media (max-width:560px){
  html[data-large-print="on"] .mml-grid{ grid-template-columns:1fr }
}

/* ---------------------------------------------------------------------
   HISTORY QUIZ (.hq-*) — the shipped notes called this one "image-led" and
   left it out. It is not: the card is a QUESTION (.hq-q) and a row of
   draggable WORD chips (.hq-chip, 14px), with no image anywhere in the play
   surface. It is a reading game with a drag, so it belongs here.
   ------------------------------------------------------------------- */
html[data-large-print="on"] .hq-q{ font-size:var(--lp-prose); line-height:1.45 }
html[data-large-print="on"] .hq-mini-title{ font-size:var(--lp-body) }
html[data-large-print="on"] .hq-mini-meta{ font-size:var(--lp-label) }
html[data-large-print="on"] .hq-mini-icon{ width:52px; height:52px; font-size:27px }
html[data-large-print="on"] .hq-progress{ font-size:var(--lp-label) }
/* the drop zone has to stay obviously bigger than the chip it receives */
html[data-large-print="on"] .hq-target{ min-height:76px; border-width:3px }
html[data-large-print="on"] .hq-target-hint{ font-size:var(--lp-body) }
html[data-large-print="on"] .hq-ans{ font-size:var(--lp-prose) }
/* the chips are DRAGGED, so target size matters even more than type here: a
   14px chip is a small thing to pick up with a shaky hand */
html[data-large-print="on"] .hq-chip{ font-size:var(--lp-btn); padding:13px 20px;
  min-height:var(--lp-tap); border-width:2px }
html[data-large-print="on"] .hq-chips{ gap:12px }
html[data-large-print="on"] .hq-done-h{ font-size:var(--lp-prose); line-height:1.5 }
html[data-large-print="on"] .hq-board-h{ font-size:var(--lp-label); letter-spacing:.04em }

/* ---------------------------------------------------------------------
   ART MATCH (.am-*) — genuinely image-led, and that is WHY it is here rather
   than a reason to skip it. Matching an artist to a painting means SEEING the
   painting, and the thumbnail ships at 64px. So this one scales the picture as
   well as the type: the artist buttons (the tap targets) come up, the work's
   title and byline come up, and the thumbnail nearly doubles.
   The two-column layout is dropped on a phone at this size — a 110px artist
   column beside a picture is unreadable once the names are 17px.
   ------------------------------------------------------------------- */
html[data-large-print="on"] .am-status{ font-size:var(--lp-label) }
html[data-large-print="on"] .am-artist{ font-size:17px; padding:12px 14px;
  min-height:var(--lp-tap); border-width:2px }
html[data-large-print="on"] .am-artists{ gap:11px }
html[data-large-print="on"] .am-art{ gap:14px; padding:10px; border-width:2px }
html[data-large-print="on"] .am-art-img{ width:110px; height:110px }
html[data-large-print="on"] .am-art-img.am-img-ph::after{ font-size:38px }
html[data-large-print="on"] .am-art-title{ font-size:17px; line-height:1.35 }
html[data-large-print="on"] .am-art-by{ font-size:15px }
html[data-large-print="on"] .am-progress{ font-size:var(--lp-body) }
html[data-large-print="on"] .am-done-h{ font-size:var(--lp-prose); line-height:1.5 }
html[data-large-print="on"] .am-board-h{ font-size:var(--lp-label); letter-spacing:.04em }
@media (max-width:640px){
  html[data-large-print="on"] .am-cols{ grid-template-columns:1fr; gap:16px }
}

/* =====================================================================
   THE MINI-FEED (.lpf-*) — feed/large-print-feed.js, mounted on /large-print/.
   Styled at BOTH sizes on purpose: a reader can turn the mode off and stay on
   this page, and the page must still look like something rather than collapsing
   into unstyled markup the moment the thing it is named after is switched off.
   ===================================================================== */
.lpf{ width:100%; max-width:720px; margin:0 auto }
.lpf-head{ text-align:center; margin:0 0 18px }
.lpf-kicker{ font-family:var(--ui); font-size:11px; font-weight:700; letter-spacing:.12em;
  text-transform:uppercase; color:var(--crimson); margin:0 0 4px }
.lpf-h{ font-family:var(--display,Georgia,serif); font-size:26px; line-height:1.2; margin:0 0 6px;
  color:var(--ink) }
.lpf-lede{ font-family:var(--ui); font-size:14px; line-height:1.55; color:var(--ink-soft);
  max-width:46ch; margin:0 auto }
.lpf-ctl{ display:flex; justify-content:center; margin:14px 0 0 }

.lpf-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:20px }
.lpf-item{ border:1px solid var(--line); border-radius:16px; background:var(--tile);
  padding:14px 14px 16px }
/* the caption is the card's own header: icon, name + tagline, coverage chip */
.lpf-cap{ display:flex; align-items:center; gap:11px; margin:0 0 10px }
.lpf-ico{ flex:none; font-size:22px; line-height:1 }
.lpf-names{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:1px }
.lpf-name{ font-family:var(--display,Georgia,serif); font-weight:700; font-size:17px; color:var(--ink) }
.lpf-sub{ font-family:var(--ui); font-size:12.5px; color:var(--ink-soft) }
/* WHAT LARGE PRINT ACTUALLY DOES FOR THIS GAME. Deliberately a quiet chip and
   not a warning colour: "the board keeps its geometry" is a fact about the
   game, not a fault, and dressing it in red would read as a broken card. */
.lpf-scale{ flex:none; font-family:var(--ui); font-size:11px; font-weight:600;
  letter-spacing:.04em; padding:4px 10px; border-radius:999px; color:var(--ink-soft);
  border:1px solid var(--line); background:transparent; cursor:help }
.lpf-scale-full{ color:var(--crimson); border-color:color-mix(in srgb, var(--crimson) 45%, var(--line)) }
.lpf-note{ font-family:var(--ui); font-size:12.5px; line-height:1.5; color:var(--ink-soft);
  margin:0 0 10px }
.lpf-host{ display:block }
/* a host that has not mounted yet reserves its frame, so the list does not jump
   as each game arrives (the same anti-CLS story as the feed's .fa-placed) */
.lpf-host:empty{ min-height:180px; border-radius:12px;
  background:color-mix(in srgb, var(--ink) 4%, transparent) }
/* the game's own card must not draw a second border inside ours */
.lpf-host > .feed-card{ border:0; background:none; padding:0; margin:0; box-shadow:none }

.lpf-open{ display:flex; align-items:center; justify-content:space-between; gap:10px;
  font-family:var(--ui); font-size:15px; font-weight:600; text-decoration:none;
  color:var(--ink); min-height:48px; padding:11px 16px; border-radius:12px;
  border:1px solid var(--line); transition:.15s ease;
  -webkit-tap-highlight-color:transparent }
.lpf-open:hover{ color:var(--crimson); border-color:var(--crimson);
  background:color-mix(in srgb, var(--crimson) 7%, transparent) }
.lpf-open-a{ font-size:18px; opacity:.7 }
@media (prefers-reduced-motion:reduce){ .lpf-open{ transition:none } }

/* ---- the same page with the mode ON ---- */
html[data-large-print="on"] .lpf{ max-width:840px }
html[data-large-print="on"] .lpf-h{ font-size:34px }
html[data-large-print="on"] .lpf-kicker{ font-size:14px }
html[data-large-print="on"] .lpf-lede{ font-size:var(--lp-body); line-height:1.65; max-width:42ch }
html[data-large-print="on"] .lpf-item{ padding:18px 16px 20px; border-width:2px; border-radius:18px }
html[data-large-print="on"] .lpf-cap{ gap:14px; flex-wrap:wrap }
html[data-large-print="on"] .lpf-ico{ font-size:30px }
html[data-large-print="on"] .lpf-name{ font-size:23px }
html[data-large-print="on"] .lpf-sub{ font-size:var(--lp-label) }
html[data-large-print="on"] .lpf-scale{ font-size:var(--lp-label); padding:6px 13px }
html[data-large-print="on"] .lpf-note{ font-size:var(--lp-label); line-height:1.55 }
html[data-large-print="on"] .lpf-open{ font-size:var(--lp-btn); min-height:var(--lp-tap);
  padding:14px 20px; border-width:2px }
html[data-large-print="on"] .lpf-open-a{ font-size:24px }
/* the off switch is the one control on this page that must never be hard to
   find — it is the way out of a mode the page turned on by itself */
html[data-large-print="on"] .lpf-ctl .lp-btn{ font-size:18px; padding:13px 20px }

/* ---------------------------------------------------------------------
   THE ORDINARY FEED, IN LARGE PRINT (owner ask 2026-08-20). /large-print/
   now appends the same feed tail every post permalink carries
   (functions/_large-print.js feedTail → feed/feed-tail.js), and a page that
   promises big type must not hand the reader 12.5px card meta the moment
   they scroll past the puzzles.

   Scoped to the ATTRIBUTE, not to /large-print/, so a reader who turned the
   mode on for themselves gets the same feed everywhere it appears — the
   homepage, /feed/ and every post page. That is the point of a mode.

   TYPE AND SPACING ONLY. No layout is changed: the vote rail, the card grid
   and the cover images keep their geometry, because moving them would break
   the stream core's measured slot heights (feed-stream-core learnSlotHeight)
   and reintroduce the cold-load layout shift the CLS budget guards.
   ------------------------------------------------------------------- */
html[data-large-print="on"] .feed-tail-h{ font-size:clamp(26px,5vw,36px) }
html[data-large-print="on"] .feed-card h3{ font-size:26px; line-height:1.25 }
html[data-large-print="on"] .feed-card .text{ font-size:var(--lp-body); line-height:1.7 }
html[data-large-print="on"] .feed-card.poem .text{ font-size:21px }
html[data-large-print="on"] .feed-card.compact h3{ font-size:21px }
html[data-large-print="on"] .feed-card.compact .text{ font-size:16.5px; line-height:1.6 }
html[data-large-print="on"] .feed-card.ping-daily h3{ font-size:20px; line-height:1.35 }
html[data-large-print="on"] .feed-card.ping-daily .text{ font-size:16.5px; line-height:1.6 }
html[data-large-print="on"] .feed-meta{ font-size:var(--lp-label); gap:14px }
/* the blog card's title/summary are spans inside one big link, not an h3 */
html[data-large-print="on"] .blog-title{ font-size:22px; line-height:1.3 }
html[data-large-print="on"] .blog-desc{ font-size:16.5px; line-height:1.55 }
/* Bluesky cards: the post body is the thing being read */
html[data-large-print="on"] .bsky-text{ font-size:var(--lp-body); line-height:1.7 }
html[data-large-print="on"] .bsky-name{ font-size:19px }
html[data-large-print="on"] .bsky-handle{ font-size:var(--lp-label) }
/* the two persistent pills feed-tail.js and back-to-top.js append to <body>.
   Class names verified against the modules that create them (.to-games in
   feed/feed-tail.js, .back-to-top in feed/back-to-top.js) — a guessed selector
   here is a rule that silently does nothing. */
html[data-large-print="on"] .to-games,
html[data-large-print="on"] .back-to-top{ font-size:var(--lp-btn); min-height:var(--lp-tap) }
