/* ============ Tokens ============ */
:root{
  --bg: #EEF0EF;
  --surface: #FFFFFF;
  --surface-2: #E3E6E4;
  --surface-3: #D7DBD8;
  --text: #171A1F;
  --text-muted: #5B6167;
  --text-faint: #868C90;
  --border: #D3D7D4;
  --border-strong: #B9BFBB;
  --accent: #8C6A3B;
  --accent-strong: #6E5029;
  --accent-ink: #FBF6EE;
  --accent-wash: rgba(140,106,59,0.10);
  --success: #3F7A5C;
  --success-wash: rgba(63,122,92,0.12);
  --warning: #A85423;
  --warning-wash: rgba(168,84,35,0.10);
  --danger: #A23D33;
  --danger-wash: rgba(162,61,51,0.10);
  --shadow: 0 1px 2px rgba(20,20,15,0.06), 0 8px 24px -12px rgba(20,20,15,0.18);

  --font-display: 'Cinzel', 'Iowan Old Style', serif;
  --font-sans: 'IBM Plex Sans', -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;
}

@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg: #13151B;
    --surface: #1B1E26;
    --surface-2: #21252F;
    --surface-3: #2A2F3B;
    --text: #E9EAEA;
    --text-muted: #8A8F9C;
    --text-faint: #656B78;
    --border: #2C303B;
    --border-strong: #3A3F4C;
    --accent: #C79A5E;
    --accent-strong: #E0B67C;
    --accent-ink: #1B1408;
    --accent-wash: rgba(199,154,94,0.12);
    --success: #6FAE8B;
    --success-wash: rgba(111,174,139,0.14);
    --warning: #D08A4C;
    --warning-wash: rgba(208,138,76,0.14);
    --danger: #D06B5E;
    --danger-wash: rgba(208,107,94,0.14);
    --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 12px 28px -14px rgba(0,0,0,0.6);
  }
}
:root[data-theme="dark"]{
  --bg: #13151B;
  --surface: #1B1E26;
  --surface-2: #21252F;
  --surface-3: #2A2F3B;
  --text: #E9EAEA;
  --text-muted: #8A8F9C;
  --text-faint: #656B78;
  --border: #2C303B;
  --border-strong: #3A3F4C;
  --accent: #C79A5E;
  --accent-strong: #E0B67C;
  --accent-ink: #1B1408;
  --accent-wash: rgba(199,154,94,0.12);
  --success: #6FAE8B;
  --success-wash: rgba(111,174,139,0.14);
  --warning: #D08A4C;
  --warning-wash: rgba(208,138,76,0.14);
  --danger: #D06B5E;
  --danger-wash: rgba(208,107,94,0.14);
  --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 12px 28px -14px rgba(0,0,0,0.6);
}

/* ============ Reset ============ */
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; height:100%; }
body{
  margin:0; height:100%; overflow:hidden; background:var(--bg); color:var(--text);
  font-family:var(--font-sans); font-size:15px; line-height:1.55;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3,p,ul,figure{ margin:0; }
ul{ list-style:none; padding:0; }
button{ font:inherit; color:inherit; }
input{ font:inherit; color:inherit; }
button{ cursor:pointer; }
:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; border-radius:4px; }
img,svg{ display:block; max-width:100%; }
.hidden{ display:none !important; }
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{ animation-duration:0.001ms !important; transition-duration:0.001ms !important; }
}

.eyebrow{
  font-family:var(--font-mono); font-size:11px; letter-spacing:0.14em; text-transform:uppercase;
  color:var(--text-faint);
}

/* ============ Seal glyph ============ */
.seal{
  position:relative; flex:none; border-radius:50%;
  background:var(--surface-2); border:1px solid var(--border);
  display:flex; align-items:center; justify-content:center;
}
.seal-glyph{ width:72%; height:72%; }
.seal-rim{ fill:none; stroke:var(--accent); stroke-width:1.4; opacity:.55; }
.seal-rim-inner{ fill:none; stroke:var(--accent); stroke-width:1; opacity:.35; }
.seal-ticks line{ stroke:var(--accent); stroke-width:1.3; stroke-linecap:round; }
.seal-core{ fill:var(--accent); }

