/* tsumiki — washi and wood.
   Paper ground, sumi ink, indigo (ai) and vermilion (shu) for the two numerals, counters that are
   blocks, and room to breathe. Flat colour throughout: no gradients, no soft shadows. The only
   relief in the whole app is the 3px block edge under a key, because a tsumiki block has one. */

:root {
  color-scheme: light dark;

  /* Brand — the three blocks of the logo, and the only colours with a hue.
     Each has an edge: the shaded underside that makes a block read as a block. */
  --indigo:      #2D4F7C;   /* ai */
  --indigo-edge: #243F63;
  --clay:        #D9482B;   /* shu */
  --clay-edge:   #AE3A22;
  --hinoki:      #D8B98A;   /* wood */
  --hinoki-edge: #AD946E;

  /* Surfaces */
  --ground:  #FBF7F2;   /* washi */
  --surface: #FFFDFA;

  /* Text */
  --ink:   #2A2724;     /* sumi */
  --muted: #81786C;     /* everything secondary: operators, labels, quiet actions */

  /* Structure */
  --border:        #E2D9CD;   /* outlines that sit quietly */
  --border-strong: #DDD3C4;   /* and the one that must not: the empty answer slot */
  --edge:          #DCD1C2;   /* the shaded underside of a key — a shadow, not an outline */
  --disabled:      #D8D1C7;

  /* Feedback */
  --good: #6F8A5E;   /* muted moss */
  --bad:  #B84C3F;   /* muted brick, kept well clear of the clay numeral */

  --gap: clamp(0.75rem, 2.5vw, 1.5rem);
  --tap: 68px;            /* a six-year-old's finger, not a cursor */
}

/* The same visual language, not the same pigments. Indigo at #2D4F7C on a near-black ground
   contrasts at about 2.2:1 and loses most of its presence, so the brand colours are lifted
   here rather than preserved literally — identity is what has to survive the theme, not hex. */
@media (prefers-color-scheme: dark) {
  :root {
    --indigo:      #7092BF;
    --indigo-edge: #5A7599;
    --clay:        #E46349;
    --clay-edge:   #B64F3A;
    /* hinoki and its edge are unchanged: the wood holds up on a dark ground as it is. */

    --ground:  #17161A;
    --surface: #201E22;

    --ink:   #F2EDE6;
    --muted: #A59C92;

    --border:        #3C3733;
    --border-strong: #4A443C;
    --edge:          #100F12;
    --disabled:      #3A3430;

    --good: #8FAD7C;
    --bad:  #D4786B;
  }
}

* { box-sizing: border-box; }
html, body { height: 100%; }

/* A class selector outranks the browser's own [hidden] rule, and .screen sets display: grid —
   so without this, hiding a screen does nothing at all and every screen stacks up on the page. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: 'M PLUS Rounded 1c', ui-rounded, -apple-system, 'Segoe UI', system-ui, sans-serif;
  background: var(--ground);
  color: var(--ink);
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

.screen {
  min-height: 100%;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  gap: calc(var(--gap) * 2);
  padding:
    calc(env(safe-area-inset-top, 0px) + var(--gap))
    calc(env(safe-area-inset-right, 0px) + var(--gap))
    calc(env(safe-area-inset-bottom, 0px) + var(--gap))
    calc(env(safe-area-inset-left, 0px) + var(--gap));
}

/* ---------------------------------------------------------------- the mark */

/* The logo is painted from the brand tokens rather than from literals, so it is no longer a
   copy of the palette that can drift from it — and it lifts with everything else in dark mode.
   logo.svg keeps its literal values: an external image cannot see the page's custom properties. */
.blocks .i-edge { fill: var(--indigo-edge); }
.blocks .i-face { fill: var(--indigo); }
.blocks .c-edge { fill: var(--clay-edge); }
.blocks .c-face { fill: var(--clay); }
.blocks .h-edge { fill: var(--hinoki-edge); }
.blocks .h-face { fill: var(--hinoki); }

.mark { display: grid; justify-items: center; gap: var(--gap); text-align: center; user-select: none; }
.mark svg { width: clamp(72px, 22vw, 132px); height: auto; display: block; }
.wordmark { font-size: clamp(2rem, 7vw, 3.25rem); font-weight: 700; letter-spacing: -0.01em; line-height: 1; margin: 0; }
/* ---------------------------------------------------------------- buttons */

.go {
  font: inherit; font-size: 1.15rem; font-weight: 800;
  min-height: var(--tap); padding: 0 2.5rem;
  color: var(--surface); background: var(--indigo);
  border: 0; border-radius: 14px; box-shadow: 0 3px 0 #00000026;
  cursor: pointer;
}
.go:active { transform: translateY(3px); box-shadow: none; }

.quiet {
  font: inherit; font-size: 0.95rem; font-weight: 500;
  min-height: 44px; padding: 0 0.75rem;
  color: var(--muted); background: none; border: 0; cursor: pointer;
}
.quiet:active { color: var(--ink); }

/* ---------------------------------------------------------------- working */

.work {
  /* Four fixed rows: bar, question, explanation, keypad. Each child is pinned to its own row
     by name — without that, hiding the explanation would let the keypad rise into its track and
     the whole screen would shuffle. */
  grid-template-rows: auto auto 1fr auto;
  align-content: stretch;
  justify-items: stretch;
  gap: var(--gap);
}
.top { grid-row: 1; display: flex; align-items: center; justify-content: space-between; gap: var(--gap); }

/* The mark and the wordmark, locked up horizontally, as the logo is drawn. */
.brand { display: flex; align-items: center; gap: 0.5rem; user-select: none; }
.brandmark { display: block; width: 34px; height: 34px; }
.brand .name { font-size: 1.35rem; font-weight: 700; letter-spacing: -0.01em; }

