/* ============================================================
   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(--bubblegum); /* 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
   ============================================================ */

/* ===== temperature-sort board (replaces the canvas) ===== */

/* The selection ring is the ONLY signal that the tap-two-to-swap path —
   the keyboard and trackpad path — has hold of a chip, and bare
   bubblegum measures 2.95:1 against the paper sheet: under the 3:1 floor
   a non-text mark that carries meaning has to clear. Ink it on paper
   (4.5:1) and leave it bright in the night studio, where it already
   reads at 6.9:1. Same split the rank pills below use. */
.ts-board { --ring-accent: color-mix(in srgb, var(--game-accent) 70%, var(--ink)); }
:root[data-theme="dark"] .ts-board { --ring-accent: var(--game-accent); }

.ts-board {
  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);
  padding: 14px 16px 16px;
}

.ts-ends {
  display: flex;
  justify-content: space-between;
  font-family: var(--hand);
  font-size: 1.1rem;
  font-weight: 700;
  line-height: 1.2;
  margin-bottom: 8px;
}
/* decorative end labels, gently tinted toward their temperature */
.ts-end-warm { color: color-mix(in srgb, var(--coral) 70%, var(--ink)); transform: rotate(-2deg); }
.ts-end-cool { color: color-mix(in srgb, var(--sky) 70%, var(--ink)); transform: rotate(1.5deg); }

.ts-chips { display: flex; gap: 8px; }

.ts-chip {
  position: relative;
  flex: 1;
  min-width: 44px; /* never below the 44px touch-target floor */
  height: 72px;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--ink) 30%, transparent);
  border-radius: 4px 10px 5px 9px;
  cursor: grab; /* chips drag — grab affords it */
  box-shadow: 0 2px 0 var(--shadow);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  touch-action: pan-y; /* horizontal drags sort; vertical swipes still scroll */
  user-select: none;
  -webkit-user-select: none;
}
.ts-chip:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 4px 0 var(--shadow); }
.ts-chip:disabled { cursor: default; }

/* mid-drag: the chip rides the pointer — no transition lag, above
   its neighbours, deeper shadow */
.ts-chip.is-dragging {
  transition: none;
  z-index: 5;
  cursor: grabbing;
  box-shadow: 0 6px 0 var(--shadow);
}

/* first tap: the accent ring (box-shadow so it never fights the
   focus-visible outline) */
.ts-chip.is-selected {
  transform: translateY(-4px) rotate(-1.5deg);
  box-shadow:
    0 0 0 3px var(--card),
    0 0 0 6px var(--ring-accent, var(--game-accent)),
    0 5px 0 var(--shadow);
}

/* reveal: warmth-rank pill on each chip (paper pill = misplaced,
   accent pill = chip sits at its own rank) */
.ts-rank {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  min-width: 26px;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.85rem;
  font-weight: 900;
  line-height: 1.5;
  pointer-events: none;
}
.ts-rank.is-ok {
  border-color: color-mix(in srgb, var(--game-accent) 70%, var(--ink));
  background: color-mix(in srgb, var(--game-accent) 30%, var(--card));
  color: color-mix(in srgb, var(--game-accent) 45%, var(--ink));
}
/* 65% accent (not 80) — keeps the pill ≥ 4.5:1 on its tinted bg in dark */
:root[data-theme="dark"] .ts-rank.is-ok { color: color-mix(in srgb, var(--game-accent) 65%, var(--ink)); }

/* reveal strip: the full warm→cool arc; numbered ticks mark each
   swatch's true hue position (top padding leaves room for numbers).
   The wrap keeps its space while sorting (visibility, not display)
   so the "done sorting" button never jumps at the reveal. */
.ts-strip-wrap { padding-top: 26px; margin-top: 6px; visibility: hidden; }
.ts-strip-wrap.is-shown { visibility: visible; }

.ts-strip {
  position: relative;
  height: 14px;
  border-radius: 7px;
  border: 1px solid color-mix(in srgb, var(--ink) 25%, transparent);
}

/* Same correct/misplaced split as the rank pills, but carried by the
   NUMBER only: the numbers sit above the strip on --card, where both
   themes clear AA (13.6:1 graphite, 6.7:1 / 10.1:1 accent). */
.ts-mark {
  position: absolute;
  top: -24px;
  transform: translateX(-50%);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 900;
  color: var(--ink);
}
.ts-mark.is-ok { color: color-mix(in srgb, var(--game-accent) 45%, var(--ink)); }
:root[data-theme="dark"] .ts-mark.is-ok { color: color-mix(in srgb, var(--game-accent) 80%, var(--ink)); }

/* The tick lies ON the gradient, and the gradient is data — it is the
   same light, saturated ramp in both themes. So the tick takes a fixed
   graphite rather than var(--ink): dark-theme ink is near-white and
   managed only 2.2:1 against the strip's cyan. Fixed graphite holds
   >= 4.3:1 across the whole arc in both themes.
   Correctness is NOT encoded in the tick's colour — an accent tint dark
   enough to stay legible here is indistinguishable from the graphite
   (1.4:1 apart) — so a correct tick is marked by WEIGHT instead, and by
   its number above. */
.ts-mark::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 1.25em;
  width: 2px;
  height: 22px;
  transform: translateX(-50%);
  background: #33291E;
  border-radius: 1px;
}
.ts-mark.is-ok::after { width: 4px; border-radius: 2px; }

.ts-actions { display: flex; justify-content: center; margin-top: 16px; }

@media (max-width: 480px) {
  .ts-board { padding-left: 10px; padding-right: 10px; } /* wider chips on narrow phones */
  .ts-chips { gap: 6px; }
  .ts-chip { height: 60px; }
}

/* ============================================================
   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 */

/* ---- the tap-to-swap path made visible ----
   It was the trackpad-friendly path and the only one with no affordance
   at all: `cursor: grab` advertised dragging, the swap lived in prose. */
.ts-swap-tip {
  margin: 8px 0 0;
  text-align: center;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: color-mix(in srgb, var(--muted) 45%, var(--ink));
}
.ts-swap-tip strong { color: var(--ink); }

/* the pre-set-1 arc: same strip, no marks, quieter */
.ts-strip-wrap.is-preview { opacity: 0.72; }
