/* =========================================================================
   ORGO — landing page
   Desktop design: 1440x800. Layout guide: 12 columns, 10px margin, 4px gutter.
   One column = (100% − 2·10px − 11·4px) / 12  →  114.67px at 1440.
   ========================================================================= */

@font-face {
  font-family: "Geist";
  src: url("assets/fonts/Geist-Light.woff2") format("woff2"), url("assets/fonts/Geist-Light.otf") format("opentype");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist";
  src: url("assets/fonts/Geist-Regular.woff2") format("woff2"), url("assets/fonts/Geist-Regular.otf") format("opentype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --margin: 10px;
  --gutter: 4px;
  /* Column width. <main> is an inline-size container, so 100cqw is always
     the page width no matter how deeply an element is nested. */
  --col: calc((100cqw - 64px) / 12);
  /* Column width relative to the viewport (for the fixed navbar). */
  --vcol: calc((100vw - 64px) / 12);

  --bg: #fbfbfb;
  --bg-alt: #ebebeb;
  --ink: #101111;
  --ink-60: rgba(16, 17, 17, 0.6);
  --ink-25: rgba(16, 17, 17, 0.25);
  --ink-15: rgba(16, 17, 17, 0.15);
  --ink-05: rgba(16, 17, 17, 0.05);
  --count: rgba(0, 0, 0, 0.4);
  --placeholder: rgba(0, 0, 0, 0.2);

  /* Where the contact heading pins while scrolling: below the fixed navbar + 20px. */
  --contact-sticky-top: 165px;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

/* Lenis smooth scroll (see script.js) */
html.lenis,
html.lenis body {
  height: auto;
}

html.lenis.lenis-smooth {
  scroll-behavior: auto;
}

.lenis:not(.lenis-autoToggle).lenis-stopped {
  overflow: clip;
}

.lenis [data-lenis-prevent] {
  overscroll-behavior: contain;
}

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

html,
body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Geist", system-ui, sans-serif;
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

main {
  container-type: inline-size;
}

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

ul {
  list-style: none;
}

img {
  display: block;
}

button,
input,
textarea {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  border-radius: 0;
}

/* No blue tap flash on touch devices; rows and controls aren't selectable */
a,
button,
.service,
.card__more,
.nav__toggle {
  -webkit-tap-highlight-color: transparent;
}

.service,
.card__more,
.nav__toggle {
  -webkit-user-select: none;
  user-select: none;
}

/* Figma "text-box-trim: trim-both / cap → alphabetic" */
.trim {
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---------- Media block: image + noise texture ----------
   Every photo on the page gets the same grain: 432x288 tile at 10%.
   The noise only renders once an <img> with a src is present, so the
   grey placeholders stay flat until real images are added. */
.media {
  position: relative;
  overflow: hidden;
  background: var(--bg-alt);
  isolation: isolate; /* keep the overlay z-indices inside the block */
}

.media > img,
.media > video,
.media__frame img,
.media__frame video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.media > img:not([src]),
.media > img[src=""],
.media > video:not([src]) {
  display: none;
}

/* Optional frame: holds the reveal zoom so the photo itself can carry the
   parallax transform (the two must not share one transform). */
.media__frame {
  position: absolute;
  inset: 0;
}

/* Parallax photos are oversized so the drift never reveals an edge */
[data-parallax] .media__frame img,
[data-parallax] .media__frame video {
  top: -8%;
  height: 116%;
  will-change: transform;
}

/* Black-and-white variant (services with data-mono) */
.media.is-mono > img,
.media.is-mono > video {
  filter: grayscale(1);
}

.media__noise {
  position: absolute;
  inset: 0;
  background: url("assets/img/noise.png") top left / 432px 288px repeat;
  opacity: 0.1;
  pointer-events: none;
}

.media:not(:has(img[src]:not([src=""]), video[src], video source)) > .media__noise {
  display: none;
}

/* ---------- "View details [+]" / "Read more [+]" ---------- */
.more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 14px;
  font-weight: 400;
  white-space: nowrap;
  color: var(--ink);
}

.more__label {
  font-size: 12px;
  line-height: 1;
  letter-spacing: -0.18px;
}

.more__icon {
  font-size: 10px;
  line-height: 1;
  letter-spacing: -0.15px;
}

/* "[+]" becomes "[−]" on the row whose details are open: the plus turns
   a quarter turn and fades while the minus turns in. */
.more__toggle {
  display: inline-grid;
}

.more__toggle > span {
  grid-area: 1 / 1;
  display: inline-block;
  text-align: center;
  transform-origin: 50% 52%;
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.25s ease;
}

.more__minus {
  opacity: 0;
  transform: rotate(-90deg);
}

.service.is-open .more__plus {
  opacity: 0;
  transform: rotate(90deg);
}

.service.is-open .more__minus {
  opacity: 1;
  transform: none;
}

/* =========================================================================
   Navbar — fixed at (10, 10), 3 columns wide. JS pushes it up when the
   footer arrives so it reads as "sticky until the footer".
   ========================================================================= */
.nav {
  position: fixed;
  top: 10px;
  left: 10px;
  z-index: 20;
  width: calc(3 * var(--vcol) + 2 * var(--gutter));
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: 10px 10px 8px;
  background: var(--bg);
  border: 0.5px solid var(--ink-15);
  font-weight: 400;
  font-size: 12px;
  line-height: 1;
  letter-spacing: -0.18px;
  will-change: transform;
}

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

.nav__logo {
  display: block;
  /* one column minus the nav's own 10px padding so the brand sits on column 2 */
  width: calc(var(--vcol) - 10px);
  flex: 0 0 auto;
}

.nav__logo img {
  width: 24.762px;
  height: 26px;
}

.nav__brand {
  white-space: nowrap;
}

/* Menu toggle — phones only */
.nav__toggle {
  display: none;
  margin-left: auto;
  cursor: pointer;
}

.nav__links li {
  display: flex;
  align-items: center;
  padding: 2px 0;
  transition: background-color 0.2s ease;
}

/* Hover: the whole row turns grey and the text nudges right */
.nav__links li:has(.nav__link:hover),
.nav__links li:has(.nav__link:focus-visible) {
  background: var(--bg-alt);
}

.nav__link {
  display: flex;
  align-items: center;
  gap: var(--gutter);
  flex: 1;
  padding-left: 0;
  transition: padding-left 0.2s ease;
  outline: none;
}

.nav__link:hover,
.nav__link:focus-visible {
  padding-left: 3px;
}

.nav__num {
  width: calc(var(--vcol) - 10px);
  flex: 0 0 auto;
}

.nav__label {
  flex: 1;
}

.nav__time {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* =========================================================================
   Hero — 1440x1000, B&W photo, 20% black, noise, bottom gradient
   ========================================================================= */
.hero {
  position: relative;
  /* One viewport for the photo + heading, then 300px more so the
     description always starts below the fold (1100px at 1440x800). */
  height: calc(100vh + 300px);
  overflow: hidden;
  color: var(--bg);
}

.hero__bg {
  position: absolute;
  inset: 0;
  background: #444;
}

/* Photo fallback is B&W; the video plays in colour */
.hero__bg img {
  filter: grayscale(1);
}

/* lighter grain over the moving picture */
.hero__bg .media__noise {
  opacity: 0.05;
}

.hero__bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.1);
  z-index: 1;
}

.hero__bg .media__noise {
  z-index: 2;
}

.hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0) 50%);
  z-index: 3;
}

