/* ROZH Property Snapshot — stylesheet
   Aesthetic: editorial, warm off-white canvas, deep ink, single ochre accent.
   Typography: Fraunces (display, serif) + IBM Plex Sans (body) + Plex Mono (labels).
*/

:root {
  --bg: #F5F1EA;              /* warm off-white / parchment (hero / site) */
  --bg-alt: #EEE8DE;          /* slightly deeper band */
  --ink: #141311;             /* near-black, warm */
  --ink-soft: #3A352E;        /* secondary text */
  --muted: #6E655A;           /* tertiary / labels */
  --rule: #C8BFB0;            /* hairlines */
  --rule-soft: #DCD3C3;
  --accent: #A85019;          /* deep ochre — ROZH brand mark. Deepened from
                                 #B25A1E for WCAG AA text contrast (4.92:1
                                 on sheet-bg vs 4.30:1 before). */
  --accent-soft: #E8C9A7;
  --good: #3F6B4A;            /* forest green */
  --good-soft: #D4E3D3;
  --caution: #B07B2D;         /* amber */
  --caution-soft: #F0DFB7;
  --warning: #9A2A1E;         /* deep red */
  --warning-soft: #F3C9BE;

  /* Tearsheet (Phase 1) — the document lives on a deeper desk. */
  --desk: #E3DBC7;                   /* page bg behind the document */
  --sheet-bg: #F7F2E7;               /* document bg, slightly creamier than --bg */
  --sheet-border: #1A1712;           /* document edge stroke */
  --sheet-rule: #CBC0AC;             /* internal rules */
  --sheet-rule-soft: #DDD4BF;        /* softer rules inside slots */
  --sheet-ink: #1A1712;              /* body ink */
  --sheet-label: #736A5F;            /* labels / tertiary. Darkened from
                                        #8C8276 for WCAG AA text contrast
                                        (4.75:1 on sheet-bg vs 3.38:1
                                        before — applies to fact dt
                                        labels, finding references,
                                        proximity distances, parcel
                                        diagnostic). */

  /* Category accents (tearsheet). Used as saturated accents only — slot
     header underlines, small indicator bars. Brief: "used sparingly, as
     accents not fills." */
  --cat-planning: #B07B2D;           /* amber */
  --cat-hazard:   #9A2A1E;           /* deep red */
  --cat-heritage: #2E4C6B;           /* deep blue */
  --cat-proximity:#3F6B4A;           /* forest green */

  --radius: 4px;
  --radius-lg: 10px;

  /* Display serif for legacy hero/how sections — not used inside the tearsheet. */
  --ff-display: "Fraunces", "Times New Roman", serif;
  /* Legacy body sans for pre-tearsheet chrome (hero, form, footer). */
  --ff-body: "IBM Plex Sans", system-ui, sans-serif;
  --ff-mono: "IBM Plex Mono", ui-monospace, monospace;

  /* Tearsheet editorial pairing. Inter for labels / UI chrome / slot headers;
     Source Serif 4 for document-feel values, addresses, prose. */
  --ff-sheet-sans: "Inter", system-ui, -apple-system, "Helvetica Neue", sans-serif;
  --ff-sheet-serif: "Source Serif 4", "Source Serif Pro", Georgia, serif;

  /* Tearsheet layout. 1150px fixed document width per brief. */
  --sheet-w: 1150px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--ff-body);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  background:
    radial-gradient(ellipse 1200px 600px at 90% -10%, rgba(178, 90, 30, 0.06), transparent 60%),
    radial-gradient(ellipse 900px 500px at -10% 50%, rgba(63, 107, 74, 0.05), transparent 60%),
    var(--bg);
  min-height: 100vh;
}

a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { color: var(--ink); }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

.wrap { max-width: 1180px; margin: 0 auto; padding: 0 28px; }
.wrap.narrow { max-width: 760px; }

/* Anchor-scroll offset for in-page jumps. The site-header is sticky
   (~63px tall on mobile, ~70px on desktop) so a bare anchor jump lands
   the target heading under the header. scroll-margin-top pushes the
   browser's resting scroll position down by this offset so the heading
   sits just below the header with a small breathing margin. Applied
   to every anchor target users land on from the nav. */
#lookup-form,
#how {
  scroll-margin-top: 80px;
}

/* ---- Header ---- */

/* Header. Brand on the left; primary nav inline on the right at desktop /
   tablet, collapsed behind a hamburger button at <=600px. The collapsed
   panel slides in from the right and is implemented in the .mobile-nav
   block below. */
.site-header {
  border-bottom: 1px solid var(--rule);
  padding: 20px 0;
  background: rgba(245, 241, 234, 0.85);
  backdrop-filter: blur(8px);
  position: sticky;
  top: 0;
  z-index: 20;
  transition: box-shadow 0.18s ease;
}
/* Elevation cue. The toggle class is added by the global scroll
   listener in app.js whenever window.scrollY > 0, so the header
   visually detaches from the page as soon as the user scrolls.
   Subtle hairline shadow rather than a hard rule — the existing
   border-bottom carries the structural separation. */
.site-header.is-scrolled {
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
}

.site-header .wrap { display: flex; align-items: baseline; justify-content: space-between; gap: 40px; }

.brand { display: inline-flex; align-items: baseline; gap: 14px; text-decoration: none; color: var(--ink); }
.brand:hover { color: var(--ink); }
.brand-mark {
  font-family: var(--ff-display);
  font-weight: 700;
  font-size: 26px;
  letter-spacing: -0.02em;
  font-variation-settings: "opsz" 36, "SOFT" 0;
}
.brand-sub {
  font-family: var(--ff-mono);
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

.site-nav { display: flex; gap: 28px; align-items: baseline; }
.site-nav a,
.site-nav-current {
  font-size: 14px;
  color: var(--ink-soft);
  text-decoration: none;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.site-nav a:hover { color: var(--accent); }

/* "You are here" treatment for the desktop nav. .is-current is set by
   the base template when the link's target matches current_page; the
   non-link <span class="site-nav-current"> renders for the current
   page (e.g. "Terms" on /terms) so we don't link to ourselves. Both
   pick up the same subdued visual: muted ink + a small leading dot. */
.site-nav a.is-current,
.site-nav-current {
  color: var(--muted);
  position: relative;
  padding-left: 14px;
}
.site-nav a.is-current::before,
.site-nav-current::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 5px;
  height: 5px;
  margin-top: -2.5px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.85;
}
.site-nav a.is-current { cursor: default; }
.site-nav a.is-current:hover { color: var(--muted); }

/* Hamburger trigger — hidden on desktop, shown <=600px. 44px tap target
   per WCAG. Three thin bars animate into an X via the [aria-expanded]
   attribute set by app.js. The bars use plain transforms so the
   animation runs on the compositor at ~60fps. */
.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  padding: 0;
  margin: 0 -10px 0 0;       /* nudge right edge flush with .wrap padding */
  background: transparent;
  border: 0;
  cursor: pointer;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
}
.nav-toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius);
}
.nav-toggle-bar {
  display: block;
  width: 22px;
  height: 1.5px;
  background: var(--ink);
  border-radius: 1px;
  transition: transform 0.2s ease, opacity 0.15s ease;
  transform-origin: center;
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) {
  transform: translateY(6.5px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) {
  opacity: 0;
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) {
  transform: translateY(-6.5px) rotate(-45deg);
}

/* Mobile slide-in nav panel. Off-canvas right by default; .is-open
   slides it into view. Cream palette matching the site (var(--bg)),
   not a generic white modal. Includes a contact line and a quiet
   "Run a snapshot" CTA at the bottom of the panel. */
.mobile-nav {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(360px, 84vw);
  background: var(--bg);
  border-left: 1px solid var(--rule);
  z-index: 100;
  transform: translateX(100%);
  transition: transform 0.28s cubic-bezier(0.22, 0.61, 0.36, 1);
  display: flex;
  flex-direction: column;
  padding: 72px 28px 32px;     /* top room clears the close-X position */
  overflow-y: auto;
  box-shadow: -16px 0 40px -12px rgba(20, 19, 17, 0.18);
}
.mobile-nav.is-open { transform: translateX(0); }

.mobile-nav-links {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.mobile-nav-links a,
.mobile-nav-current {
  font-family: var(--ff-display);
  font-size: 26px;
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink);
  text-decoration: none;
  padding: 14px 0;
  border-bottom: 1px solid var(--rule-soft);
  min-height: 44px;
  display: flex;
  align-items: center;
  letter-spacing: -0.01em;
}
.mobile-nav-links > :first-child { border-top: 1px solid var(--rule-soft); }
.mobile-nav-links a:hover,
.mobile-nav-links a:focus-visible {
  color: var(--accent);
  outline: none;
}

/* "You are here" treatment for the mobile panel. Same dot-prefix +
   muted-ink as the desktop nav, scaled up for the larger panel
   typography. */
.mobile-nav-links a.is-current,
.mobile-nav-current {
  color: var(--muted);
  padding-left: 20px;
  position: relative;
}
.mobile-nav-links a.is-current::before,
.mobile-nav-current::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 7px;
  height: 7px;
  margin-top: -3.5px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.85;
}
.mobile-nav-links a.is-current { cursor: default; }
.mobile-nav-links a.is-current:hover { color: var(--muted); }

