/* s04.css — section 04's graphic styles only (the grade plate). Owns the
   plate SVG's proportion + its dim/blue text, the per-zone hover emphasis,
   the reserved readout block (dim-label / blue-value grammar), and the
   [ next ] bracket control. Shared shell lives in research.css. HARD RULE:
   hover/click change pixels only — the canvas is a fixed aspect-ratio box
   sized from the viewBox alone, so text-length changes across the three
   cycled specimens (reserved to the widest specimen's own glyph count
   inside the SVG's fixed column) can never move the container, and the
   readout sits in a fixed-height block OUTSIDE the SVG so a rolling
   explanation swaps glyphs without moving anything. */

.spec-04 {
  max-width: 392px;
}

/* fixed box: the plate's viewBox is 360 x 152 — lock that ratio */
.spec-04 .spec-canvas {
  aspect-ratio: 360 / 152;
}

.spec-04 .spec-canvas svg text {
  font-family: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-weight: 300;
  font-size: 12px;
  fill: currentColor;
}

.spec-04 .spec-canvas svg .sv-dim {
  opacity: 0.5;
}

.spec-04 .spec-canvas svg text.sv-val {
  fill: #2222ff;
  transition: fill 120ms linear;
}

/* the counter — dim, reserved in the SVG's top-right (past the badge box),
   never affecting geometry since it's just a text node in the viewBox */
.spec-04 .spec-canvas svg .sv-counter {
  font-size: 10.5px;
}

/* the specimen caption sits under the counter, dim — it names the honesty
   qualifier permanently in the composition (never hidden by any state) */
.spec-04 .spec-canvas svg .sv-caption {
  font-size: 10.5px;
}

/* the grade token: its own hover zone (a transparent hit-rect over the
   badge box drives the .is-hot class). Resting it is the blue value; hot,
   it goes heavier + black like a row value, distinct from resting blue. */
.spec-04 .spec-canvas svg .sv-hit {
  fill: transparent;
  cursor: pointer;
}

.spec-04 .spec-canvas svg .sv-grade {
  transition: fill 120ms linear;
}

.spec-04 .spec-canvas svg .sv-zone.is-hot .sv-grade {
  fill: #000;
  font-weight: 500;
}

/* the badge frame brightens when its zone is hot (pixels only) */
.spec-04 .spec-canvas svg .sv-badge {
  transition: stroke 120ms linear, stroke-width 120ms linear;
}

.spec-04 .spec-canvas svg .sv-zone.is-hot .sv-badge {
  stroke: #2222ff;
  stroke-width: 1.4;
}

/* row hover: the value goes heavier + black (not blue-on-blue, so the
   emphasis reads distinctly from the plate's normal blue value color);
   the label brightens off its dim baseline. Pixels only — the <g> and its
   two <text> children keep their plotted x/y. */
.spec-04 .spec-canvas svg .sv-row {
  cursor: pointer;
}

.spec-04 .spec-canvas svg .sv-row .sv-dim {
  transition: opacity 120ms linear;
}

.spec-04 .spec-canvas svg .sv-row.is-hot .sv-dim {
  opacity: 0.9;
}

.spec-04 .spec-canvas svg .sv-row.is-hot .sv-val {
  fill: #000;
  font-weight: 500;
}

/* ---- the panel: reserved readout block + the [ next ] control, laid out
   so they never collide (mirrors s02's rn-panel) ---- */
.spec-04 .gp-panel {
  margin-top: 14px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

/* the readout: a dim label + a blue explanation, both in reserved slots so
   an NSRoll swap changes glyphs only. Fixed to two lines' height at all
   times (idle included) so the block never grows when a long explanation
   rolls in — the shell's one-line .spec-readout is deliberately NOT used
   here (this readout is its own block). */
.spec-04 .gp-readout {
  font-family: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--ink-dim);
  /* FIXED two-line height with overflow:hidden — the longest explanation
     wraps to exactly 2 lines at every supported column width (>=375px: the
     readout column is >=260px wide, where the longest string is 2 lines),
     and the idle/short lines sit top-aligned inside the held box. A fixed
     height (not min-height) means NO state — idle, hover, or a long roll —
     can ever grow the block: geometry is locked, pixels only. */
  height: 2.8em;
  overflow: hidden;
  flex: 1 1 auto;
  min-width: 0;
}

/* the label row: dim key in a reserved slot, then the blue value. The key
   is width-reserved to the longest zone name ("separator" 9 + a space) so
   the value column start never shifts. */
.spec-04 .gp-readout .gp-rl {
  color: var(--ink-dim);
  display: inline-block;
  min-width: 11ch;
  padding-right: 1ch;
  box-sizing: border-box;
}
.spec-04 .gp-readout .gp-rv {
  color: #2222ff;
}

/* the [ next ] control — bracket-affordance, dim ink, brightens on hover /
   focus; a real <button> fixed in the panel's top-right, nothing can
   collide with it (the readout to its left is width-bounded, min-width:0) */
.spec-04 .gp-next {
  flex: none;
  border: 0;
  background: transparent;
  padding: 0;
  margin: 0;
  font-family: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-weight: 300;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--ink);
  opacity: 0.45;
  cursor: pointer;
  transition: opacity 120ms linear;
  white-space: nowrap;
}
.spec-04 .gp-next:hover,
.spec-04 .gp-next:focus-visible {
  opacity: 0.9;
}

/* ---- essay-band recolour (white ink on the dark band) ---- */
.essay-band .spec-04 .gp-readout { color: rgba(255, 255, 255, 0.55); }
.essay-band .spec-04 .gp-readout .gp-rl { color: rgba(255, 255, 255, 0.55); }
.essay-band .spec-04 .gp-readout .gp-rv { color: #6a6aff; }
.essay-band .spec-04 .gp-next { color: #fff; }

/* under a narrow column, stack the readout above the control so nothing
   can crowd — the panel becomes a single column */
@media (max-width: 560px) {
  .spec-04 .gp-panel {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .spec-04 .gp-next { align-self: flex-start; }
}
