/* =============================================================================
   Arrow Doodle — the game's own skin
   Ported 1:1 from ui/theme/{Color,Palettes,Type}.kt. See .claude/docs/04.
   Warm paper and ink by day, soft dark by night. Baloo 2 display, system body.
   ========================================================================== */

/* ── Fonts ─────────────────────────────────────────────────────────────────
   Self-hosted, subset to latin + latin-ext from the app's own TTFs.
   SIL OFL 1.1 — see assets/fonts/OFL.txt. */
@font-face { font-family:'Baloo 2'; font-weight:500; font-display:swap;
  src:url('../fonts/baloo2-medium.woff2') format('woff2'); }
@font-face { font-family:'Baloo 2'; font-weight:600; font-display:swap;
  src:url('../fonts/baloo2-semibold.woff2') format('woff2'); }
@font-face { font-family:'Baloo 2'; font-weight:700; font-display:swap;
  src:url('../fonts/baloo2-bold.woff2') format('woff2'); }
@font-face { font-family:'Baloo 2'; font-weight:800; font-display:swap;
  src:url('../fonts/baloo2-extrabold.woff2') format('woff2'); }

/* ── Tokens: Day (Palettes.Light) ──────────────────────────────────────────
   Every colour is defined here, on bare :root, so nothing has its only
   definition inside a media query. Night overrides values only. */
:root {
  --bg:#F3EAD8;            /* PaperBg */
  --board-bg:#F3EAD8;
  --surface:#FBF5E9;       /* PaperSurface */
  --variant:#EDE3CE;       /* PaperVariant */
  --line:#E0D5BE;          /* PaperLine */
  --ink:#201D1B;           /* BuddyInk */
  --ink-soft:#3A3735;      /* BuddyInkSoft */
  --primary:#C88CEF;       /* BuddyLilac2 — label is INK, never white */
  --primary-hi:#D69FF2;    /* BuddyLilac */
  --blue:#5A4EFF;          /* BuddyBlue — hint / "free to go" */
  --orchid:#EEA0FF;        /* BuddyOrchid — hearts */
  --lime:#D9F25C;          /* BuddyLime */
  --valid-flash:#63B25E;   /* BoardPalette.validFlash — a departing arrow */
  --olive:#B7CE55;         /* BuddyOlive */
  --amber:#F3C56B;         /* BubbleAmber */
  --danger:#E2574E;        /* BuddyError — armed */
  --shadow:rgba(32,29,27,.14);
  --shadow-lift:rgba(32,29,27,.20);

  --font-body:system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue',sans-serif;
  --font-display:'Baloo 2',var(--font-body);

  --r-sm:10px; --r-md:16px; --r-lg:22px; --r-xl:30px; --r-pill:999px;

  /* Motion — docs/19. Same curves as host A: the two sites are one studio. */
  --ease:cubic-bezier(.4,0,.2,1);
  --bounce:cubic-bezier(.34,1.56,.64,1);
  --t-micro:150ms; --t-std:280ms;
  --maxw:900px; --nav-h:60px;
  --safe-t:env(safe-area-inset-top,0px);
  --safe-b:env(safe-area-inset-bottom,0px);
  --safe-l:env(safe-area-inset-left,0px);
  --safe-r:env(safe-area-inset-right,0px);
}

/* Night follows the system unless the visitor pinned Day. */
@media (prefers-color-scheme:dark) {
  :root:not([data-theme="light"]) {
    --bg:#1E1B17; --board-bg:#1E1B17; --surface:#26221C; --variant:#322C24;
    --line:#3A342B; --ink:#F2EEE8; --ink-soft:#C9C3B9;
    --blue:#9F97FF; --danger:#F2A0A0; --valid-flash:#B7CE55;
    --shadow:rgba(0,0,0,.42); --shadow-lift:rgba(0,0,0,.55);
  }
}
/* The explicit toggle wins in both directions. */
:root[data-theme="dark"] {
  --bg:#1E1B17; --board-bg:#1E1B17; --surface:#26221C; --variant:#322C24;
  --line:#3A342B; --ink:#F2EEE8; --ink-soft:#C9C3B9;
  --blue:#9F97FF; --danger:#F2A0A0; --valid-flash:#B7CE55;
  --shadow:rgba(0,0,0,.42); --shadow-lift:rgba(0,0,0,.55);
}

