/* ==========================================================================
   CastPad, design tokens.

   Dark, documentary ground: a true black page, near-black cards lifted just
   far enough off it to read as surfaces, off-white ink, hairline structure,
   and a soft radius scale (see --r below).

   Black is the ground, not a theme. There is no light build and no toggle:
   one palette, defined once in :root below. Everything else in the codebase
   reads these tokens, so the ground moves by editing this block and nothing
   else. If a rule hardcodes a colour instead, that is the bug.

   Type: DM Sans for everything read as language, 600 for headings, 500 for
   emphasis, 400 for body. Roboto Mono for everything read as a value or a
   label: figures, addresses, tickers, and small-caps labels at 500 / .08em /
   uppercase. If a label's tracking is not .08em, it is a bug.

   Two things DM Sans needs that Inter did not:
   - Negative tracking. At default spacing it reads loose and generic; the
     reference this came from runs -.03em on headings and -.02em on body.
   - A slightly larger body size. Its x-height is lower than Inter's, so the
     same pixel size reads smaller. 15px became 15.5px rather than 16px, which
     would have reflowed every card.
   Body weight stays 400. The reference runs 300 and this is now a dark page,
   which is where light weights hold up; but 400 reversed out of black is
   already optically lighter than 400 on white, and dropping to 300 on top of
   that goes thin. 400 stays.

   There is no accent hue. STATE (live), ACTION (launch, buy, confirm) and
   DIRECTION (up, down) are all carried by value, weight, motion and a printed
   sign instead. --live and --go survive as named roles so the markup still
   says which kind of thing it means, but both resolve to ink: renaming them
   away would lose that meaning from the stylesheet.

   Because hue is gone, anything that USED to be told apart by colour has to be
   told apart some other way. Error vs focus, bad toast vs good toast and up vs
   down each get an explicit non-colour treatment below; see the comments there.

   FILL/FOREGROUND PAIRS. --ink, --go and --live are FILLS, and on a dark
   ground a fill is light, so text on top of one has to be dark. Each therefore
   carries a partner: --ink-fg, --go-fg, --live-fg. Never write a literal #fff
   on top of one of these fills. That is precisely what broke when the build
   flipped: --go went from black to white and every "color:#fff" on it became
   white on white.
   ========================================================================== */
:root{
  /* Five greys and nothing else. CastPad is the layer under other people's
     brands, so it does not compete with them for colour. */
  --black:#000000;
  --page:#000000;        /* body ground: true black */
  /* Cards are not black. On a black page a black card is a void, so the
     surfaces step UP from the ground in small increments and the hairline does
     the rest. Elevation on dark reads as a lighter surface, not as a shadow:
     a black drop-shadow over black is invisible, which is why the lift and
     hover rules below move border and surface instead. */
  --panel:#0d0e11;       /* cards */
  --panel-2:#15171b;     /* inset / hover */
  --wash:#1b1e23;        /* chips, wells */
  --ink:#f5f6f7;         /* off-white: primary text */
  --ink-fg:#0b0c0e;      /* what sits ON an --ink fill */
  --ink-2:#c9ced4;       /* light grey */
  /* Both of these are pinned to a measured ratio, not picked by eye. Measured
     against --panel (#0d0e11), which is the ground under all body copy, AND
     against --wash (#1b1e23), which is the ground under every chip and pill.
     Do not darken either without re-measuring against both. */
  --muted:#9ba2ab;       /* mid grey: secondary text.  7.5:1 on --panel */
  --faint:#868d96;       /* labels, meta.              5.8:1 on --panel,
                                                       5.0:1 on --wash */
  --line:#22252a;        /* hairline */
  --line-2:#343941;      /* emphasised border */
  --slate:#9ba2ab;

  /* LIVE is signalled by maximum contrast and by motion, not by hue. A white
     pill with a breathing dot and an expanding ring reads as "on air" without
     spending the brand's only strong value on a colour. */
  --live:#ffffff;
  --live-fg:#0b0c0e;

  /* The primary action is white. On a black ground that is the loudest thing
     available, which is what a primary action should be. Hover dims rather
     than brightens: there is nothing above white to go to. */
  --go:#ffffff;
  --go-2:#e4e6e9;
  --go-fg:#0b0c0e;
  --go-wash:#1b1e23;

  /* Direction is monochrome: ink for up, mid grey for down, and the sign is
     always printed. See the note at the top of this file. */
  --up:#f5f6f7;
  --down:#9ba2ab;

  /* Protocol identity only. These are other companies' colours and are the one
     exception to the monochrome rule, because a Twitch chip that is grey is
     harder to scan than one that is Twitch-coloured. Chain chips count as
     protocol identity too, which is why .chip-sol and .chip-eth keep them.
     Nothing that is purely CastPad's own may take a hue.

     Lightened for the black ground: the brand-accurate #5b3ea8 and #2f4f9f are
     both under 3:1 on --wash and read as bruises rather than as identity. */
  --sol:#a78bfa;
  --sol-wash:rgba(167,139,250,.13);
  --sol-line:rgba(167,139,250,.34);
  --eth:#8aa6f7;
  --eth-wash:rgba(138,166,247,.13);
  --eth-line:rgba(138,166,247,.34);
  --font:"DM Sans",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Arial,sans-serif;
  --font-display:var(--font);
  --mono:"Roboto Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  /* Radii. The 2px/6px pair borrowed from the reference made every control read
     as a hard rectangle, buttons, inputs and chips all looked like unstyled
     boxes. This scale is soft enough to look finished and still tight enough to
     stay serious. Pills are fully round so they read as status, not as buttons. */
  --r:8px;               /* controls: buttons, inputs, chips */
  --r-sm:6px;            /* nested things inside a control */
  --r-lg:14px;           /* cards, panels */
  --r-pill:999px;        /* status pills */
  --shell:1200px;
}

