/* ==========================================================================
   sHTG Hero Video — TRYN-1318.

   DELTAS ONLY. The component's root carries `shtg-hero shtg-hero--campaign`
   as well as `shtg-hero--video`, so it inherits the whole of
   components/shtg-hero/shtg-hero.css (loaded through the `tryngolza/shtg-hero-base`
   library, which is why nothing under components/shtg-hero/ is touched):
   the single-grid-cell stacking model, the copy grid, all the supporting-copy
   typography, the whole CTA, and — critically — the entire <=1024px and <=600px
   blocks verbatim. That inheritance is what makes the small-screen rendering
   identical to the static hero.

   Everything below is scoped inside `.layout-container` (page.html.twig:49),
   which also lifts every selector to 0,3,0 and therefore beats the inherited
   0,2,0 rules regardless of stylesheet order.

   Bands:
     <=1024px          portrait composite, no video request
     1025-2799.98px    video
     >=2800px          ultrawide still at a flat 40.85rem, no video request

   The 2799.98px/2800px boundary is character-identical here and in BAND in
   shtg-hero-video.js. If one moves, both move, or the JS arms a video the CSS
   has already hidden.

   THE WHOLE POINT OF THIS FILE: the media box has a height of its own and the
   clip fills it with `object-fit: cover`, so the frame is scaled to the box
   rather than the box computed from the frame — at ANY aspect ratio. A new cut
   from the agency therefore changes nothing here. There is no crop ladder, no
   frame-height constant, no zoom/pan pair and no per-asset breakpoint, because
   none of those can be written without knowing the asset. The predecessors of
   this file had all four and each one had to be re-derived per delivery.

   `object-position: 50% 100%` then pins the frame's BOTTOM edge to the box, so
   the whole discarded height comes off the sky at the top and the baked brand
   arc is never touched — at every width AND every aspect ratio. That is an
   invariant, not a budget, and it is load-bearing: the arc dives from the frame's
   side edges toward the centre and exits through the frame's own bottom edge
   (measured on frame 95: 80.3%-89.6% of frame height at x=0, 99.4%-99.9% at
   x=50%). A 4.51% bottom trim — what `50% 70%` cost between cd6cdbbce and this
   file — removed the arc outright across the central 51.8% of the width, leaving
   only the two rising ends. Never trim the bottom.
   ========================================================================== */

/* --- Tokens --------------------------------------------------------------
   Two values, and only the first is ever likely to move. */