.avatar-picker{ display:flex; align-items:center; gap:10px; }
.avatar-picker .seal{ width:32px; height:32px; }
.avatar-picker input[type="color"]{
  width:32px; height:32px; padding:0; border:1px solid var(--border); border-radius:8px;
  background:none; cursor:pointer;
}
.avatar-picker input[type="color"]::-webkit-color-swatch-wrapper{ padding:2px; }
.avatar-picker input[type="color"]::-webkit-color-swatch{ border:none; border-radius:5px; }

.fingerprint{
  font-family:var(--font-mono); font-size:12.5px; letter-spacing:0.02em; color:var(--text-muted);
  font-variant-numeric:tabular-nums;
}
.fp-row{ display:flex; align-items:center; gap:10px; }

/* ============ App shell ============ */
.app{ display:grid; grid-template-columns:232px 1fr; height:100vh; height:100dvh; overflow:hidden; }
.rail{
  background:var(--surface); border-right:1px solid var(--border);
  display:flex; flex-direction:column; padding:22px 16px; overflow-y:auto;
}
.wordmark{
  font-family:var(--font-display); font-weight:700; font-size:19px; letter-spacing:0.12em;
  color:var(--text); display:flex; align-items:center; gap:10px; padding:0 4px 22px;
}
/* The rail/mobile-topbar wordmark is a <button> (logs out + goes home)
   rather than the login stage's plain <a>, so it needs the usual UA
   button-chrome reset - .wordmark's own rules don't touch border/background. */
.wordmark-home{ border:none; background:none; text-align:left; }
.wordmark-home:hover{ color:var(--accent); }
/* fill/stroke are set as literal attributes inside the #signetMark symbol
   itself (currentColor), not via these descendant classes: a CSS selector
   like `.logo-mark .ring` can never match content cloned in by <use> - it
   crosses the same shadow-tree boundary normal Shadow DOM does, so only
   inherited properties (like `color`, which currentColor resolves to
   here) actually reach it. Confirmed live: without this, the mark
   rendered as two solid black circles instead of the two thin rings. */
.logo-mark{ width:22px; height:22px; flex:none; color:var(--accent); }
.logo-mark-lg{ width:44px; height:44px; }

.device-badge{
  display:flex; align-items:center; gap:10px; padding:10px 10px;
  background:var(--surface-2); border:1px solid var(--border); border-radius:10px;
  margin-bottom:18px;
}
.device-badge .seal{ width:30px; height:30px; }
.device-badge .meta{ min-width:0; }
.device-badge .label{ font-size:11px; color:var(--text-faint); font-family:var(--font-mono); letter-spacing:.06em; text-transform:uppercase; }
.device-badge .fp{ font-family:var(--font-mono); font-size:11.5px; color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

.nav{ display:flex; flex-direction:column; gap:2px; flex:1; }
.nav button{
  display:flex; align-items:center; gap:11px; text-align:left; width:100%;
  padding:9px 10px; border-radius:8px; border:none; background:transparent; color:var(--text-muted);
  font-size:13.5px; font-weight:500; transition:background .12s ease, color .12s ease;
}
.nav button:hover{ background:var(--surface-2); color:var(--text); }
.nav button.active{ background:var(--accent-wash); color:var(--accent-strong); }
.nav button .icon{ width:17px; height:17px; flex:none; stroke:currentColor; fill:none; stroke-width:1.6; }

/* Same base look as .nav button (plain descendant selector already
   covers padding/layout/icon sizing - this only needs to add its own
   identity: a hairline divider above it and a danger tint on hover, so
   it's clearly not just another view in the list). */
.nav button.nav-logout{ margin-top:6px; padding-top:15px; border-top:1px solid var(--border); border-radius:0 0 8px 8px; }
.nav-logout:hover{ background:var(--danger-wash); color:var(--danger); }

.rail-foot{ display:flex; align-items:center; justify-content:space-between; padding-top:14px; border-top:1px solid var(--border); }
.theme-toggle{
  display:flex; align-items:center; gap:8px; padding:7px 9px; border-radius:8px; border:1px solid var(--border);
  background:var(--surface); color:var(--text-muted); font-size:12px;
}
.theme-toggle .dot{ width:9px; height:9px; border-radius:50%; background:var(--accent); }
.theme-toggle:hover{ color:var(--text); border-color:var(--border-strong); }

.content{ height:100%; min-height:0; overflow:hidden; display:flex; flex-direction:column; }
.view{ display:none; flex:1; min-height:0; overflow-y:auto; padding:28px 40px 44px; width:100%; max-width:900px; }
.view.active{ display:flex; flex-direction:column; }
.view[data-view="conversations"]{ padding:0; max-width:none; overflow:hidden; }

.app-foot{
  flex:none; display:flex; align-items:center; gap:10px; padding:9px 22px;
  border-top:1px solid var(--border); background:var(--surface); font-size:11.5px; color:var(--text-muted);
}
.app-foot svg{ width:14px; height:14px; stroke:var(--success); fill:none; stroke-width:1.8; flex:none; }
.app-foot b{ color:var(--text); font-weight:600; }

.view-head{ margin-bottom:22px; }
.view-head h1{ font-family:var(--font-display); font-size:22px; letter-spacing:.02em; font-weight:700; }
.view-head p{ color:var(--text-muted); font-size:13.5px; margin-top:6px; max-width:62ch; }

.card{ background:var(--surface); border:1px solid var(--border); border-radius:12px; }
.stack{ display:flex; flex-direction:column; gap:12px; }
.empty-note{ padding:22px; text-align:center; color:var(--text-muted); font-size:13px; }

.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  padding:8px 14px; border-radius:8px; border:1px solid var(--border-strong);
  background:var(--surface); color:var(--text); font-size:13px; font-weight:500;
  transition:border-color .12s ease, background .12s ease;
}
.btn:hover{ border-color:var(--accent); }
.btn-primary{ background:var(--accent); border-color:var(--accent); color:var(--accent-ink); }
.btn-primary:hover{ background:var(--accent-strong); border-color:var(--accent-strong); }
.btn-quiet{ border-color:transparent; background:transparent; color:var(--text-muted); }
.btn-quiet:hover{ color:var(--text); background:var(--surface-2); border-color:transparent; }
.btn-danger{ color:var(--danger); border-color:var(--border-strong); }
.btn-danger:hover{ border-color:var(--danger); background:var(--danger-wash); }
.btn[disabled]{ opacity:.45; cursor:not-allowed; }
.btn-sm{ padding:6px 11px; font-size:12.5px; }

