:root {
  /* ALIAS LAYER onto the generated tokens (static/css/tokens.css, from design-engine/tokens.json).
     The site keeps its own variable names — renaming --navy to --c-primary-navy across 560 lines
     would be churn and risk for no gain, and RULING 2 says restyle, not restructure. What changes
     is where the VALUES come from: every colour below now resolves to a token. Nothing is authored
     here. If you want to change a colour, change tokens.json and re-run scripts/brand/emit_tokens.py. */
  --navy:       var(--c-primary-navy);
  --navy-mid:   var(--c-secondary-navy);
  --navy-light: var(--c-deep-slate);
  --gold:       var(--c-luxury-gold);
  --gold-light: var(--c-soft-gold);
  --white:      var(--c-white);
  --off-white:  var(--c-light-grey);

  /* Muted text is the cream at an alpha — ONE system, not a second grey (Ruling 4). */
  --text-muted: rgba(var(--c-light-grey-rgb), 0.62);
  --text-dim:   rgba(var(--c-light-grey-rgb), 0.32);

  /* --hairline was USED THREE TIMES AND NEVER DECLARED, so those borders rendered NOTHING.
     It is declared SOLID, not as a gradient: every call site is `border: 1px solid var(--hairline)`,
     and a linear-gradient is invalid in a border-colour context — it would render nothing, i.e. it
     would not fix the bug at all. The engine's DISSOLVING rule is a different thing (a background
     gradient on a 1px element) and is available as --hairline-fade for the W3 grammar pass. */
  --hairline: var(--hairline-solid);

  /* Hero photograph dim. A multiplier, not a colour — no new hex, and nothing in tokens.json
     expresses "how bright is this one photo", which is a per-image art-direction call rather than
     a brand value. Named here rather than inlined so the level is adjustable in one place and the
     .hero-bg::before rule stays about WHERE the filter applies (see its note) rather than how much. */
  --hero-photo-dim: 0.62;   /* was 0.72 — Dan wanted darker still; see A/B/C renders (0.58/0.62/0.66)
     for the alternatives. Seam step re-measured at this value: +/-0.02, same continuity as 0.72's
     +0.06 (both well inside "under ~0.5"), so the ::before/sibling-gradient technique holds. */
}
/* ══ TYPE SCALE — derived from design-engine/tokens.json RATIOS, not copied from its px ══
   The engine is absolute px on a 1080x1080 canvas; this site is fluid clamp(). Copying 78px
   would put a 78px headline on a phone. So each step is the engine's size ÷ its body (17px),
   applied to this site's 1rem base. The RELATIONSHIPS carry; the numbers don't.            */
:root {
  --t-display-xl: 5.06rem;  /* engine displayXl 86/17 */
  --t-display-l:  3.88rem;  /* engine displayL  66/17 */
  --t-stat:       3.41rem;  /* engine statValue 58/17 */
  --t-display-m:  2.71rem;  /* engine displayM  46/17 */
  --t-body-l:     1.29rem;  /* engine bodyL     22/17 */
  --t-label:      0.88rem;  /* engine label     15/17 */
  --t-source:     0.76rem;  /* engine source    13/17 */
  --t-micro:      0.71rem;  /* engine micro     12/17 */

  /* Tracking: the engine's is px at a FIXED size; on a fluid site it must be em or it stops
     scaling. Converted at the engine's own size: label 2.6px/15px, source 2.2px/13px. */
  --track-label-em:  0.173em;
  --track-source-em: 0.169em;
  --track-micro-em:  0.100em;
}

/* ══ THE NUMERAL FIX — not cosmetic. Every number on this site IS the product. ══
   Cormorant Garamond defaults to OLD-STYLE (text) figures: the decimal sits mid-height, so
   "3.75%" renders as "3·75%" — an interpunct. On a mortgage rate. Inherited from body, so it
   reaches every figure without a per-element list that would rot. */
body { font-variant-numeric: lining-nums; font-feature-settings: 'lnum' 1; }

/* TABULAR as well, wherever a figure is the content: columns of numbers must align. */
.stat-num, .data-value, .cf-value, .lead-figure .fig, .fill {
  font-variant-numeric: lining-nums tabular-nums;
  font-feature-settings: 'lnum' 1, 'tnum' 1;
}

*, *::before, *::after { margin:0; padding:0; box-sizing:border-box; }
html { scroll-behavior:smooth; }
body { background:var(--navy); color:var(--off-white); font-family:'Jost',sans-serif; font-weight:300; overflow-x:hidden; }

/* ══ GLOBAL LINK COLOUR (2026-08-10) — the STRUCTURAL fix, not a per-component patch ══
   Until this rule existed there was no element-level `a` selector anywhere in this stylesheet
   or any of the six scoped ones — not even `a{color:inherit}` (an earlier uncommitted attempt at
   this same fix, found and superseded while building this one; it took a different, incompatible
   approach and covered none of the rest of what's below). Every anchor was dressed individually
   by class, and any anchor whose class was missed fell through to the browser's own link blue.
   That was not hypothetical: a full sweep of all 641 built pages, verified in a real browser,
   found 1,227 anchors rendering at rgb(0,0,238) on navy — 2.03:1, below AA at any text size — plus
   1,314 more anchors with no author colour rule at all, invisible-proof today only because every
   child inside them happens to carry its own colour.

   TWO PARTS. (1) `--link`/`--link-hover` custom properties, declared once here and consumed by
   the `a` rule below at specificity (0,0,1) — the lowest an element selector can have, so every
   existing class rule (`.nav-links a`, `.cd-root a`, `.footer-col a`, `.inline` and the rest)
   keeps winning, order-independently; this is a FLOOR, not an override. (2) Light plates
   (`.ep-root`, `.yi-root`) re-declare the `--link` VARIABLE on themselves, not the anchor colour
   — see their own stylesheets. Custom properties inherit, so a plate declares its surface once
   and every anchor inside it, including ones added later, resolves correctly through this same
   floor rule. That is what actually fixes the CLASS of bug: a hardcoded colour here would fix
   today's blue and reproduce the exact same failure the first time a link lands on a light band
   (and one already had — see yield-index.css's .yi-methodology note, fixed alongside this).

   White, not cream: on the three navy tones this measures 15.8–19.1:1. On `.ep-root`/`.yi-root`'s
   cream and white plates it would be 1.00–1.09:1 — invisible — which is exactly why those declare
   their own `--link` instead of taking this one.

   The persistent underline is deliberate, not decorative: white text in a cream-toned paragraph
   (`--off-white`) is close enough that colour alone won't tell a reader a run of text is a link —
   WCAG 1.4.1, use more than colour to convey information. Existing button/pill/nav anchors all
   already set their own `text-decoration:none` at higher specificity, so this only reaches the
   naked prose links the floor exists for. */
:root {
  --link: var(--c-white);
  --link-hover: var(--gold-light);
}
a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-color: rgba(var(--c-white-rgb), 0.4);
  text-underline-offset: 0.15em;
  transition: color 0.3s, text-decoration-color 0.3s;
}
a:hover, a:focus-visible { color: var(--link-hover); text-decoration-color: var(--link-hover); }
/* :visited — previously unset anywhere, so a naked anchor went UA purple (#551A8B, ~1.73:1 on
   navy) the moment it was clicked, worse than the blue this whole fix removes. Same colour as
   unvisited: this is a reference/citation site, not a link-heavy directory where "already read"
   is a useful signal, so there is no reason to introduce a second link colour. */
a:visited { color: var(--link); }
/* :focus-visible — previously unset anywhere on an anchor; kept keyboard-only (not :focus) so a
   mouse click doesn't leave a ring behind. Gold outline reads clearly against every band on the
   site, dark or light, without needing its own light-plate override. */
a:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 2px; }

/* NAV */
#navbar {
  position:fixed; top:0; left:0; right:0; z-index:100;
  padding:1.4rem 5rem;
  display:flex; align-items:center; justify-content:space-between;
  transition:background 0.5s ease, padding 0.4s ease, border-color 0.5s ease;
  /* At rest the navbar is transparent (it only gains a background past 60px of scroll), and it
     spans the full width - so it overlaps the hero photograph, which is now UNWASHED on the right.
     Measured: "Newsletter" was landing on a lit window at 1.66:1. This scrim is a NAV affordance,
     not a wash on the image: it darkens only the top ~90px, which is sky, and protects the links
     over any future hero. */
  background:linear-gradient(180deg, rgba(var(--c-primary-navy-rgb),0.92) 0%,
                                     rgba(var(--c-primary-navy-rgb),0.55) 55%,
                                     rgba(var(--c-primary-navy-rgb),0) 100%);
  border-bottom:1px solid transparent;
}
#navbar.scrolled {
  background:rgba(var(--c-primary-navy-rgb),0.96);
  backdrop-filter:blur(14px);
  padding:0.9rem 5rem;
  border-bottom-color:rgba(var(--c-luxury-gold-rgb),0.15);
}
.nav-logo {
  display:flex; align-items:center; gap:0.9rem; text-decoration:none;
}
.nav-logo img {
  /* 88, not 110: at 110 the mark competed with the hero figure. A logo should sit quietly — the
     £270,080 is the message. 88px keeps the framed variant well above Ruling 8's floor (stroke
     1.32px vs the 0.96 minimum), so it stays D-full rather than losing its frame.
     The glow comes down with it (0.2 -> 0.12): it is a GOLD HALO, so it was part of what pulled the
     eye. It still reads the token via --c-luxury-gold-rgb — the token itself is untouched, this is
     one rule's local use of it. The mark's own frame is dimmed in the asset (logo-nav.png), not
     here, because CSS opacity cannot dim the gold without also dimming the cream letters. */
  height:88px; width:88px; object-fit:contain;
  filter:drop-shadow(0 2px 8px rgba(var(--c-luxury-gold-rgb),0.12));
}
.nav-logo-text {
  font-family:'Cinzel',serif;
  font-size:0.68rem; letter-spacing:0.22em;
  color:var(--gold); text-transform:uppercase; line-height:1.4;
  border-left:1px solid rgba(var(--c-luxury-gold-rgb),0.3);
  padding-left:0.9rem;
}
.nav-links {
  /* 2.2rem, not 2.8rem — history (item count has changed several times since): this was originally
     tuned when an 8th flat item (PRS Checker) pushed the row 28px past its available width at
     1440px, where the flex row's default flex-shrink:1 "fit" that not by overflowing but by
     silently squeezing .nav-cta narrower than its "Subscribe Free" text needs — wrapping it onto
     two lines that then overlapped the divider below the nav. 2.2rem reclaims enough per gap to
     clear that shortfall with real headroom at 1440px and above.
     THAT HEADROOM DISAPPEARS well before the ~1000px hamburger breakpoint, though — this rule was
     only ever verified at 1440px/1920px, not at the intermediate desktop widths between the
     hamburger cutoff and ~1140px, where today's item set (Rental/Compliance dropdowns + Data +
     Newsletter + Contact + the CTA) is too wide for 2.2rem gaps to fit on one line even though the
     hamburger hasn't taken over yet — the exact "silently squeezing .nav-cta... wrapping it onto
     two lines" failure this rule was written to prevent, just re-appearing in a width band nobody
     checked. See the scoped fix for that band, just below. */
  /* margin:0 clears the global `ul{margin:0 0 1rem 1.2rem;}` prose-bullet rule — the SAME reset
     .footer-col ul already carries (see its own note). Not cosmetic here: #navbar is
     `align-items:center`, and flexbox centres an item's MARGIN box, so that inherited 1rem
     bottom-only margin was centring a box 16px taller than the row and lifting the links 8px above
     the logo (measured: logo centre y=66.4 vs nav y=58.4). Zeroing it makes the two centres agree
     without touching the nav's own padding or the logo's height. */
  display:flex; align-items:center; gap:2.2rem; list-style:none; margin:0;
}
/* 2026-08-07 — FIX for the dead zone above: measured (Playwright) that at 1001px (the narrowest
   width the desktop nav still renders at — anything at or below 1000px is already handled by the
   hamburger, below) the row needs ~723px at the base 2.2rem gap against ~613-634px actually
   available (that available figure itself moves a little run to run — a vertical scrollbar
   appearing/disappearing shifts it by its own width — so the fix is sized against the tighter end
   of that range, not the looser one), so .nav-cta wraps and its box doesn't grow to fit, clipping
   "Subscribe Free" against the divider exactly like the original 2.8rem->2.2rem fix above was
   written to prevent. A first pass at var(--s-sm) (12px) still wrapped — re-measured and found
   only ~6px of margin at the worst case, well inside the scrollbar-width swing above, so it wasn't
   reliably enough. var(--s-xs) (8px, still an EXISTING spacing-scale step, not a new value) is:
   at the same 1001px worst case the row needs ~587px against the same ~613px available, a real
   ~26px margin even at the tighter end — growing further as the width increases toward the point
   (~1140px) where the base 2.2rem already fits on its own. Upper bound 1145px (a few px of buffer
   past that measured 1140px crossover) so there's no visible seam where the row is tighter than it
   needs to be right as the base rule would have taken over anyway. Nothing else in this band
   changes — this touches ONLY .nav-links' own gap, not the larger max-width:1000px block's
   section/footer/logo rules, which already render correctly across this whole band and don't need
   the mobile treatment early. */
@media (min-width:1001px) and (max-width:1145px) {
  .nav-links { gap:var(--s-xs); }
}
.nav-links a {
  font-family:'Jost',sans-serif; font-weight:400;
  font-size:0.72rem; letter-spacing:0.18em; text-transform:uppercase;
  color:var(--text-muted); text-decoration:none; transition:color 0.3s;
}
.nav-links a:hover { color:var(--gold); }
.nav-cta {
  color:var(--navy) !important; background:var(--gold);
  padding:0.65rem 1.7rem !important; letter-spacing:0.16em !important;
  font-family:'Cinzel',serif !important; transition:background 0.3s !important;
}
.nav-cta:hover { background:var(--gold-light) !important; color:var(--navy) !important; }
/* Hamburger — desktop default is invisible. Only the mobile query (below, ~1000px) turns the
   bars on; nothing about the flex nav above 1000px changes. */
.nav-toggle {
  display:none; flex-direction:column; justify-content:center; gap:5px;
  width:26px; height:22px; background:none; border:0; padding:0; cursor:pointer;
}
.nav-toggle span {
  display:block; width:100%; height:2px; background:var(--gold);
  transition:transform 0.25s ease, opacity 0.25s ease;
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform:translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity:0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform:translateY(-7px) rotate(-45deg); }

/* ── RENTAL NAV DROPDOWN (2026-08-03) — the site's first nav submenu; everything else in
   .nav-links is a flat link. ".nav-dropdown-link" is a REAL link to /rental (the section landing
   page), not a JS-only toggle — the caret is a SEPARATE control that only opens/closes the
   submenu, so "Rental" always has somewhere real to land even if the submenu is never opened.
   Desktop reveal is hover/focus, CSS-only; base.html's script adds the caret click-toggle (touch-
   capable desktop, keyboard) and the mobile accordion override below. ── */
