/* Personal tool with a consistent, accessible, professional interface: no marketing, no
   decoration, but real typography/spacing/color/status conventions (CLAUDE.md section 9,
   revised in Phase 7A). Tokens below are ported from design/prototype-current.html (Run 3),
   which is the approved visual reference for Phase 7A. */

:root {
  --c-ride: #888;
  --c-segment: #1565c0;
  --c-effort: #e65100;
  --c-valid: #2e7d32;
  --c-error: #c62828;
  --c-warn: #e6a23c;
  --radius-sm: 4px;
  --radius-md: 10px;
  --space-1: .25rem;
  --space-2: .5rem;
  --space-3: .75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --font-sans: system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, Consolas, monospace;
  /* Fase 7A Run 8 checkpoint 11: bumped to 1280px (was 1100px) now that the vertical two-column
     #workspace layout is live - a wider max-width is what design/prototype-vertical.html's own
     --content-max approves for the two-column desktop split. */
  --content-max: 1280px;
  --focus-ring: 2px solid #0b5fff;
  --border: #d8dee4;
  --touch: 44px;

  /* Fase 7A Run 8: vertical workflow layout tokens (design/prototype-vertical.html, Run 7,
     approved). */
  --col-workflow-min: 520px;
  --col-map-min: 420px;
  --sticky-top: 1rem;
  --map-h: clamp(260px, calc(100vh - 7rem), 560px);
  --map-h-flow: 16rem;
  --profile-plot-h: clamp(180px, 22vh, 220px);
}

* { box-sizing: border-box; }

/* Fase 7A Run 5: standard accessible-name utility - used for <legend>/<label> text that would be
   visually redundant next to an already-labelled control (e.g. the target-ride fieldset legend,
   and each target-ride row's own select/name-input label) but is still required for a correct
   accessible name. Not decorative, not new visual language. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

body {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.5;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-6) var(--space-4) 4rem;
  color: #1a1a1a;
  background: #f6f7f9;
}

h1 { font-size: 1.5rem; margin: 0; }
h2 { font-size: 1.1rem; margin: 0 0 .25rem; }
h3 { font-size: .95rem; margin: 1rem 0 .25rem; }

.global-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}
.brand-link { color: #18324d; text-decoration: none; min-width: 0; }
.brand-lockup { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.brand-copy { display: grid; gap: .1rem; min-width: 0; }
.brand-name { font-size: 1.15rem; font-weight: 750; line-height: 1.2; }
.brand-trust { color: #4a5560; font-size: .78rem; line-height: 1.25; }
.route-mark { width: 2.75rem; height: 2.75rem; flex: none; }
.route-mark-path { fill: none; stroke: var(--c-segment); stroke-width: 3; stroke-linecap: round; }
.route-mark-start { fill: var(--c-valid); stroke: #fff; stroke-width: 2; }
.route-mark-end { fill: var(--c-error); stroke: #fff; stroke-width: 2; }
.header-nav { display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-1) var(--space-3); font-size: .88rem; }
.header-nav a { display: inline-flex; align-items: center; min-height: var(--touch); color: #274d70; text-decoration-thickness: 1px; text-underline-offset: .15em; }
.header-nav a[aria-current="page"], .brand-link[aria-current="page"] { font-weight: 750; text-decoration-thickness: 2px; }
.header-demo-action {
  min-height: 2.5rem;
  margin: 0;
  padding: .45rem .8rem;
  border-color: #315f8c;
  background: #edf4fa;
  color: #183f65;
  font-weight: 700;
}
.header-demo-action:hover { border-color: #0b3d91; background: #e2edf7; }
.page-view[hidden] { display: none; }
.tool-introduction { max-width: 49rem; margin-bottom: var(--space-3); }
.tool-introduction h1 { font-size: clamp(1.55rem, 3vw, 2rem); line-height: 1.2; }
.tool-introduction h1:focus {
  outline: 2px solid transparent;
  border-radius: 1px;
  box-shadow: -.25rem 0 0 #7fa9cf;
}
.tool-introduction p { margin: 0; }
.tool-introduction-primary { margin-top: var(--space-2) !important; color: #24384b; font-size: 1.05rem; }
.information-view {
  min-height: 20rem;
  padding: clamp(1rem, 3vw, 2.5rem);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: #fff;
}
.information-shell { max-width: 68rem; margin: 0 auto; }
.information-shell > h1 { font-size: clamp(1.55rem, 3vw, 2rem); line-height: 1.2; }
.information-lead { max-width: 46rem; margin: var(--space-2) 0 var(--space-5, 1.25rem); color: #3d4f60; font-size: 1.02rem; }
.back-to-tool { margin: var(--space-8) 0 0; }
.back-to-tool a { display: inline-flex; align-items: center; min-height: var(--touch); color: #165a96; font-weight: 700; }
.lead { margin: 0 0 1rem; color: #444; max-width: 42rem; }
.hint { margin: .25rem 0 .5rem; color: #555; font-size: .9em; }
.file-meta { overflow-wrap: anywhere; }

.notice {
  background: #fff8e1;
  border: 1px solid #e6c65c;
  border-left-width: 4px;
  padding: var(--space-2) var(--space-3);
  margin: var(--space-4) 0;
  border-radius: var(--radius-sm);
}

.panel {
  margin-top: var(--space-3);
  padding: var(--space-3);
  border: 1px solid #ccc;
  border-radius: var(--radius-sm);
  background: #fafafa;
  overflow-wrap: anywhere;
}

.panel.error {
  border-color: var(--c-error);
  border-left-width: 4px;
  background: #fdecea;
  color: #8a1a15;
}

.panel.warn {
  border-color: var(--c-warn);
  border-left-width: 4px;
  background: #fff8e1;
}

.panel.ok {
  border-color: var(--c-valid);
  border-left-width: 4px;
  background: #edf7ed;
}

.panel.plain {
  color: #555;
  font-style: italic;
}

code { font-family: var(--font-mono); font-size: .92em; }

dl.facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: .15rem .75rem;
  margin: 0;
}
dl.facts dt { color: #555; }
dl.facts dd { margin: 0; font-family: var(--font-mono); overflow-wrap: anywhere; }

/* Every informative table's markup is wrapped in <div class="table-wrap"> (js/app.js), which
   gives the table its own horizontal-scroll box (see .table-wrap below) - contained overflow,
   never page-wide. table-layout stays the browser default (auto), so a column never shrinks
   below its content's natural width; .table-wrap absorbs whatever width that produces. */
