@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-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}
}
/* the status row: "Signup bonus · Not claimed · [SOL] $2 in SOL" (entry card and member sheet) */
.cfb-srow{display:flex;align-items:center;flex-wrap:wrap;gap:6px 8px;font:600 12px/1.3 var(--font-ui);color:var(--ink2)}
.cfb-srow-k{color:var(--ink2)}
.cfb-srow-amt{display:inline-flex;align-items:center;gap:6px;margin-left:auto;font:800 13px/1 var(--font-num,var(--font-ui));color:var(--ink)}
.cfb-srow-logo{width:16px;height:16px;flex:none;display:block}
/* the signed-out entry's offer card (wallet-onboarding.js) */
.cfb-offer{box-sizing:border-box;display:flex;flex-direction:column;gap:12px;width:100%;text-align:left;padding:16px;border-radius:18px;
  border:1px solid var(--line);background:linear-gradient(160deg,var(--accBg),var(--s2) 55%)}
.cfb-offer-h{margin:0;font:800 20px/1.2 var(--font-display,var(--font-ui));letter-spacing:-.01em;color:var(--ink)}
.cfb-offer-h em{font-style:normal;color:var(--accent-text-strong,var(--acc))}
.cfb-steps--entry .cfb-step{background:var(--s1)}
.cfb-step[data-st="locked"]{opacity:.62}
.cfb-step[data-st="locked"] .cfb-dot{border-style:dashed}
.cfb-step[data-st="todo"] .cfb-dot{border-color:var(--acc);color:var(--accent-text-strong,var(--acc))}
.cfb-how{border-top:1px solid var(--line);padding-top:10px}
.cfb-how summary{cursor:pointer;min-height:44px;display:flex;align-items:center;gap:8px;list-style:none;
  font:700 13px/1.2 var(--font-ui);color:var(--ink)}
.cfb-how summary::-webkit-details-marker{display:none}
.cfb-how summary::after{content:'';width:8px;height:8px;margin-left:auto;border-right:2px solid var(--ink2);border-bottom:2px solid var(--ink2);
  transform:rotate(45deg) translate(-2px,-2px);transition:transform .2s}
.cfb-how[open] summary::after{transform:rotate(-135deg) translate(-2px,-2px)}
.cfb-how summary:focus-visible{outline:2px solid var(--focus,var(--acc));outline-offset:2px;border-radius:8px}
.cfb-how .cfb-rules{margin-top:2px}
@media (prefers-reduced-motion: reduce){ .cfb-how summary::after{transition:none} }


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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


/* ---- static/cf-profile-charts.css ---- */
/* Cartel Family — the profile's performance block (static/cf-profile-charts.js).
 *
 * Compact: ONE tile row, then ONE card -- "Performance", a chart switch and
 * the range switch, over a fixed-height stage that shows one chart at a time
 * (240px; 200px when the component is phone-narrow). The block answers to
 * its OWN width (container queries), so the same component sits in the
 * account column, the trader page and the Mini App without a per-page
 * override. Every colour is a cf-theme token.
 *
 * Content rests VISIBLE: .pc-in / .pc-swap are added from script, removed
 * when their animation ends, and only animate inside
 * prefers-reduced-motion:no-preference.
 */
.pc{container-type:inline-size;display:flex;flex-direction:column;gap:10px;min-width:0;
  font-family:var(--font-ui);color:var(--ink)}
.pc *{box-sizing:border-box}
.pc h2,.pc h3,.pc p{margin:0}

