@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-toast.css ---- */
/* CFToast -- Syndicate Noir's toast (COMPONENTS.md "Toasts"), the one toast on
   every surface. Every value is a cf-theme.css token; no colour is written
   here. Glass, a 3px accent edge in the variant colour with its glow, a 40px
   icon tile, title + body, one action, a close button and a 2px progress bar.

   The RESTING state is the visible one: the entrance is a class script adds
   and removes (`is-in`), so a paused, hidden or printed page still shows the
   words. Bottom-right on desktop; bottom-centre above the phone bar. */

.cf-toasts{
  position:fixed;z-index:var(--z-toast);right:20px;bottom:calc(20px + env(safe-area-inset-bottom,0px));
  display:flex;flex-direction:column;align-items:flex-end;gap:10px;
  width:min(400px,calc(100vw - 32px));pointer-events:none;
}
@media (max-width:767px){
  .cf-toasts{right:50%;transform:translateX(50%);align-items:stretch;
    bottom:calc(var(--bar-h) + 14px + env(safe-area-inset-bottom,0px))}
  /* above the app's phone bar (80px) and the Mini App's bar */
  body.cf-rail-on .cf-toasts,body:has(#oa-bottom-nav) .cf-toasts,body:has(.tg-nav) .cf-toasts{
    bottom:calc(96px + env(safe-area-inset-bottom,0px))}
}
.cf-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

.cf-toast{
  pointer-events:auto;position:relative;width:100%;box-sizing:border-box;
  display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:center;gap:12px;
  padding:12px 10px 14px 12px;overflow:hidden;
  border-radius:var(--r-lg);background:var(--glass-strong);border:1px solid var(--glass-edge-hi);color:var(--ink);
  box-shadow:var(--shadow-3);-webkit-backdrop-filter:blur(18px) saturate(1.3);backdrop-filter:blur(18px) saturate(1.3);
  font:500 13px/1.4 var(--font-body);cursor:default;touch-action:pan-y;
  transition:transform var(--t-med) var(--ease-out),opacity var(--t-med);
}
.cf-toast::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--toast-c,var(--gold-400));box-shadow:0 0 14px var(--toast-c,var(--gold-400))}
.cf-toast--success{--toast-c:var(--up)}
.cf-toast--error{--toast-c:var(--dn)}
.cf-toast--info{--toast-c:var(--gold-400)}
.cf-toast--live{--toast-c:var(--ion)}
.cf-toast--game{--toast-c:var(--gold-300);background:linear-gradient(120deg,rgb(var(--glow) / .16),transparent 55%),var(--glass-strong)}
.cf-toast-ic{position:relative;width:40px;height:40px;display:grid;place-items:center;border-radius:12px;color:var(--toast-c);background:rgb(var(--tint) / .05)}
.cf-toast-ic>svg{width:20px;height:20px}
.cf-toast-ic .cf-ava,.cf-toast-ic .cf-medal,.cf-toast-ic .cf-tok{position:relative;z-index:1}
.cf-toast--game .cf-toast-ic,.cf-toast--live .cf-toast-ic{background:none}
.cf-toast-ring{position:absolute;inset:-4px;width:48px;height:48px;fill:none;stroke:var(--gold-300);stroke-width:2.5;stroke-linecap:round;
  stroke-dasharray:100 132;transform-origin:50% 50%;animation:cf-ring-spin 1.6s var(--ease-out) both;filter:drop-shadow(0 0 4px rgb(var(--glow) / .7))}
@keyframes cf-ring-spin{from{transform:rotate(-270deg);stroke-dasharray:0 132}to{transform:rotate(0);stroke-dasharray:132 0}}
.cf-toast-txt{min-width:0}
.cf-toast-txt b{display:block;font:600 14px/1.3 var(--font-display);color:var(--ink);overflow-wrap:anywhere}
.cf-toast-txt span{display:block;color:var(--ink2);font-size:13px;line-height:1.4;overflow-wrap:anywhere}
.cf-toast-act{display:flex}
.cf-toast-x{width:36px;height:36px;border:0;border-radius:10px;background:none;color:var(--ink3);cursor:pointer;display:grid;place-items:center;position:relative;padding:0}
.cf-toast-x::before{content:'';position:absolute;inset:-4px}
.cf-toast-x svg{width:16px;height:16px}
.cf-toast-x:hover{color:var(--ink);background:rgb(var(--tint) / .06)}
.cf-toast-life{position:absolute;left:0;bottom:0;height:2px;width:100%;background:var(--toast-c);opacity:.7;transform-origin:left;animation:cf-life linear forwards}
@keyframes cf-life{from{transform:scaleX(1)}to{transform:scaleX(0)}}
.cf-toast.is-in{animation:cf-toast-in 480ms var(--ease-spring)}
.cf-toast.is-out{transform:translateX(24px) scale(.96);opacity:0}
@keyframes cf-toast-in{from{transform:translateY(18px) scale(.94);opacity:.2}to{transform:none;opacity:1}}
@media (max-width:767px){.cf-toast.is-out{transform:translateY(20px) scale(.96)}}
.cf-toast-badge{width:40px;height:40px;border-radius:12px;display:grid;place-items:center;background:var(--molten);color:var(--on-molten);box-shadow:0 4px 14px rgb(var(--glow) / .45)}
.cf-toast-badge svg{width:22px;height:22px}
@media (max-width:420px){.cf-toast{grid-template-columns:auto minmax(0,1fr) auto}.cf-toast-act{grid-column:2 / 4;grid-row:2}}

/* Reduced motion: no slide, no spin; the toast is simply there and leaves at
   once. The progress bar still shows the time left. */
@media (prefers-reduced-motion:reduce){
  .cf-toast,.cf-toast.is-out{transition:none}
  .cf-toast.is-in{animation:none}
  .cf-toast-ring{animation:none;stroke-dasharray:none}
}


/* ---- static/cf-bonus.css ---- */
/* The signup bonus (static/cf-bonus.js): the sheet, the Portfolio strip and
   the Help menu row. Tokens only (cf-theme.css); both themes. */
.cfb-hero{display:flex;align-items:center;gap:16px;padding:4px 0 12px}
.cfb-ring{position:relative;flex:none;width:84px;height:84px}
.cfb-ring svg{width:84px;height:84px;transform:rotate(-90deg)}
.cfb-ring circle{fill:none;stroke-width:7}
.cfb-ring .cfb-ring-bg{stroke:var(--line)}
.cfb-ring .cfb-ring-fg{stroke:var(--acc);stroke-linecap:round;transition:stroke-dashoffset .6s var(--ease-out,ease-out)}
.cfb-ring b{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;
  font:800 22px/1 var(--font-num,var(--font-ui));color:var(--ink)}
