/* ==========================================================================
   STONKFUNBOT
   Dark, financial-terminal aesthetic. Restrained accents, thin rules, real
   numbers set in monospace. No web fonts: the system UI + mono stacks render
   instantly and cost zero requests.
   ========================================================================== */

:root {
  /* Surfaces — near-black through charcoal.
     Deepened to the Grok build's ground: a darker base makes the same accent
     read as light rather than as another dark tone, which is what let its
     accents glow without raising their saturation. */
  --bg:        #060a07;
  --bg-alt:    #090e0a;
  --surface:   #0c120d;
  --surface-2: #121a13;
  /* Rules as translucent green-white rather than a fixed grey. A hairline
     then sits at a constant contrast above whatever surface it lands on,
     instead of being tuned for one of them and disappearing on the others. */
  --line:      rgb(190 255 205 / 0.10);
  --line-soft: rgb(190 255 205 / 0.055);

  /* Text */
  --text:      #eef6ef;
  --text-dim:  #a3b8a7;
  --text-mute: #64796a;

  /* Brand accent (redesign 2026-10-31). Stonk green carries identity —
     buttons, focus, active state, the live pulse. It is a brighter, purer
     green than the market-up teal below, and market numbers always carry
     their own sign/format, so the palette never has to lie to stay
     on-brand: a filled green button and a green +2.4% are different
     objects doing different jobs. */
  --brand:      #00e065;
  --brand-hi:   #4be584;
  --brand-dim:  #00a34c;
  --brand-glow: rgba(0, 224, 101, 0.15);
  --brand-line: rgba(0, 224, 101, 0.32);

  /* Market accents — semantic, never decorative. Teal-green means up, red
     means down, and neither is ever used to make something look nice. */
  --green:     #2ee6a8;
  --green-dim: #17b981;
  --green-glow: rgba(46, 230, 168, 0.12);
  --red:       #f6465d;
  --amber:     #f5a524;

  /* Nav backdrop — extracted so the light theme can override it. */
  --nav-bg: rgba(6, 10, 7, 0.85);

  /* Scrim colour for the hero section. */
  --scrim: 6, 10, 7;

  /* Elevation. Three steps, no more — a terminal has surfaces, not a stack of
     floating cards. Dark shadows are near-black and wide: on a #07070b ground
     a tight shadow is invisible, so depth here comes from a large soft pool
     rather than a drop. --ring is the one focus treatment; every interactive
     element uses it so keyboard focus looks deliberate instead of per-widget. */
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.45);
  --shadow-2: 0 2px 4px rgba(0, 0, 0, 0.4), 0 8px 24px -12px rgba(0, 0, 0, 0.7);
  --shadow-3: 0 4px 8px rgba(0, 0, 0, 0.45), 0 24px 56px -24px rgba(0, 0, 0, 0.85);
  --ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--brand);

  --radius: 6px;
  --wrap: 1180px;

  --mono: ui-monospace, SFMono-Regular, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ======================== LIGHT THEME ======================== */

[data-theme="light"] {
  --bg:        #f3f6f2;
  --bg-alt:    #e9efe7;
  --surface:   #ffffff;
  --surface-2: #eef3ec;
  /* Same idea inverted: translucent ink, so a rule holds its weight on white
     and on the green-grey ground alike. */
  --line:      rgb(16 40 22 / 0.14);
  --line-soft: rgb(16 40 22 / 0.07);

  --text:      #0e1a10;
  --text-dim:  #43563f;
  --text-mute: #72856f;

  --brand:      #00a34c;
  --brand-hi:   #008f42;
  --brand-dim:  #00c95e;
  --brand-glow: rgba(0, 163, 76, 0.10);
  --brand-line: rgba(0, 163, 76, 0.25);

  --green:     #0da271;
  --green-dim: #0a7d57;
  --green-glow: rgba(13, 162, 113, 0.08);
  --red:       #d92d20;
  --amber:     #b97d06;

  --nav-bg: rgba(243, 246, 242, 0.88);
  --scrim: 243, 246, 242;

  /* The light theme's depth comes from shadow, not from borders — a white card
     on a grey ground with only a 1px rule reads as a wireframe. Tinted toward
     the text colour rather than pure black: a neutral-black shadow on a warm
     white is the thing that makes a light UI look cheap. */
  --shadow-1: 0 1px 2px rgba(26, 26, 46, 0.06);
  --shadow-2: 0 1px 2px rgba(26, 26, 46, 0.05), 0 6px 16px -8px rgba(26, 26, 46, 0.14);
  --shadow-3: 0 2px 4px rgba(26, 26, 46, 0.05), 0 18px 40px -20px rgba(26, 26, 46, 0.22);
}

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

html {
  scroll-behavior: smooth;
  /* Offset anchor targets so the sticky header never covers a heading. */
  scroll-padding-top: 84px;
  -webkit-text-size-adjust: 100%;
}

/* While the beta strip is showing it is sticky too, so the header that an
   anchor has to clear is ~46px taller. Scoped to the gated state: when
   data-cta="live" the strip is display:none and 84px is right again. */
html[data-cta="soon"] { scroll-padding-top: 130px; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* Belt and braces against horizontal overflow on small screens. */
  overflow-x: hidden;
  transition: background 0.3s var(--ease), color 0.3s var(--ease);
}

img, svg { max-width: 100%; display: block; }

a { color: var(--text); text-decoration-color: var(--text-mute); text-underline-offset: 3px; }
a:hover { text-decoration-color: var(--brand); }

code { font-family: var(--mono); font-size: 0.92em; }
.mono { font-family: var(--mono); }
.accent { color: var(--brand-hi); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; top: -60px; left: 12px; z-index: 200;
  background: var(--brand); color: #04150a; font-weight: 700;
  padding: 10px 16px; border-radius: var(--radius); text-decoration: none;
  transition: top 0.15s var(--ease);
}
.skip-link:focus { top: 12px; }

/* Visible, consistent focus for keyboard users everywhere. */
:focus-visible {
  outline: 2px solid var(--brand-hi);
  outline-offset: 3px;
  border-radius: 2px;
}

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 24px; }
.wrap-narrow { max-width: 800px; }

/* Faint grid, fixed behind everything. Pure decoration, so aria-hidden. */
.grid-bg {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(var(--line-soft) 1px, transparent 1px),
    linear-gradient(90deg, var(--line-soft) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 35%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 35%, transparent 78%);
  opacity: 0.75;
}

main, .nav, .ticker, .footer { position: relative; z-index: 1; }

/* ============================ NAV ============================ */

.nav {
  position: sticky; top: 0; z-index: 100;
  background: var(--nav-bg);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
  transition: background 0.3s var(--ease), border-color 0.3s var(--ease);
}

.nav-inner { display: flex; align-items: center; gap: 20px; height: 64px; }

.brand {
  display: inline-flex; align-items: center; gap: 10px;
  text-decoration: none; color: var(--text); flex-shrink: 0;
}
/* The mark sits in a tile, app-icon style: the halftone portrait is
   low-contrast line art, and untiled on the nav's blur it read as a smudge.
   The tile gives it a ground and makes the brand block read as a product
   mark rather than as clip art next to a wordmark. */
.brand-mark {
  display: grid; place-items: center; color: var(--brand);
  background: color-mix(in srgb, var(--brand) 8%, var(--surface-2));
  border: 1px solid var(--brand-line);
  border-radius: 9px; padding: 3px;
}
/* The mark is a halftone portrait on transparency, so it sits on the nav
   without a tile behind it. Rendered a touch larger than the old glyph: the
   dot grid needs the pixels to stay a face rather than a smudge. */
.brand-mark img {
  display: block; width: 30px; height: 30px;
  /* The source is white dots; -webkit- prefix included because Safari still
     wants it for image-rendering hints on downscaled bitmaps. */
  image-rendering: -webkit-optimize-contrast;
}
@media (max-width: 560px) { .brand-mark img { width: 26px; height: 26px; } }
.brand-text {
  font-family: var(--mono); font-weight: 700; font-size: 15px;
  letter-spacing: 0.14em;
}

.nav-links { display: flex; gap: 28px; margin-left: auto; }
.nav-links a {
  font-size: 14px; color: var(--text-dim); text-decoration: none;
  transition: color 0.15s var(--ease);
}
.nav-links a:hover { color: var(--text); }

.nav-toggle {
  display: none; width: 40px; height: 40px; margin-left: auto;
  background: none; border: 1px solid var(--line); border-radius: var(--radius);
  cursor: pointer; padding: 11px 9px;
  flex-direction: column; justify-content: space-between;
}
.nav-toggle span { display: block; height: 1.5px; background: var(--text); transition: 0.2s var(--ease); }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

.mobile-nav {
  display: none; flex-direction: column;
  border-top: 1px solid var(--line); background: var(--bg-alt);
  padding: 8px 24px 20px;
}
.mobile-nav a {
  padding: 14px 0; font-size: 16px; color: var(--text-dim);
  text-decoration: none; border-bottom: 1px solid var(--line-soft);
}
.mobile-nav a:last-child { border-bottom: 0; }
.mobile-cta { color: var(--brand-hi) !important; font-weight: 600; }

/* --- Mobile sheet, as a terminal ---------------------------------------
   The menu reads as a session rather than a list of links: a status row at
   the top, then numbered rows with the current page marked. The numbers are
   a CSS counter, not markup — they are decoration, they must not reach a
   screen reader as part of the link text, and hardcoding them across 17
   pages would guarantee they drift the first time an item moves. */
.mobile-nav { counter-reset: navitem; }
.mobile-nav-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 0; margin-bottom: 4px;
  border-bottom: 1px solid var(--line);
  font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.18em; text-transform: uppercase;
}
.mobile-nav-session { display: inline-flex; align-items: center; gap: 7px; color: var(--green); }
/* .live-dot is brand-green by default. Here it sits beside the word
   "Session" in green, and a two-colour pair reads as two states. */
.mobile-nav-session .live-dot { background: var(--green); }
.mobile-nav-mode { color: var(--text-mute); letter-spacing: 0.14em; }

.mobile-nav a:not(.mobile-cta) {
  display: flex; align-items: center; gap: 14px;
  font-family: var(--mono); font-size: 13px;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.mobile-nav a:not(.mobile-cta)::before {
  counter-increment: navitem;
  content: counter(navitem, decimal-leading-zero);
  width: 22px; flex: none;
  color: var(--text-mute); font-size: 11px; letter-spacing: 0.08em;
}
/* The trailing arrow and the ACTIVE flag are the same slot: a row is either
   somewhere you can go or the place you already are, never both. */
.mobile-nav a:not(.mobile-cta)::after {
  content: "\2192"; margin-left: auto;
  color: var(--text-mute); font-size: 13px;
}
.mobile-nav a[aria-current="page"] {
  color: var(--text); background: var(--surface-2);
  margin: 0 -24px; padding-left: 24px; padding-right: 24px;
}
.mobile-nav a[aria-current="page"]::after {
  content: "Active"; color: var(--brand-hi);
  font-size: 10px; letter-spacing: 0.16em;
}

/* ============================ BUTTONS ============================ */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 22px; border-radius: var(--radius);
  font-size: 14px; font-weight: 600; text-decoration: none;
  border: 1px solid transparent; cursor: pointer; white-space: nowrap;
  transition: transform 0.15s var(--ease), background 0.15s var(--ease),
              border-color 0.15s var(--ease), box-shadow 0.2s var(--ease);
}
.btn-sm { padding: 9px 16px; font-size: 13px; }
.btn-lg { padding: 15px 30px; font-size: 15px; }

.btn-primary {
  /* Near-black text on the brand green: white on #00e065 measures under
     2:1, which is why the old purple-era buttons read washed out. The dark
     label is also what makes the fill read as a lit key rather than a badge. */
  background: var(--brand); color: #04150a; font-weight: 700;
  box-shadow: 0 0 0 1px var(--brand), 0 8px 26px -12px var(--brand);
}
.btn-primary:hover { background: var(--brand-hi); transform: translateY(-1px); }

.btn-ghost { background: transparent; color: var(--text); border-color: var(--line); }
.btn-ghost:hover { border-color: var(--text-mute); background: var(--surface); }

.btn:active { transform: translateY(0); }
/* A disabled button (the launch flow's Confirm when a quote is not fundable
   yet) must not read as clickable just because its color class still says
   "primary". */
.btn:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
.btn:disabled:hover { transform: none; background: var(--brand); }
.btn-ghost:disabled:hover { background: transparent; }

/* ============================ TICKER ============================ */

.ticker {
  border-bottom: 1px solid var(--line);
  background: var(--bg-alt);
  overflow: hidden;
  padding: 9px 0;
  /* Fade the edges so items enter and leave rather than being clipped. */
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.ticker-track {
  display: flex; gap: 40px; width: max-content;
  animation: scroll-x 70s linear infinite;
}
.tick {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.09em;
  /* The symbol leads a tape item, so it carries the full text colour; the
     company name behind it (<b>) stays muted. Dim-on-mute made the whole
     tape read as one grey smear at speed. */
  color: var(--text); white-space: nowrap;
  /* A tick is an <a> now. It should not read as body-copy link — no underline,
     no visited colour — but it must say it is clickable on hover. */
  text-decoration: none; cursor: pointer;
  transition: opacity 120ms ease;
}
.tick:hover { color: var(--brand-hi); opacity: 1; }
.tick:hover b, .tick:hover i { color: inherit; }
.tick-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%; flex-shrink: 0;
  overflow: hidden; vertical-align: middle; margin-right: 5px;
  font-family: var(--mono); font-size: 8px; font-weight: 700;
  border: 1px solid var(--line); background: var(--surface-2);
  color: var(--text-dim);
}
.tick-mark img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tick b { color: var(--text-mute); font-weight: 400; margin-left: 7px; }
/* The share price, when /pairs reports one. Brighter than the company name and
   dimmer than the symbol: it is the second thing read, not the first. Absent
   prices render nothing at all rather than a placeholder — see main.js. */
.tick i { color: var(--text); font-style: normal; margin-left: 7px; }

@keyframes scroll-x {
  from { transform: translateX(0); }
  /* main.js renders the pair list twice, so -50% is a seamless loop.
     The duration is set inline from the rendered width, keeping the speed
     constant however many pairs StonkFun is listing. */
  to   { transform: translateX(-50%); }
}

/* An indefinitely scrolling strip is exactly what this setting is for.

   Stopping the animation alone would strand the reader with whatever pairs
   happened to fit the viewport — about a dozen of ~48. So the strip becomes
   manually scrollable instead, and main.js renders the list once rather than
   twice (the duplicate half only exists to make the -50% loop seamless). */
@media (prefers-reduced-motion: reduce) {
  .ticker-track { animation: none; }
  .ticker {
    overflow-x: auto;
    /* The edge fade implies "there's more, it's moving". Nothing is moving
       here, and it would obscure the first and last pair while scrolling. */
    mask-image: none;
    -webkit-mask-image: none;
    scrollbar-width: thin;
  }
}

/* ============================ HERO ============================ */

/* Top padding is deliberately small. The header stack (nav + beta strip +
   ticker) already occupies ~148px, and at the old clamp ceiling of 104px the
   headline started ~300px down and the primary CTA fell below the fold on a
   1366x768 laptop. Bottom padding is unchanged. */
.hero {
  padding: clamp(32px, 4vw, 48px) 0 clamp(48px, 7vw, 88px);
  /* Containing block for the particle canvas and its scrim. overflow:hidden so
     dispersing particles clip to the hero rather than widening the page. */
  position: relative;
  overflow: hidden;
}

/* Particle field, drawn by particle-hero.js from shader-effect.png.
   Starts at zero opacity and is faded in only once the script has sampled the
   image and sized the canvas, so a blocked or broken image leaves nothing
   behind rather than an empty box. */
.hero-particles {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 900ms var(--ease);
  /* Dissolve at the edges instead of ending on a hard rectangle. */
  /* Feather the top and bottom only. The face is cropped past the hero's
     height by design, and a hard cut at the section edge would advertise the
     box it lives in. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 16%, #000 82%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0%, #000 16%, #000 82%, transparent 100%);
}
.hero-particles.is-live { opacity: 0.85; }

/* Scrim. The headline and lede sit on the left, so the field is cleared there
   and left alone on the right. This is what guarantees text contrast at peak
   particle density — canvas opacity alone is not a contract. It stops well
   before the flow card, which paints its own background anyway. */
.hero::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(95deg,
    rgba(var(--scrim), 0.97) 0%,
    rgba(var(--scrim), 0.9) 26%,
    rgba(var(--scrim), 0.6) 40%,
    rgba(var(--scrim), 0.18) 55%,
    transparent 70%);
}

.hero-inner {
  display: grid; grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(32px, 5vw, 64px); align-items: center;
  /* Above both the canvas and the scrim. */
  position: relative; z-index: 1;
}

/* Single column: the copy no longer has a clear left half to live in, so the
   field is dimmed further and the scrim runs top-down instead of across. */
@media (max-width: 900px) {
  .hero-particles.is-live { opacity: 0.5; }
  .hero::after {
    background: linear-gradient(180deg,
      rgba(var(--scrim), 0.35) 0%,
      rgba(var(--scrim), 0.82) 42%,
      var(--bg) 72%);
  }
}

.eyebrow {
  display: inline-flex; align-items: center; gap: 9px; margin: 0 0 22px;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--text-dim);
  border: 1px solid var(--line); border-radius: 100px; padding: 6px 14px;
  background: var(--surface);
}
.dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--brand-hi);
  box-shadow: 0 0 0 3px var(--brand-glow);
  animation: breathe 2.6s ease-in-out infinite;
}
@keyframes breathe { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }

h1 {
  margin: 0 0 24px;
  font-size: clamp(2.5rem, 6.4vw, 4.4rem);
  line-height: 1.02; letter-spacing: -0.035em; font-weight: 800;
  /* Long single words (a stray URL, a long ticker) must not blow out the layout. */
  overflow-wrap: break-word;
}

.lede {
  margin: 0 0 32px; font-size: clamp(1rem, 1.6vw, 1.14rem);
  color: var(--text-dim); max-width: 42ch;
}
.lede a { color: var(--text); }

.cta-row { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 26px; }

.hero-note {
  margin: 0; font-size: 13.5px; color: var(--text-mute); max-width: 46ch;
  padding-left: 14px; border-left: 2px solid var(--brand-line);
}

/* Short desktop viewports — the common laptop case. A 1366x768 screen is
   ~640px of actual viewport once browser chrome is subtracted, and at the full
   type scale the CTA lands below it. Tightened only here, so normal-height
   screens keep the intended proportions. Height-based, not width-based:
   the fold is a height problem. */
@media (min-width: 901px) and (max-height: 800px) {
  .hero { padding-top: 28px; padding-bottom: 48px; }
  .eyebrow { margin-bottom: 16px; }
  h1 { font-size: clamp(2.2rem, 4.6vw, 3.4rem); margin-bottom: 18px; }
  .lede { margin-bottom: 22px; }
  .cta-row { margin-bottom: 20px; }
}
.hero-note em { color: var(--text-dim); font-style: italic; }

/* Flow diagram */
.hero-flow {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: linear-gradient(180deg, var(--surface), var(--bg-alt));
  padding: 26px 24px 20px;
}
.flow { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.flow-step {
  display: grid; gap: 3px;
  padding: 15px 17px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--bg);
}
.flow-step.is-final { border-color: rgba(0, 224, 101, 0.34); background: rgba(0, 224, 101, 0.05); }
.flow-label {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.15em;
  text-transform: uppercase; color: var(--text-mute);
}
.flow-value { font-family: var(--mono); font-size: 21px; font-weight: 700; letter-spacing: -0.01em; }
.flow-sub { font-size: 12.5px; color: var(--text-dim); }
.flow-arrow { display: grid; place-items: center; color: var(--text-mute); padding: 1px 0; }
.flow-src { margin: 16px 0 0; font-size: 11.5px; color: var(--text-mute); text-align: center; }

/* Hero chat preview — replaces the static flow diagram */
.hero-chat {
  /* The hero's one product object, so it carries the hero's only real
     elevation: a brand-tinted edge and the deepest shadow step. Flat, it
     read as a wireframe box floating next to the headline. */
  border: 1px solid var(--brand-line); border-radius: 12px;
  background: var(--surface); overflow: hidden;
  box-shadow: var(--shadow-3), 0 0 64px -18px var(--brand-glow);
}
.hero-mascot { margin: 0; border-bottom: 1px solid var(--line); }
.hero-mascot img {
  display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover;
  object-position: 50% 22%;
}
.hero-chat-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 11px 16px; border-bottom: 1px solid var(--line);
  background: var(--surface-2); font-size: 12px;
}
/* Draggable on desktop (web/hero-drag.js), so the field behind can be seen.
   Every rule here is additive and class-gated: with the script absent the card
   renders and behaves exactly as it did before. */
