
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');

:root {
  /* Brand */
  --brand-primary:        #27BC81;
  --brand-primary-hover:  #37CD9B;
  --brand-primary-muted:  rgba(39, 188, 129, 0.15);
  --brand-fade:           #EF4444;
  --brand-fade-hover:     #F87171;
  --brand-fade-muted:     rgba(239, 68, 68, 0.15);
  --brand-accent:         #6E42CF;
  --brand-accent-hover:   #A47BFF;
  --brand-accent-muted:   rgba(110, 66, 207, 0.15);

  /* Surfaces */
  --bg-page:              #07081a;            /* Outer page surround (darker than base so 390px column reads as a device on desktop) */
  --bg-base:              #0E0F26;            /* App background (inside the 390px column) */
  --bg-surface:           #151E32;
  --bg-surface-elevated:  #1C2642;
  --bg-surface-hover:     #232E4A;

  /* Text */
  --text-primary:         #FFFFFF;
  --text-secondary:       #A0AEC0;
  --text-tertiary:        #646473;

  /* Borders */
  --border-default:       #2D3748;
  --border-subtle:        #1E2433;

  /* Status (semantic aliases) */
  --success:              #27BC81;
  --error:                #EF4444;
  --warning:              #F59E0B;
  --streak:               #FF8C00;

  /* Metallic palette — 1st / 2nd / 3rd place */
  --gold-rank:            #FFD700;
  --silver-rank:          #C0C0C0;
  --bronze-rank:          #CD7F32;
  --gold:                 #FFD700;
  --gold-soft:            #FFE56B;
  --gold-deep:            #C99A2E;
  --gold-muted:           rgba(255, 215, 0, 0.14);
  --silver:               #C0C0C0;
  --silver-soft:          #E5E5E5;
  --silver-deep:          #8A8A8A;
  --bronze:               #CD7F32;
  --bronze-soft:          #E6A66B;
  --bronze-deep:          #8C5621;

  /* Asset colors (crypto gradients) */
  --asset-sol-from:       #9945FF;
  --asset-sol-to:         #14F195;
  --asset-sol:            linear-gradient(135deg, #9945FF 0%, #14F195 100%);
  --asset-btc:            #F7931A;
  --asset-eth:            #627EEA;

  /* Avatar gradient palette */
  --av-purple-green:      linear-gradient(135deg, #6E42CF 0%, #27BC81 100%);
  --av-orange-red:        linear-gradient(135deg, #F7931A 0%, #EF4444 100%);
  --av-blue-purple:       linear-gradient(135deg, #627EEA 0%, #6E42CF 100%);
  --av-amber-rose:        linear-gradient(135deg, #EF4444 0%, #F59E0B 100%);
  --av-purple-orange:     linear-gradient(135deg, #A47BFF 0%, #F7931A 100%);
  --av-green-blue:        linear-gradient(135deg, #14F195 0%, #627EEA 100%);
  --av-violet-blue:       linear-gradient(135deg, #3b4dca 0%, #A47BFF 100%);
  --av-green-purple:      linear-gradient(135deg, #27BC81 0%, #6E42CF 100%);
  --av-bronze-amber:      linear-gradient(135deg, #b45309 0%, #F7931A 100%);

  /* Typography */
  --font-sans:            'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono:            'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

  /* Radii */
  --radius-sm:            6px;
  --radius-md:            12px;
  --radius-lg:            16px;
  --radius-full:          9999px;

  /* Motion */
  --ease-out:             cubic-bezier(0.4, 0, 0.2, 1);
  --ease-spring:          cubic-bezier(0.34, 1.56, 0.64, 1);
  --duration-fast:        150ms;
  --duration-base:        250ms;
  --duration-slow:        300ms;

  /* Layout */
  --screen-width:         390px;
  --header-h:             56px;
  --tab-bar-h:            72px;

  /* Legacy var aliases — earlier rules reference these names. Mapped
   * onto the mock palette so retoken happens globally without rewriting
   * every rule. Remove once every direct reference is migrated. */
  --bg:        var(--bg-base);
  --surface:   var(--bg-surface);
  --surface-2: var(--bg-surface-elevated);
  --border:    var(--border-default);
  --text:      var(--text-primary);
  --muted:     var(--text-secondary);
  --muted-2:   var(--text-tertiary);
  --green:      var(--brand-primary);
  --green-soft: var(--brand-primary-muted);
  --purple:     var(--brand-accent-hover);
}

* {
  box-sizing: border-box;
  /* Android WebView paints a translucent blue overlay on every tap
     target unless opted out — read as "blue flashing" in the APK
     (tester 2026-08-12). The app's own :active/:hover states carry
     the press feedback. */
  -webkit-tap-highlight-color: transparent;
}

/* Three-layer shell:
 *   html  — outer page surround (--bg-page, darker so the 390px
 *           column reads as a device on desktop/tablet)
 *   body  — flex-centered viewport-spanning row; .phone wrapper
 *           sits inside, capped at --screen-width
 *   .phone — the canonical 390px column with device chrome (rounded
 *            corners + box shadow) on desktop, edge-to-edge on
 *            mobile via the @media query below
 *   .screen — inner card (--bg-base), fills .phone
 *
 * Values switched 2026-05-27 (issue #29) to use the canonical
 * `--bg-page` / `--bg-base` / `--screen-width` tokens so the
 * outer surround and column color stay in sync with the design
 * system. The .phone wrapper preserves the prior desktop
 * "device-on-viewport" preview and the responsive collapse to
 * full-bleed on narrow viewports — both behaviors regress without
 * it.
 */
html {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  /* Kill the elastic rubber-band (notably on horizontal swipes, where
   * nothing scrolls so the gesture bounces the whole surface). */
  overscroll-behavior: none;
  background: var(--bg-page);
  color: var(--text);
  font-family: var(--font-sans);
}

body {
  display: flex;
  justify-content: center;
  margin: 0;
  padding: 18px 14px 32px;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  overscroll-behavior: none;
  background: var(--bg-page);
  color: var(--text-primary);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: inherit;
  text-decoration: none;
}

.phone {
  /* Cap at the canonical column width; on viewports narrower
   * than --screen-width, shrink to fit (handled by `width:100%`).
   * The rounded-corner + shadow chrome reads as a "device" on
   * desktop where the html surround is visible around the
   * column; the @media query below strips that chrome on real
   * mobile viewports so the column goes edge-to-edge. */
  width: 100%;
  max-width: var(--screen-width);
  height: 100%;
  border-radius: 32px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg-base);
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.45);
  position: relative;
}

.screen {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  background: var(--bg-base);
}

/* Mobile collapse — drop the desktop "device" chrome below the
 * canonical column width so the app fills the viewport edge-to-
 * edge on real phones. Threshold matches the column width
 * (token-driven so re-anchoring the design width re-anchors the
 * breakpoint). */
@media (max-width: 480px) {
  body {
    padding: 0;
  }
  .phone {
    border-radius: 0;
    border: none;
    box-shadow: none;
  }
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  /* Top inset: with viewport-fit=cover the shells render edge-to-edge
     (Android enableEdgeToEdge + iOS full-bleed WKWebView), so without
     this the header sits UNDER the OS status bar — hamburger vs
     battery icon (#128 device QA, both Seeker + iPhone). Bottom
     insets were already handled; the top one was dropped with the
     simulated status bar in #123. Zero on desktop browsers. */
  padding: calc(10px + env(safe-area-inset-top, 0px)) 20px 14px;
  border-bottom: 1px solid var(--border-default);
}

.header-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.brand {
  display: flex;
  gap: 10px;
  align-items: center;
}

.wordmark {
  display: block;
  height: 24px;
  width: auto;
}

.beta {
  display: inline-flex;
  align-items: center;
  padding: 3px 8px;
  border-radius: 999px;
  color: var(--purple);
  background: rgba(164, 123, 255, 0.14);
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* Hamburger / drawer trigger — links to /menu (#13). Mock styling:
 * no border, no background, lifts color on hover. Mock feed.html:159. */
.menu-btn {
  width: 38px;
  height: 38px;
  border-radius: var(--radius-md);
  display: grid;
  place-items: center;
  color: var(--text-secondary);
  background: transparent;
  border: none;
  cursor: pointer;
  transition: color 150ms ease, background-color 150ms ease, transform 150ms ease;
}

.menu-btn:hover {
  color: var(--text-primary);
  background: var(--bg-surface-hover);
}

.menu-btn:active {
  transform: scale(0.97);
}

.menu-btn svg {
  display: block;
}

.header-tools {
  display: flex;
  align-items: center;
}

.wallet-cta {
  min-width: 132px;
  min-height: 42px;
  padding: 0 16px;
  border-radius: 16px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.045);
  color: var(--text);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  text-align: center;
}

.wallet-cta.connected {
  background: rgba(39, 188, 129, 0.10);
  border-color: rgba(39, 188, 129, 0.18);
}

.wallet-cta.is-loading {
  opacity: 0.72;
}

.wallet-cta:disabled {
  cursor: wait;
}

.wallet-label {
  font-size: 12px;
  font-weight: 800;
  line-height: 1.1;
  white-space: nowrap;
}

.wallet-status {
  margin-bottom: 14px;
  padding: 10px 12px;
  border-radius: 14px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
  color: var(--muted);
  font-size: 12px;
  line-height: 1.45;
}

.wallet-status[data-kind="info"] {
  color: var(--text);
}

.wallet-status[data-kind="warning"] {
  color: var(--gold);
  border-color: rgba(251, 185, 36, 0.18);
}

.wallet-status[data-kind="error"] {
  color: #ff8f8f;
  border-color: rgba(255, 143, 143, 0.18);
}

.content {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* No horizontal scroll — clamps any too-wide child and removes the
   * axis the rubber-band bounce rode on. */
  overflow-x: hidden;
  /* `overscroll-behavior: contain` stops scroll chaining to the
   * body so the outer phone shell doesn't reflow when the
   * scroll hits an edge. The earlier `overflow-anchor: none` +
   * `will-change: transform` workarounds were removed when
   * `.filters` moved OUT of `.content` and became a sibling
   * (via render_page_with_above_content). Natural-position
   * pinning beats sticky every time it's available. */
  overscroll-behavior: none;
  -webkit-overflow-scrolling: touch;
  /* Bottom padding clears the absolute-positioned `.nav` (72px
   * tall, pinned to the phone shell's bottom edge). Without
   * this, the last item in a long scroll — currently the
   * trailing `.earn-card` on the Rewards tab — hides behind
   * the bottom nav. 100px = nav (72) + safe-area gutter.
   * Horizontal padding intentionally zero so pages with
   * `above_content` sticky rows (Discover filters, leaderboard
   * title-row) can manage their own gutters; individual screens
   * apply their own horizontal padding on inner containers. */
  padding-bottom: 100px;
  margin: 1rem;
}

.eyebrow {
  color: var(--muted);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.title-row {
  /* Leaderboard / page-level title row carrying the page-tabs
   * (Leagues / Rewards toggle) and the prize-pool pill per
   * canonical `tmp/updates/leaderboard.html`. Sits outside the
   * scroll container via `render_page_with_above_content`, so
   * vertical breathing room comes from this row's padding, not
   * margin. */
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px 12px;
  gap: 12px;
}

/* Leaderboard variant of `.page-tabs` — pill toggle switch. The
 * earlier canonical block defines `.page-tabs` as an underlined
 * tab pivot (used by profile-page tabs). Inside `.title-row` we
 * override to the pill-toggle treatment. Scoped to `.title-row`
 * so the underline pivot stays intact for other surfaces. */
.title-row .page-tabs {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-full);
}
.title-row .page-tab {
  border: none;
  background: none;
  padding: 0 18px;
  height: 32px;
  border-radius: var(--radius-full);
  font-family: var(--font-sans);
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: -0.2px;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: background-color 150ms ease, color 150ms ease;
}
.title-row .page-tab.active {
  background: var(--brand-primary);
  color: #fff;
}
.title-row .page-tab:hover:not(.active) {
  color: var(--text-primary);
}
/* Pill-toggle has no underline; suppress the inherited ::after
 * from the canonical-block `.page-tab` rule. */
.title-row .page-tab::after {
  display: none;
}

.title {
  font-size: 28px;
  line-height: 1;
  font-weight: 800;
  letter-spacing: -0.06em;
}

.subtitle {
  margin-top: 6px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.45;
}

.hero,
.card,
.table,
.form-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 20px;
}

.hero {
  padding: 18px;
  margin-bottom: 18px;
  background:
    radial-gradient(circle at top right, rgba(39, 188, 129, 0.14), transparent 34%),
    radial-gradient(circle at bottom left, rgba(164, 123, 255, 0.10), transparent 28%),
    rgba(255, 255, 255, 0.045);
}

.hero-statline {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 14px;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 10px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
}

.chip.on {
  background: var(--green-soft);
  color: var(--green);
  border: 1px solid rgba(39, 188, 129, 0.28);
}

.section {
  margin-top: 18px;
}

.section-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.section-title {
  font-size: 12px;
  font-weight: 800;
  color: var(--muted);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.section-link {
  color: var(--green);
  font-size: 12px;
  font-weight: 700;
}

.stack {
  display: grid;
  gap: 10px;
}

.card {
  padding: 14px;
}

.call-top,
.row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
}

.call-top {
  align-items: flex-start;
  margin-bottom: 10px;
}

.handle {
  font-size: 13px;
  font-weight: 800;
}

.meta {
  color: var(--muted);
  font-size: 11px;
  line-height: 1.45;
}

.call-title {
  font-size: 18px;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.04em;
  margin-bottom: 8px;
}

.call-thesis {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.5;
  margin-bottom: 12px;
}

.market-strip {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  margin-bottom: 12px;
}

.metric {
  background: rgba(255, 255, 255, 0.03);
  border-radius: 14px;
  padding: 10px 12px;
  border: 1px solid rgba(255, 255, 255, 0.05);
}

.metric-label {
  color: var(--muted-2);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 4px;
}

.metric-value {
  font-size: 15px;
  font-weight: 800;
}

.metric-value.green { color: var(--green); }
.metric-value.gold { color: var(--gold); }

.actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.button,
.ghost-button,
.nav-link {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  border-radius: 14px;
  border: 1px solid transparent;
  min-height: 44px;
  font-size: 13px;
  font-weight: 800;
  cursor: pointer;
}

.button {
  background: var(--green);
  color: #08120f;
}

.ghost-button {
  background: rgba(255, 255, 255, 0.045);
  border-color: var(--border);
  color: var(--text);
}

.row {
  align-items: center;
  padding: 12px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.table .row:last-child {
  border-bottom: none;
}

.avatar {
  width: 40px;
  height: 40px;
  border-radius: 14px;
  background: linear-gradient(145deg, rgba(164, 123, 255, 0.28), rgba(39, 188, 129, 0.18));
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 800;
  color: white;
  overflow: hidden;
}

/* Real profile image (X / Google) inside any avatar container — fills +
 * crops to the avatar's rounded shape, covering the gradient. Covers the
 * canonical `.avatar` plus the leaderboard podium's `.pod-avatar`. */
.avatar .avatar-img,
.pod-avatar .avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  display: block;
}

/* Top-3 leaderboard medals (#14). Numeric rank stays inside the
 * avatar; the bg + border-color reflect place. */
.avatar--rank-1 {
  background: linear-gradient(145deg, var(--gold-rank), rgba(255, 215, 0, 0.45));
  color: #1a1505;
  box-shadow: 0 0 0 2px rgba(255, 215, 0, 0.35);
}

.avatar--rank-2 {
  background: linear-gradient(145deg, var(--silver-rank), rgba(192, 192, 192, 0.4));
  color: #1a1a1a;
  box-shadow: 0 0 0 2px rgba(192, 192, 192, 0.35);
}

.avatar--rank-3 {
  background: linear-gradient(145deg, var(--bronze-rank), rgba(205, 127, 50, 0.4));
  color: #1a0c03;
  box-shadow: 0 0 0 2px rgba(205, 127, 50, 0.35);
}

.row-main {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.row-copy {
  min-width: 0;
}

.row-title {
  font-size: 13px;
  font-weight: 800;
  margin-bottom: 3px;
}

.row-subtitle {
  color: var(--muted);
  font-size: 11px;
}

.row-right {
  text-align: right;
  flex-shrink: 0;
}

.pill {
  display: inline-flex;
  align-items: center;
  padding: 4px 8px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.pill.live {
  color: var(--green);
  background: var(--green-soft);
}

.pill.settled {
  color: var(--gold);
  background: rgba(251, 185, 36, 0.12);
}

.pill.provisional {
  color: var(--purple);
  background: rgba(164, 123, 255, 0.14);
}

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.form-card {
  padding: 16px;
}

.label {
  display: block;
  color: var(--muted);
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 8px;
}

.input,
.textarea {
  width: 100%;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text);
  border-radius: 14px;
  padding: 13px 14px;
  font: inherit;
}

.textarea {
  min-height: 100px;
  resize: vertical;
}

.field {
  margin-bottom: 14px;
}

.help {
  margin-top: 6px;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.45;
}

.notice {
  margin-bottom: 14px;
  padding: 12px 14px;
  border-radius: 16px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
  font-size: 12px;
  line-height: 1.45;
}

.notice.success {
  border-color: rgba(39, 188, 129, 0.28);
  background: var(--green-soft);
  color: #c9f5e3;
}

.notice.error {
  border-color: rgba(251, 185, 36, 0.25);
  background: rgba(251, 185, 36, 0.10);
  color: #ffe1a0;
}

.select {
  appearance: none;
}

button.button,
button.ghost-button {
  width: 100%;
}

button.button:disabled,
button.ghost-button:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.option-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.option {
  padding: 9px 12px;
  border-radius: 12px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
  color: var(--muted);
  font-size: 12px;
  font-weight: 800;
}

.option.active {
  background: var(--green-soft);
  border-color: rgba(39, 188, 129, 0.28);
  color: var(--green);
}

/* Bottom tab bar — mock feed.html:606-671. Keeps existing absolute
 * positioning so .content's padding-bottom: 100px continues to clear
 * scrollable content from underneath. */
.nav {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 72px;
  display: flex;
  align-items: center;
  background: var(--bg-surface);
  border-top: 1px solid var(--border-subtle);
  z-index: 20;
}

.nav-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 10px 0 12px;
  text-decoration: none;
  transition: transform 150ms ease;
}

.nav-item:active {
  transform: scale(0.95);
}

.nav-icon {
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-tertiary);
  transition: color 150ms ease;
}

.nav-item.active .nav-icon {
  color: var(--brand-primary);
}
/* Profile tab = the viewer's own photo when they have one; a 2px ring
   carries the active state the glyph showed through `color`. */
.nav-icon .nav-avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  border: 2px solid transparent;
  transition: border-color 150ms ease;
}
.nav-item.active .nav-icon .nav-avatar {
  border-color: var(--brand-primary);
}

.create-btn {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--brand-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  cursor: pointer;
  box-shadow: 0 3px 10px rgba(39, 188, 129, 0.45), 0 1px 3px rgba(0, 0, 0, 0.25);
  transition: background-color 150ms ease, transform 150ms ease, filter 150ms ease;
}

.create-btn:hover {
  filter: brightness(1.1);
}

.create-btn svg {
  width: 18px;
  height: 18px;
}

.nav-item.create-tab:active .create-btn {
  transform: scale(0.95);
}

/*
 * Responsive shell — re-aligned 2026-05-27 (issue #29).
 *
 * Canonical design ("Mobile-first, 390px wide" — design-system/
 * README.md) calls for the column to stay locked at --screen-width
 * across all viewports. The default rules at the top of this file
 * already render the chrome correctly on desktop/tablet; the only
 * desktop-specific refinements that survive here are:
 *   - extra body padding for tablet+desktop breathing room
 * (The simulated 9:41 statusbar was removed entirely 2026-07-17 —
 * on real phones it doubled the device's own status bar.)
 *
 * The previous rules in this slot widened the column to 460px on
 * ≥481px and stripped the chrome entirely on ≥768px — both
 * regressed the canonical desktop preview, were caught by Codex
 * stop-time review, and are removed.
 *
 * Mobile collapse (edge-to-edge < 480px) lives in the main shell
 * section near the .phone rule, not here.
 */
@media (min-width: 481px) {
  body {
    padding: 24px 16px 40px;
  }
}

/* ──── Menu page (#16 — mock user_menu.html) ──────────────────── */

/* ──── Menu page (issue #29 Phase 1) ──────────────────────────────
 * Re-skinned 2026-05-27 to match `tmp/updates/user-menu-signed-out.html`.
 * All selectors below scope to `.menu-screen` so the bare class
 * names (`.row`, `.section`, `.connect-section`, `.footer`, etc.)
 * stay local to this page and don't collide with other screens
 * that own their own bare `.row` (notably `profile.rs`). */

.menu-phone {
  /* Inherits .phone's fixed height (= body content-box height).
   * Menu scrolls via the inner .scroll, not the outer page. */
  height: 100%;
}

.menu-screen {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--bg-base);
  overflow: hidden;
}

.menu-screen .header {
  flex-shrink: 0;
  /* box-sizing keeps the 56px content row; the inset only grows the
     top padding (same status-bar overlap fix as the main .header). */
  height: calc(56px + env(safe-area-inset-top, 0px));
  padding-top: env(safe-area-inset-top, 0px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 12px 0 8px;
  border-bottom: 1px solid var(--border-subtle);
  background: var(--bg-base);
  position: relative;
}

.menu-screen .header-title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -0.3px;
  color: var(--text-primary);
}

.menu-screen .header-spacer { width: 40px; }

.menu-screen .scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: none;
  display: flex;
  flex-direction: column;
}
.menu-screen .scroll::-webkit-scrollbar { display: none; }

/* Identity strip (signed-in) */
.menu-screen .user-section {
  padding: 18px 20px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  border-bottom: 1px solid var(--border-subtle);
}
.menu-screen .user-section .avatar { text-decoration: none; text-transform: uppercase; }
.menu-screen .user-info { flex: 1; min-width: 0; }
.menu-screen .uname {
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -0.3px;
  color: var(--text-primary);
}
.menu-screen .view-profile {
  margin-top: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-tertiary);
  letter-spacing: -0.1px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  text-decoration: none;
  transition: color 150ms ease, transform 150ms ease;
}
.menu-screen .view-profile:hover { color: var(--brand-primary); }
.menu-screen .view-profile svg {
  width: 11px;
  height: 11px;
  transition: transform 200ms ease;
}
.menu-screen .view-profile:hover svg { transform: translateX(2px); }

/* Connect prompt (signed-out) */
.menu-screen .connect-section {
  padding: 18px 20px 16px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  border-bottom: 1px solid var(--border-subtle);
}
.menu-screen .connect-btn {
  width: 100%;
  height: 48px;
  border-radius: var(--radius-md);
  border: none;
  background: var(--brand-primary);
  color: #fff;
  font-family: var(--font-sans);
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: -0.2px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  box-shadow: 0 4px 14px rgba(39, 188, 129, 0.32);
  transition: filter 150ms ease, transform 100ms ease;
}
.menu-screen .connect-btn:hover  { filter: brightness(1.06); }
.menu-screen .connect-btn:active { transform: scale(0.98); }
.menu-screen .connect-btn svg    { width: 16px; height: 16px; }
/* The HTML `hidden` attribute must win over the `display: inline-flex`
   above. Platform-gated connect buttons (data-tauri-only / data-web-only
   / data-shell-login) ship `hidden` and are revealed per-platform by
   wallet-bridge.js; without this rule `display` defeats `hidden` and the
   button leaks onto the wrong platform — e.g. the Tauri-only social
   CTA ("Connect Wallet", per business 2026-07-27) showing on the web
   menu. */
.menu-screen .connect-btn[hidden] { display: none; }
.menu-screen .connect-status { margin-block-start: 8px; margin-bottom: 0; }
/* WP7 coexistence: Privy login (primary, link) + wallet (secondary). */
.menu-screen .login-cta { text-decoration: none; }
.menu-screen .connect-btn.wallet-cta {
  background: var(--bg-surface);
  color: var(--text-primary);
  border: 1px solid var(--border-default);
  box-shadow: none;
}
.menu-screen .connect-btn.wallet-cta:hover { filter: none; background: var(--bg-surface-hover); }
.menu-screen .connect-or {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 12px 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.menu-screen .connect-or::before,
.menu-screen .connect-or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border-subtle);
}
/* Wallet-address chip in the signed-in identity strip. `display: flex`
   (block-level) + fit-content so it sits on its own line above the
   View Profile link rather than sharing the row. */
/* Hidden 2026-07-17 (business): chip stays in the DOM + tests so it
 * can come back with the funding work; only the display is off. */
.menu-screen .wallet-chip {
  display: none !important;
}

.menu-screen .wallet-chip {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 4px;
  padding: 3px 4px 3px 10px;
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-full);
  width: fit-content;
}
.menu-screen .wallet-chip-addr {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: -0.2px;
}
.menu-screen .wallet-chip-copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 3px;
  color: var(--text-tertiary);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: color 150ms ease, background-color 150ms ease;
}
.menu-screen .wallet-chip-copy svg { width: 13px; height: 13px; }
.menu-screen .wallet-chip-copy:hover { color: var(--text-primary); background: var(--bg-surface-hover); }
.menu-screen .wallet-chip-copy.copied { color: var(--brand-primary); }

