/* ==========================================================================
   AMIN APAC — profile-hero-v.css
   Hero V, "the room". The fourth hero: a full-bleed loop of the member's own
   place, with the copy dropped to the baseline.

   Additive and scoped to body.pf-v / .pf-hero-v. It loads after profile.css
   and profile-hero.css and touches nothing either of them own, so
   profile.html (body.pf-a2, data-hero="a") is unaffected by every rule here.

   WHAT THIS HERO IS NOT. It is not a showreel slot. The reference this was
   built from (unitedcarriers.com) survives 100px type on top of moving
   footage for exactly one reason: the footage is a single continuous shot at
   distance with no cuts, no titles and no music - it reads as environment,
   not as content. A cut montage under this composition is unreadable and the
   agency's own edit ends up fighting the H1. The brief to members is
   therefore part of the design, not a production detail:

       one shot, 8-12 seconds, no cuts, no text, no music, filmed wide.
       the room, the street outside it, a shoot in progress, hands working.
       the PLACE the work happens - not the work.

   THE POSTER IS THE FLOOR. Every member renders this hero whether or not
   they have filmed anything: js/profile-hero-v.js paints the still first,
   from the member's own imagery, and only fades the video over it once it
   can actually play. No file, bad network, reduced motion, a decode failure -
   all land on the same picture. Nobody is ever the thin profile.
   ========================================================================== */

/* --------------------------------------------------------------------------
   00a. THE PAGE IS IN THE CONTAINER; ONLY THE HERO IS FULL BLEED
   Client direction, 2026-09-02.

   For two rounds this page ran the other way round: every content band was
   full bleed on clamp(24px, 3.4vw, 72px) - hero V's gutter - and the sticky bar
   was pulled out of .wrap to match them. That has been reversed. "Our story",
   "In practice", "What they do", the work grid and Field notes are all back in
   the site's 1400px container, so the bar belongs back in it too: the rule that
   used to live here is deleted rather than rewritten.

   ONE EDGE FOR EVERYTHING EXCEPT THE PICTURE. At 1920 the header pill, the
   sticky bar, every content band and the footer all start at 260px. The hero
   keeps its own gutter at 65px, which is the point of it - it is the only
   full-bleed thing on the page, and its copy sits on the picture rather than in
   the column.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   01. The stage
   Flat black rather than hero A's radial gradients: there is no object
   standing on a ground here, the picture IS the ground.
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   00. The frame's height
   NOT FULL HEIGHT, and the reasoning is about the fold rather than the picture.
   profile.css gives every hero 100vh, which was right while this page had a
   long two-column body under it. It no longer does: the page is hero, Our
   story, Field notes, footer. A whole screen of photograph is a much larger
   share of a much shorter page.

   THE ARGUMENT IS WHAT THE FIRST SCREEN PROVES. At 100vh it carries a picture,
   a name and a button, and nothing that shows there is a page underneath except
   an 11px cue in the corner. At 86 it also carries the top of the next section -
   about 126px on a 900px viewport, enough for the white edge and the OUR STORY
   label. A visible next section is the strongest scroll affordance there is and
   it beats any cue.

   It also helps the configuration that was already tight: below ~760px of
   viewport the story panel drops its pin, and a 100vh hero on those screens is
   a tall picture with the copy crammed against the bottom edge.

   100svh STAYS BELOW 900px. On a phone a partly-revealed section reads as a
   layout that did not finish rather than as an invitation, and svh is doing
   real work there against the browser's own chrome - see the narrow block at
   the foot of this sheet.

   svh SECOND, as profile.css does it: the vh line is the floor for engines that
   do not know the small-viewport unit, and the svh line wins where they do. */
.pf-hero-v{min-height:86vh;min-height:86svh}

