/* ============================================================================
   Healthcare Classified — hcc.css
   The production design system. Ported from rew-poc/hcc-poc.css, which is the
   prototype; the two share section numbering so they can be diffed.

   ARCHITECTURE (REDESIGN-PLAN-2026-08.md §3, owner decision D6)
   This file ships ALONGSIDE tailwind.css, not instead of it. Pages migrate one
   at a time; each migration is separately verifiable and revertible. Tailwind
   is dropped only once the last page has moved (plan Part B, B7).

   That is safe because tailwind.config.js's `blue.{50…950}` scale already IS
   the navy scale below, hex for hex — so a migrated page and an unmigrated one
   resolve brand colour identically and the site never looks half-rebranded
   mid-transition.

   LOADING: head.php pulls this in for every page. A page is "migrated" when its
   markup uses these component classes instead of Tailwind utilities; until then
   it simply inherits the tokens, the canvas and the chrome.
   ============================================================================ */

/*    ---------------------------------------------------------------------------
   THE LAWS (obey these everywhere; each is enforceable by grep)

   COLOUR   navy        = interactive or structural
            slate       = informational
            photography = carries ALL the colour
            amber       = somebody paid. Featured signalling ONLY, never
                          decorative. Budget: the featured card's border+ring,
                          its badge, and the seller-CTA badge that sells it.
            emerald     = verified / success, sparingly
            red         = destructive + active favourite

   TYPE     9 steps, one job each (§1.2). Nothing else at full size.
            Responsive step-downs are declared at their breakpoints.

   SPACING  4px ladder. Off-ladder is allowed for exactly three declared
            reasons: the 44px WCAG 2.5.8 touch floor (do NOT round these to
            48), fixed art dimensions, and sub-4px optical values.

   RADIUS   --r-lg 14 / --r-md 10 / --r-sm 6. Curve tracks surface size;
            nested elements follow inner = outer − padding.

            999px is allowed on exactly three kinds of object, because in each
            of them ROUND IS THE AFFORDANCE rather than decoration:
              (a) round icon buttons — the favourite heart, lightbox nav/close
              (b) chips and pills — small, text-only, never a primary action
              (c) map price markers — the established convention on every
                  comparable portal (rew.ca, Realtor.ca, Zillow)
            Never on: a card, a panel, a text input, a select, a dropdown menu,
            a labelled button, a pagination link, or a toast. "Pills and
            over-large radius everywhere" is a named item on the anti-AI
            checklist in design/REW-REFERENCE.md, and gen-1 browse/map had
            999px on seven component families.

   ELEVATION  Borders, not shadows. slate-300 OUTLINES a thing; slate-200 is a
            line BETWEEN things. Only two shadows exist and both are for
            genuinely floating surfaces (§1.5). There is deliberately no
            --shadow-sm / --shadow-md, so "shadow-sm at rest, shadow-md on
            hover, translateY(-2px)" cannot be reintroduced by habit.
   ============================================================================ */


/* ============================================================================
   1. TOKENS
   ============================================================================ */
:root {

  /* --- 1.1 Palette --------------------------------------------------------
     Brand navy. In production these are Tailwind blue-* overrides — the
     `blue.{50…950}` scale in tailwind.config.js already IS this scale, hex for
     hex, which is what makes the page-by-page migration in REDESIGN-PLAN §3
     colour-safe: migrated and unmigrated pages resolve to identical values. */
  --navy-50:  #f1f4f9;
  --navy-100: #e4ebf4;
  --navy-200: #c1d5e9;
  --navy-300: #91b5d9;
  --navy-400: #5d92c7;
  --navy-500: #3b76b2;
  --navy-600: #265a8e;   /* 7.15:1 on white — the link colour on light surfaces */
  --navy-700: #092449;   /* primary  */
  --navy-800: #061a35;   /* hover    */
  --navy-900: #030f21;   /* deepest  */

  /* Slate neutrals (Tailwind defaults, as used site-wide) */
  --slate-50:  #f8fafc;
  --slate-100: #f1f5f9;
  --slate-200: #e2e8f0;
  --slate-300: #cbd5e1;
  --slate-400: #94a3b8;   /* 6.96:1 on slate-900 — footer link colour */
  --slate-500: #64748b;
  --slate-600: #475569;
  --slate-700: #334155;
  --slate-800: #1e293b;
  --slate-900: #0f172a;

  /* Featured (amber). See the COLOUR law — this is a paid-placement signal,
     not an accent. If you are reaching for amber and nobody paid, stop. */
  --amber-50:  #fffbeb;
  --amber-100: #fef3c7;
  --amber-200: #fde68a;
  --amber-300: #fcd34d;
  --amber-800: #92400e;

  /* Success / error */
  --emerald-50:  #ecfdf5;
  --emerald-600: #059669;
  --emerald-700: #047857;
  --red-500: #ef4444;
  --red-700: #b91c1c;

  /* The one warm off-white canvas (DESIGN-SYSTEM.md sanctions #fdfbf7).
     Tokenised so the "one canvas" claim is enforceable — a raw hex repeated in
     three places is a hex with no token behind it. */
  --canvas: #fdfbf7;


  /* --- 1.2 Type -----------------------------------------------------------
     9 steps, one job each. Weight and tracking carry hierarchy, not size
     alone. Responsive step-downs are declared inline at their breakpoints,
     which is why --t-figure's "proof numbers ONLY" holds at desktop while the
     H1 also renders 48px on tablet.

     --t-price exists as its own step because the card price used to ride
     --t-h2; that coupled a card-internal value to the section-head size and
     neither could move without the other. */
  --t-display: 72px;   /* hero H1 ONLY — exactly one use per page            */
  --t-figure:  68px;   /* the four proof numbers ONLY — THE signature        */
  --t-stmt:    40px;   /* editorial statement H2 (proof band, seller CTA)    */
  --t-h2:      28px;   /* section heads: rule head, newsletter, hub, page H1 */
  --t-price:   22px;   /* listing card price                                */
  --t-lede:    19px;   /* section ledes                                     */
  --t-body:    16px;   /* body copy, card titles                            */
  --t-meta:    14px;   /* metadata, nav, buttons, links                     */
  --t-micro:   12px;   /* uppercase micro-labels, fine print, badges        */

  /* Weights. 650/750 need the VARIABLE Inter axis — a static Google-Fonts
     instance list silently snaps 650→700 and 750→800 and the precision system
     never renders. Every page must load `Inter:wght@400..800`, not
     `Inter:wght@400;500;600;700;800`. This cost v4 a whole build round. */
  --w-body: 400;
  --w-med:  500;
  --w-semi: 600;
  --w-mid:  650;
  --w-bold: 700;
  --w-hvy:  750;
  --w-max:  800;

  --font: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;


  /* --- 1.3 Spacing — 4px ladder ------------------------------------------ */
  --s1:4px;  --s2:8px;   --s3:12px;  --s4:16px;  --s6:24px;  --s8:32px;
  --s10:40px; --s12:48px; --s16:64px; --s24:96px; --s28:112px;
  --s32:128px; --s40:160px;


  /* --- 1.3a Layout constants ---------------------------------------------
     The sticky header's bar height. It was a bare 72px repeated in five
     places (the bar, the anchor scroll-padding, .mv-shell's viewport
     subtraction, .hcd-tabs and .hcc-subnav), and two of those five had
     drifted off by a pixel because the header's BORDER-BOX is one pixel
     taller than its bar — see the 1px note on .hcc-subnav in section 12.

     Everything that offsets from the header now derives from this token, so
     the bar's height can move without hunting for magic numbers. Anything
     that must clear the header entirely adds the 1px border:
     calc(var(--header-h) + 1px). */
  --header-h: 80px;


  /* --- 1.4 Radius ---------------------------------------------------------
     The search shell is the worked example of inner = outer − padding: 14
     outer with 8px padding, so its GRANDCHILDREN (the toggle segments) sit at
     6. Its two direct children are declared optical exceptions — the toggle
     track at 9px and the submit button at 8px — because the formula's result
     read too tight against those control heights. Nobody perceives 9 vs 10;
     the exceptions are recorded here so they don't read as drift. */
  --r-lg: 14px;   /* large surfaces: cards, panels, tiles, search shell   */
  --r-md: 10px;   /* controls: buttons, inputs, selects, menus, skip link */
  --r-sm:  6px;   /* nested bits: toggle segments, thumbnails, badges     */


  /* --- 1.5 Elevation ------------------------------------------------------
     Two shadows, both for genuinely floating surfaces. Navy-tinted rather
     than black: pure black goes muddy on a warm canvas.
       --shadow-pop  detached UI that overlays content (dropdown menus, map
                     popups, the skip link)
       --shadow-lift the hero search shell only — it has to read as lifted off
                     a photograph, which a border cannot do
     There is intentionally no resting/hover shadow pair. */
  --shadow-pop:  0 4px 16px -4px rgba(3,15,33,.35);
  --shadow-lift: 0 12px 32px -8px rgba(3,15,33,.45);
}


/* ============================================================================
   2. BASE
   ============================================================================ */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* Clears the sticky header plus breathing room on in-page anchors. */
  scroll-padding-top: calc(var(--header-h) + var(--s6));
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--t-body);
  font-weight: var(--w-body);
  line-height: 1.5;
  color: var(--slate-700);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Sticky footer. body is already a 100vh flex column (above); main has to take
   the slack or the footer floats up on short pages. Element-scoped so every
   page gets it without remembering a class — the pages carried Tailwind's
   `flex-1` for this until B6, which would have failed silently at B7. */
body > main { flex: 1 0 auto; }

/* --- Element reset ---------------------------------------------------------
   This block replaces Tailwind Preflight, dropped at B7. It is not a stylistic
   choice — Preflight was doing real work that the markup depends on, and the
   two rules that matter most are the ones that fail SILENTLY and everywhere:

     menu, ol, ul { list-style: none; margin: 0; padding: 0 }

   Every nav, footer column, mobile menu and link hub on this site is a <ul>
   with no list class. Without this they all sprout bullets and ~40px of left
   indent. Surfaces that DO want markers opt back in (.hcc-list, .hcc-prose).

     button, input, optgroup, select, textarea { font-family: inherit }

   Form controls otherwise fall back to the UA's 13.3333px system font. */
blockquote, dd, dl, figure, h1, h2, h3, h4, h5, h6, hr, p, pre { margin: 0; }
menu, ol, ul { list-style: none; margin: 0; padding: 0; }
fieldset { margin: 0; padding: 0; border: 0; }
legend { padding: 0; }
table { text-indent: 0; border-color: inherit; border-collapse: collapse; }
button, input, optgroup, select, textarea { font-family: inherit; font-size: 100%; line-height: inherit; color: inherit; margin: 0; padding: 0; }
textarea { resize: vertical; }
::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; }

h1, h2, h3, h4 { color: var(--slate-900); }
a { color: inherit; text-decoration: none; }
/* Preflight splits these deliberately and so must we: display:block on all
   replaced elements, but max-width/height:auto ONLY on img and video. Applying
   height:auto to <svg> overrides the width/height attributes on every inline
   icon on the site. */
img, svg, video, canvas, audio, iframe, embed, object { display: block; vertical-align: middle; }
img, video { max-width: 100%; height: auto; }
/* Preflight's [hidden] rule, which this reset was missing: any author-level
   display beats the UA's [hidden]{display:none} regardless of specificity,
   so the mobile menu (display:flex) and every svg (display:block above)
   rendered even while carrying the `hidden` attribute the header JS toggles
   — the drawer sat permanently open on every page below 1024px. !important
   because component display rules are exactly what this must override. */
[hidden] { display: none !important; }
/* font-size:inherit as well as font-family. Without it, icon-only buttons that
   declare no size of their own (.search-submit, .hcc-fav) sit at the UA's
   13.3333px, and every SVG inside them inherits that — so `em`-relative values
   and any future text in those controls resolve against a size nobody chose.
   It is invisible today and would not stay invisible. */
