/* ============================================================================
   lab.css — styles for /lab/, the interactive version of the front-page
   figure. Loaded only there: the home page has no reason to carry the weight
   of controls it does not draw. Everything here builds on site.css tokens.
   ========================================================================== */

/* ---- the interactive block -------------------------------------------------
   Diagram+controls and the presets below them together: the sim keeps
   running anywhere inside this box (see visRoot in lab/index.html), so
   scrolling down to the presets does not read as "left the page" and pause
   it. */
.lab-interactive{ position:relative; }

.lab{
  display:grid; grid-template-columns:minmax(0,1fr) 20rem;
  gap:var(--sp-4); align-items:stretch;
  margin-top:var(--sp-5);
}
@media (max-width:940px){ .lab{ grid-template-columns:1fr; } }

/* A slim always-visible readout, mainly for narrow viewports where the rail
   stacks under the stage and for the presets section further down — a
   control moved still reads as "the system just did something" without
   scrolling back up to the full gauges. */
.mini-readout{
  position:sticky; top:3.4rem; z-index:40;
  display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-3);
  margin-top:var(--sp-3);
  padding:.5rem .85rem;
  border:1px solid var(--line); border-radius:3px;
  background:color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter:blur(10px) saturate(1.2);
  -webkit-backdrop-filter:blur(10px) saturate(1.2);
  font-family:var(--font-mono); font-size:.7rem;
}
.mini-live{
  display:flex; align-items:center; flex:none;
  color:var(--muted); letter-spacing:.1em; text-transform:uppercase; font-size:.62rem;
}
.mini-g{ display:flex; align-items:baseline; gap:.3rem; color:var(--muted); flex:none; }
.mini-g b{ color:var(--fg); font-weight:400; font-variant-numeric:tabular-nums; }
.mini-g small{ color:var(--dim); font-size:.62rem; }
.mini-jump{
  margin-left:auto; white-space:nowrap;
  color:var(--accent); text-decoration:none;
  border-bottom:1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  transition:border-color .15s ease;
}
.mini-jump:hover{ border-color:var(--accent); }
@media (max-width:640px){
  .mini-readout{ font-size:.66rem; gap:.6rem var(--sp-2); }
  .mini-jump{ margin-left:0; flex-basis:100%; }
}

/* ---- the stage ----------------------------------------------------------- */
.lab-stage{
  min-width:0; display:flex; flex-direction:column;
  scroll-margin-top:4.5rem;   /* clears the sticky bar when a preset jumps here */
}
.lab-stage .flow{ flex:0 0 auto; }
.lab .flow-canvas{ height:440px; }
@media (max-width:940px){ .lab .flow-canvas{ height:340px; } }
@media (max-width:480px){ .lab .flow-canvas{ height:280px; } }

/* ---- legend ---------------------------------------------------------------
   Orientation for anyone who has never read a system diagram, placed where
   the eye already is instead of in a wall of prose at the bottom of the page. */
.legend{
  display:grid; grid-template-columns:repeat(3, 1fr); gap:var(--sp-2) var(--sp-4);
  border:1px solid var(--line); border-top:none; background:var(--bg-1);
  padding:var(--sp-3);
}
@media (max-width:820px){ .legend{ grid-template-columns:repeat(2, 1fr); } }
@media (max-width:480px){ .legend{ grid-template-columns:1fr; } }
.legend-item{ display:flex; flex-direction:column; gap:.15rem; }
.legend-item b{
  font-family:var(--font-mono); font-size:.6rem; letter-spacing:.1em;
  text-transform:uppercase; color:var(--accent); font-weight:400;
}
.legend-item span{ font-size:.78rem; color:var(--muted); line-height:1.45; }

/* ---- readout ------------------------------------------------------------- */
.gauges{
  display:grid; grid-template-columns:repeat(6, 1fr);
  border:1px solid var(--line); border-top:none;
  background:var(--bg-1);
}
@media (max-width:820px){ .gauges{ grid-template-columns:repeat(3, 1fr); } }
@media (max-width:420px){ .gauges{ grid-template-columns:repeat(2, 1fr); } }
.gauge{
  padding:var(--sp-3) var(--sp-2);
  border-left:1px solid var(--line);
  text-align:center;
}
.gauge:first-child{ border-left:none; }
@media (max-width:820px){
  .gauge:nth-child(3n+1){ border-left:none; }
  .gauge:nth-child(n+4){ border-top:1px solid var(--line); }
}
.gauge-k{
  display:block; font-family:var(--font-mono); font-size:.58rem;
  letter-spacing:.16em; text-transform:uppercase; color:var(--dim);
}
.gauge-v{
  display:block; font-family:var(--font-mono); font-size:1.15rem;
  margin-top:.35rem; color:var(--fg); font-variant-numeric:tabular-nums;
}
.gauge-v small{ font-size:.62rem; color:var(--dim); letter-spacing:.06em; }
.gauge.hot .gauge-v{ color:var(--warn); }
.gauge.bad .gauge-v{ color:var(--accent); }
.gauge.ok  .gauge-v{ color:var(--good); }

