/* 
Theme Name: Hello Elementor Child
Theme URI: https://github.com/elementor/hello-theme-child/
Description: Hello Elementor Child is a child theme of Hello Elementor, created by Elementor team
Author: Elementor Team
Author URI: https://elementor.com/
Template: hello-elementor
Version: 2.0.0
Text Domain: hello-elementor-child
License: GNU General Public License v3 or later.
License URI: https://www.gnu.org/licenses/gpl-3.0.html
Tags: flexible-header, custom-colors, custom-menu, custom-logo, editor-style, featured-images, rtl-language-support, threaded-comments, translation-ready
*/

/* Add your custom styles here */

/* ═══════════════════════════════════════════════════════════════════
   NAMING RULE — read before adding any colour variable.

   Variable names use the Figma LEAF name, spelled in full. Never the
   group name: BOTH colour collections contain a group called
   "Primary navy", so a group-based name is ambiguous. Leaf names are
   unique across both collections.

     Primary/Primary navy/royal blue-500      → --bhm-royal-500
     Foundation /Primary Navy/primary navy-500 → --bhm-primary-navy-500

   TWO COLOUR COLLECTIONS ARE CURRENTLY LIVE IN THIS FILE, pending the
   colour-fork decision. See Notion → BHM → Design System.
   ═══════════════════════════════════════════════════════════════════ */

