/* ==========================================================================
   Iron Shore Roofing — Coastal video hero
   --------------------------------------------------------------------------
   Additive, progressively-enhanced layer. Everything is scoped to
   `.hero.ch-on`, a class added by coast-hero.js only after it has
   successfully built the scene. If the JS or this stylesheet fails to load,
   the original hero renders untouched.

   Geometry notes (measured from the source artwork, 1280x720):
     · The highest point of the roof/chimney sits at y = 147  → 20.4% of the
       frame height. Everything above that line is open sky.
     · The plane therefore flies inside the top 0–18.5% band of the *video
       frame* (not the container), so it can never cross the roofline no
       matter how the video is cropped. coast-hero.js computes the rendered
       video box and publishes it as --ch-vw / --ch-vh / --ch-vx.
     · The video is anchored `center top`, so that sky band is never the part
       that gets cropped away.

   Nothing below the hero is targeted by this file.
   ========================================================================== */

.hero.ch-on {
  /* Brand tokens — reused from the site's existing palette */
  --ch-navy-deep: #070b13;
  --ch-navy: #0b1120;
  --ch-blue: #1a5fd4;         /* --color-primary */
  --ch-blue-light: #3b7ef5;   /* --color-primary-light */
  --ch-text-dim: #93a2b6;

  /* Published by coast-hero.js (px). Fallbacks keep the layout sane if the
     measuring pass has not run yet. */
  --ch-vw: 100%;
  --ch-vh: 100%;
  --ch-vx: 0px;
  --ch-plane-w: 380px;
  --ch-plane-top: 34px;
  --ch-stage-w: 100vw;

  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: stretch;
  overflow: hidden;
  isolation: isolate;
  /* Fixed by CSS alone, so the hero reserves its space before any media
     loads — no layout shift. */
  /* Nudged up only enough to seat the trust strip. Kept deliberately modest:
     on desktop the media box is sized from the hero's height, so every extra
     pixel of height also widens the artwork and eats into the navy the copy
     sits on. */
  min-height: clamp(620px, calc(27vw + 200px), 780px);
  background:
    radial-gradient(120% 90% at 6% 45%, rgba(26, 95, 212, 0.13) 0%, rgba(26, 95, 212, 0) 58%),
    linear-gradient(100deg, var(--ch-navy-deep) 0%, var(--ch-navy) 62%, #101827 100%);
}

/* Retire the layers belonging to earlier hero iterations. Kept in the DOM
   (not removed) so the untouched React markup still validates. */
.hero.ch-on .hero-bg,
.hero.ch-on .hero-form-card,
.hero.ch-on .hero-badges,
.hero.ch-on .storm-hero-scene,
.hero.ch-on .sh-overlay,
.hero.ch-on .ish-art,
.hero.ch-on .ish-panel,
.hero.ch-on .ish-stagebar,
.hero.ch-on .ish-eyebrow { display: none !important; }

/* --------------------------------------------------------------------------
   Layer 0 — waterfront video
   -------------------------------------------------------------------------- */
/* The media box is sized by coast-hero.js to the artwork's own 16:9 ratio and
   anchored to the right, so on desktop the *whole* scene is visible — sky,
   horizon, surf, dune and the complete house, never cropped mid-porch. The
   copy panel occupies the navy to its left. */
.hero.ch-on .ch-media {
  position: absolute;
  top: 0;
  right: 0;
  width: var(--ch-vw);
  height: var(--ch-vh);
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

/* Feather the leading edge so the artwork emerges from the navy instead of
   sitting on it as a rectangle. Only applied when there is navy to emerge
   from — see .ch-inset, set by the measuring pass. */
.hero.ch-on.ch-inset .ch-media {
  -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, 0.5) 7%, #000 21%);
  mask-image: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, 0.5) 7%, #000 21%);
}

.hero.ch-on .ch-video,
.hero.ch-on .ch-still {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Top-anchored: the sky band the plane flies in is never cropped away. */
  object-position: center top;
  display: block;
  border: 0;
}

/* The video is visible from the start and the still sits behind it as a true
   fallback.

   This used to be inverted — the video was opacity:0 and only revealed by a
   one-shot `playing` listener. That made a single missed event enough to hide
   a perfectly good video behind the poster forever, which is precisely the
   "it's just a still image" failure. The video element's own `poster` is the
   same frame as the still, so showing it immediately costs nothing visually
   and removes the failure mode entirely. */
