/* VVVX — the shell every page wears.
 *
 * This file exists because the five pages each carried their own copy of the
 * tokens, header, footer and buttons. They had already drifted, and a rebrand
 * or a phone-layout fix meant editing the same rule five times and missing one.
 * Everything below is shared by two or more pages; anything used once stays in
 * that page's own <style> block.
 *
 * One committed dark world: near-black ground, VVVX red. There is no light
 * theme on purpose — the brand is a red glow on black, and a naive inversion
 * would make the accent unreadable. Every colour is painted explicitly so the
 * page never borrows a host's background.
 */

:root {
  /* Declared, not inherited: scrollbars, form-control internals, autofill and
     the caret follow it. This site has no light theme. */
  color-scheme: dark;

  /* ground and panels. Every foreground below was measured against all three
     of --bg, --card and --card-hi (the lightest surface text sits on), not
     just the page: a colour tuned on the page alone passes there and fails
     inside a raised card. */
  --bg:        #07070A;
  --bg-2:      #0E0E12;
  --card:      #121217;
  --card-hi:   #1A1A21;
  --line:      #26262F;
  --line-hi:   #34343F;
  /* The rail sits a shade below the page. */
  --side-bg:   #050507;

  /* text -- ratios are the worst of bg / card / card-hi */
  --fg:        #F4F4F6;   /* 15.75 */
  --muted:     #A3A3AD;   /* 6.92 */
  --dim:       #8A8A94;   /* 5.06 */
  --fg-2:      #D4D4DA;   /* 11.72 -- long-form prose, softer than --fg */
  --warn-fg:   #F5C46B;   /* 10.70 */

  /* brand. On a dark ground "hi" means BRIGHTER. --accent is also a text
     colour (links, the hero's emphasis) and clears AA on all three grounds;
     --accent-btn / --accent-deep are button GROUNDS, measured with their own
     white label rather than against the page. */
  /* The brand red #E8141C is 3.75:1 on --card-hi, so it cannot be a TEXT
     colour here. It is the button ground (--accent-btn, white label 4.62);
     --accent, the text/edge red, is the next step up that clears AA. Any
     rule that puts a label ON the red uses --accent-btn, never --accent. */
  --accent:      #FF2E36;   /* 4.69 worst (card-hi) */
  --accent-hi:   #FF4A50;   /* 5.23 worst -- emphasis, focus ring */
  --accent-btn:  #E8141C;   /* white on it 4.62 */
  --accent-deep: #C20F16;   /* white on it 6.22 */
  --on-accent:   #FFFFFF;
  --glow:        color-mix(in srgb, var(--accent) 30%, transparent);
  --glow-soft:   color-mix(in srgb, var(--accent) 12%, transparent);

  /* market direction */
  --up:    #22C55E;   /* 7.59 -- a label ON it is dark (--bg), not white */
  --down:  #F04444;   /* 4.63 */
  /* The brighter red, for red text sitting on a red TINT rather than on the
     card itself. --down is 4.99:1 on --card and only 4.36:1 once the ground
     carries 14% of itself, which is how .tag.sell and .impactwarn are built;
     --down-hi is 5.88:1 there. Same relation --accent-hi has to --accent, and
     it replaces the pre-theme rgb(255,107,107) two pages had hardcoded. */
  --down-hi: #FF6B6B; /* 7.25 on --bg, 6.73 on --card */
  --warn:  #F5A524;   /* 8.48 -- likewise */

  /* ── the radius scale ──────────────────────────────────────────────────
   * Three steps for everything that is not an avatar. It was five, by
   * accident: .tag 5, .ca 7, .chip 9, .btn and .field 10, cards 12 -- close
   * enough that no two ever looked deliberate, and far enough apart that a
   * button beside a chip looked like two components from two kits. Each step
   * is now a size of thing rather than a number somebody typed:
   *   --r-sm  a word          tag, badge, code chip, small icon button
   *   --r-md  a control       button, field, input, nav row, menu row
   *   --r     a surface       card, panel, toast, popover, empty box
   *   --r-lg  a page panel    the AI page and the two hero banners
   * Avatars and coin tiles keep their own radii: they frame a picture, and
   * they are sized in the same breath (34px at 10, 56px at 50%). */
  --r-sm: 6px;
  --r-md: 10px;
  --r:    12px;
  /* Half the old weight. At .07 the 40px grid was 1.11:1 against the page
     and the card border 1.25:1 -- a background pattern competing with the
     object boundaries, which is the visual signature of a template. */
  --grid: rgba(255, 255, 255, .022);
  --r-lg: 18px;
  --sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --sans-alt: Inter, ui-sans-serif, system-ui, sans-serif;
  --mono: ui-monospace, "SFMono-Regular", "JetBrains Mono", Menlo, Consolas, monospace;

  --gut: 26px;
  --top-h: 68px;
  /* 276px came from the reference concept and was never measured against
     what this rail actually holds: seven labels, the longest of which is
     "Payments". At that width a third of the column is empty and the page
     pays for it on every screen. */
  --side: 218px;
}

* { box-sizing: border-box; }

/* The browser hides [hidden] with a UA rule, and ANY author rule that sets
   display beats a UA rule whatever its specificity. .btn below sets
   display:inline-flex, which silently un-hid every button the scripts hide this
   way -- the trade panel was offering "Approve AVAX" while paying in native
   AVAX, where there is nothing to approve. Restate it as an author rule. */
[hidden] { display: none !important; }

