/* ETHERWOOD launchpad
 *
 * The palette is taken off the logo rather than invented next to it: a carved
 * wood-grain Ethereum diamond in vivid spring green on true black. Sampling
 * the art puts the ground at #000000 and the brightest grain at #3CFF80, and
 * those are the two ends of everything below.
 *
 * The sheet this replaces had the ground at #172219, a dark olive, and stepped
 * its surfaces up through more olives. Two things went wrong with that. Green
 * surfaces under a green accent leave the accent nothing to be brighter than,
 * so the one colour that should pull the eye competed with the furniture for
 * it. And an olive ground next to the logo's black read as a different brand.
 *
 * So: the ground is black, surfaces step up through neutral charcoals with
 * only a trace of green in them, and saturated green is spent exclusively on
 * things you can press, figures that matter, and focus. Everything else is
 * greyscale. The accent is the only colour on the page, which is what makes it
 * register as a colour at all.
 *
 * Type is Geist and Geist Mono, self-hosted as two variable woff2 files. The
 * mono is not decoration: it is on every number, address, selector and hex
 * string, where a fixed advance width is what lets you compare two of them by
 * eye. Prose is never mono.
 */

/* ---- type ---------------------------------------------------------------
 * Both faces are variable, so one file covers the whole weight range and
 * there is no second request for a bold. `swap` because the fallback metrics
 * are close enough that the reflow is not violent, and blocking paint on a
 * font is worse than a flash of the system sans.
 */
@font-face {
  font-family: "Geist";
  src: url("/fonts/GeistVariable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-display: swap;
  font-style: normal;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/fonts/GeistMonoVariable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-display: swap;
  font-style: normal;
}

:root {
  /* Ground and surfaces.
   *
   * The previous steps ran to #252a27, which is a light enough grey that a
   * page of inputs and cards read as a sheet of charcoal boxes sitting on
   * black rather than as a black page. Filled grey is the thing that looked
   * cheap. These are all within a few points of black, so a surface is
   * defined by its border and not by being visibly paler than the page, and
   * the ground stays actually black the way the logo lockup is.
   *
   * The green in them is real now rather than a token few percent: these are
   * hue 150 at roughly 30% saturation, dark enough that they still read as
   * black and not as green. */
  --bg:        #000000;
  --surface:   #050a07;
  --surface-2: #0a110d;
  --surface-3: #0f1813;
  --surface-4: #16241b;

  /* Borders carry the structure now that fills do not, so they have to be
     genuinely visible rather than a hairline you infer. This is the part
     that makes a page of boxes read as boxes: with the fills nearly black,
     a border at 9% lightness simply is not there, and every control melts
     into the page. */
  --line:      #1e402a;
  --line-hi:   #2f6342;

  /* Text is green-cast, not neutral.
   *
   * An earlier pass made these near-neutral on the theory that green body
   * copy is tiring and dilutes the accent. On a true black ground that was
   * wrong in practice: neutral grey on black is what made the page look
   * like an unstyled default. The hue is constant and only lightness moves,
   * so the accent still stands apart by being far brighter and fully
   * saturated rather than by being the only green thing. */
  --text:      #d6f5e2;
  --dim:       #8fbfa2;
  --faint:     #5c8770;

  /* The accent, straight off the art. --acc is the logo's brightest grain,
     --acc-hi is for hover and glow, --acc-lo is the deep carved green used
     for borders and secondary marks, and --on-acc is the only thing legible
     on top of a filled accent surface. */
  --acc:       #3cff80;
  --acc-hi:    #6bff9f;
  --acc-lo:    #18a852;
  --acc-dk:    #0e6e38;   /* third step, still readable as a fill */
  --acc-deep:  #0c3f21;   /* borders and washes only, not fills */
  --on-acc:    #00140a;

  /* States. Muted against the accent on purpose: a red that competes with
     the green for attention makes every error feel like a crash. */
  --red:       #ff6b6b;
  --amber:     #ffc857;

  /* Washes and rings, stated outright in both themes. The sheet this
     replaces wrote `--tint-soft: var(--tint-soft)` in the dark theme, which
     is a cycle and therefore invalid, so dark mode silently had no soft
     tints, no focus rings and no error washes at all. That was most of the
     reason it felt unfinished without being possible to point at. */
  --tint:      rgba(60, 255, 128, .10);
  --tint-soft: rgba(60, 255, 128, .055);
  --tint-line: rgba(60, 255, 128, .28);
  --ring:      rgba(60, 255, 128, .30);
  --tint-bad:  rgba(255, 107, 107, .10);
  --ring-bad:  rgba(255, 107, 107, .30);
  --tint-warn: rgba(255, 200, 87, .10);

  --bar-bg:    rgba(6, 8, 7, .72);
  --veil:      rgba(0, 0, 0, .66);

  --sans: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --mono: "Geist Mono", ui-monospace, "SF Mono", SFMono-Regular, "Cascadia Mono",
          "JetBrains Mono", Menlo, Consolas, monospace;

  /* Radii. Larger than the old single 8px, and graded, because "slick" is
     mostly a corner-radius decision: chips and buttons are pills, controls
     and cards are generously rounded, and the page never shows a hard corner
     except where two surfaces meet at full width. */
  --r-xs:   6px;
  --r-sm:   10px;
  --r:      14px;
  --r-lg:   18px;
  --r-xl:   24px;
  --r-pill: 999px;

  /* Elevation, and one glow.
   *
   * Each step carries an inner highlight along its top edge as well as a
   * shadow, because on a black ground a shadow alone does almost nothing:
   * there is no light for a dark blur to subtract from, so a card with only
   * `0 6px 20px rgba(0,0,0,.7)` under it is visually flat. A 1px inner line
   * of near-white along the top reads as a lit edge and is what actually
   * separates a surface from the page. The light theme restates these
   * without it, where the ordinary shadow works and a white inner line on
   * white is invisible anyway.
   *
   * The glow is only ever on the primary action and on focus, so it stays
   * meaningful. */
  --sh-1: 0 1px 2px rgba(0, 0, 0, .55),
          inset 0 1px 0 rgba(236, 246, 240, .045);
  --sh-2: 0 6px 20px -6px rgba(0, 0, 0, .70),
          inset 0 1px 0 rgba(236, 246, 240, .055);
  --sh-3: 0 22px 60px -16px rgba(0, 0, 0, .80),
          inset 0 1px 0 rgba(236, 246, 240, .07);
  --glow: 0 0 0 1px rgba(60, 255, 128, .22), 0 10px 34px -10px rgba(60, 255, 128, .34);

  /* Motion. Two curves: --ease for anything that moves a colour, --spring for
     anything that moves a position or a size, because a decelerating curve is
     what reads as "smooth" rather than "animated". */
  --t-fast: 110ms;
  --t:      180ms;
  --t-slow: 340ms;
  --t-fill: 700ms;   /* proportion bars only, see .pbar span */
  --ease:   cubic-bezier(.4, 0, .2, 1);
  --spring: cubic-bezier(.16, 1, .3, 1);

  --w:     1180px;   /* content width */
  --w-nar: 760px;    /* prose width */
}

/* ---- the light theme ----------------------------------------------------
 * Paper rather than white. Flat #ffffff under a spring-green accent glares,
 * and the surface ramp needs somewhere to go, so the ground is a warm
 * off-white and surfaces step DOWN into grey: the mirror of the dark theme
 * stepping up, and a card is still a card without a border.
 *
 * The accent is the part that cannot transfer. #3cff80 is tuned to glow on
 * black; on paper it is a highlighter and fails contrast under any text. So
 * the light theme fills with a deep forest green and keeps the bright one
 * only for large figures and for glow, where contrast is not the constraint.
 */
:root[data-theme="light"] {
  --bg:        #f7f8f6;
  --surface:   #ffffff;
  --surface-2: #f1f3f0;
  --surface-3: #e7eae6;
  --surface-4: #dae0db;

  --line:      #dfe4df;
  --line-hi:   #bcc6bd;

  --text:      #0d1410;
  --dim:       #4a564e;
  --faint:     #6d7a71;

  --acc:       #0a8f45;
  --acc-hi:    #067038;   /* hover goes darker on paper, not brighter */
  --acc-lo:    #34c77d;
  --acc-dk:    #8fdfb4;   /* on paper the ramp runs lighter, not darker */
  --acc-deep:  #d7f3e2;
  --on-acc:    #ffffff;

  --red:       #b3261e;
  --amber:     #8a6100;

  --tint:      rgba(10, 143, 69, .09);
  --tint-soft: rgba(10, 143, 69, .05);
  --tint-line: rgba(10, 143, 69, .30);
  --ring:      rgba(10, 143, 69, .24);
  --tint-bad:  rgba(179, 38, 30, .09);
  --ring-bad:  rgba(179, 38, 30, .22);
  --tint-warn: rgba(138, 97, 0, .10);

  --bar-bg:    rgba(255, 255, 255, .78);
  --veil:      rgba(20, 28, 22, .38);

  /* No inner highlight on paper: a white line along the top of a white card
     is invisible, and the ordinary shadow already reads. */
  --sh-1: 0 1px 2px rgba(16, 24, 19, .07);
  --sh-2: 0 6px 20px -6px rgba(16, 24, 19, .13);
  --sh-3: 0 22px 60px -16px rgba(16, 24, 19, .18);
  --glow: 0 0 0 1px rgba(10, 143, 69, .20), 0 10px 30px -12px rgba(10, 143, 69, .30);
}

/* Follow the operating system until the visitor says otherwise, at which point
 * theme.js sets data-theme and this stops applying. Restated rather than
 * shared because a :is() list here would lose to the [data-theme] block on
 * specificity in some engines. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --bg:        #f7f8f6;
    --surface:   #ffffff;
    --surface-2: #f1f3f0;
    --surface-3: #e7eae6;
    --surface-4: #dae0db;
    --line:      #dfe4df;
    --line-hi:   #bcc6bd;
    --text:      #0d1410;
    --dim:       #4a564e;
    --faint:     #6d7a71;
    --acc:       #0a8f45;
    --acc-hi:    #067038;
    --acc-lo:    #34c77d;
    --acc-dk:    #8fdfb4;
    --acc-deep:  #d7f3e2;
    --on-acc:    #ffffff;
    --red:       #b3261e;
    --amber:     #8a6100;
    --tint:      rgba(10, 143, 69, .09);
    --tint-soft: rgba(10, 143, 69, .05);
    --tint-line: rgba(10, 143, 69, .30);
    --ring:      rgba(10, 143, 69, .24);
    --tint-bad:  rgba(179, 38, 30, .09);
    --ring-bad:  rgba(179, 38, 30, .22);
    --tint-warn: rgba(138, 97, 0, .10);
    --bar-bg:    rgba(255, 255, 255, .78);
    --veil:      rgba(20, 28, 22, .38);
    --sh-1: 0 1px 2px rgba(16, 24, 19, .07);
    --sh-2: 0 6px 20px -6px rgba(16, 24, 19, .13);
    --sh-3: 0 22px 60px -16px rgba(16, 24, 19, .18);
    --glow: 0 0 0 1px rgba(10, 143, 69, .20), 0 10px 30px -12px rgba(10, 143, 69, .30);
  }
}

/* ---- base --------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

/* `hidden` is a user-agent rule, so ANY author `display` beats it outright,
 * whatever the specificity. Four components found that out separately: a
 * .btn, a .combo-pop, a .panel and a .modal-veil each set the attribute,
 * changed nothing on screen, and each got its own one-line repair. The fifth
 * was the launch form's .drop, which painted a "choose an image" button that
 * was deliberately not wired to anything, so clicking it did nothing at all.
 *
 * One rule instead of six, and the next component gets it for free.
 * `!important` is doing real work here rather than papering over a cascade
 * problem: the whole point is that nothing should out-rank hiding. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 88px;   /* clears the sticky bar on anchor jumps */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.6 var(--sans);
  font-feature-settings: "cv11", "ss01";   /* single-storey a, disambiguated 1/l */
  letter-spacing: -.005em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-wrap: break-word;
}

