/*
 * GENERATED by scripts/export-help-figure-css.mjs in the amordle repository.
 * Do not edit by hand — re-run the exporter instead.
 *
 * The Help-page figures, with the game's own tokens resolved onto a wrapper so
 * they cannot leak into the rest of the page.
 *
 * Both schemes are carried. The figures follow the article rather than being
 * pinned: a board frozen in the game's dark palette is a black hole in a light
 * page, and one frozen light is unreadable at night. The three selectors below
 * mirror how the blog itself resolves a theme — an explicit choice, or the
 * system preference on a storage-free page.
 */
.amordle-figure {
  --accent: oklch(0.66 0.14 165);
  --accent-soft: oklch(0.89 0.045 165);
  --accent-text: oklch(0.4 0.12 165);
  --border: oklch(0.68 0.02 220);
  --control-disabled-opacity: 0.74;
  --correct: oklch(0.57 0.14 145);
  --danger: oklch(0.56 0.19 28);
  --danger-text: oklch(0.42 0.16 28);
  --duration-feedback: 90ms;
  --ease-standard: ease-out;
  --ink: oklch(0.19 0.018 225);
  --key-absent-background: oklch(0.18 0.01 220);
  --key-absent-border: oklch(0.34 0.018 220);
  --key-absent-ink: oklch(0.96 0.006 210);
  --key-unknown-background: oklch(0.84 0.04 165);
  --key-unknown-border: oklch(0.54 0.08 165);
  --key-unknown-ink: oklch(0.18 0.03 175);
  --muted: oklch(0.42 0.018 225);
  --present: oklch(0.68 0.14 85);
  --removed: oklch(0.5 0.06 25);
  --space-2: 0.25rem;
  --space-3: 0.5rem;
  --space-4: 0.75rem;
  --surface: oklch(0.955 0.008 220);
  --surface-inset: oklch(0.99 0.003 220);
  --terminal-rule: 1px solid var(--border);
  --terminal-selected: oklch(0.24 0.025 225);
  --terminal-selected-ink: oklch(0.98 0.004 220);
  --terminal-selected-muted: oklch(0.86 0.01 220);
  --text-1: 0.6875rem;
  --tui-font: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Monaco, Consolas, var(--font-geist-mono),
    monospace;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid color-mix(in oklch, var(--ink) 25%, transparent);
  padding: 1rem;
  overflow-x: auto;
}

:root[data-resolved-theme='dark'] .amordle-figure {
  --accent: oklch(0.76 0.13 165);
  --accent-soft: oklch(0.25 0.045 165);
  --accent-text: oklch(0.8 0.12 165);
  --border: oklch(0.38 0.018 220);
  --correct: oklch(0.7 0.15 145);
  --danger: oklch(0.7 0.18 28);
  --danger-text: oklch(0.8 0.13 28);
  --ink: oklch(0.91 0.008 205);
  --key-absent-background: oklch(0.11 0.01 220);
  --key-absent-ink: oklch(0.94 0.008 205);
  --key-unknown-background: oklch(0.24 0.05 165);
  --key-unknown-border: oklch(0.48 0.09 165);
  --key-unknown-ink: oklch(0.94 0.01 210);
  --muted: oklch(0.67 0.014 210);
  --present: oklch(0.78 0.14 85);
  --removed: oklch(0.65 0.07 25);
  --surface: oklch(0.16 0.014 225);
  --surface-inset: oklch(0.105 0.01 225);
  --terminal-selected: oklch(0.9 0.008 205);
  --terminal-selected-ink: oklch(0.13 0.015 225);
  --terminal-selected-muted: oklch(0.34 0.018 225);
}

