/* ===========================================================
   Joe Henshaw — portfolio
   Built to the 1440px desktop mockup: 1280px container, 80px margins,
   3 x 411px columns, 24px gutters.
   Desktop values are mockup pixels, scaled fluidly via --u.
   =========================================================== */

:root{
  --ink:     #000000;
  --paper:   #FFFFFF;
  --surface: #EDE9E9;

  /* 1 unit = 1px at a 1440px viewport. */
  --u: clamp(0.71px, 0.0694vw, 1px);
}

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

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

body{
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display", "Helvetica Neue", Arial, Helvetica, sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img{ display: block; max-width: 100%; height: auto; }
ul{ list-style: none; margin: 0; padding: 0; }
a{ color: inherit; text-decoration: none; }
h1, h2, h3, p{ margin: 0; }

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

/* ---------- Shell ---------- */

.container{
  width: 100%;
  max-width: 1440px;
  margin-inline: auto;
  padding-inline: clamp(20px, 5.5555vw, 80px);
}

.rule{
  border: 0;
  border-top: 2px solid var(--surface);
}

/* ---------- Header ---------- */

.header__inner{
  position: relative;
  display: flex;
  align-items: center;
  padding-top: calc(55 * var(--u));
}

.logo{
  font-size: calc(62 * var(--u));
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1;
}

.nav{
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  top: calc(58 * var(--u));
  z-index: 100;
  display: flex;
  border-radius: 999px;
  padding: calc(9 * var(--u));
  overflow: hidden;
  isolation: isolate;

  /* Liquid glass.
     Layer 1 — specular sheen: bright along the top edge, fading out by the
     middle, with a faint bounce off the bottom.
     Layer 2 — the tint itself, translucent enough to pick up what's behind. */
  background:
    linear-gradient(
      180deg,
      rgba(255,255,255,0.62) 0%,
      rgba(255,255,255,0.16) 38%,
      rgba(255,255,255,0.00) 58%,
      rgba(255,255,255,0.22) 100%
    ),
    rgba(240, 237, 237, 0.62);

  -webkit-backdrop-filter: blur(26px) saturate(210%) brightness(1.05);
  backdrop-filter: blur(26px) saturate(210%) brightness(1.05);

  /* Inner glow gives the pill some thickness; the outer pair keeps it
     sitting above the page rather than printed on it. */
  box-shadow:
    inset 0 calc(1 * var(--u)) calc(1 * var(--u)) rgba(255,255,255,0.90),
    inset 0 calc(-1 * var(--u)) calc(2 * var(--u)) rgba(255,255,255,0.45),
    inset 0 0 calc(22 * var(--u)) rgba(255,255,255,0.20),
    0 calc(1 * var(--u)) calc(2 * var(--u)) rgba(0,0,0,0.04),
    0 calc(10 * var(--u)) calc(28 * var(--u)) rgba(0,0,0,0.10);

  transition: background-color 0.4s ease, box-shadow 0.4s ease;
}

/* Rim. A 1px gradient ring, brightest top-left and bottom-right, with its
   own slice of blur so the edge reads as bent light rather than a border. */
.nav::before{
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  padding: calc(1.2 * var(--u));
  background: linear-gradient(
    140deg,
    rgba(255,255,255,0.95) 0%,
    rgba(255,255,255,0.25) 28%,
    rgba(255,255,255,0.10) 50%,
    rgba(255,255,255,0.40) 72%,
    rgba(255,255,255,0.85) 100%
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}

/* Highlight that follows the pointer across the glass. */
.nav::after{
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  background: radial-gradient(
    calc(130 * var(--u)) circle at var(--gx, 50%) var(--gy, 50%),
    rgba(255,255,255,0.60),
    rgba(255,255,255,0.00) 62%
  );
  opacity: 0;
  transition: opacity 0.45s ease;
  pointer-events: none;
}

.nav:hover::after{ opacity: 1; }

/* Over content the tint thins out and the rim picks up. */
.nav.is-stuck{
  background:
    linear-gradient(
      180deg,
      rgba(255,255,255,0.70) 0%,
      rgba(255,255,255,0.18) 38%,
      rgba(255,255,255,0.00) 58%,
      rgba(255,255,255,0.26) 100%
    ),
    rgba(240, 237, 237, 0.40);
  -webkit-backdrop-filter: blur(32px) saturate(240%) brightness(1.08);
  backdrop-filter: blur(32px) saturate(240%) brightness(1.08);
  box-shadow:
    inset 0 calc(1 * var(--u)) calc(1 * var(--u)) rgba(255,255,255,1),
    inset 0 calc(-1 * var(--u)) calc(2 * var(--u)) rgba(255,255,255,0.55),
    inset 0 0 calc(26 * var(--u)) rgba(255,255,255,0.28),
    0 calc(2 * var(--u)) calc(4 * var(--u)) rgba(0,0,0,0.06),
    0 calc(14 * var(--u)) calc(38 * var(--u)) rgba(0,0,0,0.16);
}

/* No blur support (older Firefox): fall back to the solid pill. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){
  .nav,
  .nav.is-stuck{ background: var(--surface); }
  .nav::before{ opacity: 0.5; }
}

.nav__link{ transition: background-color 0.25s ease, color 0.25s ease; }
.nav__link:not(.is-current):hover{ background: rgba(0,0,0,0.06); }

.nav__link{
  position: relative;
  z-index: 1;
  display: block;
  font-size: calc(17.5 * var(--u));
  line-height: calc(17.5 * var(--u));
  font-weight: 400;
  padding: calc(7.5 * var(--u)) calc(27.8 * var(--u));
  border-radius: 999px;
  white-space: nowrap;
}

.nav__link.is-current{
  background: var(--ink);
  color: var(--paper);
}

/* Hamburger + panel: mobile only, hidden by default. */
.burger{ display: none; }
.mobile-menu{ display: none; }

/* ---------- Hero ---------- */

.hero{
  padding-top: calc(98 * var(--u));
  padding-bottom: calc(116 * var(--u));
}

.hero__title{
  text-align: center;
  font-size: calc(97 * var(--u));
  line-height: calc(108 * var(--u));
  font-weight: 700;
  letter-spacing: -0.015em;
}

/* ---------- Section furniture ---------- */

.section__head{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(24 * var(--u));
}

.section__label{
  font-size: calc(23.5 * var(--u));
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
}

.button{
  display: inline-flex;
  align-items: center;
  gap: calc(17 * var(--u));
  background: var(--surface);
  border-radius: 999px;
  padding: calc(18 * var(--u)) calc(50 * var(--u));
  font-size: calc(18 * var(--u));
  line-height: calc(14 * var(--u));
  white-space: nowrap;
}

.button__icon{
  width: calc(15 * var(--u));
  height: calc(15 * var(--u));
  flex: none;
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

.button{ transition: background-color 0.3s ease, color 0.3s ease; }

.button:hover,
.button:focus-visible{
  background: var(--ink);
  color: var(--paper);
}

.button:hover .button__icon,
.button:focus-visible .button__icon{ transform: translateX(5px); }

/* ---------- Card grids ---------- */

.grid{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: calc(24.5 * var(--u));
}

.card{ display: block; }

.card__media{
  display: block;
  overflow: hidden;
}

.card__image{ width: 100%; object-fit: cover; }

/* Hover: image grows inside its clipped box. */
.card__image{
  transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}

.card:hover .card__image,
.card:focus-visible .card__image{ transform: scale(1.03); }

.card__icon{ transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1); }

.section--work .card:hover .card__icon,
.section--work .card:focus-visible .card__icon{ transform: rotate(-45deg); }

/* Scroll-in reveal: fades up from nothing, gently. */
.js .reveal{
  opacity: 0;
  transform: translateY(28px);
  will-change: opacity, transform;
}

.js .reveal.is-in{
  opacity: 1;
  transform: none;
  will-change: auto;
  transition:
    opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1) var(--reveal-delay, 0ms),
    transform 0.9s cubic-bezier(0.22, 1, 0.36, 1) var(--reveal-delay, 0ms);
}

.card__image--work{ aspect-ratio: 4 / 5; }
.card__image--experience{ aspect-ratio: 1 / 1; }

.card__foot{
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: calc(16 * var(--u));
  margin-top: calc(21 * var(--u));
}

.card__text{ display: block; }

.card__title{
  display: block;
  font-size: calc(22 * var(--u));
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: calc(22 * var(--u));
}

.card__meta{
  display: block;
  margin-top: calc(8 * var(--u));
  font-size: calc(16.5 * var(--u));
  line-height: calc(21 * var(--u));
  text-transform: uppercase;
}

.card__icon{
  width: calc(18 * var(--u));
  height: calc(18 * var(--u));
  flex: none;
  margin-top: calc(2 * var(--u));
}

/* ---------- About ---------- */

.prose p{
  font-size: calc(33.5 * var(--u));
  line-height: calc(44 * var(--u));
  letter-spacing: -0.005em;
}

.prose p + p{ margin-top: calc(44 * var(--u)); }

.br-wide{ display: inline; }

/* Floating stage. Item coordinates are mockup px inside a 1280 x 690 box. */

.stage{
  position: relative;
  width: 100%;
  aspect-ratio: 1280 / 690;
}

.stage__portrait{
  position: absolute;
  left: 34.06%;
  top: -1.01%;
  width: 31.64%;
  height: auto;
}

.things{ position: absolute; inset: 0; }

/* Each .thing spans the whole stage, so pointer events are handed
   down to the icon and label themselves. */
.thing{ position: absolute; inset: 0; pointer-events: none; }
.thing__icon,
.thing__label{ pointer-events: auto; }

.thing__icon{
  position: absolute;
  left: calc(var(--ix) / 1280 * 100%);
  top: calc(var(--iy) / 690 * 100%);
  width: calc(var(--iw) / 1280 * 100%);
  height: auto;
}

/* Each icon drifts up into place on its own beat. --d is set in JS. */
.js .stage .thing__icon{
  opacity: 0;
  transform: translateY(calc(18 * var(--u))) scale(0.9);
}

.js .stage.is-in .thing__icon{
  opacity: 1;
  transform: none;
  transition:
    opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1) var(--d, 0ms),
    transform 0.85s cubic-bezier(0.34, 1.35, 0.5, 1) var(--d, 0ms);
}

