/* ═══════════════════════════════════════════════════════════════════════════
   HOZIO PRIMITIVE LAYER — class-scoped only

   Every rule below is scoped to a .hzo-* class. Nothing targets raw
   element selectors (h1-h6, a, p, input, etc) at top level. The file
   activates only when a template explicitly uses a .hzo-* class — the
   Global Kit preview page or any new template you build on the Hozio
   vocabulary.

   Existing client templates using .tga-* or .bs-* classes are UNAFFECTED
   because this stylesheet does not touch their selectors.

   `!important` is used only where there is a documented cascade fight:
   `:visited` from per-client main.css (link colors), form plugin
   output (form field rules), or same-file variant overrides. It is NOT
   the default — see the cluster-C A5 lock + quality-rules §1.1.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─── Utility color tokens (additive; warning + info not in main.css) ─── */
:root {
    --color-warning:        #D97706;
    --color-warning-bg:     #FFFBEB;
    --color-info:           #2563EB;
    --color-info-bg:        #EFF6FF;
    --color-warm-highlight: #FFF8E5;
}

/* ─── Container ───────────────────────────────────────────────────────
   Horizontal padding scales across five zones via the QA breakpoints
   (480, 768, 1024, 1250) — 16 / 24 / 32 / 48 / 64. Caps at 64px from
   1250 onward since wider screens don't need wider gutters. */
.hzo-container {
    max-width: var(--container-max-width);
    margin: 0 auto;
    padding: 0 var(--space-md);
}
@media (min-width: 480px)  { .hzo-container { padding: 0 var(--space-lg); } }
@media (min-width: 768px)  { .hzo-container { padding: 0 var(--space-lg-2); } }
@media (min-width: 1024px) { .hzo-container { padding: 0 var(--space-xl); } }
@media (min-width: 1250px) { .hzo-container { padding: 0 var(--space-2xl); } }

/* ─── Scroll reveal (opt-in utility; reduced-motion-safe; no-JS-safe) ──────
   Add class="hzo-reveal" to any element to fade + rise in as it scrolls into
   view. main.js adds .hzo-reveal--init (ONLY to below-the-fold elements, so
   above-fold content never flashes), then .is-revealed when it enters view.
   No JS or reduced-motion → content stays fully visible, never hidden. */
.hzo-reveal { transition: opacity 0.6s ease, transform 0.6s ease; }
.hzo-reveal.hzo-reveal--init { opacity: 0; transform: translateY(20px); will-change: opacity, transform; }
.hzo-reveal.is-revealed { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
    .hzo-reveal, .hzo-reveal.hzo-reveal--init { opacity: 1; transform: none; transition: none; }
}

/* ─── Typography ────────────────────────────────────────────────────── */
.hzo-display {
    font-family: var(--font-heading);
    font-weight: var(--font-weight-heading, 700);
    font-size: calc(clamp(2rem, 3.75vw, 3.5rem) * var(--hzo-type-scale, 1) * var(--hzo-heading-scale, 1));
    line-height: 1.05;
    letter-spacing: var(--heading-letter-spacing, -0.015em);
    text-transform: var(--heading-transform, none);
    color: var(--text-heading);
    margin: 0 0 var(--space-lg);
}
.hzo-subtitle {
    font-family: var(--font-body);
    font-size: 1.25rem;
    font-weight: var(--fw-regular, 400);
    line-height: 1.5;
    color: var(--text-muted);
    margin: 0 0 var(--space-xl);
}
.hzo-lead {
    font-size: 1.25rem;
    line-height: 1.5;
    color: var(--text-body);
    margin: 0 0 var(--space-lg);
}
.hzo-small {
    font-size: 0.875rem;
    color: var(--text-muted);
    margin: 0 0 var(--space-md);
}
.hzo-eyebrow {
    display: inline-block;
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: var(--fw-semibold, 600);
    text-transform: uppercase;
    letter-spacing: 0.7px;
    color: var(--accent-text);
    margin: 0 0 var(--space-md);
}
/* SEO pattern: eyebrows ARE the heading tags (h1-h6) for keyword placement.
   The class must fully override heading element defaults AND any theme.json
   heading styles. !important on every property a theme could set on
   headings (font-family, font-size, font-weight, color, line-height,
   text-transform, letter-spacing, margin). See quality-rules.md §6.2. */
h1.hzo-eyebrow, h2.hzo-eyebrow, h3.hzo-eyebrow,
h4.hzo-eyebrow, h5.hzo-eyebrow, h6.hzo-eyebrow {
    display: inline-block !important;
    font-family: var(--font-body) !important;
    font-size: 15px !important;
    font-weight: var(--fw-semibold, 600) !important;
    line-height: 1.4 !important;
    text-transform: uppercase !important;
    letter-spacing: 0.7px !important;
    color: var(--accent-text) !important;
    margin: 0 0 var(--space-md) !important;
}
.hzo-meta {
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: var(--fw-medium, 500);
    color: var(--text-muted);
    line-height: 1.5;
}
.hzo-caption {
    font-family: var(--font-body);
    font-size: 13px;
    color: var(--text-muted);
    font-style: italic;
    line-height: 1.5;
    margin: var(--space-sm) 0 0;
}

