/*
 * Site Hero — Immersive Visual (HERO-03) — self-contained isolated-
 * preview copy. Canonical runtime source is
 * adapters/wordpress/generation/generation.css /
 * adapters/wordpress/generation/generation-hhds.css (kept in sync by
 * hand, same convention as sections/site-header/site-header.css).
 *
 * This file is generation-hhds.css in full (Path B's own real design
 * system, which every shared primitive this family uses already lives
 * in) plus components/rating-stars/rating-stars.css inlined verbatim
 * (the one real .lib-* dependency generation.css itself pulls in via
 * LIBRARY_INLINES, not part of generation-hhds.css) -- a curated
 * per-selector extraction was tried first and silently dropped rules
 * nested inside @media blocks (indentation mismatch); copying the real
 * source files whole is correct by construction instead.
 *
 * Real evidence: HH Digital Studio's full-bleed photo + Maggy Prestige
 * Fit's full-bleed video — two independent projects arriving at the
 * same media-first architecture (Hero Convergence Audit Step 1,
 * Sections 4/5/16). Built entirely on the Step 2/3A Hero Background
 * primitive (image|video) plus the Hero Authority/Proof primitive and
 * foundational components — see catalog/governance/
 * HERO_CONVERGENCE_AUDIT.md, Hero System Step 3B.
 */

/*
 * generation-hhds.css — Path B's own, independent design system: the
 * `.hhds-*` classed HTML that adapters/wordpress/generation/
 * section-renderer.php builds straight from page-data props (Website
 * Factory Stage 10 generation), separate from Path A's raw hh-theme
 * template-parts which call the real `.lib-*` component/section CSS
 * directly (see sections/service-cta/README.md for the two-path
 * distinction). There is no canonical `.lib-*` source for what's in this
 * file to drift from -- THIS file is that source for Path B.
 *
 * This is a real, hand-edited source file, not a generated artifact --
 * edit it directly. It gets concatenated into the final
 * adapters/wordpress/generation/generation.css by
 * scripts/factory-generate-adapter-css.js, which also inlines a handful
 * of real `.lib-*` component/pattern files that section-renderer.php
 * intentionally reuses verbatim (see that script for the exact list).
 * Never hand-edit generation.css itself -- `npm run qa:adapter-drift`
 * fails the build if it stops matching what this file + those library
 * sources would generate.
 *
 * Base reset — this stylesheet is self-contained (the generation adapter's
 * own output, independent of the Path A `[data-lib-root]`/foundation.css
 * convention used by raw hh-theme templates - see sections/service-cta/
 * README.md for that distinction). Every hhds-* element (header, page
 * main, footer) needs box-sizing: border-box or width + padding-inline
 * combinations (e.g. .hhds-container) overflow the viewport. Found via
 * `npm run qa:responsive` against Michelle's Nails Service real site -
 * 17-18px horizontal overflow at 360/390px that a desktop screenshot
 * alone never surfaced.
 */
*,
*::before,
*::after {
  box-sizing: border-box;
}

.hhds-page {
  overflow: clip;
  color: var(--lib-text-primary);
  background: var(--lib-surface-page);
  font-family: var(--lib-font-body);
}

/* Real bug fixed here during Human Visual Correction pass 4
   (2026-08-25) -- see sections/hero-split/hero-split.css's identical
   fix for the full real root-cause explanation (missing explicit color
   meant foreground text depended on ambient inheritance instead of its
   own section). Same fix applied here and in generation-hhds.css
   (Path B). */
.hhds-section {
  position: relative;
  width: 100%;
  padding-block: var(--lib-space-section-y);
  background: var(--lib-surface-page);
  color: var(--lib-text-primary);
}

.hhds-section:nth-of-type(even) {
  background: var(--lib-surface-section);
}

.hhds-section[data-surface="SURFACE"] {
  background: var(--lib-surface-page);
}

.hhds-section[data-surface="PANEL"] {
  background: var(--lib-surface-section);
}

/*
 * Governance correction pass 8 (2026-08-26): a data-surface="DARK"
 * section stays deliberately, permanently dark regardless of Canvas --
 * that disposition is unchanged (catalog/governance/
 * CANVAS_AUTHORITY_MODEL.md's own, still-open "data-surface=DARK"
 * section). --lib-gradient-hero-media-scrim's DEFAULT value is now
 * Canvas-driven (core/tokens.css, keyed to --lib-color-surface, for a
 * Hero composed on a SURFACE/PANEL section, HERO-01's own real case) --
 * a Hero composed on a DARK section instead needs its media scrim to
 * match that same permanent-dark disposition, not flip to a light wash
 * under Canvas: Light while its own outer section stays dark. Locally
 * overriding the custom property here, scoped to [data-surface="DARK"],
 * restores the exact original --lib-color-deep-based gradient for that
 * one real case -- zero visual change for HERO-03 (this file's own
 * canonical Hero, always data-surface="DARK"), whether Canvas is Light
 * or Dark.
 *
 * --lib-color-inverse/-deep deliberately NOT migrated across this whole
 * [data-surface="DARK"] block and its descendants below: this is the
 * literal, canonical example CANVAS_AUTHORITY_MODEL.md itself documents
 * as the legitimate, page-author-set fixed-dark case (distinct from a
 * Component unilaterally hardcoding its own theme) -- see "Semantic
 * surface responsibility" in that file.
 */
.hhds-section[data-surface="DARK"] {
  --lib-gradient-hero-media-scrim: linear-gradient(
    180deg,
    color-mix(in srgb, var(--lib-color-deep) 90%, transparent) 0%,
    color-mix(in srgb, var(--lib-color-deep) 68%, transparent) 45%,
    color-mix(in srgb, var(--lib-color-deep) 75%, transparent) 100%
  );
  /* Real regression this pass found and fixed (see core/tokens.css's
     own note on --lib-hero-attached-foreground): a Hero-attached Trust
     Band here needs inverse, matching this section's own permanent-dark
     identity, not the Canvas-driven ink its token would otherwise
     resolve to by default. */
  --lib-hero-attached-foreground: var(--lib-color-inverse);
  color: var(--lib-color-inverse);
  background: var(--lib-gradient-deep);
}

.hhds-section[data-surface="DARK"] :is(.hhds-section__title, .hhds-section__summary, .hhds-section__notice) {
  color: var(--lib-color-inverse);
}

.hhds-section[data-surface="DARK"] .hhds-section__eyebrow {
  color: var(--lib-color-inverse);
}

.hhds-section[data-surface="SURFACE"]:has(+ .hhds-section[data-surface="SURFACE"]),
.hhds-section[data-surface="PANEL"]:has(+ .hhds-section[data-surface="PANEL"]) {
  border-bottom: var(--lib-space-hairline) solid var(--lib-border-default);
}

.hhds-container {
  width: var(--lib-container-wide);
  margin-inline: auto;
  padding-inline: var(--lib-gutter);
}

/*
 * HARD RULE, 2026-08-12: section headers use the real container width,
 * never an arbitrary character/rem cap. Real owner incident
 * (michelles-nails-website): a section shipped with the title/summary
 * capped at 52rem/20ch inside a "wide" (up to 112.5rem) container -
 * looked stuck to the left with most of the screen blank. Fixed there
 * with a scoped override, then the SAME bug turned up independently in a
 * second, unrelated section on the same page because the cap lived here,
 * in the shared default, not in that one section. Owner explicitly
 * ordered this "completamente prohibido en el sistema" - fixed at the
 * true source instead of patching section by section. max-width: 100% /
 * none here means "as wide as the container already decided to be" (wide
 * vs standard is still controlled by presentation.container per section)
 * - not literally unbounded.
 */
.hhds-section__header {
  max-width: 100%;
  margin-bottom: var(--lib-space-10);
}

.hhds-section__eyebrow {
  margin: 0 0 var(--lib-space-4);
  color: color-mix(in srgb, var(--lib-text-brand) 45%, var(--lib-text-primary));
  font-size: var(--lib-font-size-caption);
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.hhds-section__title {
  max-width: none;
  margin: 0;
  font-family: var(--lib-font-heading);
  font-size: clamp(2rem, 5vw, 4.5rem);
  line-height: 1.02;
  letter-spacing: -0.04em;
  text-wrap: balance;
}

/* Web Build System "Title keyword emphasis" LAW - one brand-colored anchor
   phrase per h1/h2/h3. Applied by hhds_render_title_markup() in
   section-renderer.php, never authored as raw HTML. */
/* Scoped to hero sections (2026-10-09): unscoped, this rule leaked the
   accent color onto every highlight on the page and failed WCAG contrast on
   light sections. Other sections use the foundation default. */
.hhds-section .hhds-title-highlight {
  color: var(--lib-text-accent);
}

/*
 * Real finding (Hero System Step 3B, via qa:component's axe:color-
 * contrast check on HERO-01, a light-surface hero): --lib-color-accent
 * measures 2.75:1 against --lib-color-surface --
 * fails WCAG AA's 4.5:1 threshold for normal text. Not specific to
 * Hero -- any section using this shared highlight on a light surface
 * has the same real defect; HERO-01 is simply the first registered,
 * qa:component-verified consumer to combine them. --lib-color-primary
 * (5.44:1) passes with real margin and still reads as visually
 * distinct from --lib-color-ink body text, unlike --lib-color-primary-
 * strong (10.26:1, but close enough to ink to lose the "highlight"
 * distinction). Scoped to light/panel surfaces only -- dark surfaces
 * were not measured as failing and are left untouched.
 */
.hhds-section[data-surface="SURFACE"] .hhds-title-highlight,
.hhds-section[data-surface="PANEL"] .hhds-title-highlight {
  color: color-mix(in srgb, var(--lib-text-brand) 45%, var(--lib-text-primary));
}

.hhds-section__summary {
  max-width: none;
  margin: var(--lib-space-5) 0 0;
  color: var(--lib-text-secondary);
  font-size: clamp(var(--lib-font-size-base), 1.5vw, var(--lib-font-size-lead));
  line-height: 1.65;
}

.hhds-section__notice {
  max-width: var(--lib-content-measure);
  margin: var(--lib-space-5) 0 0;
  color: var(--lib-text-muted);
  font-size: var(--lib-font-size-small);
}

/*
 * Real owner request 2026-08-12: "la idea es que se vea todo el
 * contenido de hero en una sola pantalla" - with the authority band now
 * part of the hero, the old min-height: min(48rem, 82vh) (738px at a
 * common 1440x900 viewport) plus the section's own top padding pushed
 * the band below the fold (measured live: nav+hero+band needed 985px
 * against a 900px viewport - ~85px of forced scroll). Reduced to
 * min(38rem, 66vh) - real content still sets its own height when it
 * needs more (min-height, not height), this only lowers the artificial
 * floor.
 */
.hhds-hero {
  display: grid;
  align-items: center;
  gap: clamp(var(--lib-space-8), 6vw, 6rem);
  min-height: min(38rem, 66vh);
}

/*
 * Same "fit in one screen" request: .hhds-section's own padding-block
 * (clamp(3rem, 5vw, 5rem), shared by every section on the page) added
 * another 72px above the hero specifically. Trimmed for hero sections
 * only, via the same :has() scoping already used for the background/
 * authority breakout rules below - every other section's spacing
 * (services, differentiators, etc.) is untouched.
 */
.hhds-section:has(> .hhds-container > .hhds-hero) {
  padding-top: var(--lib-space-8);
}

/*
 * A hero with no media prop (no project photo assigned yet) still forces
 * min-height: min(48rem, 82vh) above - invisible on desktop's 2-column
 * layout (the empty column just isn't rendered as a visible gap), but on
 * a real mobile viewport (390x844, verified live via Playwright while
 * building the first UGS-Draft run on this project) a photo-less hero
 * measured 692px tall against an 844px viewport - mostly blank space
 * before eyebrow+H1+summary+button gives way to real content below.
 * WPS_UX_Governance_Layer.md Category 06, ADJ-01.
 */
@media (max-width: 47.99rem) {
  .hhds-hero:not(:has(.hhds-hero__media)) {
    min-height: auto;
  }
}

/*
 * Full-bleed decorative hero background image (real owner request
 * 2026-08-12: an AI-composed rose-gold texture, real negative space
 * designed for text on one side). A sibling of .hhds-hero, not a child -
 * position:absolute breaks out of .hhds-container's max-width/padding to
 * cover the FULL section edge-to-edge (the standard "100vw breakout"
 * technique: left 50% + translateX(-50%) + width 100vw, anchored to the
 * nearest positioned ancestor, which is .hhds-section itself, already
 * position:relative as its own base rule - .hhds-container has no
 * position set, so it doesn't intercept as a containing block). overflow
 * hidden on the section (scoped via :has, not global) prevents the 100vw
 * breakout from ever causing horizontal page scroll.
 */
.hhds-section:has(> .hhds-container > .hhds-hero__background) {
  overflow: hidden;
}

.hhds-hero__background {
  position: absolute;
  top: 0;
  left: 50%;
  z-index: 0;
  width: 100vw;
  height: 100%;
  transform: translateX(-50%);
  pointer-events: none;
}

.hhds-hero__background img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/*
 * Video mode of the Hero Background primitive (Hero System Step 2,
 * Part 2). Converges Maggy Prestige Fit's real video-background
 * capability. The poster <img> (already covered by the
 * ".hhds-hero__background img" rule above) is the real static base
 * layer; the <video> is absolutely positioned on top of it and is the
 * only element prefers-reduced-motion hides below -- the poster stays
 * visible underneath as a genuine fallback, not a poster="" attribute
 * on a hidden element (which would never paint).
 */
.hhds-hero__background .hhds-hero__background-video {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  max-width: 100%;
  height: 100%;
  max-height: 100%;
  object-fit: cover;
  object-position: center;
}

@media (prefers-reduced-motion: reduce) {
  .hhds-hero__background-video {
    display: none;
  }
}

/*
 * Real owner feedback 2026-08-12, same session as the gallery photos:
 * "el fondo esta muy encendido" - once the 3 gallery photos got much
 * bigger, the full-brightness background competed with them instead of
 * receding behind them. A brand-tinted flat scrim mutes the image just
 * enough that the real photos and the title read as the clear subject.
 * Kept as an exact, deliberately weaker override below for exactly that
 * gallery-present case.
 *
 * Default (no gallery competing for attention) upgraded to the real
 * --lib-gradient-hero-media-scrim token (Hero System Step 2, Part 2) --
 * a 3-stop vertical gradient, not a flat tint, calibrated specifically
 * for text-over-photo legibility with no competing visual (real
 * evidence: this token's own definition in core/tokens.css is the
 * documented combined-opacity equivalent of HH Digital Studio's own
 * original pre-library hero overlay -- see sections/service-hero-
 * section/README.md's `--media` modifier section). The flat 22% tint
 * was never right for this case; it was only ever tuned for the
 * gallery-present case below.
 */
.hhds-hero__background::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--lib-gradient-hero-media-scrim);
}

/*
 * .hhds-hero__background is a preceding sibling of .hhds-hero in the
 * DOM (see hhds_render_body()'s hero-* branch) -- CSS has no
 * prior-sibling combinator, so :has(+ ...) is how this rule reaches
 * forward to detect the gallery-bearing hero that follows it.
 */
/* --lib-color-deep deliberately NOT migrated: this scrim's whole
   purpose is guaranteeing legibility over a real photo, always dark
   regardless of Canvas by design (same established pattern as
   media-focus/skills-video's own placeholders). */
.hhds-hero__background:has(+ .hhds-hero.hhds-hero--has-gallery)::after {
  background: color-mix(in srgb, var(--lib-color-deep) 22%, transparent);
}

.hhds-hero--image-bg {
  position: relative;
  z-index: 1;
}

