/*
 * Copyright (c) 2026 TwinLink (Stichting TwinLink.eu)
 * Licensed under the EUPL, Version 1.2 or later (the 'Licence').
 * You may not use this work except in compliance with the Licence.
 * A copy of the Licence is in the LICENCE file at the root of this repository.
 * SPDX-License-Identifier: EUPL-1.2
 */

/* ============================================================================
   THE AADORP ENERGY TWIN STYLESHEET.

   Everything visual lives here or in web/tokens.css and nowhere else. There is
   no <style> block in index.html, no inline style attribute that is not a
   runtime measured position, and no colour or size literal outside the token
   file. tests/test_design_tokens.py enforces all three.

   ORDER
     1  base and reset
     2  layout: topbar, rail, panels
     3  components, each defined ONCE and reused
     4  Plan mode: the answer card and its parts
     5  utilities, which exist to retire the 195 inline style attributes
     6  responsive and presentation mode

   No em dashes.
   ========================================================================= */

/* =============================================================== 1. base === */
* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  font-family: var(--font-body);
  font-size: var(--fs-3);
  color: var(--c-ink);
  background: var(--c-canvas);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

button { font-family: inherit; }

h2, h3, h4,
.ptitle, .pttl, #bp-title, #brand, .sv, .kv2 .v, .kv .v, #condPop .cline b, .btn {
  font-family: var(--font-head);
  letter-spacing: var(--track-head);
}

:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes slideL { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: none; } }
@keyframes ansIn { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
@keyframes shimmer { to { background-position: -200% 0; } }

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

.muted { color: var(--c-ink-3); }
.err { color: var(--c-bad); }

.loading {
  color: var(--c-ink-3);
  font-size: var(--fs-3);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.loading::before {
  content: "";
  width: var(--ic-1); height: var(--ic-1); min-width: var(--ic-1);
  border-radius: 50%;
  border: 2px solid var(--c-line);
  border-top-color: var(--c-accent);
  animation: spin 0.8s linear infinite;
}

#stage { position: fixed; inset: 0; }
#cesium { position: absolute; inset: 0; }
#cesium .cesium-viewer-bottom { left: var(--sp-3); bottom: var(--sp-2); }
#cesium .cesium-credit-lightbox,
#cesium .cesium-widget-credits { font-size: var(--fs-1); }

/* the glass primitive, used by every floating surface */
.glass {
  background: var(--c-glass);
  backdrop-filter: blur(var(--blur));
  -webkit-backdrop-filter: blur(var(--blur));
  border: 1px solid var(--c-line);
  border-radius: var(--r-4);
  box-shadow: var(--e-2);
}

/* ============================================================= 2. layout === */
#topbar {
  position: absolute; top: 0; left: 0; right: 0;
  height: var(--topbar-h);
  z-index: 40;
  display: flex; align-items: center; gap: var(--sp-4);
  padding: 0 var(--sp-5);
  border-radius: 0; border-left: 0; border-right: 0; border-top: 0;
  background: var(--c-glass-2);
}
#topbar::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: linear-gradient(90deg, var(--c-accent-deep), var(--c-leaf));
  opacity: 0.5; pointer-events: none;
}
#brand {
  display: flex; align-items: center; gap: var(--sp-3);
  font-weight: var(--fw-bold); font-size: var(--fs-4); white-space: nowrap;
}
#brand .dot {
  width: var(--sp-2); height: var(--sp-2); border-radius: 50%;
  background: linear-gradient(140deg, var(--c-accent), var(--c-leaf));
  box-shadow: 0 0 10px var(--c-accent);
}
#brandLink {
  display: flex; align-items: center; text-decoration: none;
  color: var(--c-ink-3); border-radius: var(--r-1); transition: var(--t-base);
}
#brandLink:hover { opacity: 0.85; }
#brandImg { height: var(--sp-6); width: auto; border-radius: var(--r-1); }

.seg {
  display: flex;
  background: var(--c-sunken);
  border: 1px solid var(--c-line-soft);
  border-radius: var(--r-2);
  overflow: hidden;
}
.seg button {
  all: unset; cursor: pointer;
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-3); color: var(--c-ink-2);
  display: flex; align-items: center; gap: var(--sp-2);
  transition: var(--t-base);
}
.seg button.on { background: var(--c-accent-deep); color: var(--c-ink); }

.iconbtn {
  all: unset; cursor: pointer;
  width: var(--sp-7); height: var(--sp-7);
  border-radius: var(--r-2);
  display: flex; align-items: center; justify-content: center;
  color: var(--c-ink-2);
  border: 1px solid var(--c-line-soft);
  transition: var(--t-base);
}
.iconbtn:hover { color: var(--c-ink); border-color: var(--c-line); background: var(--c-hover); }
.iconbtn.on { color: var(--c-ink); background: var(--c-accent-deep); border-color: var(--c-accent-deep); }

#rail {
  position: absolute; left: var(--sp-4); top: var(--below);
  z-index: 35;
  display: flex; flex-direction: column; gap: var(--sp-2);
  padding: var(--sp-2);
}
.railbtn {
  all: unset; cursor: pointer;
  width: calc(var(--rail-w) - var(--sp-6)); height: calc(var(--rail-w) - var(--sp-6));
  border-radius: var(--r-3);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; color: var(--c-ink-2); transition: var(--t-base); position: relative;
}
.railbtn span { font-size: var(--fs-1); letter-spacing: 0.02em; }
.railbtn:hover { color: var(--c-ink); background: var(--c-hover); }
.railbtn.on { color: var(--c-ink); background: var(--c-accent-deep); }

.sidepanel {
  position: absolute;
  left: calc(var(--rail-w) + var(--sp-4)); top: var(--below);
  width: var(--panel-w);
  max-height: calc(100% - var(--topbar-h) - var(--sp-6) - var(--sp-4));
  z-index: 34;
  padding: var(--sp-4);
  overflow: auto;
  display: none;
  animation: slideL var(--t-base);
}
.sidepanel.open { display: block; }

.ptitle {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--c-ink-3); margin: 0 0 var(--sp-4);
}
h4.sub {
  margin: var(--sp-5) 0 var(--sp-2);
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--c-ink-3);
}

/* ========================================================= 3. components === */

/* --- 3.1 option button and layer row ------------------------------------- */
#layers, #layers-tech, .layergroup { display: flex; flex-direction: column; gap: var(--sp-2); }

/* THE TWO KINDS INSIDE THE MOBILITY GROUP MUST LOOK DIFFERENT. M17.
   One is a choice, at most one of which paints the map. The other is a set of independent
   toggles. Rendering them as one flat list is what previously hid the fact that Road safety
   never coloured anything: it looked like a third colouring and was always an overlay.
   Every colour here is a token from tokens.css; there is not a literal in this block. */
.grouplabel {
  font-size: var(--fs-1); letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--c-ink-3); margin: var(--sp-3) 0 var(--sp-2);
}
.cbody > .grouplabel:first-child { margin-top: 0; }
/* AN OVERLAY IS A SWITCH, SO IT CARRIES A SWITCH AFFORDANCE. The dot sits where a
   radio-style selection bar would sit on a colouring row, and it fills when the overlay
   is on, so the on state is legible without reading the label. */
.opt.ovl { position: relative; padding-left: calc(var(--sp-4) + var(--sp-3)); }
.opt.ovl::before {
  content: ""; position: absolute; left: var(--sp-3); top: 50%;
  width: var(--sp-3); height: var(--sp-3); margin-top: calc(var(--sp-3) / -2);
  border-radius: var(--r-1); border: 1px solid var(--c-line); background: transparent;
  transition: background var(--t-base), border-color var(--t-base);
}
.opt.ovl.is-on::before { background: var(--c-accent); border-color: var(--c-accent); }
.opt.ovl.is-on { color: var(--c-ink); }
.layerrow { display: flex; align-items: center; gap: var(--sp-2); }
.layerrow .opt { flex: 1; }
#layerpick h4.sub { margin: var(--sp-4) 0 var(--sp-2); }

/* a.opt EXISTS BECAUSE THE BUILD WORKSPACE IS A SECOND PAGE. Moving between two pages is
   a LINK, not a button: right click, middle click and open-in-new-tab all matter for a
   workspace. `all: unset` strips the browser's default underline and its own blue, which
   is a colour from no token at all and was showing through before this selector existed. */
button.opt, a.opt {
  all: unset; cursor: pointer;
  border: 1px solid var(--c-line-soft); border-radius: var(--r-2);
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-3); color: var(--c-ink-2);
  transition: var(--t-base);
}
button.opt:hover, a.opt:hover { border-color: var(--c-line); color: var(--c-ink); }
button.opt.on, a.opt.on { background: var(--c-accent-deep); color: var(--c-ink); border-color: var(--c-accent-deep); }
button.opt.na, a.opt.na { opacity: 0.4; cursor: not-allowed; }
button.opt.block, a.opt.block { width: 100%; text-align: center; }
button.opt.grow, a.opt.grow { flex: 1; text-align: center; }

/* --- 3.2 legend: named classes with printed bands ------------------------ */
#legendhead {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--c-ink-3); margin: var(--sp-4) 0 var(--sp-2);
}
#legendhead .lname { color: var(--c-ink-2); }

.legend { margin-top: var(--sp-3); }
.legend span {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  font-size: var(--fs-2); color: var(--c-ink-2); margin: var(--sp-1) 0;
}
.sw {
  width: var(--ic-2); height: var(--ic-2); min-width: var(--ic-2);
  border-radius: var(--r-1);
  border: 1px solid var(--c-line-soft);
  margin-top: 1px;
}
/* the five class legend: a name on top, the numeric band underneath */
.legend .lclass { flex-direction: row; align-items: flex-start; }
.legend .lclass .ltext { display: flex; flex-direction: column; line-height: var(--lh-snug); }
.legend .lclass .lname2 { color: var(--c-ink); font-size: var(--fs-2); }
.legend .lclass .lband { color: var(--c-ink-3); font-size: var(--fs-1); }
.legend .lunit {
  font-size: var(--fs-1); color: var(--c-ink-3);
  margin: var(--sp-1) 0 var(--sp-2); display: block;
}