.hero-chat.is-draggable > .hero-chat-bar {
  cursor: grab; user-select: none; touch-action: none;
}
.hero-chat.is-draggable > .hero-chat-bar:focus-visible {
  outline: 2px solid var(--green); outline-offset: -2px;
}
.hero-chat.is-dragging > .hero-chat-bar { cursor: grabbing; }
.hero-chat.is-draggable { transition: box-shadow 160ms ease; }
/* Lifted off the page while it is being moved, and kept above the field once
   it has been — a card sitting mid-canvas with no shadow reads as a hole. */
.hero-chat.is-dragging,
.hero-chat.is-moved {
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.55);
  position: relative; z-index: 3;
}
.hero-chat.is-dragging { transition: none; }
@media (prefers-reduced-motion: reduce) {
  .hero-chat.is-draggable { transition: none; }
}

.hero-chat-label {
  font-family: var(--mono); font-weight: 700; color: var(--text);
  font-size: 11px; letter-spacing: 0.14em;
}
.hero-chat-tag {
  font-size: 10px; font-weight: 600; text-transform: uppercase;
  color: var(--green); letter-spacing: 0.08em;
}
.hero-chat-log {
  padding: 16px; display: flex; flex-direction: column; gap: 8px;
  /* The log is a screen, not a sheet: darker than the card around it, with
     the same scanline grain as .bg-scan. It also keeps the empty state
     (no reply until live data lands) reading as a terminal at rest rather
     than as a hole in the card. */
  background:
    repeating-linear-gradient(0deg, transparent, transparent 2px, rgb(255 255 255 / 0.012) 2px, rgb(255 255 255 / 0.012) 3px),
    var(--bg-alt);
}
[data-theme="light"] .hero-chat-log { background: var(--bg-alt); }
.hero-chat-msg {
  padding: 10px 14px; border-radius: 10px; font-family: var(--mono);
  font-size: 12.5px; line-height: 1.6; max-width: 92%;
}
.hero-chat-user {
  align-self: flex-end; background: var(--brand); color: #04150a; font-weight: 600;
  border-bottom-right-radius: 3px;
}
.hero-chat-bot {
  align-self: flex-start; background: var(--bg-alt); color: var(--text);
  border-bottom-left-radius: 3px;
}
.hero-chat-dim { color: var(--text-mute); font-size: 11.5px; }
.hero-chat-cta {
  display: flex; align-items: center; gap: 6px;
  padding: 10px 16px; border-top: 1px solid var(--line);
  font-size: 12.5px; color: var(--text-dim); background: var(--bg-alt);
}
.hero-chat-cta svg { color: var(--brand); flex-shrink: 0; }
.hero-chat-cta a { color: var(--brand); text-decoration: none; }
.hero-chat-cta a:hover { text-decoration: underline; }

/* ============================ SECTIONS ============================ */

.section { padding: clamp(56px, 8vw, 104px) 0; }
/* --bg-alt sits one step from --bg by design (it is also the ticker and
   footer ground), which left alternating sections indistinguishable and
   the page reading as one long scroll of the same black. The alt band is
   therefore mixed locally toward --surface: visibly a different room,
   still unmistakably the same house. */
.section-alt {
  background: color-mix(in srgb, var(--surface) 48%, var(--bg));
  border-block: 1px solid var(--line);
}

.section-head { max-width: 62ch; margin-bottom: clamp(32px, 4.5vw, 52px); }
.kicker {
  margin: 0 0 12px; font-family: var(--mono); font-size: 11.5px;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--brand-hi);
}
.section-head h2 {
  margin: 0 0 16px; font-size: clamp(1.75rem, 3.6vw, 2.6rem);
  line-height: 1.12; letter-spacing: -0.028em; font-weight: 700;
}
.section-lede { margin: 0; color: var(--text-dim); font-size: clamp(0.97rem, 1.4vw, 1.06rem); }

/* ============================ LIVE MARKET ============================ */

/* Top-aligned so the timestamp sits level with the kicker rather than
   drifting to the bottom of a two-line heading. */
.live-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 20px; max-width: none; flex-wrap: wrap;
}
.live-dot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--brand); margin-right: 8px; vertical-align: middle;
  box-shadow: 0 0 0 3px var(--brand-glow);
  animation: breathe 2.6s ease-in-out infinite;
}
.live-stamp {
  margin: 0; font-family: var(--mono); font-size: 11px; color: var(--text-mute);
  white-space: nowrap; border: 1px solid var(--line); border-radius: 100px;
  padding: 5px 12px; background: var(--surface);
}

.stat-strip {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  background: var(--line); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; margin-bottom: 16px;
}
.stat { background: var(--surface); padding: 20px; display: grid; gap: 7px; }
.stat-label {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--text-mute);
}
.stat-value {
  font-family: var(--mono); font-size: clamp(1.3rem, 2.4vw, 1.75rem);
  font-weight: 700; letter-spacing: -0.02em; line-height: 1;
}

.board {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
  box-shadow: var(--shadow-2);
}
.board-tabs {
  display: flex; gap: 2px; padding: 10px 12px;
  border-bottom: 1px solid var(--line); background: var(--bg-alt);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.board-tab {
  background: none; border: 1px solid transparent; border-radius: var(--radius);
  color: var(--text-dim); font-family: var(--sans); font-size: 13px;
  font-weight: 600; padding: 7px 14px; cursor: pointer; white-space: nowrap;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}
.board-tab:hover { color: var(--text); }
.board-tab.is-active {
  color: var(--brand-hi); background: var(--brand-glow);
  border-color: var(--brand-line);
}

.board-body { padding: 4px 0 8px; }

.board-row {
  display: grid;
  grid-template-columns: minmax(0, 2.1fr) minmax(0, 1fr) minmax(0, 1fr)
                         minmax(0, 1fr) minmax(0, 0.7fr) minmax(0, 1.2fr);
  gap: 14px; align-items: center; padding: 12px 20px;
  border-bottom: 1px solid var(--line-soft); font-size: 13.5px;
}
.board-row:last-child { border-bottom: 0; }
/* Cards are anchors when the row has a valid mint (see main.js) — reset the
   link defaults so a card reads exactly as it did as a plain div. */
a.board-row {
  color: inherit; text-decoration: none; cursor: pointer;
  transition: background 0.15s var(--ease);
}
a.board-row:hover, a.board-row:focus-visible { background: var(--surface-2); }
.board-header { display: none; }
.ta-r { text-align: right; }

.tk { display: flex; align-items: center; gap: 11px; min-width: 0; }
/* The identity mark for a token or quote asset (web/identity.js). It shows a
   monogram until a real logo is available — never the token's own image URL
   loaded directly, since a launcher supplies that URL and it is fetched
   through our own same-origin /api/logo instead (see logoPath in
   api/live.mjs), never the browser. Every page that lists tokens sizes its
   own mark with this same rule, so an <img> in any of them fills the box
   exactly as the monogram text did. */
.tk-mono, .sw-mono, .br-mono {
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}

/* A mark with no logo behind it. identity.js sets the background and colour
   inline — derived from the mint, so each token is its own colour instead of
   the one flat grey every page used to paint — and stamps data-mark="monogram"
   so the shared typography lands whichever page class the box is carrying.
   Colour is inline because it is per-token data, not a style; everything that
   is the same for every mark stays here. */
[data-mark="monogram"] {
  font-family: var(--mono);
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1;
  text-transform: uppercase;
  border-style: solid;
}
.tk-mono img, .sw-mono img, .br-mono img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}

/* An inlined chain mark (chain-marks.js). The artwork carries its own coloured
   disc, so the box must not draw a second one behind it — hence the reset of
   the border and background the empty state uses. Only /bridge sets this, and
   only for the fixed allowlist of chain assets whose real mark we hold; a
   symbol without one keeps data-mark="monogram" and the chrome that goes with
   it. */
[data-mark="logo"] {
  border: 0;
  background: none;
  padding: 0;
}
[data-mark="logo"] svg {
  width: 100%; height: 100%; display: block;
}
.tk-mono {
  width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0;
  font-family: var(--mono); font-size: 13px; font-weight: 700;
  border: 1px solid var(--line); background: var(--surface-2);
  color: var(--text-dim);
}
.tk-id { min-width: 0; }
.tk-sym {
  display: block; font-family: var(--mono); font-weight: 700; font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tk-name {
  display: block; font-size: 11.5px; color: var(--text-mute);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pair {
  font-family: var(--mono); font-size: 12px; color: var(--text-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pair-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0;
  overflow: hidden; vertical-align: middle; margin-right: 4px;
  font-family: var(--mono); font-size: 9px; font-weight: 700;
  border: 1px solid var(--line); background: var(--surface-2);
  color: var(--text-dim);
}
.pair-mark img { width: 100%; height: 100%; object-fit: cover; display: block; }
.col-pair { display: flex; align-items: center; gap: 0; }
.num { font-family: var(--mono); font-size: 12.5px; text-align: right; }
.chg { font-family: var(--mono); font-size: 12.5px; text-align: right; font-weight: 600; }
.chg.up { color: var(--green); }
.chg.down { color: var(--red); }
.chg.flat { color: var(--text-mute); }

.bond { display: grid; gap: 5px; min-width: 0; }
.bond-bar {
  height: 5px; border-radius: 100px; background: var(--surface-2);
  overflow: hidden; border: 1px solid var(--line);
}
.bond-fill {
  height: 100%; background: var(--green); border-radius: 100px;
  transition: width 0.5s var(--ease);
}
.bond-fill.done { background: var(--green-dim); }
/* Progress was not reported. Hatched rather than empty, so the bar cannot be
   read as "0% of the way to graduation" — see the comment in main.js. */
.bond-bar.unknown {
  background: repeating-linear-gradient(
    -45deg, var(--surface-2), var(--surface-2) 2px, transparent 2px, transparent 4px
  );
}
.bond-text { font-family: var(--mono); font-size: 10.5px; color: var(--text-mute); }

/* ---- Token cards (shared layout for live, homepage, stonkdar) ---- */
.token-card {
  display: grid;
  grid-template-columns: auto 1fr auto;
  column-gap: 12px; row-gap: 4px;
  padding: 14px 18px; align-items: center;
  border-bottom: 1px solid var(--line-soft);
}
.token-card:last-child { border-bottom: 0; }
a.token-card {
  color: inherit; text-decoration: none; cursor: pointer;
  transition: background 0.15s var(--ease);
}
a.token-card:hover, a.token-card:focus-visible {
  background: var(--surface-2);
  /* The same brand edge the selected state uses, so hovering a row in the
     board previews the state clicking it would produce. */
  box-shadow: inset 2px 0 0 var(--brand);
}
button.token-card {
  width: 100%; text-align: left; background: none; border: 0;
  color: inherit; font: inherit; cursor: pointer;
  transition: background 0.12s var(--ease);
}
button.token-card:hover, button.token-card:focus-visible { background: var(--surface-2); }
button.token-card.is-selected {
  background: var(--brand-glow); box-shadow: inset 2px 0 0 var(--brand);
}

.card-logos {
  grid-row: 1; grid-column: 1;
  display: flex; align-items: center; gap: 4px;
  flex-shrink: 0; align-self: start; padding-top: 2px;
}
.card-logos .pair-mark { margin-right: 0; }
.card-id { grid-row: 1; grid-column: 2; min-width: 0; }
.card-mcap {
  grid-row: 1; grid-column: 3;
  font-family: var(--mono); font-size: 16px; font-weight: 700;
  text-align: right; white-space: nowrap; color: var(--text);
  align-self: start; padding-top: 2px;
}
.card-meta {
  grid-row: 2; grid-column: 2 / -1;
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 0; font-family: var(--mono); font-size: 11.5px; color: var(--text-dim);
}
.card-dot { margin: 0 5px; color: var(--text-mute); user-select: none; }
.card-meta .chg { font-size: 11.5px; text-align: left; }
.card-flag {
  font-size: 9px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-mute);
  border: 1px solid var(--line); border-radius: 100px; padding: 1px 6px;
}
.card-bond { grid-row: 3; grid-column: 2 / -1; }
.card-bond .bond { gap: 4px; }
.ss-panel .token-card { padding-left: 0; padding-right: 0; }
.live-rows .token-card { padding: 9px 8px; }

@media (max-width: 560px) {
  .token-card { padding: 10px 14px; column-gap: 8px; }
  .card-mcap { font-size: 13px; }
}

.board-msg { margin: 0; padding: 30px 20px; color: var(--text-mute); font-size: 13.5px; text-align: center; }
.board-msg.err { color: var(--amber); }

/* Loading skeleton */
.sk { background: var(--surface-2); border-radius: 3px; height: 11px; }
.sk-shimmer { animation: shimmer 1.4s ease-in-out infinite; }
@keyframes shimmer { 0%, 100% { opacity: 0.35; } 50% { opacity: 0.75; } }

.live-note { margin: 16px 0 0; font-size: 12px; color: var(--text-dim); max-width: 76ch; }

@media (max-width: 900px) {
  .stat-strip { grid-template-columns: repeat(2, 1fr); }
}

/* ============================ TERMINAL DEMO ============================ */

.terminal {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: linear-gradient(180deg, var(--surface), var(--bg-alt));
  overflow: hidden;
  box-shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.9);
}
.terminal-bar {
  display: flex; align-items: center; gap: 7px;
  padding: 11px 15px; border-bottom: 1px solid var(--line); background: var(--bg);
}
.tdot { width: 9px; height: 9px; border-radius: 50%; background: var(--line); }
/* Window chrome reads as chrome: the three dots are the muted traffic-light
   set every terminal window carries, desaturated so they sit inside the
   palette instead of shouting over it. Shared by .terminal-bar and .term-bar. */
.term-bar .tdot:nth-child(1), .terminal-bar .tdot:nth-child(1) { background: rgba(246, 70, 93, 0.6); }
.term-bar .tdot:nth-child(2), .terminal-bar .tdot:nth-child(2) { background: rgba(245, 165, 36, 0.6); }
.term-bar .tdot:nth-child(3), .terminal-bar .tdot:nth-child(3) { background: rgba(0, 224, 101, 0.65); }
.terminal-title {
  margin-left: 9px; font-family: var(--mono); font-size: 11.5px;
  letter-spacing: 0.04em; color: var(--text-dim);
}
.terminal-tag {
  margin-left: auto; font-family: var(--mono); font-size: 10px;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-mute);
  border: 1px solid var(--line); border-radius: 100px; padding: 3px 9px;
}

.thread { padding: 20px 18px; display: grid; gap: 13px; }
.msg { padding: 13px 16px; border-radius: var(--radius); border: 1px solid var(--line); max-width: 88%; }
.msg p { margin: 0; font-size: 14.5px; line-height: 1.62; }
.msg-user { background: var(--bg); justify-self: end; }
.msg-bot  { background: rgba(0, 224, 101, 0.045); border-color: rgba(0, 224, 101, 0.2); }
.who {
  display: block; font-family: var(--mono); font-size: 11px;
  color: var(--text-mute); margin-bottom: 5px;
}
.msg-bot .who { color: var(--brand-hi); }
.addr, .link-ish { color: var(--text-dim); font-size: 13px; }
.status-live { display: inline-flex; align-items: center; gap: 7px; font-weight: 700; color: var(--green); }
.pulse {
  width: 7px; height: 7px; border-radius: 50%; background: var(--green);
  box-shadow: 0 0 0 0 var(--green-glow); animation: pulse 2s ease-out infinite;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(0, 224, 101, 0.5); }
  100% { box-shadow: 0 0 0 11px rgba(0, 224, 101, 0); }
}

.disclaimer { margin: 14px 0 0; font-size: 12.5px; color: var(--text-mute); text-align: center; }

/* ============================ STEPS ============================ */

/* Explicit column counts, not auto-fit: with five items an auto-fit grid
   leaves orphan cells, and the gap-as-border trick then paints them as a
   phantom empty block. Each card carries its own border instead. */
.steps {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 12px;
  grid-template-columns: repeat(5, 1fr);
}
.step {
  /* A gradient off the surface rather than the flat page ground: on the
     alt band the flat cards sank into the section, and the five steps —
     the page's one process diagram — read as five holes. */
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  padding: 24px 20px 26px;
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-1);
  transition: border-color 0.15s var(--ease);
}
.step:hover { border-color: var(--brand-line); }

@media (max-width: 1080px) { .steps { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 720px)  { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px)  { .steps { grid-template-columns: 1fr; } }
.step-num {
  display: block; font-family: var(--mono); font-size: 11.5px;
  letter-spacing: 0.14em; color: var(--brand-hi); margin-bottom: 14px;
}
.step h3 { margin: 0 0 9px; font-size: 16.5px; font-weight: 700; letter-spacing: -0.012em; }
.step p { margin: 0; font-size: 14px; color: var(--text-dim); }
.step code {
  background: var(--surface-2); border: 1px solid var(--line);
  padding: 1px 5px; border-radius: 2px; color: var(--brand-hi); font-size: 12.5px;
  /* Commands are long; let them wrap rather than overflow on mobile. */
  overflow-wrap: break-word;
}

/* ============================ ECONOMICS ============================ */

.econ-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(258px, 1fr));
  gap: 14px; margin-bottom: 24px;
}
.econ-card {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); padding: 24px 22px; display: flex; flex-direction: column;
  transition: border-color 0.15s var(--ease);
}
.econ-card:hover { border-color: var(--brand-line); }
.econ-hero {
  border-color: rgba(0, 224, 101, 0.32);
  background: linear-gradient(165deg, rgba(0, 224, 101, 0.075), var(--surface) 62%);
}
.econ-label {
  margin: 0 0 12px; font-family: var(--mono); font-size: 10.5px;
  letter-spacing: 0.15em; text-transform: uppercase; color: var(--text-mute);
}
.econ-value {
  margin: 0 0 12px; font-family: var(--mono); font-size: clamp(2rem, 4.2vw, 2.7rem);
  font-weight: 700; line-height: 1; letter-spacing: -0.03em;
}
.econ-value.quoted { font-size: clamp(1.35rem, 2.6vw, 1.7rem); color: var(--text); }
.unit {
  font-size: 0.42em; font-weight: 600; color: var(--text-mute);
  margin-left: 7px; letter-spacing: 0.06em; text-transform: uppercase;
}
.econ-value.quoted .unit { display: block; margin: 7px 0 0; font-size: 0.55em; }
.econ-desc { margin: 0 0 16px; font-size: 13.5px; color: var(--text-dim); flex-grow: 1; }
.econ-src {
  margin: 0; padding-top: 14px; border-top: 1px solid var(--line);
  font-size: 11.5px; color: var(--text-mute);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.src-badge {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.09em;
  text-transform: uppercase; padding: 3px 7px; border-radius: 2px; border: 1px solid;
}
.src-ok   { color: var(--green);    border-color: rgba(46, 230, 168, 0.36); background: rgba(46, 230, 168, 0.07); }
.src-warn { color: var(--amber);    border-color: rgba(245, 165, 36, 0.38); background: rgba(245, 165, 36, 0.07); }
.src-info { color: var(--text-dim); border-color: var(--line);              background: var(--surface-2); }

.callout {
  display: flex; gap: 14px; align-items: flex-start;
  border: 1px solid var(--line); border-left: 2px solid var(--brand-hi);
  border-radius: var(--radius); background: var(--surface);
  padding: 20px 22px; margin-bottom: 24px;
}
.callout svg { flex-shrink: 0; color: var(--brand-hi); margin-top: 2px; }
.callout p { margin: 0; font-size: 14px; color: var(--text-dim); }
.callout strong { color: var(--text); }
.callout-warn { border-left-color: var(--amber); margin-bottom: 0; }
.callout-warn svg { color: var(--amber); }

/* ============================ DETAILS / TABLE ============================ */

.details {
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
}
.details > summary, .faq > details > summary {
  cursor: pointer; padding: 17px 22px; font-weight: 600; font-size: 15px;
  list-style: none; display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
}
.details > summary:hover { background: var(--surface-2); }
.details > summary::-webkit-details-marker,
.faq > details > summary::-webkit-details-marker { display: none; }
.details > summary::after, .faq > details > summary::after {
  content: "+"; font-family: var(--mono); font-size: 19px; color: var(--text-mute);
  flex-shrink: 0; transition: transform 0.2s var(--ease);
}
.details[open] > summary::after, .faq > details[open] > summary::after {
  transform: rotate(45deg); color: var(--brand-hi);
}
.details-body { padding: 0 22px 22px; border-top: 1px solid var(--line); padding-top: 18px; }

/* Wide tables scroll inside their own box; the page never scrolls sideways. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table { width: 100%; border-collapse: collapse; font-size: 13.5px; min-width: 560px; }
th, td { text-align: left; padding: 11px 14px 11px 0; border-bottom: 1px solid var(--line-soft); }
thead th {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-mute); font-weight: 500;
}
tbody th { font-weight: 600; color: var(--text); }
tbody td { color: var(--text-dim); }
.fine { margin: 16px 0 0; font-size: 12.5px; color: var(--text-mute); }

/* ============================ REFERRALS ============================ */

.ref-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(198px, 1fr));
  gap: 14px; margin-bottom: 22px;
}
.ref-card {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg); padding: 22px 20px;
}
.ref-num {
  margin: 0 0 9px; font-family: var(--mono); font-size: 1.9rem;
  font-weight: 700; line-height: 1; letter-spacing: -0.03em;
}
.ref-desc { margin: 0; font-size: 13.5px; color: var(--text-dim); }

