/*
 * styles.css — the "drafting sheet" design system.
 *
 * Visual identity: an architect's / surveyor's drawing sheet. Hard edges,
 * hairline rules, mono uppercase micro-labels, and a single hard offset
 * shadow (no soft glows). Surveyor-orange is used sparingly for selection
 * and calls-to-action.
 */

/* ------------------------------------------------------------------ */
/* Tokens                                                            */
/* ------------------------------------------------------------------ */
:root {
  --ink: #182433;        /* primary text / lines */
  --paper: #ECEFF2;      /* drafting paper background */
  --hairline: #C6CDD4;   /* fine rules and borders */
  --accent: #FF5A36;     /* surveyor orange — selection + CTA only */

  --ink-soft: #4a5a6b;   /* muted ink for secondary text */
  --panel-bg: #ECEFF2;

  --font-display: "Big Shoulders Display", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", monospace;
  --font-sans: "IBM Plex Sans", system-ui, sans-serif;

  --shadow-offset: 6px 6px 0 var(--ink); /* the hard drafting-block shadow */
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  height: 100%;
  font-family: var(--font-sans);
  color: var(--ink);
  background: var(--paper);
}

#map {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* ------------------------------------------------------------------ */
/* First-visit splash                                                 */
/* ------------------------------------------------------------------ */
.splash {
  position: fixed;
  inset: 0;
  z-index: 50; /* over everything, including the mobile parcel sheet (20) */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(24, 36, 51, 0.55);
  overflow-y: auto;
}
.splash[hidden] {
  display: none; /* `display: flex` above would otherwise defeat [hidden] */
}
.splash-panel {
  width: 100%;
  max-width: 420px;
  margin: auto; /* keeps it centred when it's taller than the viewport */
  padding: 20px 22px 22px;
  background: var(--panel-bg);
  border: 1.5px solid var(--ink);
  box-shadow: var(--shadow-offset);
}
.splash-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 27px;
  line-height: 1.02;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 10px;
}
.splash-panel p {
  font-family: var(--font-sans);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink);
  margin: 0 0 10px;
}
/* The screenshot, shown whole. It's landscape at roughly the proportions
   this slot wants, so no cropping is needed — an earlier portrait stand-in
   had to be cropped to a band with object-position, which a replacement
   image would have had to re-tune. */
.splash-shot {
  display: block;
  width: 100%;
  height: auto;
  margin: 14px 0 16px;
  border: 1px solid var(--hairline);
}
.splash-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}
.splash-actions .tb-button {
  width: 100%;
  padding: 11px 18px;
}
.splash-actions a {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: var(--hairline);
}
.splash-actions a:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}

/* ------------------------------------------------------------------ */
/* Zoom hint — floats over the map below the parcel layers' minzoom   */
/* ------------------------------------------------------------------ */
/* Same block language as the title panel (paper, ink rule, hard offset
   shadow) so it reads as part of the sheet rather than a browser alert,
   just smaller. `pointer-events: none` so it never eats a map drag. */
.map-hint {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 5; /* over the map, under .title-block (10) */

  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  padding: 9px 13px;

  background: var(--panel-bg);
  border: 1.5px solid var(--ink);
  box-shadow: 3px 3px 0 var(--ink);

  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.3;
  color: var(--ink);
  pointer-events: none;
}
.map-hint::before {
  content: "+";
  font-weight: 600;
  color: var(--ink-soft);
}
/* `display: flex` above beats the browser's default `[hidden]{display:none}`,
   which otherwise leaves the "+" marker on screen once the hint is hidden. */
.map-hint[hidden] {
  display: none;
}

