/* ---------------------------------------------------------
   Joel Tesfai — landing page
   Fonts: Dolce Vita (titles), Clash Display (longer text),
   New Title (bigger short text)
--------------------------------------------------------- */

@font-face {
  font-family: "Dolce Vita";
  src: url("../assets/fonts/Dolce Vita Light.ttf") format("truetype");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Dolce Vita";
  src: url("../assets/fonts/Dolce Vita.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Dolce Vita";
  src: url("../assets/fonts/Dolce Vita Heavy Bold.ttf") format("truetype");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Clash Display";
  src: url("../assets/fonts/ClashDisplay-Extralight.woff2") format("woff2"),
       url("../assets/fonts/ClashDisplay-Extralight.woff") format("woff");
  font-weight: 200;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Clash Display";
  src: url("../assets/fonts/ClashDisplay-Light.woff2") format("woff2"),
       url("../assets/fonts/ClashDisplay-Light.woff") format("woff");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Clash Display";
  src: url("../assets/fonts/ClashDisplay-Regular.woff2") format("woff2"),
       url("../assets/fonts/ClashDisplay-Regular.woff") format("woff");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Clash Display";
  src: url("../assets/fonts/ClashDisplay-Medium.woff2") format("woff2"),
       url("../assets/fonts/ClashDisplay-Medium.woff") format("woff");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Clash Display";
  src: url("../assets/fonts/ClashDisplay-Semibold.woff2") format("woff2"),
       url("../assets/fonts/ClashDisplay-Semibold.woff") format("woff");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Clash Display";
  src: url("../assets/fonts/ClashDisplay-Bold.woff2") format("woff2"),
       url("../assets/fonts/ClashDisplay-Bold.woff") format("woff");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "New Title";
  src: url("../assets/fonts/NewTitle-Extralight.woff2") format("woff2"),
       url("../assets/fonts/NewTitle-Extralight.woff") format("woff");
  font-weight: 200;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "New Title";
  src: url("../assets/fonts/NewTitle-Light.woff2") format("woff2"),
       url("../assets/fonts/NewTitle-Light.woff") format("woff");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "New Title";
  src: url("../assets/fonts/NewTitle-Regular.woff2") format("woff2"),
       url("../assets/fonts/NewTitle-Regular.woff") format("woff");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "New Title";
  src: url("../assets/fonts/NewTitle-Medium.woff2") format("woff2"),
       url("../assets/fonts/NewTitle-Medium.woff") format("woff");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "New Title";
  src: url("../assets/fonts/NewTitle-Bold.woff2") format("woff2"),
       url("../assets/fonts/NewTitle-Bold.woff") format("woff");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #0a0a0a;
  --fg: #f5f4f0;
  --fg-dim: rgba(245, 244, 240, 0.62);
  --fg-faint: rgba(245, 244, 240, 0.36);
  --line: rgba(245, 244, 240, 0.18);
  --header-h: 96px;
  --edge: clamp(20px, 4vw, 56px);
  --dur-fast: 200ms;
  --dur-med: 400ms;
  --ease: cubic-bezier(.22, .61, .36, 1);
}

* { box-sizing: border-box; }

html {
  background: var(--bg);
  scrollbar-width: none;
}
html::-webkit-scrollbar { display: none; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: "Dolce Vita", "Helvetica Neue", Arial, sans-serif;
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

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

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

button {
  font-family: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}

/* ---------------- Scroller / sections ---------------- */

.scroller {
  height: 100dvh;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
}

.section {
  position: relative;
  height: 100dvh;
  width: 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  background: #000;
  isolation: isolate;
}

.section__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  filter: grayscale(0.15) contrast(1.04);
}

/* Same full-bleed treatment as .section__video, for the rare category tile
   backed by a still (no source footage exists yet for that project). */
.section__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  filter: grayscale(0.15) contrast(1.04);
}
.section--linkable .section__image { transition: transform 700ms var(--ease); }
.section--linkable:hover .section__image { transform: scale(1.035); }

.section__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, rgba(0,0,0,.78) 0%, rgba(0,0,0,.15) 32%, rgba(0,0,0,.05) 55%, rgba(0,0,0,.35) 100%);
  pointer-events: none;
}

.section--hero .section__scrim {
  background:
    linear-gradient(to top, rgba(0,0,0,.7) 0%, rgba(0,0,0,.25) 40%, rgba(0,0,0,.15) 60%, rgba(0,0,0,.55) 100%);
}

/* ---------------- Fixed header ---------------- */

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--edge);
  z-index: 60;
  pointer-events: none;
}

.site-header .logo,
.site-header .menu-toggle {
  pointer-events: auto;
}

.logo img {
  height: 22px;
  width: auto;
  opacity: 0.96;
  transition: opacity var(--dur-fast) var(--ease);
}
.logo:hover img { opacity: 0.7; }

.menu-toggle {
  display: flex;
  align-items: center;
  gap: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: 12px;
  font-weight: 400;
}

.menu-toggle__icon {
  display: inline-flex;
  flex-direction: column;
  gap: 5px;
  width: 22px;
}
.menu-toggle__icon span {
  display: block;
  height: 1px;
  width: 100%;
  background: currentColor;
  transition: transform var(--dur-med) var(--ease), opacity var(--dur-med) var(--ease);
}
.menu-toggle[aria-expanded="true"] .menu-toggle__icon span:first-child {
  transform: translateY(3px) rotate(45deg);
}
.menu-toggle[aria-expanded="true"] .menu-toggle__icon span:last-child {
  transform: translateY(-3px) rotate(-45deg);
}

/* ---------------- Full-screen nav overlay ---------------- */

.site-nav {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(8, 8, 8, 0.98);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--dur-med) var(--ease), visibility 0s linear var(--dur-med);
}
.site-nav.is-open {
  visibility: visible;
  opacity: 1;
  transition: opacity var(--dur-med) var(--ease);
}