.mobile-nav-footer {
  margin-top: auto;
  padding-top: 28px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.mobile-nav-contact {
  font-family: var(--ff-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 4px;
  min-height: 44px;
  display: flex;
  align-items: center;
}
.mobile-nav-cta {
  background: var(--ink);
  color: var(--bg);
  text-decoration: none;
  padding: 14px 18px;
  border-radius: var(--radius);
  font-family: var(--ff-body);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.02em;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  transition: background 0.15s ease;
}
.mobile-nav-cta:hover { background: var(--accent); color: var(--bg); }

/* Backdrop dim. Sits between the page and the panel; tapping it closes
   the menu (handler in app.js). */
.nav-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(20, 19, 17, 0.45);
  z-index: 90;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s ease;
}
.nav-backdrop.is-open {
  opacity: 1;
  pointer-events: auto;
}

/* Lock background scroll while menu is open. */
body.nav-open { overflow: hidden; }

@media (max-width: 600px) {
  .site-header {
    padding: 14px 0;
    /* Sticky + blur preserved here too — header stays visible while
       the user scrolls the report; the cream-tinted translucent bg
       lets long content read through cleanly. */
  }
  .brand-mark { font-size: 22px; }
  .brand-sub { font-size: 10px; letter-spacing: 0.14em; }
  .brand { gap: 10px; }
  /* Swap inline nav for the hamburger trigger. */
  .site-nav { display: none; }
  .nav-toggle { display: inline-flex; }
}

@media (min-width: 601px) {
  /* On desktop / tablet the panel & backdrop must never appear; even if
     the user resizes the viewport while the menu is open, force-hide. */
  .mobile-nav,
  .nav-backdrop { display: none !important; }
}

/* Honour reduced-motion preference — skip the slide animations and the
   hamburger morph; toggle visibility instantly instead. */
@media (prefers-reduced-motion: reduce) {
  .mobile-nav,
  .nav-backdrop,
  .nav-toggle-bar { transition: none !important; }
}

/* ---- Hero ---- */

.hero { padding: 80px 0 60px; }
.hero--compact { padding: 56px 0 28px; }

.eyebrow {
  font-family: var(--ff-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 24px;
}

.display {
  font-family: var(--ff-display);
  font-weight: 400;
  font-size: clamp(44px, 6.5vw, 92px);
  line-height: 0.98;
  letter-spacing: -0.03em;
  margin: 0 0 28px;
  font-variation-settings: "opsz" 144, "SOFT" 0;
  color: var(--ink);
}
.display em {
  font-style: italic;
  font-variation-settings: "opsz" 144, "SOFT" 100;
  color: var(--accent);
  font-weight: 400;
}

.lede {
  max-width: 720px;
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 44px;
}

/* ---- Lookup form ---- */

/* The form is now a vertical stack: input row + helper hint + unit error.
   The input row keeps the original single-bar visual treatment with two
   inputs (unit, address) and the submit button. Autocomplete dropdown
   is positioned absolutely below the address field — see further down. */
.lookup-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 780px;
}
.address-row {
  display: flex;
  gap: 0;
  border: 1.5px solid var(--ink);
  border-radius: var(--radius);
  background: #fff;
  overflow: visible;          /* dropdown overflows the bar */
  transition: box-shadow 0.2s ease, transform 0.2s ease;
  position: relative;
}
.address-row:focus-within {
  box-shadow: 0 0 0 4px var(--accent-soft);
}
.address-unit {
  flex: 0 0 110px;
  display: flex;
  align-items: stretch;
  border-right: 1px solid var(--rule);
}
.address-main {
  flex: 1;
  display: flex;
  align-items: stretch;
  position: relative;          /* anchor for dropdown */
}
.lookup-form input {
  flex: 1;
  padding: 22px 24px;
  border: 0;
  background: transparent;
  font-family: var(--ff-body);
  font-size: 17px;
  color: var(--ink);
  outline: none;
  width: 100%;
}
.address-unit input {
  padding: 22px 16px;
  font-size: 16px;
  letter-spacing: 0.02em;
}
.lookup-form input::placeholder { color: var(--muted); }
.address-unit input::placeholder {
  color: var(--muted);
  font-size: 14px;
  letter-spacing: 0.04em;
}

/* Carry the round-corner treatment on the leftmost / rightmost children
   so the inner inputs sit cleanly inside the bar at small radii. */
.address-unit input { border-radius: var(--radius) 0 0 var(--radius); }

.lookup-form button {
  border: 0;
  background: var(--ink);
  color: var(--bg);
  padding: 0 28px;
  font-family: var(--ff-body);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.01em;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  transition: background 0.15s ease;
  border-radius: 0 var(--radius) var(--radius) 0;
}
.lookup-form button:hover { background: var(--accent); }
.lookup-form button:disabled { opacity: 0.55; cursor: not-allowed; }
.lookup-form button:disabled:hover { background: var(--ink); }
.btn-arrow { transition: transform 0.2s ease; }
.lookup-form button:hover .btn-arrow { transform: translateX(3px); }

/* Mapbox autocomplete dropdown. ROZH-styled, NOT Mapbox's default UI.
   Anchors to the .address-main wrapper so it's flush with the address
   input edges. Renders below the search bar; max-height + overflow so
   long lists scroll. Each item is a button-shaped row with primary
   text (Mapbox `name`) and secondary text (`place_formatted`). */
.address-suggestions {
  position: absolute;
  top: calc(100% + 6px);
  left: -1.5px;               /* align over the bar's left border */
  right: -1.5px;              /* align over the bar's right border */
  margin: 0;
  padding: 4px 0;
  list-style: none;
  background: #fff;
  border: 1.5px solid var(--ink);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(20, 19, 17, 0.12);
  max-height: 320px;
  overflow-y: auto;
  z-index: 30;
}
.address-suggestions li {
  padding: 12px 22px;
  cursor: pointer;
  border-bottom: 1px solid var(--rule);
  transition: background 0.1s ease;
}
.address-suggestions li:last-child { border-bottom: 0; }
.address-suggestions li:hover,
.address-suggestions li[aria-selected="true"] {
  background: var(--accent-soft);
}
.address-suggestions .suggestion-primary {
  font-family: var(--ff-body);
  font-size: 16px;
  color: var(--ink);
  font-weight: 500;
}
.address-suggestions .suggestion-secondary {
  font-family: var(--ff-body);
  font-size: 13px;
  color: var(--muted);
  margin-top: 2px;
}
.address-suggestions .suggestion-empty {
  padding: 14px 22px;
  font-family: var(--ff-body);
  font-size: 14px;
  color: var(--muted);
  font-style: italic;
}

/* Inline helper / error rows under the search bar. Hint = soft (e.g. "you
   typed a unit prefix in the address field"); error = harder (unit field
   regex mismatch, Mapbox down). Both render only when populated. */
.address-hint,
.address-error {
  margin: 0;
  padding: 6px 4px 0;
  font-family: var(--ff-body);
  font-size: 13px;
  line-height: 1.4;
}
.address-hint { color: var(--muted); }
.address-error { color: var(--warning, #9A2A1E); }

.hero-fineprint {
  margin-top: 18px;
  font-size: 13px;
  color: var(--muted);
}
.hero-fineprint a { color: var(--muted); }

/* Mobile: stack unit above address. Button moves to its own row.
   Dropdown widens to the full row width. */
@media (max-width: 640px) {
  .address-row {
    flex-direction: column;
    border-radius: var(--radius);
  }
  .address-unit {
    flex: 0 0 auto;
    border-right: 0;
    border-bottom: 1px solid var(--rule);
  }
  .address-unit input { border-radius: var(--radius) var(--radius) 0 0; }
  .lookup-form button {
    border-radius: 0 0 var(--radius) var(--radius);
    padding: 16px 22px;
    justify-content: center;
  }
  .address-suggestions {
    left: -1.5px;
    right: -1.5px;
  }
}

/* ---- Status loader ---- */

.status { padding: 60px 0; }
.loader { display: flex; align-items: center; gap: 14px; color: var(--muted); font-family: var(--ff-mono); font-size: 13px; letter-spacing: 0.05em; }
.loader .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
  animation: pulse 1.2s infinite ease-in-out both;
}
.loader .dot:nth-child(2) { animation-delay: 0.15s; }
.loader .dot:nth-child(3) { animation-delay: 0.30s; }
@keyframes pulse { 0%, 80%, 100% { opacity: 0.3; transform: scale(0.85); } 40% { opacity: 1; transform: scale(1); } }

/* ---- Results (tearsheet Phase 1) ---- */

.results {
  padding: 40px 0 80px;
  animation: fadein 0.35s ease both;
}
@keyframes fadein { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* The desk: a darker tone than the document, signalling "page behind
   document". Full-bleed, generous margin on small viewports. */
.tearsheet-desk {
  background: var(--desk);
  padding: 48px 24px;
  min-height: 100vh;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

/* The document: fixed 1150px on desktop, centred, editorial hairline. */
.tearsheet {
  max-width: var(--sheet-w);
  margin: 0 auto;
  background: var(--sheet-bg);
  color: var(--sheet-ink);
  border: 1px solid var(--sheet-border);
  padding: 40px 48px 32px;
  font-family: var(--ff-sheet-serif);
  font-size: 16px;
  line-height: 1.55;
  box-shadow: 0 1px 0 rgba(26, 23, 18, 0.04), 0 30px 60px -30px rgba(26, 23, 18, 0.25);
}

/* ---- Sheet header ---- */

.sheet-header {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) minmax(420px, 2fr) minmax(180px, 1fr);
  gap: 32px;
  align-items: start;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--sheet-border);
}

.sheet-brand {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.sheet-brand-mark {
  font-family: var(--ff-sheet-serif);
  font-weight: 600;
  font-size: 22px;
  letter-spacing: -0.01em;
  color: var(--sheet-ink);
}
.sheet-brand-sub {
  font-family: var(--ff-sheet-sans);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sheet-label);
}

.sheet-title { text-align: left; }
.sheet-address {
  font-family: var(--ff-sheet-serif);
  font-weight: 400;
  font-size: clamp(24px, 2.6vw, 32px);
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0;
  color: var(--sheet-ink);
}
.sheet-locality {
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sheet-label);
  margin: 6px 0 0;
}

.sheet-meta {
  text-align: right;
  font-family: var(--ff-sheet-sans);
}
.sheet-meta-label {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sheet-label);
  margin: 0 0 6px;
}
.sheet-report-id {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--sheet-ink);
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.sheet-timestamp {
  font-size: 11px;
  color: var(--sheet-label);
  margin: 4px 0 0;
  font-variant-numeric: tabular-nums;
}