/* ------------------------------------------------------------------ */
/* Title block (the corner-of-the-sheet panel)                       */
/* ------------------------------------------------------------------ */
.title-block {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 10;
  width: 340px;
  max-width: calc(100vw - 40px);

  background: var(--panel-bg);
  border: 1.5px solid var(--ink);
  box-shadow: var(--shadow-offset);

  /* Never let the panel run off the bottom of the window. `auto` means the
     scrollbar only appears when the content actually exceeds the space —
     on most parcels it never does. This is the backstop that keeps the page
     itself from scrolling as panel content grows; the compact state above
     is what keeps it from being needed. Reset on mobile, where the panel is
     a top bar and the parcel detail is its own fixed sheet. */
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  /* Nothing in a fixed-width panel should ever scroll sideways. Explicit,
     because `overflow-y: auto` alone makes overflow-x scrollable too, so
     any element that overhangs the edge produces a horizontal scrollbar. */
  overflow-x: hidden;
}

/* Each cell is a bordered block, stacked with shared hairline rules. */
.tb-cell {
  padding: 12px 14px;
  border-bottom: 1px solid var(--hairline);
}
.tb-cell:last-child {
  border-bottom: none;
}

/* Mono uppercase micro-label — the little field titles on a drawing block. */
.tb-microlabel {
  display: block;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 6px;
}

/* Wordmark cell */
.tb-wordmark-cell {
  background: var(--ink);
  border-bottom: 1.5px solid var(--ink);
}
.tb-wordmark-cell .tb-microlabel {
  color: rgba(236, 239, 242, 0.6);
}
.tb-wordmark {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 30px;
  line-height: 0.98;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--paper);
  margin: 0;
}
/* .tb-sheetline lives on the About page header only — see
   `.about-header .tb-sheetline` further down. */

/* ------------------------------------------------------------------ */
/* Search                                                            */
/* ------------------------------------------------------------------ */
.tb-search-row {
  display: flex;
  gap: 8px;
}

.tb-input {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--ink);
  border-radius: 0;
  padding: 8px 10px;
  -webkit-appearance: none;
  appearance: none;
}
.tb-input::placeholder {
  color: var(--ink-soft);
}
.tb-input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 0;
}

.tb-button {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
  background: var(--accent);
  border: 1px solid var(--ink);
  border-radius: 0;
  padding: 8px 16px;
  cursor: pointer;
}
.tb-button:hover {
  background: #e84a28;
}
.tb-button:active {
  transform: translate(1px, 1px);
}
.tb-button:disabled {
  opacity: 0.5;
  cursor: default;
}

/* Search feedback — never silent. */
.tb-status {
  margin: 8px 0 0;
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.4;
  color: var(--ink-soft);
  min-height: 1em;
  overflow-wrap: anywhere;
}
.tb-status[data-kind="error"] {
  color: var(--accent);
}

/* Startup / fatal error cell */
.tb-error-cell {
  background: var(--accent);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.45;
}

/* ------------------------------------------------------------------ */
/* Legend (rendered from the LAYERS registry)                        */
/* ------------------------------------------------------------------ */
.tb-legend-rows {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.tb-legend-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
.tb-legend-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.tb-legend-label {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink);
}
/* Second line under a legend label (LAYERS[].legend.note) — quieter, so the
   label still leads. */
.tb-legend-note {
  font-family: var(--font-mono);
  font-size: 10.5px;
  line-height: 1.35;
  color: var(--ink-soft);
}

/* Short-form legend label — hidden until the panel compacts. */
.tb-legend-short {
  display: none;
}

/* Compact panel — the state while a parcel is selected, toggled by
   setPanelCompact() in js/layers.js. Nothing re-renders; this is all CSS.
   The legend's rows go horizontal, type notes drop out, swatches shrink,
   and short labels swap in ("Larger" for "Larger lot") so the key holds one
   line at 340px instead of wrapping to two. */
.title-block.is-compact .tb-legend-rows {
  flex-direction: row;
  flex-wrap: wrap;
  gap: 4px 12px;
}
/* Visually hidden, NOT `display: none` — the full label and type note stay
   in the accessibility tree while collapsed, so a screen reader still reads
   "Larger lot — detached · attached · internal". */