.site-nav__inner {
  max-width: 720px;
  margin: 0 auto;
  height: 100%;
  padding: calc(var(--header-h) + 24px) var(--edge) 48px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 48px;
}

.site-nav__links {
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-nav__links li + li { margin-top: 6px; }

.site-nav__links a {
  display: flex;
  align-items: baseline;
  gap: 18px;
  font-size: clamp(28px, 6vw, 46px);
  font-weight: 400;
  letter-spacing: 0.01em;
  padding: 10px 0;
  color: var(--fg-dim);
  transition: color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
  opacity: 0;
  transform: translateY(14px);
}
.site-nav.is-open .site-nav__links a {
  opacity: 1;
  transform: translateY(0);
  transition: color var(--dur-fast) var(--ease), opacity var(--dur-med) var(--ease), transform var(--dur-med) var(--ease);
}
.site-nav__links a span {
  font-size: 13px;
  font-weight: 300;
  letter-spacing: 0.1em;
  color: var(--fg-faint);
  min-width: 22px;
}
.site-nav__links a:hover,
.site-nav__links a:focus-visible {
  color: var(--fg);
  transform: translateX(6px);
}

.site-nav__footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 20px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

.site-nav__group { display: flex; gap: 22px; flex-wrap: wrap; }

.site-nav__pill,
.site-nav__social a {
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-dim);
  transition: color var(--dur-fast) var(--ease);
}
.site-nav__pill:hover,
.site-nav__social a:hover { color: var(--fg); }

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

.section__content {
  position: relative;
  z-index: 5;
  padding: calc(var(--header-h) + 24px) var(--edge) 96px;
}

.hero__kicker {
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0 0 18px;
}

.hero__tagline {
  font-family: "Clash Display", sans-serif;
  font-weight: 200;
  font-size: clamp(17px, 2.5vw, 34px);
  line-height: 1.4;
  max-width: min(880px, 84vw);
  margin: 0;
  letter-spacing: 0.005em;
}

.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 32px;
  transform: translateX(-50%);
  z-index: 6;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  color: var(--fg-dim);
}
.scroll-cue__label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
/* Two small key glyphs with up/down chevrons — a quiet hint that arrow-key
   navigation works too, without spelling it out in words. */
.scroll-cue__keys {
  width: 26px;
  height: 13px;
  flex: none;
  opacity: 0.85;
}
.scroll-cue i {
  display: block;
  width: 1px;
  height: 34px;
  background: linear-gradient(to bottom, var(--fg-dim), transparent);
  position: relative;
  overflow: hidden;
}
.scroll-cue i::after {
  content: "";
  position: absolute;
  left: 0; top: -100%;
  width: 100%; height: 100%;
  background: var(--fg);
  animation: cue-drip 1.8s ease-in-out infinite;
}
@keyframes cue-drip {
  0%   { top: -100%; }
  60%  { top: 100%; }
  100% { top: 100%; }
}
.scroll-cue:hover { color: var(--fg); }

@media (prefers-reduced-motion: reduce) {
  .scroll-cue i::after { animation: none; top: 0; }
}

/* ---------------- Category section big title ---------------- */

/* Centered, decorative restatement of the category name (the real heading is
   .section__title below). Sized with vw + a conservative ch-based cap so the
   longest label ("Fashion Projects") never touches the frame edge on any
   viewport — clamp handles the scaling, the horizontal padding is the hard
   backstop, and wrapping (rather than nowrap) is the final safety net if a
   viewport is narrower than the text at its minimum size. */
.section__big-title {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0 var(--edge);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  pointer-events: none;
}
.section__big-title span {
  display: inline-block;
  max-width: 100%;
  font-family: "Dolce Vita", sans-serif;
  font-weight: 800;
  text-transform: uppercase;
  line-height: 0.95;
  letter-spacing: -0.01em;
  color: #fff;
  font-size: clamp(34px, 11vw, 210px);
  text-wrap: balance;
  text-shadow: 0 10px 46px rgba(0, 0, 0, 0.5), 0 2px 12px rgba(0, 0, 0, 0.4);
  /* The wrapping .section__big-title is pointer-events: none (it spans the
     whole frame), but the span itself opts back in — so only the rendered
     glyphs are hoverable, not the full-bleed box around them. Clicks still
     bubble up fine to the [data-goto] handler on .section. */
  pointer-events: auto;
  transition: text-shadow var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}

/* Hovering the title itself (not just anywhere in the section) switches it
   to the same difference-blend trick as the CTA heading — it flips to read
   as the exact inverse of whatever's playing underneath, instead of staying
   a flat white with a drop shadow — plus a subtle scale-up. Blend mode can't
   be smoothly interpolated so it snaps; the shadow fade + scale are what
   make the hover read as a transition rather than a hard cut. Relies on
   .section's isolation: isolate above to keep the blend from leaking into
   neighbouring sections, and on .section__big-title having no z-index of its
   own (a stacking context there would isolate the blend from the video). */
@supports (mix-blend-mode: difference) {
  .section__big-title span:hover {
    text-shadow: none;
    mix-blend-mode: difference;
    transform: scale(1.04);
  }
}

/* ---------------- Category section meta ---------------- */

.section__meta {
  position: relative;
  z-index: 5;
  padding: 0 var(--edge) 40px;
  display: flex;
  align-items: baseline;
  gap: 18px;
}

.section__counter {
  font-size: 12px;
  letter-spacing: 0.16em;
  color: var(--fg-faint);
  white-space: nowrap;
}
.section__counter em {
  font-style: normal;
  color: var(--fg-dim);
}