/* Download PDF button — sits beneath the report ID + timestamp inside
   .sheet-meta. Small, quiet, secondary. Hidden by default; the
   frontend reveals it once a snapshot has rendered (so a fresh page
   doesn't show the button before there's anything to download).
   Hidden in print itself (we don't want a "Download PDF" button
   showing up inside the PDF). */
.sheet-pdf-btn {
  margin-top: 10px;
  background: var(--sheet-ink);
  color: #fff;
  border: 0;
  padding: 8px 14px;
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
  cursor: pointer;
  border-radius: var(--radius);
  transition: background 0.15s ease, opacity 0.15s ease;
}
.sheet-pdf-btn:hover { background: var(--accent); }
.sheet-pdf-btn:disabled {
  opacity: 0.55;
  cursor: progress;
}
.sheet-pdf-btn:disabled:hover { background: var(--sheet-ink); }
.sheet-share-btn {
  margin-top: 8px;
  margin-left: 8px;
  background: transparent;
  color: var(--sheet-ink);
  border: 1px solid var(--sheet-border);
  padding: 8px 14px;
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
  cursor: pointer;
  border-radius: var(--radius);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.sheet-share-btn:hover {
  background: var(--bg-alt);
  border-color: var(--sheet-ink);
}
.sheet-pdf-error {
  margin-top: 6px;
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  line-height: 1.4;
  color: var(--warning);
}

/* ---- Sheet body: two columns ---- */

.sheet-body {
  display: grid;
  grid-template-columns: 55% 1fr;
  gap: 36px;
  padding: 32px 0;
}

.sheet-map-col {
  display: flex;
  flex-direction: column;
  gap: 16px;
  /* Sticky on desktop — the right column (facts + findings) can scroll
     well past the map height on overlay-heavy properties. Without
     sticky, hovering or pinning a finding produces no visible map
     change because the map is offscreen. position: sticky pins the
     map column to the viewport top while the right column scrolls.
     Mobile breakpoint (< 768px) overrides this — phones rely on the
     smooth-scroll-into-view JS helper instead, which uses less screen
     real estate than a sticky mini-map. */
  position: sticky;
  top: 16px;
  align-self: flex-start;
}

.sheet-map {
  height: 650px;
  border: 1px solid var(--sheet-border);
  overflow: hidden;
  background: var(--bg-alt);
}
/* Basemap tinting — warms Carto's grey tiles toward paper tone. A single
   CSS filter keeps the map visually unified with the sheet without needing
   a custom tile service / API key. Phase 1 placeholder — a bespoke Maptiler
   or Mapbox style can swap in later by changing the tile URL in app.js. */
.sheet-map .leaflet-tile {
  filter: sepia(0.28) saturate(0.85) hue-rotate(-6deg) brightness(1.02);
}

/* Parcel diagnostic — muted prose beneath the map explaining query geometry. */
.parcel-diagnostic {
  margin: 0;
  font-family: var(--ff-sheet-sans);
  font-size: 12px;
  line-height: 1.5;
  color: var(--sheet-label);
}
.parcel-area {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  font-weight: 500;
  color: var(--sheet-ink);
}

.sheet-content-col {
  display: flex;
  flex-direction: column;
  gap: 28px;
}

/* ---- Facts panel ---- */

.facts-list {
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--sheet-border);
  border-bottom: 1px solid var(--sheet-rule-soft);
}
.fact {
  display: grid;
  grid-template-columns: minmax(140px, 38%) 1fr;
  gap: 20px;
  align-items: baseline;
  padding: 12px 0;
  border-bottom: 1px solid var(--sheet-rule-soft);
}
.fact:last-child { border-bottom: 0; }
.fact dt {
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sheet-label);
  margin: 0;
}
.fact dd {
  font-family: var(--ff-sheet-serif);
  font-size: 18px;
  font-weight: 400;
  color: var(--sheet-ink);
  margin: 0;
  line-height: 1.35;
}
.fact dd.muted { color: var(--sheet-label); }