.pill{
  display:inline-flex; align-items:center; gap:5px; font-family:var(--font-mono); font-size:11px;
  letter-spacing:.04em; text-transform:uppercase; padding:3px 9px; border-radius:20px; font-weight:500;
}
.pill-success{ background:var(--success-wash); color:var(--success); }
.pill-warning{ background:var(--warning-wash); color:var(--warning); }
.pill-danger{ background:var(--danger-wash); color:var(--danger); }

/* ---- Search ---- */
.search-box{
  display:flex; align-items:center; gap:10px; padding:11px 14px; border-radius:10px;
  border:1px solid var(--border-strong); background:var(--surface); margin-bottom:18px;
}
.search-box svg{ width:16px; height:16px; stroke:var(--text-faint); fill:none; stroke-width:1.7; flex:none; }
.search-box input{ border:none; background:none; flex:1; font-size:14px; outline:none; color:var(--text); }
.search-box .k{ font-family:var(--font-mono); font-size:11px; color:var(--text-faint); border:1px solid var(--border); border-radius:5px; padding:1px 6px; }

.result-row{ display:flex; align-items:center; gap:14px; padding:14px 16px; }
.result-row + .result-row{ border-top:1px solid var(--border); }
.result-row .seal{ width:40px; height:40px; }
.result-row .who{ flex:1; min-width:0; }
.result-row .handle{ font-weight:600; font-size:14px; }
.result-row .hint{ font-size:12px; color:var(--text-faint); margin-top:2px; }

/* ---- Conversations layout ---- */
.convo-shell{ display:grid; grid-template-columns:300px 1fr; height:100%; width:100%; background:var(--surface); }

.thread-list{ display:flex; flex-direction:column; min-height:0; border-right:1px solid var(--border); background:var(--surface); }
.thread-list-head{ flex:none; display:flex; align-items:center; gap:8px; padding:16px 14px 12px; }
.thread-search{ flex:1; display:flex; align-items:center; gap:8px; padding:8px 12px; border:1px solid var(--border); border-radius:9px; background:var(--surface-2); }
.thread-search svg{ width:14px; height:14px; stroke:var(--text-faint); fill:none; stroke-width:1.7; flex:none; }
.thread-search input{ border:none; background:none; flex:1; font-size:12.5px; outline:none; color:var(--text); }
.thread-list-head .icon-btn{ border:1px solid var(--border); }

