@charset "UTF-8";
/*
 * Thought For Food Moments
 * Built from TFFM_Website_v4.pdf (1433 x 7417 design units).
 *
 * Horizontal placement is transcribed from the comp: each offset and width is
 * that element's design-x divided by 1433. Sections whose content is scattered
 * (the gathering cards, the Fig plates) sit on a 100-column grid, so a design-x
 * percentage becomes a column number directly — exact placement, ordinary flow.
 *
 * Type: display sizes match the comp 1:1 at a 1440 viewport so its column fits
 * and line breaks hold. Only the small sizes are scaled up; the comp sets body
 * copy at 10px and the footer at 8px, both below a readable floor. Mono blocks
 * are measured in `ch`, so their line breaks match the comp at any size.
 */

/* ------------------------------------------------------------------ fonts */
@font-face { font-family: "Bradford LL"; src: url("../fonts/bradford-light.woff2") format("woff2"); font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: "Bradford LL"; src: url("../fonts/bradford-book.woff2") format("woff2"); font-weight: 450; font-style: normal; font-display: swap; }
@font-face { font-family: "Bradford LL"; src: url("../fonts/bradford-medium.woff2") format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "Bradford Mono LL"; src: url("../fonts/bradford-mono.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Cathies Hand"; src: url("../fonts/cathies-hand.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Office Times Sharp"; src: url("../fonts/office-sharp.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }

/* ----------------------------------------------------------------- tokens */
:root {
  /* palette — sampled from the comp */
  --paper: #dddbdc;
  --green: #182b29;
  --ink: #6a6c6c;
  --ink-nav: #716d6c;
  --blue: #5b87b3;
  --cream: #dcd7d2;
  --ink-hand: #2f3133;
  --dark: #1b2321;

  --fg: var(--ink);

  --f-display: "Bradford LL", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --f-mono: "Bradford Mono LL", ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  --f-hand: "Cathies Hand", "Segoe Script", "Bradley Hand", cursive;
  --f-sharp: "Office Times Sharp", var(--f-mono);

  /* small sizes: raised from the comp for legibility */
  --fs-body: clamp(13px, 0.98vw, 15.5px);
  --fs-micro: clamp(11px, 0.78vw, 12.5px);
  --fs-nav: clamp(11.5px, 0.86vw, 13.5px);
  /* display sizes: comp-exact at 1440 */
  --fs-lead: clamp(17px, 1.35vw, 23px);
  --fs-display-m: clamp(22px, 1.92vw, 32px);
  --fs-display-l: clamp(23px, 2.07vw, 35px);
  --fs-display-xl: clamp(40px, 4.6vw, 78px);
  --fs-hand-s: clamp(14px, 1.14vw, 19px);
  --fs-hand-m: clamp(17px, 1.35vw, 23px);

  --rail-w: 17.5%;
  --plate-pad: clamp(7px, 0.77vw, 12px);
  --plate-radius: clamp(4px, 0.42vw, 7px);
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ------------------------------------------------------------------ reset */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-mono);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}
img { display: block; max-width: 100%; height: auto; }
picture { display: block; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
h1, h2, h3, h4, p, ul, ol, figure, figcaption, blockquote { margin: 0; padding: 0; }
ul, ol { list-style: none; }
:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
.u-visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.u-skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--paper); color: var(--ink); padding: 0.8em 1.2em;
}
.u-skip:focus { left: 0; }

/* ------------------------------------------------------- typographic roles */
.t-kicker {
  font-family: var(--f-display); font-weight: 500; font-size: var(--fs-nav);
  letter-spacing: 0.11em; text-transform: uppercase; color: var(--blue); line-height: 1.2;
}
.t-display {
  font-family: var(--f-display); font-weight: 300; line-height: 1.16;
  letter-spacing: -0.012em; color: var(--fg);
}
.t-body {
  font-family: var(--f-mono); font-size: var(--fs-body); line-height: 1.62; color: var(--fg);
}
.t-micro {
  font-family: var(--f-mono); font-size: var(--fs-micro);
  letter-spacing: 0.06em; line-height: 1.55; text-transform: uppercase;
}
/* Display headings are set as discrete lines. --i is the comp's indent as a
   share of the 1433 grid, so 1vw is one grid unit at the design width. */
.t-display .l { display: block; margin-left: calc(var(--i, 0) * 1vw); }
.t-display .l--right { text-align: right; }

/* ------------------------------------------------------------------- shell */
.site { position: relative; }
.section { position: relative; isolation: isolate; }
.section__inner { position: relative; z-index: 2; width: 100%; }
.section.is-dark, .section.is-green { --fg: var(--paper); color: var(--paper); }
.section.is-green { background: var(--green); }
.section.is-dark { background: var(--dark); }

/* A 100-column grid: a comp percentage becomes a column number. */
.grid100 { display: grid; grid-template-columns: repeat(100, 1fr); align-items: start; }

/* --------------------------------------------------------------- nav rail */
.rail {
  position: fixed; top: 0; left: 0; z-index: 40;
  width: var(--rail-w); min-width: 176px;
  padding: 1.75vw 0 0 1.95%;
  pointer-events: none;
}
.rail__nav { pointer-events: auto; }
.rail__group + .rail__group { margin-top: 1.9vw; }
.rail__title {
  display: flex; gap: 0.7em;
  font-family: var(--f-display); font-weight: 500; font-size: var(--fs-nav);
  letter-spacing: 0.085em; text-transform: uppercase; color: var(--blue);
  line-height: 1.28; white-space: nowrap;
}
.rail__num { flex: 0 0 auto; min-width: 2.1em; }
.rail__list { margin-top: 0.24em; padding-left: 2.8em; }
.rail__link {
  display: block; font-family: var(--f-mono); font-size: var(--fs-nav);
  line-height: 1.34; white-space: nowrap;
  color: var(--rail-fg, var(--ink-nav));
  transition: color 0.5s var(--ease), opacity 0.4s var(--ease);
}
.rail__link:hover, .rail__link:focus-visible { color: var(--blue); }
/* On dark sections the whole rail goes light — group titles included. The comp
   draws it this way over the Experience photograph; the hero state it draws
   (blue titles, dark grey sub-items) is illegible on the photography, so the
   light treatment is applied to every dark and green section. */
.rail.on-dark { --rail-fg: var(--paper); }
/* Whole-rail fallback, for before the per-item theming below has run. Scoped to
   :not([data-on]) so the per-item rules always win once set — otherwise this
   selector's higher specificity kept titles paper-on-paper past a boundary. */
.rail[data-rail-title="light"] .rail__title:not([data-on]) { color: var(--paper); }
.rail.on-dark .rail__link:not([data-on]):hover,
.rail.on-dark .rail__link:not([data-on]):focus-visible { color: #fff; }
/* Per-item colour, set by the observer from the section behind each item, so the
   rail reads correctly where it crosses a background boundary. Higher
   specificity than the whole-rail rules above, which remain the fallback and
   drive the mobile bar. */
.rail__title[data-on="light"] { color: var(--blue); }
.rail__title[data-on="dark"][data-title="blue"] { color: var(--blue); }
.rail__title[data-on="dark"][data-title="light"] { color: var(--paper); }
.rail__link[data-on="light"] { color: var(--ink-nav); }
.rail__link[data-on="dark"] { color: var(--paper); }
.brand__word[data-on="light"] { color: var(--blue); }
.brand__word[data-on="dark"] { color: var(--paper); }
/* The comp keeps the mark blue on the hero and turns it paper over the
   Experience photograph — the same distinction the rail titles make, so it is
   driven by the same data-title flag rather than by the background alone. */
.brand__mark[data-on="dark"][data-title="light"] { background-color: var(--paper); }
.brand__mark[data-on="dark"][data-title="blue"] { background-color: var(--blue); }
.brand__mark[data-on="light"] { background-color: var(--blue); }
.rail__link[data-on]:hover,
.rail__link[data-on]:focus-visible { color: var(--blue); }
.rail__link[data-on="dark"]:hover,
.rail__link[data-on="dark"]:focus-visible { color: #fff; }
.rail__group:not(.is-active) .rail__link { opacity: 0.82; }
.rail__toggle { display: none; }
/* WordPress admin bar: fixed 32px (46px under 783px, where it also becomes
   fixed rather than scrolling away). Offset the rail so it clears it. */
body.admin-bar .rail { padding-top: calc(1.75vw + 32px); }
@media screen and (max-width: 782px) {
  body.admin-bar .rail { top: 46px; }
}

/* ----------------------------------------------------------------- plates */
.plate {
  position: relative; display: block;
  background: var(--cream); border-radius: var(--plate-radius);
  padding: var(--plate-pad); padding-bottom: calc(var(--plate-pad) * 1.28);
}
.plate img { width: 100%; border-radius: 1px; }
.plate--bare { background: none; border-radius: 0; padding: 0; }
/* Torn deckle edge. Uses the designer's own paper texture, linked in the .ai as
   a PSD, rather than the procedural SVG turbulence this used before.

   The face and the mat width are variables so a plate can pick the orientation
   that matches its image. background-size: 100% 100% stretches the texture to
   the box, so a portrait photo in the landscape sheet would smear the torn edge
   along one axis and read as a scaling artefact instead of paper. */
.plate--deckle {
  --deckle-face: var(--deckle-sheet-land);
  --deckle-mat: calc(var(--plate-pad) * 2.2);
  padding: var(--deckle-mat);
  border-radius: 0;
  background: none;
}
.plate--deckle::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: var(--deckle-face);
  background-size: 100% 100%;
  background-repeat: no-repeat;
}
.plate--deckle > picture { position: relative; z-index: 1; }

/* Portrait plates — Fig 1.3. The sheet in its drawn orientation, and a lighter
   mat: Fig 1.2 is roughly 620px wide at 1440 and Fig 1.3 about 187px, so the
   same absolute mat would eat a quarter of the small plate's width. */
.plate--deckle-tall {
  --deckle-face: var(--deckle-sheet);
  --deckle-mat: calc(var(--plate-pad) * 1.25);
}

/* The small torn tab the comp sets behind the Fig 1.3 caption. */
.fig__cap--tab {
  position: relative;
  display: inline-block;
  padding: 0.34em 0.9em 0.4em;
}
.fig__cap--tab::before {
  content: "";
  position: absolute;
  inset: -0.15em -0.35em -0.2em -0.35em;
  z-index: -1;
  background-image: var(--deckle-tab);
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

.fig { position: relative; }
.fig__cap {
  display: block; font-family: var(--f-hand); font-size: var(--fs-hand-s);
  color: var(--fg); line-height: 1.15; margin-top: 0.62em;
}
.fig__cap--over { margin: 0 0 0.5em; }

/* full-bleed photographic layers */
.bleed__media { position: absolute; inset: -14% 0; z-index: 0; will-change: transform; }
/* Scrim between the photograph and the copy, strength set per section. */
.section.is-dark::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: var(--scrim, linear-gradient(180deg, rgba(12, 18, 17, 0.5), rgba(12, 18, 17, 0.4) 45%, rgba(12, 18, 17, 0.62)));
}
.hero { --scrim: linear-gradient(180deg, rgba(12, 18, 17, 0.34), rgba(12, 18, 17, 0.18) 45%, rgba(12, 18, 17, 0.46)); }
.experience { --scrim: linear-gradient(180deg, rgba(12, 18, 17, 0.62), rgba(12, 18, 17, 0.52) 45%, rgba(12, 18, 17, 0.66)); }
.cta { --scrim: linear-gradient(180deg, rgba(12, 18, 17, 0.5), rgba(12, 18, 17, 0.4) 45%, rgba(12, 18, 17, 0.56)); }
.bleed__media picture, .bleed__media img { width: 100%; height: 100%; }
.bleed__media img { object-fit: cover; }

/* -------------------------------------------------------------- 1. hero */
.hero { min-height: 100svh; display: flex; align-items: flex-end; overflow: clip; }
/* Fixed to the bottom-left corner, mirroring the rail at the top. */
.brand--fixed {
  position: fixed;
  bottom: 2.6vw;
  left: 1.95%;
  z-index: 40;
}
.brand { display: inline-flex; flex-direction: column; align-items: center; gap: 0.3em; color: var(--fg); }
/* A masked box, not a coloured image, so the fill follows the section. The
   mask's transparent letters keep showing whatever is behind, as the comp does.
   The asset is the blue logo with alpha, so it doubles as the no-mask fallback:
   without mask support the logo still shows, it just cannot recolour — which is
   far better than the solid rectangle a bare background-color would leave. */
.brand__mark {
  width: clamp(42px, 3.9vw, 60px);
  aspect-ratio: 112 / 82;
  background-image: var(--logo-mask);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}
@supports (mask-image: url("")) or (-webkit-mask-image: url("")) {
  .brand__mark {
    background-image: none;
    background-color: var(--blue);
    -webkit-mask-image: var(--logo-mask);
    mask-image: var(--logo-mask);
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    transition: background-color 0.5s var(--ease);
  }
}
.brand__word {
  font-family: var(--f-display); font-weight: 450; font-size: var(--fs-nav);
  letter-spacing: 0.01em; line-height: 1;
  transition: color 0.5s var(--ease);
}

/* ------------------------------------------------------- 2. philosophy */
.philosophy__inner { padding-block: 2.9vw 3.4vw; }
.philosophy__head { margin-left: 34.54%; }
.philosophy h1 { font-size: var(--fs-display-m); margin-top: 0.55em; }
.philosophy__lede { margin: 3.4vw 0 0 51.57%; max-width: 56ch; }
.philosophy__plates { margin-top: 3.8vw; }
.philosophy__plates > *:first-child { grid-column: 35 / span 13; }
.philosophy__plate-large { grid-column: 52 / span 43; }
.philosophy__plate-small { width: 88%; }
.philosophy__note { margin-top: 1.4vw; max-width: 21ch; }
.philosophy__quote {
  font-family: var(--f-hand); font-size: var(--fs-hand-m); color: var(--ink);
  line-height: 1.45; text-align: center; margin: 3.6vw 0 0 49.9%; width: 27.91%;
}

/* ------------------------------------------------------- 3. experience */
/* align-items: stretch, and no block padding, so the inner grid is the full
   height of the section — otherwise the row is only as tall as its content and
   the rule stops short of the edges. */
.experience {
  min-height: 100svh;
  display: flex;
  align-items: stretch;
  overflow: clip;
}
.experience__inner { display: grid; grid-template-columns: 18.5% 36% 45.5%; }
/* The comp sets the heading around the middle of the section. */
.experience__head { grid-column: 2; align-self: center; padding-right: 4%; padding-top: 6vw; }
.experience h2 { font-size: var(--fs-display-m); margin-top: 0.9em; }

/* All seven movements are shown at once, spread down the section with the rule
   running its full height, as the comp draws it. The active one brightens and
   reveals its caption; that highlight auto-advances, but nothing translates. */
.stepper {
  grid-column: 3;
  position: relative;
  border-left: 1px solid rgba(221, 219, 220, 0.4);
  padding-left: 4.4%;
  align-self: stretch;
}
/* The seven are centred in that full height, which lands them at the comp's
   inset from the top and bottom edges. A grid, not a row flex: as a flex item the
   track shrank to its own content width, and every caption's percentage left and
   max-width then resolved against that instead of the column. */
.stepper__viewport {
  position: relative;
  height: 100%;
  display: grid;
  align-content: center;
}
.stepper__track { width: 100%; }
.step {
  position: relative;
  display: flex; gap: 1.1em; align-items: baseline;
  /* The comp's spacing is 6.56vw, which fills the column almost edge to edge.
     Slightly tighter, so the centred track leaves clear air above the first
     movement and below the last while the rule still runs the full height. */
  height: 5.5vw; min-height: 62px;
  font-family: var(--f-display); font-weight: 450; font-size: var(--fs-lead);
  line-height: 1.2; color: var(--paper);
  opacity: 0.4; transition: opacity 0.7s var(--ease);
}
.step__num { flex: 0 0 auto; min-width: 2.6em; }
.step.is-active { opacity: 1; }
/* Beside its own step, as the comp places the Nourish note. */
.step__caption {
  position: absolute; left: 38.5%; top: -0.15em;
  width: 38ch; max-width: 46%;
  font-family: var(--f-sharp); font-size: var(--fs-body); line-height: 1.62;
  letter-spacing: 0.01em; opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity 0.6s var(--ease);
}
.step.is-active .step__caption { opacity: 1; visibility: visible; }
.step__caption b {
  display: block; width: fit-content; font-weight: 400;
  text-transform: uppercase; letter-spacing: 0.09em;
  border-bottom: 1px solid currentColor; margin-bottom: 0.45em;
}
.stepper__meta {
  position: absolute; right: 2%; top: 50%; transform: translateY(-50%);
  text-align: right;
  display: flex; flex-direction: column; align-items: flex-end; gap: 0.9em;
}
.stepper__count {
  font-family: var(--f-display); font-weight: 500; font-size: var(--fs-nav);
  letter-spacing: 0.06em; color: var(--paper);
}
/* Auto-updating content still needs a stop control (WCAG 2.2.2), so it stays in
   the DOM and keyboard-reachable — just out of the composition until focused.
   Hovering or focusing the stepper also pauses it. */
.stepper__pause {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  background: none; border: 0; cursor: pointer; color: var(--paper);
  font-family: var(--f-mono); font-size: var(--fs-micro); letter-spacing: 0.08em;
}
.stepper__pause:focus-visible {
  position: static; width: auto; height: auto; margin: 0; padding: 0.35em;
  overflow: visible; clip-path: none;
}

/* ------------------------------------------------------- 4. gatherings */
.gatherings { padding-block: 5.2vw 6.4vw; overflow: clip; }
.gatherings h2 {
  margin-left: 26.45%; font-size: var(--fs-display-xl);
  line-height: 0.98; letter-spacing: -0.028em;
}
.gatherings__intro { margin: 1.6vw 0 0 50.66%; font-size: var(--fs-display-m); }
.gatherings__cards { margin-top: 2.2vw; }
.gatherings__cards .card:nth-child(1) { grid-column: 26 / span 20; }
.gatherings__cards .card:nth-child(2) { grid-column: 50 / span 20; margin-top: 10.6vw; }
.gatherings__cards .card:nth-child(3) { grid-column: 74 / span 20; margin-top: 3.1vw; }
.card__body { display: grid; grid-template-columns: 2.5em 1fr; margin-top: 1.5vw; }
.card__num { font-family: var(--f-mono); font-size: var(--fs-body); padding-top: 0.4em; }
.card__title { font-family: var(--f-display); font-weight: 450; font-size: var(--fs-lead); line-height: 1.16; }
.card__meta { font-family: var(--f-mono); font-size: var(--fs-body); margin-top: 0.3em; }
.card__list { margin-top: 1.3vw; max-width: 30ch; }
/* On the cards the first line is the lead, so bullets start from the second.
   Where the list is only bullets (the inner gathering page), every item gets one. */
.card__list li + li::before { content: "· "; }
.card__list--all li::before { content: "· "; }
.card__more {
  display: inline-block; margin-top: 1.8vw; padding: 0.6em 1.1em 0.52em;
  border: 1px solid rgba(221, 219, 220, 0.45);
  font-family: var(--f-mono); font-size: var(--fs-body);
  letter-spacing: 0.07em; text-transform: uppercase; color: #fff;
  transition: background 0.35s var(--ease), border-color 0.35s var(--ease);
}
.card__more:hover, .card__more:focus-visible { background: rgba(221, 219, 220, 0.14); border-color: var(--paper); }

/* --------------------------------------------------------- 5. approach */
.approach__inner { padding-block: 4.4vw 3vw; }
.approach__col { grid-column: 19 / span 40; }
.approach__aside { grid-column: 59 / span 39; }
.approach__list {
  margin-top: 1.4vw; font-family: var(--f-display); font-weight: 300;
  font-size: var(--fs-display-l); line-height: 1.19;
  letter-spacing: -0.014em; color: var(--ink);
}
.approach__list li { margin-left: calc(var(--i, 0) * 1vw); }
.approach__link {
  display: inline-block; color: inherit;
  transition: color 0.35s var(--ease), opacity 0.35s var(--ease);
}
/* The arrow marks the live topic: it follows the pointer and settles on the
   pinned topic once the pointer leaves the list. */
.approach__arrow {
  display: inline-block; margin-left: 0.42em;
  opacity: 0; transform: translateX(-0.22em);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}
.approach__link[aria-current="true"] .approach__arrow {
  opacity: 1; transform: none;
}
/* While the pointer is over the list, every arrow is suppressed and only the
   hovered item shows one; the same for keyboard focus. Written as suppress-all
   then re-show-one so the winning rule is always the more specific of the pair —
   the previous version had the hide rule at (0,5,0) beating the show rule at
   (0,4,0), which hid the pinned item's own arrow when you hovered it.
   :focus-visible, not :focus-within: a mouse click leaves :focus on the link, so
   :focus-within stayed true and the arrow disappeared until you clicked away. */
.approach__list:hover .approach__link .approach__arrow {
  opacity: 0; transform: translateX(-0.22em);
}
.approach__list:hover .approach__link:hover .approach__arrow {
  opacity: 1; transform: none;
}
.approach__list:has(.approach__link:focus-visible) .approach__link .approach__arrow {
  opacity: 0; transform: translateX(-0.22em);
}
.approach__list:has(.approach__link:focus-visible) .approach__link:focus-visible .approach__arrow {
  opacity: 1; transform: none;
}
/* The comp leaves every topic the same grey and lets the arrow alone mark the
   one in play, so the pinned label is not recoloured or the others dimmed. Only
   hover turns a topic blue, and its arrow with it. */
.approach__link:hover,
.approach__link:focus-visible { color: var(--blue); }

/* Panels share one grid cell, so swapping never shifts the layout. */
.approach__panels, .approach__details { display: grid; }
.approach__panel, .approach__detail-panel {
  grid-area: 1 / 1;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity 0.55s var(--ease);
}
.approach__panel.is-active, .approach__detail-panel.is-active {
  opacity: 1; visibility: visible; pointer-events: auto;
}
.approach__panel .plate img {
  aspect-ratio: 557 / 503;   /* the comp's cyanotype slot */
  object-fit: cover;
}
.approach__detail-panel .plate img {
  aspect-ratio: 95 / 100;    /* the comp's small dish slot */
  object-fit: cover;
}
.approach__note {
  font-family: var(--f-hand); font-size: var(--fs-hand-s); color: var(--ink-hand);
  line-height: 1.45; margin-top: 1.9vw; max-width: 34ch;
}
/* Its own row, so it begins where the taller of the two columns above ends.
   The gap is small enough that it still shares a screen with the list, which it
   must — it changes on hover. */
.approach__detail { grid-column: 19 / span 40; margin-top: 1.8vw; }
/* Every panel is a grid, not just the active one: as a block the thumbnail
   stretches to the full column width and inflates the shared cell. */
.approach__detail-panel {
  display: grid;
  grid-template-columns: 16.5% 1fr; column-gap: 4%; align-items: start;
}
.approach__detail-title {
  font-family: var(--f-display); font-weight: 450; font-size: var(--fs-lead);
  color: var(--ink); margin-bottom: 0.55em;
}
.approach__detail-panel p { max-width: 35ch; }

/* -------------------------------------------------------------- 6. cta */
.cta { min-height: 100svh; display: grid; align-content: center; overflow: clip; text-align: center; }
.cta h2 {
  font-family: var(--f-display); font-weight: 450; font-size: var(--fs-lead);
  line-height: 1.35; max-width: 56ch; margin: 0 auto; color: var(--paper);
}
.cta__rule { height: 1px; background: rgba(221, 219, 220, 0.42); margin: 3.2vw 0 2.4vw; }
.cta__btn {
  display: inline-block; padding: 0.68em 1.25em 0.6em;
  border: 1px solid rgba(255, 255, 255, 0.72);
  font-family: var(--f-mono); font-size: var(--fs-body);
  letter-spacing: 0.08em; text-transform: uppercase; color: #fff;
  transition: background 0.35s var(--ease);
}
.cta__btn:hover, .cta__btn:focus-visible { background: rgba(255, 255, 255, 0.16); }

/* ---------------------------------------------------------- 7. stories */
.stories__inner { padding-block: 4.5vw 2vw; }
.stories__copy { grid-column: 19 / span 24; grid-row: 1; }
.stories__copy p { margin-top: 1.5vw; max-width: 35ch; }
.stories__grid { grid-column: 1 / -1; grid-row: 1; }
/* scattered plates, transcribed from the comp */
/* All six share row 1 so each margin-top is an absolute offset from one
   baseline, as the comp measures them. Without the explicit row, auto-placement
   pushes the overlapping columns onto a second row and the offsets compound. */
.stories__grid .fig { grid-row: 1; }
.stories__grid .fig:nth-child(1) { grid-column: 45 / span 13; }
.stories__grid .fig:nth-child(2) { grid-column: 61 / span 12; }
.stories__grid .fig:nth-child(3) { grid-column: 88 / span 10; margin-top: 0.8vw; }
.stories__grid .fig:nth-child(4) { grid-column: 66 / span 7; margin-top: 20.9vw; }
.stories__grid .fig:nth-child(5) { grid-column: 79 / span 18; margin-top: 21.1vw; }
.stories__grid .fig:nth-child(6) { grid-column: 45 / span 10; margin-top: 31.2vw; }
.stories__grid a { display: block; transition: opacity 0.35s var(--ease); }
.stories__grid a:hover, .stories__grid a:focus-visible { opacity: 0.78; }

/* ---------------------------------------------------- 8. contact/footer */
.contact__inner { padding-block: 3vw 3.4vw; }
.contact__head { grid-column: 35 / span 49; }
.contact__display { font-size: var(--fs-display-l); margin-top: 1.1vw; }
/* The comp bottom-aligns this column with the form: the plate sits low and the
   footer block runs level with the submit button, rather than the column hanging
   from the top of the row with a gap beneath it. */
.contact__aside { grid-column: 19 / span 22; align-self: end; }
.contact__plate { width: 72%; }
.contact__form { grid-column: 51 / span 32; margin-top: 3vw; }
.field {
  position: relative; border-bottom: 1px solid rgba(106, 108, 108, 0.5);
  padding-block: 0.8em 0.5em; margin-bottom: 1.9vw;
}
.field label { display: block; font-family: var(--f-mono); font-size: var(--fs-body); color: var(--ink); line-height: 1.4; }
.field abbr { text-decoration: none; }
.field input, .field select {
  width: 100%; border: 0; background: none; padding: 0; margin-top: 0.3em; appearance: none;
}
.field--select::after {
  content: "↓"; position: absolute; right: 0.2em; bottom: 0.5em;
  font-family: var(--f-display); font-size: calc(var(--fs-body) * 1.35);
  color: var(--ink); pointer-events: none;
}
.field--area { border-bottom: 0; padding-bottom: 0; }
.field--area textarea {
  width: 100%; min-height: 9vw; margin-top: 0.65em; padding: 0.7em;
  background: none; border: 1px solid rgba(106, 108, 108, 0.5); resize: vertical;
}
.form__submit {
  width: 100%; margin-top: 1.6vw; padding: 1.05em; border: 0;
  background: #6f7271; color: var(--paper);
  font-family: var(--f-mono); font-size: var(--fs-body);
  letter-spacing: 0.12em; text-transform: uppercase; cursor: pointer;
  transition: background 0.35s var(--ease);
}
.form__submit:hover { background: #5d605f; }

/* Validation ---------------------------------------------------------------
   The form carries `novalidate`, so these states are the only feedback there
   is — written by the server on the way back, and by tffm.js as you type. Both
   put the same string in the same slot, so they look identical either way. */
.form__status {
  margin: 0 0 1.4vw; font-family: var(--f-mono); font-size: var(--fs-micro);
  letter-spacing: 0.04em; line-height: 1.5;
}
/* Zeroing the margin rather than hiding it: an empty block has no height
   anyway, and a live region that is display:none is not reliably announced
   when JavaScript later writes into it. */
.form__status:empty { margin: 0; }
.form__status.is-sent { color: var(--blue); }
.form__status.is-error { color: #8a4a4a; }

.field__error {
  display: block; margin-top: 0.4em;
  font-family: var(--f-mono); font-size: var(--fs-micro);
  letter-spacing: 0.04em; line-height: 1.4; color: #8a4a4a;
}
.field__error:empty { display: none; }
.field.is-invalid { border-bottom-color: #8a4a4a; }
.field--area.is-invalid textarea { border-color: #8a4a4a; }

.form__submit:disabled { opacity: 0.55; cursor: default; }
.form__submit:disabled:hover { background: #6f7271; }
/* Focus ------------------------------------------------------------------
   The global ring is a 2px box with a 3px offset — right for links and
   buttons, wrong on a form drawn entirely as underlines, where it reads as a
   stray blue rectangle floating around the field. These controls show focus on
   the rule the design already draws, so the indicator is moved, never removed:
   :focus-within covers pointer and keyboard alike, and a keyboard focus also
   doubles the rule to 2px via a shadow, which costs no layout shift. */
.field input:focus,
.field select:focus,
.field textarea:focus,
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible { outline: none; }

.field:focus-within { border-bottom-color: var(--ink); }
.field:has(input:focus-visible),
.field:has(select:focus-visible) { box-shadow: 0 1px 0 0 var(--ink); }

.field--area:focus-within textarea { border-color: var(--ink); }
.field--area:has(textarea:focus-visible) textarea { box-shadow: 0 0 0 1px var(--ink); }

/* An invalid field keeps saying so while it is being corrected; the message
   below it is what changes when the value becomes valid. */
.field.is-invalid:focus-within { border-bottom-color: #8a4a4a; }
.field--area.is-invalid:focus-within textarea { border-color: #8a4a4a; }

.footer { margin-top: 2.4vw; }
.footer__brand {
  font-family: var(--f-display); font-weight: 500; font-size: var(--fs-micro);
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--blue);
}
.footer__block { margin-top: 0.6em; }
.footer .brand { display: none; }
/* .footer is t-micro (uppercase); the wordmark is set sentence case in the comp. */
.footer .brand__word { text-transform: none; letter-spacing: 0.01em; }

/* -------------------------------------------------------------- motion */
/* Scroll-triggered entrance motion. Blocks cascade: a [data-seq] container
 * staggers its [data-anim] descendants in document order when it enters, so a
 * kicker, heading, body and plates arrive one after another rather than each
 * firing on its own threshold.
 *
 * The vocabulary matches the meso reference (masked line rises, staggered
 * groups, replay on scroll-back) with editorial reveals added for imagery —
 * a clip wipe with a settling scale, rather than animate.css's bounce presets,
 * which would fight this design.
 *
 * Every hidden state is scoped to .has-anim, set by an inline head script, so
 * with JavaScript off nothing is ever invisible.
 */
:root {
  /* expo-out: fast departure, long settle — reads as designed rather than mechanical */
  --ease-reveal: cubic-bezier(0.16, 1, 0.3, 1);
  /* --d is an authored group offset, --ds a JS-written cascade offset; delays
     are the sum, so neither overrides the other. */
  --anim-dur: 1.05s;
  --anim-dur-slow: 1.35s;
}

.has-anim [data-anim] {
  transition-delay: calc(var(--d, 0ms) + var(--ds, 0ms));
  will-change: opacity, transform;
}
.has-anim [data-anim].is-in { will-change: auto; }

/* ---- masked line rise: the child clips, the grandchild travels ---- */
.has-anim [data-anim="lines"] > * {
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.has-anim [data-anim="lines"] > * > * {
  display: block;
  transform: translateY(115%);
  transition: transform var(--anim-dur) var(--ease-reveal);
  transition-delay: calc(var(--d, 0ms) + var(--ds, 0ms));
}
.has-anim [data-anim="lines"].is-in > * > * { transform: none; }

/* ---- word-by-word rise: each word masked, like the reference's wrap-word.
   Used once, on the CTA headline. Applying it across the display type would
   fragment the serif lines the comp is built on. ---- */
.has-anim [data-anim="words"] .w {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
.has-anim [data-anim="words"] .w__in {
  display: inline-block;
  transform: translateY(110%);
  transition: transform var(--anim-dur) var(--ease-reveal);
  transition-delay: calc(var(--d, 0ms) + var(--ds, 0ms));
}
.has-anim [data-anim="words"].is-in .w__in { transform: none; }

/* ---- fade and rise ---- */
.has-anim [data-anim="rise"],
.has-anim [data-anim="stagger"] > *,
.has-anim .reveal {
  opacity: 0;
  transform: translate3d(0, 46px, 0);
  transition: opacity var(--anim-dur) var(--ease-reveal),
    transform var(--anim-dur) var(--ease-reveal);
  transition-delay: calc(var(--d, 0ms) + var(--ds, 0ms));
}
.has-anim [data-anim="rise"].is-in,
.has-anim [data-anim="stagger"].is-in > *,
.has-anim .reveal.is-in { opacity: 1; transform: none; }

/* ---- plain fade, for text that should not move ---- */
.has-anim [data-anim="fade"] {
  opacity: 0;
  transition: opacity var(--anim-dur-slow) var(--ease-reveal);
}
.has-anim [data-anim="fade"].is-in { opacity: 1; }

/* ---- directional, for asides and pull-quotes ---- */
.has-anim [data-anim="left"],
.has-anim [data-anim="right"] {
  opacity: 0;
  transition: opacity var(--anim-dur) var(--ease-reveal),
    transform var(--anim-dur) var(--ease-reveal);
  transition-delay: calc(var(--d, 0ms) + var(--ds, 0ms));
}
.has-anim [data-anim="left"] { transform: translate3d(-62px, 0, 0); }
.has-anim [data-anim="right"] { transform: translate3d(62px, 0, 0); }
.has-anim [data-anim="left"].is-in,
.has-anim [data-anim="right"].is-in { opacity: 1; transform: none; }

/* ---- clip wipe with a settling scale: the photographic reveal ----
   The frame wipes open while the picture inside eases back to rest. Two
   elements moving at different rates is what gives it depth. */
.has-anim [data-anim="clip"] {
  clip-path: inset(0 0 100% 0);
  transition: clip-path var(--anim-dur-slow) var(--ease-reveal);
  transition-delay: calc(var(--d, 0ms) + var(--ds, 0ms));
}
.has-anim [data-anim="clip"].is-in { clip-path: inset(0 0 0 0); }
/* The picture box clips the scale, so the photograph never bleeds past its
   cream mat or the torn paper edge while it settles. */
.has-anim [data-anim="clip"] picture { overflow: hidden; }
.has-anim [data-anim="clip"] img {
  transform: scale(1.12);
  transition: transform 1.7s var(--ease-reveal);
  transition-delay: calc(var(--d, 0ms) + var(--ds, 0ms));
}
.has-anim [data-anim="clip"].is-in img { transform: none; }

/* ---- zoom: the plate scales up into place ----
   animate.css's zoomIn starts at scale(.3), which is far too violent next to
   Bradford Light. 0.88 reads as the same gesture at this scale of type. */
.has-anim [data-anim="zoom"] {
  opacity: 0;
  transform: scale(0.84);
  transform-origin: center center;
  transition: opacity var(--anim-dur) var(--ease-reveal),
    transform var(--anim-dur-slow) var(--ease-reveal);
  transition-delay: calc(var(--d, 0ms) + var(--ds, 0ms));
}
.has-anim [data-anim="zoom"].is-in { opacity: 1; transform: none; }

/* ---- settle: a quiet scale-down, for single plates ---- */
.has-anim [data-anim="settle"] {
  opacity: 0;
  transform: scale(1.07);
  transition: opacity var(--anim-dur) var(--ease-reveal),
    transform var(--anim-dur-slow) var(--ease-reveal);
  transition-delay: calc(var(--d, 0ms) + var(--ds, 0ms));
}
.has-anim [data-anim="settle"].is-in { opacity: 1; transform: none; }

/* ---- a rule that draws itself ---- */
.has-anim [data-anim="rule"] {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--anim-dur-slow) var(--ease-reveal);
  transition-delay: calc(var(--d, 0ms) + var(--ds, 0ms));
}
.has-anim [data-anim="rule"].is-in { transform: none; }

/* Plates that are separate observers rather than one staggered container —
   they sit at different heights, so they keep their own trigger and only take
   a small offset from each other. */
.has-anim .gatherings__cards .card:nth-child(2) { --d: 130ms; }
.has-anim .gatherings__cards .card:nth-child(3) { --d: 260ms; }
.has-anim .stories__grid .fig:nth-child(2) { --d: 60ms; }
.has-anim .stories__grid .fig:nth-child(3) { --d: 120ms; }
.has-anim .stories__grid .fig:nth-child(4) { --d: 180ms; }
.has-anim .stories__grid .fig:nth-child(5) { --d: 240ms; }
.has-anim .stories__grid .fig:nth-child(6) { --d: 300ms; }
.has-anim .entry-grid .fig:nth-child(4n + 2) { --d: 90ms; }
.has-anim .entry-grid .fig:nth-child(4n + 3) { --d: 180ms; }
.has-anim .entry-grid .fig:nth-child(4n + 4) { --d: 270ms; }

/* --------------------------------------------------- inner page furniture */
/* The rail may extend past this hero onto the paper below; each rail item takes
   its colour from the section behind it, so that reads correctly. The floor is
   only here to stop the hero collapsing on a short viewport. */
.page-hero {
  min-height: max(52svh, 22rem);
  display: flex; align-items: flex-end;
  overflow: clip; padding-block: 6vw 3vw;
}
.page-hero__inner { margin-left: 26.45%; }
.page-hero h1 { font-size: var(--fs-display-xl); line-height: 0.98; letter-spacing: -0.028em; }
.page-body { padding-block: 4vw 6vw; }
.page-body__copy { grid-column: 27 / span 40; }
.page-body__copy p + p { margin-top: 1.2em; }
.page-body__meta { grid-column: 70 / span 24; }
.page-body__meta dt {
  font-family: var(--f-display); font-weight: 500; font-size: var(--fs-nav);
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--blue);
}
.page-body__meta dd { margin: 0.4em 0 1.4em; }
.page-back { display: inline-block; margin-top: 2.4vw; border-bottom: 1px solid currentColor; }

/* A hero with no photograph sits on paper and only needs to clear the rail. */
/* Featured images are whatever the editor uploads, so this scrim has to hold
   light photographs as well as dark ones. */
.page-hero.is-dark {
  --scrim: linear-gradient(180deg, rgba(12, 18, 17, 0.66), rgba(12, 18, 17, 0.5) 45%, rgba(12, 18, 17, 0.72));
}
.page-hero.is-plain { min-height: 0; padding-block: 7vw 1vw; }
.page-hero__meta { margin-top: 1em; opacity: 0.8; }

/* WordPress-authored content: the editor can emit anything, so give the common
   elements a home rather than leaving them unstyled. */
.prose > * + * { margin-top: 1.1em; }
.prose h2, .prose h3, .prose h4 {
  font-family: var(--f-display); font-weight: 450; line-height: 1.2;
  margin-top: 2em; color: var(--ink);
}
.prose h2 { font-size: var(--fs-display-m); }
.prose h3 { font-size: var(--fs-lead); }
.prose h4 { font-size: calc(var(--fs-body) * 1.25); }
.prose a { border-bottom: 1px solid currentColor; }
.prose ul, .prose ol { padding-left: 1.4em; }
.prose ul li { list-style: none; }
.prose ul li::before { content: "· "; margin-left: -1.1em; }
.prose ol { list-style: decimal; }
.prose ol li { list-style: decimal; }
.prose blockquote {
  font-family: var(--f-hand); font-size: var(--fs-hand-m);
  line-height: 1.45; margin-block: 1.6em; color: var(--ink-hand);
}
.prose img, .prose figure { margin-block: 1.6em; }
.prose figcaption {
  font-family: var(--f-hand); font-size: var(--fs-hand-s); margin-top: 0.6em;
}
.prose code, .prose pre { font-family: var(--f-mono); font-size: 0.95em; }
.prose pre { overflow-x: auto; padding: 1em; background: rgba(106,108,108,0.08); }
.prose table { width: 100%; border-collapse: collapse; }
.prose th, .prose td {
  text-align: left; padding: 0.6em 0.8em 0.6em 0;
  border-bottom: 1px solid rgba(106,108,108,0.3);
}
.prose hr { border: 0; border-top: 1px solid rgba(106,108,108,0.3); margin-block: 2em; }

/* Listing grid — archives, blog index, search. */
.entry-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 3.4vw 2.6%; margin-left: 18.28%;
}
.entry-grid .fig a { display: block; transition: opacity 0.35s var(--ease); }
.entry-grid .fig a:hover, .entry-grid .fig a:focus-visible { opacity: 0.78; }
.entry-grid .plate img { aspect-ratio: 182 / 275; object-fit: cover; }
.entry-empty { margin-left: 18.28%; }
.pager { margin: 3vw 0 2vw 18.28%; display: flex; gap: 1.2em; flex-wrap: wrap; }
.pager .page-numbers { border-bottom: 1px solid transparent; }
.pager .page-numbers.current { border-bottom-color: currentColor; color: var(--blue); }
.pager a:hover { border-bottom-color: currentColor; }

/* ------------------------------------------------------------ responsive */
@media (max-width: 1100px) {
  :root {
    --rail-w: 100%;
    --fs-body: clamp(13.5px, 1.55vw, 15.5px);
    --fs-nav: clamp(12px, 1.4vw, 14px);
    --fs-display-m: clamp(21px, 3.1vw, 30px);
    --fs-display-l: clamp(22px, 3.3vw, 32px);
    --fs-display-xl: clamp(38px, 7.4vw, 64px);
  }
  .rail {
    position: sticky; width: 100%; min-width: 0; padding: 0;
    background: var(--paper); border-bottom: 1px solid rgba(106, 108, 108, 0.22);
  }
  .rail.on-dark { background: var(--dark); border-color: rgba(221, 219, 220, 0.2); }
  /* The fixed corner mark would sit over the content on a narrow screen, so it
     steps aside and the footer's own copy is shown instead. */
  .brand--fixed { display: none; }
  .footer .brand { display: inline-flex; margin-top: 2em; color: var(--blue); }
  .rail__toggle {
    display: flex; align-items: center; justify-content: space-between; width: 100%;
    padding: 1em 5.5%; background: none; border: 0;
    font-family: var(--f-mono); font-size: var(--fs-nav);
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--rail-fg, var(--ink-nav)); cursor: pointer; pointer-events: auto;
  }
  .rail__nav { display: none; padding: 0 5.5% 1.5em; max-height: 68svh; overflow-y: auto; }
  .rail[data-open="true"] .rail__nav { display: block; }

  /* the comp's offsets drop away; everything becomes one column */
  .grid100 { display: block; }
  .section__inner { padding-inline: 5.5%; }
  .philosophy__head, .philosophy__lede, .philosophy__quote,
  .gatherings h2, .gatherings__intro, .contact__head, .contact__display,
  .page-hero__inner {
    margin-left: 0; width: auto;
  }
  .philosophy__quote { text-align: left; }
  .philosophy__plates > *, .gatherings__cards .card, .approach__col, .approach__aside,
  .approach__detail, .stories__copy, .stories__grid, .stories__grid .fig,
  .contact__aside, .contact__form, .page-body__copy, .page-body__meta {
    margin-top: 0; margin-left: 0; width: auto;
  }
  .philosophy__plate-small { width: 56%; }
  .philosophy__plates > * + * { margin-top: 2.5em; }
  .experience__inner { display: block; }
  .experience__head { padding-right: 0; }
  .stepper { margin-top: 2.5em; padding-left: 5%; }
  /* the slider unrolls into a plain list on small screens */
  .stepper__viewport { height: auto; max-height: none; min-height: 0; overflow: visible; mask-image: none; }
  .stepper__track { margin-top: 0 !important; }
  .step { height: auto; min-height: 0; display: block; margin-bottom: 1.6em; opacity: 1; }
  .step__num { margin-right: 0.6em; }
  .step__caption {
    position: static; transform: none; width: auto; max-width: none;
    opacity: 1; visibility: visible; margin-top: 0.7em;
  }
  .stepper__meta { display: none; }
  .gatherings__cards .card + .card { margin-top: 3.5em; }
  .stories__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.6em 4%; margin-top: 2.5em; }
  .entry-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-left: 0; gap: 2em 4%; }
  .entry-empty, .pager { margin-left: 0; }
  .page-hero.is-plain { padding-block: 2.5em 0; }
  /* release the desktop single-row placement so the plates flow. :nth-child(n)
     matches the specificity of the desktop rules it has to override. */
  .stories__grid .fig:nth-child(n) {
    grid-row: auto; grid-column: auto; margin-top: 0; width: auto;
  }
  /* the approach index shows every panel in sequence rather than swapping */
  .approach__panels, .approach__details { display: block; }
  .approach__panel, .approach__detail-panel {
    opacity: 1; visibility: visible; pointer-events: auto;
  }
  .approach__panel:not(.is-active), .approach__detail-panel:not(.is-active) { display: none; }
  .approach__detail-panel.is-active { display: block; }
  .approach__aside, .contact__aside, .contact__form, .page-body__meta { margin-top: 2.6em; }
  .field--area textarea { min-height: 8em; }
  .t-display .l, .approach__list li { margin-left: 0; }
  .t-display .l--right { text-align: left; }
  .cta__rule { margin: 2em 0 1.6em; }
}

@media (max-width: 640px) {
  .stories__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .philosophy__plate-small { width: 72%; }
  .card__body { grid-template-columns: 2.2em 1fr; }
}

/* ------------------------------------------------------- reduced motion */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .bleed__media { inset: 0; transform: none !important; }
  .reveal,
  [data-anim],
  [data-anim="stagger"] > *,
  [data-anim="lines"] > * > *,
  [data-anim="words"] .w__in,
  [data-anim="clip"] img {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    clip-path: none !important;
    filter: none !important;
  }
  [data-anim="lines"] > * { overflow: visible; }
  .stepper__track { transition: none; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* --------------------------------------------------------------- print */
@media print {
  .rail, .cta__btn, .card__more, .form__submit, .stepper__meta { display: none; }
  .section.is-dark, .section.is-green { background: none; color: #000; }
  .bleed__media { display: none; }
  .stepper__viewport { height: auto; overflow: visible; mask-image: none; }
  .stepper__track { margin-top: 0 !important; }
  .step { height: auto; opacity: 1; }
  .approach__panel, .approach__detail-panel { opacity: 1; visibility: visible; }
}