/* ---- Findings grid (single column, content-sized) ----
   Was a 2×2 grid with min-height 220px per slot; that produced large
   empty cells for low-overlay properties because each cell had to
   match the height of its row neighbour. Single column lets each
   section size to its own content, and the map column's existing
   `position: sticky` keeps the map visible as the right column
   scrolls. Slot order in markup (Planning → Hazard → Heritage →
   Proximity) is the visual order. */

.findings-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  border: 1px solid var(--sheet-border);
}
.finding-slot {
  padding: 18px 20px 20px;
  border-right: 0;
  border-bottom: 1px solid var(--sheet-rule);
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: var(--sheet-bg);
  transition: background 0.15s ease;
}
.finding-slot:last-child { border-bottom: 0; }

.slot-header {
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sheet-ink);
  margin: 0 0 4px;
  padding-bottom: 10px;
  border-bottom: 2px solid var(--sheet-ink);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}
/* Category-accent underline — a single saturated hair of colour per slot. */
.finding-slot[data-accent="planning"]  .slot-header { border-bottom-color: var(--cat-planning); }
.finding-slot[data-accent="hazard"]    .slot-header { border-bottom-color: var(--cat-hazard); }
.finding-slot[data-accent="heritage"]  .slot-header { border-bottom-color: var(--cat-heritage); }
.finding-slot[data-accent="proximity"] .slot-header { border-bottom-color: var(--cat-proximity); }

.slot-count {
  font-family: var(--ff-sheet-sans);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.10em;
  color: var(--sheet-label);
}

.slot-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-family: var(--ff-sheet-serif);
  font-size: 15px;
  line-height: 1.55;
  color: var(--sheet-ink);
}

/* A populated finding row within a slot. Interactive: hover (desktop)
   reveals the matching map polygon; click/tap pins it to the map; a
   second click unpins. Keyboard equivalent: focus + Enter/Space.
   See static/app.js::renderFindingItem + syncMap() for the wiring. */
.finding-item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 8px;
  margin: -6px -8px;
  border-radius: 3px;
  transition: background-color 0.12s ease;
  cursor: pointer;
}
.finding-item:hover,
.finding-item:focus-visible {
  background-color: rgba(26, 23, 18, 0.04);
  outline: none;
}
.finding-item:focus-visible {
  /* Keyboard focus ring — visible only when navigating via Tab.
     Slightly heavier than the hover bg so it reads as "this is the
     one Enter will pin". */
  box-shadow: 0 0 0 2px rgba(168, 80, 25, 0.45);
}
/* Pinned state — the overlay is currently on the map. Subtle bg
   distinguishes pinned from un-pinned at a glance; the swatch dot
   below carries the colour-of-the-overlay information. */
.finding-item.is-pinned {
  background-color: rgba(168, 80, 25, 0.06);
}

/* Swatch dot — sits to the right of the finding title, hidden by
   default, revealed by `.is-pinned`. Inline-block so it doesn't
   disturb the title's flow on the line above. Colour matches the
   slot accent (set via inline style in renderFindingItem). */
.finding-item-swatch {
  display: none;
  position: absolute;
  top: 8px;
  right: 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15);
}
.finding-item.is-pinned .finding-item-swatch {
  display: inline-block;
}

/* Clear-all toolbar — one-button strip above the findings grid.
   Hidden by default (the button itself toggles `[hidden]` from JS
   when pinnedKeys.size goes 0 ↔ 1+). When visible, the button reads
   as a quiet text link rather than a primary action — clearing
   pinned overlays is rare; we don't want it competing with the
   findings themselves for attention. */
.findings-toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 8px;
  min-height: 22px;  /* reserve space so toggle doesn't reflow grid */
}
.findings-toolbar-clear {
  background: transparent;
  border: 0;
  padding: 4px 8px;
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--sheet-label);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.findings-toolbar-clear:hover {
  color: var(--accent);
}
/* Sub-label above a finding title. Disambiguates CHARACTER vs HERITAGE
   rows inside the shared "Character & heritage" slot — the planning-
   scheme Character overlay and a heritage-register listing have
   different legal weight and we don't want skimmers to conflate them.
   Emitted by app.js renderFindingItem when layer.category is
   "character" or "heritage". */
.finding-item-sublabel {
  font-family: var(--ff-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sheet-label);
  margin-bottom: 3px;
}
.finding-item-title {
  font-family: var(--ff-sheet-sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--sheet-ink);
}
.finding-item-label {
  font-family: var(--ff-sheet-sans);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sheet-label);
  margin-top: 2px;
}
.finding-item-body {
  font-family: var(--ff-sheet-serif);
  font-size: 14px;
  line-height: 1.5;
  color: var(--sheet-ink);
  margin: 4px 0 0;
}

/* One-line reference beneath a finding. Sans, muted, smaller. Plain
   underlined text (rendered as <a> when a URL is provided, as a styled
   <span> when the URL is pending). Not a CTA — no button chrome. */
