/* Swoop — design system
 *
 * Token architecture and geometry follow Orchestra (orchestra.flashnet.xyz):
 * one radius token, hairline strokes, semantic surface/text/border ramps,
 * dedicated swap-panel tokens, snappy UI motion with a slower "arrive" curve,
 * and a warm-neutral dark ramp instead of a cool one.
 *
 * Deliberately NOT copied: Suisse Int'l / Suisse Int'l Mono are commercially
 * licensed per-domain, so the type stack stays on Swoop's open pairing from
 * .agents/brand-identity.md (Schibsted Grotesk + IBM Plex Mono) — same
 * strategy, grotesk for UI and mono for figures. The accent stays Swoop
 * Signal (#3DCF9A), which already sits a hair off Orchestra's #3dd68c.
 */

:root {
  /* ---- Geometry ---- */
  --radius: 6px;
  --radius-lg: 12px;
  --stroke-xs: 0.5px;

  /* ---- Motion ---- */
  --dur-ui: 0.18s;
  --dur-arrive: 0.6s;
  --ease-ui: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-arrive: cubic-bezier(0.19, 1, 0.22, 1);

  /* ---- Surfaces (warm neutral ramp) ---- */
  --surface-base: #111110;
  --surface-elevated: #151514;
  --surface-primary: #191918;
  --surface-sunken: #212120;
  --surface-secondary: #282826;
  --surface-hover: #eeede90f;

  /* ---- Swap widget ---- */
  --swap-panel: #212120;
  --swap-panel-hover: #252523;
  --swap-panel-border: #fffff508;
  --swap-direction-hover: #2a2a28;
  --swap-direction-icon: #77776f;

  /* ---- Text ---- */
  --text-primary: #eeede9;
  --text-secondary: #a09f96;
  --text-tertiary: #7c7b74;
  --text-inverse: #191918;

  /* ---- Borders ---- */
  --border-primary: #fffff51a;
  --border-secondary: #fffff50f;

  /* ---- Brand ---- */
  --signal: #3dcf9a;
  --signal-hover: #4ad9a6;
  --signal-rgb: 61, 207, 154;
  --signal-dim: #1f6b4f;
  --destructive: #e5484d;
  /* Two severities, one recipe (10% fill, 40% border): --destructive means do
     not proceed, --caution means proceed knowing the cost. The fee disclosure
     is the second kind — it is never a reason to stop the user. */
  --caution: #e8a33d;

  /* ---- Elevation ---- */
  --shadow-sm: 0 1px 2px #00000052;
  --shadow-md: 0 1px 2px -1px #0000003d, 0 4px 6px -1px #00000052;
  --shadow-lg: 0 1px 2px -1px #0000003d, 0 4px 6px -1px #00000052, 0 8px 16px #00000047;
  --focus-ring: 0 0 0 3px rgba(var(--signal-rgb), 0.22);

  /* ---- Type ---- */
  --font: "Schibsted Grotesk", ui-sans-serif, system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;

  /* ---- Spacing ---- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;

  --z-menu: 20;
  --z-overlay: 30;
  --z-nav: 35;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
/* The UA gives an iframe `border: 2px inset`, and an inset border takes its
   colour from currentColor — so the Turnstile widget was being framed in a
   bright rectangle of our own --text-primary. The reset above zeroes margin and
   padding but not borders, which is why it showed. */
iframe { border: 0; }
html { scroll-behavior: smooth; }
html, body { min-height: 100dvh; overflow-x: clip; }

body {
  font-family: var(--font);
  background: var(--surface-base);
  color: var(--text-primary);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
summary:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius);
}

.wrap { width: min(1160px, calc(100% - 40px)); margin: 0 auto; }

/* The header is sticky, so anchor targets must clear it. */
:target, section[id], .exchange, .swap-anchor { scroll-margin-top: 88px; }
/* #swap wraps the card so the scroll lands on its edge; the card's top margin
   collapses through this box rather than being counted as part of the target. */
.swap-anchor { display: block; }

/* ---------------- Header ---------------- */

.site-head {
  position: sticky; top: 0; z-index: var(--z-nav);
  background: color-mix(in srgb, var(--surface-base) 82%, transparent);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: var(--stroke-xs) solid var(--border-primary);
}
.site-head .wrap {
  display: flex; align-items: center; gap: var(--space-6);
  height: 64px;
}
.brand {
  display: flex; align-items: center; gap: 9px;
  color: var(--text-primary); text-decoration: none;
  font-size: 15.5px; font-weight: 600; letter-spacing: -0.02em;
  flex: none;
}
.brand svg { display: block; }
.nav-links { display: flex; align-items: center; gap: 2px; margin-right: auto; }
.nav-links a {
  color: var(--text-secondary); text-decoration: none;
  font-size: 13.5px; font-weight: 500;
  padding: 7px 11px; border-radius: var(--radius);
  transition: color var(--dur-ui) var(--ease-ui), background var(--dur-ui) var(--ease-ui);
}
.nav-links a:hover { color: var(--text-primary); background: var(--surface-hover); }

