/* ==========================================================================
   Side Dish Studio
   Brand carried over from the Google Sites build:
     background  #280F10   (deep maroon)
     accent      #EF4423   (brand red)
     ink-on-red  #1C1C1C

   Type
     headings    fabiola-capitals, loaded from Adobe Fonts (Typekit) via the
                 <link> in each page head. ONE weight (400) and NO italic
                 exists, so never set font-weight or font-style on a heading.
                 It is a capitals-only face: lowercase input renders as caps,
                 which is why heading letter-spacing is positive here while
                 the old Nunito scale used negative tracking.
     body        NickySans, self hosted below. Carries every weight the UI
                 uses (400-900) plus true italics.
   ========================================================================== */

/* ---------- NickySans (body + highlight text) ---------- */
@font-face{
  font-family:"NickySans"; src:url("/assets/fonts/NickySans-Regular.woff2") format("woff2");
  font-weight:400; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"NickySans"; src:url("/assets/fonts/NickySans-Italic.woff2") format("woff2");
  font-weight:400; font-style:italic; font-display:swap;
}
@font-face{
  font-family:"NickySans"; src:url("/assets/fonts/NickySans-SemiBold.woff2") format("woff2");
  font-weight:600; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"NickySans"; src:url("/assets/fonts/NickySans-Bold.woff2") format("woff2");
  font-weight:700; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"NickySans"; src:url("/assets/fonts/NickySans-BoldItalic.woff2") format("woff2");
  font-weight:700; font-style:italic; font-display:swap;
}
@font-face{
  font-family:"NickySans"; src:url("/assets/fonts/NickySans-ExtraBold.woff2") format("woff2");
  font-weight:800; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"NickySans"; src:url("/assets/fonts/NickySans-Black.woff2") format("woff2");
  font-weight:900; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"NickySans"; src:url("/assets/fonts/NickySans-BlackItalic.woff2") format("woff2");
  font-weight:900; font-style:italic; font-display:swap;
}

:root{
  --maroon:      #280F10;
  --maroon-deep: #1B0A0B;
  --maroon-soft: #331616;
  --red:         #EF4423;
  --red-bright:  #FF5A38;
  --ink:         #1C1C1C;
  --cream:       #F7EFEA;
  --cream-dim:   #C9B4AE;

  --body: "NickySans", system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  --head: "fabiola-capitals", "NickySans", Georgia, serif;

  --wrap: 1320px;
  --gut: clamp(20px, 5vw, 64px);

  --ease: cubic-bezier(.22,1,.36,1);
  --ease-out: cubic-bezier(.16,1,.3,1);

  --r-sm: 10px;
  --r-md: 18px;
  --r-lg: 28px;
}