/* ─── Dark section (class-scoped; only activates via .hzo-section--dark) ── */
.hzo-section--dark { background: var(--bg-dark-section); color: #fff; }
.hzo-section--dark h1, .hzo-section--dark h2, .hzo-section--dark h3, .hzo-section--dark h4, .hzo-section--dark h5, .hzo-section--dark h6 { color: var(--heading-color-on-dark, #fff); }
.hzo-section--dark p { color: rgba(255,255,255,0.85); }
.hzo-section--dark a { color: #fff; }
.hzo-section--dark .hzo-eyebrow,
.hzo-section--dark h1.hzo-eyebrow,
.hzo-section--dark h2.hzo-eyebrow,
.hzo-section--dark h3.hzo-eyebrow,
.hzo-section--dark h4.hzo-eyebrow { color: var(--accent) !important; }

/* ─── Navigation link ───────────────────────────────────────────────── */
.hzo-nav-link {
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: var(--fw-medium, 500);
    color: var(--nav-link);
    text-decoration: none;
    transition: color 0.15s;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.hzo-nav-link:hover {
    color: var(--brand-hover-on-dark); /* brighter brand — a clear jump, not one step */
}

/* ─── Breadcrumb ────────────────────────────────────────────────────── */
.hzo-breadcrumb {
    font-family: var(--font-body);
    font-size: 13px;
    color: var(--text-muted);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    list-style: none;
    padding: 0;
    margin: 0;
}
.hzo-breadcrumb a {
    color: var(--text-muted);
    text-decoration: none;
    transition: color 0.15s;
}
.hzo-breadcrumb a:hover { color: var(--brand); }
.hzo-breadcrumb__sep { color: var(--border); margin: 0 2px; }
.hzo-breadcrumb [aria-current="page"] { color: var(--text-body); font-weight: var(--fw-medium, 500); }

/* ─── Stats ─────────────────────────────────────────────────────────── */
.hzo-stat-number {
    font-family: var(--font-number);
    font-size: clamp(2.25rem, 4vw, 3rem);
    font-weight: var(--fw-bold, 700);
    line-height: 1;
    color: var(--brand);
    letter-spacing: -0.01em;
    margin: 0 0 var(--space-sm);
}
.hzo-stat-label {
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: var(--fw-medium, 500);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    line-height: 1.4;
}

/* ─── Footer typography (for dark footer contexts) ──────────────────── */
.hzo-footer-heading {
    display: block;
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: var(--fw-bold, 700);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--footer-heading-dark, #fff);
    margin: 0 0 var(--space-lg);
}
/* !important on color: fights a:visited from per-client main.css.
   Footer-link variants below match this !important so they can beat the base. */
.hzo-footer-link {
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: var(--fw-medium, 500);
    color: var(--footer-link-dark, rgba(255,255,255,0.8)) !important;
    text-decoration: none;
    line-height: 1.5;
    padding: 8px 0;
    transition: color 0.15s;
    display: block;
    width: fit-content;  /* stack vertically, but only clickable on the text itself */
}
.hzo-footer-link:hover,
.hzo-footer-link:focus-visible { color: var(--footer-link-hover-dark, #fff) !important; }
.hzo-footer-legal {
    font-family: var(--font-body);
    font-size: 13px;
    color: var(--footer-legal-text-dark, rgba(255,255,255,0.65));
    line-height: 1.6;
}

/* NAP (Name, Address, Phone) block — for the footer contact column and any
   other spot that needs a formatted business-info listing. Each row has a
   small accent-colored icon on the left and text/link on the right. */
.hzo-footer-nap {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 0;
}
.hzo-footer-nap__name {
    font-family: var(--font-body);
    font-weight: var(--fw-bold, 700);
    color: var(--footer-heading-dark, #fff);
    font-size: 15px;
    margin: 0 0 4px;
}
.hzo-footer-nap__row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: var(--fw-medium, 500);
    line-height: 1.5;
    color: var(--footer-link-dark, rgba(255,255,255,0.8));
    margin: 0;
}
/* Icons hidden by default. A client can re-show them with
   `.hzo-footer-nap__icon { display: flex; }` in their main.css. */
.hzo-footer-nap__icon {
    display: none;
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    color: var(--accent);
    margin-top: 3px;
}
/* Contact lines read like the other footer links: inherit the footer link color
   and lighten to #fff on hover. The NAP anchors carry the .hzo-footer-nap__link
   class (added in [hzo_nap], v1.1.93) — the class EXISTS purely so a per-client
   content-link rule like `a:not([class])` excludes them by contract; the styling
   here keeps the original descendant selectors, which win on normal cascade
   order within this file. No !important needed. */
.hzo-footer-nap__row a,
.hzo-footer-nap__row a:visited {
    color: inherit;
    background-image: none;
    text-decoration: none;
    transition: color 0.2s ease;
}
.hzo-footer-nap__row a:hover,
.hzo-footer-nap__row a:visited:hover,
.hzo-footer-nap__row a:focus-visible { color: var(--footer-link-hover-dark, #fff); }

/* Light footer variant — when the footer sits on a light background.
   !important on color matches the base .hzo-footer-link so the light
   variant wins the same-specificity fight against a:visited. */
.hzo-site-footer--light { background: var(--footer-bg-light, var(--bg-alt)); color: var(--footer-text-light, var(--text-body)); }
.hzo-site-footer--light .hzo-footer-heading { color: var(--footer-heading-light, var(--text-heading)); }
.hzo-site-footer--light .hzo-footer-link { color: var(--footer-link) !important; }
.hzo-site-footer--light .hzo-footer-link:hover,
.hzo-site-footer--light .hzo-footer-link:focus-visible { color: var(--footer-link-hover) !important; }
.hzo-site-footer--light .hzo-footer-legal { color: var(--footer-legal-text-light, var(--text-muted)); }
.hzo-site-footer--light a { color: var(--text-body) !important; }
/* NAP contact lines mirror the footer-link polarity on light footers too. */
.hzo-site-footer--light .hzo-footer-nap__row,
.hzo-site-footer--light .hzo-footer-nap__row a { color: var(--footer-link) !important; }
.hzo-site-footer--light .hzo-footer-nap__row a:hover,
.hzo-site-footer--light .hzo-footer-nap__row a:focus-visible { color: var(--footer-link-hover) !important; }

/* ─── Buttons ────────────────────────────────────────────────────────
   !important is scoped to `color` and `background` only — those fight
   `a:visited` from per-client main.css (links styled as buttons would
   otherwise shift to the visited color). All other properties (padding,
   border, border-radius, text-decoration) win on class specificity alone
   and do not need !important. See bottom-of-file note on why buttons
   intentionally use !important here instead of `.hzo-btn:visited` rules. */
/* Button component tokens (Hozio Studio Live, Phase 2a). Each property reads a
   --btn-* token that DEFAULTS (via the var() fallback) to the original semantic
   value — so with no override the render is byte-identical, and the design
   widget can override any of them per variant. "Linked by default": the
   fallback IS the link to --accent / --brand; an override breaks just that link. */
.hzo-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: var(--btn-padding-y, 14px) var(--btn-padding-x, 32px);
    font-family: var(--font-body);
    font-size: 1rem;
    font-weight: var(--btn-weight, var(--fw-semibold, 600));
    text-decoration: none;
    border-radius: var(--btn-radius, var(--radius-pill));
    border: 1px solid transparent;
    cursor: pointer;
    transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-base), box-shadow var(--transition-base), transform 0.1s;
    min-height: 48px;
    line-height: 1;
    white-space: nowrap;
    background: var(--btn-primary-bg, var(--accent)) !important;
    color: var(--btn-primary-text, var(--text-on-accent)) !important;
}
.hzo-btn:hover, .hzo-btn.is-hover {
    background: var(--btn-primary-hover, var(--accent-hover-on-light)) !important;
    color: var(--btn-primary-hover-text, #fff) !important; /* bg darkens on hover → flip text light for contrast */
}
.hzo-btn:focus-visible, .hzo-btn.is-focus {
    outline: 3px solid var(--focus-ring);
    outline-offset: 2px;
}
.hzo-btn.is-active, .hzo-btn:active { transform: translateY(1px); }
.hzo-btn.is-disabled, .hzo-btn[disabled], .hzo-btn[aria-disabled="true"] {
    opacity: 0.5;
    pointer-events: none;
}

.hzo-btn--primary {
    background: var(--btn-primary-bg, var(--accent)) !important;
    color: var(--btn-primary-text, var(--text-on-accent)) !important;
    border-color: var(--btn-primary-bg, var(--accent));
}
.hzo-btn--primary:hover {
    /* Deep-accent fill on hover — accent family, darkest stop (--accent-text). */
    background: var(--btn-primary-hover, var(--accent-text)) !important;
    border-color: var(--btn-primary-hover, var(--accent-text));
    color: var(--btn-primary-hover-text, #fff) !important; /* bg darkens on hover → flip text light for contrast */
}
.hzo-btn--secondary {
    background: var(--btn-secondary-bg, var(--brand)) !important;
    color: var(--btn-secondary-text, var(--text-on-brand)) !important;
    border-color: var(--btn-secondary-bg, var(--brand));
}
.hzo-btn--secondary:hover {
    background: var(--btn-secondary-hover, var(--brand-hover-on-light)) !important;
    border-color: var(--btn-secondary-hover, var(--brand-hover-on-light));
    color: var(--btn-secondary-text, var(--text-on-brand)) !important;
}
.hzo-btn--outline {
    background: transparent !important;
    color: var(--btn-outline-color, var(--brand)) !important;
    border-color: var(--btn-outline-color, var(--brand));
}
.hzo-btn--outline:hover {
    background: var(--btn-outline-color, var(--brand)) !important;
    color: var(--btn-secondary-text, var(--text-on-brand)) !important;
    border-color: var(--btn-outline-color, var(--brand));
}
.hzo-btn--ghost {
    background: transparent !important;
    color: var(--btn-ghost-color, var(--brand)) !important;
    border-color: transparent;
}
.hzo-btn--ghost:hover {
    background: var(--btn-ghost-hover, var(--brand-pale)) !important;
    color: var(--btn-ghost-color, var(--brand)) !important;
}
.hzo-btn--danger {
    background: var(--btn-danger-bg, var(--error)) !important;
    color: #fff !important;
    border-color: var(--btn-danger-bg, var(--error));
}
.hzo-btn--danger:hover {
    background: var(--btn-danger-hover, #B91C1C) !important;
    border-color: var(--btn-danger-hover, #B91C1C);
    color: #fff !important;
}

.hzo-btn--sm { padding: 10px 22px; font-size: 0.875rem; min-height: 36px; }
.hzo-btn--lg { padding: 16px 40px; font-size: 1.125rem; min-height: 52px; }

/* Full-width — stretches to the container at all breakpoints. (Mobile already
   stretches non-inline buttons; this opts desktop in too — e.g. a form submit
   or a stacked CTA pair on a narrow card.) */
.hzo-btn--block { width: 100%; }

/* Icon-only — square button sized to the button height, for a lone icon
   (search / menu / close, nav arrows, social). Pair with --sm / --lg to
   resize. Always intrinsic width (excluded from the mobile full-width rule
   below). The author MUST supply an aria-label — there is no text node. */
.hzo-btn--icon { padding: 0; width: 48px; min-width: 48px; }
.hzo-btn--icon.hzo-btn--sm { width: 36px; min-width: 36px; }
.hzo-btn--icon.hzo-btn--lg { width: 52px; min-width: 52px; }
.hzo-btn--icon > svg { width: 20px; height: 20px; }

/* Link button — button semantics, link appearance. For the lowest-emphasis
   inline actions ("Cancel", "Skip"). !important on color/background matches the
   base button rules so it wins the per-client a:visited fight (see the
   bottom-of-file note) — no stale :visited rule needed. */
.hzo-btn--link {
    background: transparent !important;
    color: var(--brand-text) !important;
    border-color: transparent;
    min-height: 0;
    padding: 4px 0;
    border-radius: 0;
    text-decoration: underline;
    text-underline-offset: 3px;
}
.hzo-btn--link:hover {
    background: transparent !important;
    color: var(--brand-hover-on-dark) !important;
    text-decoration-thickness: 2px;
}
.hzo-btn--on-dark.hzo-btn--link,
.hzo-btn--on-dark.hzo-btn--link:hover { color: #fff !important; }

/* Mobile: buttons go full-width by default for easier tapping + stacked
   layout. Opt out with .hzo-btn--inline when a button needs to stay
   intrinsic width on mobile (side-by-side pairs, etc.). Icon + link buttons
   are intrinsic-width by nature, so they're excluded too. */
@media (max-width: 767px) {
    .hzo-btn:not(.hzo-btn--inline):not(.hzo-btn--icon):not(.hzo-btn--link) { width: 100%; }
}

/* Dark-section button overrides.
   On brand-colored dark sections, the SECONDARY button (now blue) would
   disappear since it shares the section's color. Flip it to a white button
   with brand text for clear visibility. Primary (green) stays green — it
   has plenty of contrast against blue — and its hover gets the lighter
   on-dark variant for extra feedback. !important on color/background
   matches base rules so on-dark variants win the :visited fight. */
.hzo-btn--on-dark.hzo-btn--primary:hover {
    /* Palest-accent fill on dark — accent family, lightest stop (--accent-pale);
       the dark accent-on-fill text (--text-on-accent) reads cleanly on it. */
    background: var(--accent-pale) !important;
    border-color: var(--accent-pale);
    color: var(--text-on-accent) !important;
}
.hzo-btn--on-dark.hzo-btn--secondary {
    background: #fff !important;
    color: var(--brand) !important;
    border-color: #fff;
}
.hzo-btn--on-dark.hzo-btn--secondary:hover {
    /* Clear branded tint away from white so the hover obviously reads. */
    background: color-mix(in srgb, #ffffff 75%, var(--brand)) !important;
    border-color: color-mix(in srgb, #ffffff 75%, var(--brand));
    color: var(--brand-hover-on-light) !important;
}
.hzo-btn--on-dark.hzo-btn--outline {
    color: #fff !important;
    border-color: #fff;
    background: transparent !important;
}
.hzo-btn--on-dark.hzo-btn--outline:hover {
    background: #fff !important;
    color: var(--brand) !important;
}
.hzo-btn--on-dark.hzo-btn--ghost { color: #fff !important; }
.hzo-btn--on-dark.hzo-btn--ghost:hover {
    background: rgba(255,255,255,0.2) !important;
    color: #fff !important;
}

/* Loading state — add `is-loading` + `aria-busy="true"`. The label is hidden
   (color → transparent) and a spinner is painted centered; the label still
   occupies space so the button keeps its width and doesn't reflow. pointer-
   events off blocks a double-submit. The ring color is set per variant so it
   reads on each background. */
.hzo-btn.is-loading {
    color: transparent !important;
    pointer-events: none;
    position: relative;
}
.hzo-btn.is-loading::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 18px;
    height: 18px;
    margin: -9px 0 0 -9px;
    border-radius: 50%;
    /* Default: dark ring, reads on the accent/primary fill. */
    border: 2px solid color-mix(in srgb, var(--text-on-accent) 30%, transparent);
    border-top-color: var(--text-on-accent);
    animation: hzo-spin 0.6s linear infinite;
}
/* Filled-dark variants → white ring. */
.hzo-btn--secondary.is-loading::after,
.hzo-btn--danger.is-loading::after {
    border-color: rgba(255, 255, 255, 0.35);
    border-top-color: #fff;
}
/* Transparent variants → brand ring. */
.hzo-btn--outline.is-loading::after,
.hzo-btn--ghost.is-loading::after,
.hzo-btn--link.is-loading::after {
    border-color: color-mix(in srgb, var(--brand) 30%, transparent);
    border-top-color: var(--brand);
}
@media (prefers-reduced-motion: reduce) {
    .hzo-btn.is-loading::after { animation-duration: 1.5s; }
}

/* Added confirmation (add-to-cart) — briefly swaps the label for a success check
   after a successful add. Mirrors `.is-loading`: label hidden, glyph centered, no
   reflow, pointer-events off. The JS driver (main.js) toggles it on, fires
   hzo.toast('Added to cart'), then reverts to default after a short window. It's a
   state swap, not an animation, so it's reduced-motion-safe by construction. An
   integration wanting a persistent state sets the label to "In cart" instead. */
.hzo-btn.is-added {
    color: transparent !important;
    pointer-events: none;
    position: relative;
}
.hzo-btn.is-added::after {
    content: "\2713"; /* ✓ */
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 1.15em;
    font-weight: 700;
    line-height: 1;
    color: var(--text-on-accent); /* reads on the primary/accent fill */
}
.hzo-btn--secondary.is-added::after,
.hzo-btn--danger.is-added::after { color: #fff; }
.hzo-btn--outline.is-added::after,
.hzo-btn--ghost.is-added::after,
.hzo-btn--link.is-added::after { color: var(--brand); }

/* ─── Spinner ─────────────────────────────────────────────────────────
   Standalone async indicator (form submit, cart, lazy content). Inherits
   currentColor so it adapts to any text context — drop it in a dark section
   and the ring goes light automatically. Sizes via --sm / --lg. Shares the
   hzo-spin keyframe with the button loading state above. */
@keyframes hzo-spin { to { transform: rotate(360deg); } }
.hzo-spinner {
    display: inline-block;
    width: 20px;
    height: 20px;
    border: 2px solid color-mix(in srgb, currentColor 25%, transparent);
    border-top-color: currentColor;
    border-radius: 50%;
    animation: hzo-spin 0.6s linear infinite;
    vertical-align: -0.2em;
}
.hzo-spinner--sm { width: 14px; height: 14px; border-width: 1.5px; }
.hzo-spinner--lg { width: 32px; height: 32px; border-width: 3px; }
@media (prefers-reduced-motion: reduce) {
    .hzo-spinner { animation-duration: 1.5s; }
}

/* ─── Cards ─────────────────────────────────────────────────────────── */
.hzo-card {
    background: var(--card-bg, #fff);
    border: 1px solid var(--card-border, var(--border));
    border-radius: var(--card-radius, var(--radius-card));
    padding: var(--card-padding, var(--space-lg));
    box-shadow: var(--card-shadow, none); /* default flat = current; widget Shadow control sets it */
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    transition: box-shadow var(--transition-base), transform var(--transition-base);
}
/* Only cards that are actually clickable (contain a link) get the hover lift —
   static info cards stay flat. :has() is well-supported in current browsers. */
.hzo-card:has(a):hover { box-shadow: var(--shadow-md); transform: translateY(-4px); }
@media (prefers-reduced-motion: reduce) { .hzo-card:has(a):hover { transform: none; } }
/* Badges, icons, and other inline-sized elements inside cards shouldn't
   stretch to full width (default flex behavior). */
.hzo-card > .hzo-badge,
.hzo-card > .hzo-card__icon { align-self: flex-start; }
.hzo-card__icon {
    width: 56px;
    height: 56px;
    background: var(--brand-pale);
    border-radius: var(--radius-input);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--brand);
    font-size: 28px;
    line-height: 1;
    margin-bottom: var(--space-sm);
}
.hzo-card__title {
    font-family: var(--font-heading);
    font-size: 1.25rem;
    font-weight: var(--fw-bold, 700);
    color: var(--text-heading);
    margin: 0;
    letter-spacing: 0.015em;
}
.hzo-card__text {
    color: var(--text-muted);
    margin: 0;
    line-height: 1.6;
}
/* !important on color: fights a:visited from per-client main.css.
   Matching :visited rule at the bottom of this file preserves the color
   after the link has been clicked. */
.hzo-card__link {
    color: var(--accent-text) !important;
    font-weight: var(--fw-semibold, 600);
    text-decoration: none;
    align-self: flex-start;  /* inline — don't stretch to full card width */
    margin-top: auto;
    padding-top: var(--space-sm);
    transition: color 0.15s;
}
.hzo-card__link:hover { color: color-mix(in srgb, var(--accent-text) 70%, black) !important; }
/* Auto-rendered CTA arrow (bold Lucide arrow-right, masked so it inherits the
   link color). Sized 1em — same scale as the label — and floats right on hover.
   Replaces the old literal "→" glyph in the markup (cleaner + animatable). */
.hzo-card__link::after {
    content: "";
    display: inline-block;
    width: 1em;
    height: 1em;
    margin-left: 0.4em;
    vertical-align: -0.12em;
    flex-shrink: 0;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") no-repeat center / contain;
            mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") no-repeat center / contain;
    transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.5, 1);
}
.hzo-card__link:hover::after,
.hzo-card__link:focus-visible::after { transform: translateX(5px); }
@media (prefers-reduced-motion: reduce) {
    .hzo-card__link::after { transition: none; }
}

/* ─── Emphasis / decoration utilities ────────────────────────────────────
   Opt-in inline decorations keyed to --emphasis (a client's decorative accent;
   falls back to --accent if a client hasn't defined one). Re-key --emphasis per
   client in main.css for a distinct decorative hue. */

/* Keyword underline — clean rule beneath one/two key words; wraps per line and
   sits behind descenders. */
.hzo-mark {
    background-image: linear-gradient(var(--emphasis, var(--accent)), var(--emphasis, var(--accent)));
    background-repeat: no-repeat;
    background-position: 0 92%;
    background-size: 100% 0.12em;
    padding-bottom: 0.02em;
}

/* Stat brackets — [ ] framing a standout number. Wrap a number; the brackets
   carry the emphasis color, the number keeps its own. */
.hzo-bracket {
    position: relative;
    display: inline-block;
    padding: 0 0.4em;
}
.hzo-bracket::before,
.hzo-bracket::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 0.2em;
    border: 3px solid var(--emphasis, var(--accent));
}
.hzo-bracket::before { left: 0;  border-right: 0; }
.hzo-bracket::after  { right: 0; border-left: 0; }

/* Pull-quote — editorial moment, emphasis left rule, heading font. */
.hzo-pullquote {
    font-family: var(--font-heading);
    font-size: clamp(1.25rem, 2.2vw, 1.6rem);
    font-weight: var(--fw-bold, 700);
    line-height: 1.3;
    color: var(--text-heading);
    border-left: 3px solid var(--emphasis, var(--accent));
    padding-left: var(--space-lg);
    margin: var(--space-xl) 0;
}
.hzo-section--dark .hzo-pullquote { color: #fff; }

/* ═══════════════════════════════════════════════════════════════════════
   SITE HEADER · NAV · DROPDOWN · HAMBURGER · MOBILE MENU
   Structure ported from the TGA production header. Uses hzo-* classes
   throughout. Breakpoints: hamburger below 1250px, horizontal nav above.
   ═══════════════════════════════════════════════════════════════════════ */

/* Cancel WP's default block-gap between direct children of .wp-site-blocks.
   WP emits `:where(.wp-site-blocks) > * { margin-block-start: 24px; }` from
   the block-layout system (driven by --wp--style--block-gap, default 24px).
   For block templates that compose utility-bar + header + main + sections +
   footer as direct siblings, this creates visible 24px white bands between
   every section (page background showing through between brand-colored
   regions). Our header/main/section/footer carry their own padding/spacing
   for whitespace control — we don't want WP's auto-gap on top of that. */
.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }

.hzo-site-header {
    background: var(--nav-header-bg, #fff);
    box-shadow: var(--nav-header-shadow, 0 1px 4px rgba(0, 0, 0, 0.08));
    position: sticky;
    top: 0;
    z-index: var(--z-header);
}
.hzo-site-header__inner {
    display: flex;
    align-items: center;
    min-height: var(--header-height-mobile, 72px);
    gap: 16px;
}
@media (min-width: 1250px) {
    .hzo-site-header__inner { min-height: var(--header-height-desktop, 80px); }
}

/* ─── Logo ─────────────────────────────────────────────────────────── */
.hzo-site-logo {
    flex-shrink: 1;
    min-width: 0;
    font-family: var(--font-heading);
    font-size: 22px;
    font-weight: var(--fw-bold, 700);
    color: var(--brand);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
}
.hzo-site-logo img { height: 40px; width: auto; max-width: 260px; display: block; }
@media (min-width: 1250px) {
    .hzo-site-logo img { height: 46px; max-width: 300px; }
}

/* ─── Desktop nav menu (UL/LI structure) ────────────────────────── */
.hzo-site-nav {
    display: none;
    list-style: none;
    margin: 0;
    padding: 0;
    align-items: center;
    gap: 0;
    flex: 1;
    justify-content: center;
}
@media (min-width: 1250px) { .hzo-site-nav { display: flex; } }

.hzo-nav-item { position: relative; }

/* !important on color: fights a:visited from per-client main.css.
   Matching :visited rule at bottom-of-file preserves the color. */
.hzo-site-nav__link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 14px 13px;
    font-family: var(--font-body);
    font-size: 0.9375rem;
    font-weight: var(--fw-semibold, 600);
    color: var(--nav-link) !important;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: color 200ms ease;
}
/* Non-clickable dropdown parents: <span> triggers have no href, so no pointer cursor */
span.hzo-site-nav__link { cursor: default; }

.hzo-site-nav__link:hover,
.hzo-nav-item:hover > .hzo-site-nav__link,
.hzo-nav-item.is-open > .hzo-site-nav__link { color: var(--nav-link-hover) !important; }

.hzo-nav-chevron {
    flex-shrink: 0;
    opacity: 0.45;
    transition: transform 200ms ease, opacity 200ms ease;
}
.hzo-nav-item:hover > .hzo-site-nav__link .hzo-nav-chevron,
.hzo-nav-item.is-open > .hzo-site-nav__link .hzo-nav-chevron {
    transform: rotate(180deg);
    opacity: 0.8;
}

/* ─── Dropdown (mega menu) ─────────────────────────────────────────
   Centered under the parent nav item. Fades + slides in on hover/open.
   Uses opacity+visibility+transform so it animates cleanly both ways. */
.hzo-mega-menu {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%) translateY(-8px);
    min-width: 220px;
    background: var(--nav-dropdown-bg, #fff);
    border-top: 2px solid var(--accent);
    border-radius: 0 0 var(--radius-input) var(--radius-input);
    box-shadow: var(--nav-dropdown-shadow, 0 12px 40px rgba(0,0,0,0.10), 0 2px 8px rgba(0,0,0,0.04));
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    overflow: hidden; /* clip link hover backgrounds to the rounded corners */
    transition: opacity 200ms ease, transform 200ms ease, visibility 200ms;
}
.hzo-nav-item:hover > .hzo-mega-menu,
.hzo-nav-item.is-open > .hzo-mega-menu {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateX(-50%) translateY(0);
}

.hzo-mega-menu__list { list-style: none; margin: 0; padding: 0; }
/* !important on color: fights a:visited. Matching :visited rule at bottom-of-file. */
.hzo-mega-menu__link {
    display: block;
    padding: 14px 24px;
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: var(--fw-medium, 500);
    color: var(--nav-link) !important;
    text-decoration: none;
    white-space: nowrap;
    transition: color 200ms ease, background-color 200ms ease;
}
.hzo-mega-menu__link:hover {
    color: var(--nav-link-hover) !important;
    background: var(--nav-dropdown-link-hover-bg, var(--bg-alt));
}

/* ─── Desktop CTAs (right side) ─────────────────────────────────── */
.hzo-site-nav__ctas {
    display: none;
    align-items: center;
    gap: var(--space-sm);
    flex-shrink: 0;
}
@media (min-width: 1250px) { .hzo-site-nav__ctas { display: flex; } }

/* ─── Hamburger trigger (below 1250px) ─────────────────────────── */
.hzo-mobile-trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    margin-left: auto;
    /* Visual right-edge alignment: the SVG has ~10px of internal whitespace
       padding to its icon, so the icon appears inset from the button's right
       edge. Pull the button -10px right so the icon's visible edge aligns
       with the container's right edge (matching the logo's left alignment). */
    margin-right: -10px;
    border: 0;
    background: transparent;
    cursor: pointer;
    color: var(--nav-mobile-trigger-color, var(--text-heading));
    flex-shrink: 0;
}
@media (min-width: 1250px) { .hzo-mobile-trigger { display: none; } }

/* ─── Mobile menu overlay (backdrop) ──────────────────────────── */
.hzo-mobile-menu {
    position: fixed;
    inset: 0;
    background: var(--nav-mobile-overlay-bg, rgba(0, 0, 0, 0.5));
    z-index: var(--z-overlay);
    opacity: 0;
    visibility: hidden;
    overflow: hidden; /* clip the translateX'd panel so it can't cause horizontal scroll */
    transition: opacity 300ms ease, visibility 300ms;
}
.hzo-mobile-menu.is-open { opacity: 1; visibility: visible; }

/* Mobile menu panel (slides from the right) */
.hzo-mobile-menu__panel {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-width: 360px;
    background: var(--nav-mobile-panel-bg, #fff);
    display: flex;
    flex-direction: column;
    transform: translateX(100%);
    transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
.hzo-mobile-menu.is-open .hzo-mobile-menu__panel { transform: translateX(0); }

/* Sidebar header: logo + close */
.hzo-mobile-menu__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 24px;
    border-bottom: 1px solid var(--nav-mobile-divider-color, var(--border));
    flex-shrink: 0;
    min-height: 60px;
}
.hzo-mobile-close {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
    color: var(--text-body);
    flex-shrink: 0;
}

/* Sidebar nav */
.hzo-mobile-nav {
    flex: 1;
    padding: 4px 0;
    overflow-y: auto;
}

/* Base mobile menu link — context wrappers (.hzo-mobile-simple, .hzo-mobile-panel)
   layer padding + background on top; this rule guarantees color + no underline
   even when the class is used standalone. */
.hzo-mobile-menu__link,
.hzo-mobile-menu__link:visited {
    color: var(--text-body);
    text-decoration: none;
    display: block;
    font-weight: var(--fw-semibold, 600);
}
.hzo-mobile-menu__link:hover,
.hzo-mobile-menu__link:visited:hover { color: var(--nav-link-hover); }

/* Simple (non-accordion) row — a single link.
   !important on color: fights a:visited from per-client main.css. */
.hzo-mobile-simple { border-bottom: 1px solid var(--nav-mobile-divider-color, var(--border)); }
.hzo-mobile-simple > .hzo-mobile-menu__link {
    display: block;
    padding: 16px 24px;
    font-family: var(--font-body);
    font-weight: var(--fw-semibold, 600);
    font-size: 15px;
    color: var(--nav-mobile-link-color, var(--text-body)) !important;
    text-decoration: none;
    transition: color 200ms ease;
}
.hzo-mobile-simple > .hzo-mobile-menu__link:hover { color: var(--nav-link-hover) !important; }

/* Accordion row (nav item with sub-items) */
.hzo-mobile-accordion { border-bottom: 1px solid var(--nav-mobile-divider-color, var(--border)); }
.hzo-mobile-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 16px 24px;
    border: 0;
    background: transparent;
    font-family: var(--font-body);
    font-weight: var(--fw-semibold, 600);
    font-size: 15px;
    color: var(--text-body);
    cursor: pointer;
    text-align: left;
}
.hzo-mobile-accordion.is-expanded > .hzo-mobile-toggle { color: var(--nav-link-hover); }

.hzo-mobile-chevron {
    flex-shrink: 0;
    display: block;
    opacity: 0.4;
    margin-left: 12px;
    transition: transform 300ms ease, opacity 200ms ease;
}
.hzo-mobile-accordion.is-expanded > .hzo-mobile-toggle > .hzo-mobile-chevron {
    transform: rotate(180deg);
    opacity: 0.7;
}

/* Accordion collapsible panel */
.hzo-mobile-panel {
    max-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: max-height 300ms ease;
}
.hzo-mobile-accordion.is-expanded > .hzo-mobile-panel { max-height: 600px; }

/* !important on color: fights a:visited from per-client main.css. */
.hzo-mobile-panel > .hzo-mobile-menu__link {
    display: block;
    padding: 12px 24px 12px 32px;
    font-size: 14px;
    font-weight: var(--fw-medium, 500);
    color: var(--nav-mobile-link-color, var(--text-body)) !important;
    text-decoration: none;
    border-bottom: 1px solid var(--nav-mobile-divider-color, var(--border));
    transition: color 200ms ease, background 200ms ease;
}
.hzo-mobile-panel > .hzo-mobile-menu__link:last-child { border-bottom: 0; }
.hzo-mobile-panel > .hzo-mobile-menu__link:hover {
    color: var(--nav-link-hover) !important;
    background: var(--nav-mobile-link-hover-bg, var(--bg-alt));
}

/* Sidebar footer (contact info) */
.hzo-mobile-menu__footer {
    padding: 24px;
    border-top: 1px solid var(--nav-mobile-divider-color, var(--border));
    background: var(--nav-mobile-footer-bg, var(--bg-alt));
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
}
/* !important on color: fights a:visited from per-client main.css. */
.hzo-mobile-menu__contact {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    font-weight: var(--fw-medium, 500);
    color: var(--text-body) !important;
    text-decoration: none;
    transition: color 200ms ease;
}
.hzo-mobile-menu__contact:hover { color: var(--nav-link-hover) !important; }
.hzo-mobile-menu__contact svg { color: var(--accent); flex-shrink: 0; }

/* Prevent body scroll when menu is open */
body.hzo-menu-open { overflow: hidden; }

.hzo-utility-bar {
    background: var(--utility-bar-bg, var(--brand));
    color: var(--utility-bar-text, #fff);
    font-size: 13px;
    padding: var(--utility-bar-padding, 7px 0);
}
.hzo-utility-bar__inner {
    display: flex;
    align-items: center;
    justify-content: flex-end; /* desktop/tablet: right-aligned */
    gap: 12px;
}
.hzo-utility-bar__links {
    display: flex;
    align-items: center;
    gap: 12px;
}
.hzo-utility-bar__divider { color: var(--utility-bar-divider-color, rgba(255,255,255,0.3)); user-select: none; }

/* !important on color: fights a:visited from per-client main.css. */
.hzo-utility-bar a,
.hzo-utility-bar a:visited {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--utility-link) !important;
    text-decoration: none;
    font-weight: var(--fw-bold, 700);
    white-space: nowrap;
    transition: color 200ms ease;
}
.hzo-utility-bar a:hover,
.hzo-utility-bar a:visited:hover { color: var(--utility-link-hover) !important; }
.hzo-utility-bar a svg { flex-shrink: 0; }

/* Mobile: center the links (no hours on mobile) */
@media (max-width: 767px) {
    .hzo-utility-bar__inner { justify-content: center; }
}

/* Light utility bar variant — pale background with dark text/links.
   CSS custom properties are scoped to this selector, so --utility-link
   and --utility-link-hover resolve to the lighter-context values for
   everything inside. Apply via: <div class="hzo-utility-bar hzo-utility-bar--light"> */
.hzo-utility-bar--light {
    background: var(--utility-bar-light-bg, var(--bg-alt));
    color: var(--utility-bar-light-text, var(--text-body));
    border-bottom: 1px solid var(--utility-bar-light-border-color, var(--border));
    --utility-link: var(--text-muted);
    --utility-link-hover: var(--brand);
}

.hzo-mega-menu__close:hover { color: var(--brand); }

/* ─── Long-form content (legal pages, articles) ────────────────────── */
/* Heading spacing inside hzo-sections — excludes the eyebrow pattern */
.hzo-section h2:not(.hzo-eyebrow) {
    margin-top: var(--space-xl);
    margin-bottom: var(--space-md);
}
.hzo-section h3:not(.hzo-eyebrow) {
    margin-top: var(--space-lg);
    margin-bottom: var(--space-sm);
}
.hzo-section h4:not(.hzo-eyebrow) {
    margin-top: var(--space-md);
    margin-bottom: var(--space-sm);
}
.hzo-section h2:not(.hzo-eyebrow):first-child,
.hzo-section h3:not(.hzo-eyebrow):first-child {
    margin-top: 0;
}

/* Block-table borders use the global border token (pale gray, not browser default) */
.hzo-section .wp-block-table table {
    border-collapse: collapse;
    width: 100%;
}
.hzo-section .wp-block-table thead tr {
    border-bottom: 2px solid var(--border);
}
.hzo-section .wp-block-table tbody tr {
    border-bottom: 1px solid var(--border);
}
.hzo-section .wp-block-table th,
.hzo-section .wp-block-table td {
    border: none;
    padding: 12px 16px;
    text-align: left;
    vertical-align: top;
}

/* Block-table mobile stacking — rows collapse to labeled-cell cards.
   data-label is injected at runtime by main.js from each table's thead. */
@media (max-width: 767px) {
    .hzo-section .wp-block-table table,
    .hzo-section .wp-block-table thead,
    .hzo-section .wp-block-table tbody,
    .hzo-section .wp-block-table tr,
    .hzo-section .wp-block-table th,
    .hzo-section .wp-block-table td {
        display: block;
        width: auto;
    }
    .hzo-section .wp-block-table thead {
        position: absolute;
        clip: rect(0, 0, 0, 0);
        height: 1px;
        width: 1px;
        overflow: hidden;
    }
    .hzo-section .wp-block-table tbody tr {
        margin-bottom: var(--space-md);
        padding: var(--space-md) 0;
        border-bottom: 1px solid var(--border);
    }
    .hzo-section .wp-block-table tbody tr:last-child {
        border-bottom: none;
    }
    .hzo-section .wp-block-table td {
        padding: var(--space-xs) 0;
        border: none;
    }
    .hzo-section .wp-block-table td::before {
        content: attr(data-label);
        display: block;
        font-weight: var(--fw-bold, 700);
        font-size: 12px;
        color: var(--text-heading);
        text-transform: uppercase;
        letter-spacing: 0.05em;
        margin-bottom: 4px;
    }
    .hzo-section .wp-block-table td:empty {
        display: none;
    }
}

/* ─── Doc layout + sticky TOC sidebar (legal pages, long-form articles) ──
   Two-column grid: TOC sidebar on the left, document body on the right.
   The sidebar is sticky on desktop, stacks above the body on mobile.
   The active section is highlighted via IntersectionObserver scrollspy
   in main.js. Section numbers (.hzo-section-num) sit next to each <h2>
   in a flex container, aria-hidden so screen readers read only the
   heading. Both the inline number and the matching TOC number are
   hand-authored to keep the markup static + crawlable without JS. */
.hzo-doc-layout {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-xl);
    align-items: start;
}
@media (min-width: 1024px) {
    .hzo-doc-layout {
        grid-template-columns: 240px 1fr;
        gap: var(--space-3xl);
    }
}

.hzo-doc-toc { position: static; }
@media (min-width: 1024px) {
    .hzo-doc-toc {
        position: sticky;
        top: 104px;
        max-height: calc(100vh - 120px);
        overflow-y: auto;
        padding-right: 8px;
    }
}
.hzo-doc-toc::-webkit-scrollbar { width: 4px; }
.hzo-doc-toc::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

.hzo-doc-toc__label {
    font-family: var(--font-body);
    font-size: 12px;
    font-weight: var(--fw-semibold, 600);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin: 0 0 var(--space-md);
    padding-bottom: var(--space-sm);
    border-bottom: 1px solid var(--border);
}

.hzo-doc-toc__list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
}

.hzo-doc-toc__item { position: relative; }

/* !important on color: fights a:visited from per-client main.css.
   Matching :visited rule below preserves the active/idle colors. */
.hzo-doc-toc__link {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 8px 0 8px 14px;
    color: var(--text-muted) !important;
    text-decoration: none;
    font-family: var(--font-body);
    font-size: 14px;
    line-height: 1.4;
    border-left: 2px solid var(--border);
    transition: color 0.15s, border-color 0.15s;
}
.hzo-doc-toc__link:hover { color: var(--text-body) !important; }
.hzo-doc-toc__link.is-active {
    color: var(--brand) !important;
    border-left-color: var(--brand);
    font-weight: var(--fw-semibold, 600);
}
.hzo-doc-toc__link:visited { color: var(--text-muted) !important; }
.hzo-doc-toc__link:visited:hover { color: var(--text-body) !important; }
.hzo-doc-toc__link.is-active:visited { color: var(--brand) !important; }

.hzo-doc-toc__num {
    font-family: var(--font-body);
    font-size: 12px;
    font-weight: var(--fw-medium, 500);
    color: var(--text-muted);
    min-width: 22px;
    flex-shrink: 0;
}
.hzo-doc-toc__link.is-active .hzo-doc-toc__num { color: var(--brand); }

/* Section heading row inside the doc body — flex container that holds
   the decorative number + the real heading tag, baseline-aligned. The
   number is aria-hidden so screen readers read only the h2. */
.hzo-doc-section-head {
    display: flex;
    align-items: baseline;
    gap: var(--space-md);
    margin-bottom: var(--space-md);
}
.hzo-section-num {
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: var(--fw-semibold, 600);
    color: var(--text-muted);
    flex-shrink: 0;
    line-height: 1.4;
}
/* Reset the eyebrow's default bottom margin when it sits inside a
   section-head flex row — the row owns spacing, not the eyebrow. */
.hzo-doc-section-head > .hzo-eyebrow,
.hzo-doc-section-head > h1.hzo-eyebrow,
.hzo-doc-section-head > h2.hzo-eyebrow,
.hzo-doc-section-head > h3.hzo-eyebrow,
.hzo-doc-section-head > h4.hzo-eyebrow {
    margin: 0 !important;
}

/* Section adjacency rule — when [hzo_final_cta] (or any .hzo-section)
   follows another .hzo-section, collapse the doubled padding (80+80=160
   on desktop, 48+48=96 on mobile) by stripping the second section's
   top padding. The preceding section's bottom padding becomes the sole
   gap, scaling responsively via the .hzo-section ladder (48/64/80).
   System-level fix replacing per-page padding-bottom:0 hacks. */
.hzo-section + .hzo-section,
.hzo-section + .hzo-final-cta {
    padding-top: 0;
}
/* …EXCEPT a colored surface band (--pale/--tint/--dark) or a hero must ALWAYS
   keep its own top padding, even when it follows another section — otherwise
   its background sits flush against the content (the "no top padding on
   colored sections" bug). Only plain white-on-white sections collapse.
   Restored responsively to match the .hzo-section ladder (48 / 64 / 80). */
.hzo-section + .hzo-section--pale,
.hzo-section + .hzo-section--tint,
.hzo-section + .hzo-section--dark,
.hzo-section + .hzo-hero {
    padding-top: var(--space-xl);
}
@media (min-width: 768px) {
    .hzo-section + .hzo-section--pale,
    .hzo-section + .hzo-section--tint,
    .hzo-section + .hzo-section--dark,
    .hzo-section + .hzo-hero { padding-top: var(--space-2xl); }
}
@media (min-width: 1250px) {
    .hzo-section + .hzo-section--pale,
    .hzo-section + .hzo-section--tint,
    .hzo-section + .hzo-section--dark,
    .hzo-section + .hzo-hero { padding-top: var(--space-3xl); }
}

/* Doc page card — contained card with bg-alt + radius. Used for the
   hero and closing CTA on long-form doc pages (privacy, terms). Inner
   padding scales across five zones via QA breakpoints (480, 768, 1024,
   1250). Tightens on small phones, opens up on desktop, caps at
   64/48 from 1250 onward. */
.hzo-doc-card {
    background: var(--bg-alt);
    border-radius: var(--radius-card);
    padding: var(--space-lg-2) var(--space-md);
    text-align: center;
}
@media (min-width: 480px)  { .hzo-doc-card { padding: var(--space-xl-2) var(--space-lg); } }
@media (min-width: 768px)  { .hzo-doc-card { padding: var(--space-xl) var(--space-lg-2); } }
@media (min-width: 1024px) { .hzo-doc-card { padding: var(--space-2xl-2) var(--space-xl-2); } }
@media (min-width: 1250px) { .hzo-doc-card { padding: var(--space-2xl) var(--space-xl); } }

/* Vertical rhythm between adjacent doc-page siblings (.hzo-doc-card,
   .hzo-doc-layout) inside a single .hzo-section > .hzo-container.
   Same five-zone scale as the card padding. First sibling has no top
   gap — section padding-top handles that breathing room. */
.hzo-doc-card + .hzo-doc-card,
.hzo-doc-card + .hzo-doc-layout,
.hzo-doc-layout + .hzo-doc-card {
    margin-top: var(--space-lg-2);
}
@media (min-width: 480px) {
    .hzo-doc-card + .hzo-doc-card,
    .hzo-doc-card + .hzo-doc-layout,
    .hzo-doc-layout + .hzo-doc-card { margin-top: var(--space-xl-2); }
}
@media (min-width: 768px) {
    .hzo-doc-card + .hzo-doc-card,
    .hzo-doc-card + .hzo-doc-layout,
    .hzo-doc-layout + .hzo-doc-card { margin-top: var(--space-xl); }
}
@media (min-width: 1024px) {
    .hzo-doc-card + .hzo-doc-card,
    .hzo-doc-card + .hzo-doc-layout,
    .hzo-doc-layout + .hzo-doc-card { margin-top: var(--space-2xl-2); }
}
@media (min-width: 1250px) {
    .hzo-doc-card + .hzo-doc-card,
    .hzo-doc-card + .hzo-doc-layout,
    .hzo-doc-layout + .hzo-doc-card { margin-top: var(--space-2xl); }
}

/* CTA variant of .hzo-doc-card — used as the closing "Get in touch"
   block on long-form doc pages. Identical to the base card on desktop;
   on mobile (<768) the card flips to left-aligned and stacks the email
   and phone contact links onto separate lines so longer email addresses
   don't get awkwardly wrapped or centered on narrow screens. */
@media (max-width: 767px) {
    .hzo-doc-card--cta {
        text-align: left;
    }
    .hzo-doc-card--cta .hzo-doc-card__contact a {
        display: block;
    }
    .hzo-doc-card--cta .hzo-doc-card__sep {
        display: none;
    }
}

/* Body sections — separated by top rules + generous vertical rhythm.
   scroll-margin-top offsets the anchor jump so the section title lands
   below the sticky header (which is ~80px). */
.hzo-doc-body > section {
    margin-top: var(--space-3xl);
    padding-top: var(--space-3xl);
    border-top: 1px solid var(--border);
    scroll-margin-top: 100px;
}
.hzo-doc-body > section:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}
.hzo-doc-body h2:not(.hzo-eyebrow):first-child { margin-top: 0; }

/* ─── Site footer chrome ────────────────────────────────────────────── */
.hzo-site-footer { background: var(--footer-bg, transparent); color: var(--footer-text, #fff); }
.hzo-site-footer a { color: var(--footer-link-base-dark, rgba(255,255,255,0.85)); text-decoration: none; }
.hzo-site-footer a:hover { color: var(--footer-link-hover-dark, #fff); }

/* Footer column grid — single column on mobile, 4-column on tablet+.
   Brand column (first) takes 2× the width of the other columns on desktop. */
.hzo-site-footer__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--footer-gap, 32px);
}
@media (min-width: 768px) {
    .hzo-site-footer__grid {
        grid-template-columns: 2fr 1fr 1fr 1fr;
        gap: var(--footer-gap, 40px);
    }
}

/* Footer legal bar — stacks on mobile, spreads on tablet+ */
.hzo-site-footer__legal {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--footer-legal-gap, 12px);
}
@media (min-width: 768px) {
    .hzo-site-footer__legal {
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
        gap: var(--footer-legal-gap, 16px);
    }
}

/* ─── Alerts ────────────────────────────────────────────────────────── */
.hzo-alert {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: var(--space-md) var(--space-lg);
    border-left: 4px solid;
    border-radius: 4px;
    font-size: 15px;
    font-weight: var(--fw-medium, 500);
    line-height: 1.5;
}
.hzo-alert > svg { flex-shrink: 0; }
.hzo-alert--info    { background: var(--color-info-bg);    border-color: var(--color-info);    color: var(--color-info); }
.hzo-alert--success { background: var(--success-bg);       border-color: var(--success);       color: #166534; }
.hzo-alert--warning { background: var(--color-warning-bg); border-color: var(--color-warning); color: #92400E; }
.hzo-alert--error   { background: var(--error-bg);         border-color: var(--error);         color: #991B1B; }

/* ─── Badges ─────────────────────────────────────────────────────── */
.hzo-badge {
    display: inline-flex;
    align-items: center;
    line-height: 1;
    padding: 6px 11px;
    border-radius: var(--badge-radius, var(--radius-pill));
    font-size: 12px;
    font-weight: var(--badge-weight, var(--fw-semibold, 600));
    letter-spacing: 0.03em;
    text-transform: uppercase;
    background: var(--bg-alt);
    color: var(--text-body);
}
.hzo-badge--primary   { background: var(--brand); color: var(--text-on-brand); }
.hzo-badge--secondary { background: var(--accent); color: var(--text-on-accent); }
.hzo-badge--success   { background: var(--success); color: #fff; }
.hzo-badge--warning   { background: var(--color-warning); color: #fff; }
.hzo-badge--error     { background: var(--error); color: #fff; }
.hzo-badge--info      { background: var(--color-info); color: #fff; }
.hzo-badge--outline   { background: transparent; color: var(--brand); border: 1px solid var(--brand); }
/* Sale — promo attention badge. Reuses the accent (the system's `--emphasis`
   attention colour) so it stands apart from the stock states; no new token. Always
   pair with the word "Sale" so the meaning is never carried by colour alone.
   Stock states compose existing variants: in-stock = --success, low-stock =
   --warning, out-of-stock = the base (neutral) badge — unavailability is a state,
   not an error, so red (--error) is reserved for genuine errors. */
.hzo-badge--sale      { background: var(--accent); color: var(--text-on-accent); }

/* ─── Tags / chips ────────────────────────────────────────────────────
   Distinct from a badge: a tag is an INTERACTIVE category/filter chip
   (sentence case; can be a link or a removable token), where a badge is a
   STATIC status label (uppercase). <span> = static, <a> = filter link,
   <button> = toggle/removable. */
.hzo-tag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: var(--fw-medium, 500);
    line-height: 1.2;
    color: var(--text-body);
    background: var(--bg-alt);
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
}
/* Interactive tags (filter links / toggles) lift to a brand tint on hover.
   !important on color for the <a> form fights per-client a:visited; the
   matching :visited rule sits just below (co-located, same pattern as
   .hzo-footer-nap / .hzo-social-icons). */
a.hzo-tag,
button.hzo-tag {
    cursor: pointer;
    text-decoration: none;
    transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-base);
}
a.hzo-tag { color: var(--text-body) !important; }
a.hzo-tag:visited { color: var(--text-body) !important; }
a.hzo-tag:hover,
a.hzo-tag:visited:hover,
button.hzo-tag:hover { background: var(--brand-pale); border-color: var(--brand); color: var(--brand-text) !important; }
a.hzo-tag:focus-visible,
button.hzo-tag:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
/* Selected / active filter chip. */
.hzo-tag.is-active,
.hzo-tag[aria-pressed="true"] {
    background: var(--brand-pale);
    border-color: var(--brand);
    color: var(--brand-text) !important;
}
/* Removable chip — trailing × button. Removal wiring is the author's (a small
   JS handler); this styles the affordance and its states. */
.hzo-tag--removable { padding-right: 5px; }
.hzo-tag__remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-muted);
    border-radius: 50%;
    cursor: pointer;
    transition: background var(--transition-base), color var(--transition-base);
}
.hzo-tag__remove:hover { background: var(--border); color: var(--text-heading); }
.hzo-tag__remove:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.hzo-tag__remove > svg { width: 12px; height: 12px; display: block; }
/* Container for a set of (often removable) chips. Removal + focus management is
   wired by the tag-removal IIFE in main.js off the .hzo-tag__remove buttons. */
.hzo-tag-list { display: flex; flex-wrap: wrap; gap: var(--space-sm); }
.hzo-tag-list:focus { outline: none; }   /* -1 fallback focus target when the last chip is removed */

/* ─── Filters / facets (UI surface) ───────────────────────────────────
   Accessible faceted-filter UI: fieldset/legend groups of checkboxes (multi)
   or radios (single), active-filter chips (reuse .hzo-tag--removable), a
   clear-all control, and an aria-live result-count region. Behaviour — chip↔box
   sync, clear-all, count announce, and the hzo:filterchange event — is wired by
   the filters IIFE in main.js off the .hzo-filters / [data-hzo-filters] contract.
   UI surface only: it emits state, it does not query. Zero new tokens.
   Markup contract: component-patterns.md §47. */
.hzo-filters { display: flex; flex-direction: column; gap: var(--space-md); max-width: 320px; }
.hzo-filters__bar {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-sm); flex-wrap: wrap;
}
.hzo-filters__count { margin: 0; font-size: 0.875rem; color: var(--text-muted); }
.hzo-filter-group { border: 0; margin: 0; padding: 0; min-width: 0; }
.hzo-filter-group > legend {
    padding: 0; margin: 0 0 var(--space-sm);
    font-family: var(--font-heading);
    font-weight: var(--fw-semibold, 600);
    font-size: 0.9375rem; color: var(--text-heading);
}
.hzo-filter-group + .hzo-filter-group { border-top: 1px solid var(--border); padding-top: var(--space-md); }
.hzo-filter-group__options { display: flex; flex-direction: column; gap: var(--space-sm); }
.hzo-filter-option {
    display: flex; align-items: center; gap: 10px;
    font-size: 0.9375rem; color: var(--text-body); line-height: 1.3; cursor: pointer;
}
.hzo-filter-option > input { flex: 0 0 auto; width: 16px; height: 16px; accent-color: var(--brand); cursor: pointer; }

/* ─── Avatar ──────────────────────────────────────────────────────────
   Circular user/brand image with an initials fallback. Base 48px; --sm 32,
   --lg 64. Image: <span class="hzo-avatar"><img alt="..."></span>. Initials:
   <span class="hzo-avatar hzo-avatar--initials">JD</span> (brand-pale field +
   brand-text letters). Composed by the testimonial + team/bio blocks. */
.hzo-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--bg-alt);
    color: var(--text-muted);
    font-family: var(--font-body);
    font-weight: var(--fw-semibold, 600);
    font-size: 1rem;
    line-height: 1;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    user-select: none;
}
.hzo-avatar > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.hzo-avatar--initials { background: var(--brand-pale); color: var(--brand-text); }
.hzo-avatar--sm { width: 32px; height: 32px; font-size: 0.8125rem; }
.hzo-avatar--lg { width: 64px; height: 64px; font-size: 1.25rem; }

/* ─── Divider / rule ──────────────────────────────────────────────────
   Horizontal separator. Plain <hr class="hzo-divider"> or a labeled variant:
   <div class="hzo-divider hzo-divider--labeled"><span>or</span></div>. */
.hzo-divider {
    border: 0;
    border-top: 1px solid var(--border);
    height: 0;
    margin: var(--space-lg) 0;
}
.hzo-divider--labeled {
    border-top: 0;
    height: auto;
    display: flex;
    align-items: center;
    gap: var(--space-md);
    color: var(--text-muted);
    font-family: var(--font-body);
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.hzo-divider--labeled::before,
.hzo-divider--labeled::after {
    content: "";
    flex: 1;
    border-top: 1px solid var(--border);
}

/* ─── Tables ───────────────────────────────────────────────────────── */
.hzo-table { font-family: var(--font-body); }
.hzo-table thead th { font-family: var(--font-heading); color: var(--text-heading); }

/* Responsive table: on mobile, rows stack vertically and each <td> shows
   its column label via the data-label attribute. Requires each <td> to
   have data-label="Column Name" so the label appears next to the value.
   Desktop rendering is unchanged. */
@media (max-width: 767px) {
    .hzo-table thead { display: none; }
    .hzo-table,
    .hzo-table tbody,
    .hzo-table tr,
    .hzo-table td { display: block; width: 100%; box-sizing: border-box; }
    .hzo-table tr {
        border: 1px solid var(--border);
        border-radius: var(--radius-input);
        padding: 8px 16px;
        margin-bottom: 12px;
    }
    .hzo-table td {
        padding: 10px 0;
        border: 0;
        border-bottom: 1px solid var(--border);
        display: flex;
        justify-content: space-between;
        gap: 16px;
        font-size: 14px;
    }
    .hzo-table tr td:last-child { border-bottom: 0; }
    .hzo-table td[data-label]::before {
        content: attr(data-label);
        font-weight: var(--fw-semibold, 600);
        color: var(--text-muted);
        flex-shrink: 0;
    }
}

/* ─── Comparison table (feature-comparison variant of .hzo-table) ─────
   Plans across the top, features down the side, ✓/✗ (or text) in cells.
   Markup contract: <th scope="col"> plan headers, <th scope="row"> feature
   names, each value <td> carries data-label="<plan>" for the stacked view.
   Reuses .hzo-table's responsive stacking — the additions are desktop
   alignment, the featured-column tint, and the mobile rule that turns the
   feature-name row-header into a card title (base stacking only blockifies
   <td>, never <th>, so a comparison table would otherwise break when stacked). */
.hzo-table--compare { width: 100%; border-collapse: collapse; }
.hzo-table--compare th,
.hzo-table--compare td {
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
    text-align: center;
    vertical-align: middle;
}
.hzo-table--compare thead th { border-bottom: 2px solid var(--border); }
/* Feature-name column reads left-aligned (header + row-headers). */
.hzo-table--compare th:first-child,
.hzo-table--compare td:first-child { text-align: left; }
.hzo-table--compare tbody th[scope="row"] {
    font-family: var(--font-body);
    font-weight: var(--fw-semibold, 600);
    color: var(--text-heading);
}
/* ✓ / ✗ cell icons (mirrors the .hzo-pricing__features check). The SVGs carry
   role="img" + aria-label in markup so the state is announced to AT. */
.hzo-table--compare svg { width: 20px; height: 20px; }
.hzo-table__yes { color: var(--success); }
.hzo-table__no  { color: var(--text-muted); }
/* Recommended / featured column — tints each cell in the column (desktop) and,
   once stacked, the matching plan row in every card (mobile). No new token. */
.hzo-table__col--featured { background: var(--brand-pale); }

@media (max-width: 767px) {
    /* .hzo-table's base mobile rules already hide thead, block-ify tr/td, and
       add the data-label "<plan>: value" rows. The ONLY missing piece for a
       comparison table is the feature-name row-header (<th>) — base never
       touches <th> — so promote it to the card title. */
    .hzo-table--compare tbody th[scope="row"] {
        display: block;
        width: 100%;
        text-align: left;
        font-family: var(--font-heading);
        font-size: 1.0625rem;
        color: var(--text-heading);
        padding: 4px 0 10px;
        border-bottom: 1px solid var(--border);
        margin-bottom: 4px;
    }
}

/* ─── Accordion ─────────────────────────────────────────────────── */
.hzo-accordion { display: flex; flex-direction: column; gap: 8px; }
.hzo-accordion__item {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: var(--radius-input);
    overflow: hidden;
}
.hzo-accordion__question {
    padding: 18px 20px;
    font-family: var(--font-heading);
    font-size: 1.0625rem;
    font-weight: var(--fw-bold, 700);
    color: var(--text-heading);
    cursor: pointer;
    list-style: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
}
.hzo-accordion__question::-webkit-details-marker,
.hzo-accordion__question::marker { display: none; content: none; }

.hzo-accordion__icon {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    color: var(--text-heading); /* dark enough to read on the white panel */
    transition: transform 300ms ease, color 200ms ease;
}
.hzo-accordion__item[open] > .hzo-accordion__question > .hzo-accordion__icon {
    transform: rotate(180deg);
    color: var(--brand); /* highlight the open row's caret */
}

.hzo-accordion__answer { padding: 8px 20px 20px; color: var(--text-muted); }

/* When open, tighten the question's bottom padding so the title box (and its
   hover tint) hugs the title, while the answer's own top padding gives the body
   breathing room — same overall gap, but no cramped body against the tint. */
.hzo-accordion__item[open] > .hzo-accordion__question { padding-bottom: 10px; }

/* Hover lifts ONLY the title box to the lightest brand tint. Scoped to the
   question row so the open answer-body area never tints on hover. */
.hzo-accordion__question { transition: background-color 200ms ease; }
.hzo-accordion__question:hover { background: var(--brand-pale); }
@media (prefers-reduced-motion: reduce) {
    .hzo-accordion__question { transition: none; }
}

/* ─── Tabs ─────────────────────────────────────────────────────── */
.hzo-tabs__list {
    display: flex;
    gap: 4px;
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
    flex-wrap: nowrap;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.hzo-tabs__list::-webkit-scrollbar { display: none; }
/* Tabs can be authored as <button> or <a>. !important on color fights
   a:visited from per-client main.css when authored as <a>. The rest
   of the rule wins on class specificity alone. */
.hzo-tabs__tab {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    outline: none;
    box-shadow: none;
    -webkit-tap-highlight-color: transparent;
    padding: 14px 24px;
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: var(--fw-medium, 500);
    color: var(--text-muted) !important;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s;
    margin-bottom: -1px;
    line-height: 1.2;
    flex-shrink: 0;
    white-space: nowrap;
}
.hzo-tabs__tab:hover { color: var(--brand) !important; }
.hzo-tabs__tab:focus-visible { box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus-ring) 35%, transparent); border-radius: 3px; }
.hzo-tabs__tab.is-active {
    color: var(--brand) !important;
    border-bottom-color: var(--brand);
    font-weight: var(--fw-semibold, 600);
}
/* Tab panels — switched by the tabs IIFE in main.js (manual activation:
   arrow keys move focus between tabs; Enter/Space/click activates). */
.hzo-tabs__panel { padding-top: var(--space-lg); }
.hzo-tabs__panel[hidden] { display: none; }
.hzo-tabs__panel:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 4px; border-radius: 4px; }
.hzo-tabs__panel > :first-child { margin-top: 0; }
.hzo-tabs__panel > :last-child { margin-bottom: 0; }

/* ─── Forms (opt-in via .hzo-form wrapper) ──────────────────────
   Rules activate only inside a .hzo-form container. Targets two
   surfaces:

   1. Native HTML form elements (input/textarea/select) — also catches
      Fluent Forms' rendered output (Fluent Forms emits standard HTML
      inputs inside .ff-el-form-control wrappers; the .hzo-form wrapper
      style applies via tag-name match, no plugin-specific selectors
      required).
   2. Hozio Studio BEM classes (.hzo-form__label, .hzo-form__description,
      .hzo-form__option, .hzo-form__message--error/success,
      .hzo-form__input--error) — direct authoring + validation states.

   !important is retained on field-level rules so the styles win
   against equal-specificity plugin output (Fluent Forms, or any form
   plugin we swap to later) when source order isn't guaranteed. NOT
   carried into structural rules. */
.hzo-form { max-width: 640px; }

.hzo-form input[type="text"],
.hzo-form input[type="email"],
.hzo-form input[type="tel"],
.hzo-form input[type="number"],
.hzo-form input[type="url"],
.hzo-form input[type="password"],
.hzo-form input[type="date"],
.hzo-form textarea,
.hzo-form select {
    width: 100%;
    padding: var(--input-padding, 12px 16px) !important;
    font-family: var(--font-body) !important;
    font-size: 1rem !important;
    color: var(--text-body) !important;
    background: var(--input-bg, #fff) !important;
    border: 1px solid var(--input-border, var(--border)) !important;
    border-radius: var(--input-radius, var(--radius-input)) !important;
    line-height: 1.5;
    transition: border-color 0.15s, box-shadow 0.15s;
    box-sizing: border-box;
}

.hzo-form input:focus,
.hzo-form textarea:focus,
.hzo-form select:focus {
    outline: none;
    border-color: var(--focus-ring) !important;
    box-shadow: 0 0 0 2px var(--brand-pale) !important;
}

.hzo-form input::placeholder,
.hzo-form textarea::placeholder { color: #9ca3af; }

/* Validation error state — opt-in modifier class. Applied to the input
   element itself (e.g. <input class="hzo-form__input--error">). */
.hzo-form .hzo-form__input--error,
.hzo-form input.hzo-form__input--error,
.hzo-form textarea.hzo-form__input--error,
.hzo-form select.hzo-form__input--error {
    border-color: var(--error) !important;
    box-shadow: 0 0 0 2px var(--error-bg) !important;
}

/* Select dropdown: hide native arrow, paint a custom chevron (Hozio-style).
   Uses the `background` shorthand to override the .hzo-form input/select
   rule above (which also uses the shorthand with !important).
   Stroke color #1F2937 matches --text-heading for stronger contrast. */
.hzo-form select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 44px !important;
    background: #fff url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231F2937' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>") no-repeat right 16px center / 16px 16px !important;
    cursor: pointer;
}

/* Field labels — BEM class (direct authoring). Matches the Fluent
   .ff-el-input--label label rule below so direct-authored and plugin-
   rendered forms look identical. */
.hzo-form .hzo-form__label {
    display: block;
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: var(--fw-semibold, 600);
    line-height: 1.4;
    color: var(--text-body);
    margin-bottom: 6px;
}

/* Field descriptions — BEM class. */
.hzo-form .hzo-form__description {
    font-size: 15px;
    color: var(--text-muted);
    margin-top: 6px;
}

/* Validation messages — BEM modifier classes (rendered by the form handler
   or hand-placed). */
.hzo-form .hzo-form__message--error   { color: var(--error); }
.hzo-form .hzo-form__message--success { color: var(--success); }

/* Radio/checkbox option row layout — BEM class. */
.hzo-form .hzo-form__option {
    display: inline-flex;
    align-items: center;
    font-size: 15px;
    color: var(--text-body);
    line-height: 1.4;
    padding: 6px 0;
    cursor: pointer;
}

/* Custom-styled checkboxes and radios.
   Hozio-style: 20px square/round, border --border, filled --brand when checked
   with white check/dot indicator. !important kept on appearance/visual
   properties because browser-default rendering + plugin form output may
   apply equal-specificity styling that source order does not guarantee
   defeating. */
.hzo-form input[type="checkbox"],
.hzo-form input[type="radio"] {
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    width: 20px !important;
    height: 20px !important;
    padding: 0 !important;
    margin-right: 10px !important;
    border: 1.5px solid var(--border) !important;
    background: #fff !important;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
    flex-shrink: 0;
    position: relative;
    display: inline-block;
}
.hzo-form input[type="checkbox"] { border-radius: 4px !important; }
.hzo-form input[type="radio"]    { border-radius: 50% !important; }

.hzo-form input[type="checkbox"]:hover,
.hzo-form input[type="radio"]:hover {
    border-color: var(--focus-ring) !important;
}

.hzo-form input[type="checkbox"]:focus-visible,
.hzo-form input[type="radio"]:focus-visible {
    outline: none !important;
    border-color: var(--focus-ring) !important;
    box-shadow: 0 0 0 3px var(--brand-pale) !important;
}

.hzo-form input[type="checkbox"]:checked,
.hzo-form input[type="radio"]:checked {
    background: var(--brand) !important;
    border-color: var(--brand) !important;
}

/* Checkmark for checked checkbox */
.hzo-form input[type="checkbox"]:checked::after {
    content: "";
    position: absolute;
    left: 5px;
    top: 1px;
    width: 6px;
    height: 11px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

/* Dot for selected radio */
.hzo-form input[type="radio"]:checked::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #fff;
    transform: translate(-50%, -50%);
}

/* ─── Switch / toggle (styled NATIVE checkbox — zero JS) ──────────────
   A toggle is just a checkbox re-skinned as a track + thumb. The native
   <input type="checkbox"> keeps ALL behavior + accessibility for free:
   Tab focus, Space toggles, checked state exposed to assistive tech — so
   NO role / aria-checked is needed (it IS a checkbox). Opt in by wrapping
   the checkbox in <label class="hzo-switch">.

   These rules sit AFTER the base checkbox rules above and at higher
   specificity (.hzo-form .hzo-switch input = 0,0,3,1 vs base 0,0,2,1), so
   they win cleanly. The thumb is drawn with ::before; the base checkbox's
   ::after checkmark is suppressed (content:none). */
.hzo-form .hzo-switch {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    font-size: 15px;
    color: var(--text-body);
    line-height: 1.4;
}
.hzo-form .hzo-switch input[type="checkbox"] {
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    flex-shrink: 0;
    width: 44px !important;
    height: 24px !important;
    margin: 0 !important;
    padding: 0 !important;
    border: none !important;
    border-radius: var(--radius-pill) !important;
    background: var(--border) !important;
    position: relative;
    cursor: pointer;
    transition: background 0.2s ease;
}
/* Suppress the base checkbox checkmark (drawn via ::after) — the switch uses
   ::before for its thumb instead. */
.hzo-form .hzo-switch input[type="checkbox"]::after { content: none !important; }
.hzo-form .hzo-switch input[type="checkbox"]::before {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #fff;
    box-shadow: var(--shadow-sm);
    transition: transform 0.2s ease;
}
.hzo-form .hzo-switch input[type="checkbox"]:checked { background: var(--brand) !important; }
.hzo-form .hzo-switch input[type="checkbox"]:checked::before { transform: translateX(20px); }
.hzo-form .hzo-switch input[type="checkbox"]:focus-visible {
    outline: none !important;
    box-shadow: 0 0 0 3px var(--brand-pale) !important;
}
@media (prefers-reduced-motion: reduce) {
    .hzo-form .hzo-switch input[type="checkbox"],
    .hzo-form .hzo-switch input[type="checkbox"]::before { transition: none; }
}

/* ─── Disabled fields ─────────────────────────────────────────────────
   The browser default washes disabled controls to a low-opacity gray that
   reads as "broken." Use the muted surface + muted text + not-allowed
   cursor at full opacity instead. Same-specificity-as-base + later source
   order wins the bg/color (both carry !important). */
.hzo-form input:disabled,
.hzo-form textarea:disabled,
.hzo-form select:disabled {
    background: var(--bg-alt) !important;
    color: var(--text-muted) !important;
    -webkit-text-fill-color: var(--text-muted); /* Safari keeps its own disabled text color without this */
    cursor: not-allowed;
    opacity: 1;
}
.hzo-form input:disabled::placeholder,
.hzo-form textarea:disabled::placeholder { color: #b8bec9; }
.hzo-form input[type="checkbox"]:disabled,
.hzo-form input[type="radio"]:disabled,
.hzo-form .hzo-switch input[type="checkbox"]:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* ─── Fluent Forms wrapper styling (universal, inside .hzo-form) ─────
   The .hzo-form rules above target NATIVE HTML elements
   (input/textarea/select/checkbox/radio), which already catches
   Fluent's rendered inputs because Fluent emits standard HTML inside
   its own .ff-el-* wrapper divs. This block fills the gap: styling
   for those wrapper divs (labels, help text, field-to-field spacing,
   multi-column rows, section breaks, submit button, error states).

   Source: actual Fluent Forms output sampled from studio.hoziodev.com.
   See component-patterns.md §12 for the markup spec.

   !important is retained where Fluent's own default rule sets the same
   property — same rationale as the base .hzo-form rules above. */

/* Field-to-field vertical rhythm */
.hzo-form .ff-el-group {
    margin-bottom: var(--space-lg);
}

/* Label wrapper + inner label typography */
.hzo-form .ff-el-input--label {
    margin-bottom: var(--space-sm);
}

.hzo-form .ff-el-input--label label {
    display: inline;
    font-family: var(--font-body) !important;
    font-size: 15px !important;
    font-weight: var(--fw-semibold, 600) !important;
    line-height: 1.4 !important;
    color: var(--text-body) !important;
    margin: 0 !important;
}

/* Required asterisk — Fluent emits .ff-el-is-required.asterisk-right
   on the label wrapper. We render the asterisk via ::after on the
   inner label so we control the color and weight. */
.hzo-form .ff-el-input--label.ff-el-is-required label::after {
    content: " *";
    color: var(--error);
    font-weight: var(--fw-bold, 700);
    margin-left: 2px;
}

/* Tooltip info icon — Fluent emits .ff-el-tooltip with an SVG inside
   the label wrapper, surfacing the field's help text on hover. Restyle
   the icon color + bring the cursor signal in line with our body type. */
.hzo-form .ff-el-tooltip {
    display: inline-flex !important;
    align-items: center;
    margin-left: 4px;
    color: var(--text-muted);
    cursor: help;
}
.hzo-form .ff-el-tooltip svg {
    width: 14px;
    height: 14px;
    fill: currentColor;
}

/* Help message — Fluent's equivalent to our .hzo-form__description */
.hzo-form .ff-el-help-message {
    font-size: 15px;
    color: var(--text-muted);
    line-height: 1.5;
    margin-top: var(--space-sm);
    margin-bottom: 0;
}

/* Multi-column rows — Fluent uses .ff-t-container / .ff-t-cell for
   side-by-side field pairs (name first/last, address city/state).
   Mobile collapses to single column; tablet+ shows side-by-side. */
.hzo-form .ff-t-container {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-md);
}

@media (min-width: 768px) {
    .hzo-form .ff-t-container {
        grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
    }
}

.hzo-form .ff-t-cell {
    min-width: 0; /* Prevent grid blowout from long content / overflow */
}

/* Section break — Fluent wraps in .ff-el-section-break containing an
   h3 .ff-el-section-title, optional description, and an <hr>. Replace
   Fluent's default look with a Hozio-style top-border + heading. */
.hzo-form .ff-el-section-break {
    margin: var(--space-2xl) 0 var(--space-lg) 0;
    padding-top: var(--space-lg);
    border-top: 1px solid var(--border);
}

.hzo-form .ff-el-section-title {
    font-family: var(--font-heading);
    font-size: 24px;
    font-weight: var(--fw-bold, 700);
    line-height: 1.3;
    color: var(--text-heading);
    margin: 0 0 var(--space-sm) 0;
}

.hzo-form .ff-section_break_desk {
    font-size: 16px;
    color: var(--text-body);
    line-height: 1.5;
    margin: 0;
}

.hzo-form .ff-el-section-break hr {
    display: none; /* We use the section-break's own border-top */
}

/* Checkbox + radio option container — Fluent wraps each option in
   .ff-el-form-check with a <label.ff-el-form-check-label> wrapping the
   input and a <span> with the option text. The native checkbox/radio
   inside is already styled by the .hzo-form input[type=...] rules above. */
.hzo-form .ff-el-form-check {
    display: block;
    padding: 6px 0;
}

.hzo-form .ff-el-form-check-label {
    display: inline-flex;
    align-items: flex-start;
    gap: 10px;
    font-size: 15px;
    color: var(--text-body);
    line-height: 1.5;
    cursor: pointer;
    margin: 0;
}

/* Native browser default vertical-aligns the checkbox/radio input mid-
   line, which looks fine for single-line option text but misaligns when
   the label wraps to multiple lines (e.g. the marketing consent statement
   with Privacy Policy link). Nudge the input down 2px so it sits flush
   with the cap-height of the first line of text. */
.hzo-form .ff-el-form-check-label > input[type="checkbox"],
.hzo-form .ff-el-form-check-label > input[type="radio"] {
    margin-top: 2px !important;
    flex-shrink: 0;
}

/* ─── .ff_list_buttons — radio/checkbox button rows ──────────────────
   Fluent's `ff_list_buttons` layout renders each option as a clickable
   button styled on the inner <span> (background, border, padding, font).
   Fluent's defaults produce a compact connected-button-bar look that
   already matches our design language well — the only thing we need to
   override is the SELECTED state, which Fluent paints in bright blue
   (#1a7efb) and reads identically to a CTA. Replace just the selected
   span colors with a light brand tint + accent border so selection is
   visible but less prominent than the submit button.

   Fluent marks the selected option via the `ff_item_selected` class on
   the .ff-el-form-check wrapper (managed via Fluent's own JS), which
   makes the override straightforward. */
.hzo-form .ff-el-group.ff_list_buttons .ff-el-form-check.ff_item_selected label > span,
.hzo-form .ff-el-group.ff_list_buttons .ff-el-form-check.ff_item_selected:first-child label > span,
.hzo-form .ff-el-group.ff_list_buttons .ff-el-form-check.ff_item_selected:last-child label > span {
    background-color: var(--brand-pale) !important;
    color: var(--text-body) !important;
    /* Don't override the border — keep it at Fluent's default gray so
       the connected-bar layout stays consistent (no item shifts when
       toggled). Paint the brand outline via box-shadow instead, which
       draws OVER neighbor edges + doesn't double-up on shared edges. */
    box-shadow: 0 0 0 1.5px var(--brand) !important;
    position: relative;
    z-index: 2;
}

/* Suppress Fluent's :focus-within blue (#b3d4fc) on un-selected pills.
   After a mouse click that toggles a checkbox OFF, the underlying input
   keeps focus until the user clicks elsewhere — so Fluent's focus-within
   rule paints the span blue and reads as a stuck "active" state. Force
   the span back to white when the option isn't selected, regardless of
   focus. Selected items keep their --brand-pale via the rule above
   (specificity wins via the .ff_item_selected class). */
.hzo-form .ff-el-group.ff_list_buttons .ff-el-form-check:not(.ff_item_selected) label:focus-within > span {
    background-color: #fff !important;
}

/* Mobile: full-width stacked pills.
   Fluent's mobile media query already sets `.ff-el-form-check { display:
   block; width: 100% }` and `.ff-el-form-check label > span { display:
   block; width: 100% }` — but Fluent leaves the LABEL between them as
   inline (its CSS default), so the span's `width: 100%` resolves
   against the label's content width and pills end up shrunk to text
   width with awkward right-side gaps. Forcing the label to block fills
   the cascade. Also: Fluent's mobile span rule sets `border: 1px solid`
   with NO color, falling back to currentColor — re-specify --border so
   the outline is the expected light gray, and add a vertical rhythm gap
   between stacked options. */
@media only screen and (max-width: 768px) {
    .hzo-form .ff-el-group.ff_list_buttons .ff-el-form-check {
        margin: 0 0 8px 0 !important;
    }
    .hzo-form .ff-el-group.ff_list_buttons .ff-el-form-check:last-child {
        margin-bottom: 0 !important;
    }
    .hzo-form .ff-el-group.ff_list_buttons .ff-el-form-check-label {
        display: block !important;
        width: 100% !important;
        margin: 0 !important;
    }
    .hzo-form .ff-el-group.ff_list_buttons .ff-el-form-check-label > span {
        display: block !important;
        width: 100% !important;
        border: 1px solid var(--border) !important;
        border-radius: var(--radius-input) !important;
        box-sizing: border-box;
        text-align: center;
        padding: 12px 16px !important;
    }
    /* Selected state at mobile — re-assert box-shadow outline + bg so
       the media-query specificity doesn't drop the override. */
    .hzo-form .ff-el-group.ff_list_buttons .ff-el-form-check.ff_item_selected label > span {
        background-color: var(--brand-pale) !important;
        box-shadow: 0 0 0 1.5px var(--brand) !important;
    }
}

/* Multi-select — Fluent emits .ff_has_multi_select on <select multiple>.
   Hide the chevron (only meaningful on single-select). Height left to
   render naturally — the browser sizes the box from the option count. */
.hzo-form select.ff_has_multi_select {
    background-image: none !important;
    padding-right: 16px !important;
}

/* Single-select chevron override — Fluent's .ff-default .ff-el-form-control
   (0,0,2,0) and select.ff-el-form-control:not([size]):not([multiple]) at
   (0,0,3,1) both target this element. Mine at (0,0,3,1) needs !important
   on every property to win source-order ties (Fluent's CSS loads after
   primitives.css on the engine enqueue chain). Critically: Fluent sets
   `height: var(--fluentform-input-select-height)` which collapses the
   select to a fixed height different from text inputs (which size via
   padding). `height: auto !important` restores padding-driven sizing so
   the select matches text inputs above/below. */
.hzo-form select.ff-el-form-control:not(.ff_has_multi_select) {
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    height: auto !important;
    padding: 12px 44px 12px 16px !important;
    background: #fff url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231F2937' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>") no-repeat right 16px center / 18px 18px !important;
    cursor: pointer;
}

/* ─── Choices.js (multi-select widget) ──────────────────────────────────
   Fluent enhances <select multiple> via Choices.js — replacing the native
   widget with its own div-based DOM (.choices > .choices__inner >
   .choices__list--multiple + .choices__input). Without these overrides,
   the wrapper renders with Choices.js defaults: .25rem radius, light gray
   border, and a nested .choices__input that draws its OWN border + bg —
   producing the "box within a box" effect. Style the wrapper to look
   exactly like our text inputs, and dissolve the inner input into the
   wrapper. */

/* Outer container — kill Choices' margin (we control via .ff-el-group) */
.hzo-form .choices {
    margin-bottom: 0 !important;
    font-size: 1rem;
}

/* The visible "field" surface — match .hzo-form input styling. Padding
   here mirrors `.hzo-form input` (12px 16px) with right-pad expanded to
   44px to clear the chevron. min-height 50px = 48px content + 2px border
   so single + multi selects vertically match the text inputs above/below. */
.hzo-form .choices .choices__inner {
    background: #fff !important;
    border: 1px solid var(--border) !important;
    border-radius: var(--radius-input) !important;
    padding: 12px 44px 12px 16px !important;
    min-height: 50px !important;
    font-family: var(--font-body) !important;
    font-size: 1rem !important;
    color: var(--text-body) !important;
    line-height: 1.5 !important;
    transition: border-color 0.15s, box-shadow 0.15s;
    box-sizing: border-box;
}

/* Single-select value/placeholder — Choices wraps the selected value in
   .choices__list--single > .choices__item. Strip the list's default
   inline-block padding (6px 24px 6px 12px) so .choices__inner controls
   all spacing — otherwise the value text appears double-padded. */
.hzo-form .choices[data-type*="select-one"] .choices__inner {
    padding: 12px 44px 12px 16px !important;
}

.hzo-form .choices .choices__list--single {
    padding: 0 !important;
    width: 100% !important;
    display: block !important;
}

.hzo-form .choices .choices__list--single .choices__item {
    font-family: var(--font-body) !important;
    font-size: 1rem !important;
    color: var(--text-body) !important;
    line-height: 1.5 !important;
    padding: 0 !important;
}

/* Placeholder option in single-select reads dimmer */
.hzo-form .choices .choices__list--single .choices__item--placeholder {
    color: #9ca3af !important;
    opacity: 1 !important;
}

/* Focused / open state — match our text-input focus ring */
.hzo-form .choices.is-focused .choices__inner,
.hzo-form .choices.is-open .choices__inner {
    border-color: var(--focus-ring) !important;
    box-shadow: 0 0 0 2px var(--brand-pale) !important;
}

/* When dropdown is open, Choices' default flips the wrapper border-radius
   to square at the bottom. Keep it rounded — the dropdown popup gets its
   own radius below. */
.hzo-form .choices.is-open .choices__inner {
    border-radius: var(--radius-input) !important;
}

/* The typing/search input nested inside the wrapper. Choices.js styles it
   as a separate boxed input by default (border + bg + radius) — strip
   that so it visually blends into .choices__inner. */
.hzo-form .choices .choices__input {
    background: transparent !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    margin: 0 !important;
    padding: 4px 0 !important;
    font-family: var(--font-body) !important;
    font-size: 1rem !important;
    color: var(--text-body) !important;
    width: 100% !important;
    min-width: 100px;
}

.hzo-form .choices .choices__input:focus {
    outline: none !important;
    border: none !important;
    box-shadow: none !important;
}

/* Placeholder — Choices.js renders "Select all that apply" via either
   the search input's placeholder attr or a .choices__placeholder span */
.hzo-form .choices .choices__placeholder {
    opacity: 1 !important;
    color: #9ca3af !important;
}
.hzo-form .choices .choices__input::placeholder {
    color: #9ca3af !important;
    opacity: 1 !important;
}

/* Selected items in the multi-select control — chips/tags
   Match the .ff_list_buttons selected state so multi-select chips visually
   tie back to the connected-bar style (light brand fill + brand border +
   body-text color). */
.hzo-form .choices .choices__list--multiple .choices__item {
    background: var(--brand-pale) !important;
    border: 1px solid var(--brand) !important;
    border-radius: var(--radius-pill) !important;
    color: var(--text-body) !important;
    padding: 4px 12px !important;
    font-size: 14px !important;
    font-weight: var(--fw-medium, 500) !important;
    margin: 2px 4px 2px 0 !important;
    line-height: 1.4 !important;
}

/* The "x" remove-button on each chip. Choices.js paints the X as an SVG
   background-image baked white into its core CSS — invisible against our
   light --brand-pale chip background. Override the background-image with
   a brand-colored X. No left divider; tight spacing against the chip
   label. */
.hzo-form .choices .choices__list--multiple .choices__button {
    border-left: none !important;
    margin: 0 0 0 6px !important;
    padding-left: 0 !important;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23114899' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3C/svg%3E") !important;
    background-position: center !important;
    background-repeat: no-repeat !important;
    background-size: 10px 10px !important;
    opacity: 0.7 !important;
    width: 14px !important;
    height: 14px !important;
}
.hzo-form .choices .choices__list--multiple .choices__button:hover {
    opacity: 1 !important;
}

/* Dropdown popup container */
.hzo-form .choices .choices__list--dropdown,
.hzo-form .choices .choices__list[aria-expanded] {
    background: #fff !important;
    border: 1px solid var(--border) !important;
    border-top-left-radius: var(--radius-input) !important;
    border-top-right-radius: var(--radius-input) !important;
    border-bottom-left-radius: var(--radius-input) !important;
    border-bottom-right-radius: var(--radius-input) !important;
    margin-top: 4px !important;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08) !important;
    overflow: hidden;
    z-index: 100;
}

/* Items in dropdown popup */
.hzo-form .choices .choices__list--dropdown .choices__item,
.hzo-form .choices .choices__list[aria-expanded] .choices__item {
    padding: 10px 16px !important;
    font-family: var(--font-body) !important;
    font-size: 15px !important;
    color: var(--text-body) !important;
    line-height: 1.4 !important;
}

/* Hover / keyboard-highlighted item */
.hzo-form .choices .choices__list--dropdown .choices__item--selectable.is-highlighted,
.hzo-form .choices .choices__list[aria-expanded] .choices__item--selectable.is-highlighted {
    background: var(--brand-pale) !important;
    color: var(--text-body) !important;
}

/* Selected (already-picked) item in dropdown — dimmed */
.hzo-form .choices .choices__list--dropdown .choices__item--selectable[data-select-text]::after,
.hzo-form .choices .choices__list[aria-expanded] .choices__item--selectable[data-select-text]::after {
    display: none; /* Hide Choices' "Press to select" hint — feels noisy */
}

/* Custom chevron — Choices.js paints a CSS-triangle (border hack) via
   :after on the wrapper. Replace it with our V-chevron SVG to match the
   single-select. */
.hzo-form .choices[data-type*="select-multiple"]::after,
.hzo-form .choices[data-type*="select-one"]::after {
    content: "" !important;
    border: none !important;
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231F2937' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>") no-repeat center / 18px 18px !important;
    width: 18px !important;
    height: 18px !important;
    right: 16px !important;
    top: 50% !important;
    margin-top: -9px !important;
    pointer-events: none !important;
    transition: transform 0.15s !important;
}

/* Flip chevron when dropdown is open */
.hzo-form .choices.is-open::after {
    transform: rotate(180deg) !important;
    margin-top: -9px !important;
    border: none !important;
}

/* Submit button — Fluent emits .ff-btn.ff-btn-submit.ff-btn-md.
   Match the .hzo-btn--primary visual language exactly (accent bg, pill
   radius, heading-weight typography). Override every transform / shadow /
   transition Fluent may set on this button so the hover state is a
   single bg-color change, not a double-flash from competing defaults.

   The "double hover" bug came from Fluent's own ff-btn hover styles
   (transform: translateY + box-shadow on hover) firing at the same time
   as ours but with different transition curves — visually reading as
   two animations stacking. Explicitly negate them. */
.hzo-form .ff-btn.ff-btn-submit,
.hzo-form .ff-btn.ff-btn-submit:hover,
.hzo-form .ff-btn.ff-btn-submit:focus,
.hzo-form .ff-btn.ff-btn-submit:focus-visible,
.hzo-form .ff-btn.ff-btn-submit:active {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 32px !important;
    font-family: var(--font-body) !important;
    font-size: 1rem !important;
    font-weight: var(--fw-semibold, 600) !important;
    text-decoration: none !important;
    border-radius: var(--radius-pill) !important;
    border: 1px solid var(--accent) !important;
    color: var(--text-on-accent) !important;
    cursor: pointer;
    min-height: 48px;
    line-height: 1;
    white-space: nowrap;
    margin-top: var(--space-md);
    /* Nuke every property Fluent might animate on hover that could
       cause perceived double-flash (separate transition curves for
       background-color vs background-image vs box-shadow vs transform
       all firing at once). Single uniform transition on background-color
       only, fast (120ms) so any cascade-cleanup is imperceptible. */
    box-shadow: none !important;
    transform: none !important;
    text-shadow: none !important;
    filter: none !important;
    background-image: none !important;
    /* Both bg AND border animate together at identical timing — otherwise
       border-color snaps instantly (no transition) while bg fades over 120ms,
       which the eye reads as a 1px border flash followed by a separate bg
       shift = the "double-flash" the user kept reporting. */
    transition: background-color 120ms linear, border-color 120ms linear !important;
    animation: none !important;
}

.hzo-form .ff-btn.ff-btn-submit {
    background-color: var(--accent) !important;
    opacity: 1 !important;
}

.hzo-form .ff-btn.ff-btn-submit:hover,
.hzo-form .ff-btn.ff-btn-submit:focus,
.hzo-form .ff-btn.ff-btn-submit:active {
    background-color: var(--accent-hover-on-light) !important;
    border-color: var(--accent-hover-on-light) !important;
    /* Negate `.ff-default .ff_btn_style:hover { opacity: .8 }` from
       fluentform-public-default.css. That rule fires INSTANTLY on hover
       (no transition declared by Fluent) while our background-color
       fades over 120ms — the eye reads the instant 80% dim as a first
       "flash," then the bg-color shift as a second separate event. Lock
       opacity at 1 so the only visible hover change is the smooth
       bg/border fade. Diagnosed via Claude-for-Chrome Animations panel
       trace 2026-05-29. */
    opacity: 1 !important;
}

.hzo-form .ff-btn.ff-btn-submit:focus-visible {
    outline: 3px solid var(--focus-ring) !important;
    outline-offset: 2px;
}

/* Mobile: submit becomes full-width by default (matches .hzo-btn behavior) */
@media (max-width: 767px) {
    .hzo-form .ff-btn.ff-btn-submit {
        display: flex !important;
        width: 100%;
    }
}

/* Fluent's screen-reader-only form title — hide visually (duplicates
   the page heading; only meaningful to AT users when there is no
   visible heading on the page). */
.hzo-form .ff_screen_reader_title {
    position: absolute !important;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
}

/* Validation error states — Fluent adds .error to inputs on validation
   failure and emits .text-danger for the error message text. Match the
   existing .hzo-form__input--error / .hzo-form__message--error rules. */
.hzo-form .ff-el-form-control.error {
    border-color: var(--error) !important;
    box-shadow: 0 0 0 2px var(--error-bg) !important;
}

.hzo-form .text-danger {
    color: var(--error);
    font-size: 15px;
    line-height: 1.4;
    margin-top: var(--space-sm);
    display: block;
}

/* ─── Real-time format validation feedback ──────────────────────────────
   Companion to the JS hook in `assets/js/main.js` (search for "real-time
   format validation feedback"). The JS toggles `.hzo-input-valid` on
   email + masked-phone inputs as the user types; this CSS paints the
   positive cue — green check icon outside the input, subtle green
   border. Negative state is unstyled — browser red outline on blur via
   HTML5 + Fluent's server-side error on submit handle that. */

.hzo-form .ff-el-input--content {
    position: relative;
}

.hzo-form input.hzo-input-valid {
    border-color: #2ecc71 !important;
    padding-right: 44px !important;
}

.hzo-form .ff-el-input--content:has(input.hzo-input-valid)::after {
    content: '';
    position: absolute;
    right: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 20px;
    height: 20px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232ecc71' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    pointer-events: none;
}

/* ─── Flatpickr (date/time picker popup) ────────────────────────────────
   Fluent Forms' `input_date` field renders a regular text input with the
   `.ff-el-datepicker` class. On focus, Fluent enqueues the Flatpickr
   library which paints a popup calendar (`.flatpickr-calendar`) anchored
   to the input. The closed-state input is already styled by our base
   `.hzo-form input[type="text"]` rules — this block targets the OPEN
   popup so the calendar matches our design language instead of
   Flatpickr's stock blue-on-white look.

   Library reference: github.com/flatpickr/flatpickr (class catalog
   extracted from src/style/flatpickr.styl). Loaded conditionally — these
   rules are inert on pages without a date field. */

/* Popup container — sits outside .hzo-form in the DOM (Flatpickr
   appends it to <body>), so selectors here are unscoped. Use specific
   class names to avoid bleed. */
.flatpickr-calendar {
    background: #fff !important;
    border: 1px solid var(--border) !important;
    border-radius: var(--radius-input) !important;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.10) !important;
    font-family: var(--font-body) !important;
    color: var(--text-body) !important;
    /* IMPORTANT: no padding here — Fluent's CSS sets `.fluentform * {
       box-sizing: border-box }`, so any padding on .flatpickr-calendar
       eats into the content area. Flatpickr's JS sets the calendar's
       inline width to 307.875px (set to fit its dayContainer at
       307.875px). Padding + border-box = content area shrinks to
       291.875px → dayContainer overflows by 16px → Saturday column
       clipped. Box-shadow + border-radius give the popup its visual
       chrome without padding. */
    box-sizing: content-box !important;
}

/* Month/year nav row — explicit min-height so the absolutely-positioned
   .flatpickr-current-month inside it has enough vertical content area
   to render its 38px-tall children (month <select> + year wrapper) without
   clipping. Without this min-height, Flatpickr's row content area is
   ~35px (padding 8px × 2 = 16px overhead) — too small to fit 38px boxes,
   so the boxes overflow vertically and the calendar looks broken. */
.flatpickr-months {
    background: transparent !important;
    border-bottom: 1px solid var(--border-light, var(--border)) !important;
    padding: 8px 4px !important;
    margin-bottom: 8px !important;
    min-height: 54px !important;
    box-sizing: border-box !important;
}

/* `.flatpickr-month` (singular) is the inner row that holds the prev
   arrow + the current-month container + the next arrow. Flatpickr's
   default is `height: 34px` + `overflow: hidden`. The engine bumped
   the .numInputWrapper + .flatpickr-monthDropdown-months children to
   38px tall to match the form's other dropdown chrome — but the 34px
   parent with overflow:hidden shears 4px off the bottom of the
   children, including the year input's bottom border. Raise to 38px
   to match. Diagnosed via Claude-for-Chrome DevTools session
   2026-05-29. */
.flatpickr-month {
    height: 38px !important;
}

.flatpickr-current-month {
    font-family: var(--font-body) !important;
    font-size: 14px !important;
    font-weight: var(--fw-bold, 700) !important;
    color: var(--text-heading) !important;
    /* Flex layout for predictable horizontal spacing between month
       dropdown + year input + prev/next arrows. Generous gap so
       elements have breathing room. `height: auto` overrides Flatpickr's
       core 28px height default; absolute top:0/bottom:0 still stretches
       it to fill the parent's content area, which we sized to 38px above. */
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 8px !important;
    padding: 0 8px !important;
    height: auto !important;
}

/* Month <select> + year input — Flatpickr emits a real <select> for the
   month and a numeric <input type="number"> wrapper for the year. Both
   must match the form's other dropdowns visually AND must visually align
   (same height + same bottom-edge Y).

   IMPORTANT — selector specificity:
   The base form rules `.hzo-form select` (0,0,1,1) and `.hzo-form
   input[type="number"]` (0,0,2,1) both ship `!important` declarations
   (border, padding, height). A flat `.flatpickr-monthDropdown-months`
   (0,0,1,0) loses the cascade despite `!important`, because the base
   rule's element selector tips specificity. Scope the Flatpickr rules
   under `.hzo-form` to add one class layer + reach (0,0,2,0) for the
   select and (0,0,3,0) for the year input — both win the cascade. */
.hzo-form .flatpickr-monthDropdown-months {
    font-family: var(--font-body) !important;
    font-weight: var(--fw-semibold, 600) !important;
    font-size: 14px !important;
    line-height: 1.2 !important;
    color: var(--text-heading) !important;
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    background-color: #fff !important;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231b1f23' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: right 8px center !important;
    background-size: 14px !important;
    border: 1px solid var(--border) !important;
    border-radius: var(--radius-input) !important;
    /* Explicit height + matching padding so month select bottom-aligns with
       year wrapper. Both elements: 38px box, identical inner content area. */
    height: 38px !important;
    padding: 0 30px 0 12px !important;
    margin: 0 !important;
    box-sizing: border-box !important;
    width: auto !important;
    min-width: 0 !important;
    cursor: pointer !important;
    transition: border-color 150ms ease, box-shadow 150ms ease !important;
}
.hzo-form .flatpickr-monthDropdown-months:hover {
    border-color: var(--brand) !important;
}
.hzo-form .flatpickr-monthDropdown-months:focus {
    border-color: var(--brand) !important;
    outline: none !important;
    box-shadow: 0 0 0 2px var(--brand-pale) !important;
}

/* Year input wrapper — the visible "box" the user sees for the year. All
   border/background chrome lives here; the inner <input> is transparent
   and unbordered so there are no competing visible borders. Wrapper has
   an explicit width (76px) so it visually balances the month dropdown,
   and an explicit height (38px) to bottom-align with the month select.
   `overflow: hidden` clips Flatpickr's absolutely-positioned arrow spans
   inside the rounded border. */
.hzo-form .flatpickr-current-month .numInputWrapper {
    background-color: #fff !important;
    border: 1px solid var(--border) !important;
    border-radius: var(--radius-input) !important;
    padding: 0 !important;
    margin: 0 !important;
    width: 76px !important;
    height: 38px !important;
    overflow: hidden !important;
    box-sizing: border-box !important;
    position: relative !important;
    transition: border-color 150ms ease, box-shadow 150ms ease !important;
}
.hzo-form .flatpickr-current-month .numInputWrapper:hover {
    border-color: var(--brand) !important;
}
.hzo-form .flatpickr-current-month .numInputWrapper:focus-within {
    border-color: var(--brand) !important;
    box-shadow: 0 0 0 2px var(--brand-pale) !important;
}
/* Year <input> — fills wrapper exactly; no visible border of its own (the
   `.hzo-form input[type="number"]` base rule paints one at 1px solid var
   (--border) with !important, so we negate it at higher specificity here).
   Right padding leaves room for the spinner arrows pinned to the wrapper
   right edge. */
.hzo-form .flatpickr-current-month .numInput {
    font-family: var(--font-body) !important;
    font-weight: var(--fw-semibold, 600) !important;
    font-size: 14px !important;
    line-height: 1.2 !important;
    color: var(--text-heading) !important;
    background: transparent !important;
    border: 0 !important;
    border-radius: 0 !important;
    padding: 0 22px 0 10px !important;
    margin: 0 !important;
    width: 100% !important;
    height: 100% !important;
    box-shadow: none !important;
    box-sizing: border-box !important;
    -moz-appearance: textfield !important;
    appearance: textfield !important;
}
.hzo-form .flatpickr-current-month .numInput::-webkit-outer-spin-button,
.hzo-form .flatpickr-current-month .numInput::-webkit-inner-spin-button {
    -webkit-appearance: none !important;
    margin: 0 !important;
}
.hzo-form .flatpickr-current-month .numInput:focus {
    outline: none !important;
    box-shadow: none !important;
}
/* Spinner arrows — keep inside wrapper, divide its 38px height in half */
.hzo-form .flatpickr-current-month .numInputWrapper .arrowUp,
.hzo-form .flatpickr-current-month .numInputWrapper .arrowDown {
    height: 19px !important;
    border: 0 !important;
}

/* Prev/next arrow buttons */
.flatpickr-prev-month,
.flatpickr-next-month {
    color: var(--text-body) !important;
    fill: var(--text-body) !important;
    padding: 8px !important;
    border-radius: var(--radius-input) !important;
    transition: background var(--transition-base), color var(--transition-base) !important;
}
.flatpickr-prev-month:hover,
.flatpickr-next-month:hover {
    background: var(--brand-pale) !important;
    color: var(--accent-text) !important;
    fill: var(--accent-text) !important;
}
.flatpickr-prev-month svg,
.flatpickr-next-month svg {
    fill: inherit !important;
}

/* Weekday header row (Su Mo Tu We Th Fr Sa) */
.flatpickr-weekdaycontainer .flatpickr-weekday {
    color: var(--text-muted) !important;
    font-family: var(--font-body) !important;
    font-weight: var(--fw-semibold, 600) !important;
    font-size: 13px !important;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* Day cells */
.flatpickr-day {
    color: var(--text-body) !important;
    font-family: var(--font-body) !important;
    font-size: 14px !important;
    border-radius: var(--radius-input) !important;
    border: 1px solid transparent !important;
    transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-base) !important;
}
.flatpickr-day:hover {
    background: var(--brand-pale) !important;
    color: var(--text-body) !important;
    border-color: var(--brand-pale) !important;
}
.flatpickr-day.today {
    border-color: var(--accent) !important;
    color: var(--accent-text) !important;
    background: #fff !important;
}
.flatpickr-day.today:hover {
    background: var(--brand-pale) !important;
}
.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.selected.inRange,
.flatpickr-day.startRange.inRange,
.flatpickr-day.endRange.inRange,
.flatpickr-day.selected:hover {
    background: var(--accent) !important;
    border-color: var(--accent) !important;
    color: var(--text-on-accent) !important;
}
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay {
    color: var(--text-muted) !important;
    opacity: 0.5;
}

/* Time picker section — shown when `is_time_enabled: true` */
.flatpickr-time {
    border-top: 1px solid var(--border-light, var(--border)) !important;
    padding-top: 8px !important;
    margin-top: 8px !important;
}
.flatpickr-time input,
.flatpickr-time .flatpickr-am-pm {
    color: var(--text-body) !important;
    font-family: var(--font-body) !important;
    font-size: 14px !important;
}

/* Calendar icon on the date-picker input — signals to users that clicking
   opens a calendar (without it the field looks like any other text input).
   Inline SVG (no extra HTTP request). Padding-right on the input prevents
   the icon from overlapping the user's typed text. */
.hzo-form input.ff-el-datepicker {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'/%3E%3Cline x1='16' y1='2' x2='16' y2='6'/%3E%3Cline x1='8' y1='2' x2='8' y2='6'/%3E%3Cline x1='3' y1='10' x2='21' y2='10'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: right 14px center !important;
    background-size: 18px 18px !important;
    padding-right: 44px !important;
    cursor: pointer;
}

/* Flatpickr wrapper — in static:true mode Flatpickr wraps the input
   in a .flatpickr-wrapper that defaults to `display: inline-block`,
   which shrinks both the wrapper AND the input inside it to content
   width instead of filling the form column. Force the wrapper to
   block + 100% width so the date input sits at the same full-width
   as every other input in the form. */
.hzo-form .flatpickr-wrapper {
    display: block !important;
    width: 100% !important;
    position: relative !important;
}

/* Calendar popup — let it take its natural width (~308px, set by
   Flatpickr's dayContainer to fit 7 × 39px day cells). Don't clamp
   width; don't hide overflow. The static-mode positioning places it
   under the input, and the form column is wide enough to contain
   the popup at its natural size. */

/* ─── Textarea — disable horizontal resize ──────────────────────────────
   User can drag the bottom-right corner to grow vertically (helpful for
   long messages), but horizontal resize is locked. Prevents users from
   dragging the textarea narrow + visually breaking the form layout. */
.hzo-form textarea,
.hzo-form textarea.ff-el-form-control {
    resize: vertical !important;
}
.flatpickr-time input:hover,
.flatpickr-time .flatpickr-am-pm:hover,
.flatpickr-time input:focus,
.flatpickr-time .flatpickr-am-pm:focus {
    background: var(--brand-pale) !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   MARKETING BLOCK PRIMITIVES (component library Group 3, Wave A)
   Layout / composition primitives that the blocks/ patterns compose. All
   token-driven + class-scoped; the light surfaces inherit the default text
   colors (no overrides needed).
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── Section surface variants ────────────────────────────────────────
   Formalize the previously-inline section backgrounds into modifiers:
     (light)              default .hzo-section — white (--bg-page)
     .hzo-section--pale   neutral pale gray (--bg-alt) — the standard alternator
     .hzo-section--tint   brand-tinted light surface (--brand-pale), dark text
     .hzo-section--dark   brand solid + white text (defined earlier in this file)
   Vertical rhythm comes from the base .hzo-section padding ladder.
   (Named --tint, NOT --brand: "--brand" would read as the solid brand color;
   this is a pale brand TINT. The solid brand surface is --dark.) */
.hzo-section--pale  { background: var(--bg-alt); }
.hzo-section--tint  { background: var(--brand-pale); }

/* ─── Responsive content grid — 2 / 3 / 4-up ──────────────────────────
   Mobile-first single column; expands at the QA breakpoints. Drives feature
   grids, stat rows, card rows, logo grids. */
.hzo-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-lg); }
@media (min-width: 768px) {
    .hzo-grid--2, .hzo-grid--3, .hzo-grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
    .hzo-grid--3 { grid-template-columns: repeat(3, 1fr); }
    .hzo-grid--4 { grid-template-columns: repeat(4, 1fr); }
}

/* ─── Layout primitives — Stack / Cluster / Spacer ────────────────────
   Composition utilities so client builds compose spacing instead of sprinkling
   bespoke margins. Every gap/height maps to the --space ladder — zero new
   tokens. See art-direction.md "Compose spacing, don't hand-roll margins". */

/* Stack — vertical rhythm between direct children (gap-based flex column).
   Default gap = the base step (--space-md); modifiers step the ladder. */
.hzo-stack { display: flex; flex-direction: column; gap: var(--space-md); }
.hzo-stack--xs  { gap: var(--space-xs); }
.hzo-stack--sm  { gap: var(--space-sm); }
.hzo-stack--md  { gap: var(--space-md); }
.hzo-stack--lg  { gap: var(--space-lg); }
.hzo-stack--xl  { gap: var(--space-xl); }
.hzo-stack--2xl { gap: var(--space-2xl); }
.hzo-stack--3xl { gap: var(--space-3xl); }
/* --split: fill the parent and push the last child to the bottom
   (card footers, sidebar CTAs). Use on a stack inside a flex/grid cell. */
.hzo-stack--split { flex: 1 1 auto; }
.hzo-stack--split > :last-child { margin-top: auto; }

/* Cluster — horizontal group that wraps; gap + alignment. Default gap =
   --space-sm, centered cross-axis. */
.hzo-cluster { display: flex; flex-wrap: wrap; gap: var(--space-sm); align-items: center; }
.hzo-cluster--xs  { gap: var(--space-xs); }
.hzo-cluster--sm  { gap: var(--space-sm); }
.hzo-cluster--md  { gap: var(--space-md); }
.hzo-cluster--lg  { gap: var(--space-lg); }
.hzo-cluster--xl  { gap: var(--space-xl); }
.hzo-cluster--center   { justify-content: center; }
.hzo-cluster--between  { justify-content: space-between; }
.hzo-cluster--end      { justify-content: flex-end; }
.hzo-cluster--start    { align-items: flex-start; }
.hzo-cluster--baseline { align-items: baseline; }  /* icon + text rows */

/* Spacer — explicit vertical gap for the rare case a stack doesn't fit
   (e.g. between unrelated sibling blocks not in a stack). */
.hzo-spacer { display: block; flex-shrink: 0; height: var(--space-md); }
.hzo-spacer--xs  { height: var(--space-xs); }
.hzo-spacer--sm  { height: var(--space-sm); }
.hzo-spacer--md  { height: var(--space-md); }
.hzo-spacer--lg  { height: var(--space-lg); }
.hzo-spacer--xl  { height: var(--space-xl); }
.hzo-spacer--2xl { height: var(--space-2xl); }
.hzo-spacer--3xl { height: var(--space-3xl); }

/* ─── Hero ────────────────────────────────────────────────────────────
   Top-of-page composition; compose inside a .hzo-section (which supplies the
   vertical rhythm). These add the layout + the actions row. */
.hzo-hero__actions { display: flex; gap: var(--space-md); flex-wrap: wrap; margin-top: var(--space-lg); }
.hzo-hero--centered { text-align: center; }
.hzo-hero--centered .hzo-display,
.hzo-hero--centered .hzo-subtitle { margin-left: auto; margin-right: auto; }
.hzo-hero--centered .hzo-hero__actions { justify-content: center; }
/* Split — copy + media side by side on desktop, stacked on mobile. */
.hzo-hero--split { display: grid; grid-template-columns: 1fr; gap: var(--space-xl); align-items: center; }
@media (min-width: 1024px) { .hzo-hero--split { grid-template-columns: 1fr 1fr; gap: var(--space-3xl); } }
.hzo-hero__media img { width: 100%; height: auto; display: block; border-radius: var(--radius-card); }
/* Image-background — author sets background-image inline (per-page photo). A
   brand-deep scrim keeps the light text readable over any image. */
.hzo-hero--image {
    position: relative;
    background-size: cover;
    background-position: center;
    color: #fff;
}
.hzo-hero--image::before {
    content: "";
    position: absolute;
    inset: 0;
    background: color-mix(in srgb, var(--brand-deep) 60%, transparent);
}
.hzo-hero--image > * { position: relative; } /* lift content above the scrim */
.hzo-hero--image .hzo-display,
.hzo-hero--image .hzo-eyebrow { color: #fff !important; }
.hzo-hero--image .hzo-subtitle { color: rgba(255, 255, 255, 0.9); }

/* ─── Image / overlay band ────────────────────────────────────────────
   Generalizes the hero --image treatment to ANY .hzo-section: a full-bleed
   background photo + brand-deep scrim, with light text (like --dark). Set the
   section's background-image inline; the scrim keeps text readable over any
   photo. Tune scrim strength with --hzo-section-scrim (default 60%) — e.g.
   style="--hzo-section-scrim:40%" for a lighter wash. */
.hzo-section--image {
    position: relative;
    background-size: cover;
    background-position: center;
    color: #fff;
}
.hzo-section--image::before {
    content: "";
    position: absolute;
    inset: 0;
    background: color-mix(in srgb, var(--brand-deep) var(--hzo-section-scrim, 60%), transparent);
}
.hzo-section--image > * { position: relative; } /* lift content above the scrim */
.hzo-section--image h1, .hzo-section--image h2, .hzo-section--image h3,
.hzo-section--image h4, .hzo-section--image h5, .hzo-section--image h6,
.hzo-section--image .hzo-eyebrow, .hzo-section--image .hzo-display { color: #fff !important; }
.hzo-section--image p, .hzo-section--image .hzo-subtitle { color: rgba(255, 255, 255, 0.9); }
.hzo-section--image a:not(.hzo-btn) { color: #fff; }

/* ─── Before / after compare slider ───────────────────────────────────
   Two stacked images; drag the handle (or use the keyboard — the control is a
   native range input, so keyboard + click + drag all work for free) to wipe
   between "before" and "after". Built for transformations (yards, remodels,
   restorations). main.js maps the range value to --hzo-compare-pos.
   Markup: blocks/compare.html. */
.hzo-compare {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-card);
    aspect-ratio: 16 / 9;
    --hzo-compare-pos: 50%;
    user-select: none;
}
.hzo-compare__img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    -webkit-user-drag: none;
}
/* The "before" image sits on top, clipped from the right to --hzo-compare-pos,
   so the left portion shows "before" and the right reveals the "after" beneath. */
.hzo-compare__img--before {
    clip-path: inset(0 calc(100% - var(--hzo-compare-pos)) 0 0);
}
.hzo-compare__divider {
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--hzo-compare-pos);
    width: 2px;
    margin-left: -1px;
    background: #fff;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15);
    pointer-events: none;
}
.hzo-compare__divider::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 42px;
    height: 42px;
    transform: translate(-50%, -50%);
    border: 2px solid #fff;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--brand) 80%, transparent);
    box-shadow: var(--shadow-md);
}
/* The accessible control: a real range input overlaying the whole image. */
.hzo-compare__range {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: ew-resize;
}
.hzo-compare__range:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 3px; }
.hzo-compare__label {
    position: absolute;
    bottom: var(--space-md);
    padding: 4px 12px;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--brand-deep) 72%, transparent);
    color: #fff;
    font-size: 0.8125rem;
    font-weight: var(--fw-medium, 500);
    pointer-events: none;
}
.hzo-compare__label--before { left: var(--space-md); }
.hzo-compare__label--after  { right: var(--space-md); }

/* ─── Stat ────────────────────────────────────────────────────────────
   Centers a .hzo-stat-number + .hzo-stat-label pair within a grid cell. */
.hzo-stat { text-align: center; }

/* ─── Logo / brand strip ──────────────────────────────────────────────
   Centered, wrapping row of partner/brand logos. Muted + monochrome at rest,
   full color on hover (honors prefers-reduced-motion). */
.hzo-logo-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--space-xl);
}
.hzo-logo-strip img {
    height: 36px;
    width: auto;
    opacity: 0.6;
    filter: grayscale(1);
    transition: opacity var(--transition-base), filter var(--transition-base);
}
.hzo-logo-strip a:hover img,
.hzo-logo-strip img:hover { opacity: 1; filter: grayscale(0); }
@media (prefers-reduced-motion: reduce) {
    .hzo-logo-strip img { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   CONTENT BLOCK PRIMITIVES (component library Group 3, Wave B)
   Composition helpers for testimonial / bio / pricing / post-card / feature
   rows. Token-driven, class-scoped, no new tokens.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── Testimonial author row ──────────────────────────────────────────
   Avatar + name/role under a quote. The quote uses .hzo-pullquote (single
   featured) or plain card text (multi-up cards). */
.hzo-testimonial__author { display: flex; align-items: center; gap: var(--space-md); margin-top: var(--space-md); }
.hzo-testimonial__name { font-family: var(--font-body); font-weight: var(--fw-semibold, 600); color: var(--text-heading); line-height: 1.3; }
.hzo-testimonial__role { font-family: var(--font-body); font-size: 14px; color: var(--text-muted); line-height: 1.3; }

/* ─── Bio / team card ─────────────────────────────────────────────────
   Centered card content (avatar on top). Composes .hzo-card + .hzo-avatar;
   name reuses .hzo-card__title, role reuses .hzo-meta. */
.hzo-bio { text-align: center; align-items: center; }
.hzo-bio .hzo-social-icons,
.hzo-bio .hzo-footer-social { justify-content: center; }

/* ─── Pricing ─────────────────────────────────────────────────────────
   Composes .hzo-card + .hzo-btn; the price reuses .hzo-stat-number. Only the
   feature checklist + the featured-tier emphasis are new. */
.hzo-pricing__features { list-style: none; margin: var(--space-md) 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-sm); }
.hzo-pricing__features li { display: flex; align-items: flex-start; gap: var(--space-sm); color: var(--text-body); line-height: 1.5; }
.hzo-pricing__features li > svg { flex-shrink: 0; width: 18px; height: 18px; color: var(--accent-text); margin-top: 2px; }
/* Featured tier — brand emphasis via border + lift (no new tokens). Scoped as
   .hzo-card.hzo-pricing--featured (0,0,2,0) so it outranks .hzo-card's border
   (0,0,1,0) regardless of source order — not a source-position tiebreak. */
.hzo-card.hzo-pricing--featured { border-color: var(--brand); box-shadow: var(--shadow-md); }

/* ─── Card media (post / blog cards) ──────────────────────────────────
   Full-bleed image at the top of a .hzo-card — negative margins cancel the
   card's padding so the image meets the inner edges; top corners stay rounded. */
.hzo-card__media {
    margin: calc(-1 * var(--space-lg)) calc(-1 * var(--space-lg)) 0;
    border-radius: var(--radius-card) var(--radius-card) 0 0;
    overflow: hidden;
    aspect-ratio: 16 / 9;
}
.hzo-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform var(--transition-base); }
/* Alternate media ratios (default is 16/9 above). */
.hzo-card__media--square { aspect-ratio: 1 / 1; }
.hzo-card__media--wide   { aspect-ratio: 21 / 9; }
/* Subtle image zoom on hover for clickable cards (reduced-motion-safe). */
.hzo-card:has(a):hover .hzo-card__media img { transform: scale(1.05); }
@media (prefers-reduced-motion: reduce) {
    .hzo-card:has(a):hover .hzo-card__media img { transform: none; }
}

/* ─── Card variants (extend .hzo-card; compose its subparts) ──────────
   Depth choice per art-direction §5 "flat-with-intent": --bordered = flat +
   border (the system default, made explicit); --elevated = shadow, no border.
   Zero new tokens — bordered uses --border, elevated uses --shadow-md. */
.hzo-card--bordered { box-shadow: none; border-color: var(--border); }
.hzo-card--elevated { box-shadow: var(--shadow-md); border-color: transparent; }

/* Body wrapper — groups title/text/CTA, mainly for the horizontal layout. */
.hzo-card__body { display: flex; flex-direction: column; gap: var(--space-sm); min-width: 0; }

/* Horizontal card — media beside body; stacks to vertical at the mobile
   breakpoint (767px, the system's mobile boundary). Reuses __media/__body. */
.hzo-card--horizontal { flex-direction: row; align-items: stretch; gap: var(--space-lg); }
.hzo-card--horizontal > .hzo-card__media {
    flex: 0 0 40%;
    aspect-ratio: auto;          /* fill the card height instead of forcing 16/9 */
    margin: calc(-1 * var(--space-lg)) 0 calc(-1 * var(--space-lg)) calc(-1 * var(--space-lg));
    border-radius: var(--radius-card) 0 0 var(--radius-card);
}
.hzo-card--horizontal > .hzo-card__body { flex: 1 1 auto; }
@media (max-width: 767px) {
    .hzo-card--horizontal { flex-direction: column; gap: var(--space-md); }
    .hzo-card--horizontal > .hzo-card__media {
        flex-basis: auto;
        aspect-ratio: 16 / 9;
        margin: calc(-1 * var(--space-lg)) calc(-1 * var(--space-lg)) 0;
        border-radius: var(--radius-card) var(--radius-card) 0 0;
    }
}

/* Link card — the WHOLE card is one clickable target (accessible stretched-link:
   a real anchor on the title, ::after covers the card). The card must contain
   exactly ONE interactive element (the title link). Hover lift comes from the
   base .hzo-card:has(a):hover rule; the focus ring shows for keyboard only. */
.hzo-card--link { position: relative; }
.hzo-card--link .hzo-card__title a { color: inherit; text-decoration: none; }
.hzo-card--link .hzo-card__title a::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.hzo-card--link:has(.hzo-card__title a:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/* ─── Icon sizing scale ────────────────────────────────────────────────
   One icon family per site (art-direction §3) — this governs SIZE only, never
   family mixing. Icons inherit text color (currentColor) and track font-size via
   em, so an icon beside text scales + aligns with that text by default. Zero new
   tokens. a11y: decorative => aria-hidden="true"; meaningful => role="img" +
   aria-label. Wrap an inline SVG: <span class="hzo-icon hzo-icon--lg">…svg…</span>. */
.hzo-icon {
    display: inline-flex;
    flex-shrink: 0;
    width: 1em;
    height: 1em;
    vertical-align: -0.125em;   /* sit on the adjacent text baseline */
    line-height: 1;
}
.hzo-icon > svg { width: 100%; height: 100%; display: block; fill: none; stroke: currentColor; }
.hzo-icon--filled > svg { fill: currentColor; stroke: none; }  /* solid (non-stroke) icons */
.hzo-icon--xs { font-size: 0.75em; }
.hzo-icon--sm { font-size: 0.875em; }
.hzo-icon--md { font-size: 1em; }      /* default */
.hzo-icon--lg { font-size: 1.5em; }
.hzo-icon--xl { font-size: 2em; }

/* ─── Feature split — alternating image/copy content rows ─────────────
   Distinct from .hzo-hero--split: a repeatable content row. --reverse swaps
   the column order on desktop for alternating rhythm. Stacks on mobile. */
.hzo-feature { display: grid; grid-template-columns: 1fr; gap: var(--space-xl); align-items: center; }
@media (min-width: 1024px) {
    .hzo-feature { grid-template-columns: 1fr 1fr; gap: var(--space-3xl); }
    .hzo-feature--reverse .hzo-feature__media { order: 2; }
}
.hzo-feature__media img { width: 100%; height: auto; display: block; border-radius: var(--radius-card); }

/* ─── Empty state ─────────────────────────────────────────────────────
   Zero-state for no search results, an empty cart, or no posts/orders.
   Centered icon + headline (markup uses .hzo-visual-h3) + one-line
   explanation + a primary action (and optional secondary links). Composes
   .hzo-btn for the action; no new tokens. */
.hzo-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-sm);
    max-width: 480px;
    margin-inline: auto;
    padding: var(--space-2xl) 0;
}
.hzo-empty__icon {
    width: 64px;
    height: 64px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--brand);
    background: var(--brand-pale);
    border-radius: var(--radius-pill);
    margin-bottom: var(--space-sm);
}
.hzo-empty__icon svg { width: 32px; height: 32px; }
.hzo-empty__text { color: var(--text-muted); line-height: 1.5; margin: 0; max-width: 40ch; }
.hzo-empty__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-sm); margin-top: var(--space-md); }