/* ── Reset ────────────────────────────────────────────────────────────────── */
*,*::before,*::after { box-sizing:border-box; margin:0; padding:0; }
html {
  -webkit-text-size-adjust:100%; scroll-behavior:smooth;
  /* Installed there is no address bar to rubber-band against, so the bounce
     just drags the whole app up off the screen and back. */
  overscroll-behavior-y:none;
}
body {
  font-family:var(--font-body);
  background:var(--bg);
  color:var(--ink);
  line-height:1.6;
  /* dvh, not vh: on a phone browser `100vh` is the viewport with the URL bar
     HIDDEN, so a full-height page is always taller than the screen and always
     scrolls a little. Installed, the two are the same and nothing changes. */
  min-height:100dvh;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
  /* Kills the double-tap-to-zoom delay on every control. The board declares
     `touch-action:none` of its own, because it handles pinch itself. */
  touch-action:manipulation;
}
img,svg,canvas { display:block; max-width:100%; }
a { color:inherit; text-underline-offset:.18em; }
button { font:inherit; color:inherit; }
:focus-visible {
  outline:3px solid var(--blue);
  outline-offset:3px;
  border-radius:6px;
}
@media (prefers-reduced-motion:reduce) {
  *,*::before,*::after { animation:none!important; transition:none!important; scroll-behavior:auto!important; }
}

h1,h2,h3,h4 { font-family:var(--font-display); font-weight:800; line-height:1.15; letter-spacing:-.01em; }
h1 { font-size:clamp(1.9rem,5vw,2.7rem); }
h2 { font-size:clamp(1.4rem,3.4vw,1.9rem); font-weight:700; margin-top:2.2em; }
h3 { font-size:1.12rem; font-weight:700; margin-top:1.6em; }
p { margin:.85em 0; }
p,li { max-width:66ch; }

.skip {
  position:absolute; left:-9999px; top:0; z-index:100;
  background:var(--ink); color:var(--bg);
  padding:.7em 1.1em; border-radius:0 0 var(--r-sm) 0; font-weight:700;
}
.skip:focus { left:0; }

/* The side insets matter in landscape on a notched phone, where a rotated
   cutout eats into the left or right edge. */
.wrap {
  width:min(100% - 2rem - var(--safe-l) - var(--safe-r), var(--maxw));
  margin-inline:auto;
  padding-left:var(--safe-l); padding-right:var(--safe-r);
}

/* `bolder` from an inherited 700 computes to 900, and Baloo 2 ships 500/600/
   700/800 — the browser synthesises the missing face. Absolute weight instead. */
b, strong { font-weight:700; }

/* ── Header ───────────────────────────────────────────────────────────────── */
.site-head {
  position:sticky; top:0; z-index:20;
  padding-top:var(--safe-t);
  background:color-mix(in srgb,var(--bg) 88%,transparent);
  backdrop-filter:blur(10px);
  border-bottom:1px solid var(--line);
}
.site-head .wrap {
  display:flex; align-items:center; gap:.75rem;
  min-height:var(--nav-h);
}
.brand {
  display:flex; align-items:center; gap:.55rem;
  font-family:var(--font-display); font-weight:800; font-size:1.12rem;
  text-decoration:none; letter-spacing:-.02em;
}
.brand img { width:30px; height:30px; border-radius:8px; }
.site-nav { display:flex; gap:.35rem; margin-left:auto; align-items:center; }
/* Baloo 2, because these are LABELS. Type.kt puts labelLarge/labelMedium on
   Baloo 2 "so buttons and HUD read game" — and `.btn` already does, so a
   system-ui link sitting next to it put two typefaces at the same size in the
   same header. Body prose stays the system sans, exactly as the app has it. */