/* The one piece of texture, and a nod to the grain in the logo: a pair of very
 * faint green washes at the top of the page, so the black is not a flat void
 * behind the hero. Fixed, so it does not travel with the scroll. */
body::before {
  content: "";
  position: fixed;
  inset: 0 0 auto 0;
  height: 620px;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(900px 420px at 18% -8%, rgba(60, 255, 128, .075), transparent 70%),
    radial-gradient(700px 360px at 86% -14%, rgba(24, 168, 82, .055), transparent 72%);
}
:root[data-theme="light"] body::before { opacity: .55; }

img, svg { max-width: 100%; height: auto; vertical-align: middle; }

a {
  color: var(--acc);
  text-decoration-color: color-mix(in srgb, var(--acc) 40%, transparent);
  text-underline-offset: 3px;
  transition: color var(--t-fast) var(--ease);
}
a:hover { color: var(--acc-hi); text-decoration-color: currentColor; }

/* One focus treatment for the whole page. Keyboard only, so a mouse click on a
 * button does not leave a ring behind it. */
:focus-visible {
  outline: 2px solid var(--acc);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

::selection { background: var(--acc); color: var(--on-acc); }

/* Numbers, addresses, selectors and hex, everywhere they appear. */
code, kbd, samp, pre, .mono, .addr, .ca, .num b, .v, .k, .ticker {
  font-family: var(--mono);
  font-variant-ligatures: none;
  font-feature-settings: "zero" 1;   /* slashed zero, so 0 is never O */
}

/* ---- layout ------------------------------------------------------------- */

.shell {
  position: relative;
  z-index: 1;
  max-width: var(--w);
  margin: 0 auto;
  padding: 0 24px 96px;
}

.sec { padding: 56px 0; }
.sec + .sec { border-top: 1px solid var(--line); }

h1, h2, h3, h4 {
  margin: 0 0 .5em;
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -.028em;
  text-wrap: balance;
}
h1 { font-size: clamp(2.3rem, 5.4vw, 3.7rem); font-weight: 650; letter-spacing: -.035em; }
h2 { font-size: clamp(1.7rem, 3.4vw, 2.4rem); }
h3 { font-size: 1.24rem; letter-spacing: -.02em; }
h4 { font-size: 1.02rem; letter-spacing: -.012em; }

p { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }

/* The small upper-case label above a heading. Wide tracking is what stops it
 * reading as shouted body copy. */
.eyebrow {
  margin: 0 0 14px;
  font: 500 11.5px/1 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--acc);
}

.lead {
  max-width: var(--w-nar);
  font-size: 1.1rem;
  line-height: 1.66;
  color: var(--dim);
}
.lead b, .lead strong { color: var(--text); font-weight: 560; }

.note, .hint, .fine, .fineprint, .tabnote, .small, .sm {
  font-size: .855rem;
  line-height: 1.55;
  color: var(--faint);
}
.note { margin: 12px 0 0; }
.dim { color: var(--dim); }
.faint { color: var(--faint); }
.hide-sm { display: none; }

/* ---- the bar ------------------------------------------------------------
 * Sticky and blurred, so content passes under it rather than being covered by
 * a solid block. The border only appears once the page has scrolled, which
 * layout.js toggles with .pinned.
 */
.bar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  min-height: 62px;
  margin: 0 -24px;
  padding: 10px 24px;
  background: var(--bar-bg);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  border-bottom: 1px solid transparent;
  transition: border-color var(--t) var(--ease), background var(--t) var(--ease);
}
.bar.pinned { border-bottom-color: var(--line); }

.bar-left, .bar-right { display: flex; align-items: center; gap: 8px; }
/* The nav takes the slack so the mark sits left and the wallet sits right,
   which is what justify-content did before the wallet became a sibling. */
.bar-right { margin-left: auto; min-width: 0; }
.bar > .w-btn { flex: none; }
.bar-left {
  gap: 11px;
  color: var(--text);
  text-decoration: none;
  border-radius: var(--r-sm);
}
.bar-left:hover { color: var(--text); }

/* The mark is the <img> itself rather than a child of a wrapper, so this has
   to be img.logo. As `.logo img` it matched nothing and the full 1024px
   artwork painted at its natural size across the top of every page. */