.hero.ch-on .ch-video {
  opacity: 1;
  z-index: 1;
}

.hero.ch-on .ch-still { z-index: 0; }

/* Kill every native media affordance.

   This is a decorative background, never a player. iOS Safari draws a large
   centred "start playback" glyph over any inline video it has not started, and
   because the video now sits at opacity 1 that glyph became visible — it looked
   like the hero was a tap-to-play video. Suppressing these pseudo-elements
   means a refused or delayed autoplay degrades to the poster frame silently,
   with no control furniture on top of the artwork. */
.hero.ch-on .ch-video::-webkit-media-controls,
.hero.ch-on .ch-video::-webkit-media-controls-panel,
.hero.ch-on .ch-video::-webkit-media-controls-panel-container,
.hero.ch-on .ch-video::-webkit-media-controls-play-button,
.hero.ch-on .ch-video::-webkit-media-controls-overlay-play-button,
.hero.ch-on .ch-video::-webkit-media-controls-start-playback-button {
  display: none !important;
  -webkit-appearance: none !important;
  appearance: none !important;
  opacity: 0 !important;
  pointer-events: none !important;
}

/* If the video genuinely cannot decode, drop it out so the still behind is
   what shows. Set by coast-hero.js on a real `error` event only. */
.hero.ch-on.ch-novideo .ch-video { display: none !important; }

/* --------------------------------------------------------------------------
   Layer 1 — plane + banner
   -------------------------------------------------------------------------- */
/* The plane sits *under* the scrim, and the layer itself fades toward the
   copy side. Two things fall out of that: the plane can never compete with
   the headline, and its exit reads as flying off into the haze rather than
   sliding off a rectangle. */
.hero.ch-on .ch-plane-layer {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
  /* Fully gone before it reaches the copy panel — a part-faded plane over
     flat navy reads as a smudge, not as depth. The two stops are pinned to
     the artwork's actual left edge by the measuring pass, so the fade lands
     in the same place relative to the scene at every viewport width. */
  -webkit-mask-image: linear-gradient(to right,
    transparent 0%, transparent var(--ch-fade-a, 25%), #000 var(--ch-fade-b, 40%));
  mask-image: linear-gradient(to right,
    transparent 0%, transparent var(--ch-fade-a, 25%), #000 var(--ch-fade-b, 40%));
}

.hero.ch-on .ch-plane-fly {
  position: absolute;
  left: 0;
  top: var(--ch-plane-top);
  width: var(--ch-plane-w);
  will-change: transform;
  /* Parked off the right edge until the animation starts. */
  transform: translate3d(calc(var(--ch-stage-w) + 40px), 0, 0);
}

/* The negative delay starts the cycle already underway, so the plane is
   entering frame on arrival rather than making visitors wait for it. */
.hero.ch-on.ch-fly .ch-plane-fly {
  animation: ch-fly var(--ch-fly-dur, 44s) linear infinite;
  animation-delay: calc(var(--ch-fly-dur, 44s) * -0.06);
}

.hero.ch-on .ch-plane-bob {
  display: block;
  will-change: transform;
}

.hero.ch-on.ch-fly .ch-plane-bob {
  animation: ch-bob 6.5s ease-in-out infinite;
}

.hero.ch-on .ch-plane {
  display: block;
  width: 100%;
  height: auto;
  /* Seats the cut-out into the scene instead of letting it sit on top. */
  filter: drop-shadow(0 6px 14px rgba(7, 11, 19, 0.28));
}

/* Travel occupies the first 60% of the cycle; the remainder is an empty sky
   beat so the hero stays calm rather than becoming a conveyor belt. */
@keyframes ch-fly {
  0%   { transform: translate3d(calc(var(--ch-stage-w) + 40px), 0, 0); }
  60%  { transform: translate3d(calc(-1 * var(--ch-plane-w) - 40px), 0, 0); }
  100% { transform: translate3d(calc(-1 * var(--ch-plane-w) - 40px), 0, 0); }
}

@keyframes ch-bob {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
  50%      { transform: translate3d(0, -6px, 0) rotate(-0.7deg); }
}

/* --------------------------------------------------------------------------
   Layer 2 — readability scrim
   -------------------------------------------------------------------------- */
.hero.ch-on .ch-scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    /* seats the hero under the dark sticky nav */
    linear-gradient(180deg, rgba(7, 11, 19, 0.55) 0%, rgba(7, 11, 19, 0) 18%),
    /* settles the bottom edge into the section below */
    linear-gradient(0deg, rgba(7, 11, 19, 0.45) 0%, rgba(7, 11, 19, 0) 22%),
    /* The copy panel. Stops sit further right than before: the taller hero
       widens the artwork (its width derives from the hero's height), so the
       dark field has to reach further to keep the subtitle and CTAs on solid
       ground. The house itself starts well right of the last stop. */
    linear-gradient(90deg,
      rgba(7, 11, 19, 0.94) 0%,
      rgba(7, 11, 19, 0.90) 30%,
      rgba(7, 11, 19, 0.68) 44%,
      rgba(7, 11, 19, 0.30) 58%,
      rgba(7, 11, 19, 0.07) 74%,
      rgba(7, 11, 19, 0) 86%);
}

/* A whisper of brand blue in the copy field, matching the previous hero. */
.hero.ch-on .ch-scrim::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 90% at 6% 45%,
    rgba(26, 95, 212, 0.16) 0%, rgba(26, 95, 212, 0) 58%);
}

