/* ============================================================
   VIBES SHEET — foundation
   One stylesheet, two domains, no build step.
   Theme switch: <html data-site="newy"> | <html data-site="lakemac">
   Load vibes-components.css after this on every page.
   ============================================================ */

/* ---------- 0. FONTS ---------- */
/* Self-hosted, latin subset, woff2 only — no third-party request. Archivo is
   variable on both wght and wdth; --wdth-mark (106) and --wdth-display (112)
   below depend on that wdth axis, so this must stay the variable cut.
   build.sh copies fonts/ to dist/fonts/, which is what ../fonts/ resolves to. */


@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("../fonts/woff2/archivo-variable-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-stretch: 100%;
  font-display: swap;
  src: url("../fonts/woff2/ibm-plex-sans-variable-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/woff2/ibm-plex-mono-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/woff2/ibm-plex-mono-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---------- 1. TOKENS ---------- */

:root {
  /* Newy Vibes — harbour, brick, coal loader, steelworks oxide */
  --paper:    #E6E7E1;
  --paper-2:  #DFE0D9;
  --ink:      #17191C;
  --muted:    #55584F;   /* body-safe: 6.5:1 on paper */
  --faint:    #7A7D74;   /* annotation only, never body copy */
  --signal:   #A83A19;
  --signal-2: #8A5E0E;
  --rule:     #17191C;

  --font-display: "Archivo", system-ui, sans-serif;
  --font-body:    "IBM Plex Sans", system-ui, sans-serif;
  --font-data:    "IBM Plex Mono", ui-monospace, monospace;

  --wdth-mark:    106;   /* wordmark — warmer than the rest of the page */
  --wdth-display: 112;   /* headlines */

  --hair:      1px solid var(--rule);
  --hair-soft: 1px solid color-mix(in srgb, var(--rule) 26%, transparent);

  --sheet-max: 1180px;

  /* Spacing scale. Colour, type and width were tokens from the start; spacing
     was not, so every component picked its own numbers and the sheets ended up
     with 29 distinct values across 200 declarations — 5, 11, 13, 15, 26, 34,
     38, 54. Invisible in a diff, obvious on a page, and worst on a phone where
     the gaps sit next to each other. 4-based, because the hairline rhythm is. */
  --s1:  4px;
  --s2:  8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;
}

[data-site="lakemac"] {
  /* Lake Mac Vibes — channel blue, seagrass, shell grey */
  --paper:    #E4E9E6;
  --paper-2:  #DBE2DE;
  --ink:      #16232B;
  --muted:    #4A5D57;
  --faint:    #70847D;
  --signal:   #215B6B;
  --signal-2: #5E6E33;
  --rule:     #16232B;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #16171A; --paper-2: #1D1F22; --ink: #E6E7E1;
    --muted: #A6A9A1; --faint: #83867E;
    --signal: #E0703F; --signal-2: #E0AA45; --rule: #3A3C3F;
  }
  [data-site="lakemac"] {
    --paper: #101A20; --paper-2: #16242C; --ink: #E4E9E6;
    --muted: #9AAFA8; --faint: #778C85;
    --signal: #5AA9BD; --signal-2: #AEC177; --rule: #2C3E47;
  }
}

/* ---------- 2. FOUNDATION ---------- */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  font-synthesis: none;
}

/* Nothing in this system is rounded. Plans have corners. */
input, button, select, textarea, img, table { border-radius: 0; }

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

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

.sheet { max-width: var(--sheet-max); margin: 0 auto; padding: 0 24px; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; }

/* Sitewide visibility utility. It lived in style.css, which task 5.4 removed
   from _base.html — so from that commit onward every `.hidden` element on the
   site was visible: 817 uses across pages/, 45 JS toggles, an empty
   contamination block on suburb pages, and check.html's entire report scaffold
   showing before a search had run. Utilities belong here, beside .sr-only. */
.hidden { display: none !important; }