/* ═══════════════════════════════════════════════════════════════════════
   STATIC BLOCK PRIMITIVES (component library Wave D) — CSS-only, no JS,
   no new tokens.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── Rating (static stars) ───────────────────────────────────────────
   Read-only star row for trust / review contexts. Filled stars reuse
   --color-warning (the engine's amber — there is no dedicated star token);
   empty stars use --border. Author renders N filled + (5−N) empty star SVGs,
   optional count after. For AT, put role="img" + aria-label="Rated 4.8 out of
   5" on the .hzo-rating container and aria-hidden on the SVGs. */
.hzo-rating { display: inline-flex; align-items: center; gap: 2px; }
.hzo-rating svg { width: 18px; height: 18px; flex-shrink: 0; }
.hzo-rating__star { color: var(--color-warning); }
.hzo-rating__star--empty { color: var(--border); }
.hzo-rating__count { margin-left: var(--space-sm); font-size: 14px; color: var(--text-muted); }

/* ─── Pagination ──────────────────────────────────────────────────────
   Archive / search page nav. 44px tap targets; current page brand-filled;
   disabled prev/next muted + non-interactive. !important on color fights
   per-client a:visited (matching :visited rule below). */
.hzo-pagination { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--space-sm); list-style: none; margin: var(--space-xl) 0 0; padding: 0; }
.hzo-pagination__link {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 44px; min-height: 44px; padding: 0 12px;
    font-family: var(--font-body); font-weight: var(--fw-semibold, 600); font-size: 15px;
    color: var(--brand-text) !important; text-decoration: none;
    border: 1px solid var(--border); border-radius: var(--radius-input);
    transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-base);
}
.hzo-pagination__link:hover { background: var(--brand-pale); border-color: var(--brand); color: var(--brand-text) !important; }
.hzo-pagination__link:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.hzo-pagination__link.is-current { background: var(--brand) !important; border-color: var(--brand); color: var(--text-on-brand) !important; pointer-events: none; }
.hzo-pagination__link.is-disabled,
.hzo-pagination__link[aria-disabled="true"] { color: var(--text-muted) !important; pointer-events: none; opacity: 0.6; }
.hzo-pagination__link:visited { color: var(--brand-text) !important; }

