/* NinjaSwap — operating-product design system v2.
   Direction: Bloomberg terminal a competent gen-z trader actually
   wants to look at. Not fintech navy, not phosphor-green retro.
   Cool charcoal with violet undertone. Single warm amber-gold accent.
   Geist at two weights. Live trade feed as the visual identity.
   Custom per-exchanger ninja sigil as the signature mark.

   Class names from v1 are preserved so the JS layer keeps working;
   the visuals beneath them are rebuilt from scratch. */

:root {
  /* ── Color tokens (OKLCH) ────────────────────────────────────────
     Deep cool charcoal with faint violet undertone. Not the obvious
     fintech navy that the niche has copied to death; not pure black.
     Backgrounds use chroma 0.01-0.02 toward hue 270 so the dark reads
     as deliberate, not default. Accent is a warm amber-gold reserved
     EXCLUSIVELY for primary CTAs, the live status dot, and the
     append-flash on the live feed. Green and red exist only as data
     colors on +/- deltas, never as chrome. */

  /* Backgrounds: deep cool charcoal with a faint violet undertone.
     Not navy, not pure black. The dark surface reads as deliberate.
     Accent restored to the BRAND emerald green per founder direction.
     The synthesizer pushed amber to "escape the SaaS-default green"
     but the brand IS emerald; the differentiation comes from the
     surface palette, the typography, and the per-exchanger sigils,
     not from changing the brand color. */
  --bg:        oklch(0.18 0.012 270);   /* page surface */
  --bg-raised: oklch(0.22 0.014 270);   /* cards, modals, raised rows */
  --bg-pop:    oklch(0.26 0.016 270);   /* input fields, primary surface */
  --ink:       oklch(0.96 0.005 270);   /* primary text, headings, numerics */
  --text:      oklch(0.86 0.008 270);   /* body text */
  --mute:      oklch(0.62 0.012 270);   /* secondary text, labels */
  --dim:       oklch(0.42 0.010 270);   /* tertiary, placeholder */
  --rule:      oklch(0.30 0.012 270);   /* hairline border, table rows */
  --rule-2:    oklch(0.36 0.014 270);   /* slightly stronger border */
  --accent:    oklch(0.74 0.17 148);    /* brand emerald (#22c55e family) */
  --accent-2:  oklch(0.66 0.18 148);    /* pressed/hover */
  --accent-soft: oklch(0.74 0.17 148 / 0.14); /* accent wash */
  --accent-ink: oklch(0.18 0.012 270);  /* text on accent surface */
  --warn:      oklch(0.78 0.15 65);
  --danger:    oklch(0.62 0.22 25);
  --gain:      oklch(0.74 0.17 148);    /* positive delta — same as accent */
  --loss:      oklch(0.62 0.22 25);     /* negative delta */

  /* ── Motion tokens ──────────────────────────────────────────────── */
  --ease-out:    cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --t-fast:      140ms;
  --t-base:      220ms;
  --t-slow:      420ms;

  /* ── Layout tokens ──────────────────────────────────────────────── */
  --measure:    760px;
  --measure-md: 1020px;
  --measure-lg: 1260px;
  --gutter:     24px;
  --row-h:      56px;       /* canonical dense-row height */

  /* ── Z scale ────────────────────────────────────────────────────── */
  --z-dropdown:    10;
  --z-sticky:      20;
  --z-modal-back:  40;
  --z-modal:       50;
  --z-toast:       60;
  --z-tooltip:     70;
}

/* Hex fallback for browsers without OKLCH (Safari < 15.4). Cheap and
   close-enough; full OKLCH renders in modern browsers. */
@supports not (color: oklch(0.5 0 0)) {
  :root {
    --bg:        #1d1d22;
    --bg-raised: #25252b;
    --bg-pop:    #2c2c33;
    --ink:       #f1f1f4;
    --text:      #d3d3d7;
    --mute:      #93939c;
    --dim:       #62626a;
    --rule:      #3a3a42;
    --rule-2:    #45454e;
    --accent:    #22c55e;
    --accent-2:  #16a34a;
    --accent-soft: rgba(34, 197, 94, 0.14);
    --accent-ink: #1d1d22;
    --warn:      #d8924a;
    --danger:    #c84236;
    --gain:      #22c55e;
    --loss:      #c84236;
  }
}

/* ── Reset ─────────────────────────────────────────────────────────── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  background: var(--bg);
  color-scheme: dark;
  /* Smooth scroll for in-page anchors. Respects reduced motion via
     the media block at the bottom of the file. */
  scroll-behavior: smooth;
  /* Anchored landing reads under the sticky topbar without being
     buried by it. Topbar is ~62px tall on desktop. */
  scroll-padding-top: 80px;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  font-family: "Geist", "Geist Sans", -apple-system, BlinkMacSystemFont,
               "Segoe UI", Roboto, sans-serif;
  font-size: 14px;
  line-height: 1.55;
  background: var(--bg);
  color: var(--text);
  font-feature-settings: "ss01", "tnum", "cv11";
  font-variant-numeric: tabular-nums;
  min-height: 100dvh;
}