.head-cta {
  flex: none;
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--surface-secondary); color: var(--text-primary);
  border: var(--stroke-xs) solid var(--border-primary); border-radius: var(--radius);
  padding: 8px 14px;
  font-family: var(--font); font-size: 13.5px; font-weight: 500;
  text-decoration: none; cursor: pointer;
  transition: background var(--dur-ui) var(--ease-ui), color var(--dur-ui) var(--ease-ui);
}
.head-cta:hover { background: var(--swap-panel-hover); color: var(--signal); }
.head-cta .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--signal); flex: none; }

.nav-toggle {
  display: none; position: relative; flex: none;
  width: 36px; height: 36px; border-radius: var(--radius);
  background: var(--surface-secondary); border: 0; cursor: pointer;
}
.nav-toggle span {
  position: absolute; left: 11px; right: 11px; height: 1.5px;
  background: var(--text-primary); border-radius: 1px;
  transition: transform var(--dur-ui) var(--ease-ui), top var(--dur-ui) var(--ease-ui);
}
.nav-toggle span:first-child { top: 14px; }
.nav-toggle span:last-child { top: 21px; }
.nav-toggle[aria-expanded="true"] span:first-child { top: 17.5px; transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:last-child { top: 17.5px; transform: rotate(-45deg); }

.nav-overlay {
  position: fixed; inset: 0; z-index: var(--z-overlay);
  background: color-mix(in srgb, var(--surface-base) 94%, transparent);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  /* Centred, not bottom-anchored: four links pinned to the bottom of a tall phone
     screen leave the top two thirds empty, which reads as a failed render. */
  display: flex; flex-direction: column; justify-content: center;
  padding: 24px 24px 32px; gap: 4px;
}
.nav-overlay[hidden] { display: none; }
.nav-overlay a {
  color: var(--text-primary); text-decoration: none;
  font-size: clamp(30px, 8vw, 44px); font-weight: 600; letter-spacing: -0.03em;
  padding: 8px 0;
  opacity: 0; transform: translateY(40px);
  animation: maskUp var(--dur-arrive) var(--ease-arrive) forwards;
}
.nav-overlay a:nth-child(2) { animation-delay: 60ms; }
.nav-overlay a:nth-child(3) { animation-delay: 110ms; }
.nav-overlay a:nth-child(4) { animation-delay: 160ms; }
@keyframes maskUp { to { opacity: 1; transform: translateY(0); } }

/* ---------------- Hero ---------------- */

.hero { padding: clamp(32px, 5vw, 56px) 0 var(--space-6); text-align: center; }
.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 10px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--text-secondary);
  padding: 6px 12px; border-radius: var(--radius);
  border: var(--stroke-xs) solid var(--border-primary);
}
.hero h1 {
  margin-top: var(--space-5);
  font-size: clamp(34px, 5.2vw, 60px);
  font-weight: 600; letter-spacing: -0.04em; line-height: 1.04;
  text-wrap: balance;
}
.hero h1 em { font-style: normal; color: var(--signal); }
.hero-sub {
  margin: var(--space-4) auto 0; max-width: 42ch;
  font-size: clamp(15px, 1.5vw, 17px); color: var(--text-secondary);
  text-wrap: balance;
}

/* ---------------- Exchange widget ---------------- */

.exchange {
  width: min(524px, 100%);
  margin: var(--space-7) auto 0;
  text-align: left;
  background: var(--surface-primary);
  border: var(--stroke-xs) solid var(--border-primary);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

/* Step rail */
.steps {
  display: grid; grid-template-columns: repeat(4, 1fr);
  padding: var(--space-1); gap: 2px;
  border-bottom: var(--stroke-xs) solid var(--border-primary);
}
.step {
  display: flex; align-items: center; gap: 7px;
  padding: 10px 9px; border-radius: var(--radius);
  font-size: 12px; font-weight: 500; color: var(--text-tertiary);
  min-width: 0;
  transition: color var(--dur-ui) var(--ease-ui), background var(--dur-ui) var(--ease-ui);
}
.step-n {
  flex: none; width: 18px; height: 18px; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--mono); font-size: 9.5px; font-weight: 500;
  color: var(--text-tertiary);
  border: var(--stroke-xs) solid var(--border-primary);
  transition:
    color var(--dur-ui) var(--ease-ui),
    background-color var(--dur-ui) var(--ease-ui),
    border-color var(--dur-ui) var(--ease-ui);
}
.step-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.step.is-active { color: var(--text-primary); background: var(--surface-secondary); }
.step.is-active .step-n { color: var(--text-inverse); background: var(--signal); border-color: transparent; }
.step.is-done { color: var(--text-secondary); }
.step.is-done .step-n { color: var(--signal); border-color: rgba(var(--signal-rgb), 0.5); }

/* Panels — position anchors the token menu, whose top offset app.js measures. */
.panel { position: relative; padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); }
.panel[hidden] { display: none; }
.panel-nav { padding: var(--space-4) var(--space-4) 0; }
.panel-nav[hidden] { display: none; }
.panel-note { font-size: 13px; color: var(--text-secondary); line-height: 1.55; }

