/* holdwise.css - the whole site.  (A12, A19-A23, A26)
 *
 * THE ASSAY OFFICE. Not a dashboard. Surfaces are a workbench, the
 * signature element is the hallmark strike, and there is exactly ONE
 * animation on this entire site - the strike landing. No reveals, no
 * parallax, no gradient drift, no transitions. If a second animation
 * appears here, the strike stops being an event.
 *
 * SOLO-OPERATOR LAW: no build toolchain. No preprocessor, no bundler, no
 * framework. Plain CSS a person can read on a phone at 2am.
 *
 * MOBILE-FIRST. Base rules are the phone. One breakpoint, at 40rem.
 *
 * CONTRAST FLOOR. tests/test_accessibility_floor.py reads the tokens below
 * and recomputes every WCAG ratio from these hex values - including the
 * stamp's effective colour after its blend and opacity. Changing a colour
 * here can fail the suite. That is the point.
 */

/* ==========================================================================
   A20 - TYPE. Self-hosted, no external fetch of any kind.
   Only the four faces the site actually uses are declared. The zip also
   ships Public Sans Italic and JetBrains Mono Italic; they are kept with
   their licenses and deliberately NOT declared, because the Fraunces
   why-sentence is the only italic on this site.
   ========================================================================== */

@font-face {
  font-family: "Fraunces";
  src: url("/static/fonts/Fraunces-VF.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Fraunces";
  src: url("/static/fonts/Fraunces-Italic-VF.woff2") format("woff2");
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Public Sans";
  src: url("/static/fonts/PublicSans-VF.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("/static/fonts/JetBrainsMono-VF.woff2") format("woff2");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

/* ==========================================================================
   A19 - TOKENS
   ========================================================================== */

:root {
  --ink:       #12100E;   /* page ground. Warm brown-black, never blue-black */
  --bench:     #241F1A;   /* raised surfaces, panels - the workbench */
  --oxide:     #3A342C;   /* HAIRLINES, DIVIDERS, DISABLED ONLY. Never text. */
  --bone:      #E8E2D6;   /* primary text            14.72:1 on INK */
  --ash:       #9A9287;   /* secondary text, labels   6.18:1 on INK */
  --verdigris: #3F7A6E;   /* affirmative stamp ink */
  --oxblood:   #7A2E28;   /* rejection stamp ink */
  --brass:     #B08D4F;   /* tier badges + wordmark rule ONLY */

  --display: "Fraunces", Georgia, "Times New Roman", serif;
  --sans: "Public Sans", ui-sans-serif, -apple-system, BlinkMacSystemFont,
          "Segoe UI", Helvetica, Arial, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas,
          monospace;

  --radius: 4px;
  --stamp-radius: 6px;          /* A21: rounded rect. NEVER a circle. */
  --tap: 3rem;                  /* 48px - never smaller on any control */
  --pad: 1.25rem;
  --maxw: 40rem;
  --measure: 62ch;              /* A20: body copy never runs wider */

  --strike-ms: 260ms;
  --strike-ease: cubic-bezier(.2, .9, .25, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: 0 0 4rem;
  background: var(--ink);
  color: var(--bone);
  font-family: var(--sans);
  font-weight: 400;
  font-size: 1rem;
  line-height: 1.6;
}

.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--pad); }

p { max-width: var(--measure); }

/* --- keyboard access ------------------------------------------------- */

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--brass); color: var(--ink);
  padding: .75rem 1rem; z-index: 50; font-weight: 700;
}
.skip:focus { left: 0; }

:focus-visible {
  outline: 3px solid var(--brass);
  outline-offset: 2px;
  border-radius: var(--radius);
}

/* ==========================================================================
   MASTHEAD - A20 wordmark
   ========================================================================== */

.masthead { padding: 2rem var(--pad) 1rem; text-align: center; }

