/*
 * Mini App theme on top of Pico.css. Pico brings the form and typography defaults; this file sets the tokens
 * (type scale, spacing, radii, colour roles, motion), maps Telegram's theme onto them so the app looks native in
 * light and dark clients, and styles the handful of components the payment flow needs.
 *
 * The neutrals come from Telegram (the SDK writes --tg-theme-*), so light and dark clients look native. The accent
 * is ours: the logo's blue scale (brand/README.md), the same in every client and theme, so the app matches its icon.
 * What this file adds besides is the roles Telegram does not provide — success, warning, danger, soft tints — and
 * the motion: every screen, step and card enters rather than appears.
 */

/* ---- 0. tokens --------------------------------------------------------- */
:root {
  /* layout */
  --cw-max: 620px;                 /* payment, account, settings: one readable column on a desktop browser */
  --cw-wide: 1280px;               /* signals: a table wants the width, so the signals tab gets it */
  --cw-buy: 920px;                 /* three pricing cards side by side */

  /* type */
  --cw-font: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --cw-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --fs-xs: .72rem; --fs-sm: .82rem; --fs-md: .95rem; --fs-lg: 1.1rem; --fs-xl: 1.45rem; --fs-2xl: 2.25rem;

  /* shape */
  --r-sm: 10px; --r-md: 14px; --r-lg: 18px; --r-pill: 999px;   /* wallet.tg: soft, generous corners */
  --cw-radius: var(--r-lg);

  /* brand: the logo's blue (500) and its steps toward white and black (brand/README.md) */
  --cw-brand-50: #edf5fb; --cw-brand-100: #d3e6f5; --cw-brand-200: #a7cdeb; --cw-brand-300: #87bae3; --cw-brand-400: #5ba0d9;
  --cw-brand-500: #2481cc; --cw-brand-600: #1e6cab; --cw-brand-700: #18588b; --cw-brand-800: #13436a; --cw-brand-900: #0d2e49;

  /* colour roles: neutrals from Telegram with sensible fallbacks outside it, the accent from the brand */
  --cw-bg: var(--tg-theme-bg-color, #ffffff);
  --cw-ink: var(--tg-theme-text-color, #14171c);
  --cw-accent: var(--cw-brand-500);                /* fills: buttons, dots, active marks */
  --cw-accent-ink: #ffffff;
  --cw-accent-text: var(--cw-brand-500);           /* accent as text and lines; a lighter step on dark grounds */
  --cw-muted: var(--tg-theme-hint-color, #6f7d8c);
  --cw-surface: var(--tg-theme-secondary-bg-color, #f3f5f8);
  --cw-line: color-mix(in srgb, var(--cw-muted) 26%, transparent);
  --cw-line-strong: color-mix(in srgb, var(--cw-muted) 45%, transparent);
  --cw-accent-soft: color-mix(in srgb, var(--cw-accent) 12%, transparent);
  --cw-accent-deep: color-mix(in srgb, var(--cw-accent) 84%, #000);
  /* the logo, the same drawing as assets/img/icon.svg */
  --cw-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' rx='22.4' fill='%232481cc'/%3E%3Cpolyline points='20,42 34,66 48,46 62,66 76,32' fill='none' stroke='%23fff' stroke-width='8.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Ccircle cx='78' cy='29' r='7' fill='%23fff'/%3E%3C/svg%3E");

  --cw-success: #16a34a; --cw-success-soft: color-mix(in srgb, var(--cw-success) 13%, transparent);
  --cw-warn: #d97706;    --cw-warn-soft: color-mix(in srgb, var(--cw-warn) 13%, transparent);
  --cw-danger: #dc2626;  --cw-danger-soft: color-mix(in srgb, var(--cw-danger) 12%, transparent);
  --heat-hot: var(--cw-danger); --heat-warm: #ea580c; --heat-cool: #0891b2; --heat-cold: #3b82f6;

  /* depth: visible on light backgrounds, replaced by borders in the dark */
  --sh-1: 0 1px 2px rgb(0 0 0 / .05), 0 6px 20px -10px rgb(0 0 0 / .14);
  --sh-2: 0 2px 6px rgb(0 0 0 / .06), 0 14px 32px -14px rgb(0 0 0 / .22);
  --sh-btn: 0 1px 2px rgb(0 0 0 / .12), inset 0 1px 0 rgb(255 255 255 / .18);

  /* motion */
  --t-fast: .15s; --t-base: .24s; --t-slow: .38s;
  --ease: cubic-bezier(.2, .7, .2, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);

  /* hand the tokens to Pico */
  --pico-font-family: var(--cw-font);
  --pico-border-radius: var(--r-md);
  --pico-font-size: 100%;
  --pico-spacing: 1rem;
  --pico-primary: var(--cw-accent-text);
  --pico-primary-background: var(--cw-accent);
  --pico-primary-border: var(--cw-accent);
  --pico-primary-inverse: var(--cw-accent-ink);
  --pico-primary-hover-background: var(--cw-accent-deep);
  --pico-primary-hover-border: var(--cw-accent-deep);
  --pico-primary-focus: var(--cw-accent-soft);
  --pico-form-element-focus-color: var(--cw-accent);
}

/* Dark: Telegram says so through data-theme (telegram.js), the browser through prefers-color-scheme. Shadows do
   nothing on a dark ground, so depth becomes a slightly lighter surface and a firmer line instead. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --cw-bg: var(--tg-theme-bg-color, #15181d);
    --cw-ink: var(--tg-theme-text-color, #e8ebef);
    --cw-surface: var(--tg-theme-secondary-bg-color, #1e2228);
    --cw-muted: var(--tg-theme-hint-color, #8b97a5);
    --cw-accent-text: var(--cw-brand-400);
    --sh-1: none; --sh-2: none; --sh-btn: inset 0 1px 0 rgb(255 255 255 / .12);
  }
}
:root[data-theme="dark"] {
  --cw-bg: var(--tg-theme-bg-color, #15181d);
  --cw-ink: var(--tg-theme-text-color, #e8ebef);
  --cw-surface: var(--tg-theme-secondary-bg-color, #1e2228);
  --cw-muted: var(--tg-theme-hint-color, #8b97a5);
  --cw-accent-text: var(--cw-brand-400);
  --sh-1: none; --sh-2: none; --sh-btn: inset 0 1px 0 rgb(255 255 255 / .12);
}

/* ---- 1. base ----------------------------------------------------------- */
html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--cw-bg);
  color: var(--cw-ink);
  margin: 0;
  font-family: var(--cw-font);
  font-feature-settings: "cv11", "ss01", "tnum";   /* Inter: single-storey a, open digits, tabular figures */
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, h4 { letter-spacing: -.015em; }
main.page {
  max-width: var(--cw-max);
  margin: 0 auto;
  padding: 0 1rem calc(3.5rem + var(--cw-bottom-inset, 0px));   /* the home bar in Telegram's fullscreen */
}

/* The width belongs to the tab, not to the app: a payment form is easier to read in one narrow column, while the
   signals grid has cards to spread out — it takes the whole window, because a column of unused screen is a column
   of signals nobody can see. showTab() writes the active tab onto <body>. */
body[data-tab="signals"] main.page,
body[data-tab="admin"] main.page { max-width: none; }
body[data-tab="buy"] main.page { max-width: var(--cw-buy); }
body[data-tab="buy"] #rail-panel,
body[data-tab="buy"] #pay-panel { max-width: var(--cw-max); margin-inline: auto; }
main.page { transition: max-width var(--t-slow) var(--ease); }

.muted { color: var(--cw-muted); }
.mono { font-family: var(--cw-mono); font-size: .82rem; word-break: break-all; letter-spacing: -.01em; }

/* ---- 2. motion --------------------------------------------------------- */
@keyframes cw-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes cw-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes cw-pop { 0% { transform: scale(.85); } 60% { transform: scale(1.08); } 100% { transform: scale(1); } }
@keyframes cw-slide-in { from { opacity: 0; transform: translateX(-8px); background: var(--cw-accent-soft); } to { opacity: 1; transform: none; } }
@keyframes cw-spin { to { transform: rotate(360deg); } }
@keyframes cw-beat { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .35; transform: scale(.8); } }

/* A screen, a tab or a step enters instead of appearing. Toggling [hidden] restarts the animation. The fill mode
   is "backwards", not "both": a finished animation that keeps its transform makes the container the frame of every
   position:fixed child, and the filter sheet and the photo lightbox then open at the bottom of a long page instead
   of the bottom of the screen - on a phone, out of sight. */
[data-screen]:not([hidden]),
.view:not([hidden]),
.step:not([hidden]) { animation: cw-rise var(--t-slow) var(--ease-out) backwards; }

/* Pressable things answer the finger: a small press, a small lift, never a jump. */
button, [role="button"], .tabs button, .copy-btn, .plan-dot {
  transition:
    background-color var(--t-base) var(--ease), border-color var(--t-base) var(--ease),
    color var(--t-base) var(--ease), box-shadow var(--t-base) var(--ease), transform var(--t-fast) var(--ease);
}
button:active, [role="button"]:active { transform: scale(.975); }

/* ---- 3. top bar and tabs ----------------------------------------------- */
.topbar {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; gap: .75rem;
  max-width: var(--cw-max); margin: 0 auto; padding: calc(.8rem + var(--cw-top-inset, 0px)) 1rem .8rem;
  background: color-mix(in srgb, var(--cw-bg) 82%, transparent);
  -webkit-backdrop-filter: saturate(160%) blur(14px); backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid var(--cw-line);
}
.topbar .brand {
  display: inline-flex; align-items: center; gap: .5rem;
  font-weight: 800; font-size: var(--fs-md); letter-spacing: -.02em;
}
/* The pulse mark (brand/README.md) before the name. A data URI, not a file: the stylesheet is also served bundled from
   another folder (MiniAppBundle), where a relative path would miss. */
.topbar .brand::before {
  content: ""; width: 1.7rem; height: 1.7rem; flex: none;
  background: var(--cw-mark) center / contain no-repeat;
}
body:not(.landing) .topbar .brand::before { width: 1.45rem; height: 1.45rem; }
.topbar .spacer { flex: 1; }

/* The Mini App's top bar (not the landing's): the whole window wide, one compact line - the brand, the tabs, the
   connection - so the screen keeps its height for the signals. */
/* A fixed height (--cw-topbar-h), not a measured one: the sticky tool rows under it take the same value, so they
   sit flush under the bar in every browser, zoom and font look; Telegram's fullscreen inset is added above. */
:root { --cw-topbar-h: calc(2.5rem + var(--cw-top-inset, 0px)); }
body:not(.landing) .topbar {
  box-sizing: border-box; height: var(--cw-topbar-h); max-width: none; gap: .6rem;
  padding: var(--cw-top-inset, 0px) 1rem 0; align-items: center;
}
body:not([data-screen-on="app"]) .topbar .tabs { display: none; }

/* Full screen or a window, on a computer only (telegram.js fullscreen); the icon shows what a click does. */
button.fs-toggle {
  flex: none; display: inline-flex; align-items: center; justify-content: center; width: 1.9rem; height: 1.9rem;
  padding: 0; border: 0; border-radius: var(--r-pill); background: none; color: var(--cw-muted); cursor: pointer;
}
button.fs-toggle:hover { color: var(--cw-ink); background: var(--cw-surface); }
button.fs-toggle:focus-visible { outline: 2px solid var(--cw-accent); outline-offset: 2px; }
button.fs-toggle svg { width: 1.05rem; height: 1.05rem; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
button.fs-toggle .fs-exit, button.fs-toggle[data-full="true"] .fs-enter { display: none; }
button.fs-toggle[data-full="true"] .fs-exit { display: block; }

/* Connection dot. Green pulses while signals can actually reach the screen, amber pulses when the round trip over
   the hub is too slow to trade on, red sits still because nothing is arriving at all. */
.rt {
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--cw-muted);
  display: inline-flex; align-items: center; gap: .4rem; padding: .25rem .6rem; border-radius: var(--r-pill);
  background: var(--cw-surface); transition: color var(--t-base) var(--ease), background-color var(--t-base) var(--ease);
}
.rt::before { content: ""; width: .5rem; height: .5rem; border-radius: 50%; background: var(--cw-muted); transition: background-color var(--t-base) var(--ease); }
.rt[data-state="connected"] { color: var(--cw-success); background: var(--cw-success-soft); }
.rt[data-state="connected"]::before { background: var(--cw-success); animation: cw-beat 1.6s ease-in-out infinite; }
.rt[data-state="slow"], .rt[data-state="reconnecting"] { color: var(--cw-warn); background: var(--cw-warn-soft); }
.rt[data-state="slow"]::before,
.rt[data-state="reconnecting"]::before { background: var(--cw-warn); animation: cw-beat 1s ease-in-out infinite; }
.rt[data-state="disconnected"] { color: var(--cw-danger); background: var(--cw-danger-soft); }
.rt[data-state="disconnected"]::before { background: var(--cw-danger); }

.tabs {
  position: relative; display: flex; justify-content: flex-start; gap: .15rem; min-width: 0; margin: 0 0 0 .4rem; padding: 0;   /* Pico spreads a nav */
  overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain;
}
.tabs::-webkit-scrollbar { display: none; }
.tabs button {
  flex: none; width: auto; margin: 0; padding: .32rem .7rem; border: none; border-radius: var(--r-pill);
  background: transparent; color: var(--cw-muted); font-size: var(--fs-sm); font-weight: 600; white-space: nowrap; box-shadow: none; line-height: 1.25;
}
.tabs button:hover { color: var(--cw-ink); }
.tabs button.active { background: var(--cw-surface); color: var(--cw-ink); box-shadow: 0 0 0 1px var(--cw-line); }
.tabs button:active { transform: scale(.97); }

/* ---- 4. cards, rows, copy ---------------------------------------------- */
.card {
  background: var(--cw-bg);
  border: 1px solid var(--cw-line); border-radius: var(--cw-radius);
  padding: 1.05rem; margin-bottom: 1rem;
  box-shadow: var(--sh-1);
  transition: box-shadow var(--t-base) var(--ease), border-color var(--t-base) var(--ease);
}
.card > h3 { margin: 0 0 .75rem; font-size: var(--fs-md); font-weight: 700; }
.card > h4 { margin: 0 0 .5rem; font-size: var(--fs-sm); font-weight: 700; }

.row { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: .6rem 0; border-bottom: 1px solid var(--cw-line); }
.row:last-child { border-bottom: none; }
.row .label { color: var(--cw-muted); font-size: var(--fs-sm); white-space: nowrap; }
.row .value { text-align: right; font-weight: 500; }

/* Copyable value: the text plus an explicit button, because "tap the text" is not discoverable. */
.copyable { display: flex; align-items: center; gap: .5rem; justify-content: flex-end; min-width: 0; }
.copyable .mono { flex: 1; text-align: right; }
.copy-btn {
  flex: none; width: 2.1rem; height: 2.1rem; padding: 0; margin: 0; border-radius: var(--r-sm);
  border: 1px solid var(--cw-line); background: var(--cw-surface); color: inherit; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
}
.copy-btn:hover { border-color: var(--cw-line-strong); background: var(--cw-accent-soft); color: var(--cw-accent-text); }
.copy-btn svg { width: 1rem; height: 1rem; }
.copy-btn.done { background: var(--cw-success); border-color: var(--cw-success); color: #fff; animation: cw-pop var(--t-slow) var(--ease-out); }

/* Withdrawing an invoice is a correction, not a primary action: available, but not competing with "pay". */
.invoice-cancel { width: auto; margin: .75rem 0 .25rem; padding: .3rem .8rem; font-size: var(--fs-xs); font-weight: 600; }

/* ---- 5. buttons -------------------------------------------------------- */
button:not(.secondary):not(.outline):not(.copy-btn):not(.plan-dot):not(.tab):not(.plain),
[role="button"]:not(.secondary):not(.outline) {
  background: linear-gradient(180deg, var(--cw-accent), var(--cw-accent-deep));
  border: 1px solid var(--cw-accent-deep); color: var(--cw-accent-ink);
  font-weight: 700; letter-spacing: .005em; box-shadow: var(--sh-btn);
}
button:not(.secondary):not(.outline):not(.copy-btn):not(.plan-dot):not(.tab):not(.plain):hover,
[role="button"]:not(.secondary):not(.outline):hover { filter: brightness(1.06); box-shadow: var(--sh-btn), 0 6px 18px -8px var(--cw-accent); }
button.secondary, [role="button"].secondary {
  background: var(--cw-surface); border: 1px solid var(--cw-line); color: var(--cw-ink); font-weight: 600; box-shadow: none;
}
button.secondary:hover, [role="button"].secondary:hover { border-color: var(--cw-line-strong); background: color-mix(in srgb, var(--cw-surface) 70%, var(--cw-bg)); }
button.outline, [role="button"].outline { background: transparent; }
button:focus-visible, [role="button"]:focus-visible, input:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--cw-accent-soft), 0 0 0 1px var(--cw-accent); }

input, select { font-family: var(--cw-font); transition: border-color var(--t-base) var(--ease), box-shadow var(--t-base) var(--ease); }

/* ---- 6. payment -------------------------------------------------------- */
.pay-amount { text-align: center; padding: .4rem 0 1.1rem; }
.pay-amount .total {
  display: block; font-size: var(--fs-2xl); font-weight: 800; letter-spacing: -.03em; line-height: 1.1;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(180deg, var(--cw-ink), color-mix(in srgb, var(--cw-ink) 70%, var(--cw-muted)));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.pay-amount .sub { display: block; color: var(--cw-muted); margin-top: .35rem; font-size: var(--fs-sm); font-weight: 500; }

.pay-status { text-align: center; color: var(--cw-muted); margin: .75rem 0 0; font-size: var(--fs-sm); animation: cw-fade var(--t-base) var(--ease) both; }
.pay-status.ok { color: var(--cw-success, var(--cw-accent)); }
.pay-status.error { color: var(--cw-danger); }
/* "Other ways to pay": a quiet button under the networks; the bot sends the rest to the chat. */
.rail-other { width: 100%; margin: .75rem 0 0; }
/* The free trial's offer: where signals are locked, above the plans, on the Account tab, in the home page's band. */
.trial-offer { display: grid; gap: .5rem; }
.trial-offer .trial-title { margin: 0; font-size: var(--fs-lg); text-wrap: balance; }
.trial-offer .trial-lead { margin: 0; color: var(--cw-muted); }
.trial-offer .trial-start { width: 100%; margin: .25rem 0 0; font-weight: 700; }
#signals-locked .trial-offer, #tech-locked .trial-offer { padding-bottom: 1rem; margin-bottom: 1rem; border-bottom: 1px solid var(--cw-line); }
.home-band .home-trial-start { margin-top: 1rem; }
#invite-share { width: 100%; margin-top: .75rem; }
/* Add to home screen: a card on Account, a closable band on Home; the app's own icon beside the words. */
.hs-icon { flex: none; width: 2.75rem; height: 2.75rem; border-radius: 22.4%; }
.hs-row { display: flex; align-items: center; gap: .8rem; margin-bottom: .85rem; }
.hs-row h3 { margin: 0 0 .15rem; font-size: var(--fs-md); font-weight: 700; text-wrap: balance; }
.hs-row p { margin: 0; font-size: var(--fs-sm); }
#hs-add { width: 100%; margin: 0; }
.hs-ios { margin: 0 0 .75rem; font-size: var(--fs-sm); color: var(--cw-muted); }
#hs-done { width: 100%; margin: .6rem 0 0; }
.hs-band {
  display: flex; align-items: center; gap: .6rem; margin: .75rem 0 0; padding: .5rem .45rem .5rem .65rem;
  border: 1px solid var(--cw-line); border-radius: var(--r-md); background: var(--cw-surface);
}
.hs-band .hs-icon { width: 2.25rem; height: 2.25rem; }
.hs-band p { flex: 1; min-width: 0; margin: 0; font-size: var(--fs-sm); font-weight: 600; }
.hs-band button {
  flex: none; padding: .35rem .55rem; border: 0; border-radius: var(--r-sm); background: transparent;
  color: var(--cw-accent-text); font-size: var(--fs-sm); font-weight: 700; line-height: 1.2;
}
.hs-band button:hover { background: var(--cw-accent-soft); }
.hs-band .hs-band-close { color: var(--cw-muted); font-size: 1.25rem; font-weight: 500; line-height: 1; padding: .2rem .45rem; }

/* "I sent it": the transaction id shortcut. The watcher finds the payment on its own, but a payer who has just
   sent money wants to do something rather than wait, and on BEP-20 this is the only thing left to do. */
.txid-box { border-top: 1px solid var(--cw-line); margin-top: 1rem; padding-top: .85rem; }
.txid-box h4 { margin: 0 0 .25rem; font-size: var(--fs-md); font-weight: 700; }
.txid-box .hint { color: var(--cw-muted); font-size: var(--fs-sm); margin: 0 0 .6rem; }
.txid { display: flex; gap: .5rem; }
.txid input { flex: 1; min-width: 0; margin: 0; font-family: var(--cw-mono); font-size: .8rem; }
.txid button { margin: 0; width: auto; white-space: nowrap; }

details.manual { border-top: 1px solid var(--cw-line); margin-top: 1rem; padding-top: .5rem; }
details.manual summary { cursor: pointer; font-weight: 600; font-size: var(--fs-md); list-style: none; display: flex; align-items: center; gap: .5rem; }
details.manual summary::-webkit-details-marker { display: none; }
details.manual summary::after { display: none; }   /* Pico draws its own chevron; ours is the ::before */
details.manual summary::before {
  content: ""; width: .45rem; height: .45rem; border-right: 2px solid var(--cw-muted); border-bottom: 2px solid var(--cw-muted);
  transform: rotate(-45deg); transition: transform var(--t-base) var(--ease); margin-left: .1rem;
}
details.manual[open] summary::before { transform: rotate(45deg); }
details.manual[open] > *:not(summary) { animation: cw-rise var(--t-base) var(--ease-out) both; }
details.manual .hint { color: var(--cw-muted); font-size: var(--fs-sm); margin: .5rem 0; }

/* ---- 7. buy wizard and pricing ----------------------------------------- */
.wizard { display: flex; align-items: center; gap: .6rem; margin: 1rem 0 .9rem; }
.wizard .step-title { margin: 0; font-size: var(--fs-lg); font-weight: 800; flex: 1; letter-spacing: -.02em; }
.step-back { width: auto; margin: 0; padding: .3rem .75rem; font-size: var(--fs-md); line-height: 1.2; border-radius: var(--r-pill); }
.step-count {
  color: var(--cw-muted); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .03em; white-space: nowrap;
  padding: .25rem .6rem; border-radius: var(--r-pill); background: var(--cw-surface);
}

/* Three cards side by side where there is room, a swipeable row on a phone. Each one answers the same four
   questions in the same order — what it is called, what it costs, what that is per day, and what you get — so they
   can be compared by reading across rather than by remembering. */
#plan-list { display: grid; gap: .85rem; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.plan-dots { display: flex; justify-content: center; gap: .45rem; margin-bottom: .7rem; }
.plan-dot {
  width: .5rem; height: .5rem; padding: 0; margin: 0; border-radius: var(--r-pill);
  border: none; background: var(--cw-line-strong); box-shadow: none;
}
.plan-dot.active { background: var(--cw-accent); width: 1.4rem; }

@media (max-width: 700px) {
  #plan-list {
    display: flex; overflow-x: auto; scroll-snap-type: x mandatory;
    gap: .75rem; padding-bottom: .6rem; margin-inline: -1rem; padding-inline: 1rem;
    scrollbar-width: none;
  }
  #plan-list::-webkit-scrollbar { display: none; }
  .plan-card { flex: 0 0 86%; scroll-snap-align: center; }
}
@media (min-width: 701px) { .plan-dots { display: none; } }

.plan-card {
  display: flex; flex-direction: column; gap: .35rem; position: relative;
  border: 1px solid var(--cw-line); border-radius: var(--cw-radius); padding: 1.15rem 1.1rem 1.1rem;
  background: var(--cw-bg); margin: 0; box-shadow: var(--sh-1);
  animation: cw-rise var(--t-slow) var(--ease-out) both;
  transition: transform var(--t-base) var(--ease), box-shadow var(--t-base) var(--ease), border-color var(--t-base) var(--ease);
}
.plan-card:nth-child(2) { animation-delay: .06s; }
.plan-card:nth-child(3) { animation-delay: .12s; }
@media (hover: hover) {
  .plan-card:hover { transform: translateY(-3px); box-shadow: var(--sh-2); border-color: var(--cw-line-strong); }
}
.plan-card.featured {
  border-color: var(--cw-accent);
  box-shadow: 0 0 0 1px var(--cw-accent) inset, 0 12px 30px -16px var(--cw-accent);
  background: linear-gradient(180deg, var(--cw-accent-soft), transparent 45%), var(--cw-bg);
}
.plan-card header { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin: 0; padding: 0; background: none; border: none; }
.plan-name { font-weight: 800; font-size: var(--fs-md); letter-spacing: -.01em; }
.plan-price .amount { font-size: var(--fs-xl); font-weight: 800; letter-spacing: -.03em; font-variant-numeric: tabular-nums; line-height: 1.15; }
.plan-perday, .plan-days { margin: 0; color: var(--cw-muted); font-size: var(--fs-sm); }
.plan-features { list-style: none; margin: .7rem 0 .5rem; padding: .7rem 0 0; display: grid; gap: .35rem; border-top: 1px dashed var(--cw-line); }
/* Pico gives every li a square marker of its own; the check mark in ::before is the only mark a feature gets. */
.plan-features li { list-style: none; font-size: var(--fs-sm); padding-left: 1.35rem; position: relative; line-height: 1.35; }
.plan-features li::before {
  content: "✓"; position: absolute; left: 0; top: .05rem; width: .95rem; height: .95rem; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .62rem; font-weight: 800; color: var(--cw-success); background: var(--cw-success-soft);
}
/* the Walt price (home page): the big figure, the list price struck beside it, the discount as a badge */
.plan-price { display: flex; align-items: baseline; flex-wrap: wrap; gap: .25rem .5rem; }
.plan-was { color: var(--cw-muted); font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; }
.badge.plan-off { align-self: center; background: color-mix(in srgb, var(--cw-success) 16%, transparent); color: var(--cw-success); box-shadow: none; font-weight: 800; white-space: nowrap; }
.plan-how { margin: .1rem 0 .2rem; font-size: var(--fs-xs); font-weight: 700; color: var(--cw-accent-text); }
/* The Buy tab's cards: the list price is the figure; the Walt price and its badge sit under it. */
.plan-how:has(.plan-off) { display: flex; align-items: center; gap: .45rem; font-size: var(--fs-sm); color: var(--cw-success); }
.plan-choose { width: 100%; margin: auto 0 0; }

/* How to pay: each choice a card that reads as one - accent border and tint, an icon, the amount, an arrow. */
.rail-lead { margin: 0 0 .9rem; font-size: var(--fs-sm); line-height: 1.5; }
.rail-note { margin: .35rem 0 0; font-size: var(--fs-xs); }
.pay-option {
  display: flex; align-items: center; gap: .8rem; width: 100%; margin: 0 0 .6rem; padding: .85rem .8rem .85rem .9rem;
  border: 1.5px solid var(--cw-accent); border-radius: var(--r-md); background: var(--cw-accent-soft); color: var(--cw-ink);
  text-align: left; font: inherit; cursor: pointer; transition: transform var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease);
}
.pay-option:hover { background: color-mix(in srgb, var(--cw-accent) 20%, transparent); }
.pay-option:active { transform: scale(.985); }
.pay-option:disabled { opacity: .6; cursor: default; }
.pay-option-icon { flex: none; display: grid; place-items: center; width: 2.6rem; height: 2.6rem; border-radius: 50%; background: var(--cw-accent); color: #fff; }
.pay-option-icon svg { width: 1.35rem; height: 1.35rem; }
.pay-option-text { flex: 1; min-width: 0; display: grid; gap: .12rem; }
.pay-option-head { display: flex; align-items: center; flex-wrap: wrap; gap: .4rem; }
.pay-option-head b { font-size: var(--fs-md); font-weight: 800; }
.pay-option-chip { font-style: normal; font-size: var(--fs-xs); font-weight: 800; padding: .08rem .45rem; border-radius: var(--r-pill); background: var(--cw-accent); color: var(--cw-accent-ink); }
.pay-option-text small { color: var(--cw-muted); font-size: var(--fs-xs); line-height: 1.35; }
.pay-option-price { display: flex; align-items: baseline; flex-wrap: wrap; gap: .1rem .45rem; margin-top: .3rem; }
.pay-option-price s { color: var(--cw-muted); font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; }
.pay-option-price s:empty { display: none; }
.pay-option-price b { font-size: var(--fs-lg); font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.pay-option-price .badge { align-self: center; padding: .12rem .45rem; }
.pay-option-go { flex: none; margin-left: -.15rem; font-size: 1.6rem; line-height: 1; color: var(--cw-accent-text); }
/* The order: the list price, the discounts in green, a subtotal, the balance credit, and what is to pay. */
.summary { margin: 0 0 1rem; padding: .55rem .9rem .35rem; border-radius: var(--r-md); background: var(--cw-surface); font-size: var(--fs-sm); }
.summary .summary-title { padding: .25rem 0 .2rem; font-weight: 800; }
.summary .row { padding: .42rem 0; }
.summary .row.off .value { color: var(--cw-success); }
.summary .row.subtotal .label, .summary .row.subtotal .value { color: var(--cw-ink); font-weight: 700; }
.summary .row.total { margin-top: .15rem; padding-top: .6rem; border-top: 1.5px solid var(--cw-line-strong); border-bottom: 0; }
.summary .row.total .label, .summary .row.total .value { color: var(--cw-ink); font-weight: 800; font-size: var(--fs-md); }
/* Walt in three steps: numbered, each with its value to copy, the amount to enter spelled out. */
.walt-title { margin: 0 0 .65rem; font-size: var(--fs-md); font-weight: 800; }
.walt-steps { margin: 0; padding: 0; list-style: none; counter-reset: walt; display: grid; gap: .9rem; }
.walt-steps > li { counter-increment: walt; position: relative; padding-left: 2.1rem; }
.walt-steps > li::before {
  content: counter(walt); position: absolute; left: 0; top: 0; width: 1.5rem; height: 1.5rem; border-radius: 50%;
  display: grid; place-items: center; background: var(--cw-accent); color: var(--cw-accent-ink); font-size: var(--fs-xs); font-weight: 800;
}
.walt-step { display: block; margin: .1rem 0 .25rem; font-weight: 700; }
.walt-steps .row { padding: .35rem 0; border-bottom: 0; }
.walt-steps .hint { margin: .3rem 0 0; font-size: var(--fs-sm); color: var(--cw-muted); line-height: 1.45; }
#walt-open { width: 100%; margin: .65rem 0 0; }
/* Paid: a large check, the end date, the way to the signals. */
.pay-done { display: grid; justify-items: center; gap: .5rem; padding: 1.2rem .5rem .4rem; text-align: center; animation: cw-rise var(--t-slow) var(--ease-out) both; }
.pay-done-mark { display: grid; place-items: center; width: 3.4rem; height: 3.4rem; border-radius: 50%; background: var(--cw-success); color: #fff; font-size: 1.8rem; font-weight: 800; animation: cw-pop var(--t-slow) var(--ease-out); }
.pay-done h3 { margin: .2rem 0 0; font-size: var(--fs-lg); font-weight: 800; }
.pay-done p { margin: 0; color: var(--cw-muted); font-size: var(--fs-sm); }
#pay-done-go { width: 100%; margin: .6rem 0 0; }
.walt-chat { margin: -.25rem 0 .8rem; font-size: var(--fs-sm); color: var(--cw-success); font-weight: 600; }
.walt-steps .qr { display: flex; justify-content: flex-start; padding: .4rem 0 0; }
.walt-steps .qr img { width: 148px; height: 148px; background: #fff; padding: .45rem; border-radius: var(--r-md); box-shadow: 0 0 0 1px var(--cw-line); }
.walt-steps .qr-hint { margin-top: .25rem; }
.walt-done { margin: 1rem 0 0; padding: .7rem .85rem; border-radius: var(--r-md); background: var(--cw-success-soft); font-size: var(--fs-sm); line-height: 1.45; }
.rail-btn { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: .75rem; margin-bottom: .55rem; padding: .85rem 1rem; text-align: left; }
.badge { font-size: var(--fs-xs); font-weight: 800; letter-spacing: .02em; padding: .2rem .55rem; border-radius: var(--r-pill); background: var(--cw-success); color: #fff; box-shadow: 0 2px 8px -3px var(--cw-success); }
.badge.best { background: var(--cw-accent); color: var(--cw-accent-ink); box-shadow: 0 2px 8px -3px var(--cw-accent); }

/* ---- 8. alerts ------------------------------------------------------- */
.alert { border-radius: var(--r-md); padding: .75rem .95rem; font-size: var(--fs-sm); line-height: 1.45; margin: 1rem 0 0; border: 1px solid var(--cw-line); background: var(--cw-surface); }
.alert.warn { border-color: color-mix(in srgb, var(--cw-warn) 35%, transparent); background: var(--cw-warn-soft); box-shadow: inset 3px 0 0 var(--cw-warn); }
.alert.ok { border-color: color-mix(in srgb, var(--cw-success) 35%, transparent); background: var(--cw-success-soft); box-shadow: inset 3px 0 0 var(--cw-success); }
.alert.error { border-color: color-mix(in srgb, var(--cw-danger) 35%, transparent); background: var(--cw-danger-soft); box-shadow: inset 3px 0 0 var(--cw-danger); }

/* ---- 8b. owner's view --------------------------------------------------
   Figures first and large, because they are what the owner opens the app for; the lists underneath are scanned,
   not read. Nothing here is a security boundary — the API checks the role on every call. */
/* The dashboard. Numbers first: one tile per figure, toned when the figure asks for attention. Under them a grid
   of panels that reuses the signals' panel and table look - the people take the wide column, invoices, parked
   payments and the cluster the narrow one; on a phone it is one column in that order. */
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); gap: .6rem; margin: 0 0 .9rem; }
.kpi { padding: .75rem .9rem; border-radius: var(--r-md); background: var(--cw-surface); box-shadow: var(--sh-1); border-left: 4px solid var(--cw-line-strong); }
.kpi.good { border-left-color: var(--cw-success); }
.kpi.warn { border-left-color: var(--cw-warn); }
.kpi.bad { border-left-color: var(--cw-danger); }
.kpi-value { display: block; font-size: var(--fs-xl); font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums; font-family: var(--cw-mono); }
.kpi-note { display: block; margin-top: .1rem; color: var(--cw-muted); font-size: var(--fs-xs); font-family: var(--cw-mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kpis.online { margin-bottom: .6rem; }
.kpi-label { display: block; margin-top: .15rem; color: var(--cw-muted); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }

.dash { display: grid; gap: .8rem; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); grid-template-areas: "users invoices" "users unmatched" "users cluster"; align-items: start; }
.dash-users { grid-area: users; }
.dash-invoices { grid-area: invoices; }
.dash-unmatched { grid-area: unmatched; }
.dash-cluster { grid-area: cluster; }
.dash .panel-body h4 { margin: .8rem .2rem .4rem; font-size: var(--fs-xs); font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--cw-muted); }
@media (max-width: 900px) { .dash { grid-template-columns: 1fr; grid-template-areas: "users" "invoices" "unmatched" "cluster"; } }

/* The plain data table: the signals table without the tint, rows separated by a hairline. */
.data-table { width: 100%; border-collapse: collapse; margin: 0; font-size: var(--fs-sm); }
.data-table th, .data-table td { padding: .45rem .55rem; white-space: nowrap; background: transparent; border: 0; border-bottom: 1px solid var(--cw-line); vertical-align: middle; }
.data-table thead th { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .04em; color: var(--cw-muted); text-align: left; }
.data-table th.num, .data-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table td.mono, .data-table td.when { font-family: var(--cw-mono); font-size: var(--fs-xs); }
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table tbody tr:hover td { background: color-mix(in srgb, var(--cw-ink) 4%, transparent); }
.data-table td.name { font-weight: 600; max-width: 14rem; overflow: hidden; text-overflow: ellipsis; }
.data-table tr.blocked td { color: var(--cw-muted); }
.data-table .status.ok { color: var(--cw-success); font-weight: 700; }
.data-table .status.warn { color: var(--cw-warn); font-weight: 700; }
.data-table .status.bad { color: var(--cw-danger); font-weight: 700; }
.role { display: inline-block; margin-right: .25rem; padding: .1rem .45rem; border-radius: var(--r-pill); background: var(--cw-bg); box-shadow: 0 0 0 1px var(--cw-line); font-size: var(--fs-xs); font-weight: 600; }
.role.admin { background: var(--cw-accent-soft); color: var(--cw-accent-text); box-shadow: none; }
.avatar-cell { width: 2.6rem; }
.avatar {
  width: 2.2rem; height: 2.2rem; padding: 0; border: 0; border-radius: 50%; overflow: hidden; display: inline-flex; align-items: center; justify-content: center;
  background: var(--cw-accent-soft); color: var(--cw-accent-text); font-weight: 800; font-size: var(--fs-sm); cursor: zoom-in;
}
.avatar:disabled { cursor: default; opacity: 1; }
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
tr.blocked .avatar { background: var(--cw-surface); color: var(--cw-muted); }
.act-cell { text-align: right; }
.data-table .act { padding: .2rem .6rem; font-size: var(--fs-xs); white-space: nowrap; }
.leases { display: flex; flex-wrap: wrap; gap: .3rem; }
.lease { padding: .2rem .55rem; border-radius: var(--r-pill); background: var(--cw-bg); box-shadow: 0 0 0 1px var(--cw-line); font-family: var(--cw-mono); font-size: var(--fs-xs); color: var(--cw-muted); }
.lease.ok { color: var(--cw-success); }

/* A photo, full size, on a dimmed page; any tap closes it. */
.lightbox { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; padding: 1.5rem; background: rgb(0 0 0 / .7); cursor: zoom-out; animation: cw-fade var(--t-base) var(--ease-out) both; }
.lightbox img { max-width: min(92vw, 640px); max-height: 85vh; border-radius: var(--r-md); box-shadow: var(--sh-2); }

/* Sales (docs/admin-sales.md §5): the money and member tiles, a chart of stacked bars - exchange or wallet in the
   accent, Walt in a light step of it - the period table, then the lists. */
.sales { display: grid; gap: .8rem; margin: 0 0 .9rem; }
.sales-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem .8rem; }
.sales-head h3 { margin: 0; font-size: var(--fs-lg); }
.sales-head .muted { font-size: var(--fs-xs); }
.sales .kpis { margin: 0; }
.sales .kpi-note, .member-kpis .kpi-note { white-space: normal; overflow: visible; }
.sales .kpi-note + .kpi-note { margin-top: 0; }
.sales .hint { margin: .4rem 0 0; font-size: var(--fs-xs); color: var(--cw-muted); }
.sales-seg { margin-left: auto; width: auto; }
.sales-legend { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .9rem; font-size: var(--fs-xs); color: var(--cw-muted); margin-bottom: .3rem; }
.sales-legend .key { display: inline-block; width: .65rem; height: .65rem; border-radius: 2px; margin-right: .3rem; vertical-align: -.05rem; }
.key.wallet, .sales-bar i.wallet { background: var(--cw-accent); }
.key.walt, .sales-bar i.walt { background: color-mix(in srgb, var(--cw-accent) 38%, var(--cw-surface)); }
.sales-scale { font-size: var(--fs-xs); }
.sales-chart { display: flex; align-items: flex-end; gap: 3px; height: 9rem; padding-top: .2rem; border-bottom: 1px solid var(--cw-line-strong); }
.sales-bar { flex: 1 1 0; min-width: 0; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; }
.sales-bar:hover { background: color-mix(in srgb, var(--cw-accent) 7%, transparent); }
.sales-bar i { display: block; width: 100%; }
.sales-bar i.walt { border-radius: 2px 2px 0 0; }
.sales-axis { display: flex; gap: 3px; margin: .25rem 0 .7rem; font-size: var(--fs-xs); color: var(--cw-muted); }
.sales-axis span { flex: 1 1 0; min-width: 0; text-align: center; white-space: nowrap; overflow: visible; }
.sales-lists { display: grid; gap: .8rem; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); align-items: start; }
.sales-lists > :last-child { grid-column: 1 / -1; }
.sales-lists .table-wrap { max-height: 24rem; overflow: auto; }
.data-table .empty { text-align: center; padding: 1rem; }
.chip.first { margin-left: .35rem; padding: .05rem .4rem; border-radius: var(--r-pill); background: var(--cw-success-soft); color: var(--cw-success); font-size: var(--fs-xs); font-weight: 700; }
/* A name that opens the member's card: a link to look at, whatever a button looks like elsewhere (Pico). */
button.member-link, button.member-tg { width: auto; margin: 0; padding: 0; border: 0; background: none; box-shadow: none; font: inherit; font-weight: 700; color: var(--cw-accent-text); text-align: left; cursor: pointer; }
button.member-link:focus-visible, button.member-tg:focus-visible { outline: 2px solid var(--cw-accent); outline-offset: 2px; }
.member-link:hover { text-decoration: underline; }
.member-ref .muted { font-size: var(--fs-xs); }
.admin-search { margin: 0 0 0 auto; width: min(19rem, 60%); padding: .3rem .6rem; font-size: var(--fs-sm); }

/* A member's card over the page; a tap outside it closes it, a tapped photo opens in the lightbox above it. */
.member-sheet { position: fixed; inset: 0; z-index: 45; display: flex; align-items: flex-start; justify-content: center; padding: calc(1rem + var(--cw-top-inset, 0px)) .75rem 1rem; overflow-y: auto; background: rgb(0 0 0 / .55); animation: cw-fade var(--t-base) var(--ease-out) both; }
.member-card { position: relative; width: min(100%, 52rem); padding: 1rem; border-radius: var(--r-lg); background: var(--cw-bg); box-shadow: var(--sh-2); display: grid; gap: .8rem; }
.member-body { display: grid; gap: .8rem; min-width: 0; }
button.member-close { position: absolute; top: .4rem; right: .6rem; width: auto; margin: 0; padding: .2rem .5rem; border: 0; background: none; box-shadow: none; font-size: 1.4rem; line-height: 1; color: var(--cw-muted); }
.member-head { display: flex; align-items: center; gap: .8rem; padding-right: 2rem; }
.member-avatar { width: 3.4rem; height: 3.4rem; flex: none; font-size: var(--fs-lg); cursor: default; }
.member-avatar.has-photo { cursor: zoom-in; }
.member-who { display: grid; gap: .1rem; min-width: 0; }
.member-who strong { font-size: var(--fs-lg); overflow-wrap: anywhere; }
.member-who .muted { font-size: var(--fs-xs); }
.member-tg { justify-self: start; }
.member-kpis { margin: 0; grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 700px) {
  .sales-lists { grid-template-columns: minmax(0, 1fr); }
  .sales-seg { margin-left: 0; }
  .admin-search { width: 100%; margin-left: 0; }
  .dash-users .panel-head { flex-wrap: wrap; }
  .member-card { padding: .8rem; }
  .member-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* five money tiles two to a row: the last, all time, takes the row rather than sit alone */
  .sales-money .kpi:last-child { grid-column: 1 / -1; }
}

/* ---- 9. signals -------------------------------------------------------- */
/* Two ways to read the same feed. Cards: one grid of them, one column on a phone, as many as fit on a desktop.
   Table: one compact panel per source (exchange x rule), side by side where the width allows, each its own page
   of ten with its own pager. Both are built from the same rows; the reader picks, and the choice is remembered.
   Colour says direction: green for UP/PUMP, red for DOWN/DUMP. */

/* The bar. One row that reads left to right as "how, what, which": the view (a segmented control), the symbol
   search (icon, clear button), and Filter with a badge for what is applied. The sources live in a popover under
   the button - on a phone a sheet from the bottom, thumb distance - one line per source with its count at the
   right; the applied one is repeated under the bar as a tag that removes it with one tap. The table view keeps
   only the view switch: its panels filter themselves. */
/* Under the top bar, which is taller by Telegram's fullscreen inset (telegram.js sets --cw-top-inset). */
.sig-toolbar:has(.popover:not([hidden])), .tech-head:has(.popover:not([hidden])) { z-index: 45; }
.sig-toolbar {
  position: sticky; top: var(--cw-topbar-h); z-index: 6;
  display: flex; align-items: center; gap: .5rem; margin: 0 0 .6rem; padding: .35rem 0; background: var(--cw-bg);
}
/* One line: the view at its own width (a grid stretched it to half the screen), the search capped, the filter;
   what is applied follows on the same line and scrolls sideways when it is long. */
.sig-bar { display: flex; align-items: center; gap: .5rem; flex: none; min-width: 0; }
.sig-bar .search { flex: 0 1 20rem; width: 20rem; }
.sig-toolbar .applied { flex: 1 1 auto; min-width: 0; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-top: 0; }
.sig-toolbar .applied::-webkit-scrollbar { display: none; }
.sig-toolbar .applied .tag { flex: none; }
.plain { margin: 0; width: auto; box-shadow: none; }

/* Its own width: Pico stretches every [role=group] to the full line and its buttons with it, which put the two
   view buttons half a screen apart. A control that wants the line (the phone's Top 20 switch, the font look) says so. */
.seg { display: inline-flex; flex: none; width: auto; margin: 0; padding: .2rem; gap: .15rem; border-radius: var(--r-pill); background: var(--cw-surface); border: 1px solid var(--cw-line); }
.seg > .seg-btn { flex: none; }
.seg-btn {
  display: inline-flex; align-items: center; gap: .35rem; padding: .25rem .65rem; border: 0; border-radius: var(--r-pill);
  background: transparent; color: var(--cw-muted); font-size: var(--fs-sm); font-weight: 600; white-space: nowrap; line-height: 1.2;
}
.seg-btn:hover { color: var(--cw-ink); background: transparent; }
.seg-btn.active { background: var(--cw-bg); color: var(--cw-ink); box-shadow: 0 1px 3px rgb(0 0 0 / .12), 0 0 0 1px var(--cw-line); }

.search {
  display: flex; align-items: center; gap: .4rem; min-width: 0; margin: 0; padding: 0 .3rem 0 .6rem; height: 2.05rem;
  border: 1px solid var(--cw-line); border-radius: var(--r-pill); background: var(--cw-surface); color: var(--cw-muted);
  transition: border-color var(--t-base) var(--ease), box-shadow var(--t-base) var(--ease);
}
.search:focus-within { border-color: var(--cw-accent); box-shadow: 0 0 0 3px var(--cw-accent-soft); color: var(--cw-ink); }
.search svg { flex: none; }
.search input {
  flex: 1 1 auto; min-width: 0; margin: 0; padding: 0; height: 100%; border: 0; background: transparent; box-shadow: none;
  color: var(--cw-ink); font-family: var(--cw-mono); font-size: var(--fs-sm); text-transform: uppercase;
}
.search input:focus { outline: none; box-shadow: none; }
/* Pico paints its own magnifier into a search input: the box already has one, two read as a mistake. */
label.search input[type="search"] { background-image: none; padding-inline-start: 0; }
.search input::-webkit-search-cancel-button { display: none; }
.search .clear { width: 1.4rem; height: 1.4rem; padding: 0; border: 0; border-radius: 50%; background: var(--cw-line); color: var(--cw-ink); font-size: var(--fs-md); line-height: 1; }

.filter-anchor { position: relative; flex: none; }
.tool-btn {
  display: inline-flex; align-items: center; gap: .4rem; height: 2.05rem; padding: 0 .75rem; border: 1px solid var(--cw-line); border-radius: var(--r-pill);
  background: var(--cw-surface); color: var(--cw-muted); font-size: var(--fs-sm); font-weight: 600; white-space: nowrap;
}
.tool-btn:hover, .tool-btn[aria-expanded="true"] { color: var(--cw-ink); border-color: var(--cw-line-strong); background: var(--cw-surface); }
.badge-count { min-width: 1.15rem; height: 1.15rem; padding: 0 .3rem; border-radius: var(--r-pill); background: var(--cw-accent); color: var(--cw-accent-ink); font-size: .68rem; font-weight: 800; line-height: 1.15rem; text-align: center; }

.popover {
  position: absolute; right: 0; top: calc(100% + .4rem); z-index: 30; min-width: 17rem; padding: .5rem;
  max-height: calc(100vh - 9rem); max-height: calc(100dvh - 9rem); overflow-y: auto; overscroll-behavior: contain;   /* a long list scrolls inside, never off the screen */
  border-radius: var(--r-md); background: var(--cw-bg); box-shadow: var(--sh-2), 0 0 0 1px var(--cw-line);
  animation: cw-rise var(--t-base) var(--ease-out) both;
}
.popover-title { padding: .3rem .6rem .5rem; font-size: var(--fs-xs); font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--cw-muted); }
.popover-hint { margin: .4rem .6rem .2rem; font-size: var(--fs-xs); }
.choice-list { display: flex; flex-direction: column; gap: .1rem; }
.choice {
  display: flex; align-items: center; gap: .6rem; width: 100%; padding: .5rem .6rem; border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--cw-ink); font-size: var(--fs-sm); font-weight: 600; text-align: left;
}
.choice:hover { background: var(--cw-surface); color: var(--cw-ink); }
.choice .dot { width: 1rem; height: 1rem; flex: none; border-radius: 5px; border: 2px solid var(--cw-line-strong); box-sizing: border-box; transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease); }
.choice.active .dot { border-color: var(--cw-accent); background: var(--cw-accent); }
.choice.active .dot::after { content: ""; display: block; width: .28rem; height: .5rem; margin: 0 auto; border: solid #fff; border-width: 0 2px 2px 0; transform: translateY(-.05rem) rotate(45deg); }
.choice-label { flex: 1 1 auto; }
.choice-count { font-family: var(--cw-mono); font-size: var(--fs-xs); color: var(--cw-muted); font-variant-numeric: tabular-nums; }

.error-actions { display: flex; flex-wrap: wrap; gap: .5rem; }
.error-actions button { flex: 1 1 10rem; margin: 0; }

/* The sheet's head and backdrop exist only on a phone, where the popover becomes a bottom sheet. */
.sheet-head, .sheet-backdrop { display: none; }

.applied { display: flex; flex-wrap: wrap; gap: .35rem; padding-top: .5rem; }
.tag {
  display: inline-flex; align-items: center; gap: .45rem; padding: .25rem .5rem .25rem .7rem; border: 0; border-radius: var(--r-pill);
  background: var(--cw-accent-soft); color: var(--cw-accent-text); font-size: var(--fs-xs); font-weight: 700;
}
.tag:hover { background: var(--cw-accent); color: var(--cw-accent-ink); }
.tag .x { font-size: var(--fs-md); line-height: 1; }

/* A phone reads one step smaller: every size token loses a pixel (1/16 rem), so the whole scale moves together. */
@media (max-width: 700px) {
  :root { --fs-xs: .66rem; --fs-sm: .76rem; --fs-md: .89rem; --fs-lg: 1.04rem; --fs-xl: 1.39rem; --fs-2xl: 2.19rem; }
}

@media (max-width: 700px) {
  /* A phone: the top bar is the mark, the tabs (sideways) and the connection - the name is Telegram's own title bar -
     and the tool row is the view icons, the search filling the rest and the filter; what is applied gets its own line. */
  body[data-screen-on="app"] .topbar .brand-name { display: none; }
  body:not(.landing) .topbar { padding-inline: .6rem; gap: .4rem; }
  .tabs { margin-left: 0; flex: 1 1 auto; }
  .tabs button { padding: .3rem .6rem; }
  .rt { padding: .2rem .45rem; }
  .sig-toolbar { flex-wrap: wrap; row-gap: .35rem; }
  .sig-bar { flex: 1 1 100%; }
  .sig-bar .search { flex: 1 1 auto; width: auto; }
  .sig-toolbar .applied { flex-basis: 100%; }
  /* Icons alone on a phone in the two tool bars (the icon is the word); the word stays for screen readers. Only
     there: the Top 20 exchange switch and the Account settings have no icon, and an empty button is no button. */
  .sig-bar .seg-btn span, .tool-btn span:not(.badge-count) {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .sig-bar .seg-btn { padding: .3rem .55rem; }
  .tool-btn { padding: 0 .6rem; }
  /* A bottom sheet that stays short: a head with the title and a close button (and a grip to swipe it down),
     the choices as wrapping chips instead of a column, a dimmed backdrop that closes it with one tap, and never
     taller than three quarters of the screen - the rest scrolls inside. */
  .popover {
    position: fixed; left: 0; right: 0; top: auto; bottom: 0; z-index: 41; min-width: 0; max-height: 75vh; max-height: 75dvh;
    padding: 0 .8rem calc(.8rem + env(safe-area-inset-bottom, 0px)); overflow-y: auto; overscroll-behavior: contain;
    border-radius: var(--r-lg) var(--r-lg) 0 0; animation: cw-rise var(--t-slow) var(--ease-out) both;
  }
  .popover.dragging { animation: none; transition: none; }
  .popover.settling { transition: transform var(--t-base) var(--ease-out); }
  .sheet-head {
    position: sticky; top: 0; z-index: 1; display: grid; grid-template-columns: 2.4rem 1fr 2.4rem; align-items: center;
    margin: 0 -.8rem .2rem; padding: .9rem .8rem .4rem; background: var(--cw-bg); touch-action: none;
  }
  .sheet-grip { position: absolute; top: .4rem; left: 50%; width: 2.4rem; height: .25rem; margin-left: -1.2rem; border-radius: var(--r-pill); background: var(--cw-line-strong); }
  .sheet-title { grid-column: 2; text-align: center; font-size: var(--fs-md); font-weight: 800; }
  .sheet-close {
    grid-column: 3; justify-self: end; width: 2.2rem; height: 2.2rem; padding: 0; border: 0; border-radius: 50%;
    background: var(--cw-surface); color: var(--cw-ink); font-size: 1.35rem; line-height: 1;
  }
  .popover:not([hidden]) + .sheet-backdrop { display: block; position: fixed; inset: 0; z-index: 40; background: rgb(0 0 0 / .45); animation: cw-fade var(--t-base) var(--ease-out) both; }
  .popover-title { padding: .55rem .1rem .35rem; }
  .popover-hint { margin: .35rem .1rem 0; }
  .popover .choice-list { flex-direction: row; flex-wrap: wrap; gap: .4rem; }
  .popover .choice {
    width: auto; gap: .45rem; padding: .5rem .75rem; border: 1px solid var(--cw-line); border-radius: var(--r-pill); background: var(--cw-surface);
  }
  .popover .choice.active { border-color: var(--cw-accent); background: var(--cw-accent-soft); }
  .popover .choice .dot { width: .9rem; height: .9rem; }
  .popover .choice-label { flex: none; }
}
@keyframes cw-fade { from { opacity: 0; } to { opacity: 1; } }

/* Table view: one data grid per source, side by side where the width allows. Each panel has a title with the
   count behind it and a fold button, a header row, a filter row (symbol, kind), the rows, and a pager with the
   page size, "page x of y (n items)" and numbered pages. The look of a trading terminal: a solid green or red
   pill for the symbol, the row tinted the same way, the numbers in the mono face. */
/* Grids as tight as a hairline allows (owner, 2026-10-07: "the gaps between the cards to a minimum"). */
.panels { display: grid; gap: .3rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 460px), 1fr)); align-items: start; }
.panel { min-width: 0; border-radius: var(--r-lg); background: var(--cw-surface); box-shadow: var(--sh-1); transition: box-shadow var(--t-base) var(--ease), opacity var(--t-base) var(--ease); }
.panel.dragging { opacity: .5; }
.panel.drop-target { box-shadow: 0 0 0 2px var(--cw-accent), var(--sh-2); }
.panel-head[draggable="true"] { cursor: grab; }
.panel-head[draggable="true"]:active { cursor: grabbing; }
.panel.collapsed { opacity: .75; }
.panel[aria-busy="true"] .panel-body { opacity: .6; }
.panel-head { display: flex; align-items: center; gap: .5rem; padding: .55rem .8rem; border-bottom: 1px solid var(--cw-line); }
.panel.collapsed .panel-head { border-bottom: 0; }
.panel-title { font-weight: 800; font-size: var(--fs-md); letter-spacing: -.01em; font-family: var(--cw-mono); }
/* One table for every exchange of a rule: the split / combine switch, and a checkbox per exchange with its count. */
.panel-combine { margin-left: auto; padding: .2rem .55rem; border: 1px solid var(--cw-line); border-radius: 999px; background: var(--cw-bg); color: var(--cw-muted); font-size: var(--fs-xs); font-weight: 600; white-space: nowrap; }
.panel-combine + .panel-fold { margin-left: 0; }
.panel-venues { display: flex; flex-wrap: wrap; gap: .35rem .9rem; padding: .45rem .8rem; border-bottom: 1px solid var(--cw-line); font-size: var(--fs-xs); }
.panel-venues[hidden] { display: none; }
/* The fold for the exchange ticks, in the Exchange column's filter cell: shaped like the signal select beside it. */
.sig-table tr.filters .f-venues { height: 1.9rem; padding: .1rem .5rem; font-size: var(--fs-xs); font-family: var(--cw-mono); font-weight: 700; color: var(--text, inherit); background: var(--surface, var(--cw-bg)); border: 1px solid var(--border, var(--cw-line)); border-radius: var(--r-sm); white-space: nowrap; cursor: pointer; }
.sig-table tr.filters .f-venues.filtered { border-color: var(--cw-accent); color: var(--cw-accent-text); }
.panel-venues .venue { display: inline-flex; align-items: center; gap: .3rem; cursor: pointer; user-select: none; }
.panel-venues .venue input { margin: 0; accent-color: var(--cw-accent, currentColor); }
.panel-venues .venue-count { color: var(--cw-muted); font-variant-numeric: tabular-nums; }
.sig-table td.ex { color: var(--cw-muted); font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; white-space: nowrap; }
.panel-fold { margin-left: auto; width: 1.8rem; height: 1.8rem; padding: 0; border: 1px solid var(--cw-line); border-radius: 50%; background: var(--cw-bg); color: var(--cw-muted); font-size: var(--fs-md); line-height: 1; }
.panel-body { padding: 0 .5rem .5rem; }
.table-wrap { overflow-x: auto; }
.sig-table { width: 100%; border-collapse: separate; border-spacing: 0 3px; margin: 0; font-size: var(--fs-sm); font-family: var(--cw-mono); }
.sig-table th, .sig-table td { padding: .3rem .5rem; white-space: nowrap; background: transparent; border: 0; }
.sig-table thead th { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .04em; color: var(--cw-muted); text-align: left; border-bottom: 1px solid var(--cw-line); }
.sig-table th.num, .sig-table td.num { text-align: left; font-variant-numeric: tabular-nums; }
.sig-table tr.filters th { padding: .2rem .3rem; }
.sig-table tr.filters input, .sig-table tr.filters select { margin: 0; height: 1.9rem; padding: .1rem .45rem; font-size: var(--fs-xs); font-family: var(--cw-mono); text-transform: uppercase; border-radius: var(--r-sm); }
.sig-row td { border-top: 1px solid transparent; border-bottom: 1px solid transparent; }
.sig-row.up td { background: color-mix(in srgb, var(--cw-success) 10%, transparent); color: var(--cw-success); }
.sig-row.down td { background: color-mix(in srgb, var(--cw-danger) 10%, transparent); color: var(--cw-danger); }
.sig-row td:first-child { border-radius: var(--r-sm) 0 0 var(--r-sm); }
.sig-row td:last-child { border-radius: 0 var(--r-sm) var(--r-sm) 0; }
.sig-row td.sym { display: flex; align-items: center; gap: .4rem; }
.pill {
  display: inline-block; min-width: 6.5rem; padding: .25rem .6rem; border-radius: var(--r-sm); text-align: center;
  font-weight: 700; font-size: var(--fs-xs); letter-spacing: .03em; color: #fff; text-decoration: none; overflow: hidden; text-overflow: ellipsis; max-width: 11rem;
}
.sig-row.up .pill { background: var(--cw-success); }
.sig-row.down .pill { background: var(--cw-danger); }
.sig-row .pill:hover { filter: brightness(1.12); color: #fff; }
.sig-row .price a { color: inherit; text-decoration: none; border-bottom: 1px dotted var(--cw-line-strong); }
.sig-row .price a:hover { color: var(--cw-accent-text); border-bottom-color: var(--cw-accent); }
.sig-row td.kind { font-weight: 700; font-size: var(--fs-xs); letter-spacing: .04em; }
.sig-row .sig-time { font-size: var(--fs-xs); }
.sig-row .sig-count { margin: 0; font-size: var(--fs-xs); font-weight: 800; font-family: var(--cw-mono); }
.sig-row.up .sig-count { color: var(--cw-success); }
.sig-row.down .sig-count { color: var(--cw-danger); }
.sig-row.new td { animation: cw-fade var(--t-slow) var(--ease-out) both; }
.sig-row.bump td { animation: cw-fade var(--t-base) var(--ease-out); }
.pager { display: flex; align-items: center; flex-wrap: wrap; gap: .5rem; margin: .4rem 0 0; padding: .3rem .3rem 0; border: 0; border-top: 1px solid var(--cw-line); background: transparent; }
.pager .sizes, .pager .pages { display: inline-flex; align-items: center; gap: .2rem; }
/* Always two lines - page sizes and "Page x of y" on the first, the page numbers right-aligned on the second - so
   a pager never changes height with the number of pages and panels side by side keep the same bottom edge. */
.pager .pages { flex: 1 0 100%; justify-content: flex-end; }
.pager-btn { min-width: 1.7rem; padding: .1rem .4rem; border: 1px solid transparent; border-radius: var(--r-sm); background: transparent; color: var(--cw-muted); font-size: var(--fs-xs); font-family: var(--cw-mono); line-height: 1.5; }
.pager-btn:hover { color: var(--cw-ink); border-color: var(--cw-line-strong); }
.pager-btn.active, .pager-btn.active:disabled { background: var(--cw-ink); color: var(--cw-bg); border-color: var(--cw-ink); opacity: 1; }
.pager-btn:disabled { opacity: .5; }
.pager .gap { color: var(--cw-muted); font-size: var(--fs-xs); padding: 0 .1rem; }
.pager-page { font-size: var(--fs-xs); color: var(--cw-muted); font-variant-numeric: tabular-nums; }

/* Cards. An endless list: the sentinel under the grid fetches the next older page when it scrolls into view. */
.sentinel { height: 1px; }
#cards-more { display: block; width: 100%; margin: .8rem 0 0; padding: .55rem; border: 1px solid var(--cw-line); border-radius: var(--r-pill); background: var(--cw-surface); color: var(--cw-ink); font-size: var(--fs-sm); font-weight: 600; }
#cards-more:hover { border-color: var(--cw-line-strong); }
#cards-more:disabled { opacity: .5; }
.sig-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 270px), 1fr)); gap: .25rem; }
.sig {
  display: flex; flex-direction: column; gap: .45rem; margin: 0; padding: .7rem .8rem;
  border-radius: var(--r-md); border-left: 4px solid var(--cw-muted); background: var(--cw-surface); box-shadow: var(--sh-1);
}
.sig > header, .sig > footer { margin: 0; padding: 0; border: 0; background: transparent; }
.sig.up { border-left-color: var(--cw-success); }
.sig.down { border-left-color: var(--cw-danger); }
.sig.new { animation: cw-rise var(--t-slow) var(--ease-out) both; }
/* A card off the screen is neither laid out nor painted (up to 120 in the list); its last size is kept. */
.sig { content-visibility: auto; contain-intrinsic-size: auto 150px; }
.sig.bump { animation: cw-pop var(--t-slow) var(--ease-out); }
.sig > header { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "symbol time" "meta meta"; align-items: baseline; column-gap: .5rem; row-gap: .3rem; }
.sig-symbol { grid-area: symbol; font-weight: 800; font-size: var(--fs-lg); letter-spacing: -.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sig-time { grid-area: time; font-size: var(--fs-sm); font-family: var(--cw-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sig-meta { grid-area: meta; display: flex; align-items: baseline; gap: .5rem; }
.sig-kind { font-size: var(--fs-xs); font-weight: 800; letter-spacing: .06em; padding: .1rem .5rem; border-radius: var(--r-pill); white-space: nowrap; }
.sig.up .sig-kind { color: var(--cw-success); background: var(--cw-success-soft); }
.sig.down .sig-kind { color: var(--cw-danger); background: var(--cw-danger-soft); }
.sig-ex { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--cw-muted); }
.sig-body { display: flex; justify-content: space-between; align-items: baseline; gap: .6rem; }
.sig-price { font-size: var(--fs-xl); font-weight: 600; font-variant-numeric: tabular-nums; font-family: var(--cw-mono); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sig-pct { font-size: var(--fs-md); font-weight: 700; font-variant-numeric: tabular-nums; font-family: var(--cw-mono); text-align: right; white-space: nowrap; }
.sig.up .sig-pct { color: var(--cw-success); }
.sig.down .sig-pct { color: var(--cw-danger); }
/* Large trades: one whale glyph in the figure's colour, the tier small at its shoulder ("3" = three times the bar). */
.whale { display: inline-flex; align-items: flex-start; vertical-align: -0.22em; white-space: nowrap; min-width: 2.2em; }
/* "$1.31M" then the whale in a fixed slot: in a column (table, coin card) the whale is pinned to the right edge of
   the cell, so it stands still from row to row; elsewhere the two sit side by side */
.large-figure { display: inline-flex; align-items: center; gap: .35em; white-space: nowrap; }
td > .large-figure, .coin-recent-row .pct > .large-figure { display: flex; justify-content: space-between; }
/* a large trade's side as a word on a tint of its colour, one width for both so a column of them lines up */
.kind-word { display: inline-block; min-width: 4.6em; padding: .08rem .45rem; border-radius: var(--r-pill); font-size: var(--fs-xs); font-weight: 700; letter-spacing: .02em; line-height: 1.35; text-align: center; text-transform: uppercase; white-space: nowrap; }
.kind-word.up { color: var(--cw-success); background: var(--cw-success-soft); }
.kind-word.down { color: var(--cw-danger); background: var(--cw-danger-soft); }
.sig-kind .kind-word { padding: 0; min-width: 0; background: none; }
.whale svg { width: 1.35em; height: 1.35em; flex: none; }
.whale b { font-size: .66em; line-height: 1; font-weight: 700; }
/* An exchange's mark: its official symbol in one colour (the text's), one character wide; the name is its title. */
.venue-logo { display: inline-flex; align-items: center; vertical-align: -0.22em; line-height: 1; }
.venue-logo svg { width: 1.25em; height: 1.25em; display: block; flex: none; }
/* Bybit has no symbol, only its wordmark: kept low so it is no wider than a short word. */
.venue-logo svg[data-wide] { width: 2.4em; height: .83em; }
.venue-logo.wide { vertical-align: -0.04em; }
.venue-code { font-family: var(--cw-mono); font-weight: 700; letter-spacing: .04em; }
.sig > footer a.venue-link { padding-inline: .5rem; }
.panel-venues .venue .venue-logo { color: var(--cw-muted); }
/* The signal's kind as one icon (trend line, arrow through a ceiling / floor, arrow in a circle), in the badge's colour. */
.kind-mark { display: inline-flex; vertical-align: -0.28em; line-height: 1; }
.kind-mark svg { width: 1.35em; height: 1.35em; display: block; flex: none; }
/* A burst on a large-trade badge: one bolt of fixed width in the badge's colour, whatever the language. */
.form-mark { display: inline-flex; vertical-align: -0.15em; }
.form-mark svg { width: 1.05em; height: 1.05em; flex: none; }
.sig > footer { display: flex; gap: .3rem; flex-wrap: wrap; align-items: center; margin-top: auto; }
.sig-wave { flex-basis: 100%; font-size: var(--fs-sm); color: var(--cw-muted); text-wrap: pretty; }
.sig-wave-top { font-family: var(--cw-mono); font-variant-numeric: tabular-nums; color: var(--cw-text); }
.sig > footer a {
  font-size: var(--fs-xs); font-weight: 600; padding: .2rem .55rem; border-radius: var(--r-pill);
  background: var(--cw-bg); color: var(--cw-ink); text-decoration: none; box-shadow: 0 0 0 1px var(--cw-line);
  transition: background-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.sig > footer a:hover { background: var(--cw-accent-soft); color: var(--cw-accent-text); }
.sig-count { margin-left: auto; font-size: var(--fs-sm); font-weight: 800; font-family: var(--cw-mono); font-variant-numeric: tabular-nums; }
.sig.up .sig-count { color: var(--cw-success); }
.sig.down .sig-count { color: var(--cw-danger); }

/* A signal that arrived while the reader was elsewhere: a dot on the Signals tab. */
.tabs button.badge::after { content: ""; display: inline-block; width: .45rem; height: .45rem; margin-left: .35rem; border-radius: 50%; background: var(--cw-danger); vertical-align: middle; }

/* Service notices (Notify) are a toast, not a feed entry. */
.notice {
  position: fixed; top: calc(4rem + env(safe-area-inset-top, 0px)); left: 50%; transform: translateX(-50%); z-index: 30;
  max-width: min(92vw, 520px); padding: .6rem .9rem; border-radius: var(--r-md); background: var(--cw-ink); color: var(--cw-bg);
  font-size: var(--fs-sm); box-shadow: var(--sh-2); animation: cw-rise var(--t-base) var(--ease-out) both; transition: opacity var(--t-slow) var(--ease);
}
.notice.out { opacity: 0; }

/* ---- 10. loading ------------------------------------------------------- */
[data-screen="loading"] p { display: flex; align-items: center; gap: .7rem; padding: 3rem 0 0; justify-content: center; }
[data-screen="loading"] p::before {
  content: ""; width: 1.1rem; height: 1.1rem; border-radius: 50%; flex: none;
  border: 2px solid var(--cw-line-strong); border-top-color: var(--cw-accent);
  animation: cw-spin .8s linear infinite;
}

/* ---- 11. reduced motion, hidden ---------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

[hidden] { display: none !important; }

/* 12. Admin actions: two quiet buttons in one cell, and the grant form that takes the place of one of them. */
.act-cell { white-space: nowrap; }
.act-cell .act + .act, .act-cell .act + .grant { margin-left: .3rem; }
.grant { display: inline-flex; align-items: center; gap: .3rem; margin: 0; vertical-align: middle; }
.grant input { width: 4.6rem; margin: 0; height: 1.9rem; padding: .1rem .4rem; font-size: var(--fs-xs); font-family: var(--cw-mono); border-radius: var(--r-sm); }
.grant .cancel { padding: 0 .3rem; color: var(--cw-muted); font-size: var(--fs-md); }

/* 13. Top 20 Live Signals. One table, the exchange selector above it; a row is tinted by the sign of T1, the three
   moves and the four levels carry their own colour, Temp is a heat. On a phone the same row is three tiers - the
   name, the price and T1 first; the other moves and the heat under them; the four levels last - so eleven columns
   read without a sideways scroll. */
.top-head { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin: 0 0 .6rem; }
.top + .panels, .top:not([hidden]) ~ .panels { margin-top: .6rem; }
.sig-row.top-row .price a { color: inherit; text-decoration: none; border-bottom: 1px dotted currentColor; }
.sig-row.top-row .price a:hover { filter: brightness(1.15); }
.top-title { font-weight: 800; font-size: var(--fs-md); letter-spacing: -.01em; }
.top-at { margin-left: auto; font-size: var(--fs-xs); color: var(--cw-muted); font-variant-numeric: tabular-nums; }
.top-table td.time { font-family: var(--cw-mono); font-size: var(--fs-xs); white-space: nowrap; }
.cell-up { color: var(--cw-success); }
.cell-down { color: var(--cw-danger); }
.heat-hot { color: var(--heat-hot); font-weight: 800; }
.heat-cold { color: var(--heat-cold); font-weight: 800; }
.heat-neutral { color: var(--cw-muted); }
.heat-warm { color: var(--heat-warm); font-weight: 700; }
.heat-cool { color: var(--heat-cool); font-weight: 700; }

/* The Top 20 is coloured cell by cell, never by row: a symbol falling over five minutes can be rising over four
   hours and sit above two of its EMAs, and each of those facts has its own cell. Uncoloured cells (the time) are
   neutral. The row class only picks the pill's colour. */
.sig-row.top-row td { background: var(--cw-surface); color: var(--cw-ink); }
.sig-row.top-row td.cell-up { background: color-mix(in srgb, var(--cw-success) 12%, transparent); color: var(--cw-success); }
.sig-row.top-row td.cell-down { background: color-mix(in srgb, var(--cw-danger) 12%, transparent); color: var(--cw-danger); }
.sig-row.top-row td.heat-hot { background: color-mix(in srgb, var(--cw-danger) 16%, transparent); color: var(--cw-danger); }
.sig-row.top-row td.heat-cold { background: color-mix(in srgb, var(--heat-cold) 16%, transparent); color: var(--heat-cold); }
.sig-row.top-row td.heat-neutral { background: var(--cw-surface); color: var(--cw-ink); }
.sig-row.top-row td.heat-warm { background: color-mix(in srgb, var(--heat-warm) 11%, transparent); color: var(--heat-warm); }
.sig-row.top-row td.heat-cool { background: color-mix(in srgb, var(--heat-cool) 11%, transparent); color: var(--heat-cool); }
.sig-row.top-row td.time { color: var(--cw-muted); }
.to-top {
  position: fixed; right: max(1rem, env(safe-area-inset-right, 0px)); bottom: calc(1rem + env(safe-area-inset-bottom, 0px)); z-index: 40;
  width: 2.8rem; height: 2.8rem; padding: 0; border-radius: 50%; border: 1px solid var(--cw-line); background: var(--cw-bg); color: var(--cw-ink);
  box-shadow: var(--sh-2); display: flex; align-items: center; justify-content: center; animation: cw-rise var(--t-base) var(--ease-out) backwards;
}
@media (max-width: 700px) {
  /* The exchange selector is words only, so the words stay (the view switch hides its words for its icons). */
  #top-exchanges { width: 100%; }
  #top-exchanges { width: 100%; }
  #top-exchanges .seg-btn { flex: 1; justify-content: center; }
  #top-exchanges .seg-btn span { display: inline; }
  .top-head { gap: .5rem; }
  .top-title { font-size: var(--fs-sm); }

  /* A row is a small card in three tiers: who and how much (name, price, T1 large); the other moves, the heat
     and the clock; the four levels. Every figure sits under a small label; colour is in the figure, not in a
     box, so the eye reads the numbers and not the tiles. */
  .top-table thead { display: none; }
  .top-table, .top-table tbody { display: block; }
  .top-table tr.top-row {
    display: grid; grid-template-columns: 1fr 1fr 1fr 1.35fr; grid-template-areas: "sym sym price t1" "t2 t3 temp time" "e1 e2 e3 e4";
    gap: .45rem .5rem; padding: .6rem .7rem; margin-bottom: .45rem; border-radius: var(--r-md); background: var(--cw-surface); box-shadow: inset 0 0 0 1px var(--cw-line);
  }
  .sig-row.top-row td, .sig-row.top-row td.cell-up, .sig-row.top-row td.cell-down, .sig-row.top-row td.heat-hot, .sig-row.top-row td.heat-cold, .sig-row.top-row td.heat-neutral, .sig-row.top-row td.heat-warm, .sig-row.top-row td.heat-cool {
    display: block; padding: 0; background: transparent; border-radius: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.25;
  }
  .top-table td.sym { grid-area: sym; display: flex; align-items: center; }
  .top-table td.price { grid-area: price; align-self: center; font-weight: 700; font-size: var(--fs-md); }
  .top-table td.t1 { grid-area: t1; align-self: center; text-align: right; font-weight: 800; font-size: var(--fs-md); min-width: 0; }
  .top-table td.sym .pill { max-width: 100%; }
  .top-table td.t2 { grid-area: t2; } .top-table td.t3 { grid-area: t3; } .top-table td.temp { grid-area: temp; } .top-table td.time { grid-area: time; text-align: right; }
  .top-table td.e1 { grid-area: e1; } .top-table td.e2 { grid-area: e2; } .top-table td.e3 { grid-area: e3; } .top-table td.e4 { grid-area: e4; }
  .top-table td[data-l]::before { content: attr(data-l); display: block; font-size: .62rem; font-weight: 700; letter-spacing: .06em; color: var(--cw-muted); }
  .top-table td.t1::before { content: none; }
  .top-table td.t2, .top-table td.t3, .top-table td.temp { font-weight: 700; font-size: var(--fs-sm); }
  .top-table td.e1, .top-table td.e2, .top-table td.e3, .top-table td.e4 { font-size: var(--fs-xs); }
  .sig-row.top-row td.heat-neutral { color: var(--cw-ink); }
}

/* ---- Technical Premium Signal (docs/technical-signal-samples.md) --------
   One card per thread, the same card through every stage. A computer shows the cards two or three abreast with
   the details open; a phone stacks them and folds the details behind one tap. Colour follows the direction of
   the break; the stage is a small chip; the confidence is a bar, because 0.83 reads slower than a bar does. */
body[data-tab="technical"] main.page,
body[data-tab="technical"] .topbar { max-width: none; }
/* The Technical tool row, the Signals one's twin: sticky under the top bar, one line of title, search, funnel and
   the applied tags (scrolling sideways when long). The description lives in the title's tooltip. */
.tech-head {
  position: sticky; top: var(--cw-topbar-h); z-index: 6;
  display: flex; align-items: center; gap: .5rem; margin: 0 0 .6rem; padding: .35rem 0; background: var(--cw-bg);
}
.tech-title { flex: none; min-width: 0; }
.tech-title h3 { margin: 0 .3rem 0 0; font-size: var(--fs-md); font-weight: 800; letter-spacing: -.01em; white-space: nowrap; cursor: help; }
.tech-head .applied { flex: 1 1 auto; min-width: 0; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-top: 0; }
.tech-head .applied::-webkit-scrollbar { display: none; }
.tech-head .applied .tag { flex: none; }
.tech-filters { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.tech-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 380px), 1fr)); gap: .25rem; align-items: start; }
.tech {
  display: flex; flex-direction: column; gap: .5rem; margin: 0; padding: .8rem .9rem;
  border-radius: var(--r-md); border-left: 4px solid var(--cw-muted); background: var(--cw-surface); box-shadow: var(--sh-1);
}
.tech.up { border-left-color: var(--cw-success); }
/* The first load: placeholder cards that pulse until the threads arrive (still, without the pulse, under reduced motion). */
.tech-skel { gap: .65rem; border-left-color: var(--cw-line-strong); }
.tech-skel .skel { display: block; height: .8rem; background: var(--cw-line); animation: cw-skel-pulse 1.3s var(--ease) infinite; }
.tech-skel header .skel { display: inline-block; }
.tech-skel .s-sym { width: 5.5rem; height: 1.35rem; }
.tech-skel .s-tf { width: 2.4rem; height: 1.1rem; border-radius: var(--r-pill); }
.tech-skel .s-stage { width: 4.6rem; height: 1.1rem; margin-left: auto; border-radius: var(--r-pill); }
.tech-skel .s-line { width: 92%; }
.tech-skel .s-line.short { width: 62%; }
.tech-skel .s-bar { width: 100%; height: .45rem; border-radius: var(--r-pill); }
.tech-skel:nth-child(2) .skel { animation-delay: .15s; }
.tech-skel:nth-child(3) .skel { animation-delay: .3s; }
.tech-skel:nth-child(4) .skel { animation-delay: .45s; }
@keyframes cw-skel-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
.tech.down { border-left-color: var(--cw-danger); }
/* A closed card (found by the search, or with Open only off) reads as history: no colour stripe, no fill, muted
   words, a "Closed" tag, and the result line carrying the only colour. */
.tech.closed { background: transparent; box-shadow: inset 0 0 0 1px var(--cw-line); border-left-color: var(--cw-line-strong); }
.tech.closed .tech-break, .tech.closed .tech-trends, .tech.closed .tech-note { color: var(--cw-muted); }
.tech.closed .tech-conf-bar i { background: var(--cw-muted); }
.tech.closed .tech-stage { background: color-mix(in srgb, var(--cw-muted) 14%, transparent); color: var(--cw-muted); }
.tech-closed-tag { font-size: var(--fs-xs); font-weight: 800; letter-spacing: .05em; text-transform: uppercase; padding: .12rem .5rem; border-radius: var(--r-pill); color: var(--cw-bg); background: var(--cw-muted); }
.tech-closed-tag[hidden] { display: none; }
/* The coin's name reads as a button: an outlined chip with a chart mark. */
.tech-symbol { display: inline-flex; align-items: center; gap: .35rem; padding: .15rem .55rem; border-radius: var(--r-sm); color: var(--cw-ink); text-decoration: none; box-shadow: 0 0 0 1px var(--cw-line-strong); cursor: pointer; transition: background-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease); }
.tech-symbol svg { color: var(--cw-accent-text); flex: none; }
.tech-symbol:hover, .tech-symbol:focus-visible { background: var(--cw-accent-soft); box-shadow: 0 0 0 1px var(--cw-accent); color: var(--cw-ink); }
.tech-live-dot { display: inline-block; width: .5rem; height: .5rem; margin-right: .4rem; border-radius: 50%; background: currentColor; vertical-align: middle; animation: cw-tech-live 1.4s var(--ease) infinite; }
@keyframes cw-tech-live { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
.tech-now { font-weight: 700; color: var(--cw-ink); }
.tech.new { animation: cw-rise var(--t-slow) var(--ease-out) both; }
.tech.bump { animation: cw-pop var(--t-slow) var(--ease-out); }
.tech > header { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin: 0; padding: 0; border: 0; background: transparent; }
.tech-symbol-name { font-weight: 800; font-size: var(--fs-lg); letter-spacing: -.01em; }
.tech-tf { font-size: var(--fs-xs); font-weight: 700; padding: .1rem .45rem; border-radius: var(--r-pill); background: var(--cw-bg); color: var(--cw-ink); box-shadow: 0 0 0 1px var(--cw-line); }
/* A line card's shape (trend line, triangle, level): the timeframe chip's outline in the accent's ink. */
.tech-pattern { font-size: var(--fs-xs); font-weight: 700; padding: .1rem .45rem; border-radius: var(--r-pill); color: var(--cw-accent-text); box-shadow: 0 0 0 1px currentColor; white-space: nowrap; }
.tech-stage { font-size: var(--fs-xs); font-weight: 800; letter-spacing: .05em; text-transform: uppercase; padding: .12rem .5rem; border-radius: var(--r-pill); background: var(--cw-accent-soft); color: var(--cw-accent-text); }
.tech-stage[data-stage="developing"] { background: var(--cw-warn-soft); color: var(--cw-warn); }
.tech-stage[data-stage="withdrawn"] { background: var(--cw-danger-soft); color: var(--cw-danger); }
.tech-stage[data-stage="retest"] { background: var(--cw-success-soft); color: var(--cw-success); }
.tech-stage[data-stage="ran"] { background: color-mix(in srgb, var(--cw-muted) 16%, transparent); color: var(--cw-muted); }
.tech-time { margin-left: auto; font-size: var(--fs-xs); color: var(--cw-muted); font-variant-numeric: tabular-nums; }
.tech-ex { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--cw-muted); }
.tech-break { margin: 0; font-weight: 600; font-size: var(--fs-md); line-height: 1.35; }
.tech.up .tech-break { color: var(--cw-success); }
.tech.down .tech-break { color: var(--cw-danger); }
.tech-trend { display: flex; align-items: center; justify-content: space-between; gap: .8rem; flex-wrap: wrap; font-size: var(--fs-sm); }
.tech-trends { color: var(--cw-ink); font-weight: 600; }
.tech-conf { display: inline-grid; grid-template-columns: auto 72px auto; gap: .45rem; align-items: center; }
.tech-conf-label { font-size: var(--fs-xs); color: var(--cw-muted); text-transform: uppercase; letter-spacing: .05em; }
.tech-conf-bar { display: block; height: 6px; border-radius: 3px; background: color-mix(in srgb, var(--cw-muted) 22%, transparent); overflow: hidden; }
.tech-conf-bar i { display: block; height: 100%; background: var(--cw-accent); transition: width var(--t-slow) var(--ease); }
.tech-conf-value { font-size: var(--fs-sm); font-weight: 700; }
.tech-note { margin: 0; font-size: var(--fs-sm); }
.tech-more { margin: 0; padding: 0; border: 0; background: transparent; }
.tech-more > summary { padding: .2rem 0; font-size: var(--fs-xs); font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--cw-muted); cursor: pointer; list-style: none; }
.tech-more > summary::-webkit-details-marker { display: none; }
.tech-more > summary::before { content: "▸ "; }
.tech-more[open] > summary::before { content: "▾ "; }
.tech-detail { display: grid; gap: .5rem; padding-top: .35rem; }
.tech-row { display: grid; grid-template-columns: 6.2rem minmax(0, 1fr); gap: .2rem .6rem; font-size: var(--fs-sm); line-height: 1.4; }
.tech-label { font-size: var(--fs-xs); font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--cw-muted); padding-top: .1rem; }
.tech-value { min-width: 0; overflow-wrap: anywhere; }
.tech-plan { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: .4rem; font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.tech-plan div { padding: .35rem .5rem; border-radius: var(--r-sm); background: var(--cw-bg); box-shadow: 0 0 0 1px var(--cw-line); display: grid; gap: .1rem; }
.tech-plan small { font-size: .62rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--cw-muted); }
.tech-plan .stop { box-shadow: inset 3px 0 0 var(--cw-danger), 0 0 0 1px var(--cw-line); }
.tech-plan .target { box-shadow: inset 3px 0 0 var(--cw-success), 0 0 0 1px var(--cw-line); }
/* The scorecard over the cards, and the result on each card. */
.tech-score { display: flex; align-items: baseline; justify-content: space-between; gap: .3rem 1rem; flex-wrap: wrap; margin: 0 0 .6rem; padding: .3rem .7rem; border-radius: var(--r-md); background: var(--cw-surface); box-shadow: inset 0 0 0 1px var(--cw-line); font-size: var(--fs-sm); }
.tech-score-all { font-weight: 700; }
.tech-score-parts { display: flex; gap: .9rem; flex-wrap: wrap; font-size: var(--fs-xs); }
.tech-score-parts .pos { color: var(--cw-success); }
.tech-score-parts .neg { color: var(--cw-danger); }
/* The search as wide as on the Signals page and no wider: the title and its line keep the rest of the row. */
.tech-search { flex: 0 1 20rem; width: 20rem; min-width: 10rem; }
.tech-filters { flex: none; justify-content: flex-start; flex-wrap: nowrap; gap: .5rem; }

