/* ==========================================================================
   Tokens
   ========================================================================== */

@font-face {
  font-family: "Neue Haas Unica Pro";
  font-weight: 300;
  font-style: normal;
  font-display: swap;
  src: url("assets/fonts/NeueHaasUnicaPro-Light.ttf") format("truetype");
}

@font-face {
  font-family: "Neue Haas Unica Pro";
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url("assets/fonts/NeueHaasUnicaPro-Regular.ttf") format("truetype");
}

@font-face {
  font-family: "Neue Haas Unica Pro";
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  src: url("assets/fonts/NeueHaasUnicaPro-Medium.ttf") format("truetype");
}

@font-face {
  font-family: "GT Super Display Trial";
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url("assets/fonts/GT-Super-Display-Trial-Regular.otf") format("opentype");
}

@font-face {
  font-family: "TB Font 1.5";
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url("assets/fonts/TBFont1.5-Regular.otf") format("opentype");
}

:root {
  /* Colors */
  --color-bg: #e9e6db;
  --color-ink: #160e0e;
  --color-porcelain: #ffffff;
  --color-umber: #662e12;
  --color-rule: #160e0e;

  /* Motion */
  --ease-reveal: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-entrance: cubic-bezier(0.22, 1, 0.36, 1);
  --sticky-offset: 96px;

  /* Typography */
  --font-sans: "Neue Haas Unica Pro", -apple-system, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-serif: "GT Super Display Trial", Georgia, "Times New Roman", serif;
  --font-wordmark: "TB Font 1.5", var(--font-sans);

  /* Spacing */
  --page-pad: 40px;
  /* Space above the nav. Doubles as the nav's sticky offset so the inset
     is identical whether the nav is at rest or pinned. */
  --nav-pad: 24px;
  /* Height of the nav's single line of type — used to size the first
     screen so nav + hero total exactly one viewport. */
  --nav-h: 24px;

  /* Hero image dimensions, shared by the element itself and by the sticky
     offset that pins it bottom-right. */
  --hero-img-w: clamp(420px, 42vw, 900px);
  --hero-img-h: calc(var(--hero-img-w) * 651 / 636);

  /* Viewport minus the nav block and the bottom inset. */
  --first-screen: calc(100svh - var(--nav-pad) - var(--nav-h) - var(--page-pad));

  /* How far the hero image stays pinned before releasing. Capped at 700px
     so it holds through the copy without leaving a stretch of empty page,
     and scales down on short viewports where 700px would be excessive. */
  --hero-pin: 100svh;
  --row-gap: 60px;
  --section-gap: 200px;
}

@media (max-width: 1024px) {
  :root {
    --page-pad: 28px;
    --row-gap: 40px;
    --section-gap: 200px;
  }
}

@media (max-width: 640px) {
  :root {
    --page-pad: 20px;
    --row-gap: 24px;
    --section-gap: 128px;
  }
}

