@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap');

/* ---- static/cf-theme.css ---- */
/* Cartel Family — theme tokens: SYNDICATE NOIR (decided 2026-10-12).
 *
 * THE palette. Every colour, type face, space, radius, shadow, glass recipe
 * and motion value in the product resolves from this file: the web pages,
 * the Telegram Mini App, the admin console, the landing, the share-card PNGs
 * (pnl_share_cards.py parses it) and every canvas (cf-charts.js reads the
 * computed values off <body>). Nothing else defines a colour.
 *
 * The values ARE the Noir design system. The prototype they were taken from
 * (/design/a/*, its tokens.css and COMPONENTS.md) was deleted on 2026-10-15
 * once every surface wore Noir; this file and cf-noir.css are the system now,
 * with the AA corrections the product's contrast test computes
 * (tests/test_accent_contrast.py) — see "AA" below.
 *
 * Three layers:
 *   1. NOIR TOKENS — the design system's own names (--ink-0..5 grounds,
 *      --text-1..4, --gold-50..900 + --molten, the ONE electric accent --ion,
 *      --up/--dn, rank metals, glass, elevation, type, space, radii, motion,
 *      chart series). New work uses these.
 *   2. PRODUCT TOKENS — the short names every existing stylesheet already
 *      reads (--bg --s1 --s2 --line --ink --ink2 --ink3 --acc --accT --onAcc
 *      --up --dn --pro --nav-* --rank-* --series-* --dur-* ...), each pointed
 *      at its Noir value, so every page is Noir without touching its markup.
 *   3. ALIASES — the ~60 older names (--bg2, --text, --accent-cta, --m3-*).
 *
 * NAME TRAP: in Noir `--ink-1` (with a hyphen and a digit) is a GROUND
 * colour; the product's `--ink` / `--ink2` / `--ink3` are TEXT colours. They
 * are different tokens and both exist here on purpose.
 *
 * Themes (owner decision 2026-09-25, kept by the Noir decision): dark is the
 * default; [data-theme="light"] is an explicit choice; absent means dark
 * whatever the OS prefers. The light palette is scoped to body.cf-themable so
 * a legacy template with hardcoded dark surfaces is not handed light chrome
 * over dark content. Light is ice white, the same blue (deeper), navy type.
 *
 * BRAND COLOUR: BLUE (owner's decision, 2026-10-16: "change the gold colour
 * scheme to match the blue"). The ramp was sampled from the new brand art
 * (the Boss Bull icon on royal blue, and the CARTEL banner): electric
 * #1687FF, royal #0659B7, deep navy #0F264F / #061735. The --gold-* names
 * stay as ALIASES of --blue-* so every stylesheet keeps working; --molten is
 * the blue molten (ice -> electric -> royal -> deep). Rank metals keep their
 * metal tones (they are ranks, not brand). The ONE live accent --ion moved
 * from cyan to aqua-teal so it never reads as the primary blue.
 *
 * AA (tests/test_accent_contrast.py computes these from this file):
 *   dark  --acc #3d97ff under --on-molten #04122a      6.28:1
 *   dark  --accent-text #7cb8ff on --ink-4 #122036     7.90:1 (worst ground)
 *   dark  --text-3 #8b9ab0 on --ink-4                  5.71:1
 *   light --acc #1f6fe0 under #ffffff                  4.76:1
 *   light --accent-text #1652b8 on --ink-4 #eaf1fb     6.30:1
 *   light --text-3 #56647c on --ink-4                  5.26:1
 *   light --up #0e6947 / --dn #c22e40 keep their earlier AA corrections.
 */