.nav-dropdown { position:relative; display:flex; align-items:center; gap:0.35rem; }
.nav-dropdown-caret {
  display:flex; align-items:center; justify-content:center;
  background:none; border:0; padding:0.2rem; margin:0; cursor:pointer;
  color:var(--text-muted); transition:color 0.3s, transform 0.25s ease;
}
.nav-dropdown-caret:hover { color:var(--gold); }
.nav-dropdown:hover .nav-dropdown-caret,
.nav-dropdown.is-open .nav-dropdown-caret,
.nav-dropdown:focus-within .nav-dropdown-caret { transform:rotate(180deg); color:var(--gold); }
.nav-dropdown-menu {
  position:absolute; top:100%; left:-1.3rem; margin-top:0.9rem; min-width:210px;
  list-style:none; background:rgba(var(--c-primary-navy-rgb),0.98); backdrop-filter:blur(14px);
  border:1px solid rgba(var(--c-luxury-gold-rgb),0.15); border-radius:6px; padding:0.6rem 0;
  opacity:0; visibility:hidden; pointer-events:none; transform:translateY(-6px);
  transition:opacity 0.25s ease, transform 0.25s ease, visibility 0.25s;
}
.nav-dropdown:hover .nav-dropdown-menu,
.nav-dropdown.is-open .nav-dropdown-menu,
.nav-dropdown:focus-within .nav-dropdown-menu {
  opacity:1; visibility:visible; pointer-events:auto; transform:translateY(0);
}
.nav-dropdown-menu li { width:100%; }
.nav-dropdown-menu a {
  display:block; padding:0.55rem 1.3rem;
  font-family:'Jost',sans-serif; font-size:0.68rem; letter-spacing:0.14em; text-transform:uppercase;
  color:var(--text-muted); text-decoration:none; white-space:nowrap;
  transition:color 0.3s, background 0.3s;
}
.nav-dropdown-menu a:hover { color:var(--gold); background:rgba(var(--c-luxury-gold-rgb),0.06); }

/* HERO */
.hero {
  position:relative; height:100vh; min-height:700px;
  display:flex; align-items:center; justify-content:center; overflow:hidden;
}
.hero-bg {
  position:absolute; inset:0;
  background-size:cover; background-position:center 65%;
  animation:kenBurns 22s ease-in-out infinite alternate;
}
@keyframes kenBurns {
  0%   { transform:scale(1.0) translateX(0px); }
  100% { transform:scale(1.09) translateX(-8px); }
}
.hero-overlay {
  position:absolute; inset:0;
  background:linear-gradient(180deg,rgba(var(--c-primary-navy-rgb),0.5) 0%,rgba(var(--c-primary-navy-rgb),0.3) 35%,rgba(var(--c-primary-navy-rgb),0.72) 78%,rgba(var(--c-primary-navy-rgb),1) 100%);
}
.hero-content {
  position:relative; z-index:2;
  text-align:center; padding:0 2rem; max-width:860px;
}
.hero-eyebrow {
  font-family:'Cinzel',serif; font-size:0.6rem; letter-spacing:0.4em;
  color:var(--gold); text-transform:uppercase; margin-bottom:2rem;
  opacity:0; animation:fadeUp 1s ease 0.4s forwards;
}
.hero-title {
  font-family:'Cormorant Garamond',serif; font-weight:300;
  font-size:clamp(2.6rem,6vw,var(--t-display-xl)); line-height:1.08;
  color:var(--white); letter-spacing:0.01em; margin-bottom:1.3rem;
  opacity:0; animation:fadeUp 1s ease 0.6s forwards;
}
.hero-title em { font-style:italic; color:var(--gold-light); }
/* ══ THE HERO INTRO — what UKPP does, before the number ═══════════════════════════════════════
   A cold visitor meets £270,080 with no idea whose site this is. This slot answers that above the
   figure. TWO OPTIONS live here; exactly ONE is rendered (see index.html). They share the slot so
   the choice is copy, not layout.

   A — THE SLOGAN. Asserts the category ("Property Intelligence. Simplified.").
   B — THE STANDFIRST. Describes what the page does, and the page then does it.
   ══════════════════════════════════════════════════════════════════════════════════════════ */

/* Option A. Cinzel gold, tracked — the brand voice, sized ABOVE the eyebrow (0.82rem vs 0.58) so it
   leads rather than competes. Flat gold, no gradient: §1 spends one accent. */
.hero-slogan {
  font-family:'Cinzel',serif; font-size:0.82rem; letter-spacing:0.3em;
  color:var(--gold); text-transform:uppercase; line-height:1.6;
  margin-bottom:0.7rem; display:block;
  opacity:0; animation:fadeUp 1s ease 0.2s forwards;
}
.hero-slogan-sub {
  font-family:'Jost',sans-serif; font-weight:300; font-size:0.9rem;
  color:var(--text-muted); letter-spacing:0.06em; line-height:1.7;
  margin-bottom:2.4rem; max-width:34ch;
  opacity:0; animation:fadeUp 1s ease 0.3s forwards;
}
/* Option B. Jost, cream-muted, sentence case — deliberately NOT gold and NOT Cinzel: this is a
   sentence, not a badge, and dressing it in the brand's ceremonial type would turn a description
   back into a claim. It sits at 1.05rem, just above the standfirst's 1rem, so it reads as the
   frame around the number rather than a second summary. */
.hero-standfirst {
  font-family:'Jost',sans-serif; font-weight:300; font-size:1.05rem;
  color:var(--text-muted); letter-spacing:0.04em; line-height:1.75;
  max-width:46ch;                             /* margin-bottom removed — .hero-content's gap supplies it */
  padding-left:1rem; border-left:1px solid rgba(var(--c-luxury-gold-rgb),0.35);
  opacity:0; animation:fadeUp 1s ease 0.2s forwards;
}

.hero-subtitle {
  font-family:'Jost',sans-serif; font-weight:300; font-size:1rem;
  color:var(--text-muted); letter-spacing:0.05em; line-height:1.8;
  /* margin-bottom removed — .hero-content's gap supplies it (this class is hero-only; nothing
     else references it, so no scoping needed the way .section-eyebrow required). */
  opacity:0; animation:fadeUp 1s ease 0.8s forwards;
}
.hero-actions {
  display:flex; gap:1.2rem; justify-content:center; flex-wrap:wrap;
  opacity:0; animation:fadeUp 1s ease 1s forwards;
}
.btn-primary {
  font-family:'Cinzel',serif; font-size:0.68rem; letter-spacing:0.22em;
  text-transform:uppercase; color:var(--navy); background:var(--gold);
  padding:1.05rem 3rem; text-decoration:none; display:inline-block;
  transition:background 0.3s, transform 0.2s, box-shadow 0.3s;
  box-shadow:0 4px 28px rgba(var(--c-luxury-gold-rgb),0.3);
}
.btn-primary:hover { background:var(--gold-light); transform:translateY(-2px); box-shadow:0 10px 36px rgba(var(--c-luxury-gold-rgb),0.45); }
.btn-secondary {
  font-family:'Cinzel',serif; font-size:0.68rem; letter-spacing:0.22em;
  text-transform:uppercase; color:var(--gold); background:transparent;
  border:1px solid rgba(var(--c-luxury-gold-rgb),0.45); padding:1.05rem 3rem;
  text-decoration:none; display:inline-block;
  transition:border-color 0.3s, color 0.3s, transform 0.2s, background 0.3s;
}
.btn-secondary:hover { border-color:var(--gold); background:rgba(var(--c-luxury-gold-rgb),0.06); color:var(--gold-light); transform:translateY(-2px); }
.hero-scroll {
  position:absolute; bottom:2.8rem; left:50%; transform:translateX(-50%);
  display:flex; flex-direction:column; align-items:center; gap:0.6rem;
  opacity:0; animation:fadeUp 1s ease 1.4s forwards;
}
.hero-scroll span {
  font-family:'Cinzel',serif; font-size:0.48rem; letter-spacing:0.35em;
  color:var(--text-dim); text-transform:uppercase;
}
.scroll-line {
  width:1px; height:52px;
  background:linear-gradient(to bottom,rgba(var(--c-luxury-gold-rgb),0.8),transparent);
  animation:scrollPulse 2.2s ease-in-out infinite;
}
@keyframes scrollPulse { 0%,100% { opacity:0.35; transform:scaleY(1); } 50% { opacity:1; transform:scaleY(0.65); } }

/* DIVIDER */
/* SECTIONS */
section { padding:7rem 5rem; }
.section-eyebrow {
  font-family:'Cinzel',serif; font-size:0.58rem; letter-spacing:0.38em;
  color:var(--gold); text-transform:uppercase; margin-bottom:1rem; display:block;
}
.section-title {
  font-family:'Cormorant Garamond',serif; font-weight:300;
  font-size:clamp(1.9rem,3.8vw,var(--t-display-m)); line-height:1.15; color:var(--white); margin-bottom:1.2rem;
}
.section-title em { font-style:italic; color:var(--gold-light); }
.section-lead {
  font-family:'Jost',sans-serif; font-weight:300; font-size:0.95rem;
  color:var(--text-muted); line-height:1.85; max-width:540px;
}

/* COVER */
.cover-card.visible { opacity:1; transform:translateY(0); }
.cover-card:hover::after { transform:scaleX(1); }
/* STATS */
/* INTEL */
/* .intel-section removed 2026-07-21 — unused: no template references it (the live section is
   .intel-brief, a different class with its own rule below). Confirmed dead before removing. */
.intel-inner { max-width:1240px; margin:0 auto; }
.intel-header {
  display:flex; align-items:flex-end; justify-content:space-between;
  margin-bottom:3.5rem; flex-wrap:wrap; gap:2rem;
}
.intel-grid { display:grid; grid-template-columns:1.65fr 1fr 1fr; gap:2px; }
.intel-card {
  background:var(--navy-light); padding:2.6rem;
  position:relative; overflow:hidden;
  opacity:0; transform:translateY(24px);
  transition:opacity 0.7s ease, transform 0.7s ease, background 0.3s;
  text-decoration:none; display:block; color:inherit;
}
.intel-card.visible { opacity:1; transform:translateY(0); }
.intel-card:hover { background:var(--navy-mid); }
.intel-card::before {
  content:''; position:absolute; top:0; left:0; right:0; height:2px;
  background:linear-gradient(to right,var(--gold),var(--gold-light));
  transform:scaleX(0); transform-origin:left; transition:transform 0.45s ease;
}
.intel-card:hover::before { transform:scaleX(1); }
.intel-tag {
  font-family:'Cinzel',serif; font-size:0.52rem; letter-spacing:0.28em;
  color:var(--gold); text-transform:uppercase; margin-bottom:1.1rem; display:block;
}
.intel-card-title {
  font-family:'Cormorant Garamond',serif; font-weight:400;
  font-size:1.25rem; color:var(--white); line-height:1.32; margin-bottom:1rem;
}
.intel-card.featured .intel-card-title { font-size:1.75rem; line-height:1.22; }
.intel-excerpt {
  font-family:'Jost',sans-serif; font-weight:300; font-size:0.84rem;
  color:var(--text-muted); line-height:1.82; margin-bottom:1.5rem;
}
.intel-date { font-family:'Jost',sans-serif; font-size:0.68rem; color:var(--text-dim); letter-spacing:0.1em; }
.intel-arrow {
  position:absolute; bottom:2.2rem; right:2.2rem; color:var(--gold); font-size:1.3rem;
  opacity:0; transform:translateX(-8px); transition:opacity 0.3s, transform 0.3s;
}
.intel-card:hover .intel-arrow { opacity:1; transform:translateX(0); }

/* SUBSCRIBE */
.subscribe-section {
  background:var(--navy-mid); position:relative; overflow:hidden;
  text-align:center; padding:8rem 5rem;
}
.subscribe-section::before {
  content:''; position:absolute; top:50%; left:50%;
  transform:translate(-50%,-50%); width:900px; height:900px;
  background:radial-gradient(circle,rgba(var(--c-luxury-gold-rgb),0.055) 0%,transparent 62%);
  pointer-events:none;
}
.subscribe-inner { position:relative; z-index:1; max-width:640px; margin:0 auto; }
.subscribe-title {
  font-family:'Cormorant Garamond',serif; font-weight:300;
  font-size:clamp(2.2rem,4.2vw,3.5rem); color:var(--white); line-height:1.12; margin-bottom:1.1rem;
}
.subscribe-title em { font-style:italic; color:var(--gold-light); }
.subscribe-lead {
  font-family:'Jost',sans-serif; font-weight:300; font-size:0.95rem;
  color:var(--text-muted); line-height:1.85; margin-bottom:2.8rem;
}
.subscribe-form {
  display:flex; max-width:500px; margin:0 auto 1.3rem;
  box-shadow:0 8px 48px rgba(var(--c-primary-navy-rgb),0.75);
}
.subscribe-form input {
  flex:1; padding:1.05rem 1.5rem;
  background:var(--navy-light); border:1px solid rgba(var(--c-luxury-gold-rgb),0.28);
  border-right:none; color:var(--white); font-family:'Jost',sans-serif;
  font-size:0.9rem; outline:none; transition:border-color 0.3s;
}
.subscribe-form input::placeholder { color:var(--text-dim); }
.subscribe-form input:focus { border-color:rgba(var(--c-luxury-gold-rgb),0.65); }
.subscribe-form button {
  font-family:'Cinzel',serif; font-size:0.62rem; letter-spacing:0.22em;
  text-transform:uppercase; background:var(--gold); color:var(--navy);
  border:none; padding:1.05rem 2rem; cursor:pointer; transition:background 0.3s; white-space:nowrap;
}
.subscribe-form button:hover { background:var(--gold-light); }
.subscribe-note { font-family:'Jost',sans-serif; font-size:0.72rem; color:var(--text-dim); }
.subscribe-note a { color:var(--gold); text-decoration:none; }
/* Inline subscribe feedback (on-site form): honest pending / success / error states. */
.subscribe-status { font-family:'Jost',sans-serif; font-size:0.82rem; min-height:1.2em; margin:0.9rem 0 0.2rem; }
.subscribe-status.pending { color:var(--text-dim); }
.subscribe-status.success { color:var(--gold-light); }
.subscribe-status.error   { color:var(--ui-error); }
.subscribe-platforms {
  margin-top:3.2rem; display:flex; align-items:center;
  justify-content:center; gap:1rem; flex-wrap:wrap;
}
.also-on { font-family:'Cinzel',serif; font-size:0.52rem; letter-spacing:0.25em; color:var(--text-dim); text-transform:uppercase; }
/* colour bumped --text-dim -> --text-muted (2026-08-10): found while proving the link-contrast
   fix — same 2.71:1 AA failure as the footer anchors above, same token, just not one Dan had
   named. --text-muted (0.62 alpha, the same value .nav-links a already uses) keeps the pill
   visually quiet without failing AA. */
.platform-pill {
  font-family:'Cinzel',serif; font-size:0.55rem; letter-spacing:0.2em;
  text-transform:uppercase; color:var(--text-muted);
  border:1px solid rgba(var(--c-luxury-gold-rgb),0.18); padding:0.52rem 1.3rem;
  text-decoration:none; transition:color 0.3s, border-color 0.3s;
}
.platform-pill:hover { color:var(--gold); border-color:rgba(var(--c-luxury-gold-rgb),0.45); }