/* ─── Category card (a .hzo-card variant) ─────────────────────────────
   Shop-by-category / locations-index tile: media on top, centered name +
   count. Usually a whole-card link — the <a> form gets its own hover lift
   (the base .hzo-card :has(a) lift doesn't apply when the card IS the link). */
.hzo-cat-card { text-align: center; align-items: center; }
.hzo-cat-card .hzo-card__title { margin: 0; }
.hzo-cat-card__count { font-size: 14px; color: var(--text-muted); margin: 0; }
a.hzo-cat-card,
a.hzo-cat-card:visited { text-decoration: none; color: inherit; }
a.hzo-cat-card:hover { box-shadow: var(--shadow-md); }
a.hzo-cat-card:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/* ─── Gallery (static grid; lightbox is Wave E / JS) ──────────────────
   Responsive image grid (2/3/4-up), tiles cropped square via aspect-ratio,
   tighter gap than the content .hzo-grid. No lightbox yet — wrap tiles in
   <a href> to the full image until the JS lightbox ships. */
.hzo-gallery { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-sm); }
@media (min-width: 768px)  { .hzo-gallery { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .hzo-gallery { grid-template-columns: repeat(4, 1fr); } }
.hzo-gallery__item { display: block; overflow: hidden; border-radius: var(--radius-input); aspect-ratio: 1 / 1; background: var(--bg-alt); }
.hzo-gallery__item img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform var(--transition-base); }
a.hzo-gallery__item:hover img { transform: scale(1.05); }
@media (prefers-reduced-motion: reduce) {
    .hzo-gallery__item img { transition: none; }
    a.hzo-gallery__item:hover img { transform: none; }
}

