/* ============================================================ Trump Alpha — Design System ============================================================ */ :root { /* Surfaces — warm off-whites */ --bg: oklch(99% 0.004 85); --bg-sunk: oklch(97.8% 0.006 85); --bg-elev: #ffffff; --surface: #ffffff; --surface-2: oklch(97.2% 0.006 85); --surface-3: oklch(94% 0.008 85); /* Text */ --ink: oklch(18% 0.008 85); --ink-2: oklch(38% 0.008 85); --ink-3: oklch(55% 0.008 85); --ink-4: oklch(70% 0.006 85); /* Borders */ --line: oklch(93% 0.008 85); --line-2: oklch(88% 0.01 85); /* Amber accent */ --amber: oklch(78% 0.17 75); --amber-ink: oklch(45% 0.16 70); --amber-soft: oklch(96% 0.05 85); --amber-ring: oklch(88% 0.12 80); /* Signal colors */ --up: oklch(62% 0.17 148); --up-soft: oklch(95% 0.05 148); --down: oklch(58% 0.22 25); --down-soft: oklch(95% 0.05 25); --violet: oklch(55% 0.17 280); --violet-soft: oklch(96% 0.04 280); /* Radii */ --r-xs: 8px; --r-sm: 10px; --r-md: 14px; --r-lg: 20px; --r-xl: 28px; --r-pill: 999px; /* Shadow */ --shadow-1: 0 1px 2px rgba(20, 18, 14, 0.04), 0 1px 1px rgba(20, 18, 14, 0.02); --shadow-2: 0 4px 16px rgba(20, 18, 14, 0.06), 0 1px 2px rgba(20, 18, 14, 0.03); --shadow-3: 0 12px 40px rgba(20, 18, 14, 0.08), 0 2px 4px rgba(20, 18, 14, 0.04); --sans: 'Geist', ui-sans-serif, system-ui, -apple-system, 'Helvetica Neue', sans-serif; --mono: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace; } html[data-theme="dark"] { --bg: oklch(15% 0.008 85); --bg-sunk: oklch(12% 0.008 85); --bg-elev: oklch(20% 0.008 85); --surface: oklch(18% 0.008 85); --surface-2: oklch(21% 0.008 85); --surface-3: oklch(25% 0.01 85); --ink: oklch(97% 0.005 85); --ink-2: oklch(82% 0.006 85); --ink-3: oklch(62% 0.006 85); --ink-4: oklch(45% 0.006 85); --line: oklch(24% 0.008 85); --line-2: oklch(30% 0.01 85); --amber: oklch(78% 0.17 75); --amber-ink: oklch(82% 0.16 75); --amber-soft: oklch(25% 0.05 75); --amber-ring: oklch(38% 0.12 75); --up: oklch(70% 0.18 148); --up-soft: oklch(24% 0.06 148); --down: oklch(68% 0.22 25); --down-soft: oklch(24% 0.08 25); --violet: oklch(70% 0.17 280); --violet-soft: oklch(24% 0.06 280); --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3); --shadow-2: 0 4px 16px rgba(0, 0, 0, 0.35); --shadow-3: 0 12px 40px rgba(0, 0, 0, 0.5); color-scheme: dark; } html[data-theme="dark"] .src-ico.x { background: oklch(92% 0.005 85); color: oklch(15% 0.008 85); } html[data-theme="dark"] .bot-status { background: linear-gradient(160deg, oklch(28% 0.015 85) 0%, oklch(20% 0.01 85) 100%); border: 1px solid oklch(30% 0.01 85); } html[data-theme="dark"] .kpi.accent { background: linear-gradient(135deg, oklch(28% 0.05 75), oklch(24% 0.07 70)); } /* Dashboard Performance card uses the same "amber accent" treatment as .kpi.accent — without a dark-mode override the cream background floats on the dark grid as a glaring out-of-theme block. Mirror the kpi dark gradient so the card stays visually grouped with everything else. */ html[data-theme="dark"] .overview-stat-card.accent { background: linear-gradient(135deg, oklch(28% 0.05 75), oklch(24% 0.07 70)); border-color: color-mix(in oklab, var(--amber) 28%, var(--line)); } html[data-theme="dark"] .landing-nav { background: oklch(15% 0.008 85 / 0.8); } html[data-theme="dark"] .src-ico.truth { background: oklch(30% 0.08 25); color: oklch(80% 0.15 25); } html[data-theme="dark"] .post-row.selected { background: oklch(22% 0.03 75); } html, body { margin: 0; padding: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-feature-settings: 'ss01', 'cv11'; transition: background 200ms, color 200ms; } * { box-sizing: border-box; } button { font-family: inherit; cursor: pointer; border: 0; background: transparent; color: inherit; } input, textarea { font-family: inherit; } a { color: inherit; text-decoration: none; } .mono { font-family: var(--mono); font-feature-settings: 'tnum', 'zero'; } .tnum { font-variant-numeric: tabular-nums; } /* ============================================================ App scaffold ============================================================ */ .app { min-height: 100vh; display: flex; flex-direction: column; } /* ---------- Top navbar ---------- */ .nav { height: 64px; padding: 0 28px; display: flex; align-items: center; gap: 32px; background: var(--bg); border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 40; } .wallet-anchor { position: relative; display: flex; align-items: center; } .wallet-connect-error { position: absolute; right: 0; top: calc(100% + 10px); margin: 0; width: min(320px, calc(100vw - 28px)); padding: 10px 12px; border-radius: 10px; border: 1px solid color-mix(in oklab, var(--down) 24%, var(--line)); background: color-mix(in oklab, var(--down-soft) 72%, var(--surface)); color: var(--down); box-shadow: var(--shadow-2); font-size: 12px; line-height: 1.45; z-index: 50; transform-origin: top right; animation: walletErrorIn 160ms ease-out; } .wallet-connect-error::before { content: ''; position: absolute; right: 26px; top: -7px; width: 12px; height: 12px; background: inherit; border-left: 1px solid color-mix(in oklab, var(--down) 24%, var(--line)); border-top: 1px solid color-mix(in oklab, var(--down) 24%, var(--line)); transform: rotate(45deg); } @keyframes walletErrorIn { from { opacity: 0; transform: translateY(-6px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } } .brand { display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 15px; letter-spacing: -0.01em; } .brand-mark { width: 28px; height: 28px; border-radius: 8px; background: var(--ink); color: var(--bg); display: grid; place-items: center; font-family: var(--mono); font-size: 15px; font-weight: 500; position: relative; } .brand-mark::after { content: ''; position: absolute; right: -3px; bottom: -3px; width: 10px; height: 10px; border-radius: 999px; background: var(--amber); border: 2px solid var(--bg); } .nav-tabs { display: flex; align-items: center; gap: 4px; padding: 4px; background: var(--bg-sunk); border: 1px solid var(--line); border-radius: var(--r-pill); } .nav-tab { padding: 7px 14px; border-radius: var(--r-pill); font-size: 13px; font-weight: 500; color: var(--ink-3); transition: color 120ms, background 120ms; } .nav-tab:hover { color: var(--ink); } .nav-tab.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-1); } .nav-spacer { flex: 1; } .nav-right { display: flex; align-items: center; gap: 10px; } .icon-btn { width: 36px; height: 36px; border-radius: var(--r-pill); background: var(--bg-sunk); border: 1px solid var(--line); display: grid; place-items: center; color: var(--ink-2); transition: background 120ms, color 120ms; } .icon-btn:hover { background: var(--surface-3); color: var(--ink); } .connect-btn { padding: 12px 22px; border-radius: var(--r-pill); background: var(--ink); color: var(--bg); font-size: 14px; font-weight: 600; letter-spacing: -0.005em; transition: background 120ms, transform 120ms, box-shadow 120ms; box-shadow: var(--shadow-1); } .connect-btn:hover { background: oklch(30% 0.01 85); box-shadow: var(--shadow-2); } .connect-btn:active { transform: scale(0.98); } .connect-btn.lg { padding: 13px 26px; font-size: 14px; } html[data-theme="dark"] .connect-btn { background: var(--amber); color: oklch(20% 0.04 75); } html[data-theme="dark"] .connect-btn:hover { background: oklch(82% 0.17 75); } .theme-toggle { width: 40px; height: 40px; } html[data-theme="dark"] .icon-btn { background: var(--surface-2); border-color: var(--line); } html[data-theme="dark"] .icon-btn:hover { background: var(--surface-3); } html[data-theme="dark"] .nav-tab.active { background: var(--surface-2); } html[data-theme="dark"] .asset-switch button.on { background: var(--surface-2); } .wallet-chip { display: flex; align-items: center; gap: 8px; padding: 6px 12px 6px 6px; border-radius: var(--r-pill); background: var(--bg-sunk); border: 1px solid var(--line); font-size: 13px; } .wallet-chip .ava { width: 24px; height: 24px; border-radius: 999px; background: linear-gradient(135deg, var(--amber), oklch(65% 0.2 35)); } .wallet-menu { display: none; position: absolute; right: 0; top: calc(100% + 6px); min-width: 180px; padding: 6px; z-index: 1000; background: var(--bg-elev); border: 1px solid var(--line); border-radius: var(--r-sm); box-shadow: var(--shadow-2); } .wallet-menu.open { display: block; } .wallet-menu button { width: 100%; padding: 8px 10px; font-size: 13px; text-align: left; border-radius: 6px; color: var(--ink); } .wallet-menu button:hover { background: var(--bg-sunk); } .wallet-menu button.danger { color: var(--down); } /* ============================================================ Page shell ============================================================ */ .page { max-width: 1360px; margin: 0 auto; padding: 32px 28px 80px; width: 100%; } .page.wide { max-width: 1600px; } .page-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: 28px; gap: 24px; } .page-title { font-size: 34px; letter-spacing: -0.02em; font-weight: 600; line-height: 1.05; margin: 0; } .page-sub { color: var(--ink-3); font-size: 14px; margin-top: 6px; margin-bottom: 0; } /* PageHint — the prominent "what is this page" tagline directly under .page-title. Stronger contrast + bigger than .page-sub so it actually gets read (page-sub was so faint it functioned as decoration). Use via One sentence about the page.. */ .page-hint { color: var(--ink-2); font-size: 16px; line-height: 1.5; margin: 10px 0 0; max-width: 64ch; } .page-hint-count { color: var(--ink-4); font-size: 13px; margin-left: 10px; padding-left: 10px; border-left: 1px solid var(--line); } /* SectionHint — always-visible explanation block. Pairs with a section/tab to tell the user "what does this view actually do" in 1–3 sentences. More detailed than PageHint, less detail-y than an InfoTip. Spans the full content width on purpose — narrow boxes inside a wide page looked like accidentally-floating callouts. */ .section-hint { background: var(--bg-sunk); border: 1px solid var(--line); border-radius: 8px; padding: 12px 16px; margin-bottom: 14px; color: var(--ink-2); font-size: 14px; line-height: 1.55; } .section-hint strong { color: var(--ink); font-weight: 600; } /* InfoTip — small "?" pill that reveals a one-line tooltip on hover/focus. No JS, pure CSS. Pattern mimics the (i) dots in Linear/Hyperliquid: subtle until needed, never blocks the underlying content. */ .infotip { position: relative; display: inline-flex; align-items: center; justify-content: center; vertical-align: middle; margin-left: 6px; cursor: help; outline: none; /* The icon should sit on the text baseline without nudging line-height. */ line-height: 1; } .infotip-icon { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; border-radius: 50%; background: var(--bg-sunk); color: var(--ink-3); font-size: 10px; font-weight: 700; border: 1px solid var(--line); transition: background 0.12s, color 0.12s, border-color 0.12s; user-select: none; } .infotip:hover .infotip-icon, .infotip:focus-visible .infotip-icon { background: var(--ink); color: var(--bg); border-color: var(--ink); } .infotip-bubble { position: absolute; z-index: 50; width: var(--tip-w, 240px); padding: 8px 10px; /* Always-dark bubble — common pattern (Linear/Stripe/GitHub) — but needs a visible border in dark mode so it doesn't blend into the page bg. */ background: #0f0d0a; color: #f5f2ea; border: 1px solid transparent; border-radius: 6px; font-size: 12px; font-weight: 400; line-height: 1.5; letter-spacing: 0; text-transform: none; text-align: left; box-shadow: 0 6px 24px rgba(0,0,0,0.25), 0 1px 2px rgba(0,0,0,0.2); pointer-events: none; opacity: 0; transform: translateY(2px); transition: opacity 0.12s, transform 0.12s; white-space: normal; } /* Dark mode: page bg is ~oklch(15%), bubble is #0f0d0a — visually identical. Lighten the bubble slightly and add a 1px ring so the shape stays defined. */ html[data-theme="dark"] .infotip-bubble { background: oklch(28% 0.008 85); border-color: oklch(38% 0.01 85); box-shadow: 0 6px 24px rgba(0,0,0,0.6), 0 1px 2px rgba(0,0,0,0.4); } /* MacroPanel cell — subtle hover so the grid feels alive without becoming a giant heat-map of click affordances. Just a tiny background lift. */ .macro-cell:hover { background: var(--bg-sunk) !important; } .macro-panel { padding: 0; margin-bottom: 12px; overflow: hidden; } .macro-panel-head { padding: 20px 22px 18px; border-bottom: 1px solid var(--line); display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; } .macro-panel-title { display: flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 700; } .macro-panel-dot { width: 7px; height: 7px; border-radius: 999px; background: var(--up); display: inline-block; } .macro-panel-subtitle { margin-top: 6px; font-size: 12px; line-height: 1.45; color: var(--ink-3); } .macro-panel-meta { text-align: right; font-size: 11px; line-height: 1.45; color: var(--ink-4); flex-shrink: 0; } .macro-section { border-top: 1px solid var(--line); } .macro-section-title { display: flex; align-items: center; gap: 10px; padding: 14px 22px 12px; /* Was 10px / ink-3 / weight 700 — too quiet, users couldn't see the section structure. Bumped to 12px / ink-2 / weight 800. Still uppercase + tracked so it reads as a label, not a heading that competes with the metric values. */ font-size: 12px; color: var(--ink-2); letter-spacing: 0.10em; text-transform: uppercase; font-weight: 800; background: var(--bg-sunk); border-bottom: 1px solid var(--line); } /* Tiny dot anchor on the left — visual signal that "this is a section header" without using a heavy colored bar. */ .macro-section-title::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--ink-3); flex-shrink: 0; } .macro-grid { display: grid; gap: 14px; padding: 14px; } .macro-grid.one { grid-template-columns: minmax(0, 1fr); } .macro-grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); } .macro-metric-card, .macro-guide-card { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 18px; min-width: 0; min-height: 248px; display: flex; flex-direction: column; } .macro-metric-card { box-shadow: var(--shadow-1); } .macro-metric-card.tone-up { border-color: color-mix(in oklab, var(--up) 28%, var(--line)); } .macro-metric-card.tone-down { border-color: color-mix(in oklab, var(--down) 28%, var(--line)); } /* Stat card layout — label STACKED ABOVE the big number, not side-by-side. Previous side-by-side layout pushed the title to the far left and the value to the far right with too much air between them on wide screens. The eye now reads top→bottom: label → value → summary → chips → button. */ .macro-metric-head { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; } .macro-metric-title { display: flex; align-items: center; gap: 8px; min-width: 0; /* Slightly larger + bolder so "AHR999" doesn't disappear next to the big number below. Treated as a label, not a heading. */ font-size: 15px; font-weight: 650; color: var(--ink-2); } .macro-rank { font-size: 11px; color: var(--ink-4); letter-spacing: 0.08em; font-weight: 700; flex-shrink: 0; } .macro-metric-value { /* Same size as before but sits directly under the label now, so the eye-distance between "AHR999" and "0.4663" is ~6px instead of the full card width. */ font-size: 34px; line-height: 1; letter-spacing: -0.03em; font-weight: 800; color: var(--ink); text-align: left; flex-shrink: 0; } .macro-guide-title { font-size: 20px; line-height: 1.15; letter-spacing: -0.02em; font-weight: 700; color: var(--ink); } .macro-summary { margin-top: 12px; font-size: 14px; line-height: 1.55; color: var(--ink-2); min-height: 66px; } .macro-thresholds { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; } /* THRESHOLD CHIPS — "you are here" treatment ───────────────────────────────────────────────────────── Design goal: the chip that the CURRENT value falls into must be the single most-eye-catching element in the cell. Everything else fades back. Two states: base (inactive) — flat, outlined, muted gray. Tone is suppressed so a "down (red)" inactive chip doesn't visually outshout an active "neutral" chip. Stripping tone here is intentional. .active — filled pill with the tone colour, larger, raised on shadow, scale 1.05. The eye can't miss it. Hover the row → all chips bump to 0.8 opacity so you can read the other bands' rules without losing the active one. */ .macro-threshold-chip { display: inline-flex; align-items: center; min-height: 28px; padding: 5px 12px; border-radius: 999px; border: 1px solid var(--line); background: transparent; font-size: 11.5px; line-height: 1.35; color: var(--ink-4); font-weight: 500; opacity: 0.45; transition: opacity 160ms, transform 180ms cubic-bezier(.2,.8,.2,1), box-shadow 180ms, background 180ms, color 180ms; } .macro-thresholds:hover .macro-threshold-chip { opacity: 0.8; } /* When INACTIVE, suppress tone colors. They'd compete with the active chip for attention. Tone returns the moment the chip becomes .active below. */ .macro-threshold-chip:not(.active) { color: var(--ink-4) !important; background: transparent !important; border-color: var(--line) !important; } /* ACTIVE — the band the current value falls into. */ .macro-threshold-chip.active { opacity: 1; font-weight: 700; font-size: 12px; padding: 6px 14px; transform: scale(1.06); letter-spacing: 0.01em; } .macro-threshold-chip.up.active { background: var(--up); color: #fff; border-color: var(--up); box-shadow: 0 6px 18px color-mix(in oklab, var(--up) 35%, transparent), 0 1px 0 rgba(255,255,255,0.25) inset; } .macro-threshold-chip.down.active { background: var(--down); color: #fff; border-color: var(--down); box-shadow: 0 6px 18px color-mix(in oklab, var(--down) 35%, transparent), 0 1px 0 rgba(255,255,255,0.25) inset; } .macro-threshold-chip.neutral.active { /* Amber = "caution" signal — between safe and danger. Lets the user know "you are here, no extreme yet" without the alarming red. */ background: var(--amber); color: oklch(20% 0.04 75); border-color: var(--amber); box-shadow: 0 6px 18px color-mix(in oklab, var(--amber) 35%, transparent), 0 1px 0 rgba(255,255,255,0.4) inset; } /* Dark mode tweaks — the soft white-shimmer inset doesn't read on dark cards, so swap to a subtle darker outline. */ html[data-theme="dark"] .macro-threshold-chip.up.active, html[data-theme="dark"] .macro-threshold-chip.down.active, html[data-theme="dark"] .macro-threshold-chip.neutral.active { box-shadow: 0 8px 24px color-mix(in oklab, currentColor 30%, transparent), 0 0 0 1px rgba(0,0,0,0.25) inset; } /* Section variants — reference cards (rules-only, no live number) get a muted treatment so users instantly see they're explanatory, not live. We REPLACE the dot anchor with a 📐 emoji (overriding the .macro-section- title::before above) and dim the text color. */ .macro-section.reference .macro-section-title { color: var(--ink-3); } .macro-section.reference .macro-section-title::before { content: '📐'; width: auto; height: auto; background: none; border-radius: 0; font-size: 13px; line-height: 1; filter: grayscale(0.3); } .macro-guide-card { background: color-mix(in oklab, var(--bg-sunk) 60%, var(--surface)); border-style: dashed; } .macro-guide-card .macro-guide-title::before { content: 'RULES '; font-size: 9px; font-weight: 800; letter-spacing: 0.12em; padding: 2px 6px; border-radius: 4px; background: color-mix(in oklab, var(--ink) 8%, transparent); color: var(--ink-3); margin-right: 8px; vertical-align: middle; } /* Action row — single small button, aligned to the bottom-right of the card. Was previously a full-width dual-button group; pinning a compact button to the corner keeps the card's eye-flow on the value + thresholds, with the "go look at history" affordance present but quiet. */ .macro-actions { display: flex; justify-content: flex-end; margin-top: auto; padding-top: 14px; } .macro-action-btn { display: inline-flex; align-items: center; gap: 6px; /* Compact natural width — fits "Open chart CoinGlass ↗" comfortably */ padding: 7px 12px; border-radius: 8px; border: 1px solid var(--line); background: color-mix(in oklab, var(--ink) 4%, var(--surface)); color: var(--ink); text-decoration: none; transition: background 120ms, border-color 120ms, transform 120ms, box-shadow 120ms; box-shadow: inset 0 1px 0 rgba(255,255,255,0.4); } .macro-action-btn:hover { background: color-mix(in oklab, var(--ink) 7%, var(--surface)); border-color: color-mix(in oklab, var(--ink) 12%, var(--line)); transform: translateY(-1px); box-shadow: var(--shadow-1); } .macro-action-btn.chart { background: color-mix(in oklab, var(--amber) 10%, var(--surface)); border-color: color-mix(in oklab, var(--amber) 18%, var(--line)); } /* The kicker ("OPEN CHART" uppercase eyebrow) used to sit ABOVE the label in a 2-row layout. With the new compact button it lives inline next to the label as a tiny prefix tag — same words, less vertical space. */ .macro-action-copy { display: inline-flex; align-items: baseline; gap: 8px; min-width: 0; } .macro-action-kicker { font-size: 9.5px; line-height: 1; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-4); font-weight: 700; } .macro-action-label { font-size: 13px; line-height: 1; color: var(--ink); font-weight: 600; white-space: nowrap; } .macro-action-arrow { font-size: 13px; line-height: 1; color: var(--ink-3); flex-shrink: 0; } .macro-disclosure { margin-top: 14px; border-top: 1px dashed var(--line); padding-top: 12px; } .macro-disclosure summary { list-style: none; cursor: pointer; font-size: 12px; font-weight: 600; color: var(--ink-2); } .macro-disclosure summary::-webkit-details-marker { display: none; } .macro-disclosure-body { margin-top: 8px; font-size: 12px; line-height: 1.55; color: var(--ink-3); } .macro-composite { border-top: 1px solid var(--line); padding: 20px 22px 22px; background: var(--bg-sunk); } .macro-composite-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 14px; } .macro-composite-label { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); font-weight: 700; } .macro-composite-right { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; } .macro-composite-value { font-size: 32px; line-height: 0.95; font-weight: 800; letter-spacing: -0.03em; } .macro-regime-pill { display: inline-flex; align-items: center; min-height: 28px; padding: 0 10px; border-radius: 999px; border: 1px solid var(--line); font-size: 11px; font-weight: 700; letter-spacing: 0.06em; } .macro-composite-track { position: relative; height: 18px; overflow: hidden; border-radius: 999px; border: 1px solid color-mix(in oklab, var(--line) 78%, transparent); box-shadow: inset 0 1px 2px rgba(0,0,0,0.08); } .macro-composite-track::after { content: ''; position: absolute; top: 2px; bottom: 2px; left: 50%; width: 1px; background: color-mix(in oklab, var(--ink) 14%, transparent); transform: translateX(-50%); } .macro-composite-needle { position: absolute; top: 50%; width: 24px; height: 24px; border-radius: 50%; border: 3px solid var(--ink); background: var(--surface); box-shadow: var(--shadow-2); transform: translateY(-50%); transition: left 0.4s cubic-bezier(.2,.8,.2,1); /* React re-mounts this element via `key={composite_score}` whenever the score changes, which re-triggers the pulse animation below — a brief attention cue for users tracking how the macro tilt shifts day to day. */ animation: macro-needle-pulse 0.9s ease-out 1; } @keyframes macro-needle-pulse { 0% { transform: translateY(-50%) scale(0.85); box-shadow: 0 0 0 0 currentColor; } 40% { transform: translateY(-50%) scale(1.18); box-shadow: 0 0 0 8px color-mix(in oklab, currentColor 18%, transparent); } 100% { transform: translateY(-50%) scale(1); box-shadow: var(--shadow-2); } } .macro-composite-scale { display: flex; justify-content: space-between; gap: 8px; margin-top: 8px; font-size: 10px; letter-spacing: 0.04em; color: var(--ink-4); text-transform: uppercase; } .infotip:hover .infotip-bubble, .infotip:focus-visible .infotip-bubble { opacity: 1; transform: translateY(0); } /* Placement variants (default = top) */ .infotip-top .infotip-bubble { bottom: calc(100% + 8px); left: 50%; transform: translate(-50%, 2px); } .infotip-top:hover .infotip-bubble, .infotip-top:focus-visible .infotip-bubble { transform: translate(-50%, 0); } .infotip-bottom .infotip-bubble { top: calc(100% + 8px); left: 50%; transform: translate(-50%, -2px); } .infotip-bottom:hover .infotip-bubble, .infotip-bottom:focus-visible .infotip-bubble { transform: translate(-50%, 0); } .infotip-left .infotip-bubble { right: calc(100% + 8px); top: 50%; transform: translate(2px, -50%); } .infotip-left:hover .infotip-bubble, .infotip-left:focus-visible .infotip-bubble { transform: translate(0, -50%); } .infotip-right .infotip-bubble { left: calc(100% + 8px); top: 50%; transform: translate(-2px, -50%); } .infotip-right:hover .infotip-bubble, .infotip-right:focus-visible .infotip-bubble { transform: translate(0, -50%); } /* ============================================================ Cards + primitives ============================================================ */ .card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: 20px; } .card.flush { padding: 0; } .card.soft { background: var(--bg-sunk); } .card.raise { box-shadow: var(--shadow-1); } .section-title { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .section-title h2 { margin: 0; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; } .section-title .hint { font-size: 12px; color: var(--ink-3); } .chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: var(--r-pill); background: var(--bg-sunk); border: 1px solid var(--line); font-size: 12px; color: var(--ink-2); font-weight: 500; } .chip .dot { width: 6px; height: 6px; border-radius: 999px; background: currentColor; } .chip.up { color: oklch(40% 0.16 148); background: var(--up-soft); border-color: oklch(85% 0.08 148); } .chip.down { color: oklch(44% 0.2 25); background: var(--down-soft); border-color: oklch(87% 0.08 25); } .chip.amber { color: var(--amber-ink); background: var(--amber-soft); border-color: var(--amber-ring); } .chip.violet { color: oklch(38% 0.15 280); background: var(--violet-soft); border-color: oklch(86% 0.08 280); } .chip.neutral { color: var(--ink-2); } .live-dot { width: 6px; height: 6px; border-radius: 999px; background: var(--up); position: relative; display: inline-block; } .live-dot::after { content: ''; position: absolute; inset: -4px; border-radius: 999px; background: var(--up); opacity: 0.3; animation: pulse 1.6s ease-out infinite; } @keyframes pulse { 0% { transform: scale(0.6); opacity: 0.5; } 100% { transform: scale(2.2); opacity: 0; } } .btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 10px 16px; border-radius: var(--r-pill); font-size: 13px; font-weight: 500; transition: background 120ms, transform 120ms; border: 1px solid transparent; } .btn.primary { background: var(--ink); color: var(--bg); } .btn.primary:hover { background: oklch(30% 0.01 85); } .btn.amber { background: var(--amber); color: oklch(22% 0.04 75); font-weight: 600; } .btn.amber:hover { background: oklch(82% 0.17 75); } .btn.ghost { background: var(--bg-sunk); color: var(--ink); border-color: var(--line); } .btn.ghost:hover { background: var(--surface-3); } .btn.lg { padding: 14px 22px; font-size: 15px; } .btn:active { transform: scale(0.98); } .delta { font-family: var(--mono); font-weight: 500; } .delta.up { color: oklch(42% 0.16 148); } .delta.down { color: oklch(46% 0.2 25); } /* ── iOS-style toggle switch ──────────────────────────────── */ .switch { position: relative; display: inline-block; width: 34px; height: 20px; flex-shrink: 0; } .switch input { opacity: 0; width: 0; height: 0; } .switch-track { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background: var(--line-2); border-radius: 999px; transition: background 160ms; } .switch-track::before { content: ''; position: absolute; height: 16px; width: 16px; left: 2px; top: 2px; background: #fff; border-radius: 50%; transition: transform 160ms; box-shadow: 0 1px 2px rgba(0,0,0,0.15); } .switch input:checked + .switch-track { background: var(--amber); } .switch input:checked + .switch-track::before { transform: translateX(14px); } .switch.up input:checked + .switch-track { background: var(--up); } .switch.down input:checked + .switch-track { background: var(--down); } /* ── Form row: label | control, strict-aligned ─────────────── */ .form-row { display: grid; grid-template-columns: minmax(220px, 260px) minmax(0, 1fr); align-items: start; gap: 24px; padding: 16px 0; } .form-row + .form-row { border-top: 1px solid var(--line); } .form-row-label { font-size: 14px; font-weight: 600; color: var(--ink); line-height: 1.35; } .form-row-label .hint { display: block; font-size: 12px; font-weight: 400; color: var(--ink-3); margin-top: 5px; line-height: 1.5; max-width: 28ch; } .form-row-control { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; min-width: 0; } /* ── Section divider with label ────────────────────────────── */ .section-head { display: flex; align-items: center; gap: 12px; margin: 10px 0 2px; padding-top: 18px; border-top: 1px solid var(--line); } .section-head:first-child { border-top: 0; padding-top: 0; } .section-head-label { font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-4); } .settings-scope-intro { margin-bottom: 16px; } .settings-control-center { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(320px, 1fr); gap: 16px; padding: 18px 20px; margin-bottom: 16px; border: 1px solid var(--line); border-radius: 14px; background: linear-gradient(135deg, color-mix(in oklab, var(--amber) 7%, var(--surface)) 0%, var(--surface) 48%, color-mix(in oklab, var(--up) 6%, var(--surface)) 100%); box-shadow: var(--shadow-1); } .settings-control-kicker, .settings-section-kicker { font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-4); margin-bottom: 6px; } .settings-control-title, .settings-section-title { font-size: 20px; line-height: 1.2; font-weight: 700; color: var(--ink); } .settings-control-copy { margin-top: 8px; font-size: 13px; line-height: 1.6; color: var(--ink-3); max-width: 58ch; } .settings-control-meta { display: grid; grid-template-columns: 1fr; gap: 10px; } .settings-meta-card { padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: color-mix(in oklab, var(--surface) 92%, transparent); box-shadow: var(--shadow-1); } .settings-meta-card strong { display: block; font-size: 13px; line-height: 1.4; color: var(--ink); } .settings-meta-label { display: block; margin-bottom: 4px; font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-4); } .settings-scope-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; } .settings-scope-card { padding: 16px; border-radius: 12px; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow-1); } .settings-scope-card.trump { background: color-mix(in oklab, var(--amber) 8%, var(--surface)); } .settings-scope-card.btc { background: color-mix(in oklab, var(--up) 8%, var(--surface)); } .settings-scope-card.global { background: color-mix(in oklab, var(--ink) 3%, var(--surface)); } .settings-scope-eyebrow { font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-4); margin-bottom: 8px; } .settings-scope-title { font-size: 15px; font-weight: 700; color: var(--ink); margin-bottom: 6px; } .settings-scope-copy { font-size: 12px; line-height: 1.6; color: var(--ink-3); margin-bottom: 14px; } .settings-scope-link { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border-radius: 999px; border: 1px solid var(--line); background: var(--surface); font-size: 12px; font-weight: 700; color: var(--ink); box-shadow: var(--shadow-1); } .settings-section-shell { margin-bottom: 18px; } .settings-section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; margin-bottom: 10px; } .settings-section-note { font-size: 12px; line-height: 1.5; color: var(--ink-3); text-align: right; } /* ── Inline $ prefix input ─────────────────────────────────── */ .num-field { display: inline-flex; align-items: center; background: var(--bg-sunk); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 0 10px; transition: border-color 120ms, background 120ms; } .num-field:focus-within { border-color: var(--amber-ring); background: var(--bg); } .num-field[data-disabled='true'] { opacity: 0.4; pointer-events: none; } .num-field .prefix, .num-field .suffix { font-size: 12px; color: var(--ink-3); font-family: var(--mono); } .num-field input { border: 0; background: transparent; font-family: var(--mono); font-size: 13px; padding: 8px 6px; width: 80px; outline: none; color: var(--ink); } .num-field input::-webkit-inner-spin-button, .num-field input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } /* ── Slider: unified look ──────────────────────────────────── */ .slider-field { flex: 1; display: flex; flex-direction: column; gap: 4px; } .slider-field input[type=range] { -webkit-appearance: none; width: 100%; height: 4px; background: var(--line-2); border-radius: 999px; outline: none; } .slider-field input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; background: var(--amber); border: 2px solid var(--bg); border-radius: 50%; box-shadow: 0 1px 3px rgba(0,0,0,0.18); cursor: pointer; } .slider-field .ticks { display: flex; justify-content: space-between; font-size: 10px; color: var(--ink-4); font-variant-numeric: tabular-nums; } .slider-readout { font-family: var(--mono); font-size: 14px; font-weight: 600; min-width: 56px; text-align: right; color: var(--ink); font-variant-numeric: tabular-nums; } .settings-note { width: 100%; padding: 10px 12px; border-radius: 8px; background: var(--bg-sunk); border: 1px solid var(--line); font-size: 12px; line-height: 1.55; color: var(--ink-3); } .settings-note.warn { color: var(--down); border-color: color-mix(in oklab, var(--down) 18%, var(--line)); background: var(--down-soft); } /* ============================================================ Dashboard specific ============================================================ */ .dash-grid { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 20px; align-items: start; } .hero-value { font-size: 44px; font-weight: 500; letter-spacing: -0.025em; line-height: 1; font-family: var(--mono); font-feature-settings: 'tnum'; } .hero-value .cents { color: var(--ink-3); font-size: 0.6em; } .asset-switch { display: inline-flex; padding: 4px; background: var(--bg-sunk); border: 1px solid var(--line); border-radius: var(--r-pill); gap: 2px; } .asset-switch button { padding: 7px 14px; border-radius: var(--r-pill); font-size: 13px; font-weight: 500; color: var(--ink-3); display: flex; align-items: center; gap: 6px; } .asset-switch button.on { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-1); } .asset-dot { width: 14px; height: 14px; border-radius: 999px; } .asset-dot.btc { background: linear-gradient(135deg, #f7931a, #f2a93b); } .asset-dot.eth { background: linear-gradient(135deg, #627eea, #8fa2ff); } .tf-bar { display: inline-flex; gap: 2px; padding: 3px; background: var(--bg-sunk); border: 1px solid var(--line); border-radius: var(--r-pill); } .tf-bar button { padding: 5px 10px; border-radius: var(--r-pill); font-size: 12px; font-weight: 500; color: var(--ink-3); font-family: var(--mono); } .tf-bar button.on { background: var(--ink); color: var(--bg); } .chart-wrap { margin-top: 8px; position: relative; height: 360px; } .chart-footnote { display: flex; gap: 18px; font-size: 12px; color: var(--ink-3); border-top: 1px dashed var(--line); padding-top: 14px; margin-top: 4px; } .chart-footnote .item { display: flex; align-items: center; gap: 6px; } .legend-dot { width: 8px; height: 8px; border-radius: 2px; } /* KPI tiles */ .kpi-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 20px; } .kpi { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: 16px 18px; display: flex; flex-direction: column; gap: 6px; position: relative; overflow: hidden; } .kpi .label { font-size: 12px; color: var(--ink-3); display: flex; align-items: center; gap: 6px; } .kpi .value { font-size: 22px; font-weight: 500; letter-spacing: -0.01em; font-family: var(--mono); } .kpi .foot { font-size: 12px; color: var(--ink-3); display: flex; align-items: center; gap: 6px; } .kpi.accent { background: linear-gradient(135deg, oklch(97% 0.04 85), oklch(95% 0.07 80)); border-color: var(--amber-ring); } .kpi.accent .label { color: var(--amber-ink); } /* Overview */ .overview-shell { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 18px; margin-bottom: 20px; align-items: start; } .overview-main { display: flex; flex-direction: column; gap: 16px; min-width: 0; } .overview-side { display: flex; flex-direction: column; gap: 16px; } .overview-market-card, .overview-side-card, .overview-stat-card { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 18px; box-shadow: var(--shadow-1); min-width: 0; } .overview-market-card { background: linear-gradient(135deg, color-mix(in oklab, var(--amber) 8%, var(--surface)) 0%, var(--surface) 52%, color-mix(in oklab, var(--up) 6%, var(--surface)) 100%); } .overview-kicker { font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-4); margin-bottom: 10px; } .overview-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 18px; } .overview-headline-row { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; } .overview-market-subtitle { margin-top: 8px; font-size: 13px; line-height: 1.5; color: var(--ink-3); } .overview-controls { display: flex; align-items: center; justify-content: flex-end; gap: 10px; flex-wrap: wrap; } /* ── Macro composite — unified card (band + track + scale together) ── */ /* Outer wrapper so band / track / scale read as ONE component. Tone-coloured rim hints at the regime without competing with the big number; it only kicks in for bull / bear so a neutral day stays calm. */ .overview-macro-card { margin-top: 4px; padding: 16px 18px 14px; border-radius: 14px; border: 1px solid var(--line); background: color-mix(in oklab, var(--bg-sunk) 72%, var(--surface)); box-shadow: var(--shadow-1); transition: border-color 200ms ease; } .overview-macro-card.bull { border-color: color-mix(in oklab, var(--up) 30%, var(--line)); background: color-mix(in oklab, var(--up) 5%, color-mix(in oklab, var(--bg-sunk) 72%, var(--surface))); } .overview-macro-card.bear { border-color: color-mix(in oklab, var(--down) 30%, var(--line)); background: color-mix(in oklab, var(--down) 5%, color-mix(in oklab, var(--bg-sunk) 72%, var(--surface))); } /* Band = title-row + summary (left) | big score + pill (right). No own border any more — the card around it is the visual edge. */ .overview-macro-band { display: flex; align-items: center; justify-content: space-between; gap: 18px; } .overview-macro-copy { min-width: 0; flex: 1 1 0; } .overview-macro-title-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 4px; } .overview-macro-title { font-size: 14px; font-weight: 700; letter-spacing: 0.02em; color: var(--ink); } /* Small dim caption next to the title — gives the user a quick "what is this and when did it update" anchor without crowding the headline. */ .overview-macro-stamp { font-size: 11px; letter-spacing: 0.04em; color: var(--ink-4); text-transform: uppercase; } .overview-macro-text, .overview-side-copy, .overview-stat-label { font-size: 13px; line-height: 1.5; color: var(--ink-3); } .overview-macro-score { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex-shrink: 0; } .overview-score-value { font-family: var(--mono); font-size: 38px; line-height: 1; font-weight: 800; letter-spacing: -0.03em; color: var(--ink); } .overview-score-value.bull { color: var(--up); } .overview-score-value.bear { color: var(--down); } .overview-score-value.neutral { color: var(--ink-2); } .overview-score-pill { display: inline-flex; align-items: center; height: 22px; padding: 0 10px; border-radius: 999px; border: 1px solid var(--line); background: var(--surface); font-size: 10.5px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); } .overview-score-pill.bull { color: var(--up); border-color: color-mix(in oklab, var(--up) 32%, var(--line)); background: color-mix(in oklab, var(--up) 12%, var(--surface)); } .overview-score-pill.bear { color: var(--down); border-color: color-mix(in oklab, var(--down) 32%, var(--line)); background: color-mix(in oklab, var(--down) 12%, var(--surface)); } /* Gradient track. Removed the .overview-score-fill overlay — the gradient already encodes "where am I on the spectrum"; layering an opaque fill only obscured the gradient at scores near 0. */ .overview-score-track { position: relative; height: 14px; margin-top: 14px; border-radius: 999px; overflow: visible; border: 1px solid color-mix(in oklab, var(--line) 78%, transparent); box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.06); background: linear-gradient(90deg, color-mix(in oklab, var(--down) 65%, transparent) 0%, color-mix(in oklab, var(--down) 18%, transparent) 35%, var(--bg-sunk) 50%, color-mix(in oklab, var(--up) 18%, transparent) 65%, color-mix(in oklab, var(--up) 65%, transparent) 100%); } /* Vertical centerline tick so 0 is visually obvious. */ .overview-score-track::after { content: ''; position: absolute; top: -3px; bottom: -3px; left: 50%; width: 1px; background: color-mix(in oklab, var(--ink) 18%, transparent); transform: translateX(-50%); } /* SOLID needle (was a hollow ring before — looked like a placeholder). Tone-coloured fill + white ring so it stands out against any gradient position. Two-layer shadow for depth on light AND dark themes. */ .overview-score-needle { position: absolute; top: 50%; width: 22px; height: 22px; border-radius: 999px; background: var(--ink-2); border: 3px solid var(--surface); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), 0 0 0 1px color-mix(in oklab, var(--ink) 18%, transparent); transform: translateY(-50%); transition: left 400ms cubic-bezier(0.4, 0, 0.2, 1); } .overview-score-needle.bull { background: var(--up); } .overview-score-needle.bear { background: var(--down); } .overview-score-needle.neutral { background: var(--ink-3); } .overview-score-scale { display: flex; justify-content: space-between; gap: 10px; margin-top: 8px; font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-4); } .overview-system-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin-top: 16px; } .overview-system-chip { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 64px; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--line); background: var(--surface); box-shadow: var(--shadow-1); transition: transform 120ms, border-color 120ms, box-shadow 120ms; } .overview-system-chip:hover { transform: translateY(-1px); border-color: var(--line-2); box-shadow: var(--shadow-2); } .overview-system-chip.passive { cursor: default; } .overview-system-chip-name { font-size: 12px; line-height: 1.4; color: var(--ink-3); } .overview-system-chip strong { font-family: var(--mono); font-size: 24px; line-height: 1; color: var(--ink); } .overview-secondary-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); flex-wrap: wrap; gap: 14px; } .overview-stat-card { min-height: 144px; display: flex; flex-direction: column; justify-content: space-between; } .overview-stat-card.accent { background: linear-gradient(135deg, oklch(97% 0.04 85), oklch(95% 0.07 80)); border-color: var(--amber-ring); } .overview-stat-value { font-family: var(--mono); font-size: 42px; line-height: 1; font-weight: 800; letter-spacing: -0.03em; color: var(--ink); } .overview-side-card.compact { min-height: 112px; } .overview-account-list { display: flex; flex-direction: column; gap: 0; } .overview-account-item { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 10px 0; border-bottom: 1px solid var(--line); font-size: 13px; color: var(--ink-3); } .overview-account-item:last-child { border-bottom: 0; padding-bottom: 0; } .overview-account-item strong { color: var(--ink); font-size: 14px; text-align: right; } /* Right rail */ .rail { display: flex; flex-direction: column; gap: 20px; } .signal-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: 18px; } .signal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .signal-head h3 { margin: 0; font-size: 14px; font-weight: 600; } .latest-post { border: 1px solid var(--line); border-radius: var(--r-sm); padding: 14px; background: var(--bg-sunk); } .latest-post .meta { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-3); margin-bottom: 10px; } .latest-post .text { font-size: 13px; line-height: 1.55; color: var(--ink); margin: 0 0 12px; } .latest-post .divider { height: 1px; background: var(--line); margin: 12px 0; } .latest-post .lp-row { display: flex; justify-content: space-between; align-items: center; font-size: 12px; } .latest-post .lp-row + .lp-row { margin-top: 6px; } .latest-post .lp-row .k { color: var(--ink-3); } .confidence-bar { height: 6px; background: var(--surface-3); border-radius: 999px; overflow: hidden; position: relative; margin-top: 6px; } .confidence-bar > div { height: 100%; background: linear-gradient(90deg, var(--amber) 0%, oklch(68% 0.2 45) 100%); border-radius: 999px; transition: width 600ms ease-out; } .ai-metric-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin-bottom: 8px; font-size: 13px; color: var(--ink-3); } .ai-metric-head strong { font-size: 18px; line-height: 1; color: var(--ink); font-family: var(--mono); font-weight: 600; letter-spacing: -0.02em; } .ai-reasoning-label { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 10px; font-size: 12px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--amber-ink); } .ai-reasoning-label::before { content: ''; width: 8px; height: 8px; border-radius: 999px; background: linear-gradient(135deg, var(--amber), oklch(68% 0.2 45)); box-shadow: 0 0 0 4px color-mix(in oklab, var(--amber) 18%, transparent); } .ai-reasoning-card { padding: 16px 18px; background: linear-gradient(180deg, color-mix(in oklab, var(--amber-soft) 55%, var(--surface)) 0%, var(--bg-sunk) 100%); border-radius: 18px; border: 1px solid color-mix(in oklab, var(--amber-ring) 55%, var(--line)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), var(--shadow-1); font-size: 15px; line-height: 1.78; color: var(--ink); } .ai-reasoning-card.scroll { max-height: 180px; overflow-y: auto; padding-right: 14px; } html[data-theme="dark"] .ai-reasoning-card { background: linear-gradient(180deg, color-mix(in oklab, var(--amber-soft) 30%, var(--surface-2)) 0%, var(--surface) 100%); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03), var(--shadow-1); } /* Bot status */ .bot-status { background: linear-gradient(160deg, oklch(22% 0.01 85) 0%, oklch(14% 0.01 85) 100%); color: oklch(96% 0.005 85); border-radius: var(--r-lg); padding: 22px; position: relative; overflow: hidden; } .bot-status::after { content: ''; position: absolute; right: -40px; top: -40px; width: 180px; height: 180px; background: radial-gradient(circle, oklch(75% 0.17 75 / 0.4) 0%, transparent 70%); pointer-events: none; } .bot-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 18px; } .bot-head h3 { margin: 0; font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 8px; } .bot-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 20px; position: relative; z-index: 1; } .bot-stat .k { font-size: 11px; color: oklch(70% 0.01 85); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 4px; } .bot-stat .v { font-size: 20px; font-family: var(--mono); font-weight: 500; letter-spacing: -0.01em; } .bot-stat .v.up { color: oklch(75% 0.17 148); } .bot-stat .v.amber { color: var(--amber); } .bot-cta { margin-top: 18px; display: flex; gap: 8px; position: relative; z-index: 1; } .bot-cta .btn { flex: 1; } /* Post list (stream) */ .post-stream { display: flex; flex-direction: column; gap: 10px; } .post-row { display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); transition: border-color 120ms, background 120ms; cursor: pointer; overflow: hidden; } .post-row:hover { border-color: var(--line-2); } .post-row.selected { border-color: var(--amber-ring); background: oklch(99% 0.02 85); } .post-row-main { display: grid; grid-template-columns: 36px 1fr auto; gap: 14px; padding: 14px 16px; align-items: flex-start; } .post-row-detail { border-top: 1px solid var(--line); padding: 14px 16px; display: flex; flex-direction: column; gap: 14px; } .src-ico { width: 36px; height: 36px; border-radius: 10px; display: grid; place-items: center; font-family: var(--mono); font-weight: 600; font-size: 15px; flex-shrink: 0; } .src-ico.x { background: #111; color: #fff; } .src-ico.truth { background: oklch(94% 0.05 25); color: oklch(45% 0.2 25); } /* Non-Trump sources — distinct hues so the feed reads at a glance. */ .src-ico.breakout { background: oklch(94% 0.08 200); color: oklch(40% 0.15 220); } .src-ico.reversal { background: oklch(94% 0.08 300); color: oklch(40% 0.15 300); } .src-ico.whale { background: oklch(94% 0.08 150); color: oklch(40% 0.15 150); font-size: 13px; } .src-ico.manual { background: oklch(94% 0.05 60); color: oklch(45% 0.15 60); font-size: 13px; } .src-ico.external { background: var(--bg-sunk); color: var(--ink-2); } .post-body .meta { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; font-size: 12px; color: var(--ink-3); } .post-body .text { font-size: 14px; line-height: 1.5; color: var(--ink); margin: 0 0 10px; } .post-aside { display: flex; flex-direction: column; gap: 8px; align-items: flex-end; min-width: 120px; } /* Signal pill */ .sig { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: var(--r-pill); font-size: 12px; font-weight: 600; letter-spacing: 0.02em; } .sig.buy { background: var(--up-soft); color: oklch(38% 0.16 148); } .sig.sell, .sig.short { background: var(--down-soft); color: oklch(42% 0.2 25); } .sig.hold { background: var(--bg-sunk); color: var(--ink-2); } .impact-mini { display: flex; gap: 8px; align-items: center; font-family: var(--mono); font-size: 12px; } .impact-mini .tf { color: var(--ink-4); font-size: 11px; } /* Trades table */ .table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; } .table th { text-align: left; font-weight: 500; color: var(--ink-3); padding: 14px 18px; border-bottom: 1px solid var(--line); font-size: 12px; background: var(--bg-sunk); } .table th:first-child { border-top-left-radius: var(--r-md); } .table th:last-child { border-top-right-radius: var(--r-md); text-align: right; } .table td { padding: 14px 18px; border-bottom: 1px solid var(--line); } .table td:last-child { text-align: right; } .table tr:last-child td { border-bottom: 0; } .table tr:hover td { background: var(--bg-sunk); } .side-pill { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border-radius: var(--r-pill); font-size: 12px; font-weight: 600; } .side-pill.long { background: var(--up-soft); color: oklch(38% 0.16 148); } .side-pill.short { background: var(--down-soft); color: oklch(42% 0.2 25); } /* Settings */ .settings-grid { display: grid; grid-template-columns: 260px 1fr; gap: 32px; align-items: start; } .settings-side { position: sticky; top: 84px; display: flex; flex-direction: column; gap: 2px; } .settings-side button { text-align: left; padding: 10px 14px; border-radius: var(--r-sm); font-size: 13px; color: var(--ink-2); font-weight: 500; } .settings-side button.on { background: var(--bg-sunk); color: var(--ink); } .settings-side button:hover { background: var(--bg-sunk); color: var(--ink); } .field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 20px; } .field label { font-size: 13px; font-weight: 500; } .field .hint { font-size: 12px; color: var(--ink-3); } .field input, .field select, .field textarea { border: 1px solid var(--line); background: var(--surface); border-radius: var(--r-sm); padding: 11px 14px; font-size: 14px; width: 100%; outline: none; transition: border-color 120ms, box-shadow 120ms; color: var(--ink); } .field input:focus, .field textarea:focus { border-color: var(--amber-ring); box-shadow: 0 0 0 3px oklch(88% 0.12 80 / 0.4); } .settings-switch { --w: 40px; width: var(--w); height: 24px; border-radius: 999px; background: var(--surface-3); position: relative; cursor: pointer; transition: background 150ms; border: 1px solid var(--line); flex-shrink: 0; } .settings-switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 999px; background: var(--surface); box-shadow: var(--shadow-1); transition: transform 180ms; } .settings-switch.on { background: var(--ink); border-color: var(--ink); } .settings-switch.on::after { transform: translateX(16px); } .setting-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; padding: 16px 0; border-bottom: 1px solid var(--line); } .setting-row:last-child { border-bottom: 0; } .setting-row .desc { font-size: 12px; color: var(--ink-3); margin-top: 4px; max-width: 440px; line-height: 1.5; } /* Analytics */ .metric-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; } @media (max-width: 1180px) { .overview-shell { grid-template-columns: 1fr; } .overview-side { order: -1; } .dash-grid { grid-template-columns: 1fr; } .rail { order: -1; } } @media (max-width: 900px) { .nav { height: auto; min-height: 64px; padding: 12px 18px; flex-wrap: wrap; gap: 12px; } .brand { flex: 1; } .nav-tabs { order: 3; width: 100%; overflow-x: auto; justify-content: flex-start; } .nav-right { margin-left: auto; } .page { padding: 24px 18px 64px; } .page-head { align-items: flex-start; flex-direction: column; gap: 12px; } .page-title { font-size: 28px; } .kpi-row, .metric-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .overview-system-strip, .overview-secondary-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .settings-grid, .form-row { grid-template-columns: 1fr; gap: 10px; } .settings-side { position: static; } .chart-footnote { flex-wrap: wrap; } .chart-footnote > div:last-child { margin-left: 0 !important; width: 100%; } .table { min-width: 760px; } .card.flush { overflow-x: auto !important; } } @media (max-width: 900px) { .nav-tabs { /* Edge-to-edge horizontal scroll with snap on mobile */ margin: 0 -18px; padding: 0 18px; gap: 4px; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch; scrollbar-width: none; } .nav-tabs::-webkit-scrollbar { display: none; } .nav-tab { flex: 0 0 auto; scroll-snap-align: start; padding: 8px 12px; font-size: 13px; } } @media (max-width: 640px) { .nav { padding: 10px 14px; } .brand span:last-child { display: none; } .connect-btn.lg { padding: 9px 12px; font-size: 13px; } .wallet-chip { padding: 6px 10px !important; font-size: 12px; } .page { padding: 20px 14px 56px; } .kpi-row, .metric-grid { grid-template-columns: 1fr; } .overview-card-head, .overview-controls, .overview-macro-band, .overview-account-item { flex-direction: column; align-items: flex-start; } .overview-score-value { font-size: 34px; } .overview-account-item strong { text-align: left; } .overview-system-strip, .overview-secondary-grid { grid-template-columns: 1fr; } .macro-panel-head, .macro-composite-head { flex-direction: column; align-items: flex-start; } .macro-panel-meta { text-align: left; } .macro-grid.two { grid-template-columns: 1fr; } .macro-grid { padding: 12px; gap: 12px; } .macro-metric-card, .macro-guide-card { padding: 16px; min-height: 0; } .macro-metric-head { /* Desktop is now also flex-direction: column. Just override the gap for mobile to keep label-to-value spacing comfortable on small fonts. */ gap: 8px; } .macro-metric-value { font-size: 30px; } .macro-guide-title { font-size: 18px; } .macro-summary { font-size: 13px; line-height: 1.5; min-height: 0; } .macro-threshold-chip { font-size: 11.5px; /* Bump tap target on mobile — iOS HIG asks for ≥44pt, this is the inline-flex bubble so we go a bit smaller but still comfortable. */ min-height: 36px; padding: 7px 12px; } .macro-threshold-chip.active { font-size: 12px; padding: 8px 14px; /* Stronger scale on mobile — small screens lose subtle differences. */ transform: scale(1.08); } .macro-action-btn { /* Stays compact on mobile too — bottom-right corner pill, not full-width. */ padding: 8px 12px; } .settings-scope-grid { grid-template-columns: 1fr; } .settings-control-center { grid-template-columns: 1fr; } .settings-section-head { flex-direction: column; align-items: flex-start; } .settings-section-note { text-align: left; } /* Composite scale labels — "BEAR / NEUTRAL / BULL" letters crowd at narrow widths. Shorten them. */ .macro-composite-scale { font-size: 9.5px; letter-spacing: 0.02em; } /* InfoTip — boost tap area and clamp bubble inside viewport */ .infotip { /* Pad outside the visible icon to enlarge the hit zone without making the icon itself look bloated. */ padding: 8px; margin: -8px -2px -8px 4px; } .infotip-icon { width: 18px; height: 18px; font-size: 11px; } .infotip-bubble { /* On small viewports a 280px-wide bubble can hang off the edge when the tip sits near the right margin. Clamp to viewport width minus a 16px breathing room each side. */ max-width: calc(100vw - 32px) !important; } /* Touch-only browsers fire :active on tap. Combined with :hover, this ensures bubble shows on first tap (not the doubled-tap that some CSS-hover-only tooltips require). */ .infotip:active .infotip-bubble { opacity: 1; transform: none; } .macro-action-label { font-size: 12px; white-space: normal; } .macro-composite { padding: 18px 16px 20px; } .macro-composite-right { justify-content: flex-start; } .row.between { align-items: flex-start; } .post-row-main { grid-template-columns: 32px 1fr; } .post-aside { grid-column: 2; align-items: flex-start; min-width: 0; } .src-ico { width: 32px; height: 32px; } .chart-wrap, .chart-wrap > div { height: 300px !important; } .hero-value { font-size: 34px; } .asset-switch, .tf-bar { max-width: 100%; overflow-x: auto; } footer { flex-wrap: wrap; padding: 18px 14px !important; } .card[style*='grid-template-columns: 1fr auto'] { grid-template-columns: 1fr !important; } /* Tables: horizontal-scroll with subtle hint rather than page overflow */ .card.flush { border-radius: 10px; } .table { font-size: 12px; } .table th, .table td { padding: 10px 12px !important; } /* Modals / dialogs on small screens */ .modal, .dialog { width: calc(100vw - 24px) !important; max-width: calc(100vw - 24px) !important; } } /* Ultra-narrow screens — drop the regime descriptive words on the composite scale so it doesn't wrap. Keep just the numeric anchors. The .word spans inside each label are set in MacroPanel.tsx so this hide works cleanly. */ @media (max-width: 420px) { .macro-composite-scale .word { display: none; } } @media (max-width: 380px) { .nav { padding: 8px 12px; } .page { padding: 16px 12px 48px; } .page-title { font-size: 24px; } .hero-value { font-size: 28px; } .connect-btn.lg { padding: 8px 10px; font-size: 12px; } } /* Global safety: no page-level horizontal scroll */ html, body { max-width: 100%; overflow-x: hidden; } /* Misc utilities */ .stack { display: flex; flex-direction: column; } .row { display: flex; align-items: center; } .between { justify-content: space-between; } .gap-s { gap: 8px; } .gap-m { gap: 14px; } .gap-l { gap: 20px; } .grow { flex: 1; } .mono-num { font-family: var(--mono); font-variant-numeric: tabular-nums; } .muted { color: var(--ink-3); } .tiny { font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-3); font-weight: 500; } /* Scrollbar */ ::-webkit-scrollbar { width: 10px; height: 10px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 999px; border: 2px solid var(--bg); } ::-webkit-scrollbar-thumb:hover { background: oklch(80% 0.01 85); } /* ── Skeleton / shimmer loading ───────────────────────────────────────────── Use .skeleton on any block element to get a shimmer placeholder. Combine with explicit width/height or min-height to shape the placeholder. .skeleton-card wraps a card-shaped block. */ @keyframes shimmer { 0% { background-position: -600px 0; } 100% { background-position: 600px 0; } } .skeleton { border-radius: 6px; background: linear-gradient( 90deg, var(--bg-sunk) 25%, color-mix(in srgb, var(--bg-sunk) 60%, var(--line)) 50%, var(--bg-sunk) 75% ); background-size: 1200px 100%; animation: shimmer 1.4s ease-in-out infinite; } .skeleton-card { border-radius: var(--r); border: 1px solid var(--line); padding: 20px; background: var(--bg-card); display: flex; flex-direction: column; gap: 10px; } /* Convenience shorthands */ .sk-line { height: 14px; } .sk-line-sm { height: 11px; } .sk-title { height: 20px; } .sk-w-full { width: 100%; } .sk-w-3q { width: 75%; } .sk-w-half { width: 50%; } .sk-w-q { width: 25%; }