body {
  margin: 0;
  /* The ruled ground. Two hairline gradients, so it costs no image and scales
     with the page; the paper colour underneath is the token. */
  background-color: var(--bg);
  background-image:
    radial-gradient(900px 480px at 58% -12%, rgba(232, 20, 28, .13), transparent 62%),
    radial-gradient(580px 360px at 100% 18%, rgba(232, 20, 28, .06), transparent 70%),
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: auto, auto, 40px 40px, 40px 40px;
  background-attachment: fixed, fixed, scroll, scroll;
  color: var(--fg);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  /* A wide table or chart must scroll inside its own box, never take the page
     sideways with it. */
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
button, input, select, textarea { font-family: inherit; }
img { max-width: 100%; }
:focus-visible { outline: 2px solid var(--accent-hi); outline-offset: 2px; }

.wrap { max-width: 1260px; margin: 0 auto; padding: 0 var(--gut); }

/* ── the shell: a left rail, done in CSS ─────────────────────────────────
 *
 * Every page already ships `header.top`, `main.wrap` and `footer` as siblings,
 * and `.top-in` already holds the three things a sidebar wants in the order it
 * wants them: brand, navigation, wallet. So the rail is a grid on <body>
 * rather than eleven files of restructured markup -- which also means the
 * phone layout below can fold the very same DOM back into a top bar.
 *
 * The bottom nav stays outside the grid: it is `position: fixed`.
 */
@media (min-width: 981px) {
  body {
    display: grid;
    grid-template-columns: var(--side) minmax(0, 1fr);
    grid-template-rows: 1fr auto;
    min-height: 100vh;
  }
  .top    { grid-column: 1; grid-row: 1 / -1; }
  main    { grid-column: 2; grid-row: 1; }
  footer  { grid-column: 2; grid-row: 2; }

  .top {
    position: sticky; top: 0; align-self: start;
    height: 100vh; z-index: 40;
    background: var(--side-bg);
    backdrop-filter: blur(18px);
    border-right: 1px solid var(--line);
    padding: 22px 14px;
  }
  .top-in {
    display: flex; flex-direction: column; align-items: stretch;
    gap: 22px; height: 100%; max-width: none; padding: 0;
  }
  .top .mark { padding: 0 8px 20px; border-bottom: 1px solid var(--line); }

  /* Vertical, and every item a full-width hit area rather than a word.
     An icon each, because a column of six bare words reads as a list of links
     somebody forgot to finish -- the eye has nothing to land on and every
     destination weighs the same. */
  .top nav {
    /* display:flex, which was missing: flex-direction and gap do nothing on a
       block box, so the 1px gap was inert and the rows only lined up because
       each <a> is itself a flex container. */
    display: flex; flex-direction: column; align-items: stretch; gap: 1px;
    overflow: visible; font-size: 13.5px;
  }
  .top nav a {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 10px; border-radius: var(--r-md); width: 100%;
    color: var(--muted); font-weight: 500;
    transition: background .14s, color .14s;
  }
  .top nav .ico {
    width: 18px; height: 18px; flex: none;
    display: grid; place-items: center; color: var(--dim);
    transition: color .14s;
  }
  .top nav .ico svg { width: 17px; height: 17px; display: block; }
  .top nav a:hover { background: var(--card-hi); color: var(--fg); }
  .top nav a:hover .ico { color: var(--muted); }
  /* The selected item gets the accent on the ICON and a tinted ground, not a
     sliver of colour at the edge -- the 2px inset bar was clipped by the
     border radius and read as a rendering fault. */
  .top nav a[aria-current] {
    background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 13%, transparent), color-mix(in srgb, var(--accent) 4%, transparent));
    color: var(--accent-hi); font-weight: 600;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent);
  }
  .top nav a[aria-current] .ico { color: var(--accent-hi); }
  /* The underline belonged to a horizontal bar. */
  .top nav a[aria-current]::after { display: none; }

  /* Room around the three bands, and a wordmark that is not crammed against
     the top edge of the window. */
  .top { padding: 18px 12px 16px; }
  /* 10px, not 6px: the nav rows are inset 10px and their icons land at
     x=22, so a 6px inset put the glyph at x=18 and every icon below it
     four pixels to the right of the mark. */
  .top .mark { padding: 0 10px 15px; }
  /* Size and tracking are the base rule's now. What is left here is the rail's
     own problem: in a 218px column the strapline broke to three lines under the
     wordmark, so it is capped and allowed to wrap on purpose at two. */
  .top .mark .sub { max-width: 15ch; line-height: 1.35; }
  .top-in { gap: 15px; }
  /* The wordmark does not need display size in a rail; it is a label, not a
     headline, and the strapline under it is set at 7.5px anyway. */
  .top .mark .glyph { width: 28px; height: 28px; }
  .top .mark .word { font-size: 17.5px; letter-spacing: -.5px; }

  /* Wallet and network drop to the bottom of the rail, stacked. */
  .top-right {
    margin-left: 0; margin-top: auto; flex-direction: column;
    align-items: stretch; gap: 8px;
    border-top: 1px solid var(--line); padding-top: 16px;
  }
  .top-right .btn { width: 100%; min-height: 40px; font-weight: 600; }
  /* The chain picker is a 999px pill with a 3px ring everywhere else on the
     site, which is right for a standalone control and wrong directly above a
     10px-radius button: the ring made it optically wider than the thing it
     was stacked on. Same corner, same height, no ring -- in the rail only. */
  .top-right .chain-btn { width: 100%; min-height: 40px; border-radius: var(--r-md);
                          box-shadow: none; justify-content: flex-start; }

  /* The page keeps its own gutter but no longer centres against the viewport:
     inside a rail, a 1260px column centred on the REMAINING width drifts. */
  main.wrap, footer .wrap { max-width: 1180px; margin: 0; padding: 26px var(--gut) 0; }
  footer .wrap { padding-top: 0; }
}