/* Sections + rows
 *
 * The global `.section` / `.row` rules earlier in this file
 * (lines ~402 and ~536) set `margin-top: 18px`, `justify-content:
 * space-between`, `gap: 12px`, and `border-bottom: 1px solid …`
 * — all meant for profile.rs's bare-class markup, all wrong for
 * the menu. Specificity (0,2,0) here wins over (0,1,0) global,
 * but only for properties this rule actually redeclares. Every
 * property the global block sets gets an explicit override below
 * (margin-top, justify-content, border-bottom) so a global rule
 * change can never silently distort the menu layout.
 */
.menu-screen .section {
  margin-top: 0;
  padding: 8px 0;
}
.menu-screen .section + .section {
  border-top: 1px solid var(--border-subtle);
}

/* Menu rows per new/alpha/user-menu.html (parity pass 2026-08-10):
   flat 18px icons — no chip background — tighter 10px gap. */
.menu-screen .row {
  width: 100%;
  background: none;
  border: none;
  border-bottom: none;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  padding: 13px 20px;
  cursor: pointer;
  text-align: left;
  text-decoration: none;
  color: var(--text-primary);
  font-family: inherit;
  transition: background-color 150ms ease, transform 150ms ease;
}
.menu-screen .row:hover  { background: var(--bg-surface); }
.menu-screen .row:active { transform: scale(0.98); background: var(--bg-surface-hover); }

.menu-screen .row-icon {
  width: 18px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--text-secondary);
  transition: color 150ms ease;
}
.menu-screen .row-icon svg { width: 18px; height: 18px; }
.menu-screen .row-icon svg[fill="currentColor"] { width: 14px; height: 14px; }
.menu-screen .row:hover .row-icon { color: var(--text-primary); }
/* Mock styles .row--wallet as a non-pressable info row; ours stays a
   live link — it is the /wallet entrypoint — so the interactive
   affordances deliberately remain. */

.menu-screen .row-label {
  flex: 1;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.2px;
  transition: color 150ms ease;
}

.menu-screen .row-chev {
  color: var(--text-tertiary);
  display: flex;
  transition: transform 200ms ease, color 150ms ease;
}
.menu-screen .row:hover .row-chev {
  color: var(--text-secondary);
  transform: translateX(3px);
}

/* Logout row: neutral per the mock — no red chrome. */
.menu-screen .row--logout .row-label {
  color: var(--text-primary);
  font-weight: 600;
}

/* Footer */
.menu-screen .footer {
  flex-shrink: 0;
  padding: 12px 20px calc(20px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
/* Built-on Solana badge — image-based mark sourced from the
   tradeleague-marketing landing page so the menu footer and the
   marketing site share one canonical asset. WebP first with PNG
   fallback. Width matches the landing's `.landing-solana-badge`
   (8.75rem) so visual density stays consistent across surfaces. */
.menu-screen .built-on {
  display: block;
  margin-top: 2rem;
}
.menu-screen .built-on img {
  display: block;
  width: 8.75rem;
  height: auto;
}

/* ──── Feed tab strip + empty state (#10) ─────────────────────── */

.feed-tabs {
  display: flex;
  align-items: stretch;
  height: 40px;
  margin: 0 0 12px;
  position: sticky;
  top: 0;
  z-index: 19;
  border-bottom: 1px solid var(--border-subtle);
  background: var(--bg-base);
}

.feed-tab {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-tertiary);
  position: relative;
  letter-spacing: -0.1px;
  text-decoration: none;
  transition: color 150ms ease;
}

.feed-tab:hover {
  color: var(--text-secondary);
}

.feed-tab.active {
  color: var(--text-primary);
}

.feed-tab::after {
  content: '';
  position: absolute;
  bottom: -1px;
  left: 50%;
  right: 50%;
  height: 2px;
  background: transparent;
  border-radius: var(--radius-full);
  transition: left 250ms cubic-bezier(0.4, 0, 0.2, 1),
              right 250ms cubic-bezier(0.4, 0, 0.2, 1),
              background 200ms ease;
}

.feed-tab.active::after {
  left: calc(50% - 44px);
  right: calc(50% - 44px);
  background: var(--brand-primary);
}

/* V3 empty Predictions list (2026-08-08 drop) */
.list.empty-center .feed-empty { padding: 16px; }
/* Empty predictions centers vertically between the tabs and the
   nav (mock empty-profile-predictions.html; tester round 5, #188).
   The `.content` flex is :has-scoped so every other page keeps its
   block-flow scroll region — same trick as the call-detail
   centering. Covers both the own-profile `.feed-empty` and the
   other-profile `.profile-empty` variants (same wrapper). */
.content:has(> .list.empty-center) {
  display: flex;
  flex-direction: column;
}
.list.empty-center {
  flex: 1;
  justify-content: center;
}
/* Other-profile empty (empty-profile-other-*.html): gray chart
   illustration + short message, no CTA. */
.profile-empty { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 24px 16px; }
.pe-chart { display: block; margin: 0 auto 6px; }
.pe-msg { font-size: 14px; font-weight: 600; color: var(--text-secondary); }
.feed-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 32px 16px 8px;
}

.feed-empty-msg {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: -0.1px;
  text-align: center;
  line-height: 1.4;
  max-width: 280px;
}

.feed-empty-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0 22px;
  height: 44px;
  border-radius: var(--radius-md);
  background: var(--brand-primary);
  color: #fff;
  font-weight: 700;
  font-size: 14px;
  text-decoration: none;
  box-shadow: 0 3px 12px rgba(39, 188, 129, 0.35);
  transition: filter 150ms ease, transform 150ms ease;
}

.feed-empty-cta:hover {
  filter: brightness(1.08);
}

.feed-empty-cta:active {
  transform: scale(0.97);
}

.feed-empty-cta svg {
  width: 18px;
  height: 18px;
}

/* ──── Demo-data disclosure (#19) ────────────────────────────── */

/* .is-placeholder truth-marker system retired 2026-07-06 — every
 * displayed value is DB- or oracle-derived; missing history renders
 * an em-dash instead of a marked fabrication. */

.demo-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  margin: 8px 0 4px;
  border-radius: var(--radius-sm);
  background: var(--brand-accent-muted);
  border: 1px solid rgba(110, 66, 207, 0.3);
  font-size: 11px;
  font-weight: 600;
  color: var(--brand-accent-hover);
  letter-spacing: -0.05px;
  line-height: 1.4;
}

.demo-banner-dot {
  width: 8px;
  height: 8px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  background: var(--brand-accent);
  box-shadow: 0 0 0 2px var(--brand-accent-muted);
}

/* ──── Empty-feed surface (issue #29 Phase 1) ─────────────────
 * Matches `tmp/tradeleague-v1 designs/screens/empty-feed.html`.
 * Scoped under `.feed-scroll` so the bare class names don't
 * collide with the global `.divider` (none today, but cheap
 * insurance) or with profile.rs's `.section`/`.row` markup. */
.feed-scroll .empty-wrap {
  display: flex;
  flex-direction: column;
  gap: 18px;
  /* padding: 24px 20px 16px; */
}
.feed-scroll .empty-msg {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: -0.1px;
  text-align: center;
  line-height: 1.4;
}
.feed-scroll .empty-suggested {
  display: flex;
  flex-direction: column;
}
.feed-scroll .divider {
  height: 1px;
  background: var(--border-subtle);
  margin: 22px 0 16px;
}
.feed-scroll .cta-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding-bottom: 8px;
}
.feed-scroll .cta-lbl {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: -0.1px;
}

/* ──── Feed scroll + call-entry (mock feed.html) ──────────────── */

.feed-scroll {
  padding: 14px 0 8px;
}

.call-entry {
  margin-bottom: 20px;
}

.call-entry:last-child {
  margin-bottom: 0;
}

/* Detached user header above the call card */
.user-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 0 4px;
  margin-bottom: 10px;
}

.card-user {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: inherit;
}

.user-avatar {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
  letter-spacing: -0.3px;
  transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.user-avatar:hover {
  transform: scale(1.05);
}

.user-meta {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.user-name-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.username {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.2px;
}

.user-name-row .xp-badge {
  font-size: 10px;
  font-weight: 700;
  color: var(--brand-accent);
  background: var(--brand-accent-muted);
  padding: 2px 6px;
  border-radius: var(--radius-full);
  letter-spacing: 0.1px;
}

.stat-inline {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-tertiary);
}

.stat-inline svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}

.stat-inline.accuracy {
  color: var(--text-secondary);
}

.stat-inline.accuracy svg {
  color: var(--text-secondary);
}

.stat-inline.edge.pos {
  color: var(--brand-primary);
  font-weight: 700;
}

.stat-inline.edge.pos svg {
  color: var(--brand-primary);
}

.stat-inline.edge.neg {
  color: var(--brand-fade);
  font-weight: 700;
}

.stat-inline.edge.neg svg {
  color: var(--brand-fade);
}

.rank-col {
  height: 36px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.rank-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.rank-num {
  font-size: 20px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.5px;
  line-height: 1;
}

/* Call card body */
.call-card {
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: 14px;
  position: relative;
  transition: background-color 150ms ease, border-color 150ms ease;
}

.call-card:hover {
  background: var(--bg-surface-hover);
}

.card-time {
  position: absolute;
  top: 14px;
  right: 14px;
  font-size: 11px;
  color: var(--text-tertiary);
  font-weight: 500;
  white-space: nowrap;
}

.call-text-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 9px;
  padding-right: 56px;
}

.asset-icon {
  width: 22px;
  height: 22px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
}

.asset-icon.sol {
  background: linear-gradient(135deg, #9945FF 0%, #14F195 100%);
}

.asset-icon.btc {
  background: #F7931A;
}

.asset-icon.eth {
  background: #627EEA;
}

.call-text {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.3px;
  line-height: 1.3;
}

.price-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}

.price-current {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: -0.2px;
}

.price-sep {
  width: 1px;
  height: 11px;
  background: var(--border-default);
  flex-shrink: 0;
}

.price-target {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: -0.2px;
}

/* Market split bar */
.market-bar-wrap {
  margin-bottom: 10px;
}

.market-bar {
  height: 7px;
  border-radius: var(--radius-full);
  background: var(--brand-fade);
  position: relative;
  overflow: hidden;
}

.market-bar-fill {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  border-radius: var(--radius-full);
  background: linear-gradient(90deg, var(--brand-primary) 0%, var(--brand-primary-hover) 100%);
}

.bar-labels {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 5px;
}

/* Feed market card (2026-07-06 design): the market bar + a
 * VOLUME / TRADERS / AVG TRADE stat row split out of the info
 * card into its own tappable card. Stat styles mirror the
 * call-detail .mstat treatment. */
.market-card { margin-top: 8px; }
.mstat-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  margin: 12px 0;
}
.mstat.center { text-align: center; }
.mstat.right { text-align: right; }
.mstat-lbl {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-tertiary);
  margin-bottom: 3px;
}
.mstat-val {
  font-size: 18px;
  font-weight: 800;
  font-family: var(--font-mono);
  letter-spacing: -0.5px;
}

.bar-lbl {
  font-size: 11px;
  font-weight: 600;
}

.bar-lbl.back {
  color: var(--brand-primary);
}

.bar-lbl.fade {
  color: var(--brand-fade);
}

/* Action row */
.card-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px;
}

.action-btn {
  height: 40px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.1px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  text-decoration: none;
  transition: background-color 150ms ease, transform 150ms ease, filter 150ms ease;
}

.action-btn:hover {
  filter: brightness(1.1);
}

.action-btn:active {
  transform: scale(0.97);
}

.btn-back {
  background: var(--brand-primary);
  color: #fff;
}

.btn-fade {
  background: var(--brand-fade);
  color: #fff;
}

.btn-odds {
  font-size: 11px;
  font-weight: 600;
  opacity: 0.85;
}

/* Meta row beneath the buttons */
.card-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 11px;
}

.meta-chip {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
}

.meta-chip svg {
  color: var(--text-tertiary);
  opacity: 0.8;
  flex-shrink: 0;
}

/* ──── Discover (mock discover.html) ──────────────────────────── */

.filters {
  /* Sibling of `.content` (not inside it) per canonical
   * `tmp/updates/discover.html`. Sits in the flex column
   * between header and scrolling content, naturally pinned by
   * layout. Horizontal padding matches `.content` so pills
   * align with cards below. No `position: sticky` needed. */
  flex-shrink: 0;
  display: flex;
  gap: 8px;
  padding: 12px 18px;
  background: var(--bg-base);
}

.pill {
  flex-shrink: 0;
  height: 32px;
  padding: 0 14px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: var(--radius-full);
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  font-size: 13px;
  font-weight: 600;
  /* Canonical discover pill is mixed-case ("All", "SOL", "BTC",
   * "ETH"). The earlier global .pill rule (line ~643, used by
   * profile.rs status pills `.pill.live` / `.settled`) sets
   * text-transform: uppercase. Equal-specificity cascade order
   * wins this rule's redeclares but not the unset properties,
   * so reset text-transform explicitly. Same leak pattern as
   * the menu scoped fix. */
  text-transform: none;
  letter-spacing: -0.1px;
  cursor: pointer;
  transition: background-color 150ms ease, transform 150ms ease, filter 150ms ease, border-color 150ms ease, color 150ms ease;
}

.pill:hover {
  background: var(--bg-surface-hover);
  filter: brightness(1.1);
}

.pill:active {
  transform: scale(0.97);
}

.pill.active {
  background: var(--brand-primary);
  border-color: var(--brand-primary);
  color: #fff;
}

.pill-asset-icon {
  width: 14px;
  height: 14px;
  border-radius: var(--radius-full);
  font-size: 8px;
  font-weight: 800;
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.pill-asset-icon.sol {
  background: linear-gradient(135deg, #9945FF 0%, #14F195 100%);
}

.pill-asset-icon.btc {
  background: #F7931A;
}

.pill-asset-icon.eth {
  background: #627EEA;
}

.discover-content {
  padding-bottom: 8px;
}

/* Discover section blocks — canonical class names per
 * `tmp/updates/discover.html` (`.section` + `.section-title` +
 * `.label` + `.emoji` + `.view-btn`). Scoped under
 * `.discover-content` so the bare `.section` doesn't collide with
 * the global `.section { margin-top: 18px }` rule profile.rs
 * still owns. Margin-top reset explicit so the leak fix from
 * the menu page (same pattern) holds here too. */
.discover-content .section {
  margin-top: 0;
  margin-bottom: 18px;
}

.discover-content .section:last-child {
  margin-bottom: 0;
}

.discover-content .section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 4px 2px 10px;
  /* Reset uppercase + letter-spacing inherited from the global
   * `.section-title` rule (line ~451, used by profile/league
   * headers). Canonical discover titles are mixed-case
   * ("Top Traders", "Hot Calls", "Just Posted"). */
  text-transform: none;
  letter-spacing: -0.2px;
}

.discover-content .section-title .label {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.2px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* Global `.label` rule (line ~679, used by create_call form
   * labels) sets text-transform: uppercase + margin-bottom: 8px.
   * Reset both so the discover section title labels stay mixed-
   * case ("Top Traders", "Hot Calls") and don't push the
   * section-title row apart vertically. */
  text-transform: none;
  margin-bottom: 0;
}

.discover-content .section-title .emoji {
  font-size: 14px;
}

.view-btn {
  background: none;
  border: none;
  padding: 0;
  font-size: 12px;
  font-weight: 700;
  color: var(--brand-primary);
  letter-spacing: -0.1px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  text-decoration: none;
  transition: color 150ms ease, transform 150ms ease, filter 150ms ease;
}

.view-btn:hover {
  color: var(--brand-primary-hover);
  filter: brightness(1.1);
}

.view-btn svg {
  width: 14px;
  height: 14px;
}

/* Suggested trader row */
.trader {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  cursor: pointer;
  text-decoration: none;
  color: inherit;
  transition: background-color 150ms ease, border-color 150ms ease, transform 150ms ease;
}

.trader:hover {
  background: var(--bg-surface-hover);
}

.trader + .trader {
  margin-top: 8px;
}

.t-avatar {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
  letter-spacing: -0.3px;
  transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.t-avatar:hover {
  transform: scale(1.05);
}

.t-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.t-name-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.t-uname {
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: -0.3px;
}

.t-xp {
  font-size: 9px;
  font-weight: 700;
  color: var(--brand-accent);
  background: var(--brand-accent-muted);
  padding: 2px 6px;
  border-radius: var(--radius-full);
}

.t-stats {
  display: flex;
  align-items: center;
  gap: 8px;
}

.t-stat {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 600;
}

.t-stat svg {
  width: 11px;
  height: 11px;
  flex-shrink: 0;
}

.t-stat.accuracy {
  color: var(--text-secondary);
}

.t-stat.edge.pos {
  color: var(--brand-primary);
  font-weight: 700;
}

.t-stat.edge.neg {
  color: var(--brand-fade);
  font-weight: 700;
}

.follow-btn {
  flex-shrink: 0;
  padding: 6px 14px;
  background: transparent;
  color: var(--brand-primary);
  border: 1.5px solid var(--brand-primary);
  border-radius: var(--radius-full);
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: -0.1px;
  cursor: pointer;
  transition: background-color 150ms ease, transform 150ms ease, filter 150ms ease;
}
.follow-btn:hover  { background: var(--brand-primary-muted); }
.follow-btn:active { transform: scale(0.97); }
.follow-btn.is-following {
  color: var(--text-secondary);
  border-color: var(--text-secondary);
}
.follow-btn:disabled { opacity: 0.6; cursor: progress; }

/* Compact discover call card */
.c-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 10px 10px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  margin-bottom: 8px;
  cursor: pointer;
  text-decoration: none;
  color: inherit;
  transition: background-color 150ms ease, border-color 150ms ease, transform 150ms ease;
}

.c-card:last-child {
  margin-bottom: 0;
}

.c-card:hover {
  background: var(--bg-surface-hover);
}

.c-avatar {
  width: 34px;
  height: 34px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
  letter-spacing: -0.3px;
}

.c-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.c-top-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.c-username {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-secondary);
  letter-spacing: -0.2px;
}

.c-xp {
  font-size: 10px;
  font-weight: 700;
  color: var(--brand-accent);
  background: var(--brand-accent-muted);
  padding: 1px 6px;
  border-radius: var(--radius-full);
}

.c-call {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.2px;
  line-height: 1.2;
}

.c-asset {
  width: 18px;
  height: 18px;
  border-radius: var(--radius-full);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
}

.c-asset.sol {
  background: linear-gradient(135deg, #9945FF 0%, #14F195 100%);
}

.c-asset.btc {
  background: #F7931A;
}

.c-asset.eth {
  background: #627EEA;
}

.c-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.c-bottom-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
}

.c-vol,
.c-price {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--text-secondary);
  letter-spacing: -0.2px;
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

.c-time {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: var(--text-secondary);
  font-weight: 600;
}