.title-block.is-compact .tb-legend-note,
.title-block.is-compact .tb-legend-label {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Tooltip for the collapsed rows, carrying what the expanded legend shows.
   Drawn as a drafting-sheet callout: ink block, paper text, hard edges.

   It anchors to the ROW CONTAINER, not the row: anchored to the row, the
   right-hand swatch opened its tooltip rightward past the panel edge and
   the panel grew a horizontal scrollbar. Pinned left:0/right:0 on the
   container it always spans the legend's own width and can't overflow,
   whichever swatch you're on. */
.title-block.is-compact .tb-legend-rows {
  position: relative;
}
.title-block.is-compact .tb-legend-row {
  cursor: help;
}
.title-block.is-compact .tb-legend-row[data-full]::after {
  content: attr(data-full);
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin-top: 6px;
  z-index: 30;
  padding: 5px 8px;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1.45;
  white-space: normal;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease;
}
/* :active covers touch, where there's no hover at all. */
.title-block.is-compact .tb-legend-row[data-full]:hover::after,
.title-block.is-compact .tb-legend-row[data-full]:active::after {
  opacity: 1;
  visibility: visible;
}
.title-block.is-compact .tb-legend-short {
  display: inline;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink);
}
.title-block.is-compact .tb-swatch {
  width: 12px;
  height: 12px;
}
/* The search input and its placeholder stay — only the caption goes, so
   nothing becomes unreachable while a parcel is open. */
.title-block.is-compact .tb-search-cell .tb-microlabel {
  display: none;
}

/* Legend swatches — match common MapLibre layer types. */
.tb-swatch {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  border: 1px solid var(--ink);
}
.tb-swatch--square {
  background: var(--swatch-color);
}
.tb-swatch--line {
  height: 0;
  border: none;
  border-top: 3px solid var(--swatch-color);
}
.tb-swatch--circle {
  border-radius: 50%;
  background: var(--swatch-color);
}

/* ------------------------------------------------------------------ */
/* Parcel detail (populated on click by js/parcels.js)               */
/* ------------------------------------------------------------------ */
.tb-parcel-cell {
  background: #fff;
}
.pd-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.pd-close {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: 18px;
  line-height: 1;
  color: var(--ink-soft);
  background: transparent;
  border: none;
  padding: 0 2px;
  margin: -2px -2px 0 8px;
  cursor: pointer;
}
.pd-close:hover {
  color: var(--accent);
}
/* Addresses render uppercase. The assessing data is inconsistently cased —
   ~28% of parcels arrive title-cased ("1 Acorn ST") and the rest shouting —
   so this is what makes them look like one dataset. Done in CSS, not
   JS: the DOM keeps the address as the City spells it, so a copy/paste
   still yields the original. */
.pd-title {
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.01em; /* uppercase needs a little air */
  color: var(--ink);
  margin: 2px 0 0;
  text-transform: uppercase;
}
.pd-sub {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
  margin: 4px 0 0;
}
/* The ADU block — the reason the site exists, so it's the one element that
   gets a filled ground of its own. It reads against the white parcel cell
   the way a callout does on a drawing: hairline box, tier-colored edge, no
   shadow, no rounding, no gradient. */
.pd-adu {
  margin: 12px 0 0;
  padding: 12px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-left: 5px solid var(--tier-color, var(--ink-soft));
}
.pd-adu-headline {
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ink);
  margin: 0;
}
/* ADU types under the headline. */
.pd-types {
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.4;
  color: var(--ink-soft);
  margin: 5px 0 0;
}

/* Stat tiles: the two short values, side by side, divided by hairlines like
   a drawing's data block. The six-figure pair below gets full width instead
   — see .pd-ledger. */
.pd-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-top: 11px;
  border-top: 1px solid var(--hairline);
}
.pd-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 8px 9px 0;
  border-right: 1px solid var(--hairline);
  min-width: 0; /* let the grid track shrink instead of overflowing */
}
.pd-stat:nth-child(2n) {
  padding-right: 0;
  padding-left: 8px;
  border-right: none;
}
.pd-stat-label {
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* Cost-vs-value ledger — full width, right-aligned figures so the digits
   line up column-wise and the two ranges can be compared by eye. */
.pd-ledger {
  border-top: 1px solid var(--hairline);
  padding-top: 9px;
}
.pd-ledger-title {
  display: block;
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 600; /* heavier than .pd-stat-label — it heads two rows, not one value */
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 5px;
}
.pd-ledger-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-top: 2px;
}
.pd-ledger-label {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
}
.pd-ledger-value {
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ink);
  white-space: nowrap;
}
/* The read on the two figures above, in words — carries what a chart would
   have shown (do they overlap?) without the scale or the abbreviations.
   Italic because it's a gloss on the figures, not another label: at the same
   size and color as .pd-ledger-label it read as a third row of the ledger.
   Needs the italic axis in the Plex Mono request (see index.html) — the
   synthesized oblique is muddy at this size. */