/* ---------- 3. TYPE ---------- */

h1, h2, h3 {
  font-family: var(--font-display);
  font-variation-settings: "wdth" var(--wdth-display);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.012em;
  margin: 0;
  text-wrap: balance;
}

h1 { font-size: clamp(29px, 5vw, 54px); }
h2 { font-size: clamp(21px, 3vw, 32px); }
h3 { font-size: clamp(15px, 1.8vw, 19px); }

/* Heading rhythm belongs to the type scale, not to one container. It lived on
   `.article__body h2` alone, so a heading on any .sheet page — every index,
   every ranking, /suburbs.html, /check.html — had margin 0 and sat flush
   against the block above it. "Ways in" and "Notes" had a measured gap of
   zero. Components that place a heading inside a row (.list__item, .lens,
   .suburb-row, .note) set their own margins and still win. */
h2 { margin: var(--s6) 0 var(--s3); }
h3 { margin: var(--s5) 0 var(--s2); }
h2:first-child, h3:first-child { margin-top: 0; }

/* Paragraph rhythm is declared, not inherited. The browser default is 1em,
   so an undeclared <p> spaced itself by its own font-size: 14px next to a
   .verdict, 15px next to a .door, 16px in body copy. Three different gaps
   between the same two things, and nothing in the sheet to show it. */
p { max-width: 62ch; margin: 0 0 var(--s4); }
p:last-child { margin-bottom: 0; }

/* Numerals, distances and dates are monospaced. Category names are not —
   plain English carries the meaning, the mono carries the measurement. */
.data, .meta, .note-no, .legend-count { font-family: var(--font-data); font-variant-numeric: tabular-nums; }

.meta { font-size: 12px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted); }
.meta--signal { color: var(--signal); }

/* ---------- 4. TITLE BLOCK ---------- */

.titleblock {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  /* padding-block, not the `12px 0` shorthand: .titleblock is always paired
     with .sheet, and the shorthand's horizontal 0 overrode .sheet's 24px
     gutter. On desktop the sheet is narrower than the viewport so nothing
     showed; on a phone the wordmark, the nav and the register line all sat
     hard against the left edge while the content below them did not. */
  gap: 16px; padding-block: 12px; border-bottom: var(--hair);
}

.wordmark {
  display: inline-flex; align-items: center; min-height: 44px;
  font-family: var(--font-display);
  font-variation-settings: "wdth" var(--wdth-mark);
  font-weight: 700; font-size: 21px; letter-spacing: -0.02em; text-decoration: none;
}

.titleblock nav { display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 14px; }
/* 44px of vertical target, not 25. The link still reads as a hairline-underlined
   word — the padding is above and below the rule, so nothing moves visually. */
.titleblock nav a {
  display: inline-flex; align-items: center; min-height: 44px;
  /* The rule hugs the text, so it must be a text decoration and not a
     border — a border-bottom sits at the foot of the 44px box and reads
     as a detached line floating under the word. */
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--rule) 26%, transparent);
  text-decoration-thickness: 1px; text-underline-offset: 4px;
}
.titleblock nav a[aria-current="page"] { text-decoration-color: var(--signal); color: var(--signal); }

/* Burger toggle. CSS only, driven by a checkbox: about, privacy, terms and
   suburbs load no JavaScript at all, so a scripted toggle would leave the
   menu unopenable on four of the seven pages that carry this masthead.
   Both parts are off on desktop — the checkbox included, or a keyboard user
   would tab into an invisible control that changes nothing. The mobile
   rules live in the 780px block at the foot of this file. */
.menu-check, .burger { display: none; }

/* The meta slot must state something true. On the homepage: register count
   and collection date. On an address sheet: sheet no. and council. Never
   invented revision numbers. */

/* ---------- 5. RADIUS PLOT (homepage only) ---------- */
/* On results and suburb pages the map replaces this. The ring is drawn
   identically in both so the promise and the delivery match. */