/* ---------- reset ---------- */
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
body{
  margin:0;
  background:var(--maroon);
  color:var(--cream);
  font-family:var(--body);
  font-size:17px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img{ max-width:100%; display:block; }
/* <picture> only exists to offer a WebP source. display:contents keeps it
   out of the box tree entirely, so every layout rule below still applies to
   the <img> exactly as it did when the img was an unwrapped child. */
picture{ display:contents; }
a{ color:inherit; text-decoration:none; }
h1,h2,h3,p,ol,ul{ margin:0; }
ol{ padding:0; list-style:none; }
/* appearance:none first, or iOS Safari keeps its own padding and rounding on
   every button, including the gallery tiles */
button{
  -webkit-appearance:none; appearance:none;
  font:inherit; color:inherit; background:none; border:0; cursor:pointer;
}
em{ font-style:italic; }
::selection{ background:var(--red); color:var(--ink); }

/* Scroll lock behind the mobile menu and the lightbox. */
body.is-locked{ overflow:hidden; }

/* overflow:hidden alone does not hold the page on iOS Safari, it keeps
   scrolling behind the overlay, so pin the body at the offset lockScroll()
   recorded in --lock-top (main.js hands the offset back on release).
   --lock-gap stands in for the scrollbar that just disappeared, so desktop
   does not jump sideways.

   The pinning sits behind its own class on purpose. CSS and JS are cached
   separately for a day (see _headers), so a returning visitor can get one of
   them before the other. Anything that needs --lock-top must not apply until
   the JS that sets it is the version running. */
body.is-locked.is-pinned{
  position:fixed;
  top:var(--lock-top,0); left:0; right:0; width:100%;
  padding-right:var(--lock-gap,0);
}

.skip{
  position:fixed; top:-100px; left:16px; z-index:200;
  background:var(--red); color:var(--ink);
  padding:12px 18px; border-radius:var(--r-sm); font-weight:800;
  transition:top .2s var(--ease);
}
.skip:focus{ top:16px; }

:focus-visible{ outline:2px solid var(--red-bright); outline-offset:3px; border-radius:4px; }

/* Warm ambient wash + film grain.
   Both live on ONE fixed backdrop layer that sits *below* main (z-index 0 vs 1),
   so the texture never composites over the photography. Do not give this layer
   a mix-blend-mode: a blended layer escapes the z-order and washes out the
   images. The grain's strength is baked into the SVG's own opacity instead. */
body::before{
  content:""; position:fixed; inset:0; z-index:0; pointer-events:none;
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='160' height='160' filter='url(%23n)' opacity='.22'/></svg>"),
    radial-gradient(80vw 70vh at 78% -8%,  rgba(239,68,35,.20), transparent 62%),
    radial-gradient(60vw 60vh at 4% 42%,   rgba(239,68,35,.08), transparent 60%),
    radial-gradient(90vw 70vh at 50% 108%, rgba(239,68,35,.10), transparent 62%);
  background-repeat:repeat, no-repeat, no-repeat, no-repeat;
}
main,.nav,.footer,.marquee{ position:relative; z-index:1; }

.wrap{ width:100%; max-width:var(--wrap); margin-inline:auto; padding-inline:var(--gut); }

/* ==========================================================================
   Type scale

   fabiola-capitals is a very condensed face: at a given size it sets roughly
   half as wide as the Nunito it replaced, so the old numbers left every
   heading stranded in white space. These sizes are set from measured line
   widths instead, aiming for a longest line that fills ~85% of whatever box
   the heading sits in.

   Headings therefore need TWO sets of numbers, not one clamp. Below 1000px
   the hero and the about block go single column, so a heading has the full
   page width to fill and wants a much steeper vw slope; the overrides live in
   the max-width:1000px block down in Responsive. Change both or the phone
   drifts back to looking undersized.
   ========================================================================== */
.display{
  font-family:var(--head);
  font-weight:400;
  /* Bounded by viewport HEIGHT as well as width. A four line headline this
     size is tall enough that on a short laptop it would push the hero buttons
     below the fold, so the vh term wins there and the type steps down. The
     28vh - 96px figure is the height budget left over once the eyebrow, the
     sub, the buttons and the hero padding have taken their share. */
  font-size:max(4.5rem, min(10vw, 9.5rem, calc(28vh - 96px)));
  line-height:.86;
  letter-spacing:.005em;
  text-transform:uppercase;
  margin:.05em 0 0;
}
.display em{ color:var(--red); font-style:normal; }

.h2{
  font-family:var(--head);
  font-weight:400;
  font-size:clamp(3.2rem, 6.6vw, 6.25rem);
  line-height:1.0;
  letter-spacing:.005em;
  text-transform:uppercase;
}
.h2 em{ color:var(--red); font-style:normal; }

.lede{
  font-size:clamp(1rem, 1.35vw, 1.13rem);
  line-height:1.7;
  color:var(--cream-dim);
  max-width:56ch;
}
.h2 + .lede{ margin-top:clamp(24px,2.6vw,36px); }
.lede + .lede{ margin-top:1.1em; }

.label{
  display:flex; align-items:center; gap:14px;
  font-size:.75rem; font-weight:800;
  letter-spacing:.19em; text-transform:uppercase;
  color:var(--red);
  margin-bottom:26px;
}
.label__line{
  width:44px; height:2px; background:var(--red); flex:none;
  transform-origin:left; transform:scaleX(0);
  transition:transform .9s var(--ease) .1s;
}
.reveal.in .label__line,.label.in .label__line{ transform:scaleX(1); }

.eyebrow{
  display:flex; align-items:center; gap:14px;
  font-size:.8rem; font-weight:800;
  letter-spacing:.17em; text-transform:uppercase;
  color:var(--cream-dim);
}
.eyebrow__line{ width:36px; height:2px; background:var(--red); flex:none; }

/* ==========================================================================
   Nav
   ========================================================================== */
.nav{
  position:fixed; inset:0 0 auto 0; z-index:100;
  transition:background .45s var(--ease), backdrop-filter .45s var(--ease),
             border-color .45s var(--ease), padding .45s var(--ease);
  border-bottom:1px solid transparent;
  padding-block:22px;
}
.nav.is-stuck{
  background:rgba(27,10,11,.78);
  backdrop-filter:blur(14px) saturate(1.3);
  -webkit-backdrop-filter:blur(14px) saturate(1.3);
  border-bottom-color:rgba(247,239,234,.09);
  padding-block:13px;
}
.nav__inner{
  max-width:var(--wrap); margin-inline:auto; padding-inline:var(--gut);
  display:flex; align-items:center; justify-content:space-between; gap:24px;
}

.brand{ display:inline-flex; align-items:center; gap:11px; }
.brand__dot{
  width:11px; height:11px; border-radius:50%; background:var(--red); flex:none;
  box-shadow:0 0 0 0 rgba(239,68,35,.55);
  animation:pulse 3.2s var(--ease) infinite;
}
@keyframes pulse{
  0%,70%,100%{ box-shadow:0 0 0 0 rgba(239,68,35,.5); }
  35%{ box-shadow:0 0 0 9px rgba(239,68,35,0); }
}
/* The wordmark is a cream PNG on transparency, so it needs no colour rules.
   Height drives it; width:auto keeps the 4344:1556 ratio of the artwork. */
.brand__mark{ display:block; height:24px; width:auto; }
.brand--foot .brand__mark{ height:28px; }

.nav__links{ display:flex; align-items:center; gap:34px; }
.nav__links > a{
  font-size:.92rem; font-weight:800; letter-spacing:.01em;
  position:relative; padding-block:4px; color:var(--cream);
  transition:color .3s var(--ease);
}
.nav__links > a::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:2px;
  background:var(--red); transform:scaleX(0); transform-origin:right;
  transition:transform .45s var(--ease);
}
.nav__links > a:hover{ color:var(--red); }
.nav__links > a:hover::after{ transform:scaleX(1); transform-origin:left; }

.nav__cta{
  background:var(--red); color:var(--ink) !important;
  padding:11px 22px !important; border-radius:100px;
  transition:transform .35s var(--ease), background .3s var(--ease);
}
.nav__cta::after{ display:none; }
.nav__cta:hover{ background:var(--red-bright); transform:translateY(-2px); }