.c-bottom-row svg {
  width: 11px;
  height: 11px;
  color: currentColor;
  flex-shrink: 0;
}

.c-sep {
  width: 1px;
  height: 10px;
  background: var(--border-default);
  flex-shrink: 0;
}

.c-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}

.mini-btn {
  height: 36px;
  min-width: 68px;
  padding: 0 10px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: -0.1px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  transition: filter 150ms ease, transform 150ms ease;
}

.mini-btn:hover {
  filter: brightness(1.1);
}

.mini-btn:active {
  transform: scale(0.96);
}

.mini-btn.back {
  background: var(--brand-primary);
  color: #fff;
}

.mini-btn.fade {
  background: var(--brand-fade);
  color: #fff;
}

.odds {
  font-size: 10px;
  font-weight: 600;
  opacity: 0.85;
}

/* ──── League legacy rules removed in Phase 1 cleanup (issue #29)
 *
 * The .league-title-row / .league-title / .league-subtitle /
 * .league-row / .league-row--{gold,silver,bronze} / .league-avatar
 * / .league-user-col / .league-name-row / .league-uname /
 * .league-stat-row / .league-list / .title-left class family was
 * replaced when `league.rs` ported to the canonical podium +
 * `.lb-row` markup. No render-side callers remain.
 *
 * .prize-pool / .prize-lbl / .prize-val survive below — those
 * still front the canonical title-row prize-pool pill. */

.prize-pool {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  padding: 8px 12px;
  background: var(--brand-primary-muted);
  border: 1px solid rgba(39, 188, 129, 0.25);
  border-radius: var(--radius-md);
  flex-shrink: 0;
}

.prize-lbl {
  font-size: 9px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--brand-primary);
}

.prize-val {
  font-size: 18px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.5px;
  line-height: 1;
}

.xp-col {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  margin-left: auto;
}

.xp-num {
  font-size: 14px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.3px;
  white-space: nowrap;
}

.reward-col {
  flex-shrink: 0;
  margin-left: -4px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-width: 30px;
}

.reward {
  font-size: 14px;
  font-weight: 800;
  color: var(--text-tertiary);
  letter-spacing: -0.3px;
  white-space: nowrap;
}

.reward--win {
  color: var(--brand-primary);
}

/* ──── Profile (canonical, issue #29 Phase 1) ──────────────────
 * Canonical `tmp/updates/profile.html` ships bare class names
 * `.profile`, `.name-row`, `.uname`, `.bio`, `.social`, `.stats`.
 * Add the rules here. Avatar uses the existing `.avatar.xl.av-*`
 * composition (set up in the Phase 0 canonical block), so a
 * `<div class="avatar xl av-purple-green">` element gets size +
 * gradient background for free.
 */
.profile {
  display: flex;
  align-items: center;
  gap: 14px;
  /* 10px top, not 18 — mock profile.html; 18 sat the whole user
     row + tabs 8px low (tester round 5, #188). */
  padding: 10px 0px 14px;
  position: relative;
}

.profile-info {
  flex: 1;
  min-width: 0;
}

.profile .name-row {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: nowrap;
}
.profile .name-row .badge-verified { width: 14px; height: 14px; }
.profile .name-row .badge-verified svg { width: 14px; height: 14px; }
.profile .name-row .badge-champ { font-size: 12px; }
.profile .name-row .badge-champ svg { width: 13px; height: 13px; }
.profile .name-row .badge-streak { font-size: 12px; }
.profile .name-row .badge-streak svg { width: 13px; height: 13px; }

.profile .uname {
  font-size: 20px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.5px;
}

.profile .bio {
  margin-top: 4px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  letter-spacing: -0.1px;
  line-height: 1.4;
}

.profile .social {
  margin-top: 6px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 12px;
  color: var(--text-tertiary);
}

.profile .social strong {
  color: var(--text-primary);
  font-weight: 700;
}

.profile .dot-sep {
  width: 3px;
  height: 3px;
  background: var(--text-tertiary);
  border-radius: 50%;
}

/* Row-3 stats line (2026-07-17): the stat-card grid is retired —
 * stats render as a text row matching .social directly above it. */
.profile .stats-line {
  margin-top: 6px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 12px;
  color: var(--text-tertiary);
}

.profile .stats-line strong {
  color: var(--text-primary);
  font-weight: 700;
}

.profile .stats-line strong.purple {
  color: var(--brand-accent-hover);
}

.profile .stats-line .denom {
  color: var(--text-tertiary);
}

/* History tab — 4-stat grid + section heading */
.history-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  /* 16/16 — History matches the Rewards-tab rhythm (round 6:
     "spacing is perfect here [Rewards] … do the same in
     profile-history"). Rewards itself strips these margins and
     spaces via .rewards-content's 16px padding+gap. */
  margin-top: 16px;
  margin-bottom: 16px;
}
.hist-stat {
  padding: 14px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  text-align: center;
}
.hs-val {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.7px;
  line-height: 1.1;
  color: var(--text-primary);
}
.hs-val.green { color: var(--brand-primary); }
.hs-val.gold  { color: var(--gold-soft); }
.hs-val .denom {
  color: var(--text-tertiary);
  /* Mock (profile-history): denominator reads smaller than the
     numerator — business re-confirmed 2026-08-10. */
  font-size: 0.75em;
}
.hs-lbl {
  margin-top: 4px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-tertiary);
}

.section-lbl {
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-tertiary);
  padding: 0 20px;
  margin: 0 0 10px;
}

/* Rewards-content already pads its children at the screen edge,
 * so a section-lbl inside it shouldn't double-stack its own
 * horizontal padding — that pushed the EARNINGS heading ~40px
 * from the left edge instead of sitting flush with the cards
 * above + below it. Strip the inner padding so the label
 * aligns left with `.claim-card` / `.earn-list` siblings.
 * Also drop the 10px bottom margin so the heading hugs the
 * earn-list it labels. */
.rewards-content .section-lbl {
  padding: 0;
  margin-bottom: 0;
}

/* List wrapper used by Portfolio + History tabs */
.list {
  padding: 0 0px 24px;
  display: flex;
  flex-direction: column;
  /* Mock card gap is 8px (business 2026-08-10: 14px read too airy). */
  gap: 8px;
}

/* Rewards tab content */
.rewards-content {
  padding: 16px 0 24px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Inside `.rewards-content` the flex column already supplies
   vertical spacing via its gap, so strip the default
   `.history-stats` margins (mock profile-rewards.html; without
   this the Volume/Rewards tiles sat 28px under the tabs vs
   History's 12px — tester round 5, #188). */
.rewards-content .history-stats {
  margin-top: 0;
  margin-bottom: 0;
}

/* Claim card per canonical `tmp/updates/profile-rewards.html`:
 * gold-tinted gradient card with three flex children — icon
 * (gold circle + $ glyph), text (label + amount + meta), and
 * the green Claim button. Padding 14px (not 16px/18px) +
 * `border-radius: var(--radius-md)` (12px) + a soft outer
 * box-shadow glow to make the gold tones read. */
/* .claim-card family removed 2026-08-10 (business round 3): the
   Rewards tab has no claim surface — rewards leave via Wallet
   Withdraw. .claim-btn stays for History rows' payout claims. */
.claim-meta {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  margin-top: 3px;
}

.claim-btn {
  flex-shrink: 0;
  padding: 0 28px;
  height: 48px;
  border-radius: var(--radius-md);
  border: none;
  background: var(--brand-primary);
  color: #fff;
  font-family: var(--font-sans);
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: -0.2px;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(39, 188, 129, 0.32);
  transition: filter 150ms ease, transform 100ms ease;
}
.claim-btn:hover { filter: brightness(1.06); }
.claim-btn:active { transform: scale(0.97); }
.claim-btn:disabled {
  background: var(--bg-surface-elevated);
  color: var(--text-tertiary);
  box-shadow: none;
  cursor: default;
}
.claim-btn:disabled:hover { filter: none; }
/* Compact variant for bet-history winner claims (WS4). */
.claim-btn.mini {
  height: 30px;
  padding: 0 14px;
  font-size: 12.5px;
  border-radius: var(--radius-sm);
  box-shadow: 0 2px 8px rgba(39, 188, 129, 0.28);
}
.claim-done {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-tertiary);
}

.rewards-summary {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.r-stat {
  padding: 12px 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  text-align: center;
}
.r-stat-lbl {
  font-size: 10px;
  font-weight: 700;
  color: var(--text-tertiary);
  letter-spacing: 0.04em;
}
.r-stat-val {
  margin-top: 4px;
  font-family: var(--font-mono);
  font-size: 20px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.4px;
}
.r-stat-val.green { color: var(--brand-primary); }
/* Negative P&L on the Portfolio tile pair (#136). Same red as
 * `.pnl.neg` on the History rows so a loss reads identically
 * whether you're looking at the total or one settled bet. */
.r-stat-val.red { color: var(--brand-fade); }

/* All / Predictions / Trades pills (v2, 2026-08-05 — reinstated,
 * reversing #136 whose Balance/P&L tiles moved to /wallet). Anchors,
 * not buttons: the filter is server-side (?show=). */
.earn-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.earn-card {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 9px;
  padding: 12px 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.earn-asset .asset-dot {
  width: 20px;
  height: 20px;
  border-radius: var(--radius-full);
  /* Default = SOL gradient. BTC and ETH override below via
   * `data-asset` attribute selectors so each token-specific
   * background lives in one place (a new token only adds one
   * token var + one selector). */
  background: var(--asset-sol);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 10px;
  font-weight: 800;
}
.earn-asset .asset-dot[data-asset="btc"] { background: var(--asset-btc); }
.earn-asset .asset-dot[data-asset="eth"] { background: var(--asset-eth); }
.earn-asset .asset-dot[data-asset="sol"] { background: var(--asset-sol); }
.earn-title {
  flex: 1;
  min-width: 0;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* V3 earn-card grammar (2026-08-08 drop): column card of
   earn-head (asset + title + bare time) / earn-chips (Position +
   settle pill + gold amount) / earn-stats. */
.earn-head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.earn-head .earn-time {
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  font-family: var(--font-mono);
}
.earn-chips { display: flex; align-items: center; gap: 8px; }
.earn-chips .earn-amount { margin-left: auto; }
.earn-chips .creator-pos { padding: 2px 8px; font-size: 10.5px; }
.earn-chips .creator-pos svg { width: 9px; height: 9px; }
.earn-amount {
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 800;
  color: var(--gold, #FFD700);
  letter-spacing: -0.3px;
  white-space: nowrap;
  flex-shrink: 0;
}
.earn-stats {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding-top: 9px;
  border-top: 1px solid var(--border-subtle);
  font-size: 11px;
  font-weight: 600;
  color: var(--text-tertiary);
}
.earn-stats .es-left,
.earn-stats .es-right { display: inline-flex; align-items: center; gap: 5px; color: var(--text-tertiary); }
.earn-stats .es-left { justify-self: start; }
.earn-stats .es-right { justify-self: end; }
.earn-stats .es-num {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--text-secondary);
}
/* V3 history rows: hist-head / hist-chips share the earn grammar. */
.hist-head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.hist-title {
  flex: 1;
  min-width: 0;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hist-time {
  margin-left: auto;
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  font-family: var(--font-mono);
}
.hist-chips { display: flex; align-items: center; gap: 8px; }
.hist-chips .pnl { margin-left: auto; }
.hist-chips .creator-pos,
.hist-chips .pos-chip { padding: 2px 8px; font-size: 10.5px; }
.hist-chips .creator-pos svg,
.hist-chips .pos-chip svg { width: 9px; height: 9px; }
.hist-entry { display: flex; flex-direction: column; gap: 10px; }
.list .call.settled { display: flex; flex-direction: column; align-items: stretch; gap: 9px; }

/* ──── Profile (mock profile.html) ────────────────────────────── */

/* `.profile-section` removed in Phase 1 cleanup (issue #29) —
 * canonical `.profile` rule earlier in this file owns the
 * profile-header layout now. */

.profile-edit {
  /* v2 (2026-08-06): lives INSIDE .name-row, pushed to the row's far
   * right by margin-left: auto — the old absolute top-right anchor
   * aligned it under a menu hamburger that detail chrome no longer
   * renders. No circle border (that's the Followed button's look);
   * bare 12px pencil, 24px tap target shared with Follow/Followed so
   * future state transitions morph in place. */
  margin-left: auto;
  align-self: center;
  width: 24px;
  height: 24px;
  background: transparent;
  border: none;
  padding: 0;
  color: var(--text-secondary);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: color 150ms ease, transform 150ms ease;
}

.profile-edit:hover {
  color: var(--text-primary);
}

.profile-edit:active { transform: scale(0.94); }

.profile-edit svg {
  width: 12px;
  height: 12px;
  display: block;
}

.avatar-xl {
  width: 64px;
  height: 64px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  font-weight: 800;
  color: #fff;
  letter-spacing: -0.5px;
  transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.avatar-xl:hover {
  transform: scale(1.05);
}

.profile-info {
  flex: 1;
  min-width: 0;
}

/* `.profile-name-row` / `.profile-uname` / `.profile-bio` /
 * `.profile-social` / `.profile-stats` removed in Phase 1
 * cleanup (issue #29). Replaced by canonical scoped rules
 * (`.profile .name-row`, `.profile .uname`, `.profile .bio`,
 * `.profile .social`, `.stats`) earlier in this file. */

/* `.stat-card` / `.stat-val` / `.stat-lbl` retired 2026-07-17 —
 * the profile stats row is a `.stats-line` text row now. */

/* `.profile-tabs` / `.profile-tab*` / `.profile-list` /
 * `.profile-call*` removed in Phase 1 cleanup (issue #29).
 * Profile page now uses canonical `.main-tabs` / `.main-tab` for
 * its tab pivot and `.list` + `.call.settled` (+ `.bet-history`
 * modifier) for History rows. The legacy `.profile-call`
 * markup is gone. */

.asset-dot {
  width: 20px;
  height: 20px;
  border-radius: var(--radius-full);
  background: linear-gradient(135deg, #9945FF 0%, #14F195 100%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
}

.settled-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border-subtle);
}

.settled-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: -0.1px;
}

.settled-badge svg {
  width: 11px;
  height: 11px;
}

.settled-badge--hit {
  background: var(--brand-primary-muted);
  color: var(--brand-primary);
}

.settled-badge--missed {
  background: var(--brand-fade-muted);
  color: var(--brand-fade);
}

.settled-time {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
}

/* Asset-dot color variants used across profile own-call + bet cards. */
.asset-dot--sol {
  background: linear-gradient(135deg, #9945FF 0%, #14F195 100%);
}
.asset-dot--btc {
  background: #F7931A;
}
.asset-dot--eth {
  background: #627EEA;
}
/* The bottom sheets set `data-asset` from JS (bet sheet, confirm
   sheets) rather than the modifier classes — without these a
   BTC/ETH prediction rendered the SOL gradient disc behind a BTC
   glyph (tester round 5, #188 item 9). */
.asset-dot[data-asset="sol"] { background: var(--asset-sol); }
.asset-dot[data-asset="btc"] { background: var(--asset-btc); }
.asset-dot[data-asset="eth"] { background: var(--asset-eth); }

/* ──── Profile "Calls" tab — .own-call (mock profile-calls.html) ── */

.own-call {
  padding: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  transition: background-color 150ms ease;
}

.own-call + .own-call {
  margin-top: 10px;
}

.own-call:hover {
  background: var(--bg-surface-hover);
}

.oc-top {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.oc-text {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: -0.2px;
  line-height: 1.25;
  color: var(--text-primary);
}

.oc-time {
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
}

.oc-price-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: 10px;
}

.oc-sep {
  width: 1px;
  height: 11px;
  background: var(--border-default);
  flex-shrink: 0;
}

.oc-target {
  color: var(--text-secondary);
}

.oc-bar {
  height: 7px;
  border-radius: var(--radius-full);
  background: var(--brand-fade);
  position: relative;
  overflow: hidden;
  margin-bottom: 5px;
}

.oc-bar-fill {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  border-radius: var(--radius-full);
  background: linear-gradient(90deg, var(--brand-primary) 0%, var(--brand-primary-hover) 100%);
}

.oc-bar-labels {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11px;
  font-weight: 600;
  margin-bottom: 8px;
}

.oc-bar-labels .back {
  color: var(--brand-primary);
}

.oc-bar-labels .fade {
  color: var(--brand-fade);
}

.oc-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
}

.oc-meta-right {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.oc-meta-right svg {
  width: 11px;
  height: 11px;
  flex-shrink: 0;
  opacity: 0.8;
}

/* ──── Profile "Bets" tab — .bet (mock profile-bets.html) ─────── */

.bet {
  display: block;
  padding: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  text-decoration: none;
  color: inherit;
  transition: background-color 150ms ease;
}

.bet + .bet {
  margin-top: 10px;
}

.bet:hover {
  background: var(--bg-surface-hover);
}

.bet-top {
  display: flex;
  align-items: center;
  gap: 10px;
}

.b-avatar {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
  letter-spacing: -0.3px;
}

.b-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.b-user-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.b-username {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-secondary);
  letter-spacing: -0.2px;
}

.b-xp {
  font-size: 9px;
  font-weight: 700;
  color: var(--brand-accent);
  background: var(--brand-accent-muted);
  padding: 1px 6px;
  border-radius: var(--radius-full);
}

.b-call {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.2px;
  line-height: 1.25;
}

.b-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.b-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
}

.b-meta .price,
.b-meta .vol,
.b-meta .time {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-weight: 600;
  color: var(--text-secondary);
}

.b-meta svg {
  width: 11px;
  height: 11px;
  flex-shrink: 0;
}

.b-sep {
  width: 1px;
  height: 10px;
  background: var(--border-default);
  flex-shrink: 0;
}

.arc-gauge {
  flex-shrink: 0;
  align-self: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.arc-gauge svg { display: block; }

.arc-text {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  margin-top: -14px;
}

.arc-pct {
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 800;
  letter-spacing: -0.4px;
  line-height: 1;
  color: var(--text-primary);
}

.arc-lbl {
  font-size: 8.5px;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: var(--text-secondary);
  text-transform: uppercase;
}

.bet-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border-subtle);
}

.pos-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: -0.1px;
}

.pos-badge svg {
  width: 11px;
  height: 11px;
}

.pos-badge--backed {
  background: var(--brand-primary-muted);
  color: var(--brand-primary);
}

.pos-badge--faded {
  background: var(--brand-fade-muted);
  color: var(--brand-fade);
}

.pos-mid {
  flex: 1;
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-tertiary);
  letter-spacing: -0.1px;
}

.pos-size {
  font-size: 14px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.3px;
}

/* ──── Create Prediction (mocks create-1 + create-2 combined) ── */

.create-prediction {
  padding: 8px 0 16px;
  display: flex;
  flex-direction: column;
  gap: 22px;
  min-height: 100%;
}

/* `.cc-creator*` rules removed in Phase 1 cleanup (issue #29).
 * The creator-card markup it styled was inside an HTML comment
 * block (Business 2026-05-12) and got physically removed when
 * the format! template no longer threaded creator_grad/initial/
 * handle/xp/acc/edge args. Restore from git if the card returns. */

.cc-section {
  display: flex;
  flex-direction: column;
}

.cc-section-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-tertiary);
  margin: 0 2px 12px;
}

/* Asset pills (mock create-1 .asset-pills) */
.asset-pills {
  display: flex;
  gap: 8px;
}

.asset-pill {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px;
  background: var(--bg-surface);
  border: 1.5px solid var(--border-subtle);
  border-radius: var(--radius-md);
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  color: inherit;
  transition: background-color 150ms ease, border-color 150ms ease, transform 150ms ease;
}

.asset-pill:hover {
  background: var(--bg-surface-hover);
  border-color: var(--border-default);
}

.asset-pill:active {
  transform: scale(0.97);
}

.asset-pill.selected {
  border-color: var(--brand-primary);
  background: var(--brand-primary-muted);
}

.a-icon {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
}

.a-icon.sol {
  background: linear-gradient(135deg, #9945FF 0%, #14F195 100%);
}

.a-icon.btc {
  background: #F7931A;
}

.a-icon.eth {
  background: #627EEA;
}

.a-icon svg {
  width: 64%;
  height: 64%;
  display: block;
}

.a-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  min-width: 0;
}

.a-sym {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: -0.3px;
}

.a-price {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: -0.2px;
  margin-top: 1px;
}

/* Target row (mock create-1 .target-row) */
.target-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
}

.price-input {
  flex: 1;
  min-width: 0;
  text-align: center;
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.5px;
  color: var(--text-primary);
  background: var(--bg-surface);
  border: 2px solid var(--brand-primary);
  border-radius: var(--radius-md);
  padding: 10px 8px;
  outline: none;
  box-shadow: 0 0 0 3px rgba(39, 188, 129, 0.12);
  font-family: inherit;
}

.price-input::placeholder {
  color: var(--text-tertiary);
}

.pct-chip,
.prob-inline {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 8px 10px;
  background: var(--bg-surface-elevated);
  border-radius: var(--radius-md);
  min-width: 64px;
}

.pct-chip-val {
  font-size: 13px;
  font-weight: 800;
  color: var(--brand-primary);
  letter-spacing: -0.3px;
  line-height: 1;
}

.pct-chip-val.is-negative {
  color: var(--brand-fade);
}

.pct-chip-lbl,
.prob-lbl {
  font-size: 8px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-tertiary);
}

.prob-val {
  font-size: 20px;
  font-weight: 800;
  color: var(--brand-accent-hover);
  letter-spacing: -0.5px;
  line-height: 1;
}

/* Step 2 initial-probability row per canonical `tmp/updates/
 * create-2.html`. Sits between the call-card preview and the
 * back-your-call stepper. Left side stacks an uppercase label
 * + a big mono percentage; right side is a feed-style
 * `.btn-back` ("Back $0.25") so the visual matches the actual
 * buy action a creator would take to back their own call. */
