2026-04-13 21:14:47 +00:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
2026-04-25 11:39:17 +00:00
< title > APEX — AI-Powered EA Optimizer</ title >
2026-04-13 21:14:47 +00:00
< link rel = "preconnect" href = "https://fonts.googleapis.com" >
2026-04-25 11:39:17 +00:00
< link rel = "preconnect" href = "https://fonts.gstatic.com" crossorigin >
< link href = "https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel = "stylesheet" >
2026-04-13 21:14:47 +00:00
< style >
2026-04-25 11:39:17 +00:00
/* ── CSS Variables ──────────────────────────────────────────── */
: root {
--bg : #080d1a ;
--sidebar-bg : #0a0f1e ;
--card-bg : #0f1629 ;
--card-hover : #131d35 ;
--border : rgba ( 255 , 255 , 255 , 0.07 );
--border-hover : rgba ( 255 , 255 , 255 , 0.14 );
--accent : #4f46e5 ;
--accent2 : #7c6dfa ;
--teal : #00d4aa ;
--text : #e2e8f0 ;
--muted : #64748b ;
--green : #10b981 ;
--red : #ef4444 ;
--yellow : #f59e0b ;
--nav-active-bg : rgba ( 79 , 70 , 229 , 0.18 );
--nav-active-border : #4f46e5 ;
2026-04-13 21:14:47 +00:00
}
2026-04-25 11:39:17 +00:00
/* ── Reset ──────────────────────────────────────────────────── */
*, * :: before , * :: after { box-sizing : border-box ; margin : 0 ; padding : 0 ; }
2026-04-13 21:14:47 +00:00
2026-04-25 11:39:17 +00:00
body {
font-family : 'Inter' , - apple-system , BlinkMacSystemFont , sans-serif ;
background : var ( -- bg );
color : var ( -- text );
height : 100 vh ;
overflow : hidden ;
font-size : 14 px ;
line-height : 1.5 ;
2026-04-13 21:14:47 +00:00
}
2026-04-25 11:39:17 +00:00
/* ── App shell ──────────────────────────────────────────────── */
. app-shell {
display : flex ;
height : 100 vh ;
}
/* ══════════════════════════════════════════════════════════════
SIDEBAR
══════════════════════════════════════════════════════════════ */
. sidebar {
width : 220 px ;
flex-shrink : 0 ;
background : var ( -- sidebar - bg );
border-right : 1 px solid var ( -- border );
display : flex ;
flex-direction : column ;
padding : 1.25 rem 0 ;
overflow : hidden ;
}
/* Logo */
. logo-wrap {
display : flex ;
align-items : center ;
gap : 0.65 rem ;
padding : 0 1.25 rem 1.25 rem ;
border-bottom : 1 px solid var ( -- border );
margin-bottom : 0.75 rem ;
}
. logo-text {
font-size : 1.25 rem ;
font-weight : 800 ;
letter-spacing : 0.12 em ;
background : linear-gradient ( 135 deg , #7c6dfa , #00d4aa );
-webkit- background-clip : text ;
-webkit- text-fill-color : transparent ;
background-clip : text ;
}
. logo-tagline {
font-size : 0.58 rem ;
color : var ( -- muted );
font-weight : 400 ;
letter-spacing : 0.06 em ;
display : block ;
line-height : 1 ;
margin-top : -2 px ;
-webkit- text-fill-color : var ( -- muted );
}
/* Nav */
. sidebar-nav {
flex : 1 ;
display : flex ;
flex-direction : column ;
gap : 1 px ;
padding : 0.25 rem 0 ;
}
. nav-section-label {
font-size : 0.6 rem ;
font-weight : 700 ;
letter-spacing : 0.1 em ;
text-transform : uppercase ;
color : var ( -- muted );
padding : 0.75 rem 1.25 rem 0.35 rem ;
}
. nav-item {
display : flex ;
align-items : center ;
gap : 0.7 rem ;
padding : 0.6 rem 1.25 rem ;
color : var ( -- muted );
2026-04-13 21:14:47 +00:00
text-decoration : none ;
2026-04-25 11:39:17 +00:00
font-size : 0.83 rem ;
font-weight : 500 ;
transition : all 0.15 s ease ;
border-left : 2 px solid transparent ;
position : relative ;
2026-04-13 21:14:47 +00:00
}
2026-04-25 11:39:17 +00:00
. nav-item svg { flex-shrink : 0 ; }
. nav-item : hover {
color : var ( -- text );
background : rgba ( 255 , 255 , 255 , 0.04 );
}
. nav-item . active {
color : var ( -- text );
background : var ( -- nav - active - bg );
border-left-color : var ( -- accent );
}
. nav-item . active svg { color : var ( -- accent2 ); }
. nav-badge {
margin-left : auto ;
background : var ( -- accent );
color : white ;
font-size : 0.6 rem ;
font-weight : 700 ;
padding : 0.1 rem 0.4 rem ;
border-radius : 999 px ;
min-width : 18 px ;
text-align : center ;
2026-04-13 21:14:47 +00:00
}
2026-04-25 11:39:17 +00:00
/* Sidebar footer */
. sidebar-footer {
padding : 1 rem 1.25 rem 0 ;
border-top : 1 px solid var ( -- border );
display : flex ;
flex-direction : column ;
gap : 0.75 rem ;
}
. mt5-status {
display : flex ;
align-items : center ;
gap : 0.6 rem ;
}
. mt5-dot {
width : 8 px ;
height : 8 px ;
border-radius : 50 % ;
background : var ( -- green );
box-shadow : 0 0 8 px var ( -- green );
animation : pulse-dot 2 s ease-in-out infinite ;
flex-shrink : 0 ;
}
. mt5-dot . disconnected {
background : var ( -- red );
box-shadow : 0 0 8 px var ( -- red );
animation : none ;
}
@ keyframes pulse-dot {
0 %, 100 % { opacity : 1 ; box-shadow : 0 0 8 px var ( -- green ); }
50 % { opacity : 0.6 ; box-shadow : 0 0 4 px var ( -- green ); }
}
. mt5-label { font-size : 0.68 rem ; color : var ( -- muted ); font-weight : 500 ; }
. mt5-state { font-size : 0.75 rem ; color : var ( -- text ); font-weight : 600 ; }
. mt5-brand {
display : flex ;
align-items : center ;
gap : 0.5 rem ;
font-size : 0.7 rem ;
color : var ( -- muted );
}
/* ══════════════════════════════════════════════════════════════
MAIN CONTENT
══════════════════════════════════════════════════════════════ */
. main-content {
flex : 1 ;
overflow-y : auto ;
overflow-x : hidden ;
padding : 1.25 rem 1.5 rem 1.5 rem ;
display : flex ;
flex-direction : column ;
gap : 0.85 rem ;
scrollbar-width : thin ;
scrollbar-color : rgba ( 255 , 255 , 255 , 0.1 ) transparent ;
}
. main-content :: -webkit-scrollbar { width : 5 px ; }
. main-content :: -webkit-scrollbar-thumb { background : rgba ( 255 , 255 , 255 , 0.08 ); border-radius : 999 px ; }
/* ── Command Header ──────────────────────────────────────── */
. cmd-header {
display : flex ;
align-items : center ;
background : var ( -- card - bg );
border : 1 px solid rgba ( 79 , 70 , 229 , 0.28 );
2026-04-13 21:14:47 +00:00
border-radius : 14 px ;
2026-04-25 11:39:17 +00:00
padding : 0.7 rem 1.25 rem ;
flex-shrink : 0 ;
position : relative ;
overflow : hidden ;
gap : 0 ;
2026-04-13 21:14:47 +00:00
}
2026-04-25 11:39:17 +00:00
. cmd-header :: before {
content : '' ;
position : absolute ;
top : 0 ; left : 0 ; right : 0 ; height : 1 px ;
background : linear-gradient ( 90 deg , rgba ( 0 , 229 , 255 , 0.45 ), rgba ( 79 , 70 , 229 , 0.55 ), rgba ( 124 , 58 , 237 , 0.45 ));
}
. cmd-logo {
display : flex ;
align-items : center ;
gap : 0.6 rem ;
flex-shrink : 0 ;
}
. cmd-logo-text {
display : flex ;
flex-direction : column ;
gap : 0.05 rem ;
}
. cmd-apex {
font-size : 1.05 rem ;
font-weight : 800 ;
letter-spacing : 0.14 em ;
background : linear-gradient ( 135 deg , #00e5ff 0 % , #4f46e5 50 % , #7c3aed 100 % );
-webkit- background-clip : text ;
-webkit- text-fill-color : transparent ;
background-clip : text ;
}
. cmd-tagline {
font-size : 0.46 rem ;
font-weight : 600 ;
letter-spacing : 0.1 em ;
color : var ( -- muted );
text-transform : uppercase ;
-webkit- text-fill-color : var ( -- muted );
}
. cmd-sep {
width : 1 px ;
height : 30 px ;
background : var ( -- border );
margin : 0 1.1 rem ;
flex-shrink : 0 ;
}
. cmd-section {
display : flex ;
flex-direction : column ;
gap : 0.12 rem ;
}
. cmd-gen-section { min-width : 145 px ; }
. cmd-status-row { display : flex ; align-items : center ; gap : 0.4 rem ; }
. cmd-status-dot {
width : 8 px ; height : 8 px ;
border-radius : 50 % ;
background : var ( -- muted );
flex-shrink : 0 ;
transition : background 0.3 s , box-shadow 0.3 s ;
}
. cmd-status-dot . running {
background : var ( -- green );
box-shadow : 0 0 8 px rgba ( 16 , 185 , 129 , 0.6 );
animation : pulse-dot 1.5 s ease-in-out infinite ;
}
. cmd-status-label {
font-size : 0.82 rem ;
font-weight : 600 ;
color : var ( -- text );
white-space : nowrap ;
}
. cmd-section-sub { font-size : 0.66 rem ; color : var ( -- muted ); white-space : nowrap ; }
. cmd-gen-row {
display : flex ;
align-items : center ;
justify-content : space-between ;
gap : 0.5 rem ;
}
. cmd-gen-label {
font-size : 0.61 rem ;
font-weight : 700 ;
color : var ( -- muted );
text-transform : uppercase ;
letter-spacing : 0.07 em ;
}
. cmd-gen-val {
font-size : 0.8 rem ;
font-weight : 700 ;
color : var ( -- text );
font-family : 'JetBrains Mono' , monospace ;
}
. cmd-gen-sep { color : var ( -- muted ); margin : 0 0.1 rem ; font-weight : 400 ; }
. cmd-prog-track {
width : 100 % ;
height : 3 px ;
background : rgba ( 255 , 255 , 255 , 0.07 );
border-radius : 999 px ;
overflow : hidden ;
margin : 0.12 rem 0 ;
}
. cmd-prog-fill {
height : 100 % ;
background : linear-gradient ( 90 deg , #00e5ff , #4f46e5 );
border-radius : 999 px ;
transition : width 0.5 s ease ;
}
. cmd-pct-label { font-size : 0.61 rem ; color : var ( -- muted ); }
. cmd-score-label {
font-size : 0.61 rem ;
font-weight : 700 ;
color : var ( -- muted );
text-transform : uppercase ;
letter-spacing : 0.07 em ;
}
. cmd-score-val {
font-size : 0.98 rem ;
font-weight : 700 ;
color : var ( -- teal );
font-family : 'JetBrains Mono' , monospace ;
}
. cmd-score-delta { font-size : 0.62 rem ; color : var ( -- muted ); }
. cmd-spacer { flex : 1 ; }
. cmd-actions { display : flex ; align-items : center ; gap : 0.45 rem ; flex-shrink : 0 ; }
. cmd-btn {
display : inline-flex ;
align-items : center ;
gap : 0.35 rem ;
padding : 0.45 rem 0.85 rem ;
border-radius : 8 px ;
font-size : 0.76 rem ;
font-weight : 600 ;
cursor : pointer ;
border : 1 px solid transparent ;
font-family : inherit ;
transition : all 0.15 s ;
text-decoration : none ;
white-space : nowrap ;
}
. cmd-btn-start {
background : linear-gradient ( 135 deg , #4f46e5 , #7c6dfa );
color : white ;
}
. cmd-btn-start : hover { opacity : 0.88 ; }
. cmd-btn-pause {
background : rgba ( 245 , 158 , 11 , 0.1 );
border-color : rgba ( 245 , 158 , 11 , 0.25 );
color : var ( -- yellow );
opacity : 0.4 ;
pointer-events : none ;
}
. cmd-btn-pause . active { opacity : 1 ; pointer-events : auto ; }
. cmd-btn-pause . active : hover { background : rgba ( 245 , 158 , 11 , 0.18 ); }
. cmd-btn-stop {
background : rgba ( 100 , 116 , 139 , 0.08 );
border-color : rgba ( 100 , 116 , 139 , 0.2 );
color : var ( -- muted );
opacity : 0.4 ;
pointer-events : none ;
}
. cmd-btn-stop . active {
background : rgba ( 239 , 68 , 68 , 0.12 );
border-color : rgba ( 239 , 68 , 68 , 0.35 );
color : var ( -- red );
opacity : 1 ;
pointer-events : auto ;
}
. cmd-btn-stop . active : hover { background : rgba ( 239 , 68 , 68 , 0.22 ); }
/* keep run-indicator wiring for JS compat, always hidden */
# run-indicator { display : none !important ; }
2026-04-13 21:14:47 +00:00
2026-04-25 11:39:17 +00:00
/* ── Metric cards row ────────────────────────────────────── */
. metrics-row {
display : grid ;
grid-template-columns : repeat ( 6 , minmax ( 0 , 1 fr ));
gap : 0.7 rem ;
flex-shrink : 0 ;
}
. metric-card {
background : var ( -- card - bg );
border : 1 px solid var ( -- border );
border-radius : 12 px ;
padding : 0.9 rem 1 rem ;
transition : border-color 0.2 s , transform 0.15 s ;
position : relative ;
overflow : hidden ;
}
. metric-card :: before {
content : '' ;
position : absolute ;
top : 0 ; left : 0 ; right : 0 ;
height : 2 px ;
background : linear-gradient ( 90 deg , var ( -- accent ), var ( -- accent2 ));
opacity : 0 ;
transition : opacity 0.2 s ;
}
. metric-card : hover { border-color : var ( -- border - hover ); }
. metric-card : hover :: before { opacity : 1 ; }
. metric-label { font-size : 0.68 rem ; color : var ( -- muted ); font-weight : 600 ; letter-spacing : 0.04 em ; text-transform : uppercase ; margin-bottom : 0.3 rem ; }
. metric-value { font-size : 1.35 rem ; font-weight : 700 ; letter-spacing : -0.02 em ; line-height : 1.1 ; }
. metric-value . green { color : var ( -- green ); }
. metric-value . red { color : var ( -- red ); }
. metric-value . gold { color : var ( -- yellow ); }
. metric-value . teal { color : var ( -- teal ); }
. metric-value . white { color : var ( -- text ); }
. metric-delta {
font-size : 0.7 rem ;
color : var ( -- muted );
margin-top : 0.2 rem ;
display : flex ;
align-items : center ;
gap : 0.2 rem ;
}
. delta-up { color : var ( -- green ); }
. delta-down { color : var ( -- red ); }
. sparkline-wrap {
margin-top : 0.55 rem ;
}
/* AI Confidence card */
. ai-conf-card { display : flex ; flex-direction : column ; }
. ai-conf-value {
font-size : 0.95 rem ;
font-weight : 700 ;
color : var ( -- text );
margin-top : 0.15 rem ;
}
. ai-gauge-wrap {
margin-top : 0.45 rem ;
display : flex ;
align-items : center ;
justify-content : flex-start ;
}
/* ── Charts + AI panel row ───────────────────────────────── */
. charts-ai-row {
display : grid ;
grid-template-columns : 2 fr 1 fr ;
gap : 0.7 rem ;
flex-shrink : 0 ;
}
. charts-col {
display : flex ;
flex-direction : column ;
gap : 0.7 rem ;
}
/* Card base */
. card {
background : var ( -- card - bg );
border : 1 px solid var ( -- border );
border-radius : 12 px ;
padding : 1 rem 1.25 rem ;
display : flex ;
flex-direction : column ;
}
. card-header {
display : flex ;
align-items : center ;
justify-content : space-between ;
margin-bottom : 0.6 rem ;
flex-shrink : 0 ;
}
. card-title {
font-size : 0.82 rem ;
font-weight : 600 ;
color : var ( -- text );
display : flex ;
align-items : center ;
gap : 0.5 rem ;
}
. card-title . dot {
width : 7 px ; height : 7 px ; border-radius : 50 % ;
background : var ( -- teal );
}
. card-badge {
font-size : 0.65 rem ;
font-weight : 600 ;
padding : 0.15 rem 0.5 rem ;
border-radius : 999 px ;
background : rgba ( 0 , 212 , 170 , 0.12 );
color : var ( -- teal );
}
. chart-wrap {
position : relative ;
overflow : hidden ;
}
. chart-wrap canvas {
position : absolute !important ;
inset : 0 ;
width : 100 % !important ;
height : 100 % !important ;
}
. equity-chart-wrap { height : 165 px ; }
. drawdown-chart-wrap { height : 100 px ; }
/* ── AI Summary panel ────────────────────────────────────── */
. ai-panel-col {
display : flex ;
flex-direction : column ;
}
. ai-panel-card {
background : var ( -- card - bg );
border : 1 px solid rgba ( 79 , 70 , 229 , 0.3 );
border-radius : 12 px ;
padding : 1 rem 1.25 rem ;
flex : 1 ;
display : flex ;
flex-direction : column ;
gap : 0.75 rem ;
position : relative ;
overflow : hidden ;
}
. ai-panel-card :: before {
content : '' ;
position : absolute ;
top : 0 ; left : 0 ; right : 0 ; height : 1 px ;
background : linear-gradient ( 90 deg , transparent , rgba ( 124 , 109 , 250 , 0.6 ), transparent );
}
. ai-panel-card :: after {
content : '' ;
position : absolute ;
top : -80 px ; right : -80 px ;
width : 200 px ; height : 200 px ;
background : radial-gradient ( circle , rgba ( 79 , 70 , 229 , 0.06 ) 0 % , transparent 70 % );
pointer-events : none ;
}
. ai-panel-header {
display : flex ;
justify-content : space-between ;
align-items : center ;
flex-shrink : 0 ;
}
. ai-panel-title {
font-size : 0.82 rem ;
font-weight : 600 ;
display : flex ;
align-items : center ;
gap : 0.4 rem ;
}
. ai-icon {
color : var ( -- accent2 );
font-size : 0.9 rem ;
}
. view-details-link {
font-size : 0.72 rem ;
color : var ( -- accent2 );
text-decoration : none ;
transition : opacity 0.15 s ;
}
. view-details-link : hover { opacity : 0.7 ; }
. ai-waiting {
display : flex ;
flex-direction : column ;
align-items : center ;
justify-content : center ;
flex : 1 ;
gap : 0.75 rem ;
color : var ( -- muted );
font-size : 0.78 rem ;
}
. ai-pulse-dot {
width : 32 px ; height : 32 px ;
border-radius : 50 % ;
border : 2 px solid rgba ( 124 , 109 , 250 , 0.4 );
position : relative ;
animation : ai-spin 2 s linear infinite ;
}
. ai-pulse-dot :: before {
content : '' ;
position : absolute ;
top : 4 px ; left : 4 px ; right : 4 px ; bottom : 4 px ;
border-radius : 50 % ;
background : rgba ( 124 , 109 , 250 , 0.3 );
animation : ai-pulse 2 s ease-in-out infinite ;
}
@ keyframes ai-spin { from { transform : rotate ( 0 deg ); } to { transform : rotate ( 360 deg ); } }
@ keyframes ai-pulse { 0 %, 100 % { opacity : 0.4 ; } 50 % { opacity : 1 ; } }
. ai-content { display : flex ; flex-direction : column ; gap : 0.65 rem ; overflow-y : auto ; flex : 1 ; }
. ai-content :: -webkit-scrollbar { width : 3 px ; }
. ai-content :: -webkit-scrollbar-thumb { background : rgba ( 255 , 255 , 255 , 0.08 ); border-radius : 999 px ; }
. ai-headline {
font-size : 0.82 rem ;
font-weight : 600 ;
color : var ( -- text );
line-height : 1.4 ;
padding-bottom : 0.5 rem ;
border-bottom : 1 px solid var ( -- border );
}
. ai-diagnosis { font-size : 0.78 rem ; line-height : 1.7 ; color : #94a3b8 ; }
. ai-sub-title {
font-size : 0.65 rem ;
font-weight : 700 ;
text-transform : uppercase ;
letter-spacing : 0.09 em ;
color : var ( -- muted );
margin-bottom : 0.35 rem ;
}
. ai-sub-title . warn { color : #f59e0b ; }
. ai-check-list { list-style : none ; display : flex ; flex-direction : column ; gap : 0.3 rem ; }
. ai-check-list li {
font-size : 0.76 rem ;
color : var ( -- text );
display : flex ;
align-items : flex-start ;
gap : 0.45 rem ;
line-height : 1.4 ;
}
. ai-check-list li :: before { content : "✓" ; color : var ( -- green ); font-weight : 700 ; flex-shrink : 0 ; margin-top : 0.05 em ; }
. ai-warn-list { list-style : none ; display : flex ; flex-direction : column ; gap : 0.3 rem ; }
. ai-warn-list li {
font-size : 0.76 rem ;
color : #fbbf24 ;
display : flex ;
align-items : flex-start ;
gap : 0.45 rem ;
line-height : 1.4 ;
}
. ai-warn-list li :: before { content : "⚠" ; flex-shrink : 0 ; margin-top : 0.05 em ; font-size : 0.7 rem ; }
. ai-suggestion-box {
background : rgba ( 79 , 70 , 229 , 0.1 );
border : 1 px solid rgba ( 79 , 70 , 229 , 0.22 );
border-radius : 8 px ;
padding : 0.7 rem 0.75 rem ;
position : relative ;
}
. ai-suggestion-text { font-size : 0.76 rem ; color : var ( -- text ); line-height : 1.55 ; padding-right : 1.5 rem ; }
. ai-badge {
position : absolute ;
top : 0.45 rem ;
right : 0.45 rem ;
background : var ( -- accent );
color : white ;
font-size : 0.58 rem ;
font-weight : 700 ;
padding : 0.1 rem 0.35 rem ;
border-radius : 4 px ;
letter-spacing : 0.04 em ;
}
. ai-confidence-row {
display : flex ;
align-items : center ;
gap : 0.6 rem ;
margin-top : auto ;
padding-top : 0.5 rem ;
border-top : 1 px solid var ( -- border );
flex-shrink : 0 ;
}
. ai-conf-badge {
display : inline-flex ;
align-items : center ;
gap : 0.3 rem ;
padding : 0.2 rem 0.6 rem ;
border-radius : 6 px ;
font-size : 0.7 rem ;
font-weight : 600 ;
text-transform : capitalize ;
}
. ai-conf-badge :: before { content : '●' ; font-size : 0.5 rem ; }
. ai-conf-badge . high { background : rgba ( 16 , 185 , 129 , 0.15 ); color : #10b981 ; }
. ai-conf-badge . medium { background : rgba ( 245 , 158 , 11 , 0.15 ); color : #f59e0b ; }
. ai-conf-badge . low { background : rgba ( 239 , 68 , 68 , 0.15 ); color : #ef4444 ; }
. ai-run-ref { font-size : 0.68 rem ; color : var ( -- muted ); margin-left : auto ; font-family : 'JetBrains Mono' , monospace ; }
/* ── Bottom row ──────────────────────────────────────────── */
. bottom-row {
display : grid ;
grid-template-columns : repeat ( 3 , minmax ( 0 , 1 fr ));
gap : 0.7 rem ;
flex-shrink : 0 ;
}
. bottom-card {
background : var ( -- card - bg );
border : 1 px solid var ( -- border );
border-radius : 12 px ;
padding : 0.9 rem 1 rem ;
display : flex ;
flex-direction : column ;
}
. bottom-card-title {
font-size : 0.8 rem ;
font-weight : 600 ;
margin-bottom : 0.6 rem ;
display : flex ;
justify-content : space-between ;
align-items : center ;
flex-shrink : 0 ;
}
. view-all-link {
font-size : 0.7 rem ;
color : var ( -- accent2 );
text-decoration : none ;
font-weight : 500 ;
}
. view-all-link : hover { opacity : 0.75 ; }
/* Tables */
. params-table , . runs-table {
width : 100 % ;
border-collapse : collapse ;
font-size : 0.76 rem ;
}
. params-table th , . runs-table th {
color : var ( -- muted );
font-size : 0.64 rem ;
font-weight : 700 ;
text-transform : uppercase ;
letter-spacing : 0.07 em ;
padding : 0.3 rem 0.5 rem ;
border-bottom : 1 px solid var ( -- border );
text-align : left ;
}
. params-table td , . runs-table td {
padding : 0.38 rem 0.5 rem ;
border-bottom : 1 px solid rgba ( 255 , 255 , 255 , 0.03 );
vertical-align : middle ;
}
. params-table tr : last-child td , . runs-table tr : last-child td { border-bottom : none ; }
. params-table tr : hover td , . runs-table tr : hover td { background : rgba ( 255 , 255 , 255 , 0.02 ); }
. param-name { font-family : 'JetBrains Mono' , monospace ; font-size : 0.7 rem ; color : var ( -- text ); }
. param-val { font-family : 'JetBrains Mono' , monospace ; font-size : 0.72 rem ; color : var ( -- teal ); font-weight : 600 ; }
. impact-high { display : inline-block ; background : rgba ( 16 , 185 , 129 , 0.15 ); color : var ( -- green ); padding : 0.08 rem 0.4 rem ; border-radius : 4 px ; font-size : 0.64 rem ; font-weight : 700 ; }
. impact-medium { display : inline-block ; background : rgba ( 245 , 158 , 11 , 0.15 ); color : var ( -- yellow ); padding : 0.08 rem 0.4 rem ; border-radius : 4 px ; font-size : 0.64 rem ; font-weight : 700 ; }
. impact-low { display : inline-block ; background : rgba ( 100 , 116 , 139 , 0.15 ); color : var ( -- muted ); padding : 0.08 rem 0.4 rem ; border-radius : 4 px ; font-size : 0.64 rem ; font-weight : 700 ; }
. verdict-recommended { display : inline-block ; background : rgba ( 16 , 185 , 129 , 0.15 ); color : var ( -- green ); padding : 0.08 rem 0.45 rem ; border-radius : 4 px ; font-size : 0.64 rem ; font-weight : 700 ; }
. verdict-risky { display : inline-block ; background : rgba ( 245 , 158 , 11 , 0.15 ); color : var ( -- yellow ); padding : 0.08 rem 0.45 rem ; border-radius : 4 px ; font-size : 0.64 rem ; font-weight : 700 ; }
. verdict-not-reliable { display : inline-block ; background : rgba ( 239 , 68 , 68 , 0.15 ); color : var ( -- red ); padding : 0.08 rem 0.45 rem ; border-radius : 4 px ; font-size : 0.64 rem ; font-weight : 700 ; }
. empty-state { color : var ( -- muted ); font-size : 0.76 rem ; padding : 0.65 rem 0.5 rem ; }
. run-num { font-family : 'JetBrains Mono' , monospace ; font-size : 0.7 rem ; color : var ( -- muted ); }
. profit-pos { color : var ( -- green ); font-weight : 600 ; }
. profit-neg { color : var ( -- red ); font-weight : 600 ; }
/* Optimization progress */
. opt-gen-label {
font-size : 0.75 rem ;
color : var ( -- muted );
font-family : 'JetBrains Mono' , monospace ;
margin-bottom : 0.45 rem ;
}
. opt-progress-bar-track {
height : 5 px ;
background : rgba ( 255 , 255 , 255 , 0.06 );
border-radius : 999 px ;
overflow : hidden ;
margin-bottom : 0.65 rem ;
}
. opt-progress-bar-fill {
height : 100 % ;
background : linear-gradient ( 90 deg , var ( -- accent ), var ( -- teal ));
border-radius : 999 px ;
transition : width 0.6 s ease ;
width : 0 % ;
}
. opt-stats-grid {
display : grid ;
grid-template-columns : 1 fr 1 fr 1 fr ;
gap : 0.5 rem ;
}
. opt-stat { }
. opt-stat-label { font-size : 0.63 rem ; color : var ( -- muted ); font-weight : 600 ; text-transform : uppercase ; letter-spacing : 0.06 em ; }
. opt-stat-val { font-size : 0.8 rem ; color : var ( -- text ); font-weight : 600 ; margin-top : 0.15 rem ; }
/* Phase steps */
. phase-steps {
display : flex ;
align-items : center ;
margin-top : 0.6 rem ;
gap : 0 ;
}
. phase-step {
display : flex ;
flex-direction : column ;
align-items : center ;
gap : 0.3 rem ;
flex : 1 ;
position : relative ;
}
. phase-dot {
width : 24 px ; height : 24 px ;
border-radius : 50 % ;
border : 2 px solid rgba ( 255 , 255 , 255 , 0.1 );
background : var ( -- bg );
display : flex ; align-items : center ; justify-content : center ;
font-size : 0.65 rem ;
font-weight : 700 ;
color : var ( -- muted );
transition : all 0.35 s ;
z-index : 1 ;
}
. phase-name { font-size : 0.6 rem ; color : var ( -- muted ); font-weight : 500 ; text-align : center ; }
. phase-connector {
flex : 1 ;
height : 2 px ;
background : rgba ( 255 , 255 , 255 , 0.07 );
margin-top : -14 px ;
}
. phase-step . active . phase-dot { border-color : var ( -- teal ); color : var ( -- teal ); background : rgba ( 0 , 212 , 170 , 0.1 ); box-shadow : 0 0 10 px rgba ( 0 , 212 , 170 , 0.25 ); }
. phase-step . active . phase-name { color : var ( -- teal ); }
. phase-step . done . phase-dot { border-color : var ( -- teal ); background : var ( -- teal ); color : #051a14 ; }
. phase-step . done . phase-name { color : var ( -- text ); }
/* ── Live log ────────────────────────────────────────────── */
. log-panel {
flex-shrink : 0 ;
}
. log-toggle-btn {
width : 100 % ;
display : flex ;
align-items : center ;
justify-content : space-between ;
padding : 0.5 rem 1 rem ;
background : var ( -- card - bg );
border : 1 px solid var ( -- border );
border-radius : 8 px ;
cursor : pointer ;
font-family : inherit ;
font-size : 0.75 rem ;
color : var ( -- muted );
font-weight : 500 ;
transition : all 0.15 s ;
}
. log-toggle-btn : hover { color : var ( -- text ); border-color : var ( -- border - hover ); }
. log-toggle-icon { transition : transform 0.2 s ; }
. log-toggle-icon . open { transform : rotate ( 180 deg ); }
. log-body {
display : none ;
margin-top : 0.35 rem ;
background : var ( -- card - bg );
border : 1 px solid var ( -- border );
border-radius : 8 px ;
overflow : hidden ;
}
. log-body . open { display : block ; }
. log-feed {
height : 120 px ;
overflow-y : auto ;
padding : 0.6 rem 0.75 rem ;
font-family : 'JetBrains Mono' , monospace ;
font-size : 0.7 rem ;
line-height : 1.7 ;
color : #64748b ;
scrollbar-width : thin ;
scrollbar-color : rgba ( 255 , 255 , 255 , 0.06 ) transparent ;
}
. log-feed :: -webkit-scrollbar { width : 3 px ; }
. log-line { display : flex ; gap : 0.6 rem ; }
. log-time { color : rgba ( 100 , 116 , 139 , 0.6 ); flex-shrink : 0 ; }
. log-line . info . log-msg { color : #94a3b8 ; }
. log-line . success . log-msg { color : var ( -- green ); }
. log-line . warn . log-msg { color : var ( -- yellow ); }
. log-line . error . log-msg { color : var ( -- red ); }
/* ── Verdict overlay ─────────────────────────────────────── */
. verdict-overlay {
position : fixed ; inset : 0 ;
background : rgba ( 0 , 0 , 0 , 0.75 );
display : flex ;
align-items : center ;
justify-content : center ;
z-index : 200 ;
backdrop-filter : blur ( 5 px );
}
. verdict-card {
background : var ( -- card - bg );
border : 1 px solid var ( -- border );
border-radius : 20 px ;
padding : 2.25 rem 2.5 rem ;
max-width : 580 px ;
width : 92 % ;
animation : popIn 0.4 s cubic-bezier ( 0.34 , 1.56 , 0.64 , 1 ) both ;
}
@ keyframes popIn {
from { opacity : 0 ; transform : scale ( 0.88 ) translateY ( 20 px ); }
to { opacity : 1 ; transform : scale ( 1 ) translateY ( 0 ); }
}
. verdict-header-row {
display : flex ;
align-items : center ;
gap : 1.25 rem ;
margin-bottom : 1.5 rem ;
}
. verdict-icon-big { font-size : 2.5 rem ; line-height : 1 ; }
. verdict-title {
font-size : 1.5 rem ;
font-weight : 800 ;
letter-spacing : -0.02 em ;
}
. verdict-subtitle { font-size : 0.85 rem ; color : var ( -- muted ); margin-top : 0.25 rem ; line-height : 1.5 ; }
. verdict-metrics-row {
display : grid ;
grid-template-columns : repeat ( 4 , 1 fr );
gap : 1 rem ;
padding : 1.25 rem 0 ;
border-top : 1 px solid var ( -- border );
border-bottom : 1 px solid var ( -- border );
margin-bottom : 1.5 rem ;
}
. vm { text-align : center ; }
. vm-val { font-size : 1.1 rem ; font-weight : 700 ; }
. vm-lbl { font-size : 0.68 rem ; color : var ( -- muted ); margin-top : 0.2 rem ; font-weight : 500 ; }
. verdict-actions-row {
display : flex ;
gap : 0.65 rem ;
flex-wrap : wrap ;
}
. verdict-btn {
display : inline-flex ;
align-items : center ;
gap : 0.4 rem ;
padding : 0.6 rem 1.1 rem ;
border-radius : 8 px ;
font-size : 0.82 rem ;
font-weight : 600 ;
cursor : pointer ;
text-decoration : none ;
font-family : inherit ;
border : 1 px solid transparent ;
transition : all 0.15 s ;
}
. verdict-btn . primary { background : linear-gradient ( 135 deg , var ( -- accent ), var ( -- accent2 )); color : white ; }
. verdict-btn . primary : hover { opacity : 0.88 ; }
. verdict-btn . secondary { background : rgba ( 255 , 255 , 255 , 0.06 ); border-color : var ( -- border ); color : var ( -- text ); }
. verdict-btn . secondary : hover { background : rgba ( 255 , 255 , 255 , 0.1 ); }
. verdict-btn . ghost { background : transparent ; border-color : rgba ( 255 , 255 , 255 , 0.1 ); color : var ( -- muted ); }
. verdict-btn . ghost : hover { color : var ( -- text ); }
/* ── Settings Modal ─────────────────────────────────────── */
. settings-overlay {
position : fixed ; inset : 0 ;
background : rgba ( 0 , 0 , 0 , 0.78 );
display : flex ;
align-items : center ;
justify-content : center ;
z-index : 300 ;
backdrop-filter : blur ( 6 px );
animation : fadeIn 0.2 s ease both ;
}
@ keyframes fadeIn { from { opacity : 0 ; } to { opacity : 1 ; } }
. settings-card {
background : var ( -- card - bg );
border : 1 px solid var ( -- border );
border-radius : 18 px ;
width : 680 px ;
max-width : 95 vw ;
max-height : 90 vh ;
display : flex ;
flex-direction : column ;
overflow : hidden ;
animation : popIn 0.3 s cubic-bezier ( 0.34 , 1.56 , 0.64 , 1 ) both ;
}
. settings-header {
display : flex ;
align-items : center ;
justify-content : space-between ;
padding : 1.25 rem 1.5 rem ;
border-bottom : 1 px solid var ( -- border );
flex-shrink : 0 ;
}
. settings-title {
font-size : 1 rem ;
font-weight : 700 ;
letter-spacing : -0.01 em ;
display : flex ;
align-items : center ;
gap : 0.6 rem ;
}
. settings-title svg { color : var ( -- accent2 ); }
. settings-close-btn {
width : 28 px ; height : 28 px ;
border-radius : 50 % ;
background : rgba ( 255 , 255 , 255 , 0.06 );
border : 1 px solid var ( -- border );
color : var ( -- muted );
cursor : pointer ;
display : flex ;
align-items : center ;
justify-content : center ;
transition : all 0.15 s ;
font-size : 14 px ;
line-height : 1 ;
}
. settings-close-btn : hover { background : rgba ( 255 , 255 , 255 , 0.12 ); color : var ( -- text ); }
. settings-tabs {
display : flex ;
gap : 0 ;
padding : 0 1.5 rem ;
border-bottom : 1 px solid var ( -- border );
flex-shrink : 0 ;
overflow-x : auto ;
}
. settings-tab {
padding : 0.65 rem 1 rem ;
font-size : 0.78 rem ;
font-weight : 600 ;
color : var ( -- muted );
cursor : pointer ;
border-bottom : 2 px solid transparent ;
transition : all 0.15 s ;
white-space : nowrap ;
display : flex ;
align-items : center ;
gap : 0.4 rem ;
}
. settings-tab : hover { color : var ( -- text ); }
. settings-tab . active { color : var ( -- text ); border-bottom-color : var ( -- accent ); }
. settings-body {
flex : 1 ;
overflow-y : auto ;
padding : 1.5 rem ;
scrollbar-width : thin ;
scrollbar-color : rgba ( 255 , 255 , 255 , 0.1 ) transparent ;
}
. settings-panel { display : none ; }
. settings-panel . active { display : block ; }
. settings-section-label {
font-size : 0.62 rem ;
font-weight : 700 ;
letter-spacing : 0.1 em ;
text-transform : uppercase ;
color : var ( -- muted );
margin-bottom : 0.75 rem ;
margin-top : 1.25 rem ;
}
. settings-section-label : first-child { margin-top : 0 ; }
. settings-grid {
display : grid ;
grid-template-columns : 1 fr 1 fr ;
gap : 0.75 rem ;
}
. settings-grid . full { grid-template-columns : 1 fr ; }
. settings-field {
display : flex ;
flex-direction : column ;
gap : 0.35 rem ;
}
. settings-field label {
font-size : 0.72 rem ;
font-weight : 600 ;
color : var ( -- muted );
letter-spacing : 0.02 em ;
}
. settings-input {
background : rgba ( 255 , 255 , 255 , 0.04 );
border : 1 px solid var ( -- border );
border-radius : 7 px ;
padding : 0.5 rem 0.75 rem ;
color : var ( -- text );
font-size : 0.82 rem ;
font-family : inherit ;
transition : border-color 0.15 s ;
width : 100 % ;
}
. settings-input : focus {
outline : none ;
border-color : var ( -- accent );
background : rgba ( 79 , 70 , 229 , 0.06 );
}
. settings-input . mono { font-family : 'JetBrains Mono' , monospace ; font-size : 0.78 rem ; }
. settings-select {
background : rgba ( 255 , 255 , 255 , 0.04 );
border : 1 px solid var ( -- border );
border-radius : 7 px ;
padding : 0.5 rem 0.75 rem ;
color : var ( -- text );
font-size : 0.82 rem ;
font-family : inherit ;
transition : border-color 0.15 s ;
width : 100 % ;
cursor : pointer ;
}
. settings-select : focus { outline : none ; border-color : var ( -- accent ); }
. settings-select option { background : #0f1629 ; }
. settings-toggle-row {
display : flex ;
align-items : center ;
justify-content : space-between ;
background : rgba ( 255 , 255 , 255 , 0.03 );
border : 1 px solid var ( -- border );
border-radius : 8 px ;
padding : 0.6 rem 0.85 rem ;
}
. settings-toggle-label { font-size : 0.82 rem ; font-weight : 500 ; }
. settings-toggle-sub { font-size : 0.7 rem ; color : var ( -- muted ); margin-top : 0.15 rem ; }
. settings-toggle {
width : 40 px ; height : 22 px ;
background : rgba ( 255 , 255 , 255 , 0.12 );
border-radius : 999 px ;
border : none ;
cursor : pointer ;
position : relative ;
transition : background 0.2 s ;
flex-shrink : 0 ;
}
. settings-toggle :: after {
content : '' ;
position : absolute ;
top : 3 px ; left : 3 px ;
width : 16 px ; height : 16 px ;
border-radius : 50 % ;
background : white ;
transition : transform 0.2 s ;
}
. settings-toggle . on { background : var ( -- accent ); }
. settings-toggle . on :: after { transform : translateX ( 18 px ); }
. settings-hint {
font-size : 0.68 rem ;
color : var ( -- muted );
margin-top : 0.2 rem ;
line-height : 1.4 ;
}
. settings-footer {
display : flex ;
align-items : center ;
justify-content : flex-end ;
gap : 0.65 rem ;
padding : 1 rem 1.5 rem ;
border-top : 1 px solid var ( -- border );
flex-shrink : 0 ;
}
. settings-btn {
display : inline-flex ;
align-items : center ;
gap : 0.4 rem ;
padding : 0.55 rem 1.1 rem ;
border-radius : 8 px ;
font-size : 0.82 rem ;
font-weight : 600 ;
cursor : pointer ;
font-family : inherit ;
border : 1 px solid transparent ;
transition : all 0.15 s ;
}
. settings-btn . cancel {
background : rgba ( 255 , 255 , 255 , 0.05 );
border-color : var ( -- border );
color : var ( -- muted );
}
. settings-btn . cancel : hover { background : rgba ( 255 , 255 , 255 , 0.1 ); color : var ( -- text ); }
. settings-btn . save {
background : linear-gradient ( 135 deg , var ( -- accent ), var ( -- accent2 ));
color : white ;
}
. settings-btn . save : hover { opacity : 0.88 ; }
. settings-btn . save : disabled { opacity : 0.5 ; cursor : not-allowed ; }
. settings-save-msg {
font-size : 0.75 rem ;
font-weight : 600 ;
margin-right : auto ;
transition : opacity 0.3 s ;
}
. settings-save-msg . ok { color : var ( -- green ); }
. settings-save-msg . err { color : var ( -- red ); }
/* ── No profit state banner ──────────────────────────────── */
. no-profit-banner {
display : none ;
align-items : center ;
gap : 0.75 rem ;
padding : 0.75 rem 1 rem ;
background : rgba ( 239 , 68 , 68 , 0.1 );
border : 1 px solid rgba ( 239 , 68 , 68 , 0.25 );
border-radius : 10 px ;
font-size : 0.8 rem ;
color : var ( -- red );
}
. no-profit-banner . active { display : flex ; }
. no-profit-banner-icon { font-size : 1.1 rem ; flex-shrink : 0 ; }
/* ── Scrollbar for whole page ────────────────────────────── */
:: -webkit-scrollbar { width : 5 px ; height : 5 px ; }
:: -webkit-scrollbar-track { background : transparent ; }
:: -webkit-scrollbar-thumb { background : rgba ( 255 , 255 , 255 , 0.08 ); border-radius : 999 px ; }
/* ── AI panel expand / collapse ─────────────────────────── */
. ai-preview { display : flex ; flex-direction : column ; gap : 0.5 rem ; }
. ai-details { display : none ; flex-direction : column ; gap : 0.65 rem ; }
. ai-details . open { display : flex ; animation : slideDown 0.2 s ease ; }
@ keyframes slideDown { from { opacity : 0 ; transform : translateY ( -6 px ); } to { opacity : 1 ; transform : translateY ( 0 ); } }
. ai-expand-btn {
align-self : flex-start ;
background : rgba ( 79 , 70 , 229 , 0.12 );
border : 1 px solid rgba ( 79 , 70 , 229 , 0.28 );
border-radius : 6 px ;
color : var ( -- accent2 );
font-size : 0.72 rem ;
font-weight : 600 ;
padding : 0.25 rem 0.65 rem ;
cursor : pointer ;
font-family : inherit ;
transition : all 0.15 s ;
margin-top : 0.15 rem ;
}
. ai-expand-btn : hover { background : rgba ( 79 , 70 , 229 , 0.22 ); }
/* ── Details button in runs table ───────────────────────── */
. detail-btn {
background : rgba ( 79 , 70 , 229 , 0.1 );
border : 1 px solid rgba ( 79 , 70 , 229 , 0.22 );
border-radius : 5 px ;
color : var ( -- accent2 );
font-size : 0.65 rem ;
font-weight : 600 ;
padding : 0.15 rem 0.5 rem ;
cursor : pointer ;
font-family : inherit ;
transition : all 0.15 s ;
white-space : nowrap ;
}
. detail-btn : hover { background : rgba ( 79 , 70 , 229 , 0.22 ); }
/* ── Run Detail Modal ────────────────────────────────────── */
. run-detail-overlay {
position : fixed ; inset : 0 ;
background : rgba ( 0 , 0 , 0 , 0.78 );
display : flex ;
align-items : center ;
justify-content : center ;
z-index : 250 ;
backdrop-filter : blur ( 5 px );
}
. run-detail-card {
background : var ( -- card - bg );
border : 1 px solid var ( -- border );
border-radius : 18 px ;
width : 720 px ;
max-width : 95 vw ;
max-height : 88 vh ;
display : flex ;
flex-direction : column ;
overflow : hidden ;
animation : popIn 0.3 s cubic-bezier ( 0.34 , 1.56 , 0.64 , 1 ) both ;
}
. run-detail-header {
display : flex ;
align-items : flex-start ;
justify-content : space-between ;
padding : 1.1 rem 1.5 rem ;
border-bottom : 1 px solid var ( -- border );
flex-shrink : 0 ;
}
. run-detail-title {
font-size : 0.95 rem ;
font-weight : 700 ;
color : var ( -- text );
font-family : 'JetBrains Mono' , monospace ;
letter-spacing : 0.02 em ;
}
. run-detail-sub { font-size : 0.72 rem ; color : var ( -- muted ); margin-top : 0.2 rem ; }
. run-detail-body {
flex : 1 ;
overflow-y : auto ;
padding : 1.1 rem 1.5 rem ;
display : flex ;
flex-direction : column ;
gap : 1 rem ;
scrollbar-width : thin ;
scrollbar-color : rgba ( 255 , 255 , 255 , 0.1 ) transparent ;
}
. rd-metrics-grid {
display : grid ;
grid-template-columns : repeat ( 4 , 1 fr );
gap : 0.6 rem ;
}
. rd-metric {
background : rgba ( 255 , 255 , 255 , 0.03 );
border : 1 px solid var ( -- border );
border-radius : 9 px ;
padding : 0.65 rem 0.8 rem ;
}
. rd-metric-label { font-size : 0.6 rem ; font-weight : 700 ; color : var ( -- muted ); text-transform : uppercase ; letter-spacing : 0.06 em ; }
. rd-metric-val { font-size : 1 rem ; font-weight : 700 ; margin-top : 0.15 rem ; }
. rd-section-title {
font-size : 0.63 rem ;
font-weight : 700 ;
text-transform : uppercase ;
letter-spacing : 0.1 em ;
color : var ( -- muted );
padding-bottom : 0.4 rem ;
border-bottom : 1 px solid var ( -- border );
}
. rd-params-wrap { max-height : 200 px ; overflow-y : auto ; }
. rd-ai-box {
background : rgba ( 79 , 70 , 229 , 0.07 );
border : 1 px solid rgba ( 79 , 70 , 229 , 0.2 );
border-radius : 10 px ;
padding : 0.9 rem 1 rem ;
font-size : 0.78 rem ;
color : var ( -- text );
line-height : 1.7 ;
}
. rd-ai-analysis { color : #94a3b8 ; margin-bottom : 0.65 rem ; }
. rd-ai-changes { display : flex ; flex-direction : column ; gap : 0.35 rem ; }
. rd-ai-change {
display : flex ; align-items : center ; gap : 0.5 rem ;
font-family : 'JetBrains Mono' , monospace ; font-size : 0.72 rem ;
}
. rd-ai-change-param { color : var ( -- teal ); }
. rd-ai-change-arrow { color : var ( -- muted ); }
. rd-ai-change-val { color : var ( -- text ); font-weight : 600 ; }
. run-detail-footer {
padding : 0.85 rem 1.5 rem ;
border-top : 1 px solid var ( -- border );
display : flex ;
align-items : center ;
justify-content : flex-end ;
gap : 0.65 rem ;
flex-shrink : 0 ;
}
/* ── Live Intelligence (thinking / changes / validation) ──── */
. live-intel-row {
display : grid ;
grid-template-columns : 1.1 fr 1 fr 1 fr ;
gap : 0.7 rem ;
flex-shrink : 0 ;
}
. live-intel-card {
background : var ( -- card - bg );
border : 1 px solid var ( -- border );
border-radius : 12 px ;
padding : 0.9 rem 1 rem ;
display : flex ;
flex-direction : column ;
min-height : 240 px ;
max-height : 280 px ;
position : relative ;
overflow : hidden ;
}
. live-intel-card . accent {
border-color : rgba ( 79 , 70 , 229 , 0.32 );
}
. live-intel-card . accent :: before {
content : '' ;
position : absolute ;
top : 0 ; left : 0 ; right : 0 ; height : 1 px ;
background : linear-gradient ( 90 deg , transparent , rgba ( 124 , 109 , 250 , 0.7 ), transparent );
}
. live-intel-title {
font-size : 0.78 rem ;
font-weight : 600 ;
color : var ( -- text );
display : flex ;
align-items : center ;
gap : 0.5 rem ;
margin-bottom : 0.65 rem ;
flex-shrink : 0 ;
}
. live-intel-title . icon { color : var ( -- accent2 ); }
. live-intel-title . badge {
margin-left : auto ;
font-size : 0.6 rem ;
font-weight : 700 ;
padding : 0.12 rem 0.5 rem ;
border-radius : 999 px ;
background : rgba ( 100 , 116 , 139 , 0.15 );
color : var ( -- muted );
text-transform : uppercase ;
letter-spacing : 0.06 em ;
}
. live-intel-title . badge . live {
background : rgba ( 0 , 212 , 170 , 0.15 );
color : var ( -- teal );
}
. live-intel-title . badge . live :: before {
content : '●' ;
margin-right : 0.25 rem ;
animation : pulse-dot 1.8 s ease-in-out infinite ;
}
. live-intel-body {
flex : 1 ;
overflow-y : auto ;
scrollbar-width : thin ;
scrollbar-color : rgba ( 255 , 255 , 255 , 0.1 ) transparent ;
}
. live-intel-body :: -webkit-scrollbar { width : 3 px ; }
. live-intel-body :: -webkit-scrollbar-thumb { background : rgba ( 255 , 255 , 255 , 0.08 ); border-radius : 999 px ; }
. live-intel-empty {
color : var ( -- muted );
font-size : 0.76 rem ;
padding : 1 rem 0.5 rem ;
text-align : center ;
}
/* ── Thinking feed entries ──────────────────────────────── */
. tf-entry {
display : flex ;
gap : 0.55 rem ;
padding : 0.5 rem 0.1 rem ;
border-bottom : 1 px solid rgba ( 255 , 255 , 255 , 0.03 );
font-size : 0.76 rem ;
line-height : 1.45 ;
animation : tf-slidein 0.25 s ease both ;
}
@ keyframes tf-slidein {
from { opacity : 0 ; transform : translateY ( -4 px ); }
to { opacity : 1 ; transform : translateY ( 0 ); }
}
. tf-entry : last-child { border-bottom : none ; }
. tf-marker {
flex-shrink : 0 ;
width : 18 px ;
text-align : center ;
font-weight : 700 ;
font-size : 0.78 rem ;
margin-top : 0.05 em ;
}
. tf-entry . info . tf-marker { color : var ( -- muted ); }
. tf-entry . reasoning . tf-marker { color : var ( -- accent2 ); }
. tf-entry . decision . tf-marker { color : var ( -- teal ); }
. tf-entry . success . tf-marker { color : var ( -- green ); }
. tf-entry . warning . tf-marker { color : var ( -- yellow ); }
. tf-entry . hypothesis . tf-marker { color : #a78bfa ; }
. tf-body { flex : 1 ; min-width : 0 ; }
. tf-msg { color : var ( -- text ); word-wrap : break-word ; }
. tf-entry . info . tf-msg { color : #94a3b8 ; }
. tf-entry . warning . tf-msg { color : #fbbf24 ; }
. tf-meta {
font-size : 0.62 rem ;
color : var ( -- muted );
margin-top : 0.15 rem ;
display : flex ;
gap : 0.5 rem ;
font-family : 'JetBrains Mono' , monospace ;
}
. tf-chip {
display : inline-block ;
padding : 0.05 rem 0.35 rem ;
border-radius : 4 px ;
background : rgba ( 255 , 255 , 255 , 0.05 );
color : var ( -- muted );
font-size : 0.6 rem ;
letter-spacing : 0.04 em ;
}
/* ── Parameter Changes list ─────────────────────────────── */
. pc-iteration {
border-bottom : 1 px solid rgba ( 255 , 255 , 255 , 0.04 );
padding : 0.55 rem 0.1 rem ;
animation : tf-slidein 0.25 s ease both ;
}
. pc-iteration : last-child { border-bottom : none ; }
. pc-iter-header {
display : flex ;
align-items : center ;
gap : 0.4 rem ;
font-size : 0.72 rem ;
color : var ( -- text );
font-weight : 600 ;
margin-bottom : 0.3 rem ;
}
. pc-iter-label {
background : rgba ( 79 , 70 , 229 , 0.15 );
color : var ( -- accent2 );
font-family : 'JetBrains Mono' , monospace ;
padding : 0.08 rem 0.4 rem ;
border-radius : 4 px ;
font-size : 0.65 rem ;
}
. pc-iter-conf {
margin-left : auto ;
font-size : 0.62 rem ;
color : var ( -- muted );
}
. pc-change {
font-size : 0.7 rem ;
line-height : 1.55 ;
padding : 0.12 rem 0 ;
}
. pc-param { color : var ( -- teal ); font-family : 'JetBrains Mono' , monospace ; }
. pc-arrow { color : var ( -- muted ); margin : 0 0.3 rem ; }
. pc-oldval { color : var ( -- muted ); font-family : 'JetBrains Mono' , monospace ; text-decoration : line-through ; }
. pc-newval { color : var ( -- text ); font-family : 'JetBrains Mono' , monospace ; font-weight : 600 ; }
. pc-reason { color : #94a3b8 ; font-size : 0.66 rem ; margin-left : 1.3 rem ; font-style : italic ; }
/* ── Validation Live Panel ──────────────────────────────── */
. val-header {
font-size : 0.7 rem ;
color : var ( -- muted );
margin-bottom : 0.5 rem ;
}
. val-progress-row {
display : flex ;
align-items : center ;
gap : 0.45 rem ;
font-size : 0.68 rem ;
color : var ( -- muted );
margin-bottom : 0.6 rem ;
}
. val-progress-bar {
flex : 1 ;
height : 4 px ;
background : rgba ( 255 , 255 , 255 , 0.07 );
border-radius : 999 px ;
overflow : hidden ;
}
. val-progress-fill {
height : 100 % ;
background : linear-gradient ( 90 deg , var ( -- accent ), var ( -- teal ));
width : 0 % ;
transition : width 0.4 s ease ;
}
. val-run {
border : 1 px solid var ( -- border );
border-radius : 8 px ;
padding : 0.55 rem 0.7 rem ;
margin-bottom : 0.4 rem ;
background : rgba ( 255 , 255 , 255 , 0.02 );
animation : tf-slidein 0.25 s ease both ;
}
. val-run . active { border-color : rgba ( 0 , 212 , 170 , 0.4 ); background : rgba ( 0 , 212 , 170 , 0.04 ); }
. val-run . pass { border-color : rgba ( 16 , 185 , 129 , 0.35 ); }
. val-run . fail { border-color : rgba ( 239 , 68 , 68 , 0.35 ); }
. val-run-title {
font-size : 0.72 rem ;
font-weight : 600 ;
color : var ( -- text );
display : flex ;
align-items : center ;
gap : 0.4 rem ;
}
. val-run-kind {
font-size : 0.58 rem ;
font-weight : 700 ;
padding : 0.08 rem 0.4 rem ;
border-radius : 4 px ;
text-transform : uppercase ;
letter-spacing : 0.06 em ;
background : rgba ( 100 , 116 , 139 , 0.15 );
color : var ( -- muted );
}
. val-run-kind . oos { background : rgba ( 79 , 70 , 229 , 0.18 ); color : var ( -- accent2 ); }
. val-run-kind . sensitivity { background : rgba ( 245 , 158 , 11 , 0.15 ); color : var ( -- yellow ); }
. val-run-desc { font-size : 0.64 rem ; color : #94a3b8 ; margin-top : 0.2 rem ; line-height : 1.4 ; }
. val-run-metrics {
display : grid ;
grid-template-columns : repeat ( 4 , 1 fr );
gap : 0.3 rem ;
margin-top : 0.4 rem ;
}
. val-metric { background : rgba ( 255 , 255 , 255 , 0.03 ); border-radius : 5 px ; padding : 0.25 rem 0.4 rem ; }
. val-metric-lbl { font-size : 0.55 rem ; color : var ( -- muted ); text-transform : uppercase ; letter-spacing : 0.04 em ; }
. val-metric-val { font-size : 0.72 rem ; font-weight : 700 ; margin-top : 0.05 rem ; }
. val-spinner {
display : inline-block ;
width : 10 px ; height : 10 px ;
border : 2 px solid rgba ( 124 , 109 , 250 , 0.3 );
border-top-color : var ( -- accent2 );
border-radius : 50 % ;
animation : ai-spin 0.8 s linear infinite ;
}
/* ── Early Termination Banner ───────────────────────────── */
. early-term-banner {
display : none ;
flex-direction : column ;
gap : 0.35 rem ;
padding : 0.85 rem 1.1 rem ;
background : rgba ( 245 , 158 , 11 , 0.08 );
border : 1 px solid rgba ( 245 , 158 , 11 , 0.28 );
border-radius : 12 px ;
font-size : 0.82 rem ;
color : var ( -- yellow );
animation : tf-slidein 0.3 s ease both ;
}
. early-term-banner . active { display : flex ; }
. early-term-banner . success { background : rgba ( 16 , 185 , 129 , 0.08 ); border-color : rgba ( 16 , 185 , 129 , 0.3 ); color : var ( -- green ); }
. early-term-banner . warning { background : rgba ( 245 , 158 , 11 , 0.08 ); border-color : rgba ( 245 , 158 , 11 , 0.28 ); color : var ( -- yellow ); }
. early-term-banner . critical { background : rgba ( 239 , 68 , 68 , 0.1 ); border-color : rgba ( 239 , 68 , 68 , 0.3 ); color : var ( -- red ); }
. early-term-title { display : flex ; align-items : center ; gap : 0.55 rem ; font-weight : 700 ; }
. early-term-msg { font-size : 0.75 rem ; color : var ( -- text ); line-height : 1.5 ; font-weight : 500 ; }
. early-term-details {
font-size : 0.7 rem ;
color : var ( -- muted );
margin-top : 0.2 rem ;
display : flex ;
flex-wrap : wrap ;
gap : 0.5 rem 1 rem ;
}
. early-term-dismiss {
background : transparent ;
border : none ;
color : var ( -- muted );
cursor : pointer ;
margin-left : auto ;
font-size : 1 rem ;
line-height : 1 ;
padding : 0 ;
}
. early-term-dismiss : hover { color : var ( -- text ); }
/* ── Phase tracker (enhanced) ───────────────────────────── */
. phase-step . phase-sub {
font-size : 0.55 rem ;
color : var ( -- muted );
margin-top : 0.1 rem ;
text-align : center ;
font-family : 'JetBrains Mono' , monospace ;
line-height : 1 ;
}
. phase-step . active . phase-sub { color : var ( -- teal ); }
2026-04-13 21:14:47 +00:00
</ style >
</ head >
< body >
2026-04-25 11:39:17 +00:00
< div class = "app-shell" >
<!-- ══════════════════════════════════════
SIDEBAR
══════════════════════════════════════ -->
< aside class = "sidebar" >
<!-- Logo -->
< div class = "logo-wrap" >
< svg width = "36" height = "40" viewBox = "0 0 40 44" fill = "none" xmlns = "http://www.w3.org/2000/svg" >
< defs >
< linearGradient id = "logoGrad" x1 = "0%" y1 = "0%" x2 = "100%" y2 = "100%" >
< stop offset = "0%" stop-color = "#00e5ff" />
< stop offset = "45%" stop-color = "#4f46e5" />
< stop offset = "100%" stop-color = "#7c3aed" />
</ linearGradient >
< clipPath id = "sbTriClip" >
< polygon points = "20,2 39,40 1,40" />
</ clipPath >
</ defs >
< polygon points = "20,2 39,40 1,40" fill = "rgba(79,70,229,0.08)" stroke = "url(#logoGrad)" stroke-width = "2" stroke-linejoin = "round" />
< line x1 = "10" y1 = "30" x2 = "30" y2 = "30" stroke = "url(#logoGrad)" stroke-width = "1.5" />
< rect x = "11" y = "31" width = "4" height = "8" rx = "0.8" fill = "url(#logoGrad)" opacity = "0.5" clip-path = "url(#sbTriClip)" />
< rect x = "17" y = "24" width = "4" height = "15" rx = "0.8" fill = "url(#logoGrad)" opacity = "0.75" clip-path = "url(#sbTriClip)" />
< rect x = "23" y = "18" width = "4" height = "21" rx = "0.8" fill = "url(#logoGrad)" clip-path = "url(#sbTriClip)" />
< polyline points = "8,38 17,27 22,30 33,16" stroke = "#00e5ff" stroke-width = "1.5" stroke-linecap = "round" stroke-linejoin = "round" clip-path = "url(#sbTriClip)" opacity = "0.9" />
</ svg >
< div >
< span class = "logo-text" > APEX</ span >
< span class = "logo-tagline" > AI Optimizer</ span >
</ div >
</ div >
<!-- Navigation -->
< nav class = "sidebar-nav" >
< a href = "/dashboard" class = "nav-item active" data-page = "dashboard" >
< svg width = "15" height = "15" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" >
< path d = "M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z" />< polyline points = "9 22 9 12 15 12 15 22" />
</ svg >
Dashboard
</ a >
< a href = "/setup" class = "nav-item" data-page = "setup" >
< svg width = "15" height = "15" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" >
< line x1 = "4" y1 = "21" x2 = "4" y2 = "14" />< line x1 = "4" y1 = "10" x2 = "4" y2 = "3" />
< line x1 = "12" y1 = "21" x2 = "12" y2 = "12" />< line x1 = "12" y1 = "8" x2 = "12" y2 = "3" />
< line x1 = "20" y1 = "21" x2 = "20" y2 = "16" />< line x1 = "20" y1 = "12" x2 = "20" y2 = "3" />
< line x1 = "1" y1 = "14" x2 = "7" y2 = "14" />< line x1 = "9" y1 = "8" x2 = "15" y2 = "8" />< line x1 = "17" y1 = "16" x2 = "23" y2 = "16" />
</ svg >
New Run
</ a >
< a href = "/reports" class = "nav-item" data-page = "reports" >
< svg width = "15" height = "15" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" >
< line x1 = "18" y1 = "20" x2 = "18" y2 = "10" />< line x1 = "12" y1 = "20" x2 = "12" y2 = "4" />
< line x1 = "6" y1 = "20" x2 = "6" y2 = "14" />< line x1 = "2" y1 = "20" x2 = "22" y2 = "20" />
</ svg >
Reports
</ a >
< a href = "https://github.com/your-user/MT5_Optimizer" target = "_blank" rel = "noopener" class = "nav-item" data-page = "github" >
< svg width = "15" height = "15" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" >
< path d = "M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22" />
</ svg >
Source on GitHub
</ a >
< a href = "#" class = "nav-item" data-page = "set" onclick = "openSettings(); return false;" >
<!-- Gear icon -->
< svg width = "15" height = "15" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" >
< circle cx = "12" cy = "12" r = "3" />
< path d = "M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z" />
</ svg >
Settings
</ a >
</ nav >
<!-- Footer: MT5 status -->
< div class = "sidebar-footer" >
< div class = "mt5-status" >
< div class = "mt5-dot" id = "mt5-dot" ></ div >
2026-04-13 21:14:47 +00:00
< div >
2026-04-25 11:39:17 +00:00
< div class = "mt5-label" > MT5 Connection</ div >
< div class = "mt5-state" id = "mt5-state" > Ready</ div >
2026-04-13 21:14:47 +00:00
</ div >
</ div >
2026-04-25 11:39:17 +00:00
< div class = "mt5-brand" >
< svg width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >
< rect x = "2" y = "3" width = "20" height = "14" rx = "2" />< line x1 = "8" y1 = "21" x2 = "16" y2 = "21" />< line x1 = "12" y1 = "17" x2 = "12" y2 = "21" />
</ svg >
MetaTrader 5
</ div >
2026-04-13 21:14:47 +00:00
</ div >
2026-04-25 11:39:17 +00:00
</ aside >
<!-- ══════════════════════════════════════
MAIN CONTENT
══════════════════════════════════════ -->
< div class = "main-content" id = "main-content" >
<!-- ── Command Header ────────────────────────────────────── -->
< div class = "cmd-header" >
<!-- Logo -->
< div class = "cmd-logo" >
< svg width = "32" height = "36" viewBox = "0 0 40 44" fill = "none" xmlns = "http://www.w3.org/2000/svg" >
< defs >
< linearGradient id = "hdrLogoGrad" x1 = "0%" y1 = "0%" x2 = "100%" y2 = "100%" >
< stop offset = "0%" stop-color = "#00e5ff" />
< stop offset = "45%" stop-color = "#4f46e5" />
< stop offset = "100%" stop-color = "#7c3aed" />
</ linearGradient >
< clipPath id = "hdrTriClip" >
< polygon points = "20,2 39,40 1,40" />
</ clipPath >
</ defs >
< polygon points = "20,2 39,40 1,40" fill = "rgba(79,70,229,0.09)" stroke = "url(#hdrLogoGrad)" stroke-width = "1.8" stroke-linejoin = "round" />
< line x1 = "10" y1 = "30" x2 = "30" y2 = "30" stroke = "url(#hdrLogoGrad)" stroke-width = "1.4" />
< rect x = "11" y = "31" width = "4" height = "8" rx = "0.8" fill = "url(#hdrLogoGrad)" opacity = "0.5" clip-path = "url(#hdrTriClip)" />
< rect x = "17" y = "24" width = "4" height = "15" rx = "0.8" fill = "url(#hdrLogoGrad)" opacity = "0.75" clip-path = "url(#hdrTriClip)" />
< rect x = "23" y = "18" width = "4" height = "21" rx = "0.8" fill = "url(#hdrLogoGrad)" clip-path = "url(#hdrTriClip)" />
< polyline points = "8,38 17,27 22,30 33,16" stroke = "#00e5ff" stroke-width = "1.5" stroke-linecap = "round" stroke-linejoin = "round" clip-path = "url(#hdrTriClip)" opacity = "0.9" />
</ svg >
< div class = "cmd-logo-text" >
< span class = "cmd-apex" > APEX</ span >
< span class = "cmd-tagline" > AI Powered EA Optimizer</ span >
</ div >
2026-04-13 21:14:47 +00:00
</ div >
2026-04-25 11:39:17 +00:00
< div class = "cmd-sep" ></ div >
<!-- Status -->
< div class = "cmd-section" >
< div class = "cmd-status-row" >
< div class = "cmd-status-dot" id = "hdr-dot" ></ div >
< span class = "cmd-status-label" id = "hdr-status" > System Idle</ span >
</ div >
< div class = "cmd-section-sub" id = "hdr-status-sub" > Ready to optimize</ div >
2026-04-13 21:14:47 +00:00
</ div >
2026-04-25 11:39:17 +00:00
< div class = "cmd-sep" ></ div >
<!-- Generation / Progress -->
< div class = "cmd-section cmd-gen-section" >
< div class = "cmd-gen-row" >
< span class = "cmd-gen-label" > Generation</ span >
< span class = "cmd-gen-val" >< span id = "hdr-gen-cur" > 0</ span >< span class = "cmd-gen-sep" > /</ span >< span id = "hdr-gen-total" > —</ span ></ span >
</ div >
< div class = "cmd-prog-track" >
< div class = "cmd-prog-fill" id = "hdr-prog-fill" style = "width:0%" ></ div >
</ div >
< div class = "cmd-pct-label" id = "hdr-pct" > 0% Complete</ div >
2026-04-13 21:14:47 +00:00
</ div >
2026-04-25 11:39:17 +00:00
< div class = "cmd-sep" ></ div >
<!-- Best Score -->
< div class = "cmd-section" >
< div class = "cmd-score-label" > Best Score</ div >
< div class = "cmd-score-val" id = "hdr-score" > —</ div >
< div class = "cmd-score-delta" id = "hdr-score-delta" > Waiting for results...</ div >
</ div >
< div class = "cmd-spacer" ></ div >
<!-- Action buttons -->
< div class = "cmd-actions" >
< a href = "/setup" class = "cmd-btn cmd-btn-start" >
< svg width = "12" height = "12" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2.5" >< line x1 = "12" y1 = "5" x2 = "12" y2 = "19" />< line x1 = "5" y1 = "12" x2 = "19" y2 = "12" /></ svg >
Start New
</ a >
<!-- Pause is intentionally not shown — pipeline doesn't currently support it
(see: optimizer/pipeline.py — only _stop_flag exists, no _pause_event). -->
< button class = "cmd-btn cmd-btn-stop" id = "btn-stop" >
< svg width = "12" height = "12" viewBox = "0 0 24 24" fill = "currentColor" >< rect x = "4" y = "4" width = "16" height = "16" rx = "2" /></ svg >
Stop
</ button >
</ div >
<!-- Hidden run-indicator kept for JS compatibility -->
< div id = "run-indicator" style = "display:none!important;" >< span id = "run-indicator-label" ></ span ></ div >
</ div >
<!-- No-profit error banner -->
< div class = "no-profit-banner" id = "no-profit-banner" >
< span class = "no-profit-banner-icon" > ⚠</ span >
< div >
< strong > No profitable configuration found.</ strong >
< span id = "no-profit-msg" > Try different parameters or date ranges.</ span >
2026-04-13 21:14:47 +00:00
</ div >
</ div >
2026-04-25 11:39:17 +00:00
<!-- Early Termination banner (dismissible) -->
< div class = "early-term-banner" id = "early-term-banner" >
< div class = "early-term-title" >
< span id = "early-term-icon" > ⚠</ span >
< span id = "early-term-heading" > Optimization stopped early</ span >
< button class = "early-term-dismiss" onclick = "dismissEarlyTerm()" > ✕</ button >
</ div >
< div class = "early-term-msg" id = "early-term-msg" ></ div >
< div class = "early-term-details" id = "early-term-details" ></ div >
2026-04-13 21:14:47 +00:00
</ div >
2026-04-25 11:39:17 +00:00
<!-- ── Metric cards ────────────────────────────────────────── -->
< div class = "metrics-row" >
2026-04-13 21:14:47 +00:00
2026-04-25 11:39:17 +00:00
<!-- Net Profit (clickable → Best Result detail) -->
< div class = "metric-card" id = "best-card" onclick = "openBestResult()" style = "cursor:pointer" title = "Click to see how the AI arrived at this best result" >
< div class = "metric-label" > Best Net Profit < span style = "font-size:0.55rem;color:var(--accent2);font-weight:700" > ▸ details</ span ></ div >
< div class = "metric-value green" id = "m-net-profit" > $0.00</ div >
< div class = "metric-delta" id = "m-net-profit-delta" >
< span class = "delta-up" > ↑</ span >
< span id = "m-net-profit-delta-val" > 0%</ span >
< span style = "margin-left:2px" > vs baseline</ span >
</ div >
< div class = "sparkline-wrap" >
< canvas id = "spark-profit" width = "80" height = "28" ></ canvas >
2026-04-13 21:14:47 +00:00
</ div >
</ div >
2026-04-25 11:39:17 +00:00
<!-- Max Drawdown -->
< div class = "metric-card" >
< div class = "metric-label" > Max Drawdown</ div >
< div class = "metric-value red" id = "m-max-dd" > 0.00%</ div >
< div class = "metric-delta" id = "m-max-dd-delta" >
< span class = "delta-down" > ↓</ span >
< span id = "m-max-dd-delta-val" > 0%</ span >
< span style = "margin-left:2px" > vs baseline</ span >
2026-04-13 21:14:47 +00:00
</ div >
2026-04-25 11:39:17 +00:00
< div class = "sparkline-wrap" >
< canvas id = "spark-dd" width = "80" height = "28" ></ canvas >
2026-04-13 21:14:47 +00:00
</ div >
</ div >
2026-04-25 11:39:17 +00:00
<!-- Profit Factor -->
< div class = "metric-card" >
< div class = "metric-label" > Profit Factor</ div >
< div class = "metric-value gold" id = "m-pf" > 0.00</ div >
< div class = "metric-delta" >
< span id = "m-pf-quality" style = "color:var(--muted)" > —</ span >
2026-04-13 21:14:47 +00:00
</ div >
2026-04-25 11:39:17 +00:00
< div class = "sparkline-wrap" >
< canvas id = "spark-pf" width = "80" height = "28" ></ canvas >
2026-04-13 21:14:47 +00:00
</ div >
2026-04-25 11:39:17 +00:00
</ div >
<!-- Total Trades -->
< div class = "metric-card" >
< div class = "metric-label" > Total Trades</ div >
< div class = "metric-value teal" id = "m-trades" > 0</ div >
< div class = "metric-delta" >
< span style = "color:var(--muted)" > This run</ span >
</ div >
< div class = "sparkline-wrap" >
< canvas id = "spark-trades" width = "80" height = "28" ></ canvas >
</ div >
</ div >
<!-- Optimization Runs -->
< div class = "metric-card" >
< div class = "metric-label" > Optimization Runs</ div >
< div class = "metric-value white" id = "m-runs" > 0</ div >
< div class = "metric-delta" >
< span style = "color:var(--muted)" > This session</ span >
</ div >
< div class = "sparkline-wrap" >
< canvas id = "spark-runs" width = "80" height = "28" ></ canvas >
</ div >
</ div >
<!-- AI Confidence (special) -->
< div class = "metric-card ai-conf-card" >
< div class = "metric-label" > AI Confidence</ div >
< div class = "ai-conf-value" id = "ai-conf-label" > —</ div >
< div class = "ai-gauge-wrap" >
< svg id = "ai-gauge" width = "60" height = "60" viewBox = "0 0 64 64" >
< circle cx = "32" cy = "32" r = "26" fill = "none" stroke = "rgba(255,255,255,0.07)" stroke-width = "6" />
< circle id = "ai-gauge-arc" cx = "32" cy = "32" r = "26" fill = "none"
stroke = "#00d4aa" stroke-width = "6" stroke-linecap = "round"
stroke-dasharray = "163.4" stroke-dashoffset = "163.4"
transform = "rotate(-90 32 32)"
style = "transition: stroke-dashoffset 1s ease, stroke 0.5s ease" />
< text id = "ai-gauge-pct" x = "32" y = "37" text-anchor = "middle"
fill = "#e2e8f0" font-size = "12" font-weight = "700" font-family = "Inter, sans-serif" > 0%</ text >
</ svg >
</ div >
</ div >
</ div >
<!-- ── Charts + AI panel ────────────────────────────────────── -->
< div class = "charts-ai-row" >
<!-- Left: charts column -->
< div class = "charts-col" >
<!-- Equity Curve -->
< div class = "card" >
< div class = "card-header" >
< div class = "card-title" >
< div class = "dot" ></ div >
Equity Curve
</ div >
< div style = "display:flex;gap:0.6rem;align-items:center;" >
< span style = "font-size:0.68rem;color:var(--muted);display:flex;align-items:center;gap:0.3rem;" >
< span style = "display:inline-block;width:20px;height:2px;background:#4f46e5;border-radius:2px;" ></ span > Equity
</ span >
< span style = "font-size:0.68rem;color:var(--muted);display:flex;align-items:center;gap:0.3rem;" >
< span style = "display:inline-block;width:20px;height:2px;background:#00d4aa;border-radius:2px;border-bottom:2px dashed #00d4aa;height:0;" ></ span > Balance
</ span >
< div class = "card-badge" id = "equity-badge" > Live</ div >
</ div >
2026-04-13 21:14:47 +00:00
</ div >
2026-04-25 11:39:17 +00:00
< div class = "chart-wrap equity-chart-wrap" >
< canvas id = "equityChart" ></ canvas >
</ div >
</ div >
<!-- Drawdown Chart -->
< div class = "card" >
< div class = "card-header" >
< div class = "card-title" >
< div class = "dot" style = "background:var(--red);" ></ div >
Drawdown Analysis
</ div >
< span class = "card-badge" id = "max-dd-badge" style = "background:rgba(239,68,68,0.12);color:var(--red);" > Max DD: 0%</ span >
</ div >
< div class = "chart-wrap drawdown-chart-wrap" >
< canvas id = "drawdownChart" ></ canvas >
</ div >
</ div >
</ div >
<!-- Right: AI panel -->
< div class = "ai-panel-col" >
< div class = "ai-panel-card" id = "ai-panel" >
< div class = "ai-panel-header" >
< div class = "ai-panel-title" >
< span class = "ai-icon" > ✦</ span >
AI Summary
</ div >
< a href = "#" class = "view-details-link" id = "ai-view-details" onclick = "toggleAIDetails(); return false;" > View Details →</ a >
</ div >
<!-- Waiting state -->
< div class = "ai-waiting" id = "ai-waiting" >
< div class = "ai-pulse-dot" ></ div >
< span > Waiting for optimization to start...</ span >
</ div >
<!-- Active state -->
< div class = "ai-content" id = "ai-content" style = "display:none;" >
<!-- Collapsed preview (always shown when data loaded) -->
< div class = "ai-preview" id = "ai-preview" >
< div class = "ai-headline" id = "ai-headline" style = "display:none;" ></ div >
< p class = "ai-diagnosis" id = "ai-diagnosis-text" > —</ p >
< button class = "ai-expand-btn" id = "ai-expand-btn" onclick = "toggleAIDetails()" > View Details →</ button >
</ div >
<!-- Expanded details (hidden by default) -->
< div class = "ai-details" id = "ai-details" >
< div id = "ai-strengths-section" style = "display:none;" >
< div class = "ai-sub-title" > Top Patterns</ div >
< ul class = "ai-check-list" id = "ai-strengths-list" ></ ul >
</ div >
< div class = "ai-suggestion-box" id = "ai-suggestion-box" style = "display:none;" >
< div class = "ai-sub-title" style = "margin-bottom:0.3rem;" > Key Suggestion</ div >
< p class = "ai-suggestion-text" id = "ai-suggestion-text" ></ p >
< div class = "ai-badge" > AI</ div >
</ div >
< div id = "ai-risks-section" style = "display:none;" >
< div class = "ai-sub-title warn" > Risk Flags</ div >
< ul class = "ai-warn-list" id = "ai-risks-list" ></ ul >
</ div >
</ div >
< div class = "ai-confidence-row" >
< span class = "ai-conf-badge" id = "ai-panel-conf-badge" > analyzing</ span >
< span class = "ai-run-ref" id = "ai-run-ref" ></ span >
</ div >
2026-04-13 21:14:47 +00:00
</ div >
</ div >
</ div >
</ div >
2026-04-25 11:39:17 +00:00
<!-- ── Live Intelligence (thinking feed / param changes / validation) ── -->
< div class = "live-intel-row" >
2026-04-13 21:14:47 +00:00
2026-04-25 11:39:17 +00:00
<!-- AI Thinking Feed -->
< div class = "live-intel-card accent" >
< div class = "live-intel-title" >
< span class = "icon" > ✦</ span >
AI Thinking
< span class = "badge" id = "tf-badge" > Idle</ span >
</ div >
< div class = "live-intel-body" id = "thinking-feed" >
< div class = "live-intel-empty" > Waiting for the optimizer to start…< br >< span style = "font-size:0.68rem" > The AI's reasoning will stream here in real time.</ span ></ div >
2026-04-13 21:14:47 +00:00
</ div >
</ div >
2026-04-25 11:39:17 +00:00
<!-- Parameter Changes -->
< div class = "live-intel-card" >
< div class = "live-intel-title" >
< svg class = "icon" width = "13" height = "13" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< polyline points = "22 12 18 12 15 21 9 3 6 12 2 12" /></ svg >
Parameter Changes
< span class = "badge" id = "pc-badge" > —</ span >
2026-04-13 21:14:47 +00:00
</ div >
2026-04-25 11:39:17 +00:00
< div class = "live-intel-body" id = "param-changes-list" >
< div class = "live-intel-empty" > No iterations yet.< br >< span style = "font-size:0.68rem" > AI-driven parameter edits appear per iteration.</ span ></ div >
</ div >
</ div >
<!-- Validation Activity -->
< div class = "live-intel-card" >
< div class = "live-intel-title" >
< svg class = "icon" width = "13" height = "13" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< path d = "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" /></ svg >
Validation
< span class = "badge" id = "val-badge" > Pending</ span >
</ div >
< div class = "live-intel-body" id = "validation-panel" >
< div class = "live-intel-empty" > Validation runs after optimization.< br >< span style = "font-size:0.68rem" > Out-of-sample + sensitivity tests.</ span ></ div >
</ div >
</ div >
</ div >
<!-- ── Bottom row ───────────────────────────────────────────── -->
< div class = "bottom-row" >
<!-- Top Parameters -->
< div class = "bottom-card" >
< div class = "bottom-card-title" >
Top Parameters
< span style = "font-size:0.65rem;color:var(--muted);font-weight:400;" > (Best Run)</ span >
</ div >
< div style = "overflow-x:auto;flex:1;" >
< table class = "params-table" id = "params-table" >
2026-04-13 21:14:47 +00:00
< thead >
< tr >
2026-04-25 11:39:17 +00:00
< th > Parameter</ th >
< th > Value</ th >
< th > Impact</ th >
2026-04-13 21:14:47 +00:00
</ tr >
</ thead >
2026-04-25 11:39:17 +00:00
< tbody id = "params-tbody" >
< tr >< td colspan = "3" class = "empty-state" > Run optimizer to see parameters</ td ></ tr >
</ tbody >
2026-04-13 21:14:47 +00:00
</ table >
</ div >
</ div >
2026-04-25 11:39:17 +00:00
<!-- Optimization Progress -->
< div class = "bottom-card" >
< div class = "bottom-card-title" > Optimization Progress</ div >
< div style = "display:flex;flex-direction:column;gap:0.5rem;flex:1;" >
< div class = "opt-gen-label" id = "opt-gen" > Generation — / —</ div >
< div class = "opt-progress-bar-track" >
< div class = "opt-progress-bar-fill" id = "opt-progress-fill" style = "width:0%" ></ div >
</ div >
< div class = "opt-stats-grid" >
< div class = "opt-stat" >
< div class = "opt-stat-label" > Current Phase</ div >
< div class = "opt-stat-val" id = "opt-phase" > Waiting</ div >
</ div >
< div class = "opt-stat" >
< div class = "opt-stat-label" > Elapsed</ div >
< div class = "opt-stat-val" id = "opt-elapsed" > —</ div >
</ div >
< div class = "opt-stat" >
< div class = "opt-stat-label" > Est. Remaining</ div >
< div class = "opt-stat-val" id = "opt-remaining" > —</ div >
</ div >
</ div >
<!-- Phase steps -->
< div class = "phase-steps" id = "phase-steps" >
< div class = "phase-step" id = "phase-step-1" >
< div class = "phase-dot" > 1</ div >
< div class = "phase-name" > Exploration</ div >
< div class = "phase-sub" id = "phase-sub-1" > —</ div >
</ div >
< div class = "phase-connector" ></ div >
< div class = "phase-step" id = "phase-step-2" >
< div class = "phase-dot" > 2</ div >
< div class = "phase-name" > Iteration</ div >
< div class = "phase-sub" id = "phase-sub-2" > —</ div >
</ div >
< div class = "phase-connector" ></ div >
< div class = "phase-step" id = "phase-step-3" >
< div class = "phase-dot" > 3</ div >
< div class = "phase-name" > Validation</ div >
< div class = "phase-sub" id = "phase-sub-3" > —</ div >
</ div >
</ div >
2026-04-13 21:14:47 +00:00
</ div >
</ div >
2026-04-25 11:39:17 +00:00
<!-- Recent Runs -->
< div class = "bottom-card" >
< div class = "bottom-card-title" >
Recent Runs
< a href = "/reports" class = "view-all-link" > View All →</ a >
2026-04-13 21:14:47 +00:00
</ div >
2026-04-25 11:39:17 +00:00
< div style = "overflow-x:auto;flex:1;" >
< table class = "runs-table" >
< thead >
< tr >
< th > Run</ th >
< th > Net Profit</ th >
< th > PF</ th >
< th > Max DD</ th >
< th > Verdict</ th >
< th ></ th >
</ tr >
</ thead >
< tbody id = "recent-runs-tbody" >
< tr >< td colspan = "6" class = "empty-state" > No runs yet</ td ></ tr >
</ tbody >
</ table >
2026-04-13 21:14:47 +00:00
</ div >
</ div >
</ div >
2026-04-25 11:39:17 +00:00
<!-- ── Live log (collapsible) ───────────────────────────────── -->
< div class = "log-panel" >
< button class = "log-toggle-btn" id = "log-toggle-btn" onclick = "toggleLog()" >
< span style = "display:flex;align-items:center;gap:0.5rem;" >
< svg width = "12" height = "12" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< polyline points = "4 17 10 11 4 5" />< line x1 = "12" y1 = "19" x2 = "20" y2 = "19" /></ svg >
Live Log
< span id = "log-count" style = "background:rgba(100,116,139,0.2);color:var(--muted);font-size:0.65rem;padding:0.05rem 0.4rem;border-radius:999px;font-weight:600;" > 0</ span >
</ span >
< svg class = "log-toggle-icon" id = "log-toggle-icon" width = "14" height = "14" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< polyline points = "6 9 12 15 18 9" /></ svg >
</ button >
< div class = "log-body" id = "log-body" >
< div class = "log-feed" id = "log-feed" ></ div >
</ div >
</ div >
</ div > <!-- /.main-content -->
</ div > <!-- /.app-shell -->
<!-- ══════════════════════════════════════
SETTINGS MODAL
══════════════════════════════════════ -->
< div class = "settings-overlay" id = "settings-overlay" style = "display:none;" onclick = "if(event.target===this)closeSettings()" >
< div class = "settings-card" >
< div class = "settings-header" >
< div class = "settings-title" >
< svg width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" >
< circle cx = "12" cy = "12" r = "3" />
< path d = "M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z" />
</ svg >
Settings
</ div >
< button class = "settings-close-btn" onclick = "closeSettings()" > ✕</ button >
</ div >
< div class = "settings-tabs" >
< div class = "settings-tab active" data-tab = "ai" onclick = "switchSettingsTab('ai')" >
< svg width = "13" height = "13" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< polygon points = "13 2 3 14 12 14 11 22 21 10 12 10 13 2" /></ svg >
AI Engine
</ div >
< div class = "settings-tab" data-tab = "mt5" onclick = "switchSettingsTab('mt5')" >
< svg width = "13" height = "13" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< rect x = "2" y = "3" width = "20" height = "14" rx = "2" />< line x1 = "8" y1 = "21" x2 = "16" y2 = "21" />< line x1 = "12" y1 = "17" x2 = "12" y2 = "21" /></ svg >
MetaTrader 5
</ div >
< div class = "settings-tab" data-tab = "broker" onclick = "switchSettingsTab('broker')" >
< svg width = "13" height = "13" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< line x1 = "12" y1 = "1" x2 = "12" y2 = "23" />< path d = "M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6" /></ svg >
Broker
</ div >
< div class = "settings-tab" data-tab = "thresholds" onclick = "switchSettingsTab('thresholds')" >
< svg width = "13" height = "13" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< line x1 = "4" y1 = "21" x2 = "4" y2 = "14" />< line x1 = "4" y1 = "10" x2 = "4" y2 = "3" />< line x1 = "12" y1 = "21" x2 = "12" y2 = "12" />< line x1 = "12" y1 = "8" x2 = "12" y2 = "3" />< line x1 = "20" y1 = "21" x2 = "20" y2 = "16" />< line x1 = "20" y1 = "12" x2 = "20" y2 = "3" />< line x1 = "1" y1 = "14" x2 = "7" y2 = "14" />< line x1 = "9" y1 = "8" x2 = "15" y2 = "8" />< line x1 = "17" y1 = "16" x2 = "23" y2 = "16" /></ svg >
Thresholds
</ div >
</ div >
< div class = "settings-body" >
<!-- AI Engine tab -->
< div class = "settings-panel active" id = "stab-ai" >
< div class = "settings-section-label" > AI Analysis Engine</ div >
< div class = "settings-toggle-row" style = "margin-bottom:0.75rem;" >
< div >
< div class = "settings-toggle-label" > Enable AI Insights</ div >
< div class = "settings-toggle-sub" > Claude analyzes each run and provides actionable suggestions</ div >
</ div >
< button class = "settings-toggle" id = "s-ai-enabled" onclick = "toggleSettingsBool(this)" ></ button >
</ div >
< div class = "settings-grid full" >
< div class = "settings-field" >
< label > Anthropic API Key</ label >
< input type = "password" class = "settings-input mono" id = "s-ai-key" placeholder = "sk-ant-api03-..." autocomplete = "off" >
< div class = "settings-hint" > Your Claude API key from console.anthropic.com. Kept locally in config.yaml.</ div >
</ div >
</ div >
< div class = "settings-grid" style = "margin-top:0.75rem;" >
< div class = "settings-field" >
< label > Model</ label >
< select class = "settings-select" id = "s-ai-model" >
< option value = "claude-opus-4-7" > claude-opus-4-7 (Most capable)</ option >
< option value = "claude-sonnet-4-6" > claude-sonnet-4-6 (Balanced)</ option >
< option value = "claude-haiku-4-5-20251001" > claude-haiku-4-5 (Fast)</ option >
</ select >
</ div >
< div class = "settings-field" >
< label > Timeout (seconds)</ label >
< input type = "number" class = "settings-input" id = "s-ai-timeout" min = "10" max = "120" step = "5" >
</ div >
</ div >
</ div >
<!-- MetaTrader 5 tab -->
< div class = "settings-panel" id = "stab-mt5" >
< div class = "settings-section-label" > Terminal Paths</ div >
< div class = "settings-grid full" >
< div class = "settings-field" >
< label > Terminal Executable</ label >
< input type = "text" class = "settings-input mono" id = "s-mt5-exe" placeholder = "C:/Program Files/MetaTrader 5/terminal64.exe" >
< div class = "settings-hint" > Full path to terminal64.exe</ div >
</ div >
< div class = "settings-field" style = "margin-top:0.5rem;" >
< label > AppData Path</ label >
< input type = "text" class = "settings-input mono" id = "s-mt5-appdata" placeholder = "C:/Users/.../AppData/Roaming/MetaQuotes/Terminal/..." >
</ div >
< div class = "settings-field" style = "margin-top:0.5rem;" >
< label > MQL5 Files Path</ label >
< input type = "text" class = "settings-input mono" id = "s-mt5-mql5" placeholder = "C:/Users/.../MQL5/Files" >
</ div >
</ div >
< div class = "settings-section-label" > Tester Settings</ div >
< div class = "settings-grid" >
< div class = "settings-field" >
< label > Tester Timeout (seconds)</ label >
< input type = "number" class = "settings-input" id = "s-mt5-timeout" min = "30" max = "600" step = "10" >
</ div >
< div class = "settings-field" >
< label > Tester Model</ label >
< select class = "settings-select" id = "s-mt5-model" >
< option value = "1" > 1 — Every tick</ option >
< option value = "2" > 2 — Every tick based on real ticks</ option >
< option value = "3" > 3 — OHLC (M1)</ option >
< option value = "4" > 4 — Open prices only</ option >
< option value = "5" > 5 — Math calculations</ option >
</ select >
< div class = "settings-hint" > Strategy Tester modeling method</ div >
</ div >
</ div >
</ div >
<!-- Broker tab -->
< div class = "settings-panel" id = "stab-broker" >
< div class = "settings-section-label" > Broker Configuration</ div >
< div class = "settings-grid" >
< div class = "settings-field" >
< label > Timezone Offset (hours)</ label >
< input type = "number" class = "settings-input" id = "s-broker-tz" min = "-12" max = "14" step = "0.5" >
< div class = "settings-hint" > GMT offset, e.g. 3 for EET (Eastern European Time)</ div >
</ div >
< div class = "settings-field" >
< label > Account Deposit ($)</ label >
< input type = "number" class = "settings-input" id = "s-broker-deposit" min = "100" step = "100" >
</ div >
< div class = "settings-field" >
< label > Leverage (1:X)</ label >
< input type = "number" class = "settings-input" id = "s-broker-leverage" min = "1" max = "2000" step = "1" >
</ div >
</ div >
</ div >
<!-- Thresholds tab -->
< div class = "settings-panel" id = "stab-thresholds" >
< div class = "settings-section-label" > Quality Filters</ div >
< div class = "settings-grid" >
< div class = "settings-field" >
< label > Min Trades</ label >
< input type = "number" class = "settings-input" id = "s-thr-trades" min = "1" step = "1" >
< div class = "settings-hint" > Minimum trades per backtest to pass</ div >
</ div >
< div class = "settings-field" >
< label > Min Profit Factor</ label >
< input type = "number" class = "settings-input" id = "s-thr-pf" min = "0" max = "10" step = "0.05" >
</ div >
< div class = "settings-field" >
< label > Min Calmar Ratio</ label >
< input type = "number" class = "settings-input" id = "s-thr-calmar" min = "0" max = "10" step = "0.05" >
</ div >
< div class = "settings-field" >
< label > Max OOS Degradation</ label >
< input type = "number" class = "settings-input" id = "s-thr-oos" min = "0" max = "1" step = "0.01" >
< div class = "settings-hint" > Max allowed out-of-sample score drop (0– 1)</ div >
</ div >
< div class = "settings-field" >
< label > Sensitivity Tolerance</ label >
< input type = "number" class = "settings-input" id = "s-thr-sens" min = "0" max = "1" step = "0.01" >
< div class = "settings-hint" > Allowed parameter sensitivity variance (0– 1)</ div >
</ div >
</ div >
</ div >
</ div > <!-- /.settings-body -->
< div class = "settings-footer" >
< span class = "settings-save-msg" id = "settings-save-msg" style = "opacity:0;" ></ span >
< button class = "settings-btn cancel" onclick = "closeSettings()" > Cancel</ button >
< button class = "settings-btn save" id = "settings-save-btn" onclick = "saveSettings()" > Save Settings</ button >
</ div >
</ div >
</ div >
<!-- ══════════════════════════════════════
RUN DETAIL MODAL
══════════════════════════════════════ -->
< div class = "run-detail-overlay" id = "run-detail-overlay" style = "display:none;" onclick = "if(event.target===this)closeRunDetail()" >
< div class = "run-detail-card" >
< div class = "run-detail-header" >
< div >
< div class = "run-detail-title" id = "rd-run-id" > Run Details</ div >
< div class = "run-detail-sub" id = "rd-meta" ></ div >
</ div >
< button class = "settings-close-btn" onclick = "closeRunDetail()" > ✕</ button >
</ div >
< div class = "run-detail-body" >
< div class = "rd-metrics-grid" id = "rd-metrics" ></ div >
< div class = "rd-section-title" > Parameters</ div >
< div class = "rd-params-wrap" >
< table class = "params-table" style = "width:100%" >
< thead >< tr >< th > Parameter</ th >< th > Value</ th ></ tr ></ thead >
< tbody id = "rd-params-tbody" >
< tr >< td colspan = "2" class = "empty-state" > Loading...</ td ></ tr >
</ tbody >
</ table >
</ div >
< div id = "rd-ai-section" style = "display:none;" >
< div class = "rd-section-title" > AI Reasoning</ div >
< div id = "rd-ai-content" ></ div >
</ div >
</ div >
< div class = "run-detail-footer" id = "rd-footer" >
< button class = "verdict-btn ghost" onclick = "closeRunDetail()" > Close</ button >
</ div >
</ div >
</ div >
<!-- ══════════════════════════════════════
VERDICT OVERLAY
══════════════════════════════════════ -->
< div class = "verdict-overlay" id = "verdict-overlay" style = "display:none;" >
< div class = "verdict-card" id = "verdict-card" >
< div class = "verdict-header-row" >
< div class = "verdict-icon-big" id = "verdict-icon" > ✅</ div >
< div >
< div class = "verdict-title" id = "verdict-title" > RECOMMENDED</ div >
< div class = "verdict-subtitle" id = "verdict-subtitle" > Optimization complete.</ div >
</ div >
</ div >
< div class = "verdict-metrics-row" id = "verdict-metrics" ></ div >
< div class = "verdict-actions-row" id = "verdict-actions" ></ div >
</ div >
</ div >
<!-- ══════════════════════════════════════
SCRIPTS
══════════════════════════════════════ -->
< script src = "https://cdn.socket.io/4.7.5/socket.io.min.js" ></ script >
< script src = "https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js" ></ script >
< script src = "/static/js/dashboard.js" ></ script >
2026-04-13 21:14:47 +00:00
</ body >
</ html >