.cfb-ring b small{font:600 10px/1.2 var(--font-ui);color:var(--ink3);margin-top:3px;letter-spacing:.06em;text-transform:uppercase}
.cfb-hero-t{min-width:0;display:flex;flex-direction:column;gap:4px}
.cfb-amt{font:800 30px/1.05 var(--font-display,var(--font-ui));color:var(--ink);letter-spacing:-.01em}
.cfb-amt em{font-style:normal;color:var(--accent-text-strong,var(--acc))}
.cfb-sub{font:500 13px/1.45 var(--font-ui);color:var(--ink2)}
.cfb-status{display:inline-flex;align-items:center;gap:6px;align-self:flex-start;min-height:26px;padding:0 10px;border-radius:999px;
  font:700 12px/1 var(--font-ui);border:1px solid var(--line);color:var(--ink);background:var(--s2)}
.cfb-status[data-tone="ok"]{color:var(--up);border-color:var(--up);background:transparent}
.cfb-status[data-tone="wait"]{color:var(--accent-text-strong,var(--acc));border-color:var(--acc)}
.cfb-status[data-tone="off"]{color:var(--dn);border-color:var(--dn)}
.cfb-note{margin:0 0 12px;padding:10px 12px;border-radius:12px;border:1px solid var(--line);background:var(--s2);
  font:600 13px/1.45 var(--font-ui);color:var(--ink)}
