/* ==========================================================================
   HDC — WordPress-specific additions.

   ⚠️ The chrome (header, drawer, footer) is NOT styled here. It comes from
   base.css + chrome.css — the approved mockup stylesheets consolidated verbatim,
   loaded in their original cascade order. An earlier pass hand-rewrote those rules
   "close enough" and drifted on the header grid, logo size, search field, search
   button and the entire footer. Do not reintroduce chrome rules here; fix
   chrome.css instead.

   This file is only for things WordPress needs that a static prototype didn't:
   accessibility utilities, editor output, and template glue.

   Loads last, so it can override the design layer where genuinely necessary.
   Tokens only — no raw hex, no magic px.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Accessibility utilities the prototype never needed
   -------------------------------------------------------------------------- */
.screen-reader-text {
  border: 0;
  clip-path: inset(50%);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
  word-wrap: normal !important;
}

.screen-reader-text.skip-link:focus {
  clip-path: none;
  height: auto;
  width: auto;
  margin: 0;
  z-index: 200;
  top: var(--hdc-space-3);
  left: var(--hdc-space-3);
  display: block;
  padding: var(--hdc-space-3) var(--hdc-space-4);
  background: var(--hdc-surface);
  color: var(--hdc-color-heading);
  border-radius: var(--hdc-radius-sm);
  box-shadow: var(--hdc-shadow-2);
  font-family: var(--hdc-font-ui);
  font-size: var(--hdc-fs-300);
  text-decoration: none;
}

/* --------------------------------------------------------------------------
   Template glue
   -------------------------------------------------------------------------- */
/* GeneratePress makes #content.site-content a flex ROW (for its content+sidebar
   layout). Our custom single templates output a full-bleed <article> with no
   sidebar; as a flex item with flex-grow:0 it collapses to its content width
   (the .container measure, from its children) and sits LEFT-aligned — leaving dead
   space on the right and misaligning with the centered header/footer. Let the
   article fill the row so its .container children center like the chrome's. */
.site-content > article, .site-content > main { flex: 1 1 auto; min-width: 0; }

/* GeneratePress gives .site-main a 20px margin (its content↔sidebar gutter) and a
   20px bottom margin to each of its children. Our page.php <main class="site-main">
   is a full-bleed section stack with no sidebar, so that margin shows as a dead 20px
   strip down the right of every page and a 20px band of page-background beneath each
   section. Zero both — the sections own their vertical rhythm through their own
   padding. */
.site-content > main.site-main { margin: 0; }
.site-content > main.site-main > * { margin-bottom: 0; }

/* GeneratePress styles content-area <a> and <button> on :hover / :focus (both
   specificity 0,1,1): a dark label color AND a dark background. Those beat the
   design layer's base .btn { background: var(--_bg); color: var(--_fg) } (0,1,0),
   so on hover primary buttons went dark, labels went dark, and ghost buttons
   filled dark with a blue label. Re-route all three paint properties through the
   variant custom props on every interactive state at 0,2,0 so GP can never inject
   its own color — every .btn / .btn--* hover is then driven purely by the
   --_bg/--_fg/--_bd the design layer already sets. */
.btn:link, .btn:visited, .btn:hover, .btn:focus, .btn:active {
  background: var(--_bg);
  color: var(--_fg);
  border-color: var(--_bd);
}

/* Same defect, every OTHER button in content. GP's button:hover / :focus (0,1,1)
   beats any component's single-class base rule, so a bare <button> gets repainted
   #3f4047/white — which is how the carousel arrows went white-on-white once
   clicked and the video facade went black-on-black.

   This has now bitten four separate components, so it is fixed once here rather
   than re-pinned in each: every content button paints from the same --_bg/--_fg
   custom props .btn already uses. A component declares them once in its base rule
   and every state follows automatically. Anything that declares neither stays
   transparent with inherited text — GP's grey can never appear.

   border-color is deliberately NOT routed: several controls set a real border and
   only their color needs defending.

   ⚠️ THE SCOPE IS BY LOCATION, WHICH IS THE WEAK PART. GP's repaint is unscoped, so
   it reaches any <button> on the page; this defence only reaches buttons inside
   .site-content. The corner slot prints on wp_footer — outside it — and became the
   fifth component to get repainted grey-on-hover, this time on the one control that
   reopens it. Any future component that renders outside .site-content has to be
   added here too, or it inherits the same bug. */