.js .stage.is-in .stage__portrait{
  transition: opacity 0.8s ease, transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

.thing__label{
  position: absolute;
  left: calc(var(--lx) / 1280 * 100%);
  top: calc(var(--ly) / 690 * 100%);
  width: calc(102 / 1280 * 100%);
  height: calc(34 / 690 * 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ink);
  color: var(--paper);
  border-radius: 999px;
  font-size: calc(17.5 * var(--u));
  line-height: 1;
  white-space: nowrap;
}

.tagline{
  text-align: center;
  font-size: calc(34.6 * var(--u));
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
}

.tagline a{ --ul-h: calc(4 * var(--u)); --ul-b: calc(-8 * var(--u)); }

/* ---------- Vertical rhythm ---------- */

.section--work{ padding-bottom: calc(90 * var(--u)); }
.section--work .section__head{ margin-bottom: calc(42 * var(--u)); }

.rule--one{ margin-bottom: calc(90 * var(--u)); }

.section--about .stage{ margin-top: calc(22 * var(--u)); }
.section--about .tagline{ margin-top: calc(46 * var(--u)); }
.section--about{ padding-bottom: calc(88 * var(--u)); }

.rule--two{ margin-bottom: calc(93 * var(--u)); }

.section--experience .section__label{ margin-bottom: calc(47 * var(--u)); }
.section--experience{ padding-bottom: calc(97 * var(--u)); }

/* ---------- Footer ---------- */

.footer{
  background: var(--ink);
  color: var(--paper);
  padding-top: calc(100 * var(--u));
  padding-bottom: calc(141 * var(--u));
}

.footer__inner{
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: calc(32 * var(--u));
}

.footer__nav{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(30 * var(--u));
  font-size: calc(23.5 * var(--u));
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: calc(17 * var(--u));
}

.footer__nav--right{ text-align: right; align-items: flex-end; }

.footer__nav--right a{ --ul-h: calc(2 * var(--u)); --ul-b: calc(-6 * var(--u)); }

/* Desktop only: labels stay hidden until you hover an icon.
   The .thing box spans the whole stage, so pointer events are
   handed down to the icon and label themselves. */
@media (min-width: 761px){

  .thing__icon{
    transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  }

  .thing__icon:hover{ transform: scale(1.09); }

  .thing__label{
    opacity: 0;
    transform: translateY(5px) scale(0.94);
    transition: opacity 0.25s ease, transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  }

  .thing__icon:hover + .thing__label,
  .thing__label:hover{
    opacity: 1;
    transform: none;
  }
}

/* Auto-tour: one label at a time, in a random order, so the icons
   explain themselves without waiting to be hovered. Hovering wins —
   the tour pauses and hands over. */
.thing.is-showing .thing__label{
  opacity: 1;
  transform: none;
}

.stage.is-touched .thing.is-showing .thing__label{
  opacity: 0;
}

/* ===========================================================
   Tablet — proportional desktop layout gets too tight below
   ~1024px, so drop to two columns and a smaller scale.
   =========================================================== */

@media (min-width: 761px) and (max-width: 1023px){

  :root{ --u: 0.62px; }

  .container{ padding-inline: 40px; }

  .grid{ grid-template-columns: repeat(2, 1fr); gap: calc(30 * var(--u)); }

  .hero{ padding-top: calc(80 * var(--u)); padding-bottom: calc(100 * var(--u)); }

  .section--about .stage{ margin-top: calc(60 * var(--u)); }
}

/* ===========================================================
   Mobile — no mockup supplied yet, so this is a first pass.
   ===========================================================*/

@media (max-width: 760px){

  :root{ --u: 1px; }

  .container{ padding-inline: 16px; }

  .header__inner{
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    padding-top: 20px;
    padding-bottom: 20px;
  }

  .logo{ font-size: 30px; }

  /* Pill nav is desktop only. */
  .nav{ display: none; }

  .burger{
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 7px;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    align-items: flex-end;
  }

  .burger__bar{
    display: block;
    width: 26px;
    height: 2px;
    background: var(--ink);
    border-radius: 2px;
  }

  .burger[aria-expanded="true"] .burger__bar:first-child{
    transform: translateY(4.5px) rotate(45deg);
  }
  .burger[aria-expanded="true"] .burger__bar:last-child{
    transform: translateY(-4.5px) rotate(-45deg);
  }

  /* Panel drops in below the header and fills the rest of the screen. */
  .mobile-menu{
    display: block;
    position: fixed;
    inset: 84px 0 0;
    z-index: 40;
    background: var(--paper);
    padding: 24px 16px 40px;
    overflow-y: auto;
  }

  .mobile-menu[hidden]{ display: none; }

  .mobile-menu__nav{
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }

  .mobile-menu__nav a{
    font-size: 40px;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.3;
  }

  .mobile-menu__nav a.is-current{ opacity: 0.35; }

  .mobile-menu__meta{
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    margin-top: 40px;
    padding-top: 28px;
    border-top: 2px solid var(--surface);
    font-size: 16px;
  }

  .mobile-menu__meta a{ --ul-h: 1.5px; --ul-b: -4px; }

  /* Header stays put while the panel is open. */
  html.menu-open{ overflow: hidden; }
  html.menu-open .header{
    position: fixed;
    inset: 0 0 auto;
    z-index: 50;
    background: var(--paper);
  }
  html.menu-open body{ padding-top: 84px; }

  .hero{ padding-top: 48px; padding-bottom: 64px; }
  .hero__title{ font-size: 34px; line-height: 40px; letter-spacing: -0.01em; }

  .section__head{ gap: 16px; }
  .section--work .section__head{ margin-bottom: 24px; }
  .section--work{ padding-bottom: 56px; }
  .section__label{ font-size: 18px; }

  .button{ font-size: 15px; line-height: 15px; padding: 13px 20px; gap: 10px; }
  .button__icon{ width: 14px; height: 14px; }

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

  .card__foot{ margin-top: 14px; }
  .card__title{ font-size: 20px; line-height: 24px; }
  .card__meta{ font-size: 14px; line-height: 20px; margin-top: 6px; }
  .card__icon{ width: 16px; height: 16px; }

  .rule--one{ margin-bottom: 48px; }
  .rule--two{ margin-bottom: 48px; }

  .prose p{ font-size: 18px; line-height: 28px; }
  .prose p + p{ margin-top: 24px; }
  .prose .br-wide{ display: none; }

  /* Stage keeps the desktop's floating composition, recomposed for a
     portrait canvas: coordinates are mockup px inside a 343 x 620 box. */
  /* Full-bleed square stage, plotted from the 375 x 375 artboard. */
  .section--about .stage{
    aspect-ratio: 1 / 1;
    margin-top: 28px;
    width: 100vw;
    max-width: 440px;
    margin-left: 50%;
    transform: translateX(-50%);
  }

  .stage__portrait{
    left: 26.27%;
    top: 5.87%;
    width: 48%;
  }

  .thing__icon{
    left: calc(var(--mx) / 375 * 100%);
    top: calc(var(--my) / 375 * 100%);
    width: calc(var(--mw) / 375 * 100%);
    cursor: pointer;
  }

  /* Tags are revealed by tapping an icon — there's no hover on a phone,
     and the artboard has no room for twelve permanent pills. */
  .thing__label{
    left: calc(var(--mcx) / 375 * 100%);
    top: calc(var(--mly) / 375 * 100%);
    width: auto;
    height: auto;
    padding: 0 9px;
    min-height: 21px;
    font-size: clamp(11px, 3.1vw, 13px);
    opacity: 0;
    transform: translateX(-50%) translateY(4px) scale(0.94);
    transition: opacity 0.2s ease, transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
  }

  .thing.is-open .thing__label{
    opacity: 1;
    transform: translateX(-50%);
  }

  .thing.is-open .thing__icon{ transform: scale(1.06); }
  .thing__icon{ transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1); }

  .section--about .tagline{ margin-top: 32px; }
  .section--about{ padding-bottom: 48px; }
  .tagline{ font-size: 20px; }
  .tagline a{ --ul-h: 2px; --ul-b: -4px; }

  .section--experience .section__label{ margin-bottom: 24px; }
  .section--experience{ padding-bottom: 56px; }

  .footer{ padding-top: 48px; padding-bottom: 48px; }
  .footer__inner{ flex-direction: column; gap: 32px; }
  .footer__nav{ font-size: 18px; line-height: 18px; gap: 16px; }
  .footer__nav--right{ text-align: left; align-items: flex-start; }
}


