/* velveiro. site styles. Mobile first; breakpoints at 768 and 1024. */

:root {
  --white: #FFFFFF;
  --black: #0A0A0A;
  --gray: #5E5E5E;
  --light: #F2F2F2;
  --accent: #FF5C00;

  /* Placeholder greys, swapped out when real media arrives */
  --ph-1: #EDEDED;
  --ph-2: #E2E2E2;
  --ph-3: #D6D6D6;
  --ph-dark: #1A1A1A;

  --line: rgba(10, 10, 10, .14);
  --line-inv: rgba(255, 255, 255, .16);
  --muted-inv: rgba(255, 255, 255, .56);

  /* Glass (dark variant of the nav pill), used on the contact page */
  --glass-filter: blur(20px) saturate(1.4);
  --glass-dark-bg: rgba(10, 10, 10, .38);
  --glass-dark-line: rgba(255, 255, 255, .12);
  --glass-dark-shadow: 0 12px 32px rgba(0, 0, 0, .22);

  --g: 20px;
  --ease: cubic-bezier(.215, .61, .355, 1); /* power3.out */

  --f-brand: "Anybody", system-ui, sans-serif;
  --f-head: "Inter Tight", "Helvetica Neue", Arial, sans-serif;
  --f-body: "Inter", "Helvetica Neue", Arial, sans-serif;
  --f-mono: "Fragment Mono", ui-monospace, Menlo, monospace;
}

/* ---------- Base ---------- */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }

