/* COSIGNA desktop initiator — brand v0.1.1 ink/paper/gold
   Desktop-first (1024px+), degrades to mobile single-column.
   Semantic tokens: canonical COSIGNA palette.                              */

/* ── Tokens ──────────────────────────────────────────────────────────────── */
/* WP2 complete: tokens.css (linked in <head> before this file) supplies every
   canonical token AND the legacy-alias block, so this file's plain :root
   forwarders are gone. The only per-file token override that remains is the
   dark-mode --grad below (a lighter panel gradient, NOT the canonical header
   gradient). */

/* ── Dark mode ───────────────────────────────────────────────────────────── */
/* Only --grad is overridden per-file: a lighter panel gradient (surface-ivory →
   border-default) that deliberately differs from tokens.css's canonical header
   gradient (--gradient-header). All other dark tokens come from tokens.css. */
[data-theme="dark"] {
  --grad:      linear-gradient(135deg, var(--surface-ivory, #1d3147), var(--border-default, #27405e));
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --grad:      linear-gradient(135deg, var(--surface-ivory, #1d3147), var(--border-default, #27405e));
  }
}

/* ── Reset ───────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; }
body {
  font-family: var(--font);
  /* v0.532.0 D-5b WP4: aurora ABOVE base --bg; WP5: --material-body-bg paper shields body text from the aurora (AA contrast) */
  background: var(--material-body-bg), var(--material-aurora), var(--bg);
  background-repeat: no-repeat;
  background-attachment: fixed;
  color: var(--text);
  min-height: 100dvh;
}

/* ── Topbar ──────────────────────────────────────────────────────────────── */
/* W2-A A2: header SKIN properties deleted — topbar.css/.cg-topbar--app now owns
   background, color, padding, layout, border-bottom.
   .topbar CLASS is RETAINED: .topbar .btn--ghost (initiator.css:129-133) and
   descendant rules for ☰/theme buttons depend on the class.
   v0.121.x iOS-Safari fix is now covered by topbar.css (same one-hop+literal pattern). */
.topbar {
  /* skin intentionally empty — governed by topbar.css .cg-topbar--app */
}

.topbar__brand {
  display: flex; align-items: center; gap: var(--s3);
  font-size: 18px; font-weight: 800; letter-spacing: -0.3px;
  color: var(--on-ink, #FAF8F3);
}
.topbar__brand svg { flex-shrink: 0; }
/* W2-A A2: bare .brand-lockup deleted — governed by topbar.css .cg-topbar--app .brand-lockup
   (44px @desktop; was 56px here). The class is still on the SVG markup. */
/* W2-A A2: bare .lang-flag / .lang-flag__btn / .lang-flag__caret / .lang-flag__menu deleted —
   all governed by topbar.css .cg-topbar--app .lang-flag* (higher-specificity scoped rules). */
/* v0.503.0 S-F1 (design call #12): .topbar__status small-pill override REMOVED.
   The element now carries .cg-topbar__title (governed by topbar.css) — large, bold, centered.
   The old pill (13px, rounded bg, absolute positioning) was preventing the title-block style
   from rendering. topbar.css handles all centering + font-size via .cg-topbar__title-block. */
.topbar__actions { display: flex; gap: var(--s2); align-items: center; }

/* v0.14.0 UX FIX: the topbar is ALWAYS dark (--ink) in both themes, but .btn--ghost uses
   color:var(--text) — which is navy in LIGHT mode → the ☰ menu + ☽ theme toggle were navy-on-navy
   (invisible). Scope topbar ghost buttons to paper-on-ink so the icons read in both themes. */
.topbar .btn--ghost {
  color: var(--on-ink, #FAF8F3);
  border-color: rgba(250, 248, 243, 0.35);
}
.topbar .btn--ghost:hover { background: rgba(250, 248, 243, 0.12); }

/* ── Layout ──────────────────────────────────────────────────────────────── */
.workspace {
  display: grid;
  grid-template-columns: 420px 1fr;
  grid-template-rows: 1fr;
  min-height: calc(100dvh - 52px);
  gap: 0;
}
.panel-left {
  border-right: 1px solid var(--border);
  overflow-y: auto;
  padding: var(--s6);
  display: flex; flex-direction: column; gap: var(--s5);
}
.panel-right {
  padding: var(--s6);
  overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--s5);
}

@media (max-width: 1023px) {
  .workspace { grid-template-columns: 1fr; }
  .panel-left { border-right: none; border-bottom: 1px solid var(--border); }
}

/* ── v0.44 SETUP-only full-width layout ──────────────────────────────────────
   During setup the ring/photo furniture is hidden (data-state gating), so the right
   half was empty wasted space while the intro + Document + COSignees were cramped in
   the narrow 420px left column. In setup ONLY, collapse the workspace to a single
   full-width column, drop the left-panel border, and lay the title + Document/COSignees
   across the reclaimed width. Monitor/open/close/done keep the original two-column ring
   layout untouched (these rules are scoped to [data-state="setup"]). */
[data-state="setup"] .workspace { grid-template-columns: 1fr; }
[data-state="setup"] .panel-left { border-right: none; }

/* v0.93.0 S-UX (#8): the OPEN consent-capture is a single-block page — collapse the workspace to ONE
   full-width column (like setup) and drop the left border, so the capture card can centre on the whole
   screen (the camera sits at the CENTRE on a computer, not the left). The ring/photo furniture is already
   gated out of open. */
[data-state="open"] .workspace { grid-template-columns: 1fr; max-width: 720px; margin-inline: auto; }
[data-state="open"] .panel-left { border-right: none; }
[data-state="open"] .panel-right { display: none; }

/* v0.93.0 S-UX (#13): on wide desktop the DONE screen (and its #done-onboard alpha-invite panel) was
   cramped into the 420px left column while the ring cockpit sprawled on the right — buttons clipped and
   the panel read awkwardly. Collapse done to ONE centred full-width column (the closed-ring "seal" SVG
   already crowns the done screen, so the right cockpit is redundant here) and drop the left border. */
[data-state="done"] .workspace { grid-template-columns: 1fr; max-width: 720px; margin-inline: auto; }
[data-state="done"] .panel-left { border-right: none; }
[data-state="done"] .panel-right { display: none; }

/* v0.58.0: top band — title (left) beside the invite-mode doc-picker (right). The aside collapses
   when empty (normal mode), so the title spans full width and the grid rises either way. */
.setup-header { display: flex; gap: var(--s6); align-items: flex-start; margin-bottom: var(--s4); }
.setup-header .setup-title { flex: 1 1 auto; min-width: 0; margin-bottom: 0; }
.setup-aside { flex: 0 0 290px; }
.setup-aside:empty { display: none; }
.setup-aside #referral-banner {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--ag-radius-lg); padding: var(--s4);
}
.setup-aside #dogfood-doc-pick { max-width: 100%; width: 100%; }
@media (max-width: 860px) {
  .setup-header { flex-direction: column; gap: var(--s3); }
  .setup-aside { flex-basis: auto; width: 100%; }
}

/* Full-width page title above the work area. */
.setup-title { margin-bottom: var(--s2); }
.setup-title__h {
  font-size: 30px; font-weight: 800; letter-spacing: -0.5px; line-height: 1.15;
  color: var(--text); margin-bottom: var(--s2);
}
.setup-title__p {
  font-size: 16px; color: var(--text-muted); line-height: 1.5; max-width: 70ch;
}
/* v0.53.0: the SignCredits reward expectation (invite mode) — a quiet gold note under the title. */
.setup-reward {
  margin-top: var(--s2); font-size: 14.5px; font-weight: 600; line-height: 1.45;
  color: var(--text); max-width: 70ch;
  background: rgba(195,161,75,.10); border-left: 3px solid var(--gold);
  border-radius: var(--ag-radius-sm, 6px); padding: 8px 12px;
}

/* Document + COSignees as two equal columns spanning the reclaimed full width;
   stack to one column on narrow screens.
   v0.93.0 S-UX (#1): align-items:stretch so the Document(1) and COSignees(2) cards are the SAME
   HEIGHT on wide screens (they share a row); .setup-card stretches to fill its grid cell. */
.setup-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--s5); align-items: stretch;
}
.setup-grid > .setup-card { height: 100%; }
@media (max-width: 860px) {
  .setup-grid { grid-template-columns: 1fr; }
  .setup-title__h { font-size: 24px; }
}