/* ===========================================================
   Respect reduced-motion preferences.
   =========================================================== */

@media (prefers-reduced-motion: reduce){
  *,
  *::before,
  *::after{
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .js .reveal{
    opacity: 1;
    transform: none;
  }

  .js .hero__title .char{ opacity: 1 !important; }
  .js .hero__caret{ display: none !important; }
}

/* ===========================================================
   Work page
   Measured from Work_Desktop.jpg (1440 canvas, 1280 container).
   =========================================================== */

.section--intro{
  padding-top: calc(103 * var(--u));
  padding-bottom: calc(94 * var(--u));
}

/* Full-width BAVE feature */

.feature{ display: block; }

.feature__media{
  display: block;
  overflow: hidden;
}

.feature__image{
  width: 100%;
  height: auto;
  aspect-ratio: 1920 / 750;
  object-fit: cover;
  transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}

.feature:hover .feature__image,
.feature:focus-visible .feature__image{ transform: scale(1.012); }

.feature__foot{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(24 * var(--u));
  margin-top: calc(21 * var(--u));
}

/* The Expand pill is a span inside the card link, so it inherits
   the card's hover rather than owning one. */
.feature:hover .button,
.feature:focus-visible .button{
  background: var(--ink);
  color: var(--paper);
}

.feature:hover .button__icon,
.feature:focus-visible .button__icon{ transform: translateX(5px); }

/* The Expand pill matches the mockup's 210px width */
.feature__foot .button{ padding-inline: calc(58 * var(--u)); }

.section--feature{ padding-bottom: calc(49 * var(--u)); }

/* Grid wraps to a second row */

.grid--wrap{ row-gap: calc(46 * var(--u)); }

.section--grid{ padding-bottom: calc(97 * var(--u)); }

@media (min-width: 761px) and (max-width: 1023px){
  .grid--wrap{ row-gap: calc(40 * var(--u)); }
  .section--intro{ padding-top: calc(80 * var(--u)); padding-bottom: calc(60 * var(--u)); }
}

@media (max-width: 760px){
  .section--intro{ padding-top: 40px; padding-bottom: 40px; }

  .feature__foot{
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 14px;
  }

  .feature__foot .card__text{ min-width: 0; }
  .feature__foot .button{ flex: none; }

  .section--feature{ padding-bottom: 40px; }
  .feature__foot .button{ padding-inline: 24px; }
  .grid--wrap{ row-gap: 40px; }
  .section--grid{ padding-bottom: 56px; }
}


/* ===========================================================
   Text links — the underline retracts to the right and redraws
   from the left on hover. Sitewide.
   =========================================================== */

.footer__nav a,
.tagline a,
.mobile-menu__nav a,
.mobile-menu__meta a,
.contact__links a,
.project-meta__links a{
  --ul-h: calc(2 * var(--u));
  --ul-b: calc(-6 * var(--u));
  --ul-rest: 1;
  position: relative;
  display: inline-block;
  text-decoration: none;
}

.footer__nav a::before,      .footer__nav a::after,
.tagline a::before,          .tagline a::after,
.mobile-menu__nav a::before, .mobile-menu__nav a::after,
.mobile-menu__meta a::before,.mobile-menu__meta a::after,
.contact__links a::before,   .contact__links a::after,
.project-meta__links a::before, .project-meta__links a::after{
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--ul-b);
  height: var(--ul-h);
  background: currentColor;
  pointer-events: none;
}