.site-content button:not(.btn),
.site-content button:not(.btn):hover,
.site-content button:not(.btn):focus,
.site-content button:not(.btn):focus-visible,
.site-content button:not(.btn):active,
.cslot button:not(.btn),
.cslot button:not(.btn):hover,
.cslot button:not(.btn):focus,
.cslot button:not(.btn):focus-visible,
.cslot button:not(.btn):active {
  background: var(--_bg, transparent);
  color: var(--_fg, inherit);
}

/* THIRD shape, and the one that keeps slipping through. The two rules above cover
   a CLASS (.btn) and an ELEMENT (<button>). The site also has links styled as
   buttons with their own component class — an <a class="feature-card__btn"> is
   neither, so it inherits GP's generic a:hover color and the label goes dark.
   That is exactly how "Explore Community" broke.

   Listed here, once, rather than re-pinned in each component — same reasoning as
   the <button> rule above. A component joins this list and declares --_bg/--_fg;
   it never needs its own :hover color defense again.

   If you add a new link-button class, add it here. Better still, use .btn. */
.site-content a.feature-card__btn,
.site-content a.feature-card__btn:link,
.site-content a.feature-card__btn:visited,
.site-content a.feature-card__btn:hover,
.site-content a.feature-card__btn:focus,
.site-content a.feature-card__btn:active,
.site-content a.home-card__cta,
.site-content a.home-card__cta:link,
.site-content a.home-card__cta:visited,
.site-content a.home-card__cta:hover,
.site-content a.home-card__cta:focus,
.site-content a.home-card__cta:active {
  background: var(--_bg, transparent);
  color: var(--_fg, inherit);
}

/* FOURTH place GP's button repaint slips through: buttons OUTSIDE .site-content.
   The rules above only defend `.site-content button:not(.btn)`, so the header
   search dropdown — which lives in #topnav, not .site-content — went unprotected
   and GP's grey leaked in on hover. Same mechanism, scoped to the megasearch panel:
   paint every state from --_bg/--_fg. Any future region with bare buttons (footer,
   drawer) joins this selector list rather than re-pinning per component. */
.megasearch button:not(.btn),
.megasearch button:not(.btn):hover,
.megasearch button:not(.btn):focus,
.megasearch button:not(.btn):focus-visible,
.megasearch button:not(.btn):active {
  background: var(--_bg, transparent);
  color: var(--_fg, inherit);
}
/* The dropdown's bare buttons now declare --_bg/--_fg so the defense has something
   to paint (they set `background` directly before, which is why hover broke). */
.megasearch .rchip { --_bg: var(--hdc-surface); --_fg: var(--hdc-color-heading); }
.megasearch .rchip:hover { --_fg: var(--hdc-color-primary); }
.megasearch .msr-chip button { --_bg: transparent; }

/* Typo-correction note — "Showing results for X (you typed …)". Correction is never silent. */
.msr-corrected { font-family: var(--hdc-font-ui); font-size: var(--hdc-fs-300); color: var(--hdc-color-heading);
  padding: 0 0 var(--hdc-space-3); }
.msr-corrected b { color: var(--hdc-color-primary); font-weight: var(--hdc-fw-semi); }
.msr-corrected span { color: var(--hdc-color-muted); }
.msr-chip__near { color: var(--hdc-color-muted); font-weight: var(--hdc-fw-regular); }

/* Reserve the scrollbar gutter permanently so hiding the scrollbar on lock (below) doesn't
   widen the page and shift everything ~15px. No-op for overlay scrollbars (macOS default). */
html { scrollbar-gutter: stable; }

/* Page-scroll lock while the search pane or menu drawer is open — stops the background
   from scrolling when you mean to scroll inside the pane (notes.txt, esp. mobile). The
   pane keeps its own overflow:auto, so only the page behind it is frozen. With the stable
   gutter above, the scrollbar's space stays reserved so there's no width jump. */
/* ⚠️ SCOPED TO FIXED HEADERS ONLY. This used to be unconditional, and it broke the
   mega menu on every solid-header page: .topnav.is-static is position:STICKY, and
   sticky dies the moment an ancestor gets overflow:hidden. So opening the menu
   dropped the header back to its document position at the top of the page and took
   the drawer with it — scrolled down, you clicked the hamburger and nothing
   appeared. Measured at -1568px off-screen on /communities/.
   Transparent-header pages use position:fixed, which is immune, so they keep the
   lock. On the rest the page can scroll behind the dimmed backdrop, which is a far
   smaller problem than a menu that cannot be seen. */