/* Amount wells */
.well {
  position: relative;
  background: var(--swap-panel);
  border: var(--stroke-xs) solid var(--swap-panel-border);
  border-radius: var(--radius);
  padding: 13px 13px 11px;
  display: flex; flex-direction: column; gap: 5px;
  transition: background var(--dur-ui) var(--ease-ui), box-shadow var(--dur-ui) var(--ease-ui);
}
.well:hover { background: var(--swap-panel-hover); }
.well:focus-within { background: var(--swap-panel-hover); box-shadow: var(--focus-ring); }
.well-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  font-size: 12px; font-weight: 500; color: var(--text-secondary);
}
.well-limit { font-family: var(--mono); font-size: 10.5px; color: var(--text-tertiary); }
.well-row { display: flex; align-items: center; gap: 10px; min-width: 0; }

.amount, .amount-out {
  flex: 1 1 0; min-width: 0; width: 0;
  background: transparent; border: 0; color: var(--text-primary);
  font-family: var(--mono); font-size: 24px; font-weight: 500;
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.amount:focus { outline: none; box-shadow: none; }
.amount:disabled { opacity: 0.5; }
.amount-out.loading { animation: pulse 1.4s var(--ease-ui) infinite; }
.amount-out.bump { animation: landIn var(--dur-arrive) var(--ease-arrive); }
@keyframes pulse { 0%, 100% { opacity: 0.3; } 50% { opacity: 0.85; } }
@keyframes landIn { from { opacity: 0.3; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.fiat { font-family: var(--mono); font-size: 11px; color: var(--text-tertiary); min-height: 15px; }

/* Token chip */
.token-btn {
  flex: none;
  display: flex; align-items: center; gap: 7px;
  background: var(--surface-secondary); color: var(--text-primary);
  border: var(--stroke-xs) solid var(--border-primary);
  border-radius: var(--radius); padding: 6px 10px 6px 6px;
  font-family: var(--font); font-size: 14px; font-weight: 600; cursor: pointer;
  transition: background var(--dur-ui) var(--ease-ui);
}
.token-btn:hover:not(:disabled) { background: var(--swap-direction-hover); }
.token-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.token-btn .chev { width: 10px; height: 6px; color: var(--swap-direction-icon); flex: none; transition: transform var(--dur-ui) var(--ease-ui); }
.token-btn[aria-expanded="true"] .chev { transform: rotate(180deg); }

.tok-icon { position: relative; display: inline-flex; flex: none; }
/* `:not(.chain-badge)` here for the same reason as in the row rule below, and
   this is the one that was missed the first time: at (0,1,1) this selector beat
   `.chain-badge` at (0,1,0), so the badge took the icon size in the *selected*
   token button too and covered the token it belongs to. */
.tok-icon img:not(.chain-badge) { display: block; width: 22px; height: 22px; border-radius: 50%; background: var(--surface-sunken); }
.chain-badge {
  display: block;
  position: absolute; bottom: -3px; right: -5px;
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--surface-secondary); padding: 1.5px; object-fit: contain; pointer-events: none;
  box-shadow: 0 0 0 1.5px var(--surface-secondary);
}

/* Direction control */
.flip-row { display: flex; align-items: center; gap: 10px; margin: -2px 0; }
.flip-row .rule { flex: 1; height: var(--stroke-xs); background: var(--border-primary); }
.flip {
  flex: none; width: 32px; height: 32px; border-radius: var(--radius);
  background: var(--swap-panel); color: var(--swap-direction-icon);
  border: var(--stroke-xs) solid var(--swap-panel-border);
  display: grid; place-items: center; cursor: pointer;
  transition: background var(--dur-ui) var(--ease-ui), color var(--dur-ui) var(--ease-ui);
}
.flip:hover:not(:disabled) { background: var(--swap-direction-hover); color: var(--signal); }
.flip:disabled { opacity: 0.4; cursor: not-allowed; }
.flip.spin { animation: flipOnce var(--dur-arrive) var(--ease-arrive); }
@keyframes flipOnce { from { transform: rotate(0); } to { transform: rotate(180deg); } }

/* Quote meta */
.meta { display: flex; flex-direction: column; gap: 6px; padding: var(--space-1) 2px 0; font-size: 13px; }
.meta[hidden] { display: none; }
.meta-line { display: flex; justify-content: space-between; gap: 12px; }
.meta-line > span:first-child { color: var(--text-secondary); }
.meta-line > span:last-child {
  font-family: var(--mono); font-size: 12px;
  font-variant-numeric: tabular-nums; text-align: right;
}
.quote-empty { font-size: 13px; color: var(--text-tertiary); text-align: center; padding: var(--space-1) 0; }
.quote-empty[hidden] { display: none; }
/* The cost line turns amber only past COST_WARN_FRACTION, so an ordinary quote
   reads as ordinary and the colour keeps its meaning. */
#meta-cost.is-costly { color: var(--caution); }
.quote-warn {
  margin-top: var(--space-1);
  font-size: 12.5px; line-height: 1.5;
  color: #f0cd94;
  background: color-mix(in srgb, var(--caution) 10%, transparent);
  border: var(--stroke-xs) solid color-mix(in srgb, var(--caution) 40%, transparent);
  border-radius: var(--radius);
  padding: 9px 11px;
}
.quote-warn[hidden] { display: none; }
.quote-warn strong { color: #f7e0bd; font-weight: 600; }

/* Buttons */
.btn-primary {
  width: 100%;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--signal); color: var(--text-inverse);
  border: 0; border-radius: var(--radius); padding: 13px 18px;
  font-family: var(--font); font-size: 15px; font-weight: 600; letter-spacing: -0.01em;
  cursor: pointer;
  transition: background var(--dur-ui) var(--ease-ui), opacity var(--dur-ui) var(--ease-ui);
}
.btn-primary:hover:not(:disabled) { background: var(--signal-hover); }
.btn-primary:disabled { opacity: 0.32; cursor: not-allowed; }
.btn-primary.busy { opacity: 0.6; }
.btn-ico { display: grid; place-items: center; flex: none; }

.btn-back {
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: 6px;
  background: transparent; border: 0; color: var(--text-secondary);
  font-family: var(--font); font-size: 13px; font-weight: 500; cursor: pointer;
  padding: 2px 0;
  transition: color var(--dur-ui) var(--ease-ui);
}
.btn-back:hover:not(:disabled) { color: var(--text-primary); }
.btn-back:disabled { opacity: 0.4; cursor: not-allowed; }

.btn-ghost {
  width: 100%;
  background: var(--surface-secondary); color: var(--text-primary);
  border: var(--stroke-xs) solid var(--border-primary); border-radius: var(--radius);
  padding: 12px 18px;
  font-family: var(--font); font-size: 14px; font-weight: 600; cursor: pointer;
  transition: background var(--dur-ui) var(--ease-ui), color var(--dur-ui) var(--ease-ui);
}
.btn-ghost:hover { background: var(--swap-direction-hover); color: var(--signal); }
.btn-ghost[hidden] { display: none; }

/* Token menu */
.token-menu {
  position: absolute; left: var(--space-4); right: var(--space-4); z-index: var(--z-menu);
  background: var(--surface-elevated);
  border: var(--stroke-xs) solid var(--border-primary);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  max-height: 320px; display: flex; flex-direction: column; overflow: hidden;
  animation: menuIn var(--dur-ui) var(--ease-ui);
}
.token-menu[hidden] { display: none; }
@keyframes menuIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.menu-head { padding: var(--space-2); border-bottom: var(--stroke-xs) solid var(--border-primary); }
.menu-head input {
  width: 100%; background: var(--swap-panel); color: var(--text-primary);
  border: var(--stroke-xs) solid var(--border-primary);
  border-radius: var(--radius); padding: 10px 12px;
  font-family: var(--font); font-size: 14px;
}
.menu-head input::placeholder { color: var(--text-tertiary); }
.menu-list { overflow-y: auto; padding: var(--space-1); }
.tok-row {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 8px 9px; border-radius: var(--radius);
  background: transparent; border: 0; color: var(--text-primary);
  cursor: pointer; text-align: left; font-family: var(--font);
  transition: background var(--dur-ui) var(--ease-ui);
}
.tok-row:hover { background: var(--surface-hover); }
.tok-row.selected { background: var(--surface-secondary); }
.tok-row.selected .t-sym { color: var(--signal); }
/* `:not(.chain-badge)` is load-bearing. This was `.tok-row .tok-icon img`, which
   matches both images in the wrapper — and at (0,2,1) it outranks `.chain-badge`
   at (0,1,0), so it resized the badge from 13px to 26px: exactly the size of the
   token icon it is absolutely positioned on top of. Every row in the dropdown
   showed a full-size chain icon with a crescent of the token behind it. */
.tok-row .tok-icon img:not(.chain-badge) { width: 26px; height: 26px; }
/* Keeps the badge's proportion against the larger row icon: 13/22 ≈ 15/26. */
.tok-row .chain-badge { width: 15px; height: 15px; }
.tok-row .t-col { display: flex; flex-direction: column; min-width: 0; }
.tok-row .t-sym { font-size: 14px; font-weight: 600; }
.tok-row .t-name {
  font-size: 11.5px; color: var(--text-tertiary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.menu-empty { padding: 22px; text-align: center; color: var(--text-tertiary); font-size: 13px; }

/* Address step */
#panel-address { gap: var(--space-3); }
.addr-field { display: flex; flex-direction: column; }
.field-label {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 12.5px; font-weight: 500;
  color: var(--text-secondary); margin-bottom: 6px;
}
/* Chain identity as a token: it is the one detail that changes per pair, so it
   reads at a glance instead of being buried mid-sentence. */
.chain-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px 2px 3px; border-radius: 999px;
  background: var(--surface-secondary);
  border: var(--stroke-xs) solid var(--border-primary);
  font-size: 11px; font-weight: 500; color: var(--text-primary); line-height: 1.6;
}
.chain-chip img { width: 14px; height: 14px; border-radius: 50%; display: block; }
.field-input {
  width: 100%;
  background: var(--swap-panel); color: var(--text-primary);
  border: var(--stroke-xs) solid var(--swap-panel-border);
  border-radius: var(--radius); padding: 12px 13px;
  font-family: var(--mono); font-size: 13px;
  transition: background var(--dur-ui) var(--ease-ui), box-shadow var(--dur-ui) var(--ease-ui),
              border-color var(--dur-ui) var(--ease-ui);
}
.field-input:focus { outline: none; background: var(--swap-panel-hover); box-shadow: var(--focus-ring); }
/* iOS Safari zooms the whole page when a focused input is under 16px, which on a
   phone reads as the layout breaking the moment the keyboard opens. Only the touch
   case needs it, so desktop keeps its density. */
@media (pointer: coarse), (max-width: 640px) {
  .field-input, .menu-head input { font-size: 16px; }
}
.field-row { display: flex; gap: var(--space-2); align-items: stretch; }
.field-row .field-input { flex: 1 1 auto; min-width: 0; }
.paste-btn {
  flex: none;
  background: var(--surface-secondary); color: var(--text-primary);
  border: var(--stroke-xs) solid var(--border-primary); border-radius: var(--radius);
  padding: 0 14px;
  font-family: var(--font); font-size: 13px; font-weight: 500;
  cursor: pointer;
  transition: background var(--dur-ui) var(--ease-ui), color var(--dur-ui) var(--ease-ui);
}
.paste-btn:hover { background: var(--swap-panel-hover); color: var(--signal); }
.paste-btn[hidden] { display: none; }
/* An address is longer than the field, so the tail — the part a swapped character
   hides in — is never on screen while typing or after a paste. Echo the whole
   value, wrapped, directly under the field the warning tells you to check. */
.field-echo {
  margin-top: 5px;
  font-family: var(--mono); font-size: 11.5px; line-height: 1.5;
  color: var(--text-secondary);
  word-break: break-all;
}
.field-echo[hidden] { display: none; }
.field-input::placeholder { color: var(--text-tertiary); font-family: var(--font); }
.field-input.is-invalid { border-color: color-mix(in srgb, var(--destructive) 60%, transparent); }
.field-input.is-invalid:focus { box-shadow: 0 0 0 3px color-mix(in srgb, var(--destructive) 22%, transparent); }
.field-input.is-valid { border-color: rgba(var(--signal-rgb), 0.45); }
.field-hint { margin-top: 5px; font-size: 11.5px; color: var(--text-tertiary); line-height: 1.5; }
.field-msg { margin-top: 5px; font-size: 11.5px; color: #f3a6a8; line-height: 1.5; }
.field-msg[hidden] { display: none; }
.warn {
  font-size: 11.5px; color: var(--text-secondary); line-height: 1.5;
  background: var(--swap-panel); border: var(--stroke-xs) solid var(--swap-panel-border);
  border-radius: var(--radius); padding: 9px 11px;
}
#cf-turnstile { display: flex; justify-content: center; }
#cf-turnstile[hidden] { display: none; }

/* ---------------- Order / deposit panel ---------------- */

.order-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding-bottom: var(--space-3);
  border-bottom: var(--stroke-xs) solid var(--border-primary);
}
.order-id { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.order-id .k { font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-tertiary); }
.order-id .v {
  font-family: var(--mono); font-size: 12.5px; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.order-elapsed {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  font-family: var(--mono); font-size: 12px; color: var(--text-secondary);
}
.order-elapsed .pip {
  width: 6px; height: 6px; border-radius: 50%; background: var(--signal);
  animation: blink 2s var(--ease-ui) infinite;
}
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
/* A settled swap is no longer waiting on anything, so the pip stops pulsing. */
.order-elapsed.is-settled .pip { animation: none; opacity: 0.4; }

/* Deposit box */
.deposit {
  display: grid; grid-template-columns: auto 1fr; gap: var(--space-4);
  background: var(--swap-panel);
  border: var(--stroke-xs) solid rgba(var(--signal-rgb), 0.28);
  border-radius: var(--radius); padding: var(--space-4);
}
.qr {
  flex: none; width: 100px; height: 100px;
  background: var(--text-primary); border-radius: var(--radius); padding: 6px;
}
.qr svg { display: block; width: 100%; height: 100%; }
.qr[hidden] { display: none; }
.deposit-body { display: flex; flex-direction: column; gap: 9px; min-width: 0; }
.deposit-lede { font-size: 12.5px; color: var(--text-secondary); line-height: 1.5; }
.deposit-lede strong { color: var(--text-primary); font-weight: 500; }

.copyrow { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.copyrow .k {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-tertiary);
}
.copyrow .v {
  font-family: var(--mono); font-size: 12.5px; color: var(--text-primary);
  word-break: break-all; line-height: 1.45;
}
.copyrow .v.big { font-size: 15px; color: var(--signal); word-break: normal; }

/* The resolved swap: what replaces the send instructions once the deposit address
   they describe has been consumed. */
/* Louder than a hint, because it is the one instruction on the page whose absence
   loses funds outright. */
.deposit-warn {
  font-size: 12.5px; line-height: 1.5;
  color: #f3a6a8;
  background: color-mix(in srgb, var(--destructive) 10%, transparent);
  border: var(--stroke-xs) solid color-mix(in srgb, var(--destructive) 40%, transparent);
  border-radius: var(--radius);
  padding: 9px 11px;
}
.deposit-warn strong { color: #f8c9ca; font-weight: 600; }
/* The address-step tag warning is the one .deposit-warn that toggles; the memo
   one is built fresh each render and never hidden. */
.deposit-warn[hidden] { display: none; }
.outcome-title {
  font-size: 17px;
  font-weight: 500;
  color: var(--signal);
  letter-spacing: -0.01em;
}
.outcome-title.failed { color: var(--destructive); }

.btn-copy {
  flex: none;
  background: var(--surface-secondary); color: var(--text-primary);
  border: var(--stroke-xs) solid var(--border-primary);
  border-radius: var(--radius); padding: 3px 9px;
  font-family: var(--font); font-size: 11px; font-weight: 500; letter-spacing: 0;
  text-transform: none; cursor: pointer; white-space: nowrap;
  transition: background var(--dur-ui) var(--ease-ui), color var(--dur-ui) var(--ease-ui);
}
.btn-copy:hover { background: var(--swap-direction-hover); color: var(--signal); }

.details { display: flex; flex-direction: column; gap: 7px; font-size: 12.5px; }
.details .d-line { display: flex; justify-content: space-between; gap: 14px; }
.details .d-line > span:first-child { color: var(--text-secondary); flex: none; }
.details .d-line > span:last-child {
  font-family: var(--mono); font-size: 11.5px; text-align: right;
  overflow: hidden; text-overflow: ellipsis;
}

/* ---------------- Live progress (driven by /api/track) ---------------- */

.progress { display: flex; flex-direction: column; gap: var(--space-2); }
.progress-steps {
  display: grid; grid-template-columns: repeat(5, 1fr);
  gap: 3px; list-style: none;
}
.progress-steps li {
  height: 3px; border-radius: 2px;
  background: var(--surface-secondary);
  /* The label lives in .progress-note; each li is a bar, so hide its text. */
  font-size: 0; color: transparent; overflow: hidden;
  transition: background var(--dur-ui) var(--ease-ui);
}
.progress-steps li.done { background: var(--signal-dim); }
.progress-steps li.active { background: var(--signal); animation: pulse 1.6s var(--ease-ui) infinite; }
.progress-steps li.failed { background: var(--destructive); }
.progress-note { font-size: 12.5px; color: var(--text-secondary); }
.progress.complete .progress-note { color: var(--signal); }
.progress.failed .progress-note { color: var(--destructive); }

/* ---------------- Status messages ---------------- */

.status { border-radius: var(--radius); padding: 11px 13px; font-size: 13px; line-height: 1.55; margin: 0 var(--space-4) var(--space-4); }
.status[hidden] { display: none; }
.status.error {
  background: color-mix(in srgb, var(--destructive) 10%, transparent);
  border: var(--stroke-xs) solid color-mix(in srgb, var(--destructive) 40%, transparent);
  color: #f3a6a8;
}
.status.success {
  background: color-mix(in srgb, var(--signal) 8%, transparent);
  border: var(--stroke-xs) solid rgba(var(--signal-rgb), 0.28);
  color: var(--text-primary);
}
.status .retry {
  display: block; margin-top: 9px;
  background: transparent; border: 0; color: var(--signal);
  font-family: var(--font); font-size: 13px; font-weight: 600; cursor: pointer; padding: 0;
}

/* ---------------- Below the fold ---------------- */

section.block { padding: var(--space-9) 0; }
.section-kicker {
  font-size: 10px; font-weight: 500; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text-tertiary); margin-bottom: var(--space-3);
}
.section-head h2 {
  font-size: clamp(26px, 3.4vw, 36px);
  font-weight: 600; letter-spacing: -0.035em; max-width: 20ch;
}
.section-head p {
  margin-top: var(--space-4); max-width: 52ch;
  color: var(--text-secondary); font-size: 15.5px; line-height: 1.6;
}
.section-head.center { text-align: center; }
.section-head.center h2, .section-head.center p { margin-left: auto; margin-right: auto; }

.trust { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-3); margin-top: var(--space-7); }
.trust-card {
  background: var(--surface-primary);
  border: var(--stroke-xs) solid var(--border-primary);
  border-radius: var(--radius); padding: var(--space-5);
  transition: background var(--dur-ui) var(--ease-ui);
}
.trust-card:hover { background: var(--surface-elevated); }
.trust-card .t-tag {
  display: inline-block;
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--signal); margin-bottom: 9px;
}
.trust-card h3 { font-size: 16.5px; font-weight: 600; letter-spacing: -0.02em; margin-bottom: 6px; }
.trust-card p { font-size: 13.5px; color: var(--text-secondary); line-height: 1.6; }

.stats {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: var(--stroke-xs); margin-top: var(--space-7);
  background: var(--border-primary);
  border: var(--stroke-xs) solid var(--border-primary);
  border-radius: var(--radius); overflow: hidden;
}
.stat { background: var(--surface-base); padding: var(--space-5) var(--space-4); }
.stat dt {
  font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-tertiary); margin-bottom: 8px;
}
.stat dd {
  font-family: var(--mono); font-size: clamp(19px, 2.3vw, 25px);
  font-weight: 500; letter-spacing: -0.03em; color: var(--text-primary);
}
.stat dd small { display: block; font-family: var(--font); font-size: 12px; color: var(--text-secondary); margin-top: 5px; letter-spacing: 0; }

.features { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-3); margin-top: var(--space-7); }
.feature {
  background: var(--surface-primary);
  border: var(--stroke-xs) solid var(--border-primary);
  border-radius: var(--radius); padding: var(--space-5);
}
.feature h3 {
  font-size: 15px; font-weight: 600; letter-spacing: -0.02em;
  margin-bottom: 7px; display: flex; align-items: center; gap: 8px;
}
.feature h3::before { content: ""; flex: none; width: 5px; height: 5px; border-radius: 50%; background: var(--signal); }
.feature p { font-size: 13.5px; color: var(--text-secondary); line-height: 1.6; }