.thread-items{ flex:1; min-height:0; overflow-y:auto; }
.thread-item{ display:flex; align-items:center; gap:12px; padding:13px 14px; width:100%; text-align:left; border:none; background:none; border-bottom:1px solid var(--border); }
.thread-item .seal{ width:36px; height:36px; }
.thread-item:hover{ background:var(--surface-2); }
.thread-item.active{ background:var(--accent-wash); }
.thread-item .who{ min-width:0; flex:1; }
.thread-item .handle{ font-weight:600; font-size:13.5px; display:flex; align-items:center; gap:6px; }
.thread-item .preview{ font-size:12px; color:var(--text-faint); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:2px; }
.thread-item .when{ font-family:var(--font-mono); font-size:10.5px; color:var(--text-faint); flex:none; }

.thread-pane{ display:flex; flex-direction:column; min-width:0; min-height:0; height:100%; overflow:hidden; }
.thread-empty{ flex:1; display:flex; align-items:center; justify-content:center; color:var(--text-faint); font-size:13px; }
.thread-view{ display:none; }
.thread-view.active{ display:flex; flex-direction:column; height:100%; min-height:0; }
.thread-head{ flex:none; display:flex; align-items:center; gap:12px; padding:14px 18px; border-bottom:1px solid var(--border); }
.thread-head .seal{ width:34px; height:34px; }
.thread-head .name{ font-weight:600; font-size:14px; }
.thread-head .status{ font-size:11.5px; color:var(--text-faint); }
.back-btn{ display:none; }

.thread-body{ flex:1; overflow-y:auto; padding:20px 18px; display:flex; flex-direction:column; gap:14px; }
/* Wraps just the message list (app.js's renderThreadMessages target) so a
   re-render only ever touches this subtree, not the composer - but it
   must stay invisible to the box model, or .thread-body's flex/gap rules
   above would only apply to this one wrapper instead of each message. */
.thread-messages{ display:contents; }
.bubble-row{ display:flex; flex-direction:column; max-width:64%; }
.bubble-row.mine{ align-self:flex-end; align-items:flex-end; }
.bubble-row.theirs{ align-self:flex-start; align-items:flex-start; }
.bubble{ padding:10px 13px; border-radius:12px; font-size:13.5px; line-height:1.5; white-space:pre-wrap; word-break:break-word; }
.bubble-row.theirs .bubble{ background:var(--surface-2); border:1px solid var(--border); border-bottom-left-radius:4px; }
.bubble-row.mine .bubble{ background:var(--accent); color:var(--accent-ink); border-bottom-right-radius:4px; }
.bubble-row.mine .bubble.failed{ background:var(--danger-wash); color:var(--danger); border:1px solid var(--danger); }
.bubble-time{ font-family:var(--font-mono); font-size:10px; color:var(--text-faint); margin-top:4px; padding:0 3px; }

.system-note{
  align-self:center; max-width:80%; text-align:center; font-size:12px; color:var(--warning);
  background:var(--warning-wash); border:1px solid var(--warning); border-radius:10px; padding:10px 14px;
  display:flex; flex-direction:column; gap:6px;
}
.system-note .icon-line{ display:flex; align-items:center; justify-content:center; gap:6px; font-family:var(--font-mono); font-size:10.5px; letter-spacing:.06em; text-transform:uppercase; }
.system-note svg{ width:13px; height:13px; stroke:var(--warning); fill:none; stroke-width:2; }
.system-note .fps{ font-family:var(--font-mono); font-size:11px; color:var(--text-muted); }