:root {
  /* ============ COLOR — Primary (action) ============ */
  /* Collection A · Figma "Primary/Accent red". Ramp interpolated;
     only crimson-300 (#d45d68) and crimson-500 (#bf0d1d) are confirmed. */
  --bhm-crimson-50:  #f9e7e8;
  --bhm-crimson-100: #ebb4b9;
  --bhm-crimson-200: #e29097;
  --bhm-crimson-300: #d45d68;   /* ✅ confirmed — Figma crimson-red-300 */
  --bhm-crimson-400: #cc3d4a;
  --bhm-crimson-500: #bf0d1d;   /* primary CTA — ✅ confirmed via CTA button */
  --bhm-crimson-600: #ae0c1a;   /* CTA hover */
  --bhm-crimson-700: #880915;
  --bhm-crimson-800: #690710;
  --bhm-crimson-900: #50050c;

  /* ============ COLOR — Secondary (heading/brand) ============ */
  /* Collection A · Figma "Primary/Primary navy". Ramp interpolated;
     only royal-500 is confirmed. */
  --bhm-royal-50:  #e6e9f0;
  --bhm-royal-100: #b0bbd0;
  --bhm-royal-200: #8a9ab9;
  --bhm-royal-300: #546c98;
  --bhm-royal-400: #334f85;
  --bhm-royal-500: #002366;    /* heading text on light bg — ✅ confirmed */
  --bhm-royal-600: #00205d;
  --bhm-royal-700: #001948;
  --bhm-royal-800: #001338;
  --bhm-royal-900: #000f2b;

  /* ============ COLOR — Neutrals ============ */
  /* Collection A · Figma "Neutrals". */
  --bhm-white-50:  #ffffff;
  --bhm-white-500: #fafcff;    /* card / surface bg — ✅ confirmed */
  --bhm-white-700: #b2b3b5;
  --bhm-black-200: #8a8a8c;    /* card body text */
  --bhm-black-300: #545558;
  --bhm-black-400: #333437;    /* card title text — ✅ confirmed */
  --bhm-black-500: #000105;
  --bhm-grey-100:  #f2f2f2;
  --bhm-grey-500:  #d6d6d6;
  --bhm-grey-900:  #5a5a5a;    /* ✅ confirmed — Figma Neutrals/grey/grey-900 */

  /* ============ COLOR — Foundation collection ============ */
  /* Collection B · Figma "Foundation /". Added 2026-07-17.
     Used by the scroll rail (Why Choose, node 213:5878).

     COEXISTS with the Primary/Neutrals ramps above pending the colour-fork
     decision — the two collections are NOT interchangeable. All 8 values
     read live from Figma; none are interpolated.

     ⚠ --bhm-medium-gray-500 (#667085) is NOT --bhm-grey-500 (#d6d6d6).
       Different colours, one letter apart. Full leaf names prevent the mixup. */
  --bhm-primary-navy-600: #07274f;   /* active dot, rail fill */
  --bhm-primary-navy-500: #082b57;   /* card title */
  --bhm-primary-navy-200: #8d9db2;   /* inactive dot */
  --bhm-deep-navy-500:    #041a35;   /* lead paragraph */
  --bhm-harbor-blue-100:  #c8d7e4;   /* rail track, active card edge */
  --bhm-accent-red-400:   #d14550;   /* eyebrow label */
  --bhm-medium-gray-500:  #667085;   /* card body copy */
  --bhm-off-white-500:    #f7f8fa;   /* section surface, card bg */

  /* ============ COLOR — Semantic ============ */
  --bhm-success-500: #16a34a;
  --bhm-warning-500: #f59e0b;
  --bhm-error-500:   #dc2626;

  /* ============ TYPOGRAPHY — families ============ */
  --bhm-font-display: 'Plus Jakarta Sans', sans-serif;  /* headings only */
  --bhm-font-body:    'Manrope', sans-serif;            /* paragraphs, labels */

  /* ============ TYPOGRAPHY — fluid scale (375px → 1440px) ============ */
  /* ⚠ SCALE OFFSET — unresolved. Figma confirms "Display xl/Bold = 60px"
     (hero H1, node 123:2215). There is NO 60px step below: display-2xl (72px)
     sits ABOVE Figma's top step and Figma's xl was dropped. If the hero H1
     references --bhm-fs-display-2xl it renders ~67px @1280 / 72px @1440
     against a designed 60px. VERIFY the H1's computed font-size before
     changing anything — the scale is misaligned, but the H1 may not use this. */

  /* Display 2xl — H1 hero */
  --bhm-fs-display-2xl: clamp(2.5rem, calc(2.5rem + (72 - 40) * (100vw - 375px) / 1065), 4.5rem);
  /* Display lg — H2 section titles */
  --bhm-fs-display-lg:  clamp(2rem, calc(2rem + (48 - 32) * (100vw - 375px) / 1065), 3rem);
  /* Display md — H3 */
  --bhm-fs-display-md:  clamp(1.75rem, calc(1.75rem + (36 - 28) * (100vw - 375px) / 1065), 2.25rem);
  /* Display xs — card/H4 titles */
  --bhm-fs-display-xs:  clamp(1.25rem, calc(1.25rem + (24 - 20) * (100vw - 375px) / 1065), 1.5rem);
  /* Text xl — lead paragraph (Manrope) */
  --bhm-fs-text-xl:     clamp(1.125rem, calc(1.125rem + (20 - 18) * (100vw - 375px) / 1065), 1.25rem);
  /* Text md — body copy (Manrope) — deliberately NOT fluid, 16px is the readability floor */
  --bhm-fs-text-md:     1rem;
  /* Text sm — eyebrow/kicker labels, uppercase (Plus Jakarta Sans) */
  --bhm-fs-text-sm:     clamp(0.75rem, calc(0.75rem + (14 - 12) * (100vw - 375px) / 1065), 0.875rem);

  /* ============ SPACING ============ */
  /* Verified against Figma 2026-07-17. Real scale: 0 / 16 / 24 / 32 / 48 / 96. */
  --bhm-space-xs:  0.5rem;   /*  8px  — no Figma token, unconfirmed */
  --bhm-space-sm:  0.75rem;  /* 12px  — no Figma token, unconfirmed */
  --bhm-space-md:  1rem;     /* 16px  ✅ confirmed */
  --bhm-space-lg:  1.5rem;   /* 24px  ✅ confirmed (was interpolated — guessed right) */
  --bhm-space-xl:  2rem;     /* 32px  ✅ confirmed (was interpolated — guessed right) */
  --bhm-space-2xl: 3rem;     /* 48px  ✅ confirmed */
  --bhm-space-3xl: 4rem;     /* 64px  ⚠ NOT IN FIGMA — the real scale jumps 48→96.
                                       House addition. Keep only if deliberately used. */
  --bhm-space-4xl: 6rem;     /* 96px  ✅ confirmed (also = pill radius) */

  /* ============ RADIUS ============ */
  --bhm-radius-md:   1rem;     /* 16px — cards, images */
  --bhm-radius-pill: 6rem;     /* 96px — buttons, effectively 999px on their height */

  /* ============ CONTAINER ============ */
  /* ⚠ CONTRADICTS the confirmed container policy. The decided mechanism is
     Elementor's NATIVE container_width in Site Settings:
        min(1440px, calc(100vw - 192px))  → a 96px gutter.
     --bhm-container-pad maxes at 5rem = 80px. That is a 16px disagreement.
     DELETE BOTH if nothing references them. */
  --bhm-container-max: 1440px;
  --bhm-container-pad: clamp(1.25rem, calc(1.25rem + (80 - 20) * (100vw - 375px) / 1065), 5rem);
}