.layout-container .shtg-hero--video {
  /* Hero height in the video band. A design constant, deliberately NOT derived
     from the asset.

     With the delivered master (3840x2282 -> frame height 59.43vw at full bleed)
     the box discards 6.43vw of frame height at every width above 1144px, and
     `object-position: 50% 100%` puts all of it on the top: a 10.82% crop off
     the sky, nothing off the arc.

     Measured on all 96 frames of Tryngolza_WebsiteHeader_C001_05.mp4, the
     subject's highest point — the raised fist — sits at 17.1% of frame height
     in the tightest frame, so the crop clears it by 6.3 points.

     53vw is what it costs to keep that top framing while pinning the arc: 50.5vw
     with a 70/30 split gave the same 10.5% top crop but cut the arc, and 50.5vw
     bottom-pinned protects the arc but crops 15.02% off the top, leaving the
     subject only 2.1 points of clearance.

     The 608px floor binds from 1025px to 1144px, where the box aspect meets the
     frame's and the crop falls to ~0. The copy block needs 549.4px (measured),
     so the floor clears it with room to spare.

     THIS IS THE ONE NUMBER a new cut can invalidate, in two ways, both visible
     at a glance and neither needing a script:
       - a cut that frames the subject higher than 10.8% of frame height gets
         clipped -> raise this value;
       - a master WIDER than ~1.89:1 stops being width-limited, at which point
         `cover` crops the sides instead and cuts the ends off the baked arc
         -> raise this value.
     The arc's bottom is NOT one of them, and must not become one: bottom-pinning
     protects it at any aspect. */
  --shtg-hero-video-height: max(608px, 53vw);

  /* Painted under the media, so the band is never a blank rectangle: visible
     before the first video frame decodes, and for the whole visit when no
     poster is set and autoplay is refused. Sampled from the clip's own final
     frame at the rows the crop leaves visible (15%, 45%, 62%, 88% of frame
     height), so the handover to the video is not a colour jump. */
  --shtg-hero-video-fill: linear-gradient(
    180deg,
    #6d9eba 0%,
    #c7babc 35%,
    #ddc0b6 55%,
    #c4a4b1 90%,
    #b48fae 100%
  );

  /* Where the copy column starts. The AD did object to the empty desert below
     the CTA, so this now centres the copy in the media box instead of holding a
     flat 83px, and grows with the box.

     Three terms, outermost last:

       26.5vw - 233px   centres a 466px copy block in the 53vw box:
                        (53vw - 466px) / 2. The 466px is measured and constant
                        at every width >=1280px, where the headline clamps have
                        all topped out; below that the floor takes over anyway.

       100vh - 714px    the ISI ceiling, and the reason there is a vh term in an
                        otherwise vw-driven file: the ISI is fixed to the
                        VIEWPORT bottom, not to the hero, so the constraint is
                        genuinely viewport-height-based.

                        466 copy + 132 ISI peek + 40 breathing room + 76 = 714.
                        That last 76px is the header sitting ABOVE the hero, so
                        the copy starts 76px down the viewport rather than at 0
                        — measured identical at 1440/1920/2560/3400. Omitting it
                        put the CTA 36px UNDER the ISI at 1920x800; it is the
                        third thing that can invalidate this value, alongside the
                        466 and the 132, and the only one not visible from
                        inside this component.

                        Binds on short wide windows — 1920x800 and 2799x1200
                        land here, not on the centring term.

       max(83px, ...)   never rise above the original position. Guarantees this
                        change can only ever move the copy DOWN, so no window
                        that reads correctly today can regress.

     Centring overtakes the 83px floor at 1192px (26.5vw - 233px > 83px) and
     grows from there; below that the floor holds and nothing changes. */
  --shtg-hero-video-content-top: max(83px, min(26.5vw - 233px, 100vh - 714px));
}

/* --- Media box -----------------------------------------------------------
   `align-self: stretch` overrides the inherited `start`, so the box can never
   end up shorter than the copy that overlays it — if the copy ever outgrows the
   height token, the background grows with it instead of leaving an unpainted
   band. `min-height` (not `height`) is what makes that true.

   `margin-top: 0` is load-bearing: the static hero pulls its background up with
   an accelerating negative margin at 1280/1400/2000/2400px to crop sky
   (shtg-hero.css:299-326). That whole ladder is inherited here and would fight
   the cover crop, which already does the same job asset-independently. */
@media (min-width: 1025px) {
  .layout-container .shtg-hero--video .shtg-hero__bg {
    align-self: stretch;
    min-height: var(--shtg-hero-video-height);
    margin-top: 0;
    background: var(--shtg-hero-video-fill);
  }

  /* Poster and clip, framed identically. They must agree exactly, or the
     fade-in at playback start becomes a visible jump.

     `object-position: 50% 100%` is the whole framing strategy: the frame's
     bottom edge — where the brand arc is baked, and where it exits the frame at
     the centre — is pinned to the box's bottom edge, so the arc lands whole
     whatever the asset's proportions are and the crop comes off the top, which
     is sky. The height token is what buys the top framing; this declaration is
     what protects the arc. Do not trade it away. */
  .layout-container .shtg-hero--video .shtg-hero__bg-img,
  .layout-container .shtg-hero--video .shtg-hero__video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 100%;
  }

  /* No poster set: the base <img> is the <=1024px portrait composite, whose crop
     is wrong for this band, so it is hidden and the brand fill shows through
     until the first video frame decodes. */
  .layout-container .shtg-hero--video .shtg-hero__bg-img--portrait-only {
    display: none;
  }

  .layout-container .shtg-hero--video .shtg-hero__content {
    padding-top: var(--shtg-hero-video-content-top);
  }
}