.burger{ display:none; width:42px; height:42px; position:relative; }
.burger span{
  position:absolute; left:10px; width:22px; height:2px; background:var(--cream);
  border-radius:2px; transition:transform .4s var(--ease), opacity .3s var(--ease);
}
.burger span:nth-child(1){ top:17px; }
.burger span:nth-child(2){ top:24px; }
.burger[aria-expanded="true"] span:nth-child(1){ transform:translateY(3.5px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2){ transform:translateY(-3.5px) rotate(-45deg); }

.mobilemenu{
  position:fixed; inset:0; z-index:99;
  background:var(--maroon-deep);
  display:flex; flex-direction:column; justify-content:center; gap:6px;
  padding:0 var(--gut);
  opacity:0; visibility:hidden;
  transition:opacity .4s var(--ease), visibility .4s;
}
.mobilemenu.is-open{ opacity:1; visibility:visible; }
.mobilemenu > a{
  font-family:var(--head);
  font-size:clamp(2.8rem,13vw,4.2rem); font-weight:400;
  letter-spacing:.01em; text-transform:uppercase;
  padding-block:10px;
  opacity:0; transform:translateY(18px);
  transition:opacity .5s var(--ease), transform .5s var(--ease), color .25s;
}
.mobilemenu.is-open > a{ opacity:1; transform:none; }
.mobilemenu.is-open > a:nth-child(1){ transition-delay:.06s; }
.mobilemenu.is-open > a:nth-child(2){ transition-delay:.12s; }
.mobilemenu.is-open > a:nth-child(3){ transition-delay:.18s; }
.mobilemenu.is-open > a:nth-child(4){ transition-delay:.24s; }
/* last link is the CTA ("Let's talk"), so it is the one picked out in red */
.mobilemenu.is-open > a:nth-child(5){ transition-delay:.30s; }
.mobilemenu > a:last-of-type{ color:var(--red); }
.mobilemenu__foot{
  margin-top:44px; display:flex; flex-direction:column; gap:8px;
  font-size:.95rem; color:var(--cream-dim);
  opacity:0; transition:opacity .5s var(--ease) .3s;
}
.mobilemenu.is-open .mobilemenu__foot{ opacity:1; }

/* ==========================================================================
   Hero
   ========================================================================== */
.hero{
  min-height:100svh;
  display:flex; flex-direction:column; justify-content:center;
  padding:116px var(--gut) 56px;
  max-width:var(--wrap); margin-inline:auto; width:100%;
  position:relative;
}
.hero__grid{
  display:grid;
  grid-template-columns:minmax(0,1.12fr) minmax(0,.88fr);
  gap:clamp(34px,5vw,72px);
  align-items:center;
}
.hero__copy{ min-width:0; }

/* headline: each line masked, slides up */
.line{ display:block; overflow:hidden; }
.line__in{
  display:block;
  transform:translateY(105%);
  transition:transform 1.05s var(--ease-out);
}
.hero.in .line__in{ transform:none; }
.hero.in .line:nth-child(1) .line__in{ transition-delay:.05s; }
.hero.in .line:nth-child(2) .line__in{ transition-delay:.13s; }
.hero.in .line:nth-child(3) .line__in{ transition-delay:.21s; }
.hero.in .line:nth-child(4) .line__in{ transition-delay:.29s; }

.hero__sub{
  margin-top:24px; max-width:46ch;
  font-size:clamp(1rem,1.4vw,1.18rem); line-height:1.65;
  color:var(--cream-dim);
}
.hero__actions{ display:flex; flex-wrap:wrap; gap:14px; margin-top:30px; }

.hero__media{ position:relative; min-width:0; }
.hero__frame{
  border-radius:var(--r-lg);
  overflow:hidden;
  aspect-ratio:4/3.1;
  box-shadow:0 40px 90px -30px rgba(0,0,0,.75);
}
.hero__frame img{
  width:100%; height:100%; object-fit:cover;
  transform:scale(1.09);
  transition:transform 1.4s var(--ease-out);
  will-change:transform;
}
.hero.in .hero__frame img{ transform:scale(1); }

.hero__badge{
  position:absolute; z-index:2; left:-26px; bottom:-26px;
  width:104px; height:104px; border-radius:50%;
  background:var(--red); color:var(--ink);
  display:grid; place-items:center; text-align:center;
  font-family:var(--head);
  font-weight:400; font-size:1.15rem; line-height:1.12; letter-spacing:.05em;
  text-transform:uppercase;
  box-shadow:0 18px 40px -14px rgba(0,0,0,.7);
  animation:float 6s ease-in-out infinite;
}
@keyframes float{ 0%,100%{ transform:translateY(0) } 50%{ transform:translateY(-9px) } }

.scrollcue{
  position:absolute; left:var(--gut); bottom:34px;
  display:flex; align-items:center; gap:13px;
  font-size:.72rem; font-weight:800; letter-spacing:.2em;
  text-transform:uppercase; color:var(--cream-dim);
  opacity:0; animation:fadeIn .8s var(--ease) 1.3s forwards;
}
@keyframes fadeIn{ to{ opacity:1 } }
.scrollcue__track{
  width:1px; height:44px; background:rgba(247,239,234,.22); position:relative; overflow:hidden;
}
.scrollcue__dot{
  position:absolute; left:-1px; width:3px; height:14px; background:var(--red);
  animation:cue 2.1s var(--ease) infinite;
}
@keyframes cue{ 0%{ top:-14px } 60%,100%{ top:44px } }

/* On a short window the headline eats the room the cue used to sit in and the
   two collide over the hero buttons. The cue is the most expendable thing in
   the hero, so it stands down rather than overlapping. */
@media (max-height:900px){ .scrollcue{ display:none; } }

/* ---------- buttons ---------- */
.btn{
  display:inline-flex; align-items:center; gap:11px;
  padding:16px 28px; border-radius:100px;
  font-weight:900; font-size:.95rem; letter-spacing:.01em;
  transition:transform .38s var(--ease), background .3s var(--ease),
             color .3s var(--ease), border-color .3s var(--ease);
  will-change:transform;
}
.btn svg{
  width:17px; height:17px; fill:none; stroke:currentColor;
  stroke-width:2.3; stroke-linecap:round; stroke-linejoin:round;
  transition:transform .38s var(--ease);
}
.btn:hover{ transform:translateY(-3px); }
.btn:hover svg{ transform:translateX(5px); }

.btn--primary{ background:var(--red); color:var(--ink); box-shadow:0 14px 34px -14px rgba(239,68,35,.8); }
.btn--primary:hover{ background:var(--red-bright); }
.btn--ghost{ border:1.5px solid rgba(247,239,234,.26); color:var(--cream); }
.btn--ghost:hover{ border-color:var(--red); color:var(--red); }
.btn--dark{ background:var(--ink); color:var(--cream); }
.btn--dark:hover{ background:#000; }

/* ==========================================================================
   Marquee
   ========================================================================== */
.marquee{
  border-block:1px solid rgba(247,239,234,.10);
  padding-block:20px;
  overflow:hidden;
  background:rgba(27,10,11,.4);
}
.marquee__row{ display:flex; width:max-content; animation:slide 34s linear infinite; }
.marquee:hover .marquee__row{ animation-play-state:paused; }
@keyframes slide{ to{ transform:translateX(-50%) } }
.marquee__set{ display:flex; align-items:center; flex:none; }
.marquee__set span{
  font-family:var(--head);
  font-weight:400; font-size:clamp(1.3rem,3vw,2.2rem);
  letter-spacing:.03em; text-transform:uppercase;
  padding-inline:24px; white-space:nowrap; color:var(--cream);
}
.marquee__set .sep{ color:var(--red); padding-inline:4px; font-size:1rem; }

/* ==========================================================================
   Sections
   ========================================================================== */
.section{ padding-block:clamp(80px,11vw,150px); }
.sechead{ margin-bottom:clamp(42px,6vw,74px); }
.sechead--split{
  display:flex; justify-content:space-between; align-items:flex-end;
  gap:40px; flex-wrap:wrap;
}
.sechead__note{ max-width:32ch; color:var(--cream-dim); font-size:1rem; }

/* ---------- work grid ----------
   A 12-column grid with an explicit row height. The row height is fixed rather
   than derived from the images, so every card fills its box exactly and no card
   can be stretched into a freak aspect ratio by a taller neighbour.
   Rows alternate 7+5 / 5+7 to keep the rhythm from feeling like a plain table. */
.workgrid{
  display:grid;
  grid-template-columns:repeat(12,1fr);
  grid-auto-rows:clamp(250px, 27vw, 400px);
  gap:clamp(14px,1.6vw,22px);
}
.card--lg{ grid-column:span 7; }
.card--sm{ grid-column:span 5; }
.card--wide{ grid-column:span 12; }

.card{
  position:relative; display:block;
  border-radius:var(--r-md); overflow:hidden;
  background:var(--maroon-soft);
  transition:transform .55s var(--ease);
  will-change:transform;
}
.card__media{ position:relative; overflow:hidden; width:100%; height:100%; }
.card__media img{
  width:100%; height:100%; object-fit:cover;
  transition:transform 1.1s var(--ease-out);
  will-change:transform;
}
.card__media::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(to top, rgba(27,10,11,.92) 0%, rgba(27,10,11,.35) 34%, rgba(27,10,11,0) 62%);
  opacity:.85; transition:opacity .5s var(--ease);
}
.card:hover{ transform:translateY(-6px); }
.card:hover .card__media img{ transform:scale(1.07); }
.card:hover .card__media::after{ opacity:1; }

.card__meta{
  position:absolute; left:0; right:0; bottom:0; z-index:2;
  padding:clamp(18px,2.2vw,28px);
  display:flex; flex-direction:column; gap:3px;
}
.card__meta h3{
  font-family:var(--head);
  font-size:clamp(1.35rem,2.5vw,2.1rem); font-weight:400;
  letter-spacing:.02em; text-transform:uppercase;
  transition:color .35s var(--ease);
}
.card__meta span{
  font-size:.76rem; font-weight:800; letter-spacing:.16em; text-transform:uppercase;
  color:var(--cream-dim);
}
.card:hover .card__meta h3{ color:var(--red); }

.card__arrow{
  position:absolute; top:16px; right:16px; z-index:2;
  width:42px; height:42px; border-radius:50%;
  background:var(--red); color:var(--ink);
  display:grid; place-items:center;
  opacity:0; transform:translate(8px,-8px) scale(.85);
  transition:opacity .45s var(--ease), transform .45s var(--ease);
}
.card__arrow svg{
  width:18px; height:18px; fill:none; stroke:currentColor;
  stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round;
}
.card:hover .card__arrow{ opacity:1; transform:none; }

/* ---------- about ---------- */
.about__grid{
  display:grid; grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  gap:clamp(38px,6vw,86px); align-items:center;
}
.about__frame{
  border-radius:var(--r-lg); overflow:hidden; aspect-ratio:4/3.2;
  box-shadow:0 40px 90px -34px rgba(0,0,0,.8);
}
.about__frame img{
  width:100%; height:100%; object-fit:cover;
  transform:scale(1.06); transition:transform 1.3s var(--ease-out);
}
.reveal.in .about__frame img{ transform:scale(1); }
.caption{
  margin-top:14px; font-size:.8rem; letter-spacing:.13em;
  text-transform:uppercase; font-weight:800; color:var(--cream-dim);
}

.stats{ display:flex; flex-wrap:wrap; gap:clamp(24px,4vw,52px); margin-top:44px; }
.stat{ display:flex; flex-direction:column; gap:6px; }
.stat b{
  font-family:var(--head);
  font-size:clamp(2.7rem,5.2vw,4.4rem); font-weight:400;
  line-height:1; letter-spacing:.01em; color:var(--red);
}
.stat span{
  font-size:.78rem; font-weight:800; letter-spacing:.13em;
  text-transform:uppercase; color:var(--cream-dim); line-height:1.45;
}

/* ---------- services ---------- */
.svc{ border-top:1px solid rgba(247,239,234,.14); }
.svc__row{
  position:relative;
  display:grid;
  grid-template-columns:76px minmax(0,1fr) minmax(0,1.25fr) 56px;
  align-items:center; gap:24px;
  padding-block:clamp(26px,3.4vw,40px);
  border-bottom:1px solid rgba(247,239,234,.14);
  transition:padding-inline .5s var(--ease);
}
.svc__row::before{
  content:""; position:absolute; inset:0; z-index:-1;
  background:linear-gradient(90deg, rgba(239,68,35,.14), rgba(239,68,35,0));
  opacity:0; transition:opacity .45s var(--ease);
}
.svc__row:hover{ padding-inline:clamp(0px,1.6vw,22px); }
.svc__row:hover::before{ opacity:1; }

.svc__num{
  font-size:.82rem; font-weight:900; letter-spacing:.14em; color:var(--red);
}
.svc__title{
  font-family:var(--head);
  font-size:clamp(1.8rem,4.4vw,3.6rem); font-weight:400;
  letter-spacing:.015em; line-height:1.0; text-transform:uppercase;
  transition:color .4s var(--ease);
}
.svc__row:hover .svc__title{ color:var(--red); }
.svc__desc{ color:var(--cream-dim); font-size:.98rem; line-height:1.65; max-width:46ch; }
.svc__arrow{
  justify-self:end;
  width:44px; height:44px; border-radius:50%;
  border:1.5px solid rgba(247,239,234,.22);
  display:grid; place-items:center;
  transition:background .4s var(--ease), border-color .4s var(--ease),
             color .4s var(--ease), transform .4s var(--ease);
}
.svc__arrow svg{
  width:17px; height:17px; fill:none; stroke:currentColor;
  stroke-width:2.3; stroke-linecap:round; stroke-linejoin:round;
}
.svc__row:hover .svc__arrow{
  background:var(--red); border-color:var(--red); color:var(--ink);
  transform:rotate(-45deg);
}

/* ---------- motion / video ----------
   A four column grid holding two shapes of video plus one text panel:

     row 1   the two 16:9 website loops, two across
     row 2   the two 9:16 reels at one column each, then the note panel
             filling the remaining two columns so the row has no hole in it

   Every <video> is muted + loop + playsinline and carries preload="none" and
   a poster. assets/js/video.js starts each one only as it nears the viewport.
   Do NOT add the autoplay attribute: four clips downloading on page load is
   the exact thing this arrangement exists to avoid. */
.videos{ padding-top:0; }

.vidgrid{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(14px,1.6vw,22px);
  align-items:start;
}

.vid{
  position:relative;
  border-radius:var(--r-md); overflow:hidden;
  background:var(--maroon-soft);
  transition:transform .55s var(--ease);
  will-change:transform;
}
.vid--loop{ grid-column:span 2; aspect-ratio:16/9; }
.vid--reel{ grid-column:span 1; aspect-ratio:9/16; }
.vid:hover{ transform:translateY(-6px); }

.vid video{
  width:100%; height:100%; object-fit:cover; display:block;
  background:var(--maroon-soft);
}
.vid::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(to top, rgba(27,10,11,.92) 0%, rgba(27,10,11,.34) 32%, rgba(27,10,11,0) 60%);
  opacity:.85; transition:opacity .5s var(--ease);
}
.vid:hover::after{ opacity:1; }

