/* HERO FIX ONLY. Load after existing styles.css. Original product tiles are untouched. */
.hero.brandable-hero{display:grid;grid-template-columns:48% 52%;align-items:center;isolation:isolate;max-width:1440px;width:100%;margin-inline:auto;background:#fff;overflow:visible;min-height:660px}
.hero.brandable-hero .hero-copy{padding:64px 0 48px clamp(24px,4.16vw,60px);z-index:2;transform:none!important;opacity:1!important;will-change:auto}
.hero.brandable-hero h1{font-size:clamp(42px,4.4vw,66px);line-height:1.02;letter-spacing:-.06em;white-space:nowrap}
.hero.brandable-hero .hero-copy>p:not(.handwritten){max-width:525px;margin:28px 0;font-size:clamp(20px,1.9vw,27px);line-height:1.35}
.hero.brandable-hero .hero-actions{gap:24px;flex-wrap:wrap}
.hero.brandable-hero .hero-copy>.handwritten{margin:84px 0 12px 12px}
.hero.brandable-hero .scroll-cue{display:none}
.hero.brandable-hero .brandable-hero-art{width:115%;margin-left:-15%;position:relative;z-index:1;align-self:center;pointer-events:none;background:#fff}
.hero.brandable-hero .brandable-hero-art img{position:static;display:block;width:100%;max-width:100%;height:auto;object-fit:contain;/* No cover, screenshot crop, negative image offsets, or clipped container. */mask-image:linear-gradient(to right,transparent,#000 2%,#000 98%,transparent);-webkit-mask-image:linear-gradient(to right,transparent,#000 2%,#000 98%,transparent)}
@media(min-width:1440px){.hero.brandable-hero{min-height:790px}}
@media(max-width:1100px) and (min-width:801px){.hero.brandable-hero{min-height:580px}.hero.brandable-hero .hero-copy{padding-block:44px}.hero.brandable-hero .hero-copy>.handwritten{margin-top:54px}.hero.brandable-hero .hero-actions{gap:16px}}
@media(max-width:800px){.hero.brandable-hero{display:flex;flex-direction:column;min-height:0;overflow:visible}.hero.brandable-hero .hero-copy{width:100%;padding:34px 24px 12px}.hero.brandable-hero h1{font-size:clamp(37px,7.6vw,61px);white-space:normal}.hero.brandable-hero .hero-copy>p:not(.handwritten){font-size:22px;margin:24px 0;max-width:560px}.hero.brandable-hero .hero-copy>.handwritten{display:none}.hero.brandable-hero .brandable-hero-art{width:100%;max-width:660px;margin:0 auto;max-height:none;aspect-ratio:auto}.hero.brandable-hero .brandable-hero-art img{width:100%;height:auto;max-height:none;object-fit:contain}.hero.brandable-hero .hero-actions{gap:18px}}
@media(max-width:520px){.hero.brandable-hero .hero-copy{padding-inline:20px}.hero.brandable-hero .hero-actions{align-items:flex-start;flex-direction:column;gap:12px}}

/* <picture> added for WebP delivery: keep it laying out exactly like the bare <img> did. */
.hero.brandable-hero .brandable-hero-art picture{display:block;width:100%}

/* ---------------------------------------------------------------------------
   HERO MOTION v2 — light sweeping through the whole composition.

   v1 bug, fixed here: a `.hero.brandable-hero > *` rule beat the layers' own
   `position:absolute`, so they became items of the 2-column grid, collapsed to
   zero height, and `overflow:hidden` clipped them to nothing. Nothing rendered.
   The layers are out of flow now and must stay that way.

   Design rules this hero has already taught us:
     - the copy side reads WHITE. Motion may cross it, static colour may not.
     - the composition is one unit: the copy never moves against the photo.
   All decorative, all disabled under reduced motion.
--------------------------------------------------------------------------- */
.hero.brandable-hero{position:relative}

/* Specular sweep. Travels the full hero, copy column included, as moving light
   rather than a colour field, which is why it cannot read as a left/right split. */
.hero-streak{position:absolute;inset:0;z-index:3;pointer-events:none;overflow:hidden;opacity:0}
html.motion .hero-streak{opacity:1}
.hero-streak::before,.hero-streak::after{content:"";position:absolute;left:0;top:-32%;bottom:-32%;
  transform:translateX(-170%) rotate(-13deg);will-change:transform}
/* Tints only, no white core. On a white hero a bright core cannot read as a
   highlight, it just washes the black headline to grey as it passes. Every stop
   is under 6% alpha, which is clearly visible on white and invisible on #090909. */
.hero-streak::before{width:44%;
  background:linear-gradient(102deg,transparent,rgba(6,72,223,.050) 36%,rgba(90,120,255,.058) 50%,rgba(242,190,213,.050) 64%,transparent)}
.hero-streak::after{width:24%;
  background:linear-gradient(102deg,transparent,rgba(255,107,39,.038) 50%,transparent)}
html.motion .hero-streak::before{animation:hsweep 13s cubic-bezier(.45,0,.35,1) infinite}
html.motion .hero-streak::after{animation:hsweep 13s cubic-bezier(.45,0,.35,1) 1.15s infinite}
@keyframes hsweep{0%{transform:translateX(-170%) rotate(-13deg)}
                  62%,100%{transform:translateX(430%) rotate(-13deg)}}

/* The product breathes, and its shadow breathes with it so it stays grounded. */
html.motion .hero.brandable-hero .brandable-hero-art{animation:hfloat 7.5s ease-in-out infinite}
.hero.brandable-hero .brandable-hero-art img{filter:drop-shadow(0 26px 34px rgba(9,14,38,.10))}
html.motion .hero.brandable-hero .brandable-hero-art img{animation:hshadow 7.5s ease-in-out infinite}
@keyframes hfloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-13px)}}
@keyframes hshadow{0%,100%{filter:drop-shadow(0 26px 34px rgba(9,14,38,.10))}
                   50%{filter:drop-shadow(0 40px 44px rgba(9,14,38,.07))}}

/* Pointer parallax on the product. Driven by hero-motion.js through these
   variables so it composes with the float instead of fighting it. */
.hero.brandable-hero .brandable-hero-art picture{will-change:transform;
  transform:translate3d(var(--tx,0px),var(--ty,0px),0) rotate(var(--tr,0deg));
  transition:transform .5s cubic-bezier(.22,.75,.3,1)}
@media(hover:none),(pointer:coarse){
  .hero.brandable-hero .brandable-hero-art picture{transform:none!important}}

@media(prefers-reduced-motion:reduce){
  .hero-streak{display:none}
  .hero.brandable-hero .brandable-hero-art,
  .hero.brandable-hero .brandable-hero-art img{animation:none!important}
  .hero.brandable-hero .brandable-hero-art picture{transform:none!important;transition:none}
}

/* ---------------------------------------------------------------------------
   HERO v3 — the card-stack film, INSIDE the hero.

   First cut of this stacked the copy above a rounded, shadowed film. Owner:
   "i dont like that you made the video a standalone and not a part of a header
   like before." Correct — a bordered box below the copy reads as a separate
   block, not as one banner. The film goes back into the 48/52 grid the still
   life used, bleeding to the right edge with a masked left edge, so it is one
   composition again.

   The clip is a ONE-SHOT reveal: it opens on bare paper, the cards fly in and
   land, and it holds. Looping would snap the hero back to an empty white frame
   every few seconds, so there is deliberately no `loop`.

   SPECIFICITY: the v2 rules above are `.hero.brandable-hero .x` (0,3,0). Any
   override here must match or beat that — a shorter selector loses silently and
   the layout quietly reverts. This has now bitten twice.
--------------------------------------------------------------------------- */
/* The film is 16:9, the still life was square, so the hero no longer needs to be
   tall enough for a square. Let the content set the height. */
.hero.brandable-hero{min-height:0}
@media(min-width:1440px){.hero.brandable-hero{min-height:0}}

/* All four edges are feathered, because the film's paper is not the page white:
   measured, the top edge steps 255 -> 240 and the bottom 230 -> 255, both plainly
   visible as a rectangle. Cards occupy 7.7-91.5% across and 9.7-93.4% down, so
   these fades only ever eat bare paper.
   The two axes live on different elements ON PURPOSE. One element cannot carry
   two mask gradients without `mask-composite`, whose keywords differ between
   WebKit and the standard; nesting composes them with no compatibility risk. */
/* The old seam masks are gone. They existed to hide grey paper against a white
   page; the film is flat-fielded now (paper 254 against a 255 page), so all they
   did was soften the settled cards. Edge handling is the timed overlay below. */
.hero.brandable-hero .brandable-hero-art{position:relative}
.hero.brandable-hero .hero-video,
.hero.brandable-hero .brandable-hero-art picture>img{
  display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;
  background:transparent;border-radius:0;box-shadow:none}

/* Cards fly in from outside the render and get razor-cut by its frame edge.
   Measured: a card touches some edge on every frame from 0.35s to 6.35s, the top
   edge for up to 52% of its length, so no trim avoids it and the footage outside
   the frame does not exist. What CAN be fixed is the hard cut: this white
   vignette dissolves cards as they reach the boundary instead, then clears once
   the film settles so the finished stacks are perfectly crisp. */
.hero.brandable-hero .brandable-hero-art::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:
    linear-gradient(to right,#fff,rgba(255,255,255,0) 8%,rgba(255,255,255,0) 92%,#fff),
    linear-gradient(to bottom,#fff,rgba(255,255,255,0) 9%,rgba(255,255,255,0) 91%,#fff);
  opacity:1;transition:opacity .8s cubic-bezier(.3,.7,.3,1) .1s}
.hero.brandable-hero .brandable-hero-art.is-settled::after{opacity:0}
@media(prefers-reduced-motion:reduce){
  .hero.brandable-hero .brandable-hero-art::after{display:none}}
.hero.brandable-hero .brandable-hero-art picture{display:block;width:100%}

/* The film carries the motion. No float or pointer tilt on it; the light sweep
   stays, it reads across the whole hero. */
html.motion .hero.brandable-hero .brandable-hero-art{animation:none}
.hero.brandable-hero .hero-video{transform:none!important;transition:none}

@media(max-width:800px){
  /* Film FIRST on a phone. Stacked under the copy it read as an afterthought;
     leading with the product is the stronger opening on a narrow screen. */
  .hero.brandable-hero .brandable-hero-art{order:-1;width:100%;max-width:none;margin:0}
  .hero.brandable-hero .hero-copy{padding-top:18px}
  .hero.brandable-hero{padding-top:8px}
}
/* The hero's handwritten line takes the cyan card's colour. NOT the card value
   itself: #1ECBF2 is 1.93:1 on white and fails even the large-text threshold,
   and Caveat is a script, so it needs more contrast than a bold face rather than
   less. Same hue at 80% brightness clears 3:1 and still reads as the bright one.
   Scoped to the hero on purpose - the other .handwritten line sits on the cobalt
   services band, where cyan would be unreadable. */
.hero.brandable-hero .hero-copy>.handwritten{color:var(--cyan-ink,#0EA1C2)}
/* Second line of the hero headline picks up the same cyan as the handwriting.
   Safe at this size: it is 72px at weight 900, so the 3:1 large-text threshold
   applies and --cyan-ink clears it. The first line stays ink for contrast. */
.hero.brandable-hero h1 .h1-accent{color:var(--cyan-ink,#0EA1C2)}

