:root {
  /* Design tokens - shared with the DrivewayIQ marketing website so the
     calculator app and the site read as one product.

     The app runs on the site's blueprint theme: a deep navy sheet with a
     drafting grid, light ink, and the brand blue carrying every active state.
     Only the tokens below change between themes - nothing downstream hardcodes
     a colour, so the palette flips from one place.

     Exports are unaffected. DXF/PDF/PNG/JPG are drawn by dxf_builder +
     matplotlib on white, because a drawing in a documentation set has to
     print. */
  --color-bg: #0b1424;
  --color-surface: #101d31;   /* cards and panels, above the sheet */
  --color-bg-soft: #16243a;
  --color-surface-raised: #1b2c46;

  /* Input wells. On a dark theme a field has to read as recessed - cut INTO
     the panel - because there is no lighter shade left to push it forward
     with. So the field sits below the panel, not on it. */
  --color-field: #070e1a;
  --color-field-hover: #0b1524;
  --color-field-focus: #0d1b2f;
  --color-bg-cool: #1b2c46;

  --color-navy-950: #060d1a;
  --color-navy-900: #0d1c33;
  --color-navy-800: #142744;
  --color-navy-700: #1d3557;

  /* Brand blue from the identity: a confident royal blue, not the sky blue
     the app previously used. It carries "IQ", the leading driveway-profile
     line, and every active/selected state. */
  --color-accent-500: #1f6feb;
  --color-accent-600: #1a5fd0;
  --color-accent-700: #14489f;
  --color-accent-100: #12294d;
  /* Text-weight accent. accent-500/600 are fill colours - as ink on a dark
     tint they drop below 3:1, so anything that writes in accent uses this. */
  --color-accent-300: #7cb2ff;

  /* Named for the logo, which references them directly. */
  --brand-blue: #1f6feb;
  --brand-steel: #7e8da0;

  --color-success-600: #34d399;
  --color-success-100: #0f2e24;
  --color-warning-600: #fbbf24;
  --color-warning-100: #33270c;
  --color-danger-600: #f87171;
  --color-danger-100: #3b1418;

  --color-ink-900: #e2e8f0;
  --color-ink-700: #cbd5e1;
  --color-ink-500: #94a3b8;
  --color-ink-400: #7e93b5;
  --color-border: #1e2d45;
  --color-border-strong: #2b3d59;

  --font-sans: "Inter", "Segoe UI", Arial, sans-serif;
  /* Geometric display face for the brand and headings. Kept off the dense
     controls, where Inter stays more legible at 11-12px. */
  --font-display: "Montserrat", "Inter", "Segoe UI", Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;

  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.35), 0 1px 6px rgba(0, 0, 0, 0.3);
  --shadow-float: 0 10px 30px -8px rgba(0, 0, 0, 0.6);

  /* Fixed so the shell below can size itself to exactly the remaining
     viewport height and let the sidebar and workspace scroll independently. */
  --header-h: 64px;
}

html, body { height: 100%; }

/* Form controls do not inherit colour from the page in every browser, so the
   UA default (black) survived the theme flip and left unreadable fields. */
input, select, textarea, button {
  color: var(--color-ink-900);
  font-family: inherit;
}
input::placeholder, textarea::placeholder { color: var(--color-ink-400); opacity: 1; }
/* Native dropdown lists are painted by the OS, so the option rows need their
   own colours or they render dark-on-dark on Windows. */
select option { background: var(--color-surface); color: var(--color-ink-900); }
/* Date/number spinners and the like are drawn by the UA in its own scheme. */
:root { color-scheme: dark; }

* { box-sizing: border-box; }

body {
  margin: 0;
  background-color: var(--color-bg);
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(rgba(255, 255, 255, 0.025) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.025) 1px, transparent 1px);
  background-size: 96px 96px, 96px 96px, 24px 24px, 24px 24px;
  background-attachment: fixed;
  color: var(--color-ink-900);
  font-family: var(--font-sans);
  font-size: 14px;
}

.tech-figure {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* -----------------------------
   Header
----------------------------- */
.app-header {
  background: var(--color-bg);
  height: var(--header-h);
  padding: 0 18px;
  display: flex;
  align-items: center;
  gap: 12px;
  border-bottom: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  z-index: 40;
  flex: 0 0 auto;
}
.header-spacer { flex: 1; }

/* ---------- Profile menu (application-style dropdown in the header) ------- */
.pm-wrap { position: relative; flex: 0 0 auto; }
.pm-trigger {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  background: var(--color-surface);
  color: var(--color-ink-900);
  border: 1px solid var(--color-border-strong);
  border-radius: 10px;
  padding: 6px 12px;
  min-width: 210px;
  text-align: left;
}
.pm-trigger:hover { background: var(--color-bg-soft); }
.pm-trigger[aria-expanded="true"] {
  background: var(--color-bg-soft);
  border-color: var(--color-accent-500);
}
.pm-trigger-icon { font-size: 16px; line-height: 1; }
.pm-trigger-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.pm-trigger-label {
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-ink-400);
}
.pm-trigger-name {
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pm-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 60;
  display: flex;
  width: 620px;
  max-width: calc(100vw - 32px);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  box-shadow: var(--shadow-float);
  overflow: hidden;
}
.pm-panel[hidden] { display: none; }
.pm-pane { padding: 14px; }
.pm-pane-actions {
  width: 250px;
  flex: 0 0 auto;
  background: var(--color-bg-soft);
  border-right: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pm-pane-list { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pm-field { display: flex; flex-direction: column; gap: 4px; }
.pm-field label {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-ink-400);
}
.pm-field input { width: 100%; }
.pm-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  flex: 0 0 auto;
  background: var(--color-surface);
  color: var(--color-ink-700);
  border: 1px solid var(--color-border-strong);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 12px;
  text-align: left;
}
.pm-btn:hover { background: var(--color-bg-cool); }
.pm-btn-primary {
  background: var(--color-accent-500);
  border-color: var(--color-accent-600);
  color: #fff;
  font-weight: 700;
}
.pm-btn-primary:hover { background: var(--color-accent-600); }
.pm-divider { height: 1px; background: var(--color-border); margin: 2px 0; }
.pm-note {
  margin: 2px 0 0 0;
  font-size: 10px;
  line-height: 1.45;
  color: var(--color-ink-400);
}

.pm-list-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.pm-list-title {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-ink-400);
  flex: 0 0 auto;
}
.pm-list-head input { flex: 1; padding: 5px 8px; font-size: 11.5px; }
.pm-list { overflow-y: auto; max-height: 300px; min-height: 120px; }
.pm-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 8px;
  border-radius: 8px;
  cursor: pointer;
  border: 1px solid transparent;
}
.pm-item:hover { background: var(--color-bg-soft); border-color: var(--color-border); }
.pm-item.active { background: var(--color-accent-100); border-color: var(--color-accent-500); }
.pm-item-body { flex: 1; min-width: 0; }
.pm-item-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-ink-900);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pm-item-note {
  font-size: 10.5px;
  color: var(--color-ink-400);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pm-item-actions { display: none; gap: 2px; flex: 0 0 auto; }
.pm-item:hover .pm-item-actions, .pm-item.active .pm-item-actions { display: flex; }
.pm-item-actions button {
  flex: 0 0 auto;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 3px 6px;
  font-size: 11px;
  color: var(--color-ink-500);
}
.pm-item-actions button:hover { background: var(--color-surface); border-color: var(--color-border-strong); }
.pm-item-actions button.danger:hover { color: var(--color-danger-600); border-color: var(--color-danger-600); }
.pm-empty { padding: 18px 8px; text-align: center; font-size: 11.5px; color: var(--color-ink-400); }

/* ---- Brand lockup ---- */
/* The mark stands on the header rather than sitting in a navy tile - the tile
   treatment belongs to the app icon and favicon, where it needs the contrast. */
/* An <img>, not inline SVG, so the real logo file can replace it wholesale.
   object-fit keeps a supplied asset of any aspect ratio inside the box
   instead of stretching it. */
.app-header .logo-mark {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  object-fit: contain;
}

.brand-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.wordmark {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 700;
  line-height: 1;
  /* Wide tracking is the defining feature of the wordmark. */
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-ink-900);
  white-space: nowrap;
}
.wordmark .wm-iq { color: var(--color-accent-500); }
.tagline {
  font-family: var(--font-display);
  font-size: 7.5px;
  font-weight: 500;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--color-ink-400);
  white-space: nowrap;
}
.app-header .sub {
  color: var(--color-ink-500);
  font-size: 12.5px;
  padding-left: 14px;
  margin-left: 2px;
  border-left: 1px solid var(--color-border);
}
.app-header .user-row {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
}
.app-header .user-avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid var(--color-border);
}
.app-header .user-email {
  color: var(--color-ink-500);
  font-size: 12px;
}
.app-header .logout-link {
  color: var(--color-ink-900);
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  padding: 6px 14px;
}
.app-header .logout-link:hover { background: var(--color-bg-soft); }