.prob-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.prob-row .prob-left {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.prob-row .prob-lbl {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-tertiary);
}
.prob-row .prob-val {
  font-family: var(--font-mono);
  font-size: 32px;
  font-weight: 800;
  color: var(--brand-accent-hover);
  letter-spacing: -1px;
  line-height: 1;
}
.prob-row .btn-back {
  height: 40px;
  padding: 0 16px;
  border-radius: var(--radius-md);
  border: none;
  background: var(--brand-primary);
  color: #fff;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.1px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  cursor: pointer;
}
.prob-row .btn-back .btn-odds {
  font-size: 11px;
  font-weight: 600;
  font-family: var(--font-mono);
  opacity: 0.75;
}

/* Preset +/- buttons (mock create-1 .presets) */
.presets {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-top: 12px;
}

.preset {
  padding: 8px 4px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-full);
  background: var(--bg-surface);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.2px;
  cursor: pointer;
  font-family: inherit;
  transition: background-color 150ms ease, transform 150ms ease, filter 150ms ease, border-color 150ms ease, color 150ms ease;
}

.preset:hover {
  background: var(--bg-surface-hover);
  color: var(--text-primary);
  filter: brightness(1.1);
}

.preset:active {
  transform: scale(0.97);
}

.preset.active {
  background: var(--brand-primary);
  border-color: var(--brand-primary);
  color: #fff;
}

.preset.fade-preset:hover {
  color: var(--brand-fade);
  border-color: var(--brand-fade);
}

.preset.fade-preset.active {
  background: var(--brand-fade);
  border-color: var(--brand-fade);
  color: #fff;
}

/* Deadline pills (mock create-1 .deadline-pills) */
.deadline-pills {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
}

.dl-pill {
  padding: 9px 4px;
  border: 1.5px solid var(--border-subtle);
  border-radius: var(--radius-full);
  background: var(--bg-surface);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.2px;
  cursor: pointer;
  font-family: inherit;
  transition: background-color 150ms ease, transform 150ms ease, filter 150ms ease, border-color 150ms ease, color 150ms ease;
}

.dl-pill:hover {
  background: var(--bg-surface-hover);
  color: var(--text-primary);
  filter: brightness(1.1);
}

.dl-pill:active {
  transform: scale(0.97);
}

.dl-pill.active {
  background: var(--brand-primary);
  border-color: var(--brand-primary);
  color: #fff;
}

.deadline-hint {
  margin-top: 12px;
  padding: 10px 12px;
  background: var(--bg-surface-elevated);
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.dh-lbl {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-tertiary);
}

.dh-val {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.2px;
}

/* Live preview call card (mock create-2 .call-card) */
.cc-call-card {
  position: relative;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: 16px;
}

.cc-call-heading {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}

.cc-call-card .asset-icon {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
  background: linear-gradient(135deg, #9945FF 0%, #14F195 100%);
}

.cc-call-title {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.4px;
  line-height: 1.25;
  color: var(--text-primary);
}

.cc-price-block {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}

.cc-price-now,
.cc-price-target {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-secondary);
  letter-spacing: -0.3px;
}

.cc-price-sep {
  width: 1px;
  height: 12px;
  background: var(--border-default);
  flex-shrink: 0;
}

.cc-meta-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.cc-meta-box {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 10px;
  background: var(--bg-surface);
  border-radius: var(--radius-sm);
}

.cc-meta-lbl {
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-tertiary);
  flex-shrink: 0;
}

.cc-meta-val {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
}

/* .cc-disclaimer removed 2026-08-10 (business): no edit-warning
   disclaimer on the create flow or any confirm sheet. */

.cc-actions {
  margin-top: auto;
  padding-top: 16px;
  flex-shrink: 0;
}

/* ─── V3 review step (new/alpha/review-prediction.html) ─────────
   Compact call summary + one combined bubble. The "Back your
   prediction" title block (dropped 2026-08-09) is RESTORED per
   round-6 feedback, with the full mock bubble grammar. This is the
   SET-POSITION step of the create UX flow (2026-08-10): backing
   happens here, not in a post-creation bet sheet. */
.rp-call-summary {
  display: flex; flex-direction: column; gap: 8px;
  padding: 14px;
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.rp-cs-line { display: flex; align-items: center; gap: 10px; }
.rp-cs-icon {
  width: 22px; height: 22px;
  border-radius: var(--radius-full);
  background: var(--asset-sol);
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; flex-shrink: 0;
}
.rp-cs-icon[data-asset="btc"] { background: var(--asset-btc); }
.rp-cs-icon[data-asset="eth"] { background: var(--asset-eth); }
.rp-cs-icon svg { width: 62%; height: 62%; display: block; }
.rp-cs-text {
  flex: 1; min-width: 0;
  font-size: 15px; font-weight: 800;
  letter-spacing: -0.3px; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rp-cs-price-row { display: flex; align-items: center; gap: 8px; }
.rp-cs-price,
.rp-cs-target { font-family: var(--font-mono); font-size: 12px; font-weight: 600; color: var(--text-secondary); letter-spacing: -0.2px; }
/* NOTE round 6: secondary, not the mock's tertiary — business flagged
   the price + 'to target' line as too dark. */
.rp-cs-sep { width: 1px; height: 11px; background: var(--border-default); flex-shrink: 0; }
.rp-cs-target .tt-val { font-weight: 700; }
.rp-cs-deadline {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  color: var(--text-tertiary); letter-spacing: -0.2px; white-space: nowrap;
}
.rp-cs-deadline svg { width: 12px; height: 12px; flex-shrink: 0; }

.rp-combined-bubble {
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 14px 14px 10px;
  display: flex; flex-direction: column; gap: 12px;
}
.rp-combined-bubble > :where(.wallet-row, .rp-back-group, .shares-section, .breakdown) {
  background: transparent; border: none; border-radius: 0; padding: 0;
}
.rp-combined-bubble > * + * { padding-top: 12px; }
.rp-combined-bubble > .rp-back-group + .wallet-row { padding-top: 12px; border-top: 1px solid var(--border-subtle); }
.rp-combined-bubble > .wallet-row + .shares-section { padding-top: 8px; }
.rp-combined-bubble > .shares-section { padding-bottom: 0; }
.rp-combined-bubble > .breakdown { padding: 6px 0 0; }
.rp-combined-bubble > .breakdown .row:last-child { padding-bottom: 0; }
/* Back-your-prediction header (restored round 6 — the title/hint
   block dropped 2026-08-09 is back per tester feedback). */
.rp-back-group { display: flex; flex-direction: column; gap: 10px; }
.rp-back-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.rp-back-title { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.rp-back-label { font-size: 14px; font-weight: 700; letter-spacing: -0.2px; color: var(--text-primary); }
.rp-back-hint { font-size: 11px; font-weight: 500; color: var(--text-tertiary); letter-spacing: -0.1px; }
.rp-back-prob { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex-shrink: 0; }
.rp-back-prob-lbl { font-size: 11px; font-weight: 600; color: var(--text-tertiary); letter-spacing: -0.1px; text-align: right; }
.rp-back-prob-val { font-family: var(--font-mono); font-size: 15px; font-weight: 800; color: var(--brand-accent-hover); letter-spacing: -0.3px; text-align: right; }
/* Probability >= 90%: red, not purple (round 6) — a near-certain
   call prices its shares near $1 and deserves the warning color. */
.prob-val.hot, .rp-back-prob-val.hot { color: var(--brand-fade); }
/* Step-2 disclaimer (restored round 6). */
.rp-disclaimer {
  margin: 4px 0 12px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  letter-spacing: -0.1px;
  line-height: 1.5;
  text-align: center;
  padding: 0 8px;
}


.cta {
  width: 100%;
  height: 52px;
  border: none;
  border-radius: var(--radius-md);
  background: var(--brand-primary);
  color: #fff;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: -0.2px;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 4px 12px rgba(39, 188, 129, 0.3);
  transition: background-color 150ms ease, transform 150ms ease, filter 150ms ease;
}

.cta:hover {
  background: var(--brand-primary-hover);
  filter: brightness(1.1);
}

.cta:active {
  transform: scale(0.97);
}

.cta[disabled] {
  opacity: 0.6;
  cursor: not-allowed;
}

/* ──── Create Prediction form sectioning (#11) ──────────────── */

/* Each .form-section is a labeled fieldset-shaped block. The mock
 * (create-1.html) renders these as flat groups separated by a tiny
 * uppercase label; the form-card border around the whole block
 * already provides the chrome, so .form-section is just spacing. */
.form-section + .form-section {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--border-subtle);
}

.form-section-label {
  font-size: 11px;
  font-weight: 800;
  color: var(--text-tertiary);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 12px;
}

.form-disclaimer {
  margin-top: 18px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  font-size: 11.5px;
  font-weight: 500;
  color: var(--text-tertiary);
  letter-spacing: -0.1px;
  text-align: center;
}

/* XP badge next to handle (#14 — profile hero). Mirrors mock
 * profile.html .xp-badge: accent-purple text on accent-muted bg. */
.xp-pill {
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  padding: 2px 7px;
  border-radius: var(--radius-full);
  background: var(--brand-accent-muted);
  color: var(--brand-accent-hover);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.2px;
  vertical-align: middle;
}

/* ================================================================
   CANONICAL DESIGN SYSTEM — appended Phase 0 of UI replacement (#29
   on GitHub). Source: tmp/tradeleague-v1 designs/design-system/
   components.css. New screens reference these class names; legacy
   rules above remain until per-screen ports (Phase 1+) migrate
   markup. Where a class name collides, this section (loaded later)
   wins by CSS cascade order — intended, so the new design wins on
   any screen that opts into it.
   ================================================================ */

/* ─── Motion primitives (canonical) ───────────────────────────── */
@keyframes ds-shimmer {
  0%   { opacity: 0.5; }
  50%  { opacity: 0.8; }
  100% { opacity: 0.5; }
}
.skeleton-pulse { animation: ds-shimmer 1.5s infinite ease-in-out; }

@keyframes fadeUp {
  0%   { opacity: 0; transform: translateY(6px); }
  100% { opacity: 1; transform: translateY(0); }
}
.anim-in { animation: fadeUp 320ms ease both; }

@keyframes pop {
  0%   { transform: scale(0.9); opacity: 0; }
  100% { transform: scale(1);   opacity: 1; }
}

@keyframes podiumRise {
  0%   { opacity: 0; transform: translateY(20px); }
  100% { opacity: 1; transform: translateY(0); }
}

@keyframes pulse-soft {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.04); }
}

@keyframes fall {
  0%   { transform: translateY(0)     rotate(0deg);   opacity: 0; }
  10%  { opacity: 1; }
  100% { transform: translateY(105vh) rotate(720deg); opacity: 0.9; }
}

@keyframes skShimmer {
  0%   { background-position: -200% 0; }
  100% { background-position:  200% 0; }
}

/* ─── Avatars (.avatar + .av-*) ───────────────────────────────── */
.avatar {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
  letter-spacing: -0.3px;
  transition: transform 200ms var(--ease-spring);
}
.avatar:hover { transform: scale(1.05); }
.avatar.xs        { width: 20px; height: 20px; font-size:  9px; }
.avatar.sm        { width: 24px; height: 24px; font-size: 10px; }
.avatar.md        { width: 36px; height: 36px; font-size: 14px; }
.avatar.lg        { width: 48px; height: 48px; font-size: 19px; }
.avatar.xl        { width: 64px; height: 64px; font-size: 26px; }
.avatar.podium-2-3 { width: 56px; height: 56px; font-size: 20px; }
.avatar.podium-1   { width: 64px; height: 64px; font-size: 24px; }
.avatar.av-purple-green  { background: var(--av-purple-green); }
.avatar.av-orange-red    { background: var(--av-orange-red); }
.avatar.av-blue-purple   { background: var(--av-blue-purple); }
.avatar.av-amber-rose    { background: var(--av-amber-rose); }
.avatar.av-purple-orange { background: var(--av-purple-orange); }
.avatar.av-green-blue    { background: var(--av-green-blue); }
.avatar.av-violet-blue   { background: var(--av-violet-blue); }
.avatar.av-green-purple  { background: var(--av-green-purple); }
.avatar.av-bronze-amber  { background: var(--av-bronze-amber); }
/* An avatar that carries a picture (photo or the default) paints a
   neutral rim colour, NOT the palette gradient: the <img> decodes a
   frame or more after first paint (always on a cold cache, often on
   WebKit), and gradient→grey read as a flash (user report 2026-10-01).
   #c7c8cd is the default picture's own rim, so the hand-off is
   invisible. The gradient survives only for the letter-rendering `?`
   placeholder. Specificity (0,2,1) beats `.avatar.av-*` (0,2,0). */
.avatar:has(> img.avatar-img),
.pod-avatar:has(> img.avatar-img) { background: #c7c8cd; }

.avatar-wrap {
  position: relative;
  width: 56px;
  height: 56px;
  flex-shrink: 0;
}
.avatar-wrap::before {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: var(--radius-full);
  background: conic-gradient(from 0deg, var(--gold-soft), var(--gold), var(--gold-deep), var(--gold), var(--gold-soft));
  filter: drop-shadow(0 0 8px rgba(255, 215, 0, 0.4));
}
.avatar-wrap > .avatar { position: relative; border: 3px solid var(--bg-base); }

/* ─── Badges ──────────────────────────────────────────────────── */
.badge-verified {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--brand-primary);
}
.badge-verified svg { width: 12px; height: 12px; }
.profile-info .badge-verified,
.badge-verified.lg { width: 14px; height: 14px; }
.profile-info .badge-verified svg,
.badge-verified.lg svg { width: 14px; height: 14px; }

.badge-champ {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: 10px;
  font-weight: 800;
  flex-shrink: 0;
  line-height: 1;
}
.badge-champ svg { width: 11px; height: 11px; flex-shrink: 0; }
.badge-champ.gold   { color: var(--gold); }
.badge-champ.silver { color: var(--silver); }
.badge-champ.bronze { color: var(--bronze); }

.badge-streak {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: 10px;
  font-weight: 800;
  color: var(--streak);
  flex-shrink: 0;
  line-height: 1;
}
.badge-streak svg { width: 11px; height: 11px; flex-shrink: 0; }

/* ─── Asset icons ─────────────────────────────────────────────── */
.asset-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  color: #fff;
  font-weight: 800;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  font-size: 10px;
}
.asset-icon.xs { width: 14px; height: 14px; font-size:  8px; }
.asset-icon.sm { width: 18px; height: 18px; font-size:  9px; }
.asset-icon.md { width: 22px; height: 22px; font-size: 10px; }
.asset-icon.lg { width: 28px; height: 28px; font-size: 13px; }
.asset-icon[data-asset="sol"] { background: var(--asset-sol); }
.asset-icon[data-asset="btc"] { background: var(--asset-btc); }
.asset-icon[data-asset="eth"] { background: var(--asset-eth); }

/* SVG marks inside .asset-icon: percentage sizing so a single SVG
   covers .xs/.sm/.md/.lg. White fill (currentColor on the path)
   inherits from .asset-icon color: #fff above. */
.asset-icon svg {
  width: 64%;
  height: 64%;
  display: block;
}
/* .pill-asset-icon (discover filter pills) uses the same SVG payload
   but the container is smaller; tighter percentage keeps the mark
   from crowding the pill bg. */
.pill-asset-icon svg {
  width: 60%;
  height: 60%;
  display: block;
}
/* .asset-dot (earn-card + bet-history) and the cc preview chip use
   the same inline SVG. Dot defaults to 22px so 14px svg renders
   crisp; preview .asset-icon is 28px so 18px svg matches. */
.asset-dot svg {
  width: 64%;
  height: 64%;
  display: block;
}

/* ─── Buttons (canonical) ─────────────────────────────────────── */
.btn-primary,
.btn.primary {
  background: var(--brand-primary);
  color: #fff;
  border-color: transparent;
  box-shadow: 0 4px 14px rgba(39, 188, 129, 0.32);
  height: 48px;
  padding: 0 20px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  font-family: var(--font-sans);
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: -0.2px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease, transform 150ms ease, filter 150ms ease;
}
.btn-primary:hover,
.btn.primary:hover { background: var(--brand-primary-hover); filter: brightness(1.06); }
.btn-primary:active,
.btn.primary:active { transform: scale(0.98); }

.btn-ghost,
.btn.ghost {
  background: none;
  border: none;
  color: var(--text-tertiary);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.1px;
  padding: 6px 12px;
  cursor: pointer;
}
.btn-ghost:hover,
.btn.ghost:hover { color: var(--text-secondary); }

.btn-destructive,
.btn.destructive {
  background: var(--brand-fade-muted);
  border: 1px solid rgba(239, 68, 68, 0.30);
  color: var(--brand-fade);
  height: 48px;
  padding: 0 20px;
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: -0.2px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.btn-destructive:hover,
.btn.destructive:hover { background: rgba(239, 68, 68, 0.22); border-color: rgba(239, 68, 68, 0.45); }

.icon-btn {
  width: 40px;
  height: 40px;
  border: none;
  background: none;
  color: var(--text-primary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  padding: 0;
  transition: background-color 150ms ease, transform 150ms ease;
}
.icon-btn:hover  { background: var(--bg-surface); }
.icon-btn:active { transform: scale(0.97); }
.icon-btn svg    { width: 20px; height: 20px; }

.mini-btn {
  height: 36px;
  min-width: 68px;
  padding: 0 10px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: -0.1px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  transition: background-color 150ms ease, transform 150ms ease, filter 150ms ease;
}
.mini-btn:hover  { filter: brightness(1.1); }
.mini-btn:active { transform: scale(0.96); }
.mini-btn.yes,
.mini-btn.back { background: var(--brand-primary); color: #fff; }
.mini-btn.no,
.mini-btn.fade { background: var(--brand-fade);    color: #fff; }
.mini-btn .odds { font-size: 10px; font-weight: 500; font-family: var(--font-mono); opacity: 1; }

.empty-cta {
  padding: 0 28px;
  height: 48px;
  border-radius: var(--radius-md);
  border: none;
  background: var(--brand-primary);
  color: #fff;
  font-family: var(--font-sans);
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: -0.2px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  box-shadow: 0 4px 14px rgba(39, 188, 129, 0.32);
  transition: filter 150ms ease, transform 150ms ease;
}
.empty-cta:hover  { filter: brightness(1.06); }
.empty-cta:active { transform: scale(0.98); }
.empty-cta svg    { width: 15px; height: 15px; }

.action-btn {
  height: 40px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.1px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  transition: background-color 150ms ease, transform 150ms ease, filter 150ms ease;
}
.action-btn:hover  { filter: brightness(1.1); }
.action-btn:active { transform: scale(0.97); }
.btn-back  { background: var(--brand-primary); color: #fff; }
.btn-fade  { background: var(--brand-fade);    color: #fff; }
.btn-odds  { font-size: 11px; font-weight: 600; font-family: var(--font-mono); opacity: 0.75; }
/* Scoped override: on the primary Yes/No action buttons the odds are
   a real number the user acts on, not a caption. Left the bare
   .btn-odds base alone so .prob-row's usage keeps its quieter form.

   Values copied verbatim from the v2 mocks (discover / feed /
   prediction-detail / prediction-detail-settled — the four screens
   that render these buttons).

   The mock's own comment claims the odds read at the SAME size and
   weight as the Yes/No label. The shipped values don't:

     .action-btn  label 13px/700   odds 13px/500   (size ok, weight not)
     .mini-btn    label 11px/700   odds 10px/500   (neither)

   RESOLVED 2026-08-05: that comment is stale — the declarations win.
   weight 500 against a 700 label is deliberate, not a miss: digits
   read optically heavier than letters at equal weight, so dropping
   numerals to 500 is what makes them look like one continuous label.
   "Same weight" meant perceptually, not numerically.

   `.mini-btn .odds` stays at 10px against its 11px parent —
   CONFIRMED 2026-08-06, not an oversight. It was the one value in
   this block that did not move (.action-btn's odds went 11px -> 13px
   to hit its parent exactly), which made it look like a miss; it
   isn't. 10px is what every v2 screenshot renders. Do not "correct"
   it to 11px. */
.action-btn .btn-odds { font-size: 13px; font-weight: 500; opacity: 1; }

.step-btn {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  color: var(--text-primary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 150ms ease, border-color 150ms ease, transform 150ms ease;
}
.step-btn:hover  { background: var(--bg-surface-hover); border-color: var(--brand-primary); }
.step-btn:active { transform: scale(0.96); }
.step-btn svg    { width: 16px; height: 16px; }

/* ─── Chips ───────────────────────────────────────────────────── */
.position-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: var(--radius-full);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: -0.1px;
  line-height: 1;
}
.position-chip svg { width: 11px; height: 11px; flex-shrink: 0; }
.position-chip.holds {
  background: var(--brand-primary-muted);
  color: var(--brand-primary);
}
.position-chip.no {
  background: var(--brand-fade-muted);
  color: var(--brand-fade);
}
.position-chip.none {
  background: var(--brand-fade-muted);
  color: var(--brand-fade);
}

/* Creator-pos chip — sibling of .position-chip, lives on the right
 * side of `.price-row` on every feed call card per canonical
 * `tmp/updates/feed.html`. Slightly larger gap + padding + font-
 * size than the bare .position-chip; holds = green-muted bg,
 * none = red-muted bg. Defining the rules here (the earlier
 * canonical block at the end of styles.rs lacked them entirely,
 * so unstyled chips rendered svg at intrinsic 24×24 size). */
.creator-pos {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: -0.1px;
  line-height: 1;
}
.creator-pos svg { width: 11px; height: 11px; flex-shrink: 0; }
.creator-pos .mono {
  font-family: var(--font-mono);
  font-weight: inherit;
  font-size: inherit;
}
.creator-pos.holds {
  background: var(--brand-primary-muted);
  color: var(--brand-primary);
}
.creator-pos.none {
  background: var(--brand-fade-muted);
  color: var(--brand-fade);
}
/* While the create-flow self-back is in flight or parked,
 * wallet-bridge.js flips the server-rendered `.none` chip straight to
 * the real green `.holds` "$X Position" (business 2026-08-30 —
 * optimistic; the amber "Position pending" state was rejected).
 * Terminal failure reverts it; no dedicated class needed. */
.price-row .creator-pos { margin-left: auto; }

/* No-position red pill — parallel variant to `.creator-pos.holds`
 * per canonical `tmp/updates/profile.html`. Rendered on own-call
 * cards (the creator hasn't back/faded their own call) and on
 * bet entries when the creator-pos roll lands on "none". Sized
 * + colored independently of `.creator-pos.none` so the demo
 * markup distinction stays visible. SVG sized to 10×10 to match
 * canonical (smaller than the trader-card .creator-pos svg). */
.no-pos-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: var(--radius-full);
  background: var(--brand-fade-muted);
  color: var(--brand-fade);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: -0.1px;
  line-height: 1;
}
.no-pos-chip svg {
  width: 10px;
  height: 10px;
  flex-shrink: 0;
}
.price-row .no-pos-chip { margin-left: auto; }

/* Position chip on bet-history rows — shown inside `.call-top`
 * next to the call title, indicating which side the viewer bet
 * (backed → green Yes; faded → red No). Per canonical
 * `tmp/updates/profile-history.html`. Aliased to
 * `.position-chip.holds/.no` per components.css §7 but defined
 * here directly so the bet-history surface stays self-contained. */
.pos-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: var(--radius-full);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: -0.1px;
  flex-shrink: 0;
  line-height: 1;
}
.pos-chip.backed {
  background: var(--brand-primary-muted);
  color: var(--brand-primary);
}
.pos-chip.faded {
  background: var(--brand-fade-muted);
  color: var(--brand-fade);
}
.pos-chip svg {
  width: 11px;
  height: 11px;
  flex-shrink: 0;
}

.settled-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: -0.1px;
  line-height: 1;
}
.settled-badge svg { width: 11px; height: 11px; flex-shrink: 0; }
.settled-badge.hit    { background: var(--brand-primary-muted); color: var(--brand-primary); }
.settled-badge.missed { background: var(--brand-fade-muted);    color: var(--brand-fade); }

.xp-pill {
  font-size: 10px;
  font-weight: 700;
  color: var(--brand-accent);
  background: var(--brand-accent-muted);
  padding: 2px 6px;
  border-radius: var(--radius-full);
  letter-spacing: 0.1px;
}
.xp-pill.lg {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 700;
  color: var(--brand-accent-hover);
  padding: 2px 7px;
  letter-spacing: 0.2px;
}

.time-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--text-secondary);
  letter-spacing: -0.2px;
}
.time-chip svg { width: 11px; height: 11px; flex-shrink: 0; }

/* ─── Stats ───────────────────────────────────────────────────── */
.stat-card {
  padding: 12px 8px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  text-align: center;
  transition: background-color 150ms ease;
}

/* .stat-card:hover { background: var(--bg-surface-hover); } */

.stat-val {
  font-family: var(--font-mono);
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.7px;
  line-height: 1.1;
  color: var(--text-primary);
}
.stat-val.green  { color: var(--brand-primary); }
.stat-val.purple { color: var(--brand-accent-hover); }
.stat-val.gold   { color: var(--gold-soft); }
.stat-val .denom { color: var(--text-tertiary); }
.stat-lbl {
  margin-top: 4px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-tertiary);
}