.site-nav a:not(.btn) {
  padding:.55rem .7rem; border-radius:var(--r-pill);
  text-decoration:none; font-family:var(--font-display);
  font-weight:600; font-size:.92rem; color:var(--ink);
  min-height:44px; display:inline-flex; align-items:center;
}
.site-nav a:not(.btn):hover { background:var(--variant); color:var(--ink); }
.site-nav a:not(.btn)[aria-current="page"] { color:var(--ink); background:var(--variant); }
.site-nav .btn { min-height:40px; padding:.4rem .9rem; font-size:.9rem; white-space:nowrap; }
/* The way back to the studio. It leaves this host, so it says so with the
   same glyph host A uses on its own outbound links — but it stays in the SAME
   tab, because it is our property and a visitor going home should keep their
   back button. Rule 16 is about leaving the property, not about leaving a
   host. */
.site-nav__out { white-space:nowrap; }
.site-nav__out .out { margin-left:.15em; font-size:.85em; opacity:.75; }

/* Narrow phones: the header has four things in it and 390px is not enough for
   all four. The two text links fold into a second row under the brand, and the
   controls stay where the thumb expects them. Nothing is hidden behind a
   hamburger — a nav a crawler cannot see is a nav that does not count. */
@media (max-width:560px) {
  .site-head .wrap { flex-wrap:wrap; padding-block:.5rem; row-gap:.35rem; }
  .brand { font-size:1rem; }
  .brand span { white-space:nowrap; }
  .site-nav { order:3; width:100%; margin-left:0; justify-content:flex-start; }
  .site-nav a:not(.btn) { padding:.4rem .6rem; font-size:.88rem; min-height:38px;
    white-space:nowrap; }
  .site-nav .btn { margin-left:auto; }
  .site-head [data-theme-toggle] { order:2; margin-left:auto; }
}
/* 360px. The nav gained a fourth item (the way back to the studio) and "How to
   play" started wrapping to a second line, which knocked the whole row out of
   alignment — visible in the captured install screenshot before this tier
   existed. Nothing is hidden: a nav a crawler cannot see is a nav that does not
   count, and one the thumb cannot reach is worse. */
@media (max-width:25rem) {
  .site-nav { gap:.1rem; }
  .site-nav a:not(.btn) { padding:.35rem .4rem; font-size:.8rem; }
  .site-nav .btn { padding:.35rem .75rem; font-size:.82rem; }
  .brand { font-size:.95rem; }
}

/* ── Buttons ──────────────────────────────────────────────────────────────
   The lilac primary carries an INK label, exactly as the app does. White on
   lilac is 1.9:1 and would fail AA; ink on lilac is 8.4:1. */
.btn {
  display:inline-flex; align-items:center; justify-content:center; gap:.5rem;
  min-height:48px; padding:.72rem 1.3rem;
  font-family:var(--font-display); font-weight:700; font-size:1rem;
  border:none; border-radius:var(--r-pill); cursor:pointer;
  text-decoration:none; text-align:center;
  transition:transform var(--t-micro) var(--bounce),box-shadow var(--t-micro) var(--ease),background var(--t-micro) var(--ease);
}
.btn-primary {
  background:linear-gradient(180deg,var(--primary-hi),var(--primary));
  color:#201D1B;
  box-shadow:0 3px 0 color-mix(in srgb,var(--primary) 70%,#000),0 6px 18px var(--shadow);
}
.btn-primary:hover { transform:translateY(-1px); }
.btn-primary:active { transform:translateY(3px); box-shadow:0 0 0 color-mix(in srgb,var(--primary) 70%,#000); }
.btn-ghost {
  background:transparent; color:var(--ink);
  border:2px solid var(--line); font-weight:600;
}
.btn-ghost:hover { background:var(--variant); }
.btn-icon {
  min-height:44px; min-width:44px; padding:.5rem;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-md); cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center;
  font-weight:700;
}
.btn-icon { transition:transform var(--t-micro) var(--bounce), background var(--t-micro) var(--ease); }
.btn-icon:hover { background:var(--variant); transform:scale(1.12); }
.btn-icon:active { transform:scale(.9); }
.btn-row { display:flex; flex-wrap:wrap; gap:.7rem; margin:1.5rem 0; }

/* ── Panels ───────────────────────────────────────────────────────────────── */
.panel {
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-lg); padding:1.4rem;
  box-shadow:0 2px 10px var(--shadow);
}
.rule-card {
  background:var(--surface); border:1px solid var(--line);
  border-left:5px solid var(--primary);
  border-radius:var(--r-md); padding:1.1rem 1.3rem; margin:1.6rem 0;
}
.rule-card strong { font-family:var(--font-display); }

/* ── Level cards ──────────────────────────────────────────────────────────── */
.level-grid {
  display:grid; gap:1rem; margin:1.6rem 0;
  grid-template-columns:repeat(auto-fill,minmax(215px,1fr));
}
.level-card {
  display:flex; flex-direction:column; gap:.35rem;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-lg); padding:1.1rem;
  text-decoration:none; color:inherit;
  transition:transform .14s ease,box-shadow .14s ease;
}
/* The lift is exaggerated enough to be felt (6px, not 2) and the drawing
   inside leans forward a little further than the card does — a follow-through,
   so the card reads as having depth rather than as a sliding rectangle. */