.finding-reference {
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  line-height: 1.45;
  color: var(--sheet-label);
  margin: 6px 0 0;
}
.finding-reference-lead { color: var(--sheet-label); }
.finding-reference a,
.finding-reference .finding-reference-link {
  color: var(--sheet-label);
  text-decoration: underline;
  text-decoration-color: var(--sheet-rule);
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}
.finding-reference a:hover {
  color: var(--sheet-ink);
  text-decoration-color: var(--sheet-ink);
}

/* Miss-reassurance line — typographic parity with populated rows. "Emptiness
   is information" per the brief. Same size, same weight, same ink. */
.finding-miss {
  font-family: var(--ff-sheet-serif);
  font-size: 15px;
  line-height: 1.55;
  color: var(--sheet-ink);
  margin: 0;
}

/* Proximity rows: stacked at every viewport. Label small-caps on top,
   serif value below, left-aligned, full width of the slot.
   The desktop two-column treatment (label left / value right) wraps
   both sides untidily inside the half-width Proximity slot at
   ≥1025px, where the slot is ~260px. The stacked treatment reads
   cleanly at desktop, tablet, and phone widths without breaking the
   map ↔ findings linkage (proximity rows are non-interactive — no
   JS handlers bind to .finding-proximity-* classes). */
.finding-proximity-row {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  padding: 8px 0;
  border-bottom: 1px dotted var(--sheet-rule-soft);
}
.finding-proximity-row:last-child { border-bottom: 0; }
.finding-proximity-label {
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sheet-label);
}
.finding-proximity-value {
  font-family: var(--ff-sheet-serif);
  font-size: 15px;
  color: var(--sheet-ink);
  text-align: left;
}
.finding-proximity-distance {
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  font-weight: 500;
  color: var(--sheet-label);
  font-variant-numeric: tabular-nums;
}

/* ---- Market context + next steps ---- */

.market-panel,
.next-steps {
  border-top: 1px solid var(--sheet-rule);
  padding-top: 18px;
  margin-top: 18px;
  font-family: var(--ff-sheet-sans);
}
.panel-header {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: baseline;
  margin-bottom: 10px;
}
.panel-header h4 {
  margin: 0;
  font-size: 13px;
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sheet-ink);
}
.panel-kicker {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sheet-label);
}
.market-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  color: var(--sheet-ink);
}
.market-table th,
.market-table td {
  padding: 8px 0;
  border-bottom: 1px solid var(--sheet-rule-soft);
  text-align: left;
}
.market-table th {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sheet-label);
  font-weight: 600;
}
.market-note,
.market-unavailable,
.purpose-confirm {
  margin: 10px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--sheet-label);
}
.next-steps-list {
  margin: 0;
  padding-left: 18px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--sheet-ink);
}
.next-steps-list li + li { margin-top: 6px; }

/* ---- Property Structure Checks (complexity section, phase 2h) ----
   Editorial panel matching market-panel chrome (hairline top rule,
   compact uppercase header). Buyer-facing copy comes from the backend;
   styles here are layout + state visual treatment only. Caution must
   read as "check this", not "bad property" — amber accent on the left
   edge only, soft background tint, no red. */
.complexity-panel {
  border-top: 1px solid var(--sheet-rule);
  padding-top: 18px;
  margin-top: 18px;
  font-family: var(--ff-sheet-sans);
}
.complexity-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 6px;
}
.complexity-row {
  border: 1px solid var(--sheet-rule-soft);
  border-left: 3px solid var(--sheet-rule);
  border-radius: var(--radius);
  padding: 14px 16px;
  background: var(--sheet-bg);
}
.complexity-row--standard {
  border-left-color: var(--sheet-rule);
}
.complexity-row--caution {
  border-left-color: var(--caution);
  background: linear-gradient(
    to right,
    var(--caution-soft) 0,
    var(--caution-soft) 4px,
    var(--sheet-bg) 4px
  );
}
.complexity-row--unknown {
  border-left-color: var(--muted);
}
.complexity-row-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 6px;
}
.complexity-row-title {
  margin: 0;
  font-size: 13px;
  font-weight: 650;
  letter-spacing: 0.04em;
  color: var(--sheet-ink);
}
.complexity-state-chip {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 999px;
  white-space: nowrap;
}
.complexity-state-chip--standard {
  background: var(--bg-alt);
  color: var(--sheet-label);
}
.complexity-state-chip--caution {
  background: var(--caution-soft);
  color: var(--caution);
}
.complexity-state-chip--unknown {
  background: var(--rule-soft);
  color: var(--muted);
}
.complexity-row-summary {
  margin: 0 0 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--sheet-ink);
  line-height: 1.45;
}
.complexity-row-part {
  margin-top: 10px;
}
.complexity-row-part:first-of-type {
  margin-top: 0;
}
.complexity-row-eyebrow {
  margin: 0 0 3px;
  font-family: var(--ff-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sheet-label);
}
.complexity-row-body {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--sheet-ink);
}
.complexity-next-check {
  margin: 0;
  padding-left: 18px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--sheet-ink);
}
.complexity-next-check li + li { margin-top: 3px; }
.complexity-footnote {
  margin: 12px 0 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--sheet-label);
  font-style: italic;
}

/* ---- Buyer Brief synthesis — inline render (Layer 2 Option C) ----
   The synthesis layer (synthesis.py) emits cards in three buckets.
   Public-records-show cards render as inline .slot-lead / .panel-lead
   subheads above the matching detail section — quiet editorial
   annotation, NOT card chrome. ROZH-infers + Not-checked-by-ROZH cards
   render as editorial entries in the existing "Check before
   unconditional" section. No new section, no foreign chrome — the
   synthesis disappears into the existing tearsheet rhythm.
   See CLAUDE.md "Critical knowledge #18". */

/* Inline lead — italic editorial subhead with an inline "Next check —"
   action. Sits between section header and section body. Subtle
   ochre-tinted top rule to mark it as annotation, not content. */
.slot-lead,
.panel-lead {
  margin: 6px 0 14px;
  padding: 8px 0 0;
  border-top: 1px dashed var(--sheet-rule-soft);
  font-family: var(--ff-sheet-sans);
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--sheet-ink);
  font-style: italic;
  max-width: 64ch;
}
.slot-lead[hidden],
.panel-lead[hidden] { display: none; }
.slot-lead-next,
.panel-lead-next {
  font-style: normal;
  display: block;
  margin-top: 4px;
}
.slot-lead-next-label,
.panel-lead-next-label {
  font-family: var(--ff-mono, var(--ff-sheet-sans));
  font-style: normal;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sheet-label);
  margin-right: 6px;
}

/* "Check before unconditional" — editorial entries (no card chrome).
   Each rendered card becomes a heading + body paragraph + a small
   inline "Next check —" line. Cooling-off note becomes an italic
   intro to the whole section. */