/* Below the breakpoint the same DOM is a top bar again. */
@media (max-width: 980px) {
  .top {
    position: sticky; top: 0; z-index: 40;
    background: rgba(7, 7, 10, .92);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--line);
  }
  .top-in { display: flex; align-items: center; gap: 30px; min-height: var(--top-h); }
  /* A horizontal bar has no room for them and they would push the last link
     off the edge; the labels carry it there. */
  .top nav .ico { display: none; }
}

/* ── wordmark ────────────────────────────────────────────────────────────
 * VVVX, all white and uppercase (the spec's wordmark): the two halves differ
 * only in weight, and are one word, so they never wrap apart. */
.mark { display: flex; align-items: center; gap: 10px; flex: none; }
/* The mark is one file referenced everywhere rather than SVG pasted into ten
   headers, so it is cached once and only ever edited in one place. */
.mark .glyph { width: 34px; height: 34px; flex: none; display: block; border-radius: 8px;
               filter: drop-shadow(0 0 8px var(--glow)); }
/* The nav's two labels for one destination. The short one exists for widths
   under 400px and is hidden everywhere else; see the @media at the end. */
.nv-short { display: none; }

.mark .word { font-weight: 800; font-size: 21px; letter-spacing: -.6px; white-space: nowrap; text-transform: uppercase; }
.mark .word i { font-style: normal; color: var(--fg); font-weight: 500; }
.mark .word b { font-weight: 800; color: var(--fg); }
/* 9px, not 7.5px. The rail block above already said 7.5px with 1.6px of
   tracking is under the legibility floor and lifted it — but only from 981px
   up, and the ≤640 block hides the strapline altogether, so the one range that
   still rendered it was 641–980px: a top bar, at the size the comment calls
   illegible. One value, everywhere it is shown. */
.mark .sub {
  display: block; font-size: 9px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--dim); margin-top: 1px;
}

/* min-width:0 and the scroll are the backstop, not the design. A flex item's
   automatic minimum size is its content, so without this the nav refuses to
   shrink and shoves the header past the viewport instead -- and because
   .top-in is centred, the overflow splits and the wordmark goes off the LEFT
   where `overflow-x: hidden` on body eats it with no scrollbar to get it back.
   The rule below is what should normally catch it; this is here so a sixth
   link can never break the page again, only make the nav scroll. */
/* SCOPED to the phone bar. These are the horizontal-nav rules, and they used
   to sit at top level BELOW the rail's own rules -- same specificity, later in
   the file, so they won every one of them. The rail has been rendering with
   gap:26px and padding:4px 0 since the day it was built, which is why it read
   as a loose column of words with no inset, and why tightening the numbers up
   there changed nothing at all. A media query adds no specificity; only order
   and scope decide this. */
@media (max-width: 980px) {
  .top nav { display: flex; align-items: center; gap: 26px; font-size: 14.5px; color: var(--muted);
             min-width: 0; overflow-x: auto; scrollbar-width: none; }
  .top nav::-webkit-scrollbar { display: none; }
  .top nav a { flex: none; position: relative; padding: 4px 0; transition: color .15s; }
  .top nav a:hover { color: var(--fg); }
  .top nav a[aria-current] { color: var(--fg); font-weight: 600; }
  .top nav a[aria-current]::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: -22px; height: 2px;
    background: var(--accent); border-radius: 2px; box-shadow: 0 0 10px var(--glow);
  }
}
.top-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }

/* ── buttons ─────────────────────────────────────────────────────────── */
.btn {
  border-radius: var(--r-md); padding: 10px 16px; font: 600 14px var(--sans); cursor: pointer;
  background: var(--card-hi); color: var(--fg); border: 1px solid var(--line-hi);
  transition: background .15s, border-color .15s, color .15s;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
/* Was `background:#22222C; border-color:#43434F` -- the dark theme's, hard
   coded. On this ground it painted a near-black slab under --fg text: 1.19:1,
   the label simply disappeared. The state now lives in the BORDER, which is
   how .chip and .tok already signal hover. */
.btn:hover { background: var(--bg-2); border-color: var(--accent); }
/* `opacity:.45` faded the element, so a white label faded with the ground it
   sits on: 1.59:1, measured, on the Buy and Launch buttons -- both of which
   are disabled by DEFAULT, before a wallet connects. A disabled control has
   to stay readable; it just must not look pressable. */
.btn:disabled { opacity: 1; cursor: not-allowed;
                background: var(--card-hi); color: var(--dim); border-color: var(--line); }
.btn:disabled:hover { background: var(--card-hi); border-color: var(--line); }
.btn-primary:disabled {
  background: color-mix(in srgb, var(--accent) 26%, var(--card));
  color: var(--accent-hi);                       /* 6.64:1 on that ground */
  border-color: color-mix(in srgb, var(--accent) 45%, var(--card));
  box-shadow: none;
}
.btn-primary:disabled:hover { background: color-mix(in srgb, var(--accent) 26%, var(--card));
                              border-color: color-mix(in srgb, var(--accent) 45%, var(--card)); }
.btn:disabled:hover { background: var(--card-hi); border-color: var(--line-hi); }
.btn-primary {
  background: linear-gradient(180deg, var(--accent-btn), var(--accent-deep));
  color: var(--on-accent); border-color: var(--accent-deep); font-weight: 700;
  box-shadow: 0 8px 24px -12px var(--glow);
}
.btn-primary:hover {
  /* Darker on hover, not lighter. It used to lift to #7AD4FF -- a pale cyan
     carrying a white label, which was already thin on the dark theme and is
     invisible on this one. */
  background: linear-gradient(180deg, var(--accent-deep), var(--accent-btn));
  border-color: var(--accent-hi);
}
.btn-primary:disabled:hover { background: linear-gradient(180deg, var(--accent-btn), var(--accent-deep)); }
/* Connected, but the wallet is on another network: not an error, and not the
   ordinary connected state either. Amber rather than red, because nothing has
   gone wrong yet — pressing it fixes the situation. */
.btn-warn {
  background: color-mix(in srgb, var(--warn) 16%, var(--card));
  color: var(--warn); border-color: var(--warn); font-weight: 700;
}
.btn-warn:hover {
  background: color-mix(in srgb, var(--warn) 26%, var(--card));
  color: var(--warn); border-color: var(--warn);
}

/* The chain switcher's closed state. The open menu is built in ui.js and uses
   the same panel as the wallet menu, so the two dropdowns in this header are
   one design. A native <select> was tried first and is why: its menu is drawn
   by the OS, so on a dark page it opens as a white panel with a blue highlight
   and the system font, and no amount of `appearance:none` reaches it. */
.chain { position: relative; display: inline-flex; }
.chain-btn {
  --ctint: var(--accent);
  appearance: none; display: inline-flex; align-items: center; gap: 8px;
  font: 600 14px var(--sans); color: var(--fg);
  background: var(--card); border: 1.5px solid color-mix(in srgb, var(--ctint) 70%, transparent);
  border-radius: 999px; padding: 6px 12px 6px 7px; white-space: nowrap; cursor: pointer;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ctint) 14%, transparent);
  transition: border-color .15s, background .15s, box-shadow .15s;
}
.chain-btn:hover, .chain-btn[aria-expanded="true"] {
  background: var(--card-hi); border-color: var(--ctint);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--ctint) 22%, transparent);
}
.chain-btn .lbl { font-weight: 500; color: var(--dim); font-size: 12.5px; }
.chain-btn .cmark { width: 22px; height: 22px; border-radius: 50%; flex: none; object-fit: contain; }
.chain-btn i { width: 10px; height: 10px; margin: 0 6px; border-radius: 50%; background: var(--ctint);
               box-shadow: 0 0 8px var(--ctint); flex: none; }
.chain-btn .caret { width: 14px; height: 14px; flex: none; opacity: .75; margin-left: 2px; transition: transform .15s; }
.chain-btn[aria-expanded="true"] .caret { transform: rotate(180deg); }

/* ── shared atoms ────────────────────────────────────────────────────── */
.card {
  /* Two shadows, not one. The single wide blur was doing an elevation job
     with no contact: -18px of spread on a 30px blur left almost nothing at
     the edge. The 1px contact shadow is what makes a surface read as RESTING
     on the page rather than hovering somewhere above it. */
  box-shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 16px -10px rgba(0, 0, 0, .6);
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r); }

.badge {
  font-size: 9.5px; font-weight: 700; letter-spacing: .7px; text-transform: uppercase;
  border: 1px solid var(--line-hi); border-radius: var(--r-sm); padding: 3px 6px; color: var(--muted);
}
.tag {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted);
  border: 1px solid var(--line); border-radius: 999px; padding: 5px 11px; background: var(--card);
}
.pill {
  background: var(--card-hi); border: 1px solid var(--line); border-radius: 999px;
  padding: 6px 14px; font-size: 13px; color: var(--muted); font-weight: 500;
}
.chip {
  border: 1px solid var(--line); background: transparent; border-radius: var(--r-md); padding: 7px 14px;
  font: 500 13px var(--sans); color: var(--muted); cursor: pointer;
  transition: border-color .15s, color .15s, background .15s; white-space: nowrap;
}
.chip:hover { border-color: var(--line-hi); color: var(--fg); }
.chip[aria-pressed="true"] {
  background: var(--accent-btn); border-color: var(--accent-btn); color: var(--on-accent); font-weight: 700;
  box-shadow: 0 6px 18px -10px var(--glow);
}
.seg {
  background: transparent; border: 1px solid transparent; border-radius: var(--r-md); padding: 7px 13px;
  font: 500 13px var(--sans); color: var(--muted); cursor: pointer; white-space: nowrap;
}
.seg:hover { color: var(--fg); }
.seg[aria-pressed="true"] {
  background: var(--accent-btn); color: var(--on-accent); font-weight: 700;
  box-shadow: 0 6px 18px -10px var(--glow);
}

.av {
  width: 36px; height: 36px; border-radius: 10px; flex: none; display: grid; place-items: center;
  font-size: 17px; background: var(--card-hi); border: 1px solid var(--line-hi); overflow: hidden;
}
/* A pair asset's logo, wherever one is shown. */
.sk-pair { width: 100%; height: 100%; object-fit: contain; border-radius: 50%; display: block; }

.up { color: var(--up); }
.down { color: var(--down); }
.num { font-variant-numeric: tabular-nums; }

/* Marks a figure derived from DEX prices rather than an oracle. */
.est {
  font-size: 9.5px; font-weight: 600; letter-spacing: .4px; text-transform: uppercase;
  color: var(--warn); margin-left: 5px; vertical-align: middle;
}
.demo {
  display: inline-block; font-size: 10px; font-weight: 700; letter-spacing: .7px;
  text-transform: uppercase; color: var(--warn); background: color-mix(in srgb, var(--warn) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--warn) 30%, transparent); border-radius: var(--r-sm); padding: 2px 7px; vertical-align: 2px;
}