.cfb-note[data-tone="off"]{border-color:var(--dn);color:var(--dn)}
.cfb-steps{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.cfb-step{display:grid;grid-template-columns:32px minmax(0,1fr);gap:4px 12px;padding:12px;border:1px solid var(--line);border-radius:14px;background:var(--s2)}
.cfb-step.cfb-in{animation:cfb-in .45s var(--ease-out,ease-out) both;animation-delay:calc(var(--i,0) * 70ms)}
@keyframes cfb-in{from{transform:translateY(8px)}to{transform:none}}
.cfb-dot{grid-row:1 / span 3;width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font:800 14px/1 var(--font-num,var(--font-ui));border:2px solid var(--line);color:var(--ink2)}
.cfb-step[data-st="done"] .cfb-dot{border-color:var(--up);color:var(--up)}
.cfb-step[data-st="failed"] .cfb-dot,.cfb-step[data-st="blocked"] .cfb-dot{border-color:var(--dn);color:var(--dn)}
.cfb-step h4{margin:0;font:800 14px/1.3 var(--font-ui);color:var(--ink);display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cfb-step h4 span{font:700 11px/1 var(--font-ui);padding:4px 8px;border-radius:999px;border:1px solid var(--line);color:var(--ink2)}
.cfb-step[data-st="done"] h4 span{color:var(--up);border-color:var(--up)}
.cfb-rule{font:500 12px/1.4 var(--font-ui);color:var(--ink3)}
.cfb-detail{font:500 13px/1.45 var(--font-ui);color:var(--ink2);overflow-wrap:anywhere}
.cfb-detail a{color:var(--accent-text-strong,var(--acc))}
.cfb-acts{grid-column:2;display:flex;gap:8px;flex-wrap:wrap;margin-top:6px}
.cfb-rules{margin:14px 0 0;padding:0 0 0 18px;font:500 12px/1.55 var(--font-ui);color:var(--ink3)}
.cfb-pay{margin-top:12px;font:600 13px/1.45 var(--font-ui);color:var(--ink)}
.cfb-pay a{color:var(--accent-text-strong,var(--acc))}
.cfb-meter{margin-top:12px;display:flex;flex-direction:column;gap:6px;font:600 12px/1.3 var(--font-ui);color:var(--ink3)}
.cfb-meter i{display:block;height:6px;border-radius:999px;background:var(--line);overflow:hidden}
.cfb-meter i b{display:block;height:100%;width:0;background:var(--acc);border-radius:inherit;transition:width .6s var(--ease-out,ease-out)}
/* the Portfolio strip */
.cfb-strip{display:flex;align-items:center;gap:12px;margin:0 0 16px;padding:12px 14px;border-radius:16px;border:1px solid var(--line);
  background:var(--s2);cursor:pointer;width:100%;text-align:left;color:var(--ink);min-height:56px}
.cfb-strip:focus-visible{outline:2px solid var(--focus,var(--acc));outline-offset:2px}
.cfb-strip-ic{flex:none;width:36px;height:36px;border-radius:12px;display:flex;align-items:center;justify-content:center;
  background:var(--acc);color:var(--on-molten,var(--bg));font:800 14px/1 var(--font-num,var(--font-ui))}
.cfb-strip-t{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.cfb-strip-t b{font:800 14px/1.3 var(--font-ui)}
.cfb-strip-t small{font:500 12px/1.35 var(--font-ui);color:var(--ink2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cfb-strip-n{flex:none;font:700 12px/1 var(--font-ui);color:var(--ink2)}
@media (prefers-reduced-motion: reduce){
  .cfb-step.cfb-in{animation:none}
  .cfb-ring .cfb-ring-fg,.cfb-meter i b{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/landing.css ---- */
/* The landing — SYNDICATE NOIR (decided 2026-10-12).

   The master reference is /design/a/ (static/design/a/noir.css for the
   components, static/design/a/landing.css for the page). This sheet is that
   reference, drawn on the product's tokens: every var() resolves from
   static/cf-theme.css, which carries the Noir design system for both themes
   (dark by default, [data-theme="light"] on body.cf-themable). Two parts:

     1. the Noir components the landing draws (glass, buttons, chips,
        avatars, medallions, tabs, trade card, tape, toasts, celebrations,
        bars, podium, race, league, share sheet);
     2. the page itself (top bar, ember hero + phone, tape, sections, ranks,
        launches + calls, feature widgets, why, CTA, footer).

   Motion: entrances are added by script and removed when they end; the
   resting state is always the visible one. prefers-reduced-motion stops
   every loop and shows the finished state. */

/* ── 1. components ─────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body.ln-landing {
  margin: 0; min-height: 100vh; overflow-x: hidden;
  background: var(--ink-1); background-image: none; color: var(--text-1);
  font: 400 var(--fs-body)/1.55 var(--font-body);
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
}
/* The ground: ink, a warm vignette from above, and a film grain drawn by an
   SVG turbulence filter (no image file). Fixed, behind everything. */
body.ln-landing::before {
  content: ''; position: fixed; inset: 0; z-index: -2; pointer-events: none;
  background:
    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%),
    var(--ink-1);
}
body.ln-landing::after {
  content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none; opacity: .07; mix-blend-mode: overlay;
  background-image: 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 1  0 0 0 0 .95  0 0 0 0 .85  0 0 0 .9 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}
:where(.ln-landing) img { max-width: 100%; display: block; }
:where(.ln-landing) a { color: inherit; text-decoration: none; }
:where(.ln-landing) button { font: inherit; color: inherit; }
:where(.ln-landing) :focus { outline: none; }
:where(.ln-landing) :focus-visible { box-shadow: var(--focus); border-radius: var(--r-sm); }
:where(.ln-landing) ::selection { background: rgb(var(--glow) / .35); color: var(--text-1); }

/* figures, and their direction (classes built as 'ln-' + up | dn | flat) */
.ln-num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }

.ln-up { color: var(--up); } .ln-dn { color: var(--dn); } .ln-flat { color: var(--text-3); }
.ln-muted { color: var(--text-2); } .ln-faint { color: var(--text-3); }
.ln-caps { font: 600 var(--fs-micro)/1.2 var(--font-mono); letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--text-3); }

/* ── rank chip (the medallion itself is cf-medal) ─────────────────────── */

.ln-rank { display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 8px 0 3px; border-radius: var(--r-pill);
  background: rgb(var(--tint) / .05); border: 1px solid var(--glass-edge); font: 600 10.5px/1 var(--font-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--metal, var(--text-2)); }
/* The chip names its rank in the rank's own metal on ink; on parchment the
   pale metals fail contrast, so the light theme writes it in ink. */
:root[data-theme="light"] body.cf-themable .ln-rank { color: var(--rank-ink, var(--text-1)); }

/* ── trade card: a person first ────────────────────────────────────────── */

.ln-tc-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.ln-tc-who { min-width: 0; flex: 1; }
.ln-tc-who b { display: block; font: 600 15px/1.25 var(--font-display); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ln-tc-who small { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; color: var(--text-3); font: 500 12px/1.4 var(--font-mono); }
.ln-tc-what { display: flex; align-items: center; gap: 12px; margin: 14px 0 12px; padding: 12px; border-radius: var(--r-md); background: var(--well); border: 1px solid rgb(var(--tint) / .04); }
.ln-tc-what .ln-tc-sym { flex: 1; min-width: 0; }
.ln-tc-what .ln-tc-sym b { font: 700 17px/1.1 var(--font-display); letter-spacing: -.01em; }
.ln-tc-what .ln-tc-sym small { display: block; color: var(--text-3); font: 500 12px/1.4 var(--font-mono); }
.ln-tc-pnl { text-align: right; }
.ln-tc-pnl b { display: block; font: 600 20px/1.1 var(--font-mono); font-variant-numeric: tabular-nums; }
.ln-tc-pnl small { color: var(--text-3); font: 500 11px/1.4 var(--font-mono); }
.ln-tc-spark { height: 34px; margin: -2px 0 10px; }
.ln-tc-foot { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ln-tc-foot .ln-tc-also { flex: 1; min-width: 120px; display: flex; align-items: center; gap: 8px; color: var(--text-2); font-size: 12.5px; }
.ln-tc-actions { display: flex; gap: 8px; }

/* ── charts: the shared primitives, in noir: glowing trail + gradient ──── */
.ln-chart { position: relative; --glow: rgb(var(--glow) / .55); }
.ln-chart.is-up { --glow: rgb(var(--up-rgb) / .6); }
.ln-chart.is-dn { --glow: rgb(var(--dn-rgb) / .6); }
.ln-chart .cf-chart-svg path[fill="none"], .ln-chart .cf-spark-svg path[fill="none"] { filter: drop-shadow(0 0 4px var(--glow)) drop-shadow(0 0 12px var(--glow)); }
.ln-chart .cf-chart-end { width: 9px; height: 9px; box-shadow: 0 0 0 3px rgb(var(--ground-rgb) / .85), 0 0 14px var(--glow); }
.ln-chart .cf-chart-tip { background: var(--glass-strong); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); border-color: rgb(var(--glow) / .3); }
.ln-chart .cf-chart-empty { color: var(--text-3); }
.ln-chart .cf-chart-svg rect { transition: opacity var(--t-fast); }

/* ── entrances: resting state visible; .ln-in is added by script and removed
   when it ends (never parked at opacity 0) ─────────────────────────────── */
.ln-in { animation: ln-rise var(--t-enter) var(--ease-out) both; }
@keyframes ln-rise { from { opacity: 0; transform: translateY(16px) scale(.985); filter: blur(4px); } to { opacity: 1; transform: none; filter: none; } }

/* ── the share sheet (cf-sheet): its optional note ─────────────────────── */

.ln-sheet-note { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: var(--r-md); background: rgb(var(--ion-rgb) / .06); border: 1px solid rgb(var(--ion-rgb) / .25); color: var(--text-1); font-size: 13.5px; margin: var(--sp-4) 0; }
.ln-sheet-note svg { flex: none; width: 18px; height: 18px; color: var(--ion); margin-top: 2px; }

/* ── brand lockup ──────────────────────────────────────────────────────── */
.ln-brand { display: inline-flex; align-items: center; gap: 12px; min-height: var(--tap); }
.ln-brand-tile { position: relative; width: 38px; height: 38px; border-radius: 11px; overflow: hidden; flex: none; background: var(--ink-0); box-shadow: 0 0 0 1px rgb(var(--glow) / .45), 0 6px 18px rgb(var(--glow) / .25); transition: transform var(--t-med) var(--ease-spring); }
.ln-brand-tile img { position: absolute; width: 118%; height: 118%; max-width: none; left: -9%; top: -8%; object-fit: cover; }
.ln-brand:hover .ln-brand-tile { transform: translateY(-2px) rotate(-3deg); }
.ln-brand-word { display: grid; line-height: 1; }
.ln-brand-word b { font: 700 15px/1 var(--font-display); letter-spacing: .14em; text-transform: uppercase; }
.ln-brand-word small { margin-top: 5px; font: 700 9px/1 var(--font-display); letter-spacing: .26em; color: var(--accent-text); }

/* ── tape, share card, price flash ─────────────────────────────────────── */
.ln-tape { overflow: hidden; height: 56px; display: flex; align-items: center; -webkit-mask: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent); mask: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent); }
.ln-tape-track { display: flex; width: max-content; animation: ln-tape 70s linear infinite; }
.ln-tape:hover .ln-tape-track, .ln-tape.is-paused .ln-tape-track { animation-play-state: paused; }
.ln-tape-dup { display: flex; }
@keyframes ln-tape { to { transform: translateX(-50%); } }
.ln-tape-item { display: inline-flex; align-items: center; gap: 9px; height: 40px; padding: 0 22px; border-right: 1px solid var(--glass-edge); white-space: nowrap; font-size: 13.5px; transition: background var(--t-fast); }
.ln-tape-item:hover, .ln-tape-item:focus-visible { background: rgb(var(--tint) / .04); }
.ln-tape-item b { font: 600 13.5px/1 var(--font-display); }
@media (prefers-reduced-motion: reduce) { .ln-tape { overflow-x: auto; } .ln-tape-track { animation: none; } .ln-tape-dup { display: none; } }
.ln-sharecard { border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--glass-edge-hi); background: var(--ink-2); aspect-ratio: 1200 / 630; }
.ln-sharecard img { width: 100%; height: 100%; object-fit: cover; }
.ln-flash-up { animation: ln-flash-up 900ms var(--ease-out); }
.ln-flash-dn { animation: ln-flash-dn 900ms var(--ease-out); }
@keyframes ln-flash-up { from { color: var(--up); text-shadow: 0 0 14px var(--up); } }
@keyframes ln-flash-dn { from { color: var(--dn); text-shadow: 0 0 14px var(--dn); } }

/* ── season podium, race rows, family league ──────────────────────────── */
.nl-podium { display: grid; grid-template-columns: 1fr 1.15fr 1fr; align-items: end; gap: 10px; margin: 6px 0 18px; }
.nl-pod { display: grid; justify-items: center; gap: 8px; text-align: center; min-width: 0; }
.nl-pod a { display: grid; justify-items: center; gap: 6px; min-width: 0; max-width: 100%; }
.nl-pod b { font: 600 14px/1.2 var(--font-display); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nl-pod em { font: 600 13px/1 var(--font-mono); font-style: normal; color: var(--accent-text-strong); }
.nl-pod-block { width: 100%; border-radius: 14px 14px 4px 4px; display: grid; place-items: center; font: 700 26px/1 var(--font-mono); color: rgb(var(--tint) / .2);
  background: linear-gradient(180deg, rgb(var(--glow) / .28), rgb(var(--raise) / .5)); border: 1px solid rgb(var(--glow) / .25); border-bottom: 0; transition: box-shadow 800ms var(--ease-out), background 800ms; }
.nl-pod:nth-child(1) .nl-pod-block { height: 74px; }
.nl-pod:nth-child(2) .nl-pod-block { height: 110px; }
.nl-pod:nth-child(3) .nl-pod-block { height: 56px; }
.nl-podium.is-lit .nl-pod-block { box-shadow: 0 -20px 50px rgb(var(--glow) / .22), inset 0 1px 0 rgb(var(--sheen-rgb) / .5); background: linear-gradient(180deg, rgb(var(--glow) / .45), rgb(var(--shade) / .6)); color: rgb(var(--sheen-rgb) / .55); }
.nl-podium.is-lit .nl-pod:nth-child(2) .nl-pod-block { box-shadow: 0 -30px 70px rgb(var(--glow) / .35), inset 0 1px 0 rgb(var(--sheen-rgb) / .7); }
.nl-pod .nl-pod-light { position: relative; }
.nl-podium.is-lit .nl-pod:nth-child(2) .nl-pod-light::before { content: ''; position: absolute; left: 50%; top: -30px; width: 180px; height: 180px; transform: translateX(-50%); background: radial-gradient(circle, rgb(var(--glow) / .35), transparent 65%); pointer-events: none; animation: nl-spot 3.2s var(--ease-in-out) infinite alternate; }
@keyframes nl-spot { from { opacity: .6; } to { opacity: 1; } }
.nl-race-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.nl-row a { display: grid; grid-template-columns: 28px auto minmax(0, 1fr) auto; align-items: center; gap: 10px; min-height: var(--tap); padding: 6px 10px; border-radius: var(--r-md); transition: background var(--t-fast); }
.nl-row a:hover, .nl-row a:focus-visible { background: rgb(var(--tint) / .04); }
.nl-row i { font: 600 13px/1 var(--font-mono); font-style: normal; color: var(--text-3); text-align: right; }
.nl-row-n { min-width: 0; }
.nl-row-n b { display: block; font: 600 14px/1.2 var(--font-display); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nl-row-n .cf-bar { height: 3px; margin-top: 6px; }
.nl-row-s { text-align: right; }
.nl-row-s b { display: block; font: 600 14px/1 var(--font-mono); }
.nl-row-s small { color: var(--up); font: 500 11px/1.4 var(--font-mono); }
.nl-row.is-moving { transition: transform 700ms var(--ease-out); }
.nl-league { display: grid; gap: 10px; }
.nl-fam { display: grid; grid-template-columns: 24px minmax(0, 1fr) auto; gap: 10px; align-items: center; }
.nl-fam i { font: 600 13px/1 var(--font-mono); font-style: normal; color: var(--text-3); }
.nl-fam b { font: 600 14px/1.2 var(--font-display); }
.nl-fam small { display: block; color: var(--text-3); font-size: 12px; }
.nl-fam .cf-bar { height: 3px; margin-top: 6px; }
.nl-fam em { font: 600 14px/1 var(--font-mono); font-style: normal; color: var(--accent-text-strong); }
[hidden] { display: none !important; }
.ln-tc-actions { margin-left: auto; }
@media (max-width: 520px) {
  .ln-tc-foot .ln-tc-also { flex-basis: 100%; }
  .ln-tc-actions { width: 100%; }
  .ln-tc-actions .cf-btn--primary { flex: 1; }
}

/* ── gamification interactions ─────────────────────────────────────────── */
.ln-flipmedal { position: relative; perspective: 900px; cursor: pointer; border: 0; padding: 0; background: none; color: inherit; }
.ln-flipmedal-in { position: relative; display: grid; transition: transform 700ms var(--ease-spring); transform-style: preserve-3d; }
.ln-flipmedal-in > * { grid-area: 1 / 1; backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.ln-flipmedal-back { transform: rotateY(180deg); display: grid; place-items: center; align-content: center; gap: 4px; text-align: center; border-radius: 50%; padding: 12%;
  background: radial-gradient(circle at 40% 30%, var(--ink-4), var(--ink-2)); box-shadow: inset 0 0 0 2px rgb(var(--glow) / .5), var(--shadow-2); font-size: 11.5px; line-height: 1.35; color: var(--text-2); }
.ln-flipmedal-back b { font: 700 13px/1.1 var(--font-display); color: var(--accent-text-strong); }
.ln-flipmedal-back em { font: 600 11px/1.2 var(--font-mono); font-style: normal; color: var(--text-1); }
.ln-flipmedal[aria-pressed="true"] .ln-flipmedal-in { transform: rotateY(180deg); }
@media (hover: hover) { .ln-flipmedal:hover .ln-flipmedal-in { transform: rotateY(180deg); } }

.ln-pod-copy { margin-top: 4px; }

/* ── 2. the page ───────────────────────────────────────────────────────── */
.ln-skip { position: absolute; left: -999px; top: 8px; z-index: 100; display: inline-flex; align-items: center; min-height: var(--tap); padding: 0 14px; background: var(--gold-300); color: var(--on-molten); border-radius: var(--r-sm); }
.ln-skip:focus { left: 8px; }
.nl-wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); }

/* ── top bar: transparent over the hero, glass once scrolled ──────────── */
.nl-top { position: sticky; top: 0; z-index: var(--z-bar); transition: background var(--t-med), box-shadow var(--t-med), border-color var(--t-med); border-bottom: 1px solid transparent; }
.nl-top.is-scrolled { background: rgb(var(--ground-rgb) / .72); -webkit-backdrop-filter: blur(18px) saturate(1.3); backdrop-filter: blur(18px) saturate(1.3); border-color: var(--glass-edge); box-shadow: 0 10px 30px rgb(var(--shade) / .4); }
.nl-top-in { max-width: var(--maxw); margin: 0 auto; padding: 10px var(--gutter); display: flex; align-items: center; gap: var(--sp-6); }
.nl-nav { display: flex; gap: 4px; margin-left: auto; }
.nl-nav a { position: relative; display: inline-flex; align-items: center; gap: 7px; min-height: var(--tap); padding: 0 14px; color: var(--text-2); font: 500 14px/1 var(--font-display); border-radius: var(--r-pill); transition: color var(--t-fast); }
/* The glyph beside each label (navigation.ICONS via nav_icon): dim with the
   label, full when lit; it never replaces the word. */
.nl-nav a .cf-nav-i { opacity: .8; transition: opacity var(--t-fast), transform var(--t-med) var(--ease-out); }
.nl-nav a:hover .cf-nav-i, .nl-nav a:focus-visible .cf-nav-i { opacity: 1; transform: translateY(-1px); }
.nl-top-cta { gap: 7px; }
@media (prefers-reduced-motion: reduce) { .nl-nav a .cf-nav-i { transition: none; } .nl-nav a:hover .cf-nav-i { transform: none; } }
.nl-nav a::after { content: ''; position: absolute; left: 14px; right: 14px; bottom: 9px; height: 1px; background: var(--gold-300); transform: scaleX(0); transform-origin: left; transition: transform var(--t-med) var(--ease-out); }
.nl-nav a:hover, .nl-nav a:focus-visible { color: var(--text-1); }
.nl-nav a:hover::after { transform: scaleX(1); }
@media (max-width: 860px) { .nl-nav { display: none; } .nl-top [data-ln-theme] { margin-left: auto; } }
.nl-top-in { gap: 12px; } .nl-nav { margin-right: 12px; }
@media (max-width: 380px) { .ln-brand-word small { display: none; } .nl-top-cta { padding: 0 14px; font-size: 13px; } }
/* Phones: .nl-nav is hidden at 860px, so the same sections plus Blog and Docs
   (public_links) ride as one chip row under the header, scrolling inside
   itself -- never the page. 36px chips with a 44px tap area. */
.nl-quick { display: none; }
@media (max-width: 860px) {
  .nl-quick { display: flex; gap: 6px; padding: 0 var(--gutter) 10px; max-width: 100%; box-sizing: border-box; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .nl-quick::-webkit-scrollbar { display: none; }
  .nl-quick a { position: relative; flex: none; display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 12px; border-radius: var(--r-pill); border: 1px solid var(--glass-edge); background: rgb(var(--tint) / .05); color: var(--text-2); font: 600 13px/1 var(--font-display); white-space: nowrap; text-decoration: none; transition: color var(--t-fast), border-color var(--t-fast); }
  .nl-quick a::before { content: ''; position: absolute; inset: -4px 0; }
  .nl-quick a:hover, .nl-quick a:focus-visible { color: var(--text-1); border-color: var(--glass-edge-hi); }
  .nl-quick a .cf-nav-i { opacity: .8; }
}

/* ── hero ──────────────────────────────────────────────────────────────── */
.nl-hero { position: relative; overflow: hidden; margin-top: -65px; padding-top: 65px; min-height: min(100svh, 980px); display: flex; align-items: center; }
.nl-embers { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
.nl-hero::after { content: ''; position: absolute; inset: auto 0 0; height: 160px; background: linear-gradient(180deg, transparent, var(--ink-1)); pointer-events: none; z-index: 1; }
.nl-hero-in { position: relative; z-index: 2; width: 100%; max-width: var(--maxw); margin: 0 auto; padding: var(--sp-12) var(--gutter) var(--sp-16); display: grid; grid-template-columns: minmax(0, 1.12fr) minmax(0, .88fr); gap: clamp(24px, 5vw, 80px); align-items: center; }
.nl-hero-eyebrow { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 0 0 18px; font: 500 13px/1.3 var(--font-mono); }
.nl-h1 { margin: 0; font: 700 var(--fs-hero)/.94 var(--font-display); letter-spacing: -.05em; text-wrap: balance; }
.nl-h1 .cf-molten-text { padding-right: .04em; background-size: 200% 100%; animation: nl-molten 7s var(--ease-in-out) infinite alternate; }
@keyframes nl-molten { from { background-position: 0% 50%; } to { background-position: 100% 50%; } }
.nl-hero-lede { margin: 24px 0 0; max-width: 52ch; color: var(--text-2); font-size: clamp(16px, 1.45vw, 19px); line-height: 1.55; }
.nl-hero-cta { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 32px; }
.nl-xl { min-height: 54px; padding: 0 28px; font-size: 16px; }
.nl-hero-proof { display: flex; gap: clamp(20px, 4vw, 48px); flex-wrap: wrap; margin: 40px 0 0; padding-top: 22px; border-top: 1px solid var(--glass-edge); }
.nl-hero-proof div { min-width: 0; }
.nl-hero-proof dt { font: 600 var(--fs-micro)/1 var(--font-mono); letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--text-3); }
.nl-hero-proof dd { margin: 8px 0 0; font: 600 clamp(22px, 2.4vw, 30px)/1 var(--font-mono); letter-spacing: -.03em; }

/* the phone: a CSS-drawn device in molten bezel */
.nl-hero-stage { position: relative; display: flex; justify-content: center; min-width: 0; padding: 20px 0; }
.nl-phone { position: relative; width: min(340px, 100%); aspect-ratio: 9 / 18.6; border-radius: 48px; padding: 11px;
  background: linear-gradient(145deg, var(--gold-800), var(--ink-0) 30%, var(--gold-900) 70%, var(--gold-700));
  box-shadow: 0 0 0 1px rgb(var(--sheen-rgb) / .28), 0 1px 0 rgb(var(--sheen-rgb) / .35) inset, 0 40px 90px rgb(var(--shade) / .75), 0 0 120px rgb(var(--glow) / .18);
  transform: perspective(1400px) rotateY(-9deg) rotateX(3deg); transition: transform var(--t-slow) var(--ease-out); }
.nl-hero-stage:hover .nl-phone { transform: perspective(1400px) rotateY(-3deg) rotateX(1deg); }
.nl-phone-notch { position: absolute; top: 20px; left: 50%; width: 92px; height: 26px; transform: translateX(-50%); border-radius: 14px; background: var(--ink-0); z-index: 3; }
.nl-phone-screen { position: relative; height: 100%; border-radius: 38px; overflow: hidden; background: radial-gradient(120% 60% at 50% 0%, var(--ground-hi), var(--ink-1) 60%); display: flex; flex-direction: column; }
.nl-phone-bar { display: flex; align-items: center; justify-content: space-between; padding: 54px 18px 10px; }
.nl-phone-bar b { font: 700 20px/1 var(--font-display); letter-spacing: -.02em; }
.nl-phone-feed { flex: 1; overflow: hidden; padding: 0 12px; display: flex; flex-direction: column; gap: 10px;
  -webkit-mask: linear-gradient(180deg, #000 80%, transparent); mask: linear-gradient(180deg, #000 80%, transparent); }
.nl-mini { flex: none; padding: 12px; border-radius: 18px; background: linear-gradient(180deg, rgb(var(--raise) / .95), rgb(var(--raise) / .95)); border: 1px solid var(--glass-edge); box-shadow: var(--shadow-1); }
.nl-mini-h { display: flex; align-items: center; gap: 9px; }
.nl-mini-h b { font: 600 13px/1.2 var(--font-display); }
.nl-mini-h small { display: block; color: var(--text-3); font: 500 10.5px/1.3 var(--font-mono); }
.nl-mini-h .cf-chip { margin-left: auto; height: 20px; font-size: 9.5px; }
.nl-mini-t { display: flex; align-items: center; gap: 9px; margin-top: 10px; padding: 8px; border-radius: 12px; background: var(--well); }
.nl-mini-t b { font: 700 14px/1 var(--font-display); flex: 1; }
.nl-mini-t em { font: 600 14px/1 var(--font-mono); font-style: normal; }
.nl-mini-f { display: flex; justify-content: flex-end; margin-top: 9px; }
.nl-mini-f span { display: inline-flex; align-items: center; height: 28px; padding: 0 14px; border-radius: var(--r-pill); background: var(--molten); color: var(--on-molten); font: 700 12px/1 var(--font-display); }
.nl-mini.is-in { animation: nl-drop 640ms var(--ease-spring); }
@keyframes nl-drop { from { transform: translateY(-40px) scale(.94); opacity: 0; } to { transform: none; opacity: 1; } }
.nl-phone-tabbar { display: grid; grid-template-columns: repeat(5, 1fr); align-items: center; height: 62px; padding: 0 18px 8px; border-top: 1px solid var(--glass-edge); background: rgb(var(--ground-rgb) / .9); }
.nl-phone-tabbar span { justify-self: center; display: grid; place-items: center; width: 24px; height: 24px; color: var(--text-4); }
.nl-phone-tabbar span svg { width: 22px; height: 22px; }
.nl-phone-tabbar span.on { color: var(--gold-300); filter: drop-shadow(0 0 6px rgb(var(--glow) / .45)); }
.nl-phone-tabbar span.mid { width: 42px; height: 42px; border-radius: 50%; color: var(--ground, #0a0a0a); background: var(--molten); box-shadow: 0 6px 18px rgb(var(--glow) / .4); }
.nl-phone-tabbar span.mid svg { width: 22px; height: 22px; }

.nl-orbit { position: absolute; z-index: 4; display: flex; align-items: center; gap: 10px; padding: 10px 14px 10px 10px; border-radius: var(--r-lg); background: var(--glass-strong); border: 1px solid var(--glass-edge-hi); box-shadow: var(--shadow-3); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); max-width: 230px; }
.nl-orbit b { display: block; font: 600 13.5px/1.2 var(--font-display); }
.nl-orbit small { display: block; color: var(--text-3); font: 500 11px/1.3 var(--font-mono); }
.nl-orbit--a { left: -4%; top: 16%; animation: nl-float 6s var(--ease-in-out) infinite; }
.nl-orbit--b { right: -4%; bottom: 14%; animation: nl-float 7s var(--ease-in-out) -2s infinite; }
@keyframes nl-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
.nl-orbit .nl-x { font: 700 22px/1 var(--font-mono); color: var(--up); text-shadow: 0 0 16px rgb(var(--up-rgb) / .5); }

@media (max-width: 960px) {
  .nl-hero { min-height: 0; }
  .nl-hero-in { grid-template-columns: 1fr; padding-top: var(--sp-8); }
  .nl-hero-stage { margin-top: 8px; }
  .nl-phone { width: min(320px, 86vw); transform: none; }
  .nl-hero-stage:hover .nl-phone { transform: none; }
  .nl-orbit--a { left: 0; top: 6%; }
  .nl-orbit--b { right: 0; bottom: 8%; }
}
@media (max-width: 600px) {
  .nl-hero-stage { flex-wrap: wrap; gap: 10px; }
  .nl-phone { order: -1; }
  .nl-orbit { position: static; max-width: none; flex: 1 1 150px; padding: 8px 10px 8px 8px; animation: none; }
  .nl-orbit b { font-size: 12.5px; }
}

/* ── tape ──────────────────────────────────────────────────────────────── */
.nl-tape { position: relative; z-index: 2; border-block: 1px solid var(--glass-edge); background: linear-gradient(90deg, rgb(var(--glow) / .06), rgb(var(--raise) / .9) 20%, rgb(var(--raise) / .9) 80%, rgb(var(--glow) / .06)); }
.nl-tape-pause { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); width: var(--tap); height: var(--tap); border-radius: 50%; border: 1px solid var(--glass-edge-hi); background: var(--ink-3); color: var(--text-2); cursor: pointer; display: grid; place-items: center; }
.nl-tape-pause svg { width: 16px; height: 16px; }

/* ── sections ──────────────────────────────────────────────────────────── */
.nl-sec { position: relative; padding: clamp(48px, 6.5vw, 96px) 0; }
.nl-sec-h { margin-bottom: clamp(28px, 4vw, 48px); }
.nl-sec-h--row { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.nl-sec--vault { background: radial-gradient(900px 500px at 50% 0%, rgb(var(--glow) / .1), transparent 70%); }

.nl-proof { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-4); }
.nl-stat { padding: var(--sp-5); display: grid; gap: 10px; }
.nl-stat b { font: 600 clamp(26px, 3.2vw, 42px)/1 var(--font-mono); letter-spacing: -.04em; }
.nl-stat small { font-size: 12.5px; min-height: 1.3em; }
.nl-proof-charts { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: var(--sp-4); margin-top: var(--sp-4); }
.nl-proof-charts figure { margin: 0; }
.nl-chart-lg { height: 200px; }
.nl-chart-md { height: 150px; }
@media (max-width: 900px) { .nl-proof { grid-template-columns: repeat(2, minmax(0, 1fr)); } .nl-proof-charts { grid-template-columns: 1fr; } }

.nl-feed { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-4); }
@media (max-width: 1080px) { .nl-feed { grid-template-columns: repeat(2, minmax(0, 1fr)); } .nl-feed > :nth-child(3) { display: none; } }
@media (max-width: 680px) { .nl-feed { grid-template-columns: minmax(0, 1fr); } .nl-feed > :nth-child(3) { display: block; } }

/* ── ranks: five medallions on a vault ledge ───────────────────────────── */
.nl-ladder { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--sp-3); }
.nl-rung { width: 100%; display: grid; justify-items: center; gap: 8px; padding: 22px 10px 16px; border-radius: var(--r-lg); border: 1px solid var(--glass-edge); background: linear-gradient(180deg, rgb(var(--raise) / .7), rgb(var(--raise) / .7)); cursor: pointer; text-align: center; transition: transform var(--t-med) var(--ease-spring), border-color var(--t-med), box-shadow var(--t-med); position: relative; }
.nl-rung .cf-medal { transition: transform var(--t-slow) var(--ease-spring); }
.nl-rung b { font: 700 15px/1.1 var(--font-display); }
.nl-rung small { color: var(--text-3); font: 500 11.5px/1.3 var(--font-mono); }
.nl-rung .cf-bar { width: 80%; height: 4px; }
.nl-rung .nl-rung-n { font: 600 12px/1 var(--font-mono); color: var(--text-2); }
.nl-rung[aria-pressed="true"] { border-color: rgb(var(--glow) / .5); box-shadow: var(--glow-gold); transform: translateY(-6px); }
.nl-rung[aria-pressed="true"] .cf-medal { transform: scale(1.08) rotate(-6deg); }
@media (hover: hover) { .nl-rung:hover { transform: translateY(-4px); border-color: var(--glass-edge-hi); } }
.nl-ladder-detail { margin-top: var(--sp-4); display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--sp-6); align-items: start; }
.nl-ladder-detail h3 { margin: 0 0 4px; font: 700 22px/1.1 var(--font-display); }
.nl-rules { list-style: none; margin: 12px 0 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 20px; }
.nl-rules li { display: flex; justify-content: space-between; gap: 12px; padding: 9px 0; border-bottom: 1px dashed var(--glass-edge); font-size: 14px; }
.nl-rules li small { display: block; color: var(--text-3); font-size: 12px; }
.nl-rules li b { font: 600 14px/1.2 var(--font-mono); color: var(--accent-text); white-space: nowrap; }
@media (max-width: 760px) {
  .nl-ladder { grid-template-columns: 1fr; }
  .nl-rung { grid-template-columns: auto 1fr auto; justify-items: start; text-align: left; padding: 12px 14px; gap: 4px 14px; }
  .nl-rung > .ln-flipmedal { grid-row: 1 / span 3; width: 56px !important; height: 56px !important; align-self: center; }
  .nl-rung > .ln-flipmedal svg { width: 56px; height: 56px; }
  .nl-rung > b, .nl-rung > small { grid-column: 2; }
  .nl-rung .cf-bar { grid-column: 2; width: 100%; }
  .nl-rung { grid-template-rows: auto auto auto; }
  .nl-rung .nl-rung-n { grid-row: 1 / span 2; grid-column: 3; align-self: center; }
  .nl-rung[aria-pressed="true"] { transform: none; }
  .nl-ladder-detail { grid-template-columns: 1fr; }
  .nl-rules { grid-template-columns: 1fr; }
}

.nl-season { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: var(--sp-4); margin-top: var(--sp-8); }
@media (max-width: 900px) { .nl-season { grid-template-columns: 1fr; } }
.nl-last-h { margin-top: var(--sp-6); }
.nl-last { display: grid; gap: 8px; }
.nl-last a, .nl-last div { display: flex; align-items: center; gap: 10px; min-height: var(--tap); }
.nl-last b { flex: 1; font: 600 14px/1.2 var(--font-display); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nl-last em { font: 600 13px/1 var(--font-mono); font-style: normal; color: var(--text-2); }

/* ── launches + calls ──────────────────────────────────────────────────── */
.nl-two { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: var(--sp-4); }
@media (max-width: 960px) { .nl-two { grid-template-columns: 1fr; } }
.nl-launches, .nl-calls { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.nl-l { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 10px; border-radius: var(--r-md); transition: background var(--t-fast); }
.nl-l:hover, .nl-l:focus-within { background: rgb(var(--tint) / .04); }
.nl-l-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.nl-l-top b { font: 700 15px/1.1 var(--font-display); }
.nl-l-sub { margin-top: 3px; color: var(--text-3); font: 500 12px/1.4 var(--font-mono); }
.nl-l .cf-bar { margin-top: 8px; height: 5px; }
.nl-l-r { text-align: right; display: grid; gap: 6px; justify-items: end; }
.nl-l-r em { font: 600 13px/1 var(--font-mono); font-style: normal; }
.nl-launch-foot { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: var(--sp-4); font-size: 13px; }
.nl-c { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 8px 6px; }
.nl-c b { font: 600 14px/1.2 var(--font-display); }
.nl-c small { display: block; color: var(--text-3); font: 500 12px/1.3 var(--font-mono); }
.nl-c .cf-bar { height: 4px; margin-top: 6px; }
.nl-c em { font: 700 18px/1 var(--font-mono); font-style: normal; color: var(--up); text-shadow: 0 0 14px rgb(var(--up-rgb) / .35); }

/* ── feature widgets ───────────────────────────────────────────────────── */
.nl-feat { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--sp-4); }
.nl-w { grid-column: span 4; padding: var(--sp-5); display: flex; flex-direction: column; min-width: 0; min-height: 260px; }
.nl-w[data-w="copy"], .nl-w[data-w="positions"], .nl-w[data-w="share"], .nl-w[data-w="chains"] { grid-column: span 6; }
.nl-w header { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.nl-w header h3 { margin: 0; flex: 1; font: 600 16px/1.2 var(--font-display); }
.nl-w-ic, .nl-why-ic { width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center; flex: none; color: var(--accent-text-strong); background: linear-gradient(145deg, rgb(var(--glow) / .22), rgb(var(--glow) / .12)); box-shadow: inset 0 0 0 1px rgb(var(--glow) / .3); }
.nl-w-ic svg, .nl-why-ic svg { width: 18px; height: 18px; }
.nl-w-body { flex: 1; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.nl-w-chart { height: 120px; margin-top: auto; }
.nl-w-row { display: flex; align-items: center; gap: 10px; min-height: 48px; min-width: 0; }
.nl-w-row > div { flex: 1; min-width: 0; }
.nl-w-row b { display: block; font: 600 14px/1.2 var(--font-display); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nl-w-row small { display: block; color: var(--text-3); font: 500 11.5px/1.3 var(--font-mono); }
.nl-w-row .nl-w-spark { width: 80px; height: 28px; flex: none; }
.nl-w-big { font: 600 30px/1 var(--font-mono); letter-spacing: -.03em; }
.nl-locked { flex: 1; display: grid; place-items: center; text-align: center; gap: 10px; padding: 10px; border-radius: var(--r-md); border: 1px dashed rgb(var(--glow) / .22); background: repeating-linear-gradient(135deg, rgb(var(--tint) / .015) 0 10px, transparent 10px 20px); }
.nl-locked p { margin: 0; color: var(--text-2); font-size: 13.5px; max-width: 28ch; }
.nl-locked .cf-btn { margin-top: 2px; }
.nl-chains { display: flex; gap: 6px; flex-wrap: wrap; margin-top: auto; }
.nl-donut { height: 150px; display: grid; place-items: center; }
@media (max-width: 1100px) { .nl-w { grid-column: span 6; } }
@media (max-width: 680px) { .nl-w, .nl-w[data-w] { grid-column: span 12 !important; } }

/* ── why + cta + footer ───────────────────────────────────────────────── */
.nl-why { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px; background: var(--glass-edge); border: 1px solid var(--glass-edge); border-radius: var(--r-xl); overflow: hidden; }
.nl-why-i { padding: clamp(20px, 3vw, 36px); background: var(--ink-1); transition: background var(--t-med); }
.nl-why-i:hover { background: var(--surface-hover); }
.nl-why-i h3 { margin: 16px 0 6px; font: 600 19px/1.2 var(--font-display); }
.nl-why-i p { margin: 0; color: var(--text-2); font-size: 14.5px; }
@media (max-width: 900px) { .nl-why { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .nl-why { grid-template-columns: 1fr; } }
.nl-cta { padding: clamp(80px, 12vw, 160px) 0; text-align: center; background: radial-gradient(700px 360px at 50% 60%, rgb(var(--glow) / .18), transparent 70%); }
.nl-cta-in { display: grid; justify-items: center; }
.nl-cta-medal { min-height: 120px; }
.nl-cta-btns { justify-content: center; }
.nl-foot { border-top: 1px solid var(--glass-edge); padding: 28px 0 calc(28px + env(safe-area-inset-bottom)); }
.nl-foot-in { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; justify-content: space-between; font-size: 13px; }
.nl-foot nav { display: flex; gap: 6px; flex-wrap: wrap; }
.nl-foot nav a { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: var(--tap); min-width: var(--tap); padding: 0 10px; color: var(--text-2); }
.nl-foot nav a .cf-nav-i { width: 14px; height: 14px; opacity: .75; }
.nl-foot nav a:hover .cf-nav-i { opacity: 1; }
.nl-foot nav a:hover { color: var(--accent-text-strong); }

@media (prefers-reduced-motion: reduce) {
  .nl-h1 .cf-molten-text, .nl-orbit--a, .nl-orbit--b, .nl-podium.is-lit .nl-pod:nth-child(2) .nl-pod-light::before { animation: none; }
  .nl-phone, .nl-hero-stage:hover .nl-phone { transform: none; transition: none; }
}

/* ── install prompt (beforeinstallprompt only) ─────────────────────────── */
.nl-pwa { position: fixed; z-index: var(--z-toast); left: 50%; bottom: calc(16px + env(safe-area-inset-bottom)); transform: translateX(-50%);
  display: flex; align-items: center; gap: 12px; width: min(480px, calc(100vw - 32px)); padding: 12px; }
.nl-pwa-t { flex: 1; min-width: 0; display: grid; }
.nl-pwa-t b { font: 600 14px/1.3 var(--font-display); }
.nl-pwa-t span { color: var(--text-3); font-size: 12.5px; }
@media (max-width: 420px) { .nl-pwa .ln-brand-tile { display: none; } }

/* Section titles are h2 elements at the shared h1 size (the reference's
   section heading), with the reference's breathing room above and below. */
.nl-sec-h .cf-h1, .nl-cta .cf-h1 { margin: 10px 0 8px; }

/* Touch: every control is 44px to a finger on a tablet or phone. The
   theme button never shrinks in the bar; small pills keep their look on a
   desktop pointer and grow to the full target where a thumb does the
   tapping; an avatar link gets the target around it. */
.nl-top [data-ln-theme] { flex: none; }
@media (max-width: 1024px) {
  .ln-landing .cf-btn--sm { min-height: var(--tap); }
  .nl-w-row > .cf-ava-wrap { display: grid; place-items: center; min-width: var(--tap); min-height: var(--tap); }
}


/* ---- 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}