table {
  border-collapse: collapse;
  margin-top: .35rem;
  font-size: .92em;
  width: 100%;
}
th, td {
  border: 1px solid #ccc;
  padding: .2rem .5rem;
  text-align: left;
}
th { background: #eee; font-weight: 600; }
td.num { text-align: right; font-family: var(--font-mono); }
td.empty { color: #999; font-style: italic; }

/* Fase 7A Run 6A bugfix: th/td previously had `overflow-wrap: anywhere`, added before
   .table-wrap existed as a page-wide-overflow safety net (predating Run 5). Once .table-wrap
   shipped, that property became actively harmful rather than merely redundant: `anywhere`
   permits a break at *any* character position, so once width:100% above squeezed a column
   below an ordinary short word's natural width (e.g. the effort tables' Found/Time/Method
   columns), the browser split words like "Found" and "embedded" mid-letter rather than
   growing the table - reported and confirmed in the browser with real rendered data. Removed
   entirely (default `normal`, which never breaks inside a word) now that .table-wrap's own
   overflow-x:auto is the actual containment mechanism; a genuinely unbreakable long token (an
   unusually long filename, say) simply widens the table within that scrollable wrapper instead
   of being split. See #batch-output/#build-extra-batch-output below for the effort tables'
   own min-width, added at the same time so their columns don't get pre-emptively cramped
   before .table-wrap's scroll ever needs to kick in. */

.table-wrap { overflow-x: auto; margin-top: .5rem; }

.workflow-utility {
  width: min(100%, var(--content-max));
  margin: var(--space-3) auto 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  padding: .55rem .75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: #eef3f7;
}
.workflow-utility strong { color: #263d52; font-size: .92rem; }
.workflow-utility .btn { flex: none; margin: 0; }
@media (max-width: 479px) {
  .workflow-utility { align-items: stretch; flex-direction: column; }
  .workflow-utility .btn { width: 100%; }
}

.selection-status { margin: var(--space-3) 0 0; font-weight: 700; }
.ride-selection-list { display: grid; gap: var(--space-3); margin-top: var(--space-3); }
.ride-selection-card {
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  background: #fff;
}
.ride-selection-card.selected { border-color: var(--c-valid); box-shadow: 0 0 0 1px var(--c-valid) inset; }
.ride-selection-card > legend {
  display: inline-block;
  padding: 0 var(--space-1);
  background-color: inherit;
  font-weight: 700;
}
.mutate-effort-row,
.build-effort-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(9rem, auto) auto;
  gap: .45rem .75rem;
  align-items: center;
  padding: .55rem 0;
  border-top: 1px solid var(--border);
}
.mutate-effort-row:first-of-type,
.build-effort-row:first-of-type { border-top: 0; }
.mutate-effort-row.selected,
.build-effort-row.selected { background: #edf8f0; }
.build-effort-copy,
.target-effort-copy { display: inline-flex; flex-wrap: wrap; gap: var(--space-2); align-items: baseline; }
.build-effort-copy { margin-left: var(--space-1); }
.build-effort-duration { color: #5b6773; }
.target-effort-copy { display: flex; flex-direction: column; align-items: flex-start; gap: .15rem; }
.target-row.unresolved { border-color: var(--c-error); }
@media (max-width: 767px) {
  .mutate-effort-row,
  .build-effort-row { grid-template-columns: 1fr; }
}
.ride-selection-heading { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.ride-selection-heading label { display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--touch); }
.ride-selection-description { margin: var(--space-2) 0; }
.demo-ride-meta { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin: var(--space-2) 0; }
.demo-ride-meta > div { display: flex; gap: var(--space-1); }
.demo-ride-meta dt { color: #5b6773; }
.demo-ride-meta dd { margin: 0; font-weight: 700; }
.match-details { margin-top: var(--space-2); border-top: 1px solid var(--border); }
.match-details summary { display: list-item; min-height: var(--touch); padding: .55rem 0; color: #274d70; cursor: pointer; font-weight: 650; }
.match-details .facts { margin-top: 0; }
.effort-choice { display: grid; gap: var(--space-2); margin-top: var(--space-2); min-width: 0; }
.effort-choice label { display: flex; align-items: center; gap: var(--space-2); min-height: var(--touch); }
.effort-confidence { margin-left: 1.7rem; min-width: 0; }
.btn.compact { min-height: 2.4rem; padding: .35rem .65rem; margin: 0; }

/* Fase 7A Run 6A: the two effort tables (mutate "Review detected efforts" / build "Add more
   rides") share the same seven columns (focus/File/Date/Found/Time/Method/Confidence, the last
   with its own nested measures line) and are the ones the word-wrapping bug was reported
   against - an explicit min-width keeps every column comfortably readable instead of relying
   on the browser's own layout resolution, with .table-wrap providing the contained horizontal
   scroll below this width. */
#batch-output table, #build-extra-batch-output table { min-width: 46rem; }

/* Fase 7A Run 8 checkpoint 10: max-width:100% - the native file-input control's own OS-rendered
   text ("Choose files / No file chosen") is unconstrained by default and can overflow a narrow
   workflow-column track otherwise (design/prototype-vertical.html's own finding, ported here). */
input[type="file"] { font: inherit; min-height: var(--touch); margin: .25rem 0; max-width: 100%; }
input[type="text"] {
  padding: .2rem .4rem;
  font: inherit;
  margin-top: .25rem;
  min-height: var(--touch);
  border: 1px solid #bbb;
  border-radius: var(--radius-sm);
}

/* #map height is responsive. Fase 7A Run 8 checkpoint 11: the three Phase 7A Run 4 tiers
   (16/20/26rem at 375/768/1100px) are retired in favor of the two vertical-workflow tokens
   (--map-h-flow below the two-column threshold, --map-h at/above it - design/
   prototype-vertical.html, Run 7). MapView.fit()/invalidateSize() already re-measure on the
   fitBounds()/ResizeObserver-driven calls that fire on file load and on a breakpoint crossing
   (checkpoint 3), so no further JS change is needed here. margin-top lives on .map-frame
   (checkpoint 3), not on #map itself, to keep #map-empty's inset:0 overlay exactly aligned. */
#map {
  height: var(--map-h-flow);
  border: 1px solid var(--border);
  background: #e9eef2;
}
@media (min-width: 1000px) {
  #map { height: var(--map-h); }
  #map-section.profile-visible #map {
    height: clamp(260px, calc(100vh - var(--profile-plot-h) - 12rem), 500px);
  }
}

/* Fase 6A: L.divIcon handles for dragging a new segment's start/end (js/map-view.js
   draftHandle()). Overrides leaflet.css's .leaflet-div-icon (white fill, grey border) - this
   file loads after vendor/leaflet.css, so these rules win without any extra specificity. */
.draft-handle {
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .5);
  background: #666;
}
.draft-handle-start { background: var(--c-valid); }
.draft-handle-end { background: var(--c-error); }
.leaflet-marker-draggable.draft-handle { cursor: grab; }

/* Phase 7A elevation/UX Run 5: the full-ride boundary lanes stay in the workflow column while
   the read-only elevation figure has one persistent location in the map column. Their X domains
   are deliberately independent: sliders show the ride, the profile shows local terrain. */
.boundary-picker {
  --boundary-thumb-size: 24px;
  margin: var(--space-4) 0;
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
}
.elevation-profile {
  width: 100%;
  min-width: 0;
  margin: var(--space-3) 0 0;
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
}
.elevation-profile figcaption { font-weight: 600; }
.elevation-profile-summary { margin-top: var(--space-1); }
.elevation-profile-frame {
  width: 100%;
  min-width: 0;
  height: var(--profile-plot-h);
  margin-top: var(--space-2);
}
.elevation-profile svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.elevation-profile-axis { stroke: var(--border); stroke-width: 1; }
.elevation-profile-area { stroke: none; }
.elevation-profile-context-area { fill: var(--c-ride); fill-opacity: .22; }
.elevation-profile-selected-area { fill: var(--c-segment); fill-opacity: .34; }
.elevation-profile-contour {
  fill: none;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.elevation-profile-ride {
  stroke: var(--c-ride);
  stroke-width: 1.25;
}
.elevation-profile-selection {
  stroke: var(--c-segment);
  stroke-width: 2;
}
.elevation-profile-boundary line { stroke-width: 2; }
.elevation-profile-boundary text {
  font: 700 12px var(--font-sans);
  paint-order: stroke;
  stroke: #fff;
  stroke-width: 3px;
  stroke-linejoin: round;
}
.elevation-profile-start line { stroke: var(--c-valid); }
.elevation-profile-start text { fill: var(--c-valid); }
.elevation-profile-end line { stroke: var(--c-error); }
.elevation-profile-end text { fill: var(--c-error); }
.elevation-profile-end line { stroke-dasharray: 5 3; }
.elevation-profile-legend { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-3); }
.elevation-legend-area {
  display: inline-block;
  width: 1.25rem;
  height: .65rem;
  margin-top: .25em;
  border-top: 2px solid;
  border-radius: 1px;
}
.elevation-legend-ride { border-color: var(--c-ride); background: rgba(136, 136, 136, .22); }
.elevation-legend-selection { border-color: var(--c-segment); background: rgba(21, 101, 192, .34); }
.elevation-legend-boundary {
  display: inline-grid;
  place-items: center;
  width: 1.25rem;
  height: 1.25rem;
  border: 2px solid currentColor;
  border-radius: 50%;
  font-size: .72rem;
  font-weight: 700;
  line-height: 1;
}
.elevation-legend-start { color: var(--c-valid); }
.elevation-legend-end { color: var(--c-error); border-style: dashed; }

.boundary-controls {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
.boundary-controls legend { padding: 0; font-weight: 600; }
.boundary-control { margin-top: var(--space-3); }
.boundary-control + .boundary-control {
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}
.boundary-control-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
}
.boundary-control-heading label { font-weight: 600; }
.boundary-control-heading output { color: #555; font-size: .9rem; }

/* Separate full-width native lanes are intentional. Overlapping range elements make the top
   input capture the lower one's track and overlapping thumb in Chromium for both mouse and touch. */
.boundary-range {
  appearance: none;
  -webkit-appearance: none;
  display: block;
  width: 100%;
  min-width: 0;
  height: var(--touch);
  margin: var(--space-1) 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
  touch-action: pan-y;
}
.boundary-range::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: var(--border);
}
.boundary-range::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: var(--boundary-thumb-size);
  height: var(--boundary-thumb-size);
  margin-top: calc((4px - var(--boundary-thumb-size)) / 2);
  border: 2px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 0 1px #555;
  background: var(--c-valid);
}
.boundary-range-end::-webkit-slider-thumb { background: var(--c-error); }
.boundary-range::-moz-range-track {
  height: 4px;
  border: 0;
  border-radius: 2px;
  background: var(--border);
}
.boundary-range::-moz-range-thumb {
  width: var(--boundary-thumb-size);
  height: var(--boundary-thumb-size);
  border: 2px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 0 1px #555;
  background: var(--c-valid);
}
.boundary-range-end::-moz-range-thumb { background: var(--c-error); }
.boundary-range:disabled { cursor: not-allowed; opacity: .55; }
.boundary-point-controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.boundary-point-controls button {
  flex: 1 1 9rem;
  min-width: var(--touch);
}

.swatch {
  display: inline-block;
  width: 1.1rem;
  height: .3rem;
  margin: 0 .3rem 0 .75rem;
  vertical-align: middle;
  border-radius: 2px;
}
.swatch:first-child { margin-left: 0; }
.swatch-segment { background: var(--c-segment); }
.swatch-activity { background: var(--c-ride); }
.swatch-passage { background: var(--c-effort); }

tr.selected td { background: #fff3e0; }

td.measures { font-size: .9em; color: #555; }

.level-hoog { color: var(--c-valid); }
.level-middel { color: var(--c-warn); }
.level-laag { color: var(--c-error); font-weight: 600; }

.controls { margin-top: var(--space-3); }
.controls button { margin-right: .4rem; }

/* Goal-first workflow choices: these remain native buttons so the existing click/keyboard
   semantics, pressed state, IDs, and data-testid values stay unchanged. */
#mode-switch {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}
#mode-switch button.mode-option {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 100%;
  min-width: 0;
  min-height: 8.75rem;
  margin: 0;
  padding: var(--space-3) var(--space-4);
  text-align: left;
  gap: .2rem;
  border-color: #aebdca;
  background: #fff;
  color: #1b2e40;
  box-shadow: 0 1px 2px rgba(28, 43, 56, .08);
}
#mode-switch button.mode-option:hover:not(:disabled) {
  border-color: #527da5;
  background: #f6f9fc;
}
.mode-option-primary {
  display: block;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.25;
}
.mode-option-secondary {
  display: block;
  font-size: .88rem;
  font-weight: 600;
  line-height: 1.3;
}
.mode-option-supporting {
  display: block;
  margin-top: .2rem;
  font-size: .84rem;
  font-weight: 400;
  line-height: 1.4;
  overflow-wrap: anywhere;
}
.mode-option-state {
  display: inline-block;
  visibility: hidden;
  margin-top: auto;
  padding: .1rem .45rem;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .02em;
}
#mode-switch button.mode-option.active .mode-option-state { visibility: visible; }
#mode-switch button.mode-option.active .mode-option-supporting,
#mode-switch button.mode-option.active .mode-option-secondary { opacity: .9; }
@media (max-width: 767px) {
  #mode-switch { grid-template-columns: 1fr; }
}

.demo-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid #9eb7d3;
  border-left: .3rem solid #0b3d91;
  border-radius: var(--radius-sm);
  background: #f2f7fc;
}
.demo-banner[hidden] { display: none; }
.demo-banner p { margin: .15rem 0 0; }
.demo-banner-actions { display: flex; flex: none; gap: var(--space-2); }
.demo-banner-actions .btn { margin: 0; }
.demo-error { margin-top: var(--space-3); }
.demo-error p { margin: var(--space-2) 0 0; }
.demo-step-hint,
.demo-review-note,
.demo-help-callout {
  padding: var(--space-3);
  border-left: .25rem solid #0b3d91;
  background: #f2f7fc;
}
.demo-review-note p { margin: 0; }
.demo-review-note p + p { margin-top: var(--space-1); }
.demo-completion {
  margin-top: var(--space-4);
  padding: var(--space-4);
  border: 1px solid #94c79a;
  border-radius: var(--radius-sm);
  background: #f3faf3;
}
.demo-completion h3,
.demo-completion p { margin-top: 0; }
.link-button {
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: #0b3d91;
  font-weight: 600;
  text-decoration: underline;
}
.demo-dialog {
  width: min(32rem, calc(100% - 2rem));
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 1rem 3rem rgba(0, 0, 0, .25);
}
.demo-dialog::backdrop { background: rgba(20, 32, 45, .55); }
.demo-dialog h2 { margin-top: 0; }
.demo-dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); }