.vid__meta{
  position:absolute; left:0; right:0; bottom:0; z-index:2;
  padding:clamp(16px,2vw,26px);
  display:flex; flex-direction:column; gap:3px;
  pointer-events:none;
}
.vid__meta h3{
  font-family:var(--head);
  font-size:clamp(1.2rem,2.2vw,1.85rem); font-weight:400;
  letter-spacing:.02em; text-transform:uppercase;
}
.vid__meta span{
  font-size:.72rem; font-weight:800; letter-spacing:.16em;
  text-transform:uppercase; color:var(--cream-dim);
}

/* Sound toggle. Only the reels carry an audio track, so only they get one.
   It sits above .vid__meta, which is pointer-events:none. */
.vid__sound{
  position:absolute; top:13px; right:13px; z-index:3;
  width:40px; height:40px; border-radius:50%;
  display:grid; place-items:center;
  background:rgba(27,10,11,.55); color:var(--cream);
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  border:1px solid rgba(247,239,234,.24);
  transition:background .3s var(--ease), color .3s var(--ease),
             border-color .3s var(--ease), transform .3s var(--ease);
}
.vid__sound svg{
  width:18px; height:18px; fill:none; stroke:currentColor;
  stroke-width:2.1; stroke-linecap:round; stroke-linejoin:round;
}
.vid__sound .icon-on{ display:none; }
.vid__sound[aria-pressed="true"]{ background:var(--red); color:var(--ink); border-color:var(--red); }
.vid__sound[aria-pressed="true"] .icon-on{ display:block; }
.vid__sound[aria-pressed="true"] .icon-off{ display:none; }
.vid__sound:hover{ transform:scale(1.06); }