/* tiles */
.pc-tiles{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
.pc-tile{background:var(--s1);border:1px solid var(--line);border-radius:14px;padding:11px 14px;
  display:flex;flex-direction:column;gap:3px;min-width:0}
.pc-tile span{font:600 12px var(--font-ui);color:var(--ink2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pc-tile b{font:600 20px var(--font-num);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  font-variant-numeric:tabular-nums}
.pc-tile i{font:500 11px var(--font-ui);font-style:normal;color:var(--ink3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pc-up{color:var(--up)!important}
.pc-dn{color:var(--dn)!important}

.pc-note{font:500 12px/1.45 var(--font-ui);color:var(--pro);background:var(--proBg, var(--s2));
  border:1px solid var(--proLine, var(--line));border-radius:10px;padding:8px 12px}
.pc-note.pc-err{color:var(--ink2);background:var(--s1);border-color:var(--line);display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.pc-retry{appearance:none;border:1px solid var(--line);background:var(--s2);color:var(--ink);border-radius:9px;
  font:700 12px var(--font-ui);min-height:36px;padding:0 14px;cursor:pointer}

/* the one card */
.pc-card{background:var(--s1);border:1px solid var(--line);border-radius:16px;padding:12px 16px 14px;
  display:flex;flex-direction:column;gap:10px;min-width:0;position:relative}
.pc-perf-hd{display:flex;align-items:center;gap:10px 14px;flex-wrap:wrap;min-width:0}
.pc-title{font:800 15px var(--font-ui);color:var(--ink);flex:0 0 auto}
.pc-seg,.pc-tabs{display:flex;background:var(--s2);border-radius:10px;padding:2px;gap:2px;min-width:0}
.pc-seg{margin-left:auto;flex:0 0 auto}
.pc-tabs{flex:0 1 auto;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.pc-tabs::-webkit-scrollbar{display:none}
.pc-seg button,.pc-tabs button{appearance:none;border:0;background:transparent;color:var(--ink2);
  font:700 12px var(--font-ui);height:32px;padding:0 12px;border-radius:8px;cursor:pointer;white-space:nowrap;flex:0 0 auto}
.pc-seg button{min-width:44px}
.pc-seg button[aria-selected="true"],.pc-tabs button[aria-selected="true"]{background:var(--s1);color:var(--ink);box-shadow:0 1px 2px rgba(0,0,0,.18)}
/* Accent as TEXT is --accT (AA on both grounds); --acc is a fill and read 3.0:1 on the light card. */
.pc-tabs button[aria-selected="true"]{color:var(--accT, var(--ink))}
.pc-seg button:hover,.pc-tabs button:hover{color:var(--ink)}
.pc-seg button:focus-visible,.pc-tabs button:focus-visible{outline:2px solid var(--accT);outline-offset:-2px}

/* the stage: one chart, fixed height, whatever it shows */
.pc-stage{position:relative;height:240px;min-width:0;display:flex;flex-direction:column;gap:8px;overflow:hidden}
.pc-stage > .cf-chart-empty,.pc-stage .cf-chart-empty{min-height:0;height:100%;flex:1 1 auto}
.pc-fill{position:relative;flex:1 1 auto;min-height:0;width:100%}
.pc-fill.cf-chart{height:auto}
.pc-hist-host{position:relative;flex:1 1 auto;min-height:0;width:100%}
.pc-cal{flex:1 1 auto;min-height:0;min-width:0;display:flex;flex-direction:column;gap:8px}
.pc-heat-host{position:relative;flex:1 1 auto;min-height:0;min-width:0;display:flex;flex-direction:column;justify-content:center;align-items:center}
.pc-heat-host .cf-heat-scroll{flex:0 1 auto;max-width:100%}
.pc-heat-host .cf-heat-legend{justify-content:center}

/* chips: one line of readouts above a chart (scrolls sideways when narrow) */
.pc-chips{display:flex;flex-wrap:nowrap;gap:6px;overflow-x:auto;scrollbar-width:none;flex:0 0 auto;min-width:0}
.pc-chips::-webkit-scrollbar{display:none}
.pc-chip{font:600 11px var(--font-ui);color:var(--ink2);background:var(--s2);border-radius:999px;padding:5px 10px;
  white-space:nowrap;display:inline-flex;align-items:center;gap:5px;flex:0 0 auto}
.pc-chip b{font:700 11px var(--font-num);color:var(--ink)}
.pc-chip.up{color:var(--up);background:var(--upBg, var(--s2))}
.pc-chip.dn{color:var(--dn);background:var(--dnBg, var(--s2))}
.pc-chip .pc-sw{width:8px;height:8px;border-radius:2px;display:inline-block}

/* P&L with a single day: one summary line, centred in the stage */
.pc-solo{flex:1 1 auto;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;text-align:center;padding:0 12px}
.pc-solo b{font:600 26px var(--font-num);color:var(--ink);font-variant-numeric:tabular-nums}
.pc-solo span{font:500 12px/1.45 var(--font-ui);color:var(--ink2);max-width:460px}

/* wins / losses: a thin win-rate line above the histogram */
.pc-wr{flex:0 0 auto;display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:10px;height:46px}
.pc-wr-k{font:600 11px var(--font-ui);color:var(--ink2);max-width:72px;line-height:1.25}
.pc-wr-host{position:relative;height:46px;min-width:0}

/* chains: donut beside its list */
.pc-chain{flex:1 1 auto;min-height:0;display:flex;flex-direction:row;gap:16px;align-items:center}
.pc-chain.pc-chain-none{justify-content:center}
.pc-chain.pc-chain-none .pc-donut-host{flex:1 1 auto;height:100%}
.pc-chain{justify-content:center}
.pc-donut-host{position:relative;display:flex;justify-content:center;flex:0 0 auto;width:auto}
.pc-donut-host .cf-donut-svg,.pc-donut-host .cf-donut-center{width:150px;height:150px}
.pc-donut-host .cf-donut-legend{display:none}
.pc-chain-list{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;max-width:440px;max-height:100%;overflow-y:auto}
.pc-chain-row{display:grid;grid-template-columns:10px minmax(0,1fr) auto;grid-template-areas:"sw name pnl" ". n bar";
  align-items:center;column-gap:8px;row-gap:3px;padding:6px 0;border-top:1px solid var(--line)}
.pc-chain-row:first-child{border-top:0}
.pc-sw{grid-area:sw;width:10px;height:10px;border-radius:3px}
.pc-chain-name{grid-area:name;font:700 13px var(--font-ui);color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pc-chain-n{grid-area:n;font:500 11px var(--font-num);color:var(--ink2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.pc-chain-pnl{grid-area:pnl;font:600 13px var(--font-num);color:var(--ink2);white-space:nowrap;text-align:right}
.pc-chain-bar{grid-area:bar;position:relative;width:72px;height:6px;border-radius:3px;background:var(--s2);justify-self:end}
.pc-chain-bar i{position:absolute;top:0;bottom:0;border-radius:3px}
.pc-chain-bar i.up{background:var(--up)}
.pc-chain-bar i.dn{background:var(--dn)}

/* skeleton while the first read is in flight */
.pc[aria-busy="true"] .pc-stage:empty{border-radius:10px;
  background:linear-gradient(90deg,var(--s2) 0%,var(--line) 50%,var(--s2) 100%);
  background-size:200% 100%;animation:pcShimmer 1.2s linear infinite}
@keyframes pcShimmer{from{background-position:200% 0}to{background-position:-200% 0}}

/* touch: every control is a 44px target */
@media (pointer:coarse),(hover:none),(max-width:1024px){
  .pc-seg button,.pc-tabs button{height:44px}
  .pc-retry{min-height:44px}
}

/* wide: the calendar's readouts stand beside the squares */
@container (min-width:640px){
  .pc-cal{flex-direction:row;align-items:stretch;gap:20px}
  .pc-cal .pc-chips{order:2;flex:0 0 210px;flex-direction:column;justify-content:center;align-items:flex-start;overflow:visible}
  .pc-cal .pc-heat-host{order:1}
}
/* the switch on its own row when the header cannot hold title + tabs + range */
@container (max-width:780px){
  .pc-tabs{order:3;flex:1 1 100%}
}
/* phone: two tiles a row, a shorter stage, the range switch full width */
@container (max-width:560px){
  .pc-stage{height:200px}
  .pc-tiles{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  .pc-tile b{font-size:18px}
  .pc-card{padding:12px 12px 12px}
  .pc-seg{flex:1 1 auto}
  .pc-seg button{flex:1 1 0}
  .pc-chain{gap:12px}
  .pc-donut-host .cf-donut-svg,.pc-donut-host .cf-donut-center{width:116px;height:116px}
  .pc-donut-host .cf-donut-center b{font-size:15px}
  .pc-chain-row{grid-template-areas:"sw name pnl" ". n n"}
  .pc-chain-bar{display:none}
  .pc-solo b{font-size:22px}
}

@media (prefers-reduced-motion:no-preference){
  .pc-in{animation:pcIn .45s var(--ease-draw, cubic-bezier(.3,.7,.2,1)) both;
    animation-delay:calc(var(--pc-i, 0) * 40ms)}
  @keyframes pcIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
  .pc-swap{animation:pcSwap .26s var(--ease-draw, cubic-bezier(.3,.7,.2,1))}
  @keyframes pcSwap{from{opacity:.25;transform:translateY(6px)}to{opacity:1;transform:none}}
}
@media (prefers-reduced-motion:reduce){
  .pc[aria-busy="true"] .pc-stage:empty{animation:none}
}

/* ── Syndicate Noir (2026-10-12): the same block, drawn as /design/a/me ──
   Tiles and the card are glass panels with the light edge; labels are mono
   caps; figures mono and glowing in their direction; the switches are the
   ink track with a molten thumb. Tokens only. */
.pc{font-family:var(--font-body,var(--font-ui))}
.pc-tile,.pc-card{position:relative;border:1px solid var(--glass-edge);box-shadow:var(--shadow-2);border-radius:var(--r-lg,20px);
  background:linear-gradient(180deg,rgb(var(--raise) / .66),rgb(var(--raise) / .72) 38%,var(--glass));
  -webkit-backdrop-filter:blur(var(--blur)) saturate(var(--glass-saturate));backdrop-filter:blur(var(--blur)) saturate(var(--glass-saturate))}
.pc-tile::before,.pc-card::before{content:'';position:absolute;inset:0;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}
.pc-tile{padding:14px 16px;gap:6px}
.pc-tile span{font:600 10px/1.2 var(--font-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--ink3)}
.pc-tile b{font:600 22px var(--font-mono);letter-spacing:-.02em}
.pc-tile i{font:500 11.5px var(--font-body,var(--font-ui))}
.pc-up{text-shadow:0 0 14px rgb(var(--up-rgb) / .3)}
.pc-dn{text-shadow:0 0 14px rgb(var(--dn-rgb) / .3)}
.pc-card{padding:16px 18px}
.pc-title{font:600 18px var(--font-display,var(--font-ui));letter-spacing:-.01em}
.pc-seg,.pc-tabs{background:var(--ink-2);border:1px solid var(--glass-edge);border-radius:var(--r-pill,999px);padding:3px}
.pc-seg button,.pc-tabs button{border-radius:var(--r-pill,999px);font-family:var(--font-display,var(--font-ui));font-weight:600;
  transition:color var(--t-med,.28s),background var(--t-med,.28s),box-shadow var(--t-med,.28s)}
.pc-seg button[aria-selected="true"],.pc-tabs button[aria-selected="true"]{background:var(--molten);color:var(--on-molten);box-shadow:0 4px 14px rgb(var(--glow) / .35)}
.pc-seg button:focus-visible,.pc-tabs button:focus-visible{outline:none;box-shadow:var(--focus-ring)}
.pc-note{background:rgb(var(--glow) / .08);border-color:rgb(var(--glow) / .3);color:var(--accent-text-strong);border-radius:var(--r-md,14px)}
.pc-note.pc-err{background:var(--dn-dim);border-color:rgb(var(--dn-rgb) / .35);color:var(--ink)}
.pc-retry{border-radius:var(--r-pill,999px);border-color:var(--glass-edge-hi);background:var(--ink-4);font-family:var(--font-display,var(--font-ui))}
.pc-solo b{font-family:var(--font-mono)}


/* ---- static/profile-v2.css ---- */
/* Cartel Family profile v2 — approved compact profile layout */
.oa-profile-v2{
  /* Aliases onto cf-theme.css tokens. /profile carries .cf-themable, so a
     literal here would be right in one theme and wrong in the other. */
  --pf-surface:var(--bg2);
  --pf-surface-2:var(--bg3);
  --pf-line:var(--border2);
  --pf-line-soft:color-mix(in srgb,var(--border2) 60%,transparent);
  --pf-gold:var(--accent);
  --pf-copy:var(--text);
  --pf-muted:var(--muted);
  background:var(--bg);
}
.oa-profile-v2 #app{min-height:100dvh}
.oa-profile-v2 .pf-main{width:100%;max-width:820px;padding:16px 22px 96px;background:transparent}

.oa-profile-v2 .pf-cover{position:relative;height:218px;overflow:hidden;border:1px solid var(--pf-line);border-radius:22px;background:linear-gradient(130deg,var(--bg3) 0%,var(--bg2) 55%,var(--bg4) 100%);box-shadow:var(--shadow-card)}
.oa-profile-v2 .pf-cover::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;background:linear-gradient(180deg,color-mix(in srgb,var(--bg) 4%,transparent) 45%,color-mix(in srgb,var(--bg) 36%,transparent) 100%)}
.oa-profile-v2 .pf-cover-fallback{position:absolute;inset:0;z-index:0;overflow:hidden;background:radial-gradient(circle at 74% 18%,rgba(var(--accent-rgb),.18),transparent 26%),linear-gradient(125deg,var(--bg3),var(--bg2) 52%,var(--bg4))}
.oa-profile-v2 .pf-cover-fallback::before{content:"CARTEL_FAMILY";position:absolute;left:42px;top:50%;transform:translateY(-50%);font:700 clamp(22px,4vw,38px)/1 'JetBrains Mono',monospace;letter-spacing:.22em;color:rgba(var(--accent-rgb),.13)}
.oa-profile-v2 .pf-cover-orb{position:absolute;border-radius:50%;filter:blur(2px);opacity:.55}
.oa-profile-v2 .pf-cover-orb-a{width:170px;height:170px;right:8%;top:-70px;background:radial-gradient(circle,rgba(var(--accent-rgb),.28),transparent 70%)}
.oa-profile-v2 .pf-cover-orb-b{width:210px;height:210px;left:18%;bottom:-170px;background:radial-gradient(circle,color-mix(in srgb,var(--green) 16%,transparent),transparent 70%)}
.oa-profile-v2 .pf-cover-img{position:absolute;inset:0;z-index:1;width:100%;height:100%;display:block;object-fit:cover;object-position:center}
.oa-profile-v2 .pf-cover-edit-wrap{top:14px;right:14px;z-index:4}
.oa-profile-v2 .pf-cover-edit-btn,.oa-profile-v2 .pf-cover-view-btn{width:38px;height:38px;padding:0;border:1px solid var(--border2);border-radius:11px;background:color-mix(in srgb,var(--bg) 72%,transparent);color:var(--text);backdrop-filter:blur(12px);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:.16s ease}
.oa-profile-v2 .pf-cover-edit-btn:hover,.oa-profile-v2 .pf-cover-view-btn:hover{border-color:rgba(var(--accent-rgb),.65);background:color-mix(in srgb,var(--bg) 88%,transparent);color:var(--pf-gold);opacity:1}
.oa-profile-v2 .pf-cover-view-btn{position:absolute;right:62px;top:14px;z-index:4}
.oa-profile-v2 .pf-cover-menu{top:46px;border-color:var(--pf-line);border-radius:12px;background:var(--bg2);box-shadow:var(--shadow-card);backdrop-filter:blur(14px)}
.oa-profile-v2 .pf-cover-msg{right:14px;bottom:12px;z-index:4}
.oa-profile-v2 .pf-avatar-wrap{position:absolute;left:26px;bottom:-46px;z-index:5;transform:none}
.oa-profile-v2 .pf-avatar-img,.oa-profile-v2 .pf-avatar-fallback{width:92px;height:92px;border:4px solid var(--bg);box-shadow:0 0 0 1px var(--pf-line),var(--shadow-card)}
.oa-profile-v2 .pf-avatar-fallback{background:linear-gradient(145deg,var(--bg4),var(--bg3));font-size:28px}
.oa-profile-v2 .pf-avatar-edit-badge{right:-2px;bottom:0;width:29px;height:29px;padding:0;border:3px solid var(--bg);background:var(--pf-gold);box-shadow:var(--shadow-card)}
.oa-profile-v2 .pf-avatar-msg{top:auto;bottom:-31px;left:0}

.oa-profile-v2 .pf-identity{max-width:none;padding:0 6px;text-align:left}
.oa-profile-v2 .pf-name-row{gap:9px;margin-bottom:5px;justify-content:flex-start}
.oa-profile-v2 .pf-display-name{margin:0;font-size:28px;line-height:1.15;letter-spacing:-.035em}
.oa-profile-v2 .pf-verified{width:21px;height:21px;box-shadow:0 0 0 3px rgba(var(--accent-rgb),.08)}
.oa-profile-v2 .pf-meta-row{gap:9px;margin-bottom:11px;justify-content:flex-start}
.oa-profile-v2 .pf-handle-tag{font-size:13px;color:var(--muted)}
.oa-profile-v2 .pf-joined-tag{font-size:12px;color:var(--muted)}
.oa-profile-v2 .pf-meta-sep{color:var(--muted)}
.oa-profile-v2 .pf-follows-you{padding:4px 9px;border:1px solid var(--pf-line);border-radius:999px;background:var(--pf-surface-2);color:var(--muted);font-size:10px}
.oa-profile-v2 .pf-bio-text{margin:0 0 14px;max-width:610px;color:var(--text);font-size:14px;line-height:1.55}
.oa-profile-v2 .pf-action-row{display:flex;gap:8px;margin:0 0 18px;flex-wrap:wrap}
.oa-profile-v2 .pf-btn-primary,.oa-profile-v2 .pf-btn-secondary,.oa-profile-v2 .pf-btn-tip,.oa-profile-v2 .pf-btn-icon{min-height:42px;border-radius:11px;font-family:inherit;transition:.16s ease}
.oa-profile-v2 .pf-btn-primary{padding:9px 18px;border:1px solid rgba(var(--accent-rgb),.52);background:rgba(var(--accent-rgb),.08);color:var(--pf-gold)}
.oa-profile-v2 .pf-btn-primary[data-following="false"]{background:var(--pf-gold);color:var(--m3-on-primary);border-color:var(--pf-gold)}
.oa-profile-v2 .pf-btn-primary:hover{border-color:var(--pf-gold);opacity:1;transform:translateY(-1px)}
.oa-profile-v2 .pf-btn-secondary{padding:9px 18px;background:var(--pf-surface);border-color:var(--pf-line);color:var(--pf-copy)}
.oa-profile-v2 .pf-btn-icon{width:42px;padding:0;background:var(--pf-surface);border-color:var(--pf-line);color:var(--muted)}

.oa-profile-v2 .pf-follow-row{display:grid;grid-template-columns:repeat(3,1fr);gap:0;margin:0 6px 16px;padding:0;border-block:1px solid var(--pf-line-soft)}
.oa-profile-v2 .pf-follow-item{appearance:none;display:flex;align-items:baseline;justify-content:center;gap:6px;min-width:0;padding:15px 8px;border:0;border-right:1px solid var(--pf-line-soft);background:transparent;color:inherit;cursor:default;font-family:inherit}
.oa-profile-v2 button.pf-follow-item{cursor:pointer}
.oa-profile-v2 .pf-follow-item:last-child{border-right:0}
.oa-profile-v2 .pf-follow-count{font-size:15px;color:var(--pf-copy)}
.oa-profile-v2 .pf-follow-label{font-size:12px;color:var(--muted)}

.oa-profile-v2 .pf-content{max-width:none;padding:0 6px 58px}
.oa-profile-v2 .pf-wallet-row{min-height:48px;margin-bottom:12px;padding:9px 12px;border-color:var(--pf-line);border-radius:12px;background:var(--pf-surface);gap:10px}
.oa-profile-v2 .pf-wallet-label{color:var(--muted);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.1em}
.oa-profile-v2 .pf-wallet-addr{font-size:11px;color:var(--muted)}
.oa-profile-v2 .pf-copy-btn{width:34px;height:34px;border-radius:8px;display:flex;align-items:center;justify-content:center;background:var(--bg3);color:var(--muted)}
.oa-profile-v2 .pf-private-row{color:var(--muted);font-size:12px}

.oa-profile-v2 .pf-tiles{display:grid;grid-template-columns:repeat(4,1fr);gap:0;margin-bottom:16px;overflow:hidden;border:1px solid var(--pf-line);border-radius:16px;background:var(--pf-surface);box-shadow:var(--shadow-card)}
.oa-profile-v2 .pf-tile{min-width:0;padding:16px 17px;border:0;border-right:1px solid var(--pf-line-soft);border-radius:0;background:transparent;gap:5px}
.oa-profile-v2 .pf-tile:last-child{border-right:0}
.oa-profile-v2 .pf-tile-lbl{font-size:10px;color:var(--muted);letter-spacing:.12em}
.oa-profile-v2 .pf-tile-val{font-size:22px;letter-spacing:-.04em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.oa-profile-v2 .pf-tile-sub{font-size:10px;color:var(--muted)}

.oa-profile-v2 .pf-tabs{display:grid;grid-template-columns:repeat(3,1fr);border-bottom:1px solid var(--pf-line);margin:0}
.oa-profile-v2 .pf-tab{position:relative;min-height:46px;border:0;background:transparent;color:var(--muted);font:600 13px/1 'Geist',system-ui,sans-serif;cursor:pointer}
.oa-profile-v2 .pf-tab::after{content:"";position:absolute;left:24%;right:24%;bottom:-1px;height:2px;border-radius:2px 2px 0 0;background:transparent}
.oa-profile-v2 .pf-tab.active{color:var(--pf-copy)}
.oa-profile-v2 .pf-tab.active::after{background:var(--pf-gold)}
.oa-profile-v2 .pf-tab-panel{display:none;padding-top:12px}
.oa-profile-v2 .pf-tab-panel.active{display:block}
.oa-profile-v2 .pf-tab-panel[hidden]{display:none}
.oa-profile-v2 .pf-posts,.oa-profile-v2 .pf-trades,.oa-profile-v2 .pf-calls{gap:8px;margin:0}
.oa-profile-v2 .pf-post,.oa-profile-v2 .pf-trade-row,.oa-profile-v2 .pf-call-row{border-color:var(--pf-line);background:var(--pf-surface);border-radius:13px}
.oa-profile-v2 .pf-empty{min-height:134px;padding:26px 20px;border:1px solid var(--pf-line-soft);border-radius:14px;background:linear-gradient(180deg,var(--bg2),var(--bg));display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;color:var(--muted)}
.oa-profile-v2 .pf-empty-icon{display:flex;margin-bottom:5px;color:var(--muted)}
.oa-profile-v2 .pf-empty strong{font-size:13px;color:var(--text);font-weight:600}
.oa-profile-v2 .pf-empty>span:last-child{font-size:11px}

@media (max-width:767px){
  .oa-profile-v2 .pf-main{padding:10px 14px calc(126px + env(safe-area-inset-bottom))}
  .oa-profile-v2 .pf-cover{height:164px;border-radius:18px}
  .oa-profile-v2 .pf-cover-fallback::before{left:22px;font-size:20px;letter-spacing:.16em}
  .oa-profile-v2 .pf-cover-edit-wrap{top:10px;right:10px}
  .oa-profile-v2 .pf-cover-edit-btn,.oa-profile-v2 .pf-cover-view-btn{width:36px;height:36px;border-radius:10px}
  .oa-profile-v2 .pf-cover-view-btn{top:10px;right:54px}
  .oa-profile-v2 .pf-avatar-wrap{left:18px;bottom:-40px}
  .oa-profile-v2 .pf-avatar-img,.oa-profile-v2 .pf-avatar-fallback{width:80px;height:80px;border-width:3px;font-size:24px}
  .oa-profile-v2 .pf-avatar-edit-badge{width:27px;height:27px}
  .oa-profile-v2 .pf-identity{padding:0 4px}
  .oa-profile-v2 .pf-display-name{font-size:24px}
  .oa-profile-v2 .pf-meta-row{row-gap:6px}
  .oa-profile-v2 .pf-action-row{width:100%}
  .oa-profile-v2 .pf-btn-primary,.oa-profile-v2 .pf-btn-secondary,.oa-profile-v2 .pf-btn-tip{padding-inline:14px;flex:1 1 132px;justify-content:center;min-width:0}
  .oa-profile-v2 .pf-btn-icon{flex:0 0 42px}
  .oa-profile-v2 .pf-follow-row{margin-inline:4px}
  .oa-profile-v2 .pf-follow-item{padding:13px 4px;flex-direction:column;align-items:center;gap:1px}
  .oa-profile-v2 .pf-follow-count{font-size:15px}
  .oa-profile-v2 .pf-content{padding-inline:4px}
  .oa-profile-v2 .pf-wallet-label{display:none}
  .oa-profile-v2 .pf-wallet-addr{font-size:10.5px}
  .oa-profile-v2 .pf-tiles{grid-template-columns:repeat(4,minmax(0,1fr));border-radius:14px}
  .oa-profile-v2 .pf-tile{padding:14px 9px;align-items:flex-start}
  .oa-profile-v2 .pf-tile-lbl{font-size:9px;letter-spacing:.07em}
  .oa-profile-v2 .pf-tile-val{font-size:18px}
  .oa-profile-v2 .pf-tile-sub{display:none}
  .oa-profile-v2 .pf-trade-row,.oa-profile-v2 .pf-call-row{gap:8px;padding:10px}
  .oa-profile-v2 .pf-trade-time,.oa-profile-v2 .pf-call-prices{display:none}
}

@media (max-width:380px){
  .oa-profile-v2 .pf-tab{font-size:10.5px;letter-spacing:-.01em}
  .oa-profile-v2 .pf-main{padding-inline:10px}
  .oa-profile-v2 .pf-btn-primary,.oa-profile-v2 .pf-btn-secondary,.oa-profile-v2 .pf-btn-tip{font-size:12px;padding-inline:10px;flex-basis:118px}
  .oa-profile-v2 .pf-tile{padding-inline:7px}
  .oa-profile-v2 .pf-tile-val{font-size:16px}
}

/* ── TRADER CARD ─────────────────────────────────────────────────────────
   The approved "Trader Card" direction: the profile as the thing that gets
   screenshotted and shared, not a report. One hero figure over a live curve
   that IS the card's background, the chain split, Copy, and the social proof
   directly under it.

   Tokens only. --accent is a FILL; a positive number set in it renders 4.25:1
   on the light --bg, below AA, which is why --green exists and is used for
   every figure that is text. */
.oa-profile-v2 .tc-card{position:relative;overflow:hidden;margin:0 6px 14px;border:1px solid var(--pf-line);border-radius:22px;background:var(--pf-surface);box-shadow:var(--shadow-card)}
.oa-profile-v2 .tc-card .pf-cover{height:118px;border:0;border-radius:0;box-shadow:none}
/* The strip is far wider than it is tall, and the default banner is a 520x620
   portrait. Centred, `cover` crops out a slice of the mascot's middle; from
   the top it reads as a header. */
.oa-profile-v2 .tc-card .pf-cover-img{object-position:50% 14%}
.oa-profile-v2 .tc-card .pf-cover-fallback::before{left:26px;font-size:clamp(18px,3vw,26px)}

/* The curve is the card background: one object in a screenshot rather than a
   chart panel bolted under a header. pointer-events stay off so it cannot
   swallow a tap meant for Copy. */
.oa-profile-v2 .tc-curve{position:absolute;left:0;right:0;bottom:0;height:58%;z-index:0;opacity:.42;pointer-events:none}
.oa-profile-v2 .tc-curve .cf-chart-svg{height:100%}
/* CFCharts draws horizontal guides; behind a card they read as an artefact.
   The crosshair rule is the dashed one, and it is never shown here anyway. */
.oa-profile-v2 .tc-curve svg > line:not([stroke-dasharray]){display:none}
.oa-profile-v2 .tc-curve .cf-chart-tip{display:none}

.oa-profile-v2 .tc-body{position:relative;z-index:1;padding:16px 20px 20px}
.oa-profile-v2 .tc-idrow{display:flex;align-items:flex-start;gap:14px}
.oa-profile-v2 .tc-card .pf-avatar-wrap{position:relative;left:auto;bottom:auto;transform:none;z-index:auto;flex:0 0 auto}
.oa-profile-v2 .tc-card .pf-avatar-img,.oa-profile-v2 .tc-card .pf-avatar-fallback{width:58px;height:58px;border-width:2px;font-size:19px}
.oa-profile-v2 .tc-card .pf-avatar-edit-badge{width:24px;height:24px;border-width:2px}
.oa-profile-v2 .tc-card .pf-avatar-msg{top:auto;bottom:-26px;left:0}
.oa-profile-v2 .tc-card .pf-identity{flex:1 1 auto;min-width:0;padding:0}
.oa-profile-v2 .tc-card .pf-display-name{font-size:20px;letter-spacing:-.02em}
.oa-profile-v2 .tc-card .pf-meta-row{margin-bottom:0}
.oa-profile-v2 .tc-card .pf-bio-text{margin:8px 0 0;font-size:13px}
.oa-profile-v2 .tc-mark{flex:0 0 auto;font:700 9.5px/1.5 'JetBrains Mono',monospace;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);text-align:right}
.oa-profile-v2 .tc-mark b{display:block;color:var(--green);font-weight:800}

.oa-profile-v2 .tc-lead{margin:20px 0 7px;font:500 10.5px/1 'JetBrains Mono',monospace;letter-spacing:.18em;text-transform:uppercase;color:var(--muted)}
.oa-profile-v2 .tc-lead span{opacity:.72}
.oa-profile-v2 .tc-big{margin:0;font-family:'JetBrains Mono',monospace;font-weight:700;font-size:clamp(36px,8.4vw,58px);line-height:1;letter-spacing:-.035em;color:var(--green);font-variant-numeric:tabular-nums}
.oa-profile-v2 .tc-big.down{color:var(--red)}
/* An empty profile gets a sentence, never "$0.00" -- a fabricated zero is
   indistinguishable from a real, unimpressive result. */
.oa-profile-v2 .tc-big-quiet{font-family:'Geist',system-ui,sans-serif;font-size:clamp(19px,4.2vw,26px);font-weight:600;letter-spacing:-.02em;color:var(--muted)}
.oa-profile-v2 .tc-sub{margin:11px 0 0;max-width:52ch;font-size:13px;line-height:1.5;color:var(--muted)}
.oa-profile-v2 .tc-sub b{color:var(--text);font-weight:700}

.oa-profile-v2 .tc-pills{display:flex;flex-wrap:wrap;gap:7px;margin-top:16px}
.oa-profile-v2 .tc-pill{padding:6px 11px;border:1px solid var(--pf-line);border-radius:999px;background:var(--bg3);color:var(--muted);font:500 11px/1 'JetBrains Mono',monospace}
.oa-profile-v2 .tc-pill b{color:var(--text);font-weight:700}

.oa-profile-v2 .tc-card .pf-action-row{margin:18px 0 0}
.oa-profile-v2 .tc-btn-copy{display:inline-flex;align-items:center;justify-content:center;gap:7px;min-height:44px;padding:10px 20px;border:1px solid var(--accent);border-radius:11px;background:var(--accent-cta);color:var(--m3-on-primary);font:700 13.5px/1 'Geist',system-ui,sans-serif;cursor:pointer;transition:.16s ease}
.oa-profile-v2 .tc-btn-copy:hover{transform:translateY(-1px);box-shadow:0 0 0 3px rgba(var(--accent-rgb),.14)}
.oa-profile-v2 .tc-btn-copy[data-copying="true"]{background:rgba(var(--accent-rgb),.10);color:var(--green)}
.oa-profile-v2 .tc-follow[data-following="true"]{border-color:rgba(var(--accent-rgb),.5);color:var(--green)}

.oa-profile-v2 .tc-social{display:flex;align-items:center;gap:11px;margin-top:17px;padding-top:15px;border-top:1px solid var(--pf-line-soft)}
.oa-profile-v2 .tc-social-mark{flex:0 0 30px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:rgba(var(--accent-rgb),.12);color:var(--green)}
.oa-profile-v2 .tc-social p{margin:0;font-size:12.5px;line-height:1.45;color:var(--muted)}
.oa-profile-v2 .tc-social b{color:var(--text);font-weight:700}

/* ── BY MONTH ─────────────────────────────────────────────────────────── */
.oa-profile-v2 .tc-months{margin:0 6px 16px;padding:16px 18px;border:1px solid var(--pf-line);border-radius:18px;background:var(--pf-surface);box-shadow:var(--shadow-card)}
.oa-profile-v2 .tc-months-hd h2{margin:0 0 3px;font-size:13.5px;font-weight:700;color:var(--text)}
.oa-profile-v2 .tc-months-hd p{margin:0 0 13px;font-size:12px;line-height:1.45;color:var(--muted)}
.oa-profile-v2 .tc-bars{position:relative;min-height:132px}
.oa-profile-v2 .tc-bar-labels{display:flex;margin-top:7px}
.oa-profile-v2 .tc-bar-labels span{flex:1 1 0;min-width:0;text-align:center;font:500 10px/1 'JetBrains Mono',monospace;color:var(--muted)}
.oa-profile-v2 .tc-bar-labels:empty{display:none}

/* ── COPY SHEET ───────────────────────────────────────────────────────── */
.oa-profile-v2 .tc-sheet-back{display:none;position:fixed;inset:0;z-index:10040;padding:18px;background:var(--scrim);backdrop-filter:blur(7px);align-items:center;justify-content:center}
.oa-profile-v2 .tc-sheet-back.open{display:flex}
.oa-profile-v2 .tc-sheet{width:min(440px,100%);max-height:94vh;overflow-y:auto;padding:20px;border:1px solid var(--pf-line);border-radius:22px;background:var(--bg2);box-shadow:var(--shadow-card);transition:transform .2s cubic-bezier(.2,.8,.2,1)}
.oa-profile-v2 .tc-sheet-handle{width:42px;height:4px;margin:0 auto 14px;border-radius:var(--r-pill);background:var(--border2)}
.oa-profile-v2 .tc-sheet-hd{display:flex;align-items:center;justify-content:space-between;gap:12px}
.oa-profile-v2 .tc-sheet-hd h2{margin:0;font-size:19px;font-weight:700;letter-spacing:-.02em;color:var(--text)}
.oa-profile-v2 .tc-sheet-close{border:0;background:none;color:var(--muted);font-size:25px;line-height:1;padding:2px 6px;cursor:pointer}
.oa-profile-v2 .tc-sheet-lead{margin:10px 0 18px;font-size:13px;line-height:1.5;color:var(--muted)}
.oa-profile-v2 .tc-sheet-label{display:block;margin:0 0 8px;font-size:13px;font-weight:600;color:var(--text)}
.oa-profile-v2 .tc-amount-wrap{display:flex;align-items:center;gap:10px;padding:0 16px;border:1px solid var(--pf-line);border-radius:14px;background:var(--bg3)}
.oa-profile-v2 .tc-amount-wrap:focus-within{border-color:rgba(var(--accent-rgb),.65)}
.oa-profile-v2 .tc-amount{flex:1 1 auto;min-width:0;padding:13px 0;border:0;background:none;outline:none;color:var(--text);font:600 28px/1 'JetBrains Mono',monospace}
.oa-profile-v2 .tc-amount::-webkit-outer-spin-button,.oa-profile-v2 .tc-amount::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.oa-profile-v2 .tc-amount[type=number]{-moz-appearance:textfield}
.oa-profile-v2 .tc-amount-sym{font-size:13px;font-weight:600;color:var(--muted)}
.oa-profile-v2 .tc-presets{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;margin-top:11px}
.oa-profile-v2 .tc-preset{min-height:42px;padding:11px 4px;border:1px solid var(--pf-line);border-radius:12px;background:var(--bg3);color:var(--text);font:700 12.5px/1 'Geist',system-ui,sans-serif;cursor:pointer}
.oa-profile-v2 .tc-preset:hover{border-color:rgba(var(--accent-rgb),.5)}
.oa-profile-v2 .tc-preset.active{border-color:var(--accent);background:var(--accent-cta);color:var(--m3-on-primary)}
.oa-profile-v2 .tc-sheet-note{margin:13px 0 0;font-size:12px;line-height:1.5;color:var(--muted)}
.oa-profile-v2 .tc-sheet-submit{width:100%;min-height:50px;margin-top:17px;border:0;border-radius:14px;background:var(--accent-cta);color:var(--m3-on-primary);font:800 15px/1 'Geist',system-ui,sans-serif;cursor:pointer}
.oa-profile-v2 .tc-sheet-submit:disabled{opacity:.5;cursor:not-allowed}
.oa-profile-v2 .tc-sheet-submit.danger{background:var(--red);color:var(--bg)}
.oa-profile-v2 .tc-sheet-msg{min-height:19px;margin-top:11px;text-align:center;font-size:12.5px;color:var(--muted)}
.oa-profile-v2 .tc-sheet-msg.err{color:var(--red)}
.oa-profile-v2 .tc-sheet-msg.ok{color:var(--green)}

@media (max-width:767px){
  .oa-profile-v2 .tc-card{margin-inline:4px;border-radius:18px}
  .oa-profile-v2 .tc-card .pf-cover{height:96px}
  .oa-profile-v2 .tc-body{padding:14px 15px 17px}
  .oa-profile-v2 .tc-card .pf-avatar-img,.oa-profile-v2 .tc-card .pf-avatar-fallback{width:50px;height:50px;font-size:17px}
  .oa-profile-v2 .tc-card .pf-display-name{font-size:18px}
  .oa-profile-v2 .tc-mark{display:none}
  .oa-profile-v2 .tc-btn-copy{flex:1 1 100%}
  .oa-profile-v2 .tc-months{margin-inline:4px;padding:14px 15px}
  .oa-profile-v2 .tc-sheet-back{padding:0;align-items:flex-end}
  .oa-profile-v2 .tc-sheet{width:100%;border-radius:22px 22px 0 0;padding:16px 16px calc(20px + env(safe-area-inset-bottom,0px))}
}

@media (prefers-reduced-motion:reduce){
  .oa-profile-v2 .tc-btn-copy{transition:none}
  .oa-profile-v2 .tc-btn-copy:hover{transform:none}
  /* The swipe-to-dismiss drag still tracks the finger; only the snap-back
     animation goes, so nothing moves that the user did not move. */
  .oa-profile-v2 .tc-sheet{transition:none}
}

/* ── PROFILE COMMENTS ────────────────────────────────────────────────────
   Placed as a fourth sibling in the existing tab strip rather than a slab
   under it. The strip is already "what this person has been doing"; what
   people say TO them belongs in the same rail, and a permanent block under
   the strip would push Posts/Trades/Calls below the fold on a phone for
   content that is usually empty.

   The strip is now grid-auto-flow so a fourth tab needs no column count to
   be kept in sync with the markup.

   Tokens only. --accent is the brand violet and carries the one primary
   action; --green/--red stay reserved for gain/loss and status, and --red
   appears here only on the destructive control, which is what it is for. */
.oa-profile-v2 .pf-tabs{grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:1fr}
/* The label and its count are one line. Left to wrap, a four-tab strip on a
   360px phone drops the badge onto a second row and the tab grows taller
   than its neighbours. */
.oa-profile-v2 .pf-tab{white-space:nowrap}
.oa-profile-v2 .pf-tab-count{display:inline-block;margin-left:5px;padding:1px 5px;border-radius:var(--r-pill);background:var(--bg4);color:var(--muted);font:700 10px/1.5 'JetBrains Mono',monospace;vertical-align:1px}
.oa-profile-v2 .pf-tab-count:empty{display:none}
.oa-profile-v2 .pf-tab.active .pf-tab-count{background:rgba(var(--accent-rgb),.16);color:var(--accent-ink)}

/* The tint carries the per-author identity in the wash and the ring; the
   initials stay on --text so they hold contrast in both themes. A hue set
   as text is legible on one ground and grey mush on the other. */
.oa-profile-v2 .pfc-av{flex:0 0 34px;width:34px;height:34px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:color-mix(in srgb,var(--pfc-tint,var(--accent)) 18%,var(--bg3));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--pfc-tint,var(--accent)) 42%,transparent);color:var(--text);font:700 12px/1 'JetBrains Mono',monospace;text-decoration:none;letter-spacing:.02em}

/* ── composer ── */
.oa-profile-v2 .pfc-compose{display:flex;gap:11px;margin-bottom:14px;padding:13px;border:1px solid var(--pf-line);border-radius:14px;background:var(--pf-surface)}
.oa-profile-v2 .pfc-compose-body{flex:1 1 auto;min-width:0}
.oa-profile-v2 .pfc-input{width:100%;min-height:52px;max-height:200px;padding:9px 11px;border:1px solid var(--pf-line);border-radius:11px;background:var(--bg3);color:var(--text);font:400 14px/1.5 'Geist',system-ui,sans-serif;resize:vertical;outline:none;transition:border-color .16s ease}
.oa-profile-v2 .pfc-input::placeholder{color:var(--muted)}
.oa-profile-v2 .pfc-input:focus{border-color:rgba(var(--accent-rgb),.65)}
.oa-profile-v2 .pfc-compose-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:9px}
.oa-profile-v2 .pfc-count{font:500 11px/1 'JetBrains Mono',monospace;color:var(--muted);font-variant-numeric:tabular-nums}
.oa-profile-v2 .pfc-count.near{color:var(--text)}
.oa-profile-v2 .pfc-post{min-height:38px;padding:9px 20px;border:1px solid var(--accent);border-radius:11px;background:var(--accent-cta);color:var(--m3-on-primary);font:700 13px/1 'Geist',system-ui,sans-serif;cursor:pointer;transition:opacity .16s ease,box-shadow .16s ease}
.oa-profile-v2 .pfc-post:hover:not(:disabled){box-shadow:0 0 0 3px rgba(var(--accent-rgb),.14)}
.oa-profile-v2 .pfc-post:disabled{opacity:.45;cursor:not-allowed}
.oa-profile-v2 .pfc-msg{margin:8px 0 0;font-size:12.5px;line-height:1.45;color:var(--muted)}
.oa-profile-v2 .pfc-msg:empty{display:none}
.oa-profile-v2 .pfc-msg.err{color:var(--red)}
.oa-profile-v2 .pfc-msg.ok{color:var(--green)}

/* ── signed-out / not-following prompt. Honest, and never a dead input. ── */
.oa-profile-v2 .pfc-gate{display:flex;align-items:flex-start;gap:10px;margin-bottom:14px;padding:13px 15px;border:1px dashed var(--pf-line);border-radius:14px;background:var(--bg2);color:var(--muted)}
.oa-profile-v2 .pfc-gate svg{flex:0 0 auto;margin-top:1px;color:var(--muted)}
.oa-profile-v2 .pfc-gate p{margin:0;font-size:13px;line-height:1.5}
.oa-profile-v2 .pfc-gate a{color:var(--accent-ink);font-weight:600;text-decoration:none;border-bottom:1px solid rgba(var(--accent-rgb),.4)}
.oa-profile-v2 .pfc-gate a:hover{border-bottom-color:var(--accent)}

/* ── list ── */
.oa-profile-v2 .pfc-list{display:flex;flex-direction:column;gap:8px}
.oa-profile-v2 .pfc-item{display:flex;gap:11px;padding:12px 13px;border:1px solid var(--pf-line);border-radius:13px;background:var(--pf-surface)}
.oa-profile-v2 .pfc-item-busy{opacity:.55}
.oa-profile-v2 .pfc-item-body{flex:1 1 auto;min-width:0}
.oa-profile-v2 .pfc-item-hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.oa-profile-v2 .pfc-name{font-size:13px;font-weight:700;color:var(--text);text-decoration:none;overflow-wrap:anywhere}
.oa-profile-v2 a.pfc-name:hover{color:var(--accent-ink)}
.oa-profile-v2 .pfc-time{font:500 11px/1 'JetBrains Mono',monospace;color:var(--muted)}
.oa-profile-v2 .pfc-actions{margin-left:auto;display:flex;align-items:center;gap:7px}
.oa-profile-v2 .pfc-del{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:1px solid transparent;border-radius:8px;background:none;color:var(--muted);cursor:pointer;transition:color .16s ease,border-color .16s ease}
.oa-profile-v2 .pfc-del:hover{color:var(--red);border-color:color-mix(in srgb,var(--red) 45%,transparent)}
.oa-profile-v2 .pfc-text{margin:5px 0 0;font-size:14px;line-height:1.55;color:var(--text);overflow-wrap:anywhere;white-space:pre-wrap}

/* ── inline delete confirmation (no browser dialog, no accidental loss) ── */
.oa-profile-v2 .pfc-confirm{display:inline-flex;align-items:center;gap:6px}
.oa-profile-v2 .pfc-confirm-q{font-size:11.5px;color:var(--muted)}
.oa-profile-v2 .pfc-confirm-yes,.oa-profile-v2 .pfc-confirm-no{min-height:26px;padding:4px 10px;border-radius:8px;border:1px solid var(--pf-line);background:var(--bg3);color:var(--text);font:700 11.5px/1 'Geist',system-ui,sans-serif;cursor:pointer}
.oa-profile-v2 .pfc-confirm-yes{border-color:color-mix(in srgb,var(--red) 55%,transparent);color:var(--red)}
.oa-profile-v2 .pfc-confirm-yes:disabled,.oa-profile-v2 .pfc-confirm-no:disabled{opacity:.5;cursor:default}
.oa-profile-v2 .pfc-confirm-err{font-size:11.5px;color:var(--red)}

/* ── empty / failure states ── */
.oa-profile-v2 .pfc-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;min-height:134px;padding:26px 20px;border:1px solid var(--pf-line-soft);border-radius:14px;background:linear-gradient(180deg,var(--bg2),var(--bg));color:var(--muted);text-align:center}
.oa-profile-v2 .pfc-state-icon{display:flex;margin-bottom:5px;color:var(--muted)}
.oa-profile-v2 .pfc-state strong{font-size:13px;font-weight:600;color:var(--text)}
.oa-profile-v2 .pfc-state span:not(.pfc-state-icon){font-size:11.5px;line-height:1.5;max-width:34ch}
.oa-profile-v2 .pfc-err .pfc-state-icon{color:var(--red)}
.oa-profile-v2 .pfc-retry{min-height:36px;margin-top:9px;padding:8px 17px;border:1px solid var(--pf-line);border-radius:10px;background:var(--bg3);color:var(--text);font:700 12.5px/1 'Geist',system-ui,sans-serif;cursor:pointer;transition:border-color .16s ease}
.oa-profile-v2 .pfc-retry:hover{border-color:rgba(var(--accent-rgb),.6)}

/* ── loading. The resting state of every skeleton part is a VISIBLE block;
   the shimmer only moves a highlight across it. Nothing is parked at
   opacity:0 waiting for an animation that a background tab, a thumbnail or
   a print may never run — see the long note in static/app-ux.css. ── */
.oa-profile-v2 .pfc-skel-wrap{display:flex;flex-direction:column;gap:8px}
.oa-profile-v2 .pfc-skel{display:flex;gap:11px;padding:12px 13px;border:1px solid var(--pf-line-soft);border-radius:13px;background:var(--pf-surface)}
.oa-profile-v2 .pfc-skel-av{flex:0 0 34px;width:34px;height:34px;border-radius:50%;background:var(--bg4)}
.oa-profile-v2 .pfc-skel-lines{flex:1 1 auto;display:flex;flex-direction:column;gap:8px;padding-top:4px}
.oa-profile-v2 .pfc-skel-line{display:block;height:10px;border-radius:5px;background:var(--bg4)}
.oa-profile-v2 .pfc-skel-line-s{width:38%}
.oa-profile-v2 .pfc-skel-av,.oa-profile-v2 .pfc-skel-line{background-image:linear-gradient(90deg,transparent,color-mix(in srgb,var(--text) 9%,transparent),transparent);background-size:220% 100%;background-repeat:no-repeat;animation:pfc-shimmer 1.25s linear infinite}
@keyframes pfc-shimmer{from{background-position:-110% 0}to{background-position:110% 0}}

@media (max-width:767px){
  .oa-profile-v2 .pf-tab{font-size:11.5px}
  .oa-profile-v2 .pf-tab-count{margin-left:4px;padding:1px 4px;font-size:9px}
  .oa-profile-v2 .pfc-compose{padding:11px;gap:9px}
  .oa-profile-v2 .pfc-av{flex-basis:30px;width:30px;height:30px;font-size:11px}
  .oa-profile-v2 .pfc-item{padding:11px;gap:9px}
  .oa-profile-v2 .pfc-post{flex:0 0 auto;padding-inline:16px}
}

@media (prefers-reduced-motion:reduce){
  .oa-profile-v2 .pfc-skel-av,.oa-profile-v2 .pfc-skel-line{animation:none;background-image:none}
  .oa-profile-v2 .pfc-input,.oa-profile-v2 .pfc-post,.oa-profile-v2 .pfc-del,.oa-profile-v2 .pfc-retry{transition:none}
}

/* The "$" that sits before the copy amount. The unit used to be SOL and sat
   only on the right; dollars read wrong without the symbol in front. */
.tc-amount-pre{ margin-right:2px; opacity:.75; }


/* ---- static/cf-trader-profile.css ---- */
/* Cartel Family — someone else's profile (the design's CFPeople "trader" view).
 *
 * Measured from the design source's inline styles: a 1100px column (24/28
 * padding; 12/16/24 on a phone), a header card (r18, pad 18) with a 72px
 * avatar and 44px actions, badges as 28px accent pills, then a 1.6fr/1fr grid:
 * Track record (200px area, four stat tiles) over the Open / History /
 * Achievements card, with Profile comments on the right. Tokens only.
 */
.oa-profile-v2 .pf-main.tp-main{max-width:1100px;margin:0;padding:16px 24px 80px}
.tp-page{display:flex;flex-direction:column;gap:14px;font-family:var(--font-ui);color:var(--ink)}
.tp-page h1,.tp-page h2,.tp-page p{margin:0}

.tp-back{align-self:flex-start;height:36px;padding:0 12px;display:flex;align-items:center;border:0;border-radius:10px;
  background:var(--s2);font:600 13px var(--font-ui);color:var(--ink2);cursor:pointer}
.tp-back:hover{color:var(--ink)}

.tp-head{background:var(--s1);border:1px solid var(--line);border-radius:18px;padding:18px;display:flex;flex-direction:column;gap:14px}
.tp-id-row{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.tp-av{width:72px;height:72px;border-radius:50%;flex:none;position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;
  /* A generated identity disc (seeded fill from script), so its ink is the
     fixed white that clears 4.5:1 on every shade of that palette. */
  background:var(--s2);font:700 24px var(--font-ui);color:#fff}
.tp-av img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;cursor:pointer}
.tp-id{display:flex;flex-direction:column;gap:4px;flex:1;min-width:180px}
.tp-h{font:800 22px/normal var(--font-ui);color:var(--ink);display:flex;align-items:center;gap:8px;flex-wrap:wrap;overflow-wrap:anywhere}
.tp-x{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background:var(--s2);color:var(--ink2)}
.tp-follows-you{font:700 10px var(--font-ui);color:var(--ink2);background:var(--s2);padding:3px 7px;border-radius:var(--r-badge)}
.tp-bio{font:500 13px/normal var(--font-ui);color:var(--ink2)}
/* One row, as drawn: on a narrow column each count wraps inside itself
   ("8.2k" over "followers") rather than the row breaking between counts. */
.tp-counts{display:flex;gap:14px;font:600 12px var(--font-ui);color:var(--ink2)}
.tp-counts b{color:var(--ink);font-weight:bolder}
.tp-counts button{border:0;background:none;padding:0;font:inherit;color:inherit;cursor:pointer}
.tp-counts button:hover b{color:var(--accT)}
.tp-acts{display:flex;gap:8px;flex-wrap:wrap}
.tp-act{height:44px;padding:0 16px;display:flex;align-items:center;justify-content:center;border:0;border-radius:12px;
  background:var(--s2);font:700 14px var(--font-ui);color:var(--ink);cursor:pointer;text-decoration:none;white-space:nowrap;
  transition:filter var(--dur-fast),background var(--dur-fast)}
.tp-act:hover{filter:brightness(1.08)}
.tp-act[data-following="true"]{color:var(--accT)}
.tp-copy{padding:0 20px;font-weight:800;background:var(--acc);color:var(--onAcc)}
.tp-copy[data-copying="true"]{background:var(--upBg);color:var(--up)}
.tp-copy[data-copying="true"] span::before{content:'\2713  '}
.tp-badges{display:flex;gap:6px;flex-wrap:wrap}
.tp-badge{height:28px;padding:0 10px;display:flex;align-items:center;border-radius:14px;background:var(--accBg);font:700 12px var(--font-ui);color:var(--accT)}

.tp-grid{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);gap:14px;align-items:start}
.tp-col{display:flex;flex-direction:column;gap:14px;min-width:0}
.tp-card{background:var(--s1);border:1px solid var(--line);border-radius:16px}

.tp-track{padding:14px;display:flex;flex-direction:column;gap:10px}
.tp-card-hd{display:flex;align-items:center;justify-content:space-between;gap:10px}
.tp-card-hd h2,.tp-comments h2{font:800 16px var(--font-ui);color:var(--ink)}
.tp-ranges{display:flex;gap:4px}
.tp-ranges button{height:30px;min-width:44px;padding:0 10px;border:0;border-radius:15px;cursor:pointer;
  font:700 12px var(--font-ui);background:var(--s2);color:var(--ink2)}
.tp-ranges button.on{background:var(--ink);color:var(--bg)}
.tp-chart{height:200px;position:relative}
.tp-chart .cf-chart-empty{min-height:200px}
.tp-stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.tp-stats div{background:var(--bg);border-radius:10px;padding:8px 10px;display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-width:0}
.tp-stats span{font:600 11px var(--font-ui);color:var(--ink2)}
.tp-stats b{max-width:100%;font:500 14px var(--font-num);font-variant-numeric:tabular-nums;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tp-stats b.up,.tp-fig.up{color:var(--up)}
.tp-stats b.dn,.tp-fig.dn{color:var(--dn)}

.tp-book{overflow:hidden}
.tp-tabs{display:flex;gap:4px;padding:0 12px;border-bottom:1px solid var(--line)}
.tp-tabs button{height:44px;padding:0 10px;border:0;border-bottom:2px solid transparent;margin-bottom:-1px;background:none;cursor:pointer;
  font:700 14px var(--font-ui);color:var(--ink2)}
.tp-tabs button.on{color:var(--ink);border-bottom-color:var(--acc)}
.tp-row{display:flex;align-items:center;gap:10px;padding:10px 16px;border-bottom:1px solid var(--line);min-height:56px}
.tp-panel .tp-row:last-child{border-bottom:0}
/* The Posts tab: the feed's own post cards (cf-posts.css), inset in the book. */
.tp-posts{padding:12px}
.tp-posts .cf-post:last-child{margin-bottom:0}
.tp-letter{width:32px;height:32px;border-radius:50%;background:var(--s2);font:800 11px/32px var(--font-ui);color:var(--accT);text-align:center;flex:none}
.tp-row-id{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0;color:inherit;text-decoration:none}
.tp-sym{font:800 14px var(--font-ui);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tp-sym i{font:700 10px var(--font-ui);font-style:normal;color:var(--ink2)}
.tp-sym i.dn{color:var(--dn)}
.tp-sub{font:500 12px var(--font-num);color:var(--ink2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tp-fig{font:500 13px var(--font-num);font-variant-numeric:tabular-nums;color:var(--ink3);white-space:nowrap}
.tp-buy{height:36px;padding:0 12px;border:0;border-radius:9px;background:var(--acc);font:700 12px var(--font-ui);color:var(--onAcc);cursor:pointer}
.tp-none .tp-sym{color:var(--ink2)}

.tp-comments{padding:14px 16px;display:flex;flex-direction:column;gap:12px}
/* profile-comments.js renders into #pf-panel-comments; restyled here to the
   design's one-line composer and 30px-avatar list. */
.tp-comments .pfc-compose{display:flex;gap:8px;margin:0 0 12px;padding:0;border:0;background:none}
.tp-comments .pfc-compose .pfc-av-me{display:none}
.tp-comments .pfc-compose-body{flex:1;min-width:0;display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.tp-comments .pfc-input{flex:1;min-width:0;height:44px;min-height:44px;max-height:44px;padding:11px 12px;resize:none;overflow:hidden;
  background:var(--bg);border:1px solid var(--line);border-radius:10px;font:500 14px/1.45 var(--font-ui);color:var(--ink)}
.tp-comments .pfc-compose-foot{margin:0;gap:8px}
.tp-comments .pfc-count{display:none}
.tp-comments .pfc-post{height:44px;min-height:44px;padding:0 14px;border:0;border-radius:10px;background:var(--acc);color:var(--onAcc);font:700 13px var(--font-ui)}
.tp-comments .pfc-msg{flex-basis:100%}
.tp-comments .pfc-list{gap:12px}
.tp-comments .pfc-item{padding:0;border:0;background:none;gap:10px}
.tp-comments .pfc-item-hd{gap:4px}
.tp-comments .pfc-av{flex:0 0 30px;width:30px;height:30px;font:700 11px var(--font-ui)}
.tp-comments .pfc-name{font:700 13px var(--font-ui)}
.tp-comments .pfc-time{font:500 11px var(--font-num);color:var(--ink3)}
.tp-comments .pfc-text{font:500 13px/1.45 var(--font-ui);color:var(--body);margin:2px 0 0}
.tp-comments .pfc-gate{margin:0 0 4px;border-radius:10px}

.tp-page button:focus-visible,.tp-page a:focus-visible{outline:2px solid var(--acc);outline-offset:2px}

@media (max-width:1024px){
  .tp-grid{grid-template-columns:1fr}
}
@media (max-width:767px){
  .oa-profile-v2 .pf-main.tp-main{padding:12px 16px calc(96px + env(safe-area-inset-bottom));max-width:none}
}
@media (prefers-reduced-motion:reduce){
  .tp-act{transition:none}
}
@media (max-width:374px){
  .tp-stats{grid-template-columns:repeat(3,minmax(0,1fr))}
}
/* Touch: every control is a 44px target. Pills and small buttons keep the
   design's face -- the extra height is transparent border outside the
   painted background -- and their rows pull in by the same amount. */
@media (pointer:coarse){
  .tp-back{height:44px;border:4px solid transparent;border-left:0;border-right:0;background-clip:padding-box;
    border-radius:10px/14px;margin-top:-4px;margin-bottom:-4px;}
  .tp-ranges{margin-top:-7px;margin-bottom:-7px;}
  .tp-ranges button{height:44px;border:7px solid transparent;border-left:0;border-right:0;background-clip:padding-box;
    border-radius:15px/22px}
  .tp-buy{height:44px;border:4px solid transparent;border-left:0;border-right:0;background-clip:padding-box;
    border-radius:9px/13px;margin-top:-4px;margin-bottom:-4px;}
  .tp-counts button{min-height:44px;margin-top:-14px;margin-bottom:-14px;}
}

/* A very wide screen: the column centres in the room beside the rail
   instead of leaving a dead band down the right. Below 1700 it sits left,
   as the design draws it. */
@media (min-width:1700px){ .oa-profile-v2 .pf-main.tp-main{ margin-left:auto; margin-right:auto; } }
/* A state that repaints with the `background` shorthand resets the clip
   to the border box; it is re-asserted so the 44px target keeps its face. */
@media (pointer:coarse){ .tp-ranges button.on,.tp-copy[data-copying="true"]{ background-clip:padding-box; } }
@media (pointer:coarse){
  .tp-comments .pfc-gate a{display:inline-flex;align-items:center;min-height:44px;margin-top:-13px;margin-bottom:-13px}
  /* A comment's avatar and name are links: 44px targets that keep the
     design's 30px disc and 13px name (transparent border outside the disc;
     an inset ring paints inside the padding box, so it stays on the disc). */
  .tp-comments a.pfc-av{flex-basis:44px;width:44px;height:44px;margin:-7px;border:7px solid transparent;background-clip:padding-box}
  .tp-comments a.pfc-name{display:inline-flex;align-items:center;min-height:44px;margin-top:-14px;margin-bottom:-14px}
}

/* ── Syndicate Noir (2026-10-12): the trader profile, drawn as /design/a/me ──
   The header and cards are glass with the light edge, the actions are the
   Noir pills (Copy molten), the tabs are the ink track with a molten thumb,
   the figure wells are mono. Same markup, ids and handlers. Tokens only. */
.tp-head,.tp-card{position:relative;border:1px solid var(--glass-edge);box-shadow:var(--shadow-2);border-radius:var(--r-lg,20px);
  background:linear-gradient(180deg,rgb(var(--raise) / .66),rgb(var(--raise) / .72) 38%,var(--glass));
  -webkit-backdrop-filter:blur(var(--blur)) saturate(var(--glass-saturate));backdrop-filter:blur(var(--blur)) saturate(var(--glass-saturate))}
.tp-head::before,.tp-card::before{content:'';position:absolute;inset:0;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}
.tp-head{padding:22px}
.tp-back{border-radius:var(--r-pill,999px);border:1px solid var(--glass-edge-hi);background:var(--ink-4);font-family:var(--font-display,var(--font-ui))}
.tp-act{position:relative;overflow:hidden;isolation:isolate;border-radius:var(--r-pill,999px);border:1px solid var(--glass-edge-hi);
  background:var(--ink-4);color:var(--ink);box-shadow:var(--shadow-1);font-family:var(--font-display,var(--font-ui));font-weight:600;
  transition:transform var(--t-med,.28s) var(--ease-spring,ease),box-shadow var(--t-med,.28s),border-color var(--t-med,.28s)}
.tp-act::after{content:'';position:absolute;inset:-2px;z-index:-1;pointer-events:none;transform:translateX(-120%);
  background:linear-gradient(105deg,transparent 30%,rgb(var(--sheen-rgb) / .38) 46%,rgb(var(--sheen-rgb) / .06) 54%,transparent 64%)}
@media (hover:hover){
  .tp-act:hover{filter:none;border-color:rgb(var(--glow) / .45);box-shadow:var(--shadow-2),0 0 0 1px rgb(var(--glow) / .18)}
  .tp-act:hover::after{transform:translateX(120%);transition:transform var(--t-sweep,.76s) var(--ease-out,ease)}
}
.tp-act:active{transform:scale(.95);transition-duration:90ms}
.tp-act:focus-visible{outline:none;box-shadow:var(--focus-ring)}
.tp-act[data-following="true"]{color:var(--accent-text-strong);border-color:rgb(var(--glow) / .45)}
.tp-copy{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)}
.tp-copy[data-copying="true"]{background:var(--up-dim);color:var(--up);border-color:rgb(var(--up-rgb) / .4);box-shadow:none;text-shadow:none}
.tp-card-hd h2,.tp-comments h2{font:600 18px var(--font-display,var(--font-ui));letter-spacing:-.01em}
.tp-stats div{background:var(--well);border:1px solid rgb(var(--tint) / .04);border-radius:var(--r-md,14px);padding:12px}
.tp-stats span{font:600 10px/1.2 var(--font-mono);letter-spacing:.12em;text-transform:uppercase;color:var(--ink3)}
.tp-stats b{font:600 18px var(--font-mono);margin-top:4px}
.tp-stats b.up{text-shadow:0 0 14px rgb(var(--up-rgb) / .3)}
.tp-stats b.dn{text-shadow:0 0 14px rgb(var(--dn-rgb) / .3)}
.tp-tabs{gap:2px;margin:12px 12px 0;padding:3px;border:1px solid var(--glass-edge);border-radius:var(--r-pill,999px);background:var(--ink-2);width:max-content;max-width:calc(100% - 24px);overflow-x:auto;scrollbar-width:none}
.tp-tabs button{height:36px;padding:0 14px;border-bottom:0;margin-bottom:0;border-radius:var(--r-pill,999px);font-family:var(--font-display,var(--font-ui));font-weight:600;
  transition:color var(--t-med,.28s),background var(--t-med,.28s)}
.tp-tabs button.on{background:var(--molten);color:var(--on-molten);box-shadow:0 4px 14px rgb(var(--glow) / .35)}
.tp-badge{border-radius:var(--r-pill,999px);font-family:var(--font-mono);letter-spacing:.08em;text-transform:uppercase}
@media (pointer:coarse),(hover:none),(max-width:1024px){.tp-tabs button{height:44px}}


/* ---- static/cf-pages.css ---- */
/* Cartel Family — Syndicate Noir pieces the people and account pages share
 * (the behaviour is static/cf-pages.js). Every value is a token from
 * cf-theme.css; the components themselves are cf-noir.css.
 *
 *   .cf-noir-in        the Noir entrance: rise 16px + scale .985 + blur 4px
 *                      (added by script, removed on animationend)
 *   .cf-has-vault      an empty line with the engraved vault drawn above it
 *   .cf-page-head      title + right-hand actions, as /design/a/* draws it
 *   .cf-stat-row       the reference's mono figure row (dt caps / dd mono)
 *   .cf-rowlist        a list of person/token rows inside a glass panel
 */
@media (prefers-reduced-motion:no-preference){
  .cf-noir-in{ animation:cf-noir-rise var(--t-enter,600ms) var(--ease-out,cubic-bezier(.2,.75,.3,1)) both; }
  @keyframes cf-noir-rise{ from{ opacity:0; transform:translateY(16px) scale(.985); filter:blur(4px); } to{ opacity:1; transform:none; filter:none; } }
}

/* the vault above an empty line */
.cf-has-vault{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px; text-align:center; }
.cf-has-vault > .cf-vault{ width:54px; height:54px; flex:none; opacity:.9; }
.cf-noir-empty > span{ max-width:44ch; color:var(--ink3); font:500 12.5px/1.5 var(--font-body); }
.cf-noir-empty .cf-btn{ margin-top:6px; }

/* a page head: the title left, actions right */
.cf-page-head{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.cf-page-head > .cf-tabs, .cf-page-head > .cf-page-acts{ margin-left:auto; }
.cf-page-acts{ display:flex; gap:8px; flex-wrap:wrap; align-items:center; }

/* the reference's figure row: caps label, mono figure */
.cf-stat-row{ display:flex; gap:22px; flex-wrap:wrap; margin:0; }
.cf-stat-row > div{ min-width:70px; }
.cf-stat-row dt{ font:600 10px/1 var(--font-mono); letter-spacing:.14em; text-transform:uppercase; color:var(--ink3); }
.cf-stat-row dd{ margin:6px 0 0; font:600 20px/1 var(--font-mono); font-variant-numeric:tabular-nums; color:var(--ink); }

/* rows inside a glass panel (traders, calls, referrals, notifications) */
.cf-rowlist{ display:grid; gap:2px; }
.cf-rowlist > *{ border-radius:var(--r-md); transition:background var(--t-fast); }
@media (hover:hover){ .cf-rowlist > *:hover{ background:rgb(var(--tint) / .03); } }

/* a figure well (stats inside a card) */
.cf-wells{ display:grid; grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); gap:10px; }
.cf-wells > div{ padding:12px; border-radius:var(--r-md); background:var(--well); border:1px solid rgb(var(--tint) / .04); min-width:0; }
.cf-wells dt, .cf-wells span{ display:block; font:600 10px/1.2 var(--font-mono); letter-spacing:.12em; text-transform:uppercase; color:var(--ink3); }
.cf-wells dd, .cf-wells b{ display:block; margin:6px 0 0; font:600 18px/1.1 var(--font-mono); color:var(--ink); }

/* figures glow in their direction */
.cf-glow-up{ color:var(--up); text-shadow:0 0 14px rgb(var(--up-rgb) / .35); }
.cf-glow-dn{ color:var(--dn); text-shadow:0 0 14px rgb(var(--dn-rgb) / .35); }


/* ---- static/cf-rich.css ---- */
/* Cartel Family — rich post text (cf-rich.js): the links a post's words
   become, and the composer's @ / $ autocomplete popover.
   Every colour is a cf-theme token; nothing here is right in one theme only. */

/* ── the words ─────────────────────────────────────────────────────────── */
.cf-rich{
  color:var(--accent-text, var(--acc)); text-decoration:none; font-weight:600;
  border-radius:4px; transition:color var(--dur-fast, .16s) var(--ease-out, ease), background-color var(--dur-fast, .16s) var(--ease-out, ease);
}
.cf-rich:hover{ text-decoration:underline; text-underline-offset:2px; }
.cf-rich:focus-visible{ outline:none; box-shadow:var(--focus-ring, 0 0 0 2px var(--acc)); }
.cf-rich-t, .cf-rich-a{
  font-family:var(--font-mono); font-weight:600; font-size:.95em; letter-spacing:.01em;
  padding:0 .28em; margin:0 -.05em;
  background:color-mix(in srgb, var(--acc) 12%, transparent);
}
.cf-rich-t:hover, .cf-rich-a:hover{ background:color-mix(in srgb, var(--acc) 20%, transparent); text-decoration:none; }
/* Not a token we can name: the word still goes somewhere useful (the market
   search), but it is drawn as a question, never as a trade. */
.cf-rich-t.is-unresolved{
  color:var(--ink2); background:transparent; border-bottom:1px dashed var(--ink3); border-radius:0; padding:0;
}
.cf-rich-t.is-unresolved:hover{ color:var(--ink); border-bottom-color:var(--ink2); background:transparent; }
.cf-rich-a b{ font-weight:700; }
.cf-rich-addr{ opacity:.85; }
.cf-rich-l{ overflow-wrap:anywhere; font-weight:500; }
/* The Mini App draws these as buttons (its screens open in place). */
button.cf-rich{ appearance:none; border:0; background:transparent; font:inherit; cursor:pointer; display:inline; line-height:inherit; margin:0; min-height:0; }
button.cf-rich-m{ padding:0; }
button.cf-rich-t, button.cf-rich-a{ background:color-mix(in srgb, var(--acc) 12%, transparent); }

/* ── the autocomplete ──────────────────────────────────────────────────── */
.cf-rich-host{ position:relative; }
.cf-rich-pop{
  position:absolute; z-index:40; box-sizing:border-box;
  max-height:min(50vh, 316px); overflow-y:auto; overscroll-behavior:contain;
  padding:6px; border-radius:14px;
  background:var(--s2, var(--s1)); border:1px solid var(--line);
  box-shadow:var(--cf-modal-shadow, 0 18px 48px rgba(0,0,0,.45));
}
.cf-rich-pop.is-enter{ animation:cfRichIn var(--dur-fast, .16s) var(--ease-out, ease) both; }
@keyframes cfRichIn{ from{ opacity:0; transform:translateY(-4px); } to{ opacity:1; transform:none; } }
.cf-rich-row{
  display:flex; align-items:center; gap:10px; width:100%; box-sizing:border-box;
  min-height:36px; padding:6px 8px; border:0; border-radius:10px; text-align:left;
  background:transparent; color:var(--ink); font:500 13.5px/1.25 var(--font-ui); cursor:pointer;
}
.cf-rich-row:hover, .cf-rich-row.is-sel{ background:color-mix(in srgb, var(--acc) 14%, transparent); }
.cf-rich-row.is-sel .cf-rich-p{ color:var(--accent-text, var(--acc)); }
.cf-rich-row:focus-visible{ outline:none; box-shadow:var(--focus-ring, 0 0 0 2px var(--acc)); }
.cf-rich-tile{
  width:26px; height:26px; flex:0 0 26px; border-radius:50%; object-fit:cover;
  display:inline-flex; align-items:center; justify-content:center;
  background:color-mix(in srgb, var(--acc) 18%, var(--s1)); color:var(--ink);
  font:700 11px/1 var(--font-ui);
}
.cf-rich-main{ display:flex; flex-direction:column; gap:1px; min-width:0; }
.cf-rich-p{ font-family:var(--font-mono); font-weight:600; font-size:13px; }
.cf-rich-s{
  display:inline-flex; align-items:center; gap:5px; color:var(--ink3); font-size:11.5px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.cf-rich-chain{ width:12px; height:12px; border-radius:50%; flex:0 0 12px; }
@media (pointer: coarse){
  .cf-rich-row{ min-height:44px; font-size:14.5px; }
  .cf-rich-tile{ width:30px; height:30px; flex-basis:30px; }
}
@media (prefers-reduced-motion: reduce){
  .cf-rich, .cf-rich-pop.is-enter{ animation:none; transition:none; }
}


/* ---- static/cf-posts.css ---- */
/* Cartel Family — the public post composer and the posts feed.
 *
 * Both of these already existed on the server and had worked for months. They
 * were unreachable: their only caller lived inside templates/dashboard.html +
 * static/dashboard.js, the single document that used to BE the app, and when
 * the redesign replaced `/` with the feed that document stopped being served.
 * The routes still answered 200 the whole time. An audit found 74 endpoints in
 * the same position; this restores the social ones.
 *
 * Every colour is a cf-theme token. --accent is the brand (violet), --green
 * and --red mean gain and loss and nothing else, and a literal here would be
 * right in one theme and wrong in the other.
 */

/* ── composer ──────────────────────────────────────────────────────────── */
/* The design's (02-feed): a 36px avatar beside the text, then + Image,
   @ Mention and $ Token chips under it (indented to the text on desktop,
   full width on a phone) with Post on the right. */
.cf-comp{
  background:var(--s1); border:1px solid var(--line); border-radius:16px;
  padding:12px 14px; margin-bottom:14px;
}
.cf-comp-row{ display:flex; gap:10px; align-items:flex-start; }
.cf-comp-av{
  width:36px; height:36px; flex:0 0 36px; border-radius:50%; overflow:hidden;
  display:flex; align-items:center; justify-content:center;
  /* --ink, not white: the disc mixes into --s2 and is pale on light. */
  font:700 12px/1 var(--font-ui); color:var(--ink);
  background:color-mix(in srgb, var(--series-4) 45%, var(--s2));
}
.cf-comp-av img{ width:100%; height:100%; object-fit:cover; display:block; }
.cf-comp-av-guest{ background:none; border:2px dashed var(--ink3); box-sizing:border-box; }
.cf-comp-main{ flex:1; min-width:0; }
.cf-comp-in{
  width:100%; box-sizing:border-box; min-height:48px; resize:none; margin:0;
  background:transparent; border:0; outline:none; padding:8px 0 0;
  color:var(--ink); font:500 15px/1.4 var(--font-ui);
}
.cf-comp-in::placeholder{ color:var(--ink3); opacity:1; }
.cf-comp-guest-t{ color:var(--ink3); }

.cf-comp-preview{ position:relative; margin-top:10px; }
.cf-comp-preview img{
  width:100%; max-height:280px; object-fit:cover; display:block;
  border-radius:12px; border:1px solid var(--line);
}
.cf-comp-drop{
  position:absolute; top:8px; right:8px; width:28px; height:28px; border-radius:50%;
  border:0; cursor:pointer; background:var(--scrim); color:#fff;
  font:700 15px/1 var(--font-ui);
}

.cf-comp-bar{ display:flex; align-items:center; flex-wrap:wrap; gap:6px; margin-top:10px; }
.cf-comp-chip{
  position:relative; height:32px; padding:0 10px; display:flex; align-items:center;
  border:0; border-radius:8px; background:var(--s2); cursor:pointer; white-space:nowrap;
  font:600 12px/1 var(--font-ui); color:var(--ink2);
  transition:color .14s ease;
}
.cf-comp-chip:hover{ color:var(--ink); }
.cf-comp-icon input{ position:absolute; width:1px; height:1px; opacity:0; }
.cf-comp-count{
  margin-left:auto; font:500 11px/1 var(--font-num); color:var(--ink3);
  font-variant-numeric:tabular-nums; display:none;
}
/* The count appears only near the limit, so it never costs the chips room. */
.cf-comp-count.is-near, .cf-comp-count.is-over{ display:block; }
.cf-comp-count.is-near + .cf-comp-send, .cf-comp-count.is-over + .cf-comp-send{ margin-left:0; }
.cf-comp-count.is-near{ color:var(--pro); }
.cf-comp-count.is-over{ color:var(--dn); }
.cf-comp-send{
  height:36px; padding:0 18px; display:flex; align-items:center;
  border:0; border-radius:10px; cursor:pointer; text-decoration:none;
  font:700 13px/1 var(--font-ui); background:var(--acc); color:var(--onAcc);
  margin-left:auto;
}
.cf-comp-send:disabled{ background:var(--s2); color:var(--ink3); cursor:default; }
.cf-comp-connect{ margin-left:auto; }
.cf-comp-send:focus-visible,.cf-comp-chip:focus-visible,.cf-comp-icon:focus-within{ outline:2px solid var(--acc); outline-offset:2px; }

/* The composer's own status line. A post that failed must say why, in the
   server's words, and leave what was typed alone so it can be retried. */
.cf-comp-say{ margin-top:9px; font:500 12.5px/1.5 var(--font-ui); color:var(--ink2); }
.cf-comp-say[data-kind="error"]{ color:var(--dn); }
.cf-comp-say[data-kind="ok"]{ color:var(--up); }
.cf-comp-say:empty{ display:none; }

@media (max-width:767px){
  /* The chips run the full width of the card on a phone. */
  .cf-comp-bar{ margin-left:-46px; }
}

/* Touch: 44px targets, the design's drawn sizes. Each control's hit box
   grows with a transparent border and its fill stays clipped to the drawn
   32/36px shape; negative margins keep the drawn 6px spacing, and the bar
   sits 6px higher so the chips' drawn tops stay where they were. */
@media (pointer:coarse), (hover:none){
  .cf-comp-bar{ gap:0; margin-top:4px; }
  .cf-comp-chip{
    height:44px; box-sizing:border-box; margin-right:-6px;
    border:6px solid transparent; background-clip:padding-box; border-radius:14px;
  }
  .cf-comp-bar > .cf-comp-chip:first-child{ margin-left:-6px; }
  .cf-comp-send, .cf-comp-send:disabled{
    height:44px; box-sizing:border-box; margin-right:-4px;
    border:4px solid transparent; background-clip:padding-box; border-radius:14px;
  }
  .cf-comp-drop{ width:44px; height:44px; top:0; right:0; border:8px solid transparent; background-clip:padding-box; }
}

/* ── a post ────────────────────────────────────────────────────────────── */
.cf-post{
  background:var(--bg2); border:1px solid var(--border); border-radius:17px;
  padding:15px; margin-bottom:12px;
}
.cf-post-hd{ display:flex; align-items:center; gap:11px; }
.cf-post-av{
  width:36px; height:36px; flex:0 0 36px; border-radius:var(--r-pill); overflow:hidden;
  display:flex; align-items:center; justify-content:center;
  font:800 12px var(--font-sans); color:var(--m3-on-primary,#fff);
  background:linear-gradient(135deg, var(--accent-cta), var(--m3-primary-fixed-dim,var(--accent-cta)));
}
.cf-post-av img{ width:100%; height:100%; object-fit:cover; display:block; }
.cf-post-id{ min-width:0; display:flex; flex-direction:column; gap:2px; }
.cf-post-name{
  display:flex; align-items:center; gap:6px;
  font:700 13.5px var(--font-sans); color:var(--text);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.cf-post-when{ font:500 11px var(--font-mono); color:var(--dim); }
.cf-post-verified{
  width:14px; height:14px; flex:0 0 14px; border-radius:var(--r-pill);
  background:var(--accent-cta); color:var(--m3-on-primary,#fff);
  display:grid; place-items:center;
}
.cf-post-verified svg{ width:8px; height:8px; }
.cf-post-del{
  margin-left:auto; border:0; background:transparent; cursor:pointer;
  color:var(--dim); font:600 11.5px var(--font-sans); padding:4px 8px; border-radius:8px;
}
.cf-post-del:hover{ color:var(--red); background:var(--bg3); }

.cf-post-body{
  margin-top:11px; font-size:14px; line-height:1.55; color:var(--text);
  white-space:pre-wrap; overflow-wrap:anywhere;
}
.cf-post-img{
  margin-top:11px; width:100%; max-height:420px; object-fit:cover; display:block;
  border-radius:12px; border:1px solid var(--border);
}

/* A trade that came through the social feed keeps the feed's own language
   rather than becoming a third kind of card. */
.cf-post-trade{
  margin-top:11px; display:flex; align-items:baseline; gap:10px; flex-wrap:wrap;
  padding:10px 12px; border-radius:12px; background:var(--bg3); border:1px solid var(--border);
}
.cf-post-trade b{ font:700 13.5px var(--font-mono); }
.cf-post-trade .pnl{ margin-left:auto; font:700 13px var(--font-mono); color:var(--green); }
.cf-post-trade .pnl.down{ color:var(--red); }

.cf-post-ft{
  display:flex; align-items:center; gap:6px; margin-top:12px;
  padding-top:11px; border-top:1px solid var(--border);
}
.cf-post-act{
  display:inline-flex; align-items:center; gap:7px;
  border:0; background:transparent; cursor:pointer; color:var(--muted);
  font:600 12px var(--font-sans); padding:6px 10px; border-radius:9px;
  transition:color .14s ease, background .14s ease;
}
.cf-post-act:hover{ background:var(--bg3); color:var(--text); }
.cf-post-act:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
.cf-post-act svg{ width:15px; height:15px; }
/* Liked is the ONE place --red is not a loss on this surface, which is why it
   is a fill on an icon rather than a number. */
.cf-post-act.is-on{ color:var(--red); }
.cf-post-act.is-on svg{ fill:currentColor; }
.cf-post-views{ margin-left:auto; font:500 11px var(--font-mono); color:var(--dim); }

/* ── replies ───────────────────────────────────────────────────────────── */
.cf-post-replies{ margin-top:11px; padding-top:11px; border-top:1px solid var(--border); }
.cf-post-replies[hidden]{ display:none; }
.cf-reply{ display:flex; gap:10px; padding:8px 0; }
.cf-reply-av{
  width:26px; height:26px; flex:0 0 26px; border-radius:var(--r-pill); overflow:hidden;
  display:flex; align-items:center; justify-content:center;
  font:800 9px var(--font-sans); color:var(--m3-on-primary,#fff);
  background:linear-gradient(135deg, var(--accent-cta), var(--m3-primary-fixed-dim,var(--accent-cta)));
}
.cf-reply-av img{ width:100%; height:100%; object-fit:cover; display:block; }
.cf-reply-b{ min-width:0; flex:1; }
.cf-reply-who{ font:700 12px var(--font-sans); }
.cf-reply-when{ font:500 10px var(--font-mono); color:var(--dim); margin-left:6px; }
.cf-reply-t{
  font-size:13px; line-height:1.5; color:var(--muted); margin-top:3px;
  white-space:pre-wrap; overflow-wrap:anywhere;
}
.cf-reply-form{ display:flex; gap:8px; margin-top:9px; }
.cf-reply-form input{
  flex:1; min-width:0; box-sizing:border-box;
  background:var(--bg3); border:1px solid var(--border2); border-radius:11px;
  padding:9px 12px; color:var(--text); font:500 13px var(--font-sans); outline:none;
}
.cf-reply-form input:focus{ border-color:var(--accent); }
.cf-reply-form button{
  border:0; border-radius:11px; padding:9px 15px; cursor:pointer;
  font:700 12.5px var(--font-sans); color:var(--m3-on-primary,#fff);
  background:var(--accent-cta);
}
.cf-reply-form button:disabled{ opacity:.45; cursor:default; }

/* ── list states ───────────────────────────────────────────────────────── */
.cf-posts-state{
  text-align:center; padding:34px 18px; color:var(--muted);
  font-size:13.5px; line-height:1.6;
}
.cf-posts-state h3{ font-size:15px; font-weight:700; color:var(--text); margin-bottom:7px; }
.cf-posts-state button{
  margin-top:13px; border:1px solid var(--border2); background:var(--bg3); color:var(--text);
  border-radius:11px; padding:9px 17px; cursor:pointer; font:600 12.5px var(--font-sans);
}
.cf-posts-more{
  width:100%; margin-top:4px; border:1px solid var(--border2); background:var(--bg2);
  color:var(--muted); border-radius:12px; padding:11px; cursor:pointer;
  font:600 12.5px var(--font-sans);
}
.cf-posts-more:hover{ color:var(--text); border-color:var(--border); }
.cf-posts-more[hidden]{ display:none; }

@media (prefers-reduced-motion:reduce){
  .cf-comp-send, .cf-comp-icon, .cf-post-act{ transition:none; }
}
@media (max-width:560px){
  .cf-post{ border-radius:14px; padding:13px; }
}

/* The author's own post while it is being written: drawn at once, quieter
   until the server's stored row replaces it. Visible at rest, never parked. */
.cf-post.is-pending{ opacity:.72; }
.cf-post.is-pending .cf-post-when{ color:var(--acc, currentColor); }
/* A post in the For-you stream sits between trade cards: the stream's own 14px gap, no margin of its own. */
.hf-feed > .cf-post{ margin:0; }


/* ---- static/cf-creator-launches.css ---- */
/* "Launches" on a creator's profile (cf-creator-launches.js). Theme tokens
 * only, so both themes read; the curve bar fills from --p. The resting state
 * is visible: .cl-in is the entrance, added by script and removed when it
 * ends, and reduced motion never adds it. */
[data-cf-launches]{margin:16px 0;padding:16px;box-sizing:border-box;min-width:0}
/* In the visitor layout the mount is itself a .tp-card in the side column:
   no extra outer margin, so it lines up with the cards beside it. */
[data-cf-launches].tp-card{margin:0}
[data-cf-launches][hidden]{display:none}
.cl-h{display:flex;align-items:baseline;justify-content:space-between;flex-wrap:wrap;gap:4px 12px;margin:0 0 12px;min-width:0}
.cl-h h2{margin:0;font:700 18px/1.2 var(--font-ui);color:var(--ink)}
.cl-n{font:600 11px/1 var(--font-num, var(--font-mono));letter-spacing:.08em;text-transform:uppercase;color:var(--ink3)}
.cl-list{display:flex;flex-direction:column;gap:8px}
.cl-card{display:grid;grid-template-columns:40px minmax(0,1fr) auto;grid-template-areas:"img main meta" "img prog prog";
  align-items:center;gap:4px 12px;padding:12px 14px;border-radius:14px;background:var(--s1);border:1px solid var(--line, var(--s2));
  color:var(--ink);text-decoration:none;min-height:44px;transition:border-color .2s,transform .2s}
.cl-card:hover,.cl-card:focus-visible{border-color:var(--acc);transform:translateY(-1px)}
.cl-card:focus-visible{outline:none;box-shadow:var(--focus-ring)}
.cl-img{grid-area:img;width:40px;height:40px;border-radius:10px;object-fit:cover;background:var(--s2)}
.cl-img--none{display:flex;align-items:center;justify-content:center;font:700 13px var(--font-ui);color:var(--ink2)}
.cl-main{grid-area:main;display:flex;flex-direction:column;min-width:0}
.cl-main b{font:700 15px/1.2 var(--font-ui)}
.cl-main small,.cl-meta small{font:500 12px/1.3 var(--font-ui);color:var(--ink3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cl-meta{grid-area:meta;display:flex;flex-direction:column;align-items:flex-end}
.cl-meta b{font:700 14px/1.2 var(--font-num, var(--font-mono))}
.cl-prog{grid-area:prog;display:flex;align-items:center;gap:8px}
.cl-curve{flex:1;height:6px;border-radius:3px;background:var(--s2);overflow:hidden}
.cl-curve i{display:block;height:100%;width:var(--p);background:var(--acc);border-radius:3px}
.cl-pct{font:600 11px var(--font-num, var(--font-mono));color:var(--ink2)}
.cl-grad{font:700 10px/1.3 var(--font-ui);padding:2px 6px;border-radius:5px;color:var(--up);background:var(--upBg)}
.cl-in{animation:cl-in .5s cubic-bezier(.2,.7,.2,1) both}
@keyframes cl-in{from{opacity:.001;transform:translateY(8px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion: reduce){.cl-card{transition:none}.cl-in{animation:none}}


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

/* ── the ENTRY (owner, 2026-10-16): banner, offer card (cf-bonus.css draws
   the card itself), What's new, Sign up / Maybe later. */
.oa-ob-modal .oa-ob-entry{align-items:stretch;text-align:left;gap:14px}
.oa-ob-modal .oa-ob-hero{box-sizing:border-box;position:relative;width:100%;aspect-ratio:1230 / 475;border-radius:16px;overflow:hidden;flex:none;
  background:var(--s2);box-shadow:0 0 0 1px var(--line),0 12px 30px var(--accBg)}
.oa-ob-modal .oa-ob-hero img{position:absolute;inset:0;width:100%;height:100%;max-width:none;display:block;object-fit:cover;object-position:62% 50%}
/* a soft scrim at the foot so the art settles into the sheet; the art's own words sit above it */
.oa-ob-modal .oa-ob-hero::after{content:'';position:absolute;left:0;right:0;bottom:0;height:30%;pointer-events:none;
  background:linear-gradient(to top,var(--cf-scrim,var(--scrim)),transparent)}
.oa-ob-modal .oa-ob-main{display:flex;flex-direction:column;gap:12px;min-height:120px}
.oa-ob-modal .oa-ob-skel{display:flex;flex-direction:column;gap:10px}
.oa-ob-modal .oa-ob-skel i{display:block;border-radius:14px;background:var(--s2);height:56px}
.oa-ob-modal .oa-ob-skel i:first-child{height:150px;border-radius:18px}
.oa-ob-modal .oa-ob-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.oa-ob-modal .oa-ob-fhero{display:flex;flex-direction:column;gap:6px;padding:2px 2px 0}
.oa-ob-modal .oa-ob-fh{margin:0;font:800 24px/1.15 var(--font-display,var(--font-ui));letter-spacing:-.02em;color:var(--ink)}
.oa-ob-modal .oa-ob-fh span{color:var(--accent-text-strong,var(--acc))}
.oa-ob-modal .oa-ob-fhero .oa-ob-pitch{margin:0;max-width:none}
/* What's new: a strip (one row on show, rotating) or a list */
.oa-ob-modal .oa-ob-wn{box-sizing:border-box;width:100%;border:1px solid var(--line);border-radius:16px;background:var(--s2);padding:6px 10px 4px}
.oa-ob-modal .oa-ob-wn-h{display:flex;align-items:center;justify-content:space-between;min-height:30px;padding:0 4px}
.oa-ob-modal .oa-ob-wn-k{font:700 11px/1 var(--font-ui);letter-spacing:.08em;text-transform:uppercase;color:var(--accT)}
.oa-ob-modal .oa-ob-wn-all{min-height:44px;margin:-7px -6px;padding:0 10px;border:0;border-radius:10px;background:none;cursor:pointer;
  font:600 12px/1 var(--font-ui);color:var(--ink2)}
.oa-ob-modal .oa-ob-wn-all b{color:var(--ink);font-weight:800}
.oa-ob-modal .oa-ob-wn-all:hover{color:var(--ink)}
.oa-ob-modal .oa-ob-wn-vp{overflow:hidden}
.oa-ob-modal .oa-ob-wn[data-mode="strip"] .oa-ob-wn-vp{height:60px}
.oa-ob-modal .oa-ob-wn-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;transition:transform .45s var(--ease-out,ease-out)}
.oa-ob-modal .oa-ob-wn[data-mode="list"] .oa-ob-wn-list li+li{border-top:1px solid var(--line)}
.oa-ob-modal .oa-ob-wn-i{width:100%;min-height:60px;display:flex;align-items:center;gap:12px;padding:8px 4px;border:0;border-radius:12px;
  background:none;color:var(--ink);text-align:left;cursor:pointer}
.oa-ob-modal .oa-ob-wn-i:hover .oa-ob-wn-go{color:var(--acc)}
.oa-ob-modal .oa-ob-wn-i:focus-visible,.oa-ob-modal .oa-ob-wn-all:focus-visible,.oa-ob-modal .oa-ob-link:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.oa-ob-modal .oa-ob-wn-ico{width:40px;height:40px;border-radius:12px;flex:none;display:grid;place-items:center;background:var(--accBg);color:var(--accT)}
.oa-ob-modal .oa-ob-wn-ico svg{width:22px;height:22px;display:block}
.oa-ob-modal .oa-ob-wn-t{flex:1;min-width:0;display:grid;gap:2px}
.oa-ob-modal .oa-ob-wn-t b{font:700 14px/1.3 var(--font-ui);color:var(--ink)}
.oa-ob-modal .oa-ob-wn-t span{font:500 12px/1.4 var(--font-ui);color:var(--ink2)}
.oa-ob-modal .oa-ob-wn[data-mode="strip"] .oa-ob-wn-t b,.oa-ob-modal .oa-ob-wn[data-mode="strip"] .oa-ob-wn-t span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.oa-ob-modal .oa-ob-wn-go{width:18px;height:18px;flex:none;color:var(--ink3)}
.oa-ob-modal .oa-ob-entry .oa-ob-ctas{margin-top:0}
.oa-ob-modal .oa-ob-later{min-height:48px}
.oa-ob-modal .oa-ob-entry .oa-ob-foot{align-self:center;text-align:center}
.oa-ob-modal .oa-ob-link{border:0;background:none;padding:0 2px;min-height:44px;cursor:pointer;font:600 12px/1.5 var(--font-ui);
  color:var(--accT);text-decoration:underline;text-underline-offset:2px}
.oa-ob-modal .oa-ob-entry .oa-ob-foot-note{align-self:center}
@media (prefers-reduced-motion:reduce){ .oa-ob-modal .oa-ob-wn-list{transition: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}