@media (max-width: 767px) {
  .demo-banner { align-items: stretch; flex-direction: column; }
  .demo-banner-actions,
  .demo-dialog-actions { flex-direction: column; }
  .demo-banner-actions .btn,
  .demo-dialog-actions .btn,
  .demo-completion .btn { width: 100%; margin: 0 0 var(--space-2); }
}

/* Neutral, accessible baseline for every bare/unclassed <button> in today's markup (Adjust
   start/end, Start over, Generate all, per-target mutate buttons, etc.). Deliberately not a
   primary/blue treatment - that emphasis is reserved for the two scoped exceptions below
   (#mode-switch button.active, a.download) and for the future .btn/.btn.secondary classes. */
button {
  font: inherit;
  padding: .5rem .9rem;
  min-height: var(--touch);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: #f4f4f4;
  cursor: pointer;
}

/* Generic "pressed/active toggle" meaning, unchanged since before Phase 7A - used by the
   Adjust-start/Adjust-end correction buttons in both mutate and build mode (js/app.js). Left
   as-is (color token only) so #mode-switch's own active styling below can be scoped without
   disturbing this. */
button.active { outline: 2px solid var(--c-effort); }

/* The selected workflow card uses a restrained tint and a structural edge accent instead of a
   large dark fill. The visible Selected pill supplements aria-pressed, so color is not the only
   state cue. */
