/* ============================================================
   Art Daily game chrome — sketchbook edition.
   Every drill wears this same paper: warm sheet, graphite ink,
   one watercolor accent (--game-accent), handwritten Caveat for
   the display type (shared with the page, OFL — /fonts/LICENSE.txt), mono for
   numbers and annotations. Paper-first: light is the default,
   dark is "night studio". Token NAMES match the Art Daily page
   so a game's canvas inks (--ink/--muted/--game-accent, read via
   getComputedStyle) follow the theme automatically.
   A game's own styles belong BELOW the marker at the end.
   ============================================================ */

@font-face {
  font-family: 'Caveat';
  src: url('../../fonts/caveat-latin.woff2') format('woff2');
  font-weight: 400 700;
  font-display: swap;
}

:root {
  color-scheme: light;
  --bg: #F6EFDF;
  --card: #FDFAF1;
  --ink: #33291E;
  --muted: #766850; /* AA on the paper card (was #8A7B66 at ~3.9:1) */
  --line: #D9CBB2;
  --shadow: rgba(59, 47, 32, 0.16);
  --focus: #C4622F;
  --link: #3E6C8E;
  --prompt: #C4622F;

  --coral: #E26D5A;
  --sunny: #E9A93D;
  --mint: #56A382;
  --sky: #5C93B8;
  --lilac: #907BC0;
  --bubblegum: #D077A0;

  --hand: 'Caveat', 'Segoe Print', 'Comic Sans MS', cursive;
  --mono: ui-monospace, "Cascadia Code", "JetBrains Mono", "Fira Code", Menlo, Consolas, monospace;

  --game-accent: var(--sky); /* TODO: pick this game's accent */
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #191511;
  --card: #221D16;
  --ink: #EFE7D7;
  --muted: #A39682;
  --line: #443A2C;
  --shadow: rgba(0, 0, 0, 0.5);
  --focus: #E88B4F;
  --link: #7FB2D8;
  --prompt: #E88B4F;

  --coral: #F08262;
  --sunny: #F2B345;
  --mint: #5FBF97;
  --sky: #6FADD6;
  --lilac: #A78FDF;
  --bubblegum: #E58AB5;
}

* { box-sizing: border-box; }

[hidden] { display: none !important; }

html { height: 100%; scrollbar-color: var(--muted) var(--bg); }

