/* Shared by index.html (landing) and flash.html - NOT loaded alongside
   app.css (that file's body{overflow:hidden} is built for the fixed-height
   chat shell; these are ordinary scrolling pages). Token values are kept
   in sync with app.css by hand - there's no build step to share them
   through, and every other page in web/ already inlines its own copy of
   the signet mark SVG for the same reason. */
: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);
}

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

/* ---- Shared marks/primitives (mirrors app.css) ---- */
.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-core{ fill:var(--accent); }

.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;
}
/* 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); }

.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  padding:11px 18px; border-radius:10px; border:1px solid var(--border-strong);
  background:var(--surface); color:var(--text); font-size:14px; font-weight:500;
  text-decoration:none; 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); font-weight:600; }
.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[disabled]{ opacity:.45; cursor:not-allowed; pointer-events:none; }
.card{ background:var(--surface); border:1px solid var(--border); border-radius:14px; }

.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); flex:none; }
.theme-toggle:hover{ color:var(--text); border-color:var(--border-strong); }
.spinner{ width:13px; height:13px; border-radius:50%; border:2px solid var(--border); border-top-color:var(--accent); animation:spin .8s linear infinite; flex:none; }
@keyframes spin{ to{ transform:rotate(360deg); } }

/* ---- Site chrome ---- */
.site-nav{
  position:relative; display:flex; align-items:center; justify-content:space-between;
  max-width:1040px; margin:0 auto; padding:22px 24px;
}
.site-nav a.wordmark{ text-decoration:none; }
.site-nav-links{ display:flex; align-items:center; gap:10px; }

/* Hidden on desktop - the media query below turns this into a hamburger
   that opens .site-nav-links as a dropdown, same "separate mobile
   markup" approach app.css uses for its own rail/bottom-nav split. */
.menu-toggle{
  display:none; flex-direction:column; justify-content:center; align-items:center; gap:4px;
  width:36px; height:36px; border:1px solid var(--border); border-radius:8px;
  background:var(--surface); padding:0; flex:none;
}
.menu-toggle span{ display:block; width:16px; height:1.6px; background:var(--text-muted); transition:transform .15s ease, opacity .15s ease; }
.menu-toggle.active span:nth-child(1){ transform:translateY(5.6px) rotate(45deg); }
.menu-toggle.active span:nth-child(2){ opacity:0; }
.menu-toggle.active span:nth-child(3){ transform:translateY(-5.6px) rotate(-45deg); }

.site-footer{
  border-top:1px solid var(--border); margin-top:64px;
}
.site-footer-inner{
  max-width:1040px; margin:0 auto; padding:28px 24px 40px;
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:14px;
}
.site-footer .wordmark{ font-size:15px; }
.site-footer p{ color:var(--text-faint); font-size:12.5px; max-width:46ch; }
.site-footer-links{ display:flex; gap:18px; font-size:13px; }
.site-footer-links a{ color:var(--text-muted); text-decoration:none; }
.site-footer-links a:hover{ color:var(--accent); }

@media (max-width:640px){
  .site-nav{ padding:16px 18px; }
  .site-footer-inner{ padding:24px 18px 32px; }

  .menu-toggle{ display:flex; }
  .site-nav-links{
    display:none; flex-direction:column; align-items:stretch; gap:8px;
    position:absolute; top:100%; left:0; right:0; margin-top:1px;
    padding:14px 18px 18px; background:var(--surface); border-bottom:1px solid var(--border);
    box-shadow:var(--shadow); z-index:20;
  }
  .site-nav-links.show{ display:flex; }
  .site-nav-links .btn{ width:100%; }
  .site-nav-links .theme-toggle{ align-self:flex-start; }
}

/* ============ Landing hero ============ */
.hero{
  position:relative; text-align:center; padding:56px 24px 0;
  background:
    radial-gradient(circle at 50% 0%, var(--accent-wash), transparent 60%),
    var(--bg);
  overflow:hidden;
}
.hero-inner{
  max-width:1040px; margin:0 auto; display:flex; flex-direction:column-reverse;
  align-items:center; gap:36px;
}
.hero-content{ min-width:0; }
.hero-image{ width:100%; max-width:420px; align-self:center; position:relative; }
/* .hero-inner defaults to column-reverse (below) so the split-layout
   breakpoint further down can turn into a plain row without a DOM/CSS
   order mismatch - below that breakpoint it's overridden back to a
   normal column here, so the mockup renders where it sits in the DOM:
   under the copy/CTAs, not above them pushing everything below the fold.
   The floating badge is dropped at this width instead of shrunk - at
   phone widths it has no room that doesn't either clip against .hero's
   overflow:hidden or sit on top of the composer input beneath it. */
