/* W2's stylesheet. Block W law W-L1, in its own words:
 *
 *   "A later module that needs a class the base does not have adds it in its own
 *    stylesheet, inside its own fence, built only from the base's tokens — never
 *    a new colour, never a new font, never a hard-coded pixel value where a token
 *    exists."
 *
 * So: not one colour below is a literal. Every one is a var() onto a token
 * `src/design/design.css` declares in its own :root — --bg --sidebar --panel
 * --panel2 --line --line2 --text --muted --subtle --green --green-dim --amber
 * --red --blue --purple --font --mono — or onto --chain, the per-chip relay A9
 * introduced, which is assigned `var(--c-*)` from the contract's closed
 * chain-accent set at the call site and never a value of its own.
 *
 * There are no size tokens in the base, so sizes here are the base's own
 * component scale, copied from it: 30px for a mark disc (.coin), 17px for a nav
 * icon (.navlink svg), 6px radii, 1px hairlines.
 *
 * FOUR SECTIONS:
 *   1  the base, re-asserted over A9's older chrome rules
 *   2  the three A9 components the base has no class for
 *   3  the topbar's as-of slot
 *   4  the route-slot guard, which is temporary and says so
 */

/* == 1 == the base, re-asserted ============================================ *
 * `src/styles/shell.css` is still linked — five route modules use its `.def*`
 * and `.vh` and W2 does not restyle a route — and it is linked BEFORE the base
 * so the base wins. These four are what it declares and the base does not, so
 * the base has nothing to win with. */

html {
  /* A9 painted the root the contract's --ink. The body is the base's --bg now,
   * and an overscroll that reveals a different ground is a seam a visitor sees. */
  background: var(--bg);
}

/* One focus ring, one colour, everywhere — W-L6. The base rings `a` and
 * `summary`; a button, an input and the route slot are focusable too, and a ring
 * that only some focusable things get is not a ring you can rely on. */
:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 3px;
}

.skip:focus {
  /* The base moves it to top:10px. A9's sheet also parks it at left:-9999px,
   * which is later than the base for `left` only because A9 set it on `.skip:focus`. */
  left: 10px;
  z-index: 50;
}

/* == 2 == the three components A9 declares and the base has no class for ==== *
 * Their markup and their `data-vct` are unchanged (W-L2). Only the ink moved,
 * from the contract's token set to the base's, so the frame reads as one thing. */

/* ---- the brand · A9's `.wordmark` rule is still linked and still paints the
 *      contract's --mark and the contract's display face. Under the design
 *      system the identity green is --green and the brand is the base's `.brand`:
 *      the glyph carries the green and the word carries --text. That keeps the
 *      identity green to three jobs, which is what DL-01 asks — the brand glyph,
 *      the focus ring and the active-nav marker — in the base's own token. */

.brand.wordmark {
  color: var(--text);
  font-family: var(--font);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 1.1px;
}

/* ---- the sidebar's own stack */

.sidebar > .navigation,
.sidebar > .chains,
.sidebar > .riskfree {
  min-width: 0;
}

.navigation {
  display: grid;
  gap: 21px;
}

/* ---- scan field · doc 11 §7: an action available everywhere, never a destination */

.scan {
  /* A9 wrote `flex: 1 1 240px` for a field sitting in a horizontal header bar.
   * The sidebar is a COLUMN flex container, so that grow factor made the field
   * 420px tall. Measured, not guessed: the box was 245x420 before this line. */
  flex: 0 0 auto;
  /* A9 also wrote `margin-left:auto` above 920px, to push the field to the right
   * of a header bar. An auto margin on the cross axis switches `align-self:stretch`
   * OFF, so the form sized to its content (245px) inside a 179px column and the
   * Scan button sat on top of the page heading. Measured, then fixed. */
  margin-left: 0;
  display: flex;
  align-items: stretch;
  gap: 6px;
  min-width: 0;
}

.scan__input {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 5px;
  color: var(--text);
  font-family: var(--mono);
  font-size: 11px;
  padding: 8px 9px;
}
.scan__input::placeholder { color: var(--subtle); }
.scan__input:hover { border-color: var(--line2); }

.scan__go {
  flex: 0 0 auto;
  padding: 8px 10px;
  gap: 5px;
  cursor: pointer;
  color: var(--text);
}
.scan__go svg { width: 14px; height: 14px; }
.scan__go:hover { border-color: var(--line2); color: var(--green); }