/* ==========================================================================
   Reset
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

/* Umber behind the page keeps overscroll at either end on-brand. */
body {
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

img {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

p {
  margin: 0;
}

/* ==========================================================================
   Cap-height trim

   Figma measures spacing from the cap height / baseline (every text layer
   in the file carries `text-box-trim: trim-both` + `text-box-edge:
   cap alphabetic`). CSS line boxes instead include the font's leading, so
   an identical 16px gap in Figma renders visibly larger in the browser —
   which is why gaps, pill padding and divider spacing all read as too
   loose against the design.

   `text-box` reproduces Figma's measurement exactly. It only trims the
   first line's top and last line's bottom, so multi-line copy keeps its
   internal leading. Unsupported browsers simply keep the looser spacing.
   ========================================================================== */

@supports (text-box: trim-both cap alphabetic) {
  .eyebrow,
  .row__heading,
  .hero__statement,
  .bio__statement,
  .fact__value,
  .touch__statement,
  .article__title,
  .article__meta,
  .press-item__title,
  .press-item__meta,
  .essay__excerpt,
  .footer__links a,
  .mobile-menu__links a,
  .faq-question,
  .tag,
  .lang-option,
  .nav__lang > span[aria-hidden="true"],
  .footer__links--inline > span[aria-hidden="true"],
  .nav__items a,
  .nav__wordmark,
  .link-cta span {
    text-box: trim-both cap alphabetic;
  }
}

/* ==========================================================================
   Shared type styles
   ========================================================================== */

.eyebrow {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 14px;
  letter-spacing: -0.28px;
  line-height: normal;
}

/* H1 — Neue Haas Unica Pro Medium. (Was GT Super Display; the serif is no
   longer used anywhere in the design.) */
.row__heading,
.hero__statement {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 40px;
  letter-spacing: -1.2px;
  line-height: 1.1;
  margin: 0;
}

.hero-line {
  display: block;
  overflow: hidden;
  padding-block: 0.1em 0.14em;
  margin-block: -0.1em -0.14em;
}

.hero-line__inner {
  display: block;
  white-space: nowrap;
  will-change: transform;
}

.hero-line-measure {
  display: inline;
  white-space: nowrap;
}

/* H2 — Neue Haas Unica Pro Regular. */
.fact__value,
.article__title {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 36px;
  letter-spacing: -1.08px;
  line-height: 1.1;
  margin: 0;
}

.touch__statement,
.footer__links a,
.lang-option {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 28px;
  letter-spacing: -0.84px;
  line-height: 1.1;
}

.link-cta span {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 18px;
  letter-spacing: -0.36px;
}

@media (max-width: 1024px) {
  .row__heading,
  .hero__statement {
    font-size: 32px;
    letter-spacing: -0.9px;
  }

  .fact__value,
  .article__title {
    font-size: 28px;
    letter-spacing: -0.84px;
  }
}

@media (max-width: 640px) {
  .row__heading,
  .hero__statement {
    font-size: 26px;
    letter-spacing: -0.7px;
  }

  .fact__value,
  .article__title {
    font-size: 22px;
    letter-spacing: -0.6px;
  }

  .touch__statement {
    font-size: 22px;
    letter-spacing: -0.6px;
  }
}

/* ==========================================================================
   Page shell
   ========================================================================== */

/* Article wrapper for semantics only; its sections keep the page rhythm. */
.post-article {
  display: contents;
}

.page-main {
  /* Wrap exceptionally long CMS copy, never the navigation chrome. */
  overflow-wrap: anywhere;
  display: flex;
  flex-direction: column;
  gap: inherit;
  min-width: 0;
}

.skip-link {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 2147483647;
  padding: 12px 20px;
  background: var(--color-ink);
  color: var(--color-bg);
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }
:where(a, button, input, textarea, select):focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 5px;
}

.page {
  display: flex;
  flex-direction: column;
  gap: var(--section-gap);
  padding: var(--nav-pad) var(--page-pad) var(--page-pad);
  width: 100%;
  /* Carries the page colour itself, so the umber body shows through while
     the page is still fading in. */
  background: var(--color-bg);
  min-height: 100svh;
}

/* Full-screen internal-page transition. */
.transition-panel {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: var(--color-umber);
  transform: translateY(100%);
  pointer-events: none;
  will-change: transform;
}

.transition-panel.cover {
  animation: page-cover 650ms cubic-bezier(0.76, 0, 0.24, 1) forwards;
}

.transition-panel.reveal {
  transform: translateY(0%);
  animation: page-reveal 700ms cubic-bezier(0.76, 0, 0.24, 1) forwards;
}

/* Set synchronously in <head> so the destination is covered on its first
   paint, before DOMContentLoaded or the main script can run. */
html.page-transition-arrival::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 10001;
  background: var(--color-umber);
  pointer-events: none;
  transform: translateY(0%);
  animation: page-reveal 700ms cubic-bezier(0.76, 0, 0.24, 1) forwards;
  will-change: transform;
}

@keyframes page-cover {
  from { transform: translateY(100%); }
  to { transform: translateY(0%); }
}

@keyframes page-reveal {
  from { transform: translateY(0%); }
  to { transform: translateY(-100%); }
}

/* ==========================================================================
   Nav
   ========================================================================== */

/* The nav scrolls away with the page rather than pinning — it sits above
   the content in stacking order only so the mobile drawer's colour swap
   still reads correctly while it is on screen. */
.nav {
  position: relative;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}

.nav__items {
  display: flex;
  gap: 24px;
  width: clamp(160px, 14vw, 280px);
  font-weight: 500;
  font-size: 14px;
  letter-spacing: -0.28px;
}

/* A translated navigation label is one item, including its spaces. */
.nav__items a {
  white-space: nowrap;
  flex-shrink: 0;
}

.nav__wordmark {
  font-family: var(--font-wordmark);
  font-size: 24px;
  letter-spacing: -0.48px;
  text-transform: uppercase;
  order: 0;
}

.nav__lang {
  display: flex;
  align-items: baseline;
  line-height: 1.1;
  gap: 8px;
  width: clamp(160px, 14vw, 280px);
  justify-content: flex-end;
  font-weight: 500;
  font-size: 14px;
  letter-spacing: -0.28px;
}

/* Nav links and language options share one behaviour: one solid colour,
   underline on hover, and a persistent underline on the current page /
   selected language. */
.lang-option,
.nav__items a,
.mobile-menu__links a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 0.07em;
  text-decoration-color: transparent;
  text-underline-offset: 4px;
  transition: text-decoration-color 0.25s var(--ease-reveal);
}