.next-steps-cooling {
  margin: 0 0 14px;
  font-family: var(--ff-sheet-sans);
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--sheet-label);
  font-style: italic;
  max-width: 70ch;
}
.next-steps-cooling[hidden] { display: none; }
.next-steps-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
  font-family: var(--ff-sheet-sans);
}
.next-steps-entry {
  /* No border, no background. Pure editorial. The hairline rule
     between entries is delivered by the parent gap + a top divider
     on every entry except the first. */
  padding-top: 12px;
  border-top: 1px solid var(--sheet-rule-soft);
}
.next-steps-entry:first-child {
  padding-top: 0;
  border-top: none;
}
.next-steps-entry-title {
  margin: 0 0 6px;
  font-family: var(--ff-sheet-sans);
  font-size: 13px;
  font-weight: 650;
  letter-spacing: 0.01em;
  color: var(--sheet-ink);
  line-height: 1.3;
}
.next-steps-entry-tease {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--sheet-ink);
}
.next-steps-entry-next {
  margin: 6px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--sheet-ink);
}
.next-steps-entry-next-label {
  font-family: var(--ff-mono, var(--ff-sheet-sans));
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sheet-label);
  margin-right: 6px;
}
.next-steps-entry-limit {
  margin: 4px 0 0;
  font-size: 11px;
  line-height: 1.45;
  color: var(--sheet-label);
  font-style: italic;
}

/* Static fallback list — visible only if JS doesn't populate the
   editorial body (no-synthesis mode). When the body has any content,
   the fallback hides. */
.next-steps-body:not(:empty) ~ .next-steps-list {
  display: none;
}

/* ---- Unit-mode (Layer 5) — body corp + CMS scheme checks ----
   Same editorial register as next-steps entries. Renders only when
   /api/lookup returns a non-null `unit_mode` field (unit + townhouse
   classifications). The intro is an italic body-sans paragraph mirroring
   the cooling-off note above it; cards use the same heading + tease +
   next + limit shape as next-steps entries. See CLAUDE.md "Critical
   knowledge #20". */
.unit-mode[hidden] { display: none; }
.unit-mode-intro {
  margin: 0 0 14px;
  font-family: var(--ff-sheet-sans);
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--sheet-label);
  font-style: italic;
  max-width: 70ch;
}
.unit-mode-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
  font-family: var(--ff-sheet-sans);
}
.unit-mode-entry {
  padding-top: 12px;
  border-top: 1px solid var(--sheet-rule-soft);
}
.unit-mode-entry:first-child {
  padding-top: 0;
  border-top: none;
}
.unit-mode-entry-title {
  margin: 0 0 6px;
  font-family: var(--ff-sheet-sans);
  font-size: 13px;
  font-weight: 650;
  letter-spacing: 0.01em;
  color: var(--sheet-ink);
  line-height: 1.3;
}
.unit-mode-entry-tease {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--sheet-ink);
}
.unit-mode-entry-next {
  margin: 6px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--sheet-ink);
}
.unit-mode-entry-next-label {
  font-family: var(--ff-mono, var(--ff-sheet-sans));
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sheet-label);
  margin-right: 6px;
}
.unit-mode-entry-limit {
  margin: 4px 0 0;
  font-size: 11px;
  line-height: 1.45;
  color: var(--sheet-label);
  font-style: italic;
}

/* ---- Anonymous purpose-prompt strip ----
   Quiet single-line ask near the document end. Visual register
   deliberately below the report sections — small typography, hairline
   top rule only (no panel chrome), short padding. The "×" dismiss
   sits on the right; submit and dismiss both hide the section
   via the .is-dismissed class. */
.purpose-strip {
  position: relative;
  margin-top: 22px;
  padding: 14px 36px 14px 0;
  border-top: 1px solid var(--sheet-rule-soft);
  font-family: var(--ff-sheet-sans);
  font-size: 12px;
  color: var(--sheet-label);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
}
.purpose-strip.is-dismissed { display: none; }
.purpose-prompt {
  margin: 0;
  font-size: 12px;
  color: var(--sheet-label);
  letter-spacing: 0.01em;
}
.purpose-options {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
}
.purpose-options button {
  border: 1px solid var(--sheet-rule);
  background: transparent;
  color: var(--sheet-label);
  border-radius: var(--radius);
  padding: 4px 9px;
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}
.purpose-options button:hover {
  border-color: var(--sheet-ink);
  color: var(--sheet-ink);
}
.purpose-options button.is-selected {
  border-color: var(--sheet-ink);
  background: var(--sheet-ink);
  color: var(--sheet-bg);
}
.purpose-dismiss {
  position: absolute;
  top: 10px;
  right: 0;
  width: 28px;
  height: 28px;
  border: 0;
  background: transparent;
  color: var(--sheet-label);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  border-radius: var(--radius);
}
.purpose-dismiss:hover {
  color: var(--sheet-ink);
  background: rgba(26, 23, 18, 0.04);
}
.purpose-confirm {
  flex-basis: 100%;
  margin: 0;
  font-size: 11px;
  color: var(--sheet-label);
  font-style: italic;
}

/* ---- Waitlist (Phase 4) ----
   Last block inside the tearsheet article, before the sheet-footer.
   Subdued: hairline top rule, centred, narrow column. No filled
   container — sits on the same warm paper as the findings grid so it
   reads as part of the document, not as an inset card. */

.waitlist {
  margin-top: 32px;
  padding: 28px 20px 8px;
  border-top: 1px solid var(--sheet-rule);
  text-align: center;
}

.waitlist-eyebrow {
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sheet-ink);
  margin: 0 0 14px;
}

.waitlist-context {
  font-family: var(--ff-sheet-serif);
  font-size: 16px;
  line-height: 1.55;
  color: var(--sheet-ink);
  margin: 0 auto 18px;
  max-width: 460px;
}

.waitlist-form {
  display: flex;
  gap: 0;
  max-width: 460px;
  margin: 0 auto 12px;
  border: 1.5px solid var(--sheet-border);
  border-radius: var(--radius);
  background: #fff;
  overflow: hidden;
  transition: box-shadow 0.2s ease;
}
.waitlist-form:focus-within {
  box-shadow: 0 0 0 3px rgba(168, 80, 25, 0.18);  /* echoes --accent soft halo */
}

.waitlist-form input[type="email"] {
  flex: 1;
  padding: 11px 14px;
  border: 0;
  background: transparent;
  font-family: var(--ff-sheet-sans);
  font-size: 14px;
  color: var(--sheet-ink);
  outline: none;
}
.waitlist-form input::placeholder {
  color: var(--sheet-label);
}

.waitlist-form button {
  border: 0;
  background: var(--sheet-border);
  color: var(--sheet-bg);
  padding: 0 18px;
  font-family: var(--ff-sheet-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: background 0.15s ease;
  white-space: nowrap;
}
.waitlist-form button:hover:not(:disabled) {
  background: var(--accent);
}
.waitlist-form button:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Sub-480px: stack the form vertically — input full-width on top,
   button full-width below. The horizontal layout truncates the
   "Add me to the list" label on narrow phones. */
@media (max-width: 480px) {
  .waitlist-form { flex-direction: column; }
  .waitlist-form input[type="email"] {
    width: 100%;
    padding: 14px 16px;
    border-bottom: 1px solid var(--sheet-rule);
  }
  .waitlist-form button {
    width: 100%;
    padding: 14px 16px;
    text-align: center;
  }
}

.waitlist-privacy {
  font-family: var(--ff-sheet-sans);
  font-size: 11px;
  color: var(--sheet-label);
  margin: 0 auto;
  max-width: 460px;
}

.waitlist-error {
  font-family: var(--ff-sheet-sans);
  font-size: 12px;
  color: var(--warning);
  margin: 10px auto 0;
  max-width: 460px;
  line-height: 1.5;
}

.waitlist-success {
  font-family: var(--ff-sheet-serif);
  font-size: 16px;
  line-height: 1.55;
  color: var(--sheet-ink);
  margin: 0 auto;
  max-width: 460px;
  padding: 6px 0 14px;
}

/* ---- Sheet footer ---- */

.sheet-footer {
  margin-top: 8px;
  padding-top: 20px;
  border-top: 1px solid var(--sheet-border);
  font-family: var(--ff-sheet-sans);
}
.sheet-disclaimer {
  font-size: 11px;
  line-height: 1.55;
  color: var(--sheet-label);
  margin: 0 0 16px;
  max-width: 900px;
}
.sheet-sources {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sheet-label);
}
.sheet-sources-label {
  font-weight: 600;
  color: var(--sheet-ink);
}
.sheet-sources-licence {
  text-transform: none;
  letter-spacing: 0;
  color: var(--sheet-label);
  font-weight: 400;
}
.sheet-sources-date {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  text-transform: none;
  letter-spacing: 0.02em;
}
/* Container around the JS-injected source links. `display: contents`
   means it doesn't generate a box of its own — the inner <span> link
   wrappers become direct flex items of .sheet-sources and pick up
   the parent's 18px gap automatically. Keeps the existing visual
   rhythm without nesting a second flex layer. */
