/* Styles of / only (moved out of its <style> block on 2026-11-10).
   Loaded after the shared sheets, at the same place the block was, so the
   cascade is unchanged. Rules shared by several pages go in /css. */

/* HOME HERO. Two complete states of the same scene, from the Figma design,
   and nothing in between: one scroll gesture goes from one to the other.
   p = 0  the video fills the screen, the name and the headline sit over it
   p = 1  the video is a block on the grid, the headline moves up, the menu
          is the plain bar, the blurbs and "to clarity" are uncovered.
   js/home-hero.js toggles html.hero-open on the first scroll down from the
   top (and removes it on the first scroll up back at the top); --p is a
   registered number that transitions between 0 and 1, and everything here
   is calc() on it. Layers copy the Figma stack: the video covers the
   blurbs and "to clarity", the name and headline sit over it.

   One scene for the three breakpoints, on the shared grid (css/grid.css):
   columns come from --g-cols (12 desktop, 8 tablet, 4 mobile), the gutter is
   16, the container is 1200 at most, and the vertical lines are the 12 rows
   that stretch to the screen (--v-pitch: row N starts at (N - 1) * pitch).
   Every edge below is one of those lines, so nothing is a pixel position.
   Per breakpoint only these numbers change:
     --hspan  columns the video block spans at p = 1 (all but the last two,
              which hold the blurbs; on mobile all four)
     --vtop   rows above the video (it starts on row --vtop + 1)
     --vbot   rows below the video (it ends on row 12 - --vbot)
     --lines  lines of the headline, --fsr its size as a share of the grid
              width. */
@property --p { syntax: '<number>'; inherits: true; initial-value: 0; }
/* --pn is the menu name's fade. Wider than a phone it moves with --p;
   on a phone it runs on its own clock (below) so the name shows in the
   menu first and the scene follows. */
@property --pn { syntax: '<number>'; inherits: true; initial-value: 0; }
html { --p: 0; --pn: 0; transition: --p 1000ms cubic-bezier(0.65, 0, 0.35, 1), --pn 1000ms cubic-bezier(0.65, 0, 0.35, 1); }
html.hero-open { --p: 1; --pn: 1; }
/* Phone, 1000ms in all (js/home-hero.js DURATION). Opening: the name fades in
   in the first 500ms, the scene starts at 250ms and ends at 1000ms. Closing is
   the reverse: the scene goes first, the name is the last to leave the menu. */
@media (max-width: 39.99em) and (prefers-reduced-motion: no-preference) {
  html { transition: --p 750ms cubic-bezier(0.65, 0, 0.35, 1) 0ms, --pn 500ms cubic-bezier(0.65, 0, 0.35, 1) 500ms; }
  html.hero-open { transition: --pn 500ms cubic-bezier(0.65, 0, 0.35, 1) 0ms, --p 750ms cubic-bezier(0.65, 0, 0.35, 1) 250ms; }
}
html.hero-instant { transition: none; }
@media (prefers-reduced-motion: reduce) { html { transition: none; } }
html { scroll-snap-type: none; }
/* cases.css hides horizontal overflow on html and body, which kills the
   sticky head of the featured cases; clip hides it without that. */
html, body { overflow-x: clip; }
/* G overlay (js/grid-overlay.js) on the home: the zones of the cases from
   the first screen (2026-11-10; before, only once the featured cases
   reached the middle of the screen). The hero is the only part of the
   home off that grid. The body declares the zone tokens the overlay reads
   (the same values as body.cp-case in css/case-page.css). */
@media (min-width: 75.0625em) {
  body {
    --cp-zone-cols: 4;
    --cp-cols: 12;
    --cp-rail-min: 320px;
    --cp-right: min(max(var(--g-content), 50%), 100% - 320px);
    --cp-zone-pad: 24px;
    --cp-rail-pad: clamp(24px, 12%, var(--g-margin));
  }
}
body { --side-delay: 300ms; }

main.hero.home-hero {
  display: block;
  padding: 0;
  overflow: visible;
  background: var(--bg);
  scroll-snap-align: none;
  height: 100dvh;
}
/* hero.css darkens the whole hero with a scrim on phones; the scene paints
   its own layers. */
main.hero.home-hero::after { content: none; }