/* Resting underline — retracts rightward once the incoming one has gone */
.footer__nav a::before,
.tagline a::before,
.mobile-menu__nav a::before,
.mobile-menu__meta a::before,
.contact__links a::before,
.project-meta__links a::before{
  transform: scaleX(var(--ul-rest));
  transform-origin: right;
  transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0.24s;
}

/* Incoming underline — draws in from the left once the first has cleared */
.footer__nav a::after,
.tagline a::after,
.mobile-menu__nav a::after,
.mobile-menu__meta a::after,
.contact__links a::after,
.project-meta__links a::after{
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
}

.footer__nav a:hover::before,       .footer__nav a:focus-visible::before,
.tagline a:hover::before,           .tagline a:focus-visible::before,
.mobile-menu__nav a:hover::before,  .mobile-menu__nav a:focus-visible::before,
.mobile-menu__meta a:hover::before, .mobile-menu__meta a:focus-visible::before,
.contact__links a:hover::before,    .contact__links a:focus-visible::before,
.project-meta__links a:hover::before, .project-meta__links a:focus-visible::before{
  transform: scaleX(0);
  transition-delay: 0s;
}

.footer__nav a:hover::after,       .footer__nav a:focus-visible::after,
.tagline a:hover::after,           .tagline a:focus-visible::after,
.mobile-menu__nav a:hover::after,  .mobile-menu__nav a:focus-visible::after,
.mobile-menu__meta a:hover::after, .mobile-menu__meta a:focus-visible::after,
.contact__links a:hover::after,    .contact__links a:focus-visible::after,
.project-meta__links a:hover::after, .project-meta__links a:focus-visible::after{
  transform: scaleX(1);
  transition-delay: 0.24s;
}