@media (max-width:900px){
  .hero-inner{ flex-direction:column; }
  .hero-image{ max-width:360px; margin:24px auto 0; }
}

/* A live-looking mock of the actual app.html chat UI - reuses the real
   product's bubble/seal styling (mirrored from app.css, since this page
   doesn't load it) so a first-time visitor sees "messaging app" at a
   glance instead of only reading it in the lede. The token/seal product
   photo moves to a small supporting badge (.chat-mock-badge below)
   instead of carrying the whole hero on its own. */
.chat-mock{
  background:var(--surface); border:1px solid var(--border); border-radius:16px;
  box-shadow:var(--shadow); overflow:hidden;
}
.chat-mock-bar{ display:flex; align-items:center; gap:5px; padding:10px 14px; border-bottom:1px solid var(--border); background:var(--surface-2); }
.chat-mock-dot{ width:6px; height:6px; border-radius:50%; background:var(--border-strong); }
.chat-mock-url{ margin-left:6px; font-family:var(--font-mono); font-size:10px; color:var(--text-faint); }
.chat-mock-head{ display:flex; align-items:center; gap:10px; padding:13px 16px; border-bottom:1px solid var(--border); }
.chat-mock-head .seal{ width:30px; height:30px; }
.chat-mock-head .name{ font-weight:600; font-size:13px; }
.chat-mock-head .status{ display:flex; align-items:center; gap:5px; font-size:11px; color:var(--text-faint); margin-top:1px; }
.chat-mock-head .status::before{ content:""; width:6px; height:6px; border-radius:50%; background:var(--success); }
.chat-mock-body{ display:flex; flex-direction:column; gap:9px; padding:16px; }
.chat-mock .bubble-row{ display:flex; flex-direction:column; max-width:80%; }
.chat-mock .bubble-row.mine{ align-self:flex-end; align-items:flex-end; }
.chat-mock .bubble-row.theirs{ align-self:flex-start; align-items:flex-start; }
.chat-mock .bubble{ padding:9px 12px; border-radius:12px; font-size:12.5px; line-height:1.45; }
.chat-mock .bubble-row.theirs .bubble{ background:var(--surface-2); border:1px solid var(--border); border-bottom-left-radius:4px; }
.chat-mock .bubble-row.mine .bubble{ background:var(--accent); color:var(--accent-ink); border-bottom-right-radius:4px; }
.chat-mock .bubble-time{ font-family:var(--font-mono); font-size:9.5px; color:var(--text-faint); margin-top:3px; padding:0 2px; }
.chat-mock-composer{ display:flex; align-items:center; gap:8px; padding:11px 14px; border-top:1px solid var(--border); }
.chat-mock-input{ flex:1; padding:8px 12px; border-radius:10px; background:var(--surface-2); border:1px solid var(--border); font-size:12px; color:var(--text-faint); }
.chat-mock-send{ width:28px; height:28px; border-radius:8px; background:var(--accent); display:flex; align-items:center; justify-content:center; flex:none; }
.chat-mock-send svg{ width:13px; height:13px; stroke:var(--accent-ink); fill:none; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }

/* Overlaps the top-right corner (not the bottom, where the composer's
   placeholder text lives) so the floating badge never covers the one
   piece of the mock that has to stay legible. */