body {
  margin: 0;
  background: var(--white);
  color: var(--black);
  font: 400 16px/1.4 var(--f-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
p, h1, h2, h3, ul, ol, dl, dd, figure, fieldset { margin: 0; padding: 0; }
ul, ol { list-style: none; }
fieldset { border: 0; min-width: 0; }
::selection { background: var(--black); color: var(--white); }
:focus-visible { outline: 1px solid currentColor; outline-offset: 3px; }

.skip { position: absolute; left: -9999px; top: 0; }
.skip:focus { left: var(--g); top: var(--g); z-index: 300; background: var(--white); padding: 10px 14px; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* JS-driven entry: body stays hidden until main.js fades it in (inline head script sets .js) */
html.js:not(.loading):not(.is-ready) body { opacity: 0; }

/* ---------- Type ---------- */

.wordmark {
  font-family: var(--f-brand);
  font-stretch: 150%;
  font-weight: 400;
  letter-spacing: -.03em;
  line-height: 1;
  text-transform: lowercase;
  white-space: nowrap;
}
.dot { color: var(--accent); }

.h1 {
  font-family: var(--f-brand);
  font-stretch: 150%;
  font-weight: 400;
  font-size: clamp(30px, 4.4vw, 64px);
  line-height: .98;
  letter-spacing: -.04em;
}

.h2 {
  font-family: var(--f-head);
  font-weight: 500;
  font-size: clamp(32px, 3.4vw, 56px);
  line-height: 1;
  letter-spacing: -.03em;
}

.label {
  font-family: var(--f-mono);
  font-size: 11px;
  line-height: 1.3;
  letter-spacing: .02em;
  text-transform: uppercase;
}

.lead {
  font-size: 20px;
  line-height: 1.15;
  letter-spacing: -.01em;
}

.muted { color: var(--gray); }

/* Line masks for text reveals */
.line { display: block; overflow: hidden; padding-bottom: .1em; margin-bottom: -.1em; }
.line > span { display: block; }

/* ---------- Links and buttons ---------- */

/* Underline that draws in from the left and leaves to the right */
.ul {
  background: linear-gradient(currentColor, currentColor) 100% 100% / 0 1px no-repeat;
  transition: background-size .8s var(--ease);
  padding-bottom: 1px;
}
.ul:hover { background-position: 0 100%; background-size: 100% 1px; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 42px;
  padding: 0 22px;
  border-radius: 999px;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: .02em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background-color .6s var(--ease), color .6s var(--ease);
}
.btn__in { display: inline-flex; align-items: center; gap: .9em; transition: gap .8s var(--ease); }
.btn:hover .btn__in { gap: 1.4em; }
.btn--dark { background: var(--black); color: var(--white); }
.btn--light { background: var(--white); color: var(--black); }
.btn--accent { background: var(--accent); color: var(--black); }
.btn--wide { min-width: 200px; }

/* Orange hover, scoped to two buttons only: hero [ See the work ] and the nav [ Contact ] (not the white Back button in the contact page nav).
   Same .8s ease as the bracket gap and text roll, so the colour moves with them. The nav keeps its opacity/visibility fades for the compact pill. */
.hero__cta-wrap .btn { transition: background-color .8s var(--ease), color .8s var(--ease); }
html:not([data-page="contact"]) .nav__cta { transition: background-color .8s var(--ease), color .8s var(--ease), opacity .5s var(--ease), visibility .5s; }
@media (hover: hover) and (pointer: fine) {
  .hero__cta-wrap .btn:hover,
  html:not([data-page="contact"]) .nav__cta:hover { background-color: var(--accent); color: var(--black); }
}
.hero__cta-wrap .btn:focus-visible,
html:not([data-page="contact"]) .nav__cta:focus-visible { background-color: var(--accent); color: var(--black); }

/* Text roll on hover: the label slides up and is replaced by a copy of itself */
.roll { display: inline-block; overflow: hidden; height: 1.3em; line-height: 1.3; vertical-align: top; }
.roll > span { display: block; transition: transform .8s var(--ease); }
.roll > span::after { content: attr(data-t); content: attr(data-t) / ""; display: block; }
a:hover .roll > span, button:hover .roll > span { transform: translateY(-50%); }

/* ---------- Loader (home, first visit per session) ---------- */

.loader { display: none; }
html.js.loading .loader {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  background: var(--white);
}
.loader__mark { font-size: clamp(40px, 9vw, 120px); display: flex; overflow: hidden; padding-bottom: .08em; }
.loader__ch { display: inline-block; }

/* ---------- Nav ---------- */

.nav {
  position: fixed;
  top: 20px;
  left: 0;
  right: 0;
  z-index: 100;
  width: calc(100% - 2 * var(--g));
  max-width: 500px;
  margin-inline: auto;
  transition: max-width .9s var(--ease);
}
.nav__pill {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  height: 54px;
  padding: 6px 6px 6px 20px;
  border-radius: 999px;
  background: rgba(242, 242, 242, .72);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
}
.nav__mark { font-size: 18px; margin-right: auto; }
.nav__cta { flex: 1 1 auto; max-width: 210px; }
.nav__toggle {
  position: relative;
  flex: none;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--white);
}
.nav__toggle span {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 14px;
  height: 1.5px;
  background: var(--black);
  transform: translate(-50%, -50%);
  transition: transform .8s var(--ease);
}
.nav__toggle span:last-child { transform: translate(-50%, -50%) rotate(90deg); }
.nav.is-open .nav__toggle span:first-child { transform: translate(-50%, -50%) rotate(45deg); }
.nav.is-open .nav__toggle span:last-child { transform: translate(-50%, -50%) rotate(135deg); }

.nav__mark, .nav__cta, .nav__toggle { transition: opacity .5s var(--ease), visibility .5s; }
.nav__sym {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: 999px;
  opacity: 0;
  visibility: hidden;
  transition: opacity .5s var(--ease), visibility .5s;
}
.nav__sym img { width: 28px; height: 28px; }

/* Mobile: the pill shrinks to the symbol while scrolling down */
.nav.is-compact { max-width: 84px; }
.nav.is-compact .nav__pill { overflow: hidden; }
.nav.is-compact .nav__mark,
.nav.is-compact .nav__cta,
.nav.is-compact .nav__toggle { opacity: 0; visibility: hidden; }
.nav.is-compact .nav__sym { opacity: 1; visibility: visible; }

.nav__menu {
  margin-top: 6px;
  padding: 28px 20px;
  border-radius: 24px;
  background: rgba(242, 242, 242, .9);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
}
.nav__menu[hidden] { display: none; }
.menu__list li { overflow: hidden; }
.menu__link {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 4px 0;
  font-family: var(--f-head);
  font-weight: 500;
  font-size: 32px;
  line-height: 1.05;
  letter-spacing: -.03em;
}
.menu__link .label { color: var(--gray); transform: translateY(-.6em); }
/* Current page, or the home section in view: the number turns orange */
.nav__menu .menu__link[aria-current] .label { color: var(--accent); }

/* ---------- Placeholders ---------- */

.ph { display: grid; place-items: center; background: var(--ph-1); color: var(--gray); }
.ph--2 { background: var(--ph-2); }
.ph--3 { background: var(--ph-3); }
.ph--dark { background: var(--ph-dark); color: var(--muted-inv); }
.ph__label { font-family: var(--f-mono); font-size: 11px; letter-spacing: .02em; text-transform: uppercase; text-align: center; padding: 0 16px; }

/* ---------- Home hero ---------- */

.hero__media {
  position: relative;
  height: 80svh;
  min-height: 460px;
  overflow: hidden;
  background: var(--black);
}
.hero__slides { position: absolute; inset: 0; }
.hero__slide { position: absolute; inset: 0; opacity: 0; }
.hero__slide.is-active { opacity: 1; }
/* 45% across keeps the face (left of centre in the video) in frame on phones and tablets; wide desktops only crop top and bottom */
.hero__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 45% 50%; }
/* Laptop brush canvas (main.js draws the video into it). .is-plain = no brush: phones, touch, reduced motion, no WebGL */
.hero__brush { position: absolute; inset: 0; z-index: 2; display: block; width: 100%; height: 100%; }
.hero__media.is-plain .hero__brush { display: none; }
@media (min-width: 768px) and (hover: hover) and (pointer: fine) {
  /* Black over the video until the brush reveals it; also before main.js runs, so the poster never flashes.
     The light band is not needed on black, and the clock and location turn white. */
  html.js .hero__media:not(.is-plain) .hero__slide::before,
  .hero__media.is-brush .hero__slide::before { content: ""; position: absolute; inset: 0; z-index: 1; background: var(--black); }
  html.js .hero__media:not(.is-plain)::after,
  .hero__media.is-brush::after { display: none; }
  html.js .hero__media:not(.is-plain) :is(.hero__clock, .hero__loc),
  .hero__media.is-brush :is(.hero__clock, .hero__loc) { color: var(--white); }
}

.hero__bar {
  position: absolute;
  left: var(--g);
  right: var(--g);
  bottom: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.hero__clock, .hero__loc { display: none; }
.hero__cta-wrap { display: flex; justify-content: center; }

.intro {
  display: grid;
  gap: 24px 16px;
  padding: 32px var(--g) 0;
}
.intro__clock { grid-row: 1; justify-self: end; margin-bottom: -8px; }
/* "Your Product." is ~10.5em wide: at 1440px this makes it ~24% of the viewport */
/* Same size is used for the project page titles, the Next project name and the Work page title */
.intro .h1, .case-head__title, .case-next__name, .work-hero__title { font-size: clamp(24px, 2.25vw, 34px); line-height: 1.05; }
.intro .h1 { grid-row: 2; }
.intro__text { display: grid; gap: 18px; padding-top: 4px; }

/* ---------- Work ---------- */

.work { padding: 120px 0 0; }
.work__head {
  display: flex;
  justify-content: space-between;
  padding: 0 var(--g) 24px;
}
.project { display: grid; margin-bottom: 110px; }
.project:last-child { margin-bottom: 0; }
.project__media {
  position: relative;
  display: block;
  aspect-ratio: 375 / 600;
  overflow: hidden;
}
.project__inner { position: absolute; inset: -8% 0; }
/* Home: the project image grows slightly on hover (desktop pointers). It stays on top of the next card while it shrinks back. */
.project__media { transition: transform .8s var(--ease), z-index 0s .8s; }
@media (hover: hover) and (pointer: fine) {
  .project__media:hover { z-index: 1; transform: scale(1.03); transition: transform .8s var(--ease), z-index 0s; }
}
/* Scroll stacking (main.js adds .is-stack): rows are opaque so the row tucked under each one stays hidden.
   On mobile the 110px gap becomes padding so it covers too. */
.work.is-stack .project { position: relative; background: var(--white); }
.work.is-stack .project:not(:last-child) { margin-bottom: 0; padding-bottom: 110px; }
.project__meta { display: grid; gap: 14px; padding: 18px var(--g) 0; }
.project__name { font-family: var(--f-head); font-weight: 500; font-size: 24px; letter-spacing: -.02em; line-height: 1; }
.meta { display: grid; gap: 4px; }
.meta div { display: flex; gap: .7em; }
.meta dt { color: var(--gray); flex: none; min-width: 11ch; }
.meta dd { text-align: left; }
.meta dt::after { content: "\00a0\00a0:"; }

/* ---------- Work page ---------- */

/* Dark header. Placeholder gradient for now; a video or image placed in .work-hero__bg is blurred behind the text. */
.work-hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  z-index: 1; /* above the pinned project list, which starts under it */
  /* 98px top padding keeps the title 24px clear of the nav pill (20px + 54px) on short screens */
  min-height: clamp(340px, 45svh, 480px);
  padding: 98px var(--g) 28px;
  overflow: hidden;
  background: radial-gradient(120% 90% at 70% 15%, #2B2B2B 0%, #161616 55%, var(--black) 100%);
  color: var(--white);
}
.work-hero__bg { position: absolute; inset: 0; }
.work-hero__bg > img,
.work-hero__bg > video { position: absolute; inset: -40px; width: calc(100% + 80px); height: calc(100% + 80px); object-fit: cover; filter: blur(28px); }
.work-hero__shade { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10, 10, 10, .2) 0%, rgba(10, 10, 10, .6) 100%); }
.work-hero__text { position: relative; display: grid; gap: 20px; }
.work-hero__sub { max-width: 380px; }

/* Project list: square cards in one centred column, captions use the home card meta.
   Static by default (also the reduced-motion view). main.js adds .is-live, pins the stage and sets each card's size,
   position and caption opacity from the scroll. --wl-max is the largest card, --wl-min-k the smallest as a share of it. */