/* Queue depth over time. A number tells you where you are; the line tells you
   where you are heading, which is the part people miss. */
.spark{
  border:1px solid var(--line); border-top:none; background:var(--bg-1);
  padding:var(--sp-2) var(--sp-3);
  flex:0 0 auto;
}
.spark-head{
  display:flex; justify-content:space-between;
  font-family:var(--font-mono); font-size:.58rem;
  letter-spacing:.16em; text-transform:uppercase; color:var(--dim);
  margin-bottom:.4rem;
}
.spark canvas{ display:block; width:100%; height:96px; }
@media (max-width:940px){ .spark canvas{ height:64px; } }

/* ---- control rail -------------------------------------------------------- */
.rig{
  border:1px solid var(--line); background:var(--bg-1);
  display:flex; flex-direction:column;
}
/* the last group absorbs any leftover height so the borders stay even */
.rig-group:last-child{ margin-top:auto; }
/* the one-line reason a control exists, right where you're about to move it */
.rig-why{ font-size:.74rem; color:var(--muted); line-height:1.5; margin:-.15rem 0 var(--sp-2); }
.rig-head{
  display:flex; align-items:baseline; justify-content:space-between;
  padding:.6rem .85rem; border-bottom:1px solid var(--line);
  font-family:var(--font-mono); font-size:.66rem;
  letter-spacing:.1em; text-transform:uppercase; color:var(--muted);
}
.rig-group{ padding:var(--sp-3) .85rem; border-bottom:1px solid var(--line); }
.rig-group:last-child{ border-bottom:none; }
.rig-k{
  display:block; font-family:var(--font-mono); font-size:.58rem;
  letter-spacing:.16em; text-transform:uppercase; color:var(--dim);
  margin-bottom:var(--sp-2);
}
.ctl{ margin-top:var(--sp-2); }
.ctl:first-of-type{ margin-top:0; }
.ctl-lab{
  display:flex; justify-content:space-between; align-items:baseline; gap:var(--sp-2);
  font-family:var(--font-mono); font-size:.7rem; color:var(--muted);
}
.ctl-lab b{ color:var(--accent); font-weight:400; font-variant-numeric:tabular-nums; }
.ctl.off{ opacity:.4; }

input[type=range]{
  -webkit-appearance:none; appearance:none;
  width:100%; height:2px; margin:.55rem 0 0;
  background:var(--line-2); border-radius:2px; outline:none; cursor:pointer;
}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none; appearance:none;
  width:12px; height:12px; border-radius:2px;
  background:var(--accent); cursor:pointer;
  border:none;
}
input[type=range]::-moz-range-thumb{
  width:12px; height:12px; border-radius:2px;
  background:var(--accent); border:none; cursor:pointer;
}
input[type=range]:focus-visible{ outline:1px solid var(--accent); outline-offset:4px; }

/* a switch that looks like the rest of the page: a box that is either
   struck through or not, same language the diagram uses */
.sw{
  display:flex; align-items:center; justify-content:space-between; gap:var(--sp-2);
  font-family:var(--font-mono); font-size:.72rem; color:var(--muted);
  cursor:pointer; padding:.28rem 0;
}
.sw input{ position:absolute; opacity:0; width:0; height:0; }
.sw i{
  width:26px; height:14px; border-radius:2px; flex:none;
  border:1px solid var(--line-2); background:var(--bg-2);
  position:relative; transition:border-color .15s ease, background .15s ease;
}
.sw i::after{
  content:""; position:absolute; top:2px; left:2px;
  width:8px; height:8px; border-radius:1px;
  background:var(--line-2); transition:transform .15s ease, background .15s ease;
}
.sw input:checked + i{ border-color:var(--accent); background:var(--accent-soft); }
.sw input:checked + i::after{ transform:translateX(12px); background:var(--accent); }
.sw input:focus-visible + i{ outline:1px solid var(--accent); outline-offset:3px; }