*{box-sizing:border-box}
/* Tells the browser this is a dark document, which is the ONLY way to reach the
   parts of the UI the page does not draw: the default ::placeholder grey, the
   scrollbars, the text caret, autofill backgrounds and any native select or
   date popup. Without it Chrome keeps its light-mode values and a bare <input>
   shows pale-grey placeholder text on a near-black well. */
/* The site read as zoomed out: a 1200px shell of 15.5px type on a wide screen
   leaves everything small. Every length in this file is px, so a root
   font-size would move nothing; root zoom scales all of them at once - type,
   padding, radii, the shell and the breakpoints - so the design keeps its
   proportions exactly and simply lands larger.
   1.07 = 7%. Supported in Chrome, Edge, Safari and Firefox 126+; anywhere it
   is not, the property is ignored and the site renders at its old size, which
   is a graceful floor rather than a broken layout. */
html{scroll-behavior:smooth;color-scheme:dark;zoom:1.07}
html,body{margin:0;padding:0;background:var(--page);color:var(--ink)}
/* A backstop for inputs that no component rule matches (the trade amount and
   the chat box are bare <input>s). ::placeholder does not inherit. */
input::placeholder,textarea::placeholder{color:var(--faint);opacity:1}
body{font-family:var(--font);font-size:15.5px;line-height:1.55;letter-spacing:-.02em;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden}
a{color:inherit;text-decoration:none}
button,input,select,textarea{font:inherit;color:inherit}
button{background:none;border:0;cursor:pointer}
input:focus,button:focus,select:focus,textarea:focus{outline:none}
img{max-width:100%;display:block}
::selection{background:var(--ink);color:var(--page)}
h1,h2,h3,h4{font-family:var(--font);font-weight:600;letter-spacing:-.032em;margin:0}
h1{letter-spacing:-.04em;line-height:1.04}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}
.shell{width:100%;max-width:var(--shell);margin:0 auto;padding:0 22px}
.up{color:var(--up)}
.down{color:var(--down)}
.muted{color:var(--muted)}
.faint{color:var(--faint)}
.hide{display:none!important}

/* ------------------------------------------------------------- animation */
/* Everything here animates opacity and transform only, those are the two the
   compositor can run without re-laying-out the page, which is the difference
   between smooth and the stutter this had before. */