/* v0.93.0 S-UX (#4): when Options(3) is revealed, the setup grid becomes THREE columns on desktop —
   Document(1) | COSignees(2) | Options(3) — and the Launch seal + plain button span all columns.
   .setup-grid--3col is toggled by revealOptions(); collapses to one column on narrow screens. */
@media (min-width: 1024px) {
  .setup-grid--3col { grid-template-columns: 1fr 1fr 1fr; }
  .setup-grid--3col > #launch-seal-mount,
  .setup-grid--3col > #btn-launch { grid-column: 1 / -1; }
}
/* The Launch step header + seal + button always span the full grid width (1/2/3-col layouts). */
.setup-grid--3col > #launch-step-head { grid-column: 1 / -1; }
.setup-grid > #launch-step-head,
.setup-grid > #launch-seal-mount,
.setup-grid > #btn-launch { grid-column: 1 / -1; }

/* v0.95.0: the "3 · Seal & start" step header. Greyed (aria-disabled) until the setup is ready, then
   it brightens and the gate hint gives way to the hold-to-seal — same gating idiom as step 2. */
.launch-step-head {
  display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
  justify-content: center; margin-top: var(--s5);
}
.launch-step-head__t { font-size: 17px; font-weight: 700; color: var(--text); }
.launch-step-head[aria-disabled="true"] { opacity: .55; filter: saturate(.6); }
.launch-step-head .launch-gate-hint { display: none; }
.launch-step-head[aria-disabled="true"] .launch-gate-hint {
  display: inline-block; flex-basis: 100%; text-align: center;
  font-size: 13px; font-weight: 600; color: var(--text-muted);
  background: var(--surface-2); border: 1px dashed var(--border);
  border-radius: var(--ag-radius-md); padding: 8px 12px; margin-top: var(--s2);
}
/* v0.97.0: when the step is READY (the seal is the action), make the "3 · Seal & start" pill brand-gold
   so it reads as the live step, not a dim label the tester couldn't find. */
.launch-step-head:not([aria-disabled="true"]) .order-pill { background: var(--gold); color: #1a1205; }

/* v0.97.0 — the high-contrast "do this next" prompt shown above a hold-to-seal once it's the action
   (launch / open). Full-width, accent-coloured, with a gentle attention pulse. Replaces the situation
   where the seal sat below the fold with no signpost ("had to scroll down to find it"). */
.action-cta {
  flex-basis: 100%; display: block; text-align: center;
  font-size: 15px; font-weight: 800; letter-spacing: .01em; line-height: 1.4;
  color: var(--ink); background: rgba(195,161,75,.14);
  border: 1.5px solid var(--gold); border-radius: var(--ag-radius-lg);
  padding: 10px 14px; margin: var(--s3) auto 2px; max-width: 460px;
  animation: ctaPulse 2.2s ease-in-out infinite;
}
@keyframes ctaPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(195,161,75,0); }
  50%      { box-shadow: 0 0 0 6px rgba(195,161,75,.16); }
}
@media (prefers-reduced-motion: reduce) { .action-cta { animation: none; } }
[data-theme="dark"] .action-cta,
:root:not([data-theme="light"]) .action-cta { color: var(--text); }

/* v0.93.0 S-UX (#2): numbered order pills on the card titles (1 = Document, 2 = COSignees, 3 = Options)
   so the flow reads visually left→right. Optional variant (3) is muted/outline to signal it's not a gate. */
