blackmistcode's picture
Add files using upload-large-folder tool
0dc7194 verified
@import url('https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Syne:wght@400;500;600;700&display=swap');
:root {
--bg: #0a0c10;
--bg2: #111318;
--bg3: #181c24;
--bg4: #1e232d;
--border: rgba(255,255,255,0.08);
--border2: rgba(255,255,255,0.13);
--text: #e8eaf0;
--text2: #8b90a0;
--text3: #7e8494;
--green: #22d37a;
--green2: #0d6e3a;
--green3: #052a17;
--red: #f04040;
--red2: #7a1a1a;
--red3: #2d0808;
--blue: #4a9eff;
--blue2: #1a4a80;
--blue3: #081830;
--amber: #f0a020;
--amber2: #7a4e08;
--amber3: #2d1c02;
--accent: #4a9eff;
--font-sans: 'Syne', sans-serif;
--font-mono: 'DM Mono', monospace;
--sidebar-width: 240px;
--sidebar-collapsed: 56px;
--topbar-height: 56px;
--panel-gap: 16px;
--radius: 10px;
--radius-sm: 6px;
/* Fluid typography scale */
--fs-p: clamp(1rem, 1.15vw, 1.125rem);
--fs-h1: clamp(1.75rem, 2.8vw, 2.25rem);
--fs-h2: clamp(1.5rem, 2.4vw, 1.875rem);
--fs-h3: clamp(1.25rem, 1.9vw, 1.5rem);
--fs-h4: clamp(1.125rem, 1.6vw, 1.25rem);
--fs-h5: clamp(1rem, 1.3vw, 1.125rem);
--fs-h6: clamp(0.875rem, 1.1vw, 1rem);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 16px;
}
html, body, #app {
height: 100%;
width: 100%;
overflow: hidden;
}
body {
background: var(--bg);
color: var(--text);
font-family: var(--font-sans);
font-size: 1rem;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/* Semantic type hierarchy (fluid) */
p { font-size: var(--fs-p); line-height: 1.55; }
h1 { font-size: var(--fs-h1); line-height: 1.15; font-weight: 700; }
h2 { font-size: var(--fs-h2); line-height: 1.2; font-weight: 700; }
h3 { font-size: var(--fs-h3); line-height: 1.25; font-weight: 600; }
h4 { font-size: var(--fs-h4); line-height: 1.3; font-weight: 600; }
h5 { font-size: var(--fs-h5); line-height: 1.35; font-weight: 500; }
h6 { font-size: var(--fs-h6); line-height: 1.4; font-weight: 500; }
/* ─── Layout principal ─── */
.layout {
display: grid;
grid-template-areas:
"topbar topbar"
"sidebar main";
grid-template-columns: var(--sidebar-width) 1fr;
grid-template-rows: var(--topbar-height) 1fr;
height: 100vh;
width: 100vw;
transition: grid-template-columns 0.25s ease;
}
.layout.collapsed {
grid-template-columns: var(--sidebar-collapsed) 1fr;
}
/* ─── Sidebar ─── */
.sidebar {
grid-area: sidebar;
background: var(--bg2);
border-right: 1px solid var(--border);
display: flex;
flex-direction: column;
overflow: hidden;
transition: width 0.25s ease;
position: relative;
}
.sidebar-toggle {
position: absolute;
top: 12px;
right: -10px;
width: 24px;
height: 24px;
border-radius: 50%;
background: var(--bg3);
border: 1px solid var(--border2);
color: var(--text2);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 0.875rem;
z-index: 10;
transition: transform 0.2s;
}
.layout.collapsed .sidebar-toggle {
transform: rotate(180deg);
right: -10px;
}
/* ─── Topbar Logo ─── */
.topbar-logo {
position: fixed;
left: 16px;
top: 0;
height: var(--topbar-height);
display: flex;
align-items: center;
gap: 10px;
z-index: 100;
}
.topbar-logo .logo-dot {
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--blue);
animation: pulse 2s ease-in-out infinite;
flex-shrink: 0;
}
.topbar-logo .logo-text {
font-size: 1.125rem;
font-weight: 700;
color: var(--text);
letter-spacing: -0.3px;
white-space: nowrap;
}
.sidebar-nav {
flex: 1;
padding: 14px 8px;
display: flex;
flex-direction: column;
gap: 4px;
overflow-y: auto;
}
.nav-item {
display: flex;
align-items: center;
gap: 14px;
padding: 14px 14px;
border-radius: var(--radius-sm);
cursor: pointer;
color: var(--text2);
font-size: 1rem;
font-weight: 500;
transition: background 0.15s, color 0.15s;
white-space: nowrap;
overflow: hidden;
}
.nav-item:hover {
background: var(--bg3);
color: var(--text);
}
.nav-item.active {
background: var(--blue3);
color: var(--blue);
border: 0.5px solid var(--blue2);
}
.nav-icon {
font-size: 1rem;
width: 20px;
text-align: center;
flex-shrink: 0;
}
.nav-label {
opacity: 1;
transition: opacity 0.15s;
}
.layout.collapsed .nav-label {
opacity: 0;
width: 0;
}
.sidebar-footer {
padding: 14px;
border-top: 1px solid var(--border);
font-size: 0.875rem;
color: var(--text3);
font-family: var(--font-mono);
text-align: center;
white-space: nowrap;
overflow: hidden;
}
.layout.collapsed .sidebar-footer {
opacity: 0;
}
/* ─── Topbar ─── */
.topbar {
grid-area: topbar;
background: var(--bg2);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
padding: 0 16px;
padding-left: calc(var(--sidebar-width) + var(--panel-gap));
gap: 16px;
overflow: hidden;
position: relative;
}
.layout.collapsed .topbar {
padding-left: calc(var(--sidebar-width) + var(--panel-gap));
}
.live-badge {
font-family: var(--font-mono);
font-size: 0.875rem;
background: var(--green3);
color: var(--green);
border: 0.5px solid var(--green2);
padding: 6px 12px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 4px;
flex-shrink: 0;
}
.live-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--green);
animation: pulse 1.5s ease-in-out infinite;
}
.topbar-stats {
display: flex;
align-items: center;
gap: 20px;
flex: 1;
overflow: hidden;
}
.stat {
display: flex;
align-items: center;
gap: 14px;
flex-shrink: 0;
}
.stat-label {
font-size: 0.875rem;
color: var(--text3);
font-family: var(--font-mono);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.stat-val {
font-size: 1rem;
font-weight: 600;
color: var(--text);
font-family: var(--font-mono);
}
.stat-delta {
font-size: 0.875rem;
font-family: var(--font-mono);
}
.stat-delta.up { color: var(--green); }
.stat-delta.dn { color: var(--red); }
.stat-delta.neutral { color: var(--text3); }
.topbar-filters {
display: flex;
align-items: center;
gap: 10px;
flex-shrink: 0;
}
.filter-select {
background: var(--bg3);
border: 0.5px solid var(--border2);
border-radius: var(--radius-sm);
padding: 7px 12px;
color: var(--text);
font-size: 0.875rem;
font-family: var(--font-mono);
outline: none;
cursor: pointer;
min-width: 140px;
max-width: 180px;
appearance: none;
-webkit-appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238b90a0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 10px center;
padding-right: 30px;
transition: border-color 0.15s;
}
.filter-select:hover {
border-color: var(--border2);
}
.filter-select:focus {
border-color: var(--blue2);
}
.filter-select option {
background: var(--bg2);
color: var(--text);
}
.topbar-actions {
margin-left: auto;
display: flex;
align-items: center;
gap: 16px;
flex-shrink: 0;
}
.btn-ghost {
font-size: 0.9375rem;
font-weight: 500;
color: var(--blue);
border: 0.5px solid var(--blue2);
background: var(--blue3);
padding: 8px 16px;
border-radius: var(--radius-sm);
cursor: pointer;
font-family: var(--font-sans);
transition: opacity 0.15s;
}
.btn-ghost:hover {
opacity: 0.85;
}
.icon-btn {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--bg3);
border: 0.5px solid var(--border2);
color: var(--text2);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 1rem;
transition: color 0.15s, border-color 0.15s;
}
.icon-btn:hover {
color: var(--text);
border-color: var(--border2);
}
/* ─── Main content ─── */
.main {
grid-area: main;
overflow: auto;
padding: var(--panel-gap);
background: var(--bg);
}
/* Vistas */
.view { display: none; }
.view.active { display: block; height: 100%; }
/* ─── Dashboard layout ─── */
.dashboard-grid {
display: grid;
grid-template-columns: 1fr 336px;
grid-template-rows: minmax(120px, 59%) 1fr;
gap: var(--panel-gap);
height: 100%;
min-height: 0;
}
.panel {
background: var(--bg2);
border: 0.5px solid var(--border);
border-radius: var(--radius);
display: flex;
flex-direction: column;
overflow: hidden;
min-height: 0;
}
.panel-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 14px;
border-bottom: 0.5px solid var(--border);
cursor: pointer;
user-select: none;
transition: background 0.15s;
}
.panel-header:hover {
background: rgba(255,255,255,0.02);
}
.panel-title {
font-size: 0.875rem;
color: var(--text3);
font-family: var(--font-mono);
text-transform: uppercase;
letter-spacing: 0.08em;
display: flex;
align-items: center;
gap: 14px;
}
.panel-toggle {
font-size: 0.875rem;
color: var(--text3);
transition: transform 0.2s;
}
.panel.collapsed .panel-toggle {
transform: rotate(-90deg);
}
.panel-body {
flex: 1;
overflow: auto;
padding: 12px;
min-height: 0;
}
.panel.collapsed .panel-body {
display: none;
}
.panel-subtitle {
font-size: 0.875rem;
color: var(--text3);
}
.positions-separator {
margin-top: 10px;
padding-top: 10px;
border-top: 0.5px solid var(--border);
}
.panel-title.mb-sm {
margin-bottom: 8px;
}
.panel.full-height {
height: 100%;
}
.hidden {
display: none;
}
.desktop-only { display: initial; }
.mobile-only { display: none; }
/* ID-level rules beat class rules — ensure circle buttons and auth dot stay off in desktop */
#btn-notif,
#btn-auth-mobile {
display: none;
}
/* Hide topbar legend in all views — desktop uses the map panel legend instead */
.topbar-stats .legend {
display: none;
}
/* Map panel legend */
.map-legend {
display: flex;
align-items: center;
gap: 12px;
margin-left: auto;
}
#panel-map .panel-header {
justify-content: flex-start;
}
/* Panel mapa */
.map-panel {
grid-row: 1 / 2;
grid-column: 1 / 2;
}
#map-container {
width: 100%;
height: 100%;
min-height: 300px;
background: var(--bg3);
border-radius: var(--radius-sm);
overflow: hidden;
}
/* Panel señales */
.signals-panel {
grid-row: 1 / 3;
grid-column: 2 / 3;
}
.signals-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.market-card {
background: var(--bg3);
border: 0.5px solid var(--border);
border-radius: var(--radius-sm);
padding: 14px;
cursor: pointer;
transition: border-color 0.15s, background 0.15s;
}
.market-card:hover {
border-color: var(--border2);
}
.market-card.active {
border-color: var(--blue2);
background: var(--blue3);
}
.market-cat {
font-size: 0.875rem;
font-family: var(--font-mono);
color: var(--text3);
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: 4px;
}
.market-q {
font-size: 0.9375rem;
color: var(--text);
line-height: 1.4;
font-weight: 500;
margin-bottom: 8px;
}
.market-footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
}
.prob-bar-wrap {
flex: 1;
min-width: 0;
}
.prob-bar-bg {
height: 5px;
background: var(--bg4);
border-radius: 2px;
overflow: hidden;
}
.prob-bar-fill {
height: 100%;
border-radius: 2px;
width: var(--prob-width, 0%);
transition: width 0.8s ease;
}
.prob-val {
font-size: 0.9375rem;
font-weight: 600;
font-family: var(--font-mono);
flex-shrink: 0;
}
.signal-badge {
font-size: 0.875rem;
font-weight: 600;
padding: 2px 6px;
border-radius: 4px;
font-family: var(--font-mono);
letter-spacing: 0.04em;
flex-shrink: 0;
}
.sig-bull { background: var(--green3); color: var(--green); border: 0.5px solid var(--green2); }
.sig-bear { background: var(--red3); color: var(--red); border: 0.5px solid var(--red2); }
.sig-neut { background: var(--bg4); color: var(--text2); border: 0.5px solid var(--border2); }
.badge-abbr { display: none; }
.badge-full { display: inline; }
.sig-none {
background: transparent;
color: var(--text3, #6e7681);
border: 0.5px dashed var(--border2);
font-size: 0.72rem;
letter-spacing: 0.06em;
font-weight: 500;
}
.model-badge {
font-size: 0.65rem;
font-weight: 500;
color: var(--text3, #6e7681);
background: var(--bg4);
border: 0.5px solid var(--border2);
border-radius: 4px;
padding: 1px 5px;
margin-left: 6px;
font-family: var(--font-mono);
letter-spacing: 0.04em;
text-transform: uppercase;
flex-shrink: 0;
}
/* Spread badge inline en categoria */
.spread-badge {
margin-left: 6px;
font-size: 0.7rem;
color: var(--text3, #6e7681);
font-family: var(--font-mono);
}
.spread-badge.illiquid {
color: var(--red, #f04040);
font-weight: 600;
}
/* Fila Edge: Mercado · IA · Edge */
.edge-row {
display: flex;
align-items: center;
gap: 6px;
margin-top: 6px;
padding-top: 6px;
border-top: 0.5px solid var(--border2, #1f242b);
font-size: 0.72rem;
font-family: var(--font-mono);
letter-spacing: 0.02em;
}
.edge-implied { color: var(--text2, #9aa4b2); }
.edge-fair { font-weight: 600; }
.edge-sep { color: var(--text3, #4a5260); opacity: 0.6; }
.edge-value { font-weight: 700; padding: 1px 5px; border-radius: 3px; }
.edge-pos { color: var(--green, #22d37a); background: var(--green3, rgba(34,211,122,0.08)); }
.edge-neg { color: var(--red, #f04040); background: var(--red3, rgba(240,64,64,0.08)); }
.edge-zero { color: var(--text3, #6e7681); }
/* Sugerencia de tamano (Kelly) bajo el simulador */
.kelly-note {
flex: 1;
font-size: 0.78rem;
color: var(--text2, #9aa4b2);
font-family: var(--font-mono);
padding: 4px 8px;
border-left: 2px solid var(--border2, #1f242b);
background: rgba(255,255,255,0.02);
border-radius: 0 4px 4px 0;
}
.kelly-warn {
color: var(--red, #f04040);
border-left-color: var(--red, #f04040);
background: rgba(240,64,64,0.05);
}
/* Panel detalle */
.detail-panel {
grid-row: 2 / 3;
grid-column: 1 / 2;
overflow: hidden;
}
.detail-panel .panel-body {
overflow: hidden;
}
/* The anonymous content wrapper built by buildDetailDOM */
.detail-panel .panel-body > div {
height: 100%;
display: flex;
flex-direction: column;
gap: 10px;
min-height: 0;
}
.detail-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 12px;
gap: 16px;
}
.detail-tag {
font-size: 0.875rem;
color: var(--blue);
font-family: var(--font-mono);
text-transform: uppercase;
letter-spacing: 0.08em;
margin-bottom: 4px;
}
.detail-q {
font-size: 1rem;
font-weight: 600;
color: var(--text);
line-height: 1.5;
}
.detail-meta {
font-size: 0.875rem;
color: var(--text3);
font-family: var(--font-mono);
margin-top: 2px;
}
.detail-metrics {
display: flex;
gap: 16px;
align-items: center;
flex-shrink: 0;
}
.metric {
text-align: right;
}
.metric-label {
font-size: 0.875rem;
color: var(--text3);
font-family: var(--font-mono);
margin-bottom: 2px;
}
.metric-value {
font-size: 0.875rem;
font-weight: 700;
font-family: var(--font-mono);
}
.metric-sep {
width: 1px;
height: 40px;
background: var(--border);
}
.outcomes-row {
display: flex;
gap: 16px;
flex: 1;
min-height: 0;
}
.outcome-card {
flex: 1;
background: var(--bg3);
border: 0.5px solid var(--border);
border-radius: var(--radius-sm);
padding: 14px;
text-align: center;
}
.outcome-name {
font-size: 0.875rem;
color: var(--text2);
margin-bottom: 4px;
font-family: var(--font-mono);
}
.outcome-price {
font-size: 1.25rem;
font-weight: 700;
color: var(--text);
font-family: var(--font-mono);
}
.outcome-delta {
font-size: 0.875rem;
font-family: var(--font-mono);
margin-top: 2px;
}
.outcome-card.yes .outcome-price { color: var(--green); }
.outcome-card.no .outcome-price { color: var(--red); }
.chart-container {
flex: 2;
background: var(--bg3);
border: 0.5px solid var(--border);
border-radius: var(--radius-sm);
padding: 14px;
min-height: 80px;
overflow: hidden;
align-self: stretch;
}
.chart-label {
font-size: 0.875rem;
color: var(--text3);
font-family: var(--font-mono);
margin-bottom: 6px;
}
/* SÍ / NO mini chips in the detail header */
.outcome-mini {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
padding: 0 10px;
}
.outcome-mini-label {
font-size: 0.72rem;
font-family: var(--font-mono);
color: var(--text3);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.outcome-mini-price {
font-size: 1rem;
font-weight: 700;
font-family: var(--font-mono);
}
.outcome-mini-price.yes { color: var(--green); }
.outcome-mini-price.no { color: var(--red); }
.ai-title-group {
display: flex;
align-items: center;
gap: 8px;
}
.ai-title-group .ai-icon {
width: 20px;
height: 20px;
font-size: 0.75rem;
}
.ai-box {
flex: 1;
background: var(--bg3);
border: 0.5px solid var(--blue2);
border-radius: var(--radius-sm);
padding: 14px;
display: flex;
flex-direction: column;
gap: 8px;
overflow: hidden;
min-width: 0;
}
.ai-icon {
width: 32px;
height: 32px;
border-radius: 6px;
background: var(--blue3);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-size: 0.875rem;
}
.ai-label {
font-size: 0.875rem;
color: var(--blue);
font-family: var(--font-mono);
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: 3px;
}
.ai-text {
font-size: 0.9375rem;
color: var(--text2);
line-height: 1.5;
}
.sim-row {
display: flex;
gap: 16px;
align-items: center;
flex-wrap: wrap;
justify-content: flex-end;
}
.sim-label {
font-size: 0.9375rem;
color: var(--text3);
font-family: var(--font-mono);
}
.sim-input {
background: var(--bg3);
border: 0.5px solid var(--border2);
border-radius: var(--radius-sm);
padding: 8px 14px;
color: var(--text);
font-size: 1rem;
font-family: var(--font-mono);
width: 100px;
outline: none;
}
.sim-input:focus {
border-color: var(--blue2);
}
.sim-btn-yes {
background: var(--green3);
border: 0.5px solid var(--green2);
color: var(--green);
font-size: 0.9375rem;
font-weight: 600;
padding: 8px 16px;
border-radius: var(--radius-sm);
cursor: pointer;
font-family: var(--font-mono);
transition: opacity 0.15s;
}
.sim-btn-no {
background: var(--red3);
border: 0.5px solid var(--red2);
color: var(--red);
font-size: 0.9375rem;
font-weight: 600;
padding: 8px 16px;
border-radius: var(--radius-sm);
cursor: pointer;
font-family: var(--font-mono);
transition: opacity 0.15s;
}
.sim-btn-yes:hover, .sim-btn-no:hover {
opacity: 0.85;
}
.sim-disclaimer {
font-size: 0.875rem;
color: var(--text3);
font-family: var(--font-mono);
}
/* ─── Legend inline ─── */
.legend {
display: flex;
gap: 16px;
align-items: center;
}
.legend-item {
display: flex;
align-items: center;
gap: 5px;
font-size: 0.875rem;
color: var(--text3);
font-family: var(--font-mono);
}
.legend-dot {
width: 10px;
height: 10px;
border-radius: 50%;
}
.legend-dot.green { background: var(--green); }
.legend-dot.red { background: var(--red); }
.legend-dot.gray { background: var(--text3); }
.legend.end { margin-left: auto; }
/* ─── Positions / Watchlist views ─── */
.table-wrap {
overflow: auto;
border: 0.5px solid var(--border);
border-radius: var(--radius-sm);
background: var(--bg3);
}
table {
width: 100%;
border-collapse: collapse;
font-size: 1rem;
}
th, td {
padding: 14px 14px;
text-align: left;
border-bottom: 0.5px solid var(--border);
}
th {
font-family: var(--font-mono);
font-size: 0.875rem;
color: var(--text3);
text-transform: uppercase;
letter-spacing: 0.06em;
font-weight: 500;
background: var(--bg4);
position: sticky;
top: 0;
}
tr:hover td {
background: rgba(255,255,255,0.02);
}
td {
color: var(--text);
}
.td-mono {
font-family: var(--font-mono);
}
.td-green { color: var(--green); }
.td-red { color: var(--red); }
.td-blue { color: var(--blue); }
.empty-state {
padding: 40px;
text-align: center;
color: var(--text3);
font-size: 1rem;
}
/* ─── Leaflet overrides ─── */
#app .leaflet-container {
background: var(--bg3);
font-family: var(--font-mono);
}
#app .leaflet-popup-content-wrapper {
background: var(--bg2);
color: var(--text);
border: 0.5px solid var(--border);
border-radius: var(--radius-sm);
}
#app .leaflet-popup-tip {
background: var(--bg2);
}
/* ─── Sparklines ─── */
.sparkline {
display: flex;
align-items: flex-end;
gap: 2px;
height: 32px;
margin-top: 6px;
}
.spark-bar {
width: 3px;
border-radius: 1px;
background: var(--blue2);
transition: height 0.3s;
}
/* ─── Animations ─── */
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
@keyframes scroll-stats {
0% { transform: translateX(0); }
100% { transform: translateX(-50%); }
}
/* ─── Scrollbar ─── */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--bg4); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text3); }
/* ─── Utilities ─── */
.flex-between {
display: flex;
justify-content: space-between;
align-items: center;
}
.flex-start {
display: flex;
align-items: flex-start;
justify-content: space-between;
}
.flex-row {
display: flex;
align-items: center;
}
.flex-wrap {
flex-wrap: wrap;
}
.gap-6 {
gap: 14px;
}
.gap-8 {
gap: 16px;
}
.text-green { color: var(--green); }
.text-red { color: var(--red); }
.text-blue { color: var(--blue); }
.text-amber { color: var(--amber); }
.text-neutral { color: var(--text3); }
.bg-green { background: var(--green); }
.bg-red { background: var(--red); }
.bg-amber { background: var(--amber); }
.flex-1 { flex: 1; }
.font-mono { font-family: var(--font-mono); }
.text-xs { font-size: 0.875rem; }
.text-sm { font-size: 0.875rem; }
.text-base { font-size: 0.9375rem; }
.text-lg { font-size: 1rem; }
.text-xl { font-size: 1.125rem; }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }
.mb-4 { margin-bottom: 4px; }
.mb-6 { margin-bottom: 6px; }
.mb-8 { margin-bottom: 8px; }
.mt-4 { margin-top: 4px; }
.mt-6 { margin-top: 6px; }
.ml-auto { margin-left: auto; }
.divider {
height: 1px;
background: var(--border);
margin: 8px 0;
}
.empty-state-sm {
padding: 16px;
text-align: center;
color: var(--text3);
font-size: 1rem;
}
/* Map popup */
.map-popup {
font-family: var(--font-sans);
font-size: 0.9375rem;
color: var(--text);
max-width: 200px;
}
.map-popup-cat {
font-size: 0.875rem;
color: var(--text3);
font-family: var(--font-mono);
margin-bottom: 4px;
text-transform: uppercase;
}
.map-popup-q {
font-weight: 600;
margin-bottom: 4px;
line-height: 1.3;
}
.map-popup-prices {
display: flex;
gap: 16px;
font-family: var(--font-mono);
font-size: 0.9375rem;
}
.map-label-text {
color: var(--text2);
font-family: var(--font-mono);
font-size: 0.875rem;
text-shadow: 0 1px 2px #000;
}
/* ─── Auth Modal ─── */
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(4px);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
opacity: 1;
transition: opacity 0.2s ease;
}
.modal-overlay.hidden {
display: none;
}
.modal {
background: var(--bg2);
border: 0.5px solid var(--border);
border-radius: var(--radius);
width: 100%;
max-width: 420px;
/* No box-shadow on dark themes — rely on border + backdrop blur for depth */
overflow: hidden;
}
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px;
border-bottom: 0.5px solid var(--border);
}
.modal-tabs {
display: flex;
gap: 4px;
}
.modal-tab {
background: transparent;
border: none;
color: var(--text2);
font-family: var(--font-sans);
font-size: 0.9375rem;
font-weight: 500;
padding: 8px 16px;
border-radius: var(--radius-sm);
cursor: pointer;
transition: background 0.15s, color 0.15s;
}
.modal-tab:hover {
color: var(--text);
}
.modal-tab.active {
background: var(--bg3);
color: var(--text);
}
.modal-close {
background: transparent;
border: none;
color: var(--text2);
font-size: 1.125rem;
cursor: pointer;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-sm);
transition: background 0.15s, color 0.15s;
}
.modal-close:hover {
background: var(--bg3);
color: var(--text);
}
.modal-body {
padding: 20px;
}
.modal-form {
display: none;
flex-direction: column;
gap: 16px;
}
.modal-form.active {
display: flex;
}
.form-group {
display: flex;
flex-direction: column;
gap: 6px;
}
.form-group label {
font-size: 0.875rem;
color: var(--text2);
font-family: var(--font-mono);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.form-group input {
background: var(--bg3);
border: 0.5px solid var(--border2);
border-radius: var(--radius-sm);
padding: 12px 14px;
color: var(--text);
font-size: 0.9375rem;
font-family: var(--font-sans);
outline: none;
transition: border-color 0.15s;
}
.form-group input:focus {
border-color: var(--blue2);
}
.form-group input::placeholder {
color: var(--text3);
}
.form-error {
font-size: 0.875rem;
color: var(--red);
font-family: var(--font-mono);
min-height: 18px;
}
.modal-submit {
background: #2563eb;
border: none;
color: #fff;
font-family: var(--font-sans);
font-size: 0.9375rem;
font-weight: 600;
padding: 12px;
border-radius: var(--radius-sm);
cursor: pointer;
transition: opacity 0.15s;
margin-top: 4px;
}
.modal-submit:hover {
opacity: 0.9;
}
/* ─── Telegram Modal ─── */
.modal-title {
display: flex;
align-items: center;
gap: 10px;
font-size: 1rem;
font-weight: 600;
color: var(--text);
}
.modal-title-icon {
font-size: 1.125rem;
}
.form-hint {
font-size: 0.8125rem;
color: var(--text3);
line-height: 1.4;
}
.form-hint a {
color: var(--blue);
text-decoration: none;
}
.form-hint a:hover {
text-decoration: underline;
}
.toggle-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.toggle-switch {
position: relative;
display: inline-block;
width: 44px;
height: 24px;
cursor: pointer;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.toggle-slider {
position: absolute;
inset: 0;
background: var(--bg4);
border-radius: 24px;
transition: background 0.2s;
border: 0.5px solid var(--border);
}
.toggle-slider::before {
content: '';
position: absolute;
height: 18px;
width: 18px;
left: 2px;
bottom: 2px;
background: var(--text2);
border-radius: 50%;
transition: transform 0.2s, background 0.2s;
}
.toggle-switch input:checked + .toggle-slider {
background: var(--blue2);
border-color: var(--blue);
}
.toggle-switch input:checked + .toggle-slider::before {
transform: translateX(20px);
background: var(--text);
}
.form-status {
font-size: 0.875rem;
font-family: var(--font-mono);
min-height: 18px;
color: var(--text2);
}
.form-status.success {
color: var(--green);
}
.form-status.error {
color: var(--red);
}
.form-actions {
display: flex;
gap: 10px;
margin-top: 4px;
}
.modal-submit--secondary {
background: var(--bg3);
color: var(--text);
border: 0.5px solid var(--border2);
}
.modal-submit--secondary:hover {
background: var(--bg4);
opacity: 1;
}
/* ─── Telegram Instructions ─── */
.telegram-instructions {
display: flex;
flex-direction: column;
gap: 12px;
margin-bottom: 20px;
padding-bottom: 16px;
border-bottom: 0.5px solid var(--border);
}
.instruction-step {
display: flex;
gap: 12px;
align-items: flex-start;
}
.step-num {
width: 24px;
height: 24px;
border-radius: 50%;
background: var(--blue3);
color: var(--blue);
font-size: 0.8125rem;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
margin-top: 2px;
}
.step-body {
flex: 1;
}
.step-body strong {
display: block;
font-size: 0.875rem;
font-weight: 600;
color: var(--text);
margin-bottom: 2px;
}
.step-body p {
font-size: 0.8125rem;
color: var(--text2);
line-height: 1.5;
margin: 0;
}
.step-body a {
color: var(--blue);
text-decoration: none;
}
.step-body a:hover {
text-decoration: underline;
}
.step-body code {
background: var(--bg3);
padding: 1px 5px;
border-radius: 4px;
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--text);
}
/* ─── Auth Indicator ─── */
.auth-indicator {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--bg3);
border: 0.5px solid var(--border2);
color: var(--text2);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
padding: 0;
flex-shrink: 0;
transition: color 0.15s, border-color 0.15s, background 0.2s;
}
.auth-indicator::after {
content: '';
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--red);
display: block;
transition: background 0.2s;
}
.auth-indicator.logged-in::after {
background: var(--green);
}
/* ─── Stats Carousel Track ─── */
.stats-track {
display: flex;
align-items: center;
gap: 20px;
flex: 1;
}
/* Duplicate stats are only needed for the mobile infinite-scroll animation */
.stats-track .legend.end ~ .stat,
.stats-track .legend.end ~ .legend {
display: none;
}
/* ─── Lazy loading sentinel ─── */
.signals-sentinel {
padding: 12px;
text-align: center;
color: var(--text3);
font-family: var(--font-mono);
font-size: 0.875rem;
}
/* ─── Trend Select ─── */
#filter-trend {
min-width: 170px;
background: var(--bg3);
border: 0.5px solid var(--amber2);
color: var(--amber);
}
#filter-trend:focus {
border-color: var(--amber);
}
#filter-trend option {
background: var(--bg2);
color: var(--text);
}
/* ─── Trend Badges ─── */
.trend-badge {
font-size: 0.75rem;
font-weight: 600;
padding: 2px 6px;
border-radius: 4px;
font-family: var(--font-mono);
letter-spacing: 0.04em;
margin-left: 8px;
}
.trend-hot {
background: rgba(240, 160, 32, 0.15);
color: var(--amber);
border: 0.5px solid var(--amber2);
}
.trend-bull {
background: var(--green3);
color: var(--green);
border: 0.5px solid var(--green2);
}
.trend-bear {
background: var(--red3);
color: var(--red);
border: 0.5px solid var(--red2);
}
.trend-volatile {
background: rgba(74, 158, 255, 0.15);
color: var(--blue);
border: 0.5px solid var(--blue2);
}
/* ─── Responsive ─── */
@media (max-width: 1024px) {
* {
scrollbar-width: none;
-ms-overflow-style: none;
}
*::-webkit-scrollbar {
display: none;
}
.dashboard-grid {
grid-template-columns: 1fr;
grid-template-rows: auto auto auto;
}
.signals-panel {
grid-row: auto;
grid-column: auto;
max-height: 400px;
}
.map-panel {
grid-row: auto;
grid-column: auto;
min-height: 300px;
}
.detail-panel {
grid-row: auto;
grid-column: auto;
}
}
@media (max-width: 640px) {
.layout {
grid-template-columns: 0 1fr;
grid-template-rows: auto 1fr;
}
.sidebar { display: none; }
/* ── Detail: header stacks, metrics row below ── */
.detail-header {
flex-direction: column;
gap: 8px;
margin-bottom: 8px;
}
.detail-metrics {
width: 100%;
justify-content: flex-start;
}
.metric {
text-align: left;
}
/* ── Outcomes: AI box full-width, chart full-width below ── */
.outcomes-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-bottom: 10px;
}
.outcomes-row .ai-box {
grid-column: 1 / -1;
}
.outcomes-row .chart-container {
grid-column: 1 / -1;
height: 130px;
max-height: 130px;
min-height: 0;
}
/* ── Simulator: kelly → label → input → buttons (2-col grid) ── */
.sim-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
align-items: center;
}
.sim-row .kelly-note {
grid-column: 1 / -1;
border-left: 2px solid var(--border2);
padding: 6px 10px;
}
.sim-row .sim-label {
grid-column: 1 / -1;
font-size: 0.875rem;
}
.sim-row .sim-input {
grid-column: 1 / -1;
width: 100%;
min-width: 0;
}
.sim-row .sim-btn-yes,
.sim-row .sim-btn-no {
width: 100%;
padding: 10px 8px;
font-size: 0.8125rem;
white-space: nowrap;
text-align: center;
}
.sim-row .sim-disclaimer {
grid-column: 1 / -1;
font-size: 0.75rem;
}
.desktop-only { display: none !important; }
.mobile-only { display: initial; }
.model-badge { display: none; }
.badge-full { display: none; }
.badge-abbr { display: inline; }
/* Topbar becomes two rows */
.topbar {
flex-wrap: wrap;
padding: 8px 12px;
gap: 8px;
min-height: auto;
height: auto;
}
.topbar-logo {
position: static;
height: auto;
order: 0;
flex: 1;
}
.topbar-actions {
order: 0;
margin-left: 0;
gap: 10px;
}
/* Stats row with infinite scroll */
.topbar-stats {
order: 1;
width: 100%;
flex: none;
display: flex;
align-items: center;
overflow: hidden;
}
.topbar-stats .live-badge {
display: none;
}
.stats-track {
display: flex;
align-items: center;
gap: 24px;
width: max-content;
animation: scroll-stats 20s linear infinite;
flex: none;
mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
-webkit-mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
}
.stats-track:hover {
animation-play-state: paused;
}
.topbar-stats .stat {
gap: 8px;
padding: 4px 0;
flex-shrink: 0;
}
.topbar-stats .stat-label {
font-size: 0.75rem;
}
.topbar-stats .stat-val {
font-size: 0.875rem;
}
.topbar-stats .stat-delta {
font-size: 0.75rem;
}
.topbar-stats .legend {
display: none;
}
/* Restore duplicate stats for the scroll animation (legend stays hidden) */
.stats-track .legend.end ~ .stat {
display: flex;
}
/* Dashboard grid scrolls instead of stretching to fill viewport */
.dashboard-grid {
height: auto;
}
/* Remove fixed heights on panels so collapsed state can fully shrink */
.map-panel {
min-height: 250px;
}
.signals-panel {
max-height: none;
}
.panel.collapsed {
min-height: 0;
max-height: none;
}
/* Mobile icon buttons */
#btn-telegram-mobile {
color: var(--blue);
background: var(--blue3);
border-color: var(--blue2);
}
#btn-notif,
#btn-auth-mobile {
display: flex;
}
.topbar-logo .logo-text {
font-size: 1rem;
}
/* Map panel header: title + toggle on row 1, legend right-aligned on row 2 */
#panel-map .panel-header {
flex-wrap: wrap;
gap: 6px 0;
}
#panel-map .panel-title {
flex: 1;
}
.map-legend {
width: 100%;
margin: 0;
justify-content: flex-end;
order: 1;
}
/* Sticky signals header — stays below topbar while list scrolls */
#panel-signals .panel-header {
position: sticky;
top: 0;
z-index: 10;
background: var(--bg2);
}
/* Detail is shown inline in mobile — hide the separate panel */
#panel-detail {
display: none;
}
/* Inline market detail expansion inside signals list */
.market-card-detail {
background: var(--bg3);
border: 0.5px solid var(--blue2);
border-radius: var(--radius-sm);
padding: 14px;
display: flex;
flex-direction: column;
gap: 12px;
}
}