/* FOOTER */
footer {
  background:var(--navy); padding:4rem 5rem 2.5rem;
  border-top:1px solid rgba(var(--c-luxury-gold-rgb),0.1);
}
.footer-inner {
  max-width:1240px; margin:0 auto;
  /* EVEN, not 1.8fr-then-three-narrow. The old ratio gave the brand a 393px column to hold a 230px
     tagline — a ~160px hole — and squeezed the three link lists into 218px each, bunched hard right.
     That is what read as "left-heavy": weight at both ends and a gap where the eye expects rhythm.
     Four equal columns distribute the sections across the full width instead.
     Not CENTRED: these are ragged-right link lists, and centring them would stack every list on its
     own axis so no two items share a left edge — the FT/Bloomberg register this borrows from aligns
     footer lists, it does not centre them. Distribution fixes the balance; centring would cost
     scannability to fix it twice. */
  display:grid; grid-template-columns:repeat(4, 1fr);
  gap:2.5rem 3rem; margin-bottom:3rem;
}
/* THE MARK'S OWN ROW — above the grid, sharing the grid's max-width and centring so it starts on
   the same left edge as "UK Property Portal" below it rather than floating off it. */
.footer-mark {
  max-width:1240px; margin:0 auto 2.2rem;
}
.footer-mark img {
  height:52px; object-fit:contain; display:block;
  filter:drop-shadow(0 2px 8px rgba(var(--c-luxury-gold-rgb),0.15));
}
/* The slogan sits WITH the mark — one lockup, so it stays identity rather than drifting into a
   claim. Indented to the mark's optical left edge and dimmed: it labels the mark, it is not an
   announcement. */
.footer-mark .footer-slogan { margin:0.85rem 0 0; }
/* THE BRAND NAME IS NOW A COLUMN HEADING, and is typed as one.
   It was 0.68rem/0.22em against the h4s' 0.55rem/0.28em. Lifting the logo out aligns the four
   heading TOPS, but tops are not baselines: at a different size and line-height the type still sat
   on its own line, ~2px off the other three. Since the mark above now carries the brand statement,
   this text's job here is to label its column exactly as "Intelligence" labels the next one — so it
   takes the same type and the baseline is shared by construction, not by a magic number.
   Same declarations as `.footer-col h4` below; kept as a separate rule because the element is a
   <div> in a different parent, and merging the selectors would tie the brand block's markup to the
   link columns'. */
.footer-brand-name {
  font-family:'Cinzel',serif; font-size:0.55rem; letter-spacing:0.28em;
  color:var(--gold); text-transform:uppercase; margin-bottom:1.2rem;
}
/* OPTION C — the slogan as a wordmark tagline under the mark. Cinzel gold at eyebrow scale, sitting
   with the brand name rather than over the data. Identity, not a claim. */
.footer-slogan {
  font-family:'Cinzel',serif; font-size:0.55rem; letter-spacing:0.24em;
  color:var(--gold); text-transform:uppercase; margin-bottom:0.9rem; opacity:0.75;
}
/* 30ch, not 230px: the cap exists to keep the line readable, and readability is measured in
   CHARACTERS, not pixels. At 230px it under-filled the new equal column and reopened the hole the
   grid change just closed. 30ch tracks the font and fills the column without running long. */
.footer-tagline { font-family:'Jost',sans-serif; font-size:0.82rem; color:var(--text-dim); line-height:1.7; max-width:30ch; }
.footer-col h4 {
  font-family:'Cinzel',serif; font-size:0.55rem; letter-spacing:0.28em;
  color:var(--gold); text-transform:uppercase; margin-bottom:1.2rem;
}
/* margin:0 clears the global `ul{margin:0 0 1rem 1.2rem;}` rule (prose bullet-list indent,
   below) — without it these links sit 1.2rem/19.2px right of their own h4, at every width down
   to 600px. Was previously reset only inside the <=600px mobile block (see its own note there,
   now removed as redundant); this had never been true at any wider viewport, including desktop. */
.footer-col ul { list-style:none; margin:0; }
.footer-col li { margin-bottom:0.6rem; }
/* No colour of its own (2026-08-10, was --text-dim = 2.71:1, failing AA) — falls through to the
   sitewide `a{color:var(--link)}` floor, white at 19.09:1, same system as every other plain link
   on the site rather than a special faded treatment nothing else uses. */
.footer-col a { font-family:'Jost',sans-serif; font-size:0.82rem; text-decoration:none; transition:color 0.3s; }
.footer-col a:hover { color:var(--gold); }
.footer-bottom {
  max-width:1240px; margin:0 auto; padding-top:1.8rem;
  border-top:1px solid rgba(var(--c-white-rgb),0.05);
  display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:1rem;
}
.footer-copy { font-family:'Jost',sans-serif; font-size:0.7rem; color:var(--text-dim); }
.footer-legal { display:flex; gap:1.8rem; }
/* No colour of its own — same fix and same reason as .footer-col a above. */
.footer-legal a { font-family:'Jost',sans-serif; font-size:0.7rem; text-decoration:none; transition:color 0.3s; }
.footer-legal a:hover { color:var(--gold); }
.footer-disclaimer {
  max-width:1240px; margin:1.2rem auto 0;
  font-family:'Jost',sans-serif; font-size:0.66rem;
  color:rgba(var(--c-light-grey-rgb),0.2); line-height:1.7;
}

/* ANIMATIONS */
@keyframes fadeUp { from { opacity:0; transform:translateY(26px); } to { opacity:1; transform:translateY(0); } }
.reveal { opacity:0; transform:translateY(28px); transition:opacity 0.85s ease, transform 0.85s ease; }
.reveal.visible { opacity:1; transform:translateY(0); }

/* RESPONSIVE */
@media (max-width:1000px) {
  #navbar { padding:0.6rem 1.5rem; } #navbar.scrolled { padding:0.5rem 1.5rem; }
  /* Hamburger takes over reachability here: .nav-links used to just be display:none with no
     way back in (a crawl-orphan/keyboard/mobile dead end). It's still hidden by default, but
     now as a collapsible dropdown the toggle opens — never a permanent dead end. `nav` is
     already `position:fixed` (see base rule above), which is itself a positioning context, so
     `top:100%` here anchors under the bar without any extra positioning hook needed. */
  .nav-toggle { display:flex; }
  .nav-links {
    display:none; position:absolute; top:100%; left:0; right:0;
    flex-direction:column; align-items:flex-start; gap:0; list-style:none;
    background:rgba(var(--c-primary-navy-rgb),0.98); backdrop-filter:blur(14px);
    padding:0.5rem 1.5rem 1.2rem;
    border-bottom:1px solid rgba(var(--c-luxury-gold-rgb),0.15);
  }
  .nav-links.open { display:flex; }
  .nav-links li { width:100%; }
  .nav-links a { display:block; padding:0.9rem 0; }
  .nav-links li:not(:last-child) a { border-bottom:1px solid rgba(248,245,239,0.06); }
  .nav-links .nav-cta { display:inline-block; margin-top:0.9rem; }
  /* RENTAL DROPDOWN -> MOBILE ACCORDION. No hover exists on touch, so the desktop hover-reveal
     above is dead weight here — the caret becomes the ONLY way to open it (base.html's script),
     and the menu goes from an absolutely-positioned popover to a static, indented, height-
     animated block nested inside the same row. #nav-links (an ID) is used for the submenu-link
     overrides below purely for specificity: .nav-links li:not(:last-child) a already sets a
     border-bottom on every non-last top-level link, including these nested ones, at any depth
     (a plain .nav-dropdown-menu a class selector can't outrank that rule's own specificity). */
  .nav-dropdown { position:static; display:flex; align-items:center; justify-content:space-between; width:100%; }
  .nav-dropdown-link { flex:1 1 auto; }
  .nav-dropdown-caret { padding:0.9rem 0 0.9rem 1rem; }
  .nav-dropdown-menu {
    position:static; width:100%; max-width:none; margin:0; padding:0; min-width:0;
    background:none; border:0; backdrop-filter:none; border-radius:0;
    opacity:1; visibility:visible; pointer-events:auto; transform:none;
    max-height:0; overflow:hidden; transition:max-height 0.3s ease;
  }
  .nav-dropdown.is-open .nav-dropdown-menu { max-height:20rem; }
  #nav-links .nav-dropdown-menu a {
    padding:0.7rem 0 0.7rem 1.2rem; font-size:0.66rem; color:var(--text-dim);
    border-bottom:1px solid rgba(248,245,239,0.04);
  }
  #nav-links .nav-dropdown-menu li:last-child a { border-bottom:0; }
  /* 64, not 60: Ruling 8's floor for the full mark is 64px @1x — below it the gold square's stroke
     goes sub-pixel and smudges. 60px measures fine in practice (Δ27; the true crossing is 56px, and
     the stated 64 is a deliberate conservative round-up) — but a system that obeys its own rule
     everywhere beats one that relies on knowing where the rule is soft. 4px is a cheap way to make
     the sweep provably clean. The nav-logo-text hides here, so the mark stands alone. */
  .nav-logo img { height:64px; width:64px; }
  .nav-logo-text { display:none; }
  /* 3.5rem/1.75rem, not 5rem/2.5rem: measured with .brief-page/.section-pad-y (below) as too much
     air between mobile sections — inter-section gaps ran noticeably looser than desktop's own
     7rem:5rem RATIO would predict, adding real scroll distance with no readability gain. Vertical
     only tightened here; horizontal keeps its own (smaller) proportional cut. Pages that need MORE
     top clearance than this (the first section under the fixed nav) carry .brief-page, which sets
     its own padding-top and wins on source order — this rule no longer has to double as both "the
     general mobile section rhythm" and "nav clearance" at once. */
  section, .subscribe-section { padding:3.5rem 1.75rem; }   /* .intel-section removed — dead selector */
.intel-grid { grid-template-columns:1fr; }
.footer-inner { grid-template-columns:1fr 1fr; gap:2.5rem; }
  footer { padding:3.5rem 2.5rem 2rem; }
  .subscribe-platforms { margin-top:2rem; }   /* was 3.2rem — same rhythm tightening as the section padding above */
}
@media (max-width:600px) {
.subscribe-form { flex-direction:column; }
  .subscribe-form input { border-right:1px solid rgba(var(--c-luxury-gold-rgb),0.28); }
  .footer-inner { grid-template-columns:1fr; }
  .footer-bottom { flex-direction:column; text-align:center; }

  /* ── MOBILE FOOTER (the 1-col stack). Desktop (>600px) is untouched — every rule here is inside
     this query, so the 4-column distributed footer, its shared heading baseline and the 52px
     D-small mark are byte-identical above 600px. ────────────────────────────────────────────── */

  /* 1. THE MARK — D-full at 72px. Desktop's 52px is below Ruling 8's 64px floor (frame smudges), so
     it stays frameless D-small. Mobile sizes up past the floor and the <picture>'s <source> swaps
     in logo.png (framed), so the gold border draws cleanly (~1.08px stroke). inline-block so the
     centring below applies. */
  .footer-mark img { height:72px; width:72px; display:inline-block; }

  /* 2. BREATHING ROOM under the slogan: 2.2rem -> 3.4rem between it and "UK Property Portal". */
  .footer-mark { text-align:center; margin-bottom:3.4rem; }

  /* 3. CENTER all four sections + the mark lockup — headings, links, tagline and the social row. */
  .footer-brand, .footer-col { text-align:center; }
  .footer-tagline { margin-left:auto; margin-right:auto; }
  .footer-follow ul { justify-content:center; }
}
/* ===== INTELLIGENCE EXCERPT (on-page brief) ===== */
.intel-brief { position:relative; background:var(--navy); padding:7rem 5rem 6rem; overflow:hidden; }
.intel-brief::before {
  content:''; position:absolute; top:-10%; left:50%; transform:translateX(-50%);
  width:140%; height:60%;
  background:radial-gradient(ellipse at center, rgba(var(--c-luxury-gold-rgb),0.07) 0%, transparent 60%);
  pointer-events:none;
}
.brief-inner { position:relative; z-index:1; max-width:780px; margin:0 auto; }
.brief-eyebrow { font-family:'Cinzel',serif; font-size:0.6rem; letter-spacing:0.4em; color:var(--gold); text-transform:uppercase; text-align:center; margin-bottom:1.4rem; }
.brief-title { font-family:'Cormorant Garamond',serif; font-weight:300; font-size:clamp(2.2rem,5vw,var(--t-display-l)); line-height:1.1; color:var(--white); text-align:center; letter-spacing:0.01em; margin-bottom:1rem; }
.brief-title em { font-style:italic; color:var(--gold-light); }
.brief-meta { font-family:'Jost',sans-serif; font-weight:400; font-size:0.7rem; letter-spacing:0.22em; text-transform:uppercase; color:var(--text-dim); display:flex; align-items:center; justify-content:center; gap:0.9rem; margin-bottom:4rem; flex-wrap:wrap; }
.brief-meta .dot { width:3px; height:3px; border-radius:50%; background:var(--gold); opacity:0.6; }
.data-strip { display:grid; grid-template-columns:repeat(4,1fr); border-top:1px solid rgba(var(--c-luxury-gold-rgb),0.18); border-bottom:1px solid rgba(var(--c-luxury-gold-rgb),0.18); margin-bottom:4rem; }
.data-cell { padding:1.6rem 1rem; text-align:center; border-right:1px solid rgba(var(--c-luxury-gold-rgb),0.18); }
.data-cell:last-child { border-right:none; }
.data-label { font-family:'Jost',sans-serif; font-size:0.6rem; font-weight:400; letter-spacing:0.18em; text-transform:uppercase; color:var(--text-dim); margin-bottom:0.6rem; }
.data-value { font-family:'Cormorant Garamond',serif; font-weight:400; font-size:1.9rem; color:var(--off-white); line-height:1; }
.data-delta { font-family:'Jost',sans-serif; font-size:0.7rem; font-weight:400; letter-spacing:0.04em; margin-left:0.3rem; }
/* RULING 6 — the up/down COLOURS are retired. The same number means opposite things to
   different readers: a falling mortgage rate is good news to a landlord, a falling house price
   is bad news to a seller. Colour must not tell the reader which. Direction is carried by the
   SIGN, which the delta text already has ("+3.8% yoy"), and emphasis by gold — never by hue.
   The .up/.down classes REMAIN in the markup (Ruling 2: no class renames); they simply no
   longer colour anything. Re-adding a green here is re-adding an opinion. */