/* Text block: right-aligned 6-column box (columns 7–12) */
.hero__content {
  position: absolute;
  left: var(--margin);
  right: var(--margin);
  top: calc(100vh - 94px); /* 706px at 800 tall */
  z-index: 1;
  display: flex;
  justify-content: flex-end;
}

.hero__content--text {
  top: calc(100vh + 10px); /* 810px at 800 tall */
}

.hero__title {
  width: calc(6 * var(--col) + 5 * var(--gutter));
  font-weight: 300;
  font-size: 28px;
  line-height: 1.2;
}

.hero__title {
  /* the headline itself wraps at ~314px inside the 708px box */
  padding-right: calc(6 * var(--col) + 5 * var(--gutter) - 314px);
}

.hero__text {
  width: calc(6 * var(--col) + 5 * var(--gutter));
  font-size: 14px;
  line-height: 1.2;
  letter-spacing: -0.21px;
  text-align: justify;
}

.hero__text p {
  /* 4 columns, capped at the 1440 measure so the line length stays put */
  width: min(471px, calc(4 * var(--col) + 3 * var(--gutter)));
}

.hero__text p + p {
  margin-top: 1.2em;
}

/* =========================================================================
   Intro
   ========================================================================= */
.intro {
  display: flex;
  justify-content: center;
  padding: 200px var(--margin);
}