/* -----------------------------
   Auth pages (dormant for now)
----------------------------- */
.auth-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: var(--color-bg-soft);
}
.auth-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
  padding: 36px 40px;
  max-width: 380px;
  width: 100%;
  text-align: center;
}
.auth-card h1 {
  margin: 0 0 4px 0;
  font-size: 22px;
  font-weight: 800;
  color: var(--color-ink-900);
}
.auth-sub {
  color: var(--color-ink-500);
  font-size: 13px;
  margin: 0 0 20px 0;
}
.auth-blurb {
  font-size: 13px;
  color: var(--color-ink-700);
  margin: 0 0 24px 0;
  line-height: 1.5;
}
.google-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  background: var(--color-surface);
  color: var(--color-ink-700);
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.google-btn:hover { background: var(--color-bg-soft); }

/* -----------------------------
   Layout - dashboard shell
   Sidebar of parameter groups on the left, workspace on the right. The
   drawing is the product, so it gets the space; parameters are grouped into
   one scrollable accordion instead of six equally-weighted cards competing
   across a grid, which pushed the schematic below the fold.
----------------------------- */
.app-shell {
  display: flex;
  align-items: stretch;
  /* Fill the viewport under the sticky header so the workspace can own its
     own scrolling and the sidebar can stay put. */
  height: calc(100vh - var(--header-h));
  min-height: 0;
}

.sidebar {
  /* Driven by a custom property so the drag handle has one number to set and
     both the width and the flex basis follow it. */
  width: var(--sidebar-w, 344px);
  flex: 0 0 var(--sidebar-w, 344px);
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--color-bg-soft);
  border-right: 1px solid var(--color-border);
}
.sidebar.is-collapsed { display: none; }

.sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 12px 14px 12px 18px;
  border-bottom: 1px solid var(--color-border);
  flex: 0 0 auto;
}
.sidebar-title {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-400);
}
.sidebar-collapse {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 7px;
  color: var(--color-ink-500);
}
.sidebar-collapse svg { width: 15px; height: 15px; }
.sidebar-collapse:hover { background: var(--color-surface); border-color: var(--color-border-strong); }

.sidebar-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 8px;
}

/* Tab shown once the sidebar is hidden, to bring it back. */
.sidebar-reopen {
  /* Fixed, not absolute: the workspace owns the scrolling, so there is no
     positioned ancestor to hang this off reliably. */
  position: fixed;
  left: 0;
  top: calc(var(--header-h) + 14px);
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  width: auto;
  padding: 8px 12px 8px 9px;
  background: var(--color-surface);
  color: var(--color-ink-700);
  border: 1px solid var(--color-border-strong);
  border-left: none;
  border-radius: 0 10px 10px 0;
  font-size: 11.5px;
  font-weight: 600;
  box-shadow: var(--shadow-card);
}
.sidebar-reopen svg { width: 14px; height: 14px; }
.sidebar-reopen:hover { background: var(--color-bg-soft); }
.sidebar-reopen[hidden] { display: none; }

/* ---- accordion sections ---- */
.side-section {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  margin-bottom: 8px;
  overflow: hidden;
}
.side-section:last-child { margin-bottom: 0; }
.ss-head {
  display: flex;
  align-items: center;
  gap: 4px;
  padding-right: 10px;
}
.ss-toggle {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 11px 4px 11px 12px;
  color: var(--color-ink-900);
  font-size: 12.5px;
  font-weight: 700;
  text-align: left;
}
.ss-toggle:hover { background: transparent; color: var(--color-accent-300); }
.ss-icon {
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
  color: var(--color-ink-400);
}
.ss-toggle:hover .ss-icon { color: var(--color-accent-500); }
.ss-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ss-chev {
  width: 13px;
  height: 13px;
  flex: 0 0 auto;
  color: var(--color-ink-400);
  transition: transform 0.16s ease;
}
.side-section.is-folded .ss-chev { transform: rotate(-90deg); }
.ss-extra { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.ss-body {
  padding: 4px 14px 14px 14px;
  border-top: 1px solid var(--color-border);
}
.side-section.is-folded .ss-body { display: none; }

/* ---- workspace ---- */
.workspace {
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  padding: 16px 18px 22px 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: var(--color-bg-cool);
}

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 16px 18px;
}
.card h2 {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.005em;
  margin: 0 0 12px 0;
  color: var(--color-ink-900);
  padding-bottom: 10px;
  border-bottom: 1px solid var(--color-border);
}

.field-row {
  display: grid;
  grid-template-columns: 130px 1fr 30px;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}
.field-row label {
  color: var(--color-ink-500);
  font-size: 12.5px;
  font-weight: 500;
}
.field-row .unit {
  color: var(--color-ink-400);
  font-size: 12px;
}
.checkbox-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0;
  color: var(--color-ink-700);
  font-size: 12.5px;
}

input[type="text"], input[type="number"], select {
  background: var(--color-field);
  color: var(--color-ink-900);
  border: 1px solid var(--color-border-strong);
  border-radius: 8px;
  padding: 6px 9px;
  font-size: 12.5px;
  width: 100%;
  /* Inner shadow does the recessing. Without it the field is just a darker
     rectangle; with it the edge catches, and it reads as a well. */
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.45);
  transition: background-color 0.15s, border-color 0.15s, box-shadow 0.15s;
}

input[type="text"]:hover:not(:disabled),
input[type="number"]:hover:not(:disabled),
select:hover:not(:disabled) {
  background: var(--color-field-hover);
  border-color: #3d5578;
}

/* Focus has to be unmistakable: the well lightens, the border goes full
   accent, and a bright ring sits outside it. The old ring used the dark
   accent tint, which on a navy panel was almost invisible. */
input[type="text"]:focus, input[type="number"]:focus, select:focus {
  outline: none;
  background: var(--color-field-focus);
  border-color: var(--color-accent-500);
  box-shadow:
    inset 0 1px 2px rgba(0, 0, 0, 0.3),
    0 0 0 3px rgba(95, 160, 255, 0.28);
}

/* Keyboard users get the same treatment plus the UA outline, which some
   browsers suppress once box-shadow is set. */
input[type="text"]:focus-visible,
input[type="number"]:focus-visible,
select:focus-visible {
  outline: 2px solid transparent;
  outline-offset: 2px;
}

input:disabled, select:disabled {
  opacity: 0.45;
  background: var(--color-surface);
  box-shadow: none;
  cursor: not-allowed;
}

/* Navy on navy made the tick invisible. */
input[type="checkbox"] { accent-color: var(--color-accent-500); }

.zone-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 4px;
}
.zone-table th {
  font-size: 10px;
  color: var(--color-ink-400);
  text-align: left;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 2px 4px 6px;
}
.zone-table td {
  padding: 2px 4px;
}
.zone-table input, .zone-table select {
  font-size: 11px;
  padding: 4px 5px;
}
.zone-table td:nth-child(1) { width: 38%; }
.zone-table td:nth-child(2) { width: 22%; }
.zone-table td:nth-child(3) { width: 18%; }
.zone-table td:nth-child(4) { width: 22%; }

.button-row {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}
button {
  background: var(--color-navy-900);
  color: #fff;
  border: 1px solid var(--color-navy-900);
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  flex: 1;
  transition: background-color 0.15s, opacity 0.15s;
}
button:hover { background: var(--color-navy-800); }
button:disabled { opacity: 0.4; cursor: default; }

/* Secondary/outline style for the small utility buttons (Reset, etc.) */
.button-row button {
  background: var(--color-surface);
  color: var(--color-ink-700);
  border: 1px solid var(--color-border-strong);
}
.button-row button:hover:not(:disabled) { background: var(--color-bg-soft); }

/* The primary call-to-action of the simulation card. It needs its own rule
   rather than the shared `.primary` class: `.button-row button` above resets
   every button in a row to the white outline style, so a bare `.primary`
   never took effect and the control read as just another utility button. */
.button-row button.run-sim-btn {
  background: linear-gradient(180deg, var(--color-accent-500), var(--color-accent-600));
  color: #fff;
  border: 1px solid var(--color-accent-600);
  padding: 11px 18px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.01em;
  box-shadow: 0 2px 6px -1px rgba(2, 132, 199, 0.45);
}
.button-row button.run-sim-btn:hover:not(:disabled) {
  background: linear-gradient(180deg, var(--color-accent-600), #0369a1);
  box-shadow: 0 4px 12px -2px rgba(2, 132, 199, 0.55);
}
.button-row button.run-sim-btn:active:not(:disabled) {
  transform: translateY(1px);
  box-shadow: 0 1px 3px -1px rgba(2, 132, 199, 0.5);
}
.button-row button.run-sim-btn:disabled {
  background: var(--color-bg-cool);
  color: var(--color-ink-400);
  border-color: var(--color-border-strong);
  box-shadow: none;
  opacity: 1; /* the muted palette already reads as disabled */
}

/* The menu is absolutely positioned against this, so it must establish a
   containing block. Without it `top: 100%` resolves against whatever
   positioned ancestor happens to be up the tree - which put the export menu
   at the bottom of the whole schematic panel instead of under its button. */
.dropdown { position: relative; }

.dropdown-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 6px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  min-width: 240px;
  overflow: hidden;
  z-index: 20;
  box-shadow: var(--shadow-float);
}
/* The export menu now hangs below its button in the schematic toolbar, and
   is right-aligned so it can't overflow the panel's right edge. (The former
   drop-UP variant existed only because the button sat at the bottom of the
   card; it has no remaining users.) */