.order-pill {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: var(--ag-radius-full);
  background: var(--ink); color: var(--on-ink, #FAF8F3);
  font-size: 14px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums;
}
.order-pill--optional { background: transparent; color: var(--text-muted); border: 1.5px solid var(--border); }
.order-pill__opt { font-size: 12px; font-weight: 600; color: var(--text-muted); }

/* v0.93.0 S-UX (#3): gate step 2 on the document — until a PDF is picked, the COSignees card is
   greyed out + non-interactive (best-practice disabled affordance). #cosignees-card carries
   aria-disabled="true" until handlePDF success / a sample is loaded; checkSetupReady() clears it. */
#cosignees-card[aria-disabled="true"] {
  opacity: .5; pointer-events: none; filter: saturate(.6);
}
#cosignees-card[aria-disabled="true"] #cosignees-gate-hint { display: block; }
.gate-hint {
  display: none; margin: calc(-1 * var(--s2)) 0 var(--s4);
  font-size: 13px; font-weight: 600; color: var(--text-muted);
  background: var(--surface-2); border: 1px dashed var(--border);
  border-radius: var(--ag-radius-md); padding: 8px 12px;
}
#cosignees-card:not([aria-disabled="true"]) #cosignees-gate-hint { display: none; }

/* v0.93.0 S-UX (#5): the launch hold-to-seal logo gesture on the paper bg — ink C+Signa. */
#launch-seal-mount .cg-logo { --logo-c: #14253D; }
.launch-seal-mount { display: flex; justify-content: center; margin-top: var(--s5); }

/* Larger fonts in the setup cards (a clear notch up vs the rest of the UI). */
.setup-grid .card__title { font-size: 19px; }
.setup-grid label.field-label { font-size: 14px; }
.setup-grid .drop-zone__label { font-size: 17px; }
.setup-grid .drop-zone__sub { font-size: 14px; }
.setup-grid .hash-pill { font-size: 14px; }
.setup-grid .roster-item__name { font-size: 16px; }
.setup-grid .roster-item__channel { font-size: 14px; }

/* v0.3.2: shared widgets (Ceremony Progress + Consent photograph chain) stack by default. */
.shared-widgets { display: flex; flex-direction: column; gap: var(--s5); }

/* v0.34.0: the ring + consent-photo chain are "ceremony in progress" furniture — keep them OUT of the
   setup/open screens (they're empty there and clutter the step-by-step flow). They appear once the
   COSignMaster has opened the ring + taken their consent photo, i.e. from the monitor state on. */
[data-state="setup"] .shared-widgets,
[data-state="open"]  .shared-widgets { display: none; }

/* v0.3.2 wide-screen (≥1280px): make the right panel a 3rd+2nd column pair.
   Setup: Invitation preview | Security Mode side by side; Launch + What's new full width.
   Shared widgets: Ceremony Progress | Consent photograph chain side by side.
   (Document + Signers stay stacked in the 420px left panel = visual column 1.) */
/* v0.93.0 S-UX: the old right-panel setup 2-col grid is gone (Options+Launch moved into #setup-grid).
   Keep only the shared-widgets side-by-side treatment for the monitor cockpit. */
@media (min-width: 1280px) {
  .shared-widgets {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); align-items: start;
  }
}

/* ── v0.74.0 bugfix: SETUP layout + Launch button ─────────────────────────────
   The founder's report: on a computer the setup blocks sprawl edge-to-edge and the
   "Launch ceremony" control renders as a full-bleed dark BAR (not a button).
   Cause: in setup the workspace collapses to one column (panel-right spans the full
   viewport); at ≥1280 the panel-right state-panel is a 2-col grid whose 2nd column is
   empty (the ring/photo furniture is hidden until first signature), and #btn-launch
   spans grid-column 1/-1 → as an inline-flex grid item it stretches the whole width.
   Fix (scoped to setup only — cockpit states untouched): cap + centre the setup column,
   make the panel-right setup panel a single centred column, and let the Launch button
   size to its content as an obvious, centred primary button. Placed AFTER the 1280 grid
   block so source order wins the cascade (equal specificity). */
/* v0.93.0 S-UX (#4): the setup workspace was capped at 1040px (a 2-col-friendly width). With Options(3)
   now a third column, widen the cap so three cards breathe on desktop. */
[data-state="setup"] .workspace {
  max-width: 1280px;
  margin-inline: auto;
}
/* v0.93.0 S-UX: Options(3) + Launch moved into #setup-grid, so the right-panel setup slot is empty —
   collapse it so it adds no stray gap. */
[data-state="setup"] .panel-right .state-panel--setup { display: none; }
/* v0.93.0 S-UX: #btn-launch is now hidden (the hold-to-seal logo replaces it). #btn-continue-options
   is an optional ghost link inside the COSignees card — left-aligned, content-sized (not a big CTA). */
[data-state="setup"] #btn-continue-options {
  align-self: flex-start; width: auto;
}
/* G1 fix: launch button + seal mount are always rendered (visible-disabled affordance).
   When aria-disabled="true" they appear at reduced opacity with a not-allowed cursor so the
   user knows the control exists and understands it needs steps 1–2 first. */
#btn-launch[aria-disabled="true"],
#launch-seal-mount[aria-disabled="true"] {
  opacity: 0.45; cursor: not-allowed; pointer-events: none;
}
#btn-launch[aria-disabled="true"] { filter: saturate(0.4); }

/* v0.3.2: roster drag-handle — makes reordering discoverable. */
.roster-item__handle {
  cursor: grab; color: var(--text-muted); font-size: 16px; line-height: 1;
  user-select: none; padding-right: 2px; flex-shrink: 0;
}
.roster-item.dragging { opacity: 0.5; }

/* ── State visibility — js adds data-state to <body> ──────────────────── */
[data-state] .state-panel { display: none; }
[data-state="setup"]   .state-panel--setup   { display: flex; flex-direction: column; gap: var(--s4); }
[data-state="open"]    .state-panel--open    { display: flex; flex-direction: column; gap: var(--s4); }
[data-state="monitor"] .state-panel--monitor { display: flex; flex-direction: column; gap: var(--s4); }
[data-state="close"]   .state-panel--close   { display: flex; flex-direction: column; gap: var(--s4); }
[data-state="done"]    .state-panel--done    { display: flex; flex-direction: column; gap: var(--s4); }