.wlist { --wl-max: 70vw; --wl-min-k: .643; position: relative; background: var(--white); padding: 48px var(--g) 160px; }
.wlist__item { position: relative; width: var(--wl-max); margin: 0 auto; }
.wlist__item + .wlist__item { margin-top: 24px; }
.wlist__media { position: relative; display: block; aspect-ratio: 1; overflow: hidden; }
.wlist__inner { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Mobile: caption below the card, centred */
.wlist .wlist__meta { align-self: auto; padding: 14px 0 0; justify-items: center; text-align: center; }
.wlist .wlist__meta .meta { width: max-content; max-width: 100%; }
.wlist .wlist__meta .meta div { justify-content: flex-start; }
.wlist__fallback { display: grid; gap: 8px; justify-items: center; }

.wlist.is-live { padding: 0; }
.wlist.is-live .wlist__stage { position: sticky; top: 0; height: 100svh; overflow: hidden; }
.wlist.is-live .wlist__item { position: absolute; top: 0; left: 0; margin: 0; will-change: transform; }
.wlist.is-live .wlist__media { will-change: transform; }
.wlist.is-live .wlist__meta { position: absolute; top: 100%; left: 0; right: 0; opacity: 0; visibility: hidden; }

/* "In production" card: holds a project slot (Project 04 on home and work) until the real project is ready.
   The card is a size container, so every measure is in cqw and it scales with its slot. Not a link: no hover zoom, default cursor. */
.wlist__media--soon, .project__media--soon { cursor: default; }
@media (hover: hover) and (pointer: fine) {
  .project__media.project__media--soon:hover { z-index: auto; transform: none; }
}
.soon { position: absolute; inset: 0; container-type: inline-size; background: var(--black); color: var(--white); }
.soon__num, .soon__note { position: absolute; font-size: clamp(9px, 2cqw, 13px); color: rgba(255, 255, 255, .5); white-space: nowrap; }
.soon__num { top: 6.4cqw; left: 6.4cqw; }
.soon__note { bottom: 6.4cqw; left: 50%; transform: translateX(-50%); }
/* Work page: the card shrinks to 55% (64% on phones) while scrolling, so its labels divide by the scale (--wl-s, set by main.js)
   and stay at the same readable on-screen size as on the full-size card */
.wlist__media--soon .soon__num, .wlist__media--soon .soon__note { font-size: calc(clamp(9px, 2cqw, 13px) / var(--wl-s, 1)); }
.soon__title {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--f-brand);
  font-stretch: 150%;
  font-weight: 400;
  font-size: 7.3cqw;
  line-height: .98;
  letter-spacing: -.04em;
  white-space: nowrap;
}
.soon__dot { color: var(--accent); animation: soon-pulse 2.4s ease-in-out infinite; }
@keyframes soon-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .soon__dot { animation: none; } }

/* Spinner: a small ring with a gap that turns forever. Takes the text colour, so it is white on the black card and black on white.
   Size is 0.45em of the surrounding text; on the 11px status line it is fixed at 14px. */
.spinner {
  display: inline-block;
  flex: none;
  width: .45em;
  height: .45em;
  margin-left: .35em;
  border: 1.5px solid;
  border-color: currentColor currentColor currentColor transparent;
  border-radius: 50%;
  vertical-align: middle;
  animation: spinner-turn .9s linear infinite;
}
.meta .spinner { width: 14px; height: 14px; margin-left: 8px; vertical-align: -3px; }
@keyframes spinner-turn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2.5s !important; } }

/* ---------- Services (dark) ---------- */

.services {
  display: grid;
  gap: 72px;
  margin-top: 160px;
  padding: 50px var(--g);
  background: var(--black);
  color: var(--white);
}
.services__intro { display: grid; gap: 22px; align-content: start; justify-items: start; }
.services__intro .label { color: var(--muted-inv); }
.services__text { max-width: 300px; color: var(--muted-inv); font-size: 16px; line-height: 1.25; }
.services__intro .btn { margin-top: 18px; }

/* Mobile: number, name and description stacked */
.service {
  display: grid;
  row-gap: 10px;
  padding: 22px 0;
  border-top: 1px solid var(--line-inv);
}
/* Lines only between services: none above the first or below the last */
.service:first-child { border-top: 0; }
.service__n { color: var(--muted-inv); }
.service__name {
  font-family: var(--f-head);
  font-weight: 500;
  font-size: clamp(28px, 8vw, 40px);
  line-height: 1.05;
  letter-spacing: -.035em;
  transition: transform .9s var(--ease);
}
/* Every description reserves two lines, so rows stay the same height when one wraps */
.service__desc { max-width: 380px; min-height: 2.6em; color: var(--muted-inv); font-size: 14px; line-height: 1.3; }

/* ---------- FAQ ---------- */

.faq { display: grid; gap: 48px; padding: 140px var(--g) 160px; }
.faq__head { display: grid; gap: 22px; align-content: start; }
.faq__list { border-top: 1px solid #D4D4D4; }
.faq__item { border-bottom: 1px solid #D4D4D4; }
.faq__q {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  width: 100%;
  padding: 22px 0;
  text-align: left;
  font-family: var(--f-head);
  font-weight: 500;
  font-size: clamp(19px, 1.6vw, 24px);
  line-height: 1.2;
  letter-spacing: -.02em;
}
.faq__icon { position: relative; flex: none; width: 12px; height: 12px; }
.faq__icon::before, .faq__icon::after {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 100%;
  height: 1px;
  background: currentColor;
  transition: transform .5s var(--ease);
}
.faq__icon::after { transform: rotate(90deg); }
.faq__item.is-open .faq__icon::after { transform: rotate(0deg); }
/* Answers are collapsed only once main.js has wired the accordion, so they stay readable without JS */
.faq__list.is-ready .faq__a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .6s var(--ease); }
.faq__list.is-ready .faq__item.is-open .faq__a { grid-template-rows: 1fr; }
.faq__inner { overflow: hidden; }
.faq__inner p { max-width: 560px; padding: 0 36px 26px 0; color: var(--gray); font-size: 16px; line-height: 1.4; }

/* ---------- Contact page (dark, over a full-bleed film) ---------- */

html[data-page="contact"] { background: var(--black); }
html[data-page="contact"] body { background: var(--black); color: var(--white); }
html[data-page="contact"] ::selection { background: var(--white); color: var(--black); }

/* Dark glass nav on the contact and work pages only: one thin border, no inner highlight.
   On work.html it only applies over the dark header; main.js adds .on-light over the white list and the footer. */
html[data-page="contact"] .nav__pill,
html[data-page="work"] .nav:not(.on-light) .nav__pill {
  background: var(--glass-dark-bg);
  border: 1px solid var(--glass-dark-line);
  -webkit-backdrop-filter: var(--glass-filter);
  backdrop-filter: var(--glass-filter);
}
html[data-page="contact"] .nav__mark,
html[data-page="work"] .nav:not(.on-light) .nav__mark { color: var(--white); }
html[data-page="contact"] .nav__cta,
html[data-page="work"] .nav:not(.on-light) .nav__cta { background: var(--white); color: var(--black); }
html[data-page="contact"] .nav__toggle,
html[data-page="work"] .nav:not(.on-light) .nav__toggle { background: rgba(255, 255, 255, .12); }
html[data-page="contact"] .nav__toggle span,
html[data-page="work"] .nav:not(.on-light) .nav__toggle span { background: var(--white); }
html[data-page="contact"] .nav__menu,
html[data-page="work"] .nav:not(.on-light) .nav__menu {
  background: rgba(10, 10, 10, .72);
  color: var(--white);
  border: 1px solid var(--glass-dark-line);
  -webkit-backdrop-filter: var(--glass-filter);
  backdrop-filter: var(--glass-filter);
}
html[data-page="contact"] .menu__link .label,
html[data-page="work"] .nav:not(.on-light) .menu__link:not([aria-current]) .label { color: var(--muted-inv); }

/* work.html: fade between the dark and light pill */
html[data-page="work"] .nav__pill { border: 1px solid transparent; transition: background-color .4s var(--ease), border-color .4s var(--ease); }
html[data-page="work"] .nav__mark,
html[data-page="work"] .nav__toggle { transition: color .4s var(--ease), background-color .4s var(--ease), opacity .5s var(--ease), visibility .5s; }
html[data-page="work"] .nav__toggle span { transition: background-color .4s var(--ease), transform .8s var(--ease); }
html[data-page="work"] .nav.on-light .nav__sym img { filter: invert(1); }

/* Background: film, or a near-black gradient until the file is added */
.cbg {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: radial-gradient(120% 90% at 75% 20%, #1B1B1B 0%, var(--black) 62%);
}
/* Phones: 36% across keeps the runner's head and torso in the narrow crop (centred shows only the jacket) */
.cbg__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 36% 50%; }
.cbg__shade {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, rgba(10, 10, 10, .7) 0%, rgba(10, 10, 10, 0) 45%),
    linear-gradient(to right, rgba(10, 10, 10, .6) 0%, rgba(10, 10, 10, 0) 55%),
    rgba(10, 10, 10, .35);
}