/* The note panel. It is stretched to the reels' height by the grid row, so it
   centres its own content rather than sitting at the top of a tall box. */
.vidnote{
  grid-column:span 2; align-self:stretch;
  border-radius:var(--r-md);
  border:1px solid rgba(247,239,234,.14);
  background:linear-gradient(160deg, rgba(239,68,35,.22), rgba(239,68,35,.03) 62%);
  padding:clamp(26px,3.2vw,44px);
  display:flex; flex-direction:column; justify-content:center;
  align-items:flex-start;
}
.vidnote__label{
  font-size:.72rem; font-weight:800; letter-spacing:.19em;
  text-transform:uppercase; color:var(--red); margin-bottom:18px;
}
.vidnote__title{
  font-family:var(--head); font-weight:400;
  font-size:clamp(2rem,4.4vw,3.4rem);
  line-height:1.0; letter-spacing:.005em; text-transform:uppercase;
}
.vidnote__title em{ color:var(--red); font-style:normal; }
.vidnote__body{
  margin-top:18px; max-width:38ch;
  color:var(--cream-dim); font-size:.99rem; line-height:1.65;
}
.vidnote .btn{ margin-top:28px; }

@media (max-width:900px){
  .vidgrid{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  /* Loops go full width, the two reels keep sitting side by side the way they
     are actually watched, and the note takes its own full width row. */
}

/* ---------- contact CTA ---------- */
.contact{ padding-bottom:clamp(60px,8vw,110px); }
.cta{
  background:var(--red); color:var(--ink);
  border-radius:var(--r-lg);
  padding:clamp(44px,6.5vw,92px) clamp(26px,5vw,76px);
  text-align:center;
  position:relative; overflow:hidden;
}
.cta::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(60% 70% at 50% 0%, rgba(255,255,255,.22), transparent 70%);
}
.cta > *{ position:relative; z-index:1; }
.label--dark{ color:var(--ink); justify-content:center; }
.label--dark .label__line{ background:var(--ink); }
.cta__title{
  font-family:var(--head);
  font-size:clamp(2.8rem,8.4vw,8rem); font-weight:400;
  line-height:1.0; letter-spacing:.005em; text-transform:uppercase;
}
.cta__title em{ font-style:normal; color:var(--cream); }
.cta__sub{
  margin:22px auto 0; max-width:44ch;
  font-size:clamp(1rem,1.3vw,1.1rem); line-height:1.6;
  color:rgba(28,28,28,.78);
}
.cta .btn{ margin-top:36px; }
.cta__alt{ margin-top:22px; font-size:.92rem; font-weight:700; color:rgba(28,28,28,.75); }
.cta__alt a{ text-decoration:underline; text-underline-offset:3px; font-weight:900; }