/* Links with no underline at rest just draw one in, no wait */
.footer__nav:not(.footer__nav--right) a,
.mobile-menu__nav a{ --ul-rest: 0; }

/* Stacked links sit close together, so the rule rides tight to the text. */
.project-meta__links a{
  --ul-h: calc(1.5 * var(--u));
  --ul-b: calc(-2 * var(--u));
}

.footer__nav:not(.footer__nav--right) a:hover::after,
.footer__nav:not(.footer__nav--right) a:focus-visible::after,
.mobile-menu__nav a:hover::after,
.mobile-menu__nav a:focus-visible::after{ transition-delay: 0s; }

/* ===========================================================
   Contact page
   Measured from Contact.jpg (1440 canvas).
   =========================================================== */

.contact__links{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(44 * var(--u));
  margin-top: calc(56 * var(--u));
  font-size: calc(33.5 * var(--u));
  line-height: calc(44 * var(--u));
}

.section--contact{ padding-bottom: calc(102 * var(--u)); }

@media (max-width: 760px){
  .contact__links{
    margin-top: 32px;
    gap: 24px;
    font-size: 18px;
    line-height: 26px;
  }
  .contact__links a{ --ul-h: 1.5px; --ul-b: -5px; }
  .section--contact{ padding-bottom: 48px; }
}