@media (prefers-color-scheme: dark) {
  :root[data-storage-free-theme='system'] .amordle-figure,
  :root[data-theme-choice='system'] .amordle-figure {
    --accent: oklch(0.76 0.13 165);
    --accent-soft: oklch(0.25 0.045 165);
    --accent-text: oklch(0.8 0.12 165);
    --border: oklch(0.38 0.018 220);
    --correct: oklch(0.7 0.15 145);
    --danger: oklch(0.7 0.18 28);
    --danger-text: oklch(0.8 0.13 28);
    --ink: oklch(0.91 0.008 205);
    --key-absent-background: oklch(0.11 0.01 220);
    --key-absent-ink: oklch(0.94 0.008 205);
    --key-unknown-background: oklch(0.24 0.05 165);
    --key-unknown-border: oklch(0.48 0.09 165);
    --key-unknown-ink: oklch(0.94 0.01 210);
    --muted: oklch(0.67 0.014 210);
    --present: oklch(0.78 0.14 85);
    --removed: oklch(0.65 0.07 25);
    --surface: oklch(0.16 0.014 225);
    --surface-inset: oklch(0.105 0.01 225);
    --terminal-selected: oklch(0.9 0.008 205);
    --terminal-selected-ink: oklch(0.13 0.015 225);
    --terminal-selected-muted: oklch(0.34 0.018 225);
  }
}

/* Doubled class: the imported rules come after this block, and a figure that
   loses its own background shows the game's ink on the host page's colour. */
.amordle-figure.amordle-figure {
  color: var(--ink);
  background: var(--surface);
}

/*
 * Board surface — the shared visual language of a guess.
 *
 * Extracted from `solo-game.css` so that `/help` can draw real boards and real keyboards
 * without importing a stylesheet built for a screen where the board IS the page. Help
 * previously kept a hand-copied duplicate of the tile presentation for exactly that
 * reason; with six teaching figures now drawing boards, keyboards, evidence and draft
 * rows, a second copy would have been a second source of truth for the thing those
 * figures exist to teach.
 *
 * The split is deliberate and narrow:
 *
 *   HERE            paint and intrinsic structure — what a tile IS.
 *   solo-game.css   everything route-specific, every media query, and the tile SIZING.
 *
 * Sizing stays behind because it is the one thing a game screen and a figure legitimately
 * disagree about: the board sizes itself from the viewport, a figure sizes itself from the
 * column it sits in. Consumers set their own `--tile-size`-equivalent rules.
 *
 * Import this BEFORE `solo-game.css` on the play and combat routes, so their route
 * overrides still win at equal specificity.
 */

.board-row {
  display: flex;
  justify-content: center;
  gap: 0;
}

.tile {
  position: relative;
  display: grid;
  aspect-ratio: 1;
  place-items: center;
  border: var(--terminal-rule);
  border-inline-end: 0;
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--tui-font);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}

.tile:last-child {
  border-inline-end: var(--terminal-rule);
}

.tile-letter {
  line-height: 1;
}

.tile-evidence {
  position: absolute;
  right: 0.18rem;
  bottom: 0.08rem;
  font-size: 0.5em;
  line-height: 1;
}

.tile.is-correct {
  border-color: color-mix(in oklch, var(--correct) 72%, var(--border));
  background: color-mix(in oklch, var(--correct) 34%, transparent);
}

.tile.is-present {
  border-color: color-mix(in oklch, var(--present) 72%, var(--border));
  background: color-mix(in oklch, var(--present) 31%, transparent);
}

.tile.is-absent {
  border-color: var(--key-absent-border);
  background: var(--key-absent-background);
  color: var(--key-absent-ink);
}

/*
 * v8-A4. The answer, when a match ended by forfeit and nobody guessed it.
 *
 * Red is deliberately the one colour no tile state has ever used — the three evidence
 * states are green, amber and slate — so this cannot be misread as a solve. It is not
 * evidence and carries no ✓/~/× glyph.
 *
 * `--danger-text` for the letter rather than `--danger`: the text variant is the darker ink
 * counterpart added in v7.3 for exactly this reason, and the fill version is not legible as
 * type.
 */
.tile.is-answer {
  border-color: var(--danger);
  background: color-mix(in oklch, var(--danger) 22%, transparent);
  color: var(--danger-text);
}

.board-row.is-draft .tile {
  border-color: var(--accent);
  background: color-mix(in oklch, var(--accent-soft) 42%, transparent);
}