.sheet-sources-list { display: contents; }
.sheet-source-link {
  color: var(--sheet-label);
  text-decoration: underline;
  text-decoration-color: var(--sheet-rule);
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}
.sheet-source-link:hover {
  color: var(--sheet-ink);
  text-decoration-color: var(--sheet-ink);
}

/* ---- Responsive breakpoints ----
   Desktop ≥1025px: fixed 1150px document, two-column tearsheet
   Tablet / portrait laptop ≤1024px: fluid document, single-column stack
   Phone ≤767px: phone-only typography + map height + slot borders

   Single transition at 1024px (inclusive) — iPad landscape (exactly
   1024px wide) stacks. No "desktop chrome + stacked content" half-state. */

@media (max-width: 1024px) {
  /* Container goes fluid + tighter padding; map height drops for the
     stacked layout (full-width map doesn't need to be as tall as the
     desktop two-column version). */
  .tearsheet {
    max-width: 100%;
    padding: 32px 36px 28px;
  }
  .sheet-map { height: 560px; }
  /* Stack the whole report. All column grids collapse to 1fr; sticky
     map drops (no second column to scroll alongside); header meta
     left-aligns now that it's not in a right-hand column. */
  .sheet-header {
    grid-template-columns: 1fr;
    gap: 16px;
    padding-bottom: 18px;
  }
  .sheet-meta { text-align: left; }
  .sheet-body {
    grid-template-columns: 1fr;
    gap: 24px;
    padding: 22px 0;
  }
  .sheet-map-col { position: static; }
  .fact {
    grid-template-columns: 1fr;
    gap: 4px;
    padding: 14px 0;
  }
}

@media (max-width: 767px) {
  /* Phone-only adjustments: container padding, typography compression,
     map height reduction, slot border treatment. These do NOT apply at
     tablet stacked widths — tablets get the desktop typography scale. */
  .tearsheet-desk { padding: 20px 12px; }
  .tearsheet { padding: 24px 22px 24px; }
  .sheet-address { font-size: 24px; }
  .sheet-map { height: 320px; }
  .fact dd {
    font-size: 17px;
    line-height: 1.3;
    text-align: left;
  }
  .sheet-sources { flex-direction: column; gap: 6px; }
  .sheet-sources-date { margin-left: 0; }
}

/* ---- "How it works" / what-we-check ---- */

.how { padding: 80px 0; background: var(--bg-alt); border-top: 1px solid var(--rule); }
.section-h {
  font-family: var(--ff-display);
  font-weight: 400;
  font-size: 34px;
  letter-spacing: -0.02em;
  margin: 0 0 28px;
}
.section-h--mt { margin-top: 60px; }

.how-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  border-top: 1px solid var(--rule);
}
.how-card {
  border-bottom: 1px solid var(--rule);
  border-right: 1px solid var(--rule);
  padding: 24px 22px;
}
.how-card:nth-child(3n) { border-right: 0; }
/* Below 900px the 3-col layout gets cramped (each card ~250px wide
   minus padding). Collapse straight to single column rather than
   passing through 2-col, which would reintroduce the orphan bug
   (9 items / 2 cols = 4 rows + 1 lonely card). */
@media (max-width: 900px) {
  .how-grid { grid-template-columns: 1fr; }
  .how-card { border-right: 0; }
}
.how-card strong {
  font-family: var(--ff-display);
  font-size: 20px;
  font-weight: 500;
  display: block;
  margin-bottom: 6px;
}
.how-card p { margin: 0; font-size: 14px; color: var(--ink-soft); }

.not-list { padding-left: 0; list-style: none; margin: 0; border-top: 1px solid var(--rule); }
.not-list li {
  padding: 18px 0;
  border-bottom: 1px solid var(--rule);
  font-size: 15px;
  color: var(--ink-soft);
}
.not-list li strong { color: var(--ink); }

/* ---- Legal page ---- */
.legal { padding: 20px 0 80px; }
.legal h2 {
  font-family: var(--ff-display);
  font-weight: 500;
  font-size: 22px;
  margin: 40px 0 12px;
  letter-spacing: -0.01em;
}
.legal p, .legal ul { font-size: 15px; color: var(--ink-soft); }
.legal ul { padding-left: 20px; }
.legal-ack { margin-top: 40px; padding-top: 20px; border-top: 1px solid var(--rule); font-size: 13px; color: var(--muted); }

/* ---- Footer ---- */