/* ── 1+2. DARK (the default): Noir tokens and the product names ────────── */
:root, [data-theme="dark"] {
  color-scheme: dark;

  /* product names, first so every parser (pnl_share_cards.py, the contrast
     test) reads the dark value; each resolves to a Noir token below */
  --bg: var(--ink-1); --s1: var(--ink-3); --s2: var(--ink-4);
  --ink: var(--text-1); --ink2: var(--text-2); --ink3: var(--text-3); --body: #d5deea;
  --acc: #3d97ff; --accT: var(--accent-text); --onAcc: var(--on-molten);
  --up: #4fe0a2; --dn: #ff5f6d;
  --upBg: rgba(79,224,162,.14); --dnBg: rgba(255,95,109,.14);
  --pro: #f2b84b; --proBg: #120d06; --proLine: #4a3a1c;
  --onPro: #1c1209;   /* label on an amber FILL */

  /* ground and surfaces */
  --ink-0: #03070f;                 /* deepest: bezel inner, dial */
  --ink-1: #050b17;                 /* page: deep navy ink */
  --ink-2: #081120;                 /* sunken: inputs, segmented track */
  --ink-3: #0c1729;                 /* card */
  --ink-4: #122036;                 /* raised control */
  --ink-5: #1c2d48;                 /* hairline on raised, sheet grabber */
  --ground-rgb: 5 11 23;
  --ground-hi: #0b1a33;
  --raise: 17 29 49;
  --card-hi: #122036; --card-lo: #09121f;
  --sheet-hi: #101c30; --sheet-lo: #081120;
  --well-hi: #0d1626; --well-lo: #060c17;
  --badge-hi: #11213b; --badge-lo: #08101e;
  --surface-hover: #0b1424;
  --well: rgb(0 0 0 / .26);         /* figure wells inside cards */
  --tint: 214 232 255;              /* light-on-dark channel: rgb(var(--tint) / .04) */
  --shade: 0 0 0;
  --scrim-rgb: 2 5 12;
  --ion-ground: 4 28 28;

  /* text: ice white, never pure white */
  --text-1: #eef3fb;
  --text-2: #a7b4c8;
  --text-3: #8b9ab0;
  --text-4: #4a566a;
  --accent-text: #7cb8ff;           /* blue as TEXT (= --blue-300) */
  --accent-text-strong: #b0d4ff;    /* blue figures (= --blue-200) */
  --on-molten: #04122a;
  --on-ion: #032622;

  /* molten blue: brand electric #1687FF / royal #0659B7 / navy #0F264F ramped */
  --blue-50: #eef6ff; --blue-100: #d6e9ff; --blue-200: #b0d4ff; --blue-300: #7cb8ff;
  --blue-400: #3d97ff; --blue-500: #1687ff; --blue-600: #0f6ad8; --blue-700: #0b4fa8;
  --blue-800: #0b3570; --blue-900: #071a38;
  --gold-50: var(--blue-50); --gold-100: var(--blue-100); --gold-200: var(--blue-200); --gold-300: var(--blue-300);
  --gold-400: var(--blue-400); --gold-500: var(--blue-500); --gold-600: var(--blue-600); --gold-700: var(--blue-700);
  --gold-800: var(--blue-800); --gold-900: var(--blue-900);
  --glow: 61 151 255;
  --molten: linear-gradient(118deg, #d4e9ff 0%, #8cc4ff 22%, #4aa0ff 46%, #2f86ff 64%, #1a5fd0 100%);
  --molten-text: linear-gradient(100deg, #eef6ff 0%, #b0d4ff 30%, #6aaeff 62%, #3d97ff 100%);
  --molten-edge: linear-gradient(180deg, rgba(214,233,255,.42), rgba(22,135,255,.08) 40%, rgba(22,135,255,0) 70%);
  --molten-hi: rgba(214,233,255,.55);    /* the molten fill's own rim */
  --molten-lo: rgba(6,40,110,.35);       /* its inset royal base */
  --sheen-rgb: 236 245 255;              /* the light sweep, the ripple, a top highlight */

  /* the ONE electric accent: ion = live / active only (aqua-teal, so it never
     reads as the primary blue) */
  --ion: #40ead2; --ion-rgb: 64 234 210;

  /* direction, as channels */
  --up-rgb: 79 224 162; --dn-rgb: 255 95 109;

  /* ember: the celebration palette (sparks, embers), as HSL parts */
  --ember-h: 208; --ember-h-span: 22; --ember-s: 100%; --ember-l: 70%;

  /* rank metals, Associate -> Boss: base / highlight / shadow */
  --metal-associate: #8d939c; --metal-associate-hi: #d7dce3; --metal-associate-lo: #3a3e45;
  --metal-soldier: #c07a45;   --metal-soldier-hi: #f3c194;   --metal-soldier-lo: #5a3016;
  --metal-capo: #c6ccd6;      --metal-capo-hi: #ffffff;      --metal-capo-lo: #5d6470;
  --metal-underboss: #e0b464; --metal-underboss-hi: #fff0c4; --metal-underboss-lo: #7a5420;
  --metal-boss: #f4d79a;      --metal-boss-hi: #fffaf0;      --metal-boss-lo: #2a1c0e;

  /* chart series: brand blue, ion, jade, amethyst, ember, gold, brass, rose */
  --series-1: #7cb8ff; --series-2: #40ead2; --series-3: #4fe0a2; --series-4: #c08cff;
  --series-5: #ff9b5c; --series-6: #ecc286; --series-7: #f2e58a; --series-8: #ff6fa8;

  /* chains (one dot colour per chain; NA.chainChip in the reference) */
  --chain-solana: #b98cff; --chain-base: #5b8cff; --chain-bsc: #f3c74f;
  --chain-arbitrum: #62b5ff; --chain-polygon: #a77bff; --chain-robinhood: #c6f25b;
  --chain-ethereum: #9aa9ff; --chain-monad: #a98bff; --chain-hyperevm: #5fe3c4;

  /* navigation hues (navigation.HUES): drawn from the Noir series */
  --nav-feed: #5fd0ff; --nav-discover: #c08cff; --nav-market: #4fe0a2; --nav-bot: #40ead2;
  --nav-traders: #ff9b5c; --nav-calls: #f2e58a; --nav-leaderboard: #7cb8ff; --nav-groups: #8fb4ff;
  --nav-promote: #ff6fa8; --nav-launch: #4fe0a2; --nav-share: #9aa7ba; --nav-admin: #7cb8ff;
  --nav-portfolio: #4fe0a2; --nav-profile: #7cb8ff; --nav-trade: #3d97ff; --nav-history: #8fb4ff;
  --nav-referrals: #f2e58a; --nav-settings: #9aa7ba; --nav-about: #9aa7ba;

  /* family ranks (gamification.RANKS): each rank's metal */
  --rank-associate: #8d939c; --rank-soldier: #d08a55; --rank-capo: #c6ccd6;
  --rank-underboss: #e0b464; --rank-boss: #f4d79a;
}

/* ── 1. NOIR: theme-independent tokens ──────────────────────────────────── */
:root {
  /* type: Space Grotesk for words, JetBrains Mono for every figure */
  --font-display: 'Space Grotesk', ui-sans-serif, system-ui, sans-serif;
  --font-body: 'Space Grotesk', ui-sans-serif, system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;
  --font-ui: var(--font-body);
  --font-num: var(--font-mono);
  --fs-hero: clamp(40px, 7.4vw, 104px); --lh-hero: .94; --fw-hero: 700; --tr-hero: -.05em;
  --fs-h1: clamp(30px, 4.4vw, 56px);    --lh-h1: 1.02;  --fw-h1: 700;   --tr-h1: -.035em;
  --fs-page-title: 26px;                --lh-page-title: 1.1; --fw-page-title: 700; --tr-page-title: -.03em;
  --fs-h2: clamp(22px, 2.6vw, 34px);    --lh-h2: 1.1;   --fw-h2: 700;   --tr-h2: -.03em;
  --fs-h3: 18px; --lh-h3: 1.2; --fw-h3: 600; --tr-h3: -.01em;
  --fs-body: 15px; --lh-body: 1.55; --fw-body: 400;
  --fs-small: 13px; --lh-small: 1.45;
  --fs-micro: 11px; --lh-micro: 1.2; --fw-micro: 600;
  --fs-figure-xl: clamp(26px, 3.2vw, 42px);
  --fs-figure: 20px;
  --tr-caps: .16em; --track-caps: var(--tr-caps);

  /* space: a 4px grid */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 20px;
  --sp-6: 24px; --sp-8: 32px; --sp-10: 40px; --sp-12: 48px; --sp-16: 64px; --sp-24: 96px;
  --gutter: clamp(16px, 4vw, 48px);
  --maxw: 1320px;
  --rail-w: 232px; --rail-w-collapsed: 72px;
  --bar-h: 64px;
  --tap: 44px;                       /* minimum touch target */
  --pad-compact: 12px; --pad-comfortable: 16px;

  /* radii: badge 6 · control 10 · card 14 · sheet 20 · hero 28 · pill */
  --r-badge: 6px; --r-control: 10px; --r-card: 14px; --r-sheet: 20px; --r-full: 999px;
  --r-xs: 6px; --r-sm: 10px; --r-md: 14px; --r-lg: 20px; --r-xl: 28px; --r-pill: 999px;

  /* glass */
  --blur: 16px; --glass-saturate: 1.2;

  /* motion (COMPONENTS.md "Motion & toasts"). The --t-* names are Noir's; the
     --dur-* names are the product's, at the same values. */
  --ease-out: cubic-bezier(.2,.8,.2,1);
  --ease-in: cubic-bezier(.55,0,1,.45);
  --ease-in-out: cubic-bezier(.65,0,.35,1);
  --ease-spring: cubic-bezier(.34,1.56,.64,1);
  --ease-draw: cubic-bezier(.3,.7,.2,1);
  --t-fast: 160ms; --t-med: 280ms; --t-slow: 520ms; --t-enter: 600ms;
  --t-count: 900ms; --t-draw: 700ms; --t-sweep: 760ms; --t-ripple: 620ms; --t-press: 90ms;
  --toast-life: 5200ms;
  --dur-fast: .16s; --dur: .28s; --dur-draw: .7s;

  /* z-index, on the product's scale (its modals sit at 1500, its tips at 9800) */
  --z-base: 0; --z-sticky: 30; --z-bar: 40; --z-popover: 900; --z-sheet: 1500;
  --z-toast: 9700; --z-overlay: 9750;

  /* breakpoints (documentation: media queries use the literals) */
  --bp-phone: 390px; --bp-phone-max: 767px; --bp-tablet: 768px; --bp-laptop: 1024px; --bp-desktop: 1280px; --bp-wide: 1440px;

  --chart-fill-top: .22; --chart-glow: 4px;

  /* Card padding follows density; compact is the default. */
  --pad: var(--pad-compact);

  /* ── density: the compact pass (owner, 2026-10-11: "more minimal and
     compact"). One dial per kind of space, so every page tightens together.
     Touch targets stay 44px: --h-btn only drops on a fine pointer at laptop
     width. */
  --wrap-pad: 16px 24px;
  --wrap-pad-phone: 10px 12px 20px;
  --gap-cols: 16px;
  --gap-section: 12px;
  --gap-stack: 10px;
  --pad-card: var(--pad) 16px;
  --pad-card-head: 12px 16px 6px;
  --row-min: 48px;
  --h-btn: 44px;
}
@media (hover:hover) and (pointer:fine) and (min-width:1025px){
  :root{ --h-btn: 36px; }
}

/* ── derived tokens + aliases ───────────────────────────────────────────── */
/* Declared on body.cf-themable as well as :root. A custom property that
   references another is resolved where it is DECLARED, so a recipe declared
   only on :root resolves against the root's (dark) values and stays dark
   under the light palette, which lives on body.cf-themable. Re-declared on
   the body, every recipe follows the theme. */
:root, body.cf-themable {
  /* Noir recipes */
  --ion-dim: rgb(var(--ion-rgb) / .14);
  --ion-glow: 0 0 12px rgb(var(--ion-rgb) / .55), 0 0 2px rgb(var(--ion-rgb) / .9);
  --up-dim: rgb(var(--up-rgb) / .14);
  --dn-dim: rgb(var(--dn-rgb) / .14);
  --danger: var(--dn);
  --rank-ink: var(--text-1);
  --glass: rgb(var(--raise) / .62);
  --glass-edge: rgb(var(--tint) / .09);
  --glass-edge-hi: rgb(var(--tint) / .18);
  --glass-fill: linear-gradient(180deg, rgb(var(--raise) / .7), rgb(var(--raise) / .6) 38%, var(--glass));
  --glow-gold: 0 0 0 1px rgb(var(--glow) / .35), 0 8px 30px rgb(var(--glow) / .28);
  --focus-ring: 0 0 0 2px var(--ink-1), 0 0 0 4px var(--gold-300);
  --focus: var(--focus-ring);
  --chart-up: var(--up); --chart-down: var(--dn);
  --chart-grid: rgb(var(--tint) / .06);
  --chart-crosshair: rgb(var(--glow) / .55);
  /* the ground: navy ink, a blue light from above, a hint of ion top-right,
     royal blue bottom-left, and a 7% film grain drawn by an SVG turbulence filter */
  --ground:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 .85  0 0 0 0 .92  0 0 0 0 1  0 0 0 .055 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"),
    radial-gradient(1200px 600px at 50% -10%, rgb(var(--glow) / .16), transparent 60%),
    radial-gradient(900px 500px at 100% 0%, rgb(var(--ion-rgb) / .05), transparent 60%),
    radial-gradient(800px 800px at 0% 100%, rgb(var(--glow) / .14), transparent 60%);

  /* product names that are recipes */
  --line: rgb(var(--tint) / .1);
  --grid: var(--chart-grid);
  --accBg: rgb(var(--glow) / .16);
  --scrim: rgb(var(--scrim-rgb) / .66);
  --e1: var(--shadow-2);
  --e2: var(--shadow-3);

  /* older names */
  --bg2: var(--s1);
  --bg3: var(--s2);
  --bg4: var(--s2);
  --text: var(--ink);
  --muted: var(--ink2);
  --dim: var(--ink3);
  --border: var(--line);
  --border2: var(--glass-edge-hi);
  --glass-border: var(--glass-edge);

  --accent: var(--acc);
  --accent-rgb: 61,151,255;
  --accent-cta: var(--acc);        /* a FILL: its label is --onAcc */
  --accent-ink: var(--accT);       /* accent as TEXT */
  --accent-fill: var(--molten);    /* the molten FILL, where a gradient is allowed */
  --gold: var(--acc);
  --gold2: var(--accT);
  --gold-rgb: 61,151,255;
  --on-gold: var(--onAcc);

  --green: var(--up);
  --green2: var(--up);
  --green-glow: var(--upBg);
  --red: var(--dn);
  --yellow: var(--pro);
  --blue: var(--series-6);
  --purple: var(--series-4);

  --m3-background: var(--bg);
  --m3-surface-lowest: var(--bg);
  --m3-surface-low: var(--s1);
  --m3-surface: var(--s1);
  --m3-surface-high: var(--s2);
  --m3-surface-highest: var(--s2);
  --m3-surface-bright: var(--s2);
  --m3-on-surface: var(--ink);
  --m3-on-surface-variant: var(--ink2);
  --m3-outline: var(--ink3);
  --m3-outline-variant: var(--line);
  --m3-primary: var(--accT);
  --m3-primary-container: var(--acc);
  --m3-on-primary: var(--onAcc);
  --m3-on-primary-container: var(--onAcc);
  --m3-primary-fixed: var(--gold-300);  /* brand fill, hovered */
  --m3-primary-fixed-dim: var(--acc);
  --m3-secondary: var(--series-2);
  --m3-secondary-container: var(--series-2);
  --m3-tertiary-fixed: var(--series-5);
  --m3-tertiary-fixed-dim: var(--series-5);
  --m3-error: var(--dn);
  --m3-error-container: var(--dnBg);

  --card-radius: var(--r-card);

  --space-xs: var(--sp-1);
  --space-sm: var(--sp-2);
  --gutter-compact: var(--sp-3);
  --space-md: var(--sp-4);
  --space-lg: var(--sp-6);
  --space-xl: var(--sp-8);

  --shadow-card: var(--shadow-2);
  --cf-scrim: var(--scrim);
  --cf-scrim-strong: rgb(var(--scrim-rgb) / .88);
  --cf-modal-shadow: var(--shadow-3);

  --font-sans: var(--font-body);
}

/* elevation + glass fill, per theme (the light values are warm and low) */
:root, [data-theme="dark"] {
  --glass-strong: rgba(10,19,34,.88);
  --shadow-1: 0 1px 0 rgb(var(--tint) / .05) inset, 0 1px 2px rgb(var(--shade) / .5), 0 4px 12px rgb(var(--shade) / .35);
  --shadow-2: 0 1px 0 rgb(var(--tint) / .07) inset, 0 2px 4px rgb(var(--shade) / .45), 0 12px 32px rgb(var(--shade) / .45);
  --shadow-3: 0 1px 0 rgb(var(--tint) / .09) inset, 0 4px 10px rgb(var(--shade) / .5), 0 28px 64px rgb(var(--shade) / .6);
}

html{min-height:100%;background:var(--bg)}

/* ── LIGHT: ice white, the brand blue (deeper), navy type ───────────────── */
:root[data-theme="light"]:has(body.cf-themable),
html:has(body.cf-themable.cf-light){
  --bg: #f3f7fd;
  color-scheme: light;
}
:root[data-theme="light"] body.cf-themable,
body.cf-themable.cf-light{
  --bg: #f3f7fd; --s1: #ffffff; --s2: #eaf1fb;
  --ink: #0a1628; --ink2: #45536a; --ink3: #56647c; --body: #1a2638;
  --acc: #1f6fe0; --accT: #1652b8; --onAcc: #ffffff;
  --up: #0e6947; --upBg: rgba(14,105,71,.10);
  --dn: #c22e40; --dnBg: rgba(194,46,64,.10);
  --pro: #936100; --proBg: #fbf3e2; --proLine: #ebd6a8;
  --onPro: #ffffff;

  --ink-0: #0a1426; --ink-1: #f3f7fd; --ink-2: #e8eff9; --ink-3: #ffffff; --ink-4: #eaf1fb; --ink-5: #cfdbec;
  --ground-rgb: 243 247 253; --ground-hi: #f8fbff; --raise: 255 255 255;
  --card-hi: #ffffff; --card-lo: #f6f9fe; --sheet-hi: #ffffff; --sheet-lo: #f1f6fd;
  --well-hi: #e8eff9; --well-lo: #dde7f4; --badge-hi: #eef5ff; --badge-lo: #dce9fb; --surface-hover: #e8f0fb;
  --well: rgb(30 70 140 / .07);
  --glass: rgb(var(--raise) / .74); --glass-edge: rgb(var(--tint) / .11); --glass-edge-hi: rgb(var(--tint) / .2);
  --tint: 20 40 80; --shade: 30 50 90; --scrim-rgb: 8 18 38; --ion-ground: 226 250 246;
  --text-1: #0a1628; --text-2: #45536a; --text-3: #56647c; --text-4: #9eabbf;
  --accent-text: #1652b8; --accent-text-strong: #0f3f8f;
  --on-molten: #ffffff; --on-ion: #ffffff;
  --molten: linear-gradient(118deg, #4a9dff 0%, #2a7ff0 22%, #1f6fe0 46%, #1a5fc8 64%, #0f3f8f 100%);
  --molten-text: linear-gradient(100deg, #2a7ff0 0%, #1f6fe0 35%, #1652b8 70%, #0f3f8f 100%);
  --molten-hi: rgba(255,255,255,.45);
  --molten-lo: rgba(6,30,80,.35);
  --sheen-rgb: 255 255 255;
  --glow: 31 111 224;
  --ion: #0b7d70; --ion-rgb: 11 125 112;
  --up-rgb: 14 105 71; --dn-rgb: 194 46 64;
  --ember-l: 45%;
  --glass-strong: rgba(255,252,247,.94);
  --molten-edge: linear-gradient(180deg, rgba(255,255,255,.9), rgba(31,111,224,.18) 40%, rgba(31,111,224,0) 70%);
  --shadow-1: 0 1px 0 rgba(255,255,255,.8) inset, 0 1px 2px rgb(var(--shade) / .08), 0 4px 12px rgb(var(--shade) / .07);
  --shadow-2: 0 1px 0 rgba(255,255,255,.9) inset, 0 2px 4px rgb(var(--shade) / .07), 0 12px 32px rgb(var(--shade) / .1);
  --shadow-3: 0 1px 0 rgba(255,255,255,.9) inset, 0 4px 10px rgb(var(--shade) / .08), 0 28px 64px rgb(var(--shade) / .16);
  --focus-ring: 0 0 0 2px var(--ink-1), 0 0 0 4px var(--gold-600);
  --series-1: #1f6fe0; --series-2: #0b7d70; --series-3: #12895c; --series-4: #7d4fd0;
  --series-5: #d2622a; --series-6: #a8743c; --series-7: #9a8320; --series-8: #c23c78;
  --metal-boss-lo: #4a3218;
  --chain-solana: #7d4fd0; --chain-base: #2f5fd6; --chain-bsc: #a8840f;
  --chain-arbitrum: #2a7cc4; --chain-polygon: #6e44c4; --chain-robinhood: #5f7d12; --chain-ethereum: #4b5bc4; --chain-monad: #6a48c8; --chain-hyperevm: #11806a;
  --nav-feed: #0a76b8; --nav-discover: #7d4fd0; --nav-market: #12895c; --nav-bot: #0b7d70;
  --nav-traders: #c4581f; --nav-calls: #8a7314; --nav-leaderboard: #1652b8; --nav-groups: #4a68c8;
  --nav-promote: #c23c78; --nav-launch: #12895c; --nav-share: #56647c; --nav-admin: #1652b8;
  --nav-portfolio: #12895c; --nav-profile: #1652b8; --nav-trade: #1652b8; --nav-history: #4a68c8;
  --nav-referrals: #8a7314; --nav-settings: #56647c; --nav-about: #56647c;
  --rank-associate: #5d6470; --rank-soldier: #8a4f22; --rank-capo: #4f5866;
  --rank-underboss: #7a5420; --rank-boss: #6b4a14;
  --chart-crosshair: rgb(var(--glow) / .7);
}

/* Comfortable density: set on <body data-density="comfortable">. */
body[data-density="comfortable"]{ --pad: var(--pad-comfortable); }

body{
  background-color:var(--bg);
  background-image:var(--ground);
  background-repeat:repeat,no-repeat,no-repeat,no-repeat;
  background-attachment:fixed;
  color:var(--ink);
  font-family:var(--font-body);
  font-weight:500;
  -webkit-font-smoothing:antialiased;
  /* Without this the ground stops where the content does, and a short page
     shows the browser's own canvas below the fold. */
  min-height:100vh;
}
::selection{background:rgb(var(--glow) / .35);color:var(--ink)}

/* ── type ramp (DESIGN_PROMPT §2) ─────────────────────────────────────────── */
.cf-display{font:var(--fw-h1) var(--fs-h1)/var(--lh-h1) var(--font-display);letter-spacing:var(--tr-h1)}
.cf-page-title{font-family:var(--font-display);font-size:var(--fs-page-title);line-height:var(--lh-page-title);font-weight:var(--fw-page-title);letter-spacing:var(--tr-page-title)}
.cf-card-title{font-size:16px;line-height:1.3;font-weight:700}
.cf-handle{font-size:15px;font-weight:700}
.cf-body{font-size:14px;line-height:1.45;font-weight:500;color:var(--body)}
.cf-label{font-size:12px;font-weight:600}
.cf-mono-label{font-family:var(--font-mono);font-size:var(--fs-micro);font-weight:500}
/* Noir caps: 11px mono, wide tracking (section labels, table heads, chips) */
.cf-caps{font:600 var(--fs-micro)/var(--lh-micro) var(--font-mono);letter-spacing:var(--tr-caps);text-transform:uppercase;color:var(--ink3)}
.cf-molten-text{background:var(--molten-text);-webkit-background-clip:text;background-clip:text;color:transparent}
.cf-hero-price{font-family:var(--font-mono);font-size:var(--fs-figure-xl);font-weight:600;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.cf-row-figure{font-family:var(--font-num);font-size:13px;font-weight:500;font-variant-numeric:tabular-nums}
/* Earlier names, kept so pages that opted in keep their sizes. */
.cf-headline-lg{font-size:26px;line-height:1.2;font-weight:700}
.cf-headline-md{font-size:22px;line-height:1.25;font-weight:700}
.cf-headline-sm{font-size:18px;line-height:1.3;font-weight:700}
.cf-title-md{font-size:16px;line-height:1.3;font-weight:700}
.cf-body-lg{font-size:16px;line-height:1.45}
.cf-body-md{font-size:14px;line-height:1.45}
.cf-body-sm{font-size:12px;line-height:1.4}
.cf-label-md{font-size:12px;letter-spacing:.04em;font-weight:600;text-transform:uppercase}
.cf-label-sm{font-size:11px;letter-spacing:.08em;font-weight:700;text-transform:uppercase}

/* Figures: JetBrains Mono, tabular, so columns of prices align. */
.cf-num,.cf-data{font-family:var(--font-num);font-variant-numeric:tabular-nums}

.cf-pill,.cf-avatar{border-radius:var(--r-full)}

/* Focus ring (Noir --focus-ring: a 2px ground gap, then 2px gold), drawn as
   an outline so it never replaces an element's own shadow. */
:focus-visible{outline:2px solid var(--focus-c,var(--gold-300));outline-offset:2px}
:root[data-theme="light"] body.cf-themable{--focus-c:var(--gold-600)}

/* ── theme toggle ─────────────────────────────────────────────────────────── */
.cf-theme-toggle{
  width:40px;height:40px;flex:0 0 40px;
  display:inline-flex;align-items:center;justify-content:center;
  border-radius:var(--r-pill);border:1px solid var(--glass-edge-hi);
  background:var(--s2);color:var(--ink2);cursor:pointer;padding:0;box-shadow:var(--shadow-1);
  transition:color var(--dur-fast),background var(--dur-fast),border-color var(--dur-fast);
}
.cf-theme-toggle:hover{color:var(--accent-text-strong);border-color:rgb(var(--glow) / .45)}
.cf-theme-toggle svg{transition:transform var(--t-med) var(--ease-spring)}
.cf-theme-toggle:hover svg{transform:rotate(-18deg)}
.cf-theme-toggle svg{width:16px;height:16px;display:block}
.cf-theme-toggle .cf-ico-sun{display:none}
:root[data-theme="light"] .cf-theme-toggle .cf-ico-sun{display:block}
:root[data-theme="light"] .cf-theme-toggle .cf-ico-moon{display:none}

@media (prefers-reduced-motion:reduce){
  .cf-theme-toggle{transition:none}
}

/* ── brand marks (DESIGN_PROMPT §1) ───────────────────────────────────────
   The wordmark is set in TYPE: the display face, white on dark and ink on light
   -- "never set the wordmark in gold". New markup uses .cf-wordmark-text.

   .cf-wordmark is the older EMPTY element drawn through a mask image, still
   used in six places. It keeps working, recoloured to --ink (it was gold, which
   the brand rules now forbid) until each place moves to the text mark. */
.cf-wordmark-text{
  font-family:var(--font-display);font-weight:700;letter-spacing:.14em;
  color:var(--ink);text-transform:uppercase;white-space:nowrap;
}
.cf-wordmark{
  display:block;
  background-color:var(--ink);
  -webkit-mask-image:url('/static/img/cartel-family-wordmark-mask.png');
          mask-image:url('/static/img/cartel-family-wordmark-mask.png');
  -webkit-mask-size:contain;   mask-size:contain;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center;  mask-position:center;
}
.cf-tagline{
  font-family:var(--font-display);font-weight:700;letter-spacing:.26em;
  color:var(--accT);text-transform:uppercase;
}
.cf-icon-tile{
  display:block;border-radius:22%;object-fit:cover;
  background:url('/static/brand/icon-tile-128.png') center/cover no-repeat;
}

/* A member who predates handles (users.username empty) reads "unnamed" on
   every list -- never their wallet (handles.UNNAMED, decided 2026-10-09).
   Lower-case, muted, no '@': it is the absence of a name, not a name. */
.cf-unnamed{
  color:var(--ink3);font-weight:500;font-style:normal;text-transform:none;letter-spacing:0;
}

/* Native controls follow the theme. Without color-scheme the browser drew
   every <select>'s open list (Bridge's From/To, Convert's network, settings)
   in light-mode colours on the dark app -- white text on white, unreadable
   (owner's report, 2026-10-11). The open list is painted by the OS, so the
   options get the theme's own surface and ink as well. */
:root{color-scheme:dark}
:root[data-theme="light"]{color-scheme:light}
select option,select optgroup{background-color:var(--s1);color:var(--ink)}

/* ── shared primitives: icons and tooltips ────────────────────────────────
   CFIcon (static/cf-icons.js, Lucide subset) draws in currentColor at
   Lucide's own 2px stroke, 1em square unless a size is given. */
.cf-i{
  width:1em;height:1em;flex:none;display:inline-block;vertical-align:-.125em;
  fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;
}
/* The glyph beside a menu label (navigation.icon_svg / {{ nav_icon() }}):
   a fixed box that never shrinks or shifts, currentColor so it follows the
   row lit, dim, dark or light. The label stays; this only sits beside it. */
.cf-nav-i{flex:none;display:inline-block;vertical-align:-3px;width:16px;height:16px}
.cf-nav-i[width="18"]{width:18px;height:18px}
.cf-nav-i[width="14"]{width:14px;height:14px}
.cf-nav-i[width="12"]{width:12px;height:12px}
/* CFFloat tooltips ([data-cf-tip]). One shared node, positioned by
   Floating UI; never parked invisible -- it is display:none until shown. */
.cf-tip{
  display:none;z-index:9800;pointer-events:none;max-width:240px;
  padding:7px 10px;border-radius:var(--r-sm);
  background:var(--glass-strong);color:var(--ink);border:1px solid rgb(var(--glow) / .3);
  font:500 12px/1.35 var(--font-body);box-shadow:var(--shadow-3);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
}
.cf-tip.on{display:block}
/* One dropdown menu (CFFloat.menu positions it): the profile and DM "more"
   menus, a message's own menu, the admin role picker. Each used to carry its
   own copy of these rules, at three slightly different paddings. */
.cf-menu{
  display:none;position:absolute;z-index:900;min-width:150px;padding:4px;
  background:var(--glass-strong);border:1px solid var(--glass-edge-hi);border-radius:var(--r-md);box-shadow:var(--shadow-3);
  -webkit-backdrop-filter:blur(var(--blur)) saturate(var(--glass-saturate));backdrop-filter:blur(var(--blur)) saturate(var(--glass-saturate));
}
.cf-menu.open{display:block;animation:cf-pop-in var(--dur-pop) var(--ease-spring)}
@keyframes cf-pop-in{from{transform:translateY(-4px) scale(.97)}to{transform:none}}
.cf-menu>a,.cf-menu>button{
  display:flex;align-items:center;gap:8px;width:100%;min-height:36px;box-sizing:border-box;
  text-align:left;background:none;border:0;cursor:pointer;text-decoration:none;
  padding:0 10px;border-radius:var(--r-sm);font:500 13.5px var(--font-body);color:var(--ink);transition:background var(--dur-fast);
}
.cf-menu>a:hover,.cf-menu>button:hover,.cf-menu>a:focus-visible,.cf-menu>button:focus-visible{background:rgb(var(--tint) / .06)}
.cf-menu>.danger{color:var(--dn)}
@media (pointer:coarse){.cf-menu>a,.cf-menu>button{min-height:44px}}

/* ── motion system (2026-10-11: "looks plain, no animations") ─────────────
   One set of durations, easings and a stagger step, read by every surface
   (CSS here, JS through CFMotion, the Mini App through the same file) instead
   of the scattered .3s / .25s / cubic-bezier literals each stylesheet used to
   guess. Values are Syndicate Noir's (COMPONENTS.md "Motion & toasts"); the
   easings and --dur-fast/--dur/--dur-draw sit with the Noir tokens above.

   Two rules every class below obeys:
     - The RESTING state is the visible one. An entrance is a class script
       adds and removes on animationend (CFMotion.enter); nothing is parked
       at opacity 0 waiting for it, so a paused, hidden or printed page still
       shows its content.
     - prefers-reduced-motion shows the finished state: the classes stop
       animating and the content is simply there. */
:root{
  --dur-flash: .9s;            /* a price tick's glow, in and out            */
  --dur-enter: .6s;            /* a card, a row, a sheet arriving (--t-enter) */
  --dur-exit: .26s;            /* the same leaving -- always faster           */
  --dur-count: .9s;            /* a figure counting to its value (--t-count) */
  --dur-pop: .32s;             /* a like / follow / copy acknowledgement     */
  --stagger: 60ms;             /* between siblings entering together         */
  --stagger-max: 8;            /* siblings past this arrive with the 8th     */
}

/* enter: rise + fade, from script only (CFMotion.enter adds, then removes) */
@keyframes cf-enter-rise{from{opacity:0;transform:translateY(16px) scale(.985);filter:blur(4px)}to{opacity:1;transform:none;filter:none}}
@keyframes cf-enter-fade{from{opacity:0}to{opacity:1}}
@keyframes cf-enter-down{from{opacity:0;transform:translateY(-14px)}to{opacity:1;transform:none}}
@keyframes cf-enter-left{from{opacity:0;transform:translateX(28px)}to{opacity:1;transform:none}}
@keyframes cf-enter-right{from{opacity:0;transform:translateX(-28px)}to{opacity:1;transform:none}}
@keyframes cf-exit-left{from{opacity:1;transform:none}to{opacity:0;transform:translateX(-36px) rotate(-1.5deg)}}
@keyframes cf-exit-right{from{opacity:1;transform:none}to{opacity:0;transform:translateX(36px) rotate(1.5deg)}}
.cf-enter{animation:cf-enter-rise var(--dur-enter) var(--ease-out) var(--cf-delay,0s) both}
.cf-enter-fade{animation:cf-enter-fade var(--dur-enter) var(--ease-out) var(--cf-delay,0s) both}
.cf-enter-down{animation:cf-enter-down var(--dur-enter) var(--ease-out) var(--cf-delay,0s) both}
.cf-enter-left{animation:cf-enter-left var(--dur-enter) var(--ease-out) var(--cf-delay,0s) both}
.cf-enter-right{animation:cf-enter-right var(--dur-enter) var(--ease-out) var(--cf-delay,0s) both}
.cf-exit-left{animation:cf-exit-left var(--dur-exit) var(--ease-in) both}
.cf-exit-right{animation:cf-exit-right var(--dur-exit) var(--ease-in) both}

/* flash: a value that just moved tints up / down and settles back */
@keyframes cf-flash-up{0%{background-color:var(--upBg);color:var(--up);text-shadow:0 0 14px rgb(var(--up-rgb) / .8)}100%{background-color:transparent}}
@keyframes cf-flash-dn{0%{background-color:var(--dnBg);color:var(--dn);text-shadow:0 0 14px rgb(var(--dn-rgb) / .8)}100%{background-color:transparent}}
.cf-flash-up,.cf-flash-dn{border-radius:var(--r-badge)}
.cf-flash-up{animation:cf-flash-up var(--dur-flash) var(--ease-out)}
.cf-flash-dn{animation:cf-flash-dn var(--dur-flash) var(--ease-out)}

/* pop: an action acknowledged (like, follow, copy) */
@keyframes cf-pop{0%{transform:scale(1)}40%{transform:scale(1.18)}100%{transform:scale(1)}}
.cf-pop{animation:cf-pop var(--dur-pop) var(--ease-spring)}
/* a count that changed ticks up into place */
@keyframes cf-tick-up{from{transform:translateY(60%);opacity:.2}to{transform:none;opacity:1}}
@keyframes cf-tick-dn{from{transform:translateY(-60%);opacity:.2}to{transform:none;opacity:1}}
.cf-tick-up,.cf-tick-dn{display:inline-block}
.cf-tick-up{animation:cf-tick-up var(--dur-fast) var(--ease-out)}
.cf-tick-dn{animation:cf-tick-dn var(--dur-fast) var(--ease-out)}

/* a live dot: one soft pulse per new value (never an infinite loop) */
@keyframes cf-pulse{0%{box-shadow:0 0 0 0 var(--cf-pulse,rgb(var(--glow) / .55))}100%{box-shadow:0 0 0 12px transparent}}
.cf-pulse{animation:cf-pulse .7s var(--ease-out)}

/* the success mark: a ring and a tick that draw, used by the trade sheet */
.cf-mark{display:inline-block;width:44px;height:44px;color:var(--up)}
.cf-mark circle{stroke-dasharray:132;stroke-dashoffset:0}
.cf-mark path{stroke-dasharray:30;stroke-dashoffset:0}
.cf-mark.is-drawing circle{animation:cf-mark-ring .45s var(--ease-out) both}
.cf-mark.is-drawing path{animation:cf-mark-tick .3s var(--ease-out) .32s both}
@keyframes cf-mark-ring{from{stroke-dashoffset:132}to{stroke-dashoffset:0}}
@keyframes cf-mark-tick{from{stroke-dashoffset:30}to{stroke-dashoffset:0}}

/* "N new" pill: new items wait above the list instead of shoving it */
.cf-newpill{
  position:sticky;top:calc(var(--cf-sticky-top,72px) + 8px);z-index:30;
  display:flex;justify-content:center;height:0;overflow:visible;pointer-events:none;
}
.cf-newpill[hidden]{display:none}
.cf-newpill button{
  pointer-events:auto;display:inline-flex;align-items:center;gap:6px;
  height:36px;padding:0 16px;border-radius:var(--r-pill);cursor:pointer;
  border:1px solid rgb(var(--ion-rgb) / .45);background:var(--glass-strong);color:var(--ion);
  font:600 12.5px var(--font-mono);letter-spacing:.04em;
  box-shadow:var(--ion-glow),var(--shadow-3);animation:cf-enter-down var(--dur-enter) var(--ease-spring);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
}
.cf-newpill button:focus-visible{outline:2px solid var(--ion);outline-offset:2px}

/* skeleton shimmer: a loading block that says "loading", not "empty" */
@keyframes cf-shimmer{from{background-position:150% 0}to{background-position:-50% 0}}
.cf-skel{
  background:linear-gradient(90deg,rgb(var(--tint) / .04) 0%,rgb(var(--tint) / .1) 45%,rgb(var(--tint) / .04) 90%);
  background-size:200% 100%;animation:cf-shimmer 1.4s linear infinite;border-radius:var(--r-md);
}

@media (prefers-reduced-motion:reduce){
  .cf-enter,.cf-enter-fade,.cf-enter-down,.cf-enter-left,.cf-enter-right,
  .cf-flash-up,.cf-flash-dn,.cf-pop,.cf-tick-up,.cf-tick-dn,.cf-pulse,.cf-skel,
  .cf-newpill button{animation:none!important}
  .cf-exit-left,.cf-exit-right{animation:none!important;opacity:0}
  .cf-mark.is-drawing circle,.cf-mark.is-drawing path{animation:none!important}
}

/* Reduced motion: every Noir timing token is 0 -- no entrances, sweeps,
   ripples, magnet, shimmer or ring spin; the finished state shows. */
@media (prefers-reduced-motion:reduce){
  :root{--t-fast:0ms;--t-med:0ms;--t-slow:0ms;--t-enter:0ms;--t-count:0ms;--t-draw:0ms;--t-sweep:0ms;--t-ripple:0ms;--t-press:0ms}
  .cf-theme-toggle svg,.cf-menu.open{transition:none;animation:none}
}


/* ---- static/cf-noir.css ---- */
/* Cartel Family — SYNDICATE NOIR shared components (decided 2026-10-12).
 *
 * THE Noir component library. It began as the port of the prototype's
 * noir.css (spec COMPONENTS.md, both under /design/a/*, deleted 2026-10-15
 * once every surface wore it): the reference's `na-X` became the product's
 * `cf-X` (na-btn -> cf-btn, na-chip -> cf-chip, na-glass -> cf-glass,
 * na-tabs -> cf-tabs, na-sheet -> cf-sheet ...). Comments elsewhere that
 * name /design/a/* or static/design/a/* describe where a layout came from;
 * the classes and tokens they refer to live here and in cf-theme.css.
 *
 * Every value is a token from static/cf-theme.css; this file declares no
 * colour of its own. Loaded right after cf-theme.css on every surface
 * (noir_inject.py puts the <link> there), so any page, the Mini App, the admin
 * console and the landing can use these classes.
 *
 * Two rules every rule here keeps:
 *   - The RESTING state is the visible one. Entrances are classes script adds
 *     and removes (CFMotion.enter); nothing is parked at opacity 0.
 *   - Reduced motion is the finished state: no sweep, ripple, magnet,
 *     shimmer, pulse or spin; transitions off.
 */

/* ── glass panel: real depth, a 1px light edge on top ───────────────────── */
.cf-glass{
  position:relative;border-radius:var(--r-lg);
  background:linear-gradient(180deg,rgb(var(--raise) / .66),rgb(var(--raise) / .72) 38%,var(--glass));
  border:1px solid var(--glass-edge);box-shadow:var(--shadow-2);
  -webkit-backdrop-filter:blur(var(--blur)) saturate(var(--glass-saturate));
  backdrop-filter:blur(var(--blur)) saturate(var(--glass-saturate));
}
.cf-glass::before{
  content:'';position:absolute;inset:-1px;border-radius:inherit;padding:1px;pointer-events:none;
  background:var(--molten-edge);opacity:.9;
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}
.cf-panel{padding:var(--sp-5)}
.cf-panel-h{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);margin-bottom:var(--sp-4);flex-wrap:wrap}
.cf-panel-h h2,.cf-panel-h h3{margin:0;font:var(--fw-h3) var(--fs-h3)/var(--lh-h3) var(--font-display);letter-spacing:var(--tr-h3)}

/* ── live marker: the ion accent's one job ──────────────────────────────── */
.cf-live{display:inline-flex;align-items:center;gap:7px;font:600 var(--fs-micro)/1 var(--font-mono);letter-spacing:var(--tr-caps);color:var(--ion);text-transform:uppercase}
.cf-live::before{content:'';width:7px;height:7px;border-radius:50%;background:var(--ion);box-shadow:var(--ion-glow);animation:cf-beat 1.6s var(--ease-in-out) infinite}
.cf-live.is-off{color:var(--ink3)}
.cf-live.is-off::before{background:var(--text-4);box-shadow:none;animation:none}
@keyframes cf-beat{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.7)}}

/* ── buttons: magnetic, light sweep, press, ripple ──────────────────────── */
.cf-btn{
  --mx:0px;--my:0px;
  position:relative;display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:var(--tap);padding:0 20px;border-radius:var(--r-pill);border:1px solid var(--glass-edge-hi);
  background:var(--ink-4);color:var(--ink);cursor:pointer;overflow:hidden;isolation:isolate;
  font:600 14px/1 var(--font-display);letter-spacing:.01em;white-space:nowrap;text-decoration:none;
  transform:translate(var(--mx),var(--my)) scale(var(--press,1));
  transition:transform var(--t-med) var(--ease-spring),box-shadow var(--t-med) var(--ease-out),background var(--t-med),border-color var(--t-med);
  box-shadow:var(--shadow-1);-webkit-tap-highlight-color:transparent;user-select:none;
}
.cf-btn svg{width:18px;height:18px;flex:none}
.cf-btn::after{ /* the light sweep */
  content:'';position:absolute;inset:-2px;z-index:-1;pointer-events:none;
  background:linear-gradient(105deg,transparent 30%,rgb(var(--sheen-rgb) / .38) 46%,rgb(var(--sheen-rgb) / .06) 54%,transparent 64%);
  transform:translateX(-120%);transition:transform 0s;
}
@media (hover:hover){
  .cf-btn:hover{border-color:rgb(var(--glow) / .45);box-shadow:var(--shadow-2),0 0 0 1px rgb(var(--glow) / .18)}
  .cf-btn:hover::after{transform:translateX(120%);transition:transform var(--t-sweep) var(--ease-out)}
}
.cf-btn:active{--press:.95;transition-duration:var(--t-press)}
.cf-btn[disabled],.cf-btn[aria-disabled="true"]{opacity:.45;cursor:not-allowed}
.cf-btn--primary{
  background:var(--molten);color:var(--on-molten);border-color:var(--molten-hi);
  box-shadow:0 1px 0 rgb(var(--sheen-rgb) / .5) inset,0 -2px 0 var(--molten-lo) inset,0 6px 22px rgb(var(--glow) / .32),0 2px 4px rgb(var(--shade) / .4);
  text-shadow:0 1px 0 rgb(var(--sheen-rgb) / .45);
}
@media (hover:hover){
  .cf-btn--primary:hover{box-shadow:0 1px 0 rgb(var(--sheen-rgb) / .55) inset,0 -2px 0 var(--molten-lo) inset,0 10px 34px rgb(var(--glow) / .45),0 2px 4px rgb(var(--shade) / .4);border-color:rgb(var(--sheen-rgb) / .8)}
}
/* The sweep (::after, z-index -1 inside the button's own stacking context)
   always paints UNDER the label; what can still wash the label out is its
   colour. A page's scoped `.page a{color}` (0,1,1) outranks `.cf-btn--primary`
   (0,1,0), so a molten link button took the gold link colour -- gold on gold,
   which read as "washed out" the moment the sheen passed (the docs hero).
   :link/:visited lift the molten label above any such rule. */
a.cf-btn--primary:link,a.cf-btn--primary:visited{color:var(--on-molten)}
.cf-btn--ghost{background:transparent;box-shadow:none}
.cf-btn--ion{background:rgb(var(--ion-rgb) / .08);border-color:rgb(var(--ion-rgb) / .35);color:var(--ion)}
.cf-btn--danger{background:var(--dn-dim);color:var(--dn);border-color:rgb(var(--dn-rgb) / .45)}
@media (hover:hover){.cf-btn--danger:hover{border-color:var(--dn);box-shadow:var(--shadow-2),0 0 0 1px rgb(var(--dn-rgb) / .3)}}
.cf-btn--sm{min-height:36px;padding:0 14px;font-size:13px}
.cf-btn--sm::before{content:'';position:absolute;inset:-4px}   /* 36px pill, 44px to a finger */
.cf-btn--block{width:100%}
.cf-btn--icon{width:var(--tap);padding:0}
.cf-btn--xl{min-height:54px;padding:0 28px;font-size:16px}

/* The ripple CFMotion spawns at the pointer. On a .cf-btn it lives inside
   the button; on any other control it is a fixed overlay clipped to the
   control's own box and radius, so the control itself is never restyled. */
.cf-ripple{
  position:absolute;border-radius:50%;pointer-events:none;z-index:-1;transform:translate(-50%,-50%) scale(0);
  background:radial-gradient(circle,rgb(var(--sheen-rgb) / .55),rgb(var(--sheen-rgb) / 0) 70%);
  animation:cf-ripple var(--t-ripple) var(--ease-out) forwards;
}
.cf-ripple-host{position:fixed;overflow:hidden;pointer-events:none;z-index:var(--z-popover)}
.cf-ripple-host .cf-ripple{z-index:0;background:radial-gradient(circle,rgb(var(--sheen-rgb) / .32),rgb(var(--sheen-rgb) / 0) 70%)}
@keyframes cf-ripple{to{transform:translate(-50%,-50%) scale(1);opacity:0}}

/* Product controls that were drawn as a flat gold fill before Noir: CFMotion
   marks each one whose computed fill IS the theme's --acc with .cf-molten,
   and it takes the molten fill and the sweep. Nothing is restyled by a
   colour literal, and a control the page later repaints keeps its own look. */
.cf-molten{
  background-image:linear-gradient(105deg,transparent 30%,rgb(var(--sheen-rgb) / .38) 46%,rgb(var(--sheen-rgb) / .06) 54%,transparent 64%),var(--molten)!important;
  background-size:300% 100%,100% 100%!important;
  background-position:100% 0,0 0!important;
  background-repeat:no-repeat!important;
  color:var(--on-molten)!important;
  border-color:var(--molten-hi)!important;
  text-shadow:0 1px 0 rgb(var(--sheen-rgb) / .45);
  box-shadow:0 1px 0 rgb(var(--sheen-rgb) / .5) inset,0 -2px 0 var(--molten-lo) inset,0 6px 22px rgb(var(--glow) / .28);
  transition:background-position var(--t-sweep) var(--ease-out),box-shadow var(--t-med) var(--ease-out),scale var(--t-press);
}
@media (hover:hover){
  .cf-molten:hover{background-position:0 0,0 0!important;box-shadow:0 1px 0 rgb(var(--sheen-rgb) / .55) inset,0 -2px 0 var(--molten-lo) inset,0 10px 34px rgb(var(--glow) / .45)}
}
.cf-molten:disabled,.cf-molten[aria-disabled="true"]{box-shadow:none}
/* press: the individual `scale` property, so it composes with whatever
   transform the control already has (a centred FAB keeps its translate) */
.cf-pressing{scale:.95;transition:scale var(--t-press) var(--ease-out)}

/* ── chips ──────────────────────────────────────────────────────────────── */
.cf-chip{
  display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 9px;border-radius:var(--r-pill);
  background:rgb(var(--tint) / .05);border:1px solid var(--glass-edge);color:var(--ink2);
  font:600 10.5px/1 var(--font-mono);letter-spacing:.08em;text-transform:uppercase;white-space:nowrap;
}
.cf-chip i{width:6px;height:6px;border-radius:50%;background:var(--chain,var(--gold-400));box-shadow:0 0 8px var(--chain,transparent)}
.cf-chip--gold{color:var(--accent-text-strong);border-color:rgb(var(--glow) / .35);background:rgb(var(--glow) / .12)}
.cf-chip--ion{color:var(--ion);border-color:rgb(var(--ion-rgb) / .35);background:var(--ion-dim)}
.cf-chip--up{color:var(--up);border-color:rgb(var(--up-rgb) / .3);background:var(--up-dim)}
.cf-chip--dn{color:var(--dn);border-color:rgb(var(--dn-rgb) / .3);background:var(--dn-dim)}
button.cf-chip{cursor:pointer;min-height:32px;height:auto;padding:6px 12px;position:relative;transition:background var(--t-fast),color var(--t-fast),border-color var(--t-fast)}
button.cf-chip::before{content:'';position:absolute;inset:-6px -2px}
button.cf-chip[aria-pressed="true"]{color:var(--accent-text-strong);border-color:rgb(var(--glow) / .55);background:rgb(var(--glow) / .2)}
@media (hover:hover){button.cf-chip:hover{color:var(--ink);border-color:var(--glass-edge-hi)}}
.cf-chip[data-chain="solana"]{--chain:var(--chain-solana)}
.cf-chip[data-chain="base"]{--chain:var(--chain-base)}
.cf-chip[data-chain="bsc"]{--chain:var(--chain-bsc)}
.cf-chip[data-chain="arbitrum"]{--chain:var(--chain-arbitrum)}
.cf-chip[data-chain="polygon"]{--chain:var(--chain-polygon)}
.cf-chip[data-chain="robinhood"]{--chain:var(--chain-robinhood)}
.cf-chip[data-chain="ethereum"]{--chain:var(--chain-ethereum)}
.cf-chip[data-chain="monad"]{--chain:var(--chain-monad)}
.cf-chip[data-chain="hyperevm"]{--chain:var(--chain-hyperevm)}

/* ── avatars + token marks: API image over a designed fallback ──────────── */
.cf-ava{
  --s:40px;position:relative;flex:none;width:var(--s);height:var(--s);border-radius:50%;
  display:grid;place-items:center;overflow:hidden;color:var(--on-molten);
  font:700 calc(var(--s) * .4)/1 var(--font-display);background:var(--monogram,var(--molten));
  box-shadow:0 0 0 1px rgb(var(--tint) / .16),0 3px 10px rgb(var(--shade) / .45);
}
.cf-ava img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.cf-ava-wrap{position:relative;flex:none}
.cf-ava-wrap .cf-medal,.cf-medal-slot{position:absolute;right:-6px;bottom:-6px;line-height:0}
.cf-medal-slot:empty{display:none}
.cf-tok{
  --s:36px;position:relative;flex:none;width:var(--s);height:var(--s);border-radius:calc(var(--s) * .3);overflow:hidden;
  display:grid;place-items:center;background:var(--ink-4);box-shadow:0 0 0 1px var(--glass-edge-hi),var(--shadow-1);
}
.cf-tok svg{width:100%;height:100%}
.cf-tok img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.cf-faces{display:inline-flex}
.cf-faces .cf-ava{--s:22px;margin-left:-7px;box-shadow:0 0 0 2px var(--ink-3)}
.cf-faces .cf-ava:first-child{margin-left:0}

/* ── rank medallion (CFGame.medal draws the SVG) ────────────────────────── */
.cf-medal{display:inline-block;flex:none;line-height:0;filter:drop-shadow(0 3px 6px rgb(var(--shade) / .55))}
.cf-medal svg{display:block;overflow:visible}
.cf-medal .cf-sheen{transform:translateX(-140%) skewX(-18deg);transform-box:fill-box}
@media (hover:hover){
  .cf-medal:hover .cf-sheen,.cf-medal-host:hover .cf-sheen{transform:translateX(260%) skewX(-18deg);transition:transform 900ms var(--ease-out)}
}
.cf-medal.is-shining .cf-sheen{transform:translateX(260%) skewX(-18deg);transition:transform 900ms var(--ease-out)}

/* ── segmented tabs with a sliding molten indicator ─────────────────────── */
.cf-tabs{position:relative;display:inline-flex;gap:2px;padding:4px;border-radius:var(--r-pill);background:var(--ink-2);border:1px solid var(--glass-edge);max-width:100%;overflow-x:auto;scrollbar-width:none}
.cf-tabs::-webkit-scrollbar{display:none}
.cf-tab{position:relative;z-index:1;min-height:36px;padding:0 14px;border:0;border-radius:var(--r-pill);background:transparent;color:var(--ink2);cursor:pointer;font:600 13px/1 var(--font-display);white-space:nowrap;transition:color var(--t-med)}
.cf-tab::before{content:'';position:absolute;inset:-4px 0}
.cf-tab[aria-selected="true"]{color:var(--on-molten)}
@media (hover:hover){.cf-tab:not([aria-selected="true"]):hover{color:var(--ink)}}
.cf-tabs-ind{position:absolute;z-index:0;top:4px;bottom:4px;left:0;width:0;border-radius:var(--r-pill);background:var(--molten);box-shadow:0 4px 14px rgb(var(--glow) / .35);transition:transform var(--t-med) var(--ease-spring),width var(--t-med) var(--ease-out)}

/* ── card ───────────────────────────────────────────────────────────────── */
.cf-card{
  position:relative;padding:var(--sp-4);border-radius:var(--r-lg);
  background:linear-gradient(180deg,rgb(var(--raise) / .9),rgb(var(--raise) / .92));
  border:1px solid var(--glass-edge);box-shadow:var(--shadow-2);
  transition:transform var(--t-med) var(--ease-out),border-color var(--t-med),box-shadow var(--t-med);
}
@media (hover:hover){.cf-card.is-lift:hover,a.cf-card:hover{transform:translateY(-2px);border-color:rgb(var(--glow) / .22);box-shadow:var(--shadow-3)}}
.cf-card.is-new{animation:cf-arrive 700ms var(--ease-out)}
@keyframes cf-arrive{0%{box-shadow:0 0 0 1px var(--ion),0 0 30px rgb(var(--ion-rgb) / .35)}100%{box-shadow:var(--shadow-2)}}
.cf-well{padding:12px;border-radius:var(--r-md);background:var(--well);border:1px solid rgb(var(--tint) / .04)}

/* ── empty state: an engraved vault door, gently turning ────────────────── */
.cf-noir-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:28px 16px;text-align:center;color:var(--ink3);font-size:13.5px}
.cf-noir-empty svg{width:54px;height:54px;opacity:.9}
.cf-noir-empty b{color:var(--ink2);font-weight:600}
.cf-empty-dial{transform-origin:32px 32px;animation:cf-dial 9s var(--ease-in-out) infinite alternate}
@keyframes cf-dial{from{transform:rotate(-30deg)}to{transform:rotate(60deg)}}

/* ── skeleton: shaped like what replaces it ─────────────────────────────── */
.cf-skel-noir,.cf-shimmer{position:relative;overflow:hidden;border-radius:var(--r-md);background:rgb(var(--tint) / .04);min-height:18px}
.cf-skel-noir::after,.cf-shimmer::after{content:'';position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,rgb(var(--tint) / .06),transparent);animation:cf-sweep 1.4s infinite}
@keyframes cf-sweep{to{transform:translateX(100%)}}