::selection {
  background: var(--accent);
  color: var(--accent-ink);
}

.hidden { display: none !important; }

a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--rule-2);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out);
}
a:hover {
  text-decoration-color: var(--ink);
  color: var(--ink);
}
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 1px;
}

button {
  font: inherit;
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
}
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

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

/* ── Typography utilities ────────────────────────────────────────── */
.mono {
  font-family: "JetBrains Mono", "Geist Mono", ui-monospace, SFMono-Regular,
               Menlo, Consolas, monospace;
  letter-spacing: -0.01em;
  font-feature-settings: "tnum";
}
.tnum { font-variant-numeric: tabular-nums; }
.num {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--ink);
}

/* Eyebrow label, used SPARINGLY. The synthesizer's rule: at the top
   of the live feed, at the top of the leaderboard, and almost nowhere
   else. If you find yourself using this on every section, stop. */
.label {
  font-size: 11px;
  font-weight: 500;
  color: var(--mute);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  line-height: 1;
}

/* ── Page chrome ──────────────────────────────────────────────────── */
/* Each page declares its content max-width via the --content-max
   custom property. The topbar reads that same value when computing
   its horizontal padding, so the brand mark sits exactly above the
   page content's left edge. Without this, the brand floated at the
   topbar's own 1260px-padded left edge while .lead sat 120px inside
   it — the "logo looks misplaced" effect. */
.page {
  --content-max: var(--measure);
  max-width: var(--measure);
  margin: 0 auto;
  padding: 32px var(--gutter) 96px;
}
.page--md { --content-max: var(--measure-md); max-width: var(--measure-md); }
.page--lg { --content-max: var(--measure-lg); max-width: var(--measure-lg); }

@media (max-width: 720px) {
  .page { padding: 20px 18px 64px; }
}

/* ── Top bar ──────────────────────────────────────────────────────── */
.topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  /* No justify-content. The brand pushes itself to the left via
     margin-right: auto below; the nav + user-slot stay grouped on
     the right with the topbar's gap between them. That gives the
     even "nav and user pill sit together" rhythm the founder asked
     for instead of the user pill being slammed to the far edge. */
  gap: 24px;
  /* Horizontal padding aligns the topbar's content edge with the
     page's content edge. The .page sits centered with max-width =
     --content-max and adds var(--gutter) of horizontal padding
     internally; the topbar has to add BOTH halves of the
     (viewport - content-max) gap AND the gutter so the brand mark
     sits at exactly the same x as the page content's left edge
     (the slogan on home, the page-title on every other page). */
  padding: 14px max(24px, calc((100vw - var(--content-max, 1020px)) / 2 + var(--gutter)));
  /* Negative top margin pulls the topbar flush with the viewport
     edge, cancelling the .page padding-top: 32px. */
  margin: -32px calc(50% - 50vw) 40px;
  background: color-mix(in oklab, var(--bg) 84%, transparent);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
          backdrop-filter: blur(10px) saturate(140%);
  border-bottom: 1px solid var(--rule);
}

/* Brand bookends the left. Both .brand and .user-slot have
   margin-right: auto so the remaining horizontal space splits
   evenly between them, which puts the nav + user-slot cluster
   in the center of the topbar instead of slamming it to the
   far right edge. The visual rhythm:

     [BRAND]   ......  [NAV]  [USER]   ......

   Equal whitespace on either side of the cluster, brand still
   aligned with the page content's left edge per the calc above. */
.topbar > .brand     { margin-right: auto; }
.topbar > .user-slot { margin-right: auto; }

@media (max-width: 640px) {
  .topbar { gap: 12px; padding: 12px 18px; margin: -20px calc(50% - 50vw) 24px; }
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  font-weight: 600;
  font-size: 14px;
  letter-spacing: -0.005em;
  color: var(--ink);
  transition: opacity var(--t-fast) var(--ease-out);
}
.brand:hover { text-decoration: none; color: var(--ink); opacity: 0.85; }

/* Logo asset now has a transparent background. The trimmed
   source is 140x240 (taller than wide), so we size by height and
   let the width respond. Bigger than the v1 28px since the
   visible mark no longer competes with a heavy black frame. */
img.brand-mark, .brand-mark {
  height: 36px;
  width: auto;
  flex-shrink: 0;
  object-fit: contain;
  object-position: center;
  transition: transform var(--t-base) var(--ease-out);
}
.brand:hover .brand-mark { transform: rotate(-4deg); }

.nav {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: nowrap;
  gap: 24px;
  min-width: 0;
  font-size: 13px;
  color: var(--mute);
}

.nav a {
  text-decoration: none;
  color: var(--mute);
  white-space: nowrap;
  transition: color var(--t-fast) var(--ease-out);
  position: relative;
  padding: 4px 0;
}
.nav a:hover, .nav a[aria-current="page"] { color: var(--ink); }

.nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  bottom: -2px;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-base) var(--ease-out);
}
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }

@media (max-width: 640px) {
  .nav { gap: 14px; font-size: 12.5px; }
  .nav a:not(.nav-keep) { display: none; }
}

/* ── User menu pill ──────────────────────────────────────────────── */
.user-slot { display: inline-flex; align-items: center; min-height: 32px; }

