/* ============================================================
   BARBAROSSO DESIGN — Design System
   ============================================================ */

:root {
  --black:      #050505;
  --white:      #FFFFFF;
  --red:        #8C1F1F;
  --red-glow:   rgba(140,31,31,0.35);
  --concrete:   #B8B2A7;
  --graphite:   #3A3A3A;
  --champagne:  #C9B896;

  --font-display: "Fraunces", "Times New Roman", serif;
  --font-body: "Archivo", "Helvetica Neue", Arial, sans-serif;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);      /* power3.out */
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);   /* power2.inOut */

  --nav-h: 88px;
  --container-pad: clamp(24px, 5vw, 72px);
  --section-pad-y: clamp(56px, 7vw, 120px);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: auto; }
html, body {
  margin: 0; padding: 0;
  background: var(--black);
  color: var(--white);
  overflow-x: hidden;
}
body {
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul, ol, dl { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, p, dd { margin: 0; }
button, input, textarea {
  font-family: inherit; color: inherit; background: none; border: none;
}
button { cursor: pointer; }
:focus-visible { outline: 1px solid var(--champagne); outline-offset: 4px; }

/* ---------- Layout helpers ---------- */
.section-inner {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 var(--container-pad);
}
main > section {
  position: relative;
  padding-top: var(--section-pad-y);
  padding-bottom: var(--section-pad-y);
}

.eyebrow {
  position: relative; z-index: 2;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--champagne);
  display: inline-block;
  margin-bottom: 1.5em;
}

.section-headline {
  position: relative; z-index: 2;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.2rem, 5vw, 4.4rem);
  /* Same descender-clipping fix as .hero-headline — see its comment. */
  line-height: 1.25;
  letter-spacing: -0.01em;
  max-width: 16ch;
}

.section-sub {
  position: relative; z-index: 2;
  font-size: 15px;
  color: var(--concrete);
  margin-top: 1.25em;
  max-width: 46ch;
}

/* ---------- Grain overlay (SVG feTurbulence, ~4% opacity, multiply) ---------- */
.grain { position: relative; overflow: hidden; }
.grain::after {
  content: "";
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: 0.04;
  mix-blend-mode: multiply;
  pointer-events: none;
}

