/* Tokens Saved — design system
   Tokens derived from Uniswap's open-source Spore system (Uniswap/interface:
   packages/ui/src/theme/colors.ts, borderRadii.ts, spacing.ts, fonts.ts) plus a
   measured capture of app.uniswap.org's computed styles.

   Two rules that are load-bearing, both learned the hard way:
   1. Surfaces separate by FILL CONTRAST, not borders and shadows. Uniswap's
      marketing surfaces carry neither. Adding a border to a card here breaks the
      resemblance more than any colour would.
   2. Every value below was contrast-checked against composited pixels. Uniswap's
      own neutral3 (2.26:1) and their brand pink (3.17:1) FAIL AA as small text on
      white, so they are deliberately not used that way. --acc-fill takes DARK text
      (7.45:1); white on it is 2.50:1 and must never ship. */

:root{
  /* ── light: Spore surface1/surface2 ── */
  --bg:#FFFFFF;            /* surface1 — measured oklch(1 0 0) */
  --bg-2:#F9F9F9;          /* surface2 — raised fill */
  --bg-3:#F2F2F2;          /* surface3 solid — deeper fill */
  --line:rgba(19,19,19,.08);   /* surface3 — hairline only, used sparingly */
  --line-2:rgba(19,19,19,.14);

  --ink:#131313;                 /* neutral1        18.58:1 */
  --ink-2:rgba(19,19,19,.63);    /* neutral2         5.38:1 */
  --ink-3:rgba(19,19,19,.60);    /* derived; Spore's .35 fails AA at 2.26:1 */

  --acc-fill:#19BB77;      /* button fill — takes DARK text */
  --acc-ink:#131313;       /* label ON acc-fill              7.45:1 */
  --acc-text:#0B7A4B;      /* links, eyebrows  5.39:1 on bg, 4.92:1 on tint */
  --acc-soft:rgba(25,187,119,.10);
  --acc-line:rgba(13,130,82,.22);

  --warn:#996F01;          /* statusWarning light */
  --stop:#E10F0F;          /* statusCritical light */
  --tag-same-bg:#E6F7EF; --tag-same-ink:#0A5C36;
  --tag-diff-bg:#FDE8E8; --tag-diff-ink:#A11212;

  /* Uniswap's real radius scale */
  --r-32:32px; --r-28:28px; --r-24:24px; --r-20:20px; --r-16:16px; --r-12:12px; --r-8:8px;
  --r-full:999px;

  /* shadows exist in Spore but are reserved for genuinely floating things */
  --shadow-pop:0 4px 24px rgba(19,19,19,.10);

  --sans:'Inter var','Inter',-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  --w-book:485; --w-med:535;   /* Basel's real weights; degrade fine on system fonts */

  --nav-h:72px;                /* INTERFACE_NAV_HEIGHT */
  --gut:clamp(1.15rem,5vw,3rem);
  --max:72rem;
  --rhythm:clamp(4.5rem,11vw,8rem);
}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --bg:#131313;            /* surface1 dark */
  --bg-2:#1F1F1F;          /* surface2 dark */
  --bg-3:#393939;          /* surface3Solid dark */
  --line:rgba(255,255,255,.12);
  --line-2:rgba(255,255,255,.18);

  --ink:#FFFFFF;
  --ink-2:rgba(255,255,255,.65);
  --ink-3:rgba(255,255,255,.62);

  --acc-fill:#21C95E;      /* statusSuccess dark */
  --acc-ink:#0A1A10;
  --acc-text:#21C95E;      /* 8.6:1 on #131313 */
  --acc-soft:rgba(33,201,94,.12);
  --acc-line:rgba(33,201,94,.26);

  --warn:#FFBF17; --stop:#FF593C;
  --tag-same-bg:#10331F; --tag-same-ink:#5FE39B;
  --tag-diff-bg:#3A1B16; --tag-diff-ink:#FF8B76;
  --shadow-pop:0 4px 24px rgba(0,0,0,.5);
}}
:root[data-theme="dark"]{
  --bg:#131313; --bg-2:#1F1F1F; --bg-3:#393939;
  --line:rgba(255,255,255,.12); --line-2:rgba(255,255,255,.18);
  --ink:#FFFFFF; --ink-2:rgba(255,255,255,.65); --ink-3:rgba(255,255,255,.62);
  --acc-fill:#21C95E; --acc-ink:#0A1A10; --acc-text:#21C95E;
  --acc-soft:rgba(33,201,94,.12); --acc-line:rgba(33,201,94,.26);
  --warn:#FFBF17; --stop:#FF593C;
  --tag-same-bg:#10331F; --tag-same-ink:#5FE39B;
  --tag-diff-bg:#3A1B16; --tag-diff-ink:#FF8B76;
  --shadow-pop:0 4px 24px rgba(0,0,0,.5);
}