/* Selecting text runs a highlighter over it. */
::selection { background: #F3DF7E; color: #33291E; }
:root[data-theme="dark"] ::selection { background: #B99A2E; color: #191511; }

body {
  margin: 0;
  min-height: 100%;
  display: flex;
  flex-direction: column;
  background:
    radial-gradient(color-mix(in srgb, var(--ink) 6%, transparent) 1px, transparent 1.4px) 0 0 / 22px 22px,
    var(--bg);
  color: var(--ink);
  font-family: var(--mono);
  font-variant-ligatures: none;
  font-variant-numeric: tabular-nums lining-nums;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; }

:is(a, button, input, [tabindex]):focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ===== The sheet (keeps the .term class so games need no markup edits) ===== */

.term {
  position: relative;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 6px 14px 8px 12px;
  box-shadow: 0 2px 0 var(--shadow), 0 14px 30px -20px var(--shadow);
  text-align: left;
}
/* washi tape holding the sheet */
.term::before {
  content: "";
  position: absolute;
  top: -11px;
  left: 34px;
  width: 84px;
  height: 22px;
  transform: rotate(-3deg);
  background:
    repeating-linear-gradient(105deg, transparent 0 7px, rgba(255, 255, 255, 0.28) 7px 12px),
    color-mix(in srgb, var(--game-accent) 55%, transparent);
  border-radius: 2px;
  box-shadow: 0 1px 2px var(--shadow);
  pointer-events: none;
  z-index: 1;
}

/* The old terminal title bar becomes a pencil label in the corner. */
.term-bar {
  display: flex;
  justify-content: flex-end;
  padding: 10px 16px 0;
}
.dot { display: none; }
.term-title {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--muted);
  letter-spacing: 0.05em;
}

.term-body { padding: 14px 24px 26px; }

.promptline { margin: 0 0 10px; font-size: 0.85rem; font-weight: 700; color: var(--muted); }
.prompt { color: var(--prompt); font-weight: 900; user-select: none; }

/* ===== Topbar ===== */

.topbar { display: flex; align-items: center; gap: 8px; padding: 16px 16px 8px; }
.topbar-spacer { flex: 1; }

.backlink {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
  font-size: 0.82rem;
  text-decoration: none;
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: 3px 10px 4px 9px;
  background: var(--card);
  box-shadow: 0 2px 0 var(--shadow);
  transform: rotate(-0.6deg);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.backlink:hover { transform: rotate(0deg) translateY(-2px); box-shadow: 0 4px 0 var(--shadow); }

.iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 10px 4px 9px 5px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  cursor: pointer;
  padding: 0;
  text-decoration: none;
  box-shadow: 0 2px 0 var(--shadow);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.iconbtn:hover { transform: translateY(-2px) rotate(2deg); box-shadow: 0 4px 0 var(--shadow); }

/* Light (default) shows the moon (click → dark); dark shows the sun. */
.ic-sun { display: none; }
:root[data-theme="dark"] .ic-sun { display: inline; }
:root[data-theme="dark"] .ic-moon { display: none; }

/* ===== Stage ===== */

.stage {
  flex: 1;
  width: 100%;
  max-width: 860px;
  margin: 0 auto;
  padding: 20px 20px 48px;
}
.stage.game-wide { max-width: 780px; }

.game-body { text-align: left; }

/* ===== HUD ===== */

.game-hud {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}

.game-name {
  margin: 0;
  font-family: var(--hand);
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.05;
}
.game-emoji { margin-right: 2px; font-size: 1.5rem; }
.game-tagline {
  margin: 2px 0 0;
  font-family: var(--hand);
  font-size: 1.2rem;
  font-weight: 500;
  color: var(--muted);
}

.hud-stats { display: flex; gap: 8px; margin: 0; }

.hud-stat {
  min-width: 64px;
  padding: 5px 10px 6px;
  border: 1px solid var(--line);
  border-radius: 4px 10px 5px 9px;
  background: color-mix(in srgb, var(--line) 14%, var(--card));
  text-align: center;
}
.hud-stat dt {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.hud-stat dd {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 900;
  /* the 45% mix — the same ink the canvas uses — measured worst case 5.01:1 on paper (sunny); 55% left sunny at 4.09, under the 4.5 text owes */
  color: color-mix(in srgb, var(--game-accent) 45%, var(--ink));
}
/* …and pure accent on the dark sheet, where it already passes. */
:root[data-theme="dark"] .hud-stat dd { color: var(--game-accent); }

.hint { min-height: 1.6em; margin: 6px 0 10px; color: var(--muted); font-size: 0.83rem; font-weight: 600; }

/* ===== Drill stage ===== */

.game-stage { position: relative; }

/* The canvas stays transparent; this graph-paper grid shows through.
   Games repaint on ArtDaily.onTheme() so inks follow the theme. */
.game-canvas {
  display: block;
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 5px 12px 6px 11px;
  background:
    radial-gradient(color-mix(in srgb, var(--ink) 8%, transparent) 1px, transparent 1.5px) 0 0 / 18px 18px,
    var(--card);
  touch-action: none;      /* draw, don't scroll, on touch screens */
  cursor: crosshair;
}

/* Score pop — a little sticker. The global reduced-motion rule
   flattens the animation. */
.toast {
  position: absolute;
  left: 50%;
  top: 14px;
  transform: translateX(-50%) rotate(-1.5deg);
  padding: 6px 16px;
  border: 1px solid var(--line);
  border-radius: 4px 12px 5px 10px;
  background: var(--card);
  box-shadow: 0 3px 0 var(--shadow);
  font-family: var(--hand);
  font-size: 1.2rem;
  font-weight: 700;
  white-space: nowrap;
  animation: toast-pop 0.25s ease;
}
.toast .toast-accent { color: color-mix(in srgb, var(--game-accent) 45%, var(--ink)); }
:root[data-theme="dark"] .toast .toast-accent { color: var(--game-accent); }
@keyframes toast-pop {
  from { transform: translateX(-50%) translateY(-8px) rotate(-1.5deg); opacity: 0; }
  to   { transform: translateX(-50%) translateY(0) rotate(-1.5deg);    opacity: 1; }
}

/* ===== Controls — sticker buttons ===== */

.game-controls { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }

.btn {
  font-family: var(--hand);
  font-size: 1.18rem;
  font-weight: 700;
  color: var(--ink);
  padding: 6px 18px;
  border: 1px solid var(--line);
  border-radius: 4px 12px 5px 10px;
  background: var(--card);
  box-shadow: 0 2px 0 var(--shadow);
  cursor: pointer;
  transform: rotate(-0.5deg);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.btn:hover { transform: rotate(0deg) translateY(-2px); box-shadow: 0 4px 0 var(--shadow); }
.btn:active { transform: translateY(1px); box-shadow: 0 1px 0 var(--shadow); }
.btn:disabled { opacity: 0.45; cursor: default; transform: none; box-shadow: 0 1px 0 var(--shadow); }

.btn-primary {
  background: color-mix(in srgb, var(--game-accent) 26%, var(--card));
  border-color: color-mix(in srgb, var(--game-accent) 60%, var(--line));
}

.howto {
  margin-top: 12px;
  padding: 10px 16px;
  border: 1px dashed var(--line);
  border-radius: 6px 12px 6px 12px;
  color: var(--muted);
  font-size: 0.83rem;
  font-weight: 600;
}
.howto p { margin: 4px 0; }
.howto-cmd { font-weight: 800; }

/* ---- page copy ----
   What this drill is, in prose, for the visitor who arrived from a search
   result rather than from the catalogue — the drill itself says almost
   nothing a crawler can read, because it is a canvas. It sits OUTSIDE
   <main> and is hidden in the player (see the :root.embed rule further
   down), so the arcade's iframe is exactly what it always was. */
.about {
  width: 100%;
  max-width: 860px;      /* the .stage column, so it lines up under the drill */
  margin: 0 auto;
  padding: 0 20px 40px;
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.65;
}
.about h2, .about h3 {
  color: var(--ink);
  font-family: var(--hand);
  font-weight: 700;
  letter-spacing: 0.01em;
}
.about h2 { font-size: 1.5rem; margin: 8px 0 6px; }
.about h3 { font-size: 1.2rem; margin: 18px 0 4px; }
.about p { margin: 0 0 10px; }
.about a { color: var(--link); }
.about-more {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px dashed var(--line);
  font-size: 0.86rem;
}

/* ===== Footer ===== */

.footer { text-align: center; padding: 40px 20px 28px; color: var(--muted); }
.footnav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-weight: 700;
  font-size: 0.85rem;
}
.footnav a { text-decoration: none; }
.footnav a:hover { text-decoration: underline wavy; text-decoration-thickness: 2px; }
#supportLinks { display: contents; }
.heart-ink { color: var(--coral); }
.fineprint { margin: 12px 0 0; font-size: 0.76rem; }

/* ===== Embedded inside the Art Daily player ===== */
/* The player supplies the sheet, so the game sheds its own. */

:root.embed .topbar,
:root.embed .footer,
:root.embed .term-bar { display: none; }
:root.embed .stage { padding: 10px 12px 16px; max-width: none; }
:root.embed .term { border: 0; box-shadow: none; border-radius: 0; background: transparent; }
:root.embed .term::before { display: none; }
:root.embed .term-body { padding: 0; }
:root.embed .about { display: none; }

@media (max-width: 480px) {
  .stage { padding: 14px 12px 36px; }
  .term-body { padding: 12px 16px 20px; }
  .game-name { font-size: 1.7rem; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* The SDK fills this when it knows the input hardware. Scores are eased
   per device, so the drill says which device it eased for. */
.hud-input { min-width: 0; border: 0; background: none; padding: 5px 2px; display: flex; align-items: flex-end; }
.hud-input dd {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--muted);
  max-width: 8.5rem;
  line-height: 1.25;
}

/* Shown by the SDK when a drill is played on its own page: progress
   lives per-origin, so a standalone score needs a way home. */
.handoff {
  margin: 12px 0 0;
  padding: 9px 14px;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--muted);
  border: 1px dashed color-mix(in srgb, var(--game-accent) 55%, var(--line));
  border-radius: 5px 12px 6px 11px;
  background: color-mix(in srgb, var(--game-accent) 8%, transparent);
}
.handoff-link {
  font-family: var(--hand);
  font-size: 1.15rem;
  font-weight: 700;
  color: color-mix(in srgb, var(--game-accent) 45%, var(--ink));
  text-decoration: underline;
  text-underline-offset: 3px;
}
:root[data-theme="dark"] .handoff-link { color: var(--game-accent); }

/* ============================================================
   game-specific styles below this line
   ============================================================ */

/* palette-pick: painted scene on the canvas, chip picker below */

/* no canvas input in this drill — let touch swipes scroll the page */
.game-canvas { cursor: default; touch-action: auto; }

.picker { margin-top: 12px; }

.picker-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 10px;
}

.slots { display: flex; gap: 8px; }

.slot {
  width: 46px;
  height: 46px;
  padding: 0;
  border: 2px dashed var(--line);
  border-radius: 5px 11px 6px 10px;
  background: color-mix(in srgb, var(--line) 12%, var(--card));
  /* --muted alone is ~3.9:1 on the paper card; mix ink in for ≥ 4.5:1 */
  color: color-mix(in srgb, var(--muted) 55%, var(--ink));
  font-family: var(--mono);
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
  transition: transform 0.15s ease;
}
.slot:hover { transform: translateY(-2px); }
.slot.filled {
  border-style: solid;
  border-color: color-mix(in srgb, var(--ink) 35%, var(--line));
  color: transparent;
}

.btn-lock { margin-left: auto; }

/* Wider gutters: a one-cell overshoot in a 12-wide grid is the drill's
   most common non-colour error. The chips stay 1fr wide so the grid can
   never overflow its column count on a narrow sheet.
   The gap is declared HERE (and per breakpoint below) rather than in a
   trailing override — an override at the end of the file has the same
   specificity as the media-query rules and comes after them, so it won
   at every width and silently widened the gutters the breakpoints below
   were sized around. */
/* THE ROW GUTTER IS WIDER THAN THE COLUMN GUTTER ON EVERY REFLOWED
   LAYOUT, and that is a scoring-fairness measure, not a decoration.
   The sheet is built as 4 tone rows × 12 hue columns (HUE_COLS), so at
   the full 12 columns the chip to the RIGHT is one hue step and the chip
   BELOW is one tone step — measured at 1.00 and 1.17 cells, i.e. 50 and
   42 out of 100 for that role against ZERO_CELLS = 2. Below 704px the
   grid reflows and the chip below is no longer the next tone, it is
   `cols` HUE steps away: measured 2.74 cells at 8 columns and 3.12 at 6,
   both a flat 0. So the same one-chip aiming slip costs 42 on a laptop
   and everything on a phone, purely because the sheet rewrapped.
   The price is fixed by the colour maths and must stay that way; what
   can be changed is how easy the expensive slip is to make. Column gaps
   are left EXACTLY as the breakpoint maths below assumes (they set the
   44px chip edge), and only the rows are opened up. */
.chips {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: 8px;
  row-gap: 8px;   /* 12 columns: down IS the next tone, nothing to guard */
}
.chip {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 4px 8px 5px 7px;
  cursor: pointer;
  transition: transform 0.12s ease;
}
.chip:hover { transform: translateY(-2px); }
/* PICKED CHIPS STAY TAPPABLE — a retap unpicks them — which means they
   also stay FOCUSABLE, and the fade that marks them used to be
   `opacity: 0.3` on the button itself. `opacity` composites the whole
   element as one group, its outline included, so the shared
   :focus-visible ring faded with the chip: --focus at 0.3 over the
   sheet measures 1.45:1 in the light theme and 1.74:1 in the night
   studio, against the 3:1 a focus indicator has to clear (full
   strength it is 3.92 / 6.56). A keyboard player tabbing back to
   un-pick a chip could not see where they were standing — on precisely
   the chips they had a reason to return to.
   Draw the fade as an OVERLAY instead. The fill dims by the same
   amount over the same sheet colour, and the border and the focus ring
   keep full strength because neither is inside the faded box. */
.chip[aria-pressed="true"] { transform: none; }
.chip[aria-pressed="true"]::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--card); /* the sheet behind the grid — .term's background */
  opacity: 0.7;
  pointer-events: none;
}
.chip:disabled { cursor: default; transform: none; }