/* the swatch colours. The ONLY place a data ramp reaches the DOM. */
.sw-seq-1 { background: var(--d-seq-1); }
.sw-seq-2 { background: var(--d-seq-2); }
.sw-seq-3 { background: var(--d-seq-3); }
.sw-seq-4 { background: var(--d-seq-4); }
.sw-seq-5 { background: var(--d-seq-5); }
/* the two satellite ramps, so a legend swatch shows the ramp its layer is drawn in */
.sw-green-1 { background: var(--d-green-1); }
.sw-green-2 { background: var(--d-green-2); }
.sw-green-3 { background: var(--d-green-3); }
.sw-green-4 { background: var(--d-green-4); }
.sw-green-5 { background: var(--d-green-5); }
.sw-therm-1 { background: var(--d-therm-1); }
.sw-therm-2 { background: var(--d-therm-2); }
.sw-therm-3 { background: var(--d-therm-3); }
.sw-therm-4 { background: var(--d-therm-4); }
.sw-therm-5 { background: var(--d-therm-5); }
.sw-label-a { background: var(--d-label-a); }
.sw-label-b { background: var(--d-label-b); }
.sw-label-c { background: var(--d-label-c); }
.sw-label-d { background: var(--d-label-d); }
.sw-label-e { background: var(--d-label-e); }
.sw-label-f { background: var(--d-label-f); }
.sw-label-g { background: var(--d-label-g); }
.sw-none { background: var(--d-none); }
.sw-good { background: var(--c-good); }
.sw-warn { background: var(--c-warn); }
.sw-bad { background: var(--c-bad); }
.sw-accent { background: var(--c-accent); }
.sw-accent-deep { background: var(--c-accent-deep); }
.sw-leaf { background: var(--c-leaf); }
.sw-surface-2 { background: var(--c-surface-2); }

/* --- 3.3 chip ------------------------------------------------------------ */
.chip {
  display: inline-flex; align-items: center;
  font-size: var(--fs-1); font-weight: var(--fw-bold);
  padding: 2px var(--sp-3); border-radius: var(--r-pill);
  background: var(--c-accent-tint); color: var(--c-accent-ink);
  margin: 1px 2px 1px 0;
}
.chip.warn { background: var(--c-bad-tint); color: var(--c-bad); }
.chip.ok { background: var(--c-leaf-tint); color: var(--c-leaf); }
.chip.sim { background: var(--c-warn-tint); color: var(--c-warn); }

.badges { display: flex; gap: var(--sp-1); flex-wrap: wrap; margin-top: var(--sp-3); }
.badge {
  font-size: var(--fs-1); font-weight: var(--fw-bold);
  padding: 3px var(--sp-3); border-radius: var(--r-pill);
  background: var(--c-accent-tint); color: var(--c-accent-ink);
  text-transform: uppercase; letter-spacing: 0.03em;
}
.badge.sim { background: var(--c-warn-tint); color: var(--c-warn); }
.badge.tier-high { background: var(--c-good-tint); color: var(--c-good); }
.badge.tier-medium { background: var(--c-warn-tint); color: var(--c-warn); }
.badge.tier-low { background: var(--c-bad-tint); color: var(--c-bad); }
.badge.robust { background: var(--c-leaf-tint); color: var(--c-leaf); }

/* --- 3.4 card and expander (ONE primitive for every collapsible) --------- */
.card {
  border: 1px solid var(--c-line-soft); border-radius: var(--r-3);
  padding: var(--sp-4); margin-bottom: var(--sp-4);
  font-size: var(--fs-3); line-height: var(--lh-normal); color: var(--c-ink-2);
}
.card h3 {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--c-ink-3); display: flex; align-items: center; gap: var(--sp-2);
}

.collapse > .chead {
  cursor: pointer; display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; box-sizing: border-box;
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--c-ink-3); padding: var(--sp-3) 0;
  user-select: none; transition: var(--t-base);
}
.collapse > .chead:hover { color: var(--c-ink-2); }
.collapse > .chead .chev { margin-left: auto; transition: transform var(--t-base); opacity: 0.7; }
.collapse.open > .chead .chev { transform: rotate(90deg); }
.collapse > .cbody { display: none; }
.collapse.open > .cbody { display: block; animation: fadeIn var(--t-base); }

.card.collapse { padding: 0; }
.card.collapse > .chead { padding: var(--sp-4) var(--sp-4); font-size: var(--fs-1); }
.card.collapse > .chead .ctitle {
  font-family: var(--font-head); letter-spacing: 0.02em; color: var(--c-ink-2);
  text-transform: none; font-size: var(--fs-3); font-weight: var(--fw-semibold);
  display: flex; align-items: center; gap: var(--sp-2);
}
.card.collapse.open > .chead .ctitle { color: var(--c-ink); }
.card.collapse > .cbody { padding: 0 var(--sp-4) var(--sp-4); }
.card.collapse .cverdict {
  font-size: var(--fs-1); color: var(--c-ink-3);
  margin-left: auto; margin-right: var(--sp-3); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 130px;
}

/* --- 3.5 info icon and popover ------------------------------------------- */
.i {
  all: unset; cursor: pointer;
  width: var(--ic-2); height: var(--ic-2); min-width: var(--ic-2);
  border-radius: 50%; border: 1px solid var(--c-line);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-1); font-weight: var(--fw-bold);
  color: var(--c-ink-3); line-height: 1; transition: var(--t-base);
}
.i:hover { color: var(--c-ink); border-color: var(--c-accent); background: var(--c-accent-tint); }
.i.on-title { margin-left: auto; }
.i.centred { align-self: center; }
.i.inert { pointer-events: none; }

/* Every element below is shown and hidden by TOGGLING .is-hidden from JavaScript,
   so its natural display is declared here and never in a style attribute. */
#infopop {
  position: fixed; z-index: 200; max-width: 260px;
  padding: var(--sp-4); font-size: var(--fs-2); line-height: var(--lh-normal);
  color: var(--c-ink); display: block;
}
#infopop b { color: var(--c-ink); }

#tip {
  position: absolute; pointer-events: none;
  background: var(--c-glass-2); color: var(--c-ink);
  padding: var(--sp-2) var(--sp-3); border-radius: var(--r-2);
  font-size: var(--fs-2); display: block; z-index: 50;
  max-width: 250px; line-height: var(--lh-snug);
  border: 1px solid var(--c-line);
}

/* --- 3.6 stat tile ------------------------------------------------------- */
.kv2 { display: grid; grid-template-columns: 1fr auto; gap: 3px var(--sp-4); font-size: var(--fs-3); }
.kv2 .v { font-weight: var(--fw-bold); text-align: right; color: var(--c-ink); }
.kv { display: grid; grid-template-columns: 1fr auto; gap: var(--sp-1) var(--sp-4); margin: var(--sp-3) 0; }
.kv .k { color: var(--c-ink-3); display: flex; align-items: center; gap: var(--sp-1); }
.kv .v { font-weight: var(--fw-semibold); text-align: right; color: var(--c-ink); }

/* --- 3.7 form controls --------------------------------------------------- */
select, #budget { width: 100%; }
select {
  padding: var(--sp-3); border-radius: var(--r-2);
  border: 1px solid var(--c-line); background: var(--c-sunken);
  color: var(--c-ink); font-size: var(--fs-3);
}
#budget { margin-top: var(--sp-1); accent-color: var(--c-accent); }
input[type="range"] { accent-color: var(--c-accent); }
input[type="checkbox"] { accent-color: var(--c-accent); }

.ovl { display: flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-3); color: var(--c-ink-2); margin: var(--sp-3) 0; }
.scene-ovl { margin-top: var(--sp-2); padding-top: var(--sp-2); border-top: 1px solid var(--c-line); }

#sunctl { margin: 2px 0 var(--sp-1); padding-left: var(--sp-6); }
#sunctl input[type="range"] { width: 100%; margin: 2px 0 var(--sp-2); }
.sunrow { display: flex; justify-content: space-between; font-size: var(--fs-2); color: var(--c-ink-3); }

.lens { display: flex; gap: var(--sp-2); margin: var(--sp-3) 0; }
.lens button {
  all: unset; cursor: pointer; flex: 1; text-align: center;
  border: 1px solid var(--c-line-soft); border-radius: var(--r-2);
  padding: var(--sp-2); font-size: var(--fs-2); color: var(--c-ink-2);
  transition: var(--t-base);
}
.lens button.on { background: var(--c-accent-deep); color: var(--c-ink); border-color: var(--c-accent-deep); }

.note { font-size: var(--fs-1); color: var(--c-warn); line-height: var(--lh-normal); margin-top: var(--sp-2); }
.note.quiet { color: var(--c-ink-3); }

/* --- 3.8 side panel: the right hand building detail ---------------------- */
#bpanel {
  position: absolute; right: var(--sp-4); top: var(--below); bottom: var(--sp-4);
  width: var(--bpanel-w); max-width: calc(100% - var(--sp-6));
  z-index: 36;
  display: flex; flex-direction: column; overflow: hidden;
  transform: translateX(120%); transition: transform var(--t-base);
}
#bpanel.open { transform: none; }
#bp-head { padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--c-line-soft); }
#bp-head .row1 { display: flex; justify-content: space-between; align-items: center; gap: var(--sp-3); }
#bp-title { margin: 0; font-size: var(--fs-4); font-weight: var(--fw-bold); word-break: break-all; }
#bp-close { all: unset; cursor: pointer; color: var(--c-ink-3); display: flex; padding: 3px; border-radius: var(--r-1); }
#bp-close:hover { color: var(--c-ink); background: var(--c-hover); }
#bp-body { padding: var(--sp-4) var(--sp-5); overflow: auto; flex: 1; font-size: var(--fs-3); }

.empty { color: var(--c-ink-3); text-align: center; padding: var(--sp-7) var(--sp-5); font-size: var(--fs-3); line-height: var(--lh-loose); }
.empty .big { font-size: var(--fs-7); margin-bottom: var(--sp-3); opacity: 0.7; }