.pf-hero-v .pf-stage{background:#0B0C0E}

.pf-media{position:absolute;inset:0;overflow:hidden}

/* Poster and video occupy the same box and are cross-faded, so the swap has
   no reflow and no flash of black between them. --pos is the member's own
   focal point, carried over from the same field hero B reads. */
.pf-media img,
.pf-media video{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:var(--pos,50% 45%);
  /* The 1.06 is headroom for the parallax below, not a crop for its own sake:
     without it the translate exposes a hairline of stage at the bottom edge. */
  transform:scale(var(--zoom,1.06)) translate3d(0,calc(var(--sy,0) * .12px),0);
  will-change:transform;
}
.pf-media video{opacity:0;transition:opacity 1.1s ease}
/* Set by the script on `canplay`, and only then. */
.pf-media.is-playing video{opacity:1}
/* Once the video is up the poster is dead weight over it - but it stays in
   the box rather than being removed, because a loop that stalls mid-scroll
   falls back onto it. */
.pf-media.is-playing img{opacity:0;transition:opacity 1.1s ease}

/* --------------------------------------------------------------------------
   02. The scrim
   Bottom-weighted, where hero A's is a side gradient lighting the plate.
   The copy sits on the floor of the frame here, so that is where the density
   has to be; the light top band is only enough to hold the header's white
   logo and nav off a bright sky.
   -------------------------------------------------------------------------- */
/* THESE NUMBERS WERE RAISED AFTER LOOKING AT A RENDER, not chosen up front.
   The reference's footage is a dark road at dusk and needs very little help;
   a member's room is lit, white-walled and often has a screen in it, and at
   the first pass the tagline was sitting on a bright laptop. The floor is
   now opaque enough to carry small type over any frame, which is the actual
   requirement - a scrim that only works on dark footage is not a scrim. */
.pf-hero-v .pf-scrim{
  background:
    linear-gradient(180deg, rgba(11,12,14,.74) 0%, rgba(11,12,14,.3) 15%, transparent 32%),
    linear-gradient(180deg, transparent 26%, rgba(11,12,14,.55) 58%, rgba(11,12,14,.88) 82%, rgba(11,12,14,.97) 100%),
    /* Weight into the left column, where the name is heaviest. */
    linear-gradient(78deg, rgba(11,12,14,.58) 0%, rgba(11,12,14,.2) 38%, transparent 58%);
}

/* THE FLOOR EXTENSION. The scrim is a box with a hard bottom edge, and on
   profile-v2.html the curtain drifts it upwards while the section climbs over
   the hero (see css/profile-story.css section 00). Drift it far enough and that
   edge crosses into view: the gradient's dense floor stops dead in the middle
   of the picture and the frame below it goes bright, which reads as a broken
   render rather than as a scrim.

   This continues the gradient's LAST STOP - the same rgba(11,12,14,.97) it ends
   on above, so the join is seamless - for the length of the drift. The hero's
   overflow:hidden clips it, so nothing below the frame is affected.

   var(--story-lift, 0px) IS THE CROSS-SHEET LINK AND THE FALLBACK IS THE POINT.
   The token is declared on body by css/profile-story.css, which only
   profile-v2.html loads. Anywhere else it resolves to 0px, the extension has no
   height, and this rule costs nothing - so hero V still works on a page with no
   curtain in it. */
.pf-hero-v .pf-scrim::after{
  content:"";position:absolute;left:0;right:0;top:100%;
  height:var(--story-lift, 0px);
  background:rgba(11,12,14,.97);
}

/* --------------------------------------------------------------------------
   03. The copy: two columns on one baseline
   The whole composition. Name bottom-left at scale, tagline bottom-right and
   deliberately small, both sitting on the same line - then one hairline, and
   under it the rail on the left with the single action on the right.

   The eyebrow spans, so the country reads as a label over the pair rather
   than as the first line of the left column only.
   -------------------------------------------------------------------------- */
.pf-hero-v .pf-copy{padding-bottom:clamp(36px,6vh,64px)}

/* FULL BLEED, so this is the one .wrap on the site that does not centre in
   1400px. It is a deliberate exception and it is scoped as tightly as it can
   be - .pf-hero-v .pf-copy .wrap, one element on one page.

   The reason is that the picture behind it already runs edge to edge. A
   headline stopped at a 1400px column over a full-bleed frame reads as a
   caption laid on a photograph; run to the same edges as the picture, it
   reads as part of it. The reference does exactly this: its H1 starts about
   1.7vw from the left edge of the window at any width.

   Everything else on the page - the bar, the body, the footer - keeps the
   1400px measure, which is what stops this from being a site-wide change. */
.pf-hero-v .pf-copy .wrap{
  max-width:none;
  padding-inline:clamp(24px,3.4vw,72px);
  /* Wider left than before (1.35fr): with the full width to divide, the old
     split gave the tagline far more room than a two-line sentence needs and
     took it from the name, which is the thing being made bigger. */
  grid-template-columns:minmax(0,1.62fr) minmax(0,1fr);
  column-gap:clamp(32px,5vw,96px);
  row-gap:clamp(20px,3vh,34px);
  align-items:end;
}
.pf-hero-v .pf-eyebrow{grid-column:1 / -1}
.pf-hero-v .pf-id{grid-column:1}

/* Bottom-aligned against the name's last line, not top-aligned against its
   first. The reference does the same thing and it is what makes the two
   columns read as one sentence across the foot of the frame instead of as
   two stacked blocks that happen to be side by side. The small optical nudge
   is because .pf-name sits on a .88 line-height and its baseline is well
   above its box. */
/* THE RIGHT-HAND BLOCK: standfirst over action. It is the grid item now, not
   the paragraph - the button used to be placed separately in column 1 under the
   name, which put the page's one call to action at the end of the identity
   rather than at the end of the argument for it. Read down the right column it
   now goes claim, reach, do something about it.

   IT CARRIES THE MEASURE AND THE OPTICAL NUDGE, both moved off .pf-tagline: the
   nudge aligns the block's last line with the name's baseline and the last line
   is the button now, and a max-width on the paragraph alone would have let the
   button sit wider than the text above it. */
.pf-hero-v .pf-side{
  grid-column:2;align-self:end;
  /* NO MEASURE CAP (client direction, 2026-09-01). The block takes the whole
     right-hand track, so what bounds the line is the grid, not a ch value.

     THE MEASURE HOLDS ANYWAY, WHICH IS WHY THIS IS SAFE. The hero's .wrap is
     the one on this site with no 1400px cap - it runs edge to edge with the
     picture, so this column keeps growing with the window and there is nothing
     structural stopping the line. Measured on the real copy rather than
     assumed: 33 characters a line at 1024, 44 at 1600 and 1920, 66 at 2560 -
     inside the 60-75 rule at the widest and under it everywhere else. The
     standfirst is two short sentences, and two short sentences cannot make a
     long line however wide the box is.

     WHAT TO WATCH is copy length, not screen width. A member whose two
     sentences ran to three or four would set genuinely long lines out here.
     If that happens the fix is one line - a max-width in ch, back on this
     rule - and NOT a cap on the wrap, which would pull the H1 in off the edge
     of the picture and undo the full-bleed decision above. */
  margin-bottom:.5em;
}

.pf-hero-v .pf-tagline{
  /* NO CAP HERE EITHER, AND THIS ONE IS AN OVERRIDE. profile.css:307 gives
     every .pf-tagline max-width:44ch for hero A, and that rule was still
     binding after the cap came off .pf-side above: at 2560 the block took the
     full 886px track while the text inside it stopped at 666. The removal only
     appeared to work because below about 1900px the column is narrower than
     44ch and the base rule never bit.

     Scoped to .pf-hero-v, so hero A on profile.html keeps its 44ch.

     The paragraph and the button under it have to share one edge - a cap on
     one and not the other is what leaves the block with two different left-hand
     measures. */
  max-width:none;
  /* Up from clamp(15px,1.15vw,18px). At 18px against a name set near 100px the
     paragraph read as a caption on the picture rather than as the other half of
     the composition; the reference's block is close to a fifth of its headline
     and this is the same ratio. */
  font-size:clamp(17px,1.5vw,22px);line-height:1.45;
  color:rgb(255 255 255 / .84);
}

/* TWO BLOCKS, ONE PARAGRAPH. Both sentences are in the same <p> and read as one
   standfirst; the only separation is a line of space and a step down in
   brightness, because the first sentence is this member's claim and the second
   is the network's. Same idea as the reveal in the story band below: a shift in
   emphasis between two readable tones, not a strong line and a faint one.
   .84 and .72 against the scrim are both well clear of the contrast floor. .66
   was the first value and it was cutting it fine: this text sits over the
   BRIGHT end of some members' frames - a window wall, a lit studio - and the
   scrim is the only thing holding it up. .72 keeps the step down legible as a
   step without betting the second sentence on the picture behind it. */
.pf-hero-v .pf-tagline .pf-lede,
.pf-hero-v .pf-tagline .pf-scope{display:block}
.pf-hero-v .pf-tagline .pf-scope{
  margin-top:.65em;
  color:rgb(255 255 255 / .72);
}

/* --------------------------------------------------------------------------
   04. The name
   Hero A2's clamp mechanism kept wholesale - including the --word cap that
   stops "Communications" overflowing its column - and only re-tuned for this
   frame, where the left column is wider than A2's (no plate to stay clear of)
   but the type has to survive moving footage underneath it.

   NOT uppercased, though the reference is. "GLOBAL FREIGHT FORWARDING" is a
   description and takes caps naturally; a member's name is a proper noun and
   several of them break under it - M2.0 COMMUNICATIONS reads as a part
   number. If you want the wordmark treatment it is one line, commented at
   the bottom of this block.
   -------------------------------------------------------------------------- */
/* THE CAP IS MEASURED, NOT APPROXIMATED. Hero A2 expresses the same cap as a
   fraction of the viewport - "(62vw - 120px)" - and that works there because
   its plate hero has no wrap max-width in play at the sizes it was checked at.
   Here it fails at both ends, and both failures were measured rather than
   guessed: at 1920 the vw term keeps growing after the wrap has stopped, so
   "Communications" ran 200px into the tagline's column; at 390 the same term
   collapses and the name computed to 14px.

   So the container is asked directly. .pf-id is the lockup, it is a grid item
   whose width comes from the track and not from its contents, and 100cqw is
   therefore the real column - at any viewport, with any wrap max-width, in one
   or two columns. 88px is the tile plus its gap, which the name does not get.
   .58 is the measured average advance of this face at this weight and
   tracking, in em per character, and is A2's number unchanged.

   If the grid template in section 03 changes, nothing here needs re-measuring.
   That is the point of doing it this way. */
body.pf-v .pf-id{container-type:inline-size}
body.pf-v .pf-name{
  /* RAISED from clamp(46px,8.6vw,124px). The copy is full-bleed now, so the
     column that feeds the cqw term below is far wider and the old ceiling was
     leaving most of it unused - eleven of eleven names sat on the 124px cap
     rather than on the measured fit. .92 line-height with it: at this scale a
     two-line name needs the lines closer or the lockup falls apart.
     The subtrahend is now 8px, not 96px: with the tile stacked above rather
     than beside it, the name has the whole column and only needs a hair of
     slack against the rounding. */
  font-size:min(clamp(52px,11.4vw,208px), calc((100cqw - 8px) / (var(--word,9) * .58)));
  font-weight:600;letter-spacing:-.042em;line-height:.86;
  max-width:100%;text-wrap:balance;
  /* Heavier than A2's. That shadow sits over a static plate on a controlled
     ground; this one has to hold against whatever frame the loop is on. */
  text-shadow:0 2px 6px rgb(0 0 0 / .34), 0 14px 48px rgb(0 0 0 / .5);
}
/* .pf-name{text-transform:uppercase;letter-spacing:-.02em}  <- wordmark option */

/* THE TILE STACKS ABOVE THE NAME rather than sitting beside it, which is the
   change that actually delivers "full width". .pf-id is a flex row on the
   other heroes - tile, then name - and that row was indenting the name by the
   tile plus its gap: measured at 1600 the copy block started at 54px and the
   name at 142px. The largest type on the page was the one thing not touching
   the frame's left edge, which is precisely what the reference does not do.

   Above it, the mark still reads as the agency's own and the name sets flush
   left at any size. This is CSS only - the markup order is unchanged, so
   profile.js's fillTile() and every other hero keep working as they are. */
body.pf-v .pf-id{
  display:grid;justify-items:start;
  gap:clamp(12px,1.3vw,20px);
}
body.pf-v .pf-id .tile{width:clamp(48px,3.4vw,64px);height:clamp(48px,3.4vw,64px);font-size:clamp(17px,1.2vw,22px)}

/* The eyebrow carries the country and nothing else, so it can afford to be
   quieter here than on a hero where it competes with a ghost word. */
body.pf-v .pf-eyebrow{color:rgb(255 255 255 / .72);letter-spacing:.18em}

/* --------------------------------------------------------------------------
   05. The baseline strip
   The reference has nothing along its foot and is slightly bare because of
   it - it can afford that with a six-word headline filling three lines. An
   agency name is one to three words, so this frame has real space under the
   lockup, and the rail is what earns it: the four facts a buyer actually
   scans for, on one line, over a hairline.
   -------------------------------------------------------------------------- */
/* Slightly brighter than profile.css's .74. That value is tuned for hero A's
   flat plate ground; here the rail sits on a photograph and lost its labels. */
/* THE RIGHT-HAND COLUMN HOLDS THE TAGLINE AND NOTHING ELSE. The reference has
   one text block there and the emptiness under it is doing work.

   NO RAIL RULES HERE ANY MORE. .pf-hero-v .pf-rail styled the strip of facts
   and the hairline above it along the foot of the frame; both went with the
   markup (see the note in profile-v2.html). The remaining rules in this sheet
   that mention .pf-rail are in the narrow-width block at the bottom and are
   inert - left in place so restoring the one line of markup restores the whole
   thing, at every width, with no second edit here. */
/* Inside .pf-side now, so this places nothing - it only sets the air between
   the standfirst and the button. --s6, not the --s2 .pf-actions carries in
   profile.css: 8px was the gap under a NAME, where the button reads as part of
   the identity block. Under a six-line paragraph it needs to read as the thing
   you do after reading, which takes a paragraph's worth of space, not a
   line's. */
.pf-hero-v .pf-actions{margin-top:var(--s6)}

/* ONE ACTION IN THE FRAME, not two. The header already carries "Get in touch"
   and the sticky bar already carries "Visit website", so hero A's pair made
   three primaries in one viewport - and the reference this hero is built from
   puts zero buttons in the hero at all, keeping its single CTA up in the
   header. This is the middle position: the one action the page exists for,
   and nothing beside it. The <a id="pfVisit"> is simply not in the markup for
   this variant; profile.js's wireVisit() no-ops on a missing element, so
   nothing else has to change.

   The site's own rule is that a control on dark uses .btn-on-dark, which this
   inherits from base.css - only the placement is here. */
.pf-hero-v .pf-actions .btn{white-space:nowrap}

/* --------------------------------------------------------------------------
   06. The credit
   A member's room is usually shot by someone. Same rule the work grid runs
   on: if a credit is on file it is printed, quietly, where it does not sit
   on the copy.
   -------------------------------------------------------------------------- */
.pf-hero-v .pf-vcredit{
  position:absolute;left:var(--s6);bottom:calc(var(--s6) * .55);z-index:3;
  margin:0;font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  color:rgb(255 255 255 / .42);pointer-events:none;
}
.pf-hero-v .pf-vcredit:empty{display:none}

/* The cue stays. The reference drops it and gets away with it because that is
   a homepage whose next section is obvious; a profile has a long body under
   this frame and no other signal that it is there. */

/* --------------------------------------------------------------------------
   07. Narrow
   Below 900 the two columns become one and the composition reverts to a
   plain bottom-left stack: name, tagline, rail, action. The tagline loses its
   optical nudge (nothing to align to any more) and the rail loses its rule,
   because at this width it is the only thing above the action and does not
   need separating from it.
   -------------------------------------------------------------------------- */
@media (max-width:900px){
  /* Full height again - see the note at section 00 - LESS THE HEADER, which is
     in flow at this width and was pushing the hero's last element past the
     fold. --hdr-h is measured by js/profile-hero-v.js and is 0 wherever the
     header is out of flow, so the calc is safe at any width; the fallback of 0
     means a page without that script gets exactly the old behaviour rather than
     a broken one. The measurements are in the script's note. */
  .pf-hero-v{
    min-height:calc(100vh - var(--hdr-h, 0px));
    min-height:calc(100svh - var(--hdr-h, 0px));
  }
  .pf-hero-v .pf-copy .wrap{grid-template-columns:minmax(0,1fr)}
  .pf-hero-v .pf-side,
  .pf-hero-v .pf-rail,
  .pf-hero-v .pf-actions{grid-column:1}
  /* The nudge is only meaningful beside the name; stacked there is nothing to
     align to, and the measure can open up to a phone's full width. */
  .pf-hero-v .pf-side{margin-bottom:0;max-width:46ch}
  .pf-hero-v .pf-tagline{margin-bottom:0;max-width:none}
  .pf-hero-v .pf-rail{border-top:0;padding-top:0}
  .pf-hero-v .pf-actions{justify-self:start;align-self:auto;padding-top:4px}
  /* max-width is already 100% */
  /* The scrim's side gradient is pointless at this width - the copy spans the
     frame - and it was darkening the left third of a picture nobody can crop. */
  .pf-hero-v .pf-scrim{
    background:
      linear-gradient(180deg, rgba(11,12,14,.7) 0%, transparent 26%),
      linear-gradient(180deg, transparent 30%, rgba(11,12,14,.66) 68%, rgba(11,12,14,.95) 100%);
  }
}

/* --------------------------------------------------------------------------
   08. Reduced motion
   The video is never requested at all in this mode - the script checks the
   same query before it touches the network - so this only has to stop the
   parallax. The hero becomes a still photograph, which is a complete version
   of the design rather than a degraded one.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  .pf-media img,
  .pf-media video{transform:scale(var(--zoom,1.02))}
}