.wordmark {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(2.5rem, 6vw, 4.5rem);
  font-weight: 700;
  font-optical-sizing: none;
  font-variation-settings: "opsz" 144, "wght" 700, "SOFT" 0, "WONK" 0;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--bone);
}
.wordmark a { color: inherit; text-decoration: none; }

/* the 1px BRASS rule beneath the wordmark, 60% width */
.wordmark::after {
  content: "";
  display: block;
  width: 60%;
  height: 1px;
  margin: .5rem auto 0;
  background: var(--brass);
}

.slogan {
  margin: .6rem auto 0;
  font-family: var(--sans);
  font-weight: 500;
  font-size: .8125rem;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--ash);
}

/* --- nav -------------------------------------------------------------- */

.nav {
  display: flex; gap: .25rem; justify-content: center; flex-wrap: wrap;
  padding: 1rem var(--pad) 0;
  border-bottom: 1px solid var(--oxide);
  margin-bottom: 1.5rem;
}
.nav a {
  display: block;
  min-height: var(--tap);
  padding: .8rem .7rem;
  color: var(--ash);
  text-decoration: none;
  font-size: .75rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  border-bottom: 2px solid transparent;
}
.nav a:hover { color: var(--bone); }
.nav a[aria-current="page"] { color: var(--bone); border-bottom-color: var(--brass); }

/* ==========================================================================
   BLOCKS
   ========================================================================== */

h1, h2, h3 { line-height: 1.2; }

.page-title {
  font-family: var(--mono);
  font-size: .75rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ash); margin: 0 0 1.25rem; font-weight: 500;
}

.panel {
  background: var(--bench);
  border: 1px solid var(--oxide);
  border-radius: var(--radius);
  padding: var(--pad);
  margin: 0 0 1rem;
}

.rule { border: 0; border-top: 1px solid var(--oxide); margin: 1.5rem 0; }

.muted { color: var(--ash); }
.small { font-size: .8125rem; }
.center { text-align: center; }

/* A20: JetBrains Mono carries every numeral, cert, card number and figure */
.mono, .figure, .datum__value { font-family: var(--mono); }

.figure { font-size: 1.5rem; color: var(--bone); font-weight: 500; }

.label {
  font-family: var(--mono);
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--ash);
  display: block;
}

/* ==========================================================================
   CONTROLS
   ========================================================================== */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap);
  width: 100%;
  padding: .85rem 1rem;
  border: 1px solid var(--oxide);
  border-radius: var(--radius);
  background: var(--bench);
  color: var(--bone);
  font-family: var(--sans);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { border-color: var(--ash); }
.btn--quiet { background: transparent; color: var(--ash); }
.btn--danger { color: var(--oxblood); border-color: var(--oxide); }
.btn[disabled] { color: var(--oxide); border-color: var(--oxide); cursor: not-allowed; }

/* A22: THE one control above the fold. BRASS border, INK fill. */
.btn--rank {
  min-height: 4.5rem;
  background: var(--ink);
  border: 1px solid var(--brass);
  color: var(--brass);
  font-family: var(--sans);
  font-size: 1.125rem;
  font-weight: 800;
  letter-spacing: .18em;
}
.btn--rank:hover { border-color: var(--bone); color: var(--bone); }

.rank-caption {
  margin: .75rem auto 0;
  text-align: center;
  color: var(--ash);
  font-size: .9rem;
}

label { display: block; font-family: var(--mono); font-size: .75rem;
        letter-spacing: .1em; text-transform: uppercase;
        color: var(--ash); margin: 0 0 .4rem; }

input[type="text"], input[type="search"], input[type="number"],
input[type="file"], select {
  width: 100%;
  min-height: var(--tap);
  padding: .7rem .8rem;
  background: var(--ink);
  border: 1px solid var(--oxide);
  border-radius: var(--radius);
  color: var(--bone);
  font-family: var(--sans);
  font-size: 1rem;         /* 16px: anything smaller makes iOS zoom on focus */
}
input[type="number"], input[type="search"] { font-family: var(--mono); }
input::placeholder { color: var(--ash); opacity: .75; }