/* ===========================================================
   Hero: typed in one character at a time.
   Every character is in the DOM from the start at zero opacity,
   so nothing reflows as it types.
   =========================================================== */

.hero__title{ position: relative; }

.js .hero__title .char{ opacity: 0; }
.js .hero__title .char.is-shown{ opacity: 1; }

.hero__caret{
  position: absolute;
  width: calc(5 * var(--u));
  background: var(--ink);
  pointer-events: none;
  animation: caret-blink 1s steps(1, end) infinite;
}

.hero__caret[hidden]{ display: none; }

@keyframes caret-blink{
  0%, 50%   { opacity: 1; }
  50.01%, 100%{ opacity: 0; }
}

@media (max-width: 760px){
  .hero__caret{ width: 2px; }
}

/* ===========================================================
   Project detail page
   Measured from Work_Detail_Desktop.jpg: 300px sidebar, 24px gap,
   956px media column inside the 1280 container.
   =========================================================== */

.detail__layout{
  display: grid;
  grid-template-columns: calc(300 * var(--u)) calc(956 * var(--u));
  gap: calc(24 * var(--u));
  padding-top: calc(121 * var(--u));
}

/* --- Sidebar --------------------------------------------------------- */

.detail__sticky{
  position: sticky;
  top: calc(132 * var(--u));
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 200 * var(--u));
}

.project-meta__title{
  font-size: calc(20 * var(--u));
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: calc(24 * var(--u));
}

.project-meta__role{
  margin-top: calc(2 * var(--u));
  font-size: calc(16.5 * var(--u));
  line-height: calc(21 * var(--u));
  text-transform: uppercase;
}

.project-meta__links{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(5 * var(--u));
  margin-top: calc(40 * var(--u));
  font-size: calc(16.5 * var(--u));
  line-height: calc(20 * var(--u));
}


/* The rail holds one description per chapter, stacked and crossfaded. */

.chapter-rail{
  position: relative;
  margin-top: auto;          /* sits low in the sticky panel, as in the mockup */
  padding-bottom: calc(24 * var(--u));
}

.chapter-rail__item{
  position: absolute;
  inset: 0 0 auto;
  opacity: 0;
  /* --exit is set in JS so copy always leaves the way you're scrolling
     and the next block arrives from the opposite side. */
  transform: translateY(var(--exit, 22px));
  filter: blur(5px);
  transition:
    opacity 0.45s cubic-bezier(0.32, 0.08, 0.24, 1),
    transform 0.62s cubic-bezier(0.22, 1, 0.36, 1),
    filter 0.45s ease;
  pointer-events: none;
}

.chapter-rail__item.is-active{
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}

/* Label leads, copy follows a beat behind. */
.chapter-rail__item .chapter__label{
  transition: inherit;
}

.chapter-rail__item .chapter__copy{
  opacity: 0;
  transform: translateY(var(--exit-copy, 14px));
  transition:
    opacity 0.45s cubic-bezier(0.32, 0.08, 0.24, 1) 0.08s,
    transform 0.62s cubic-bezier(0.22, 1, 0.36, 1) 0.08s;
}

.chapter-rail__item.is-active .chapter__copy{
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce){
  .chapter-rail__item,
  .chapter-rail__item .chapter__copy{
    transform: none !important;
    filter: none !important;
  }
}

.chapter__label{
  font-size: calc(16.5 * var(--u));
  font-weight: 700;
  line-height: calc(20 * var(--u));
  text-transform: uppercase;
  letter-spacing: 0.01em;
}

.chapter__copy{
  margin-top: calc(22 * var(--u));
  font-size: calc(13.5 * var(--u));
  line-height: calc(17 * var(--u));
}

/* --- Media column ---------------------------------------------------- */

.chapter + .chapter{ margin-top: calc(40 * var(--u)); }

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

.media{ display: block; }
.media img,
.media__video{
  display: block;
  width: 100%;
  height: auto;
}

/* Belt and braces: if a browser won't derive the ratio from the width/height
   attributes, the box still holds its shape instead of collapsing. */
.media__video{ background: #F7F7F7; }
.media__video[width="1920"]{ aspect-ratio: 16 / 9; }
.media__video[width="1080"]{ aspect-ratio: 1 / 1; }

/* Desktop: the copy lives in the sidebar rail, so hide the in-flow
   version visually but keep it for screen readers and for cloning. */
@media (min-width: 761px){
  .chapter__text{
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    border: 0;
  }
}

/* --- Social wall ----------------------------------------------------- */

.wall{
  column-count: 3;
  column-gap: calc(16 * var(--u));
  background: #F7F7F7;
  padding: calc(70 * var(--u)) calc(61 * var(--u));
}

.wall__item{
  break-inside: avoid;
  margin-bottom: calc(16 * var(--u));
}

.reel{ display: block; }

.wall__tile{
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  overflow: hidden;
}

.wall__tile img{
  display: block;
  width: 100%;
  height: auto;
}

.wall__play{
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(56 * var(--u));
  height: calc(56 * var(--u));
  margin: calc(-28 * var(--u)) 0 0 calc(-28 * var(--u));
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.35);
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), background-color 0.3s ease;
}