/* ─── Modal / dialog ──────────────────────────────────────────────────
   A backdrop (.hzo-modal) centers a panel (.hzo-modal__dialog, which carries
   role="dialog" + aria-modal="true"). Closed = opacity:0; visibility:hidden, so
   the panel's controls are non-focusable and click-inert until opened; the
   .is-open class reveals it (200ms fade + rise, reduced-motion-bounded). Focus
   trap, background inert, Esc/backdrop close, and focus-return live in the modal
   IIFE in main.js (built on hzo.trapFocus). Modals are portaled to <body> on
   init so ancestor overflow/transform/z-index can't clip or mis-stack them. */
.hzo-modal {
    position: fixed;
    inset: 0;
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-lg);
    background: rgba(0, 0, 0, 0.5);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--transition-base) ease, visibility var(--transition-base);
}
.hzo-modal.is-open { opacity: 1; visibility: visible; }

.hzo-modal__dialog {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 520px;
    max-height: calc(100vh - var(--space-2xl));
    overflow-y: auto;
    background: #fff;
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-lg);
    transform: translateY(12px);
    transition: transform var(--transition-base) ease;
}
.hzo-modal.is-open .hzo-modal__dialog { transform: none; }
.hzo-modal__dialog--sm { max-width: 400px; }
.hzo-modal__dialog--lg { max-width: 760px; }