/* THE PHOTO PICKER.  (A.11)
   A browser writes "Choose File" and "No file chosen" on a file input and
   there is no attribute that changes those words. This site says "Choose
   Photo" and "No photo chosen", because a photo is what it is asking for -
   so the native control is taken off the screen and a <label> is styled to
   stand in its place. The input is still there, still focusable, still what
   the form posts: it is clipped to a pixel rather than display:none, which
   would take it out of the tab order and hand keyboard users nothing. */
.file-field { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem; }
.file-field .file-input {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: 0; overflow: hidden; white-space: nowrap;
  clip: rect(0 0 0 0); clip-path: inset(50%); border: 0;
}
.file-field .btn { width: auto; flex: 0 0 auto; padding-inline: 1.1rem;
                   cursor: pointer; }
/* The keyboard focus ring belongs to the input; it has to be drawn on the
   thing the user can actually see, which is the label beside it. */
.file-field .file-input:focus-visible + .btn { outline: 2px solid var(--brass);
                                               outline-offset: 2px; }
.file-name { color: var(--ash); font-family: var(--mono); font-size: .8rem; }

/* A.12: the way out, sitting in the nav as though it were another link.
   It is a form and not a link because logging out is a change, and a change
   made by following a link is one a browser can make on its own. */
.nav__out { display: inline; margin: 0; }
.nav__out button {
  background: none; border: 0; padding: 0;
  color: inherit; font: inherit; letter-spacing: inherit;
  text-transform: inherit; cursor: pointer;
}

.field { margin: 0 0 1.25rem; }
.row { display: flex; gap: .5rem; align-items: stretch; }
.row .btn { width: auto; flex: 0 0 auto; padding-inline: 1.1rem; }
.row input { flex: 1 1 auto; }

fieldset { border: 1px solid var(--oxide); border-radius: var(--radius);
           padding: var(--pad); margin: 0 0 1rem; }
legend { padding: 0 .4rem; font-family: var(--mono); font-size: .7rem;
         letter-spacing: .1em; text-transform: uppercase; color: var(--ash); }

.check {
  display: flex; align-items: center; gap: .75rem;
  min-height: var(--tap); cursor: pointer;
  color: var(--bone); font-family: var(--sans); font-size: 1rem;
  letter-spacing: normal; text-transform: none; margin: 0;
}
.check input { width: 1.35rem; height: 1.35rem; accent-color: var(--brass); flex: 0 0 auto; }

/* ==========================================================================
   A21 - THE STAMP. The signature element.
   ========================================================================== */

.stamp-stage {
  position: relative;
  padding: 2rem .5rem;
  display: flex; justify-content: center;
  overflow: hidden;          /* the tilt must never widen the page */
}

.stamp {
  --stamp-gap: var(--ink);
  --strike-rot: -7deg;
  display: inline-block;
  padding: 1.1rem 2.2rem;
  border: 4px solid currentColor;
  border-radius: var(--stamp-radius);        /* NEVER a circle */
  /* the double rule: 3px gap in the ground, then a 1.5px inner rule */
  box-shadow: inset 0 0 0 3px var(--stamp-gap),
              inset 0 0 0 4.5px currentColor;
  text-align: center;
  text-transform: uppercase;
  font-family: var(--sans);
  font-weight: 900;                          /* A20: 900 IS the stamp face */
  line-height: .98;
  letter-spacing: .01em;
  /* THE INK EFFECT. `screen`, not `multiply`: on a warm-dark ground
   * multiply drives the ink toward black and measures 1.2:1 against its own
   * bench - the strike disappears. Screen is the same physics inverted, and
   * it is what a hallmark struck into dark metal actually does: the struck
   * face catches the light. The intent (the bench showing through the ink)
   * is unchanged. */
  opacity: .88;
  mix-blend-mode: screen;
  transform: rotate(var(--strike-rot));
}