.chat-mock-badge{
  position:absolute; right:-20px; top:-20px; width:150px;
  display:flex; align-items:center; gap:9px; padding:8px; border-radius:13px;
  background:var(--surface); border:1px solid var(--border); box-shadow:var(--shadow);
}
.chat-mock-badge img{ width:44px; height:44px; border-radius:8px; object-fit:cover; flex:none; }
.chat-mock-badge span{ font-size:11px; line-height:1.35; color:var(--text-muted); font-weight:500; }
@media (max-width:900px){
  .chat-mock-badge{ display:none; }
}
@media (min-width:901px){
  .hero-inner{ flex-direction:row; text-align:left; gap:56px; }
  .hero-content{ flex:1; }
  .hero-content .hero-mark{ margin:0 0 22px; }
  .hero-content .hero-tagline{ margin:14px 0 0; }
  .hero-content .lede{ margin:14px 0 0; }
  .hero-content .hero-ctas{ justify-content:flex-start; }
  .hero-content .hero-flash-link{ justify-content:flex-start; }
  .hero-image{ flex:1; max-width:480px; }
}
.hero-mark{ width:112px; height:112px; margin:0 auto 22px; position:relative; cursor:pointer; }
.hero-mark .seal{ width:100%; height:100%; background:var(--surface); box-shadow:var(--shadow); }
.hero-mark .seal-glyph{ width:66%; height:66%; }
.hero-mark .ring{
  position:absolute; inset:-14px; border-radius:50%; border:1px solid var(--accent);
  opacity:0; transform:scale(0.7);
}
/* Fires once on load (JS adds .pressed on first frame) and replays on click/
   Enter/Space (JS toggles the class off and back on) - no ambient/looping
   animation otherwise. */
.hero-mark.pressed .seal{ animation:heroPress 1.1s cubic-bezier(.2,.8,.2,1); }
@keyframes heroPress{ 0%{ transform:scale(1); } 40%{ transform:scale(0.88) translateY(3px); } 100%{ transform:scale(1); } }
.hero-mark.pressed .ring{ animation:heroImpress 1.3s ease forwards .2s; }
@keyframes heroImpress{ 0%{ opacity:.9; transform:scale(0.7); } 100%{ opacity:0; transform:scale(1.7); } }

.hero h1{ font-family:var(--font-display); font-size:42px; letter-spacing:.16em; font-weight:700; }
.hero-tagline{
  font-family:var(--font-sans); font-weight:600; font-size:19px; color:var(--text);
  max-width:45ch; margin:18px auto 0;
}
.hero .lede{
  color:var(--text-muted); font-size:15.5px; max-width:46ch; margin:6px auto 0;
}
.hero .lede b{ color:var(--text); font-weight:600; }
.hero-ctas{ display:flex; align-items:center; justify-content:center; gap:10px; margin-top:28px; flex-wrap:wrap; }
.hero-ctas .btn{ min-width:150px; }
.hero-flash-link{
  display:inline-flex; align-items:center; gap:6px; margin-top:18px;
  font-size:13px; color:var(--text-faint); text-decoration:none;
}
.hero-flash-link:hover{ color:var(--accent); }
.hero-flash-link svg{ width:14px; height:14px; stroke:currentColor; fill:none; stroke-width:1.8; }

/* ============ Hero flow illustration ============ */
/* Sits under the whole hero-inner (copy + chat mock), full width up to the
   site's usual 1040px content measure. Two .flow-row groups (Alice through
   the server; the server back out to Bob) - on desktop that grouping is
   inert (.flow-row is display:contents, so both rows' items lay out as one
   flat sequence directly inside .flow) but it's what lets the mobile
   breakpoint below fold the diagram onto a second line exactly at the
   server, instead of leaving that decision to wherever flex-wrap happens
   to run out of width, which can just as easily split a connector from
   the node it points at. The two "sealed by the token" connectors carry
   an "Encrypted" label since that's the one fact this diagram exists to
   show (everything past the sender's own token is ciphertext, including
   in transit through the server). */
.flow{
  display:flex; align-items:flex-start; justify-content:center; flex-wrap:wrap;
  gap:8px 2px; max-width:1040px; margin:0 auto; padding:60px 24px 10px;
}
.flow-row{ display:contents; }
.flow-node{ display:flex; flex-direction:column; align-items:center; width:104px; flex:none; text-align:center; }
.flow-node-server{ width:140px; }
.flow-icon{
  position:relative; width:56px; height:56px; border-radius:50%; flex:none;
  background:var(--surface); border:1px solid var(--border); box-shadow:var(--shadow);
  display:flex; align-items:center; justify-content:center;
}
.flow-icon > svg:first-child{ width:26px; height:26px; stroke:var(--accent); fill:none; stroke-width:1.7; }
.flow-badge{
  position:absolute; right:-5px; bottom:-5px; width:20px; height:20px; padding:3px; box-sizing:border-box;
  border-radius:50%; background:var(--surface); border:1px solid var(--border);
  stroke:var(--accent-strong); fill:none; stroke-width:2;
}
.flow-label{ font-size:12.5px; font-weight:600; margin-top:10px; }
.flow-sublabel{ font-family:var(--font-mono); font-size:10px; color:var(--text-faint); margin-top:2px; }
.flow-caption{ font-size:11px; color:var(--text-muted); margin-top:6px; line-height:1.4; }