.note { margin: 30px 0 10px; font-size: 12.5px; color: var(--dim); line-height: 1.7; max-width: 88ch; }
/* ── the one empty state ─────────────────────────────────────────────────
 *
 * An empty or loading slot is a piece of design, not a leftover string: a
 * frame that says "content belongs here and is not here yet", which is the
 * one place a DASHED edge is correct. Given height, so the page does not jump
 * when the rows land.
 *
 * It lives HERE and not in js/ui.js, although ui.js's empty() is what builds
 * most of them. Three pages ship a "Loading…" row in their static markup,
 * before a line of script runs, and while the box was injected by ui.js those
 * rows could not wear it -- which is exactly how /token ended up with a dashed
 * box under its chart and four bare floating words in the table beneath it.
 * One definition, reachable from markup and from script. */
.sk-empty {
  /* Spans the row: dropped into a coin grid this is the state of the PAGE,
     and one column wide it reads as a broken card among real ones. */
  grid-column: 1 / -1;
  display: grid; place-items: center; gap: 4px;
  min-height: 160px; padding: 32px 24px; text-align: center;
  color: var(--dim); font-size: 14px; line-height: 1.7;
  /* --muted, not --line-hi. The dashed edge is the whole visual idea of an
     empty state and at #34343F on --bg-2 it measured 1.57:1 -- not a soft
     border, an absent one. It also sits on two different backgrounds (page
     and card), so it is a colour that works on both rather than one tuned to
     either. */
  background: var(--bg-2); border: 1px dashed var(--muted); border-radius: var(--r);
}
.sk-empty b { display: block; color: var(--fg); font-size: 16px; font-weight: 600;
              margin-bottom: 3px; letter-spacing: -.3px; }
.sk-empty .sk-empty-do { margin-top: 10px; }
/* was an inline style="color:var(--accent)" on each caller's <a>; the body is
   built from parts now, so the stylesheet carries it. */
.sk-empty a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }

/* The same box as a table row. A <td> cannot BE the box: every table on this
   site is `border-collapse: collapse`, which throws border-radius away. So the
   cell gives up its own padding, border and alignment and the box goes inside
   it -- `!important` because a full-width message cell is, by definition, also
   the table's LAST cell, and every table here right-aligns that one for its
   figures column. */
td.empty, .tbl td.empty, table.tbl td.empty, table.an td.empty {
  padding: 4px 0 !important; border: 0 !important; text-align: left !important;
}
/* On a phone a table wider than the screen scrolls sideways, which is fine for
   rows of data and wrong for a message: centred inside a 620px table, "Reading
   the chain…" lands at x=310, past the right edge of a 375px screen. Starting
   it where the scroll starts keeps it on screen. */
@media (max-width: 640px) {
  td.empty > .sk-empty { place-items: center start; text-align: left; }
}

.ca {
  font: 600 10px var(--sans); letter-spacing: .6px; color: var(--dim);
  border: 1px solid var(--line-hi); border-radius: var(--r-sm); padding: 4px 8px;
  background: transparent; cursor: pointer;
}
.ca:hover { color: var(--fg); border-color: var(--accent); }
.ca.done { color: var(--up); border-color: var(--up); }
/* A community link this page refused to make clickable: not https, or not a URL
   at all. It still shows, because the reader should know the coin published
   something — it just does not act like a link, and hovering shows the raw
   value it was given. */
.ca.bad { color: var(--warn); border-style: dashed; cursor: default; }
.ca.bad:hover { color: var(--warn); border-color: var(--line-hi); }

/* Any table wide enough to overflow scrolls inside its own box.
 *
 * That keeps the page from moving sideways, but it also hides the fact that
 * there is more table: on a phone the right-hand columns simply are not there
 * and nothing says to swipe. The mask fades the right edge while the box is
 * scrollable and disappears once it is scrolled to the end, so the affordance
 * is the content itself rather than a caption nobody reads. */
.tblwrap {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  --edge: 28px;
  mask-image: linear-gradient(to right, #000 calc(100% - var(--edge)), transparent);
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--edge)), transparent);
}
.tblwrap.at-end { --edge: 0px; }
@media (min-width: 900px) { .tblwrap { --edge: 0px; } }

/* A contract address is 42 characters with no break opportunity anywhere in it.
   Every place one is printed has to be allowed to break: at 375px a single
   unbroken address drags the whole page sideways, which is how the docs page
   was scrolling to 434px on a phone. */
code, .kv .v, .addr, .mono { overflow-wrap: anywhere; }

/* The same rule, for the same reason, wherever a coin's own name or ticker is
   printed — and this one is hostile input, not just long input. The contract
   takes any 32 characters, so a coin can be named with no space in it at all,
   and one launched that way pushed a 375px phone out to 800px on every page
   that showed it. Nobody has to be attacked for this to happen, but anybody
   could do it deliberately, which puts it in the same class as the escaping in
   js/ui.js: chain text is untrusted, in layout as well as in markup.

   break-word, NOT anywhere. The two break a long word identically; they differ
   in whether those break opportunities count towards the element's min-content
   width. `anywhere` says they do, which inside a table lets the column collapse
   to one character wide: "Avalanche Doge" came out as a vertical stack of
   single letters in the portfolio. `break-word` breaks the word that would
   overflow and leaves the column sized by its longest word, which is what a
   name column wants. */