.section__title {
  font-family: "Dolce Vita", sans-serif;
  font-weight: 400;
  font-size: clamp(13px, 1.4vw, 16px);
  line-height: 1;
  letter-spacing: 0.14em;
  margin: 0;
  text-transform: uppercase;
  color: var(--fg-dim);
}
.section__title a {
  color: inherit;
  border-bottom: 1px solid transparent;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.section__title a:hover,
.section__title a:focus-visible {
  color: var(--fg);
  border-bottom-color: currentColor;
}

/* A category section that opens a full project-overview page (e.g. Commercial
   Work). The whole frame is clickable (handled in main.js via [data-goto]);
   the title link above covers keyboard/screen-reader access to the same
   destination. Subtle zoom on hover signals the surface is interactive
   without relying on a visible button. */
.section--linkable { cursor: pointer; }
.section--linkable .section__video {
  transition: transform 700ms var(--ease);
}
.section--linkable:hover .section__video {
  transform: scale(1.035);
}

/* ---------------- CTA section ("Let's talk") ---------------- */

/* Deliberately no z-index: a stacking context here would isolate the heading
   from the video and break its mix-blend-mode. DOM order already paints this
   above the video and scrim. */
.cta__content {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 32px;
  padding: 0 var(--edge);
}

.cta__heading {
  font-family: "New Title", sans-serif;
  font-weight: 200;
  font-size: clamp(34px, 6.4vw, 84px);
  line-height: 1.08;
  letter-spacing: -0.01em;
  margin: 0;
  max-width: 16ch;
}
.cta__heading strong {
  font-weight: 700;
}

.section--cta,
.cta-band {
  isolation: isolate;
}

.cta__link {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  font-family: "Dolce Vita", sans-serif;
  font-size: clamp(18px, 2.2vw, 24px);
  letter-spacing: 0.02em;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--fg);
  transition: gap var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}
.cta__link::after {
  content: "\2192";
  transition: transform var(--dur-fast) var(--ease);
}
.cta__link:hover { gap: 20px; }
.cta__link:hover::after { transform: translateX(4px); }

/* The heading and link invert against the footage behind them, so they always
   render as the opposite colour of whatever the video is showing at that
   moment. Requires both to share a stacking context with the video (see
   .cta__content — no z-index) and the section to isolate so the blend doesn't
   leak into the rest of the page. The video itself is left unfiltered.
   Placed after the base rules above: border-bottom is a shorthand there, and
   a longhand border-bottom-color declared earlier in the cascade would be
   wiped out by it regardless of specificity. */
@supports (mix-blend-mode: difference) {
  .cta__heading,
  .cta__link {
    color: #fff;
    mix-blend-mode: difference;
  }
  .cta__link {
    border-bottom-color: #fff;
  }
}

/* ---------------- Floating contact button ----------------
   Persistent bottom-right link on every page except Contact itself (that
   page already has the form front and center — repeating the CTA there
   would just be noise). Deliberately text-only — no box or fill — so it
   reads as a quiet, ever-present affordance rather than a competing CTA.
   Sits below the full-screen nav overlay (z-index 50) so opening the menu
   covers it instead of floating on top of it. */
.floating-contact {
  position: fixed;
  right: var(--edge);
  bottom: 28px;
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 2px;
  background: none;
  border: none;
  font-family: "Dolce Vita", sans-serif;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-dim);
  transition: color var(--dur-fast) var(--ease), gap var(--dur-fast) var(--ease);
}
.floating-contact::after {
  content: "\2192";
  transition: transform var(--dur-fast) var(--ease);
}
.floating-contact:hover,
.floating-contact:focus-visible {
  color: var(--fg);
  gap: 14px;
}
.floating-contact:hover::after,
.floating-contact:focus-visible::after { transform: translateX(4px); }

@media (max-width: 640px) {
  .floating-contact { right: 16px; bottom: 18px; font-size: 11px; }
}

/* ---------------- CTA band (non-fullscreen pages) ---------------- */

.cta-band {
  position: relative;
  overflow: hidden;
  padding: clamp(80px, 14vw, 160px) 0;
  display: flex;
  background: #000;
}
.cta-band .section__video,
.cta-band .section__scrim { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cta-band .cta__content {
  position: relative;
  height: auto;
  padding: 0 var(--edge);
  align-items: flex-start;
}

/* ---------------- Trusted by: logo reel video strip ---------------- */

.trusted-by {
  --sky-h: clamp(340px, 82vh, 880px);
  position: relative;
  padding: clamp(20px, 3vw, 32px) 0 0;
}

.trusted-by__label {
  font-family: "Dolce Vita", sans-serif;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-faint);
  text-align: center;
  margin: 0 0 clamp(14px, 2.4vw, 22px);
}

/* Edge-masked so the video reel melts into the page instead of showing a hard
   rectangle, and kept short (--sky-h) so it reads as a strip, not a section. */
.trusted-by__sky {
  position: relative;
  height: var(--sky-h);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
}

.trusted-by__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

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

.site-footer {
  position: relative;
  z-index: 5;
  border-top: 1px solid var(--line);
  scroll-snap-align: start;
}

.site-footer__top {
  padding: 40px var(--edge) 24px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.footer__email {
  font-size: 14px;
  letter-spacing: 0.04em;
  color: var(--fg-dim);
}
.footer__email:hover { color: var(--fg); }

.footer__socials { display: flex; gap: 22px; }
.footer__socials a {
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-dim);
}
.footer__socials a:hover { color: var(--fg); }

.site-footer__legal {
  padding: 0 var(--edge) 20px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.footer__copy {
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--fg-faint);
  margin: 0;
}

.footer__legal-links { display: flex; gap: 20px; }
.footer__legal-links a {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-faint);
}
.footer__legal-links a:hover { color: var(--fg-dim); }

/* Whichever block ends up last inside the footer needs enough trailing
   space that at max scroll it doesn't land underneath the fixed header
   (which always covers the top var(--header-h) of the viewport regardless
   of scroll position). On pages where the trusted-by strip leads and the
   legal row closes the footer, the legal row is that last block. */
.site-footer .trusted-by ~ .site-footer__legal { padding-bottom: calc(var(--header-h) + 48px); }

/* Standalone placement (About page, between the portraits and the CTA band):
   the image strip above already supplies the top gap. */
.page > .trusted-by {
  padding-top: 0;
  padding-bottom: clamp(64px, 9vw, 112px);
}

/* ---------------- Static content pages (About / Contact / Legal) ---------------- */