.data-delta.up, .data-delta.down { color:var(--text-muted); }
.intel-item { margin-bottom:3.2rem; }
.intel-item:last-of-type { margin-bottom:0; }
.item-tag { font-family:'Cinzel',serif; font-size:0.62rem; font-weight:500; letter-spacing:0.26em; text-transform:uppercase; color:var(--gold); display:inline-flex; align-items:center; gap:0.7rem; margin-bottom:1rem; }
.item-tag::before { content:''; width:22px; height:1px; background:var(--gold); opacity:0.7; }
.item-headline { font-family:'Cormorant Garamond',serif; font-weight:400; font-size:clamp(1.5rem,3vw,var(--t-display-m)); line-height:1.2; color:var(--white); margin-bottom:1rem; letter-spacing:0.01em; }
.item-headline em { font-style:italic; color:var(--gold-light); }
.item-body { font-family:'Jost',sans-serif; font-weight:300; font-size:1.02rem; color:var(--text-muted); line-height:1.85; }
.item-body + .item-body { margin-top:1rem; }
.item-body strong { color:var(--off-white); font-weight:400; }
.lead-figure { display:flex; align-items:baseline; gap:1.1rem; margin:1.6rem 0; padding-left:1.4rem; border-left:2px solid var(--gold); }
.lead-figure .fig { font-family:'Cormorant Garamond',serif; font-weight:500; font-style:italic; font-size:3rem; color:var(--gold-light); line-height:0.9; }
.lead-figure .fig-text { font-family:'Jost',sans-serif; font-weight:300; font-size:0.92rem; color:var(--text-muted); line-height:1.5; }
.item-rule { height:1px; background:rgba(var(--c-luxury-gold-rgb),0.18); margin:3.2rem 0; }
.gate { position:relative; }
.gate-fade { position:relative; max-height:150px; overflow:hidden; }
.gate-fade::after { content:''; position:absolute; inset:0; background:linear-gradient(180deg, transparent 0%, rgba(var(--c-primary-navy-rgb),0.6) 45%, var(--navy) 92%); }
.gate-cta { text-align:center; margin-top:2.2rem; }
.gate-line { font-family:'Cormorant Garamond',serif; font-style:italic; font-weight:300; font-size:1.3rem; color:var(--off-white); line-height:1.5; max-width:520px; margin:0 auto 0.8rem; }
.gate-sub { font-family:'Jost',sans-serif; font-weight:300; font-size:0.9rem; color:var(--text-muted); margin-bottom:2rem; }
.gate-sub strong { color:var(--gold-light); font-weight:400; }
.gate-note { font-family:'Jost',sans-serif; font-size:0.72rem; color:var(--text-dim); margin-top:1.3rem; letter-spacing:0.04em; }
@media (max-width:680px) {
  .intel-brief { padding:5rem 1.6rem 3rem; }
  .data-strip { grid-template-columns:repeat(2,1fr); margin-bottom:2.8rem; }
  .data-cell:nth-child(2) { border-right:none; }
  .data-cell:nth-child(1), .data-cell:nth-child(2) { border-bottom:1px solid rgba(var(--c-luxury-gold-rgb),0.18); }
  .data-value { font-size:1.6rem; }
  /* INTER-BLOCK RHYTHM — desktop's 3.2-4rem gaps between brief items/rules/facts read as long,
     un-scannable scroll on a phone (a brief page can be 8-10 of these blocks deep). Same order,
     same elements, just closer together; nothing here changes what a block IS, only the air
     around it. */
  .intel-item { margin-bottom:2.2rem; }
  .item-rule { margin:2.2rem 0; }
  .citable-facts { margin-bottom:2.6rem; }
  .brief-faq { margin-top:2.6rem; padding-top:2rem; }
  .brief-related { margin-top:2.4rem; padding-top:2rem; }
}

/* ===== Static asset wiring (was injected via JS in the original) ===== */
.hero-bg { background-image:url('/static/images/banner.jpg'); }


/* ===== LEGAL PAGES ===== */
.legal-bar{padding:1.6rem 5rem;border-bottom:1px solid var(--hairline);display:flex;align-items:center;justify-content:space-between;}
.legal-bar a.home{font-family:'Cinzel',serif;font-size:0.72rem;letter-spacing:0.22em;color:var(--gold);text-transform:uppercase;text-decoration:none;}
.legal-bar a.back{font-family:'Jost',sans-serif;font-size:0.72rem;letter-spacing:0.14em;color:var(--text-muted);text-decoration:none;text-transform:uppercase;}
.legal-bar a.back:hover{color:var(--gold);}
.legal-wrap{max-width:760px;margin:0 auto;padding:5rem 2rem 6rem;}
.legal-eyebrow{font-family:'Cinzel',serif;font-size:0.6rem;letter-spacing:0.4em;color:var(--gold);text-transform:uppercase;margin-bottom:1.2rem;}
h1{font-family:'Cormorant Garamond',serif;font-weight:300;font-size:clamp(2.2rem,5vw,var(--t-display-l));color:var(--white);line-height:1.1;margin-bottom:0.6rem;}
.updated{font-family:'Jost',sans-serif;font-size:0.78rem;color:var(--text-dim);letter-spacing:0.06em;margin-bottom:3rem;}
h2{font-family:'Cormorant Garamond',serif;font-weight:400;font-size:1.6rem;color:var(--gold-light);margin:2.8rem 0 0.9rem;}
p,li{font-family:'Jost',sans-serif;font-weight:300;font-size:1rem;color:var(--text-muted);}
/* SCOPED to .legal-wrap (2026-07-21) — this was written for /privacy and /terms body copy, but
   as a bare `p` element selector it beat the sitewide `*{margin:0}` reset (an element selector
   always outranks the universal selector on specificity, regardless of source order) and was
   silently taxing every <p> on the site that didn't declare its own margin-bottom: measured on
   .hero-source, and it also reached .section-lead/.item-body/.subscribe-lead elsewhere on the
   homepage. Scoping to where it was actually meant to apply removes that leak everywhere else. */
.legal-wrap p{margin-bottom:1rem;}
ul{margin:0 0 1rem 1.2rem;}
li{margin-bottom:0.5rem;}
strong{color:var(--off-white);font-weight:400;}
a.inline{color:var(--gold);text-decoration:none;}
a.inline:hover{text-decoration:underline;}
.fill{color:var(--gold-light);font-style:italic;}
.legal-foot{border-top:1px solid var(--hairline);padding:2rem 5rem;text-align:center;font-family:'Jost',sans-serif;font-size:0.72rem;color:var(--text-dim);letter-spacing:0.06em;}
@media(max-width:680px){.legal-bar,.legal-foot{padding-left:1.4rem;padding-right:1.4rem;}}

/* ===== BRIEF ARCHIVE + BRIEF PAGE ===== */
.brief-page { padding-top:9rem; }
.brief-back {
  display:inline-block; font-family:'Jost',sans-serif; font-size:0.72rem;
  letter-spacing:0.14em; text-transform:uppercase; color:var(--text-muted);
  text-decoration:none; margin-bottom:2rem; transition:color 0.3s;
}
.brief-back:hover { color:var(--gold); }

.archive-list { display:flex; flex-direction:column; gap:1.4rem; margin-top:3rem; }
.archive-card {
  display:block; text-decoration:none; padding:2rem 2.2rem;
  background:var(--navy-mid); border:1px solid var(--hairline);
  transition:border-color 0.4s, transform 0.3s, background 0.4s;
}
.archive-card:hover {
  border-color:rgba(var(--c-luxury-gold-rgb),0.5); transform:translateY(-3px);
  background:var(--navy-light);
}
.archive-edition {
  font-family:'Cinzel',serif; font-size:0.6rem; letter-spacing:0.22em;
  text-transform:uppercase; color:var(--gold); display:block; margin-bottom:0.8rem;
}
.archive-title {
  font-family:'Cormorant Garamond',serif; font-weight:400; font-size:1.5rem;
  color:var(--white); line-height:1.25; margin-bottom:0.7rem;
}
.archive-title em { font-style:italic; color:var(--gold-light); }
.archive-summary {
  font-family:'Jost',sans-serif; font-weight:300; font-size:0.95rem;
  color:var(--text-muted); line-height:1.7; margin-bottom:1rem;
}
.archive-arrow {
  font-family:'Cinzel',serif; font-size:0.62rem; letter-spacing:0.18em;
  text-transform:uppercase; color:var(--gold);
}
@media (max-width:680px) { .brief-page { padding-top:7rem; } .archive-card { padding:1.5rem 1.4rem; } }

/* MEMBERS COMING-SOON (members.html, 2026-08-06) — reuses .archive-card's box wholesale and
   changes exactly one thing: .archive-card is built for clickable <a> cards, so it lifts and
   brightens on hover. These three roadmap cards are <div>s with nowhere to go (the products
   aren't live — that's the point of the page), and a card that animates under the cursor but
   does nothing when clicked reads as a broken link. Cancelling the affordance is more honest
   than inventing a destination for it. Nothing else about the card is touched. */
.ma-card { cursor:default; }
.ma-card:hover {
  border-color:var(--hairline); transform:none; background:var(--navy-mid);
}

/* COUNTY GROUPING (region.html, 2026-08-03) — a heading-only label above a county's cities, NEVER
   a data value: ONS PIPR has no county tier, so nothing renders here but the name itself. Distinct
   type from .archive-title (Cormorant, city names) so it reads as a grouping, not another card. */
.county-group { margin-top:2.8rem; }
.county-group:first-child { margin-top:0; }
.county-heading {
  font-family:'Cinzel',serif; font-weight:500; font-size:0.85rem; letter-spacing:0.16em;
  text-transform:uppercase; color:var(--gold);
  margin-bottom:1.2rem; padding-bottom:0.7rem; border-bottom:1px solid var(--hairline);
}

/* ===== SOCIAL ICONS ===== */
/* THE SOCIAL ROW — side by side, not stacked.
   Two icon links stacked vertically wasted the column and read as a list of two things rather than
   a set of handles. They now sit on one row. The `li` still exists (the markup is a real list, and
   it stays one for a screen reader) — only its box goes inline.
   The Newsletter link is pushed to its own full-width row: it is a TEXT destination, not a social
   handle, and letting it flow into the icon row would make "𝕏 Newsletter" read as one item. */
.footer-follow ul { display:flex; flex-wrap:wrap; align-items:center; gap:1.4rem; }
.footer-follow li { margin-bottom:0; }
.footer-follow li:has(> a:not(.social-link)) { flex-basis:100%; margin-top:0.2rem; }
.social-link {
  display:inline-flex; align-items:center; gap:0.5rem;
  color:var(--gold); text-decoration:none; transition:color 0.3s;
}
.social-link:hover { color:var(--gold-light); }
.social-icon {
  width:0.95rem; height:0.95rem; flex-shrink:0;
  fill:currentColor; vertical-align:middle;
}

/* ===== GEO/AEO: citable facts, FAQ, related editions, archive search ===== */
.citable-facts { margin:0 0 4rem; padding:2rem 2rem 1.4rem; border:1px solid rgba(var(--c-luxury-gold-rgb),0.22);
  background:linear-gradient(180deg, rgba(var(--c-luxury-gold-rgb),0.05), transparent); border-radius:2px; }
.cf-title { font-family:'Cinzel',serif; font-size:0.72rem; font-weight:500; letter-spacing:0.24em;
  text-transform:uppercase; color:var(--gold); margin-bottom:0.5rem; }
.cf-sub { font-family:'Jost',sans-serif; font-weight:300; font-size:0.82rem; color:var(--text-dim);
  margin-bottom:1.4rem; }
.cf-list { display:grid; gap:0; }
.cf-row { display:grid; grid-template-columns:1fr auto; grid-template-areas:"label value" "src src";
  align-items:baseline; padding:0.9rem 0; border-top:1px solid rgba(var(--c-luxury-gold-rgb),0.14); }
.cf-row:first-child { border-top:none; }
.cf-label { grid-area:label; font-family:'Jost',sans-serif; font-weight:400; font-size:0.9rem;
  letter-spacing:0.02em; color:var(--off-white); }
.cf-value { grid-area:value; margin:0; font-family:'Cormorant Garamond',serif; font-weight:500;
  font-style:italic; font-size:1.5rem; color:var(--gold-light); line-height:1; text-align:right; }
.cf-src { grid-area:src; margin:0.35rem 0 0; font-family:'Jost',sans-serif; font-weight:300;
  font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-dim); }

/* All four padding sides declared (was padding-top only): the other three fell through to the
   bare `section{padding:7rem 5rem}` element rule at every width — measured 80px/112px it never
   asked for, narrowing the FAQ block inside its own content column instead of running full width
   like the rest of the brief. See brief-related below for a related, worse instance of the same
   root cause (a bare-element rule leaking through an incomplete override). */
.brief-faq { margin:4rem 0 0; padding:3rem 0 0; border-top:1px solid rgba(var(--c-luxury-gold-rgb),0.18); }
.faq-title { font-family:'Cormorant Garamond',serif; font-weight:400; font-size:clamp(1.4rem,3vw,var(--t-display-m));
  color:var(--white); margin-bottom:1.6rem; letter-spacing:0.01em; }
.faq-item { margin-bottom:1.6rem; }
.faq-q { font-family:'Jost',sans-serif; font-weight:500; font-size:1rem; color:var(--off-white);
  margin-bottom:0.4rem; letter-spacing:0.01em; }
.faq-a { font-family:'Jost',sans-serif; font-weight:300; font-size:0.98rem; color:var(--text-muted);
  line-height:1.75; }

/* This is a <nav> (semantically correct — it navigates to related editions), which means it also
   matched the SITE'S FIXED NAVBAR rule (bare `nav{...}`, top of this file): position:fixed,
   top/left/right:0, z-index:100, display:flex, and the navy scrim background all leaked through
   undeclared, on top of the same padding-fallthrough .brief-faq had. Measured before this fix:
   position:fixed, pinned to the viewport top, painting a translucent "More UK property
   intelligence" bar over the real navbar and the page headline on every brief page — a real,
   visible bug, not just a spacing one. Every leaked property is reset explicitly so nothing
   inherits from the unrelated site-nav rule again. */
.brief-related { position:static; display:block; background:none;
  margin:3.5rem 0 0; padding:3rem 0 0; border-top:1px solid rgba(var(--c-luxury-gold-rgb),0.18); }
.related-title { font-family:'Cinzel',serif; font-size:0.68rem; font-weight:500; letter-spacing:0.24em;
  text-transform:uppercase; color:var(--gold); margin-bottom:1.2rem; }
.related-list { list-style:none; display:grid; gap:0.8rem; }
.related-list a { display:flex; flex-direction:column; gap:0.25rem; text-decoration:none;
  padding:0.9rem 1.1rem; border:1px solid rgba(var(--c-luxury-gold-rgb),0.18); border-radius:2px;
  transition:border-color 0.25s, background 0.25s; }
.related-list a:hover { border-color:rgba(var(--c-luxury-gold-rgb),0.45); background:rgba(var(--c-luxury-gold-rgb),0.04); }
.rel-ed { font-family:'Jost',sans-serif; font-size:0.62rem; font-weight:400; letter-spacing:0.18em;
  text-transform:uppercase; color:var(--gold); }
.rel-title { font-family:'Cormorant Garamond',serif; font-weight:400; font-size:1.15rem;
  color:var(--off-white); line-height:1.25; }
.rel-title em { font-style:italic; color:var(--gold-light); }

/* Prev/next chronological nav — reuses .rel-ed/.rel-title's type (same visual language as
   "related", one fewer thing to maintain) with its own layout: two cards side by side, prev on
   the left, next pushed to the right with margin-left:auto so a single card (catalogue's ends)
   sits on its own natural side instead of stretching full-width or leaving a dangling gap. */
.brief-adjacent { display:flex; gap:1.4rem; flex-wrap:wrap;
  margin:3.5rem 0 0; padding:3rem 0 0; border-top:1px solid rgba(var(--c-luxury-gold-rgb),0.18); }