.user-signin {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border-radius: 6px;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  transition: background var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
.user-signin:hover { background: var(--accent-2); color: var(--accent-ink); text-decoration: none; }
.user-signin:active { transform: scale(0.97); }

.user-menu { position: relative; }

.user-menu-button {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 4px 12px 4px 4px;
  background: var(--bg-pop);
  border: 1px solid var(--rule-2);
  border-radius: 999px;
  color: var(--text);
  font-size: 13px;
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out);
}
.user-menu-button:hover { border-color: var(--rule-2); background: var(--bg-raised); }
.user-menu-button[aria-expanded="true"] { border-color: var(--accent); }

.user-menu-button img {
  width: 22px; height: 22px;
  border-radius: 999px;
}

.user-menu-button .name {
  max-width: 110px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--ink);
  font-weight: 500;
}

.user-menu-popover {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 240px;
  background: var(--bg-raised);
  border: 1px solid var(--rule-2);
  border-radius: 8px;
  box-shadow: 0 16px 48px -12px rgba(0,0,0,0.6);
  padding: 8px;
  z-index: var(--z-dropdown);
  font-size: 13px;
}
.user-menu-popover[hidden] { display: none; }

.user-menu-header {
  padding: 10px 12px 12px;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 6px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.user-menu-header img { width: 32px; height: 32px; border-radius: 999px; }
.user-menu-header .name {
  color: var(--ink);
  font-weight: 600;
  font-size: 13px;
  display: block;
  max-width: 160px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.user-menu-header .id {
  color: var(--mute);
  font-size: 11px;
  display: block;
  font-family: "JetBrains Mono", monospace;
}

.user-menu-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 12px;
  color: var(--text);
  text-decoration: none;
  border-radius: 4px;
  transition: background var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out);
  font-size: 13px;
}
.user-menu-link:hover { background: var(--bg-pop); color: var(--ink); text-decoration: none; }
.user-menu-link.danger { color: var(--danger); }
.user-menu-link.danger:hover { background: color-mix(in oklab, var(--danger) 12%, transparent); color: var(--danger); }

.user-menu-link .meta {
  color: var(--mute);
  font-size: 11px;
  font-family: "JetBrains Mono", monospace;
}

.user-menu-rule {
  height: 1px;
  background: var(--rule);
  margin: 6px 0;
  border: none;
}

/* ── Live status dot + heartbeat ─────────────────────────────────── */
.status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--mute);
  white-space: nowrap;
}

.status-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
  position: relative;
}
.status-dot::before, .status-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.55;
  animation: dot-ping 1.8s var(--ease-out) infinite;
}
.status-dot::after { animation-delay: 0.9s; }

