
  /* Self-hosted brand faces, served same-origin under /static/fonts
     (the CSP has no font-src, so it inherits default-src 'self'). */
  @font-face { font-family: "Inter"; font-style: normal; font-weight: 100 900;
    font-display: swap; src: url("/static/fonts/Inter.woff2") format("woff2"); }
  @font-face { font-family: "JetBrains Mono"; font-style: normal;
    font-weight: 100 800; font-display: swap;
    src: url("/static/fonts/JetBrainsMono.woff2") format("woff2"); }

  /* Design tokens — same names + values as the main site stylesheet;
     this block is inlined so vars work without an external stylesheet. */
  :root {
    --ink: #1a1a1a;
    --ink-soft: #2a2a2a;
    --muted: #5a5a5a;
    --muted-soft: #6b6b6b;
    --line: #e6e6e6;
    --line-soft: #efece7;
    --bg: #ffffff;
    --bg-warm: #fbf8f3;
    --bg-soft: #f7f5f0;
    --accent: #1565c0;
    --accent-strong: #1976d2;
    --tint: #e3f2fd;
    --tint-line: #64b5f6;
    --ok: #176f30;
    --sans: "Inter", -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;
    --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace;
    --serif: var(--sans);   /* serif retired — match apex (every old serif → sans) */
    /* Content-width scale — matches the main site. */
    --prose-w: 760px;
    --content-w: 1040px;
  }

  body { font-family: var(--sans); max-width: var(--content-w, 1040px);
         margin: 2em auto; padding: 0 1em; color: #222; line-height: 1.55; }
  h1, h2, h3 {
    font-family: var(--sans);
    font-weight: 600;
    letter-spacing: -0.015em;
    color: var(--ink);
  }
  h1 { font-size: 1.95em; line-height: 1.15; margin-bottom: 0.15em; }
  h2 { font-size: 1.35em; line-height: 1.2; margin-top: 1.8em; }
  h3 { font-size: 1.05em; margin-top: 1.2em; }
  .sub { color: var(--muted); margin-top: 0.4em; font-size: 1.05em; }
  label { display: block; margin: 1em 0 0.2em; font-weight: 600; }
  input[type=text], input[type=number],
  input[type=file]:not(.visually-hidden), textarea {
    width: 100%; box-sizing: border-box; padding: 0.5em;
    border: 1px solid #bbb; border-radius: 4px; font-size: 1em; font-family: inherit;
  }
  textarea { font-family: ui-monospace, SFMono-Regular, monospace; font-size: 0.9em; }
  button { margin-top: 1.5em; padding: 0.7em 1.4em; font-size: 1em;
           background: var(--accent-strong); color: #fff; border: 0; border-radius: 4px;
           cursor: pointer; font-weight: 600; }
  button:disabled { background: #999; cursor: not-allowed; }
  code { background: #f3f3f3; padding: 0 0.3em; border-radius: 3px;
         font-family: SFMono-Regular, ui-monospace, monospace; font-size: 0.9em;
         word-break: break-all; }
  pre { background: #f5f5f5; padding: 1em; border-radius: 4px;
        overflow-x: auto; font-size: 0.85em; line-height: 1.4; }
  .banner { background: #fff8e1; padding: 0.8em 1em; border-radius: 4px;
            border: 1px solid #ffd54f; margin: 1em 0; }
  .ok { background: #e8f5e9; border-color: #81c784; }
  .err { background: #ffebee; border-color: #e57373; }
  /* Stronger warning style for product-critical constraints (e.g.,
     "lose this bundle and the proof is unverifiable"). Heavier border
     + amber tint + ! glyph in the headline. Keeps the same layout as
     .banner so existing markup just adds .banner-warn. */
  .banner.banner-warn {
    background: #fff5e6; border: 2px solid #f0a000;
    padding: 0.95em 1.1em;
  }
  .banner.banner-warn b:first-child::before {
    content: "\26A0\fe0f  ";
    margin-right: 0.1em;
  }
  /* Access-gate banner: informational gating, not a warning. Uses the
     blue/info palette so yellow stays reserved for genuine warnings
     (dry-run mode, "lose this bundle and the proof breaks", etc.) and
     doesn't visually compete when both fire on the same page. */
  .banner.banner-access {
    display: flex; flex-wrap: wrap; align-items: center; gap: 0.8em 1.2em;
    background: var(--tint); border: 1px solid var(--tint-line); padding: 1em 1.2em;
  }
  /* Class selectors (0,2,0) outrank UA `[hidden]{display:none}` (0,1,0),
     so without this, hidden banners stay visible — fixed here for both
     signin-notice/chip and any future banner that uses banner-access. */
  .banner.banner-access[hidden] { display: none; }
  .banner.banner-access .ba-text { flex: 1 1 240px; }
  .banner.banner-access .ba-action {
    display: flex; flex-direction: column; gap: 0.25em;
    align-items: flex-end;
  }
  .banner.banner-access .btn-request {
    display: inline-block; padding: 0.6em 1.1em;
    background: var(--accent-strong); color: #fff; text-decoration: none;
    border-radius: 4px; font-size: 0.95em; font-weight: 600;
    white-space: nowrap;
  }
  .banner.banner-access .btn-request:hover { background: var(--accent); }
  .banner.banner-access .ba-meta {
    color: var(--muted); font-size: 0.82em;
  }
  .privacy { background: var(--tint); border: 1px solid var(--tint-line);
             padding: 0.7em 1em; border-radius: 4px; margin: 1em 0;
             font-size: 0.95em; }
  /* Batch C (Proof #3, cosmetic): elevate the privacy reassurance so
     it reads as a prominent promise, not small inline bold; and a
     quiet "no account until you anchor" hint at the anchor step. The
     sign-in modal already fires only on the anchor click (server 401
     -> satsignalOpenSignin); these are copy/visual changes only. */
  #privacy-headline { display: block; font-size: 1.06em;
    color: var(--ok); margin-bottom: 0.25em; letter-spacing: 0.005em; }
  .anchor-signin-hint { margin: 0 0 0.6em; }
  .hash-readout { font-family: ui-monospace, monospace; font-size: 0.85em;
                  word-break: break-all; background: #f5f5f5; padding: 0.6em;
                  border-radius: 4px; margin-top: 0.5em; min-height: 1.2em; }
  .hash-readout.computing { color: var(--muted-soft); font-style: italic; }
  .hash-readout.done { color: var(--ok); }
  .meta { color: var(--muted); font-size: 0.9em; }
  a { color: var(--accent); }
  details { background: #fafafa; border: 1px solid var(--line); border-radius: 5px;
            padding: 0.6em 1em; margin: 0.5em 0; }
  details[open] { background: #fff; }
  details summary { cursor: pointer; font-weight: 600; padding: 0.2em 0; }
  details summary:hover { color: var(--accent-strong); }
  .footer { color: var(--muted-soft); font-size: 0.85em; margin-top: 3em;
            border-top: 1px solid #eee; padding-top: 1em; }
  .footer a { color: var(--muted-soft); }
  /* Proof page: privacy claim under the badge pills. Replaces the
     full .privacy panel above the proof grid — same copy, less
     chrome, lifts the data block up by ~60-80px. The pills above
     already say 'Standard proof'; this paragraph elaborates without
     repeating the visual weight of a tinted box. */
  .proof-claim {
    margin: 0.6em 0 1em; color: var(--muted); font-size: 0.95em;
    line-height: 1.55; max-width: 64ch;
  }
  .proof-claim b { color: var(--ink); }

  /* Visually-hidden text for screen readers (e.g. labels on the file
     input where the visible "Choose your file" step heading isn't a
     real <label>). Standard pattern, no layout impact. */
  .visually-hidden {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0,0,0,0); white-space: nowrap; border: 0;
  }

  /* Quiet inline pointer to the public demo proof. Replaces the
     full rich demo card on the proof landing so the form rises closer
     to the fold. Visually subdued — single line of muted text with
     one accent link. */
  .demo-strip {
    margin: 1.2em 0 0.4em;
    padding: 0.6em 0.9em;
    background: #fafafa;
    border-left: 2px solid var(--accent);
    color: var(--muted); font-size: 0.93em; line-height: 1.5;
    border-radius: 0 4px 4px 0;
  }
  .demo-strip b { color: var(--ink); }
  .demo-strip a { color: var(--accent); text-decoration: none;
                  border-bottom: 1px solid rgba(21,101,192,0.3); }
  .demo-strip a:hover { border-bottom-color: var(--accent); }

  /* Trust bullets directly below the upload form — three short
     reassurances so the user can act first and read the technical
     case below. Visually subdued; not a primary block. */
  .trust-bullets {
    list-style: none; padding: 0;
    margin: 1em 0 0.4em;
    display: flex; flex-direction: column; gap: 0.3em;
    color: var(--muted); font-size: 0.92em;
  }
  .trust-bullets li::before {
    content: "\2713\00a0\00a0";
    color: var(--ok);
  }

  /* "What you get" follows the access-gated note. Plain list under an
     h2 — same weight as Privacy & Trust further down. */
  .what-you-get { margin-top: 1.6em; }
  .what-you-get ul {
    margin: 0.5em 0 0; padding-left: 1.3em;
    color: var(--ink-soft);
  }
  .what-you-get li { margin: 0.25em 0; }

  /* Editorial hero kicker matching the apex landing's .hero-mark — a
     small accent rule + label that anchors the H1 visually so the
     proof + sealed pages feel like the same brand as the apex. */
  .hero-mark {
    display: flex; align-items: center; gap: 0.7em;
    margin: 0 0 0.9em; color: var(--accent);
  }
  .hero-mark .rule {
    width: 32px; height: 2px;
    background: var(--accent); border-radius: 2px;
  }
  .hero-mark .label {
    font-family: -apple-system, system-ui, sans-serif;
    font-size: 0.78em; font-weight: 700;
    letter-spacing: 0.16em; text-transform: uppercase;
    color: var(--muted-soft);
  }

  .proof-grid { display: grid; grid-template-columns: max-content 1fr;
                  gap: 0.4em 1em; margin: 1em 0; }
  .proof-grid dt { font-weight: 600; color: var(--muted); }
  .proof-grid dd { margin: 0; word-break: break-all; }
  .proof-grid dd .meta { word-break: normal; }
  /* Mobile: stack each label above its value so long hex/txid values
     don't crush the dd column to ~50% of the viewport, and parenthetical
     captions get their own line below the code. */
  @media (max-width: 600px) {
    .proof-grid { grid-template-columns: 1fr; gap: 0.15em 0; }
    .proof-grid dt { margin-top: 0.85em; }
    .proof-grid dt:first-of-type { margin-top: 0; }
    .proof-grid dd .meta { display: block; margin-top: 0.25em; }
  }
  .button-row { display: flex; gap: 0.6em; margin-top: 1em; flex-wrap: wrap; }
  .button-row a, .button-row button { display: inline-block; padding: 0.55em 1em;
                  background: var(--accent-strong); color: #fff; text-decoration: none;
                  border-radius: 4px; font-size: 0.95em;
                  border: 0; cursor: pointer; font-family: inherit; }
  .button-row a.secondary, .button-row button.secondary { background: #fff;
                            color: var(--accent-strong); border: 1px solid var(--accent-strong); }
  .button-row button:disabled { opacity: 0.6; cursor: default; }

  /* Proof-page primary CTA + collapsed-disclosure for power-user actions. */
  .action-primary { margin: 1.4em 0 0.3em; }
  .primary-cta {
    display: inline-block; padding: 0.85em 1.6em;
    background: var(--accent-strong); color: #fff; border: 0;
    border-radius: 6px; font-size: 1.05em; font-weight: 600;
    cursor: pointer; font-family: inherit; text-decoration: none;
  }
  .primary-cta:disabled { opacity: 0.6; cursor: default; }
  .primary-cta-sub { margin: 0.55em 0 0; color: var(--muted); font-size: 0.92em; }
  .share-row {
    display: flex; align-items: center; gap: 0.85em;
    flex-wrap: wrap;
    margin: 1em 0 0.4em;
    padding: 0.85em 1em;
    background: #f6f9fc;
    border: 1px solid #d6e3f0;
    border-radius: 6px;
  }
  .share-btn {
    display: inline-block; padding: 0.5em 1.05em;
    background: #fff; color: var(--accent-strong);
    border: 1px solid var(--accent-strong); border-radius: 4px;
    font-size: 0.95em; font-weight: 600;
    cursor: pointer; font-family: inherit;
    flex-shrink: 0;
  }
  .share-btn:hover { background: var(--accent-strong); color: #fff; }
  .share-btn.copied { background: #1f7a3a; border-color: #1f7a3a; color: #fff; }
  .share-row-hint {
    color: var(--muted); font-size: 0.9em;
    line-height: 1.45; flex: 1; min-width: 14em;
  }
  .action-disclosure { margin: 1.2em 0 0.6em;
                       border-top: 1px solid #eee; padding-top: 0.9em; }
  .action-disclosure summary {
    cursor: pointer; color: var(--accent); font-weight: 600;
    padding: 0.2em 0; user-select: none; font-size: 0.95em;
    list-style: none;
  }
  .action-disclosure summary::-webkit-details-marker { display: none; }
  .action-disclosure summary::before {
    content: "▸ "; display: inline-block; transition: transform 0.15s;
    margin-right: 0.2em;
  }
  .action-disclosure[open] summary::before { transform: rotate(90deg); }
  .action-disclosure[open] summary { margin-bottom: 0.7em; }
  .action-row { display: flex; gap: 0.55em; flex-wrap: wrap; }
  .action-row a, .action-row button {
    display: inline-block; padding: 0.45em 0.9em;
    background: #fff; color: var(--accent);
    border: 1px solid var(--accent); border-radius: 4px;
    font-size: 0.9em; font-weight: 500;
    text-decoration: none; cursor: pointer; font-family: inherit;
  }
  .action-followup { margin: 0.6em 0 1.5em; font-size: 0.95em; }
  .action-followup a { color: var(--accent); }

  /* Manual verify recipe — folded under details so it doesn't dominate
     the page below the fold. Most users will click /verify; the wall of
     jq + sha256sum commands is a power-user artifact. */
  .manual-verify { margin: 1.4em 0; }
  .manual-verify summary {
    cursor: pointer; font-weight: 600; padding: 0.5em 0;
    user-select: none; font-size: 1em;
  }
  .manual-verify[open] summary { margin-bottom: 0.5em; }
  .demo-card { background: #f1f8e9; border: 1px solid #aed581;
               padding: 0.9em 1.1em; border-radius: 6px; margin: 1.2em 0; }
  .demo-card .meta { color: var(--muted); }

  .demo-preview {
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 1.5em 1.4em 1.25em;
    margin: 1.4em 0 2em;
    box-shadow: 0 1px 0 rgba(20, 20, 20, 0.02),
                0 12px 32px -16px rgba(20, 20, 20, 0.12);
    position: relative;
  }
  .demo-preview-tab {
    position: absolute;
    top: -0.7em; left: 1.2em;
    background: #fff;
    padding: 0 0.55em;
    font-size: 0.74em;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted-soft);
  }
  .demo-preview h3 {
    font-size: 1.15em; margin: 0.3em 0 0.1em;
  }
  .demo-preview .proof-grid { font-size: 0.93em; margin: 0.6em 0 0.9em; }
  .demo-preview .proof-grid dd a { text-decoration: none;
    border-bottom: 1px solid rgba(21, 101, 192, 0.25); }
  .demo-preview .proof-grid dd a:hover { border-bottom-color: var(--accent); }

  .badges { display: flex; flex-wrap: wrap; gap: 0.5em;
            margin: 0.8em 0 0.5em; }
  .badges .pill {
    display: inline-flex; align-items: center; gap: 0.35em;
    padding: 0.3em 0.7em; border-radius: 999px;
    font-size: 0.85em; font-weight: 600;
    background: #e6f4ea; color: var(--ok);
    border: 1px solid #b8dcc1;
  }
  .badges .pill.warn { background: #fff7d6; color: #9a6700;
                       border-color: #f0d674; }
  /* Phase 8a: descriptive metadata pill for proof category. Tinted
     orange so it reads as an attribute (kind-of-thing) rather than a
     verification status. */
  .badges .pill.cat { background: #fdf2e0; color: #8a4f0d;
                      border-color: #f3d1a4; }
  .badges .pill::before { content: "\2713"; }
  .badges .pill.warn::before { content: "\21\fe0e"; }
  .badges .pill.cat::before { content: "\1F3F7\fe0f"; }  /* 🏷️ */

  .copy-btn {
    display: inline-block; padding: 0.55em 1em;
    background: #fff; color: var(--accent, var(--accent));
    border: 1px solid var(--accent, var(--accent)); border-radius: 4px;
    font-size: 0.95em; font-weight: 600; cursor: pointer;
    text-decoration: none;
  }
  .copy-btn:hover { background: var(--tint); }
  .copy-btn.copied { background: #e6f4ea; color: var(--ok);
                     border-color: #b8dcc1; }

  .verify-tldr { background: var(--tint); border: 1px solid var(--tint-line);
                 padding: 0.8em 1.1em; border-radius: 4px;
                 margin: 1em 0; font-size: 0.95em; }

  /* Sealed-mode lifecycle diagram. Four equal cards in a flex row with
     arrows between them; stacks vertically on narrow viewports with the
     arrows rotated 90 degrees. Used on the sealed-mode landing page to
     give the Hermes-requested visual companion to the textual flow. */
  .sealed-flow {
    display: flex; align-items: stretch; gap: 0.5em;
    margin: 1.5em 0; flex-wrap: wrap;
  }
  .sealed-flow-step {
    flex: 1 1 11em;
    background: #fafafa; border: 1px solid var(--line);
    border-radius: 6px; padding: 0.9em 1em;
  }
  .sealed-flow-stage {
    font-size: 0.72em; font-weight: 700; color: var(--accent);
    letter-spacing: 0.08em; text-transform: uppercase;
    margin-bottom: 0.35em;
  }
  .sealed-flow-title {
    font-weight: 700; color: var(--ink); font-size: 1em;
    margin-bottom: 0.3em;
  }
  .sealed-flow-body { font-size: 0.88em; color: var(--muted); line-height: 1.45; }
  .sealed-flow-arrow {
    display: flex; align-items: center;
    /* Was #aaa → 2.32:1 on white, deep WCAG AA fail. var(--muted-soft)
       (#6b6b6b) reaches 5.25:1 while staying visually lighter than
       the active step copy. Arrow is aria-hidden=true (decorative)
       but visual contrast still applies. */
    font-size: 1.4em; color: var(--muted-soft);
    flex: 0 0 auto; padding: 0 0.1em;
  }
  @media (max-width: 640px) {
    .sealed-flow { flex-direction: column; }
    .sealed-flow-step { flex: 1 1 auto; }
    .sealed-flow-arrow { transform: rotate(90deg); align-self: center;
                         padding: 0.2em 0; }
  }

  /* Public-vs-Sealed comparison table. Highlighted column = the host
     the user is currently on. Rows wrap on narrow viewports via the
     wrapper's overflow-x. */
  .compare-wrap { overflow-x: auto; margin: 1em 0 1.5em; }
  .compare { width: 100%; border-collapse: collapse;
             font-size: 0.95em; }
  .compare th, .compare td {
    padding: 0.7em 0.9em; text-align: left;
    vertical-align: top;
    border-bottom: 1px solid #ececec;
  }
  .compare thead th { font-weight: 700; font-size: 1em;
                      border-bottom: 2px solid #ddd; }
  .compare tbody th {
    font-weight: 600; color: var(--muted); width: 18%;
    background: #fafafa;
  }
  .compare .compare-link {
    font-weight: normal; font-size: 0.85em;
    color: var(--accent); text-decoration: none;
  }
  .compare .compare-link:hover { text-decoration: underline; }
  .compare .compare-pill {
    font-size: 0.7em; font-weight: 600;
    color: var(--accent-strong); letter-spacing: 0.04em;
    text-transform: uppercase;
  }
  .compare .compare-current { background: var(--tint); }
  .compare thead th.compare-current {
    background: var(--accent-strong); color: #fff;
    border-bottom-color: var(--accent-strong);
  }
  .compare thead th.compare-current .compare-link,
  .compare thead th.compare-current .compare-pill { color: #fff; }

  /* Mobile: stack columns vertically — each row becomes a row label
     plus two labeled blocks. Avoids hiding the Sealed column off the
     right edge of the viewport on narrow screens. */
  @media (max-width: 640px) {
    .compare, .compare thead, .compare tbody, .compare tr,
    .compare th, .compare td { display: block; width: auto; }
    .compare thead { display: none; }
    .compare tbody tr {
      border: 1px solid #ececec; border-radius: 8px;
      padding: 0.4em 0.9em 0.9em; margin: 0.9em 0;
      background: #fff;
    }
    .compare tbody th[scope=row] {
      width: auto; background: transparent;
      color: var(--ink); font-size: 1em; font-weight: 700;
      padding: 0.5em 0 0.4em; border: 0;
    }
    .compare tbody td {
      padding: 0.55em 0 0.55em 0.9em;
      border: 0; border-left: 3px solid #e3e3e3;
    }
    .compare tbody td:nth-of-type(1)::before,
    .compare tbody td:nth-of-type(2)::before {
      display: block; font-size: 0.72em; font-weight: 700;
      letter-spacing: 0.08em; text-transform: uppercase;
      margin-bottom: 0.25em;
    }
    .compare tbody td:nth-of-type(1)::before {
      content: "Standard"; color: var(--accent);
    }
    .compare tbody td:nth-of-type(2)::before {
      content: "Sealed"; color: var(--accent-strong);
    }
    .compare tbody td.compare-current { background: var(--tint); }
    .compare tbody td.compare-current:nth-of-type(1) { border-left-color: var(--accent); }
    .compare tbody td.compare-current:nth-of-type(2) { border-left-color: var(--accent-strong); }
  }

  /* Two-step form layout: file pick first, metadata + anchor second.
     Step 1 (file) and step 2 (details/retention) sit side by side on
     desktop via `.anchor-cols`; the anchor button + progress are a
     full-width row beneath (`.anchor-footer`). Step 2 is rendered but
     `step--locked` (dimmed, non-interactive) until a file is picked —
     JS removes the class. Single column below the breakpoint. */
  .step { padding-top: 1.4em; margin-top: 1.4em;
          border-top: 1px solid #ececec; }
  .step:first-of-type { border-top: 0; padding-top: 0; margin-top: 0; }
  .anchor-cols { display: grid; grid-template-columns: 1fr; }
  .step--locked { opacity: 0.5; pointer-events: none; user-select: none;
                  transition: opacity 0.18s ease; }
  .step--locked .step-num { background: var(--muted); }
  .anchor-footer { margin-top: 1.4em; padding-top: 1.4em;
                   border-top: 1px solid #ececec; }
  @media (min-width: 880px) {
    .anchor-cols { grid-template-columns: 1fr 1fr; column-gap: 2.4em;
                   align-items: start; }
    .anchor-cols .step,
    .anchor-cols .step:first-of-type { border-top: 0; padding-top: 0;
                                       margin-top: 0; }
  }
  .step-label {
    display: inline-flex; align-items: center; gap: 0.55em;
    font-weight: 600; color: var(--muted); font-size: 0.85em;
    margin-bottom: 0.7em; text-transform: uppercase;
    letter-spacing: 0.07em;
  }
  .step-num {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.6em; height: 1.6em; border-radius: 50%;
    background: var(--accent-strong); color: #fff;
    font-size: 0.85em; font-weight: 700; letter-spacing: 0;
  }

  .progress { margin: 1em 0 0.5em; padding: 0; list-style: none; }
  /* Pending state copy: was #999 on white → 2.85:1, deep WCAG AA fail
     once the form expands to show the progress list. var(--muted)
     (#5a5a5a) lifts to 7.04:1 while still reading as quieter than
     the active (--accent-strong) and done (--ok) states. */
  .progress li { display: flex; align-items: center; gap: 0.6em;
                 padding: 0.35em 0; color: var(--muted); font-size: 0.95em; }
  .progress li .dot {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.4em; height: 1.4em; border-radius: 50%;
    background: #eee; color: var(--muted); font-size: 0.85em; font-weight: 600;
    flex-shrink: 0;
  }
  .progress li.active { color: var(--accent-strong); font-weight: 600; }
  .progress li.active .dot { background: var(--accent-strong); color: #fff; }
  .progress li.done { color: var(--ok, var(--ok)); }
  .progress li.done .dot { background: var(--ok, var(--ok)); color: #fff; }
  .progress li.done .dot::before { content: "✓"; }
  .progress li.active .dot::before { content: "•"; }
  .progress li.pending .dot::before { content: ""; }
  .retention { background: #fafafa; border: 1px solid #e0e0e0;
               padding: 0.7em 1em; border-radius: 5px;
               font-size: 0.9em; margin-top: 1.2em; color: var(--muted); }

  /* Upload card — visually-dominant file picker. Replaces the native
     <input type=file> chrome with a designed surface so the primary
     action feels like product, not a browser form field. The native
     input stays in the DOM (visually-hidden) so form submission and
     keyboard a11y still work; click + drop are wired in JS to call
     fileInput.click() and set fileInput.files. */
  .upload-card {
    display: block; box-sizing: border-box;
    border: 2px dashed var(--line); border-radius: 10px;
    background: #fafafa;
    padding: 2.2em 1.4em; margin: 0.4em 0 0.6em;
    text-align: center; cursor: pointer;
    transition: border-color .12s ease, background .12s ease;
  }
  .upload-card:hover, .upload-card:focus-within {
    border-color: var(--accent); background: #f3f7ff;
  }
  .upload-card.dragover {
    border-color: var(--accent-strong); background: #eaf1ff;
  }
  .upload-card-prompt-title {
    font-size: 1.15em; font-weight: 600; color: var(--ink);
    margin-bottom: 0.45em;
  }
  .upload-card-prompt-or {
    color: var(--muted); font-size: 0.85em;
    margin: 0.45em 0;
  }
  .upload-card-cta {
    display: inline-block; padding: 0.55em 1.4em;
    background: var(--accent-strong); color: #fff;
    border-radius: 5px; font-weight: 600; font-size: 0.95em;
  }
  .upload-card:hover .upload-card-cta { filter: brightness(0.95); }
  .upload-card-meta {
    color: var(--muted); font-size: 0.85em;
    margin-top: 1em; line-height: 1.4;
  }
  .upload-card-selected {
    text-align: left;
  }
  .upload-card-selected-label {
    font-size: 0.78em; font-weight: 600; color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.07em;
    margin-bottom: 0.35em;
  }
  .upload-card-selected-name {
    font-family: ui-monospace, monospace; font-size: 1em;
    color: var(--ink); word-break: break-all;
  }
  .upload-card-selected-size {
    color: var(--muted); font-size: 0.88em; margin-top: 0.2em;
  }
  .upload-card-clear {
    display: inline-block; margin-top: 0.9em;
    background: transparent; border: 0;
    color: var(--accent); font-size: 0.88em;
    padding: 0; cursor: pointer; text-decoration: underline;
  }
  .upload-card-clear:hover { color: var(--accent-strong); }

  /* Styled picker for the opt-in "include the original file" item
     (_include_original_details_html[_sealed]). The native
     <input type=file> is visually-hidden but kept in the DOM with its
     load-bearing id/name so the verify/proof runtime change-handler
     still binds; a styled <label> drives it and a span echoes the
     chosen filename. */
  .include-original-pick {
    display: inline-block; padding: 0.45em 1.1em;
    background: var(--accent-strong); color: #fff;
    border-radius: 5px; font-weight: 600; font-size: 0.9em;
    cursor: pointer;
  }
  .include-original-pick:hover { filter: brightness(0.95); }
  .include-original-filename {
    display: inline-block; margin-left: 0.7em;
    font-family: ui-monospace, monospace; font-size: 0.88em;
    color: var(--muted); word-break: break-all;
  }

  @media print {
    body { max-width: none; margin: 0; padding: 1em; color: #000; }
    .no-print { display: none !important; }
    a { color: #000; text-decoration: underline; }
    pre, code { background: #fff; border: 1px solid #ccc; }
    .privacy, .banner, .demo-card, .retention { border: 1px solid var(--muted-soft); background: #fff; }
    h1 { border-bottom: 1px solid #000; padding-bottom: 0.3em; }
  }

  /* ============================================================
     notary-dark v1 — dark skin for the notary pages. Tokens
     mirror the apex dark system.
     ============================================================ */
  :root {
    --ink: #e9edf3;  --ink-soft: #d3d9e2;
    --muted: #a6b0bd; --muted-soft: #8a94a2;
    --line: #232b35;  --line-soft: #232b35;
    --bg: #060709;    --bg-warm: #0e1117;  --bg-soft: #0e1117;
    --accent: #3aa0ff; --accent-strong: #3aa0ff;
    --tint: #0f1d2b;  --tint-line: #15324b;
    --ok: #46d08a;
    --line-strong: #38434f;
    --surface-1: #0e1117; --surface-2: #141a22; --surface-3: #1b222c;
    --inset: #08090c;
    --pending: #f2b45a; --bad: #ff6a6a;
    /* Batch 0 — semantic state tokens (Batch C prep; additive,
       nothing consumes them yet so zero render change). */
    --verified: var(--ok); --sealed: #a78bfa;
    --limitation: var(--pending); --inactive: var(--muted);
    --anchor: var(--accent);
  }

  html, body { background: var(--bg); color: var(--ink-soft); }
  body { color: var(--ink-soft); }
  h1, h2, h3 { color: var(--ink); }

  input[type=text], input[type=number],
  input[type=file]:not(.visually-hidden), textarea {
    background: var(--inset); color: var(--ink); border-color: var(--line);
  }
  button:disabled { background: var(--surface-3); color: var(--muted); }
  code { background: var(--surface-3); color: var(--ink); }
  pre  { background: var(--inset); color: var(--ink-soft);
         border: 1px solid var(--line); }

  .banner            { background: rgba(242,180,90,.09);
                       border-color: rgba(242,180,90,.42);
                       color: var(--ink-soft); }
  .banner.banner-warn{ background: rgba(242,180,90,.14);
                       border-color: #5a4a1f; }
  .ok  { background: rgba(70,208,138,.10);  border-color: #1f5a42; }
  .err { background: rgba(255,106,106,.10); border-color: #7a2f2f; }
  .banner.banner-access .btn-request { color: #04121f; }

  .hash-readout { background: var(--inset); color: var(--ink-soft); }
  details        { background: var(--surface-1); }
  details[open]  { background: var(--surface-2); }
  .footer        { border-top-color: var(--line); }
  .footer a      { color: var(--muted); }

  .button-row a, .button-row button { color: #04121f; }
  .button-row a.secondary, .button-row button.secondary {
    background: transparent; color: var(--accent);
    border-color: var(--accent); }
  .primary-cta   { color: #04121f; }
  .share-row     { background: var(--surface-1); border-color: var(--line); }
  .share-btn     { background: transparent; color: var(--accent);
                   border-color: var(--accent); }
  .share-btn:hover{ background: var(--accent); color: #04121f; }
  .share-btn.copied{ background: rgba(70,208,138,.16); color: var(--ok);
                      border-color: #1f5a42; }
  .action-disclosure { border-top-color: var(--line); }
  .action-row a, .action-row button {
    background: transparent; color: var(--accent);
    border-color: var(--accent); }
  .demo-card     { background: rgba(70,208,138,.08);
                   border-color: #1f5a42; }
  .demo-preview  { background: var(--surface-2);
                   border-color: var(--line);
                   box-shadow: 0 12px 32px -16px rgba(0,0,0,.55); }
  .demo-preview-tab { background: var(--surface-2); }

  /* Batch 0 — light-surface leftovers the notary-dark v1 pass
     missed. Verified light on live proof./sealed. (computed
     #fafafa on #060709 body, WCAG ~1.1-2.1:1). These selectors
     weren't in the override list so the #fafafa base survived;
     border/text already resolve to dark tokens, so bg only. */
  .demo-strip       { background: var(--surface-1); }
  .sealed-flow-step { background: var(--surface-2); }

  .badges .pill      { background: rgba(70,208,138,.13); color: var(--ok);
                       border-color: #1f5a42; }
  .badges .pill.warn { background: rgba(242,180,90,.16);
                       color: var(--pending); border-color: #5a4a1f; }
  .badges .pill.cat  { background: rgba(242,180,90,.10);
                       color: #e0a96a; border-color: #5a4a1f; }
  .copy-btn          { background: transparent; color: var(--accent);
                       border-color: var(--accent); }
  .copy-btn.copied   { background: rgba(70,208,138,.16); color: var(--ok);
                       border-color: #1f5a42; }

  .compare th, .compare td       { border-bottom-color: var(--line); }
  .compare thead th              { border-bottom-color: var(--line-strong); }
  .compare tbody th              { background: var(--surface-1); }
  .compare thead th.compare-current { background: var(--accent);
                                      color: #04121f; }
  @media (max-width: 640px) {
    .compare tbody tr { background: var(--surface-2);
                        border-color: var(--line); }
    .compare tbody td { border-left-color: var(--line); }
  }

  .step          { border-top-color: var(--line); }
  .anchor-footer  { border-top-color: var(--line); }
  .step-num  { color: #04121f; }
  .progress li .dot          { background: var(--surface-3);
                               color: var(--muted); }
  .progress li.active .dot   { color: #04121f; }
  .progress li.done   .dot   { color: #04121f; }
  .retention { background: var(--surface-1); border-color: var(--line);
               color: var(--muted); }

  .upload-card               { background: var(--surface-1);
                               border-color: var(--line-strong); }
  .upload-card:hover,
  .upload-card:focus-within  { background: var(--surface-2);
                               border-color: var(--accent); }
  .upload-card.dragover      { background: var(--tint);
                               border-color: var(--accent); }
  .upload-card-cta           { color: #04121f; }

  /* Match the apex .topnav. Shared dark palette (--ink/--accent/--line
     same values), so these render identically to the apex bar: translucent
     blurred bar, muted-ink links, active = ink + a signal underline (NOT
     a full-blue fill), and the account link is the single filled CTA. */
  body .topnav            { background: rgba(6,7,9,0.72);
                            border-bottom-color: rgba(255,255,255,0.06); }
  body .topnav .brand     { color: var(--ink); }
  body .topnav ul a       { color: rgba(233,237,243,0.62); font-weight: 460; }
  body .topnav ul a:hover { color: var(--ink); }
  body .topnav ul a.active{ color: var(--ink);
                            border-bottom: 2px solid var(--accent); }
  body .topnav .nav-account       { color: #04121f; background: var(--accent);
                            font-weight: 620; border-radius: 6px;
                            padding: 0.45em 0.95em; }
  body .topnav .nav-account:hover { background: #73c2ff; color: #04121f; }
  body .skip-link         { background: var(--accent); color: #04121f; }

  body .signin-modal-card { background: var(--surface-2); color: var(--ink-soft); }
  body .signin-modal-card input[type=email] { background: var(--inset);
    color: var(--ink); border-color: var(--line); }

  .proof-summary {
    margin: 0.4em 0 1.1em; padding: 0.9em 1.1em;
    background: var(--surface-1);
    border: 1px solid var(--line);
    border-left: 2px solid var(--accent);
    border-radius: 0 6px 6px 0;
    color: var(--ink-soft); font-size: 0.97em; line-height: 1.6;
    max-width: 64ch;
  }
  .proof-summary b { color: var(--ink); }
  .proof-grid dt .dt-plain {
    display: block; margin-top: 0.1em;
    font-weight: 400; font-size: 0.82em;
    color: var(--muted); letter-spacing: 0;
  }

  /* ============================================================
     Batch C — proof identity card (Proof #1/#4/#5). Promotes
     status / anchored-time / mode / label / proof-ID into one
     shareable card; the canonical limitation sentence sits under
     the status pill; raw hashes + size collapse into
     .technical-proof-details. .proof-grid itself is left
     untouched (it is also reused inside .demo-preview on the
     index page, so restyling it would have side effects).
     ============================================================ */
  .rcard {
    margin: 0.7em 0 1.3em; padding: 1.15em 1.3em 1.25em;
    background: var(--surface-2);
    border: 1px solid var(--line-strong);
    border-left: 3px solid var(--anchor);
    border-radius: 0 8px 8px 0;
    max-width: 66ch;
  }
  .rcard-status {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: 0.5em; margin-bottom: 0.7em;
  }
  .rcard-status-pill {
    display: inline-flex; align-items: center; gap: 0.4em;
    font-weight: 700; font-size: 0.97em;
    padding: 0.34em 0.85em; border-radius: 999px;
    background: rgba(70,208,138,.13); color: var(--verified);
    border: 1px solid #1f5a42; letter-spacing: 0.01em;
  }
  .rcard-status-pill::before { content: "\2713"; }
  .rcard-status-pill.warn {
    background: rgba(242,180,90,.16); color: var(--limitation);
    border-color: #5a4a1f;
  }
  .rcard-status-pill.warn::before { content: "\21\fe0e"; }
  .rcard-claim {
    margin: 0 0 1em; color: var(--muted);
    font-size: 0.89em; line-height: 1.55; max-width: 62ch;
  }
  .rcard-meta {
    display: grid; grid-template-columns: max-content 1fr;
    gap: 0.5em 1.4em; margin: 0;
  }
  .rcard-meta dt {
    font-weight: 600; color: var(--muted);
    font-size: 0.78em; text-transform: uppercase;
    letter-spacing: 0.05em; align-self: center;
  }
  .rcard-meta dd {
    margin: 0; color: var(--ink-soft); word-break: break-word;
  }
  .rcard-time { font-size: 1.12em; font-weight: 650; color: var(--ink); }
  .rcard-id code {
    font-size: 0.9em; background: var(--inset); color: var(--ink);
    padding: 0.12em 0.45em; border-radius: 3px;
  }
  .rcard-id .copy-btn { margin-left: 0.55em; }
  .rcard-chain { margin: 1em 0 0; }
  .rcard-chain a {
    color: var(--anchor); font-weight: 600; text-decoration: none;
    font-size: 0.95em;
  }
  .rcard-chain a:hover { text-decoration: underline; }
  .rcard .action-primary { margin-top: 1.2em; }
  .rcard .share-row { margin-bottom: 0; }
  @media (max-width: 560px) {
    .rcard-meta { grid-template-columns: 1fr; gap: 0.15em 0; }
    .rcard-meta dt { margin-top: 0.7em; }
    .rcard-meta dt:first-of-type { margin-top: 0; }
    .rcard-meta dd { margin-top: 0.1em; }
  }
  .technical-proof-details { margin: 1.4em 0; }
  .technical-proof-details > summary {
    cursor: pointer; font-weight: 600; color: var(--ink-soft);
    list-style: none; padding: 0.2em 0;
  }
  .technical-proof-details > summary::-webkit-details-marker {
    display: none;
  }
  .technical-proof-details > summary::before {
    content: "\25B8"; color: var(--anchor);
    display: inline-block; margin-right: 0.5em; font-size: 0.85em;
  }
  .technical-proof-details[open] > summary::before { content: "\25BE"; }
  .technical-proof-details[open] > summary { margin-bottom: 0.7em; }

  /* Keep-both visual on the proof success state. Ported from the
     apex .kb component; apex tokens remapped to the notary set
     (--signal -> --accent, the --r/--r-lg radii inlined). Native
     HTML/CSS/SVG only. */
  .kb {
    margin: 1.4em 0; border: 1px solid var(--line);
    border-radius: 8px; background: var(--surface-1);
    padding: 1.3em 1.3em 1.4em; text-align: center;
  }
  .kb-title {
    font-size: 0.74em; letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--muted); margin: 0 0 1em;
  }
  .kb-pair {
    display: flex; align-items: center; justify-content: center;
    gap: 1.1em; flex-wrap: wrap;
  }
  .kb-art {
    display: flex; flex-direction: column; align-items: center;
    gap: 0.4em; max-width: 16em;
    background: var(--surface-2); border: 1px solid var(--line);
    border-radius: 4px; padding: 1em 1.1em;
  }
  .kb-art svg { width: 30px; height: 30px; color: var(--accent); }
  .kb-name { font-family: ui-monospace, monospace; font-size: 0.9em;
             color: var(--ink); }
  .kb-note { font-size: 0.82em; color: var(--muted-soft);
             line-height: 1.45; }
  .kb-note b { color: var(--ink-soft); }
  .kb-plus { font-size: 1.4em; color: var(--muted); font-weight: 600; }
  .kb-cap {
    margin: 1.1em auto 0; max-width: 52ch;
    font-size: 0.92em; color: var(--ink-soft);
  }
  .kb-warn {
    margin: 0.6em auto 0; max-width: 52ch;
    font-size: 0.84em; color: var(--muted-soft);
  }
  @media (max-width: 560px) { .kb-pair { flex-direction: column; } }

  /* ============================================================
     notary-density v1 — readability layer. Body type only:
     17px / line-height 1.65 (16.5px on mobile) for comfortable
     prose measure. body is not styled by the nav block, so this
     later rule wins cleanly (no `body `-prefix needed). NO --muted
     change: dark --muted #a6b0bd already clears WCAG AA (7.97:1+).
     Placed before @media print so print light-safety still wins.
     ============================================================ */
  body { font-size: 17px; line-height: 1.65; }
  @media (max-width: 640px) {
    body { font-size: 16.5px; line-height: 1.65; }
  }

  @media print {
    html, body { background: #fff !important; color: #000 !important; }
    h1, h2, h3, .proof-grid dt, .proof-summary b,
    .rcard-time, .rcard-status-pill, .rcard-meta dd,
    .kb-name, .kb-cap { color: #000 !important; }
    .proof-summary, .retention, .banner, .privacy, .demo-card,
    .rcard, .rcard-status-pill, .kb, .kb-art,
    pre, code, details, details[open], .compare tbody tr {
      background: #fff !important; border-color: #ccc !important;
      color: #000 !important;
    }
    a { color: #000 !important; }
  }