.intro__text {
  /* 6 columns, but capped at the 1440 width so the line breaks stay the
     same on bigger screens. */
  width: min(708px, calc(6 * var(--col) + 5 * var(--gutter)));
  font-size: 28px;
  line-height: 1;
  text-align: center;
}

/* =========================================================================
   Services — reuses the projects-sections list / hover-preview pattern
   ========================================================================= */
.services {
  position: relative;
  /* preview height (4 columns at 470:646) + 77.5px above and 76.5px below.
     Resolves to 800px at 1440 and grows with the columns, so the preview
     is never clipped on wider screens. */
  --preview-h: calc((4 * var(--col) + 3 * var(--gutter)) * 646 / 470);
  height: calc(154px + var(--preview-h));
  overflow: hidden;
}

.services__head {
  position: absolute;
  /* column 2, aligned with the service names below */
  left: calc(var(--margin) + var(--col) + var(--gutter));
  top: 76.5px;
  display: flex;
  align-items: flex-start;
  gap: 11px;
  z-index: 3;
  white-space: nowrap;
}

.services__title {
  order: 1;
  margin-top: 5.6px;
  font-weight: 300;
  font-size: 28px;
  line-height: 1;
}

.services__count {
  order: 2;
  font-size: 12px;
  line-height: 1;
  letter-spacing: -0.24px;
  color: var(--count);
}

/* Centered preview: columns 5–8, 470x646 at 1440 */
.services__preview {
  position: absolute;
  top: 77.5px;
  left: calc(var(--margin) + 4 * (var(--col) + var(--gutter)));
  width: calc(4 * var(--col) + 3 * var(--gutter));
  aspect-ratio: 470 / 646; /* 646px tall at 1440, scales with the columns */
  z-index: 2;
  pointer-events: none;
}

.services__list {
  position: absolute;
  left: var(--margin);
  right: var(--margin);
  /* the 186px list stays centred on the preview (307px at 1440) */
  top: calc(77.5px + var(--preview-h) / 2 - 93px);
  z-index: 1;
}

.service {
  display: flex;
  align-items: flex-start;
  gap: var(--gutter);
  width: 100%;
  text-align: left;
  cursor: pointer;
  padding: 24px 0;
  border-top: 0.5px solid var(--ink-15);
  color: var(--ink-25);
  transition: color 0.35s ease, border-color 0.35s ease;
}

.service .more {
  color: inherit;
}

.service__left {
  display: flex;
  align-items: center;
  gap: var(--gutter);
  width: calc(10 * var(--col) + 9 * var(--gutter));
  flex: 0 0 auto;
}

.service__num {
  width: var(--col);
  flex: 0 0 auto;
  font-size: 12px;
  line-height: 1;
  letter-spacing: -0.18px;
  text-transform: uppercase;
}

.service__name {
  font-size: 20px;
  line-height: 1;
  letter-spacing: -0.3px;
  white-space: nowrap;
}

.service__right {
  display: flex;
  flex: 1;
  min-width: 0;
}

/* One row is always active (full ink + solid rule); the rest are dimmed. */
.service.is-active {
  color: var(--ink);
  border-top-color: var(--ink);
}

.service:focus-visible {
  outline: 1.5px solid var(--ink);
  outline-offset: 4px;
}

/* Inline per-service media — only used on tablet/mobile (built in JS). */
.service__media {
  display: none;
}

/* =========================================================================
   Team
   ========================================================================= */
.team__head {
  display: flex;
  justify-content: center;
  padding: 200px var(--margin);
}

.team__title {
  width: 400px;
  font-weight: 300;
  font-size: 28px;
  line-height: 1;
  text-align: center;
}

.team__grid {
  display: flex;
  gap: var(--gutter);
  padding: 0 var(--margin) 200px;
}

.team__spacer,
.team__cards {
  flex: 1 1 0;
  min-width: 0;
}

.team__cards {
  display: flex;
  gap: var(--gutter);
}

.card {
  flex: 1 1 0;
  min-width: 0;
}

.card__image {
  aspect-ratio: 4 / 5; /* 352 x 440 at 1440 */
  width: 100%;
}

.card__info {
  margin-top: 20px;
  padding-right: 40px;
}

.card__name {
  font-weight: 300;
  font-size: 20px;
  line-height: 1;
  letter-spacing: -0.3px;
  white-space: nowrap;
}

.card__desc {
  margin-top: 10px;
  font-size: 14px;
  line-height: 1.2;
  letter-spacing: -0.21px;
  color: var(--ink-60);
  text-align: left;
}

.card .more {
  margin-top: 20px;
}