.page {
  padding-top: var(--header-h);
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

.page__hero {
  padding: clamp(80px, 13vw, 168px) var(--edge) clamp(72px, 10vw, 128px);
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: clamp(44px, 7vw, 104px);
  align-items: end;
}

/* Full-bleed photo behind a hero's text instead of the plain dark background
   (Contact page). Image + scrim sit absolutely behind everything; the text
   column is pinned to the top-left corner via absolute positioning (not
   grid/flow alignment) so it lands in the same spot regardless of viewport
   width — a flow-based alignment would still reflow at each breakpoint.
   Deliberately carries no explicit z-index on the text column — an explicit
   value would start a new stacking context and cut the heading off from the
   image behind it, breaking the mix-blend-mode trick below. With image and
   text both "positioned" at stack-level 0, DOM order alone puts the text
   column (last) on top — same technique as .cta__content. */
.page__hero--bg {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: block;
  width: 100%;
  padding: 0;
  min-height: clamp(440px, 44vw, 660px);
}
/* Background-image on a ::before rather than an <img> with object-fit:
   sidesteps intrinsic-size/replaced-element sizing quirks entirely — a
   background layer only ever needs background-size:cover to fill its box,
   with no dependency on the element's own natural width/height. */
.page__hero--bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("../assets/images/about/portrait_contact_bg.jpg");
  background-size: cover;
  background-position: 15% 20%;
  background-repeat: no-repeat;
  filter: grayscale(0.15) contrast(1.05);
}
/* This photo has a large plain, blown-out-white area on one side — instead
   of fighting that for a dark scrim, the text sits directly on it as dark
   text, and a light radial guarantees that corner stays bright enough for
   contrast regardless of viewport width or which part of the photo crops
   into frame (mirroring the dark-corner-scrim trick, just inverted). */
.page__hero--bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 1000px 700px at 0% 0%, rgba(255,255,255,.55) 0%, rgba(255,255,255,.55) 40%, rgba(255,255,255,.25) 62%, transparent 90%);
}
.page__hero--bg > div {
  position: absolute;
  top: calc(var(--header-h) + 16px);
  left: var(--edge);
  right: var(--edge);
  max-width: 480px;
}
.page__hero--bg .page__heading { color: #000; }

@media (max-width: 640px) {
  .page__hero--bg > div { top: calc(var(--header-h) + 12px); }
  .page__hero--bg::after { background: radial-gradient(ellipse 560px 480px at 0% 0%, rgba(255,255,255,.6) 0%, rgba(255,255,255,.6) 40%, rgba(255,255,255,.28) 65%, transparent 90%); }
}

.page__eyebrow {
  font-family: "Dolce Vita", sans-serif;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0 0 28px;
}

.page__heading {
  font-family: "New Title", sans-serif;
  font-weight: 200;
  font-size: clamp(32px, 5vw, 64px);
  line-height: 1.2;
  letter-spacing: -0.005em;
  margin: 0;
}
.page__heading strong { font-weight: 700; }
.page__heading em { font-style: normal; font-weight: 500; color: var(--fg-dim); }

.page__lede {
  font-family: "Clash Display", sans-serif;
  font-weight: 300;
  font-size: clamp(16px, 1.6vw, 20px);
  line-height: 1.75;
  color: var(--fg-dim);
  margin: 0;
  max-width: 46ch;
}

.page__portrait {
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: #111;
}
.page__portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(0.25) contrast(1.05);
}

/* ---------------- Stats bar (slot-machine numbers) ---------------- */

.stats-bar {
  padding: clamp(72px, 10vw, 132px) var(--edge);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: clamp(32px, 5vw, 64px);
  row-gap: clamp(48px, 7vw, 72px);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.stat {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.stat__value {
  font-family: "New Title", sans-serif;
  font-weight: 700;
  font-size: clamp(34px, 5vw, 58px);
  line-height: 1;
  letter-spacing: -0.01em;
  display: inline-flex;
  align-items: flex-start;
}

.reel {
  display: inline-block;
  height: 1em;
  overflow: hidden;
  vertical-align: top;
  line-height: 1;
}
.reel__strip {
  display: flex;
  flex-direction: column;
  transform: translateY(0);
  transition: transform 1.5s cubic-bezier(.13, .71, .18, 1);
}
.reel__strip span {
  height: 1em;
  line-height: 1;
  display: block;
}
/* Digits repeat 3x (0-9, 0-9, 0-9); always land in the final cycle so every
   reel does a full multi-loop roll, regardless of how low the target digit is. */
.stats-bar.is-visible .reel__strip {
  transform: translateY(calc((20 + var(--target, 0)) * -1em));
}

.stat__value .reel:nth-of-type(2) .reel__strip { transition-delay: 0.1s; }
.stat__value .reel:nth-of-type(3) .reel__strip { transition-delay: 0.2s; }

.stat__suffix {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--dur-med) var(--ease), transform var(--dur-med) var(--ease);
  transition-delay: 1.3s;
}
.stats-bar.is-visible .stat__suffix {
  opacity: 1;
  transform: translateY(0);
}

.stat__label {
  font-family: "Dolce Vita", sans-serif;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-dim);
}

/* ---------------- Image strip (About) ---------------- */

.image-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(10px, 1.4vw, 20px);
  padding: clamp(56px, 8vw, 104px) var(--edge);
}
.image-strip__item { aspect-ratio: 3 / 4; overflow: hidden; background: #111; }
.image-strip__item img,
.image-strip__item video {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(0.3) contrast(1.05);
  transition: transform 600ms var(--ease);
}
.image-strip__item:hover img,
.image-strip__item:hover video { transform: scale(1.04); }

/* Wide variant for BTS galleries: fewer, larger tiles read better than a
   dense 3-up grid when there are only 3-6 images/clips per project. */
.image-strip--wide { grid-template-columns: repeat(2, 1fr); }
.image-strip--wide .image-strip__item { aspect-ratio: 4 / 3; }

.page__body {
  padding: clamp(48px, 8vw, 96px) var(--edge);
  max-width: 860px;
}
.page__body p {
  font-family: "Clash Display", sans-serif;
  font-weight: 300;
  font-size: clamp(17px, 1.7vw, 21px);
  line-height: 1.7;
  color: var(--fg-dim);
  margin: 0 0 28px;
}
.page__body h2 {
  font-family: "Dolce Vita", sans-serif;
  font-weight: 400;
  font-size: 15px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg);
  margin: 48px 0 16px;
}
.page__body h2:first-child { margin-top: 0; }

