/* AMIN APAC — profile-approach.css
   ============================================================================
   "BUILT AROUND": the band under "Our story" on profile-v2.html only.

   Cut against the reference the client sent: a display heading held on the left
   in two tones — a quiet first line, then the terms it is built around at full
   weight — against a narrow right column carrying a lead sentence and a short
   run of body copy. Two columns, no imagery, no card. It is the page taking a
   breath after the scrollytelling band and before the footer.

   WHAT THIS IS NOT. The reference sets its heading in heavy uppercase grotesk.
   This site does not have one and does not want one: every heading on every
   page is sentence case in the body face, and one all-caps display line here
   would read as a different site's section pasted in. What carries across is
   the STRUCTURE — the size, the two-tone split, the asymmetric pairing with a
   small right column — not the typeface.

   WHY THE TWO TONES ARE --ash AND --black. They are the same two colours the
   word reveal in css/profile-story.css mixes between. The band above spends its
   whole scroll moving copy from ash to black; this one arrives with that move
   already finished. The rhyme is deliberate and free — no new tokens.

   ADDITIVE. Delete this file, js/profile-approach.js and the one
   <section class="approach"> in profile-v2.html and the page is exactly what it
   was. Nothing here is shared with profile.html.
   ============================================================================ */

/* --------------------------------------------------------------------------
   00. The band
   -------------------------------------------------------------------------- */
/* NO GROUND ON THIS BAND (client direction, 2026-09-01). It carried
   --surface-alt for one round and the tint moved to .svc below it instead, so
   the page now runs white (story) - white (this) - tinted (svc) - dark
   (footer).

   WHAT THAT COSTS, WRITTEN DOWN SO IT IS A CHOICE AND NOT A DRIFT: base.css's
   surface rule at --surface says adjacent sections must differ in tone, because
   the tone change is the separator. Two white bands in a row is that rule
   relaxed, and the thing that has to carry the separation instead is the
   layout - the story column ends in pictures, this one opens on an eyebrow over
   84px display type, and the two are far enough apart that nothing reads as one
   continuous block. If it ever does, the fix is the ground, not a hairline: a
   border between two sections this far apart is a rule across the page, which
   is exactly why the hairlines on .hub and .tl-how were deleted.

   The eyebrow and the source rule below both arrived WITH that ground and stay
   without it - they were doing the anchoring the tint was only reinforcing. */
.approach{ padding: var(--sec) 0; }

/* ONE SEAM, NOT TWO, BETWEEN BANDS THAT SHARE A GROUND (client direction,
   2026-09-02).

   base.css's surface rule says adjacent sections must differ in tone, because
   the tone change IS the separator. This band deliberately declares no ground -
   see the long note above - so it sits on white between .story and .trust,
   which are also white. Three white bands in a row means the only separator
   left is space, and each seam was carrying TWO full section paddings.

   Measured at 1600: 192px between the last line of the story column and this
   band's eyebrow, 96 above and 96 below, with nothing in between to explain
   the distance. At 1280 it was 169. A gap that size on an unchanged ground
   does not read as a separator, it reads as the page having lost its place.

   ONE padding is the separator. The band above supplies it, so this one takes
   none - and the same on the way out into .trust. 96px against 84px display
   type is still generous; it is the doubling that was wrong, not the number.

   SCOPED TO THE ADJACENCY, so the rule cannot reach a layout where these
   sections are not neighbours, and to body.pf-v so it cannot reach
   profile.html at all. Where the ground DOES change - .trust into .svc, which
   is --surface-alt - the doubled padding stays, because that seam has a tone
   change to spend it on. */
body.pf-v .story + .approach{ padding-top: 0 }
body.pf-v .approach + .trust{ padding-top: 0 }

/* IN THE CONTAINER, LIKE EVERY OTHER BAND (client direction, 2026-09-02). This
   ran full bleed on hero V's gutter for two rounds; .wrap's own 1400px cap is
   back in charge, so there is nothing to declare here but the grid.

   THE CAPPED TRACKS BELOW STAY, and they are still doing something inside the
   container: 600 + 96 + 560 is 1256 against a 1352px content box, so the band
   is left-aligned in the container with ~96px spare at its right rather than
   stretched to fill it. That is deliberate - see the note on the tracks. */
