/* ============================================================
   HERO — the two-frame slideshow
   Front page only. Loaded after main.css.

   Why this is a separate file rather than a rule inside main.css:
   main.css was owned by another agent when this was written, and two
   agents editing one stylesheet is the cascade collision this project
   has lost work to four times. The same reasoning produced figures.css.

   Why a new class rather than a second .hero-bg:
   .hero-bg carries `opacity: 1 !important`. A CSS animation loses to an
   !important declaration, so an alt layer sharing that class could never
   fade. A distinct class sidesteps the fight entirely — no !important is
   needed anywhere in this file.

   R14 note: the supplied hero was originally out of scope. The client
   opened it himself on 23 August — "keep that already existing image too,
   but also add this image as a 2 second slideshow." His call, his hero.
   ============================================================ */

/* The second frame. Sits directly above .hero-bg (z-index auto) and below
   .hero::before (z-index 1), so both gradient scrims and all the copy stay
   exactly where they were. Nothing about the existing hero is modified —
   if this file fails to load, the hero renders precisely as it did before. */
.hero .cz-hero-frame {
  position: absolute;
  inset: 0;

  /* z-index 1, deliberately — ABOVE .hero::before, BELOW the copy.
     Measured stack in main.css:
       .hero-bg        z-index auto   base image + its own heavy gradient
       .hero::before   z-index 1      solid black 0-29%, .82 at 43%, clear at 64%
       .cz-hero-frame  z-index 1      THIS — same level, later in paint order
       .hero-inner     z-index 2      the copy (main.css:1211)
       .hero-copy      z-index 2      (main.css:1221)

     At z-index 0 this layer sat UNDER the scrim, and the scrim is opaque black
     across exactly the region the two figures occupy — the man at ~28% across,
     the Burj at ~45%, the woman at ~55%. The photograph rendered, animated and
     measured correctly and was still invisible. Twice.

     Raising it to 1 puts it above the scrim; the copy at 2 still sits above it,
     so the headline is untouched. This layer now carries its own scrim, below. */
  z-index: 1;
  pointer-events: none;

  /* NO GRADIENT ON THIS LAYER. This was wrong in the first version and the
     client caught it — the image was invisible.

     The stack, bottom to top:
       .hero-bg        image + a 99%/95%/84% black gradient   (z-index auto)
       .cz-hero-frame  THIS layer                             (z-index 0)
       .hero::before   linear-gradient(90deg, …)              (z-index 1)

     `.hero::before` is SOLID black from 0% to 29%, still .82 at 43%, and only
     reaches transparent at 64%. It sits ABOVE this layer, so it already
     supplies every bit of scrim the headline needs.

     Copying .hero-bg's gradient in here darkened the photograph twice over.
     The two figures sit at roughly 28% and 55% across the frame — the first
     under solid black, the second under .82 black plus another .95 from the
     duplicated gradient. The image was rendering, animating and measurable,
     and still could not be seen. Bottom layers carry the scrim; a layer above
     one must not repeat it. */
  /* Its own scrim, and a far gentler one than the layer below.

     Because this frame now sits ABOVE .hero::before, nothing else darkens it —
     so the scrim here is the only thing standing between the photograph and
     the headline, and it has to do two jobs that pull against each other:
     keep white type legible on the left, and let three specific things be seen.

     The client named them: the man (~28% across), the woman (~55%) and the
     Burj Khalifa behind them (~45%). The old scrim put the first two under
     solid black. This one holds .86 under the first words of the headline,
     is down to .40 by the time it reaches the man, .16 at the Burj, and fully
     clear before the woman. The headline is 60px+ and 800 weight — it survives
     .40 comfortably; a body paragraph would not, and there is none here. */
  background-image:
    /* RE-RAMPED 1 Sep. The client asked for the left dimmed harder while the
       man, the woman and the etched pin all stay visible. The old ramp did
       the opposite of both halves: it held only .86 under the headline, and
       it was still at .40 when it reached the man at 28% — so the type was
       under-protected and the subject he wants seen was the one being
       dimmed. Steeper at the left, clear earlier across the middle:
         0-12%   .94 to .86   the headline and standfirst sit here
         22%     .58          falling away before the man
         30%     .26          the man, now readable (was .40)
         44%     .10          the Burj
         56%     .02          the woman, effectively clear
         68%     0            the pin etched on the glass
       The headline is 60px+ at weight 800 and survives .26 comfortably;
       the standfirst below it is body-sized, which is why the first stop
       is held flat to 12% rather than ramping immediately. */
    /* RE-RAMPED AGAIN 2 Sep, because the first re-ramp was not enough and the
       client said so. Two things were wrong with it.

       ONE: this layer sits at z-index 1 and LATER IN PAINT ORDER than
       .hero::before, so it is the only scrim the headline gets. .hero-bg
       below is protected by ::before (solid black to 29%); this frame is not
       protected by anything except the stops below. I had been reasoning as
       though the shared scrim helped here. It does not.

       TWO: the headline runs from 2% to 31% across, and the previous ramp
       was already down to .26 at 30% — so the last third of "Move with
       clarity." sat on a brightly lit white kandura at barely a quarter
       cover. Measured, not guessed: the copy block spans x 2-31%.

       The three things he wants seen, from the source comment above: the man
       at ~28% across, the Burj at ~45%, the woman at ~55%, and the pin
       etched on the glass at ~67%.

       So the ramp is now HARD through the type zone and clears FASTER once
       past it, rather than sloping gently across both:
         0-14%    .96 to .93   the full width of the headline start
         22%      .74          still behind type
         30%      .40          the man: shaded, clearly visible
         40%      .16          past him, opening up
         45%      .10          the Burj
         55%      .02          the woman, effectively clear
         64%      0            the pin, untouched
       Against the old ramp this is +.35 at 22% and +.14 at 30% — materially
       darker exactly where the words are — while reaching clear EARLIER
       (64% against 68%), so the right two-thirds of the photograph is more
       open than before, not less. */
    /* A SECOND AXIS, because the first one alone cannot win.

       Measured on the live hero at 1600px with Range.getClientRects(), so
       these are glyph extents and not block boxes:
         eyebrow    ink ends 20%   scrim .79
         standfirst ink ends 20%   scrim .79
         buttons    ink ends 29%   scrim .44
         HEADLINE   ink ends 31%   scrim .38   <- the only weak point
       The kandura behind that tail sits near .85 luminance; at .38 cover it
       is still .53, and white type on .53 is about 1.8:1. Illegible.

       Raising the HORIZONTAL ramp to fix it would bury the man, who is at
       28% — one column left of where the headline ends. Horizontally they
       are the same place, so no purely horizontal ramp can protect one and
       release the other. VERTICALLY they are not: the headline occupies
       roughly y 32-48%, and the lit shoulder of the kandura runs y 55-95%.

       So this ellipse sits high and left, centred behind the copy block, and
       falls away before the man s shoulder. It adds cover where the words
       are and almost none where the subject is — which is the whole ask:
       dim the left, keep the logo, the man and the woman visible. */
    /* STRENGTHENED to Burj weight, 2 Sep, third pass — and this time against
       the right reference. The client pointed at the SKYLINE hero and said
       the logo hero needs the same left dim. Measured, .hero::before on that
       frame is SOLID BLACK to 29%, .98 at 36%, .82 at 43%, and only clears
       at 64%. My boardroom ramp was .74 at 22% and .40 at 30% — not close.

       Why it cannot simply be copied: the skyline frame has NOBODY on the
       left, so solid-to-29% costs it nothing. This frame has the man at
       ~28%, and the file already records that a heavy horizontal scrim here
       made the photograph invisible twice.

       The separation that does exist is VERTICAL. The copy block sits high
       (eyebrow y~28%, headline y~32-50%); the man s face and lit shoulder
       sit lower (y~45-100%). So the ellipse is pulled UP and made shorter —
       centred at y30% with a 38% height, it is spent by y52% — and made much
       stronger, so the type band reaches the skyline hero s weight while the
       man s face stays in the clear.

       Composite (ellipse over linear, 1-(1-a)(1-b)):
         headline tail 31% x y40%   .74   was .60, skyline reference ~.80
         eyebrow       20% x y28%   .96
         man s face    35% x y50%   .47   visible
         Burj          45% x y30%   .22
         woman         55% x y60%   .04
         pin           67% x y30%   0 */
    linear-gradient(90deg,
      var(--cz-black) 0%,
      var(--cz-black) 36%,
      rgba(5, 6, 7, .98) 39.5%,
      rgba(5, 6, 7, .55) 41.5%,
      rgba(5, 6, 7, .18) 43.5%,
      rgba(5, 6, 7, 0) 45%,
      rgba(5, 6, 7, 0) 100%),
    url('../img/hero-boardroom-burj.jpg');



  /* PER-LAYER, and this is the whole ballgame.

     `background-position` and `background-size` apply to EVERY layer in the
     stack. Writing `background-position: 24vw 6%` slid the SCRIM right by 365px
     along with the photograph, so a ramp whose stops read "clear by 45%" was
     actually painting solid black out to 69% and burying the man completely.
     The scrim must stay pinned to the element while only the photo moves.

     First value = first layer = the gradient. Second = the image. */
  background-size: 100% 100%, cover;
  background-repeat: no-repeat, no-repeat;


  /* 25vw, and both numbers are forced by the photograph, not chosen.

     Measured in the source file (R3 - opened and looked at, not estimated from
     a screenshot, which is what cost four rounds here):
       man's face    0.21-0.34   (skin-tone column scan, not eyeballed)
       woman's face  0.51-0.53
       pin           0.65-0.70
       wall          0.78-1.00  (warm stone - reads as skin, discount it)

     `cover` renders this 1672x941 source at exactly frame-width, so there is no
     horizontal pan budget and background-position-% is inert. A LENGTH offset
     works: the strip it opens on the left is already under a solid scrim, so it
     is black on black, and what falls off the right is the travertine wall the
     client asked to lose.

     Two constraints close on the offset from both sides:
       man's face clear of the ramp  ->  0.26W + off >= 0.49W  ->  off >= 0.23W
       pin in frame, drift included  ->  0.70W + off <= 0.95W  ->  off <= 0.25W
     25vw is the top of that window - the most light the man can keep while the
     pin still survives the 1.09 drift. There is no slack. Changing the ramp end
     or the offset breaks one of the two.

     Vertical stays 6%: the spire tip is 7% down the source and the pin starts at
     24%; cover discards 22.7% of the scaled height and a centred split took 11.3%
     off the top, removing the spire and clipping the pin. At 6% the top loses
     3.8% and the bottom loses 23% - bare table, three sheets and a pen box. */
  background-position: 0 0, 24vw 6%;


  opacity: 0;
  will-change: opacity, transform;

  /* Two animations, deliberately.
     .hero-bg already runs `cinematicDrift 24s` — a slow scale from 1.03 to
     1.09 with a slight drift. Measured live, that makes the base layer
     1637x640 inside a 1585x620 hero.

     Without matching it, frame two fades in perfectly still on top of a
     frame that is moving, and the eye reads that as the picture stopping
     dead every two seconds. Sharing the drift makes the two frames feel
     like one continuous camera move that happens to change subject.

     This is not new motion — it is the motion the hero already had. R16 is
     about bounce and spin, not about a 24-second drift the client approved. */
  animation:
    cz-hero-cross 7.4s cubic-bezier(.4, 0, .2, 1) infinite,
    cinematicDrift 24s ease-in-out infinite alternate;
}

