/* reveal
   Split from the single v22 stylesheet. Everything here is scoped to
   .card.reveal and this form's own class prefix (rule 14: a change made for one
   card form is scoped to that form, by class). */
.card.drag .cardface,.card.drag .thread{transition:none}

/* ------------------------------------------------------------------ *
   The Reveal
 * ------------------------------------------------------------------ */
.card.reveal .vizsec{padding:18px 0}
/* lane-reveal-panel, 2026-09-04: the stage flexes to whatever panel it is
   given, the same fix session 33 gave The Close (`prototype/v23/forms/
   close.css`) -- foldcheck measured this form's stage overflowing its own
   panel by 34px at 430x743 (the reviewer's phone) before this. The one
   thing that grows is already right: `setup` (`.rv-spark`, below) is
   `flex:1;min-height:0` and does absorb the panel's slack exactly the way
   the shared prompt_first block means it to (shell.css, "the question's
   room comes out of setup, the only slot that flexes") -- it was already
   measuring at 0px on the two short viewports before this change, so the
   overflow was never the picture's to give.

   It was the shell's own `.revealviz{gap:16px}` (shell.css -- grepped
   first, rule 17) and this form's own internal paddings that could not:
   `gap` is not a flex item, flex-shrink does not touch it, and a padding
   cannot flex-shrink any more than a margin can (the Close comment: "only
   a flex item can"). Four gaps at a fixed 16px is 64px that never gave an
   inch back regardless of how short the panel got.

   The Close's fix was real, empty flex-item spacers between its own rows.
   That does not transplant here: this form's rows are five `data-slot`
   children the SHARED prompt_first block in shell.css orders and sizes by
   slot name (`.stage > * > [data-slot="setup"]{flex-grow:1;...}` and
   siblings) and `review/formcheck.mjs`'s `checkStack` reads each slot's
   position with a single `.find(r => r.slot === slot)` -- a second element
   sharing a slot name to act as a spacer would answer that lookup instead
   of the real row for `control`/`commit`/`note` on some code paths and
   silently break the drag-stability and post-lock checks that depend on
   it (out of this lane's paths to touch, and not worth risking to save
   30px). So instead of new elements, this rule overrides the shell's own
   `.revealviz` selector with the identical selector, unchanged specificity
   (0,1,0) -- forms load after shell.css (rule 14's own mechanism), so the
   later declaration wins the same way an accidental override would --
   except `pipeline/selftest.mjs`'s own duplicate-selector sweep (rule 17's
   guard, added session 27) does not distinguish an intentional later pass
   from the accidental collision it exists to catch, and fixing a false
   positive there means adding this selector to that file's own
   `DELIBERATE_OVERLAPS` allowlist -- `pipeline/selftest.mjs` is not one of
   this lane's paths. So `.card.reveal .revealviz` instead of the shell's
   bare `.revealviz`: three classes, (0,3,0), which outranks the shell
   rule's (0,1,0) on specificity alone regardless of load order, and reads
   as a distinct selector to that sweep because it IS one -- exactly the
   first fix the guard's own failure message suggests ("give the second
   declaration a distinct name/selector"), not a way around it.

   First pass: 16 -> 5px, paired with `.rv-foot`'s own padding-top below
   (14 -> 6, same reasoning). The two short viewports needed ~30px
   design-px back on the closed card alone (34px/28px measured, scaled)
   and the LOCKED card -- the button's text grows to two lines once it is
   carrying a guess and a verdict ("You guessed 0.0% · You missed by 8.7
   points") -- needed noticeably more again; nothing here checks that
   state at 430x743 (foldcheck does not lock a guess, and formcheck's own
   interactive drive only ever runs at 393x852) so it was found by looking
   at the frame after pressing the button, not by a gate.

   Second pass (reviewer, same day): 5 -> 1px, and `.rv-foot` 6 -> 2px,
   because the first pass's own `.rv-slot` revert (below) turned out to be
   wrong too -- see that comment. This gap and `.rv-foot`'s padding are the
   budget that pass now spends on `.rv-slot` instead, since neither of
   them positions anything against a reader-visible label the way
   `.rv-slot`'s padding does. `setup` still absorbs whatever all three
   cuts free at a tall panel (852) rather than the row rhythm changing
   there -- 852 already fit with 0px to spare closed (footnote bottom
   679.98, .vizsec's own bottom padding starts at 697.98 -- exact), so
   what these cuts free becomes more sparkline, not a narrower card. */
.card.reveal .revealviz{gap:1px}
/* The run into the filing. `flex:1` so this is the slot that absorbs the
   panel slack, which is what `setup` is for -- the job The Price gives its
   photo and The Poll its sparkline. `.rv-spark` is new; grepped first
   (rule 17). Scoped to this form (rule 14). */