*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
body{background:var(--bg);color:var(--ink);font-family:var(--sans);font-size:16px;
  font-weight:var(--w-book);line-height:1.6;-webkit-font-smoothing:antialiased;overflow-x:hidden}
.wrap{max-width:var(--max);margin:0 auto;padding-inline:var(--gut)}
::selection{background:var(--acc-fill);color:var(--acc-ink)}
:focus-visible{outline:2px solid var(--acc-text);outline-offset:3px;border-radius:var(--r-12)}

/* ── nav: plain full-width bar (Spore INTERFACE_NAV_HEIGHT 72px), hairline only ── */
nav{height:var(--nav-h);border-bottom:1px solid var(--line)}
nav .inner{display:flex;align-items:center;gap:1.75rem;height:100%;
  max-width:var(--max);margin:0 auto;padding-inline:var(--gut)}
.brand{font-weight:var(--w-med);letter-spacing:-.022em;font-size:1.06rem;display:flex;
  align-items:center;gap:.55rem;text-decoration:none;color:var(--ink);margin-right:auto}
.brand .dot{width:10px;height:10px;border-radius:50%;background:var(--acc-fill)}
nav .links{display:flex;gap:1.5rem;align-items:center}
nav .links a{font-size:.92rem;color:var(--ink-2);text-decoration:none;font-weight:var(--w-book)}
nav .links a:hover,nav .links a[aria-current]{color:var(--ink)}
nav .links a[aria-current]{font-weight:var(--w-med)}
@media(max-width:680px){nav .links a.hide-sm{display:none}nav .inner{gap:1.1rem}}

/* ── type ──
   Re-measured off uniswap.org 2026-08-09, and the numbers were not what this file
   assumed. Their h1 is 64px / weight 485 / line-height 76px (1.1875) / letter-spacing
   NORMAL. Not a tight heavy display face — a light one with air in it. The earlier
   values here (weight 535, -.042em, 1.02) were the generic SaaS display setting, and
   they are the single biggest reason the page did not read as Uniswap. The only
   departure kept is -.012em, because Inter/SF run wider than Basel at display size and
   true `normal` opens the line past the reference. */
.eyebrow{font-size:.8rem;letter-spacing:.01em;color:var(--acc-text);font-weight:var(--w-med)}
h1{font-size:clamp(2.5rem,6.4vw,4rem);line-height:1.1875;letter-spacing:-.012em;
  font-weight:var(--w-book);text-wrap:balance}
h2{font-size:clamp(1.7rem,4vw,2.6rem);line-height:1.16;letter-spacing:-.014em;
  font-weight:var(--w-book);text-wrap:balance}
h3{font-size:1.06rem;font-weight:var(--w-med);letter-spacing:-.014em}
p{max-width:62ch}
.lede{font-size:clamp(1.05rem,2vw,1.24rem);color:var(--ink-2);max-width:54ch;line-height:1.55}
a{color:var(--acc-text)}
strong{color:var(--ink);font-weight:var(--w-med)}
code{font-family:var(--mono);font-size:.88em;background:var(--bg-2);color:var(--ink);
  padding:.14em .44em;border-radius:var(--r-8)}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}