.home-hero__stage {
  position: relative;
  height: 100%;
  overflow: hidden;
  isolation: isolate;
  background: var(--bg);
  container-type: inline-size;

  --hw: min(var(--g-content), 100cqw - 2 * var(--g-margin));   /* grid width */
  --hin: calc((100cqw - var(--hw)) / 2);                        /* side inset */
  --hcol: calc((var(--hw) - (var(--g-cols) - 1) * var(--g-gutter)) / var(--g-cols));
  --hspan: calc(var(--g-cols) - 2);
  --vtop: 3;
  --vbot: 2;
  --lines: 2;
  --lcap: 2;         /* lines the height cap of the size allows for (fixed, so the size never depends on how the text wraps) */
  /* Open state: Geist 500, 47px on a 1200 grid. */
  --fsr: 0.0393;
  /* The size also respects the height: the headline never needs more than
     rows 2 to --vtop (from row 2 down to one gutter above the video), so on
     a short screen it shrinks instead of running over the menu or the video. */
  --fs2: min(calc(var(--hw) * var(--fsr)), calc(((var(--vtop) - 1) * var(--v-pitch) - var(--v-gutter)) / (var(--lcap) * 1.3)));
  /* First frame: the same words, bigger, over the video (2026-11-10). */
  --fsr0: 0.07;
  --fs0: calc(var(--hw) * var(--fsr0));
  /* Headline top in the open state: the lines end one gutter above the
     video (never above row 2). */
  --T2: max(var(--v-pitch), var(--topnav-h, 0px), calc(var(--vtop) * var(--v-pitch) - var(--v-gutter) - var(--lines) * 1.3 * var(--fs2)));
}

/* Phone: four columns. The video block runs from the left edge to the end
   of the last column, from row 5 to row 9; the headline wraps (js/home-hero.js
   measures its lines), and the blurbs take rows 11 and 12. */
@media (max-width: 37.49em) {
  .home-hero__stage {
    --hspan: var(--g-cols);
    --vtop: 4;
    --vbot: 3;
    --lines: 6;
    --lcap: 6;
    --fsr: 0.067;
    --fsr0: 0.1;
  }
}

.home-hero__blurbs p { text-wrap: pretty; }
.home-hero__title { margin: 0; font-family: var(--font-main); font-weight: 500; }
.home-hero__title b { font-weight: 600; }
.home-hero__blurbs b { font-weight: 600; letter-spacing: 0.02em; }
.home-hero__blurbs p { margin: 0; }
.home-hero .hero__video {
  position: static;
  display: block;
  width: 100%;
  height: 100%;
  max-height: none;
  translate: none;
  object-fit: cover;
}

.home-hero__media {
  position: absolute;
  z-index: 1;
  left: 0;                                                   /* bleeds off the left edge */
  top: calc(var(--p) * var(--vtop) * var(--v-pitch));        /* start of row --vtop + 1 */
  bottom: calc(var(--p) * var(--vbot) * var(--v-pitch));     /* end of row 12 - --vbot */
  /* ends on the right edge of column --hspan */
  right: calc(var(--p) * (100cqw - var(--hin) - var(--hspan) * var(--hcol) - (var(--hspan) - 1) * var(--g-gutter)));
}
/* Scrim: the site’s black at 40% (2026-11-10, before 30%) over the full-screen video, so the white
   name and headline read on it. It fades out as the scene opens, when the
   text leaves the video (2026-11-09). */
.home-hero__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(var(--black-rgb, 31, 31, 41), 0.4);
  opacity: calc(1 - var(--p));
  pointer-events: none;
}

/* The menu (2026-11-10). With the scene closed there is nothing but the
   video and the headline: the menu fades in with the scene (--pn, so on a
   phone it comes first) and out when it closes, and while it is gone it
   takes no pointer and no focus. Open, it is the menu of the cases: ink,
   no blend, the bar at rest and the pill once the page scrolls. */
html.is-home .hero__side-menu { opacity: var(--pn); }
html.is-home:not(.hero-open) .hero__side-menu {
  visibility: hidden;
  pointer-events: none;
  transition: visibility 0s linear 1000ms;
}
/* The bar at rest on the two zones, like the cases above 1200px
   (css/case-page.css, body.cp-case, which the home does not load): the
   hero is the only part of the home off that grid. The name on the
   editorial zone at the case inset (12% of the zone, 24 to 72px), the
   links on content columns 7, 9 and 11, CONTACT closing on 12. Floating,
   the pill keeps the centered grid of css/topnav.css, as on the cases. */
@media (min-width: 75.0625em) {
  html.has-topnav body {
    --nv-r: min(max(var(--g-content), 50%), 100% - 320px);
    --nv-zp: 24px;
    --nv-p: clamp(var(--nv-zp), (100% - var(--nv-r)) * 0.12, var(--g-margin));
    --nv-zc: calc((100% - var(--nv-r) - 2 * var(--nv-p) - 3 * var(--g-gutter)) / 4);
    --nv-cc: calc((var(--nv-r) - 2 * var(--nv-zp) - 11 * var(--g-gutter)) / 12);
  }
  html.has-topnav:not(.topnav-float) body .hero__side-menu {
    padding: 0;
    grid-template-columns:
      calc(var(--nv-p) - var(--g-gutter))
      repeat(4, var(--nv-zc))
      calc(var(--nv-p) + var(--nv-zp) - 2 * var(--g-gutter))
      repeat(12, var(--nv-cc))
      calc(var(--nv-zp) - var(--g-gutter));
  }
  html.has-topnav:not(.topnav-float) body .hero__side-menu .hero__name { grid-column: 2 / span 4; }
  html.has-topnav:not(.topnav-float) body .topnav__links { grid-column: 13 / span 6; }
}

