/* ===========================================================================
   Treble Four — site styles
   Load order: tokens.css, then this file.
   Sections in this file follow the order of the page.
   =========================================================================== */

/* ---------------------------------------------------------------- fonts -- */
@font-face {
  font-family: "Alegreya Sans";
  src: url("../fonts/alegreya-sans-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Alegreya Sans";
  src: url("../fonts/alegreya-sans-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Alegreya Sans";
  src: url("../fonts/alegreya-sans-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  margin: 0;
  background-color: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  font-weight: var(--weight-regular);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1,
h2,
h3,
h4,
p,
figure,
blockquote,
ol,
ul {
  margin: 0;
}

ol,
ul {
  padding: 0;
  list-style: none;
}

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

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

button,
input,
textarea {
  font: inherit;
  color: inherit;
}

::selection {
  background: var(--accent);
  color: var(--bg);
}

/* ------------------------------------------------------------- utilities -- */
.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background: var(--bg);
  color: var(--ink);
  border: var(--hairline) solid var(--ink);
  transform: translateY(-120%);
}

.skip-link:focus-visible {
  transform: translateY(0);
}

/* Focus is deliberately quiet but unmistakable. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 1px;
}

/* ------------------------------------------------------------ typography -- */
.label {
  font-size: var(--t-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  font-weight: var(--weight-medium);
  color: var(--ink-muted);
}

.section-heading {
  font-size: var(--t-title);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  letter-spacing: 0.01em;
  color: var(--ink);
}

/* --------------------------------------------------------------- layout -- */
.section {
  position: relative;
  padding-block: var(--section-pad);
}

/* Anchor jumps must clear the sticky masthead. */
.section,
.hero {
  scroll-margin-top: clamp(4rem, 3rem + 2vw, 5.5rem);
}

/* Sections carry no background of their own — the tone engine drifts the
   page ground instead, so there are no hard rectangular breaks. */

/* ------------------------------------------------------------ masthead --- */
.masthead {
  position: sticky;
  top: 0;
  z-index: 50;
  background-color: transparent;
  /* Kept short so the masthead tracks the page tone closely during a fast
     scroll rather than trailing a pale band over a dark section. */
  transition: background-color var(--dur-fast) linear,
    box-shadow var(--dur-mid) var(--ease);
}

.masthead[data-scrolled="true"] {
  background-color: var(--veil);
  box-shadow: 0 var(--hairline) 0 var(--rule);
}

@supports (backdrop-filter: blur(1px)) {
  .masthead[data-scrolled="true"] {
    backdrop-filter: blur(14px) saturate(115%);
  }
}

.masthead__inner {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-m);
  padding-block: clamp(1.1rem, 0.8rem + 0.9vw, 1.75rem);
}

/* About a fifth larger than it was, and a step heavier than the navigation,
   so the brand sits clearly above it rather than beside it. */
.wordmark {
  font-size: clamp(1.3rem, 1.2rem + 0.45vw, 1.53rem);
  font-weight: var(--weight-medium);
  letter-spacing: -0.004em;
  color: var(--ink);
  transition: color var(--dur-fast) var(--ease);
}

.wordmark:hover {
  color: var(--accent);
}

.nav {
  display: flex;
  align-items: baseline;
  gap: clamp(1.25rem, 0.5rem + 2vw, 2.75rem);
}

/* Lighter than the wordmark, by size and letterspacing rather than by
   fading it further: 0.78 is as low as this opacity can go before 14px text
   stops meeting 4.5:1 against the ivory. */
.nav__link {
  position: relative;
  font-size: 0.875rem;
  letter-spacing: 0.012em;
  color: var(--ink);
  opacity: 0.78;
  transition: opacity var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease);
}

.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.35em;
  height: var(--hairline);
  background: currentColor;
  opacity: 0;
  transform: scaleX(0.4);
  transform-origin: left;
  transition: opacity var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease);
}

.nav__link:hover,
.nav__link:focus-visible {
  opacity: 1;
  color: var(--accent);
}

.nav__link[aria-current="location"] {
  opacity: 1;
}

.nav__link[aria-current="location"]::after {
  opacity: 0.45;
  transform: scaleX(1);
}