.card__more {
  cursor: pointer;
  transition: opacity 0.3s ease;
}

.card__more:hover {
  opacity: 0.5;
}

/* =========================================================================
   Team "Read more" modal — panel under the navbar, page blurred behind
   ========================================================================= */
.modal {
  position: fixed;
  inset: 0;
  z-index: 15; /* below the navbar (20), above everything else */
}

.modal[hidden] {
  display: none;
}

.modal__overlay {
  position: absolute;
  inset: 0;
  background: rgba(16, 17, 17, 0.05);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.modal__panel {
  position: absolute;
  left: 10px;
  top: var(--modal-top, 153px); /* navbar bottom + 10px, set by JS */
  bottom: 10px;
  width: calc(3 * var(--vcol) + 2 * var(--gutter)); /* same as the navbar */
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border: 0.5px solid var(--ink-15);
  opacity: 0;
  transform: translate3d(0, 12px, 0);
  transition: opacity 0.3s ease, transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  outline: none;
}

.modal.is-open .modal__overlay,
.modal.is-open .modal__panel {
  opacity: 1;
}

.modal.is-open .modal__panel {
  transform: none;
}

.modal__close {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1;
  padding: 6px 8px;
  height: auto;
  background: var(--bg);
  cursor: pointer;
}

.modal__close:focus-visible {
  outline: 1.5px solid var(--ink);
  outline-offset: 2px;
}

.modal__scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 10px;
}

/* 2px scrollbar. Chrome ignores ::-webkit-scrollbar once scrollbar-width is
   set, so the standard property is only applied where the WebKit pseudo
   element doesn't exist (Firefox). */
@supports not selector(::-webkit-scrollbar) {
  .modal__scroll {
    scrollbar-width: thin;
    scrollbar-color: rgba(16, 17, 17, 0.2) transparent;
  }
}

.modal__scroll::-webkit-scrollbar {
  width: 2px;
}

.modal__scroll::-webkit-scrollbar-track {
  background: transparent;
}

/* thumb only shows while scrolling (JS toggles .is-scrolling) */
.modal__scroll::-webkit-scrollbar-thumb {
  background: transparent;
  border-radius: 2px;
}

.modal__scroll.is-scrolling::-webkit-scrollbar-thumb {
  background: rgba(16, 17, 17, 0.2);
}

.modal__image {
  width: 100%;
  aspect-ratio: 4 / 5; /* 331 x 413.75 at 1440 */
}

.modal__body {
  padding: 24px 10px 14px;
}

.modal__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.modal__name {
  font-weight: 300;
  font-size: 20px;
  line-height: 1;
  letter-spacing: -0.3px;
}

.modal__meta {
  flex: 0 0 auto;
  font-weight: 400;
  font-size: 12px;
  line-height: 1;
  letter-spacing: -0.18px;
  color: var(--ink-60);
  white-space: nowrap;
}

.modal__bio {
  margin-top: 20px;
  font-size: 14px;
  line-height: 1.2;
  letter-spacing: -0.21px;
  color: var(--ink-60);
  text-align: justify;
}

.modal__bio p + p {
  margin-top: 1.2em;
}

body.modal-open {
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .modal__overlay,
  .modal__panel,
  .details__card,
  .more__toggle > span,
  .nav__menu,
  .nav__menu > .nav__links {
    transition: none;
  }
}

/* =========================================================================
   Services "View details" — a card on the preview image, in place
   ========================================================================= */
.services__details {
  /* JS moves this inside the preview (desktop) or the row's inline image,
     so it simply fills its host and drifts with it. */
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: auto; /* the preview itself ignores the pointer */
}

.services__details[hidden] {
  display: none;
}

/* Centred box holding the card */
.details__box {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  width: 60%; /* 283 of 470 */
}

.details__card {
  position: relative;
  width: 100%;
  /* sized by JS to fit the longest copy (same for all services);
     448 of 646 as a floor, as in the design */
  height: var(--details-h, 69.3%);
  display: flex;
  flex-direction: column;
  padding: 18px;
  background: var(--bg);
  color: var(--ink);
  opacity: 0;
  transform: scale(0.98);
  transition: opacity 0.3s ease, transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  outline: none;
}

.services__details.is-open .details__card {
  opacity: 1;
  transform: none;
}