#mode-switch button.active {
  background: #edf5fc;
  border-color: #0b3d91;
  color: #17324d;
  font-weight: 600;
  outline: none;
  box-shadow: inset .25rem 0 0 #0b3d91, 0 1px 2px rgba(28, 43, 56, .08);
}
#mode-switch #mode-mutate-button.active {
  background: #eef4fd;
  border-color: #0b3d91;
  color: #17324d;
}
#mode-switch button.mode-option.active .mode-option-state {
  border-color: #6f98bd;
  background: #fff;
  color: #164f82;
}
/* Regression found during Run 4 browser verification: the resting outline:none above also
   suppressed the keyboard :focus-visible ring on the mode button that's active by default
   (mutate mode on page load), since #mode-switch button.active outranks the plain
   button:focus-visible rule. Restore the ring specifically for keyboard focus. */
#mode-switch button.active:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}

.mode-status { margin: .4rem 0 0; font-size: .9em; color: #555; }

/* Established, single-purpose CTA link (the primary result of a mutation/build). Scoped
   exception to the neutral button baseline above - existing selector, not generalized. */
a.download {
  display: inline-block;
  margin-top: .4rem;
  padding: .5rem .9rem;
  min-height: var(--touch);
  border-radius: var(--radius-sm);
  background: #0b3d91;
  color: #fff;
  font-weight: 600;
  text-decoration: none;
}

details.changelog, details.checklist { margin-top: var(--space-3); }
details.changelog summary, details.checklist summary { cursor: pointer; color: #555; }
details.changelog table, details.checklist table { font-size: .85em; }

td.status-ok { color: var(--c-valid); }
td.status-fail { color: var(--c-error); font-weight: 600; }
td.status-skip { color: #999; font-style: italic; }

details.unsafe { margin-top: var(--space-3); }
details.unsafe summary { cursor: pointer; color: #8a1a15; }
/* Dev-only escape hatch (CLAUDE.md section 6/section 8) - secondary and warning-styled, never
   the primary CTA treatment a.download gets above. */
a.unsafe-download {
  display: inline-block;
  margin-top: .4rem;
  padding: .5rem .9rem;
  min-height: var(--touch);
  border-radius: var(--radius-sm);
  border: 1px solid #8a1a15;
  background: #fdecea;
  color: #8a1a15;
  font-weight: 600;
  text-decoration: none;
}

/* Closes a pre-existing gap: js/app.js:451 already emits <details class="technical-details">
   for "Interne fout"-style messages, but no rule for it existed before Phase 7A Run 4. */
details.technical-details { margin-top: var(--space-3); }
details.technical-details summary {
  cursor: pointer;
  color: #555;
  font-size: .9em;
  min-height: var(--touch);
  display: flex;
  align-items: center;
}

.device-checklist {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid #bfe2c0;
}
.device-checklist h3 { margin: 0 0 var(--space-2); }
.device-checklist ol { margin: 0; padding-left: 1.3rem; }

.help-shell { max-width: 68rem; margin: 0 auto; }
.help-local-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  margin-top: var(--space-4);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--border);
}
.help-local-nav a {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch);
  color: #274d70;
  font-weight: 600;
  text-underline-offset: .18em;
}
.help-section {
  max-width: 52rem;
  margin-top: 3rem;
  scroll-margin-top: var(--sticky-top);
}
.help-story { max-width: 46rem; }
.help-section h2 { margin: 0 0 var(--space-3); font-size: 1.4rem; line-height: 1.25; }
.help-section h3 { margin: 0 0 var(--space-2); font-size: 1rem; }
.help-section p, .help-section ul, .help-section ol { margin-top: var(--space-2); }
.help-section li + li { margin-top: var(--space-1); }
.help-story p { margin: 0 0 var(--space-4); }
.help-story .story-lead { color: #24384b; font-size: 1.08rem; font-weight: 600; }
.how-it-works { max-width: none; }
.help-steps {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
  margin-bottom: 0;
  padding: 0;
  list-style: none;
  counter-reset: help-step;
}
.help-steps li {
  counter-increment: help-step;
  margin: 0;
  padding: var(--space-4);
  border: 1px solid #c9d6e2;
  border-radius: var(--radius-md);
  background: #f7fafc;
}
.help-steps li::before {
  content: counter(help-step);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  margin-bottom: var(--space-2);
  border-radius: 50%;
  background: var(--c-segment);
  color: #fff;
  font-weight: 700;
}
.help-steps strong, .help-steps span { display: block; }
.help-steps span { margin-top: var(--space-1); color: #3d4852; }
.compatibility-note {
  max-width: 48rem;
  padding: var(--space-3) var(--space-4);
  border-left: 4px solid var(--c-segment);
  background: #f3f7fb;
}
.device-compatibility-guidance { max-width: 48rem; margin-top: var(--space-4); }
.device-compatibility-guidance h3 { margin-bottom: var(--space-2); }
.device-compatibility-guidance p { margin: var(--space-2) 0 0; }
.device-guide-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-4); margin-top: var(--space-4); }
.device-guide-grid > section {
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fafbfc;
}
.device-guide-grid p:last-child, .device-guide-grid ul, .device-guide-grid ol { margin-bottom: 0; }
.faq-section { max-width: 52rem; }
.faq-section details {
  margin-top: var(--space-2);
  padding: 0 var(--space-3) var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
}
.faq-section details summary {
  display: list-item;
  min-height: var(--touch);
  padding: .65rem 0;
  cursor: pointer;
  font-weight: 600;
  color: #274d70;
}
.faq-section details p { margin: 0 0 var(--space-2); }
.privacy-section {
  max-width: 52rem;
  padding: var(--space-4);
  border-radius: var(--radius-sm);
  background: #f3f7fb;
}
.privacy-section ul { margin-bottom: 0; padding-left: 1.3rem; }
.privacy-disclaimer { margin: var(--space-3) 0 0; color: #596774; font-size: .88rem; }
.contact-section { max-width: 52rem; }
.contact-email-action { display: inline-flex; align-items: center; text-decoration: none; }
.device-feedback { margin: var(--space-3) 0 0; color: #4a5560; font-size: .92rem; }
.device-feedback a { color: #165a96; }
.information-view code { overflow-wrap: anywhere; word-break: break-word; }
.information-view h1:focus,
.help-section h2:focus {
  outline: var(--focus-ring);
  outline-offset: 4px;
}

/* Activity-file sourcing help uses the same restrained disclosure and help-card language as
   Help & About, while keeping the native details marker and keyboard behavior intact. */
.activity-file-guidance { margin: 0 0 var(--space-2); color: #444; }
.device-compatibility-help {
  margin: var(--space-2) 0;
  padding: 0;
  border: 0;
  color: #4b5965;
  font-size: .9rem;
}
.device-compatibility-help summary {
  display: list-item;
  min-height: var(--touch);
  padding: .45rem 0;
  color: #274d70;
  cursor: pointer;
  font-weight: 600;
}
.device-compatibility-help p { margin: 0 0 var(--space-2); }
.activity-file-help {
  margin-top: var(--space-2);
  padding: 0 var(--space-3) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #f7fafc;
}
.activity-file-help summary {
  display: list-item;
  min-height: var(--touch);
  padding: .65rem 0;
  cursor: pointer;
  color: #274d70;
  font-weight: 600;
}
.activity-source-method + .activity-source-method { margin-top: var(--space-3); }
.activity-source-method h3, .activity-source-method h4 { margin: 0 0 var(--space-1); }
.activity-source-method p { margin: 0 0 var(--space-2); }
.fit-only-note {
  margin: var(--space-3) 0 0;
  padding: var(--space-3);
  border-left: 4px solid #b7791f;
  background: #fff8e8;
  font-weight: 600;
}
.external-help-link {
  color: #165a96;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: .18em;
}
.activity-file-guide.help-section { max-width: none; margin-top: var(--space-5); }
.activity-source-list { padding-left: 1.4rem; }
.activity-file-guidance code,
.activity-file-help code,
.activity-file-guide code,
.external-help-link {
  overflow-wrap: anywhere;
  word-break: break-word;
}

button:focus-visible,
a:focus-visible,
input:focus-visible,
summary:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------------------
   Component styles shared by both workflows (originally added in Phase 7A Run 5 as an
   additive, not-yet-used foundation; live since Run 5/6, extended by Run 8's vertical
   workflow below). Fase 7A Run 8 checkpoint 11: the Run 5/6A horizontal-stepper family
   (nav.step-nav, ol.step-indicator, .step/.step-reason/.step.locked/.active/.done) and
   .summary-card are retired here - nothing in index.html or js/app.js's generated markup
   references them any more (renderVerticalSteps()/.vsteps below replaced both).
   --------------------------------------------------------------------------------------- */

.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: .5rem .75rem; margin: .5rem 0 0; }
.stat { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: .5rem .6rem; background: #f7f7f7; }
.stat dt { font-size: .72rem; color: #666; text-transform: uppercase; letter-spacing: .03em; margin: 0; }
.stat dd { margin: .1rem 0 0; font-weight: 600; font-size: .95rem; }

.review-filename-field { margin-top: .75rem; }
.review-filename-field label { display: block; font-weight: 600; }
.review-filename-field input { display: block; width: 100%; }
.field-error { color: var(--c-error); font-size: .9rem; margin: .25rem 0 0; }

.target-rides { display: grid; gap: .6rem; margin-top: .5rem; }
/* Fase 7A Run 5: 5 columns, not the 4 in the original Run 4 preparation - the real build-mode
   target-ride row keeps the existing "Becomes" preview column (build-target-slot-preview-N,
   already a kept data-testid) alongside Target ride/Ride/Name/Default, which the prototype's
   simplified mockup didn't show. */
/* Fase 7A Run 6A: 4 columns, not 5 - the "Becomes" column was removed (redundant with Name on
   device, and it exposed a raw "goal (8)" FIT enum string in normal UI). Freed width goes to
   Ride/Name on device, the two fields that most need it. */
.target-row {
  display: grid;
  grid-template-columns: 4.5rem minmax(10rem, 1.35fr) minmax(9rem, 1fr) 6rem 5.5rem;
  gap: .4rem 1rem;
  align-items: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: .6rem .75rem;
  background: #fff;
}
.target-row.header-row {
  background: #eee;
  font-size: .95rem;
  font-weight: 700;
  line-height: 1.25;
  padding: .55rem .75rem;
}
.target-field-label { display: none; font-size: .72rem; color: #666; text-transform: uppercase; letter-spacing: .03em; margin-bottom: .1rem; }
.target-field label { display: inline-flex; align-items: center; gap: .3rem; min-height: var(--touch); }
.target-field select, .target-field input[type="text"] { width: 100%; }
.target-ride-summary { display: grid; gap: .15rem; }
.target-ride-summary span:last-child { color: #555; font-size: .85rem; }

@media (max-width: 767px) {
  .ride-selection-heading { align-items: stretch; flex-direction: column; }
  .ride-selection-heading .btn { width: 100%; }
  .target-row.header-row { display: none; }
  .target-row { grid-template-columns: 1fr; }
  .target-field-label { display: block; }
  .target-field { padding: .3rem 0; border-bottom: 1px dashed #eee; }
  .target-field:last-child { border-bottom: none; }
}

.btn {
  display: inline-block;
  padding: .6rem 1.1rem;
  min-height: var(--touch);
  border-radius: var(--radius-sm);
  border: 1px solid #0b3d91;
  background: #0b3d91;
  color: #fff;
  font: inherit;
  font-weight: 600;
  font-size: .92rem;
  text-align: center;
  cursor: pointer;
}
.btn.secondary { background: #fff; color: #0b3d91; }
.btn[disabled] { background: #d8dee4; border-color: #c3cbd3; color: #7c8590; cursor: not-allowed; }

/* ---------------------------------------------------------------------------------------
   Fase 7A Run 8: the vertical workflow layout, ported from design/prototype-vertical.html
   (Run 7, approved) - #workspace, .workflow-col, .map-col, .map-frame, #map-empty, ol.vsteps
   and its descendants, .btn.full, .actions*, .gate-*, .filename-cell. Live since checkpoints
   3 (map region) and 4-6 (step skeleton and panels); the superseded horizontal-stepper
   family (nav.step-nav/.step/.summary-card) was retired in checkpoint 11, a few blocks above.
   --------------------------------------------------------------------------------------- */

#workspace {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
}
.workflow-col {
  /* .target-row's own @container rule further below reacts to THIS column's width, not the
     viewport - a 400px workflow column at a 1000px viewport still needs stacked target cards,
     which the existing 767px media query alone would not trigger. */
  container-type: inline-size;
  min-width: 0;
}
.map-col { min-width: 0; }
.map-frame { position: relative; margin-top: .5rem; }

@media (min-width: 1000px) {
  /* Threshold chosen for production (not the prototype's 960px container-query gallery value):
     at 1000px viewport width, available content width is min(1000, content-max) minus 2 * 1rem
     body padding = 968px, comfortably above the 520+420+16(gap) = 956px floor the two columns
     need (CLAUDE.md "Fase 7A Run 8" design decision - see the plan). */
  #workspace {
    grid-template-columns:
      minmax(var(--col-workflow-min), 55fr)
      minmax(var(--col-map-min), 45fr);
    grid-template-rows: max-content minmax(0, 1fr);
    column-gap: var(--space-4);
    row-gap: 0;
    align-items: start;
  }
  .workflow-col { grid-column: 1; }
  .workflow-pre-visual { grid-row: 1; }
  .workflow-post-visual { grid-row: 2; align-self: start; }
  .map-col {
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: flex-start;
  }
}

/* The combined map/profile column is sticky only when it fits a normal desktop-height viewport.
   Short desktop windows use ordinary page scrolling, never an internal visual-column scroller. */
@media (min-width: 1000px) and (min-height: 700px) {
  .map-col {
    position: sticky;
    top: var(--sticky-top);
  }
}

@media (max-width: 767px) {
  .global-header { align-items: stretch; flex-direction: column; gap: var(--space-2); }
  .header-nav { justify-content: flex-start; }
  .header-nav a { min-height: 2.5rem; }
  .help-local-nav { gap: 0 var(--space-3); }
}

@media (min-width: 768px) {
  .help-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .device-guide-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1000px) {
  .help-steps { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@container (max-width: 599px) {
  .target-row.header-row { display: none; }
  .target-row { grid-template-columns: 1fr; }
  .target-field-label { display: block; }
  .target-field { padding: .3rem 0; border-bottom: 1px dashed #eee; }
  .target-field:last-child { border-bottom: none; }
}

/* --- Map empty state ------------------------------------------------------------------- */
/* .map-frame wraps #map with no explicit height of its own, so it exactly matches #map's
   rendered box (its only in-flow child); #map-empty overlays that box via inset:0. Decorative
   only (no interactive content) - pointer-events:none in both states, and [hidden] (not a
   visibility/opacity toggle) is the actual mechanism that removes it from hit-testing and the
   tab order once a layer exists. The map keeps an explicit neutral background, so missing tiles
   still leave a usable ready-map surface behind this light message treatment. */
#map-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(233, 238, 242, .2);
  color: #314252;
  font-size: .9rem;
  text-align: center;
  padding: var(--space-2);
  pointer-events: none;
}
#map-empty > span {
  max-width: min(28rem, 90%);
  padding: .55rem .8rem;
  border: 1px solid rgba(92, 111, 128, .45);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, .9);
  box-shadow: 0 1px 3px rgba(28, 43, 56, .16);
}
#map-empty[hidden] { display: none; }

/* --- Vertical stepper -------------------------------------------------------------------- */

ol.vsteps { list-style: none; margin: 0 0 var(--space-4); padding: 0; }
#build-step-list { margin-bottom: 0; }
ol.vsteps-continuation { margin-top: var(--space-3); }
.vstep { position: relative; margin: 0 0 .75rem; }
.vstep:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 1.4rem;
  top: 2.9rem;
  bottom: -.75rem;
  width: 2px;
  background: var(--border);
  z-index: 0;
}
.vstep-head {
  all: unset;
  box-sizing: border-box;
  cursor: pointer;
  display: flex;
  gap: .6rem;
  align-items: flex-start;
  width: 100%;
  min-height: var(--touch);
  padding: .65rem .8rem .65rem 3rem;
  border-radius: var(--radius-sm);
  border: 1px solid #999;
  background: #fff;
  position: relative;
  z-index: 1;
  scroll-margin-top: var(--sticky-top);
}
.vstep-marker {
  position: absolute;
  left: .6rem;
  top: .5rem;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .8rem;
  font-weight: 700;
  border: 2px solid #999;
  background: #fff;
  color: #333;
  flex: none;
}
.vstep-text { display: flex; flex-direction: column; gap: .12rem; min-width: 0; }
.vstep-title { font-weight: 600; font-size: .93rem; color: #1a1a1a; }
.vstep-status { font-size: .8rem; color: #555; }
.vstep-reason { font-size: .78rem; color: #7c8590; }
.vstep-chevron { margin-left: auto; color: #999; flex: none; align-self: center; font-size: 1.1rem; }
.vstep-optional-tag {
  font-size: .68rem; font-weight: 600; color: #8a6d00; background: #fff3cd;
  padding: .05rem .4rem; border-radius: 999px; margin-left: .35rem; white-space: nowrap;
}

.vstep.available .vstep-head:hover { border-color: var(--c-segment); }
.vstep.locked .vstep-head { cursor: not-allowed; background: #f7f7f7; border-color: #e2e2e2; }
.vstep.locked .vstep-marker { background: #f2f2f2; border-color: #ddd; color: #949494; font-size: .85rem; }
.vstep.locked .vstep-title { color: #7c8590; }
.vstep.locked .vstep-chevron { visibility: hidden; }
.vstep.optional .vstep-marker { border-style: dashed; }
.vstep.active .vstep-head { border-color: var(--c-segment); background: #eef4fd; box-shadow: 0 0 0 1px var(--c-segment) inset; }
.vstep.active .vstep-marker { background: #0b3d91; border-color: #0b3d91; color: #fff; }
.vstep.done .vstep-marker { background: var(--c-valid); border-color: var(--c-valid); color: #fff; }
.vstep.done .vstep-head { border-color: #bfe2c0; }
/* A step that is both open (active) and already has a valid file (done) - a distinct "result"
   treatment, not blue-active-plus-green-check stacked (Run 7 correction, ported verbatim).
   Higher specificity (3 classes) than either .vstep.active or .vstep.done alone, so it always
   wins regardless of source order. */
.vstep.active.done .vstep-head { border-color: var(--c-valid); background: #f3faf3; box-shadow: 0 0 0 1px var(--c-valid) inset; }
.vstep.active.done .vstep-panel { border-top-color: var(--c-valid); }

.vstep-head:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }

.vstep-panel {
  margin: .5rem 0 0 3rem;
  padding: .8rem 1rem 1rem;
  border: 1px solid var(--border);
  border-top: 3px solid var(--c-segment);
  border-radius: var(--radius-sm);
  background: #fff;
}
.vstep-panel-continuation { margin-top: 0; }
.vstep-panel h3 { margin-top: 0; }
.vstep-intro { color: #444; margin: 0 0 .6rem; }

/* --- Action hierarchy ---------------------------------------------------------------------- */

.btn.full { display: block; width: 100%; }
.actions { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: .6rem; }
.actions-primary { margin-top: .75rem; }

.gate-status { font-weight: 600; margin: .6rem 0 .1rem; }
.gate-reason { color: #7c8590; font-size: .85rem; margin: 0 0 .5rem; }

.filename-cell { max-width: 14rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