.pd-ledger-note {
  font-family: var(--font-mono);
  font-size: 10px;
  font-style: italic;
  line-height: 1.4;
  color: var(--ink-soft);
  margin: 7px 0 0;
}
/* Sized so a full six-figure range ("~$280,000–370,000") stays on one line
   in a 2-up grid at the panel's width — wrapping a dollar range across two
   lines makes it read as two numbers. */
.pd-stat-value {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--ink);
}
/* Call to action under the ADU block. Uses the accent, which the design
   system reserves for selection and CTAs — this is the one place on the
   panel that qualifies. */
.pd-cta {
  display: block;
  width: 100%;
  margin-top: 10px;
  padding: 9px 12px;
  font-size: 12px;
  text-align: center;
  text-decoration: none;
}

.pd-rows {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 12px;
}
.pd-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--font-mono);
  font-size: 12px;
}
.pd-row-label {
  color: var(--ink-soft);
}
.pd-row-value {
  color: var(--ink);
  text-align: right;
}
/* Outbound row value (the parcel ID → City zoning viewer). */
.pd-row-link {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.pd-row-link:hover {
  color: var(--accent);
}
/* Lot-shape flags as badges under the address — outlined chips, no fill, so
   they read as annotations on the parcel rather than as a status. */
.pd-flags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px;
  margin: 7px 0 0;
}
.pd-flag {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  border: 1px solid var(--hairline);
  padding: 2px 6px;
}
/* The "!" does the work the word "check" used to — see about.html. */
.pd-flag-mark {
  font-weight: 600;
  font-size: 10px;
  color: var(--ink-soft);
}
/* Sized to hold "Physical potential only — not a legal determination." on a
   single line at the panel's width — the wrap made the one non-negotiable
   sentence on the panel read like a footnote nobody finishes. */
.pd-caveat {
  font-family: var(--font-mono);
  font-size: 9.5px;
  line-height: 1.45;
  letter-spacing: -0.01em;
  color: var(--ink-soft);
  margin: 10px 0 0;
  padding-top: 8px;
  border-top: 1px solid var(--hairline);
}