.level-card:hover { transform:translateY(-6px); box-shadow:0 14px 30px var(--shadow-lift); }
.level-card svg { transition:transform var(--t-std) var(--bounce); }
.level-card:hover svg { transform:scale(1.06) translateY(-2px); }
.level-card:active { transform:translateY(-1px) scale(.985); }
.level-card .n {
  font-family:var(--font-display); font-weight:800; font-size:.8rem;
  color:var(--ink-soft); letter-spacing:.08em; text-transform:uppercase;
}
.level-card .shape { font-family:var(--font-display); font-weight:800; font-size:1.3rem; }
.level-card .meta { font-size:.86rem; color:var(--ink-soft); }
.level-card svg { width:100%; height:auto; margin:.3rem 0; }

/* ── The board ────────────────────────────────────────────────────────────── */
/* The board, the HUD and the live region are ONE unit. They were siblings once,
   and play.js looked for the HUD inside .board-shell — so every engine check
   passed while a player watched a frozen heart count. Grouping them is what
   makes that impossible; C6b and C6c assert it from the DOM. */
/* ── The play-first hub (sprint 10 T6) ────────────────────────────────────
   This host exists for the game, so the game is what it opens with. Each
   section answers one question, in order: what is it, play it, how it works,
   what else is here, what the full game adds. */
.play-intro { text-align:center; max-width:44rem; margin:0 auto 1.1rem; }
/* Deliberately smaller than an h1 elsewhere: every pixel here is a pixel
   the board does not get, and the board is the point of the page. */
.play-intro h1 { margin-bottom:.35em; font-size:clamp(1.5rem,5.4vw,2.2rem); }
.one-rule {
  display:block; max-width:34rem; margin:1rem auto 0; text-align:left;
  padding:.7rem 1.1rem;
  background:var(--surface); border:2px solid var(--line); border-radius:var(--r-lg);
  box-shadow:0 6px 18px var(--shadow); font-size:1.02rem;
}
.play-now { margin:0 auto 3.25rem; max-width:760px; }
.play-under { text-align:center; margin-top:1rem; color:var(--ink-soft); font-size:.95rem; }
.scroll-cue {
  text-align:center; font-size:1.9rem; color:var(--ink-soft); margin-top:.75rem;
  animation:ad-cue 1.6s ease-in-out infinite;
}
@keyframes ad-cue { 0%,100%{transform:translateY(0);} 50%{transform:translateY(7px);} }

.steps { list-style:none; counter-reset:step; display:grid; gap:1rem; margin:1.25rem 0; }
.steps li {
  counter-increment:step; position:relative;
  background:var(--surface); border:2px solid var(--line); border-radius:var(--r-lg);
  padding:1rem 1.25rem 1rem 3.4rem; box-shadow:0 6px 16px var(--shadow);
}
/* The numbers are real information here: the steps are a sequence you work
   through in order, which is the only reason to number anything. */
.steps li::before {
  content:counter(step); position:absolute; left:1rem; top:1rem;
  width:1.7rem; height:1.7rem; border-radius:50%; display:grid; place-items:center;
  background:var(--primary); color:var(--ink); font-family:var(--font-display);
  font-weight:800; font-size:.95rem;
}
.steps h3 { margin-bottom:.25rem; }
.steps p { color:var(--ink-soft); }

