:root{
  /* Sensifai brand green on a white ground. #93D500 is only 1.8:1 against white, so it is used
     for fills and rules, and --accent-text (4.5:1) carries anything that has to be read. */
  --bg:#ffffff; --panel:#ffffff; --ink:#15181d; --muted:#6b7280; --line:#e6e8ec;
  --accent:#93d500; --accent-hover:#a6e61a; --accent-ink:#141a06; --accent-text:#5a8200;
  --accent-soft:rgba(147,213,0,.13); --accent-line:rgba(147,213,0,.42);
  --warm:#93d500; --cold:#8c8c8c; --ok:#3f8f1e;
  --radius:14px; --shadow:0 1px 2px rgba(16,24,40,.05), 0 8px 24px -12px rgba(16,24,40,.18);
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
}
*{box-sizing:border-box}
/* a class that sets `display` otherwise beats the UA rule for the hidden attribute */
[hidden]{display:none !important}
html,body{margin:0;padding:0}
body{
  background:var(--bg); color:var(--ink); font:15px/1.55 -apple-system,BlinkMacSystemFont,
  "Segoe UI",Inter,Roboto,Helvetica,Arial,sans-serif; -webkit-font-smoothing:antialiased;
}
h1,h2,h3{margin:0; font-weight:620; letter-spacing:-.01em}
p{margin:0}
code{font-family:var(--mono); font-size:.9em; background:var(--surface-2, #f4f5f7); padding:.1em .35em; border-radius:5px}
.muted{color:var(--muted); font-size:13.5px}
.error{color:#b42318; font-size:13.5px; margin-top:10px}
.note{color:var(--note-ink, #8a5b00); background:var(--note-bg, #fff8e6); border:1px solid var(--note-line, #f4e3b4); padding:10px 12px;
      border-radius:10px; font-size:13.5px; margin-top:14px}


/* ------------------------------------------------------------------ dark theme
   "system" (no data-theme) follows the media query; data-theme forces one. The brand green
   stays the accent in both -- on a dark ground it is legible enough to carry text as well. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --note-ink:#e3c06a; --note-bg:rgba(180,130,20,.13); --note-line:rgba(180,130,20,.34);
    --bg:#0e1117; --panel:#161b23; --ink:#ffffff; --muted:#c3cdda; --line:#2a3342;
    --accent-ink:#131a05; --accent-text:#a9e223;
    --accent-soft:rgba(147,213,0,.16); --accent-line:rgba(147,213,0,.42);
    --cold:#8c8c8c; --ok:#5cc03a;
    --shadow:0 1px 2px rgba(0,0,0,.4), 0 10px 28px -14px rgba(0,0,0,.7);
    --surface-2:#1b212b; --surface-3:#11161d;
  }
}
:root[data-theme="dark"]{
  --note-ink:#e3c06a; --note-bg:rgba(180,130,20,.13); --note-line:rgba(180,130,20,.34);
  --bg:#0e1117; --panel:#161b23; --ink:#ffffff; --muted:#c3cdda; --line:#2a3342;
  --accent-ink:#131a05; --accent-text:#a9e223;
  --accent-soft:rgba(147,213,0,.16); --accent-line:rgba(147,213,0,.42);
  --cold:#8c8c8c; --ok:#5cc03a;
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 10px 28px -14px rgba(0,0,0,.7);
  --surface-2:#1b212b; --surface-3:#11161d;
}

/* ------------------------------------------------------------------ theme toggle */
.theme-toggle{display:flex; align-items:center; gap:7px; background:var(--panel);
  border:1px solid var(--line); color:var(--muted); border-radius:20px; padding:5px 12px 5px 9px;
  font-size:12px; text-transform:lowercase}
.theme-toggle:hover{border-color:var(--accent); color:var(--ink)}
.theme-toggle svg{width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; display:none}
:root[data-theme="light"] .ico-sun,
:root[data-theme="dark"] .ico-moon{display:block}
:root:not([data-theme]) .ico-auto{display:block}

/* Figures are rendered on white by matplotlib, so they keep a paper surface in dark mode. */
figure img{background:#fff}

/* ------------------------------------------------------------------ chrome */
.topbar{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:18px 28px; border-bottom:1px solid var(--line); position:sticky; top:0;
  background:color-mix(in srgb, var(--bg) 88%, transparent); backdrop-filter:blur(10px); z-index:20;
}
.brand{display:flex; align-items:center; gap:13px}
.brand h1{font-size:17px}
.brand p{font-size:12.5px; color:var(--muted)}
.mark{width:34px; height:34px; flex:0 0 auto; display:block}
.status{font-size:12.5px; color:var(--muted); display:flex; gap:14px; align-items:center}
.status b{color:var(--ink); font-weight:560}
.lede{max-width:820px; color:var(--muted); font-size:14px; line-height:1.6; margin:2px 2px 2px}
.lede b{color:var(--ink); font-weight:600}
.mode h3 .sub, .step-head .sub{font-weight:450; color:var(--muted); font-size:13px}
main{max-width:1180px; margin:0 auto; padding:26px 20px 60px; display:flex; flex-direction:column; gap:30px}
/* The step cards live inside #app, so main's gap does not reach them: give it the same column
   layout, otherwise consecutive cards sit flush against each other. */
#app{display:flex; flex-direction:column; gap:30px}
/* the run list is a summary, not a step: give it room before the workflow starts */
#runs-card{margin-bottom:10px}
footer{border-top:1px solid var(--line); padding:16px 28px; display:flex; gap:16px;
  justify-content:space-between; color:var(--muted); font-size:12.5px; flex-wrap:wrap}

.card{background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:22px 24px; box-shadow:var(--shadow)}
.step-head{display:flex; align-items:center; gap:12px; margin-bottom:18px}
.step-head h2{font-size:16px; flex:1}
.step-no{width:24px; height:24px; border-radius:50%; background:var(--accent-soft); color:var(--accent-text);
  display:grid; place-items:center; font-size:12.5px; font-weight:650; flex:0 0 auto}
.run-actions{display:flex; align-items:center; gap:10px}

/* ------------------------------------------------------------------ buttons */
button{font:inherit; cursor:pointer; border-radius:10px; border:1px solid transparent; transition:.14s}
button:disabled{opacity:.45; cursor:not-allowed}
.primary{background:var(--accent); color:var(--accent-ink); padding:9px 18px; font-weight:560}
.primary:hover:not(:disabled){background:var(--accent-hover)}
.primary.big{padding:12px 26px; font-size:15px; width:100%; margin-top:18px}
.ghost{background:var(--panel); border-color:var(--line); color:var(--ink); padding:7px 14px}
.ghost:hover{background:var(--surface-2, #f7f8fa)}
.ghost.small{padding:4px 10px; font-size:12.5px; text-decoration:none; color:var(--ink);
  border:1px solid var(--line); border-radius:8px}

/* ------------------------------------------------------------------ gate */
.gate{max-width:520px; margin:40px auto}
.gate h2{font-size:16px; margin-bottom:8px}
#gate-form{display:flex; gap:10px; margin-top:16px}
#gate-form input{flex:1; padding:10px 13px; border:1px solid var(--line); border-radius:10px; font:inherit;
  background:var(--panel); color:var(--ink)}
#gate-form input:focus{outline:3px solid var(--accent-soft); border-color:var(--accent)}

/* ------------------------------------------------------------------ dropzone */
.dropzone{
  border:2px dashed #d3d8e0; border-radius:12px; padding:34px 20px; text-align:center;
  cursor:pointer; transition:.15s; background:var(--surface-3, #fcfcfd);
}
.dropzone:hover,.dropzone:focus-visible{border-color:var(--accent); background:var(--accent-soft); outline:none}
.dropzone.over{border-color:var(--accent); background:var(--accent-soft); transform:scale(1.005)}
.dz-icon{width:30px; height:30px; stroke:var(--accent-text); stroke-width:1.7; fill:none;
  stroke-linecap:round; stroke-linejoin:round; margin-bottom:8px}
.dz-title{font-weight:560}
.dz-sub{color:var(--muted); font-size:13px; margin-top:4px}
.dz-tip{color:var(--accent-text); font-size:12.5px; margin-top:10px}
.dropzone.has-file{border-style:solid; border-color:var(--ok); background:var(--accent-soft)}
.dropzone.uploading{border-style:solid; border-color:var(--accent); cursor:default}

.dz-progress{margin:14px auto 0; max-width:420px}
.dz-progress .bar{height:8px; border-radius:5px; overflow:hidden;
  background:var(--line); border:1px solid var(--line)}
.dz-progress .fill{height:100%; width:0; border-radius:4px; background:var(--accent);
  transition:width .15s linear}
.dz-progress-row{display:flex; align-items:center; justify-content:space-between; gap:12px;
  margin-top:8px; font-family:var(--mono); font-size:12px; color:var(--muted)}

.layout-help{margin-top:14px; font-size:13.5px}
.layout-help summary{cursor:pointer; color:var(--accent-text); font-size:13.5px}
.layout-help pre{background:var(--surface-3, #f7f8fa); border:1px solid var(--line); border-radius:10px;
  padding:12px 14px; overflow:auto; font-family:var(--mono); font-size:12.5px; line-height:1.5; margin:10px 0}
.layout-help p{margin-top:8px}

.or{display:flex; align-items:center; gap:14px; color:var(--muted); font-size:12.5px; margin:20px 0 14px}
.or::before,.or::after{content:""; flex:1; height:1px; background:var(--line)}

.samples{display:grid; grid-template-columns:repeat(auto-fill,minmax(210px,1fr)); gap:12px}
.sample{border:1px solid var(--line); border-radius:12px; padding:13px 15px; text-align:left;
  background:var(--panel); display:flex; flex-direction:column; gap:3px}
.sample:hover{border-color:var(--accent); background:var(--accent-soft)}
.sample.selected{border-color:var(--accent); background:var(--accent-soft); box-shadow:0 0 0 3px var(--accent-line)}
.sample b{font-size:14px; font-weight:600}
.sample span{font-size:12.5px; color:var(--muted)}
.sample .tags{display:flex; gap:6px; flex-wrap:wrap; margin-top:5px}
.tag{font-size:11px; background:var(--surface-2, #f1f3f6); color:var(--muted); border-radius:20px; padding:2px 8px}
.tag.no-coarse{background:rgba(180,35,24,.12); color:#e06c63}

/* ------------------------------------------------------------------ modes */
.modes{display:grid; grid-template-columns:1fr 1fr; gap:14px}
.modes.three{grid-template-columns:repeat(3,1fr)}
@media (max-width:980px){.modes.three{grid-template-columns:1fr}}
.mode{border:1px solid var(--line); border-radius:12px; padding:16px 18px; cursor:pointer;
  display:block; transition:.14s; background:var(--panel)}
.mode:hover{border-color:#b9c6da}
.mode:has(input:checked){border-color:var(--accent); background:var(--accent-soft); box-shadow:0 0 0 3px var(--accent-line)}
.mode:has(input:disabled){opacity:.5; cursor:not-allowed}
.mode input{margin-right:8px; accent-color:var(--accent)}
.mode h3{font-size:14.5px; display:inline-flex; align-items:center; gap:8px}
.mode p{font-size:13px; color:var(--muted); margin:8px 0 10px}
.mode ul{margin:0; padding-left:18px; font-size:12.5px; color:var(--muted)}
.badge{background:var(--accent-soft); color:var(--accent-text); font-size:10.5px; font-weight:650;
  border-radius:20px; padding:2px 8px; letter-spacing:.02em}

/* ------------------------------------------------------------------ run */
.chip{font-size:12px; font-weight:560; padding:4px 11px; border-radius:20px;
  background:var(--surface-2, #f1f3f6); color:var(--muted); text-transform:lowercase}
.chip.running{background:var(--accent-soft); color:var(--accent-text)}
.chip.done{background:var(--accent-soft); color:var(--ok)}
.chip.failed{background:rgba(180,35,24,.12); color:#e06c63}
.chip.cancelled{background:rgba(109,81,201,.14); color:#9b8ae0}
.elapsed{font-family:var(--mono); font-size:12.5px; color:var(--muted); min-width:56px}

.stages{list-style:none; display:flex; flex-wrap:wrap; gap:8px; padding:0; margin:0 0 16px}
.stages li{font-size:12.5px; border:1px solid var(--line); border-radius:20px; padding:4px 12px;
  color:var(--muted); display:flex; align-items:center; gap:7px; background:var(--panel)}
.stages li::before{content:""; width:7px; height:7px; border-radius:50%; background:#d3d8e0}
.stages li.active{border-color:var(--accent); color:var(--accent-text); background:var(--accent-soft)}
.stages li.active::before{background:var(--accent); animation:pulse 1.1s infinite}
.stages li.done{color:var(--ink)}
.stages li.done::before{background:var(--ok)}
@keyframes pulse{50%{opacity:.3}}

.console-wrap{border:1px solid var(--line); border-radius:12px; overflow:hidden}
.console-head{display:flex; align-items:center; gap:14px; padding:8px 13px; background:var(--surface-3, #fafbfc);
  border-bottom:1px solid var(--line); font-size:12.5px; color:var(--muted)}
.console-head span:first-child{flex:1; font-family:var(--mono)}
.follow{display:flex; align-items:center; gap:5px; cursor:pointer}
.console{margin:0; padding:13px 15px; height:340px; overflow:auto; background:#0f1115; color:#d7dce4;
  font-family:var(--mono); font-size:12px; line-height:1.55; white-space:pre-wrap; word-break:break-word}
.console .hl{color:#b6ec4a}
.console .warn{color:#ffd479}
.console .err{color:#ff8a80}

/* ------------------------------------------------------------------ results */
.kpis{display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:12px; margin-bottom:6px}
.kpi{border:1px solid var(--line); border-radius:12px; padding:13px 15px; background:var(--surface-3, #fcfcfd)}
.kpi b{display:block; font-size:22px; font-weight:640; letter-spacing:-.02em}
.kpi span{font-size:12px; color:var(--muted)}
.kpi.good b{color:var(--ok)}
.kpi.warm b{color:var(--warm)}

.tabs{display:flex; gap:4px; border-bottom:1px solid var(--line); margin:20px 0 4px}
.tab{background:none; border:none; padding:9px 15px; color:var(--muted); font-size:13.5px;
  border-radius:0; border-bottom:2px solid transparent; margin-bottom:-1px}
.tab.active{color:var(--accent-text); border-bottom-color:var(--accent); font-weight:560}
.tab-panel{display:none; padding-top:16px}
.tab-panel.active{display:block}
figure{margin:0 0 18px}
figure img{width:100%; height:auto; border:1px solid var(--line); border-radius:10px; display:block}
figcaption{font-size:12.5px; color:var(--muted); margin-top:8px}

/* ------------------------------------------------------------------ 3d viewer */
.viewer-controls{display:flex; gap:16px; flex-wrap:wrap; align-items:center; margin-bottom:12px;
  font-size:12.5px; color:var(--muted)}
.viewer-controls label{display:flex; align-items:center; gap:7px}
.viewer-controls select{font:inherit; font-size:12.5px; padding:5px 8px; border:1px solid var(--line);
  border-radius:8px; background:var(--panel); color:var(--ink)}
.viewer-controls .slider{min-width:210px}
.viewer-controls input[type=range]{flex:1; accent-color:var(--accent)}
.viewer-controls .check{cursor:pointer}
#v-height{font-family:var(--mono); color:var(--ink); min-width:52px}
.viewer{position:relative; height:520px; border:1px solid var(--line); border-radius:12px;
  overflow:hidden; background:var(--surface-3, #f4f6fa)}
.viewer canvas{display:block}
.viewer-msg{position:absolute; inset:0; display:grid; place-items:center; color:var(--muted); font-size:13.5px}
.viewer-legend{position:absolute; left:14px; bottom:14px; display:flex; align-items:center; gap:8px;
  background:color-mix(in srgb, var(--panel) 92%, transparent); border:1px solid var(--line); border-radius:10px;
  padding:7px 11px; font-size:11.5px; font-family:var(--mono); z-index:2}
.ramp{width:140px; height:9px; border-radius:5px; border:1px solid rgba(0,0,0,.08)}
.viewer-legend .unit{font-family:inherit; color:var(--muted)}

/* ------------------------------------------------------------------ run list */
/* Four rows visible, the rest on a scroll -- the list grows with every run and would otherwise
   push the actual workflow off the screen. The header stays put while the body scrolls. */
.table-wrap{overflow:auto; border:1px solid var(--line); border-radius:12px; max-height:310px}   /* +16px for the horizontal scrollbar */
.results thead th{position:sticky; z-index:2; background:var(--surface-3,#fafbfc)}
.results thead tr:first-child th{top:0}
.results thead tr.sub-head th{top:29px}
.results{width:100%; border-collapse:collapse; font-size:13px; min-width:860px}
.results th{text-align:left; vertical-align:bottom; font-weight:560; color:var(--muted); font-size:12px;
  padding:8px 12px; background:var(--surface-3, #fafbfc); border-bottom:1px solid var(--line); white-space:nowrap}
.results thead tr:first-child th{border-bottom:none; padding-bottom:2px}
.results .sub-head th{padding-top:0; font-weight:450; font-size:11.5px}
.results td{padding:10px 12px; border-bottom:1px solid var(--line); white-space:nowrap}
.results tr:last-child td{border-bottom:none}
.results tbody tr.openable{cursor:pointer}
.results tbody tr:hover{background:var(--accent-soft)}
.results .num{font-family:var(--mono); font-size:12.5px}
.results .gain{font-family:var(--mono); font-size:12.5px; color:var(--accent-text); font-weight:600}
.results .case b{font-weight:600}
.results .case span{display:block; color:var(--muted); font-size:12px}
.results .capped{color:#8a5b00}

@media (max-width:760px){
  .modes{grid-template-columns:1fr}
  main{padding:18px 14px 44px}
  .card{padding:18px 16px}
  .viewer{height:400px}
}
