/* LEXIS — one stylesheet. Bright, warm, over-legible typesetting. Depth lives in the grammar's
 * behaviour, never in mood lighting. Palette measured for WCAG AA (see docs/METRICS). */

:root {
  --paper: #F4EFE6;   /* ground */
  --panel: #E9E2D4;   /* slots / state field */
  --edge:  #D8CFBD;   /* hairlines */
  --ink:   #2B2820;   /* glyphs + body — 12.85:1 on paper (AAA) */
  --muted: #6B6455;   /* secondary — 5.12:1 on paper (AA) */
  --accent:#0A7B84;   /* liveness ONLY, >=24px non-text, redundantly coded; 4.39:1 on paper (>3:1 graphics floor) */
  --mono: ui-monospace, "Cascadia Code", "SF Mono", "DejaVu Sans Mono", Menlo, Consolas, monospace;
  --serif: ui-serif, Georgia, "Times New Roman", serif;
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 20px; --s5: 32px; --s6: 52px;
  --cell: 3.1rem;
  color-scheme: light dark;
}
@media (prefers-color-scheme: dark) {
  :root {
    --paper: #171613; --panel: #211F1A; --edge: #34302A;
    --ink: #ECE6D8; --muted: #A79E8B; --accent: #1FB6C1;
  }
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
/* the hidden attribute must beat author display rules — without this, .grid{display:grid} and
 * .filmstrip{display:flex} defeat hidden in EVERY browser (r5 compat audit, high) */
[hidden] { display: none !important; }
/* no-JS honesty: the interactive controls are hidden until lexis.js removes this class,
 * so a JS-less reader meets prose and the noscript explanation, not dead buttons */
html.no-js .toggle, html.no-js .controls, html.no-js .palette, html.no-js .verify-btn,
html.no-js .state, html.no-js .linewrap { display: none; }   /* a JS-less reader meets the noscript prose, not a dead panel */
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

.skip-link {
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: var(--paper); padding: var(--s2) var(--s3);
  border-radius: 0 0 6px 0; z-index: 20; text-decoration: none;
}
.skip-link:focus { left: 0; }

/* ---------- masthead ---------- */
.mast {
  display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap;
  gap: var(--s3);
  max-width: 46rem; margin: 0 auto; padding: var(--s4) var(--s4) var(--s2);
}
.wordmark {
  font-family: var(--mono); font-weight: 600; font-size: 1.35rem; letter-spacing: 0.32em;
  color: var(--ink); text-decoration: none; padding-left: 0.32em;
}
.mast__nav { display: flex; gap: var(--s3); align-items: baseline; font-family: var(--mono); font-size: 0.82rem; }
.mast__nav a { color: var(--muted); text-decoration: none; border-bottom: 1px solid transparent; padding-bottom: 2px; }
.mast__nav a:hover { color: var(--ink); border-bottom-color: var(--ink); }
.mast__nav a:focus-visible { color: var(--ink); border-bottom-color: var(--ink); }
.toggle {
  font: inherit; font-family: var(--mono); font-size: 0.82rem; color: var(--muted);
  background: none; border: 1px solid var(--edge); border-radius: 6px; cursor: pointer;
  min-height: 44px; padding: 2px var(--s3); display: inline-flex; align-items: center;
}
.toggle:hover { color: var(--ink); border-color: var(--ink); }
.toggle:focus-visible { color: var(--ink); border-color: var(--ink); }

/* ---------- the app: state / line / field ---------- */
.stage { max-width: 46rem; margin: 0 auto; padding: var(--s3) var(--s4) var(--s6); }

.state {
  background: var(--panel);
  border: 1px solid var(--edge);
  border-radius: 12px;
  padding: var(--s4);
  display: flex; justify-content: center;
  overflow-x: auto;   /* sub-280px floor: scroll inside the panel, never break the page */
}
.grid {
  position: relative;   /* carries the transient fold-axis overlay */
  display: grid;
  grid-template-columns: repeat(5, var(--cell));
  grid-template-rows: repeat(5, var(--cell));
  gap: 2px;
}
/* a vacuous fold performs its mirror axis for a beat — "already a palindrome", never a dead
 * button (r4 playtest). Ink-only, one shot, vanishes; nothing rests. */
.grid--axis::after {
  content: ""; position: absolute; left: 50%; top: 2%; bottom: 2%; width: 2px;
  margin-left: -1px; background: var(--ink); opacity: 0; pointer-events: none;
  animation: axisblink 360ms ease-out;
}
@keyframes axisblink { 0% { opacity: 0.3; } 100% { opacity: 0; } }
.cell {
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 1.6rem; line-height: 1;
  color: var(--ink);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
}
.cell[data-k=""] { color: var(--edge); }
.cell[data-k=""]::before { content: "·"; opacity: 0.6; }   /* faint grid dot so structure is legible */
/* the origin — where the language begins placing; structured ground at placeholder weight,
 * neutral edge ink, encoding no history and no outcome (r2 handpicked, honest-ground package) */
.cell--origin[data-k=""]::before { content: "·"; opacity: 0.95; font-size: 1.25em; }
.cell[data-k]:not([data-k=""]) { background: rgba(43,40,32,0.05); border-color: var(--edge); }
/* cells carry real glyph drawings; distance-falloff is SCALE on the drawing, never colour —
 * full ink at every tier (figure never sinks beneath ground), and two tiers forever: a third
 * step would read as a value gradient (r2 handpicked, Albers's restraint clause). */
.cell svg { width: 1.9rem; height: 1.9rem; display: block; }
.cell[data-v="2"] svg { transform: scale(0.8); }
.cell[data-v="1"] svg { transform: scale(0.6); }
@media (prefers-color-scheme: dark) {
  .cell[data-k]:not([data-k=""]) { background: rgba(236,230,216,0.06); }
}
/* reduced-motion chain: a static filmstrip of labelled stills */
.filmstrip { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; justify-content: center; }
.film__frame { display: flex; flex-direction: column; align-items: center; gap: var(--s1); }
.film__label { font-family: var(--mono); font-size: 0.7rem; color: var(--muted); }
.film__arrow { font-family: var(--mono); color: var(--muted); font-size: 1.2rem; }
.mini { display: grid; grid-template-columns: repeat(5, 1.15rem); grid-template-rows: repeat(5, 1.15rem); gap: 1px; }
.cell--mini { font-size: 0.7rem; border-radius: 3px; }
.cell--mini svg { width: 0.85rem; height: 0.85rem; display: block; }
.cell--settling { animation: settle 220ms ease-out; }
@keyframes settle {
  0% { transform: scale(0.7); }
  60% { transform: scale(1.08); outline: 2px solid var(--accent); outline-offset: 1px; }
  100% { transform: scale(1); outline-color: transparent; }
}
/* the ground's one quiet breath when nothing changed — the visual sibling of the still tone;
 * ink-only, one shot, well under 1 Hz; skipped by JS under reduced motion */
.grid--still { animation: stillbreath 340ms ease-in-out; }
@keyframes stillbreath {
  0% { opacity: 1; }
  50% { opacity: 0.82; }
  100% { opacity: 1; }
}
/* the inspectable past (prefix scrub): while a line tile is hovered/focused, the state panel
 * carries a dashed border and the glyphs after the cut dim — no colour, no sound, no narration */
.state--preview { border-style: dashed; }
.tile--dim { opacity: 0.45; }

/* the line — the open composition strip */
.linewrap { margin-top: var(--s4); }
.line {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2);
  min-height: 3.2rem; padding: var(--s2) var(--s3);
  border-bottom: 2px solid var(--ink);
}
.line__empty { color: var(--muted); font-family: var(--mono); font-size: 0.85rem; }
.tile {
  width: 2.4rem; height: 2.4rem; min-width: 44px; min-height: 44px; padding: 4px;
  background: var(--paper); border: 1px solid var(--edge); border-radius: 8px;
  color: var(--ink); cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
}
.tile svg { width: 100%; height: 100%; }
.tile--op { border-style: dashed; }
.tile--split { margin: 0 var(--s3); position: relative; }   /* chain: a visible gap so the sentence-split is seen */
.tile--split::before, .tile--split::after {
  content: ""; position: absolute; top: 50%; width: var(--s2); height: 1px; background: var(--edge);
}
.tile--split::before { right: 100%; margin-right: 2px; }
.tile--split::after { left: 100%; margin-left: 2px; }
.tile:hover { border-color: var(--ink); }

