/* ==================================================================
   Muse UGC
   Editorial fashion layout - paper, ink, hairlines, nothing else.
   ------------------------------------------------------------------
   1  tokens
   2  reset
   3  type
   4  header + menu
   5  media primitives (the bit that has to hold up at any size)
   6  home
   7  work reel + lightbox
   8  muses
   9  inner pages
   10 form
   11 footer
   12 motion
   ================================================================== */

/* ---- 1. tokens ------------------------------------------------- */

:root {
  --paper: #f8f6f1;
  --ink: #111111;
  --muted: #75706a;
  --hairline: rgba(17, 17, 17, 0.16);
  --hairline-soft: rgba(17, 17, 17, 0.08);
  --shade: #e9e5de;

  --sans: "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --gutter: clamp(18px, 3.4vw, 62px);
  --gap: clamp(10px, 1.1vw, 18px);
  --rule: clamp(56px, 9vh, 116px);      /* vertical rhythm between blocks */
  --measure: 64ch;

  --header-h: 66px;
  --logo-h: 34px;
  --header-ink: var(--ink);

  --ease: cubic-bezier(0.22, 0.72, 0.2, 1);
  --slow: 720ms;
}

@media (min-width: 900px) {
  :root { --header-h: 82px; --logo-h: 44px; }
}

/* ---- 2. 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(--sans);
  font-size: clamp(15px, 0.42vw + 13.6px, 17px);
  font-weight: 300;
  line-height: 1.55;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Scroll lock. `overflow: hidden` alone is ignored by iOS Safari, which
   happily scrolls the page behind an open overlay, so the body is pinned
   and site.js restores the offset on close. */
body.is-locked {
  position: fixed;
  inset-inline: 0;
  width: 100%;
  overflow: hidden;
}

img, video, svg { display: block; max-width: 100%; }

a { color: inherit; }

button { font: inherit; color: inherit; }

:focus-visible {
  outline: 1px solid var(--ink);
  outline-offset: 3px;
}

.skip {
  position: absolute;
  top: -100px;
  left: var(--gutter);
  z-index: 200;
  padding: 12px 18px;
  background: var(--ink);
  color: var(--paper);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
}

.skip:focus { top: 12px; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---- 3. type --------------------------------------------------- */

h1, h2, h3, h4, p, figure, blockquote { margin: 0; }

.display,
.display-l,
.display-m {
  font-family: var(--sans);
  font-weight: 200;
  line-height: 0.94;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  text-wrap: balance;
}

.display   { font-size: clamp(40px, 10.5vw, 168px); letter-spacing: -0.03em; }
.display-l { font-size: clamp(30px, 5.4vw, 84px); }
.display-m { font-size: clamp(23px, 2.9vw, 40px); }

.label {
  display: block;
  font-size: clamp(9.5px, 0.62vw, 11px);
  font-weight: 400;
  letter-spacing: 0.24em;
  line-height: 1.4;
  text-transform: uppercase;
}

.label--muted { color: var(--muted); }

.lede {
  max-width: 46ch;
  font-size: clamp(17px, 1.35vw, 23px);
  font-weight: 200;
  line-height: 1.4;
  text-wrap: pretty;
}

.prose { max-width: var(--measure); }

.prose > p + p { margin-top: 1.15em; }

.prose a { text-decoration-thickness: 1px; text-underline-offset: 3px; }

/* A hairline-topped block of copy - the site's default text container. */
.copy-block {
  display: grid;
  gap: 1.15em;
  max-width: var(--measure);
  border-top: 1px solid var(--hairline);
  padding-top: clamp(18px, 2vw, 28px);
}

.link-line {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  /* Inline-flex still stretches when it is a grid or flex item, which drags
     the underline across the whole column. Pin it to its own content. */
  width: fit-content;
  justify-self: start;
  align-self: start;
  border-bottom: 1px solid currentColor;
  padding-bottom: 3px;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
  transition: opacity 240ms var(--ease);
}

.link-line:hover { opacity: 0.55; }

.link-line::after {
  content: "";
  width: 15px;
  height: 1px;
  background: currentColor;
  transform: translateY(-4px);
  transition: width 240ms var(--ease);
}

.link-line:hover::after { width: 26px; }

/* ---- 4. header + menu ------------------------------------------ */

.header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 60;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: var(--header-h);
  padding-inline: var(--gutter);
  color: var(--ink);
  transition: color 400ms var(--ease), background-color 400ms var(--ease),
              transform 400ms var(--ease);
}

/* On a phone the header rides on top of the hero footage, so it turns white.
   From 900px up the hero puts paper under the header and ink is correct
   again - which is also why this needs no JavaScript. */