.labelchip {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--sp-6); height: var(--sp-6); border-radius: var(--r-1);
  color: var(--c-canvas); font-weight: var(--fw-bold); font-size: var(--fs-3);
  padding: 0 var(--sp-2);
}
.labelchip.lc-a { background: var(--d-label-a); }
.labelchip.lc-b { background: var(--d-label-b); }
.labelchip.lc-c { background: var(--d-label-c); }
.labelchip.lc-d { background: var(--d-label-d); }
.labelchip.lc-e { background: var(--d-label-e); }
.labelchip.lc-f { background: var(--d-label-f); }
.labelchip.lc-g { background: var(--d-label-g); }
.labelchip.lc-none { background: var(--d-none); }

.sect { border-top: 1px solid var(--c-line-soft); margin-top: var(--sp-4); padding-top: var(--sp-4); }
.sect h4 {
  margin: 0 0 var(--sp-3); font-size: var(--fs-1);
  text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--c-ink-3); display: flex; align-items: center; gap: var(--sp-2);
}

.presets { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); }
.presets button {
  all: unset; cursor: pointer; text-align: center;
  border: 1px solid var(--c-line); border-radius: var(--r-3);
  padding: var(--sp-4) var(--sp-2); font-size: var(--fs-3); color: var(--c-ink);
  transition: var(--t-base);
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-1);
}
.presets button:hover { border-color: var(--c-accent); background: var(--c-accent-tint); }
.presets button.on { background: var(--c-accent-deep); color: var(--c-ink); border-color: var(--c-accent-deep); }
.presets button.na { opacity: 0.35; cursor: not-allowed; }
.presets button .pico { display: flex; }

.arrow { color: var(--c-ink-3); padding: 0 var(--sp-1); }

.bars { margin: var(--sp-3) 0 2px; }
.bar {
  display: grid; grid-template-columns: 50px 1fr 90px;
  align-items: center; gap: var(--sp-3); margin: var(--sp-1) 0;
  font-size: var(--fs-2); color: var(--c-ink-2);
}
.bar .track { background: var(--c-hover); border-radius: var(--r-1); height: 13px; overflow: hidden; }
.bar .fill { height: 100%; border-radius: var(--r-1); transition: width 0.5s var(--ease); background: var(--c-accent); }
.bar .fill.good { background: var(--c-good); }
.bar .fill.warn { background: var(--c-warn); }
.bar .fill.bad { background: var(--c-bad); }
.bar .fill.leaf { background: var(--c-leaf); }
.bar .fill.muted { background: var(--d-none); }

.flag {
  background: var(--c-warn-tint); border: 1px solid var(--c-warn);
  color: var(--c-warn); border-radius: var(--r-2);
  padding: var(--sp-3) var(--sp-4); font-size: var(--fs-2);
  margin: var(--sp-3) 0; line-height: var(--lh-normal);
}
.why {
  background: var(--c-hover); border-radius: var(--r-2);
  padding: var(--sp-3) var(--sp-4); font-size: var(--fs-2);
  color: var(--c-ink-2); line-height: var(--lh-normal);
}
.footnote { font-size: var(--fs-1); color: var(--c-ink-3); margin-top: var(--sp-4); line-height: var(--lh-normal); }

/* rooftop aerial in the building panel */
.roofwrap { margin: 0 0 var(--sp-4); }
.roofthumb {
  width: 100%; max-height: 190px; object-fit: cover;
  border-radius: var(--r-2); border: 1px solid var(--c-line-soft);
  cursor: zoom-in; display: block; background: var(--c-sunken);
}
.roofthumb:hover { border-color: var(--c-accent); }
.roofcap { font-size: var(--fs-1); line-height: var(--lh-normal); margin-top: var(--sp-2); }
.roofcap .dq { color: var(--c-ink); }
.roofcap .src { color: var(--c-ink-3); margin-top: 2px; }
/* Round 10 Phase 0: the "Flag this roof" control under the rooftop photo */
.roofflag { margin-top: var(--sp-3); }
.roofflag .flagnote {
  width: 100%; box-sizing: border-box; margin-top: var(--sp-2); min-height: var(--sp-7);
  padding: var(--sp-2); border-radius: var(--r-1); border: 1px solid var(--c-line);
  background: var(--c-sunken); color: var(--c-ink); font: inherit; font-size: var(--fs-1);
  resize: vertical;
}
.roofflag .flagmsg { margin-top: var(--sp-2); }

#rooflightbox {
  position: fixed; inset: 0; z-index: 400;
  background: var(--c-scrim);
  display: none; align-items: center; justify-content: center;
  cursor: zoom-out; padding: var(--sp-6);
}
#rooflightbox.open { display: flex; }
#rooflightbox img {
  max-width: 92vw; max-height: 88vh; border-radius: var(--r-3);
  box-shadow: var(--e-3); border: 1px solid var(--c-line);
}

/* --- 3.9 pathway and scenario cards -------------------------------------- */
.pcard {
  border: 1px solid var(--c-line-soft); border-radius: var(--r-3);
  padding: var(--sp-4); margin: var(--sp-3) 0; transition: var(--t-base);
}
.pcard:hover { border-color: var(--c-line); }
.pcard.on { border-color: var(--c-accent); background: var(--c-accent-tint); }
.pcard .ptop { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.pcard .pttl { font-weight: var(--fw-bold); font-size: var(--fs-3); color: var(--c-ink); }
.pcard .pdesc { font-size: var(--fs-2); color: var(--c-ink-2); line-height: var(--lh-normal); margin: var(--sp-1) 0 var(--sp-3); }
.pcard .pstats { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2) var(--sp-4); margin-bottom: var(--sp-3); }
.pcard .pstat .sl { font-size: var(--fs-1); color: var(--c-ink-3); display: flex; align-items: center; gap: var(--sp-1); }
.pcard .pstat .sv { font-size: var(--fs-4); font-weight: var(--fw-bold); color: var(--c-ink); }
.pcard .sv.good { color: var(--c-good); }
.pcard .sv.bad { color: var(--c-bad); }
.pcard .pshow {
  all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-2); color: var(--c-accent-ink);
  border: 1px solid var(--c-line); border-radius: var(--r-1);
  padding: var(--sp-2) var(--sp-4); transition: var(--t-base);
}
.pcard .pshow:hover { border-color: var(--c-accent); background: var(--c-accent-tint); }

/* --- 3.10 PED assessment ------------------------------------------------- */
#pedcard .verdict {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  border-radius: var(--r-2); padding: var(--sp-3) var(--sp-4); margin: 2px 0 var(--sp-4);
  background: var(--c-bad-tint); border: 1px solid var(--c-bad);
}
#pedcard .verdict.pass { background: var(--c-leaf-tint); border-color: var(--c-leaf); }
#pedcard .verdict .vt { font-weight: var(--fw-bold); color: var(--c-bad); font-size: var(--fs-3); font-family: var(--font-head); }
#pedcard .verdict.pass .vt { color: var(--c-leaf); }
#pedcard .verdict .vd { font-size: var(--fs-2); color: var(--c-ink-2); line-height: var(--lh-normal); margin-top: 2px; }

.twoview { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); margin: var(--sp-2) 0 var(--sp-1); }
.twoview .tv { border: 1px solid var(--c-line-soft); border-radius: var(--r-2); padding: var(--sp-3); }
.twoview .tvh { font-size: var(--fs-1); text-transform: uppercase; letter-spacing: 0.03em; color: var(--c-ink-3); display: flex; align-items: center; gap: var(--sp-1); }
.twoview .tvv { font-size: var(--fs-5); font-weight: var(--fw-bold); margin-top: 3px; font-family: var(--font-head); }
.twoview .tvv.good { color: var(--c-good); }
.twoview .tvv.bad { color: var(--c-bad); }
.twoview .tvs { font-size: var(--fs-1); color: var(--c-ink-3); margin-top: 3px; line-height: var(--lh-snug); }

.pedhead { font-size: var(--fs-1); text-transform: uppercase; letter-spacing: var(--track-caps); color: var(--c-ink-3); margin: var(--sp-4) 0 var(--sp-1); display: flex; align-items: center; gap: var(--sp-2); }
.pedkpi { display: flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-2); padding: var(--sp-1) 0; border-top: 1px solid var(--c-line-soft); }
.pedkpi .kd { width: var(--sp-3); height: var(--sp-3); min-width: var(--sp-3); border-radius: 50%; }
.pedkpi .kd.bad { background: var(--c-bad); }
.pedkpi .kd.ok { background: var(--c-accent); }
.pedkpi .kn { color: var(--c-ink-2); flex: 1; }
.pedkpi .kv { font-weight: var(--fw-bold); color: var(--c-ink); font-family: var(--font-head); }
#pedmismatch svg { width: 100%; height: 96px; display: block; margin: var(--sp-1) 0 2px; }
#pedmismatch text { fill: var(--c-ink-3); }
.pedbuurt { display: flex; justify-content: space-between; font-size: var(--fs-2); color: var(--c-ink-2); padding: 3px 0; }
.pedbuurt b { color: var(--c-ink); font-family: var(--font-head); }
.pedpolicy { font-size: var(--fs-1); color: var(--c-ink-2); line-height: var(--lh-normal); margin: var(--sp-1) 0; }
.pedpolicy b { color: var(--c-ink); }

#paretoBox svg { width: 100%; height: 150px; display: block; }
#pareto text { fill: var(--c-ink-3); }
.tradeoff { font-size: var(--fs-2); color: var(--c-ink-2); line-height: var(--lh-normal); margin: var(--sp-3) 0; }

/* --- 3.11 button -------------------------------------------------------- */
.btn {
  all: unset; cursor: pointer;
  padding: var(--sp-3) var(--sp-5); border-radius: var(--r-2);
  font-size: var(--fs-3); font-weight: var(--fw-semibold); transition: var(--t-base);
}
.btn.primary { background: var(--c-accent-deep); color: var(--c-ink); }
.btn.primary:hover { background: var(--c-accent); }
.btn.ghost { color: var(--c-ink-2); border: 1px solid var(--c-line); }
.btn.ghost:hover { color: var(--c-ink); border-color: var(--c-accent); }

.opt:active, .presets button:active, .btn:active, .pshow:active, .railbtn:active,
.iconbtn:active, .seg button:active, .lens button:active, .i:active,
#basemapPop button[data-bm]:active { transform: scale(0.965); }