.board-row.is-draft .tile:empty:first-child::after {
  width: 0.58rem;
  height: 1.15rem;
  background: var(--accent);
  content: '';
  animation: terminal-cursor 1.05s steps(1, end) infinite;
}

.board-row.is-draft .tile.is-revealed {
  outline: 1px dashed var(--accent);
  outline-offset: -4px;
}

@keyframes terminal-cursor {
  0%,
  48% {
    opacity: 1;
  }

  49%,
  100% {
    opacity: 0.2;
  }
}

.keyboard {
  display: flex;
  min-width: 0;
  max-width: 100%;
  flex-direction: column;
  gap: 0.25rem;
  touch-action: manipulation;
}

.keyboard-row {
  display: flex;
  min-width: 0;
  max-width: 100%;
  justify-content: center;
  gap: 0.2rem;
}

/*
 * `:is(button, span).key` has the same specificity as the `button.key` it replaces —
 * (0,1,1) — because `:is()` takes the specificity of its most specific argument. That
 * matters: demoting to a bare `.key` would be (0,1,0) and would start losing to
 * `button:hover` for `background`.
 *
 * The span form exists so Help's figures can draw a keyboard without shipping 56 tab
 * stops and 56 more nodes into the control contrast sweep. A figure is not a control.
 */
:is(button, span).key {
  position: relative;
  min-width: 0;
  min-height: 2.75rem;
  flex: 1 1 0;
  border: 1px solid var(--key-unknown-border);
  border-radius: 0;
  background: var(--key-unknown-background);
  padding: 0.4rem 0.12rem;
  color: var(--key-unknown-ink);
  font-family: var(--tui-font);
  font-size: clamp(0.68rem, 2.7vw, 0.86rem);
  text-transform: uppercase;
}

/*
 * A `<span>` key has to be told the things a `<button>` key gets for free.
 *
 * The properties that actually centre a key's glyph are declared on `button, .button` in
 * globals.css, not on `.key` — so a span, which matches neither, is blockified as a flex
 * item and renders its letter top-left at weight 400 instead of centred and bold. That is
 * the entire reason the Help figures' keyboards looked wrong next to the real one; it was
 * never a styling drift.
 *
 * Deliberately scoped to `span.key` rather than folded into the shared rule above: these
 * values are identical to what a button already computes, so restating them for buttons
 * would be harmless but unprovable. Scoped this way, the change *cannot* move a game
 * screen. `cursor: pointer` is pointedly not included — a figure is not clickable and
 * must not claim to be.
 */
span.key {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /*
   * 650 and 0, not the 700 and 0.015em that `globals.css` declares — `tui-shell.css`
   * redeclares `button, .button` and loads second, so those are the values a real key
   * actually computes. Copying from the first rule found would have made every figure key
   * bolder and wider-tracked than the keyboard it is imitating.
   */
  font-weight: 650;
  letter-spacing: 0;
  transition:
    background-color var(--duration-feedback) var(--ease-standard),
    border-color var(--duration-feedback) var(--ease-standard),
    box-shadow var(--duration-feedback) var(--ease-standard),
    color var(--duration-feedback) var(--ease-standard);
}

/*
 * W2b. `:not(:disabled)` guards what was an unguarded hover: a dead key still lit up
 * with an accent border under the pointer, which reads as "press me" on precisely the
 * keys that cannot be pressed — a removed letter, or any key during the opponent's turn.
 */
button.key:hover:not(:disabled),
button.key:focus-visible:not(:disabled) {
  border-color: var(--accent);
  outline: 2px solid transparent;
  box-shadow: inset 0 0 0 1px var(--accent);
}

:is(button, span).key.is-wide {
  flex-basis: 3.5rem;
  font-size: clamp(0.54rem, 1.8vw, 0.66rem);
}

:is(button, span).key.is-correct {
  border-color: var(--correct);
  background: color-mix(in oklch, var(--correct) 34%, transparent);
}

