/*
 * Lens visual system: display (owner: lane V1d).
 *
 * Section, disclosure, surface, tables, rows, facts, state, tag, figure, change, empty states, job
 * state, legend, chart frame, map chrome and the answer block, on the tokens of system/tokens.css
 * only: no colour literal, no size below the type scale. Every component is shown in every state
 * by templates/design/display.html (/design). Contract: docs/web/visual-system-contract.md §4,
 * items 11–26. Behaviour: js/lens-section.js (hash and print open sections) and js/lens-more.js
 * (the problem table's "Show all N").
 */

/* ------------------------------------------------------------------ 11. section */

/* Open on the canvas: no border, no shadow; a hairline divides it from the next one. */
.lens-section {
  display: block;
  padding-block: var(--lens-sp-5);
  color: var(--lens-text);
}

.lens-section + .lens-section {
  border-top: 1px solid var(--lens-divider);
}

.lens-section__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--lens-sp-3);
  row-gap: var(--lens-sp-1);
  margin-bottom: var(--lens-sp-3);
}

.lens-section__title {
  margin: 0;
  font-size: var(--lens-fs-section);
  font-weight: var(--lens-fw-strong);
  line-height: 1.3;
  color: var(--lens-heading);
}

.lens-section__summary {
  margin: 0;
  font-size: var(--lens-fs-body);
  color: var(--lens-text-muted);
}

.lens-section__body > :last-child {
  margin-bottom: 0;
}

/* Collapsible (D2): <details class="lens-section"> with <summary class="lens-section__head">. */
details.lens-section > summary.lens-section__head {
  margin-bottom: 0;
  cursor: pointer;
  list-style: none;
  border-radius: var(--lens-r-s);
}

details.lens-section > summary.lens-section__head::-webkit-details-marker {
  display: none;
}

/* The chevron points right when closed and down when open; drawn from borders in currentColor. */
details.lens-section > summary.lens-section__head::before {
  content: "";
  flex: none;
  align-self: center;
  width: var(--lens-sp-2);
  height: var(--lens-sp-2);
  margin-inline: var(--lens-sp-1) var(--lens-sp-1);
  border-right: 2px solid var(--lens-text-muted);
  border-bottom: 2px solid var(--lens-text-muted);
  transform: rotate(-45deg);
  transition: transform var(--lens-duration) var(--lens-ease);
}

details.lens-section[open] > summary.lens-section__head::before {
  transform: rotate(45deg);
}

details.lens-section > summary.lens-section__head:hover .lens-section__title {
  color: var(--lens-link-hover);
}

details.lens-section > summary.lens-section__head:focus-visible,
details.lens-disclosure > summary:focus-visible {
  outline: 2px solid var(--lens-focus);
  outline-offset: 2px;
}

details.lens-section[open] > summary.lens-section__head {
  margin-bottom: var(--lens-sp-3);
}

/* ------------------------------------------------------------------ 12. disclosure */

.lens-disclosure {
  margin-block: var(--lens-sp-3);
  font-size: var(--lens-fs-body);
}

.lens-disclosure > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--lens-sp-2);
  cursor: pointer;
  list-style: none;
  color: var(--lens-link);
  border-radius: var(--lens-r-s);
}

.lens-disclosure > summary::-webkit-details-marker {
  display: none;
}

.lens-disclosure > summary::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform var(--lens-duration) var(--lens-ease);
}

.lens-disclosure[open] > summary::before {
  transform: rotate(45deg);
}

.lens-disclosure > summary:hover {
  color: var(--lens-link-hover);
  text-decoration: underline;
}

.lens-disclosure__body {
  margin-top: var(--lens-sp-2);
  color: var(--lens-text-muted);
  max-width: 72ch;
}

.lens-disclosure__body > :last-child {
  margin-bottom: 0;
}

/* ------------------------------------------------------------------ 13. surface */

/* A bounded working object (a map, an operable chart, a form): a border, never a shadow. */
.lens-surface {
  background: var(--lens-surface);
  border: 1px solid var(--lens-border);
  border-radius: var(--lens-r-m);
  padding: var(--lens-sp-4);
  color: var(--lens-text);
}