/* --- 3.12 basemap popover ------------------------------------------------ */
#basemapWrap { position: relative; }
#basemapPop {
  position: absolute; top: calc(var(--topbar-h) - var(--sp-3)); right: 0;
  width: 210px; padding: var(--sp-3); display: none; z-index: 70;
}
#basemapPop.open { display: block; }
#basemapPop .bmhead {
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--c-ink-3); margin: 2px var(--sp-1) var(--sp-2);
  display: flex; align-items: center; gap: var(--sp-2);
}
#basemapPop button[data-bm] {
  all: unset; cursor: pointer; display: block; width: 100%; box-sizing: border-box;
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-1);
  font-size: var(--fs-3); color: var(--c-ink-2); transition: var(--t-base);
}
#basemapPop button[data-bm]:hover { background: var(--c-hover); color: var(--c-ink); }
#basemapPop button[data-bm].on { background: var(--c-accent-deep); color: var(--c-ink); }
#basemapPop .bmnote { font-size: var(--fs-1); color: var(--c-ink-3); line-height: var(--lh-snug); margin: var(--sp-2) var(--sp-1) 2px; }

/* --- 3.13 conditions chip, drawhint, onboarding -------------------------- */
#conditions { position: absolute; left: 50%; transform: translateX(-50%); bottom: var(--sp-4); z-index: 33; }
#condChip {
  all: unset; cursor: pointer; display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-pill);
  font-size: var(--fs-2); color: var(--c-ink-2);
}
#condChip:hover { color: var(--c-ink); }
#condPop { position: absolute; left: 50%; transform: translateX(-50%); bottom: 44px; width: 280px; padding: var(--sp-4); display: none; }
#condPop.open { display: block; }
#condPop .cline { margin: var(--sp-2) 0; font-size: var(--fs-2); color: var(--c-ink-2); }
#condPop .cline b { color: var(--c-ink); font-size: var(--fs-4); font-weight: var(--fw-bold); }
#condPop .cs { font-size: var(--fs-1); color: var(--c-ink-3); display: block; margin-top: 1px; }
#co2now {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4); border-radius: var(--r-pill);
  font-size: var(--fs-1); color: var(--c-ink-2); margin-top: var(--sp-3);
}
#co2now b { font-family: var(--font-head); }

#drawhint {
  position: absolute; top: var(--below); left: 50%; transform: translateX(-50%);
  z-index: 38; padding: var(--sp-3) var(--sp-5); border-radius: var(--r-pill);
  font-size: var(--fs-3); color: var(--c-ink); display: none;
  align-items: center; gap: var(--sp-3);
}
#drawhint.on { display: flex; }

#onboard {
  position: fixed; inset: 0; z-index: 300;
  background: var(--c-scrim); backdrop-filter: blur(4px);
  display: none; align-items: center; justify-content: center;
}
#onboard.open { display: flex; }
#obcard { width: 400px; max-width: calc(100% - var(--sp-7)); padding: var(--sp-6) var(--sp-6) var(--sp-5); text-align: center; }
#obcard .obig { font-size: var(--fs-7); margin-bottom: var(--sp-2); }
#obcard h2 { margin: var(--sp-1) 0 var(--sp-3); font-size: var(--fs-5); }
#obcard p { margin: 0 0 var(--sp-5); color: var(--c-ink-2); font-size: var(--fs-3); line-height: var(--lh-loose); }
#obdots { display: flex; gap: var(--sp-2); justify-content: center; margin-bottom: var(--sp-5); }
#obdots i { width: 7px; height: 7px; border-radius: 50%; background: var(--c-line); transition: var(--t-base); }
#obdots i.on { background: var(--c-accent); width: 20px; border-radius: var(--r-1); }
.obrow { display: flex; gap: var(--sp-3); justify-content: center; }

/* --- 3.14 trust card ----------------------------------------------------- */
#trustcard {
  border: 1px solid var(--c-leaf); background: var(--c-leaf-tint);
  border-radius: var(--r-3); padding: var(--sp-4); margin: 0 0 var(--sp-4);
}
#trustcard .th {
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--c-ink-3); display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-2);
}
.trust-big { font-family: var(--font-head); font-size: var(--fs-6); font-weight: var(--fw-bold); color: var(--c-leaf); line-height: var(--lh-tight); }
.trust-lead { font-size: var(--fs-3); color: var(--c-ink-2); margin: 2px 0 var(--sp-3); }
.trust-text { font-size: var(--fs-2); color: var(--c-ink-3); line-height: var(--lh-normal); }
.trust-text b { color: var(--c-ink-2); }
#reliabilitybody { margin-top: var(--sp-3); }

/* --- 3.16 tree popup ----------------------------------------------------- */
#treepop {
  display: block; position: fixed; z-index: 250; max-width: 300px;
  padding: var(--sp-4); font-size: var(--fs-2); color: var(--c-ink);
  border-radius: var(--r-4); line-height: var(--lh-normal);
}

/* --- 3.18 chat ----------------------------------------------------------- */
#chatfab {
  position: fixed; right: var(--sp-6); bottom: var(--sp-6); z-index: 90;
  width: 52px; height: 52px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--c-accent-deep); color: var(--c-ink);
  border: 1px solid var(--c-accent); cursor: pointer; box-shadow: var(--e-2);
}
#chatfab:hover { background: var(--c-accent); }

/* ================================================== 4. Plan mode: answers === */
body:not(.planner) .planner-only { display: none !important; }

/* ONE ASK SURFACE PER AUDIENCE.
   There are two ways to ask this twin a question, and they were both on screen at once in
   Plan: the six questions in the Plan panel, and the assistant bubble bottom right. Two
   front doors to the same house, and the two answer differently, which leaves the reader
   deciding which one to believe rather than reading an answer.
   They are split by audience instead. The six questions are already Plan only, through
   .planner-only on #panel-scenario. The bubble was not hidden anywhere, so it is Explore
   only from here, which is where an open ended question belongs: a resident arrives with a
   question in their own words, a planner arrives with the six.
   NEITHER SURFACE WAS REMOVED. web/ask.js holds three analyses (where to start first, the
   proposed pathway per building, and who is most at risk) that exist nowhere else and
   would become unreachable if the panel went. */
body.planner #chatBubble,
body.planner #chatPanel { display: none !important; }

.asklead { margin: 2px 0 var(--sp-4); font-size: var(--fs-3); color: var(--c-ink-2); }

.qcard {
  all: unset; cursor: pointer; display: flex; align-items: center; gap: var(--sp-4);
  width: 100%; box-sizing: border-box;
  border: 1px solid var(--c-line-soft); border-radius: var(--r-3);
  padding: var(--sp-4); margin: 0 0 var(--sp-3);
  transition: var(--t-base); position: relative;
}
.qcard:hover { border-color: var(--c-accent); background: var(--c-accent-tint); transform: translateX(2px); }
.qcard:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
.qcard .qico {
  width: var(--sp-7); height: var(--sp-7); min-width: var(--sp-7);
  border-radius: var(--r-3); display: flex; align-items: center; justify-content: center;
  color: var(--c-accent-ink);
  background: linear-gradient(140deg, var(--c-accent-tint-strong), var(--c-leaf-tint));
}
.qcard .qt { font-family: var(--font-head); font-weight: var(--fw-semibold); font-size: var(--fs-4); color: var(--c-ink); line-height: var(--lh-tight); }
.qcard .qs { font-size: var(--fs-2); color: var(--c-ink-3); margin-top: 2px; line-height: var(--lh-snug); }
.qcard .qgo { margin-left: auto; color: var(--c-ink-3); opacity: 0; transition: var(--t-base); }
.qcard:hover .qgo { opacity: 1; color: var(--c-accent-ink); }

#askBack {
  all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-3); color: var(--c-ink-2);
  padding: var(--sp-2) var(--sp-4); border-radius: var(--r-2);
  border: 1px solid var(--c-line-soft); margin-bottom: var(--sp-4); transition: var(--t-base);
}
#askBack:hover { color: var(--c-ink); border-color: var(--c-line); background: var(--c-hover); }
#askBack:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }

#ansCard { animation: ansIn 240ms var(--ease); }

.ans-q { display: flex; align-items: center; gap: var(--sp-3); margin: 0 0 var(--sp-4); }
.ans-q .qico {
  width: 30px; height: 30px; min-width: 30px; border-radius: var(--r-2);
  display: flex; align-items: center; justify-content: center;
  color: var(--c-accent-ink);
  background: linear-gradient(140deg, var(--c-accent-tint-strong), var(--c-leaf-tint));
}
.ans-q .qqt {
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--c-ink-3); line-height: var(--lh-snug); flex: 1;
}

/* THE HERO. One headline sentence in plain Dutch, then the numbers. */
.ans-headline {
  font-family: var(--font-head); font-size: var(--fs-4); font-weight: var(--fw-semibold);
  color: var(--c-ink); line-height: var(--lh-normal);
  margin: 0 0 var(--sp-4); padding-left: var(--sp-4);
  border-left: 3px solid var(--c-accent);
}
.ans-sub {
  font-size: var(--fs-2); color: var(--c-ink-2); line-height: var(--lh-normal);
  margin: calc(-1 * var(--sp-2)) 0 var(--sp-4); padding-left: var(--sp-4);
}

.ans-nums { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); margin: 0 0 var(--sp-4); }
.ans-nums .bn {
  border: 1px solid var(--c-line-soft); border-radius: var(--r-3);
  padding: var(--sp-4); background: var(--c-accent-tint); transition: var(--t-base);
}
.ans-nums .bn:hover { border-color: var(--c-line); }
.ans-nums .bn.wide { grid-column: 1 / -1; }
.ans-nums .bv {
  font-family: var(--font-head); font-size: var(--fs-5); font-weight: var(--fw-bold);
  color: var(--c-ink); line-height: var(--lh-tight); letter-spacing: -0.01em;
}
.ans-nums .bv.good { color: var(--c-good); }
.ans-nums .bv.bad { color: var(--c-bad); }
.ans-nums .bl {
  font-size: var(--fs-2); color: var(--c-ink-2); margin-top: var(--sp-1);
  line-height: var(--lh-snug); display: flex; align-items: flex-start; gap: var(--sp-1);
}
/* the plain language range, under the label it belongs to */
.ans-nums .brange {
  font-size: var(--fs-1); color: var(--c-ink-3); margin-top: var(--sp-1);
  line-height: var(--lh-snug); padding-top: var(--sp-1);
  border-top: 1px solid var(--c-line-soft);
}
.ans-nums .bl .i { margin-top: 1px; }