/* ---------- Placeholder media gradients (swap for real <img> later) ---------- */
.ph-hero, .ph-before, .ph-after, .ph-about, .ph-contact,
.ph-p1, .ph-p2, .ph-p3, .ph-p4, .ph-p5, .ph-p6,
[class*="ph-proj-"] {
  background-color: var(--black);
  background-repeat: no-repeat;
}
.ph-hero {
  background-image:
    radial-gradient(120% 100% at 20% 0%, rgba(140,31,31,0.16), transparent 55%),
    linear-gradient(155deg, #14100d 0%, #1b1815 35%, #050505 75%),
    linear-gradient(0deg, #000 0%, #0d0b0a 100%);
}
.ph-before {
  background-image:
    linear-gradient(180deg, #2b2b2b 0%, #1a1a1a 60%, #050505 100%),
    radial-gradient(80% 60% at 50% 20%, rgba(184,178,167,0.12), transparent 60%);
  filter: saturate(0.7) brightness(0.85);
}
.ph-after {
  background-image:
    radial-gradient(90% 70% at 30% 10%, rgba(201,184,150,0.18), transparent 60%),
    linear-gradient(200deg, #241a14 0%, #17100c 45%, #050505 100%);
}
.ph-about {
  background-image:
    linear-gradient(160deg, #201c18 0%, #0c0a09 60%),
    radial-gradient(70% 60% at 80% 20%, rgba(140,31,31,0.10), transparent 60%);
}
.ph-contact {
  background-image:
    radial-gradient(100% 80% at 50% 30%, rgba(140,31,31,0.14), transparent 60%),
    linear-gradient(180deg, #171310 0%, #050505 80%);
}
.ph-p1 { background-image: linear-gradient(160deg,#2c2c2c,#0a0a0a); }
.ph-p2 { background-image: linear-gradient(160deg,#241f1a,#0a0a0a); }
.ph-p3 { background-image: linear-gradient(160deg,#33302c,#0a0a0a); }
.ph-p4 { background-image: linear-gradient(160deg,#241414,#0a0a0a); }
.ph-p5 { background-image: linear-gradient(160deg,#241c14,#0a0a0a); }
.ph-p6 { background-image: linear-gradient(160deg,#2a2420,#0a0a0a); }

/* deterministic project-card gradient variants, cycled 0-7 by js/gallery.js */
.ph-proj-0 { background-image: radial-gradient(130% 110% at 25% 15%, rgba(201,184,150,0.18), transparent 65%), linear-gradient(165deg,#4a3d2e 0%,#2c241b 55%,#1c1712 100%); }
.ph-proj-1 { background-image: radial-gradient(130% 110% at 75% 15%, rgba(184,178,167,0.18), transparent 65%), linear-gradient(165deg,#3d4248 0%,#252a2e 55%,#181b1e 100%); }
.ph-proj-2 { background-image: radial-gradient(130% 110% at 25% 15%, rgba(140,31,31,0.2), transparent 65%), linear-gradient(165deg,#4a2626 0%,#301c1c 55%,#1e1414 100%); }
.ph-proj-3 { background-image: radial-gradient(130% 110% at 75% 15%, rgba(201,184,150,0.16), transparent 65%), linear-gradient(165deg,#443a29 0%,#2a2419 55%,#1a1610 100%); }
.ph-proj-4 { background-image: radial-gradient(130% 110% at 25% 15%, rgba(184,178,167,0.16), transparent 65%), linear-gradient(165deg,#383838 0%,#242424 55%,#181818 100%); }
.ph-proj-5 { background-image: radial-gradient(130% 110% at 75% 15%, rgba(140,31,31,0.18), transparent 65%), linear-gradient(165deg,#43384a 0%,#2a232e 55%,#1a161c 100%); }
.ph-proj-6 { background-image: radial-gradient(130% 110% at 25% 15%, rgba(184,178,167,0.18), transparent 65%), linear-gradient(165deg,#2c3e3e 0%,#1c2929 55%,#131c1c 100%); }
.ph-proj-7 { background-image: radial-gradient(130% 110% at 75% 15%, rgba(201,184,150,0.18), transparent 65%), linear-gradient(165deg,#4a3826 0%,#2e2418 55%,#1c150e 100%); }

/* ---------- Text reveal / line-mask machinery ---------- */
.reveal-line { overflow: hidden; }
[data-split-lines], [data-split-chars] { overflow: visible; }
.split-line-mask { overflow: hidden; display: block; }
.split-line { display: inline-block; will-change: transform; }
.split-char { display: inline-block; will-change: transform, opacity; }

/* ---------- Buttons ---------- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 16px 34px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  border-radius: 2px;
  overflow: hidden;
  isolation: isolate;
}
.btn span { position: relative; z-index: 2; transition: color 0.4s var(--ease-inout); }
.btn-solid {
  background: var(--red);
  color: var(--white);
}
.btn-solid::before {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: var(--white);
  transform: translateX(-101%);
  transition: transform 0.4s var(--ease-inout);
}
.btn-solid:hover::before { transform: translateX(0); }
.btn-solid:hover span { color: var(--black); }

.btn-ghost {
  border: 1px solid rgba(255,255,255,0.4);
  color: var(--white);
}
.btn-ghost::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; z-index: 1;
  background: var(--red);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.4s var(--ease-inout);
}
.btn-ghost:hover::before { transform: scaleX(1); }

/* ============================================================
   CUSTOM CURSOR (desktop only)
   ============================================================ */
.cursor { position: fixed; top: 0; left: 0; z-index: 10000; pointer-events: none; mix-blend-mode: difference; }
.cursor-dot, .cursor-ring {
  position: absolute; top: 0; left: 0;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}
.cursor-dot { width: 6px; height: 6px; background: var(--white); }
.cursor-ring {
  width: 40px; height: 40px;
  border: 1px solid var(--white);
  transition: width 0.3s var(--ease-out), height 0.3s var(--ease-out), border-color 0.3s;
  display: flex; align-items: center; justify-content: center;
}
.cursor-label {
  font-size: 10px; font-weight: 600; letter-spacing: 0.1em;
  opacity: 0; transition: opacity 0.2s;
  white-space: nowrap;
}
.cursor.is-active .cursor-ring { width: 76px; height: 76px; }
.cursor.is-active .cursor-label { opacity: 1; }
@media (hover: none), (pointer: coarse) {
  .cursor { display: none; }
}

/* ============================================================
   INTRO SEQUENCE
   ============================================================ */
.intro-overlay {
  position: fixed; inset: 0; z-index: 9999;
  background: var(--black);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.intro-scene { position: relative; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
.intro-bg-image {
  position: absolute; inset: 0;
  background: radial-gradient(70% 60% at 50% 45%, rgba(80,60,45,0.5), transparent 70%),
              linear-gradient(160deg, #1b1815, #050505 70%);
  opacity: 0; filter: blur(18px);
}
.intro-line {
  position: absolute; top: 56%; left: 50%;
  width: min(320px, 60vw); height: 1px;
  background: var(--red);
  box-shadow: 0 0 24px 2px var(--red-glow);
  transform: translate(-50%, -50%) scaleX(0);
}
.intro-logo {
  position: relative; z-index: 2;
  text-align: center;
  font-family: var(--font-display);
}
/* The mark's two pieces (flourish + dot) animate in independently via GSAP —
   see js/intro.js — rather than the whole logo fading in as one flat image. */
.intro-logo-mark {
  position: relative;
  display: block;
  height: clamp(56px, 7.5vw, 88px);
  aspect-ratio: 308 / 643;
  margin: 0 auto 0.6em;
}
.intro-mark-flourish, .intro-mark-dot {
  position: absolute;
  width: 100%;
  height: auto;
  /* Matches the hidden state js/intro.js sets via GSAP before the timeline
     starts — without this default, the assembled mark flashes fully visible
     for a frame while the intro's setup script is still loading/running. */
  opacity: 0;
}
.intro-mark-flourish { top: 0; left: 0; }
.intro-mark-dot { top: 83.4%; left: 23.7%; width: 34.7%; }
.intro-mark-glow {
  position: absolute; top: 83.4%; left: 23.7%; width: 34.7%; aspect-ratio: 1 / 1;
  border-radius: 50%;
  background: radial-gradient(circle, var(--red-glow) 0%, transparent 70%);
  opacity: 0;
  pointer-events: none;
  transform: translate(-33%, -33%) scale(2.2);
}
.intro-logo-word {
  display: block;
  font-size: clamp(1.6rem, 4.2vw, 3rem);
  letter-spacing: 0.32em;
  font-weight: 400;
  /* Hidden until js/intro.js has split it into per-character spans and hidden
     those individually — otherwise the full plain-text word flashes for a
     frame before the reveal animation takes over. */
  opacity: 0;
}
.intro-logo-sub {
  font-size: clamp(0.7rem, 1.2vw, 0.95rem);
  letter-spacing: 0.5em;
  color: var(--champagne);
  margin-top: 0.6em;
  font-family: var(--font-body);
  font-weight: 600;
}
.intro-skip {
  position: absolute; bottom: clamp(20px, 4vw, 40px); right: clamp(20px, 4vw, 40px);
  z-index: 3;
  font-size: 11px; letter-spacing: 0.2em; color: var(--concrete);
  border-bottom: 1px solid rgba(255,255,255,0.3);
  padding-bottom: 2px;
  opacity: 0; animation: intro-skip-in 0.6s 1.2s forwards;
}
@keyframes intro-skip-in { to { opacity: 0.7; } }
.intro-overlay.is-done { pointer-events: none; }

/* ============================================================
   NAVIGATION
   ============================================================ */
.site-nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 500;
  height: var(--nav-h);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  background: rgba(5,5,5,0);
  transition: background 0.5s var(--ease-inout);
}
.site-nav.is-scrolled { background: rgba(5,5,5,0.85); }
.nav-inner {
  max-width: 1600px; margin: 0 auto; height: 100%;
  padding: 0 var(--container-pad);
  display: flex; align-items: center; justify-content: space-between; gap: 32px;
}
.nav-logo {
  font-family: var(--font-display);
  font-size: 18px; letter-spacing: 0.24em;
  display: inline-flex; align-items: center; gap: 10px;
}
/* Split-layer logo mark: the flourish and the dot are separate cropped images
   (already separated by a transparent gap in the source art), positioned to
   reproduce the original combined mark, then "parted" apart on hover. */
.logo-mark {
  position: relative;
  display: inline-block;
  aspect-ratio: 308 / 643;
  flex-shrink: 0;
}
.logo-mark-flourish,
.logo-mark-dot {
  position: absolute;
  width: 100%;
  height: auto;
  transition: transform 0.55s var(--ease-out);
  will-change: transform;
}
.logo-mark-flourish { top: 0; left: 0; }
.logo-mark-dot { top: 83.4%; left: 23.7%; width: 34.7%; }

.logo-link:hover .logo-mark-flourish { transform: translate(-30%, -22%) rotate(-6deg); }
.logo-link:hover .logo-mark-dot { transform: translate(70%, -60%); }

@media (prefers-reduced-motion: reduce) {
  .logo-mark-flourish, .logo-mark-dot { transition: none; }
  .logo-link:hover .logo-mark-flourish,
  .logo-link:hover .logo-mark-dot { transform: none; }
}

.nav-logo-mark { height: 38px; }
.nav-links { display: flex; gap: 36px; }
.nav-link {
  position: relative;
  font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase;
  padding-bottom: 6px;
}
.nav-link::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--red);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.4s var(--ease-inout);
}
.nav-link:hover::after { transform: scaleX(1); }
.nav-cta { padding: 12px 22px; font-size: 11px; }

/* ---------- Google Website Translator (EN/TR) ---------- */
/* Google injects a top iframe banner (+ a hover tooltip) as direct children
   of <body> and shifts <body> down while translating; both would break our
   fixed-position nav/hero, so only those body-level injections are hidden —
   #google_translate_element itself lives in the header, untouched by these
   selectors, since its native <select> is kept (just invisible) to drive
   our own toggle below. */
body > iframe.skiptranslate,
body > div.skiptranslate,
body > div[class*="VIpgJd"],
body > #goog-gt-tt {
  display: none !important;
}
body { top: 0 !important; }

/* The native widget stays in the DOM (functional, wired to our toggle) but
   is visually hidden — visually-hidden, not display:none, so Google's script
   still finds a rendered <select> to operate on. */
#google_translate_element {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0; padding: 0; margin: -1px;
}

/* Custom EN/TR toggle — sits left of the CTA button and the burger. */
.lang-toggle {
  position: relative;
  display: flex; align-items: center;
  border: 1px solid rgba(255,255,255,0.3);
  border-radius: 20px;
  padding: 3px;
  gap: 2px;
  margin-left: auto;
}
.lang-toggle-fill {
  position: absolute; top: 3px; left: 3px;
  height: calc(100% - 6px);
  border-radius: 16px;
  background: var(--red);
  transition: transform 0.35s var(--ease-inout), width 0.35s var(--ease-inout);
}
.lang-toggle-btn {
  position: relative; z-index: 1;
  min-width: 32px;
  padding: 6px 10px;
  font-family: var(--font-body);
  font-size: 11px; letter-spacing: 0.08em;
  color: rgba(255,255,255,0.55);
  text-align: center;
  border-radius: 16px;
  transition: color 0.35s var(--ease-inout);
}
.lang-toggle-btn.is-active { color: var(--white); }
.nav-burger {
  display: none; flex-direction: column; gap: 5px; width: 28px;
}
.nav-burger span { display: block; height: 1px; width: 100%; background: var(--white); }

/* ============================================================
   HERO
   ============================================================ */
.hero {
  position: relative;
  overflow: hidden;
  padding-top: 0;
}
/* The first screen a visitor sees is the video/photo alone — .hero-stage is
   pinned to exactly 100vh so the Before/After strip below it never bleeds
   into view until the visitor actually scrolls. */
.hero-stage {
  position: relative;
  height: 100vh; min-height: 100vh;
  display: flex; flex-direction: column; justify-content: center;
  padding-top: var(--nav-h);
  overflow: hidden;
}
.hero-bg-parallax { position: absolute; top: 0; left: 0; right: 0; height: 100vh; z-index: 2; overflow: hidden; }
.hero-bg {
  position: absolute; inset: -3%;
  transform: scale(1);
  animation: hero-kenburns 20s linear infinite alternate;
}
@keyframes hero-kenburns { from { transform: scale(1); } to { transform: scale(1.06); } }
.hero-video {
  position: absolute; inset: -4%;
  width: 108%; height: 108%;
  object-fit: cover;
  object-position: center 8%;
  animation: hero-kenburns 24s linear infinite alternate;
}
.hero-scrim {
  position: absolute; inset: 0; z-index: 3;
  background: linear-gradient(180deg, rgba(5,5,5,0.35) 0%, rgba(5,5,5,0.15) 40%, rgba(5,5,5,0.75) 100%);
}
.hero-content {
  position: relative; z-index: 4;
  max-width: 1600px; margin: 0 auto; width: 100%;
  padding: 0 var(--container-pad);
}
.hero-headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.6rem, 6.4vw, 6rem);
  /* 1.02 clipped descenders (g, y, p, j, q) against the split-line-mask's
     overflow:hidden — Fraunces needs roughly 1.25x to fit its full glyph
     box (measured via canvas metrics), so this is the minimum safe value,
     not a stylistic choice. */
  line-height: 1.25;
  letter-spacing: -0.015em;
  max-width: 17ch;
  margin-bottom: 0.5em;
}
.hero-subtitle {
  font-size: 15px; color: var(--concrete);
  margin-bottom: 2.2em;
  max-width: 40ch;
}
.hero-ctas { display: flex; gap: 18px; flex-wrap: wrap; }

.scroll-hint {
  position: absolute; bottom: 28px; left: 50%; transform: translateX(-50%);
  z-index: 2; width: 1px; height: 60px;
  background: rgba(255,255,255,0.25);
  overflow: hidden;
}
.scroll-hint span {
  display: block; width: 100%; height: 30%;
  background: var(--champagne);
  animation: scroll-hint-move 2s ease-in-out infinite;
}
@keyframes scroll-hint-move {
  0% { transform: translateY(-100%); }
  100% { transform: translateY(330%); }
}

/* ---------- Before / After strip ---------- */
.before-after-wrap {
  position: relative; z-index: 2;
  width: 100%; margin-top: clamp(48px, 8vw, 96px);
}
.before-after {
  position: relative;
  width: 100%; height: clamp(320px, 38vw, 560px);
  overflow: hidden;
  /* pan-y (not none): the drag itself is always horizontal, so a vertical
     touch that starts here is left free for the browser's native scroll —
     only touch-action's own gesture recognizer can make that call cleanly,
     since by the time a pointermove event reaches JS it's too late to tell
     "scrolling past" apart from "dragging the handle". */
  touch-action: pan-y;
  cursor: ew-resize;
}
.ba-panel { position: absolute; inset: 0; }
.ba-after { clip-path: inset(0 50% 0 0); }
.ba-label {
  position: absolute; top: 24px; font-size: 11px; letter-spacing: 0.2em;
  color: var(--white); opacity: 0.85;
  transition: opacity 0.3s;
}
.ba-label-before { left: 24px; }
.ba-label-after { right: 24px; }
.ba-handle {
  position: absolute; top: 0; bottom: 0; left: 50%;
  width: 2px; background: var(--champagne);
  transform: translateX(-50%);
  display: flex; align-items: center; justify-content: center;
}
.ba-handle-dot {
  width: 64px; height: 64px; border-radius: 50%;
  flex-shrink: 0;
  background: rgba(5,5,5,0.55);
  border: 1px solid var(--champagne);
  display: flex; align-items: center; justify-content: center;
}
.ba-handle-dot::after {
  content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--red);
}
.ba-overlay-headline {
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 2.6vw, 1.9rem);
  text-align: center;
  margin-top: 28px;
  color: var(--white);
}
.ba-overlay-headline em { font-style: italic; color: var(--champagne); }

/* ============================================================
   GALLERY / PROJECT UNIVERSE
   ============================================================ */
.gallery { background: var(--black); }
.category-nav-outer {
  position: relative; z-index: 2;
  margin: clamp(40px, 6vw, 72px) 0 clamp(48px, 7vw, 88px);
  padding: 0 var(--container-pad);
}
.category-nav-wrap {
  position: relative;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  cursor: grab;
}
.category-nav-wrap::-webkit-scrollbar { display: none; }
.category-nav-wrap.is-dragging { cursor: grabbing; user-select: none; }
.category-nav-wrap.is-dragging .category-item { pointer-events: none; }
/* override swiper-bundle's default .swiper{overflow:hidden} so native scroll
   works as a fallback whenever the Swiper JS instance isn't active (desktop) */
.category-nav-wrap .category-nav.swiper { overflow: visible; }

.category-nav-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: rgba(255,255,255,0.6);
  background: rgba(5,5,5,0.75);
  border: 1px solid rgba(255,255,255,0.16);
  opacity: 0; pointer-events: none;
  transition: opacity 0.3s var(--ease-inout), border-color 0.3s, color 0.3s, background 0.3s;
}
[data-category-arrow="prev"] { left: 8px; }
[data-category-arrow="next"] { right: 8px; }
.category-nav-arrow svg { width: 13px; height: 13px; display: block; }
.category-nav-arrow.is-visible { opacity: 1; pointer-events: auto; }
.category-nav-arrow:hover { border-color: var(--red); color: var(--red); background: rgba(140,31,31,0.08); }

/* "Show All" pagination control for the ALL tab */
.gallery-show-all-wrap { position: relative; z-index: 2; text-align: center; margin-top: clamp(32px, 5vw, 56px); }
.gallery-show-all {
  display: none;
  align-items: center; gap: 10px;
  padding: 15px 32px;
  border: 1px solid rgba(255,255,255,0.28);
  border-radius: 2px;
  font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--white);
  transition: border-color 0.3s, color 0.3s, background 0.3s;
}
.gallery-show-all.is-visible { display: inline-flex; }
.gallery-show-all:hover { border-color: var(--red); color: var(--red); background: rgba(140,31,31,0.06); }
.gallery-show-all-count { color: var(--concrete); font-size: 11px; letter-spacing: 0.04em; }
.gallery-show-all:hover .gallery-show-all-count { color: inherit; }
@media (max-width: 1024px) {
  .gallery-show-all-wrap { display: none; }
}
.category-nav .swiper-wrapper { display: flex; }
[data-category-list] { display: flex; gap: clamp(28px, 3vw, 56px); }
@media (max-width: 1024px) { [data-category-list] { gap: 0; } }
.category-item {
  flex-shrink: 0;
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 2.4vw, 1.7rem);
  letter-spacing: 0.02em;
  color: rgba(255,255,255,0.35);
  transition: color 0.4s var(--ease-inout);
  white-space: nowrap;
  padding-bottom: 14px;
}
.category-item.is-active { color: var(--white); }
.category-underline {
  position: absolute; bottom: 0; height: 1px; background: var(--red);
  box-shadow: 0 0 10px var(--red-glow);
  transform-origin: left;
}

.gallery-grid {
  padding: 0 var(--container-pad);
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-auto-flow: dense;
  gap: clamp(10px, 1.4vw, 20px);
}
.project-card {
  position: relative; z-index: 2;
  grid-column: span 2;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border-radius: 2px;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.14);
}
/* Asymmetric editorial masonry, built to survive an admin adding/removing
   projects in any order without ever producing a mid-grid gap:
   "wide" always spans the full row by itself (a span equal to the column
   count can never conflict with neighbors), and "tall"/"square" both span 2
   columns so any quantity of them simply wraps every 3 into a clean row —
   the only possible imperfection is a shorter *final* row, never a gap. */
.project-card.shape-wide { grid-column: span 6; aspect-ratio: 2.4 / 1; }
.project-card.shape-square { grid-column: span 2; aspect-ratio: 1 / 1; }
.project-card.shape-tall { grid-column: span 2; aspect-ratio: 3 / 4; }
img.project-card-media {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 0.6s var(--ease-out);
}
.project-card:hover .project-card-media { transform: scale(1.06); }
.project-card-overlay {
  position: absolute; inset: 0;
  background: linear-gradient(0deg, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0) 55%);
  opacity: 0; transition: opacity 0.5s var(--ease-inout);
}
.project-card:hover .project-card-overlay { opacity: 1; }
.project-card-info {
  position: absolute; left: 20px; right: 20px; bottom: 18px;
  transform: translateY(14px); opacity: 0;
  transition: transform 0.5s var(--ease-out), opacity 0.5s var(--ease-out);
}
.project-card:hover .project-card-info { transform: translateY(0); opacity: 1; }
.project-card-rule {
  width: 28px; height: 1px; background: var(--red); margin-bottom: 10px;
  transform: scaleX(0); transform-origin: left; transition: transform 0.5s 0.1s var(--ease-out);
}
.project-card:hover .project-card-rule { transform: scaleX(1); }
.project-card-name { font-family: var(--font-display); font-size: 1.05rem; }
.project-card-meta { font-size: 11px; letter-spacing: 0.08em; color: var(--concrete); margin-top: 4px; }

/* Mobile feed gallery — hidden on desktop. A plain vertically-scrolling
   list of large, uniform cards (native page scroll, no separate swipe
   library fighting it) with a horizontal swipe-to-change-category gesture
   layered on top (see js/gallery.js's initStoryGestures). */
.gallery-mobile-story {
  display: none;
  position: relative;
  z-index: 2; /* see js/scene3d.js's z-index note above — content sits above the 3D canvas */
  touch-action: pan-y; /* native vertical scroll stays native; horizontal drag is left free for our own gesture code */
}
.gallery-story-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 0 var(--container-pad);
}
.gallery-story-show-more-wrap { position: relative; z-index: 2; text-align: center; margin-top: clamp(20px, 5vw, 32px); padding: 0 var(--container-pad); }
.gallery-mobile-story .project-card {
  width: 100%;
  height: 76vh;
  aspect-ratio: unset; /* every card the same big size on mobile, regardless of its desktop-grid shape */
  border-radius: 10px;
  flex-shrink: 0;
}
.gallery-mobile-story .project-card-media,
.gallery-mobile-story .project-card-overlay,
.gallery-mobile-story .project-card-info { position: absolute; inset: 0; }
.gallery-mobile-story .project-card-overlay {
  opacity: 1; top: auto; height: 68%;
  /* Darker/taller than the desktop hover-only gradient — this one has to
     carry legible text at all times, not just add a hover accent. */
  background: linear-gradient(0deg, rgba(0,0,0,0.94) 0%, rgba(0,0,0,0.6) 45%, rgba(0,0,0,0) 100%);
}
.gallery-mobile-story .project-card-info {
  top: auto; bottom: 24px; left: 22px; right: 22px;
  opacity: 1; transform: none; inset: auto;
}
.gallery-mobile-story .project-card-rule { transform: scaleX(1); }
.gallery-mobile-story .project-card-name {
  font-size: 1.4rem;
  text-shadow: 0 2px 16px rgba(0,0,0,0.7);
}
.gallery-mobile-story .project-card-meta {
  font-size: 12.5px;
  color: rgba(255,255,255,0.9);
  text-shadow: 0 1px 8px rgba(0,0,0,0.6);
}
/* The category name gets its own small solid tag instead of sitting inline
   in the meta line — the one detail most likely to matter to a browsing
   visitor, pulled out so it doesn't just blend into the photo like the rest
   of the caption. */
.project-card-tag {
  display: inline-block;
  background: var(--red);
  color: var(--white);
  font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase;
  padding: 5px 11px; border-radius: 20px;
  margin-bottom: 10px;
}

/* ============================================================
   PROJECT MODAL (full-screen project experience)
   ============================================================ */
.project-modal {
  position: fixed; inset: 0; z-index: 2000;
  background: var(--black);
  visibility: hidden; opacity: 0;
  pointer-events: none;
}
.project-modal.is-open { visibility: visible; opacity: 1; pointer-events: auto; }
/* z-index:2 (not auto) so the modal's real content stays above the 3D scene
   canvas (z-index:1) when js/scene3d.js reparents it in as the modal's first
   child — same convention as the home page's protected text/photo elements. */
.project-modal-scroll { position: absolute; inset: 0; overflow-y: auto; z-index: 2; }
.project-modal-close {
  position: fixed; top: 28px; right: clamp(20px, 4vw, 40px); z-index: 10;
  color: var(--white);
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255,255,255,0.3); border-radius: 50%;
  background: transparent;
  transition: color 0.25s var(--ease-inout), border-color 0.25s var(--ease-inout), background 0.25s var(--ease-inout);
}
.project-modal-close svg { width: 16px; height: 16px; display: block; }
/* Set by js/gallery.js when the cover photo behind the button (its exact
   top-right corner, not the whole image) is light — a white icon on a
   bright/white cover would otherwise disappear entirely. */
.project-modal-close.is-light-cover {
  color: var(--black);
  border-color: rgba(0,0,0,0.25);
  background: rgba(255,255,255,0.55);
}
.project-modal-hero { position: relative; width: 100%; height: 64vh; min-height: 380px; overflow: hidden; }
.media-fill { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- Responsive <img> blur-up ----------
   The LQIP (inline background-image) and the real srcset photo live on the
   *same* element, so opacity can never hide one without hiding the other —
   an element hidden via opacity:0 while waiting to load showed nothing at
   all (not even its own background), which is what turned unloaded cards
   solid black. Blur instead: the element is always fully opaque (LQIP or
   photo is always visible), it just sharpens into focus once loaded. */
.responsive-img {
  filter: blur(16px);
  -webkit-user-drag: none; user-drag: none; user-select: none;
}
.responsive-img.is-loaded { filter: none; }
.lightbox-photo-img { width: 100%; height: 100%; object-fit: contain; display: block; }
.project-modal-body {
  max-width: 1100px; margin: 0 auto; padding: clamp(40px, 6vw, 80px) var(--container-pad) 120px;
}
.project-modal-title {
  font-family: var(--font-display); font-size: clamp(2rem, 4.4vw, 3.4rem); margin: 0.2em 0 0.7em;
}
.project-modal-ba { margin: 40px 0 20px; }
.project-modal-ba .before-after { height: clamp(260px, 40vw, 460px); }

/* Full-screen photo gallery swiper within a project's detail view */
.project-modal-gallery {
  position: relative;
  width: 100%;
  margin: clamp(48px, 6vw, 88px) 0;
}
.project-modal-gallery .swiper {
  width: 100%;
  height: clamp(360px, 62vw, 82vh);
}
.project-modal-gallery .swiper-slide {
  position: relative;
  overflow: hidden;
}
.modal-gallery-slide-media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background-color: #0a0a0a; display: block; }
.modal-gallery-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  z-index: 5;
  width: 48px; height: 48px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--white); font-size: 18px;
  background: rgba(5,5,5,0.35);
  border: 1px solid rgba(255,255,255,0.25);
  transition: background 0.3s, border-color 0.3s;
}
.modal-gallery-nav:hover { background: rgba(140,31,31,0.55); border-color: var(--red); }
.modal-gallery-prev { left: clamp(12px, 2.5vw, 32px); }
.modal-gallery-next { right: clamp(12px, 2.5vw, 32px); }

.video-slide { position: relative; }
.video-toggle {
  position: absolute; left: 16px; bottom: 16px; z-index: 6;
  width: 46px; height: 46px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--white);
  background: rgba(5,5,5,0.55);
  border: 1px solid rgba(255,255,255,0.3);
  transition: background 0.3s, border-color 0.3s, transform 0.2s;
}
.video-toggle:hover { background: rgba(140,31,31,0.6); border-color: var(--red); transform: scale(1.06); }
.video-toggle svg { width: 16px; height: 16px; }
.modal-gallery-counter {
  position: absolute; right: clamp(12px, 2.5vw, 32px); bottom: 18px; z-index: 5;
  font-size: 11px; letter-spacing: 0.15em; color: var(--white);
  background: rgba(5,5,5,0.5);
  padding: 6px 12px; border-radius: 2px;
}
.modal-gallery-expand {
  position: absolute; left: clamp(12px, 2.5vw, 32px); bottom: 18px; z-index: 5;
  width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--white);
  background: rgba(5,5,5,0.5);
  border: 1px solid rgba(255,255,255,0.25);
  transition: background 0.3s, border-color 0.3s;
}
.modal-gallery-expand svg { width: 16px; height: 16px; }
.modal-gallery-expand:hover { background: rgba(140,31,31,0.55); border-color: var(--red); }

/* ============================================================
   PHOTO LIGHTBOX
   ============================================================ */
.photo-lightbox {
  position: fixed; inset: 0; z-index: 3000;
  background: rgba(5,5,5,0.97);
  visibility: hidden; opacity: 0;
  pointer-events: none;
  transition: opacity 0.35s var(--ease-inout);
  display: flex; align-items: center; justify-content: center;
}
.photo-lightbox.is-open { visibility: visible; opacity: 1; pointer-events: auto; }
.photo-lightbox-media {
  position: relative;
  width: min(90vw, 1400px);
  height: min(84vh, 900px);
  border-radius: 2px;
  overflow: hidden;
}
/* Swipe track: 3 panels (prev | current | next), dragged/animated horizontally */
.lightbox-track {
  display: flex;
  width: 300%;
  height: 100%;
  transform: translateX(-33.3333%);
  will-change: transform;
  cursor: grab;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}
.lightbox-track.is-animating {
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.lightbox-track.is-dragging { cursor: grabbing; }
.lightbox-panel {
  flex: 0 0 33.3333%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.photo-lightbox-close {
  position: absolute; top: 28px; right: clamp(20px, 4vw, 40px); z-index: 10;
  color: var(--white);
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255,255,255,0.3); border-radius: 50%;
}
.photo-lightbox-close svg { width: 16px; height: 16px; display: block; }
.photo-lightbox-prev, .photo-lightbox-next { position: absolute; top: 50%; transform: translateY(-50%); }
.photo-lightbox-prev { left: clamp(12px, 3vw, 40px); }
.photo-lightbox-next { right: clamp(12px, 3vw, 40px); }
.photo-lightbox-counter { position: absolute; left: 50%; bottom: 24px; transform: translateX(-50%); }

@media (max-width: 1024px) {
  .photo-lightbox-media { width: 94vw; height: 70vh; }
  .modal-gallery-expand { bottom: auto; top: 18px; left: clamp(12px, 3vw, 24px); }
}

.project-modal-info { display: grid; gap: 40px; grid-template-columns: repeat(2, 1fr); }
.modal-info-block h3 {
  font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--champagne);
  margin-bottom: 0.9em;
}
.modal-info-block p { color: var(--concrete); font-size: 15px; line-height: 1.7; }

/* ============================================================
   ABOUT
   ============================================================ */
.about {
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 6vw, 96px);
  align-items: center;
}
.about-media {
  position: relative; z-index: 2; width: 100%; min-height: 460px; border-radius: 2px;
  object-fit: cover;
  /* Vignette: darkens toward the edges so the photo blends into the section's
     dark background instead of cutting off with a hard rectangular edge.
     Deepens slightly on hover as a subtle interactive cue. */
  box-shadow: inset 0 0 clamp(50px, 7vw, 110px) clamp(12px, 2vw, 30px) rgba(0,0,0,0.6);
  transition: box-shadow 0.5s var(--ease-inout);
}
.about-media:hover {
  box-shadow: inset 0 0 clamp(65px, 8.5vw, 135px) clamp(16px, 2.5vw, 36px) rgba(0,0,0,0.75);
}
.about-headline {
  position: relative; z-index: 2;
  width: fit-content; max-width: 100%; /* hug the actual text, not the full grid column, so it doesn't block particles in the empty space beside it */
  font-family: var(--font-display); font-size: clamp(2rem, 4.2vw, 3.4rem); margin-bottom: 0.5em;
}
.about-body { position: relative; z-index: 2; color: var(--concrete); font-size: 16px; max-width: 44ch; margin-bottom: 2em; }
.about-list { position: relative; z-index: 2; display: flex; flex-direction: column; }
.about-row {
  display: grid; grid-template-columns: 1fr 1.4fr; gap: 24px;
  padding: 20px 0; border-top: 1px solid rgba(255,255,255,0.12);
}
.about-row:last-child { border-bottom: 1px solid rgba(255,255,255,0.12); }
.about-row dt { font-family: var(--font-display); font-size: 1rem; }
.about-row dd { color: var(--concrete); font-size: 14px; line-height: 1.6; }

/* ============================================================
   PROCESS TIMELINE
   ============================================================ */
.process-timeline { position: relative; margin-top: 60px; padding-left: clamp(20px, 4vw, 40px); }
.process-line {
  position: absolute; top: 0; bottom: 0; left: clamp(20px, 4vw, 40px);
  width: 1px; background: rgba(255,255,255,0.12);
}
.process-line-fill {
  position: absolute; top: 0; left: 0; width: 100%; height: 0%;
  background: var(--red); box-shadow: 0 0 10px var(--red-glow);
}
.process-steps { display: flex; flex-direction: column; gap: clamp(56px, 8vw, 100px); padding-left: clamp(28px, 5vw, 56px); }
.process-step { position: relative; z-index: 2; max-width: 640px; }
.process-index {
  position: absolute; left: calc(-1 * clamp(28px, 5vw, 56px) - 6px); top: 0;
  transform: translateX(-100%);
  font-family: var(--font-display); font-size: 13px; color: var(--champagne); letter-spacing: 0.1em;
}
.process-media {
  position: relative; overflow: hidden;
  width: 100%; height: clamp(180px, 26vw, 320px); border-radius: 2px; margin-bottom: 24px;
  clip-path: inset(0 0 0 0);
  display: flex; align-items: center; justify-content: center;
}
.process-media img.process-photo {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
.process-media::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 clamp(40px, 6vw, 90px) clamp(10px, 1.6vw, 24px) rgba(0,0,0,0.5);
}
.process-media-logo {
  width: clamp(48px, 9vw, 84px); height: auto;
  opacity: 0.85;
  filter: drop-shadow(0 4px 18px rgba(0,0,0,0.5));
}
.process-step h3 { font-family: var(--font-display); font-size: clamp(1.4rem, 2.4vw, 2rem); margin-bottom: 0.4em; }
.process-step p { color: var(--concrete); font-size: 14px; max-width: 46ch; }

/* ============================================================
   FEATURED PROJECTS
   ============================================================ */
.featured-list { display: flex; flex-direction: column; margin-top: 40px; }
.featured-card {
  position: relative; z-index: 2;
  height: 92vh; min-height: 480px;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.08);
}
.featured-card + .featured-card { margin-top: 8px; }
img.featured-card-media {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 4s linear;
}
.featured-card:hover .featured-card-media { transform: scale(1.04); }
.featured-card-overlay {
  position: absolute; inset: 0;
  background: linear-gradient(0deg, rgba(0,0,0,0.75) 0%, rgba(0,0,0,0.05) 60%);
}
.featured-card-text {
  position: absolute; left: var(--container-pad); bottom: 56px; right: var(--container-pad);
  opacity: 0; transform: translateY(16px);
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out);
}
.featured-card:hover .featured-card-text { opacity: 1; transform: translateY(0); }
.featured-card-name { font-family: var(--font-display); font-size: clamp(1.8rem, 3.6vw, 3rem); }
.featured-card-meta { font-size: 12px; letter-spacing: 0.1em; color: var(--concrete); margin-top: 10px; }

/* ============================================================
   TRUST SECTION
   ============================================================ */
.trust { background: var(--black); }
.trust-counters {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 32px;
  margin-bottom: clamp(56px, 8vw, 96px);
}
.counter-item { text-align: left; }
.counter-value {
  display: block; font-family: var(--font-display); font-size: clamp(2.4rem, 5vw, 4.2rem);
  color: var(--white);
}
.counter-label { font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--concrete); }
.client-row {
  position: relative; z-index: 2;
  overflow: hidden;
  padding-top: 40px; border-top: 1px solid rgba(255,255,255,0.12);
}
/* Two identical tracks side by side, exactly double width — animating the
   wrap to translateX(-50%) moves precisely one track's width, so the second
   (duplicate, aria-hidden) track lands exactly where the first started the
   instant the loop resets: a seamless infinite marquee, not a visible jump. */
.client-track-wrap { display: flex; width: max-content; }
.client-track {
  display: flex; align-items: center; flex-shrink: 0;
  gap: clamp(24px, 4vw, 56px);
  padding-right: clamp(24px, 4vw, 56px);
}
.client-row.is-marquee .client-track-wrap {
  animation: client-marquee 28s linear infinite;
  will-change: transform; /* keeps this on its own compositor layer so the
    loop restart doesn't have to repaint — that repaint is what read as a
    "jerky" hitch every time it cycled back to the start. */
}
@keyframes client-marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
.client-mark {
  font-family: var(--font-display); font-size: 14px; font-weight: 400; letter-spacing: 0.06em;
  white-space: nowrap;
  color: var(--white); opacity: 0.5;
  transition: opacity 0.4s, font-weight 0.2s;
}
.client-mark:hover { opacity: 1; font-weight: 600; }
@media (prefers-reduced-motion: reduce) {
  .client-track:not(:first-child) { display: none; }
  .client-row.is-marquee .client-track-wrap { animation: none; }
}

/* ============================================================
   CONTACT
   ============================================================ */
.contact { position: relative; overflow: hidden; }
.contact-bg { position: absolute; inset: 0; z-index: 0; }
.contact-scrim { position: absolute; inset: 0; z-index: 1; background: rgba(5,5,5,0.55); }
.contact-inner {
  position: relative; z-index: 2;
  max-width: 1400px; margin: 0 auto; padding: 0 var(--container-pad);
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(40px, 6vw, 96px);
}
.contact-copy .section-headline { max-width: 12ch; }
.quick-actions { display: flex; gap: 28px; margin-top: 2em; }
.quick-action { font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; border-bottom: 1px solid rgba(255,255,255,0.4); padding-bottom: 3px; }
.quick-action:hover { border-color: var(--red); }

.contact-form { display: flex; flex-direction: column; gap: 30px; padding-top: 12px; }
.field input:focus-visible, .field textarea:focus-visible { outline: none; }
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.form-status { font-size: 13px; letter-spacing: 0.03em; }
.form-status.is-success { color: var(--champagne); }
.form-status.is-error { color: #e0736b; }
.recaptcha-notice { font-size: 11px; color: rgba(255,255,255,0.35); margin-top: 12px; }
.recaptcha-notice a { color: rgba(255,255,255,0.45); text-decoration: underline; }
.grecaptcha-badge,
.grecaptcha-badge * { visibility: hidden !important; pointer-events: none !important; width: 0 !important; height: 0 !important; overflow: hidden !important; }
.field { position: relative; }
.field input, .field textarea {
  width: 100%; padding: 10px 0 10px;
  border-bottom: 1px solid rgba(255,255,255,0.3);
  font-size: 15px; resize: none;
  background: transparent;
}
.field textarea { min-height: 44px; }
/* Chrome/Edge force a white autofill background (phone/email/etc) unless
   overridden — this fakes a transparent dark background via a huge inset
   shadow, which is the standard workaround since autofill ignores
   background-color directly. */
.field input:-webkit-autofill,
.field input:-webkit-autofill:hover,
.field input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--white);
  -webkit-box-shadow: 0 0 0px 1000px var(--black) inset;
  box-shadow: 0 0 0px 1000px var(--black) inset;
  transition: background-color 5000s ease-in-out 0s;
  caret-color: var(--white);
}
.field label {
  position: absolute; left: 0; top: 10px;
  font-size: 13px; color: var(--concrete);
  letter-spacing: 0.04em;
  pointer-events: none;
  transition: transform 0.3s var(--ease-out), font-size 0.3s var(--ease-out), color 0.3s;
  transform-origin: left;
}
.field input:focus, .field textarea:focus { border-color: var(--red); }
.field input:focus ~ label,
.field input:not(:placeholder-shown) ~ label,
.field textarea:focus ~ label,
.field textarea:not(:placeholder-shown) ~ label,
.field.has-value label {
  transform: translateY(-18px); font-size: 11px; color: var(--champagne);
}
.contact-form .btn { align-self: flex-start; margin-top: 10px; }

/* ============================================================
   FOOTER
   ============================================================ */
.site-footer { position: relative; background: var(--black); padding-top: 6px; }
.footer-glow {
  position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: var(--red);
  box-shadow: 0 0 16px 2px var(--red-glow);
  animation: footer-pulse 3s ease-in-out infinite;
}
@keyframes footer-pulse {
  0%, 100% { opacity: 0.5; }
  50% { opacity: 1; }
}
.footer-inner { max-width: 1600px; margin: 0 auto; padding: 64px var(--container-pad) 40px; }
.footer-top {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 32px;
  padding-bottom: 40px; border-bottom: 1px solid rgba(255,255,255,0.12);
}
.footer-logo {
  font-family: var(--font-display); font-size: 20px; letter-spacing: 0.2em;
  display: inline-flex; align-items: center; gap: 12px;
}
.footer-logo-mark { height: 44px; }
.footer-links { display: flex; gap: 28px; flex-wrap: wrap; }
.footer-links a { font-size: 12px; letter-spacing: 0.08em; color: var(--concrete); }
.footer-links a:hover { color: var(--white); }
.footer-social { display: flex; gap: 14px; }
.footer-social a {
  width: 36px; height: 36px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255,255,255,0.18);
  color: var(--concrete);
  transition: border-color 0.3s, color 0.3s, background 0.3s;
}
.footer-social a svg { width: 16px; height: 16px; }
.footer-social a:hover { border-color: var(--red); color: var(--red); background: rgba(140,31,31,0.08); }
.footer-bottom {
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px;
  padding-top: 28px; font-size: 11px; color: rgba(255,255,255,0.4); letter-spacing: 0.04em;
}
.footer-admin-link {
  color: rgba(255,255,255,0.3);
  border-bottom: 1px solid transparent;
  transition: color 0.3s, border-color 0.3s;
}
.footer-admin-link:hover { color: var(--red); border-color: var(--red); }

/* ============================================================
   RESPONSIVE — MOBILE
   ============================================================ */
@media (max-width: 900px) {
  .about { grid-template-columns: 1fr; }
  .about-media { min-height: 320px; }
  .contact-inner { grid-template-columns: 1fr; }
  .trust-counters { grid-template-columns: repeat(2, 1fr); }
  .project-modal-info { grid-template-columns: 1fr; }
}

@media (max-width: 1024px) {
  :root { --nav-h: 68px; }
  .nav-inner { gap: 12px; }
  .nav-logo {
    margin-right: auto;
    font-size: clamp(9px, 2.6vw, 12px);
    letter-spacing: 0.08em;
  }
  .nav-logo-mark { height: clamp(24px, 7vw, 38px); }
  .nav-links, .nav-cta { display: none; }
  .nav-burger { display: flex; flex-shrink: 0; }
  .lang-toggle { flex-shrink: 0; margin-left: 0; }
  .lang-toggle-btn { min-width: 24px; padding: 4px 7px; font-size: clamp(8px, 2.2vw, 10px); }
  .site-nav.is-mobile-open {
    background: rgba(5,5,5,0.97);
    height: auto;
    padding-bottom: 24px;
  }
  .site-nav.is-mobile-open .nav-links {
    display: flex; flex-direction: column; gap: 0;
    width: 100%; padding: 0 var(--container-pad);
  }
  .site-nav.is-mobile-open .nav-links .nav-link {
    padding: 16px 0; border-bottom: 1px solid rgba(255,255,255,0.1);
  }
  .site-nav.is-mobile-open .nav-cta {
    display: flex; margin: 20px var(--container-pad) 0;
  }
  .site-nav.is-mobile-open .nav-inner { flex-wrap: wrap; }
  .nav-burger.is-open span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .nav-burger.is-open span:nth-child(2) { opacity: 0; }
  .nav-burger.is-open span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
  .nav-burger span { transition: transform 0.3s var(--ease-inout), opacity 0.3s; }
  .gallery-grid { display: none; }
  .gallery-mobile-story { display: block; }
  .featured-card { height: 70vh; }
  .footer-top { flex-direction: column; align-items: flex-start; gap: 20px; }
  .category-nav-arrow { width: 40px; height: 40px; }
  .category-nav-arrow svg { width: 15px; height: 15px; }
}

/* ============================================================
   WORK IN PROGRESS SECTION — the current "Coming Soon" project.
   Starts `hidden` in the markup; js/comingSoon.js unhides it only when the
   admin panel has it switched on and there is something to show.
   ============================================================ */
/* A full-bleed horizontal carousel, one frame at a time. Deliberately breaks
   out of the site's container: no max-width and no side padding, so the
   photograph runs from one edge of the screen to the other with no strip of
   background beside it. Vertical stacking was replaced because a swipe reads
   as browsing the project, where scrolling past six tall frames reads as a
   chore. */
.wip-slider {
  position: relative;
  /* z-index:2 is not decoration — it is the site's standing rule. The floating
     3D logo scene is one fixed, full-viewport canvas at z-index:1, and every
     real photograph and every piece of text on the page sits at z-index:2 so
     it always paints above it (see .scene3d-canvas). Without this the logo
     drifted straight across the client's photographs. */
  z-index: 2;
  width: 100%;
  margin-top: clamp(32px, 4vw, 56px);
  overflow: hidden;
}
/* Width is left to Swiper, which sets it inline from its own measurement —
   a `width: 100%` here only competes with that and confuses the two. */
.wip-slider .swiper-slide { height: auto; }

.wip-tile {
  position: relative;
  /* Height is computed, not derived from `aspect-ratio`, and that is
     deliberate: `aspect-ratio` together with `max-height` shrinks the *width*
     too once the cap bites, which pulled the frame away from the screen edges
     and put back the very margins this layout exists to remove. 56.25vw is
     16:9; the vh term caps it on a wide monitor and the photo crops instead. */
  width: 100%;
  height: min(56.25vw, 82vh);
  overflow: hidden;
  background: #101010;
  cursor: zoom-in;
}
/* Swiper puts a grab cursor on the track; letting the tile inherit it keeps
   the whole strip reading as draggable. Desktop visitors see the site's own
   custom cursor here anyway (data-cursor="VIEW"). */
.wip-slider .wip-tile { cursor: inherit; }
.wip-tile:focus-visible {
  outline: 1px solid var(--champagne);
  outline-offset: -4px;
}
/* On a phone a 16:9 frame across a 390 px screen is barely 220 px tall — too
   slight to carry a photograph. A squarer crop claims real height instead. */
@media (max-width: 700px) {
  /* Square, and the same height for photos and video alike. Two reasons: a
     16:9 band across a phone came out at barely a quarter of the screen, far
     too slight to carry a photograph; and giving video its own ratio made the
     carousel jump in height every time a swipe crossed from one kind of frame
     to the other. */
  .wip-tile,
  .wip-tile-video { height: min(100vw, 66vh); }
}

/* Arrows sit inside the frame, and step out of the way on touch screens where
   the swipe itself is the control. */
.wip-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  z-index: 5;
  width: 52px; height: 52px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--white);
  background: rgba(5,5,5,0.35);
  border: 1px solid rgba(255,255,255,0.25);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  cursor: pointer;
  transition: background 0.3s, border-color 0.3s, opacity 0.3s;
}
.wip-nav svg { width: 18px; height: 18px; }
.wip-nav:hover { background: rgba(140,31,31,0.55); border-color: var(--red); }
.wip-nav-prev { left: clamp(14px, 2.5vw, 36px); }
.wip-nav-next { right: clamp(14px, 2.5vw, 36px); }
.wip-nav.swiper-button-disabled { opacity: 0.25; pointer-events: none; }
@media (hover: none) {
  .wip-nav { display: none; }
}

.wip-dots {
  position: absolute; left: 50%; bottom: 18px; z-index: 5;
  transform: translateX(-50%);
  display: flex; gap: 8px;
  padding: 9px 14px; border-radius: 999px;
  background: rgba(5,5,5,0.4);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.wip-dot {
  width: 22px; height: 2px;
  background: rgba(255,255,255,0.3);
  transition: background 0.35s ease;
}
.wip-dot.is-active { background: var(--champagne); }

/* Fallback for the case where the Swiper script never arrives: a native
   scroll-snap strip. Still swipes on touch, just without drag-by-mouse. */
.wip-slider.is-native-scroll .swiper-wrapper {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.wip-slider.is-native-scroll .swiper-wrapper::-webkit-scrollbar { display: none; }
.wip-slider.is-native-scroll .swiper-slide { flex: 0 0 100%; scroll-snap-align: center; }
.wip-slider.is-native-scroll .wip-nav { display: none; }
.wip-tile img,
.wip-tile video {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.wip-tile img {
  transition: transform 0.8s var(--ease-out), opacity 0.6s ease;
}
.wip-tile:hover img { transform: scale(1.04); }

/* A quiet darkening on hover so it reads as something you can open, without
   putting an icon on top of the photography. */
.wip-tile::before {
  content: "";
  position: absolute; inset: 0; z-index: 2;
  background: linear-gradient(to top, rgba(5,5,5,0.5), rgba(5,5,5,0) 55%);
  opacity: 0;
  transition: opacity 0.45s var(--ease-out);
  pointer-events: none;
}
.wip-tile:hover::before,
.wip-tile:focus-visible::before { opacity: 1; }

/* ============================================================
   COMING SOON POPUP
   Sits above the project modal (2000) and the photo lightbox (3000), but
   below the intro overlay (9999) — the intro must always win, and the popup
   is only opened once the intro is gone anyway.
   ============================================================ */
/* The frame around the card is deliberately tighter than the site's usual
   --container-pad. This is a full-attention moment on a dark backdrop, and
   the container padding left so much empty margin that the card read as a
   small notice rather than a presentation. */
.cs-popup {
  position: fixed; inset: 0; z-index: 4000;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(14px, 2.6vw, 52px);
}
.cs-popup[hidden] { display: none; }
.cs-popup-backdrop {
  position: absolute; inset: 0;
  background: rgba(5,5,5,0.88);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}
.cs-popup-card {
  position: relative;
  display: grid;
  /* The photograph is the point, so it takes the larger share; the copy needs
     only enough room to sit comfortably beside it. */
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.65fr);
  align-items: center;
  gap: clamp(26px, 3.2vw, 56px);
  width: min(1280px, 100%);
  max-height: calc(100dvh - 2 * clamp(14px, 2.6vw, 52px));
  padding: clamp(18px, 2vw, 40px);
  background: #0B0B0B;
  border: 1px solid rgba(201,184,150,0.22);
  box-shadow: 0 50px 140px rgba(0,0,0,0.75);
}
.cs-popup-close {
  position: absolute; top: 12px; right: 12px; z-index: 3;
  width: 46px; height: 46px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(5,5,5,0.6);
  border: 1px solid rgba(255,255,255,0.18);
  color: var(--white);
  cursor: pointer;
  transition: border-color 0.3s, color 0.3s, background 0.3s;
}
.cs-popup-close:hover { border-color: var(--champagne); color: var(--champagne); background: rgba(5,5,5,0.9); }
.cs-popup-close svg { width: 19px; height: 19px; }

.cs-popup-stage {
  position: relative;
  /* Wider than the old 4:3 — interiors are shot landscape, and at this card
     width a 3:2 frame fills the height without the copy column running short. */
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: #060606;
  /* The frames are thrown in from above and shaken about; without this they
     would spill out over the copy beside them. */
  isolation: isolate;
}
.cs-popup-frame {
  position: absolute; inset: 0;
  opacity: 0;
  will-change: transform, opacity, filter;
}
.cs-popup-frame img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
/* The lightning itself. `screen` so it blows the photo out to white at full
   opacity instead of just laying a grey sheet over it. */
.cs-popup-flash {
  position: absolute; inset: 0; z-index: 2;
  background: radial-gradient(circle at 50% 35%, #FFFFFF 0%, rgba(201,184,150,0.85) 45%, rgba(140,31,31,0.4) 100%);
  mix-blend-mode: screen;
  opacity: 0;
  pointer-events: none;
}

.cs-popup-copy { min-width: 0; }
.cs-popup-eyebrow {
  font-family: var(--font-body);
  font-size: 12px; font-weight: 600;
  letter-spacing: 0.32em; text-transform: uppercase;
  color: var(--champagne);
  margin-bottom: 1.5em;
}
.cs-popup-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.2rem, 3.6vw, 3.8rem);
  line-height: 1.1;
  color: var(--white);
  overflow-wrap: anywhere;
}
.cs-popup-text {
  margin-top: 1.1em;
  font-size: 15px;
  line-height: 1.7;
  color: var(--concrete);
}
.cs-popup-dots { display: flex; gap: 8px; margin-top: 2.2em; }
.cs-popup-dot {
  width: 26px; height: 2px;
  background: rgba(255,255,255,0.2);
  transition: background 0.35s ease;
}
.cs-popup-dot.is-active { background: var(--champagne); }

@media (max-width: 760px) {
  /* Full screen on a phone. No frame, no margins, no floating card: the
     photograph runs edge to edge and the copy sits under it. A centred box
     with margins reads as a system alert; this reads as the studio's work.
     `100dvh` rather than `100vh` so the browser's own collapsing toolbar
     cannot leave the bottom of the copy cut off. */
  .cs-popup { padding: 0; }
  .cs-popup-card {
    /* One single cell. The photo and the copy are both placed into it and
       overlap, so the photograph gets the entire screen and the text sits on
       top of it rather than stealing a strip along the bottom. */
    grid-template-columns: 1fr;
    grid-template-rows: 1fr;
    align-items: stretch;
    gap: 0;
    width: 100%;
    height: 100dvh;
    max-height: none;
    padding: 0;
    border: none;
    box-shadow: none;
    overflow: hidden;
  }
  /* Height comes from the grid cell, so the fixed ratio has to go — otherwise
     it would fight the cell for control and leave a band of dead space. */
  .cs-popup-stage {
    grid-area: 1 / 1;
    aspect-ratio: auto;
    height: 100%;
    min-height: 0;
  }
  .cs-popup-copy {
    grid-area: 1 / 1;
    align-self: end;
    position: relative;
    z-index: 3;
    padding: 90px 22px calc(30px + env(safe-area-inset-bottom, 0px));
    /* Reaches well up the frame: the text has to stay readable over a photo
       whose brightness nobody controls, and a hard-edged panel would cut the
       image in half. */
    background: linear-gradient(
      to top,
      rgba(5,5,5,0.94) 0%,
      rgba(5,5,5,0.86) 35%,
      rgba(5,5,5,0.45) 70%,
      rgba(5,5,5,0) 100%
    );
  }
  .cs-popup-name { font-size: clamp(2rem, 9vw, 2.8rem); }
  .cs-popup-close {
    top: calc(14px + env(safe-area-inset-top, 0px));
    right: 14px;
    background: rgba(5,5,5,0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
  }
  .cs-popup-dots { margin-top: 1.5em; }
}

/* ============================================================
   SCROLL-TO-TOP BUTTON
   ============================================================ */
.scroll-top-btn {
  position: fixed; right: clamp(18px, 4vw, 36px); bottom: clamp(18px, 4vw, 36px);
  z-index: 400;
  width: 52px; height: 52px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(5,5,5,0.65);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255,255,255,0.18);
  color: var(--champagne);
  cursor: pointer;
  opacity: 0; transform: translateY(12px) scale(0.9); pointer-events: none;
  transition: opacity 0.4s var(--ease-out), transform 0.4s var(--ease-out), border-color 0.3s, background 0.3s, bottom 0.3s var(--ease-inout);
}
.scroll-top-btn.is-visible { opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; }
.scroll-top-btn:hover { border-color: var(--red); background: rgba(140,31,31,0.35); color: var(--white); }
.scroll-top-btn svg { width: 20px; height: 20px; }
/* Clears the footer's "Admin" link, which sits in this same corner. */
.scroll-top-btn.is-above-footer { bottom: calc(clamp(18px, 4vw, 36px) + 60px); }

/* ============================================================
   ATMOSPHERE — 3D falling logo objects (see js/scene3d.js)
   ============================================================ */
/* One shared, full-viewport, fixed WebGL canvas — not a per-section DOM
   layer — since a single Three.js context is far cheaper than several. It
   sits at the same z-index:1 tier the old 2D particle layer used, so the
   existing protection scheme is untouched: every real photo container
   (.project-card, .featured-card, .about-media, .hero-bg-parallax) and every
   text element (.eyebrow, .section-headline, .section-sub, .about-headline,
   etc.) already sits at z-index:2, so those always paint above the canvas
   regardless of where an object's screen position lands. */
.scene3d-canvas {
  position: fixed; inset: 0;
  z-index: 1;
  pointer-events: none;
}

/* ============================================================
   ACCESSIBILITY — reduced motion
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .hero-bg { animation: none; }
  .scroll-hint span { animation: none; }
  .footer-glow { animation: none; }
  * {
    scroll-behavior: auto !important;
  }
}