body.has-hero .header { color: #fff; }

@media (min-width: 900px) {
  body.has-hero .header { color: var(--ink); }
}

/* Solid once we are past the hero, so the type never fights the artwork. */
.header.is-solid,
body.has-hero .header.is-solid {
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 1px 0 var(--hairline-soft);
}

.header.is-hidden { transform: translateY(-100%); }

body.is-menu-open .header { transform: none; color: var(--ink); }

.header__wordmark {
  grid-column: 2;
  display: block;
  font-size: clamp(12px, 1.05vw, 15px);
  font-weight: 400;
  letter-spacing: 0.34em;
  text-indent: 0.34em;              /* balances the trailing letterspace */
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}

/*
   The mark replaces the words. It is drawn as a mask filled with currentColor
   rather than an <img>, so it inherits the header's ink-to-white transition
   exactly as the text did - one file, every state, no second artwork.
   Browsers without mask support keep the typeset wordmark.
*/
@supports (mask-image: url("../img/logo-mark.png")) or
          (-webkit-mask-image: url("../img/logo-mark.png")) {
  .header__wordmark-text {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .header__wordmark::before {
    content: "";
    display: block;
    width: calc(var(--logo-h) * 1.962);   /* the trimmed mark's aspect ratio */
    height: var(--logo-h);
    background-color: currentColor;
    -webkit-mask: url("../img/logo-mark.png") center / contain no-repeat;
    mask: url("../img/logo-mark.png") center / contain no-repeat;
  }
}

.header__right {
  grid-column: 3;
  justify-self: end;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
}

@media (max-width: 640px) {
  .header__right { display: none; }
}

.menu-btn {
  grid-column: 1;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border: 0;
  background: none;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  cursor: pointer;
}

.menu-btn__bars {
  position: relative;
  width: 20px;
  height: 9px;
}

.menu-btn__bars i {
  position: absolute;
  left: 0; right: 0;
  height: 1px;
  background: currentColor;
  transition: transform 300ms var(--ease);
}

.menu-btn__bars i:first-child { top: 0; }
.menu-btn__bars i:last-child  { bottom: 0; }

body.is-menu-open .menu-btn__bars i:first-child { transform: translateY(4px) rotate(45deg); }
body.is-menu-open .menu-btn__bars i:last-child  { transform: translateY(-4px) rotate(-45deg); }

@media (max-width: 480px) {
  .menu-btn__label { display: none; }
}

.menu {
  position: fixed;
  inset: 0;
  z-index: 55;
  visibility: hidden;
}

body.is-menu-open .menu { visibility: visible; }

.menu__scrim {
  position: absolute;
  inset: 0;
  background: rgba(17, 17, 17, 0.3);
  opacity: 0;
  transition: opacity 420ms var(--ease);
}

body.is-menu-open .menu__scrim { opacity: 1; }

.menu__panel {
  position: absolute;
  inset: 0 auto 0 0;
  display: flex;
  flex-direction: column;
  width: min(430px, 100%);
  padding: calc(var(--header-h) + 26px) var(--gutter) 34px;
  background: var(--paper);
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translateX(-100%);
  transition: transform 480ms var(--ease);
}

body.is-menu-open .menu__panel { transform: none; }

.menu__list { margin: 0; padding: 0; list-style: none; }

.menu__list > li { border-bottom: 1px solid var(--hairline); }

.menu__link,
.menu__parent {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  padding: 18px 0;
  border: 0;
  background: none;
  font-size: clamp(13px, 1.4vw, 15px);
  font-weight: 300;
  letter-spacing: 0.18em;
  text-align: left;
  text-decoration: none;
  text-transform: uppercase;
  cursor: pointer;
}

.menu__parent::after {
  content: "";
  position: relative;
  width: 9px; height: 9px;
  flex: 0 0 9px;
  background:
    linear-gradient(currentColor, currentColor) center/100% 1px no-repeat,
    linear-gradient(currentColor, currentColor) center/1px 100% no-repeat;
  transition: background-size 320ms var(--ease);
}

/* Plus becomes minus: the vertical stroke collapses to nothing.
   (Rotating as well would just stand the remaining stroke back up.) */
.menu__parent[aria-expanded="true"]::after { background-size: 100% 1px, 1px 0; }

.menu__sub {
  height: 0;
  overflow: hidden;
  transition: height 380ms var(--ease);
}

.menu__sub ul { margin: 0; padding: 0 0 14px; list-style: none; }

.menu__sub a {
  display: block;
  padding: 8px 0;
  color: var(--muted);
  font-size: 13px;
  font-weight: 300;
  letter-spacing: 0.06em;
  text-decoration: none;
  transition: color 200ms var(--ease);
}

.menu__sub a:hover,
.menu__sub a[aria-current="page"] { color: var(--ink); }

.menu__foot {
  margin-top: auto;
  padding-top: 34px;
  color: var(--muted);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.menu__foot a { text-decoration: none; border-bottom: 1px solid var(--hairline); }

/* ---- 5. media primitives --------------------------------------- */
/*
   Every image and every video on the site goes through .frame.

   The frame owns the aspect ratio, so the browser reserves the exact box
   before a single byte of media arrives - no layout shift, no jumping grid.
   The blurred LQIP sits underneath as a background-image and is revealed
   only until the real file decodes.
*/

.frame {
  position: relative;
  overflow: hidden;
  background-color: var(--shade);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}

/* The <img> stays inside its <picture> - moving it out would silently
   disable the AVIF and WebP <source>s - so every rule below reaches
   through the wrapper as well as matching a bare child. */
.frame > picture { display: contents; }

.frame > img,
.frame > video,
.frame > picture > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focal, center);
  opacity: 0;
  transition: opacity 900ms var(--ease);
}

/* Media that has to fill a fixed box (grid tiles, hero) is absolutely
   positioned so the ratio comes from the frame, never from the file. */
.frame--fill > img,
.frame--fill > video,
.frame--fill > picture > img {
  position: absolute;
  inset: 0;
}

.frame.is-ready > img,
.frame.is-ready > video,
.frame.is-ready > picture > img { opacity: 1; }

/* The placeholder fades out from under the media instead of popping. */
.frame::after {
  content: "";
  position: absolute;
  inset: 0;
  background: inherit;
  background-color: transparent;
  filter: blur(18px);
  transform: scale(1.08);
  opacity: 1;
  transition: opacity 900ms var(--ease);
  pointer-events: none;
}

.frame.is-ready::after { opacity: 0; }

.ratio-3x4  { aspect-ratio: 3 / 4; }
.ratio-4x5  { aspect-ratio: 4 / 5; }
.ratio-9x16 { aspect-ratio: 9 / 16; }
.ratio-1x1  { aspect-ratio: 1 / 1; }
.ratio-16x9 { aspect-ratio: 16 / 9; }

/* A full-bleed strip that keeps a sane height on ultrawide and on phones. */
.frame--bleed {
  width: 100%;
  height: clamp(420px, 74vh, 860px);
}

/* ---- 6. home --------------------------------------------------- */

/*
   The source footage is 9:16. Cropping that to a 16:9 desktop hero throws
   away three quarters of the frame, so the layout changes shape instead:
   phones get the full-bleed overlay, wide screens get a portrait plate
   next to the type. The video is never asked to be a shape it is not.
*/

.hero {
  position: relative;
  display: grid;
  height: 100svh;
  min-height: 540px;
  background: var(--ink);
}

.hero__media {
  grid-area: 1 / 1;
  position: relative;
  overflow: hidden;
  background: var(--ink);
}

.hero__media > .frame {
  position: absolute;
  inset: 0;
  background-color: var(--ink);
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  background:
    linear-gradient(180deg, rgba(0, 0, 0, 0.38) 0%, rgba(0, 0, 0, 0) 28%),
    linear-gradient(0deg, rgba(0, 0, 0, 0.55) 0%, rgba(0, 0, 0, 0) 46%);
  pointer-events: none;
}

.hero__body {
  grid-area: 1 / 1;
  position: relative;
  z-index: 3;
  align-self: end;
  display: grid;
  gap: 16px;
  padding: 0 var(--gutter) clamp(30px, 5vh, 62px);
  color: #fff;
}

.hero__title {
  max-width: 14ch;
  font-size: clamp(31px, 7.4vw, 60px);
  font-weight: 200;
  line-height: 1.02;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  text-wrap: balance;
}

.hero__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 4px;
}