#export_menu {
  left: auto;
  right: 0;
}
.dropdown-menu.open { display: block; }
.dropdown-menu button {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  border-radius: 0;
  color: var(--color-ink-700);
  padding: 10px 14px;
  font-weight: 500;
  font-size: 12.5px;
}
.dropdown-menu button:hover { background: var(--color-bg-soft); }
.dropdown-menu button.danger { color: var(--color-danger-600); }
.dropdown-menu button.danger:hover { background: var(--color-danger-100); }
.dropdown-divider {
  border-top: 1px solid var(--color-border);
  margin: 4px 0;
}

.card p {
  margin: 3px 0;
  font-size: 12.5px;
}

.card hr {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: 10px 0;
}

.card-header-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--color-border);
}
.card-header-row h2 { margin: 0; padding: 0; border: none; }
.display-badge {
  background: var(--color-accent-100);
  color: var(--color-accent-300);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 3px 8px;
  border-radius: 999px;
}
/* Overlay toggles are grouped by what they draw (numbers vs linework), with
   a quiet caption over each set so the card scans as two short lists rather
   than one undifferentiated block of six checkboxes. */
.ov-group + .ov-group { margin-top: 12px; }
.ov-group-title {
  display: block;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-ink-400);
  margin-bottom: 6px;
}
.layer-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}
/* For a toggle that should occupy its own full-width row. */
.layer-cell.wide { grid-column: 1 / -1; }

/* ---- Auto Profile Designer (self-contained; safe to delete as a block) ---- */
.auto-hint {
  margin: 0 0 12px 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--color-ink-500);
}
.auto-result {
  margin-top: 12px;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--color-bg-soft);
  border: 1px solid var(--color-border);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--color-ink-700);
}
.auto-result.error {
  background: var(--color-danger-100);
  border-color: var(--color-danger-600);
  color: var(--color-danger-600);
}
.auto-result ul { margin: 6px 0 0 0; padding-left: 16px; }
.auto-result li { margin-bottom: 3px; }
.auto-zones {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 8px;
}
.auto-zone-pill {
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  padding: 3px 10px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  color: var(--color-ink-900);
}
.layer-cell {
  background: var(--color-bg-soft);
  border: 1px solid var(--color-border);
  padding: 6px 8px;
  border-radius: 8px;
  font-size: 11.5px;
  color: var(--color-ink-700);
  display: flex;
  align-items: center;
  gap: 6px;
}
.style-row {
  background: var(--color-bg-soft);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  padding: 8px 10px;
  margin-top: 8px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 10px;
  color: var(--color-ink-500);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.style-row select { width: auto; flex: 1; }

.output-bar {
  /* Fills the workspace column; the column supplies the padding. */
  flex: 0 0 auto;
}
.output-bar-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
}
.output-bar-row p {
  margin: 0;
  padding-right: 20px;
  border-right: 1px solid var(--color-border);
  white-space: nowrap;
  color: var(--color-ink-700);
}
.output-bar-row p:last-child {
  border-right: none;
  padding-right: 0;
}

/* The two status flags read as sentences, not as columns of figures, and they
   are long enough that flex dropped them onto a second line at whatever x the
   flow happened to reach - the rate-of-change flag landed under no column at
   all. Each now takes a full-width line so both start hard against the left
   edge, in line with the first value above. */
.output-bar-row .pack-status,
.output-bar-row .out-flag {
  flex: 0 0 100%;
  border-right: none;
  padding-right: 0;
  white-space: normal;
}

.schematic-wrap {
  /* Sized to the drawing rather than stretched to fill the column. Taking the
     slack left the card hundreds of pixels taller than its contents, which is
     the empty band that used to sit under the profile. The floor keeps an
     empty or errored state from collapsing to a sliver. */
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 300px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
  position: relative;
}
/* Toolbar row: title on the left, the panel's own actions on the right. In
   normal flow above the canvas, so it can never sit on top of the drawing
   the way the old absolutely-positioned command cluster did. */
.schematic-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--color-border);
}
.schematic-banner {
  font-size: 13px;
  font-weight: 700;
  color: var(--color-ink-900);
  letter-spacing: -0.005em;
}
.schematic-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}
/* The global `button { flex: 1 }` would stretch these to fill the row. */
.schematic-actions button { flex: 0 0 auto; }
.schematic-stage {
  position: relative;
}
.schematic-canvas {
  padding: 0 16px 16px 16px;
  /* The drawing's ground, which used to be a rect inside the SVG. It moved
     out here so the vehicle can be stacked between it and the linework. */
  background: var(--color-bg);
}
/* Stacking, deliberately:
      ground (this div's background)
        -> grid      z 0
        -> vehicle   z 1
        -> drawing   z 2
   The car therefore runs over the paper and behind the profile, the
   dimensions and every label. */
.schematic-canvas svg { position: relative; z-index: 3; }
.schematic-grid {
  position: absolute; inset: 0; z-index: 0;
  padding: 0 16px 16px 16px; pointer-events: none;
}
.schematic-grid svg { width: 100%; height: auto; display: block; border-radius: 10px; }
.schematic-canvas svg {
  width: 100%;
  height: auto;
  display: block;
  border-radius: 10px;
}

/* Car overlay: identical padding to .schematic-canvas so its own SVG (same
   viewBox dimensions as the schematic's) lines up pixel-for-pixel with the
   profile underneath, regardless of container width. */
.sim-overlay {
  position: absolute;
  inset: 0;
  padding: 0 16px 16px 16px;
  pointer-events: none;
  z-index: 1;            /* under .schematic-canvas svg, over the ground */
}
.sim-overlay svg {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
}

.veh-search-results {
  max-height: 160px;
  overflow-y: auto;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  margin-top: -6px;
  margin-bottom: 10px;
}
.veh-search-results button {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
  padding: 7px 10px;
  font-size: 12px;
  color: var(--color-ink-700);
  cursor: pointer;
}
.veh-search-results button:last-child { border-bottom: none; }
.veh-search-results button:hover { background: var(--color-bg-soft); }
.veh-selected {
  font-size: 12.5px;
  color: var(--color-ink-500);
  padding: 8px 10px;
  background: var(--color-bg-soft);
  border-radius: 8px;
  margin-bottom: 10px;
}
.veh-selected.has-vehicle {
  color: var(--color-ink-900);
  font-weight: 600;
  background: var(--color-accent-100);
}

.sim-panel {
  flex: 0 0 auto;
  border-left: 3px solid var(--color-accent-500);
  animation: sim-panel-in 0.25s ease-out;
}
@keyframes sim-panel-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}
.sim-panel-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.sim-panel-title {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--color-ink-900);
  letter-spacing: -0.005em;
}
.sim-close {
  margin-left: auto;
  border: none;
  background: transparent;
  color: var(--color-ink-400);
  font-size: 13px;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 6px;
}
.sim-close:hover { background: var(--color-bg-soft); color: var(--color-ink-700); }
.sim-result-badge {
  font-size: 11px;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 999px;
  letter-spacing: 0.01em;
}
.sim-result-badge.pass { background: #dcfce7; color: #16a34a; border: 1px solid #16a34a; }
.sim-result-badge.fail { background: var(--color-danger-100); color: #dc2626; border: 1px solid #dc2626; }
.sim-result-badge.tight { background: var(--color-warning-100); color: #d97706; border: 1px solid #d97706; }
.sim-readout {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
  font-size: 12px;
  color: var(--color-ink-700);
  margin-bottom: 10px;
}
.sim-readout b { color: var(--color-ink-900); }
.sim-readout .sim-readout-danger { color: var(--color-danger-600); font-weight: 700; }
.schematic-actions button.primary,
.schematic-actions button.secondary {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  padding: 8px 16px;
}
.schematic-actions button svg { width: 14px; height: 14px; flex: 0 0 auto; }
.schematic-actions button.primary {
  background: var(--color-navy-900);
  border-color: var(--color-navy-900);
  color: #fff;
  padding: 8px 18px;
}
.schematic-actions button.primary:hover { background: var(--color-navy-800); }
.schematic-actions button.secondary {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
  color: var(--color-ink-700);
}
.schematic-actions button.secondary:hover { background: var(--color-bg-soft); }

/* Export menu: two-line entries so the format name stays scannable while the
   detail (and the live scale) sits underneath. */
#export_menu { min-width: 264px; padding: 6px; }
#export_menu .menu-group {
  padding: 8px 10px 4px 10px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-ink-400);
}
#export_menu button {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  padding: 7px 10px;
  border-radius: 8px;
}
#export_menu button:hover { background: var(--color-bg-soft); }
#export_menu .fmt-name {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--color-ink-900);
}
#export_menu .fmt-note { font-size: 10.5px; color: var(--color-ink-400); }
#export_menu .fmt-scale { font-family: var(--font-mono); font-weight: 600; }