.stamp__line { display: block; }

/* the date line beneath the main text */
.stamp__date {
  display: block;
  margin-top: .55rem;
  font-family: var(--mono);
  font-size: .7rem;
  font-weight: 400;
  letter-spacing: .08em;
  color: currentColor;
  opacity: .7;
}

/* FACE A - INVESTABLE. VERDIGRIS ink, -7deg, overlapping the card panel. */
.stamp--invest {
  --strike-rot: -7deg;
  --stamp-gap: var(--bench);
  color: var(--verdigris);
  font-size: clamp(1.6rem, 8vw, 2.6rem);
}

/* FACE B - SAVE YOUR MONEY, CHAMP. OXBLOOD ink, +4deg (a different angle on
 * purpose), LARGER than Face A, dead centre.
 *
 * Face B is a STRUCK FIELD, not outlined letters: OXBLOOD as a foreground on
 * the bench measures 2.16:1 even screened, which is unreadable, and this is
 * the screen the product is judged on. Filling the field with the same ink
 * and knocking the letters out in BONE keeps OXBLOOD as the ink exactly as
 * ordered and puts the lettering back above the contrast floor. */
.stamp--reject {
  --strike-rot: 4deg;
  --stamp-gap: var(--oxblood);
  color: var(--oxblood);
  background: var(--oxblood);
  font-size: clamp(2rem, 11vw, 3.6rem);
}
.stamp--reject .stamp__line,
.stamp--reject .stamp__date { color: var(--bone); }
.stamp--reject { box-shadow: inset 0 0 0 3px var(--oxblood),
                             inset 0 0 0 4.5px var(--bone); }

/* THE STRIKE - the ONE animation on this entire site. */
@keyframes strike {
  0%   { opacity: 0;   transform: rotate(calc(var(--strike-rot) * 2.6)) scale(1.6); }
  62%  { opacity: .95; transform: rotate(calc(var(--strike-rot) * .92)) scale(.97); }
  100% { opacity: .88; transform: rotate(var(--strike-rot)) scale(1); }
}
.stamp { animation: strike var(--strike-ms) var(--strike-ease) both; }

/* A22 - the hero: an EMPTY stamp awaiting a card. It never animates: there
 * is nothing to strike yet. */
.stamp--awaiting {
  --strike-rot: -7deg;
  --stamp-gap: var(--ink);
  color: var(--verdigris);
  opacity: .18;
  font-size: clamp(2rem, 13vw, 4rem);
  animation: none;
  mix-blend-mode: normal;
}