@keyframes dot-ping {
  0%   { transform: scale(1);   opacity: 0.5; }
  80%, 100% { transform: scale(2.6); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .status-dot::before, .status-dot::after { animation: none; opacity: 0.35; }
}

/* ── Headlines (display) ─────────────────────────────────────────── */

/* The hero metric: 72px tabular-nums semibold. Used for the giant
   numbers on the home + history pages. Pairs with .label below it. */
.metric {
  font-size: clamp(48px, 7vw, 72px);
  font-weight: 600;
  line-height: 0.95;
  letter-spacing: -0.04em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.metric .unit {
  font-size: 0.32em;
  color: var(--mute);
  font-weight: 500;
  margin-left: 0.18em;
  letter-spacing: 0;
}

/* The page-title block — left-aligned, two-line spaced. Used on
   /history, /exchangers, /wallet, profile pages. Less display-y
   than v1 to match the operating-product feel. */
.page-title {
  font-size: clamp(28px, 4vw, 40px);
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1.05;
  color: var(--ink);
  margin-bottom: 6px;
  text-wrap: balance;
}

.page-sub {
  font-size: 14px;
  color: var(--mute);
  margin-bottom: 32px;
  max-width: 60ch;
}

/* The homepage lead. Smaller, tighter, less posturing than v1's
   96px. Kept word-rise classes alive for the existing JS but the
   visual is rebuilt below. */
.lead {
  font-size: clamp(40px, 6vw, 64px);
  font-weight: 600;
  line-height: 0.98;
  letter-spacing: -0.04em;
  color: var(--ink);
  margin-bottom: 20px;
  text-wrap: balance;
}
.lead .accent { color: var(--accent); }
.lead .word { display: inline-block; }

.lead-sub {
  font-size: 15px;
  color: var(--mute);
  line-height: 1.55;
  margin-bottom: 28px;
  max-width: 56ch;
}

/* Section headings */
h1, h2, h3, h4 {
  color: var(--ink);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.15;
}

h2.section-title {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--mute);
  text-transform: uppercase;
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 10px;
}
/* DROPPED in v2: the // prefix. Was reading as Linear/Vercel cosplay. */

h3 { font-size: 18px; font-weight: 600; margin-bottom: 10px; }
h4 { font-size: 14px; font-weight: 600; margin-bottom: 6px; }

/* ── Prose ────────────────────────────────────────────────────────── */
.prose {
  font-size: 15px;
  line-height: 1.7;
  color: var(--text);
  max-width: 65ch;
}
.prose p + p { margin-top: 16px; }
.prose strong { color: var(--ink); font-weight: 600; }

.prose code, code.inline {
  font-family: "JetBrains Mono", monospace;
  font-size: 0.9em;
  background: var(--bg-pop);
  color: var(--ink);
  padding: 1px 6px;
  border-radius: 3px;
  border: 1px solid var(--rule);
}

/* ── Section divider ──────────────────────────────────────────────── */
.section {
  margin-top: 56px;
  padding-top: 32px;
  border-top: 1px solid var(--rule);
}
.section:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

/* ── Inline ticker (stats as a sentence on the home) ─────────────── */
.ticker {
  font-size: 14px;
  color: var(--mute);
  line-height: 1.85;
  margin-bottom: 28px;
}
.ticker-num {
  color: var(--ink);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ── Live wrap (status pill on the home ticker) ──────────────────── */
.live-wrap {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: default;
}
.live-now {
  font-size: 12px;
  color: var(--mute);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 500;
}

/* ──────────────────────────────────────────────────────────────────
   LIVE TRADE FEED — THE SIGNATURE COMPONENT
   ────────────────────────────────────────────────────────────────── */
/* This is the visual identity of NinjaSwap. Each row: per-exchanger
   ninja sigil, handle, pair, tabular-numeric amount, timestamp,
   transcript link. New trades append at the top and flash amber
   for 600ms. Ten rows visible. The label sits above as a small
   uppercase mute eyebrow. No headline. The component IS the brand. */

.live-feed {
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.live-feed-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 0;
  border-bottom: 1px solid var(--rule);
}

.live-feed-head .label {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.live-feed-list {
  list-style: none;
  display: flex;
  flex-direction: column;
}

.live-feed-row {
  display: grid;
  /* sigil + avatar + (name/id) + pair + amount + when */
  grid-template-columns: 22px 22px 1fr auto auto auto;
  align-items: center;
  gap: 12px;
  min-height: var(--row-h);
  padding: 10px 12px;
  border-bottom: 1px solid var(--rule);
  margin: 0 -12px;
  text-decoration: none;
  color: inherit;
  transition: background var(--t-fast) var(--ease-out);
}
.live-feed-row:last-child { border-bottom: none; }
.live-feed-row:hover {
  background: var(--bg-raised);
  text-decoration: none;
}

.live-feed-row .sigil {
  width: 22px; height: 22px;
  border-radius: 4px;
  flex-shrink: 0;
}

.live-feed-row .row-avatar {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--bg-pop);
  border: 1px solid var(--rule-2);
  object-fit: cover;
}
.live-feed-row .row-avatar--blank {
  display: inline-block;
}

.live-feed-row .feed-who {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.live-feed-row .feed-who .name {
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.live-feed-row .feed-who .id {
  font-size: 11px;
  color: var(--mute);
  font-family: "JetBrains Mono", monospace;
}

.live-feed-row .pair {
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  color: var(--mute);
  padding: 2px 6px;
  border: 1px solid var(--rule-2);
  border-radius: 3px;
  white-space: nowrap;
}

.live-feed-row .amount {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--ink);
  font-size: 14px;
  text-align: right;
  white-space: nowrap;
}

.live-feed-row .when {
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  color: var(--mute);
  white-space: nowrap;
}

/* Append flash — amber tint settles back over 600ms */
.live-feed-row.is-new {
  animation: feed-flash 600ms var(--ease-out);
}
@keyframes feed-flash {
  0%   { background: var(--accent-soft); }
  100% { background: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .live-feed-row.is-new { animation: none; }
}

@media (max-width: 640px) {
  .live-feed-row {
    grid-template-columns: 24px 1fr auto;
    gap: 10px;
  }
  .live-feed-row .pair { display: none; }
  .live-feed-row .when { font-size: 10.5px; }
}

/* ──────────────────────────────────────────────────────────────────
   SIGIL — deterministic ninja crest per Discord ID
   ────────────────────────────────────────────────────────────────── */
/* Rendered inline as <svg> by web/static/sigil.js. The CSS here is
   only for sizing + tint variation. Color tint comes from the .sigil
   --tint custom property set inline per-sigil. */

.sigil {
  display: inline-block;
  background: var(--tint-bg, color-mix(in oklab, var(--accent) 14%, var(--bg-raised)));
  color: var(--tint-fg, var(--accent));
  border-radius: 4px;
}
.sigil--lg { width: 64px; height: 64px; border-radius: 8px; }
.sigil--xl { width: 96px; height: 96px; border-radius: 10px; }

/* ── CTA buttons ─────────────────────────────────────────────────── */
.cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--accent);
  color: var(--accent-ink);
  text-decoration: none;
  padding: 12px 20px;
  font-size: 14px;
  font-weight: 600;
  border-radius: 6px;
  transition: background var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
.cta:hover {
  text-decoration: none;
  background: var(--accent-2);
  color: var(--accent-ink);
}
.cta:active { transform: scale(0.97); }

.cta-arrow {
  display: inline-block;
  transition: transform var(--t-base) var(--ease-out);
}
.cta:hover .cta-arrow { transform: translateX(3px); }

.cta.cta--outline {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--rule-2);
}
.cta.cta--outline:hover {
  background: var(--bg-raised);
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
}

.cta-row {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-top: 28px;
}

.cta-row .secondary {
  color: var(--mute);
  font-size: 13px;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.cta-row .secondary:hover { color: var(--ink); }

/* Ghost button (secondary CTA in cards/forms) */
.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--rule-2);
  padding: 8px 14px;
  font-size: 13px;
  font-weight: 500;
  border-radius: 5px;
  text-decoration: none;
  transition: border-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out);
  cursor: pointer;
}
.btn-ghost:hover {
  border-color: var(--ink);
  color: var(--ink);
  background: var(--bg-raised);
  text-decoration: none;
}
.btn-ghost:active { transform: scale(0.98); }
.btn-ghost.danger { color: var(--danger); border-color: var(--danger); }
.btn-ghost.danger:hover { background: color-mix(in oklab, var(--danger) 10%, transparent); }