:is(button, span).key.is-present {
  border-color: var(--present);
  background: color-mix(in oklch, var(--present) 31%, transparent);
}

:is(button, span).key.is-absent {
  border-color: var(--key-absent-border);
  background: var(--key-absent-background);
  color: var(--key-absent-ink);
}

:is(button, span).key.is-removed {
  background: color-mix(in oklch, var(--removed) 27%, transparent);
  text-decoration: line-through 2px;
}

.key-evidence {
  position: absolute;
  right: 0.2rem;
  bottom: 0.08rem;
  font-size: 0.58rem;
  font-weight: 700;
  line-height: 1;
}

@media (prefers-reduced-motion: reduce) {
  .board-row.is-draft .tile:empty:first-child::after {
    animation: none;
  }
}

@media (forced-colors: active) {
  .tile,
  :is(button, span).key {
    border-color: CanvasText;
    background: Canvas;
  }

  .tile.is-correct,
  .tile.is-present,
  .tile.is-absent,
  .tile.is-answer,
  :is(button, span).key.is-correct,
  :is(button, span).key.is-present,
  :is(button, span).key.is-absent,
  .board-row.is-draft .tile {
    border-color: Highlight;
  }

  .board-row.is-draft .tile:empty:first-child::after {
    background: Highlight;
  }
}


/*
 * Geometry and composition for the Help teaching figures.
 *
 * Route-scoped on purpose: `globals.css` and `tui-shell.css` ship from the root layout, so
 * every rule added to either counts against the home and game CSS budgets even though it
 * only ever paints on `/help`. Imported by the Help page alone, this costs those budgets
 * nothing. The paint itself — tiles, evidence colours, keys — comes from the shared
 * `board-surface.css`, so the figures cannot drift from the real board.
 */

/*
 * `.help-example` caps every Help figure at 34rem, which is right for a three-swatch
 * legend and wrong for a board. At 34rem the COMBAT figure sits below its own 44rem
 * container breakpoint, so it would have stacked at EVERY width and the two-keyboard
 * composition could never have appeared in the app at all — the artifact was reviewed at
 * 800px, and this cap is the difference.
 *
 * 52rem is this rule's own choice, not an inherited bound: `.route-frame.is-narrow` reads
 * `min(52rem, 100%)` in globals.css but is redeclared at `min(96rem, 100%)` in
 * tui-shell.css, which loads second and wins. Delete the line below and the figures jump
 * to roughly 1490px.
 */
.help-example.help-figure {
  width: min(52rem, 100%);
}

.help-figure {
  --tile-size: 2.4rem;
  container-type: inline-size;
}

.help-figure .tile {
  width: var(--tile-size);
  font-size: calc(var(--tile-size) * 0.42);
}

/*
 * The single-keyboard figures get the REAL keyboard: the same width rule the play routes
 * use, the same key height, the same font ramp. At 44rem the Remove figure is
 * pixel-for-pixel the keyboard a player actually types on. Only COMBAT compresses, below,
 * because two keyboards have to flank a board.
 */
.help-figure .keyboard {
  width: min(44rem, 100%);
  margin-inline: auto;
}

.help-combat .keyboard {
  width: 100%;
}

.help-combat :is(button, span).key {
  min-height: 2.1rem;
  padding: 0.3rem 0.1rem;
  font-size: 0.7rem;
}

/*
 * SUBMIT and DELETE, proportionally rather than at the real `3.5rem`.
 *
 * On the real 44rem keyboard that basis is 7.95% of the row. Reused as a fixed 56px inside
 * a 247px figure column it would eat half the row and crush the seven letters beside it to
 * about 12px. As a percentage it reproduces the real ratio at ANY width: the row-three
 * letter lands at 0.92x the row-one key, against the game's own 0.93x.
 *
 * Declared after the compressed `.key` rule above on purpose — both are (0,2,1), so
 * without this the figure's 0.7rem would win and the wide keys would render LARGER than
 * real ones instead of smaller.
 */
.help-figure :is(button, span).key.is-wide {
  flex-basis: 8%;
  font-size: clamp(0.45rem, 1.4cqi, 0.66rem);
}