/* ---------- project story ----------
   Long form copy under the gallery. Measure is capped at 62ch because these
   are full paragraphs, not the short leads used up in .projhead. */
.projstory{ padding-block:clamp(40px,6vw,86px) 0; }
.projstory__inner{ max-width:62ch; }
.projstory__delivered{ margin-top:clamp(30px,4vw,48px); }
.projstory__h{
  font-family:var(--head); font-weight:400; font-size:1.5rem;
  letter-spacing:.02em; text-transform:uppercase; margin-bottom:14px;
}
.projstory__delivered ul{ list-style:none; display:flex; flex-direction:column; gap:9px; }
.projstory__delivered li{
  position:relative; padding-left:22px; color:var(--cream-dim); font-size:1rem;
}
.projstory__delivered li::before{
  content:""; position:absolute; left:0; top:.55em;
  width:7px; height:7px; border-radius:50%; background:var(--red);
}

/* ---------- FAQ ----------
   Plain headings and paragraphs rather than <details>. The answers carry
   FAQPage schema, and Google will not read text that is collapsed behind a
   summary as reliably as text that is simply on the page. */
.faq__list{ max-width:74ch; display:flex; flex-direction:column; }
.faq__row{
  padding-block:clamp(20px,2.4vw,28px);
  border-top:1px solid rgba(247,239,234,.12);
}
.faq__row:last-child{ border-bottom:1px solid rgba(247,239,234,.12); }
.faq__q{
  font-family:var(--head); font-weight:400;
  font-size:clamp(1.25rem,2.4vw,1.6rem);
  letter-spacing:.02em; text-transform:uppercase; line-height:1.1;
  margin-bottom:10px;
}
.faq__a{ color:var(--cream-dim); max-width:66ch; }

/* ---------- language switch ----------
   Sits in the nav next to the CTA. Bordered rather than underlined so it does
   not read as one more section link. */
.langswitch{
  border:1px solid rgba(247,239,234,.28);
  border-radius:100px; padding:6px 14px;
  font-size:.82rem; font-weight:800; letter-spacing:.03em;
  text-transform:uppercase; color:var(--cream-dim);
  transition:color .3s var(--ease), border-color .3s var(--ease);
}
.langswitch::after{ display:none; }
.langswitch:hover{ color:var(--cream); border-color:rgba(247,239,234,.6); }

/* ---------- footer ---------- */
.footer{ border-top:1px solid rgba(247,239,234,.12); padding-block:44px; }
.footer__inner{
  display:flex; align-items:center; justify-content:space-between;
  gap:22px; flex-wrap:wrap;
}
.footer__links{ display:flex; gap:26px; flex-wrap:wrap; font-size:.93rem; font-weight:700; }
.footer__links a{ color:var(--cream-dim); transition:color .3s var(--ease); }
.footer__links a:hover{ color:var(--red); }
.footer__note{ font-size:.83rem; color:var(--cream-dim); }

/* ==========================================================================
   Scroll reveal
   ========================================================================== */