img.logo, img.xlogo {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  transition: transform var(--t) var(--spring), filter var(--t) var(--ease);
}
.bar-left:hover img.logo {
  transform: rotate(-6deg) scale(1.08);
  filter: drop-shadow(0 0 10px var(--tint-line));
}

/* The wordmark. One line now: the chain name and id used to sit under it in a
   second, smaller line, which is why this was a stacking column and why the
   mark itself was only 13.5px -- it was sized to leave room. Alone it can be
   a mark, so it is a little larger and tracked out slightly. */
.bar-left .id { display: flex; min-width: 0; }
.bar-left .ticker {
  font: 600 15px/1 var(--mono);
  letter-spacing: .02em;
  color: var(--text);
}

/* Nav links in the bar are ghost buttons, so they need to be smaller than a
   real one or the bar becomes a row of equally loud pills. */
.bar-right .btn { padding: 8px 15px; font-size: .9rem; }

/* Nav links are quiet until hovered, and the current page is the only green
   one, so where you are is never ambiguous. */
.bar a:not(.logo):not(.btn) {
  padding: 7px 11px;
  border-radius: var(--r-sm);
  font-size: .915rem;
  color: var(--dim);
  text-decoration: none;
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.bar a:not(.logo):not(.btn):hover { color: var(--text); background: var(--surface-2); }
.bar a.on { color: var(--acc); background: var(--tint); }

/* Carries the words "light mode" / "dark mode" rather than an icon, so it is
   a pill sized to its text and not a square. */
.theme-btn {
  padding: 6px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface-2);
  color: var(--dim);
  font: 500 .82rem/1.4 var(--sans);
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.theme-btn:hover { color: var(--acc); border-color: var(--tint-line); background: var(--surface-3); }
.theme-btn:active { transform: scale(.96); }

/* ---- buttons -----------------------------------------------------------
 * A pill, a fill, and a lift on hover. The primary carries the only glow on
 * the page besides focus, which is what makes it obviously the thing to press.
 */
.btn {
  --btn-bg: var(--acc);
  --btn-fg: var(--on-acc);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 20px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font: 550 .945rem/1 var(--sans);
  letter-spacing: -.008em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t) var(--ease),
              background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease), opacity var(--t-fast) var(--ease);
}
/* Background and glow only, no lift.
 *
 * A button that rises under the cursor competes with the cards, which do
 * rise, and the two movements at slightly different amounts read as jitter
 * rather than as depth. Cards move; controls change colour. The press is
 * still felt, through the scale on :active. */
.btn:hover { background: var(--acc-hi); box-shadow: var(--glow); color: var(--btn-fg); }
.btn:active { transform: scale(.985); box-shadow: none; }

.btn.big { padding: 14px 26px; font-size: 1.01rem; }

/* Secondary: the same shape, no fill. Reads as available without competing. */
.btn.ghost, .btn.secondary {
  --btn-bg: transparent;
  --btn-fg: var(--text);
  border-color: var(--line-hi);
}
.btn.ghost:hover, .btn.secondary:hover {
  background: var(--surface-2);
  border-color: var(--acc);
  color: var(--acc);
  box-shadow: none;
}
.btn.primary { --btn-bg: var(--acc); --btn-fg: var(--on-acc); }

.btn[disabled], .btn.off, .btn[aria-disabled="true"] {
  opacity: .42;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}
.btn[disabled]:hover { background: var(--btn-bg); transform: none; box-shadow: none; }

/* A button that reads as a link, for inline "jump to the advanced tab". */
.linkish {
  padding: 0;
  border: 0;
  background: none;
  color: var(--acc);
  font: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.linkish:hover { color: var(--acc-hi); }

/* In-flight. The sweep is the only spinner on the site. */
.btn.busy, .busy { position: relative; pointer-events: none; opacity: .8; }
.btn.busy::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, .22) 50%, transparent 80%);
  background-size: 220% 100%;
  animation: sweep 1.15s linear infinite;
}
@keyframes sweep { from { background-position: 180% 0; } to { background-position: -80% 0; } }

.cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 26px 0 0;
}

/* ---- cards and panels --------------------------------------------------- */

.card, .callout, .facts, .preview, .lcard, .panel-foot, .sched, .tablewrap,
.field.grouped, .stat, .steps li {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  /* Carries the lit top edge described at --sh-1. Without a shadow declared
     there is nowhere for that inner line to live, and every card on a black
     page sits perfectly flat. */
  box-shadow: var(--sh-1);
}
.card, .callout, .facts, .sched { padding: 20px 22px; }

/* Anything clickable that is a card lifts and warms its border. One rule, so
   every card on the site behaves identically under the cursor. */
.lcard, .xrow, .card.linked {
  transition: transform var(--t) var(--spring), border-color var(--t) var(--ease),
              box-shadow var(--t) var(--ease), background var(--t) var(--ease);
}
.lcard:hover, .xrow:hover, .card.linked:hover {
  transform: translateY(-3px);
  border-color: var(--tint-line);
  box-shadow: var(--sh-2);
  background: var(--surface-2);
}

.callout {
  border-left: 2px solid var(--acc);
  background: var(--tint-soft);
}
.callout.warn { border-left-color: var(--amber); background: var(--tint-warn); }
.callout.bad  { border-left-color: var(--red);   background: var(--tint-bad); }

.warn { color: var(--amber); }
.bad, .err:not(:empty) { color: var(--red); }
.ok   { color: var(--acc); }

/* ---- hero --------------------------------------------------------------- */

.hero { padding: 72px 0 64px; }
.hero h1 { max-width: 19ch; }
.hero .lead { font-size: 1.16rem; }

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin: 34px 0 0;
}
.stats.one { grid-template-columns: minmax(180px, 240px); }
.stats.three { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

.stat {
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  transition: border-color var(--t) var(--ease), background var(--t) var(--ease);
}
.stat:hover { border-color: var(--tint-line); background: var(--surface-2); }
.stat .k {
  display: block;
  margin-bottom: 7px;
  font: 500 10.5px/1 var(--mono);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--faint);
}
.stat .v {
  display: block;
  font: 600 1.85rem/1 var(--mono);
  letter-spacing: -.02em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
/* util.js adds this when a figure changes, so a refreshed number is noticed. */
.v.bump { animation: bump var(--t-slow) var(--spring); }
@keyframes bump {
  0%   { transform: translateY(5px); opacity: .35; color: var(--acc); }
  100% { transform: none; opacity: 1; }
}

/* The three numbered steps. Counters are pills so they echo the buttons. */
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px;
  margin: 40px 0 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}
.steps li {
  display: flex;
  gap: 14px;
  padding: 20px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  transition: transform var(--t) var(--spring), border-color var(--t) var(--ease),
              background var(--t) var(--ease);
}
.steps li:hover { transform: translateY(-3px); border-color: var(--tint-line); background: var(--surface-2); }
.steps .pc {
  flex: none;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: var(--r-pill);
  background: var(--tint);
  color: var(--acc);
  font: 600 12px/1 var(--mono);
}
.steps b { display: block; margin-bottom: 5px; font-weight: 560; letter-spacing: -.012em; }
.steps p { margin: 0; font-size: .89rem; color: var(--faint); }

/* ---- forms -------------------------------------------------------------
 * Controls are large, softly rounded and sit a step above the page, so the
 * form reads as a stack of surfaces rather than a list of outlines. Focus
 * lifts the surface, warms the border and draws the ring in one move.
 */
.launch-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 26px;
  align-items: start;
  margin-top: 30px;
}

.lf { min-width: 0; }

.field { margin: 0 0 20px; }
.field:last-child { margin-bottom: 0; }

/* A bordered box around a control that owns several inputs, so "the tax and
   where it goes" reads as one decision rather than five stray fields. */
.field.grouped {
  padding: 20px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.field.grouped + .field.grouped { margin-top: 16px; }

label, .label, .slabel {
  display: block;
  margin: 0 0 8px;
  font: 550 .875rem/1.3 var(--sans);
  letter-spacing: -.006em;
  color: var(--text);
}
.slabel, .side-cap {
  font: 500 10.5px/1 var(--mono);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--faint);
}
.field .hint { margin: -2px 0 10px; }
.field .hint:last-child { margin-bottom: 0; }