/* Menu button — mobile only, no desktop hamburger. */
.nav-toggle {
  display: none;
  align-items: center;
  gap: 0.55rem;
  padding: 0.4rem 0;
  background: none;
  border: 0;
  cursor: pointer;
  font-size: var(--t-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
}

.nav-toggle__bars {
  display: block;
  position: relative;
  width: 1.125rem;
  height: var(--hairline);
  background: currentColor;
}

.nav-toggle__bars::before,
.nav-toggle__bars::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: var(--hairline);
  background: currentColor;
  transition: transform var(--dur-fast) var(--ease);
}

.nav-toggle__bars::before {
  top: -0.3125rem;
}

.nav-toggle__bars::after {
  top: 0.3125rem;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars {
  background: transparent;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars::before {
  transform: translateY(0.3125rem) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars::after {
  transform: translateY(-0.3125rem) rotate(-45deg);
}

@media (max-width: 51.99em) {
  /* The collapsing panel is only offered when there is script to open it.
     Without it, the links stay on the page as a plain wrapped row. */
  .js .nav-toggle {
    display: inline-flex;
  }

  html:not(.js) .masthead__inner {
    flex-wrap: wrap;
    row-gap: 0.75rem;
  }

  html:not(.js) .nav {
    flex-wrap: wrap;
    gap: 0.5rem 1.25rem;
  }

  .js .nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch; /* so the dividing rules span the panel */
    gap: 0;
    padding: var(--space-xs) var(--gutter) var(--space-m);
    background-color: var(--veil);
    box-shadow: 0 var(--hairline) 0 var(--rule);
    visibility: hidden;
    opacity: 0;
    transform: translateY(-0.5rem);
    transition: opacity var(--dur-fast) var(--ease),
      transform var(--dur-fast) var(--ease), visibility var(--dur-fast);
  }

  @supports (backdrop-filter: blur(1px)) {
    .js .nav {
      backdrop-filter: blur(16px) saturate(115%);
    }
  }

  .js .nav[data-open="true"] {
    visibility: visible;
    opacity: 1;
    transform: translateY(0);
  }

  .js .nav__link {
    display: block;
    width: 100%;
    padding-block: 0.7rem;
    font-size: 1.0625rem;
    opacity: 1;
    border-bottom: var(--hairline) solid var(--rule);
  }

  .nav__link::after {
    display: none;
  }

  .js .nav li:last-child .nav__link {
    border-bottom: 0;
  }
}

/* ------------------------------------------------------------------ hero -- */
/* Sized so the whole hero — both lines and the closing rule — sits within
   the first screen without feeling crowded. */
.hero {
  min-height: 76svh;
  display: flex;
  align-items: center;
  padding-block: clamp(2.5rem, 2rem + 3vw, 5rem) clamp(3.5rem, 2.5rem + 5vw, 7rem);
}

.hero__inner {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--col-gap);
  width: 100%;
}

.hero__line {
  grid-column: 1 / span 11;
  font-size: var(--t-display);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  font-weight: var(--weight-regular);
  color: var(--ink);
  text-wrap: balance;
}

/* The one piece of copper above the fold. Putting it on the supporting line
   rather than on a rule under the wordmark keeps the masthead monochrome —
   so the brand-over-navigation hierarchy stays clean — and puts the accent
   on the best line of copy on the page instead of on a decoration. */
.hero__support {
  grid-column: 2 / span 8;
  margin-top: clamp(2rem, 1rem + 4vw, 4rem);
  font-size: var(--t-body-lg);
  color: var(--accent);
}

@media (min-width: 52em) {
  .hero__line {
    grid-column: 1 / span 10;
  }

  .hero__support {
    grid-column: 2 / span 6;
  }
}

/* A single hairline that quietly marks the end of the hero. */
.hero__rule {
  grid-column: 1 / -1;
  margin-top: clamp(3rem, 2rem + 5vw, 6rem);
  height: var(--hairline);
  background: var(--rule);
  transform-origin: left;
}

/* ---------------------------------------------------- current interests -- */
.interests-head {
  margin-bottom: clamp(2.5rem, 1.5rem + 4vw, 5rem);
}

.interests {
  position: relative;
}

.interest {
  position: relative;
  padding-block: clamp(1.6rem, 1rem + 2vw, 2.4rem);
  border-top: var(--hairline) solid var(--rule);
}

.interest:last-child {
  border-bottom: var(--hairline) solid var(--rule);
}

.interest__name {
  position: relative;
  font-size: var(--t-word);
  line-height: var(--lh-snug);
  letter-spacing: var(--track-display);
  font-weight: var(--weight-regular);
  color: var(--ink);
}

/* The copper rule belongs to every entry, not only to the pinned one. On a
   phone there is no hover and no pinned marker, so without this the accent
   would never appear on a touch device at all. */
.interest__name::before {
  content: "";
  display: block;
  width: 1.75rem;
  height: var(--hairline);
  margin-bottom: 0.7rem;
  background: var(--accent);
}

.interest__copy {
  margin-top: var(--space-xs);
  max-width: 32rem;
  font-size: var(--t-body-lg);
  color: var(--ink-muted);
}

/* Added by script only in the pinned composition, where jumping between
   interests is a real thing to want. In the stacked list all five are already
   on screen, so there is nothing to jump to and no control is created. */
.interest__trigger {
  display: block;
  width: 100%;
  padding: 0;
  margin: 0;
  background: none;
  border: 0;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease);
}