@keyframes fadeUp{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
/* A soft breath, not a blink. The old 1 → .28 flash was a strobe on a 5px dot;
   .55 at the trough reads as "alive" without flickering. */
@keyframes breathe{0%,100%{opacity:1}50%{opacity:.55}}
/* The ring is what actually says "broadcasting": it expands out of the dot and
   fades, like a signal leaving it. Pure transform+opacity, so it is free. */
@keyframes ring{0%{transform:scale(1);opacity:.5}70%{transform:scale(2.6);opacity:0}100%{opacity:0}}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes mq{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.fade{animation:fadeUp .5s cubic-bezier(.22,1,.36,1) both}
.d1{animation-delay:.05s}.d2{animation-delay:.1s}.d3{animation-delay:.15s}.d4{animation-delay:.2s}
/* Shorter travel and a shorter duration: 16px over .7s is far enough that the
   eye tracks it as a slide, which is what made the grids feel like they lurched
   in. 8px over .45s registers as "settling" instead. */
.reveal{opacity:0;transform:translateY(8px);
  transition:opacity .45s cubic-bezier(.22,1,.36,1),transform .45s cubic-bezier(.22,1,.36,1)}
.reveal.in{opacity:1;transform:none}

/* A group whose children arrive one after another rather than as a block. The
   delay is on the child, so the container itself can stay a plain grid. Capped
   at eight: past that the last card is still waiting while you have scrolled on. */
.reveal-group > *{opacity:0;transform:translateY(10px);
  transition:opacity .5s cubic-bezier(.22,1,.36,1),transform .5s cubic-bezier(.22,1,.36,1)}
.reveal-group.in > *{opacity:1;transform:none}
.reveal-group.in > *:nth-child(1){transition-delay:0s}
.reveal-group.in > *:nth-child(2){transition-delay:.06s}
.reveal-group.in > *:nth-child(3){transition-delay:.12s}
.reveal-group.in > *:nth-child(4){transition-delay:.18s}
.reveal-group.in > *:nth-child(5){transition-delay:.24s}
.reveal-group.in > *:nth-child(6){transition-delay:.3s}
.reveal-group.in > *:nth-child(7){transition-delay:.36s}
.reveal-group.in > *:nth-child(n+8){transition-delay:.42s}

/* Hover lift. Still restrained - past about 1.03 on a card this size it reads
   as the layout jumping rather than as the card responding - but the old 1.012
   was small enough to be missed entirely. */
.lift{transition:transform .24s cubic-bezier(.22,1,.36,1),box-shadow .24s ease,border-color .18s}
/* On dark, depth comes from the surface getting lighter and the border picking
   up, not from a shadow: a shadow over black has nothing to darken. */
.lift:hover{transform:translateY(-4px) scale(1.02);
  box-shadow:0 18px 40px -12px rgba(0,0,0,.8);border-color:var(--line-2)}
.lift:active{transform:translateY(-1px) scale(1.005);transition-duration:.09s}

/* The thumbnail pushes in slightly behind the card's own frame. This is the
   part that reads as "alive": the card moves, and the picture inside it moves
   a little more. overflow:hidden on .sc-thumb clips it, so nothing spills. */
.card .sc-thumb .art,.card .sc-thumb img,.card .sc-thumb video{
  transition:transform .45s cubic-bezier(.22,1,.36,1)}
.card:hover .sc-thumb .art,.card:hover .sc-thumb img,.card:hover .sc-thumb video{
  transform:scale(1.06)}

/* Table rows are not card-shaped, so they get the flat version of the same
   idea: the surface lifts in value instead of in space. */
.tbl tbody tr{transition:background .16s}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.001s!important;transition-duration:.001s!important}
  .reveal{opacity:1;transform:none}
}

/* ---------------------------------------------------------------- header */
/* Glass bar, floating rather than pinned to the edge.

   The blur is back by request. It was removed earlier because a backdrop-filter
   on a sticky element re-composites the strip under it every scroll frame; the
   cost is contained here by keeping the blurred surface small (a floating bar,
   not a full-width strip) and by promoting it to its own layer with
   `will-change`, so the blur is computed once and reused rather than on each
   frame. */
/* Glass, on every page. It floats over the black hero on the home page and over
   the black page everywhere else, so it is given its own surface rather than
   being tinted to match whatever is underneath. Switching it on scroll was the
   alternative and it flickers at the handover.

   It is LIGHTER than the page, not darker. On the old off-white build a dark
   bar separated itself by being dark; on black that same value disappears into
   the ground and the bar stops reading as an object. */
