/* ==========================================================================
   Vesper — design system
   One file. Tokens at the top; nothing below invents a colour or a radius.
   ========================================================================== */

:root {
  /* --- ground & ink -------------------------------------------------------
     Pure white, pure black, nothing in between that is not a percentage of
     the ink. Vespers is the last office of the day, sung from a printed
     book — so the whole product is set like one: black on paper, hairline
     rules, no shading that a press could not hold. */
  --void:        #fff;
  --void-raised: #fafafa;
  --void-sunk:   #f2f2f2;   /* the deepest a surface goes; still paper */

  --ink:      #000;
  --ink-soft: #000000a6;
  --ink-mute: #0000008f;
  --ink-dim:  #0006;
  --ink-ghost:#00000024;

  --line:        #0000001a;
  --line-strong: #0003;

  /* --- signal -------------------------------------------------------------
     There are no hues on paper, so the two market states are coded the way a
     printer codes them: filled or open.
     SHUT is solid ink — the shutter down, the bell rung, the hour closed.
     OPEN is the hairline outline — the page still blank, the session running.
     Every dot, bar, cell, pill and candle on this site uses exactly that pair
     to mean exactly those two things. Nothing else is ever filled solid. */
  --shut:      #000;         /* filled: the exchange is dark, the fee is wide */
  --shut-soft: #0000000d;    /* the wash behind a shut-state panel */

  --open:      #000;         /* outlined: the exchange is trading */
  --open-soft: #fff;
  --open-line: #00000021;

  /* Diagonal rule, used as the fill for anything that is dark-but-not-stopped:
     a stale feed, a pending bar. A hatch reads as "no reading", where a flat
     grey would read as a low reading. */
  --hatch: repeating-linear-gradient(-45deg, #000 0 1px, #0000 1px 5px);

  /* --- geometry --- */
  --page:  1280px;
  --gutter: 32px;
  --header-h: 76px;

  --r-panel: 18px;
  --r-card:  14px;
  --r-ctl:   10px;
  --r-pill:  999px;

  /* --- motion --- */
  --ease: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-io: cubic-bezier(0.32, 0.72, 0, 1);
  --t-fast: 0.14s;
  --t-base: 0.24s;

  /* --- type ---------------------------------------------------------------
     One family, everywhere, at three weights. A monospace set as body copy is
     the tell of a document that was printed to be checked rather than read —
     which is what a record of market hours is. --sans is kept as a name so
     every rule below still reads correctly; it resolves to the same face. */
  --sans: "Roboto Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --mono: "Roboto Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --cjk:  "Noto Sans SC", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;

  color-scheme: light;
}

/* ==========================================================================
   reset
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 24px);
}

body {
  position: relative;
  margin: 0;
  background: var(--void);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.7;
  font-feature-settings: "ss01" 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, svg, canvas { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
::selection { background: #000; color: #fff; }

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ==========================================================================
   type scale
   Display sizes are fluid and tightly tracked — the reference point is a
   grotesque set large enough that the tracking has to come back in.
   ========================================================================== */

.d1 {
  font-size: clamp(1.85rem, 3.6vw, 3.25rem);
  line-height: 1.08;
  letter-spacing: -0.04em;
  font-weight: 500;
}

.d2 {
  font-size: clamp(1.35rem, 2.3vw, 2rem);
  line-height: 1.1;
  letter-spacing: -0.03em;
  font-weight: 500;
}

.d3 {
  font-size: clamp(1.05rem, 1.5vw, 1.3rem);
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-weight: 500;
}

.lede {
  font-size: clamp(0.875rem, 1.05vw, 1rem);
  line-height: 1.62;
  letter-spacing: 0.005em;
  color: var(--ink-soft);
}

.body { color: var(--ink-soft); letter-spacing: -0.005em; }
.small { font-size: 0.875rem; line-height: 1.5; color: var(--ink-mute); }

.eyebrow {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
/* Both states are ink; what separates them is fill, not hue. `.shut` is set
   at full strength, `.open` steps back to the mid tone — the same contrast
   relationship the fills carry, so a number and its bar always agree. */
.shut { color: var(--ink); }
.open { color: var(--ink-mute); }

/* ==========================================================================
   layout
   ========================================================================== */

.wrap {
  width: 100%;
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

section { position: relative; }

.band { padding-block: clamp(72px, 10vw, 132px); }
.band + .band { border-top: 1px solid var(--line); }

.head { max-width: 720px; margin-bottom: clamp(36px, 5vw, 60px); }
.head .eyebrow { margin-bottom: 18px; }
.head .d2 + .lede { margin-top: 20px; }

/* ==========================================================================
   atmosphere — the field and the page wash
   The dark build put a starfield behind a coloured horizon. On paper there is
   no horizon and no colour, so the same slot carries a printed point field: a
   projected grid riding two crossed sine waves, drawn in ink and washed out
   where the copy sits, so the page still reads as white first.
   ========================================================================== */

/* Anchored to the top of the document, not fixed to the viewport: the field is
   the first screen's ground, and everything below it is clean paper. Fixed, it
   followed the reader down and put a horizon through the middle of every
   section. */
.sky {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 112svh;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  background: var(--void);
}

.sky__field { position: absolute; inset: 0; }
.sky__field canvas { display: block; }

.sky__veil {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 54% 26% at 50% 26%, #fff 34%, #fff0 82%),
    linear-gradient(180deg, #ffffffe6 0, #ffffff8c 13%, #fff0 33%, #fff0 66%, #fff 97%);
}

/* ==========================================================================
   header
   ========================================================================== */

.hdr {
  position: sticky;
  top: 0;
  z-index: 60;
  height: var(--header-h);
  border-bottom: 1px solid transparent;
  background: transparent;
  transition: background var(--t-base) var(--ease), border-color var(--t-base) var(--ease),
              backdrop-filter var(--t-base) var(--ease);
}

.hdr.is-stuck {
  background: #ffffffd1;
  backdrop-filter: blur(28px) saturate(1.7);
  -webkit-backdrop-filter: blur(28px) saturate(1.7);
  border-bottom-color: #00000021;
  box-shadow: 0 10px 34px #0000000f, 0 2px 6px #0000000a;
}

.hdr__in {
  height: 100%;
  display: flex;
  align-items: center;
  gap: 28px;
}

.brand { display: flex; align-items: center; gap: 11px; margin-right: auto; }
.brand__mark { width: 25px; height: 25px; flex: none; }
.brand__name {
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.02em;   /* all-caps needs opening up, not tightening */
}

.nav { display: flex; gap: 26px; }
.nav a {
  font-size: 0.9rem;
  letter-spacing: -0.012em;
  color: var(--ink-mute);
  transition: color var(--t-fast) var(--ease);
}
.nav a:hover { color: var(--ink); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding-inline: 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: rgba(0,0,0,0.025);
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  white-space: nowrap;
}

.dot {
  width: 6px; height: 6px;
  flex: none;
  border-radius: 50%;
  background: var(--ink-dim);
  transition: background var(--t-base) var(--ease), box-shadow var(--t-base) var(--ease);
}
/* Open is a ring — an empty mark, the session still running. Shut is the same
   ring filled in. Same dot, same size; only the middle changes. */
.dot.is-live { background: var(--void); box-shadow: inset 0 0 0 1.5px var(--ink), 0 0 0 3px var(--shut-soft); }
.dot.is-dark { background: var(--ink); box-shadow: 0 0 0 3px var(--shut-soft); }
.dot.is-pulse { animation: pulse 2.6s var(--ease-io) infinite; }

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

/* ==========================================================================
   hero
   ========================================================================== */

.hero {
  min-height: calc(100svh - var(--header-h));
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: 56px 72px;
}

.hero__status {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  align-self: flex-start;
  height: 34px;
  padding-inline: 14px;
  margin-bottom: 26px;
  border: 1px solid var(--ink);
  border-radius: var(--r-pill);
  background: var(--ink);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--void);
  transition: border-color var(--t-base) var(--ease), background var(--t-base) var(--ease),
              color var(--t-base) var(--ease);
}
/* Shut is the pill knocked out white on black — the shutter down. Open gives the
   ground back and leaves only the rule. */
.hero__status[data-state="open"] {
  border-color: var(--open-line);
  background: var(--void);
  color: var(--ink);
}

.hero__title { max-width: 15ch; }
/* The emphasised word carries the state as a rule under it rather than a hue:
   solid while the market is shut, hairline while it is open. */
.hero__title em {
  font-style: normal;
  box-shadow: inset 0 -0.1em 0 var(--ink);
  transition: box-shadow var(--t-base) var(--ease);
}
.hero__title[data-state="open"] em { box-shadow: inset 0 -0.035em 0 var(--line-strong); }

.hero__clock {
  margin-top: clamp(30px, 4.4vw, 52px);
  display: flex;
  align-items: flex-end;
  gap: clamp(16px, 2.4vw, 30px);
  flex-wrap: wrap;
}

.clock {
  font-family: var(--mono);
  font-size: clamp(2rem, 4.6vw, 3.4rem);
  font-weight: 500;
  line-height: 0.9;
  letter-spacing: -0.05em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  transition: color var(--t-base) var(--ease);
}
.clock[data-state="open"] { color: var(--ink-mute); }
.clock small {
  font-size: 0.26em;
  letter-spacing: 0.02em;
  color: var(--ink-dim);
  margin: 0 0.42em 0 0.1em;
  vertical-align: 0.12em;   /* the digits sit on a 0.9 line-height; pull the units up to them */
}
.clock small:last-child { margin-right: 0; }

/* Before the chain answers there is no elapsed time to show. Dim it so it reads as
   pending rather than as a broken readout. */
.clock.is-waiting { color: var(--ink-ghost); }
.clock.is-waiting small { color: var(--ink-ghost); }

.hero__caption { max-width: 34ch; padding-bottom: 6px; }

.hero__actions { margin-top: clamp(34px, 4.6vw, 54px); display: flex; gap: 12px; flex-wrap: wrap; }

.btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 46px;
  padding-inline: 21px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: #00000008;
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink);
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              transform var(--t-fast) var(--ease);
}
.btn:hover { background: var(--ink); border-color: var(--ink); color: var(--void); }
.btn:active { transform: translateY(1px); }

.btn--solid {
  background: var(--ink);
  color: var(--void);
  border-color: var(--ink);
}
.btn--solid:hover { background: #000000d9; border-color: #000000d9; }

.hero__scroll {
  margin-top: clamp(40px, 6vw, 76px);
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--ink-dim);
  font-size: 0.8rem;
}
.hero__scroll svg { animation: nudge 2.8s var(--ease-io) infinite; }

@keyframes nudge {
  0%, 100% { transform: translateY(0); opacity: .5; }
  50%      { transform: translateY(4px); opacity: 1; }
}

/* ==========================================================================
   panels & cards
   ========================================================================== */

.panel {
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: linear-gradient(180deg, rgba(0,0,0,0.025), rgba(0,0,0,0.009));
  backdrop-filter: blur(18px) saturate(1.06);
  -webkit-backdrop-filter: blur(18px) saturate(1.06);
}

.card {
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: rgba(0,0,0,0.02);
  padding: 24px;
  transition: border-color var(--t-base) var(--ease), background var(--t-base) var(--ease);
}
.card:hover { border-color: var(--line-strong); background: rgba(0,0,0,0.032); }

/* ==========================================================================
   feeds table — the live proof
   ========================================================================== */

.feeds { padding: 8px; }

.feeds__row {
  display: grid;
  grid-template-columns: 116px 132px 1fr 132px;
  align-items: center;
  gap: 18px;
  padding: 17px 20px;
  border-radius: var(--r-card);
  transition: background var(--t-fast) var(--ease);
}
.feeds__row + .feeds__row { border-top: 1px solid var(--line); }
.feeds__row:hover { background: rgba(0,0,0,0.022); }

.feeds__head {
  padding-block: 12px;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.feeds__head:hover { background: none; }

.feeds__name { display: flex; align-items: center; gap: 10px; font-weight: 520; letter-spacing: -0.018em; }
.feeds__price { font-family: var(--mono); font-size: 0.95rem; font-variant-numeric: tabular-nums; }

.feeds__bar {
  position: relative;
  height: 6px;
  border-radius: var(--r-pill);
  background: rgba(0,0,0,0.05);
  overflow: hidden;
}
/* A stale feed is hatched, not filled: a hatch reads as "no reading", where a
   flat grey bar would read as a low one. A live feed is solid ink. */
.feeds__fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  border-radius: var(--r-pill);
  background: var(--hatch);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  transition: width 0.9s var(--ease), background 0.5s var(--ease);
}
.feeds__fill.is-live { background: var(--ink); box-shadow: none; }

.feeds__age {
  font-family: var(--mono);
  font-size: 0.875rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.feeds__age.is-live { color: var(--ink-mute); }

.feeds__note { padding: 16px 20px 10px; }

/* Loading state. An empty panel reads as broken; a skeleton reads as pending. */
.feeds__row.is-skeleton .feeds__name,
.feeds__row.is-skeleton .feeds__price,
.feeds__row.is-skeleton .feeds__age { color: transparent; }
.feeds__row.is-skeleton .sk {
  display: block;
  height: 11px;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, rgba(0,0,0,0.036), rgba(0,0,0,0.072), rgba(0,0,0,0.036));
  background-size: 220% 100%;
  animation: shimmer 1.6s var(--ease-io) infinite;
}
@keyframes shimmer {
  0%   { background-position: 130% 0; }
  100% { background-position: -30% 0; }
}

/* ==========================================================================
   the week grid — 168 hours, lit and unlit
   ========================================================================== */

.week { display: grid; gap: 12px; }

.week__row { display: grid; grid-template-columns: 44px 1fr; align-items: center; gap: 14px; }
.week__day {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.week__hours { display: grid; grid-template-columns: repeat(24, 1fr); gap: 3px; }

.week__h {
  aspect-ratio: 1;
  border-radius: 2.5px;
  background: rgba(0,0,0,0.04);
  transition: background var(--t-base) var(--ease), transform var(--t-base) var(--ease);
}
/* Every hour the exchange is open is a filled square; every hour it is shut
   is the empty ground. Extended hours are the hairline in between. */
.week__h.is-open { background: var(--ink); opacity: 1; }
.week__h.is-pre  { background: var(--void); box-shadow: inset 0 0 0 1px var(--line-strong); }

.week__legend { display: flex; gap: 22px; flex-wrap: wrap; margin-top: 22px; }
.week__key { display: flex; align-items: center; gap: 8px; font-size: 0.82rem; color: var(--ink-mute); }
.week__swatch { width: 11px; height: 11px; border-radius: 3px; }
.week__swatch.is-open { background: var(--ink); }
.week__swatch.is-pre  { background: var(--void); box-shadow: inset 0 0 0 1px var(--line-strong); }
.week__swatch.is-dark { background: rgba(0,0,0,0.04); }

/* ==========================================================================
   the curve — interactive
   ========================================================================== */

.curve { display: grid; grid-template-columns: minmax(0, 1fr) 316px; gap: 0; }

.curve__plot { position: relative; padding: 30px 30px 18px; min-height: 372px; }
.curve__canvas { width: 100%; height: 330px; }

.curve__panel {
  border-left: 1px solid var(--line);
  padding: 30px;
  display: flex;
  flex-direction: column;
  gap: 26px;
}

.readout { }
.readout__val {
  font-family: var(--mono);
  font-size: 3.35rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.05em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  transition: color var(--t-base) var(--ease);
}
/* At the base fee the number steps back; at the ceiling it is boxed, which is
   the only way a monochrome readout can shout. */
.readout__val[data-state="base"] { color: var(--ink-mute); }
.readout__val[data-state="max"]  { color: var(--ink); box-shadow: inset 0 -0.08em 0 var(--ink); }
.readout__unit { font-size: 0.36em; color: var(--ink-dim); letter-spacing: 0; margin-left: 0.2em; }

.slider { display: grid; gap: 11px; }
.slider__top { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.slider__label { font-size: 0.85rem; color: var(--ink-soft); letter-spacing: -0.01em; }
.slider__val { font-family: var(--mono); font-size: 0.85rem; color: var(--ink); font-variant-numeric: tabular-nums; }

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 22px;
  background: none;
  cursor: grab;
}
input[type="range"]:active { cursor: grabbing; }
input[type="range"]::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: var(--r-pill);
  background: rgba(0,0,0,0.101);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 15px; height: 15px;
  margin-top: -6px;
  border-radius: 50%;
  background: var(--ink);
  border: 0;
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.16); box-shadow: 0 0 0 6px rgba(0,0,0,0.065); }
input[type="range"]::-moz-range-track { height: 3px; border-radius: 999px; background: rgba(0,0,0,0.101); }
input[type="range"]::-moz-range-thumb { width: 15px; height: 15px; border: 0; border-radius: 50%; background: var(--ink); }