.ref-how {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg); padding: 24px 22px;
}
.ref-how-title { margin: 0 0 12px; font-size: 14px; color: var(--text-dim); }
.cmd {
  display: block; font-family: var(--mono); font-size: 13.5px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 13px 15px; margin-bottom: 20px;
  color: var(--text); overflow-wrap: break-word;
}
.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.ticks li {
  position: relative; padding-left: 24px; font-size: 14px; color: var(--text-dim);
}
.ticks li::before {
  content: ""; position: absolute; left: 3px; top: 8px;
  width: 6px; height: 10px; border: solid var(--green);
  border-width: 0 1.5px 1.5px 0; transform: rotate(45deg);
}
.ticks code {
  background: var(--surface-2); border: 1px solid var(--line);
  padding: 1px 5px; border-radius: 2px; color: var(--brand-hi);
}

/* ============================ SECURITY ============================ */

.sec-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(262px, 1fr));
  gap: 14px; margin-bottom: 24px;
}
.sec-card {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); padding: 22px 20px;
  position: relative; padding-top: 26px;
  transition: border-color 0.15s var(--ease);
}
.sec-card:hover { border-color: var(--brand-line); }
/* A hairline accent at the top edge, instead of an icon that would need alt text. */
.sec-card::before {
  content: ""; position: absolute; top: -1px; left: 20px; width: 28px; height: 2px;
  background: var(--brand-hi);
}
.sec-card h3 { margin: 0 0 9px; font-size: 15.5px; font-weight: 700; letter-spacing: -0.012em; }
.sec-card p { margin: 0; font-size: 13.5px; color: var(--text-dim); }

/* ============================ FAQ ============================ */

.faq { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.faq > details { background: var(--bg); }
.faq > details > summary:hover { background: var(--surface); }
.faq-body { padding: 0 22px 20px; }
.faq-body p { margin: 0; font-size: 14px; color: var(--text-dim); }
.faq-body code {
  background: var(--surface-2); border: 1px solid var(--line);
  padding: 1px 5px; border-radius: 2px; color: var(--brand-hi);
}

/* ============================ FINAL CTA ============================ */

.final {
  padding: clamp(64px, 9vw, 116px) 0; text-align: center;
  border-top: 1px solid var(--line);
  background:
    radial-gradient(ellipse 42% 62% at 50% 108%, var(--brand-glow), transparent 70%),
    radial-gradient(ellipse 60% 100% at 50% 100%, rgba(0, 224, 101, 0.07), transparent 70%);
}
.final h2 {
  margin: 0 0 12px; font-size: clamp(1.9rem, 4.4vw, 3rem);
  letter-spacing: -0.032em; font-weight: 800; line-height: 1.06;
  text-wrap: balance;
}
.final p { margin: 0 0 28px; color: var(--text-dim); font-size: 1.03rem; }
.final-cmd { margin: 24px 0 0 !important; }
.final-cmd code {
  font-size: 13px; color: var(--text-mute);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 8px 14px; background: var(--surface);
  display: inline-block; overflow-wrap: break-word; max-width: 100%;
}

/* ======================= CTA GATE (closed beta) =======================

   Driven entirely by data-cta on <html>. The default here is the *gated*
   state, so the live CTAs only appear when the attribute is explicitly
   "live". A missing or misspelled attribute therefore shows "closed beta"
   rather than inviting people to tweet at a bot that isn't answering.

   Restoring display per element type is deliberate: `display: revert` would
   drop .btn's inline-flex and break the buttons, so each shape says what it
   goes back to.
   ------------------------------------------------------------------------ */

.cta-live { display: none; }

[data-cta="live"] a.cta-live.btn      { display: inline-flex; }
[data-cta="live"] .mobile-nav a.cta-live { display: block; }
[data-cta="live"] p.cta-live          { display: block; }
[data-cta="live"] .cta-soon           { display: none; }

/* The gated stand-in: reads as a state, not a button you failed to click. */
.btn-gated {
  background: var(--surface);
  color: var(--text-dim);
  border-color: var(--line);
  cursor: default;
  user-select: none;
}
.btn-gated:hover { transform: none; }

.gated-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-mute);
  flex: none;
}

.mobile-cta-gated {
  color: var(--text-mute) !important;
  font-weight: 600;
  cursor: default;
}

/* Strip under the nav. States no date, deliberately — see HANDOFF §5c.

   Sticky, pinned directly beneath the nav, so the header moves as one block.
   Unsticky it slid up underneath the translucent nav on scroll, which read as
   the nav itself moving. `top` is the nav's height; z-index sits just under
   the nav's 100 so the nav wins any overlap. Opaque background is required —
   content scrolls behind it. */
.beta-strip {
  position: sticky; top: 64px; z-index: 99;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.beta-strip-inner {
  display: flex; align-items: baseline; gap: 12px;
  padding: 11px 0;
}
.beta-strip p {
  margin: 0;
  font-size: 13px; line-height: 1.55;
  color: var(--text-dim);
}
.beta-badge {
  flex: none;
  font-family: var(--mono);
  font-size: 10px; letter-spacing: 0.09em; text-transform: uppercase;
  /* Same status language as the preview strip above it: amber means
     "state of the product", everywhere it appears. */
  color: var(--amber);
  border: 1px solid color-mix(in srgb, var(--amber) 45%, transparent);
  border-radius: var(--radius);
  padding: 3px 8px;
  background: color-mix(in srgb, var(--amber) 7%, var(--bg-alt));
}

@media (max-width: 640px) {
  .beta-strip-inner { flex-direction: column; align-items: flex-start; gap: 8px; }
  .beta-strip p { font-size: 12.5px; }
}

/* ============================ FOOTER ============================ */

.footer { border-top: 1px solid var(--line); background: var(--bg-alt); padding: 56px 0 34px; }
.footer-inner {
  display: flex; justify-content: space-between; gap: 32px;
  flex-wrap: wrap; padding-bottom: 26px;
}
.footer-brand { max-width: 42ch; }
.footer-brand .brand-text { display: block; margin-bottom: 10px; color: var(--text); }
.footer-brand p { margin: 0; font-size: 12.5px; color: var(--text-mute); }
.footer-links { display: flex; flex-wrap: wrap; gap: 10px 26px; align-content: flex-start; }
.footer-links a { font-size: 13.5px; color: var(--text-dim); text-decoration: none; }
.footer-links a:hover { color: var(--brand-hi); }
.footer-legal { border-top: 1px solid var(--line); padding-top: 22px; }
.footer-legal p { margin: 0; font-size: 11.5px; color: var(--text-mute); max-width: 78ch; }

/* ============================ SCROLL REVEAL ============================ */

.reveal { opacity: 0; transform: translateY(14px); }
.reveal.in { opacity: 1; transform: none; transition: opacity 0.6s var(--ease), transform 0.6s var(--ease); }
/* If JS never runs, content must still be visible — this is the fallback. */
.no-js .reveal { opacity: 1; transform: none; }

/* ============================ RESPONSIVE ============================ */

@media (max-width: 900px) {
  .hero-inner { grid-template-columns: 1fr; }
  .hero-flow, .hero-chat { order: 2; }
  .nav-links { display: none; }
  .nav .btn-primary { display: none; }
  .nav-toggle { display: flex; }
  .mobile-nav:not([hidden]) { display: flex; }
}

@media (max-width: 640px) {
  .wrap { padding: 0 18px; }
  html { scroll-padding-top: 74px; }
  .msg { max-width: 100%; }
  .thread { padding: 16px 14px; }
  .footer-inner { flex-direction: column; gap: 24px; }
  .btn { width: 100%; }
  .cta-row { flex-direction: column; align-items: stretch; }
  .nav .btn { width: auto; }
  .mobile-nav .btn { width: auto; }
  .econ-value { font-size: clamp(1.8rem, 9vw, 2.3rem); }
}

@media (max-width: 380px) {
  .wrap { padding: 0 14px; }
  .brand-text { font-size: 13.5px; }
  .step, .econ-card, .sec-card, .ref-card { padding-left: 17px; padding-right: 17px; }
  .details > summary, .faq > details > summary { padding: 15px 17px; }
  .faq-body, .details-body { padding-left: 17px; padding-right: 17px; }
}

/* ============================ THEME TOGGLE ============================ */

.theme-toggle {
  display: grid; place-items: center;
  width: 36px; height: 36px; flex-shrink: 0;
  background: none; border: 1px solid var(--line); border-radius: var(--radius);
  color: var(--text-dim); cursor: pointer;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.theme-toggle:hover { color: var(--brand-hi); border-color: var(--brand-line); }
.theme-toggle svg { display: block; }

/* Light mode: soften the grid background so it does not overpower. */
[data-theme="light"] .grid-bg { opacity: 0.3; }

/* Light mode: dim the particle hero further. */
[data-theme="light"] .hero-particles.is-live { opacity: 0.35; }

/* Light mode: terminal shadow softens. */
[data-theme="light"] .terminal {
  box-shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.15);
}

/* Light mode: section-alt gets a subtler tint. */
[data-theme="light"] .section-alt {
  background: var(--bg-alt);
}

/* Light mode: card borders and surfaces carry over as-is via the tokens,
   but the branded glow-card gradient needs adjusting. */
[data-theme="light"] .econ-hero {
  background: linear-gradient(165deg, rgba(0, 163, 76, 0.06), var(--surface) 62%);
}
[data-theme="light"] .final {
  background: radial-gradient(ellipse 60% 100% at 50% 100%, rgba(0, 163, 76, 0.05), transparent 70%);
}

/* Light mode: CTA button shadows soften. */
[data-theme="light"] .btn-primary {
  box-shadow: 0 0 0 1px var(--brand), 0 6px 18px -8px rgba(0, 163, 76, 0.3);
}

/* Light mode: msg-bot tint. */
[data-theme="light"] .msg-bot {
  background: rgba(0, 163, 76, 0.05);
  border-color: rgba(0, 163, 76, 0.16);
}

/* Light mode: flow-step final. */
[data-theme="light"] .flow-step.is-final {
  border-color: rgba(0, 163, 76, 0.28);
  background: rgba(0, 163, 76, 0.04);
}

/* Smooth transitions for themed elements. */
.section-alt,
.board, .board-tabs, .stat, .econ-card, .sec-card, .ref-card,
.terminal, .terminal-bar, .footer, .beta-strip,
.step, .details, .faq, .faq > details, .callout,
.flow-step, .hero-flow, .hero-chat, .mobile-nav, .ticker,
.radar-card, .term, .term-bar, .trade {
  transition: background 0.3s var(--ease), border-color 0.3s var(--ease);
}

/* ============================ MOTION / PRINT ============================ */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
  .ticker-track { animation: none; }
}

/* Higher-contrast borders when the OS asks for them. */
@media (prefers-contrast: more) {
  :root { --line: #3a444f; --text-dim: #b8c2ce; --text-mute: #8b95a1; }
}

@media print {
  .grid-bg, .ticker, .nav, .final, .theme-toggle { display: none; }
  body { background: #fff; color: #000; }
  .reveal { opacity: 1; transform: none; }
}

/* ============================ DOC PAGES ============================ */

.doc { padding: clamp(44px, 6vw, 76px) 0 clamp(56px, 8vw, 92px); }
.doc-title {
  margin: 12px 0 18px; font-size: clamp(1.9rem, 4.4vw, 2.8rem);
  line-height: 1.08; letter-spacing: -0.03em; font-weight: 800;
}
.doc-lede { margin: 0 0 12px; color: var(--text-dim); font-size: clamp(0.98rem, 1.5vw, 1.08rem); }
.doc-updated {
  margin: 0 0 32px; font-family: var(--mono); font-size: 11.5px; color: var(--text-mute);
}

.doc-toc {
  display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 44px;
  padding: 16px 18px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface);
}
.doc-toc a {
  font-size: 12.5px; color: var(--text-dim); text-decoration: none;
  border: 1px solid var(--line); border-radius: 100px; padding: 5px 12px;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.doc-toc a:hover { color: var(--brand-hi); border-color: rgba(0, 224, 101, 0.34); }

.doc section { margin-bottom: 48px; scroll-margin-top: 84px; }
.doc h2 {
  margin: 0 0 16px; font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  letter-spacing: -0.02em; font-weight: 700;
  padding-bottom: 12px; border-bottom: 1px solid var(--line);
}
.doc h3 { margin: 0 0 9px; font-size: 15px; font-weight: 700; letter-spacing: -0.012em; }
.doc p { margin: 0 0 16px; color: var(--text-dim); font-size: 14.5px; }
.doc p strong, .doc li strong { color: var(--text); }
.doc .sec-grid { margin-bottom: 8px; }
.doc .ticks { margin-bottom: 16px; }
.doc .ticks li { font-size: 14.5px; }
.doc table { margin-bottom: 16px; }
.doc code {
  background: var(--surface-2); border: 1px solid var(--line);
  padding: 1px 5px; border-radius: 2px; color: var(--brand-hi);
}

.doc-back { margin: 40px 0 0; padding-top: 24px; border-top: 1px solid var(--line); }
.doc-back a { font-size: 14px; color: var(--text-dim); text-decoration: none; }
.doc-back a:hover { color: var(--brand-hi); }

.sec-more { margin: 22px 0 0; font-size: 14px; color: var(--text-dim); }
.sec-more a { color: var(--brand-hi); }

/* ==========================================================================
   TERMINAL (/terminal)
   Reuses the board's row primitives (.tk, .num, .chg, .bond) so a token reads
   identically wherever it appears. Only the shell around them is new.
   ========================================================================== */

.term-section { padding-top: 56px; }
.term-section h1 {
  margin: 0 0 12px; font-size: clamp(1.9rem, 4.2vw, 2.8rem);
  letter-spacing: -0.03em; line-height: 1.08; font-weight: 800;
}

.term {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: linear-gradient(180deg, var(--surface), var(--bg-alt));
  overflow: hidden; margin-top: 28px;
}

.term-bar {
  display: flex; align-items: center; gap: 7px;
  padding: 10px 14px; border-bottom: 1px solid var(--line);
  background: var(--bg);
}
.term-status {
  margin-left: auto; font-family: var(--mono); font-size: 10.5px;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--brand-hi);
}
/* The status reads as an instrument, not a label: a pill with a lit dot,
   but only once the script has something to say — an empty pill is noise. */
.term-status:not(:empty) {
  border: 1px solid var(--brand-line); background: var(--brand-glow);
  border-radius: 100px; padding: 3px 10px;
}
.term-status:not(:empty)::before {
  content: ""; display: inline-block; width: 6px; height: 6px;
  border-radius: 50%; background: var(--green); margin-right: 7px;
  box-shadow: 0 0 6px var(--green); vertical-align: 1px;
}

.term-log {
  padding: 18px 20px; max-height: 62vh; overflow-y: auto;
  display: grid; gap: 18px; align-content: start;
  scrollbar-width: thin;
}
/* The boot lines are a session banner, not two stray paragraphs: framed,
   with the wordmark line lit and the framing line dropped a register. */
.term-boot {
  border: 1px solid var(--line-soft); border-left: 2px solid var(--brand);
  border-radius: var(--radius); padding: 12px 14px;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
}
.term-boot p { margin: 0; font-family: var(--mono); font-size: 12.5px; color: var(--text-dim); }
.term-boot p:first-of-type {
  color: var(--brand-hi); font-weight: 700; letter-spacing: 0.05em;
}
.term-boot-sub { margin-top: 6px !important; color: var(--text-mute) !important; }

.term-entry { display: grid; gap: 12px; }
.term-echo { display: flex; gap: 9px; align-items: baseline; }
.term-echo-text {
  font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--text);
  word-break: break-word;
}
.term-prompt { font-family: var(--mono); color: var(--brand-hi); font-weight: 700; }

.term-answer { padding-left: 18px; border-left: 2px solid var(--line); }
.term-answer-err { border-left-color: var(--red); }
.term-msg {
  margin: 0; font-family: var(--mono); font-size: 13px; line-height: 1.65;
  color: var(--text-dim); white-space: pre-wrap; word-break: break-word;
}
.term-note { margin: 0; font-size: 12.5px; color: var(--text-mute); }
.term-sub {
  margin: 6px 0 0; font-family: var(--mono); font-size: 10.5px;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-mute);
}

/* The command line is the focal point of the whole page: deepest ground in
   the shell, a brand hairline above it, the prompt carried in a lit chip,
   and a glow that arrives when the visitor is actually typing in it. */
.term-input {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 14px; border-top: 1px solid var(--brand-line);
  background: var(--bg);
  transition: box-shadow 0.2s var(--ease), background 0.2s var(--ease);
}
.term-input:focus-within {
  background: var(--bg-alt);
  box-shadow: inset 0 0 0 1px var(--brand-line);
}
.term-input .term-prompt {
  background: var(--brand-glow); border: 1px solid var(--brand-line);
  border-radius: 4px; padding: 2px 8px; font-size: 13px; line-height: 1.5;
  flex: 0 0 auto;
}
.term-input input {
  flex: 1; min-width: 0; background: none; border: 0; outline: none;
  color: var(--text); font-family: var(--mono); font-size: 14px; padding: 4px 0;
  caret-color: var(--brand);
}
.term-input input::placeholder { color: var(--text-mute); }
.term-input input:disabled { opacity: 0.5; }
/* On brand green, the label is near-black — white on #00e065 is a glare,
   not a label. Scoped to the terminal's own submit so shared buttons are
   untouched. */
.term-input .btn-primary { color: #04160b; font-weight: 700; }

.term-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.chip {
  background: var(--bg-alt); border: 1px solid var(--line);
  border-radius: 100px; color: var(--text-dim);
  font-family: var(--mono); font-size: 11.5px; padding: 7px 14px;
  cursor: pointer;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease),
              transform 0.15s var(--ease), background 0.15s var(--ease);
}
.chip:hover {
  color: var(--brand-hi); border-color: rgba(0, 224, 101, 0.35);
  background: var(--surface); transform: translateY(-1px);
}

/* --- result blocks --- */

/* ---- quote card ----
   The figures the server measured, shown before anything is signed. Styled as
   a receipt rather than as transcript: this is the moment someone decides to
   spend, and it should not read like more conversation. */
.term-quote {
  border: 1px solid var(--brand-line, var(--line));
  border-radius: var(--radius);
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  box-shadow: var(--shadow-2);
  padding: 15px 16px 13px;
  max-width: 420px;
}
.term-quote-head {
  margin: 0 0 9px; font-size: 13px; font-weight: 700;
  letter-spacing: -0.01em; color: var(--text);
}
.term-quote-row {
  display: flex; justify-content: space-between; gap: 14px;
  padding: 3px 0; font-size: 12px;
}
.term-quote-k { color: var(--text-mute); }
.term-quote-v {
  font-family: var(--mono); color: var(--text);
  text-align: right; word-break: break-word;
}
.term-quote-actions { display: flex; gap: 8px; margin-top: 12px; }
.term-quote-actions .btn:disabled { opacity: 0.5; pointer-events: none; }
/* Same rule as the command line's submit: on brand green the label is
   near-black. Scoped to the quote card, a terminal surface. */
.term-quote-actions .btn-primary { color: #04160b; }
.term-quote .term-note { margin-top: 9px; }
.term-link {
  display: inline-block; margin-top: 6px;
  font-family: var(--mono); font-size: 11.5px;
  color: var(--brand-hi); word-break: break-all;
}

.term-stats {
  display: grid; gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--radius);
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); overflow: hidden;
}
.term-stat { background: var(--surface); padding: 12px 14px; display: grid; gap: 4px; }
.term-stat-label {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-mute);
}
.term-stat-value { font-family: var(--mono); font-size: 15px; font-weight: 700; color: var(--text); }