.controls { display: flex; gap: var(--s3); margin-top: var(--s2); align-items: center; }
.linkbtn {
  font-family: var(--mono); font-size: 0.8rem; color: var(--muted);
  background: none; border: none; cursor: pointer; border-bottom: 1px solid transparent;
  /* quiet, but a full-size target: these are the buttons an older hand most needs (r4) */
  min-height: 44px; padding: 10px 2px; display: inline-flex; align-items: center;
}
.linkbtn:hover { color: var(--ink); border-bottom-color: var(--ink); }
.linkbtn:focus-visible { color: var(--ink); border-bottom-color: var(--ink); }
.linkbtn.is-kept { color: var(--ink); border-bottom-color: var(--ink); }
.caption { color: var(--muted); font-size: 0.9rem; margin: var(--s2) 0 0; font-style: italic; min-height: 1.5em; }
/* the answer line breathes with the ground when nothing changed, so the honest words are SEEN */
.caption--pulse { animation: captionpulse 340ms ease-in-out; }
@keyframes captionpulse { 0% { color: var(--muted); } 45% { color: var(--ink); } 100% { color: var(--muted); } }

/* the field — the glyph palette */
.palette { margin-top: var(--s5); display: flex; flex-direction: column; gap: var(--s4); }
.palette__row { display: flex; gap: var(--s3); flex-wrap: wrap; }
/* the operators sit in their own quiet tray, so "these are a different kind of move" reads
   without a word of instruction — the playtest's biggest lever against the mark-only plateau. */