.reveal{
  opacity:0; transform:translateY(30px);
  transition:opacity .95s var(--ease-out), transform .95s var(--ease-out);
  will-change:opacity, transform;
}
.reveal.in{ opacity:1; transform:none; }

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width:1000px){
  /* Single column from here down, so every heading has the whole page width
     to fill and needs a much steeper vw slope than the desktop numbers up in
     the Type scale. The maxima are what stop a 4 line hero from growing
     taller than a tablet screen. */
  /* 22.5vw, not 25vw: the longest headline line is now "Foodfotografie"
     on /nl/, which is wider than the English "restaurants." the old
     figure was tuned against. At 25vw it wrapped on a 390px phone. */
  .display{ font-size:clamp(3.2rem, 22.5vw, 11rem); }
  .h2,
  .nextproj__name{ font-size:clamp(2.8rem, 15vw, 5rem); }
  .cta__title{ font-size:clamp(2rem, 9.8vw, 4rem); }
  .svc__title{ font-size:clamp(2.1rem, 10.5vw, 3.6rem); }
  .vidnote__title{ font-size:clamp(2.1rem, 10vw, 3.4rem); }
  .stat b{ font-size:clamp(2.4rem, 9vw, 3.6rem); }

  .hero__grid{ grid-template-columns:1fr; gap:44px; }
  .hero{ padding-top:112px; min-height:auto; }
  .hero__media{ order:-1; }
  .hero__frame{ aspect-ratio:16/10; }
  .hero__badge{ width:86px; height:86px; font-size:.76rem; left:auto; right:-14px; bottom:-18px; }
  .scrollcue{ display:none; }
  .about__grid{ grid-template-columns:1fr; }
  .about__media{ order:-1; }
  .svc__row{ grid-template-columns:60px minmax(0,1fr) 44px; row-gap:10px; }
  .svc__desc{ grid-column:2 / -1; max-width:none; }
  .svc__arrow{ grid-row:1; grid-column:3; }
}

@media (max-width:820px){
  .nav__links{ display:none; }
  .burger{ display:block; }
  .card--lg,.card--sm{ grid-column:span 6; }
  .card--wide{ grid-column:span 12; }
  .workgrid{ grid-auto-rows:clamp(210px,30vw,300px); }
}

@media (max-width:560px){
  body{ font-size:16px; }
  .brand__mark{ height:20px; }
  .brand--foot .brand__mark{ height:24px; }
  .workgrid{ gap:14px; grid-auto-rows:auto; }
  .card--lg,.card--sm,.card--wide{ grid-column:span 12; }
  .card__media{ aspect-ratio:4/3.2; height:auto; }
  .footer__inner{ flex-direction:column; align-items:flex-start; gap:20px; }
  .stats{ gap:22px; }
  .stat{ flex:1 1 40%; }
}

/* ==========================================================================
   Project pages (/work/<slug>/)
   Shared by all five case studies. Markup is generated, so keep the class
   names stable: assets/js/gallery.js hooks .gallery and .lightbox by class.
   ========================================================================== */
.projhead{ padding:clamp(130px,15vw,190px) 0 clamp(38px,5vw,62px); }
.projhead__top{
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:28px; flex-wrap:wrap;
}
.backlink{
  display:inline-flex; align-items:center; gap:10px;
  font-size:.75rem; font-weight:800; letter-spacing:.18em; text-transform:uppercase;
  color:var(--cream-dim); margin-bottom:26px;
  transition:color .3s var(--ease);
}
.backlink svg{
  width:15px; height:15px; fill:none; stroke:currentColor;
  stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round;
  transition:transform .35s var(--ease);
}
.backlink:hover{ color:var(--red); }
.backlink:hover svg{ transform:translateX(-4px); }

/* 16ch was measured against the old mixed-case face. A `ch` in
   fabiola-capitals is much narrower, so 16ch now cuts the second line of a
   two line project headline in half; 24ch is the same measure by eye. */
.projhead .h2{ max-width:24ch; }
.projhead__lede{ margin-top:clamp(22px,2.4vw,30px); }

.projmeta{
  display:flex; flex-wrap:wrap; gap:clamp(24px,4vw,56px);
  margin-top:clamp(30px,3.4vw,44px);
  padding-top:clamp(24px,2.6vw,32px);
  border-top:1px solid rgba(247,239,234,.12);
}
.projmeta div{ display:flex; flex-direction:column; gap:5px; }
.projmeta dt{
  font-size:.71rem; font-weight:800; letter-spacing:.18em;
  text-transform:uppercase; color:var(--red);
}
.projmeta dd{ margin:0; font-size:1rem; font-weight:700; }

/* ---------- masonry gallery ----------
   CSS columns, not grid. The shoots are mixed orientation and the crop IS the
   photograph, so every tile keeps its native aspect ratio. Never put
   object-fit:cover or a fixed aspect-ratio on .gallery__item img. */
.gallery{
  columns:3;
  column-gap:clamp(14px,1.6vw,22px);
  padding-bottom:clamp(60px,8vw,110px);
}
.gallery__item{
  break-inside:avoid; -webkit-column-break-inside:avoid;
  margin:0 0 clamp(14px,1.6vw,22px);
  display:block; width:100%; padding:0; border:0;
  position:relative; overflow:hidden;
  border-radius:var(--r-md);
  background:var(--maroon-soft);
  cursor:zoom-in;
  transition:transform .5s var(--ease);
  /* no will-change here. It promotes every tile to its own compositing layer
     for the whole life of the page, and a promoted layer inside a CSS multicol
     container is exactly where WebKit mispaints, tiles landing in the wrong
     column or dropping out on scroll. A 23 photo set is 23 permanent layers
     for a hover that lasts half a second. */
}
.gallery__item img{
  width:100%; height:auto;
  transition:transform 1s var(--ease-out), opacity .6s var(--ease);
}
.gallery__item::after{
  content:""; position:absolute; inset:0;
  background:rgba(27,10,11,.28);
  opacity:0; transition:opacity .4s var(--ease);
}
.gallery__item:hover{ transform:translateY(-4px); }
.gallery__item:hover img{ transform:scale(1.04); }
.gallery__item:hover::after{ opacity:1; }