.details__text {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* starts with "Contact us" and stops at the left edge of "ORGO"
     (JS sets the exact inset from the logo's width; 40px is the fallback) */
  padding: 0 40px 0 0;
  font-size: 14px;
  line-height: 1.2;
  letter-spacing: -0.21px;
  text-align: justify;
}

.details__text p + p {
  margin-top: 1.2em;
}

/* Foot row. Hovering "Contact us" greys the whole row and nudges the label,
   the same treatment as the nav links. */
.details__foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 0;
  margin: 16px 0 -4px;
  transition: background-color 0.2s ease;
}

.details__foot:has(.details__contact:hover),
.details__foot:has(.details__contact:focus-visible) {
  background: var(--bg-alt);
}

.details__contact {
  font-weight: 400;
  font-size: 12px;
  line-height: 1;
  letter-spacing: -0.18px;
  padding-left: 0;
  transition: padding-left 0.2s ease;
  outline: none;
}

.details__contact:hover,
.details__contact:focus-visible {
  padding-left: 3px;
}

.details__brand {
  font-weight: 400;
  font-size: 14px;
  line-height: 1;
  letter-spacing: -0.21px;
}

/* =========================================================================
   Contact — photo, 30% ink overlay, noise, thin white rules at the margins
   ========================================================================= */
.contact {
  position: relative;
  height: 600px;
  overflow: clip;
  color: var(--bg);
}

.contact__bg {
  position: absolute;
  inset: 0;
  background: #444;
}

.contact__bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(16, 17, 17, 0.3);
  z-index: 1;
}

.contact__bg .media__noise {
  z-index: 2;
}

.contact__inner {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  padding: 0 20px 0 var(--margin);
}

/* vertical hairlines at x=10 and x=1430 */
.contact__inner::before,
.contact__inner::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 0.5px;
  pointer-events: none;
}

.contact__inner::before {
  left: var(--margin);
  background: rgba(255, 255, 255, 0.2);
}

.contact__inner::after {
  right: var(--margin);
  background: rgba(255, 255, 255, 0.2);
}

.contact__col {
  /* six columns (+ their gutters) so the card starts on column 7 like the
     team cards; 712px at 1440 */
  width: calc(6 * var(--col) + 6 * var(--gutter));
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  padding: 40px 0;
}

/* The heading pins while the section scrolls, and stops 20px above the
   description because its containing track ends there. */
.contact__track {
  position: relative;
  flex: 1;
}

.contact__title {
  position: sticky;
  top: var(--contact-sticky-top);
  display: flex;
  align-items: center;
  gap: 16.667px;
  font-weight: 300;
  font-size: 28px;
  line-height: 1;
  white-space: nowrap;
  font-feature-settings: "dlig" 1, "lnum" 1, "tnum" 1;
}

.contact__bar {
  width: 0.833px;
  height: 56px;
  background: var(--bg);
  flex: 0 0 auto;
}

.contact__desc {
  margin-top: 20px;
  padding-left: 16.667px;
  width: 365.833px;
  font-size: 14px;
  line-height: 1.2;
  letter-spacing: -0.21px;
  font-feature-settings: "dlig" 1, "lnum" 1, "tnum" 1;
}

.contact__formwrap {
  flex: 1;
  min-width: 0;
  display: flex;
  padding: 40px 10px 40px 8px; /* card at 730→1410 at 1440 */
}

.contact__card {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 40px;
  background: var(--bg);
  color: var(--ink);
}

.form__title {
  font-weight: 300;
  font-size: 20px;
  line-height: 1;
  letter-spacing: -0.3px;
  text-transform: capitalize;
  font-feature-settings: "dlig" 1, "lnum" 1, "tnum" 1;
}

.form__fields {
  margin-top: 20px;
  display: flex;
  flex-direction: column;
  gap: 6.667px;
}

.form__row {
  display: flex;
  gap: 6.667px;
}

.form__row .field {
  flex: 1;
  min-width: 0;
}

.field {
  display: block;
  background: var(--ink-05);
  padding: 14px;
  font-weight: 400;
  font-size: 12px;
  line-height: 1;
}

.field input,
.field textarea {
  display: block;
  width: 100%;
  height: 12px;
  line-height: 1;
  outline: none;
}

.field textarea {
  height: 152px; /* 180px box − 2·14px padding */
  resize: none;
}

.field ::placeholder {
  color: var(--placeholder);
  opacity: 1;
}

.field:focus-within {
  box-shadow: inset 0 0 0 0.5px var(--ink-15);
}