.lens-surface--form {
  padding: var(--lens-sp-6);
}

@media (max-width: 640px) {
  .lens-surface--form {
    padding: var(--lens-sp-4);
  }
}

/* ------------------------------------------------------------------ 14. table */

.lens-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--lens-fs-body);
  color: var(--lens-text);
  background: transparent;
}

.lens-table caption {
  caption-side: top;
  padding: 0 0 var(--lens-sp-2);
  font-size: var(--lens-fs-meta);
  color: var(--lens-text-muted);
  text-align: left;
}

/* Sentence-case headers at the meta size; never uppercase. */
.lens-table th {
  padding: var(--lens-sp-2) var(--lens-sp-3);
  font-size: var(--lens-fs-meta);
  font-weight: var(--lens-fw-medium);
  color: var(--lens-text-muted);
  text-align: left;
  text-transform: none;
  letter-spacing: normal;
  vertical-align: bottom;
  white-space: nowrap;
  border-bottom: 1px solid var(--lens-border-strong);
}

.lens-table td {
  padding: var(--lens-sp-2) var(--lens-sp-3);
  vertical-align: top;
  border-bottom: 1px solid var(--lens-divider);
}

.lens-table th:first-child,
.lens-table td:first-child {
  padding-left: 0;
}

.lens-table th:last-child,
.lens-table td:last-child {
  padding-right: 0;
}

.lens-table tbody tr:hover {
  background: var(--lens-hover);
}

.lens-table tbody tr[aria-selected="true"] {
  background: var(--lens-selected);
}

.lens-table .lens-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* A sortable header: its words are a button, and the th's aria-sort draws the direction (lane V2b). */
.lens-table__sort {
  display: inline-flex;
  align-items: center;
  gap: var(--lens-sp-1);
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: inherit;
  cursor: pointer;
}

.lens-table__sort:hover {
  color: var(--lens-link-hover);
}

.lens-table__sort:focus-visible {
  outline: 2px solid var(--lens-focus);
  outline-offset: 2px;
  border-radius: var(--lens-r-s);
}

.lens-table__sort::after {
  content: "";
  border-inline: 4px solid transparent;
}

.lens-table th[aria-sort="ascending"] > .lens-table__sort::after {
  border-bottom: 5px solid currentColor;
}

.lens-table th[aria-sort="descending"] > .lens-table__sort::after {
  border-top: 5px solid currentColor;
}

/* Tier 2: the table scrolls inside its own frame; the page never scrolls sideways. */
.lens-table-wrap {
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.lens-table-wrap > .lens-table td {
  white-space: nowrap;
}

/* Tier 1: each row stacks as label and value pairs (td[data-label]) on a phone. */
@media (max-width: 640px) {
  .lens-table--stack,
  .lens-table--stack tbody,
  .lens-table--stack tr,
  .lens-table--stack td {
    display: block;
    width: 100%;
  }

  .lens-table--stack thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .lens-table--stack tr {
    padding-block: var(--lens-sp-3);
    border-bottom: 1px solid var(--lens-divider);
  }

  .lens-table--stack td,
  .lens-table--stack td:first-child,
  .lens-table--stack td:last-child,
  .lens-table--stack td.lens-num {
    padding: var(--lens-sp-1) 0;
    border-bottom: 0;
    text-align: left;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .lens-table--stack td[data-label] {
    display: grid;
    grid-template-columns: minmax(6.5rem, 38%) minmax(0, 1fr);
    column-gap: var(--lens-sp-3);
  }

  .lens-table--stack td[data-label]::before {
    content: attr(data-label);
    font-size: var(--lens-fs-meta);
    color: var(--lens-text-muted);
  }

  /* A cell without a label is the row's title (its name). */
  .lens-table--stack td:not([data-label]) {
    font-weight: var(--lens-fw-medium);
  }
}

/* The problem table: rows past the first N wait behind "Show all N" (js/lens-more.js). */
[data-lens-extra]:not([data-lens-shown]) {
  display: none;
}

.lens-more {
  display: inline-flex;
  align-items: center;
  gap: var(--lens-sp-1);
  margin-top: var(--lens-sp-2);
  padding: var(--lens-sp-1) 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--lens-fs-body);
  color: var(--lens-link);
  cursor: pointer;
}

.lens-more:hover {
  color: var(--lens-link-hover);
  text-decoration: underline;
}

.lens-more:focus-visible {
  outline: 2px solid var(--lens-focus);
  outline-offset: 2px;
  border-radius: var(--lens-r-s);
}

/* A repeated name carries where it is: "Corridor  Main · Floor 2". */
.lens-qualified__where {
  margin-left: var(--lens-sp-1);
  font-size: var(--lens-fs-meta);
  font-weight: var(--lens-fw-regular);
  color: var(--lens-text-muted);
}

/* ------------------------------------------------------------------ 15. rows */

.lens-rows {
  margin: 0;
  padding: 0;
  list-style: none;
}

.lens-row {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr) auto;
  align-items: start;
  gap: var(--lens-sp-4);
  padding-block: var(--lens-sp-3);
  border-bottom: 1px solid var(--lens-divider);
}