/* ── Stripped metric row (HodlHodl move) ─────────────────────────── */
/* Stripped numerals, hairline dividers above and below the row, no
   card chrome. 72px hero numerals, 11px uppercase labels.
   Replaces the v1 .stat-row card-bordered look. */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  margin: 32px 0;
}

.stat {
  padding: 24px 28px;
  border-right: 1px solid var(--rule);
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.stat:last-child { border-right: none; }

.stat-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--mute);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.stat-val {
  font-size: clamp(36px, 5vw, 56px);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.stat-val .unit {
  font-size: 0.35em;
  color: var(--mute);
  font-weight: 500;
  margin-left: 0.3em;
  letter-spacing: 0;
}
.stat-val.accent { color: var(--accent); }

.stat-sub {
  font-size: 12px;
  color: var(--mute);
  font-family: "JetBrains Mono", monospace;
}

@media (max-width: 720px) {
  .stat { border-right: none; border-bottom: 1px solid var(--rule); padding: 18px 20px; }
  .stat:last-child { border-bottom: none; }
}

/* ── Methods table (the old format) ──────────────────────────────── */
.methods {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.methods th, .methods td {
  text-align: left;
  padding: 14px 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}
.methods th {
  font-weight: 500;
  color: var(--mute);
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.08em;
  padding-bottom: 10px;
}
.methods td:first-child {
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  padding-right: 28px;
  width: 1px;
}
.methods td:last-child { color: var(--text); }

/* ── Methods grid (homepage) ─────────────────────────────────────── */
/* Borderless tiled chip-list. Drops the v1 card grid since cards are
   the lazy answer. Method name + emoji on a low-key surface. */
.methods-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px;
}

.method-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  background: var(--bg-raised);
  border-radius: 6px;
  font-size: 13px;
  color: var(--ink);
  font-weight: 500;
  transition: background var(--t-fast) var(--ease-out);
}
.method-card:hover { background: var(--bg-pop); }
.method-card img {
  width: 18px; height: 18px;
  flex-shrink: 0;
}

.methods-caption {
  margin-top: 16px;
  font-size: 13px;
  color: var(--mute);
}

/* ──────────────────────────────────────────────────────────────────
   METHOD BANDS — fiat / crypto / gift cards.
   Three horizontal bands, each with a heading row and a wrapping
   chip list. The chip is the smallest brand-marked atom: a logo,
   a name, and a fee override pill when the rate differs from the
   band base. Chips wrap naturally so the page doesn't read as a
   uniform card grid. */

.methods-grid {
  display: flex;
  flex-direction: column;
  gap: 28px;
}

.band { display: flex; flex-direction: column; gap: 12px; }

.band-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--rule);
}

.band-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--mute);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.band-sub {
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  color: var(--mute);
  letter-spacing: 0;
}

.band-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--bg-raised);
  border-radius: 6px;
  font-size: 13px;
  color: var(--ink);
  font-weight: 500;
  text-decoration: none;
  transition: background var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out);
  cursor: pointer;
  position: relative;
}

.chip:hover {
  background: var(--bg-pop);
  color: var(--ink);
  text-decoration: none;
}

.chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.chip-logo {
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--brand, var(--mute));
}

.chip-logo img,
.chip-logo svg {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.chip-name {
  white-space: nowrap;
}

.chip-pct {
  font-family: "JetBrains Mono", monospace;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--warn);
  letter-spacing: 0;
  padding: 1px 6px;
  border: 1px solid color-mix(in oklab, var(--warn) 40%, transparent);
  border-radius: 3px;
}

.methods-trailer {
  margin-top: 20px;
  font-size: 13px;
  color: var(--mute);
  max-width: 65ch;
  line-height: 1.6;
}

/* ── Steps list (numbered) ───────────────────────────────────────── */
.steps {
  list-style: none;
  counter-reset: step;
}

.steps > li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 18px;
  padding: 20px 0;
  border-bottom: 1px solid var(--rule);
}
.steps > li:last-child { border-bottom: none; }