/* ═══════════════════════════════════════════════════════════════════
   HERO — scroll-expand clip mask
   Pairs with initHeroExpand() in animations.js.

   The inset values below are DUPLICATED in the JS `clip` proxy. This is
   deliberate — the CSS initial state prevents a full-bleed flash before
   GSAP runs. But nothing enforces the match: if they drift, the hero
   visibly jumps the moment GSAP takes over. Change both together.
   ═══════════════════════════════════════════════════════════════════ */

.bhm-hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  will-change: clip-path;
}

/* Initial masked state in CSS, not JS — prevents full-bleed flash before GSAP runs */
@media (min-width: 1025px) {
  .bhm-hero__media { clip-path: inset(30px 96px 40px 96px round 24px); }
}
@media (min-width: 768px) and (max-width: 1024px) {
  .bhm-hero__media { clip-path: inset(20px 48px 30px 48px round 24px); }
}
/* Below 768px NO JS context matches — mobile is designed to keep this static
   inset with no scroll-expand. This rule IS the mobile state, not a fallback.
   It only applies because clearClip() removes GSAP's inline clip-path on
   revert; without that cleanup an inline desktop value blocks this forever. */
@media (max-width: 767px) {
  .bhm-hero__media { clip-path: inset(16px 24px 24px 24px round 16px); }
}

.bhm-hero__content {
  position: relative;
  z-index: 1;
}


/* ═══════════════════════════════════════════════════════════════════
   SCROLL RAIL — serves Why Choose (213:5878) and Our Process (123:2246)
   Pairs with initWhyRail() in animations.js.

   GEOMETRY CONTRACT: JS reads --dot-offset back out of this CSS on every
   ScrollTrigger refresh (pseudo-element dots can't be measured with
   getBoundingClientRect). CSS is the single source of truth — change
   --dot-offset HERE only, never in the JS.
   ═══════════════════════════════════════════════════════════════════ */

.bhm-steps {
  /* ── Semantic layer ──────────────────────────────────────────────
     The ONLY place this component touches the palette. Currently mapped
     to the Foundation collection. If the colour fork resolves to
     Primary/Neutrals, change these seven lines and nothing else. */
  --rail-track: var(--bhm-harbor-blue-100);
  --rail-fill:  var(--bhm-primary-navy-600);
  --dot-idle:   var(--bhm-primary-navy-200);
  --dot-live:   var(--bhm-primary-navy-600);
  --card-edge:  var(--bhm-harbor-blue-100);
  --card-title: var(--bhm-primary-navy-500);
  --card-body:  var(--bhm-medium-gray-500);

  /* ── Geometry ──────────────────────────────────────────────────── */
  --dot-size:   16px;
  --dot-x:       8px;
  --dot-offset: 30px;   /* dot CENTRE from step top. DERIVED:
                           2 (card border) + 16 (padding) + 12 (½ × 20px × 1.2).
                           Recompute if the title's size or line-height changes. */
  --rail-w:      4px;
  --card-x:     44px;
  --step-gap:   24px;   /* = --bhm-space-lg */

  /* ── Driven by JS — do not hand-edit ───────────────────────────── */
  --rail-top: 30px;
  --rail-h:    0px;
  --rail-p:      0;

  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--step-gap);
  width: 100%;
  max-width: 414px;
}

/* ── Rail: track + fill share identical geometry ─────────────────── */
.bhm-steps::before,
.bhm-steps::after {
  content: "";
  position: absolute;
  left: calc(var(--dot-x) + (var(--dot-size) - var(--rail-w)) / 2);
  width: var(--rail-w);
  top: var(--rail-top);
  height: var(--rail-h);
  border-radius: var(--rail-w);
  pointer-events: none;
}

.bhm-steps::before {
  background: var(--rail-track);
}