/* THREE seconds per frame — a 6s cycle. The client asked for 2s first and
   revised to 3s. The 0.7s crossfades sit inside that budget rather than on
   top of it, so each image genuinely holds ~2.3s at full opacity and the
   change reads as a dissolve rather than a cut.

   A dissolve is the only motion here — no slide, no zoom, no Ken Burns.
   R16: nothing bounces, nothing spins. */
@keyframes cz-hero-cross {
  /* A 7.4s cycle: 3.0s hold + 0.7s dissolve, twice. Each photograph is fully
     itself for a full three seconds, which is the brief, and the change between
     them takes 0.7s - long enough to read as a dissolve, short enough that the
     double-exposure never becomes the subject.

     0.7s is the number a film editor reaches for on a slow dissolve. Shorter
     than ~0.4s reads as a cut; longer than ~1s and the two images argue with
     each other. It was briefly 0.18s while chasing the scrim bug, which turned
     it into a cut - restored.

     cubic-bezier(.4, 0, .2, 1) on the shorthand: the two holds are flat so the
     curve only shapes the fades, easing in and out of each one. No bounce, no
     overshoot, nothing that draws attention to itself. R16. */
  0%,  40.5% { opacity: 0; }   /* frame one holds 0.00-3.00s */
  50%, 90.5% { opacity: 1; }   /* frame two holds 3.70-6.70s */
  100%       { opacity: 0; }
}


