/* Rosetta M: the stone and its controls. Dark theme matching the SVG faces
   the renderer emits (#1e1e2e / #cdd6f4). No build step; plain CSS. */
:root {
  color-scheme: dark;
  --bg: #1e1e2e;
  --panel: #181825;
  --face: #1e1e2e;
  --edge: #45475a;
  --fg: #cdd6f4;
  --dim: #a6adc8;
  --accent: #89b4fa;
  --warm: #fab387;
  /* The stone's geometry is in abstract units; --unit is the pixels per unit.
     Face widths, the shared height, the inradius and each face's angle and
     in-plane offset are computed by the script from the widths and set as
     variables on the stone (see makeGeometry in rosetta.js). */
  --unit: min(1px, 92vw / 720);
  --stone-w: 720;
  --face-hu: 440;
  --face-h: calc(var(--face-hu) * var(--unit));
}
* { box-sizing: border-box; }
body {
  margin: 0; background: var(--bg); color: var(--fg); overflow-x: clip;
  font: 16px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
}
header, main, footer { max-width: 62rem; margin: 0 auto; padding: 0 16px; }
header { padding-top: 24px; }
h1 { margin: 0 0 8px; font-size: 2rem; letter-spacing: 0.01em; }
.masthead { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 8px 16px; }
.masthead-controls { display: inline-flex; align-items: center; gap: 12px; }
.masthead-controls kbd, .lede kbd {
  font: 0.85em ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--fg);
  background: var(--bg); border: 1px solid var(--edge); border-bottom-width: 2px; border-radius: 4px; padding: 0 5px;
}
.stone-pick { color: var(--dim); font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.06em; display: inline-flex; align-items: center; gap: 8px; }
.stone-pick select {
  font: inherit; font-size: 1rem; text-transform: none; letter-spacing: 0; color: var(--fg);
  background: var(--panel); border: 1px solid var(--edge); border-radius: 6px; padding: 4px 8px;
}
.lede { margin: 0 0 8px; font-size: 1.05rem; }
.eq { font-family: "Latin Modern Math", "Cambria Math", "STIX Two Math", serif; }
.note { margin: 0 0 16px; color: var(--dim); font-size: 0.95rem; }
a { color: var(--accent); }
code { font-size: 0.95em; }

/* The stage holds the stone in perspective; the stone is a triangular prism
   of three faces standing on its axis. */
.stage {
  position: relative;
  height: calc(var(--face-h) * var(--view-scale, 1) + 150px);
  transition: height 0.3s;
  perspective: 1800px; perspective-origin: 50% 45%;
  display: grid; place-items: center;
  touch-action: none; user-select: none; cursor: grab;
}
.stage.dragging { cursor: grabbing; }
.stone {
  /* recomputed here so a read-mode --unit set on the stone carries through */
  --face-h: calc(var(--face-hu) * var(--unit));
  position: relative; width: calc(var(--stone-w) * var(--unit)); height: var(--face-h);
  transform-style: preserve-3d;
  /* The yaw is applied on the faces, not here: the stone's own box is the
     z = 0 plane of the 3D context, and Blink's hit testing loses the faces
     whenever that plane is between the viewer and a face or nearly edge-on,
     which is exactly where a turn to the M face lands. Kept flat toward the
     viewer (pitch only), and transparent to the pointer, the box never
     shadows a face. */
  transform: translate(var(--pan-x, 0px), var(--pan-y, 0px)) scale(var(--view-scale, 1)) rotateX(var(--pitch, -4deg));
  pointer-events: none;
}
/* modal keys: the cursor says which mode is armed */
body[data-mode="grab"] { cursor: move; }
body[data-mode="rotate"] { cursor: ew-resize; }
body[data-mode="scale"] { cursor: ns-resize; }
body[data-mode="travel"] { cursor: col-resize; }
body[data-mode="focus"] { cursor: crosshair; }
body[data-mode] .stage { cursor: inherit; }
body.reading .stage { height: auto; padding: 56px 0 12px; cursor: default; }
body.reading .minimap { width: 44px; height: 44px; }
body.reading .face:not(.reading-face) { visibility: hidden; }