/* Matched by exclusion rather than by listing the text-like types.
 *
 * Enumerating them looked tidier and quietly broke two controls: the derived
 * liquidity and cut boxes are written `<input value="1" disabled readonly>`
 * with no type attribute at all. An input with no type behaves as text, but
 * `[type="text"]` tests the attribute, not the resolved behaviour, so neither
 * matched and both fell back to the browser default: Arial at 13px in a 17px
 * tall box, wedged between two properly styled fields.
 *
 * `:not()` takes a selector list, whose specificity is that of its most
 * specific argument, so this stays at the same weight the enumeration had and
 * the .numbox overrides further down still win. */
input:not([type="file"], [type="checkbox"], [type="radio"], [type="hidden"],
          [type="range"], [type="submit"], [type="button"], [type="reset"],
          [type="image"], [type="color"]),
textarea, select {
  width: 100%;
  padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  color: var(--text);
  font: 400 .97rem/1.45 var(--sans);
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease);
  appearance: none;
}
input[inputmode="decimal"], input[inputmode="numeric"], input[type="number"],
#f-creator-addr, #f-logo-url {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
textarea { min-height: 84px; resize: vertical; line-height: 1.55; }

input::placeholder, textarea::placeholder { color: var(--faint); opacity: .75; }

input:hover, textarea:hover, select:hover { border-color: var(--line-hi); }
input:focus, textarea:focus, select:focus {
  outline: none;
  background: var(--surface);
  border-color: var(--acc);
  box-shadow: 0 0 0 3px var(--ring);
}
input[disabled], input[readonly], .numbox input[disabled] {
  background: var(--surface);
  color: var(--faint);
  cursor: default;
}

/* An invalid control is washed as well as ringed: colour alone on a thin
   border is easy to miss on a dark ground. */
input.bad, textarea.bad, select.bad, .numbox.bad, .combo-btn.bad {
  border-color: var(--red);
  background: var(--tint-bad);
}
input.bad:focus, textarea.bad:focus, .combo-btn.bad:focus { box-shadow: 0 0 0 3px var(--ring-bad); }

.err { margin: 6px 0 0; font-size: .845rem; color: var(--red); min-height: 0; }
.err:empty { display: none; }

.row2, .row3, .halves {
  display: grid;
  gap: 14px;
}
.row2, .halves { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.row3 { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.socials { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* A number with its unit inside the box, so the unit cannot be mistaken for
   part of the value and the caret never lands on it. */
.numbox, .inline-unit {
  position: relative;
  display: flex;
  align-items: center;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease);
}
.numbox:focus-within, .inline-unit:focus-within {
  background: var(--surface);
  border-color: var(--acc);
  box-shadow: 0 0 0 3px var(--ring);
}
/* A numbox only ever holds a number, so the face and the tabular figures are
   set here rather than per id. The derived liquidity and cut boxes have no
   type and no inputmode, so any rule keyed on those missed them and they sat
   in the sans next to four mono siblings. */
.numbox input, .inline-unit input {
  border: 0;
  background: none;
  box-shadow: none;
  border-radius: inherit;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
.numbox input:focus, .inline-unit input:focus { box-shadow: none; background: none; }
/* Disabled inside a numbox keeps the box's own fill: the wrapper is already
   drawing the surface, and a second one on top of it reads as a broken
   control rather than a read-only one. Being derived is said by the colour. */
.numbox input[disabled], .numbox input[readonly],
.inline-unit input[disabled], .inline-unit input[readonly] {
  background: none;
  color: var(--faint);
}
.numbox i, .inline-unit .unit, .unit {
  flex: none;
  padding: 0 14px 0 6px;
  font: 500 .875rem/1 var(--mono);
  font-style: normal;
  color: var(--faint);
  user-select: none;
}
/* Native spinners are tiny, ugly and inconsistent between engines. */
.numbox input::-webkit-outer-spin-button,
.numbox input::-webkit-inner-spin-button { appearance: none; margin: 0; }
.numbox input[type="number"] { appearance: textfield; -moz-appearance: textfield; }

/* ---- preset chips ------------------------------------------------------
 * The tax has twenty legal values and nothing between them, so chips rather
 * than a slider: a slider cannot land on one reliably and hides which exist.
 */
.presets {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin: 0 0 12px;
}
.preset {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--dim);
  font: 500 .875rem/1.25 var(--mono);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease),
              box-shadow var(--t) var(--ease);
}
.preset:hover { color: var(--text); border-color: var(--line-hi); background: var(--surface-3); transform: translateY(-1px); }
.preset:active { transform: scale(.96); }
.preset.on {
  background: var(--acc);
  border-color: var(--acc);
  color: var(--on-acc);
  box-shadow: var(--glow);
}
.preset.on:hover { background: var(--acc-hi); border-color: var(--acc-hi); }

/* A preset that cannot be reached from the current state, such as a 1% creator
   fee on a 1% launch where the whole share is 0.67%. */
.preset[disabled] {
  opacity: .34;
  cursor: not-allowed;
  transform: none;
}
.preset[disabled]:hover { background: var(--surface-2); border-color: var(--line); color: var(--dim); }

/* The secondary line some presets carry ("split evenly", "620 blocks"). It is
   a second text node inside the button, so without this it ran straight on
   from the label: "holders + liquiditysplit evenly". */
.preset .sm {
  font-family: var(--sans);
  font-size: .78rem;
  font-weight: 400;
  color: var(--faint);
  transition: color var(--t-fast) var(--ease);
}
.preset.on .sm { color: color-mix(in srgb, var(--on-acc) 68%, transparent); }

/* The split presets describe a whole arrangement rather than a value, so they
   are full-width rows with the label left and the description right, instead
   of pills sized to their text. */
.presets .preset.wide {
  width: 100%;
  justify-content: space-between;
  padding: 11px 17px;
  border-radius: var(--r);
  text-align: left;
}
.presets .preset.wide .sm { text-align: right; }

/* The reward type is a choice between two whole launchpads rather than
   between two values, so each option is a half-width card with its label
   above what it means. Stacked full-width rows read as a list of things to do
   next; pills sized to their text read as a setting. Two cards side by side
   read as a fork, which is what this is.

   They wrap to full width when the column is too narrow to halve, which is
   why min-width is set rather than a flex-basis percentage. */
.presets.pick2 { gap: 9px; }
.presets.pick2 .preset {
  flex: 1 1 0;
  min-width: 190px;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  padding: 12px 15px;
  border-radius: var(--r);
  text-align: left;
}

.custom-row {
  display: flex;
  align-items: center;
  gap: 11px;
  margin: 0 0 4px;
}
.custom-row label {
  margin: 0;
  flex: none;
  font-size: .855rem;
  color: var(--faint);
}
.custom-row .numbox { width: 130px; }

/* ---- the asset picker -------------------------------------------------
 * Was a native <select>, which is the one control a page cannot style and
 * which looked, in the complaint that prompted this, like the most basic
 * thing possible. Now a button that opens a searchable sheet.
 */
.combo { position: relative; }

.combo-btn {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 11px 13px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  color: var(--text);
  font: 500 .97rem/1.3 var(--sans);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease);
}
.combo-btn:hover { border-color: var(--line-hi); background: var(--surface-3); }
.combo-btn[aria-expanded="true"] {
  border-color: var(--acc);
  background: var(--surface);
  box-shadow: 0 0 0 3px var(--ring);
}
.combo-btn .chev {
  margin-left: auto;
  flex: none;
  color: var(--faint);
  transition: transform var(--t) var(--spring);
}
.combo-btn[aria-expanded="true"] .chev { transform: rotate(180deg); color: var(--acc); }

/* The round token mark. Stock tickers have no icon art, so the mark is the
   first character over a tinted disc, which is legible at 26px where a
   downscaled logo would not be. */