/* Right answers so far. It only ever goes up — a wrong answer costs another go, not a point. */
.count {
  font-size: 1.35rem; font-weight: 800; color: var(--ink);
  font-variant-numeric: tabular-nums; min-width: 1.5em; text-align: right;
}
/* The question holds its place. It is anchored below the bar rather than centred in the screen,
   so that opening an explanation underneath it cannot shift it: a child who has just read
   "4 + 1" should not have to find it again because they asked for help. */
.head {
  grid-row: 2; display: grid; justify-items: center;
  gap: calc(var(--gap) * 1.2); padding-top: clamp(0.5rem, 6vh, 3rem);
}
.bottom { grid-row: 4; display: grid; justify-items: center; gap: 0.5rem; }

.lead { margin: 0; color: var(--muted); font-size: 1rem; letter-spacing: 0.02em; }

.prompt {
  display: flex; align-items: center; gap: 0.18em;
  font-size: clamp(2.6rem, 13vw, 4.5rem); font-weight: 800; line-height: 1;
  transition: opacity 0.2s ease;
}
.prompt .n.one { color: var(--indigo); }   /* colour follows position in the written problem */
.prompt .n.two { color: var(--clay); }
.prompt .n.q   { color: var(--border); }
.prompt .n.ans { color: var(--ink); }
.prompt .op    { color: var(--muted); font-weight: 500; }
.prompt.right .n.ans { color: var(--indigo); }

/* The answer slot sits inside the equation. What the child types lands where the answer goes. */
.prompt .slot {
  display: inline-grid; place-items: center;
  min-width: 1.6em; padding: 0 0.1em; line-height: 1.15;
  color: var(--ink); background: var(--surface);
  border: 3px solid var(--border); border-radius: 14px;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.prompt .slot.empty {
  color: color-mix(in srgb, var(--muted) 35%, var(--ground));
  border-color: var(--border-strong); border-style: dashed;
}
.prompt .slot.right { color: var(--good); border-color: var(--good); border-style: solid; }
.prompt .slot.wrong { color: var(--bad);  border-color: var(--bad);  border-style: solid; }

/* ---------------------------------------------------------------- the picture */

.stage { grid-row: 3; display: grid; align-content: center; justify-items: center; gap: 0.6rem; width: 100%; }
.art { width: 100%; }
.caption { margin: 0; max-width: 32ch; text-align: center; font-size: 1.05rem; line-height: 1.45; color: var(--ink); }

.track { display: block; width: 100%; max-width: 560px; height: auto; margin: 0 auto; }
.track .cell rect { fill: none; stroke: var(--border); stroke-width: 2; }
.track .cell text { font-size: 24px; font-weight: 700; fill: var(--muted); }
.track .from rect { fill: var(--indigo); stroke: var(--indigo); }
.track .to   rect { fill: var(--clay);   stroke: var(--clay); }
.track .from text, .track .to text { fill: var(--surface); }
.track .skipped rect { stroke-dasharray: 5 5; }
.track .skipped text { opacity: 0.45; }
.track .hop { fill: none; stroke: var(--ink); stroke-width: 3; stroke-linecap: round; }
.track .hop.skip { stroke-dasharray: 8 7; }
.track marker path { fill: var(--ink); }

.swap {
  display: flex; align-items: center; justify-content: center; gap: 0.15em; flex-wrap: wrap;
  font-size: clamp(1.5rem, 7vw, 2.2rem); font-weight: 800; margin-bottom: 0.6rem;
}
.swap .one { color: var(--indigo); }
.swap .two { color: var(--clay); }
.swap .op, .swap .arrow { color: var(--muted); font-weight: 500; }
.swap .arrow { margin: 0 0.4em; }

/* ---------------------------------------------------------------- keypad */

.keypad {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
  width: min(100%, 330px);
}
.key {
  font: inherit; font-size: 1.7rem; font-weight: 700;
  min-height: var(--tap);
  color: var(--ink); background: var(--surface);
  border: 1px solid var(--border); border-radius: 14px; box-shadow: 0 3px 0 var(--edge);
  cursor: pointer;
}
.key:active { transform: translateY(3px); box-shadow: none; }
.key.ok { color: var(--surface); background: var(--indigo); border-color: var(--indigo); }
.key.ok:disabled { background: var(--disabled); border-color: var(--disabled); }

.actions { display: grid; justify-items: center; }
/* Offering help is an action, so it is lit like one. An earlier 0.8 opacity over the quiet grey
   left it looking switched off, which is the one thing a child stuck on a problem must not see. */
.show { color: var(--muted); }

/* ---------------------------------------------------------------- blocks */

.tally { display: grid; justify-items: center; gap: 0.3rem; }
.finalCount {
  margin: 0; font-size: clamp(3.5rem, 18vw, 6rem); font-weight: 800; line-height: 1;
  color: var(--indigo); font-variant-numeric: tabular-nums;
}
.closeText { margin: 0; color: var(--muted); font-size: 1.1rem; }

@media (prefers-reduced-motion: no-preference) {
  .mark { animation: settle 0.5s ease-out both; }
  .count.tick { animation: tick 0.3s ease-out; }
  @keyframes settle {
    from { opacity: 0; transform: translateY(0.4rem); }
    to   { opacity: 1; transform: none; }
  }
  /* Just enough to be noticed from across a table, not enough to be a reward in itself. */
  @keyframes tick {
    from { transform: translateY(-0.15em); color: var(--good); }
    to   { transform: none; }
  }
}

/* Short screens: a child who must scroll to answer will not answer. */
@media (max-height: 700px) {
  :root { --tap: 58px; }
  .prompt { font-size: clamp(2rem, 9vw, 3rem); }
  .track { max-width: 420px; }
}