/*
 * Governance correction pass 8 (2026-08-26), Hero Canvas authority
 * final fix -- RETIRED. See generation-hhds.css's identical note at the
 * same location for the full reasoning: this block forced text color
 * off the `background.foreground` prop unconditionally, regardless of
 * Canvas, exactly the exception the governance model banned. HERO-03's
 * canonical preview never used `foreground` in the first place (it
 * composes on data-surface="DARK", untouched by this pass), so this
 * removal is a no-op for its own rendering -- it only retires a shared,
 * now-dead mechanism a different Hero configuration could otherwise
 * still reach.
 */

/* --lib-color-inverse deliberately NOT migrated across this modifier
   pair and its descendants below: a real, page-author-set fixed-dark
   hero identity (--hero-dark/--hero-video are explicit opt-in classes),
   the same legitimate case as service-hero-section.css's own DEFAULT
   state. */
.hhds-section--hero-dark,
.hhds-section--hero-video {
  color: var(--lib-color-inverse);
  background: var(--lib-gradient-service-hero);
  isolation: isolate;
}

.hhds-section--hero-dark::before,
.hhds-section--hero-video::before {
  position: absolute;
  z-index: -1;
  inset: 0;
  background: radial-gradient(circle at 82% 18%, color-mix(in srgb, var(--lib-surface-brand-accent) 24%, transparent), transparent 42%);
  content: "";
}

.hhds-section--hero-dark .hhds-section__summary,
.hhds-section--hero-video .hhds-section__summary {
  color: color-mix(in srgb, var(--lib-color-inverse) 78%, transparent);
}

.hhds-hero__media .hhds-media {
  min-height: 22rem;
}

/*
 * Real owner request 2026-08-12: a 3-photo rail filling the hero's empty
 * right-side grid column on desktop only ("en version desk") - one real
 * result photo per featured service, deliberately plain vertical
 * rectangles (not the organic-blob mask hhds-media uses elsewhere - "3
 * rectangulos de forma verticales" was explicit). Hidden below the same
 * 48rem breakpoint the 2-column hero grid itself collapses at, so mobile
 * never gets 3 extra eager-loaded images stacked into an already-tall
 * hero (WPS_UX_Governance_Layer.md Category 06, ADJ-01 - the same real
 * mobile-hero-height finding that shaped .hhds-hero's min-height rule
 * above).
 *
 * Sized up same day, real owner feedback on the first pass: "se ven muy
 * pequeños... aumenta casi el doble a lo alto y casi la mitad mas a lo
 * ancho" - measured the live render (lateral items ~152x203px, center
 * ~182x280px) and solved new aspect ratios directly for ~1.5x width /
 * ~2x height against the WIDER column below, rather than just bumping the
 * old 3/4 ratio (which would have grown both dimensions by the same
 * factor and missed the "almost double height" part specifically).
 * .hhds-hero--has-gallery widens the hero's 2nd grid column - the
 * original minmax(18rem, 0.85fr) had no room for the new target width at
 * any content-column size worth keeping.
 *
 * Mobile behavior upgraded (Hero System Step 2, Part 4): previously
 * display:none below 48rem, removing all 3 real photos below tablet
 * width. Audited and rejected as canonical -- content-loss is not
 * "the primitive's responsibility to hide," per the Step 2 brief. Below
 * 48rem the gallery is now a real horizontal scroll-snap row: all 3
 * photos stay in the DOM once (no duplication), each snaps to center on
 * swipe, sized relative to the viewport rather than assuming any one
 * phone width.
 */
.hhds-hero__gallery {
  display: flex;
  gap: var(--lib-space-4);
  margin-top: var(--lib-space-2);
  padding-block: var(--lib-space-1);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
}

.hhds-hero__gallery-item {
  position: relative;
  flex: 0 0 auto;
  overflow: hidden;
  width: min(70vw, 20rem);
  margin: 0;
  aspect-ratio: 4 / 5;
  border-radius: var(--lib-radius-lg);
  box-shadow: var(--lib-shadow-card-stat);
  scroll-snap-align: center;
}

.hhds-hero__gallery-item img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (min-width: 48rem) {
  /*
   * Real bug found live: .hhds-hero--has-gallery alone ties .hhds-hero,
   * .hhds-founder's specificity (one class each) - the base rule sits
   * later in this file (the shared 2-column grid block, further down)
   * and won the tie by source order, so the widened column never actually
   * applied (measured live: gallery items barely grew at all). Chaining
   * both classes on one compound selector beats it outright regardless of
   * source order.
   */
  .hhds-hero.hhds-hero--has-gallery {
    grid-template-columns: minmax(0, 1fr) minmax(24rem, 48rem);
  }

  .hhds-hero__gallery {
    display: grid;
    grid-template-columns: 1fr 1.2fr 1fr;
    align-items: center;
    gap: var(--lib-space-5);
    overflow: visible;
    scroll-snap-type: none;
  }

  .hhds-hero__gallery-item {
    width: auto;
    aspect-ratio: 4 / 7;
    scroll-snap-align: none;
  }

  /* Center item (2nd of 3) reads larger, per the owner's explicit request. */
  .hhds-hero__gallery-item:nth-child(2) {
    aspect-ratio: 1 / 2;
  }

  /*
   * Real owner correction 2026-08-12: "quiero que hagan zoom sin pasar el
   * cursor" - pointing at hhdigitalstudio.com's own service hero photo
   * (.hero-ent__photo-img, service-hero-enterprise.css), which zooms
   * continuously on its own via a plain CSS animation, never a :hover
   * trigger. The previous version here WAS a real scale-transform zoom,
   * just gated behind hover - wrong mechanism entirely for what was
   * actually asked. Matched that exact pattern: same duration, easing and
   * scale ceiling, alternating so it breathes in and out forever. A small
   * per-item animation-delay keeps the 3 photos from zooming in perfect
   * unison, which would read as robotic rather than premium. The site's
   * existing global `@media (prefers-reduced-motion: reduce)` rule
   * (.hhds-page *) already caps this animation's duration and iteration
   * count - no separate override needed here.
   */
  .hhds-hero__gallery-item img {
    /* Phase 6B.1C (2026-08-27): re-synced from generation-hhds.css (this
       file's own declared canonical source) -- ease-in-out ->
       var(--lib-motion-ease-breathe), zero value change. */
    animation: hhds-hero-gallery-zoom var(--lib-motion-duration-breathe) var(--lib-motion-ease-breathe) infinite alternate;
  }

  .hhds-hero__gallery-item:nth-child(2) img {
    animation-delay: 1.5s;
  }

  .hhds-hero__gallery-item:nth-child(3) img {
    animation-delay: 3s;
  }

  @keyframes hhds-hero-gallery-zoom {
    from {
      transform: scale(1);
    }
    to {
      transform: scale(1.1);
    }
  }
}

/*
 * Framed Visual Zone -- frame mode (Hero System Step 2, Part 4). Real
 * evidence: Empire Metal Solutions' bordered, shadowed, rounded visual
 * panel beside its hero content (Hero Convergence Audit Step 1, Section
 * 6). Visible at every width (not hidden on mobile, unlike the old
 * gallery behavior above) -- a single decorative image has no
 * duplication cost, so there's no reason to hide it; it simply stacks
 * as the hero's second grid row on narrow viewports where .hhds-hero is
 * already a single-column grid by default.
 */
.hhds-hero__frame {
  position: relative;
  overflow: hidden;
  min-height: 14rem;
  margin-top: var(--lib-space-2);
  border: var(--lib-space-hairline) solid var(--lib-color-border-card);
  border-radius: var(--lib-radius-lg);
  box-shadow: var(--lib-shadow-card-stat);
}

.hhds-hero__frame-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (min-width: 48rem) {
  .hhds-hero.hhds-hero--has-frame {
    grid-template-columns: minmax(0, 1fr) minmax(20rem, 32rem);
  }

  .hhds-hero__frame {
    min-height: 24rem;
    margin-top: 0;
  }
}

/*
 * SVC-03 Dual Spotlight -> editorial rows (EXPERIMENTAL - see
 * sections/featured-spotlight/README.md, source of truth for this rule
 * set). v1-v4 (2026-08-12, all same day) tried photo-as-background with
 * text on top, in shrinking variations - every version fought the same
 * underlying problem: a real photo behind readable text always risks
 * cropping the photo or hurting legibility, no matter how the crop/
 * contrast is tuned.
 *
 * v5 (2026-08-12, same day, real owner redesign): dropped photo-as-
 * background entirely. Two-column editorial row per item, alternating
 * sides (photo/text, then text/photo) - the real photo lives in its own
 * column at its own real proportions, using the exact organic-blob-masked
 * treatment (hhds_render_media(), PAT-016) already used elsewhere in this
 * library, not a new pattern. Title/summary/CTA live in plain page
 * background next to it - no contrast to manage, no crop to negotiate,
 * ever.
 *
 * This section's own header gets a local override on the generic
 * .hhds-section__header max-width: 52rem cap (real owner finding,
 * 2026-08-12: on a wide container the title/summary were stuck in a
 * narrow column with most of the screen blank - a width problem, not a
 * font-size problem) so the intro title/summary actually use the width a
 * "wide" container reserves. Both title and summary flow at
 * max-width: none - each line grows as wide as the real heading/body font
 * size naturally allows before wrapping, rather than an arbitrary
 * character cap that still left space unused.
 *
 * Real owner correction (2026-08-12, same day): "mucho espacio entre el
 * servicio de arriba y el de abajo" - the two rows read as far apart even
 * with a normal row-to-row gap. Root cause confirmed by measuring real
 * layout, not guessed: a CSS grid row's height is always the tallest
 * column (the photo, ~554px at this max-width) regardless of
 * align-items - so the row-to-row gap itself (photo bottom to next photo
 * top) was already just the declared gap the whole time. What actually
 * created the "too much space" read was align-items: center leaving the
 * much-shorter text vertically centered inside that tall row, far from
 * both the photo above it and the next row below.
 *
 * Tried align-items: end first (bottom-aligned text/photo) - fixed the
 * rows-feel-far-apart read, but the owner immediately flagged the
 * opposite problem: text now sat low, disconnected from the TOP of its
 * own photo ("sube a nivel de las fotos que corresponden a cada foto").
 * align-items: start is the real fix for both: text starts right where
 * its own photo starts (paired, "at the photo's level"), and the row gap
 * was never dependent on alignment in the first place - reducing gap
 * itself (--lib-space-10 -> --lib-space-6) is what actually tightened the
 * rows. Photo size completely unchanged throughout (explicit owner
 * constraint: "no quiero que reduzcas el tamano de las imagenes").
 *
 * This section originally carried its own scoped max-width override on
 * .hhds-section__header/__title/__summary - promoted to the shared
 * defaults themselves (see the HARD RULE comment on .hhds-section__header
 * near the top of this file) once the identical bug turned up
 * independently in a second section. Removed here, now redundant.
 */

.hhds-spotlight {
  display: flex;
  flex-direction: column;
  gap: var(--lib-space-6);
  max-width: 100rem;
  margin-inline: auto;
}

.hhds-spotlight__row {
  display: grid;
  grid-template-columns: 1fr;
  align-items: start;
  gap: var(--lib-space-6);
}

/*
 * Real owner correction (michelles-nails-website, 2026-08-13, second
 * pass): a first compaction attempt stacked each service's own photo
 * above its own text ("no te pedi que dejes los contenidos abajo") -
 * wrong axis. What was actually wanted: keep each service's photo|text
 * pair exactly as it already was (side by side, "en su respectivo
 * lugar"), just stop stacking the two PAIRS as separate full-width rows
 * and put both pairs in one single row instead - "tenemos mas que
 * suficiente espacio" on desktop for 4 columns (photo, text, photo,
 * text). Needs real desktop width to not cramp four columns, so this
 * kicks in at 64rem, not 48rem - between 48rem and 64rem (tablet) the two
 * pairs still stack as full-width rows, each 2-column internally.
 */
@media (min-width: 48rem) {
  .hhds-spotlight__row {
    grid-template-columns: 1fr 1fr;
    gap: var(--lib-space-10);
  }

  .hhds-spotlight__row--reverse .hhds-spotlight__media {
    order: 2;
  }

  .hhds-spotlight__row--reverse .hhds-spotlight__content {
    order: 1;
  }
}

@media (min-width: 64rem) {
  .hhds-spotlight {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    align-items: start;
    gap: var(--lib-space-6);
  }

  /*
   * display: contents removes the row wrapper's own box, so its children
   * (media/content) become direct items of the outer 4-column grid - but
   * that also means `order` on the wrapper itself would do nothing (a
   * display: contents element isn't a grid item anymore, only its
   * children are). Order has to be set on the children directly, and
   * explicitly for BOTH rows now that all 4 boxes share one order scale:
   * Pedicure (reverse) keeps its existing 1/2 from the tablet tier above,
   * Acrylics gets 3/4 so it lands second (right) instead of falling back
   * to default order: 0, which would have put it first.
   */
  .hhds-spotlight__row {
    display: contents;
  }

  .hhds-spotlight__row:not(.hhds-spotlight__row--reverse) .hhds-spotlight__media {
    order: 3;
  }

  .hhds-spotlight__row:not(.hhds-spotlight__row--reverse) .hhds-spotlight__content {
    order: 4;
  }

  .hhds-spotlight__media,
  .hhds-spotlight__content {
    min-width: 0;
  }
}

.hhds-spotlight__media .hhds-media {
  width: 100%;
  height: 100%;
  aspect-ratio: 3 / 4;
}

/*
 * Real owner correction, 2026-08-12: with align-items: start, the media
 * element's own box top lines up exactly with the title's box top
 * (verified via getBoundingClientRect) - but the organic-blob mask
 * (lib-organic-blob-05) doesn't touch the top of its own box; it's an
 * organic curve that only reaches its highest point a good distance down,
 * so the visible photo reads as starting lower than the title even though
 * their boxes are aligned. Measured directly against real pixels (not
 * guessed): ~38-39px. transform (not margin-top - a negative margin here
 * feeds back into the grid row's own auto-height calculation and
 * compounds instead of just nudging the visual position) shifts the
 * painted photo up with zero effect on layout/row sizing. Applied to the
 * wrapper (.hhds-spotlight__media), not .hhds-media directly -
 * hhds_render_media() puts hhds-motion-target on the figure itself, and
 * the reveal-motion system's own
 * [data-hhds-motion-state="visible"] .hhds-motion-target rule sets
 * transform: none with higher specificity than a plain
 * ".hhds-spotlight__media .hhds-media" selector, silently overriding a
 * transform placed there (confirmed via getComputedStyle - it read back
 * as "none" until moved here). Consistent across both rows since both use
 * the same blob-05 shape.
 *
 * Real owner request (michelles-nails-website, 2026-08-13): bigger photos
 * (the 4-column desktop row still had unused width to spare) and a thin
 * brand-burgundy border traced around the actual organic-blob curve, not
 * a rectangular border around the invisible box (the visible curve never
 * touches its own box edges - a normal `border` would sit almost entirely
 * outside the painted shape and read as a faint rectangle, not a frame
 * around the photo). Standard masked-frame technique: the wrapper itself
 * now carries the SAME blob mask + a burgundy background (added in
 * section-renderer.php: `lib-organic-blob lib-organic-blob-05` on
 * .hhds-spotlight__media), sized slightly larger than the photo inside
 * it; the padding gap between the two independently-masked, self-similar
 * curves reads as a thin burgundy ring that actually follows the shape.
 *
 * A later revision asked for a real drop SHADOW instead of a solid-fill
 * border. Tried `filter: drop-shadow()` on the masked .hhds-media (the
 * theoretically correct tool - it operates on the rendered alpha shape
 * AFTER masking) - confirmed via getComputedStyle + pixel-scanning a
 * screenshot that it produces ZERO visible output at any blur up to
 * 20px. Root cause: this engine clips a masked element's compositing
 * layer to its own border-box before the filter stage runs, so a
 * drop-shadow's overflow has nowhere to paint - a real mask+filter
 * limitation, not a tuning problem. Reverted to this frame technique per
 * the owner's own fallback instruction, padding thinned from 0.3rem to
 * 0.09rem for a genuinely thin line.
 */