.flow-arrow{ width:24px; height:1px; background:var(--border-strong); position:relative; margin:27px 2px 0; flex:none; }
.flow-arrow::after{
  content:""; position:absolute; right:0; top:0; width:6px; height:6px;
  border-right:1.6px solid var(--border-strong); border-bottom:1.6px solid var(--border-strong);
  transform:translateY(-50%) rotate(-45deg);
}
.flow-segment{ display:flex; flex-direction:column; align-items:center; width:84px; flex:none; margin-top:27px; }
.flow-segment-label{ font-family:var(--font-mono); font-size:9.5px; color:var(--accent); margin-bottom:5px; white-space:nowrap; }
.flow-line{
  width:100%; height:1px; position:relative;
  background:repeating-linear-gradient(to right, var(--border-strong) 0 5px, transparent 5px 9px);
}
.flow-line::after{
  content:""; position:absolute; right:-1px; top:0; width:6px; height:6px;
  border-right:1.6px solid var(--border-strong); border-bottom:1.6px solid var(--border-strong);
  transform:translateY(-50%) rotate(-45deg);
}
/* Below 720px, .flow-row stops being inert: .flow switches to a plain
   centered column of its two rows, and each row becomes its own nowrap
   flex line, so a row can only ever shrink internally, never split across
   the fold. Everything inside a row shrinks to fit - smaller icons, tighter
   gaps - rather than wrapping, since a mid-row wrap would reintroduce the
   same "connector stranded from its node" problem this structure exists to
   avoid. Connector margin-top (27px in the base rule, offsetting them to
   the vertical middle of the full-size 56px icon) is reset to 0 and
   align-items switched to center so they re-center against the smaller
   icons below without a second hand-tuned offset to keep in sync. */
@media (max-width:720px){
  .flow{ flex-direction:column; align-items:center; gap:18px; padding:40px 20px 52px; }
  .flow-row{ display:flex; flex-wrap:nowrap; align-items:center; justify-content:center; gap:4px; width:100%; }
  .flow-node{ width:68px; }
  .flow-node-server{ width:96px; }
  .flow-icon{ width:42px; height:42px; }
  .flow-icon > svg:first-child{ width:19px; height:19px; }
  .flow-badge{ width:16px; height:16px; padding:2.5px; }
  .flow-label{ font-size:10.5px; margin-top:7px; }
  .flow-sublabel{ font-size:8.5px; }
  .flow-caption{ font-size:9px; }
  .flow-arrow{ width:12px; margin:0; }
  .flow-segment{ width:48px; margin-top:0; }
  .flow-segment-label{ font-size:8px; }
}
@media (max-width:360px){
  .flow-node{ width:60px; }
  .flow-node-server{ width:84px; }
  .flow-segment{ width:40px; }
}

/* ============ How it works ============ */
.section{ max-width:1040px; margin:0 auto; padding:64px 24px; }
.section-head{ text-align:center; max-width:56ch; margin:0 auto 40px; }
.section-head .eyebrow{
  font-family:var(--font-mono); font-size:11px; letter-spacing:.16em; text-transform:uppercase; color:var(--accent);
}
.section-head h2{ font-family:var(--font-display); font-size:24px; font-weight:700; margin-top:10px; }
.steps-h2 span{ color:var(--accent); font-weight:400; margin:0 4px; }
.section-head p{ color:var(--text-muted); font-size:14px; margin-top:10px; }