.attach{
  display:flex; align-items:center; gap:10px; padding:9px 12px; border-radius:9px;
  background:var(--surface-3); border:1px solid var(--border); cursor:pointer;
  position:relative;
}
.attach svg{ width:16px; height:16px; stroke:currentColor; fill:none; stroke-width:1.7; flex:none; }
.attach .meta{ font-size:12px; }
.attach .meta b{ display:block; font-size:12.5px; }
.attach img{ max-width:220px; max-height:220px; border-radius:8px; cursor:zoom-in; display:block; }
.attach .download-image{
  position:absolute; top:6px; right:6px; width:28px; height:28px; border-radius:8px;
  background:rgba(0,0,0,.45); backdrop-filter:blur(2px);
}
.attach .download-image svg{ stroke:#fff; }
.attach .download-image:hover{ background:rgba(0,0,0,.65); }
.attach .download-image:hover svg{ stroke:#fff; }

.reveal-image{ transition:background .12s ease, border-color .12s ease; }
.reveal-image:hover{ background:var(--surface-2); border-color:var(--accent); }
.reveal-image svg{ stroke:var(--accent); }
.reveal-image .meta span{ color:var(--text-muted); }

.img-viewer{
  position:fixed; inset:0; z-index:100; display:flex; align-items:center; justify-content:center;
  padding:32px; opacity:0; pointer-events:none; transition:opacity .15s ease;
}
.img-viewer.open{ opacity:1; pointer-events:auto; }
.img-viewer-scrim{ position:absolute; inset:0; background:rgba(10,10,12,0.82); }
.img-viewer-img{
  position:relative; max-width:min(90vw,900px); max-height:88vh; border-radius:10px;
  box-shadow:0 20px 60px rgba(0,0,0,0.45); cursor:zoom-out;
  transform:scale(.97); transition:transform .15s ease;
}
.img-viewer.open .img-viewer-img{ transform:scale(1); }
.img-viewer-close{
  position:absolute; top:18px; right:18px; background:rgba(0,0,0,0.35); color:#fff;
  border:1px solid rgba(255,255,255,0.2);
}
.img-viewer-close:hover{ background:rgba(0,0,0,0.55); }
.img-viewer-close svg{ width:16px; height:16px; stroke:currentColor; fill:none; stroke-width:2; }
@media (prefers-reduced-motion: reduce){
  .img-viewer, .img-viewer-img{ transition:none; }
}

/* min-height roughly matches a single-line .bubble + .bubble-time's real
   footprint (~56px) - this used to be a lot shorter than an actual
   message, so decoding finishing (this element swapping for a real
   bubble) visibly reflowed every message below it. Centering the
   label/track vertically inside the reserved height keeps this looking
   intentional rather than like empty padding was bolted on. */
.encode-progress{
  align-self:flex-end; width:220px; max-width:100%; min-height:56px; box-sizing:border-box;
  display:flex; flex-direction:column; justify-content:center;
}
.encode-progress.theirs{ align-self:flex-start; }
.encode-progress .label{ display:flex; justify-content:space-between; font-family:var(--font-mono); font-size:10.5px; color:var(--text-faint); margin-bottom:5px; }
.encode-track{ height:5px; border-radius:3px; background:var(--surface-3); overflow:hidden; }
.encode-fill{ height:100%; width:0%; background:var(--accent); border-radius:3px; transition:width .2s ease; }

.composer{ padding:12px 16px 16px; border-top:1px solid var(--border); }
.composer-box{ display:flex; align-items:center; gap:6px; border:1px solid var(--border-strong); border-radius:14px; background:var(--surface-2); padding:6px; transition:border-color .12s ease; }
.composer-box:focus-within{ border-color:var(--accent); }
.composer-box.disabled{ opacity:.55; }
.composer-box input{ flex:1; border:none; background:none; padding:8px 6px; font-size:13.5px; outline:none; }
.icon-btn{ width:32px; height:32px; border-radius:9px; border:none; background:none; display:flex; align-items:center; justify-content:center; flex:none; }
.icon-btn svg{ width:16px; height:16px; stroke:var(--text-muted); fill:none; stroke-width:1.7; }
.icon-btn:hover{ background:var(--surface-3); }
.icon-btn:hover svg{ stroke:var(--text); }
.icon-btn.send{ background:var(--accent); }
.icon-btn.send svg{ stroke:var(--accent-ink); }
.icon-btn.send:hover{ background:var(--accent-strong); }
.icon-btn[disabled]{ opacity:.5; pointer-events:none; }

.thread-head .actions{ margin-left:auto; display:flex; gap:2px; }
.thread-head .icon-btn{ width:30px; height:30px; }
.thread-head .icon-btn svg{ width:15px; height:15px; }

.thread-secure-banner{
  display:flex; align-items:center; gap:12px; padding:11px 13px; border-radius:11px;
  border:1px solid var(--border); background:var(--surface-2); margin-bottom:6px;
}
.thread-secure-banner .seal{ width:32px; height:32px; }
.thread-secure-banner .copy{ flex:1; min-width:0; }
.thread-secure-banner .copy b{ display:block; font-size:12.5px; }
.thread-secure-banner .copy span{ font-size:11.5px; color:var(--text-muted); }

.day-divider{
  align-self:center; font-family:var(--font-mono); font-size:10px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--text-faint); border:1px solid var(--border); border-radius:999px; padding:3px 12px; margin:2px 0 4px;
}

.bubble-with-avatar{ display:flex; gap:8px; align-items:flex-end; }
.bubble-with-avatar .seal{ width:22px; height:22px; margin-bottom:2px; }

/* ---- Devices ---- */
.device-card{ display:flex; align-items:center; gap:16px; padding:20px; }
.device-card .seal{ width:56px; height:56px; }
.device-card .info{ flex:1; min-width:0; }
.device-card .role{ font-family:var(--font-mono); font-size:10.5px; letter-spacing:.08em; text-transform:uppercase; color:var(--text-faint); }
.device-card .name{ font-weight:600; font-size:15px; margin-top:2px; }
.current-device-badge{
  display:block; width:max-content; margin-top:6px; padding:2px 8px; border-radius:99px;
  background:color-mix(in srgb, var(--accent) 18%, transparent); color:var(--accent);
  font-family:var(--font-mono); font-size:10px; font-weight:600; letter-spacing:.03em; text-transform:uppercase;
}
.device-card .actions{ display:flex; gap:8px; flex:none; }
.device-empty{ padding:22px; text-align:center; }
.device-empty .seal{ width:48px; height:48px; margin:0 auto 12px; opacity:.6; }
.device-empty p{ font-size:13px; color:var(--text-muted); max-width:44ch; margin:6px auto 14px; }

.warn-box{ display:flex; gap:10px; padding:12px 14px; border-radius:10px; background:var(--danger-wash); border:1px solid var(--danger); color:var(--danger); font-size:12.5px; margin-top:14px; }
.warn-box svg{ width:15px; height:15px; stroke:var(--danger); fill:none; stroke-width:1.8; flex:none; margin-top:1px; }

/* ---- Account ---- */
.row-between{ display:flex; align-items:center; justify-content:space-between; padding:16px 18px; }
.row-between + .row-between{ border-top:1px solid var(--border); }
.row-label{ font-size:11px; color:var(--text-faint); font-family:var(--font-mono); letter-spacing:.06em; text-transform:uppercase; }
.row-value{ font-size:14.5px; font-weight:500; margin-top:3px; }

.nudge-card{ display:flex; gap:14px; padding:18px; margin-top:16px; border:1px dashed var(--accent); border-radius:12px; background:var(--accent-wash); }
.nudge-card svg{ width:22px; height:22px; stroke:var(--accent); fill:none; stroke-width:1.6; flex:none; }
.nudge-card h3{ font-size:14px; font-weight:600; }
.nudge-card p{ font-size:12.5px; color:var(--text-muted); margin-top:4px; max-width:48ch; }

/* ============ Pairing / login hero ============ */
.stage{
  min-height:100vh; min-height:100dvh; display:flex; align-items:center; justify-content:center; flex-direction:column;
  background:
    radial-gradient(circle at 50% 18%, var(--accent-wash), transparent 55%),
    var(--bg);
  padding:40px 20px; text-align:center; overflow-y:auto;
}
.stage-mark{ width:132px; height:132px; margin-bottom:26px; position:relative; }
.stage-mark .seal{ width:100%; height:100%; background:var(--surface); box-shadow:var(--shadow); }
.stage-mark .seal-glyph{ width:66%; height:66%; }
.stage-mark.pressed .seal{ animation:press .5s ease; }
@keyframes press{ 0%{ transform:scale(1); } 45%{ transform:scale(0.9) translateY(3px); } 100%{ transform:scale(1); } }
.stage-mark .ring{
  position:absolute; inset:-14px; border-radius:50%; border:1px solid var(--accent);
  opacity:0; transform:scale(0.7);
}
.stage-mark.pressed .ring{ animation:impress .7s ease forwards .15s; }
@keyframes impress{ 0%{ opacity:.9; transform:scale(0.7); } 100%{ opacity:0; transform:scale(1.35); } }

.stage h1{ font-family:var(--font-display); font-size:30px; letter-spacing:.18em; font-weight:700; }
.stage .tagline{ color:var(--text-muted); font-size:14px; margin-top:8px; max-width:42ch; }

.stage-panel{ margin-top:30px; width:340px; max-width:100%; }
.stage-mode{ display:flex; gap:4px; padding:3px; border-radius:10px; background:var(--surface-2); border:1px solid var(--border); margin-bottom:14px; }
.stage-mode button{ flex:1; padding:8px; border-radius:8px; border:none; background:none; color:var(--text-muted); font-size:12.5px; font-weight:500; }
.stage-mode button.active{ background:var(--surface); color:var(--text); box-shadow:var(--shadow); }
.stage-step{ display:none; flex-direction:column; gap:12px; }
.stage-step.active{ display:flex; }
.stage-panel input{
  width:100%; text-align:center; padding:11px 14px; border-radius:10px; border:1px solid var(--border-strong);
  background:var(--surface); font-size:14px; outline:none; font-family:var(--font-mono);
}
.stage-panel input:focus{ border-color:var(--accent); }
.stage-panel .btn{ width:100%; padding:11px 14px; }
.stage-hint{ font-size:11.5px; color:var(--text-faint); }
.stage-status{ display:flex; align-items:center; justify-content:center; gap:8px; font-family:var(--font-mono); font-size:12px; color:var(--text-muted); }
.spinner{ width:12px; height:12px; border-radius:50%; border:2px solid var(--border); border-top-color:var(--accent); animation:spin .8s linear infinite; }
@keyframes spin{ to{ transform:rotate(360deg); } }
.stage-success .fp-row{ justify-content:center; margin-top:4px; }
.stage-success .seal{ width:44px; height:44px; }
.stage-error{ display:flex; flex-direction:column; gap:10px; padding:14px; border-radius:10px; background:var(--danger-wash); border:1px solid var(--danger); color:var(--danger); font-size:13px; }

/* ---- Mobile chrome: a slim top bar + a real bottom tab bar, both       ---- */
/* ---- separate markup from the desktop rail, not the same nav squeezed  ---- */
/* ---- sideways. Hidden on desktop; the media query below turns them on. ---- */
.mobile-topbar{ display:none; }
.bottom-nav{ display:none; }

/* ---- Responsive ---- */
@media (max-width: 880px){
  .app{ grid-template-columns:1fr; grid-template-rows:auto 1fr auto; }
  .rail{ display:none; }

  .mobile-topbar{
    display:flex; align-items:center; gap:10px; padding:10px 14px;
    border-bottom:1px solid var(--border); background:var(--surface);
  }
  .mobile-topbar .wordmark{ padding:0; font-size:15px; gap:7px; }
  .mobile-topbar .logo-mark{ width:18px; height:18px; }
  .mobile-topbar .spacer{ flex:1; }
  .mobile-topbar .seal{ width:26px; height:26px; }
  .mobile-topbar .icon-btn{ width:30px; height:30px; border:1px solid var(--border); }
  .mobile-topbar .icon-btn .dot{ width:9px; height:9px; border-radius:50%; background:var(--accent); }

  .view{ padding:20px 16px 32px; max-width:none; }

  /* Conversations: list and thread swap, one full-bleed pane at a time */
  .convo-shell{ display:block; height:100%; }
  .thread-list{ height:100%; }
  .thread-pane{ display:none; }
  .convo-shell.show-thread .thread-list{ display:none; }
  .convo-shell.show-thread .thread-pane{ display:flex; }
  .back-btn{ display:flex; }

  .app-foot{ padding:8px 14px; }
  .app-foot div{ display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }

  /* A real grid row pinned to the viewport bottom, not position:fixed —   */
  /* the app shell is already a fixed-height, non-scrolling grid (100dvh), */
  /* so the last row stays put on its own; nothing to overlay or reserve   */
  /* padding for underneath it.                                           */
  .bottom-nav{
    display:flex; justify-content:space-around; align-items:stretch;
    border-top:1px solid var(--border); background:var(--surface);
    padding:7px 2px calc(7px + env(safe-area-inset-bottom));
  }
  .bottom-nav button{
    display:flex; flex-direction:column; align-items:center; gap:3px;
    background:none; border:none; color:var(--text-muted);
    font-family:var(--font-mono); font-size:9.5px; padding:3px 6px; border-radius:8px;
    position:relative; flex:1;
  }
  .bottom-nav button.active{ color:var(--accent); }
  .bottom-nav button .icon{ width:19px; height:19px; stroke:currentColor; fill:none; stroke-width:1.8; }
}