.term-table {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow-x: auto;
}
.term-row {
  display: grid;
  grid-template-columns: minmax(150px, 2.1fr) minmax(60px, 1fr) minmax(70px, 1fr)
                         minmax(70px, 1fr) minmax(52px, 0.7fr) minmax(80px, 1.2fr);
  gap: 14px; align-items: center; padding: 11px 16px;
  border-bottom: 1px solid var(--line-soft); font-size: 13px; min-width: 620px;
}
.term-table-wallet .term-row {
  grid-template-columns: minmax(150px, 2.1fr) minmax(70px, 1fr)
                         minmax(70px, 1fr) minmax(70px, 1fr) minmax(80px, 1.2fr);
  min-width: 560px;
}
.term-row:last-child { border-bottom: 0; }
.term-row:not(.term-row-head) { transition: background 0.12s var(--ease); }
.term-row:not(.term-row-head):hover { background: var(--surface-2); }
.term-row-head {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-mute); background: var(--bg-alt);
}
a.tk-sym { color: var(--text); text-decoration: none; }
a.tk-sym:hover { color: var(--brand-hi); }

.term-token {
  display: grid; gap: 16px; border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  box-shadow: var(--shadow-1);
}
.term-token-head { display: flex; align-items: center; gap: 13px; flex-wrap: wrap; }
.term-token-titles { display: grid; min-width: 0; }
.term-token-sym {
  font-family: var(--mono); font-size: 18px; font-weight: 800;
  color: var(--text); text-decoration: none; letter-spacing: -0.01em;
}
a.term-token-sym:hover { color: var(--brand-hi); }
.term-token-name { font-size: 12.5px; color: var(--text-mute); }
.term-token-badges { display: flex; gap: 7px; flex-wrap: wrap; margin-left: auto; }
.badge {
  font-family: var(--mono); font-size: 10.5px; padding: 4px 9px;
  border-radius: 100px; border: 1px solid rgba(0, 224, 101, 0.3);
  color: var(--brand-hi); background: rgba(0, 224, 101, 0.07); white-space: nowrap;
}
.badge-dim {
  color: var(--text-mute); border-color: var(--line); background: var(--surface-2);
}
.term-bond { display: grid; gap: 7px; }
.term-mint { margin: 0; display: grid; gap: 4px; min-width: 0; }
.term-mint code {
  font-family: var(--mono); font-size: 11.5px; color: var(--text-dim);
  word-break: break-all;
}

/* Token detail page: a code value with a copy button beside it. */
.mint-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0; }
.mint-row code {
  font-family: var(--mono); font-size: 11.5px; color: var(--text-dim);
  word-break: break-all;
}
.copy-btn {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius);
  color: var(--text-dim); font-family: var(--mono); font-size: 10.5px; padding: 3px 9px;
  cursor: pointer; flex-shrink: 0;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.copy-btn:hover { color: var(--brand-hi); border-color: rgba(0, 224, 101, 0.35); }
.copy-btn.copied { color: var(--brand-hi); border-color: rgba(0, 224, 101, 0.35); }

.term-pairs {
  display: grid; gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--radius);
  grid-template-columns: repeat(auto-fill, minmax(155px, 1fr)); overflow: hidden;
}
.term-pair { background: var(--surface); padding: 11px 13px; display: grid; gap: 3px; min-width: 0; }
.term-pair-sym { font-family: var(--mono); font-size: 13px; font-weight: 700; }
.term-pair-name,
.term-pair-cat {
  font-size: 11px; color: var(--text-mute);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.term-pair-cat { color: var(--brand-dim); font-family: var(--mono); font-size: 10px; }

.term-wallet { display: grid; gap: 14px; }

.term-notes { margin-top: 52px; max-width: 780px; }
.term-notes h2 {
  margin: 32px 0 14px; font-size: 1.15rem; font-weight: 700; letter-spacing: -0.02em;
  padding-bottom: 11px; border-bottom: 1px solid var(--line);
}
.term-notes h2:first-child { margin-top: 0; }
.term-notes p { margin: 0; color: var(--text-dim); font-size: 14.5px; }
.term-ref { margin: 0; display: grid; gap: 16px; }
.term-ref dt { font-family: var(--mono); font-size: 12.5px; color: var(--brand-hi); }
.term-ref dd { margin: 5px 0 0; color: var(--text-dim); font-size: 14px; }
.term-ref code {
  background: var(--surface-2); border: 1px solid var(--line);
  padding: 1px 5px; border-radius: 2px; color: var(--brand-hi);
}

@media (max-width: 640px) {
  .term-log { padding: 14px; max-height: 58vh; }
  .term-answer { padding-left: 12px; }
  .term-token-badges { margin-left: 0; }
  /* `.btn { width: 100% }` at this breakpoint is right for a page of stacked
     CTAs and wrong for a prompt: it squeezed the input to nothing and left a
     terminal you could not type into. */
  .term-input .btn { width: auto; flex: 0 0 auto; }
  .term-input input { min-width: 0; }
}

.live-more {
  margin: 14px 0 0; font-size: 14px; color: var(--text-dim); text-align: center;
}
.live-more a { color: var(--brand-hi); }

.term-creator {
  background: none; border: 0; padding: 0; text-align: left;
  font-family: var(--mono); font-size: 11.5px; color: var(--brand-hi);
  cursor: pointer; text-decoration: underline; text-underline-offset: 2px;
}
.term-creator:hover { color: #2ad98a; }

/* A launch record has different columns from a token — no market data. */
.term-table-launch .term-row {
  grid-template-columns: minmax(150px, 2.1fr) minmax(70px, 1fr)
                         minmax(80px, 1fr) minmax(70px, 1fr) minmax(80px, 1fr);
  min-width: 560px;
}

/* ============================ ACCOUNT ============================ */

.acct-status { display: block; margin: 0 0 28px; }

#acct-signin { display: grid; gap: 18px; max-width: 640px; }
.acct-actions { display: flex; flex-wrap: wrap; gap: 12px; }
/* The copy button sits under the address inside a card, where the sign-in
   buttons it shares a class with do not. */
.sec-card .acct-actions { margin: 12px 0 0; }

.acct-list { margin: 12px 0 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.acct-list li {
  font-family: var(--mono); font-size: 12.5px; color: var(--text-dim);
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 8px 11px; word-break: break-word;
}

/* ---------------- launch flow ----------------
   The state machine lives in one card that spans the full grid row: itemised
   costs and a confirm/cancel pair need more width than a 262px sec-card gives
   the other tiles. */
.sec-card-wide { grid-column: 1 / -1; }

.launch-state {
  margin: 14px 0 16px; font-family: var(--mono); font-size: 10.5px;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--brand-hi);
}
.launch-state.is-err { color: var(--red); }
.launch-state.is-warn { color: #e0a33a; }

.launch-form { display: grid; gap: 16px; max-width: 480px; }
.launch-field { display: grid; gap: 7px; }
.launch-field span { font-size: 12.5px; color: var(--text-dim); }
.launch-field input,
.launch-field select {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius);
  color: var(--text); font-family: var(--sans); font-size: 14.5px;
  padding: 11px 13px; width: 100%;
}
.launch-field input:disabled,
.launch-field select:disabled { opacity: 0.5; cursor: not-allowed; }
.launch-field input::placeholder { color: var(--text-mute); }

.launch-costs { margin: 0 0 18px; padding: 0; list-style: none; display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; max-width: 480px; }
.launch-costs li {
  display: flex; justify-content: space-between; gap: 14px;
  background: var(--surface); padding: 11px 14px; font-size: 13.5px;
}
.launch-costs li span:first-child { color: var(--text-dim); }
.launch-costs li span:last-child { font-family: var(--mono); color: var(--text); }
.launch-costs .launch-total span:last-child { color: var(--brand-hi); font-weight: 700; }

.launch-spin {
  display: inline-block; width: 12px; height: 12px; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: var(--brand-hi);
  animation: launch-spin 0.8s linear infinite; margin-right: 8px; vertical-align: -1px;
}
@keyframes launch-spin { to { transform: rotate(360deg); } }

.launch-mint { word-break: break-all; }

@media (max-width: 480px) {
  .launch-form,
  .launch-costs { max-width: none; }
}

/* This page has no mobile-nav toggle behind it — account.js only fetches
   /api/auth, it does not wire one up like main.js/terminal.js do for their
   pages — so hiding .nav-links behind a button that nothing opens would strand
   mobile visitors with no navigation at all. Kept visible and let it wrap
   instead of collapsing behind dead UI. */
.nav-simple .nav-links { display: flex; }
@media (max-width: 480px) {
  .nav-simple .nav-inner { height: auto; padding: 10px 0; }
  .nav-simple .nav-links { flex-wrap: wrap; gap: 10px 16px; margin-left: 0; width: 100%; }
}

/* ============================== RADAR ==============================
   The trading-desk surface. Dense, monospaced figures, one accent.
   Numbers are right-aligned and tabular so a column scans vertically —
   the whole point of a desk is that your eye finds the outlier without
   reading every row. */

.radar-section { padding-top: clamp(28px, 4vw, 44px); padding-bottom: clamp(20px, 3vw, 32px); }

.radar-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; margin-bottom: clamp(20px, 3vw, 30px);
}
.radar-head h1 {
  margin: 0; font-size: clamp(1.7rem, 3.4vw, 2.45rem);
  line-height: 1.1; letter-spacing: -0.03em; font-weight: 700;
}
.radar-meta { display: flex; align-items: center; gap: 12px; }
.radar-stamp {
  margin: 0; font-family: var(--mono); font-size: 11.5px;
  color: var(--text-mute); letter-spacing: 0.02em;
}

.radar-grid {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
}

.radar-card {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
  display: flex; flex-direction: column;
  /* A hairline of brand at the top edge, so a column reads as a panel in a
     desk rather than a card floating on a marketing page. */
  box-shadow: inset 0 1px 0 0 var(--brand-line);
}

.radar-card-head { padding: 14px 16px 12px; border-bottom: 1px solid var(--line-soft); }
.radar-card-head h2 {
  margin: 0 0 3px; font-size: 12px; font-weight: 700;
  font-family: var(--mono); letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--brand-hi);
}
.radar-card-head p { margin: 0; font-size: 12px; color: var(--text-mute); line-height: 1.4; }

.radar-body { display: flex; flex-direction: column; }

.radar-row {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "main val" "meta val";
  align-items: center; gap: 0 12px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--line-soft);
  text-decoration: none; color: var(--text);
  transition: background 0.12s var(--ease);
}
.radar-body > .radar-row:last-child { border-bottom: 0; }
a.radar-row:hover { background: var(--surface-2); }
a.radar-row:hover .radar-sym { color: var(--brand-hi); }

.radar-row-main { grid-area: main; display: flex; align-items: baseline; gap: 7px; min-width: 0; }
.radar-row-meta { grid-area: meta; display: flex; align-items: baseline; gap: 8px; min-width: 0; }

.radar-sym {
  font-family: var(--mono); font-size: 13px; font-weight: 700;
  letter-spacing: 0.02em; transition: color 0.12s var(--ease);
}
.radar-pair { font-family: var(--mono); font-size: 11px; color: var(--text-mute); }
.radar-tag {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--brand-hi);
  border: 1px solid var(--brand-line); border-radius: 2px; padding: 1px 5px;
}
.radar-name {
  font-size: 11.5px; color: var(--text-mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 26ch;
}
.radar-age { font-family: var(--mono); font-size: 11px; color: var(--text-mute); }

.radar-val {
  grid-area: val; font-family: var(--mono); font-size: 12.5px;
  color: var(--text); text-align: right; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.radar-val.is-progress { color: var(--green); font-weight: 700; }
.radar-val.is-age { color: var(--text-dim); }

/* Bonding progress, drawn as a hairline across the bottom of its row rather
   than as another column: it is context for the number already shown. */
.radar-bar {
  position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
  background: var(--line-soft);
}
.radar-bar-fill { display: block; height: 100%; background: var(--green); }

.radar-empty { margin: 0; padding: 18px 16px; font-size: 12.5px; color: var(--text-mute); }

.radar-note {
  margin: 18px 0 0; font-size: 12.5px; color: var(--text-mute);
  max-width: 78ch; line-height: 1.6;
}

@media (max-width: 560px) {
  .radar-head { align-items: flex-start; }
  .radar-name { max-width: 18ch; }
}

/* The query terminal sits below radar now, so it needs a little air and a
   quieter heading — it is the second thing on this page, not the first. */
.term-section { padding-top: clamp(24px, 3.5vw, 40px); }
.term-section h1 { font-size: clamp(1.4rem, 2.6vw, 1.85rem); }

/* ============================== TRADE ============================== */

.trade {
  margin-top: clamp(22px, 3vw, 34px);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
  box-shadow: inset 0 1px 0 0 var(--brand-line);
}
.trade-head { padding: 16px 18px 12px; border-bottom: 1px solid var(--line-soft); }
.trade-head h2 {
  margin: 0 0 3px; font-size: 12px; font-weight: 700; font-family: var(--mono);
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--brand-hi);
}
.trade-head h2 .badge { margin-left: 8px; text-transform: none; letter-spacing: 0.02em; vertical-align: middle; }
.trade-sub { margin: 0; font-size: 12px; color: var(--text-mute); }
.trade-body { padding: 16px 18px; display: flex; flex-direction: column; gap: 14px; align-items: flex-start; }

.trade-sides { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.trade-side {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  font-family: var(--mono); font-size: 12px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-mute); padding: 8px 18px;
  transition: color 0.12s var(--ease), background 0.12s var(--ease);
}
.trade-side:hover { color: var(--text); }
.trade-side.is-active { color: var(--brand-hi); background: var(--brand-glow); }

.trade-amounts { display: flex; flex-wrap: wrap; gap: 8px; }
.trade-amt {
  appearance: none; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface-2); color: var(--text-dim);
  font-family: var(--mono); font-size: 12.5px; padding: 9px 14px;
  font-variant-numeric: tabular-nums;
  transition: color 0.12s var(--ease), border-color 0.12s var(--ease);
}
.trade-amt:hover { color: var(--text); border-color: var(--text-mute); }
.trade-amt.is-active { color: var(--brand-hi); border-color: var(--brand-line); background: var(--brand-glow); }

.trade-quote {
  display: grid; grid-template-columns: auto 1fr; gap: 7px 20px;
  margin: 0; width: 100%; max-width: 460px;
  padding: 14px 16px; border: 1px solid var(--line-soft);
  border-radius: var(--radius); background: var(--bg-alt);
}
.trade-quote dt { font-size: 12.5px; color: var(--text-mute); }
.trade-quote dd {
  margin: 0; font-family: var(--mono); font-size: 12.5px; color: var(--text);
  text-align: right; font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

.trade-pos { margin: 0 0 10px; font-size: 13px; color: var(--text-dim); }
.trade-pos strong { font-family: var(--mono); color: var(--text); }
.trade-empty, .trade-error, .trade-done, .trade-sig { margin: 0; font-size: 13px; }
.trade-empty { color: var(--text-mute); }
.trade-error { color: var(--red); }
.trade-done { color: var(--green); font-weight: 700; }
.trade-sig code { font-family: var(--mono); font-size: 12px; color: var(--text-dim); }

.trade-risk {
  margin: 0; padding: 12px 18px 16px; font-size: 12px; line-height: 1.6;
  color: var(--text-mute); border-top: 1px solid var(--line-soft);
}
.trade-risk-compact { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.trade-risk-compact a { color: var(--text-dim); text-decoration: underline; white-space: nowrap; }
.trade-risk-compact a:hover { color: var(--green); }

/* ============================================================
   TERMINAL APP SHELL  (terminal.html)
   A workspace, not a marketing scroll: command pane is the hero,
   radar is a live rail. Reuses .term-* and .radar-* atoms; only the
   layout is new. All ids/classes are radar.js / terminal.js hooks.
   ============================================================ */

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.tapp { position: relative; padding: clamp(28px, 4vw, 48px) 0 clamp(48px, 7vw, 88px); }
.tapp-wrap { width: 100%; max-width: 1320px; margin: 0 auto; padding: 0 24px; }

.tapp-head {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 32px;
  margin-bottom: clamp(20px, 3vw, 32px);
}
.tapp-head-main { min-width: 0; }
.tapp-head h1 {
  margin: 6px 0 0; font-size: clamp(1.9rem, 3.6vw, 2.75rem);
  letter-spacing: -0.03em; line-height: 1.05; font-weight: 800;
}
.tapp-head-sub {
  margin: 0; color: var(--text-dim); font-size: 0.95rem; line-height: 1.5;
  max-width: 52ch; flex: 1 1 320px;
}

/* ---- bot mark ----
   One drawn mark for the bot, so the product has a face that is the same face
   in the page header, the floating widget's avatar and its launcher. It is a
   drawing, not a data claim: nothing here stands in for a number or a token's
   own artwork. currentColor throughout, so it inherits the theme instead of
   carrying a second palette. */
.botmark {
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--brand-hi);
}
.botmark svg { width: 100%; height: 100%; display: block; }
.botmark-lg {
  width: 42px; height: 42px; margin-bottom: 12px;
  border: 1px solid var(--brand-line); border-radius: 12px;
  background: var(--brand-glow); padding: 6px;
  box-shadow: 0 8px 24px -12px var(--brand);
}

/* The rail is gone — the bot gets the width. See the note in terminal.html. */
.tapp-grid {
  display: grid; gap: clamp(16px, 2vw, 24px);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

/* ---- starter cards (empty state) ---- */
.term-starters { display: grid; gap: 12px; }
.term-starters-h {
  margin: 0; font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--text-dim);
}
.term-starter-grid {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(248px, 1fr));
}
.starter {
  display: grid; gap: 8px; align-content: start;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px 16px 14px;
  transition: border-color 0.15s var(--ease), transform 0.15s var(--ease),
              box-shadow 0.2s var(--ease);
}
.starter:hover {
  border-color: rgba(0, 224, 101, 0.35);
  transform: translateY(-2px); box-shadow: var(--shadow-2);
}
.starter-tag {
  justify-self: start; font-family: var(--mono); font-size: 9.5px;
  letter-spacing: 0.12em; text-transform: uppercase; font-weight: 700;
  color: var(--text-dim); border: 1px solid var(--line);
  background: var(--bg-alt);
  border-radius: 100px; padding: 3px 8px;
}
/* The one card that moves money carries the brand tint, so the eye learns
   where the consequential door is before it reads a word. */
.starter-tag[data-tag="trade"] {
  color: var(--brand-hi); border-color: var(--brand-line);
  background: var(--brand-glow);
}
.starter-q {
  margin: 0; font-size: 14.5px; font-weight: 700; line-height: 1.35;
  letter-spacing: -0.01em; color: var(--text);
}
.starter-d { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--text-dim); }
.starter-go {
  justify-self: start; margin-top: 4px; cursor: pointer;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-hi); background: none; border: 0; padding: 4px 0;
  border-bottom: 1px solid transparent;
  transition: border-color 0.15s var(--ease);
}
.starter-go::after { content: " \2192"; }
.starter-go:hover { border-bottom-color: currentColor; }
.term-starters-foot {
  margin: 2px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--text-mute);
}

/* ---- command pane ---- */
.tapp-pane { min-width: 0; display: grid; gap: 14px; align-content: start; }
.tapp-pane .term {
  margin-top: 0;
  box-shadow: 0 1px 0 var(--line-soft), 0 32px 80px -40px rgba(0,0,0,0.95),
              0 0 0 1px rgba(0,0,0,0.35);
}
/* The log is a working surface, not a void: a faint dot grid and a brand
   wash from the top give the empty state structure without inventing
   content, and the height is a desk's working height — tall enough to read
   a table in, not a shaft the boot lines fall down. (A scanline grain was
   tried first; at 3px pitch it moirés on screenshot and reads as damage,
   where the dot grid just reads as graph paper.) */
.tapp-pane .term-log {
  min-height: clamp(300px, 44vh, 560px); max-height: 62vh;
  background-image:
    radial-gradient(rgb(190 255 205 / 0.05) 1px, transparent 1.4px),
    radial-gradient(115% 80% at 50% 0%, rgb(0 224 101 / 0.05), transparent 55%);
  background-size: 22px 22px, 100% 100%;
}
.tapp-pane .term-chips { margin-top: 0; }

.tapp-help { border-top: 1px solid var(--line-soft); padding-top: 4px; }
.tapp-help > summary {
  cursor: pointer; list-style: none; padding: 10px 2px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-mute);
  transition: color 0.15s var(--ease);
}
.tapp-help > summary:hover { color: var(--brand-hi); }
.tapp-help > summary::-webkit-details-marker { display: none; }
.tapp-help > summary::before { content: "+ "; color: var(--brand-hi); }
.tapp-help[open] > summary::before { content: "– "; }
.tapp-help[open] > summary { color: var(--text-dim); }
.tapp-help .term-ref { margin: 8px 0 4px; }
.tapp-help .term-note { margin-top: 10px; }