/* the wide view: every face flat, side by side, the stone's 3D gone */
body.wide .stage {
  /* the row of faces wants the whole window, not the page column */
  height: auto; padding: 56px 8px 12px; cursor: default;
  width: 100vw; margin-left: calc(50% - 50vw); overflow-x: auto;
}
body.wide .minimap { display: none; }
body.wide .stone { transform: none; width: max-content; display: flex; gap: 12px; }
body.wide .face { position: static; transform: none; flex: none; }
body.wide .face h2 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 6px 10px; font-size: 0.8rem; }
body.wide .face h2 small { font-size: 0.9rem; }

/* the walk: the current line's tokens lit on the text faces, its ids lit on the others */
body.walking .text-face .rs-token:not(.walk):not(.focus) { opacity: 0.35; }
body.walking .scene line:not(.walk):not(.focus), body.walking .scene text:not(.walk):not(.focus) { opacity: 0.3; }
.rs-token.walk { fill: var(--accent); }
body.has-focus .text-face .rs-token.walk:not(.focus) { opacity: 0.8; }
.scene line.walk { stroke: var(--accent) !important; stroke-width: 3.5; }
.scene text.walk { fill: var(--accent); }
.walk-row output { color: var(--dim); font-variant-numeric: tabular-nums; min-width: 4ch; text-align: center; }
.focus-caption .walk-m { color: var(--dim); }

/* orientation cues: a top-down minimap of the prism with the viewer below it */
.minimap { position: absolute; top: 8px; right: 8px; width: 64px; height: 64px; z-index: 2; pointer-events: none; }
.minimap polygon { fill: var(--panel); stroke: none; }
.minimap .eye { fill: none; stroke: var(--dim); stroke-width: 2; }
.minimap line { stroke: var(--edge); stroke-width: 5; stroke-linecap: round; transition: stroke 0.15s; }
.minimap line.front { stroke: var(--warm); }
.minimap .eye { fill: none; stroke: var(--dim); stroke-width: 2; }
.back { position: absolute; top: 8px; left: 8px; z-index: 2; }
.scale-group { display: inline-flex; align-items: center; gap: 4px; }
.scale-group output { min-width: 3.5ch; text-align: center; font-variant-numeric: tabular-nums; color: var(--dim); }
.face {
  /* each face: its own width --w (units), angle --a (deg), in-plane offset --o
     (units); all faces sit at the inradius --r (units) from the axis */
  position: absolute; top: 0; bottom: 0;
  width: calc(var(--w) * var(--unit));
  left: calc((var(--stone-w) - var(--w)) / 2 * var(--unit));
  background: var(--face); border: 1px solid var(--edge); border-radius: 6px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
  backface-visibility: hidden;
  display: flex; flex-direction: column; overflow: hidden;
}
.face { transform: rotateY(calc(var(--yaw, 0deg) + var(--a) * 1deg)) translateZ(calc(var(--r) * var(--unit))) translateX(calc(var(--o) * var(--unit))); pointer-events: auto; }
.face h2 {
  margin: 0; padding: 8px 14px; font-size: 0.95rem; font-weight: 600;
  color: var(--dim); border-bottom: 1px solid var(--edge); letter-spacing: 0.04em;
  text-transform: uppercase;
}
.face h2 small { text-transform: none; font-weight: 400; letter-spacing: 0; margin-left: 8px; color: var(--fg); }
.face h2 small { font-family: "Latin Modern Math", "Cambria Math", "STIX Two Math", serif; font-size: 1.05rem; }
.text-face { flex: 1; min-height: 0; display: grid; place-items: center; padding: 8px; }
.text-face svg { width: 100%; height: 100%; }
.text-face svg > rect { fill: transparent; }
.scene { flex: 1; min-height: 0; width: 100%; display: block; }
.scene text {
  /* size is set by the projector in viewBox units */
  font-family: "Latin Modern Math", "Cambria Math", "STIX Two Math", serif;
  fill: var(--fg); text-anchor: middle; dominant-baseline: middle;
  paint-order: stroke; stroke: var(--face); stroke-width: 4px;
}
.scene line { stroke-linecap: round; }