/* Scale picker, inside the menu and immediately above the formats it drives. */
.export-scale-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 0 4px 4px 4px;
  padding: 7px 8px;
  background: var(--color-bg-soft);
  border: 1px solid var(--color-border);
  border-radius: 8px;
}
.export-scale-row label {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--color-ink-700);
}
.export-scale-row select {
  width: auto;
  min-width: 92px;
  padding: 5px 8px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
}

/* Anchored bottom-right, not top-right: the profile menu occupies the top
   right corner, and a "Loaded profile…" toast fires at exactly the moment
   that menu is open, so it landed on top of the thing the user was using.
   Newest toast sits nearest the corner and older ones stack upward. */
#toast {
  position: fixed;
  bottom: 16px;
  right: 16px;
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-end;
  pointer-events: none;
}
.toast-msg { pointer-events: auto; }
.toast-msg {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent-500);
  padding: 10px 14px;
  border-radius: 10px;
  font-size: 12.5px;
  color: var(--color-ink-700);
  max-width: 340px;
  box-shadow: var(--shadow-float);
}
.toast-msg.error { border-left-color: var(--color-danger-600); }

/* Sidebar narrows before it ever stacks: a two-column workspace is the
   point of the layout, so it is held onto down to tablet width rather than
   collapsing the moment the window is less than full desktop. */
@media (max-width: 1240px) {
  .sidebar { width: 300px; flex-basis: 300px; }
  .workspace { padding: 14px; }
}
@media (max-width: 880px) {
  /* Below tablet the split stops being useful - flow the panels instead and
     let the page scroll as one document. */
  .app-shell { flex-direction: column; height: auto; }
  .sidebar { width: auto; flex: 0 0 auto; border-right: none; border-bottom: 1px solid var(--color-border); }
  .sidebar-scroll { overflow-y: visible; }
  .workspace { overflow-y: visible; }
  .sidebar-reopen {
    position: static; width: 100%; justify-content: center;
    border-radius: 0; border-left: 1px solid var(--color-border-strong);
  }
  .pm-panel { flex-direction: column; width: min(420px, calc(100vw - 24px)); }
  .pm-pane-actions { width: auto; border-right: none; border-bottom: 1px solid var(--color-border); }
}
@media (max-width: 700px) {
  /* Stack the schematic toolbar so the actions don't squeeze the title. */
  .schematic-header { flex-direction: column; align-items: stretch; gap: 10px; }
  .schematic-actions { justify-content: flex-end; }
  .app-header .sub { display: none; }
}

/* ================= Export preview ================= */
/* Shows the drawing as the export pipeline renders it, with the zone dimension
   band draggable so its height is settled before any file is written. */
.ep-backdrop {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(6, 16, 31, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Tight margin - the drawing is the point, so give it the screen. */
  padding: 12px;
}
.ep-backdrop[hidden] { display: none; }

.ep-dialog {
  background: var(--color-bg);
  border-radius: 12px;
  box-shadow: var(--shadow-float);
  width: min(1680px, 100%);
  max-height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Drawing on the left, settings on the right - the drawing is the thing being
   judged, so it gets the space and the controls get a fixed column. */
.ep-body {
  position: relative;   /* anchors the zoom control, which must not scroll away */
  display: flex;
  flex: 1;
  min-height: 0;
}

.ep-head {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 52px 16px 20px;   /* room for the corner close button */
  border-bottom: 1px solid var(--color-border);
}
.ep-head h2 { margin: 0; font-size: 16px; color: var(--color-ink-900); }
.ep-sub { margin: 4px 0 0; font-size: 12px; color: var(--color-ink-500); }
/* Pinned to the very corner and square-cornered, the way a window close
   button sits - not floated inside the header's padding. */
.ep-close {
  position: absolute;
  top: 0;
  right: 0;
  width: 46px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: transparent;
  font-size: 20px;
  line-height: 1;
  color: var(--color-ink-500);
  cursor: pointer;
  border-radius: 0;
  border-top-right-radius: 12px;   /* follow the dialog's own corner */
}
.ep-close:hover { background: var(--color-danger-600); color: #fff; }

.ep-stage {
  position: relative;
  flex: 1;
  min-width: 0;
  cursor: grab;
  min-height: 0;
  overflow: auto;
  background: var(--color-bg-cool);
  padding: 20px;
  display: flex;
  align-items: flex-start;
  /* Plain `center` makes the overflowing half of a zoomed drawing
     unreachable - scroll cannot go negative, so the left side was clipped.
     `safe center` falls back to start alignment once it overflows. */
  justify-content: center;
  justify-content: safe center;
}

/* The handle is positioned as a percentage of this box, so it has to wrap the
   image exactly - no padding, and shrink-to-fit the rendered page. */
.ep-canvas {
  position: relative;
  display: inline-block;
  line-height: 0;
  background: var(--color-surface);
  box-shadow: var(--shadow-card);
  /* Width is set explicitly by the zoom control, so no max-width cap here -
     zooming past the stage is exactly when the stage should start scrolling. */
  flex: 0 0 auto;
}
.ep-canvas img { display: block; width: 100%; height: auto; }
/* The schematic SVG is authored at width/height 100%, so inside the
   shrink-to-fit canvas it would collapse to a thumbnail. Give it a width to
   resolve against and let the viewBox drive the height. */
.ep-svg-holder { background: var(--color-surface); width: 100%; }
.ep-svg-holder svg { display: block; width: 100%; height: auto; }
/* An author `display` declaration outranks the user-agent's [hidden] rule, so
   the two renderers would both stay on screen without this. */
.ep-canvas [hidden] { display: none; }

/* Movable text is not marked by a separate grip - the text itself is the
   target. Each region sits over the labels it moves, stays invisible until
   pointed at, then washes them in a highlight so it is obvious what will move
   and by how much. */
:root {
  --ep-live: #1d4ed8;                       /* "this is movable" */
  --ep-live-wash: rgba(29, 78, 216, 0.13);
  --ep-live-wash-strong: rgba(29, 78, 216, 0.22);
}

.ep-handle {
  position: absolute;
  touch-action: none;
  cursor: move;
  border: 1px solid transparent;
  border-radius: 2px;
  transition: background 0.1s, border-color 0.1s;
}
.ep-handle[hidden] { display: none; }
.ep-handle:focus-visible { outline: none; }

.ep-handle:hover,
.ep-handle:focus-visible {
  background: var(--ep-live-wash);
  border-color: var(--ep-live);
}
.ep-handle.is-dragging {
  background: var(--ep-live-wash-strong);
  border-color: var(--ep-live);
  border-style: dashed;
}

/* The band spans the drawing and is dragged straight up or down. */
.ep-handle.is-band { cursor: ns-resize; }

.ep-handle-label {
  position: absolute;
  left: 0;
  top: -17px;
  font: 500 9px/1.6 var(--font-mono);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: #fff;
  background: var(--ep-live);
  border-radius: 2px;
  padding: 0 5px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.1s;
}
.ep-handle:hover .ep-handle-label,
.ep-handle:focus-visible .ep-handle-label,
.ep-handle.is-dragging .ep-handle-label { opacity: 1; }

/* Zoom control, floating over the drawing rather than taking panel space. */
.ep-zoom {
  position: absolute;
  top: 12px;
  right: 300px;   /* clear of the settings panel */
  display: flex;
  align-items: stretch;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: 6px;
  overflow: hidden;
  box-shadow: var(--shadow-card);
  z-index: 2;
}
.ep-zoom button {
  border: 0;
  background: var(--color-surface);
  color: var(--color-ink-700);
  font: 600 13px/1 var(--font-sans);
  padding: 5px 9px;
  cursor: pointer;
}
.ep-zoom button:hover { background: var(--color-bg-soft); color: var(--color-ink-900); }
.ep-zoom .ep-zoom-val {
  font: 500 10px/1 var(--font-mono);
  min-width: 44px;
  border-left: 1px solid var(--color-border);
  border-right: 1px solid var(--color-border);
}

.ep-stage.is-panning { cursor: grabbing; }
/* While panning, the drawing must not intercept the drag or start a text
   move, and the browser must not begin an image drag. */
.ep-stage.is-panning .ep-handle,
.ep-stage.is-panning img { pointer-events: none; }
.ep-canvas img { user-select: none; -webkit-user-drag: none; }

.ep-spinner {
  position: absolute;
  top: 28px;
  right: 28px;
  width: 18px;
  height: 18px;
}
.ep-spinner[hidden] { display: none; }
.ep-spinner span {
  display: block;
  width: 100%;
  height: 100%;
  border: 2px solid var(--color-border-strong);
  border-top-color: var(--color-accent-600);
  border-radius: 50%;
  animation: ep-spin 0.7s linear infinite;
}
@keyframes ep-spin { to { transform: rotate(360deg); } }

.ep-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  padding: 14px 20px;
  border-top: 1px solid var(--color-border);
}
.ep-actions { display: flex; align-items: center; gap: 10px; }
.ep-foot label {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-ink-700);
  white-space: nowrap;
}
.ep-foot-note {
  font-size: 12px;
  color: var(--color-ink-500);
  flex: 1;
  min-width: 0;
}

/* ---- Settings panel ---- */
.ep-panel {
  width: 288px;
  flex: 0 0 288px;
  border-left: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 12px;
  gap: 10px;
}
/* The panes are the only part that should absorb spare height; the tab strip
   and the reset button are flex children too and would stretch without this. */
.ep-panel > .ep-tabs,
.ep-panel > .ep-btn { flex: 0 0 auto; }

.ep-tabs {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 2px;
  background: var(--color-bg-soft);
  border-radius: 8px;
  padding: 3px;
}
.ep-tab {
  border: 0;
  background: transparent;
  border-radius: 6px;
  padding: 6px 4px;
  font: 600 11px/1.4 var(--font-sans);
  color: var(--color-ink-500);
  cursor: pointer;
}
.ep-tab:hover { color: var(--color-ink-900); }
.ep-tab.is-active {
  background: var(--color-bg);
  color: var(--color-ink-900);
  box-shadow: var(--shadow-card);
}
/* Vertical scrolling only - a range input's intrinsic width overshoots the
   column by a few pixels and would otherwise raise a horizontal scrollbar. */
.ep-tabpanes { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; }
.ep-pane { display: none; }
.ep-pane.is-active { display: block; }

.ep-field { display: block; margin-bottom: 12px; }
.ep-field > span {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font: 600 11px/1.6 var(--font-sans);
  color: var(--color-ink-700);
  margin-bottom: 4px;
}
.ep-field > span output { font: 600 11px/1 var(--font-mono); color: var(--color-ink-900); }
.ep-field select, .ep-field input[type="text"] {
  width: 100%;
  border: 1px solid var(--color-border-strong);
  border-radius: 6px;
  padding: 6px 8px;
  font-size: 12px;
  background: var(--color-bg);
  color: var(--color-ink-900);
}
.ep-field input[type="range"] { width: 100%; }

.ep-group-head {
  margin: 14px 0 6px;
  font: 700 10px/1.6 var(--font-sans);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-ink-400);
}
.ep-hint { margin: 0 0 10px; font-size: 11px; line-height: 1.5; color: var(--color-ink-500); }