.stat-inline {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-tertiary);
}
.stat-inline svg { width: 12px; height: 12px; flex-shrink: 0; }
.stat-inline.accuracy { color: var(--text-secondary); gap: 2px; }
.stat-inline.accuracy svg { color: var(--text-secondary); }
.acc-pct { color: var(--text-primary); font-weight: 800; }
.stat-inline.edge.pos     { color: var(--brand-primary); font-weight: 700; }
.stat-inline.edge.pos svg { color: var(--brand-primary); }
.stat-inline.edge.neg     { color: var(--brand-fade);    font-weight: 700; }
.stat-inline.edge.neg svg { color: var(--brand-fade); }
.stat-inline.record {
  font-family: var(--font-mono);
  font-weight: 700;
  letter-spacing: -0.2px;
}
.stat-inline.record .rec-num   { color: var(--text-primary);  font-weight: 800; }
.stat-inline.record .rec-denom { color: var(--text-tertiary); font-weight: 700; }

.rank-col {
  height: 36px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.rank-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.rank-num {
  font-size: 20px;
  font-weight: 800;
  color: var(--text-primary);
  font-family: var(--font-mono);
  letter-spacing: -0.5px;
  line-height: 1;
}

/* ─── Cards — feed call entry ─────────────────────────────────── */
.call-entry { margin-bottom: 20px; }
.call-entry:last-child { margin-bottom: 0; }
/* Profile lists space via the .list gap (8px) — the feed's 20px
   entry margin stacked on top read as "too much space between the
   cards" (round 6). Feed keeps its margin via .feed-scroll. */
.list > .call-entry { margin-bottom: 0; }

.user-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 0 4px;
  margin-bottom: 10px;
}
.card-user { display: flex; align-items: center; gap: 10px; }
.user-meta { display: flex; flex-direction: column; gap: 3px; }
.user-name-row { display: flex; align-items: center; gap: 6px; }
.username {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.call-card {
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: 14px;
  position: relative;
  cursor: pointer;
  transition: background-color 150ms ease, border-color 150ms ease;
}
.call-card:hover { background: var(--bg-surface-hover); }

.card-time {
  position: absolute;
  top: 17px;
  right: 14px;
  font-size: 11px;
  color: var(--text-tertiary);
  font-weight: 500;
  white-space: nowrap;
}

.call-text-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 9px;
  padding-right: 56px;
}
.call-text,
.call-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.3px;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  flex: 1;
}

.price-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}
.price-current,
.price-target,
.price {
  font-size: 12px;
  font-weight: 600;
  font-family: var(--font-mono);
  color: var(--text-secondary);
  letter-spacing: -0.2px;
}
.price-sep,
.price-row .sep,
.sk-price-sep {
  width: 1px;
  height: 11px;
  background: var(--border-default);
  flex-shrink: 0;
}
.to-target {
  font-size: 12px;
  font-weight: 600;
  font-family: var(--font-mono);
  color: var(--text-secondary);
  letter-spacing: -0.2px;
}

.market-bar-wrap { margin-bottom: 10px; }
.market-bar {
  height: 7px;
  border-radius: var(--radius-full);
  background: var(--brand-fade);
  position: relative;
  overflow: hidden;
}
.market-bar-fill {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  border-radius: var(--radius-full);
  background: linear-gradient(90deg, var(--brand-primary) 0%, var(--brand-primary-hover) 100%);
}
.bar-labels {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 5px;
}

/* Feed market card (2026-07-06 design): the market bar + a
 * VOLUME / TRADERS / AVG TRADE stat row split out of the info
 * card into its own tappable card. Stat styles mirror the
 * call-detail .mstat treatment. */
.market-card { margin-top: 8px; }
.mstat-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  margin: 12px 0;
}
.mstat.center { text-align: center; }
.mstat.right { text-align: right; }
.mstat-lbl {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-tertiary);
  margin-bottom: 3px;
}
.mstat-val {
  font-size: 18px;
  font-weight: 800;
  font-family: var(--font-mono);
  letter-spacing: -0.5px;
}
.bar-lbl { font-size: 11px; font-weight: 600; }
.bar-lbl.back,
.bar-lbl.yes  { color: var(--brand-primary); }
.bar-lbl.fade,
.bar-lbl.no   { color: var(--brand-fade); }

.card-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px;
}

/* V3 card grammar (2026-08-08 drop): 1fr auto 1fr grid so the
   centered pool-split's divider aligns with the gap between the
   Yes/No buttons above it. Chips read secondary; icons tertiary. */
.card-meta {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 6px;
  margin-top: 11px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
}
.card-meta .meta-chip { color: var(--text-secondary); }
.card-meta .meta-chip svg { color: var(--text-tertiary); }
.card-meta .vol { font-family: var(--font-mono); }
/* Canonical Yes/No split — child colors only. Deliberately sets NO
   font-size/weight/family: it inherits typography from whatever hosts
   it (.card-meta at 11px/500, the call-detail mstat row at 13px), so
   one component serves every surface. `inline-flex` + baseline keeps
   yes/slash/no on the surrounding text's baseline.
   The separator is a DRAWN 1px bar, not a glyph — the `/` character
   stays in the markup (color: transparent) so the split still reads
   as "185 Yes / 100 No" with CSS stripped. */
.pool-split { display: inline-flex; align-items: baseline; }
.pool-split .yes { color: var(--brand-primary); }
.pool-split .no { color: var(--brand-fade); }
.pool-split .slash {
  display: inline-block;
  width: 1px;
  height: 0.85em;
  background: var(--text-tertiary);
  vertical-align: middle;
  margin: 0 6px;
  border-radius: 1px;
  color: transparent;
  overflow: hidden;
}
.card-meta .meta-right { display: inline-flex; align-items: center; gap: 4px; }
.meta-chip {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
}
.meta-chip svg { color: var(--text-tertiary); opacity: 0.8; flex-shrink: 0; }
.meta-chip.center { justify-content: center; }
.meta-chip.right  { justify-content: flex-end; }

/* ─── Quote-bet social proof banner ───────────────────────────── */
.quote-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 12px;
  margin: 0 4px 8px;
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.qb-avatar {
  width: 20px;
  height: 20px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
  letter-spacing: -0.3px;
}
.qb-text {
  flex: 1;
  min-width: 0;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: -0.1px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}
.qb-uname  {
  font-weight: 800;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 140px;
}
.qb-meta   { color: var(--text-tertiary); font-family: var(--font-mono); font-size: 10.5px; }
.qb-action { color: var(--text-tertiary); }
.qb-amount {
  font-family: var(--font-mono);
  font-weight: 800;
  padding: 1px 6px;
  border-radius: var(--radius-full);
  font-size: 10.5px;
  letter-spacing: -0.1px;
}
.qb-amount.yes { color: var(--brand-primary); background: var(--brand-primary-muted); }
.qb-amount.no  { color: var(--brand-fade);    background: var(--brand-fade-muted); }
.qb-on { color: var(--text-tertiary); }

.qb-time {
  color: var(--text-tertiary);
  font-size: 10.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex-shrink: 0;
}

/* ─── V3 social row + in-card trade comment (2026-08-08 drop) ──── */
/* Both sit above the .card-tap stretched link (z-index 2) so the
   Yes/No count buttons stay tappable, same trick as .card-actions. */
.post-social {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border-default);
  position: relative;
  z-index: 2;
}
.ps-side {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 2px 6px;
  position: relative;
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
}
.ps-side.active::after {
  content: '';
  position: absolute;
  left: 2px;
  right: 2px;
  bottom: 0;
  height: 2px;
  border-radius: var(--radius-full);
}
.ps-side.yes.active .ps-yn { color: var(--brand-primary); }
.ps-side.yes.active::after { background: var(--brand-primary); }
.ps-side.no.active .ps-yn { color: var(--brand-fade); }
.ps-side.no.active::after { background: var(--brand-fade); }
.ps-yn {
  color: var(--text-tertiary);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: -0.1px;
}
.ps-count {
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.1px;
}
.ps-spacer { flex: 1; }
.ps-time {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.1px;
  white-space: nowrap;
}
.ps-time svg { color: var(--text-tertiary); flex-shrink: 0; }

.post-comment {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  padding-top: 6px;
  position: relative;
  z-index: 2;
}
.pc-time {
  color: var(--text-tertiary);
  font-size: 10.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex-shrink: 0;
  margin-left: 4px;
}
.call-card .post-social:last-child { margin-bottom: -6px; }
.call-card .post-comment:last-child { margin-bottom: -4px; }

/* %-to-target is ALWAYS colored (design-system rule 2026-08-03):
   green up, red down (markup carries the leading minus). */
.tt-val.up { color: var(--brand-primary); }
.tt-val.down { color: var(--brand-fade); }

/* ─── Intro / Duels promo card ────────────────────────────────── */
.intro-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  padding: 14px 16px;
  margin-bottom: 16px;
  background:
    radial-gradient(120% 100% at 0% 0%,   rgba(110, 66, 207, 0.35), transparent 55%),
    radial-gradient(120% 100% at 100% 100%, rgba(239, 68, 68, 0.25), transparent 55%),
    linear-gradient(135deg, #1C2642 0%, #151E32 100%);
  border: 1px solid var(--border-default);
  display: flex;
  align-items: center;
  gap: 12px;
}
.intro-emoji {
  width: 44px;
  height: 44px;
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, var(--brand-accent) 0%, var(--brand-fade) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  flex-shrink: 0;
}
.intro-body { flex: 1; min-width: 0; }
.intro-eyebrow {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--brand-accent-hover);
  margin-bottom: 2px;
}
.intro-title  { font-size: 15px; font-weight: 800; letter-spacing: -0.3px; margin-bottom: 2px; }
.intro-sub    { font-size: 12px; font-weight: 500; color: var(--text-secondary); letter-spacing: -0.1px; }
.intro-cta {
  height: 44px;
  padding: 0 14px;
  border-radius: var(--radius-full);
  border: none;
  cursor: pointer;
  background: var(--text-primary);
  color: var(--bg-base);
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: -0.1px;
  flex-shrink: 0;
  transition: background-color 150ms ease, transform 150ms ease, filter 150ms ease;
}
.intro-cta:hover  { filter: brightness(1.1); }
.intro-cta:active { transform: scale(0.96); }

/* ─── Trader card (discover) ──────────────────────────────────── */
.trader {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color 150ms ease;
}
.trader:hover { background: var(--bg-surface-hover); }
.trader + .trader { margin-top: 8px; }

/* Inner navigation surface — `<a>` wrapping avatar + info. Lets a
 * tap on the identity side of the card navigate to the profile
 * while the Follow button stays a sibling (avoids invalid
 * `<button>` inside `<a>` nesting). Hybrid markup decision —
 * issue #29 discussion 2026-05-27. */
.trader-link {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  color: inherit;
  text-decoration: none;
}

.t-info {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 3px;
}
.t-name-row { display: flex; align-items: center; gap: 6px; }
.t-uname    {
  font-size: 13.5px; font-weight: 800; letter-spacing: -0.3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.t-stats { display: flex; align-items: center; gap: 8px; }
.t-stat {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 600;
}
.t-stat svg { width: 11px; height: 11px; flex-shrink: 0; }
.t-stat.accuracy { color: var(--text-secondary); gap: 2px; }
.t-stat.edge.pos { color: var(--brand-primary); font-weight: 700; }
.t-stat.edge.neg { color: var(--brand-fade);    font-weight: 700; }
.t-stat.record {
  color: var(--text-tertiary);
  font-family: var(--font-mono);
  font-weight: 700;
  letter-spacing: -0.2px;
  gap: 3px;
}
.t-stat.record .rec-num   { color: var(--text-primary);  font-weight: 800; }
.t-stat.record .rec-denom { color: var(--text-tertiary); font-weight: 700; }

/* ─── Compact call card (discover) ────────────────────────────── */
.c-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 10px 10px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  margin-bottom: 8px;
  cursor: pointer;
  transition: background-color 150ms ease;
}
.c-card:last-child { margin-bottom: 0; }
.c-card:hover { background: var(--bg-surface-hover); }
.c-info {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 3px;
}
.c-top-row  { display: flex; align-items: center; gap: 6px; }
.c-username {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-secondary);
  letter-spacing: -0.2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.c-call {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.2px;
  line-height: 1.2;
}
.c-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.c-bottom-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
}
.c-time {
  font-family: var(--font-mono);
  color: var(--text-secondary);
  font-weight: 600;
  display: inline-flex; align-items: center; gap: 3px;
}
.c-bottom-row svg { width: 11px; height: 11px; color: currentColor; flex-shrink: 0; }
.c-sep {
  width: 1px;
  height: 10px;
  background: var(--border-default);
  flex-shrink: 0;
}
.c-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}

/* ─── Own-call / Bet card (profile-portfolio) ─────────────────── */
.own-call,
.bet {
  display: flex;
  flex-direction: column;
  padding: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color 150ms ease;
}
.own-call:hover,
.bet:hover { background: var(--bg-surface-hover); }
.bet + .bet,
.own-call + .own-call { margin-top: 10px; }
.bet-top { display: flex; gap: 10px; align-items: center; }
.b-info {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 3px;
}
.b-user-row { display: flex; align-items: center; gap: 6px; }
.b-username {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-secondary);
  letter-spacing: -0.2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.b-call {
  display: flex; align-items: center; gap: 6px;
  font-size: 14px; font-weight: 700;
  color: var(--text-primary); letter-spacing: -0.2px; line-height: 1.2;
}
.b-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.b-meta {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 500; color: var(--text-tertiary);
}
.b-meta .price, .b-meta .vol, .b-meta .time {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--text-secondary);
  display: inline-flex; align-items: center; gap: 3px;
}
.b-meta .sep { width: 1px; height: 10px; background: var(--border-default); flex-shrink: 0; }
.b-meta svg  { width: 11px; height: 11px; flex-shrink: 0; }

/* ─── Settled rows + bet history ──────────────────────────────── */
.settled,
.call.settled {
  padding: 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color 150ms ease;
}
.settled:hover,
.call.settled:hover { background: var(--bg-surface-hover); }
.call.settled + .call.settled { margin-top: 0; }
.bet-history,
.call.settled.bet-history { border-left: 2.5px solid var(--brand-accent); }
.bh-trader {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 1px dashed var(--border-subtle);
}
.bh-uname {
  font-size: 12.5px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.2px;
}
.bh-vol {
  margin-left: auto;
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--text-secondary);
  letter-spacing: -0.2px;
}
.call-top { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.settled .c-text {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: -0.2px;
  line-height: 1.25;
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
}
.settled-row {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--border-subtle);
}
.settled-left { display: inline-flex; align-items: center; gap: 8px; }
.settled-time {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-tertiary);
  font-family: var(--font-mono);
}
.pnl {
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 800;
  letter-spacing: -0.3px;
}
.pnl.pos { color: var(--brand-primary); }
.pnl.neg { color: var(--brand-fade); }

/* ─── Leaderboard podium ──────────────────────────────────────── */
.podium {
  position: relative;
  padding: 14px 0 6px;
  display: grid;
  grid-template-columns: 1fr 1.15fr 1fr;
  align-items: end;
  gap: 8px;
}
.pod-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  animation: podiumRise 450ms var(--ease-spring) both;
}
.pod-col.gold   { animation-delay: 0ms; }
.pod-col.silver { animation-delay: 80ms; }
.pod-col.bronze { animation-delay: 160ms; }
.pod-user { display: flex; flex-direction: column; align-items: center; gap: 4px; margin-bottom: 8px; }
.pod-trophy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  color: var(--gold);
  filter: drop-shadow(0 4px 8px rgba(255, 215, 0, 0.45));
  line-height: 1;
  margin-bottom: 2px;
}
.pod-trophy.silver-t { color: var(--silver); filter: drop-shadow(0 4px 8px rgba(200, 200, 200, 0.35)); }
.pod-trophy.bronze-t { color: var(--bronze); filter: drop-shadow(0 4px 8px rgba(205, 127, 50, 0.4)); }
.pod-trophy svg { width: 28px; height: 28px; }

.pod-avatar-wrap { position: relative; width: 56px; height: 56px; }
.pod-col.gold .pod-avatar-wrap { width: 64px; height: 64px; }
.pod-avatar-wrap::before {
  content: '';
  position: absolute;
  inset: -2.5px;
  border-radius: var(--radius-full);
  background: conic-gradient(from 0deg, var(--gold-soft), var(--gold), var(--gold-deep), var(--gold), var(--gold-soft));
  filter: drop-shadow(0 0 8px rgba(255, 215, 0, 0.4));
}
.pod-col.silver .pod-avatar-wrap::before {
  background: conic-gradient(from 0deg, var(--silver-soft), var(--silver), var(--silver-deep), var(--silver), var(--silver-soft));
  filter: drop-shadow(0 0 6px rgba(200, 200, 200, 0.3));
}
.pod-col.bronze .pod-avatar-wrap::before {
  background: conic-gradient(from 0deg, var(--bronze-soft), var(--bronze), var(--bronze-deep), var(--bronze), var(--bronze-soft));
  filter: drop-shadow(0 0 6px rgba(205, 127, 50, 0.35));
}
.pod-avatar {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: var(--radius-full);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 800;
  color: #fff;
  letter-spacing: -0.5px;
  border: 3px solid var(--bg-base);
  transition: transform 200ms var(--ease-spring);
}
.pod-col.gold .pod-avatar { font-size: 24px; }
.pod-avatar:hover { transform: scale(1.05); }

.pod-name-row { display: flex; align-items: center; gap: 4px; margin-top: 6px; }
.pod-uname {
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: -0.3px;
  max-width: 96px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pod-col.gold .pod-uname { font-size: 13.5px; }
.pod-xp {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: -0.3px;
  color: var(--text-secondary);
}
.pod-col.gold   .pod-xp { color: var(--gold-soft);   font-size: 13px; }
.pod-col.silver .pod-xp { color: var(--silver-soft); }
.pod-col.bronze .pod-xp { color: var(--bronze-soft); }

.pod-reward {
  margin-top: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 800;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  letter-spacing: -0.2px;
}
.pod-col.gold   .pod-reward { background: rgba(255, 215, 0, 0.15);  color: var(--gold-soft);   border: 1px solid rgba(255, 215, 0, 0.30); }
.pod-col.silver .pod-reward { background: rgba(200, 200, 200, 0.10); color: var(--silver-soft); border: 1px solid rgba(200, 200, 200, 0.25); }
.pod-col.bronze .pod-reward { background: rgba(205, 127, 50, 0.12); color: var(--bronze-soft); border: 1px solid rgba(205, 127, 50, 0.30); }

.pod-platform {
  width: 100%;
  margin-top: 8px;
  border-top-left-radius: var(--radius-md);
  border-top-right-radius: var(--radius-md);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 8px;
  font-family: var(--font-mono);
  font-size: 28px;
  font-weight: 900;
  letter-spacing: -1px;
  line-height: 1;
  position: relative;
  overflow: hidden;
}
.pod-platform::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: linear-gradient(180deg, rgba(255,255,255,0.10) 0%, transparent 50%);
}
.pod-col.gold .pod-platform {
  height: 78px;
  background: linear-gradient(180deg, rgba(255, 215, 0, 0.30) 0%, rgba(255, 215, 0, 0.10) 100%);
  border: 1px solid rgba(255, 215, 0, 0.35);
  border-bottom: none;
  color: var(--gold-soft);
  text-shadow: 0 0 14px rgba(255, 215, 0, 0.4);
}
.pod-col.silver .pod-platform {
  height: 60px;
  background: linear-gradient(180deg, rgba(200, 200, 200, 0.22) 0%, rgba(200, 200, 200, 0.06) 100%);
  border: 1px solid rgba(200, 200, 200, 0.30);
  border-bottom: none;
  color: var(--silver-soft);
}
.pod-col.bronze .pod-platform {
  height: 46px;
  background: linear-gradient(180deg, rgba(205, 127, 50, 0.24) 0%, rgba(205, 127, 50, 0.06) 100%);
  border: 1px solid rgba(205, 127, 50, 0.32);
  border-bottom: none;
  color: var(--bronze-soft);
}