/* ---- nav · the base draws .navgroup/.navlabel/.navlink; these three are ours */

/* `.vh` is `position:absolute`. With no positioned ancestor its containing block
 * is the document, so it sits at its static position OUTSIDE the nav's scroll
 * box and drags the page's scrollWidth out with it — measured at 390px: the
 * document scrolled to 607 with three reserved reasons parked off to the right.
 * A positioned parent is the whole fix. */
.navlink { position: relative; }
.navlink > span { min-width: 0; overflow-wrap: anywhere; }

/* Visibly disabled: dimmed to the base's quietest text, struck through, not a
 * pointer, and carrying its reason. DL-12 — absence is designed, not hidden. */
.nav__link--reserved {
  color: var(--subtle);
  cursor: not-allowed;
  font-weight: 400;
  text-decoration: line-through;
  text-decoration-color: var(--subtle);
  text-decoration-thickness: 1px;
}
.nav__link--reserved:hover { background: none; color: var(--subtle); }
.nav__link--reserved svg { opacity: 0.55; }

/* ---- chain filter · doc 11 §3.5, a logo with the ticker beneath */

.chains__list {
  display: flex;
  flex-wrap: wrap;           /* six chips fit 390px by wrapping, never by scrolling */
  gap: 6px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.chain__btn {
  display: flex;
  flex-direction: column;    /* logo, ticker beneath — doc 11 §3.5 */
  align-items: center;
  gap: 4px;
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 5px 6px;
  cursor: pointer;
  color: var(--subtle);
}
.chain__btn:hover { background: var(--panel2); }
/* U2 · THE CHIP IS A LINK AND ITS SELECTED STATE IS aria-current.
 *
 * `aria-pressed` is kept because W2 declared it and nothing else in this repository should
 * have to know which of the two a chip carries; what was added is the link's state, and the
 * declaration is the same one. A selected chain must be VISIBLE and not only announced —
 * tests/shell/acceptance.test.ts measures the computed background, border and colour against
 * the resting state and fails if they are equal.
 *
 * AND `text-decoration: none`, because the chip is an anchor now: without it the base
 * underlines the ticker, which is a logo with a underlined label beneath it rather than
 * doc 11 §3.5's chip. */
.chain__btn { text-decoration: none; }
.chain__btn[aria-pressed="true"],
.chain__btn[aria-current="true"] {
  background: var(--panel2);
  border-color: var(--line2);
  color: var(--text);
}
/* A chain the platform lists and does not serve yet is a rendered STATE, not a control
 * (DL-12). It is dimmed and it does not take the pointer, the same treatment the nav's
 * reserved items get, so a reader can see at a glance which chips answer. */
.chain__btn[aria-disabled="true"] {
  cursor: default;
  opacity: 0.45;
}
.chain__btn[aria-disabled="true"]:hover { background: none; }

/* The chain accent tints the mark and nothing else — 13% alpha, per doc 11 §2.
 * It never colours text and it never colours a value. The disc is the base's
 * .coin geometry at the size the base gives a mark inside a dense column. */
.chain__mark {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--chain) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--chain) 25%, transparent);
  color: var(--chain);
}
.chain__mark svg { width: 15px; height: 15px; }

