/* ==========================================================================
   KHRS|HR - Signature Site  ·  A GT Studios website
   --------------------------------------------------------------------------
   v3 - divergence pass. Typeface moved off the reference's face; the tabbed
   values section rebuilt as a sticky-scroll read with a live label; the hero
   value pills replaced by a caption bar contained in the photo half.
   DESKTOP PASS ONLY. Mobile is a separate pass (see PROJECT.md).
   ========================================================================== */

@font-face {
  font-family: "Manrope";
  src: url("../fonts/manrope-var-latin.woff2") format("woff2-variations");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   01 · Tokens
   -------------------------------------------------------------------------- */
:root {
  --bg:        #fbfbfa;
  --panel:     #ffffff;
  --ink:       #111317;
  --ink-65:    rgba(17, 19, 23, .65);
  --ink-45:    rgba(17, 19, 23, .45);
  --muted:     #8e8e8e;
  --line:      rgba(17, 19, 23, .10);
  --hairline:  rgba(17, 19, 23, .07);

  /* identity - from the KHRS|HR wordmark */
  --navy:      #17395f;
  --navy-deep: #0e2340;
  --accent:    #1c6fc4;
  --accent-soft: #7db4ea;

  --on-dark:    #ffffff;
  --on-dark-70: rgba(255, 255, 255, .70);
  --on-dark-80: rgba(255, 255, 255, .82);
  --line-dark:  rgba(255, 255, 255, .14);

  /* Depth kit for the navy panels - testimonial band and team band both draw
     from these, so the look is tuned in one place rather than two.
     --navy-grade: diagonal ramp, light top-left to deep bottom-right. Both ends
     clear 7:1 against white, so nothing here costs legibility.
     --orb / --orb-soft: the oversized circles that bleed off a panel edge, the
     same device as the hero's navy half. The last stop lands at 74% but the
     fade is effectively done by 66% - finishing the fade INSIDE the shape is
     what makes it read as a circle instead of as more diagonal ramp. */
  --navy-grade: linear-gradient(158deg, #1c4270 0%, var(--navy) 46%, #102b4b 100%);
  --orb: radial-gradient(circle,
           rgba(255, 255, 255, .10) 0%, rgba(255, 255, 255, .052) 44%,
           rgba(255, 255, 255, .014) 66%, rgba(255, 255, 255, 0) 74%);
  --orb-soft: radial-gradient(circle,
           rgba(255, 255, 255, .075) 0%, rgba(255, 255, 255, .038) 44%,
           rgba(255, 255, 255, .01) 66%, rgba(255, 255, 255, 0) 74%);

  --wrap: 1570px;
  --pad: 80px;
  --nav-h: 84px;

  --ease: cubic-bezier(.44, 0, .56, 1);
}

/* --------------------------------------------------------------------------
   02 · Reset & base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

/* Native smooth scroll is the fallback path - it is what runs if Lenis is absent
   (script blocked, JS off) or suppressed by reduced motion. scroll-padding-top
   keeps an anchor from landing its target underneath the fixed bar. */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 24px);
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* Lenis overrides, per its docs: when it takes over, native smooth must get out
   of the way or the two animate the same scroll and fight. */
html.lenis, html.lenis body { height: auto; }
/* Keyed off .lenis, not only .lenis-smooth: measured, 1.1.20 stamps .lenis on
   init but not always .lenis-smooth, and native smooth left on top of Lenis
   means two animators driving one scroll. If Lenis is running at all, native
   smooth must be off. */
html.lenis { scroll-behavior: auto !important; }
html.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-scrolling iframe { pointer-events: none; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Manrope", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 18px;
  font-weight: 350;
  line-height: 1.55;
  letter-spacing: -.3px;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
}

img, video, svg { display: block; max-width: 100%; }
img, video { height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul { list-style: none; padding: 0; }
table { border-collapse: collapse; }

h1, h2, h3, h4, h5, h6 { font-weight: 300; line-height: 1.1; }
::selection { background: var(--accent); color: #fff; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.skip {
  position: absolute; left: 16px; top: -60px; z-index: 200;
  background: var(--ink); color: #fff; padding: .7em 1.2em; border-radius: 50px;
  font-size: 14px; font-weight: 600; transition: top .2s var(--ease);
}
.skip:focus { top: 16px; }

/* --------------------------------------------------------------------------
   03 · Primitives
   -------------------------------------------------------------------------- */
.container {
  width: 100%; max-width: var(--wrap);
  margin-inline: auto; padding-inline: var(--pad);
}

.h1    { font-size: 66px; letter-spacing: -2.2px; }
.h2    { font-size: 56px; letter-spacing: -1.9px; }
.h2-sm { font-size: 40px; letter-spacing: -1.2px; line-height: 1.2; }
.h3    { font-size: 30px; letter-spacing: -.9px;  line-height: 1.2; }
.h4    { font-size: 24px; letter-spacing: -.7px;  line-height: 1.25; }

.body { font-size: 18px; font-weight: 350; line-height: 1.55; letter-spacing: -.3px; color: var(--ink-65); }
.body--light { color: var(--on-dark-70); }

.eyebrow { display: flex; align-items: flex-start; gap: 10px; }
.eyebrow svg { width: 22px; height: 19px; flex: none; margin-top: 4px; }
.eyebrow span { font-size: 17px; font-weight: 500; letter-spacing: -.2px; line-height: 1.3; }
.eyebrow--light span { color: #fff; }
.eyebrow--light svg { fill: #fff; }
.eyebrow--dark svg { fill: var(--ink); }

/* small uppercase label used on rules, table heads, index strips */
.micro {
  font-size: 13px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; line-height: 1.2;
}

/* --------------------------------------------------------------------------
   04 · Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 13px 24px; border-radius: 50px;
  font-size: 14px; font-weight: 600; letter-spacing: .03em; line-height: 1.2;
  text-transform: uppercase; white-space: nowrap;
  border: 1px solid transparent;
  transition: background-color .35s var(--ease), color .35s var(--ease), border-color .35s var(--ease);
}
.btn--dark   { background: var(--ink); color: #fff; border-color: var(--ink); }
.btn--dark:hover { background: transparent; color: var(--ink); }
.btn--light  { background: #fff; color: var(--ink); border-color: #fff; }
.btn--light:hover { background: transparent; color: #fff; }
.btn--accent { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn--accent:hover { background: transparent; color: #fff; border-color: #fff; }

.link-u { display: inline-flex; flex-direction: column; gap: 2px; }
.link-u span { font-size: 13px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; }
.link-u i { display: block; height: 1px; background: currentColor; transition: opacity .35s var(--ease); }
.link-u:hover i { opacity: .4; }

/* --------------------------------------------------------------------------
   05 · Navigation
   -------------------------------------------------------------------------- */
/* Solid white, always. It used to start transparent over the hero and turn
   white past 40px of scroll; the bar is now one fixed object that never
   changes state, so the scroll class does nothing visual. No rgba and no
   backdrop-filter here on purpose - "no transparency" means the hero must not
   show through even slightly. */
.nav {
  position: fixed; inset: 0 0 auto 0; z-index: 30;
  padding-block: 20px;
  background: #fff;
  border-bottom: 1px solid var(--line);
  /* links and the phone number pick this up by inheritance, and the phone's
     underline rule is currentColor, so it follows too */
  color: var(--ink);
}
.nav__inner { display: flex; align-items: center; justify-content: space-between; }
.nav__logo img { width: 190px; }
.nav__logo .logo-light { display: none; }
.nav__logo .logo-dark  { display: block; }

.nav__right { display: flex; align-items: center; gap: 55px; }
.nav__links { display: flex; align-items: center; gap: 24px; }
.nav__links a {
  font-size: 13px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  transition: opacity .35s var(--ease);
}
.nav__links a:hover { opacity: .65; }
.nav__actions { display: flex; align-items: center; gap: 20px; }

/* Between the mobile breakpoint (1180) and roughly 1300 the bar runs out of
   room and the labels were breaking to a second line - "What is HR", "The Team"
   and the phone number all split, which predates the longer brand label but is
   made tighter by it. Labels never wrap; the gaps close up instead. */
.nav__links a,
.nav__actions .link-u span { white-space: nowrap; }
@media (min-width: 1181px) and (max-width: 1360px) {
  .nav__logo img { width: 160px; }
  .nav__right   { gap: 28px; }
  .nav__links   { gap: 16px; }
  .nav__actions { gap: 14px; }
}

/* The CTA has to be the dark treatment - a white button on a white bar would
   be invisible. Not scoped to .is-stuck any more. */
.nav .btn--light { background: var(--ink); color: #fff; border-color: var(--ink); }

/* Hovering the button drops the fill out to white and puts the label in black
   alongside the border. Gated on a real pointer: on a touchscreen :hover
   latches after a tap, which would strand the button in its hovered state
   until something else was tapped. */
@media (hover: hover) and (pointer: fine) {
  .nav .btn--light:hover { background: #fff; color: var(--ink); border-color: var(--ink); }
}

/* ---- Hamburger + drawer (mobile only; shown at the breakpoint) ---------- */
.nav__burger {
  display: none; flex: none;
  width: 44px; height: 44px; padding: 11px 9px;
  flex-direction: column; justify-content: space-between;
  background: transparent; border: 0; cursor: pointer;
}
.nav__burger span {
  display: block; height: 2px; width: 100%; border-radius: 2px;
  background: var(--ink); transition: background-color .4s var(--ease), transform .3s var(--ease), opacity .2s var(--ease);
}
body.drawer-open .nav__burger span { background: var(--ink); }
body.drawer-open .nav__burger span:nth-child(1) { transform: translateY(9px) rotate(45deg); }
body.drawer-open .nav__burger span:nth-child(2) { opacity: 0; }
body.drawer-open .nav__burger span:nth-child(3) { transform: translateY(-9px) rotate(-45deg); }

/* Drops out of the bar, full width - not a side panel. It sits BEHIND the nav
   (which lifts to z-index 41 when open) and slides down from under it, so the
   bar reads as the thing the panel came from. */
/* The CLIPPER. Fixed from the bottom of the bar to the foot of the screen, and
   it never moves. Everything above var(--nav-h) is outside it, so the panel
   sliding inside is cut off exactly at the navbar's lower edge - going in and,
   the part that was wrong before, coming back out. This is deliberately not
   solved by making the bar opaque: on close the bar's background transitions
   back to transparent while the panel is still travelling, so any opacity-based
   fix is a race between two durations. Clipping has no timing to get wrong.
   pointer-events pass through to the veil beneath; the panel re-enables them. */
.drawer {
  position: fixed; top: var(--nav-h); left: 0; right: 0; bottom: 0; z-index: 40;
  overflow: hidden; pointer-events: none;
  visibility: hidden;
  transition: visibility 0s linear .38s;
}
body.drawer-open .drawer { visibility: visible; transition: visibility 0s; }

.drawer__panel {
  pointer-events: auto;
  max-height: 100%; overflow-y: auto;   /* short viewports must still reach the CTA */
  background: var(--panel); color: var(--ink);
  padding: 26px var(--pad) 34px;
  display: flex; flex-direction: column; gap: 34px;
  transform: translateY(-100%);
  transition: transform .38s var(--ease);
}
body.drawer-open .drawer__panel {
  transform: none;
  /* shadow only while open, so nothing bleeds onto the page when closed */
  box-shadow: 0 26px 60px rgba(8, 20, 38, .3);
}
.drawer__links { display: flex; flex-direction: column; }
.drawer__links a {
  padding-block: 15px; border-bottom: 1px solid var(--hairline);
  font-size: 32px; font-weight: 300; letter-spacing: -1.1px; line-height: 1.15;
}
.drawer__foot { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.drawer__tel { font-size: 26px; font-weight: 400; letter-spacing: -.8px; }
.drawer__mail { font-size: 15px; color: var(--ink-65); word-break: break-word; }
.drawer__foot .btn { margin-top: 8px; }

.drawer__veil {
  position: fixed; inset: 0; z-index: 39;
  background: rgba(8, 20, 38, .5);
  opacity: 0; visibility: hidden;
  transition: opacity .38s var(--ease), visibility 0s linear .38s;
}
body.drawer-open .drawer__veil {
  opacity: 1; visibility: visible;
  transition: opacity .38s var(--ease), visibility 0s;
}
body.drawer-open { overflow: hidden; }
/* The drawer (z-index 40) covers the bar, which would bury the X the burger
   animates into and leave the veil as the only way out. Lift the bar above it;
   the rule under it would otherwise draw a line across the open panel. */
/* The bar stays in front of the panel and must be OPAQUE while open - over the
   hero it is transparent, and the panel would be visible sliding up through it
   on close. Solid white also makes the bar and the dropdown read as one surface,
   with the hairline as the divider between them. */
body.drawer-open .nav {
  z-index: 41;
  background: var(--panel);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border-bottom-color: var(--hairline);
}
/* ...and on that white bar the white logo would be invisible */

@media (prefers-reduced-motion: reduce) {
  .drawer, .drawer__panel, .drawer__veil, .nav__burger span { transition: none; }
}

/* --------------------------------------------------------------------------
   06 · Hero - split ground, bottom-anchored, caption bar on the photo
   -------------------------------------------------------------------------- */
.hero {
  position: relative; min-height: 100vh;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding-bottom: clamp(120px, 14vh, 170px); overflow: hidden;
}
.hero__left {
  position: absolute; inset: 0 auto 0 0; width: 49%; height: 100%;
  background: var(--navy); overflow: hidden;
}
.hero__left::before,
.hero__left::after {
  content: ""; position: absolute; border-radius: 50%;
  background: rgba(255, 255, 255, .045);
}
.hero__left::before { width: 132%; height: 96%; left: -46%; top: -34%; }
.hero__left::after  { width: 108%; height: 78%; left: -30%; bottom: -38%; background: rgba(255, 255, 255, .03); }

.hero__right { position: absolute; inset: 0 0 0 auto; width: 51%; height: 100%; overflow: hidden; background: var(--navy-deep); }
.hero__right video, .hero__right img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
/* Photo grade: a navy multiply pulls the frame into the palette, and the
   bottom-left ramp gives the index strip something to sit on. */
.hero__right::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(25deg, rgba(8, 18, 34, .88) 0%, rgba(8, 18, 34, .34) 42%, rgba(8, 18, 34, .06) 72%),
    linear-gradient(rgba(20, 46, 78, .42), rgba(20, 46, 78, .42));
}
.hero__scrim {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(8, 16, 28, .55) 0, rgba(8, 16, 28, 0) 190px),
    linear-gradient(to top,    rgba(8, 16, 28, .58) 0, rgba(8, 16, 28, 0) 260px);
}

.hero > .container { position: relative; z-index: 3; }
/* 600, not 560: "Practical HR Support" measures 570px at the H1 spec, so the
   old column split it after "HR". There is ~770px to the photo edge, so the
   extra 40 costs nothing. */
.hero__body { max-width: 600px; display: flex; flex-direction: column; gap: 38px; }
.hero__title { display: flex; flex-direction: column; gap: 20px; }
.hero__title h1 { color: #fff; }

.hero__orb { display: none; }   /* mobile only - see the mobile pass */
/* Just the lede now - the certification seals that used to sit above it were
   removed, and they still appear in the trust band further down the page. The
   paragraph gets the whole 600px column. */
.hero__proof { display: flex; flex-direction: column; align-items: flex-start; }
.hero__proof p {
  font-size: 16px; font-weight: 350; line-height: 1.6; letter-spacing: -.1px;
  color: var(--on-dark-80);
}

/* Short desktop screens (1366x768 and 1280x720 are both common) do not have
   the room the longer hero lede now needs, and the bottom-anchored stack was
   growing up underneath the fixed nav. Trim the hero's own spacing rather than
   the copy - nothing here changes on a normal-height display. */
@media (min-width: 861px) and (max-height: 900px) {
  .hero { padding-bottom: clamp(78px, 9vh, 120px); }
  .hero__body { gap: 26px; }
  .hero__title { gap: 14px; }
  .hero__title h1 { font-size: 56px; letter-spacing: -1.9px; }
  .hero__caption { bottom: clamp(22px, 2.6vh, 40px); }
}
@media (min-width: 861px) and (max-height: 760px) {
  .hero { padding-bottom: 62px; }
  .hero__body { gap: 22px; }
  .hero__title h1 { font-size: 48px; letter-spacing: -1.5px; }
  .hero__proof p { font-size: 15px; line-height: 1.55; }
}

/* caption bar - sits inside the right (photo) half only, centred, at the base */
.hero__caption {
  position: absolute; z-index: 3;
  left: 49%; right: 0; bottom: clamp(34px, 4vh, 56px);
  padding-inline: clamp(28px, 4vw, 76px);
}
/* one rule per label, broken by the gap - no vertical dividers */
.hero__caption-inner {
  display: flex; align-items: stretch; justify-content: center;
  gap: clamp(16px, 2.2vw, 38px);
}
.hero__caption-inner span {
  flex: 1 1 0; text-align: center;
  padding: 18px 6px 2px;
  border-top: 1px solid rgba(255, 255, 255, .30);
  font-size: 24px; font-weight: 300; letter-spacing: -.7px; line-height: 1.2; color: #fff;
}

/* --------------------------------------------------------------------------
   07 · About
   -------------------------------------------------------------------------- */
/* Label gutter + single content column - rhymes with the testimonial and the
   sticky pillars, and everything is top-aligned so nothing can float out of
   register the way a side-by-side lede does. */
.about { padding-top: 140px; }
.about__grid { display: flex; align-items: flex-start; gap: clamp(40px, 5vw, 100px); }
.about__gutter {
  flex: none; width: 150px; padding-top: 16px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 26px;
}

/* Owner portrait - small, directly under the section label, so it reads as a
   margin note rather than a feature image competing with the statement. */
.about__owner { display: flex; flex-direction: column; gap: 14px; }
.about__owner img {
  width: 100%; aspect-ratio: 4 / 5; object-fit: cover; object-position: 50% 12%;
}
.about__owner figcaption { font-size: 13px; line-height: 1.5; color: var(--ink-45); letter-spacing: 0; }
.about__owner figcaption b {
  display: block; font-size: 14px; font-weight: 600; color: var(--ink);
  letter-spacing: -.1px; margin-bottom: 2px;
}
.about__body { flex: 1 1 0; }
.about__statement { max-width: 30ch; }

/* Two editorial columns under a hairline. A grid rather than CSS multicol so
   each paragraph owns a column and nothing splits mid-sentence; the 1.4:1
   track ratio evens out the two unequal paragraphs. */
.about__cols {
  margin-top: clamp(40px, 4.4vw, 62px);
  padding-top: 34px;
  border-top: 1px solid var(--line);
  max-width: 1020px;
  display: grid; grid-template-columns: 1.4fr 1fr;
  column-gap: clamp(40px, 4vw, 66px);
}
.about__cta { margin-top: clamp(36px, 3.6vw, 50px); }

/* --------------------------------------------------------------------------
   08 · Services
   -------------------------------------------------------------------------- */
.services { padding-top: 150px; display: flex; flex-direction: column; gap: 60px; }
/* mobile only - desktop reads the heading in context and doesn't need the label */
.services__eyebrow { display: none; }
/* single line above the panels - no max-width, it should not wrap at desktop */
.services__title { max-width: none; }

.svc-row { display: flex; gap: 20px; padding-inline: 15px; }
.svc {
  position: relative; flex: 1 1 0; min-height: 600px;
  display: flex; align-items: center; overflow: hidden;
}
.svc__img { position: absolute; inset: 0; z-index: 0; }
.svc__img img { width: 100%; height: 100%; object-fit: cover; }
.svc__tint { position: absolute; inset: 0; z-index: 1; background: rgba(0, 0, 0, .6); }
.svc__wash {
  position: absolute; inset: 0; z-index: 1; background: var(--navy);
  transform: translateY(-100%); transition: transform .55s var(--ease);
}
.svc:hover .svc__wash { transform: translateY(0); }

.svc__body {
  position: relative; z-index: 2;
  flex: 1 1 0; align-self: stretch; max-width: 400px;
  display: flex; flex-direction: column; justify-content: space-between; padding: 40px;
}
.svc__body h3 { color: #fff; max-width: 250px; }
.svc__foot { display: flex; flex-direction: column; align-items: flex-start; gap: 28px; }
.svc__foot p { font-size: 17px; font-weight: 350; line-height: 1.5; letter-spacing: -.2px; color: #fff; }


/* --------------------------------------------------------------------------
   09 · What is HR - sticky-scroll read
   -------------------------------------------------------------------------- */
.pillars { padding-block: 110px 40px; }
.pillars__grid { display: flex; align-items: flex-start; gap: clamp(60px, 7vw, 120px); }

.pillars__aside {
  position: sticky; top: 130px;
  width: 33%; flex: none;
  display: flex; flex-direction: column; gap: 22px;
}
/* No max-width: the heading needs the full column so the four short names hold
   one line. 38px leaves ~32px of slack on the widest of those four while still
   letting the fifth wrap, which is the intended behaviour. */
.pillars__aside h2 {
  max-width: none;
  font-size: 38px; letter-spacing: -1.15px;
}
/* The heading itself is live: "HR is <pillar>", the pillar name tracking the
   block in view. No reserved height - the rule below hugs the text and drops a
   line when a longer name wraps. */
/* balance evens the two-line case - "HR is A Workplace / People Enjoy" rather
   than orphaning "Enjoy". Self-adjusting, so it survives copy and width edits;
   degrades to normal wrapping where unsupported. */
.pillars__heading { text-wrap: balance; }
.pillars__heading em {
  font-style: normal; color: var(--accent);
  transition: opacity .18s var(--ease);
}
.pillars__count {
  margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--line);
  display: flex; align-items: baseline; gap: 8px;
}
.pillars__count b {
  font-size: 30px; font-weight: 300; letter-spacing: -.9px; line-height: 1;
  color: var(--accent);
}
.pillars__count .micro { color: var(--muted); }
@media (prefers-reduced-motion: reduce) { .pillars__heading em { transition: none; } }

.pillars__list { flex: 1 1 0; display: flex; flex-direction: column; gap: clamp(80px, 8vw, 120px); }
.pillar { display: flex; flex-direction: column; gap: 26px; max-width: 700px; }
.pillar__fig {
  /* The old rounded-right box became the letterform itself. Height is unchanged:
     it was aspect-ratio 3/2, so the height was two thirds of the column width.
     Setting width to (2/3 x --ar) of the column and the ratio to --ar gives a
     box that hugs the letter while resolving to exactly that same height. */
  width: calc(66.6667% * var(--ar));
  aspect-ratio: var(--ar);
  position: relative; overflow: hidden;

  /* Outlines lifted from the site's own Manrope file at weight 800, not <text>
     in the mask: a data-URI SVG cannot reach the page @font-face, so a text
     mask would quietly fall back to a system face. Masking the container and
     not the img means the tint overlay below is clipped to the letter too. */
  -webkit-mask-image: var(--glyph);
          mask-image: var(--glyph);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
}
.pillar[data-p="01"] .pillar__fig { --ar: 0.9013; --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1352 1500'%3E%3Cpath transform='translate(-60 1470) scale(1 -1)' d='M758 -30Q542 -30 385.5 64.0Q229 158 144.5 327.0Q60 496 60 720Q60 944 144.5 1113.0Q229 1282 385.5 1376.0Q542 1470 758 1470Q1006 1470 1174.5 1347.0Q1343 1224 1412 1014L1138 938Q1098 1069 1003.0 1141.5Q908 1214 758 1214Q621 1214 529.5 1153.0Q438 1092 392.0 981.0Q346 870 346 720Q346 570 392.0 459.0Q438 348 529.5 287.0Q621 226 758 226Q908 226 1003.0 299.0Q1098 372 1138 502L1412 426Q1343 216 1174.5 93.0Q1006 -30 758 -30Z'/%3E%3C/svg%3E"); }
.pillar[data-p="02"] .pillar__fig { --ar: 0.7333; --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1100 1500'%3E%3Cpath transform='translate(-140 1470) scale(1 -1)' d='M140 0V1440H748Q769 1440 804.5 1438.5Q840 1437 868 1432Q997 1412 1079.5 1347.0Q1162 1282 1201.0 1183.5Q1240 1085 1240 964Q1240 843 1200.5 744.5Q1161 646 1078.5 581.0Q996 516 868 496Q840 492 804.0 490.0Q768 488 748 488H412V0ZM412 742H736Q757 742 782.0 744.0Q807 746 828 752Q883 767 913.0 802.5Q943 838 954.5 881.5Q966 925 966 964Q966 1003 954.5 1046.5Q943 1090 913.0 1125.5Q883 1161 828 1176Q807 1182 782.0 1184.0Q757 1186 736 1186H412Z'/%3E%3C/svg%3E"); }
.pillar[data-p="03"] .pillar__fig { --ar: 0.7333; --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1100 1500'%3E%3Cpath transform='translate(-140 1470) scale(1 -1)' d='M140 0V1440H748Q769 1440 804.5 1438.5Q840 1437 868 1432Q997 1412 1079.5 1347.0Q1162 1282 1201.0 1183.5Q1240 1085 1240 964Q1240 843 1200.5 744.5Q1161 646 1078.5 581.0Q996 516 868 496Q840 492 804.0 490.0Q768 488 748 488H412V0ZM412 742H736Q757 742 782.0 744.0Q807 746 828 752Q883 767 913.0 802.5Q943 838 954.5 881.5Q966 925 966 964Q966 1003 954.5 1046.5Q943 1090 913.0 1125.5Q883 1161 828 1176Q807 1182 782.0 1184.0Q757 1186 736 1186H412Z'/%3E%3C/svg%3E"); }
.pillar[data-p="04"] .pillar__fig { --ar: 0.5947; --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 892 1500'%3E%3Cpath transform='translate(-160 1470) scale(1 -1)' d='M160 0V1440H432V254H1052V0Z'/%3E%3C/svg%3E"); }
.pillar[data-p="05"] .pillar__fig { --ar: 0.6267; --glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 940 1500'%3E%3Cpath transform='translate(-140 1470) scale(1 -1)' d='M140 0V1440H1080V1186H412V878H960V624H412V254H1080V0Z'/%3E%3C/svg%3E"); }
.pillar__fig img {
  width: 100%; height: 100%; object-fit: cover;
  filter: grayscale(1) contrast(1.05) brightness(.95);
}
.pillar__fig::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(200deg, rgba(23, 57, 95, .46), rgba(14, 35, 64, .22));
  mix-blend-mode: multiply;
}
.pillar__head {
  display: flex; align-items: baseline; gap: 18px;
  border-top: 1px solid var(--line); padding-top: 22px;
}
.pillar__head b { color: var(--accent); flex: none; }
.pillar__head h3 { font-size: 34px; letter-spacing: -1.1px; line-height: 1.15; }
.pillar > p { max-width: 58ch; }

/* --------------------------------------------------------------------------
   10 · Statistics
   -------------------------------------------------------------------------- */
.stats-sec { padding-block: 40px 150px; }
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(28px, 3vw, 56px); }
.stat { padding-top: 24px; border-top: 1px solid var(--ink); display: flex; flex-direction: column; gap: 10px; }
.stat__n { font-size: 54px; font-weight: 300; letter-spacing: -1.9px; line-height: 1.05; min-height: 2.1em; }
.stat__c { font-size: 17px; font-weight: 350; line-height: 1.5; letter-spacing: -.2px; color: var(--ink-65); }

/* --------------------------------------------------------------------------
   11 · Team band
   -------------------------------------------------------------------------- */
/* Navy, not the --navy-deep the Why panel uses: the two dark sections are
   adjacent and need to read as two, not one long block. */
.team {
  position: relative; overflow: hidden;
  padding-block: 130px; min-height: 640px;
  display: flex; align-items: center;
  background:
    radial-gradient(110% 140% at 24% 4%, rgba(255, 255, 255, .05) 0%, rgba(255, 255, 255, 0) 60%),
    var(--navy-grade);
}
/* Same depth treatment as the testimonial band, but BOTH circles sit left - the
   right 52% is under the headshot mosaic, so anything placed there is simply not
   seen. The highlight is pulled to 24% for the same reason: it belongs over the
   copy, not behind the photographs. */
.team::before,
.team::after {
  content: ""; position: absolute; border-radius: 50%; pointer-events: none; z-index: 0;
}
.team::before { width: 920px;  height: 920px;  left: -310px; top: -340px;    background: var(--orb); }
.team::after  { width: 1060px; height: 1060px; left: -250px; bottom: -640px; background: var(--orb-soft); }

/* A solid wall of faces filling the right half, bleeding to the viewport edge:
   no gutters between tiles and no navy showing through, so the eight read as one
   surface rather than eight cards. Absolute rather than a flex child because the
   panel has to match the section's full height, which the copy column sets. */
.team__roster {
  position: absolute; top: 0; right: 0; bottom: 0; width: 52%;
  /* above the circle ornaments: .team::after is a later sibling, so at an equal
     z-index it would paint a white haze over the bottom-left photographs */
  list-style: none; z-index: 1;
  display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(2, 1fr);
}
.team__member { position: relative; overflow: hidden; }
.team__member img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  /* In colour. The light hand here is the only thing left evening out eight
     backdrops shot on eight different days -- a touch off the saturation and a
     touch onto the contrast, not enough to read as a filter. */
  filter: saturate(.94) contrast(1.03);
}
/* keeps the name legible over whatever tone the tile bottom happens to be */
.team__member::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 45%; pointer-events: none;
  background: linear-gradient(to top, rgba(8, 20, 38, .82), rgba(8, 20, 38, 0));
}
.team__member span {
  position: absolute; z-index: 2; left: 16px; right: 10px; bottom: 13px;
  font-size: 13px; font-weight: 500; letter-spacing: -.1px; color: #fff;
}

.team .container { position: relative; z-index: 2; }
.team__body { width: 41%; display: flex; flex-direction: column; gap: 20px; }
.team__body h2 { color: #fff; }
/* sits on top of the column's 20px gap, landing near the About CTA's offset */
.team__cta { margin-top: clamp(14px, 1.4vw, 22px); }

/* --------------------------------------------------------------------------
   12 · Why KHRS|HR (dark)
   -------------------------------------------------------------------------- */
.why { background: var(--navy-deep); color: #fff; padding-block: 150px; }
.why__grid { display: flex; align-items: flex-start; justify-content: space-between; gap: 80px; }
.why__lead { width: 46%; display: flex; flex-direction: column; gap: 20px; }
.why__lead h2 { color: #fff; }
.why__points { width: 46%; display: flex; flex-direction: column; }
.why__pt { padding-block: 34px; border-top: 1px solid var(--line-dark); display: flex; gap: 30px; }
.why__pt:last-child { border-bottom: 1px solid var(--line-dark); }
.why__pt-n { color: var(--accent-soft); padding-top: 8px; flex: none; }
.why__pt h3 { font-size: 24px; letter-spacing: -.7px; color: #fff; margin-bottom: 10px; }

/* --------------------------------------------------------------------------
   13 · Trust band + intake questionnaire

   The band is the slot the testimonials and then the questionnaire occupied;
   it keeps the same navy treatment so the page's rhythm is unchanged again.
   The questionnaire itself now lives on the contact page and is styled for that
   page's light ground - the same look as the single-step form it replaced.
   -------------------------------------------------------------------------- */
.trust {
  position: relative; overflow: hidden;
  margin-top: clamp(70px, 6vw, 100px);
  padding-block: clamp(56px, 4.4vw, 76px);
  color: #fff;
  background:
    radial-gradient(120% 150% at 50% 8%, rgba(255, 255, 255, .05) 0%, rgba(255, 255, 255, 0) 62%),
    var(--navy-grade);
}
.trust::before,
.trust::after {
  content: ""; position: absolute; border-radius: 50%; pointer-events: none; z-index: 0;
}
.trust::before { width: 980px;  height: 980px;  left: -270px;  top: -415px;    background: var(--orb); }
.trust::after  { width: 1120px; height: 1120px; right: -330px; bottom: -580px; background: var(--orb-soft); }
.trust .container { position: relative; z-index: 1; }

.trust__grid {
  display: grid; grid-template-columns: auto 1fr;
  gap: clamp(34px, 4vw, 76px); align-items: center;
}

/* The seals keep their own colours. They are certification marks belonging to
   SHRM and HRCI - recolouring one to match a palette misrepresents it and
   breaks both bodies' usage rules. They sit on a white disc instead, which is
   what lets gold and purple read as deliberate against the navy. */
.trust__seals { display: flex; align-items: center; gap: 18px; margin: 0; }
.trust__seals li {
  width: 108px; height: 108px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%; background: #fff;
}
/* The source files are 160px, so 88 is still inside their native resolution. */
.trust__seals img { width: 88px; height: 88px; }

.trust__stats {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(20px, 2.4vw, 44px); margin: 0;
  padding-left: clamp(30px, 3.4vw, 62px); border-left: 1px solid var(--line-dark);
}
.trust__stat b {
  display: block;
  font-size: clamp(34px, 3vw, 46px); font-weight: 300; letter-spacing: -1.6px; line-height: 1;
  color: #fff;
}
.trust__stat span {
  display: block; margin-top: 10px;
  font-size: 15px; font-weight: 350; line-height: 1.4; letter-spacing: -.2px;
  color: var(--on-dark-70);
}

/* ---- intake questionnaire  ·  PARKED, NOT CURRENTLY ON ANY PAGE ----
   The four-step form was pulled off the contact page for launch; its
   markup is kept at ../_parked/questionnaire-form.html (outside the
   deploy root, so it is never served). These rules and
   block 9 of site.js are left in place so dropping that markup back onto
   the page is the only step needed to restore it.
   Light ground, the same as the single-step form this replaced: no panel, no
   box, white fields on the page's own paper. Everything below therefore leans
   on the base .field styles and only adds what the steps need. */

/* ---- the stepper ---- */
/* space-between rather than a fixed gap: the four steps then use whatever width
   the column has and stay on one line, instead of wrapping 3+1 the moment it
   narrows. */
.qz__rail { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px 14px; margin: 34px 0 30px; }
.qz__rail li { display: flex; align-items: center; gap: 10px; color: var(--ink-45); transition: color .35s var(--ease); }
.qz__rail li.is-on, .qz__rail li.is-done { color: var(--ink); }
.qz__n {
  width: 26px; height: 26px; flex: none; display: grid; place-items: center;
  border: 1px solid var(--line); border-radius: 50%;
  font-size: 12px; font-weight: 600;
  transition: background-color .35s var(--ease), border-color .35s var(--ease), color .35s var(--ease);
}
.qz__rail li.is-on .qz__n { background: var(--navy); border-color: var(--navy); color: #fff; }
.qz__rail li.is-done .qz__n { background: var(--accent); border-color: var(--accent); color: #fff; }
.qz__l { font-size: 13px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
/* the rail is decoration for a sighted reader; the count is the spoken version */
.qz__count { position: absolute; left: -9999px; }

/* ---- panels ---- */
.qz__panel { border: 0; padding: 0; margin: 0; min-inline-size: 0; }
.qz__legend { position: absolute; left: -9999px; }
/* Default is every panel open, which is what a no-JS visitor gets: one long
   form that still submits. The step behaviour is added only once JS is present. */
.js .qz__panel { display: none; }
/* A holding value only, so nothing flashes a short panel before the script runs.
   The real lock is measured at runtime - the tallest step changes with width
   because the option pills rewrap, so no single number works. See block 8. */
.js .qz__panel.is-active { display: block; min-height: 420px; }
.qz__panel + .qz__panel { margin-top: 30px; }
.js .qz__panel + .qz__panel { margin-top: 0; }
/* Direct children only. Without the > this also matched the second .field
   inside a .form__row - they are adjacent siblings too - which pushed the
   right-hand column of every pair 22px below the left. */
.qz__panel > .field + .field, .qz__panel > .form__row + .field,
.qz__panel > .field + .form__row, .qz__panel > .form__row + .form__row { margin-top: 22px; }

/* the question above a group of options, matching the field labels beside it */
.qz__q {
  display: block; margin-bottom: 14px;
  font-size: 12px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-65);
}

/* ---- radio / checkbox options as pills ---- */
.qz__opts { display: flex; flex-wrap: wrap; gap: 10px; }
.opt { position: relative; }
/* the input stays in the layer under its own label so it remains focusable and
   reachable by keyboard - visually hidden, not display:none */
.opt input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.opt span {
  display: block; padding: 11px 18px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 50px;
  font-size: 15px; font-weight: 350; letter-spacing: -.2px; color: var(--ink-65);
  transition: background-color .3s var(--ease), border-color .3s var(--ease), color .3s var(--ease);
}
.opt:hover span { border-color: var(--ink-45); color: var(--ink); }
/* navy rather than the accent: a checked pill sits next to the navy step marker
   and the dark submit button, and a third colour there is one too many */
.opt input:checked + span { background: var(--navy); border-color: var(--navy); color: #fff; font-weight: 500; }
.opt input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ---- nav ---- */
.qz__nav { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 34px; }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--ghost:hover { border-color: var(--ink); }
/* with no JS there are no steps to move between, so only the real submit shows */
.qz__nav [data-qz="prev"], .qz__nav [data-qz="next"] { display: none; }
.js .qz__nav [data-qz="prev"], .js .qz__nav [data-qz="next"] { display: inline-flex; }
.qz__nav [hidden] { display: none !important; }
.qz__alt { margin-left: auto; font-size: 15px; color: var(--ink-45); }
.qz__alt a { color: var(--ink); border-bottom: 1px solid var(--line); }
.qz__alt a:hover { color: var(--accent); border-color: var(--accent); }

/* Below ~1360 the column cannot carry four labelled steps on one line, and a
   3+1 wrap reads as a mistake. Only the label goes - the numbered markers still
   show position, and the spoken "Step n of 4" is unaffected. */
@media (max-width: 1360px) {
  .qz__l { display: none; }
  .qz__rail { justify-content: flex-start; gap: 14px; }
}

.qz__status { margin-top: 18px; }

/* --------------------------------------------------------------------------
   14 · Get started
   -------------------------------------------------------------------------- */
.cta { position: relative; padding-block: 120px; overflow: hidden; background: var(--navy-deep); }
.cta > picture img { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; object-fit: cover; }
.cta__scrim { position: absolute; inset: 0; z-index: 1; background: rgba(14, 35, 64, .78); }
.cta .container { position: relative; z-index: 2; display: flex; align-items: flex-start; justify-content: space-between; gap: 60px; }
.cta__body { flex: 1 1 0; max-width: 640px; display: flex; flex-direction: column; align-items: flex-start; gap: 38px; }
/* the form is the primary route now, so the phone number steps back to a rule
   link beside it rather than competing as a second filled button */
.cta__actions { display: flex; align-items: center; gap: 30px; flex-wrap: wrap; }
.cta__actions .link-u { color: var(--on-dark-70); }
.cta__actions .link-u:hover { color: #fff; }
.cta__body h2 { color: #fff; }
.cta__body .body { max-width: 460px; }
.cta__title { display: flex; flex-direction: column; gap: 12px; }

.cta__card {
  flex: none; width: 420px;
  border: 1px solid var(--line-dark);
  background: rgba(255, 255, 255, .06);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  padding: 34px; display: flex; flex-direction: column; gap: 24px;
}
.cc { display: flex; flex-direction: column; gap: 5px; }
.cc__k { font-size: 13px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--on-dark-70); }
.cc__v { font-size: 20px; font-weight: 350; letter-spacing: -.4px; color: #fff; line-height: 1.4; }
a.cc__v { transition: color .3s var(--ease); }
a.cc__v:hover { color: var(--accent-soft); }
.cc__v small { display: block; font-size: 16px; color: var(--on-dark-70); }

/* --------------------------------------------------------------------------
   15 · Footer
   -------------------------------------------------------------------------- */
.foot { background: var(--bg); padding-bottom: 30px; }
/* Contact has no band of its own between the form and the footer, so the page
   ran straight into it. Drawn on .foot__top, not on .container: the container
   carries the page gutter as padding, so a border there runs the full bleed,
   while .foot__top sits inside that padding and matches the hairline it already
   draws along its own bottom edge. The two rules then line up exactly. */
.foot--ruled .foot__top { border-top: 1px solid var(--hairline); }
.foot__top { display: flex; gap: 40px; border-bottom: 1px solid var(--hairline); }
.foot__brand { width: 32%; padding: 100px 60px 60px 0; border-right: 1px solid var(--hairline); display: flex; flex-direction: column; gap: 30px; }
.foot__brand img { width: 220px; }
.foot__brand p { font-size: 17px; color: var(--muted); max-width: 340px; }
.foot__links { width: 28%; padding: 100px 30px 60px 0; border-right: 1px solid var(--hairline); display: flex; gap: 80px; }
.foot__col { display: flex; flex-direction: column; gap: 24px; }
.foot__col a { font-size: 13px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; transition: color .3s var(--ease); }
.foot__col a:hover { color: var(--accent); }
.foot__contact { width: 33%; padding: 100px 0 40px; display: flex; flex-direction: column; gap: 34px; }
.foot__addr { font-size: 28px; font-weight: 300; letter-spacing: -.9px; line-height: 1.25; color: var(--muted); }
.foot__contact-links { display: flex; flex-direction: column; gap: 15px; align-items: flex-start; }
.foot__contact-links a { font-size: 22px; font-weight: 400; letter-spacing: -.5px; border-bottom: 1px solid var(--ink); padding-bottom: 2px; }
.foot__bar { padding-top: 26px; display: flex; justify-content: space-between; gap: 24px; font-size: 15px; color: var(--muted); }

/* The GT credit: the monogram alone, with the whole credit carried in the alt
   text so the link still announces itself rather than reading as an unlabelled
   image. The asset is a flat black glyph, so weight is matched to the grey
   text opposite it with opacity rather than a second recoloured file; that also
   gives the hover state for free and survives a change to --muted.
   Sized off the 48px-tall source (3x) so it stays crisp on retina. */
.foot__gt { display: inline-flex; align-items: center; }
.foot__gt img {
  width: auto; height: 16px;
  opacity: .45;                        /* lands on ~#8e8e8e over the footer */
  transition: opacity .35s var(--ease);
}
.foot__gt:hover img { opacity: 1; }
.foot__gt:hover { color: var(--ink); }

/* --------------------------------------------------------------------------
   16 · Motion
   -------------------------------------------------------------------------- */
html.js .rv { opacity: 0; transform: translateY(30px); }
html.js .rv.is-in {
  opacity: 1; transform: none;
  transition: opacity .8s var(--ease), transform .8s var(--ease);
  transition-delay: var(--d, 0s);
}
@media (prefers-reduced-motion: reduce) {
  html.js .rv { opacity: 1; transform: none; transition: none; }
  .svc__wash { transition: none; }
}

/* --------------------------------------------------------------------------
   17 · Interior page header  (team.html and every page after it)
   The Vuna Partners archetype, restated in KHRS|HR's language: one full-bleed
   graded panel, the headline stacked top-left, and the lede sitting on a
   baseline at the foot with a single meta figure opposite it. Reuses the
   homepage depth kit rather than inventing a second dark treatment.
   -------------------------------------------------------------------------- */
/* No min-height. The panel used to be held open to 74svh with the title and the
   foot rule pushed to opposite ends, which is where the gap under the headline
   came from - it is now sized by its own content and padding. */
.phead {
  position: relative; overflow: hidden;
  padding: calc(var(--nav-h) + 84px) 0 58px;
  display: flex; align-items: stretch;
  color: #fff;
  background:
    radial-gradient(105% 130% at 18% 8%, rgba(255, 255, 255, .05) 0%, rgba(255, 255, 255, 0) 58%),
    var(--navy-grade);
}
.phead::before,
.phead::after {
  content: ""; position: absolute; border-radius: 50%; pointer-events: none; z-index: 0;
}
.phead::before { width: 900px;  height: 900px;  left: -280px;  top: -330px;    background: var(--orb); }
.phead::after  { width: 1150px; height: 1150px; right: -300px; bottom: -640px; background: var(--orb-soft); }

.phead__grid {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; gap: 30px; width: 100%;
}
.phead__title { display: flex; flex-direction: column; gap: 22px; }
/* No measure cap, so the headline takes one line wherever the container allows
   it. balance only engages once it has to wrap, and stops the last word being
   stranded alone on line two at the widths where it does. */
.phead__title h1 { color: #fff; text-wrap: balance; }
/* The lede sits alone on the foot rule and is given room to run - set at a
   step above body copy and measured in ch so it breaks to three comfortable
   lines on a wide screen rather than a narrow column pinned to one side. */
/* Headline only - the panel's floor comes up to meet it. 76px against the 84px
   of clearance under the navbar, so the headline sits optically centred rather
   than pinned to the top of a box that is taller than its contents. */
.phead--tight { padding-bottom: 76px; }

.phead__foot { padding-top: 34px; border-top: 1px solid var(--line-dark); }
.phead__lede {
  max-width: 84ch;
  font-size: clamp(19px, 1.45vw, 23px); font-weight: 350; line-height: 1.5;
  letter-spacing: -.35px; color: var(--on-dark-70);
}

/* --------------------------------------------------------------------------
   18 · Team - scroll-pinned horizontal track
   The section is tall. The stage inside it sticks to the viewport, and the
   track translates left in proportion to how far you have scrolled through
   that height - so the whole team passes before the page moves on. No
   scrollbar, no arrows, and no independent scroll area to get lost in.

   DEFAULT here is the fallback: a plain grid. The pinned behaviour only
   engages when JS adds .is-pinned, which it refuses to do under reduced
   motion or below 1024px, where hijacking the scroll is hostile.
   -------------------------------------------------------------------------- */
.pin { position: relative; }
.pin__stage { position: relative; padding-block: 110px 120px; }
.pin__track {
  list-style: none; margin: 0;
  /* The first card has to start on the same line as the eyebrow and headline,
     which sit inside .container - so this reproduces that box exactly: the
     centring margin once --wrap is reached, plus the gutter. Measured in % and
     not vw on purpose; 100vw counts the scrollbar the container does not, which
     was leaving the track 7px out even where the arithmetic agreed. */
  padding-inline: calc(max((100% - var(--wrap)) / 2, 0px) + var(--pad));
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 48px clamp(14px, 1.6vw, 22px);
}

/* ---- pinned mode ---- */
.pin.is-pinned .pin__stage {
  position: sticky; top: 0;
  height: 100svh; overflow: hidden;
  padding-block: 0;
  display: flex; flex-direction: column; justify-content: center;
}
.pin.is-pinned .pin__track {
  display: flex; grid-template-columns: none; gap: clamp(14px, 1.6vw, 22px);
  /* translated by JS; promoted so the slide stays on the compositor */
  will-change: transform;
}
/* Sized off the viewport HEIGHT as well as its width: the card is a 3:4 frame
   plus ~135px of type, and the stage is only 100svh tall, so a width-only rule
   overflows the stage on a short window. 44svh keeps the whole card on screen
   down to a 600px-tall viewport. */
.pin.is-pinned .member { flex: 0 0 clamp(236px, min(26vw, 44svh), 380px); }

.member { display: flex; flex-direction: column; align-items: flex-start; }

/* 3:4 rather than the homepage tiles' 4:5. These frames are pulled back to
   three-quarter length, so they need the extra height - a 4:5 box would crop
   the standing shots back to a headshot and undo the point of the page. */
.member__shot {
  position: relative; width: 100%; aspect-ratio: 3 / 4;
  overflow: hidden; background: var(--navy);
}
.member__img { position: absolute; inset: 0; display: block; }
.member__img img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  /* the same light hand as the homepage mosaic - eight backdrops, one look */
  filter: saturate(.94) contrast(1.03);
  transition: transform .6s var(--ease);
}

/* The second, less formal take crossfades in over the first. Only five of the
   eight have one; the rest have no --alt element and simply hold still.
   focus-within so it is reachable by keyboard through the LinkedIn button. */
.member__img--alt { opacity: 0; transition: opacity .45s var(--ease); }
.member:hover .member__img--alt,
.member:focus-within .member__img--alt { opacity: 1; }
.member:hover .member__img img,
.member:focus-within .member__img img { transform: scale(1.03); }

.member__role { margin-top: 22px; color: var(--muted); }
.member__role--todo { color: var(--accent); }   /* visible placeholder, not a real title */
.member__name { font-size: 24px; font-weight: 400; letter-spacing: -.7px; line-height: 1.2; }
.member__creds { margin-top: 4px; font-size: 14px; color: var(--ink-45); letter-spacing: 0; }

/* Name and mark share a line. baseline would hang the glyph off a 24px cap
   height; centring it on the name reads level. */
.member__id { display: flex; align-items: center; gap: 11px; margin-top: 7px; }

/* the mark alone - no chip, no label. Three of the eight have one, and a
   bordered button at four different heights was more furniture than signal. */
.member__li {
  flex: none; display: inline-flex; width: 22px; height: 22px;
  color: var(--ink-45);
  transition: color .3s var(--ease), transform .3s var(--ease);
}
.member__li svg { width: 100%; height: 100%; fill: currentColor; }
.member__li:hover { color: var(--accent); transform: translateY(-1px); }

/* ---- biography pane ----
   A navy panel the height of the photograph that drops down over it. It uses
   the same graded navy as the page header so it reads as the site's own
   surface rather than a tooltip pasted on top. */
.member__bio {
  position: absolute; inset: 0; z-index: 2;
  padding: 26px 24px 64px;              /* the cross sits in that bottom band */
  overflow-y: auto; overscroll-behavior: contain;
  color: var(--on-dark-70);
  background:
    radial-gradient(120% 90% at 12% 0%, rgba(255, 255, 255, .06) 0%, rgba(255, 255, 255, 0) 60%),
    var(--navy-grade);
  transform: translateY(-100%);
  /* visibility, not display: it keeps the pane out of the tab order and the
     accessibility tree while still leaving the transform something to animate */
  visibility: hidden;
  transition: transform .5s var(--ease), visibility .5s;
}
.member__bio.is-open { transform: none; visibility: visible; }
.member__bio p { font-size: 13.5px; line-height: 1.62; letter-spacing: -.1px; }
.member__bio p + p { margin-top: 13px; }

.member__more {
  position: absolute; right: 13px; bottom: 13px; z-index: 3;
  width: 34px; height: 34px; padding: 0;
  display: grid; place-items: center;
  border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(255, 255, 255, .92); color: var(--navy);
  /* Melanie's and Danny's backdrops are pale enough that a white disc on its own
     nearly disappears; the shadow is what holds its edge on a light photograph. */
  box-shadow: 0 1px 6px rgba(8, 20, 38, .2);
  transition: background-color .3s var(--ease), color .3s var(--ease),
              transform .4s var(--ease);
}
.member__more svg {
  width: 15px; height: 15px;
  fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round;
}
.member__more:hover { background: #fff; }
/* the same cross turned 45° is the close affordance - one glyph, two states */
.member__more[aria-expanded="true"] {
  background: var(--accent); color: #fff; transform: rotate(45deg);
}

@media (prefers-reduced-motion: reduce) {
  /* the swap still happens, it just stops moving and stops easing */
  .member__img img, .member__img--alt { transition: none; }
  .member:hover .member__img img,
  .member:focus-within .member__img img { transform: none; }
  .member__li:hover { transform: none; }
  .member__bio { transition: none; transform: none; opacity: 0; }
  .member__bio.is-open { opacity: 1; }
  .member__more { transition: none; }
  .member__more[aria-expanded="true"] { transform: none; }
}

/* Hover is a pointer idea. On touch there is no hover state to leave, so the
   alt frame would either never show or stick after a tap - neither is useful. */
@media (hover: none) {
  .member__img--alt { display: none; }
}

/* --------------------------------------------------------------------------
   19 · Contact page - inquiry form beside the direct details
   The form carries the page; the details column is a navy panel so the two
   halves read as separate offers rather than one long column of inputs. It
   reuses .cta__card / .cc wholesale - those are already built white-on-navy,
   so only the width and the flat ground change here.
   -------------------------------------------------------------------------- */
.contact { padding-block: 110px 130px; }
.contact__grid {
  display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, .74fr);
  gap: clamp(44px, 5vw, 96px); align-items: start;
}
.contact__form h2 { max-width: 20ch; }
.contact__note { margin-top: 16px; max-width: 52ch; }

/* the panel trails the form on a long page rather than leaving dead space */
.contact__aside { position: sticky; top: calc(var(--nav-h) + 26px); }
/* The aerial under a navy scrim, the same device as the homepage CTA band -
   so the two dark panels on the site read as one treatment, not two.
   isolation:isolate keeps the z-index stack local to the card. */
.contact__aside .cta__card {
  position: relative; overflow: hidden; isolation: isolate;
  width: 100%;
  background: var(--navy-deep);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  border-color: transparent;
}
.contact__card > picture img {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover;
}
/* .82, not the band's .78: this panel is a fifth of the width, so the same
   photograph arrives far busier per square inch and the type needs the extra. */
.contact__scrim { position: absolute; inset: 0; z-index: 1; background: rgba(14, 35, 64, .82); }
.contact__card .cc { position: relative; z-index: 2; }

.form { margin-top: 40px; display: flex; flex-direction: column; gap: 22px; }
.form__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; }

.field label {
  display: block; margin-bottom: 9px;
  font-size: 12px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-65);
}
.field__req { color: var(--accent); }

.field input, .field select, .field textarea {
  width: 100%; font: inherit; color: var(--ink);
  /* 16px is deliberate: anything smaller and iOS zooms the page on focus */
  font-size: 16px; font-weight: 350; letter-spacing: -.2px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 4px;
  padding: 14px 16px;
  transition: border-color .3s var(--ease), box-shadow .3s var(--ease);
}
.field textarea { resize: vertical; min-height: 132px; line-height: 1.55; }

/* native select chrome varies wildly between platforms; this normalises it and
   supplies the chevron as a data URI so nothing extra has to be fetched */
.field select {
  appearance: none; -webkit-appearance: none;
  padding-right: 44px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23111317' stroke-opacity='.5' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 16px center; background-size: 12px 8px;
}

.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(28, 111, 196, .15);
}
/* Nothing is red until the sender has actually done something wrong.
   :user-invalid waits for interaction, unlike :invalid which fires on an
   untouched empty required field. aria-invalid is what the submit handler sets
   on a blind submit, so "check the highlighted fields" is true in that case too
   - and it carries to a screen reader rather than being colour alone. */
/* Deliberately two rules, not one comma list. An unknown selector invalidates
   the whole list it sits in, so pairing these would let a browser without
   :user-invalid silently drop the aria-invalid styling as well - and that is
   the half the submit handler depends on. */
.field [aria-invalid="true"] { border-color: #b3261e; }
.field [aria-invalid="true"]:focus-visible { box-shadow: 0 0 0 3px rgba(179, 38, 30, .15); }
.field input:user-invalid, .field select:user-invalid, .field textarea:user-invalid { border-color: #b3261e; }

/* the honeypot: off-screen rather than display:none, which some bots skip */
.field--trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }


.form__foot { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; margin-top: 4px; }
.form__alt { font-size: 15px; color: var(--ink-45); }
.form__alt a { color: var(--ink); border-bottom: 1px solid var(--line); }
.form__alt a:hover { color: var(--accent); border-color: var(--accent); }

.form__status { font-size: 15px; line-height: 1.5; color: var(--ink-65); }
.form__status:empty { display: none; }
.form__status.is-bad { color: #b3261e; }
.form__status.is-good { color: var(--accent); }

/* --------------------------------------------------------------------------
   20 · Mobile pass
   Mobile-only. Desktop above 1180 is untouched.
   1180 = stack the side-by-side layouts.  700 = phone sizing and density.
   -------------------------------------------------------------------------- */
@media (max-width: 1180px) {
  :root { --pad: 40px; }
  .h1 { font-size: 48px; }
  .h2 { font-size: 40px; }
  .h2-sm { font-size: 32px; }

  /* nav: links and actions move into the drawer, logo and burger stay */
  .nav__links, .nav__actions { display: none; }
  .nav__burger { display: flex; }
  .nav__right { gap: 0; }

  /* hero: fill the screen so the next section can't peek in. svh, not vh, so it
     doesn't jump as mobile browser chrome hides and shows. The content is
     bottom-anchored, so the shorter bottom padding pushes the whole stack down
     and opens the top of the frame for the photo circle. */
  .hero { min-height: 100svh; padding-top: 140px; padding-bottom: clamp(40px, 5.5vh, 66px); }

  /* The desktop photograph, re-cut square and masked into a circle that bleeds
     off the right edge - the hero already carries two circle ornaments, so this
     joins the vocabulary instead of importing a banner. Sized and positioned in
     viewport units so it scales with the screen rather than needing its own
     breakpoints. */
  .hero__orb {
    display: block; position: absolute; z-index: 1;
    width: min(76vw, 340px); aspect-ratio: 1;
    top: clamp(82px, 11.5vh, 126px); right: -15vw;
    border-radius: 50%; overflow: hidden;
  }
  .hero__orb img { display: block; width: 100%; height: 100%; object-fit: cover; }
  /* the same navy grade the desktop half carries, weighted to the lower left so
     the headline stays legible if a short screen brings the two together */
  .hero__orb::after {
    content: ""; position: absolute; inset: 0;
    background:
      /* bottom fade: on a short screen the headline reaches the lower arc, and
         the photo has bright laptop screens in it. Measured - without this,
         white type landed on patches as weak as 2.9:1. Keeps the centre clean. */
      linear-gradient(to bottom, rgba(8, 18, 34, 0) 46%, rgba(8, 18, 34, .80) 100%),
      linear-gradient(212deg, rgba(8, 18, 34, .08) 0%, rgba(8, 18, 34, .30) 52%, rgba(8, 18, 34, .62) 100%),
      linear-gradient(rgba(20, 46, 78, .34), rgba(20, 46, 78, .34));
  }

  /* The founding line drops below the CTA and gets quiet: it is supporting
     detail, and at full size directly under the H1 it was competing with it.
     About repeats the founding facts in full a screen later. */
  .hero__body { gap: 26px; }
  .hero__cta { order: 2; }
  .hero__proof { order: 3; align-items: flex-start; }
  .hero__proof p { font-size: 14px; line-height: 1.55; color: var(--on-dark-70); }
  .hero__left { width: 100%; }
  .hero__right { display: none; }
  .hero__body { max-width: none; }
  /* hand-set line breaks are a desktop decision; the H1 is smaller in a much
     narrower column here and needs to wrap on its own */
  .lb { display: none; }
  .hero__caption { display: none; }

  .about__grid, .why__grid, .cta .container { flex-direction: column; align-items: flex-start; }
  .about__gutter { width: auto; align-self: auto; padding-top: 0; gap: 30px; }
  .about__owner { flex-direction: row; align-items: flex-end; gap: 18px; }
  .about__owner picture { flex: none; width: 120px; }
  .about__cols { grid-template-columns: minmax(0, 1fr); row-gap: 1.15em; }
  .about__body, .why__lead, .why__points, .cta__body { width: 100%; max-width: none; }

  .svc-row { flex-wrap: wrap; }
  .svc { flex: 1 1 320px; min-height: 460px; }
  .svc__body { max-width: none; }

  /* the other sections set this gap on a flex parent; this heading has none */
  .services__eyebrow { display: flex; margin-bottom: 14px; }

  .pillars__grid { flex-direction: column; }
  .pillars__aside { position: static; width: 100%; }
  /* The heading stays, but static: the live pillar name and the counter only
     mean anything while the column is pinned, and stacked at the top of the
     section they scroll away before they can track anything. Each block already
     carries its own number and title, so the label here becomes "HR is:". */
  .pillars__count, .pillars__heading em { display: none; }
  .pillars__lead::after { content: ":"; }
  .pillar { max-width: none; }

  /* minmax(0,…) not 1fr: "4 → 100s" and "Nationwide" are wider than the track
     and were forcing the grid past the viewport - this was the horizontal scroll */
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 40px; }

  /* team: the mosaic un-anchors from the right half and becomes a full-width
     band under the copy. Without this it stays absolutely positioned over 52%
     and crushes the text column. */
  .team { display: block; min-height: 0; padding-block: 90px 0; }
  .team__roster { position: static; width: 100%; margin-top: 60px; grid-template-rows: none; }
  .team__member { aspect-ratio: 4 / 5; }
  .team__body { width: 100%; }

  /* interior page header */
  .phead { padding: calc(var(--nav-h) + 70px) 0 54px; }
  .phead__grid { gap: 28px; }
  .phead__lede { max-width: none; }

  /* team track (grid fallback at this width) */
  .pin__stage { padding-block: 80px 92px; }

  .cta .container { gap: 40px; }
  .cta__card { width: 100%; }

  /* both side-by-side layouts stack: title over form, form over details panel */
  .trust__grid { grid-template-columns: minmax(0, 1fr); gap: 34px; }
  .trust__stats { padding-left: 0; border-left: 0; }

  .contact { padding-block: 80px 92px; }
  .contact__grid { grid-template-columns: minmax(0, 1fr); gap: 48px; }
  .contact__aside { position: static; }
  .contact__form h2 { max-width: none; }

  .foot__top { flex-wrap: wrap; }
  .foot__brand, .foot__links, .foot__contact { width: 100%; border-right: 0; padding-inline: 0; padding-block: 50px 30px; }
}

@media (max-width: 700px) {
  :root { --pad: 22px; }
  .h1 { font-size: 40px; letter-spacing: -1.4px; }
  .h2 { font-size: 32px; letter-spacing: -1.1px; }
  .h2-sm { font-size: 27px; letter-spacing: -.8px; }
  .h3 { font-size: 25px; letter-spacing: -.7px; }
  .body { font-size: 17px; }

  /* every section was padded for a 1570px canvas */
  .about { padding-top: 80px; }
  .services { padding-top: 90px; gap: 34px; }
  .pillars { padding-block: 70px 30px; }
  .pillars__list { gap: 62px; }
  .stats-sec { padding-block: 30px 80px; }
  .why { padding-block: 80px; }
  .cta { padding-block: 80px; }

  .about__cols { margin-top: 30px; padding-top: 26px; }

  /* gutters, not full bleed: edge-to-edge cards read as an ultrawide band and
     lose the alignment with the section heading above them */
  .svc-row { padding-inline: var(--pad); gap: 16px; }
  .svc { min-height: 400px; }
  .svc__body { padding: 30px 24px; }

  .pillar__head h3 { font-size: 26px; letter-spacing: -.8px; }

  /* one column: two 54px figures cannot share a 390px row legibly */
  .stats { grid-template-columns: minmax(0, 1fr); row-gap: 30px; }
  .stat__n { font-size: 38px; letter-spacing: -1.2px; min-height: 0; }

  /* 34px over a 340px measure ran the shortest quote to eleven lines */
  blockquote { font-size: 21px; letter-spacing: -.5px; line-height: 1.3; }

  .team { padding-block: 70px 0; }
  .team__roster { margin-top: 44px; grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .phead { padding: calc(var(--nav-h) + 54px) 0 44px; }
  .pin__stage { padding-block: 60px 72px; }
  /* two per row rather than one huge column: eight full-width cards would be a
     very long page for very little information */
  .pin__track { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 34px 14px; }
  .member__name { font-size: 19px; letter-spacing: -.5px; }
  .member__role { margin-top: 16px; }
  .member__li { padding-top: 14px; }

  .why__pt { padding-block: 26px; gap: 18px; }
  .cta__card { padding: 26px; }

  .contact { padding-block: 60px 72px; }
  /* paired fields go one per row - two 150px-wide inputs help nobody */
  .form__row { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .form__foot { gap: 18px; }
  .form__foot .btn { width: 100%; justify-content: center; }

  /* the stepper keeps its numbers and drops the words; four uppercase labels
     wrap to three lines on a phone and push the form off the screen */
  /* no floor on a phone: the panels stack tall anyway and screen height is the
     scarce thing, so reserved empty space costs more than a settled button */
  .js .qz__panel.is-active { min-height: 0; }
  .qz__l { display: none; }
  .qz__rail { gap: 12px; }
  .qz__opts { gap: 8px; }
  .opt span { padding: 10px 15px; font-size: 14px; }
  .qz__nav { gap: 12px; }
  .qz__nav .btn { flex: 1 1 auto; }
  .qz__alt { margin-left: 0; flex-basis: 100%; }

  /* Footer, consolidated: three stacked blocks separated by hairlines instead of
     three blocks each carrying 80px of its own padding. Same content, ~40% less
     scroll, and the divider does the separating that whitespace was doing. */
  .foot { padding-bottom: 22px; }
  .foot__top { gap: 0; }
  .foot__brand, .foot__links, .foot__contact {
    padding-block: 28px; border-bottom: 1px solid var(--hairline);
  }
  .foot__brand { padding-top: 44px; gap: 16px; }
  .foot__brand img { width: 165px; }
  .foot__brand p { font-size: 15px; line-height: 1.5; }
  /* two real columns rather than a flex row with an 80px gap that wrapped */
  .foot__links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 18px; }
  .foot__col { gap: 15px; }
  .foot__contact { border-bottom: 0; gap: 20px; }
  .foot__addr { font-size: 19px; letter-spacing: -.5px; }
  .foot__contact-links { gap: 11px; }
  .foot__contact-links a { font-size: 17px; }
  .foot__bar { padding-top: 20px; flex-direction: column; gap: 7px; font-size: 13px; }
}