.steps > li::before {
  content: counter(step, decimal-leading-zero);
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  font-weight: 600;
  color: var(--mute);
  padding-top: 6px;
  letter-spacing: 0.04em;
}

.step-title {
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 4px;
  font-size: 14px;
}
.step-body { color: var(--mute); font-size: 13px; line-height: 1.6; }

/* ──────────────────────────────────────────────────────────────────
   DATA TABLE — dense, tabular, sparkline-ready
   ────────────────────────────────────────────────────────────────── */
/* Row height locked at --row-h (56px) so every dense table has the
   same density rhythm. Right-aligned numerics. Tabular figures
   globally. Sparkline cell is fixed width. No vertical lines —
   only horizontal hairlines between rows. */

.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.data thead th {
  text-align: left;
  font-weight: 500;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--mute);
  padding: 12px 16px;
  border-bottom: 1px solid var(--rule-2);
  vertical-align: middle;
  white-space: nowrap;
}
.data thead th:first-child { padding-left: 16px; }
.data thead th:last-child { padding-right: 16px; text-align: right; }
.data thead th.num,
.data thead th[data-num] { text-align: right; }

.data tbody td {
  padding: 14px 16px;
  border-bottom: 1px solid var(--rule);
  vertical-align: middle;
  color: var(--text);
  height: var(--row-h);
}
.data tbody td:first-child { padding-left: 16px; }
.data tbody td:last-child { padding-right: 16px; text-align: right; }

.data tbody tr {
  transition: background var(--t-fast) var(--ease-out);
}
.data tbody tr.clickable { cursor: pointer; }
.data tbody tr.clickable:hover { background: var(--bg-raised); }

.data .id {
  font-family: "JetBrains Mono", monospace;
  color: var(--mute);
  font-size: 12px;
}
.data .num {
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  font-weight: 600;
  text-align: right;
  white-space: nowrap;
}
.data .when {
  font-family: "JetBrains Mono", monospace;
  color: var(--mute);
  font-size: 11.5px;
  white-space: nowrap;
}
.data .who { color: var(--ink); font-weight: 500; }
.data .who a { text-decoration: none; color: var(--ink); }
.data .who a:hover { color: var(--accent); }
.data .accent { color: var(--accent); }
.data .gain { color: var(--gain); font-weight: 600; }
.data .loss { color: var(--loss); font-weight: 600; }

/* ── Sparkline cell ──────────────────────────────────────────────── */
/* Drawn inline as SVG by JS (see web/static/sparkline.js). The cell
   reserves space so the table doesn't reflow when sparklines render. */
.spark {
  width: 80px;
  height: 18px;
  display: inline-block;
  vertical-align: middle;
  color: var(--mute);
}
.spark--gain { color: var(--gain); }
.spark--loss { color: var(--loss); }
.spark svg { width: 100%; height: 100%; display: block; }

/* ── Recent trades feed (legacy compact home-page version) ─────── */
.feed { list-style: none; }

.feed > li {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--rule);
  align-items: baseline;
  margin: 0 -16px;
  border-radius: 4px;
  transition: background var(--t-fast) var(--ease-out);
}
.feed > li:hover { background: var(--bg-raised); }
.feed > li:last-child { border-bottom: none; }

.feed-flow {
  font-size: 13px;
  color: var(--mute);
}
.feed-flow .who { color: var(--ink); text-decoration: none; }
.feed-flow .who:hover { color: var(--accent); }

.feed-amount {
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  font-weight: 600;
  white-space: nowrap;
  font-family: "JetBrains Mono", monospace;
}

.feed-time {
  font-family: "JetBrains Mono", monospace;
  color: var(--mute);
  font-size: 11.5px;
  margin-left: 8px;
}

/* ──────────────────────────────────────────────────────────────────
   FEE SIMULATOR — kept structurally same, restyled to the new
   surface language. No emerald accent.
   ────────────────────────────────────────────────────────────────── */
.sim-frame {
  margin-top: 24px;
}

.sim {
  background: var(--bg-raised);
  border-radius: 8px;
  padding: 24px;
  display: grid;
  gap: 20px;
}

.sim-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.sim-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--mute);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.sim-rate {
  font-size: 11px;
  color: var(--mute);
  letter-spacing: 0.04em;
}

.sim-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.sim-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.sim-field-label {
  font-size: 11px;
  color: var(--mute);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 500;
}

.sim-field select.input,
.sim-field input.input {
  font-size: 13px;
  padding: 10px 12px;
}

.sim-result {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  background: var(--bg-pop);
  border-radius: 6px;
  overflow: hidden;
}