/* ─── Leaderboard standings ───────────────────────────────────── */
.list-head {
  margin: 18px 4px 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-tertiary);
}
.list-head .lh-left { display: inline-flex; align-items: center; gap: 8px; }
/* ─── Header wallet chip (build spec 2026-10-07; mock CSS, bare not
   pill). `.wallet-chip` is the user-menu's wallet-ADDRESS chip. ─── */
.hdr-wallet {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 2px;
  background: none;
  border: none;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: -0.2px;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  transition: color 150ms ease;
}
.hdr-wallet svg { width: 14px; height: 14px; color: var(--text-secondary); flex-shrink: 0; }
.hdr-wallet:hover svg { color: var(--text-primary); }
/* Placeholder reserves the footprint until the balance hydrates. */
.hdr-wallet-val { min-width: 4ch; text-align: right; }

/* ─── Empty league states (build spec 2026-10-07, mocks
   empty-leaderboard*.html). The content region becomes a flex column
   only when it holds the cluster, so populated boards are untouched. ─── */
.content:has(> .lb-empty) { display: flex; flex-direction: column; }
.lb-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 24px 28px 96px; /* bottom clears the nav */
}
.lb-empty .lh-countdown { margin-bottom: 20px; }
/* Fixed slot = tallest graphic (74px podium): countdown/title/copy/CTA
   sit at identical y on both tabs (alignment contract). */
.lbe-art { height: 74px; display: flex; align-items: center; justify-content: center; margin-bottom: 20px; }
.lbe-podium { align-items: flex-end; gap: 6px; }
.lp-col {
  width: 46px;
  border-radius: 8px 8px 3px 3px;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 8px;
  font-size: 14px;
  font-weight: 800;
  color: var(--text-tertiary);
  background: linear-gradient(180deg, var(--bg-surface-hover) 0%, var(--bg-surface-elevated) 100%);
  border: 1px solid var(--border-default);
}
.lp-col.first { height: 74px; color: var(--text-secondary); }
.lp-col.second { height: 52px; }
.lp-col.third { height: 42px; }
.lbe-trophy { width: 60px; height: 60px; color: var(--text-tertiary); }
.lbe-title { font-size: 17px; font-weight: 800; letter-spacing: -0.3px; color: var(--text-primary); margin-bottom: 8px; }
.lbe-sub {
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--text-secondary);
  max-width: 270px;
  margin-bottom: 24px;
  min-height: 41px; /* two lines reserved */
}

.lh-countdown {
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 700;
  color: var(--brand-primary);
  background: var(--brand-primary-muted);
  padding: 2px 7px;
  border-radius: var(--radius-full);
  text-transform: none;
  letter-spacing: 0;
}

.leaderboard-row,
.lb-row {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 12px 11px 8px;
  background: var(--bg-surface);
  border: 1.5px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color 150ms ease, border-color 150ms ease;
}
.leaderboard-row:hover,
.lb-row:hover { background: var(--bg-surface-hover); }
.leaderboard-row + .leaderboard-row,
.lb-row + .lb-row { margin-top: 8px; }
.leaderboard-row.you,
.lb-row.you {
  border-color: var(--brand-primary);
  background: var(--brand-primary-muted);
  box-shadow: 0 0 0 4px rgba(39, 188, 129, 0.08);
}
.rank {
  font-family: var(--font-mono);
  font-size: 17px;
  font-weight: 800;
  color: var(--text-secondary);
  letter-spacing: -0.4px;
  white-space: nowrap;
}
.user-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.stat-row { display: flex; align-items: center; gap: 8px; }
.xp-col      { flex-shrink: 0; display: flex; align-items: center; margin-left: auto; }
.xp-num {
  font-family: var(--font-mono);
  font-size: 14px; font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.3px;
  white-space: nowrap;
}
.reward-col  { flex-shrink: 0; margin-left: -4px; display: flex; align-items: center; justify-content: flex-end; min-width: 30px; }
.reward {
  font-family: var(--font-mono);
  font-size: 14px; font-weight: 800;
  color: var(--text-tertiary);
  letter-spacing: -0.3px;
  white-space: nowrap;
}
.reward.win { color: var(--brand-primary); }

/* Fee column for the Rewards-tab variant of the leaderboard
 * (`tmp/updates/leaderboard-rewards.html`). Same flex behavior
 * as `.xp-col` but distinct class so the render swap between
 * Standings (XP) and Rewards (fees) lines up without per-row
 * branching in CSS. */
.fee-col {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  margin-left: auto;
}
.fee-num {
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.3px;
  white-space: nowrap;
}

.prize-pool {
  flex-shrink: 0;
  position: relative;
  padding: 8px 14px;
  background: linear-gradient(135deg, rgba(255, 215, 0, 0.18), rgba(255, 215, 0, 0.06));
  border: 1px solid rgba(255, 215, 0, 0.35);
  border-radius: var(--radius-md);
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
  box-shadow: 0 0 24px rgba(255, 215, 0, 0.10);
}
.prize-lbl {
  font-size: 9px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--gold-soft);
}
.prize-val {
  font-family: var(--font-mono);
  font-size: 17px;
  font-weight: 800;
  color: var(--gold-soft);
  letter-spacing: -0.5px;
  line-height: 1;
  text-shadow: 0 0 10px rgba(255, 215, 0, 0.4);
}

/* ─── Tabs (canonical) ────────────────────────────────────────── */
.feed-tabs {
  flex-shrink: 0;
  height: 40px;
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--border-subtle);
  background: var(--bg-base);
  position: sticky;
  top: 0;
  z-index: 19;
}
.feed-tab {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-tertiary);
  cursor: pointer;
  position: relative;
  letter-spacing: -0.1px;
  transition: color 150ms ease;
  text-decoration: none;
}
.feed-tab::after {
  content: '';
  position: absolute;
  bottom: -1px;
  left: 50%;
  right: 50%;
  height: 2px;
  background: var(--brand-primary);
  border-radius: var(--radius-full);
  transition: left 250ms var(--ease-out), right 250ms var(--ease-out), background 200ms ease;
}
.feed-tab.active { color: var(--text-primary); }
.feed-tab.active::after { left: calc(50% - 44px); right: calc(50% - 44px); }

.main-tabs {
  display: flex;
  border-bottom: 1px solid var(--border-subtle);
  gap: 0;
}
.main-tab {
  flex: 1;
  text-align: center;
  padding: 12px 0;
  font-size: 14px;
  font-weight: 700;
  color: var(--text-tertiary);
  cursor: pointer;
  position: relative;
  letter-spacing: -0.2px;
  transition: color 150ms ease;
  text-decoration: none;
}
.main-tab::after {
  content: '';
  position: absolute;
  left: 50%;
  right: 50%;
  bottom: -1px;
  height: 2.5px;
  background: transparent;
  border-radius: 2px;
  transition: left 250ms var(--ease-out), right 250ms var(--ease-out), background 200ms ease;
}
.main-tab.active { color: var(--text-primary); }
.main-tab.active::after { left: 22%; right: 22%; background: var(--brand-primary); }
.main-tab { padding-bottom: 7px; }
.main-tabs + .list { padding-top: 14px; }
.list > .call.settled:first-of-type,
.list > .hist-entry:first-of-type { margin-top: 14px; }
/* …but not when the record tiles sit above the list: their 16px
   margin-bottom IS the gap (round 7: History matches Rewards'
   tiles→card spacing; the extra 14px read as 30). */
.history-stats + .list > .call.settled:first-of-type,
.history-stats + .list > .hist-entry:first-of-type { margin-top: 0; }

.page-tabs {
  flex-shrink: 0;
  display: flex;
  border-bottom: 1px solid var(--border-subtle);
  padding: 0;
  margin: 0;
  background: transparent;
}
.page-tab {
  flex: 1;
  text-align: center;
  padding: 14px 0;
  background: none;
  border: none;
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 800;
  color: var(--text-tertiary);
  cursor: pointer;
  position: relative;
  letter-spacing: -0.2px;
  border-radius: 0;
  transition: color 150ms ease;
  text-decoration: none;
  align-content: center;
}
.page-tab::after {
  content: '';
  position: absolute;
  left: 50%;
  right: 50%;
  bottom: -1px;
  height: 2.5px;
  background: transparent;
  border-radius: 2px;
  transition: left 250ms var(--ease-out), right 250ms var(--ease-out), background 200ms ease;
}
.page-tab.active { color: var(--text-primary); }
.page-tab.active::after { left: 30%; right: 30%; background: var(--brand-primary); }
.page-tab:hover:not(.active) { color: var(--text-secondary); }

/* `.sub-tabs` / `.sub-pill` removed for good (V3 drop, 2026-08-09
 * plan — V3.1: "no filter anywhere"). The Predictions tab renders
 * one interleaved list of both card types. */

/* ─── Search ─────────────────────────────────────────────────────
 * `.filters` + `.pill` are defined earlier in this file (lines
 * ~1701 / ~1700) — the canonical-block duplicates that lived
 * here got removed (issue #29). They were equal-specificity
 * with the originals and added `flex-shrink: 0`, which combined
 * with `position: sticky` on the original `.filters` produced
 * unpredictable scroll behavior. Single source of truth now. */
.search {
  width: 200px;
  margin-left: auto;
  height: 32px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-full);
}
.search svg { color: var(--text-tertiary); flex-shrink: 0; }
.search input {
  flex: 1;
  background: none;
  border: none;
  outline: none;
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  min-width: 0;
}
.search input::placeholder { color: var(--text-tertiary); }

/* ─── Overlays ────────────────────────────────────────────────── */
.overlay-backdrop,
.overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(2px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 20px calc(24px + env(safe-area-inset-bottom));
  z-index: 10;
}
.modal {
  position: relative;
  width: 100%;
  max-width: 340px;
  background: linear-gradient(180deg, var(--bg-surface) 0%, var(--bg-surface-elevated) 100%);
  border: 1px solid rgba(255, 215, 0, 0.22);
  border-radius: var(--radius-lg);
  padding: 22px 20px 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.4),
    0 20px 60px rgba(0, 0, 0, 0.55),
    0 0 60px rgba(255, 215, 0, 0.10);
  animation: pop 0.35s var(--ease-spring);
}
.bottom-sheet,
.sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--bg-surface);
  border-top-left-radius: var(--radius-lg);
  border-top-right-radius: var(--radius-lg);
  border-top: 1px solid var(--border-subtle);
  padding: 10px 20px calc(20px + env(safe-area-inset-bottom));
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 16px;
  box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.5);
  transform: translateY(100%);
  transition: transform 300ms var(--ease-out);
}
.bottom-sheet.open,
.sheet.open { transform: translateY(0); }
.handle {
  align-self: center;
  width: 40px;
  height: 4px;
  border-radius: var(--radius-full);
  background: var(--text-tertiary);
  margin-bottom: 6px;
}

/* ─── v2 form modals (custom deadline; edit-profile + error follow
   in WS-I/K). `.modal.plain` strips the champion modal's gold chrome
   — same shell, different occasion. */
.modal.plain {
  align-items: stretch;
  gap: 16px;
  border-color: var(--border-subtle);
  padding: 20px 20px 18px;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.4),
    0 20px 60px rgba(0, 0, 0, 0.55);
}
.modal-overlay { z-index: 40; }
.modal-overlay[hidden] { display: none; }
.m-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.m-title { font-size: 16px; font-weight: 800; letter-spacing: -0.3px; color: var(--text-primary); }
.close-btn {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background-color 150ms ease, color 150ms ease, transform 150ms ease;
}
.close-btn:hover { background: var(--bg-surface-hover); color: var(--text-primary); }
.close-btn:active { transform: scale(0.94); }
.close-btn svg { width: 14px; height: 14px; }
.cd-pickers { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 4px; }
.cd-input {
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  color: var(--text-primary);
  font-family: inherit;
  font-size: 14px;
  color-scheme: dark;
  min-width: 0;
}
.cd-input:focus { outline: none; border-color: var(--brand-primary); box-shadow: 0 0 0 3px rgba(39, 188, 129, 0.18); }
.cd-duration { margin-top: 12px; text-align: center; font-family: var(--font-mono); font-size: 15px; font-weight: 700; color: var(--text-secondary); letter-spacing: -0.1px; }
.cd-duration .cd-duration-lbl { color: var(--text-tertiary); font-weight: 500; margin-right: 4px; }
/* Too-far readout renders red (business 2026-08-11). */
.cd-duration .dur-err { color: var(--brand-fade); }
.m-foot { display: block; margin-top: 16px; }
.m-cta {
  width: 100%;
  height: 48px;
  border-radius: var(--radius-md);
  border: none;
  background: var(--brand-primary);
  color: #fff;
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: -0.2px;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(39, 188, 129, 0.32);
  transition: filter 150ms ease, transform 150ms ease;
}
.m-cta:hover { filter: brightness(1.06); }
.m-cta:active { transform: scale(0.98); }
.m-cta:disabled { opacity: 0.55; cursor: not-allowed; box-shadow: none; }

/* Error modal (WS-K): m-body centers icon + text; the head carries
   only the close X, pushed to the row end. error-icon/-title/-sub
   base rules live in the empty/error section below and serve both
   this modal and the wallet's inline error line. */
.m-head-end { justify-content: flex-end; }
.m-body { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 14px; padding: 4px 6px 0; }
.m-body .error-text { display: flex; flex-direction: column; gap: 6px; }
.m-body .error-sub { max-width: 260px; font-size: 13.5px; }
.modal .close-btn { text-decoration: none; }

/* Confirm-sheet prompt line + creating-prediction overlay (WS-G). */
/* Mock confirm-trade-sheet.html: the prompt row is a flex column
   holding the Position breakdown (tester round 5, #188 item 8). */
.prompt-row { display: flex; flex-direction: column; gap: 4px; text-align: center; padding: 2px 4px; }
.prompt-row .prompt-sub { margin: 6px 0 0; font-size: 13px; font-weight: 600; color: var(--text-secondary); letter-spacing: -0.1px; line-height: 1.4; }
.cc-step-cost-row { display: flex; justify-content: center; margin-top: 8px; }
.cp-loading {
  position: absolute;
  inset: 0;
  z-index: 60;
  background: var(--bg-base);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
}
.cp-loading[hidden] { display: none; }
.cp-spinner {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 3px solid var(--border-subtle);
  border-top-color: var(--brand-primary);
  animation: cp-spin 0.9s linear infinite;
}
@keyframes cp-spin { to { transform: rotate(360deg); } }
.cp-title { font-size: 15px; font-weight: 700; color: var(--text-primary); letter-spacing: -0.2px; }
.cp-dots span { animation: cp-dot 1.2s infinite; opacity: 0; }
.cp-dots span:nth-child(2) { animation-delay: 0.2s; }
.cp-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes cp-dot { 0%, 60%, 100% { opacity: 0; } 30% { opacity: 1; } }

/* ─── Skeleton (canonical) ────────────────────────────────────── */
.sk {
  background-color: var(--bg-surface-elevated);
  background-image: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0)    0%,
    rgba(255, 255, 255, 0.06) 50%,
    rgba(255, 255, 255, 0)    100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: skShimmer 1.5s linear infinite;
  border-radius: var(--radius-sm);
  display: block;
}
.sk.circle { border-radius: var(--radius-full); }
.sk.pill   { border-radius: var(--radius-full); }

/* ─── Empty / Error states ────────────────────────────────────── */
.empty,
.error {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  max-width: 300px;
  margin: 0 auto;
}
.empty-icon {
  width: 80px;
  height: 80px;
  border-radius: var(--radius-full);
  background: var(--brand-accent-muted);
  border: 1px solid rgba(110, 66, 207, 0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--brand-accent-hover);
  margin-bottom: 6px;
  box-shadow: 0 0 0 8px rgba(110, 66, 207, 0.05);
  animation: pulse-soft 3s ease-in-out infinite;
}
.empty-icon svg { width: 48px; height: 48px; }
.empty-title {
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.5px;
}
.empty-sub {
  font-size: 14px;
  font-weight: 500;
  color: var(--text-secondary);
  letter-spacing: -0.1px;
  line-height: 1.45;
}
.error-icon {
  width: 80px;
  height: 80px;
  border-radius: var(--radius-full);
  background: var(--brand-fade-muted);
  border: 1px solid rgba(239, 68, 68, 0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--brand-fade);
  margin-bottom: 6px;
  box-shadow: 0 0 0 8px rgba(239, 68, 68, 0.05);
  animation: pulse-soft 3s ease-in-out infinite;
}
.error-icon svg { width: 48px; height: 48px; }
.error-title { font-size: 20px; font-weight: 800; letter-spacing: -0.5px; }
.error-sub {
  font-size: 14px;
  font-weight: 500;
  color: var(--text-secondary);
  letter-spacing: -0.1px;
  line-height: 1.45;
}
/* ──── Call-detail screen + feed card tap-through (#31 Phase 3) ──── */

/* Stretched-link overlay: the whole feed card body navigates to the
   detail screen, except the Yes/No buttons which sit above the
   overlay via z-index. The user-header profile link is a sibling
   BEFORE .call-card, so it is never covered. */
.call-card .card-tap {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
}
.call-card .card-actions { position: relative; z-index: 2; }

/* Sub-row (back + title), rendered in the above_content slot so it
   stays outside the .content scroll region. */
.cd-subrow {
  /* v2 (2026-08-06): flex, not the 44/1fr/44 grid — the right side
   * now holds TWO buttons (share + ext), so the title centers via
   * position: absolute below instead of a mirrored spacer column. */
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: calc(6px + env(safe-area-inset-top, 0px)) 8px 8px;
  border-bottom: 1px solid var(--border-default);
  flex-shrink: 0;
}
.cd-icon-btn {
  width: 36px;
  height: 36px;
  /* No auto margins — they centered the back button in the flex
     row (device pass 2026-08-10). The mock pins it hard left; the
     title centers absolutely and the right button carries
     margin-left: auto. */
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  color: var(--text-primary);
  transition: background-color 150ms ease, transform 150ms ease;
}
.cd-icon-btn:hover  { background: var(--bg-surface-hover); }
.cd-icon-btn:active { transform: scale(0.96); }
.cd-title {
  /* Absolute-centered so an asymmetric button count (1 left, 2 right)
   * can't shove the title off optical center. pointer-events: none —
   * it overlays the row and must not eat button taps. */
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.3px;
  white-space: nowrap;
  pointer-events: none;
}
.cd-subrow .cd-share-btn,
.cd-subrow .cd-ext-btn {
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  flex-shrink: 0;
  transition: background-color 150ms ease, color 150ms ease;
}
.cd-subrow .cd-share-btn { margin-left: auto; }
.cd-subrow .cd-share-btn:hover,
.cd-subrow .cd-ext-btn:hover { background: var(--bg-surface); color: var(--text-primary); }
.cd-subrow .cd-share-btn:active,
.cd-subrow .cd-ext-btn:active { transform: scale(0.94); }
.cd-subrow .cd-share-btn svg,
.cd-subrow .cd-ext-btn svg { width: 18px; height: 18px; }

.call-detail { display: flex; flex-direction: column; gap: 12px; padding: 14px 0; }
.call-detail .empty { margin: 40px auto; }
/* V3: detail content sits vertically centered when shorter than the
   viewport. Scoped with :has so the global .content scroll region
   keeps block layout on every other page. */
.content:has(> .call-detail) { display: flex; flex-direction: column; }
.content:has(> .call-detail) > .call-detail { flex: 1; justify-content: center; }

/* Shared creator-details row (2026-07-17): accuracy + record + XP,
 * used by the feed/detail .user-header. */
.creator-xp {
  font-size: 10px;
  font-weight: 700;
  color: var(--brand-accent);
  background: var(--brand-accent-muted);
  padding: 2px 7px;
  border-radius: var(--radius-full);
}
.creator-details { display: flex; align-items: center; gap: 10px; min-width: 0; }

/* V3 market stats (inside .call-summary): icon-led values, no
   uppercase labels. The bars/person icons carry the meaning. */
.call-detail .mstat.center { text-align: center; }
.call-detail .mstat.right  { text-align: right; }
.call-detail .mstat.center .mstat-val.pool-split { letter-spacing: -0.2px; white-space: nowrap; }
.call-detail .mstat-val.vol-icons {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-secondary);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.1px;
}
.call-detail .mstat-val.vol-icons.vi-right { justify-content: flex-end; }
.vol-icons svg { color: var(--text-tertiary); flex-shrink: 0; }

.call-detail .cd-actions { margin-top: 2px; }

/* Trades sheet: breathing room between the Yes/No filter tabs and
   the first row (business 2026-08-11), and pointer affordance on
   the tabs now that they filter. */
.trade-sheet .cs-trades { margin-top: 12px; }
.trade-sheet .ps-side { cursor: pointer; }

/* In-card trades (.cs-trades): flat quote-banner rows, dividers
   between rows only, + the More reveal. */