.ans-extra {
  font-size: var(--fs-2); color: var(--c-ink-2); line-height: var(--lh-normal);
  margin: 0 0 var(--sp-4); padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-2); background: var(--c-leaf-tint); border: 1px solid var(--c-leaf);
}
.ans-extra b { color: var(--c-ink); }

.ans-foot {
  display: flex; flex-direction: column; gap: var(--sp-2);
  border-top: 1px solid var(--c-line-soft); padding-top: var(--sp-3); margin-bottom: 2px;
}
.ans-src, .ans-caveat {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  font-size: var(--fs-1); line-height: var(--lh-normal); margin: 0;
}
.ans-src { color: var(--c-ink-3); }
.ans-src svg { color: var(--c-ink-3); flex: none; margin-top: 1px; }
.ans-src b { color: var(--c-ink-2); font-weight: var(--fw-semibold); }
.ans-caveat { color: var(--c-warn); }
.ans-caveat svg { flex: none; margin-top: 1px; }

#ansMethod, #ansAdvanced {
  border: 1px solid var(--c-line-soft); border-radius: var(--r-3);
  margin-top: var(--sp-3); padding: 0 var(--sp-4);
}
#ansMethod > .chead, #ansAdvanced > .chead { padding: var(--sp-3) 0; }
#ansMethod > .cbody, #ansAdvanced > .cbody { padding-bottom: var(--sp-3); }
#ansMethodBody { font-size: var(--fs-3); color: var(--c-ink-2); line-height: var(--lh-loose); }
#ansAdvBody > .card, #ansAdvBody > div { margin-top: var(--sp-2); }

.skel {
  border-radius: var(--r-2);
  background: linear-gradient(100deg, var(--c-hover) 40%, var(--c-line-soft) 50%, var(--c-hover) 60%);
  background-size: 200% 100%;
  animation: shimmer 1.3s infinite;
}
.skel-headline { height: 52px; margin-bottom: var(--sp-4); }
.skel-tile { height: 64px; }
.skel-tile.wide { grid-column: 1 / -1; }
.skel-line { height: 26px; }

/* --- 4.1 named scenario cards (they replace the raw sliders) -------------- */
.scenariorow { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); margin: var(--sp-2) 0 var(--sp-3); }
.scard {
  all: unset; cursor: pointer;
  border: 1px solid var(--c-line-soft); border-radius: var(--r-2);
  padding: var(--sp-3); transition: var(--t-base);
  display: flex; flex-direction: column; gap: 2px;
}
.scard:hover { border-color: var(--c-accent); background: var(--c-accent-tint); }
.scard:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
.scard.on { background: var(--c-accent-deep); border-color: var(--c-accent-deep); }
.scard .sn { font-family: var(--font-head); font-size: var(--fs-2); font-weight: var(--fw-semibold); color: var(--c-ink); line-height: var(--lh-tight); }
.scard .sd { font-size: var(--fs-1); color: var(--c-ink-3); line-height: var(--lh-snug); }
.scard.on .sd { color: var(--c-accent-ink); }

.langcode { font-family: var(--font-head); font-size: var(--fs-1); font-weight: var(--fw-semibold); letter-spacing: 0.04em; }

/* --- 4.1a the exchange rate picker, Phase 5 ---------------------------------
   Four stated rates, none correct. Each prints how many trees it condemns, so the cost
   of the assumption is on the button before you press it. */
.ratepick { display: grid; gap: var(--sp-1); margin: 0 0 var(--sp-3); }
.ratepick b { font-size: var(--fs-1); color: var(--c-ink); margin-bottom: var(--sp-1); }
.ratebtn {
  all: unset; cursor: pointer; display: flex; justify-content: space-between;
  align-items: baseline; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3); border: 1px solid var(--c-line-soft);
  border-radius: var(--r-2); transition: var(--t-base);
}
.ratebtn:hover { border-color: var(--c-accent); background: var(--c-accent-tint); }
.ratebtn:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
.ratebtn.on { background: var(--c-accent-deep); border-color: var(--c-accent-deep); }
.ratebtn .rn { font-size: var(--fs-1); color: var(--c-ink); }
.ratebtn .rv { font-size: var(--fs-0); color: var(--c-ink-3); white-space: nowrap; }
.ratebtn.on .rn, .ratebtn.on .rv { color: var(--c-accent-ink); }

/* --- 4.1b de schakelaar maaiveld / daken, zelfde motor twee kanten op ----- */
.sunmode { display: flex; gap: var(--sp-1); margin: 0 0 var(--sp-3); }
.smbtn {
  all: unset; cursor: pointer; flex: 1; text-align: center;
  padding: var(--sp-2) var(--sp-3); border: 1px solid var(--c-line-soft);
  border-radius: var(--r-2); font-size: var(--fs-1); color: var(--c-ink-2);
  transition: var(--t-base);
}
.smbtn:hover { border-color: var(--c-accent); }
.smbtn:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 2px; }
.smbtn.on { background: var(--c-accent-deep); border-color: var(--c-accent-deep); color: var(--c-accent-ink); }
/* De naamdagen van de zevende vraag. Eigen id, want #sunScenarios bestond al in
   index.html voor de zonstand-kaartjes van Fase 2, en een dubbel id levert stil de
   verkeerde, onzichtbare container op. Gemeten met een DOM-probe, niet geraden. */
#askSunDays { display: flex; width: 100%; gap: var(--sp-2); margin: 0 0 var(--sp-3); }
#askSunDays .scard { flex: 1 1 0; min-width: 0; }
#askSunDays .scard[data-on] { background: var(--c-accent-deep); border-color: var(--c-accent-deep); }
#askSunDays .scard[data-on] .sd { color: var(--c-accent-ink); }
.ans-list { font-size: var(--fs-1); color: var(--c-ink-2); margin: 0 0 var(--sp-3); }
.ans-list b { color: var(--c-ink); }
.ans-list ul { margin: var(--sp-1) 0 0; padding-left: var(--sp-4); }
.ans-list li { margin: 0 0 var(--sp-1); line-height: var(--lh-snug); }

/* --- 4.2 the computation parameters, printed ON the map ------------------- */
#mapparams {
  position: absolute; left: 50%; transform: translateX(-50%);
  /* boven de stapel met live omstandigheden, anders schrijven ze over elkaar heen */
  bottom: calc(var(--sp-4) + 96px); z-index: 33;
  /* AUDIT FINDING, 2026-08-06, gezien op 25b_presentation_sun.png en niet uit de code
     afgeleid: deze strook stond gecentreerd op het HELE venster, dus zodra het rechter
     gebouwpaneel openstond liep hij eronderdoor en las je de rekenparameters dwars door
     het paneel heen. Hij hoort gecentreerd op de KAART te staan, en dat is het venster
     min het paneel dat openstaat. */
  display: none; align-items: center; flex-wrap: wrap; justify-content: center;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-2) var(--sp-4); border-radius: var(--r-pill);
  font-size: var(--fs-1); color: var(--c-ink-2); max-width: 60vw;
}
#mapparams.on { display: flex; }
/* Het rechter gebouwpaneel is open: schuif de strook naar links over de halve
   paneelbreedte, zodat hij binnen het zichtbare deel van de kaart blijft. */
body:has(#bpanel.open) #mapparams {
  transform: translateX(calc(-50% - (var(--bpanel-w) + var(--sp-4)) / 2));
  max-width: calc(100vw - var(--bpanel-w) - var(--sp-6) * 2);
}
#mapparams .mp { display: flex; align-items: center; gap: var(--sp-1); white-space: nowrap; }
#mapparams .mpk { color: var(--c-ink-3); text-transform: uppercase; letter-spacing: 0.04em; }
#mapparams .mpv { color: var(--c-ink); font-family: var(--font-head); font-weight: var(--fw-semibold); }

/* --- 4.3 the machinery drawer ------------------------------------------- */
/* The machinery is revealed IN PLACE, but only when the Gevorderd drawer is really
   open. Before this rule the lens and the grid switches sat under a COLLAPSED drawer,
   in full view of a citizen, which is exactly the machinery the July ruling banned. */
#machinery { display: none; }
body.adv-open #machinery.adv-visible { display: block; }
#machinery > * { display: none; }
#machinery > .adv-on { display: block; }
#lensblock.adv-on, #gridblock.adv-on { display: block; }

/* ========================================================== 5. utilities ===
   These exist for one reason: to retire the 195 inline style attributes. Each
   is a single declaration that used to be written inline dozens of times. */

/* icon sizes, which were 60 of the 195 */
.ic { flex: none; }
.ic-1 { width: var(--ic-1); height: var(--ic-1); }
.ic-2 { width: var(--ic-2); height: var(--ic-2); }
.ic-3 { width: var(--ic-3); height: var(--ic-3); }
.ic-4 { width: var(--ic-4); height: var(--ic-4); }
.ic-5 { width: var(--ic-5); height: var(--ic-5); }

/* show and hide, which was 55 of the 69 JavaScript style assignments */
.is-hidden { display: none !important; }
.is-block { display: block; }
.is-flex { display: flex; }
.is-inline-flex { display: inline-flex; }

.u-row { display: flex; gap: var(--sp-2); }
.u-row-4 { display: flex; gap: var(--sp-4); }
.u-between { display: flex; justify-content: space-between; align-items: center; }
.u-grow { flex: 1; }
.u-push { margin-left: auto; }
.u-center { text-align: center; }
.u-full { width: 100%; }
.u-rel { position: relative; }
.u-nopointer { pointer-events: none; }
.u-pointer { cursor: pointer; }

.u-mt-1 { margin-top: var(--sp-1); }
.u-mt-2 { margin-top: var(--sp-2); }
.u-mt-3 { margin-top: var(--sp-3); }
.u-mt-4 { margin-top: var(--sp-4); }
.u-mb-3 { margin-bottom: var(--sp-3); }
.u-mb-4 { margin-bottom: var(--sp-4); }