/* ---------------- Project detail pages ---------------- */

.project-hero {
  padding: clamp(56px, 10vw, 120px) var(--edge) clamp(40px, 6vw, 64px);
}

.project-hero__back {
  display: inline-block;
  font-family: "Dolce Vita", sans-serif;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0 0 24px;
  border-bottom: 1px solid transparent;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.project-hero__back:hover {
  color: var(--fg-dim);
  border-bottom-color: currentColor;
}

.project-hero__client {
  font-family: "Dolce Vita", sans-serif;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0 0 20px;
}

/* Full-bleed 16:9 player. Ratio-box keeps layout stable before the iframe or
   video loads (no CLS), and works identically for a Vimeo embed or the local
   <video> fallback used until a project's Vimeo link is wired up. */
.project-player {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  overflow: hidden;
}
.project-player iframe,
.project-player video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.project-player video { object-fit: cover; }

/* Some deliverables (social-format campaigns) are shot vertically — force a
   16:9 box around 9:16 footage would letterbox it into a thin strip. This
   swaps to a centered portrait frame instead. */
.project-player--vertical {
  aspect-ratio: 9 / 16;
  max-width: 480px;
  margin: 0 auto;
}

.project-note {
  padding: 18px var(--edge) 0;
  font-family: "Dolce Vita", sans-serif;
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--fg-faint);
  max-width: 860px;
}
/* Same treatment, but for a player embedded inside page__body's already-padded
   column rather than full-bleed — no extra horizontal padding needed. */
.project-note--inline { padding: 14px 0 8px; }

/* A smaller video embedded mid-article (e.g. the making-of clip that led to
   a project) rather than the full-bleed hero player. */
.page__video { margin: 8px 0 4px; }
.page__video .project-player { aspect-ratio: 16 / 9; }

/* Project title on detail pages reads as one typeface — Dolce Vita at two
   weights — instead of mixing in New Title like the About/Contact heroes. */
.project-hero .page__heading {
  font-family: "Dolce Vita", sans-serif;
  font-weight: 400;
}
.project-hero .page__heading strong { font-weight: 800; }
.project-hero .page__heading em { font-weight: 400; color: var(--fg-dim); }

/* Still frame dropped between two page__body sections to break up long
   copy blocks — same desaturated treatment as the BTS gallery tiles. */
.page__still { margin: 8px 0 40px; }
.page__still img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  filter: grayscale(0.25) contrast(1.05);
}

/* Portrait stills (native 9:16 source, e.g. phone-shot social content) keep
   their real aspect ratio instead of being force-cropped into the default
   landscape frame — cropping a 9:16 photo into 16:10 cuts off the subject. */
.page__still--portrait {
  max-width: 380px;
  margin-left: auto;
  margin-right: auto;
}
.page__still--portrait img { aspect-ratio: 9 / 16; }

/* ---------------- Editorial split rows (project detail pages) ----------------
   Alternating text/media rows instead of a straight text-block-then-gallery
   stack — keeps Challenge/Goal/Approach/Result readable while giving the
   page a more magazine-like, intertwined rhythm. */
.split-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(28px, 5vw, 72px);
  align-items: center;
  max-width: 1240px;
  margin: 0 auto;
  padding: clamp(40px, 6vw, 80px) var(--edge);
}
.split-row--reverse .split-row__media { order: 2; }
.split-row--reverse .split-row__text { order: 1; }

/* Asymmetric variant: uneven column widths, top-aligned instead of centered,
   with the media column dropped below the text's baseline — reads as an
   art-directed collage rather than a clean 50/50 row. Used sparingly to break
   up a page that would otherwise be an unbroken run of centered split-rows. */
.split-row--offset {
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  align-items: start;
}
.split-row--offset .split-row__media {
  margin-top: clamp(24px, 7vw, 104px);
}

/* Text-only variant: a section with no paired media, single narrow column.
   Used to break the alternating text/media rhythm so it doesn't read as a
   mechanical left-right-left-right pattern. */
.split-row--text-only { grid-template-columns: minmax(0, 1fr); max-width: 780px; }

/* Full-bleed break between split-rows — a single large frame with no text
   alongside it, edge to edge rather than boxed into the two-column grid.
   Used sparingly (once or twice per project) as a visual breather/reveal
   moment, distinct from the paired text+media rows around it. */