.tokmark {
  flex: none;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-pill);
  background: var(--surface-4);
  border: 1px solid var(--line-hi);
  color: var(--text);
  font: 600 11px/1 var(--mono);
  letter-spacing: 0;
  overflow: hidden;
}
.tokmark img { width: 100%; height: 100%; object-fit: cover; }
.tokmark.eth { background: var(--acc-deep); border-color: var(--tint-line); color: var(--acc); }

.combo-btn .tsym { font-weight: 560; letter-spacing: -.01em; }
.combo-btn .tname { color: var(--faint); font-size: .85rem; font-weight: 400; }

/* The sheet. Anchored under the button on a wide screen, and a centred sheet
   on a narrow one, which is handled in the media query at the end. */
.combo-pop {
  position: absolute;
  z-index: 60;
  top: calc(100% + 7px);
  left: 0;
  right: 0;
  padding: 9px;
  background: var(--surface);
  border: 1px solid var(--line-hi);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-3);
  transform-origin: top center;
  animation: pop var(--t) var(--spring);
}
@keyframes pop {
  from { opacity: 0; transform: translateY(-7px) scale(.98); }
  to   { opacity: 1; transform: none; }
}
.combo-search {
  margin: 0 0 8px;
  padding: 10px 12px;
  font-size: .93rem;
  border-radius: var(--r-sm);
}

.combo-list {
  /* Deliberately not a round number: it cuts the last visible row in half,
     which is what tells you the list scrolls without needing a scrollbar. */
  max-height: 282px;
  overflow-y: auto;
  /* Reaching the end of this list must not start scrolling the form behind
     it. Without this, flicking through seventeen assets throws the page. */
  overscroll-behavior: contain;
  margin: 0;
  padding: 0;
  list-style: none;
  scrollbar-width: thin;
  scrollbar-color: var(--surface-4) transparent;
}
.combo-list::-webkit-scrollbar { width: 9px; }
.combo-list::-webkit-scrollbar-thumb { background: var(--surface-4); border-radius: var(--r-pill); }

.combo-group {
  padding: 10px 10px 5px;
  font: 500 10px/1 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--faint);
}

.combo-opt {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 9px 10px;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--text);
  font: 400 .95rem/1.3 var(--sans);
  text-align: left;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease);
}
.combo-opt .tsym { font-weight: 550; letter-spacing: -.01em; }
.combo-opt .tname { color: var(--faint); font-size: .85rem; }
.combo-opt .tick { margin-left: auto; color: var(--acc); opacity: 0; transition: opacity var(--t-fast) var(--ease); }
.combo-opt:hover, .combo-opt.cursor { background: var(--surface-2); }
.combo-opt[aria-selected="true"] { background: var(--tint); }
.combo-opt[aria-selected="true"] .tick { opacity: 1; }

/* An asset the chain cannot currently pay rewards in. Dimmed and inert, but
 * still listed and still legible: somebody looking for NVDA needs to find out
 * that it is unavailable, not fail to find it. The note carries the reason so
 * the row explains itself without a tooltip. */
.combo-opt.off { cursor: not-allowed; opacity: .45; }
.combo-opt.off:hover, .combo-opt.off.cursor { background: none; }
.combo-opt .tnote {
  margin-left: auto;
  padding: 2px 7px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--faint);
  font-size: .75rem;
  white-space: nowrap;
}
.combo-empty { padding: 20px 10px; text-align: center; color: var(--faint); font-size: .89rem; }

/* ---- tabs --------------------------------------------------------------
 * A segmented control on its own surface, which is what makes the selected
 * tab read as raised rather than merely coloured.
 */
.tabs {
  display: inline-flex;
  gap: 3px;
  margin: 0 0 22px;
  padding: 4px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
}
.tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 18px;
  border: 0;
  border-radius: var(--r-pill);
  background: none;
  color: var(--dim);
  font: 500 .925rem/1 var(--sans);
  letter-spacing: -.008em;
  cursor: pointer;
  transition: background var(--t) var(--ease), color var(--t) var(--ease),
              box-shadow var(--t) var(--ease);
}
.tab:hover { color: var(--text); }
.tab.on {
  background: var(--surface-4);
  color: var(--text);
  box-shadow: var(--sh-1);
}
.tabnote {
  padding: 3px 7px;
  border-radius: var(--r-pill);
  background: var(--tint);
  color: var(--acc);
  font: 500 9.5px/1 var(--mono);
  letter-spacing: .09em;
  text-transform: uppercase;
}

/* Switching tabs fades the incoming panel in. Short, because a panel that
   takes its time feels slow rather than smooth. */
.panel { animation: fade var(--t-slow) var(--ease); }
@keyframes fade { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }

.panel-foot {
  margin-top: 20px;
  padding: 14px 16px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
}

/* ---- the fee readout ---------------------------------------------------
 * One hue, three depths. These were three unrelated colours, which implied
 * three unrelated kinds of thing; they are three slices of one number, so
 * they are three weights of the accent and the eye reads them as a set.
 */
.fee-read {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  gap: 9px;
  margin: 14px 0 10px;
}
.fr {
  padding: 13px 15px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  transition: border-color var(--t) var(--ease), background var(--t) var(--ease);
}
.fr:hover { border-color: var(--line-hi); }
.fr span {
  display: block;
  margin-bottom: 6px;
  font: 500 10px/1.3 var(--mono);
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--faint);
}
.fr b {
  font: 600 1.42rem/1 var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
  color: var(--text);
}
/* Three figures, two roles.
 *
 * What a trader pays is the total and the other two are parts of it, so the
 * total is the only one that gets the accent and a tinted ground. The cut
 * and your share are peers: they must look identical to each other, because
 * a different colour is a claim that they differ in kind, and they do not.
 * The previous pass gave all three their own hue (accent, grey, mid-green),
 * which read as three unrelated categories rather than a total and its
 * parts. */
.fr.big { background: var(--tint); border-color: var(--tint-line); }
.fr.big b { color: var(--acc); }
.fr.cut b,
.fr.share b { color: var(--text); }

.split-nums {
  display: grid;
  gap: 11px;
  margin: 4px 0 12px;
}
.split-nums.four { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); }
.num { display: block; }
.num > span:first-child {
  display: block;
  margin-bottom: 7px;
  font-size: .845rem;
  color: var(--faint);
}
.num.fixed .numbox, .num.fixed input { color: var(--faint); }

/* ---- the split bar ----------------------------------------------------
 * The whole bar is the tax a trader pays, so the four legs are proportions of
 * the total and the cut visibly shrinks as the total rises.
 *
 * Also one hue, four depths, for the same reason as the readout above: these
 * are four slices of one tax, not four different subjects. Order runs bright
 * to dark so the legend reads top to bottom as the bar reads left to right.
 */
.pbar-cap {
  margin: 20px 0 8px;
  font: 500 10.5px/1 var(--mono);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--faint);
}
.pbar {
  display: flex;
  height: 13px;
  border-radius: var(--r-pill);
  overflow: hidden;
  background: var(--surface-3);
  box-shadow: inset 0 0 0 1px var(--line);
}
.pbar span {
  display: block;
  min-width: 0;
  /* Width is set from JS, so the CSP keeps style-src at 'self'.
     Deliberately slower than everything else on the page: a bar that fills
     lazily reads as a quantity being poured, where one that snaps reads as a
     number being replaced. */
  transition: width var(--t-fill) var(--spring);
}

/* Four steps down one hue, with the luminance gaps wide enough to survive a
   13px bar. The first pass used --acc-deep for the creator leg, which is
   #0c3f21: legible as a border, invisible as a 13px segment on black and
   indistinguishable from the grey next to it. These are spaced by lightness
   rather than by name. */
.pbar-r { background: var(--acc); }
.pbar-l { background: var(--acc-lo); }
.pbar-c { background: var(--acc-dk); }
.pbar-p { background: var(--surface-4); box-shadow: inset 0 0 0 1px var(--line-hi); }

.plegend {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 7px 16px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
  font-size: .875rem;
  color: var(--dim);
}
.plegend li { display: flex; align-items: center; gap: 8px; }
.plegend b {
  margin-left: auto;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  font-weight: 550;
}
.sw {
  flex: none;
  width: 11px;
  height: 11px;
  border-radius: 4px;
  background: var(--surface-4);
}
.sw.r { background: var(--acc); }
.sw.l { background: var(--acc-lo); }
.sw.c { background: var(--acc-dk); }
.sw.p { background: var(--surface-4); box-shadow: inset 0 0 0 1px var(--line-hi); }