/* ── sheet: bottom sheet on a phone, drawer from 900px ──────────────────── */
.cf-scrim{position:fixed;inset:0;z-index:var(--z-sheet);background:rgb(var(--scrim-rgb) / .66);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);animation:cf-enter-fade var(--t-med) var(--ease-out)}
.cf-sheet{
  position:fixed;z-index:calc(var(--z-sheet) + 1);left:0;right:0;bottom:0;max-height:88vh;overflow:auto;overscroll-behavior:contain;
  padding:10px var(--sp-5) calc(var(--sp-6) + env(safe-area-inset-bottom,0px));border-radius:var(--r-xl) var(--r-xl) 0 0;
  background:linear-gradient(180deg,var(--sheet-hi),var(--sheet-lo));border:1px solid var(--glass-edge-hi);border-bottom:0;box-shadow:var(--shadow-3);
  color:var(--ink);animation:cf-sheet-up var(--t-slow) var(--ease-spring);touch-action:pan-y;
}
.cf-sheet.is-closing{animation:cf-sheet-down 240ms var(--ease-in-out) forwards}
@keyframes cf-sheet-up{from{transform:translateY(100%)}to{transform:none}}
@keyframes cf-sheet-down{to{transform:translateY(105%)}}
.cf-sheet-grab{width:44px;height:5px;margin:0 auto 14px;border-radius:3px;background:var(--ink-5)}
.cf-sheet h2{margin:0 0 4px;font:700 22px/1.2 var(--font-display);letter-spacing:-.02em}
.cf-sheet-sub{margin:0 0 var(--sp-4);color:var(--ink2);font-size:14px}
.cf-sheet-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:var(--sp-4)}
.cf-sheet-actions .cf-btn{flex:1 1 160px}
@media (min-width:900px){
  .cf-sheet{left:auto;top:0;width:440px;max-height:none;border-radius:var(--r-xl) 0 0 var(--r-xl);border-bottom:1px solid var(--glass-edge-hi);border-right:0;padding-top:var(--sp-6);animation-name:cf-drawer-in}
  .cf-sheet.is-closing{animation-name:cf-drawer-out}
  .cf-sheet-grab{display:none}
}
@keyframes cf-drawer-in{from{transform:translateX(100%)}to{transform:none}}
@keyframes cf-drawer-out{to{transform:translateX(105%)}}

/* ── overlay: a centred moment (rank-up) ────────────────────────────────── */
.cf-overlay{
  position:fixed;inset:0;z-index:var(--z-overlay);display:grid;place-items:center;padding:20px;
  background:radial-gradient(circle at 50% 45%,rgb(var(--glow) / .22),rgb(var(--scrim-rgb) / .82) 60%);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);animation:cf-enter-fade 320ms var(--ease-out);
}
.cf-overlay.is-out{opacity:0;transition:opacity 240ms}
@keyframes cf-noir-pop{from{transform:scale(.7);opacity:0}to{transform:none;opacity:1}}

/* ── fields, inputs, presets, switch ────────────────────────────────────── */
.cf-field{display:grid;gap:6px;margin:12px 0}
.cf-field label,.cf-field>span{font:600 var(--fs-micro)/1 var(--font-mono);letter-spacing:var(--tr-caps);text-transform:uppercase;color:var(--ink3)}
.cf-presets{display:flex;gap:8px;flex-wrap:wrap}
.cf-input{
  min-height:var(--tap);padding:0 14px;border-radius:var(--r-md);background:var(--ink-2);border:1px solid var(--glass-edge-hi);
  color:var(--ink);font:500 16px/1 var(--font-mono);width:100%;box-sizing:border-box;
  transition:border-color var(--t-fast),box-shadow var(--t-fast);
}
.cf-input:focus-visible{outline:none;border-color:var(--gold-400);box-shadow:0 0 0 3px rgb(var(--glow) / .2)}
.cf-switch{position:relative;flex:none;width:52px;height:30px;padding:0;border-radius:15px;border:1px solid var(--glass-edge-hi);background:var(--ink-2);cursor:pointer;transition:background var(--t-med),border-color var(--t-med)}
.cf-switch::before{content:'';position:absolute;inset:-8px -4px}
.cf-switch i{position:absolute;top:3px;left:3px;width:22px;height:22px;border-radius:50%;background:var(--ink3);box-shadow:var(--shadow-1);transition:transform var(--t-med) var(--ease-spring),background var(--t-med)}
.cf-switch[aria-checked="true"]{background:rgb(var(--glow) / .25);border-color:rgb(var(--glow) / .6)}
.cf-switch[aria-checked="true"] i{transform:translateX(22px);background:var(--molten);box-shadow:0 0 12px rgb(var(--glow) / .6)}

/* ── table ──────────────────────────────────────────────────────────────── */
.cf-table-wrap{overflow-x:auto;max-width:100%}
.cf-table{width:100%;border-collapse:separate;border-spacing:0;font-size:13.5px}
.cf-table th{text-align:left;padding:0 10px 10px;font:600 10px/1 var(--font-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--ink3);border-bottom:1px solid var(--glass-edge);white-space:nowrap}
.cf-table td{padding:12px 10px;border-bottom:1px solid rgb(var(--tint) / .05);vertical-align:middle}
.cf-table tbody tr{transition:background var(--t-fast)}
.cf-table tbody tr:hover{background:rgb(var(--tint) / .03)}
.cf-table .r{text-align:right;font-family:var(--font-mono);font-variant-numeric:tabular-nums}
.cf-cell-p{display:inline-flex;align-items:center;gap:8px;font-weight:600}

/* ── progress bar (curve, season, XP) ───────────────────────────────────── */
.cf-bar{position:relative;display:block;height:6px;border-radius:3px;background:rgb(var(--tint) / .06);overflow:hidden}
.cf-bar i{position:absolute;inset:0 auto 0 0;width:0;border-radius:inherit;background:var(--molten);box-shadow:0 0 10px rgb(var(--glow) / .5);transition:width 900ms var(--ease-out)}
.cf-bar.is-ion i{background:linear-gradient(90deg,rgb(var(--ion-rgb) / .3),var(--ion));box-shadow:var(--ion-glow)}

/* ── headings ───────────────────────────────────────────────────────────── */
.cf-eyebrow{display:inline-flex;align-items:center;gap:10px;font:600 var(--fs-micro)/1 var(--font-mono);letter-spacing:.22em;text-transform:uppercase;color:var(--accT)}
.cf-eyebrow::before{content:'';width:26px;height:1px;background:linear-gradient(90deg,transparent,var(--gold-400))}
.cf-h1{margin:0;font:var(--fw-h1) var(--fs-h1)/var(--lh-h1) var(--font-display);letter-spacing:var(--tr-h1)}
.cf-h2{margin:10px 0 8px;font:var(--fw-h2) var(--fs-h2)/var(--lh-h2) var(--font-display);letter-spacing:var(--tr-h2)}
.cf-lede{margin:0;max-width:60ch;color:var(--ink2);font-size:16px}

/* ── house-account badge (house_accounts.py): "House bot" / "Official" beside
   the name of a platform account, on every surface that shows a person. The
   payload decides (account_kind); static/cf-house.js draws it. ─────────── */
.cf-house{display:inline-flex;align-items:center;gap:4px;height:18px;max-width:max-content;padding:0 7px;border-radius:var(--r-full);
  font:700 9.5px/1 var(--font-mono);letter-spacing:.08em;text-transform:uppercase;white-space:nowrap;vertical-align:middle;
  color:var(--accent-text-strong);border:1px solid rgb(var(--glow) / .38);background:rgb(var(--glow) / .13);flex:none}
.cf-house svg{width:10px;height:10px;flex:none}
.cf-house--official{color:var(--on-molten);border-color:transparent;background:var(--molten)}
[data-theme="light"] .cf-house{color:var(--accT)}
.cf-house-note{margin:6px 0 0;font:500 13px/1.5 var(--font-ui);color:var(--ink2)}
.cf-house-note b{color:var(--ink);font-weight:700}
.cf-house-group{margin-top:14px;padding-top:10px;border-top:1px solid var(--glass-edge)}
.cf-house-group-h{display:flex;align-items:center;gap:8px;margin:0 0 6px;font:600 var(--fs-micro)/1 var(--font-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--ink3)}

/* ── reduced motion: the finished state ─────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  .cf-live::before,.cf-skel-noir::after,.cf-shimmer::after,.cf-empty-dial{animation:none}
  .cf-btn,.cf-card,.cf-tabs-ind,.cf-bar i,.cf-switch,.cf-switch i,.cf-molten,.cf-pressing{transition:none}
  .cf-btn::after{display:none}
  .cf-ripple{display:none}
  .cf-btn{transform:none}
  .cf-sheet,.cf-scrim,.cf-overlay,.cf-card.is-new{animation:none}
  .cf-molten:hover{background-position:100% 0,0 0!important}
}

/* ── brand marks: a chain's or launchpad's real logo BESIDE its name ─────── */
/* (owner, 2026-10-13; brand_logos.py + cf-brand.js). Fixed box, so nothing
   shifts while it loads; the dot above stays only where no mark exists. A
   project that publishes its mark only as mono white / mono black ships both
   files: --dark is drawn on the dark theme, --light on the light one. */
.cf-logo{flex:none;display:inline-block;width:14px;height:14px;object-fit:contain;vertical-align:-2px;border-radius:3px;background:transparent}
.cf-chip .cf-logo{width:12px;height:12px;margin-left:-2px;vertical-align:-1px}
.cf-logo--lg{width:20px;height:20px;border-radius:5px}
.cf-logo--light{display:none}
.cf-logo-slot{display:none}   /* a dot-less placeholder cf-brand.js fills once the registry answers */
[data-theme="light"] .cf-logo--dark{display:none}
[data-theme="light"] .cf-logo--light{display:inline-block}
/* The Mini App outside Telegram follows a light OS theme with body.cf-light and no
   data-theme attribute: the light-theme mark must follow it there too. */
.cf-light .cf-logo--dark{display:none}
.cf-light .cf-logo--light{display:inline-block}
/* A pale mark (HyperEVM mint) vanishes on the light ground: it sits on a neutral dark plate from the tokens. */
[data-theme="light"] .cf-logo[src*="/chains/hyperevm"]{background:var(--ink-0);padding:1px;border-radius:50%}
[aria-disabled="true"] .cf-logo,[disabled] .cf-logo{opacity:.7}

/* ── Alive: XP chip, streak flame, season strip, success check (2026-10-14) ─
 * Fed by cf-toast.js's pulse. The resting state is the finished one; every
 * motion runs on a CHANGE only and not under prefers-reduced-motion. */
.cf-xpchip-wrap{position:relative;flex:none;margin-left:8px}
.cf-xpchip{position:relative;display:inline-flex;align-items:center;gap:6px;min-height:36px;padding:0 12px;border-radius:var(--r-pill,999px);
  border:1px solid var(--glass-edge-hi);background:var(--glass-bg,rgb(var(--sheen-rgb) / .06));color:var(--ink);font:600 12px/1 var(--font-mono);cursor:pointer}
.cf-xpchip b{font-weight:700}
.cf-xpchip small{color:var(--ink3);font-size:10px;letter-spacing:.08em}
.cf-xpchip:hover{border-color:var(--gold-300)}
.cf-xpchip:focus-visible{outline:2px solid var(--gold-300);outline-offset:2px}
.cf-xpchip-sep{width:1px;height:14px;background:var(--glass-edge-hi)}
.cf-flame{display:inline-grid;place-items:center;width:16px;height:16px;color:var(--ink3)}
.cf-flame svg{width:16px;height:16px}
.cf-flame.on{color:var(--gold-300);filter:drop-shadow(0 0 6px rgb(var(--glow) / .6))}
.cf-flame.risk{color:var(--ember,var(--gold-300))}
.cf-xpchip-pop{position:absolute;right:6px;top:-4px;pointer-events:none;color:var(--gold-200,var(--gold-300));font:700 12px/1 var(--font-mono)}
.cf-xpchip-pop.go{animation:cf-xp-pop .9s var(--ease-out) forwards}
.cf-xpchip.bump{animation:cf-xp-bump .5s var(--ease-spring)}
@keyframes cf-xp-pop{0%{opacity:0;transform:translateY(6px) scale(.8)}20%{opacity:1}100%{opacity:0;transform:translateY(-20px) scale(1.1)}}
@keyframes cf-xp-bump{0%{transform:scale(1)}40%{transform:scale(1.08)}100%{transform:scale(1)}}
.cf-xpp{position:absolute;right:0;top:calc(100% + 8px);z-index:var(--z-pop,9400);width:min(300px,calc(100vw - 32px));padding:14px;border-radius:var(--r-lg,16px);
  border:1px solid var(--glass-edge-hi);background:linear-gradient(180deg,var(--sheet-hi),var(--sheet-lo));box-shadow:var(--shadow-3);color:var(--ink)}