.lang-option {
  font-size: inherit;
  letter-spacing: inherit;
  font-weight: inherit;
}

.lang-option:hover,
.lang-option:focus-visible,
.lang-option.is-active,
.nav__items a:hover,
.nav__items a:focus-visible,
.nav__items a[aria-current="page"],
.mobile-menu__links a:focus-visible,
.mobile-menu__links a[aria-current="page"] {
  text-decoration-color: currentColor;
}

/* Desktop directional underline: enters from the left and leaves through
   the right. Current-page and active-language states remain underlined. */
.nav__items a,
.nav__lang .lang-option,
.footer__links a {
  position: relative;
  text-decoration: none;
}

.nav__items a::after,
.nav__lang .lang-option::after,
.footer__links a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 0.07em;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.nav__items a:hover::after,
.nav__items a:focus-visible::after,
.nav__items a[aria-current="page"]::after,
.nav__lang .lang-option:hover::after,
.nav__lang .lang-option:focus-visible::after,
.nav__lang .lang-option.is-active::after,
.footer__links a:hover::after,
.footer__links a:focus-visible::after,
.footer__links a.is-active::after {
  transform: scaleX(1);
  transform-origin: left center;
}

@media (prefers-reduced-motion: reduce) {
  .lang-option,
  .nav__items a,
  .mobile-menu__links a {
    transition: none;
  }

  .nav__items a::after,
  .nav__lang .lang-option::after,
  .footer__links a::after {
    transition: none;
  }
}

.nav__menu-trigger {
  display: none;
  align-items: center;
  gap: 6px;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: -0.24px;
}

/* Plus mark drawn from two bars so it can rotate into an X, and so it
   inherits the trigger's colour (dark on the page, light over the open
   brown panel) without swapping assets mid-animation. */
.nav__menu-icon {
  position: relative;
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  transition: transform 0.5s var(--ease-reveal);
}

.nav__menu-icon::before,
.nav__menu-icon::after {
  content: "";
  position: absolute;
  background: currentColor;
}

.nav__menu-icon::before {
  left: 0;
  right: 0;
  top: 50%;
  height: 1px;
  transform: translateY(-50%);
}

.nav__menu-icon::after {
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  transform: translateX(-50%);
}

body.menu-open .nav__menu-icon {
  transform: rotate(135deg);
}

.nav__menu-label--open {
  display: none;
}

body.menu-open .nav__menu-label--closed {
  display: none;
}

body.menu-open .nav__menu-label--open {
  display: inline;
}

/* The drawer slides in from the right, so it reaches the trigger (right
   edge) almost immediately and the wordmark (left edge) only at the end
   of the travel. Each element flips colour as the panel actually passes
   beneath it, rather than both switching the instant the button is hit.
   Closing reverses: the wordmark is uncovered first, the trigger last. */
.nav__wordmark {
  transition: color 0.1s linear 0.04s;
}

.nav__menu-trigger {
  transition: color 0.1s linear 0.42s;
}

body.menu-open .nav__wordmark {
  color: var(--color-porcelain);
  transition-delay: 0.42s;
}

body.menu-open .nav__menu-trigger {
  color: var(--color-porcelain);
  transition-delay: 0.04s;
}

@media (prefers-reduced-motion: reduce) {
  .nav__wordmark,
  .nav__menu-trigger {
    transition: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .nav__menu-icon {
    transition: none;
  }
}

/* The inline nav is swapped for the drawer at the tablet breakpoint. The
   three nav groups are laid out as fixed-width side columns either side of
   a centred wordmark, so once the viewport tightens they run into the
   wordmark rather than reflowing — the swap has to happen before that
   collision, not at phone width. */
@media (max-width: 1024px) {
  .nav__items,
  .nav__lang {
    display: none;
  }

  .nav__menu-trigger {
    display: flex;
  }
}

@media (max-width: 640px) {
  .nav__wordmark {
    font-size: 12px;
    letter-spacing: -0.24px;
  }
}

/* ==========================================================================
   Mobile full-bleed menu
   ========================================================================== */

.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  background: var(--color-umber);
  padding: 96px 24px 40px;
  transform: translateX(100%);
  transition:
    transform 0.72s var(--ease-reveal),
    visibility 0s linear 0.72s;
  visibility: hidden;
}

body.menu-open .mobile-menu {
  transform: translateX(0%);
  visibility: visible;
  transition:
    transform 0.88s var(--ease-reveal),
    visibility 0s linear 0s;
}