.t-1 { font-size: var(--fs-1); }
.t-2 { font-size: var(--fs-2); }
.t-3 { font-size: var(--fs-3); }
.t-4 { font-size: var(--fs-4); }
.t-5 { font-size: var(--fs-5); }
.t-6 { font-size: var(--fs-6); }
.t-ink { color: var(--c-ink); }
.t-ink-2 { color: var(--c-ink-2); }
.t-ink-3 { color: var(--c-ink-3); }
.t-good { color: var(--c-good); }
.t-warn { color: var(--c-warn); }
.t-bad { color: var(--c-bad); }
.t-accent { color: var(--c-accent-ink); }
.t-lead { line-height: var(--lh-loose); }
.t-medium { font-weight: var(--fw-medium); }
.t-semibold { font-weight: var(--fw-semibold); }
.t-bold { font-weight: var(--fw-bold); }

#status { display: none; }

/* ============================================ 6. responsive and projector === */
@media (max-width: 820px) {
  #brand span.t { display: none; }
  .sidepanel { width: calc(100% - var(--rail-w) - var(--sp-6)); }
  #bpanel { width: calc(100% - var(--sp-6)); }
}
/* On narrow windows the panels span most of the width, leaving no clear spot
   for the bottom chips, so they are hidden rather than left half covered. */
@media (max-width: 960px) {
  #conditions, #mapparams { display: none; }
}

/* PRESENTATION MODE. The token file already moved the base size and the
   surfaces. These are the few rules that are about the ROOM rather than the
   scale: heavier borders, no translucency to fight a projector's gamma, and
   the decorative chrome removed so only the answer is left. */
body.presenting .glass { backdrop-filter: none; -webkit-backdrop-filter: none; }
body.presenting .sidepanel { border-width: 2px; }
body.presenting #rail,
body.presenting #chatBubble,
body.presenting #chatPanel,
body.presenting #basemapWrap { display: none; }
body.presenting .ans-headline { border-left-width: 5px; }
body.presenting .qcard .qs, body.presenting .footnote { color: var(--c-ink-2); }
body.presenting .legend .lband { color: var(--c-ink-2); }
body.presenting #cesium .cesium-widget-credits { display: none; }
body.presenting .sidepanel { left: var(--sp-4); }
/* AUDIT FINDING, 2026-08-06: at 18px five of the six answer cards overflowed the panel,
   and on one the caveat was sliced in half. The type must NOT shrink, so the vertical
   rhythm tightens instead: the panel takes the full height it can, the ranges fold into
   the tile they belong to, and the gaps come down a step. */
body.presenting .sidepanel {
  top: calc(var(--topbar-h) + var(--sp-2));
  max-height: calc(100% - var(--topbar-h) - var(--sp-4));
  padding: var(--sp-3) var(--sp-4);
}
body.presenting .ans-headline { margin-bottom: var(--sp-3); }
body.presenting .ans-sub { margin-bottom: var(--sp-3); }
body.presenting .ans-nums { gap: var(--sp-2); margin-bottom: var(--sp-3); }
body.presenting .ans-nums .bn { padding: var(--sp-3); }
body.presenting .ans-nums .brange { display: none; }
body.presenting .ans-extra { margin-bottom: var(--sp-3); padding: var(--sp-2) var(--sp-3); }
body.presenting .ans-q { margin-bottom: var(--sp-3); }
body.presenting #askBack { margin-bottom: var(--sp-3); }
/* AUDIT: the wider panel physically covered the on-map parameters, so they move right */
body.presenting #mapparams {
  left: auto; right: var(--sp-5); transform: none; max-width: 46vw;
}

/* ---- swatch classes for the categorical families and the no-value states ---- */
.sw-cat-1 { background: var(--d-cat-1); }
.sw-cat-2 { background: var(--d-cat-2); }
.sw-cat-3 { background: var(--d-cat-3); }
.sw-cat-4 { background: var(--d-cat-4); }
.sw-none-empty { background: var(--c-line); }
.sw-none-never { background: var(--c-surface-2); }
.sw-none-outside { background: var(--c-line-soft); }
/* Round 10 Phase 1: too small to assess, panels without a capacity figure, not a building */
.sw-none-small { background: var(--d-small); }
.sw-none-nocap { background: var(--d-nocap); }
.sw-none-noassess { background: var(--d-noassess); }
.sw-none-gone { background: var(--d-gone); }

/* svg axis labels inside the trade off plot */
.pxlab { font-size: var(--fs-1); }

/* the Cesium canvas cursor, as a class so no JavaScript writes a style property */
.cur-pointer { cursor: pointer; }
.cur-crosshair { cursor: crosshair; }
.u-mr-1 { margin-right: var(--sp-1); }

/* --- 3.18b the assistant drawer. This was 36 lines of CSS that chat.js injected
   into <head> at runtime, with 5 colour literals and 9 font sizes of its own. --- */
#chatBubble {
  position: absolute; right: var(--sp-5); bottom: var(--sp-5); z-index: 120;
  width: 56px; height: 56px; border-radius: 50%;
  border: none; cursor: pointer;
  background: linear-gradient(140deg, var(--c-accent-deep), var(--c-accent));
  color: var(--c-ink); box-shadow: var(--e-2);
  display: flex; align-items: center; justify-content: center; transition: transform var(--t-base);
}
#chatBubble:hover { transform: scale(1.06); }
#chatBubble .pulse {
  position: absolute; inset: 0; border-radius: 50%;
  box-shadow: 0 0 0 0 var(--c-accent-tint-strong); animation: cpulse 2.6s infinite;
}
@keyframes cpulse {
  0% { box-shadow: 0 0 0 0 var(--c-accent-tint-strong); }
  70% { box-shadow: 0 0 0 14px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
#chatPanel {
  position: absolute; right: var(--sp-5); bottom: var(--sp-5); z-index: 121;
  width: 360px; max-width: calc(100% - var(--sp-7) - var(--sp-1));
  height: 74%; max-height: 560px; display: none;
  flex-direction: column; overflow: hidden; border-radius: var(--r-4);
}
#chatPanel.open { display: flex; animation: cin 0.22s var(--ease); }
@keyframes cin { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
#chatHead {
  padding: var(--sp-4); display: flex; justify-content: space-between;
  align-items: center; border-bottom: 1px solid var(--c-line-soft);
}
#chatHead .t { font-weight: var(--fw-bold); font-size: var(--fs-3); display: flex; align-items: center; gap: var(--sp-3); }
#chatClose { all: unset; cursor: pointer; color: var(--c-ink-3); display: flex; }
#chatClose:hover { color: var(--c-ink); }
#chatBanner {
  background: var(--c-warn-tint); color: var(--c-warn);
  font-size: var(--fs-1); padding: var(--sp-2) var(--sp-4); line-height: var(--lh-snug);
}
#chatMsgs { flex: 1; overflow: auto; padding: var(--sp-4); font-size: var(--fs-3); line-height: var(--lh-normal); }
.cmsg { margin: var(--sp-2) 0; padding: var(--sp-3) var(--sp-4); border-radius: var(--r-3); max-width: 92%; white-space: pre-wrap; word-wrap: break-word; }
.cmsg.user { background: var(--c-accent-deep); color: var(--c-ink); margin-left: auto; border-bottom-right-radius: var(--sp-1); }
.cmsg.bot { background: var(--c-hover); color: var(--c-ink); border-bottom-left-radius: var(--sp-1); white-space: normal; }
.cmsg.bot p { margin: var(--sp-2) 0; }
.cmsg.bot p:first-child { margin-top: 0; }
.cmsg.bot p:last-child { margin-bottom: 0; }
.cmsg.bot strong { color: var(--c-ink); font-weight: var(--fw-bold); }
.cmsg.bot em { font-style: italic; }
.cmsg.bot ul, .cmsg.bot ol { margin: var(--sp-2) 0; padding-left: var(--sp-5); }
.cmsg.bot li { margin: 3px 0; }
.cmsg.bot code {
  background: var(--c-hover); padding: 1px var(--sp-1); border-radius: var(--r-1);
  font-family: ui-monospace, Menlo, Consolas, monospace; font-size: var(--fs-2);
}
.cmsg.bot pre.cblock {
  background: var(--c-sunken); border: 1px solid var(--c-line-soft);
  border-radius: var(--r-1); padding: var(--sp-3) var(--sp-4); margin: var(--sp-2) 0; overflow-x: auto;
}
.cmsg.bot pre.cblock code { background: none; padding: 0; font-size: var(--fs-2); line-height: var(--lh-normal); }
.cmsg.bot a { color: var(--c-accent-ink); text-decoration: underline; }
.cmsg.bot a:hover { color: var(--c-ink); }
.ctrace { font-size: var(--fs-1); color: var(--c-ink-3); margin-top: var(--sp-1); line-height: var(--lh-normal); }
#chatForm { display: flex; gap: var(--sp-2); padding: var(--sp-3); border-top: 1px solid var(--c-line-soft); }
#chatIn {
  flex: 1; padding: var(--sp-3) var(--sp-4); border: 1px solid var(--c-line);
  border-radius: var(--r-2); background: var(--c-sunken); color: var(--c-ink);
  font-size: var(--fs-3); outline: none;
}
#chatIn:focus { border-color: var(--c-accent); }
#chatSend {
  all: unset; cursor: pointer; background: var(--c-accent-deep); color: var(--c-ink);
  border-radius: var(--r-2); padding: var(--sp-3) var(--sp-4); font-size: var(--fs-3);
  display: flex; align-items: center;
}
#chatSend:disabled { opacity: 0.5; }
.sugbtn {
  all: unset; cursor: pointer; display: inline-block; font-size: var(--fs-2);
  color: var(--c-ink-2); border: 1px solid var(--c-line); border-radius: var(--r-pill);
  padding: var(--sp-1) var(--sp-3); margin: 3px 3px 0 0;
}
.sugbtn:hover { border-color: var(--c-accent); color: var(--c-ink); }

