8ab7c55288
- overflow-x: clip on html/body (was `hidden`, which silently made body a scroll container and broke position:sticky on the navbar) - .macro-composite: card style matching indicator cards (14px margin, border + 12px radius + surface bg + shadow-1, no more full-bleed band) - .macro-composite-track: remove overflow:hidden so 24px needle isn't clipped by 18px track; add 6px vertical margin for breathing room Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2823 lines
67 KiB
CSS
2823 lines
67 KiB
CSS
/* ============================================================
|
||
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 <PageHint>One sentence about the page.</PageHint>. */
|
||
.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 {
|
||
/* Aligned to the indicator-card grid above (.macro-grid uses 14px gutters
|
||
and metric cards have 12px radius / 1px border / surface bg). The
|
||
composite reads as a "summary card" sitting at the same indent as the
|
||
metric cards rather than a full-bleed banner. */
|
||
margin: 14px;
|
||
padding: 20px 22px 22px;
|
||
background: var(--surface);
|
||
border: 1px solid var(--line);
|
||
border-radius: 12px;
|
||
box-shadow: var(--shadow-1);
|
||
}
|
||
|
||
.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;
|
||
/* No `overflow: hidden` — the 24px needle is taller than the track and
|
||
gets clipped top/bottom otherwise. The gradient is naturally rounded
|
||
by border-radius, so clipping isn't needed. */
|
||
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);
|
||
margin: 6px 0;
|
||
}
|
||
|
||
.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.
|
||
Use `overflow-x: clip` (not `hidden`) — `hidden` turns body into a scroll
|
||
container, which silently breaks `position: sticky` on the navbar. */
|
||
html, body { max-width: 100%; overflow-x: clip; }
|
||
|
||
/* 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%; }
|