.hhds-spotlight__media {
  display: block;
  max-width: 30rem;
  aspect-ratio: 3 / 4;
  margin-inline: auto;
  /* design-allow: SP-04 -- simulates a hairline border via background
     bleed-through, not layout spacing; see the comment above this rule
     for why it's a mask+filter workaround, tuned to an exact thin-line
     value rather than a step on the space scale. */
  padding: 0.09rem;
  background: var(--lib-color-primary);
  transform: translateY(-2.4rem);
}

.hhds-spotlight__content {
  max-width: 32rem;
}

.hhds-spotlight__title {
  font-family: var(--lib-font-heading);
  font-size: clamp(1.75rem, 2.4vw, 2.25rem);
  line-height: 1.15;
  margin: 0;
  color: var(--lib-color-ink);
}

.hhds-spotlight__text {
  margin: var(--lib-space-4) 0 0;
  color: var(--lib-color-muted);
  line-height: 1.65;
}

.hhds-spotlight__content .hhds-button {
  margin-top: var(--lib-space-5);
}

/*
 * SVC-04 Service Rows (EXPERIMENTAL - see the "Render modes" section of
 * this adapter's own README.md). Every individual bookable service gets
 * its own card inside a `.hhds-service-group` (one group per catalog
 * category): optional real badge, photo/placeholder, title, duration/
 * price with icons, a short description, a real booking CTA. Fixed
 * 4-column grid at the wide breakpoint (not auto-fit - auto-fit's own
 * math lands on 3 at a real 1440px viewport, not 4), explicit step-down
 * breakpoints below that, so every card is genuinely the same width at
 * every size, never just "up to" a max.
 *
 * A highlighted card gets a heavier border + real shadow instead of a
 * different card shape, so it still lines up exactly with its neighbors
 * in the grid - no card is ever bigger than another, regardless of
 * badge, photo, or text-length variation (verified with per-card pixel
 * measurement across a full 27-card real page: all cards measured
 * bit-identical; what can read as a size difference between groups is a
 * row-completeness/pattern effect - a group that fills a complete grid
 * row reads denser than one that trails off with empty slots - not a
 * card-size defect).
 */
.hhds-service-group + .hhds-service-group {
  margin-top: var(--lib-space-8);
}

.hhds-service-group__title {
  margin: 0 0 var(--lib-space-2);
  font-family: var(--lib-font-heading);
  font-size: var(--lib-font-size-lead);
  font-weight: 750;
  color: var(--lib-color-ink);
}

.hhds-service-group__note {
  margin: 0 0 var(--lib-space-4);
  color: var(--lib-color-primary);
  font-size: var(--lib-font-size-small);
  font-weight: 700;
}

.hhds-service-rows {
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  gap: var(--lib-space-4);
}

@media (min-width: 40rem) {
  .hhds-service-rows {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 64rem) {
  .hhds-service-rows {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (min-width: 80rem) {
  .hhds-service-rows {
    grid-template-columns: repeat(4, 1fr);
  }
}

.hhds-service-row {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--lib-space-3);
  padding: var(--lib-space-5);
  border: var(--lib-space-hairline) solid var(--lib-color-primary);
  border-radius: var(--lib-radius-md);
  background: var(--lib-color-panel);
  transition: transform var(--lib-transition-base), box-shadow var(--lib-transition-base);
}

.hhds-service-row--highlighted {
  border-width: 0.125rem;
  box-shadow: var(--lib-shadow-card);
}

@media (hover: hover) {
  .hhds-service-row:hover {
    transform: translateY(calc(var(--lib-motion-distance-sm) * -1));
    box-shadow: var(--lib-shadow-card-hover);
  }
}

.hhds-service-row__badge {
  position: absolute;
  top: -0.75rem;
  left: var(--lib-space-4);
  padding: 0.25rem var(--lib-space-3);
  border-radius: var(--lib-radius-pill);
  background: var(--lib-color-primary);
  color: var(--lib-color-inverse);
  font-size: var(--lib-font-size-caption);
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.hhds-service-row__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--lib-space-4);
}

/* Title and description share this column so the description closes the
   real gap under a short title, instead of the photo's height deciding
   where it starts. */
.hhds-service-row__text {
  order: 1;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--lib-space-2);
  min-width: 0;
}

.hhds-service-row__media {
  flex-shrink: 0;
  order: 2;
  width: 7rem;
  height: 7rem;
  border-radius: var(--lib-radius-md);
  overflow: hidden;
}

/* Every card reserves this spot even with no photo yet, instead of
   collapsing to a text-only card - same dashed-icon language already
   used by .hhds-card__media-note elsewhere in this file for "photo
   needed" states. */
.hhds-service-row__media--placeholder {
  display: grid;
  place-items: center;
  background: var(--lib-color-panel-soft);
  color: var(--lib-color-primary);
}

.hhds-service-row__media--placeholder svg {
  width: 2.25rem;
  height: 2.25rem;
}

.hhds-service-row__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hhds-service-row__title {
  display: -webkit-box;
  min-height: 2.6rem;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  font-weight: 700;
  line-height: 1.3;
  color: var(--lib-color-ink);
}

.hhds-service-row__meta {
  display: flex;
  gap: var(--lib-space-4);
  font-size: var(--lib-font-size-small);
  color: var(--lib-color-muted);
}

.hhds-service-row__meta-item {
  display: inline-flex;
  align-items: center;
  gap: var(--lib-space-1);
  font-weight: 700;
  color: var(--lib-color-primary);
}

.hhds-service-row__meta-item svg {
  flex-shrink: 0;
  width: 1.05rem;
  height: 1.05rem;
}

/* Icon stays brand-colored (currentColor from the parent above), only
   the actual duration/price text takes this muted tone - a consuming
   project may map --lib-color-muted to true black rather than a soft
   gray if its own brand tokens call for it. */
.hhds-service-row__meta-text {
  color: var(--lib-color-muted);
}

/* description is a required field (always present in the data, see
   hhds_render_collection()'s 'service-rows' mode) precisely so this
   reserved 2-line height keeps every card the same height across the
   whole grid, not just within one row of it. */
.hhds-service-row__description {
  display: -webkit-box;
  min-height: 2.65rem;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  color: var(--lib-color-muted);
  font-size: var(--lib-font-size-small);
  line-height: 1.5;
}

/* On mobile (single column, below the 40rem breakpoint .hhds-service-rows
   switches to 1 column at), a 2-line clamp on title/description would
   truncate real text with "…". Mobile cards already stack in a single
   column (no "same row" neighbor whose height this needs to match,
   unlike the desktop grid), so letting text grow the card instead of
   truncating it is the right tradeoff here specifically. */
@media (max-width: 39.99rem) {
  .hhds-service-row__title,
  .hhds-service-row__description {
    display: block;
    min-height: 0;
    overflow: visible;
    -webkit-line-clamp: unset;
  }
}

.hhds-service-row .hhds-button {
  justify-content: center;
  width: 100%;
  margin-top: auto;
}

/*
 * Hero Authority convergence (Human Visual Correction pass 3,
 * 2026-08-25): this used to be a real, hand-rolled duplicate of TRU-01
 * (sections/trust-strip) -- same history as sections/hero-split/
 * hero-split.css's own identical block (see that file's comment for the
 * full real owner-decision provenance, all preserved verbatim in
 * trust-strip.css's `.lib-trust-strip--hero-attached` rule now). Fixed
 * by composing the real classes directly instead of a second
 * implementation.
 */
.hhds-section:has(> .hhds-container > .hhds-hero__background),
.hhds-section:has(> .hhds-container > .lib-trust-strip--hero-attached) {
  overflow: hidden;
}

/*
 * Real premium-site reference (2026-08-11, owner-supplied screenshots):
 * every photo container in those references is a soft, asymmetric organic
 * shape - never a plain rounded rectangle, never a hard geometric cut.
 * First pass here used border-radius alone (a distorted oval) - real
 * owner feedback on that first pass, plus a proper look at the reference
 * sites, confirmed border-radius reads as generic/approximate against a
 * genuine irregular blob mask (patterns/organic-blob, PAT-016). Border
 * dropped entirely: a hard edge around an irregular photo silhouette
 * reads as a sticker outline, not a soft edge - the references use no
 * border at all, just the shadow to lift the shape off the page.
 */
.hhds-media {
  overflow: hidden;
  margin: 0;
  background: var(--lib-color-panel);
  box-shadow: var(--lib-shadow-card-stat);
}

.hhds-media img {
  display: block;
  width: 100%;
  height: 100%;
  min-height: inherit;
  object-fit: cover;
}