.breakdown { display: grid; gap: 9px; padding-top: 22px; box-shadow: inset 0 1px 0 var(--line); }
.breakdown__row { display: flex; justify-content: space-between; gap: 12px; font-size: 0.83rem; }
.breakdown__row span:first-child { color: var(--ink-mute); }
.breakdown__row span:last-child { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.breakdown__row.is-total { padding-top: 9px; box-shadow: inset 0 1px 0 var(--line); font-weight: 500; }
.breakdown__row.is-total span:first-child { color: var(--ink); }

.preset { display: flex; gap: 7px; flex-wrap: wrap; }
.preset button {
  height: 30px;
  padding-inline: 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-mute);
  transition: all var(--t-fast) var(--ease);
}
.preset button:hover { color: var(--ink); border-color: var(--line-strong); }
.preset button[aria-pressed="true"] { background: var(--ink); color: var(--void); border-color: var(--ink); }

/* ==========================================================================
   code
   ========================================================================== */

.code {
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: var(--void-raised);
  overflow: hidden;
}
.code__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-dim);
}
.code pre {
  margin: 0;
  padding: 20px 22px;
  overflow-x: auto;
  font-family: var(--mono);
  font-size: 0.795rem;
  line-height: 1.72;
  letter-spacing: -0.012em;
  color: var(--ink-soft);
  tab-size: 4;
}
/* No syntax colours. A listing on paper is separated by weight and by italics,
   and that is enough to read Solidity by. */