.cpage {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-areas: "title" "card" "details";
  gap: 36px;
  align-content: start;
  padding: 112px var(--g) 56px;
}
/* Same fluid size and line-height as the home intro H1 */
.cpage__title { grid-area: title; font-size: clamp(24px, 2.25vw, 34px); line-height: 1.05; }
.cpage__details { grid-area: details; display: grid; gap: 16px; align-content: start; }
.clabel { margin-bottom: 6px; font-family: var(--f-mono); font-size: 11px; letter-spacing: .02em; text-transform: uppercase; color: rgba(255, 255, 255, .5); }
.cval { font-family: var(--f-mono); font-size: 12px; letter-spacing: .02em; text-transform: uppercase; color: var(--white); }

.ccard {
  grid-area: card;
  position: relative;
  width: 100%;
  padding: 8px;
  border-radius: 24px;
  background: var(--glass-dark-bg);
  border: 1px solid var(--glass-dark-line);
  box-shadow: var(--glass-dark-shadow);
  -webkit-backdrop-filter: var(--glass-filter);
  backdrop-filter: var(--glass-filter);
}
.cform { display: grid; gap: 6px; }
.cform[hidden] { display: none; }

/* Rows: single line, fixed height, no border at rest */
.cfield {
  position: relative;
  display: block;
  height: 55px;
  border-radius: 16px;
  border: 1px solid transparent;
  background: rgba(255, 255, 255, .06);
  transition: border-color .3s var(--ease), background-color .3s var(--ease);
}
.cfield--area { height: 84px; }
.cfield:hover { background: rgba(255, 255, 255, .08); }
.cfield:focus-within, .cfield.is-open { border-color: rgba(255, 255, 255, .4); }

/* The label sits in the row like a placeholder, and moves up to a 10px caption once the field is focused or filled */
.cfield__label {
  position: absolute;
  top: 50%;
  left: 16px;
  font-family: var(--f-mono);
  font-size: 12px;
  line-height: 1;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .55);
  transform: translateY(-6px);
  transform-origin: left top;
  pointer-events: none;
  transition: transform .35s var(--ease);
}
.cfield:focus-within .cfield__label,
.cfield.is-open .cfield__label,
.cfield:has(input:not(:placeholder-shown)) .cfield__label,
.cfield:has(textarea:not(:placeholder-shown)) .cfield__label,
.cfield:has(select:valid) .cfield__label { transform: translateY(-17.5px) scale(.8333); }
.cfield:has(input:-webkit-autofill) .cfield__label { transform: translateY(-17.5px) scale(.8333); }
.cfield--area .cfield__label { top: 17px; transform: none; }
.cfield--area:focus-within .cfield__label,
.cfield--area:has(textarea:not(:placeholder-shown)) .cfield__label { transform: translateY(-8px) scale(.8333); }

.cfield input, .cfield textarea, .cfield select {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 22px 16px 6px;
  border: 0;
  border-radius: 15px;
  background: transparent;
  color: var(--white);
  font: 400 14px/1.2 var(--f-body);
  outline: none;
}
.cfield input::placeholder, .cfield textarea::placeholder { color: transparent; }
/* Below desktop, typed text is 16px: iOS Safari zooms the page into any field under 16px */
@media (max-width: 1023px) { .cfield input, .cfield textarea, .cfield select { font-size: 16px; } }
.cfield input:-webkit-autofill { -webkit-text-fill-color: var(--white); transition: background-color 9999s; }
.cfield textarea { padding: 26px 16px 8px; line-height: 1.4; resize: none; }
.cfield select { padding-right: 44px; -webkit-appearance: none; appearance: none; cursor: pointer; }
.cfield select option { background: #141414; color: var(--white); }
.cfield--select::after {
  content: "";
  position: absolute;
  right: 20px;
  top: 50%;
  width: 6px;
  height: 6px;
  margin-top: -5px;
  border-right: 1.5px solid rgba(255, 255, 255, .7);
  border-bottom: 1.5px solid rgba(255, 255, 255, .7);
  transform: rotate(45deg);
  transition: transform .35s var(--ease);
  pointer-events: none;
}
.cfield.is-open { z-index: 5; }
.cfield.is-open::after { transform: translateY(3px) rotate(225deg); }

/* Desktop dropdown list (main.js); touch keeps the native picker */
.cselect__list {
  position: absolute;
  left: -1px;
  right: -1px;
  top: calc(100% + 6px);
  margin: 0;
  padding: 6px;
  list-style: none;
  border-radius: 16px;
  background: rgba(18, 18, 18, .94);
  border: 1px solid var(--glass-dark-line);
  box-shadow: var(--glass-dark-shadow);
  -webkit-backdrop-filter: var(--glass-filter);
  backdrop-filter: var(--glass-filter);
  outline: none;
  /* Closed lists leave the layout entirely (an invisible list under the last field would make the page scroll);
     the fade still runs both ways where display can transition (allow-discrete + @starting-style) */
  display: none;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity .25s var(--ease), transform .25s var(--ease), display .25s allow-discrete;
}
.cfield.opens-up .cselect__list { top: auto; bottom: calc(100% + 6px); transform: translateY(4px); }
.cfield.is-open .cselect__list { display: block; opacity: 1; transform: none; }
@starting-style {
  .cfield.is-open .cselect__list { opacity: 0; transform: translateY(-4px); }
  .cfield.is-open.opens-up .cselect__list { transform: translateY(4px); }
}
.cselect__opt {
  display: flex;
  align-items: center;
  height: 44px;
  padding: 0 12px;
  border-radius: 10px;
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .7);
  cursor: pointer;
}
.cselect__opt.is-active { background: rgba(255, 255, 255, .08); color: var(--white); }
.cselect__opt[aria-selected="true"] { color: var(--white); }
.cselect__opt[aria-selected="true"]::after { content: "\00a0\00a0•"; }