/* ---- the logo control -------------------------------------------------- */

.logo-ctl {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}
.logo-prev {
  display: grid;
  place-items: center;
  width: 96px;
  height: 96px;
  overflow: hidden;
  background: var(--surface-2);
  border: 1px dashed var(--line-hi);
  border-radius: var(--r);
  transition: border-color var(--t) var(--ease);
}
.logo-prev img { width: 100%; height: 100%; object-fit: cover; }
.logo-prev.has { border-style: solid; border-color: var(--tint-line); }
.logo-prev .ph { font-size: .78rem; color: var(--faint); text-align: center; padding: 0 8px; }

.drop {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 16px;
  background: var(--surface-2);
  border: 1px dashed var(--line-hi);
  border-radius: var(--r);
  transition: border-color var(--t) var(--ease), background var(--t) var(--ease);
}
.drop.over { border-color: var(--acc); background: var(--tint); }
.drop input[type="file"] { display: none; }
.drop .or { margin: 0; font-size: .855rem; color: var(--faint); }
.logo-url { margin-top: 10px; }
.logo-state { margin: 7px 0 0; font-size: .83rem; color: var(--faint); }
.logo-state.ok { color: var(--acc); }
.logo-state.bad { color: var(--red); }
.logo-state.pending { color: var(--amber); }

/* ---- submit and status ------------------------------------------------- */

.submit {
  display: flex;
  flex-wrap: wrap;
  gap: 11px;
  margin: 26px 0 0;
  padding-top: 22px;
  border-top: 1px solid var(--line);
}

.status { margin: 16px 0 0; }
.status:empty { display: none; }
.status > :not(.btn) {
  padding: 14px 16px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-left: 2px solid var(--acc);
  border-radius: var(--r);
  font-size: .91rem;
}
.status .bad { border-left-color: var(--red); background: var(--tint-bad); }
.status .ok  { border-left-color: var(--acc); background: var(--tint-soft); }

/* ---- the preview rail -------------------------------------------------- */

.preview {
  position: sticky;
  top: 82px;
  padding: 22px;
}
.psent {
  margin: 0 0 8px;
  font-size: 1.04rem;
  line-height: 1.5;
  font-weight: 500;
  letter-spacing: -.014em;
}
.psent b { color: var(--acc); font-weight: 600; }
.ppair { margin: 0; font-size: .89rem; color: var(--faint); }

/* The raw encoding, folded away. Open it and you get exactly what goes on
   chain; closed, it stops basis points competing with the coin's name. */
.exact {
  margin: 16px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.exact > summary {
  font: 500 10.5px/1 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faint);
  cursor: pointer;
  list-style: none;
  transition: color var(--t-fast) var(--ease);
}
.exact > summary::-webkit-details-marker { display: none; }
.exact > summary::before {
  content: "+ ";
  color: var(--acc);
}
.exact[open] > summary::before { content: "\2212 "; }
.exact > summary:hover { color: var(--text); }
.exact .kv { margin-top: 14px; }
.exact .kv dd { font-size: .84rem; }

/* ---- key/value lists --------------------------------------------------- */

.kv { margin: 18px 0 0; }
.kv dt {
  font: 500 10.5px/1 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faint);
}
.kv dd {
  margin: 5px 0 14px;
  font-family: var(--mono);
  font-size: .91rem;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  /* `anywhere` rather than break-all: a 42-character address still wraps in a
     narrow column, but a word that fits is left whole. With break-all the split
     line broke mid-word on a phone, reading "no c / ut, genesis launch". */
  overflow-wrap: anywhere;
}
.kv dd:last-child { margin-bottom: 0; }
.kv.tight dd { margin-bottom: 11px; }
/* Two columns once there is room, because these lists are long and narrow. */
.kv.halves, .kv.two {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 0 18px;
}

/* ---- docs -------------------------------------------------------------
 * A prose column with a sticky table of contents beside it. Prose is capped
 * near 70 characters because that is where long-form reading stops being
 * comfortable, whatever the window is doing.
 */
.docs-wrap {
  display: grid;
  grid-template-columns: 236px minmax(0, 1fr);
  gap: 40px;
  align-items: start;
  margin-top: 26px;
}
.docs-side { position: sticky; top: 82px; }
.side-cap { margin: 0 0 12px; }

/* The contents rail.
 *
 * `.docs-side` as well as `.toc`, because the markup is
 * `<nav class="docs-side"><ol>` and there is no `.toc` element anywhere: as
 * `.toc` alone every rule here matched nothing, the list kept its default
 * decimal markers, and each link fell through to the global `a` colour. That
 * painted all fourteen entries accent green, so the one marker meant to say
 * "you are here" was invisible among thirteen identical siblings. */
.toc, .docs-side ol {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: toc;
}
.toc li, .docs-side ol li { margin: 0 0 1px; }
.toc a, .docs-side ol a {
  display: block;
  padding: 7px 11px;
  border-radius: var(--r-sm);
  border-left: 2px solid transparent;
  font-size: .89rem;
  line-height: 1.4;
  color: var(--dim);
  text-decoration: none;
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease);
}
.toc a:hover, .docs-side ol a:hover { color: var(--text); background: var(--surface-2); }
.toc a.on, .docs-side ol a.on {
  color: var(--acc);
  background: var(--tint);
  border-left-color: var(--acc);
}
.toc .sub a, .docs-side ol .sub a { padding-left: 22px; font-size: .845rem; }

/* The one-line summary under a section heading. */
.doc > .sub {
  display: block;
  margin: -.25em 0 1.2em;
  max-width: 60ch;
  font-size: .95rem;
  line-height: 1.5;
  color: var(--faint);
}

.docs-body { min-width: 0; max-width: 72ch; }
.doc { padding: 34px 0; }
.doc:first-child { padding-top: 0; }
.doc + .doc { border-top: 1px solid var(--line); }
.doc h2 { margin-bottom: .55em; }
.doc h3 { margin: 1.9em 0 .5em; }
.doc p, .doc li { color: var(--dim); }
.doc > p:first-of-type { font-size: 1.06rem; color: var(--text); }
.doc ul, .doc ol { margin: 0 0 1rem; padding-left: 1.3em; }
.doc li { margin: 0 0 .45em; }
.doc li::marker { color: var(--acc); }
.doc strong, .doc b { color: var(--text); font-weight: 560; }

.code, pre {
  margin: 0 0 1rem;
  padding: 15px 17px;
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  font-size: .855rem;
  line-height: 1.6;
  color: var(--dim);
}
:not(pre) > code {
  padding: 2px 6px;
  background: var(--surface-3);
  border-radius: var(--r-xs);
  font-size: .89em;
  color: var(--text);
}

/* ---- tables ------------------------------------------------------------ */

/* Used by the docs, the token page, analytics and profile, so these live on
   their own rather than under any one page's heading. */
.tablewrap { overflow-x: auto; margin: 0 0 1rem; }
table { width: 100%; border-collapse: collapse; font-size: .9rem; }
th, td {
  padding: 11px 14px;
  text-align: left;
  border-bottom: 1px solid var(--line);
}
th {
  font: 500 10.5px/1 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faint);
  white-space: nowrap;
}
td { color: var(--dim); }
/* A numeric cell. Deliberately not called .num: that is a launch-form class
   with display:block on it, and putting it on a <td> turns the cell into a
   block box, which quietly unpicks the row into a vertical stack of values
   under the first column. It renders without erroring and looks like a table
   that has come apart. */
td.figure {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
td:first-child { color: var(--text); font-weight: 500; }
tr:last-child td { border-bottom: 0; }
tbody tr { transition: background var(--t-fast) var(--ease); }
tbody tr:hover { background: var(--surface-2); }
.odd { background: var(--surface-2); }

.facts { margin: 0 0 1rem; }
.facts dt { color: var(--text); font-weight: 550; margin-top: 12px; }
.facts dt:first-child { margin-top: 0; }
.facts dd { margin: 4px 0 0; color: var(--dim); font-size: .92rem; }

.sched { margin: 0 0 1rem; }

/* ---- explore ----------------------------------------------------------- */

.xbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin: 0 0 22px;
}
.xbar .count { font-family: var(--mono); font-size: .875rem; color: var(--faint); }
/* Pushes the count and the launch button to the right of the search box, and
   collapses to a stack on a narrow screen without a media query. */