.scan {
  display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr);
  gap: 48px; align-items: center;
  padding: 48px 24px; border-bottom: var(--hair);
  max-width: var(--sheet-max); margin: 0 auto;
}

.scan__plot { width: 100%; height: auto; display: block; }
.scan__ring { fill: none; stroke: var(--rule); stroke-width: 1; opacity: 0.55; }
.scan__ring--outer { stroke-dasharray: 4 5; }
.scan__cross { stroke: var(--rule); stroke-width: 0.75; opacity: 0.24; }
.scan__origin { fill: var(--ink); }
.scan__label { font-family: var(--font-data); font-size: 13px; fill: var(--faint); }
.scan__pin   { font-family: var(--font-data); font-size: 14px; fill: var(--ink); }
.scan__mark      { fill: var(--signal); }
.scan__mark--alt { fill: var(--signal-2); }

.scan__sweep {
  stroke: var(--signal); stroke-width: 1.25; transform-origin: 50% 50%;
  animation: sweep 1900ms cubic-bezier(0.32, 0, 0.2, 1) both;
}
.scan__signal {
  opacity: 0; animation: land 420ms ease-out both;
  animation-delay: calc(320ms + var(--i, 0) * 190ms);
}

@keyframes sweep { from { transform: rotate(-8deg); opacity: 1; } to { transform: rotate(352deg); opacity: 0; } }
@keyframes land  { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .scan__sweep { display: none; }
  .scan__signal { animation: none; opacity: 1; }
}

/* ---------- 6. ADDRESS FIELD ---------- */

.field { display: flex; border: var(--hair); background: var(--paper); }
.field input {
  flex: 1; min-width: 0; border: 0; background: transparent;
  padding: 16px 12px; font-family: var(--font-data); font-size: 15px; color: var(--ink);
}
.field input::placeholder { color: var(--faint); }
.field input:focus { outline: 0; }
.field:focus-within { box-shadow: inset 0 0 0 1px var(--signal); }
.field button {
  border: 0; border-left: var(--hair); background: var(--ink); color: var(--paper);
  padding: 0 24px; font-family: var(--font-data); font-size: 13px;
  letter-spacing: 0.08em; text-transform: uppercase; cursor: pointer;
}
.field button:hover { background: var(--signal); }

/* Suburb autocomplete under the field. Markup comes from landing.js; these
   rules replace the ones that left with landing.css. Hairlines only — the
   list is a continuation of the field, not a floating card. */
.search-suggestions {
  border: var(--hair); border-top: 0; background: var(--paper);
  max-height: 300px; overflow-y: auto;
}
.search-suggestions.hidden { display: none; }
.suggestion-item {
  display: flex; align-items: baseline; gap: 12px;
  padding: 11px 12px; border-bottom: var(--hair-soft); cursor: pointer;
}
.suggestion-item:last-child { border-bottom: 0; }
.suggestion-item:hover, .suggestion-active { background: var(--paper-2); }
.suggestion-title { font-size: 15px; }
.suggestion-subtitle { font-family: var(--font-data); font-size: 13px; color: var(--signal); }
.suggestion-type { margin-left: auto; font-family: var(--font-data); font-size: 12px; color: var(--faint); }

/* Address type-ahead against the national address register. A continuation of
   the field, same as .search-suggestions — hairlines, not a floating card. */
.address-options {
  list-style: none; margin: 0; padding: 0;
  border: var(--hair); border-top: 0; background: var(--paper);
  max-height: 320px; overflow-y: auto;
}
.address-options.hidden { display: none; }
.address-option {
  padding: 11px 12px; border-bottom: var(--hair-soft);
  cursor: pointer; font-size: 15px;
}
.address-option:last-child { border-bottom: 0; }
.address-option:hover,
.address-option-active { background: var(--paper-2); }
.address-option-note {
  padding: 8px 12px; border-bottom: var(--hair-soft);
  font-family: var(--font-data); font-size: 12px; color: var(--signal);
  letter-spacing: 0.03em;
}