/* R16. Reduced motion means no slideshow at all — not a slower one.
   The frame is hidden entirely, so the hero falls back to the single
   image the client already approved. */
@media (prefers-reduced-motion: reduce) {
  .hero .cz-hero-frame {
    animation: none;
    opacity: 0;
  }
}

/* PHONE.
   Two things change below 760px, and both are forced by geometry rather than
   taste.

   The crop. The hero becomes 375x573 — portrait, against a 1672x941 landscape
   source. cover scales to 1018x573 and throws away 63% of the width. Centre
   would keep source x 638..1017, which is the woman and the travertine wall:
   the man and the Burj both fall off the left edge. 38% keeps source x
   401..1017 — 24% to 61% across — which is exactly the band holding all three
   subjects. (.hero-bg uses 69% here for its own picture; the number is
   per-image, not a house value.)

   The scrim. On desktop the copy sits in the left third and the photograph has
   the right two thirds to itself. On a phone .hero-copy is min(540px, 88%) —
   it spans the whole frame, and a 60-word paragraph sits directly over the
   picture. The desktop ramp (.40 by 30%) would put body text on a lit window.
   So this mirrors what .hero::before already does at this width for the base
   image: near-opaque under the copy, opening up only at the right edge. The
   second frame reads as a change of scene rather than a competing picture,
   which on a 375px screen is the only version of it that is also readable. */