.form__bottom {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.check {
  display: flex;
  align-items: center;
  gap: 6.667px;
  cursor: pointer;
}

.check input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.check__box {
  width: 11.667px;
  height: 11.667px;
  border: 0.5px solid var(--ink);
  background: var(--bg);
  flex: 0 0 auto;
  position: relative;
}

.check input:checked + .check__box::after {
  content: "";
  position: absolute;
  inset: 2px;
  background: var(--ink);
}

.check input:focus-visible + .check__box {
  outline: 1.5px solid var(--ink);
  outline-offset: 2px;
}

.check__label {
  font-size: 12px;
  line-height: 12px;
}

.submit {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 33.333px;
  padding: 5px 13.333px 5px 16.667px;
  background: var(--ink);
  color: var(--bg);
  cursor: pointer;
  transition: opacity 0.3s ease;
}

.submit:hover {
  opacity: 0.85;
}

.submit__label {
  font-weight: 400;
  font-size: 12px;
  line-height: 1;
}

.submit__arrow {
  width: 16.667px;
  height: 16.631px;
  transform: rotate(90deg);
}

.form__status {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  margin-top: 8px;
  font-size: 12px;
  line-height: 1;
  color: var(--ink-60);
  min-height: 12px;
}

/* =========================================================================
   Reveal on scroll — patterns from project-niwa. Elements start hidden only
   once JS runs (html.js) and get .is-shown when they enter the viewport.
   ========================================================================= */

/* Copy blocks / cards: fade up */
.js [data-reveal="fade"] {
  opacity: 0;
  transform: translate3d(0, 16px, 0);
  transition: opacity 0.8s ease, transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--reveal-delay, 0s);
  will-change: opacity, transform;
}

.js [data-reveal="fade"].is-shown {
  opacity: 1;
  transform: none;
}


/* Photos: ease in from a slight zoom (inside their overflow-hidden frame).
   Targets the frame when there is one, else the image itself. */
.js [data-reveal="image"] > img,
.js [data-reveal="image"] > .media__frame {
  opacity: 0;
  transform: scale(1.06);
  transition: opacity 1.1s ease, transform 1.4s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.js [data-reveal="image"].is-shown > img,
.js [data-reveal="image"].is-shown > .media__frame {
  opacity: 1;
  transform: none;
}

/* Headlines: each line is a mask and wipes up into view, staggered.
   The mask is a clip-path (not overflow) so it adds no box size, with a
   little room above/below for ascenders and descenders. */
.rl {
  display: block;
  /* room for accents above and descenders below (the last line is trimmed
     at the baseline, so a "g" hangs ~0.25em under its box) */
  clip-path: inset(-0.2em 0 -0.3em 0);
}

.rl__in {
  display: block;
  /* start below the mask's descender allowance so nothing peeks through */
  transform: translate3d(0, calc(100% + 0.35em), 0);
  transition: transform 0.95s cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--reveal-delay, 0s);
  will-change: transform;
}

.is-shown .rl__in {
  transform: none;
}

/* Keep the Figma cap trimming: the block's own trim no longer reaches the
   nested lines, so trim the first line's top and the last line's bottom. */
.trim .rl:first-child .rl__in {
  text-box-trim: trim-start;
  text-box-edge: cap alphabetic;
}

.trim .rl:last-child .rl__in {
  text-box-trim: trim-end;
  text-box-edge: cap alphabetic;
}

.trim .rl:first-child:last-child .rl__in {
  text-box-trim: trim-both;
}

.contact__title-text {
  display: block;
}

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

  [data-parallax] .media__frame img,
  [data-parallax] .media__frame video {
    top: 0;
    height: 100%;
    transform: none !important;
  }

  .rl__in {
    transform: none;
    transition: none;
  }
}

/* =========================================================================
   Outro: one sticky scene pinned for a viewport of scroll. JS scrubs the
   letters from the centre to the corners, fades the background from the
   page colour to the footer grey and fades the footer content in. The
   stylesheet describes the FINAL state; `.js` sets the starting state.
   ========================================================================= */
.outro {
  position: relative;
  height: 200svh;
}

.outro__scene {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--bg-alt);
}

.js .outro__scene {
  background: var(--bg);
}

/* Footer grey fades in over the page colour (opacity only: compositor-cheap
   on phones, unlike animating background-color on a full-screen layer). */
.outro__tint {
  position: absolute;
  inset: 0;
  background: var(--bg-alt);
  opacity: 1;
  will-change: opacity;
}

.js .outro__tint {
  opacity: 0;
}