/* reveal: the three true chips get an ink ring in the still-visible grid.
   (No focus clash here: every chip is disabled for the reveal, so none
   of them can hold focus while this outline is on.) */
.chip.rv-true {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
  z-index: 1;
}
/* a correct pick shows full strength */
.chip.rv-true[aria-pressed="true"]::after { display: none; }

/* Fewer columns as the sheet narrows, so every chip stays ≥ 44px — the
   touch-target floor, and the whole reason a finger can play this at all.
   A chip's edge is (C − gap × (cols − 1)) / cols, where C is the drill's
   own content box: the shared sheet spends 88px of chrome on it above
   480px (.stage 20 + .term-body 24, per side) and 56px at or below, so
   C = V − 88 / V − 56. Each breakpoint below is the width where the next
   column count would put that edge under 44 — including the ugly step at
   480px, where C DROPS by 32px as the chrome tightens, which is why 8
   columns cannot be carried down to 480 itself.
     12 cols, gap 8 → needs C ≥ 616 → V ≥ 704
      8 cols, gap 8 → needs C ≥ 408 → V ≥ 496
      6 cols, gap 6 → needs C ≥ 294 → V ≥ 350
      5 cols, gap 6 → needs C ≥ 244 → V ≥ 300
      4 cols, gap 6 → needs C ≥ 194 → V ≥ 250  */