/* --- Headline ------------------------------------------------------------
   Nothing to override. The headline is live HTML at every width and inherits
   the static hero's treatment wholesale — the three art-directed lines, the
   -3deg rotation, the blurred gradient understudy and the responsive clamps
   (shtg-hero.css:90-153, plus the <=1024px sizes at :371-380).

   It is deliberately NOT baked into the video and NOT hidden: real text keeps
   WCAG 1.4.5 (images of text) and 1.4.4 (resize to 200%) satisfied, and the
   headline survives a refused autoplay, when only the poster is ever painted. */

/* --- Video layer ---------------------------------------------------------
   Starts transparent and fades in once playback actually starts; if autoplay is
   refused the element simply stays invisible and the poster (or the fill)
   remains.

   `pointer-events: none` is load-bearing: it keeps the CTA clickable across the
   whole media box. z-index 1 sits above the <img> inside `.shtg-hero__bg`
   (itself z-index 0) and below both `.shtg-hero__actor` (z-index 2) and
   `.shtg-hero__inner` (z-index 1 at section level, later in the DOM). */
.layout-container .shtg-hero--video .shtg-hero__video {
  display: none;
}

@media (min-width: 1025px) {
  .layout-container .shtg-hero--video .shtg-hero__video {
    display: block;
    opacity: 0;
    transition: opacity 200ms linear;
    pointer-events: none;
    z-index: 1;
  }

  .layout-container .shtg-hero--video .shtg-hero__video.is-visible {
    opacity: 1;
  }
}

/* --- Ultrawide still band -------------------------------------------------
   >=2800px swaps the clip for a purpose-made still. The master is 3840px wide,
   so past ~2800px of box width it is being upscaled and softens on exactly the
   displays big enough to show it — and it is 7.6MB to do so.

   The still is cut for THIS band, not borrowed from the video: 3200x655
   (4.885:1) against a box that runs 4.28:1 at 2800px to 5.26:1 at 3440px, so
   `cover` trims the sides at the narrow end and a little sky at the wide end.
   A frame cut at the video's 1.68:1 would lose about two thirds of its height
   here and keep only a strip of ground.

   It is masked to the arc: the corners below the arc are transparent by design
   and the page background shows through them.

   The <picture> in the Twig serves the file; the two rules here only settle who
   is visible. BAND in shtg-hero-video.js excludes this band, so the video is
   never armed and costs nothing. */
@media (min-width: 2800px) {
  .layout-container .shtg-hero--video {
    /* The spec puts the ultrawide band at a flat 40.85rem, not 53vw. It is a
       short wide strip rather than a scaled-up version of the video band, so
       the height stops tracking the viewport here and the box aspect goes from
       1.887:1 to 4.28:1 at 2800px, widening further from there.

       This is what the ultrawide asset has to be cut for: at this aspect a
       1.68:1 frame loses almost all of its height off the top and keeps only a
       sliver of ground. See the note above the picture element in the Twig. */
    --shtg-hero-video-height: 40.85rem;

    /* Re-centre against the new height: (40.85rem - 466px) / 2 = 93.8px. No ISI
       ceiling here — that term guards a box whose height tracks the viewport,
       and this one is fixed at 654px, so the copy cannot reach the ISI. */
    --shtg-hero-video-content-top: max(83px, (40.85rem - 466px) / 2);
  }

  /* The still is masked to the arc, so its bottom corners are transparent and
     the page's own background is what shows through them — which is the Figma
     comp. The brand fill from the video band would show there instead, so it
     comes off. */
  .layout-container .shtg-hero--video .shtg-hero__bg {
    background: none;
  }

  /* The base <img> is hidden across the video band when no poster is set (see
     above). Here it is the ultrawide still, so it comes back. The
     `--portrait-only` name predates this band and now undersells itself: it
     means "the no-poster fallback image", and it serves two bands, not one. */
  .layout-container .shtg-hero--video .shtg-hero__bg-img--portrait-only {
    display: block;
  }

  .layout-container .shtg-hero--video .shtg-hero__video {
    display: none;
  }
}