.cform__submit {
  height: 52px;
  border-radius: 16px;
  background: var(--white);
  color: var(--black);
  font-family: var(--f-mono);
  font-size: 13px;
  letter-spacing: .02em;
  text-transform: uppercase;
  transition: background-color .4s var(--ease);
}
.cform__submit:hover { background: rgba(255, 255, 255, .86); }
.cform__submit:focus-visible { outline: 1px solid var(--white); outline-offset: 3px; }

.ccard__success { padding: 40px 20px; outline: none; }
.ccard__success p { font-family: var(--f-head); font-weight: 500; font-size: 22px; letter-spacing: -.02em; line-height: 1.15; }

.cbar {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 24px;
  padding: 0 var(--g) 20px;
  color: rgba(255, 255, 255, .55);
}

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

.footer { position: relative; overflow: hidden; background: var(--light); padding: 24px var(--g) 20px; }
.footer__top { display: flex; justify-content: space-between; align-items: center; }
.footer__top img { width: 32px; height: 32px; }
.footer__cols { display: grid; grid-template-columns: 1fr 1fr; gap: 36px 20px; margin-top: 64px; }
.footer__cols .muted { margin-bottom: 14px; }
.footer__links { display: grid; justify-content: start; gap: 6px 20px; white-space: nowrap; }
.footer__cols a { white-space: nowrap; }
/* Email and Instagram sit as blocks so their first line lines up with the nav list and Studio */
.footer__cols > div > a { display: block; width: max-content; }
/* [ Let's work together ]: a footer link in orange. Mobile: its own row above the other columns */
.footer__cta { grid-column: 1 / -1; }
.footer__cta a { color: var(--accent); }
.footer__giant { margin-top: 72px; overflow: hidden; padding-bottom: .04em; }
.footer__giant .wordmark { display: inline-flex; font-size: 17vw; line-height: .9; }
.footer__giant .ch { display: inline-block; }
/* Letters rest at width 140 on the variable width axis; main.js moves them between 134 and 150 on hover. The period stays at 150. */
.footer__giant .ch:not(.dot) { font-variation-settings: 'wdth' 140; }
/* Script-driven only: no CSS transitions (the reduced-motion rule's 0.01ms transitions would make the width fit read stale sizes) */
.footer__giant .wordmark, .footer__giant .ch { transition: none !important; }
.footer__bottom {
  display: grid;
  gap: 8px;
  margin-top: 20px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.footer__bottom button { justify-self: start; }

/* Bar-only footer (project pages and work.html): one strip, no divider.
   Mobile: copyright and Back to top on one line, the tagline below. */
.footer--bar { padding: 28px var(--g); }
.footer--bar .footer__bottom { grid-template-columns: 1fr auto; align-items: center; gap: 10px 20px; margin-top: 0; padding-top: 0; border-top: 0; }
.footer--bar .footer__bottom > :nth-child(2) { grid-column: 1 / -1; grid-row: 2; }
.footer--bar .footer__bottom button { grid-column: 2; grid-row: 1; justify-self: end; }

/* ---------- Project page ---------- */

.project__name a { padding-bottom: 2px; }

.case-head { padding: 140px var(--g) 56px; }
.case-head__labels { display: flex; justify-content: space-between; gap: 16px; }
.case-head__title { margin-top: 40px; }
.case-head__body { display: grid; gap: 28px; margin-top: 48px; }
.case-head__body .lead { max-width: 480px; }
/* Phones: a quieter description */
@media (max-width: 767px) {
  .case-head__body .lead { font-size: 17px; line-height: 1.4; font-weight: 400; letter-spacing: -.005em; }
}
/* Tablet and desktop: about 50% wider measure (about 69 characters per line) */
@media (min-width: 768px) {
  .case-head__body .lead { max-width: 720px; }
}

.case-media { position: relative; overflow: hidden; }
.case-media__inner { position: absolute; inset: -8% 0; }
.case-media--hero { aspect-ratio: 4 / 5; }
.case-gallery { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 8px var(--g) 0; }
.case-media--half, .case-media--wide { grid-column: span 2; }
.case-media--half { aspect-ratio: 4 / 5; }
.case-media--wide { aspect-ratio: 16 / 9; }
.case-media--story { aspect-ratio: 9 / 16; }

.case-next { display: grid; gap: 32px; padding: 64px var(--g); }
.case-next__name {
  font-family: var(--f-brand);
  font-stretch: 150%;
  letter-spacing: -.04em;
  transition: transform .9s var(--ease);
}
.case-next:hover .case-next__name { transform: translateX(16px); }

/* Images inside the parallax media boxes (home cards) */
.project__inner > img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* ---------- Look Closer (work/project-03.html) ---------- */

.lc-tags { display: flex; flex-wrap: wrap; align-content: start; gap: 6px 16px; }
.lc-intro { display: grid; gap: 24px; }

/* People: one section each, in normal flow. Label top left, 4:5 frame centred (--lc-w), progress line under it.
   The page script adds .is-live: the close-ups join the frame and crossfade behind the arrows. Without JS the
   <noscript> list stacks them under the portrait. */
.lc-p { --lc-w: min(100%, 62.4svh); display: grid; grid-template-rows: auto 1fr auto; row-gap: 12px; padding: 24px var(--g) 48px; }
.lc-p__stage { position: relative; justify-self: center; align-self: center; width: var(--lc-w); }
.lc-p__frame { position: relative; aspect-ratio: 4 / 5; overflow: hidden; background: var(--ph-1); touch-action: pan-y; }
.lc-p__frame .lc-p__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .2s ease; }
.lc-p__frame .lc-p__img.is-active { z-index: 2; opacity: 1; }
/* The outgoing frame stays opaque under the incoming one, so the crossfade never dips to the background */
.lc-p__frame .lc-p__img.is-leaving { z-index: 1; opacity: 1; transition: none; }
/* Progress line: 2px light gray track, black fill at (photo / photos), as wide as the frame */
.lc-p__bar { justify-self: center; width: var(--lc-w); height: 2px; overflow: hidden; background: var(--ph-2); }
.lc-p__fill { display: block; height: 100%; background: var(--black); transform-origin: 0 50%; transition: transform .3s var(--ease); }
.lc:not(.is-live) .lc-p__bar { visibility: hidden; }
.lc-p__rest { display: grid; gap: 8px; width: min(100%, 62.4svh); margin: 8px auto 0; }
.lc-p__rest .lc-p__img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }

/* Arrows: thin chevrons, 44px hit area. Phones and tablets: over the frame edges, white with a soft shadow. */
.lc-p__arrow { position: absolute; top: 50%; z-index: 3; display: grid; place-items: center; width: 44px; height: 44px; margin-top: -22px; padding: 0; border: 0; background: none; color: var(--white); cursor: pointer; transition: opacity .3s var(--ease), transform .3s var(--ease); }
.lc-p__arrow[hidden] { display: none; }
.lc-p__arrow svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.5; filter: drop-shadow(0 0 4px rgba(10, 10, 10, .55)); }
.lc-p__arrow svg path { vector-effect: non-scaling-stroke; }
.lc-p__arrow--prev { left: 0; }
.lc-p__arrow--next { right: 0; }
.lc-p__arrow[aria-disabled="true"] { opacity: .25; cursor: default; }
.lc-p__arrow:focus-visible { outline: 1px solid currentColor; outline-offset: -4px; }
@media (hover: hover) and (pointer: fine) {
  .lc-p__arrow--prev:not([aria-disabled="true"]):hover { transform: translateX(-3px); }
  .lc-p__arrow--next:not([aria-disabled="true"]):hover { transform: translateX(3px); }
}
@media (prefers-reduced-motion: reduce) {
  .lc-p__frame .lc-p__img, .lc-p__fill { transition: none; }
}
/* Phones: a tighter header so the first portrait is on screen at load */
@media (max-width: 767px) {
  .lc-head { padding-top: 112px; padding-bottom: 16px; }
  .lc-head .case-head__title { margin-top: 28px; }
  .lc-head .case-head__body { margin-top: 32px; gap: 20px; }
}

/* Closing: line and link to contact */
.lc-end { display: grid; gap: 24px; padding: 120px var(--g) 0; }
.lc-end__line { font-family: var(--f-head); font-weight: 500; font-size: clamp(24px, 2.25vw, 34px); line-height: 1.05; letter-spacing: -.02em; }
.lc-end__cta { justify-self: start; font-family: var(--f-head); font-weight: 500; font-size: 20px; letter-spacing: -.01em; padding-bottom: 2px; }

@media (min-width: 768px) {
  /* About a screen per person, so the next one peeks in. Frame about 80svh, sized so that after a jump link
     (which stops 90px from the top) the whole frame and its progress line sit below the nav pill. */
  .lc-p { --lc-w: min(100%, 64svh, (100svh - 190px) * .8); min-height: 92svh; }
  .lc-p__rest { width: min(100%, 64svh); }
}
@media (min-width: 1024px) {
  /* Desktop: arrows outside the frame, in the gutters, black */
  .lc-p__arrow { color: var(--black); }
  .lc-p__arrow svg { filter: none; }
  .lc-p__arrow--prev { left: auto; right: calc(100% + 12px); }
  .lc-p__arrow--next { right: auto; left: calc(100% + 12px); }
  .lc-p__arrow:focus-visible { outline-offset: 2px; }
}

/* ---------- Project transition cover ---------- */

/* Sits under the nav (z 100) so the pill stays put while the page changes, as on the reference */
.pt {
  position: fixed;
  inset: 0;
  z-index: 95;
  display: grid;
  place-items: center;
  background: var(--black);
  color: var(--white);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
html.pt-in { background: var(--black); }
html.pt-in .pt { opacity: 1; visibility: visible; }
.pt__mask { display: block; overflow: hidden; padding: 0 var(--g) .12em; }
.pt__name {
  display: block;
  font-family: var(--f-head);
  font-weight: 500;
  font-size: clamp(26px, 2.6vw, 40px);
  line-height: 1.1;
  letter-spacing: -.02em;
  text-align: center;
}

/* ---------- 404 ---------- */

.lost { min-height: 100svh; display: grid; align-content: center; justify-items: start; gap: 28px; padding: 120px var(--g); }
.lost .h1 { font-size: clamp(34px, 7vw, 112px); }

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

@media (min-width: 768px) {
  .cbg__video { object-position: 50% 50%; }
  .hero__media { height: 70svh; min-height: 520px; }
  .hero__bar { z-index: 1; justify-content: space-between; }
  .hero__clock, .hero__loc { display: block; }
  /* Light band so the black clock and location stay readable on the dark frames of the video (the sea) */
  .hero__media::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 110px; background: linear-gradient(to top, rgba(255, 255, 255, .4), rgba(255, 255, 255, 0)); pointer-events: none; }
  .hero__cta-wrap { position: absolute; left: 0; right: 0; pointer-events: none; }
  .hero__cta-wrap .btn { pointer-events: auto; }
  .intro__clock { display: none; }

  .project { grid-template-columns: 40.625% 1fr; column-gap: 20px; margin-bottom: 0; }
  .project__media { aspect-ratio: auto; height: clamp(420px, 41.67vw, 720px); }
  .project__meta { align-self: center; padding: 0 var(--g) 0 0; }
  .work.is-stack .project:not(:last-child) { padding-bottom: 0; }

  /* Caption beside the card, on its right, bottom-aligned */
  .work-hero { min-height: clamp(380px, 50svh, 560px); }
  .wlist { --wl-max: min(50vw, 520px); --wl-min-k: .55; }
  .wlist .wlist__meta { position: absolute; left: calc(100% + 20px); bottom: 0; width: max-content; padding: 0; justify-items: start; text-align: left; }
  .wlist .wlist__meta .meta div { justify-content: flex-start; }
  .wlist.is-live .wlist__meta { top: auto; right: auto; left: calc(100% + 20px); }

  .footer__cols { grid-template-columns: repeat(4, 1fr); }
  /* Line up with the links under the EMAIL / INSTAGRAM / STUDIO headings (heading line 11px x 1.3 + 14px gap) */
  .footer__cta { grid-column: auto; padding-top: calc(11px * 1.3 + 14px); }
  .footer__bottom { grid-template-columns: 1fr auto 1fr; align-items: center; }
  .footer__bottom > :nth-child(2) { text-align: center; }
  .footer__bottom button { justify-self: end; }
  .footer--bar .footer__bottom { grid-template-columns: 1fr auto 1fr; }
  .footer--bar .footer__bottom > :nth-child(2) { grid-column: 2; grid-row: 1; }
  .footer--bar .footer__bottom button { grid-column: 3; }


  .case-media--hero { aspect-ratio: 16 / 9; }
  .case-gallery { grid-template-columns: repeat(4, 1fr); }
  .case-media--half, .case-media--wide { grid-column: span 2; }
  .case-media--wide { grid-column: span 4; }
  .case-media--story { grid-column: span 2; aspect-ratio: 4 / 5; }

  /* Services rows: number | name | 320px description, all top-aligned.
     --svc-fs: clamp(26px, 2.5vw, 38px), capped to the name column so the longest name ("Launch Campaign", 7.45em) stays on one line.
     --svc-cap drops the number and description by the name's cap-height offset, so their first lines line up with it. */
  .services__list { container-type: inline-size; }
  .service {
    --svc-fs: min(clamp(26px, 2.5vw, 38px), calc((100cqi - 432px) / 7.6));
    --svc-cap: calc(var(--svc-fs) * .16 - 4px);
    grid-template-columns: 64px minmax(0, 1fr) 320px;
    column-gap: 24px;
    row-gap: 0;
    align-items: start;
    padding: 28px 0;
  }
  .service__n { padding-top: var(--svc-cap); }
  .service__name { font-size: var(--svc-fs); }
  .service__desc { max-width: none; padding-top: var(--svc-cap); min-height: calc(2.6em + var(--svc-cap)); }
}

/* ---------- Desktop ---------- */