@media (max-width: 703px) {
  .chips { grid-template-columns: repeat(8, 1fr); column-gap: 8px; row-gap: 16px; }
}
@media (max-width: 495px) {
  .chips { grid-template-columns: repeat(6, 1fr); column-gap: 6px; row-gap: 14px; }
}
@media (max-width: 359px) {
  .chips { grid-template-columns: repeat(5, 1fr); column-gap: 6px; row-gap: 14px; }
}
@media (max-width: 307px) {
  .chips { grid-template-columns: repeat(4, 1fr); column-gap: 6px; row-gap: 14px; }
}

/* narrow screens: pin the scene while the chip grid scrolls beneath it */
@media (max-width: 640px) {
  .game-stage {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--bg);
    padding-bottom: 4px;
  }
}

.reveal {
  margin-top: 12px;
  padding: 10px 14px 12px;
  border: 1px solid color-mix(in srgb, var(--game-accent) 55%, var(--line));
  border-radius: 6px 12px 6px 12px;
  font-size: 0.8rem;
  font-weight: 600;
}
.reveal-title {
  margin: 0 0 6px;
  font-family: var(--hand);
  font-size: 1.25rem;
  font-weight: 700;
  color: color-mix(in srgb, var(--game-accent) 55%, var(--ink));
}
:root[data-theme="dark"] .reveal-title { color: var(--game-accent); }