.board-wrap { display:block; }

.board-shell {
  position:relative;
  /* Reserving the box is what keeps CLS at 0 — the canvas never resizes the
     page when the level JSON arrives. */
  aspect-ratio:1/1;
  width:100%;
  /* Every CSS pixel here is arrowhead. A 39x39 board in a 386 px square puts
     the cell at 9 px; the same board in a 640 px square puts it at 15. Bounded
     by the viewport HEIGHT too, so a square board never pushes its own HUD off
     the screen on a laptop. */
  max-width:min(100%,720px,72vh);
  margin:1.2rem auto;
  border-radius:var(--r-lg);
  border:1px solid var(--line);
  background:var(--board-bg);
  overflow:hidden;
  box-shadow:0 6px 26px var(--shadow);
  touch-action:none;
}
.board-shell canvas { width:100%; height:100%; }
.board-shell canvas:focus-visible { outline:3px solid var(--blue); outline-offset:-3px; }
/* Placed AFTER every base rule it overrides. A media query adds no specificity,
   so this block sitting next to `.play-intro` lost to a `.play-intro h1` rule
   defined further down the file and did nothing at all.

   Every line above the board is a line of scrolling before somebody can play,
   and on a phone the HUD is what falls off the bottom when there is one too
   many. */
@media (max-width:30rem) {
  .play-intro { margin-bottom:.6rem; }
  .play-intro h1 { margin-bottom:.2em; }
  .one-rule { padding:.55rem .85rem; font-size:.95rem; }
  .board-shell { margin:.7rem auto; }
}

.hud {
  display:flex; align-items:center; gap:.9rem; flex-wrap:wrap;
  max-width:560px; margin:0 auto; padding:.2rem;
  font-family:var(--font-display); font-weight:700;
}
.hud .hearts { color:var(--orchid); font-size:1.15rem; letter-spacing:.1em; }
.hud .hearts .spent { opacity:.24; }
.hud .stat { color:var(--ink-soft); font-size:.94rem; }
.hud .stat b { color:var(--ink); font-variant-numeric:tabular-nums; }
.hud .tools { margin-left:auto; display:flex; gap:.4rem; }

.sr-only {
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

/* ── Sheets ───────────────────────────────────────────────────────────────── */
.sheet-backdrop {
  position:fixed; inset:0; z-index:60;
  background:color-mix(in srgb,var(--ink) 46%,transparent);
  display:grid; place-items:center; padding:1rem;
  backdrop-filter:blur(3px);
}
.sheet-backdrop[hidden] { display:none; }
/* Staging: the backdrop fades, then the sheet arrives on the bounce curve a
   beat later, so the eye is already on the dimmed board when it lands. */
.sheet-backdrop { animation:ad-fade 180ms var(--ease) both; }
.sheet { animation:ad-pop 380ms var(--bounce) 90ms both; }
@keyframes ad-fade { from { opacity:0; } to { opacity:1; } }
@keyframes ad-pop { from { opacity:0; transform:translateY(22px) scale(.94); }
                    to { opacity:1; transform:none; } }
.sheet {
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-xl); padding:1.7rem 1.5rem;
  width:min(100%,430px); text-align:center;
  box-shadow:0 18px 60px rgba(0,0,0,.3);
  animation:sheet-in .22s ease both;
}
@keyframes sheet-in { from { transform:translateY(14px); opacity:0; } }
.sheet h2 { margin:0 0 .3rem; font-size:1.7rem; }
.sheet p { margin-inline:auto; }
.sheet .stars { font-size:2.1rem; letter-spacing:.12em; color:var(--amber); margin:.2rem 0 .5rem; }
.sheet .stars .off { opacity:.2; }
.sheet .tally {
  display:flex; justify-content:center; gap:1.5rem; margin:1rem 0;
  font-family:var(--font-display);
}
.sheet .tally div { display:flex; flex-direction:column; }
.sheet .tally span { font-size:.76rem; color:var(--ink-soft); text-transform:uppercase; letter-spacing:.07em; }
.sheet .tally b { font-size:1.35rem; font-variant-numeric:tabular-nums; }
.sheet .btn { width:100%; margin-top:.5rem; }
.sheet .quiet {
  display:inline-block; margin-top:.9rem; font-size:.92rem;
  color:var(--ink-soft); background:none; border:none; cursor:pointer;
  text-decoration:underline; min-height:44px;
}

