/* Green Drain interactive hero styles — PRODUCTION (shipped on the homepage).
   Loads AFTER styles.css/animations.css to override the base hero with the cutaway-drain compositor.
   Sim-logic/style source of truth = website/hero-lab/ + the _herolab-* sandbox; keep in sync on changes. */

/* keep the ORIGINAL hero height (68vh / max 640px desktop, 70vh mobile) so the section
   below stays exactly where the live site has it — only add positioning for the overlay. */
.hero { position: relative; overflow: hidden; }
.hero > .container { position: relative; z-index: 2; pointer-events: none; } /* click-through so the in-scene Seal-it CTA / drain below is reachable; .hero-content re-enables itself */
.hero .hero-content { pointer-events: auto; }
.hero .hero-media { visibility: hidden; } /* hide product image, keep the grid column */

.drain-media { position: absolute; inset: 0; z-index: 0; }
.drain-zoom { position: absolute; inset: 0; }  /* zoom wrapper (passthrough unless the foldable rule scales it); holds plate + fx + seal so they scale together */
.plate, .plate-fallback {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center 55%;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 46%, #000 100%),
                      linear-gradient(to top, transparent 0%, #000 12%, #000 100%);
  -webkit-mask-composite: source-in;
          mask-image: linear-gradient(to right, transparent 0%, #000 46%, #000 100%),
                      linear-gradient(to top, transparent 0%, #000 12%, #000 100%);
          mask-composite: intersect;
}
.plate-fallback { display: grid; place-items: center; color: #3d6b3d; font-size: 14px;
  background: repeating-linear-gradient(45deg, #e3e9dd, #e3e9dd 14px, #dde4d5 14px, #dde4d5 28px); }

.fx { position: absolute; inset: 0; z-index: 1; pointer-events: none; overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 46%, #000 100%);
          mask-image: linear-gradient(to right, transparent 0%, #000 46%, #000 100%); }
/* CENTER the roach sprite on its transform/path point. The box is 30×20 with NO offset, so translate() would
   otherwise anchor the box's TOP-LEFT corner → the sprite's visual CENTER renders +15/+10 off the line. That
   latent offset pokes roaches through the pipe wall (worst on the thin mobile pipe, but it grazes the wall on
   desktop/iPad/tablet too). −half-box re-centers it at ALL breakpoints; rotate/scale are about the box center
   so the center stays put. (Found 2026-06-23 by measuring getBoundingClientRect vs the path point — see DEVLOG.) */
.bug { position: absolute; width: 30px; height: 30px; margin-left: -15px; margin-top: -15px; will-change: transform;
  background-repeat: no-repeat; background-size: 400% 100%; background-position: 0 0;
  animation: roachWalk 0.45s steps(4, jump-none) infinite; } /* photoreal 4-frame roach sprite strip: legs auto-cycle via background-position, INDEPENDENT of the JS transform. SQUARE box so the center-anchor (margin = half) holds through any rotation (the load-bearing anchor rule) */
@keyframes roachWalk { from { background-position: 0% 0; } to { background-position: 100% 0; } } /* steps(4, jump-none) stops at 0/33.3/66.7/100% = frames 0-3 (bg-size 400%) */
.bug.fly { margin-left: 0; margin-top: 0; background: none; animation: none; }  /* flies (20×15, set inline) keep their own anchor + SVG, no sprite/cycle */
/* sewer-gas haze: BIG, SOFT, LOW-ALPHA, BLURRED muted sage — the column is built from OVERLAP of many
   faint puffs (kills the bright-lime-squiggle look). multiply darkens like real haze over the cream hero. */
.gas { position: absolute; width: 70px; height: 70px; border-radius: 50%;
  background: radial-gradient(circle, rgba(150,180,120,0.18) 0%, rgba(150,180,120,0.08) 45%, rgba(150,180,120,0) 72%);
  filter: blur(10px); will-change: transform, opacity; } /* normal blend: reads over BOTH the dark gunk (bend) and the light marble (above the grate) */
.gas.billow { filter: blur(18px); } /* cloudier once it's free of the grate */
/* water pooled in the U-bend (evaporation intro) — murky green sewer water with a wet sheen */
.water { position: absolute; border-radius: 50%; pointer-events: none; will-change: transform, opacity, width, height;
  background: radial-gradient(ellipse at 50% 32%, rgba(190,205,150,0.5) 0%, rgba(120,140,95,0.42) 50%, rgba(120,140,95,0) 74%);
  filter: blur(2.5px); box-shadow: inset 0 2px 5px rgba(255,255,255,0.3); }

/* foreground occluder: re-draws the grate's SOLID body (the red lip/frame) from the plate ON TOP of the
   gas/bug layer, clipped to that region, so particles are hidden where they'd be "in front of" the solid
   grate — they only show through the green slots + above. Pixel-aligned with the plate so it's seamless. */
.grate-cover { position: absolute; background-repeat: no-repeat; z-index: 2; pointer-events: none; }
.gd-seal { position: absolute; z-index: 3; width: 8%; opacity: 0; pointer-events: none; will-change: transform, opacity; }
.gd-seal-fallback { border-radius: 50% 50% 46% 46% / 70% 70% 36% 36%;
  background: radial-gradient(ellipse at 40% 30%, #2d5a2d, #14210f 70%);
  box-shadow: 0 6px 14px rgba(0,0,0,0.35); aspect-ratio: 1 / 0.7; }

.marker { position: absolute; width: 16px; height: 16px; border-radius: 50%; transform: translate(-50%,-50%);
  z-index: 5; pointer-events: none; box-shadow: 0 0 0 2px #fff; display: none; }
.marker.show { display: block; } #mGrate { background: #ff2d55; } #mThroat { background: #2d6cff; }

/* in-scene "Seal it" CTA — a GREEN sonar-ping hotspot at the seal seat (replaces the dev HUD). The compositor
   anchors it at SEAL_SEAT each frame; it shows only while leaking + the "Seal it" word reveals on hover. Lives in
   #drainZoom (above the seal) so it scales with the foldable zoom. */
.seal-cta { position: absolute; transform: translate(-50%, -50%); z-index: 6; pointer-events: auto;
  width: 30px; height: 30px; background: none; border: 0; padding: 0; cursor: pointer; }
/* RADAR/SONAR ping: a small soft CORE + two rings that expand outward and fade (staggered) — no persistent hard
   circle, reads as an interactive hotspot. (Chris didn't like the box-shadow "circle"; this is motion, not an edge.) */
.seal-cta-dot { position: absolute; left: 50%; top: 50%; width: 13px; height: 13px; transform: translate(-50%, -50%);
  border-radius: 50%; background: radial-gradient(circle, rgba(230,255,188,0.98) 0%, rgba(150,226,96,0.92) 50%, rgba(150,226,96,0.12) 100%); }
.seal-cta-dot::before, .seal-cta-dot::after { content: ''; position: absolute; left: 50%; top: 50%;
  width: 13px; height: 13px; border-radius: 50%; background: rgba(150,228,96,0.45);
  transform: translate(-50%, -50%) scale(0.7); animation: sealPing 2.4s cubic-bezier(0.2,0.6,0.3,1) infinite; }
.seal-cta-dot::after { animation-delay: 1.2s; }
.seal-cta-label { position: absolute; top: calc(100% + 7px); left: 50%; transform: translateX(-50%);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 0.8rem; font-weight: 500;
  letter-spacing: 0.03em; color: #f4fbed; text-shadow: 0 1px 6px rgba(0,0,0,0.85); white-space: nowrap;
  opacity: 0; transition: opacity 0.22s ease; pointer-events: none; } /* HIDDEN by default — the pulsing glow IS the
  subtle CTA so it never competes with the hero copy (Chris). The word appears only on hover/focus; the <button>'s
  aria-label keeps it accessible to screen readers regardless. */
.seal-cta:hover .seal-cta-label, .seal-cta:focus-visible .seal-cta-label { opacity: 1; }
@keyframes sealPing { 0% { transform: translate(-50%, -50%) scale(0.7); opacity: 0.55; }
  70%, 100% { transform: translate(-50%, -50%) scale(3.4); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .seal-cta-dot::before, .seal-cta-dot::after { animation: none; } }

/* ---- Desktop (>=1024, hero is height-capped ~640px): HEIGHT-DRIVEN plate so it never
   width-zooms on wide/2K monitors. The plate is exactly hero-height tall (so the FULL cutaway
   floor->grate->plume room->throat->U-bend is always visible) and ~857px wide, parked
   right-of-center; wider screens add clean LEFT space for the copy instead of zooming.
   The `left` % MUST stay in sync with cxFrac() in the compositor JS. ---- */
@media (min-width: 1024px) {
  /* HOLD the image-4 size: the real .hero is min-height:68vh, which GROWS on tall/maximized windows
     (734px @1080-tall, 979px @1440-tall) and — because the plate is height-driven — balloons the drain.
     Pin the hero to its design height (640 = the site's own max-height) so the drain stays the contained,
     balanced proportion Chris loves at every window size. cover() reads this height -> no JS change. */
  .hero { min-height: 640px; max-height: 640px; }
  .plate, .plate-fallback {
    inset: auto; top: 50%; bottom: auto; left: auto; right: 0; /* FLUSH right on <=2560 (reaches edge, old 2K look) */
    height: 100%; width: auto; max-width: none; aspect-ratio: 3168 / 1344;  /* full WIDE cutaway at hero height; max-width:none defeats the site's img{max-width:100%} which would squish the wide plate */
    transform: translateY(-50%);
    object-position: center center;
    /* LEFT fade keeps the copy legible over the floor. Opaque by 68% (was 76%): the grate's left edge is at plate
       70%, so a 76% fade let ~10% cream bleed THROUGH the plate onto the grate (Chris caught the "white haze on the
       grate" 2026-06-23). The headline ends at ~62.6%, so 68% sits in the gap between the text and the grate — the
       copy still reads over the faded floor, and the grate is fully opaque (no cream). >1200 already clears it. */
    -webkit-mask-image: linear-gradient(to right, transparent 0%, transparent 16%, #000 68%, #000 100%);
            mask-image: linear-gradient(to right, transparent 0%, transparent 16%, #000 68%, #000 100%);
  }
}
/* >1200: align the drain's right edge to the CONTENT CONTAINER (center+600 = .container 1200/2) so the
   margins are symmetric and the whole hero reads balanced (the windowed-2K look) instead of "aligned right".
   Also fade the RIGHT edge into the cream margin. */
@media (min-width: 1201px) {
  .plate, .plate-fallback {
    right: max(0px, calc(50% - 600px));
    -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 60%, #000 85%, transparent 100%);
            mask-image: linear-gradient(to right, transparent 0%, #000 60%, #000 85%, transparent 100%);
  }
}

/* ---- Tablet (681–1023, mostly iPad portrait): TWO-COLUMN SPLIT — copy in a left column, the drain
   CONTAINED in the right column. We constrain the drain-media (#media) box to the right half, so cover()
   (which reads media.getBoundingClientRect()) re-frames the cutaway inside it automatically — NO JS change.
   The plate's object-position MUST match cover()'s tablet posX/posY (0.76 / 0.5) or the overlay drifts off
   the drain; a soft left fade blends the drain into the column seam. The real .hero is display:flex /
   align-items:center, so the copy vertical-centers in the band for free. ---- */
@media (min-width: 681px) and (max-width: 1023px) {
  .hero { min-height: 600px; }              /* contained 2-col band (flex-centers the copy) */
  .hero .hero-media { display: none; }      /* drop the empty product-image slot (was a dead 331px gap) */
  .hero-grid { grid-template-columns: 1fr 1fr; }  /* copy in the left cell; right cell is the drain */
  .drain-media { inset: 0 0 0 44%; }        /* media box = the right column; nudged a touch left so the soft fade reaches BEHIND the text edge (no hard cream/drain line). cover() frames the drain inside it */
  .plate, .plate-fallback {
    object-position: 82% 50%;               /* MATCH cover() tablet posX/posY (0.82 / 0.5) — drain centered in the right column */
    /* Opaque by 30% (was 48%): at the NARROW end of this band (681–940px) the grate sits at box-frac ~0.32–0.40, so a
       48% fade let the cream background bleed THROUGH the plate onto the grate — breaking the "bugs pass through the
       grate" illusion (Chris caught it 2026-06-23). 30% is opaque before the grate's left edge across the whole band,
       while still soft-blending the drain's left edge under the copy seam (which sits at box-frac <0.12). */
    -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 30%, #000 100%);
            mask-image: linear-gradient(to right, transparent 0%, #000 30%, #000 100%);
  }
  .fx {                                       /* match the plate fade so bugs/gas stay visible AT the grate (not faded out before it) */
    -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 30%, #000 100%);
            mask-image: linear-gradient(to right, transparent 0%, #000 30%, #000 100%);
  }
}

/* ---- Phones: STACK + PEEKING TEASER.
   Copy on top, then the FULL cutaway (no crop) sized by VIEWPORT HEIGHT (height-driven + centered,
   so it auto-shrinks on short phones instead of locking to 280px), then the dark-green products
   section RISES UP as a rounded "sheet" overlapping the drain's lower edge — its "One product.
   Every drain size." headline + grab-handle peek above the fold = a teaser that pops up.
   (Chris: on mobile the drain must NOT push the products section far down.)
   Drain-media sizing is mirrored in hero-lab/index.html; the products-sheet is sandbox-only
   (the lab has no section below the hero). ---- */
@media (max-width: 680px) {
  .hero { min-height: auto; display: flex; flex-direction: column; align-items: stretch; justify-content: flex-start;
    padding-top: 40px; padding-bottom: 0; } /* trim chrome so copy+drain fit ~one screen, leaving room to peek */
  .hero > .container { order: 1; } /* copy first */
  .hero .hero-media { display: none; } /* drop the empty product-image slot so it doesn't add a white gap */
  .hero .hero-content { padding-bottom: 0; }
  /* tighten the copy stack a touch to claw back vertical space (no size change, just margins) */
  .hero .hero-label { margin-bottom: 16px; }
  .hero .hero-headline { margin-bottom: 16px; }
  .hero .hero-subtitle { margin-bottom: 22px; }
  /* The cutaway is now WIDE (3168x1344) — it can't show full-width on a phone, so crop to the DRAIN
     (right third) at full hero-band width. clamp() keeps the band sane / lets the products teaser peek.
     object-position 76% MUST match cover()'s posX in the compositor. (Rough first pass — dial in w/ Chris.) */
  .drain-media { position: relative; order: 2; inset: auto; width: 100%; height: clamp(190px, 34vh, 300px);
    margin: 0; aspect-ratio: auto; }
  .plate, .plate-fallback {
    object-fit: cover; object-position: 76% 50%; /* focus the drain (right third), crop the left floor */
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 12%, #000 100%); /* soft blend into the copy above */
            mask-image: linear-gradient(to bottom, transparent 0%, #000 12%, #000 100%);
  }
  .fx {
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 12%, #000 100%);
            mask-image: linear-gradient(to bottom, transparent 0%, #000 12%, #000 100%);
  }
  /* the products section pops up as a rounded sheet over the drain's bottom -> the teaser */
  .products-section {
    position: relative; z-index: 3;               /* paint above the drain-media (which is positioned) */
    margin-top: -78px;                            /* overlap the drain's lower edge so the sheet rises over it */
    padding-top: 30px;                            /* headline sits near the sheet top -> peeks higher */
    border-radius: 24px 24px 0 0;                 /* rounded top = a sheet */
    box-shadow: 0 -14px 30px rgba(26, 60, 26, 0.26); /* upward lift shadow -> reads as popped up */
  }
  .products-section::before {                     /* grab-handle: the "pull up / more below" affordance */
    content: ""; position: absolute; top: 11px; left: 50%; transform: translateX(-50%);
    width: 44px; height: 5px; border-radius: 999px; background: rgba(255, 255, 255, 0.30);
  }
}

/* ---- SHORT viewports (smart displays like Nest Hub 1024×600, phones in landscape, short laptop windows):
   the tablet/desktop hero is pinned ~600–640px tall — taller than the screen — so the CTAs fall BELOW the fold.
   Cap the hero to the viewport height and shrink the copy (headline scales with vh) so the headline + CTAs stay
   visible. Scoped to max-height:700 so the approved normal-height tablet/desktop looks are untouched. ---- */
@media (min-width: 681px) and (max-height: 700px) {
  .hero { min-height: 0; max-height: calc(100vh - 110px); }   /* fit under the announcement bar + nav */
  .hero-headline { font-size: clamp(1.7rem, 5.4vh, 2.6rem); margin-bottom: 10px; }
  .hero-subtitle { margin-bottom: 16px; }
  .hero-label { margin-bottom: 8px; }
}

/* ---- PORTRAIT FOLDABLES / large phones (481–680 wide): the wide (2.36:1) cutaway in a short full-width band
   renders the marble floor as a big slab with a tiny drain underneath — and a taller band can't fix that (the
   floor is an inherent ~30% of the image height). FIX: ZOOM the drain scene with a CSS transform on #media,
   transform-origin ON the drain, so the drain is the star and most of the floor is cropped. The plate (CSS
   object-fit:cover) and the fx layer (cover()-positioned) are BOTH children of #media, so they scale together
   and stay matched; cover() reads the UN-transformed box (offsetWidth/Height) so the framing math is unaffected.
   The LAYOUT height is un-transformed, so the products-sheet teaser overlap still works. overflow:hidden clips
   the zoomed-out floor. Guarded min-height:600 → a phone in LANDSCAPE (short) keeps the safe un-zoomed band. ---- */
@media (min-width: 481px) and (max-width: 680px) and (min-height: 600px) {
  .drain-media { height: clamp(280px, 54vw, 360px); overflow: hidden;
    /* white fade on the LEFT edge (like the other breakpoints) + a soft top edge into the copy. On the band
       container (not the panned content) so the fade stays put regardless of the inner pan/zoom. */
    -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 14%, #000 100%), linear-gradient(to bottom, transparent 0%, #000 8%, #000 100%);
    -webkit-mask-composite: source-in;
            mask-image: linear-gradient(to right, transparent 0%, #000 14%, #000 100%), linear-gradient(to bottom, transparent 0%, #000 8%, #000 100%);
            mask-composite: intersect; }
  .drain-zoom { transform-origin: 50% 50%; transform: translate(4px, -70px) scale(1); }  /* Chris-tuned framing 2026-06-22 (DEBUG_FOLD) */
  .plate, .plate-fallback, .fx { -webkit-mask-image: none; mask-image: none; }  /* fade lives on the band container now */
}

/* ---- PHONES ≤480: same idea as the foldable — the plain band shows a marble-floor slab with a small drain.
   PAN the drain scene UP to crop the floor (as a %, so one value works across 360–430), + left/top fade on the
   band container. Particles are already right-sized via dscale. Pan %, not px, because the band height varies
   with viewport height across phones. ---- */
@media (max-width: 480px) {
  .drain-media { overflow: hidden;
    -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 12%, #000 100%), linear-gradient(to bottom, transparent 0%, #000 8%, #000 100%);
    -webkit-mask-composite: source-in;
            mask-image: linear-gradient(to right, transparent 0%, #000 12%, #000 100%), linear-gradient(to bottom, transparent 0%, #000 8%, #000 100%);
            mask-composite: intersect; }
  .drain-zoom { transform-origin: 50% 50%; transform: translate(0, -24%) scale(1); }  /* crop the floor slab (first pass — tune via DEBUG_FOLD) */
  .plate, .plate-fallback, .fx { -webkit-mask-image: none; mask-image: none; }
  /* (roach sprite centering is now GLOBAL on the base .bug rule — applies here too) */
  /* Keep "Shop Products" + "Find Your Industry" on ONE row on narrow phones (they wrapped below ~390px; Chris wants
     them side-by-side like the S20 Ultra). Grouped LEFT (flex-start, not spread to the edges) + compact so they
     clear the right edge even on the narrowest common phone (Galaxy S9+ 320). */
  .hero-ctas { display: flex; flex-wrap: nowrap; justify-content: flex-start; gap: 10px; align-items: center; }
  .hero-ctas .btn-primary { padding-left: 18px; padding-right: 18px; white-space: nowrap; }
  .hero-ctas .btn-text { white-space: nowrap; }
}

/* ---- SHORT/MID phones (iPhone SE 375×667, Samsung Galaxy S8+ 360×740, etc.): copy + band + products are cramped
   and the hero sits too far down the screen. Shrink the copy + pull it up (Chris) + ease the teaser overlap so the
   drain isn't clipped. max-height 780 catches the S8+ (740) too; taller phones (iPhone 12 844 / S20U 915, ✓approved)
   keep the full-size copy. ---- */
@media (max-width: 480px) and (max-height: 780px) {
  .hero { padding-top: 18px; }
  .hero-label { margin-bottom: 10px; }
  .hero-headline { font-size: 1.7rem; margin-bottom: 10px; }
  .hero-subtitle { font-size: 0.9rem; line-height: 1.45; margin-bottom: 14px; }
  .products-section { margin-top: -10vh; }  /* rise to MEET the drain image — covers the cream sliver the pan-up leaves at the band bottom (the "white bar"), without reaching the U-bend */
}