@media (max-width: 760px) {
  .hero .cz-hero-frame {
    background-position: 38% 12%;
    background-image:
      linear-gradient(90deg,
        rgba(5, 6, 7, .97) 0%,
        rgba(5, 6, 7, .96) 62%,
        rgba(5, 6, 7, .94) 82%,
        rgba(5, 6, 7, .86) 92%,
        rgba(5, 6, 7, .70) 100%),
      url("../img/hero-boardroom-burj.jpg");
  }
}

/* TABLET — 761 to 1050px, the band between the phone rule and the desktop one.

   This band had no rule of its own, so it inherited the desktop scrim. That
   scrim is anchored in PIXELS (solid to 650px, clear by 1310px) because the
   copy is a fixed 620px column and a percentage bed drifts away from it as the
   window narrows. Correct on a wide screen; wrong here — 1310px is 174% of a
   753px frame, so the ramp never finishes and the whole photograph sits under
   a 42% veil. Measured at 768: right edge .42 covered. Not dark, just murky.

   Here .hero-copy is min(610px, 62%) — the copy spans nearly two thirds and a
   60-word paragraph sits over the picture, the same problem the phone rule
   already solves. So this mirrors that decision rather than inventing a third
   one: near-opaque under the copy, opening only in the last quarter.

   The consequence is deliberate and worth stating. At this width the man is
   veiled — he lands at 43-68% of the frame, underneath the text, and no ramp
   separates them. The photograph stops being a portrait and becomes the room:
   the Burj at 74% and the woman across 76-99% carry it. That is the same
   trade the phone rule makes. R4's committed light, not a muddy compromise.

   Anchor moves to 4% because cover leaves 491px of horizontal slack at this
   width (the frame is nearly square, the source is 16:9), and spending it on
   the left pushes the woman and the window light into the open right quarter. */
@media (min-width: 761px) and (max-width: 1245px) {
  .hero-copy { width: min(560px, 52%); }

  .hero .cz-hero-frame {
    background-position: 4% 10%;
    background-image:
      linear-gradient(92deg,
        rgba(5, 6, 7, .97) 0%,
        rgba(5, 6, 7, .96) 52%,
        rgba(5, 6, 7, .42) 63%,
        rgba(5, 6, 7, .14) 75%,
        rgba(5, 6, 7, .05) 87%,
        rgba(5, 6, 7, .03) 100%),
      url("../img/hero-boardroom-burj.jpg");
  }
}