/* --- "Actor portrayal." --------------------------------------------------
   The inherited rule sets `display: none` (shtg-hero.css:67). Re-enabled only
   in the video band, so the <=1024px rendering stays untouched.

   The offsets come from two props, defaulted in the Twig, and are anchored to
   the box's BOTTOM-right — the edge the frame is pinned to, so a bottom offset
   in vw tracks the numerals at every width with no breakpoint and no crop term.
   They are authored rather than derived on purpose: the label annotates numerals
   baked into the frame, and every new cut reframes them. Nothing here can be
   computed once and trusted. (The 17.7vw default is 2.7vw lower than the 15vw
   used while the frame was trimmed at the bottom: re-pinning the frame moves the
   numerals down with it.) */
@media (min-width: 1025px) {
  .layout-container .shtg-hero--video .shtg-hero__actor {
    display: block;
    top: auto;
    right: var(--shtg-hero-video-actor-right, 11.5%);
    bottom: var(--shtg-hero-video-actor-bottom, 17.7vw);
    z-index: 2;
  }
}

/* Ultrawide band. `actor_bottom` is authored as 17.7vw against the 53vw box; on
   this 654px one that is 601px at 3400px wide and throws the label to the top of
   the frame. `bottom` has to be overridden directly — the prop writes a custom
   property inline, and an inline value cannot be beaten by redefining it in a
   stylesheet.

   This block must stay AFTER the rule above: both selectors score 0,3,0 and a
   media query adds nothing, so order is the only thing deciding it.

   Both values put the label directly under the numerals, per the comp, and both
   are AUTHORED against this particular cut rather than derived — they annotate
   numerals baked into the frame, so a new ultrawide cut reframes them and these
   move with it.

   Measured on the asset: the 184 / mg-dL group spans x 1730-2115 of 3200 (centre
   60.1%) and its bottom sits 135px above the frame's bottom edge.

     bottom: 17%   = 111px. The group's bottom lands 134px above the box bottom
                     at 2800px and 143px at 3400px, so the label clears it by
                     9-18px once its own 14px line box is counted.
     right: 38%    centres the label's ~78px width under the group. The group's
                     centre maps to 37.1% from the right at 2800px, where `cover`
                     trims the sides, and 38.8% at 3400px and above, where it
                     trims sky instead. 38% splits that. */
@media (min-width: 2800px) {
  .layout-container .shtg-hero--video .shtg-hero__actor {
    right: 38%;
    bottom: 17%;
  }
}

/* --- Copy entrance -------------------------------------------------------
   The eight copy elements fade up and slide in from the left, in reading order,
   once on load. Option B of three reviewed by the client; see
   docs/plans/shtg-hero-text-animations/.

   Independent of video state on purpose: the copy must arrive normally when the
   clip never plays (<=1025px, autoplay refused, Data Saver, reduced motion), and
   `ended` would hide the H1 for four seconds.

   `both` fill applies the from-state through the delay, so nothing is painted
   opaque and then yanked back. Opacity and transform only, which leaves the
   headline's gradient understudy (`::before`) untouched and stays off the layout
   path. */