.lens-row__main {
  min-width: 0;
}

.lens-row__title {
  margin: 0;
  font-size: var(--lens-fs-object);
  font-weight: var(--lens-fw-strong);
  color: var(--lens-heading);
  overflow-wrap: anywhere;
}

.lens-row__text {
  margin: var(--lens-sp-1) 0 0;
  color: var(--lens-text-muted);
}

.lens-row__facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--lens-sp-1) var(--lens-sp-4);
  margin: 0;
  font-size: var(--lens-fs-meta);
  color: var(--lens-text-muted);
}

.lens-row__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--lens-sp-2);
}

@media (max-width: 640px) {
  .lens-row {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--lens-sp-2);
  }

  .lens-row__actions {
    justify-content: flex-start;
  }
}

/* ------------------------------------------------------------------ 16. facts and summary strip */

.lens-facts {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--lens-sp-2) var(--lens-sp-5);
  margin: 0;
}

.lens-facts > dt {
  font-size: var(--lens-fs-meta);
  font-weight: var(--lens-fw-regular);
  color: var(--lens-text-muted);
}

.lens-facts > dd {
  margin: 0;
  color: var(--lens-text);
  overflow-wrap: anywhere;
}

@media (max-width: 640px) {
  .lens-facts {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0;
  }

  .lens-facts > dd {
    margin-bottom: var(--lens-sp-2);
  }
}

/* Divided by rules, never tiles. */
.lens-summary {
  display: flex;
  flex-wrap: wrap;
  row-gap: var(--lens-sp-3);
  margin-block: var(--lens-sp-3);
}

.lens-summary__item {
  display: flex;
  flex-direction: column;
  gap: var(--lens-sp-1);
  min-width: 0;
  padding-inline: var(--lens-sp-5);
  border-left: 1px solid var(--lens-divider);
}

.lens-summary__item:first-child {
  padding-left: 0;
  border-left: 0;
}

.lens-summary__label {
  font-size: var(--lens-fs-meta);
  color: var(--lens-text-muted);
  text-transform: none;
}

.lens-summary__value {
  font-size: var(--lens-fs-object);
  font-weight: var(--lens-fw-medium);
  color: var(--lens-heading);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

@media (max-width: 640px) {
  .lens-summary {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--lens-sp-3) var(--lens-sp-4);
  }

  .lens-summary__item,
  .lens-summary__item:first-child {
    padding: 0;
    border: 0;
  }
}

/* ------------------------------------------------------------------ 17. state (D1) */

/* A dot and a word; the word is always visible, the dot is decoration. */
.lens-state {
  --dot: var(--lens-neutral);
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  color: var(--lens-text);
  white-space: nowrap;
}

.lens-state::before {
  content: "";
  flex: none;
  box-sizing: border-box;
  width: 0.6em;
  height: 0.6em;
  border: 1.5px solid var(--dot);
  border-radius: 50%;
  background: var(--dot);
}