@media (min-width: 1024px) {
  /* Right column starts at 58% of the viewport and runs to the right page padding */
  .intro {
    grid-template-columns: calc(58vw - var(--g) - 20px) minmax(0, 1fr);
    column-gap: 20px;
    align-items: start;
    min-height: 30svh;
    padding-top: 48px;
    padding-bottom: 40px;
  }
  .intro .h1 { grid-column: 1; grid-row: 1; }
  .intro__text { grid-column: 2; grid-row: 1; padding-top: 0; max-width: 680px; }

  .wlist { --wl-max: min(33vw, 520px); }

  .services { grid-template-columns: calc(31.94% - 20px) 1fr; column-gap: 20px; }
  .services__intro { position: sticky; top: 110px; }
  .service:hover .service__name { transform: translateX(12px); }

  .faq { grid-template-columns: calc(31.94% - 20px) 1fr; column-gap: 20px; padding-top: 180px; padding-bottom: 220px; }
  .faq__head { position: sticky; top: 110px; align-self: start; }

  /* Contact: one screen. H1 centred on the card's middle, details below it, card on the right, 6vw side margins. */
  html[data-page="contact"] body { position: relative; }
  .cpage {
    min-height: 100svh;
    grid-template-columns: minmax(0, 1fr) clamp(380px, 28vw, 480px);
    grid-template-rows: minmax(0, 1fr) auto minmax(0, 1fr);
    grid-template-areas: ". card" "title card" "details card";
    column-gap: 6vw;
    row-gap: 0;
    padding: 96px 6vw 56px;
  }
  .ccard { align-self: center; }
  .cpage__details { align-self: start; padding-top: 48px; }
  /* Two columns: the text sits on black beside the runner, so the flat layer drops from 35% to 15% and the runner keeps its tone */
  .cbg__shade {
    background:
      linear-gradient(to top, rgba(10, 10, 10, .7) 0%, rgba(10, 10, 10, 0) 45%),
      linear-gradient(to right, rgba(10, 10, 10, .6) 0%, rgba(10, 10, 10, 0) 55%),
      rgba(10, 10, 10, .15);
  }
  .cbar { position: absolute; left: 0; right: 0; bottom: 0; display: grid; grid-template-columns: 1fr auto 1fr; padding: 0 6vw 20px; }
  .cbar > :nth-child(2) { text-align: center; }

  .case-head { padding-top: 180px; padding-bottom: 72px; }
  /* Description starts at the same x as the Services list column */
  .case-head__body { grid-template-columns: calc(31.94% - 20px) 1fr; column-gap: 20px; }
  /* Story pair sits in the two middle columns */
  .case-media--story { grid-column: span 1; aspect-ratio: 9 / 16; }
  .case-media--wide + .case-media--story { grid-column: 2 / span 1; }
}

/* ---------- VELT (work/project-01.html) ---------- */

/* Free collage. The canvas is full-bleed (capped at 1920px, centred) and keeps one aspect ratio per layout.
   Every photo is a frame: x, y, w, h in cqw (percent of the canvas width, so y and h use the same unit), stacked by z.
   Inside the frame the full image is placed from its crop (cx, cy, cw, ch, percent of the original), never stretched.
   Desktop values are on each .vf--name rule, phone values in the max-width: 767px block. */
.velt { padding-bottom: 168px; } /* 48px under the last Look Closer person + 120px above its closing block */
.velt-canvas { position: relative; width: 100%; max-width: 1920px; margin-inline: auto; aspect-ratio: 1440 / 8453; container-type: inline-size; overflow: hidden; background: var(--white); }
.vf {
  position: absolute; z-index: var(--z); margin: 0; overflow: hidden;
  left: calc(var(--x) * 1cqw); top: calc(var(--y) * 1cqw);
  width: calc(var(--w) * 1cqw); height: calc(var(--h) * 1cqw);
}
.vf img {
  position: absolute; display: block; max-width: none;
  width: calc(10000% / var(--cw)); height: calc(10000% / var(--ch));
  left: calc(-100% * var(--cx) / var(--cw)); top: calc(-100% * var(--cy) / var(--ch));
}
/* Reveal: armed by the page script only when motion is allowed */
.velt-canvas.is-armed .vf { opacity: 0; transform: translateY(12px); transition: opacity .9s var(--ease), transform .9s var(--ease); }
.velt-canvas.is-armed .vf.is-in { opacity: 1; transform: none; }

.vf--billboard  { --x: 0;       --y: .069;    --w: 100;    --h: 75;      --z: 3; --cx: 13.96; --cy: 23.378; --cw: 66.667; --ch: 66.667; }
.vf--website    { --x: 2.992;   --y: 80;      --w: 67.627; --h: 58.257;  --z: 2; --cx: 0;     --cy: 20.298; --cw: 100;    --ch: 79.702; }
.vf--form       { --x: 61.574;  --y: 80;      --w: 38.426; --h: 45.098;  --z: 6; --cx: 0;     --cy: 2.729;  --cw: 100;    --ch: 94.542; }
.vf--symbol     { --x: 45.347;  --y: 125.098; --w: 33.25;  --h: 44.507;  --z: 7; --cx: 0;     --cy: 0;      --cw: 100;    --ch: 100; }
.vf--foldable   { --x: 0;       --y: 169.925; --w: 100;    --h: 97.04;   --z: 8; --cx: 0;     --cy: 10.432; --cw: 100;    --ch: 77.632; }
.vf--packaging  { --x: 18.051;  --y: 264.375; --w: 63.898; --h: 79.872;  --z: 4; --cx: 0;     --cy: 0;      --cw: 100;    --ch: 100; }
.vf--phone      { --x: 0;       --y: 351.927; --w: 99.954; --h: 74.433;  --z: 5; --cx: 2.24;  --cy: 3.24;   --cw: 96.76;  --ch: 96.76; }
.vf--montage    { --x: 2.755;   --y: 430.109; --w: 94.444; --h: 118.056; --z: 1; --cx: 0;     --cy: 0;      --cw: 100;    --ch: 100; }
.vf--drip       { --x: 2.755;   --y: 523.489; --w: 51.207; --h: 63.567;  --z: 9; --cx: 0;     --cy: 0;      --cw: 100;    --ch: 100; }

@media (max-width: 767px) {
  .velt-canvas { aspect-ratio: 390 / 2927; }
  .vf--montage    { --x: 4.103;   --y: 0;       --w: 92.322;  --h: 115.403; --z: 3; --cx: 0;      --cy: 0;      --cw: 100;    --ch: 100; }
  .vf--drip       { --x: -5.374;  --y: 99.608;  --w: 64.615;  --h: 80.212;  --z: 4; --cx: 0;      --cy: 0;      --cw: 100;    --ch: 100; }
  .vf--symbol     { --x: 54.512;  --y: 121.473; --w: 43.59;   --h: 58.348;  --z: 2; --cx: 0;      --cy: 0;      --cw: 100;    --ch: 100; }
  .vf--foldable   { --x: -2.711;  --y: 179.821; --w: 102.711; --h: 104.164; --z: 5; --cx: 1.519;  --cy: 6.297;  --cw: 97.086;  --ch: 78.767; }
  .vf--packaging  { --x: 5.647;   --y: 276.565; --w: 88.615;  --h: 104.622; --z: 1; --cx: 0;      --cy: 0;      --cw: 100;    --ch: 94.45; }
  .vf--billboard  { --x: -.162;   --y: 393.294; --w: 103.178; --h: 77.383;  --z: 6; --cx: 11.852; --cy: 21.702; --cw: 73.604;  --ch: 73.604; }
  .vf--website    { --x: 3.016;   --y: 476.096; --w: 92.573;  --h: 100.15;  --z: 8; --cx: 0;      --cy: 13.811; --cw: 86.108;  --ch: 86.189; }
  .vf--phone      { --x: -.162;   --y: 585.423; --w: 100.955; --h: 75.178;  --z: 7; --cx: 0;      --cy: 0;      --cw: 100;    --ch: 100; }
  .vf--form       { --x: 23.863;  --y: 669.691; --w: 55.128;  --h: 68.435;  --z: 9; --cx: 0;      --cy: 0;      --cw: 100;    --ch: 100; }
}