/* The Check button is disabled until a real address is picked. */
.field button[disabled] { opacity: 0.45; cursor: not-allowed; }
.field button[disabled]:hover { background: var(--ink); }

/* Address search failure: the message, plus "did you mean" or the suburbs an
   ambiguous street could be in. Populated by showError() in js/app.js. */
.error-state { padding: 16px 0; }
.error-message { font-size: 15px; color: var(--ink); margin: 0; }

.address-suggestions {
  list-style: none; margin: 12px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 8px;
}
.address-suggestions.hidden { display: none; }
.address-suggestion {
  font-family: var(--font-data); font-size: 13px; letter-spacing: 0.04em;
  padding: 7px 12px; border: var(--hair); background: var(--paper);
  color: var(--ink); cursor: pointer;
}
.address-suggestion:hover,
.address-suggestion:focus-visible { background: var(--ink); color: var(--paper); }

/* ---------- 7. LEGEND ---------- */
/* Plain-English names. Register codes are for the pipeline, not the reader. */

.legend { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); border-top: var(--hair); border-left: var(--hair); }
.legend__item { border-right: var(--hair); border-bottom: var(--hair); padding: 16px; display: flex; gap: 12px; align-items: flex-start; }
.legend__key { width: 11px; height: 11px; margin-top: 4px; flex: none; background: var(--signal); }
.legend__key--alt { background: var(--signal-2); }
.legend__name { font-size: 15px; font-weight: 500; margin: 0; }
.legend__src { font-size: 13px; color: var(--muted); margin: 2px 0 0; }
.legend-count { font-size: 14px; margin-left: auto; color: var(--signal); }

/* The same grid, but every cell is a link. Used by #start-here, where the
   tiles are the suburb journey's entry points rather than a key to the plot.
   No underline: at this size twelve underlined cells read as a wall of rules,
   and the whole cell is already the target — the arrow and the hover carry
   the affordance instead. 44px min-height is the tap target, not decoration. */
/* Explicit counts, not auto-fit. Both rows hold exactly six tiles, and
   auto-fit resolved to five at desktop width — one orphan tile sitting beside
   four empty cells, twice. 6 / 3 / 2 all divide six, so every row stays full
   at every width. */
.legend--links { grid-template-columns: repeat(6, 1fr); }
@media (max-width: 1000px) { .legend--links { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 620px)  { .legend--links { grid-template-columns: repeat(2, 1fr); } }

.legend--links .legend__item {
  text-decoration: none; color: var(--ink); min-height: 44px;
  transition: background 120ms ease, color 120ms ease;
}
.legend--links .legend__item:hover { background: var(--ink); color: var(--paper); }
.legend--links .legend__item:hover .legend__src { color: var(--paper); opacity: 0.72; }
/* The key square is the one thing that must not invert — it is the same
   colour token the plot uses, and flipping it would break the association. */
.legend--links .legend__item:hover .legend__key { background: var(--paper); }
/* NBSP, not a plain space: at six columns "Rising momentum" and "Most
   development" broke before the arrow and left it stranded on its own line. */
.legend--links .legend__name::after { content: "\00A0\2192"; color: var(--signal); }
.legend--links .legend__item:hover .legend__name::after { color: var(--paper); }

/* Guides carry no description, so the cell would otherwise be half the height
   of a ranking tile sitting directly above it. */
.legend--compact .legend__item { align-items: center; }

/* ---------- 8. BLOCKS ---------- */

/* padding-block, same reason as .titleblock and .foot — the shorthand's
   horizontal 0 cancelled .sheet's 24px gutter, so the example rows and the
   notes ran to both edges of a phone screen. */
.block { padding-block: 48px; border-bottom: var(--hair); }
.block__head { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; margin-bottom: 24px; flex-wrap: wrap; }

/* ---------- 9. DISTANCE ROWS ---------- */
/* Order encodes distance. Nearest first. Real information. */

.rows { border-top: var(--hair); }
.row { display: grid; grid-template-columns: 80px 1fr auto; gap: 16px; align-items: baseline; padding: 16px 0; border-bottom: var(--hair-soft); }
.row__dist { font-family: var(--font-data); font-size: 15px; color: var(--signal); font-variant-numeric: tabular-nums; }
.row__what { margin: 0; font-size: 16px; max-width: none; }
.row__what small { display: block; color: var(--muted); font-size: 14px; line-height: 1.5; margin-top: 2px; }
.row__reg { font-size: 13px; color: var(--muted); }

/* A row that is a link. The findings rows on this page are static text, so
   this only applies where a row leads somewhere — the #watching strip. No
   underline: the row is the target, and an underline across a three-column
   grid reads as a rule, not a link. */
a.row { text-decoration: none; color: var(--ink); }
a.row:hover { background: color-mix(in srgb, var(--rule) 8%, transparent); }
a.row:hover .row__what { color: var(--signal); }
/* The signal word is the payload, so it stops being muted here. */
#watching .row__reg { color: var(--signal); font-family: var(--font-data); }

/* ---------- 10. LEDGER ---------- */

.ledger { width: 100%; border-collapse: collapse; font-size: 16px; }
.ledger th { text-align: left; font-size: 12px; font-weight: 500; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted); padding: 8px 16px 8px 0; border-bottom: var(--hair); }
.ledger td { padding: 12px 16px 12px 0; border-bottom: var(--hair-soft); vertical-align: top; }
.ledger td:first-child { color: var(--muted); width: 44%; }