.interest__trigger:hover {
  color: var(--accent);
}

.interest__trigger:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
}

/* --- Desktop: semi-pinned progressive focus ------------------------------
   The list stays put while a tall track scrolls past it. Each interest takes
   its turn as the active one; the others recede rather than disappear. The
   stacked layout above is the fallback for narrow screens, reduced motion and
   no-JS, so the content is identical in every mode.                        */
@media (min-width: 62em) and (prefers-reduced-motion: no-preference) {
  /* The track is the scroll distance the composition holds for. Kept short
     enough that reading five sentences does not cost three screens of
     scrolling — the reveal is the point, the toll is not. */
  .js .interests[data-mode="pinned"] {
    height: calc(5 * 40vh);
  }

  /* Two levels of display:contents lift the headings and paragraphs into the
     stage grid, so the copy can share one slot without leaving the DOM
     position that keeps the reading order sensible. */
  .js .interests[data-mode="pinned"] .interests__list,
  .js .interests[data-mode="pinned"] .interest {
    display: contents;
  }

  .js .interests[data-mode="pinned"] .interests__stage {
    position: sticky;
    top: 24vh;
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--col-gap);
    align-items: start;
  }

  .js .interests[data-mode="pinned"] .interest__name {
    position: relative;
    grid-column: 1;
    padding-block: clamp(0.35rem, 0.1rem + 0.7vw, 0.7rem);
    padding-left: 0;
    border-top: 0;
    /* Present enough to read as a standing list of five, not as ghosts. */
    opacity: 0.36;
    transform: scale(0.97);
    transform-origin: left center;
    transition: opacity var(--dur-slow) var(--ease),
      transform var(--dur-slow) var(--ease),
      padding-left var(--dur-slow) var(--ease),
      color var(--dur-slow) var(--ease);
  }

  .js .interests[data-mode="pinned"] .interest[data-active="true"] .interest__name {
    opacity: 1;
    transform: scale(1);
    padding-left: clamp(1.5rem, 3vw, 3.25rem);
    /* The active interest takes the copper as well as the size, so the accent
       is doing something structural rather than only decorating a hairline. */
    color: var(--accent);
  }

  .js
    .interests[data-mode="pinned"]
    .interest[data-active="true"]
    .interest__trigger {
    color: var(--accent);
  }

  /* The copper marker is the only place the accent appears in this section. */
  .js .interests[data-mode="pinned"] .interest__name::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.62em;
    width: clamp(0.75rem, 2vw, 2.25rem);
    height: var(--hairline);
    background: var(--accent);
    opacity: 0;
    transform: scaleX(0);
    transform-origin: left;
    transition: opacity var(--dur-mid) var(--ease),
      transform var(--dur-slow) var(--ease);
  }

  .js
    .interests[data-mode="pinned"]
    .interest[data-active="true"]
    .interest__name::before {
    opacity: 1;
    transform: scaleX(1);
  }

  /* All five paragraphs share one slot beside the list and cross-fade.
     Spanning every row keeps them from stretching the list. */
  .js .interests[data-mode="pinned"] .interest__copy {
    grid-column: 2;
    grid-row: 1 / span 5;
    align-self: center;
    max-width: 26rem;
    opacity: 0;
    transform: translateY(0.5rem);
    transition: opacity var(--dur-mid) var(--ease),
      transform var(--dur-mid) var(--ease);
    pointer-events: none;
  }

  .js .interests[data-mode="pinned"] .interest[data-active="true"] .interest__copy {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }
}