/* Log scrollbar, understated */
.tapp-pane .term-log::-webkit-scrollbar { width: 8px; }
.tapp-pane .term-log::-webkit-scrollbar-thumb {
  background: var(--line); border-radius: 100px;
}

@media (max-width: 560px) {
  .tapp-wrap { padding: 0 16px; }
  .tapp-pane .term-log { min-height: 260px; }
  .term-starter-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   BUTLER CHAT (chatbot.js) — the same desk, in the same system
   chatbot.js injects its own <style> at runtime, and that sheet still
   carries the old purple palette in its shadows, chips and header wash.
   Its rules are single-class, so everything here is prefixed with
   .cb-widget (two classes beat one — the same trick the tab-bar fix
   below uses) and the script itself is untouched. What this buys: the
   chat stops being a second, rounder, paler product floating over the
   terminal and becomes the same desk — same tokens, same radius, brand
   green read as near-black text wherever it fills a control.
   ============================================================ */

.cb-widget .cb-fab {
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-dim) 100%);
  color: #04160b;
  box-shadow: 0 10px 30px -8px rgba(0, 224, 101, 0.5), 0 2px 8px rgba(0, 0, 0, 0.45);
}
.cb-widget .cb-fab:hover {
  box-shadow: 0 14px 36px -8px rgba(0, 224, 101, 0.6), 0 3px 12px rgba(0, 0, 0, 0.45);
}
.cb-widget .cb-panel {
  background: linear-gradient(180deg, var(--surface) 0%, var(--bg-alt) 100%);
  border: 1px solid var(--brand-line);
  border-radius: 14px;
  box-shadow: var(--shadow-3), 0 0 0 1px rgba(0, 0, 0, 0.35);
}
.cb-widget .cb-header {
  background: linear-gradient(135deg, rgba(0, 224, 101, 0.13) 0%, rgba(0, 224, 101, 0.03) 100%);
  border-bottom: 1px solid var(--brand-line);
  padding: 14px 16px;
}
.cb-widget .cb-title {
  font-family: var(--mono); font-size: 12.5px; letter-spacing: 0.16em;
}
.cb-widget .cb-subtitle { color: var(--text-dim); font-size: 11.5px; }
.cb-widget .cb-status-dot {
  background: var(--green); box-shadow: 0 0 8px var(--green);
}
/* The chat log gets the command log's treatment, one register lighter:
   a brand wash from the top so the empty panel has structure. */
.cb-widget .cb-log {
  padding: 18px 16px; gap: 14px;
  background-image: radial-gradient(115% 70% at 50% 0%, rgb(0 224 101 / 0.04), transparent 55%);
  scrollbar-color: var(--line) transparent;
}
.cb-widget .cb-msg { max-width: 86%; }
.cb-widget .cb-msg-inner { gap: 10px; }
.cb-widget .cb-avatar {
  background: linear-gradient(135deg, var(--brand), var(--brand-dim));
  color: #04160b; border: 1px solid var(--brand-line); border-radius: 9px;
}
.cb-widget .cb-msg-text {
  font-size: 13.5px; line-height: 1.6; padding: 11px 14px; border-radius: 12px;
}
.cb-widget .cb-msg-user .cb-msg-text {
  background: linear-gradient(135deg, var(--brand), var(--brand-dim));
  color: #04160b; font-weight: 550; border-bottom-right-radius: 4px;
}
.cb-widget .cb-msg-bot .cb-msg-text {
  background: var(--surface-2); border: 1px solid var(--line);
  border-bottom-left-radius: 4px;
}
.cb-widget .cb-msg-err .cb-msg-text {
  color: var(--red); border-color: rgba(246, 70, 93, 0.3);
}
.cb-widget .cb-chip {
  background: var(--brand-glow); border-color: var(--brand-line);
  color: var(--brand-hi); font-family: var(--mono); font-size: 11.5px;
  font-weight: 600; padding: 7px 13px;
}
.cb-widget .cb-chip:hover {
  background: rgba(0, 224, 101, 0.22); border-color: var(--brand);
}
.cb-widget .cb-form {
  background: var(--bg); border-top: 1px solid var(--brand-line);
  padding: 12px;
}
.cb-widget .cb-input {
  background: var(--surface); border-color: var(--line);
  border-radius: var(--radius); font-size: 13.5px; padding: 11px 13px;
  caret-color: var(--brand);
}
.cb-widget .cb-input:focus {
  border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-glow);
}
.cb-widget .cb-send {
  background: linear-gradient(135deg, var(--brand), var(--brand-dim));
  color: #04160b; border-radius: var(--radius); width: 42px;
}
.cb-widget .cb-action-btn {
  background: linear-gradient(135deg, var(--brand), var(--brand-dim));
  color: #04160b;
}
.cb-widget .cb-footer { background: var(--bg-alt); }
.cb-widget .cb-quote {
  background: var(--bg); border-color: var(--brand-line);
  border-radius: var(--radius);
}
.cb-widget .cb-quote-head {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em;
  text-transform: uppercase;
}
.cb-widget .cb-quote-go {
  background: linear-gradient(135deg, var(--brand), var(--brand-dim));
  color: #04160b; border-radius: var(--radius);
}
.cb-widget .cb-quote-no { border-radius: var(--radius); }
.cb-widget .cb-badge {
  background: var(--red); box-shadow: 0 2px 6px rgba(246, 70, 93, 0.5);
}

/* Hero mode is the /terminal page itself: a touch less height than the
   injected default, so the panel reads as a desk on the page rather than
   a shaft under the header. */
.cb-widget.cb-hero .cb-panel {
  border-radius: 14px; height: min(640px, calc(100vh - 240px));
}


/* ==========================================================================
   TOP-BAR STAT RAIL
   Present under the header on every page. Ships hidden; main.js unhides it
   only once a real /api/live payload lands, so a failed fetch shows no rail
   rather than a rail of em dashes.
   ========================================================================== */

.statrail {
  border-bottom: 1px solid var(--line-soft);
  background: var(--bg-alt);
}
.statrail-inner {
  display: flex; align-items: stretch; gap: 0;
  overflow-x: auto; scrollbar-width: none;
}
.statrail-inner::-webkit-scrollbar { display: none; }
/* Set by main.js only while the rail actually overflows. The gradient fades
   the last 34px so a clipped item reads as "there is more this way" instead of
   as text that stopped mid-word, and lifts once the reader reaches the end. */
.statrail.is-scrollable .statrail-inner {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent 100%);
  mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent 100%);
}
.statrail.is-scrollable.is-scrolled-end .statrail-inner {
  -webkit-mask-image: none;
  mask-image: none;
}
.statrail-item {
  display: flex; align-items: baseline; gap: 8px;
  padding: 9px 20px 9px 0; margin-right: 20px;
  border-right: 1px solid var(--line-soft);
  white-space: nowrap;
}
.statrail-item:last-child { border-right: 0; margin-right: 0; }
.statrail-k {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--text-mute);
}
.statrail-v { font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--text); }
/* The reason a figure is an em dash, carried next to it rather than left to
   be read as a zero or as a loading state. */
.statrail-note {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.04em;
  color: var(--text-mute); opacity: 0.8;
}
@media (max-width: 700px) {
  .statrail-opt { display: none; }
  .statrail-item { padding-right: 14px; margin-right: 14px; }
}

/* ==========================================================================
   HERO PRIVACY LINE
   ========================================================================== */

/* The bottom margin is not cosmetic. With `margin: 1.1rem 0 0` this paragraph
   ran straight into .cta-row, and because the last thing in it is an
   underlined link the underline touched the top edge of the Launch button —
   the two read as one control. .cta-row carries only a bottom margin, so the
   clearance has to come from here. */
.hero-privacy {
  margin: 1.1rem 0 1.6rem; font-size: 0.9rem; line-height: 1.6; color: var(--text-dim);
  max-width: 560px;
}
.hero-privacy-badge {
  display: inline-block; margin-right: 8px; padding: 2px 9px;
  border: 1px solid var(--brand-line); border-radius: 100px;
  background: var(--brand-glow);
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--brand-hi);
}

/* ==========================================================================
   FAQ TEASER (homepage)
   ========================================================================== */

.faq-teaser {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1.5rem;
}
.faq-teaser-list {
  list-style: none; margin: 0 0 1.25rem; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px 24px;
}
.faq-teaser-list a { color: var(--text-dim); text-decoration: none; font-size: 0.92rem; }
.faq-teaser-list a:hover { color: var(--text); }
.final-inline {
  margin-top: 2.5rem; padding: 1.75rem; text-align: center;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
}
.final-inline h2 { font-family: var(--mono); font-size: 1.15rem; margin: 0 0 0.5rem; }
.final-inline p { color: var(--text-dim); font-size: 0.9rem; margin: 0 0 1.1rem; }
@media (max-width: 620px) { .faq-teaser-list { grid-template-columns: 1fr; } }

/* ==========================================================================
   CHARTS
   The iframe is the provider's document. `chart-empty` is the state that
   matters most: it carries the reason no chart could be drawn, and it must
   never be mistaken for a chart that is still loading.
   ========================================================================== */

.chart-tabs { display: flex; gap: 6px; }
.chart-tab {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text-dim);
  font-family: var(--mono); font-size: 11px; padding: 6px 11px;
  cursor: pointer; transition: border-color 0.15s var(--ease), color 0.15s var(--ease);
}
.chart-tab span { font-size: 9px; letter-spacing: 0.09em; text-transform: uppercase; color: var(--text-mute); }
.chart-tab:hover:not(:disabled) { border-color: var(--brand-line); color: var(--text); }
.chart-tab.is-active { border-color: var(--brand); color: var(--text); background: var(--brand-glow); }
.chart-tab:disabled { opacity: 0.4; cursor: not-allowed; }

/* A fixed 380px min-height read as a real chart's height in a narrow column
   but flattened badly the moment the pane got wide — on /live's two-column
   grid the chart column can run 800-900px wide against the same 380px, a
   ~2.3:1 slab rather than anything a trading terminal would ship. Sizing off
   viewport height instead keeps the frame tall enough to read as a chart
   regardless of how wide its column is, within a floor and ceiling so it
   never gets uselessly short on a small laptop or absurdly tall on a big
   monitor. Kept equal to .live-rows' max-height below so the two panes read
   as one terminal, not two mismatched cards. */
.chart-host {
  position: relative; height: clamp(440px, 56vh, 640px);
  display: flex; flex-direction: column;
}
.chart-frame {
  width: 100%; flex: 1 1 auto; min-height: 0; border: 0;
  background: var(--bg-alt); border-radius: var(--radius);
}
.chart-empty {
  margin: auto; padding: 2rem 1.25rem; text-align: center;
  color: var(--text-dim); font-size: 0.88rem; line-height: 1.6; max-width: 42ch;
}
.chart-empty-sub { color: var(--text-mute); font-size: 0.8rem; margin-top: 0.5rem; }
.chart-note {
  margin: 0.65rem 0 0; font-size: 0.76rem; line-height: 1.55; color: var(--text-mute);
}
.chart-note code { font-family: var(--mono); color: var(--text-dim); }
.chart-note strong { color: var(--amber); }
.chart-title { font-family: var(--mono); font-size: 0.95rem; margin: 0; }

.tok-chart {
  margin-top: 1.5rem; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 1rem 1.15rem 1.15rem;
}

/* ==========================================================================
   LIVE TERMINAL (/live)
   ========================================================================== */

.live-page { padding: 2rem 0 3rem; }
.live-page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 1.25rem;
}
.live-page-head h1 { font-size: clamp(1.5rem, 3vw, 2rem); margin: 0.35rem 0 0; }

.live-grid { display: grid; grid-template-columns: minmax(300px, 400px) 1fr; gap: 16px; align-items: start; }
.live-pane {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 0.9rem 1rem 1rem;
}
.live-pane-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; margin-bottom: 0.8rem;
}
.live-pane-head h2 { font-family: var(--mono); font-size: 0.95rem; margin: 0; }
/* Matches .chart-host's height exactly (see the comment there) so the list
   and the chart beside it read as one panel of equal height, not a tall
   chart next to a shorter list or vice versa. */
/* One track definition shared by the header and every row, so a column and its
   heading cannot drift apart. The last track is the optional "no pool" flag. */
.live-rows {
  --live-cols: minmax(0, 1.6fr) minmax(0, 0.9fr) minmax(0, 0.9fr) minmax(0, 0.6fr) auto;
  max-height: clamp(440px, 56vh, 640px); overflow-y: auto;
}

/* Sortable column header. Sticky so the labels stay with the numbers while the
   list scrolls under them. */
.live-head-row {
  display: grid; grid-template-columns: var(--live-cols); gap: 10px;
  position: sticky; top: 0; z-index: 2;
  background: var(--surface); border-bottom: 1px solid var(--line);
}
.live-h {
  display: flex; align-items: center; gap: 4px;
  padding: 7px 8px; background: none; border: 0; color: var(--text-mute);
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.09em;
  text-transform: uppercase; cursor: pointer; white-space: nowrap;
  transition: color 0.12s var(--ease);
}
.live-h:hover { color: var(--text); }
.live-h.is-sorted { color: var(--brand-hi); }
/* Right-aligned to sit over the figures, which are right-aligned themselves. */
.live-h-num { justify-content: flex-end; text-align: right; }
.live-h-caret { font-size: 9px; }

/* A row is a button: it selects the chart. The outbound links for whatever is
   selected live in the chart panel, so nothing interactive is ever nested
   inside anything else interactive. */
.live-row {
  display: grid;
  grid-template-columns: var(--live-cols);
  gap: 10px; align-items: center; width: 100%; text-align: left;
  padding: 9px 8px; background: none; border: 0;
  border-bottom: 1px solid var(--line-soft); color: inherit;
  font: inherit; font-size: 13px; cursor: pointer;
  transition: background 0.12s var(--ease);
}
.live-row:last-child { border-bottom: 0; }
.live-row:hover, .live-row:focus-visible { background: var(--surface-2); }
.live-row.is-selected { background: var(--brand-glow); box-shadow: inset 2px 0 0 var(--brand); }
.live-row-id { display: flex; align-items: center; gap: 9px; min-width: 0; }
.live-row-mcap, .live-row-vol, .live-row-chg { font-family: var(--mono); font-size: 12px; text-align: right; }
.live-row-flag {
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-mute);
  border: 1px solid var(--line); border-radius: 100px; padding: 1px 6px;
}
.chart-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 0.9rem; }

@media (max-width: 900px) {
  .live-grid { grid-template-columns: 1fr; }
  .live-rows { max-height: 340px; }
  /* Stacked single-column layout: width, not viewport height, is the
     constrained dimension here, so the chart is sized off it instead —
     tall enough to read as a chart, capped so it doesn't push the list
     off a short phone screen before anyone scrolls. */
  .chart-host { height: min(85vw, 420px); }
}

/* ==========================================================================
   ADVANTAGE (/advantage)
   ========================================================================== */

.adv-hero { padding: 5rem 0 2rem; text-align: center; }
.adv-hero h1 {
  font-size: clamp(1.9rem, 5vw, 2.9rem);
  line-height: 1.1; margin: 0.6rem 0 1rem;
}
.adv-hero .lede { color: var(--text-dim); font-size: 1.02rem; line-height: 1.7; margin: 0 auto 1.75rem; }
.adv-hero .cta-row { justify-content: center; }

.adv-numbers { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 1.5rem; }
.adv-num {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1.5rem;
}
.adv-num-value { font-family: var(--mono); font-size: 3rem; font-weight: 700; line-height: 1; margin: 0; }
.adv-num-value .unit { font-size: 1.1rem; margin-left: 4px; color: var(--text-mute); }
.adv-num-label {
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--text-mute); margin: 0.6rem 0 0.75rem;
}
.adv-num-desc { color: var(--text-dim); font-size: 0.88rem; line-height: 1.65; margin: 0 0 0.9rem; }

.adv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); gap: 14px; }
.adv-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1.25rem;
}
.adv-card h3 { font-family: var(--mono); font-size: 0.95rem; margin: 0 0 0.55rem; }
.adv-card h4 { font-family: var(--mono); font-size: 0.9rem; margin: 0 0 0.45rem; }
.adv-card p { color: var(--text-dim); font-size: 0.87rem; line-height: 1.65; margin: 0; }
.adv-card-warn { border-color: rgba(229, 72, 77, 0.35); }
.adv-card-warn h3 { color: var(--red); }
.adv-fine { color: var(--text-mute); font-size: 0.83rem; margin-top: 1.25rem; }

.adv-flowgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; }
.adv-card-lead { position: relative; padding-top: 2.4rem; }
.adv-step {
  position: absolute; top: 1.1rem; left: 1.25rem;
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.12em; color: var(--brand-hi);
}
.adv-link {
  display: inline-block; margin-top: 0.85rem; font-family: var(--mono);
  font-size: 0.78rem; color: var(--brand-hi); text-decoration: none;
}
.adv-link:hover { text-decoration: underline; }

@media (max-width: 720px) { .adv-numbers { grid-template-columns: 1fr; } }

/* ==========================================================================
   LAUNCH (/launch)
   ==========================================================================
   A financial checkout, not a form on a page. The card is the instrument:
   the token's identity first, the pair picked from a market grid, and the
   quote rendered as a trade ticket whose Total is the loudest figure on
   the screen. Every class launch.js emits (lf-*, the .trade-* state
   blocks, lx-ref) is styled here; the .trade-* overrides are scoped to
   .launch-card so the terminal and swap surfaces keep their own atoms. */

/* ---- hero ---- */
.launch-hero { padding: 3.75rem 0 1.75rem; }
.launch-hero h1 {
  font-size: clamp(2rem, 4.6vw, 2.9rem);
  line-height: 1.08; letter-spacing: -0.025em; font-weight: 800;
  margin: 0.7rem 0 1rem;
}
.launch-hero .lede { color: var(--text-dim); font-size: 1.05rem; line-height: 1.65; max-width: 640px; margin: 0; }

/* ---- layout + card shell ---- */
.launch-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 340px); gap: 24px; align-items: start; padding-bottom: 3rem; }
.launch-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; overflow: hidden;
  box-shadow: inset 0 1px 0 0 var(--brand-line), var(--shadow-3);
}
.launch-card .trade-head {
  padding: 20px 22px 14px;
  background: linear-gradient(180deg, var(--surface-2), rgba(0, 0, 0, 0) 130%);
}
.launch-card .trade-head h2 { font-size: 13px; }
.launch-card .trade-sub { font-size: 12.5px; }
.launch-card .trade-body { padding: 20px 22px 22px; gap: 16px; }
/* launch.js renders each state as a single wrapper div; the flex body
   would otherwise shrink-wrap it to its widest child. */
.launch-card .trade-body > div { width: 100%; }
.launch-card .trade-risk {
  background: rgba(245, 165, 36, 0.05);
  background: color-mix(in srgb, var(--amber) 5%, transparent);
  padding: 14px 22px 18px;
}
/* Actions sit in the flow the state renderer leaves them in: the primary
   action is a full-width checkout button, secondary actions breathe. */
.launch-card .trade-body .btn-lg { width: 100%; margin-top: 16px; }
.launch-card .trade-body .btn-sm { margin-top: 12px; }
.launch-card .trade-body > .btn { margin-top: 14px; }

/* ---- state panels (scoped: session, info, error, success) ---- */
.launch-card .trade-empty {
  width: 100%; color: var(--text-dim); font-size: 12.5px; line-height: 1.65;
  background: var(--bg-alt); border: 1px solid var(--line-soft);
  border-radius: 10px; padding: 13px 15px;
}
.launch-card .trade-error {
  width: 100%; font-size: 12.5px; font-weight: 600; line-height: 1.6;
  color: var(--red);
  color: color-mix(in srgb, var(--red) 62%, var(--text));
  background: rgba(246, 70, 93, 0.08);
  background: color-mix(in srgb, var(--red) 8%, transparent);
  border: 1px solid rgba(246, 70, 93, 0.38);
  border: 1px solid color-mix(in srgb, var(--red) 38%, transparent);
  border-left: 3px solid var(--red);
  border-radius: 10px; padding: 12px 15px;
}
.launch-card .trade-done {
  display: flex; align-items: center; gap: 11px;
  font-size: 1.3rem; font-weight: 800; letter-spacing: -0.01em;
}
.launch-card .trade-done::before {
  content: "\2713"; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  background: var(--green-glow); border: 1px solid var(--green-dim);
  font-family: var(--mono); font-size: 14px; color: var(--green);
}
.launch-card .trade-sig {
  width: 100%; background: var(--bg-alt); border: 1px solid var(--line);
  border-radius: 8px; padding: 10px 12px; font-size: 12.5px; color: var(--text-dim);
}
.launch-card .trade-sig code { color: var(--text); font-size: 12px; }