.hhds-collection {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  /* Explicit, not relying on the grid default: real owner requirement
     (michelles-nails-website, 2026-08-12) - same-row cards (e.g. a
     3-across service grid) must be the same size regardless of how much
     their own text wraps. */
  align-items: stretch;
  gap: var(--lib-space-grid-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

/*
 * Real premium-site reference (2026-08-11): a moderate asymmetric radius
 * (not the full organic blob .hhds-media uses - this holds headings,
 * multi-line body text, buttons, so it can't distort as aggressively)
 * plus a richer, more diffused shadow reads as a soft custom container
 * instead of a generic flat rectangle, without breaking text layout.
 */
.hhds-card {
  position: relative;
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: var(--lib-space-3);
  padding: clamp(var(--lib-space-5), 3vw, var(--lib-space-8));
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: var(--lib-radius-organic-soft);
  background: var(--lib-color-panel);
  box-shadow: var(--lib-shadow-card-stat);
  transition: transform var(--lib-transition-base), box-shadow var(--lib-transition-base), border-color var(--lib-transition-base);
}

/* Real owner requirement (michelles-nails-website, 2026-08-12), same
   session as align-items: stretch above: a CTA button pins to the bottom
   of its own (now equal-height) card, instead of sitting right under
   whatever line count that card's own text happened to wrap to - keeps
   all buttons in a row lined up at the same height too, not just the
   card outlines. */
.hhds-card .hhds-button {
  margin-top: auto;
}

@media (hover: hover) {
  .hhds-card:hover {
    transform: translateY(calc(var(--lib-motion-distance-sm) * -1));
    border-color: color-mix(in srgb, var(--lib-color-primary) 34%, var(--lib-color-border));
    box-shadow: var(--lib-shadow-card-hover);
  }
}

/*
 * Section weight/density (Layout Intelligence, home-decision.json's
 * composition[].weight/density) already varied per section but nothing
 * ever read data-weight/data-density from the DOM - every section looked
 * like the same rectangle regardless of what Layout Intelligence actually
 * decided. Real signal, previously unused, now driving real visual
 * differentiation instead of an identical .hhds-card everywhere.
 */

/* STRIP (e.g. trust) - compact, pill-like, minimal chrome. */
.hhds-section[data-weight="STRIP"] .hhds-card {
  padding: var(--lib-space-4) var(--lib-space-5);
  border-radius: var(--lib-radius-pill);
  box-shadow: none;
}

/* LIGHT (e.g. final CTA content, when it carries cards) - flat, no box
   chrome at all, just a bottom hairline for separation. */
.hhds-section[data-weight="LIGHT"] .hhds-card {
  padding-block: var(--lib-space-3);
  border: none;
  border-bottom: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

/* HEAVY (e.g. proof/testimonials) - the section's dominant visual weight,
   real asymmetric shape (not a uniform rounded rect) and an accent edge. */
.hhds-section[data-weight="HEAVY"] .hhds-card {
  padding: var(--lib-space-6) var(--lib-space-7);
  border: none;
  border-left: 0.25rem solid var(--lib-color-accent);
  border-radius: 0 var(--lib-radius-lg) var(--lib-radius-lg) 0;
  box-shadow: var(--lib-shadow-card);
}

/* MEDIUM (e.g. differentiators, process, most standard grids) - previously
   fell through to the bare .hhds-card default with no weight-specific
   identity of its own, the single most common weight value ending up
   visually indistinguishable from "nothing was decided." A top accent bar
   (not HEAVY's left edge, not STRIP's pill, not LIGHT's hairline) plus a
   slightly deeper shadow gives it a real, own silhouette. */
.hhds-section[data-weight="MEDIUM"] .hhds-card {
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-top: 0.1875rem solid var(--lib-color-accent);
  border-radius: var(--lib-radius-lg);
  box-shadow: var(--lib-shadow-card);
}

/*
 * Real owner correction (michelles-nails-website, 2026-08-12): tried
 * HEAVY's left-accent-border style on a 3-card service grid first, per an
 * ambiguous reference - explicitly rejected ("no esas lineas absurdas de
 * los laterales"). The actual reference was the Stats section
 * (lib-bento-grid__cell): fully rounded corners, soft diffused shadow,
 * solid fill, no border/accent line at all. Same token combination
 * (--lib-radius-organic-soft + --lib-shadow-card-stat) that already
 * produces that exact look there, applied directly to this mode instead
 * of fighting one of the 4 named weight variants (none of which is
 * "no border" on their own).
 *
 * Selector specificity note: `.hhds-section[data-weight="MEDIUM"]
 * .hhds-card` is 3 class-level selectors (.hhds-section + [data-weight]
 * + .hhds-card) - a plain `.hhds-collection--services-grid .hhds-card`
 * (2 classes) loses to it regardless of source order. Matched here via
 * `.hhds-section[data-hhds-mode="services-grid"]` (also 3) so source
 * order (this rule comes later) actually decides it.
 */
.hhds-section[data-hhds-mode="services-grid"] .hhds-card {
  border: none;
  border-radius: var(--lib-radius-organic-soft);
  box-shadow: var(--lib-shadow-card-stat);
  /* Real owner request (michelles-nails-website, 2026-08-12): brand color
     as the card fill, not plain white/panel - but blended down with
     white so it reads as a soft professional wash, not a solid saturated
     pink block ("no se vea rosa solido"). --lib-color-panel-soft is the
     project's own brand pink token (already used for alternating section
     washes sitewide); mixed at 30% into white keeps the same hue family
     without the full-strength saturation. */
  background: color-mix(in srgb, var(--lib-color-panel-soft) 30%, white);
}

/* Density controls grid rhythm - HIGH packs more per row with tighter
   gaps, LOW gives fewer/larger cards room to breathe. MEDIUM density gets
   the same treatment as the unweighted default (repeat(auto-fit,
   minmax(18rem, 1fr))) - already a real, deliberate choice, not a gap. */
.hhds-section[data-density="HIGH"] .hhds-collection {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  gap: var(--lib-space-4);
}

.hhds-section[data-density="LOW"] .hhds-collection {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: var(--lib-space-8);
}

/* Asymmetric rhythm for dense grids of 4+ items (bento-style unequal
   sizing without needing a separate pattern component) - the first card
   in a HIGH-density collection spans two columns when there's room.
   Real incident (michelles-nails-website, 2026-08-12): a plain 3-card
   services grid was left on density: HIGH from its default composition
   entry - this rule doesn't check item count, so it silently doubled the
   first card's width against the other two equal ones, read as "all 3
   cards are a different size" even though their heights matched via
   align-items: stretch. A same-size 3-item (or fewer) grid needs
   density: MEDIUM (or LOW), never HIGH - HIGH's asymmetry is only
   correct for 4+ item collections where one hero cell is a deliberate
   choice. */
@media (min-width: 720px) {
  .hhds-section[data-density="HIGH"] .hhds-collection > :first-child {
    grid-column: span 2;
  }
}

/* Real per-item photo inside a card (hhds_render_item_fields()'s 'image'
   key) - the same .hhds-media figure hero/section media already uses,
   given a card-appropriate aspect ratio here since it has no hero-level
   min-height of its own otherwise. */
.hhds-card > .hhds-media {
  aspect-ratio: 4 / 3;
  min-height: 0;
}

/*
 * Described placeholder for a real, warranted photo that doesn't exist
 * yet (hhds_render_item_fields()'s 'media_note' key) - an honest "photo
 * coming" state, never a silently absent media slot. Dashed border reads
 * as "intentionally pending," not "broken image" (no broken-image icon,
 * no empty box) and not "finished" (no solid fill/shadow a real photo
 * card would have).
 */
.hhds-card__media-note {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--lib-space-2);
  aspect-ratio: 4 / 3;
  padding: var(--lib-space-4);
  border: 2px dashed color-mix(in srgb, var(--lib-color-border) 60%, transparent);
  border-radius: var(--lib-radius-lg);
  color: var(--lib-color-muted);
  text-align: center;
}

.hhds-card__media-note-icon {
  width: 1.75rem;
  height: 1.75rem;
  opacity: 0.6;
}

.hhds-card__media-note-text {
  margin: 0;
  font-size: var(--lib-font-size-caption);
  line-height: 1.4;
}

.hhds-card__index {
  display: inline-grid;
  width: 2.5rem;
  aspect-ratio: 1;
  place-items: center;
  border-radius: var(--lib-radius-pill);
  color: var(--lib-color-inverse);
  background: var(--lib-color-primary);
  font-weight: 800;
}

/*
 * Real owner request (michelles-nails-website, 2026-08-12): replace the
 * plain numbered-circle-plus-flat-card default with something premium/
 * deluxe - "no algo generico". A floating step badge that overlaps the
 * card's own top edge (classic premium "journey" convention) instead of
 * sitting flush inside it, on a soft card fill lighter than the section's
 * own fully-saturated wash so the cards still read as distinct objects,
 * not the same flat color as their background.
 */
.hhds-section[data-hhds-mode="process-dark"] .hhds-card {
  position: relative;
  border: none;
  border-radius: var(--lib-radius-organic-soft);
  background: color-mix(in srgb, var(--lib-color-panel-soft) 14%, white);
  box-shadow: var(--lib-shadow-card-stat);
  padding-top: calc(var(--lib-space-8) + 0.75rem);
}

.hhds-section[data-hhds-mode="process-dark"] .hhds-card__index {
  position: absolute;
  top: -1.35rem;
  left: var(--lib-space-6);
  width: 3rem;
  font-size: var(--lib-font-size-lead);
  border: 3px solid var(--lib-color-panel-soft);
  box-shadow: var(--lib-shadow-card);
}

/*
 * Real owner request (michelles-nails-website, 2026-08-12): "los reviews
 * deben ser a estilo de Maggy Prestige Fit" - a horizontal snap-scroll
 * carousel matching that project's real testimonials-grid.css pattern
 * (single focused card centered in view, circular avatar, accent divider,
 * left-aligned quote, circular prev/next nav). No avatar photos unless
 * the project actually has them (real initial letter otherwise) and no
 * star ratings unless every item in the set actually documents one - a
 * mixed authentic/fabricated rating set would misrepresent the rest.
 */
.hhds-proof-carousel {
  /*
   * Nav buttons are absolutely-positioned overlays, not flex siblings of
   * the track - a percentage padding-inline on a flex item resolves
   * against the flex CONTAINER's width (the spec's containing-block rule
   * for flex items), not the item's own rendered width, which silently
   * broke the centering math when nav buttons shared a flex row with the
   * track. Matches the real reference (Maggy Prestige Fit) structure.
   *
   * max-width caps this to a single-card-focus "frame" (matches the
   * reference's own frame-max convention, scaled to this component's
   * 340px card): full section width lets 2-3 cards show at once instead
   * of one focused card with peeks.
   */
  position: relative;
  max-width: 45rem;
  margin-inline: auto;
}

.hhds-proof-carousel__track {
  display: flex;
  width: 100%;
  gap: var(--lib-space-6);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-block: var(--lib-space-4);
  padding-inline: calc(50% - 170px);
  scrollbar-width: none;
}

.hhds-proof-carousel__track::-webkit-scrollbar {
  display: none;
}

.hhds-proof-carousel__slide {
  flex: 0 0 340px;
  max-width: 90vw;
  scroll-snap-align: center;
}

.hhds-proof-carousel__card {
  display: flex;
  flex-direction: column;
  gap: var(--lib-space-3);
  height: 100%;
  padding: var(--lib-space-7) var(--lib-space-6);
  border: none;
  border-radius: var(--lib-radius-organic-soft);
  background: var(--lib-color-surface);
  box-shadow: var(--lib-shadow-card-stat);
  /* Phase 6B.1C (2026-08-27): re-synced from generation-hhds.css --
     0.2s/ease -> var(--lib-transition-base). */
  transition: transform var(--lib-transition-base), box-shadow var(--lib-transition-base);
}

.hhds-proof-carousel__avatar {
  display: inline-flex;
  width: 3rem;
  height: 3rem;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--lib-color-primary);
  color: var(--lib-color-inverse);
  font-family: var(--lib-font-heading);
  font-size: var(--lib-font-size-lead);
  font-weight: 700;
}

img.hhds-proof-carousel__avatar {
  display: block;
  object-fit: cover;
}

.hhds-proof-carousel__name {
  display: block;
  margin-top: calc(var(--lib-space-3) * -1);
  color: var(--lib-color-ink);
  font-family: var(--lib-font-heading);
  font-size: var(--lib-font-size-base);
  font-weight: 700;
}

.hhds-proof-carousel__meta {
  display: block;
  margin-top: calc(var(--lib-space-2) * -1);
  color: var(--lib-color-muted);
  font-size: var(--lib-font-size-small);
}

.hhds-proof-carousel__divider {
  width: 2.5rem;
  height: var(--lib-space-hairline);
  margin: 0;
  border: none;
  background: var(--lib-color-accent);
}

.hhds-proof-carousel__quote {
  margin: 0;
  color: var(--lib-color-muted);
  font-size: var(--lib-font-size-base);
  line-height: 1.6;
  text-align: left;
}

.hhds-proof-carousel__nav {
  display: flex;
  position: absolute;
  top: 50%;
  z-index: 2;
  width: 2.75rem;
  height: 2.75rem;
  align-items: center;
  justify-content: center;
  transform: translateY(-50%);
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: 50%;
  background: var(--lib-color-surface);
  color: var(--lib-color-primary);
  box-shadow: var(--lib-shadow-card);
  cursor: pointer;
  /* Phase 6B.1C (2026-08-27): re-synced from generation-hhds.css --
     0.2s/ease -> var(--lib-transition-base). */
  transition: background-color var(--lib-transition-base), color var(--lib-transition-base);
}

.hhds-proof-carousel__nav--prev {
  left: 0;
}

.hhds-proof-carousel__nav--next {
  right: 0;
}

.hhds-proof-carousel__nav svg {
  width: 1.25rem;
  height: 1.25rem;
}

.hhds-proof-carousel__nav:hover {
  background: var(--lib-color-primary);
  color: var(--lib-color-inverse);
}

.hhds-proof-carousel__nav:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

@media (max-width: 640px) {
  .hhds-proof-carousel__track {
    padding-inline: var(--lib-space-4);
  }

  .hhds-proof-carousel__slide {
    flex-basis: 280px;
  }

  .hhds-proof-carousel__nav {
    width: 2.25rem;
    height: 2.25rem;
  }

  .hhds-proof-carousel__nav--prev {
    left: -0.5rem;
  }

  .hhds-proof-carousel__nav--next {
    right: -0.5rem;
  }
}

.hhds-card__title,
.hhds-card__metric {
  display: block;
  color: var(--lib-color-ink);
  font-family: var(--lib-font-heading);
  font-size: var(--lib-font-size-subheading);
  line-height: 1.2;
}

.hhds-card__metric {
  color: var(--lib-color-primary);
  font-size: clamp(2rem, 4vw, 3.5rem);
}

.hhds-card__text,
.hhds-card__meta,
.hhds-card__quote {
  margin: 0;
  color: var(--lib-color-muted);
  line-height: 1.6;
}

.hhds-card__quote {
  /* Real owner rule (michelles-nails-website, 2026-08-12): a brand accent
     color (--lib-color-ink) is for titles/highlights only - description/
     body copy, including a real testimonial quote sitting on a light
     card, is pure black or pure white on dark, never an in-between brand
     color. Was explicitly overriding the shared __text/__meta/__quote
     color: muted rule above to ink - removed, inherits muted like the
     rest (each project's own --lib-color-muted value decides pure black/
     white, not this component). */
  font-size: var(--lib-font-size-lead);
}

.hhds-card__meta {
  margin-top: auto;
  font-size: var(--lib-font-size-small);
  font-weight: 700;
}

.hhds-card__features {
  display: grid;
  gap: var(--lib-space-2);
  margin: var(--lib-space-3) 0 0;
  padding-left: var(--lib-space-5);
  color: var(--lib-color-muted);
}

.hhds-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--lib-space-3);
  margin-top: var(--lib-space-8);
}

.hhds-button {
  display: inline-flex;
  min-height: 3rem;
  align-items: center;
  justify-content: center;
  padding: var(--lib-button-padding-y, var(--lib-space-3)) var(--lib-button-padding-x, var(--lib-space-6));
  border: var(--lib-button-border-width, var(--lib-space-hairline)) solid transparent;
  border-radius: var(--lib-button-radius, var(--lib-radius-pill));
  gap: var(--lib-button-gap, var(--lib-space-2));
  font-family: var(--lib-button-font-family, inherit);
  font-size: var(--lib-button-font-size, inherit);
  font-weight: var(--lib-button-font-weight, 800);
  letter-spacing: var(--lib-button-letter-spacing, inherit);
  text-transform: var(--lib-button-text-transform, inherit);
  line-height: var(--lib-button-line-height, inherit);
  text-decoration: none;
  transition: transform var(--lib-transition-base), box-shadow var(--lib-transition-base), background-color var(--lib-transition-base);
}

.hhds-button--primary {
  color: var(--lib-button-primary-color, var(--lib-action-primary-text));
  border-color: var(--lib-button-primary-border, transparent);
  background: var(--lib-button-primary-bg, var(--lib-gradient-primary));
  box-shadow: var(--lib-button-primary-shadow, var(--lib-shadow-button));
}

.hhds-button--primary:hover,
.hhds-button--primary:focus-visible {
  border-color: var(--lib-button-primary-border-hover, var(--lib-button-primary-border, transparent));
  background: var(--lib-button-primary-bg-hover, var(--lib-button-primary-bg, var(--lib-gradient-primary)));
}

.hhds-button--secondary {
  color: color-mix(in srgb, var(--lib-text-brand) 45%, var(--lib-text-primary)); /* design-allow: CASE-4 same proven 45% brand-on-Canvas-neutral fix used library-wide, no dedicated role for this outlined-on-brand button variant */
  border-color: color-mix(in srgb, var(--lib-border-brand) 32%, transparent);
  background: var(--lib-surface-elevated);
}

.hhds-button:focus-visible,
.hhds-faq summary:focus-visible,
.hhds-form :is(input, textarea, button):focus-visible {
  outline: 0.2rem solid var(--lib-border-accent);
  outline-offset: var(--lib-space-1);
}

.hhds-section--trust-strip,
.hhds-section--differentiators-dark,
.hhds-section--cta-dark-form {
  color: var(--lib-color-inverse);
  background: var(--lib-gradient-deep);
}

.hhds-section--trust-strip .hhds-card {
  border-color: color-mix(in srgb, var(--lib-color-inverse) 18%, transparent);
  background: color-mix(in srgb, var(--lib-color-inverse) 8%, transparent);
}

/*
 * differentiators-dark / cta-dark-form sit on --lib-gradient-deep, which on
 * saturated brand palettes (e.g. a burgundy-to-hot-pink gradient) is itself
 * high-chroma - the trust-strip tint (18%/8% white) reads as barely-there
 * against that much color, cards lose their edges and the whole section
 * reads as one flat block. A real glass surface (higher-opacity tint +
 * backdrop-blur + its own shadow) holds a visible edge against any brand
 * gradient, loud or muted, without hand-tuning per project.
 */