.rail { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3); margin-top: var(--space-7); }
.rail-step {
  background: var(--surface-primary);
  border: var(--stroke-xs) solid var(--border-primary);
  border-radius: var(--radius); padding: var(--space-5);
  display: flex; flex-direction: column; gap: 9px;
}
.rail-n {
  width: 26px; height: 26px; border-radius: var(--radius);
  display: grid; place-items: center;
  font-family: var(--mono); font-size: 11px; color: var(--signal);
  border: var(--stroke-xs) solid rgba(var(--signal-rgb), 0.35);
}
.rail-step h3 { font-size: 15px; font-weight: 600; letter-spacing: -0.02em; }
.rail-step p { font-size: 13px; color: var(--text-secondary); line-height: 1.6; }

.pairs { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-6); }
.pair {
  background: var(--surface-primary); color: var(--text-primary);
  border: var(--stroke-xs) solid var(--border-primary);
  border-radius: var(--radius); padding: 8px 13px;
  font-family: var(--mono); font-size: 12px; font-weight: 500; cursor: pointer;
  transition: background var(--dur-ui) var(--ease-ui), color var(--dur-ui) var(--ease-ui);
}
.pair:hover:not(:disabled) { background: var(--surface-secondary); color: var(--signal); }
.pair:disabled { opacity: 0.35; cursor: not-allowed; }

