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

@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');

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