:root{
  --ink:#1a1a1a; --muted:#6a6560; --line:#ded9d0; --bg:#faf8f4;
  --panel:#fff; --accent:#004C8C;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);
  font:18px/1.55 Charter,"PT Serif",Palatino,Georgia,"DejaVu Serif",serif}
header,main,footer{max-width:1460px;margin:0 auto;padding:0 22px}

#err{position:fixed;inset:0 0 auto 0;z-index:99;background:#7a1420;color:#fff;
  padding:9px 14px;font:12.5px/1.4 ui-monospace,Menlo,monospace;white-space:pre-wrap}

.bar{display:flex;align-items:baseline;gap:18px;flex-wrap:wrap;padding-top:16px}
.mark{font-size:2.0rem;letter-spacing:-.025em;line-height:1.05;white-space:nowrap}
.stand{font-size:1.0rem;color:var(--muted);flex:1 1 26ch;min-width:0}

.ghost{color:var(--muted);font:inherit;font-size:.9rem;flex:0 0 auto;
  margin-left:auto;
  padding:3px 12px;border:1px solid var(--line);border-radius:5px;
  background:transparent;cursor:pointer}
.ghost:hover{background:#f1ede5;color:var(--ink)}
.tabs{display:flex;gap:3px;margin:12px 0 6px;border-bottom:1px solid var(--line)}
.tab{display:flex;flex-direction:column;align-items:flex-start;gap:1px;
  padding:6px 13px 7px;border:1px solid transparent;border-bottom:none;
  border-radius:6px 6px 0 0;background:transparent;cursor:pointer;
  font:inherit;color:var(--ink);margin-bottom:-1px}
.tab b{font-weight:600;font-size:1.1rem;letter-spacing:-.01em}
.tab span{color:var(--muted);font-size:.88rem}
.tab:hover{background:#f1ede5}
.tab[aria-selected="true"]{background:var(--panel);border-color:var(--line);
  border-bottom:1px solid var(--panel)}

main{display:grid;grid-template-columns:308px minmax(0,1fr);gap:20px;
  align-items:start;padding-top:16px;padding-bottom:8px}
/* The controls are the only things here that are inputs; everything else is
   output.  Pinning the rail keeps the sliders on screen while the panels
   below the spectrum are read, which is otherwise impossible -- the rail is
   taller than most viewports on its own. */
/* Sticky on the grid item itself does not engage -- the item is sized to its
   content, so there is nothing for it to travel within.  The rail inside it
   is what sticks. */
/* The aside must stretch to the full row, or the rail inside it has no
   travel and sticky does nothing; main sets align-items:start for the
   panels column, so this overrides it for the rail only. */
aside{align-self:stretch}
.rail{position:sticky;top:10px;max-height:calc(100vh - 20px);
  overflow-y:auto;overscroll-behavior:contain;
  scrollbar-width:thin;padding-right:4px}
.rail::-webkit-scrollbar{width:7px}
.rail::-webkit-scrollbar-thumb{background:var(--line);border-radius:4px}
aside section,.panel{background:var(--panel);border:1px solid var(--line);
  border-radius:8px;padding:11px 13px 13px;margin-bottom:14px}
/* The rail carries only the controls now.  Everything else is output and
   lives in the panel grid, which keeps the rail shorter than any viewport so
   that every slider stays on screen while the panels are read. */
aside section:last-child{margin-bottom:0}
h2{font-size:.93rem;font-weight:600;letter-spacing:.055em;text-transform:uppercase;
  color:var(--muted);margin:0 0 9px}
.ph{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
.ph h2{margin-bottom:7px}

.ctl{margin-bottom:11px}
.ctl label{display:flex;justify-content:space-between;align-items:baseline;
  gap:8px;font-size:1.0rem;color:var(--muted);margin-bottom:2px}
.ctl .val{color:var(--ink);font-variant-numeric:tabular-nums;font-size:1.02rem}
input[type=range]{width:100%;accent-color:var(--accent);height:18px;margin:0}
.chk{display:block;font-size:1.0rem;color:var(--ink);margin-top:8px;cursor:pointer}
.chk input{margin-right:6px;accent-color:var(--accent)}
.chk.inline{display:inline-flex;align-items:center;gap:5px;font-size:.94rem;
  color:var(--muted);margin:0}
.chk.inline input{margin:0}
.ph{gap:16px;flex-wrap:wrap}
.rng{font-size:.94rem;color:var(--muted);display:flex;align-items:center;gap:7px}
/* control row under a panel heading, after the pattern in spex */
.prow{display:flex;align-items:center;gap:20px;flex-wrap:wrap;
  margin:2px 0 10px}
.c2{display:flex;align-items:center;gap:7px;font-size:.94rem;color:var(--muted)}
.c2 label{white-space:nowrap}
.c2 input[type=range]{width:110px}
.c2 input[type=checkbox]{accent-color:var(--accent);margin:0}
/* two-handled range; no native input does this */
/* margin, not padding: the handles are offset half their width past each end */
.dual{position:relative;width:132px;height:20px;flex:0 0 auto;touch-action:none;
  margin:0 9px}
.dual .track{position:absolute;top:8px;left:0;right:0;height:4px;
  border-radius:2px;background:var(--line)}
.dual .fill{position:absolute;top:8px;height:4px;border-radius:2px;
  background:var(--accent);cursor:grab}
.dual .h{position:absolute;top:1px;width:16px;height:16px;margin-left:-8px;
  border-radius:50%;background:var(--accent);border:2px solid var(--panel);
  cursor:ew-resize;box-shadow:0 0 0 1px var(--line)}
.rng input:disabled{opacity:.35}
.rng:has(input:disabled){opacity:.5}
.rng input{width:96px}
.rv{color:var(--ink);font-variant-numeric:tabular-nums;min-width:6.5ch;
  white-space:nowrap}
#ycutv{min-width:19ch}

.rd{display:flex;justify-content:space-between;gap:10px;font-size:.98rem;
  padding:3.5px 0;border-bottom:1px dotted var(--line)}
.rd:last-child{border-bottom:none}
.rd span{color:var(--muted)}
.rd b{font-weight:500;font-variant-numeric:tabular-nums}

/* An explicit CSS height is required: fit() sets the backing-store height
   from the measured box, and without one the new attribute becomes the
   layout height, so the canvas grows on every draw. */
canvas{display:block;width:100%}
#spec{height:425px} #cool{height:282px} #ionz{height:250px}
.cwrap{position:relative}
#tip{position:absolute;z-index:5;background:rgba(255,255,255,.97);
  border:1px solid var(--line);border-radius:5px;padding:6px 9px;
  font-size:.94rem;line-height:1.45;pointer-events:none;max-width:260px;
  box-shadow:0 2px 9px rgba(0,0,0,.09)}
.note{font-size:.94rem;color:var(--muted);margin:8px 0 0;line-height:1.5}
.two{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr);
  gap:14px}
#bpt{height:300px}
#therm{height:250px}
.two .panel{margin-bottom:0}
select{font:inherit;font-size:.88rem;color:var(--ink);background:var(--panel);
  border:1px solid var(--line);border-radius:5px;padding:1px 5px}
@media (max-width:1240px){.two{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}}
.two .panel{margin-bottom:0}

.tw{max-height:296px;overflow:auto}
table{width:100%;border-collapse:collapse;font-size:.95rem;
  font-variant-numeric:tabular-nums}
/* No uppercase transform here: it turns the header "λ (air)" into "Λ (AIR)",
   and capital lambda is a different symbol. */
th{text-align:left;font-weight:600;color:var(--muted);font-size:.88rem;
  letter-spacing:.02em;padding:0 6px 4px 0;
  position:sticky;top:0;background:var(--panel)}
td{padding:1.5px 6px 1.5px 0;border-bottom:1px dotted var(--line)}
td.n,th.n{text-align:right}
td.wl{color:var(--muted)}

footer{padding-bottom:34px;font-size:.93rem;color:var(--muted);line-height:1.55}
footer p{margin:.5em 0}
.src{font-size:.86rem}

@media (max-width:980px){
  main{grid-template-columns:1fr}
  .two{grid-template-columns:1fr}
}