.mobile-menu__links {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.mobile-menu__links a {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 36px;
  letter-spacing: -1.08px;
  color: var(--color-porcelain);
  opacity: 0;
  transform: translateY(22px);
  transition:
    opacity 1400ms var(--ease-entrance),
    transform 1400ms var(--ease-entrance);
}

.mobile-menu__links a:nth-child(4) { transition-delay: 40ms; }
.mobile-menu__links a:nth-child(3) { transition-delay: 90ms; }
.mobile-menu__links a:nth-child(2) { transition-delay: 140ms; }
.mobile-menu__links a:nth-child(1) { transition-delay: 190ms; }

body.menu-open .mobile-menu__links a {
  opacity: 1;
  transform: translateY(0);
}

body.menu-open .mobile-menu__links a:nth-child(1) { transition-delay: 350ms; }
body.menu-open .mobile-menu__links a:nth-child(2) { transition-delay: 590ms; }
body.menu-open .mobile-menu__links a:nth-child(3) { transition-delay: 830ms; }
body.menu-open .mobile-menu__links a:nth-child(4) { transition-delay: 1070ms; }

.mobile-menu__lang {
  display: flex;
  gap: 8px;
  color: var(--color-porcelain);
  opacity: 0;
  transform: translateY(22px);
  transition:
    opacity 1400ms var(--ease-entrance),
    transform 1400ms var(--ease-entrance);
}

body.menu-open .mobile-menu__lang {
  opacity: 1;
  transform: translateY(0);
  transition-delay: 1310ms;
}

.mobile-menu__lang .lang-option {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 36px;
  letter-spacing: -1.08px;
  color: var(--color-porcelain);
}

/* Matches the nav swap above — the drawer only exists while the inline
   nav is hidden. */
@media (min-width: 1025px) {
  .mobile-menu {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .mobile-menu__links a,
  .mobile-menu__lang {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  display: flex;
  gap: 24px;
  align-items: flex-end;
}

.hero__copy {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 40px;
  justify-content: flex-end;
}

.hero__image {
  flex-shrink: 0;
  width: var(--hero-img-w);
  aspect-ratio: 636 / 651;
  overflow: hidden;
}

/* First screen — nav plus hero fill exactly one viewport, with the same
   40px inset at the bottom as the sides so the padding reads as even all
   the way round. The 200px section gap above the hero is cancelled; the
   open space above the copy comes instead from the copy being
   bottom-aligned inside a full-height column.

   `svh` (small viewport height) keeps this stable on mobile browsers,
   where dynamic toolbars make `vh` jump mid-scroll.

   The image is pinned bottom-right by a sticky `top` calculated so its
   *bottom* lands one page-padding above the viewport floor. Sticky can
   only hold an element via `top` when scrolling down, so anchoring by
   `bottom` would not hold at all — the offset is computed instead.

   The hero is then extended by a second screen's worth of padding: that
   extra length is precisely how far the copy scrolls up past the pinned
   image before it releases. */
@media (min-width: 641px) {
  .hero {
    margin-top: calc(var(--section-gap) * -1);
    align-items: stretch;
    /* One screen of visible hero plus the pin length, which is the
       distance the copy travels while the image stays put. This has to
       come from real height rather than padding — a flex item's sticky
       containing block is the flex line, which only spans the content
       box, so padding here would give the image no travel at all. */
    min-height: calc(var(--first-screen) + var(--hero-pin));
  }

  /* Stretched over the full hero, then padded by the pin length so the
     copy still lands at the bottom of the first screen. */
  .hero__copy {
    padding-bottom: var(--hero-pin);
  }

  .hero__image {
    align-self: flex-start;
    position: sticky;
    top: calc(100vh - var(--page-pad) - var(--hero-img-h));
    top: calc(100svh - var(--page-pad) - var(--hero-img-h));
  }
}

.hero__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.link-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
}

.icon-arrow {
  width: 19px;
  height: 12px;
  transition: transform 0.3s var(--ease-reveal);
}

.link-cta:hover .icon-arrow,
.link-cta:focus-visible .icon-arrow {
  transform: translateX(5px);
}

@media (prefers-reduced-motion: reduce) {
  .icon-arrow {
    transition: none;
  }
}

@media (max-width: 1024px) {
  .hero {
    flex-direction: column-reverse;
    min-height: auto;
    margin-top: 0;
    align-items: stretch;
  }

  .hero__copy {
    padding-bottom: 0;
  }

  .hero__image {
    position: static;
    width: 100%;
    max-width: none;
    aspect-ratio: 4 / 3;
    align-self: stretch;
  }
}

@media (max-width: 640px) {
  .hero {
    gap: 40px;
    margin-top: calc(24px - var(--section-gap));
  }

  .hero__image {
    width: 100%;
    aspect-ratio: 4 / 5;
  }
}

/* ==========================================================================
   Placeholder pages (Blog / Media)
   ========================================================================== */

.intro {
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.intro__title {
  width: auto;
  max-width: 800px;
}

/* ==========================================================================
   About page
   ========================================================================== */

/* The design separates paragraphs with a full blank line, so successive
   paragraphs sit two line-heights apart baseline to baseline. Because the
   paragraphs are cap-trimmed, the gap has to make up the difference
   between that 2x step and the cap height:

     gap = (2 x 1.1em) - capHeight ~= 2.2em - 0.7em = 1.5em

   Expressed in em so it tracks the font size at every breakpoint. */
.bio {
  display: flex;
  flex-direction: column;
  font-size: 40px;
  gap: 1.5em;
}

/* H1 */
.bio__statement {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 1em;
  letter-spacing: -1.2px;
  line-height: 1.1;
  margin: 0;
}

/* Narrow single-statement page introductions without affecting the longer,
   multi-paragraph biography on About. */
.bio:not(.bio--about) > .bio__statement:only-child {
  max-width: 50%;
}

@media (max-width: 1024px) {
  .bio {
    font-size: 32px;
  }

  .bio__statement {
    letter-spacing: -0.9px;
  }

  .bio:not(.bio--about) > .bio__statement:only-child {
    max-width: 75%;
  }
}

@media (max-width: 640px) {
  .bio {
    font-size: 26px;
  }

  .bio__statement {
    letter-spacing: -0.7px;
  }

  .bio:not(.bio--about) > .bio__statement:only-child {
    max-width: 100%;
  }
}

.bio-image {
  width: 100%;
  aspect-ratio: 1360 / 627;
  overflow: hidden;
}

.bio-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 1024px) {
  .bio-image {
    aspect-ratio: 4 / 3;
  }
}

@media (max-width: 640px) {
  .bio-image {
    aspect-ratio: 4 / 5;
  }
}

.stack-lg {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.stack-item {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding-top: 32px;
  border-top: 1px solid var(--color-rule);
}

.stack-item:first-child {
  padding-top: 0;
  border-top: none;
}

.stack-item .fact__value {
  max-width: 1000px;
}

.stack-item a {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 0.07em;
}

.tag-list {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* Figma's pill is 16px padding above and below the CAP height: 16 + 13 + 16
   = 45px tall. `text-box` can't trim here (the label is an anonymous item
   inside a flex container), so the height is set explicitly instead —
   which also makes it immune to font-metric differences. */
.tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 45px;
  max-width: 100%;
  padding: 12px 20px;
  border-radius: 50px;
  background: var(--color-ink);
  color: var(--color-bg);
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 18px;
  line-height: 1;
  letter-spacing: -0.36px;
  white-space: normal;
  text-align: center;
}

.faq-list {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.faq-item {
  display: flex;
  flex-direction: column;
  padding-top: 32px;
  border-top: 1px solid var(--color-rule);
}

.faq-item:first-child {
  padding-top: 0;
  border-top: none;
}

.faq-question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  text-align: left;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 28px;
  letter-spacing: -0.84px;
  line-height: 1.1;
}

.faq-icon {
  flex-shrink: 0;
  width: 14px;
  height: 8px;
  transition: transform 0.4s var(--ease-reveal);
}

.faq-question[aria-expanded="true"] .faq-icon {
  transform: rotate(180deg);
}

.faq-answer {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.4s var(--ease-reveal);
}

.faq-answer p {
  min-height: 0;
  overflow: hidden;
  margin: 0;
  padding-top: 16px;
  font-family: var(--font-sans);
  font-size: 18px;
  line-height: 1.5;
  max-width: 700px;
}

.faq-question[aria-expanded="true"] + .faq-answer {
  grid-template-rows: 1fr;
}

@media (max-width: 1024px) {
  .bio-image {
    aspect-ratio: 4 / 5;
  }
}

@media (max-width: 640px) {
  .tag {
    font-size: 16px;
    min-height: 40px;
    padding: 10px 16px;
  }

  .faq-question {
    font-size: 20px;
    letter-spacing: -0.6px;
  }
}

/* ==========================================================================
   Row sections (In brief / Latest / Get in touch)
   ========================================================================== */

.row {
  display: flex;
  align-items: flex-start;
  gap: var(--row-gap);
}

.row__heading {
  position: sticky;
  top: var(--sticky-offset);
  flex-shrink: 0;
  width: clamp(220px, 18vw, 420px);
}

@media (max-width: 1024px) {
  .row {
    flex-direction: column;
  }

  .row__heading {
    position: static;
    width: auto;
  }
}

/* In brief */

.fact-list {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.fact {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding-top: 32px;
  border-top: 1px solid var(--color-rule);
}

.fact:first-child {
  padding-top: 0;
  border-top: none;
}

/* Latest */

.article-list {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.rule {
  border-top: 1px solid var(--color-rule);
  margin: 32px 0;
}

.article {
  display: flex;
  gap: 24px;
}

/* The frame is fixed; only the image inside scales, so the layout never
   shifts. It sits slightly zoomed in at rest and pulls back on hover —
   both states are >= 1 so the frame stays filled with no edge gaps. */
.article__thumb {
  flex-shrink: 0;
  width: clamp(140px, 14vw, 240px);
  aspect-ratio: 200 / 130;
  overflow: hidden;
}

.article__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.06);
  transition: transform 0.6s var(--ease-reveal);
}

.article:hover .article__thumb img {
  transform: scale(1);
}

@media (prefers-reduced-motion: reduce) {
  .article__thumb img {
    transition: none;
  }
}

.article__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.article__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  font-weight: 500;
  font-size: 14px;
  letter-spacing: -0.28px;
}

.article__title {
  display: inline-flex;
  align-items: flex-start;
  gap: 8px;
}

@media (max-width: 640px) {
  .article {
    flex-direction: column;
    gap: 16px;
  }

  .article__thumb {
    width: 100%;
    height: auto;
    aspect-ratio: 200 / 130;
  }
}

/* Get in touch */

.touch {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

/* ==========================================================================
   Footer
   ========================================================================== */

.footer {
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.footer__top {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 40px 60px;
  padding-top: 24px;
}

.footer__rule {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 1px;
  background: var(--color-rule);
}

.footer__col {
  flex: 1;
  min-width: 180px;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.footer__links {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.footer__links a {
  align-self: flex-start;
  max-width: 100%;
}

.footer__links a::after {
  bottom: -8px;
}

.footer__links--inline {
  flex-direction: row;
  align-items: baseline;
  gap: 8px;
}

/* Footer language options carry the same type as "Published Identity"
   et al. in the column beside them. */
.footer__links--inline .lang-option,
.footer__links--inline span {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 28px;
  letter-spacing: -0.84px;
  line-height: 1.1;
}

/* ==========================================================================
   Homepage preloader
   ========================================================================== */

.preloader {
  position: fixed;
  inset: 0;
  z-index: 10002;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-umber);
}

html.skip-home-preloader .preloader {
  display: none;
}

.preloader__logo {
  display: flex;
  gap: 0.35em;
  font-family: var(--font-wordmark);
  font-size: 24px;
  letter-spacing: -0.48px;
  text-transform: uppercase;
  color: var(--color-bg);
}

.preloader__word {
  display: inline-block;
  overflow: hidden;
}

.preloader__word > span {
  display: block;
}

body.is-locked {
  overflow: hidden;
  height: 100vh;
}

@media (max-width: 640px) {
  .preloader__logo {
    font-size: 18px;
    letter-spacing: -0.36px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .preloader {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .transition-panel,
  html.page-transition-arrival::after {
    display: none;
  }
}

/* ==========================================================================
   Blog page
   ========================================================================== */

/* Three columns of equal-height white cards, collapsing to two then one. */
.essay-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 32px;
  width: 100%;
}

.essay {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 40px;
  background: var(--color-porcelain);
  transform-origin: center;
  transition: transform 500ms cubic-bezier(0.22, 1, 0.36, 1);
}

.essay:hover,
.essay:focus-within {
  transform: scale(1.012);
}

@media (prefers-reduced-motion: reduce) {
  .essay {
    transition: none;
  }

  .essay:hover,
  .essay:focus-within {
    transform: none;
  }
}

/* Pins the CTA to the bottom of the card so it sits on a common line
   across the row, however long each excerpt runs. */
.essay .link-cta {
  margin-top: auto;
}

.essay__header {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.essay__header > div {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

@media (max-width: 1024px) {
  .essay-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 640px) {
  .essay-list {
    grid-template-columns: 1fr;
  }

  .essay {
    padding: 28px;
  }
}

.essay__excerpt {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 18px;
  letter-spacing: -0.54px;
  line-height: 1.1;
  margin: 0;
}

@media (max-width: 640px) {
.essay__excerpt {
    font-size: 17px;
    letter-spacing: -0.4px;
  }
}

/* ==========================================================================
   Blog detail
   ========================================================================== */

.page--post {
  gap: 160px;
}

.post-hero {
  min-height: calc(100svh - var(--nav-pad) - var(--nav-h) - var(--page-pad));
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 80px;
}

.post-hero__back {
  width: fit-content;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.32px;
}

.post-hero__heading {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.post-hero__title {
  max-width: 1250px;
  margin: 0;
  font-family: var(--font-sans);
  font-size: clamp(64px, 7.4vw, 138px);
  font-weight: 500;
  letter-spacing: -0.055em;
  line-height: 0.92;
}

.post-hero__footer {
  display: grid;
  grid-template-columns: minmax(0, 1.8fr) minmax(280px, 1fr);
  align-items: end;
  gap: 80px;
}

.post-hero__dek {
  max-width: 900px;
  font-size: 32px;
  font-weight: 400;
  letter-spacing: -0.9px;
  line-height: 1.1;
}

.post-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px 20px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.28px;
}

.post-image {
  width: 100%;
  height: min(76vw, 900px);
  min-height: 560px;
  overflow: hidden;
  background: var(--color-porcelain);
}

.post-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 58%;
  transform: scale(var(--portrait-scroll-scale, 1));
  transform-origin: center;
  will-change: transform;
}

.post-layout {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) minmax(0, 2fr);
  gap: clamp(80px, 10vw, 190px);
  align-items: start;
}

.post-aside {
  position: sticky;
  top: 40px;
  display: flex;
  flex-direction: column;
  gap: 24px;
  max-width: 320px;
  font-size: 17px;
  letter-spacing: -0.35px;
  line-height: 1.3;
}

.post-body {
  width: 100%;
  max-width: 820px;
  display: flex;
  flex-direction: column;
  gap: 34px;
  font-size: 22px;
  font-weight: 400;
  letter-spacing: -0.44px;
  line-height: 1.4;
}

.post-body p,
.post-body h2,
.post-body blockquote {
  margin: 0;
}

.post-body__lead {
  font-size: 32px;
  font-weight: 500;
  letter-spacing: -0.9px;
  line-height: 1.16;
}

.post-body h2 {
  padding-top: 60px;
  font-size: 42px;
  font-weight: 500;
  letter-spacing: -1.25px;
  line-height: 1.05;
}

.post-body blockquote {
  padding: 42px 0 46px;
  border-top: 1px solid var(--color-rule);
  border-bottom: 1px solid var(--color-rule);
  font-size: 42px;
  font-weight: 500;
  letter-spacing: -1.25px;
  line-height: 1.06;
}

.post-end {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 40px;
  padding-top: 32px;
  border-top: 1px solid var(--color-rule);
}

.post-end > div {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.post-end__author {
  font-size: 28px;
  font-weight: 500;
  letter-spacing: -0.84px;
}

.post-related {
  display: flex;
  flex-direction: column;
  gap: 60px;
}

.essay-list--related {
  grid-template-columns: repeat(2, 1fr);
}

@media (max-width: 1024px) {
  .page--post {
    gap: 200px;
  }

  .post-hero {
    min-height: auto;
    gap: 96px;
  }

  .post-hero__footer {
    grid-template-columns: 1fr;
    gap: 40px;
  }

  .post-meta {
    justify-content: flex-start;
  }

  .post-image {
    height: auto;
    min-height: 0;
    aspect-ratio: 4 / 3;
  }

  .post-layout {
    grid-template-columns: minmax(160px, 0.65fr) minmax(0, 2fr);
    gap: 64px;
  }
}

@media (max-width: 640px) {
  .page--post {
    gap: 96px;
  }

  .post-hero {
    gap: 72px;
  }

  .post-hero__heading {
    gap: 24px;
  }

  .post-hero__title {
    font-size: clamp(46px, 14vw, 66px);
    line-height: 0.94;
  }

  .post-hero__dek {
    font-size: 24px;
    letter-spacing: -0.65px;
  }

  .post-meta {
    flex-direction: column;
    gap: 8px;
  }

  .post-image {
    aspect-ratio: 4 / 5;
  }

  .post-layout {
    display: flex;
    flex-direction: column;
    gap: 64px;
  }

  .post-aside {
    position: static;
    max-width: 280px;
  }

  .post-body {
    gap: 28px;
    font-size: 19px;
    letter-spacing: -0.35px;
    line-height: 1.42;
  }

  .post-body__lead {
    font-size: 26px;
    letter-spacing: -0.7px;
  }

  .post-body h2 {
    padding-top: 40px;
    font-size: 32px;
    letter-spacing: -0.9px;
  }

  .post-body blockquote {
    padding: 32px 0 36px;
    font-size: 30px;
    letter-spacing: -0.85px;
  }

  .post-end {
    flex-direction: column;
    align-items: flex-start;
    gap: 48px;
  }

  .post-related {
    gap: 40px;
  }

  .essay-list--related {
    grid-template-columns: 1fr;
  }
}

/* ==========================================================================
   Media page
   ========================================================================== */

/* "Featured in" — heading stacked above a full-bleed infinite ticker.
   The track holds the logo set twice; translating it exactly -50% lands
   the duplicate where the original started, so the loop is seamless. */

.featured {
  display: flex;
  flex-direction: column;
  gap: var(--row-gap);
}

.ticker {
  width: calc(100% + (var(--page-pad) * 2));
  margin-left: calc(var(--page-pad) * -1);
  overflow: hidden;
}

.ticker__track {
  display: flex;
  align-items: center;
  gap: 80px;
  width: max-content;
  padding-left: 80px;
  animation: ticker-scroll 45s linear infinite;
}

.ticker__track img {
  filter: grayscale(1);
  height: 36px;
  width: auto;
  flex-shrink: 0;
}

/* Text stand-in for outlets whose logo files aren't in yet — matched to
   the 36px logo height so the row keeps an even baseline either way. */
.ticker__name {
  display: flex;
  align-items: center;
  height: 36px;
  flex-shrink: 0;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 28px;
  letter-spacing: -0.84px;
  line-height: 1;
  white-space: nowrap;
}

@keyframes ticker-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .ticker__track {
    animation: none;
  }
}

.press-list {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.press-item {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding-top: 32px;
  border-top: 1px solid var(--color-rule);
}

.press-item:first-child {
  padding-top: 0;
  border-top: none;
}

.press-item__meta {
  display: flex;
  gap: 16px;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 14px;
  letter-spacing: -0.28px;
}

/* H2 */
.press-item__title {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 36px;
  letter-spacing: -1.08px;
  line-height: 1.1;
  margin: 0;
}

@media (max-width: 1024px) {
  .press-item__title {
    font-size: 28px;
    letter-spacing: -0.84px;
  }
}

/* ==========================================================================
   Contact page
   ========================================================================== */

.contact-form {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.contact-form__fields {
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 100%;
}

/* Each field carries its own rule underneath, 16px below the label, with
   another 16px before the next field. */
.contact-form__field {
  display: flex;
  flex-direction: column;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--color-rule);
}

.contact-form input,
.contact-form textarea {
  width: 100%;
  display: block;
  border: none;
  background: transparent;
  padding: 0;
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 28px;
  letter-spacing: -0.84px;
  line-height: 1.1;
  color: var(--color-ink);
  outline: none;
  resize: none;
}

.contact-form input::placeholder,
.contact-form textarea::placeholder {
  color: var(--color-ink);
  opacity: 1;
}

.contact-form input:focus-visible,
.contact-form textarea:focus-visible {
  outline: 2px solid var(--color-ink);
  outline-offset: 5px;
}

/* Prevent browser autofill from painting its blue/yellow field background. */
.contact-form input:autofill,
.contact-form textarea:autofill,
.contact-form input:-webkit-autofill,
.contact-form input:-webkit-autofill:hover,
.contact-form input:-webkit-autofill:focus,
.contact-form textarea:-webkit-autofill,
.contact-form textarea:-webkit-autofill:hover,
.contact-form textarea:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--color-ink);
  caret-color: var(--color-ink);
  box-shadow: 0 0 0 1000px var(--color-bg) inset;
  -webkit-box-shadow: 0 0 0 1000px var(--color-bg) inset;
  border-radius: 0;
}

.contact-form textarea {
  min-height: 1.3em;
  field-sizing: content;
}

.contact-form button {
  cursor: pointer;
}

.contact-form button:disabled {
  cursor: wait;
  opacity: 0.55;
}

.contact-form__honeypot {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.contact-form__status {
  min-height: 1.1em;
  font-size: 18px;
  line-height: 1.1;
}

.contact-form.is-sent .contact-form__fields,
.contact-form.is-sent .cf-turnstile,
.contact-form.is-sent button {
  display: none;
}

.contact-form.is-sent {
  gap: 0;
}

.contact-form.is-sent .contact-form__status {
  margin: 0;
  max-width: 18em;
  font-size: 28px;
  font-weight: 500;
  letter-spacing: -0.84px;
}

@media (max-width: 640px) {
  .contact-form input,
  .contact-form textarea {
    font-size: 22px;
    letter-spacing: -0.6px;
  }
}

/* ==========================================================================
   Link underlines
   ========================================================================== */

/* Every link behaves the same way: clean at rest, underlined on hover.
   Inline links in body copy included, so an inline URL like haute.com
   doesn't read differently from the ventures listed beside it. */
.link-underline,
.stack-item a,
.essay__excerpt a,
.bio__statement a {
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: right bottom;
  background-size: 0% 0.07em;
  padding-bottom: 0;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  transition: background-size 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.article:hover .link-underline,
.press-item:hover .link-underline,
.stack-item a:hover,
.essay__excerpt a:hover,
.bio__statement a:hover,
.article__title:focus-visible .link-underline,
.press-item:focus-visible .link-underline,
.stack-item a:focus-visible,
.essay__excerpt a:focus-visible,
.bio__statement a:focus-visible {
  background-size: 100% 0.07em;
  background-position: left bottom;
}

@media (prefers-reduced-motion: reduce) {
  .link-underline,
  .footer__links a,
  .stack-item a,
  .essay__excerpt a,
  .bio__statement a {
    transition: none;
  }
}