button { font-family: inherit; font-size: inherit; cursor: pointer; }
::selection { background: var(--navy-700); color: #fff; }

/* ONE container, ONE left edge — the rail every content section aligns to.
   1200 max / 1120 content box at desktop. */
.hcc-container { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 var(--s6); }
@media (min-width: 1024px) { .hcc-container { padding: 0 var(--s10); } }

/* --- 2.1 Focus -------------------------------------------------------------
   Two-tone ring: navy on light surfaces, inverted to white on dark ones.

   NO border-radius here, deliberately. The property lands on the ELEMENT, not
   on the outline, and at (0,1,0) it outranks every single-class radius rule in
   this file — poc-shared.css shipped exactly that declaration and the round
   favourite button squared off to 2px the moment it took focus. Browsers
   already follow the element's own radius when drawing an outline, so the
   declaration bought nothing and cost the whole radius scale. */
:focus-visible {
  outline: 2px solid var(--navy-700);
  outline-offset: 3px;
}
.site-header :focus-visible,
.site-footer :focus-visible,
.hcc-on-dark :focus-visible { outline-color: #fff; }

/* Skip link — must land legibly on any background, so it carries the one
   detached-UI shadow rather than a border. */
.hcc-skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: #fff; color: var(--navy-700);
  padding: var(--s3) var(--s6); border-radius: var(--r-md);
  font-size: var(--t-meta); font-weight: var(--w-bold);
  box-shadow: var(--shadow-pop);
}
.hcc-skip:focus { left: var(--s6); top: var(--s3); }

/* --- 2.2 Motion ------------------------------------------------------------
   The entire motion budget: one photo push-in, one favourite pop. No GSAP —
   ~35–40 KB for one effect is the wrong trade on this stack. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hcc-card-media img, .hp-tile img { transition: none; }
  .hcc-card:hover .hcc-card-media img, .hp-tile:hover img { transform: none; }
}



/* ============================================================================
   3. CHROME — header, nav, footer, SEO hub, breadcrumb
   ============================================================================ */

.site-header {
  background: var(--navy-700);
  position: sticky; top: 0; z-index: 50;
  /* The transparent border is load-bearing: .is-stuck swaps only its COLOUR.
     Adding a border on stick instead would grow the sticky bar's border box
     by 1px and nudge the whole document down a pixel mid-scroll. That 1px is
     why everything offsetting from the header uses
     calc(var(--header-h) + 1px). */
  border-bottom: 1px solid transparent;
}
.site-header.is-stuck { border-bottom-color: rgba(255,255,255,.14); }

/* Bar and nav gaps are UNCONDITIONAL at --s10 / --s8.

   These WERE --s6/--s6. An earlier attempt at 40/32 overflowed: the bar's own
   content measured 1147px inside the 1120px content box, so "Post an Ad"
   rendered a constant 27px right of the container edge at every width ≥1200 —
   visibly right of the content directly beneath it, breaking the one-rail law.
   Nothing was clipped (the 40px gutter absorbed it) and no page scroll
   appeared, which is exactly why an overflow-only pass missed it.

   What changed since: Phase 1 shortened the nav to Practices / Jobs /
   Equipment, which took the nav from ~640px to 382px. Re-measured at the two
   widths where the bar is tightest — 1200 (the boost link switches on) and
   1024 (the full nav switches on) — the content now fits with 199px and 175px
   of slack respectively. The 40px logo→nav gap is the point: at --s6 the
   brand chip and the first nav item were the same 24px apart as two nav items
   are, so the wordmark read as the first item in the nav rather than as the
   brand. */
.site-header .bar { display: flex; align-items: center; gap: var(--s10); height: var(--header-h); }

.logo-chip {
  display: inline-flex; align-items: center;
  background: #fff; border-radius: var(--r-sm);
  padding: var(--s2) var(--s3);
  flex-shrink: 0;
}
.logo-chip img { height: 34px; width: auto; object-fit: contain; }

.main-nav { display: none; align-items: center; gap: var(--s8); height: 100%; }
@media (min-width: 1024px) { .main-nav { display: flex; } }
.main-nav a {
  color: rgba(255,255,255,.85);
  font-size: var(--t-meta); font-weight: var(--w-med);
  white-space: nowrap; height: 100%;
  display: flex; align-items: center;
  border-bottom: 2px solid transparent;
  transition: color .15s;
}
.main-nav a:hover { color: #fff; }
/* Active nav is WHITE, never amber. */
.main-nav a.active { color: #fff; border-bottom-color: #fff; }

.header-actions { display: flex; align-items: center; gap: var(--s6); margin-left: auto; flex-shrink: 0; }
.header-actions .signin {
  color: rgba(255,255,255,.85);
  font-size: var(--t-meta); font-weight: var(--w-semi);
  display: inline-flex; align-items: center; min-height: 44px;
}
.header-actions .signin:hover { color: #fff; }

.btn-header-cta {
  background: #fff; color: var(--navy-700);
  font-size: var(--t-meta); font-weight: var(--w-bold);
  padding: 0 var(--s6); min-height: 44px;
  display: inline-flex; align-items: center;
  border-radius: var(--r-md);
  white-space: nowrap;
  transition: background-color .15s;
}
.btn-header-cta:hover { background: var(--slate-50); }

/* The Featured entry point in the page chrome. It appears from 1200px, NOT
   1024px: at 1024 the full nav switches on too, and logo + nav + actions then
   needed 1147px inside a 944px bar — the page scrolled sideways on every
   iPad-landscape and small laptop. Both halves of this pair are required; a
   lone min-width rule left a 40px hole when the old shared sheet turned the
   link on at 1160. */
.boost-link { display: none; color: rgba(255,255,255,.85); font-size: var(--t-meta); font-weight: var(--w-med); }
.boost-link:hover { color: #fff; }
@media (min-width: 1200px) { .boost-link { display: inline; } }
@media (max-width: 1199px) { .boost-link { display: none; } }

/* Below ~420px the logo chip + "Sign in" + "Post an Ad" cannot all fit, and
   the CTA was pushing the page wider than the viewport. Tighten the bar and
   drop "Sign in" — the footer Company column carries a real Sign in link, so
   the affordance survives at every width.
   NOTE for the PHP port: production's mobile disclosure menu is real and used;
   it is NOT dropped in favour of this. See REDESIGN-PLAN §4 Phase 1. */
/* --- Small-width ladder ---------------------------------------------------
   Three steps, each set from a measurement rather than a guess. The bar holds
   logo(157) + [account] + [CTA] + burger(44) plus gaps, against a rail of
   (viewport - 48). Everything dropped here is still reachable: the mobile menu
   carries the account links AND a full-width "Post an Ad" button, which is the
   entire point of having one.

     <=559  gaps 24 -> 16, CTA padding tightened      (fits to ~480)
     <=479  account control drops                     (fits to ~420)
     <=419  header CTA drops; bar is logo + burger    (fits to 320 and below)

   The previous single 419px step named only .signin, so a LOGGED-IN visitor on
   a small phone kept the account control and the bar overflowed — the state
   nobody checks because the mockups are all logged out. */
@media (max-width: 559px) {
  .site-header .bar { gap: var(--s4); }
  .header-actions { gap: var(--s4); }
  .btn-header-cta { padding: 0 var(--s3); }
}
@media (max-width: 479px) {
  .header-actions .signin,
  .header-actions .hcc-acct { display: none; }
}
@media (max-width: 419px) {
  .btn-header-cta { display: none; }
}

/* --- 3.0a Account menu + mobile disclosure --------------------------------
   PRODUCTION-ONLY. These two have no counterpart in rew-poc/hcc-poc.css and
   deliberately so: the POC has no session state and ships no mobile nav (its
   .main-nav is simply display:none below 1024px). Production's mobile menu is
   real and used, so porting the POC chrome literally would have deleted a
   working feature. This block is the documented divergence between the
   prototype and this file — everything else in §1-§8 is a straight copy. */

.hcc-acct { position: relative; }
.hcc-acct-btn {
  display: inline-flex; align-items: center; gap: var(--s2);
  background: transparent; border: 0; color: rgba(255,255,255,.85);
  font-size: var(--t-meta); font-weight: var(--w-semi);
  min-height: 44px; padding: 0 var(--s2);
  border-radius: var(--r-md);
  transition: color .15s, background-color .15s;
}
.hcc-acct-btn:hover { color: #fff; background: rgba(255,255,255,.08); }
/* Below 1200 the greeting text is dropped and the control becomes the user
   icon alone. Measured: logo + nav + actions needs 1194px with the name shown,
   against a 1120px content box — 74px past the rail at every width >=1200 and
   34px of real page scroll at exactly 1200. The name is the only part of this
   control that is not an affordance, so it is the part that goes. */
@media (max-width: 1199px) {
  .hcc-acct-btn span { display: none; }
  .hcc-acct-btn .chev { display: none; }
}
.hcc-acct-btn .chev { transition: transform .15s; }
.hcc-acct-btn[aria-expanded="true"] .chev { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .hcc-acct-btn .chev { transition: none; } }

/* A floating panel: --r-md + the detached-UI shadow, on white rather than on
   the navy bar, because it overlays page content and not the header. */
.hcc-acct-menu {
  position: absolute; right: 0; top: calc(100% + var(--s2)); z-index: 60;
  min-width: 232px; background: #fff;
  border: 1px solid var(--slate-200); border-radius: var(--r-md);
  box-shadow: var(--shadow-pop);
  padding: var(--s1);
}
.hcc-acct-menu a {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); border-radius: var(--r-sm);
  font-size: var(--t-meta); font-weight: var(--w-med); color: var(--slate-700);
  white-space: nowrap;
  transition: background-color .15s, color .15s;
}
.hcc-acct-menu a:hover { background: var(--navy-50); color: var(--navy-700); }
.hcc-acct-menu a.is-danger:hover { background: color-mix(in srgb, var(--red-500) 8%, #fff); color: var(--red-700); }
.hcc-acct-sep { height: 1px; background: var(--slate-200); margin: var(--s1) var(--s3); }
/* The menu sits on white, so it needs the navy ring back — the header's
   white-on-dark inversion (§2.1) would be white-on-white inside it. */
.hcc-acct-menu :focus-visible { outline-color: var(--navy-700); }

/* Burger: the mirror of .main-nav's breakpoint, so exactly one of the two is
   ever present. */
.hcc-burger {
  display: inline-flex; align-items: center; justify-content: center;
  /* flex-shrink:0 is load-bearing — without it the bar squeezed the burger from
     44px to 24px at 320px rather than admitting it did not fit, which is both a
     WCAG 2.5.8 touch-target failure and a way to hide an overflow from a naive
     eyeball check. */
  width: 44px; height: 44px; flex-shrink: 0; margin-left: auto;
  background: transparent; border: 0; color: #fff;
  border-radius: var(--r-md);
  transition: background-color .15s;
}
.hcc-burger:hover { background: rgba(255,255,255,.10); }
@media (min-width: 1024px) { .hcc-burger { display: none; } }

.hcc-mobile-menu {
  background: var(--navy-800);
  border-top: 1px solid rgba(255,255,255,.12);
  display: flex; flex-direction: column;
  padding: var(--s2) 0 var(--s4);
}
@media (min-width: 1024px) { .hcc-mobile-menu { display: none; } }
.hcc-mobile-menu a {
  color: rgba(255,255,255,.88);
  font-size: var(--t-body); font-weight: var(--w-med);
  padding: var(--s3) var(--s6); min-height: 48px;
  display: flex; align-items: center;
}
.hcc-mobile-menu a:hover { color: #fff; background: rgba(255,255,255,.06); }
.hcc-mobile-cta { padding: var(--s3) var(--s6) 0; }
.hcc-mobile-cta .hcc-btn { width: 100%; }
/* The panel is inside .site-header, which the base inverts to a white ring —
   correct here, since the panel is navy too. */

/* --- 3.1 Breadcrumb ------------------------------------------------------- */
.breadcrumb {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2);
  font-size: var(--t-meta); color: var(--slate-500);
  padding: var(--s4) 0;
}
.breadcrumb .sep { color: var(--slate-300); }
.breadcrumb a:hover { color: var(--navy-700); text-decoration: underline; text-underline-offset: 3px; }
.breadcrumb .current { color: var(--slate-500); }

/* --- 3.2 SEO link hub — a different substrate: infrastructure ------------- */
.link-hub { background: #fff; border-top: 1px solid var(--slate-200); padding: var(--s16) 0 var(--s12); }
.link-hub h2 {
  font-size: var(--t-h2); font-weight: var(--w-hvy);
  letter-spacing: -.025em; line-height: 1.2; margin-bottom: var(--s10);
}
.link-hub .cols { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s12) var(--s6); }
/* Hold 2 columns until 1024. Flipping to 4 at 768 wrapped virtually all 40
   links onto two ragged lines through the whole tablet band. */
@media (min-width: 1024px) { .link-hub .cols { grid-template-columns: repeat(4, 1fr); } }
.link-hub h3 { font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-900); margin-bottom: var(--s3); }
.link-hub ul { list-style: none; padding: 0; display: flex; flex-direction: column; gap: var(--s2); }
.link-hub ul a { font-size: var(--t-meta); color: var(--navy-600); }   /* 7.15:1 on white */
.link-hub ul a:hover { color: var(--navy-700); text-decoration: underline; text-underline-offset: 3px; }
.hcc-hub-close { border-top: 1px solid var(--slate-300); margin-top: var(--s12); }

/* --- 3.3 Footer ----------------------------------------------------------- */
.site-footer { background: var(--slate-900); color: var(--slate-300); padding: var(--s16) 0 var(--s8); margin-top: auto; }
.footer-grid { display: grid; grid-template-columns: 1fr; gap: var(--s10); }
@media (min-width: 768px)  { .footer-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .footer-grid { grid-template-columns: 2fr 1fr 1fr 1fr; gap: var(--s8); } }
.footer-brand .chip { display: inline-flex; background: #fff; border-radius: var(--r-sm); padding: var(--s2) var(--s3); margin-bottom: var(--s4); }
.footer-brand img { height: 28px; width: auto; }
.footer-brand p { font-size: var(--t-meta); color: var(--slate-400); line-height: 1.6; max-width: 340px; }
/* <h3>, not <h4>: these heads are siblings of the SEO hub's four column h3s.
   Demoting them would nest the whole footer under the hub's last column
   ("Pre-owned equipment") and make the document outline strictly worse. This
   resolves the h3/h4 divergence that used to split index.html from the other
   three files — one grammar, all pages. */
.site-footer h3 {
  color: #fff; font-size: var(--t-micro); font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: .08em; margin-bottom: var(--s4);
}
.site-footer ul { list-style: none; padding: 0; display: flex; flex-direction: column; gap: var(--s3); }
.site-footer ul a { font-size: var(--t-meta); color: var(--slate-400); }   /* 6.96:1 on slate-900 */
.site-footer ul a:hover { color: #fff; }
/* Social row. One link today (Instagram); the previous footer shipped two dead
   "#" placeholders beside it, which is a trust cost on a page whose whole
   argument is that the site is real. */
.footer-social { display: flex; gap: var(--s2); margin-top: var(--s4); }
.footer-social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: var(--r-md);
  background: var(--slate-800); color: var(--slate-300);
  transition: background-color .15s, color .15s;
}
.footer-social a:hover { background: var(--navy-700); color: #fff; }

.footer-bottom {
  border-top: 1px solid var(--slate-800);
  margin-top: var(--s10); padding-top: var(--s8);
  display: flex; flex-wrap: wrap; gap: var(--s3);
  justify-content: space-between;
  font-size: var(--t-micro); color: var(--slate-400);
}


/* ============================================================================
   4. PRIMITIVES — buttons, pills, badges, icons
   ============================================================================ */

/* The border/appearance reset is load-bearing: these classes land on <a> in
   some places and <button type="submit"> in others. Without it the button
   inherits the UA's 2px outset 3D frame and appearance:auto, painting a bevel
   over the navy fill right beside a clean 1px input. */
.hcc-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  font-family: inherit; font-size: var(--t-meta);
  border: 0; appearance: none; -webkit-appearance: none;
  border-radius: var(--r-md);
  transition: background-color .15s, border-color .15s, color .15s;
  white-space: nowrap;
}
.hcc-btn--primary {
  background: var(--navy-700); color: #fff; font-weight: var(--w-bold);
  padding: 0 var(--s6); min-height: 48px;
}
.hcc-btn--primary:hover { background: var(--navy-800); }
.hcc-btn--secondary {
  background: #fff; border: 1px solid var(--slate-300); color: var(--slate-700);
  font-weight: var(--w-semi); padding: 0 var(--s6); min-height: 48px;
}
.hcc-btn--secondary:hover { border-color: var(--navy-300); background: var(--navy-50); color: var(--navy-700); }
/* Compact variant for dense control rows (browse filter bar, map topbar). */
.hcc-btn--sm { min-height: 44px; padding: 0 var(--s4); }

/* Inline text link with a trailing arrow — the "more" affordance. */
.hcc-link {
  font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--navy-700);
  display: inline-flex; align-items: center; gap: var(--s1); min-height: 44px;
}
.hcc-link:hover { text-decoration: underline; text-underline-offset: 3px; }

/* Pill — chip-scale navigation affordance. One of the three sanctioned 999px
   uses (see the RADIUS law). Small, text-only, never a primary action. */
.pill {
  display: inline-flex; align-items: center; gap: var(--s1);
  background: #fff; border: 1px solid var(--slate-300);
  border-radius: 999px; padding: var(--s2) var(--s4);
  font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-700);
  white-space: nowrap;
  transition: background-color .15s, border-color .15s, color .15s;
}
.pill:hover { border-color: var(--navy-300); color: var(--navy-700); background: var(--navy-50); }
.pill[aria-pressed="true"], .pill.is-on { border-color: var(--navy-700); color: var(--navy-700); background: var(--navy-50); }

/* Badges — DESIGN-SYSTEM.md's formula: tiny, bold, uppercase, *-50 fill +
   *-100/200 border + dark same-hue text. */
.badge {
  display: inline-block;
  font-size: 10px; font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: .04em;
  padding: 3px var(--s2); border-radius: var(--r-sm);
}
.badge-adtype   { color: var(--navy-700);  background: var(--navy-50);  border: 1px solid var(--navy-100); }
.badge-category { color: var(--slate-600); background: var(--slate-100); border: 1px solid var(--slate-200); }
.badge-featured { color: var(--amber-800); background: var(--amber-50);  border: 1px solid var(--amber-200); }
/* On a photograph the tinted badge needs an opaque backing to stay legible. */
.badge-on-photo { background: rgba(255,255,255,.94); }

/* Verified / trust tick — emerald, used sparingly. */
.hcc-verified {
  display: inline-flex; align-items: center; gap: var(--s2);
  font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--emerald-700);
}

/* Icons. DESIGN-SYSTEM.md specifies stroke-width 2 for the Lucide-style set;
   these pages run 1.75–2.2, which is OPTICAL SCALING, not drift — stroke weight
   is scaled against icon size so every size reads at the same visual weight
   (1.75 at 19px matches 2 at 14px far better than 2 would). Everything else in
   that spec is honoured: fill=none, stroke=currentColor, 14–19px, aria-hidden
   + focusable="false", no emoji, no filled sets. Do not "normalise" these. */
.icon { width: 15px; height: 15px; flex-shrink: 0; }

.muted { color: var(--slate-500); }

/* Visible to assistive tech only. Clip-path rather than width/height:0, so the
   text still has layout and is announced in reading order. */
.hcc-sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}


/* ============================================================================
   5. SECTION HEADS — two grammars, never mixed
   ============================================================================
   (A) rule head      inventory sections. Quiet by design.
   (B) editorial head sections making an argument. Reserved — it loses its
                      force if it appears more than twice on a page.
   ============================================================================ */

/* (A) RULE HEAD — H2 · hairline · "View all →" */
.hcc-rulehead { display: flex; align-items: baseline; gap: var(--s6); margin-bottom: var(--s10); }
.hcc-rulehead h1,
.hcc-rulehead h2 { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; line-height: 1.2; flex-shrink: 0; }
.hcc-rulehead .rule { flex: 1; height: 1px; background: var(--slate-200); }
.hcc-rulehead .more {
  flex-shrink: 0; font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--navy-700);
  display: inline-flex; align-items: center; gap: var(--s1); min-height: 44px;
}
.hcc-rulehead .more:hover { text-decoration: underline; text-underline-offset: 3px; }
/* Below 600px the hairline is hidden, which used to leave an unshrinkable
   H2 + "View all" pair wider than the content box — one of three causes of a
   horizontally-scrolling page on every phone narrower than 409px. Wrap
   instead. */
@media (max-width: 599px) {
  .hcc-rulehead { flex-wrap: wrap; gap: var(--s2) var(--s6); }
  .hcc-rulehead .rule { display: none; }
  .hcc-rulehead h1,
  .hcc-rulehead h2 { flex-shrink: 1; }
}

/* (B) EDITORIAL HEAD — uppercase kicker → statement H2 → lede.
   .k declares no colour, so each instance is tinted by its surface; the
   on-dark override lives with the surface that needs it. */
.hcc-edhead .k {
  display: block; font-size: var(--t-micro); font-weight: var(--w-semi);
  letter-spacing: .1em; text-transform: uppercase; margin-bottom: var(--s4);
  color: var(--slate-500);
}
.hcc-edhead h1,
.hcc-edhead h2 { font-size: var(--t-stmt); font-weight: var(--w-bold); letter-spacing: -.025em; line-height: 1.1; }
.hcc-edhead .lede { margin-top: var(--s6); font-size: var(--t-lede); line-height: 1.6; color: var(--slate-600); max-width: 54ch; }
.hcc-on-dark .hcc-edhead .k { color: rgba(255,255,255,.55); }
.hcc-on-dark .hcc-edhead h1,
.hcc-on-dark .hcc-edhead h2 { color: #fff; }
@media (max-width: 599px) { .hcc-edhead h1, .hcc-edhead h2 { font-size: 33px; line-height: 1.15; } }


/* ============================================================================
   6. CARDS — one component, three shapes
   ============================================================================
   .hcc-card            the standard photo-first, price-led card.
                        Home's 4-up row and browse's grid are the SAME object.
   .hcc-card--row       horizontal compact variant (map list panel).
   .hcc-card--marquee   the browse paid-placement card: gallery + body split.

   Before this file these were three separate implementations (.hp-card,
   .listing-card, .mvc) that drifted apart on radius, elevation, price size and
   favourite-button behaviour. They are one component now.
   ============================================================================ */

.hcc-card {
  position: relative;
  display: flex; flex-direction: column;
  background: #fff;
  border: 1px solid var(--slate-300);        /* slate-300 OUTLINES a thing */
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: border-color .15s;
}
.hcc-card:hover { border-color: var(--slate-400); }

/* Amber is exclusively the Featured signal: border + 1px ring, identical on
   home, browse and detail so the paid tier reads the same everywhere. */
.hcc-card.is-featured { border-color: var(--amber-200); box-shadow: 0 0 0 1px var(--amber-100); }
.hcc-card.is-featured:hover { border-color: var(--amber-300); }

/* NO transform here. A transform makes this a stacking context, which traps
   the chip and the favourite button inside it — they can then never rise above
   the stretched title link, and every click on the heart silently navigates to
   the listing instead. Keyboard still worked, which is why a keyboard-only
   pass would never have caught it. overflow:hidden alone clips the push-in. */
.hcc-card-media { position: relative; overflow: hidden; }
.hcc-card-media img {
  width: 100%; height: 100%; object-fit: cover;
  /* 3:2 NORMALISES a mixed library. The 600x400 category photos are already
     3:2; the 816x489 listing photos (1.669) lose ~10% of their width to cover.
     Re-check the crop if either of those files is swapped. */
  aspect-ratio: 3 / 2;
  transition: transform .45s cubic-bezier(.2,.6,.2,1);
}
.hcc-card:hover .hcc-card-media img { transform: scale(1.03); }

/* NO-PHOTO FALLBACK. photo1 is required at Step 3, but legacy rows predate
   that and can be photoless — on a photo-first card that is a real state, not
   an edge case, so it is designed rather than left to collapse the layout.
   A quiet slate plate at the same 3:2 keeps the grid's rhythm intact; it
   deliberately does NOT borrow a category stock photo, because dressing a
   generic photo up as a listing's own is a credibility problem, not a
   layout fix. Also the honest treatment for the equipment category, which has
   almost no photography in the approved library. */
.hcc-card-media.is-empty {
  aspect-ratio: 3 / 2;
  background: var(--slate-100);
  border-bottom: 1px solid var(--slate-200);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s2); color: var(--slate-400);
}
.hcc-card-media.is-empty .lbl {
  font-size: var(--t-micro); font-weight: var(--w-semi);
  letter-spacing: .06em; text-transform: uppercase;
}

/* z-index 3 keeps the overlay controls above the stretched link, which is a
   positioned z-index:auto box later in tree order. */
.hcc-card-chip { position: absolute; top: var(--s3); left: var(--s3); z-index: 3; }
.hcc-card-cat  { position: absolute; bottom: var(--s3); left: var(--s3); z-index: 3; }

/* Photo count / gallery affordance, bottom-right on the media. */
.hcc-card-count {
  position: absolute; bottom: var(--s3); right: var(--s3); z-index: 3;
  display: inline-flex; align-items: center; gap: var(--s1);
  background: rgba(3,15,33,.68); color: #fff;
  font-size: var(--t-micro); font-weight: var(--w-semi);
  padding: var(--s1) var(--s2); border-radius: var(--r-sm);
}

/* Round IS the affordance here — sanctioned 999px use #1. */
.hcc-fav {
  position: absolute; top: var(--s3); right: var(--s3); z-index: 3;
  width: 40px; height: 40px; border-radius: 999px;
  background: rgba(255,255,255,.92); border: none;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--slate-600);
  transition: color .15s, background-color .15s;
}
.hcc-fav:hover { color: var(--red-500); background: #fff; }
/* PRODUCTION-ONLY (no counterpart in the prototype, which fakes the toggle in
   JS): saving a listing is a mutation, so it goes out as a POST carrying a
   CSRF token. The <form> takes the overlay position and the button sits static
   inside it — that preserves both the button's geometry and the z-index that
   holds it above the card's stretched title link. Without the z-index the
   media becomes the topmost positioned box and every tap on the heart
   navigates to the listing instead. */
.hcc-fav-form { position: absolute; top: var(--s3); right: var(--s3); z-index: 3; margin: 0; }
.hcc-fav-form .hcc-fav { position: static; }
.hcc-fav[aria-pressed="true"] { color: var(--red-500); }
.hcc-fav[aria-pressed="true"] svg { fill: currentColor; }
@media (prefers-reduced-motion: no-preference) {
  .hcc-fav[aria-pressed="true"] svg { animation: hcc-pop .28s cubic-bezier(.2,.7,.3,1.4); }
  @keyframes hcc-pop { 0%{transform:scale(1)} 45%{transform:scale(1.22)} 100%{transform:scale(1)} }
}

.hcc-card-body { padding: var(--s4); display: flex; flex-direction: column; gap: var(--s1); flex: 1; }

.hcc-card-price {
  font-size: var(--t-price); font-weight: var(--w-hvy);
  letter-spacing: -.02em; line-height: 1.2;
  color: var(--slate-900); font-variant-numeric: tabular-nums;
}
/* The frequency suffix never scales with the numeral, so $180,000/yr sits
   correctly against $890,000. */
.hcc-card-price .freq { font-size: var(--t-meta); font-weight: var(--w-med); color: var(--slate-500); letter-spacing: 0; margin-left: var(--s1); }

/* NULL-PRICE RULE. Owner decision D2: show the price where it is set (>0),
   never where it is empty. hcc_price() already returns null on empty/zero, so
   the PHP port simply does not render this element — the title moves up into
   its place. Never "$0", never a "Price on request" placeholder. The class is
   here for the static mockups, which have no PHP to omit the node. */
.hcc-card.is-noprice .hcc-card-price { display: none; }

.hcc-card-title {
  font-size: var(--t-body); font-weight: var(--w-semi); line-height: 1.35; color: var(--slate-900);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
  /* Reserve 2 lines for levelling but allow a 3rd: a clipped listing title
     ("…Parental Leave Cov…") costs more credibility than one meta rule sitting
     a line lower. */
  min-height: 2.7em;
}
.hcc-card-title a { color: inherit; }
.hcc-card-title a::after { content: ""; position: absolute; inset: 0; }   /* stretched link */
.hcc-card:hover .hcc-card-title { text-decoration: underline; text-underline-offset: 3px; }

.hcc-card-loc { display: flex; align-items: center; gap: var(--s1); font-size: var(--t-meta); color: var(--slate-500); }

/* margin-top:auto pins the meta to the card bottom, so all the hairlines in a
   grid row share one baseline even when titles run to different line counts.
   ONE line, truncated — the cards close with a single quiet fact line and the
   adtype/category live on the photo as a chip. */
.hcc-card-meta {
  margin-top: auto; padding-top: var(--s3);
  border-top: 1px solid var(--slate-200);    /* slate-200 = a line BETWEEN things */
  font-size: var(--t-meta); color: var(--slate-500); line-height: 1.5;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Card focus: where :has() is supported the ring is drawn on the CARD and the
   inner link's own ring is suppressed, so exactly one renders. That matters
   because .hcc-card-title is a -webkit-box with overflow:hidden for the clamp,
   so an inner ring paints as a clipped navy bracket beside the title. Both
   selectors contain :has() and are therefore self-gating — engines without it
   keep the inner link ring, which is the correct degradation. */
.hcc-card:has(a:focus-visible) { outline: 2px solid var(--navy-700); outline-offset: 3px; }
.hcc-card:has(a:focus-visible) .hcc-card-title a:focus-visible { outline: none; }

/* --- 6.1 Row variant — horizontal, for scrolling list panels -------------- */
.hcc-card--row { flex-direction: row; gap: var(--s3); padding: var(--s2); align-items: stretch; }
.hcc-card--row .hcc-card-media {
  width: 124px; flex-shrink: 0;
  border-radius: var(--r-sm);            /* inner = outer(14) − padding(8) */
  align-self: stretch;
  min-height: 96px;                      /* floor when the body is short */
}
/* The thumbnail must CROP to the row, never size it. Left as a normal in-flow
   image with height:100%, the percentage resolves against a parent whose own
   height comes from the flex line — so it falls back to `auto` and the image's
   INTRINSIC ratio takes over. A portrait source (801x1200) then rendered
   124 x 186px and dragged the whole card to 204px, while its landscape
   neighbours sat at 126px. Ragged rows from nothing but source aspect ratio.
   Absolute positioning breaks the cycle: the media stretches to the flex line,
   the image fills the media, object-fit does the cropping. */
.hcc-card--row .hcc-card-media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  aspect-ratio: auto; object-fit: cover;
}
/* The row's media is a fixed-width thumbnail that stretches to the card's
   height, so the 3:2 the grid card uses would fight `align-self: stretch`.
   The label is dropped too — "NO PHOTOS YET" does not fit 124px and would
   wrap to three lines. */
.hcc-card--row .hcc-card-media.is-empty { aspect-ratio: auto; min-height: 96px; border-bottom: none; }
.hcc-card--row .hcc-card-media.is-empty .lbl { display: none; }
.hcc-card--row .hcc-card-body { padding: var(--s2) var(--s2) var(--s2) 0; gap: 2px; }
.hcc-card--row .hcc-card-price { font-size: var(--t-body); }
.hcc-card--row .hcc-card-title {
  font-size: var(--t-meta); font-weight: var(--w-semi); min-height: 0;
  -webkit-line-clamp: 2;
}
.hcc-card--row .hcc-card-meta { font-size: var(--t-micro); padding-top: var(--s2); }
/* The row's favourite button is inline in the body, not overlaid on a photo,
   so it drops the white backing plate but keeps the round affordance. */
.hcc-card--row .hcc-fav {
  position: static; width: 32px; height: 32px;
  background: transparent; margin: -4px -4px 0 0;
}
.hcc-card--row .hcc-fav:hover { background: var(--slate-100); }
/* Selected state — used by the map when a pin is clicked. */
.hcc-card--row.is-active { border-color: var(--navy-700); box-shadow: 0 0 0 1px var(--navy-700); }

/* --- 6.2 Marquee variant — the paid placement on browse ------------------- */
.hcc-card--marquee { margin-bottom: var(--s6); }
@media (min-width: 920px) {
  .hcc-card--marquee { display: grid; grid-template-columns: minmax(0, 58fr) minmax(0, 42fr); }
}
.hcc-mq-gallery { display: flex; flex-direction: column; gap: var(--s1); padding: var(--s1); }
.hcc-mq-main {
  position: relative; display: block; overflow: hidden;
  border-radius: var(--r-md);            /* inner = outer(14) − padding(4) */
  aspect-ratio: 16/10; background: var(--slate-100);
}
/* The photo link wraps ONLY the image. The Featured chip and the favourite
   control are SIBLINGS of it, not children — a <button> (or a CSRF <form>)
   nested inside an <a> is invalid content and gives the row two overlapping
   activation targets. This is the same defect the map's list cards had. */
.hcc-mq-main > a { position: absolute; inset: 0; display: block; z-index: 1; }
.hcc-mq-thumbs { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s1); }
.hcc-mq-thumbs a {
  position: relative; display: block; overflow: hidden;
  border-radius: var(--r-sm);
  aspect-ratio: 16/10; background: var(--slate-100);
}
.hcc-mq-main img, .hcc-mq-thumbs img { width: 100%; height: 100%; object-fit: cover; }
.hcc-mq-more {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(3,15,33,.62); color: #fff;
  font-size: var(--t-micro); font-weight: var(--w-semi); text-align: center; padding: var(--s1);
}
.hcc-mq-body { padding: var(--s6); display: flex; flex-direction: column; gap: var(--s3); }
@media (min-width: 920px) { .hcc-mq-body { padding: var(--s8); } }
.hcc-mq-badges { display: flex; flex-wrap: wrap; gap: var(--s1); }
.hcc-mq-price {
  font-size: var(--t-stmt); font-weight: var(--w-hvy); letter-spacing: -.03em; line-height: 1.1;
  color: var(--slate-900); font-variant-numeric: tabular-nums;
}
.hcc-mq-price .freq { font-size: var(--t-lede); font-weight: var(--w-med); color: var(--slate-500); letter-spacing: 0; margin-left: var(--s1); }
.hcc-mq-title { font-size: var(--t-lede); font-weight: var(--w-bold); line-height: 1.3; letter-spacing: -.015em; color: var(--slate-900); }
.hcc-mq-title a:hover { text-decoration: underline; text-underline-offset: 3px; }
.hcc-mq-stats {
  display: flex; flex-wrap: wrap; gap: var(--s1) 0;
  font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-600);
  padding: var(--s3) 0;
  border-top: 1px solid var(--slate-200); border-bottom: 1px solid var(--slate-200);
}
.hcc-mq-stats span { display: inline-flex; align-items: center; }
.hcc-mq-stats span + span::before { content: ""; width: 1px; height: 14px; background: var(--slate-200); margin: 0 var(--s3); }
/* The gallery column is taller than the body's price+title+stats, so without
   this the footer's margin-top:auto opened ~100px of dead space in the middle
   of the page's most expensive placement. An excerpt is not filler — browse
   already renders one per listing via hcc_excerpt(), so this is the marquee
   showing the field it should always have shown. */