/* ---------- 11. QUOTE ---------- */
/* The only place a person appears. No photo, no stars, no card.
   If there is no real quote, omit the block. Empty beats invented. */

.quote { border-top: var(--hair); border-bottom: var(--hair); padding: 32px 0; margin: 0; }
.quote p { font-family: var(--font-display); font-variation-settings: "wdth" 104; font-size: clamp(19px, 2.4vw, 26px); line-height: 1.3; margin: 0 0 12px; max-width: 34ch; }
.quote footer { font-size: 14px; color: var(--muted); }

/* ---------- 12. NOTES ---------- */
/* Numbered because notes on a plan are numbered and get referenced. */

.notes { border-top: var(--hair); }
.note { display: grid; grid-template-columns: 46px 1fr; gap: 16px; padding: 16px 0; border-bottom: var(--hair-soft); }
.note-no { font-size: 13px; color: var(--muted); padding-top: 3px; }
.note h3 { margin: 0 0 4px; }
.note p { margin: 0; font-size: 16px; }

/* ---------- 13. REGISTER / FOOTER ---------- */

.register__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 24px; }
.register h4 { font-size: 12px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted); font-weight: 500; margin: 0 0 8px; }
.register ul { list-style: none; margin: 0; padding: 0; font-size: 15px; }
.register li { padding: 3px 0; }
.register li a { text-decoration: none; border-bottom: var(--hair-soft); }

/* padding-block for the same reason as .titleblock — the shorthand's
   horizontal 0 was cancelling .sheet's gutter, so the whole footer ran to the
   edge of a phone screen. */
.foot { padding-block: 32px 48px; font-size: 14px; color: var(--muted); }
.foot__rule { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; border-top: var(--hair); padding-top: 12px; margin-top: 24px; }

/* ---------- 14. RESPONSIVE ---------- */

