Files
quant-trading/web/src/client/styles.css
Gahow Wang c2882ae4cf fix(live): remount strategy detail when switching focused strategy
Keying LiveStrategyDetail by strategy name resets its child state (trade-log
pagination), so switching strategies no longer keeps the previous page index.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 00:17:09 +08:00

2475 lines
38 KiB
CSS

:root {
color: #e7edf5;
background: #080a0e;
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-synthesis: none;
text-rendering: optimizeLegibility;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-width: 320px;
background:
linear-gradient(180deg, rgba(23, 28, 36, 0.95), rgba(8, 10, 14, 1) 360px),
#080a0e;
}
button,
input,
select {
font: inherit;
}
button {
cursor: pointer;
}
.shell {
width: min(1680px, calc(100% - 28px));
margin: 0 auto;
padding: 18px 0 28px;
}
.topbar,
.metrics,
.workspace,
.panelHeader,
.stockForm,
.watchlist,
.infoGrid,
.insightGrid,
.quoteLine,
.configRows,
.fundTable {
display: grid;
gap: 12px;
}
.topbar {
grid-template-columns: minmax(0, 1fr) auto auto;
align-items: center;
min-height: 58px;
padding: 6px 0 16px;
margin-bottom: 22px;
border-bottom: 1px solid #1d2530;
}
.eyebrow {
margin: 0 0 3px;
color: #7f8da0;
font-size: 11px;
font-weight: 850;
letter-spacing: 0;
text-transform: uppercase;
}
h1,
h2,
p {
margin: 0;
}
h1 {
color: #f4f7fb;
font-size: clamp(24px, 2.8vw, 38px);
line-height: 1.06;
letter-spacing: 0;
}
h2 {
color: #f0f4fa;
font-size: 15px;
letter-spacing: 0;
}
.iconText,
.iconButton,
.ghostIcon,
.smallButton,
.tagChip,
.toolButton,
.segmented button {
border-radius: 6px;
min-height: 36px;
}
.iconText,
.smallButton {
border: 1px solid #2c74b8;
background: #155f9f;
color: #fff;
font-weight: 850;
}
.iconText {
display: inline-flex;
align-items: center;
gap: 8px;
min-height: 38px;
padding: 0 14px;
}
.iconText:disabled {
opacity: 0.65;
}
.smallButton {
padding: 0 11px;
}
.iconButton,
.ghostIcon {
width: 40px;
height: 40px;
display: inline-grid;
place-items: center;
}
.iconButton {
border: 1px solid #208c6c;
background: #14785e;
color: #fff;
}
.ghostIcon {
border: 1px solid #283241;
background: #111821;
color: #91a0b3;
}
.alert {
border: 1px solid #7a2b34;
background: #251015;
color: #ff9aa5;
padding: 11px 13px;
margin-bottom: 14px;
border-radius: 6px;
}
.statusBar {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: -4px 0 14px;
}
.loadState {
border: 1px solid #202936;
border-radius: 999px;
background: #0d1219;
color: #91a0b3;
padding: 6px 10px;
font-size: 12px;
font-weight: 850;
}
.loadState.loading {
border-color: #2e79c8;
color: #9dd3ff;
background: #102235;
}
.loadState.done {
border-color: #17654e;
color: #74e4bd;
background: #10281f;
}
.loadState.error {
border-color: #7a2b34;
color: #ff99a1;
background: #2a1117;
}
.metrics {
grid-template-columns: repeat(4, minmax(0, 1fr));
margin-bottom: 14px;
}
.metric,
.panel {
background: #10151d;
border: 1px solid #202936;
border-radius: 8px;
box-shadow: 0 10px 28px rgba(0, 0, 0, 0.18);
}
.metric {
min-height: 78px;
padding: 13px 14px;
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: auto auto;
gap: 5px 10px;
align-content: center;
}
.metric svg {
grid-row: 1 / 3;
color: #d5a44b;
}
.metric span,
.panelHeader p,
.panelHeader span,
.empty,
.hint,
.watchItem span,
.configRows span,
.cacheMeta {
color: #8390a2;
font-size: 12px;
}
.metric strong {
color: #f4f7fb;
font-size: 18px;
line-height: 1.1;
}
.workspace {
grid-template-columns: 330px minmax(0, 1fr);
align-items: start;
}
.sidebar,
.detailStack {
min-width: 0;
}
.panel {
padding: 14px;
}
.sidebar {
position: sticky;
top: 12px;
}
.panelHeader {
grid-template-columns: minmax(0, 1fr) auto;
align-items: start;
margin-bottom: 12px;
}
.chartHeader {
align-items: center;
margin-bottom: 10px;
}
.cacheMeta {
display: inline-flex;
align-items: center;
gap: 6px;
white-space: nowrap;
}
.sidebarSectionLabel {
font-size: 11px;
color: #7f8da0;
font-weight: 800;
letter-spacing: 0;
text-transform: uppercase;
}
.sidebarHint {
margin: 0;
font-size: 11px;
color: #6f7c8f;
line-height: 1.4;
}
.stockForm {
display: flex;
flex-direction: column;
gap: 6px;
margin-bottom: 14px;
padding: 10px;
background: #0c1118;
border: 1px solid #1d2530;
border-radius: 7px;
}
.stockFormRow {
display: flex;
gap: 6px;
min-width: 0;
}
.stockFormRow > .ghostInput {
flex: 1 1 0;
min-width: 0;
width: 0;
}
.stockFormSubmitRow .ghostButton {
flex-shrink: 0;
}
.stockFormSubmit {
justify-content: center;
}
.sidebarSection {
display: flex;
flex-direction: column;
gap: 6px;
padding: 10px;
background: #0c1118;
border: 1px solid #1d2530;
border-radius: 7px;
margin-bottom: 14px;
min-width: 0;
}
.tagFilterSection .tagFilter {
margin-bottom: 0;
}
input {
width: 100%;
min-height: 40px;
border: 1px solid #283241;
border-radius: 6px;
padding: 0 11px;
color: #e7edf5;
background: #0b1017;
}
input[type="checkbox"] {
width: 16px;
height: 16px;
min-height: 16px;
padding: 0;
margin: 0;
flex: 0 0 auto;
}
input::placeholder {
color: #536173;
}
input:focus {
outline: 2px solid rgba(46, 121, 200, 0.45);
border-color: #2e79c8;
}
.tagFilter {
display: flex;
flex-wrap: wrap;
gap: 7px;
margin-bottom: 12px;
}
.tagChip {
border: 1px solid #283241;
background: #0d131b;
color: #a8b3c2;
display: inline-flex;
align-items: center;
gap: 5px;
padding: 0 9px;
font-size: 12px;
font-weight: 800;
}
.tagChip.active {
border-color: #2e79c8;
background: #112943;
color: #d5ebff;
}
.watchlist {
gap: 6px;
}
.watchItem {
width: 100%;
display: flex;
flex-direction: column;
gap: 6px;
text-align: left;
border: 1px solid #1d2530;
background: #0c1118;
border-radius: 7px;
padding: 9px 10px;
transition: border-color 0.12s, background 0.12s;
min-width: 0;
}
.watchItem:hover {
border-color: #2c3a4f;
background: #0d141d;
}
.watchItem.selected {
border-color: #2c74b8;
background: rgba(77, 182, 255, 0.07);
}
.watchItem.editing {
border-color: #2c74b8;
}
.watchItemHead {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 8px;
cursor: pointer;
min-width: 0;
}
.watchItemHead:focus-visible {
outline: 2px solid rgba(46, 121, 200, 0.45);
outline-offset: 2px;
border-radius: 4px;
}
.watchItemTitle {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
}
.watchItemTitle strong {
color: #f3f6fb;
font-size: 13px;
font-weight: 800;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.watchItemTitle span {
color: #8390a2;
font-size: 11px;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.watchItemActions {
display: inline-flex;
align-items: center;
gap: 4px;
flex-shrink: 0;
}
.watchItemTags {
min-width: 0;
}
.watchItemTagEdit {
display: flex;
gap: 6px;
align-items: center;
}
.watchItemTagEdit .ghostInput {
flex: 1 1 0;
min-width: 0;
}
.ghostIconButton {
width: 26px;
height: 26px;
display: inline-grid;
place-items: center;
border: 1px solid #1d2530;
background: transparent;
color: #7f8da0;
border-radius: 5px;
cursor: pointer;
transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.ghostIconButton:hover {
border-color: #2c74b8;
background: #11202f;
color: #cfe6ff;
}
.ghostIconButton.danger:hover {
border-color: #7a2b34;
background: #2a1117;
color: #ff9aa5;
}
.ghostButtonPrimary {
border-color: #2c74b8;
background: #112943;
color: #cfe6ff;
}
.ghostButtonPrimary:hover:not(:disabled) {
border-color: #4d97e0;
background: #163556;
color: #ffffff;
}
.tagList {
display: flex;
flex-wrap: wrap;
gap: 5px;
}
.tagList em {
border-radius: 999px;
background: #10281f;
color: #7bdcbf;
font-size: 11px;
font-style: normal;
font-weight: 850;
padding: 2px 7px;
}
.tagList.muted {
color: #617083;
}
.detailStack {
display: grid;
gap: 14px;
}
.chartPanel {
background: #070b11;
border-color: #1a2230;
padding: 14px;
}
.chartPanel .eyebrow,
.chartPanel .cacheMeta,
.chartPanel .panelHeader span {
color: #7f8da0;
}
.chartControls {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 5px;
margin: -4px 0 8px;
}
.segmented {
display: inline-grid;
grid-template-columns: repeat(4, 28px);
gap: 2px;
border: 1px solid #222c3a;
border-radius: 6px;
padding: 2px;
background: #080d13;
}
.segmented button,
.toolButton {
border: 0;
background: #111923;
color: #9caabc;
font-size: 11px;
font-weight: 850;
min-height: 26px;
}
.segmented button.active {
background: #d5a44b;
color: #0b0f15;
}
.toolButton {
width: 28px;
display: inline-grid;
place-items: center;
border-radius: 6px;
}
.chartWrap {
display: grid;
gap: 10px;
}
.tickerTape {
min-height: 36px;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 7px;
color: #a8b3c2;
font-size: 12px;
}
.tickerTape strong {
color: #f7fafc;
font-size: 24px;
line-height: 1;
margin-right: 2px;
}
.tickerTape span {
border: 1px solid #1d2632;
border-radius: 6px;
background: #0d131b;
padding: 5px 8px;
font-weight: 850;
}
.tickerTape .up {
color: #ff6b72;
border-color: rgba(239, 83, 80, 0.3);
background: rgba(239, 83, 80, 0.1);
}
.tickerTape .down {
color: #3bd6aa;
border-color: rgba(38, 166, 154, 0.3);
background: rgba(38, 166, 154, 0.1);
}
.maToggleBar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 6px;
margin-top: -2px;
}
.maToggleBar button {
min-height: 27px;
border: 1px solid #1d2632;
border-radius: 6px;
background: #0d131b;
color: #8f9caf;
display: inline-flex;
align-items: center;
gap: 6px;
padding: 0 8px;
font-size: 11px;
font-weight: 850;
}
.maToggleBar button.active {
border-color: #334256;
color: #f0f5fb;
background: #121b26;
}
.maToggleBar i {
width: 14px;
height: 2px;
border-radius: 999px;
opacity: 0.45;
}
.maToggleBar button.active i {
opacity: 1;
}
.libraryChart {
width: 100%;
min-height: 390px;
overflow: hidden;
border: 1px solid #1a2230;
border-radius: 7px;
background: #070b11;
}
.chartEmpty {
min-height: 340px;
display: grid;
place-items: center;
color: #7f8da0;
border: 1px solid #1a2230;
border-radius: 7px;
background: #070b11;
}
.dayDetail {
border: 1px solid #1a2230;
border-radius: 7px;
background: #0a0f16;
padding: 9px;
display: grid;
gap: 8px;
}
.dayDetail.empty {
min-height: 42px;
place-items: center;
color: #7f8da0;
font-size: 12px;
font-weight: 800;
}
.dayDetailTitle {
display: flex;
align-items: center;
gap: 8px;
}
.dayDetailTitle strong {
color: #f0f5fb;
font-size: 13px;
}
.dayDetailTitle span {
border-radius: 999px;
padding: 3px 8px;
font-size: 11px;
font-weight: 850;
}
.dayDetailTitle .up {
color: #ff737a;
background: rgba(239, 83, 80, 0.12);
}
.dayDetailTitle .down {
color: #4be2b8;
background: rgba(38, 166, 154, 0.12);
}
.dayDetailGrid {
display: grid;
grid-template-columns: repeat(12, minmax(86px, 1fr));
gap: 6px;
overflow-x: auto;
}
.dayDetailGrid .signal {
padding: 7px 8px;
gap: 2px;
}
.dayDetailGrid .signal span {
font-size: 10px;
}
.dayDetailGrid .signal strong {
font-size: 12px;
}
.infoGrid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.insightGrid {
grid-template-columns: minmax(360px, 0.95fr) minmax(0, 1.25fr);
}
.hint {
margin-top: 8px;
}
.configRows {
grid-template-columns: 92px minmax(0, 1fr);
gap: 8px 12px;
align-items: baseline;
}
.configRows strong {
min-width: 0;
overflow-wrap: anywhere;
color: #e7edf5;
font-size: 13px;
}
.report {
min-width: 0;
}
.quoteLine {
grid-template-columns: repeat(3, minmax(0, 1fr));
margin-bottom: 12px;
}
.quoteLine span {
border: 1px solid #202936;
border-radius: 7px;
background: #0d1219;
min-height: 34px;
display: grid;
place-items: center;
color: #dfe7f1;
font-size: 12px;
font-weight: 850;
text-align: center;
padding: 0 8px;
}
.fundTable {
grid-template-columns: 0.7fr repeat(4, minmax(0, 1fr));
gap: 0;
overflow: hidden;
border: 1px solid #202936;
border-radius: 7px;
}
.fundTable > * {
min-height: 36px;
display: grid;
align-items: center;
padding: 0 10px;
border-bottom: 1px solid #202936;
color: #cfd8e5;
font-size: 12px;
}
.fundTable > *:nth-last-child(-n + 5) {
border-bottom: 0;
}
.fundHead {
background: #121923;
color: #8d9aad;
font-weight: 850;
}
.fundTable strong {
color: #f2f6fb;
font-size: 12px;
}
.relatedGrid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 9px;
}
.coverageRows {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 9px;
}
.signal {
min-width: 0;
border: 1px solid #202936;
border-radius: 7px;
background: #0d1219;
padding: 10px;
display: grid;
gap: 4px;
}
.signal span {
color: #8390a2;
font-size: 11px;
}
.signal strong {
min-width: 0;
overflow-wrap: anywhere;
color: #f0f5fb;
font-size: 13px;
}
.riskFlags {
grid-column: 1 / -1;
border: 1px solid #61451d;
border-radius: 7px;
background: #21180c;
color: #e3ba72;
padding: 10px;
font-size: 12px;
font-weight: 850;
}
.mentionList {
grid-column: 1 / -1;
border: 1px solid #202936;
border-radius: 7px;
background: #0d1219;
padding: 10px;
display: grid;
gap: 7px;
}
.mentionList > strong {
color: #f0f5fb;
font-size: 12px;
}
.mentionList a {
color: #aebbd0;
font-size: 12px;
line-height: 1.4;
text-decoration: none;
}
.mentionList a:hover {
color: #d5a44b;
}
.mentionList a span {
color: #6f7f94;
font-size: 10px;
font-weight: 850;
margin-right: 6px;
text-transform: uppercase;
}
.analysisPanel {
min-width: 0;
}
.analysisScore {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 10px;
margin-bottom: 10px;
}
.analysisScore strong {
color: #f5f8fc;
font-size: 36px;
line-height: 1;
}
.analysisScore em {
color: #8390a2;
font-size: 12px;
font-style: normal;
font-weight: 800;
}
.analysisSummary {
color: #c8d2df;
font-size: 13px;
line-height: 1.55;
margin-bottom: 12px;
}
.tradePlan {
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: 8px;
border: 1px solid #273246;
border-radius: 7px;
background: #0a1018;
padding: 10px;
margin-bottom: 12px;
}
.tradePlan p,
.tradePlan em {
grid-column: 1 / -1;
color: #c8d2df;
font-size: 12px;
line-height: 1.45;
}
.tradePlan em {
color: #e6c071;
font-style: normal;
}
.marketContext {
display: flex;
flex-wrap: wrap;
gap: 7px;
margin-bottom: 12px;
}
.marketContext span {
border: 1px solid #273246;
border-radius: 999px;
background: #0d1219;
color: #aebbd0;
padding: 5px 9px;
font-size: 11px;
font-weight: 800;
}
.factorList {
display: grid;
gap: 8px;
}
.factorRow {
display: grid;
grid-template-columns: minmax(0, 1fr) 42px;
gap: 10px;
align-items: center;
border-top: 1px solid #202936;
padding-top: 8px;
}
.factorRow div {
min-width: 0;
display: grid;
gap: 2px;
}
.factorRow strong {
color: #eef4fb;
font-size: 12px;
}
.factorRow span {
color: #8390a2;
font-size: 12px;
line-height: 1.45;
}
.factorRow b {
border-radius: 7px;
background: #112943;
color: #9dd3ff;
min-height: 30px;
display: grid;
place-items: center;
}
.riskNotes {
display: flex;
flex-wrap: wrap;
gap: 7px;
margin-top: 12px;
}
.riskNotes span {
border: 1px solid #202936;
border-radius: 999px;
background: #0d1219;
color: #9aa8ba;
padding: 5px 9px;
font-size: 11px;
font-weight: 800;
}
.badge {
border-radius: 999px;
padding: 5px 10px;
font-size: 12px;
font-weight: 850;
}
.buy_watch {
color: #74e4bd;
background: #10281f;
}
.hold {
color: #e6c071;
background: #21180c;
}
.avoid {
color: #ff99a1;
background: #2a1117;
}
@media (max-width: 1180px) {
.workspace,
.infoGrid,
.insightGrid {
grid-template-columns: 1fr;
}
.sidebar {
position: static;
}
.relatedGrid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.coverageRows {
grid-template-columns: 1fr;
}
.tradePlan {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 760px) {
.shell {
width: min(100% - 16px, 720px);
padding-top: 14px;
}
.topbar,
.metrics,
.quoteLine {
grid-template-columns: 1fr;
}
.stockForm {
grid-template-columns: 1fr auto;
}
.stockForm input,
.stockForm input:first-child,
.stockForm input:nth-child(3) {
grid-column: 1 / -1;
}
.stockForm .iconButton {
width: 100%;
grid-column: 1 / -1;
}
.cacheMeta {
white-space: normal;
justify-content: start;
}
.chartControls {
justify-content: start;
}
.libraryChart {
min-height: 360px;
}
.dayDetailGrid {
grid-template-columns: repeat(12, minmax(82px, 1fr));
}
.relatedGrid {
grid-template-columns: 1fr;
}
.tradePlan {
grid-template-columns: 1fr;
}
.fundTable {
grid-template-columns: repeat(5, minmax(86px, 1fr));
overflow-x: auto;
}
}
/* ---------------------------------------------------------------------------
Tab navigation
--------------------------------------------------------------------------- */
.topbarTabs {
display: flex;
gap: 4px;
background: #131820;
border-radius: 8px;
padding: 3px;
}
.tabButton {
background: transparent;
border: none;
color: #7f8da0;
font-size: 13px;
font-weight: 600;
padding: 6px 16px;
border-radius: 6px;
transition: all 0.15s;
}
.tabButton.active {
background: #1d2530;
color: #f0f4fa;
}
.tabButton:hover:not(.active) {
color: #b0b8c4;
}
/* ---------------------------------------------------------------------------
Strategy Page
--------------------------------------------------------------------------- */
.strategyPage {
padding-top: 8px;
}
.strategyLayout {
display: grid;
grid-template-columns: minmax(340px, 360px) minmax(0, 1fr);
gap: 16px;
align-items: start;
}
.strategySelector {
position: sticky;
top: 16px;
max-height: calc(100vh - 100px);
overflow-y: auto;
overflow-x: hidden;
display: flex;
flex-direction: column;
gap: 12px;
padding: 14px !important;
}
.strategyConfig {
display: flex;
flex-direction: column;
gap: 8px;
}
.configRow {
display: grid;
grid-template-columns: 82px minmax(0, 1fr);
align-items: center;
gap: 8px;
}
.configRow label {
font-size: 12px;
color: #7f8da0;
white-space: nowrap;
}
.configRow input[type="number"],
.configRow select {
width: 100%;
min-width: 0;
min-height: 34px;
background: #131820;
border: 1px solid #1d2530;
color: #e7edf5;
border-radius: 5px;
padding: 5px 8px;
font-size: 13px;
}
.configRow .segmented.small {
width: 100%;
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.configRow .segmented.small button {
min-height: 28px;
padding: 4px 8px;
font-size: 12px;
}
.precomputedHeader {
display: flex;
flex-direction: column;
gap: 6px;
padding-bottom: 10px;
border-bottom: 1px solid #1d2530;
}
.precomputedHeaderRow {
display: grid;
grid-template-columns: 82px minmax(0, 1fr);
align-items: center;
gap: 8px;
}
.precomputedHeaderRow label {
font-size: 12px;
color: #7f8da0;
}
.precomputedHint {
margin: 0;
font-size: 11px;
color: #6f7c8f;
font-weight: 700;
letter-spacing: 0;
}
.scenarioPicker {
display: flex;
flex-direction: column;
gap: 6px;
}
.scenarioPickerLabel {
font-size: 11px;
color: #7f8da0;
font-weight: 800;
letter-spacing: 0;
text-transform: uppercase;
}
.scenarioOptions {
display: flex;
flex-direction: column;
gap: 6px;
}
.scenarioOption {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 2px;
background: #0c1118;
border: 1px solid #1d2530;
border-radius: 6px;
padding: 8px 10px;
text-align: left;
cursor: pointer;
transition: border-color 0.12s, background 0.12s;
}
.scenarioOption strong {
color: #e7edf5;
font-size: 12px;
font-weight: 800;
}
.scenarioOption span {
color: #7f8da0;
font-size: 11px;
font-weight: 700;
}
.scenarioOption:hover {
border-color: #2c3a4f;
}
.scenarioOption.active {
border-color: #2c74b8;
background: rgba(77, 182, 255, 0.07);
}
.scenarioOption.active strong {
color: #cfe6ff;
}
.quickPicks {
display: flex;
flex-direction: column;
gap: 6px;
}
.quickPicksLabel {
font-size: 11px;
color: #7f8da0;
font-weight: 800;
letter-spacing: 0;
text-transform: uppercase;
}
.quickPicksRow {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.quickPickButton {
display: inline-flex;
align-items: center;
gap: 4px;
background: #14304a;
border: 1px solid #1d4571;
color: #cfe6ff;
border-radius: 5px;
padding: 5px 9px;
font-size: 11px;
font-weight: 700;
cursor: pointer;
transition: background 0.12s;
}
.quickPickButton:hover {
background: #1c3f5e;
}
.quickPickButton.ghost {
background: transparent;
border-color: #283241;
color: #91a0b3;
}
.quickPickButton.ghost:hover {
background: #131820;
}
.strategyList {
display: flex;
flex-direction: column;
gap: 1px;
max-height: 460px;
overflow-y: auto;
border-top: 1px solid #1d2530;
padding-top: 6px;
}
.strategyItem {
display: grid;
grid-template-columns: 26px 16px 10px minmax(0, 1fr) auto auto;
align-items: center;
gap: 6px;
padding: 5px 6px;
border-radius: 5px;
cursor: pointer;
font-size: 12px;
color: #b0b8c4;
transition: background 0.12s;
}
.strategyItem:hover {
background: #1a2030;
}
.strategyItem.selected {
background: #1a2a3d;
color: #f0f4fa;
}
.strategyItem input[type="checkbox"] {
accent-color: #4db6ff;
margin: 0;
width: 14px;
height: 14px;
}
.strategyRank {
font-size: 10px;
font-weight: 800;
color: #6f7c8f;
text-align: center;
letter-spacing: 0;
}
.strategyRank[data-top="1"] {
color: #f3c969;
}
.strategyDot {
width: 8px;
height: 8px;
border-radius: 50%;
border: 1px solid #2a3344;
}
.strategyLabel {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.strategyMetric {
font-size: 11px;
font-weight: 800;
font-variant-numeric: tabular-nums;
}
.strategyMetric.positive {
color: #26a69a;
}
.strategyMetric.negative {
color: #ef5350;
}
.strategyMetricMuted {
font-size: 10px;
font-weight: 700;
color: #7f8da0;
font-variant-numeric: tabular-nums;
min-width: 28px;
text-align: right;
}
.strategyEmpty {
color: #7f8da0;
font-size: 12px;
line-height: 1.45;
padding: 10px 6px;
}
.strategyResults {
display: flex;
flex-direction: column;
gap: 16px;
}
.legendEmpty {
color: #6f7c8f;
font-size: 12px;
font-style: italic;
}
/* Ranking leaderboard */
.rankingPanel {
padding: 14px !important;
}
.rankingWrap {
overflow-x: auto;
border: 1px solid #1d2530;
border-radius: 7px;
background: #0c1118;
margin-top: 6px;
}
.rankingTable {
width: 100%;
border-collapse: collapse;
font-size: 12px;
font-variant-numeric: tabular-nums;
}
.rankingTable th {
text-align: left;
color: #7f8da0;
font-weight: 600;
padding: 8px 10px;
border-bottom: 1px solid #1d2530;
background: #0c1118;
white-space: nowrap;
position: sticky;
top: 0;
}
.rankingTable th.sortable {
cursor: pointer;
user-select: none;
}
.rankingTable th.sortable:hover {
color: #cfe6ff;
}
.rankingTable th.sortable.active {
color: #4db6ff;
display: inline;
}
.rankingTable th.sortable svg {
margin-left: 4px;
vertical-align: middle;
}
.rankingTable td {
padding: 7px 10px;
border-bottom: 1px solid #131820;
color: #b0b8c4;
white-space: nowrap;
}
.rankingTable tbody tr {
cursor: pointer;
}
.rankingTable tbody tr:hover td {
background: rgba(255, 255, 255, 0.025);
}
.rankingTable tbody tr.selected td {
background: rgba(77, 182, 255, 0.06);
color: #f0f4fa;
}
.rankingTable td.positive {
color: #26a69a;
}
.rankingTable td.negative {
color: #ef5350;
}
.rankingTable td:nth-child(2) strong {
display: block;
color: #eef4fb;
}
.rankSub {
display: block;
margin-top: 2px;
color: #6f7c8f;
font-size: 10px;
font-weight: 800;
}
.rankCol {
width: 50px;
text-align: center;
}
.rankBadge {
display: inline-block;
min-width: 26px;
padding: 2px 6px;
border-radius: 4px;
background: #131820;
color: #b0b8c4;
font-size: 11px;
font-weight: 800;
text-align: center;
}
.rankBadge.top {
background: rgba(243, 201, 105, 0.12);
color: #f3c969;
border: 1px solid rgba(243, 201, 105, 0.3);
}
.categoryChip {
display: inline-block;
padding: 2px 8px;
background: #131820;
border: 1px solid #1d2530;
border-radius: 999px;
font-size: 10px;
color: #91a0b3;
font-weight: 700;
}
.emptyState {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 12px;
min-height: 400px;
color: #7f8da0;
text-align: center;
}
.emptyState svg {
opacity: 0.4;
}
/* Equity chart */
.equityChartContainer {
width: 100%;
min-height: 480px;
}
.equityHeader {
display: flex;
justify-content: space-between;
align-items: flex-end;
gap: 12px;
margin-bottom: 6px;
padding-bottom: 10px;
border-bottom: 1px solid #161e2a;
}
.equityTitle {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
}
.equityTitle h2 {
font-size: 16px;
line-height: 1.2;
}
.equityMeta {
display: inline-flex;
align-items: center;
flex-wrap: wrap;
gap: 6px;
font-size: 12px;
font-weight: 700;
color: #8390a2;
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
.equityMetaItem {
padding: 3px 8px;
border: 1px solid #1d2530;
border-radius: 4px;
background: #0c1118;
color: #cfd8e3;
}
.equityMetaSep {
color: #4a5566;
font-weight: 800;
}
.legendRow {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-bottom: 10px;
}
.legendItem {
display: flex;
align-items: center;
gap: 5px;
background: transparent;
border: 1px solid #2a2a4a;
border-radius: 4px;
padding: 3px 8px;
font-size: 11px;
color: #b0b8c4;
cursor: pointer;
transition: all 0.12s;
}
.legendItem.focused {
border-color: #4db6ff;
color: #f0f4fa;
background: rgba(77, 182, 255, 0.08);
}
.legendItem.hidden {
color: #5e6a78;
opacity: 0.62;
}
.legendItem.hidden .legendDot {
background: transparent !important;
border: 1px solid #5e6a78;
}
.benchmarkLegend {
color: #8d98a8;
cursor: default;
}
.benchmarkLegend .legendDot {
border-radius: 2px;
background: #777;
}
.legendDot {
width: 8px;
height: 8px;
border-radius: 50%;
flex-shrink: 0;
}
/* Metrics panel */
.metricsPanel {
padding: 14px !important;
}
.metricsGrid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
margin-bottom: 14px;
}
.focusSummary {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: -4px 0 12px;
}
.focusSummary span {
min-height: 30px;
display: inline-flex;
align-items: center;
gap: 6px;
border: 1px solid #222c3a;
border-radius: 6px;
background: #0d131b;
color: #b8c3d1;
padding: 0 10px;
font-size: 12px;
font-weight: 800;
}
.metricCell {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
padding: 8px 4px;
background: #131820;
border-radius: 6px;
}
.metricValue {
font-size: 16px;
font-weight: 700;
color: #f0f4fa;
}
.metricCell.positive .metricValue {
color: #26a69a;
}
.metricCell.negative .metricValue {
color: #ef5350;
}
.metricLabel {
font-size: 11px;
color: #7f8da0;
}
/* Comparison table */
.comparisonWrap {
overflow-x: auto;
border: 1px solid #1d2530;
border-radius: 7px;
background: #0c1118;
}
.comparisonTable {
width: 100%;
border-collapse: collapse;
font-size: 12px;
}
.comparisonTable th {
text-align: left;
color: #7f8da0;
font-weight: 600;
padding: 8px 10px;
border-bottom: 1px solid #1d2530;
white-space: nowrap;
}
.comparisonTable td {
padding: 9px 10px;
border-bottom: 1px solid #131820;
color: #b0b8c4;
vertical-align: middle;
white-space: nowrap;
}
.comparisonTable tbody tr {
cursor: pointer;
}
.comparisonTable tbody tr:hover td {
background: rgba(255, 255, 255, 0.025);
}
.comparisonTable td:first-child {
min-width: 220px;
white-space: normal;
}
.comparisonTable td:first-child strong,
.comparisonTable td:first-child span {
display: block;
}
.comparisonTable td:first-child strong {
color: #eef4fb;
font-size: 12px;
}
.comparisonTable td:first-child span {
margin-top: 2px;
color: #6f7c8f;
font-size: 10px;
font-weight: 800;
}
.comparisonTable tr.focused td {
color: #f0f4fa;
background: rgba(77, 182, 255, 0.08);
}
.comparisonTable .positive {
color: #26a69a;
}
.comparisonTable .negative {
color: #ef5350;
}
/* Drawdown panel */
.drawdownPanel {
padding: 14px !important;
}
.drawdownTable {
width: 100%;
border-collapse: collapse;
font-size: 12px;
}
.drawdownTable th {
text-align: left;
color: #7f8da0;
font-weight: 600;
padding: 5px 8px;
border-bottom: 1px solid #1d2530;
}
.drawdownTable td {
padding: 5px 8px;
border-bottom: 1px solid #131820;
color: #b0b8c4;
}
.drawdownTable .negative {
color: #ef5350;
}
/* Return heatmap */
.heatmapPanel {
padding: 14px !important;
}
.heatmapContainer {
overflow-x: auto;
}
.heatmapTable {
width: 100%;
border-collapse: collapse;
font-size: 11px;
min-width: 700px;
}
.heatmapTable th {
text-align: center;
color: #7f8da0;
font-weight: 600;
padding: 4px 2px;
border-bottom: 1px solid #1d2530;
}
.heatmapTable td {
text-align: center;
padding: 4px 2px;
color: #e7edf5;
}
.heatmapTable .yearLabel {
font-weight: 600;
color: #b0b8c4;
text-align: left;
padding-left: 6px;
}
.heatCell {
border-radius: 3px;
font-size: 10px;
min-width: 42px;
}
.yearReturn {
font-weight: 700;
font-size: 12px;
}
.yearReturn.positive {
color: #26a69a;
}
.yearReturn.negative {
color: #ef5350;
}
/* ---------------------------------------------------------------------------
Live Page
--------------------------------------------------------------------------- */
.livePage {
padding-top: 8px;
display: flex;
flex-direction: column;
gap: 12px;
}
.liveTopbar {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.ghostInput {
flex: 1 1 200px;
min-width: 160px;
min-height: 32px;
background: #0c1118;
border: 1px solid #1d2530;
color: #e7edf5;
border-radius: 6px;
padding: 4px 10px;
font-size: 12px;
transition: border-color 0.12s, background 0.12s;
}
.ghostInput::placeholder {
color: #5e6a78;
}
.ghostInput:hover {
border-color: #2c3a4f;
}
.ghostInput:focus {
border-color: #2c74b8;
outline: none;
background: #0d141d;
}
.ghostSelectLabel {
display: inline-flex;
align-items: stretch;
gap: 0;
border: 1px solid #1d2530;
border-radius: 6px;
background: #0c1118;
overflow: hidden;
min-height: 32px;
}
.ghostSelectLabel > span {
display: inline-flex;
align-items: center;
padding: 0 8px;
font-size: 11px;
font-weight: 800;
letter-spacing: 0;
color: #7f8da0;
background: #0a0f15;
border-right: 1px solid #1d2530;
text-transform: uppercase;
}
.ghostSelect {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background: transparent;
background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12' fill='none' stroke='%237f8da0' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 5l3 3 3-3'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 10px center;
background-size: 10px;
border: none;
color: #cfd8e3;
padding: 0 26px 0 10px;
font-size: 12px;
font-weight: 700;
cursor: pointer;
outline: none;
}
.ghostSelectLabel:hover {
border-color: #2c3a4f;
}
.ghostSelectLabel:focus-within {
border-color: #2c74b8;
}
.ghostSelect option {
background: #0c1118;
color: #e7edf5;
}
/* Standalone select without the label chip (e.g. pagination size). */
.ghostSelectCompact {
min-height: 28px;
background: #0c1118;
background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12' fill='none' stroke='%237f8da0' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 5l3 3 3-3'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 8px center;
background-size: 10px;
border: 1px solid #1d2530;
border-radius: 5px;
padding: 0 22px 0 8px;
}
.ghostSelectCompact:hover {
border-color: #2c3a4f;
}
.ghostButton {
display: inline-flex;
align-items: center;
gap: 6px;
min-height: 32px;
padding: 0 14px;
border: 1px solid #1d2530;
background: #0c1118;
color: #cfd8e3;
border-radius: 6px;
font-size: 12px;
font-weight: 700;
cursor: pointer;
transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.ghostButton:hover:not(:disabled) {
border-color: #2c74b8;
background: #11202f;
color: #e7edf5;
}
.ghostButton:disabled {
opacity: 0.55;
cursor: not-allowed;
}
.ghostButton.loading svg {
animation: ghostSpin 1s linear infinite;
}
@keyframes ghostSpin {
to { transform: rotate(360deg); }
}
.liveLayout {
display: grid;
grid-template-columns: minmax(320px, 360px) minmax(0, 1fr);
gap: 16px;
align-items: start;
}
.liveSidebar {
position: sticky;
top: 16px;
max-height: calc(100vh - 120px);
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 8px;
padding: 12px !important;
}
.liveList {
display: flex;
flex-direction: column;
gap: 4px;
}
.liveListItem {
display: flex;
flex-direction: column;
gap: 4px;
padding: 8px 10px;
background: #0c1118;
border: 1px solid #1d2530;
border-radius: 6px;
text-align: left;
cursor: pointer;
transition: border-color 0.12s, background 0.12s;
min-width: 0;
overflow: hidden;
}
.liveListItem:hover {
border-color: #2c3a4f;
}
.liveListItem.selected {
border-color: #2c74b8;
background: rgba(77, 182, 255, 0.07);
}
.liveListTitle {
display: flex;
flex-direction: column;
gap: 1px;
min-width: 0;
max-width: 100%;
}
.liveListTitle strong {
color: #eef4fb;
font-size: 13px;
font-weight: 800;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: block;
max-width: 100%;
}
.liveListName {
color: #6f7c8f;
font-size: 10px;
font-weight: 700;
letter-spacing: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: block;
max-width: 100%;
}
.liveListBody {
display: flex;
justify-content: space-between;
align-items: center;
font-variant-numeric: tabular-nums;
}
.liveListValue {
font-size: 14px;
font-weight: 800;
color: #e7edf5;
}
.liveListPnl {
display: inline-flex;
align-items: center;
gap: 2px;
font-size: 12px;
font-weight: 800;
}
.liveListPnl.positive {
color: #26a69a;
}
.liveListPnl.negative {
color: #ef5350;
}
.liveListMeta {
display: flex;
justify-content: space-between;
gap: 8px;
font-size: 10px;
color: #6f7c8f;
font-weight: 700;
}
.liveDetail {
display: flex;
flex-direction: column;
gap: 16px;
}
.liveSummary {
padding: 14px !important;
}
.liveSummaryHead {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 16px;
flex-wrap: wrap;
}
.liveTotalPnl {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 2px;
font-variant-numeric: tabular-nums;
}
.liveTotalPnl strong {
font-size: 22px;
font-weight: 800;
color: #e7edf5;
}
.liveTotalPnl span {
font-size: 12px;
font-weight: 800;
}
.liveTotalPnl.positive strong,
.liveTotalPnl.positive span {
color: #26a69a;
}
.liveTotalPnl.negative strong,
.liveTotalPnl.negative span {
color: #ef5350;
}
.liveSummaryGrid {
margin-top: 14px;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
}
.summaryCell {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
padding: 8px 4px;
background: #131820;
border-radius: 6px;
}
.summaryValue {
font-size: 15px;
font-weight: 700;
color: #f0f4fa;
font-variant-numeric: tabular-nums;
}
.summaryCell.positive .summaryValue {
color: #26a69a;
}
.summaryCell.negative .summaryValue {
color: #ef5350;
}
.summaryLabel {
font-size: 11px;
color: #7f8da0;
}
.liveEquityChart {
width: 100%;
min-height: 280px;
}
.holdingsPanel {
padding: 14px !important;
}
.holdingsTable,
.tradeLogTable {
width: 100%;
border-collapse: collapse;
font-size: 12px;
font-variant-numeric: tabular-nums;
}
.holdingsTable th,
.tradeLogTable th {
text-align: left;
color: #7f8da0;
font-weight: 600;
padding: 7px 10px;
border-bottom: 1px solid #1d2530;
white-space: nowrap;
}
.holdingsTable td,
.tradeLogTable td {
padding: 7px 10px;
border-bottom: 1px solid #131820;
color: #b0b8c4;
white-space: nowrap;
}
.holdingsTable td:first-child strong,
.tradeLogTable td:first-child strong {
color: #eef4fb;
}
.holdingsCashRow td {
background: rgba(255, 255, 255, 0.02);
color: #7f8da0;
}
.tradeAction {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 11px;
font-weight: 800;
}
.tradeAction.buy {
background: rgba(38, 166, 154, 0.15);
color: #26a69a;
border: 1px solid rgba(38, 166, 154, 0.3);
}
.tradeAction.sell {
background: rgba(239, 83, 80, 0.15);
color: #ef5350;
border: 1px solid rgba(239, 83, 80, 0.3);
}
.tradeLogPanel {
padding: 14px !important;
}
.paginationBar {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 8px;
margin-top: 10px;
padding-top: 8px;
border-top: 1px solid #1d2530;
font-size: 12px;
font-variant-numeric: tabular-nums;
}
.paginationRange {
color: #7f8da0;
font-weight: 700;
}
.paginationControls {
display: inline-flex;
align-items: center;
gap: 4px;
}
.paginationButton {
min-width: 28px;
min-height: 28px;
padding: 0 8px;
background: #0c1118;
border: 1px solid #1d2530;
color: #cfd8e3;
border-radius: 5px;
font-size: 13px;
font-weight: 700;
line-height: 1;
cursor: pointer;
transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.paginationButton:hover:not(:disabled) {
border-color: #2c74b8;
background: #11202f;
color: #e7edf5;
}
.paginationButton:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.paginationPage {
padding: 0 10px;
color: #b0b8c4;
font-weight: 800;
letter-spacing: 0;
}
/* Live page responsive */
@media (max-width: 960px) {
.liveLayout {
grid-template-columns: 1fr;
}
.liveSidebar {
position: static;
max-height: none;
}
.liveSummaryGrid {
grid-template-columns: repeat(2, 1fr);
}
}
/* Strategy page responsive */
@media (max-width: 960px) {
.strategyLayout {
grid-template-columns: 1fr;
}
.strategySelector {
position: static;
max-height: none;
}
.metricsGrid {
grid-template-columns: repeat(2, 1fr);
}
}