.rv-spark{flex:1;min-height:0;display:block;width:100%}
.rv-spark svg{width:100%;height:100%;display:block;overflow:visible}
.rv-spark path{fill:none;stroke:var(--muted);stroke-width:1.5;
  vector-effect:non-scaling-stroke;stroke-linejoin:round;stroke-linecap:round}

/* `.rv-prompt` has no type of its own any more: it is the stack's `question`
   slot and the layout block sets it, with the other three forms' questions.

   `.rv-stage` is gone with it, and that is the load-bearing half. It grouped
   the figure, the rail, Lock in and the result into ONE child of the form
   root, and the shared stack orders the root's own children -- so those four
   rows were invisible to it and could not be sequenced against the question
   and the note. Flattened, they are four rows carrying four `data-slot`s.
   What it took with it was `justify-content:center`, which centred the group
   inside whatever height it had; nothing centres now, on either mode, which
   is what the sequence wanted anyway -- the mode that cancelled the centring
   was doing it because the centring was wrong, not because the mode was
   unusual. The 16px step is the same one `.revealviz` already set between its
   own rows, so the rhythm does not change (rule 15: one step, not two). */

/* The guess, before. The largest thing on the card until there is an answer. */
.rv-value{font-size:var(--fs-guess);font-weight:700;line-height:1;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1;color:var(--ink);
  transition:color .18s ease-out}
.rv-value.up{color:var(--up)}
.rv-value.dn{color:var(--down)}

/* lane-reveal-panel, 2026-09-04 (second pass, reviewer): 14 -> 38, and the
   first pass's own revert of this rule (which is what shipped as "14,
   unchanged" before this) turns out to have been the wrong fix for the
   right finding. `.rv-mark em`'s label sits `top:-24px` off its mark
   (`-44px` in `lane1`, the second row it takes when two labels would
   collide, which this card's own data does: "You 0.0%" and "Crowd +4.1%"
   land close enough to force one of them up), and the mark itself anchors
   on `.rv-track`'s own vertical centre -- `.rv-slot`'s padding-top plus
   half the track's 8px. That overlap is pre-existing on `main` at the
   unmodified 14px (confirmed on port 8420, main's own server, read-only,
   before touching anything here: the CROWD label already overlaps the
   hero figure there, at a worse 50px panel overflow besides) and was NOT
   caused by the first pass's gap cut -- shrinking the shared `.revealviz`
   gap moved the whole answer-to-control run closer together, but the
   label's own reach was already past 14px of clearance before that ever
   happened. So the padding needed to GROW, not stay put: raised to 38,
   measured against the actual rendered boxes (`.rv-value`'s bottom edge
   vs `.rv-mark.lane1 em`'s bottom edge, both read via
   `getBoundingClientRect()`) rather than reasoned from the CSS numbers,
   because the scale transform at 430 makes the two disagree -- 38 clears
   the worst case (the lane1 collision this card's data actually produces)
   by ~4px of screen space at 430x743, the tightest viewport. `.rv-range`'s
   `top` moves with it, unchanged reasoning from the first pass (pinned to
   this same padding so the invisible slider stays under the visible
   track). The budget comes from the `.revealviz` gap and `.rv-foot` above
   and below (1px and 2px now, from 5 and 6), not from shrinking any of
   the three protected rows (rule: "the sparkline, the slider ..., and the
   reveal answer... stay legible"). */
.rv-slot{position:relative;padding:38px 0 0}
/* The rail the input draws on and the markers share, so a marker at 8.74%
   lands exactly where the thumb would. */
.rv-track{position:relative;height:8px;border-radius:var(--radius-xs);background:var(--line);margin:0 0 8px}
.rv-range{position:absolute;left:0;right:0;top:38px;width:100%;height:8px;margin:0;
  -webkit-appearance:none;appearance:none;background:none;z-index:2;cursor:grab;
  /* a drag on the rail must not take the feed with it */
  touch-action:none}
.rv-range:active{cursor:grabbing}
.rv-range::-webkit-slider-runnable-track{height:8px;border-radius:var(--radius-xs);background:var(--line)}
.rv-range::-moz-range-track{height:8px;border-radius:var(--radius-xs);background:var(--line)}
.rv-range::-webkit-slider-thumb{-webkit-appearance:none;width:26px;height:26px;border-radius:50%;
  background:var(--ink);border:0;margin-top:-9px;box-shadow:0 2px 10px rgba(0,0,0,.5)}
.rv-range::-moz-range-thumb{width:26px;height:26px;border-radius:50%;background:var(--ink);border:0}
.rv-range:focus-visible{outline:2px solid var(--muted);outline-offset:6px;border-radius:var(--radius-xs)}