/* ---- side rail ---- */
.launch-rail { display: grid; gap: 14px; }
.rail-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; padding: 18px; box-shadow: var(--shadow-1);
}
.rail-card h3 {
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-mute); margin: 0 0 0.9rem;
}
.mode-row, .deploy-row { padding: 0.75rem 0; border-top: 1px solid var(--line-soft); }
.mode-row:first-of-type, .deploy-row:first-of-type { border-top: 0; padding-top: 0; }
.mode-row p, .deploy-row p { color: var(--text-dim); font-size: 0.8rem; line-height: 1.6; margin: 0.4rem 0 0; }
/* The one selectable mode / the one working surface are panels, not rows:
   a choice the user actually has should look chosen. */
.mode-row.is-active {
  background: var(--brand-glow); border: 1px solid var(--brand-line);
  border-radius: 10px; padding: 12px 14px; margin-bottom: 4px;
}
.deploy-row.is-active {
  background: var(--green-glow);
  border: 1px solid rgba(46, 230, 168, 0.35);
  border: 1px solid color-mix(in srgb, var(--green) 35%, transparent);
  border-radius: 10px; padding: 12px 14px; margin-bottom: 4px;
}
.mode-name, .deploy-name { font-family: var(--mono); font-size: 0.85rem; color: var(--text); margin-right: 8px; }
.mode-badge {
  display: inline-block; padding: 2px 8px; border-radius: 100px;
  border: 1px solid var(--brand); background: var(--brand);
  font-family: var(--mono); font-size: 0.62rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--bg);
}
.mode-badge-off { border-color: var(--line); background: none; color: var(--text-mute); font-weight: 400; }
.mode-row.is-off, .deploy-row.is-off { opacity: 0.55; }
.rail-card .src-badge { padding: 2px 8px; border-radius: 100px; white-space: nowrap; }
.rail-costs { display: grid; grid-template-columns: auto 1fr; gap: 0 14px; margin: 0 0 0.85rem; }
.rail-costs dt { font-size: 0.8rem; color: var(--text-dim); padding: 8px 0; border-bottom: 1px solid var(--line-soft); }
.rail-costs dd { margin: 0; font-family: var(--mono); font-size: 0.82rem; color: var(--text); text-align: right; padding: 8px 0; border-bottom: 1px solid var(--line-soft); }
.rail-costs > :nth-last-child(-n+2) { border-bottom: 0; }
.rail-fine { color: var(--text-mute); font-size: 0.76rem; line-height: 1.6; margin: 0; }

/* ---- form controls ---- */
.lf-row { display: grid; grid-template-columns: 1fr minmax(120px, 0.5fr); gap: 14px; }
.lf-row .lf-block { margin-bottom: 0; }
.lf-block { margin-bottom: 1.15rem; }
.lf-label {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-family: var(--mono); font-size: 0.7rem; font-weight: 600; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--text-dim); margin-bottom: 8px;
}
.lf-count {
  font-size: 0.68rem; letter-spacing: 0.06em; color: var(--brand-hi);
  background: var(--brand-glow); border: 1px solid var(--brand-line);
  border-radius: 100px; padding: 2px 9px;
}
.lf-input, .lf-select {
  width: 100%; background: var(--bg); border: 1px solid var(--line);
  border-radius: 10px; color: var(--text); font-family: var(--mono);
  font-size: 0.92rem; padding: 13px 14px; outline: none;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.lf-input::placeholder { color: var(--text-mute); }
.lf-input:hover, .lf-select:hover { border-color: rgba(0, 224, 101, 0.35); border-color: color-mix(in srgb, var(--brand) 35%, var(--line)); }
.lf-input:focus, .lf-select:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-glow); }
.lf-input-sm { max-width: 130px; }
.lf-inline { display: flex; align-items: center; gap: 9px; }
.lf-unit { font-family: var(--mono); font-size: 0.8rem; color: var(--text-mute); }
.lf-hint { color: var(--text-mute); font-size: 0.78rem; line-height: 1.6; margin: 7px 0 0; max-width: 58ch; }

/* Category chips: the market filter above the grid. */
.lf-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.lf-chip {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 100px;
  color: var(--text-dim); font-family: var(--mono); font-size: 0.72rem;
  padding: 6px 13px; cursor: pointer;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease), background 0.15s var(--ease);
}
.lf-chip:hover { border-color: var(--brand-line); color: var(--text); }
.lf-chip.is-active { border-color: var(--brand); background: var(--brand); color: var(--bg); font-weight: 700; }

/* The pair grid is the market selector: real cards with room to read,
   a selected card that cannot be mistaken for a hovered one. */
.lf-pair-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
  gap: 8px; margin-bottom: 10px; max-height: 232px; overflow-y: auto;
  scrollbar-width: thin; padding: 2px;
}
.lf-pair-card {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--surface-2);
  cursor: pointer; font-size: 12.5px; color: var(--text-dim);
  text-align: left;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease),
              transform 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.lf-pair-card:hover { border-color: var(--brand-line); color: var(--text); transform: translateY(-1px); box-shadow: var(--shadow-1); }
.lf-pair-card.is-active {
  border-color: var(--brand); background: var(--brand-glow); color: var(--text);
  box-shadow: inset 0 0 0 1px var(--brand);
}
.lf-pair-card.is-active::after {
  content: ""; position: absolute; top: 8px; right: 8px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--brand); box-shadow: 0 0 0 3px var(--brand-glow);
}
.lf-pair-card .pair-mark { width: 26px; height: 26px; font-size: 10px; margin-right: 0; }
.lf-pair-sym { font-family: var(--mono); font-weight: 700; font-size: 13px; white-space: nowrap; }
.lf-pair-name { color: var(--text-mute); font-size: 11.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lf-select {
  appearance: none; -webkit-appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23a3b8a7' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center;
  padding-right: 38px;
}

/* Token image: a dropzone, not a bare OS file control. */
.lf-file {
  width: 100%; font-size: 0.8rem; color: var(--text-dim);
  border: 1px dashed var(--line); border-radius: 10px;
  background: var(--bg-alt); padding: 10px 12px; cursor: pointer;
  transition: border-color 0.15s var(--ease);
}
.lf-file:hover { border-color: var(--brand-line); }
.lf-file::file-selector-button {
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  color: var(--text); background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 8px 14px; margin-right: 12px; cursor: pointer;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease);
}
.lf-file:hover::file-selector-button { border-color: var(--brand-line); color: var(--brand-hi); }
.lf-file-chosen {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  font-size: 0.8rem; color: var(--text-dim); margin: 10px 0 0;
  background: var(--green-glow); border: 1px solid rgba(46, 230, 168, 0.35);
  border: 1px solid color-mix(in srgb, var(--green) 35%, transparent);
  border-radius: 8px; padding: 8px 11px;
}
.lf-file-chosen strong { font-family: var(--mono); color: var(--text); }
.lf-file-clear {
  margin-left: auto; background: none; border: 0; color: var(--text-mute);
  font-family: var(--mono); font-size: 0.72rem; text-decoration: underline;
  text-underline-offset: 3px; cursor: pointer; padding: 2px 4px;
}
.lf-file-clear:hover { color: var(--red); }

/* Optional metadata: a proper disclosure panel. */
.lf-details {
  margin: 0.25rem 0 1.25rem; border: 1px solid var(--line);
  border-radius: 12px; background: var(--surface-2); overflow: hidden;
}
.lf-details > summary {
  cursor: pointer; padding: 0.85rem 1rem; font-size: 0.88rem; font-weight: 600;
  list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.lf-details > summary::-webkit-details-marker { display: none; }
.lf-details > summary::after {
  content: ""; width: 8px; height: 8px; flex-shrink: 0;
  border-right: 1.5px solid var(--text-mute); border-bottom: 1.5px solid var(--text-mute);
  transform: rotate(45deg); transition: transform 0.2s var(--ease);
}
.lf-details[open ] > summary::after { transform: rotate(225deg); }
.lf-meta { padding: 0.25rem 1rem 1rem; }
.lf-meta .lf-block:last-child { margin-bottom: 0.25rem; }

/* ---- quote: the trade ticket ---- */
.lf-review-head {
  font-family: var(--mono); font-size: 1.02rem; font-weight: 700;
  letter-spacing: -0.01em; color: var(--text); margin: 0 0 14px;
}
/* Scoped to the launch card: full-width ticket, hairline rows, and the
   Total — always the second-to-last row, balance is context under it —
   set off by the brand rule and the largest figures on the card. */
.launch-card .trade-quote {
  display: grid; grid-template-columns: auto 1fr; gap: 0;
  margin: 0; width: 100%; max-width: none;
  padding: 6px 20px;
  border: 1px solid var(--brand-line); border-radius: 12px;
  background: var(--bg-alt);
  background: linear-gradient(180deg, var(--surface-2), var(--bg-alt));
  box-shadow: var(--shadow-2);
}
.launch-card .trade-quote dt {
  font-size: 13px; color: var(--text-dim);
  padding: 11px 16px 11px 0; border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center;
}
.launch-card .trade-quote dd {
  margin: 0; font-family: var(--mono); font-size: 13.5px; font-weight: 600;
  color: var(--text); text-align: right; font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
  padding: 11px 0 11px 16px; border-bottom: 1px solid var(--line-soft);
  display: flex; align-items: center; justify-content: flex-end;
}
.launch-card .trade-quote dt:last-of-type,
.launch-card .trade-quote dd:last-of-type { border-bottom: 0; }
.launch-card .trade-quote dt:nth-last-of-type(3),
.launch-card .trade-quote dd:nth-last-of-type(3) { border-bottom: 0; }
.launch-card .trade-quote dt:nth-last-of-type(2) {
  color: var(--text); font-weight: 700; border-top: 1px solid var(--brand-line);
}
.launch-card .trade-quote dd:nth-last-of-type(2) {
  color: var(--brand-hi); font-size: 1.05rem; font-weight: 800;
  border-top: 1px solid var(--brand-line);
}
.launch-card .trade-quote dt:nth-of-type(1) { color: var(--text-mute); }
.launch-card .trade-quote dd:nth-of-type(1) { color: var(--brand-hi); font-weight: 700; }
.lf-review-meta { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 14px 0 0; padding: 0; }
.lf-review-meta li {
  font-family: var(--mono); font-size: 0.74rem; color: var(--text-dim);
  background: var(--surface-2); border: 1px solid var(--line-soft);
  border-radius: 100px; padding: 4px 11px;
}

@media (max-width: 900px) {
  .launch-layout { grid-template-columns: 1fr; }
  .lf-row { grid-template-columns: 1fr; }
  .lf-row .lf-block { margin-bottom: 1.15rem; }
  .lf-row .lf-block:last-child { margin-bottom: 0; }
}

@media (max-width: 560px) {
  .launch-hero { padding-top: 2.75rem; }
  .launch-card .trade-head { padding: 17px 16px 12px; }
  .launch-card .trade-body { padding: 17px 16px 18px; }
  .launch-card .trade-risk { padding: 13px 16px 16px; }
  .lf-pair-grid { grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); max-height: 204px; }
  .launch-card .trade-quote { padding: 4px 14px; }
  .launch-card .trade-quote dd { font-size: 12.5px; }
  .launch-card .trade-quote dd:nth-last-of-type(2) { font-size: 0.98rem; }
}

/* ==========================================================================
   SWAP (/swap) — two-panel DEX layout
   ========================================================================== */

.sw-panel { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 0.9rem 1rem 1rem; }
.sw-panel-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 0.7rem; }
.sw-role {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-mute);
}
.sw-bal { font-family: var(--mono); font-size: 0.72rem; color: var(--text-mute); }
.sw-asset { display: flex; align-items: center; gap: 10px; }
.sw-mono {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex-shrink: 0;
  background: var(--surface); border: 1px solid var(--line); border-radius: 50%;
  font-family: var(--mono); font-size: 0.68rem; color: var(--text-dim);
}
.sw-ident { display: flex; flex-direction: column; min-width: 0; }
.sw-sym { font-family: var(--mono); font-weight: 600; font-size: 0.92rem; }
.sw-name { font-size: 0.74rem; color: var(--text-mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sw-change {
  margin-left: auto; display: flex; align-items: center; gap: 4px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 100px; color: var(--text-dim); font-family: var(--mono);
  font-size: 0.72rem; font-weight: 600; padding: 5px 10px 5px 12px; cursor: pointer;
}
.sw-change::after {
  content: ''; width: 6px; height: 6px; margin-top: -2px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
}
.sw-change:hover { border-color: var(--brand-line); color: var(--text); }
/* The pay/receive amounts are the one place this otherwise-dense terminal UI
   goes big — the single number a trader actually reads before confirming,
   the same weight Jupiter and every other production swap give it. */
.sw-out {
  font-family: var(--mono); font-size: clamp(1.4rem, 6vw, 1.9rem); font-weight: 700;
  margin-top: 0.7rem; line-height: 1.15; overflow-wrap: anywhere;
}
.sw-out.is-empty { color: var(--text-mute); font-weight: 400; }
.sw-quick { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 0.8rem; }
.sw-quick-btn {
  background: var(--surface); border: 1px solid var(--line); border-radius: 100px;
  color: var(--text-dim); font-family: var(--mono); font-size: 0.72rem;
  padding: 4px 11px; cursor: pointer;
}
.sw-quick-btn:hover { border-color: var(--brand-line); color: var(--text); }
.sw-quick-btn.is-active { border-color: var(--brand); background: var(--brand-glow); color: var(--text); }
.sw-quick-btn.sw-max { border-color: var(--brand-line); color: var(--brand-hi); font-weight: 700; }
.sw-amount { display: flex; align-items: center; gap: 8px; margin-top: 0.7rem; }
.sw-amount-input {
  flex: 1; min-width: 0; background: none; border: 0; border-bottom: 1px solid transparent;
  color: var(--text); font-family: var(--mono); font-weight: 700;
  font-size: clamp(1.4rem, 6vw, 1.9rem); line-height: 1.15; padding: 2px 0; outline: none;
}
.sw-amount-input:focus { border-bottom-color: var(--brand); }
.sw-amount-unit { font-family: var(--mono); font-size: 0.85rem; color: var(--text-mute); }
.sw-sell-note { font-size: 0.75rem; color: var(--text-mute); line-height: 1.55; margin: 0.6rem 0 0; }
.sw-quote-note { font-size: 0.75rem; color: var(--text-mute); line-height: 1.55; margin: 0.5rem 0 0; }

.sw-flip { display: flex; justify-content: center; margin: -9px 0; position: relative; z-index: 1; }
.sw-flip-btn {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--line);
  color: var(--text-dim); font-size: 15px; line-height: 1; cursor: pointer;
}
.sw-flip-btn:hover { border-color: var(--brand); color: var(--text); }

.sw-slip { margin-top: 1rem; }
.sw-slip-label {
  display: block; font-family: var(--mono); font-size: 0.66rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-mute); margin-bottom: 7px;
}
.sw-slip-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.sw-slip-btn {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 100px;
  color: var(--text-dim); font-family: var(--mono); font-size: 0.72rem;
  padding: 4px 12px; cursor: pointer;
}
.sw-slip-btn:hover { border-color: var(--brand-line); color: var(--text); }
.sw-slip-btn.is-active { border-color: var(--brand); background: var(--brand-glow); color: var(--text); }
.sw-slip-input {
  width: 78px; background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text); font-family: var(--mono);
  font-size: 0.75rem; padding: 5px 9px; outline: none;
}
.sw-slip-input:focus { border-color: var(--brand); }
.sw-slip-unit { font-family: var(--mono); font-size: 0.75rem; color: var(--text-mute); }
.sw-slip-warn { color: var(--amber); font-size: 0.76rem; line-height: 1.55; margin: 7px 0 0; }
.sw-cta { width: 100%; margin-top: 1rem; justify-content: center; }
.sw-done { text-align: center; }

/* ==========================================================================
   BRIDGE (/bridge) — chain cards
   ========================================================================== */

.br-route { display: grid; grid-template-columns: 1fr auto 1fr; gap: 12px; align-items: center; margin-bottom: 1rem; }
/* min-width: 0 overrides the grid default of sizing a track to its content's
   min-content width. Without it, an unbreakable destination name ("Hyperliquid")
   forced its whole card — and the chip grid inside it — wider than the shell,
   and the card spilled out past the trade card's own right edge with no
   border ever drawn around the part that overflowed. */
.br-card {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 0.85rem 1rem 1rem; min-width: 0;
}
.br-role {
  display: block; font-family: var(--mono); font-size: 0.66rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-mute); margin-bottom: 0.65rem;
}
.br-chain { display: flex; align-items: center; gap: 10px; }
.br-mono {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex-shrink: 0;
  background: var(--surface); border: 1px solid var(--line); border-radius: 50%;
  font-family: var(--mono); font-size: 0.62rem; color: var(--text-dim);
}
.br-ident { display: flex; flex-direction: column; min-width: 0; }
.br-sym { font-family: var(--mono); font-weight: 600; font-size: 0.92rem; }
.br-net { font-size: 0.74rem; color: var(--text-mute); }
.br-meta { font-size: 0.76rem; color: var(--text-mute); margin: 0.7rem 0 0; }
.br-meta code { font-family: var(--mono); }
.br-fixed-note { font-size: 0.72rem; color: var(--text-mute); line-height: 1.55; margin: 0.5rem 0 0; }
.br-arrow { font-size: 1.1rem; color: var(--text-mute); text-align: center; }
/* The amount, inside the FROM card — same big-number treatment swap gives
   the pay side, so sending and receiving read as one family of controls. */
.br-amount-row { display: flex; align-items: baseline; gap: 8px; margin-top: 0.75rem; }
.br-amount-input {
  flex: 1; min-width: 0; background: none; border: 0; border-bottom: 1px solid transparent;
  color: var(--text); font-family: var(--mono); font-weight: 700;
  font-size: clamp(1.3rem, 5vw, 1.6rem); line-height: 1.15; padding: 2px 0; outline: none;
}
.br-amount-input:focus { border-bottom-color: var(--brand); }
.br-unit { font-family: var(--mono); font-size: 0.8rem; color: var(--text-mute); }
/* The estimate, inside the TO card. Never computed here — Relay's own
   number once a quote exists, an em dash before one. */
.br-out {
  font-family: var(--mono); font-weight: 700; font-size: clamp(1.3rem, 5vw, 1.6rem);
  line-height: 1.15; margin-top: 0.75rem; overflow-wrap: anywhere;
}
.br-out.is-empty { color: var(--text-mute); font-weight: 400; font-size: 1.1rem; }
.br-chains { display: grid; grid-template-columns: repeat(auto-fit, minmax(82px, 1fr)); gap: 6px; min-width: 0; }
.br-chip {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 8px 10px; cursor: pointer; text-align: left; min-width: 0; max-width: 100%;
}
.br-chip:hover { border-color: var(--brand-line); }
.br-chip.is-active { border-color: var(--brand); background: var(--brand-glow); }
.br-chip-top { display: flex; align-items: center; gap: 6px; min-width: 0; }
/* The chip is a 82px-minimum grid track, so its mark is a badge, not the
   34px disc the panel pills use. */
.br-chip-top .br-mono { width: 18px; height: 18px; font-size: 0.5rem; }
.br-chip-sym { font-family: var(--mono); font-size: 0.82rem; font-weight: 600; color: var(--text); }
/* "Hyperliquid" has no space to wrap at — without this it forced its chip,
   its grid track and the whole card wider than the shell (see .br-card). */
.br-chip-net { font-size: 0.68rem; color: var(--text-mute); overflow-wrap: anywhere; max-width: 100%; }
.br-field { display: block; margin-bottom: 0.9rem; }
.br-field > span { display: block; font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-mute); margin-bottom: 6px; }
.br-field input {
  width: 100%; background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text); font-family: var(--mono);
  font-size: 0.85rem; padding: 10px 12px; outline: none;
}
.br-field input:focus { border-color: var(--brand); }
.br-field-row { display: flex; align-items: center; gap: 8px; }
.br-unit { font-family: var(--mono); font-size: 0.82rem; color: var(--text-mute); }
.br-hint { color: var(--text-mute); font-size: 0.76rem; line-height: 1.6; margin: 6px 0 0; }
/* Shown only when Relay reported a gas fee of exactly zero. */
.br-sponsored {
  margin: 0 0 0.85rem; padding: 8px 11px;
  border: 1px solid rgba(34, 198, 125, 0.3); border-radius: var(--radius);
  background: rgba(34, 198, 125, 0.08); color: var(--green);
  font-size: 0.79rem; line-height: 1.55;
}
.br-next { margin-top: 1rem; padding-top: 0.9rem; border-top: 1px solid var(--line-soft); }
.br-next h3 { font-family: var(--mono); font-size: 0.8rem; margin: 0 0 0.45rem; }
.br-next p { color: var(--text-dim); font-size: 0.8rem; line-height: 1.65; margin: 0; }

