.hero {
  position: relative;
  isolation: isolate;
  background: var(--c-hero-edge);
  color: var(--c-focus-light);
  overflow: hidden;
  /* The default focus ring is near-black, which measures 1.1:1 to 2.0:1 against
     the scrim over a photograph and so is effectively invisible on the two
     buttons here. WCAG 1.4.11 wants 3:1. White measures well above it on any
     image the scrim can produce. */
  --c-focus: var(--c-focus-light);
  --hero-media-max: 100rem; /* the photo stops growing here; see below */
}

/* The photograph spans the whole hero, with the text over it. */
.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}

/* The transform wraps the <img> in a <picture>, an inline box with no height,
   so `height: 100%` below would resolve to auto and the photograph would
   collapse. This gives the wrapper a definite box. `> *`, not `picture`, so it
   holds for a bare <img> too; with inset and a width both set the width wins
   and the box anchors left, which the shift at 64em relies on. */
.hero__media > * {
  position: absolute;
  inset: 0;
  display: block;
}

/* Parallax, no script: the photograph lags to ~70% of scroll speed, pushed down
   by up to 30% of its height over the first screen. Framing at the top is the
   tuned one (transform 0); the gap at its top edge is always off screen; the
   scrim is on .hero__media, which stays put. Still hero with reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .hero__media > * { animation: hero-parallax linear both; animation-timeline: scroll(root); animation-range: 0 100vh; }
  }
}
@keyframes hero-parallax { to { transform: translateY(30%); } }

/* On a wide screen the photo stops at 1600px, centred, rather than being drawn
   2400 to 3200px wide and cropped hard; the hero's own blue fills either side,
   and the outer 10% fades into it. The mask's colours are opacity, not palette.
   The text column stays inside, on the scrim's full-strength half; the photo
   widens less, so the right-hand figure ends before the fade. */
@media (min-width: 100em) {
  .hero__media {
    --hero-image-shift: 112%;
    max-width: var(--hero-media-max);
    margin-inline: auto;
    mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
  }
}

/* A real <img>, not a CSS background: stylesheets are not rewritten by the
   pathPrefix transform, so a url() here would break on a project-page build. */
.hero__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* A tall narrow frame crops the sides. Centred, the crop cuts the right-hand
     figure in half; nudged right it holds the group. */
  object-position: 58% center;
}

/* The scrim (text on the bare photo failed 1.4.3); --c-scrim is the measured
   floor. Uniform on narrow screens, where the text spans the whole width. */
.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--c-scrim);
}

@media (min-width: 64em) {
  /* Widened past the hero and pinned left, to move the people out from behind
     the text: the hero is wider than the photo here, so object-position alone
     has no horizontal slack. 125% is the ceiling; more cuts off the right-hand
     figure. */
  .hero__image {
    width: var(--hero-image-shift, 125%);
    max-width: none;
    object-position: center;
  }

  /* Full strength past the end of the text column (about 48% across), then
     clearing over the people. The fade must start after the text, not on it. */
  .hero__media::after {
    background: linear-gradient(
      90deg,
      var(--c-scrim) 0%,
      var(--c-scrim) 50%,
      rgb(6 0 79 / 0.18) 72%,
      rgb(6 0 79 / 0.08) 100%
    );
  }
}

/* The same .container as every section, so the hero shares the page's edge. */
.hero__inner {
  padding-block: var(--s-9);
}

/* The measure on the wrapper, at the 1rem body size: on the heading, 62ch at
   the hero's font size would be over 1700px. */
.hero__content {
  max-width: 62ch;
}

@media (min-width: 64em) {
  /* The text must end before the scrim fades at 50%: 44vw holds that at 1024px,
     where the column runs from the gutter to 474px, and 34rem above about
     1240px. It also leaves the picture worth having. */
  .hero__content {
    max-width: min(34rem, 44vw);
  }
}

.hero__title {
  /* One step down from --t-4xl. Design SIG: "Title super long, is there a way
     to make it smaller / not all caps?" The caps stay by explicit decision, so
     the size carries the whole fix: at --t-3xl the sentence sets in three lines
     at desktop width instead of four. */
  font-size: var(--t-3xl);
  color: var(--c-focus-light);
  /* Caps so the picked-out acronym letters read as a deliberate highlight
     rather than erratic capitalisation. text-transform, not typed-in capitals:
     the text stays sentence case, so what is copied, indexed and read aloud is
     unaffected. Capitals in the markup are what some screen readers spell out
     letter by letter. */
  text-transform: uppercase;
  /* Capitals need a little more tracking than lowercase to stay legible. */
  letter-spacing: 0.01em;
}

/* The letters that make up LIL-ECHOES, picked out of the sentence. Decorative
   emphasis only: the accessible name is the plain sentence, so nothing is
   carried by colour alone. */
.acronym {
  color: var(--c-brand-orange-soft);
  font-weight: inherit;
}

.hero__lede {
  font-size: var(--t-lg);
  color: var(--c-focus-light);
  margin-block: var(--s-5);
}

/* Project facts, as a description list: name and value pairs, which is what a
   screen reader should hear. The ink, not the brand blue: these are metadata
   and want to stay small, and on the brand blue nothing small is legal, so
   using it meant inflating the type into a title. Here every size passes,
   white at 14.15:1 and the labels at 8.24:1. */
.facts {
  padding-block: var(--s-6);
  background: var(--c-ink);
  color: var(--c-focus-light);
}

/* Re-binds on the child: a custom property declared on an element also applies
   to that element's own declarations, so re-binding --c-ink beside
   `background: var(--c-ink)` paints the strip white and writes white on it. */
.facts > * {
  --c-ink: var(--c-focus-light);
  --c-ink-muted: var(--c-brand-orange-soft);
  --c-link: var(--c-focus-light);
  --c-focus: var(--c-focus-light);
}

.facts__list {
  display: grid;
  gap: var(--s-5);
  margin: 0;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
}

/* Bold, like .eyebrow, which is the same species of label at the same size.
   These were the exception at 400, and the soft orange is the lightest colour
   on the site, so thin strokes showed on it first. 8.24:1 on the ink. */
.facts__list dt {
  font-size: var(--t-xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--c-ink-muted);
  margin-block-end: var(--s-1);
}

.facts__list dd {
  margin: 0;
  font-size: var(--t-lg);
  font-weight: var(--fw-medium);
  color: var(--c-ink);
}