/* --------------------------------------------------------------------------
   Layer 3 — copy
   -------------------------------------------------------------------------- */
.hero.ch-on .hero-inner {
  position: relative;
  z-index: 3;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  width: 100%;
  padding-top: 40px;
  /* Reserves the trust strip's shelf so the copy can never sit under it. */
  padding-bottom: 96px;
  /* The site's own rules zero the horizontal padding on .hero-inner; restore
     the container gutter so the copy lines up with the navigation above. */
  padding-left: 20px;
  padding-right: 20px;
}

.hero.ch-on .hero-content {
  /* Slightly narrower than before so the larger display type still resolves
     inside the navy and never runs out over the bright part of the artwork. */
  max-width: min(470px, 38vw);
  padding-right: 8px;
}

.hero.ch-on .hero-accent { margin-bottom: 16px; }

/* Eyebrow — Iron Shore's own logo tagline, set as a tracked label above the
   headline. Gives the hero the layered "label / display / support / action"
   rhythm the reference builds its authority from. */
.hero.ch-on .ch-eyebrow {
  margin: 0 0 14px;
  font-family: Oswald, sans-serif;
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 3.2px;
  text-transform: uppercase;
  color: var(--ch-blue-light);
}

.hero.ch-on .hero-content h1 {
  margin: 0 0 20px;
  font-family: "Barlow Condensed", sans-serif;
  font-weight: 900;
  /* Larger and tighter than before: the display line is what carries the
     "premium/cinematic" read, so it gets the most room. */
  font-size: clamp(42px, 4.15vw, 66px);
  line-height: 0.98;
  letter-spacing: -0.2px;
  color: #fff;
  text-transform: uppercase;
  text-shadow: 0 3px 28px rgba(0, 0, 0, 0.5);
}

.hero.ch-on .hero-content h1 span {
  display: block;
  color: var(--ch-blue-light);
}

.hero.ch-on .hero-subtitle {
  margin: 0 0 30px;
  max-width: 42ch;
  font-size: 17px;
  line-height: 1.62;
  color: #c2cddb;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.45);
}

.hero.ch-on .hero-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin: 0 0 22px;
}

/* Reuses the site's existing .btn-primary / .btn-outline components; only the
   hero-specific sizing is adjusted so the CTA stays visually dominant. */
.hero.ch-on .hero-ctas .btn-primary {
  padding: 15px 30px;
  font-size: 15px;
  box-shadow: 0 10px 26px rgba(224, 92, 26, 0.30);
}

.hero.ch-on .hero-ctas .btn-outline {
  padding: 13px 26px;
  font-size: 15px;
  border-color: rgba(59, 126, 245, 0.85);
  background: rgba(26, 95, 212, 0.14);
  backdrop-filter: blur(2px);
}

.hero.ch-on .hero-ctas .btn-outline:hover {
  background: rgba(26, 95, 212, 0.26);
}

/* The old single-line trust text is superseded by the strip below. Kept in the
   DOM so the copy still exists for anything reading the page as text. */