/* ------------------------------------------------------------------ */
/* Reference line (bottom of the title block)                        */
/* ------------------------------------------------------------------ */
.tb-stamp-cell {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.tb-about-link {
  display: block;
  font-family: inherit;
  font-size: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: var(--ink-soft);
  text-decoration: none;
}
.tb-about-link:hover {
  color: var(--ink);
  text-decoration: underline;
}

/* ------------------------------------------------------------------ */
/* About page                                                        */
/* ------------------------------------------------------------------ */
.about-header {
  background: var(--ink);
  color: var(--paper);
  padding: 20px 24px;
  border-bottom: 1.5px solid var(--ink);
}
.about-header .tb-microlabel {
  color: rgba(236, 239, 242, 0.6);
}
.about-header .tb-wordmark {
  font-size: 28px;
}
.about-header .tb-sheetline {
  display: block;
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid rgba(198, 205, 212, 0.3);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(236, 239, 242, 0.75);
}
/* Contents — styled as a drawing-set sheet index: numbered, monospaced,
   ruled top and bottom. */
.about-toc {
  margin: 0 0 34px;
  padding: 12px 0 10px;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.about-toc ol {
  counter-reset: toc;
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
}
.about-toc > ol > li {
  counter-increment: toc;
}
.about-toc > ol > li > a::before {
  content: counter(toc, decimal-leading-zero);
  margin-right: 12px;
  color: var(--ink-soft);
}
.about-toc a {
  display: block;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink);
  text-decoration: none;
  padding: 3px 0;
}
.about-toc a:hover {
  color: var(--accent);
  text-decoration: underline;
}
.about-toc ul {
  list-style: none;
  margin: 0 0 4px;
  padding: 0 0 0 34px;
}
.about-toc ul a {
  font-size: 11.5px;
  color: var(--ink-soft);
}
/* Anchor targets shouldn't land flush against the viewport edge. */
.about-section,
.about-section h3[id] {
  scroll-margin-top: 20px;
}

/* Pulled-out warning in the About copy — a ruled block, not a colored
   alert box; the design system has no alert color and shouldn't gain one. */
.about-callout {
  border-left: 4px solid var(--ink);
  padding: 2px 0 2px 14px;
  margin: 18px 0;
}

/* Inline sample of a parcel flag badge, so the About copy can show the
   thing it's describing. Mirrors .pd-flag. */
.about-flag {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  border: 1px solid var(--hairline);
  padding: 1px 6px;
  vertical-align: middle;
}
.about-flag span {
  font-weight: 600;
  color: var(--ink-soft);
}
.about-back {
  display: inline-block;
  margin-bottom: 14px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(236, 239, 242, 0.75);
  text-decoration: none;
  border: 1px solid rgba(236, 239, 242, 0.35);
  padding: 6px 10px;
}
.about-back:hover {
  border-color: var(--paper);
  color: var(--paper);
}

.about-body {
  max-width: 680px;
  margin: 0 auto;
  padding: 32px 24px 48px;
}

/* The maker's note. Set on the paper ground with a ruled edge so it reads as
   a personal preamble rather than another numbered section — the sections
   below are impersonal and cite the City; this one is a voice. */
.about-letter {
  border-left: 3px solid var(--ink);
  padding: 2px 0 2px 16px;
  margin: 0 0 28px;
}
.about-letter p {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink);
  margin: 0 0 12px;
}
.about-letter p:last-child {
  margin-bottom: 0;
}
/* Signed off like a drawing: mono, spaced, quiet. */
.about-signature {
  font-family: var(--font-mono) !important;
  font-size: 12px !important;
  letter-spacing: 0.1em;
  color: var(--ink-soft) !important;
  margin-top: 16px !important;
}

.about-intro {
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 0 0 28px;
}

.about-section {
  padding: 24px 0;
  border-top: 1px solid var(--hairline);
}
.about-section:first-of-type {
  border-top: none;
  padding-top: 0;
}
.about-section h2 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 22px;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  color: var(--ink);
  margin: 4px 0 12px;
}
.about-section h3 {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 20px 0 8px;
}
.about-section p {
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink);
  margin: 0 0 12px;
}
.about-section code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: rgba(24, 36, 51, 0.06);
  padding: 1px 4px;
}

.about-tiers {
  list-style: none;
  margin: 0 0 12px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.about-tiers li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
}
.about-tiers .tb-swatch {
  margin-top: 3px;
}

.about-links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.about-links li {
  border-left: 3px solid var(--hairline);
  padding-left: 12px;
}
.about-links a {
  display: block;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
}
.about-links a:hover {
  color: var(--accent);
  text-decoration: underline;
}
.about-links span {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
  margin-top: 2px;
}

/* Inline prose links. Without this they fell through to the browser's
   default blue, which is the one colour the design system doesn't own.
   Underlined by default (unlike the block links above): in running text
   colour alone shouldn't be what marks a link. */
.about-section p a,
.about-letter p a,
.about-links span a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: var(--hairline);
}
/* A link inside a resource's description is running text, not another card
   title — undo the block/large/bold treatment `.about-links a` gives the
   titles above, which otherwise breaks the sentence onto its own line. */
.about-links span a {
  display: inline;
  font-family: inherit;
  font-size: inherit;
  font-weight: inherit;
}
.about-section p a:hover,
.about-letter p a:hover,
.about-links span a:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}