/* Two copies of the headline, crossfaded (2026-11-10; before, one
   mono headline that travelled and shrank). First frame: the big one,
   white over the video, its last line on the start of row 12. It fades out
   in the first half of the scene and the h1 fades in at its place above the
   video in the second half. Geist 500 in both. */
.home-hero__lead {
  position: absolute;
  z-index: 3;
  left: var(--hin);
  width: var(--hw);
  bottom: calc(100% - 11 * var(--v-pitch));
  margin: 0;
  font-family: var(--font-main);
  font-weight: 500;
  font-size: var(--fs0);
  line-height: 1.1;
  text-wrap: balance;
  color: #fff;
  opacity: calc(1 - 2 * var(--p));
  pointer-events: none;
}
.home-hero__top {
  position: absolute;
  z-index: 3;
  left: var(--hin);
  width: var(--hw);
  line-height: 1.3;
  font-size: var(--fs2);
  top: var(--T2);
  color: var(--black);
  opacity: calc(2 * var(--p) - 1);
}
.home-hero__top .l { display: block; white-space: nowrap; }
/* Display type in every mode: on a phone the headline is under 22px, so
   js/a11y.js would scale it by 4/3 (3/2 in the accessible mode) and the
   scene, which places it from its own size, would land it on the video.
   The selector outranks css/a11y.css (0,4,1). */
html.is-home main.home-hero .home-hero__title .home-hero__top { font-size: var(--fs2) !important; }
html.is-home main.home-hero .home-hero__title .home-hero__top * { font-size: inherit !important; font-family: var(--font-main); }

/* The last two columns. The last baseline of the text sits on the bottom
   edge of the video: 0.29em is what Geist leaves under the baseline at a
   line height of 1.3. */
.home-hero__blurbs {
  position: absolute;
  z-index: 0;
  left: calc(var(--hin) + var(--hspan) * (var(--hcol) + var(--g-gutter)));
  width: calc((var(--g-cols) - var(--hspan)) * var(--hcol) + (var(--g-cols) - var(--hspan) - 1) * var(--g-gutter));
  bottom: calc(var(--vbot) * var(--v-pitch) - 0.29em);
  display: flex;
  flex-direction: column;
  gap: var(--v-gutter);
  font-family: var(--font-main);
  font-size: 14px;
  line-height: 1.3;
  letter-spacing: 0.02em;
  color: var(--black, #1f1f29);
}

@media (max-width: 37.49em) {
  .home-hero__top .l { display: inline; white-space: normal; }
  /* All four columns, from the start of row 11, or higher when the text
     (16px, 18px in the accessible mode) needs more than two rows: it then
     ends one gutter above the bottom edge. --bl is its measured height
     (js/home-hero.js). */
  .home-hero__blurbs {
    font-size: 12px;   /* 14px wider; js/a11y.js scales this to 16 on a phone */
    left: var(--hin);
    width: var(--hw);
    bottom: auto;
    top: calc(min(100dvh - 2 * var(--v-pitch) + var(--v-gutter), 100dvh - var(--bl, 0px) - var(--v-gutter)));
  }
  /* The video block ends a gutter or two above the text when the text is taller than rows 11 and 12. */
  .home-hero__media {
    bottom: calc(var(--p) * max(var(--vbot) * var(--v-pitch), var(--bl, 0px) + 2 * var(--v-gutter)));
  }
}

  /* The black column of the disciplines has no visible text (2026-11-04).
   The line is kept for screen readers only, so the section keeps its
   heading. */
.disciplines__sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* Phone: no black column at all (the heading stays for screen readers). */
@media (max-width: 37.49em) {
  .disciplines__intro { position: absolute; width: 1px; height: 1px; min-height: 0; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); }
}
/* Tablet and desktop: the column starts as one more top rule, on the same
   line and as thick as the rules of the modules, and grows down to its full
   height as the section scrolls in. --grow (0 to 1) is written by the
   script at the end of the page. Reduced motion and the accessible mode
   show it full. */
@media (min-width: 37.5em) {
  html.js-grow .disciplines__intro { clip-path: inset(0 0 calc((100% - var(--rule-h)) * (1 - var(--grow, 0))) 0); }
}