@media (max-width: 640px) {
  .br-route { grid-template-columns: 1fr; }
  .br-arrow { transform: rotate(90deg); }
}

/* ==========================================================================
   STONKDAR (/stonkdar) — renamed from Stay Stonky; classes kept as `ss-*`
   ========================================================================== */

.ss-hero { padding: 4.5rem 0 1.5rem; }
.ss-hero h1 { font-size: clamp(1.7rem, 4vw, 2.4rem); margin: 0.5rem 0 0.9rem; }
.ss-hero .lede { color: var(--text-dim); font-size: 1rem; line-height: 1.7; max-width: 640px; margin: 0; }
.ss-stamp { font-family: var(--mono); font-size: 0.74rem; color: var(--text-mute); margin: 0.9rem 0 0; }

.ss-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(275px, 1fr)); gap: 14px; }
.ss-panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 0.9rem 1rem 0.5rem; }
.ss-panel-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 0.6rem; }
.ss-panel-head h2 { font-family: var(--mono); font-size: 0.88rem; margin: 0; }
.ss-panel-note { font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.05em; color: var(--text-mute); }
.ss-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 9px; align-items: center; padding: 8px 0;
  border-bottom: 1px solid var(--line-soft); color: inherit; text-decoration: none;
}
.ss-row:last-child { border-bottom: 0; }
a.ss-row:hover { background: var(--surface-2); }
.ss-row-id { display: flex; flex-direction: column; min-width: 0; }
.ss-row-sym { font-family: var(--mono); font-size: 0.82rem; font-weight: 600; }
.ss-row-sub { font-size: 0.72rem; color: var(--text-mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ss-row-meta { font-family: var(--mono); font-size: 0.75rem; color: var(--text-dim); }

.ss-absent { margin-top: 2rem; }
.ss-absent h2 { font-family: var(--mono); font-size: 1rem; margin: 0 0 0.9rem; }
.ss-absent-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 14px; }
.ss-absent-card {
  background: var(--bg-alt); border: 1px dashed var(--line);
  border-radius: var(--radius); padding: 1.1rem 1.2rem;
}
.ss-absent-card h3 { font-family: var(--mono); font-size: 0.87rem; margin: 0 0 0.5rem; }
.ss-absent-card p { color: var(--text-dim); font-size: 0.82rem; line-height: 1.65; margin: 0 0 0.75rem; }
.ss-absent-tag {
  display: inline-block; padding: 2px 9px; border: 1px solid var(--line);
  border-radius: 100px; font-family: var(--mono); font-size: 0.62rem;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-mute);
}

.ss-community { margin-top: 2.5rem; padding-bottom: 3rem; }
.ss-community h2 { font-family: var(--mono); font-size: 1rem; margin: 0 0 0.9rem; }
.ss-community-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 12px; }
.ss-comm-card {
  display: flex; flex-direction: column; gap: 3px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1.05rem 1.1rem;
  color: inherit; text-decoration: none;
  transition: border-color 0.15s var(--ease);
}
.ss-comm-card:hover { border-color: var(--brand-line); }
.ss-comm-k { font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-mute); }
.ss-comm-v { font-family: var(--mono); font-size: 0.92rem; color: var(--text); }
.ss-comm-d { font-size: 0.79rem; color: var(--text-dim); line-height: 1.6; margin-top: 0.4rem; }
.ss-tips { margin-top: 1.75rem; background: var(--bg-alt); border: 1px solid var(--line-soft); border-radius: var(--radius); padding: 1.25rem 1.4rem; }
.ss-tips h3 { font-family: var(--mono); font-size: 0.85rem; margin: 0 0 0.75rem; }
.ss-tips ul { margin: 0; padding-left: 1.1rem; }
.ss-tips li { color: var(--text-dim); font-size: 0.85rem; line-height: 1.7; margin-bottom: 0.5rem; }
.ss-tips strong { color: var(--text); }

/* ==========================================================================
   MARKET MAKER PANEL (deep-link only)
   ========================================================================== */

.mm-panel {
  margin-top: 1.5rem; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 1.15rem 1.25rem 1.25rem;
}
.mm-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 0.6rem; }
.mm-head h3 { font-family: var(--mono); font-size: 0.95rem; margin: 0; }
.mm-badge {
  padding: 2px 9px; border: 1px solid var(--line); border-radius: 100px;
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--text-mute);
}
.mm-lede { color: var(--text-dim); font-size: 0.86rem; line-height: 1.65; margin: 0 0 0.9rem; }
.mm-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; margin-bottom: 1rem; }
.mm-option { background: var(--bg-alt); border: 1px solid var(--line-soft); border-radius: var(--radius); padding: 1rem 1.1rem; }
.mm-option h4 { font-family: var(--mono); font-size: 0.87rem; margin: 0 0 0.45rem; }
.mm-option p { color: var(--text-dim); font-size: 0.8rem; line-height: 1.6; margin: 0 0 0.85rem; }
.mm-actions { display: flex; gap: 7px; flex-wrap: wrap; }
.mm-risk { border: 1px solid rgba(227, 160, 8, 0.3); border-radius: var(--radius); background: rgba(227, 160, 8, 0.05); }
.mm-risk > summary { cursor: pointer; padding: 0.75rem 1rem; font-size: 0.84rem; font-weight: 600; color: var(--amber); }
.mm-risk-body { padding: 0 1rem 1rem; }
.mm-risk-body ul { margin: 0; padding-left: 1.1rem; }
.mm-risk-body li { color: var(--text-dim); font-size: 0.81rem; line-height: 1.65; margin-bottom: 0.55rem; }

/* ==========================================================================
   Swap and Bridge inside .trade-body — stretch children to full width
   ========================================================================== */

.trade-body > .sw-panel,
.trade-body > .sw-flip,
.trade-body > .sw-slip,
.trade-body > .sw-cta,
.trade-body > .sw-done,
.trade-body > .sw-picker,
.trade-body > .sw-details,
.trade-body > .sw-preset-editor,
.trade-body > .trade-quote,
.trade-body > .trade-error,
.trade-body > .br-route,
.trade-body > .br-field,
.trade-body > .bridge-quote,
.trade-body > .bridge-err,
.trade-body > .br-hint,
.trade-body > .swap-pick {
  align-self: stretch;
  width: 100%;
}

.br-card-to { display: flex; flex-direction: column; }
.br-chains { flex: 1; align-content: start; }
.br-route { align-items: stretch; }

/* ==========================================================================
   Swap/Bridge page layout — centered card
   ========================================================================== */

.swap-page {
  padding: 5rem 1rem 2rem;
  display: flex;
  justify-content: center;
  min-height: 60vh;
}
.swap-card-shell {
  width: 100%;
  max-width: 460px;
}

/* ==========================================================================
   Swap card — new components
   ========================================================================== */

/* Amount row: input + asset pill side by side */
.sw-amount-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 0.1rem;
}
.sw-amount-est {
  flex: 1;
  font-family: var(--mono);
  font-size: clamp(1.3rem, 5vw, 1.8rem);
  font-weight: 700;
  line-height: 1.15;
  overflow-wrap: anywhere;
}
.sw-amount-est.is-empty {
  color: var(--text-mute);
  font-weight: 400;
  font-size: 1.1rem;
}
.sw-amount-pct {
  flex: 1;
  font-family: var(--mono);
  font-size: clamp(1.3rem, 5vw, 1.8rem);
  font-weight: 700;
  line-height: 1.15;
}
.sw-amount-of {
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--text-mute);
}

/* Asset pill (SOL or token icon + name) */
.sw-asset-pill {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 100px;
  padding: 6px 12px 6px 6px;
  flex-shrink: 0;
}
.sw-pill-sym {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 0.88rem;
}
.sw-pill-chevron {
  font-size: 0.7rem;
  color: var(--text-mute);
  margin-left: 2px;
}
.sw-pill-net {
  font-size: 0.66rem;
  color: var(--text-mute);
}

/* Preset buttons */
.sw-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 0.6rem;
  align-items: center;
}
.sw-preset {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 100px;
  color: var(--text-dim);
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 4px 11px;
  cursor: pointer;
}
.sw-preset:hover { border-color: var(--brand-line); color: var(--text); }
.sw-preset.is-active { border-color: var(--brand); background: var(--brand-glow); color: var(--text); }
.sw-preset.sw-max { border-color: var(--brand-line); color: var(--brand-hi); font-weight: 700; }

/* Gear icon for preset editing */
.sw-preset-gear {
  background: none;
  border: 1px solid var(--line);
  border-radius: 50%;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--text-mute);
  font-size: 0.78rem;
  flex-shrink: 0;
}
.sw-preset-gear:hover { border-color: var(--brand-line); color: var(--text); }

/* Preset editor */
.sw-preset-editor {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.8rem 1rem;
}
.sw-preset-editor-label {
  display: block;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-mute);
  margin-bottom: 8px;
}
.sw-preset-edit-row {
  display: flex;
  gap: 6px;
  align-items: center;
}
.sw-preset-edit-input {
  flex: 1;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.82rem;
  padding: 8px 10px;
  outline: none;
}
.sw-preset-edit-input:focus { border-color: var(--brand); }
.sw-preset-hint {
  font-size: 0.72rem;
  color: var(--text-mute);
  margin: 6px 0 0;
}

/* Token picker */
.sw-picker { display: flex; flex-direction: column; gap: 12px; }
.sw-search-row { display: flex; gap: 8px; }
.sw-search-input {
  flex: 1;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.82rem;
  padding: 11px 13px;
  outline: none;
}
.sw-search-input:focus { border-color: var(--green); }
.sw-search-input::placeholder { color: var(--text-mute); }

.sw-pick-label {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-mute);
}
.sw-pick-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.sw-pick-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 100px;
  color: var(--text-dim);
  font-family: var(--mono);
  font-size: 0.74rem;
  padding: 5px 12px 5px 5px;
  cursor: pointer;
}
.sw-pick-chip:hover { border-color: var(--green); color: var(--text); }
.sw-pick-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 50%;
  font-family: var(--mono);
  font-size: 0.52rem;
  color: var(--text-dim);
  overflow: hidden;
}
.sw-pick-icon img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}

/* Balance MAX button */
.sw-bal-max {
  background: none;
  border: none;
  color: var(--brand-hi);
  font-family: var(--mono);
  font-size: 0.66rem;
  font-weight: 700;
  cursor: pointer;
  text-decoration: underline;
  padding: 0;
}
.sw-bal-max:hover { color: var(--text); }

/* Details (collapsible quote info) */
.sw-details {
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  font-size: 0.8rem;
}
.sw-details > summary {
  padding: 10px 14px;
  cursor: pointer;
  color: var(--text-mute);
  font-family: var(--mono);
  font-size: 0.74rem;
}
.sw-details > .trade-quote { border: 0; margin: 0; }

/* Flip arrow for bridge (non-interactive) */
.sw-flip-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  color: var(--text-mute);
  font-size: 15px;
}

/* Bridge disclaimer text below card */
.br-disclaimer {
  color: var(--text-mute);
  font-size: 0.76rem;
  line-height: 1.55;
  margin-top: 1rem;
  text-align: center;
}

@media (max-width: 480px) {
  .sw-search-row { flex-direction: column; }
  .sw-preset-edit-row { flex-wrap: wrap; }
}

/* ==========================================================================
   POLISH LAYER

   Applies the elevation and focus tokens across the surfaces that already
   exist. Deliberately last in the file so it can lift the shared components
   without every page's own block being edited, and deliberately small: the
   look this site is going for is a trading terminal, so depth is used to
   separate a surface from its ground, never to make a card float for its own
   sake. Nothing here changes a layout, a colour's meaning, or a number.
   ========================================================================== */

/* ---------- one focus treatment, everywhere ---------- */

/* Keyboard focus only. Pointer users never see it, so a control can be styled
   for the mouse without the keyboard path losing its outline. The double ring
   punches a gap in the element's own background first, which is what keeps it
   legible on a card that already has a border. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--radius);
}

/* ---------- surfaces get depth instead of only a rule ---------- */

.stat-strip,
.hero-chat,
.board,
.trade,
.term,
.radar-card {
  box-shadow: var(--shadow-2);
}

/* The nav floats over content once the page scrolls, so it needs to sit on
   top of it visually and not just in z-order. The border alone disappears
   against a section-alt band of nearly the same value. */
.nav { box-shadow: var(--shadow-1); }

/* ---------- interactive surfaces respond ---------- */

/* Cards that are links or carry a click target. The lift is 1px — enough to
   register as "this responds", small enough that a grid of them does not
   bounce. Border brightening does most of the work; the transform is a hint. */
.radar-card,
.econ-card,
.sec-card,
.ref-card {
  transition: transform 0.15s var(--ease), box-shadow 0.2s var(--ease),
              border-color 0.15s var(--ease), background 0.3s var(--ease);
}
a.radar-card:hover,
.radar-card:hover {
  transform: translateY(-1px);
  border-color: var(--brand-line);
  box-shadow: var(--shadow-3);
}

/* ---------- buttons ---------- */

/* The primary button already carries a brand-coloured pool. What it lacked is
   a top highlight, which is what separates a solid fill from a lit surface;
   inset rather than a gradient so the fill stays one flat colour and the hover
   swap does not have to repaint a ramp. */
.btn-primary {
  box-shadow: 0 0 0 1px var(--brand),
              inset 0 1px 0 rgba(255, 255, 255, 0.16),
              0 8px 26px -12px var(--brand);
}
.btn-primary:hover {
  box-shadow: 0 0 0 1px var(--brand-hi),
              inset 0 1px 0 rgba(255, 255, 255, 0.2),
              0 12px 30px -12px var(--brand);
}

/* The ghost button sat on transparent, which on the light theme's grey ground
   made it look disabled next to a filled primary. It gets the card surface and
   the same hairline the cards use, so it reads as the second real option. */
.btn-ghost {
  background: var(--surface);
  border-color: var(--line);
  box-shadow: var(--shadow-1);
}
.btn-ghost:hover {
  border-color: var(--text-mute);
  background: var(--surface-2);
  transform: translateY(-1px);
  box-shadow: var(--shadow-2);
}

/* Restated after the hover rules above so a disabled control cannot inherit a
   lift or a glow from them. */
.btn:disabled,
.btn:disabled:hover {
  transform: none;
  box-shadow: none;
}

/* ---------- honour a reduced-motion preference ---------- */

/* Every lift above is decoration. Someone who has asked the OS for less motion
   keeps the colour and shadow feedback and loses only the movement. */
@media (prefers-reduced-motion: reduce) {
  .btn:hover,
  .radar-card:hover,
  a.radar-card:hover,
  .btn-ghost:hover,
  .btn-primary:hover {
    transform: none;
  }
}

/* ==========================================================================
   PAGE HEADLINES — ONE TREATMENT

   The site had two headline systems and no rule deciding between them. Five
   pages set an h1 in --mono (/agents, /advantage, /launch, /live, /stonkdar)
   and three in the sans stack (home, /launches, /terminal), so which product
   you appeared to be looking at depended on where you landed.

   The homepage's system wins, because it is the one with a reason behind it:
   sans carries headlines, and --mono is reserved for the things that are
   actually machine output — tickers, addresses, prices, timestamps, labels,
   eyebrows. A monospace headline spends that signal on a sentence, and once
   the headline is mono the eyebrow directly above it stops reading as a
   different kind of information.

   Sizes stay per-page: a section header should not be homepage-sized. What is
   unified is the family, the weight and the tracking, which is what the eye
   actually reads as "same voice".
   ========================================================================== */

.adv-hero h1,
.launch-hero h1,
.live-page-head h1,
.ss-hero h1,
.radar-head h1,
.tapp-head h1 {
  font-family: var(--sans);
  font-weight: 800;
  letter-spacing: -0.03em;
}

/* ==========================================================================
   MOBILE TAB BAR

   Built by main.js; see the note there for why it is not in the markup.
   Phone only — on a desktop the header nav already shows all ten destinations
   at once and a second bar would just cover content.
   ========================================================================== */

.tabbar { display: none; }

@media (max-width: 720px) {
  .tabbar {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
    background: var(--nav-bg);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-top: 1px solid var(--line);
    /* Clears the iPhone home indicator. Zero on anything without one, so this
       costs nothing on the devices that do not need it. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }

  .tabbar-item {
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    padding: 8px 4px 7px; text-decoration: none;
    color: var(--text-mute); font-size: 10px; letter-spacing: 0.02em;
    /* A tab is a thumb target before it is a label. */
    min-height: 48px; justify-content: center;
    /* Containing block for the active marker below. */
    position: relative;
    transition: color 0.15s var(--ease);
  }
  .tabbar-item svg { width: 21px; height: 21px; }
  .tabbar-item.is-current { color: var(--brand-hi); }
  /* The active tab is already the brand colour, so this rule on the top edge
     is a second signal rather than the only one — colour alone is not a state. */
  .tabbar-item.is-current::before {
    content: ''; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
    width: 20px; height: 2px; border-radius: 0 0 2px 2px; background: var(--brand);
  }

  /* The bar floats over the page, so the last of the content has to clear it
     or the footer's final line sits under the tabs permanently. */
  body.has-tabbar { padding-bottom: calc(58px + env(safe-area-inset-bottom, 0px)); }

  /* chatbot.js injects its own stylesheet at runtime, which lands after this
     file and would otherwise win. Two classes beat its one, which is the whole
     reason for the body prefix — without it the chat bubble sits on top of the
     tab bar and covers two of the five tabs. */
  body.has-tabbar .cb-widget {
    bottom: calc(74px + env(safe-area-inset-bottom, 0px));
  }
}

/* Row language on the /live board, following the same grammar the rest of the
   category uses: a trace of the day's direction on the whole row, and the
   token's age beside its name.

   The tint is deliberately faint. On a board of fifty rows a saturated stripe
   per row turns the table into a barcode and buries the figures, which are the
   thing being read. A row with no reported change gets no tint at all — the
   absence is not "flat". */
.live-row.is-up   { background: linear-gradient(90deg, rgba(34, 198, 125, 0.055), transparent 62%); }
.live-row.is-down { background: linear-gradient(90deg, rgba(229, 72, 77, 0.055), transparent 62%); }
/* Selection and hover still win: they are states the reader caused, and they
   have to be legible on top of whichever tint the row already carries. */
.live-row.is-up:hover, .live-row.is-down:hover,
.live-row.is-up:focus-visible, .live-row.is-down:focus-visible { background: var(--surface-2); }
.live-row.is-selected, .live-row.is-up.is-selected, .live-row.is-down.is-selected {
  background: var(--brand-glow);
}

.live-row-age {
  font-family: var(--mono); font-size: 10.5px; color: var(--text-mute);
  margin-left: 2px;
}

/* The board at phone width. Four numeric columns plus the "no pool" flag do
   not fit in 390px — the 24h figure ran into the flag, and the identity cell
   was squeezed until the pair and age ellipsised away.

   24h volume is the column that goes. Market cap and the 24h move are what a
   row is scanned for; volume is the tie-breaker, and it stays one tap away on
   the token page. The flag goes too: the chart panel already says, in a full
   sentence, that StonkFun reported no pool for the selected token, so the
   badge was the less useful of the two places that say it. */
@media (max-width: 560px) {
  .live-rows { --live-cols: minmax(0, 1.7fr) minmax(0, 0.9fr) minmax(0, 0.62fr); }
  /* Third child of each: the volume cell in a row, its heading in the header. */
  .live-row .live-row-vol,
  .live-head-row .live-h:nth-child(3) { display: none; }
  .live-row-flag { display: none; }
}

/* ==========================================================================
   /live ROW — art, pairing badge, change pill

   Follows the row grammar the competing boards share: big token art with the
   paired asset badged on its corner, the age beside the pairing, and the day's
   move as a filled pill rather than coloured text. The palette stays this
   site's own — brand green for state, green and red only for direction.
   ========================================================================== */

.live-art { position: relative; display: inline-flex; flex-shrink: 0; }
.live-art .tk-mono { width: 40px; height: 40px; font-size: 13px; }

/* The paired xStock, badged on the corner of the token's own art. Ringed in
   the row's background colour so it reads as sitting on top of the artwork
   rather than being part of it. */