.letters {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

.letter {
  position: absolute;
  will-change: transform;
}

.letter--o1 { left: 10px; top: 10px;    width: 28.1753px; height: 29.7888px; }
.letter--r  { right: 10px; top: 10px;   width: 23.045px;  height: 29.3751px; }
.letter--g  { left: 10px; bottom: 10px; width: 26.2721px; height: 29.7888px; }
.letter--o2 { right: 10px; bottom: 10px; width: 28.1753px; height: 29.7888px; }

.footer {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.js .footer {
  opacity: 0;
  transform: translate3d(0, 16px, 0);
  will-change: opacity, transform;
}

.footer__center {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-10px);
  display: flex;
  flex-direction: column;
  align-items: center;
}

.footer__title {
  width: calc(6 * var(--col) + 5 * var(--gutter));
  font-weight: 300;
  font-size: 28px;
  line-height: 1;
  text-align: center;
}

.footer__links {
  margin-top: 40px;
  /* Symmetric: the middle link sits on the heading's axis, 32px gaps either side. */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  column-gap: 32px;
  font-weight: 400;
  font-size: 14px;
  line-height: 1;
  letter-spacing: -0.21px;
}

.footer__links li:nth-child(1) { justify-self: end; }
.footer__links li:nth-child(3) { justify-self: start; }

.footer__links a {
  transition: opacity 0.3s ease;
}

.footer__links a:hover {
  opacity: 0.5;
}

.footer__copy {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 9px;
  font-weight: 400;
  font-size: 14px;
  line-height: 1;
  letter-spacing: -0.21px;
  text-align: center;
}

/* =========================================================================
   Reduced motion: skip the scrub, show the finished footer.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  .outro { height: 100svh; }
  .js .outro__scene { background: var(--bg-alt); }
  .js .outro__tint { opacity: 1; }
  .js .footer { opacity: 1; transform: none; }
}

/* =========================================================================
   Tablet (769–1100px)
   Same 12-column grid. No reliable hover, so the services become 2-up cards
   with their image inline, the team cards span the full width, and the
   contact card sits beside the copy at a narrower measure.
   ========================================================================= */
@media (max-width: 1100px) {
  /* four columns so the brand line and the clock still fit */
  .nav,
  .modal__panel {
    width: calc(4 * var(--vcol) + 3 * var(--gutter));
  }

  .hero__text p {
    width: 100%;
  }

  .intro {
    padding: 160px var(--margin);
  }

  .intro__text {
    width: min(708px, 100%);
  }

  /* Services: cards */
  .services {
    height: auto;
    padding: 80px 0 120px;
    overflow: visible;
  }

  .services__head {
    position: static;
    padding: 0 0 48px calc(var(--margin) + var(--col) + var(--gutter));
  }

  .services__preview {
    display: none;
  }

  .services__list {
    position: static;
    margin: 0 var(--margin);
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 20px;
    row-gap: 16px;
    align-items: start;
  }

  .services__list > li {
    padding-bottom: 28px;
  }

  .service {
    display: grid;
    grid-template-columns: var(--col) minmax(0, 1fr) auto;
    column-gap: var(--gutter);
    align-items: center;
    padding: 14px 0 0;
  }

  /* every card reads at full weight — no active/dimmed states */
  .services__list .service,
  .services__list .service.is-active {
    color: var(--ink);
    border-top-color: var(--ink-15);
  }

  .service__left {
    display: contents;
  }

  .service__num {
    width: auto;
  }

  .service__name {
    white-space: normal;
  }

  .service__media {
    display: block;
    width: 100%;
    margin-top: 20px;
    aspect-ratio: 470 / 646; /* JS may set an explicit height while details are open */
    opacity: 0;
    transform: translateY(24px);
    transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  }

  .services__list > li.in-view .service__media {
    opacity: 1;
    transform: none;
  }

  /* Team: two cards across the full width */
  .team__head {
    padding: 160px var(--margin);
  }

  .team__grid {
    padding-bottom: 160px;
  }

  .team__spacer {
    display: none;
  }

  /* Contact: narrower card beside the copy */
  .contact__col {
    padding-right: 20px;
  }

  .contact__desc {
    width: auto;
    max-width: 365.833px;
  }

  .contact__card {
    padding: 24px;
  }
}

/* =========================================================================
   Mobile (≤768px)
   4 columns · 10px margin · 4px gutter. Everything stacks, the nav collapses
   behind a Menu toggle, and the pre-footer → footer scrub stays.
   ========================================================================= */
@media (max-width: 768px) {
  :root {
    --col: calc((100cqw - 32px) / 4);
    --vcol: calc((100vw - 32px) / 4);
    --contact-sticky-top: 66px; /* below the closed nav */
  }

  /* Nav: full width, links behind the toggle */
  .nav,
  .modal__panel {
    width: calc(100% - 20px);
  }

  .nav {
    gap: 0; /* the menu carries its own spacing so it can collapse to zero */
  }

  .nav__row {
    align-items: center;
  }

  .nav__toggle {
    display: inline-flex;
  }

  /* The menu is a grid row that eases from 0 to its content height, so the
     card reads as expanding downwards; the links fade in as it opens. */
  .nav__menu {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.45s cubic-bezier(0.22, 1, 0.36, 1);
  }

  .nav__menu > .nav__links {
    min-height: 0;
    overflow: hidden;
    opacity: 0;
    transform: translate3d(0, -6px, 0);
    transition: opacity 0.3s ease, transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
  }

  /* spacing lives inside the clipped list so it collapses with it */
  .nav__menu > .nav__links > li:first-child {
    margin-top: 24px;
  }

  .nav.is-open .nav__menu {
    grid-template-rows: 1fr;
  }

  .nav.is-open .nav__menu > .nav__links {
    opacity: 1;
    transform: none;
    transition-delay: 0.05s;
  }

  /* Hero: first screen with the heading at its foot, description below */
  .hero {
    height: auto;
    min-height: 100svh;
    display: flex;
    flex-direction: column;
  }

  .hero__content {
    position: static;
    flex: 1 0 auto;
    min-height: 100svh;
    align-items: flex-end;
    justify-content: flex-start;
    /* heading clear of the browser's floating toolbar */
    padding: 0 var(--margin) 32px;
  }

  .hero__content--text {
    flex: 0 0 auto;
    min-height: 0;
    align-items: flex-start;
    /* iOS Safari: the small viewport (svh) still includes the strip behind
       the floating toolbar, so start the description below the *large*
       viewport instead — it is never visible until the user scrolls. */
    padding: calc(100lvh - 100svh + 8px) var(--margin) 80px;
  }

  .hero__title {
    width: 100%;
    padding-right: 0;
    font-size: 24px;
  }

  .hero__text,
  .hero__text p {
    width: 100%;
  }

  .intro {
    padding: 120px var(--margin);
  }

  .intro__text {
    font-size: 24px;
  }

  /* Services: single-column feed */
  .services {
    padding: 0;
  }

  .services__head {
    padding: 0 var(--margin) 40px;
  }

  .services__title {
    font-size: 24px;
  }

  .services__list {
    grid-template-columns: 1fr;
    row-gap: 0;
  }

  /* gap between each image and the next service's divider */
  .services__list > li {
    padding-bottom: 32px;
  }

  /* number | name (wraps) | View details, vertically centred on the name */
  .service {
    grid-template-columns: 32px minmax(0, 1fr) auto;
    column-gap: 8px;
    align-items: center;
    padding: 16px 0 0;
  }

  .service__name {
    font-size: 18px;
    line-height: 1.15;
  }

  .service__media {
    margin-top: 20px;
  }

  /* Team: stacked */
  .team__head {
    padding: 120px var(--margin);
  }

  .team__title {
    width: 100%;
    font-size: 24px;
  }

  .team__grid {
    padding-bottom: 120px;
  }

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

  .card__info {
    padding-right: 0;
  }

  .card__name {
    white-space: normal;
  }

  /* Contact: stacked */
  .contact {
    height: auto;
  }

  .contact__inner {
    position: relative;
    flex-direction: column;
    padding: 0 var(--margin);
  }

  .contact__col {
    width: auto;
    min-height: 40svh;
    padding: 40px 0;
  }

  .contact__title {
    font-size: 24px;
  }

  .contact__bar {
    height: 48px;
  }

  .contact__desc {
    max-width: none;
  }

  .contact__formwrap {
    padding: 0 0 40px;
  }

  .contact__card {
    gap: 40px;
  }

  .form__row {
    flex-direction: column;
  }


  /* Quicker reveals on phones: they run while the page is still moving */
  .js [data-reveal="fade"] {
    transition-duration: 0.55s;
  }

  .rl__in {
    transition-duration: 0.7s;
  }

  /* No parallax on phones: photos/video sit at their natural size */
  [data-parallax] .media__frame img,
  [data-parallax] .media__frame video {
    top: 0;
    height: 100%;
  }

  /* Footer */
  .footer__title {
    width: 100%;
    font-size: 24px;
  }

  .footer__links {
    column-gap: 24px;
  }
}