.hzo-modal__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-md);
    padding: var(--space-lg) var(--space-lg) 0;
}
.hzo-modal__title {
    margin: 0;
    font-family: var(--font-heading);
    font-size: 22px;
    line-height: 1.3;
    color: var(--text-heading);
}
.hzo-modal__close {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin: -10px -10px 0 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-muted);
    border-radius: var(--radius-input);
    cursor: pointer;
    transition: background var(--transition-base) ease, color var(--transition-base) ease;
}
.hzo-modal__close:hover { background: var(--bg-alt); color: var(--text-heading); }

.hzo-modal__body {
    padding: var(--space-md) var(--space-lg) var(--space-lg);
    color: var(--text-body);
}
.hzo-modal__body > :first-child { margin-top: 0; }
.hzo-modal__body > :last-child { margin-bottom: 0; }

.hzo-modal__footer {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--space-sm);
    padding: 0 var(--space-lg) var(--space-lg);
}

/* Lock background scroll while any overlay (modal/drawer) is open — set by the
   shared overlay lock in main.js (hzo.lockOverlayBackground). */
body.hzo-overlay-open { overflow: hidden; }

/* Phone: dock as a bottom sheet with full-width stacked actions. */
@media (max-width: 480px) {
    .hzo-modal { padding: 0; align-items: flex-end; }
    .hzo-modal__dialog,
    .hzo-modal__dialog--sm,
    .hzo-modal__dialog--lg {
        max-width: none;
        max-height: 92vh;
        border-radius: var(--radius-card) var(--radius-card) 0 0;
    }
    .hzo-modal__footer .hzo-btn { flex: 1 1 auto; }
}