.ep-check {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 2px;
  font-size: 12px;
  color: var(--color-ink-700);
  cursor: pointer;
}
.ep-check:hover { color: var(--color-ink-900); }

.ep-pos-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 4px 8px;
  padding: 5px 0;
  border-bottom: 1px solid var(--color-border);
}
.ep-pos-name { font-size: 12px; color: var(--color-ink-700); }
.ep-pos-nudge { display: flex; gap: 2px; }
.ep-pos-nudge button {
  border: 1px solid var(--color-border-strong);
  background: var(--color-bg);
  border-radius: 4px;
  width: 20px;
  height: 20px;
  font-size: 10px;
  line-height: 1;
  color: var(--color-ink-700);
  cursor: pointer;
  padding: 0;
}
.ep-pos-nudge button:hover { background: var(--color-bg-cool); border-color: var(--ep-grip); }
.ep-pos-nudge .ep-pos-reset { width: auto; padding: 0 5px; font-size: 9px; }
.ep-pos-val {
  grid-column: 1 / -1;
  font: 500 10px/1 var(--font-mono);
  color: var(--color-ink-400);
}
.ep-pos-val.is-moved { color: var(--ep-grip-active); font-weight: 600; }

/* Collapsible group - keeps long lists from dominating the panel. */
.ep-details { margin: 10px 0; border-top: 1px solid var(--color-border); }
.ep-details > summary {
  cursor: pointer;
  list-style: none;
  padding: 8px 0 6px;
  font: 700 10px/1.6 var(--font-sans);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-ink-500);
  display: flex;
  align-items: center;
  gap: 6px;
}
.ep-details > summary::-webkit-details-marker { display: none; }
.ep-details > summary::before {
  content: "B8";
  font-size: 9px;
  transition: transform 0.12s;
}
.ep-details[open] > summary::before { transform: rotate(90deg); }
.ep-details > summary:hover { color: var(--color-ink-900); }
.ep-count {
  margin-left: auto;
  font: 500 9px/1 var(--font-mono);
  color: var(--color-ink-400);
  letter-spacing: 0;
}

.ep-preset-actions { display: flex; gap: 6px; margin-bottom: 12px; }
.ep-btn {
  border: 1px solid var(--color-border-strong);
  background: var(--color-bg);
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--color-ink-700);
  cursor: pointer;
}
.ep-btn:hover { background: var(--color-bg-soft); }
.ep-btn.wide { width: 100%; }
.ep-btn.primary {
  background: var(--color-navy-900);
  border-color: var(--color-navy-900);
  color: #fff;
}
.ep-btn.primary:hover { background: var(--color-navy-800); }
.ep-btn.danger { color: var(--color-danger-600); }
.ep-btn.danger:hover { background: var(--color-danger-100); }

/* Sits above the format list it acts on, separated so it doesn't read as one
   of the download buttons. */
.export-preview-item { border-bottom: 1px solid var(--color-border); }

@media (max-width: 900px) {
  /* Stack the panel under the drawing rather than squeezing both. */
  .ep-body { flex-direction: column; }
  .ep-panel { width: auto; flex: 0 0 auto; border-left: none; border-top: 1px solid var(--color-border); }
  .ep-tabpanes { max-height: 240px; }
  .ep-foot { flex-direction: column; align-items: stretch; }
}

/* Rate-of-change result in the Calculation Output. Colour-coded the way the
   badge on the drawing was, so pass/fail still reads at a glance. */
.out-flag { font-weight: 600; }
.out-flag.is-ok { color: var(--color-success-600); }
.out-flag.is-fail { color: var(--color-danger-600); }


/* ================= Brand typography ================= */
/* The display face carries titles and the small uppercase group labels. Form
   controls and readouts stay on Inter, which holds up better at 11-12px in a
   screen this dense. */
.schematic-header h2,
.output-bar h2,
.sim-panel h2,
.ep-head h2 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: 0.02em;
}
.sidebar-title,
.ss-title,
.ov-group-title,
.pm-list-title,
.pm-trigger-label,
.style-row > span,
.ep-group-head,
.ep-details > summary {
  font-family: var(--font-display);
  font-weight: 600;
}
.sidebar-title,
.ov-group-title,
.pm-list-title,
.pm-trigger-label {
  letter-spacing: 0.1em;
}
.ss-title { letter-spacing: 0.01em; }
.btn.primary,
.pm-btn-primary,
.ep-btn.primary {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* ---- Vehicle data provenance note ---- */
/* Collapsed by default: it is reference material, not something needed on
   every run, but it must be one click away rather than buried in a policy page. */
.data-note { margin-top: 12px; border-top: 1px solid var(--color-border); }
.data-note > summary {
  cursor: pointer;
  list-style: none;
  padding: 9px 0 7px;
  font: 600 11px/1.5 var(--font-display);
  color: var(--color-accent-300);
  display: flex;
  align-items: center;
  gap: 6px;
}
.data-note > summary::-webkit-details-marker { display: none; }
.data-note > summary::before { content: "\24D8"; font-size: 12px; }
.data-note > summary:hover { color: var(--color-ink-900); }
.data-note p {
  margin: 0 0 8px;
  font-size: 11px;
  line-height: 1.55;
  color: var(--color-ink-500);
}
.data-note strong { color: var(--color-ink-700); }
.data-note .data-note-caveat {
  padding: 7px 9px;
  background: var(--color-warning-100);
  border-radius: 6px;
  color: var(--color-warning-600);
}

/* ---- Occupant load ----------------------------------------------------- */
/* The readout is deliberately as prominent as the figures it explains. This
   control makes a driveway look worse than the published specs suggest, so
   the working behind it has to be visible without a second click. */
.occ-block {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--color-border);
}
.occ-check {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: 12px;
  color: var(--color-ink-700);
}
.occ-check input { accent-color: var(--color-accent-500); cursor: pointer; }
.occ-check:hover { color: var(--color-ink-900); }
/* .field-row sets its own display, which beats the `hidden` attribute's
   UA-stylesheet `display:none`. Without this the dropdown shows even when the
   box is unticked. */