/* utilities added while retiring the last inline styles */
.u-my-1 { margin: var(--sp-1) 0; }
.u-mb-1 { margin-bottom: var(--sp-1); }
.u-gap-2 { gap: var(--sp-2); }
.u-gap-3 { gap: var(--sp-3); }
.u-pad-tight { padding: 1px var(--sp-2); }
.u-pad-2 { padding: var(--sp-2); }
.u-pr-5 { padding-right: var(--sp-5); }
.u-boxed { border: 1px solid var(--c-line-soft); border-radius: var(--r-2); }
.u-rule { border-top: 1px solid var(--c-line-soft); margin: var(--sp-3) 0 var(--sp-2); }
.u-abs { position: absolute; }
.u-unset { all: unset; }

/* the tree trade off verdict box */
.verdictbox {
  margin-top: var(--sp-3); padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-1); color: var(--c-ink);
}
.verdictbox.good { background: var(--c-leaf-tint); }
.verdictbox.warn { background: var(--c-warn-tint); }

/* the trade off plot: two axes, direct labels, no radius or ring encoding */
.pxlab { fill: var(--c-ink-3); }

/* the PED seasonal mismatch chart: axis and month labels, as classes rather than
   SVG presentation attributes, which the token guard could not see */
.pedaxis { stroke: var(--c-line); }
.pedlab { font-size: var(--fs-1); fill: var(--c-ink-3); }

/* ==========================================================================
   THE SATELLITE CARD. Everything below uses tokens only, no literals, so
   scripts/design_audit.py still reports zero and presentation mode scales it
   with the rest of the interface.
   ========================================================================== */
#satcard { display: flex; flex-direction: column; gap: var(--sp-3); }
#satcard.is-hidden { display: none; }

.satchip { margin-bottom: var(--sp-1); }

/* The date selector across the clear scenes. Wraps rather than scrolls, so
   presentation mode cannot push a row off the panel. */
.satdays { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.satday {
  background: var(--c-surface-2); color: var(--c-ink-2);
  border: 1px solid var(--c-line-soft); border-radius: var(--r-pill);
  padding: var(--sp-1) var(--sp-3); font-size: var(--fs-1);
  font-family: var(--font-body); cursor: pointer; transition: background var(--t-fast);
}
.satday:hover { background: var(--c-hover); }
.satday.on {
  background: var(--c-accent-tint-strong); color: var(--c-accent-ink);
  border-color: var(--c-accent);
}

/* THE REFUSAL. It is given the warning tint deliberately: it is the sentence
   that says what this measurement may NOT be used for, and it must not read
   as a footnote. */
.satrefuse {
  background: var(--c-warn-tint); border-left: 2px solid var(--c-warn);
  border-radius: var(--r-1); padding: var(--sp-3);
  color: var(--c-ink-2); font-size: var(--fs-2); line-height: var(--lh-normal);
  margin: 0;
}
.satnote {
  color: var(--c-ink-3); font-size: var(--fs-1);
  line-height: var(--lh-snug); margin: 0;
}

/* THE PROVENANCE STRIP: which scene is drawn, when the twin last looked for a newer one,
   and how many clear images there have ever been. A map that does not say how old it is
   reads as current, and this one is a single satellite pass on a single day. */
.satprov {
  display: flex; flex-direction: column; gap: var(--sp-1);
  padding: var(--sp-2) 0; border-bottom: 1px solid var(--c-line-soft);
}
.satprovrow { display: flex; gap: var(--sp-2); font-size: var(--fs-1); }
.satprovk { color: var(--c-ink-3); text-transform: uppercase;
            letter-spacing: var(--track-caps); min-width: 34%; }
.satprovv { color: var(--c-ink-2); flex: 1; }

/* THE POINT READOUT. Bottom right, its own small box, so it neither covers the layer
   panel on the left nor fights the building panel: #bpanel is 384px wide at right 12px
   and this sits BELOW it, clear of the building panel's bottom edge. */
#satat {
  position: absolute; right: var(--sp-4); bottom: var(--sp-4);
  width: var(--panel-w); max-height: 46vh; overflow-y: auto; z-index: 37;
  border-radius: var(--r-3); padding: var(--sp-4);
  display: flex; flex-direction: column; gap: var(--sp-2);
}
#satat.is-hidden { display: none; }
.sathead {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--c-ink-3);
}
.satx {
  all: unset; cursor: pointer; margin-left: auto;
  color: var(--c-ink-3); font-size: var(--fs-4); line-height: 1;
  padding: 0 var(--sp-1);
}
.satx:hover { color: var(--c-ink); }
.satvals { display: flex; gap: var(--sp-4); }
.satval { display: flex; flex-direction: column; flex: 1; }

.satsec { display: flex; flex-direction: column; gap: var(--sp-2);
          padding-top: var(--sp-3); border-top: 1px solid var(--c-line-soft); }
.satsectitle {
  color: var(--c-ink); font-family: var(--font-head);
  font-size: var(--fs-2); font-weight: var(--fw-semibold);
  letter-spacing: var(--track-caps); text-transform: uppercase;
}

.sattrend { display: flex; flex-direction: column; gap: var(--sp-3); }
.satrow { display: flex; flex-direction: column; gap: var(--sp-1); }
.satrowhead { display: flex; justify-content: space-between; align-items: baseline;
              gap: var(--sp-2); }
.satlabel { color: var(--c-ink-2); font-size: var(--fs-2); }
.satslope { font-family: var(--font-head); font-size: var(--fs-4);
            font-weight: var(--fw-semibold); }

/* TRUSTED AND DOUBTED, and never colour alone: the trusted figure keeps the
   normal ink weight and the doubted one is struck through as well as tinted,
   so the distinction survives a colour blind reader and a greyscale print. */
.sattrust { color: var(--c-good); }
.satdoubt { color: var(--c-warn); text-decoration: line-through;
            text-decoration-thickness: 1px; }

.sattrade { display: flex; flex-direction: column; gap: var(--sp-3); }
.satlead { color: var(--c-ink); font-size: var(--fs-3);
           line-height: var(--lh-snug); margin: 0; }
.satpair { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.satstat {
  flex: 1 1 40%; display: flex; flex-direction: column; gap: var(--sp-1);
  background: var(--c-surface-2); border-radius: var(--r-2); padding: var(--sp-3);
}
.satbig { font-family: var(--font-head); font-size: var(--fs-5);
          font-weight: var(--fw-bold); }
.satsub { color: var(--c-ink-3); font-size: var(--fs-1); line-height: var(--lh-snug); }
.satlist { margin: 0; padding-left: var(--sp-5); color: var(--c-ink-2);
           font-size: var(--fs-2); line-height: var(--lh-normal); }
.satlist li { margin-bottom: var(--sp-1); }

/* ---------------- build dock (phase 5c, merged) ----------------
   THE READOUT MUST NOT SIT WHERE YOU DRAW. The first version put this in the Select
   panel, a full height sidebar over the left third of the map, so the user had to close
   it to draw and reopen it to read the answer. This is a COMPACT dock pinned to the
   bottom left, clear of the map centre where the cable is laid, and it stays live while
   drawing. Every colour and size is a token.

   ONE DOCK, TWO SECTIONS. The cable line tool and the asset palette had a dock each,
   stacked in the same corner behind two rail buttons, so only ever one of them could be
   read. They are sections of one dock now, separated by a rule rather than by a mode. */
.netdock {
  position: absolute; left: calc(var(--rail-w) + var(--sp-4)); bottom: var(--sp-5);
  width: var(--panel-w); max-height: var(--dock-h); z-index: 30;
  display: flex; flex-direction: column; gap: var(--sp-3);
}
.netdock.is-hidden { display: none; }

/* ONE CORNER, ONE COLUMN.
   The Build dock, the Results dock and the simulator notice each pinned THEMSELVES to
   this same spot with this same z-index, so they were not overlapping, they were the
   SAME RECTANGLE, and document order decided which one you could read. The notice is
   last in the markup, so it always won: it covered the asset palette and the dock's only
   Close button, which is what the user photographed.
   The corner is one element now and the three boxes are its children, laid out in a
   column. A column cannot overlap itself, so nothing arbitrates and there is no ordering
   rule to remember. */
.cornerbox {
  /* A flex item will not shrink below its own content unless it is told it may. Without
     this the column overruns its own max-height as soon as two boxes are open and climbs
     over the top bar. It looks like noise and it is load bearing. */
  min-height: 0;
  border-radius: var(--r-3); padding: var(--sp-4);
}
.cornerbox.is-hidden { display: none; }
/* WHO GIVES WAY WHEN THE COLUMN IS FULL, and it is not the message.
   The notice does not shrink, so a sentence the user has to read before anything else
   makes sense keeps its natural height instead of being scrolled down to two lines.
   Letting both boxes shrink does NOT achieve that: flex distributes shrinkage in
   proportion to each item's own content height, so the short box still loses its share,
   and the notice was measured at 94px of a 140px message with room to spare.
   TWO BOUNDS, AND THEY CANNOT FIGHT. The docks never go below the floor, and the notice
   never goes above its cap, and cap plus floor is less than the column, so there is no
   state where the only way to satisfy both is to overflow the corner. */
#simnotice { flex: 0 0 auto; max-height: var(--notice-max-h); overflow-y: auto; }
#builddock, #simdock { flex: 0 1 auto; overflow-y: auto; min-height: var(--dock-min-h); }
/* THE HEAD DOES NOT SCROLL AWAY WITH ITS OWN BODY. The dock had scrolled 807px and taken
   the word Build and the only Close button with it, so the user was inside a mode whose
   exit had left the screen. The top padding moves ONTO the head because a sticky element
   pins at the CONTENT box: leave the padding on the container and the body scrolls
   through a transparent strip above the head. */
#builddock, #simdock { padding-top: 0; }
#builddock > .ndhead, #simdock > .ndhead {
  position: sticky; top: 0; z-index: 1;
  padding-top: var(--sp-4); margin-bottom: var(--sp-3);
  /* OPAQUE, NOT GLASS. The dock is translucent by design, but a sticky head that shares
     that translucency shows the palette sliding underneath it, which reads as two lines
     of text printed on top of each other. This is the same colour the panel is built from,
     at full opacity, so it looks like part of the dock and hides what passes behind. */
  background: var(--c-surface-2);
}
.ndhead {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--c-ink-3); margin-bottom: var(--sp-3);
}
.ndhead .ndsp { margin-left: auto; }
.ndrow { display: flex; gap: var(--sp-2); margin-top: var(--sp-3); flex-wrap: wrap; }
.ndrow .opt { flex: 1; text-align: center; }
.ndlead { font-size: var(--fs-2); color: var(--c-ink-2); line-height: var(--lh-normal); }
.ndruns { margin-top: var(--sp-3); }
.ndrun {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-2); color: var(--c-ink-2);
  padding: var(--sp-1) 0; border-top: 1px solid var(--c-line-soft);
}
.ndrun .ndrunname { flex: 1; }