.feature-media { margin: clamp(8px, 2vw, 24px) 0 clamp(24px, 4vw, 56px); }
.feature-media__frame { width: 100%; aspect-ratio: 21 / 9; overflow: hidden; background: #111; }
/* For a real deliverable (not a decorative BTS loop) shown full-bleed — keeps
   native 16:9 framing uncropped and lets <video controls> render normally. */
.feature-media__frame--content { aspect-ratio: 16 / 9; }
.feature-media__frame--content img,
.feature-media__frame--content video { object-fit: contain; background: #000; }
.feature-media__frame img,
.feature-media__frame video {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(0.2) contrast(1.05);
  display: block;
}
.feature-media__caption {
  margin: 14px var(--edge) 0;
  font-family: "Dolce Vita", sans-serif;
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--fg-faint);
}

/* ---------------- Manifesto intro (project detail pages) ----------------
   An oversized, right-aligned opening statement offset from the standard
   grid — used sparingly for projects whose brief itself calls for a bolder,
   more art-directed opening than the usual Goal/Challenge/Approach/Result
   rhythm (e.g. Encoded Identity). */
.manifesto {
  max-width: 1100px;
  margin: 0 auto;
  padding: clamp(32px, 6vw, 72px) var(--edge) clamp(16px, 3vw, 32px);
}
.manifesto__kicker {
  font-family: "Dolce Vita", sans-serif;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0 0 20px;
  text-align: right;
}
.manifesto__text {
  font-family: "New Title", sans-serif;
  font-weight: 200;
  font-size: clamp(24px, 3.6vw, 42px);
  line-height: 1.35;
  color: var(--fg);
  margin: 0 0 0 auto;
  max-width: 34ch;
  text-align: right;
}
@media (max-width: 640px) {
  .manifesto__kicker,
  .manifesto__text { margin: 0; text-align: left; max-width: none; }
}

/* ---------------- Editorial pull-quote (project detail pages) ----------------
   A single oversized statement pulled out of the surrounding copy, magazine-
   style, instead of another boxed text-only split-row — gives a page a
   deliberate rhythm break rather than a uniform stack of equal-weight
   paragraphs. */
.editorial-quote {
  max-width: 980px;
  margin: 0 auto;
  padding: clamp(48px, 9vw, 104px) var(--edge);
}
.editorial-quote__mark {
  font-family: "New Title", sans-serif;
  font-weight: 700;
  font-size: clamp(64px, 11vw, 150px);
  line-height: 0.7;
  color: var(--fg-faint);
  opacity: 0.55;
  margin: 0 0 -0.08em;
}
.editorial-quote__text {
  font-family: "New Title", sans-serif;
  font-weight: 200;
  font-size: clamp(28px, 4.6vw, 54px);
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0 0 32px;
  max-width: 18ch;
}
.editorial-quote__context {
  font-family: "Clash Display", sans-serif;
  font-weight: 300;
  font-size: clamp(16px, 1.6vw, 20px);
  line-height: 1.7;
  color: var(--fg-dim);
  margin: 0;
  max-width: 58ch;
  padding-left: clamp(0px, 4vw, 44px);
  border-left: 1px solid var(--line);
}
@media (max-width: 640px) {
  .editorial-quote__context { padding-left: 18px; border-left-width: 1px; }
}

.split-row__text h2 {
  font-family: "Dolce Vita", sans-serif;
  font-weight: 400;
  font-size: 15px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg);
  margin: 0 0 16px;
}
.split-row__text p {
  font-family: "Clash Display", sans-serif;
  font-weight: 300;
  font-size: clamp(16px, 1.6vw, 20px);
  line-height: 1.7;
  color: var(--fg-dim);
  margin: 0;
}

.split-row__media { aspect-ratio: 4 / 5; overflow: hidden; background: #111; }
.split-row__media--wide { aspect-ratio: 16 / 9; }
.split-row__media--tall { aspect-ratio: 3 / 4; max-width: 340px; margin: 0 auto; }
/* True 9:16 source (vertical social film, phone-shot portrait) — kept at its
   native ratio rather than cropped into --tall's 3:4, so nothing is cut off. */
.split-row__media--portrait { aspect-ratio: 9 / 16; max-width: 300px; margin: 0 auto; }
.split-row__media img,
.split-row__media video {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(0.2) contrast(1.05);
  display: block;
}
/* A Vimeo embed sitting in a split-row / feature slot instead of a local
   <video>. Deliberately excluded from the rules above: the grayscale
   treatment suits muted b-roll but would wash out a real player's own
   chrome, and object-fit does nothing on an iframe. */
.split-row__media iframe,
.feature-media__frame iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}
.split-row__caption {
  margin: 10px 0 0;
  font-family: "Dolce Vita", sans-serif;
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--fg-faint);
}

/* Two images/clips shown side by side in a single split-row media slot,
   for moments that read better as a pair than as one lone frame. */
.split-row__media-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.split-row__media-pair img,
.split-row__media-pair video {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  filter: grayscale(0.2) contrast(1.05);
  display: block;
}
@media (max-width: 640px) {
  .split-row__media-pair { grid-template-columns: 1fr; }
}

/* ---------------- Before/after reveal (AI Production) ----------------
   Two stacked images; moving the cursor horizontally across the frame
   wipes the "after" layer in from the right as a vertical-line slider —
   everything left of the pointer stays "before", everything right shows
   "after". Driven by main.js ([data-reveal]). */
.reveal {
  position: relative;
  overflow: hidden;
  background: #111;
  aspect-ratio: 4 / 5;
  cursor: col-resize;
}
.reveal__before,
.reveal__after {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}
.reveal__after {
  clip-path: inset(0 0 0 100%);
}
.reveal__tag {
  position: absolute;
  top: 16px;
  z-index: 2;
  font-family: "Dolce Vita", sans-serif;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9);
  background: rgba(0, 0, 0, 0.5);
  padding: 5px 10px;
  pointer-events: none;
}
.reveal__tag--before { left: 16px; }
.reveal__tag--after { right: 16px; }

/* Vertical dividing line + circular knob, tracking the pointer's X
   position — the conventional before/after slider affordance. */
.reveal__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 3;
  width: 2px;
  background: rgba(255, 255, 255, 0.9);
  pointer-events: none;
  opacity: 0;
  transition: opacity 150ms ease;
}
.reveal__handle::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 36px;
  height: 36px;
  border: 1px solid rgba(255, 255, 255, 0.9);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.35);
  transform: translate(-50%, -50%);
}

.reveal__hint {
  position: absolute;
  z-index: 2;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  font-family: "Dolce Vita", sans-serif;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.65);
  pointer-events: none;
  transition: opacity 200ms ease;
}
.reveal.is-active .reveal__hint { opacity: 0; }

/* Full-bleed variant for a reveal used as a standalone feature moment
   (inside .feature-media) rather than paired with text in a split-row. */
.reveal--wide { aspect-ratio: 16 / 9; }

/* Portrait variant, source shown uncropped — for photo pairs where a
   cover-fit box would cut off too much of the frame. */