.tech-result { display: grid; gap: .35rem; padding: .5rem .6rem; border-radius: var(--r-sm); background: var(--cw-bg); box-shadow: inset 0 0 0 1px var(--cw-line); }
.tech-result.pos { box-shadow: inset 3px 0 0 var(--cw-success), inset 0 0 0 1px var(--cw-line); }
.tech-result.neg { box-shadow: inset 3px 0 0 var(--cw-danger), inset 0 0 0 1px var(--cw-line); }
.tech-result-line { font-size: var(--fs-sm); font-weight: 700; }
.tech-result.pos .tech-result-line { color: var(--cw-success); }
.tech-result.neg .tech-result-line { color: var(--cw-danger); }
.tech-result-meta { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; font-size: var(--fs-xs); }
.tech-chip { padding: .05rem .45rem; border-radius: var(--r-pill); color: var(--cw-muted); box-shadow: 0 0 0 1px var(--cw-line); }
.tech-chip.hit { color: var(--cw-success); background: var(--cw-success-soft); box-shadow: none; font-weight: 700; }
.tech-chip.stop.hit { color: var(--cw-danger); background: var(--cw-danger-soft); }
.tech-range { margin-left: auto; color: var(--cw-muted); }
/* Details are closed by default; until opened once, the summary pulses so a reader sees there is more. */
.tech-more > summary { display: inline-flex; align-items: center; gap: .3rem; padding: .25rem .6rem; border-radius: var(--r-pill); color: var(--cw-accent-text); background: var(--cw-accent-soft); }
.tech-more.unseen:not([open]) > summary { animation: cw-tech-pulse 1.6s var(--ease) infinite; }
@keyframes cw-tech-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--cw-accent) 45%, transparent); opacity: 1; }
  50% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--cw-accent) 0%, transparent); opacity: .7; }
}
.tech-follow { margin: 0; padding-top: .35rem; border-top: 1px dashed var(--cw-line); font-size: var(--fs-sm); font-weight: 600; }
.tech[data-stage="withdrawn"] .tech-follow { color: var(--cw-danger); }
.tech[data-stage="retest"] .tech-follow { color: var(--cw-success); }
.tech[data-stage="ran"] .tech-follow { color: var(--cw-muted); }
@media (max-width: 700px) {
  /* a phone: the title and the tools on one line (the title short, the search filling), the tags under them */
  .tech-head { flex-wrap: wrap; row-gap: .35rem; }
  .tech-title { display: none; }   /* the tab already says Technical; the line is the tools */
  .tech-filters { flex: 1 1 auto; }
  .tech-search { flex: 1 1 auto; width: auto; }
  .tech-head .applied { flex-basis: 100%; }
  .tech-row { grid-template-columns: 1fr; }
  .tech-conf { grid-template-columns: auto 1fr auto; width: 100%; }
}