.cf-xpp[hidden]{display:none}
.cf-xpp-rank{display:flex;align-items:center;gap:10px}
.cf-xpp-rank b{display:block;font:700 16px/1.1 var(--font-display)}
.cf-xpp-rank small{color:var(--ink3);font:600 11px var(--font-mono)}
.cf-xpbar{height:8px;border-radius:99px;background:rgb(var(--sheen-rgb) / .1);overflow:hidden;margin:12px 0 6px}
.cf-xpbar i{display:block;height:100%;border-radius:99px;background:var(--molten-text,var(--gold-300));transition:width .7s var(--ease-out)}
.cf-xpbar i.glint{animation:cf-xp-glint .9s var(--ease-out)}
@keyframes cf-xp-glint{0%{filter:brightness(1.9)}100%{filter:none}}
.cf-xpp-next,.cf-xpp-season{margin:0 0 10px;font:500 12px/1.4 var(--font-body);color:var(--ink2)}
.cf-xpp-season{margin:8px 0 0}
.cf-xpp-streak{display:flex;align-items:center;gap:10px;padding-top:10px;border-top:1px solid var(--glass-edge-hi)}
.cf-xpp-streak b{display:block;font:700 13px var(--font-display)}
.cf-xpp-streak small{display:block;color:var(--ink3);font:500 11px/1.3 var(--font-body)}
.cf-xpp-streak .cf-flame{width:22px;height:22px}.cf-xpp-streak .cf-flame svg{width:22px;height:22px}
.cf-xpp-week{margin-left:auto;display:flex;gap:3px}
.cf-xpp-week i{width:7px;height:7px;border-radius:50%;background:rgb(var(--sheen-rgb) / .16)}
.cf-xpp-week i.on{background:var(--gold-300)}
.cf-xpp-week i.today{outline:1px solid var(--gold-300);outline-offset:1px}
@media (max-width:1024px){.cf-xpchip{min-height:44px}}
@media (max-width:640px){.cf-xpchip{padding:0 9px}.cf-xpchip small{display:none}}
/* the season strip on the feed */
.cf-race{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:10px 14px;border-radius:var(--r-lg,16px);border:1px solid var(--glass-edge-hi);
  background:var(--glass-bg,rgb(var(--sheen-rgb) / .05));font:500 13px var(--font-body);color:var(--ink2)}