.tok-key { color: var(--ink); font-weight: 600; }
.tok-typ { color: var(--ink); font-weight: 500; }
.tok-num { color: var(--ink); box-shadow: inset 0 -1px 0 var(--line-strong); }
.tok-str { color: var(--ink-soft); }
.tok-com { color: var(--ink-dim); font-style: italic; }
.tok-fn  { color: var(--ink); font-weight: 600; }

/* ==========================================================================
   stats
   ========================================================================== */

.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }

.stat { padding: 26px 24px 24px; }
.stat__n {
  font-family: var(--mono);
  font-size: clamp(1.9rem, 3.1vw, 2.65rem);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.045em;
  font-variant-numeric: tabular-nums;
}
.stat__l { margin-top: 13px; font-size: 0.845rem; color: var(--ink-mute); line-height: 1.42; }

/* ==========================================================================
   split / prose columns
   ========================================================================== */

.split { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.split--2 { grid-template-columns: repeat(2, 1fr); }

.card__k {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: 14px;
}
.card__t { font-size: 1.05rem; font-weight: 520; letter-spacing: -0.022em; margin-bottom: 9px; }
.card__b { font-size: 0.9rem; color: var(--ink-mute); line-height: 1.55; }

/* ==========================================================================
   address table
   ========================================================================== */

.addr { padding: 6px; }
.addr__row {
  display: grid;
  grid-template-columns: 190px 1fr auto;
  align-items: center;
  gap: 18px;
  padding: 15px 18px;
  border-radius: var(--r-ctl);
}
.addr__row + .addr__row { border-top: 1px solid var(--line); border-radius: 0; }
.addr__row:hover { background: rgba(0,0,0,0.02); }
.addr__k { font-size: 0.88rem; letter-spacing: -0.014em; }
.addr__v {
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--ink-mute);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.addr__c {
  font-family: var(--mono);
  font-size: 0.68rem;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--ink-dim);
  transition: all var(--t-fast) var(--ease);
}
.addr__c:hover { color: var(--ink); border-color: var(--line-strong); }