/* Sound toggle for the hero loop - it ships muted, the visitor opts in. */
.hero__sound {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 9px 16px;
  border: 1px solid currentColor;
  background: none;
  color: inherit;
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 240ms var(--ease), color 240ms var(--ease);
}

.hero__sound:hover { background: currentColor; }

.hero__sound:hover .hero__sound-label { color: var(--ink); }

/* Desktop affordance only - on a phone it lands on top of the hero copy,
   and a touch visitor does not need to be told the page scrolls. */
.hero__scroll { display: none; }

@media (min-width: 900px) {
  .hero__scroll { display: block; }
}

.hero__scroll {
  position: absolute;
  left: 50%;
  bottom: clamp(20px, 3vh, 34px);
  z-index: 4;
  width: 1px;
  height: 44px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0));
  transform: translateX(-50%);
  animation: scroll-cue 2.4s var(--ease) infinite;
}

@media (min-width: 900px) {
  /* Paper on the left, a full-height portrait plate on the right. The header
     now sits entirely on paper, so its type can stay ink. */
  .hero {
    grid-template-columns: 1fr clamp(340px, 40vw, 620px);
    align-items: stretch;
    padding-top: var(--header-h);
    background: var(--paper);
  }

  .hero__media { grid-area: 1 / 2; }

  .hero__body {
    grid-area: 1 / 1;
    align-self: center;
    gap: 22px;
    padding: 0 clamp(30px, 4vw, 76px) 0 var(--gutter);
    color: var(--ink);
  }

  .hero__title { max-width: 13ch; font-size: clamp(44px, 4.9vw, 86px); }

  .hero__scrim { display: none; }

  .hero__scroll { bottom: clamp(26px, 4vh, 52px); }
}