.palette__row--ops {
  padding: var(--s2) var(--s3);
  background: var(--panel);
  border: 1px dashed var(--edge);
  border-radius: 10px;
  width: -webkit-fit-content;
  width: -moz-fit-content;
  width: fit-content;
  max-width: 100%;
}
.glyph {
  width: 3.4rem; height: 3.4rem; min-width: 44px; min-height: 44px; padding: 8px;
  background: var(--panel); border: 1px solid var(--edge); border-radius: 10px;
  color: var(--ink); cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
}
.glyph svg { width: 100%; height: 100%; display: block; }
.glyph--op { border-style: dashed; background: var(--paper); }
.glyph:hover { border-color: var(--ink); }
.glyph:active { transform: translateY(1px); }

/* focus — outline (survives forced-colors), plus a non-colour scale cue.
   Base :focus keeps a visible ring so browsers WITHOUT :focus-visible (older Safari/iOS/Chrome)
   still show keyboard focus; :focus:not(:focus-visible) removes it only where supported. */
:focus { outline: 2px solid var(--ink); outline-offset: 3px; }
:focus:not(:focus-visible) { outline: none; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.glyph:focus-visible, .tile:focus-visible { outline-offset: 3px; transform: scale(1.06); }

/* live regions (visually hidden but present) */
.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;
}

/* ---------- reading pages (about / colophon / concepts) ---------- */
.page { max-width: 40rem; margin: 0 auto; padding: var(--s4) var(--s4) var(--s6); }
.page h1 { font-family: var(--serif); font-weight: 600; font-size: 1.9rem; line-height: 1.2; margin: var(--s4) 0 var(--s3); }
.page h2 { font-family: var(--mono); font-weight: 600; font-size: 1.02rem; letter-spacing: 0.02em; margin: var(--s5) 0 var(--s2); }
.page p, .page li { font-size: 1.02rem; }
.page a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; text-decoration-color: var(--muted); }
.page a:hover { text-decoration-color: var(--ink); }
.page a:focus-visible { text-decoration-color: var(--ink); }
.eyebrow { font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); margin: 0; }
.ref { color: var(--muted); font-family: var(--mono); font-size: 0.85rem; }
.backhome { font-family: var(--mono); font-size: 0.85rem; }
.pagenav { max-width: 40rem; margin: 0 auto; padding: var(--s4) var(--s4) 0; display: flex; gap: var(--s3); flex-wrap: wrap; font-family: var(--mono); font-size: 0.82rem; }
.pagenav a { color: var(--muted); text-decoration: none; }
.pagenav a[aria-current="page"] { color: var(--ink); }
.pagenav a:hover { color: var(--ink); }
.pagenav a:focus-visible { color: var(--ink); }
.pagenav .wm { color: var(--ink); font-weight: 600; letter-spacing: 0.2em; }
.legend { display: grid; grid-template-columns: auto 1fr; gap: var(--s2) var(--s3); align-items: center; margin: var(--s3) 0; }
.legend .g { width: 2.4rem; height: 2.4rem; color: var(--ink); }
.legend .g svg { width: 100%; height: 100%; }
.noscript { max-width: 40rem; margin: var(--s4) auto; padding: 0 var(--s4); color: var(--muted); }
.shelf { list-style: none; padding: 0; margin: var(--s3) 0; display: flex; flex-direction: column; gap: var(--s2); }
.shelf a { font-family: var(--mono); font-size: 0.92rem; }
.verify-out { font-family: var(--mono); font-size: 0.85rem; background: var(--panel); border: 1px solid var(--edge); border-radius: 8px; padding: var(--s3); overflow-x: auto; }
.verify-btn { font: inherit; font-family: var(--mono); font-size: 0.9rem; color: var(--ink); background: var(--panel); border: 1px solid var(--edge); border-radius: 8px; padding: var(--s2) var(--s3); cursor: pointer; }
.verify-btn:hover { border-color: var(--ink); }
.verify-btn:focus-visible { border-color: var(--ink); }

/* ---------- responsive: phone-first ---------- */
@media (max-width: 30rem) {
  :root { --cell: 2.7rem; }
  .mast { padding: var(--s3) var(--s3) var(--s2); }
  .stage { padding: var(--s2) var(--s3) var(--s5); }
  .state { padding: var(--s3); }
  .glyph { width: 3rem; height: 3rem; }
}

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .cell--settling { animation: none; }
  .grid--still { animation: none; }
  .grid--axis::after { animation: none; }
  .caption--pulse { animation: none; }
  * { scroll-behavior: auto; }
}

/* ---------- forced colors ---------- */
@media (forced-colors: active) {
  .cell[data-k]:not([data-k=""]) { border-color: CanvasText; }
  .glyph, .tile { border-color: CanvasText; }
  .grid--axis::after { background: CanvasText; }   /* the fold-axis answer survives forced colors */
  :focus-visible { outline-color: Highlight; }
}