.hhds-section--differentiators-dark .hhds-card,
.hhds-section--cta-dark-form .hhds-card {
  border-color: color-mix(in srgb, var(--lib-color-inverse) 28%, transparent);
  background: color-mix(in srgb, var(--lib-color-inverse) 14%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: 0 1rem 2rem color-mix(in srgb, var(--lib-color-deep) 35%, transparent);
}

.hhds-section--trust-strip :is(.hhds-card__title, .hhds-card__text),
.hhds-section--differentiators-dark :is(.hhds-card__title, .hhds-card__text),
.hhds-section--cta-dark-form :is(.hhds-section__title, .hhds-section__summary) {
  color: var(--lib-color-inverse);
}

/*
 * patterns/glass-bridge — real component, existed in the library, never
 * wired. trust-strip always sits directly after a hero-* section (every
 * WPS-generated page orders them this way), and used to just repeat the
 * same flat --lib-gradient-deep fill as the hero above it — two identical
 * dark blocks stacked with a hard seam, no depth cue. Swapping trust-strip's
 * own background for a real blurred glass pane lets the hero behind it
 * (photo when a project has one, its gradient otherwise) show through,
 * reading as a floating panel bridging the two sections instead of a
 * color change. Only overrides the base fill above when a hero-* section
 * actually precedes it — a trust-strip with no hero above it keeps the
 * flat fallback, never renders unstyled.
 */
.hhds-section[data-hhds-mode^="hero-"] + .hhds-section--trust-strip {
  position: relative;
  z-index: 1;
  margin-top: calc(var(--lib-treatment-glass-overlap) * -1);
  background: color-mix(in srgb, var(--lib-color-deep) 55%, transparent);
  backdrop-filter: blur(var(--lib-treatment-glass-blur));
  -webkit-backdrop-filter: blur(var(--lib-treatment-glass-blur));
  border-top: var(--lib-space-hairline) solid color-mix(in srgb, var(--lib-color-inverse) 20%, transparent);
  box-shadow: var(--lib-shadow-card-hover);
}

/*
 * Boundary between a non-DARK section and the DARK section right after it
 * (any project's page structure, self-applying, no per-page markup) used
 * to be a hard diagonal wedge (patterns/diagonal-cut, PAT-007 - that
 * pattern still exists in the library for other real uses, just not this
 * one anymore). Real owner feedback 2026-08-11 on this exact boundary,
 * live on Michelle's Nails Service: reads as a cheap hard-edged cut, not
 * premium. First replacement (a CSS-only border-radius ellipse) was an
 * approximation and still isn't the real curve the library actually owns.
 * Upgraded to the real patterns/wave-divider (PAT-006) "--01 gentle" curve
 * - same SVG path as .lib-wave-divider--01, inlined here (a pseudo-element
 * can't carry a second class).
 *
 * First cut of this used the pattern's original background-image +
 * fill="currentColor" technique and it rendered solid black in Chromium -
 * confirmed by screenshot on Michelle's real staging site 2026-08-11.
 * background-image is an opaque external resource; currentColor inside it
 * does not resolve against the host element's `color`, it falls back to
 * the SVG default (black). Both this rule and patterns/wave-divider were
 * fixed the same way: the SVG only supplies the shape via mask-image
 * (alpha), background-color supplies the real, themeable fill - the same
 * technique patterns/organic-blob already used and had verified working.
 */
.hhds-section:not([data-surface="DARK"]) + .hhds-section[data-surface="DARK"] {
  position: relative;
}

.hhds-section:not([data-surface="DARK"]) + .hhds-section[data-surface="DARK"]::before {
  content: "";
  display: block;
  position: absolute;
  top: calc(var(--lib-treatment-diagonal-height) * -1.6);
  left: -5%;
  right: -5%;
  height: calc(var(--lib-treatment-diagonal-height) * 1.6);
  background-color: var(--lib-diagonal-cut-fill, var(--lib-color-deep));
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%201440%2090%22%20preserveAspectRatio%3D%22none%22%3E%3Cpath%20d%3D%22M0%2C45.0%20C%2090.0%2C45.0%2090.0%2C54.9%20180.0%2C54.9%20C%20270.0%2C54.9%20270.0%2C59.0%20360.0%2C59.0%20C%20450.0%2C59.0%20450.0%2C54.9%20540.0%2C54.9%20C%20630.0%2C54.9%20630.0%2C45.0%20720.0%2C45.0%20C%20810.0%2C45.0%20810.0%2C35.1%20900.0%2C35.1%20C%20990.0%2C35.1%20990.0%2C31.0%201080.0%2C31.0%20C%201170.0%2C31.0%201170.0%2C35.1%201260.0%2C35.1%20C%201350.0%2C35.1%201350.0%2C45.0%201440.0%2C45.0%20L1440%2C90%20L0%2C90%20Z%22/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%201440%2090%22%20preserveAspectRatio%3D%22none%22%3E%3Cpath%20d%3D%22M0%2C45.0%20C%2090.0%2C45.0%2090.0%2C54.9%20180.0%2C54.9%20C%20270.0%2C54.9%20270.0%2C59.0%20360.0%2C59.0%20C%20450.0%2C59.0%20450.0%2C54.9%20540.0%2C54.9%20C%20630.0%2C54.9%20630.0%2C45.0%20720.0%2C45.0%20C%20810.0%2C45.0%20810.0%2C35.1%20900.0%2C35.1%20C%20990.0%2C35.1%20990.0%2C31.0%201080.0%2C31.0%20C%201170.0%2C31.0%201170.0%2C35.1%201260.0%2C35.1%20C%201350.0%2C35.1%201350.0%2C45.0%201440.0%2C45.0%20L1440%2C90%20L0%2C90%20Z%22/%3E%3C/svg%3E");
  pointer-events: none;
}

.hhds-faq {
  display: grid;
  max-width: 64rem;
  gap: var(--lib-space-3);
}

.hhds-faq__item {
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: var(--lib-radius-md);
  background: var(--lib-color-panel);
}

.hhds-faq summary {
  padding: var(--lib-space-5) var(--lib-space-6);
  color: var(--lib-color-ink);
  cursor: pointer;
  font-family: var(--lib-font-heading);
  font-weight: 750;
}

.hhds-faq__answer {
  padding: 0 var(--lib-space-6) var(--lib-space-6);
  color: var(--lib-color-muted);
}

.hhds-tabs {
  display: grid;
  max-width: 72rem;
  gap: var(--lib-space-5);
}

.hhds-tabs__list {
  display: flex;
  gap: var(--lib-space-2);
  overflow-x: auto;
  padding: var(--lib-space-1);
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: var(--lib-radius-pill);
  background: var(--lib-color-panel);
  scrollbar-width: thin;
}

.hhds-tabs__tab {
  display: inline-flex;
  min-height: 2.75rem;
  flex: 1 0 max-content;
  align-items: center;
  justify-content: center;
  padding-inline: var(--lib-space-5);
  border-radius: var(--lib-radius-pill);
  color: var(--lib-color-muted);
  font-weight: 800;
  text-decoration: none;
  transition: color var(--lib-transition-base), background-color var(--lib-transition-base), transform var(--lib-transition-base);
}

.hhds-tabs__tab:is(:hover, [aria-selected="true"]) {
  color: var(--lib-color-inverse);
  background: var(--lib-color-primary);
}

.hhds-tabs__tab:focus-visible {
  outline: 0.2rem solid var(--lib-border-accent);
  outline-offset: var(--lib-space-1);
}

.hhds-tabs__panels {
  display: grid;
  gap: var(--lib-space-4);
}

.hhds-tabs__panel {
  display: grid;
  min-height: 13rem;
  align-content: center;
  gap: var(--lib-space-4);
  padding: clamp(var(--lib-space-6), 5vw, 4rem);
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: var(--lib-radius-lg);
  background:
    radial-gradient(circle at 92% 10%, color-mix(in srgb, var(--lib-color-accent) 13%, transparent), transparent 34%),
    var(--lib-color-panel);
  box-shadow: var(--lib-shadow-card-soft);
}

.hhds-tabs__panel[hidden] {
  display: none;
}

.hhds-tabs:not(.hhds-tabs--enhanced) .hhds-tabs__panel + .hhds-tabs__panel {
  margin-top: var(--lib-space-4);
}

.hhds-founder {
  display: grid;
  align-items: center;
  gap: clamp(var(--lib-space-8), 6vw, 6rem);
}

.hhds-form {
  display: grid;
  max-width: 48rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--lib-space-5);
  padding: clamp(var(--lib-space-5), 4vw, var(--lib-space-8));
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: var(--lib-radius-lg);
  background: var(--lib-color-panel);
  box-shadow: var(--lib-shadow-card);
}

.hhds-form__field {
  display: grid;
  gap: var(--lib-space-2);
}

.hhds-form__field:has(textarea),
.hhds-form__status {
  grid-column: 1 / -1;
}

.hhds-form label {
  color: var(--lib-color-ink);
  font-size: var(--lib-font-size-small);
  font-weight: 750;
}

.hhds-form :is(input, textarea) {
  width: 100%;
  padding: var(--lib-space-3) var(--lib-space-4);
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: var(--lib-radius-sm);
  color: var(--lib-color-ink);
  background: var(--lib-color-surface);
  font: inherit;
}

.hhds-form__status {
  min-height: 1.5em;
  margin: 0;
}

/*
 * Real bug found 2026-08-11 on Michelle's Nails Service staging: this
 * rule used to also set opacity: 0 while data-hhds-motion-state="pending"
 * (i.e. real content, before the IntersectionObserver in
 * generation-motion.js has confirmed it's scrolled into view). A real
 * scrolling user never sees a problem - the observer fires within a
 * frame or two of the section entering the viewport. But anything that
 * renders the page WITHOUT actually scrolling the browser viewport
 * through it - a full-page screenshot tool (confirmed: Playwright's
 * captureBeyondViewport composites the whole document without ever
 * changing the small layout viewport IntersectionObserver checks
 * against), a search crawler, a social-preview generator, a client
 * reviewing via screenshot - sees the content as invisible instead of
 * "not yet animated in". Real, differentiator-card and process-step
 * content going fully invisible in exactly this way is what the owner
 * saw and flagged. Fix: never hide real content via opacity behind a
 * scroll-timing dependency - only animate the position offset, which
 * still reads as a real reveal to an actual scrolling user but leaves
 * the content legible in every non-interactive render.
 */
.hhds-motion-enabled :is([data-hhds-motion="reveal"], [data-hhds-motion="stagger"])[data-hhds-motion-state="pending"] .hhds-motion-target {
  transform: translateY(var(--lib-motion-distance-md));
}

.hhds-motion-enabled :is([data-hhds-motion="reveal"], [data-hhds-motion="stagger"])[data-hhds-motion-variant="left"][data-hhds-motion-state="pending"] .hhds-motion-target {
  transform: translateX(calc(var(--lib-motion-distance-md) * -1));
}

.hhds-motion-enabled :is([data-hhds-motion="reveal"], [data-hhds-motion="stagger"])[data-hhds-motion-state="visible"] .hhds-motion-target {
  opacity: 1;
  transform: none;
  transition: opacity var(--lib-transition-reveal), transform var(--lib-transition-reveal);
}

.hhds-motion-enabled [data-hhds-motion="stagger"] .hhds-motion-target:nth-child(2) { transition-delay: var(--lib-delay-1); }
.hhds-motion-enabled [data-hhds-motion="stagger"] .hhds-motion-target:nth-child(3) { transition-delay: var(--lib-delay-2); }
.hhds-motion-enabled [data-hhds-motion="stagger"] .hhds-motion-target:nth-child(4) { transition-delay: var(--lib-delay-3); }
.hhds-motion-enabled [data-hhds-motion="stagger"] .hhds-motion-target:nth-child(n + 5) { transition-delay: var(--lib-delay-4); }

.hhds-section[data-hhds-motion="state-transition"] :is(.hhds-card:focus-within, .hhds-faq__item[open], .hhds-tabs__tab[aria-selected="true"]) {
  border-color: var(--lib-color-primary);
  box-shadow: var(--lib-shadow-card-soft);
}

.hhds-section[data-hhds-motion="state-transition"] .hhds-faq__answer {
  transform: translateY(0);
  opacity: 1;
  transition: opacity var(--lib-transition-base), transform var(--lib-transition-base);
}

@media (hover: hover) {
  .hhds-section[data-hhds-motion="media-focus"] :is(.hhds-card, .hhds-media):is(:hover, :focus-within) {
    transform: translateY(calc(var(--lib-motion-distance-sm) * -1)) scale(var(--lib-motion-scale-focus));
    box-shadow: var(--lib-shadow-card-hover);
  }
}

.hhds-motion-control {
  display: none;
  min-height: 2.75rem;
  align-items: center;
  justify-content: center;
  margin-top: var(--lib-space-5);
  padding: var(--lib-space-2) var(--lib-space-5);
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: var(--lib-radius-pill);
  color: var(--lib-color-ink);
  background: var(--lib-color-panel);
  font: inherit;
  font-weight: 750;
  cursor: pointer;
}

.hhds-motion-control:focus-visible {
  outline: 0.2rem solid var(--lib-border-accent);
  outline-offset: var(--lib-space-1);
}

@keyframes hhds-generation-marquee {
  from { transform: translateX(0); }
  to { transform: translateX(calc(-100% + 82vw)); }
}

@media (min-width: 48rem) {
  .hhds-hero,
  .hhds-founder {
    grid-template-columns: minmax(0, 1.15fr) minmax(18rem, 0.85fr);
  }

  /* A tabs panel carrying a real photo (hhds_render_item_fields()'s
     'image' key) reads better photo-beside-details than stacked
     full-width - also halves the image's rendered CSS width, which
     matters for real client photos that don't have hero-scale native
     resolution (see qa:media's MX03 upscale check). */
  .hhds-tabs__panel:has(.hhds-media) {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    align-items: start;
  }
}

@media (max-width: 47.99rem) {
  .hhds-form { grid-template-columns: 1fr; }

  .hhds-section[data-hhds-motion="swipe-hint"] .hhds-collection {
    grid-auto-columns: min(82vw, 22rem);
    grid-auto-flow: column;
    grid-template-columns: none;
    justify-content: start;
    overflow-x: auto;
    padding-bottom: var(--lib-space-3);
    scroll-padding-inline: var(--lib-space-1);
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
  }

  .hhds-section[data-hhds-motion="swipe-hint"] .hhds-card {
    scroll-snap-align: start;
  }

  .hhds-motion-enabled .hhds-section[data-hhds-motion="marquee"] .hhds-container {
    overflow: hidden;
  }

  .hhds-motion-enabled .hhds-section[data-hhds-motion="marquee"][data-hhds-motion-state="visible"] .hhds-collection {
    width: max-content;
    grid-auto-columns: min(72vw, 18rem);
    grid-auto-flow: column;
    grid-template-columns: none;
    animation: hhds-generation-marquee var(--lib-duration-marquee) var(--lib-motion-ease-linear) infinite alternate;
    will-change: transform;
  }

  .hhds-motion-enabled .hhds-section[data-hhds-motion="marquee"] .hhds-motion-control {
    display: inline-flex;
  }

  .hhds-motion-enabled .hhds-section[data-hhds-motion="marquee"][data-hhds-motion-paused="true"] .hhds-collection {
    animation-play-state: paused;
  }
}

/*
 * Real finding (Hero System Step 3B, via qa:component): scoping this to
 * `.hhds-page *` silently never applies in the Visual Lab -- the Lab
 * wraps every fixture in its own `.lab-canvas` chrome
 * (previews/assets/lab.js), never `.hhds-page` (that only exists in a
 * real WordPress render). HRO-01..05's Visual Lab fixtures never
 * exposed this because they use Path A's real `.lib-button` (its own,
 * separately-correct reduced-motion handling), not this Path B rule --
 * HERO-01/HERO-03 are the first Path B fixtures ever registered in the
 * Lab. A user's reduced-motion preference must not depend on which
 * wrapper happens to contain the content, so this is scoped to every
 * element, not one specific page wrapper.
 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: var(--lib-transition-reduced) !important;
    animation-duration: var(--lib-motion-duration-reduced) !important;
    animation-iteration-count: 1 !important;
  }

  .hhds-motion-target {
    opacity: 1 !important;
    transform: none !important;
  }
}

/*
 * ── Site chrome (HDR-01 / FTR-01) — selected once per project, ART-17 ──
 *
 * Matured 2026-08-12 from the barebones original: real owner feedback on
 * Michelle's Nails Service (staging screenshot review) found the elements
 * too tightly packed, the logo too small with zero hover feedback, no
 * indication of the current page, and — the most serious one — no sticky
 * behavior at all, so the header scrolled away with the page instead of
 * staying reachable. Normalized from the header already matured on the
 * Maggy Prestige Fit project (sticky + frosted glass + active capsule via
 * aria-current, real hover states) into this shared HDR-01, generalized
 * to the current .hhds-header__* naming (Maggy's copy still used the
 * older .lib-site-header__* prefix from before HDR-01 was wired into the
 * generation adapter) and with its bilingual language picker made fully
 * OPTIONAL (.hhds-header__lang, only rendered when a project actually
 * ships >1 language — most HHDS sites, like Michelle's, are single-
 * language and simply omit it).
 */

/* HDR-01 -- Classic Balanced Header. Canonical runtime source; kept in sync with sections/site-header/site-header.css (isolated preview copy). */
/* HDR-01 -- Classic Balanced Header. Canonical runtime source; kept in sync with sections/site-header/site-header.css (isolated preview copy). */
/* HDR-01 -- Classic Balanced Header. Canonical runtime source; kept in sync with sections/site-header/site-header.css (isolated preview copy). */
/* HDR-01 -- Classic Balanced Header. Canonical runtime source; kept in sync with sections/site-header/site-header.css (isolated preview copy). */
/* HDR-01 -- Classic Balanced Header. Canonical runtime source; kept in sync with sections/site-header/site-header.css (isolated preview copy). */
/* HDR-01 -- Classic Balanced Header. Canonical runtime source; kept in sync with sections/site-header/site-header.css (isolated preview copy). */
/* HDR-01 -- Classic Balanced Header. Canonical runtime source; kept in sync with sections/site-header/site-header.css (isolated preview copy). */
/* HDR-01 -- Classic Balanced Header. Canonical runtime source; kept in sync with sections/site-header/site-header.css (isolated preview copy). */
.hhds-header {
  --hhds-header-logo-height: 5rem;
  position: sticky;
  top: 0;
  z-index: 30;
  width: 100%;
  color: var(--lib-color-ink);
  background: color-mix(in srgb, var(--lib-color-surface) 88%, transparent);
  backdrop-filter: blur(0.875rem);
  -webkit-backdrop-filter: blur(0.875rem);
  border-bottom: var(--lib-space-hairline) solid color-mix(in srgb, var(--lib-color-border) 55%, transparent);
  font-family: var(--lib-font-body);
}

/* Padding is deliberately tight (--lib-space-fine-1, 6px) so the logo --
   the largest single element in the row -- occupies most of the header's
   usable inner height instead of competing with generous vertical
   padding for it. The header still only grows ~8px overall vs. the
   pre-redefinition version (76px -> 84px inner height): a bigger logo,
   not a bulkier bar. */
.hhds-header__container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--lib-space-6);
  padding-block: var(--lib-space-1);
}

.hhds-header__brand {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  color: var(--lib-color-ink);
  text-decoration: none;
  transition: opacity var(--lib-transition-base), transform var(--lib-transition-base);
}

.hhds-header__brand:hover,
.hhds-header__brand:focus-visible {
  opacity: 0.8;
  transform: translateY(-0.0625rem);
}

/* Optional responsive-logo <picture> participates directly in the flex
   layout as if it weren't there. */
.hhds-header__brand > picture {
  display: contents;
}