.rig-btns{ display:grid; grid-template-columns:1fr; gap:.4rem; }
.rig-btn{
  font-family:var(--font-mono); font-size:.72rem; text-align:left;
  padding:.5rem .6rem; cursor:pointer;
  color:var(--fg); background:var(--bg-2);
  border:1px solid var(--line-2); border-radius:2px;
  transition:border-color .15s ease, color .15s ease, background .15s ease;
}
.rig-btn:hover{ border-color:var(--accent); color:var(--accent); }
.rig-btn:active{ background:var(--accent-soft); }
.rig-btn.quiet{ background:transparent; color:var(--muted); }

/* ---- presets -------------------------------------------------------------
   A shortcut for anyone who'd rather watch a curated scenario than drive the
   rail by hand: a badge, a hover lift and an explicit "run it" line so a
   card reads as a button before anyone reads a word of the copy on it. */
.presets{ margin-top:var(--sp-6); }
.preset-grid{
  display:grid; grid-template-columns:repeat(3, 1fr); gap:var(--sp-3);
  margin-top:var(--sp-3);
}
@media (max-width:900px){ .preset-grid{ grid-template-columns:repeat(2, 1fr); } }
@media (max-width:560px){ .preset-grid{ grid-template-columns:1fr; } }
.preset{
  text-align:left; cursor:pointer;
  border:1px solid var(--line); border-radius:3px;
  background:var(--bg-1); padding:var(--sp-3);
  display:flex; flex-direction:column;
  transition:border-color .2s ease, transform .2s ease, background .2s ease;
}
.preset:hover{ border-color:var(--accent); transform:translateY(-2px); background:var(--accent-soft); }
.preset[aria-pressed="true"]{ border-color:var(--accent); background:var(--accent-soft); }
.preset-k{
  display:inline-flex; align-items:center; justify-content:center;
  width:1.7rem; height:1.7rem; flex:none;
  border:1px solid var(--line-2); border-radius:2px;
  font-family:var(--font-mono); font-size:.68rem; color:var(--dim);
  transition:border-color .2s ease, color .2s ease;
}
.preset:hover .preset-k,
.preset[aria-pressed="true"] .preset-k{ border-color:var(--accent); color:var(--accent); }
.preset h3{
  font-family:var(--font-display); font-weight:400; font-size:1.12rem;
  margin:.6rem 0 .35rem; line-height:1.2; letter-spacing:-.005em; color:var(--fg);
}
.preset p{ font-size:.82rem; color:var(--muted); line-height:1.5; }
.preset-go{
  display:flex; align-items:center; gap:.3rem;
  margin-top:var(--sp-3); padding-top:var(--sp-2);
  border-top:1px solid var(--line);
  font-family:var(--font-mono); font-size:.66rem;
  letter-spacing:.08em; text-transform:uppercase; color:var(--dim);
  transition:color .2s ease;
}
.preset-go .arrow{ display:inline-block; transition:transform .18s ease; }
.preset:hover .preset-go{ color:var(--accent); }
.preset:hover .preset-go .arrow{ transform:translateX(2px); }

/* the sentence that turns a toy into a demonstration */
.lesson{
  display:flex; gap:var(--sp-3); align-items:flex-start;
  margin-top:var(--sp-3);
  border:1px dashed var(--line-2); border-left:2px solid var(--accent);
  background:var(--bg-1); padding:var(--sp-3) var(--sp-4);
}
.lesson-k{
  font-family:var(--font-mono); font-size:.58rem; letter-spacing:.16em;
  text-transform:uppercase; color:var(--accent); flex:none; padding-top:.2rem;
}
.lesson p{ font-size:.9rem; color:var(--muted); line-height:1.6; }

.lab-caveat{
  font-family:var(--font-mono); font-size:.68rem; color:var(--dim);
  margin-top:var(--sp-5); padding-top:var(--sp-3);
  border-top:1px solid var(--line);
}

/* ---- what I'm building --------------------------------------------------
   The closing block. Someone who enjoyed breaking the toy should leave
   knowing what the real thing is. Borrows .slot-k and .slot-bar from
   site.css so it is visibly the same site, not a page that resembles it. */