@media (min-width: 1500px) {
  .hero { grid-template-columns: 1fr clamp(420px, 34vw, 700px); }
}

@keyframes scroll-cue {
  0%, 100% { opacity: 0; transform: translate(-50%, -10px); }
  40%      { opacity: 1; transform: translate(-50%, 0); }
  75%      { opacity: 0; transform: translate(-50%, 12px); }
}

.section {
  padding: var(--rule) var(--gutter);
}

.section--tight { padding-block: clamp(38px, 6vh, 74px); }

.section--flush { padding-inline: 0; }

.shell { max-width: 1560px; margin-inline: auto; }

.section__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: clamp(22px, 3vw, 40px);
  padding-bottom: 16px;
  border-bottom: 1px solid var(--hairline);
}

/* The single big line that carries the brand voice. */
.statement {
  max-width: 24ch;
  margin-inline: auto;
  padding-block: clamp(50px, 9vh, 120px);
  text-align: center;
}

/* Asymmetric editorial split: portrait one side, copy the other. */
.split {
  display: grid;
  gap: clamp(22px, 3.4vw, 62px);
  align-items: center;
}

@media (min-width: 860px) {
  .split { grid-template-columns: 1.05fr 1fr; }
  .split--reverse > *:first-child { order: 2; }
  .split--narrow { grid-template-columns: 0.8fr 1fr; }
  /* For a short block of copy against a tall portrait, centring leaves the
     text stranded in the middle of the column. Hang it from the top rule. */
  .split--top { grid-template-columns: 1fr 0.72fr; align-items: start; }
}

.split__copy { display: grid; gap: clamp(18px, 2vw, 30px); align-content: start; }

/* A staggered pair of portraits - the second one drops and shrinks. */
.duo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gap);
  align-items: start;
}

.duo > *:last-child { margin-top: clamp(28px, 7vw, 90px); }

.strip {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gap);
}