.xbar .xfilter { flex: 1 1 220px; min-width: 200px; }
.xbar .count { margin-left: auto; }

.lgrid {
  display: grid;
  /* The art is square and full width, so the column width sets how large the
     logos are. 200px gives five across a desktop and two across a phone. */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 12px;
}
.lcard {
  display: block;
  padding: 10px;
  color: inherit;
  text-decoration: none;
  /* Cards below the fold are not laid out until they are near the viewport.
     The intrinsic size keeps the scrollbar honest while they are skipped, so
     this costs nothing and stops a few hundred launches from being a slow
     first paint. Roughly the square art plus the two text rows: too small and
     the scrollbar jumps as you scroll. */
  content-visibility: auto;
  contain-intrinsic-size: auto 300px;
}
/* The whole tile is a link, so it needs the focus ring the buttons inside it
   used to carry. */
.lcard:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }

/* The art. Square whatever the image is, so a grid of cards is a grid and not
   a ragged column of different heights, and so a logo nobody set leaves the
   same hole as one that failed to load rather than collapsing the card. */
.xart {
  position: relative;
  aspect-ratio: 1;
  border-radius: 14px;
  overflow: hidden;
  background: var(--surface-3);
  border: 1px solid var(--line);
}
.lcard img.xlogo, .lcard .xlogo.ph {
  width: 100%;
  height: 100%;
  /* Logos are square by convention and rectangular in practice. Cover crops
     the odd one rather than letterboxing every card to fit it. */
  object-fit: cover;
  display: block;
}
.lcard .xlogo.ph {
  display: grid;
  place-items: center;
  font: 600 2.2rem/1 var(--mono);
  color: var(--faint);
}
.lcard:hover img.xlogo { transform: scale(1.03); }
.lcard img.xlogo { transition: transform var(--t) var(--ease); }

/* Both sit over the art, one per corner, on a scrim dark enough to stay
   readable over an image we have never seen. */
.xbadge, .lcard .rank {
  position: absolute;
  top: 8px;
  font: 500 .68rem/1 var(--mono);
  letter-spacing: .04em;
  padding: 5px 7px;
  border-radius: 999px;
  background: rgba(12, 16, 13, .72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: #eef3ee;
}
.xbadge { left: 8px; }
.lcard .rank { right: 8px; font-variant-numeric: tabular-nums; }

/* A name is one line. Left to wrap, a long one grows the card, which in a grid
   of cards reads as a mistake. */
.lcard .xname { min-width: 0; margin: 10px 2px 0; }
.lcard .xname b {
  display: block;
  font-size: .95rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* What it trades against and what it pays, then what it costs underneath. */
.xmeta {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin: 8px 2px 0;
  font: 500 .78rem/1.4 var(--mono);
  color: var(--dim);
  white-space: nowrap;
}
.xmeta .xarrow { color: var(--faint); }
.xmeta .xreward { color: var(--acc); }
.xmeta .xpair, .xmeta .xreward { overflow: hidden; text-overflow: ellipsis; }
.xmeta .xtax { margin-left: auto; padding-left: 8px; color: var(--faint); }

/* The market cap row. Reserved rather than added: it is filled in by a second
   round trip, and a card that grows a line under the cursor after the grid has
   settled is worse than one that was always this tall. */
.lcard .xval {
  display: flex;
  align-items: baseline;
  gap: 5px;
  min-height: 1.25rem;
  margin: 4px 2px 0;
  font: 500 .82rem/1.25 var(--mono);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
}
.lcard .xval b { font-weight: 600; }
.lcard .xval .k {
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .04em;
  color: var(--faint);
}
.tokhead { display: flex; align-items: center; gap: 12px; }
.xname { min-width: 0; font-weight: 560; letter-spacing: -.014em; }
.xname .sym, .ticker {
  display: block;
  font-family: var(--mono);
  font-size: .8rem;
  color: var(--faint);
  font-weight: 400;
}
.xtags, .llinks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 14px 0 0;
}
.tag, .badge {
  padding: 4px 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font: 500 .765rem/1.4 var(--mono);
  color: var(--dim);
}
.tag.hl, .badge.grad { background: var(--tint); border-color: var(--tint-line); color: var(--acc); }
.xfoot { margin: 14px 0 0; font-size: .82rem; color: var(--faint); }
.empty, .loading {
  padding: 56px 20px;
  text-align: center;
  color: var(--faint);
  border: 1px dashed var(--line);
  border-radius: var(--r-lg);
}

/* ---- analytics --------------------------------------------------------- */

/* A heading inside a section that already has an h2. Spaced rather than sized:
   h3 is already the right size, what it lacks is room above it when it follows
   a grid of cards. */
.sub-h { margin: 0 0 .5rem; }
.sub-h + .sub { margin-bottom: 1.1rem; }

/* A note under a figure. The figure says what, this says what it means, and
   without it a page of large numbers needs a paragraph above it instead. */
.stat .n {
  display: block;
  margin: 8px 0 0;
  font-size: .78rem;
  line-height: 1.45;
  color: var(--faint);
}

.acols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 28px;
  margin: 22px 0 0;
}
.abars h4 {
  margin: 0 0 12px;
  font: 500 10.5px/1 var(--mono);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--faint);
}
.abar {
  display: grid;
  /* Fixed first and last columns so the bars all start and end on the same
     two lines regardless of ticker length. A bar chart whose baseline moves
     per row is not a bar chart. Wide enough for ANTHROPICx1L, which is the
     longest symbol on the allow list by some margin and wrapped onto two
     lines at every width that fitted the equity tickers. */
  grid-template-columns: 7.5rem 1fr 2.5rem;
  align-items: center;
  gap: 10px;
  margin: 0 0 7px;
}
.abar-k {
  font: 500 .8rem/1.4 var(--mono);
  color: var(--dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.abar-v {
  font: 500 .8rem/1.4 var(--mono);
  color: var(--faint);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.abar-track {
  height: 8px;
  background: var(--surface-3);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.abar-fill {
  height: 100%;
  /* A count of one out of four hundred is a real answer and must still be
     visible, so the fill has a floor. */
  min-width: 3px;
  background: var(--acc);
  border-radius: var(--r-pill);
}

/* ---- profile ----------------------------------------------------------- */

/* Not .pbar. That is the launch form's split bar: 13 pixels tall with
   overflow:hidden, which clipped this row of 39px controls down to a green
   sliver that looked exactly like a broken gradient. */
.phead {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin: 28px 0 0;
}
.pwho {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.pwho .k {
  font: 500 10.5px/1 var(--mono);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--faint);
}
/* An address is 42 characters of hex and the only thing on the page that has
   to be readable character by character, so it wraps rather than ellipsing. */
.pwho .addr { font-size: .8rem; word-break: break-all; }

.prow-name { min-width: 0; }
.prow-name b { display: block; font-weight: 560; }
.prow-name .sym {
  display: block;
  font: 400 .76rem/1.4 var(--mono);
  color: var(--faint);
}
.pact {
  display: flex;
  gap: 6px;
  justify-content: flex-end;
  white-space: nowrap;
}

/* ---- token page -------------------------------------------------------- */

.tokgrid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 26px;
  align-items: start;
  margin-top: 26px;
}
.tlogo {
  flex: none;
  width: 60px;
  height: 60px;
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.tlogo img { width: 100%; height: 100%; object-fit: cover; }
.tdesc { margin: 16px 0 0; color: var(--dim); }
.gradline { margin: 12px 0 0; font-size: .875rem; color: var(--faint); }

/* ---- footer ------------------------------------------------------------ */

.foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: 20px 32px;
  margin-top: 26px;
  padding: 26px 0 0;
  border-top: 1px solid var(--line);
  font-size: .875rem;
  color: var(--faint);
}
/* The four contract addresses. A four-row definition list ran the footer down
   the page, so they sit in a grid and each row is label-above-value. */
.foot .ca {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 12px 22px;
  margin: 0;
}
.foot .ca > div { min-width: 0; }
.foot .ca dt {
  margin: 0 0 3px;
  font: 500 9.5px/1 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faint);
}
.foot .ca dd { margin: 0; font-size: .82rem; }
.foot .ca .off { color: var(--line-hi); font-style: normal; }

.foot-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  justify-content: flex-end;
}
.foot-links a {
  padding: 5px 9px;
  border-radius: var(--r-sm);
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.foot-links a:hover { background: var(--surface-2); }
.foot-links a.on { color: var(--acc); }
.foot a { color: var(--dim); text-decoration: none; }
.foot a:hover { color: var(--acc); }
/* The closing disclaimer spans both columns. */
.foot > .note { grid-column: 1 / -1; margin: 6px 0 0; max-width: 78ch; }

@media (max-width: 680px) {
  .foot { grid-template-columns: minmax(0, 1fr); }
  .foot-links { justify-content: flex-start; }
}

/* ---- modal ------------------------------------------------------------
 * Used by the wallet picker. A veil that blurs the page behind it, and a
 * sheet that rises rather than appearing.
 */
.modal-veil {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: 20px;
  background: var(--veil);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: fade var(--t) var(--ease);
}
.modal {
  width: 100%;
  max-width: 408px;
  max-height: 86vh;
  overflow-y: auto;
  padding: 22px;
  background: var(--surface);
  border: 1px solid var(--line-hi);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-3);
  animation: rise var(--t-slow) var(--spring);
}
@keyframes rise {
  from { opacity: 0; transform: translateY(14px) scale(.975); }
  to   { opacity: 1; transform: none; }
}
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 0 0 16px;
}
.modal-head h3 { margin: 0; }
.modal-x {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--dim);
  cursor: pointer;
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
              transform var(--t-fast) var(--ease);
}
.modal-x:hover { color: var(--text); background: var(--surface-3); }
.modal-x:active { transform: scale(.93); }