.wall__play::after{
  content: "";
  position: absolute;
  left: 54%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: calc(9 * var(--u)) 0 calc(9 * var(--u)) calc(15 * var(--u));
  border-color: transparent transparent transparent #fff;
}

.wall__tile--video:hover .wall__play,
.wall__tile--video:focus-visible .wall__play{
  transform: scale(1.08);
  background: rgba(0, 0, 0, 0.72);
}

.wall__tile--placeholder{
  position: relative;
  aspect-ratio: 1206 / 1950;
  background: #EAE8E8;
  border: calc(2 * var(--u)) dashed #C8C4C4;
  cursor: default;
}

.wall__tile--placeholder .wall__play{ background: rgba(0,0,0,0.25); }

.wall__placeholder-label{
  position: absolute;
  left: 0;
  right: 0;
  top: calc(50% + 40 * var(--u));
  text-align: center;
  font-size: calc(14 * var(--u));
  color: #8C8888;
}

/* --- Bottom navigation ----------------------------------------------- */

.detail__foot{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(24 * var(--u));
  padding-top: calc(48 * var(--u));
  padding-bottom: calc(99 * var(--u));
}

.button--back .button__icon{ transform: scaleX(-1); }

.button--back:hover .button__icon,
.button--back:focus-visible .button__icon{ transform: scaleX(-1) translateX(5px); }

/* --- Lightbox -------------------------------------------------------- */