.rv-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 5px 0;
}
.rv-bar {
  height: 22px;
  border: 1px solid var(--line);
  border-radius: 4px;
  flex: 0 0 auto;
}
/* true colour + your pick, butted edge to edge so subtle misses read */
.rv-pair { display: inline-flex; flex: 0 0 auto; }
.rv-pair .rv-bar {
  height: 34px;
  border-radius: 4px 0 0 4px;
  border-right: 0;
}
.rv-swatch {
  width: 34px;
  height: 34px;
  border: 1px solid var(--line);
  border-radius: 0 4px 4px 0;
  flex: 0 0 auto;
}
.rv-label { color: color-mix(in srgb, var(--muted) 55%, var(--ink)); min-width: 110px; }
.rv-de { font-variant-numeric: tabular-nums; }
.rv-note { margin: 6px 0 0; color: color-mix(in srgb, var(--muted) 55%, var(--ink)); }

/* ============================================================
   Tablet + phone gestures — shared hardening.
   A slow, deliberate press is exactly the gesture that raises the
   iOS copy/share callout over a drawing surface, and a quick second
   tap on a control is exactly what zooms the sheet mid-round. Both
   read to a beginner as "this page is broken", so both are shut off
   here rather than left to the platform default.
   ============================================================ */
html, body { overscroll-behavior-y: contain; }

.game-canvas {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

button, .btn {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  touch-action: manipulation;  /* a second quick tap must not zoom the sheet */
}

.btn { min-height: 44px; }     /* the phone tap-target floor */

/* ---- role captions under the three slots ----
   The words "dominant / secondary / accent" used to be asked for in the
   hint and only decoded by the reveal, i.e. after the score. Name the
   roles in plain English on the first screen instead. */
.slots { align-items: flex-start; }
.slot-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  width: 4.6em;
}
.slot-cap {
  font-size: 0.6rem;
  font-weight: 800;
  line-height: 1.15;
  text-align: center;
  letter-spacing: 0.01em;
  color: color-mix(in srgb, var(--muted) 55%, var(--ink));
}

/* (the chip grid's gutters and column breakpoints live with the .chips
   rule above, so the media queries are not overridden from down here) */