.chain__ticker {
  font-family: var(--mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.10em;
  line-height: 1.2;
}

/* ---- the risk-free note · DL-04, and it is never hidden from anybody */

.riskfree {
  display: block;            /* A9's rule makes it a wrapping flex row for a header strip */
  font-size: 11px;
  color: var(--subtle);
  line-height: 1.5;
}

/* The base gives every <details> a top hairline and 13px of padding, which is
 * the pack's own inline-disclosure look. In the sidebar it needs neither. */
.riskfree .def { border-top: 0; padding: 0; position: static; }
.riskfree .def__term { color: var(--green); font-weight: 600; }

/* In a 180px column the popover A9 draws on a board would run off the screen,
 * so here the definition opens in flow. Same element, same sentences, same
 * mechanism with no script — only the geometry is the sidebar's. */
.riskfree .def__body {
  position: static;
  width: auto;
  margin-top: 8px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 10px 11px;
  color: var(--muted);
  font-size: 11px;
}
.riskfree .def__source {
  color: var(--subtle);
  font-family: var(--mono);
  overflow-wrap: anywhere;
}
.riskfree__tail { display: block; margin-top: 6px; overflow-wrap: anywhere; }

/* ---- the route slot's own designed state · DL-12, W-L3 (the sentence is A9's)
 *
 * The placeholder is the SHELL's markup that happens to live inside the slot, so
 * the route-slot guard in section 4 strips the base's `.callout` off it along
 * with every route's. It is put back here, from the base's own tokens, at a
 * specificity the guard cannot reach. W-L10: the nearest pattern the pack draws
 * for "here is a thing you should read" is the callout, so this is the callout. */

:where(#vct-route) .route__placeholder.callout {
  padding: 15px 17px;
  background: var(--panel2);
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 12px;
  color: var(--muted);
}
.route__placeholder-line { display: block; color: var(--amber); font-weight: 500; }
.route__placeholder-note { margin-top: 6px; font-size: 11px; line-height: 1.7; }

/* == 3 == the topbar's as-of slot ========================================== *
 * The design's topbar carries a snapshot stamp. Ours carries the stamp the
 * page's DATA has, or says in words that the page declares none. It is never a
 * clock: `[data-as-of="absent"]` is a sentence, not a blank. */

.asof {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--subtle);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.asof[data-as-of="absent"] { color: var(--muted); }
.asof time { font-family: var(--mono); }

.breadcrumb { min-width: 0; }
.breadcrumb > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.breadcrumb strong { color: var(--text); font-weight: 600; flex: 0 1 auto; }
/* U17 · THE STAMP SHRINKS INSTEAD OF PUSHING THE PAGE.
 *
 * `.asof` is `white-space:nowrap; overflow:hidden; text-overflow:ellipsis` and has been since
 * A9 - which does nothing at all unless its parent is a flex line that can squeeze it. It was
 * not one, so at 390px a long stamp grew the topbar's right-hand group past the viewport and
 * the whole document scrolled sideways: measured at 550px inside 390px, on every page in the
 * platform, the moment the absent-stamp sentence got four words longer.
 *
 * R-112 §6 lifts U-L3 for exactly this - "table overflow" - and nothing moves at a width where
 * the stamp already fitted: `flex: 0 1 auto` only ever shrinks. */
.topbar .right { display: flex; align-items: center; gap: 10px; min-width: 0; overflow: hidden; }
.topbar .right > .asof { flex: 0 1 auto; }
.topbar .right > .avatar { flex: 0 0 auto; }

/* Below the base's own 650px breakpoint the topbar is 52px tall and the trail,
 * the stamp and the account do not all fit. The LAST crumb is the one that says
 * where you are, so the earlier ones go and it stays — measured: at 390px the
 * `Me` crumb was being squeezed to zero width and the reader saw a lone group
 * name for a page it was not the name of. */
@media (max-width: 650px) {
  .breadcrumb > :not(:last-child) { display: none; }
  .asof { flex: 0 1 auto; }
}

/* The sprite. Two <svg> elements of symbols, inlined so a mark needs no second
 * request and survives script being off (W-L4, W-L7). */
.vct-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* == 4 == the route-slot guard · TEMPORARY, and W3 … W7 remove it =========== *
 * The base carries bare-element rules — details, table, th, td, svg — and
 * linking it puts them over every route's markup as well as the frame. W2's stop
 * condition is that the shell renders the slot and does not decide what mounts
 * into it, so each rule below holds ONE measured property at the value that
 * route had before this module, and nothing else.
 *
 * `:where()` contributes no specificity, so every one of these loses to any
 * class a route's own stylesheet uses. They are a floor, not an override.
 *
 * Each line names the base rule it neutralises. The module that lays a route out
 * deletes the lines its route needed; W8 is what notices if one is left behind.
 *
 * ---- W3 · HOW A CONVERTED ROUTE LEAVES, and why it is not a deletion --------
 *
 * SCOPED, NOT DELETED (00-IMPORT.md C-11, at the marker W2 left in three places:
 * this header, src/shell/README.md and tests/shell/route-guard.test.ts's own
 * failure message — "if the route has been laid out against the base by its own
 * W module, remove that route from the concern").
 *
 * Deleting a line here does not free ONE route. `:where(#vct-route) table` holds
 * the tables on /leaders, /profile, /asset and /me as well, and W4 … W7 have not
 * run: measured over the built site, `.row` alone reaches 16 route slots and
 * `table` reaches every board on the platform. A deletion would hand nine
 * unconverted routes the base's `white-space:nowrap` and `th{font-size:9px}` —
 * the two W2 measured as the ones that break a page.
 *
 * So the guard is scoped instead. A route laid out against the base marks its
 * own root `data-vct-design="v3"`, and `:not(:has([data-vct-design]))` takes the
 * WHOLE guard off that page at once — every bare-element rule and every class
 * collision together, which is the only coherent unit: a page is either the
 * base's world or the contract's, and half of each is neither.
 *
 * `:has()` inside `:where()` still contributes no specificity, so a route rule
 * beats these exactly as it did before. The lines stay, named and measured, for
 * every route that has not been converted yet, and the last W module to convert
 * one deletes the section rather than thinning it.
 *
 * W3's three routes carry the marker: /discover/tokens, /discover/long-short and
 * /search (with /scan, which renders the same page).
 */

/* THE BIGGEST ONE, and it is inheritance rather than a selector. The base's
 * `body{color:var(--text);font:14px/1.55 var(--font)}` is inherited by every
 * element in a route that does not set its own, which moved 646 computed-property
 * groups across /discover/tokens, /me and /leaders in one measurement — colour,
 * face, size and leading on boards this module is not laying out. These four
 * declarations put the slot back on A9's body values.
 *
 * `:where()` again: specificity 0, so a route's own stylesheet beats it on the
 * first rule it writes, which is exactly what W3 … W7 will do. */
:where(#vct-route:not(:has([data-vct-design]))) {
  color: var(--t2);
  font-family: var(--ui);
  font-size: 14px;
  line-height: 1.6;
  /* --mono is the ONE name the two token sets share, and they disagree about it:
   * the contract says 'IBM Plex Mono', the base says SFMono-Regular. design.css
   * declares its :root after tokens.generated.css, so every `font-family:var(--mono)`
   * in a route quietly changed face — 1,516 computed readings across nine routes.
   * The slot is the contract's world until its own W module converts it, so the
   * contract's value is put back here. It is NOT retyped from memory:
   * tests/shell/route-guard.test.ts reads the token out of the pinned contract and
   * asserts the browser resolves exactly that string inside the slot. */
  --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', monospace;
}

/* base: details{border-top:1px solid var(--line);padding:13px 17px} — five route
 * modules put a definition popover on a <details> and none of them expect a
 * hairline and 30px of padding around the term. */
:where(#vct-route:not(:has([data-vct-design]))) details { border-top: revert; padding: revert; font-size: revert; }

/* base: details p{margin-top:9px;color:var(--muted)} */
:where(#vct-route:not(:has([data-vct-design]))) details p { margin-top: revert; color: revert; }

/* base: summary{cursor:pointer;color:var(--green)} — keep the pointer, drop the
 * green: a definition term next to a value must not read as the identity mark. */
:where(#vct-route:not(:has([data-vct-design]))) summary { color: revert; }

/* base: svg{display:block} — B5's charts and the boards' inline glyphs are laid
 * out inline by their own stylesheets. */
:where(#vct-route:not(:has([data-vct-design]))) svg { display: revert; }

/* base: table{border-collapse:collapse;width:100%;text-align:left;font-size:12px;
 *             white-space:nowrap}
 *       th{font-size:9px;…;padding:12px 16px;border-bottom:…;background:#101813}
 *       td{padding:13px 16px;border-bottom:…;font-variant-numeric:tabular-nums}
 *       tbody tr:last-child td{border-bottom:0}
 *
 * `white-space:nowrap` is the one that bites hardest and it is not obvious:
 * inherited into every cell it stops a board's text wrapping at all, so the
 * table's min-content width becomes the sum of its longest lines. MEASURED on
 * /discover/tokens: the index table went from 1284px to 1406px and the page
 * gained a horizontal scrollbar at every width from 960 to 1650.
 *
 * `th{font-size:9px}` is the second: it is below the contract's own 11px floor,
 * which tests/shell/acceptance.test.ts measures in a browser. */
:where(#vct-route:not(:has([data-vct-design]))) table { border-collapse: revert; border-spacing: revert; width: revert; text-align: revert; font-size: revert; white-space: revert; }
/* `revert` and not a hand-picked value, everywhere the pre-W2 page had no author
 * rule at all: it rolls the property back to the browser's own sheet, which is
 * exactly what these elements had before the base was linked. A route rule still
 * wins outright — these selectors carry no specificity. */
:where(#vct-route:not(:has([data-vct-design]))) th, :where(#vct-route:not(:has([data-vct-design]))) td { padding: revert; text-align: revert; font-weight: revert; font-size: revert; letter-spacing: revert; text-transform: revert; color: revert; background: revert; border-bottom: revert; font-variant-numeric: revert; }
:where(#vct-route:not(:has([data-vct-design]))) td .sub { display: revert; font-size: revert; color: revert; margin-top: revert; }

/* base: tbody tr:last-child td{border-bottom:0}. `:last-child` is a pseudo-CLASS,
 * so that selector scores (0,1,3) and outranks a board's own `.td` — which is why
 * only the LAST row of every index table lost its rule. Re-scored to (0,0,1) here,
 * which puts the board back in front of it. */
:where(#vct-route:not(:has([data-vct-design]))) :where(tbody tr:last-child) td { border-bottom: revert; }

/* base: button{font:inherit}. A route's unstyled button had the browser's own
 * font metrics before this module; `font:inherit` changed its leading. */
:where(#vct-route:not(:has([data-vct-design]))) button { font: revert; }

/* base: h1{font-size:34px} h2{17px} h3{14px} small{11px} and h1..h4,p{margin:0} */
:where(#vct-route:not(:has([data-vct-design]))) h1, :where(#vct-route:not(:has([data-vct-design]))) h2, :where(#vct-route:not(:has([data-vct-design]))) h3, :where(#vct-route:not(:has([data-vct-design]))) h4 { font-size: revert; letter-spacing: revert; line-height: revert; font-weight: revert; margin: revert; }
:where(#vct-route:not(:has([data-vct-design]))) p { margin: revert; }
:where(#vct-route:not(:has([data-vct-design]))) small { font-size: revert; }

/* base: a:hover{color:var(--green)} — a row link turning the identity green on
 * hover puts the mark next to a value, which DL-01 does not allow. */
:where(#vct-route:not(:has([data-vct-design]))) a:hover { color: revert; }

/* ---- and the other half of the same problem: CLASS-NAME collisions.
 *
 * The base defines 140 short, generic class names. The routes were written
 * before it existed and already use some of them for something else. MEASURED
 * over the built site: 8 of the base's 140 classes appear inside the route slot,
 * and `tests/shell/route-guard.test.ts` recomputes that intersection on every
 * run and goes red if a 9th ever appears unguarded — because the next one will
 * arrive silently, the way `.row` did.
 *
 * `.row` is the one that showed why this matters. B3 puts `class="row"` on a
 * `<tr>`; the base's `.row{display:flex}` turned every cell into a flex item,
 * which is why `/discover/long-short` laid its index table out 1673px wide in a
 * 1156px column. A class collision does not look like a styling difference. It
 * looks like a broken page.
 *
 * Each block below reverses exactly what the base's BARE rule for that class
 * sets, and nothing else, at zero specificity. */

:where(#vct-route:not(:has([data-vct-design]))) .row { display: revert; align-items: revert; gap: revert; flex-wrap: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .panel { background: revert; border: revert; border-radius: revert; min-width: revert; overflow: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .link { color: revert; font-size: revert; white-space: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .callout { padding: revert; background: revert; border: revert; border-radius: revert; font-size: revert; color: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .callout p { font-size: revert; margin-top: revert; line-height: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .callout strong { color: revert; font-weight: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .asset { display: revert; align-items: revert; gap: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .asset strong { font-size: revert; font-weight: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .asset .sub { display: revert; font-size: revert; color: revert; margin-top: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .btn { display: revert; align-items: revert; justify-content: revert; gap: revert; border: revert; border-radius: revert; padding: revert; font-size: revert; line-height: revert; background: revert; white-space: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .btn svg { width: revert; height: revert; }

/* base: .chart{width:100%;height:auto;overflow:visible} .chart text{font-size:11px}
 *       .chart .gridline{stroke:var(--line);…} .chart-large{min-height:150px}
 *
 * Found by tests/shell/route-guard.test.ts, not by a person reading: `.chart` is
 * B5's chart component AND a class the base defines, and it only reaches the slot
 * on the chart module's own probe pages, so the first sweep over `npm run build`
 * alone did not see it. That is the check doing exactly what C-23 asks of it. */
:where(#vct-route:not(:has([data-vct-design]))) .chart { width: revert; height: revert; overflow: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .chart text { font-size: revert; }
:where(#vct-route:not(:has([data-vct-design]))) .chart .gridline { stroke: revert; stroke-width: revert; stroke-dasharray: revert; }

/* == 5 == U17 · the chain mark's disc, now that there is a mark to draw =====
 *
 * The base is `.coin{color:var(--coin,var(--green))}` — with no `--coin` set it falls back to the
 * IDENTITY GREEN, and DL-01 gives that colour three jobs, none of them on a surface carrying a
 * value. W3 measured it painted 25 times on the shipped Discover board and bound `--coin` for the
 * ONE state the disc then had: `data-mark="fallback"`, the `#` placeholder.
 *
 * U2's contract gave every chain a name and a sprite, so the disc now carries `data-mark="base"`,
 * `"bsc"`, `"eth"`, `"arb"` — and every one of them walked straight back into the identity green.
 * This binds the variable for ANY declared mark, which is every value the attribute can take.
 *
 * MUTED INK AND NOT THE CHAIN'S ACCENT, deliberately. `src/shell/identity.ts` carries the whole
 * argument: a chain accent token is a second colour claim inside a row of values, and the chain is
 * identified by its SHAPE and its NAME, which is what doc 11 §3.5 asks for. */
.coin[data-mark] { --coin: var(--subtle, var(--t3)); }

/* ===========================================================================
 * U21 · FINISH-SPEC §2 · the shell: a full-width top bar (brand, search, account), the menu and
 * the chain filter in the sidebar, the footer under every page. Brand colours (R-116): lime
 * the site's accent green; declared once in src/styles/brand.css.
 * ======================================================================== */
.navlink.active { background: var(--brand-active); color: var(--green) }
.btn.primary, .btn--primary { background: var(--green); color: var(--brand-on); border-color: var(--green); font-weight: 600 }

.app { grid-template-columns: 216px minmax(0, 1fr); grid-template-rows: auto 1fr }
.app > .topbar { grid-column: 1 / -1; position: sticky; top: 0; z-index: 30; background: var(--bg); gap: 24px; height: 64px; padding: 0 24px; justify-content: flex-start }
.topbar .brand { display: flex; align-items: center; gap: 8px; flex-shrink: 0; width: auto; min-width: 168px }
.topbar .brand img { max-width: none }
.brand__mark { height: 22px; width: auto; display: block }
.brand__word { height: 15px; width: auto; display: block }
.topbar .right { margin-left: auto; flex-shrink: 0 }
.signin { padding: 8px 14px }
.account { display: inline-flex; align-items: center; gap: 8px; padding: 6px 10px; border-radius: 8px; border: 1px solid var(--line2); color: var(--text); font-size: 13px; text-decoration: none }
.account__plan { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--line2); color: var(--muted) }
.account__plan--trader, .account__plan--pro { border-color: var(--green); color: var(--green) }

.search { position: relative; flex: 1; min-width: 0; max-width: 760px; display: flex; align-items: center }
.search__icon { position: absolute; left: 12px; width: 16px; height: 16px; color: var(--subtle); pointer-events: none }
.search__input { width: 100%; height: 40px; padding: 0 14px 0 38px; border-radius: 8px; border: 1px solid var(--line2); background: var(--panel); color: var(--text); font: inherit; font-size: 13px }
.search__input::placeholder { color: var(--subtle) }
.search__input:focus { outline: 2px solid var(--green); outline-offset: 1px; border-color: transparent }
.search__suggest { position: absolute; top: 46px; left: 0; right: 0; margin: 0; padding: 6px; list-style: none; background: var(--panel); border: 1px solid var(--line2); border-radius: 8px; box-shadow: var(--brand-shadow); z-index: 40; max-height: 360px; overflow-y: auto }
.search__option a { display: flex; justify-content: space-between; gap: 12px; padding: 9px 10px; border-radius: 6px; font-size: 13px }
.search__option.is-selected a, .search__option a:hover { background: var(--panel2); color: var(--text) }
.search__option .muted { font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }

.sidebar { padding-top: 22px }
.chains__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px }
.chains .chain__btn { display: flex; flex-direction: row; justify-content: flex-start; align-items: center; gap: 10px; padding: 8px 11px; border: 0; border-radius: 6px; font-size: 12px; color: var(--muted); opacity: 1 }
.chains__list { display: grid; grid-template-columns: 1fr; gap: 2px }
a.chain__btn:hover { background: var(--panel2) }
.chain__btn[aria-current="true"] { background: var(--brand-active); color: var(--green) }
.chain__logo { width: 18px; height: 18px; border-radius: 50%; flex-shrink: 0; display: block }
.chains .chain__btn--soon { cursor: default; opacity: .75 }
.chain__soon { margin-left: auto; font-size: 11px; letter-spacing: .6px; text-transform: uppercase; border: 1px solid var(--line2); border-radius: 4px; padding: 1px 5px; color: var(--subtle) }
.coin--logo { background: none; border: 0 }
.coin--logo img { width: 70%; height: 70%; border-radius: 50%; display: block }

.workspace { display: flex; flex-direction: column; min-height: calc(100vh - 64px) }
.workspace > .content { flex: 1; width: 100% }
.workspace > .footer { margin: 0; padding: 18px 34px 24px; display: flex; flex-wrap: wrap; align-items: center; gap: 10px 22px; font-size: 11px; color: var(--subtle); border-top: 1px solid var(--line) }
.footer__brand { display: flex; align-items: center; gap: 8px; color: var(--muted) }
.footer__labs { height: 20px; width: auto; display: block }
.footer__links { display: flex; flex-wrap: wrap; gap: 8px; align-items: center }
.footer__links a { color: var(--muted) }
.footer__links a:hover { color: var(--green) }
.footer__line { margin-left: auto }
.riskfree { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border-radius: 999px; border: 1px solid var(--brand-badge-line); background: var(--brand-badge); color: var(--green); font-size: 11px }

/* FINISH-SPEC §1 · rule 1: a header's definition is a tooltip — hover, or tap (focus) on a phone. */
.tip { position: relative; cursor: help; text-decoration: underline dotted color-mix(in srgb, currentColor 45%, transparent); text-underline-offset: 3px }
.tip:hover::after, .tip:focus::after, .tip:focus-visible::after {
  content: attr(data-tip); position: absolute; top: calc(100% + 6px); left: 0; z-index: 35; width: max-content; max-width: 280px;
  white-space: normal; text-transform: none; letter-spacing: normal; font-size: 12px; font-weight: 400; line-height: 1.45;
  color: var(--text); background: var(--brand-tip); border: 1px solid var(--line2); border-radius: 6px; padding: 8px 10px; box-shadow: var(--brand-shadow) }
th.r .tip:hover::after, th.r .tip:focus::after, .r .tip:hover::after, .r .tip:focus::after { left: auto; right: 0 }
.tip:focus { outline: none }
.tip:focus-visible { outline: 2px solid var(--green); outline-offset: 3px }
/* rule 3: a missing value is a muted dash */
.dash { color: var(--subtle) }
/* rule 4: one sentence and an action */
.empty { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 34px 20px; text-align: center; color: var(--muted) }
.empty__line { font-size: 13px; max-width: 520px }
.empty__art { max-height: 160px; width: auto }

@media (max-width: 1200px) { .app { grid-template-columns: 185px minmax(0, 1fr) } .topbar .brand { width: auto } }
@media (max-width: 650px) {
  .app { display: block }
  .app > .topbar { height: auto; flex-wrap: wrap; padding: 10px 14px; gap: 10px }
  .topbar .brand { order: 1 }
  .topbar .right { order: 2 }
  .search { order: 3; flex-basis: 100%; max-width: none }
  .sidebar { padding: 10px 14px }
  .chains { margin-top: 8px }
  .chains .navlabel { display: none }
  .chains__list { display: flex; flex-wrap: nowrap; overflow-x: auto; gap: 6px }
  .chains .chain__btn { white-space: nowrap; padding: 6px 9px; font-size: 11px; flex-shrink: 0 }
  .chain__soon { margin-left: 4px }
  .workspace { min-height: 0 }
  .workspace > .footer { padding: 16px 18px 22px; flex-direction: column; align-items: flex-start }
  .footer__line { margin-left: 0 }
  .tip:hover::after, .tip:focus::after { max-width: 220px }
}
/* the search's submit button is for assistive technology and the keyboard; it paints nothing */
.search button.vh { background: none; border: 0; color: inherit }