.reveal--contain { aspect-ratio: 2 / 3; background: #000; }
.reveal--contain .reveal__before,
.reveal--contain .reveal__after { object-fit: contain; }

/* Portrait variant for a reveal used as the page's main visual (in place
   of .project-player) when the source is a vertical/social-format render. */
/* width: 100% (not auto) so this resolves to a definite size even as a
   direct flex child of .page — an auto cross-axis margin on a flex item
   suppresses align-items: stretch, which would otherwise leave it at 0
   width since the absolutely-positioned before/after images contribute
   no intrinsic size of their own. */
.reveal--hero { aspect-ratio: 9 / 16; width: 100%; max-width: 480px; margin: 0 auto; }

/* ---------------- Mosaic gallery (project detail pages) ----------------
   Mixed tile sizes read as more considered than a uniform strip — used for
   BTS stills/clips left over once a few have been placed inline as split
   rows. `dense` packing lets tiles of different sizes tessellate cleanly
   regardless of how many items a given project has. */
.mosaic {
  display: grid;
  grid-auto-flow: dense;
  grid-template-columns: repeat(6, 1fr);
  grid-auto-rows: minmax(90px, auto);
  gap: clamp(10px, 1.4vw, 20px);
  padding: clamp(56px, 8vw, 104px) var(--edge);
}
.mosaic__item { overflow: hidden; background: #111; }
.mosaic__item img,
.mosaic__item video {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(0.3) contrast(1.05);
  transition: transform 600ms var(--ease);
  display: block;
}
.mosaic__item:hover img,
.mosaic__item:hover video { transform: scale(1.04); }

.mosaic__item--a { grid-column: span 4; grid-row: span 3; }
.mosaic__item--b { grid-column: span 2; grid-row: span 3; }
.mosaic__item--c { grid-column: span 3; grid-row: span 2; }
.mosaic__item--d { grid-column: span 2; grid-row: span 2; }
.mosaic__item--wide { grid-column: span 6; grid-row: span 2; }
.mosaic__item--tall { grid-column: span 2; grid-row: span 4; }

/* Secondary video row for projects with more than one deliverable
   (e.g. iffland.hören's three campaign spots). Unmuted with controls,
   same as the primary player, so sound is available on every clip. */
.project-more { padding: clamp(48px, 7vw, 88px) var(--edge) 0; max-width: 860px; }
.project-more__label {
  font-family: "Dolce Vita", sans-serif;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0 0 20px;
}
.project-more__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2.4vw, 28px);
}
.project-more .project-player--vertical { margin: 0; max-width: none; }

/* Small, subtle credits list — deliberately kept out of the main copy
   rhythm (smaller type, muted color, hairline rows) since it's reference
   material, not part of the Challenge/Goal/Approach/Result narrative. */
/* ---------------- Music Videos page ----------------
   Each track gets its own title block above its player — larger than a
   .split-row section label, smaller than the page h1, so several tracks can
   sit on one page without competing with the page heading. */
.track { padding: clamp(56px, 8vw, 104px) var(--edge) 0; max-width: 1240px; margin: 0 auto; }
.track__title {
  font-family: "Dolce Vita", sans-serif;
  font-weight: 800;
  font-size: clamp(22px, 3.2vw, 40px);
  line-height: 1.1;
  letter-spacing: -0.005em;
  margin: 0 0 8px;
}
.track__meta {
  font-family: "Dolce Vita", sans-serif;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0;
}

/* Subtle outbound link for press/feature coverage inside a text block. */
.page__extlink {
  display: inline-block;
  margin-top: 4px;
  font-family: "Dolce Vita", sans-serif;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-dim);
  border-bottom: 1px solid rgba(245, 244, 240, 0.3);
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.page__extlink:hover { color: var(--fg); border-bottom-color: currentColor; }

/* ---------------- Press / feature card ----------------
   A whole-block link for external coverage of a project (a published
   review, a gallery listing). Optionally wraps a screenshot of the piece
   itself so the actual words are visible on the page rather than hidden
   behind a text link. */
.press-card {
  display: block;
  max-width: 860px;
  margin: 8px 0 0;
  padding: 20px;
  border: 1px solid rgba(245, 244, 240, 0.14);
  background: rgba(245, 244, 240, 0.02);
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.press-card:hover {
  border-color: rgba(245, 244, 240, 0.34);
  background: rgba(245, 244, 240, 0.05);
}
.press-card__label {
  font-family: "Dolce Vita", sans-serif;
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0 0 12px;
}
/* Screenshot of the published text — no grayscale/crop filter here, unlike
   the gallery tiles: this is type that has to stay legible. */
.press-card__shot {
  display: block;
  width: 100%;
  height: auto;
  margin: 0 0 14px;
}
.press-card__source {
  font-family: "Clash Display", sans-serif;
  font-weight: 300;
  font-size: clamp(15px, 1.5vw, 18px);
  line-height: 1.5;
  color: var(--fg-dim);
  margin: 0;
}
.press-card__cta {
  display: inline-block;
  margin: 12px 0 0;
  font-family: "Dolce Vita", sans-serif;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-dim);
  transition: color var(--dur-fast) var(--ease);
}
.press-card:hover .press-card__cta { color: var(--fg); }

@media (max-width: 640px) {
  .press-card { padding: 16px; }
}

.credits { padding: clamp(40px, 6vw, 72px) var(--edge); max-width: 860px; }
.credits__label {
  font-family: "Dolce Vita", sans-serif;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0 0 20px;
}
.credits__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0 40px;
}
.credits__row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 6px 0;
  border-bottom: 1px solid rgba(245, 244, 240, 0.08);
  font-family: "Dolce Vita", sans-serif;
  font-size: 11px;
  letter-spacing: 0.03em;
}
.credits__role { color: var(--fg-faint); }
.credits__name { color: var(--fg-dim); text-align: right; }
.credits__thanks {
  margin: 28px 0 0;
  font-family: "Clash Display", sans-serif;
  font-weight: 300;
  font-size: 13px;
  line-height: 1.7;
  color: var(--fg-faint);
  max-width: 640px;
}