/* Reads the logo/brand-slot contract above -- never a raw height here.
   width: auto preserves each logo type's real aspect ratio at that
   height -- a wide wordmark, a square icon-only mark, and an
   icon+wordmark combination are all sized correctly by this one rule,
   never tiny, without a separate override per logo shape. The preview
   fixture demonstrates this with real edge-to-edge synthetic marks (see
   site-header.html), not placeholder text with font-metric padding
   baked in, which is what made this contract read as unsolved before:
   the box was already correctly sized, but text glyphs only filled
   roughly 40% of their own box height, an artifact of the demo asset,
   not the sizing rule. */
.hhds-header__logo {
  display: block;
  height: var(--hhds-header-logo-height);
  width: auto;
  max-width: none;
}

.hhds-header__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  gap: var(--lib-space-6);
}

.hhds-header__link {
  padding: var(--lib-space-3) var(--lib-space-6);
  border: var(--lib-space-hairline) solid transparent;
  border-radius: var(--lib-radius-pill);
  color: var(--lib-color-muted);
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition:
    color var(--lib-transition-base),
    background var(--lib-transition-base),
    border-color var(--lib-transition-base);
}

.hhds-header__link:hover:not([aria-current="page"]),
.hhds-header__link:focus-visible:not([aria-current="page"]) {
  color: var(--lib-color-primary-strong);
  background: var(--lib-color-panel-soft);
}

.hhds-header__link[aria-current="page"] {
  color: var(--lib-color-ink);
  background: var(--lib-color-panel-soft);
  border-color: color-mix(in srgb, var(--lib-color-border) 70%, transparent);
  font-weight: 800;
}

.hhds-header__action {
  display: flex;
  align-items: center;
  gap: var(--lib-space-4);
  flex-shrink: 0;
}

/* Optional bilingual picker - present only when a project ships >1 language. */
.hhds-header__lang {
  display: inline-flex;
  align-items: stretch;
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: var(--lib-radius-md);
  overflow: hidden;
  flex-shrink: 0;
}

.hhds-header__lang-opt {
  display: inline-flex;
  align-items: center;
  padding: var(--lib-space-fine-1) var(--lib-space-3);
  color: var(--lib-color-muted);
  font-size: var(--lib-font-size-caption);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-decoration: none;
  text-transform: uppercase;
  white-space: nowrap;
  transition: color var(--lib-transition-base), background var(--lib-transition-base);
}

.hhds-header__lang-opt + .hhds-header__lang-opt {
  border-left: var(--lib-space-hairline) solid var(--lib-color-border);
}

.hhds-header__lang-opt[aria-current="true"] {
  color: var(--lib-color-ink);
  background: var(--lib-color-panel-soft);
}

.hhds-header__lang-opt:not([aria-current="true"]):hover,
.hhds-header__lang-opt:not([aria-current="true"]):focus-visible {
  color: var(--lib-color-primary-strong);
}

.hhds-header__menu {
  display: none;
}

.hhds-header__summary {
  list-style: none;
}

.hhds-header__summary::-webkit-details-marker {
  display: none;
}

.hhds-header__summary-icon {
  display: block;
  position: relative;
  width: 1.25rem;
  height: 0.15rem;
  background: currentColor;
}

.hhds-header__summary-icon::before,
.hhds-header__summary-icon::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 0.15rem;
  background: currentColor;
}

.hhds-header__summary-icon::before {
  top: -0.4rem;
}

.hhds-header__summary-icon::after {
  top: 0.4rem;
}

/* Tablet-compact nav -- see adapters/wordpress/generation/generation.css
   for the full rationale (found 2026-08-22 via the catalog-wide
   responsive check). Kept in sync with that canonical file. */
@media (max-width: 1180px) {
  .hhds-header__nav {
    gap: var(--lib-space-3);
  }

  .hhds-header__link {
    padding-inline: var(--lib-space-4);
  }

  .hhds-header__action {
    gap: var(--lib-space-2);
  }

  .hhds-header {
    --hhds-header-logo-height: 4.25rem;
  }
}

/* Narrow phones -- found via qa-component.js's overflow/clipping check
   (directed correction pass, Site Header Family Redefinition): the
   enlarged logo, combined with the brand+menu-toggle-only row this
   width already collapses to, could overflow the very narrowest phone
   viewports. A smaller mobile logo is normal, expected mobile UX, not a
   violation of "the logo must be large" -- that requirement was about
   the desktop presence a project's real (icon-only) logo has room for
   here regardless. */
@media (max-width: 400px) {
  .hhds-header {
    --hhds-header-logo-height: 3.5rem;
  }
}

@media (max-width: 1024px) {
  .hhds-header__nav,
  .hhds-header__action {
    display: none;
  }

  .hhds-header__menu {
    display: block;
    position: relative;
  }

  .hhds-header__summary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--lib-space-2);
    min-width: 2.75rem;
    min-height: 2.75rem;
    padding-inline: var(--lib-space-3);
    border: var(--lib-space-hairline) solid var(--lib-color-border);
    border-radius: var(--lib-radius-md);
    color: var(--lib-color-primary-strong);
    background: var(--lib-color-panel);
    cursor: pointer;
  }

  /* Visible text alongside the icon -- without it, a sighted visitor
     with JavaScript disabled (native <details> still opens without JS)
     saw only an unlabeled icon: near-zero readable text on the page
     before interacting. Found via qa-component.js's no-js-content check
     (HDR-02 Category-by-Category Visual QA, 2026-08-24). aria-label on
     <summary> was updated to match this visible text exactly (WCAG 2.5.3
     Label in Name) instead of keeping a differently-worded aria-label. */
  .hhds-header__summary-text {
    font-size: var(--lib-font-size-caption);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }

  .hhds-header__panel {
    position: absolute;
    top: calc(100% + var(--lib-space-2));
    right: 0;
    z-index: 5;
    display: grid;
    gap: var(--lib-space-1);
    min-width: min(18rem, calc(100vw - 1.5rem));
    padding: var(--lib-space-3);
    border: var(--lib-space-hairline) solid var(--lib-color-border);
    border-radius: var(--lib-radius-md);
    background: var(--lib-color-panel);
    box-shadow: var(--lib-shadow-card);
  }

  .hhds-header__panel .hhds-header__link {
    padding: var(--lib-space-3);
    border-color: transparent;
    border-radius: var(--lib-radius-sm);
  }

  .hhds-header__panel .hhds-header__link:hover:not([aria-current="page"]),
  .hhds-header__panel .hhds-header__link:focus-visible:not([aria-current="page"]) {
    background: var(--lib-color-panel-soft);
  }

  .hhds-header__panel .hhds-header__link[aria-current="page"] {
    border-radius: var(--lib-radius-sm);
  }

  .hhds-header__panel .hhds-button {
    margin-top: var(--lib-space-2);
    text-align: center;
  }

  .hhds-header__lang--mobile {
    display: flex;
    width: 100%;
    border: none;
    border-top: var(--lib-space-hairline) solid var(--lib-color-border);
    border-radius: 0;
    overflow: visible;
    margin-top: var(--lib-space-2);
    padding-top: var(--lib-space-2);
  }

  .hhds-header__lang--mobile .hhds-header__lang-opt {
    flex: 1;
    justify-content: center;
    /* min-height matches .hhds-header__summary's real 44px target
       elsewhere in this same file -- padding alone (space-2) left this
       at ~35px, under the minimum tap target size. Found via
       qa-component.js's target-size check (HDR-02 Category-by-Category
       Visual QA, 2026-08-24). */
    min-height: 2.75rem;
    padding: var(--lib-space-2) var(--lib-space-3);
  }
}

/* Mirrors the real, already-correct global rule in
   adapters/wordpress/generation/generation-hhds.css (`.hhds-page *`
   under 

/* HDR-02 -- Editorial Underline Header. Canonical runtime source; kept in sync with sections/site-header-editorial/site-header-editorial.css (isolated preview copy). */
.hhds-header-editorial {
  --hhds-header-logo-height: 5rem;
  position: sticky;
  top: 0;
  z-index: 30;
  width: 100%;
  color: var(--lib-color-ink);
  background: color-mix(in srgb, var(--lib-color-surface) 88%, transparent);
  backdrop-filter: blur(0.875rem);
  -webkit-backdrop-filter: blur(0.875rem);
  border-bottom: var(--lib-space-hairline) solid color-mix(in srgb, var(--lib-color-border) 55%, transparent);
  font-family: var(--lib-font-body);
}

/* Same tight padding-block as the rest of the family (Site Header
   Family Redefinition correction pass) -- the logo occupies most of the
   header's usable inner height instead of competing with generous
   vertical padding for it. */
.hhds-header-editorial__container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--lib-space-6);
  padding-block: var(--lib-space-1);
}

.hhds-header-editorial__brand {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  color: var(--lib-color-ink);
  text-decoration: none;
  transition: opacity var(--lib-transition-base), transform var(--lib-transition-base);
}

.hhds-header-editorial__brand:hover,
.hhds-header-editorial__brand:focus-visible {
  opacity: 0.8;
  transform: translateY(-0.0625rem);
}

.hhds-header-editorial__brand > picture {
  display: contents;
}

/* Reads the shared logo/brand-slot contract -- see
   sections/site-header/site-header.css for the full rationale. */
.hhds-header-editorial__logo {
  display: block;
  height: var(--hhds-header-logo-height);
  width: auto;
  max-width: none;
}

/* Centered, same as HDR-01's .hhds-header__nav -- the correction pass
   restores this; the prior "masthead" grouping (logo+nav together, left-
   weighted) was ruled an incorrect interpretation. */
.hhds-header-editorial__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  gap: var(--lib-space-5);
  /* The editorial "underline system": a full baseline rule spans the
     whole nav row; each link's own ::after segment (below) sits on top
     of it, colored on hover/current. This is the real typographic
     distinction from HDR-01, not a different zone layout. */
  border-bottom: var(--lib-space-hairline) solid var(--lib-color-border);
  padding-bottom: var(--lib-space-1);
}

/* Typographic treatment: uppercase, letter-spaced, medium weight -- a
   deliberately different voice from HDR-01's bold pill-background nav,
   not just a different active-state indicator. */
.hhds-header-editorial__link {
  position: relative;
  padding-block: var(--lib-space-2);
  color: var(--lib-color-muted);
  font-size: var(--lib-font-size-small);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--lib-transition-base);
}

.hhds-header-editorial__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.1875rem;
  height: 0.125rem;
  border-radius: var(--lib-radius-pill);
  background: var(--lib-color-primary);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform var(--lib-transition-base);
}

.hhds-header-editorial__link:hover,
.hhds-header-editorial__link:focus-visible {
  color: var(--lib-color-primary-strong);
}

.hhds-header-editorial__link:hover::after,
.hhds-header-editorial__link:focus-visible::after {
  transform: scaleX(1);
}

.hhds-header-editorial__link[aria-current="page"] {
  color: var(--lib-color-ink);
  font-weight: 800;
}

.hhds-header-editorial__link[aria-current="page"]::after {
  transform: scaleX(1);
}

/* CTA + language picker integrated in one right-side cluster (Site
   Header Family Redefinition correction pass) -- same pattern as
   HDR-01's .hhds-header__action, not a separate utility bar. */
.hhds-header-editorial__action {
  display: flex;
  align-items: center;
  gap: var(--lib-space-4);
  flex-shrink: 0;
}

.hhds-header-editorial__lang {
  display: inline-flex;
  align-items: stretch;
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: var(--lib-radius-md);
  overflow: hidden;
  flex-shrink: 0;
}

.hhds-header-editorial__lang-opt {
  display: inline-flex;
  align-items: center;
  padding: var(--lib-space-fine-1) var(--lib-space-3);
  color: var(--lib-color-muted);
  font-size: var(--lib-font-size-caption);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-decoration: none;
  text-transform: uppercase;
  white-space: nowrap;
  transition: color var(--lib-transition-base), background var(--lib-transition-base);
}

.hhds-header-editorial__lang-opt + .hhds-header-editorial__lang-opt {
  border-left: var(--lib-space-hairline) solid var(--lib-color-border);
}

.hhds-header-editorial__lang-opt[aria-current="true"] {
  color: var(--lib-color-ink);
  background: var(--lib-color-panel-soft);
}

.hhds-header-editorial__lang-opt:not([aria-current="true"]):hover,
.hhds-header-editorial__lang-opt:not([aria-current="true"]):focus-visible {
  color: var(--lib-color-primary-strong);
}

.hhds-header-editorial__menu {
  display: none;
}

.hhds-header-editorial__summary {
  list-style: none;
}

.hhds-header-editorial__summary::-webkit-details-marker {
  display: none;
}

.hhds-header-editorial__summary-icon {
  display: block;
  position: relative;
  width: 1.25rem;
  height: 0.15rem;
  background: currentColor;
}

.hhds-header-editorial__summary-icon::before,
.hhds-header-editorial__summary-icon::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 0.15rem;
  background: currentColor;
}

.hhds-header-editorial__summary-icon::before {
  top: -0.4rem;
}

.hhds-header-editorial__summary-icon::after {
  top: 0.4rem;
}

@media (max-width: 1180px) {
  .hhds-header-editorial__nav {
    gap: var(--lib-space-3);
  }

  .hhds-header-editorial__link {
    padding-inline: var(--lib-space-2);
  }

  .hhds-header-editorial__action {
    gap: var(--lib-space-2);
  }

  .hhds-header-editorial {
    --hhds-header-logo-height: 4.25rem;
  }
}

/* Narrow phones -- same real overflow fix as HDR-01
   (sections/site-header/site-header.css), found via qa-component.js. */
@media (max-width: 400px) {
  .hhds-header-editorial {
    --hhds-header-logo-height: 3.5rem;
  }
}

@media (max-width: 1024px) {
  .hhds-header-editorial__nav,
  .hhds-header-editorial__action {
    display: none;
  }

  .hhds-header-editorial__menu {
    display: block;
    position: relative;
  }

  .hhds-header-editorial__summary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--lib-space-2);
    min-width: 2.75rem;
    min-height: 2.75rem;
    padding-inline: var(--lib-space-3);
    border: var(--lib-space-hairline) solid var(--lib-color-border);
    border-radius: var(--lib-radius-md);
    color: var(--lib-color-primary-strong);
    background: var(--lib-color-panel);
    cursor: pointer;
  }

  .hhds-header-editorial__summary-text {
    font-size: var(--lib-font-size-caption);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }

  .hhds-header-editorial__panel {
    position: absolute;
    top: calc(100% + var(--lib-space-2));
    right: 0;
    z-index: 5;
    display: grid;
    gap: var(--lib-space-1);
    min-width: min(18rem, calc(100vw - 1.5rem));
    padding: var(--lib-space-3);
    border: var(--lib-space-hairline) solid var(--lib-color-border);
    border-radius: var(--lib-radius-md);
    background: var(--lib-color-panel);
    box-shadow: var(--lib-shadow-card);
  }

  .hhds-header-editorial__panel .hhds-header-editorial__link {
    padding: var(--lib-space-3);
    border-left: 0.1875rem solid transparent;
    border-radius: 0;
    text-transform: none;
    letter-spacing: normal;
    font-weight: 700;
    transition: border-color var(--lib-transition-base), background var(--lib-transition-base), color var(--lib-transition-base);
  }

  .hhds-header-editorial__panel .hhds-header-editorial__link::after {
    display: none;
  }

  .hhds-header-editorial__panel .hhds-header-editorial__link:hover,
  .hhds-header-editorial__panel .hhds-header-editorial__link:focus-visible {
    border-left-color: color-mix(in srgb, var(--lib-color-primary) 45%, transparent);
    background: var(--lib-color-panel-soft);
  }

  .hhds-header-editorial__panel .hhds-header-editorial__link[aria-current="page"] {
    border-left-color: var(--lib-color-primary);
  }

  .hhds-header-editorial__panel .hhds-button {
    margin-top: var(--lib-space-2);
    text-align: center;
  }

  .hhds-header-editorial__lang--mobile {
    display: flex;
    width: 100%;
    border-top: var(--lib-space-hairline) solid var(--lib-color-border);
    margin-top: var(--lib-space-2);
    padding-top: var(--lib-space-2);
  }

  .hhds-header-editorial__lang--mobile .hhds-header-editorial__lang-opt {
    flex: 1;
    justify-content: center;
    min-height: 2.75rem;
    padding: var(--lib-space-2) var(--lib-space-3);
  }
}