/*
 * A pressed key. The game itself has no press state at all — `button:active` sets a 1px
 * nudge in globals.css and tui-shell.css cancels it with `translate: 0` — so the only
 * thing a real key ever shows is the hover treatment, which on touch IS the tap state,
 * because hover latches after a tap. That treatment is the first two declarations here,
 * copied from `button.key:hover:not(:disabled)` in board-surface.css.
 *
 * The amplification is the RING, doubled to 2px, not a fill — and that is a correction.
 * The first attempt tinted the key with `--accent-soft`, which the new contrast sweep
 * immediately caught at 1.31:1: an absent key carries near-white ink on a near-black
 * ground, and dropping a light accent tint underneath it left white on pale green. A fill
 * would have to be mixed differently for all five key states in both schemes across seven
 * accents to stay safe. The ring cannot fail, because it never touches the text/background
 * pair at all — and on a 22px key, 2px is proportionally far stronger than the 1px a real
 * 68px key shows, so it reads as at least as emphatic as the fill did.
 *
 * It eases over the same `--duration-feedback` a real button uses, so it reads as a press
 * rather than a flicker. Reduced motion clamps the transition; the figure stays legible.
 */
.help-figure :is(button, span).key.is-pressed {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 2px var(--accent);
}

.help-stage {
  border: var(--terminal-rule);
  background: var(--surface-inset);
  padding: var(--space-4);
}

.help-board {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}