.adjacent-link { flex:1 1 0; max-width:48%; display:flex; flex-direction:column; gap:0.3rem;
  text-decoration:none; padding:0.9rem 1.1rem; border:1px solid rgba(var(--c-luxury-gold-rgb),0.18);
  border-radius:2px; transition:border-color 0.25s, background 0.25s; }
.adjacent-link:hover { border-color:rgba(var(--c-luxury-gold-rgb),0.45); background:rgba(var(--c-luxury-gold-rgb),0.04); }
.adjacent-next { margin-left:auto; text-align:right; align-items:flex-end; }
.adjacent-dir { font-family:'Jost',sans-serif; font-size:0.62rem; font-weight:500; letter-spacing:0.14em;
  text-transform:uppercase; color:var(--text-dim); }
@media (max-width:680px) {
  .adjacent-link { max-width:100%; flex-basis:100%; }
  .adjacent-next { margin-left:0; text-align:left; align-items:flex-start; }
}

.archive-search-wrap { max-width:520px; margin:0 auto 3rem; }
.archive-search { width:100%; padding:0.9rem 1.2rem; background:rgba(var(--c-white-rgb),0.03);
  border:1px solid rgba(var(--c-luxury-gold-rgb),0.25); border-radius:2px; color:var(--off-white);
  font-family:'Jost',sans-serif; font-weight:300; font-size:0.95rem; letter-spacing:0.02em; }
.archive-search::placeholder { color:var(--text-dim); }
.archive-search:focus { outline:none; border-color:var(--gold); }
.archive-noresults { text-align:center; margin-top:1rem; font-family:'Jost',sans-serif;
  font-weight:300; font-size:0.9rem; color:var(--text-dim); }

@media (max-width:600px) {
  .citable-facts { padding:1.5rem 1.3rem 1rem; }
  .cf-value { font-size:1.3rem; }
}

/* ===== PRS Database cornerstone: standfirst + the 3-tier source rail ===== */
/* .prs-standfirst sits between the brief-meta row and the first .intel-item — same role a brief's
   lead paragraph plays, just not part of the .intel-item loop since this page has no data_strip. */
.prs-standfirst { font-family:'Jost',sans-serif; font-weight:300; font-size:1.05rem; line-height:1.7;
  color:var(--text-muted); text-align:center; max-width:640px; margin:0 auto 3.5rem; }

/* .prs-honesty-note — the PRS Database checker's (sentinel-mvp-region-checker-v1.md) up-front
   admission that no per-region date exists, so the guardrail is visible BEFORE the answer, not
   just cited afterward in the source rail. A callout, not a paragraph: it needs to read as a
   boundary on the tool, not as one more sentence of body copy a reader skims past. */
.prs-honesty-note { max-width:640px; margin:0 auto 3rem; padding:1rem 1.4rem;
  border:1px solid rgba(var(--c-luxury-gold-rgb),0.22); border-radius:2px;
  background:linear-gradient(180deg, rgba(var(--c-luxury-gold-rgb),0.05), transparent);
  font-family:'Jost',sans-serif; font-weight:300; font-size:0.86rem; line-height:1.65;
  color:var(--text-muted); text-align:center; }

/* .source-rail reuses .citable-facts/.cf-* wholesale (same box, same "Key figures at a glance"
   visual language the brief already uses for sourced claims) and adds only the tier grouping:
   each .rail-tier is one of the three specificity levels (document / per-claim / currency-check),
   named with a small gold badge so a reader can see WHICH kind of provenance they're looking at
   without the wording repeating "Tier N" as a full heading three times. */
.source-rail { margin-top:4rem; }
.rail-tier { margin-top:1.6rem; }
.rail-tier:first-of-type { margin-top:0; }
.rail-tier-badge { display:inline-block; font-family:'Cinzel',serif; font-size:0.62rem; font-weight:500;
  letter-spacing:0.2em; text-transform:uppercase; color:var(--gold); margin-bottom:0.6rem; }
.rail-tier-body { font-family:'Jost',sans-serif; font-weight:300; font-size:0.92rem; line-height:1.7;
  color:var(--text-muted); }
.rail-tier-body a { color:var(--gold-light); }
.rail-tier .cf-list { margin-top:0.2rem; }
/* Tier 2's rows reuse .cf-row/.cf-label/.cf-value/.cf-src as-is; .cf-value here carries the
   roadmap locator (e.g. "&sect;14-15") rather than a numeric figure — same gold italic treatment,
   consistent typographic weight for "the specific citation marker" regardless of what it contains. */