.occ-row { margin-top: 8px; }
.occ-row[hidden], .occ-readout[hidden] { display: none; }
.occ-readout {
  margin-top: 9px;
  padding: 9px 10px;
  border: 1px solid var(--color-border);
  border-left: 2px solid var(--color-accent-500);
  border-radius: 6px;
  background: var(--color-navy-950);
}
.occ-readout.is-warn {
  border-left-color: var(--color-warning-600);
  background: var(--color-warning-100);
}
.occ-figs {
  display: flex;
  gap: 14px;
  margin-bottom: 7px;
  font: 11px/1 var(--font-mono);
  color: var(--color-ink-500);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.occ-figs b {
  font-size: 14px;
  letter-spacing: 0;
  color: var(--color-accent-300);
}
.occ-readout.is-warn .occ-figs b { color: var(--color-warning-600); }
.occ-readout p {
  margin: 0 0 6px;
  font-size: 11px;
  line-height: 1.55;
  color: var(--color-ink-500);
}
.occ-readout p:last-child { margin-bottom: 0; }

/* ---- Selected vehicle: name plus what its figures actually represent ---- */
.veh-selected .veh-name { display: block; font-weight: 600; }
.veh-selected .veh-basis {
  display: block;
  margin-top: 3px;
  font-size: 10.5px;
  line-height: 1.4;
  color: var(--color-ink-400);
}
/* Generation-specific data is the stronger claim, so it is marked as such. */
.veh-selected .veh-basis.is-generation { color: var(--color-success-600); font-weight: 500; }


/* ==========================================================================
   Technical-instrument treatment
   ========================================================================== */

/* Figures must not wobble as their digits change - that is the single thing
   that separates an instrument from a web page. Applied to every surface that
   shows a computed number. */
.tech-figure,
.output-bar,
.sim-panel,
.zone-table,
input[type="number"],
input[type="text"],
.ob-v {
  font-variant-numeric: tabular-nums;
}

/* Numeric entry in mono, so a column of RLs lines up digit for digit. */
input[type="number"],
#boundary_rl, #driveway_length, #tolerance, #rebate,
.zone-table input {
  font-family: var(--font-mono);
  letter-spacing: -0.01em;
}

/* ---- Calculation Output as an instrument strip ---- */
.output-bar-row { gap: 0; }
.output-bar-row > p {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 0;
  padding: 2px 16px;
  border-left: 1px solid var(--color-border);
}
.output-bar-row > p:first-child { border-left: none; padding-left: 0; }
.ob-k {
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-ink-400);
  white-space: nowrap;
}
.ob-v {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--color-ink-900);
  white-space: nowrap;
}

/* ---- Live cursor readout ---- */
/* Clips the readout chip so a pointer near the edge can never widen the page. */
.schematic-wrap { position: relative; overflow: hidden; }
.cursor-readout {
  position: absolute;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border: 1px solid var(--color-accent-500);
  border-radius: 6px;
  background: rgba(7, 14, 26, 0.92);
  box-shadow: var(--shadow-float);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  /* The chip trails the pointer, so it must never eat the pointer events the
     drawing's own drag handles rely on. */
  pointer-events: none;
}
.cursor-readout[hidden] { display: none; }
.cr-k { color: var(--color-ink-400); letter-spacing: 0.1em; }
.cr-v { color: var(--color-accent-300); font-weight: 600; }
.cr-sep {
  width: 1px;
  height: 10px;
  background: var(--color-border-strong);
}


/* ---- Rule packs / feasibility ---- */
.rules-detail { margin-top: 10px; }
.rules-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin: 0 0 10px;
}
.rules-grid > div {
  padding: 7px 9px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  background: var(--color-field);
}
.rules-grid dt {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-ink-400);
}
.rules-grid dd {
  margin: 2px 0 0;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--color-ink-900);
}
.rules-src, .rules-note {
  margin: 6px 0 0;
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--color-ink-500);
}
.rules-note { color: var(--color-ink-400); font-style: italic; }

/* Envelope band chart: the swept range as a track, with the compliant span
   marked on it and the comfortable span inset inside that. */
.env-bar {
  position: relative;
  height: 26px;
  margin: 4px 0 12px;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  background: var(--color-field);
  overflow: hidden;
}
.env-ok, .env-good { position: absolute; top: 0; bottom: 0; }
.env-ok { background: rgba(31, 111, 235, 0.35); }
.env-good { background: rgba(52, 211, 153, 0.45); }
.env-tick { position: absolute; top: 0; bottom: 0; }
.env-tick i {
  position: absolute; top: 0; bottom: 0; left: 0;
  width: 1px; background: var(--color-ink-900);
}
.env-tick b {
  position: absolute; top: 50%; left: 4px;
  transform: translateY(-50%);
  font-family: var(--font-mono);
  font-size: 8.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-400);
  font-weight: 500;
}
.env-table { width: 100%; border-collapse: collapse; margin-bottom: 8px; }
.env-table th {
  text-align: left;
  font-size: 10px;
  font-weight: 600;
  color: var(--color-ink-400);
  padding: 3px 0;
}
.env-table td { font-size: 11.5px; text-align: right; color: var(--color-ink-900); }
.feas-result { margin-top: 10px; }
.auto-hint.is-fail { color: var(--color-danger-600); }


/* Grouped tools inside a section body - a labelled block with its own rule
   above it, so several tools can share one accordion without running together. */
.tool-block {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--color-border);
}
.tool-block:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.tool-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.tool-title {
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-ink-400);
}
.tool-head .display-badge { margin-left: auto; }


/* Two controls side by side inside a tool block.
   Deliberately NOT called .field-row: that class already exists as the app's
   three-column label/input/unit grid, and redefining it here silently broke
   every Input Parameters row - the unit column collapsed and the m/mm wrapped
   onto a line of its own. */
.tool-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

/* Unit suffix sitting hard against its input rather than under it. The span is
   pinned inside the field's own box so it reads as part of the control, and the
   input is padded so a long value never runs beneath it. */
.input-unit {
  position: relative;
  display: block;
}
.input-unit input {
  width: 100%;
  padding-right: 30px;
}
.input-unit > span {
  position: absolute;
  top: 50%;
  right: 9px;
  transform: translateY(-50%);
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--color-ink-400);
  pointer-events: none;
}


/* Rule-pack verdict. Sits with rate of change - both are pass/fail statements
   about the profile just calculated. Breaches are listed in the title so the
   summary stays one line. */
.pack-status {
  margin: 0;
  font-size: 11.5px;
  font-weight: 600;
  cursor: help;
}
.pack-status.is-ok { color: var(--color-success-600); }
.pack-status.is-fail { color: var(--color-danger-600); }
.pack-status[hidden] { display: none; }



/* ------------------------------------------------------------ account menu
   Same surface, border and shadow tokens as the profile menu beside it, so
   the two panels are visibly the same component family rather than two
   designs sharing a toolbar. */
.acct-wrap { position: relative; flex: 0 0 auto; margin-right: 10px; }

.acct-trigger {
  display: flex; align-items: center; gap: 9px; cursor: pointer;
  padding: 5px 11px 5px 6px; border-radius: 11px;
  border: 1px solid var(--color-border); background: var(--color-surface);
  font: inherit; color: var(--color-ink-900);
  transition: background .15s, border-color .15s, box-shadow .15s;
}
.acct-trigger:hover { background: var(--color-bg-soft);
                      border-color: var(--color-border-strong); }
.acct-trigger[aria-expanded="true"] { background: var(--color-bg-soft);
                                      border-color: var(--color-accent-500);
                                      box-shadow: 0 0 0 3px rgba(31,111,235,.16); }
/* Amber only in the two states that need acting on - a trial about to lapse
   and a failed payment. Everything else stays quiet. */
.acct-trigger.urgent { border-color: rgba(251,191,36,.45);
                       background: var(--color-warning-100); }
.acct-trigger.urgent .acct-trigger-state { color: var(--color-warning-600); }

.acct-avatar { width: 26px; height: 26px; border-radius: 50%; flex: 0 0 auto;
               object-fit: cover; }
.acct-initial { display: grid; place-items: center;
                font: 700 12px var(--font-sans);
                background: var(--color-accent-500); color: #fff; }
.acct-trigger-text { display: flex; flex-direction: column; line-height: 1.2;
                     text-align: left; min-width: 0; }
.acct-trigger-name { font-size: 12.5px; font-weight: 600;
                     color: var(--color-ink-900); white-space: nowrap; }
.acct-trigger-state { font-size: 10.5px; color: var(--color-ink-500);
                      white-space: nowrap; letter-spacing: .01em; }
.acct-trigger .caret { font-size: 10px; color: var(--color-ink-500); }

.acct-panel {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
  min-width: 256px; padding: 7px; border-radius: 14px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-float);
}
.acct-panel[hidden] { display: none; }

.acct-id { display: flex; flex-direction: column; gap: 2px;
           padding: 10px 12px 12px; margin-bottom: 7px;
           border-bottom: 1px solid var(--color-border); }
.acct-id b { font-size: 13.5px; font-weight: 600; color: var(--color-ink-900); }
.acct-id span { font-size: 11.5px; color: var(--color-ink-500);
                overflow-wrap: anywhere; }