.layout-container .shtg-hero--video .shtg-hero__title-line,
.layout-container .shtg-hero--video .shtg-hero__lead,
.layout-container .shtg-hero--video .shtg-hero__subtext,
.layout-container .shtg-hero--video .shtg-hero__rule,
.layout-container .shtg-hero--video .shtg-hero__detail,
.layout-container .shtg-hero--video .shtg-hero__cta {
  animation-name: shtg-hero-video-copy-in;
  animation-duration: 650ms;
  animation-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1);
  animation-fill-mode: both;
  /* 100ms stagger; the fallback holds an un-indexed element at 0s. */
  animation-delay: calc(var(--shtg-hero-video-copy-step, 0) * 100ms);
}

/* Reading order, top to bottom. Renumber here and nowhere else. */
.layout-container .shtg-hero--video .shtg-hero__title-line--1 { --shtg-hero-video-copy-step: 0; }
.layout-container .shtg-hero--video .shtg-hero__title-line--2 { --shtg-hero-video-copy-step: 1; }
.layout-container .shtg-hero--video .shtg-hero__title-line--3 { --shtg-hero-video-copy-step: 2; }
.layout-container .shtg-hero--video .shtg-hero__lead          { --shtg-hero-video-copy-step: 3; }
.layout-container .shtg-hero--video .shtg-hero__subtext       { --shtg-hero-video-copy-step: 4; }
.layout-container .shtg-hero--video .shtg-hero__rule          { --shtg-hero-video-copy-step: 5; }
.layout-container .shtg-hero--video .shtg-hero__detail        { --shtg-hero-video-copy-step: 6; }
.layout-container .shtg-hero--video .shtg-hero__cta           { --shtg-hero-video-copy-step: 7; }

/* The headline travels further so the big type leads.

   ITS KEYFRAMES MUST CARRY rotate(-3deg) (rest angle, shtg-hero.css:88-95). A
   filling animation replaces the inherited transform outright, so a keyframe
   without it snaps all three lines flat on landing. */
.layout-container .shtg-hero--video .shtg-hero__title-line {
  animation-name: shtg-hero-video-title-in;
}

@keyframes shtg-hero-video-copy-in {
  from { opacity: 0; transform: translateX(-40px); }
  to   { opacity: 1; transform: translateX(0); }
}

@keyframes shtg-hero-video-title-in {
  from { opacity: 0; transform: translateX(-56px) rotate(-3deg); }
  to   { opacity: 1; transform: translateX(0) rotate(-3deg); }
}

/* --- Canvas edit mode ----------------------------------------------------
   Canvas re-renders on every property change, which would replay the entrance
   each time. Editors get the resting state. 0,3,1 beats the 0,3,0 above, so no
   !important is needed. */
body.path-canvas .shtg-hero--video .shtg-hero__title-line,
body.path-canvas .shtg-hero--video .shtg-hero__lead,
body.path-canvas .shtg-hero--video .shtg-hero__subtext,
body.path-canvas .shtg-hero--video .shtg-hero__rule,
body.path-canvas .shtg-hero--video .shtg-hero__detail,
body.path-canvas .shtg-hero--video .shtg-hero__cta {
  animation: none;
}

/* --- Reduced motion ------------------------------------------------------
   Reduced-motion visitors are never served the video at all (the JS refuses to
   arm), so the fade and the copy entrance both go.

   Killing the animation is enough: nothing outside the keyframes sets opacity,
   and the headline's rotate(-3deg) returns from the inherited rule. Do NOT add
   `transform: none` here — that is what would flatten the lines. */
@media (prefers-reduced-motion: reduce) {
  .layout-container .shtg-hero--video .shtg-hero__video {
    transition: none;
  }

  .layout-container .shtg-hero--video .shtg-hero__title-line,
  .layout-container .shtg-hero--video .shtg-hero__lead,
  .layout-container .shtg-hero--video .shtg-hero__subtext,
  .layout-container .shtg-hero--video .shtg-hero__rule,
  .layout-container .shtg-hero--video .shtg-hero__detail,
  .layout-container .shtg-hero--video .shtg-hero__cta {
    animation: none;
  }
}