html.hd-locked:has(#topnav:not(.is-static)),
html.hd-locked:has(#topnav:not(.is-static)) body { overflow: hidden; }

/* Dropdown height: home-v2.css re-positions .megasearch to absolute (attached under
   the field), so megasearch.css's max-height (tuned for the fixed variant, top near 0)
   overshoots and the last results fall below the fold. Cap to what fits under the
   header; it already scrolls (overflow:auto). */
.megasearch { max-height: calc(100vh - 10rem); }

/* Sticky footer. Short pages otherwise end at the footer and expose the <html>
   background below it — which reads as a white bar under the dark footer. */
html { background: var(--hdc-surface-ink); }
/* Warm page base. Was set by homepage-v3 (body { background: surface-warm }),
   which is no longer loaded sitewide — declared here so the warm base survives. */
body { display: flex; flex-direction: column; min-height: 100vh; background: var(--hdc-surface-warm); }
/* The warm base ALSO sits on .site-content, so <body>'s own colour is never seen
   between the header and the footer — which frees it to steer iOS 26 Safari's
   status-bar tint (it reads <body>'s background, not theme-color): ink while the
   header is transparent over a hero, warm again once chrome.js drops the class
   as the header turns solid. See the theme-color note in inc/chrome.php. */
.site-content { flex: 1 0 auto; background: var(--hdc-surface-warm); }
body.hdc-over-hero { background: var(--hdc-surface-ink); }
.site-footer { flex-shrink: 0; }

/* --------------------------------------------------------------------------
   Header on pages WITHOUT a photo hero.

   The design layer makes .topnav transparent by default and relies on .is-solid
   (scrolled) or .menu-open (drawer) to solidify it. That is correct for the
   homepage, where a hero sits behind it — but on a page with no hero it renders
   a white logo and white utility links on a white background.

   .is-static is set server-side by hdc_header_is_transparent(). It reuses the
   .menu-open look — solid, but WITHOUT collapsing the utility bar, which is the
   scrolled behavior and wrong at rest.

   Selectors carry the same :not() chain as the design layer purely to win on
   specificity; the design rules are (0,4,1) and these are (0,5,1).
   -------------------------------------------------------------------------- */
.topnav.is-static {
  position: sticky;                      /* not fixed — there is no hero to overlay */
  background: var(--hdc-surface);
  box-shadow: var(--hdc-shadow-1);
}
.topnav.is-static:not(.is-solid):not(.menu-open) .utilbar a { color: var(--hdc-color-muted); }
.topnav.is-static:not(.is-solid):not(.menu-open) .brand img { filter: none; }
.topnav.is-static:not(.is-solid):not(.menu-open) .hamburger { color: var(--hdc-color-heading); }

/* Scrolled state on these pages should still collapse the utility bar, so the
   design layer's .is-solid keeps working untouched. */

/* --------------------------------------------------------------------------
   GeneratePress form/button reset for our chrome.

   The prototype never had a parent theme under it. GP styles bare elements —
   input[type=text] {border;radius;padding;background} and
   button {background:#55555e;color:#fff;padding} — and `input[type=text]` is
   (0,1,1), which BEATS the design layer's `.headersearch__input` at (0,1,0).
   That is what put a grey rectangle inside the rounded search pill.

   These selectors are deliberately over-specific to win, and do nothing except
   restore the approved design.
   -------------------------------------------------------------------------- */
.headersearch input[type="text"].headersearch__input {
  border: 0;
  border-radius: 0;
  background: transparent;
  padding: var(--hdc-space-2) 2px;
  max-width: none;
  font-family: var(--hdc-font-ui);
  font-size: var(--hdc-fs-300);
  line-height: var(--hdc-lh-body);
}
.headersearch input[type="text"].headersearch__input:focus {
  outline: 0;
  box-shadow: none;
}
/* Touch screens: fs-400 (16px), not fs-300. iOS Safari zooms the page into any
   focused field under 16px and leaves it zoomed, so the page scrolls sideways
   (Carter, 10/2). Every Fluent form field is already 16px; this was the only one
   under it. It lives HERE, with the same over-specific selector, because this rule
   is what sets the size — a plain .headersearch__input override lost to it. Keyed
   to touch rather than width: an iPad zooms too. */
@media (hover: none) and (pointer: coarse) {
  .headersearch input[type="text"].headersearch__input { font-size: var(--hdc-fs-400); }
}

/* Buttons in the chrome are not GP buttons. */
.headersearch__go,
.hamburger,
.hdmenu button {
  -webkit-appearance: none;
  appearance: none;
  border: 0;
  font-family: var(--hdc-font-ui);
  line-height: 1;
}
.hamburger,
.hamburger:hover,
.hamburger:focus,
.hamburger:active {
  background: transparent;
  padding: 0;
  box-shadow: none;
}
.hamburger:focus-visible {
  outline: 2px solid var(--hdc-color-primary);
  outline-offset: 2px;
}
.headersearch__go:hover { background: var(--hdc-color-primary-deep); }

/* --------------------------------------------------------------------------
   Utility bar links go brand blue on hover.

   The design layer only sets this for the SOLID header
   (homepage-v2.css: .utilbar a:hover), so over a photo hero — and on
   .is-static pages, which use a different color chain — the hover was doing
   nothing. Covers all three header states.
   -------------------------------------------------------------------------- */
.topnav .utilbar a:hover,
.topnav .utilbar a:focus-visible,
.topnav.is-static:not(.is-solid):not(.menu-open) .utilbar a:hover,
.topnav:not(.is-solid):not(.menu-open) .utilbar a:hover {
  color: var(--hdc-color-primary);
}

/* --------------------------------------------------------------------------
   Hamburger color.

   home-v2.css turns it white with
     .topnav:not(.is-solid):not(:hover):not(.menu-open) .hamburger
   which is right over a photo hero. But the moment the header is SOLID — either
   scrolled, or with the drawer open — the icon sits on a near-white surface and
   must be dark. Stated explicitly rather than relying on the base rule winning,
   because the white rule and our .is-static rule have identical specificity.
   -------------------------------------------------------------------------- */
.topnav.is-solid .hamburger,
.topnav.menu-open .hamburger,
.topnav.is-static:not(.is-solid) .hamburger {
  color: var(--hdc-color-heading);
}

/* Chips were re-pinned here per component (.siteplan .chip, .plan-explorer
   .plan-chip) back when they painted with plain `background`. That block is gone:
   it sat at (0,3,0) and beat the shared .chip.is-on at (0,2,0), while loading
   last — so the component's own active state could never win. The symptom was a
   chip with THREE appearances: white while focused, light blue once blurred, and
   the real fill only in the instant between.

   .chip / .plan-chip now declare --_bg/--_fg and the generic
   `.site-content button:not(.btn)` rule above paints every state from them. One
   mechanism, no per-component pins — which is what that rule was always for. */

/* The plan/video tabs are bare <button>s too, and GP paints a dark background
   AND a dark label on button:hover (0,1,1). A tab has no fill by design, so the
   background must be pinned transparent on every state, not just recolored. */
.plan-explorer .plan-tab,
.plan-explorer .plan-tab:hover,
.plan-explorer .plan-tab:focus,
.plan-explorer .plan-tab:active {
  background: transparent;
  color: var(--hdc-color-muted);
}
.plan-explorer .plan-tab:hover,
.plan-explorer .plan-tab:focus {
  color: var(--hdc-color-primary);
}
.plan-explorer .plan-tab.is-on,
.plan-explorer .plan-tab.is-on:hover,
.plan-explorer .plan-tab.is-on:focus {
  color: var(--hdc-color-heading);
}

/* And the video facade, which is the same defect with more surface area: a bare
   <button> the size of the media column, so GP's button:hover filled the whole
   thing #3f4047 behind the poster. Its own hover affordance is the play badge
   lighting up — the plate underneath never changes. */
.plan-explorer .plan-video,
.plan-explorer .plan-video:hover,
.plan-explorer .plan-video:focus,
.plan-explorer .plan-video:active {
  background: var(--hdc-surface-tint);
  color: var(--hdc-color-heading);
}

/* Same GP problem, same technique, for the mobile "Show all N lots" toggle — also
   a bare <button>. Its own design (community.css) keeps the label primary-colored
   at rest and only swaps the background on hover, so — unlike the chips above —
   that is what gets re-declared here rather than reusing the chips' values. */
.siteplan__more,
.siteplan__more:hover,
.siteplan__more:focus {
  color: var(--hdc-color-primary);
}
.siteplan__more { background: var(--hdc-surface); }
.siteplan__more:hover,
.siteplan__more:focus {
  background: var(--hdc-surface-warm);
}

/* --------------------------------------------------------------------------
   Homepage carousel controls vs GeneratePress element defaults.

   GP darkens bare <button> backgrounds on :hover/:focus (0,1,1), which beats the
   design layer's base background (0,1,0) — the Featured Homes, Custom Collection
   and Reviews arrows all turned dark on hover. Re-assert each control's own
   resting background at 0,2,0; the intended blue border/label on hover already
   comes from the design layer. Tokens only — values mirror the base rules.
   -------------------------------------------------------------------------- */
.fh-arrow:hover, .fh-arrow:focus,
.rev__arrow:hover, .rev__arrow:focus { background: var(--hdc-surface); }

/* Custom Collection arrows: match the Featured Homes / Reviews arrows — a solid
   white disc with a hairline border that goes blue (border + glyph) on hover —
   instead of the translucent overlay chip. They keep the design layer's absolute
   position over the image; only the paint changes. */
.cc-arrow { background: var(--hdc-surface); border: 1px solid var(--hdc-line-strong); color: var(--hdc-color-heading); }
.cc-arrow:hover, .cc-arrow:focus { background: var(--hdc-surface); border-color: var(--hdc-color-primary); color: var(--hdc-color-primary); }

/* The Custom Collection CTA is now the canonical .btn--on-dark; restore only the
   spacing the bespoke .cc-btn used to carry. */
.cc-cta { margin-top: var(--hdc-space-6); }

/* --------------------------------------------------------------------------
   Reviews + Custom Collection: server-rendered slides, JS-enhanced carousels.

   Both partials emit every slide as real markup with the first carrying
   .is-active; home.js adds .is-enhanced and pages through by toggling .is-active.
   With no JS the first slide shows (crawlable) and the inert nav hides — the same
   progressive-enhancement shape the Featured Homes carousel already uses.
   -------------------------------------------------------------------------- */

/* Reviews. GP gives a bare <blockquote> a left rule + indent the mockup never had —
   strip them; type dialled down a step from the design layer's clamp so the long
   quotes sit calmer. font-style is the same story: GP italicises blockquotes, and
   it now matters more than it did, because Literata ships a TRUE italic where Prata
   had none — the browser was previously faking a slant and is now drawing real
   cursive letterforms. Upright is what the mockup showed either way. */
.rev__quote { border: 0; padding: 0; font-style: normal;
  font-size: clamp(1.5rem, 1rem + 2vw, 2.3rem); }
.rev__item { margin: 0; }
.rev__item:not(.is-active) { display: none; }
/* home.js locks the stage to the tallest testimonial so the section keeps a
   constant height while paging; the flex column centers the shorter quotes in it. */
.rev__stage { display: flex; flex-direction: column; justify-content: center; }
.rev:not(.is-enhanced) .rev__nav { display: none; }

/* Custom Collection. Copy slides and images are two index-synced lists; only the
   active one of each shows. Images stack absolutely so they swap in place inside
   the fixed-height stage.

   Both were display:none, i.e. an instant cut. They now transition — but by two
   different mechanisms, on purpose:

   IMAGES cross-fade. They are absolutely stacked, so both can be visible at once
   and the outgoing one fades under the incoming. visibility is transitioned
   alongside opacity (0s, delayed to the end) so a faded-out image leaves the
   accessibility tree and stops catching clicks instead of sitting invisible on
   top of the arrows.

   COPY animates in only. Text slides are in normal flow, so stacking them to
   cross-fade would need a fixed height and would jump whenever two slides have
   different copy lengths. The outgoing one leaves immediately and the incoming
   one rises 8px into place, which reads as a change without any layout risk. */
.cc-slide:not(.is-active) { display: none; }
/* Shared with the reviews carousel (.rev__item), which is structurally the same
   thing: one text slide visible at a time, in normal flow. Renamed off the cc-
   prefix now that two components use it — a keyframe named after one of its
   callers is the kind of thing that gets duplicated rather than reused. */
.cc-slide.is-active,
.rev__item.is-active { animation: hdc-slide-in var(--hdc-dur-slow) var(--hdc-ease) both; }
@keyframes hdc-slide-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

.cc-img { position: absolute; inset: 0;
  opacity: 0; visibility: hidden;
  transition: opacity var(--hdc-dur-slow) var(--hdc-ease),
              visibility 0s linear var(--hdc-dur-slow); }
.cc-img.is-active { opacity: 1; visibility: visible;
  transition: opacity var(--hdc-dur-slow) var(--hdc-ease), visibility 0s; }

/* A carousel that fades and rises is exactly the kind of motion this setting
   exists for. Both revert to the instant swap. */
@media (prefers-reduced-motion: reduce) {
  .cc-slide.is-active, .rev__item.is-active { animation: none; }
  .cc-img, .cc-img.is-active { transition: none; }
}
.cc-band:not(.is-enhanced) .cc-dots,
.cc-band:not(.is-enhanced) .cc-arrow { display: none; }