@media (max-width:600px) {
  .prs-standfirst { font-size:0.95rem; margin-bottom:2.6rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   W3 — R3 ORDER.  Hero (the claim) · Ranked table (the twist) · Brief · Subscribe ·
   Choropleth · Figure board.  All colours come from the tokens; no raw hexes.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* -- HERO: SPLIT. The type gets its own ground; the photograph runs BESIDE it. --------------
   London 6's dark is horizontal (sky/river), not a left-hand column, so the conventional
   figure-over-photo hero needed a 0.56 wash - which erases the photograph. A split needs NO WASH
   AT ALL: worst measured contrast 17.54:1 on the true glyph boxes, and the photo keeps every stop
   of its tonal range. This is how the FT and Bloomberg run a photo hero.
   ------------------------------------------------------------------------------------------ */
.hero {
  /* 40/60. ORIGINALLY forced by the £270,080 figure's ~380px width, which with the panel's
     padding set a ~476px floor. Since 2026-08-07 that figure lives in .hero-proof (now its own
     section below the routing block, not a row of this grid — see that section's own comment) —
     not in this panel — so the constraint that set this ratio no longer applies. Kept at 40/60
     anyway: widening the panel (e.g. to 50/50) would give the H1 and CTAs more breathing room, but
     it visibly shrinks the photograph, which is a content/photo balance call and not a layout
     necessity. Left as a deliberate decision for whoever owns that call, not defaulted into by
     this change. */
  /* FIXED TEXT COLUMN, 2026-08-08. Was 0.80fr 1.20fr (both proportional to .hero's own width).
     Measured (Playwright, before this change): at every capped width the text column actually
     rendered at a CONSTANT 629.29px, not the naive 0.80/(0.80+1.20)*1280=512px the ratio alone
     would predict — the .hero-actions button row (nowrap CTAs, current copy) is wider than that
     512px share, so the fr track's implicit min-width:auto (= min-content) floor was already
     winning over the ratio and holding the column at the buttons' own min-content width. Rather
     than hardcode 629.29px (a number that would silently go stale the day the CTA copy changes
     again), grid-template-columns' `min-content` keyword asks for exactly that same floor
     directly — it reproduces the identical 629.29px at every width tested (1280-3440,
     Playwright-verified equal to the pre-change seam to the pixel) without depending on how wide
     the .hero container itself is, which a bare fr value cannot do. See the padding-left note
     below for why that's what keeps the seam still while the image column (1fr) is free to grow. */
  /* THREE columns, 2026-08-08: text | inset spacer | photo. Was `min-content 1fr` with the inset
     applied as .hero's own padding-left (see the note at the end of this rule for why that inset
     exists at all). That padding pushed the TEXT in by the same amount it pushed the seam out, so
     the headline started at 152.4px against the logo/nav's 80px — a 72.4px indent at 1440 that
     grew with the viewport (400px at 1920) and matched nothing else on the page.
     Moving the inset out of .hero's padding and into a real grid track separates the two: the text
     column now starts at the viewport edge (so .hero-content's own 5rem padding lands the text on
     the same 80px as #navbar's 5rem), while the spacer reproduces the identical inset to the pixel
     and keeps the seam exactly where it was. The spacer needs no element and no background — .hero
     is transparent over body's var(--navy), the same token .hero-content paints itself with, so the
     panel and the spacer read as one continuous ground.
     WHY THE PERCENTAGE STILL RESOLVES THE SAME: in grid-template-columns it resolves against the
     grid container's own content box, which (now that padding is 0) is .hero's full width — the
     exact basis the old padding-left percentage used. Same input, same value, seam unmoved. */
  display:grid; grid-template-columns:min-content max(0px, calc((100% - 1280px) / 2)) 1fr;
  /* grid-template-rows was `1fr auto` (row 2 = .hero-proof, full-bleed under both columns) until
     2026-08-07's second follow-up moved .hero-proof out to its own <section> entirely. One row
     now — both hero-content and hero-bg are grid-row:1. */
  grid-template-rows:1fr;
  /* min-height 760px -> 640px (first fold-clearing pass) -> 530px (this pass): with .hero-proof
     no longer inside this element, the CONTENT floor this min-height used to have to clear
     (hero-content's own stack AND a ~170px proof row) is just hero-content's stack now — measured
     (Playwright) at ~468.7px with .hero-content's padding/gap restored a step below (see that
     rule's own comment) — so this can drop well below the first pass's 640px without cutting
     anything. 530px, not the ~468.7px bare floor: at the floor itself the panel's own
     justify-content:center has no slack left to push the eyebrow down, and #navbar (133.6px,
     fixed) would end up overlapping it again (the exact bug the first pass's 104px padding-top
     attempt hit — see .hero-content's own comment). 530px keeps 25px of real clearance under the
     nav (measured) while still comfortably clearing BOTH a 1440x700 and a 1440x780 viewport once
     the routing block is added on top — see that block's own FOLD CHECK comment (index.html) and
     .hero-proof's own comment for the resulting y-positions this was tuned against. */
  height:auto; min-height:530px; align-items:stretch; justify-content:initial;
  /* .hero IS a <section>, so it inherits `section { padding:7rem 5rem }` (and 5rem 2.5rem on
     mobile). That inset the photograph away from the edge on BOTH breakpoints - it read as a card
     rather than a bleed. The panel supplies its own padding; the photo must run to the edge. */
  padding:0;
  /* CONTAINED (2026-08-08), then REVERSED same day. The centred max-width:1280px cap that lived
     here made the hero's right edge line up with the 1280 column every section below it uses —
     correct for stopping the image from outgrowing the page, but Dan's follow-up call was the
     opposite direction for the image specifically: keep the seam exactly where the 1280 cap put
     it, but let the photo itself run past that column all the way to the viewport's true right
     edge, full-bleed, with the nav (already `position:fixed` at z-index:100, already designed to
     float over "any future hero" per its own comment) sitting on top of it. A plain revert to no
     max-width would have moved the SEAM too (0.80fr is proportional to .hero's own width, so an
     uncapped .hero widens the text column right along with the image) — not what was asked, only
     the image's right edge was meant to move. Fixing the text column at 512px (see above) and
     reproducing the OLD centred cap's left inset here as padding-left is what keeps the seam
     pinned at the exact pixel the 1280px cap put it at, at every width, while grid-template-
     columns' 1fr image track absorbs 100% of whatever's left, all the way to .hero's own right
     edge — which, with no max-width and padding-right:0, is the viewport's right edge. */
     The inset itself is now the middle grid track above, not this padding — see that note. What is
     preserved here is the OUTCOME this padding was written for: the seam sits where a centred
     1280px cap would put it, and the image runs from there to the viewport's true right edge. */
  max-width:none; margin:0;
  padding-left:0;
}
.hero-content {
  grid-column:1; grid-row:1;
  text-align:left; display:flex; flex-direction:column; justify-content:center;
  /* Top was 8rem/128px flat; now 8rem + var(--s-2xl) (176px), 2026-08-09 — Dan found the stack sat
     too close under the nav. NOT a 1:1 shift: this padding sits inside a `justify-content:center`
     column, so the stack (still centred within the padded box) only drops by HALF of what's added
     here — measured, not assumed (a raw padding-top delta and a centred-flex offset delta are not
     the same number, and guessing would have shipped the wrong distance).
     The earlier reasoning below (128px clearing the 133.6px nav, .hero's own min-height/centring
     adding further real clearance) is additive with this, not superseded by it.
     Bottom was var(--s-2xl) (48px), now 0 — 2026-08-09, second change same day. .hero has NO fixed
     height (see its own min-height comment): height:auto with align-items:stretch means the row's
     resolved height IS this element's own natural height (padding + content-stack), and .hero-bg
     stretches to match it exactly. So this padding-bottom was, invisibly, ALSO the gap between the
     photo's bottom edge and the CTA row's own bottom edge — measured constant at 48px across every
     width 1280-2560 (this box's height doesn't vary with viewport, only the image's does). Dan
     wanted the two flush; zeroing this is the whole fix — nothing else touches the photo, the
     buttons, or .hero's own height rule, because nothing else was contributing to that gap.
     Row height still clears the 530px floor at every tested width (570-578.3px here), so min-height
     stays a non-binding safety net, not the active constraint, exactly as before this change. */
  padding:calc(8rem + var(--s-2xl)) 4.5rem 0 5rem; max-width:none; width:auto; margin:0;
  background:var(--navy);                    /* the type's OWN GROUND - so no wash is needed */
  position:relative; z-index:2;
  /* var(--s-md) (16px, was var(--s-sm)/12px during the first fold-clearing pass) — restored one
     step for the same reason as the bottom padding above: .hero-proof moving out gives this room
     back without giving back the fold clearance the trim pass was for. Still one step down from
     the original var(--s-lg)/24px. Existing 8pt-scale token throughout, not a new number. */
  gap:var(--s-md);
}
.hero-bg {
  grid-column:3; grid-row:1; position:relative; inset:auto;   /* col 3 — col 2 is the inset spacer */
  animation:none;                            /* kenBurns would crawl real geography around */
  /* The photo moved to ::before (see below), which un-masked a rule this one used to override:
     the legacy "static asset wiring" block near line 693 still sets .hero-bg's background-image to
     banner.jpg. It was dead code while this rule declared hero-skyline.webp; with that declaration
     gone it would quietly become live again — an undimmed stale image behind the pseudo-element,
     fetched on every page load and visible if the webp ever failed. Neutralised explicitly here
     rather than deleted there: that block is the only remaining reference to banner.jpg, and
     removing an asset wiring line is a wider change than this task owns. */
  background-image:none;
  /* THE DIM, added 2026-08-07, REVERTED 2026-08-08. filter:brightness(0.5) uniformly darkened
     the whole photograph, not just the seam — the reference (pre buy->rental swap) hero ran this
     same image at brightness(1)/no filter, and side-by-side at every width 1280-3440px the dimmed
     version reads as flat/murky while the seam gradient below (unchanged since the reference)
     stops actually dissolving into anything: past the gradient's 15% stop the "revealed" photo is
     itself half-black, so the text-into-image bleed the split composition was built around barely
     registers. This was flagged as a known risk in its own commit (the overlay renders inside the
     filter group too, ~3-8 RGB darker than the panel), but the uniform 50% cut to the whole image
     was the larger effect, not that side note. Restoring brightness(1) here is what brings the
     bleed back to the reference's appearance, not a hoist of .hero-overlay out of this element.

     RE-DIMMED 2026-08-08, but NOT the way that reverted attempt did it. The photo still reads too
     bright; the reason the previous pass had to be undone is named in its own note above — the
     filter sat on THIS element, and .hero-overlay is a CHILD of it, so the gradient was rendered
     inside the filter group and got darkened along with the photo. Dimming the navy end of a
     navy-to-photo fade is what flattened the dissolve: both sides moved together, so the contrast
     the bleed is made of collapsed.
     The image now lives on ::before instead, and the filter goes THERE. The gradient is a sibling
     of that pseudo-element rather than its descendant, so it keeps full-strength var(--navy) at the
     seam while the photograph behind it dims. The dissolve therefore gets STRONGER as the image
     darkens, not weaker — the opposite of the failure mode that forced the revert — which is why
     this can carry a real dim where the blanket version could not. */
}
/* The photograph. Split onto ::before purely so `filter` can reach the image WITHOUT reaching
   .hero-overlay — see the note above; that containment is the whole point of this rule existing.
   Paint order needs no z-index: ::before precedes .hero-overlay in the box tree, and both are
   position:absolute at z-index:auto, so the gradient already composites on top of the photo. */
.hero-bg::before {
  content:''; position:absolute; inset:0; z-index:0;
  background-image:url('/static/images/hero-skyline.webp');
  background-size:cover; background-position:center center;
  filter:brightness(var(--hero-photo-dim));
}
.hero-overlay { z-index:1; }        /* explicit, so a future ::after can't slip above the gradient */
/* DEEPER BLEED, 2026-08-08. Was a hard two-stop fade — opaque navy at 0%, fully transparent by
   15% of the image panel's own width — which read as a quick edge more than a dissolve. Extended
   to a three-stop curve: still opaque at the seam, still carrying real navy (55% alpha, so the
   skyline is already showing through) out to 24%, then easing out to fully clear by 46% — roughly
   3x the old reach and no longer a straight linear ramp, so the fade slows into the photo rather
   than cutting off. Same var(--navy) token throughout (via --c-primary-navy-rgb), no new colour.
   Text sits on .hero-content's own solid var(--navy) ground, not on this gradient, so extending
   the reach doesn't touch legibility. */
.hero-overlay {
  position:absolute; inset:0;
  background:linear-gradient(90deg, var(--navy) 0%, rgba(var(--c-primary-navy-rgb),0.55) 24%, rgba(var(--c-primary-navy-rgb),0) 46%);
}
.hero-figure {
  font-family:'Cormorant Garamond',Georgia,serif; font-weight:400;
  font-size:clamp(3rem,5.6vw,5.4rem); line-height:0.9; letter-spacing:-0.015em;
  color:var(--white); margin:0;               /* spacing now comes from .hero-content's gap */
  /* Cormorant ships old-style figures: without this, 270,080 renders with a dropped numeral run
     and 3.75% becomes 3.75% with an interpunct. */
  font-variant-numeric:lining-nums tabular-nums; font-feature-settings:'lnum' 1,'tnum' 1;
}
.hero-source {
  font-family:'Jost',sans-serif; font-weight:500; font-size:0.66rem; letter-spacing:0.16em;
  text-transform:uppercase; color:var(--c-graph-grey);
  /* margin-top removed — .hero-content's gap supplies it. (This element also used to pick up an
     unrelated, unintended margin-bottom:1rem from the legal-page `p{margin-bottom}` rule —
     see that rule's own note; it's now scoped to .legal-wrap and no longer reaches here.) */
}
.hero-deltas { display:flex; gap:2.6rem; padding-top:1.4rem;
  border-top:1px solid var(--hairline); }      /* margin-top removed — gap on .hero-content supplies it */
.hero-delta b {
  display:block; font-family:'Cormorant Garamond',Georgia,serif; font-weight:500; font-size:1.6rem;
  color:var(--c-light-grey);
  font-variant-numeric:lining-nums tabular-nums; font-feature-settings:'lnum' 1,'tnum' 1;
}
.hero-delta span { font-family:'Jost',sans-serif; font-size:0.58rem; letter-spacing:0.15em;
  text-transform:uppercase; color:var(--text-muted); }
.hero .hero-subtitle { max-width:32rem; }      /* margin-top removed — gap on .hero-content supplies it */
.hero .hero-actions { justify-content:flex-start; }
/* .section-eyebrow is reused sitewide (regions/subscribe/welcome all rely on its own
   margin-bottom:1rem — see the base rule) so it can't be edited directly; scoped here instead,
   for the same reason every other child in this list lost its margin: .hero-content's gap
   already supplies it, and the base rule's margin would just add on top. */
.hero-content .section-eyebrow { margin-bottom:0; }
.hero-scroll { grid-column:1; grid-row:1; align-self:end; z-index:3; }
/* .hero-scroll's MARKUP was removed 2026-08-07 (it collided with .hero-proof below — the
   indicator is position:absolute; bottom:2.8rem against the WHOLE .hero, which now extends past
   the panel). Rule kept, matching this file's own convention of leaving a component's CSS in
   place rather than churning it the moment its one usage goes away — costs nothing, and
   .hero-scroll/.scroll-line are still real, restorable component names if a future hero wants
   the affordance back. */

/* ── HERO REBUILD, 2026-08-07 — the sentence H1, the offers strip, the proof strip. ────────────
   Nothing above this line in the split-composition block changed shape; these rules only ADD the
   new pieces the rebuilt .hero-content/.hero markup (index.html) needs. */

/* THE SENTENCE HEADLINE. The base .hero-title clamp tops out at --t-display-xl (5.06rem) — sized
   for "£270,080" and for the two-line slogan fallback with its manual <br>. The new H1 is a
   55-character sentence in a ~424px panel: at 5.06rem it sets six-plus lines. --t-display-m
   (2.71rem) is the EXISTING token that lands it on two-to-three lines, and is already the ceiling
   .item-headline uses for the identical job — a sentence headline in a fixed-width column (see
   line ~617). No new size introduced.
   Scoped, not edited: .hero-title's base rule still serves the no-facts fallback path elsewhere on
   the page (none currently, but the class stays generic on purpose) — the scoping idiom used
   throughout this block (.hero .hero-subtitle, .hero-content .section-eyebrow) is followed here.
   margin:0 is load-bearing: the OLD h1 also carried .hero-figure, which zeroed the base rule's
   margin-bottom:1.3rem; the new h1 doesn't carry that class, and .hero-content's flex `gap` would
   stack ON TOP of an unzeroed margin exactly as this file's own note on .hero-content warns. */
.hero-content .hero-title {
  font-size:clamp(2rem, 3.2vw, var(--t-display-m));
  line-height:1.15;                          /* base is 1.08, tuned for a display figure, not a
                                                 sentence; line-heights are hand-set throughout this
                                                 file (1.08/1.1/1.2/1.25 all appear elsewhere), so
                                                 this is consistent with existing practice, not a
                                                 new convention. */
  /* margin:0 is load-bearing: the OLD h1 also carried .hero-figure, which zeroed the base rule's
     margin-bottom:1.3rem; the new h1 doesn't carry that class, and .hero-content's flex `gap` would
     stack ON TOP of an unzeroed margin exactly as this file's own note on .hero-content warns.
     (2026-08-09: the 168px "step" that briefly lived here and on .section-eyebrow/.hero-standfirst/
     .hero-actions — all four children sharing one left edge under the logo's right edge — has been
     reverted at Dan's request, back to this baseline, to work forward from. See git history for the
     step's own rationale/measurements if it comes back.) */
  margin:0;
}
/* .hero-break — the H1's forced 3-line layout (index.html), DESKTOP-ONLY by default: display:none
   here, flipped to display:inline in the @media (min-width:901px) block below (alongside the other
   split-layout-only rules already there). A hidden <br> inserts NO line break at all, so <900px this
   is a no-op and the H1 falls through to plain natural wrapping — the same wrapping it already used
   before these were added (verified 3 lines at 390px). Forcing the desktop break points onto a
   390px column would either overflow the first (longest) segment or wrap it awkwardly mid-phrase,
   which is exactly the failure this file's own mobile-breakpoint convention exists to prevent (see
   .hero .hero-actions' own near-miss note in the >900px block for the general shape of that bug). */
.hero-break { display:none; }
/* The standfirst now sits UNDER the H1 (previously it sat ABOVE the whole eyebrow/figure block,
   with its own 0.2s fadeUp delay). Re-delayed so it animates in AFTER the H1 it now supports,
   rather than before the claim it's meant to follow. */
.hero-content .hero-standfirst { animation-delay:0.9s; }

/* HERO OFFERS. Not a new component: each card is .archive-card VERBATIM (navy-mid box,
   var(--hairline) border, gold border + 3px lift on hover — see line ~692) with .archive-title/
   .archive-summary carrying the type. Same vocabulary rental.html already uses for the identical
   job: four fixed, distinct features, each linking onward (see that template's own comment on
   why it's four hand-written cards, not a loop). What's NEW here is the GRID and the SCALE, not
   the card: .archive-list is a single vertical column sized for a ~780px content well; four cards
   at their native padding/type stack to ~715px tall, inside a hero panel that is ~424px wide. 2x2
   at one step down the spacing scale keeps the block to ~236px. No new colour, family, or box. */
.hero-offers {
  display:grid; grid-template-columns:repeat(2,1fr); gap:var(--s-xs);
}
.hero-offer { padding:var(--s-sm) var(--s-md); }
.hero-offer .archive-title {
  display:block;                    /* these are <span>s (links, not sections) — see index.html's
                                        own note on why no <h2>: four extra headings in a hero
                                        would compete with the page's real section titles below. */
  font-size:1.15rem; line-height:1.3; margin-bottom:0.2rem;
}
.hero-offer .archive-summary {
  display:block; font-size:0.82rem; line-height:1.5;
  margin-bottom:0;                  /* the card has no .archive-arrow to clear space for */
}

/* HERO PROOF. Was its own full-bleed row inside .hero's grid, spanning the panel AND the
   photograph, because it couldn't fit in the panel: .data-strip's four columns across ~424px give
   each figure a ~74px text box, and "£271,295" alone sets ~113px at .data-value's 1.9rem (line
   ~604). 2026-08-07's second fold-clearing pass moved it OUT of .hero entirely, to its own
   <section> placed after the routing block (index.html has the full rationale) — so it's now a
   NORMAL standalone section, same outer-section + max-width:1280px-.hero-proof-inner shape every
   other section here uses (.wyg-section/.wyg-inner directly above it), not a hero grid row. Still
   full-bleed background (var(--navy), same tone as its neighbours — this page never uses a colour
   block to separate sections). .data-strip/.data-cell/.data-label/.data-value are reused VERBATIM
   — the identical strip this very page already runs further down (index.html ~line 250, the
   brief's own stats). The only element that's still this section's own is the citation line,
   .hero-source: the exact Jost 500 / 0.66rem / 0.16em / var(--c-graph-grey) treatment that used to
   sit directly under the old hero figure, unchanged since. */
.hero-proof { background:var(--navy); padding:6rem 0; }   /* 6rem 0 — this page's own standard
                                                               section padding (.board-section,
                                                               .regions-section, etc. all use the
                                                               same literal value); no longer
                                                               fold-constrained now that it's below
                                                               the routing block, so no reason to
                                                               hold it any tighter than that. */
.hero-proof-inner { max-width:1280px; margin:0 auto; padding:0 5rem; }   /* matches .wyg-inner/
                                                                             .board-inner's own
                                                                             values exactly, so this
                                                                             section's edges line up
                                                                             with its neighbours'. */
.hero-proof .data-strip { margin-bottom:0; }  /* the base rule's 4rem margin is tuned for mid-page
                                                  use, between two unrelated blocks; here
                                                  .hero-proof-inner IS the block, so there's nothing
                                                  to separate from. */
/* 2026-08-07 — the base .data-cell (above) carries no background of its own, so on this section
   it sits directly on .hero-proof's own var(--navy), the same tone as the page around it: no
   contrast at all between "the box" and the page, which read as too dark to register as a
   distinct card. var(--navy-mid) is the next step up the SAME token ladder .intel-card already
   uses for an "elevated panel" surface (styles.css ~323) — one step rather than that component's
   own two-step jump (--navy-light), since a whole hero-proof full of panels needs a lighter touch
   than a single card elsewhere on the page. Scoped to .hero-proof only: the brief's own data-strip
   further down this file (.intel-brief, unrelated context, not mentioned here) is unaffected. */
.hero-proof .data-cell { background:var(--navy-mid); }
.data-cell-source { margin-top:var(--s-xs); line-height:1.6; }

/* ── WHAT YOU GET, 2026-08-07 — directly under the hero, answers "what am I looking at". Same
   section shape as .regions-section right below: background var(--navy) (matching the hero above
   AND the section after — this page separates sections with whitespace/typography, never a
   colour block, so staying on navy is consistency, not an oversight), vertical-only padding on
   the section, horizontal on the -inner wrapper — the exact .regions-section/.regions-inner
   split. .section-eyebrow/.section-title(+em)/.section-lead reused VERBATIM, the identical
   eyebrow + gold-italic-em h2 + lede components .regions-section itself uses two sections down.
   No new colour, no new font — every value below is an existing token. ────────────────────── */
/* 2026-08-07 — was padding:6rem 0. This section lost its own eyebrow/H2/lede (moved into the
   hero area, routing only) so the same 6rem+6rem rhythm every full header'd section uses would
   now be mostly empty air above and below four short lines. var(--s-lg)/var(--s-md) (24px/16px,
   both existing scale steps, not new numbers) keep it a section-shaped band directly under the
   hero without the extra height a section that still has a header needs — trimmed down from an
   initial var(--s-3xl) symmetric pass once measuring at 1440x900 showed the hero's own
   pre-existing min-height:760px (unchanged, out of scope here) already used most of the fold
   before this block even starts; slightly less on the bottom than the top since nothing below
   needs matching breathing room the way the gap under the hero does.
   TOP restored to var(--s-3xl) (64px), 2026-08-09 — the SAME value this rule started at, above,
   before being trimmed for the fold-clearance reason this comment already documents. That reason
   was about the HERO's own height, not this section's, and the hero has since shrunk twice more
   (760px min-height down to ~570-578px rendered) — the fold pressure that justified 24px doesn't
   hold at the same strength any more. Immediate cause: zeroing .hero-content's own padding-bottom
   (separately, to level the photo with the text — see that rule's own note) pulled this section up
   by the same 48px it removed, leaving only 24px between the CTA row and this section's own content
   — down from 72px. 64px was chosen over var(--s-2xl)/48px (the other value in range) because it's
   not a new number for this specific junction, only a reversion of the ONE change this rule has
   ever had. Bottom (var(--s-md)) is untouched — nothing changed below this section, only the gap
   above it. */
.wyg-section { background:var(--navy); padding:var(--s-3xl) 0 var(--s-md); }
.wyg-inner { max-width:1280px; margin:0 auto; padding:0 5rem; }

/* THE GRID. Four columns, divided by a SINGLE vertical hairline between adjacent items — no box,
   no fill, no top/bottom frame (unlike .data-strip just above, which frames the whole strip too;
   this section doesn't need that, and per Dan's explicit correction — "no solid gold fills
   anywhere" — a divider line is not a fill, but a bordered/backed panel would read as one, so
   this stays a plain grid with only a border-right divider).
   margin-top:0 (was var(--s-2xl)) — that gap used to separate the grid from the section-lead
   paragraph above it; the grid is now .wyg-inner's first child, so the section's own padding
   supplies the top space instead. */
.wyg-grid {
  display:grid; grid-template-columns:repeat(4,1fr);
  margin-top:0;
}
/* 2026-08-07 — border-right was 1px solid var(--hairline) (the sitewide 0.18-alpha gold token,
   tuned for a quiet divider between unrelated content blocks — .item-rule, .brief-faq's own
   border-top, etc.). Between four cards a visitor is meant to read as distinct choices, that
   quiet weight read as too faint to register at all. 2px (not a new width — .lead-figure's own
   border-left, styles.css ~625, already uses it) and 0.28 alpha (not a new value — .archive-card's
   own border, ~384, already uses it) make the divider actually visible without it reading as a
   frame or a fill; still a single flat line, still gold, still this page's own token family. NOT
   changed: var(--hairline) itself, which every other quiet divider on the site still uses at its
   original weight. */
.wyg-item {
  padding:0 var(--s-lg);
  border-right:2px solid rgba(var(--c-luxury-gold-rgb),0.28);
}
.wyg-item:first-child { padding-left:0; }
.wyg-item:last-child { padding-right:0; border-right:none; }

/* THE NUMBER. Cinzel, tracked, gold — the same family/case/tracking treatment .archive-edition
   and .data-label already use for "a small caps label above the real content"; only the size and
   the content (a two-digit ordinal, not a category label) differ. */
.wyg-number {
  display:block; font-family:'Cinzel',serif; font-size:0.72rem; font-weight:500;
  letter-spacing:0.22em; color:var(--gold); margin-bottom:1rem;
}
/* THE HEADING. Cormorant Garamond, same family/weight .archive-title already uses for "a card's
   own short title" — one step down from .archive-card's 1.5rem (matching .hero-offer's own
   scaled-down instance of the SAME class, styles.css ~1008) because this column is narrower
   (~280px at the 1280px max-width, four-up) and carries more body copy underneath. */
.wyg-heading {
  font-family:'Cormorant Garamond',serif; font-weight:400; font-size:1.3rem;
  line-height:1.25; color:var(--white); margin-bottom:var(--s-xs);
}
/* THE BODY. Jost, muted — .archive-summary/.item-body's own family/weight/colour. Sized between
   the two: .archive-summary's 0.95rem reads slightly large across four dense columns at once;
   .item-body's 1.02rem is tuned for one wide reading column, not four narrow ones.
   margin-bottom:var(--s-sm) (was 1.2rem) — trimmed alongside .wyg-section's own padding once this
   became a one-line-per-item routing strip rather than a paragraph; .wyg-link below still gets a
   visible gap, just not a full section's worth. */
.wyg-body {
  font-family:'Jost',sans-serif; font-weight:300; font-size:0.9rem;
  color:var(--text-muted); line-height:1.7; margin-bottom:var(--s-sm);
}
/* THE LINK. Gold text, a PERSISTENT hairline underline — explicitly not .archive-arrow (tracked
   Cinzel caps, no underline, ends in an arrow glyph) and explicitly not .btn-primary/.btn-
   secondary (Dan's correction: "links... not buttons"). a.inline already exists on this page
   (color:var(--gold); text-decoration:none, underlines on HOVER only) but this needs the
   underline visible by default, so it's a new rule — every value in it is still an existing
   token, though: var(--gold) for both the text and the line (var(--gold-light) on hover, same
   pairing .btn-secondary's own hover state uses), Jost for the family (matching every other
   small link/label on the page). "Hairline" here means genuine 1px THICKNESS
   (text-decoration-thickness), not the low-opacity --hairline TOKEN — that token is tuned for a
   quiet structural divider between content blocks (like .wyg-item's own border-right above), not
   for a functional link affordance someone needs to actually see is clickable; a legible gold
   link needs a legible gold line under it. */
.wyg-link {
  display:inline-block; font-family:'Jost',sans-serif; font-weight:400; font-size:0.85rem;
  letter-spacing:0.02em; color:var(--gold);
  text-decoration:underline; text-decoration-color:var(--gold);
  text-decoration-thickness:1px; text-underline-offset:4px;
  transition:color 0.3s, text-decoration-color 0.3s;
}
.wyg-link:hover { color:var(--gold-light); text-decoration-color:var(--gold-light); }

/* ── WHY THIS, NOT THAT, 2026-08-07 — the differentiator, directly under "What you get". First
   section on this page NOT sitting on plain var(--navy) — see the template's own note (index.html)
   for why deep-slate over secondary-navy. Two columns: .wtnt-inner mirrors .map-inner's own
   0.8fr/1.2fr split two sections down, the site's existing "text left, content right" shape,
   reused rather than invented — same max-width/gap/align-items too. ─────────────────────────── */
.wtnt-section { background:var(--navy-light); padding:6rem 0; }
.wtnt-inner {
  max-width:1280px; margin:0 auto; padding:0 5rem;
  display:grid; grid-template-columns:0.8fr 1.2fr; gap:5rem; align-items:center;
}
/* .section-lead carries NO margin-bottom of its own by design — every call site sets the
   trailing space it actually needs (see .yield-index-inner .section-lead's own identical-shaped
   override, styles.css ~1224). This one needs room before the CTA link below it. */
.wtnt-left .section-lead { margin-bottom:var(--s-xl); }

/* THE FIVE ROWS. Modelled on .rt-head/.rt-row — the regions ranked table, two sections down: a
   tracked-caps header row + hairline-divided data rows, the same shape as that existing
   component, new content. Column widths: var(--s-6xl) (128px, the spacing scale's own top step,
   not a new measurement) for the row's own attribute label, then two equal value columns.
   "Ours"/"Elsewhere" are genuinely rendered as the header row's two column labels, not left for
   the reader to infer from colour alone — using the SAME tracked/dim treatment .rt-head span
   already uses for its own column headers. Per-row attribute labels (Source/Dating/…) get the
   identical treatment, for the identical reason: they are captions, not content. */
.wtnt-head, .wtnt-row {
  display:grid; grid-template-columns:var(--s-6xl) 1fr 1fr; gap:1.6rem; align-items:baseline;
}
.wtnt-head { padding-bottom:0.7rem; }
.wtnt-head span {
  font-family:'Jost',sans-serif; font-size:0.6rem; letter-spacing:0.15em;
  text-transform:uppercase; color:var(--text-dim);
}
.wtnt-row { padding:1.1rem 0; border-bottom:1px solid var(--hairline); }
.wtnt-row:last-child { border-bottom:none; }
.wtnt-label {
  font-family:'Jost',sans-serif; font-size:0.6rem; letter-spacing:0.15em;
  text-transform:uppercase; color:var(--text-dim);
}
/* "Ours" — Cormorant Garamond, var(--off-white), the brief's own word AND the exact token name. */
.wtnt-ours {
  font-family:'Cormorant Garamond',serif; font-weight:400; font-size:1.15rem;
  line-height:1.4; color:var(--off-white);
}
/* "Elsewhere" — smaller, italic, var(--text-muted) (the standard "readable but secondary" body
   tone — .archive-summary/.item-body's own colour — not the fainter var(--text-dim), which this
   file reserves for tiny all-caps captions and would read as barely-there for a value someone
   still needs to READ, not just glance past). SAME family as "ours", not Jost: Cormorant Garamond
   italic-as-secondary-emphasis is already an established pattern on this exact page
   (.regions-kicker, two sections down) — reusing it here keeps both halves of each row reading
   as "one type of value, one de-emphasised" rather than mixing two unrelated font families
   within a single row. */
.wtnt-elsewhere {
  font-family:'Cormorant Garamond',serif; font-weight:400; font-style:italic; font-size:0.95rem;
  line-height:1.4; color:var(--text-muted);
}

/* ── THE TWIST: the ranked nation ──────────────────────────────────────────────────────── */
.regions-section { background:var(--navy); padding:6rem 0; }
.regions-inner { max-width:1280px; margin:0 auto; padding:0 5rem; }
.regions-header { display:flex; justify-content:space-between; align-items:flex-end; gap:3rem;
  margin-bottom:2.6rem; }
.regions-kicker { font-family:'Cormorant Garamond',Georgia,serif; font-style:italic;
  font-size:1.3rem; color:var(--gold-light); line-height:1.4; max-width:20rem; text-align:right; }
.regions-table { border-top:1px solid rgba(201,168,76,0.28); }
.rt-head, .rt-row {
  display:grid; grid-template-columns:26px 190px 1fr 82px 100px; gap:1.6rem; align-items:center;
}
.rt-head { padding-bottom:0.7rem; }
.rt-head span { font-family:'Jost',sans-serif; font-size:0.6rem; letter-spacing:0.15em;
  text-transform:uppercase; color:var(--text-dim); }
.rt-scale { text-align:center; }
.rt-right { text-align:right; }
.rt-row { padding:0.62rem 0; border-bottom:1px solid rgba(248,245,239,0.055); }
.rt-row:hover { background:rgba(26,35,50,0.42); }
.rt-rank { font-family:'Jost',sans-serif; font-size:0.62rem; letter-spacing:0.1em;
  color:var(--text-dim); font-variant-numeric:tabular-nums; }
.rt-name { font-family:'Jost',sans-serif; font-size:0.88rem; color:var(--c-light-grey); }
/* The zero line is REAL: London is genuinely negative and its bar runs left of it. */
.rt-track { position:relative; height:8px; background:rgba(248,245,239,0.045); display:block; }
.rt-track::before { content:''; position:absolute; left:var(--zero); top:-3px; bottom:-3px;
  width:1px; background:rgba(248,245,239,0.22); }
.rt-track i { position:absolute; top:0; bottom:0; }
.rt-yoy { font-family:'Cormorant Garamond',Georgia,serif; font-weight:500; font-size:1.05rem;
  color:var(--white); font-variant-numeric:lining-nums tabular-nums; font-feature-settings:'lnum' 1,'tnum' 1; }
.rt-price { font-family:'Jost',sans-serif; font-size:0.72rem; color:var(--text-muted);
  font-variant-numeric:lining-nums tabular-nums; }
.rt-foot { display:flex; justify-content:space-between; margin-top:1.1rem; padding-top:0.6rem;
  border-top:1px solid var(--hairline); }
.rt-foot span { font-family:'Jost',sans-serif; font-size:0.6rem; letter-spacing:0.15em;
  text-transform:uppercase; color:var(--text-dim); }

/* ── EVIDENCE: the choropleth — REMOVED 2026-08-09 ─────────────────────────────────────────
   The map itself went on 2026-08-07 (it re-rendered the same twelve ITL1 figures the ranked
   table above already shows). Its CSS was deliberately left in place then, per this codebase's
   convention of not churning a component's styles the moment its one usage goes. Two days on
   nothing has come back to use it: .map-section/-inner/-figure/-legend/-ramp/-source appear on
   zero elements in all 636 built pages and in zero templates, so they were shipping in every
   stylesheet download for a component that no longer exists.
   Removed WITH them: choropleth_svg() and hpi_ramp_css() in generate.py, and index.html's
   --hpi-ramp <style> emitter — .map-ramp was that variable's only consumer, so the ramp CSS had
   nothing left to colour. hpi_ramp() itself STAYS: it still fills the ranked table's bars
   (generate.py, r["fill"]), which is a live encoding, not decoration.
   The rule that outlived the code: the legend IS the encoding — a map published without its ramp
   printed is decoration, not data. That applies to whatever draws the next one. */

/* ── EVIDENCE, ROUTED: the figure board slimmed to one line + a link (2026-08-07) ──────────── */
.board-section { background:var(--navy); padding:6rem 0; }
.board-inner { max-width:1280px; margin:0 auto; padding:0 5rem; }
/* .board-route — the one new rule this slim-down needs. .section-lead is left-aligned and
   max-width:540px by default (tuned for sitting beside other left-aligned copy, e.g.
   .wtnt-left); a single sentence closing out the section reads better centred, the same
   treatment .yield-index-inner/.prs-database-inner's own closing CTAs already use for their own
   single-paragraph case (see their own ".section-lead { margin-bottom; max-width:none }"
   overrides just below). Position only — no new colour, no new font. */
.board-route { max-width:640px; margin:0 auto; text-align:center; }

/* ── ENTRY POINT: the free rental yield index. A closing CTA, not a data block, so it's a
   single centred column rather than the two-up grid the evidence sections use above. ──────── */
.yield-index-section { background:var(--navy); padding:6rem 0; }
.yield-index-inner {
  max-width:640px; margin:0 auto; padding:0 5rem;
  text-align:center; display:flex; flex-direction:column; align-items:center;
}
.yield-index-inner .section-lead { margin-bottom:2rem; max-width:none; }

/* ── ENTRY POINT: the PRS Database cornerstone. Same single-column CTA pattern as
   .yield-index-section directly above (another free, sourced, plain-English resource getting
   equal homepage weight) — separate class, not a rename, so each keeps its own copy/heading. ── */
.prs-database-section { background:var(--navy); padding:6rem 0; }
.prs-database-inner {
  max-width:640px; margin:0 auto; padding:0 5rem;
  text-align:center; display:flex; flex-direction:column; align-items:center;
}
.prs-database-inner .section-lead { margin-bottom:2rem; max-width:none; }

/* ── ENTRY POINT: the PRS Database checker. Same single-column CTA pattern as the two entry
   points above — separate class, not a rename, so each keeps its own copy/heading. ── */
.prs-checker-section { background:var(--navy); padding:6rem 0; }
.prs-checker-inner {
  max-width:640px; margin:0 auto; padding:0 5rem;
  text-align:center; display:flex; flex-direction:column; align-items:center;
}
.prs-checker-inner .section-lead { margin-bottom:2rem; max-width:none; }

/* ── ENTRY POINT: the Rent Guides hub. Same single-column CTA pattern as the three entry
   points above — separate class, not a rename, so each keeps its own copy/heading. ── */
.rent-guides-section { background:var(--navy); padding:6rem 0; }
.rent-guides-inner {
  max-width:640px; margin:0 auto; padding:0 5rem;
  text-align:center; display:flex; flex-direction:column; align-items:center;
}
.rent-guides-inner .section-lead { margin-bottom:2rem; max-width:none; }

@media (max-width:900px) {
  /* Stack: the type first (it is the message), the photograph beneath it as a band. Was a 3rd row
     here for .hero-proof (auto-height, since it needed its own row rather than sharing the
     photo's) until 2026-08-07's second follow-up moved .hero-proof out of .hero entirely, to its
     own <section> after the routing block — see that section's own comment (styles.css, just
     below .hero-offer's rules) for why. Two rows now, matching the desktop grid's own row count. */
  .hero { grid-template-columns:1fr; grid-template-rows:auto 300px; min-height:0; padding:0; }
  /* Nav bottom measures ~84px on mobile (<=1000px) - clear it. 6rem/96px keeps a real 12px
     margin below the fixed bar (was 7rem/112px - more than needed once the bar itself isn't
     growing, just excess top air); 2.5rem trims the same amount off the bottom, closing the gap
     to the photograph band without touching the split itself. */
  .hero-content { grid-column:1; grid-row:1; padding:6rem 1.4rem 2.5rem; }
  .hero-bg { grid-column:1; grid-row:2; }
  .hero-overlay { background:linear-gradient(180deg, var(--navy) 0%, rgba(var(--c-primary-navy-rgb),0) 22%); }
  .hero-scroll { display:none; }
  /* .hero-deltas mobile rule REMOVED 2026-08-07 — the element no longer exists in the markup
     (see the desktop block's own note on why; .hero-deltas' base rule is left in place there for
     the same "don't churn a component's CSS the moment its usage goes" reason, but there is no
     live element for THIS rule to ever have applied to once removed, so it's dropped here rather
     than kept as a mobile override with nothing to override). Replaced by the two rules below. */
  .hero-offers { grid-template-columns:1fr; }   /* .archive-card's own mobile behaviour (none
                                                    needed — it's already a simple block) carries
                                                    over; only the 2-column grid needs to collapse. */
  /* .hero-proof's own mobile rule REMOVED 2026-08-07 (second follow-up) along with the grid-row it
     used to occupy above — it's a normal standalone section now (see its base rule, styles.css)
     and picks up the SAME generic section-pad-y + "-inner" mobile padding every other section here
     uses (the -inner list a few rules down now includes .hero-proof-inner), rather than a
     bespoke override with nothing left to be bespoke about. */
  /* The inline style="grid-template-columns:repeat(N,1fr)" on .data-strip (set per-edition, in
     the template, from the live fact count) beats any stylesheet selector on specificity grounds
     alone — !important is the only way a media query can override an inline style, and it is
     scoped as tightly as possible (.hero-proof .data-strip, not .data-strip) so it can never leak
     onto the OTHER .data-strip this page already has further down (index.html ~line 250), which
     must keep its own responsive behaviour untouched. This file already tolerates !important where
     justified this way (see .subscribe-section). The alternative — dropping the inline style and
     accepting uneven/empty columns when an edition is missing a fact — was rejected as the worse
     failure mode. */
  .hero-proof .data-strip { grid-template-columns:repeat(2,1fr) !important; }
  /* Today's edition carries exactly 4 proof facts, so this reads as a clean 2x2: cells 1-2 get
     the row-1/row-2 divider, cell 4 (the last of 4) already loses its border-right from the base
     .data-cell:last-child rule. If a future edition carries fewer than 4 (a fact honestly dropped
     rather than faked — see proof_facts' own note in index.html), this degrades to an uneven last
     row rather than a broken one: still 2 columns, still bordered correctly for cells that exist,
     never an empty cell or a fabricated figure filling the gap. */
  .hero-proof .data-cell:nth-child(1), .hero-proof .data-cell:nth-child(2) {
    border-bottom:1px solid rgba(var(--c-luxury-gold-rgb),0.18);
  }

  /* WHAT YOU GET, mobile — 4-across to 1 column. The divider direction has to flip with it: a
     border-RIGHT down a full-width single column would read as a stray vertical line the length
     of the whole stack, so it becomes a border-BOTTOM between stacked items instead — same 2px/
     0.28-alpha weight as the desktop border-right above (2026-08-07), just rotated 90deg with
     the grid. */
  .wyg-grid { grid-template-columns:1fr; margin-top:var(--s-xl); }
  .wyg-item {
    padding:var(--s-lg) 0; border-right:none;
    border-bottom:2px solid rgba(var(--c-luxury-gold-rgb),0.28);
  }
  .wyg-item:first-child { padding-top:0; }
  .wyg-item:last-child { padding-bottom:0; border-bottom:none; }

  /* THE MARKER, replacing three near-identical per-section overrides (.regions-section,
     .map-section, .board-section — a full audit, 2026-07-21, found they'd each independently
     dodged the generic `section` mobile reduction the same way: a class-level unconditional
     `padding:6rem 0`, above, always outranks the bare `section` element selector on specificity,
     with no warning). Each now carries `section-pad-y` in its template markup instead of relying
     on being named here by hand — a future section that forgets the class is visibly missing it
     in the template diff, rather than silently opting out and only showing up wrong in a
     screenshot. Horizontal stays untouched on purpose: each of these has its own `-inner`
     child supplying mobile side padding already (.regions-inner/.board-inner below; .map-inner
     was the third until the choropleth's CSS was removed on 2026-08-09);
     a marker that also zeroed horizontal on a FUTURE section without that pattern would silently
     collapse its side padding to 0, so this class deliberately means "vertical only," not
     "the general mobile padding fix". .subscribe-section and .intel-brief do NOT carry this
     marker — both already have their own working, differently-shaped mobile overrides (real
     horizontal padding of their own, no `-inner` wrapper to lean on, and .intel-brief uses a
     different breakpoint entirely) that this marker would break, not replace, if applied.
     --s-3xl (64px), not --s-4xl (80px): measured stacked with the other mobile section rhythm
     values (the generic `section, .subscribe-section` rule above is now 3.5rem/56px) 80px read
     looser than every neighbouring gap on the page — still one step off the 8pt scale, just the
     next one down, not a hand-picked number. Placed in THIS query, not the ~440 one, because every
     section-pad-y user's own unconditional rule sits earlier in the file (766/801/814) — equal
     specificity, so this still has to come after them in source order. The marker changes WHO
     opts in, not the ordering rule itself. */
  .section-pad-y { padding:var(--s-3xl) 0; }
  .regions-inner, .board-inner, .yield-index-inner, .prs-database-inner, .prs-checker-inner, .wyg-inner, .wtnt-inner, .hero-proof-inner { padding:0 1.4rem; }
  .regions-header { flex-direction:column; align-items:flex-start; gap:1rem; }
  .regions-kicker { text-align:left; font-size:1.1rem; }
  .rt-head, .rt-row { grid-template-columns:22px 1fr 66px; gap:0.6rem; }
  .rt-track, .rt-price, .rt-head .rt-scale, .rt-head span:nth-child(5) { display:none; }
  .rt-foot { flex-direction:column; gap:0.4rem; }

  /* WHY THIS, NOT THAT, mobile — stack the two columns (1fr + 2.5rem gap; this was the same pair
     .map-inner used just above for the identical "text left, content right" split collapsing,
     until that rule went with the choropleth on 2026-08-09 — the values are unchanged). The
     3-column row (label + ours + elsewhere) would cram to unreadable widths at 390px, so each
     row REFLOWS via grid-template-areas: the attribute label moves to its own line above the
     pair, "ours"/"elsewhere" stay side by side below it — the direct juxtaposition is the whole
     point of a comparison row, so that pairing is the one thing kept intact. The header row's
     first cell (blank, was the label column's placeholder) is hidden — nothing to show above a
     label that no longer has its own column. */
  .wtnt-inner { grid-template-columns:1fr; gap:2.5rem; }
  .wtnt-left .section-lead { margin-bottom:var(--s-lg); }
  .wtnt-head { grid-template-columns:1fr 1fr; }
  .wtnt-head span:first-child { display:none; }
  .wtnt-row {
    grid-template-columns:1fr 1fr;
    grid-template-areas:"label label" "ours elsewhere";
    row-gap:0.4rem; padding:0.9rem 0;
  }
  .wtnt-label { grid-area:label; }
  .wtnt-ours { grid-area:ours; }
  .wtnt-elsewhere { grid-area:elsewhere; }
}


/* ══════════════════════════════════════════════════════════════════════════════════════════
   SEAM CLOSURE. The site read as "two websites in one": a dark data publication stitched to a
   gold-and-light estate-agent brochure. Sec 1 says ONE accent - one gold figure, one tracked
   label, hairlines. Everything below resolves the old treatment toward the new one.
   ══════════════════════════════════════════════════════════════════════════════════════════ */

/* The dissolving hairline, replacing the gold diamond dividers. A rule that DIES - it does more
   brand work than the palette does, and it costs no accent budget. */
hr.hairline-rule {
  height:1px; border:0; margin:0;
  background:linear-gradient(90deg, rgba(var(--c-luxury-gold-rgb),0.55), rgba(var(--c-luxury-gold-rgb),0));
}



/* THE LIGHT BANDS GO DARK. Sec 1 rule 3: dark, deep, calm. subscribe-section was navy-MID
   (luma 23.6 against the page's 15.0) - a visible band mid-page, and the seam that survived the
   cuts. The radial gold glows are decoration; they spend accent budget on atmosphere. */
.subscribe-section { background:var(--navy) !important; }
.subscribe-section::before,
.intel-brief::before { display:none !important; }

/* Gold gradient bars on the card tops - decorative, and the cards they belonged to are gone. */
.intel-card::before { display:none !important; }

/* The last two decorative gold FILLS. */
/* A 606,000px2 gold wash behind the figure board - atmosphere paid for out of the accent budget. */
.citable-facts { background:none !important; }
/* Gold separator dots in the brief meta. A dot is not a figure and not a hairline. */
.brief-meta .dot { background:rgba(var(--c-light-grey-rgb),0.28) !important; }

/* NB: the gold in .rt-track i is NOT decoration - it is the HPI magnitude ramp, whose top end is
   luxuryGold by construction. Colour there ENCODES how much (Ruling 6). It stays. */

/* At 40/60 the type column is 424px and the two CTAs wrapped. Tighten them so they sit on one row.
   SCOPED to >900px, which is the ONLY place that split exists — below it .hero goes to a single
   column (see the max-width:900px block above). Unscoped, this was the mobile cut-off bug: it beat
   the base `.hero-actions{flex-wrap:wrap}` on specificity at every width, so at 390px the two
   nowrap CTAs (168px + 216px + 12.8px gap = 396.8px) could not break. A grid item will not shrink
   below min-width:auto, so the column was forced to 396.8 + 44.8 of padding = 441.3px in a 390px
   viewport, and `.hero{overflow:hidden}` — which is here for the Ken Burns scale, not for this —
   silently ate the 51px overhang instead of scrolling it. The content was GONE, not reachable.
   Fix the row, never the symptom: `overflow-x:hidden` on an ancestor is what hid this for weeks. */
@media (min-width:901px) {
  .hero .hero-actions { flex-wrap:nowrap; gap:0.8rem; }
  .hero .hero-actions .btn-primary,
  .hero .hero-actions .btn-secondary { padding:0.9rem 1.5rem; white-space:nowrap; font-size:0.68rem; }
  .hero-break { display:inline; }
}


/* ══════════════════════════════════════════════════════════════════════════════════════════
   RESTYLE (not delete): the stats bar and the subscribe button.

   THE PRINCIPLE. Gold as a FILL is decorative — a solid gold box spends §1's entire one-accent
   budget on a background, and shouts louder than the £270,080 it sits below. Gold as a HAIRLINE,
   a FIGURE or a LABEL is structural. Both elements below keep their function and lose the slab.

   OPTION A (shipped): deepSlate surface + gold hairline + gold figures.
   OPTION B: deepSlate surface + gold figures, NO hairline. Toggle with <body class="opt-b">.
   ══════════════════════════════════════════════════════════════════════════════════════════ */

/* ── THE STATS BAR ─────────────────────────────────────────────────────────────────────── */
.stats-bar {
  background:var(--c-deep-slate);
  padding:2.6rem 5rem;
  display:flex; justify-content:space-around; align-items:center; gap:2rem;
  border-top:1px solid rgba(var(--c-luxury-gold-rgb),0.45);      /* A: gold hairline */
  border-bottom:1px solid rgba(var(--c-luxury-gold-rgb),0.45);
}
body.opt-b .stats-bar { border-top:0; border-bottom:0; }          /* B: no hairline */
.stat-item { display:flex; flex-direction:column; align-items:center; gap:0.5rem; text-align:center; }
.stat-number {
  /* The figure, in Cormorant with lining + tabular numerals — the same treatment as every other
     number on the site. Gold as a FIGURE is structural. */
  font-family:'Cormorant Garamond',Georgia,serif; font-weight:500;
  font-size:2.6rem; line-height:1; color:var(--gold);
  font-variant-numeric:lining-nums tabular-nums; font-feature-settings:'lnum' 1,'tnum' 1;
}
.stat-label {
  font-family:'Jost',sans-serif; font-weight:500; font-size:0.6rem; letter-spacing:0.16em;
  text-transform:uppercase; color:var(--text-muted);
}

/* ── THE SUBSCRIBE BUTTON — the ONLY conversion mechanism on the site ──────────────────── */
/* It must still read unmistakably as the primary action. A subscribe button that doesn't look
   clickable is worse than an ugly one: deepSlate surface, gold hairline, GOLD text (not cream —
   the gold is what marks it as the action), and a hover that fills toward gold so the affordance
   is unmistakable on contact. */
.btn-primary,
.nav-cta,
.subscribe-form button {
  background:var(--c-deep-slate) !important;
  color:var(--gold) !important;
  border:1px solid rgba(var(--c-luxury-gold-rgb),0.60) !important;
  transition:background 0.25s ease, color 0.25s ease, border-color 0.25s ease !important;
}
/* OPTION B IS NOT AVAILABLE FOR THE BUTTON, deliberately. Measured: the button's surface is
   IDENTICAL to the email input beside it (1.00:1) — the gold hairline is the ONLY thing that makes
   it read as a button. Remove it and the primary (and only) conversion mechanism on the site stops
   looking clickable. B applies to the STATS BAR only. */

.btn-primary:hover,
.nav-cta:hover,
.subscribe-form button:hover {
  background:rgba(var(--c-luxury-gold-rgb),0.16) !important;
  border-color:var(--gold) !important;
  color:var(--gold-light) !important;
}
/* The secondary action stays quieter than the primary — the hierarchy must survive the restyle. */
.btn-secondary { border-color:rgba(var(--c-light-grey-rgb),0.28) !important; color:var(--text-muted) !important; }
.btn-secondary:hover { border-color:rgba(var(--c-light-grey-rgb),0.55) !important; color:var(--c-light-grey) !important; }

@media (max-width:900px) {
  .stats-bar { padding:2rem 1.4rem; flex-wrap:wrap; gap:1.6rem 1rem; }
  .stat-item { flex:1 1 40%; }
  .stat-number { font-size:2rem; }
}

/* ── BRIEF EDITORIAL NOTE (2026-08-11) ────────────────────────────────────────────────────────
   Renders only on an edition whose content changed after publication — currently the three that
   cited the withdrawn 2-year OIS figure. Deliberately styled as a NOTICE, not as content: a warm
   left rule and a muted plate, distinct from .item-body prose, so it reads as the publisher
   speaking about the edition rather than as part of the edition's own argument. Sits directly
   under the meta line and above the data strip — a correction notice below the thing it corrects
   is one most readers never reach. */
.brief-editorial-note {
  margin: 0 0 2.4rem; padding: 1rem 1.3rem;
  border-left: 2px solid var(--gold);
  background: rgba(var(--c-luxury-gold-rgb), 0.05);
  border-radius: 0 3px 3px 0;
}
.brief-editorial-note strong {
  display: block; font-family: 'Cinzel', serif; font-size: 0.6rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--gold); margin-bottom: 0.5rem; font-weight: 500;
}
.brief-editorial-note p {
  font-family: 'Jost', sans-serif; font-weight: 300; font-size: 0.88rem; line-height: 1.75;
  color: var(--text-muted); margin: 0;
}
@media (max-width: 680px) { .brief-editorial-note { margin-bottom: 1.8rem; } }