@media (min-width: 760px)  { .strip { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1180px) { .strip { grid-template-columns: repeat(4, 1fr); } }

/* Full-bleed image with a call to action sitting on it. */
.feature {
  position: relative;
  display: grid;
}

.feature__body {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 20px;
  padding: var(--gutter);
  color: #fff;
  text-align: center;
  background: rgba(0, 0, 0, 0.22);
}

.feature__body .link-line { border-color: #fff; justify-self: center; }

.feature__body .display-m { max-width: 18ch; }

/* ---- 7. work reel + lightbox ----------------------------------- */

.reel {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gap);
}

@media (min-width: 700px)  { .reel { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1080px) { .reel { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1500px) { .reel { grid-template-columns: repeat(5, 1fr); } }

.tile {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: var(--ink);
  cursor: pointer;
  overflow: hidden;
}

.tile .frame { background-color: var(--ink); }

.tile__preview {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 420ms var(--ease);
}

.tile.is-previewing .tile__preview { opacity: 1; }

.tile__mark {
  position: absolute;
  left: 14px;
  bottom: 12px;
  z-index: 3;
  color: #fff;
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
  opacity: 0.9;
}

.tile__play {
  position: absolute;
  left: 50%; top: 50%;
  z-index: 3;
  display: grid;
  place-items: center;
  width: clamp(38px, 3.6vw, 50px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border: 1px solid rgba(255, 255, 255, 0.8);
  border-radius: 50%;
  transition: transform 320ms var(--ease), background 320ms var(--ease),
              opacity 320ms var(--ease);
}

.tile__play svg { width: 26%; fill: #fff; margin-left: 10%; }

.tile:hover .tile__play { background: rgba(255, 255, 255, 0.16); transform: translate(-50%, -50%) scale(1.06); }

.tile.is-previewing .tile__play { opacity: 0; }

.tile:hover .frame > picture > img { transform: scale(1.03); }

.tile .frame > picture > img { transition: opacity 900ms var(--ease), transform 1.2s var(--ease); }

/* --- lightbox --- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: #0c0b0a;
  opacity: 0;
  visibility: hidden;
  transition: opacity 340ms var(--ease), visibility 340ms;
}

.lightbox.is-open { opacity: 1; visibility: visible; }

.lightbox__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px var(--gutter);
  color: rgba(255, 255, 255, 0.7);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.lightbox__stage {
  position: relative;
  display: grid;
  place-items: center;
  padding: 0 clamp(8px, 4vw, 72px);
  min-height: 0;
}

.lightbox__stage video {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  background: #000;
}

.lightbox__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 42px;
  min-height: 42px;
  padding: 10px 14px;
  border: 0;
  background: none;
  color: rgba(255, 255, 255, 0.75);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 200ms var(--ease);
}

.lightbox__btn:hover:not(:disabled) { color: #fff; }
.lightbox__btn:disabled { opacity: 0.28; cursor: default; }

.lightbox__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(10px, 3vw, 40px);
  padding: 12px var(--gutter) clamp(18px, 4vh, 34px);
}

/* ---- 8. muses -------------------------------------------------- */

/* Category tabs, in the manner of an agency board index. */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(18px, 3vw, 38px);
  margin-top: clamp(18px, 2.4vw, 30px);
}

.tab {
  padding: 0 0 7px;
  border: 0;
  border-bottom: 1px solid transparent;
  background: none;
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 240ms var(--ease), border-color 240ms var(--ease);
}

.tab:hover { color: var(--ink); }

.tab[aria-selected="true"] {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

.tab__count {
  margin-left: 7px;
  font-size: 9px;
  vertical-align: 2px;
  color: var(--muted);
}

.muses {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(18px, 2.2vw, 34px) var(--gap);
  margin-top: clamp(26px, 3.4vw, 48px);
}

@media (min-width: 720px)  { .muses { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1200px) { .muses { grid-template-columns: repeat(4, 1fr); } }

.muse { margin: 0; }

.muse[hidden] { display: none; }

.muse__link { display: block; text-decoration: none; }

/*
   The board reads as black and white; a card finds its colour when you
   reach for it. Touch devices have no hover, so :active covers the press
   and the muse's own page is always in full colour.

   These photos were shot flat, on pale walls under soft light, so plain
   grayscale() leaves them grey and washed. Dropping the brightness a
   little before pushing contrast deepens the blacks without blowing the
   walls out: at 0.95 / 1.4 the worst frame clips 2.5% of its highlights,
   and nothing crushes. Past about 1.45 the freckles and skin texture on
   the closer portraits start to crunch.
*/
.muse__frame > picture > img {
  filter: grayscale(1) brightness(0.95) contrast(1.4);
  /* --card-zoom evens out the head sizes across the board. Scaling about the
     focal point rather than the middle keeps the face where object-position
     already put it, so the crop tightens around her instead of drifting. */
  transform: scale(var(--card-zoom, 1));
  transform-origin: var(--focal, center);
  transition: opacity 900ms var(--ease), filter 700ms var(--ease),
              transform 1.4s var(--ease);
}

.muse__link:hover .muse__frame > picture > img,
.muse__link:active .muse__frame > picture > img,
.muse__link:focus-visible .muse__frame > picture > img {
  filter: grayscale(0) brightness(1) contrast(1);
  transform: scale(calc(var(--card-zoom, 1) * 1.02));
}

.muse__caption {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-top: 11px;
}

.muse__name {
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.muse__height { color: var(--muted); font-size: 10px; letter-spacing: 0.14em; }

.muses__empty {
  margin-top: clamp(30px, 5vh, 60px);
  color: var(--muted);
  font-size: 14px;
}

/* ---- 8b. one muse ---------------------------------------------- */

.muse-page { display: grid; gap: clamp(26px, 4vw, 60px); }

@media (min-width: 960px) {
  /* The photo column is sized from the height available rather than a share
     of the width: a 3:4 portrait in a half-width column on a wide screen is
     over a thousand pixels tall, and pushes the measurements off screen.
     0.75 is the 3:4 ratio, so the whole frame fits without being cropped. */
  .muse-page {
    grid-template-columns:
      min(56%, calc((100svh - var(--header-h) - 190px) * 0.75)) 1fr;
    align-items: start;
    gap: clamp(34px, 5vw, 88px);
  }
}

/* Swipeable on a phone, arrow-driven on a desktop - one component either
   way, because scroll-snap is what makes both feel native. */
.lookbook { position: relative; }

.lookbook__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  gap: var(--gap);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.lookbook__track::-webkit-scrollbar { display: none; }

.lookbook__track > * { scroll-snap-align: start; }

.lookbook__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 14px;
}

.lookbook__count {
  color: var(--muted);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.lookbook__nav { display: flex; gap: 6px; }

.lookbook__btn {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--hairline);
  background: none;
  cursor: pointer;
  transition: border-color 200ms var(--ease), background 200ms var(--ease),
              opacity 200ms var(--ease);
}

.lookbook__btn:hover:not(:disabled) { border-color: var(--ink); background: var(--ink); color: var(--paper); }

.lookbook__btn:disabled { opacity: 0.3; cursor: default; }

.lookbook__btn svg { width: 13px; fill: none; stroke: currentColor; stroke-width: 1.2; }

/* Dots stand in for the arrows where there is no pointer to hover. */
.lookbook__dots { display: flex; gap: 6px; }

.lookbook__dot {
  width: 5px;
  height: 5px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--hairline);
  cursor: pointer;
  transition: background 240ms var(--ease);
}

.lookbook__dot[aria-current="true"] { background: var(--ink); }

@media (hover: hover) and (pointer: fine) {
  .lookbook__dots { display: none; }
}

@media (hover: none) {
  .lookbook__nav { display: none; }
}

.muse-info { display: grid; gap: clamp(18px, 2.4vw, 30px); align-content: start; }

@media (min-width: 960px) {
  .muse-info { position: sticky; top: calc(var(--header-h) + 34px); }
}

.muse-info__name {
  font-size: clamp(32px, 4.4vw, 62px);
  font-weight: 200;
  line-height: 0.98;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}

.specs { margin: 0; display: grid; }

.specs > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
  padding: 13px 0;
  border-bottom: 1px solid var(--hairline);
}

.specs > div:first-child { border-top: 1px solid var(--hairline); }

.specs dt {
  color: var(--muted);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.specs dd {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 15px;
  font-weight: 300;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(17, 17, 17, 0.14);
}

/* Walk the board without going back to the index. */
.muse-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: var(--rule);
  padding-top: 20px;
  border-top: 1px solid var(--hairline);
}

.muse-nav a,
.muse-nav span {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
}

.muse-nav span { color: var(--hairline); }

.muse-nav a:hover { opacity: 0.55; }

/* ---- 9. inner pages -------------------------------------------- */

.page {
  padding: calc(var(--header-h) + clamp(34px, 7vh, 90px)) var(--gutter) 0;
}

.page__head {
  display: grid;
  gap: clamp(18px, 2.4vw, 30px);
  padding-bottom: clamp(30px, 5vh, 62px);
  border-bottom: 1px solid var(--hairline);
}

.page__body { padding-block: var(--rule); }

.page__body h2 { margin-bottom: clamp(16px, 2vh, 26px); }

/*
   Magazine rail. On a wide screen a 64ch measure sitting alone in a 1560px
   column reads as an unfinished page, so the heading hangs in a narrow left
   rail and the copy runs beside it. Below 1000px it stacks, heading first.
*/
.rail {
  display: grid;
  gap: clamp(14px, 2vw, 26px);
  margin-top: var(--rule);
  padding-top: clamp(24px, 3vw, 42px);
  border-top: 1px solid var(--hairline);
}

@media (min-width: 1000px) {
  .rail {
    grid-template-columns: 0.34fr 1fr;
    gap: clamp(30px, 5vw, 96px);
  }
}

.rail > h2 { align-self: start; margin-bottom: 0; }

.rail__body { display: grid; gap: clamp(20px, 2.4vw, 32px); }

/* The rail already draws the rule above the block. */
.rail .copy-block { border-top: 0; padding-top: 0; }

.steps {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
  max-width: var(--measure);
}

.steps li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 52px 1fr;
  gap: 16px;
  padding: 20px 0;
  border-bottom: 1px solid var(--hairline);
}

.steps li:first-child { border-top: 1px solid var(--hairline); }

.steps li::before {
  content: counter(step, decimal-leading-zero);
  color: var(--muted);
  font-size: 10px;
  letter-spacing: 0.18em;
  padding-top: 5px;
}

.facts {
  display: grid;
  gap: 1px;
  margin-top: var(--rule);
  background: var(--hairline);
  border-block: 1px solid var(--hairline);
}

@media (min-width: 700px) { .facts { grid-template-columns: repeat(3, 1fr); } }

.facts > div { background: var(--paper); padding: clamp(22px, 3vw, 34px) clamp(16px, 2vw, 26px); }

.facts dt { margin-bottom: 8px; }

.facts dd {
  margin: 0;
  font-size: clamp(26px, 3vw, 40px);
  font-weight: 200;
  line-height: 1;
  letter-spacing: -0.02em;
}

/* ---- 10. form -------------------------------------------------- */

.form .field,
.form .two-up,
.form .fieldset,
.form .submit,
.form .hint { max-width: 660px; }

.field { margin-bottom: 24px; }

.field > label,
.fieldset > legend {
  display: block;
  margin-bottom: 8px;
  padding: 0;
  color: var(--muted);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.field input[type="text"],
.field input[type="number"],
.field input[type="email"],
.field input[type="url"],
.field textarea {
  width: 100%;
  padding: 10px 0;
  border: 0;
  border-bottom: 1px solid var(--ink);
  border-radius: 0;
  background: none;
  color: var(--ink);
  font-family: inherit;
  font-size: 16px;              /* 16px stops iOS zooming the page on focus */
  font-weight: 300;
  transition: border-color 200ms var(--ease);
}

.field input::placeholder { color: rgba(17, 17, 17, 0.32); }

.field input:focus,
.field textarea:focus {
  outline: none;
  border-bottom-color: var(--ink);
  box-shadow: 0 1px 0 var(--ink);
}

.field input[aria-invalid="true"] { border-bottom-color: #8a2020; }

.field textarea { min-height: 100px; resize: vertical; }

.field input[type="file"] {
  width: 100%;
  font-family: inherit;
  font-size: 13px;
  color: var(--muted);
}

.two-up { display: grid; gap: 24px; }

@media (min-width: 620px) { .two-up { grid-template-columns: 1fr 1fr; } }

.fieldset { margin: 0 0 24px; padding: 0; border: 0; }

.choices { display: flex; gap: 9px; flex-wrap: wrap; }

.choice {
  padding: 12px 32px;
  border: 1px solid var(--ink);
  background: none;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 220ms var(--ease), color 220ms var(--ease);
}

.choice[aria-pressed="true"] { background: var(--ink); color: var(--paper); }

.conditional { height: 0; overflow: hidden; transition: height 380ms var(--ease); }

.conditional__inner { padding: 4px 0 2px 18px; border-left: 1px solid var(--hairline); }

.hint { margin-top: 8px; color: var(--muted); font-size: 12.5px; line-height: 1.45; }

.submit {
  width: 100%;
  margin-top: 10px;
  padding: 18px 24px;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  font-size: 11px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 220ms var(--ease), color 220ms var(--ease);
}

.submit:hover { background: transparent; color: var(--ink); }

.form__error { min-height: 20px; margin-top: 12px; color: #8a2020; font-size: 13px; }

.form__done {
  display: none;
  margin-top: 20px;
  padding: 20px 22px;
  border: 1px solid var(--ink);
  font-size: 15px;
}

.form__done.is-on { display: block; }

/* ---- 11. footer ------------------------------------------------ */

.footer {
  margin-top: var(--rule);
  padding: clamp(44px, 7vh, 86px) var(--gutter) clamp(26px, 4vh, 40px);
  border-top: 1px solid var(--hairline);
}

.footer__grid {
  display: grid;
  gap: clamp(28px, 4vw, 54px);
  max-width: 1560px;
  margin-inline: auto;
}

@media (min-width: 760px) {
  .footer__grid { grid-template-columns: 1.4fr repeat(3, 1fr); }
}

.footer__col ul { margin: 10px 0 0; padding: 0; list-style: none; }

.footer__col li + li { margin-top: 7px; }

.footer__col a {
  color: var(--muted);
  font-size: 12.5px;
  text-decoration: none;
  transition: color 200ms var(--ease);
}

.footer__col a:hover { color: var(--ink); }

.footer__mark {
  font-size: clamp(24px, 3.4vw, 44px);
  font-weight: 200;
  letter-spacing: 0.1em;
  line-height: 1;
  text-transform: uppercase;
}

.footer__note { margin-top: 12px; max-width: 34ch; color: var(--muted); font-size: 12.5px; }

.footer__base {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  max-width: 1560px;
  margin: clamp(34px, 5vw, 60px) auto 0;
  padding-top: 18px;
  border-top: 1px solid var(--hairline);
  color: var(--muted);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* ---- 12. motion ------------------------------------------------ */

/* Blocks lift in once, as they enter. Applied by site.js so that with
   JavaScript off everything is simply visible. */
.js .reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease);
}

.js .reveal.is-in { opacity: 1; transform: none; }

.js .reveal--d1 { transition-delay: 90ms; }
.js .reveal--d2 { transition-delay: 180ms; }
.js .reveal--d3 { transition-delay: 270ms; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .js .reveal { opacity: 1; transform: none; }
  .hero__scroll { display: none; }
}

@media print {
  .header, .menu, .lightbox, .book, .hero__scroll { display: none !important; }
  body { background: #fff; }
}

/* ------------------------------------------------------------------
   13. portfolio
------------------------------------------------------------------ */

/* The jump list under the page title. Reads as one line of small caps
   with middots between, wrapping freely. */
.index {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  margin-top: clamp(16px, 2vw, 24px);
}

.index a {
  color: var(--muted);
  font-size: 10.5px;
  letter-spacing: 0.18em;
  line-height: 2.1;
  text-transform: uppercase;
  text-decoration: none;
  transition: color 200ms var(--ease);
}

.index a:hover { color: var(--ink); }

.index a::after {
  content: "\00b7";
  margin: 0 11px;
  color: var(--hairline);
}

.index a:last-child::after { content: ""; margin: 0; }

.case {
  padding-top: clamp(20px, 2.6vw, 34px);
  border-top: 1px solid var(--hairline);
  /* Clears the fixed header when a jump link lands here. */
  scroll-margin-top: calc(var(--header-h) + 20px);
}

.case + .case { margin-top: var(--rule); }

/* page__head already draws a rule directly above the first client. */
.page__body > .case:first-child { border-top: 0; padding-top: 0; }

.case__head {
  display: grid;
  gap: 6px;
  margin-bottom: clamp(16px, 2vw, 26px);
}

@media (min-width: 1000px) {
  /* Client on the left, work on the right. The name stays put while its
     own clips scroll past, then releases at the next client. */
  .case {
    display: grid;
    grid-template-columns: 0.28fr 1fr;
    gap: clamp(28px, 4.5vw, 88px);
  }

  .case__head {
    position: sticky;
    top: calc(var(--header-h) + 26px);
    align-self: start;
    margin-bottom: 0;
  }
}

.case__name {
  font-size: clamp(21px, 2.1vw, 31px);
  font-weight: 200;
  line-height: 1.04;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  text-wrap: balance;
}

.case__count {
  color: var(--muted);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.case__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gap);
}

@media (min-width: 700px)  { .case__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1360px) { .case__grid { grid-template-columns: repeat(4, 1fr); } }

/* A one-clip job would otherwise sit as a lonely quarter-width tile. */
@media (min-width: 700px) {
  .case__grid--single { grid-template-columns: minmax(0, 320px); }
}

/* ------------------------------------------------------------------
   14. banner, buttons, contact
------------------------------------------------------------------ */

/* A full-bleed opening image with the page title sitting on it. */
.banner {
  position: relative;
  display: grid;
  background: var(--ink);
}

.banner__body {
  position: absolute;
  inset: auto 0 0;
  z-index: 2;
  display: grid;
  gap: 14px;
  padding: var(--gutter);
  padding-top: clamp(60px, 12vh, 140px);
  color: #fff;
  background: linear-gradient(0deg, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 100%);
}

.banner__title {
  max-width: 16ch;
  font-size: clamp(30px, 5vw, 76px);
  font-weight: 200;
  line-height: 1.02;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  text-wrap: balance;
}

/* The banner already supplies the top margin. */
.page--flush { padding-top: 0; }

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 15px 30px;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background 220ms var(--ease), color 220ms var(--ease);
}

.button:hover { background: transparent; color: var(--ink); }

.button--quiet {
  border-color: var(--hairline);
  background: none;
  color: var(--ink);
  padding: 12px 24px;
}

.button--quiet:hover { border-color: var(--ink); background: var(--ink); color: var(--paper); }

.cta-row {
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 34px);
  flex-wrap: wrap;
}

/* Contact rows reuse the muse spec list, but the values are links. */
.specs dd a { text-decoration: none; border-bottom: 1px solid var(--hairline); }

.specs dd a:hover { border-bottom-color: var(--ink); }

@media (max-width: 560px) {
  /* A long address will not sit beside its label on a phone. */
  .specs > div { flex-direction: column; align-items: flex-start; gap: 6px; }
  .specs dd { text-align: left; }
}

.footer__reach {
  display: inline-block;
  margin-top: 6px;
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.footer__buttons {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  max-width: 1560px;
  margin: clamp(30px, 4vw, 48px) auto 0;
}