.approach-grid{
  display:grid;
  /* 1.15/.85, not 1/1. The heading is display type that wants to break into
     three short lines; the copy is 60-75 character measure. Equal columns gave
     the heading a fourth line and the copy an eleven-word one. */
  /* CAPPED TRACKS, NOT FRACTIONS, AND THE HOLE IN THE MIDDLE IS WHY.
     Both columns were fr-based while both contents were ch-capped, so every
     pixel the band gained past ~1600 went into the gap between them rather
     than into either column. Measured: the void between the heading's ink and
     the copy ran 72px at 1440, 80px at 1600, 251px at 1920 and 611px at 2560 -
     the composition came apart on exactly the screens it was widened for.

     The numbers are measured off the ink, not chosen. The heading's longest
     line sets at 567px at its 84px ceiling, so 600px holds it with slack for
     the members whose tag strings run longer. 560px on the copy is the reading
     measure: ~65 characters at 17px, inside the 60-75 rule.

     Surplus leaves on the right as white space instead of opening a gap in the
     middle. justify-content:start is what sends it there rather than splitting
     it around a centred pair - and with the band back inside the 1400px
     container that surplus is now ~96px, not the 611 it was full bleed. */
  grid-template-columns: minmax(0, 600px) minmax(0, 560px);
  justify-content: start;
  column-gap: clamp(40px, 5vw, 96px);
  align-items: start;
}

/* The eyebrow spans both columns as its own row, which does two jobs at once:
   it labels the section the way "Our story" labels the band above, and it puts
   something at the top-left corner so the display heading is not the first
   thing to arrive out of empty space. Spanning also means the heading and the
   copy column both start on row 2 and align to each other rather than one of
   them starting under a label the other does not have. */
/* --s6, not --s10, and no colour of its own. This rule and .svc-eyebrow's
   were the same four declarations - a copy-paste that carried --ash into two
   bands while the story band kept base.css's --gray, and that set the gap
   under the label at 40 here, 20 there and 24 in the story band. One label
   repeated three times had three specifications. See css/profile-v-system.css. */
.approach-eyebrow{
  grid-column: 1 / -1;
  margin: 0 0 var(--s6);
}

/* --------------------------------------------------------------------------
   01. The heading
   -------------------------------------------------------------------------- */
/* One step above --t-display's ceiling. This is the largest type on the page
   after the hero name, which is the hierarchy the reference has and the point
   of the section: it is a statement, not a label. Tracking follows the rule at
   the head of css/base.css — display size takes -.02em. */
/* NO max-width HERE ANY MORE - the 600px track is the cap, and one number
   doing this job is what stops the two disagreeing. The three-line lockup
   survives because the track is only 33px wider than the longest line the
   heading sets at its ceiling. */
.approach-head{
  margin:0;
  font-size: var(--pf-d1);
  /* 600, raised from 500. This is the biggest type on the page after the hero
     and it was the LIGHTEST of the three display steps - hero 600, this 500,
     the service names 600 - so weight went down and then up again as size
     came down. See css/profile-v-system.css. */
  font-weight:600;
  line-height:1.04;
  letter-spacing:-.02em;
}
.approach-head span{ display:block; }

/* The quiet half. --ash is the site's inactive/placeholder ink, and "quiet"
   here is a tonal step, not a legibility one: it measures 7.93:1 on
   --surface-alt (8.34:1 on white), so the first line of the heading is fully
   readable body-grade contrast that simply sits behind the second. */
.approach-pre{ color: var(--ash); }
.approach-terms{ color: var(--black); }

/* --------------------------------------------------------------------------
   02. The copy column
   -------------------------------------------------------------------------- */
/* Nudged down off the heading's cap line. At 84px and 1.04 leading the cap of
   "Built" sits ~9px below the top of its own box, and a lead sentence flush
   with the top of the grid row read as sitting slightly high against it. */
.approach-col{ padding-top: 9px; }

/* The lead sentence. 500, one step up from body, and --black: the reference
   sets its lead darker and heavier than the paragraphs under it, and that
   contrast is what stops the column reading as one undifferentiated grey
   block. */