.hcc-mq-excerpt {
  font-size: var(--t-meta); line-height: 1.65; color: var(--slate-600);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.hcc-mq-footer {
  margin-top: auto; padding-top: var(--s3);
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: var(--s3);
}
.hcc-mq-meta { font-size: var(--t-micro); color: var(--slate-500); }


/* ============================================================================
   7. SEARCH — shell, segmented toggle, submit
   ============================================================================
   A softly-rounded PANEL, not a 999px capsule. Sized as the primary action.
   ============================================================================ */
.search-shell {
  background: #fff;
  border-radius: var(--r-lg);
  display: flex; align-items: center;
  padding: var(--s2); gap: var(--s2);
  max-width: 720px; width: 100%;
}
.search-shell:focus-within { box-shadow: var(--shadow-pop), 0 0 0 3px rgba(255,255,255,.85); }

/* The toggle track and the submit button are the two declared optical
   exceptions to inner = outer − padding (see §1.4). */
.search-toggle { display: flex; background: var(--slate-100); border-radius: 9px; padding: 3px; flex-shrink: 0; }
.search-toggle button {
  border: none; background: transparent;
  font-size: var(--t-meta); font-weight: var(--w-mid); color: var(--slate-600);
  min-height: 48px; padding: 0 var(--s4);
  border-radius: var(--r-sm);
  transition: background-color .15s, color .15s;
  white-space: nowrap;
}
.search-toggle button:hover { color: var(--navy-700); }
.search-toggle button.active { background: var(--navy-700); color: #fff; }

.search-input {
  flex: 1; min-width: 0; border: none; outline: none; background: transparent;
  font-family: inherit; font-size: var(--t-body); color: var(--slate-900);
  padding: var(--s2); text-overflow: ellipsis;
}
.search-input::placeholder { color: var(--slate-400); }

.search-submit {
  width: 52px; height: 52px; border-radius: 8px;
  background: var(--navy-700); color: #fff; border: none;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; transition: background-color .15s;
}
.search-submit:hover { background: var(--navy-800); }

/* 767, and the number is derived, not chosen.
   With the toggle still inline the input gets `shell − 406px` (toggle 322 +
   submit 52 + 16 padding + 16 gaps). The default placeholder — "City,
   province, profession, or keyword" — measures 286.6px in Inter 16px, and the
   placeholder is the only thing telling a first-time visitor what the box
   accepts, so it must not clip. Solving shell ≥ 693 against
   shell = min(760, viewport − 48) gives viewport ≥ 741; 767 is the next
   standard breakpoint above that, and yields 314px of input at 768.

   This was 689px, which was correct for the mockup's THREE-segment toggle
   (~250px wide). Production ships FOUR segments — "All" was added so the
   homepage search does not silently narrow to one adtype — and the extra 72px
   pushed the squeeze point up: at 690px the input measured 236px against a
   287px placeholder. If the segment count ever changes again, re-derive this
   number rather than nudging it. */
@media (max-width: 767px) {
  .search-shell { flex-wrap: wrap; }
  .search-toggle { width: 100%; }
  .search-toggle button { flex: 1; }
}
/* The scaled-up toggle overflowed a 320px viewport — three buttons' min-content
   beat the wrapped shell's width. Step it back where every pixel counts.
   16px on the input also suppresses iOS focus-zoom. */
@media (max-width: 419px) {
  .search-toggle button { padding: 0 var(--s2); }
  .search-input { font-size: 16px; }
}


/* ============================================================================
   8. PAGE MODULES
   ============================================================================
   Everything above is shared by all four pages. Everything below is scoped to
   one page and prefixed accordingly:  .hp-* home · .br-* browse · .mv-* map ·
   .dt-* detail. A rule that starts wanting to live in two of these blocks
   belongs in §4–§7 instead.
   ============================================================================ */


/* ============================================================================
   8.1 HOME (.hp-*)
   ============================================================================ */

/* ---- HERO ----------------------------------------------------------------
   Centred masthead. This is rew.ca's own hero move: a band whose job is to
   state what the site is and hand over the search, not to be a poster. The
   hero is the ONLY centred block on the page; every content section below sits
   on the left rail, so "everything centred" — the actual checklist tell —
   still does not happen.
   Zero pills, zero backdrop-filter, zero text-shadow: the scrim does the work. */
.hp-hero {
  position: relative; color: #fff; overflow: hidden;
  background: url('images/hero-clinic.jpg') center 42% / cover no-repeat var(--navy-800);
}
/* The scrim was 80/60/82% and turned a warm, bright reception photo into navy
   mud — rew.ca's hero works because the photo stays BRIGHT. Cut to 62/26/58,
   bottom-weighted, so the wood, plants and warm light actually read. White
   text still clears WCAG over the darkened top band. */
.hp-hero::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(3,15,33,.62) 0%, rgba(3,15,33,.62) 18%, rgba(3,15,33,.26) 55%, rgba(3,15,33,.58) 100%);
}
.hp-hero .hcc-container { position: relative; z-index: 1; }
.hp-hero-inner {
  max-width: 760px;          /* sized for the search shell; the H1 caps in ch */
  margin: 0 auto;
  /* A hero this quiet needs HEIGHT to read as confident — was ≈435px, now
     ≈580px. rew.ca gives its hero the same room. */
  padding: var(--s28) 0 var(--s24);
  display: flex; flex-direction: column; justify-content: center;
  align-items: center; text-align: center;
}
@media (max-width: 899px) { .hp-hero-inner { padding: var(--s16) 0 var(--s12); } }

/* Plain uppercase text. No pill, no border, no amber. */
.hp-kicker {
  font-size: var(--t-micro); font-weight: var(--w-semi);
  letter-spacing: .1em; text-transform: uppercase;
  color: #fff; margin-bottom: var(--s2);
}
/* The hero carries NO subcopy — rew.ca's structure is eyebrow, headline,
   search. The paragraph that used to sit here ran 168 characters over three
   lines and listed practices / equipment / careers, which the search toggle
   immediately below already says as an interactive control. 24ch holds the
   headline to two lines. */
.hp-headline {
  font-size: var(--t-display); font-weight: var(--w-max);
  letter-spacing: -.03em; line-height: 1.02;
  max-width: 24ch; text-wrap: balance; color: #fff;
  margin-bottom: var(--s8);
}
@media (max-width: 1023px) { .hp-headline { font-size: 48px; } }
@media (max-width: 599px)  { .hp-headline { font-size: 36px; line-height: 1.08; margin-bottom: var(--s6); } }

/* The search shell has to read as lifted off a photograph, which is what
   --shadow-lift exists for. This is one of only two shadow uses on the page. */
.hp-hero .search-shell { box-shadow: var(--shadow-lift); max-width: 100%; }

/* The map entry is a translucent dark pill — rew.ca's own affordance. On the
   brighter photo an underlined text link disappeared. Sanctioned 999px use #2
   (chip-scale). The locations line moved OUT of the hero entirely (see
   .hp-locstrip), so the hero is just kicker → headline → search → map. */
.hp-hero-utils { margin-top: var(--s6); display: flex; justify-content: center; }
.hp-maplink {
  display: inline-flex; align-items: center; gap: var(--s2);
  font-size: var(--t-meta); font-weight: var(--w-mid); color: #fff;
  min-height: 44px; padding: 0 var(--s6);
  background: rgba(3,15,33,.55);
  border: 1px solid rgba(255,255,255,.22);
  border-radius: 999px;
  backdrop-filter: none;     /* deliberate: no glassmorphism — the tint reads */
  transition: background-color .15s, border-color .15s;
}
.hp-maplink:hover { background: rgba(3,15,33,.75); border-color: rgba(255,255,255,.4); }

/* The search shell is a WHITE panel inside the dark hero, so the inverted ring
   would be white-on-white (1:1). Navy ring back for the controls inside it;
   .hp-maplink keeps the white ring it needs over the photograph. */
.hp-hero .search-shell :focus-visible { outline-color: var(--navy-700); }

/* ---- LOCATIONS STRIP -----------------------------------------------------
   rew.ca's pattern: "Top Cities" live on the CANVAS under the hero, not inside
   it. Quiet row; .pill comes from §4. */
.hp-locstrip { padding: var(--s6) 0; }
.hp-locstrip .row { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s3); justify-content: center; }
.hp-locstrip .lbl {
  font-size: var(--t-micro); font-weight: var(--w-mid); letter-spacing: .1em;
  text-transform: uppercase; color: var(--slate-500); margin-right: var(--s2);
}
@media (max-width: 599px) { .hp-locstrip .lbl { flex-basis: 100%; text-align: center; margin-right: 0; } }

/* ---- 01 MOST POPULAR LISTINGS -------------------------------------------
   rew.ca's own homepage pattern: a row of four photo-first, price-led cards
   plus a "View all". Cards are peers — the photo does the work and the price
   leads. The card itself is §6, shared with browse. */
.hp-market { padding: var(--s16) 0 var(--s32); }
@media (max-width: 899px) { .hp-market { padding: var(--s12) 0 var(--s24); } }
.hp-cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s6); }
@media (max-width: 1023px) { .hp-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 559px) {
  .hp-cards { grid-template-columns: 1fr; }
  /* single column: the 2-line title reservation just leaves a blank band */
  .hp-cards .hcc-card-title { min-height: 0; }
}
/* Tighter facade crop — the wide framing read as an architectural rendering
   (flat sky, empty lot) at card sizes. */
.hcc-card-media img.crop-facade { object-position: center 68%; }

/* ---- 02 BY PROFESSION (run-on) ------------------------------------------
   Shares the canvas with 01 and is separated by a rail-anchored hairline that
   stops at the content box — never full-bleed. That is what makes the rail
   visible. */
.hp-prof { padding: 0 0 var(--s24); }
.hp-prof-rule { border-top: 1px solid var(--slate-200); padding-top: var(--s10); }
.hp-mosaic { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s6); }
/* Two-tier prominence, ordered by real listing count: the four largest
   professions take a double-width tile, the four smallest a single. (Honest
   framing: two tiers, not an exact area-to-count mapping.) */
.hp-tile { position: relative; overflow: hidden; border-radius: var(--r-lg); height: 200px; transform: translateZ(0); }
.hp-tile.is-wide { grid-column: span 2; }
/* ONE grading baseline for eight photos from eight shoots — mild desaturation
   levels the warm/cool spread; per-tile fine-tuning below. */
.hp-tile img { width: 100%; height: 100%; object-fit: cover; filter: saturate(.92); transition: transform .45s cubic-bezier(.2,.6,.2,1); }
.hp-tile:hover img { transform: scale(1.03); }
.hp-tile::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(0deg, rgba(3,15,33,.72) 0%, rgba(3,15,33,.12) 55%, rgba(3,15,33,0) 100%);
}
/* Crop with intent, per tile — one default object-position served eight
   different compositions and decapitated three of the four wide tiles. */
.hp-tile[data-crop="dentistry"] img     { object-position: center 38%; }
.hp-tile[data-crop="chiropractic"] img  { object-position: center 25%; filter: saturate(.92) brightness(1.1); }
.hp-tile[data-crop="physiotherapy"] img { object-position: center 30%; filter: saturate(.9) brightness(.95); }
.hp-tile[data-crop="senior"] img        { object-position: 72% 38%; filter: saturate(.88); }
.hp-tile[data-crop="naturopathy"] img   { object-position: center 35%; filter: saturate(.85); }
.hp-tile-cap { position: absolute; left: var(--s4); right: var(--s4); bottom: var(--s3); z-index: 1; }
.hp-tile-cap b { display: block; font-size: var(--t-body); font-weight: var(--w-mid); color: #fff; letter-spacing: -.015em; }
.hp-tile-cap span { font-size: var(--t-meta); color: rgba(255,255,255,.82); }
@media (max-width: 899px) {
  .hp-mosaic { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s4); }
  .hp-tile { height: 150px; }
  /* Uniform 2-col across the whole sub-900 band. The earlier 5/2-capped wide
     tiles stacked four near-full-width banners ahead of the small ones, and a
     grid item is width:auto — with aspect-ratio + min-height the ratio happily
     resolves WIDTH from the floored height and blows through the track, which
     scrolled the page sideways on every phone under 409px. */
  .hp-tile.is-wide { grid-column: span 1; width: 100%; height: 150px; aspect-ratio: auto; min-height: 0; }
}
/* Below 600px the two-tier system stops earning its length — 8 stacked tiles
   were a big share of an ~8,700px page. */
@media (max-width: 599px) {
  .hp-tile, .hp-tile.is-wide { grid-column: span 1; height: 130px; aspect-ratio: auto; min-height: 0; }
  .hp-tile-cap b { font-size: 15px; }
  .hp-tile-cap span { font-size: var(--t-micro); }
}

/* ---- 03 THE FIGURE SPREAD (proof) ---------------------------------------
   Flat navy-800. No gradient, no photograph, no icons, no chips. This is the
   direct answer to the three-icon value-prop triad on the anti-AI checklist.
   THE signature: scale is the one place this page spends its boldness. */
.hp-proof { background: var(--navy-800); color: #fff; padding: var(--s28) 0 var(--s24); }
@media (max-width: 899px) { .hp-proof { padding: var(--s16) 0; } }
.hp-proof-shelf { display: grid; grid-template-columns: 6fr 6fr; gap: var(--s10) var(--s16); align-items: end; }
@media (max-width: 899px) { .hp-proof-shelf { grid-template-columns: 1fr; gap: var(--s6); } }
.hp-proof h2 { max-width: 18ch; }
.hp-proof-lede {
  font-size: var(--t-lede); line-height: 1.6;
  color: rgba(255,255,255,.86); max-width: 46ch;
  padding-bottom: var(--s1);        /* optical baseline alignment with the H2 */
}
.hp-figs {
  margin-top: var(--s12); padding-top: var(--s12);
  border-top: 1px solid rgba(255,255,255,.14);
  /* minmax(0,1fr): plain 1fr floors at min-content, and one wide figure
     then bends the whole ruled grid wider than its peers (it did, when the
     spread had four figures incl. "15,000+" — removed 2026-09-26 on owner
     decision). Geometry beats raw size — also why --t-figure is 68 not 92. */
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
}
.hp-fig { padding-left: var(--s8); padding-right: var(--s6); border-left: 1px solid rgba(255,255,255,.14); }
.hp-fig:first-child { padding-left: 0; border-left: none; }
.hp-fig .n {
  font-size: var(--t-figure); font-weight: var(--w-hvy); letter-spacing: -.04em;
  line-height: .95; color: #fff; font-variant-numeric: tabular-nums;
}
/* Suffixes: size does the work an amber tint would otherwise be reached for. */
.hp-fig .n em { font-style: normal; font-size: .42em; font-weight: var(--w-mid); color: rgba(255,255,255,.85); letter-spacing: -.01em; }
/* "+" reads as a subscript at baseline; raise it toward cap height. "%" and
   "-in-1" stay on the baseline deliberately. */
.hp-fig .n em.up { vertical-align: .5em; }
.hp-fig .l { margin-top: var(--s4); font-size: var(--t-meta); color: rgba(255,255,255,.66); line-height: 1.45; max-width: 20ch; }
@media (max-width: 1199px) { .hp-fig .n { font-size: 56px; } }
/* Three figures, so no 2x2 band (it would strand the third). 3-up holds to
   640px with tighter gutters; below that a third of the column is too narrow
   for "100%" plus its label, so the spread stacks. The old 479/399/359 bands
   existed only because "15,000+" was one ~165px unbreakable token. */
@media (max-width: 899px) {
  .hp-fig { padding-left: var(--s6); padding-right: var(--s4); }
  .hp-fig .n { font-size: 52px; }
}
@media (max-width: 639px) {
  .hp-figs { grid-template-columns: 1fr; gap: var(--s8) 0; }
  .hp-fig { padding-left: 0; padding-right: 0; border-left: none; }
  .hp-fig .n { font-size: 46px; }
}

/* ---- 04 SELLER CTA -------------------------------------------------------
   Photo bleeds off the RIGHT edge. This is the page's ONE asymmetric split — a
   single deliberate break from the left rail, placed at the last content
   section so it reads as a closing gesture rather than a layout habit.
   overflow-x is LOAD-BEARING: it contains that bleed. */
.hp-cta { padding: var(--s28) 0; overflow-x: hidden; }
@media (max-width: 899px) { .hp-cta { padding: var(--s24) 0; } }
.hp-cta-grid { display: grid; grid-template-columns: 6fr 6fr; gap: var(--s16); align-items: center; }
@media (max-width: 899px) { .hp-cta-grid { grid-template-columns: 1fr; gap: var(--s10); } }
.hp-cta-body p.lede { margin-top: 20px; font-size: var(--t-lede); line-height: 1.6; color: var(--slate-700); max-width: 46ch; }
.hp-cta-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s4) var(--s6); margin-top: var(--s8); }
/* Amber, final appearance: the upsell DEMONSTRATES the convention at the
   moment it sells it, rather than imitating it. */
.hp-cta-featured { margin-top: var(--s6); font-size: var(--t-meta); color: var(--slate-600); line-height: 1.6; text-wrap: pretty; }
.hp-cta-media { position: relative; }
.hp-cta-media img {
  width: 100%; height: 100%; object-fit: cover;
  object-position: center 66%;      /* portrait source — hold the face in crop */
  aspect-ratio: 16 / 10; max-height: 460px;
  border-radius: var(--r-lg) 0 0 var(--r-lg);
}
/* Full-bleed to the RIGHT viewport edge. The bleed is derived from CONTAINER
   geometry, NOT from `50% - 50vw`: this element is a grid item in `6fr 6fr`, so
   a percentage margin resolves against its 528px grid area rather than the
   container content box. That drew a constant ~296px of the photo off-screen
   and the inflated width drove the height into max-height, so the declared
   ratio never actually rendered above 768px. Correct distance from content-box
   right edge to viewport edge: (container − 100vw) / 2 − container padding. */
@media (min-width: 900px)  { .hp-cta-media { margin-right: calc((min(1200px, 100vw) - 100vw) / 2 - 24px); } }
@media (min-width: 1024px) { .hp-cta-media { margin-right: calc((min(1200px, 100vw) - 100vw) / 2 - 40px); } }
@media (max-width: 899px)  { .hp-cta-media img { border-radius: var(--r-lg); } }

/* ---- 05 NEWSLETTER -------------------------------------------------------
   A bare input floating on the canvas read as an afterthought. Contained panel
   — navy-50 fill + navy-100 border, the ONE tinted-surface use on the page —
   so the section has object presence without introducing new colour. */
.hp-news { padding: 0 0 var(--s24); }
.hp-news-rule { padding-top: var(--s16); }
.hp-news-panel {
  background: var(--navy-50); border: 1px solid var(--navy-100);
  border-radius: var(--r-lg); padding: var(--s10) var(--s12);
}
@media (max-width: 599px) { .hp-news-panel { padding: var(--s6); } }
.hp-news-grid { display: grid; grid-template-columns: 5fr 7fr; gap: var(--s16); align-items: center; }
@media (max-width: 899px) { .hp-news-grid { grid-template-columns: 1fr; gap: var(--s6); } }
.hp-news h2 { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; line-height: 1.2; }
.hp-news-deck { margin-top: var(--s3); font-size: var(--t-body); color: var(--slate-600); line-height: 1.6; }
.hp-news-label { display: block; font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-700); margin-bottom: var(--s2); }
.hp-news-row { display: flex; gap: var(--s2); }
.hp-news-form input {
  flex: 1; min-width: 0; border: 1px solid var(--slate-300);
  border-radius: var(--r-md); padding: 0 var(--s4); min-height: 48px;
  font-family: inherit; font-size: var(--t-body); color: var(--slate-900);
  background: #fff; outline: none;
}
.hp-news-form input::placeholder { color: var(--slate-500); }
/* The input sets outline:none at (0,1,1) for its resting state, and the bare
   :focus-visible in §2.1 at (0,1,0) can never outrank it — so the page's only
   text input had no visible focus indicator at all (WCAG 2.4.7 failure).
   Restore it at (0,1,2). */