/* One row per wallet. The icon comes from the wallet itself via EIP-6963, so
   it is the mark the user already recognises rather than one we drew. */
.wlist { display: grid; gap: 7px; }
.wopt {
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  padding: 13px 14px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  color: var(--text);
  font: 500 .97rem/1.3 var(--sans);
  text-align: left;
  cursor: pointer;
  transition: transform var(--t) var(--spring), background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease);
}
.wopt:hover { transform: translateX(3px); background: var(--surface-3); border-color: var(--tint-line); }
.wopt:active { transform: translateX(0) scale(.99); }
.wopt img, .wopt .wicon {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: var(--surface-4);
  display: grid;
  place-items: center;
  font: 600 12px/1 var(--mono);
  color: var(--dim);
  overflow: hidden;
}
.wopt .wmeta { min-width: 0; }
.wopt .wsub { display: block; font-size: .8rem; color: var(--faint); font-weight: 400; }
.wopt .wtag {
  margin-left: auto;
  flex: none;
  padding: 3px 8px;
  border-radius: var(--r-pill);
  background: var(--tint);
  color: var(--acc);
  font: 500 9.5px/1 var(--mono);
  letter-spacing: .09em;
  text-transform: uppercase;
}

/* ---- the locker -------------------------------------------------------
 * Two things /lock/ needs that no other page does: a checkbox, and a row that
 * opens under a table row to take a date.
 */

/* The site's first checkbox. The generic input rule deliberately skips
 * [type="checkbox"], so this styles the row around it rather than fighting
 * the native control, which is the one widget browsers already draw well and
 * which has keyboard and screen-reader behaviour worth keeping. */
.wcheck {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast);
}
.wcheck:hover { border-color: var(--line-hi); }
.wcheck input { width: 16px; height: 16px; accent-color: var(--acc); cursor: pointer; }
.wcheck span { font-size: 13px; }
.wcheck:has(input:checked) {
  border-color: var(--tint-line);
  background: var(--tint-soft);
}
.wcheck:has(input:focus-visible) { box-shadow: 0 0 0 3px var(--ring); }

/* One lock, on a coin's own page. A line rather than a table row: there are
 * usually one or two, and a two-row table with headings takes more of the
 * card than the figures in it. */
.lockline {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 7px 0;
  border-top: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
}
.lockline b { font: 500 13px/1.3 var(--mono); }

/* The date must not break. A rewards-too badge on the same line squeezes the
 * middle column enough that "2027-03-15" wraps after the month and reads as a
 * different, earlier date for as long as it takes to notice the 15 below it.
 * Let the line wrap between its parts instead. */
.lockline .sm { color: var(--dim); white-space: nowrap; }
.lockline { flex-wrap: wrap; }

/* Opens beneath the lock it belongs to, spanning the table, so the date being
 * typed is visibly attached to one row and not to the table. */
.krow-extend > td {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  background: var(--tint-soft);
  border-top: 1px dashed var(--line);
}
.krow-extend input { max-width: 190px; }
.krow-extend .sm { flex: 1 1 240px; color: var(--faint); }

/* ---- misc utilities ---------------------------------------------------- */

.g { color: var(--acc); }
.u { text-decoration: underline; text-underline-offset: 3px; }
.tight { margin-top: 10px; }
.wide { width: 100%; }
.half { max-width: 50%; }
.three { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.id, .leg, .rank, .totline, .wrow, .wcheck, .pinned { }
.addr, .ca {
  font-size: .875rem;
  color: var(--dim);
}
/* Only hex breaks mid-character. This used to be on .ca, which is the whole
   definition list, so the prose in it broke mid-word too: on a phone the split
   line read "no c / ut, genesis launch". */
.addr { word-break: break-all; }
.grad { color: var(--acc); }
.count { font-variant-numeric: tabular-nums; }

/* ---- motion, reduced --------------------------------------------------
 * Everything above that moves is decoration over a layout that already works
 * without it, so this turns all of it off rather than trying to soften it.
 */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .btn:hover, .lcard:hover, .steps li:hover, .stat:hover, .wopt:hover { transform: none; }
}

/* ---- narrow ------------------------------------------------------------ */

@media (max-width: 1000px) {
  .launch-grid, .tokgrid, .docs-wrap { grid-template-columns: minmax(0, 1fr); }
  .preview, .docs-side { position: static; }
  .docs-side { display: none; }        /* the sticky toc has nowhere to stick */
  .preview { order: -1; }              /* what you are launching, before the form */
}

@media (max-width: 680px) {
  .shell { padding: 0 16px 72px; }
  .bar { margin: 0 -16px; padding: 10px 16px; min-height: 56px; }

  /* Two rows: the mark and the wallet, then the tabs spread across the full
     width underneath. Four tabs plus a wallet button on one line is about
     560px of content, which is wider than any phone. */
  .bar { flex-wrap: wrap; gap: 8px 10px; }
  .bar-left { order: 1; }
  .bar > .w-btn { order: 2; margin-left: auto; }
  .bar-right { order: 3; flex-basis: 100%; margin-left: 0; gap: 6px; }
  .bar-right .btn { flex: 1; justify-content: center; padding: 8px 4px; }
  .sec { padding: 40px 0; }
  .hero { padding: 44px 0 40px; }
  .hide-sm { display: none !important; }
  .field.grouped { padding: 16px; }
  .logo-ctl { grid-template-columns: 1fr; }
  .logo-prev { width: 100%; height: 132px; }
  .tabs { display: flex; width: 100%; }
  .tab { flex: 1; justify-content: center; padding: 10px 10px; }
  .submit .btn { flex: 1; }

  /* The anchored sheet becomes a centred one, because an absolutely
     positioned popover inside a 16px gutter has nowhere to go. */
  .combo-pop {
    position: fixed;
    inset: auto 16px 16px;
    top: auto;
    max-height: 72vh;
    overflow-y: auto;
    animation: rise var(--t-slow) var(--spring);
  }
  .combo-list { max-height: 52vh; }
}

@media (min-width: 681px) {
  .hide-sm { display: initial; }
}