.approach-lede{
  font-size: var(--pf-lede);
  line-height:1.3;
  /* Balanced, because removing the tracking below 1579px made it a hair wider
     and m2's lead went from two lines to three with "it holds." alone on the
     last. The site sets headings this way already and this is set like one. */
  text-wrap:balance;
  font-weight:500;
  color: var(--black);
  /* NO TRACKING BY DEFAULT, and the clamp above is why. The old comment here
     read "past 30px the h2 step's tracking applies" and the intent was right,
     but the rule was written unconditionally: --pf-lede only REACHES 30px at
     1.9vw = 1579px of viewport, so at every width below that this was
     negative tracking on type under 30px, which base.css forbids outright.
     Measured at 1440 it was 27.4px at -.015em.

     The query below turns it on at exactly the width where the size earns it,
     and at -.01em - the h3 step's value, which is the step this lands on -
     rather than the h2's -.015em, which belongs to type from 36px up. */
}
@media (min-width:1579px){
  .approach-lede{ letter-spacing:-.01em }
}

/* The gap between the lead and the body is doing the work a rule would do. */
/* --s10, not --s12. With the lead's own leading under it the 48px step drew
   67px of visual space and the column read as two blocks that had come apart
   rather than as a lead and the copy it introduces. */
.approach-body{ margin-top: var(--s10); }
/* 17/27, not 16/25. This is the only body copy in the section and it was set at
   the small step meant for captions and meta, against a heading three and a
   half times its size - the gap read as a footnote rather than as the section's
   substance. 17 keeps it clearly subordinate to the lead without whispering. */
.approach-body p{
  font-size:var(--pf-body-sm);
  line-height:var(--pf-line);
  color: var(--slate);
}
.approach-body p + p{ margin-top: var(--s6); }

/* .approach-src IS DELETED, not commented out (client direction, 2026-09-02).
   It styled the "Drawn from what <domain> publishes." line, which is gone from
   the markup and from js/profile-approach.js. Its border-top was this section's
   only hairline - a foot for the column rather than a separator between
   sections - so the column now ends on the last paragraph. Nothing else in the
   file referenced the class. */

/* --------------------------------------------------------------------------
   03. The sweep
   A band of colour travelling through the copy against the scroll. Cut against
   unitedcarriers.com/about, which the client sent as the target: the text does
   not fade in, it changes colour - pale ahead of the band, brand purple inside
   it, settled behind it.

   --ap is the section's own scroll progress, 0 to 1, written by
   js/profile-approach.js. --i is a unit's index and --n the count, both written
   there too. Registered below so an engine that supports @property treats --ap
   as a number rather than a token; one that does not still substitutes it into
   the calc, which is all this needs.

   GREY, NOT PURPLE (client direction, 2026-09-02). It ran three stops for one
   round - pale purple, brand purple, settled - and the hue in the middle read
   as a second, louder effect on a page that already has one. This is now the
   SAME TWO STOPS as the word reveal in css/profile-story.css: one grey ahead of
   the band, the unit's own settled colour behind it, nothing in between. The
   band above and this one are deliberately the same move, which is what makes
   the page read as one idea rather than two tricks.

   THE PURPLE IS ONE VALUE AWAY. --appr-pale below is the only thing that
   changed; put the two nested color-mixes back and the hue returns. Kept
   documented rather than deleted so the choice stays reversible.
   -------------------------------------------------------------------------- */
@property --ap{syntax:"<number>";inherits:true;initial-value:0}

.approach.is-swept{
  /* The tone ahead of the band, and it is the STORY BAND'S OWN --story-unlit
     value, not a near miss: #B4B9C2 measures 1.97:1 on white, which is under the
     text floor by design - a word ahead of the band is meant to read as not
     yet arrived, and everything is legible the moment the band reaches it.
     Copied as a literal because the two files are independent and additive;
     if it ever moves, it moves in both. */
  --appr-pale:#B4B9C2;   /* kept identical to --story-unlit on purpose */
  /* How many units wide the band is. Wider than the story band's 9 because
     this one crosses characters as well as words - at 9 the gradient was a
     three-letter smear inside one word of the heading rather than a travelling
     edge across the composition. */
  --appr-fade:16;
}