/* ---------------- Contact form ---------------- */

.contact-layout {
  padding: clamp(24px, 6vw, 64px) var(--edge) 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(40px, 6vw, 100px);
  align-items: start;
}

.contact-aside {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding-bottom: 48px;
}

.contact-aside__block h3 {
  font-family: "Dolce Vita", sans-serif;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0 0 12px;
}
.contact-aside__block a,
.contact-aside__block p {
  font-family: "Clash Display", sans-serif;
  font-size: clamp(18px, 2vw, 22px);
  font-weight: 300;
  color: var(--fg-dim);
  margin: 0;
}
.contact-aside__block a { color: var(--fg); border-bottom: 1px solid var(--line); padding-bottom: 2px; }
.contact-aside__block a:hover { border-color: var(--fg); }

.form {
  padding-bottom: 64px;
  display: flex;
  flex-direction: column;
  gap: 30px;
}

.form__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
}

/* min-width:0 is required: a grid track's automatic minimum is the item's
   min-content size, and form controls carry an intrinsic default width that
   would otherwise push the row wider than the viewport. */
.field { display: flex; flex-direction: column; gap: 10px; min-width: 0; }

.field label {
  font-family: "Dolce Vita", sans-serif;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-faint);
}
.field label .req { color: var(--fg-dim); }

.field input,
.field select,
.field textarea {
  width: 100%;
  min-width: 0;
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  color: var(--fg);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line);
  padding: 10px 2px;
  outline: none;
  transition: border-color var(--dur-fast) var(--ease);
  appearance: none;
  -webkit-appearance: none;
  border-radius: 0;
}
.field input::placeholder,
.field textarea::placeholder { color: var(--fg-faint); }
.field input:focus,
.field select:focus,
.field textarea:focus { border-color: var(--fg); }

.field--select { position: relative; }
.field--select::after {
  content: "\2193";
  position: absolute;
  right: 4px;
  bottom: 12px;
  color: var(--fg-dim);
  pointer-events: none;
}
.field--select select {
  cursor: pointer;
  padding-right: 24px;
}
.field--select select option { background: #111; color: var(--fg); }

.field textarea { resize: vertical; min-height: 110px; font-family: inherit; }

.form__submit {
  align-self: flex-start;
  margin-top: 8px;
  padding: 16px 34px;
  border: 1px solid var(--fg);
  font-family: "Dolce Vita", sans-serif;
  font-size: 14px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.form__submit:hover { background: var(--fg); color: #0a0a0a; }
.form__submit:disabled { opacity: 0.5; cursor: default; }

.form__note {
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--fg-faint);
  margin: 0;
}

.form__status {
  font-size: 13px;
  color: var(--fg-dim);
  min-height: 1em;
}
.form__status[data-state="error"] { color: #e2867a; }
.form__status[data-state="success"] { color: #9fd3a8; }

/* ---------------- Responsive ---------------- */

/* The two-up contact layout plus the two-up name row gets too tight well
   before the phone breakpoint, so stack the aside earlier. */
@media (max-width: 900px) {
  .contact-layout { grid-template-columns: 1fr; gap: clamp(32px, 5vw, 56px); }
}

@media (max-width: 640px) {
  :root { --header-h: 76px; }
  .section__content { padding-bottom: 120px; }
  .section__meta { padding-bottom: 56px; }
  .hero__tagline { max-width: 100%; font-size: clamp(15px, 4.4vw, 19px); }
  .site-nav__inner { justify-content: flex-start; padding-top: calc(var(--header-h) + 12px); gap: 32px; }
  .site-nav__links a { font-size: 9vw; padding: 8px 0; }
  .site-footer__top,
  .site-footer__legal { flex-direction: column; align-items: flex-start; }
  .cta__heading { max-width: 100%; }

  .page__hero { grid-template-columns: 1fr; }
  .page__portrait { order: -1; aspect-ratio: 16 / 10; }
  .stats-bar { grid-template-columns: repeat(2, 1fr); }
  .image-strip { grid-template-columns: repeat(2, 1fr); }
  /* Third portrait spans the row instead of being hidden, so no image is lost. */
  .image-strip__item:nth-child(3) { grid-column: 1 / -1; aspect-ratio: 16 / 10; }
  .contact-layout { grid-template-columns: 1fr; }
  .form__row { grid-template-columns: 1fr; gap: 30px; }

  .image-strip--wide { grid-template-columns: 1fr; }
  .project-more__grid { grid-template-columns: 1fr; }
  .credits__row { flex-direction: column; gap: 2px; }
  .credits__name { text-align: left; }

  .split-row { grid-template-columns: 1fr; padding-top: clamp(32px, 6vw, 56px); padding-bottom: clamp(32px, 6vw, 56px); }
  .split-row--reverse .split-row__media,
  .split-row--reverse .split-row__text { order: initial; }
  .split-row__media--tall { max-width: 260px; }
  .split-row--offset { grid-template-columns: 1fr; }
  .split-row--offset .split-row__media { margin-top: 0; }

  .mosaic { grid-template-columns: repeat(2, 1fr); }
  .mosaic__item,
  .mosaic__item--a, .mosaic__item--b, .mosaic__item--c,
  .mosaic__item--d, .mosaic__item--tall { grid-column: span 1; grid-row: span 1; aspect-ratio: 3 / 4; }
  .mosaic__item--wide { grid-column: span 2; grid-row: span 1; aspect-ratio: 16 / 10; }

  .feature-media__frame { aspect-ratio: 4 / 3; }
}

@media (max-height: 480px) and (orientation: landscape) {
  .section__content, .section__meta { padding-bottom: 24px; }
  .scroll-cue { display: none; }
  /* Short viewports leave little vertical room between the centered big title
     and the bottom-pinned counter/label — scale it down so they can't collide. */
  .section__big-title span { font-size: clamp(20px, 7vw, 60px); }
}