.cf-race[hidden]{display:none}
.cf-race-k{font:600 var(--fs-micro,10px) var(--font-mono);letter-spacing:var(--tr-caps,.1em);text-transform:uppercase;color:var(--ink3)}
.cf-race-pos{font:700 20px/1 var(--font-display);color:var(--ink)}
.cf-race-track{flex:1 1 80px;min-width:80px;height:6px;border-radius:99px;background:rgb(var(--sheen-rgb) / .1);overflow:hidden}
.cf-race-track i{display:block;height:100%;background:var(--molten-text,var(--gold-300));border-radius:99px;transition:width .8s var(--ease-out)}
.cf-race-pts{font:600 12px var(--font-mono);color:var(--ink)}
.cf-race-link{color:var(--gold-300);font:600 12px var(--font-mono);text-decoration:none}
.cf-race.moved .cf-race-pos{animation:cf-xp-bump .7s var(--ease-spring);color:var(--gold-200,var(--gold-300))}
/* success check drawn on a confirmed trade / copy (sheets add .cf-check) */
.cf-check{display:inline-block;width:56px;height:56px;color:var(--ok,var(--gold-300))}
.cf-check circle,.cf-check path{fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.cf-check circle{stroke-dasharray:151;stroke-dashoffset:0}
.cf-check path{stroke-dasharray:40;stroke-dashoffset:0}
.cf-check.draw circle{animation:cf-draw .55s var(--ease-out) both}
.cf-check.draw path{animation:cf-draw .4s var(--ease-out) .35s both}
@keyframes cf-draw{from{stroke-dashoffset:151}to{stroke-dashoffset:0}}
/* staggered arrival: the class is added from script and removed on end */
.cf-arrive{animation:cf-arrive .5s var(--ease-out) both;animation-delay:calc(var(--i,0) * 55ms)}
@keyframes cf-arrive{from{transform:translateY(10px)}to{transform:none}}
@media (prefers-reduced-motion:reduce){
  .cf-xpchip-pop.go,.cf-xpchip.bump,.cf-xpbar i.glint,.cf-race.moved .cf-race-pos,.cf-check.draw circle,.cf-check.draw path,.cf-arrive{animation:none}
  .cf-xpbar i,.cf-race-track i{transition:none}
}


/* ---- static/cf-charts.css ---- */
/* Cartel Family — shared chart primitives (see cf-charts.js), dressed in
   Syndicate Noir (COMPONENTS.md §16): every line carries a two-step glow
   trail in its own colour, the end point is a 9px dot ringed in the ground
   with the shared pulse, the readouts are glass with a gold edge. Tokens
   only; the line colour itself comes from cf-charts.js (read off <body>). */

/* the glow trail: the path's `color` is its stroke (set by cf-charts.js) */
.cf-line{filter:drop-shadow(0 0 4px color-mix(in srgb,currentColor 55%,transparent)) drop-shadow(0 0 12px color-mix(in srgb,currentColor 35%,transparent))}
.cf-line--spark{filter:drop-shadow(0 0 3px color-mix(in srgb,currentColor 50%,transparent))}

.cf-chart{position:relative;width:100%}
.cf-chart-svg{display:block;width:100%;height:100%;overflow:visible}

/* The tooltip is an HTML element rather than SVG text: it needs to stay
   upright and legibly sized while the SVG itself is stretched by
   preserveAspectRatio:none, which would distort any text drawn inside it. */
.cf-chart-tip{
  /* The design's readout: 132px wide, value over clock time, centred. */
  position:absolute;top:-6px;transform:translateX(-50%);box-sizing:border-box;
  width:132px;text-align:center;
  pointer-events:none;opacity:0;transition:opacity var(--t-fast,.13s);
  background:var(--glass-strong);border:1px solid rgb(var(--glow) / .3);border-radius:var(--r-sm);
  padding:6px 9px;white-space:nowrap;z-index:5;
  box-shadow:var(--shadow-3);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
}
.cf-chart-tip.on{opacity:1}
.cf-chart-tip b{
  display:block;color:var(--ink);font:500 12px/1.3 var(--font-num);
  font-variant-numeric:tabular-nums;overflow:hidden;text-overflow:ellipsis;
}
.cf-chart-tip i{display:block;color:var(--ink2);font:500 10px/1.3 var(--font-num);font-style:normal;margin-top:1px}

.cf-chart-end{position:absolute;width:7px;height:7px;border-radius:50%;
  transform:translate(-50%,-50%);pointer-events:none;z-index:2;
  box-shadow:0 0 0 3px rgb(var(--ground-rgb) / .85),0 0 14px currentColor;width:9px;height:9px}
/* The live pulse (cf-charts.js addPulse): a ring the size of the dot, grown
   and faded by ONE requestAnimationFrame loop for the page -- transform and
   opacity only. At rest it is invisible decoration; the dot is the mark. */
.cf-pulse-ring{position:absolute;inset:0;border-radius:50%;opacity:0;
  pointer-events:none;will-change:transform,opacity;transform-origin:50% 50%}
.cf-spark-end{position:absolute;width:5px;height:5px;border-radius:50%;
  transform:translate(-50%,-50%);pointer-events:none;z-index:2}
/* The latest value on the right edge (opts.lastLabel); slides with the line. */
.cf-chart-last{position:absolute;right:0;transform:translateY(-50%);z-index:3;
  font:600 11px/1.3 var(--font-num);color:var(--onAcc);
  padding:2px 6px;border-radius:6px;white-space:nowrap;pointer-events:none;
  font-variant-numeric:tabular-nums}
/* A redraw with a new series cross-fades: the old drawing on top, fading. */
.cf-chart-ghost{position:absolute;inset:0;pointer-events:none;z-index:1}

/* Label of the dashed gold entry line (CFCharts.area opts entry + entryLabel). */
.cf-chart-entry{
  position:absolute;left:8px;transform:translateY(-100%);margin-top:-4px;
  font:600 11px/1.3 var(--font-num);color:var(--onAcc);background:var(--acc);
  padding:2px 6px;border-radius:6px;white-space:nowrap;pointer-events:none;
}

/* Candles: OHLC readout top-left; the price under the pointer shown as
   gold pill on the right edge. */
.cf-ohlc{
  position:absolute;left:8px;top:8px;display:flex;gap:12px;flex-wrap:wrap;
  font:500 12px/1.3 var(--font-num);color:var(--ink2);background:var(--glass-strong);
  border:1px solid rgb(var(--glow) / .3);border-radius:var(--r-sm);padding:6px 10px;
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  pointer-events:none;opacity:0;transition:opacity .13s;z-index:4;max-width:calc(100% - 16px);
}
.cf-ohlc.on{opacity:1}
.cf-ohlc b{font-weight:500}
.cf-ohlc b.up{color:var(--up)}
.cf-ohlc b.down{color:var(--dn)}
.cf-chart-pricepill{
  position:absolute;right:0;transform:translateY(-50%);
  font:600 11px/1.3 var(--font-num);color:var(--onAcc);background:var(--acc);
  padding:3px 6px;border-radius:6px;pointer-events:none;opacity:0;z-index:4;
}
.cf-chart-pricepill.on{opacity:1}
.cf-candles{cursor:crosshair;touch-action:pan-y;user-select:none}

.cf-chart-empty{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:7px;min-height:120px;height:100%;color:var(--muted);
  font-size:12px;text-align:center;padding:18px 12px;
}
.cf-chart-empty svg{opacity:.5}

.cf-spark{display:block;width:100%;line-height:0}
/* The spark readout sits above the line so a finger does not cover it. */
.cf-spark{position:relative}
.cf-spark-tip{top:auto;bottom:calc(100% + 4px);padding:3px 7px;width:auto;min-width:0}
.cf-spark-tip b{font-size:11.5px}
.cf-spark-svg{display:block;width:100%;height:100%}

/* donut */
.cf-donut{display:flex;flex-direction:column;align-items:center;gap:12px}
.cf-donut-svg{display:block;width:168px;height:168px;max-width:100%}
.cf-donut-center{
  position:absolute;top:0;left:50%;transform:translateX(-50%);
  width:168px;height:168px;display:flex;flex-direction:column;
  align-items:center;justify-content:center;pointer-events:none;
}
.cf-donut-center b{
  color:var(--text);font-size:17px;font-weight:600;letter-spacing:-.02em;
  font-family:var(--font-mono);
}
.cf-donut-center i{color:var(--muted);font-size:10px;font-style:normal;
  text-transform:uppercase;letter-spacing:.12em;margin-top:2px}
.cf-donut-legend{display:flex;flex-wrap:wrap;gap:8px 14px;justify-content:center;width:100%}
.cf-dl-item{display:inline-flex;align-items:center;gap:6px;font-size:11px;color:var(--muted)}
.cf-dl-item i{width:8px;height:8px;border-radius:2px;flex:0 0 8px}
.cf-dl-item b{color:var(--text);font-weight:700;
  font-family:var(--font-mono)}

/* A card wrapper pages can reuse so charts sit consistently. */
.cf-chart-card{
  position:relative;border-radius:var(--r-lg);padding:16px 18px 14px;
  background:linear-gradient(180deg,rgb(var(--raise) / .66),rgb(var(--raise) / .72) 38%,var(--glass));
  border:1px solid var(--glass-edge);box-shadow:var(--shadow-2);
}
.cf-chart-head{display:flex;align-items:baseline;justify-content:space-between;
  gap:10px;margin-bottom:12px;flex-wrap:wrap}
.cf-chart-title{font:600 var(--fs-micro,11px)/1.2 var(--font-mono);letter-spacing:var(--tr-caps,.16em);
  text-transform:uppercase;color:var(--muted)}
.cf-chart-value{font-size:20px;font-weight:600;color:var(--text);letter-spacing:-.02em;
  font-family:var(--font-mono);font-variant-numeric:tabular-nums}
.cf-chart-delta{font-size:11.5px;font-weight:600;font-family:var(--font-mono)}
.cf-chart-delta.up{color:var(--green)}
.cf-chart-delta.down{color:var(--red)}
.cf-chart-delta.flat{color:var(--muted)}

@media (prefers-reduced-motion:reduce){
  .cf-chart-tip,.cf-ohlc{transition:none}
  .cf-pulse-ring,.cf-chart-ghost{display:none}
  .cf-line,.cf-line--spark{filter:none}
}
/* bars(): the optional label row under the slots (opts.ticks). */
.cf-chart-axis{position:relative;height:16px;margin-top:2px}
.cf-chart-axis span{position:absolute;top:0;transform:translateX(-50%);font:500 10px var(--font-num);color:var(--ink3);white-space:nowrap}

/* Keyboard readout (opts.keyboard; always on for heatmap and histogram):
   the chart is focusable and shows a visible focus ring. */
.cf-chart-kb{outline:none;border-radius:8px}
.cf-chart-kb:focus-visible{box-shadow:var(--focus-ring,0 0 0 2px var(--bg),0 0 0 4px var(--accT))}

/* donut(): a hovered / focused legend row (opts.hover). */
.cf-dl-item[tabindex]{cursor:pointer;border-radius:6px;padding:2px 4px;margin:-2px -4px}
.cf-dl-item.on{color:var(--text)}
.cf-dl-item[tabindex]:focus-visible{outline:2px solid var(--accT);outline-offset:1px}

/* heatmap(): squares keep their shape; a long range scrolls in its own box. */
.cf-heat{display:flex;flex-direction:column;gap:8px}
.cf-heat-scroll{overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;padding-top:2px}
.cf-heat-svg{display:block;height:auto}
/* SVG text never wraps; it only must not inherit a nowrap meant for HTML text. */
.cf-heat-svg text{white-space:normal;user-select:none}
.cf-heat-legend{display:flex;align-items:center;gap:3px;justify-content:flex-end;
  font:500 10px var(--font-num);color:var(--ink3)}
.cf-heat-legend span{margin:0 4px}
.cf-heat-legend i{width:10px;height:10px;border-radius:2px;display:inline-block}
.cf-heat-tip{transform:translate(-50%,calc(-100% - 8px));width:auto;min-width:132px;max-width:220px}

/* histogram(): the marker's label rides above the plot. */
.cf-hist{height:100%}
.cf-hist-marker{position:absolute;top:0;transform:translateX(-50%);pointer-events:none;
  font:600 10px/1.3 var(--font-num);color:var(--onAcc);background:var(--acc);
  padding:1px 6px;border-radius:5px;white-space:nowrap}
.cf-hist-axis{height:18px;margin-top:0}


/* ── CFPriceChart (cf-price-chart.js): price pane, volume pane, readout ── */
.cf-pc{position:relative}
.cf-pc-wrap{position:relative;border-radius:12px;overflow:hidden;background:var(--s1)}
.cf-pc{outline:none;border-radius:12px}
.cf-pc:focus-visible{box-shadow:0 0 0 2px var(--bg),0 0 0 4px var(--accT)}
/* Candle mode's live dot: placed by transform on the library's coordinates. */
.cf-pc-dot{position:absolute;left:0;top:0;width:9px;height:9px;border-radius:50%;
  pointer-events:none;z-index:3;box-shadow:0 0 0 3px rgb(var(--ground-rgb) / .85),0 0 14px rgb(var(--glow) / .6)}
.cf-pc-price,.cf-pc-vol{position:relative;width:100%}
.cf-pc-vol{border-top:1px solid var(--line)}
.cf-pc-empty{display:flex;align-items:center;justify-content:center;height:100%;min-height:220px;
  color:var(--ink3);font:500 13px/1.4 var(--font-body);text-align:center;padding:0 16px}
.cf-pc-tip{position:absolute;top:10px;left:12px;z-index:4;pointer-events:none;opacity:0;transform:translateY(-4px);
  transition:opacity var(--t-fast,.14s),transform var(--t-fast,.14s);background:var(--glass-strong);border:1px solid rgb(var(--glow) / .3);border-radius:var(--r-sm);
  padding:7px 10px;box-shadow:var(--shadow-3);max-width:min(92%,420px);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
.cf-pc-tip.on{opacity:1;transform:none}
.cf-pc-tip.right{left:auto;right:64px}
.cf-pc-tip i{display:block;font:500 10px/1.3 var(--font-num);color:var(--ink3);font-style:normal;letter-spacing:.02em}
.cf-pc-tip b{display:flex;flex-wrap:wrap;gap:4px 10px;font:600 12px/1.4 var(--font-num);color:var(--ink);
  font-variant-numeric:tabular-nums;margin-top:2px}
.cf-pc-tip em{display:inline-block;margin-top:2px;font:600 11px/1.3 var(--font-num);font-style:normal}
.cf-pc-tip em.up{color:var(--up)} .cf-pc-tip em.dn{color:var(--dn)}
.cf-pc-tip small{display:block;margin-top:2px;font:500 10px/1.3 var(--font-num);color:var(--ink2)}
/* Entrance: a left-to-right reveal on first paint, a crossfade on a rebuild.
   Both are added from script and removed on animationend; the resting state
   is fully visible, so a paused tab never leaves a chart hidden. */
.cf-pc-reveal{animation:cfPcReveal var(--t-draw,.7s) var(--ease-out) both}
@keyframes cfPcReveal{from{clip-path:inset(0 100% 0 0);opacity:.6}to{clip-path:inset(0 0 0 0);opacity:1}}
.cf-pc-swap{animation:cfPcSwap var(--t-med,.28s) var(--ease-out) both}
@keyframes cfPcSwap{from{opacity:.25;transform:translateY(4px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.cf-pc-reveal,.cf-pc-swap{animation:none}.cf-pc-tip{transition:none}}


/* ---- static/cf-trade-card.css ---- */
/* Cartel Family — THE trade card (see cf-trade-card.js), SYNDICATE NOIR.
 *
 * Drawn to the reference's person card (/design/a/app#feed, static/design/a
 * noir.css ".na-tc*"): a glass card (cf-card), a person row (44px avatar
 * with its rank medallion, @handle in display type, the rank chip + "68%
 * win · 2m ago" in mono, the side chip on the right -- Bought on the ion
 * accent), the token WELL (40px token mark, $SYM 17px, price · size, and the
 * figure in 20px mono on the right), the 34px curve under it, and the foot:
 * the faces of who else is in it, then Share (ghost icon), Buy (secondary)
 * and Copy (molten primary) -- all three are cf-btn from cf-noir.css.
 *
 * Every colour is a Noir token from cf-theme.css, so both themes come for
 * free. One card at every width; only the foot wraps on a narrow card.
 * Rendered by Home, Discover, Live Market and Calls alike.
 */

.tc{
  container:tc / inline-size;
  position:relative;
  display:flex;flex-direction:column;gap:0;
  padding:var(--sp-4, 16px);
  border-radius:var(--r-lg);
  background:linear-gradient(180deg, rgb(var(--raise) / .9), rgb(var(--raise) / .92));
  border:1px solid var(--glass-edge);
  box-shadow:var(--shadow-2);
  color:var(--text-1);
  font-family:var(--font-body, var(--font-display));
  box-sizing:border-box;
  transition:transform var(--t-med) var(--ease-out), border-color var(--t-med), box-shadow var(--t-med);
}
@media (hover:hover){
  .tc:hover{transform:translateY(-2px);border-color:rgb(var(--glow) / .22);box-shadow:var(--shadow-3)}
}

/* ── person row ────────────────────────────────────────────────────────── */
.tc-who{display:flex;align-items:center;gap:12px;min-width:0}
.tc-person{
  display:flex;align-items:center;gap:12px;min-width:0;flex:1 1 auto;
  color:inherit;text-decoration:none;border-radius:var(--r-md);
}
.tc-person:focus-visible,.tc-tok:focus-visible{outline:2px solid var(--gold-400);outline-offset:2px}
.tc-av-wrap{position:relative;flex:none;line-height:0}
.tc-av{
  width:44px;height:44px;flex:0 0 44px;border-radius:50%;object-fit:cover;
  background:var(--ink-4);display:flex;align-items:center;justify-content:center;
  box-shadow:0 0 0 1px rgb(var(--tint) / .16), 0 3px 10px rgb(var(--shade) / .45);
}
.tc-medal{position:absolute;right:-6px;bottom:-6px;line-height:0}
.tc-medal:empty{display:none}
.tc-ini{font:700 15px/1 var(--font-display);color:var(--on-molten)}
/* Initials discs: the molten monogram the reference draws (warm, never
   candy). The per-wallet hue classes stay for the surfaces that read them. */
.tc .tc-ini{background:var(--molten);color:var(--on-molten)}
.tc-av-empty{background:rgb(var(--tint) / .04);border:1px dashed var(--text-4);color:var(--text-3);box-sizing:border-box;box-shadow:none}
.tc-av-empty svg{width:20px;height:20px}
.tc-id{display:flex;flex-direction:column;gap:3px;min-width:0}
.tc-name-row{display:flex;align-items:center;gap:6px;min-width:0}
.tc-name{
  font:600 15px/1.25 var(--font-display);color:var(--text-1);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;
}
.tc-person:hover .tc-name{color:var(--accent-text-strong)}
.tc-verified{width:13px;height:13px;flex:0 0 13px;color:var(--accent-text)}
.tc-meta{
  display:flex;align-items:center;gap:6px;min-width:0;
  font:500 12px/1.4 var(--font-mono);color:var(--text-3);font-variant-numeric:tabular-nums;
}
.tc-meta-t{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.tc-rankchip{flex:none;display:inline-flex}
.tc-rankchip:empty{display:none}
.is-nobody .tc-name{color:var(--text-2)}
/* the side chip: .cf-chip's shape, uppercase mono */
.tc-pill{
  margin-left:auto;flex:0 0 auto;white-space:nowrap;
  display:inline-flex;align-items:center;height:24px;padding:0 9px;border-radius:var(--r-pill);
  font:600 10.5px/1 var(--font-mono);letter-spacing:.08em;text-transform:uppercase;
  background:rgb(var(--tint) / .05);border:1px solid var(--glass-edge);color:var(--text-2);
}
.tc-pill-bought{color:var(--ion);border-color:rgb(var(--ion-rgb) / .35);background:var(--ion-dim)}
.tc-pill-sold{color:var(--text-2)}
.tc-pill-called,.tc-pill-launched{color:var(--accent-text-strong);border-color:rgb(var(--glow) / .35);background:rgb(var(--glow) / .12)}
.tc-pill-graduated{color:var(--up);border-color:rgb(var(--up-rgb) / .3);background:var(--up-dim)}

/* ── the token well ────────────────────────────────────────────────────── */
.tc-trade{
  display:grid;align-items:center;
  grid-template-columns:minmax(0,1fr) auto;
  column-gap:12px;
  margin:14px 0 12px;padding:12px;
  border-radius:var(--r-md);background:var(--well);border:1px solid rgb(var(--tint) / .04);
}
.tc-tok{display:flex;align-items:center;gap:12px;min-width:0;color:inherit;text-decoration:none;border-radius:var(--r-sm)}
.tc-tok:hover .tc-sym{color:var(--accent-text-strong)}
.tc-logo{
  width:40px;height:40px;flex:0 0 40px;border-radius:12px;object-fit:cover;background:var(--ink-4);
  box-shadow:0 0 0 1px var(--glass-edge-hi), var(--shadow-1);
}
.tc .tc-logo.tc-ini{background:var(--ink-4);color:var(--accent-text-strong);font:700 15px/1 var(--font-display)}
.tc-logo.tc-ini,.tc-face.tc-ini{display:flex;align-items:center;justify-content:center}
.tc-tok-id{display:flex;flex-direction:column;gap:3px;min-width:0}
.tc-sym{
  display:flex;align-items:center;gap:6px;min-width:0;
  font:700 17px/1.1 var(--font-display);letter-spacing:-.01em;color:var(--text-1);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.tc-chain{
  display:inline-flex;align-items:center;height:20px;padding:0 7px;border-radius:var(--r-pill);
  font:600 9.5px/1 var(--font-mono);letter-spacing:.08em;text-transform:uppercase;color:var(--text-2);
  background:rgb(var(--tint) / .05);border:1px solid var(--glass-edge);
}
.tc-px{
  font:500 12px/1.4 var(--font-mono);color:var(--text-3);
  font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.tc-px-v{color:var(--text-2)}
.tc-spark{position:relative;height:34px;min-width:0;margin:-2px 0 10px}
.tc-spark .cf-spark-svg{width:100%;height:100%;overflow:visible}
.tc-spark-none{
  display:flex;align-items:center;justify-content:center;height:100%;
  font:500 11px/1.2 var(--font-mono);color:var(--text-4);text-align:center;
}
.tc-fig{display:flex;flex-direction:column;align-items:flex-end;gap:3px;text-align:right;min-width:0}
.tc-fig-v{
  font:600 20px/1.1 var(--font-mono);font-variant-numeric:tabular-nums;white-space:nowrap;letter-spacing:-.02em;
}
.tc-fig-v.up{color:var(--green);text-shadow:0 0 14px rgb(var(--up-rgb) / .25)}
.tc-fig-v.down{color:var(--dn)}
.tc-fig-v.flat{color:var(--text-1)}
.tc-fig-sub{font:500 11px/1.3 var(--font-mono);color:var(--text-3);white-space:nowrap}

.tc-cap{margin:0 0 12px;font:400 14px/1.5 var(--font-body, var(--font-display));color:var(--text-2)}

/* ── compact market facts (token surfaces) ─────────────────────────────── */
.tc-stats{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));margin:0 0 12px;gap:8px;
}
.tc-stats>div{min-width:0;padding:8px 10px;border-radius:var(--r-sm);background:var(--well)}
.tc-stats dt{font:600 10px/1.3 var(--font-mono);letter-spacing:.12em;text-transform:uppercase;color:var(--text-3)}
.tc-stats dd{
  margin:4px 0 0;font:600 13px/1.3 var(--font-mono);color:var(--text-1);
  font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* ── the foot: who else is in it, then the actions ─────────────────────── */
.tc-social{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}
.tc-faces{display:inline-flex;align-items:center;flex:0 0 auto}
.tc-face{
  width:22px;height:22px;border-radius:50%;object-fit:cover;background:var(--ink-4);
  box-shadow:0 0 0 2px var(--ink-3);font-size:8px;
}
.tc-face + .tc-face{margin-left:-7px}
.tc-also{
  font:500 12.5px/1.3 var(--font-display);color:var(--text-2);
  min-width:0;flex:1 1 120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.tc-rep{font:500 12px/1.3 var(--font-mono);color:var(--text-3);padding:0 4px;white-space:nowrap;flex:0 0 auto}
.tc-acts{margin-left:auto;display:flex;gap:8px;flex:0 0 auto}
/* The buttons ARE cf-btn (cf-noir.css: magnet, sweep, press, ripple); this
   keeps only what the card adds: the copying state and the disabled one. */
.tc-btn svg{width:16px;height:16px;flex:none}
.tc-btn.cf-btn--icon svg{width:17px;height:17px}
.tc-btn.cf-btn--icon{width:36px;min-width:36px;padding:0;border-color:var(--glass-edge-hi)}
.tc-btn:focus-visible{outline:2px solid var(--gold-400);outline-offset:2px}
.tc-copy.is-copying{
  background:var(--up-dim)!important;color:var(--up)!important;border-color:rgb(var(--up-rgb) / .45)!important;
  box-shadow:none!important;text-shadow:none!important;
}
.tc-copy.is-copying svg{display:none}
.tc-copy:disabled{opacity:.5;cursor:default}

/* ── a launch: the bonding curve inside the well ─────────────────────────
   (launch_feed.py). The bar is the curve's own progress to graduation from
   the pool account; unknown reads "reading curve…", never 0%. */
.tc-launch .tc-trade,.tc-graduated .tc-trade{grid-template-columns:minmax(0,1fr) auto;row-gap:10px}
.tc-launch .tc-tok,.tc-graduated .tc-tok{grid-row:1;grid-column:1}
.tc-launch .tc-fig,.tc-graduated .tc-fig{grid-row:1;grid-column:2}
.tc-curve{grid-row:2;grid-column:1 / -1;display:flex;align-items:center;gap:10px;min-width:0}
.tc-curve-bar{display:block;flex:1 1 auto;min-width:48px;height:6px;border-radius:3px;background:rgb(var(--tint) / .06);overflow:hidden}
.tc-curve-bar i{display:block;height:100%;border-radius:inherit;background:var(--molten);box-shadow:0 0 10px rgb(var(--glow) / .5)}
.tc-curve.is-grad .tc-curve-bar i{background:var(--up);box-shadow:0 0 10px rgb(var(--up-rgb) / .4)}
.tc-curve.is-unknown .tc-curve-bar i{width:100%;background:rgb(var(--tint) / .08);box-shadow:none}
.tc-curve-t{flex:0 1 auto;font:500 11.5px/1.2 var(--font-mono);color:var(--text-2);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums}
.tc-curve.is-grad .tc-curve-t{color:var(--up)}
.tc[data-tc-href]{cursor:pointer}
.tc[data-tc-href] .tc-social{cursor:default}
.tc-buy{min-width:70px}
@media (prefers-reduced-motion:no-preference){
  .tc.tc-in .tc-curve-bar i{animation:tcGrow .6s cubic-bezier(.2,.8,.2,1)}
}
@keyframes tcGrow{from{transform:scaleX(0)}to{transform:none}}
.tc-curve-bar i{transform-origin:left center}

/* A narrow card (a 320-360 phone): the chain chip and price line give way
   before the symbol; the foot wraps its actions onto their own line. */
@container tc (max-width:340px){
  .tc-fig-v{font-size:17px}
  .tc-chain{display:none}
  .tc-curve-t{max-width:62%}
}

/* ── entrance ─────────────────────────────────────────────────────────
   MOVEMENT ONLY, never opacity: app-ux.css pauses animations on a hidden
   tab, and a card parked at opacity 0 waiting for one stays invisible in a
   background tab, a thumbnail or a screenshot (CLAUDE.md). The class is
   added from script, removed on animationend and by a timer, and never
   added under reduced motion. */
@media (prefers-reduced-motion:no-preference){
  .tc.tc-in{animation:tcIn .5s var(--ease-out, cubic-bezier(.2,.8,.2,1))}
}
@media (prefers-reduced-motion:reduce){
  .tc{transition:none}
  .tc:hover{transform:none}
}
@keyframes tcIn{from{transform:translateY(12px)}to{transform:none}}

/* Touch: the person and the token are links, and each is a 44px target.
   The rows pull in by the added height, so the card measures as drawn. */
@media (pointer:coarse){
  .tc-person{min-height:44px;margin-top:-2px;margin-bottom:-2px;}
  .tc-tok{min-height:44px;margin-top:-2px;margin-bottom:-2px;}
}

/* Touch: the actions are 44px boxes, not only 44px hit areas. */
@media (pointer:coarse), (hover:none){
  .tc-btn.cf-btn--sm{ min-height:44px; }
  .tc-btn.cf-btn--icon{ width:44px; min-width:44px; }
}


/* ---- static/cf-promoted.css ---- */
/* Cartel Family — promoted token placements (PAID). Styles for cf-promoted.js.
 *
 * SYNDICATE NOIR promoted card (owner, 2026-10-16: the thin gold box "looks
 * plain"). A glass panel with a slow conic edge in the brand ramp (one turn in 6s), a soft
 * ember glow behind the token's logo, the token's real figures and curve,
 * the molten Buy with its light sweep and a ghost Chart. ONE component; the
 * host carries the size: .is-card (feed, Discover, Calls), .is-row (Traders,
 * Leaderboard), .is-banner (Live Market). The layout follows the slot's OWN
 * width (container queries), so a 300px aside and a 1200px column both fit.
 *
 * Every colour here is a cf-theme.css token. A literal would be correct in one
 * theme and wrong in the other, and this block has to stay legible in both
 * because its whole job is to be read as an advertisement.
 *
 * The disclosure is the word "Promoted" on amber on every card, plus "Paid
 * placement" beside it. The design is explicit: paid placement always carries
 * the word "Promoted" on amber — never the gain colour (a paid label painted
 * like a profit reads as a positive signal) and never the brand fill (which
 * reads as the platform's endorsement). The pill's label is --onPro, the
 * ink for an amber FILL (--on-gold failed AA on it in light mode); focus
 * rings are --gold. The molten fill is on the Buy BUTTON only, as on every
 * primary action in the product.
 *
 * Reduced motion is the finished state: the edge rests, no ember breath, no
 * sweep, no entrance; the figures and the curve are drawn in full.
 */

@property --cf-promo-a { syntax: '<angle>'; inherits: false; initial-value: 0deg; }

.cf-promo {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* Mounted into containers of very different widths (a full-width column,
     a 300px aside), so the card lays out on its OWN width. */
  container-type: inline-size;
  flex: 0 0 auto;
  margin: 0;
}
.cf-promo[hidden] { display: none; }

/* ── the panel ──────────────────────────────────────────────────────────── */
.cf-promo-card {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: 16px;
  border-radius: var(--r-lg, 20px);
  color: var(--ink);
  font-family: var(--font-ui);
  background:
    radial-gradient(260px 160px at 44px 64px, rgb(var(--glow) / .16), transparent 70%),
    linear-gradient(180deg, rgb(var(--raise) / .66), rgb(var(--raise) / .72) 38%, var(--glass));
  border: 1px solid var(--glass-edge);
  box-shadow: var(--shadow-2), 0 10px 36px rgb(var(--glow) / .14);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(var(--glass-saturate));
  backdrop-filter: blur(var(--blur)) saturate(var(--glass-saturate));
}
/* The edge: a conic sweep of the brand ramp (--glow, so it follows the
   brand and both themes) masked to a 2px ring, one slow turn. */
.cf-promo-card::before {
  content: '';
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: inherit;
  padding: 2px;
  pointer-events: none;
  background: conic-gradient(from var(--cf-promo-a),
    rgb(var(--glow) / .3) 0deg, rgb(var(--glow) / 1) 45deg, rgb(var(--sheen-rgb) / .95) 62deg,
    rgb(var(--glow) / .85) 80deg, rgb(var(--glow) / .3) 140deg, rgb(var(--glow) / .3) 200deg,
    rgb(var(--glow) / .8) 250deg, rgb(var(--glow) / .3) 320deg);
  -webkit-mask: linear-gradient(black 0 0) content-box, linear-gradient(black 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(black 0 0) content-box, linear-gradient(black 0 0);
  mask-composite: exclude;
  animation: cf-promo-spin 6s linear infinite;
}
@keyframes cf-promo-spin { to { --cf-promo-a: 360deg; } }

/* ── head: the disclosure, then where it trades ─────────────────────────── */
.cf-promo-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 10px;
  min-width: 0;
}
.cf-promo-badge {
  flex: 0 0 auto;
  font: 800 11px/1.3 var(--font-ui);
  letter-spacing: .02em;
  color: var(--onPro);   /* amber FILL label: see --onPro in cf-theme.css */
  background: var(--pro);
  padding: 4px 9px;
  border-radius: var(--r-badge, 6px);
}
.cf-promo-note {
  font: 600 11px/1.3 var(--font-mono, var(--font-num));
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink2);
}
.cf-promo-tags {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-left: auto;
  min-width: 0;
}
.cf-promo-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 9px;
  border-radius: var(--r-pill, 999px);
  background: rgb(var(--tint) / .06);
  border: 1px solid var(--glass-edge);
  font: 600 12px/1 var(--font-ui);
  color: var(--ink2);
  white-space: nowrap;
}
.cf-promo-tag .cf-logo { width: 14px; height: 14px; flex: none; }

/* ── body: the card size by default ─────────────────────────────────────── */
.cf-promo-body {
  display: grid;
  margin-top: 14px;
  gap: 12px 16px;
  align-items: center;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "id    quote"
    "spark spark"
    "stats here"
    "acts  acts";
}
.cf-promo-id {
  grid-area: id;
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  color: inherit;
  text-decoration: none;
  border-radius: var(--r-md, 14px);
}
a.cf-promo-id:hover .cf-promo-sym { text-decoration: underline; }

.cf-promo-logo {
  --s: 48px;
  position: relative;
  flex: none;
  width: var(--s);
  height: var(--s);
  border-radius: calc(var(--s) * .3);
  display: grid;
  place-items: center;
  background: var(--molten);
  color: var(--on-molten);
  box-shadow: 0 0 0 1px var(--glass-edge-hi), 0 4px 14px rgb(var(--shade) / .4);
}
/* The ember behind the logo: a soft, breathing warmth, never a ring. */
.cf-promo-logo::before {
  content: '';
  position: absolute;
  inset: -18px;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(var(--glow) / .55), rgb(var(--glow) / 0) 66%);
  filter: blur(4px);
  pointer-events: none;
  animation: cf-promo-ember 3.6s var(--ease-in-out, ease-in-out) infinite alternate;
}
@keyframes cf-promo-ember { from { opacity: .55; transform: scale(.9); } to { opacity: 1; transform: scale(1.08); } }
.cf-promo-letter { font: 800 calc(var(--s) * .42)/1 var(--font-display, var(--font-ui)); }
.cf-promo-logo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  background: var(--ink-4);
}

.cf-promo-names { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cf-promo-sym {
  font: 800 18px/1.15 var(--font-display, var(--font-ui));
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cf-promo-name {
  font: 500 13px/1.3 var(--font-ui);
  color: var(--ink2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cf-promo-quote {
  grid-area: quote;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  min-width: 0;
}
.cf-promo-price {
  font: 700 18px/1.1 var(--font-num, var(--font-mono));
  color: var(--ink);
  white-space: nowrap;
}
.cf-promo-price.is-up { animation: cf-promo-up .9s var(--ease-out, ease-out); }
.cf-promo-price.is-dn { animation: cf-promo-dn .9s var(--ease-out, ease-out); }
@keyframes cf-promo-up { from { color: var(--up); } }
@keyframes cf-promo-dn { from { color: var(--dn); } }
.cf-promo-chg {
  font: 700 12px/1 var(--font-num, var(--font-mono));
  padding: 4px 7px;
  border-radius: var(--r-pill, 999px);
  white-space: nowrap;
}
.cf-promo-chg.up { color: var(--up); background: var(--up-dim, var(--upBg)); }
.cf-promo-chg.dn { color: var(--dn); background: var(--dn-dim, var(--dnBg)); }
.cf-promo-chg.flat { color: var(--ink3); background: rgb(var(--tint) / .06); }
.cf-promo-chg i { font-style: normal; opacity: .7; margin-right: 4px; font-weight: 600; }

.cf-promo-spark {
  grid-area: spark;
  position: relative;
  height: 40px;
  min-width: 0;
}
.cf-promo-spark .cf-spark-svg { width: 100%; height: 100%; display: block; }
.cf-promo-nochart {
  display: flex;
  align-items: center;
  height: 100%;
  font: 500 12px/1.3 var(--font-ui);
  color: var(--ink3);
  border-top: 1px dashed var(--line);
  border-bottom: 1px dashed var(--line);
  padding: 0 4px;
}

.cf-promo-stats {
  grid-area: stats;
  display: flex;
  gap: 18px;
  margin: 0;
  min-width: 0;
}
.cf-promo-stats div { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cf-promo-stats dt {
  font: 600 10px/1 var(--font-mono, var(--font-num));
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink3);
}
.cf-promo-stats dd {
  margin: 0;
  font: 700 14px/1.1 var(--font-num, var(--font-mono));
  color: var(--ink);
  white-space: nowrap;
}

.cf-promo-here {
  grid-area: here;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  min-width: 0;
}
.cf-promo-faces { display: inline-flex; }
.cf-promo-face {
  position: relative;
  width: 22px;
  height: 22px;
  margin-left: -6px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  overflow: hidden;
  font: 700 10px/1 var(--font-display, var(--font-ui));
  color: var(--on-molten);
  background: var(--molten);
  box-shadow: 0 0 0 2px var(--ink-3);
}
.cf-promo-face:first-child { margin-left: 0; }
.cf-promo-face img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cf-promo-here-t { font: 500 12px/1.3 var(--font-ui); color: var(--ink2); white-space: nowrap; }
.cf-promo-here-t b { color: var(--ink); font-weight: 700; }

.cf-promo-acts {
  grid-area: acts;
  display: flex;
  gap: 10px;
  min-width: 0;
}
.cf-promo-acts .cf-btn { min-height: var(--tap, 44px); }
.cf-promo-buy { flex: 1 1 auto; font-weight: 700; }
.cf-promo-chart { flex: 0 0 auto; padding: 0 18px; }
/* The molten Buy carries the sweep on its own, every few seconds, not only
   on hover: it is the one thing on the card to press. */
.cf-promo-buy::after { animation: cf-promo-sweep 6s var(--ease-out, ease-out) 1.4s infinite; }
@keyframes cf-promo-sweep {
  0% { transform: translateX(-120%); }
  16%, 100% { transform: translateX(120%); }
}

/* ── the row (Traders, Leaderboard) and the banner (Live Market) ───────── */
@container (min-width: 600px) {
  .cf-promo.is-row .cf-promo-body,
  .cf-promo.is-banner .cf-promo-body {
    grid-template-columns: minmax(180px, 1.3fr) minmax(120px, 1fr) auto;
    grid-template-areas:
      "id    spark quote"
      "stats here  acts";
  }
  .cf-promo.is-row .cf-promo-here,
  .cf-promo.is-banner .cf-promo-here { justify-content: flex-start; }
  .cf-promo.is-row .cf-promo-acts .cf-btn,
  .cf-promo.is-banner .cf-promo-acts .cf-btn { flex: 0 0 auto; }
  .cf-promo.is-row .cf-promo-buy,
  .cf-promo.is-banner .cf-promo-buy { min-width: 132px; }
}
@container (min-width: 980px) {
  .cf-promo.is-row .cf-promo-body,
  .cf-promo.is-banner .cf-promo-body {
    grid-template-columns: minmax(200px, 1.2fr) minmax(140px, 1fr) auto auto auto auto;
    grid-template-areas: "id spark quote stats here acts";
    gap: 12px 22px;
  }
}
.cf-promo.is-banner .cf-promo-card { padding: 18px 20px; }
.cf-promo.is-banner .cf-promo-logo { --s: 56px; }
.cf-promo.is-banner .cf-promo-sym { font-size: 20px; }
.cf-promo.is-banner .cf-promo-spark { height: 48px; }

/* A narrow slot (the 300px Discover aside, a 320px phone): one column. */
@container (max-width: 340px) {
  .cf-promo-body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "id" "quote" "spark" "stats" "here" "acts";
  }
  .cf-promo-quote { flex-direction: row; align-items: center; justify-content: flex-start; gap: 8px; }
  .cf-promo-here { justify-content: flex-start; }
  .cf-promo-tags { margin-left: 0; }
}

/* ── the entrance: added by script, taken off again; never a resting state */
.cf-promo-in .cf-promo-card { animation: cf-promo-enter .55s var(--ease-out, ease-out); }
@keyframes cf-promo-enter { from { opacity: 0; transform: translateY(10px) scale(.985); } }

/* ── unsold: the slot offering itself, at the server's price ───────────── */
.cf-promo-card.is-sell {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  min-height: 40px;
  padding: 12px 16px;
  border-radius: var(--r-card, 14px);
}
.cf-promo-card.is-sell::before { animation: none; opacity: .55; }
/* Unsold (CFFeed / CFDiscover): "Promote your token here" 700 15 beside the
   pill, the price line "— SOL · 24h" in mono 12, then the outlined action. */
.cf-promo-card.is-sell .cf-promo-sym { flex: 0 0 auto; min-width: 0; font: 700 15px/1.3 var(--font-ui); white-space: normal; }
.cf-promo-card.is-sell .cf-promo-desc { flex: 1 1 0; font: 500 12px/1.3 var(--font-num); }

.cf-promo-desc {
  flex: 1 1 0;
  min-width: 0;
  font: 500 13px/1.3 var(--font-ui);
  color: var(--ink2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Unsold: the design's outlined "Buy this slot" -- 40px inside a 1px amber
   line, 700 13 in --pro like the pill. Gold here read as the platform's own
   button; the design keeps paid placement amber. The line is an inset
   shadow so a touch screen can hang a 44px hit area on it. */
.cf-promo-sell {
  flex: 0 0 auto;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  padding: 0 16px;
  border-radius: var(--r-control, 10px);
  font: 700 13px/1 var(--font-ui);
  cursor: pointer;
  text-decoration: none;
  box-sizing: border-box;
  color: var(--pro);
  background: transparent;
  border: 0;
  box-shadow: inset 0 0 0 1px var(--pro);
}
.cf-promo-sell:hover { background: var(--proBg); filter: brightness(1.12); }

.cf-promo-sell:focus-visible,
.cf-promo-id:focus-visible,
.cf-promo-own:focus-visible,
.cf-promo-acts .cf-btn:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.cf-promo-own {
  align-self: flex-end;
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  font: 600 12px/1.3 var(--font-ui);
  color: var(--accT);
  text-decoration: none;
}
.cf-promo-own:hover { text-decoration: underline; }

/* The Leaderboard's UNSOLD row: flush in the list, no card of its own, the
   action as a text link. A sold promotion there is the full row card. */
.cf-promo[data-cf-promoted-variant="row"] .cf-promo-card.is-sell {
  border: 0;
  border-radius: 0;
  padding: 12px 16px;
  min-height: 0;
  background: none;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.cf-promo[data-cf-promoted-variant="row"] .cf-promo-card.is-sell::before { display: none; }
.cf-promo[data-cf-promoted-variant="row"] .cf-promo-card.is-sell .cf-promo-sym { font-size: 13px; }
.cf-promo[data-cf-promoted-variant="row"] .cf-promo-sell {
  height: auto;
  padding: 0;
  box-shadow: none;
  border-radius: 0;
  background: none;
  line-height: normal;
}
.cf-promo[data-cf-promoted-variant="row"] .cf-promo-sell:hover { background: none; }
.cf-promo[data-cf-promoted-variant="row"].is-empty .cf-promo-own { display: none; }

@container (max-width: 300px) {
  .cf-promo-card.is-sell .cf-promo-desc { flex-basis: 100%; order: 3; }
  .cf-promo-sell { order: 2; }
}

/* Touch: the unsold slot's call to action is a 44px target. The drawn face
   stays 40px: the extra height is transparent border above and below. */
@media (pointer: coarse) {
  .cf-promo-card.is-sell .cf-promo-sell {
    height: 44px;
    border-top: 2px solid transparent; border-bottom: 2px solid transparent;
    background-clip: padding-box;
    border-radius: 10px / 12px;
    margin-top: -2px; margin-bottom: -2px;
  }
  .cf-promo[data-cf-promoted-variant="row"] .cf-promo-sell { min-height: 44px; margin-top: -14px; margin-bottom: -14px; }
  .cf-promo-own { min-height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  .cf-promo-card::before,
  .cf-promo-logo::before,
  .cf-promo-buy::after,
  .cf-promo-in .cf-promo-card,
  .cf-promo-price.is-up,
  .cf-promo-price.is-dn { animation: none; }
}

/* ── the official token (promo_cards.official_mint): the platform's own,
   labelled in the BRAND fill -- it is ours, not a paid placement, so it
   never borrows the amber that means "Promoted". ──────────────────────── */
.cf-promo-badge.is-official {
  color: var(--on-molten);
  background: var(--molten);
  box-shadow: 0 0 0 1px var(--molten-hi), 0 4px 14px rgb(var(--glow) / .35);
}

/* ── several promotions in a single-card slot: one shown, rotating ─────── */
.cf-promo-rot { display: grid; }
.cf-promo-rot > .cf-promo-card {
  grid-area: 1 / 1;
  visibility: hidden;
  opacity: 0;
  transition: opacity .45s var(--ease-out, ease-out), visibility 0s linear .45s;
}
.cf-promo-rot > .cf-promo-card.is-shown {
  visibility: visible;
  opacity: 1;
  transition: opacity .45s var(--ease-out, ease-out);
}
.cf-promo-dots { display: flex; justify-content: center; gap: 2px; margin-top: -2px; }
.cf-promo-dot {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  border-radius: var(--r-pill, 999px);
}
.cf-promo-dot i {
  display: block;
  width: 7px;
  height: 7px;
  border-radius: var(--r-pill, 999px);
  background: rgb(var(--tint) / .28);
  transition: width .3s var(--ease-out, ease-out), background .3s;
}
.cf-promo-dot[aria-selected="true"] i { width: 20px; background: var(--acc); }
.cf-promo-dot:focus-visible { outline: 2px solid var(--gold); outline-offset: 0; }
@media (pointer: coarse) { .cf-promo-dot { width: 44px; height: 44px; } }
@media (prefers-reduced-motion: reduce) {
  .cf-promo-rot > .cf-promo-card, .cf-promo-rot > .cf-promo-card.is-shown, .cf-promo-dot i { transition: none; }
}


/* ---- static/live-market.css ---- */
/* Live Market — design screen 4, measured from CFMarket.dc.html.
 * Every colour is a design token (cf-theme.css), so light and dark both hold. */

body.cf-live-market{background:var(--bg);color:var(--ink);font-family:var(--font-ui)}

.lm-wrap{
  display:flex;flex-direction:column;gap:var(--gap-section);
  padding:var(--wrap-pad);padding-bottom:32px;box-sizing:border-box;min-width:0;
}
.lm-wrap .cf-phone-hub{margin:0}

/* ── title row ─────────────────────────────────────────────────────────── */
.lm-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.lm-h1{margin:0;font:800 var(--fs-page-title)/normal var(--font-ui);color:var(--ink);letter-spacing:0}
/* "● LIVE" is one run of text, pulsing as a whole, as the design draws it. */
.lm-live{display:inline-block;font:600 12px/normal var(--font-num);color:var(--up);white-space:nowrap}
.lm-live.is-stale{color:var(--ink3);animation:none}
@media (prefers-reduced-motion:no-preference){
  .lm-live.is-live{animation:lmPulse 1.6s ease-in-out infinite}
}
@keyframes lmPulse{50%{opacity:.35}}
.lm-range{margin-left:auto;display:flex;gap:4px}
.lm-rng{
  height:32px;min-width:44px;padding:0 10px;box-sizing:border-box;border:0;cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;border-radius:16px;
  font:700 12px/1 var(--font-ui);background:var(--s2);color:var(--ink2);
}
.lm-rng.is-on{background:var(--ink);color:var(--bg)}

/* ── tabs ──────────────────────────────────────────────────────────────── */
.lm-tabs{display:flex;gap:4px;border-bottom:1px solid var(--line);overflow-x:auto;scrollbar-width:none}
.lm-tabs::-webkit-scrollbar{display:none}
.lm-tab{
  /* 44px of label plus its 2px underline: the design's tab is content-box,
     so the row is 46 tall and everything below it sits 2px lower. */
  height:42px;padding:0 12px;flex:none;display:flex;align-items:center;cursor:pointer;
  background:none;border:0;border-bottom:2px solid transparent;margin-bottom:-1px;
  font:700 14px/1 var(--font-ui);color:var(--ink2);
}
.lm-tab.is-on{color:var(--ink);border-bottom-color:var(--acc)}

/* ── scanner + surge radar ─────────────────────────────────────────────── */
.lm-top{display:grid;grid-template-columns:1.3fr 1fr;gap:12px}
.lm-card{
  background:var(--s1);border:1px solid var(--line);border-radius:14px;padding:var(--pad-card);
  display:flex;flex-direction:column;gap:8px;min-width:0;
}
.lm-surge{gap:8px}
.lm-card-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
.lm-card-h{margin:0;font:800 15px/1.3 var(--font-ui);color:var(--ink)}
.lm-switch{
  display:inline-flex;align-items:center;gap:8px;background:none;border:0;padding:0;cursor:pointer;
  min-height:26px;
}
.lm-switch-lbl{font:600 12px/normal var(--font-ui);color:var(--ink2)}
.lm-switch-track{width:44px;height:26px;border-radius:13px;background:var(--s2);position:relative;display:block}
.lm-switch-knob{
  position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;
  background:white;transition:left .2s;box-shadow:0 1px 2px rgba(0,0,0,.25);
}
.lm-switch[aria-checked="true"] .lm-switch-track{background:var(--acc)}
.lm-switch[aria-checked="true"] .lm-switch-knob{left:21px}
.lm-chips{display:flex;flex-wrap:wrap;gap:6px}
.lm-chip{
  height:34px;padding:0 12px;display:inline-flex;align-items:center;border-radius:17px;cursor:pointer;
  border:0;font:600 12px/1 var(--font-ui);background:var(--s2);color:var(--ink2);
}
.lm-chip.is-on{background:var(--ink);color:var(--bg)}
.lm-chip.is-on::before{content:'✓ '}
.lm-note{margin:0;font:500 12px/normal var(--font-num);color:var(--ink3)}
.lm-alerts{font:600 12px/1 var(--font-ui);color:var(--accT);text-decoration:none;cursor:pointer}
.lm-alerts:hover{text-decoration:underline}
.lm-surges{display:flex;flex-direction:column;gap:8px}
.lm-surge-row{
  display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:10px;background:var(--bg);
  color:inherit;text-decoration:none;min-width:0;
}
.lm-surge-row:hover{background:var(--s2)}
.lm-mult{font:800 11px/1.3 var(--font-ui);color:var(--onAcc);background:var(--acc);padding:3px 6px;border-radius:5px;flex:none}
.lm-surge-sym{font:800 14px/1.3 var(--font-ui);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lm-surge-sym span{font:500 12px/1.3 var(--font-ui);color:var(--ink2)}
.lm-surge-ago{font:500 12px/1 var(--font-num);color:var(--ink3);flex:none}
.lm-surge-empty{display:flex;flex-direction:column;gap:4px;padding:8px 10px;border-radius:10px;background:var(--bg)}
.lm-surge-empty b{font:700 13px/1.3 var(--font-ui);color:var(--ink)}
.lm-surge-empty span{font:500 12px/1.4 var(--font-ui);color:var(--ink2)}

/* ── the table ─────────────────────────────────────────────────────────── */
.lm-table{background:var(--s1);border:1px solid var(--line);border-radius:16px;overflow:hidden}
.lm-thead,.lm-row{
  display:grid;gap:12px;align-items:center;
  grid-template-columns:28px minmax(160px,1.4fr) 110px 90px 72px 100px 100px 150px 72px;
}
.lm-thead{
  padding:10px 16px;border-bottom:1px solid var(--line);
  font:600 11px/1.3 var(--font-num);color:var(--ink3);letter-spacing:.06em;
}
.r{text-align:right}
.lm-row{
  padding:0 16px;min-height:52px;border-bottom:1px solid var(--line);cursor:pointer;
  font:500 13px/1.3 var(--font-num);font-variant-numeric:tabular-nums;color:var(--ink);
}
.lm-rows>.lm-row:last-child{border-bottom:0}
.lm-row:hover{background:var(--s2)}
.lm-rank{font:500 12px/normal var(--font-num);color:var(--ink3)}
.lm-tok{display:flex;align-items:center;gap:10px;min-width:0;color:inherit;text-decoration:none}
.lm-tok:focus-visible,.lm-row button:focus-visible,.lm-surge-row:focus-visible,
.lm-rng:focus-visible,.lm-tab:focus-visible,.lm-chip:focus-visible,.lm-switch:focus-visible{
  outline:2px solid var(--acc);outline-offset:2px;
}
.lm-disc{
  width:32px;height:32px;border-radius:50%;background:var(--s2);flex:none;overflow:hidden;
  display:flex;align-items:center;justify-content:center;font:800 11px/1 var(--font-ui);color:var(--accT);
}
.lm-disc img{width:100%;height:100%;object-fit:cover}
.lm-tok-id{display:flex;flex-direction:column;gap:1px;min-width:0}
.lm-sym{font:800 14px/1.3 var(--font-ui);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* a launch's venue (DEEP), beside the ticker on the Launches tab */
.lm-venue{display:inline-block;margin-left:4px;padding:1px 5px;border-radius:5px;background:var(--s2,var(--line));color:var(--ink2);font:700 9px/1.4 var(--font-num);letter-spacing:.06em;vertical-align:2px}
.lm-risk{font:700 10px/1.3 var(--font-ui);color:var(--dn);background:var(--dnBg);padding:2px 5px;border-radius:5px}
.lm-sub{font:500 11px/1.3 var(--font-num);color:var(--ink2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lm-chg.up{color:var(--up)}
.lm-chg.dn{color:var(--dn)}
.lm-chg.flat{color:var(--ink2)}
.lm-vol,.lm-liq{color:var(--ink2)}
.lm-spark{display:block;width:72px;height:24px;position:relative}
.lm-spark-none{font:500 10px/24px var(--font-ui);color:var(--ink3)}
.lm-here{
  display:flex;align-items:center;gap:6px;background:none;border:0;padding:0;cursor:pointer;
  min-height:44px;color:var(--ink2);font:600 12px/1 var(--font-ui);text-align:left;min-width:0;
}
.lm-here:hover .lm-here-n{color:var(--ink);text-decoration:underline}
.lm-faces{display:flex}
.lm-face{width:20px;height:20px;border-radius:50%;outline:2px solid var(--s1);background:var(--s2);object-fit:cover;display:block}
.lm-face+.lm-face{margin-left:-6px}
.lm-hue-1{background:var(--series-1)}.lm-hue-2{background:var(--series-2)}
.lm-buy{
  height:36px;padding:0 14px;display:inline-flex;align-items:center;justify-content:center;border:0;cursor:pointer;
  background:var(--acc);border-radius:9px;font:700 12px/1 var(--font-ui);color:var(--onAcc);
}
.lm-buy:hover{filter:brightness(1.06)}
.lm-who{padding:12px 16px;border-bottom:1px solid var(--line);background:var(--bg)}

.lm-sk{height:52px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:12px;padding:0 16px}
.lm-sk i{width:32px;height:32px;border-radius:50%;background:var(--s2)}
.lm-sk b{width:160px;height:12px;border-radius:6px;background:var(--s2)}
@media (prefers-reduced-motion:no-preference){
  .lm-sk{animation:lmPulse 1.4s ease-in-out infinite}
}
.lm-state{padding:28px;display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center}
.lm-state b{font:700 15px/1.3 var(--font-ui)}
.lm-state span{font:500 13px/1.4 var(--font-ui);color:var(--ink2)}
.lm-state-empty{display:block;font:600 14px/1.4 var(--font-ui);color:var(--ink2)}
.lm-retry{height:40px;padding:0 18px;border:0;border-radius:10px;background:var(--acc);color:var(--onAcc);font:700 13px/1 var(--font-ui);cursor:pointer}
.lm-link{background:none;border:0;padding:0;cursor:pointer;font:inherit;color:var(--accT)}

/* Entrance: movement only (never opacity), added from script and removed. */
@media (prefers-reduced-motion:no-preference){
  .lm-row.lm-in{animation:lmIn .4s ease both}
}
@keyframes lmIn{from{transform:translateY(8px)}to{transform:none}}

/* ── narrower tables ───────────────────────────────────────────────────
   Columns step out by the room the TABLE has (a container query), not by
   the window: the rail beside it is 72 or 232 wide depending on the window
   and on the reader's own collapse choice. Liquidity goes first, then who
   is in it, then the phone's five columns. */
.lm-table{container-type:inline-size;container-name:lmt}
@container lmt (max-width:1009px){
  .lm-thead,.lm-row{grid-template-columns:24px minmax(140px,1.4fr) 100px 84px 72px 90px 130px 64px}
  .lm-thead>span:nth-child(7),.lm-row>.lm-liq{display:none}
}
@container lmt (max-width:819px){
  .lm-thead,.lm-row{grid-template-columns:24px minmax(120px,1.4fr) 100px 84px 72px 90px 64px}
  .lm-thead>span:nth-child(8),.lm-row>.lm-here{display:none}
}
/* The phone row: rank, token, price, change, Buy. The design's fixed 90/72px
   figure columns leave a 390 phone ~36px for the token, so its symbol ran
   under the price; the figures take their own width instead and the symbol
   keeps the rest, ellipsized when a long one still does not fit. */
@container lmt (max-width:677px){
  .lm-thead{display:none}
  .lm-row{grid-template-columns:20px minmax(0,1fr) auto auto 60px;gap:8px}
  .lm-row>.lm-spark,.lm-row>.lm-vol,.lm-row>.lm-liq,.lm-row>.lm-here{display:none}
  .lm-tok{gap:8px}
  .lm-buy{padding:0;width:60px}
  /* The trust pill's "Unchecked" state ate the symbol on a phone ("$Q…");
     the scanner note above already counts the unchecked tokens, so here only
     the design's own "⚠ RISK" flag stays beside the symbol. */
  .lm-row .cf-trust.is-unchecked{display:none}
}
@container lmt (max-width:340px){
  .lm-row{grid-template-columns:minmax(0,1fr) auto auto 60px;gap:8px;padding:0 12px}
  .lm-row>.lm-rank,.lm-disc{display:none}
}

/* ── phone ─────────────────────────────────────────────────────────────── */
@media (max-width:760px){
  .lm-wrap{padding:var(--wrap-pad-phone)}
  .lm-top{grid-template-columns:1fr}
  .lm-range{margin-left:auto}
}
/* Between a phone and a desktop the scanner and the radar are too narrow
   side by side: they stack. */
@media (min-width:761px) and (max-width:1099px){
  .lm-top{grid-template-columns:1fr}
}
/* Touch: every control is a 44px target. The pills keep the design's
   32/34px face -- the extra height is transparent border outside the
   painted background -- and their rows pull in by the same amount, so the
   layout measures as drawn. */
@media (pointer:coarse){
  /* Buy stays the design's 36px face; 4px of transparent border above and
     below make the 44px target, and the row's 60px height absorbs it. */
  .lm-buy{height:44px;border:4px solid transparent;border-left:0;border-right:0;background-clip:padding-box;
    border-radius:9px/11px}
  .lm-range{margin-top:-6px;margin-bottom:-6px;}
  .lm-rng{height:44px;border:6px solid transparent;border-left:0;border-right:0;background-clip:padding-box;
    border-radius:16px/22px}
  /* Chip rows sit 40px apart (34 drawn + the design's 6px gap): each 44px
     chip overlaps its neighbour's transparent margin by 2px, never its face. */
  .lm-chips{row-gap:0;margin-top:-3px;margin-bottom:-3px;}
  .lm-chip{height:44px;margin-top:-2px;margin-bottom:-2px;border:5px solid transparent;border-left:0;border-right:0;
    background-clip:padding-box;border-radius:17px/22px}
  .lm-switch{min-height:44px;margin-top:-9px;margin-bottom:-9px;}
  .lm-alerts{display:inline-flex;align-items:center;min-height:44px;min-width:44px;justify-content:flex-end;margin-top:-16px;margin-bottom:-16px;}
}

/* A very wide screen: the column centres in the room beside the rail
   instead of leaving a dead band down the right. Below 1700 it sits left,
   as the design draws it. */
.lm-wrap{max-width:1560px}
@media (min-width:1700px){ .lm-wrap{margin-left:auto;margin-right:auto} }
/* A state that repaints with the `background` shorthand resets the clip
   to the border box; it is re-asserted so the 44px target keeps its face. */
@media (pointer:coarse){ .lm-rng.is-on,.lm-chip.is-on,.lm-buy:hover{ background-clip:padding-box; } }
@media (pointer:coarse){ .lm-surge-row{min-height:44px;box-sizing:border-box} }

/* ── Launches tab (launchpad.board) ─────────────────────────────────────
   The same table and the same row height; the columns carry a launch:
   token + who launched it, market cap, curve progress, spark, 24h volume,
   holders here, the creator with Copy, Buy. Columns step out by the
   table's own width, like the market's. */
.lm-lsorts{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.lm-lsorts[hidden]{display:none}
.lm-lsorts .lm-chip.is-on::before{content:none}
.lm-lnew{margin-left:auto;font:700 12px/1 var(--font-ui);color:var(--accT);text-decoration:none;
  min-height:44px;display:inline-flex;align-items:center}
.lm-lnew:hover{text-decoration:underline}
.lm-launch-mode .lm-thead,.lm-row.lm-lrow{
  grid-template-columns:28px minmax(150px,1.3fr) 96px 80px minmax(120px,1fr) 72px 86px 84px 168px 72px;
}
/* The quality bar line (launch_gate.py) and the Quality pill a row that clears it wears. */
.lm-lgate{flex-basis:100%;margin:0;font:500 11.5px/1.4 var(--font-num);color:var(--ink2)}
.lm-lgate[hidden]{display:none}
.lm-quality{display:inline-block;margin-left:4px;padding:1px 6px;border-radius:5px;background:var(--upBg);color:var(--up);
  font:700 9px/1.4 var(--font-ui);letter-spacing:.06em;vertical-align:2px}
.lm-clones{color:var(--ink3)}
/* The row's figures in one line (liq · vol · holders · age): the phone row's; the wide table has columns. */
.lm-lstats{display:none;font:500 11px/1.3 var(--font-num);color:var(--ink3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lm-lliq{color:var(--ink2)}
.lm-lhere{display:block;font:500 10px/1.2 var(--font-num);color:var(--ink3)}
.lm-launch-mode .lm-thead>span{white-space:nowrap}
.lm-lprog-cell{min-width:0}
.lm-lprog{display:flex;align-items:center;gap:8px;min-width:0}
.lm-lbar{flex:1;min-width:36px;height:8px;border-radius:4px;background:var(--s2);overflow:hidden;display:block}
.lm-lbar i{display:block;height:100%;border-radius:4px;background:var(--acc);transform-origin:left center}
.is-grad .lm-lbar i{background:var(--up)}
.is-unknown .lm-lbar i{width:0}
.lm-lpct{flex:none;font:600 12px/1 var(--font-num);color:var(--ink);white-space:nowrap}
.is-unknown .lm-lpct{color:var(--ink3);font-weight:500}
.lm-grad{display:inline-block;font:700 10px/1.3 var(--font-ui);color:var(--up);background:var(--upBg);
  padding:2px 6px;border-radius:5px;letter-spacing:.02em}
.lm-lcap{color:var(--ink)}
.lm-lholders{color:var(--ink2);display:flex;flex-direction:column;align-items:flex-end;justify-content:center;gap:1px}
.lm-lcreator{display:flex;align-items:center;gap:8px;min-width:0}
.lm-lby{display:flex;align-items:center;gap:6px;min-width:0;flex:1;color:var(--ink2);text-decoration:none;
  font:600 12px/1.3 var(--font-ui)}
.lm-lby>span:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
a.lm-lby:hover{color:var(--ink)}
.lm-lby .lm-face{flex:none}
.lm-lcopy{
  flex:none;height:32px;padding:0 12px;border-radius:9px;cursor:pointer;
  border:1px solid var(--acc);background:none;color:var(--accT);font:700 12px/1 var(--font-ui);
}
.lm-lcopy:hover{background:var(--s2)}
.lm-lcopy.is-copying{background:var(--acc);color:var(--onAcc)}
.lm-lcopy:focus-visible,.lm-lby:focus-visible,.lm-lnew:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.lm-row.lm-lrow:hover,.lm-row.lm-lrow:focus-within{background:var(--s2);box-shadow:inset 3px 0 0 var(--acc)}
.lm-lrow .lm-tok:focus-visible{border-radius:8px}
.lm-lempty{display:flex;padding:48px 24px}
.lm-lempty span{max-width:44ch}
.lm-lgo{display:inline-flex;align-items:center;text-decoration:none}
.lm-lwarn{padding:10px 16px;border-bottom:1px solid var(--line)}
@media (prefers-reduced-motion:no-preference){
  .lm-lbar i{transition:width var(--dur-draw) var(--ease-draw)}
  .lm-lbar i.lm-lin{animation:lmFill var(--dur-draw) var(--ease-draw) both}
  .lm-row.lm-lrow{transition:background var(--dur-fast),box-shadow var(--dur-fast)}
}
@keyframes lmFill{from{transform:scaleX(0)}to{transform:none}}
@container lmt (max-width:1009px){
  .lm-launch-mode .lm-thead,.lm-row.lm-lrow{grid-template-columns:24px minmax(140px,1.3fr) 90px minmax(110px,1fr) 80px 84px 150px 64px}
  .lm-launch-mode .lm-thead>span:nth-child(4),.lm-row.lm-lrow>.lm-lliq,
  .lm-launch-mode .lm-thead>span:nth-child(6),.lm-row.lm-lrow>.lm-spark{display:none}
  .lm-row.lm-lrow .lm-lstats{display:block}
}
@container lmt (max-width:819px){
  .lm-launch-mode .lm-thead,.lm-row.lm-lrow{grid-template-columns:24px minmax(120px,1.3fr) 84px minmax(100px,1fr) 64px 64px}
  .lm-launch-mode .lm-thead>span:nth-child(7),.lm-row.lm-lrow>.lm-vol,
  .lm-launch-mode .lm-thead>span:nth-child(8),.lm-row.lm-lrow>.lm-lholders{display:none}
  .lm-row.lm-lrow .lm-lby{display:none}
  .lm-launch-mode .lm-thead>span:nth-child(9){visibility:hidden}
}
/* The phone row: token (with "by @creator · age"), progress, Copy, Buy.
   The market cap moves under the bar so the token keeps its room. */
@container lmt (max-width:677px){
  .lm-row.lm-lrow{grid-template-columns:minmax(0,1fr) 76px auto 56px;gap:8px;padding:0 12px;min-height:60px}
  .lm-row.lm-lrow>.lm-rank,.lm-row.lm-lrow>.lm-lcap{display:none}
  .lm-row.lm-lrow .lm-lprog{flex-direction:column;align-items:stretch;gap:4px}
  .lm-row.lm-lrow .lm-lbar{flex:none;width:100%}
  .lm-row.lm-lrow .lm-lpct{text-align:right;font-size:11px}
  .lm-row.lm-lrow .lm-lcopy{padding:0 10px}
  .lm-row.lm-lrow .lm-buy{width:56px}
}
@container lmt (max-width:340px){
  .lm-row.lm-lrow .lm-disc{display:none}
  .lm-row.lm-lrow{grid-template-columns:minmax(0,1fr) 64px auto 52px}
  .lm-row.lm-lrow .lm-buy{width:52px}
}
@media (pointer:coarse){
  .lm-lcopy{height:44px;border-width:6px 0;border-style:solid;border-color:transparent;background-clip:padding-box;
    box-shadow:inset 0 0 0 1px var(--acc);border-radius:9px/15px}
  .lm-lsorts{margin-top:-5px;margin-bottom:-5px}
  .lm-lsorts .lm-chip{height:44px;border:5px solid transparent;border-left:0;border-right:0;background-clip:padding-box;
    border-radius:17px/22px}
}

/* ── Outside launchpads on the Launches tab (external_launchpads/) ──────
   The launchpad chips sit on their own line under the sorts; a curve token
   from four.meme / Flap / Pons carries its venue and chain beside the
   ticker, and its last cell is an honest link out to that launchpad (it
   trades there until it graduates), never a dead Buy. */
.lm-lpads{display:flex;gap:6px;flex-basis:100%;align-items:center;overflow-x:auto;scrollbar-width:none;
  padding:2px 0;-webkit-overflow-scrolling:touch}
.lm-lpads::-webkit-scrollbar{display:none}
.lm-lpads .lm-chip{flex:none}
.lm-lpad-off{font:600 9px/1 var(--font-num);color:var(--ink3);margin-left:4px;text-transform:uppercase;letter-spacing:.06em}
.lm-venue-x{background:var(--accBg,var(--s2));color:var(--accT)}
/* The ticker shrinks, the venue badge never does: on a phone row the badge
   is the venue, so it must not be the part the ellipsis eats. */
.lm-sym.lm-lsym{display:flex;align-items:center;min-width:0}
.lm-lsym .lm-sym-t{flex:0 1 auto;min-width:0;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lm-lsym .lm-venue{flex:0 1 auto;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
/* The symbol is what the row is: on a narrow row the badge gives way to its logo alone. */
@media (max-width:640px){.lm-lsym .lm-vname,.lm-lsym .lm-vchain{display:none}.lm-lsym .lm-venue .cf-logo{margin-right:0}}
.lm-row.lm-lrow .lm-lpct{overflow:hidden;text-overflow:ellipsis;max-width:100%}
.lm-sub-out{color:var(--ink3)}
.lm-ltrust{display:inline-block;vertical-align:1px;margin-left:4px}
.lm-lpool{display:inline-block;margin-left:6px;font:500 10px/1 var(--font-num);color:var(--ink3)}
.lm-buy.lm-buy-out{gap:4px;padding:0 10px;text-decoration:none;background:none;color:var(--accT);
  box-shadow:inset 0 0 0 1px var(--acc);white-space:nowrap}
.lm-buy.lm-buy-out:hover{background:var(--s2);filter:none}
.lm-buy.lm-buy-out:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
/* The launch row's ten cells (2026-10-15, launch_gate.py): #, token, MCAP, LIQ, curve, spark, VOL 24H, HOLDERS, creator, Buy.
   LIQ and the spark step out first, then VOL and HOLDERS (the token cell's stats line carries them from there). The
   market table's own breakpoint rules hide its 7th and 8th HEADER cells (LIQ, HERE); in launch mode the 7th is VOL 24H,
   so it is put back here. */
.lm-launch-mode .lm-thead,.lm-launch-mode .lm-row.lm-lrow{grid-template-columns:28px minmax(150px,1.3fr) 96px 80px minmax(120px,1fr) 72px 86px 84px 168px 104px}
.lm-launch-mode .lm-row.lm-lrow>.lm-buy{justify-self:end}
/* The ticker and the Quality pill never shrink: the venue badge is what gives way in a narrow token cell. */
.lm-lsym .lm-sym-t,.lm-lsym .lm-quality{flex:none}
.lm-lstats>[data-k="vol"],.lm-lstats>[data-k="holders"]{display:none}
@container lmt (max-width:1009px){
  .lm-launch-mode .lm-thead,.lm-launch-mode .lm-row.lm-lrow{grid-template-columns:24px minmax(140px,1.3fr) 90px minmax(110px,1fr) 80px 84px 150px 104px}
  .lm-launch-mode .lm-thead>span:nth-child(7){display:block}
}
@container lmt (max-width:819px){
  .lm-launch-mode .lm-thead,.lm-launch-mode .lm-row.lm-lrow{grid-template-columns:24px minmax(120px,1.3fr) 84px minmax(100px,1fr) 64px 104px}
  .lm-launch-mode .lm-thead>span:nth-child(7),.lm-launch-mode .lm-thead>span:nth-child(8){display:none}
  .lm-lstats>[data-k="vol"],.lm-lstats>[data-k="holders"]{display:inline}
  .lm-sub-out{display:none}
}
/* The phone row's figures: one full-width line under the cells (hidden wider, where the token cell's line and the columns carry them). */
.lm-row.lm-lrow>.lm-lstats-full{display:none}
@container lmt (max-width:677px){
  .lm-row.lm-lrow .lm-lstats,.lm-row.lm-lrow .lm-lsym .lm-quality{display:none}
  .lm-row.lm-lrow>.lm-lstats-full{display:block;grid-column:1/-1;padding:0 0 10px;margin-top:-4px;
    font:500 11px/1.35 var(--font-num);color:var(--ink3);white-space:normal}
  .lm-row.lm-lrow>.lm-lstats-full>[data-k]{display:inline}
  .lm-row.lm-lrow>.lm-lstats-full .lm-quality{margin-left:6px;vertical-align:1px}
}
@container lmt (max-width:677px){
  /* The last column is as wide as ITS button, up to the 92px a "Trades on X" link
     needs: a fixed 92px left 36px dead beside every Buy and starved the symbol
     ("$FRE", "$NEA" at 390). */
  .lm-launch-mode .lm-row.lm-lrow{grid-template-columns:minmax(0,1fr) 76px auto fit-content(92px)}
  .lm-row.lm-lrow .lm-buy.lm-buy-out{width:auto;min-width:56px;max-width:92px;padding:0 8px}
  .lm-lpool{display:none}
  .lm-vchain{display:none}
}
@container lmt (max-width:340px){
  .lm-launch-mode .lm-row.lm-lrow{grid-template-columns:minmax(0,1fr) 64px auto fit-content(88px)}
}
@media (pointer:coarse){
  .lm-lpads .lm-chip{height:44px;border:5px solid transparent;border-left:0;border-right:0;background-clip:padding-box;
    border-radius:17px/22px}
  .lm-buy.lm-buy-out{height:44px}
}

/* ══ SYNDICATE NOIR (2026-10-12) ══════════════════════════════════════════
   Drawn to /design/a/app#trade (static/design/a/app.css .na-mkt*, .na-sub,
   .na-chains): the page title lives in the top bar (data-cf-title), the
   sort tabs and the range are segmented bars with the molten indicator
   (CFMotion places it under the lit tab), filter and chain chips are Noir
   pills (a chain's own dot), the scanner, the radar and the table are glass
   panels, the table's header is mono caps and its rows are 64px with a
   tint on hover. Product columns the reference does not draw (liquidity,
   bought here, the scanner and the surge radar) keep their place. */

body.cf-live-market{background:transparent;color:var(--text-1);font-family:var(--font-display)}
.lm-wrap{padding-top:6px}
/* The title is the top bar's (one level-1 heading per page). */
body[data-cf-title] .lm-h1{display:none}
.lm-head{min-height:0}
.lm-live{font:600 10.5px/1 var(--font-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--ion)}
.lm-live.is-stale{color:var(--text-3)}
.lm-range{margin-left:auto}

/* segmented bars: the reference's .na-tabs */
.lm-tabs.cf-tabs,.lm-range.cf-tabs{display:inline-flex;gap:2px;padding:4px;border:1px solid var(--glass-edge);border-radius:var(--r-pill);background:var(--ink-2);align-self:flex-start;flex-wrap:nowrap}
.lm-tabs .lm-tab{height:36px;margin:0;padding:0 14px;border:0;border-radius:var(--r-pill);background:transparent;color:var(--text-2);font:600 13px/1 var(--font-display);transition:color var(--t-med)}
.lm-tabs .lm-tab.is-on{color:var(--on-molten);border:0}
.lm-range .lm-rng{height:32px;min-width:44px;padding:0 12px;border-radius:var(--r-pill);background:transparent;color:var(--text-2);font:600 12px/1 var(--font-mono)}
.lm-range .lm-rng.is-on{background:transparent;color:var(--on-molten)}
@media (hover:hover){.lm-tabs .lm-tab:not(.is-on):hover,.lm-range .lm-rng:not(.is-on):hover{color:var(--text-1)}}
.lm-rng:focus-visible,.lm-tab:focus-visible,.lm-chip:focus-visible,.lm-switch:focus-visible,
.lm-tok:focus-visible,.lm-row button:focus-visible,.lm-surge-row:focus-visible{outline:2px solid var(--gold-400)}

/* glass panels */
.lm-card.cf-glass{padding:18px;border-radius:var(--r-lg)}
.lm-card-h{font:var(--fw-h3) var(--fs-h3)/var(--lh-h3) var(--font-display);letter-spacing:var(--tr-h3);color:var(--text-1)}
.lm-switch-lbl{font:600 10.5px/1 var(--font-mono);letter-spacing:.1em;text-transform:uppercase;color:var(--text-3)}
.lm-switch-track{width:52px;height:30px;border-radius:15px;background:var(--ink-2);border:1px solid var(--glass-edge-hi);box-sizing:border-box}
.lm-switch-knob{top:3px;left:3px;width:22px;height:22px;background:var(--text-3);box-shadow:var(--shadow-1);transition:left var(--t-med) var(--ease-spring),background var(--t-med)}
.lm-switch[aria-checked="true"] .lm-switch-track{background:rgb(var(--glow) / .25);border-color:rgb(var(--glow) / .6)}
.lm-switch[aria-checked="true"] .lm-switch-knob{left:23px;background:var(--molten);box-shadow:0 0 12px rgb(var(--glow) / .6)}

/* chips: the reference's .na-chip; a chain chip carries the chain's dot */
.lm-chip{height:32px;padding:0 12px;gap:6px;border:1px solid var(--glass-edge);border-radius:var(--r-pill);background:rgb(var(--tint) / .05);
  color:var(--text-2);font:600 10.5px/1 var(--font-mono);letter-spacing:.08em;text-transform:uppercase;
  transition:background var(--t-fast),color var(--t-fast),border-color var(--t-fast)}
@media (hover:hover){.lm-chip:hover{color:var(--text-1);border-color:var(--glass-edge-hi)}}
.lm-chip.is-on{color:var(--accent-text-strong);border-color:rgb(var(--glow) / .55);background:rgb(var(--glow) / .2)}
.lm-chip[data-f^="chain:"]::before{content:'';width:6px;height:6px;border-radius:50%;background:var(--chain,var(--gold-400));box-shadow:0 0 8px var(--chain,transparent)}
.lm-chip[data-f^="chain:"].is-on::before{content:''}
.lm-chip[data-f="chain:solana"]{--chain:var(--chain-solana)}
.lm-chip[data-f="chain:base"]{--chain:var(--chain-base)}
.lm-chip[data-f="chain:bsc"]{--chain:var(--chain-bsc)}
.lm-chip[data-f="chain:arbitrum"]{--chain:var(--chain-arbitrum)}
.lm-chip[data-f="chain:polygon"]{--chain:var(--chain-polygon)}
.lm-chip[data-f="chain:robinhood"]{--chain:var(--chain-robinhood)}
.lm-chip[data-f="chain:ethereum"]{--chain:var(--chain-ethereum)}
.lm-chip[data-f="chain:monad"]{--chain:var(--chain-monad)}
.lm-chip[data-f="chain:hyperevm"]{--chain:var(--chain-hyperevm)}
.lm-note{font:500 12px/1.4 var(--font-mono);color:var(--text-3)}
.lm-alerts{font:600 10.5px/1 var(--font-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--accent-text)}

/* surge radar */
.lm-surge-row{border-radius:var(--r-md)}
.lm-surge-row:hover{background:rgb(var(--tint) / .04)}
.lm-mult{background:var(--molten);color:var(--on-molten);font:700 11px/1.3 var(--font-mono);border-radius:var(--r-pill);padding:3px 8px}
.lm-surge-sym{font:600 14px/1.3 var(--font-display)}
.lm-surge-ago{font-family:var(--font-mono);color:var(--text-3)}
.lm-surge-empty{background:var(--well);border:1px solid rgb(var(--tint) / .04);border-radius:var(--r-md);padding:10px 12px}
.lm-surge-empty b{font:600 13.5px/1.3 var(--font-display);color:var(--text-1)}
.lm-surge-empty span{color:var(--text-2);font-family:var(--font-body)}

/* the table: a glass panel, mono caps header, 64px rows */
.lm-table.cf-glass{border-radius:var(--r-lg);overflow:hidden;padding:6px}
.lm-thead{border-bottom:0;padding:12px 12px 8px;color:var(--text-4);font:600 10px/1 var(--font-mono);letter-spacing:.14em;text-transform:uppercase}
.lm-row{min-height:64px;padding:8px 12px;border-bottom:0;border-radius:var(--r-md);border:1px solid transparent;
  font:500 13px/1.3 var(--font-mono);color:var(--text-1);transition:background var(--t-fast),border-color var(--t-fast)}
.lm-row:hover{background:rgb(var(--tint) / .03);border-color:var(--glass-edge)}
.lm-rows{display:grid;gap:2px}
.lm-rank{font:600 12px/1 var(--font-mono);color:var(--text-4);text-align:right}
.lm-disc{width:40px;height:40px;border-radius:12px;background:var(--ink-4);box-shadow:0 0 0 1px var(--glass-edge-hi),var(--shadow-1);color:var(--text-2);font:700 13px/1 var(--font-display)}
.lm-sym{font:600 15px/1.2 var(--font-display);color:var(--text-1)}
.lm-sub{font:500 11.5px/1.4 var(--font-mono);color:var(--text-3)}
.lm-venue{border-radius:var(--r-pill);background:rgb(var(--tint) / .05);border:1px solid var(--glass-edge);color:var(--text-2);font:600 9.5px/1.4 var(--font-mono);padding:1px 6px}
.lm-risk{border-radius:var(--r-pill);font:600 10px/1.3 var(--font-mono);letter-spacing:.06em;background:var(--dn-dim);color:var(--dn);padding:2px 7px}
.lm-chg{font:600 12.5px/1.4 var(--font-mono)}
.lm-vol,.lm-liq{color:var(--text-2)}
.lm-spark{height:34px}
.lm-spark-none{line-height:34px;color:var(--text-4);font-family:var(--font-mono)}
.lm-here{color:var(--text-2);font:500 12.5px/1 var(--font-display)}
.lm-face{outline:0;box-shadow:0 0 0 2px var(--ink-3)}
.lm-buy{height:36px;padding:0 16px;border-radius:var(--r-pill);background:var(--molten);color:var(--on-molten);border:1px solid var(--molten-hi);
  font:600 13px/1 var(--font-display);box-shadow:0 1px 0 rgb(var(--sheen-rgb) / .5) inset,0 -2px 0 var(--molten-lo) inset,0 6px 22px rgb(var(--glow) / .32)}
.lm-buy:hover{filter:none;box-shadow:0 1px 0 rgb(var(--sheen-rgb) / .55) inset,0 -2px 0 var(--molten-lo) inset,0 10px 34px rgb(var(--glow) / .45)}
.lm-buy.lm-buy-out{background:transparent;color:var(--accent-text-strong);border:1px solid rgb(var(--glow) / .55);box-shadow:none}
.lm-buy.lm-buy-out:hover{background:rgb(var(--glow) / .12)}
.lm-who{background:var(--well);border-bottom:0;border-radius:var(--r-md);margin:2px 0}
.lm-sk{height:64px;border-bottom:0}
.lm-sk i{width:40px;height:40px;border-radius:12px;background:rgb(var(--tint) / .05)}
.lm-sk b{background:rgb(var(--tint) / .05)}
.lm-state b{font:600 15px/1.3 var(--font-display);color:var(--text-1)}
.lm-state span{color:var(--text-2);font-family:var(--font-body)}
.lm-retry{border-radius:var(--r-pill);background:var(--molten);color:var(--on-molten);font:600 13px/1 var(--font-display)}
.lm-link{color:var(--accent-text)}

/* Launches: the sub-row (New / Hot / Near graduation) as a segmented bar,
   the molten Launch a token, the curve as the reference's .na-bar */
.lm-lsorts .lm-chip.is-on{color:var(--accent-text-strong)}
.lm-lnew{display:inline-flex;align-items:center;min-height:36px;padding:0 16px;border-radius:var(--r-pill);background:var(--molten);color:var(--on-molten);
  border:1px solid var(--molten-hi);font:600 13px/1 var(--font-display);box-shadow:0 6px 22px rgb(var(--glow) / .32)}
.lm-lnew:hover{text-decoration:none;box-shadow:0 10px 34px rgb(var(--glow) / .45)}
.lm-lbar{height:6px;border-radius:3px;background:rgb(var(--tint) / .06)}
.lm-lbar i{border-radius:3px;background:var(--molten);box-shadow:0 0 10px rgb(var(--glow) / .5)}
.is-grad .lm-lbar i{background:var(--up);box-shadow:0 0 10px rgb(var(--up-rgb) / .45)}
.lm-lpct{font-family:var(--font-mono);color:var(--text-1)}
.lm-grad{border-radius:var(--r-pill);background:var(--up-dim);color:var(--up);font-family:var(--font-mono);letter-spacing:.06em}
.lm-lcopy{border-radius:var(--r-pill);border:1px solid var(--glass-edge-hi);background:var(--ink-4);color:var(--text-1);font-family:var(--font-display)}
.lm-lcopy:hover{background:var(--ink-4);border-color:rgb(var(--glow) / .45)}
.lm-lcopy.is-copying{background:var(--up-dim);color:var(--up);border-color:rgb(var(--up-rgb) / .45)}
.lm-row.lm-lrow:hover,.lm-row.lm-lrow:focus-within{background:rgb(var(--tint) / .03);box-shadow:inset 3px 0 0 var(--gold-400)}

@media (max-width:860px){
  .lm-row{padding:8px 6px}
}
@media (pointer:coarse){
  .lm-tabs .lm-tab::before,.lm-range .lm-rng::before{inset:-4px 0}
  .lm-range{margin-top:0;margin-bottom:0}
  .lm-range .lm-rng{height:36px;border:0;border-radius:var(--r-pill)}
  .lm-chip{height:44px;border:6px solid transparent;border-left:0;border-right:0;background-clip:padding-box;border-radius:var(--r-pill);
    box-shadow:inset 0 0 0 1px var(--glass-edge)}
  .lm-chip.is-on{box-shadow:inset 0 0 0 1px rgb(var(--glow) / .55)}
  .lm-buy{height:44px;border:4px solid transparent;border-left:0;border-right:0;background-clip:padding-box;border-radius:var(--r-pill)}
}
@media (prefers-reduced-motion:reduce){
  .lm-row,.lm-chip,.lm-tab,.lm-switch-knob{transition:none!important}
}
.lm-head .lm-tabs{flex:0 1 auto;min-width:0}
.lm-row{box-sizing:border-box}

/* Launches tab: the chain row and the "launch here / outside launchpad" note (2026-10-13). */
.lm-lchains{display:flex;flex-wrap:wrap;gap:6px}
.lm-lchains[hidden]{display:none}
.lm-lchain[data-chain]::after{content:'';display:inline-block;width:6px;height:6px;border-radius:50%;margin-left:6px;background:var(--chain,var(--acc));vertical-align:middle}
.lm-lchain[data-chain="solana"]{--chain:var(--chain-solana)}.lm-lchain[data-chain="base"]{--chain:var(--chain-base)}
.lm-lchain[data-chain="bsc"]{--chain:var(--chain-bsc)}.lm-lchain[data-chain="robinhood"]{--chain:var(--chain-robinhood)}
.lm-lchain[data-chain="hyperevm"]{--chain:var(--chain-hyperevm)}
.lm-lnote{flex-basis:100%;margin:0;font:500 12px/1.5 var(--font-ui);color:var(--ink3)}
.lm-lnote[hidden],.lm-lnote:empty{display:none}

/* Brand marks beside chain and launchpad names (brand_logos.py + cf-brand.js, 2026-10-13). The dot stays only where no mark exists. */
.lm-chip .cf-logo{width:12px;height:12px;margin-right:6px;vertical-align:-2px}
.lm-lchain.has-logo[data-chain]::after{display:none}
.lm-chip.has-logo[data-f^="chain:"]::before{display:none}   /* the mark replaces the dot */
.lm-sub .cf-logo{width:11px;height:11px;margin-right:4px;vertical-align:-2px}
.lm-venue .cf-logo{width:11px;height:11px;margin-right:3px;vertical-align:-2px;border-radius:2px}


/* ---- static/cf-signin-methods.css ---- */
/* Get-started sheet: the passkey, EVM-wallet, password and "secure your
   sign-in" screens added by wallet-onboarding.js. Tokens only (cf-theme.css);
   a literal colour works in one theme and breaks the other. Injected by
   passkeys.py beside cf-passkey.js. */
.oa-ob-modal .oa-ob-remember{margin:14px 0 4px;justify-content:center}
.oa-ob-modal .oa-ob-pk{display:flex;flex-direction:column;gap:10px}
.oa-ob-modal .oa-ob-pk-lead{margin:0;font:600 14px/1.45 var(--font-ui);color:var(--ink)}
.oa-ob-modal .oa-ob-pk-lead[data-kind="bad"]{color:var(--dn)}
.oa-ob-modal .oa-ob-pk-note{margin:0;font:500 12.5px/1.5 var(--font-ui);color:var(--ink2)}
.oa-ob-modal .oa-ob-pk-note b{color:var(--ink);font-weight:700}
.oa-ob-modal .oa-ob-secure{display:flex;flex-direction:column;gap:12px}
.oa-ob-modal .oa-ob-secure .oa-ob-method[disabled]{opacity:.55;cursor:not-allowed}
.oa-ob-modal .oa-ob-mnote[data-kind="good"]{color:var(--up)}
.oa-ob-modal .oa-ob-mnote[data-kind="bad"]{color:var(--dn)}
.oa-ob-modal .oa-ob-secure-pw{display:flex;flex-direction:column;gap:8px}
.oa-ob-modal .oa-ob-secure-pw[hidden]{display:none}
.oa-ob-modal .oa-ob-inline-btn{
  align-self:flex-start;min-height:44px;padding:0 16px;border-radius:10px;border:1px solid var(--line);
  background:var(--acc);color:var(--onAcc);font:700 13px var(--font-ui);cursor:pointer}
.oa-ob-modal .oa-ob-inline-btn:disabled{opacity:.6;cursor:progress}


/* ---- static/cf-modal.css ---- */
/* Cartel Family — the one modal / dialog / bottom-sheet surface.
 *
 * CLAUDE.md, "Design system": *one* set of modals and sheets. Before this file
 * the app had `.s-modal` duplicated verbatim into six templates (each with a
 * slightly different `.s-title`), a bespoke `.oa-ob-*` shell for wallet
 * onboarding, `.gd-modal-*`, `.w-modal-*`, `.lm-token-modal`, `.pt-sheet-*`
 * and more — none of which agreed on padding, radius, close-button position,
 * focus handling or where an error message goes.
 *
 * Shape follows static/cf-trade-sheet.js, which already got this right:
 * centred dialog from 768px up, bottom sheet below it, same scrim, same
 * swipe-to-dismiss, same reduced-motion behaviour. This is that behaviour
 * generalised, not a second system next to it.
 *
 * COLOURS: tokens from cf-theme.css only. A literal works in one theme and
 * breaks the other (`.pt-nb-more-item{color:#c7ccd4}` was legible on dark and
 * nearly invisible on light). The one colour defined here is --cf-scrim,
 * because cf-theme.css ships no scrim token — and it is declared for BOTH
 * themes below, in all three of the theme states cf-theme.css defines
 * (system / forced light / forced dark), so it cannot have that bug.
 */

:root{
  --cf-scrim:rgba(3,8,14,.74);
  --cf-modal-shadow:0 24px 64px rgba(0,0,0,.55);
}
:root[data-theme="light"] body.cf-themable,
html:not([data-theme]) body.cf-themable.cf-light{
  --cf-scrim:rgba(11,20,32,.44);
  --cf-modal-shadow:0 18px 48px rgba(11,20,32,.18);
}
@media (prefers-color-scheme: light){
  :root:not([data-theme]) body.cf-themable{
    --cf-scrim:rgba(11,20,32,.44);
    --cf-modal-shadow:0 18px 48px rgba(11,20,32,.18);
  }
}

/* ── layer ──────────────────────────────────────────────────────────────
 * One layer per open modal. Stacking (a modal opened from a modal) is just
 * another layer at a higher z-index; nothing about the scroll lock or the
 * focus trap is per-instance state that a second instance could corrupt.
 * Above cf-trade-sheet (9001) and above app-ux.css's forced 1500 for the
 * legacy shells, so a confirm raised from either one is never buried.
 */
.cf-modal-layer{
  position:fixed;inset:0;z-index:9400;
  display:flex;align-items:center;justify-content:center;
  /* Safe-area aware, so a dialog never sits under a notch or a home
     indicator. The side gutter stays 16px at every width. */
  padding:calc(var(--space-md,16px) + env(safe-area-inset-top,0px))
          var(--space-md,16px)
          calc(var(--space-md,16px) + env(safe-area-inset-bottom,0px));
  font-family:var(--font-ui,system-ui,-apple-system,sans-serif);
}


.cf-modal-scrim{
  position:absolute;inset:0;
  background:var(--scrim,var(--cf-scrim));
  opacity:0;transition:opacity .3s ease;
}
.cf-modal-layer.cf-on .cf-modal-scrim{opacity:1}

/* ── the sheet (DESIGN_PROMPT §4) ───────────────────────────────────────
 * Desktop: a 440px right drawer, full height. Phone: a bottom sheet, 22px top
 * corners, a 5px grab handle, max-height 90%. Both move on .38s
 * var(--ease-spring). A small confirm (size "sm") stays a centred dialog on
 * desktop -- a one-line question does not need a drawer. Measured from the
 * design's sheet shell; every colour is a design token.
 */
.cf-modal{
  position:relative;
  display:flex;flex-direction:column;
  width:100%;max-width:440px;max-height:100%;
  background:var(--s1);
  color:var(--ink);
  border:0;
  border-radius:16px;
  box-shadow:var(--e2);
  overflow:hidden;
  opacity:0;transform:translateY(8px) scale(.98);
  transition:opacity .2s ease,transform .38s var(--ease-spring);
  text-align:left;
}
.cf-modal-layer.cf-on .cf-modal{opacity:1;transform:none}
.cf-modal:focus{outline:none}
.cf-modal[data-size="sm"]{max-width:380px;border:1px solid var(--line)}

@media (min-width:768px){
  .cf-modal-layer:has(.cf-modal:not([data-size="sm"])){align-items:stretch;justify-content:flex-end;padding:0}
  .cf-modal:not([data-size="sm"]){
    max-width:440px;height:100%;max-height:none;border-radius:0;
    border-left:1px solid var(--line);box-shadow:-20px 0 60px rgba(0,0,0,.35);
    opacity:1;transform:translateX(100%);
  }
  .cf-modal[data-size="lg"]{max-width:520px}
  .cf-modal-layer.cf-on .cf-modal:not([data-size="sm"]){transform:none}
}

/* Grip is sheet-only. */
.cf-modal-grip{display:none}

/* ── header: title 18/800, a 36px round close ─────────────────────────── */
.cf-modal-head{
  display:flex;align-items:center;gap:10px;
  padding:10px 20px 6px;
  flex:0 0 auto;
}
.cf-modal-heading{min-width:0;flex:1;display:flex;flex-direction:column;gap:2px}
.cf-modal-title{margin:0;font:800 18px/1.3 var(--font-ui);color:var(--ink)}
.cf-modal-sub{margin:0;font:500 13px/1.45 var(--font-ui);color:var(--ink2)}

.cf-modal-back,.cf-modal-x{
  flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  width:36px;height:36px;margin:0;padding:0;
  border:0;border-radius:50%;
  background:var(--s2);color:var(--ink2);cursor:pointer;
  transition:color .14s,background .14s;
}
.cf-modal-back:hover,.cf-modal-x:hover{color:var(--ink)}
.cf-modal-back svg{width:17px;height:17px;display:block}
.cf-modal-x svg{width:14px;height:14px;display:block}
.cf-modal-x:focus-visible,.cf-modal-back:focus-visible,
.cf-modal-act:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
/* On touch widths the 36px disc keeps its size and takes a 44px tap: the
   fill is clipped to the content box, as navbar.css draws the avatar. The
   negative margin keeps the header's geometry unchanged. */
@media (pointer:coarse),(hover:none),(max-width:1024px){
  .cf-modal-back,.cf-modal-x{
    width:44px;height:44px;margin:-4px;padding:4px;box-sizing:border-box;background-clip:content-box;
  }
}

/* ── body ───────────────────────────────────────────────────────────── */
.cf-modal-body{
  flex:1 1 auto;min-height:0;
  padding:8px 20px 24px;
  overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
  font:500 14px/1.45 var(--font-ui);color:var(--body);
}
.cf-modal-body:empty{padding-bottom:8px}
.cf-modal-body p{margin:0 0 10px}
.cf-modal-body p:last-child{margin-bottom:0}
.cf-modal-body strong,.cf-modal-body b{color:var(--ink);font-weight:700}
.cf-modal-body a{color:var(--accT)}

/* Explicit empty state: say there is nothing rather than draw something
   plausible (CLAUDE.md, "no invented data, ever"). */
.cf-modal-empty{display:flex;flex-direction:column;align-items:center;gap:6px;padding:24px 16px;text-align:center}
.cf-modal-empty-mark{
  width:40px;height:40px;border-radius:50%;border:1px dashed var(--ink3);
  display:grid;place-items:center;color:var(--ink2);margin-bottom:2px;
}
.cf-modal-empty-mark svg{width:16px;height:16px;display:block}
.cf-modal-empty-title{font:700 14px var(--font-ui);color:var(--ink)}
.cf-modal-empty-text{font:500 13px/1.5 var(--font-ui);color:var(--ink2);max-width:34ch}

/* Field primitives, so a migrated sheet does not have to bring its own. */
.cf-modal-field{display:block;margin:0 0 12px}
.cf-modal-label{display:block;margin:0 0 6px;font:600 12px/1.3 var(--font-ui);color:var(--ink2)}
.cf-modal-input,.cf-modal-textarea{
  box-sizing:border-box;width:100%;
  background:var(--bg);color:var(--ink);
  border:1px solid var(--line);border-radius:12px;
  font:500 15px/1.4 var(--font-num);
  padding:12px;outline:none;min-height:48px;
}
.cf-modal-textarea{min-height:96px;resize:none;font-size:13px;line-height:1.5}
.cf-modal-select{
  box-sizing:border-box;width:100%;min-height:48px;
  background:var(--bg);color:var(--ink);
  border:1px solid var(--line);border-radius:12px;
  font:600 14px/1.4 var(--font-ui);padding:11px 12px;outline:none;
}
.cf-modal-input:focus,.cf-modal-textarea:focus,.cf-modal-select:focus{border-color:var(--acc)}
.cf-modal-input::placeholder,.cf-modal-textarea::placeholder{color:var(--ink2)}
.cf-modal-input:disabled,.cf-modal-select:disabled{opacity:.6;cursor:not-allowed}

/* input + trailing button (Max, paste, scan). */
.cf-modal-row{display:flex;gap:8px;align-items:stretch}
.cf-modal-row .cf-modal-input{flex:1;min-width:0}
.cf-modal-row-btn{
  flex:0 0 auto;min-width:64px;border:0;border-radius:12px;
  background:var(--s2);color:var(--accT);font:700 12px/1 var(--font-ui);cursor:pointer;
}
.cf-modal-row-btn:disabled{opacity:.45;cursor:not-allowed}

/* Secondary line under a field: chain, balance, unit. */
.cf-modal-meta{
  display:flex;justify-content:space-between;gap:10px;margin-top:6px;
  font:500 12px/1.35 var(--font-num);color:var(--ink2);
}
.cf-modal-meta .cf-accent{color:var(--accT)}

.cf-modal-stat{display:flex;gap:8px;margin:0 0 12px}
.cf-modal-stat>div{flex:1;min-width:0;background:var(--bg);border:1px solid var(--line);border-radius:12px;padding:10px}
.cf-modal-stat dt{margin:0 0 2px;font:600 11px var(--font-ui);color:var(--ink2)}
.cf-modal-stat dd{
  margin:0;font:500 16px/1.2 var(--font-num);font-variant-numeric:tabular-nums;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;
}
.cf-modal-stat dd.cf-accent{color:var(--accT)}

.cf-modal-copy{
  display:flex;align-items:center;gap:8px;background:var(--bg);border:1px solid var(--line);
  border-radius:14px;padding:12px 14px;margin:0 0 6px;
}
.cf-modal-copy code{flex:1;min-width:0;word-break:break-all;font:500 13px/1.5 var(--font-num);color:var(--ink)}
.cf-modal-copy button{
  flex:0 0 auto;width:36px;height:36px;display:grid;place-items:center;border:0;border-radius:10px;
  background:var(--s2);color:var(--ink2);cursor:pointer;transition:color .14s;
}
.cf-modal-copy button:hover{color:var(--ink)}
.cf-modal-copy button.cf-done{color:var(--up)}
.cf-modal-copy button svg{width:15px;height:15px;display:block}

.cf-modal-hint{min-height:15px;margin:0 0 4px;font:700 12px/15px var(--font-ui);color:var(--accT)}

.cf-modal-check{
  display:flex;align-items:center;gap:10px;margin:14px 0 0;
  font:600 14px/1.4 var(--font-ui);color:var(--ink);cursor:pointer;
}
.cf-modal-check input{flex:0 0 auto;width:22px;height:22px;margin:0;accent-color:var(--acc);cursor:pointer}

/* ── footer: actions, and the message that belongs WITH them ────────────
 * The failure text sits immediately above the button that produced it. */
.cf-modal-foot{
  flex:0 0 auto;padding:0 20px 20px;
  padding-bottom:calc(20px + env(safe-area-inset-bottom,0px));
  display:flex;flex-direction:column;gap:10px;
}
.cf-modal-foot[hidden]{display:none}

.cf-modal-note{display:flex;align-items:flex-start;gap:8px;padding:10px 12px;border-radius:12px;font:500 13px/1.5 var(--font-ui);border:0}
.cf-modal-note[hidden]{display:none}
.cf-modal-note svg{flex:0 0 auto;width:15px;height:15px;margin-top:2px;display:block}
.cf-modal-note[data-kind="error"]{color:var(--dn);background:var(--dnBg)}
.cf-modal-note[data-kind="success"]{color:var(--up);background:var(--upBg)}
.cf-modal-note[data-kind="info"]{color:var(--ink2);background:var(--s2)}

.cf-modal-actions{display:flex;gap:8px;flex-wrap:wrap}
.cf-modal-actions:empty{display:none}

.cf-modal-act{
  flex:1 1 auto;min-width:120px;min-height:48px;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  border:0;border-radius:12px;font:700 14px/1 var(--font-ui);
  cursor:pointer;padding:0 16px;transition:opacity .14s,background .14s,color .14s;
}
/* The class rule above would beat the UA's [hidden]{display:none}; this
   re-asserts it with more specificity so setAction({hidden:true}) hides. */
.cf-modal-act[hidden]{display:none}

/* The accent is a FILL with ink text (--onAcc), never a text colour. */
.cf-modal-act[data-variant="primary"]{background:var(--acc);color:var(--onAcc)}
.cf-modal-act[data-variant="primary"][data-full="1"]{min-height:54px;border-radius:14px;font-weight:800;font-size:15px}
.cf-modal-act[data-variant="ghost"]{background:var(--s2);color:var(--ink)}
/* Destructive is outlined, so no single foreground has to read on a red fill
   in both themes. */
.cf-modal-act[data-variant="danger"]{background:transparent;color:var(--dn);border:1px solid var(--dn)}
.cf-modal-act:disabled{background:var(--s2);color:var(--ink2);cursor:not-allowed}
.cf-modal-act[data-full="1"]{flex:1 1 100%}

/* Busy: the spinner joins the label, so the button never changes width. */
.cf-modal-spin{
  width:14px;height:14px;flex:0 0 auto;border-radius:50%;
  border:2px solid currentColor;border-top-color:transparent;
  animation:cf-modal-spin .62s linear infinite;
}
@keyframes cf-modal-spin{to{transform:rotate(360deg)}}

/* An action waiting on a dependency it does not have yet says so, and cannot
   be pressed. */
.cf-modal-act[data-pending="1"]{cursor:progress}

/* ── phone: bottom sheet ────────────────────────────────────────────── */
@media (max-width:767px){
  .cf-modal-layer{align-items:flex-end;padding:0}
  .cf-modal,.cf-modal[data-size="sm"]{
    /* dvh, not vh: on a phone the URL bar collapses and expands. */
    max-width:none;width:100%;max-height:90dvh;
    border:0;border-top:1px solid var(--line);
    border-radius:22px 22px 0 0;
    transform:translateY(100%) scale(1);
    transition:transform .38s var(--ease-spring);
    opacity:1;
  }
  .cf-modal-layer.cf-on .cf-modal{transform:translateY(0)}
  .cf-modal.cf-drag{transition:none}
  .cf-modal-grip{
    display:block;flex:0 0 auto;width:40px;height:5px;margin:10px auto 0;
    border-radius:3px;background:var(--line);
  }
  .cf-modal-head{padding-top:10px}
  .cf-modal-act{min-width:0}
  /* A phone keyboard must never hide the primary action. */
  .cf-modal-foot{position:sticky;bottom:0;background:var(--s1)}
  /* 16px minimum or iOS zooms the whole sheet on focus. */
  .cf-modal-input,.cf-modal-textarea{font-size:16px}
}

/* ── reduced motion: the finished state ─────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  .cf-modal,.cf-modal-scrim{transition:none}
  .cf-modal,.cf-modal-layer .cf-modal,.cf-modal-layer .cf-modal:not([data-size="sm"]){transform:none;opacity:1}
  .cf-modal-layer:not(.cf-on){opacity:0}
  .cf-modal-spin{animation-duration:1.4s}
}


/* ---- static/wallet-onboarding.css ---- */
/* Cartel Family — "Get started" (DESIGN_PROMPT §4), inside the shared sheet.
 *
 * There is no dialog in this file. The frame, the scrim, the heading, the
 * footer, the focus trap, the scroll lock and the phone bottom sheet all come
 * from cf-modal.css / cf-modal.js — the app's one sheet system. What is here
 * is only what is specific to the onboarding steps, scoped under
 * `.oa-ob-modal`, which the script stamps on the dialog element. Measured
 * from CFFlows.dc.html.
 *
 * COLOURS: design tokens from cf-theme.css only. This stylesheet is injected
 * into EVERY HTML response, so one literal here is a literal everywhere, and
 * the app has a light and a dark palette. The method tiles take token
 * colours rather than each wallet's brand hex for the same reason.
 */

/* ── the chooser: pick a method ────────────────────────────────────────── */
.oa-ob-modal .cf-modal-act[hidden]{display:none}
.oa-ob-modal .cf-modal-body{display:flex;flex-direction:column;gap:14px}

/* ── the join screen (owner, 2026-10-15): mark, title, pitch, three feature
   rows, one molten button, one outlined button, a footnote. The dialog's
   own heading stays for assistive tech and is hidden visually here; the ✕
   keeps the top-right corner. */
.oa-ob-modal.oa-ob-chooser .cf-modal-heading{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.oa-ob-modal.oa-ob-chooser .cf-modal-head{padding-bottom:0}
.oa-ob-modal.oa-ob-chooser .cf-modal-x{margin-left:auto}
.oa-ob-modal .oa-ob-join{display:flex;flex-direction:column;align-items:center;gap:14px;text-align:center;padding-top:2px}
.oa-ob-modal .oa-ob-mark{
  position:relative;width:64px;height:64px;border-radius:18px;overflow:hidden;flex:none;background:var(--s2);
  box-shadow:0 0 0 1px var(--line),0 10px 28px var(--accBg);
}
/* The kit's small lockup crop (cf-rail.css): the Boss Bull's face fills the
   tile; the whole icon at this size is mostly dark padding. */
.oa-ob-modal .oa-ob-mark img{position:absolute;width:118%;height:118%;max-width:none;left:-9%;top:-8%;display:block;object-fit:cover}
.oa-ob-modal .oa-ob-title{margin:-2px 0 0;font:700 24px/1.15 var(--font-display);letter-spacing:-.02em;color:var(--ink)}
.oa-ob-modal .oa-ob-pitch{margin:-4px 0 0;max-width:38ch;font:500 14px/1.5 var(--font-ui);color:var(--ink2)}
.oa-ob-modal .oa-ob-feats{list-style:none;margin:2px 0 0;padding:0;width:100%;display:flex;flex-direction:column;gap:14px;text-align:left}
.oa-ob-modal .oa-ob-feat{display:flex;align-items:flex-start;gap:14px}
.oa-ob-modal .oa-ob-feat-ico{width:44px;height:44px;border-radius:50%;flex:none;display:grid;place-items:center;background:var(--accBg);color:var(--accT)}
.oa-ob-modal .oa-ob-feat-ico svg{width:22px;height:22px;display:block}
.oa-ob-modal .oa-ob-feat-text{display:grid;gap:2px;min-width:0;padding-top:2px}
.oa-ob-modal .oa-ob-feat-text b{font:700 15px/1.3 var(--font-ui);color:var(--ink)}
.oa-ob-modal .oa-ob-feat-text span{font:500 13px/1.45 var(--font-ui);color:var(--ink2)}
.oa-ob-modal .oa-ob-ctas{width:100%;display:flex;flex-direction:column;gap:10px;margin-top:2px}
/* The labels name every method ("Sign in with Telegram, X, Google or Apple"),
   so the pill may wrap at 320px instead of clipping. */
.oa-ob-modal .oa-ob-cta{white-space:normal;line-height:1.25;padding:12px 18px;min-height:54px;height:auto}
.oa-ob-modal .oa-ob-foot{margin:0;max-width:42ch;font:500 12px/1.5 var(--font-ui);color:var(--ink2)}
@media (prefers-reduced-motion:no-preference){
  /* A short rise, position only: a paused animation (app-ux.css pauses a
     hidden tab) leaves the rows visible, never parked at opacity 0. */
  .oa-ob-modal .oa-ob-feat{animation:oaObRise .5s var(--ease-out,ease-out) both}
  .oa-ob-modal .oa-ob-feat:nth-child(2){animation-delay:.06s}
  .oa-ob-modal .oa-ob-feat:nth-child(3){animation-delay:.12s}
  @keyframes oaObRise{from{transform:translateY(8px)}to{transform:none}}
}

.oa-ob-modal .oa-ob-methods{display:flex;flex-direction:column;gap:14px}
.oa-ob-modal .oa-ob-method{
  min-height:56px;display:flex;align-items:center;gap:12px;padding:0 14px;width:100%;
  background:var(--bg);border:1px solid var(--line);border-radius:14px;cursor:pointer;
  color:var(--ink);text-align:left;transition:border-color .14s;
}
.oa-ob-modal .oa-ob-method:hover:not(:disabled){border-color:var(--acc)}
.oa-ob-modal .oa-ob-method:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.oa-ob-modal .oa-ob-method:disabled{cursor:progress;opacity:.6}
.oa-ob-modal .oa-ob-code{
  position:relative;width:36px;height:36px;border-radius:10px;flex:none;display:flex;align-items:center;justify-content:center;
  background:var(--s2);border:1px solid var(--line);color:var(--ink2);overflow:hidden;
}
/* Our own methods draw a single-stroke glyph; a third-party brand draws its
   own mark (CFBrand.wallet), which replaces the generic wallet glyph. */
.oa-ob-modal .oa-ob-glyph{width:20px;height:20px;flex:none}
.oa-ob-modal .oa-ob-code .cf-logo{width:24px;height:24px;margin:0;vertical-align:0;border-radius:6px;object-fit:contain}
.oa-ob-modal .oa-ob-code:has(.cf-logo) .oa-ob-glyph{display:none}
.oa-ob-modal .oa-ob-method:hover:not(:disabled) .oa-ob-code{border-color:var(--acc)}
.oa-ob-modal .oa-ob-method:hover:not(:disabled) .oa-ob-glyph{color:var(--acc)}
.oa-ob-modal .oa-ob-mlabel{font:700 15px var(--font-ui);flex:1;min-width:0}
/* The note wraps on the right (46% at most) rather than riding over the label at 320px. */
.oa-ob-modal .oa-ob-mnote{font:500 12px/1.3 var(--font-ui);color:var(--ink2);flex:none;max-width:46%;text-align:right}

/* The three big rows (the "Sign in" step): Telegram, X, Google (Apple when
   configured). 64px, a 40px mark tile, the label at 16/700; the lit edge is
   the one gold line the Noir component library draws on a primary control. */
.oa-ob-modal .oa-ob-primary{gap:10px}
.oa-ob-modal .oa-ob-method.is-primary{
  min-height:64px;padding:0 16px;gap:14px;border-radius:16px;background:var(--s1);
  border-color:var(--line);position:relative;
}
.oa-ob-modal .oa-ob-method.is-primary .oa-ob-code{width:40px;height:40px;border-radius:12px}
.oa-ob-modal .oa-ob-method.is-primary .oa-ob-code .cf-logo{width:26px;height:26px}
.oa-ob-modal .oa-ob-method.is-primary .oa-ob-mlabel{font-size:16px}
.oa-ob-modal .oa-ob-method.is-primary::after{
  content:"";position:absolute;left:14px;right:14px;top:-1px;height:1px;opacity:0;
  background:linear-gradient(90deg,transparent,var(--acc),transparent);transition:opacity .16s;
}
.oa-ob-modal .oa-ob-method.is-primary:hover:not(:disabled)::after,
.oa-ob-modal .oa-ob-method.is-primary:focus-visible::after{opacity:1}

@media (prefers-reduced-motion:reduce){
  .oa-ob-modal .oa-ob-method.is-primary::after{transition:none}
}

.oa-ob-modal .oa-ob-foot-note,
.oa-ob-modal .oa-ob-security-note,.oa-ob-modal .oa-ob-lock-note{
  display:flex;align-items:center;justify-content:center;gap:7px;
  font:500 12px var(--font-ui);color:var(--ink2);
}
.oa-ob-modal .oa-ob-foot-note svg,.oa-ob-modal .oa-ob-security-note svg,
.oa-ob-modal .oa-ob-lock-note svg{width:14px;height:14px;flex:0 0 auto}
.oa-ob-modal .oa-ob-foot-note b{padding:0 2px;color:var(--ink2);font-weight:700}
.oa-ob-modal .oa-ob-security-note{justify-content:flex-start}

/* ── Telegram login mounts here ─────────────────────────────────────── */
.oa-ob-modal .oa-ob-tg{background:var(--bg);border:1px solid var(--line);border-radius:14px;padding:16px}

/* ── create: progress, warning, the keys (revealed on demand) ─────────── */
.oa-ob-modal .oa-ob-progress{
  display:grid;grid-template-columns:auto 1fr auto 1fr auto;align-items:start;gap:8px;
}
.oa-ob-modal .oa-ob-progress-line{height:1px;background:var(--line);margin-top:13px}
.oa-ob-modal .oa-ob-step{display:grid;justify-items:center;gap:5px;color:var(--ink2);font:600 11px var(--font-ui);white-space:nowrap}
.oa-ob-modal .oa-ob-step-dot{
  display:grid;place-items:center;width:26px;height:26px;border-radius:50%;
  background:var(--s2);color:var(--ink2);font:700 11px var(--font-ui);
}
.oa-ob-modal .oa-ob-step.done,.oa-ob-modal .oa-ob-step.active{color:var(--accT)}
.oa-ob-modal .oa-ob-step.done .oa-ob-step-dot,
.oa-ob-modal .oa-ob-step.active .oa-ob-step-dot{background:var(--acc);color:var(--onAcc)}

.oa-ob-modal .oa-ob-warning{
  display:grid;grid-template-columns:22px 1fr;align-items:center;gap:10px;
  padding:10px 12px;border:1px solid var(--proLine);border-radius:12px;background:var(--proBg);
  font:600 13px/1.45 var(--font-ui);color:var(--ink);
}
.oa-ob-modal .oa-ob-shield{width:20px;height:22px;color:var(--pro)}

.oa-ob-modal .oa-ob-fields{display:flex;flex-direction:column;gap:10px;background:var(--bg);
  border:1px solid var(--line);border-radius:14px;padding:14px}
.oa-ob-modal .oa-ob-field-card{display:flex;flex-direction:column;gap:6px}
.oa-ob-modal .oa-ob-field-label{font:500 12px var(--font-num);color:var(--ink2)}
.oa-ob-modal .oa-ob-value-row{display:flex;align-items:stretch;gap:6px;min-width:0}
.oa-ob-modal .oa-ob-value{
  display:flex;align-items:center;min-width:0;min-height:44px;flex:1;
  border-radius:10px;background:var(--s2);color:var(--ink);padding:0 12px;
  font:500 13px/1.5 var(--font-num);
}
.oa-ob-modal .oa-ob-value-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.oa-ob-modal .oa-ob-secret-input{
  box-sizing:border-box;width:100%;min-width:0;border:0;outline:0;
  background:transparent;color:var(--ink);font:500 13px/1 var(--font-num);
}
.oa-ob-modal .oa-ob-secret-input[type=password]{letter-spacing:.14em}
.oa-ob-modal .oa-ob-icon-btn,.oa-ob-modal .oa-ob-show-btn{
  display:flex;align-items:center;justify-content:center;gap:5px;flex:0 0 auto;min-height:44px;
  border:0;border-radius:10px;background:var(--s2);color:var(--accT);
  font:700 12px/1 var(--font-ui);cursor:pointer;
}
.oa-ob-modal .oa-ob-icon-btn{width:44px}
.oa-ob-modal .oa-ob-show-btn{padding:0 12px}
.oa-ob-modal .oa-ob-icon-btn.copied{color:var(--up)}
.oa-ob-modal .oa-ob-icon-btn:focus-visible,.oa-ob-modal .oa-ob-show-btn:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.oa-ob-modal .oa-ob-icon{width:17px;height:17px;display:block}
.oa-ob-modal .oa-ob-check{margin:0}

/* ── import: base58 / JSON array, validated live ────────────────────── */
.oa-ob-modal .oa-ob-seg{display:flex;background:var(--s2);border-radius:10px;padding:2px}
.oa-ob-modal .oa-ob-seg button{
  flex:1;height:34px;border:0;border-radius:8px;background:transparent;
  font:700 13px var(--font-ui);color:var(--ink2);cursor:pointer;
}
.oa-ob-modal .oa-ob-seg button.on{background:var(--s1);color:var(--ink)}
.oa-ob-modal .oa-ob-seg button:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.oa-ob-modal .cf-modal-body>.cf-modal-label{margin:0 0 -8px}
.oa-ob-modal textarea.oa-ob-secret{min-height:96px}
.oa-ob-modal textarea.oa-ob-bad{border-color:var(--dn)}
.oa-ob-modal .oa-ob-keymsg{font:600 12px var(--font-ui);color:var(--ink2);margin-top:-6px}
.oa-ob-modal .oa-ob-keymsg[data-kind="bad"]{color:var(--dn)}
.oa-ob-modal .oa-ob-keymsg[data-kind="good"]{color:var(--up)}
.oa-ob-modal .oa-ob-label-optional small{font-size:11px;font-weight:600;color:var(--ink2)}

@media (max-width:767px){
  /* The reveal button keeps its 44px target but drops the word. */
  .oa-ob-modal .oa-ob-show-btn{width:44px;padding:0;font-size:0}
  .oa-ob-modal .oa-ob-show-btn .oa-ob-icon{width:19px;height:19px}
}
@media (max-width:370px){
  .oa-ob-modal .oa-ob-progress{gap:4px}
  .oa-ob-modal .oa-ob-step{font-size:10px}
}

/* ── the pairing-code sheet (cf-wallet-connect.js, 2026-10-12) ──────────
   The home-screen app types the code the signing page shows. Tokens only. */
.cf-pair-sheet .cf-pair-lede{margin:0 0 14px;font:500 14px/1.5 var(--font-ui);color:var(--body,var(--ink))}
.cf-pair-sheet .cf-pair-input{
  height:56px;text-align:center;
  font:700 26px/1 var(--font-num);letter-spacing:.18em;text-transform:uppercase;
  color:var(--ink);font-variant-numeric:tabular-nums;
}
.cf-pair-sheet .cf-pair-fine{margin:10px 0 0;font:500 12px/1.45 var(--font-ui);color:var(--ink2)}
.cf-pair-sheet .cf-pair-steps{margin:0;padding:0 0 0 20px;display:grid;gap:8px;
  font:500 14px/1.45 var(--font-ui);color:var(--body,var(--ink))}
.cf-pair-sheet .cf-pair-steps b{color:var(--ink);font-weight:700}
.cf-pair-sheet .cf-pair-steps li::marker{color:var(--accT);font-weight:700}