/* ---------- LÄTT (work/project-02.html) ---------- */

/* Same canvas component as VELT (.velt, .velt-canvas, .vf). Only the aspect ratios and the per-photo values change.
   Keys are the layout ids of the photos. Desktop values here, phone values in the max-width: 767px block. */
.velt-canvas--latt { aspect-ratio: 1440 / 5914; }

.vf--l-cce4e5b2 { --x: 0;       --y: 0;        --w: 99.977; --h: 55.8011; --z: 1;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-6f79f3f1 { --x: 40.9722; --y: 140.162;  --w: 16.6667; --h: 29.6296; --z: 2;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-03a88419 { --x: 70.6944; --y: 117.9977; --w: 20.8333; --h: 33.3081; --z: 3;  --cx: 0;      --cy: 10.7654; --cw: 100;    --ch: 89.2346; }
.vf--l-cbfba9d1 { --x: 33.6806; --y: 116.5316; --w: 33.3333; --h: 59.7222; --z: 4;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-1b2f4bd6 { --x: 34.9501; --y: 60.2763;  --w: 30.7943; --h: 54.7454; --z: 5;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-1178ef9b { --x: 20.2083; --y: 160.7063; --w: 21.4912; --h: 34.3785; --z: 6;  --cx: 0;      --cy: 10.7172; --cw: 100;    --ch: 89.2828; }
.vf--l-6e0304fe { --x: 0;       --y: 198.289;  --w: 99.977; --h: 65.0961; --z: 7;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-dd030448 { --x: 2.0833;  --y: 146.6242; --w: 16.6667; --h: 29.6296; --z: 8;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-0423d53f { --x: 2.0833;  --y: 60.2763;  --w: 30.5556; --h: 54.7454; --z: 9;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-ebb42750 { --x: 0;       --y: 336.0125; --w: 99.977; --h: 74.8104; --z: 10; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-e31b159f { --x: 63.5687; --y: 263.3851; --w: 36.4083; --h: 45.2434; --z: 11; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-2caf8309 { --x: 67.5694; --y: 60.2763;  --w: 30.5556; --h: 54.7454; --z: 12; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-c9144330 { --x: 74.8072; --y: 154.0141; --w: 23.3178; --h: 41.0707; --z: 13; --cx: 1.1301;  --cy: 1.6987;  --cw: 98.7575; --ch: 97.0864; }
.vf--l-3f307eca { --x: 2.0833;  --y: 265.9086; --w: 23.6111; --h: 42.0573; --z: 14; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-1f13c6a1 { --x: 67.5694; --y: 307.1605; --w: 28.6781; --h: 24.6914; --z: 15; --cx: 0;      --cy: 25.7848; --cw: 100;    --ch: 48.4304; }
.vf--l-797e12ea { --x: 13.2639; --y: 116.5316; --w: 19.0972; --h: 34.0169; --z: 16; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
.vf--l-e9dfdf17 { --x: 28.9388; --y: 265.9086; --w: 36.8056; --h: 65.9433; --z: 17; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }

@media (max-width: 767px) {
  .velt-canvas--latt { aspect-ratio: 390 / 6027; }
  .vf--l-e31b159f { --x: 0;       --y: 860.4951;  --w: 100;      --h: 124.2656; --z: 1;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
  .vf--l-cce4e5b2 { --x: 0;       --y: 0;         --w: 100;      --h: 55.8128;  --z: 2;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
  .vf--l-6f79f3f1 { --x: 54.8718; --y: 493.0769;  --w: 50.154;   --h: 89.1626;  --z: 3;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
  .vf--l-03a88419 { --x: -5.3109; --y: 493.0769;  --w: 55.7692;  --h: 89.1626;  --z: 4;  --cx: 0;      --cy: 10.7654; --cw: 100;    --ch: 89.2346; }
  .vf--l-cbfba9d1 { --x: -6.1381; --y: 659.7436;  --w: 113.1929; --h: 202.8028; --z: 5;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
  .vf--l-1178ef9b { --x: 38.922;  --y: 1226.1538; --w: 69.7436;  --h: 111.5641; --z: 6;  --cx: 0;      --cy: 10.7172; --cw: 100;    --ch: 89.2828; }
  .vf--l-6e0304fe { --x: 0;       --y: 587.0555;  --w: 100;      --h: 65.6243;  --z: 7;  --cx: 24.6487; --cy: 12.4895; --cw: 75.3513; --ch: 75.9452; }
  .vf--l-dd030448 { --x: 4.1026;  --y: 1007.1795; --w: 58.9744;  --h: 104.8436; --z: 8;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
  .vf--l-0423d53f { --x: 0.4584;  --y: 55.8128;   --w: 52.9487;  --h: 94.8667;  --z: 9;  --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
  .vf--l-ebb42750 { --x: -0.7478; --y: 1468.7179; --w: 102.4123; --h: 76.6333;  --z: 10; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
  .vf--l-2caf8309 { --x: 0.4584;  --y: 192.3432;  --w: 100;      --h: 179.1672; --z: 11; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
  .vf--l-797e12ea { --x: 19.2308; --y: 377.4359;  --w: 61.5385;  --h: 109.6154; --z: 12; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
  .vf--l-e9dfdf17 { --x: 0;       --y: 981.9949;  --w: 100;      --h: 179.1656; --z: 13; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
  .vf--l-1b2f4bd6 { --x: 47.5877; --y: 98.4661;   --w: 52.4123;  --h: 93.877;   --z: 14; --cx: 0.3726; --cy: 0;       --cw: 99.2548; --ch: 100; }
  .vf--l-3f307eca { --x: -0.9909; --y: 1167.3143; --w: 47.1293;  --h: 83.9487;  --z: 15; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 100; }
  .vf--l-c9144330 { --x: -0.7478; --y: 1298.9566; --w: 49.2308;  --h: 89.1626;  --z: 16; --cx: 3.8433; --cy: 1.6987;  --cw: 96.0443; --ch: 97.0869; }
  .vf--l-1f13c6a1 { --x: 42.8845; --y: 1367.6354; --w: 57.1155;  --h: 95.075;   --z: 17; --cx: 0;      --cy: 0;       --cw: 100;    --ch: 93.6343; }
}

/* ---------- Reduced motion ---------- */

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