.hp-news-form input:focus-visible { outline: 2px solid var(--navy-700); outline-offset: 3px; }
.hp-news-fine { margin-top: var(--s3); font-size: var(--t-micro); color: var(--slate-500); }
.hp-news-fine a { color: var(--navy-700); font-weight: var(--w-semi); text-decoration: underline; text-underline-offset: 2px; }
/* Skin by STATE class, not by :not(:empty) — keying the success colours off
   "has text" meant the error message rendered as red type inside the green
   success panel. Tints are mixed from the palette rather than hard-coded,
   because the token set declares only emerald-50/600/700 and red-500/700. */
.hp-news-status:not(:empty) {
  margin-top: var(--s3); font-size: var(--t-meta); font-weight: var(--w-semi);
  border-radius: var(--r-md); padding: var(--s3) var(--s4);
}
.hp-news-status.is-ok {
  color: var(--emerald-700); background: var(--emerald-50);
  border: 1px solid color-mix(in srgb, var(--emerald-600) 35%, #fff);
}
.hp-news-status.is-err {
  color: var(--red-700);
  background: color-mix(in srgb, var(--red-500) 8%, #fff);
  border: 1px solid color-mix(in srgb, var(--red-500) 35%, #fff);
}
@media (max-width: 479px) {
  .hp-news-row { flex-direction: column; }
  .hp-news-row .hcc-btn { width: 100%; }
}


/* ============================================================================
   8.2 BROWSE (.br-*)
   ============================================================================
   The listing cards, the marquee, the section-head grammars, the buttons and
   the badges are all §4–§7. What remains here is genuinely browse-only: the
   control rows, the dropdowns, pagination and the SEO block.
   ============================================================================ */

.br-main { padding-bottom: var(--s16); }

/* ---- Page intro — editorial head, grammar (B) ---------------------------- */
.br-intro { padding-top: var(--s2); }
.br-intro .lede { margin-top: var(--s4); max-width: 72ch; font-size: var(--t-lede); line-height: 1.6; color: var(--slate-600); }

/* ---- Toolbar: keyword + map view ----------------------------------------
   The keyword field is a CONTROL, so --r-md. It used to be a 999px capsule,
   which put it in the same shape family as the filter chips beside it and made
   the primary input read as one more chip. */
.br-toolbar { display: flex; gap: var(--s2); flex-wrap: wrap; margin: var(--s10) 0 var(--s3); }
.br-search {
  flex: 1 1 280px; display: flex; align-items: center; gap: var(--s2);
  background: #fff; border: 1px solid var(--slate-300); border-radius: var(--r-md);
  padding: 0 var(--s4); min-height: 48px;
  transition: border-color .15s;
}
.br-search:focus-within { border-color: var(--navy-400); }
.br-search svg { color: var(--slate-400); }
.br-search input {
  flex: 1; min-width: 0; border: none; outline: none; background: transparent;
  font-family: inherit; font-size: var(--t-body); color: var(--slate-900);
}
.br-search input::placeholder { color: var(--slate-400); }
/* 16px suppresses iOS focus-zoom; below 420 the field is the whole row anyway. */
@media (max-width: 419px) { .br-search input { font-size: 16px; } }

/* ---- Filter row ----------------------------------------------------------
   Chips are .pill (§4) — sanctioned 999px, chip-scale. The MENUS they open are
   floating panels and take --r-md + --shadow-pop, not a pill radius. */
.br-filters { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2); margin-bottom: var(--s4); }
.br-filters .spacer { flex: 1; }

/* ---- .br-chip — a filter chip that is a NATIVE <select> -------------------
   The mockup drew a bespoke dropdown (.br-drop / .br-menu below). That is fine
   for a mockup, but in production it would mean re-implementing keyboard
   interaction, type-ahead, and the native mobile picker — and every filter's
   name, value and session key has to survive the port untouched. A styled
   native select gives the chip appearance and keeps all of that for free.

   No `outline: none` on :focus. The chip changes its BORDER on focus and lets
   the global :focus-visible ring (§2.1) do the accessibility work; killing the
   outline here is how the newsletter input ended up with no focus indicator at
   all. */
.br-chip {
  appearance: none; -webkit-appearance: none;
  background-color: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--s3) center;
  border: 1px solid var(--slate-300);
  border-radius: 999px;                 /* sanctioned 999px: chip-scale */
  padding: 0 var(--s8) 0 var(--s4);
  min-height: 44px;
  font-family: inherit; font-size: var(--t-meta); font-weight: var(--w-semi);
  color: var(--slate-700);
  cursor: pointer;
  transition: border-color .15s, background-color .15s, color .15s;
}
.br-chip:hover { border-color: var(--navy-300); background-color: var(--navy-50); color: var(--navy-700); }
.br-chip:focus { border-color: var(--navy-400); }
/* "On" = narrowed to something other than the default. Without this a row of
   four chips reads as four active filters on a completely unfiltered page. */
.br-chip.is-on { border-color: var(--navy-700); color: var(--navy-700); background-color: var(--navy-50); }
/* Hidden by the country switch, not removed — the select must stay in the form
   so its value still posts when it IS relevant. */
.br-chip-wrap.is-hidden { display: none; }

.br-clear {
  display: inline-flex; align-items: center; gap: var(--s1);
  min-height: 44px; padding: 0 var(--s2);
  font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--navy-700);
}
.br-clear:hover { text-decoration: underline; text-underline-offset: 3px; }
.br-drop { position: relative; }
.br-drop > .pill { min-height: 44px; }
.br-menu {
  position: absolute; top: calc(100% + var(--s1)); left: 0; z-index: 30;
  min-width: 220px; background: #fff;
  border: 1px solid var(--slate-200); border-radius: var(--r-md);
  box-shadow: var(--shadow-pop);
  padding: var(--s1); display: none;
}
.br-drop.open .br-menu { display: block; }
.br-drop.br-right .br-menu { left: auto; right: 0; }
.br-menu button {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  width: 100%; text-align: left; border: none; background: transparent;
  font-family: inherit; font-size: var(--t-meta); font-weight: var(--w-med); color: var(--slate-700);
  padding: var(--s2) var(--s3); border-radius: var(--r-sm);
}
.br-menu button:hover { background: var(--navy-50); color: var(--navy-700); }
.br-menu button .cnt { font-size: var(--t-micro); color: var(--slate-400); font-weight: var(--w-semi); }
.br-menu button .tick { visibility: hidden; color: var(--emerald-600); }
.br-menu button.selected { color: var(--navy-700); font-weight: var(--w-bold); }
.br-menu button.selected .tick { visibility: visible; }
.pill .chev { transition: transform .15s; }
.br-drop.open > .pill .chev { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .pill .chev { transition: none; } }

/* ---- Result bar: sort + count -------------------------------------------
   The select is a CONTROL: --r-md, not a 999px capsule. */
.br-resultbar {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: var(--s2); margin-bottom: var(--s6);
}
.br-sort { display: flex; align-items: center; gap: var(--s2); font-size: var(--t-meta); color: var(--slate-500); }
.br-sort select {
  font-family: inherit; font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-800);
  background-color: #fff; border: 1px solid var(--slate-300); border-radius: var(--r-md);
  padding: var(--s2) var(--s8) var(--s2) var(--s3);
  min-height: 44px;
  appearance: none; -webkit-appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right var(--s3) center;
}
.br-sort select:focus { border-color: var(--navy-400); }
.br-count { font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-600); }

/* ---- Card grid -----------------------------------------------------------
   3-up at desktop (REDESIGN-PLAN D7). On the 1120px content box that gives
   ~357px cards, which carries a 3:2 photo comfortably; 2-up would halve the
   listings above the fold. */
.br-grid { display: grid; grid-template-columns: 1fr; gap: var(--s6); }
@media (min-width: 640px)  { .br-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .br-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ---- Pagination ----------------------------------------------------------
   Links, not pills: --r-md. */
.br-pagination { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--s2); margin: var(--s10) 0 0; }
.br-pagination a {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s1);
  min-width: 44px; min-height: 44px; padding: 0 var(--s3);
  border-radius: var(--r-md);
  background: #fff; border: 1px solid var(--slate-300);
  font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-700);
  transition: background-color .15s, border-color .15s, color .15s;
}
.br-pagination a:hover { border-color: var(--navy-300); color: var(--navy-700); background: var(--navy-50); }
.br-pagination a.current { background: var(--navy-700); border-color: var(--navy-700); color: #fff; }

/* ---- SEO block -----------------------------------------------------------
   Sits on the canvas behind a rail-anchored hairline, like every other
   run-on section — it was a white card with a shadow, which made a block of
   supporting prose the most elevated object on a page full of listings. */
.br-seo { margin-top: var(--s16); border-top: 1px solid var(--slate-200); padding-top: var(--s10); }
.br-seo h2 { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; line-height: 1.2; margin-bottom: var(--s4); }
.br-seo p { font-size: var(--t-body); line-height: 1.7; color: var(--slate-600); max-width: 72ch; }
.br-seo p + p { margin-top: var(--s3); }
.br-seo .extra { display: none; }
.br-seo.expanded .extra { display: block; }
.br-seo-toggle {
  margin-top: var(--s4); border: none; background: none; padding: 0;
  display: inline-flex; align-items: center; gap: var(--s1); min-height: 44px;
  font-family: inherit; font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--navy-700);
}
.br-seo-toggle:hover { text-decoration: underline; text-underline-offset: 3px; }
.br-seo.expanded .br-seo-toggle .chev { transform: rotate(180deg); }


/* ============================================================================
   8.3 MAP (.mv-*)
   ============================================================================
   The list panel's cards are .hcc-card--row (§6.1). What is genuinely
   map-only: the split shell, the segmented type filter, the price markers,
   the Leaflet popup skin, the mobile list/map toggle, the offline fallback.
   ============================================================================ */

.mv-shell {
  position: relative;
  z-index: 0;               /* isolate Leaflet's internal z-indexes below the sticky header */
  display: flex;
  /* The header's BORDER-BOX, not its bar: 72px here left the shell one pixel
     taller than the space below the header, so the map note's bottom edge sat
     a pixel under the fold. */
  height: calc(100vh - var(--header-h) - 1px);
  height: calc(100dvh - var(--header-h) - 1px);
  min-height: 480px;
  background: var(--slate-100);
}

/* ---- Left list panel ----------------------------------------------------- */
.mv-list { display: none; }
@media (min-width: 900px) {
  .mv-list {
    display: flex; flex-direction: column;
    width: 42%; min-width: 380px; max-width: 540px;
    background: var(--canvas);
    border-right: 1px solid var(--slate-200);
  }
}
@media (max-width: 899.98px) {
  /* z-index must clear Leaflet's internal panes (its controls sit at 1000) */
  .mv-list { position: absolute; inset: 0; z-index: 1200; background: var(--canvas); }
  .mv-shell.list-open .mv-list { display: flex; flex-direction: column; }
}

.mv-topbar {
  padding: var(--s3);
  border-bottom: 1px solid var(--slate-200);
  display: flex; flex-direction: column; gap: var(--s3);
  background: var(--canvas);
}
/* Segmented control — same grammar as the hero search toggle (§7), so the two
   places on the site that switch adtype look like the same control. */
.mv-seg { display: flex; background: var(--slate-100); border-radius: 9px; padding: 3px; gap: 2px; }
/* Segments are <a> in production and <button> in the mockup. Production makes
   each one a real URL so the filtered view is shareable and works with
   JavaScript off; the mockup had no server to link to. Both are styled. */
.mv-seg a,
.mv-seg button {
  flex: 1; border: none; background: transparent;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: inherit; font-size: var(--t-meta); font-weight: var(--w-mid); color: var(--slate-600);
  min-height: 40px; padding: 0 var(--s2);
  border-radius: var(--r-sm);
  transition: background-color .15s, color .15s;
  white-space: nowrap;
}
.mv-seg a:hover,
.mv-seg button:hover { color: var(--navy-700); }
.mv-seg a.active,
.mv-seg button.active { background: var(--navy-700); color: #fff; }

.mv-topbar-sub { display: flex; align-items: center; gap: var(--s2); position: relative; }

/* --- Map filters panel ----------------------------------------------------
   <details>/<summary>, so the panel opens with no JavaScript at all; JS only
   adds outside-click/Escape close and the country->province/state toggle.
   Anchored to .mv-topbar-sub (position:relative above). The selects reuse
   .br-chip so map filters and Browse chips can never drift apart visually. */
.mv-filters > summary { list-style: none; cursor: pointer; user-select: none; }
.mv-filters > summary::-webkit-details-marker { display: none; }
.mv-filters > summary.is-on,
.mv-filters[open] > summary { border-color: var(--navy-700); color: var(--navy-700); }
.mv-filters-panel {
  position: absolute; left: 0; top: calc(100% + var(--s2)); z-index: 500;
  width: min(320px, calc(100vw - var(--s6)));
  display: flex; flex-direction: column; gap: var(--s3);
  background: #fff; border: 1px solid var(--slate-200); border-radius: var(--r-md);
  box-shadow: var(--shadow-pop); padding: var(--s4);
}
.mv-f-field { display: flex; flex-direction: column; gap: var(--s1); }
.mv-f-field > span {
  font-size: var(--t-micro); font-weight: var(--w-semi);
  text-transform: uppercase; letter-spacing: .06em; color: var(--slate-500);
}
.mv-f-field .br-chip { width: 100%; }
.mv-filters-foot { display: flex; align-items: center; justify-content: space-between; padding-top: var(--s1); }
.mv-f-clear { font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-500); }
.mv-f-clear:hover { color: var(--navy-700); }
.mv-f-browse {
  display: inline-flex; align-items: center; gap: var(--s1);
  font-size: var(--t-micro); color: var(--slate-500);
  border-top: 1px solid var(--slate-200); padding-top: var(--s3);
}
.mv-f-browse:hover { color: var(--navy-700); }
.mv-count { font-size: var(--t-meta); color: var(--slate-500); flex: 1; }
.mv-count strong { color: var(--slate-900); font-weight: var(--w-hvy); }
.mv-sort { display: flex; align-items: center; gap: var(--s2); }
.mv-sort select {
  font-family: inherit; font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-700);
  border: 1px solid var(--slate-300); border-radius: var(--r-md);
  padding: var(--s2) var(--s6) var(--s2) var(--s3); min-height: 44px;
  background-color: #fff; outline: none; max-width: 170px;
  appearance: none; -webkit-appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right var(--s2) center;
}
.mv-sort select:focus { border-color: var(--navy-400); }
.mv-filter-pop {
  position: absolute; top: calc(100% + var(--s2)); left: 0; z-index: 30;
  background: #fff; border: 1px solid var(--slate-200);
  border-radius: var(--r-md); box-shadow: var(--shadow-pop);
  padding: var(--s4); width: 280px; display: none;
  font-size: var(--t-meta); color: var(--slate-600); line-height: 1.55;
}
.mv-filter-pop.open { display: block; }
.mv-filter-pop strong { color: var(--slate-900); display: block; margin-bottom: var(--s1); }
.mv-filter-pop a { color: var(--navy-700); font-weight: var(--w-semi); text-decoration: underline; text-underline-offset: 3px; }

.mv-cards {
  position: relative; flex: 1; overflow-y: auto;
  padding: var(--s3);
  display: flex; flex-direction: column; gap: var(--s2);
}
.mv-cards .hcc-card--row { flex-shrink: 0; }
.mv-cards .hcc-card--row.mv-hidden { display: none; }

/* ---- Map column ---------------------------------------------------------- */
.mv-map-wrap { flex: 1; min-width: 0; display: flex; flex-direction: column; position: relative; }
#mvMap { flex: 1; background: var(--slate-200); }
/* .mv-map-note now has ONE remaining use: the "no mapped listings" empty
   state inside the list rail. The privacy note that used to share this class
   lives on the map itself as .mv-privacy below. */
.mv-map-note {
  padding: var(--s2) var(--s4);
  font-size: var(--t-micro); color: var(--slate-500);
}
.mv-map-note a { color: var(--navy-700); font-weight: var(--w-semi); text-decoration: underline; text-underline-offset: 3px; }

/* The pin-privacy promise, as a chip ON the map (bottom-left; Leaflet's
   attribution owns bottom-right). REQUIRED content, quiet form: collapsed it
   is a labelled control, one click expands the full sentence. <details>, so
   no JS is involved. The panel opens UPWARD so it never leaves the map. */
.mv-privacy { position: absolute; left: var(--s3); bottom: var(--s3); z-index: 500; }
.mv-privacy > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; gap: var(--s1);
  padding: var(--s1) var(--s3);
  background: rgba(255,255,255,.92); border: 1px solid var(--slate-200);
  border-radius: 999px;                /* sanctioned 999px: chip-scale */
  font-size: var(--t-micro); font-weight: var(--w-semi); color: var(--slate-600);
  box-shadow: var(--shadow-pop);
}
.mv-privacy > summary::-webkit-details-marker { display: none; }
.mv-privacy > summary:hover,
.mv-privacy[open] > summary { color: var(--navy-700); border-color: var(--navy-300); }
.mv-privacy > p {
  position: absolute; left: 0; bottom: calc(100% + var(--s2));
  width: min(340px, calc(100vw - var(--s8)));
  background: #fff; border: 1px solid var(--slate-200); border-radius: var(--r-md);
  box-shadow: var(--shadow-pop); padding: var(--s3) var(--s4);
  font-size: var(--t-micro); color: var(--slate-600); line-height: 1.55;
}

/* ---- Price markers -------------------------------------------------------
   Sanctioned 999px use #3: chip-scale, and on a map a rounded price capsule is
   the established convention (rew.ca, Realtor.ca, Zillow all use it). The
   marker floats over tiles, so --shadow-pop is correct here. */
.mv-pin-wrap { background: transparent; border: none; }
.mv-pin {
  position: absolute; left: 0; top: 0;
  transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; gap: var(--s1);
  background: #fff; border: 1.5px solid var(--navy-700); color: var(--navy-700);
  font-family: var(--font); font-size: var(--t-micro); font-weight: var(--w-hvy);
  line-height: 1; letter-spacing: -.01em;
  padding: var(--s2) var(--s3); border-radius: 999px;
  box-shadow: var(--shadow-pop);
  white-space: nowrap; cursor: pointer;
  transition: transform .15s, background-color .15s, color .15s;
}
.mv-pin:hover, .mv-pin--hover { transform: translate(-50%, -50%) scale(1.1); }
.mv-pin--selected { background: var(--navy-700); color: #fff; }
/* Amber on the map is the same Featured signal it is everywhere else. */
.mv-pin--featured { border-color: var(--amber-300); background: var(--amber-50); color: var(--amber-800); }
.mv-pin--featured.mv-pin--selected { background: var(--amber-300); color: var(--navy-900); }
/* Region-precision pin: the listing's city could not be resolved and the pin
   sits on a province/state centroid. Dashed, so a viewer is not told a listing
   is precisely somewhere it is not. The popup says "approximate area" too —
   the visual difference alone would be a code nobody has been taught. */
.mv-pin--coarse { border-style: dashed; color: var(--slate-600); border-color: var(--slate-400); }
/* A single listing with no price used to label its pin "1", which reads as a
   broken cluster ("1 what?"). It renders as a plain dot instead — the popup
   already says "1 listing". Sized so the dot still meets the chip's border. */
.mv-pin--dot { width: 16px; height: 16px; padding: 0; background: var(--navy-700); }
.mv-pin--dot.mv-pin--selected { background: var(--navy-900); }
.mv-pin--dot.mv-pin--coarse { background: var(--slate-500); border-style: solid; }
@media (prefers-reduced-motion: reduce) {
  .mv-pin { transition: none; }
  .mv-pin:hover, .mv-pin--hover { transform: translate(-50%, -50%); }
}

/* ---- Leaflet's own controls ----------------------------------------------
   Leaflet ships a 4px radius and a black shadow on its zoom control, which is
   the only value on the page off the radius scale and the only pure-black
   shadow anywhere. Third-party CSS is still CSS the user sees. */
.leaflet-control-zoom { border-radius: var(--r-sm) !important; box-shadow: var(--shadow-pop) !important; border: none !important; }
.leaflet-control-zoom a {
  color: var(--slate-700) !important; border-bottom-color: var(--slate-200) !important;
  font-weight: var(--w-semi);
}
.leaflet-control-zoom a:hover { background: var(--navy-50) !important; color: var(--navy-700) !important; }
.leaflet-control-zoom a:first-child { border-radius: var(--r-sm) var(--r-sm) 0 0 !important; }
.leaflet-control-zoom a:last-child  { border-radius: 0 0 var(--r-sm) var(--r-sm) !important; }
.leaflet-control-attribution { font-family: var(--font); font-size: 10px; }

/* ---- Leaflet popup skin -------------------------------------------------- */
.mv-popup .leaflet-popup-content-wrapper { border-radius: var(--r-lg); padding: 0; overflow: hidden; box-shadow: var(--shadow-pop); }
.mv-popup .leaflet-popup-content { margin: 0; width: 240px !important; font-family: var(--font); line-height: 1.4; }
.mv-popup .leaflet-popup-close-button { color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.5); font-size: 20px; padding: var(--s1) var(--s2) 0 0; z-index: 5; }
.mv-pop { display: block; }
.mv-pop-photo { display: block; height: 130px; position: relative; overflow: hidden; }
.mv-pop-photo img { width: 100%; height: 100%; object-fit: cover; }
.mv-pop-body { display: block; padding: var(--s3); }
.mv-pop-body .badge { margin-bottom: var(--s1); }
.mv-pop-price { display: block; font-size: var(--t-body); font-weight: var(--w-hvy); color: var(--slate-900); letter-spacing: -.02em; }
.mv-pop-title { display: block; font-size: var(--t-micro); font-weight: var(--w-med); color: var(--slate-600); margin: var(--s1) 0 var(--s2); }
.mv-pop-link { display: inline-flex; align-items: center; gap: var(--s1); font-size: var(--t-micro); font-weight: var(--w-bold); color: var(--navy-700); }

/* ---- Mobile list/map toggle ---------------------------------------------
   A floating action control, so --r-md and the detached-UI shadow. It was a
   999px uppercase capsule, which is two anti-AI-checklist tells in one object. */