/* the texture filter target */
.stamp-filters { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ==========================================================================
   A23 - THE DOCKET
   ========================================================================== */

.docket { padding-top: .5rem; }

.docket__id { margin-bottom: 1.25rem; }
.docket__provenance {
  font-family: var(--mono);
  font-size: .75rem;
  letter-spacing: .06em;
  color: var(--ash);
  text-transform: uppercase;
}
.docket__name {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 1.5rem;
  color: var(--bone);
  margin: .35rem 0;
  line-height: 1.2;
}
.docket__grade {
  font-family: var(--mono);
  font-size: .8125rem;
  color: var(--ash);
}

.docket section { padding: 1.5rem 0; border-top: 1px solid var(--oxide); }
.docket section:first-of-type { border-top: 0; }

/* the user's photo - the ONLY image on this site */
.plate {
  position: relative;
  background: var(--bench);
  border: 1px solid var(--oxide);
  border-radius: var(--radius);
  padding: .5rem;
}
.plate img {
  display: block; width: 100%; height: auto;
  border-radius: 2px;
}
.plate .stamp-stage {
  position: absolute;
  top: -6%; right: -4%;
  padding: 0;
  width: 60%;
  justify-content: flex-end;
  overflow: visible;
}

/* A20: the why-sentence. Fraunces italic - the ONLY italic on the site. */
.why {
  font-family: var(--display);
  font-style: italic;
  font-weight: 400;
  font-optical-sizing: none;
  font-variation-settings: "opsz" 48, "wght" 400, "SOFT" 40, "WONK" 0;
  font-size: clamp(1.25rem, 2.6vw, 1.75rem);
  line-height: 1.45;
  color: var(--bone);
  margin: 0;
  max-width: var(--measure);
}

/* A20: the tier badge */
.tier-badge {
  display: inline-block;
  font-family: var(--sans);
  font-weight: 800;
  font-size: 1rem;
  letter-spacing: .22em;
  text-indent: .22em;
  text-transform: uppercase;
  color: var(--brass);
  background: var(--bench);
  border: 1px solid var(--brass);
  border-radius: var(--radius);
  padding: .5rem .9rem;
}

/* ==========================================================================
   A26 - NUMBERS BLOCK AND BAND RAIL
   ========================================================================== */

.data-pair {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;
  margin: 0 0 1.5rem;
}
.datum { min-width: 0; }
.datum__value { font-size: 1.5rem; color: var(--bone); font-weight: 500;
                margin: .3rem 0 0; word-break: break-word; }
.datum__note { font-family: var(--mono); font-size: .7rem; color: var(--ash); }

.projections { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.proj { border: 1px solid var(--oxide); border-radius: var(--radius);
        padding: .9rem; }
.proj__horizon { font-family: var(--mono); font-size: .75rem;
                 text-transform: uppercase; letter-spacing: .1em;
                 color: var(--ash); }
.proj__base { font-family: var(--mono); font-size: 1.5rem; color: var(--bone);
              margin: .3rem 0; }
.proj__spread { font-family: var(--mono); font-size: .75rem; color: var(--ash); }

/* the rail */
.rail { margin: 1.5rem 0 .5rem; }
.rail__track {
  position: relative;
  height: 1px;
  background: var(--oxide);
  margin: 2.25rem 0 2.75rem;
}
.rail__fill {
  position: absolute; top: -2px; height: 5px;
  background: var(--verdigris);
}
.rail__fill.is-over { background: var(--oxblood); }
.rail__tick {
  position: absolute; top: -6px; width: 1px; height: 13px;
  background: var(--ash);
}
.rail__tick span {
  position: absolute; top: -1.6rem; left: 50%;
  transform: translateX(-50%);
  font-family: var(--mono); font-size: .625rem; letter-spacing: .1em;
  color: var(--ash); text-transform: uppercase; white-space: nowrap;
}
.rail__tick b {
  position: absolute; top: 1rem; left: 50%;
  transform: translateX(-50%);
  font-family: var(--mono); font-size: .6875rem; font-weight: 400;
  color: var(--bone); white-space: nowrap;
}
.rail__marker {
  position: absolute; top: -11px; width: 3px; height: 23px;
  background: var(--bone);
}
.rail__marker.is-yours { background: var(--brass); }
.rail__legend {
  display: flex; gap: 1.25rem; flex-wrap: wrap;
  font-family: var(--mono); font-size: .7rem; color: var(--ash);
}
.rail__legend b { color: var(--bone); font-weight: 400; }

/* the dial */
.dial__answer {
  font-family: var(--mono);
  font-size: 1.5rem;
  color: var(--bone);
  margin: .5rem 0;
}
.dial__modes { display: flex; gap: .5rem; margin-bottom: 1rem; flex-wrap: wrap; }
.dial__modes .btn { width: auto; flex: 1 1 auto; font-size: .75rem;
                    letter-spacing: .08em; }
.dial__modes .btn[aria-pressed="true"] { border-color: var(--brass);
                                         color: var(--brass); }

/* A.10: the horizon is stated, not chosen - one horizon ships. Sized to sit
   on the same baseline as the input beside it so the pair still reads as a
   row of two fields rather than a field and a stray sentence. */
.dial__fixed {
  font-family: var(--mono);
  color: var(--bone);
  margin: .35rem 0 0;
  padding: .55rem 0;
}

.tag {
  display: inline-block;
  padding: .25rem .55rem;
  border: 1px solid currentColor;
  border-radius: var(--radius);
  font-family: var(--mono);
  font-size: .625rem;
  letter-spacing: .1em;
  text-transform: uppercase;
}
/* NO-SALES: the shelf's short marker for a card the engine issued a
   market disclosure on. ASH, the same weight as PROVISIONAL, on purpose -
   it is a statement about what is KNOWN, not an alarm about the card, and
   a louder colour would read as a downgrade the verdict did not make. The
   full sentence lives on the docket; this is the reminder that survives
   the row format. */
.tag--illustrative, .tag--provisional, .tag--nosales { color: var(--ash); }
.tag--found { color: var(--verdigris); }
.tag--missing { color: var(--bone); background: var(--oxblood);
                border-color: var(--oxblood); }

/* ==========================================================================
   CANDIDATES, SHELF, CAMERA, PAYWALL
   ========================================================================== */

.candidates { list-style: none; margin: 0; padding: 0; }
.candidate { margin: 0 0 .5rem; }
.candidate button {
  display: block; width: 100%; text-align: left;
  min-height: var(--tap);
  padding: .9rem 1rem;
  background: var(--bench);
  border: 1px solid var(--oxide);
  border-left: 2px solid var(--oxide);
  border-radius: var(--radius);
  color: var(--bone); font-family: var(--sans); font-size: 1rem;
  cursor: pointer;
}
.candidate button:hover { border-left-color: var(--brass); }
.candidate .cand__name { font-weight: 700; display: block; }
.candidate .cand__meta { display: block; color: var(--ash);
                         font-size: .8125rem; margin-top: .2rem; }
.candidate .cand__score { font-family: var(--mono); font-size: .7rem;
                          color: var(--ash); }
/* A39. SMALL and honest: a note beside the card, not a warning banner. The
   printing may well be real - our lane has it and the reference database
   does not - and shouting would tell the reader something we do not know. */
.candidate .cand__flag { display: block; margin-top: .3rem;
                         font-family: var(--mono); font-size: .65rem;
                         letter-spacing: .04em; color: var(--brass); }

/* Fix 2B item 6. The other lanes a card is printed in, said on the candidate
   row where it can still change which card a person taps. ASH and small: it
   is context for the choice, not a claim about the card. No figure appears
   here and none ever may - see Candidate.also_printed_in. */
.candidate .cand__langs, .cand__langs {
  display: block; margin-top: .3rem;
  font-family: var(--mono); font-size: .65rem;
  letter-spacing: .04em; color: var(--ash);
}

.ambiguous { border-left: 2px solid var(--brass); }

/* ==========================================================================
   A.10 - THE PHOTO CANDIDATE SCREEN
   ========================================================================== */

/* WHAT WE READ. Deliberately plain and deliberately ABOVE the candidates:
   it is the evidence for them, and evidence printed below a conclusion is
   decoration. */
.ocr-read { margin-bottom: 1rem; }
.ocr-read__nums, .ocr-read__toks { margin: .5rem 0 0; }
.ocr-read__raw { margin-top: .75rem; }
.ocr-read__raw pre {
  white-space: pre-wrap; word-break: break-word;
  margin: .5rem 0 0; padding: .5rem;
  background: var(--bench); border: 1px solid var(--oxide);
  border-radius: var(--radius); color: var(--ash);
  max-height: 14rem; overflow: auto;
}

/* One token, as read. Monospace because these are machine output and should
   not be dressed up as prose the user wrote. */
.tok {
  display: inline-block;
  margin: .2rem .3rem 0 0;
  padding: .15rem .4rem;
  font-size: .75rem;
  background: var(--bench);
  border: 1px solid var(--oxide);
  border-radius: 2px;
  color: var(--bone);
}
/* The collector number is the strongest thing we read, so it is set apart
   from the word chips - but NOT in brass. Brass marks what you are meant to
   act on, and a token is evidence, not a control. A heavier border in the
   primary text colour carries the emphasis without borrowing the one signal
   this palette reserves. */
.tok--num { border-color: var(--bone); font-weight: 700; }

/* The strong path gets the brass edge the site uses for "this one matters".
   The weak path gets nothing - it is not a lesser version of a match, it is
   a different and worse kind of evidence, and the page says so in words
   above the list rather than relying on a colour to carry it. */
.candidate--strong button { border-left-color: var(--brass); }

.candidate .cand__why {
  display: block; margin-top: .35rem;
  font-size: .75rem; color: var(--ash);
}

/* NONE OF THESE. Full width, same weight as the candidate buttons above it.
   A recognition flow that makes disagreeing harder than agreeing will be
   agreed with when it is wrong. */
.none-of-these { margin-top: 1rem; }

/* SIBLING PRINTINGS. Two columns, language then figure, in the order the
   engine handed them over - which is language order, never price order. A
   price-sorted family would rank its members, and a ranking is a view on
   which one to own. Mono on the figures so the column lines up. */
/* Fix 3. GUIDE versus SOLD. A WORD, never a colour alone - it has to survive
   a screenshot, a colour-blind reader, the command line and the sample
   sheet, and this site already tells its two verdict faces apart by their
   words before their ink. Both marks are the same size and the same weight:
   neither is an alarm, and a guide is not a downgrade of a sale. ASH on
   both, which clears the body bar on either ground. */
.mark {
  font-family: var(--mono); font-size: .625rem;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ash); vertical-align: .12em;
  border: 1px solid currentColor; border-radius: var(--radius);
  padding: .05rem .3rem; margin-left: .4rem;
}
.mark--sold { border-style: solid; }
/* The guide's border is dashed - the SECOND signal, after the word. A
   modelled figure is drawn with a line that is not quite solid, which is
   the same idea in a different channel and still not a colour. */
.mark--guide { border-style: dashed; }

.siblings { display: grid; grid-template-columns: auto 1fr; gap: .3rem .9rem;
            margin: .75rem 0; }
.siblings dt { color: var(--ash); font-size: .875rem; }
.siblings dd { margin: 0; font-family: var(--mono); font-size: .875rem; }

.shelf { list-style: none; margin: 0; padding: 0; }
.shelf-row {
  display: flex; gap: .75rem; align-items: flex-start;
  padding: 1rem 0; border-bottom: 1px solid var(--oxide);
}
.shelf-row__face {
  flex: 0 0 auto; width: 5rem;
  font-family: var(--mono); font-size: .6875rem; letter-spacing: .06em;
  text-transform: uppercase; padding-top: .2rem;
}
.shelf-row__face.is-invest { color: var(--verdigris); }
.shelf-row__face.is-reject { color: var(--oxblood); }
.shelf-row__body { flex: 1 1 auto; min-width: 0; }
.shelf-row__name { font-weight: 700; }
.shelf-row__meta { color: var(--ash); font-size: .8125rem; font-family: var(--mono); }
.shelf-row__why { font-size: .875rem; margin-top: .3rem; }

.tally { display: flex; gap: 1.5rem; justify-content: center; margin-bottom: 1.25rem; }
.tally div { text-align: center; }
.tally .tally__n { font-family: var(--mono); font-size: 1.5rem;
                   color: var(--bone); display: block; }

.viewfinder {
  width: 100%; aspect-ratio: 3 / 4; background: #000;
  border: 1px solid var(--oxide); border-radius: var(--radius);
  object-fit: cover; display: block;
}
.shutter { margin-top: 1rem; min-height: 4.5rem; font-size: 1.125rem; }
[hidden] { display: none !important; }

.price { font-family: var(--mono); font-size: 2rem; color: var(--brass);
         text-align: center; margin: .5rem 0; }
.pitch { list-style: none; padding: 0; margin: 1rem 0; }
.pitch li { padding: .5rem 0 .5rem 1.25rem; position: relative;
            max-width: var(--measure); }
.pitch li::before { content: "\2014"; position: absolute; left: 0;
                    color: var(--brass); }

.meter {
  display: flex; justify-content: space-between; align-items: center;
  gap: .75rem; font-family: var(--mono); font-size: .75rem; color: var(--ash);
  padding: .7rem .85rem; border: 1px solid var(--oxide);
  border-radius: var(--radius); margin-bottom: 1.25rem;
}
.meter__n { color: var(--bone); }

.notice {
  border: 1px solid var(--oxide);
  border-left: 2px solid var(--brass);
  background: var(--bench);
  border-radius: var(--radius);
  padding: .85rem 1rem; margin: 0 0 1.25rem;
  font-size: .875rem; color: var(--ash);
}
.notice p { max-width: none; }
.notice strong { color: var(--bone); }
.error { border-left-color: var(--oxblood); }
.error strong { color: var(--bone); }

/* A27 - what we do not do */
.nots { list-style: none; padding: 0; margin: 1rem 0 0; }
.nots li { padding: .45rem 0 .45rem 1.25rem; position: relative;
           color: var(--ash); font-size: .9375rem; max-width: var(--measure); }
.nots li::before { content: "\00d7"; position: absolute; left: .1rem;
                   color: var(--oxblood); font-weight: 700; }
.nots li.is-do::before { content: "\2014"; color: var(--verdigris); }
.nots li.is-do { color: var(--bone); }

.foot {
  margin-top: 2.5rem; padding-top: 1.25rem;
  border-top: 1px solid var(--oxide);
  color: var(--ash); font-size: .75rem; text-align: center;
}
.foot p { max-width: none; }
.foot__house { font-family: var(--mono); letter-spacing: .1em;
               text-transform: uppercase; margin-top: .75rem; }

/* ==========================================================================
   THE ONE BREAKPOINT
   ========================================================================== */

@media (min-width: 40rem) {
  :root { --maxw: 44rem; }
  .stamp--invest { font-size: clamp(1.8rem, 4vw, 2.8rem); }
  .stamp--reject { font-size: clamp(2.6rem, 6vw, 4rem); }
  .row .btn { padding-inline: 1.5rem; }
}

/* A22 - mobile: the hero stamp scales to 88vw and the one control becomes a
   full-width bar in the bottom safe area, so the camera is a thumb away. */
@media (max-width: 39.999rem) {
  .hero .stamp--awaiting { font-size: 13vw; padding: 1.1rem 1.4rem; }
  .hero { min-height: 62vh; display: flex; flex-direction: column;
          justify-content: center; }
  .hero .stamp-stage { width: 88vw; margin: 0 auto; }
  .rank-bar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
    padding: .75rem var(--pad) calc(.75rem + env(safe-area-inset-bottom, 0px));
    background: var(--ink);
    border-top: 1px solid var(--oxide);
  }
  .rank-bar .rank-caption { margin-top: .5rem; }
  body.has-rank-bar { padding-bottom: 10rem; }
  .data-pair, .projections { grid-template-columns: 1fr; }
}

/* ==========================================================================
   REDUCED MOTION - the strike does not play. Nothing else moves anyway.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .stamp { animation: none; }
  * { animation: none !important; }
}

@media print {
  body { background: #fff; color: #000; }
  .nav, .btn, .foot, .rank-bar { display: none; }
  .stamp { mix-blend-mode: normal; opacity: 1; animation: none; }
}