.steps{ display:grid; grid-template-columns:repeat(3, 1fr); gap:20px; counter-reset:step; }
.step{ padding:26px 22px; position:relative; }
.step-img{ width:100%; max-width:220px; margin:18px auto 0; }
.step-num{
  font-family:var(--font-mono); font-size:12px; color:var(--accent); letter-spacing:.06em;
}
.step h3{ font-size:16px; font-weight:600; margin-top:12px; }
.step p{ color:var(--text-muted); font-size:13.5px; margin-top:8px; }
.step-connector{
  position:absolute; top:38px; left:100%; width:20px; height:1px; background:var(--border-strong);
}
.step:last-child .step-connector{ display:none; }

.feature-grid{ display:grid; grid-template-columns:repeat(3, 1fr); gap:16px; }
.feature{ padding:22px; }
.feature svg{ width:20px; height:20px; stroke:var(--accent); fill:none; stroke-width:1.7; }
.feature h3{ font-size:14.5px; font-weight:600; margin-top:14px; }
.feature p{ color:var(--text-muted); font-size:13px; margin-top:6px; }

/* ============ Closing CTA ============ */
/* The one other gold button on the page besides the hero's "See how it
   works" - by the time a visitor scrolls this far they've read the pitch,
   so the funnel inverts: conversion, not explanation, is the right primary
   action here. Nothing else nearby competes with it (nav's Register is
   plain-styled precisely so it doesn't), keeping "one gold button per
   view" true at both ends of the page. */
.cta-band{
  text-align:center; padding:64px 24px; margin-top:8px;
  background:
    radial-gradient(circle at 50% 100%, var(--accent-wash), transparent 60%),
    var(--surface);
  border-top:1px solid var(--border); border-bottom:1px solid var(--border);
}
.cta-band-inner{ max-width:480px; margin:0 auto; }
.cta-band h2{ font-family:var(--font-display); font-size:24px; font-weight:700; }
.cta-band p{ color:var(--text-muted); font-size:14px; margin-top:10px; }
.cta-band-actions{ display:flex; align-items:center; justify-content:center; gap:10px; margin-top:24px; flex-wrap:wrap; }
.cta-band-actions .btn{ min-width:150px; }

@media (max-width:800px){
  .hero h1{ font-size:32px; }
  .steps, .feature-grid{ grid-template-columns:1fr; }
  .step-connector{ display:none; }
  .section{ padding:48px 20px; }
}

/* ============ Flash page ============ */
.flash-head{ max-width:640px; margin:0 auto; padding:48px 24px 8px; text-align:center; }
.flash-head h1{ font-family:var(--font-display); font-size:28px; font-weight:700; }
.flash-head p{ color:var(--text-muted); font-size:14.5px; margin-top:12px; }
.flash-note{
  display:flex; gap:10px; text-align:left; padding:12px 14px; border-radius:10px;
  background:var(--surface-2); border:1px solid var(--border); font-size:12.5px; color:var(--text-muted);
  margin-top:20px;
}
.flash-note svg{ width:15px; height:15px; stroke:var(--text-faint); fill:none; stroke-width:1.8; flex:none; margin-top:1px; }

.board-gallery{ display:grid; grid-template-columns:repeat(3, 1fr); gap:14px; max-width:640px; margin:24px auto 0; padding:0 24px; }
.board-card{ padding:18px 14px 20px; text-align:center; }
.board-card img{ height:92px; width:100%; margin:0 auto 12px; object-fit:contain; }
.board-card h3{ font-size:13.5px; font-weight:600; }
.board-card .badge{
  display:inline-block; margin-top:7px; padding:3px 9px; border-radius:99px;
  font-family:var(--font-mono); font-size:10px; letter-spacing:.03em;
}
.board-card .badge-ok{ background:var(--success-wash); color:var(--success); }
.board-card .badge-preflashed{ background:var(--accent-wash); color:var(--accent-strong); }
.board-card p{ color:var(--text-muted); font-size:11.5px; margin-top:8px; }
@media (max-width:640px){
  .board-gallery{ grid-template-columns:1fr; max-width:340px; }
}

.flash-panel{ max-width:560px; margin:28px auto 80px; padding:0 24px; }
.flash-card{ padding:28px; }
.flash-step{ display:none; flex-direction:column; gap:14px; text-align:center; }
.flash-step.active{ display:flex; }
.flash-status{ display:flex; align-items:center; justify-content:center; gap:9px; font-family:var(--font-mono); font-size:13px; color:var(--text-muted); }