.about-coffee {
  display: inline-block;
  text-decoration: none;
}

.about-footer {
  max-width: 680px;
  margin: 0 auto;
  padding: 0 24px 40px;
}
/* Colophon — practice name, set like a title-block field. */
.about-colophon {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 14px 0 0;
}
.about-colophon a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: var(--hairline);
}
.about-colophon a:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}

/* ------------------------------------------------------------------ */
/* MapLibre control tweaks (keep them on-brand: square, hairline)    */
/* ------------------------------------------------------------------ */
.maplibregl-ctrl-group {
  border-radius: 0 !important;
  border: 1px solid var(--ink) !important;
  box-shadow: 3px 3px 0 rgba(24, 36, 51, 0.25) !important;
}
.maplibregl-ctrl-group button {
  border-radius: 0 !important;
}

/* ------------------------------------------------------------------ */
/* Mobile: full-width panel, comfortable tap targets                 */
/* ------------------------------------------------------------------ */
@media (max-width: 600px) {
  .title-block {
    top: 0;
    left: 0;
    width: 100%;
    max-width: 100%;
    border-left: none;
    border-right: none;
    border-top: none;
    box-shadow: 0 4px 0 rgba(24, 36, 51, 0.2);
    /* Undo the desktop scroll container: here the panel is a top bar and the
       parcel detail is a separate fixed sheet with its own scroll. */
    max-height: none;
    overflow-y: visible;
    /* viewport-fit=cover (added for the bottom sheet's safe-area padding
       below) lets content draw under the notch/status bar — keep the
       wordmark clear of it. 0 on non-notched devices. */
    padding-top: env(safe-area-inset-top);
  }
  .tb-wordmark {
    font-size: 26px;
  }
  /* Top-right is the title block's on mobile (it spans the full width), so
     the hint moves to the bottom-left — the one map corner the zoom,
     geolocate, and attribution controls don't occupy. */
  .map-hint {
    top: auto;
    right: auto;
    bottom: 22px;
    left: 12px;
  }
  .tb-input {
    font-size: 16px; /* prevents iOS zoom-on-focus */
    padding: 11px 12px;
  }
  .tb-button {
    padding: 11px 18px;
  }

  /*
   * On mobile, selecting a parcel opens its detail as a FULL-SCREEN view
   * over the map, scrolled on its own, dismissed with the × back to the
   * map. No JS changes needed — parcels.js only ever toggles
   * `#parcel-detail`'s `hidden` attribute and fills its contents; this is
   * pure repositioning.
   *
   * This replaces an earlier 60vh bottom sheet, which kept the title block's
   * search reachable underneath. That trade is deliberately reversed here:
   * a phone has too little room to read the ADU block, the ledger, and the
   * facts through a half-height window, and the × is a cheap way back. On
   * desktop the panel still stacks normally and search stays visible.
   */
  .tb-parcel-cell {
    position: fixed;
    inset: 0;
    z-index: 20; /* above .title-block (10) and the map */

    max-height: none;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain; /* don't chain the scroll to the page behind */

    border: none;
    box-shadow: none;
    padding-top: 0; /* .pd-head carries the top inset instead, so it can stick */
    padding-bottom: calc(12px + env(safe-area-inset-bottom));
  }
  /* The drag handle belonged to the bottom sheet; a full-screen view isn't
     draggable, so the affordance would be a lie. */
  .tb-parcel-cell::before {
    content: none;
  }
  /* The × is the only way out of a full-screen view, so it stays pinned at
     the top while the content scrolls under it. */
  .pd-head {
    position: sticky;
    top: 0;
    z-index: 1;
    margin: 0 -14px 0; /* cancel the parent .tb-cell's padding so this sits flush */
    padding: calc(12px + env(safe-area-inset-top)) 14px 8px;
    background: #fff;
    border-bottom: 1px solid var(--hairline);
  }
  /* Comfortable tap target now that it's the only exit. */
  .pd-close {
    font-size: 24px;
    padding: 6px 10px;
    margin: -6px -10px 0 8px;
  }
}