.hdr{position:sticky;top:14px;z-index:90;margin:14px auto 0;width:calc(100% - 44px);
  max-width:var(--shell);border:1px solid rgba(255,255,255,.10);border-radius:var(--r-lg);
  background:rgba(30,33,38,.72);
  backdrop-filter:blur(20px) saturate(140%);-webkit-backdrop-filter:blur(20px) saturate(140%);
  box-shadow:0 8px 30px -12px rgba(0,0,0,.8);
  will-change:transform}
.hdr .brand{color:#fff}
.hdr .nav a{color:rgba(255,255,255,.62)}
.hdr .nav a:hover,.hdr .nav a.on{color:#fff}
.hdr .burger{border-color:rgba(255,255,255,.22);color:#fff}
/* Controls inside the bar invert with it. */
.hdr .btn{background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.20);color:#fff}
.hdr .btn:hover{background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.3)}
.hdr .btn-live{background:#fff;border-color:#fff;color:var(--ink-fg)}
.hdr .btn-live:hover{background:rgba(255,255,255,.88);border-color:rgba(255,255,255,.88)}
.hdr .ca{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.16);
  color:rgba(255,255,255,.66)}
.hdr .ca:hover{background:rgba(255,255,255,.12);color:#fff;border-color:rgba(255,255,255,.28)}
.hdr .hdr-in{padding:0 8px 0 16px}
/* The bar carries its own width, so the shell inside it must not add another. */
.hdr .shell{max-width:none;padding:0 8px 0 16px}
@media(max-width:900px){.hdr{top:8px;margin-top:8px;width:calc(100% - 24px)}}
.hdr-in{height:58px;display:flex;align-items:center;justify-content:space-between;gap:18px}
.hdr-l{display:flex;align-items:center;gap:28px;min-width:0}
.brand{display:flex;align-items:center;gap:8px;font-weight:600;font-size:16px;letter-spacing:-.02em}
.brand svg,.brand img{width:22px;height:22px;flex:none;border-radius:6px}
.nav{display:flex;align-items:center;gap:20px}
.nav a{font-size:13px;color:var(--muted);transition:color .15s}
.nav a:hover,.nav a.on{color:var(--ink)}
.hdr-r{display:flex;align-items:center;gap:8px}
.burger{display:none;width:34px;height:34px;border:1px solid var(--line-2);border-radius:var(--r);
  align-items:center;justify-content:center}
@media(max-width:900px){
  .nav{display:none}
  .burger{display:flex}
  .hdr-r .btn-launch{display:none}
}
.sheet{position:fixed;inset:80px 0 auto 0;z-index:89;background:var(--panel);
  border-bottom:1px solid var(--line);padding:8px 0 14px;display:none}
.sheet.open{display:block;animation:fadeUp .22s ease both}
@media(max-width:900px){.sheet{inset:74px 0 auto 0}}
.sheet a{display:block;padding:11px 22px;font-size:15px;color:var(--muted)}
.sheet a.on{color:var(--ink)}
/* The sheet also contains a button, and ".sheet a" out-specifies ".btn-live",
   so without these the primary CTA inherits the nav link's muted grey straight
   onto its white fill. It was legible while --go was black; it is not now. */
.sheet a.btn{color:var(--ink);display:inline-flex;font-size:13px;padding:0 14px}
.sheet a.btn-live{color:var(--go-fg)}

/* --------------------------------------------------------------- buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;height:36px;padding:0 14px;
  border-radius:var(--r);font-size:13px;font-weight:600;border:1px solid var(--line-2);
  color:var(--ink);background:var(--panel);white-space:nowrap;
  transition:background .15s,border-color .15s,transform .12s,opacity .15s}
.btn:hover{background:var(--panel-2);border-color:var(--slate)}
.btn:active{transform:translateY(1px)}
.btn:disabled{opacity:.45;cursor:not-allowed;transform:none}
/* The primary action. Named .btn-live for continuity with the markup, but it is
   the ACTION colour, a live stream never uses it. */
.btn-live{background:var(--go);border-color:var(--go);color:var(--go-fg)}
.btn-live:hover{background:var(--go-2);border-color:var(--go-2)}
.btn-ghost{background:transparent}
.btn-ghost:hover{background:var(--panel-2)}
.btn-lg{height:44px;padding:0 20px;font-size:14px}
.btn-sm{height:30px;padding:0 10px;font-size:12px}
.btn-block{width:100%}
/* NOTE: there is deliberately no shared "on a dark band" class here. The two
   places that need one (the home hero over its video, and the closing band)
   each carry their own .hero .btn / .band .btn overrides, because each also
   tunes its translucency to what is behind it. An unused shared class that
   hardcodes #fff is what breaks on the next ground change. */

/* ----------------------------------------------------------------- chips */
.chip{display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 8px;border-radius:var(--r);
  background:var(--wash);border:1px solid var(--line);font-family:var(--mono);font-size:11px;
  font-weight:500;color:var(--muted);letter-spacing:.03em}
.chip-sol{color:var(--sol);border-color:var(--sol-line);background:var(--sol-wash)}
.chip-eth{color:var(--eth);border-color:var(--eth-line);background:var(--eth-wash)}
.chip-go{color:var(--ink);border-color:var(--ink);background:var(--panel);font-weight:500}

/* ------------------------------------------------------------------- CA */
/* The contract address. Monospace because it is a value, click to copy, and
   deliberately quiet: it sits next to the two buttons in the nav and must not
   compete with either. */
.ca{display:inline-flex;align-items:center;gap:7px;height:36px;padding:0 11px;
  border-radius:var(--r);border:1px solid var(--line);background:var(--panel-2);
  color:var(--muted);font-family:var(--mono);font-size:12px;
  transition:color .15s,border-color .15s,background .15s}
.ca:hover{color:var(--ink);border-color:var(--line-2);background:var(--panel)}
.ca svg{opacity:.55;flex:none}
.ca:hover svg{opacity:1}
.ca-soon{cursor:default;letter-spacing:.08em;text-transform:uppercase;font-size:11px;
  color:var(--faint)}
.ca-soon:hover{color:var(--faint);border-color:var(--line);background:var(--panel-2)}
@media(max-width:900px){.hdr-r .ca{display:none}}
/* In the footer it has room for the whole address. */
.ftr .ca{height:auto;padding:8px 11px;font-size:12px;word-break:break-all;text-align:left}

/* LIVE. Fully round, because a status pill should not look like something you
   can click. It is the brightest object on the page by design: on black, a
   white fill is the loudest thing there is. */
.live-pill{display:inline-flex;align-items:center;gap:7px;height:24px;padding:0 10px;
  border-radius:var(--r-pill);background:var(--live);color:var(--live-fg);font-family:var(--mono);font-size:11px;
  font-weight:500;letter-spacing:.08em;text-transform:uppercase}
/* The dot breathes; a ring expands out of it and fades. The ring is a
   pseudo-element so it can scale past the dot without moving anything, and both
   properties are compositor-only. */
.live-pill .dot{position:relative;width:6px;height:6px;border-radius:50%;background:var(--live-fg);
  flex:none;animation:breathe 2.4s ease-in-out infinite}
.live-pill .dot::after{content:"";position:absolute;inset:0;border-radius:50%;
  background:var(--live-fg);animation:ring 2.4s ease-out infinite;pointer-events:none}
.off-pill{display:inline-flex;align-items:center;gap:7px;height:24px;padding:0 10px;
  border-radius:var(--r-pill);background:var(--wash);border:1px solid var(--line-2);color:var(--muted);
  font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase}
.dot{width:6px;height:6px;border-radius:50%;background:var(--go);display:inline-block;flex:none}
/* Connected-wallet dot. It only ever appears inside .hdr, which is dark glass
   on every page, so it is white with a ring rather than ink. */
.conn-dot{width:7px;height:7px;border-radius:50%;background:#fff;flex:none;
  box-shadow:0 0 0 3px rgba(255,255,255,.18)}

/* Inline link inside body copy and callouts. a{color:inherit} globally, so
   without this an <a class="in"> is indistinguishable from the text round it. */
a.in{text-decoration:underline;text-underline-offset:2px;
  text-decoration-color:var(--line-2);color:var(--ink);font-weight:500}
a.in:hover{text-decoration-color:var(--ink)}
.toast.bad a.in{color:var(--ink-fg);text-decoration-color:rgba(0,0,0,.45)}

/* ---------------------------------------------------------------- layout */
.sec{padding:70px 0}
.sec-tight{padding:40px 0}
.eyebrow{font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.08em;
  text-transform:uppercase;color:var(--faint)}
.sec-head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin-bottom:22px}
.sec-head h2{font-size:26px}
.sec-head p{margin:8px 0 0;color:var(--muted);font-size:14px}
.link-more{font-size:13px;color:var(--muted);display:inline-flex;align-items:center;gap:5px;
  transition:color .15s}
.link-more:hover{color:var(--ink)}
.grid{display:grid;gap:16px}
.g2{grid-template-columns:repeat(2,1fr)}
.g3{grid-template-columns:repeat(3,1fr)}
.g4{grid-template-columns:repeat(4,1fr)}
@media(max-width:1000px){.g4{grid-template-columns:repeat(2,1fr)}}
@media(max-width:860px){.g3{grid-template-columns:repeat(2,1fr)}}
@media(max-width:620px){.g2,.g3,.g4{grid-template-columns:1fr}}

.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;
  transition:border-color .18s,transform .18s,box-shadow .18s}
a.card:hover{border-color:var(--line-2);transform:translateY(-2px);
  background:var(--panel-2);box-shadow:0 10px 26px -8px rgba(0,0,0,.7)}
.panel{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);padding:20px}