@media (max-width: 780px) {
  .scan { grid-template-columns: 1fr; gap: 24px; padding: 32px 24px; }
  .scan__figure { order: 2; }
  /* SVG text scales with the viewBox, so bump it in user units or it
     renders at ~7px on a phone. */
  /* 21, not 22: the longest surviving pin is "Road noise 174 m", which anchors
     start at x=434 and measured 645 at 22px — five units past the 640 viewBox,
     so the last glyph was clipped. It never showed before because that pin used
     to be hidden on phones. */
  .scan__pin { font-size: 21px; }
  .scan__label { font-size: 21px; }
  /* Six markers is unreadable at 380px, so the colliding pins go. It said
     "keep three" and kept two, both of them approvals — the phone lost every
     other category. Three now, spanning 123 m to 286 m and two kinds of
     finding. The figcaption claims no count precisely because this number
     changes with the viewport. */
  .scan__signal--dense { display: none; }
  .row { grid-template-columns: 66px 1fr; }
  .row__reg { grid-column: 2; margin-top: -4px; }
  .ledger td:first-child { width: auto; }

  /* ---- Masthead: five links become a burger ----
     Wrapped, the nav took three lines and pushed the page down before it
     said anything. Collapsed, line one is the wordmark and the toggle, and
     the register line and the open menu each take a full row of their own
     so the wrap order never depends on how long the meta text is. */
  .burger {
    display: inline-flex; align-items: center; justify-content: flex-end;
    width: 44px; min-height: 44px; cursor: pointer; color: inherit;
  }
  /* Visually hidden, not display:none — the label does the pointing, but the
     checkbox is what the keyboard focuses and Space toggles. */
  .menu-check {
    display: block; position: absolute; width: 1px; height: 1px;
    opacity: 0; pointer-events: none;
  }
  .menu-check:focus-visible ~ .burger { outline: 2px solid var(--signal); outline-offset: 2px; }

  /* Three hairlines that fold into a cross. One element, two pseudos. */
  .burger span, .burger span::before, .burger span::after {
    display: block; width: 22px; height: 1.5px; background: currentColor;
    transition: transform 120ms ease, top 120ms ease, background 120ms ease;
  }
  .burger span { position: relative; }
  .burger span::before, .burger span::after { content: ""; position: absolute; }
  .burger span::before { top: -6px; }
  .burger span::after { top: 6px; }
  .menu-check:checked ~ .burger span { background: transparent; }
  .menu-check:checked ~ .burger span::before { top: 0; transform: rotate(45deg); }
  .menu-check:checked ~ .burger span::after { top: 0; transform: rotate(-45deg); }

  .titleblock nav { display: none; flex-basis: 100%; flex-direction: column; gap: 0; }
  .menu-check:checked ~ nav { display: flex; }
  /* Stacked, each link is a row and the hairline under the word reads as an
     underline again only because it hugs the text — so keep the rule off the
     row and let the row take its own separator. */
  .titleblock nav a { border-top: var(--hair-soft); }
  .titleblock > .meta { flex-basis: 100%; }
}

@media (max-width: 780px) and (prefers-reduced-motion: reduce) {
  .burger span, .burger span::before, .burger span::after { transition: none; }
}

/* ---------- SEO breadcrumb ----------
   Moved out of _base.html's inline <style> in task 1.5. Keyed to --signal;
   --brand-accent no longer exists. */
.seo-breadcrumb { font-size: 0.85rem; color: var(--muted); margin-bottom: 1rem; }
.seo-breadcrumb a { color: var(--signal); text-decoration: none; }
.seo-breadcrumb a:hover { text-decoration: underline; }

/* The closing hint under the address matches reads as guidance, not an
   option — it sits below the list and never takes a hover or a click. */
.address-option-foot { border-bottom: 0; border-top: var(--hair-soft); color: var(--muted); }

/* A suburb offered inside the address list. Tagged, because the whole failure
   it fixes was someone typing "Warners Bay" and being handed houses on Warners
   Bay Road — the row has to say which kind of thing it is. */
.address-option-suburb { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); }
.address-option-tag {
  font-family: var(--font-data); font-size: 12px; letter-spacing: 0.04em;
  color: var(--muted); white-space: nowrap;
}
/* The way out for someone who has not picked a suburb yet. */
.address-option-explore {
  font-family: var(--font-data); font-size: 13px; color: var(--signal);
  border-top: var(--hair-soft);
}