/* LAPTOP — 1051 to 1499px.

   The desktop offset is a fixed 460px while the photograph scales with the box,
   so the man's left edge sits at 0.16*W + 460. At 1905 that is 765px, clear of a
   ramp that ends at 800. At 1425 it is 688px — back underneath it. Fixed offset,
   scaling subject: the gap closes as the window narrows.

   Measured in the source file, the subjects sit at these fractions of its width:
   man 0.16-0.40 (face 0.26-0.34), Burj 0.45, woman 0.51-0.66, etched pin
   0.65-0.70, travertine wall 0.78-1.00.

   Two requirements pull against each other here. Clearing the man needs
   offset >= 700 - 0.16W = 472px at this width. Keeping the pin in frame needs
   offset < 0.30W = 427px. They do not both fit — at 1425 the frame is not wide
   enough to hold a 620px copy column AND the full width of this photograph.

   So the copy column gives way first: capped to 540px here, which pulls the
   standfirst ink back to ~550px and lets the ramp finish by 700 instead of 800.
   That buys enough room for offset 415 — the pin lands at 1412 of 1425, just
   inside, the woman is untouched, and the man keeps a 16% veil on his leftmost
   fold only. His face, at 0.26-0.34, is clear.

   The alternative was cropping the pin off entirely to spare that fold. The
   client named the man, the woman and the logo behind her as the three that
   must read, so the fold loses. */
@media (min-width: 1246px) and (max-width: 1499px) {
  /* The scrim and the offset are both proportional now, so they scale on their
     own and this band overrides neither. Only the copy needs help: the headline
     font is 4vw here, so its measure grows as a share of the frame and the ink
     would run past the ramp. Capping the column and the standfirst pulls it back
     inside the bed. */
  .hero-copy { width: min(540px, 42%); }
  .hero-summary { max-width: min(420px, 34%); }
}


/* PHONE, 600px and under — THE PHONE VEIL IS VERTICAL — 8 OCTOBER 2026

   His words: *"the hero images in mobile view are not clearly visible."* The 760px rule
   above is kept for 601-760, where the copy is still a column; this band is where the
   copy is the whole width.

   That rule's own docblock argues for near-opacity under the copy and it was right about
   the problem. What it could not see is how much veil the copy actually needs. Measured
   per element — both photographs drawn into a canvas at their real cover scale and
   position, sampled in each text band, composited, and scored against each element's own
   colour and WCAG threshold — every one of the seven passes at .72, and the binding
   element is the `.hero-note` span at `rgba(255,255,255,.6)`, whose ink composites over
   the background and so dims as the veil lifts (4.04 at .66, FAIL; 4.70 at .72; 5.69 at
   .80, against 4.5 needed).

   .80 ships. At .94-.97 the photograph contributed 3-6% of its own light; at .80 it
   contributes 20%, and the hero still runs 5.7:1 to 12.4:1.

   VERTICAL, because the copy spans the full 343.2px and the only region without text is
   the band under the copy. The hold ends at 80% — 468px — and opens to .12, where
   this photograph reads at mean .18 / p95 .43 of its own luminance. The shape matches
   `.hero::before`'s new one exactly, so the 7.4s cross-fade still reads as a change of
   scene rather than a change of veil.

   `background-position` and `background-size` are deliberately NOT restated: the gradient
   layer is sized `100% 100%`, so its position is inert, and 38% 12% is already within a
   percent of this photograph's brightest crop (.316 against a .324 peak at 30%, sampled
   at eleven pan positions). Only the gradient changes. */
@media (max-width: 600px) {
  .hero .cz-hero-frame {
    background-image:
      linear-gradient(180deg,
        rgba(5, 6, 7, .88) 0%,
        rgba(5, 6, 7, .80) 16%,
        rgba(5, 6, 7, .80) 80%,
        rgba(5, 6, 7, .24) 89%,
        rgba(5, 6, 7, .12) 100%),
      url("../img/hero-boardroom-burj.jpg");
  }
}