.bhm-steps::after {
  background: var(--rail-fill);
  transform: scaleY(var(--rail-p));
  transform-origin: top center;
  /* Permanent hint is deliberate: one 4px element under scrub for the whole
     section transit. Promoting once beats thrashing the layer on enter/leave. */
  will-change: transform;
}

/* ── Step + dot ──────────────────────────────────────────────────── */
.bhm-step {
  position: relative;
  padding-left: var(--card-x);
}

.bhm-step::before {
  content: "";
  position: absolute;
  /* LOAD-BEARING. .bhm-steps::after paints after every child by spec — without
     this the navy fill draws straight over all the dots and they never appear
     to change. The rail still animates, so it fails SILENTLY. Do not remove. */
  z-index: 1;
  left: var(--dot-x);
  top: calc(var(--dot-offset) - var(--dot-size) / 2);
  width: var(--dot-size);
  height: var(--dot-size);
  border-radius: 50%;
  background: var(--dot-idle);
  transform: scale(1);
  transition:
    background-color .35s ease,
    box-shadow       .35s ease,
    transform        .35s cubic-bezier(.34, 1.36, .64, 1);
}

.bhm-step.is-active::before {
  background: var(--dot-live);
  transform: scale(1.15);
  /* Legacy fallback — hardcoded, WILL go stale if the colour fork resolves
     to Collection A. Only reached by browsers without color-mix (pre-2023). */
  box-shadow: 0 0 0 6px rgb(7 39 79 / .10);
  /* Ring derives from the fill, so it follows the semantic layer automatically. */
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--dot-live) 10%, transparent);
}

/* ── Card ────────────────────────────────────────────────────────── */
/* The section surface is ALREADY --bhm-off-white-500, so a card background
   fill is a visual no-op — transparent over #f7f8fa renders identically.
   The 2px border is the only state slot the surface allows. Reserved at
   `transparent` so activation causes zero layout shift. */
.bhm-step__card {
  display: flex;
  flex-direction: column;
  gap: var(--bhm-space-md);
  padding: var(--bhm-space-md);
  border: 2px solid transparent;
  border-radius: var(--bhm-radius-md);
  background: transparent;
  transition: border-color .4s ease;
}

.bhm-step.is-active .bhm-step__card {
  border-color: var(--card-edge);
}

.bhm-step__title {
  margin: 0;
  font-family: var(--bhm-font-display);
  font-weight: 700;
  /* Flat 20px, matching Figma "Plus Jakarta Sans/Text xl/Bold" exactly.
     Deliberately NOT --bhm-fs-display-xs: that is fluid 20→24px, and above
     ~1065px it would render 24px, making --dot-offset wrong (needs 32.4, not
     30) and drifting the dots ~2px high on wide screens.
     If this ever goes fluid, derive the offset instead:
       --dot-offset: calc(2px + var(--bhm-space-md) + (<title-size> * 1.2 / 2));
     getComputedStyle resolves calc() to px, so the JS contract still holds. */
  font-size: 1.25rem;
  line-height: 1.2;
  color: var(--card-title);
}

.bhm-step__text {
  margin: 0;
  font-family: var(--bhm-font-body);
  font-weight: 500;
  font-size: var(--bhm-fs-text-md);
  line-height: 1.3;
  color: var(--card-body);
}

/* ══ Responsive ═══════════════════════════════════════════════════
   --dot-offset must be recomputed whenever the title's rendered size or
   line-height changes at a breakpoint. JS picks it up for free. */

@media (max-width: 1024px) {
  .bhm-steps {
    max-width: 100%;
    --dot-x:  0px;      /* rail recentres itself via the calc() on `left` */
    --card-x: 32px;
  }
}

@media (max-width: 767px) {
  .bhm-steps {
    --step-gap:   20px;
    --dot-size:   12px;
    --card-x:     28px;
    --dot-offset: 29px;   /* 2 + 16 + (18 × 1.2 / 2) = 28.8 */
  }
  .bhm-step__title {
    font-size: 1.125rem;  /* 18px */
  }
}

/* ── Reduced motion: JS lights every state instantly, CSS must not tween ── */
@media (prefers-reduced-motion: reduce) {
  .bhm-step::before,
  .bhm-step__card {
    transition: none;
  }
}