.lens-state--good {
  --dot: var(--lens-good);
  color: var(--lens-good-ink);
}

.lens-state--watch {
  --dot: var(--lens-watch);
  color: var(--lens-watch-ink);
}

.lens-state--action {
  --dot: var(--lens-action);
  color: var(--lens-action-ink);
}

.lens-state--none,
.lens-state--stale,
.lens-state--inferred,
.lens-state--neutral {
  --dot: var(--lens-neutral);
  color: var(--lens-neutral-ink);
}

.lens-state--info {
  --dot: var(--lens-info);
  color: var(--lens-info-ink);
}

/* Too little evidence: a hollow dot. */
.lens-state--none::before {
  background: transparent;
}

/* Stale: hollow and dashed. */
.lens-state--stale::before {
  width: 0.7em;
  height: 0.7em;
  background: transparent;
  border-style: dashed;
}

/* Inferred: half a dot. */
.lens-state--inferred::before {
  background: linear-gradient(90deg, var(--dot) 50%, transparent 50%);
}

/* ------------------------------------------------------------------ 18. tag */

/* Classification, never state: neutral, no dot. */
.lens-tag {
  display: inline-block;
  padding: 0 var(--lens-sp-2);
  border: 1px solid var(--lens-border);
  border-radius: var(--lens-r-pill);
  background: var(--lens-surface-subtle);
  font-size: var(--lens-fs-meta);
  line-height: 1.6;
  color: var(--lens-text);
  white-space: nowrap;
  vertical-align: baseline;
}

.lens-tag--mono {
  font-family: var(--lens-font-mono);
  border-radius: var(--lens-r-s);
}

/* A long unbroken value (a revision hash) breaks anywhere instead of widening the page: on a
   tag or a state, which keep to one line otherwise */
.lens-break {
  max-width: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* ------------------------------------------------------------------ 19. figure */

.lens-figure {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 0.15em;
  color: var(--lens-heading);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.lens-figure__value {
  font-size: var(--lens-fs-figure-m);
  font-weight: var(--lens-fw-strong);
  letter-spacing: -0.01em;
}

.lens-figure__unit {
  font-size: var(--lens-fs-lead);
  font-weight: var(--lens-fw-medium);
  color: var(--lens-text-muted);
}

.lens-figure--s .lens-figure__value {
  font-size: var(--lens-fs-figure-s);
}

.lens-figure--s .lens-figure__unit {
  font-size: var(--lens-fs-body);
}

.lens-figure--l .lens-figure__value {
  font-size: var(--lens-fs-figure-l);
}

.lens-figure--l .lens-figure__unit {
  font-size: var(--lens-fs-section);
}

/* The denominator and recency, on its own line under the number. */
.lens-figure__note {
  flex-basis: 100%;
  margin-top: var(--lens-sp-1);
  font-size: var(--lens-fs-meta);
  font-weight: var(--lens-fw-regular);
  line-height: 1.4;
  color: var(--lens-text-muted);
}

/* Provisional: a measured subset, never a verdict; neutral ink. */
.lens-figure--provisional,
.lens-figure--provisional .lens-figure__unit {
  color: var(--lens-neutral-ink);
}

/* An empty figure (nothing computable) reads as a dash in muted ink, never a zero. */
.lens-figure__value:empty::before {
  content: "\2014";
  color: var(--lens-text-muted);
}

/* ------------------------------------------------------------------ 20. change */

.lens-change {
  margin: 0;
  font-size: var(--lens-fs-body);
  color: var(--lens-text-muted);
  font-variant-numeric: tabular-nums;
}

.lens-change--better {
  color: var(--lens-good-ink);
}

.lens-change--worse {
  color: var(--lens-action-ink);
}

.lens-change--flat {
  color: var(--lens-text-muted);
}

/* The direction is an icon at the line's size and in its colour, never a glyph in the text (a
   small triangle at body size reads as a dot). Decorative: the sentence says higher, lower or no
   clear change. A span inside a line ("· +13 pts") gets it too. */
:is(.lens-change--better, .lens-change--worse, .lens-change--flat)::before {
  display: inline-block;
  margin-inline-end: 0.3em;
  font-family: bootstrap-icons;
  font-size: 1em;
  line-height: 1;
  vertical-align: -0.125em;
}

.lens-change--better::before {
  content: "\f144" / "";
}

.lens-change--worse::before {
  content: "\f123" / "";
}

.lens-change--flat::before {
  content: "\f63b" / "";
}

/* Inside a line it takes the line's size. */
span.lens-change {
  font-size: inherit;
  white-space: nowrap;
}

/* ------------------------------------------------------------------ 21. empty */

/* Explicit sentence, reason and next step; never a zero, never a success colour. */
.lens-empty {
  padding: var(--lens-sp-5);
  border: 1px dashed var(--lens-border);
  border-radius: var(--lens-r-m);
  color: var(--lens-text);
}

.lens-empty__title {
  display: flex;
  align-items: center;
  gap: var(--lens-sp-2);
  margin: 0;
  font-size: var(--lens-fs-object);
  font-weight: var(--lens-fw-strong);
  color: var(--lens-heading);
}

.lens-empty__why {
  margin: var(--lens-sp-2) 0 0;
  color: var(--lens-text-muted);
  max-width: 72ch;
}

.lens-empty__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--lens-sp-2);
  margin-top: var(--lens-sp-4);
}