.chip-result{ display:flex; align-items:center; gap:14px; padding:14px 16px; border-radius:10px; background:var(--surface-2); border:1px solid var(--border); text-align:left; }
.chip-result svg{ width:26px; height:26px; stroke:var(--accent); fill:none; stroke-width:1.5; flex:none; }
.chip-result .name{ font-weight:600; font-size:15px; }
.chip-result .detail{ font-size:12px; color:var(--text-muted); margin-top:2px; }

.flash-files{ display:flex; flex-direction:column; gap:10px; text-align:left; }
.flash-file-row{ display:flex; align-items:center; gap:10px; }
.flash-file-row .label{ font-family:var(--font-mono); font-size:11.5px; color:var(--text-muted); width:112px; flex:none; }
.flash-track{ flex:1; height:6px; border-radius:99px; background:var(--surface-3); overflow:hidden; }
.flash-fill{ height:100%; background:var(--accent); width:0%; transition:width .15s ease; }
.flash-file-row .pct{ font-family:var(--font-mono); font-size:11px; color:var(--text-faint); width:34px; text-align:right; flex:none; }

.flash-advanced{ text-align:left; font-size:12.5px; }
.flash-advanced summary{ cursor:pointer; color:var(--text-muted); }
.flash-advanced summary:hover{ color:var(--text); }
.flash-advanced .warn{ display:flex; gap:8px; align-items:flex-start; margin-top:10px; padding:10px 12px; border-radius:8px; background:var(--warning-wash); border:1px solid var(--warning); color:var(--warning); }
.flash-advanced .warn svg{ width:14px; height:14px; stroke:var(--warning); fill:none; stroke-width:1.8; flex:none; margin-top:1px; }
.flash-advanced label{ display:flex; align-items:center; gap:8px; margin-top:10px; color:var(--text-muted); }

.flash-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; text-align:left; }

/* The one deliberately non-adaptive surface on the site: a real serial
   console reads as itself only in dark-on-mono, in either site theme -
   the same reason a hardware UART monitor doesn't reskin for daytime. */
.terminal{
  background:#0B0D10; color:#C9D1D9; border-radius:10px; padding:14px 16px;
  font-family:var(--font-mono); font-size:12px; line-height:1.6;
  height:220px; overflow-y:auto; text-align:left; white-space:pre-wrap; word-break:break-all;
}
.terminal .line-e{ color:#E5837A; }
.terminal .line-w{ color:#E0B67C; }
.terminal .line-i{ color:#7FBF9B; }

/* ============ Legal notice ============ */
/* Narrower than .section's 1040px - long-form paragraphs read better at a
   shorter line length than the landing page's marketing copy does. */
.legal-page{ max-width:720px; margin:0 auto; padding:48px 24px 80px; }
.legal-page .eyebrow{
  font-family:var(--font-mono); font-size:11px; letter-spacing:.16em; text-transform:uppercase; color:var(--accent);
}
.legal-page h1{ font-family:var(--font-display); font-size:32px; font-weight:700; margin-top:10px; }
.legal-page .updated{ color:var(--text-faint); font-size:12.5px; margin-top:10px; font-family:var(--font-mono); }
.legal-page .intro{ color:var(--text-muted); font-size:15px; line-height:1.75; margin-top:26px; }
.legal-page section{ margin-top:36px; }
.legal-page h2{ font-family:var(--font-display); font-size:19px; font-weight:700; display:flex; align-items:baseline; gap:10px; }
.legal-page h2 .num{ color:var(--accent); font-family:var(--font-mono); font-size:13px; font-weight:500; }
.legal-page p{ color:var(--text-muted); font-size:14.5px; line-height:1.75; margin-top:14px; }
.legal-page ul{ margin-top:14px; }
.legal-page li{ color:var(--text-muted); font-size:14.5px; line-height:1.75; margin-top:8px; padding-left:20px; position:relative; }
.legal-page li::before{ content:"—"; position:absolute; left:0; color:var(--accent); }
.legal-page a{ color:var(--accent); text-decoration:underline; text-underline-offset:2px; }
.legal-page a:hover{ color:var(--accent-strong); }