/* ── layout ── */
section{padding-block:var(--rhythm)}
.head{display:flex;flex-direction:column;gap:1rem;max-width:56ch}
.stack{display:flex;flex-direction:column;gap:1.3rem}
.grid{display:grid;gap:.9rem}
.g2{grid-template-columns:repeat(auto-fit,minmax(18rem,1fr))}
.g3{grid-template-columns:repeat(auto-fit,minmax(15rem,1fr))}
.mt{margin-top:2.6rem}

/* ── buttons: 20px radius (Spore rounded20), NOT a pill ── */
.btn{font-size:1rem;font-weight:var(--w-med);padding:.9rem 1.6rem;border-radius:var(--r-20);
  text-decoration:none;display:inline-block;border:none;cursor:pointer;
  transition:filter .15s ease,background .15s ease}
.btn.pri{background:var(--acc-fill);color:var(--acc-ink)}   /* dark on green — 7.45:1 */
.btn.pri:hover{filter:brightness(1.06)}
.btn.sec{background:var(--bg-2);color:var(--ink)}
.btn.sec:hover{background:var(--bg-3)}
.btn.sm{padding:.6rem 1.1rem;font-size:.9rem;border-radius:var(--r-12)}
.row{display:flex;flex-wrap:wrap;gap:.75rem;align-items:center}

/* ── surfaces: FILL CONTRAST, no border, no shadow ── */
.card{background:var(--bg-2);border-radius:var(--r-20);padding:1.75rem;
  display:flex;flex-direction:column;gap:.65rem}
.card .num{font-size:2.2rem;font-weight:var(--w-med);letter-spacing:-.04em;
  color:var(--acc-text);display:block;line-height:1}
.card p{font-size:.95rem;color:var(--ink-2)}
.panel{background:var(--bg-2);border-radius:var(--r-24);padding:1.75rem}

.figs{display:grid;grid-template-columns:repeat(auto-fit,minmax(9.5rem,1fr));gap:.6rem}
.fig{background:var(--bg-2);border-radius:var(--r-16);padding:1.3rem 1.35rem}
.fig .k,.fig .v,.fig .n{display:block}
.fig .k{font-size:.82rem;color:var(--ink-2)}
.fig .v{font-size:clamp(1.6rem,3.6vw,2.15rem);font-weight:var(--w-med);
  letter-spacing:-.04em;line-height:1.14;margin-top:.3rem;font-variant-numeric:tabular-nums}
.fig .n{font-size:.8rem;color:var(--ink-3);margin-top:.2rem}
.fig .v.acc{color:var(--acc-text)} .fig .v.dim{color:var(--ink-2)} .fig .v.bad{color:var(--stop)}

/* ── table ── */
.tw{overflow-x:auto;border-radius:var(--r-20);background:var(--bg-2)}
table{border-collapse:collapse;width:100%;font-size:.9rem}
th,td{padding:.95rem 1.15rem;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}
thead th{font-size:.82rem;color:var(--ink-2);font-weight:var(--w-med)}
tbody td{color:var(--ink-2)}
tbody td:first-child{color:var(--ink);font-weight:var(--w-med);white-space:nowrap}
tbody tr:last-child td{border-bottom:none}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.tag{font-size:.74rem;font-weight:var(--w-med);padding:.28em .7em;border-radius:var(--r-8);white-space:nowrap}
.tag.same{background:var(--tag-same-bg);color:var(--tag-same-ink)}
.tag.diff{background:var(--tag-diff-bg);color:var(--tag-diff-ink)}

/* ── notes ── */
.note{font-size:.95rem;color:var(--ink-2);background:var(--bg-2);border-radius:var(--r-16);
  padding:1.15rem 1.3rem;max-width:62ch}