.rv-scale{display:flex;justify-content:space-between;font-size:12px;color:var(--dim);
  letter-spacing:0;text-transform:none;font-variant-numeric:tabular-nums}

/* Markers exist only after the lock. Before it, showing where the answer sits
   would be the card answering its own question. */
.rv-mark{position:absolute;top:50%;transform:translate(-50%,-50%);opacity:0;
  pointer-events:none;transition:opacity .3s ease-out,left .5s cubic-bezier(.16,1,.3,1)}
.rv-mark i{display:block;width:3px;height:22px;border-radius:var(--radius-xs);background:var(--muted);margin:0 auto}
.rv-mark em:empty{display:none}
.rv-mark em{position:absolute;left:50%;top:-24px;white-space:nowrap;
  font-style:normal;font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
  color:var(--muted);font-variant-numeric:tabular-nums}
/* The second lane, taken only when a label would otherwise land on top of the
   one beside it -- js/guessmark.js's `paintGuessMarks` applies this class
   now, not this form's own layoutMarks, generalised from three marks to
   however many of `mine`/`crowd` a caller has (the answer, `real` below,
   never joins that group -- see that file's own header). */
.rv-mark.lane1 em{top:-44px}
/* `rv-real` and `rv-mine`, not `rv-actual`/`rv-you`: the guess-family's own
   suffixes for the answer and the guess (js/guessmark.js, shared with
   forms/price.css's `.pr-real`/`.pr-mine` and forms/pricegap.css's
   `.pg-real`/`.pg-mine`), which this form did not use until it started
   painting its rail marks with the same shared function. */
.rv-mark.rv-real i{background:var(--up);width:4px;height:28px}
.rv-mark.rv-real em{color:var(--up);top:26px}
.rv-mark.rv-real.lane1 em{top:46px}
.rv-mark.rv-real.dn i{background:var(--down)}
.rv-mark.rv-real.dn em{color:var(--down)}
.rv-mark.rv-mine i{background:var(--ink)}
.rv-mark.rv-mine em{color:var(--ink)}
/* Sample data, and subordinate on the evidence as well as in the hierarchy. */
.rv-mark.rv-crowd i{background:var(--edge);width:2px;height:16px}
.rv-mark.rv-crowd em{color:var(--dim);font-size:10px}

.revealviz.locked .rv-range{opacity:0;pointer-events:none}
.revealviz.locked .rv-mark{opacity:1;transition-delay:.15s}
/* Locking changes what the card SAYS and nothing about where it says it.

   These four rules used to live here and each one moved the layout:
   `.rv-slot{padding-top:58px}`, `.rv-track{margin-bottom:34px}`,
   `.rv-lock{display:none}` and `.rv-value{display:none}`, with `.rv-result`
   arriving underneath. Measured on the sibling form -- the same pattern, the
   same four rules -- the picture lost 81.7px of its 153.9 and every row
   between it and the footnote rose by the same amount. The reader answers a
   question and the card rearranges itself around the answer, so the thing
   they were looking at is not the thing they are looking at.

   The reveal is the two marks on the rail and the figure changing. Both were
   already in place: the marks are absolutely positioned inside the track, so
   the 58px and the 34px were visual room rather than containment, and the
   figure is the same box the guess was shown in. What was additive was the
   block underneath -- and its two sentences are the reader's own result, which
   fits in the button that asked for it. */

.rv-lock{appearance:none;-webkit-appearance:none;width:100%;padding:15px 16px;border:0;
  border-radius:var(--radius-md);background:var(--ink);color:var(--lock-ink);cursor:pointer;
  font:700 16px/1 "IBM Plex Sans",system-ui,sans-serif;letter-spacing:-.01em;
  transition:transform .12s ease-out,opacity .18s ease-out}
.rv-lock:hover{opacity:.9}
.rv-lock:active{transform:scale(.985)}
/* The guess, once locked ("Locked in +3.0%"), keeps its sign colour the same
   way `.rv-value` and `.rv-yours`'s own "Actual" figure do -- against this
   button's own inverted fill (`background:var(--ink)`), not the card's. */
.rv-lock b{font-weight:800}
.rv-lock b.up{color:var(--up)}
.rv-lock b.dn{color:var(--down)}