.hero.ch-on .ch-trust {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Trust strip — pinned to the foot of the hero
   --------------------------------------------------------------------------
   Four proof points on a hairline-topped translucent shelf, each with a
   thin-line glyph. This is the single most useful idea in the desktop
   reference: it converts a throwaway line of small print into the hero's
   credibility anchor without costing any vertical space in the copy column.

   Absolutely positioned so the headline stays optically centred in the full
   hero; .hero-inner reserves matching padding so the two can never collide.
   -------------------------------------------------------------------------- */
.hero.ch-on .ch-trustbar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: center;
  /* --ch-gutter is measured from the copy column by the measuring pass, so the
     first proof point lines up exactly under the headline at any width. */
  padding: 0 var(--ch-gutter, 20px);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  background: linear-gradient(180deg, rgba(7, 11, 19, 0.42) 0%, rgba(7, 11, 19, 0.78) 100%);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.hero.ch-on .ch-tb-item {
  display: flex;
  align-items: center;
  gap: 11px;
  min-width: 0;
  padding: 20px 18px 20px 0;
}

/* Hairline separators between the columns, matching the reference. */
.hero.ch-on .ch-tb-item + .ch-tb-item {
  border-left: 1px solid rgba(255, 255, 255, 0.10);
  padding-left: 22px;
}

.hero.ch-on .ch-tb-icon {
  flex: 0 0 auto;
  width: 21px;
  height: 21px;
  color: var(--ch-blue-light);
}

.hero.ch-on .ch-tb-label {
  font-family: Oswald, sans-serif;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 1.5px;
  line-height: 1.25;
  text-transform: uppercase;
  color: #d5dee9;
}

/* ==========================================================================
   Tablet
   ========================================================================== */
@media (min-width: 768px) and (max-width: 1023px) {
  .hero.ch-on {
    min-height: clamp(600px, 70vh, 700px);
  }

  .hero.ch-on .hero-content { max-width: min(430px, 50vw); }
  .hero.ch-on .hero-content h1 { font-size: clamp(36px, 5.2vw, 48px); }
  .hero.ch-on .hero-subtitle { font-size: 16px; }

  /* Two columns of two at this width — four across gets too cramped to read. */
  .hero.ch-on .ch-trustbar { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero.ch-on .ch-tb-item { padding: 14px 14px 14px 0; }
  .hero.ch-on .ch-tb-item:nth-child(odd) { border-left: 0; padding-left: 0; }
  .hero.ch-on .ch-tb-item:nth-child(n + 3) { border-top: 1px solid rgba(255, 255, 255, 0.08); }
  .hero.ch-on .hero-inner { padding-bottom: 132px; }

  .hero.ch-on .ch-scrim {
    background:
      linear-gradient(180deg, rgba(7, 11, 19, 0.55) 0%, rgba(7, 11, 19, 0) 18%),
      linear-gradient(0deg, rgba(7, 11, 19, 0.50) 0%, rgba(7, 11, 19, 0) 24%),
      linear-gradient(90deg,
        rgba(7, 11, 19, 0.96) 0%,
        rgba(7, 11, 19, 0.92) 38%,
        rgba(7, 11, 19, 0.70) 56%,
        rgba(7, 11, 19, 0.32) 74%,
        rgba(7, 11, 19, 0.08) 92%,
        rgba(7, 11, 19, 0) 100%);
  }
}

/* ==========================================================================
   Mobile — copy sits over the scene, plane keeps its own reserved band
   ========================================================================== */
@media (max-width: 767px) {
  /* The scene runs full width as a band across the top — the entire coastal
     frame, uncropped — and dissolves into navy where the copy sits. Fitting
     it any other way turns the hero into a close-up of the house and loses
     the waterfront entirely. Height is reserved in pure CSS (56.25vw is the
     artwork's 16:9 height at full width), so there is no layout shift. */
  .hero.ch-on {
    min-height: 0;
    justify-content: flex-start;
  }

  .hero.ch-on .ch-media {
    width: 100%;
    height: 56.25vw;
    right: 0;
    -webkit-mask-image: linear-gradient(to bottom, #000 60%, rgba(0, 0, 0, 0.45) 84%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 60%, rgba(0, 0, 0, 0.45) 84%, transparent 100%);
  }

  .hero.ch-on .hero-inner {
    display: block;
    padding-top: calc(56.25vw + 18px);
    padding-bottom: 26px;
    padding-left: clamp(16px, 5vw, 28px);
    padding-right: clamp(16px, 5vw, 28px);
  }

  /* In normal flow here, beneath the CTAs — the copy is already stacked, so
     there is nothing to pin the strip over and no reason to overlay it. */
  .hero.ch-on .ch-trustbar {
    position: static;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0;
    /* Tight margins here: the strip is worth its space on mobile, but the hero
       already carries the video band, headline and two full-width CTAs, so
       every row has to earn its height. */
    margin: 0 clamp(16px, 5vw, 28px) 18px;
    padding: 2px 0 0;
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-top: 1px solid rgba(255, 255, 255, 0.11);
  }

  .hero.ch-on .ch-tb-item {
    gap: 9px;
    padding: 10px 10px 10px 0;
  }

  .hero.ch-on .ch-tb-item + .ch-tb-item { border-left: 0; padding-left: 0; }
  .hero.ch-on .ch-tb-item:nth-child(even) { padding-left: 12px; }
  .hero.ch-on .ch-tb-item:nth-child(n + 3) { border-top: 1px solid rgba(255, 255, 255, 0.07); }

  .hero.ch-on .ch-tb-icon { width: 18px; height: 18px; }
  .hero.ch-on .ch-tb-label { font-size: 10.5px; letter-spacing: 1.1px; }

  .hero.ch-on .ch-eyebrow { font-size: 11px; letter-spacing: 2.6px; margin-bottom: 12px; }

  .hero.ch-on .hero-content {
    max-width: 100%;
    padding-right: 0;
  }

  .hero.ch-on .hero-content h1 {
    font-size: clamp(32px, 8.6vw, 44px) !important;
    line-height: 1.06 !important;
    margin-bottom: 14px;
  }

  .hero.ch-on .hero-subtitle {
    font-size: 15.5px;
    line-height: 1.52;
    max-width: 100%;
    margin-bottom: 22px;
  }

  /* The copy sits below the plane here rather than beside it, so the plane
     stays legible right across the width. */
  .hero.ch-on .ch-plane-layer {
    -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 12%);
    mask-image: linear-gradient(to right, transparent 0%, #000 12%);
  }

  /* The copy sits on navy here, not on the scene, so the scrim only has to
     seat the artwork under the dark sticky nav. */
  .hero.ch-on .ch-scrim {
    background: linear-gradient(180deg, rgba(7, 11, 19, 0.48) 0%, rgba(7, 11, 19, 0) 26%);
  }

  .hero.ch-on .ch-scrim::after { opacity: 0.55; }

  /* Comfortably tappable, full-width CTAs. */
  .hero.ch-on .hero-ctas {
    display: grid;
    grid-template-columns: 1fr;
    gap: 12px;
    margin-bottom: 18px;
  }

  .hero.ch-on .hero-ctas .btn-primary,
  .hero.ch-on .hero-ctas .btn-outline {
    width: 100%;
    text-align: center;
    padding: 16px 20px;
    box-sizing: border-box;
  }

  .hero.ch-on .ch-trust { font-size: 12.5px; }

  /* Gentler bob at small sizes. */
  @keyframes ch-bob {
    0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
    50%      { transform: translate3d(0, -4px, 0) rotate(-0.5deg); }
  }
}

/* ==========================================================================
   Reduced motion — static scene, plane parked in open sky
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .hero.ch-on .ch-video { display: none !important; }

  .hero.ch-on .ch-plane-fly,
  .hero.ch-on.ch-fly .ch-plane-fly {
    animation: none !important;
    transform: translate3d(var(--ch-park-x, 8%), 0, 0) !important;
  }

  .hero.ch-on .ch-plane-bob,
  .hero.ch-on.ch-fly .ch-plane-bob {
    animation: none !important;
    transform: none !important;
  }

  .hero.ch-on .ch-video { transition: none !important; }
}

/* Same treatment when the JS reduced-motion / save-data branch takes over. */
.hero.ch-on.ch-rm .ch-video { display: none !important; }
.hero.ch-on.ch-rm .ch-plane-fly {
  animation: none !important;
  transform: translate3d(var(--ch-park-x, 8%), 0, 0) !important;
}
.hero.ch-on.ch-rm .ch-plane-bob { animation: none !important; transform: none !important; }