/* Too little evidence: the hollow dot of lens-state--none before the title. */
.lens-empty--insufficient .lens-empty__title::before {
  content: "";
  flex: none;
  box-sizing: border-box;
  width: 0.6em;
  height: 0.6em;
  border: 1.5px solid var(--lens-neutral);
  border-radius: 50%;
}

/* ------------------------------------------------------------------ 22. job state */

.lens-job {
  --dot: var(--lens-neutral);
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--lens-sp-1) 0.45em;
  color: var(--lens-text);
}

.lens-job::before {
  content: "";
  flex: none;
  box-sizing: border-box;
  width: 0.6em;
  height: 0.6em;
  border-radius: 50%;
  background: var(--dot);
}

.lens-job--running {
  --dot: var(--lens-info);
  color: var(--lens-info-ink);
}

.lens-job--running::before {
  animation: lens-job-pulse 1.4s ease-in-out infinite;
}

.lens-job--ready {
  --dot: var(--lens-good);
  color: var(--lens-good-ink);
}

.lens-job--failed {
  --dot: var(--lens-action);
  color: var(--lens-action-ink);
}

.lens-job__reason {
  color: var(--lens-text-muted);
}

.lens-job .btn {
  margin-left: var(--lens-sp-2);
}

@keyframes lens-job-pulse {
  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.3;
  }
}

@media (prefers-reduced-motion: reduce) {
  .lens-job--running::before {
    animation: none;
  }
}

/* ------------------------------------------------------------------ 23. legend */

.lens-legend {
  display: inline-flex;
  flex-direction: column;
  gap: var(--lens-sp-1);
  max-width: 100%;
  font-size: var(--lens-fs-meta);
  color: var(--lens-text);
}

.lens-legend__title {
  font-weight: var(--lens-fw-medium);
  color: var(--lens-text);
}

/* A stepped ramp: one span per step, each with style="--swatch: var(--lens-band-…)". */
.lens-legend__ramp,
.lens-legend__ticks {
  display: grid;
  grid-template-columns: repeat(var(--steps, 5), minmax(2.75rem, 1fr));
}

.lens-legend__ramp {
  height: var(--lens-sp-3);
  border-radius: var(--lens-r-s);
  overflow: hidden;
}

.lens-legend__ramp > span {
  background: var(--swatch, transparent);
}