.cs-trades { margin-top: 0; }
.cs-trades .quote-banner {
  background: none;
  border: none;
  border-radius: 0;
  margin: 0;
  padding: 8px 2px;
}
.cs-trades .quote-banner + .quote-banner { border-top: 1px solid var(--border-default); }
.cs-trades .quote-banner:last-child { padding-bottom: 4px; }
.cs-more {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  min-height: 36px;
  padding: 8px 2px;
  margin-bottom: -8px;
  background: none;
  border: none;
  border-top: 1px solid var(--border-default);
  color: var(--text-secondary);
  cursor: pointer;
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.1px;
  transition: color 150ms ease;
}
.cs-more:hover { color: var(--text-primary); }
.cs-more svg { width: 14px; height: 14px; }

/* Settled outcome pill (social row right slot) */
.settle-pill {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: -0.1px;
}
.settle-pill svg { width: 9px; height: 9px; }
.settle-pill.hit  { color: var(--brand-primary); background: var(--brand-primary-muted); }
.settle-pill.miss { color: var(--brand-fade); background: var(--brand-fade-muted); }
.post-social .settle-pill { margin-left: auto; }

/* "Trades" bottom sheet (V3 trade-comment-sheet). Geometry + motion
   match .bet-sheet / .login-sheet so the sheets read as one system. */
.trade-sheet {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  max-height: 76%;
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  border-top-left-radius: var(--radius-lg);
  border-top-right-radius: var(--radius-lg);
  border-top: 1px solid var(--border-subtle);
  padding: 10px 20px calc(16px + env(safe-area-inset-bottom));
  z-index: 41;
  box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.5);
  transform: translateY(100%);
  transition: transform 300ms var(--ease-out);
  visibility: hidden;
}
.trade-sheet.open { transform: translateY(0); visibility: visible; }
.sheet-grab {
  width: 36px; height: 4px;
  border-radius: var(--radius-full);
  background: var(--border-default);
  margin: 2px auto 10px;
  flex-shrink: 0;
}
.ts-title {
  font-size: 17px; font-weight: 800;
  letter-spacing: -0.3px;
  text-align: center;
  color: var(--text-primary);
  margin-bottom: 4px;
  flex-shrink: 0;
}
.trade-sheet .post-social {
  margin-top: 0;
  padding: 8px 2px 0;
  border-top: none;
  flex-shrink: 0;
}
.trade-sheet .cs-trades {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Settings modal rows (three-dot header button) */
.set-rows { display: flex; flex-direction: column; gap: 4px; }
.set-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 10px;
  border: none;
  background: none;
  border-radius: var(--radius-md);
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  text-decoration: none;
  transition: background-color 150ms ease;
}
.set-row:hover { background: var(--bg-surface-hover); }
.set-row:active { transform: scale(0.99); }
.set-ic {
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-secondary);
  flex-shrink: 0;
}
.set-ic svg { width: 18px; height: 18px; }
.set-lbl { font-size: 14px; font-weight: 700; color: var(--text-primary); letter-spacing: -0.2px; }

/* ──── Sign-in surface (/login, WP4) ───────────────────────────── */
.login-screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 8px;
  padding: 40px 20px 24px;
  max-width: 360px;
  margin: 0 auto;
}
.login-title { font-size: 22px; font-weight: 800; letter-spacing: -0.5px; }
.login-sub { font-size: 14px; font-weight: 500; color: var(--text-secondary); letter-spacing: -0.1px; }
.privy-login { width: 100%; margin-top: 18px; display: flex; flex-direction: column; gap: 12px; }
.pl-field { display: flex; flex-direction: column; gap: 10px; }
.pl-input {
  width: 100%;
  height: 48px;
  padding: 0 14px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-default);
  background: var(--bg-surface);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 15px;
  letter-spacing: -0.1px;
  outline: none;
  transition: border-color 150ms ease;
}
.pl-input::placeholder { color: var(--text-tertiary); }
.pl-input:focus { border-color: var(--brand-primary); }
.pl-btn {
  height: 48px;
  border-radius: var(--radius-md);
  border: none;
  background: var(--brand-primary);
  color: #fff;
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 800;
  letter-spacing: -0.1px;
  cursor: pointer;
  transition: filter 150ms ease, transform 150ms ease, opacity 150ms ease;
}
.pl-btn:hover { filter: brightness(1.08); }
.pl-btn:active { transform: scale(0.98); }
.pl-btn:disabled { opacity: 0.6; cursor: default; }
.pl-status { font-size: 13px; font-weight: 500; color: var(--text-secondary); min-height: 18px; letter-spacing: -0.1px; }
.pl-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 4px 0;
}
.pl-divider::before, .pl-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border-subtle);
}
.pl-oauth-row { display: flex; flex-direction: column; gap: 10px; }
.pl-oauth {
  background: var(--bg-surface);
  color: var(--text-primary);
  border: 1px solid var(--border-default);
}
.pl-oauth:hover { filter: none; background: var(--bg-surface-hover); }

/* Closed-market note shown in place of the live Yes/No controls when
   a call is locked / settled / cancelled. */
.call-detail .cd-closed {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 2px;
  padding: 12px 14px;
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
}
.call-detail .cd-closed svg { width: 20px; height: 20px; flex-shrink: 0; color: var(--text-tertiary); }
.call-detail .cd-closed-text { display: flex; flex-direction: column; gap: 1px; }
.call-detail .cd-closed-title { font-size: 13px; font-weight: 700; color: var(--text-primary); letter-spacing: -0.2px; }
.call-detail .cd-closed-sub { font-size: 12px; font-weight: 500; color: var(--text-tertiary); }

/* ──── Loading skeleton (#31 Phase 3, TRADELEAGUE_MOCK_LOADING=1) ──── */
.loading-skel { padding: 4px 0; }
.skel-card {
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: 16px;
  margin-bottom: 12px;
}
.skel-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.skel-lines { display: flex; flex-direction: column; gap: 7px; flex: 1; }
.skel-line { display: block; height: 11px; border-radius: 6px; }
.skel-line.w85 { width: 85%; }
.skel-line.w65 { width: 65%; }
.skel-line.w50 { width: 50%; }
.skel-line.w30 { width: 30%; }
.skel-avatar { width: 40px; height: 40px; border-radius: var(--radius-full); flex-shrink: 0; }
.skel-bar { height: 10px; border-radius: var(--radius-full); margin: 14px 0; }
.skel-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.skel-btn { height: 44px; border-radius: var(--radius-md); }
.skel-avatar,
.skel-line,
.skel-bar,
.skel-btn {
  background: var(--bg-surface-hover);
  animation: ds-shimmer 1.5s infinite ease-in-out;
}

/* ─── Bet sheet (canonical tmp/bet-confirmation.html) ─────────── */
.bet-overlay {
  position: absolute;
  inset: 0;
  background: #000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms ease;
  z-index: 40;
}
.bet-overlay.open { opacity: 0.6; pointer-events: auto; }
.bet-sheet {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  background: var(--bg-surface);
  border-top-left-radius: var(--radius-lg);
  border-top-right-radius: var(--radius-lg);
  border-top: 1px solid var(--border-subtle);
  padding: 10px 20px calc(20px + env(safe-area-inset-bottom));
  z-index: 41;
  display: flex;
  flex-direction: column;
  gap: 16px;
  box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.5);
  transform: translateY(100%);
  transition: transform 300ms var(--ease-out);
  visibility: hidden;
}
.bet-sheet.open { transform: translateY(0); visibility: visible; }

/* ─── Login sheet (shell stand-in for Privy's web modal) ──────────
   Privy's native SDKs ship no aggregate modal, so the shell draws its
   own. Geometry + motion deliberately match .bet-sheet so the two
   sheets read as one system. */
.ls-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  opacity: 0;
  visibility: hidden;
  transition: opacity 220ms var(--ease-out), visibility 220ms var(--ease-out);
  z-index: 40;
}
.ls-overlay.open { opacity: 1; visibility: visible; }
.login-sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--bg-surface);
  border-top-left-radius: var(--radius-lg);
  border-top-right-radius: var(--radius-lg);
  border-top: 1px solid var(--border-subtle);
  padding: 10px 20px calc(20px + env(safe-area-inset-bottom));
  z-index: 41;
  display: flex;
  flex-direction: column;
  gap: 16px;
  box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.5);
  transform: translateY(100%);
  transition: transform 300ms var(--ease-out);
  visibility: hidden;
}
.login-sheet.open { transform: translateY(0); visibility: visible; }
.ls-title {
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.3px;
  text-align: center;
  color: var(--text-primary);
}
.ls-options {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* Same visual language as .connect-btn, scoped to the sheet so the
   menu's own CTA styling is untouched. */
.ls-option {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 14px 16px;
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.2px;
  cursor: pointer;
  transition: background 160ms var(--ease-out), border-color 160ms var(--ease-out);
}
.ls-option:active { background: var(--bg-surface); }
.ls-option:disabled { opacity: 0.6; cursor: default; }
.ls-option svg { width: 18px; height: 18px; flex: none; }
.ls-privy {
  text-align: center;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-tertiary);
}
.ls-privy-mark { color: var(--text-secondary); font-weight: 800; }
/* V3 (2026-08-08 drop): the combined summary card — column layout
   shared by the bet sheet's one-line summary and the prediction-detail
   page, where it hosts the whole market (price row, bar, actions,
   stats, social row, trades). */