/* ── Prose ────────────────────────────────────────────────────────────────── */
main { padding:1.4rem 0 3.5rem; }
.lede { font-size:1.1rem; color:var(--ink-soft); max-width:60ch; }
.crumbs { font-size:.86rem; color:var(--ink-soft); margin:.2rem 0 1rem; }
.crumbs a { color:var(--ink-soft); display:inline-flex; align-items:center; min-height:26px; }
.facts { display:flex; flex-wrap:wrap; gap:.5rem; margin:1.1rem 0; padding:0; list-style:none; }
.facts li {
  background:var(--variant); border-radius:var(--r-pill);
  padding:.35rem .85rem; font-size:.88rem; font-weight:600;
}
table.stats { border-collapse:collapse; margin:1.2rem 0; font-size:.94rem; }
table.stats th,table.stats td { text-align:left; padding:.5rem .9rem .5rem 0; border-bottom:1px solid var(--line); }
table.stats th { font-family:var(--font-display); font-weight:700; color:var(--ink-soft); font-size:.86rem; }
.prev-next { display:flex; justify-content:space-between; gap:1rem; margin-top:2.5rem; flex-wrap:wrap; }

/* ── Footer ───────────────────────────────────────────────────────────────── */
.site-foot {
  border-top:1px solid var(--line);
  padding:2rem 0 calc(2rem + var(--safe-b));
  margin-top:3rem;
  color:var(--ink-soft); font-size:.9rem;
}
/* ── Add to home screen (docs/21) ─────────────────────────────────────────
   Deliberately a CARD IN THE PAGE, not a floating bar. A dismissible banner
   pinned over the bottom of the screen is the single most complained-about
   pattern on the mobile web, and this one would be covering a game. It sits
   below the fold, after the thing it is advertising, and once dismissed it
   never returns. */
.install-card {
  display:flex; align-items:center; gap:.9rem; flex-wrap:wrap;
  margin:2rem 0; padding:1rem 1.1rem;
  background:var(--surface); border:2px solid var(--line);
  border-radius:var(--r-lg); box-shadow:0 6px 18px var(--shadow);
}
.install-card > img { width:48px; height:48px; border-radius:12px; flex:0 0 auto; }
.install-copy { flex:1 1 14rem; min-width:0; }
.install-copy strong { display:block; font-family:var(--font-display); font-size:1.05rem; }
.install-copy p { color:var(--ink-soft); font-size:.92rem; margin-top:.15rem; }
.install-copy b { font-family:var(--font-display); }
.install-actions { display:flex; align-items:center; gap:.5rem; flex:0 0 auto; margin-left:auto; }
/* Wrapped onto its own row the icon was centring against three lines of text
   and floating away from the heading it belongs to. */
@media (max-width:34rem) {
  .install-card { align-items:flex-start; }
  .install-actions { width:100%; margin-left:0; justify-content:flex-start; }
}
.btn-text {
  background:none; border:none; cursor:pointer; padding:.6rem .7rem;
  min-height:44px; color:var(--ink-soft); font-weight:600; font-size:.9rem;
  border-radius:var(--r-pill);
}
.btn-text:hover { background:var(--variant); color:var(--ink); }

.site-foot nav { display:flex; flex-wrap:wrap; gap:.4rem 1.2rem; margin-bottom:.9rem; }
.site-foot nav a { font-family:var(--font-display); font-weight:600;
  display:inline-flex; align-items:center; min-height:26px; }
.site-foot a { color:var(--ink-soft); }
.site-foot .credit { font-size:.82rem; opacity:.85; margin-top:.7rem; }
.site-foot .credit a { color:var(--ink); }

/* ── noscript ─────────────────────────────────────────────────────────────── */
.noscript {
  background:var(--variant); border:1px solid var(--line);
  border-radius:var(--r-lg); padding:1.2rem; margin:1.2rem 0;
}