.faq { margin-top: var(--space-7); max-width: 780px; }
.faq details {
  border-bottom: var(--stroke-xs) solid var(--border-primary);
  border-radius: var(--radius);
  transition: background var(--dur-ui) var(--ease-ui);
}
.faq details[open] { background: var(--surface-primary); }
.faq summary {
  list-style: none; cursor: pointer;
  padding: 16px var(--space-4);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  font-size: 15px; font-weight: 500; letter-spacing: -0.01em;
  transition: color var(--dur-ui) var(--ease-ui);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--signal); }
.faq summary::after {
  content: ""; flex: none; width: 8px; height: 8px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--dur-ui) var(--ease-ui);
  opacity: 0.55;
}
.faq details[open] summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.faq .faq-body { padding: 0 var(--space-4) 16px; font-size: 14px; color: var(--text-secondary); line-height: 1.65; max-width: 62ch; }

/* ---------------- Footer ---------------- */

.site-foot { padding: var(--space-8) 0 var(--space-7); border-top: var(--stroke-xs) solid var(--border-primary); }
.foot-grid { display: grid; grid-template-columns: 1.6fr repeat(3, 1fr); gap: var(--space-6) var(--space-5); }
.foot-brand { max-width: 30ch; }
.foot-brand p { margin-top: var(--space-3); font-size: 13px; color: var(--text-secondary); line-height: 1.6; }
.foot-col h4 {
  font-size: 10px; font-weight: 500; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-tertiary); margin-bottom: var(--space-3);
}
.foot-col ul { list-style: none; display: flex; flex-direction: column; gap: 8px; }
.foot-col a, .foot-col button {
  background: none; border: 0; padding: 0;
  color: var(--text-primary); text-decoration: none; cursor: pointer;
  font-family: var(--font); font-size: 13px; text-align: left;
  transition: color var(--dur-ui) var(--ease-ui);
}
.foot-col a:hover, .foot-col button:hover { color: var(--signal); }
.foot-col button:disabled { opacity: 0.35; cursor: not-allowed; }
.foot-pairs { columns: 2; column-gap: var(--space-4); }
.foot-pairs li { break-inside: avoid; margin-bottom: 8px; }