.note.warn{background:var(--acc-soft)}
.tbd{color:var(--warn);font-family:var(--mono);font-size:.92em}

/* ── footer ── */
footer{border-top:1px solid var(--line);padding-block:3rem 4rem}
footer .wrap{display:flex;flex-wrap:wrap;gap:2.5rem;justify-content:space-between;align-items:flex-start}
footer .fl{display:flex;flex-direction:column;gap:.55rem}
footer .fl a{font-size:.92rem;color:var(--ink-2);text-decoration:none}
footer .fl a:hover{color:var(--ink)}
footer small{font-size:.82rem;color:var(--ink-3);line-height:1.75;display:block;max-width:44ch}

/* ── motion ── */
.reveal{opacity:0;transform:translateY(10px);
  transition:opacity .42s cubic-bezier(.16,1,.3,1),transform .42s cubic-bezier(.16,1,.3,1)}
.reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  .reveal{opacity:1;transform:none;transition:none}
  *{transition:none!important;animation:none!important}
}


/* ── module: Uniswap's stacked-row card (their swap widget's structure) ── */
.module{background:var(--bg-2);border-radius:var(--r-24);padding:.45rem;
  display:flex;flex-direction:column;gap:.3rem}
.module .rowcard{background:var(--bg);border-radius:var(--r-20);padding:1.15rem 1.3rem}
.module .rowcard.flush{background:transparent;padding:1rem 1.3rem}
:root[data-theme="dark"] .module .rowcard,
:root:not([data-theme="light"]) .module .rowcard{background:var(--bg-3)}
@media (prefers-color-scheme:light){:root:not([data-theme="dark"]) .module .rowcard{background:var(--bg)}}


/* ── hero art ──────────────────────────────────────────────────────────── */
.hero{position:relative;overflow:hidden}
.hero-art{position:absolute;inset:0 0 auto 0;height:min(78vh,720px);z-index:-2;
  pointer-events:none;overflow:hidden}
.hero-art img{width:100%;height:100%;object-fit:cover;object-position:70% 45%;
  opacity:.92;will-change:transform}
/* fade the art into the page ground so there is never a hard seam */
.hero-art::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to bottom,transparent 30%,var(--bg) 94%),
             linear-gradient(to right,var(--bg) 0%,var(--bg) 33%,rgba(0,0,0,0) 66%)}
:root[data-theme="dark"] .hero-art img,
:root:not([data-theme="light"]) .hero-art img{opacity:.34}
@media (prefers-color-scheme:light){:root:not([data-theme="dark"]) .hero-art img{opacity:.92}}

/* on narrow viewports the copy column spans most of the width, so the
   left-to-right scrim never reaches it — hold more ground there. */
@media(max-width:760px){
  .hero-art::after{background:linear-gradient(to bottom,transparent 16%,var(--bg) 86%),
    linear-gradient(to right,var(--bg) 0%,var(--bg) 64%,rgba(0,0,0,0) 100%)}
  .hero-art img{opacity:.7}
}

/* ── ambient drift on the brand dot — the one piece of autonomous motion ── */
@keyframes breathe{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.35);opacity:.72}}
.brand .dot{animation:breathe 3.6s ease-in-out infinite}

/* ── lift on interactive surfaces ───────────────────────────────────────── */
.card,.fig{transition:transform .22s cubic-bezier(.16,1,.3,1),background .22s ease}
.card:hover,.fig:hover{transform:translateY(-2px);background:var(--bg-3)}
.btn.pri{position:relative;overflow:hidden}
.btn.pri::after{content:"";position:absolute;inset:0;
  background:linear-gradient(120deg,transparent 30%,rgba(255,255,255,.34) 50%,transparent 70%);
  transform:translateX(-120%)}
.btn.pri:hover::after{transform:translateX(120%);transition:transform .7s ease}