/* ── Cards ───────────────────────────────────────────────────────────────── */
.card {
  /* v0.532.0 D-5b WP4: material card glass (setup/monitor/done cards) */
  background: var(--material-card-bg, linear-gradient(180deg, rgba(255,255,255,.86), rgba(255,255,255,.52)));
  border: 1px solid var(--material-card-border, rgba(255,255,255,.72));
  border-radius: var(--material-card-radius, 14px); padding: var(--s5);
  backdrop-filter: var(--material-card-blur, blur(16px) saturate(1.45));
  -webkit-backdrop-filter: var(--material-card-blur, blur(16px) saturate(1.45));
  box-shadow: var(--material-card-rim, inset 0 1px 0 rgba(255,255,255,.95), 0 8px 22px -12px rgba(20,37,61,.30));
  animation: agFadeIn .3s ease;
}
.card__title {
  font-size: 17px; font-weight: 700;   /* v0.34.0 type bump: 15→17 */
  display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s4);
  color: var(--text);
}
.card__title .icon { font-size: 18px; }

/* ── Form elements ───────────────────────────────────────────────────────── */
label.field-label {
  display: block; font-size: 13px; font-weight: 600;   /* v0.34.0 type bump: 12→13 */
  /* v0.74.0 bugfix: drop uppercase — it mangled the brand casing ("Your name (COSignMaster)"
     → "YOUR NAME (COSIGNMASTER)"). Weight + muted colour carry the label affordance;
     sentence-case preserves brand names (COSignMaster / COSignee / COSigna). */
  text-transform: none; letter-spacing: .01em;
  color: var(--text-muted); margin-bottom: var(--s1);
}
input[type="text"], input[type="email"], select {
  width: 100%; padding: var(--s3) var(--s4);
  border: 1.5px solid var(--border); border-radius: var(--ag-radius-md);
  font-family: var(--font); font-size: 16px;   /* v0.34.0 type bump: 14→16 (also stops iOS zoom-on-focus) */
  background: var(--field); color: var(--text);
  transition: border-color .2s;
}
input:focus, select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(20,37,61,.12);
}

/* ── Drop zone ───────────────────────────────────────────────────────────── */
.drop-zone {
  border: 2px dashed var(--border); border-radius: var(--ag-radius-xl);
  padding: var(--s8) var(--s6); text-align: center;
  cursor: pointer; transition: border-color .2s, background .2s;
  display: flex; flex-direction: column; align-items: center; gap: var(--s3);
}
.drop-zone:hover, .drop-zone.drag-over {
  border-color: var(--accent); background: rgba(195,161,75,.06);
}
.drop-zone--done { border-color: var(--success); background: rgba(46,125,91,.05); }
.drop-zone__icon { font-size: 32px; }
.drop-zone__label { font-size: 15px; font-weight: 600; }   /* v0.34.0: 14→15 */
.drop-zone__sub { font-size: 13px; color: var(--text-muted); }   /* v0.34.0: 12→13 */

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  padding: 12px var(--s6); border: none; border-radius: var(--ag-radius-lg);
  font-family: var(--font); font-size: 15px; font-weight: 600; cursor: pointer;   /* v0.34.0 type bump: 14→15 */
  min-height: 44px; transition: transform .15s, box-shadow .15s, opacity .2s;
  text-decoration: none; white-space: nowrap;
}
.btn:active { transform: scale(.97); }
.btn:disabled { opacity: .4; cursor: not-allowed; }
.btn--primary {
  background: var(--grad); color: var(--on-ink, #FAF8F3);
  box-shadow: 0 2px 12px rgba(20,37,61,.18);
}
.btn--primary:not(:disabled):hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 18px rgba(20,37,61,.28);
}
.btn--ghost { background: transparent; border: 1.5px solid var(--border); color: var(--text); }
.btn--ghost:hover { background: var(--bg); }
.btn--danger { background: var(--danger); color: white; }
.btn--success { background: var(--success); color: white; }
/* Gold ceremonial close button */
.btn--seal {
  background: linear-gradient(135deg, var(--gold), var(--brand-gold-dark, #a88435));
  color: #fff;  /* white text on gold bg — intentional */
  box-shadow: 0 2px 12px rgba(195,161,75,.35);
}
.btn--seal:not(:disabled):hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 20px rgba(195,161,75,.5);
}
.btn--sm { padding: 8px var(--s4); font-size: 13px; min-height: 34px; }
.btn-row { display: flex; gap: var(--s3); flex-wrap: wrap; }

/* v0.52.0: QR fingerprint + Preview/Download on ONE row, led by a prominent "download & send" CTA.
   The COSignee must receive the document out-of-band (the server is blind) — so this is a real step. */
.qr-doc-row { display: flex; gap: var(--s4); align-items: flex-start; flex-wrap: wrap; margin-top: var(--s3); }
.qr-doc-row__actions { flex: 1 1 200px; min-width: 180px; }
/* v0.56.1: preview eye + the single "download & send" banner on one row (banner IS the download). */
.doc-send-row { display: flex; gap: var(--s2); align-items: stretch; margin-bottom: var(--s3); }
.doc-preview-icon {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  padding: 0 12px; font-size: 18px; line-height: 1; cursor: pointer; color: var(--text);
  background: transparent; border: 1px solid var(--border); border-radius: var(--ag-radius-md);
}
.doc-preview-icon:hover { background: rgba(195,161,75,.10); border-color: var(--gold); }
.doc-send-cta {
  flex: 1 1 auto; font-size: 15px; font-weight: 700; line-height: 1.4; color: var(--text);
  background: rgba(195,161,75,.12); border: 1px solid var(--gold); cursor: pointer;
  border-radius: var(--ag-radius-md); padding: 10px 12px; text-decoration: none;
  display: flex; align-items: center;
}
.doc-send-cta:hover { background: rgba(195,161,75,.18); }
.setup-grid .doc-send-cta { font-size: 16px; }   /* a notch larger in the side-by-side setup layout */

/* ── Badges ──────────────────────────────────────────────────────────────── */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px var(--s3); border-radius: var(--ag-radius-full);
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
}
/* v0.62.0: status chips match the C-ring — Signed = gold (no more green), Withdrawn = danger,
   Pending = neutral, Skipped = neutral. Keeps the whole monitor on the brand palette. */