.sim-cell {
  padding: 14px 16px;
  border-right: 1px solid var(--rule);
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.sim-cell:last-child { border-right: none; }

.sim-cell-label {
  font-size: 10.5px;
  color: var(--mute);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 500;
}

.sim-cell-val {
  font-size: 18px;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: opacity var(--t-fast) var(--ease-out);
}

.sim-cell-val.warn { color: var(--warn); }
.sim-cell-val.accent { color: var(--accent); }
.sim-cell-val--flash { opacity: 0.4; }

.sim-foot {
  font-size: 11.5px;
  color: var(--mute);
}

@media (max-width: 640px) {
  .sim-grid { grid-template-columns: 1fr; }
  .sim-result { grid-template-columns: 1fr; }
  .sim-cell { border-right: none; border-bottom: 1px solid var(--rule); }
  .sim-cell:last-child { border-bottom: none; }
}

/* ── Q/A pairs ───────────────────────────────────────────────────── */
.qa { display: grid; gap: 24px; }

.qa dt {
  color: var(--ink);
  font-weight: 600;
  margin-bottom: 6px;
  font-size: 14px;
}

.qa dd {
  color: var(--text);
  font-size: 13.5px;
  line-height: 1.65;
}

/* DROPPED in v2: the Q. / A. mono prefixes. Was reading as cosplay. */

/* ── Forms ───────────────────────────────────────────────────────── */
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.field-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--mute);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.input, .textarea, .select {
  width: 100%;
  background: var(--bg-pop);
  border: 1px solid var(--rule-2);
  color: var(--ink);
  font-family: inherit;
  font-size: 14px;
  padding: 11px 14px;
  border-radius: 5px;
  outline: none;
  transition: border-color var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out);
}

.input::placeholder { color: var(--dim); }
.input:hover, .textarea:hover, .select:hover { border-color: var(--rule-2); }
.input:focus, .textarea:focus, .select:focus {
  border-color: var(--accent);
  background: color-mix(in oklab, var(--bg-pop) 90%, var(--accent) 10%);
}

.textarea { resize: vertical; min-height: 96px; line-height: 1.55; }

.field-hint {
  font-size: 11.5px;
  color: var(--mute);
}

.field-error {
  font-size: 11.5px;
  color: var(--danger);
}

/* ── Toggle / switch ─────────────────────────────────────────────── */
.toggle {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  user-select: none;
}

.toggle input { position: absolute; opacity: 0; pointer-events: none; }

.toggle-track {
  width: 32px; height: 18px;
  background: var(--bg-pop);
  border: 1px solid var(--rule-2);
  border-radius: 999px;
  position: relative;
  transition: background var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out);
}

.toggle-track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 12px;
  height: 12px;
  background: var(--mute);
  border-radius: 50%;
  transition: transform var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out);
}

.toggle input:checked + .toggle-track {
  background: var(--accent);
  border-color: var(--accent);
}

.toggle input:checked + .toggle-track::after {
  transform: translateX(14px);
  background: var(--accent-ink);
}

/* ── Badge / chip ────────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 500;
  padding: 3px 8px;
  border-radius: 3px;
  letter-spacing: 0.04em;
  border: 1px solid currentColor;
  text-transform: uppercase;
  font-family: inherit;
}
.badge--ok { color: var(--gain); }
.badge--warn { color: var(--warn); }
.badge--danger { color: var(--danger); }
.badge--mute { color: var(--mute); }

/* ── Loading placeholder ─────────────────────────────────────────── */
[data-load] {
  color: var(--dim);
}
[data-load]::after {
  content: " ·";
  animation: load-dot 1.4s linear infinite;
}
@keyframes load-dot {
  0%, 80%, 100% { opacity: 0.2; }
  40%           { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  [data-load]::after { animation: none; }
}

/* ──────────────────────────────────────────────────────────────────
   SKELETON ROW — pulsing placeholder for the live feed before data
   arrives. Renders as a faded ghost row that shimmers. The JS swaps
   real rows in over the skeleton. Way better than "loading..." text.
   ────────────────────────────────────────────────────────────────── */

.live-feed-skeleton {
  list-style: none;
  display: flex;
  flex-direction: column;
}

.live-feed-skeleton li {
  display: grid;
  /* matches the real row: sigil + avatar + name + pair + amount + when */
  grid-template-columns: 22px 22px 1fr 80px 60px 50px;
  align-items: center;
  gap: 12px;
  min-height: var(--row-h);
  padding: 10px 12px;
  border-bottom: 1px solid var(--rule);
  margin: 0 -12px;
}
.live-feed-skeleton li:last-child { border-bottom: none; }

.live-feed-skeleton .bar {
  height: 10px;
  background: var(--bg-raised);
  border-radius: 2px;
  position: relative;
  overflow: hidden;
}
.live-feed-skeleton .bar--sigil {
  width: 22px;
  height: 22px;
  border-radius: 4px;
}
.live-feed-skeleton .bar--avatar {
  width: 22px;
  height: 22px;
  border-radius: 50%;
}
.live-feed-skeleton .bar::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in oklab, var(--mute) 30%, transparent) 50%,
    transparent 100%
  );
  animation: skeleton-shimmer 1.4s var(--ease-in-out) infinite;
}
@keyframes skeleton-shimmer {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
  .live-feed-skeleton .bar::after { animation: none; }
}

@media (max-width: 640px) {
  .live-feed-skeleton li {
    grid-template-columns: 22px 22px 1fr 60px;
  }
  .live-feed-skeleton li > :nth-child(5),
  .live-feed-skeleton li > :nth-child(6) { display: none; }
}