/* ── dark band section ──────────────────────────────────────────────────── */
.band{position:relative;overflow:hidden;border-radius:var(--r-32);
  background:#0E1512;color:#FFFFFF;padding:clamp(2.5rem,7vw,4.5rem)}
.band .art{position:absolute;inset:0;z-index:0}
.band .art img{width:100%;height:100%;object-fit:cover;opacity:.5}
.band > *{position:relative;z-index:1}
.band h2{color:#FFFFFF}
.band p{color:rgba(255,255,255,.72)}
.band .eyebrow{color:#5FE39B}

@media (prefers-reduced-motion:reduce){
  .brand .dot{animation:none}
  .card:hover,.fig:hover{transform:none}
  .btn.pri::after{display:none}
  .hero-art img{transform:none!important}
}


/* ══ orb field ═══════════════════════════════════════════════════════════
   Replaces the photographic hero art. Measured off uniswap.org: flat-colour
   discs, blur 5→45px, opacity tracking the blur. Two things this buys beyond
   resemblance — it is ~0 bytes, and it retired every scrim this file used to
   need to keep hero text legible over a bitmap. Text now sits on plain ground. */
.orbwrap{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden;
  contain:strict}
.orb{position:absolute;border-radius:50%;transform:translate3d(0,0,0)}
/* the field sits behind everything in the hero, including the card */
.hero > .wrap{position:relative;z-index:1}

/* ══ centered hero — the reference's actual composition ══════════════════
   uniswap.org centres a 64px headline, puts the PRODUCT directly underneath as
   a live widget, then a 16px full-ink line, then a scroll cue. The widget is
   the hero; there is no hero image and no button pair floating in space. */
.hero.mid{text-align:center;padding-block:clamp(3rem,7vw,5.5rem) clamp(2.5rem,6vw,4rem);
  display:flex;flex-direction:column;align-items:center}
.hero.mid .wrap{display:flex;flex-direction:column;align-items:center;width:100%}
.hero.mid h1{max-width:17ch}
.hero.mid .subline{font-size:1rem;line-height:1.5;color:var(--ink);max-width:46ch;
  margin-top:1.4rem}                     /* full ink at 16px — their choice, not muted */
.hero.mid .subline a{text-decoration:none;font-weight:var(--w-med)}
.hero.mid .subline a:hover{text-decoration:underline}
.hero.mid .fine{font-size:.84rem;color:var(--ink-3);margin-top:.7rem}

/* the widget */
.meter{width:100%;max-width:463px;margin-top:2.4rem;text-align:left;position:relative}
.meter .module{background:var(--bg-2);padding:.4rem;gap:.25rem}
.meter .rowcard{padding:1.15rem 1.25rem;position:relative}
.meter .lab{font-size:.85rem;color:var(--ink-2);display:block;margin-bottom:.35rem}
.meter .big{display:flex;align-items:center;gap:.6rem;justify-content:space-between}
.meter .amt{font-size:2rem;line-height:1.15;font-weight:var(--w-book);letter-spacing:-.028em;
  font-variant-numeric:tabular-nums;color:var(--ink);border:none;background:none;
  width:100%;min-width:0;padding:0;font-family:inherit}
.meter .amt:focus{outline:none}
.meter .amt::-webkit-outer-spin-button,.meter .amt::-webkit-inner-spin-button{
  -webkit-appearance:none;margin:0}
.meter .amt[type=number]{-moz-appearance:textfield}
.meter .out{color:var(--acc-text)}
.meter .sub{font-size:.85rem;color:var(--ink-3);margin-top:.3rem;display:block}
.meter .chip{background:var(--bg-3);border-radius:var(--r-full);padding:.42rem .85rem;
  font-size:.86rem;font-weight:var(--w-med);white-space:nowrap;display:flex;
  align-items:center;gap:.4rem;color:var(--ink)}
.meter .chip .cd{width:8px;height:8px;border-radius:50%;background:var(--acc-fill)}
/* the button that straddles the seam between the two rows, exactly as theirs does.
   It anchors to .rows, NOT to .meter — anchoring to .meter puts 50% below the CTA
   button and drops the marker into the middle of the second card. */
.meter .rows{position:relative;display:flex;flex-direction:column;gap:.25rem}
.meter .seam{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:38px;height:38px;border-radius:var(--r-12);background:var(--bg);
  display:grid;place-items:center;z-index:2;border:4px solid var(--bg-2);
  color:var(--ink-2);font-size:1rem;line-height:1}
.meter .btn{width:100%;text-align:center;margin-top:.25rem;padding:1.05rem 1.6rem;
  border-radius:var(--r-20)}
:root[data-theme="dark"] .meter .seam,
:root:not([data-theme="light"]) .meter .seam{background:var(--bg-3);border-color:var(--bg-2)}
@media (prefers-color-scheme:light){
  :root:not([data-theme="dark"]) .meter .seam{background:var(--bg);border-color:var(--bg-2)}}

/* scroll cue */
.cue{margin-top:clamp(2.5rem,6vw,3.75rem);display:flex;flex-direction:column;
  align-items:center;gap:.35rem;font-size:.85rem;color:var(--ink-3)}
.cue svg{display:block}
@keyframes nudge{0%,100%{transform:translateY(0);opacity:.55}50%{transform:translateY(4px);opacity:1}}
.cue svg{animation:nudge 2.1s ease-in-out infinite}

/* inner-page heroes get the same field, quieter */
.hero.slim{position:relative;padding-block:clamp(2.5rem,6vw,4rem) clamp(1.5rem,4vw,2.5rem)}
.hero.slim .orbwrap{opacity:.62}

/* inner-page + 404 heroes host the same field, quieter and behind the copy */
.page-head>.wrap,.lost>.wrap{position:relative;z-index:1}
.page-head .orbwrap,.lost .orbwrap{opacity:.66}

/* On a narrow viewport the copy column spans the full width, so there is no margin
   for the field to live in and a disc always ends up under text. --acc-text has only
   0.89 of headroom over the 4.5:1 floor on white, and a lightly tinted backdrop eats
   all of it — measured at 3.42:1 under an eyebrow before this rule. Fade the field
   rather than move it; the depth read survives, the contrast comes back. */
@media(max-width:760px){
  .orbwrap{opacity:.30}
  .page-head .orbwrap,.lost .orbwrap{opacity:.22}
}

/* ══ media panel — a section that is mostly picture ═══════════════════════
   Uniswap breaks its long text runs with wide illustrative panels; without
   them the 256px inter-section gaps here read as an unfinished page. */
.split{display:grid;grid-template-columns:1.15fr .85fr;gap:clamp(1.5rem,4vw,3rem);
  align-items:center}
@media(max-width:860px){.split{grid-template-columns:1fr}}
.media{border-radius:var(--r-32);overflow:hidden;background:var(--bg-2);
  aspect-ratio:16/9;display:block}
.media img{width:100%;height:100%;object-fit:cover;display:block}
.split .copy{display:flex;flex-direction:column;gap:1rem}
.split .copy p{max-width:38ch}

/* band.avif runs brighter than the ribbon art it replaced, and the 72%-white lede
   dropped to 3.42:1 over its light ribbons. Scrim the ART, not the section: the
   ground stays #0E1512 so the copy column sits on a known colour, and the picture
   keeps its full brightness at the right edge where nothing is written. */
.band .art::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to right,#0E1512 0%,rgba(14,21,18,.90) 46%,rgba(14,21,18,.30) 100%)}
@media(max-width:860px){
  .band .art::after{background:linear-gradient(to right,#0E1512 0%,rgba(14,21,18,.93) 72%,rgba(14,21,18,.55) 100%)}
}