/* Ticks sit on the boundaries between steps: the first one on the boundary after step one. */
.lens-legend__ticks > span {
  color: var(--lens-text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  transform: translateX(-50%);
}

.lens-legend__ticks > span:first-child {
  grid-column-start: 2;
}

.lens-legend__items,
.lens-legend__keys {
  display: flex;
  flex-wrap: wrap;
  gap: var(--lens-sp-1) var(--lens-sp-4);
}

.lens-legend__keys {
  margin-top: var(--lens-sp-1);
}

.lens-legend__item {
  display: inline-flex;
  align-items: center;
  gap: var(--lens-sp-2);
  white-space: nowrap;
}

.lens-legend__swatch {
  flex: none;
  box-sizing: border-box;
  width: 0.9em;
  height: 0.9em;
  border: 1px solid var(--lens-border);
  border-radius: 2px;
  background: var(--swatch, var(--lens-surface-subtle));
}

/* Too few readings: the "none" key is drawn hatched, as the map draws it. */
.lens-legend__swatch--none {
  background: repeating-linear-gradient(
    45deg,
    var(--lens-band-none) 0 2px,
    transparent 2px 5px
  );
}

/* ------------------------------------------------------------------ 24. chart */

/* Scripts draw with classes only; these rules colour the marks, so charts carry no colours. */
.lens-chart {
  margin: 0;
  max-width: 100%;
}

.lens-chart svg {
  display: block;
  width: 100%;
  overflow: visible;
  font-family: var(--lens-font-ui);
}

.lens-chart-axis {
  stroke: var(--lens-chart-axis);
  stroke-width: 1;
  fill: none;
  vector-effect: non-scaling-stroke;
}

.lens-chart-grid {
  stroke: var(--lens-chart-grid);
  stroke-width: 1;
  fill: none;
  vector-effect: non-scaling-stroke;
}

.lens-chart-label {
  fill: var(--lens-chart-label);
  font-size: var(--lens-fs-meta);
  font-variant-numeric: tabular-nums;
}

.lens-chart-series-1 {
  color: var(--lens-chart-series-1);
}

.lens-chart-series-2 {
  color: var(--lens-chart-series-2);
}

.lens-chart-series-3 {
  color: var(--lens-chart-series-3);
}

.lens-chart-series-4 {
  color: var(--lens-chart-series-4);
}

.lens-chart-compare {
  color: var(--lens-chart-compare);
}

/* A series is filled as a bar, area or point, and stroked as a line. */
.lens-chart :is(rect, circle):is(.lens-chart-series-1, .lens-chart-series-2,
.lens-chart-series-3, .lens-chart-series-4, .lens-chart-compare) {
  fill: currentColor;
  stroke: none;
}

.lens-chart :is(line, path, polyline):is(.lens-chart-series-1, .lens-chart-series-2,
.lens-chart-series-3, .lens-chart-series-4, .lens-chart-compare) {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.lens-chart :is(line, path, polyline).lens-chart-compare {
  stroke-dasharray: 4 3;
}

.lens-chart-threshold {
  stroke: var(--lens-chart-threshold);
  stroke-width: 1.5;
  stroke-dasharray: 6 4;
  fill: none;
  vector-effect: non-scaling-stroke;
}

.lens-chart-threshold-band {
  fill: var(--lens-chart-threshold-band);
  stroke: none;
}

.lens-chart-mark {
  fill: var(--lens-chart-mark);
  stroke: var(--lens-surface);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}

.lens-chart__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--lens-sp-1) var(--lens-sp-4);
  margin-top: var(--lens-sp-2);
  font-size: var(--lens-fs-meta);
  color: var(--lens-text);
}

/* A series key: a short line of the series' colour. */
.lens-chart__key {
  display: inline-flex;
  align-items: center;
  gap: var(--lens-sp-2);
}

.lens-chart__key::before {
  content: "";
  width: var(--lens-sp-4);
  border-top: 3px solid currentColor;
}

.lens-chart__key.lens-chart-compare::before {
  border-top-style: dashed;
}

.lens-chart__key.lens-chart-threshold::before {
  border-top: 2px dashed var(--lens-chart-threshold);
}

.lens-chart__key > span {
  color: var(--lens-text);
}

.lens-chart__caption {
  margin-top: var(--lens-sp-2);
  font-size: var(--lens-fs-meta);
  color: var(--lens-text-muted);
}