/* ── Safety banner ───────────────────────────────────────────────── */
.safety {
  font-size: 12.5px;
  color: var(--mute);
  padding-bottom: 12px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--rule);
}
.safety strong { color: var(--ink); font-weight: 600; }

/* ── Security strip (wallet page, also reusable) ─────────────────── */
/* A horizontal row of small "attribute on/off" pills with a top + bottom
   hairline. Used as a confidence strip at the top of the wallet page
   to show the security posture at a glance. */
.security-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  padding: 12px 0;
  margin-bottom: 32px;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  font-size: 11.5px;
  color: var(--mute);
  font-family: "JetBrains Mono", monospace;
  letter-spacing: 0;
}
.security-strip > span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.security-strip strong {
  color: var(--ink);
  font-weight: 600;
}
.security-strip .pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--bg-raised);
  color: var(--ink);
  font-weight: 600;
}
.security-strip .pill::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
  flex-shrink: 0;
}
.security-strip .sep {
  color: var(--rule-2);
  user-select: none;
}

/* ── Avatar (small monogram or img) ──────────────────────────────── */
.avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--bg-pop);
  display: inline-block;
  vertical-align: middle;
  border: 1px solid var(--rule-2);
  flex-shrink: 0;
  object-fit: cover;
}
img.avatar { display: block; }
.avatar--lg { width: 56px; height: 56px; }
.avatar--xl { width: 96px; height: 96px; }

/* ── Profile header (used on /u/<id>) ────────────────────────────── */
.profile-head {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-bottom: 32px;
}

.profile-head .meta { min-width: 0; }
.profile-head .name {
  font-size: clamp(24px, 3.5vw, 32px);
  font-weight: 600;
  letter-spacing: -0.028em;
  color: var(--ink);
  line-height: 1.1;
  margin-bottom: 4px;
}
.profile-head .sub {
  font-size: 13px;
  color: var(--mute);
  font-family: "JetBrains Mono", monospace;
}

/* Crown / founder mark — keep but restyle to inline pill */
.founder-mark {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 3px;
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  vertical-align: middle;
}

/* ── Modal ───────────────────────────────────────────────────────── */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal-back);
  background: color-mix(in oklab, var(--bg) 70%, transparent);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.modal-backdrop.is-open { display: flex; }

.modal {
  background: var(--bg-raised);
  border: 1px solid var(--rule-2);
  border-radius: 10px;
  max-width: 560px;
  width: 100%;
  max-height: 90dvh;
  overflow-y: auto;
  padding: 28px;
  z-index: var(--z-modal);
  box-shadow: 0 24px 64px -16px rgba(0,0,0,0.5);
}

.modal-close {
  position: absolute;
  top: 14px;
  right: 14px;
  font-size: 20px;
  color: var(--mute);
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 3px;
  transition: color var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out);
}
.modal-close:hover { color: var(--ink); background: var(--bg-pop); }

.modal-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  font-family: "JetBrains Mono", monospace;
  margin-bottom: 4px;
}

/* ── Footer ──────────────────────────────────────────────────────── */
.foot {
  margin-top: 80px;
  padding-top: 24px;
  border-top: 1px solid var(--rule);
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  color: var(--mute);
  gap: 24px;
  flex-wrap: wrap;
}
.foot-links { display: flex; gap: 18px; flex-wrap: wrap; }
.foot a {
  text-decoration: none;
  color: var(--mute);
  transition: color var(--t-fast) var(--ease-out);
}
.foot a:hover { color: var(--ink); }

/* ── Motion system ────────────────────────────────────────────────── */

/* Restrained first-paint: subtle rise on the topbar and lead only.
   The synthesizer's rule: page feels alive because real data is
   moving, not because the CSS is choreographed. So scroll-reveal
   is kept minimal and gates ONLY existing-visible content (no
   reveal-on-scroll fade-up that hides content in headless renders). */

@keyframes ns-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes ns-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes ns-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.5; transform: scale(0.85); }
}

.topbar,
main.page > .lead,
main.page > .safety,
main.page > .page-title {
  animation: ns-rise 380ms var(--ease-out) both;
}

main.page > .section,
main.page > h2,
main.page > .stat-row,
main.page > .cta-row,
main.page > .data,
main.page > .feed,
main.page > .live-feed,
main.page > .qa,
main.page > .ticker {
  animation: ns-fade 280ms var(--ease-out) both;
}

@media (prefers-reduced-motion: reduce) {
  main.page > * { animation: none !important; }
}

/* Press feedback on every interactive control */
.cta, .btn-ghost, .user-signin, .user-menu-button, button.tab-btn,
button[type="button"], button[type="submit"] {
  transition: transform var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out);
}
.cta:active, .btn-ghost:active, .user-signin:active,
.user-menu-button:active, button:active {
  transform: scale(0.97);
}

@media (prefers-reduced-motion: reduce) {
  *:active { transform: none !important; }
}

/* Word-rise legacy helper for the lead headline */
.lead .word {
  display: inline-block;
  animation: ns-rise 420ms var(--ease-out) both;
  animation-delay: var(--d, 0ms);
}
@media (prefers-reduced-motion: reduce) {
  .lead .word { animation: none; }
}