.approach.is-swept .appr-u{
  /* How far this unit is through the band: 0 ahead of it, 1 behind it,
     fractional inside. The + --appr-fade is what lets the LAST unit finish -
     without it the band's leading edge only reaches unit --n at --ap 1, so the
     tail of the source line would land on the final pixel of travel. */
  --lit:clamp(0, calc((var(--ap, 0) * (var(--n, 1) + var(--appr-fade)) - var(--i, 0)) / var(--appr-fade)), 1);

  /* ONE MIX, TWO STOPS. --lit drives it straight from the grey to the unit's
     own settled colour - the same single color-mix profile-story.css runs. The
     --a/--b pair that used to split the travel in half for a purple midpoint is
     gone with it; nothing else in this file referenced them. */
  color:color-mix(in srgb,
    var(--appr-end, var(--black)) calc(var(--lit) * 100%),
    var(--appr-pale));
}

/* THE SPANS ARE INVISIBLE TO LINE BREAKING, and that is the whole rule.
   SCOPED TO .approach-head DELIBERATELY: the rule two sections up sets
   `.approach-head span{display:block}` to force the two heading lines apart,
   and at 0,1,1 it beats a bare class at 0,1,0 - which turned every term into
   its own block and printed the heading as PR / , / reputation, one per line,
   commas stranded. Measured, not theorised.

   `inline`, NOT `inline-block`, AND THE ORPHANS ARE WHY. Boxing each term made
   it unbreakable, so the heading could only break BETWEEN terms - and with one
   short term in the list that produced a stranded line every time: measured at
   1600, m2 set `PR,` at 132px against a 600px track, brew and brandigo `B2B,`
   at 182, asiaworks closed on `post` at 171. Inline spans break like the text
   they are, so `PR, reputation` sets on one line at 583px and the heading
   comes back to two. The character spans take the same value for a harder
   reason: an inline-block is an atomic inline, and a break opportunity opens
   on both sides of one - a per-character box would have let the heading break
   mid-word. */
.approach-head .appr-term{ display:inline }

/* THE WORD IS THE BOX THAT PROTECTS THE LINE BREAKS. Each letter below is an
   inline-block so the cursor effect can transform it - a transform does
   nothing on an inline box - and an atomic inline opens a break opportunity on
   both sides of itself, which without this would let the heading break in the
   middle of a word. nowrap closes every opening inside a word and leaves the
   ones between words untouched, so the orphan rules above still decide where
   this heading breaks. */
.approach-head .appr-w{ display:inline; white-space:nowrap }

/* --u is the cursor's reach at this letter: 1 under the pointer, 0 outside the
   radius, written per frame by js/profile-approach.js. It is only ever a
   TRANSFORM - colour is the sweep's language and reusing it here would make
   two effects look like one misfiring. translate3d rather than translateY so
   the letters are composited rather than laid out again on every frame.

   NO transition. The value already changes every frame the pointer moves;
   easing on top of it is a second animation chasing the first, and it turns a
   quick pass across the heading into a lag. The smoothing is in the falloff
   curve instead, which is in the script. */
.approach-head .appr-u{
  display:inline-block;
  transform:translate3d(0, calc(var(--u, 0) * -9px), 0);
}

/* EVEN LINES, NOT GREEDY ONES. Greedy breaking packs each line to the track
   and leaves whatever is left on the last one, which is the other half of the
   orphan problem - asiaworks ran 389 / 600 / 171. Balance minimises the widest
   line instead, so the remainder is shared across all of them.

   Only the terms take it. The quiet first line is two words and always sets on
   one line; balancing it costs a measure pass for nothing. Unsupported engines
   fall back to greedy, which is what this had before - the inline fix above is
   what carries the orphans, and this is the polish on top of it. */
.approach-terms{ text-wrap: balance }

@media (prefers-reduced-motion:reduce){
  /* The script settles --ap at 1 and stops; this is the belt to that braces,
     for the case where the class is on but no script ever ran. */
  .approach.is-swept .appr-u{ color:var(--appr-end, var(--black)) }
}

/* --------------------------------------------------------------------------
   04. Narrow
   -------------------------------------------------------------------------- */
/* One column below the same 900px the rest of this page stacks at. The heading
   keeps its size ratio but drops its ceiling — 84px over a 360px viewport is
   four words a line. */
@media (max-width: 900px){
  .approach-grid{ grid-template-columns: minmax(0,1fr); row-gap: var(--s8); }

  .approach-eyebrow{ margin-bottom: var(--s6); }
  .approach-col{ padding-top:0; }
  /* The ch caps that used to be released here are gone from the wide layout
     too - the copy track is the only measure now, and stacking releases it. */
}