/* ---- coin card (docs/coin-card.md) ------------------------------------
   One dialog, computer and tablet widths only: the market as the exchange shows it, then the chart filling
   whatever height is left. The trigger is the coin's name; on a wide screen it reads as a button. */
@media (min-width: 701px) {
  .sig-symbol[data-coin], .pill[data-coin] { cursor: pointer; }
  .sig-symbol[data-coin]:hover { color: var(--cw-accent-text); }
}
/* Pico styles a bare <dialog> as the full-screen overlay and expects an <article> inside; this dialog is the
   card itself, so the overlay properties are taken back and ::backdrop is the overlay. */
.coin { position: fixed; inset: var(--cw-top-inset, 0px) 0 var(--cw-bottom-inset, 0px) 0; width: min(96vw, 1100px); min-width: 0; max-width: none; height: min(92vh, 900px); min-height: 0; max-height: calc(92vh - var(--cw-top-inset, 0px) - var(--cw-bottom-inset, 0px)); margin: auto; padding: 0; border: 0; border-radius: var(--r-lg); background: var(--cw-bg); color: var(--cw-ink); box-shadow: var(--sh-2); backdrop-filter: none; display: none; flex-direction: column; align-items: stretch; justify-content: flex-start; overflow: hidden; }
.coin[open] { display: flex; animation: cw-rise var(--t-base) var(--ease-out) backwards; }
.coin::backdrop { background: rgb(0 0 0 / .55); backdrop-filter: blur(2px); }
body.coin-open { overflow: hidden; }
.coin-head { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 1rem; padding: 1rem 1.1rem .6rem; }
.coin-name { display: flex; flex-direction: column; min-width: 0; }
.coin-symbol { font-size: var(--fs-xl); font-weight: 800; letter-spacing: -.01em; line-height: 1.1; }
.coin-market { font-size: var(--fs-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The full name beside the ticker, and what it is when it is not a crypto coin (Stock, Commodity, …). */
.coin-title { display: flex; align-items: baseline; gap: .55rem; flex-wrap: wrap; min-width: 0; }
.coin-fullname { font-size: var(--fs-md); font-weight: 600; color: var(--cw-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.coin-class { align-self: center; padding: .1rem .55rem; border-radius: var(--r-pill); font-size: var(--fs-xs); font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--cw-accent-text); background: var(--cw-accent-soft); white-space: nowrap; }
.coin-quote { display: flex; align-items: baseline; gap: .7rem; white-space: nowrap; }
.coin-price { font-size: var(--fs-xl); font-weight: 700; font-variant-numeric: tabular-nums; transition: color var(--t-base) var(--ease); }
.coin-price.up { color: var(--cw-success); }
.coin-price.down { color: var(--cw-danger); }
.coin-change { font-size: var(--fs-md); font-weight: 700; padding: .1rem .5rem; border-radius: var(--r-pill); }
.coin-change.up { color: var(--cw-success); background: var(--cw-success-soft); }
.coin-change.down { color: var(--cw-danger); background: var(--cw-danger-soft); }
.coin-live { display: inline-flex; align-items: center; gap: .35rem; font-size: var(--fs-xs); color: var(--cw-muted); }
.coin-live .dot { width: .5rem; height: .5rem; border-radius: 50%; background: var(--cw-muted); }
.coin-live.on .dot { background: var(--cw-success); animation: cw-beat 1.6s ease-in-out infinite; }
.coin-live.off .dot { background: var(--cw-danger); }
.coin-close { width: 2.2rem; height: 2.2rem; margin: 0; padding: 0; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: 50%; color: var(--cw-muted); background: var(--cw-surface); box-shadow: none; }
.coin-close svg { display: block; }
.coin-close:hover { color: var(--cw-ink); }
.coin-stats { display: flex; flex-wrap: wrap; gap: .4rem 1.4rem; padding: 0 1.1rem .5rem; font-size: var(--fs-sm); }
.coin-stats div { display: flex; flex-direction: column; min-width: 6.5rem; }
.coin-stats dt, .coin-stats .k { font-size: var(--fs-xs); font-family: var(--cw-font); color: var(--cw-muted); }
.coin-stats .v { font-variant-numeric: tabular-nums; font-weight: 600; }
.coin-stats .v.up { color: var(--cw-success); }
.coin-stats .v.down { color: var(--cw-danger); }
/* The queue: the coin's last three signals, newest on top; a live arrival slides in and glows once. */
.coin-signal { padding: .5rem 1.1rem .6rem; border-top: 1px solid var(--cw-line); }
.coin-recent-head { display: flex; align-items: baseline; gap: .8rem; margin-bottom: .35rem; }
.coin-recent-title { font-size: var(--fs-xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--cw-muted); }
.coin-top-since { font-size: var(--fs-xs); color: var(--cw-muted); }
.coin-recent-empty { margin: 0; font-size: var(--fs-sm); }
.coin-recent { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .25rem; }
.coin-recent-row { display: grid; grid-template-columns: 8.5rem 7rem minmax(6rem, auto) minmax(7rem, 1fr) auto; align-items: center; gap: .8rem; margin: 0; padding: .3rem .6rem; border-radius: var(--r-sm); font-size: var(--fs-sm); background: var(--cw-surface); border-left: 3px solid transparent; opacity: .72; }
.coin-recent-row.latest { opacity: 1; }
.coin-recent-row.up { border-left-color: var(--cw-success); }
.coin-recent-row.down { border-left-color: var(--cw-danger); }
.coin-recent-row .kind { font-weight: 800; font-size: var(--fs-xs); letter-spacing: .04em; white-space: nowrap; }
.coin-recent-row.up .kind, .coin-recent-row.up .pct { color: var(--cw-success); }
.coin-recent-row.down .kind, .coin-recent-row.down .pct { color: var(--cw-danger); }
.coin-recent-row .pct { font-weight: 700; white-space: nowrap; }
.coin-recent-row .when { font-size: var(--fs-xs); color: var(--cw-muted); }
.coin-recent-row .since { font-weight: 700; text-align: right; }
.coin-recent-row .since.up { color: var(--cw-success); }
.coin-recent-row .since.down { color: var(--cw-danger); }
.coin-recent-row.fresh { animation: cw-slide-in var(--t-slow) var(--ease-out) both, coin-glow 2.4s var(--ease-out) both; }
@keyframes coin-glow { 0% { box-shadow: 0 0 0 2px var(--cw-accent); } 100% { box-shadow: 0 0 0 0 transparent; } }

/* Loading, said in words and shapes: a spinner with "Connecting to Binance…", and shimmering bars where the
   figures will be, sized like them so nothing jumps. */
.skel { display: inline-block; vertical-align: middle; border-radius: var(--r-sm); background: linear-gradient(90deg, var(--cw-surface) 0%, var(--cw-line-strong) 50%, var(--cw-surface) 100%); background-size: 200% 100%; animation: coin-shimmer 1.2s linear infinite; }
.skel-price { width: 7.5rem; height: 1.7rem; }
.skel-change { width: 4.2rem; height: 1.2rem; border-radius: var(--r-pill); }
.skel-cell { display: flex; flex-direction: column; gap: .3rem; min-width: 6.5rem; }
.skel-cell .skel-k { width: 5rem; height: .6rem; }
.skel-cell .skel-v { width: 4rem; height: .9rem; }
@keyframes coin-shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }
.coin-live.connecting .dot { background: transparent; border: 2px solid var(--cw-line-strong); border-top-color: var(--cw-accent); width: .7rem; height: .7rem; animation: cw-spin .8s linear infinite; }
.coin-live.connecting { color: var(--cw-ink); }
.coin-chart-loading { position: absolute; inset: 0; z-index: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .7rem; background: var(--cw-surface); color: var(--cw-muted); font-size: var(--fs-sm); pointer-events: none; animation: cw-fade var(--t-base) var(--ease-out) both; }
.coin-chart-loading .spinner { width: 1.6rem; height: 1.6rem; border-radius: 50%; border: 3px solid var(--cw-line-strong); border-top-color: var(--cw-accent); animation: cw-spin .8s linear infinite; }
.coin-links { display: flex; flex-wrap: wrap; gap: .4rem; padding: 0 1.1rem .7rem; }
.coin-links a { font-size: var(--fs-xs); font-weight: 600; padding: .3rem .7rem; border-radius: var(--r-pill); background: var(--cw-surface); color: var(--cw-ink); text-decoration: none; border: 1px solid var(--cw-line); }
.coin-links a:hover { border-color: var(--cw-accent); color: var(--cw-accent-text); }
/* An exchange's own name for the coin, where it differs from the one on screen (kPEPE, XBT). */
.coin-links a small, .venue-links a small { font-weight: 400; opacity: .7; margin-left: .35em; font-family: var(--cw-mono); }
.venue-links { display: flex; flex-wrap: wrap; gap: .35rem; }
.venue-links a { font-size: var(--fs-xs); font-weight: 600; padding: .2rem .6rem; border-radius: var(--r-pill); background: var(--cw-surface); color: var(--cw-ink); text-decoration: none; border: 1px solid var(--cw-line); }
.venue-links a:hover { border-color: var(--cw-accent); color: var(--cw-accent-text); }
.coin-chart { flex: 1 1 auto; min-height: 360px; position: relative; border-top: 1px solid var(--cw-line); background: var(--cw-surface); }
.coin-chart > div:not(.coin-chart-loading):not(.coin-chart-fallback), .coin-chart iframe { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }
.coin-chart .coin-chart-fallback { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .6rem; color: var(--cw-muted); font-size: var(--fs-sm); }
.coin-chart .coin-chart-fallback a { font-weight: 600; }

/* ---- font look (Settings → Text) ---------------------------------------
   smooth: the default, Inter with grey-scale smoothing - soft and easy on the eyes.
   sharp:  the platform's own hinted fonts (Segoe UI / SF / Roboto, Consolas / Menlo) without smoothing, so glyphs
           snap to the pixel grid: crisp on screen shares and recordings.
   bold:   sharp, 8 % larger, a step heavier and with stronger secondary text - readable in a compressed live
           stream or on a projector. */
:root[data-font="sharp"], :root[data-font="bold"] {
  --cw-font: "Segoe UI", system-ui, -apple-system, Roboto, "Helvetica Neue", Arial, sans-serif;
  --cw-mono: Consolas, "Cascadia Mono", Menlo, "DejaVu Sans Mono", monospace;
  --pico-font-family: var(--cw-font);
}
:root[data-font="sharp"] body, :root[data-font="bold"] body {
  -webkit-font-smoothing: auto;
  -moz-osx-font-smoothing: auto;
  text-rendering: optimizeSpeed;
  font-feature-settings: normal;
}
:root[data-font="bold"] { font-size: 108%; --cw-muted: color-mix(in srgb, var(--cw-ink) 72%, var(--cw-bg)); }
:root[data-font="bold"] body { font-weight: 500; letter-spacing: .005em; }
:root[data-font="bold"] .mono, :root[data-font="bold"] .sig-table, :root[data-font="bold"] .coin-price { font-weight: 600; }
.font-seg { display: flex; width: 100%; margin: .2rem 0 .3rem; }
.font-seg .seg-btn { flex: 1 1 0; justify-content: center; }
.font-hint { font-size: var(--fs-xs); margin-top: 0; }

/* ---- colours (Settings → Colours) --------------------------------------
   Colour-blind friendly: up and down are blue and vermilion instead of green and red (told apart with any of the
   common colour-vision deficiencies), and the Temp heat runs from the Okabe-Ito palette. The ▲ ▼ arrows stay, so
   direction is never colour alone. */
:root[data-palette="cvd"] {
  --cw-success: #1f77d0;
  --cw-danger: #e0661b;
  --heat-hot: #d55e00; --heat-warm: #e69f00; --heat-cool: #56b4e9; --heat-cold: #0072b2;
}
.swatch { display: inline-flex; gap: 2px; margin-right: .35rem; vertical-align: middle; }
.swatch i { width: .55rem; height: .55rem; border-radius: 2px; }
.swatch i.up { background: #16a34a; } .swatch i.down { background: #dc2626; }
.swatch.cvd i.up { background: #1f77d0; } .swatch.cvd i.down { background: #e0661b; }

/* ---- Top 20 pager in the header -----------------------------------------
   One line next to the title (sizes · pages · "Page 1 of 2"), not the two-line table footer: the Top 20 is one
   short table, and a footer under it merged visually with the source tables below. The block itself ends with a
   rule and some air, so the two parts of the screen read as two. */
.top-head .top-pager { display: inline-flex; flex-wrap: nowrap; align-items: center; gap: .6rem; margin: 0 0 0 auto; padding: 0; border: 0; }
.top-head .top-pager .pages { flex: none; justify-content: flex-start; }
.top-head .top-pager .sizes { padding-right: .6rem; border-right: 1px solid var(--cw-line); }
.top-head .top-at { margin-left: .4rem; }
#signals-top { margin-bottom: .6rem; padding-bottom: .4rem; border-bottom: 1px solid var(--cw-line); }
@media (max-width: 700px) {
  .top-head .top-pager { order: 5; margin: 0; width: 100%; justify-content: space-between; }
  #signals-top { border-bottom: 0; padding-bottom: 0; }
}

/* ---- home page (home.js): the Mini App's Home tab and the public landing at / --------------------------------
   One page that sells by showing: a large claim, the live numbers, real signals an hour late drawn exactly like
   the cards a subscriber gets, then every feature as a tile, the plans and the questions. Wider than the payment
   column, narrower than the signals grid: a page that is read, not scanned. */
:root { --cw-home: 1180px; }
body[data-tab="home"] main.page, body[data-tab="home"] .topbar,
body.landing main.page, body.landing .topbar { max-width: var(--cw-home); }

.home { display: flex; flex-direction: column; gap: clamp(2.4rem, 6vw, 4.5rem); padding-block: .5rem 1rem; position: relative; isolation: isolate; }
.home h1 { font-size: clamp(2.1rem, 6.2vw, 3.7rem); line-height: 1.04; letter-spacing: -.04em; font-weight: 800; margin: .9rem 0 1rem; text-wrap: balance; }
.home h2 { font-size: clamp(1.45rem, 3.6vw, 2.15rem); line-height: 1.12; letter-spacing: -.03em; font-weight: 800; margin: 0 0 .55rem; text-wrap: balance; }
.home h3 { font-size: var(--fs-lg); font-weight: 800; letter-spacing: -.02em; margin: 0; line-height: 1.25; }
.home p { margin: 0; }
.home ul, .home ol { margin: 0; padding: 0; }
.home li { list-style: none; margin: 0; }
.home-sub { color: var(--cw-muted); font-size: var(--fs-md); line-height: 1.55; max-width: 46rem; margin: 0 0 1.4rem !important; }
.home-note { margin-top: .9rem !important; color: var(--cw-muted); font-size: var(--fs-sm); }

/* hero: the claim on the left, an hour-old slice of the feed on the right (under it on a phone) */
.home-hero {
  display: grid; grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr); gap: clamp(1.6rem, 4vw, 3.2rem);
  align-items: center; padding-top: clamp(.4rem, 3vw, 2.4rem); isolation: isolate;
}
@media (max-width: 860px) { .home-hero { grid-template-columns: minmax(0, 1fr); } }
.home-live {
  display: inline-flex; align-items: center; gap: .5rem; padding: .3rem .85rem .3rem .65rem; border-radius: var(--r-pill);
  background: var(--cw-success-soft); color: var(--cw-success); font-size: var(--fs-sm); font-weight: 700; font-variant-numeric: tabular-nums;
}
.live-dot { width: .5rem; height: .5rem; border-radius: 50%; background: currentColor; animation: cw-beat 1.6s ease-in-out infinite; flex: none; }
.home-lead { font-size: clamp(1rem, 2vw, 1.14rem); line-height: 1.6; color: var(--cw-muted); max-width: 36rem; }
.home-actions { display: flex; flex-wrap: wrap; gap: .6rem; margin: 1.6rem 0 1.5rem; }
.home .home-cta { width: auto; margin: 0; padding: .8rem 1.6rem; border-radius: var(--r-pill); font-weight: 700; font-size: var(--fs-md); }
.home-ghost {
  margin: 0; padding: .8rem 1.35rem; border-radius: var(--r-pill); border: 1px solid var(--cw-line-strong);
  background: transparent; color: var(--cw-ink); font-weight: 600; font-size: var(--fs-md); cursor: pointer; box-shadow: none;
}
.home-ghost:hover { border-color: var(--cw-ink); }
.home-from { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem 1rem; color: var(--cw-muted); font-size: var(--fs-sm); }
.home-from-marks { display: flex; flex-wrap: wrap; gap: .35rem 1.1rem; color: var(--cw-ink); font-weight: 650; }
.home-from-item { display: inline-flex; align-items: center; gap: .15rem; white-space: nowrap; }

.home-feed {
  position: relative; border-radius: var(--r-lg); padding: .9rem; background: var(--cw-surface);
  border: 1px solid var(--cw-line); box-shadow: var(--sh-2);
}
.home-feed::before {
  content: ""; position: absolute; inset: -18% -12% 20%; z-index: -1; pointer-events: none;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--cw-accent) 22%, transparent), transparent);
}
.home-feed > header { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin: 0 0 .7rem; padding: 0 .2rem; background: none; border: 0; }
.home-feed-title { font-weight: 800; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .07em; color: var(--cw-muted); }
.home-chip {
  display: inline-flex; align-items: center; padding: .15rem .55rem; border-radius: var(--r-pill); background: var(--cw-bg);
  box-shadow: 0 0 0 1px var(--cw-line); font-size: var(--fs-xs); font-weight: 700; color: var(--cw-muted); white-space: nowrap;
}
.home-feed-list { display: grid; gap: .5rem; max-height: 27rem; overflow: hidden; -webkit-mask-image: linear-gradient(180deg, #000 82%, transparent); mask-image: linear-gradient(180deg, #000 82%, transparent); }
.home-feed-list .sig { background: var(--cw-bg); box-shadow: 0 0 0 1px var(--cw-line); animation: cw-rise var(--t-slow) var(--ease-out) backwards; }
.home-feed-list .sig:nth-child(2) { animation-delay: .06s; }
.home-feed-list .sig:nth-child(3) { animation-delay: .12s; }
.home-feed-list .sig:nth-child(4) { animation-delay: .18s; }
.home-feed-list .sig:nth-child(n+5) { animation-delay: .24s; }
@media (min-width: 560px) and (max-width: 860px) { .home-feed-list { grid-template-columns: 1fr 1fr; max-height: 19rem; } }
.home-feed-empty { padding: 2.5rem 0; text-align: center; font-size: var(--fs-sm); }
.home-feed-note { margin-top: .75rem !important; font-size: var(--fs-xs); color: var(--cw-muted); text-align: center; }

/* the numbers: one band, four cells */
.home-stats {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border: 1px solid var(--cw-line);
  border-radius: var(--r-lg); overflow: hidden; background: var(--cw-surface);
}
.home-stat { padding: 1.2rem 1.35rem; display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
.home-stat + .home-stat { border-left: 1px solid var(--cw-line); }
.home-stat b { font-size: clamp(1.7rem, 4vw, 2.6rem); font-weight: 800; letter-spacing: -.04em; font-variant-numeric: tabular-nums; line-height: 1.05; }
.home-stat span { color: var(--cw-muted); font-size: var(--fs-sm); line-height: 1.35; }
@media (max-width: 700px) {
  .home-stats { grid-template-columns: 1fr 1fr; }
  .home-stat:nth-child(3) { border-left: 0; }
  .home-stat:nth-child(n+3) { border-top: 1px solid var(--cw-line); }
}

/* the last hours by exchange: a small data table, a bar per cell */
.home-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); margin: 0; }
.home-table th {
  text-align: left; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .05em; color: var(--cw-muted);
  font-weight: 700; padding: .55rem .7rem; border-bottom: 1px solid var(--cw-line); background: none; white-space: nowrap;
}
.home-table th.num { text-align: right; }
.home-table td { padding: .75rem .7rem; border-bottom: 1px solid var(--cw-line); background: none; vertical-align: middle; white-space: nowrap; }
.home-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.home-table td.ex { font-weight: 700; }
.home-table td.num b { font-family: var(--cw-mono); font-weight: 600; display: inline-block; min-width: 6ch; text-align: right; }
.home-table td.total { font-family: var(--cw-mono); font-weight: 800; }
.home-table td.perps { color: var(--cw-muted); font-family: var(--cw-mono); }
.home-bar { display: inline-block; width: 4.5rem; height: .35rem; border-radius: var(--r-pill); background: var(--cw-line); margin-right: .65rem; vertical-align: middle; overflow: hidden; }
.home-bar i { display: block; height: 100%; width: 0; background: var(--cw-accent); border-radius: inherit; transition: width var(--t-slow) var(--ease-out); }
@media (max-width: 640px) { .home-bar, .home-table .perps { display: none; } }
/* A phone: the logo alone names the exchange, and the headers may wrap, so five columns fit without a side scroll. */
@media (max-width: 480px) {
  .home-table .ex-name { display: none; }
  .home-table th { white-space: normal; font-size: .6rem; vertical-align: bottom; }
  .home-table th, .home-table td { padding-inline: .4rem; }
  .home-table td.ex { font-size: 1.1rem; }
}

/* features: a bento of tiles, three columns on a computer, two on a tablet, one on a phone */
.home-bento { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .9rem; }
.home-tile {
  display: flex; flex-direction: column; gap: .75rem; padding: 1.25rem; margin: 0; min-width: 0;
  border-radius: var(--r-lg); background: var(--cw-surface); border: 1px solid var(--cw-line); box-shadow: none;
}
.home-tile.span-2 { grid-column: span 2; }
.home-tile.span-3 { grid-column: span 3; }
@media (max-width: 860px) { .home-bento { grid-template-columns: 1fr 1fr; } .home-tile.span-3 { grid-column: span 2; } }
@media (max-width: 600px) { .home-bento { grid-template-columns: minmax(0, 1fr); } .home-tile.span-2, .home-tile.span-3 { grid-column: auto; } }
.home-tile > p { color: var(--cw-muted); font-size: var(--fs-sm); line-height: 1.55; }
.home-tile-head { display: flex; align-items: center; gap: .65rem; }
.home-icon {
  display: inline-flex; align-items: center; justify-content: center; width: 2.2rem; height: 2.2rem; flex: none;
  border-radius: var(--r-md); background: var(--cw-accent-soft); color: var(--cw-accent-text);
}
.home-icon svg { width: 1.2rem; height: 1.2rem; display: block; }
.home-icon.sm { width: 1.5rem; height: 1.5rem; border-radius: var(--r-sm); }
.home-icon.sm svg { width: .85rem; height: .85rem; }

/* One mark column for all three rows (subgrid; 4.5rem where subgrid is unknown), the up and down marks one above the
   other, so the BUY / SELL words never push their text further right than the arrows do (owner, 2026-10-10). */
.home-kinds { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: .5rem; margin-top: auto !important; }
.home-kinds li {
  grid-column: 1 / -1; display: grid; grid-template-columns: 4.5rem minmax(0, 1fr); grid-template-columns: subgrid;
  column-gap: .85rem; align-items: center; padding: .65rem .8rem; border-radius: var(--r-md); background: var(--cw-bg);
}
.home-kinds li > span:last-child { display: flex; flex-direction: column; gap: .1rem; font-size: var(--fs-sm); min-width: 0; }
.home-kinds li > span:last-child span { color: var(--cw-muted); }
.home-kind-marks { display: flex; flex-direction: column; align-items: center; gap: .3rem; min-width: 2.6rem; font-size: 1.1rem; }
.home-kind-marks .up, .home-kind.up, .home-large-figure.up { color: var(--cw-success); }
.home-kind-marks .down, .home-kind.down, .home-large-figure.down { color: var(--cw-danger); }

.home-large-sample { margin-top: auto; display: grid; gap: .35rem; }
.home-large-figure { font-family: var(--cw-mono); font-size: clamp(1.6rem, 3.4vw, 2.1rem); font-weight: 800; letter-spacing: -.03em; line-height: 1.1; }
.home-large-line { display: flex; align-items: center; gap: .3rem; flex-wrap: wrap; font-size: var(--fs-sm); color: var(--cw-muted); }
.home-large-line .home-kind { font-size: 1.05rem; }

.home-top { display: grid; gap: .35rem; margin-top: auto !important; }
.home-top li { display: flex; align-items: center; gap: .65rem; padding: .5rem .75rem; border-radius: var(--r-md); background: var(--cw-bg); font-size: var(--fs-sm); }
.home-top .rank { font-family: var(--cw-mono); font-weight: 800; color: var(--cw-accent-text); min-width: 1.1rem; }
.home-top b { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.home-top .muted { font-size: var(--fs-xs); white-space: nowrap; }
.home-top li.locked {
  color: var(--cw-muted); font-weight: 600;
  background: repeating-linear-gradient(135deg, var(--cw-bg) 0 9px, color-mix(in srgb, var(--cw-bg) 55%, transparent) 9px 18px);
}

.home-stages, .home-langs, .home-chips { display: flex; flex-wrap: wrap; gap: .35rem; align-items: center; }
/* the filters and screens tiles: what the reader will find, as the chips they look like in the app */
.home-chips span { font-size: var(--fs-xs); font-weight: 700; padding: .25rem .65rem; border-radius: var(--r-pill); background: var(--cw-bg); box-shadow: 0 0 0 1px var(--cw-line); }
.home-chips span.on { background: var(--cw-accent-soft); color: var(--cw-accent-text); box-shadow: none; }
.home-points-col { flex-direction: column; align-items: flex-start; margin-top: auto; }
.home-chips.end { margin-top: auto; }
.home-langs span {
  font-family: var(--cw-mono); font-size: var(--fs-xs); font-weight: 700; padding: .2rem .6rem;
  border-radius: var(--r-pill); background: var(--cw-bg); box-shadow: 0 0 0 1px var(--cw-line);
}
.home-langs { margin-top: auto; }
.home-langs b { font-size: var(--fs-xs); color: var(--cw-muted); margin-right: .2rem; }

/* The screens tile (owner, 2026-10-10: "told better and more visually"): a phone, a tablet and a computer drawn in a
   few lines with what each shows, then the home-screen icon and the languages. */
.home-devices { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .6rem; }
.home-device { margin: 0; display: flex; flex-direction: column; gap: .7rem; padding: .9rem; border-radius: var(--r-md); background: var(--cw-bg); min-width: 0; }
.home-device .art { height: 5.4rem; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; }
.home-device figcaption { display: flex; flex-direction: column; gap: .15rem; font-size: var(--fs-sm); line-height: 1.45; }
.home-device figcaption span { color: var(--cw-muted); }
.dev {
  box-sizing: border-box; display: flex; flex-direction: column; gap: .22rem; padding: .3rem;
  border: 2px solid var(--cw-line-strong); border-radius: .45rem; background: var(--cw-surface);
}
.dev i { display: block; border-radius: 2px; background: var(--cw-line); }
.dev.phone { width: 3rem; height: 5.4rem; border-radius: .65rem; padding-top: .45rem; }
.dev.phone .c { height: .75rem; border-left: 3px solid var(--cw-success); }
.dev.phone .c.down { border-left-color: var(--cw-danger); }
.dev.phone .sheet { margin: auto -.3rem -.3rem; height: 1.1rem; border-radius: .35rem .35rem .45rem .45rem; background: var(--cw-accent-soft); box-shadow: inset 0 1px 0 var(--cw-accent); }
.dev .strip { height: .55rem; background: var(--cw-accent); }
.dev.tablet { width: 7.2rem; height: 5rem; border-radius: .55rem; }
.dev .cols { flex: 1; display: grid; grid-template-columns: 1fr 1fr; gap: .25rem; }
.dev .cols i { background: repeating-linear-gradient(to bottom, var(--cw-line) 0 .32rem, transparent .32rem .48rem); }
.dev.desktop { width: 8.6rem; height: 4.9rem; border-radius: .35rem; }
.dev .split { flex: 1; display: grid; grid-template-columns: 1fr 1.25fr; gap: .25rem; min-height: 0; }
.dev .rows { display: flex; flex-direction: column; gap: .2rem; }
.dev .rows i { flex: 1; }
.dev .chart { width: 100%; height: 100%; display: block; border-radius: 2px; background: var(--cw-accent-soft); }
.dev .chart polyline { fill: none; stroke: var(--cw-accent); stroke-width: 2; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.home-device .stand { display: block; width: 2.4rem; height: .4rem; border-radius: 0 0 .25rem .25rem; background: var(--cw-line-strong); }
.home-screens-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .75rem 1.25rem; margin-top: auto; }
.home-hs { display: flex; align-items: center; gap: .7rem; flex: 1 1 18rem; min-width: 0; font-size: var(--fs-sm); line-height: 1.45; }
.home-hs svg { width: 2.25rem; height: 2.25rem; flex: none; display: block; }
.home-hs span { display: flex; flex-direction: column; }
.home-hs span span { color: var(--cw-muted); }
.home-screens-foot .home-langs { margin-top: 0; }
@media (max-width: 640px) {
  .home-devices { grid-template-columns: minmax(0, 1fr); }
  .home-device { flex-direction: row; align-items: center; gap: .9rem; }
  /* the drawings at three quarters, so the words keep most of the line */
  .home-device .art { width: 8.7rem; flex: none; zoom: .76; }
}
.home-stages span { font-size: var(--fs-xs); font-weight: 700; padding: .25rem .65rem; border-radius: var(--r-pill); background: var(--cw-accent-soft); color: var(--cw-accent-text); }
.home-stages i { font-style: normal; color: var(--cw-muted); }
.home-tech-sample { margin-top: auto; padding: .85rem .95rem; border-radius: var(--r-md); background: var(--cw-bg); display: grid; gap: .6rem; }
.home-tech-line { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; font-size: var(--fs-sm); }
.home-tech-line b { font-size: var(--fs-md); }
.home-tech-line .home-chip.stage { color: var(--cw-accent-text); }
.home-kind { font-weight: 700; }
.home-conf { display: flex; align-items: center; gap: .6rem; font-size: var(--fs-xs); color: var(--cw-muted); }
.home-conf-bar { flex: 1; height: .4rem; border-radius: var(--r-pill); background: var(--cw-line); overflow: hidden; }
.home-conf-bar i { display: block; height: 100%; width: 0; background: var(--cw-accent); border-radius: inherit; }
.home-conf b { font-family: var(--cw-mono); color: var(--cw-ink); }

.home-logos { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .4rem; margin-top: auto; }
.home-logo { display: flex; align-items: center; gap: .45rem; padding: .45rem .55rem; border-radius: var(--r-sm); background: var(--cw-bg); font-size: 1.05rem; min-width: 0; }
.home-logo small { font-size: var(--fs-xs); font-weight: 600; color: var(--cw-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-logo .venue-logo.wide + small { display: none; }

.home-points { display: flex; flex-wrap: wrap; gap: .45rem; }
.home-points li { padding: .35rem .8rem .35rem .65rem; border-radius: var(--r-pill); background: var(--cw-bg); font-size: var(--fs-sm); font-weight: 600; }
.home-points li::before { content: "\2713"; color: var(--cw-success); font-weight: 800; margin-right: .45rem; }

/* plans: the Buy tab's cards, one grid */
.home-plans { display: grid; gap: .85rem; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

.home-band {
  border-radius: var(--r-lg); padding: clamp(1.2rem, 3vw, 1.9rem); background: var(--cw-accent-soft);
  border: 1px solid color-mix(in srgb, var(--cw-accent) 28%, transparent);
}
.home-band h3 { margin-bottom: .35rem; }
.home-invite-how { margin-top: .5rem !important; font-size: var(--fs-sm); color: var(--cw-muted); }

/* the ways to pay less: chips under the hero's buttons, a band above the plans, the TON price on each plan */
.home-perks { display: flex; flex-wrap: wrap; gap: .4rem; margin: .9rem 0 .8rem; }
.home-perk { color: var(--cw-accent-text); box-shadow: 0 0 0 1px color-mix(in srgb, var(--cw-accent) 35%, transparent); }
.home-save {
  display: grid; gap: .2rem; margin: 0 0 1.1rem; padding: .85rem 1rem; border-radius: var(--r-md);
  background: var(--cw-accent-soft); border: 1px solid color-mix(in srgb, var(--cw-accent) 28%, transparent);
}
.home-save-title { font-size: var(--fs-md); }
.home-save-text { margin: 0; font-size: var(--fs-sm); line-height: 1.55; }


.home-faq details { border-bottom: 1px solid var(--cw-line); padding: .95rem 0; margin: 0; }
.home-faq summary { font-weight: 700; cursor: pointer; }
.home-faq details p { color: var(--cw-muted); margin-top: .55rem; font-size: var(--fs-sm); line-height: 1.6; max-width: 46rem; }

.home-final {
  display: flex; flex-direction: column; align-items: center; gap: 1.1rem; text-align: center;
  padding: clamp(2rem, 5vw, 3.4rem) 1rem; border-radius: var(--r-lg); background: var(--cw-surface); border: 1px solid var(--cw-line);
}
.home-final h2 { max-width: 30rem; margin: 0; }
.home-disclaimer { color: var(--cw-muted); font-size: var(--fs-xs); max-width: 36rem; }

/* the landing page's own frame around the same page */
body.landing .topbar .lang { width: auto; margin: 0; padding: .3rem 1.8rem .3rem .6rem; font-size: var(--fs-sm); }
body.landing .topbar .home-cta { width: auto; margin: 0; padding: .45rem 1rem; border-radius: var(--r-pill); font-size: var(--fs-sm); font-weight: 700; }
body.landing .footer { max-width: var(--cw-home); margin: 0 auto; padding: 1.5rem 1rem 2.5rem; display: flex; flex-wrap: wrap; justify-content: space-between; gap: .5rem; color: var(--cw-muted); font-size: var(--fs-xs); }
@media (max-width: 480px) { body.landing .topbar .lang { display: none; } }

/* ---- home: one story per signal (pitch beside a looping demo on example data) ------------------------------ */
.home-stories { display: grid; gap: clamp(1.6rem, 4vw, 2.8rem); }
.home-stories > h2, .home-stories > .home-sub { margin-bottom: 0 !important; }
.home-story {
  display: grid; gap: clamp(1rem, 3vw, 2.4rem); grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); align-items: center;
  margin: 0; padding: 0; background: none; border: 0; box-shadow: none;   /* not Pico's article card: the demo is the only panel */
}
.home-story.flip .home-story-text { order: 2; }
/* a pair of stacked stories side by side; a wide story stacks its demo under the text */
.home-story-pair { display: grid; gap: clamp(1.4rem, 3vw, 2.4rem); grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; }
.home-story.stack, .home-story.wide { grid-template-columns: 1fr; align-items: start; }
/* side by side, the demos line up at the bottom however long each pitch is */
.home-story.stack { grid-template-rows: 1fr auto; }
.home-story.stack .home-demo { align-self: end; }
.home-story.wide .home-story-text { max-width: 46rem; }
.home-story.wide .home-demo { max-width: 40rem; }
.home-story h3 { font-size: var(--fs-md); font-weight: 800; letter-spacing: -.01em; margin: 0 0 .3rem; color: var(--cw-accent-text); }
.home-story-lead { font-size: clamp(1.2rem, 2.2vw, 1.5rem); font-weight: 700; line-height: 1.25; letter-spacing: -.015em; margin: 0 0 .9rem !important; text-wrap: balance; }
.home-story-points { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }
.home-story-points li { position: relative; margin: 0; padding-left: 1.5rem; color: var(--cw-muted); line-height: 1.55; list-style: none; }
.home-story-points li::before { content: "✓"; position: absolute; left: 0; top: 0; font-weight: 800; color: var(--cw-accent-text); }
.home-demo { margin: 0; display: grid; gap: .45rem; }
.home-demo figcaption { font-size: var(--fs-xs); color: var(--cw-muted); text-align: right; }
.home-demo-stage {
  position: relative; min-height: 15rem; padding: 1rem; border-radius: var(--r-lg); overflow: hidden;
  background: var(--cw-surface); border: 1px solid var(--cw-line); display: grid; align-content: end; gap: .75rem;
}
.demo-chart { position: absolute; inset: 1rem 1rem auto; width: calc(100% - 2rem); height: 7.5rem; overflow: visible; }
/* no non-scaling-stroke here: it measures the dash in screen pixels, and the 0-100 path length would stop drawing halfway */
.demo-line { fill: none; stroke: var(--cw-accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 100; stroke-dashoffset: 0; }
.demo-band { fill: color-mix(in srgb, var(--cw-accent) 16%, transparent); }
.demo-high { stroke: var(--cw-muted); stroke-width: 1.2; stroke-dasharray: 4 5; vector-effect: non-scaling-stroke; }
.demo-label { position: absolute; top: 1.35rem; right: 1.2rem; font-size: var(--fs-xs); font-weight: 700; color: var(--cw-muted); }
.demo-card, .demo-sig { position: relative; background: var(--cw-bg); border-radius: var(--r-md); }
.demo-card { padding: .8rem .9rem; display: grid; gap: .55rem; box-shadow: 0 0 0 1px var(--cw-line); }
.demo-result { margin: 0; font-size: var(--fs-sm); font-weight: 700; color: var(--cw-success); }
.demo-swap { display: inline-grid; }
.demo-swap > * { grid-area: 1 / 1; }
/* the still picture (no motion, or before a block first plays): the end of the story */
.demo-swap > .s1, .demo-swap > .s2, .demo-swap > .v1, .demo-swap > .n1, .demo-swap > .n2 { opacity: 0; }
.demo-tech .s3 { color: var(--cw-success); }
.home-conf-bar i.demo-conf { display: block; width: 100%; transform-origin: left center; transform: scaleX(.86); }
.demo-large { place-items: center; align-content: center; }
.demo-large .demo-sig { width: min(100%, 22rem); }
.demo-ring { position: absolute; width: 9rem; height: 9rem; border-radius: 50%; border: 2px solid color-mix(in srgb, var(--cw-success) 45%, transparent); opacity: 0; }
.demo-top { --row: 2.3rem; grid-template-columns: auto 1fr; align-content: center; column-gap: .8rem; }
.demo-ranks, .demo-rows { list-style: none; margin: 0; padding: 0; position: relative; height: calc(5 * var(--row)); }
.demo-ranks li { height: var(--row); display: flex; align-items: center; font-weight: 800; color: var(--cw-muted); font-variant-numeric: tabular-nums; }
.demo-rows li { position: absolute; left: 0; right: 0; top: calc(var(--i) * var(--row)); height: var(--row); display: flex; align-items: center; gap: .6rem; }
.demo-rows li.climb b { color: var(--cw-success); }

@media (max-width: 760px) {
  .home-story, .home-story-pair { grid-template-columns: 1fr; }
  .home-story.flip .home-story-text { order: 0; }
}

/* motion only for those who did not ask for less, and only while the block is on screen (.playing) */
@media (prefers-reduced-motion: no-preference) {
  .home-story.playing .demo-line { animation: demo-draw 9s var(--ease-out) infinite; }
  .home-story.playing .demo-tech .s1 { animation: demo-s1 9s steps(1) infinite; }
  .home-story.playing .demo-tech .s2 { animation: demo-s2 9s steps(1) infinite; }
  .home-story.playing .demo-tech .s3 { animation: demo-s3 9s steps(1) infinite; }
  .home-story.playing .demo-tech .v1 { animation: demo-s1 9s steps(1) infinite; }
  .home-story.playing .demo-tech .v2 { animation: demo-v2 9s steps(1) infinite; }
  .home-story.playing .demo-conf { animation: demo-conf 9s var(--ease-out) infinite; }
  .home-story.playing .demo-result { animation: demo-result 9s var(--ease-out) infinite; }
  .home-story.playing .demo-pa .demo-sig, .home-story.playing .demo-pd .demo-sig { animation: demo-enter 9s var(--ease-out) infinite; }
  .home-story.playing .demo-pa .n1 { animation: demo-n1 9s steps(1) infinite; }
  .home-story.playing .demo-pa .n2 { animation: demo-n2 9s steps(1) infinite; }
  .home-story.playing .demo-pa .n3 { animation: demo-n3 9s steps(1) infinite; }
  .home-story.playing .demo-ring { animation: demo-ring 3s var(--ease-out) infinite; }
  .home-story.playing .demo-ring.r2 { animation-delay: 1s; }
  .home-story.playing .demo-ring.r3 { animation-delay: 2s; }
  .home-story.playing .demo-large .demo-sig { animation: demo-beat 3s var(--ease-out) infinite; }
  .home-story.playing .demo-rows li.climb { animation: demo-climb 7s var(--ease-out) infinite; }
  .home-story.playing .demo-rows li.step { animation: demo-step 7s var(--ease-out) infinite; }
}
@keyframes demo-draw { 0% { stroke-dashoffset: 100; opacity: 1; } 50%, 94% { stroke-dashoffset: 0; opacity: 1; } 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes demo-s1 { 0% { opacity: 1; } 40%, 100% { opacity: 0; } }
@keyframes demo-s2 { 0% { opacity: 0; } 40% { opacity: 1; } 66%, 100% { opacity: 0; } }
@keyframes demo-s3 { 0% { opacity: 0; } 66%, 100% { opacity: 1; } }
@keyframes demo-v2 { 0% { opacity: 0; } 40%, 100% { opacity: 1; } }
@keyframes demo-conf { 0%, 38% { transform: scaleX(.58); } 46%, 100% { transform: scaleX(.86); } }
@keyframes demo-result { 0%, 66% { opacity: 0; transform: translateY(4px); } 72%, 96% { opacity: 1; transform: none; } 100% { opacity: 0; } }
@keyframes demo-enter { 0%, 44% { opacity: 0; transform: translateY(12px) scale(.98); } 52%, 94% { opacity: 1; transform: none; } 100% { opacity: 0; } }
@keyframes demo-n1 { 0% { opacity: 1; } 66%, 100% { opacity: 0; } }
@keyframes demo-n2 { 0% { opacity: 0; } 66% { opacity: 1; } 82%, 100% { opacity: 0; } }
@keyframes demo-n3 { 0% { opacity: 0; } 82%, 100% { opacity: 1; } }
@keyframes demo-ring { 0% { opacity: .55; transform: scale(.45); } 100% { opacity: 0; transform: scale(1.7); } }
@keyframes demo-beat { 0%, 100% { transform: none; } 8% { transform: scale(1.02); } 16% { transform: none; } }
@keyframes demo-climb { 0%, 40% { transform: none; } 52%, 90% { transform: translateY(calc(-3 * var(--row))); } 100% { transform: none; } }
@keyframes demo-step { 0%, 40% { transform: none; } 52%, 90% { transform: translateY(var(--row)); } 100% { transform: none; } }

/* ---- home: depth on scroll ------------------------------------------------------------------------------------
   Two screen-sized back layers behind the page: a faint dot grid (far, barely moves) and two soft accent lights
   (nearer, drift up faster). Screen-sized and fixed, not page-sized: a layer as tall as the page would cost tens of
   megabytes of GPU memory on a phone. The movement is a scroll-driven animation (the browser runs it off the main
   thread, no scroll listener); without scroll timelines, or for those who asked for less motion, it stays still. */
.home::before, .home::after { content: ""; position: fixed; inset: -14vh 0; pointer-events: none; z-index: -1; }
.home::before {
  background-image: radial-gradient(color-mix(in srgb, var(--cw-ink) 10%, transparent) 1px, transparent 1.4px);
  background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 35%, #000 25%, transparent 75%);
  mask-image: radial-gradient(ellipse 70% 60% at 50% 35%, #000 25%, transparent 75%);
}
.home::after {
  background:
    radial-gradient(38rem 24rem at 88% 18%, color-mix(in srgb, var(--cw-accent) 13%, transparent), transparent 70%),
    radial-gradient(34rem 22rem at 6% 78%, color-mix(in srgb, var(--cw-accent) 9%, transparent), transparent 70%);
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .home::before { animation: home-far linear both; animation-timeline: scroll(root block); }
    .home::after { animation: home-near linear both; animation-timeline: scroll(root block); }
    /* each demo drifts against its text while its block crosses the screen */
    .home-demo { animation: home-float linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
  }
}
@keyframes home-far { to { transform: translateY(-6vh); } }
@keyframes home-near { to { transform: translateY(-13vh); } }
@keyframes home-float { from { transform: translateY(1.8rem); } to { transform: translateY(-1.8rem); } }