.help-board-entry {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.help-row-meta {
  width: 5.2rem;
  flex: 0 0 5.2rem;
  color: var(--muted);
  font-size: 0.58rem;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.help-row-meta.is-seed {
  color: var(--accent-text);
}

.help-note {
  min-height: 2.4rem;
  margin-block: var(--space-3) 0;
  color: var(--muted);
  font-size: var(--text-1);
  text-align: center;
}

/*
 * COMBAT. The board box reserves its FINAL nine-slot height from the first frame while the
 * board itself grows inside it from six. Both of the owner's requirements fall out of that
 * one decision: the gameplay area stays above the midline between the two keyboards at
 * every stage of the match, and the keyboards do not slide down the page as the board
 * extends past row six — which is exactly when a reader is trying to look at them.
 */
.help-combat {
  display: grid;
  align-items: center;
  gap: var(--space-4);
  grid-template-columns: 1fr auto 1fr;
}

.help-combat-board {
  min-height: 24rem;
  grid-column: 2;
}

.help-combat-side {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: var(--space-2);
}

.help-combat-side .keyboard {
  width: 100%;
}

/*
 * Rook is violet so that one keyboard is unmistakably not yours. If the viewer's own
 * accent happens to BE violet, that distinction collapses and we are back to the defect
 * this fixes — so in that one case Rook is retinted amber instead.
 *
 * Only the properties a keyboard and a draft row actually read are restated: the three
 * `--key-unknown-*`, plus `--accent` and `--accent-soft` for the draft outline, caret and
 * pressed fill, plus `--accent-text` for the turn marker. Values are lifted verbatim from
 * the amber blocks in tui-shell.css; nothing new is invented.
 *
 * A custom accent that happens to look violet cannot be detected and is accepted.
 */
:root[data-accent='violet'] .help-combat [data-accent='violet'] {
  --accent: oklch(0.73 0.14 80);
  --accent-text: oklch(0.4 0.105 80);
  --accent-soft: oklch(0.91 0.045 80);
  --key-unknown-background: oklch(0.84 0.035 75);
  --key-unknown-border: oklch(0.55 0.08 75);
  --key-unknown-ink: oklch(0.2 0.025 75);
}

@media (prefers-color-scheme: dark) {
  :root[data-accent='violet'] .help-combat [data-accent='violet'] {
    --accent: oklch(0.8 0.13 80);
    --accent-text: oklch(0.84 0.11 80);
    --accent-soft: oklch(0.27 0.045 80);
    --key-unknown-background: oklch(0.25 0.04 70);
    --key-unknown-border: oklch(0.48 0.08 70);
    --key-unknown-ink: oklch(0.95 0.01 75);
  }
}

.help-combat-name {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  border-inline-start: 2px solid transparent;
  padding-inline-start: var(--space-3);
  color: var(--muted);
  font-size: var(--text-1);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

/*
 * The turn marker is the app's own `❯` idiom plus an accent rail — never an opacity
 * change, which would drag the inactive keyboard's contrast down with it and make the
 * figure fail the sweep for a purely decorative reason.
 */
.help-combat-name::before {
  color: var(--border);
  content: '❯';
}

.help-combat-side.is-active .help-combat-name {
  border-inline-start-color: var(--accent);
  color: var(--ink);
}

.help-combat-side.is-active .help-combat-name::before {
  color: var(--accent-text);
}

/*
 * Below roughly 44rem the three-column composition cannot hold two keyboards and a
 * five-wide board, so it stacks. Still two players, one board, shared evidence — only the
 * literal left-and-right is lost, which is the right thing to give up.
 */
@container (max-width: 44rem) {
  .help-combat {
    align-items: stretch;
    grid-template-columns: 1fr;
  }

  .help-combat-board {
    min-height: 0;
    grid-column: 1;
    grid-row: 2;
  }
}

.help-tool-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  margin-block-end: var(--space-4);
}

.help-tool-button {
  border: var(--terminal-rule);
  padding: var(--space-2) var(--space-4);
  color: var(--ink);
  font-size: var(--text-1);
  text-transform: uppercase;
}

.help-tool-button::before {
  content: '[';
}

.help-tool-button::after {
  content: ']';
}

.help-tool-button.is-firing {
  border-color: var(--accent);
  background: color-mix(in oklch, var(--accent-soft) 50%, transparent);
}

.help-result {
  margin-block-start: var(--space-3);
  border: 1px solid var(--danger);
  padding: var(--space-3);
  color: var(--ink);
  font-size: var(--text-1);
  text-align: center;
}

.help-calendar {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.help-weekdays,
.help-calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 2px;
}

.help-weekdays {
  color: var(--muted);
  font-size: 0.55rem;
  text-align: center;
}

.help-day {
  display: grid;
  min-height: 2.6rem;
  align-content: center;
  justify-items: center;
  gap: 1px;
  border: var(--terminal-rule);
  color: var(--ink);
  font-size: 0.66rem;
}

.help-day small {
  color: var(--muted);
  font-size: 0.48rem;
}

.help-day.is-future {
  opacity: var(--control-disabled-opacity);
}

.help-day.is-target {
  border-color: var(--accent);
}

.help-day.is-unlocked {
  border-color: var(--correct);
}

.help-day.is-selected {
  background: var(--terminal-selected);
  color: var(--terminal-selected-ink);
}

/* W3's rule, applied ahead of the defect rather than after it: secondary text on a
   selected surface takes the token that exists for exactly that. */
.help-day.is-selected small {
  color: var(--terminal-selected-muted);
}

@media (forced-colors: active) {
  .help-stage,
  .help-tool-button,
  .help-day,
  .help-result {
    border-color: CanvasText;
    background: Canvas;
  }

  .help-day.is-selected {
    background: Highlight;
    color: HighlightText;
  }

  .help-day.is-selected small {
    color: HighlightText;
  }
}


/*
 * Overflow safety, added by the exporter rather than the game.
 *
 * The game's figures centre their contents, which is right when they fit. Inside
 * a scroll container they do not fit at every width, and centred overflow puts
 * the left half of a board where nothing can scroll to it — the figure reads as
 * shoved to the right. `safe` is the keyword for exactly this: centre when there
 * is room, fall back to start when there is not.
 */
.amordle-figure .help-board,
.amordle-figure .help-combat,
.amordle-figure .help-calendar,
.amordle-figure .help-tool-bar {
  align-items: safe center;
  justify-content: safe center;
}

.amordle-figure .help-board-entry {
  justify-content: safe center;
}