/* HDR-03 -- Framed Floating Header. Canonical runtime source; kept in sync with sections/site-header-drawer/site-header-drawer.css (isolated preview copy). */
.hhds-header-drawer {
  --hhds-header-logo-height: 4.75rem;
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 40;
  display: flex;
  justify-content: center;
  padding-block-start: var(--lib-space-4);
  padding-inline: var(--lib-gutter);
  pointer-events: none;
  font-family: var(--lib-font-body);
}

/* The visible floating surface. Padding is deliberately tight
   (--lib-space-fine-1 block) so the logo occupies most of the frame's
   usable inner height, same principle as HDR-01/HDR-02/HDR-04. */
.hhds-header-drawer__frame {
  pointer-events: auto;
  width: 100%;
  max-width: var(--lib-container-wide);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--lib-space-6);
  padding-block: var(--lib-space-1);
  padding-inline: var(--lib-space-6);
  color: var(--lib-color-ink);
  background: color-mix(in srgb, var(--lib-color-surface) 82%, transparent);
  backdrop-filter: blur(0.875rem);
  -webkit-backdrop-filter: blur(0.875rem);
  border: var(--lib-space-hairline) solid color-mix(in srgb, var(--lib-color-border) 55%, transparent);
  border-radius: var(--lib-radius-xl);
  box-shadow: var(--lib-shadow-card-soft);
  transition: background var(--lib-transition-base), box-shadow var(--lib-transition-base), border-color var(--lib-transition-base);
}

/* Scroll-driven state -- the frame becomes more solid/elevated rather
   than a bar becoming opaque, keeping the floating identity intact
   while still signalling "you've scrolled." Toggled by
   site-header-drawer.js past a fixed, proven scroll threshold; opts out
   entirely when the header carries data-scroll-solidify="false" (see
   README "Props"). */
.hhds-header-drawer.is-scrolled .hhds-header-drawer__frame {
  background: color-mix(in srgb, var(--lib-color-surface) 97%, transparent);
  border-color: color-mix(in srgb, var(--lib-color-border) 70%, transparent);
  box-shadow: var(--lib-shadow-card-hover);
}

.hhds-header-drawer__brand {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  color: var(--lib-color-ink);
  text-decoration: none;
  transition: opacity var(--lib-transition-base), transform var(--lib-transition-base);
}

.hhds-header-drawer__brand:hover,
.hhds-header-drawer__brand:focus-visible {
  opacity: 0.8;
  transform: translateY(-0.0625rem);
}

/* Optional responsive-logo <picture> (shared capability with HDR-01/HDR-02,
   Header Convergence Audit Phase 2) participates directly in the flex
   layout as if it weren't there. */
.hhds-header-drawer__brand > picture {
  display: contents;
}

/* Reads the shared logo/brand-slot contract -- see
   sections/site-header/site-header.css for the full rationale. */
.hhds-header-drawer__logo {
  display: block;
  height: var(--hhds-header-logo-height);
  width: auto;
  max-width: none;
}

.hhds-header-drawer__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  gap: var(--lib-space-6);
}

.hhds-header-drawer__link {
  padding: var(--lib-space-2) var(--lib-space-5);
  border-radius: var(--lib-radius-pill);
  color: var(--lib-color-muted);
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--lib-transition-base), background var(--lib-transition-base);
}

.hhds-header-drawer__link:hover:not([aria-current="page"]),
.hhds-header-drawer__link:focus-visible:not([aria-current="page"]) {
  color: var(--lib-color-primary-strong);
  background: var(--lib-color-panel-soft);
}

.hhds-header-drawer__link[aria-current="page"] {
  color: var(--lib-color-ink);
  background: var(--lib-color-panel-soft);
  font-weight: 800;
}

.hhds-header-drawer__action {
  display: flex;
  align-items: center;
  gap: var(--lib-space-3);
  flex-shrink: 0;
}

.hhds-header-drawer__toggle {
  display: none;
  align-items: center;
  justify-content: center;
  gap: var(--lib-space-2);
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding-inline: var(--lib-space-3);
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: var(--lib-radius-md);
  color: var(--lib-color-primary-strong);
  background: var(--lib-color-panel);
  cursor: pointer;
  flex-shrink: 0;
}

.hhds-header-drawer__toggle-icon {
  display: block;
  position: relative;
  width: 1.25rem;
  height: 0.15rem;
  background: currentColor;
  transition: background var(--lib-transition-base);
}

.hhds-header-drawer__toggle-icon::before,
.hhds-header-drawer__toggle-icon::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 0.15rem;
  background: currentColor;
  transition: transform var(--lib-transition-base), top var(--lib-transition-base);
}

.hhds-header-drawer__toggle-icon::before {
  top: -0.4rem;
}

.hhds-header-drawer__toggle-icon::after {
  top: 0.4rem;
}

/* Animated hamburger -> X, driven by aria-expanded (the JS toggle's own
   state, not a second hand-rolled flag). */
.hhds-header-drawer__toggle[aria-expanded="true"] .hhds-header-drawer__toggle-icon {
  background: transparent;
}

.hhds-header-drawer__toggle[aria-expanded="true"] .hhds-header-drawer__toggle-icon::before {
  top: 0;
  transform: rotate(45deg);
}

.hhds-header-drawer__toggle[aria-expanded="true"] .hhds-header-drawer__toggle-icon::after {
  top: 0;
  transform: rotate(-45deg);
}

.hhds-header-drawer__toggle-text {
  font-size: var(--lib-font-size-caption);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.hhds-header-drawer__backdrop {
  position: fixed;
  inset: 0;
  z-index: 45;
  background: color-mix(in srgb, var(--lib-color-deep) 55%, transparent);
  backdrop-filter: blur(0.25rem);
  -webkit-backdrop-filter: blur(0.25rem);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--lib-transition-reveal), visibility 0s linear var(--lib-transition-reveal);
}

.hhds-header-drawer__backdrop.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--lib-transition-reveal);
}

.hhds-header-drawer__panel {
  position: fixed;
  inset-block: 0;
  inset-inline-end: 0;
  z-index: 46;
  display: flex;
  flex-direction: column;
  gap: var(--lib-space-1);
  width: min(20rem, 88vw);
  padding: calc(var(--lib-space-3) + 4.5rem) var(--lib-space-5) var(--lib-space-5);
  background: var(--lib-color-panel);
  box-shadow: var(--lib-shadow-card);
  transform: translateX(100%);
  transition: transform var(--lib-transition-reveal);
  overflow-y: auto;
}

.hhds-header-drawer__panel.is-open {
  transform: translateX(0);
}

.hhds-header-drawer__panel .hhds-header-drawer__link {
  padding: var(--lib-space-3);
  border-radius: var(--lib-radius-sm);
  text-align: left;
}

.hhds-header-drawer__panel .hhds-header-drawer__link:hover:not([aria-current="page"]),
.hhds-header-drawer__panel .hhds-header-drawer__link:focus-visible:not([aria-current="page"]) {
  background: var(--lib-color-panel-soft);
}

.hhds-header-drawer__panel .hhds-button {
  margin-top: var(--lib-space-2);
  text-align: center;
}

@media (max-width: 900px) {
  .hhds-header-drawer {
    --hhds-header-logo-height: 4rem;
    padding-block-start: var(--lib-space-2);
    padding-inline: var(--lib-space-3);
  }

  .hhds-header-drawer__frame {
    padding-inline: var(--lib-space-4);
    border-radius: var(--lib-radius-lg);
  }

  .hhds-header-drawer__nav,
  .hhds-header-drawer__action {
    display: none;
  }

  .hhds-header-drawer__toggle {
    display: inline-flex;
  }
}

/* Narrow phones -- same real overflow fix as HDR-01
   (sections/site-header/site-header.css), found via qa-component.js. */
@media (max-width: 400px) {
  .hhds-header-drawer {
    --hhds-header-logo-height: 3.5rem;
  }
}

/* HDR-04 -- Centered Brand Split Header. Canonical runtime source; kept in sync with sections/site-header-split/site-header-split.css (isolated preview copy). */
.hhds-header-split {
  --hhds-header-logo-height: 5rem;
  position: sticky;
  top: 0;
  z-index: 30;
  width: 100%;
  color: var(--lib-color-ink);
  background: color-mix(in srgb, var(--lib-color-surface) 88%, transparent);
  backdrop-filter: blur(0.875rem);
  -webkit-backdrop-filter: blur(0.875rem);
  border-bottom: var(--lib-space-hairline) solid color-mix(in srgb, var(--lib-color-border) 55%, transparent);
  font-family: var(--lib-font-body);
}

.hhds-header-split__container {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: var(--lib-space-6);
  padding-block: var(--lib-space-1);
}

.hhds-header-split__nav {
  display: flex;
  align-items: center;
  gap: var(--lib-space-5);
  min-width: 0;
}

/* Nav items cluster close to the logo (the extra 1fr space becomes edge
   margin instead) -- reads as a deliberate, spacious composition rather
   than links stranded at the outer container edges. */
.hhds-header-split__nav--left {
  grid-column: 1;
  justify-self: end;
}

/* nav-right lives inside .hhds-header-split__right (its own flanking
   grid cell, alongside the actions cluster) -- see the file header
   comment for why this must not be a standalone grid column. */

.hhds-header-split__link {
  padding: var(--lib-space-2) var(--lib-space-4);
  border-radius: var(--lib-radius-pill);
  color: var(--lib-color-muted);
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--lib-transition-base), background var(--lib-transition-base);
}

.hhds-header-split__link:hover:not([aria-current="page"]),
.hhds-header-split__link:focus-visible:not([aria-current="page"]) {
  color: var(--lib-color-primary-strong);
  background: var(--lib-color-panel-soft);
}

.hhds-header-split__link[aria-current="page"] {
  color: var(--lib-color-ink);
  background: var(--lib-color-panel-soft);
  font-weight: 800;
}

.hhds-header-split__brand {
  grid-column: 2;
  display: inline-flex;
  align-items: center;
  justify-self: center;
  color: var(--lib-color-ink);
  text-decoration: none;
  transition: opacity var(--lib-transition-base), transform var(--lib-transition-base);
}

.hhds-header-split__brand:hover,
.hhds-header-split__brand:focus-visible {
  opacity: 0.8;
  transform: translateY(-0.0625rem);
}

.hhds-header-split__brand > picture {
  display: contents;
}

/* Reads the shared logo/brand-slot contract -- see
   sections/site-header/site-header.css for the full rationale. Because
   this family makes the logo the visual center of the whole
   composition, it should feel substantial -- the same height as
   HDR-01/HDR-02, not reduced. */
.hhds-header-split__logo {
  display: block;
  height: var(--hhds-header-logo-height);
  width: auto;
  max-width: none;
}

/* Right-side flanking grid cell -- nav-right and the actions cluster
   share it so this side of the header occupies exactly one grid track,
   matching nav-left's single track on the other side (see the file
   header comment). */
.hhds-header-split__right {
  grid-column: 3;
  justify-self: end;
  display: flex;
  align-items: center;
  gap: var(--lib-space-6);
  min-width: 0;
}

.hhds-header-split__action {
  display: flex;
  align-items: center;
  gap: var(--lib-space-4);
  flex-shrink: 0;
}

.hhds-header-split__lang {
  display: inline-flex;
  align-items: stretch;
  border: var(--lib-space-hairline) solid var(--lib-color-border);
  border-radius: var(--lib-radius-md);
  overflow: hidden;
  flex-shrink: 0;
}

.hhds-header-split__lang-opt {
  display: inline-flex;
  align-items: center;
  padding: var(--lib-space-fine-1) var(--lib-space-3);
  color: var(--lib-color-muted);
  font-size: var(--lib-font-size-caption);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-decoration: none;
  text-transform: uppercase;
  white-space: nowrap;
  transition: color var(--lib-transition-base), background var(--lib-transition-base);
}

.hhds-header-split__lang-opt + .hhds-header-split__lang-opt {
  border-left: var(--lib-space-hairline) solid var(--lib-color-border);
}

.hhds-header-split__lang-opt[aria-current="true"] {
  color: var(--lib-color-ink);
  background: var(--lib-color-panel-soft);
}

.hhds-header-split__lang-opt:not([aria-current="true"]):hover,
.hhds-header-split__lang-opt:not([aria-current="true"]):focus-visible {
  color: var(--lib-color-primary-strong);
}

.hhds-header-split__menu {
  display: none;
}

.hhds-header-split__summary {
  list-style: none;
}

.hhds-header-split__summary::-webkit-details-marker {
  display: none;
}

.hhds-header-split__summary-icon {
  display: block;
  position: relative;
  width: 1.25rem;
  height: 0.15rem;
  background: currentColor;
}

.hhds-header-split__summary-icon::before,
.hhds-header-split__summary-icon::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 0.15rem;
  background: currentColor;
}

.hhds-header-split__summary-icon::before {
  top: -0.4rem;
}

.hhds-header-split__summary-icon::after {
  top: 0.4rem;
}

@media (max-width: 1180px) {
  .hhds-header-split__container {
    gap: var(--lib-space-3);
  }

  .hhds-header-split__nav {
    gap: var(--lib-space-2);
  }

  .hhds-header-split__link {
    padding-inline: var(--lib-space-3);
  }

  .hhds-header-split__right {
    gap: var(--lib-space-3);
  }

  .hhds-header-split__action {
    gap: var(--lib-space-2);
  }

  .hhds-header-split {
    --hhds-header-logo-height: 4.25rem;
  }
}

/* Narrow phones -- same real overflow fix as HDR-01
   (sections/site-header/site-header.css), found via qa-component.js. */
@media (max-width: 400px) {
  .hhds-header-split {
    --hhds-header-logo-height: 3.5rem;
  }
}

/* Mobile: "LOGO ... MENU" -- split navigation is not preserved
   literally on small screens (explicit instruction). The container
   switches from the desktop 3-column grid back to a plain flex row;
   nav-left/nav-right/.hhds-header-split__right are all display:none, so
   the brand link is the only child left before the menu trigger -- it
   sits flush left against justify-content: space-between, with the menu
   trigger flush right. Same zero-JS <details> mobile mechanism as
   HDR-01/HDR-02/HDR-03's non-drawer families -- family-consistent, not
   a fifth pattern. */
@media (max-width: 1024px) {
  .hhds-header-split__container {
    display: flex;
    justify-content: space-between;
  }

  .hhds-header-split__nav,
  .hhds-header-split__right {
    display: none;
  }

  .hhds-header-split__menu {
    display: block;
    position: relative;
  }

  .hhds-header-split__summary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--lib-space-2);
    min-width: 2.75rem;
    min-height: 2.75rem;
    padding-inline: var(--lib-space-3);
    border: var(--lib-space-hairline) solid var(--lib-color-border);
    border-radius: var(--lib-radius-md);
    color: var(--lib-color-primary-strong);
    background: var(--lib-color-panel);
    cursor: pointer;
  }

  .hhds-header-split__summary-text {
    font-size: var(--lib-font-size-caption);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }

  .hhds-header-split__panel {
    position: absolute;
    top: calc(100% + var(--lib-space-2));
    right: 0;
    z-index: 5;
    display: grid;
    gap: var(--lib-space-1);
    min-width: min(18rem, calc(100vw - 1.5rem));
    padding: var(--lib-space-3);
    border: var(--lib-space-hairline) solid var(--lib-color-border);
    border-radius: var(--lib-radius-md);
    background: var(--lib-color-panel);
    box-shadow: var(--lib-shadow-card);
  }

  .hhds-header-split__panel .hhds-header-split__link {
    padding: var(--lib-space-3);
    border-radius: var(--lib-radius-sm);
  }

  .hhds-header-split__panel .hhds-header-split__link:hover:not([aria-current="page"]),
  .hhds-header-split__panel .hhds-header-split__link:focus-visible:not([aria-current="page"]) {
    background: var(--lib-color-panel-soft);
  }

  .hhds-header-split__panel 

  .hhds-header-split__lang--mobile {
    display: flex;
    width: 100%;
    border: none;
    border-top: var(--lib-space-hairline) solid var(--lib-color-border);
    border-radius: 0;
    overflow: visible;
    margin-top: var(--lib-space-2);
    padding-top: var(--lib-space-2);
  }

  .hhds-header-split__lang--mobile .hhds-header-split__lang-opt {
    flex: 1;
    justify-content: center;
    min-height: 2.75rem;
    padding: var(--lib-space-2) var(--lib-space-3);
  }
}