/* A visible, draggable scroll track under a wide table (js/lens-hscroll.js): a native horizontal
   scrollbar can overlay the last row and vanish at rest. */
.lens-hbar {
  position: relative;
  width: 100%;
  height: 12px;
  margin: var(--lens-sp-2) 0 var(--lens-sp-1);
  border: 1px solid var(--lens-border);
  border-radius: var(--lens-r-pill);
  background: var(--lens-surface-subtle);
  cursor: grab;
  touch-action: none;
}
.lens-hbar[hidden] { display: none !important; }
.lens-hbar.is-held { cursor: grabbing; }
.lens-hbar:focus-visible { outline: 2px solid var(--lens-focus); outline-offset: 2px; }
.lens-hbar__thumb {
  position: absolute;
  top: 1px;
  bottom: 1px;
  left: 0;
  min-width: 34px;
  border-radius: var(--lens-r-pill);
  background: var(--lens-border-strong);
}
.lens-hbar:hover .lens-hbar__thumb,
.lens-hbar.is-held .lens-hbar__thumb { background: var(--lens-text-muted); }
.lens-hbar-host { scrollbar-width: none; }
.lens-hbar-host::-webkit-scrollbar { display: none; }

/* ------------------------------------------------------------------ 25. map chrome */

.lens-map {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--lens-surface);
  border: 1px solid var(--lens-border);
  border-radius: var(--lens-r-m);
  overflow: hidden;
}

.lens-map__toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--lens-sp-2) var(--lens-sp-4);
  padding: var(--lens-sp-2) var(--lens-sp-3);
  border-bottom: 1px solid var(--lens-divider);
  background: var(--lens-surface);
}

.lens-map__tools {
  display: flex;
  gap: var(--lens-sp-2);
  margin-left: auto;
}

/* The floor rail: one button per floor, aria-pressed on the shown one; it scrolls inside itself. */
.lens-map__floors {
  display: flex;
  gap: var(--lens-sp-1);
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: thin;
}

.lens-map__floor {
  flex: none;
  min-width: 2.5rem;
  padding: var(--lens-sp-1) var(--lens-sp-2);
  border: 1px solid var(--lens-border);
  border-radius: var(--lens-r-s);
  background: var(--lens-surface);
  font: inherit;
  font-size: var(--lens-fs-meta);
  font-variant-numeric: tabular-nums;
  color: var(--lens-text);
  cursor: pointer;
}

.lens-map__floor:hover {
  background: var(--lens-hover);
}

.lens-map__floor[aria-pressed="true"] {
  border-color: var(--lens-primary);
  background: var(--lens-selected);
  color: var(--lens-heading);
  font-weight: var(--lens-fw-strong);
}

.lens-map__floor:focus-visible {
  outline: 2px solid var(--lens-focus);
  outline-offset: 1px;
}

/* The drawing area (Leaflet's container or an SVG plan). */
.lens-map__canvas {
  position: relative;
  /* Its own stacking context: the legend, floor rail and breadcrumb drawn over the map (z-index
     up to 500, above Leaflet's panes) stay inside the map instead of painting over the sticky shell
     when the page scrolls. The full-screen map is outside the canvas and still goes above all. */
  isolation: isolate;
  flex: 1 1 auto;
  min-height: 320px;
  background: var(--lens-surface-subtle);
}

.lens-map__crumb {
  position: absolute;
  top: var(--lens-sp-3);
  left: var(--lens-sp-3);
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--lens-sp-1);
  max-width: calc(100% - 2 * var(--lens-sp-3));
  margin: 0;
  padding: var(--lens-sp-1) var(--lens-sp-2);
  list-style: none;
  border: 1px solid var(--lens-border);
  border-radius: var(--lens-r-s);
  background: var(--lens-surface-raised);
  font-size: var(--lens-fs-meta);
  color: var(--lens-text-muted);
}

.lens-map__crumb > li + li::before {
  content: "\203A";
  margin-right: var(--lens-sp-1);
  color: var(--lens-text-muted);
}

.lens-map__crumb [aria-current] {
  color: var(--lens-heading);
  font-weight: var(--lens-fw-medium);
}