.lab-build{ margin-top:var(--sp-6); padding-top:var(--sp-5); border-top:1px solid var(--line); }
.build-grid{
  display:grid; grid-template-columns:1.25fr 1fr; gap:var(--sp-3);
  margin-top:var(--sp-4);
}
@media (max-width:760px){ .build-grid{ grid-template-columns:1fr; } }
.build{
  position:relative; overflow:hidden;
  border:1px solid var(--line); border-radius:3px;
  background:var(--bg-1); padding:var(--sp-4);
  display:flex; flex-direction:column;
}
.build.lead{
  border-color:color-mix(in srgb, var(--accent) 38%, var(--line));
  background:linear-gradient(180deg, var(--accent-soft), transparent 60%), var(--bg-1);
}
.build.lead::before{
  content:""; position:absolute; left:0; top:0; bottom:0; width:2px;
  background:var(--accent);
}
.build h3{
  font-family:var(--font-display); font-weight:400; font-size:1.55rem;
  margin:.55rem 0 0; letter-spacing:-.008em; line-height:1.15;
}
.build h3.build-quiet{ color:var(--dim); font-size:1.25rem; }
.build-tag{
  font-family:var(--font-mono); font-size:.62rem; letter-spacing:.16em;
  text-transform:uppercase; color:var(--accent); margin-top:.4rem;
}
.build-line{ font-size:.88rem; color:var(--muted); line-height:1.6; margin-top:var(--sp-3); }
.build-actions{
  display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-3);
  margin-top:auto; padding-top:var(--sp-4);
}
.build-more{
  font-family:var(--font-mono); font-size:.72rem; color:var(--muted);
  text-decoration:none;
  border-bottom:1px solid color-mix(in srgb, var(--accent) 32%, transparent);
  transition:color .15s ease, border-color .15s ease;
}
.build-more:hover{ color:var(--accent); border-color:var(--accent); }

.lab-byline{
  font-family:var(--font-mono); font-size:.7rem; color:var(--dim);
  margin-top:var(--sp-4); line-height:1.9;
}
.lab-byline a{
  color:var(--muted); text-decoration:none;
  border-bottom:1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}
.lab-byline a:hover{ color:var(--accent); border-color:var(--accent); }

/* ---- event log ------------------------------------------------------------
   The panel that squares the two columns off. A log can be any height without
   looking wrong, which a stretched diagram cannot, and it is the piece that
   explains why the queue looks the way it does thirty seconds later. */
.lab-log{
  border:1px solid var(--line); border-top:none; background:var(--bg-1);
  padding:var(--sp-2) var(--sp-3) 0;
  flex:1 1 auto; min-height:8rem;
  display:flex; flex-direction:column;
}
@media (max-width:940px){ .lab-log{ flex:none; min-height:0; } }
.log-body{
  flex:1 1 0; min-height:0; overflow-y:auto;
  padding-bottom:var(--sp-2);
  font-family:var(--font-mono); font-size:.68rem;
  scrollbar-width:thin;
}
@media (max-width:940px){ .log-body{ height:9rem; flex:none; } }
.log-body:empty::after{
  content:"nothing has happened yet · break something";
  color:var(--dim); opacity:.7;
}
.log-row{
  display:flex; gap:var(--sp-2); align-items:baseline;
  padding:.28rem 0; border-top:1px solid color-mix(in srgb, var(--line) 60%, transparent);
}
.log-row:first-child{ border-top:none; }
.log-t{ color:var(--dim); flex:none; font-variant-numeric:tabular-nums; }
.log-m{ color:var(--muted); flex:1 1 auto; }
.log-n{ color:var(--dim); flex:none; }
.log-row[data-n="1"] .log-n{ display:none; }
.log-row.warn .log-m{ color:var(--warn); }
.log-row.bad  .log-m{ color:var(--accent); }
.log-row.ok   .log-m{ color:var(--good); }

/* the standfirst carries a link now, and site.css only styles links inside
   .doc-body */
.doc-standfirst a{
  color:var(--accent); text-decoration:none;
  border-bottom:1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  transition:border-color .15s ease;
}
.doc-standfirst a:hover{ border-color:var(--accent); }

/* ---- live indicator -------------------------------------------------------
   Same dot as the header bar, at label scale. It goes grey when the engine
   pauses itself, because a green light that is always on says nothing. */
.live-dot{
  display:inline-block; width:5px; height:5px; border-radius:50%;
  background:var(--good); margin-right:.45rem; vertical-align:middle;
  box-shadow:0 0 0 2px color-mix(in srgb, var(--good) 18%, transparent);
  transition:background .2s ease, box-shadow .2s ease;
}
@media (prefers-reduced-motion: no-preference){
  .live-dot{ animation:pulse 2.8s ease-in-out infinite; }
}
.live-dot.off{
  background:var(--line-2); box-shadow:none; animation:none;
}