#tName, #tTick, #pNm, #pTk,
.tick, .nm, .sym, .coin .nm, .coin .tk, .asset .sub {
  overflow-wrap: break-word;
}

/* ── page head, shared by create / docs / portfolio ──────────────────── */
.phead { margin: 34px 0 26px; }
.phead h1 { margin: 0; font-size: 42px; font-weight: 800; letter-spacing: -2px;
            line-height: 1.05; text-wrap: balance; }
.phead p { margin: 12px 0 0; color: var(--muted); max-width: 62ch; }

/* ── footer ──────────────────────────────────────────────────────────── */
footer { border-top: 1px solid var(--line); margin-top: 56px; padding: 26px 0 46px; }
.foot { display: flex; gap: 22px; align-items: center; flex-wrap: wrap; font-size: 13px; color: var(--dim); }
.foot a:hover { color: var(--fg); }
.foot-mark .glyph { width: 24px; height: 24px; border-radius: 6px; }
.foot-mark .word { font-size: 16px; }
.foot-mark .sub { display: none; }
.foot .sp { margin-left: auto; }
/* Clear of the AI button: it is fixed in this corner on every page and was
   covering the chain id, which read as "Base . 845". */
@media (min-width: 641px) { .foot .sp { padding-right: 72px; } }
/* The X link (only when SITE.x is set) sits with the chain line rather than
   in its own row: one social account does not need a strip of icons, and a
   lone icon with no label reads as decoration. */