.badge--success { background:rgba(195,161,75,.20); color:#7a5e16; }
.badge--warning { background:#fde8e8; color:#B91C1C; }
.badge--danger  { background:#fde8e8; color:#B91C1C; }
.badge--info    { background:var(--surface-2); color:var(--text-muted); }
.badge--neutral { background:var(--surface-2); color:var(--text-muted); }
[data-theme="dark"] .badge--success { background:#3a2f12; color:#d8b864; }
[data-theme="dark"] .badge--warning { background:#3a1414; color:#f0a3a3; }
[data-theme="dark"] .badge--danger  { background:#3a1414; color:#f0a3a3; }
[data-theme="dark"] .badge--info    { background:#27405e; color:var(--text-muted); }
[data-theme="dark"] .badge--neutral { background:#27405e; color:var(--text-muted); }

/* ── Hash ─────────────────────────────────────────────────────────────────── */
.hash-pill {
  font-family: var(--font-mono); font-size: 12px;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--ag-radius-md); padding: var(--s2) var(--s3);
  word-break: break-all; cursor: pointer; transition: color .2s;
}
.hash-pill:hover { color: var(--accent); }

/* ── Roster ──────────────────────────────────────────────────────────────── */
.roster-item {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4); border: 1px solid var(--border);
  border-radius: var(--ag-radius-lg); background: var(--bg);
}
.roster-item__avatar {
  width: 36px; height: 36px; border-radius: var(--ag-radius-full);
  background: var(--grad); color: var(--on-ink, #FAF8F3); display: flex; align-items: center;
  justify-content: center; font-weight: 700; font-size: 14px; flex-shrink: 0;
}
.roster-item__name { font-weight: 600; font-size: 15px; }   /* v0.34.0: 14→15 */
.roster-item__channel { font-size: 13px; color: var(--text-muted); }   /* v0.34.0: 12→13 */
.roster-item__remove { margin-left: auto; color: var(--text-muted); cursor: pointer; font-size: 18px; line-height: 1; }
.roster-item__remove:hover { color: var(--danger); }

/* ── Signer Links ────────────────────────────────────────────────────────── */
.signer-links { display: flex; flex-direction: column; gap: var(--s2); font-size: 14px; }   /* v0.34.0: 13→14 */
.signer-links__note { color: var(--text-muted); margin-bottom: var(--s2); line-height: 1.5; font-size: 12px; }
.signer-link-row { display: flex; flex-direction: column; padding: var(--s3); background: var(--bg); border-radius: var(--ag-radius-lg); border: 1px solid var(--border); }
.signer-link-row__name { font-weight: 600; margin-bottom: 4px; }
/* W2-C: display:block moved from inline style → governed CSS class; hidden attr still suppresses until "Show link" is clicked. */
.signer-link-row__url { display: block; margin-top: 6px; font-family: var(--font-mono); font-size: 11px; word-break: break-all; color: var(--accent); text-decoration: none; }
.signer-link-row__url:hover { text-decoration: underline; }
/* v0.93.0 S-UX (#14): the Notarize / self-2nd-device row narrows to JUST the "📱 Scan to open" QR
   (Email/Message/Copy dropped — you ARE the other device, so a QR is the only relevant action). */
.signer-link-row--self { max-width: 340px; }
.signer-link-row--self .signer-link-row__actions { justify-content: flex-start; }

/* ── Message preview ─────────────────────────────────────────────────────── */
.msg-preview {
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--ag-radius-lg); padding: var(--s4);
  font-size: 13px; line-height: 1.6; color: var(--text-muted);
  font-style: italic;
}

/* v0.93.0 S-UX (#8): centre the OPEN consent-capture card horizontally so on a computer the user
   (and the camera) look at the CENTRE of the screen, not the left edge (mirrors the FaceCapture fix).
   The viewfinder already centres via margin:auto; this centres the whole card + caps its width. */
.state-panel--open { align-items: center; }
.state-panel--open__card {
  width: 100%; max-width: 560px; margin-inline: auto; text-align: center;
}
.state-panel--open__card .card__title { justify-content: center; }
.state-panel--open__card .btn-row { justify-content: center; }
/* v0.93.0 S-UX (#9): the OPEN hold-to-seal logo gesture on paper — ink C+Signa, centred. */
#open-seal-mount .cg-logo { --logo-c: #14253D; }
.open-seal-mount { display: flex; justify-content: center; margin-top: var(--s4); }

/* ── Camera ──────────────────────────────────────────────────────────────── */
.viewfinder-wrap {
  position: relative; width: 100%; max-width: 480px; margin: 1rem auto;
  border-radius: var(--ag-radius-xl); overflow: hidden; aspect-ratio: 3/4;
  /* Calm near-black viewfinder so the moment before the feed loads (or if permission is
     denied) reads as a dark camera, never a flash of white/green. */
  background: #0c1726;  /* camera dark bg — intentional; skin literal */
}
#open-camera-feed {
  width: 100%; height: 100%; object-fit: cover; display: block; transform: scaleX(-1);
}
.qr-corner {
  position: absolute; bottom: var(--s3); right: var(--s3);
  width: 72px; height: 72px; background: white;
  border-radius: var(--ag-radius-md); padding: 4px;
  box-shadow: 0 2px 8px rgba(0,0,0,.4);
}
.qr-corner img { width: 100%; height: 100%; display: block; }
.face-guide-dt {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; pointer-events: none;
}
.face-oval {
  /* Delicate gold ring outline (thin, not a solid block) — the framing guide. */
  width: 160px; height: 200px; border: 2px solid var(--gold);
  border-radius: 50%/40%; transition: border-color .3s; opacity: .85;
}
.face-oval--ok { border-color: var(--success); border-style: solid; }
.cam-hint {
  position: absolute; top: var(--s3); left: var(--s3); right: var(--s3); text-align: center;
  font-size: 12px; color: white; font-weight: 600; text-shadow: 0 1px 3px rgba(0,0,0,.8);
}

/* ── Ring visualization ──────────────────────────────────────────────────── */
/* v0.2.3 S-uxrevamp: circle on the LEFT, legend stacked vertically on the RIGHT
   (row layout); wraps back to a stack on narrow widths so nothing clips. */
/* v0.99.1 (founder bug): the abort confirmation is a CENTERED fixed modal (was inserted into the topbar
   and overflowed the top-right on mobile). Pinned just under the sticky topbar; width-capped to the viewport. */
.abort-confirm {
  position: fixed; top: calc(var(--topbar-h, 56px) + 12px); left: 50%; transform: translateX(-50%);
  z-index: 200; width: min(360px, 92vw); box-sizing: border-box;
  display: flex; flex-direction: column; align-items: center; gap: var(--s2);
  padding: var(--s4); background: var(--surface); border: 1.5px solid var(--danger, #c0392b);
  border-radius: var(--ag-radius-lg); box-shadow: 0 14px 44px rgba(0,0,0,.30);
}
.abort-confirm__msg { font-weight: 700; font-size: 14px; text-align: center; line-height: 1.45; color: var(--text); }
.abort-confirm__cancel { margin-top: 2px; }

/* v0.98.0 (founder): explicit monitor wayfinding — "Waiting for your COSignees to sign…" while collecting. */
.monitor-wait {
  display: flex; align-items: center; gap: 10px; justify-content: center;
  font-size: 13.5px; font-weight: 600; color: var(--text); line-height: 1.45;
  background: rgba(195,161,75,.10); border: 1px solid var(--gold);
  border-radius: var(--ag-radius-md); padding: 10px 14px; margin: 0 0 var(--s4); text-align: left;
}
.monitor-wait__pulse {
  flex: 0 0 auto; width: 10px; height: 10px; border-radius: 50%; background: var(--gold);
  animation: waitPulse 1.6s ease-in-out infinite;
}
@keyframes waitPulse { 0%,100% { opacity: .35; transform: scale(.8); } 50% { opacity: 1; transform: scale(1.1); } }
@media (prefers-reduced-motion: reduce) { .monitor-wait__pulse { animation: none; } }

.ring-wrap { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--s6); }
.ring-svg { max-width: 240px; width: 100%; flex: 0 1 240px; }
.ring-legend {
  display: flex; flex-direction: column; flex-wrap: nowrap; gap: var(--s2);
  justify-content: center; align-items: flex-start; font-size: 13px;
}
.ring-legend-item { display: flex; align-items: center; gap: 6px; }
.ring-legend-dot {
  width: 12px; height: 12px; border-radius: var(--ag-radius-full);
}

/* ── Photo strip ─────────────────────────────────────────────────────────── */
.photo-strip {
  display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center;
}
.photo-strip__item {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.photo-strip__face {
  width: 56px; height: 56px; border-radius: var(--ag-radius-full);
  object-fit: cover; border: 2.5px solid var(--accent);
  background: var(--bg);
}
.photo-strip__face--placeholder {
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; border-color: var(--border);
}
.photo-strip__name { font-size: 11px; color: var(--text-muted); max-width: 60px; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* v0.99.0 (founder): tap a consent-photo pill to enlarge it (esp. on mobile); tap again to shrink. */
.photo-strip__face { cursor: zoom-in; transition: transform .18s ease, box-shadow .18s ease; }
.photo-strip__face.enlarged {
  transform: scale(2.8); position: relative; z-index: 30; cursor: zoom-out;
  box-shadow: 0 10px 30px rgba(20,37,61,.35); border-color: var(--gold);
}
@media (prefers-reduced-motion: reduce) { .photo-strip__face { transition: none; } }

/* v0.402.0 S-signpad: per-COSignee self-declared-signature cell in the monitor participant table.
   Honest label always; thumbnail swaps in when CK decrypts the sealed commitment. Never identity. */
.ptable-signpad { display: inline-flex; align-items: center; gap: 6px; }
.ptable-signpad__label { font-size: 11px; color: var(--text-muted); white-space: nowrap; }
.ptable-signpad__img {
  height: 28px; max-width: 110px; object-fit: contain;
  background: #fff; border: 1px solid var(--border, #ddd); border-radius: 4px; padding: 2px;
  cursor: zoom-in;
}

/* v0.99.0 (founder): mobile-only "send this document to your other device" note (2-device seal). */
.mobile-doc-note {
  margin-top: var(--s4); padding: var(--s3) var(--s4);
  background: rgba(195,161,75,.10); border: 1px solid var(--gold); border-radius: var(--ag-radius-lg);
}
.mobile-doc-note p { margin: 0 0 var(--s3); font-size: 13px; line-height: 1.5; color: var(--text); }
.mobile-doc-note .btn { width: 100%; }
.photo-strip__arrow { font-size: 16px; color: var(--text-muted); margin-bottom: 16px; }

/* ── Audit log ───────────────────────────────────────────────────────────── */
.audit-log { display: flex; flex-direction: column; gap: var(--s2); max-height: 220px; overflow-y: auto; }
.audit-entry { display: flex; gap: var(--s3); align-items: flex-start; font-size: 13.5px; }   /* v0.34.0: 13→13.5 */
.audit-entry__time { color: var(--text-muted); font-family: var(--font-mono); font-size: 11px; white-space: nowrap; }
.audit-entry__action { font-weight: 600; }
.audit-entry__detail { color: var(--text-muted); }

/* ── Dispatch preview ────────────────────────────────────────────────────── */
.dispatch-preview-table { width: 100%; font-size: 13px; border-collapse: collapse; }
.dispatch-preview-table td { padding: var(--s2) var(--s3); border-bottom: 1px solid var(--border); vertical-align: top; }
.dispatch-preview-table td:first-child { font-weight: 600; white-space: nowrap; width: 1%; }

/* ── Lifecycle breadcrumb (founder decision D3) ──────────────────────────────
   The prominent numbered stepper was replaced by a slim single-line caption so it
   never competes with the central ring (the hero). It is present in every state. */
.lifecycle-bar {
  padding: var(--s2) var(--s8); border-bottom: 1px solid var(--border);
  background: var(--surface);
  /* v0.97.0 (founder bug): keep "Step N of 5" on screen — it scrolled away, so the tester "had no idea I
     was not done yet". Sticky just under the (also-sticky) topbar; JS sets --topbar-h to the live height. */
  position: sticky; top: var(--topbar-h, 56px); z-index: 9;
  cursor: default;   /* v0.97.0: it's wayfinding, never clickable — kill the stray pointer cursor */
}
.breadcrumb { cursor: default; }
.breadcrumb__caption {
  /* v0.97.0: bumped contrast (was --text-muted) so the current step reads clearly. */
  font-size: 12.5px; font-weight: 700; letter-spacing: .02em;
  color: var(--text); text-transform: uppercase; cursor: default;
}

/* ── Confirm affirm ──────────────────────────────────────────────────────── */
.affirm-box {
  border: 1.5px solid var(--border); border-radius: var(--ag-radius-lg);
  padding: var(--s4); display: flex; gap: var(--s3); align-items: flex-start; cursor: pointer;
}
.affirm-box:has(input:checked) { border-color: var(--success); background: rgba(46,125,91,.05); }
.affirm-box input { width: 20px; height: 20px; margin-top: 2px; flex-shrink: 0; accent-color: var(--success); }
.affirm-box label { font-size: 14px; line-height: 1.5; cursor: pointer; }

/* ── Close predecessor panel ─────────────────────────────────────────────── */
.close-pred { display: flex; gap: var(--s4); align-items: center; padding: var(--s4); background: var(--bg); border-radius: var(--ag-radius-xl); }
.close-pred__face {
  width: 80px; height: 80px; border-radius: var(--ag-radius-full);
  object-fit: cover; border: 3px solid var(--gold); flex-shrink: 0; background: var(--bg);
}
.close-pred__info { flex: 1; }
.close-pred__name { font-size: 18px; font-weight: 700; }
.close-pred__role { font-size: 13px; color: var(--text-muted); }

/* ── Done screen ──────────────────────────────────────────────────────────── */
/* v0.93.0 S-UX (#13): on wide desktop the done screen (and its #done-onboard alpha-invite panel) read
   awkwardly edge-to-edge. Centre the whole screen, cap its width, and lay action buttons in a tidy
   centred column so it reads cleanly. */
.state-panel--done { align-items: center; }
.done-screen {
  text-align: center; padding: var(--s12) var(--s8); animation: agFadeIn .4s ease;
  width: 100%; max-width: 560px; margin-inline: auto;
  display: flex; flex-direction: column; align-items: center;
}
.done-screen > a.btn, .done-screen > button.btn { align-self: stretch; }
/* #done-onboard alpha-invite panel: constrain + centre so it no longer sprawls on wide screens. */
#done-onboard {
  width: 100%; max-width: 520px; margin-inline: auto; box-sizing: border-box;
}
#done-onboard .btn { width: 100%; }
.done-screen__icon { font-size: 80px; }
/* Closed ring "cryptographic lock" — soft gold glow signifying the sealed loop. */
.done-screen__seal {
  display: inline-flex; align-items: center; justify-content: center;
  margin-bottom: var(--s2);
  filter: drop-shadow(0 0 14px rgba(195,161,75,.55)) drop-shadow(0 0 4px rgba(15,118,110,.45));
  animation: sealGlow 2.4s ease-in-out infinite;
}
@keyframes sealGlow {
  0%, 100% { filter: drop-shadow(0 0 10px rgba(195,161,75,.40)) drop-shadow(0 0 4px rgba(15,118,110,.35)); }
  50%      { filter: drop-shadow(0 0 18px rgba(195,161,75,.65)) drop-shadow(0 0 6px rgba(15,118,110,.50)); }
}
@media (prefers-reduced-motion: reduce) { .done-screen__seal { animation: none; } }
/* v0.96.0 S-DESIGN: the SEALED lockup as the DONE-screen hero mark — ink C+wordmark (currentColor),
   gold o/S/padlock; responsive width so the padlock stays legible without overflowing on a phone. */
.done-screen__seal .sealed-lockup { width: min(260px, 78vw); height: auto; color: var(--text); }
.done-screen__title { font-size: 28px; font-weight: 800; margin: var(--s4) 0 var(--s3); }
.done-screen__body { font-size: 15px; color: var(--text-muted); line-height: 1.6; max-width: 480px; margin: 0 auto var(--s6); }

/* ── Enrollment nudge (post-close viral CTA) ─────────────────────────────── */
.enrollment-nudge {
  margin-top: var(--s8);
  border-top: 1px solid var(--border);
  padding-top: var(--s8);
  text-align: center;
  max-width: 480px;
  margin-left: auto;
  margin-right: auto;
}
.enrollment-nudge__heading {
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: var(--s3);
}
.enrollment-nudge__body {
  font-size: 14px;
  color: var(--text-muted);
  line-height: 1.7;
  margin-bottom: var(--s5);
}
.enrollment-nudge__actions {
  display: flex;
  gap: var(--s3);
  flex-wrap: wrap;
  justify-content: center;
}

/* ── Spinner ─────────────────────────────────────────────────────────────── */
.spinner { width: 36px; height: 36px; border: 3px solid var(--border); border-top-color: var(--ink); border-radius: var(--ag-radius-full); animation: agSpin .8s linear infinite; margin: 0 auto; }

/* ── Animations ──────────────────────────────────────────────────────────── */
@keyframes agFadeIn { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:none; } }
@keyframes agSpin   { to { transform:rotate(360deg); } }

/* v0.1.4 — Center Stage guidance note + live version chip */
.camera-help {
  font-size: 12px;
  color: var(--text-muted);
  text-align: center;
  margin-top: var(--s3);
  line-height: 1.45;
}
.camera-help strong { color: var(--text); }
.app-version {
  position: fixed;
  right: 8px;
  bottom: 6px;
  font-size: 11px;
  font-family: var(--font-mono);
  color: var(--text-muted);
  opacity: .65;
  pointer-events: none;
  z-index: 5;
}

/* v0.89.0 Test-Mode: "try a COSigna sample" prompt under the drop-zone (1-page / 350-page).
   Hidden once a document is loaded (#pdf-drop gains .drop-zone--done). */
.sample-try{ margin-top:var(--s2); display:flex; flex-direction:column; gap:6px; }
.sample-try__head{ font-size:12.5px; color:var(--text-muted); line-height:1.4; }
.sample-try__btns{ display:flex; gap:8px; flex-wrap:wrap; }
.sample-try__btns .btn{ text-decoration:none; }
#pdf-drop.drop-zone--done ~ .sample-try{ display:none; }

/* v0.90.0 Test-Mode: cross-device self-cosign nudge atop the COSignee links panel. */
.selfcosign-note{ background:var(--surface-2); border:1px solid var(--accent); border-radius:var(--ag-radius-lg);
  padding:var(--s3); margin-bottom:var(--s3); font-size:13px; line-height:1.45; color:var(--text); }
.selfcosign-note strong{ color:var(--accent); }

/* v0.91.0: scan-to-open QR under a COSignee/notarize link (built client-side; preserves zero-trust). */
.signer-qr{ margin-top:8px; padding:8px; background:#fff; border:1px solid var(--border); border-radius:var(--ag-radius-md); display:inline-block; }
/* The `display:inline-block` above is an AUTHOR rule and defeats the `hidden` attribute (author CSS beats
   the UA `[hidden]{display:none}`), so the per-COSignee QR box was ALWAYS visible as an empty white
   rectangle and cosignaShowQR()'s `box.hidden = true` toggle could not hide it. Honor `hidden` explicitly.
   (signer-qr--auto on the self/notarize row carries no `hidden` attr + an inline display:block → unaffected.) */
.signer-qr[hidden]{ display:none; }
.signer-qr svg{ display:block; }
.signer-qr__cap{ margin-top:6px; font-size:11px; color:var(--text-muted); max-width:180px; line-height:1.35; }
/* v0.304.0 D: the auto-render self/notarize QR is click-to-enlarge. */
.signer-qr--auto{ cursor:zoom-in; }
/* v0.304.0 D: big-by-default QR overlay — centered, NON-fullscreen, z-index 150 (below the abort modal z-200,
   above the topbar z-10). Tap anywhere (card or backdrop) to shrink. SVG scales losslessly to ~72vh. */
/* Positioned BELOW the sticky topbar (var(--topbar-h)) so the Abort control in the header stays visible
   and clickable while the QR is enlarged (§3: the abort must never be occluded). Auto-collapses on seal. */
.self-qr-overlay{ position:fixed; top:var(--topbar-h,56px); left:0; right:0; bottom:0; z-index:150;
  display:flex; align-items:center; justify-content:center; background:rgba(20,37,61,.45); padding:var(--s3,16px); cursor:zoom-out; }
.self-qr-overlay[hidden]{ display:none; }
.self-qr-overlay__card{ background:#fff; border-radius:var(--ag-radius-lg,16px); padding:var(--s4,24px);
  box-sizing:border-box; max-width:92vw; text-align:center; box-shadow:0 12px 48px rgba(0,0,0,.30); cursor:zoom-out; }
/* v0.402.0 S-qr (founder, mobile): the QR + caption must FIT the card content box, not a bare viewport
   width. Before, height:min(72vh,86vw) + width:auto made the SVG ~86vw wide while the card content box
   is only (92vw − padding), so the SVG OVERFLOWED the card → both the card and the QR read left-aligned
   on a portrait phone. max-width:100% caps the SVG to the card → margin:0 auto centers it → the card
   stays ≤92vw and the flex overlay centers the card; margin:auto centres the caution/cap blocks too. */
.self-qr-overlay__qr{ text-align:center; }
.self-qr-overlay__qr svg{ width:auto; height:auto; max-width:100%; max-height:min(72vh,80vw); display:block; margin:0 auto; }
.self-qr-overlay__caution{ font-size:13px; color:var(--brand-gold,#C3A14B); margin:0 auto 10px; max-width:min(72vh,86vw); line-height:1.4; }
.self-qr-overlay__cap{ font-size:13px; color:var(--text-muted); margin:10px auto 0; max-width:min(72vh,86vw); line-height:1.4; }
@media (prefers-reduced-motion: no-preference){ .self-qr-overlay__card{ animation:self-qr-pop .18s ease-out; } }
@keyframes self-qr-pop{ from{ transform:scale(.86); opacity:0; } to{ transform:scale(1); opacity:1; } }

/* v0.535.0 S-movie gate-fix (2026-07-25): the global `input:focus{outline:none}` (see l.365) strips
   the native ring, but its border/box-shadow compensation only renders on bordered text inputs — a
   native checkbox shows neither, leaving zero measurable focus delta (spec-77 focus). Restore a
   high-contrast, theme-adaptive outline: var(--text) clears the 3:1 focus-contrast bar on both the
   light and the dark card, and a solid outline (not box-shadow) also survives forced-colors mode.
   NB: `:focus` (not `:focus-visible`) — the spec-77 guard focuses via programmatic element.focus(),
   which does NOT reliably match :focus-visible (browser modality heuristic; passed in isolation but
   failed in the full suite). `:focus` matches deterministically on every .focus(). */
#allow-attachments-check:focus {
  outline: 2px solid var(--text);
  outline-offset: 2px;
}