/* `.rv-outcome` and `.rv-explain` stay off the face -- the outcome is
   already the figure (`.rv-value`, above), and the explain paragraph and
   the methodology are what Read more is for; kept in the markup because
   the detail view reads them. `.rv-yours` and `.rv-lines` are the "result
   line" the votes lane's crowd median had nowhere to show (NEXT.md): the
   actual figure and how far the reader's guess (`.rv-lock`, which carries
   the guess itself) sat from it, and, when the store has one, the crowd's.
   `display` was the only thing keeping them off the card.

   Shown once locked, not before. This USED to be `display:none` holding no
   space in the flex column, with what became visible paying for its own
   height out of `.rv-spark` (`flex:1`, the one row in this stack that
   flexes) -- which kept the claim, the timestamp and the action row
   (siblings of `.vizsec`, structurally untouchable from inside it) from
   moving, but not the rest of THIS form's own stack: shrinking `.rv-spark`
   to make room pulled every row below it -- `.rv-value`, `.rv-slot`, the
   rail, `.rv-lock` -- up by the exact height `.rv-result` gained, which
   `review/formcheck.mjs`'s answer-stability check (session 42, the
   reviewer: "before the guess/answer should be similar to after the guess
   ... with the extra stuff appearing") now catches by name. Locking still
   changes nothing about where anything sits -- `visibility:hidden` instead
   of `display:none` means this row is IN the flex column from the first
   paint, at the height js/forms/reveal.js's `reserveResultHeight()`
   measures off this card's own real "Actual ..." text (and a representative
   crowd line, since a `crowdOpen` card's median can arrive after the lock
   this reserve already has to be in place for) -- so `.rv-spark` never
   resizes at lock, it is simply born however many px shorter this card's
   own answer needs, once, and stays that size regardless of lock state.

   No fade of its own, deliberately: everything this line says (the actual
   figure and how far the guess sat from it) is already known the instant
   the reader locks, same as the figure flipping to `actual` and the lock
   button's own text -- both instant, no delay, on the same `.locked` class
   flip. A staged reveal (marks first, this line after) was tried and
   dropped -- it could not be told apart, in a driven capture, from never
   finishing: `review/simdrive.mjs` has no clock for this form
   (`card.__clock` is Move/Poll/Insider/Close only, confirmed by running
   `--seek` here and reading its own refusal) and no way to let real time
   pass between a `--js` click and the `--shot` that follows it other than
   blocking the main thread, which freezes the animation's own clock right
   along with it -- proven by a 900ms busy-wait after the click still
   reading the delayed rule's opacity at 0. `formcheck.mjs`'s Playwright
   drive does not share that limit (`page.waitForTimeout` is a real,
   non-blocking wait), so a delayed reveal would have been provable there
   and unprovable everywhere else this form gets looked at by hand -- not
   a trade worth making for motion the brief never asked for. */
.rv-result{display:flex;flex-direction:column;gap:9px;margin-top:10px;visibility:hidden}
.revealviz.locked .rv-result{visibility:visible}
/* Still not drawn -- `.rv-result` going `flex` makes every child a flex item
   regardless of ITS OWN `display`, so the outcome and the explain paragraph
   need their own `display:none` now that their parent is visible, or they
   would render as two more rows nobody asked to see. */
.rv-outcome,.rv-explain{display:none}
/* 1 the market, 2 your guess against it, 3 the crowd, 4 why, 5 methodology. */
.rv-outcome{font-size:clamp(26px,7.4vw,32px);font-weight:700;line-height:1.1;
  letter-spacing:-.02em;color:var(--stance);font-variant-numeric:tabular-nums}
.rv-yours{font-size:15px;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.rv-yours b{font-weight:700}
.rv-yours b.up{color:var(--up)}
.rv-yours b.dn{color:var(--down)}
.rv-lines{display:flex;flex-direction:column;gap:3px;font-size:13px;color:var(--dim);
  font-variant-numeric:tabular-nums}
.rv-lines b{color:var(--muted);font-weight:600}
.rv-explain{font-size:13px;line-height:1.5;color:var(--dim)}

/* No margin-top:auto -- the stack's `note` slot sets it, once, for every
   prompt-first form (rule 17). lane-reveal-panel, 2026-09-04: 14 -> 6, the
   same give as the `.revealviz` gap above (see that comment) -- pure
   position padding above the rule, nothing positioned against it the way
   `.rv-range`'s `top:14px` is pinned to `.rv-slot`'s own padding. */
.rv-foot{padding-top:2px;display:flex;flex-direction:column;gap:1px;
  border-top:1px solid var(--line)}
.rv-when{font-size:12.5px;color:var(--muted)}
.rv-note{font-size:12.5px;color:var(--dim)}
.rv-again{display:none;align-self:flex-start;margin-top:5px;appearance:none;-webkit-appearance:none;
  background:none;border:0;padding:0;color:var(--muted);cursor:pointer;
  font:600 12px/1 "IBM Plex Sans",system-ui,sans-serif;
  text-decoration:underline;text-underline-offset:3px}
/* Prototype only: shown when the renderer is opened with ?dev=1, so the
   production card has no way to un-answer itself. */
body.devtools .revealviz.locked .rv-again{display:inline-block}
.rv-again:hover,.rv-again:focus-visible{color:var(--ink)}