/* The face card: what the stone is for, and what the face toward the viewer shows */
.face-card { margin: 4px auto 12px; padding: 10px 16px; border-left: 3px solid var(--warm); }
.stone-purpose { margin: 0 0 6px; color: var(--dim); font-size: 0.9rem; }
.face-card h2 { margin: 0; font-size: 1.05rem; }
.face-card p { margin: 4px 0 0; }
.lines { margin: 8px 0 0; padding-left: 1.4rem; color: var(--dim); font-size: 0.92rem; }
.lines[hidden] { display: none; }
.lines li { margin: 2px 0; }
.lines b { color: var(--fg); font-family: "Latin Modern Math", "Cambria Math", "STIX Two Math", serif; font-weight: 600; margin-right: 6px; }
.text-face text { cursor: help; }
.legend { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 4px 20px; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); color: var(--dim); font-size: 0.92rem; }
.legend li { display: flex; gap: 8px; align-items: baseline; }
.legend .swatch { flex: none; width: 1.6em; height: 0.35em; border-radius: 2px; background: var(--edge); }
.legend b { color: var(--fg); font-weight: 600; }

/* Controls */
.controls { margin: 12px auto 24px; padding: 12px 16px; background: var(--panel);
  border: 1px solid var(--edge); border-radius: 8px; }
.row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 10px; }
.verb { min-width: 4.5rem; color: var(--dim); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.06em; }
button {
  font: inherit; color: var(--fg); background: var(--bg); border: 1px solid var(--edge);
  border-radius: 6px; padding: 4px 12px; cursor: pointer;
}
button:hover { border-color: var(--accent); }
button[aria-pressed="true"] { background: var(--accent); color: #11111b; border-color: var(--accent); }
.time label { color: var(--dim); }
.time output { color: var(--fg); font-variant-numeric: tabular-nums; min-width: 2ch; display: inline-block; }
.time input[type="range"] { flex: 1 1 200px; accent-color: var(--warm); }
.readout {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 6px 16px; margin: 0; font-variant-numeric: tabular-nums;
}
.readout div { display: flex; justify-content: space-between; gap: 8px; border-bottom: 1px dotted var(--edge); }
.readout dt { color: var(--dim); font-family: "Latin Modern Math", "Cambria Math", "STIX Two Math", serif; }
.readout dd { margin: 0; }
.readout .points { grid-column: 1 / -1; }
.readout .points dd { font-size: 0.95em; }
.focus-row { margin-bottom: 0; margin-top: 10px; }
.keys-row { margin: 10px 0 0; padding-top: 8px; border-top: 1px solid var(--edge); }
.key-legend { margin: 0; flex: 1; color: var(--dim); font-size: 0.85rem; }
.key-legend kbd, .help kbd {
  font: 0.85em ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--fg);
  background: var(--bg); border: 1px solid var(--edge); border-bottom-width: 2px;
  border-radius: 4px; padding: 0 5px; margin: 0 1px;
}
.key-legend.active { color: var(--warm); }
.key-legend.active kbd { border-color: var(--warm); }
.help {
  position: fixed; inset: 0; z-index: 10; display: grid; place-items: center;
  background: rgba(17, 17, 27, 0.75); padding: 16px;
}
.help[hidden] { display: none; }
.help > div {
  background: var(--panel); border: 1px solid var(--edge); border-radius: 10px;
  padding: 16px 20px; max-width: 34rem; width: 100%; max-height: 90vh; overflow: auto;
}
.help h2 { margin: 0 0 8px; font-size: 1.1rem; }
.help p { margin: 0 0 10px; color: var(--dim); font-size: 0.95rem; }
.help table { border-collapse: collapse; width: 100%; font-size: 0.95rem; }
.help td { padding: 3px 6px 3px 0; vertical-align: top; border-bottom: 1px dotted var(--edge); }
.help td:first-child { white-space: nowrap; width: 8rem; }
.help .close { margin-top: 12px; }
.focus-caption { margin: 0; flex: 1; color: var(--dim); font-size: 0.95rem; }
.focus-caption b { color: var(--fg); font-family: "Latin Modern Math", "Cambria Math", "STIX Two Math", serif; font-weight: 600; }
.focus-caption .val { color: var(--warm); font-variant-numeric: tabular-nums; }
footer { color: var(--dim); font-size: 0.9rem; padding-bottom: 32px; }
footer .colophon { border-top: 1px solid var(--edge); padding-top: 8px; font-size: 0.85rem; }