.site-footer {
  border-top: 1px solid var(--rule);
  padding: 40px 0 60px;
  margin-top: 60px;
  background: var(--bg);
}
.site-footer .wrap { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; align-items: baseline; }
@media (max-width: 600px) { .site-footer .wrap { grid-template-columns: 1fr; } }
.foot-brand .brand-mark { font-size: 22px; }
.foot-brand p { margin: 4px 0 0; color: var(--muted); font-size: 13px; }
.foot-links { display: flex; gap: 22px; justify-content: flex-end; flex-wrap: wrap; align-items: baseline; }
@media (max-width: 600px) { .foot-links { justify-content: flex-start; gap: 16px; } }
.foot-links a,
.foot-links-current {
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 14px;
  white-space: nowrap;       /* keep "Terms" and the email each on one line */
  /* WCAG AAA tap target — footer links are small visually but the
     hit area must be ≥44px tall on touch devices. inline-flex keeps
     the visual baseline alignment intact while padding the hit box. */
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
.foot-links a:hover { color: var(--accent); }
/* "You are here" — non-link span renders on /terms in place of the
   self-link. Subdued so it reads as info, not a CTA. */
.foot-links-current { color: var(--muted); cursor: default; }
.foot-note {
  grid-column: 1 / -1;
  margin: 32px 0 0;
  font-size: 11px;
  color: var(--muted);
  max-width: 780px;
  line-height: 1.5;
}

/* ---- Leaflet attribution cleanup (readability on our bg) ---- */
.leaflet-container { font-family: var(--ff-body); }
.leaflet-control-attribution { font-size: 10px; background: rgba(245, 241, 234, 0.92); }

/* ---- Mobile section-padding audit ----
   The desktop padding scale (80px section gutters, 60px footer top
   margin) is comically large on a 414px viewport — it produces obvious
   empty bands between blocks (above the hero eyebrow, between the
   "What we don't check" list and the footer, etc). One block of
   explicit overrides keeps the desktop layout untouched and scales
   spacing down where viewport is scarce. */
@media (max-width: 600px) {
  .hero          { padding: 28px 0 28px; }
  .hero--compact { padding: 24px 0 16px; }
  .how           { padding: 40px 0 36px; }
  .results       { padding: 24px 0 32px; }
  .status        { padding: 24px 0; }
  .tearsheet-desk{ padding: 16px 10px; }
  .site-footer   { padding: 28px 0 36px; margin-top: 32px; }
  .foot-note     { margin-top: 20px; }
  .legal         { padding: 16px 0 40px; }
  .section-h     { font-size: 26px; margin-bottom: 18px; }
  .section-h--mt { margin-top: 36px; }
  .lede          { font-size: 16px; margin-bottom: 28px; }
  .eyebrow       { margin-bottom: 16px; }
  .display       { margin-bottom: 20px; }
}


/* ============================================================================
   Print styles — browser "Save as PDF" / Cmd+P → PDF path.
   No native PDF generation; we lean on the browser's print engine and just
   shape the output with CSS.

   Design goals:
   - Report header + facts + findings + disclaimer print cleanly.
   - Site nav, hero / search bar, "What we check", waitlist form, site
     footer all hide.
   - Black on white. Cream/ochre theming dropped for ink economy.
   - Each finding slot stays on one page when possible; report header
     sticks to the first body block.
   - Disclaimer repeats at the bottom of every page via `body::after`
     (Chrome's print engine duplicates `position: fixed` on each page).
   ========================================================================= */

@media print {

  /* Page geometry. A4 default; bottom margin reserves room for the
     running disclaimer footer below. */
  @page {
    size: A4;
    margin: 14mm 12mm 22mm 12mm;
  }

  /* Reset colours and chrome — black on white, drop tinted backgrounds
     and shadows. Browsers ignore many CSS-var overrides at the :root
     level when printing iframed previews; use direct rules instead. */
  :root,
  body,
  main,
  .tearsheet-desk,
  .tearsheet,
  .sheet-header,
  .sheet-body,
  .sheet-footer,
  .facts-panel,
  .findings-grid,
  .finding-slot,
  .finding-item,
  .fact {
    background: #fff !important;
    color: #000 !important;
    box-shadow: none !important;
  }

  body { font-family: var(--ff-sheet-serif), Georgia, serif; }

  /* Hide everything that's not the tearsheet:
     - global nav and search input
     - hero / lede / fineprint
     - status / "Locating address" UI
     - the "What we check" educational section
     - waitlist signup
     - global footer
     - in-document map controls + zoom buttons (the polygons stay) */
  .site-header,
  .hero,
  .status,
  .waitlist,
  #how,
  .site-footer,
  .lookup-form,
  .findings-toolbar,
  .finding-item-swatch,
  .sheet-pdf-btn,
  .sheet-share-btn,
  .sheet-pdf-error,
  .purpose-panel,
  .leaflet-control-zoom,
  .leaflet-control-attribution { display: none !important; }

  /* Show the results section even if it carries `hidden` from the
     screen flow (the print user typically opens the URL, runs the
     lookup, then prints — but a deep-linked /snapshot/<…> page is
     ALSO a print target where results auto-render). */
  #results { display: block !important; }

  .tearsheet-desk { padding: 0 !important; max-width: none !important; }
  .tearsheet {
    border: 0 !important;
    border-radius: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    max-width: none !important;
  }

  /* Two-column body on screen → stacked on print. A4 portrait can't
     comfortably hold the map + facts + findings side-by-side at
     legible type sizes. Stack: map first, then facts + findings. */
  .sheet-body { display: block !important; }
  .sheet-map-col,
  .sheet-content-col { width: 100% !important; }
  .sheet-map { height: 95mm !important; }

  /* Remove the warm tile filter so the basemap prints in its natural
     palette (the ochre-tinted version eats ink and reads muddy on
     greyscale printers). Polygons (parcel + overlays) print as-is. */
  .sheet-map .leaflet-tile { filter: none !important; }

  /* Page-break controls.
     - sheet-header sticks to the first body block (no orphaned title).
     - facts-panel + map-col are kept whole when possible.
     - each finding-slot stays on one page when it fits.
     - findings-grid itself can break between slots. */
  .sheet-header { break-after: avoid; page-break-after: avoid; }
  .sheet-map-col { break-inside: avoid; page-break-inside: avoid; }
  .facts-panel { break-inside: avoid; page-break-inside: avoid; }
  .finding-slot { break-inside: avoid; page-break-inside: avoid; }
  .finding-item { break-inside: avoid; page-break-inside: avoid; }
  .sheet-footer { break-before: avoid; page-break-before: avoid; }

  /* Header strip — keep address, locality, report ID + timestamp
     prominent. Drop any background colour rules from screen. */
  .sheet-header,
  .sheet-address,
  .sheet-locality,
  .sheet-report-id,
  .sheet-timestamp,
  .sheet-meta-label,
  .sheet-brand-mark,
  .sheet-brand-sub { color: #000 !important; }

  /* Findings grid — drop the slot-accent border colours (greyscale-
     friendly), keep the structural rules. */
  .findings-grid { gap: 12pt !important; }
  .finding-slot[data-accent] .slot-header { border-bottom-color: #000 !important; }
  .finding-item-sublabel { color: #444 !important; }

  /* Footer / disclaimer — the in-flow `.sheet-disclaimer` prints once
     at the end of the document. The running-footer disclaimer below
     (body::after) repeats on every page so a recipient seeing only one
     page of a PDF still sees the disclaimer. */
  .sheet-disclaimer {
    color: #000 !important;
    font-size: 9pt;
    line-height: 1.45;
  }
  .sheet-sources { color: #444 !important; font-size: 8.5pt; }

  /* Running footer: repeats on every printed page in Chrome (and
     other Chromium-derived browsers — Edge, Brave, Opera). Firefox
     and Safari handle `position: fixed` differently in print, so the
     in-flow `.sheet-disclaimer` is the load-bearing copy; this is
     belt-and-braces for the most common browser. Kept short so it
     fits one line on A4 portrait. */
  body::after {
    content: "ROZH Property Snapshot — public-data summary. Not a formal Council search. Not legal or building advice. See /terms.";
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 4mm 12mm 0 12mm;
    font-family: var(--ff-sheet-sans), system-ui, sans-serif;
    font-size: 8pt;
    line-height: 1.4;
    color: #444;
    border-top: 0.5pt solid #999;
    background: #fff;
  }

  /* Drop link decoration; URLs in body text would print noisy. */
  a, a:visited { color: #000 !important; text-decoration: none !important; }

  /* Sub-label colours (CHARACTER / HERITAGE eyebrows) — keep visible
     but greyscale-friendly. */
  .finding-item-title { color: #000 !important; }
  .finding-item-body { color: #000 !important; }
  .finding-reference { color: #444 !important; }

  /* Parcel-diagnostic line ("Assessed against lot boundary…") prints
     as a small caveat under the map. Keep it. */
  .parcel-diagnostic { color: #333 !important; font-size: 9pt; }
}