.call-summary {
  display: flex; flex-direction: column; gap: 10px;
  padding: 14px;
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.cs-line { display: flex; align-items: center; gap: 10px; }
.cs-line .cs-time { margin-top: 2px; }
.cs-text {
  flex: 1; min-width: 0;
  font-size: 15px; font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -0.3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cs-time {
  flex-shrink: 0;
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 700;
  color: var(--text-secondary);
}
.cs-time svg { width: 11px; height: 11px; }
/* Tertiary is DETAIL-scoped (mock: ".call-detail .cs-time") — the
   bottom sheets keep the base secondary time-left treatment. The
   old unscoped `.call-summary .cs-time` grayed every sheet's
   timestamp (tester round 5, #188 item 9). */
.call-detail .cs-time { color: var(--text-tertiary); }
.call-summary .cs-time { margin-top: 2px; }
.call-summary .user-header {
  border-bottom: 1px solid var(--border-default);
  margin-bottom: 0;
  padding: 0 0 8px 0;
}
/* Sheet card slot (#188 items 7/8): the trade sheets clone the
   tapped card's .user-header into .cs-user at open. display:
   contents makes the clone a direct flex child of .call-summary so
   the mock's card grammar (gap, divider) applies untouched; the
   :not([hidden]) guard keeps the empty slot collapsible. */
.call-summary .cs-user:not([hidden]) { display: contents; }
.call-summary .price-row { margin-bottom: 0; }
.call-summary .price-row .price-current {
  font-family: var(--font-mono);
  font-size: 14px; font-weight: 800;
  letter-spacing: -0.3px;
  color: var(--text-primary);
}
.call-summary .market-bar-wrap { margin-bottom: 0; }
.call-summary .market-stats {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 8px;
  margin-top: 0;
}
.call-summary .market-stats,
.call-summary .market-stats .mstat-val,
.call-summary .market-stats .pool-split { font-size: 12px; }
.call-summary .post-social { margin-top: -2px; padding-top: 6px; }
/* pos-type banner: removed round 5, RESTORED round 6 ("trade +
   confirmation sheet is missing the backing/fading prediction bar
   at the top"). */
.pos-type {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 14px;
  border-radius: var(--radius-md);
  font-size: 13px; font-weight: 800;
  letter-spacing: -0.2px;
  background: var(--brand-primary-muted);
  color: var(--brand-primary);
  border: 1px solid rgba(39, 188, 129, 0.3);
}
.pos-type.fade {
  background: var(--brand-fade-muted);
  color: var(--brand-fade);
  border-color: rgba(239, 68, 68, 0.3);
}
.pos-type svg { width: 14px; height: 14px; }
[data-bet-confirm-sheet] .pos-type svg { width: 16px; height: 16px; }
/* In-sheet Position chip matches the $X Position pill (mock:
   12px / 3px 9px; the shared 10.5px rule is the history chip). */
.bet-sheet .qb-amount { font-size: 12px; padding: 3px 9px; }
.shares-section {
  display: flex; flex-direction: column; gap: 12px;
  padding: 16px 14px;
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.shares-lbl {
  font-size: 10px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--text-tertiary);
  text-align: center;
}
.shares-control {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
}
.shares-num {
  flex: 1;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 32px; font-weight: 800;
  letter-spacing: -1.2px;
  color: var(--text-primary);
  line-height: 1;
}
/* Editable variant (bet sheet): borderless input that reads like
 * the static number; spinners hidden — the ± buttons and quick
 * chips are the primary affordance. Inputs have a UA-intrinsic
 * width (~20ch) and don't inherit typography, so pin flex-basis
 * to 0 and restate the type ramp explicitly. */
input.shares-num {
  flex: 1 1 0;
  width: 100%;
  min-width: 0;
  height: auto;
  margin: 0;
  background: none;
  border: none;
  outline: none;
  padding: 0;
  font: 800 32px/1 var(--font-mono);
  letter-spacing: -1.2px;
  color: var(--text-primary);
  text-align: center;
  -moz-appearance: textfield;
  appearance: textfield;
}
input.shares-num::-webkit-outer-spin-button,
input.shares-num::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.quick-row { display: flex; gap: 6px; justify-content: center; }
.quick {
  flex: 1;
  padding: 7px 0;
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-full);
  font-family: var(--font-mono);
  font-size: 12px; font-weight: 700;
  color: var(--text-secondary);
  cursor: pointer;
  letter-spacing: -0.2px;
  transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease;
}
.quick:hover { color: var(--text-primary); border-color: var(--brand-primary); }
.quick.active {
  background: var(--brand-primary-muted);
  color: var(--brand-primary);
  border-color: var(--brand-primary);
}
.quick[disabled] { opacity: 0.35; cursor: not-allowed; }
.breakdown {
  display: flex; flex-direction: column;
  padding: 14px;
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.breakdown .row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 7px 0;
  font-size: 13px;
}
.breakdown .row + .row { border-top: 1px dashed var(--border-subtle); }
.breakdown .row:first-child { padding-top: 0; }
.breakdown .row:last-child { border-bottom: none; padding-bottom: 0; }

/* ─── Trade bubble (v2, 2026-08-06) ───────────────────────────────
   One container holding Available Balance -> amount input -> presets
   -> cost/payout. The children keep their standalone rules (the
   create-prediction flow still uses .shares-section and .breakdown
   bare), and these child overrides strip their card chrome so inside
   the bubble they read as rows of one surface rather than three
   stacked cards. */
.trade-bubble {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 14px 10px;
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.trade-bubble > .wallet-row { background: transparent; border: none; padding: 0; padding-bottom: 10px; border-bottom: 1px dashed var(--border-subtle); }
.trade-bubble > .shares-section { padding: 0; background: transparent; border: none; border-radius: 0; gap: 10px; }
.trade-bubble > .breakdown { padding: 8px 0 0; background: transparent; border: none; border-radius: 0; border-top: 1px dashed var(--border-subtle); }

.wallet-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.wallet-row .wallet-ico { display: inline-flex; align-items: center; justify-content: center; flex: none; color: var(--text-secondary); }
.wallet-row .wallet-ico svg { width: 18px; height: 18px; }
.wallet-row .wallet-lbl { font-size: 13px; font-weight: 700; letter-spacing: -0.1px; color: var(--text-primary); }
.wallet-row .wallet-balance {
  margin-left: auto;
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 800;
  letter-spacing: -0.3px;
  color: var(--text-primary);
}
.wallet-row .wallet-balance .ccy { font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-tertiary); }

/* The amount field sizes to its content so the "$" prefix stays glued
   to the number instead of floating at a fixed offset. */
.amount-input-wrap { flex: 1 1 0; min-width: 0; display: flex; align-items: baseline; justify-content: center; gap: 3px; }
.amount-input-wrap .amount-prefix { font-family: var(--font-mono); font-size: 22px; font-weight: 800; color: var(--text-secondary); letter-spacing: -0.6px; line-height: 1; flex: none; }
input.shares-num.amount-input { flex: 0 1 auto; width: auto; min-width: 40px; max-width: 100%; text-align: left; padding: 0; field-sizing: content; }

/* Cost is two facts on one line: how the dollars became shares, and
   what is actually charged. */
.breakdown .cost-val { display: inline-flex; align-items: baseline; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.breakdown .cost-val .cost-calc { font-family: var(--font-mono); font-size: 13px; font-weight: 700; color: var(--text-secondary); letter-spacing: -0.2px; }
.breakdown .cost-val .cost-total { font-family: var(--font-mono); font-size: 14px; font-weight: 700; color: var(--text-primary); letter-spacing: -0.3px; }

/* ─── Wallet page (v2, #159 WS-A) ─────────────────────────────────
   Hero Total Balance + breakdown tiles + disabled Deposit/Withdraw.
   SIX tiles, not the mock's 2x2 — At Stake and Unclaimed were added
   by decision 2026-08-05 (§2.1: without them escrowed money has no
   surface anywhere in the product). The 1fr 1fr grid reflows six
   items to three rows with no extra CSS. */
.wallet-page { display: flex; flex-direction: column; gap: 12px; padding: 4px 0 12px; }
.wallet-hero {
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 20px 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
.wallet-hero-lbl {
  color: var(--text-tertiary);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.wallet-hero-val {
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: 38px;
  font-weight: 800;
  letter-spacing: -1.4px;
  line-height: 1.05;
}
.wallet-breakdown { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.wb-item {
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: background-color 150ms ease;
}
.wb-item:hover { background: var(--bg-surface-hover); }
.wb-lbl {
  color: var(--text-tertiary);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.wb-val {
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.4px;
  line-height: 1.15;
}
.wb-val.green { color: var(--brand-primary); }
.wb-val.red { color: var(--brand-fade); }
.wb-val.gold { color: var(--gold-soft); text-shadow: 0 0 12px rgba(255, 215, 0, 0.22); }
.wallet-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.wallet-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 48px;
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: 14.5px;
  font-weight: 800;
  letter-spacing: -0.2px;
  cursor: pointer;
  transition: filter 150ms ease, transform 100ms ease, background-color 150ms ease, border-color 150ms ease;
}
.wallet-btn svg { width: 16px; height: 16px; }
.wallet-btn.deposit  { background: var(--brand-primary); border: 1px solid transparent; color: #fff; box-shadow: 0 4px 14px rgba(39, 188, 129, 0.32); }
.wallet-btn.withdraw { background: var(--brand-fade); border: none; color: #fff; box-shadow: 0 4px 12px rgba(239, 68, 68, 0.28); }
.wallet-btn.deposit:hover, .wallet-btn.withdraw:hover { filter: brightness(1.06); }
.wallet-btn.deposit:active, .wallet-btn.withdraw:active { transform: scale(0.98); }
.wallet-btn:disabled { opacity: 0.55; cursor: not-allowed; filter: none; transform: none; box-shadow: none; }

/* Recent Activity (placeholder rows until the #161 ledger lands) */
.wallet-activity { display: flex; flex-direction: column; gap: 10px; }
.wallet-list { display: flex; flex-direction: column; gap: 8px; }
.wact {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  transition: background-color 150ms ease;
}
.wact:hover { background: var(--bg-surface-hover); }
.wact-ico {
  width: 36px; height: 36px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-subtle);
}
.wact-ico svg { width: 16px; height: 16px; }
.wact-ico.pos { background: var(--brand-primary-muted); border-color: rgba(39, 188, 129, 0.28); color: var(--brand-primary); }
.wact-ico.neg { background: var(--brand-fade-muted); border-color: rgba(239, 68, 68, 0.28); color: var(--brand-fade); }
.wact-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.wact-lbl {
  font-size: 13.5px; font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.2px; line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wact-time { font-family: var(--font-mono); font-size: 11px; font-weight: 500; color: var(--text-tertiary); letter-spacing: -0.1px; }
.wact-amt { flex-shrink: 0; font-family: var(--font-mono); font-size: 14px; font-weight: 800; letter-spacing: -0.3px; }
.wact-amt.pos { color: var(--brand-primary); }
.wact-amt.neg { color: var(--brand-fade); }

/* Menu wallet row: the balance figure sits between label and chevron. */
.menu-screen .row--wallet .row-label { font-weight: 700; }
.menu-screen .row--wallet .wallet-balance {
  margin-left: auto;
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: 14.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.2px;
}

/* Insufficient-balance explanation under the CTA. NOT in the v2
   mocks — the mocks have no failure state, but blocking the button
   without saying why is not shippable. Deliberately reuses the
   retired .wallet-note's size/placement so it reads as the same slot. */
/* .bet-warn retired 2026-08-12 (no-inline-errors rule) — the
   funds modal is the balance surface. */
.bet-warn-retired {
  margin: 0;
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: -0.1px;
  color: var(--brand-fade);
}
.bet-warn[hidden] { display: none; }
.breakdown .lbl {
  color: var(--text-secondary);
  font-weight: 600;
  letter-spacing: -0.1px;
}
.breakdown .val {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.3px;
}
.breakdown .val.green { color: var(--brand-primary); }
.breakdown .profit-pct {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--brand-primary);
  margin-left: 4px;
  opacity: 0.85;
}
.bet-sheet .cta {
  display: flex; align-items: center; justify-content: center; gap: 8px;
}
.bet-sheet .cta.fade {
  background: var(--brand-fade);
  box-shadow: 0 4px 14px rgba(239, 68, 68, 0.32);
}
.bet-sheet .cancel {
  align-self: center;
  background: none; border: none;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 13px; font-weight: 600;
  letter-spacing: -0.1px;
  cursor: pointer;
  padding: 4px 12px;
  transition: color 150ms ease;
}
.bet-sheet .cancel:hover { color: var(--text-primary); }
.wallet-note {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  font-size: 11px; font-weight: 600;
  color: var(--text-tertiary);
  letter-spacing: -0.1px;
}
.wallet-note svg { width: 12px; height: 12px; }
.bet-toast {
  position: absolute;
  left: 50%;
  bottom: calc(84px + env(safe-area-inset-bottom));
  transform: translateX(-50%) translateY(8px);
  background: var(--bg-surface-elevated);
  border: 1px solid var(--brand-primary);
  color: var(--text-primary);
  font-size: 13px; font-weight: 700;
  padding: 10px 16px;
  border-radius: var(--radius-full);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease, transform 200ms var(--ease-out);
  z-index: 42;
}
.bet-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ──── Live price flash (P4, #98) ─────────────────────────────────
 * price-ticker.js toggles these on [data-price-asset] cells per the
 * server-sent direction. `from`-only keyframes: the color snaps to
 * green/red then eases back to the element's own computed color, so
 * one animation works on every surface regardless of base color. */
.price-flash-up { animation: price-flash-up 900ms ease-out; }
.price-flash-down { animation: price-flash-down 900ms ease-out; }
/* Hold the flash color through 40% of the run so it reads before the
 * ease back to the element's own color (2026-07-09 feedback). */
@keyframes price-flash-up { 0%, 40% { color: var(--green); } }
@keyframes price-flash-down { 0%, 40% { color: var(--brand-fade); } }
@media (prefers-reduced-motion: reduce) {
  .price-flash-up, .price-flash-down { animation: none; }
}

/* ───── Social: follow button skins, follow lists (2026-09-24) ───── */
/* Header pill (profile-unfollowed.html): gray outline in .name-row. */
.name-row .follow-btn {
  margin-left: auto;
  padding: 3px 12px;
  height: 24px;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--text-secondary);
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: -0.2px;
  cursor: pointer;
  transition: width 220ms cubic-bezier(0.34, 1.56, 0.64, 1),
              padding 220ms cubic-bezier(0.34, 1.56, 0.64, 1),
              border-radius 220ms ease,
              background-color 150ms ease,
              color 150ms ease,
              border-color 150ms ease,
              transform 150ms ease;
}
.name-row .follow-btn:hover { background: rgba(160, 174, 192, 0.12); color: var(--text-primary); border-color: var(--text-primary); }
.name-row .follow-btn:active { transform: scale(0.97); }
/* Header circle (profile-followed.html). */
.followed-btn {
  margin-left: auto;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--text-secondary);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  padding: 0;
  transition: width 220ms cubic-bezier(0.34, 1.56, 0.64, 1),
              padding 220ms cubic-bezier(0.34, 1.56, 0.64, 1),
              border-radius 220ms ease,
              background-color 150ms ease,
              color 150ms ease,
              border-color 150ms ease,
              transform 150ms ease;
}
.followed-btn:hover { background: rgba(160, 174, 192, 0.12); color: var(--text-primary); border-color: var(--text-primary); }
.followed-btn:active { transform: scale(0.94); }
.followed-btn svg { width: 14px; height: 14px; }
/* List rows (profile-followers.html). `.pl-row` is a div wrapper; the
   identity surface is the inner `.pl-link` anchor (button is a sibling —
   <button> inside <a> is invalid HTML; approved deviation). */
.pl-list { display: flex; flex-direction: column; padding: 4px 0 8px; }
.pl-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 18px; min-height: 56px;
  border-bottom: 1px solid var(--border-subtle);
  transition: background-color 150ms ease;
}
.pl-row:hover { background: var(--bg-surface); }
.pl-row:last-child { border-bottom: none; }
.pl-link { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; color: inherit; text-decoration: none; }
.pl-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pl-name-row { display: flex; align-items: center; gap: 6px; }
.pl-name { font-size: 14px; font-weight: 800; color: var(--text-primary); letter-spacing: -0.3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-stats { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; overflow: hidden; white-space: nowrap; min-width: 0; }
.pl-follow-btn {
  flex-shrink: 0; padding: 3px 14px; height: 26px;
  border-radius: var(--radius-full); background: transparent;
  color: var(--text-secondary); border: 1px solid var(--text-secondary);
  font-family: var(--font-sans); font-size: 12px; font-weight: 800; letter-spacing: -0.2px;
  cursor: pointer;
  transition: color 150ms ease, border-color 150ms ease, background-color 150ms ease, transform 150ms ease;
}
.pl-follow-btn:hover  { color: var(--text-primary); border-color: var(--text-primary); background: rgba(160, 174, 192, 0.10); }
.pl-follow-btn:active { transform: scale(0.97); }
.pl-follow-btn[data-state="following"] {
  width: 28px; height: 28px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; padding: 0;
}
.pl-follow-btn[data-state="following"]:hover { background: transparent; }
.pl-follow-btn[data-state="following"]:active { transform: scale(0.94); }
.pl-follow-btn[data-state="following"] svg { width: 14px; height: 14px; }
.pl-follow-btn:disabled { opacity: 0.6; cursor: progress; }
/* List-page sub-row identity cluster. */
.pf-title-user { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 4px 6px; border-radius: var(--radius-md); transition: background-color 150ms ease; }
.pf-title-user:hover { background: var(--bg-surface); }
.pf-title-name { font-size: 14.5px; font-weight: 800; color: var(--text-primary); letter-spacing: -0.3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pf-header-spacer { width: 36px; height: 36px; flex-shrink: 0; visibility: hidden; }
.tab-count { color: var(--text-tertiary); font-weight: 600; margin-left: 5px; }
.pl-more { display: block; padding: 12px 18px; text-align: center; font-size: 13px; font-weight: 700; color: var(--text-tertiary); text-decoration: none; }
.pl-more:hover { color: var(--text-primary); }
.profile .social .social-link { color: inherit; text-decoration: none; }
.profile .social .social-link:hover strong { text-decoration: underline; }

/* Edit-profile modal (edit-profile-modal.html), WS-I Task 14. Camera
   badge (.ep-cam) is skipped — no upload path yet. `.ep-avatar`'s
   hard-coded gradient is dropped versus the mock; the markup instead
   carries the base `.avatar` class alongside `.ep-avatar` so the
   canonical `.avatar.av-*` palette rules (same convention as every
   other avatar in the app) paint the gradient. `.ep-avatar.avatar`
   below pins the mock's 88px size / 34px type against `.avatar`'s own
   (smaller) base sizing — belt-and-braces alongside `.ep-avatar`
   simply being declared later in this file. */
.ep-photo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-top: 2px;
}
.ep-avatar-wrap {
  position: relative;
  width: 88px;
  height: 88px;
  cursor: pointer;
}
/* Camera badge — disc pinned bottom-right of the avatar (edit-profile-modal.html). */
.ep-cam {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--bg-surface-hover);
  border: 3px solid var(--bg-surface-elevated);
  display: grid;
  place-items: center;
  color: var(--text-primary);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.35);
  transition: filter 150ms ease, transform 150ms ease;
}
.ep-avatar-wrap:hover  .ep-cam { filter: brightness(1.15); }
.ep-avatar-wrap:active .ep-cam { transform: scale(0.92); }
.ep-avatar-wrap.busy { opacity: 0.6; pointer-events: none; }
.ep-cam svg { width: 15px; height: 15px; }
.ep-avatar {
  width: 88px;
  height: 88px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -0.5px;
  color: #fff;
  border: 2px solid var(--border-default);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  user-select: none;
}
.ep-avatar.avatar {
  width: 88px;
  height: 88px;
  border-radius: var(--radius-full);
  font-size: 34px;
}
/* Neither the modal avatar nor the profile header avatar is a control
   (no upload path), so the global `.avatar:hover` scale reads as a
   broken button on them (business 2026-10-01: "remove the hover
   effect on profile pic"). */
.ep-avatar.avatar:hover,
.profile .avatar.xl:hover { transform: none; }
/* edit-profile-modal.html: footer sits 4px under the field, not the
   16px the other modals use. */
[data-edit-profile-modal] .m-foot { margin-top: 4px; }
.ep-field { display: flex; flex-direction: column; gap: 7px; }
.ep-lbl {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2px;
  text-transform: uppercase;
  color: var(--text-tertiary);
  padding-left: 2px;
}
.ep-input-wrap {
  display: flex;
  align-items: center;
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 0 14px;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
.ep-input-wrap:focus-within {
  border-color: var(--brand-primary);
  box-shadow: 0 0 0 3px rgba(39, 188, 129, 0.18);
}
.ep-at {
  color: var(--text-tertiary);
  font-size: 15px;
  font-weight: 700;
  margin-right: 2px;
}
.ep-input {
  flex: 1;
  min-width: 0;
  background: none;
  border: none;
  outline: none;
  color: var(--text-primary);
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.1px;
  padding: 13px 0;
}
.ep-input::placeholder { color: var(--text-tertiary); font-weight: 500; }

/* ─── Onboarding: tutorial pages + Login 1 (design spec 2026-10-12;
   mocks docs/onboarding-mocks.zip). Bare chrome: the body owns the
   screen, so .content drops its padding/scroll only when it holds the
   onboarding screen. ─────────────────────────────────────────────── */
.content:has(> .onb-screen) { padding: 0; overflow: hidden; display: flex; }
.onb-screen { position: relative; display: flex; flex-direction: column; width: 100%; flex: 1; min-height: 0; background: var(--bg-base); overflow: hidden; }
/* `.onboard .cta` / `.onb-modal .ls-cta` set `display: inline-flex`, which
   beats the UA `[hidden] { display: none }` rule — without this override
   the platform-gated Seeker/Connect-Wallet pair (data-android-only /
   data-not-android, toggled by wallet-bridge.js) both stay visible until
   JS runs, and on a JS-less or pre-paint frame both primaries show. */
.onb-screen [hidden] { display: none !important; }
img.tut-bg, img.hero-bg { position: absolute; left: 50%; top: 40%; height: 105%; width: auto; transform: translate(-86.5%, -29%); opacity: 0.26; pointer-events: none; z-index: 0; -webkit-mask-image: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 7%, rgba(0,0,0,1) 62%, rgba(0,0,0,0) 96%); mask-image: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 7%, rgba(0,0,0,1) 62%, rgba(0,0,0,0) 96%); }
.tut { position: relative; z-index: 1; flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; padding: calc(env(safe-area-inset-top, 0px) + 24px) 20px calc(env(safe-area-inset-bottom, 0px) + 20px); text-align: center; }
.tut-nav-btn { position: absolute; top: calc(env(safe-area-inset-top, 0px) + 12px); z-index: 3; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border: none; background: transparent; border-radius: var(--radius-full); color: var(--text-primary); cursor: pointer; transition: background-color 150ms ease, transform 150ms ease; }
.tut-nav-btn:hover { background: var(--bg-surface-hover); }
.tut-nav-btn:active { transform: scale(0.96); }
.tut-nav-btn.back { left: 10px; }
.tut-nav-btn.close { right: 10px; }
.tut-nav-btn.close svg { transition: transform 300ms var(--ease-out); }
.tut-nav-btn.close:hover svg { transform: rotate(90deg); }
.tut-brand, .onboard-brand { display: flex; flex-direction: column; align-items: center; gap: 10px; margin-top: 12%; flex-shrink: 0; }
.tut-brand img.wordmark, .onboard-brand img.wordmark { display: block; width: 260px; height: auto; }
.tut-brand picture.built-on, .onboard-brand picture.built-on { display: inline-block; line-height: 0; }
.tut-brand picture.built-on img, .onboard-brand picture.built-on img { display: block; width: 130px; height: auto; opacity: 0.85; }
.tut-mid { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; }
.tut-dots { display: flex; align-items: center; gap: 7px; margin-bottom: 18px; }
.tut-dot { width: 6px; height: 6px; border-radius: var(--radius-full); background: var(--text-tertiary); opacity: 0.55; transition: width 250ms var(--ease-out), background-color 250ms ease, opacity 250ms ease; }
.tut-dot.active { width: 22px; background: var(--brand-primary); opacity: 1; }
/* FIXED 94px slot = tallest graphic, so dots/title/body sit at identical y on every page. */
.tut-art { height: 94px; display: flex; align-items: center; justify-content: center; margin-bottom: 18px; }
.tut-chart { width: 200px; height: auto; }
.tut-pools { display: flex; align-items: center; gap: 16px; }
.onb-screen .pool { border-radius: var(--radius-full); display: flex; align-items: center; justify-content: center; font-weight: 800; }
.onb-screen .pool.lose { width: 72px; height: 72px; font-size: 12px; letter-spacing: -0.1px; background: linear-gradient(180deg, #232E4A 0%, #1C2642 100%); border: 1px solid var(--border-default); color: #fff; }
.onb-screen .pool.win { width: 72px; height: 72px; font-size: 12px; letter-spacing: -0.2px; color: #fff; background: linear-gradient(180deg, #27BC81 0%, #19AD6A 100%); box-shadow: 0 0 22px rgba(39, 188, 129, 0.25); }
.onb-screen .pool-flow { display: flex; align-items: center; color: #fff; }
.pool-flow svg { width: 22px; height: 22px; }
.tut-podium { display: flex; align-items: flex-end; gap: 6px; }
.tp-col { width: 48px; border-radius: 8px 8px 3px 3px; display: flex; align-items: flex-start; justify-content: center; padding-top: 10px; font-size: 15px; font-weight: 800; color: #fff; }
.tp-col.first { height: 92px; background: linear-gradient(180deg, #27BC81 0%, #19AD6A 100%); box-shadow: 0 0 22px rgba(39, 188, 129, 0.25); }
.tp-col.second, .tp-col.third { background: linear-gradient(180deg, #232E4A 0%, #1C2642 100%); border: 1px solid var(--border-default); color: var(--text-secondary); }
.tp-col.second { height: 66px; }
.tp-col.third { height: 52px; }
.tut-bubbles { position: relative; width: 128px; height: 94px; }
.tb-bubble { position: absolute; display: flex; flex-direction: column; justify-content: center; gap: 7px; padding: 0 14px; width: 90px; height: 54px; }
.tb-bubble.back { top: 0; left: 0; background: var(--bg-surface-elevated); border: 1px solid var(--border-default); border-radius: 16px 16px 16px 3px; }
.tb-bubble.front { bottom: 0; right: 0; background: linear-gradient(180deg, #27BC81 0%, #1EA873 100%); border-radius: 16px 16px 3px 16px; box-shadow: 0 6px 18px rgba(39, 188, 129, 0.25); z-index: 2; }
.tb-line { display: block; height: 5px; width: 100%; border-radius: var(--radius-full); background: var(--text-tertiary); opacity: 0.75; }
.tb-line.short { width: 62%; }
.tb-bubble.front .tb-line { background: #fff; opacity: 0.92; }
.tut-title { font-size: 23px; font-weight: 800; letter-spacing: -0.5px; line-height: 1.22; color: var(--text-primary); max-width: 300px; margin-bottom: 12px; }
.tut-body { font-size: 14px; font-weight: 500; line-height: 1.55; color: var(--text-secondary); max-width: 350px; margin-bottom: 32px; min-height: 44px; }
.tut-cta { display: inline-flex; align-items: center; justify-content: center; width: 100%; max-width: 320px; height: 48px; border: none; border-radius: var(--radius-md); background: var(--brand-primary); color: #fff; font-family: inherit; font-size: 14.5px; font-weight: 800; letter-spacing: -0.2px; cursor: pointer; text-decoration: none; box-shadow: 0 4px 14px rgba(39, 188, 129, 0.32); transition: filter 150ms ease, transform 150ms ease; }
.tut-cta:hover { filter: brightness(1.06); }
.tut-cta:active { transform: scale(0.98); }
.tut-skip { margin-top: 16px; border: none; background: none; color: var(--text-secondary); font-family: inherit; font-size: 13px; font-weight: 600; letter-spacing: -0.1px; cursor: pointer; padding: 4px 8px; text-decoration: none; transition: color 150ms ease; }
.tut-skip:hover { color: var(--text-primary); }

/* ─── Login 1 (mock login1.html) ─────────────────────────────────── */
.login-close { position: absolute; top: calc(env(safe-area-inset-top, 0px) + 12px); right: 10px; z-index: 3; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border: none; background: transparent; border-radius: var(--radius-full); color: var(--text-primary); cursor: pointer; transition: background-color 150ms ease, transform 150ms ease; }
.login-close:hover { background: var(--bg-surface-hover); }
.login-close:active { transform: scale(0.96); }
.login-close svg { transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1); }
.login-close:hover svg { transform: rotate(90deg); }
.onboard { position: relative; z-index: 1; flex: 1; min-height: 0; display: flex; flex-direction: column; padding: calc(env(safe-area-inset-top, 0px) + 24px) 20px calc(env(safe-area-inset-bottom, 0px) + 20px); }
.onboard-bottom { margin-top: auto; padding-top: 18vh; display: flex; flex-direction: column; gap: 12px; }
.hero-carousel { position: relative; height: 44px; overflow: hidden; text-align: center; margin-bottom: 2px; }
.hero-carousel .hi { color: var(--brand-primary); }
.hero-carousel > span { position: absolute; inset: 0; display: block; line-height: 44px; text-align: center; font-size: 32px; font-weight: 800; letter-spacing: -0.8px; color: var(--text-primary); opacity: 0; animation: heroRotate 8s cubic-bezier(0.4, 0, 0.2, 1) infinite; white-space: nowrap; }
.hero-carousel > span:nth-child(1) { animation-delay: 0s; }
.hero-carousel > span:nth-child(2) { animation-delay: 2s; }
.hero-carousel > span:nth-child(3) { animation-delay: 4s; }
.hero-carousel > span:nth-child(4) { animation-delay: 6s; }
@keyframes heroRotate { 0%, 2.25% { opacity: 0; transform: translateY(8px); } 6%, 22.5% { opacity: 1; transform: translateY(0); } 26.25%, 100% { opacity: 0; transform: translateY(-8px); } }
.hero-sub { margin: 0 0 14px; text-align: center; font-size: 14.5px; font-weight: 500; color: var(--text-secondary); letter-spacing: -0.1px; line-height: 1.4; }
.onboard .cta { display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%; height: 52px; padding: 0 20px; border-radius: var(--radius-md); border: none; cursor: pointer; font-family: inherit; font-size: 15px; font-weight: 800; letter-spacing: -0.2px; transition: filter 150ms ease, transform 150ms ease, background-color 150ms ease, border-color 150ms ease; }
.onboard .cta.primary { background: var(--brand-primary); color: #fff; box-shadow: 0 4px 14px rgba(39, 188, 129, 0.32); }
.onboard .cta.primary:hover { filter: brightness(1.06); }
.onboard .cta.primary:active { transform: scale(0.98); }
.onboard .cta.ghost { background: transparent; color: var(--text-secondary); border: none; height: auto; padding: 4px 8px; font-size: 13px; font-weight: 600; letter-spacing: -0.1px; box-shadow: none; }
.onboard .cta.ghost:hover { background: transparent; color: var(--text-primary); }
.onboard .cta.ghost:active { transform: scale(0.98); }
.onb-screen .sol-glyph { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; background: linear-gradient(135deg, #9945FF 0%, #14F195 100%); color: #fff; flex-shrink: 0; }
.onb-screen .sol-glyph svg { width: 12px; height: 12px; display: block; }
.onb-screen .legal { margin: 4px 0 0; text-align: center; font-size: 12px; font-weight: 500; color: var(--text-tertiary); letter-spacing: -0.1px; line-height: 1.4; }
.onb-screen .legal a { color: var(--text-secondary); text-decoration: none; }
.onb-screen .legal a:hover { color: var(--text-primary); }
/* ─── Login 2 sheet (mock login2.html; no email row — spec D1) ──── */
.onb-sheet { position: absolute; inset: 0; z-index: 10; }
.onb-sheet-overlay { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.7); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); animation: onbOverlayIn 220ms ease-out; }
@keyframes onbOverlayIn { from { opacity: 0; } to { opacity: 1; } }
.onb-modal { position: absolute; left: 0; right: 0; bottom: 0; background: var(--bg-surface); border-top: 1px solid var(--border-subtle); border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding: 10px 20px calc(20px + env(safe-area-inset-bottom)); display: flex; flex-direction: column; gap: 12px; box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.5); animation: onbSheetUp 300ms cubic-bezier(0.4, 0, 0.2, 1); touch-action: none; }
@keyframes onbSheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.onb-modal .sheet-grab { width: 36px; height: 4px; border-radius: var(--radius-full); background: var(--border-default); margin: 2px auto 4px; flex-shrink: 0; }
.onb-modal .ls-oauth-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.onb-modal .ls-oauth { display: inline-flex; align-items: center; justify-content: center; height: 44px; border-radius: var(--radius-full); background: var(--bg-surface-elevated); border: 1px solid var(--border-subtle); cursor: pointer; transition: background-color 150ms ease, border-color 150ms ease, transform 150ms ease; }
.onb-modal .ls-oauth:hover { background: var(--bg-surface-hover); border-color: var(--border-default); }
.onb-modal .ls-oauth:active { transform: scale(0.97); }
.onb-modal .ls-oauth.google svg { width: 20px; height: 20px; display: block; }
.onb-modal .ls-oauth.x svg { width: 18px; height: 18px; display: block; color: #fff; }
.onb-modal .ls-cta { display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%; height: 48px; padding: 0 18px; border-radius: var(--radius-md); border: none; cursor: pointer; font-family: inherit; font-size: 14.5px; font-weight: 800; letter-spacing: -0.2px; color: #fff; transition: filter 150ms ease, transform 150ms ease; }
.onb-modal .ls-cta.seeker { background: var(--brand-primary); box-shadow: 0 4px 14px rgba(39, 188, 129, 0.32); }
.onb-modal .ls-cta.wallet { background: var(--bg-surface-elevated); color: var(--text-primary); border: 1px solid var(--border-subtle); box-shadow: none; }
.onb-modal .ls-cta.wallet:hover { background: var(--bg-surface-hover); border-color: var(--border-default); filter: none; }
.onb-modal .ls-cta:hover { filter: brightness(1.06); }
.onb-modal .ls-cta:active { transform: scale(0.98); }
.onb-modal .ls-cta svg { width: 16px; height: 16px; display: block; }
.onb-modal .ls-cancel { display: block; margin: 4px auto 0; border: none; background: none; color: var(--text-secondary); font-family: inherit; font-size: 13px; font-weight: 600; letter-spacing: -0.1px; cursor: pointer; padding: 4px 8px; transition: color 150ms ease; }
.onb-modal .ls-cancel:hover { color: var(--text-primary); }