@media (prefers-reduced-motion: reduce) {
    .hzo-modal,
    .hzo-modal__dialog,
    .hzo-modal__close { transition: none; }
    .hzo-modal__dialog { transform: none; }
}

/* ─── Drawer / off-canvas ──────────────────────────────────────────────
   Edge-anchored side panel (filters, mini-cart, secondary nav). Shares the
   modal's overlay MECHANICS — focus trap, the shared background inert + scroll
   lock, Esc / backdrop / close-button dismiss, focus return (drawer IIFE in
   main.js, built on hzo.trapFocus) — but NOT its layout: it stays a side panel
   at EVERY width. Phones cap the width but keep the side anchor; it never
   becomes a bottom sheet (that's the modal). Default slides from the right;
   --left slides from the left. Portaled to <body> on init. */
.hzo-drawer {
    position: fixed;
    inset: 0;
    z-index: var(--z-drawer);
    display: flex;
    justify-content: flex-end;
    background: rgba(0, 0, 0, 0.5);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--transition-base) ease, visibility var(--transition-base);
}
.hzo-drawer--left { justify-content: flex-start; }
.hzo-drawer.is-open { opacity: 1; visibility: visible; }

.hzo-drawer__panel {
    position: relative;
    display: flex;
    flex-direction: column;
    width: min(85vw, 360px);
    max-width: 100%;
    height: 100%;
    background: #fff;
    box-shadow: var(--shadow-lg);
    overflow-y: auto;
    transform: translateX(100%);
    transition: transform var(--transition-base) ease;
}
.hzo-drawer--left .hzo-drawer__panel { transform: translateX(-100%); }
.hzo-drawer.is-open .hzo-drawer__panel { transform: none; }
.hzo-drawer__panel--wide { width: min(92vw, 480px); }

.hzo-drawer__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    padding: var(--space-lg);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.hzo-drawer__title {
    margin: 0;
    font-family: var(--font-heading);
    font-size: 20px;
    line-height: 1.3;
    color: var(--text-heading);
}
.hzo-drawer__close {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin: -10px -10px -10px 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-muted);
    border-radius: var(--radius-input);
    cursor: pointer;
    transition: background var(--transition-base) ease, color var(--transition-base) ease;
}
.hzo-drawer__close:hover { background: var(--bg-alt); color: var(--text-heading); }

.hzo-drawer__body {
    flex: 1 1 auto;
    padding: var(--space-lg);
    color: var(--text-body);
}
.hzo-drawer__body > :first-child { margin-top: 0; }
.hzo-drawer__body > :last-child { margin-bottom: 0; }

.hzo-drawer__footer {
    flex-shrink: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    padding: var(--space-lg);
    border-top: 1px solid var(--border);
}

@media (prefers-reduced-motion: reduce) {
    .hzo-drawer,
    .hzo-drawer__panel,
    .hzo-drawer__close { transition: none; }
}

/* ─── Mini-cart ────────────────────────────────────────────────────────
   A .hzo-drawer COMPOSITION (it is a drawer — all open/close/trap/lock/Esc/
   focus-return machinery is reused). Only the line-item layout + totals are new
   here. Empty state reuses .hzo-empty; remove reuses the tag-removal focus-move
   pattern (in main.js). Zero new tokens. Contract: component-patterns §46. */
.hzo-minicart__items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-lg); }
.hzo-minicart__item {
    display: grid;
    grid-template-columns: 56px 1fr auto;
    gap: var(--space-md);
    align-items: start;
}
.hzo-minicart__thumb {
    width: 56px;
    height: 56px;
    border-radius: var(--radius-input);
    overflow: hidden;
    background: var(--bg-alt);
    flex-shrink: 0;
}
.hzo-minicart__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hzo-minicart__info { min-width: 0; display: flex; flex-direction: column; gap: var(--space-sm); }
.hzo-minicart__title { margin: 0; font-size: 14px; font-weight: 600; color: var(--text-heading); line-height: 1.3; }
.hzo-minicart__qty {
    display: inline-flex;
    align-items: center;
    width: max-content;
    border: 1px solid var(--border);
    border-radius: var(--radius-input);
}
.hzo-minicart__step {
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    color: var(--text-body);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
}
.hzo-minicart__step:hover { color: var(--brand); }
.hzo-minicart__step:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.hzo-minicart__count { min-width: 30px; text-align: center; font-size: 14px; font-variant-numeric: tabular-nums; }
.hzo-minicart__line { display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-sm); }
.hzo-minicart__linetotal { font-size: 14px; font-weight: 600; color: var(--text-heading); font-variant-numeric: tabular-nums; }
.hzo-minicart__remove {
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-muted);
    border-radius: 50%;
    cursor: pointer;
    transition: background var(--transition-base) ease, color var(--transition-base) ease;
}
.hzo-minicart__remove:hover { background: var(--bg-alt); color: var(--text-heading); }
.hzo-minicart__remove:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.hzo-minicart__remove > svg { width: 14px; height: 14px; display: block; }
/* Footer overrides the drawer's row footer → stacked subtotal + full-width CTA. */
.hzo-minicart__footer { flex-direction: column; align-items: stretch; gap: var(--space-md); }
.hzo-minicart__subtotal { display: flex; justify-content: space-between; align-items: baseline; font-size: 15px; color: var(--text-body); }
.hzo-minicart__subtotal-value { font-size: 18px; font-weight: 700; color: var(--text-heading); font-family: var(--font-number); }
/* These elements set display: flex, which would beat the UA [hidden] rule — restore
   it so the JS empty/footer/list toggles actually hide (specificity 0,0,2,0 > 0,0,1,0). */