.foot-base {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: var(--space-3);
  margin-top: var(--space-7); padding-top: var(--space-5);
  border-top: var(--stroke-xs) solid var(--border-primary);
  color: var(--text-tertiary); font-size: 12px;
}
.disclaimer { margin-top: var(--space-4); color: var(--text-tertiary); font-size: 11.5px; line-height: 1.65; max-width: 76ch; }

/* ---------------- Reveal ---------------- */

.reveal { opacity: 0; transform: translateY(20px); }
.reveal.in { animation: revealIn var(--dur-arrive) var(--ease-arrive) forwards; }
@keyframes revealIn { to { opacity: 1; transform: none; } }

/* Without scripting nothing adds .in, which would hide every section below
   the fold permanently. Show them outright instead. */
@media (scripting: none) {
  .reveal { opacity: 1; transform: none; }
}

/* ---------------- Responsive ---------------- */

@media (max-width: 1023px) {
  .trust, .features, .rail { grid-template-columns: repeat(2, 1fr); }
  .foot-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 767px) {
  .wrap { width: calc(100% - 32px); }
  .nav-links, .head-cta { display: none; }
  .nav-toggle { display: block; margin-left: auto; }

  .hero { padding: var(--space-7) 0 var(--space-8); }
  section.block { padding: var(--space-8) 0; }

  .step { flex-direction: column; gap: 4px; padding: 9px 4px; text-align: center; }
  .step-label { font-size: 10px; }
  .token-menu { left: var(--space-4); right: var(--space-4); }
  .amount, .amount-out { font-size: clamp(18px, 6vw, 24px); }

  .deposit { grid-template-columns: 1fr; justify-items: center; }
  .deposit-body { width: 100%; }

  .trust, .features, .rail { grid-template-columns: 1fr; }
  .stats { grid-template-columns: 1fr 1fr; }
  .foot-grid { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal, .reveal.in { opacity: 1; transform: none; animation: none; }
  .nav-overlay a { opacity: 1; transform: none; animation: none; }
  .amount-out.bump, .amount-out.loading, .flip.spin, .token-menu,
  .order-elapsed .pip, .progress-steps li.active { animation: none; }
  * { transition: none !important; }
}

/* ================================================================
   Redesign, 2026-08-20 — hierarchy by consequence, not by uniformity
   ================================================================

   The widget had one visual voice for everything: rounded card, same
   radius, same surface, same weight. That reads as tidy and tells the
   user nothing about what matters. Three screens were reworked, and the
   rule driving all three is that emphasis follows *consequence* — how
   much it costs to get that element wrong.

   On the deposit view that inverted the old order outright: the address
   is the one string that must be reproduced character-for-character, and
   it was set smaller than the amount beside it, under a QR panel that was
   the loudest thing on screen.
   ---------------------------------------------------------------- */

/* ---- Deposit view ---- */

/* The address leads. It gets the block's own weight and a rule above it,
   because everything else on this screen can be re-read and it cannot be
   un-sent. */
.copyrow.is-primary {
  padding-top: var(--space-3);
  border-top: var(--stroke-xs) solid var(--border-primary);
}
.copyrow .v.addr {
  font-size: 15px;
  line-height: 1.5;
  color: var(--text-primary);
  letter-spacing: 0.01em;
}
/* The amount steps back a little so the address can lead. It stays in the
   accent because it is still a figure the user must match exactly. */
.copyrow .v.big { font-size: 14px; }

/* The QR was `background: var(--text-primary)` — a full-strength cream slab,
   the brightest surface on a near-black page, carrying the least actionable
   thing on it. A QR needs light backing to scan; it does not need to be the
   loudest element. This is dimmed to the point where contrast is still far
   past the ~3:1 that scanners want, and framed rather than floated. */
.qr {
  width: 92px; height: 92px;
  background: #d8d6d0;
  border: var(--stroke-xs) solid var(--border-primary);
  padding: 5px;
}

/* ---- Progress ---- */

/* Five 3px hairlines with the label in a separate line below read as
   decoration. This is the only feedback a user gets while their funds are
   in flight, so it carries an actual current-step label and a track thick
   enough to see. */
.progress { gap: var(--space-3); }
.progress-steps { gap: 4px; }
.progress-steps li {
  height: 5px;
  border-radius: 3px;
  background: var(--surface-secondary);
}
.progress-note {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 13px; color: var(--text-primary); font-weight: 500;
}
/* The step count sits beside the label so "where am I" is answerable
   without counting bars. */
.progress-note::after {
  content: attr(data-step);
  margin-left: auto;
  font-family: var(--mono); font-size: 11px; font-weight: 400;
  color: var(--text-tertiary);
}

/* ---- Quote panel ---- */

/* The two wells were identical, so nothing distinguished the field you type
   into from the figure you read out. Send keeps its affordance; receive is
   a readout and now looks like one. */
.well.is-readout {
  background: transparent;
  border-color: var(--border-secondary);
}
.well.is-readout:hover { background: transparent; }

/* Total cost was the first of five rows of equal weight — the decision
   figure filed alongside "Rate type". It gets its own band above the
   button, where the decision is actually made. */
.meta-line#meta-cost-line {
  padding-bottom: var(--space-2);
  margin-bottom: var(--space-1);
  border-bottom: var(--stroke-xs) solid var(--border-primary);
  font-size: 14px;
}
.meta-line#meta-cost-line > span:first-child { color: var(--text-primary); font-weight: 500; }
.meta-line#meta-cost-line > span:last-child { font-size: 14px; }

/* ---- Address step ---- */

/* One more filled grey box was one too many on a screen that is already
   three stacked boxes. A ruled note says the same thing and stops competing
   with the fields it is about. */
.warn {
  background: transparent;
  border: 0;
  border-left: 2px solid var(--caution);
  border-radius: 0;
  padding: 2px 0 2px var(--space-3);
}

/* ---- Information added from the Chainflip reference, 2026-08-20 ---- */

/* A deposit channel expires, and SwapKit says when — the field was simply
   discarded. Amber rather than red: the address is still good, it just has a
   deadline. When it lapses the line becomes a .deposit-warn instead, because at
   that point it is no longer a countdown but an instruction not to send. */
.deposit-expiry {
  display: flex; align-items: center; gap: 7px;
  font-size: 12px; color: var(--caution);
}
.deposit-expiry::before {
  content: ""; flex: none;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--caution);
}

/* Fiat sits beside its figure rather than under it, so the pair reads as one
   value. Tertiary and lighter so it never competes with the number the user has
   to reproduce exactly. */
.v-fiat {
  margin-left: 8px;
  font-size: 12px; font-weight: 400;
  color: var(--text-tertiary);
  letter-spacing: 0;
}