.live-art-pair {
  position: absolute; right: -3px; bottom: -3px;
  width: 19px; height: 19px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  background: var(--surface-2); color: var(--text-dim);
  font-family: var(--mono); font-size: 7.5px; font-weight: 700;
  box-shadow: 0 0 0 2px var(--surface);
}
.live-art-pair img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The move as a filled pill. Scoped to this board rather than applied to .chg
   globally: the same class sets figures on /token, /launches and /stonkdar,
   where a run of solid blocks down a column would fight the text around it.
   Worth rolling out, but as its own decision rather than a side effect. */
.live-row-chg {
  justify-self: end;
  display: inline-block; min-width: 62px; padding: 3px 7px;
  border-radius: 4px; text-align: center; font-weight: 700; font-size: 11.5px;
}
.live-row-chg.up   { background: rgba(34, 198, 125, 0.16); color: var(--green); }
.live-row-chg.down { background: rgba(229, 72, 77, 0.16);  color: var(--red); }
/* No pill for an unreported move: a filled block would give absence the same
   visual weight as a real number. It stays a bare em dash. */
.live-row-chg.flat { background: none; color: var(--text-mute); }

/* The taller art needs the row to breathe with it. */
.live-row { padding-top: 8px; padding-bottom: 8px; }
.live-row-id { gap: 11px; }

/* ==========================================================================
   TRADE CARDS — /swap and /bridge

   Restyled to the Jupiter-style layout in the reference: the asset pill on the
   left, a large right-aligned figure, soft raised panels rather than hairline
   boxes, and a round direction button straddling the seam between them.

   The structure was already this shape — sw-panel, sw-panel-head with a
   balance and MAX, sw-amount-input, sw-asset-pill, sw-flip-btn — and /bridge
   renders the same classes, so both pages move together. What changes is the
   scale and the softness.

   The softness is scoped to these cards on purpose. --radius is 3px because
   the rest of the site is a terminal, and a 16px radius everywhere would undo
   that. A trade card is the one surface where the category has settled on a
   soft, large, touch-first form, and where being unfamiliar costs real money.
   ========================================================================== */

.sw-panel {
  background: var(--surface-2);
  /* The panel is raised rather than outlined. A hairline box at this size
     reads as a form field; the reference's panels read as objects. */
  border: 1px solid transparent;
  border-radius: 16px;
  padding: 1rem 1.1rem 1.15rem;
  box-shadow: var(--shadow-1);
}
/* The side being spent is the one with focus, so it carries the accent. */
.sw-panel-pay { border-color: var(--line); }
.sw-panel:focus-within { border-color: var(--brand-line); }

.sw-panel-head { align-items: center; margin-bottom: 0.55rem; }
.sw-role { font-size: 0.78rem; letter-spacing: 0.02em; text-transform: none;
           font-family: var(--sans); font-weight: 700; color: var(--text); }

/* Balance and MAX, grouped right like the reference. MAX becomes a chip: an
   underlined link at 0.66rem was a hard target for a thumb. */
.sw-bal { font-size: 0.78rem; }
.sw-bal-max {
  text-decoration: none;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 8px; padding: 4px 9px; margin-left: 7px;
  font-size: 0.68rem; color: var(--text);
}
.sw-bal-max:hover { border-color: var(--brand-line); background: var(--surface-2); color: var(--brand-hi); }

/* Pill left, figure right. The DOM appends the figure first and the pill
   after, so the row is reversed rather than the markup reordered — the reading
   order for a screen reader stays "amount, of asset". */
.sw-amount-row { flex-direction: row-reverse; gap: 12px; margin-top: 0.35rem; }

.sw-asset-pill {
  border-radius: 100px; padding: 6px 14px 6px 6px; gap: 8px;
  background: var(--surface); border-color: var(--line);
}
.sw-asset-pill .sw-mono { width: 30px; height: 30px; }
.sw-pill-sym { font-size: 1rem; font-weight: 700; }

/* The figure is the largest thing on the card, and right-aligned so the digits
   of the two panels line up with each other. */
.sw-amount-input, .sw-amount-est, .sw-amount-pct {
  text-align: right;
  font-size: clamp(1.8rem, 8vw, 2.6rem);
  font-weight: 700; line-height: 1.1;
}
.sw-amount-input { border-bottom: 0; }
.sw-amount-input:focus { border-bottom: 0; }
.sw-amount-est.is-empty { font-size: clamp(1.5rem, 6vw, 2rem); }

/* The direction button straddles the seam. Larger than the old 32px, which is
   under the 44px a thumb wants, and ringed in the page background so the two
   panels appear to part around it. */
.sw-flip { margin: -17px 0; }
.sw-flip-btn {
  width: 40px; height: 40px; font-size: 17px;
  background: var(--surface-2);
  box-shadow: 0 0 0 4px var(--bg);
}
.sw-flip-btn:hover { background: var(--surface); color: var(--brand-hi); }

@media (max-width: 560px) {
  .sw-panel { padding: 0.9rem 0.95rem 1rem; }
  /* A long figure and a pill cannot share one line on a narrow phone without
     one of them being clipped, so the pill sits above the figure it labels. */
  .sw-amount-row { flex-direction: column-reverse; align-items: stretch; gap: 8px; }
  .sw-asset-pill { align-self: flex-start; }
}

/* ==========================================================================
   TERMINAL LAYER — ported from the Grok build

   The art from that build, on this codebase's engine. Everything here is
   presentational: no data path, no auth, no signing. Its palette already
   shared this site's brand green, so what carried across is the treatment —
   a deeper ground, translucent rules, panels that announce themselves with a
   mono caps bar, and the corner ticks that make a box read as instrumentation
   rather than as a card.

   Its display face (Oswald / IBM Plex) is deliberately NOT here. See the note
   on .display below — that one is a decision, not an oversight.
   ========================================================================== */

/* ---------- figures ---------- */

/* Tabular numerals. In a column of prices a proportional "1" is narrower than
   a "0", so the digits fail to line up and the eye cannot compare rows down
   the column — which is the entire job of a market table. This should have
   been here before the sortable board shipped. */
.num, .chg, .stat-value, .statrail-v,
.live-row-mcap, .live-row-vol, .live-row-chg,
.sw-amount-input, .sw-amount-est, .lt-val, .tk-sym {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

/* ---------- panels ---------- */

/* A panel states what it is in a mono caps bar, the way an instrument labels a
   readout. Opt-in: added to a container, not imposed on every card. */
.panel-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 12px; border-bottom: 1px solid var(--line);
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--text);
}

/* Corner ticks. Two pseudo-elements, no markup, no image — the cheapest way
   to make a rectangle read as a framed instrument. Purely decorative, so it
   never carries meaning a screen reader would miss. */
.corner-ticks { position: relative; }
.corner-ticks::before,
.corner-ticks::after {
  content: ''; position: absolute; width: 10px; height: 10px;
  pointer-events: none; opacity: 0.55;
  border-color: var(--brand); border-style: solid;
}
.corner-ticks::before { top: -1px; left: -1px; border-width: 1px 0 0 1px; }
.corner-ticks::after { right: -1px; bottom: -1px; border-width: 0 1px 1px 0; }

/* ---------- texture ---------- */

/* Scanlines. 1px of white at ~1% every third row: invisible as lines, present
   as grain. Skipped entirely on the light theme, where it reads as banding
   rather than as a CRT. */
.bg-scan {
  background-image: repeating-linear-gradient(
    0deg, transparent, transparent 2px,
    rgb(255 255 255 / 0.012) 2px, rgb(255 255 255 / 0.012) 3px);
}
[data-theme="light"] .bg-scan { background-image: none; }

/* Two soft washes behind the hero, one brand and one live-green, offset from
   each other so the corner has depth without a visible gradient edge. */
.hero-wash {
  background:
    radial-gradient(ellipse 55% 70% at 78% 48%, rgb(46 230 168 / 0.055), transparent 62%),
    radial-gradient(ellipse 44% 54% at 72% 42%, rgb(0 224 101 / 0.10), transparent 58%);
}

/* ---------- accents ---------- */

/* A glow belongs on the live indicator and the brand, and nowhere near a
   number: a price that went up must not appear to be emitting light. */
.text-glow { text-shadow: 0 0 42px rgb(0 224 101 / 0.35); }
.hairline  { box-shadow: 0 0 0 1px var(--line); }

/* ---------- display type ---------- */

/* The Grok build sets headlines in Oswald — a condensed face, uppercase, at
   line-height 0.88. It is most of why its hero reads as a terminal.
   It is not adopted here, for two reasons worth stating rather than burying:
   the CSP in vercel.json is font-src 'self', so a webfont has to be
   self-hosted rather than pulled from Google; and the payload work in this
   branch just cut the homepage 55%, which one more download would partly
   undo. The tightening below is what the system stack can do unaided.
   Ship the real face by dropping a subset woff2 into web/ and adding it to
   --display — the hook is here for it. */
.display {
  font-family: var(--display, var(--sans));
  font-weight: 800; letter-spacing: -0.035em; line-height: 0.94;
}
/* The accent line of a display headline carries the brand's halo. Scoped
   to .display: the same .accent class at text sizes (a fee figure, a
   command line) must stay flat — a glow near a number is a lie about the
   number, per the note on .text-glow above. */
.display .accent { text-shadow: 0 0 46px var(--brand-glow); }

/* Uppercase is deliberately NOT part of .display, and this is a finding rather
   than a preference. Setting the hero in caps at the existing clamp ceiling
   pushed "YOUR CREATOR FEES." onto a fourth line and the primary CTA below the
   fold on a 1440x900 screen — the exact failure the note above .hero already
   documents for a 1366x768 laptop. Caps only work at that size in a condensed
   face, which is precisely what the reference build has and this one does not
   yet. Opt in with .display-caps once a condensed --display is loaded. */
.display-caps { text-transform: uppercase; }

/* ---------- motion ---------- */

@keyframes rise-in {
  from { opacity: 0; transform: translateY(10px); filter: blur(4px); }
  to   { opacity: 1; transform: translateY(0);    filter: blur(0); }
}
.rise-in { animation: rise-in 500ms var(--ease) both; }

@media (prefers-reduced-motion: reduce) {
  .rise-in { animation: none; }
}

/* The referral link on the launch success screen. It appears only after a
   launch has actually happened — a referral code shown to somebody who has not
   used the product is a placeholder, which is what the homepage used to print. */
.lx-ref {
  margin: 16px 0 0; padding: 16px;
  border: 1px solid var(--brand-line); border-radius: 12px;
  background: var(--surface-2);
}
.lx-ref-label {
  margin: 0 0 10px; font-family: var(--mono); font-size: 0.68rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--brand-hi);
}
.lx-ref-row { display: flex; gap: 8px; align-items: stretch; }
.launch-card .lx-ref-row .btn-sm { margin-top: 0; }
.lx-ref-input {
  flex: 1; min-width: 0;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: 8px; color: var(--text);
  font-family: var(--mono); font-size: 0.78rem; padding: 10px 12px; outline: none;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.lx-ref-input:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-glow); }
.lx-ref-note {
  margin: 10px 0 0; font-size: 0.76rem; line-height: 1.55; color: var(--text-dim);
}
@media (max-width: 480px) { .lx-ref-row { flex-direction: column; } }

/* ==========================================================================
   COIN FLIP

   Two faces of the bot on a real 3D flip. The coin is a disc, so both faces
   are cropped to a circle rather than being pre-cut images — the heads art is
   the same logo.png the nav uses, and cutting a second copy would be a second
   file to keep in step.
   ========================================================================== */

.cf-stage {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(24px, 5vw, 56px); align-items: center;
}

/* The wrapper owns the perspective; the coin owns the rotation. Putting both
   on one element makes the depth scale with the spin, which reads as a wobble. */
.cf-coin-wrap { perspective: 900px; flex-shrink: 0; }

.cf-coin {
  position: relative; width: 120px; height: 120px;
  transform-style: preserve-3d;
  /* Long, and eased almost to a stop: a coin that lands abruptly reads as a
     card being turned over. */
  transition: transform 1.5s cubic-bezier(0.19, 1, 0.22, 1);
}

.cf-face {
  position: absolute; inset: 0;
  display: block; border-radius: 50%; overflow: hidden;
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  border: 1px solid var(--line);
  background: var(--surface-2);
  box-shadow: var(--shadow-2);
}
.cf-face img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Tails is pre-rotated, so the same forward spin shows whichever face the
   final half-turn lands on. */
.cf-tails { transform: rotateY(180deg); }

/* Capped: the two fields hold a ticker, and letting them run the full width
   of a 1180px wrap makes a 6-character input look like a comment box. */
.cf-controls { display: grid; gap: 12px; min-width: 0; max-width: 520px; }
.cf-inputs { display: flex; gap: 10px; flex-wrap: wrap; }
.cf-field { display: grid; gap: 5px; flex: 1 1 160px; min-width: 0; }
.cf-field > span {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-mute);
}
.cf-field input {
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text);
  font-family: var(--mono); font-size: 0.9rem; padding: 10px 12px; outline: none;
  min-width: 0;
}
.cf-field input:focus { border-color: var(--brand); }

.cf-go { justify-self: start; }

/* The result. Reserves its line whether or not it holds a word, so the button
   and the note below do not jump when an answer lands. */
.cf-out {
  margin: 0; min-height: 1.9rem;
  font-family: var(--mono); font-size: 1.35rem; font-weight: 700;
  line-height: 1.4; color: var(--text-mute);
  overflow-wrap: anywhere;
}
.cf-out.is-done { color: var(--brand-hi); }

.cf-note { margin: 0; font-size: 0.78rem; color: var(--text-mute); line-height: 1.55; }

@media (max-width: 620px) {
  .cf-stage { grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .cf-controls { justify-items: center; width: 100%; }
  .cf-go { justify-self: center; }
}

@media (prefers-reduced-motion: reduce) {
  .cf-coin { transition: none; }
}

/* ---- status strip -------------------------------------------------------
   The current-state line carried under the nav on the public surfaces.
   It exists so a page can say, in one place and in the product's own
   words, what is actually open today — and be updated in one place when
   that changes. Amber, not brand: this is a status, not a pitch. */
.status-strip {
  border-bottom: 1px solid var(--line);
  /* A whisper of amber in the ground, so the strip separates from the nav
     above and the page below before a word of it is read. Derived from the
     token, not a new hex. */
  background: color-mix(in srgb, var(--amber) 5%, var(--bg-alt));
}
.status-strip-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 10px;
  align-items: baseline;
  padding-top: 9px;
  padding-bottom: 9px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-dim);
}
.status-strip-tag {
  /* A filled chip, not coloured text: a status should be scannable from
     across the room, and amber text at 11px on a dark ground is not. */
  font-weight: 700;
  letter-spacing: 0.1em;
  font-size: 10.5px;
  color: #1a1200;
  background: var(--amber);
  border-radius: 3px;
  padding: 2px 8px;
  text-transform: uppercase;
  white-space: nowrap;
}
.status-strip a { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }

/* ==========================================================================
   REDESIGN — MOBILE LAYER (2026-10-31)

   One consolidated block for the responsive pass, appended last so it wins
   the cascade over the per-component rules above without rewriting them.
   Everything here is measured, not guessed: heights quoted in comments are
   the rendered sizes on a 390px phone before this block landed.

   Three jobs:
     1. Tap targets. Anything a thumb is meant to hit is at least 44px tall
        on touch widths — the platform minimum, and the size at which a
        target stops being a precision instrument.
     2. No iOS focus zoom. Safari zooms the page when a focused input's
        font-size is under 16px. Every text input in the product sat at
        13.5–14.5px, so every tap into a field on an iPhone lurched.
     3. The fee table. It scrolls inside its own box by design; this makes
        the box narrower to escape and advertises that it scrolls.
   ========================================================================== */

/* The desktop header's broken band. Measured: brand 162 + links 690 +
   CTA 126 + toggle 36 + gaps 60 = ~1074px of content, but the sheet only
   takes over at 900px — so from 901 to ~1120px the header was wider than
   the page and pushed every page's scroll width out with it (1099px at a
   1024px viewport, on all three surfaces). Rather than collapsing the nav
   earlier and taking the desktop header away from small laptops, the band
   compacts: same destinations, less air between them. Above 1120px and
   below 901px nothing here applies. */
@media (max-width: 1120px) and (min-width: 901px) {
  .nav-inner { gap: 12px; }
  .nav-links { gap: 10px; }
  .nav-links a { font-size: 13px; }
  .nav .btn-sm { padding: 9px 11px; }
}

@media (max-width: 1024px) {
  /* Quick-command chips were 28px tall — a row of near-misses under the
     terminal input, where a thumb is already moving fast. */
  .chip {
    min-height: 44px; display: inline-flex; align-items: center;
    padding: 10px 15px;
  }

  /* Launch: category chips were 23px, pair cards 34px. The pair card is the
     single most consequential tap in the flow — it decides what real money
     pairs against — so it gets 48px, not the minimum. */
  .lf-chip {
    min-height: 44px; display: inline-flex; align-items: center;
    padding: 10px 14px;
  }
  .lf-pair-card { min-height: 48px; padding: 10px 12px; }
  .lf-file-clear { min-height: 44px; padding: 12px 6px; }

  /* Board view tabs were ~33px. */
  .board-tab {
    min-height: 44px; display: inline-flex; align-items: center;
  }

  /* The starter cards' only action was a 19px text link. The card teaches
     the vocabulary; its button is the lesson's point, so it is sized like
     one. Negative right margin keeps the arrow inside the card's padding
     rhythm without widening the hit area past the card edge. */
  .starter-go {
    min-height: 44px; display: inline-flex; align-items: center;
    padding: 10px 6px 10px 0; margin-top: 0;
  }
}

@media (max-width: 720px) {
  /* Header controls: the menu button was 40px, the theme toggle 36px.
     Both are 44px now; the inner gap tightens so brand + two 44px targets
     still fit a 360px bar with room to spare. */
  .nav-inner { gap: 12px; }
  .nav-toggle { width: 44px; height: 44px; }
  .theme-toggle { width: 44px; height: 44px; }

  /* The terminal's Run button was 35px (.btn-sm at phone width). */
  .term-input .btn { min-height: 44px; }

  /* Command-reference disclosure: the summary row was ~37px. */
  .tapp-help > summary { padding: 15px 2px; }

  /* Footer links were 22px lines of text. Padding, not font size: the
     footer should stay quiet, it just has to be tappable. */
  .footer-links a { display: inline-block; padding: 11px 0; }
}

@media (max-width: 640px) {
  /* iOS focus zoom: 16px is the threshold below which Safari scales the
     page on focus. Set on every text entry surface in the product. */
  .term-input input,
  .lf-input, .lf-select,
  .launch-field input, .launch-field select,
  .cf-field input { font-size: 16px; }

  /* And the fields themselves reach the target height (they were
     40–42px). The terminal input's own box grows inside its row, which
     was already tall enough — the row is not the target, the field is. */
  .lf-input, .lf-select,
  .launch-field input, .launch-field select { min-height: 44px; }
  .term-input input { padding: 13px 0; }

  /* The metadata disclosure on the launch form: its summary row joins
     the 44px rule like every other control in the flow. */
  .lf-details > summary {
    min-height: 44px; display: flex; align-items: center;
  }

  /* The hero eyebrow pill: 36 characters of tracked mono in a bordered
     pill measured ~348px against 324px of usable width at 360px, so the
     pill wrapped its own border ("…TOKENS ON / SOLANA"). Slightly smaller
     type and tracking and it sits on one line with room to spare. */
  .eyebrow {
    font-size: 10.5px; letter-spacing: 0.08em;
    padding: 6px 12px; gap: 7px;
  }

  /* The fee table keeps its internal scroll — four columns of money facts
     do not compress honestly — but it gives up less of the reader's
     screen to get there: 500px of table instead of 560, tighter cells,
     and an inset shadow on the box's right edge so the clipped column
     reads as "scroll me" rather than as the end of the content. */
  table { min-width: 500px; font-size: 12.5px; }
  th, td { padding: 10px 10px 10px 0; }
  .table-scroll {
    box-shadow: inset -22px 0 22px -22px rgba(0, 0, 0, 0.6);
  }

  /* Source badges are single facts ("not published", "verified"). One
     wrapped mid-word on the launch rail and read as two separate badges;
     a badge never breaks internally, and its row wraps around it instead. */
  .src-badge { white-space: nowrap; }
  .rail-costs dd {
    display: flex; flex-wrap: wrap; align-items: center;
    justify-content: flex-end; gap: 4px 8px;
  }
}

@media (max-width: 380px) {
  .nav-inner { gap: 10px; }
}