.lightbox{
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(20px, 4vw, 56px);
  background: rgba(0, 0, 0, 0.88);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.lightbox[hidden]{ display: none; }
.lightbox.is-open{ opacity: 1; }

.lightbox__stage{
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 100%;
  max-height: 100%;
}

.lightbox__stage img,
.lightbox__stage video{
  display: block;
  max-width: min(100%, 820px);
  max-height: 88vh;
  width: auto;
  height: auto;
}

.lightbox__close{
  position: absolute;
  top: clamp(14px, 2vw, 28px);
  right: clamp(14px, 2vw, 28px);
  width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.25s ease;
}

.lightbox__close:hover{ background: rgba(255, 255, 255, 0.28); }

html.lightbox-open{ overflow: hidden; }

/* --- Tablet / mobile -------------------------------------------------- */

@media (min-width: 761px) and (max-width: 1023px){
  .detail__layout{
    grid-template-columns: calc(260 * var(--u)) 1fr;
    padding-top: calc(80 * var(--u));
  }
}

@media (max-width: 760px){
  .detail__layout{
    display: block;
    padding-top: 24px;
  }

  .detail__sticky{
    position: static;
    display: block;
    min-height: 0;          /* the sticky panel reserved a screen's worth of height */
  }
  .chapter-rail{ display: none; }

  .project-meta__title{ font-size: 20px; line-height: 24px; }
  .project-meta__role{ font-size: 14px; line-height: 19px; }
  .project-meta__links{ margin-top: 16px; font-size: 14px; line-height: 22px; }

  .detail__main{ margin-top: 20px; }

  .chapter + .chapter{ margin-top: 48px; }

  /* Caption under the work, not a wall of copy before it. */
  .chapter{
    display: flex;
    flex-direction: column;
  }

  .chapter__media{ order: 1; }

  .chapter__text{
    order: 2;
    margin-top: 14px;
  }

  .chapter__label{
    font-size: 13px;
    line-height: 18px;
    letter-spacing: 0.05em;
  }

  .chapter__copy{
    margin-top: 8px;
    font-size: 14.5px;
    line-height: 21px;
    max-width: 46ch;
  }

  .wall{ column-count: 2; column-gap: 10px; padding: 16px; }
  .wall__item{ margin-bottom: 10px; }
  .wall__play{ width: 40px; height: 40px; margin: -20px 0 0 -20px; }
  .wall__play::after{ border-width: 7px 0 7px 11px; }
  .wall__placeholder-label{ top: calc(50% + 30px); font-size: 12px; }

  .detail__foot{
    padding-top: 32px;
    padding-bottom: 48px;
    gap: 12px;
  }
  .detail__foot .button{ padding-inline: 20px; font-size: 15px; line-height: 15px; }
}

/* --- Social wall: JS masonry, CSS columns as the no-JS fallback ------- */

.wall--js{
  column-count: auto;
  display: flex;
  align-items: flex-start;
  gap: calc(16 * var(--u));
}

.wall__col{
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: calc(16 * var(--u));
}

.wall--js .wall__item{ margin-bottom: 0; }

/* --- Embedded video (YouTube) ---------------------------------------- */

.embed{
  position: relative;
  display: block;
  width: 100%;
  background: #0E0D0D;
  overflow: hidden;
}

.embed--16x9{ aspect-ratio: 16 / 9; }
.embed--teal{ background: #72B6B4; }
.embed--1x1{ aspect-ratio: 1 / 1; }
.embed--9x16{ aspect-ratio: 9 / 16; }

.embed iframe,
.embed wistia-player{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* Before the Wistia component upgrades, the blurred swatch stands in. */
.embed wistia-player:not(:defined){ background-size: cover; }

/* Blocks the hover title bar and clicks on the decorative loop. */
.embed__shield{
  position: absolute;
  inset: 0;
  z-index: 2;
  cursor: default;
}

.embed iframe{ z-index: 1; }

/* --- Vertical video band --------------------------------------------- */

.reel-band{
  padding: calc(57 * var(--u)) calc(50 * var(--u));
  background: var(--ink);
}

.reel-band__inner{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: calc(30 * var(--u));
}

.reel__tile{
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 9 / 16;
  padding: 0;
  border: 0;
  background: #141313;
  cursor: pointer;
  overflow: hidden;
}

.reel__poster{
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.reel__tile:hover .wall__play,
.reel__tile:focus-visible .wall__play{
  transform: scale(1.08);
  background: rgba(0, 0, 0, 0.72);
}

.reel__tile--placeholder{
  background: #1B1919;
  border: calc(2 * var(--u)) dashed #3C3838;
  cursor: default;
}

.reel__tile--placeholder .wall__play{ background: rgba(255, 255, 255, 0.10); }
.reel__tile--placeholder .wall__placeholder-label{ color: #7E7A7A; }

@media (max-width: 760px){
  .reel-band{ padding: 16px; }
  .reel-band__inner{ gap: 10px; }
}
/* Present for screen readers, invisible on screen. */
.visually-hidden{
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  border: 0;
  white-space: nowrap;
}

/* ===========================================================
   Link underline overrides.
   These sit after the shared text-link block above, which would
   otherwise flatten every context back to 2px / -6px.
   =========================================================== */

.tagline a{
  --ul-h: calc(4 * var(--u));
  --ul-b: calc(-8 * var(--u));
}

@media (max-width: 760px){
  .tagline a{ --ul-h: 2px; --ul-b: -2px; }
  .mobile-menu__meta a{ --ul-h: 1.5px; --ul-b: -4px; }
  .footer__nav--right a{ --ul-h: 1.5px; --ul-b: -4px; }
}

/* The About stage is centred with a transform, which the reveal's
   `transform: none` would otherwise cancel — pushing it off-screen.
   Both states carry the centring explicitly. */

@media (max-width: 760px){
  .section--about .stage{ transform: translate(-50%, 28px); }
  .js .section--about .stage.is-in{ transform: translate(-50%, 0); }
  .section--about .stage:not(.reveal){ transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce){
  @media (max-width: 760px){
    .js .section--about .stage,
    .js .section--about .stage.is-in{ transform: translate(-50%, 0) !important; }
  }
}

/* Small phones: the two project-nav pills don't fit side by side. */
@media (max-width: 380px){
  .detail__foot{ flex-wrap: wrap; }
  .detail__foot .button{ padding-inline: 14px; font-size: 14px; gap: 8px; }
}

/* --- Art direction grid (Medici) -------------------------------------- */

.artgrid{
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: calc(16 * var(--u));
}

.artgrid img{
  display: block;
  width: 100%;
  height: auto;
}

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

/* The photography reel sits in the grid like one of the stills. */
.artgrid__reel{
  position: relative;
  aspect-ratio: 9 / 16;
  background: #141313;
  overflow: hidden;
}

.artgrid__reel wistia-player{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.artgrid__reel wistia-player:not(:defined){ background-size: cover; }

/* Two reels side by side rather than three (M&S) */
.reel-band__inner--pair{ grid-template-columns: repeat(2, 1fr); }

/* The feature image on the work overview switches to a portrait crop on mobile */
.feature__media picture{ display: block; }

@media (max-width: 760px){
  .feature__image{ aspect-ratio: 4 / 5; }
  .artgrid{ gap: 10px; }

  .reel-band__inner--pair{ grid-template-columns: repeat(2, 1fr); }
}

/* Wistia renders its player with rounded corners by default; the design
   wants it flush inside its block. */
wistia-player{
  --wistia-player-border-radius: 0;
  border-radius: 0 !important;
  overflow: hidden;
}

/* Very small phones can't take the designed hero break — it fragments
   into four lines. Let it wrap naturally there instead. */
@media (max-width: 360px){
  .hero__title{ font-size: 30px; line-height: 36px; }
  .hero__title .br-wide{ display: none; }
}

/* On mobile the label is centred on its coordinate with translateX(-50%).
   The auto-tour's `transform: none` would cancel that and shove each pill
   half its own width to the right, so restore it here. */
@media (max-width: 760px){
  .thing.is-showing .thing__label{ transform: translateX(-50%); }
}

/* Contact links carry the weight of the page — set them bold. */
.contact__links a{ font-weight: 700; }