.lens-map__legend {
  position: absolute;
  bottom: var(--lens-sp-3);
  left: var(--lens-sp-3);
  z-index: 2;
  max-width: calc(100% - 2 * var(--lens-sp-3));
  padding: var(--lens-sp-2) var(--lens-sp-3);
  border: 1px solid var(--lens-border);
  border-radius: var(--lens-r-s);
  background: var(--lens-surface-raised);
}

/* The tooltip, also on a Leaflet tooltip given the class. */
.lens-map-tip,
.leaflet-tooltip.lens-map-tip {
  max-width: 18rem;
  padding: var(--lens-sp-2) var(--lens-sp-3);
  border: 1px solid var(--lens-border);
  border-radius: var(--lens-r-m);
  background: var(--lens-surface-raised);
  box-shadow: var(--lens-shadow-overlay);
  font-family: var(--lens-font-ui);
  font-size: var(--lens-fs-meta);
  line-height: 1.45;
  color: var(--lens-text);
  white-space: normal;
}

.lens-map-tip__title {
  display: block;
  font-size: var(--lens-fs-body);
  font-weight: var(--lens-fw-strong);
  color: var(--lens-heading);
}

.leaflet-tooltip-top.lens-map-tip::before {
  border-top-color: var(--lens-border);
}

.leaflet-tooltip-bottom.lens-map-tip::before {
  border-bottom-color: var(--lens-border);
}

.leaflet-tooltip-left.lens-map-tip::before {
  border-left-color: var(--lens-border);
}

.leaflet-tooltip-right.lens-map-tip::before {
  border-right-color: var(--lens-border);
}

/* Full screen: the map covers the page, above the shell. */
.lens-map--full {
  position: fixed;
  inset: 0;
  z-index: var(--lens-z-overlay);
  border: 0;
  border-radius: 0;
  box-shadow: var(--lens-shadow-overlay);
}

.lens-map--full .lens-map__canvas {
  min-height: 0;
}

/* ------------------------------------------------------------------ 26. answer */

.lens-answer {
  display: grid;
  gap: var(--lens-sp-2);
  padding-block: var(--lens-sp-4) var(--lens-sp-5);
}

.lens-answer__sentence {
  margin: 0;
  max-width: 60ch;
  font-size: var(--lens-fs-lead);
  font-weight: var(--lens-fw-medium);
  line-height: 1.45;
  color: var(--lens-heading);
}

.lens-answer__notes {
  margin: var(--lens-sp-1) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--lens-fs-meta);
  color: var(--lens-text-muted);
}

.lens-answer__notes > li + li {
  margin-top: var(--lens-sp-1);
}

/* ------------------------------------------------------------------ print */

/* Every row prints; the "Show all" button does not (sections are opened by js/lens-section.js). */
@media print {
  [data-lens-extra]:not([data-lens-shown]) {
    display: revert;
  }

  .lens-more,
  .lens-map__toolbar {
    display: none;
  }
}

/* ------------------------------------------------------------------ reach preview */

/* How far a change reaches before it is saved (design 7.11; fragments/reach-preview.html). */
.lens-reach {
  margin: 0 0 var(--lens-sp-3);
  padding: var(--lens-sp-3) var(--lens-sp-4);
  border: 1px solid var(--lens-border);
  border-radius: var(--lens-r-m);
  background: var(--lens-surface);
}
.lens-reach p { margin: 0; }
.lens-reach p + p { margin-top: var(--lens-sp-1); }
.lens-reach__figure { font-size: var(--lens-fs-lead); font-weight: var(--lens-fw-medium); color: var(--lens-heading); }

/* A row of tags (deployments, dimension values, locations): wraps, with a gap. */
.lens-tags { display: flex; flex-wrap: wrap; gap: var(--lens-sp-1); align-items: center; }

/* A list of what a destructive change deletes or keeps (a location's deletion). */
.lens-deletion { margin: 0 0 var(--lens-sp-4); padding-left: var(--lens-sp-5); }
.lens-step > * + * { margin-top: var(--lens-sp-3); }