/* ==========================================================================
   ledger list (status / honesty)
   ========================================================================== */

.ledger { display: grid; gap: 0; }
.ledger__row {
  display: grid;
  grid-template-columns: 26px 1fr auto;
  align-items: start;
  gap: 16px;
  padding: 17px 4px;
}
.ledger__row + .ledger__row { border-top: 1px solid var(--line); }
.ledger__ic { margin-top: 3px; }
.ledger__t { display: block; font-size: 0.95rem; letter-spacing: -0.016em; }
.ledger__d { display: block; font-size: 0.85rem; color: var(--ink-mute); margin-top: 4px; }
.ledger__s {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  color: var(--ink-dim);
  white-space: nowrap;
  margin-top: 2px;
}
.ledger__s[data-s="done"] { color: var(--ink-mute); border-color: var(--line-strong); }
.ledger__s[data-s="next"] { background: var(--ink); border-color: var(--ink); color: var(--void); }

/* ==========================================================================
   footer
   ========================================================================== */

.ftr { padding-block: 76px 56px; border-top: 1px solid var(--line); }
.ftr__grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1.6fr; gap: 40px; }
.ftr__k {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: 20px;
}
.ftr__list { display: grid; gap: 13px; }
.ftr__list a { font-size: 0.9rem; color: var(--ink-mute); transition: color var(--t-fast) var(--ease); }
.ftr__list a:hover { color: var(--ink); }
.ftr__note { font-size: 0.82rem; color: var(--ink-dim); line-height: 1.6; }
.ftr__base {
  margin-top: 54px;
  padding-top: 26px;
  border-top: 1px solid var(--line);
  display: flex;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  font-size: 0.8rem;
  color: var(--ink-dim);
}

/* ==========================================================================
   reveal on scroll
   ========================================================================== */

/* Scoped to .js: if scripting is off, or the observer never fires, every section
   must still be on the page. Content is never hidden behind an animation. */
.js .rise {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.72s var(--ease), transform 0.72s var(--ease);
}
.js .rise.is-in { opacity: 1; transform: none; }

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

/* ==========================================================================
   responsive
   ========================================================================== */

@media (max-width: 1080px) {
  .stats { grid-template-columns: repeat(2, 1fr); }
  .split { grid-template-columns: 1fr; }
  .curve { grid-template-columns: 1fr; }
  .curve__panel { border-left: 0; box-shadow: inset 0 1px 0 var(--line); }
  .ftr__grid { grid-template-columns: 1fr 1fr; gap: 34px; }
}

@media (max-width: 860px) {
  :root { --gutter: 20px; --header-h: 64px; }
  .nav { display: none; }
  .feeds__row { grid-template-columns: 82px 1fr auto; gap: 12px; }
  .feeds__row > .feeds__bar { grid-column: 1 / -1; }
  .feeds__head { display: none; }
  .addr__row { grid-template-columns: 1fr; gap: 6px; }
  .addr__c { justify-self: start; }
  .hero__clock { flex-direction: column; align-items: flex-start; gap: 14px; }
  .week__row { grid-template-columns: 34px 1fr; gap: 9px; }
  .week__hours { gap: 2px; }
  .curve__plot { padding: 20px 16px 10px; }
  .curve__panel { padding: 24px 20px; }
}

@media (max-width: 560px) {
  .stats { grid-template-columns: 1fr; }
  .split--2 { grid-template-columns: 1fr; }
  .ftr__grid { grid-template-columns: 1fr; }

  .d1 { font-size: clamp(2.5rem, 10.4vw, 3.1rem); letter-spacing: -0.036em; }
  .hero__title { max-width: none; }

  /* "BNB Smart Chain · 56" crowds the wordmark; the number carries the meaning. */
  .chip { font-size: 0.68rem; padding-inline: 11px; }
  .chip .chip__long { display: none; }

  .readout__val { font-size: 2.9rem; }
  .feeds__row { padding: 15px 16px; }
  .week__legend { gap: 12px; }
  .week__key { font-size: 0.78rem; }
}

/* ==========================================================================
   print
   The atmosphere is a fixed layer and would repeat on every sheet, so it is
   dropped and the ground is painted flat instead.
   ========================================================================== */

