/* Additive player surfaces. Original tabletop, cards and game controls stay intact. */
/* The heading takes focus on every route change, and that stays: it is what
   tells a screen reader it has arrived somewhere new instead of leaving it on
   an element that no longer exists. What goes is the visible ring.

   tabindex="-1" keeps the heading out of the tab order, so nobody can Tab to
   it and no keyboard user ever navigates to it on purpose - it is a focus
   target, not a control. WCAG 2.4.7 asks for a visible indicator on
   keyboard-operable components, which this is not. Drawing one here only put
   a box around the page title for people who had no use for it, including on
   a plain load of a URL with a #route in it, where focus moves with no prior
   interaction at all and the browser rightly treats it as keyboard focus. */
main h1[tabindex="-1"]:focus{outline:none}
/* Equal daily-entry choices; color, not size, distinguishes the primary action. */
.daily-card>.actions{display:grid;grid-template-columns:minmax(0,1fr);gap:12px}
.daily-card>.actions>.primary,.daily-card>.actions>.secondary{width:100%;min-height:54px;padding:14px 21px;font-size:15px;line-height:1.4}
.daily-card>.actions>.primary{position:relative;justify-content:center;padding-inline:44px}
.daily-card>.actions>.primary>span{position:absolute;right:21px;top:50%;transform:translateY(-50%)}
.daily-card>#daily-play-notice{margin:20px 0 0;font-size:13px;line-height:1.6;color:var(--muted)}
.daily-card>.card-pace{margin:24px 0 0}
.player-panel{max-width:760px;margin:0 auto;padding:32px;background:var(--paper);color:var(--ink);border-radius:12px;box-shadow:0 5px 0 #d9c6ac,0 13px 30px #260d1840;overflow-wrap:anywhere}
.player-panel h1{font-size:38px;margin:10px 0 20px}
.player-panel p{font-size:14px;line-height:1.75;margin:14px 0;color:var(--muted)}
.player-panel .actions{margin-top:22px}
.player-panel .actions>a:not(.primary):not(.secondary){display:inline-flex;align-items:center;min-height:44px;font-size:13px}
.player-form{display:grid;gap:9px;max-width:480px;margin:24px 0}
.player-form label{font-size:13px;font-weight:700;margin-top:8px}
.player-form input{width:100%;min-height:48px;padding:11px 13px;border:1px solid var(--rule);border-radius:6px;background:#fffdf6;color:var(--ink);font-size:16px}
.player-form .primary{margin-top:12px}
.player-form .error{color:var(--bad);margin:8px 0}
.player-footnote{max-width:760px;margin:25px auto;font-size:12px;line-height:1.9;color:var(--table-muted)}
.player-table-wrap{overflow-x:auto;margin:24px 0}
.player-table{width:100%;border-collapse:collapse;font-size:14px;text-align:left;font-variant-numeric:tabular-nums}
.player-table caption{text-align:left;font-size:12px;color:var(--muted);padding-bottom:12px}
.player-table th{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
.player-table td,.player-table th{padding:15px 10px;border-bottom:1px solid var(--line)}
.player-table td:last-child,.player-table th:last-child{text-align:right;white-space:nowrap}
.player-table td:nth-child(2){overflow-wrap:anywhere}
.player-standing{padding:12px 16px;background:var(--soft);border-left:3px solid var(--action);border-radius:4px}
.recovery-codes{display:block;width:100%;min-height:260px;padding:16px;font:15px/1.8 var(--mono);background:var(--soft);color:var(--ink);border:1px solid var(--rule);border-radius:6px;resize:vertical}
.site-header nav{gap:18px;flex-wrap:wrap}
/* The nav links are styled; the help button beside them never was, so it fell
   back to the browser's default size for a <button> - 12px against their 13px.
   Same colour, same weight, one pixel out, which is enough to read as not
   quite belonging. It has to track the links at BOTH widths: below 680px the
   links drop to 12px themselves, where the button already happened to match
   by accident. style.css is in the frozen half of the repository and
   player.css loads after it, so the correction lands here. */
.site-header .help-button{font-size:13px}
/* And the same 2px the links reserve underneath themselves for the active
   underline. Without it the button's content box is 2px taller than theirs,
   so its text centres one pixel lower - every link's text sits at 38.3 and
   this one sat at 39.3. One pixel is not enough to name and quite enough to
   see, which is why it still read as not belonging after the type matched.
   Transparent, so nothing is drawn; it only reserves the same room. */
.site-header .help-button{border-bottom:2px solid transparent}
@media(max-width:680px){.site-header .help-button{font-size:12px}}
/* One more step on the brand ladder style.css already walks - 32px, 29px,
   27px at 360px. 27px is still wide enough that below about 340px the brand
   and the help button stop sharing a row, so the button takes a 44px row of
   its own and the header reaches 214px: 38% of a 568px screen, which pushes
   the daily card toward the fold. Measured, not guessed - it fits at 344px
   and wraps at 330px. At 23px they share a row again and the header is back
   to 163px, the same as any other phone. Wider phones are untouched. */
@media(max-width:340px){.site-header .brand-name{font-size:23px}}
@media(max-width:1000px) and (min-width:681px){.site-header{flex-wrap:wrap}.site-header nav{order:2;width:100%;justify-content:flex-start}.site-header .help-button{margin-left:auto}}
@media(max-width:680px){.site-header nav{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0 15px}.site-header nav a{justify-content:center;padding:9px 0;font-size:12px;min-width:0}.player-panel{padding:25px 20px}.player-panel h1{font-size:32px}.player-table td,.player-table th{padding:12px 6px}.player-table{font-size:13px}.player-footnote{padding:0 5px}.player-panel .actions{gap:10px 16px}.player-form{max-width:none}}
/* Pro surfaces reuse the tabletop tokens; the badge echoes the brass edition stamp. */
.pro-badge{display:inline-block;padding:2px 8px;border-radius:999px;background:var(--accent);color:#fffdf6;font-size:11px;font-weight:700;line-height:1.6;letter-spacing:.08em;text-transform:uppercase;vertical-align:middle}
.pro-badge-line{color:var(--ink)!important}
.pro-compare{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;margin:24px 0}
.pro-compare section{padding:18px 20px;border:1px solid var(--line);border-radius:8px;background:#fffdf6}
.pro-compare .pro-column{border-color:var(--accent);box-shadow:inset 0 3px 0 var(--accent)}
.pro-compare h2{font-size:22px;margin:0 0 10px}
.pro-compare ul{margin:0;padding-left:18px;font-size:14px;line-height:1.8;color:var(--muted)}
.pro-plans{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:22px 0 8px}
.pro-plan{display:flex;flex-direction:column;align-items:flex-start;gap:6px;min-height:88px;padding:16px 18px;border:1px solid var(--rule);border-radius:8px;background:#fffdf6;color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.pro-plan:hover,.pro-plan:focus-visible{border-color:var(--action);box-shadow:0 0 0 2px var(--action)}
.pro-plan:disabled{opacity:.6;cursor:progress}
.pro-plan.pro-plan-soon{opacity:.85;cursor:default}.pro-plan-soon .pro-plan-cta{color:var(--muted)}
.pro-plan-label{font-size:13px;font-weight:700}.pro-plan-label em{font-style:normal;color:var(--accent);margin-left:6px}
.pro-plan-price{font-size:14px;color:var(--muted)}.pro-plan-price strong{font-size:26px;color:var(--ink)}
.pro-plan-cta{margin-top:4px;font-size:13px;font-weight:700;color:var(--accent)}
.player-panel .danger,.player-form .danger{background:var(--bad);color:#fffdf6;box-shadow:0 3px 0 #6e2920}
.archive-locked{opacity:.78}.archive-locked .secondary{display:inline-flex;align-items:center;gap:8px}
.archive-note{margin:20px 0;color:var(--table-muted)}
@media(max-width:680px){.pro-compare,.pro-plans{grid-template-columns:1fr}}

/* Game touch controls: leave browser zoom available outside explicit map movement. */
.number-control .step,.map-tools button{touch-action:manipulation;min-width:48px;min-height:48px}
.number-control .step{width:48px}
.map-button{touch-action:pan-y pinch-zoom}
.map-button.is-moving{touch-action:none;cursor:grab}
.map-button.is-moving:active{cursor:grabbing}
.map-tools{flex-wrap:wrap}
.map-tools #pin-status{flex:1 0 100%}
.map-tools #map-move{font-size:13px;border-radius:6px;padding:0 12px}
.map-tools .zooms{margin-left:auto}
.map-caption{font-size:12px;line-height:1.5}

/* Ranked stats reuse the paper, burgundy and rule tokens; no fixed-width charts. */
.player-stats-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:24px 0;color:var(--ink)}
.player-stats-grid>div,.player-category-grid>li{min-width:0;padding:16px;border:1px solid var(--line);border-radius:8px;background:var(--soft)}
.player-stats-grid dt{font-size:13px;color:var(--muted)}
.player-stats-grid dd{margin:8px 0 0;font-size:23px;font-weight:700;font-variant-numeric:tabular-nums;color:var(--ink)}
.player-stats-section{margin-top:28px;padding-top:20px;border-top:1px solid var(--line)}
.player-stats-section h2{margin:0;font-size:24px}
.player-category-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:18px 0;padding:0;list-style:none}
.player-category-grid h3{margin:0;font-size:16px}
.player-category-grid p{margin:10px 0 0;font-variant-numeric:tabular-nums}
.player-recent-days{list-style:none;padding:0;margin:16px 0}
.player-recent-days li{display:flex;flex-wrap:wrap;gap:6px 20px;justify-content:space-between;padding:12px 0;border-bottom:1px solid var(--line);font-size:14px;line-height:1.6;font-variant-numeric:tabular-nums}
.player-recent-days time{font-weight:700}.player-recent-days span{color:var(--muted)}
@media(max-width:680px){.player-stats-grid,.player-category-grid{grid-template-columns:1fr}.player-recent-days li{flex-direction:column}.player-stats-grid dd{font-size:22px}}
/* The remark sits between how close you were and the fact it teaches. Set in
   italic rather than a colour of its own: it is an aside, and the reveal
   already carries the answer, the score and a source link without another
   competing accent. public/style.css is original source and holds .feedback,
   so this additive rule lives here, where the game page loads it. */
.feedback>.remark{font-style:italic;margin:6px 0 10px;color:var(--ink);opacity:.82}

/* The reveal between questions.
   public/style.css is original source and owns .feedback, .feedback-title and
   .points, so everything the reaction adds lives here and only overrides the
   one colour it needs to.

   Two tokens per band, not one. --band is the fill: the mark, the meter, the
   streak pill, and it is the iOS and Android client's exact hex, so the three
   look like the same game. --band-ink is the text, darkened where the fill is
   too light to read against --paper. The gold is already in the palette as
   --action, which is why a bullseye needs no new colour at all. */
.feedback.reveal{--band:#537448;--band-ink:#3f6a47}
.feedback.reveal-bullseye{--band:var(--action);--band-ink:#8a6520}
.feedback.reveal-close{--band:#537448;--band-ink:#3f6a47}
.feedback.reveal-middling{--band:#c68f30;--band-ink:#8a5f14}
/* Brick, not the palette's --bad: the house rule in Remarks.php is that a
   wrong answer is never scolded, and an alarm red would undo what the words
   are careful about. */
.feedback.reveal-far{--band:#91443b;--band-ink:#8c3a2f}

.reveal-banner{display:flex;align-items:center;gap:10px;margin:0 0 12px}
.reveal-headline{font-weight:800;font-size:15px;letter-spacing:.07em;color:var(--band-ink)}
.reveal-mark{position:relative;flex:none;width:17px;height:17px;border-radius:50%;border:2.5px solid var(--band-ink)}
.reveal-bullseye .reveal-mark::after,.reveal-close .reveal-mark::after,.reveal-middling .reveal-mark::after{content:'';position:absolute;inset:2.5px;border-radius:50%;border:2px solid var(--band-ink)}
.reveal-bullseye .reveal-mark::before{content:'';position:absolute;inset:5px;border-radius:50%;background:var(--band-ink)}

.reveal-run{margin-left:auto;display:inline-flex;align-items:center;gap:6px;white-space:nowrap;padding:4px 10px;border-radius:999px;font-size:11px;font-weight:600;letter-spacing:.02em;color:var(--band-ink);background:rgba(64,42,48,.07)}
.reveal-run.reveal-hot{background:var(--ink);color:var(--action);font-weight:800}

.feedback.reveal .feedback-title .points{color:var(--band-ink);font-variant-numeric:tabular-nums}

.reveal-meter{height:7px;margin:9px 0 2px;border-radius:999px;background:var(--line);overflow:hidden}
.reveal-meter>span{display:block;height:100%;border-radius:999px;background:var(--band);transform-origin:left center;animation:reveal-grow .85s cubic-bezier(.2,.7,.3,1) both}

.reveal-scale{margin:13px 0 2px}
.reveal-track{position:relative;height:14px}
.reveal-track::before{content:'';position:absolute;left:0;right:0;top:5px;height:4px;border-radius:999px;background:var(--line)}
.reveal-gap{position:absolute;top:5px;height:4px;border-radius:999px;background:var(--rule);transform-origin:left center;animation:reveal-grow .7s cubic-bezier(.2,.7,.3,1) .15s both}
.reveal-you,.reveal-truth{position:absolute}
.reveal-you{top:0;width:13px;height:13px;margin-left:-6.5px;border-radius:50%;border:2px solid var(--ink);background:var(--paper);box-sizing:border-box}
.reveal-truth{top:2px;width:10px;height:10px;margin-left:-5px;background:var(--action);transform:rotate(45deg)}
.reveal-legend{display:flex;align-items:center;gap:14px;margin-top:7px;font-size:11px;color:var(--muted)}
.reveal-legend strong{margin-left:auto;color:var(--ink);font-weight:700}
.reveal-legend i{display:inline-block;width:8px;height:8px;margin-right:5px;vertical-align:-1px;box-sizing:border-box}
.reveal-key-you{border-radius:50%;border:1.5px solid var(--ink)}
.reveal-key-truth{background:var(--action);transform:rotate(45deg)}

@keyframes reveal-grow{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@media(prefers-reduced-motion:reduce){.reveal-meter>span,.reveal-gap{animation:none}}
@media(max-width:680px){.reveal-headline{font-size:13px}.reveal-run{font-size:10px;padding:3px 8px}}

/* The aside, promoted.
   It used to sit third in a stack of small grey paragraphs, in italic at 82%
   opacity, between the detail and the fact - which is the typography of a
   caption, and players read straight past it. Now it sits directly under the
   score with the band's own colour on its edge, so the card reads: what you
   got, then what the game thinks of it, then the facts.
   The plain .feedback>.remark rule above still covers any non-reveal use. */
.feedback.reveal>.remark{
  margin:14px 0 4px;
  padding:8px 0 8px 14px;
  border-left:3px solid var(--band);
  font-style:italic;
  font-size:17px;
  line-height:1.5;
  color:var(--band-ink);
  opacity:1;
}
@media(max-width:680px){.feedback.reveal>.remark{font-size:15px;padding-left:12px}}

/* Friends.
   The invite code is the one string on this site a player reads aloud across
   a table, so it is set large, in the monospace face, and widely tracked -
   the alphabet already excludes I, l, 1, O and 0 for the same reason. */
.friends-invite{margin:22px 0;padding:18px 20px;border:1px solid var(--line);border-radius:12px;background:var(--soft)}
.friends-invite h2{margin:0 0 10px;font-size:14px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.friends-code{margin:0 0 14px;font:700 30px/1.1 var(--mono);letter-spacing:.14em;word-break:break-word;color:var(--ink)}
.friends-invite .actions{margin:0 0 8px}
/* The copy fallback puts the whole invitation where eight characters were.
   Tracked 30px monospace is for a code, not for a sentence. */
.friends-code.friends-code-plain{font:400 15px/1.5 Arial,sans-serif;letter-spacing:0;word-break:break-word}

.friends-list{margin:22px 0}
.friends-list h2{margin:0 0 10px;font-size:14px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.friends-list ul{list-style:none;margin:0;padding:0}
.friends-list li{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:11px 0;border-bottom:1px solid var(--line)}
.friends-list button{font-size:12px;padding:5px 11px}

/* The viewer's own row is the one every other row is read against, so it is
   the only one that needs to be findable without counting. */
.friends-table th[scope="row"]{text-align:left;font-weight:600}
.friends-table tbody tr.friends-you{background:var(--soft)}
.friends-table tbody tr.friends-you th[scope="row"]{font-weight:800}
.friends-table td{font-variant-numeric:tabular-nums}
/* A cell where they beat you. Weight and colour rather than a background,
   because six of these in a row would read as a highlighted row. */
.friends-table td.friends-ahead{font-weight:800;color:var(--accent)}
/* Eight columns of digits, on a phone. The shared .player-table rule that
   breaks a long display name mid-word is aimed at the leaderboard, where
   column two is a name; here column two is a score, and 1,000 arriving as
   "1,00 / 0" reads as a bug rather than a number. So nothing in this table
   breaks, and the wrap scrolls sideways if it has to. */
.friends-table td,.friends-table th{white-space:nowrap}
.friends-table td:nth-child(2){overflow-wrap:normal}

.friends-verdicts{list-style:none;margin:14px 0 0;padding:0;font-size:14px;line-height:1.8}
@media(max-width:680px){.friends-code{font-size:24px;letter-spacing:.1em}.friends-list li{gap:10px}.friends-table{font-size:12px}.friends-table td,.friends-table th{padding:12px 4px}}

/* The website's Sign in with Apple, above the username form. The rule either
   side of "or" is drawn with borders rather than a background image so it
   follows the paper colour in both the game and the information pages. */
.player-apple{display:grid;gap:9px;max-width:480px;margin:24px 0 0}
.player-apple .error{color:var(--bad);margin:8px 0}
.player-apple .tiny-note{margin:0}

/* Apple's button, drawn to Apple's guidelines: their mark, their wording,
   white artwork on black, and at least as prominent as what sits beside it.
   A ghost button here read as the lesser option when it is in fact the only
   way most players have an account at all - eleven of the first fourteen.
   The mark is inline SVG so the button needs no network round trip and no
   Apple script until somebody actually presses it. */
.apple-signin{display:flex;align-items:center;justify-content:center;gap:9px;width:100%;min-height:50px;padding:0 18px;border:0;border-radius:8px;background:#000;color:#fff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:17px;font-weight:500;letter-spacing:-.01em;line-height:1;cursor:pointer;box-shadow:0 3px 0 #000}
.apple-signin:hover{background:#171717}
.apple-signin:active{transform:translateY(2px);box-shadow:0 1px 0 #000}
.apple-signin:focus-visible{outline:3px solid var(--action);outline-offset:3px}
.apple-signin:disabled{opacity:.45;cursor:default;transform:none;box-shadow:0 3px 0 #000}
.apple-signin-mark{width:17px;height:21px;flex:none;fill:currentColor;position:relative;top:-1px}
.player-apple-or{display:flex;align-items:center;gap:12px;max-width:480px;margin:20px 0 0;font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
/* One word, because anything longer wraps inside a phone-width panel and the
   flexed rules either side then collapse - the right-hand one vanishing
   altogether. The fields below are labelled Username and Password, so the
   caption has no work to do beyond separating the two routes. */
.player-apple-or::before,.player-apple-or::after{content:"";flex:1 0 18px;border-top:1px solid var(--line)}

/* The public delete-account page writes its fields as a label WRAPPING its
   input, rather than as the sibling pairs player.js emits. Without a rule of
   its own that label is inline, so the caption and the box sit on one line
   and the form reads as a run-on sentence. */
.player-form .field{display:grid;gap:6px}

/* Marks the route this browser used last. A quiet pill, not a recommendation:
   it sits on whichever of the two was used and changes nothing else, so the
   other route is never harder to reach than it was. */
.last-used{display:inline-flex;align-items:center;gap:7px;justify-self:start;margin:16px 0 0;padding:5px 11px;border:1px solid var(--line);border-radius:999px;background:var(--soft);font-size:12px;font-weight:700;letter-spacing:.02em;color:var(--muted)}
.last-used::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--action);flex:none}
.player-apple .last-used{margin:0}