.foot .sp { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.foot .x { display: inline-flex; align-items: center; gap: 6px; }
.foot .x:hover { color: var(--accent); }
.foot .dot { color: var(--line-hi); }


/* ── responsive ──────────────────────────────────────────────────────────
 * Three real layouts, not one design squeezed: desktop, tablet (<=1024) and
 * phone (<=640). The nav never disappears — a site you cannot navigate on a
 * phone is broken, not minimal. */

/* tablet */
@media (max-width: 1024px) {
  :root { --gut: 18px; }
  .phead h1 { font-size: 34px; letter-spacing: -1.4px; }
}
/* The header-bar half of the rule above, scoped to where the header IS a bar.
   Between 981 and 1024 it used to override the rail's own gap and type size,
   because the rail exists there and these rules did not know it. */
@media (max-width: 980px) {
  .top-in { gap: 20px; }
  .top nav { gap: 20px; font-size: 14px; }
}

/* The nav drops to its own row before it can collide with the wallet button.
   This said 900px and was simply wrong. Measured: the one-row header needs
   979px here and 1033px on the sibling site that shares this file, so every
   width from 901 up was pushing the header past the edge -- and .top-in is
   centred, so the overflow split both ways and clipped the wordmark and the
   first nav links off the LEFT, where body's `overflow-x: hidden` eats them
   with no scrollbar to get them back.

   1100 covers both with slack for a longer chain name in the switcher. If the
   header gains a link, re-measure rather than nudge this -- and note
   headerAutoHide() in js/ui.js carries the same number. */
/* 980, not 1100. Everything in this block exists to fold a HORIZONTAL header
   onto two rows, and since the rail landed the horizontal header only exists
   at 980px and below. Left at 1100 it reached into the rail between 981 and
   1100 -- a range that includes iPad landscape -- where it moved the nav below
   the wallet with `order:3`, gave it the bar's negative gutters, and, worst,
   let `.top.tucked nav { display:none }` hide the rail's navigation
   entirely whenever the page scrolled down. js/ui.js headerAutoHide() carries
   the same number and was changed with it. */
@media (max-width: 980px) {
  .top-in { min-height: 0; height: auto; flex-wrap: wrap; padding-top: 11px; gap: 12px 16px; }
  .top nav {
    order: 3; width: 100%; gap: 20px; overflow-x: auto; scrollbar-width: none;
    padding: 4px var(--gut) 10px; margin: 0 calc(-1 * var(--gut));
  }
  .top nav::-webkit-scrollbar { display: none; }
  .top nav a { white-space: nowrap; }
  .top nav a[aria-current]::after { bottom: -4px; }

  /* ── the sixth item ────────────────────────────────────────────────────
   *
   * The nav scrolls sideways, and nothing said so. Measured slack
   * (scrollWidth - clientWidth): 390 -> 0, 375 -> 11, 360 -> 24, 320 -> 66 --
   * so a 390 phone has no margin at all and every smaller one cut the last
   * item, which at 360 read "Doc". A scrollbar is hidden here by design, so
   * the only clue that Docs existed was knowing it existed.
   *
   * Three things, in the order they cost least: "My coins" becomes "Coins"
   * (-20px), the gap tightens to 16 (-20px across five gaps), and what still
   * does not fit fades out at the right edge instead of ending mid-word.
   *
   * The fade is on `:not(.at-end)`, so it appears only while there is more to
   * the right and goes when you reach the end. ui.js already computes that
   * for scrollable tables; the nav is now on the same watch list. */
  .top nav:not(.at-end) {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
    mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
  }
  /* .nv-short's base rule is outside this block on purpose: hidden at EVERY
     width except the one that needs it. Declared only here, the rail at
     >=981px showed both labels and the link read "My coinsCoins". */

  /* Scrolling down drops the nav row; scrolling up brings it straight back.
     The nav is the row to lose, not the wordmark and the wallet button.

     display:none rather than a transform or an animated height. A transform
     would move the whole header, taking the row worth keeping off screen
     instead; an animated height fights nav's own overflow-x, which is what
     makes it scroll sideways when the links do not fit. And because the header
     is sticky, its place in the flow is at the very top of the document — by
     the time this fires the page has scrolled past it, so nothing below moves
     when it shrinks. */
  .top.tucked nav { display: none; }
}

/* phone */
@media (max-width: 640px) {
  /* One row, not two. The wordmark (112px) and the chain picker + wallet
     button (233px) came to 345px against 347 available, so by 14px the
     header folded onto a second line and took 22% of the screen before a
     single word of the page. The word "Network" is ~50px and says nothing
     the coloured dot and the chain name do not -- and the button keeps
     aria-label="Network", so a screen reader still hears it. */
  /* 361px of content against 347 available (wordmark 112, gap 16, picker
     103, gap 8, wallet button 122), so the header folded onto two rows and
     took 22% of the screen. "Network" was already hidden at this width; the
     rest is spacing and one px of type on the two controls, which buys ~25px
     and keeps the chain NAME -- the one thing on the picker that tells you
     where your transaction goes. */
  .top-in { column-gap: 10px; }
  /* Six links now that Analytics is one of them, and at 26px of gap the sixth
     ran off the right edge of a 390px screen into a scroll with no scrollbar.
     Tighter, so the whole row is on screen; the bottom bar carries the three
     that matter one-handed. */
  .top nav { gap: 15px; font-size: 13.5px; }
  .top-right { gap: 6px; }
  .top-right .chain-btn { padding-left: 5px; padding-right: 7px; font-size: 13px; }
  .top-right .btn { padding-left: 11px; padding-right: 11px; font-size: 13px; }
  /* ...and 2px of slack is one font-rendering difference away from folding
     again. A slightly smaller wordmark buys a margin that survives another
     OS's metrics. */
  .top .mark .glyph { width: 28px; height: 28px; }
  .top .mark .word { font-size: 17px; }
  :root { --gut: 14px; }
  body { font-size: 14.5px; }
  /* Kept on phones now that it is a control rather than a label: the switcher
     is the only way off a chain, and the header already wraps at this width. */
  .chain-btn { padding: 5px 10px 5px 6px; font-size: 13px; }
  .top .chain-btn .lbl { display: none; }   /* the logo and name say it; the header has no room
                                            for a label on a phone */
  .mark .glyph { width: 30px; height: 30px; }
  .mark .word { font-size: 19px; }
  .mark .sub { display: none; }
  .btn { padding: 9px 14px; font-size: 13.5px; }
  .phead { margin: 24px 0 20px; }
  .phead h1 { font-size: 28px; letter-spacing: -1.1px; }
  footer { margin-top: 38px; padding: 22px 0 34px; }
  .foot { gap: 14px; font-size: 12.5px; }
  .foot .sp { margin-left: 0; width: 100%; }
  /* The wordmark takes a row of its own, so the five links wrap among
     themselves. Sharing a row with it, they ran out at "Transparency", which
     dropped alone to x=14 while the four above it started at x=121 -- a
     ragged list with no left edge. */
  .foot-mark { flex: 0 0 100%; }
}

/* Under 400 the sixth nav item does not fit; see the note at the nav's own
   rules. "Coins" says the same thing as "My coins" in 20px less, and the gap
   gives back another 20 across five gaps. */
@media (max-width: 400px) {
  .top nav { gap: 16px; }
  .nv-long { display: none; }
  .nv-short { display: inline; }
}

/* The 320px class still exists in the wild (iPhone SE / older Android webviews).
   It is too narrow for the phone header's six-link row at the 360px spacing,
   but it does not need a different layout: a smaller gap and tighter segment
   controls keep the text inside the viewport while the bottom nav carries the
   thumb targets. */
@media (max-width: 340px) {
  .top nav { gap: 8px; font-size: 13px; }
  .seg { padding-left: 10px; padding-right: 10px; }
}

/* 360px is the most common Android width, and at 332px of content the header
   still folded to two rows. Below 370 the chain picker drops its NAME and
   keeps the coloured dot and the caret -- this build serves one chain, the dot
   is that chain's colour, and the button's aria-label still names it. 375 and
   390 keep the name, because they fit it. */
@media (max-width: 370px) {
  .top-right .chain-btn .chain-name { display: none; }
}

@media (max-width: 380px) {
  .mark .word { font-size: 17px; }
  .btn { padding: 8px 12px; font-size: 13px; }
}

/* ── touch targets ───────────────────────────────────────────────────────
 * A fingertip is about 9mm; a mouse pointer is one pixel. Measured at 390px,
 * this site had 28 controls under 40px on the coin page alone and a cluster
 * at 24px — the chart timeframes, the buy/sell slippage buttons and the
 * custom-slippage input among them. Mis-tapping a slippage button on a trade
 * panel costs money, so this is not only a comfort question.
 *
 * min-height rather than padding, so a control grows to a thumb-sized box
 * without its text moving off the baseline it shares with its neighbours.
 *
 * The width fallback goes to 1024, not 640: pointer:coarse is the honest
 * predicate but a tablet at 820px matched neither it (in testing) nor a
 * 640px phone rule, so every iPad-sized viewport fell through the gap and
 * got 26 sub-40px controls. A narrow desktop window picking up thumb-sized
 * buttons is the cheaper mistake of the two. */
@media (pointer: coarse), (max-width: 1024px) {
  /* min-height does nothing to a non-replaced inline box, and most of these are
     <a> or <button> that some page left inline — so each one is given a box
     before it is given a height. */
  .btn, .chip, .cat, .seg, .ca,
  /* The network switcher was 33px. It is the only way off a chain. */
  .chain-btn,
  .tf button, .tabs button, .pw-opts button, .slip-opts button,
  /* Buy and Sell are the two most consequential controls on the site. They
     were 33px. */
  .swaptabs button {
    min-height: 42px; display: inline-flex; align-items: center; justify-content: center;
  }
  /* A link sitting on its own in a panel row, not inside a sentence: it has a
     line box and nothing else, which left "Pharaoh" at 15px.

     34px was the first pass and still missed — a finger needs 44. Growing
     the link grows the row, which is what keeps two stacked rows from handing
     a tap near their shared edge to the wrong one; a 44px hit-area
     pseudo-element would overlap the neighbour instead.

     #lockProof's link is deliberately NOT here any more. It sits mid-sentence,
     where WCAG exempts it and where a 44px inline-flex box prises apart the
     line it lives on. */
  .kv a, .steps a, #tradeOut {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  .slip-opts button, .pw-opts button, .cat { padding-inline: 14px; }
  /* .tf moved out of the padding-inline line above and into this one: it is
     the same underline control as .tabs now, and 14px of side padding on an
     underline widens the RULE under the word, not the word's own box. */
  .tf button, .tabs button { padding-block: 10px; }
  .top nav a, .foot a, .back {
    min-height: 42px; display: inline-flex; align-items: center;
  }
  /* The wordmark is the way back to Explore from every page. */
  .mark { min-height: 42px; }
  .top nav a[aria-current]::after { bottom: 0; }
  input[type="text"], input[type="search"], input[type="number"], select { min-height: 42px; }
  /* A transaction link in a dense table cannot be 42px without doubling the
     height of the table it sits in, but 12px is not a target either. Padding
     inside the cell buys a usable box without moving the text off its row. */
  /* Padding was the wrong lever here: 12px gave 38.7px and 13px gave 39.7px,
     because the line box under a 12px font is 13.7px and the total is padding
     plus that, not padding plus a round number. Stating the height directly
     lands on 44 — what Apple and WCAG AAA both name — and matches how every
     other target in this block is written. Rows tile without gaps, so no tap
     falls between two links. */
  td a, td button {
    display: inline-flex; align-items: center; min-height: 44px;
  }
}

/* ── the iOS zoom guard ──────────────────────────────────────────────────
 * Safari on iPhone zooms the entire page when a focused form control has a
 * font smaller than 16px, and it does not zoom back out. The launch form had
 * nine such fields at 13-14.5px, so every tap on a name, ticker or link field
 * threw the page out of scale, and the trade panel did it on the custom
 * slippage box.
 *
 * !important is deliberate and is the narrowest tool that works: each page
 * sets its own input font with the `font:` shorthand, which is more specific
 * than anything this file can say from outside without it. A page may choose
 * the family and the weight; it may not choose a size that breaks the
 * viewport. 16px is the threshold, not a preference — below it the bug
 * returns. */
@media (pointer: coarse), (max-width: 1024px) {
  input, select, textarea { font-size: 16px !important; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ── bottom bar (phones) ────────────────────────────────────────────────
   A launchpad is used one-handed, and the top nav sits above the fold once
   the page scrolls. Four destinations, thumb height, hidden from 641px up
   where the header nav is always visible. */
.botnav { display: none; }
@media (max-width: 640px) {
  .botnav {
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 140;
    background: rgba(7, 7, 10, .96); backdrop-filter: blur(10px);
    border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom, 0);
  }
  .botnav a {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 4px; min-height: 56px; text-decoration: none;
    color: var(--dim); font: 600 10.5px var(--sans); letter-spacing: .5px; text-transform: uppercase;
  }
  .botnav a[aria-current="page"] { color: var(--accent); }
  .botnav a.mid span.ic {
    background: var(--accent-btn); color: var(--on-accent); border-radius: var(--r);
    width: 40px; height: 28px; display: grid; place-items: center;
  }
  .botnav .ic { display: grid; place-items: center; height: 22px; line-height: 1; }
  .botnav .ic svg { display: block; }
  /* room for the bar, so the last row of content is never under it */
  body { padding-bottom: 64px; }
}


/* For a live region that has something to say and nothing to show. Not
   display:none and not visibility:hidden -- both take the element out of the
   accessibility tree, which is the one thing it is for. */
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ── headings ─────────────────────────────────────────────────────────────
   These used to be UPPERCASE, and the reason was "set in the mono face, the
   way a ledger prints them". The mono face is gone -- the type is Inter now
   -- so what was left was upper-casing for its own sake: a 50px headline
   shouting, `letter-spacing:.02em` fighting the -2.6px the hero asks for,
   and `font-weight:700` quietly overriding the 800 next to it.

   Sentence case, and each page's own size/tracking wins. The small uppercase
   LABELS elsewhere (badges, table headers, stat captions) keep it: at 10px
   with letter-spacing it is a device, not a volume control.
*/
h1, h2, .sechead h2, .an-head h1 { letter-spacing: -.02em; font-weight: 700; }



/* ── figures ──────────────────────────────────────────────────────────────
   tabular-nums default, not opt-in. It was a `.num` class and most of the
   site forgot it: headline figures, every transparency cell and
   every table body rendered in proportional digits, so a live figure changed
   WIDTH as it updated and columns of them never lined up. Anything that holds
   a number gets it; `.num` stays for the odd inline case. */
.num, td, th, .stat .v, .kv .v, .livestrip b, .facts .v, .big, .bignum,
input[type="number"] { font-variant-numeric: tabular-nums; }