/* the two tools inside the one Build dock */
.buildsec + .buildsec {
  margin-top: var(--sp-4); padding-top: var(--sp-3);
  border-top: 1px solid var(--c-line-soft);
}

/* ---------------- model editor palette (phase 6a) ---------------- */
.edpal { display: flex; flex-wrap: wrap; gap: var(--sp-1); margin-top: var(--sp-2); }
.edpal .opt { flex: 0 0 auto; }
.edpal .opt.on { background: var(--c-accent-deep); color: var(--c-ink); }
.edcarrier {
  font-size: var(--fs-1); text-transform: uppercase; letter-spacing: var(--track-caps);
  color: var(--c-ink-3); margin-top: var(--sp-3); display: flex; align-items: center;
  gap: var(--sp-2);
}
.edcarrier .sw { flex: 0 0 auto; }
.edform { margin-top: var(--sp-3); }
.edform label { display: block; font-size: var(--fs-2); color: var(--c-ink-3);
                margin-top: var(--sp-2); }
.edform .edunit { color: var(--c-ink-3); font-size: var(--fs-1); }
.edform input { width: 100%; }
.edattr { font-size: var(--fs-1); color: var(--c-ink-3); }

/* SIMULATION RESULTS. The bar colours come from the same state tokens the swatches use,
   so no colour literal appears in web/simulation.js; only the bar HEIGHT is inline,
   because it is the one thing the browser can know at runtime. */
.simerr { white-space: pre-wrap; word-break: break-word; max-height: 14rem;
          overflow-y: auto; font-family: var(--font-mono, monospace);
          font-size: var(--fs-2); margin: var(--sp-2) 0; }
.simfig { float: right; color: var(--c-ink-2); }
.simcurve { margin-top: var(--sp-3); }
.simday { margin-bottom: var(--sp-3); }
.simbars { display: flex; align-items: flex-end; gap: 1px; height: 4rem;
           border-bottom: 1px solid var(--c-line); }
.simbar { display: block; flex: 1 1 auto; min-height: 1px; border-radius: 1px 1px 0 0; }
.simbar.s-summer { background: var(--c-warn); }
.simbar.s-winter { background: var(--c-accent); }
.simasset.on { outline: 2px solid var(--c-accent); }

/* THE PLAIN READING. Each sentence carries its figure beside it, always, so the words can
   be checked against the number without leaving the panel. */
.simreading { margin-top: var(--sp-2); }
.simsentence { border-left: 2px solid var(--c-line); padding-left: var(--sp-3);
               margin-bottom: var(--sp-3); }
.simsentence p { margin: 0 0 var(--sp-1) 0; }
.simfigure { color: var(--c-ink-2); font-size: var(--fs-2); }
.simfigure .v { color: var(--c-ink); font-weight: 600; }

/* ============================================================ Build workspace
   web/build.html. A SECOND PAGE, and it takes no exemption from this design system:
   web/label.html is the only file scripts/design_audit.py excuses, that exclusion is a
   fixed two element list, and tests/test_design_tokens.py asserts it is exactly those two
   names. So build.html carries no <style> block and no colour of its own, and every rule
   it needs lives here in terms of tokens.

   NO #stage RULE APPLIES. #stage is the map page's fixed full-viewport canvas, and this
   page is an ordinary scrolling document. */
body.bwpage {
  position: static;
  overflow: auto;
  background: var(--c-canvas);
}

.bwtop {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--c-line);
  background: var(--c-surface);
}

.bwtitle { display: flex; align-items: center; gap: var(--sp-3); }
.bwtitle h1 { font-family: var(--font-head); font-size: var(--fs-5); margin: 0; }

.bwmark {
  width: var(--sp-3);
  height: var(--sp-3);
  border-radius: 50%;
  background: var(--c-accent);
  display: inline-block;
}

.bwnav { display: flex; align-items: center; gap: var(--sp-3); }

.bwmain {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-5);
  padding: var(--sp-5);
  align-items: start;
}

/* THE READ REGION SPANS BOTH COLUMNS. It carries the tables and, from the next step, the
   charts, and a chart squeezed into half a column is a chart nobody reads. */
.bwwide { grid-column: 1 / -1; }

.bwcol {
  background: var(--c-surface);
  border: 1px solid var(--c-line-soft);
  border-radius: var(--r-3);
  padding: var(--sp-4);
}

.bwcol > .sub { margin-bottom: var(--sp-3); }
.bwbody + .bwbody { margin-top: var(--sp-4); }

.bwtable { width: 100%; border-collapse: collapse; margin-top: var(--sp-3); }
.bwtable th {
  text-align: left;
  font-size: var(--fs-2);
  color: var(--c-ink-3);
  font-weight: 600;
  padding: var(--sp-2) var(--sp-3) var(--sp-2) 0;
  border-bottom: 1px solid var(--c-line);
}
.bwtable td {
  padding: var(--sp-2) var(--sp-3) var(--sp-2) 0;
  border-bottom: 1px solid var(--c-line-soft);
  vertical-align: top;
}
.bwtable .bwid { color: var(--c-ink-3); width: var(--sp-7); }
.bwtable .bwnum { text-align: right; font-variant-numeric: tabular-nums; }

.bwruns { flex-wrap: wrap; }
.bwrun { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }

.bwfoot {
  padding: var(--sp-4) var(--sp-5) var(--sp-6);
  color: var(--c-ink-3);
  font-size: var(--fs-2);
  border-top: 1px solid var(--c-line-soft);
}

@media (max-width: 900px) {
  .bwmain { grid-template-columns: minmax(0, 1fr); }
}

/* The workspace's chart and reading blocks. Hand rolled SVG, so the sizes and the grid
   live here in tokens and the SERIES COLOUR is set from JavaScript through
   window.paint.token(), which reads --d-cat from this stylesheet. That is the only way a
   chart gets a colour without a literal ever appearing in a .js file. */
.bwread p { margin: 0 0 var(--sp-3); color: var(--c-ink-2); }
.bwread .bwfig { color: var(--c-ink); font-variant-numeric: tabular-nums; }

.bwrec th {
  text-align: left; color: var(--c-ink-3); font-weight: 600;
  padding-right: var(--sp-4); white-space: nowrap; border-bottom: none;
}
.bwrec td { border-bottom: none; }

.bwaid { word-break: break-all; }

.bwchart { margin-top: var(--sp-3); }
.bwchart svg { width: 100%; height: auto; display: block; }
.bwtick { fill: var(--c-ink-3); font-size: var(--fs-1); font-family: var(--font-body); }
.bwgrid { stroke: var(--c-line-soft); stroke-width: 1; }

.bwleg { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-bottom: var(--sp-2); }
.bwkey { display: inline-flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-2); color: var(--c-ink-2); }
.bwswatch { width: var(--sp-4); height: var(--sp-2); border-radius: var(--r-1);
  display: inline-block; }

/* THE FOUR SERIES COLOURS, as classes so no value is ever handed to an element from
   JavaScript. --d-cat is the validated categorical ramp: worst pair deltaE 10.0 under
   protanopia and 11.2 under deuteranopia, both above the floor of 6. There are FOUR, and a
   fifth series gets a name in the legend rather than a fifth colour. */
.bwline { fill: none; stroke-width: 2; stroke-linejoin: round; }
.bwline.bws-1 { stroke: var(--d-cat-1); }
.bwline.bws-2 { stroke: var(--d-cat-2); }
.bwline.bws-3 { stroke: var(--d-cat-3); }
.bwline.bws-4 { stroke: var(--d-cat-4); }
.bwswatch.bws-1 { background: var(--d-cat-1); }
.bwswatch.bws-2 { background: var(--d-cat-2); }
.bwswatch.bws-3 { background: var(--d-cat-3); }
.bwswatch.bws-4 { background: var(--d-cat-4); }

/* THE ASSEMBLE AND CALCULATE CONTROLS. Every colour is a token from tokens.css and every
   size is a spacing or radius token, so nothing here is a literal. */
.bwform { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center;
          margin: var(--sp-3) 0; }
.bwin { background: var(--c-surface-2); color: var(--c-ink); border: 1px solid var(--c-line);
        border-radius: var(--r-2); padding: var(--sp-2) var(--sp-3);
        font-family: var(--font-body); font-size: var(--fs-base); min-width: 0; }
.bwin:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 1px; }
.bwform .bwin { flex: 1 1 8rem; }
.bwtable .bwin { width: 100%; text-align: right; padding: var(--sp-1) var(--sp-2); }
.opt.bwprimary { background: var(--c-accent); color: var(--c-accent-ink);
                 border-color: var(--c-accent-deep); font-weight: var(--fw-semibold); }
.opt.bwprimary:hover:not(:disabled) { background: var(--c-accent-deep); }
.opt:disabled { opacity: 0.55; cursor: not-allowed; }
.opt.bwdel { padding: var(--sp-1) var(--sp-2); color: var(--c-ink-3); }
.opt.bwdel:hover { color: var(--c-bad); border-color: var(--c-bad); }
.bwform .flag { flex: 0 0 auto; margin: 0; }
.flagword { color: var(--c-warn); }

/* A FLAT SERIES IS DASHED, and the dash is the signal that survives when colour does not:
   protanopia, deuteranopia, greyscale printing and a bad projector all keep it. It is the
   second of four signals, after the geometry itself (a constant is a horizontal line) and
   before the word in the legend. See docs/build-workspace-charts-design.md section 3. */
.bwline.bwflat { stroke-dasharray: 7 5; }
.bwswatch.bwflat { opacity: 0.55; }
.bwflatword { color: var(--c-warn); font-size: var(--fs-1); }