.hhds-button {
  display: inline-flex;
  min-height: 3rem;
  align-items: center;
  justify-content: center;
  padding: var(--lib-button-padding-y, var(--lib-space-3)) var(--lib-button-padding-x, var(--lib-space-6));
  border: var(--lib-button-border-width, var(--lib-space-hairline)) solid transparent;
  border-radius: var(--lib-button-radius, var(--lib-radius-pill));
  gap: var(--lib-button-gap, var(--lib-space-2));
  font-family: var(--lib-button-font-family, inherit);
  font-size: var(--lib-button-font-size, inherit);
  font-weight: var(--lib-button-font-weight, 800);
  letter-spacing: var(--lib-button-letter-spacing, inherit);
  text-transform: var(--lib-button-text-transform, inherit);
  line-height: var(--lib-button-line-height, inherit);
  text-decoration: none;
  transition: transform var(--lib-transition-base), box-shadow var(--lib-transition-base), background-color var(--lib-transition-base);
}

.hhds-footer {
  width: 100%;
  color: var(--lib-color-inverse);
  background: var(--lib-gradient-deep);
  font-family: var(--lib-font-body);
}

.hhds-footer .hhds-container {
  padding-block: var(--lib-space-10);
}

/*
 * Real bug found 2026-08-11 (owner report, live screenshot): this grid
 * used to live directly on .hhds-container, with .hhds-footer__bottom
 * (grid-column: 1 / -1) as a sibling grid item alongside the real
 * columns. A full-width-spanning item inside an auto-fit grid is a real,
 * documented CSS Grid quirk - it inflates the implicit track count the
 * browser allocates, so auto-fit created more column tracks than there
 * were real columns to fill, leaving dead space on the right instead of
 * the columns spanning the full footer width. Fix: the auto-fit grid now
 * only ever contains the real columns (brand + link groups) - the bottom
 * bar is a plain sibling block below it, full width by default, no grid
 * math involved.
 */
.hhds-footer__top {
  display: grid;
  grid-template-columns: minmax(14rem, 1.2fr) repeat(auto-fit, minmax(10rem, 0.7fr));
  gap: var(--lib-space-8);
}

.hhds-footer__brand-name {
  margin: 0;
  font-family: var(--lib-font-heading);
  font-size: var(--lib-font-size-subheading);
  font-weight: 900;
}

.hhds-footer__brand-summary {
  max-width: 26rem;
  margin: var(--lib-space-4) 0 0;
  color: color-mix(in srgb, var(--lib-color-inverse) 72%, transparent);
}

.hhds-footer__group-title {
  margin: 0 0 var(--lib-space-4);
  color: color-mix(in srgb, var(--lib-color-inverse) 86%, transparent);
  font-size: var(--lib-font-size-caption);
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.hhds-footer__links {
  display: grid;
  gap: var(--lib-space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.hhds-footer__link {
  color: color-mix(in srgb, var(--lib-color-inverse) 70%, transparent);
  text-decoration: none;
}

.hhds-footer__link:hover,
.hhds-footer__link:focus-visible {
  color: var(--lib-color-inverse);
}

.hhds-footer__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--lib-space-4);
  margin-top: var(--lib-space-5);
  padding-top: var(--lib-space-5);
  border-top: var(--lib-space-hairline) solid color-mix(in srgb, var(--lib-color-inverse) 16%, transparent);
  color: color-mix(in srgb, var(--lib-color-inverse) 62%, transparent);
  font-size: var(--lib-font-size-small);
}

.hhds-footer__copyright {
  margin: 0;
}

.hhds-footer__legal {
  display: flex;
  gap: var(--lib-space-4);
}

.hhds-footer__legal-link {
  color: inherit;
  text-decoration: none;
}

.hhds-footer__legal-link:hover,
.hhds-footer__legal-link:focus-visible {
  color: var(--lib-color-inverse);
}

@media (max-width: 820px) {
  .hhds-footer__top {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 540px) {
  .hhds-footer__top {
    grid-template-columns: 1fr;
  }

  .hhds-footer__bottom {
    flex-direction: column;
    align-items: flex-start;
  }
}

/*
 * ===========================================================
 * HERO-01 -- Conversion Split (Hero System Step 3B -- catalog/
 * governance/HERO_CONVERGENCE_AUDIT.md). Real evidence: Empire Metal
 * Solutions' true 2-column grid + the generic engine's real gallery.
 * Content and a bounded visual zone (frame or gallery, from Step 2/3A's
 * primitives, reused verbatim below via the existing hhds-hero__frame
 * and hhds-hero__gallery classes -- only this family's own wrapper/
 * content classes are new).
 * ===========================================================
 */

.hhds-hero-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  gap: clamp(2rem, 5vw, 3rem);
}

.hhds-hero-split__content {
  display: flex;
  flex-direction: column;
  gap: var(--lib-space-6);
}

.hhds-hero-split__content .hhds-section__title {
  font-size: clamp(2.25rem, 4.75vw, 4rem);
}

.hhds-hero-split__closing {
  margin: 0;
  max-width: 32rem;
  font-size: var(--lib-font-size-small);
  color: var(--lib-text-secondary);
}

.hhds-hero-split__visual {
  min-width: 0;
}

/* No visual zone content on this narrow a viewport should ever force the
   page wider than it is -- gallery/frame already handle their own
   internal responsive behavior (Step 2/3A); this only bounds the column
   itself. */
@media (max-width: 47.99rem) {
  .hhds-hero-split__visual {
    width: 100%;
  }
}

/* Same 48rem breakpoint the Framed Visual Zone primitives already use
   internally (Step 2, Part 4) -- one unified transition point, not a
   second breakpoint the visual zone and its parent grid disagree on. */
@media (min-width: 48rem) {
  .hhds-hero-split {
    grid-template-columns: minmax(0, 1.15fr) minmax(22rem, 0.85fr);
    min-height: clamp(34rem, 72svh, 46rem);
  }

  .hhds-hero-split__content {
    max-width: 38rem;
  }
}

/*
 * ===========================================================
 * HERO-03 -- Immersive Visual (Hero System Step 3B). Real evidence: HH
 * Digital Studio's full-bleed photo + Maggy Prestige Fit's full-bleed
 * video -- two independent projects, one architecture. Uses the same
 * Hero Background primitive (Step 2, Part 2) via .hhds-hero__background*
 * (reused verbatim); only the family wrapper/content classes below are
 * new.
 * ===========================================================
 */

.hhds-hero-immersive {
  position: relative;
  z-index: 1;
  display: flex;
  /* Brand-owned vertical placement of the content block (2026-10-14):
     bottom by default; a brand whose home hero centers it sets center. */
  align-items: var(--lib-hero-content-align, flex-end);
  /* svh (small viewport height), same real pattern already used by
     sections/split-hero and sections/inner-page-hero (both real Empire
     evidence) -- assumes the mobile browser's own chrome is visible, so
     content never gets clipped when it appears. Not 100vh (the Step 3B
     brief explicitly rejects blindly copying HHDS's real value) and not
     dvh (no real precedent for it anywhere else in this system yet). */
  min-height: calc(clamp(26rem, 78svh, 34rem) + var(--lib-site-header-overlay, 0px));
  padding-block: clamp(3rem, 8svh, 5rem);
  /* A transparent site header drawn over the hero (project token
     --lib-site-header-overlay) must never cover the eyebrow or the H1. */
  padding-top: calc(clamp(3rem, 8svh, 5rem) + var(--lib-site-header-overlay, 0px));
}

/* --lib-color-inverse deliberately NOT migrated across this whole
   .hhds-hero-immersive__* block below: this file's own comment already
   documents HERO-03 as an "always-data-surface=DARK environment" by
   real evidence -- the same legitimate fixed-dark case as the
   [data-surface="DARK"] block above. */
.hhds-hero-immersive__content {
  display: flex;
  flex-direction: column;
  gap: var(--lib-space-6);
  /* Brand-owned measure (2026-10-14): a brand whose H1 reads on one line
     (Joe's home) widens it; the summary keeps its own readable measure. */
  max-width: var(--lib-hero-content-max, 46rem);
  color: var(--lib-color-inverse);
}

.hhds-hero-immersive__content .hhds-section__title {
  font-size: var(--lib-hero-title-size, clamp(2.5rem, 6vw, 4.75rem));
  /* Brand-owned title type (2026-10-14): a brand whose home H1 is set in
     its own style (Joe's: italic, uppercase, 800) maps it here so the
     service H1 reads at the same size and weight as the home. */
  font-style: var(--lib-hero-title-style, normal);
  font-weight: var(--lib-hero-title-weight, inherit);
  line-height: var(--lib-hero-title-line-height, 1.02);
  letter-spacing: var(--lib-hero-title-letter-spacing, inherit);
  word-spacing: var(--lib-hero-title-word-spacing, normal);
  text-transform: var(--lib-hero-title-transform, none);
}

.hhds-hero-immersive__closing {
  margin: 0;
  max-width: 30rem;
  font-size: var(--lib-font-size-small);
  color: color-mix(in srgb, var(--lib-color-inverse) 78%, transparent);
}

/* HERO-03's whole premise is a full-bleed, always-data-surface="DARK"
   environment (real evidence: both HHDS and Maggy always show white
   text over their real photo/video) -- unconditional inverse, matching
   .hhds-hero-immersive__content's own base above.
   Governance correction pass 8 (2026-08-26): the `.hhds-hero--
   foreground-dark` override this comment used to describe is RETIRED
   (see this file's earlier note near .hhds-hero__background::after) --
   HERO-03 never actually emitted that class in the first place (its
   canonical preview never sets `background.foreground`), so this is a
   no-op removal for its own rendering, kept in sync with the shared
   mechanism's retirement elsewhere. */
.hhds-hero-immersive__content .hhds-section__summary {
  max-width: var(--lib-hero-summary-max, none);
  color: color-mix(in srgb, var(--lib-color-inverse) 82%, transparent);
}

/*
 * Hero actions take the brand's own button (2026-10-14, owner: "joes tiene
 * sus propios botones"). Shape and type come from the shared --lib-button-*
 * contract (button-system README); the look of an action over the hero
 * photo is brand-owned through --lib-hero-action-*, defaulting to the
 * brand's regular primary button. Nothing here is a library color choice.
 */
.hhds-hero-immersive .hhds-actions .hhds-button--primary {
  border-width: var(--lib-hero-action-border-width, var(--lib-button-border-width, var(--lib-space-hairline)));
  border-color: var(--lib-hero-action-border, var(--lib-button-primary-border, transparent));
  color: var(--lib-hero-action-color, var(--lib-button-primary-color, var(--lib-action-primary-text)));
  font-weight: var(--lib-hero-action-font-weight, var(--lib-button-font-weight, 800));
  background: var(--lib-hero-action-bg, var(--lib-button-primary-bg, var(--lib-gradient-primary)));
  box-shadow: var(--lib-hero-action-shadow, var(--lib-button-primary-shadow, var(--lib-shadow-button)));
  -webkit-backdrop-filter: var(--lib-hero-action-backdrop, none);
  backdrop-filter: var(--lib-hero-action-backdrop, none);
}

.hhds-hero-immersive .hhds-actions .hhds-button--primary:hover,
.hhds-hero-immersive .hhds-actions .hhds-button--primary:focus-visible {
  border-color: var(--lib-hero-action-border-hover, var(--lib-button-primary-border-hover, var(--lib-button-primary-border, transparent)));
  color: var(--lib-hero-action-color, var(--lib-button-primary-color, var(--lib-action-primary-text)));
  background: var(--lib-hero-action-bg-hover, var(--lib-button-primary-bg-hover, var(--lib-button-primary-bg, var(--lib-gradient-primary))));
  box-shadow: var(--lib-hero-action-shadow-hover, var(--lib-hero-action-shadow, var(--lib-button-primary-shadow, var(--lib-shadow-button))));
}

@media (max-width: 47.99rem) {
  .hhds-hero-immersive .hhds-actions .hhds-button {
    padding: var(--lib-button-mobile-padding-y, var(--lib-button-padding-y, var(--lib-space-3))) var(--lib-button-mobile-padding-x, var(--lib-button-padding-x, var(--lib-space-6)));
  }
}

.hhds-button__icon {
  display: inline-flex;
  flex-shrink: 0;
  width: var(--lib-button-icon-size, 1.25em);
  height: var(--lib-button-icon-size, 1.25em);
}

.hhds-button__icon svg {
  width: 100%;
  height: 100%;
}

@media (min-width: 48rem) {
  .hhds-hero-immersive {
    min-height: calc(clamp(30rem, 84svh, 44rem) + var(--lib-site-header-overlay, 0px));
  }
}

.lib-rating-stars {
  display: inline-flex;
  gap: var(--lib-space-1);
  color: var(--lib-color-star);
  line-height: 1;
}

.lib-rating-stars__item {
  width: var(--lib-size-rating-star);
  height: var(--lib-size-rating-star);
  fill: currentColor;
  stroke: var(--lib-color-star-stroke);
  stroke-width: var(--lib-size-star-stroke);
  paint-order: stroke fill;
  filter: drop-shadow(var(--lib-shadow-star));
  flex-shrink: 0;
}

.lib-rating-stars__item--empty {
  fill: none;
  opacity: 0.35;
}

@media (min-width: 768px) {
  .lib-rating-stars {
    gap: var(--lib-space-2);
  }

  .lib-rating-stars__item {
    width: var(--lib-size-rating-star-lg);
    height: var(--lib-size-rating-star-lg);
  }
}

/*
 * HERO-03 with an attached trust band = exactly the first screen
 * (2026-10-14, owner: "debe ser lo mismo que la banda de la home"). The
 * band is part of the hero, so it sits on the bottom edge of the first
 * view instead of below the fold. Before: the section's own padding was
 * stacked on top of the hero's (72 + 72 px), another 72 px sat under the
 * band, and the hero's min-height ignored the band, so at 1440x900 the
 * band started at 980 px. Now the section is a one-screen column: the
 * hero takes the free space (content anchored to its bottom), the band
 * closes the screen. Spacing scales with the screen height, and a hero
 * whose content is taller than the screen simply grows (never clipped).
 */
.hhds-section--hero-immersive:has(.lib-trust-strip--hero-attached) {
  padding-block: 0;
}

.hhds-section--hero-immersive:has(.lib-trust-strip--hero-attached) > .hhds-container {
  display: flex;
  flex-direction: column;
  min-height: 100svh;
}

.hhds-section--hero-immersive .hhds-hero-immersive--has-authority {
  flex: 1 0 auto;
  min-height: 0;
  padding-top: calc(clamp(1.5rem, 5svh, 4rem) + var(--lib-site-header-overlay, 0px));
  padding-bottom: clamp(1.5rem, 4svh, 3rem);
}

.hhds-hero-immersive--has-authority .hhds-hero-immersive__content {
  gap: clamp(var(--lib-space-4), 2.6svh, var(--lib-space-6));
}

.hhds-hero-immersive--has-authority .hhds-hero-immersive__content .hhds-section__title {
  font-size: var(--lib-hero-title-size, clamp(2.25rem, min(6vw, 7.5svh), 4.75rem));
}