/* -------------------------------------------------------- special projects -- */
.cases-head {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--col-gap);
  margin-bottom: clamp(3rem, 2rem + 5vw, 6.5rem);
}

.cases-head__label {
  grid-column: 1 / -1;
  margin-bottom: clamp(1.75rem, 1rem + 3vw, 3.25rem);
}

.cases-head__lede {
  grid-column: 1 / -1;
  font-size: var(--t-lead);
  line-height: 1.16;
  letter-spacing: var(--track-display);
  font-weight: var(--weight-regular);
  color: var(--ink);
  text-wrap: balance;
}

@media (min-width: 52em) {
  .cases-head__lede {
    grid-column: 2 / span 9;
  }
}

.cases {
  display: flex;
  flex-direction: column;
}

/* Case files are deliberately ruled rather than boxed — a dossier, not cards.
   To make one clickable later, wrap .case__body content in an <a> and add
   `position:absolute; inset:0` to its ::after. No other change is required. */
.case {
  position: relative;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--col-gap);
  padding-block: clamp(2.25rem, 1.5rem + 3vw, 4rem);
  border-top: var(--hairline) solid var(--rule);
}

.case:last-child {
  border-bottom: var(--hairline) solid var(--rule);
}

.case__meta {
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
  margin-bottom: var(--space-s);
}