.acct-status { padding: 10px 12px; margin: 0 0 7px; border-radius: 10px;
               background: var(--color-accent-100);
               border: 1px solid rgba(31,111,235,.22); }
.acct-status.urgent { background: var(--color-warning-100);
                      border-color: rgba(251,191,36,.28); }
.acct-status-line { display: block; font-size: 12.5px; font-weight: 600;
                    color: var(--color-ink-900); }
.acct-status.urgent .acct-status-line { color: var(--color-warning-600); }
.acct-status-sub { display: block; font-size: 11px; color: var(--color-ink-500);
                   margin-top: 2px; }

.acct-item {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; border-radius: 10px; font-size: 13px; font-weight: 500;
  text-decoration: none; color: var(--color-ink-700);
  transition: background .12s, color .12s;
}
.acct-item:hover { background: var(--color-bg-soft); color: var(--color-ink-900); }
.acct-item.primary { justify-content: center; margin-bottom: 5px;
                     font-weight: 650; color: #fff;
                     background: var(--color-accent-500);
                     box-shadow: 0 2px 10px rgba(31,111,235,.28); }
.acct-item.primary:hover { background: var(--color-accent-600); color: #fff; }
.acct-item.danger { color: var(--color-danger-600); }
.acct-item.danger:hover { background: var(--color-danger-100);
                          color: var(--color-danger-600); }
.acct-ext { font-size: 11px; color: var(--color-ink-500); }

/* Both header menus get the same entrance, so opening either feels like the
   same control rather than two different ones. */
@media (prefers-reduced-motion: no-preference) {
  .acct-panel:not([hidden]), .pm-panel:not([hidden]) {
    animation: menu-in .13s ease-out;
  }
}
@keyframes menu-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------------------------------------------------------- sidebar resizer
   Four pixels of hit area, one pixel of visible line. Invisible until it is
   wanted: a permanently drawn divider competes with the panel borders either
   side of it, and there are already enough lines on this screen. */
.sidebar-resizer {
  flex: 0 0 4px;
  cursor: col-resize;
  background: transparent;
  position: relative;
  z-index: 5;
  transition: background .12s;
}
.sidebar-resizer::after {
  content: "";
  position: absolute; inset: 0 auto 0 1px; width: 2px;
  background: var(--color-accent-500);
  opacity: 0; transition: opacity .12s;
}
.sidebar-resizer:hover::after,
.sidebar-resizer:focus-visible::after,
.sidebar-resizer.is-dragging::after { opacity: 1; }
.sidebar-resizer:focus-visible { outline: none; }

/* Nothing to resize when the panel is closed. */
.sidebar.is-collapsed + .sidebar-resizer { display: none; }

/* While dragging, stop the pointer selecting text or the iframe/canvas
   swallowing the move events. */
body.is-resizing { user-select: none; cursor: col-resize; }
body.is-resizing .schematic-canvas,
body.is-resizing .sim-overlay { pointer-events: none; }

/* ------------------------------------------------- numeric readouts in mono
   "Data only": anything that reports a measured or computed value gets the
   drawing's typeface, so a column of clearances lines up digit for digit and
   reads as instrumentation. Labels, buttons and prose stay in Inter, where a
   proportional face is easier at 11-12px.

   The output bar already did this via .ob-k / .ob-v; these are the readouts
   that were missed. */
.sim-readout,
.sim-result-badge,
.ep-zoom-val,
.ep-count {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* ------------------------------------------------- simulation transport
   Attached to the foot of the drawing and sharing its horizontal padding, so
   the track's coordinate space IS the schematic's - a marker at 40% along the
   bar sits under the point 40% along the profile. */
.sim-transport {
  display: flex; align-items: center; gap: 12px;
  margin: 2px 16px 14px;
  padding: 9px 12px;
  border: 1px solid var(--color-border);
  border-radius: 12px;
  background: linear-gradient(180deg, var(--color-surface), var(--color-bg-soft));
}
.sim-transport[hidden] { display: none; }

/* Round, filled, and big enough to hit without aiming. The ring on hover
   reads as a media control rather than a form button. */
.sim-play {
  flex: 0 0 auto; width: 58px; height: 58px; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer; border: 0;
  color: #fff;
  /* Flat colour. The gradient and the outer glow made a plain transport
     control look like it was trying to be a feature. */
  background: var(--color-accent-500);
  transition: transform .1s, background .12s;
}
.sim-play:hover { background: var(--color-accent-600); }
.sim-play:active { transform: scale(.93); }
.sim-play:focus-visible { outline: 2px solid var(--color-accent-300);
                          outline-offset: 3px; }
/* :not([hidden]) matters. A bare `.sim-play svg { display: block }` beats the
   user-agent rule that makes [hidden] display:none, so BOTH icons render and
   the grid stacks them - which is why the pause bars appeared to hang over
   the edge. They are stacked in the same cell rather than swapped. */
.sim-play svg:not([hidden]) { display: block; }
.sim-play svg[hidden] { display: none; }
/* Playing: same button, cooler, so the state is legible without the
   control changing shape under the pointer. */
/* Playing: same button, cooler, so the state reads without the control
   changing shape under the pointer. */
.sim-play.is-playing { background: var(--color-navy-700); }
.sim-play.is-playing:hover { background: var(--color-navy-800); }

.sim-track { position: relative; flex: 1; height: 50px; min-width: 0; }
/* Tight-spot bands are positioned by station and the traverse runs past
   both ends of the drawing, so anything outside the drawn range is
   clipped rather than escaping the control. */
.sim-spots { overflow: hidden; border-radius: 999px; }

/* One thin rail. No stretched profile line - the drawing above already shows
   the shape, and repeating it squashed only competed with it. */
.sim-rail { position: absolute; left: 0; right: 0; top: 50%; height: 5px;
            transform: translateY(-50%); border-radius: 999px;
            background: var(--color-field);
            border: 1px solid var(--color-border); }
/* --car-half is the inset every moving part shares. The handle is a wide
   vehicle, not a small knob, so at 0% a naively centred one hangs half its
   width off the left of the track and lands on the play button. Everything
   that has to line up with it - the fill, the tight-spot bands - is inset by
   the same amount, so the car sits exactly inside the rail at both ends the
   way a range thumb does. */
.sim-track { --car-half: 46px; }
.sim-fill { position: absolute; left: 0; top: 50%; height: 5px;
            width: calc(var(--car-half) + var(--p, 0) * (100% - var(--car-half) * 2));
            transform: translateY(-50%); border-radius: 999px;
            background: var(--color-accent-500); opacity: .55; pointer-events: none; }

/* Tight spots as discrete bands, positioned by station. Each is a stretch of
   the drive where clearance drops below comfortable - amber where it is
   merely tight, red where the vehicle grounds. Reading them is "there is a
   problem HERE", which is the question being asked. */
.sim-spots { position: absolute; top: 0; bottom: 0;
             left: var(--car-half); right: var(--car-half);
             pointer-events: none; }
.sim-spot { position: absolute; top: 50%; height: 9px; min-width: 3px;
            transform: translateY(-50%); border-radius: 3px;
            background: var(--color-warning-600); opacity: .9; }
.sim-spot.is-fail { background: var(--color-danger-600); }
.sim-spot.is-worst { height: 15px; border-radius: 4px;
                     box-shadow: 0 0 0 2px var(--color-bg), 0 0 10px currentColor; }

/* The handle is the vehicle under test, drawn from the same artwork as the
   one on the drawing. Grabbing the actual car is more legible than grabbing
   an anonymous knob, and it makes the bar obviously about the vehicle. */
.sim-car { position: absolute; top: 50%; width: 92px; height: 44px;
           left: calc(var(--car-half) + var(--p, 0) * (100% - var(--car-half) * 2));
           transform: translate(-50%, -50%); pointer-events: none;
           filter: drop-shadow(0 2px 4px rgba(0,0,0,.45));
           transition: filter .12s; }
.sim-car svg { width: 100%; height: 100%; overflow: visible; display: block; }
/* Parked at an end because the vehicle is off the drawing. */
.sim-car.is-offstage { opacity: .38; }
.sim-track:focus-within .sim-car,
.sim-track:hover .sim-car { filter: drop-shadow(0 2px 8px rgba(31,111,235,.75)); }

.sim-track input[type="range"] {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0;
  opacity: 0; cursor: grab; -webkit-appearance: none; appearance: none;
  background: transparent;
}
.sim-track input[type="range"]:active { cursor: grabbing; }

.sim-station { flex: 0 0 auto; min-width: 64px; text-align: right;
               font-family: var(--font-mono); font-variant-numeric: tabular-nums;
               font-size: 12.5px; font-weight: 600; color: var(--color-ink-700); }

/* ------------------------------------------------------- profile menu tabs */
.pm-tabs { display: flex; gap: 4px; padding: 0 0 10px; }
.pm-tab {
  flex: 1; cursor: pointer; border: 0; border-radius: 8px;
  padding: 8px 10px; font: 600 12px var(--font-sans);
  background: transparent; color: var(--color-ink-500);
  transition: background .14s, color .14s;
}
.pm-tab:hover { color: var(--color-ink-900); background: var(--color-bg-soft); }
.pm-tab.on { background: var(--color-accent-500); color: #fff; }
.pm-tabpane[hidden] { display: none; }

.pm-tpl-note { margin: 0 0 10px; font-size: 11.5px; line-height: 1.5;
               color: var(--color-ink-500); }

/* ---- job cards ---- */
.pm-item { gap: 11px; }
/* The job's own long section, at 54x30. Recognising a site by the shape of
   its driveway is faster than reading a list of addresses, and the shape is
   the one thing every job on this list definitely differs by. */
.pm-thumb {
  flex: 0 0 auto; width: 54px; height: 30px; border-radius: 6px;
  background: var(--color-field); border: 1px solid var(--color-border);
  overflow: hidden;
}
.pm-thumb svg { display: block; width: 100%; height: 100%; }
.pm-thumb.is-empty { display: grid; place-items: center; }
.pm-thumb.is-empty::after { content: "—"; color: var(--color-ink-400); font-size: 12px; }

.pm-item-facts { display: flex; flex-wrap: wrap; gap: 4px 9px; margin-top: 3px;
                 font-family: var(--font-mono); font-size: 10.5px;
                 color: var(--color-ink-400); }
.pm-item-when { font-size: 10.5px; color: var(--color-ink-400); margin-top: 2px; }

/* ------------------------------------------------- jobs section in the panel
   Was a 620px two-pane dropdown in the header. In a 344px sidebar it has to
   be one narrow column, so the save controls stack above the list rather than
   sitting beside it. */
.side-jobs .pm-pane { padding: 0; }
.side-jobs .pm-pane-actions,
.side-jobs .pm-pane-list { width: auto; border: 0; background: none; }
.side-jobs .pm-pane-actions { margin-bottom: 12px; }
.side-jobs .pm-list { max-height: 260px; overflow-y: auto; }

/* Current job, on the section header, so it is legible with the section shut. */
.pm-current {
  margin-left: auto; margin-right: 6px; max-width: 42%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--font-mono); font-size: 10.5px;
  color: var(--color-ink-400);
}

/* Cards get tight in a narrow panel: the row actions only appear on hover or
   keyboard focus, so the name and thumbnail keep the width. */
.side-jobs .pm-item-actions { opacity: 0; transition: opacity .12s; }
.side-jobs .pm-item:hover .pm-item-actions,
.side-jobs .pm-item:focus-within .pm-item-actions { opacity: 1; }

/* A profile that was produced but breaks 1:4. Amber rather than red: red is
   the drawing's job here, and two reds competing would blur which one is
   reporting the geometry. */
.auto-result.warn { border-color: rgba(251,191,36,.45); background: var(--color-warning-100); }
.auto-result.warn .auto-zone-pill { border-color: rgba(251,191,36,.4);
                                    color: var(--color-warning-600); }
.auto-warn { margin: 0 0 10px; font-size: 12.5px; font-weight: 600; line-height: 1.5;
             color: var(--color-warning-600); }

/* ------------------------------------------------------ sidebar group heads
   Four peers: Jobs & Templates, Parameters, the simulator and the designer.
   Parameters used to be the name of the whole panel, which quietly implied
   the other three were parameters too - they are separate tools that happen
   to share a panel. Same treatment as the old panel title so they read as
   headings rather than another row of controls. */
.side-group {
  margin: 22px 0 9px;
  padding: 0 4px 8px;
  /* A brighter rule than the section borders beneath it, so the heading reads
     as the thing the sections hang off rather than as another card edge. */
  border-bottom: 1px solid var(--color-border-strong);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  /* White. These name the four tools in the panel and were being outranked by
     the section titles under them, which is backwards. */
  color: #fff;
}
/* The first one sits against the panel bar, so it needs no gap above it. */
.side-group:first-child { margin-top: 2px; }

/* ------------------------------------------------------------- undo / redo */
.undo-group { display: inline-flex; gap: 2px; margin-right: 6px;
              padding-right: 8px; border-right: 1px solid var(--color-border); }
.icon-btn {
  width: 32px; height: 32px; display: grid; place-items: center; cursor: pointer;
  /* Explicit, because the element-level `button` rule sets 7px 14px - which on
     a 32px border-box button leaves a 2px content box for a 14px icon, and the
     overflow is what pushed the arrows off centre. */
  padding: 0;
  border: 1px solid var(--color-border); border-radius: 8px;
  background: transparent; color: var(--color-ink-700);
  transition: background .12s, color .12s, border-color .12s;
}
.icon-btn:hover:not(:disabled) { background: var(--color-bg-soft);
                                 color: var(--color-ink-900);
                                 border-color: var(--color-border-strong); }
.icon-btn:active:not(:disabled) { transform: translateY(1px); }
/* Dimmed rather than hidden: a control that vanishes when there is nothing to
   undo moves everything beside it, and the row jumps as you work. */
.icon-btn:disabled { opacity: .34; cursor: default; }
.icon-btn svg { width: 15px; height: 15px; }

/* ================================================================= section
   state: open vs collapsed
   ==========================================================================
   The chevron already rotated, but it was doing the job alone: 13px, dim,
   and every section otherwise identical. One small cue carrying all the
   state is exactly the thing that does not read at a glance.

   The fix is redundancy, which is what every application with a lot of
   collapsible panels does - VS Code, Figma, Blender, the Windows and macOS
   file panes. None of them rely on the arrow. They all stack several signals
   that agree with each other, so the state is legible from any one of them:

     1. the arrow           direction, and it MOVES between states
     2. surface             an open section is raised; a closed one is flat
        and sits back into the panel
     3. title weight/colour open reads at full strength, closed recedes
     4. an accent rail      down the open section only
     5. the icon            tinted when open, grey when closed

   Hover on a closed section previews the open treatment, so the control
   advertises what clicking will do before it is clicked.
   ------------------------------------------------------------------------ */

/* --- open (the default state of .side-section) --- */
.side-section {
  position: relative;
  border-color: var(--color-border-strong);
  transition: background .15s, border-color .15s;
}
/* Accent rail, drawn only while open. The strongest peripheral cue: you can
   see which sections are open without reading anything. */
.side-section::before {
  content: "";
  position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
  background: var(--color-accent-500);
  border-radius: 12px 0 0 12px;
  opacity: 1; transition: opacity .15s;
}
.side-section .ss-icon { color: var(--color-accent-300); }
.side-section .ss-chev { color: var(--color-ink-700); }

/* --- collapsed --- */
.side-section.is-folded {
  background: var(--color-bg-soft);
  border-color: var(--color-border);
}
.side-section.is-folded::before { opacity: 0; }
.side-section.is-folded .ss-toggle { color: var(--color-ink-500); font-weight: 600; }
.side-section.is-folded .ss-icon { color: var(--color-ink-400); }
.side-section.is-folded .ss-chev { color: var(--color-ink-400); }

/* Hovering a closed section shows what opening it will look like. */
.side-section.is-folded:hover { background: var(--color-surface);
                                border-color: var(--color-border-strong); }
.side-section.is-folded:hover .ss-toggle { color: var(--color-ink-900); }
.side-section.is-folded:hover .ss-chev { color: var(--color-ink-700); }

/* Bigger, and it travels further: -90deg reads as "pointing at a heading
   that is shut" against 0deg "pointing down into open content". */
.ss-chev { width: 15px; height: 15px; }

/* Keyboard users get the same information as the pointer. */
.ss-toggle:focus-visible { outline: 2px solid var(--color-accent-500);
                           outline-offset: -2px; border-radius: 10px; }

/* ---------------------------------------------------------- schematic zoom */
.zoom-controls {
  display: inline-flex; align-items: stretch; gap: 1px;
  margin-right: 6px; padding-right: 8px;
  border-right: 1px solid var(--color-border);
}

.zoom-btn {
  border: 1px solid var(--color-border); background: transparent; cursor: pointer;
  border-radius: 8px; color: var(--color-ink-700); font: 600 14px var(--font-sans);
  padding: 0; min-width: 32px; height: 32px;
  display: grid; place-items: center;
  transition: background .12s, color .12s, border-color .12s;
}
.zoom-btn:hover { background: var(--color-bg-soft); color: var(--color-ink-900); }
.zoom-btn:disabled { opacity: .35; cursor: default; background: transparent; }
.zoom-level {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  min-width: 52px; font-variant-numeric: tabular-nums;
}
.zoom-controls.is-zoomed .zoom-level { color: var(--color-accent-300);
                                       border-color: var(--color-accent-500); }

/* Grab only while there is somewhere to pan to. */
.schematic-canvas.is-pannable { cursor: grab; }
.schematic-canvas.is-panning { cursor: grabbing; }