/* ------------------------------------------------------------ stream card */
.sc-thumb{position:relative;aspect-ratio:16/9;background:var(--wash);overflow:hidden}
.sc-thumb .art{position:absolute;inset:0;display:grid;place-items:center;font-family:var(--font);
  font-weight:600;font-size:42px;letter-spacing:-.04em;color:rgba(255,255,255,.34)}
.sc-thumb .veil{position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(14,17,22,0) 38%,rgba(14,17,22,.72))}
.sc-thumb .tl{position:absolute;top:9px;left:9px;display:flex;gap:6px}
.sc-thumb .tr{position:absolute;top:9px;right:9px}
.sc-thumb .bl{position:absolute;bottom:9px;left:9px;right:9px;display:flex;align-items:center;
  justify-content:space-between;gap:8px}
.sc-title{font-size:12px;font-weight:500;color:#fff;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.viewers{display:inline-flex;align-items:center;gap:5px;height:22px;padding:0 8px;
  border-radius:var(--r);background:rgba(14,17,22,.74);color:#fff;font-family:var(--mono);
  font-size:11px;font-weight:500;flex:none}
.sc-body{padding:13px 14px 15px}
.sc-top{display:flex;align-items:center;gap:10px;min-width:0}
.sc-logo{width:32px;height:32px;border-radius:var(--r-lg);flex:none;display:grid;place-items:center;
  font-family:var(--font);font-weight:600;font-size:13px;color:#fff}
.sc-name{font-weight:600;font-size:14px;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.sc-sym{font-size:11px;color:var(--faint);font-family:var(--mono)}
.sc-stats{display:flex;align-items:center;justify-content:space-between;margin-top:12px;
  padding-top:11px;border-top:1px solid var(--line);font-size:13px}

/* ---------------------------------------------------------------- tables */
.tbl-wrap{border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;background:var(--panel)}
.tbl-scroll{overflow-x:auto}
table.tbl{width:100%;border-collapse:collapse;min-width:900px}
.tbl th{font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.08em;
  text-transform:uppercase;color:var(--faint);text-align:right;padding:11px 16px;
  border-bottom:1px solid var(--line);background:var(--panel-2);white-space:nowrap;user-select:none}
.tbl th:first-child,.tbl td:first-child{text-align:left}
.tbl th.sortable{cursor:pointer}
.tbl th.sortable:hover{color:var(--ink)}
.tbl th .caret{opacity:0;margin-left:4px}
.tbl th.act{color:var(--ink)}
.tbl th.act .caret{opacity:1}
.tbl td{padding:13px 16px;border-bottom:1px solid var(--line);text-align:right;font-size:14px;
  white-space:nowrap}
.tbl tbody tr{transition:background .14s}
.tbl tbody tr:hover{background:var(--panel-2);cursor:pointer}
.tbl tbody tr:last-child td{border-bottom:0}
.cell-coin{display:flex;align-items:center;gap:11px}

/* ---------------------------------------------------------------- filters */
.filters{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:20px}
.seg{display:inline-flex;background:var(--panel-2);border:1px solid var(--line);
  border-radius:var(--r);padding:2px}
.seg button{height:30px;padding:0 12px;border-radius:var(--r-sm);font-size:13px;font-weight:500;
  color:var(--muted);transition:color .15s,background .15s}
.seg button:hover{color:var(--ink)}
.seg button.on{background:var(--panel);color:var(--ink);box-shadow:0 1px 2px rgba(0,0,0,.5)}
.search{display:flex;align-items:center;gap:8px;height:36px;padding:0 12px;background:var(--panel);
  border:1px solid var(--line-2);border-radius:var(--r);min-width:210px}
.search:focus-within{border-color:var(--ink)}
.search input{background:none;border:0;width:100%;font-size:14px}
.search input::placeholder{color:var(--faint)}
.spacer{flex:1 1 auto}

/* ------------------------------------------------------------------ forms */
.field{margin-bottom:18px}
.field > label{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  font-size:12px;font-weight:500;color:var(--muted);margin-bottom:6px}
.field .hint{font-size:12px;color:var(--faint);font-weight:400}
.inp{width:100%;height:40px;padding:0 12px;background:var(--panel);border:1px solid var(--line-2);
  border-radius:var(--r);font-size:14px;transition:border-color .15s}
textarea.inp{height:auto;padding:11px 12px;resize:vertical;min-height:88px;line-height:1.5}
.inp:focus{border-color:var(--ink)}
.inp::placeholder{color:var(--faint)}
.inp.bad{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink);background:var(--wash)}
/* The message itself is set apart by weight and a rule, not by being red. */
.err{font-size:12px;color:var(--ink);margin-top:6px;font-weight:500;
  padding-left:9px;border-left:2px solid var(--ink)}
.note{font-size:12px;color:var(--faint);margin-top:6px;line-height:1.5}

/* ---------------------------------------------------------------- empty */
.empty{border:1px dashed var(--line-2);border-radius:var(--r-lg);padding:50px 24px;text-align:center;
  background:var(--panel)}
.empty h3{font-size:18px;margin-bottom:7px}
.empty p{color:var(--muted);font-size:14px;margin:0 auto 18px;max-width:440px}

/* ------------------------------------------------------------------ footer */
.ftr{border-top:1px solid var(--line);background:var(--panel);margin-top:40px}
.ftr-in{display:grid;grid-template-columns:2fr 1fr 1fr;gap:34px;padding:46px 0 32px}
@media(max-width:760px){.ftr-in{grid-template-columns:1fr 1fr;gap:26px}}
.ftr h4{font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:.08em;
  text-transform:uppercase;color:var(--faint);margin-bottom:12px}
.ftr ul{list-style:none;margin:0;padding:0;display:grid;gap:9px}
.ftr ul a{font-size:13px;color:var(--muted);transition:color .15s}
.ftr ul a:hover{color:var(--ink)}
.ftr-bar{border-top:1px solid var(--line);padding:15px 0;display:flex;align-items:center;
  justify-content:space-between;gap:16px;flex-wrap:wrap;font-size:12px;color:var(--faint)}
.ticks{display:flex;gap:16px;flex-wrap:wrap}
.tick{display:flex;align-items:center;gap:6px}
.tick b{font-family:var(--mono);font-weight:500;color:var(--muted);font-size:11px;letter-spacing:.06em}

/* ------------------------------------------------------------------ toast */
.toasts{position:fixed;right:18px;bottom:18px;z-index:200;display:grid;gap:9px;max-width:330px}
.toast{background:var(--panel);border:1px solid var(--line-2);border-radius:var(--r-lg);
  padding:12px 14px;font-size:13px;box-shadow:0 12px 34px rgba(0,0,0,.65);
  animation:fadeUp .3s cubic-bezier(.22,1,.36,1) both}
.toast.good{border-left:2px solid var(--ink)}
.toast.bad{background:var(--ink);border-color:var(--ink);color:var(--ink-fg);
  box-shadow:0 10px 30px rgba(0,0,0,.6)}
.toast.bad a{color:var(--ink-fg);text-decoration:underline}