/* Callouts: one 2D box in page space with a leader line and arrowhead to the
   hovered element. The box never covers the element; the script places it
   above or below and flips it to stay in the viewport. */
.callout { position: fixed; inset: 0; z-index: 9; pointer-events: none; }
.callout[hidden] { display: none; }
.callout-box {
  position: absolute; max-width: 20rem; padding: 7px 11px;
  background: var(--panel); color: var(--fg); border: 1px solid var(--edge); border-radius: 8px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5); font-size: 0.86rem; line-height: 1.35;
  opacity: 0.92;
}
.callout-box.near { border-color: var(--warm); opacity: 1; z-index: 1; max-width: 17rem; }
.callout-box.whole { font-size: 0.98rem; max-width: 22rem; border: 2px solid var(--fg); opacity: 1; padding: 10px 14px; }
.callout-box.whole b { font-size: 1.15rem; }
.callout-leader .whole line { stroke: var(--fg); stroke-width: 2; }
.callout-leader .whole path { fill: var(--fg); }
.callout-box.far { font-size: 0.8rem; max-width: 14rem; }
.callout-box.far span { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.callout-box b { display: block; font-family: "Latin Modern Math", "Cambria Math", "STIX Two Math", serif; font-size: 1.05rem; margin-bottom: 2px; }
.callout-box small { display: block; color: var(--warm); margin-top: 4px; font-variant-numeric: tabular-nums; }
.callout-box small:empty { display: none; }
.callout-leader { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.callout-leader line { stroke: var(--edge); stroke-width: 1.5; }
.callout-leader path { fill: var(--edge); }
.callout-leader .ghost { fill: none; stroke: var(--warm); stroke-width: 1.5; }
.callout-leader .near line { stroke: var(--warm); }
.callout-leader .near path { fill: var(--warm); }
/* generous hit areas: a token's whole box, not its glyph outline */
.text-face text, .text-face tspan { pointer-events: bounding-box; }
.scene .hit line { stroke: transparent; stroke-width: 14; pointer-events: stroke; }
.scene .hit rect { fill: transparent; pointer-events: all; }
.scene .panel-hit { fill: transparent; stroke: none; pointer-events: all; }
body.no-hints .callout { display: none; }

/* Focus: every element carrying data-id is a target. The script marks the
   matching ones .focus and the body .has-focus; CSS does the rest, the same
   way on every face. */
[data-id] { cursor: pointer; }
.rs-token { transition: fill 0.15s, opacity 0.15s; }
.scene line, .scene text { transition: opacity 0.15s; }
body.has-focus .text-face .rs-token:not(.focus) { opacity: 0.4; }
body.has-focus .scene line:not(.focus), body.has-focus .scene text:not(.focus) { opacity: 0.3; }
body.has-focus .readout div:not(.focus) { opacity: 0.55; }
.rs-token.focus { fill: var(--warm); }
.scene line.focus { stroke: var(--warm) !important; stroke-width: 4.5; }
.scene text.focus { fill: var(--warm); font-weight: 700; }
.readout div.focus { border-bottom-color: var(--warm); }
.readout div.focus dt, .readout div.focus dd { color: var(--warm); }

@media (prefers-reduced-motion: reduce) {
  .stone { transition: none; }
}
.callout-box[hidden] { display: none; }