/* ---------- lightbox ---------- */
/* No backdrop-filter. At 96% opacity the blur is invisible anyway, and a
   blurred full screen layer that fades in is a reliable way to get a black
   flash and dropped frames out of Safari. overscroll-behavior stops a flick
   inside the box from chaining to the page underneath. */
.lightbox{
  position:fixed; inset:0; z-index:200;
  background:rgba(11,4,5,.96);
  overscroll-behavior:contain;
  opacity:0; visibility:hidden;
  transition:opacity .35s var(--ease), visibility .35s;
}
.lightbox.is-open{ opacity:1; visibility:visible; }

/* The stage is absolutely positioned rather than a grid row on purpose: it
   needs a *definite* height for the photo's max-height:100% to resolve
   against, otherwise a tall portrait frame overflows and pushes the controls
   off screen. The bar is overlaid at the bottom, and the stage reserves room
   for it in its own padding. */
.lightbox__stage{
  position:absolute; inset:0;
  /* explicit 1fr track, not the implicit auto one: a percentage max-height on
     a grid item only resolves against a *definite* track, and an auto track
     sized by the photo itself is not definite. */
  display:grid; grid-template:minmax(0,1fr) / minmax(0,1fr);
  place-items:center;
  padding:clamp(56px,7vw,80px) clamp(16px,6vw,96px) clamp(84px,9vw,104px);
}
.lightbox__img{
  max-width:100%; max-height:100%;
  width:auto; height:auto;
  object-fit:contain;
  border-radius:var(--r-sm);
  box-shadow:0 40px 90px -30px rgba(0,0,0,.8);
  transition:opacity .25s var(--ease);
}
/* the previous photo stays on screen while the next 2000px file arrives, so
   dim it: the counter has already moved on and the two should not disagree */
.lightbox.is-loading .lightbox__img{ opacity:.35; }
.lightbox__bar{
  position:absolute; left:0; right:0; bottom:0; z-index:2;
  display:flex; align-items:center; justify-content:center; gap:18px;
  padding:0 var(--gut) clamp(20px,3vw,32px);
  font-size:.76rem; font-weight:800; letter-spacing:.16em;
  text-transform:uppercase; color:var(--cream-dim);
}
.lb-btn{
  width:46px; height:46px; border-radius:50%;
  display:grid; place-items:center; flex:none;
  border:1px solid rgba(247,239,234,.22);
  transition:background .3s var(--ease), color .3s var(--ease),
             border-color .3s var(--ease), transform .3s var(--ease);
}
.lb-btn svg{
  width:19px; height:19px; fill:none; stroke:currentColor;
  stroke-width:2.3; stroke-linecap:round; stroke-linejoin:round;
}
.lb-btn:hover{ background:var(--red); color:var(--ink); border-color:var(--red); transform:scale(1.06); }
.lightbox__close{ position:absolute; top:clamp(14px,2.2vw,24px); right:clamp(14px,2.2vw,24px); z-index:2; }
.lightbox__count{ min-width:6ch; text-align:center; }

/* ---------- next project ---------- */
.nextproj{ border-top:1px solid rgba(247,239,234,.12); }
.nextproj__link{
  display:flex; align-items:center; justify-content:space-between;
  gap:24px; flex-wrap:wrap;
  padding-block:clamp(44px,6vw,80px);
}
.nextproj__label{
  font-size:.72rem; font-weight:800; letter-spacing:.19em;
  text-transform:uppercase; color:var(--red); display:block; margin-bottom:12px;
}
.nextproj__name{
  font-family:var(--head);
  font-weight:400; letter-spacing:.005em; line-height:1.0;
  font-size:clamp(3.2rem,6.6vw,6.25rem); text-transform:uppercase;
  transition:color .35s var(--ease);
}
.nextproj__link:hover .nextproj__name{ color:var(--red); }
.nextproj__thumb{
  width:clamp(96px,13vw,168px); aspect-ratio:1; flex:none;
  border-radius:var(--r-md); overflow:hidden;
}
.nextproj__thumb img{
  width:100%; height:100%; object-fit:cover;
  transition:transform 1s var(--ease-out);
}
.nextproj__link:hover .nextproj__thumb img{ transform:scale(1.07); }

@media (max-width:900px){
  .gallery{ columns:2; }
}
@media (max-width:560px){
  .gallery{ columns:1; }
  .projmeta{ gap:22px 34px; }
  .lightbox__stage{ padding:64px 12px 88px; }
}

/* ==========================================================================
   Reduced motion
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important; scroll-behavior:auto !important;
  }
  .reveal{ opacity:1; transform:none; }
  .line__in{ transform:none; }
  .hero__frame img,.about__frame img,.card__media img,
  .gallery__item img,.nextproj__thumb img{ transform:none; }
  .marquee__row{ animation:none; }
}

@media print{
  body::before,body::after,.nav,.marquee,.scrollcue{ display:none; }
  body{ background:#fff; color:#000; }
}

/* ---------- no casual saving on /work galleries ----------
   Stops the iOS long press "Save to Photos" menu, which no JS can catch.
   Right click and drag are handled in gallery.js. Deterrent only. */
.gallery img,
.lightbox__img{
  -webkit-touch-callout:none;
  -webkit-user-select:none; user-select:none;
}