.case__index {
  font-size: var(--t-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  font-weight: var(--weight-medium);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.case__field {
  font-size: var(--t-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.case__body {
  grid-column: 1 / -1;
}

.case__title {
  font-size: var(--t-title);
  line-height: var(--lh-snug);
  font-weight: var(--weight-medium);
  color: var(--ink);
  margin-bottom: var(--space-xs);
}

.case__copy {
  max-width: 42rem;
  color: var(--ink-muted);
  font-size: var(--t-body-lg);
}

@media (min-width: 52em) {
  .case__meta {
    grid-column: 1 / span 3;
    flex-direction: column;
    gap: 0.4rem;
    margin-bottom: 0;
  }

  .case__body {
    grid-column: 4 / span 8;
  }

  /* A small, deliberate stagger — asymmetry without novelty. */
  .case:nth-child(2) .case__body {
    grid-column: 5 / span 8;
  }

  .case:nth-child(3) .case__body {
    grid-column: 6 / span 7;
  }
}

/* ---------------------------------------------------------- how we work -- */
.modes {
  display: flex;
  flex-direction: column;
  margin-top: clamp(2.5rem, 1.5rem + 4vw, 5rem);
}

.mode {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--col-gap);
  padding-block: clamp(1.75rem, 1.2rem + 2.4vw, 3rem);
  border-top: var(--hairline) solid var(--rule);
}

.mode:last-child {
  border-bottom: var(--hairline) solid var(--rule);
}

.mode__name {
  grid-column: 1 / -1;
  font-size: clamp(1.5rem, 1.15rem + 1.6vw, 2.35rem);
  line-height: var(--lh-snug);
  font-weight: var(--weight-regular);
  letter-spacing: var(--track-display);
  color: var(--ink);
  margin-bottom: var(--space-2xs);
}

.mode__copy {
  grid-column: 1 / -1;
  max-width: 34rem;
  color: var(--ink-muted);
  font-size: var(--t-body-lg);
}

@media (min-width: 52em) {
  .mode__name {
    grid-column: 1 / span 4;
    margin-bottom: 0;
  }

  .mode__copy {
    grid-column: 5 / span 7;
  }

  .mode:nth-child(2) .mode__copy {
    grid-column: 6 / span 6;
  }

  .mode:nth-child(3) .mode__copy {
    grid-column: 7 / span 6;
  }
}

/* ----------------------------------------------------------------- about -- */
.about {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--col-gap);
}

/* About now opens with a section heading like every other section, instead
   of going straight into the oversized lead. */
.about__heading {
  grid-column: 1 / -1;
  margin-bottom: clamp(2rem, 1.2rem + 3vw, 3.5rem);
}

.about__lead {
  grid-column: 1 / -1;
  font-size: var(--t-lead);
  line-height: 1.14;
  letter-spacing: var(--track-display);
  font-weight: var(--weight-regular);
  color: var(--ink);
  text-wrap: balance;
}

.about__body {
  grid-column: 1 / -1;
  margin-top: clamp(2rem, 1.25rem + 3vw, 3.75rem);
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  max-width: var(--measure);
  font-size: var(--t-body-lg);
  color: var(--ink-muted);
}

@media (min-width: 52em) {
  .about__lead {
    grid-column: 1 / span 8;
  }

  .about__body {
    grid-column: 5 / span 7;
  }
}

/* --------------------------------------------------------------- contact -- */
.contact {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--col-gap);
  row-gap: clamp(2.5rem, 1.5rem + 5vw, 4.5rem);
}

.contact__intro {
  grid-column: 1 / -1;
}

.contact__heading {
  font-size: var(--t-title);
  font-weight: var(--weight-medium);
  color: var(--ink);
  margin-bottom: clamp(1.5rem, 1rem + 2vw, 2.5rem);
}

.contact__copy {
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  max-width: 30rem;
  font-size: var(--t-body-lg);
  color: var(--ink-muted);
}

.contact__copy strong {
  font-weight: var(--weight-regular);
  color: var(--ink);
}

.contact__form-wrap {
  grid-column: 1 / -1;
}

@media (min-width: 52em) {
  .contact__intro {
    grid-column: 1 / span 5;
  }

  .contact__form-wrap {
    grid-column: 7 / span 6;
  }
}

/* ------------------------------------------------------------------ form -- */
.form {
  display: flex;
  flex-direction: column;
  gap: clamp(1.5rem, 1rem + 1.5vw, 2.25rem);
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/* A step up from the other small caps on the page: this is the one place a
   visitor has to actually do something, and 12px letterspaced is tight for
   that. */
.field__label {
  font-size: 0.8125rem;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.field__input {
  width: 100%;
  padding: 0.45rem 0;
  background: transparent;
  border: 0;
  border-bottom: var(--hairline) solid var(--rule);
  border-radius: 0;
  color: var(--ink);
  font-size: var(--t-body-lg);
  transition: border-color var(--dur-fast) var(--ease);
}

.field__input:hover {
  border-bottom-color: var(--ink-muted);
}

.field__input:focus {
  outline: none;
  border-bottom-color: var(--accent);
}

.field__input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
}

textarea.field__input {
  min-height: 7.5rem;
  resize: vertical;
  line-height: var(--lh-body);
}

.field__error {
  font-size: var(--t-small);
  color: var(--accent);
  min-height: 0;
}

.field[data-invalid="true"] .field__input {
  border-bottom-color: var(--accent);
}

/* Honeypot: present for bots, gone for people and assistive technology. */
.field--trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__actions {
  display: flex;
  align-items: center;
  gap: var(--space-s);
}

/* Deliberately not a giant CTA — a considered piece of text with a rule. */
.button {
  display: inline-block;
  padding: 0.55rem 0;
  background: none;
  border: 0;
  border-bottom: var(--hairline) solid var(--ink);
  color: var(--ink);
  font-size: var(--t-body-lg);
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}

.button:hover,
.button:focus-visible {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.button[disabled] {
  opacity: 0.45;
  cursor: default;
}

.form__status {
  font-size: var(--t-small);
  color: var(--ink-muted);
}

.form__status[data-state="error"] {
  color: var(--accent);
}

.form__turnstile:not(:empty) {
  margin-block: calc(var(--space-xs) * -1);
}

/* Confirmation replaces the form in place. */
.form-confirmation {
  font-size: var(--t-body-lg);
  color: var(--ink);
  padding-top: 0.5rem;
  border-top: var(--hairline) solid var(--rule);
  padding-block-start: var(--space-s);
}

/* ---------------------------------------------------------------- footer -- */
.footer {
  padding-block: clamp(3rem, 2rem + 3vw, 5rem) clamp(2rem, 1.5rem + 2vw, 3.5rem);
  border-top: var(--hairline) solid var(--rule);
}

/* Stacked and left-aligned: mark, then Privacy, then the copyright. Spread
   across the full width the three read as three unrelated things; in a column
   on the axis the rest of the page sits on, they read as a colophon. */
.footer__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-xs);
}

.footer__mark {
  font-size: 1.0625rem;
  font-weight: var(--weight-medium);
  color: var(--ink);
}

.footer__links {
  display: flex;
  gap: var(--space-m);
  font-size: var(--t-small);
}

.footer__link {
  color: var(--ink-muted);
  border-bottom: var(--hairline) solid transparent;
  transition: color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}

.footer__link:hover,
.footer__link:focus-visible {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.footer__legal {
  font-size: var(--t-small);
  color: var(--ink-muted);
}

/* -------------------------------------------------------- privacy page --- */
.doc {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--col-gap);
}

.doc__head {
  grid-column: 1 / -1;
  margin-bottom: clamp(2.5rem, 1.5rem + 4vw, 4.5rem);
}

.doc__title {
  font-size: var(--t-lead);
  line-height: 1.14;
  letter-spacing: var(--track-display);
  font-weight: var(--weight-regular);
  color: var(--ink);
}

.doc__meta {
  margin-top: var(--space-xs);
}

.doc__body {
  grid-column: 1 / -1;
  max-width: var(--measure);
}

@media (min-width: 52em) {
  .doc__head {
    grid-column: 1 / span 9;
  }

  .doc__body {
    grid-column: 3 / span 8;
  }
}

.doc__body section + section {
  margin-top: clamp(2.25rem, 1.5rem + 2.5vw, 3.25rem);
}

.doc__body h2 {
  font-size: var(--t-title);
  font-weight: var(--weight-medium);
  color: var(--ink);
  margin-bottom: var(--space-xs);
}

.doc__body p,
.doc__body li {
  color: var(--ink-muted);
}

.doc__body p + p {
  margin-top: var(--space-s);
}

.doc__body ul {
  margin-top: var(--space-xs);
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.doc__body li {
  position: relative;
  padding-left: 1.25rem;
}

.doc__body li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.75em;
  width: 0.5rem;
  height: var(--hairline);
  background: var(--rule);
}

.doc__body code {
  font-family: ui-monospace, "SFMono-Regular", "Consolas", monospace;
  font-size: 0.875em;
  color: var(--ink);
}

.doc__body strong {
  font-weight: var(--weight-medium);
  color: var(--ink);
}

.doc__body a {
  color: var(--ink);
  border-bottom: var(--hairline) solid var(--rule);
  transition: color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}

.doc__body a:hover,
.doc__body a:focus-visible {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* ------------------------------------------------------- privacy notice -- */
/* One quiet line, not a banner. Behaviour is controlled in assets/js/config.js. */
.notice {
  position: fixed;
  left: var(--gutter);
  bottom: clamp(1rem, 3vw, 2rem);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: var(--space-s);
  max-width: min(30rem, calc(100vw - var(--gutter) * 2));
  padding: 0.75rem 1rem;
  background-color: var(--veil);
  border: var(--hairline) solid var(--rule);
  font-size: var(--t-small);
  color: var(--ink-muted);
  opacity: 0;
  transform: translateY(0.5rem);
  transition: opacity var(--dur-mid) var(--ease),
    transform var(--dur-mid) var(--ease);
}

@supports (backdrop-filter: blur(1px)) {
  .notice {
    backdrop-filter: blur(14px);
  }
}

.notice[data-visible="true"] {
  opacity: 1;
  transform: translateY(0);
}

.notice a {
  color: var(--ink);
  border-bottom: var(--hairline) solid var(--rule);
}

.notice a:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.notice__dismiss {
  margin-left: auto;
  padding: 0;
  background: none;
  border: 0;
  color: var(--ink);
  font-size: var(--t-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  cursor: pointer;
  white-space: nowrap;
}

.notice__dismiss:hover {
  color: var(--accent);
}

/* ---------------------------------------------------------------- reveal -- */
/* Elements are visible by default; the hidden start state only applies once
   JavaScript has confirmed it can reveal them again. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(0.75rem);
  transition: opacity var(--dur-reveal) var(--ease),
    transform var(--dur-reveal) var(--ease);
}

.js [data-reveal][data-revealed="true"] {
  opacity: 1;
  transform: none;
}

.js [data-reveal="rule"] {
  transform: scaleX(0);
  transition: transform 1.4s var(--ease);
}

.js [data-reveal="rule"][data-revealed="true"] {
  transform: scaleX(1);
}

@media (prefers-reduced-motion: reduce) {
  .js [data-reveal],
  .js [data-reveal="rule"] {
    opacity: 1;
    transform: none;
    transition: none;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Staggered reveal delays, applied sparingly. */
.js [data-reveal-delay="1"] {
  transition-delay: 90ms;
}
.js [data-reveal-delay="2"] {
  transition-delay: 180ms;
}
.js [data-reveal-delay="3"] {
  transition-delay: 270ms;
}

@media print {
  .masthead,
  .notice,
  .form {
    display: none;
  }
}