.mv-mobile-toggle {
  position: absolute; bottom: var(--s16); left: 50%;
  transform: translateX(-50%);
  z-index: 1300;              /* above the list overlay and Leaflet controls */
  display: inline-flex; align-items: center; gap: var(--s2);
  background: var(--navy-700); color: #fff; border: none;
  border-radius: var(--r-md); padding: 0 var(--s6); min-height: 48px;
  font-family: inherit; font-size: var(--t-meta); font-weight: var(--w-bold);
  box-shadow: var(--shadow-pop);
}
.mv-mobile-toggle:active { transform: translateX(-50%) scale(.97); }
@media (min-width: 900px) { .mv-mobile-toggle { display: none; } }

/* ---- Offline fallback ---------------------------------------------------- */
.mv-fallback {
  display: none; flex: 1; align-items: center; justify-content: center;
  padding: var(--s8) var(--s6); text-align: center;
  background-color: var(--canvas);
  background-image: linear-gradient(var(--slate-200) 1px, transparent 1px), linear-gradient(90deg, var(--slate-200) 1px, transparent 1px);
  background-size: 32px 32px;
}
.mv-fallback.show { display: flex; }
.mv-fallback-box {
  max-width: 400px; background: #fff;
  border: 1px solid var(--slate-300); border-radius: var(--r-lg);
  padding: var(--s8);
}
.mv-fallback-box h2 { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; }
.mv-fallback-box p { font-size: var(--t-meta); color: var(--slate-500); margin: var(--s2) 0 var(--s6); line-height: 1.6; }


/* ============================================================================
   8.4 DETAIL (.hcd-*)
   ============================================================================
   Namespace note: the plan called this block .dt-*; the existing POC already
   uses .hcd-*, so the existing prefix wins — renaming 300 attributes to match
   a planning placeholder buys nothing.

   Every .hcd-section used to be a white card with a shadow, which made blocks
   of supporting prose the most elevated objects on a page whose subject is a
   photograph. They are now run-on sections separated by rail-anchored
   hairlines, the same grammar the homepage uses between 01 and 02.
   ============================================================================ */

/* ---- Sticky anchor tabs --------------------------------------------------
   Sits directly under the sticky header. Border, not shadow. */
/* +1px for .site-header's bottom border, exactly as .hcc-subnav does in
   section 12 — at a bare var(--header-h) the tabs slide one pixel under the
   header and their top edge is clipped. */
.hcd-tabs { background: var(--canvas); border-bottom: 1px solid var(--slate-200); position: sticky; top: calc(var(--header-h) + 1px); z-index: 40; }
.hcd-tabs .inner { display: flex; align-items: center; gap: 2px; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.hcd-tabs a {
  font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-600);
  padding: var(--s4) var(--s3) var(--s3); border-bottom: 2px solid transparent;
  white-space: nowrap; transition: color .15s;
}
.hcd-tabs a:hover { color: var(--navy-700); }
.hcd-tabs a.active { color: var(--navy-700); border-bottom-color: var(--navy-700); }
.hcd-tabs .lid { margin-left: auto; font-size: var(--t-micro); color: var(--slate-500); display: none; white-space: nowrap; padding-left: var(--s4); }
@media (min-width: 768px) { .hcd-tabs .lid { display: inline; } }

/* ---- Gallery hero -------------------------------------------------------- */
.hcd-gallery { display: grid; grid-template-columns: 1fr; gap: var(--s2); margin-top: var(--s3); }
@media (min-width: 768px) { .hcd-gallery { grid-template-columns: 2fr 1fr; } }
.hcd-gal-main {
  position: relative; border-radius: var(--r-lg); overflow: hidden;
  aspect-ratio: 16/10; background: var(--slate-100); cursor: pointer;
}
.hcd-gal-side { display: none; flex-direction: column; gap: var(--s2); }
@media (min-width: 768px) { .hcd-gal-side { display: flex; } }
.hcd-gal-side .ph {
  position: relative; flex: 1; min-height: 0;
  border-radius: var(--r-lg); overflow: hidden; background: var(--slate-100); cursor: pointer;
}
/* Absolute, not in-flow — the same trap as the row-card thumbnail. Left in
   flow, `height: 100%` resolves against a .ph whose own height comes from
   `flex: 1` against an indefinite column, so it falls back to `auto` and the
   image's INTRINSIC ratio takes over. Two 1200x800 sources then measured
   247px each and the side column grew to 502px against the main's declared
   16/10 = 463px — so the side column, not the hero, set the row height and the
   main photo sat in a 40px well. Absolute positioning lets .hcd-gal-main's
   aspect-ratio govern the row, which is the whole point of declaring it. */
.hcd-gallery img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Same count treatment as .hcc-card-count, so the gallery affordance reads
   identically on the card that brought you here and on the page itself. */
.hcd-gal-count {
  position: absolute; left: var(--s3); bottom: var(--s3);
  display: inline-flex; align-items: center; gap: var(--s1);
  background: rgba(3,15,33,.68); color: #fff;
  font-size: var(--t-micro); font-weight: var(--w-semi);
  padding: var(--s1) var(--s2); border-radius: var(--r-sm);
  pointer-events: none;
}
.hcd-gal-actions { position: absolute; right: var(--s3); bottom: var(--s3); display: flex; gap: var(--s2); }
.hcd-gal-btn {
  display: inline-flex; align-items: center; gap: var(--s1);
  background: rgba(255,255,255,.95); border: none; color: var(--slate-800);
  font-family: inherit; font-size: var(--t-micro); font-weight: var(--w-bold);
  padding: 0 var(--s3); min-height: 40px; border-radius: var(--r-md);
  transition: background-color .15s;
}
.hcd-gal-btn:hover { background: #fff; }

/* ---- Listing header row -------------------------------------------------
   Price is the largest element on the page — rew.ca's own treatment. The H1 is
   the TITLE and sits a step below it; visual size is not document outline. */
.hcd-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--s4) var(--s6); padding: var(--s6) 0 var(--s2); }
.hcd-head-main { min-width: 0; flex: 1 1 480px; display: flex; flex-direction: column; gap: var(--s3); }
.hcd-price {
  font-size: var(--t-stmt); font-weight: var(--w-hvy); letter-spacing: -.03em;
  color: var(--slate-900); line-height: 1.05; font-variant-numeric: tabular-nums;
}
.hcd-price .freq { font-size: var(--t-lede); font-weight: var(--w-med); color: var(--slate-500); letter-spacing: 0; margin-left: var(--s1); }
@media (max-width: 767px) { .hcd-price { font-size: 33px; } }
.hcd-title { font-size: var(--t-h2); font-weight: var(--w-bold); letter-spacing: -.025em; line-height: 1.25; color: var(--slate-800); }
@media (max-width: 767px) { .hcd-title { font-size: 22px; } }
.hcd-chips { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }
.hcd-meta { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s4); font-size: var(--t-meta); color: var(--slate-500); }
.hcd-meta span { display: inline-flex; align-items: center; gap: var(--s1); }
.hcd-head-actions { display: flex; gap: var(--s2); flex-shrink: 0; padding-top: var(--s1); }
/* Sentence case, not uppercase: a row of tiny uppercase micro-buttons is one of
   the "AI-generated" tells the redesign exists to remove. */