.hzo-minicart__items[hidden],
.hzo-minicart__empty[hidden],
.hzo-minicart__footer[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { .hzo-minicart__remove { transition: none; } }

/* ─── Toast / snackbar ─────────────────────────────────────────────────
   Transient status messages (form success, add-to-cart, errors). NOT an
   overlay: no focus trap, no background inert — it must NEVER steal focus.
   Announced via an aria-live region (polite default; assertive for errors).
   Created + managed by hzo.toast() in main.js. Reuses the alert status colours;
   zero new tokens. The empty region is click-through; toasts re-enable pointer
   events so their dismiss button works. */
.hzo-toast-region {
    position: fixed;
    z-index: var(--z-toast);
    right: var(--space-lg);
    bottom: var(--space-lg);
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    width: min(92vw, 380px);
    pointer-events: none;
}
/* Assertive region sits just above the polite one so they don't overlap. */
.hzo-toast-region--assertive { bottom: auto; top: var(--space-lg); }
@media (max-width: 480px) {
    .hzo-toast-region {
        left: var(--space-md);
        right: var(--space-md);
        bottom: var(--space-md);
        width: auto;
    }
    .hzo-toast-region--assertive { top: var(--space-md); bottom: auto; }
}

.hzo-toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: var(--space-md);
    background: #fff;
    border-left: 4px solid var(--text-muted);
    border-radius: var(--radius-input);
    box-shadow: var(--shadow-lg);
    font-size: 15px;
    line-height: 1.5;
    color: var(--text-body);
    opacity: 0;
    transform: translateY(10px);
    transition: opacity var(--transition-base) ease, transform var(--transition-base) ease;
}
.hzo-toast.is-visible { opacity: 1; transform: none; }
.hzo-toast--success { border-left-color: var(--success); }
.hzo-toast--warning { border-left-color: var(--color-warning); }
.hzo-toast--error   { border-left-color: var(--error); }
.hzo-toast--info    { border-left-color: var(--color-info); }
.hzo-toast__message { flex: 1 1 auto; min-width: 0; }
.hzo-toast__close {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    margin: -2px -2px 0 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-muted);
    border-radius: 50%;
    cursor: pointer;
    transition: background var(--transition-base) ease, color var(--transition-base) ease;
}
.hzo-toast__close:hover { background: var(--bg-alt); color: var(--text-heading); }
.hzo-toast__close:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.hzo-toast__close > svg { width: 14px; height: 14px; display: block; }

@media (prefers-reduced-motion: reduce) {
    .hzo-toast { transition: none; }
}

/* ─── Dropdown / menu ──────────────────────────────────────────────────
   Menu-button popup (account menu, nav dropdown, row actions). A transient
   popup, NOT an overlay — no focus trap, no background inert. The menu-button
   IIFE in main.js manages aria-expanded, roving arrow-key focus, Esc +
   click-outside close, and focus return. Markup contract: component-patterns
   §35. Anchored to the trigger; --right aligns the menu to the trigger's right
   edge. Reuses existing tokens; zero new tokens. */
.hzo-dropdown { position: relative; display: inline-block; }
.hzo-dropdown__menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: var(--z-popover);
    min-width: 200px;
    margin: 0;
    padding: 6px;
    list-style: none;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity var(--transition-base) ease, transform var(--transition-base) ease, visibility var(--transition-base);
}
.hzo-dropdown__menu--right { left: auto; right: 0; }
.hzo-dropdown.is-open .hzo-dropdown__menu { opacity: 1; visibility: visible; transform: none; }

.hzo-dropdown__item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 12px;
    border: 0;
    border-radius: var(--radius-input);
    background: transparent;
    font-family: var(--font-body);
    font-size: 14px;
    line-height: 1.3;
    color: var(--text-body) !important;   /* fights a:visited when authored as <a> */
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--transition-base) ease, color var(--transition-base) ease;
}
.hzo-dropdown__item:hover,
.hzo-dropdown__item:focus {
    background: var(--bg-alt);
    color: var(--text-heading) !important;
    outline: none;
}
.hzo-dropdown__item:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.hzo-dropdown__item[aria-disabled="true"] { color: var(--text-muted) !important; cursor: default; }
.hzo-dropdown__item[aria-disabled="true"]:hover { background: transparent; }
.hzo-dropdown__sep { height: 1px; margin: 6px 4px; background: var(--border); }

@media (prefers-reduced-motion: reduce) {
    .hzo-dropdown__menu { transition: none; }
}

/* ─── Tooltip ──────────────────────────────────────────────────────────
   Short text hint, shown on hover/focus (toggled by main.js). Dark surface
   (--text-heading) + white text. Default above the trigger; --bottom flips
   below when the edge-flip positioner detects top clipping. Never interactive
   (pointer-events:none) — that's a popover. Reuses existing tokens. */
.hzo-tooltip-wrap { position: relative; display: inline-flex; }
.hzo-tooltip {
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
    z-index: var(--z-popover);
    width: max-content;
    max-width: 240px;
    padding: 6px 10px;
    background: var(--text-heading);
    color: #fff;
    border-radius: var(--radius-input);
    font-size: 13px;
    line-height: 1.4;
    pointer-events: none;
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--transition-base) ease, visibility var(--transition-base);
}
.hzo-tooltip.is-open { opacity: 1; visibility: visible; }
.hzo-tooltip--bottom { bottom: auto; top: calc(100% + 8px); }
@media (prefers-reduced-motion: reduce) { .hzo-tooltip { transition: none; } }

/* ─── Popover ──────────────────────────────────────────────────────────
   A richer dropdown surface (interactive content allowed). Anchored below the
   trigger by default; --right right-aligns; --flip places it above when the
   edge-flip positioner detects bottom clipping. Managed by main.js (open/close,
   Esc, click-outside, focus return). Reuses existing tokens. */
.hzo-popover { position: relative; display: inline-block; }
.hzo-popover__panel {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    z-index: var(--z-popover);
    min-width: 220px;
    max-width: 320px;
    padding: var(--space-md);
    background: #fff;
    border: 1px solid var(--border);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity var(--transition-base) ease, transform var(--transition-base) ease, visibility var(--transition-base);
}
.hzo-popover__panel--right { left: auto; right: 0; }
.hzo-popover.is-open .hzo-popover__panel { opacity: 1; visibility: visible; transform: none; }
.hzo-popover__panel--flip { top: auto; bottom: calc(100% + 8px); }
@media (prefers-reduced-motion: reduce) { .hzo-popover__panel { transition: none; } }

/* ─── Top banner / promo bar ───────────────────────────────────────────
   Full-width announcement strip. Reuses brand/accent/section-surface tokens.
   Dismissed in-session via [data-hzo-banner-dismiss] (main.js) — NO browser
   storage; collapses height + opacity (no layout jank), reduced-motion-bounded.
   Static markup needs no aria-live; if inserted dynamically use aria-live=polite. */
.hzo-banner {
    overflow: hidden;
    background: var(--brand);
    color: var(--text-on-brand);
    transition: height var(--transition-base) ease, opacity var(--transition-base) ease;
}
.hzo-banner--accent { background: var(--accent); color: var(--text-on-accent); }
.hzo-banner--pale   { background: var(--bg-alt); color: var(--text-body); }
.hzo-banner__inner {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding-top: 10px;
    padding-bottom: 10px;
}
.hzo-banner__text { flex: 1; margin: 0; text-align: center; font-size: 14px; line-height: 1.4; }
.hzo-banner a { color: inherit; text-decoration: underline; }
.hzo-banner__close {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    border-radius: var(--radius-pill);
    cursor: pointer;
    transition: background var(--transition-base) ease;
}
.hzo-banner__close:hover { background: color-mix(in srgb, currentColor 15%, transparent); }
.hzo-banner__close:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.hzo-banner__close > svg { width: 16px; height: 16px; display: block; }
.hzo-banner.is-dismissing { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .hzo-banner { transition: none; } }

/* ─── Carousel ─────────────────────────────────────────────────────────
   Core accessible carousel (one slide per view): prev/next + arrow keys,
   aria-roledescription, per-slide labels, inactive slides inert. Optional
   opt-in autoplay (data-hzo-carousel-autoplay) pauses on hover/focus and is
   disabled under reduced-motion; it needs a [data-hzo-carousel-toggle] pause
   button (WCAG 2.2.2). Touch-swipe, infinite-loop (manual), and dot indicators
   are deferred to Wave E.1. Wired by the carousel IIFE in main.js. Markup
   contract: component-patterns §38. Reuses existing tokens; zero new tokens. */
.hzo-carousel { position: relative; }
.hzo-carousel__viewport { overflow: hidden; touch-action: pan-y; }  /* swipe horiz, keep vertical page scroll */
.hzo-carousel__track {
    display: flex;
    transition: transform var(--transition-base) ease;
}
.hzo-carousel__slide { flex: 0 0 100%; min-width: 0; }

.hzo-carousel__btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 0;
    border-radius: var(--radius-pill);
    background: #fff;
    color: var(--text-heading);
    box-shadow: var(--shadow-md);
    cursor: pointer;
    z-index: 1;
    transition: background var(--transition-base) ease;
}
.hzo-carousel__btn:hover { background: var(--bg-alt); }
.hzo-carousel__btn:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.hzo-carousel__btn--prev { left: 8px; }
.hzo-carousel__btn--next { right: 8px; }
.hzo-carousel__btn[disabled] { opacity: 0.4; cursor: default; box-shadow: var(--shadow-sm); }
.hzo-carousel__btn > svg { width: 22px; height: 22px; display: block; }

.hzo-carousel__toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: var(--space-md);
    padding: 6px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: #fff;
    color: var(--text-body);
    font-size: 13px;
    cursor: pointer;
}
.hzo-carousel__toggle:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/* Dot indicators (generated by the carousel IIFE). 24px hit area, 10px visual dot. */
.hzo-carousel__dots { display: flex; justify-content: center; gap: 4px; margin-top: var(--space-md); }
.hzo-carousel__dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
}
.hzo-carousel__dot::before {
    content: "";
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--border);
    transition: background var(--transition-base) ease, transform var(--transition-base) ease;
}
.hzo-carousel__dot[aria-current="true"]::before { background: var(--brand); transform: scale(1.3); }
.hzo-carousel__dot:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; border-radius: 50%; }

@media (prefers-reduced-motion: reduce) {
    .hzo-carousel__track,
    .hzo-carousel__btn,
    .hzo-carousel__dot::before { transition: none; }
}

/* ─── Gallery lightbox ─────────────────────────────────────────────────
   Full-screen image viewer launched from a .hzo-gallery[data-hzo-lightbox].
   Built + managed by the lightbox IIFE in main.js (portaled to <body>): focus
   trap (via the shared trap stack, so it nests over a modal), Esc / backdrop /
   close-button dismiss, arrow-key + prev/next navigation, focus return to the
   clicked thumbnail. Sits at --z-popover so it layers above a modal it opens
   from. Reuses existing tokens; zero new tokens. Markup contract: §39. */
.hzo-lightbox {
    position: fixed;
    inset: 0;
    z-index: var(--z-popover);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-xl);
    background: rgba(0, 0, 0, 0.85);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--transition-base) ease, visibility var(--transition-base);
}
.hzo-lightbox.is-open { opacity: 1; visibility: visible; }
.hzo-lightbox__figure {
    margin: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-sm);
    max-width: 100%;
    max-height: 100%;
}
.hzo-lightbox__img {
    max-width: 100%;
    max-height: 80vh;
    object-fit: contain;
    border-radius: var(--radius-input);
    background: #fff;
}
.hzo-lightbox__caption { color: #fff; font-size: 14px; line-height: 1.5; text-align: center; max-width: 60ch; }
.hzo-lightbox__close,
.hzo-lightbox__nav {
    position: absolute;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 0;
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    cursor: pointer;
    transition: background var(--transition-base) ease;
}
.hzo-lightbox__close:hover,
.hzo-lightbox__nav:hover { background: rgba(255, 255, 255, 0.25); }
.hzo-lightbox__close:focus-visible,
.hzo-lightbox__nav:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.hzo-lightbox__close { top: 16px; right: 16px; }
.hzo-lightbox__nav { top: 50%; transform: translateY(-50%); }
.hzo-lightbox__nav--prev { left: 16px; }
.hzo-lightbox__nav--next { right: 16px; }
.hzo-lightbox__close > svg,
.hzo-lightbox__nav > svg { width: 24px; height: 24px; display: block; }

@media (prefers-reduced-motion: reduce) {
    .hzo-lightbox { transition: none; }
}

/* ─── Skip link (a11y) ────────────────────────────────────────────────
   Visually hidden until focused. Intended as the FIRST focusable element in
   the header, jumping keyboard/AT users past the nav to <main id="main">.
   Reveal on :focus (not :focus-visible — it must appear for keyboard Tab). */
.hzo-skip-link {
    position: fixed;
    top: 8px;
    left: 8px;
    z-index: var(--z-toast);
    transform: translateY(-150%);
    background: var(--brand);
    color: var(--text-on-brand) !important;
    padding: 12px 20px;
    border-radius: var(--radius-input);
    font-family: var(--font-body);
    font-weight: var(--fw-semibold, 600);
    text-decoration: none;
    transition: transform var(--transition-base) ease;
}
.hzo-skip-link:focus { transform: translateY(0); outline: 3px solid var(--focus-ring); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .hzo-skip-link { transition: none; } }

/* ─── Input group (input + button) ────────────────────────────────────
   Joins a text input + a .hzo-btn into one control (header search, footer
   newsletter). Use STANDALONE — not inside .hzo-form, which stacks full-width
   fields; the group styles its own input. */
.hzo-input-group { display: flex; width: 100%; max-width: 480px; }
.hzo-input-group > input {
    flex: 1;
    min-width: 0;
    padding: 13px 16px;
    font-family: var(--font-body);
    font-size: 1rem;
    color: var(--text-body);
    background: #fff;
    border: 1px solid var(--border);
    border-right: 0;
    border-radius: var(--radius-input) 0 0 var(--radius-input);
}
.hzo-input-group > input:focus {
    outline: none;
    border-color: var(--focus-ring);
    box-shadow: 0 0 0 2px var(--brand-pale);
    position: relative;
    z-index: 1;
}
.hzo-input-group > input::placeholder { color: #9ca3af; }
.hzo-input-group > .hzo-btn {
    flex-shrink: 0;
    border-radius: 0 var(--radius-input) var(--radius-input) 0;
}
/* The base mobile rule sets non-inline buttons to width:100%, which would crush
   the input in this flex row. Keep input-group buttons intrinsic on mobile —
   specificity (0,0,5,0) beats the base rule (0,0,4,0) regardless of source order. */
@media (max-width: 767px) {
    .hzo-input-group > .hzo-btn:not(.hzo-btn--inline):not(.hzo-btn--icon):not(.hzo-btn--block) { width: auto; }
}

/* ─── :visited state normalization ───────────────────────────────────
   Browsers default :visited links to dark purple/grey, which overrides
   our styling once a link has been clicked. Each class-based link type
   below resets :visited to match its base color. This is critical for
   nav, footer, and card CTAs where visited links would otherwise shift
   color after a visitor's first navigation. */
.hzo-nav-link:visited,
.hzo-site-nav__link:visited,
.hzo-mega-menu__link:visited,
.hzo-mobile-menu__link:visited { color: var(--nav-link); }

/* :visited:hover — must be re-declared because :visited and :hover have the
   same specificity, so without this block the :visited rule above (which
   comes later in source order) would win on hover-over-visited links. */
.hzo-nav-link:visited:hover,
.hzo-site-nav__link:visited:hover,
.hzo-mega-menu__link:visited:hover,
.hzo-mobile-menu__link:visited:hover { color: var(--nav-link-hover); }

.hzo-breadcrumb a:visited { color: var(--text-muted); }
.hzo-breadcrumb a:visited:hover { color: var(--brand); }
.hzo-breadcrumb [aria-current="page"]:visited { color: var(--text-body); }

.hzo-card__link:visited { color: var(--accent-text) !important; }
.hzo-card__link:visited:hover { color: color-mix(in srgb, var(--accent-text) 70%, black) !important; }

.hzo-site-logo:visited { color: var(--brand); }

/* Dark-footer variant */
.hzo-site-footer a:visited { color: var(--footer-link-base-dark, rgba(255,255,255,0.85)); }
.hzo-footer-link:visited { color: var(--footer-link-dark, rgba(255,255,255,0.8)) !important; }

/* Light-footer variant */
.hzo-site-footer--light a:visited { color: var(--text-body) !important; }
.hzo-site-footer--light .hzo-footer-link:visited { color: var(--footer-link) !important; }

/* Buttons do NOT need :visited rules. The base .hzo-btn rules use !important
   on `color` and `background` which already overrides a:visited from per-client
   main.css. Adding :visited here creates a maintenance trap: if the base color
   changes, the :visited rule goes stale and shows the wrong color once a
   button link has been clicked. */

/* ─── Social icons (v1.1.3) ────────────────────────────────────────────────
   [hzo_social_icons] outputs inline SVGs without explicit width/height
   attributes. Without an explicit CSS constraint, SVGs in a flex container
   fall to fill-the-parent sizing — produced the 150px+ Facebook/Instagram
   icons surfaced 2026-05-22. Constrains both the default .hzo-social-icons
   class and the .hzo-footer-social variant the footer.html part passes. */
.hzo-social-icons,
.hzo-footer-social {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    margin-top: 12px;
}
/* Social icon links carry the .hzo-social-icons__link class (added in
   [hzo_social_icons], v1.1.93) — again, the class exists so a per-client
   `a:not([class])` content-link rule excludes them. Styling stays on the
   original descendant selectors, which win on cascade order within this file.
   No !important. */
.hzo-social-icons a,
.hzo-footer-social a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    color: var(--footer-social-link, var(--accent, currentColor));
    text-decoration: none;
    background-image: none;
    border-radius: 50%;
    /* Smooth ease-out settle rather than a snappy linear flip (v1.1.93). */
    transition: color 0.3s cubic-bezier(0.22, 1, 0.36, 1),
                background-color 0.3s cubic-bezier(0.22, 1, 0.36, 1),
                transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
/* Hold the accent color after the (external) social link is visited — without
   this, `.hzo-site-footer a:visited` (rgba .85) repaints visited icons. Mirrors
   the .hzo-footer-link:visited pattern; placed after that rule so it wins the
   same-specificity tie on cascade order. No !important. */
.hzo-social-icons a:visited,
.hzo-footer-social a:visited { color: var(--footer-social-link, var(--accent, currentColor)); }
.hzo-social-icons a:hover,
.hzo-social-icons a:focus-visible,
.hzo-footer-social a:hover,
.hzo-footer-social a:focus-visible {
    color: var(--footer-social-link-hover, var(--text-on-accent, #fff));
    background-color: var(--footer-social-bg-hover, var(--accent-hover-on-dark, rgba(255,255,255,0.1)));
    transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
    .hzo-social-icons a,
    .hzo-footer-social a { transition: color 0.15s ease, background-color 0.15s ease; }
    .hzo-social-icons a:hover,
    .hzo-footer-social a:hover { transform: none; }
}
.hzo-social-icons svg,
.hzo-footer-social svg {
    width: 20px;
    height: 20px;
    display: block;
}