@media print {
  :root { --gutter: 24px; }

  html, body {
    background: #fff !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .sky { display: none; }
  .hdr { position: static; background: none; border-bottom: 1px solid var(--line); }
  .hero { min-height: 0; padding-block: 40px 56px; }
  .band { padding-block: 48px; break-inside: avoid-page; }
  .js .rise { opacity: 1 !important; transform: none !important; }
  .hero__scroll, .preset, .addr__c { display: none; }
  .panel, .card, .code { break-inside: avoid; }
}

/* ==========================================================================
   ==========================================================================
   LAUNCHPAD
   Everything below builds the Explore / Launch product on the tokens above.
   No new colours, no new radii.
   ==========================================================================
   ========================================================================== */

/* ---------------------------------------------------------------- header v2 */

.hdr__in { position: relative; }

.nav--center {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  gap: 30px;
}
.nav--center a {
  position: relative;
  font-size: 1.0625rem;
  letter-spacing: -0.018em;
  color: var(--ink-mute);
  padding-block: 4px;
}
.nav--center a:hover { color: var(--ink); }
.nav--center a[aria-current="page"] { color: var(--ink); }
.nav--center a[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 1.5px;
  border-radius: 2px;
  background: var(--ink);
}

.hdr__right { display: flex; align-items: center; gap: 10px; margin-left: auto; }

.btn--sm { height: 36px; padding-inline: 15px; font-size: 0.86rem; border-radius: var(--r-pill); }
.btn--connected { font-family: var(--mono); font-size: 0.78rem; letter-spacing: -0.01em; }

.icon-btn {
  display: grid;
  place-items: center;
  width: 36px; height: 36px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  color: var(--ink-mute);
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.icon-btn:hover { color: var(--ink); background: rgba(0,0,0,0.043); }

.sheet {
  position: absolute;
  left: 0; right: 0; top: 100%;
  z-index: 70;
  background: rgba(255,255,255,.96);
  backdrop-filter: blur(20px) saturate(1.1);
  -webkit-backdrop-filter: blur(20px) saturate(1.1);
  border-bottom: 1px solid var(--line);
}
.sheet__in { display: grid; gap: 2px; padding-block: 14px 20px; }
.sheet__in a {
  padding: 11px 0;
  font-size: 1rem;
  letter-spacing: -0.018em;
  color: var(--ink-soft);
  border-bottom: 1px solid var(--line);
}
.sheet__in a:hover { color: var(--ink); }
.sheet__chain { padding-top: 14px; font-size: 0.72rem; color: var(--ink-dim); }

/* ------------------------------------------------------------------ page top */

.page { padding-block: clamp(46px, 7vw, 86px) clamp(64px, 9vw, 120px); }
.page__head { text-align: center; margin-bottom: clamp(30px, 4vw, 46px); }
.page__head .d2 { margin-inline: auto; }
.page__head .lede { max-width: 60ch; margin: 18px auto 0; }

.page__bar {
  display: flex;
  align-items: center;
  gap: 12px;
  justify-content: space-between;
  margin-bottom: 26px;
  flex-wrap: wrap;
}
.crumb {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 0.92rem;
  color: var(--ink-mute);
  transition: color var(--t-fast) var(--ease);
}
.crumb:hover { color: var(--ink); }
.page__meta { font-family: var(--mono); font-size: 0.78rem; color: var(--ink-dim); }

/* ------------------------------------------------------------- segmented ctl */

.seg {
  display: inline-flex;
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: rgba(0,0,0,0.022);
}
.seg button {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 32px;
  padding-inline: 14px;
  border-radius: var(--r-pill);
  font-size: 0.83rem;
  letter-spacing: -0.012em;
  color: var(--ink-mute);
  transition: all var(--t-fast) var(--ease);
}
.seg button:hover { color: var(--ink); }
.seg button[aria-pressed="true"] { background: var(--ink); color: var(--void); }

/* ------------------------------------------------------------- launch cards */

.launch-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
}

.lcard {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: rgba(0,0,0,0.02);
  overflow: hidden;
  transition: border-color var(--t-base) var(--ease), background var(--t-base) var(--ease),
              transform var(--t-base) var(--ease);
}
.lcard:hover {
  border-color: var(--line-strong);
  background: rgba(0,0,0,0.036);
  transform: translateY(-2px);
}

.lcard__art {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
  background: var(--void-raised);
  background-image: radial-gradient(#0000001a 0.6px, #0000 0.6px);
  background-size: 13px 13px;
}
.lcard__body { padding: 26px 28px 28px; }
.lcard__title { font-size: clamp(1.6rem, 2.4vw, 2.15rem); font-weight: 500; letter-spacing: -0.032em; }
.lcard__desc { margin-top: 10px; font-size: 0.95rem; color: var(--ink-mute); line-height: 1.5; max-width: 44ch; }
.lcard__go {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: 22px;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--ink);
}
.lcard__go svg { transition: transform var(--t-base) var(--ease); }
.lcard:hover .lcard__go svg { transform: translateX(4px); }

.lcard__tag {
  position: absolute;
  top: 16px; left: 16px;
  z-index: 2;
  height: 27px;
  padding-inline: 11px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.84);
  backdrop-filter: blur(10px);
  border: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* The stacked-slips illustration on the Module Mode card. */
.slips { position: absolute; inset: 0; display: grid; place-items: center; }
.slip {
  position: absolute;
  width: min(74%, 330px);
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 15px 18px;
  border-radius: 14px;
  background: #fff;
  color: var(--ink);
  border: 1px solid var(--line);
  font-weight: 500;
  letter-spacing: -0.01em;
  box-shadow: 0 14px 34px #0000000f, 0 2px 6px #0000000a;
}
.slip i { font-family: var(--mono); font-style: normal; font-size: .72rem; color: var(--ink-dim); }
.slip b { margin-left: auto; font-family: var(--mono); font-weight: 500; font-size: .78rem; color: var(--ink-dim); }
.slip:nth-child(1) { transform: translateY(-58px) rotate(-2.6deg); }
.slip:nth-child(2) { transform: translateY(0) rotate(1.4deg); }
.slip:nth-child(3) { transform: translateY(58px) rotate(-1deg); }

/* The permission-bits illustration on the Custom Hook card. An Infinity hook declares
   its callbacks as a 14-bit registration bitmap, so the bits are the picture. */
.bits { position: absolute; inset: 0; display: grid; place-content: center; gap: 26px; overflow: hidden; }
.bits::before {
  content: "";
  position: absolute;
  inset: -25%;
  background: radial-gradient(46% 46% at 50% 50%, #00000012, transparent 70%);
}
.bits__row { position: relative; display: flex; gap: 7px; }
.bits__c {
  width: clamp(15px, 2.4vw, 24px);
  aspect-ratio: 1;
  border-radius: 5px;
  border: 1px solid var(--line);
  background: rgba(0,0,0,0.032);
}
.bits__c.is-on {
  background: var(--ink);
  border-color: var(--ink);
}
.bits__addr {
  position: relative;
  text-align: center;
  font-family: var(--mono);
  font-size: clamp(1.1rem, 1.7vw, 1.5rem);
  letter-spacing: 0.06em;
  color: var(--ink-dim);
}
.bits__addr span { color: var(--ink); font-weight: 600; }

/* ------------------------------------------------------------------ toolbar */

.toolbar { display: flex; gap: 10px; align-items: center; justify-content: center; margin-bottom: 30px; flex-wrap: wrap; }

.search {
  position: relative;
  flex: 1 1 460px;
  max-width: 520px;
}
.search svg { position: absolute; left: 16px; top: 50%; transform: translateY(-50%); color: var(--ink-dim); }
.search input {
  width: 100%;
  height: 46px;
  padding: 0 16px 0 44px;
  border-radius: var(--r-ctl);
  border: 1px solid var(--line);
  background: rgba(0,0,0,0.022);
  color: var(--ink);
  font: inherit;
  font-size: 0.94rem;
  letter-spacing: -0.012em;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.search input::placeholder { color: var(--ink-dim); }
.search input:focus { outline: none; border-color: var(--line-strong); background: rgba(0,0,0,0.04); }

.tool-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 46px;
  padding-inline: 17px;
  border-radius: var(--r-ctl);
  border: 1px solid var(--line);
  background: rgba(0,0,0,0.022);
  font-size: 0.9rem;
  color: var(--ink-soft);
  transition: all var(--t-fast) var(--ease);
}
.tool-btn:hover { color: var(--ink); border-color: var(--line-strong); }
.tool-btn[aria-pressed="true"] { background: var(--ink); color: var(--void); border-color: var(--ink); }
.tool-btn:disabled { opacity: .35; cursor: not-allowed; }
.tool-btn--sq { width: 46px; padding: 0; justify-content: center; }

/* --------------------------------------------------------------- token grid */

.tgrid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 14px;
}

.tcard {
  display: flex;
  flex-direction: column;
  padding: 11px;
  border: 1px solid var(--line);
  border-radius: var(--r-panel);
  background: rgba(0,0,0,0.019);
  transition: border-color var(--t-base) var(--ease), background var(--t-base) var(--ease),
              transform var(--t-base) var(--ease);
}
.tcard:hover {
  border-color: var(--line-strong);
  background: rgba(0,0,0,0.036);
  transform: translateY(-2px);
}

.tcard__art {
  aspect-ratio: 1;
  border-radius: 12px;
  overflow: hidden;
  background: var(--void-raised);
  box-shadow: inset 0 0 0 1px var(--line);
  margin-bottom: 15px;
}
.tcard__art img, .tcard__art svg { width: 100%; height: 100%; object-fit: cover; display: block; }

.tcard__body { padding: 0 7px 7px; display: flex; flex-direction: column; flex: 1; }
.tcard__name {
  font-size: 1.02rem;
  font-weight: 520;
  letter-spacing: -0.024em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tcard__sym { margin-top: 2px; font-size: 0.86rem; color: var(--ink-mute); }
.tcard__kind {
  margin-top: 3px;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.tcard__foot { margin-top: 16px; }
.tcard__mcl { font-size: 0.78rem; color: var(--ink-dim); }
.tcard__row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-top: 3px; }
.tcard__mc { font-family: var(--mono); font-size: 1.18rem; letter-spacing: -0.035em; font-variant-numeric: tabular-nums; }
.tcard__ago { font-size: 0.78rem; color: var(--ink-dim); white-space: nowrap; }

.tcard__chg { font-family: var(--mono); font-size: 0.78rem; }
/* Printed candlestick convention, carried into the type: a rise is hollow, a
   fall is filled. It survives being photocopied, which no colour pair does. */
.tcard__chg.up { color: var(--ink); }
.tcard__chg.down { color: var(--void); background: var(--ink); padding: 1px 5px; border-radius: 4px; }

/* skeletons */
.tcard.is-skeleton { pointer-events: none; }
.tcard.is-skeleton .tcard__art,
.tcard.is-skeleton .sk {
  background: linear-gradient(90deg, rgba(0,0,0,0.029), rgba(0,0,0,0.065), rgba(0,0,0,0.029));
  background-size: 220% 100%;
  animation: shimmer 1.6s var(--ease-io) infinite;
}
.tcard.is-skeleton .sk { display: block; height: 12px; border-radius: var(--r-pill); }

.empty {
  grid-column: 1 / -1;
  padding: 64px 20px;
  text-align: center;
  color: var(--ink-mute);
}
.empty strong { display: block; color: var(--ink); font-size: 1.1rem; font-weight: 520; margin-bottom: 8px; letter-spacing: -0.02em; }

/* ------------------------------------------------------------------- builder */

.build { display: grid; grid-template-columns: minmax(0, 1fr) 344px; gap: 18px; align-items: start; }

.form { border: 1px solid var(--line); border-radius: var(--r-panel); background: rgba(0,0,0,0.019); }
.step { padding: 28px 30px; }
.step + .step { border-top: 1px solid var(--line); }
.step__h { display: flex; align-items: center; gap: 13px; margin-bottom: 24px; }
.step__n {
  display: grid;
  place-items: center;
  width: 25px; height: 25px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-mute);
}
.step__t { font-size: 1.16rem; font-weight: 540; letter-spacing: -0.026em; }

.field { display: grid; gap: 9px; }
.field + .field, .row + .field, .field + .row, .row + .row { margin-top: 20px; }
.row { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
/* Inside a grid row the gap does the spacing; the sibling margin would shift the
   second field down and break the labels' shared baseline. */
.row .field + .field { margin-top: 0; }
.row--3 { grid-template-columns: repeat(3, 1fr); }

.label { font-size: 0.875rem; color: var(--ink-soft); letter-spacing: -0.01em; }
.label span { color: var(--ink-dim); margin-left: 6px; font-size: 0.82rem; }

.input, .textarea, .select {
  width: 100%;
  border-radius: var(--r-ctl);
  border: 1px solid var(--line);
  background: rgba(0,0,0,0.022);
  color: var(--ink);
  font: inherit;
  font-size: 0.94rem;
  letter-spacing: -0.012em;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.input, .select { height: 46px; padding-inline: 15px; }
.textarea { padding: 13px 15px; min-height: 96px; resize: vertical; line-height: 1.5; }
.input::placeholder, .textarea::placeholder { color: var(--ink-dim); }
.input:focus, .textarea:focus, .select:focus {
  outline: none;
  border-color: var(--line-strong);
  background: rgba(0,0,0,0.04);
}
/* Achromatic, so an invalid field is marked by weight: the rule doubles and
   goes to full ink rather than turning red. */
.input[aria-invalid="true"] { border-color: var(--ink); border-width: 1.5px; }

.hint { font-size: 0.8rem; color: var(--ink-dim); }
.err { font-size: 0.8rem; color: var(--ink); font-weight: 500; padding-left: 9px; box-shadow: inset 2px 0 0 var(--ink); }

.suffixed { position: relative; }
.suffixed .input { padding-right: 62px; }
.suffixed span {
  position: absolute;
  right: 15px; top: 50%;
  transform: translateY(-50%);
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--ink-dim);
}

.drop {
  display: flex;
  align-items: center;
  gap: 16px;
}
.drop__box {
  display: grid;
  place-items: center;
  width: 82px; height: 82px;
  flex: none;
  border-radius: var(--r-ctl);
  border: 1px dashed var(--line-strong);
  background: rgba(0,0,0,0.022);
  color: var(--ink-dim);
  overflow: hidden;
}
.drop__box img, .drop__box svg { width: 100%; height: 100%; object-fit: cover; }
.drop.is-over .drop__box { border-color: var(--ink); background: var(--shut-soft); }

/* modules picker */
.mods { display: grid; gap: 10px; }
.mod {
  display: grid;
  grid-template-columns: 22px 1fr auto;
  align-items: start;
  gap: 14px;
  padding: 17px 18px;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background: rgba(0,0,0,0.014);
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.mod:hover { border-color: var(--line-strong); }
.mod[data-on="true"] { border-color: var(--ink); background: var(--shut-soft); }
.mod__check {
  display: grid; place-items: center;
  width: 20px; height: 20px; margin-top: 1px;
  border-radius: 6px;
  border: 1px solid var(--line-strong);
  color: transparent;
}
.mod[data-on="true"] .mod__check { background: var(--ink); border-color: var(--ink); color: var(--void); }
.mod__t { font-size: 0.98rem; font-weight: 520; letter-spacing: -0.02em; }
.mod__d { margin-top: 4px; font-size: 0.855rem; color: var(--ink-mute); line-height: 1.5; }
.mod__tag {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  color: var(--ink-dim);
  white-space: nowrap;
}
.mod__tag[data-k="ours"] { background: var(--ink); border-color: var(--ink); color: var(--void); }

/* preview rail */
.rail { position: sticky; top: calc(var(--header-h) + 18px); display: grid; gap: 14px; }

.pv { padding: 20px; border: 1px solid var(--line); border-radius: var(--r-panel); background: rgba(0,0,0,0.022); }
.pv__top { display: flex; align-items: center; gap: 13px; margin-bottom: 18px; }
.pv__art {
  width: 54px; height: 54px; flex: none;
  border-radius: 13px;
  overflow: hidden;
  background: var(--void-raised);
  display: grid; place-items: center;
  color: var(--ink-dim);
}
.pv__art img, .pv__art svg { width: 100%; height: 100%; object-fit: cover; }
.pv__name { font-size: 1.04rem; font-weight: 540; letter-spacing: -0.024em; }
.pv__sym { font-family: var(--mono); font-size: 0.84rem; color: var(--ink-mute); }

.pv__pill {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  margin-bottom: 9px;
}
.pv__pill b { font-size: 0.92rem; font-weight: 520; letter-spacing: -0.018em; }
.pv__pill i { display: block; font-style: normal; font-size: 0.8rem; color: var(--ink-mute); margin-top: 2px; }
.pv__pill .ok { margin-left: auto; color: var(--ink); }

.pv__rows { margin-top: 18px; display: grid; gap: 10px; }
.pv__row { display: flex; justify-content: space-between; gap: 12px; font-size: 0.87rem; }
.pv__row span:first-child { color: var(--ink-mute); }
.pv__row span:last-child { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.pv__row.is-total { padding-top: 11px; border-top: 1px solid var(--line); font-weight: 500; }
.pv__row.is-total span:first-child { color: var(--ink); }
.pv__note { margin-top: 15px; font-size: 0.78rem; color: var(--ink-dim); line-height: 1.5; }

.btn--full { width: 100%; justify-content: center; }
.btn:disabled { opacity: .4; cursor: not-allowed; }

/* review dialog */
.sheet-over {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  padding: 20px;
  background: rgba(0,0,0,.34);
  backdrop-filter: blur(6px);
}
.dlg {
  width: min(560px, 100%);
  max-height: 86vh;
  overflow: auto;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-panel);
  background: var(--void-raised);
  padding: 30px;
  box-shadow: 0 30px 80px rgba(0,0,0,.16);
}
.dlg__t { font-size: 1.45rem; font-weight: 500; letter-spacing: -0.03em; }
.dlg__d { margin-top: 10px; font-size: 0.92rem; color: var(--ink-mute); line-height: 1.55; }
.dlg__rows { margin: 22px 0; display: grid; gap: 11px; }
.dlg__acts { display: flex; gap: 10px; flex-wrap: wrap; }

.note {
  display: flex;
  gap: 12px;
  padding: 15px 17px;
  border-radius: var(--r-card);
  border: 1px solid var(--line-strong);
  background: var(--shut-soft);
  font-size: 0.86rem;
  color: var(--ink-soft);
  line-height: 1.55;
}
.note b { color: var(--ink); font-weight: 600; }

/* ------------------------------------------------------------------- prose */

.prose { max-width: 74ch; }
.prose h2 { font-size: 1.55rem; font-weight: 500; letter-spacing: -0.03em; margin-top: 46px; margin-bottom: 14px; }
.prose h3 { font-size: 1.1rem; font-weight: 540; letter-spacing: -0.022em; margin-top: 30px; margin-bottom: 10px; }
.prose p { color: var(--ink-soft); margin-bottom: 15px; line-height: 1.62; }
.prose ul { margin: 0 0 18px; padding-left: 20px; list-style: disc; }
.prose li { color: var(--ink-soft); margin-bottom: 8px; line-height: 1.6; }
.prose code {
  font-family: var(--mono);
  font-size: 0.86em;
  padding: 2px 6px;
  border-radius: 6px;
  background: rgba(0,0,0,0.05);
}
.prose a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.prose table { width: 100%; border-collapse: collapse; margin-bottom: 22px; font-size: 0.9rem; }
.prose th, .prose td { text-align: left; padding: 11px 14px; border-bottom: 1px solid var(--line); }
.prose th { font-family: var(--mono); font-size: 0.68rem; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-dim); }
.prose td { color: var(--ink-soft); }

.docs { display: grid; grid-template-columns: 214px minmax(0, 1fr); gap: 46px; align-items: start; }
.toc { position: sticky; top: calc(var(--header-h) + 18px); display: grid; gap: 3px; }
.toc a {
  padding: 7px 11px;
  border-radius: 9px;
  font-size: 0.875rem;
  color: var(--ink-mute);
  transition: all var(--t-fast) var(--ease);
}
.toc a:hover { color: var(--ink); background: rgba(0,0,0,0.032); }
.toc a.is-on { color: var(--ink); background: rgba(0,0,0,0.05); }

/* -------------------------------------------------------------- responsive */

@media (max-width: 1140px) {
  .tgrid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .build { grid-template-columns: 1fr; }
  .rail { position: static; }
  /* `1fr` resolves to `minmax(auto, 1fr)`, and the TOC's auto minimum is the
     full width of its own scrolling row — which dragged the whole page wider
     than the viewport at 390. The explicit 0 minimum is what lets it scroll
     inside its track instead of pushing the track. */
  .docs { grid-template-columns: minmax(0, 1fr); gap: 26px; }
  .toc { position: static; min-width: 0; grid-auto-flow: column; grid-auto-columns: max-content; overflow-x: auto; padding-bottom: 6px; }

  /* The chain reference is a column of 42-character addresses set in mono — a
     min-content width no phone has. Below the two-column breakpoint it becomes
     its own scroll container so it can be dragged sideways instead of dragging
     the whole page with it. It keeps `width: 100%` above that. */
  .prose table { display: block; width: 100%; overflow-x: auto; }
}

@media (max-width: 900px) {
  .nav--center { display: none; }
  .tgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .launch-cards { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .tgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .row, .row--3 { grid-template-columns: 1fr; }
  .step { padding: 22px 18px; }
  .search { flex-basis: 100%; }
  .tcard__mc { font-size: 1.05rem; }
  .dlg { padding: 22px; }
}

/* ------------------------------------------------------------------- home */

.home-hero {
  min-height: calc(100svh - var(--header-h));
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding-block: 56px 84px;
}
.home-hero__title { letter-spacing: -0.02em; }  /* set in caps */
.home-hero__sub { margin-top: 20px; max-width: 54ch; }
.home-hero #cards { width: 100%; }

/* The home hero centres its own copy; the cards inside it must not inherit that. */
.home-hero .lcard { text-align: left; }

/* ---------------------------------------------------------------- social */

.ftr__handle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 18px;
  padding: 7px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-size: 0.83rem;
  color: var(--ink-mute);
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.ftr__handle:hover { color: var(--ink); border-color: var(--line-strong); }

.ftr__x { display: inline-flex; align-items: center; gap: 8px; }

/* ------------------------------------------------------------------ language
   A two-state segmented control in the header. It is a toggle rather than a
   dropdown because there are exactly two languages and both fit — the reader
   can see what they are switching to without opening anything.

   The pressed state is carried by aria-pressed, which is also what the toggle
   reads back, so the visual state cannot drift from the announced one. */
.langtog {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: #00000008;
}

.langtog__b {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--ink-dim);
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  line-height: 1;
  padding: 7px 10px;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: color 140ms ease, background-color 140ms ease;
}

.langtog__b:hover { color: var(--ink-soft); }
.langtog__b[lang="zh-Hans"] { font-family: var(--cjk); letter-spacing: 0.02em; }

.langtog__b[aria-pressed="true"] {
  color: var(--void);
  background: var(--ink);
  font-weight: 600;
}

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

/* Roboto Mono has no Han glyphs, so without this the browser falls back
   per-glyph and the labels end up optically different sizes. Noto Sans SC is
   already loaded for the Chinese build of every page. */
html[lang="zh-Hans"] body { font-family: var(--cjk); }

/* Han characters carry more ink per em than Latin, so the display sizes that
   look right in English read as shouting in Chinese. Pull them back a little
   and open up the line height, which CJK needs more of. */
html[lang="zh-Hans"] .d1 { letter-spacing: 0; }
html[lang="zh-Hans"] .d2,
html[lang="zh-Hans"] .d3 { letter-spacing: 0; }
html[lang="zh-Hans"] .lede,
html[lang="zh-Hans"] .body,
html[lang="zh-Hans"] .prose p { line-height: 1.85; letter-spacing: 0; }

/* On narrow screens the header runs out of room before the toggle does. */
@media (max-width: 560px) {
  .langtog__b { padding: 6px 8px; font-size: 0.74rem; }
}

/* Small uppercase labels are tracked out for Latin, which looks like a mistake in
   Chinese — Han characters are already full-width and the extra space reads as a
   gap between unrelated words. Reset tracking and drop the case transform, which
   does nothing to Han glyphs but does affect any Latin mixed in. */
html[lang="zh-Hans"] .eyebrow,
html[lang="zh-Hans"] .label,
html[lang="zh-Hans"] .card__k,
html[lang="zh-Hans"] .ftr__k,
html[lang="zh-Hans"] .readout__label,
html[lang="zh-Hans"] .stat__l,
html[lang="zh-Hans"] .lcard__tag,
html[lang="zh-Hans"] .mod__tag,
html[lang="zh-Hans"] .ledger__s,
html[lang="zh-Hans"] .page__meta {
  letter-spacing: 0.02em;
}