.hcd-act {
  display: inline-flex; align-items: center; gap: var(--s2);
  background: #fff; border: 1px solid var(--slate-300); border-radius: var(--r-md);
  padding: 0 var(--s4); min-height: 44px;
  font-family: inherit; font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-700);
  transition: background-color .15s, border-color .15s, color .15s;
}
.hcd-act:hover { border-color: var(--navy-300); color: var(--navy-700); background: var(--navy-50); }
.hcd-act.on { color: var(--red-500); border-color: color-mix(in srgb, var(--red-500) 35%, #fff); background: color-mix(in srgb, var(--red-500) 6%, #fff); }
.hcd-act.on svg { fill: currentColor; }

/* ---- Layout -------------------------------------------------------------- */
.hcd-layout { display: grid; grid-template-columns: 1fr; gap: var(--s6); align-items: start; padding-bottom: var(--s12); }
@media (min-width: 1024px) { .hcd-layout { grid-template-columns: minmax(0, 1fr) 350px; gap: var(--s10); } }
.hcd-main { display: flex; flex-direction: column; min-width: 0; }
/* Run-on sections on the canvas, separated by hairlines — not stacked cards. */
.hcd-section { padding: var(--s10) 0; border-top: 1px solid var(--slate-200); scroll-margin-top: 150px; }
.hcd-section:first-child { border-top: none; padding-top: var(--s6); }
.hcd-section > h2 { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; line-height: 1.2; margin-bottom: var(--s6); }
.hcd-prose { font-size: var(--t-body); line-height: 1.75; color: var(--slate-600); display: flex; flex-direction: column; gap: var(--s3); max-width: 68ch; }

/* ---- Facts tables -------------------------------------------------------- */
.hcd-facts { display: grid; grid-template-columns: 1fr; column-gap: var(--s10); }
@media (min-width: 768px) { .hcd-facts { grid-template-columns: 1fr 1fr; } }
.hcd-fgroup h3 {
  font-size: var(--t-micro); font-weight: var(--w-bold); text-transform: uppercase;
  letter-spacing: .06em; color: var(--slate-500); margin: var(--s6) 0 var(--s1);
}
/* `:first-child` on the GROUP zeroed the top margin only in the left column,
   so the right column's first heading sat 24px lower and the two fact tables
   started on different baselines. The rule wants "the first heading in each
   column", which is `> h3:first-child`. */
.hcd-fgroup > h3:first-child { margin-top: 0; }
.hcd-frow {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s6);
  padding: var(--s3) 0; border-bottom: 1px solid var(--slate-200); font-size: var(--t-meta);
}
.hcd-frow .k { color: var(--slate-500); flex-shrink: 0; }
/* overflow-wrap:anywhere, not break-word — the 32-char Listing ID is one
   unbreakable token, and only `anywhere` reduces its min-content width, so
   only `anywhere` stops it pushing 58px of page scroll at 320px. Same fix
   family as the bare email address in .hcc-prose (B5). */
.hcd-frow .v { font-weight: var(--w-semi); color: var(--slate-800); text-align: right; min-width: 0; overflow-wrap: anywhere; }

/* ---- Seller ----------------------------------------------------------------
   No initial-letter avatar. header-new.php already dropped that device for a
   real reason: account names derive from the email local part, so a single
   letter reads random. The name plus the verified tick carries this. */
.hcd-seller { display: flex; flex-direction: column; gap: var(--s2); }
.hcd-seller-name { font-size: var(--t-lede); font-weight: var(--w-bold); color: var(--slate-900); display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.badge-verified {
  display: inline-block; font-size: 10px; font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: .04em;
  padding: 3px var(--s2); border-radius: var(--r-sm);
  color: var(--emerald-700); background: var(--emerald-50);
  border: 1px solid color-mix(in srgb, var(--emerald-600) 30%, #fff);
}
.hcd-seller-meta { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s6); font-size: var(--t-meta); color: var(--slate-500); }

/* ---- Featured upsell -----------------------------------------------------
   Amber is legitimate here — this block sells the paid placement, so it is
   Featured signalling at the moment of sale. But the BUTTON is navy: amber is
   a signal, never an interactive colour (COLOUR law). An amber-300 fill on a
   call to action was the one place amber had escaped its meaning. */
.hcd-upsell {
  background: var(--amber-50); border: 1px solid var(--amber-200); border-radius: var(--r-lg);
  padding: var(--s6); display: flex; flex-wrap: wrap;
  align-items: center; justify-content: space-between; gap: var(--s4) var(--s6);
  margin-top: var(--s10);
}
.hcd-upsell h3 { font-size: var(--t-body); font-weight: var(--w-bold); color: var(--amber-800); margin-bottom: var(--s1); }
.hcd-upsell p { font-size: var(--t-meta); color: var(--amber-800); opacity: .88; max-width: 52ch; }

/* ---- Location ------------------------------------------------------------ */
.hcd-map { border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--slate-200); background: var(--navy-50); margin-bottom: var(--s4); }
.hcd-map svg, .hcd-map img { width: 100%; height: auto; display: block; }
.hcd-map-note { font-size: var(--t-meta); color: var(--slate-500); line-height: 1.6; max-width: 62ch; }

/* ---- Insights ------------------------------------------------------------ */
.hcd-insights { display: grid; grid-template-columns: 1fr; gap: var(--s3); }
@media (min-width: 640px) { .hcd-insights { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.hcd-stat { border: 1px solid var(--slate-200); border-radius: var(--r-md); padding: var(--s4); display: flex; flex-direction: column; gap: var(--s1); background: #fff; }
.hcd-stat .n { font-size: var(--t-price); font-weight: var(--w-hvy); letter-spacing: -.02em; color: var(--navy-700); font-variant-numeric: tabular-nums; }
.hcd-stat .l { font-size: var(--t-micro); color: var(--slate-500); line-height: 1.45; }

/* ---- Sticky contact sidebar ---------------------------------------------
   The one place on the page that IS a card: it floats beside scrolling
   content and has to read as a distinct object. Border, not shadow. */
.hcd-side { display: flex; flex-direction: column; gap: var(--s4); }
/* Clears two sticky layers, not one: the header (+1px border) and the 52px
   .hcd-tabs bar beneath it, then --s6 of breathing room. The 52px is
   .hcd-tabs' intrinsic height — if its padding or type changes, this moves
   with it. */
@media (min-width: 1024px) { .hcd-side { position: sticky; top: calc(var(--header-h) + 1px + 52px + var(--s6)); } }
.hcd-cta-card {
  background: #fff; border: 1px solid var(--slate-300); border-radius: var(--r-lg);
  padding: var(--s6); display: flex; flex-direction: column; gap: var(--s4);
}
.hcd-cta-price { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; color: var(--slate-900); font-variant-numeric: tabular-nums; }
.hcd-cta-price .sub { display: block; font-size: var(--t-micro); font-weight: var(--w-semi); color: var(--slate-500); text-transform: uppercase; letter-spacing: .05em; margin-top: 2px; }
.hcd-cta-row { display: flex; gap: var(--s2); }
.hcd-cta-row .hcc-btn { flex: 1; padding: 0 var(--s3); }
.hcd-signin-note { font-size: var(--t-micro); color: var(--slate-500); line-height: 1.6; text-align: center; }
.hcd-signin-note a { color: var(--navy-700); font-weight: var(--w-semi); text-decoration: underline; text-underline-offset: 2px; }
.hcd-safety {
  background: var(--navy-50); border: 1px solid var(--navy-100); border-radius: var(--r-md);
  padding: var(--s4); display: flex; gap: var(--s3);
  font-size: var(--t-micro); line-height: 1.6; color: var(--navy-700);
}
.hcd-safety svg { flex-shrink: 0; margin-top: 1px; }
.hcd-safety strong { display: block; margin-bottom: 2px; }

/* ---- Similar listings ---------------------------------------------------- */
.hcd-similar { padding: var(--s10) 0 var(--s16); border-top: 1px solid var(--slate-200); }
.hcd-similar-grid { display: grid; grid-template-columns: 1fr; gap: var(--s6); }
@media (min-width: 640px) { .hcd-similar-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 960px) { .hcd-similar-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ---- Lightbox ------------------------------------------------------------
   Round icon buttons — sanctioned 999px (a). */
.hcd-lightbox { position: fixed; inset: 0; background: rgba(3,15,33,.92); z-index: 90; display: none; align-items: center; justify-content: center; padding: var(--s6); }
.hcd-lightbox.open { display: flex; }
.hcd-lb-figure { width: min(920px, 100%); position: relative; }
.hcd-lb-stage { border-radius: var(--r-lg); overflow: hidden; background: var(--slate-100); aspect-ratio: 16/10; position: relative; }
.hcd-lb-stage img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hcd-lb-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); color: #fff; margin-top: var(--s3); font-size: var(--t-meta); }
.hcd-lb-bar .cap { font-weight: var(--w-semi); }
.hcd-lb-bar .cnt { color: rgba(255,255,255,.7); font-size: var(--t-meta); font-variant-numeric: tabular-nums; }
.hcd-lb-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 44px; height: 44px; border-radius: 999px; border: none;
  background: rgba(255,255,255,.92); color: var(--slate-800);
  display: flex; align-items: center; justify-content: center;
  transition: background-color .15s;
}
.hcd-lb-nav:hover { background: #fff; }
.hcd-lb-prev { left: var(--s2); }
.hcd-lb-next { right: var(--s2); }
@media (min-width: 1080px) { .hcd-lb-prev { left: -60px; } .hcd-lb-next { right: -60px; } }
.hcd-lb-close {
  position: absolute; top: calc(var(--s3) * -1); right: 0; transform: translateY(-100%);
  width: 40px; height: 40px; border-radius: 999px; border: none;
  background: rgba(255,255,255,.18); color: #fff;
  display: flex; align-items: center; justify-content: center;
  transition: background-color .15s;
}
.hcd-lb-close:hover { background: rgba(255,255,255,.32); }
.hcd-lightbox :focus-visible { outline-color: #fff; }

/* ---- Toast ---------------------------------------------------------------
   A message surface, not a chip: --r-md. */
.hcd-toast {
  position: fixed; bottom: var(--s6); left: 50%;
  transform: translateX(-50%) translateY(10px);
  background: var(--slate-900); color: #fff;
  font-size: var(--t-meta); font-weight: var(--w-semi);
  padding: var(--s3) var(--s6); border-radius: var(--r-md);
  opacity: 0; transition: opacity .25s, transform .25s;
  z-index: 100; pointer-events: none;
  box-shadow: var(--shadow-pop); white-space: nowrap;
}
.hcd-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
@media (prefers-reduced-motion: reduce) { .hcd-toast { transition: opacity .25s; } }


/* ============================================================================
   8.5 AUTH (.hcc-auth-*)
   ============================================================================
   One centred, single-column form card, shared by login, register, the
   register confirmation, forgot-password and password-reset. Those five pages
   previously each carried their own copy of the same Tailwind utility stack,
   which is how they drifted apart on input height, label weight and alert
   colour.
   ============================================================================ */

.hcc-auth {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  padding: var(--s16) var(--s6);
}
.hcc-auth-inner { width: 100%; max-width: 440px; }
/* Wider variant for the register form, which has enough fields that 440px
   forces an uncomfortably tall column. */
.hcc-auth-inner.is-wide { max-width: 560px; }

/* A card, because it is a distinct object floating on the canvas — but a
   BORDERED one. The old version carried `shadow-xl shadow-slate-200/60`, which
   made a login box the most elevated thing on the entire site. */
.hcc-auth-card {
  background: #fff;
  border: 1px solid var(--slate-300);
  border-radius: var(--r-lg);
  padding: var(--s10);
}
@media (max-width: 479px) { .hcc-auth-card { padding: var(--s6); } }

.hcc-auth-head { text-align: center; margin-bottom: var(--s8); }
.hcc-auth-head .chip {
  display: inline-flex; background: #fff;
  border: 1px solid var(--slate-200); border-radius: var(--r-sm);
  padding: var(--s2) var(--s3); margin-bottom: var(--s4);
}
.hcc-auth-head .chip img { height: 30px; width: auto; }
.hcc-auth-head h1 { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; line-height: 1.2; }
.hcc-auth-head p { margin-top: var(--s2); font-size: var(--t-meta); color: var(--slate-600); line-height: 1.6; }

.hcc-auth-form { display: flex; flex-direction: column; gap: var(--s6); }

.hcc-field { display: flex; flex-direction: column; gap: var(--s2); }
/* Wraps: on a 320px phone the description field's head carries a label, an
   autosave pill and two AI buttons, which is 16px wider than the viewport
   on one line. */
.hcc-field-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s2) var(--s3); }
.hcc-field-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.hcc-field label {
  font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-700);
}
.hcc-field .req { color: var(--red-500); }
.hcc-field .hint { font-size: var(--t-micro); color: var(--slate-500); line-height: 1.5; }
.hcc-field-head a { font-size: var(--t-micro); font-weight: var(--w-semi); color: var(--navy-700); }
.hcc-field-head a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* font-size is --t-body (16px) deliberately: iOS zooms the viewport on focus
   for anything smaller, which on a login form reads as the page breaking. */
.hcc-input,
.hcc-auth-form select,
.hcc-auth-form textarea,
.hcc-form select,
.hcc-form textarea {
  width: 100%;
  border: 1px solid var(--slate-300); border-radius: var(--r-md);
  padding: 0 var(--s4); min-height: 48px;
  font-family: inherit; font-size: var(--t-body); color: var(--slate-900);
  background: #fff;
  transition: border-color .15s;
}
.hcc-auth-form textarea, .hcc-form textarea { padding: var(--s3) var(--s4); min-height: 120px; line-height: 1.6; }
.hcc-input::placeholder { color: var(--slate-400); }
.hcc-input:focus, .hcc-auth-form select:focus, .hcc-auth-form textarea:focus,
.hcc-form select:focus, .hcc-form textarea:focus { border-color: var(--navy-400); }
/* No `outline: none` — the border change is decoration and the global
   :focus-visible ring (§2.1) does the accessibility work. Killing the outline
   here is how the newsletter input ended up with no focus indicator at all. */

.hcc-auth-form .hcc-btn { width: 100%; }

.hcc-auth-foot {
  margin-top: var(--s6); text-align: center;
  font-size: var(--t-meta); color: var(--slate-600); line-height: 1.7;
}
.hcc-auth-foot a { color: var(--navy-700); font-weight: var(--w-semi); }
.hcc-auth-foot a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* ---- Alerts --------------------------------------------------------------
   Tints are mixed from the palette rather than hard-coded.

   NOTE THE MISSING ONE: there is no amber alert. The old login page used
   `bg-amber-50` for its "you are not logged in" notice, which breaks the
   COLOUR law — amber means somebody paid, and a session-expiry notice is
   informational. That state now uses the navy informational tint. */
.hcc-alert {
  border-radius: var(--r-md); padding: var(--s3) var(--s4);
  font-size: var(--t-meta); line-height: 1.6;
}
.hcc-alert strong { font-weight: var(--w-bold); }
.hcc-alert--err {
  color: var(--red-700);
  background: color-mix(in srgb, var(--red-500) 8%, #fff);
  border: 1px solid color-mix(in srgb, var(--red-500) 35%, #fff);
}
.hcc-alert--ok {
  color: var(--emerald-700); background: var(--emerald-50);
  border: 1px solid color-mix(in srgb, var(--emerald-600) 35%, #fff);
}
.hcc-alert--info {
  color: var(--navy-700); background: var(--navy-50);
  border: 1px solid var(--navy-100);
}

/* ---- Auth sub-components ------------------------------------------------- */

/* Two fields side by side (first/last name). Collapses early: two 200px inputs
   are worse than two full-width ones the moment the card narrows. */
.hcc-field-row { display: grid; grid-template-columns: 1fr; gap: var(--s6); }
@media (min-width: 520px) { .hcc-field-row { grid-template-columns: 1fr 1fr; } }

/* The register page's "a free account lets you" list. Was a dark two-panel
   split; folded into the card so all five auth pages share one shape. */
.hcc-auth-perks {
  list-style: none; padding: 0; margin: 0 0 var(--s8);
  display: flex; flex-direction: column; gap: var(--s2);
  font-size: var(--t-meta); color: var(--slate-600); line-height: 1.6;
}
.hcc-auth-perks li { position: relative; padding-left: var(--s6); }
/* A tick drawn in CSS rather than an inline SVG per item — three identical
   SVGs in the markup is three copies of the same thing to keep in sync. */
.hcc-auth-perks li::before {
  content: ""; position: absolute; left: 0; top: .45em;
  width: 6px; height: 10px;
  border: solid var(--emerald-600); border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Checkbox row. The whole block is the <label>, so the text is part of the hit
   target — a 20px box alone is under the 44px touch floor. */
.hcc-check {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s4); cursor: pointer;
  border: 1px solid var(--slate-300); border-radius: var(--r-md);
  font-size: var(--t-meta); color: var(--slate-600); line-height: 1.6;
  transition: border-color .15s, background-color .15s;
}
.hcc-check:hover { border-color: var(--navy-300); background: var(--navy-50); }
.hcc-check input[type="checkbox"],
.hcc-check input[type="radio"] {
  width: 18px; height: 18px; margin: 2px 0 0; flex-shrink: 0;
  accent-color: var(--navy-700);   /* native control, brand-tinted */
}
/* Radios in this block form a choose-one stack, so the selected one gets the
   same treatment as .hcc-radio's chip: a checkbox is independent and needs no
   such emphasis, which is why only the radio variant carries it. */
.hcc-check:has(input[type="radio"]:checked) { border-color: var(--navy-700); background: var(--navy-50); }
.hcc-check strong { display: block; font-weight: var(--w-semi); color: var(--slate-900); }
/* :has() so the ring lands on the whole row, matching the card-focus pattern
   in §6. Self-gating — engines without it keep the input's own ring. */
.hcc-check:has(input:focus-visible) { outline: 2px solid var(--navy-700); outline-offset: 3px; }
.hcc-check:has(input:focus-visible) input:focus-visible { outline: none; }

/* Success mark for the registration confirmation. Emerald, which the COLOUR
   law reserves for verification and success — this is the one place on an auth
   page it appears. Round because it is an icon badge, not a surface. */
.hcc-auth-tick {
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; border-radius: 999px;
  background: var(--emerald-50); color: var(--emerald-600);
  border: 1px solid color-mix(in srgb, var(--emerald-600) 25%, #fff);
  margin-bottom: var(--s4);
}

/* ---- 3.4 Dashboard sub-nav ------------------------------------------------
   The advertiser area used to ship its OWN white header, duplicating the
   account links the navy header already carries in its dropdown — two headers
   to keep in sync, which is the same drift that split the five auth pages.
   It now uses the shared header plus this second-level bar.

   Structurally the same object as .hcd-tabs (§8.4) and it sits at the same
   sticky offset; they are kept separate because this one carries count badges
   and links to other PAGES, while .hcd-tabs are in-page anchors driven by an
   IntersectionObserver. Merging them would mean one component with two
   behaviours. */
.hcc-subnav {
  background: #fff;
  border-bottom: 1px solid var(--slate-200);
  /* +1px, not a bare var(--header-h): .site-header's .bar is --header-h tall
     PLUS a 1px bottom border, so without it the subnav slides one pixel under
     the header and its own top edge is clipped. The bar height is constant at
     every breakpoint (only its gap changes), so a fixed offset is safe. */
  position: sticky; top: calc(var(--header-h) + 1px); z-index: 40;
}
.hcc-subnav .inner {
  display: flex; align-items: center; gap: 2px;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
}
.hcc-subnav a {
  display: inline-flex; align-items: center; gap: var(--s2);
  font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-600);
  padding: var(--s4) var(--s3) var(--s3);
  border-bottom: 2px solid transparent;
  white-space: nowrap; transition: color .15s;
}
.hcc-subnav a:hover { color: var(--navy-700); }
.hcc-subnav a.active { color: var(--navy-700); border-bottom-color: var(--navy-700); }
/* Pushes the trailing action to the right edge of the bar. */
.hcc-subnav .spacer { flex: 1; min-width: var(--s4); }
.hcc-subnav .cta {
  border-bottom: 0; color: var(--navy-700);
}
.hcc-subnav .cta:hover { text-decoration: underline; text-underline-offset: 3px; }

/* Count badge — red, because it is an unattended-work signal, not a paid
   placement. Round: chip-scale, one of the sanctioned 999px uses. */
.hcc-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 999px;
  background: var(--red-500); color: #fff;
  font-size: var(--t-micro); font-weight: var(--w-bold); line-height: 1;
}


/* ============================================================================
   8.6 DASHBOARD (.hcc-row, .hcc-status, .hcc-panel)
   ============================================================================ */

/* ---- Status pill ----------------------------------------------------------
   Listing lifecycle state. The old markup used SIX ad-hoc colours including
   `amber` for "Pending Approval" and an `orange` that is not in the palette at
   all. Amber means SOMEBODY PAID — using it for a moderation queue makes a
   listing awaiting review look like a Featured one.

   Four tints, chosen by what the advertiser has to DO, not by how many states
   exist. The LABEL carries the distinction; the colour carries the urgency:
     neutral  draft, paused      nothing is wrong, nothing is live
     info     pending approval   in the system, waiting on us
     ok       active             live
     alert    needs update, expired   waiting on YOU */
.hcc-status {
  display: inline-flex; align-items: center; gap: var(--s2);
  font-size: var(--t-micro); font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: .04em;
  padding: 3px var(--s2); border-radius: var(--r-sm);
  white-space: nowrap;
}
/* No leading dot. Tint, label and border already say the same thing three
   ways; a fourth would also be the only 999px shape on the page that is not
   a chip, a round icon button or a map marker. */
.hcc-status--neutral { color: var(--slate-600); background: var(--slate-100); border: 1px solid var(--slate-200); }
.hcc-status--info    { color: var(--navy-700); background: var(--navy-50);  border: 1px solid var(--navy-100); }
.hcc-status--ok      { color: var(--emerald-700); background: var(--emerald-50); border: 1px solid color-mix(in srgb, var(--emerald-600) 25%, #fff); }
.hcc-status--alert   { color: var(--red-700); background: color-mix(in srgb, var(--red-500) 8%, #fff); border: 1px solid color-mix(in srgb, var(--red-500) 30%, #fff); }

/* ---- Listing row ----------------------------------------------------------
   The dashboard's own object: thumbnail + details + actions. Related to
   .hcc-card--row (§6.1) but not the same thing — that one is a public listing
   teaser, this one is a management row with lifecycle state and controls, and
   collapsing them would give one component two jobs. */
.hcc-row {
  background: #fff; border: 1px solid var(--slate-300);
  border-radius: var(--r-lg); padding: var(--s4);
  display: flex; flex-direction: column; gap: var(--s4);
}
.hcc-row + .hcc-row { margin-top: var(--s4); }
.hcc-row-top { display: flex; flex-direction: column; gap: var(--s4); }
@media (min-width: 640px) { .hcc-row-top { flex-direction: row; } }
.hcc-row-thumb {
  display: block; flex-shrink: 0; overflow: hidden;
  border-radius: var(--r-sm); background: var(--slate-100);
  width: 100%; aspect-ratio: 3/2;
  /* Flex items stretch by default, and a stretched cross-size beats
     aspect-ratio — the thumb rendered 132x109 (1.22) instead of 132x88.
     Same family as the height:100% bugs on the map rows and the detail
     gallery: a ratio only holds when nothing else is setting the height. */
  align-self: flex-start;
}
@media (min-width: 640px) { .hcc-row-thumb { width: 132px; aspect-ratio: 3/2; } }
.hcc-row-thumb img { width: 100%; height: 100%; object-fit: cover; }
.hcc-row-thumb .empty { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; color: var(--slate-400); }
.hcc-row-body { flex: 1; min-width: 0; }
.hcc-row-body h3 { font-size: var(--t-body); font-weight: var(--w-semi); line-height: 1.35; margin: var(--s2) 0 var(--s1); }
.hcc-row-body h3 a:hover { text-decoration: underline; text-underline-offset: 3px; }
.hcc-row-crumb { font-size: var(--t-micro); color: var(--slate-500); line-height: 1.5; }
.hcc-row-meta {
  display: flex; flex-wrap: wrap; gap: var(--s1) var(--s4);
  margin-top: var(--s3); font-size: var(--t-micro); color: var(--slate-500);
}
.hcc-row-meta .is-alert { color: var(--red-700); font-weight: var(--w-semi); }
.hcc-row-actions {
  display: flex; flex-wrap: wrap; gap: var(--s2);
  padding-top: var(--s4); border-top: 1px solid var(--slate-200);
}
.hcc-row-actions form { margin: 0; }
/* Compact action button. Not .hcc-btn--sm: these sit four-across in a row and
   need to stay on one line on a phone. */
.hcc-row-actions .act {
  display: inline-flex; align-items: center; gap: var(--s1);
  min-height: 40px; padding: 0 var(--s3);
  border: 1px solid var(--slate-300); border-radius: var(--r-md);
  background: #fff; font-family: inherit;
  font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-700);
  white-space: nowrap; transition: background-color .15s, border-color .15s, color .15s;
}
.hcc-row-actions .act:hover { border-color: var(--navy-300); background: var(--navy-50); color: var(--navy-700); }
.hcc-row-actions .act.is-primary { background: var(--navy-700); border-color: var(--navy-700); color: #fff; }
.hcc-row-actions .act.is-primary:hover { background: var(--navy-800); border-color: var(--navy-800); color: #fff; }
.hcc-row-actions .act.is-danger:hover { border-color: color-mix(in srgb, var(--red-500) 40%, #fff); background: color-mix(in srgb, var(--red-500) 6%, #fff); color: var(--red-700); }

/* ---- Inline panel (moderator notes, callouts) ---------------------------- */
.hcc-panel { border-radius: var(--r-md); padding: var(--s4); font-size: var(--t-meta); line-height: 1.6; }
.hcc-panel strong { display: block; font-weight: var(--w-bold); margin-bottom: var(--s1); }
.hcc-panel .body { white-space: pre-wrap; }
.hcc-panel--alert { color: var(--red-700); background: color-mix(in srgb, var(--red-500) 6%, #fff); border: 1px solid color-mix(in srgb, var(--red-500) 28%, #fff); }
.hcc-panel--info  { color: var(--navy-700); background: var(--navy-50); border: 1px solid var(--navy-100); }
.hcc-panel--ok    { color: var(--emerald-700); background: var(--emerald-50); border: 1px solid color-mix(in srgb, var(--emerald-600) 30%, #fff); }

/* ---- Status filter tabs -------------------------------------------------- */
.hcc-filters-row { display: flex; flex-wrap: wrap; gap: var(--s2); margin-bottom: var(--s6); }
.hcc-filters-row a { min-height: 44px; }
.hcc-filters-row .n { font-weight: var(--w-bold); opacity: .7; }

/* ---- Page head ----------------------------------------------------------- */
.hcc-pagehead {
  display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between;
  gap: var(--s4); margin-bottom: var(--s8);
}
.hcc-pagehead h1 { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; line-height: 1.2; }
.hcc-pagehead p { margin-top: var(--s2); font-size: var(--t-meta); color: var(--slate-600); }
.hcc-main { padding: var(--s10) 0 var(--s16); }

/* Narrower measures for form pages. A form wants ~65ch, not 1200px. The
   dashboard list keeps the full container so it lines up with .hcc-subnav
   above it — mismatched maxima put the bar's first link 60px left of the
   page heading, which reads as a broken header rather than a choice. */
.hcc-container--narrow { max-width: 680px; }
.hcc-container--tight  { max-width: 560px; }

/* ---- Filter chip ----------------------------------------------------------
   The dashboard status tabs, and later the messages/favourites filters. Same
   affordance as browse's `.br-chip`, which is page-local because it wraps a
   native <select>; this one wraps a link. */
.hcc-chip {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 44px; padding: 0 var(--s4);
  border: 1px solid var(--slate-300); border-radius: 999px;
  background: #fff; font-size: var(--t-meta); font-weight: var(--w-semi);
  color: var(--slate-700); white-space: nowrap;
  transition: background-color .15s, border-color .15s, color .15s;
}
.hcc-chip:hover { border-color: var(--navy-300); background: var(--navy-50); color: var(--navy-700); }
.hcc-chip[aria-current="page"] {
  background: var(--navy-700); border-color: var(--navy-700); color: #fff;
}
.hcc-chip[aria-current="page"] .n { opacity: .8; }

/* ---- Empty state ----------------------------------------------------------
   Shared by every list surface (ads, favourites, messages). Deliberately not
   an illustration or a gradient-filled icon tile: an empty list is a normal
   state, not an event, and dressing it up makes it read as an error. */
.hcc-empty {
  background: #fff; border: 1px solid var(--slate-300); border-radius: var(--r-lg);
  padding: var(--s12) var(--s6); text-align: center;
}
@media (min-width: 640px) { .hcc-empty { padding: var(--s16) var(--s10); } }
.hcc-empty > svg { color: var(--slate-400); margin-bottom: var(--s4); }
/* Direct child only. As a descendant selector this also hit the check
   icon inside .hcc-auth-tick when the confirmation pages reuse this
   shape — greying the emerald tick and knocking it off-centre inside
   its own circle. */
.hcc-empty > .hcc-auth-tick { margin-bottom: var(--s4); }
.hcc-empty h2 { font-size: var(--t-lede); font-weight: var(--w-bold); letter-spacing: -.02em; }
.hcc-empty p { margin: var(--s2) auto 0; max-width: 44ch; font-size: var(--t-meta); color: var(--slate-600); line-height: 1.6; }
.hcc-empty .hcc-btn { margin-top: var(--s6); }

/* ---- Renewal tiers (expired listings) ------------------------------------ */
.hcc-renew { margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--slate-200); }
.hcc-renew > summary {
  cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 44px; font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--navy-700);
}
.hcc-renew > summary::-webkit-details-marker { display: none; }
.hcc-renew > summary:hover { text-decoration: underline; text-underline-offset: 3px; }
.hcc-renew-grid { display: grid; grid-template-columns: 1fr; gap: var(--s3); margin-top: var(--s4); }
@media (min-width: 640px) { .hcc-renew-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 640px) { .hcc-renew-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }  /* jobs + equipment plans have two tiers */
.hcc-renew-note { margin-top: var(--s2); font-size: var(--t-micro); color: var(--slate-500); max-width: 60ch; }
.hcc-renew-tier { background: var(--slate-50); border: 1px solid var(--slate-200); border-radius: var(--r-md); padding: var(--s4); }
.hcc-renew-tier .term { font-size: var(--t-micro); font-weight: var(--w-bold); text-transform: uppercase; letter-spacing: .04em; color: var(--slate-500); }
.hcc-renew-tier .amt { font-size: var(--t-price); font-weight: var(--w-hvy); letter-spacing: -.02em; margin: var(--s1) 0 var(--s3); }

/* ---- Standalone card form (profile, and later the post-ad steps) ----------
   Same field primitives as .hcc-auth-form (§8.5) but on a card inside normal
   page chrome rather than the centred auth shell. */
.hcc-form {
  background: #fff; border: 1px solid var(--slate-300); border-radius: var(--r-lg);
  padding: var(--s6); display: flex; flex-direction: column; gap: var(--s6);
}
@media (min-width: 640px) { .hcc-form { padding: var(--s8); } }
.hcc-form fieldset { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--s3); min-width: 0; }
.hcc-form legend { padding: 0; font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-700); }
/* Radio row. Native controls, brand-tinted — a custom radio here would be a
   new component for one use and a new set of a11y bugs to own. */
.hcc-radio-row { display: flex; flex-wrap: wrap; gap: var(--s3); }
.hcc-radio {
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 44px; padding: 0 var(--s4);
  border: 1px solid var(--slate-300); border-radius: var(--r-md);
  font-size: var(--t-meta); color: var(--slate-700); cursor: pointer;
  transition: border-color .15s, background-color .15s;
}
.hcc-radio:hover { border-color: var(--navy-300); background: var(--navy-50); }
.hcc-radio input[type="radio"] { width: 18px; height: 18px; margin: 0; accent-color: var(--navy-700); }
.hcc-radio:has(input:checked) { border-color: var(--navy-700); background: var(--navy-50); color: var(--navy-700); font-weight: var(--w-semi); }
.hcc-radio:has(input:focus-visible) { outline: 2px solid var(--navy-700); outline-offset: 3px; }
.hcc-radio:has(input:focus-visible) input:focus-visible { outline: none; }
/* Divider + action row at the foot of a form. */
.hcc-form-sep { border-top: 1px solid var(--slate-200); padding-top: var(--s6); display: flex; flex-direction: column; gap: var(--s6); }
.hcc-form-foot {
  border-top: 1px solid var(--slate-200); padding-top: var(--s6);
  display: flex; flex-direction: column-reverse; gap: var(--s3);
}
@media (min-width: 520px) { .hcc-form-foot { flex-direction: row; justify-content: flex-end; } }

/* Utility. Owned here rather than borrowed from Tailwind's `.hidden`, which
   disappears at B7 — a page whose password fields are revealed by toggling a
   class must not depend on a stylesheet that is being retired. */
.hcc-hidden { display: none !important; }

/* ---- Shared card grid -----------------------------------------------------
   Browse ships `.br-grid` and detail ships `.hcd-similar-grid`, both of which
   predate this and are page-local. Favourites is the third surface to need the
   same grid, so it goes in the system instead. Consolidating the other two on
   to it is a B7 cleanup — worth doing, not worth re-verifying two already-
   signed-off pages for right now. */
.hcc-card-grid { display: grid; grid-template-columns: 1fr; gap: var(--s6); }
@media (min-width: 640px) { .hcc-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 960px) { .hcc-card-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* Saved-listings grid. The §6 favourite button pops when it renders pressed,
   which reads as feedback on browse — you clicked save, the page reloaded,
   that one heart pulses. Here every card is saved by definition, so on load
   the whole grid pulses at once and reads as a rendering glitch rather than
   confirmation. Nothing was just saved, so nothing should animate. */
.hcc-card-grid--saved .hcc-fav[aria-pressed="true"] svg { animation: none; }

/* ============================================================================
   8.7 POST-AD FLOW (.hcc-steps, .hcc-formpage)
   ============================================================================ */

/* ---- Step indicator -------------------------------------------------------
   Shared by Steps 1-3 and the edit page. Was three ad-hoc Tailwind blocks
   repeated per page with the active state hand-set each time, which is how the
   three copies had already drifted on circle size (40 vs 48) and label case. */
.hcc-steps {
  display: flex; align-items: flex-start;
  margin: 0 auto var(--s10); max-width: 640px;
}
.hcc-step { display: flex; flex-direction: column; align-items: center; gap: var(--s2); flex-shrink: 0; width: 96px; }
.hcc-step .n {
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 999px;
  border: 1px solid var(--slate-300); background: #fff;
  font-size: var(--t-meta); font-weight: var(--w-bold); color: var(--slate-500);
}
.hcc-step .lbl {
  font-size: var(--t-micro); font-weight: var(--w-semi);
  color: var(--slate-500); text-align: center; line-height: 1.35;
}
.hcc-step.is-current .n { background: var(--navy-700); border-color: var(--navy-700); color: #fff; }
.hcc-step.is-current .lbl { color: var(--navy-700); font-weight: var(--w-bold); }
.hcc-step.is-done .n { background: var(--navy-50); border-color: var(--navy-300); color: var(--navy-700); }
.hcc-step.is-done .lbl { color: var(--slate-600); }
/* The connector sits level with the middle of the 40px circle, not centred in
   the item — the labels below have variable height and would drag it around. */
.hcc-step-bar { flex: 1; height: 1px; background: var(--slate-300); margin-top: 20px; min-width: var(--s2); }
@media (max-width: 419px) {
  .hcc-step { width: 72px; }
  .hcc-step .n { width: 32px; height: 32px; }
  .hcc-step-bar { margin-top: 16px; }
}

/* ---- Form page shell ------------------------------------------------------
   Centred heading + steps + card. The post-ad pages are the only place on the
   site with a centred page head; it belongs to the wizard, not to pages. */
.hcc-formpage { max-width: 780px; }
.hcc-formpage-head { text-align: center; margin-bottom: var(--s10); }
.hcc-formpage-head h1 { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; line-height: 1.2; }
.hcc-formpage-head p { margin-top: var(--s2); font-size: var(--t-lede); color: var(--slate-600); line-height: 1.6; }
/* Section head inside a form card. */
.hcc-form-head { display: flex; flex-direction: column; gap: var(--s1); }
.hcc-form-head h2,
/* A section card that leads with a bare <h2> rather than a head block —
   the edit page stacks six of them and does not need a lede under each. */
.hcc-form > h2 { font-size: var(--t-lede); font-weight: var(--w-bold); letter-spacing: -.02em; }
.hcc-form-head p { font-size: var(--t-meta); color: var(--slate-600); line-height: 1.6; }

/* ---- Summary strip (Step 3 recap of Steps 1-2) --------------------------- */
.hcc-summary {
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s6);
  background: var(--navy-50); border: 1px solid var(--navy-100);
  border-radius: var(--r-md); padding: var(--s4);
  font-size: var(--t-meta); margin-bottom: var(--s6);
}
.hcc-summary .k { color: var(--slate-600); }
.hcc-summary .v { font-weight: var(--w-semi); color: var(--navy-700); }

/* ---- Photo upload slots -------------------------------------------------- */
.hcc-photo-list { display: flex; flex-direction: column; gap: var(--s3); }
.hcc-photo-slot {
  border: 1px solid var(--slate-300); border-radius: var(--r-md);
  padding: var(--s4); background: var(--slate-50);
  display: flex; flex-direction: column; gap: var(--s4);
}
@media (min-width: 560px) { .hcc-photo-slot { flex-direction: row; } }
.hcc-photo-thumb {
  position: relative; flex-shrink: 0; align-self: flex-start;
  width: 100%; aspect-ratio: 3/2; overflow: hidden;
  border-radius: var(--r-sm); border: 1px solid var(--slate-200); background: #fff;
}
@media (min-width: 560px) { .hcc-photo-thumb { width: 108px; } }
.hcc-photo-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hcc-photo-thumb .ph {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: var(--slate-400);
}
.hcc-photo-fields { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--s2); }
.hcc-photo-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); }
.hcc-photo-head label { font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-700); }
/* Global, NOT scoped to .hcc-photo-head. It is used 21 times across the
   post-ad flow, the edit page and the inbox as the "secondary half" of a
   label; scoped to one parent, 20 of those rendered unstyled and the two
   halves ran together as one bold string. */
.opt { font-weight: var(--w-body); color: var(--slate-500); }
.hcc-convo-who .opt { margin-left: var(--s1); font-size: var(--t-micro); }
.hcc-photo-head button {
  font-family: inherit; font-size: var(--t-micro); font-weight: var(--w-semi);
  color: var(--slate-500); background: none; border: 0; cursor: pointer;
  min-height: 44px; padding: 0 var(--s1); flex-shrink: 0;
}
.hcc-photo-head button:hover { color: var(--red-700); }
/* Native file input, brand-tinted button. A custom control here would mean
   owning the filename display, the empty state and the keyboard behaviour for
   no gain the user can see. */
.hcc-file {
  width: 100%; font-family: inherit; font-size: var(--t-meta); color: var(--slate-700);
}
.hcc-file::file-selector-button {
  margin-right: var(--s3); padding: 0 var(--s3); min-height: 40px;
  border: 0; border-radius: var(--r-sm); cursor: pointer;
  font-family: inherit; font-size: var(--t-meta); font-weight: var(--w-semi);
  background: var(--navy-700); color: #fff;
}
.hcc-file::file-selector-button:hover { background: var(--navy-800); }
/* Add-another affordance. Dashed, because it is a placeholder for content that
   is not there yet — the one place dashes earn their keep. */
.hcc-photo-add {
  width: 100%; margin-top: var(--s3);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 48px; padding: 0 var(--s4);
  border: 1px dashed var(--slate-400); border-radius: var(--r-md);
  background: none; font-family: inherit;
  font-size: var(--t-meta); font-weight: var(--w-semi); color: var(--slate-600);
  cursor: pointer; transition: border-color .15s, color .15s, background-color .15s;
}
.hcc-photo-add:hover { border-color: var(--navy-700); color: var(--navy-700); background: var(--navy-50); }

/* Submit-once state. Replaces a Tailwind class trio the JS used to bolt on,
   which would have gone silently inert at B7 and left the button looking
   clickable while doing nothing. */
.hcc-btn.is-busy { opacity: .7; pointer-events: none; cursor: default; }

/* Split action row: Back on the left, primary on the right. */
.hcc-form-foot--split { justify-content: space-between; }

/* Currency-prefixed input. The prefix needs a positioned parent AND matching
   left padding on the field, or the "$" sits on top of the typed value. The
   old markup used Tailwind's `.relative` for the parent, which would have gone
   inert at B7 and thrown the prefix onto whatever ancestor was positioned. */
.hcc-input-prefix { position: relative; }
.hcc-input-prefix .pfx {
  position: absolute; left: var(--s4); top: 50%; transform: translateY(-50%);
  color: var(--slate-500); font-weight: var(--w-semi); pointer-events: none;
}
.hcc-input-prefix .hcc-input { padding-left: calc(var(--s4) + 14px); }

/* ============================================================================
   8.8 MODAL (AI assistant — post-ad Step 2)
   ============================================================================
   The old markup drove this off Tailwind utilities plus a documented reliance
   on SOURCE ORDER: `.hidden` had to out-rank `.block`/`.flex` because both were
   present on the container at once. That is fragile in principle and dead at
   B7, and it gated 98 classList call sites. Here `.hcc-hidden` carries
   `!important`, so it wins regardless of order or of which stylesheet ships. */
.hcc-modal {
  position: fixed; inset: 0; z-index: 100;
  overflow-y: auto; overscroll-behavior: contain;
}
.hcc-modal-backdrop {
  position: fixed; inset: 0;
  background: color-mix(in srgb, var(--slate-900) 90%, transparent);
  backdrop-filter: blur(3px);
  animation: hcc-fade .18s ease-out;
}
@keyframes hcc-fade { from { opacity: 0 } to { opacity: 1 } }
/* min-height:100% keeps flex centring correct when the panel fits, and lets the
   container grow past the viewport when it doesn't, so .hcc-modal scrolls
   instead of clipping the panel at both ends (flex centring puts the overflow
   at negative Y, which cannot be scrolled to). */
.hcc-modal-center {
  position: relative; min-height: 100%;
  display: flex; align-items: center; justify-content: center;
  padding: var(--s4);
}
.hcc-modal-panel {
  position: relative; display: flex; flex-direction: column;
  width: 100%; max-width: 640px; max-height: 90vh;
  background: #fff; border: 1px solid var(--slate-300);
  border-radius: var(--r-lg); overflow: hidden;
  box-shadow: 0 24px 48px -12px rgb(15 23 42 / .25);
}
.hcc-modal-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: var(--s4) var(--s6); border-bottom: 1px solid var(--slate-200);
}
.hcc-modal-head h2 { font-size: var(--t-lede); font-weight: var(--w-bold); letter-spacing: -.02em; }
.hcc-modal-close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex-shrink: 0;
  border: 0; border-radius: var(--r-sm); background: none; cursor: pointer;
  color: var(--slate-500); transition: background-color .15s, color .15s;
}
.hcc-modal-close:hover { background: var(--slate-100); color: var(--slate-900); }
/* overscroll-behavior stops wheel/touch chaining out to the page at the edges. */
.hcc-modal-body {
  flex: 1; min-height: 0; padding: var(--s6);
  overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
}
.hcc-modal-body:focus { outline: none; }
.hcc-modal-foot {
  display: flex; flex-wrap: wrap; gap: var(--s3); justify-content: flex-end;
  padding: var(--s4) var(--s6); border-top: 1px solid var(--slate-200);
  background: var(--slate-50);
}
/* Scroll lock. overflow:hidden on BOTH html and body is the reliable technique.
   Deliberately NOT position:fixed on body — that creates a stacking context
   that interacts badly with the sticky header, and fixed children of a fixed
   ancestor get clipped in some rendering paths, which previously stopped the
   backdrop covering the header. */
html.hcc-scroll-locked, body.hcc-scroll-locked { overflow: hidden !important; }
/* Full-width cell inside .hcc-field-row. */
.hcc-span-2 { grid-column: 1 / -1; }

/* ---- AI assistant surfaces (Step 2) -------------------------------------- */
.hcc-choice {
  text-align: left; background: #fff; cursor: pointer;
  border: 1px solid var(--slate-300); border-radius: var(--r-lg);
  padding: var(--s6); font-family: inherit;
  display: flex; flex-direction: column; gap: var(--s3);
  transition: border-color .15s, background-color .15s;
}
.hcc-choice:hover { border-color: var(--navy-700); background: var(--navy-50); }
.hcc-choice-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex-shrink: 0;
  border-radius: var(--r-md); background: var(--slate-100); color: var(--slate-700);
  transition: background-color .15s, color .15s;
}
.hcc-choice:hover .hcc-choice-icon,
.hcc-choice-icon.is-on { background: var(--navy-50); color: var(--navy-700); }
.hcc-empty > .hcc-choice-icon { margin: 0 auto var(--s4); }

.hcc-loading { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s4); padding: var(--s12) 0; text-align: center; }
.hcc-spinner {
  width: 44px; height: 44px; border-radius: 999px;
  border: 3px solid var(--navy-100); border-top-color: var(--navy-700);
  animation: hcc-spin .7s linear infinite;
}
.hcc-spin-icon { color: var(--navy-700); animation: hcc-spin .7s linear infinite; }
@keyframes hcc-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .hcc-spinner, .hcc-spin-icon { animation-duration: 2s; }
}

/* ---- AI action buttons ----------------------------------------------------
   The old markup carried `disabled:` utilities AND the JS swapped six colour
   classes on every keystroke to produce the same effect. `.disabled` was
   already being set, so the class juggling was redundant with a plain
   :disabled rule — and it was 14 more Tailwind names to lose at B7. */
.hcc-ai-btn {
  display: inline-flex; align-items: center; gap: var(--s1);
  min-height: 36px; padding: 0 var(--s3);
  border: 1px solid transparent; border-radius: var(--r-sm);
  font-family: inherit; font-size: var(--t-micro); font-weight: var(--w-bold);
  background: var(--navy-700); color: #fff; cursor: pointer;
  transition: background-color .15s, color .15s, border-color .15s;
}
.hcc-ai-btn:hover:not(:disabled) { background: var(--navy-800); }
.hcc-ai-btn--soft { background: var(--navy-50); color: var(--navy-700); border-color: var(--navy-100); }
.hcc-ai-btn--soft:hover:not(:disabled) { background: var(--navy-100); }
.hcc-ai-btn:disabled {
  background: var(--slate-100); color: var(--slate-400);
  border-color: var(--slate-200); cursor: not-allowed;
}

/* ---- Status pill (autosave) ----------------------------------------------
   Three states driven by one class each, rather than adding and removing
   three colour utilities per transition. */
.hcc-pill {
  display: inline-flex; align-items: center; gap: var(--s1);
  padding: 3px var(--s2); border-radius: 999px;
  font-size: var(--t-micro); font-weight: var(--w-semi);
  background: var(--slate-100); color: var(--slate-600); border: 1px solid var(--slate-200);
}
.hcc-pill--busy { background: var(--navy-50); color: var(--navy-700); border-color: var(--navy-100); }
.hcc-pill--err  { background: color-mix(in srgb, var(--red-500) 8%, #fff); color: var(--red-700); border-color: color-mix(in srgb, var(--red-500) 30%, #fff); }

/* Suggestion list button (AI title suggestions, built in JS). */
.hcc-suggest {
  display: block; width: 100%; text-align: left; cursor: pointer;
  font-family: inherit; font-size: var(--t-meta); color: var(--slate-700);
  background: var(--slate-50); border: 1px solid var(--slate-300);
  border-radius: var(--r-sm); padding: var(--s2) var(--s3);
  transition: background-color .15s, border-color .15s;
}
.hcc-suggest:hover { background: var(--navy-50); border-color: var(--navy-300); color: var(--navy-700); }
/* Footnote strip pinned under a modal body (quota / tier messaging). */
.hcc-modal-note {
  display: flex; align-items: flex-start; gap: var(--s2);
  padding: var(--s2) var(--s6);
  background: var(--navy-50); border-top: 1px solid var(--navy-100);
  font-size: var(--t-micro); color: var(--slate-600); line-height: 1.5;
}
/* Ordered list inside a panel (wizard "what happens next" steps). */
.hcc-list { margin: var(--s2) 0 0; padding-left: 1.2em; display: flex; flex-direction: column; gap: var(--s1); list-style: decimal; }

/* ============================================================================
   8.9 MESSAGING (.hcc-convo, .hcc-thread, .hcc-msg)
   ============================================================================ */

/* Round initial badge. One of the sanctioned 999px uses — it is a round icon,
   not a surface. */
.hcc-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; flex-shrink: 0; border-radius: 999px;
  background: var(--slate-100); color: var(--slate-600);
  font-size: var(--t-meta); font-weight: var(--w-bold);
}
.hcc-avatar.is-unread { background: var(--navy-700); color: #fff; }

/* Conversation row in the inbox list. */
.hcc-convo {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s4);
  background: #fff; border: 1px solid var(--slate-300); border-radius: var(--r-md);
  transition: border-color .15s, background-color .15s;
}
.hcc-convo + .hcc-convo { margin-top: var(--s2); }
.hcc-convo:hover { border-color: var(--navy-300); background: var(--navy-50); }
.hcc-convo.is-unread { border-color: var(--navy-100); background: var(--navy-50); }
.hcc-convo-body { flex: 1; min-width: 0; }
.hcc-convo-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s2); }
.hcc-convo-who { font-size: var(--t-body); font-weight: var(--w-semi); color: var(--slate-900); }
.hcc-convo.is-unread .hcc-convo-who { font-weight: var(--w-bold); }
.hcc-convo-when { font-size: var(--t-micro); color: var(--slate-500); white-space: nowrap; flex-shrink: 0; }
.hcc-convo-sub,
.hcc-convo-prev {
  font-size: var(--t-meta); color: var(--slate-600); margin-top: var(--s1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hcc-convo-sub { font-size: var(--t-micro); color: var(--slate-500); }

/* ---- Thread ---------------------------------------------------------------
   Bubbles. `max-width:80%` keeps a long paragraph from spanning the full
   column, which is what makes a chat read as a chat. */
.hcc-thread { display: flex; flex-direction: column; gap: var(--s4); }
.hcc-msg-day {
  display: flex; align-items: center; gap: var(--s3);
  font-size: var(--t-micro); font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: .04em; color: var(--slate-500);
  margin: var(--s2) 0;
}
.hcc-msg-day::before, .hcc-msg-day::after { content: ""; flex: 1; height: 1px; background: var(--slate-200); }
.hcc-msg { display: flex; flex-direction: column; gap: var(--s1); max-width: 80%; align-self: flex-start; }
.hcc-msg--mine { align-self: flex-end; align-items: flex-end; }
.hcc-msg-who { font-size: var(--t-micro); font-weight: var(--w-semi); color: var(--slate-500); }
.hcc-msg--mine .hcc-msg-who { color: var(--navy-700); }
/* One square corner on the sender's side is the whole visual grammar of a
   bubble; without it the two sides are just tinted rectangles. */
.hcc-msg-bubble {
  padding: var(--s2) var(--s4); border-radius: var(--r-lg);
  font-size: var(--t-meta); line-height: 1.6; white-space: pre-wrap;
  background: var(--slate-100); color: var(--slate-900);
  border-bottom-left-radius: var(--r-sm);
}
.hcc-msg--mine .hcc-msg-bubble {
  background: var(--navy-700); color: #fff;
  border-bottom-left-radius: var(--r-lg); border-bottom-right-radius: var(--r-sm);
}
.hcc-msg-when { font-size: var(--t-micro); color: var(--slate-400); }

/* ---- Photo sort tiles ----------------------------------------------------- */
.hcc-tile-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
@media (min-width: 560px) { .hcc-tile-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 900px) { .hcc-tile-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.hcc-tile {
  background: var(--slate-50); border: 1px solid var(--slate-300);
  border-radius: var(--r-md); overflow: hidden; cursor: move;
  transition: border-color .15s, background-color .15s;
}
.hcc-tile:hover { border-color: var(--navy-300); background: var(--navy-50); }
.hcc-tile.is-dragging { opacity: .5; }
.hcc-tile-media { aspect-ratio: 1; background: var(--slate-100); overflow: hidden; }
.hcc-tile-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hcc-tile-foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s2);
  padding: var(--s2); background: #fff; border-top: 1px solid var(--slate-200);
  font-size: var(--t-micro); color: var(--slate-500);
}
/* Scrollable thread feed. max-height keeps the reply box reachable without
   scrolling past the whole history on a long conversation. */
.hcc-thread-feed {
  background: #fff; border: 1px solid var(--slate-300); border-radius: var(--r-lg);
  padding: var(--s4); margin-bottom: var(--s4);
  max-height: 60vh; overflow-y: auto; overscroll-behavior: contain;
}

/* Destructive action. The only red button in the system — reserved for
   irreversible operations (delete a listing), never for validation errors. */
.hcc-btn--danger {
  background: var(--red-500); color: #fff; font-weight: var(--w-bold);
  padding: 0 var(--s6); min-height: 48px; border: 1px solid transparent;
}
.hcc-btn--danger:hover { background: var(--red-700); }

/* Icon-leading search field (inbox filter). */
.hcc-search-field { position: relative; }
.hcc-search-field .icon {
  position: absolute; left: var(--s3); top: 50%; transform: translateY(-50%);
  color: var(--slate-400); pointer-events: none;
}
.hcc-search-field .hcc-input { padding-left: calc(var(--s3) + 26px); }

/* Small square media thumb (listing preview beside a contact form). */
.hcc-thumb-sm {
  width: 80px; height: 80px; flex-shrink: 0; overflow: hidden;
  border-radius: var(--r-md); background: var(--slate-100);
  display: flex; align-items: center; justify-content: center; color: var(--slate-400);
}
.hcc-thumb-sm img { width: 100%; height: 100%; object-fit: cover; }

/* Round icon tile for empty states / confirmations. */
.hcc-icon-tile {
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; border-radius: var(--r-lg);
  background: var(--slate-100); color: var(--slate-400);
}
.hcc-icon-tile--danger { background: color-mix(in srgb, var(--red-500) 8%, #fff); color: var(--red-700); border: 1px solid color-mix(in srgb, var(--red-500) 25%, #fff); }

/* Definition-style fact grid (delete confirmation summary). */
.hcc-facts { display: grid; grid-template-columns: 1fr; gap: var(--s1) var(--s4); font-size: var(--t-meta); }
@media (min-width: 560px) { .hcc-facts { grid-template-columns: max-content 1fr; } }
.hcc-facts dt { color: var(--slate-500); }
.hcc-facts dd { margin: 0; color: var(--slate-900); font-weight: var(--w-semi); }
/* Unread marker dot. */
.hcc-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--navy-700); flex-shrink: 0; }

/* Display utilities the markup genuinely depends on. `display:contents` on a
   <form> takes it out of the box tree so its children lay out in the PARENT's
   grid/flex — without it those forms become block boxes and the row they sit
   in collapses. Borrowed from Tailwind until now, which would have failed
   silently and structurally at B7. */
.hcc-contents { display: contents; }
.hcc-inline   { display: inline; }

/* ============================================================================
   8.10 PROSE (marketing + legal long-form)
   ============================================================================
   One editorial column for about / disclaimer / privacy / terms. Measure is
   capped at 68ch: these pages run to 29 KB of text and a full-width line at
   1440px is unreadable.

   Element selectors, deliberately. This is the one place in the system where
   the content is authored prose rather than composed components — the legal
   pages are 62 <p> tags with no classes at all, and requiring a class per
   paragraph would guarantee they drift the first time someone edits them. */
/* overflow-wrap is not optional here: these pages carry bare email addresses
   and URLs ("privacy.officer@healthcareclassified.com" is 40 unbreakable
   characters) which push 33px of horizontal page scroll at 320px. `anywhere`
   rather than `break-word` on links, because break-word does not reduce the
   element's min-content contribution and so does not stop the overflow. */
.hcc-prose { max-width: 68ch; font-size: var(--t-body); line-height: 1.7; color: var(--slate-700); overflow-wrap: break-word; }
.hcc-prose a { overflow-wrap: anywhere; }
.hcc-prose > * + * { margin-top: var(--s4); }
.hcc-prose h1 {
  font-size: var(--t-h2); font-weight: var(--w-hvy);
  letter-spacing: -.025em; line-height: 1.2; color: var(--slate-900);
}
.hcc-prose h2 {
  font-size: var(--t-lede); font-weight: var(--w-bold);
  letter-spacing: -.02em; line-height: 1.35; color: var(--navy-700);
  margin-top: var(--s10); padding-top: var(--s4);
  border-top: 1px solid var(--slate-200);
}
.hcc-prose h1 + h2, .hcc-prose > h2:first-child { margin-top: var(--s6); border-top: 0; padding-top: 0; }
.hcc-prose h3 {
  font-size: var(--t-body); font-weight: var(--w-bold);
  color: var(--slate-900); margin-top: var(--s6);
}
.hcc-prose strong { font-weight: var(--w-semi); color: var(--slate-900); }
.hcc-prose a { color: var(--navy-700); font-weight: var(--w-semi); text-decoration: underline; text-underline-offset: 2px; }
.hcc-prose a:hover { color: var(--navy-800); }
.hcc-prose ul, .hcc-prose ol { padding-left: 1.3em; display: flex; flex-direction: column; gap: var(--s2); }
/* Opt back in: the reset above strips markers globally. */
.hcc-prose ul { list-style: disc; }
.hcc-prose ol { list-style: decimal; }
.hcc-prose li::marker { color: var(--slate-400); }
.hcc-prose .lede { font-size: var(--t-lede); color: var(--slate-600); line-height: 1.6; }
/* Effective-date / last-updated line under the title. */
.hcc-prose .stamp { font-size: var(--t-micro); color: var(--slate-500); }

/* Small pill above a heading. Navy, so it can never be mistaken for Featured. */
.hcc-eyebrow {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: var(--s1) var(--s3); border-radius: 999px;
  background: var(--navy-50); border: 1px solid var(--navy-100);
  font-size: var(--t-micro); font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: .04em; color: var(--navy-700);
}

/* ---- Pricing tiers (banner advertising) ---------------------------------- */
.hcc-tier-grid { display: grid; grid-template-columns: 1fr; gap: var(--s4); }
@media (min-width: 640px) { .hcc-tier-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.hcc-tier {
  background: #fff; border: 1px solid var(--slate-300); border-radius: var(--r-lg);
  padding: var(--s6); text-align: center;
}
.hcc-tier.is-featured { border-color: var(--navy-300); background: var(--navy-50); }
.hcc-tier .term {
  font-size: var(--t-micro); font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: .04em; color: var(--slate-500);
}
.hcc-tier.is-featured .term { color: var(--navy-700); }
.hcc-tier .amt { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; margin-top: var(--s1); color: var(--slate-900); }
.hcc-tier .note { font-size: var(--t-meta); color: var(--slate-600); margin-top: var(--s2); }

/* ============================================================================
   8.11 PLAN CARDS (monetization: AI Listing Pro, Featured, Student Registry)
   ============================================================================ */
.hcc-plan-grid { display: grid; grid-template-columns: 1fr; gap: var(--s4); }
@media (min-width: 720px) { .hcc-plan-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 720px) { .hcc-plan-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.hcc-plan {
  position: relative; display: flex; flex-direction: column;
  background: #fff; border: 1px solid var(--slate-300);
  border-radius: var(--r-lg); padding: var(--s6);
}
/* Recommended = navy (an editorial pick). Owned = emerald, which the COLOUR
   law reserves for verified/confirmed — "you already have this" is exactly
   that. Neither is amber: amber marks a listing somebody paid to Feature, not
   a product tile that happens to cost money. */
.hcc-plan.is-recommended { border-color: var(--navy-300); box-shadow: 0 0 0 3px var(--navy-50); }
.hcc-plan.is-owned { border-color: color-mix(in srgb, var(--emerald-600) 40%, #fff); box-shadow: 0 0 0 3px var(--emerald-50); }
.hcc-plan-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.hcc-plan-name {
  font-size: var(--t-micro); font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: .04em; color: var(--slate-500);
}
.hcc-plan-price { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; color: var(--slate-900); margin-top: var(--s2); }
.hcc-plan-terms { font-size: var(--t-micro); color: var(--slate-500); margin-top: var(--s1); }
.hcc-plan-feats {
  list-style: none; padding: 0; margin: var(--s4) 0 var(--s6);
  display: flex; flex-direction: column; gap: var(--s2);
  font-size: var(--t-meta); color: var(--slate-700);
}
.hcc-plan-feats li { display: flex; align-items: flex-start; gap: var(--s2); line-height: 1.5; }
.hcc-plan-feats svg { color: var(--emerald-600); flex-shrink: 0; margin-top: 3px; }
.hcc-plan-foot { margin-top: auto; }
.hcc-plan-foot .hcc-btn { width: 100%; }
/* Ribbon pinned to the card's top edge. */
.hcc-ribbon {
  position: absolute; top: 0; left: 50%; transform: translate(-50%, -50%);
  display: inline-flex; align-items: center;
  padding: 3px var(--s3); border-radius: 999px;
  background: var(--navy-700); color: #fff;
  font-size: var(--t-micro); font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: .04em; white-space: nowrap;
}
/* "Active" / owned pill inside a plan head. */
.hcc-plan-state {
  display: inline-flex; align-items: center;
  padding: 2px var(--s2); border-radius: 999px;
  font-size: var(--t-micro); font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: .04em;
  color: var(--emerald-700); background: var(--emerald-50);
  border: 1px solid color-mix(in srgb, var(--emerald-600) 30%, #fff);
}
/* Disabled CTA on an owned plan — states a fact, is not clickable. */
.hcc-btn--owned {
  background: var(--emerald-50); color: var(--emerald-700);
  border: 1px solid color-mix(in srgb, var(--emerald-600) 30%, #fff);
  font-weight: var(--w-bold); padding: 0 var(--s6); min-height: 48px; cursor: default;
}


/* ============================================================================
   8.12 PRICING PAGE (.pr-*) — place-ad-with-healthcare-classified.php
   ============================================================================
   Redesigned 2026-09-26 (owner: "extremely clear and less boring"). The page
   exists to answer one question, so it answers it FIRST: the hero states the
   price as a receipt — every line a seller worries about, each one $0 — laid
   over a photograph. Then prices by category as photo-first cards (Practice
   For Sale leads: it is the flagship and the priciest), the renewal rules as
   a diagram of a listing's life instead of a bullet list, the two optional
   extras demonstrated rather than described, a FAQ, and a closing CTA.
   Every price is read from hcc_listing_plans(); nothing here is a number. */

.pr { padding-bottom: var(--s24); }
@media (max-width: 899px) { .pr { padding-bottom: var(--s16); } }

/* Section head — H2 and its lede share a row at desktop (left rail, bottom-
   aligned) so the page doesn't repeat the centred eyebrow/H2/sub stack. */
.pr-sechead {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: var(--s3) var(--s16); align-items: end; margin-bottom: var(--s10);
}
.pr-sechead h2 { font-size: var(--t-h2); font-weight: var(--w-hvy); letter-spacing: -.025em; line-height: 1.2; }
.pr-sechead p { font-size: var(--t-body); color: var(--slate-600); line-height: 1.6; max-width: 56ch; }
.pr-sechead--stack { grid-template-columns: 1fr; align-items: start; margin-bottom: 0; }
@media (max-width: 899px) { .pr-sechead { grid-template-columns: 1fr; margin-bottom: var(--s8); } }
.pr-inline { color: var(--navy-700); font-weight: var(--w-semi); text-decoration: underline; text-underline-offset: 2px; }
.pr-inline:hover { color: var(--navy-800); }

/* ---- 1. HERO ------------------------------------------------------------- */
.pr-hero { padding: var(--s16) 0 var(--s24); }
@media (max-width: 899px) { .pr-hero { padding: var(--s10) 0 var(--s16); } }
.pr-hero-grid {
  display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 6fr);
  gap: var(--s16); align-items: center;
}
@media (max-width: 899px) { .pr-hero-grid { grid-template-columns: 1fr; gap: var(--s10); } }
.pr-kicker {
  display: block; margin-bottom: var(--s4);
  font-size: var(--t-micro); font-weight: var(--w-semi);
  letter-spacing: .1em; text-transform: uppercase; color: var(--slate-500);
}
/* The page's one --t-display use. Two tiers in one H1: the answer at display
   size, the condition beneath it at --t-h2, so the whole headline reads as a
   single sentence but the eye lands on "free". */
.pr-hero h1 {
  font-size: var(--t-display); font-weight: var(--w-max);
  letter-spacing: -.04em; line-height: 1.02; text-wrap: balance;
}
.pr-hero h1 span {
  display: block; margin-top: var(--s4);
  font-size: var(--t-h2); font-weight: var(--w-bold);
  letter-spacing: -.02em; line-height: 1.25; color: var(--slate-600);
}
@media (max-width: 1023px) { .pr-hero h1 { font-size: 56px; } }
@media (max-width: 599px)  { .pr-hero h1 { font-size: 44px; } .pr-hero h1 span { font-size: 22px; } }
.pr-lede {
  margin-top: var(--s6); max-width: 46ch;
  font-size: var(--t-lede); line-height: 1.6; color: var(--slate-600);
}
.pr-hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s4) var(--s6); margin-top: var(--s8); }

/* Photo with the receipt overhanging its lower-left corner. The left padding
   is the overhang's room, so the receipt never leaves the grid column; the
   negative bottom hangs it below the photo so it sits on the coat, not the
   face (the hero's s24 bottom padding absorbs the overhang). */
.pr-hero-media { position: relative; padding-left: var(--s12); }
.pr-hero-media img {
  width: 100%; aspect-ratio: 4 / 5; max-height: 580px;
  object-fit: cover; object-position: center 30%;
  border-radius: var(--r-lg);
}
/* A genuinely floating surface over a photograph, so it takes --shadow-pop
   (ELEVATION law) — a border alone disappears against the white coat. */
.pr-receipt {
  position: absolute; left: 0; bottom: calc(-1 * var(--s8));
  width: min(300px, 78%);
  background: #fff; border: 1px solid var(--slate-300);
  border-radius: var(--r-md); box-shadow: var(--shadow-pop);
  padding: var(--s4) var(--s6) var(--s6);
  font-variant-numeric: tabular-nums;
}
.pr-receipt-head {
  display: flex; justify-content: space-between;
  padding-bottom: var(--s3); margin-bottom: var(--s3);
  border-bottom: 1px dashed var(--slate-300);
  font-size: var(--t-micro); font-weight: var(--w-bold);
  letter-spacing: .08em; text-transform: uppercase; color: var(--slate-500);
}
.pr-receipt dl { display: flex; flex-direction: column; gap: var(--s2); }
.pr-receipt dl > div { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s4); font-size: var(--t-meta); }
.pr-receipt dt { color: var(--slate-600); }
.pr-receipt dd { color: var(--slate-900); font-weight: var(--w-semi); white-space: nowrap; }
.pr-receipt-total {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-top: var(--s4); padding-top: var(--s3);
  border-top: 1px dashed var(--slate-300);
  font-size: var(--t-meta); font-weight: var(--w-bold); color: var(--slate-900);
}
.pr-receipt-total strong { font-size: var(--t-h2); font-weight: var(--w-max); letter-spacing: -.025em; color: var(--navy-700); }
@media (max-width: 899px) {
  .pr-hero-media { padding-left: 0; }
  .pr-hero-media img { aspect-ratio: 4 / 3; max-height: none; object-position: center 22%; }
  .pr-receipt { position: relative; left: auto; bottom: auto; width: auto; max-width: 340px; margin: calc(-1 * var(--s10)) var(--s4) 0; }
}

/* ---- 2. PLANS ------------------------------------------------------------ */
.pr-plans { padding: var(--s16) 0; background: #fff; border-block: 1px solid var(--slate-200); }
.pr-plan-grid { display: grid; grid-template-columns: 1fr; gap: var(--s6); }
@media (min-width: 720px) { .pr-plan-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.pr-plan {
  display: flex; flex-direction: column; overflow: hidden;
  background: #fff; border: 1px solid var(--slate-300); border-radius: var(--r-lg);
}
/* The img is taken out of flow: an in-flow child with a taller intrinsic
   ratio (the equipment photo is portrait) stretches an aspect-ratio box,
   because aspect-ratio only sets a minimum when content overflows it. */
.pr-plan-media { position: relative; aspect-ratio: 16 / 9; background: var(--slate-100); }
.pr-plan-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.pr-plan--equipment .pr-plan-media img { object-position: center 62%; }
.pr-plan-media .badge { position: absolute; left: var(--s4); top: var(--s4); }
.pr-plan-body { display: flex; flex-direction: column; flex: 1; padding: var(--s6); }
/* The lead card: Practice For Sale spans the row, photo left, at desktop. */
@media (min-width: 720px) { .pr-plan:first-child { grid-column: 1 / -1; } }
@media (min-width: 900px) {
  .pr-plan:first-child { display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }
  .pr-plan:first-child .pr-plan-media { aspect-ratio: auto; min-height: 380px; }
  .pr-plan:first-child .pr-plan-body { padding: var(--s10); }
}
.pr-plan-for { font-size: var(--t-meta); color: var(--slate-600); line-height: 1.5; }
.pr-free {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s3);
  margin-top: var(--s3); padding-bottom: var(--s6);
  border-bottom: 1px solid var(--slate-200);
}
.pr-free-amt { font-size: var(--t-stmt); font-weight: var(--w-max); letter-spacing: -.03em; line-height: 1; color: var(--navy-700); }
.pr-free-for { font-size: var(--t-body); color: var(--slate-600); }
.pr-free-for strong { font-weight: var(--w-bold); color: var(--slate-900); }
.pr-then {
  margin-top: var(--s6);
  font-size: var(--t-micro); font-weight: var(--w-semi);
  letter-spacing: .08em; text-transform: uppercase; color: var(--slate-500);
}
.pr-tiers { display: flex; flex-direction: column; gap: var(--s2); margin-top: var(--s3); }
.pr-tiers li {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "term amt" "note amt";
  column-gap: var(--s4); align-items: center;
  padding: var(--s3) var(--s4);
  border: 1px solid var(--slate-200); border-radius: var(--r-md);
}
.pr-tiers li.is-best { border-color: var(--navy-300); background: var(--navy-50); }
.pr-tier-term {
  grid-area: term; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2);
  font-size: var(--t-body); font-weight: var(--w-semi); color: var(--slate-900);
}
.pr-tier-note { grid-area: note; font-size: var(--t-micro); color: var(--slate-500); font-variant-numeric: tabular-nums; }
.pr-tier-amt {
  grid-area: amt; font-size: var(--t-price); font-weight: var(--w-hvy);
  letter-spacing: -.02em; color: var(--slate-900); font-variant-numeric: tabular-nums;
}
/* Navy, never amber: "best value" is our editorial pick, not a paid placement. */
.pr-tier-tag {
  font-size: 10px; font-weight: var(--w-bold); letter-spacing: .04em; text-transform: uppercase;
  padding: 2px var(--s2); border-radius: var(--r-sm);
  background: var(--navy-700); color: #fff;
}
.pr-plan-cta { margin-top: auto; padding-top: var(--s4); align-self: flex-start; }
.pr-promises {
  display: flex; flex-wrap: wrap; gap: var(--s3) var(--s8); margin-top: var(--s8);
  font-size: var(--t-meta); font-weight: var(--w-med); color: var(--slate-700);
}
.pr-promises li { display: flex; align-items: center; gap: var(--s2); }
.pr-promises .icon { color: var(--emerald-600); }

/* ---- 3. A LISTING'S LIFE — the renewal rules as a diagram ------------------
   Desktop: one horizontal track, segment widths roughly proportional to how
   long each phase lasts. Below 900px it turns vertical, the bar running down
   the left of each stage's text. */
.pr-life { padding: var(--s24) 0 var(--s16); }
@media (max-width: 899px) { .pr-life { padding: var(--s16) 0 var(--s10); } }
.pr-track { display: grid; grid-template-columns: 2.6fr 3.4fr 3fr 3fr; gap: var(--s1); }
.pr-stage { display: flex; flex-direction: column; padding-right: var(--s6); }
.pr-bar {
  display: flex; align-items: center; justify-content: center; gap: var(--s3);
  height: 28px; margin: 0 calc(-1 * var(--s6)) var(--s6) 0;   /* bleed across the stage's right padding so the track reads continuous */
  border-radius: 3px;
  font-size: var(--t-micro); font-weight: var(--w-bold); letter-spacing: .08em; text-transform: uppercase;
}
.pr-stage:first-child .pr-bar { border-radius: var(--r-sm) 3px 3px var(--r-sm); }
.pr-stage:last-child .pr-bar  { border-radius: 3px var(--r-sm) var(--r-sm) 3px; margin-right: 0; }
.pr-stage:last-child { padding-right: 0; }
.pr-stage--review .pr-bar { background: var(--slate-300); }
.pr-stage--live   .pr-bar { background: var(--navy-700); color: #fff; }
.pr-stage--notice .pr-bar { background: var(--navy-500); justify-content: space-evenly; }
.pr-stage--after  .pr-bar { background: repeating-linear-gradient(90deg, var(--navy-200) 0 10px, transparent 10px 16px); }
/* Countdown markers for the 7/3/1-day reminder emails. */
.pr-bar i {
  font-style: normal; display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 var(--s1); border-radius: 4px;
  background: #fff; color: var(--navy-700); letter-spacing: 0; font-variant-numeric: tabular-nums;
}
.pr-when {
  font-size: var(--t-micro); font-weight: var(--w-semi);
  letter-spacing: .08em; text-transform: uppercase; color: var(--navy-600);
}
.pr-stage h3 { margin-top: var(--s2); font-size: var(--t-body); font-weight: var(--w-bold); letter-spacing: -.01em; }
.pr-stage p  { margin-top: var(--s2); font-size: var(--t-meta); color: var(--slate-600); line-height: 1.6; }
@media (max-width: 899px) {
  .pr-track { grid-template-columns: 1fr; gap: var(--s1); }
  .pr-stage { display: grid; grid-template-columns: 28px minmax(0, 1fr); column-gap: var(--s4); padding-right: 0; }
  .pr-stage > :not(.pr-bar) { grid-column: 2; }
  .pr-bar { grid-column: 1; grid-row: 1 / span 3; height: auto; margin: 0; flex-direction: column; justify-content: center; }
  .pr-bar span { display: none; }
  .pr-stage--notice .pr-bar { justify-content: space-evenly; }
  .pr-stage--after .pr-bar { background: repeating-linear-gradient(180deg, var(--navy-200) 0 10px, transparent 10px 16px); }
  .pr-stage:first-child .pr-bar { border-radius: var(--r-sm) var(--r-sm) 3px 3px; }
  .pr-stage:last-child .pr-bar  { border-radius: 3px 3px var(--r-sm) var(--r-sm); }
  .pr-stage p { padding-bottom: var(--s8); }
  .pr-stage:last-child p { padding-bottom: 0; }
}

/* ---- 4. OPTIONAL EXTRAS ---------------------------------------------------
   Each card SHOWS its product above the words: a mini browse list with the
   Featured card pinned on top (amber here is the Featured treatment itself —
   the COLOUR law's "sells it" allowance), and a draft → polished rewrite. */
.pr-extras { padding: var(--s16) 0; }
.pr-extra-grid { display: grid; grid-template-columns: 1fr; gap: var(--s6); }
@media (min-width: 800px) { .pr-extra-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.pr-extra {
  display: flex; flex-direction: column; overflow: hidden;
  background: #fff; border: 1px solid var(--slate-300); border-radius: var(--r-lg);
}
.pr-extra-demo {
  display: flex; flex-direction: column; justify-content: center; gap: var(--s2);
  min-height: 220px; padding: var(--s6) var(--s8);
  background: var(--slate-100); border-bottom: 1px solid var(--slate-200);
}
.pr-extra-body { padding: var(--s6); }
/* A lone extra (AI Listing Pro is switched off on live — see
   hcc_ai_features_enabled()) spans the row as a side-by-side card: demo left,
   words right. Half-width would strand an empty column; full-width stacked
   would stretch the mini list across 1120px. :only-child keeps the switch in
   PHP alone. */
@media (min-width: 800px) {
  .pr-extra:only-child { grid-column: 1 / -1; display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
  .pr-extra:only-child .pr-extra-demo { border-bottom: 0; border-right: 1px solid var(--slate-200); }
  .pr-extra:only-child .pr-extra-body { align-self: center; padding: var(--s10); }
  .pr-extra:only-child .pr-extra-body > p { font-size: var(--t-body); max-width: 46ch; }
}
.pr-extra-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s1) var(--s4); margin-bottom: var(--s3); }
.pr-extra h3 { font-size: var(--t-lede); font-weight: var(--w-bold); letter-spacing: -.02em; }
.pr-extra-price { font-size: var(--t-price); font-weight: var(--w-hvy); letter-spacing: -.02em; color: var(--slate-900); }
.pr-extra-price span { font-size: var(--t-meta); font-weight: var(--w-body); letter-spacing: 0; color: var(--slate-500); }
.pr-extra-body > p { font-size: var(--t-meta); color: var(--slate-600); line-height: 1.6; }

.pr-mini {
  display: flex; align-items: center; gap: var(--s3); padding: var(--s2);
  background: #fff; border: 1px solid var(--slate-200); border-radius: var(--r-md);
}
.pr-mini:not(.is-featured) { opacity: .75; }
.pr-mini.is-featured { border-color: var(--amber-200); box-shadow: 0 0 0 1px var(--amber-100); }
.pr-mini-photo { flex-shrink: 0; width: 64px; height: 44px; border-radius: var(--r-sm); background: var(--slate-200); }
.pr-mini.is-featured .pr-mini-photo { background: url('images/featured-dentist.jpg') center / cover var(--slate-200); }
.pr-mini-lines { flex: 1; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.pr-mini-lines b { display: block; width: 72%; height: 8px; border-radius: 2px; background: var(--slate-300); }
.pr-mini-lines i { display: block; width: 44%; height: 6px; border-radius: 2px; background: var(--slate-200); }

.pr-draft { background: #fff; border: 1px solid var(--slate-200); border-radius: var(--r-md); padding: var(--s4); }
.pr-draft-label {
  display: block; font-size: 10px; font-weight: var(--w-bold);
  letter-spacing: .06em; text-transform: uppercase; color: var(--slate-500);
}
.pr-draft-label--after { margin-top: var(--s4); padding-top: var(--s3); border-top: 1px dashed var(--slate-300); color: var(--navy-600); }
.pr-draft-before { margin-top: var(--s1); font-size: var(--t-meta); color: var(--slate-500); line-height: 1.5; }
.pr-draft-after  { margin-top: var(--s1); font-size: var(--t-meta); font-weight: var(--w-med); color: var(--slate-900); line-height: 1.5; }

/* ---- 5. FAQ — <details>, no JS ------------------------------------------- */
.pr-faq { padding: var(--s16) 0; border-top: 1px solid var(--slate-200); }
.pr-faq-grid { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); gap: var(--s6) var(--s16); align-items: start; }
@media (max-width: 899px) { .pr-faq-grid { grid-template-columns: 1fr; } }
.pr-faq-list details { border-bottom: 1px solid var(--slate-200); }
.pr-faq-list details:first-child { border-top: 1px solid var(--slate-200); }
.pr-faq-list summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s4);
  min-height: 56px; padding: var(--s3) 0;
  font-size: var(--t-body); font-weight: var(--w-semi); color: var(--slate-900);
}
.pr-faq-list summary::-webkit-details-marker { display: none; }
.pr-faq-list summary::after {
  content: ""; flex-shrink: 0; width: 8px; height: 8px; margin-right: var(--s1);
  border-right: 2px solid var(--slate-500); border-bottom: 2px solid var(--slate-500);
  transform: translateY(-2px) rotate(45deg); transition: transform .15s;
}
.pr-faq-list details[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.pr-faq-list summary:hover { color: var(--navy-700); }
.pr-faq-list details p { padding-bottom: var(--s6); max-width: 62ch; font-size: var(--t-body); color: var(--slate-600); line-height: 1.65; }
@media (prefers-reduced-motion: reduce) { .pr-faq-list summary::after { transition: none; } }

/* ---- 6. CLOSING CTA ------------------------------------------------------ */
.pr-close { padding-top: var(--s8); }
.pr-close-card {
  display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); overflow: hidden;
  background: var(--navy-700); border-radius: var(--r-lg); color: #fff;
}
.pr-close-body { padding: var(--s12); }
.pr-close h2 { font-size: var(--t-stmt); font-weight: var(--w-hvy); letter-spacing: -.025em; line-height: 1.1; color: #fff; }
.pr-close-steps { display: flex; flex-direction: column; gap: var(--s3); margin: var(--s6) 0 var(--s8); }
.pr-close-steps li { display: flex; align-items: center; gap: var(--s3); font-size: var(--t-body); color: var(--navy-100); }
.pr-close-steps span {
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--r-sm);
  border: 1px solid rgba(255,255,255,.3);
  font-size: var(--t-meta); font-weight: var(--w-bold); color: #fff; font-variant-numeric: tabular-nums;
}
.pr-close .hcc-btn--primary { background: #fff; color: var(--navy-700); }
.pr-close .hcc-btn--primary:hover { background: var(--slate-100); }
.pr-fine { margin-top: var(--s4); font-size: var(--t-micro); color: var(--navy-200); }
.pr-close-media { position: relative; min-height: 320px; }
.pr-close-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 899px) {
  .pr-close-card { grid-template-columns: 1fr; }
  .pr-close-media { order: -1; min-height: 0; aspect-ratio: 16 / 9; }
  .pr-close-body { padding: var(--s8) var(--s6); }
}
@media (max-width: 599px) { .pr-close h2 { font-size: 33px; line-height: 1.15; } }
