/* ============================================================
   ROUND 2 CUSTOMS — styles.css
   ============================================================ */

/* --- Custom Properties --- */
:root {
  --bg: #000000;
  --terracotta: #b84d1a;
  --white: #ffffff;
  --gray-inactive: #3d3d3d;

  /* Adobe Fonts kit family name is 'halyard-display' — 'Halyard Display'
     only matched copies installed locally (e.g. via Creative Cloud), so
     phones fell back to the system font */
  --font-display: 'halyard-display', sans-serif;
  /* Gotham via the Adobe Fonts kit (weights 300-800 + italics) */
  --font-body: 'gotham', sans-serif;

  --page-pad: 120px;
  --section-py: 80px;
  --gap: 24px;
  --navbar-h: 76px; /* scrolled-state navbar height — .navbar.is-scrolled .nav-inner padding (16px * 2) + .nav-toggle (44px) */

  --btn-gradient: linear-gradient(181.14deg, rgba(255,255,255,0.07) 15.71%, rgba(242,242,242,0.07) 92.36%);
  --field-gradient: linear-gradient(180.6deg, rgba(255,255,255,0.07) 15.71%, rgba(242,242,242,0.07) 92.36%);
  --field-border: 1px solid rgba(255,255,255,0.07);
}

/* --- Reset --- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }

/* visually hidden but still announced by screen readers/assistive tech —
   for content that needs to exist in the a11y tree without a visual
   presence, e.g. a real page <h1> when the visible heading is decorative */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
body {
  position: relative;
  background: var(--bg);
  color: var(--white);
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 16px;
  line-height: 26px;
  letter-spacing: 0.16px;
  overflow-x: hidden;
}

/* Lift all real content above the guide lines below */
body > * { position: relative; z-index: 1; }

/* Vertical guide lines tracking the content column edges, with randomized
   faint highlights (generated in JS) that drift on scroll like parallax */
.grid-line {
  display: none; /* hidden for now */
  content: '';
  position: fixed;
  top: 0;
  bottom: 0;
  width: 1px;
  background-color: rgba(255, 255, 255, 0.08);
  background-repeat: repeat-y;
  pointer-events: none;
  z-index: 2;
  will-change: background-position;
}
.grid-line--left { left: var(--page-pad); }
.grid-line--right { right: var(--page-pad); }

/* Horizontal rules marking section boundaries, each with its own
   elongated highlight sliding across it, alternating direction */
.fully-custom,
.trusted-vendors,
.studio,
.customer-build,
.contact,
.site-footer {
  border-top: none; /* hidden for now */
}

.fully-custom::before,
.trusted-vendors::before,
.studio::before,
.customer-build::before,
.contact::before,
.site-footer::before {
  display: none; /* hidden for now */
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background-image: linear-gradient(to right, transparent 0%, rgba(255, 255, 255, 0.12) 50%, transparent 100%);
  background-size: 28% 100%;
  background-repeat: no-repeat;
  background-position-x: -28%;
  pointer-events: none;
  animation: h-line-flow 11s linear infinite;
}

.trusted-vendors::before,
.customer-build::before {
  animation-direction: reverse;
}

@keyframes h-line-flow {
  from { background-position-x: -28%; }
  to { background-position-x: 128%; }
}

/* Desktop: inset each section 24px from the viewport's left/right edges,
   on top of the existing --page-pad content padding inside each section */
@media (min-width: 1025px) {
  .hero,
  .split-section,
  .trusted-vendors,
  .studio,
  .contact,
  .site-footer {
    margin-left: 0; /* inset disabled for now */
    margin-right: 0;
  }
}
img { display: block; max-width: 100%; }
a { text-decoration: none; color: inherit; }
ul { list-style: none; }
button { cursor: pointer; border: none; background: none; font: inherit; color: inherit; }

/* ============================================================
   NAV
   ============================================================ */
.navbar {
  position: sticky;
  top: 0;
  z-index: 200;
  width: 100%;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(30px);
  -webkit-backdrop-filter: blur(30px);
  transform: translateY(0);
  transition: transform 0.3s ease;
}

/* Set by the product-bar scroll handler on the VPIN Noire page — slides
   the navbar away on scroll-down past the hero, and pushes the product
   bar back down to navbar-height when it returns on scroll-up. */
body.nav-collapsed .navbar {
  transform: translateY(-100%);
}

body.nav-collapsed .product-bar {
  top: 20px;
}

.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 44px var(--page-pad);
  transition: padding 0.3s ease;
}

.navbar.is-scrolled .nav-inner {
  padding-top: 16px;
  padding-bottom: 16px;
}

.nav-logo img {
  height: 26px;
  width: auto;
}

/* Hamburger */
.nav-toggle {
  width: 44px;
  height: 44px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
}

.nav-toggle span {
  display: block;
  width: 30px;
  height: 1.5px;
  background: var(--white);
  transition: transform 0.3s ease, opacity 0.2s ease;
  transform-origin: center;
}

/* open state: the bars fade out and the pixel-style X from the gallery
   lightbox's close button takes their place */
.nav-toggle { position: relative; }

.nav-toggle::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 28px;
  height: 28px;
  transform: translate(-50%, -50%);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 168 168'%3E%3Cpath d='M24 168H0V144H24V168ZM168 144V168H144V144H168ZM48 144H24V120H48V144ZM144 120V144H120V120H144ZM72 120H48V96H72V120ZM120 96V120H96V96H120ZM96 72V96H72V72H96ZM72 72H48V48H72V72ZM120 48V72H96V48H120ZM48 48H24V24H48V48ZM144 24V48H120V24H144ZM24 24H0V0H24V24ZM168 0V24H144V0H168Z' fill='%23fff'/%3E%3C/svg%3E") center / contain no-repeat;
  opacity: 0;
  transition: opacity 0.2s ease;
  pointer-events: none;
}

.nav-toggle.is-open span { opacity: 0; }
.nav-toggle.is-open::after { opacity: 1; }

/* Nav overlay menu */
.nav-menu {
  position: fixed;
  inset: 0;
  z-index: 199;
  background: rgba(0, 0, 0, 0.85);
  backdrop-filter: blur(36.5px);
  -webkit-backdrop-filter: blur(36.5px);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 10px;
  padding: 60px var(--page-pad);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.35s ease;
}

.nav-menu.is-open {
  opacity: 1;
  pointer-events: all;
}

.nav-menu ul {
  display: flex;
  flex-direction: column;
  gap: 28px;
  width: 100%;
}

.nav-menu li a {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  width: 100%;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 64px;
  line-height: 1.05;
  letter-spacing: 1.28px;
  text-align: right;
  text-transform: uppercase;
  color: var(--white);
  text-shadow: 0 0 0 rgba(214, 94, 56, 0);
  transition: color 0.2s ease, text-shadow 0.3s ease;
}

/* Retro-menu selection arrow — the same pixel chevron used as the
   carousel's next-slide cursor (Figma "8bit-arrow", node 56:78) — slides
   in from the left of the hovered item without shifting its text. */
.nav-menu li a::before {
  content: "";
  flex: none;
  width: 46px;
  height: 32px;
  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5NiIgaGVpZ2h0PSI2NyIgdmlld0JveD0iMTAgMTAgMjQwIDE2OCI+CjxwYXRoIGQ9Ik0xNzggMTc4SDE1NFYxNTRIMTc4VjE3OFpNMjAyIDE1NEgxNzhWMTMwSDIwMlYxNTRaTTIyNiAxMzBIMjAyVjEwNkgxMFY4MkgyMDJWNThIMjI2VjgySDI1MFYxMDZIMjI2VjEzMFpNMjAyIDU4SDE3OFYzNEgyMDJWNThaTTE3OCAzNEgxNTRWMTBIMTc4VjM0WiIgZmlsbD0iI0Q2NUUzOCIvPgo8L3N2Zz4K");
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  opacity: 0;
  margin-right: -62px;
  transform: translateX(12px);
  transition: opacity 0.25s ease, transform 0.25s ease, margin-right 0.25s ease;
}

.nav-menu li a:hover { text-shadow: 0 0 28px rgba(214, 94, 56, 0.65); }

.nav-menu li a:hover::before {
  opacity: 1;
  transform: translateX(0);
  margin-right: 16px;
}

.nav-menu li a.is-current { color: var(--terracotta); }

/* Custom Builder is a placeholder feature — it doesn't link anywhere.
   Reads normal by default; on hover (mouse) or click/tap (.is-revealed,
   toggled in scripts.js) the text greys out instead of glowing, the
   "Coming Soon" flag fades in, and the selection-arrow stays suppressed */
#nav-link-custom-builder { cursor: pointer; }
#nav-link-custom-builder:hover,
#nav-link-custom-builder.is-revealed { color: rgba(255, 255, 255, 0.45); text-shadow: 0 0 0 rgba(214, 94, 56, 0); }
#nav-link-custom-builder:hover::before,
#nav-link-custom-builder.is-revealed::before { opacity: 0; transform: translateX(12px); margin-right: -62px; }

/* "Coming Soon" flag on the Custom Builder nav item — pinned so it overlaps
   the top-right corner of the text rather than floating clear above it,
   hidden until the item is hovered */
.nav-badge {
  position: absolute;
  top: 14px;
  right: -10px;
  transform: translateY(calc(-40% + 10px));
  display: inline-flex;
  align-items: center;
  padding: 4px 12px;
  border-radius: 60px;
  background: linear-gradient(90deg, #e6431e 0%, #ff8a3d 100%);
  color: var(--white);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 11px;
  line-height: 1;
  letter-spacing: 0.6px;
  text-shadow: none;
  white-space: nowrap;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
  opacity: 0;
  transition: opacity 0.3s ease, transform 0.3s ease;
}

#nav-link-custom-builder:hover .nav-badge,
#nav-link-custom-builder.is-revealed .nav-badge { opacity: 1; transform: translateY(-40%); }

/* ============================================================
   BUTTONS
   ============================================================ */
.btn-primary {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  height: 58px;
  padding: 16px 32px;
  border-radius: 60px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  background: var(--btn-gradient);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.65px;
  color: var(--white);
  white-space: nowrap;
  flex-shrink: 0;
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.btn-primary::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--terracotta);
  transform: translateX(-101%);
  transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: -1;
}

.btn-primary:hover::before {
  transform: translateX(0);
}


/* ============================================================
   HERO
   ============================================================ */
.hero {
  display: flex;
  gap: var(--gap);
  min-height: 861px;
  overflow: hidden;
}

.hero--compact {
  min-height: 450px;
  justify-content: flex-start;
}

.hero--compact .hero-content {
  flex: none;
  align-items: flex-start;
  text-align: left;
  padding: 0 var(--page-pad);
  transform: none;
}

.hero--compact .hero-text p {
  max-width: 588px;
}

.hero-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 60px;
  padding-left: var(--page-pad);
  min-width: 0;
  transform: translateY(-80px);
  z-index: 2;
}

.hero-text {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

/* Scroll-reveal: text blocks slide up + fade in as their section enters view */
.hero-text,
.section-text,
.contact-header {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.8s ease, transform 0.8s ease;
}

.hero-text.is-visible,
.section-text.is-visible,
.contact-header.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.hero h1 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 100px;
  line-height: 92px;
  letter-spacing: 2.3px;
  color: var(--white);
}

/* Word-cycle scanline glitch animation ("ARCADES" / "SPACES" / "EXPERIENCES") */
.word-cycle {
  position: relative;
  display: inline-block;
  overflow: hidden;
  height: 92px;
  vertical-align: top;
}

.word-cycle-display {
  position: relative;
  display: flex;
  align-items: center;
  height: 92px;
  white-space: nowrap;
}

.word-cycle.is-glitching .word-cycle-display {
  animation: glitch-jitter 0.25s steps(2, jump-none) 2;
}

.word-cycle.is-glitching .word-cycle-display::before,
.word-cycle.is-glitching .word-cycle-display::after {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  mix-blend-mode: screen;
}

.word-cycle.is-glitching .word-cycle-display::before {
  color: var(--terracotta);
  clip-path: polygon(0 8%, 100% 8%, 100% 38%, 0 38%);
  transform: translateX(-14px);
  animation: glitch-shift-before 0.25s steps(2, jump-none) 2;
}

.word-cycle.is-glitching .word-cycle-display::after {
  color: #3f9bdc;
  clip-path: polygon(0 62%, 100% 62%, 100% 92%, 0 92%);
  transform: translateX(14px);
  animation: glitch-shift-after 0.25s steps(2, jump-none) 2;
}

@keyframes glitch-shift-before {
  0% { transform: translateX(-14px); }
  50% { transform: translateX(-20px); }
  100% { transform: translateX(-9px); }
}

@keyframes glitch-shift-after {
  0% { transform: translateX(14px); }
  50% { transform: translateX(20px); }
  100% { transform: translateX(9px); }
}

.word-cycle::after {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.5) 0px,
    rgba(0, 0, 0, 0.5) 1px,
    transparent 1px,
    transparent 3px
  );
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: multiply;
  transition: opacity 0.15s ease;
}

.word-cycle.is-glitching::after { opacity: 1; }

@keyframes glitch-jitter {
  0% { transform: translateX(0); }
  50% { transform: translateX(-6px); }
  100% { transform: translateX(6px); }
}

.hero-content > p,
.hero-text p {
  font-size: 16px;
  line-height: 26px;
  letter-spacing: 0.16px;
  max-width: 588px;
}

.hero-image {
  flex: 1;
  position: relative;
  overflow: hidden;
  min-width: 0;
}

.hero-image img {
  position: absolute;
  inset: 0;
  width: 104%;
  height: 114%;
  top: -2.8%;
  left: -0.02%;
  object-fit: cover;
  transform: scale(0.85) translate(-6%, -8%) translateY(var(--parallax-y, 0px));
  transform-origin: center;
  will-change: transform;
}

.hero-image-fade {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right, var(--bg) 0%, transparent 18%),
    linear-gradient(to top, var(--bg) 0%, transparent 12%);
  pointer-events: none;
}

/* ============================================================
   SPLIT SECTIONS (shared by Fully Custom + Customer Build)
   ============================================================ */
.split-section {
  display: flex;
  overflow: hidden;
}

.split-image {
  flex: 1;
  position: relative;
  overflow: hidden;
  min-height: 728px;
  min-width: 0;
}

.split-image img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  transform: translateY(var(--parallax-y, 0px));
  will-change: transform;
}

/* Customer Build: nudge the cutout 100px toward the copy and 50px down (side-by-side
   layout only — it's centred once the section stacks on mobile) */
@media (min-width: 769px) {
  /* let the shifted cutout spill left instead of being clipped — the
     section's own overflow: hidden still contains the parallax */
  .customer-build .split-image { overflow: visible; }
  .customer-build .split-image img {
    top: 50px;
    bottom: -50px;
    left: -100px;
    right: 100px;
  }
}
/* …and a bit larger on desktop — the image is sized by the box height
   (object-fit: contain), so a taller box grows it without cropping */
@media (min-width: 1025px) {
  .customer-build .split-image { min-height: 820px; }
}

.image-fade {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.image-fade--left  { background: linear-gradient(to right, var(--bg) 0%, transparent 18%); }
.image-fade--bottom { background: linear-gradient(to top, var(--bg) 0%, transparent 12%); }

.split-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 60px;
  padding: var(--section-py) 0;
  min-width: 0;
}

.split-content--right {
  padding-left: var(--gap);
  padding-right: var(--page-pad);
}

.split-content--left {
  padding-left: var(--page-pad);
  padding-right: var(--gap);
}

.section-text {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 58px;
  line-height: 54px;
  letter-spacing: 1.16px;
  color: var(--white);
}

.section-text p {
  font-size: 16px;
  line-height: 26px;
  letter-spacing: 0.16px;
  max-width: 540px;
}

/* Services list */
.services-list {
  display: flex;
  gap: 60px;
}

.services-list ul {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.services-list li {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 16px;
  line-height: 26px;
  letter-spacing: 1px;
  white-space: nowrap;
}

.services-list li::before {
  content: '';
  flex-shrink: 0;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--terracotta);
}

/* Eyebrow label */
.eyebrow {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 24px;
  letter-spacing: 1.8px;
  color: var(--terracotta);
}

/* ============================================================
   TRUSTED VENDORS
   ============================================================ */
.trusted-vendors {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 44px;
  padding: 140px var(--page-pad);
}

.section-label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 20px;
  line-height: 44px;
  letter-spacing: 0.4px;
  text-align: center;
}

.logo-gallery {
  width: 100%;
}

/* static row — capped width pulls the logos in from the page edges */
.logo-track {
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: 1120px;
  margin: 0 auto;
  gap: 20px;
}

.vendor-logo {
  height: 56px;
  width: 190px;
  object-fit: contain;
  opacity: 0.85;
  transition: opacity 0.2s ease;
}

.vendor-logo:hover { opacity: 1; }

/* ============================================================
   STUDIO CAROUSEL
   ============================================================ */
.studio {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 60px;
  padding: var(--section-py) 0;
  overflow: hidden;
}

.carousel-container {
  position: relative;
  width: 100%;
  height: 653px;
}

/* All slides stack at dead center; JS drives each one's xPercent/scale/
   opacity based on its distance from `current`, so navigating literally
   slides the side slides across into the middle. */
.carousel-track {
  position: absolute;
  width: 646px;
  height: 100%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.carousel-slide {
  list-style: none;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: 12px;
  cursor: pointer;
}

/* 8-bit arrow cursors on the side slides, from the Figma "8bit-arrow" component
   (node 56:78) — solid terracotta staircase-pixel chevron, no outline. */
.carousel-slide[data-role="prev"]:hover,
.rp-tile[data-role="prev"]:hover {
  cursor: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5NiIgaGVpZ2h0PSI2NyIgdmlld0JveD0iMTAgMTAgMjQwIDE2OCI+CjxwYXRoIGQ9Ik04MiAxNzhIMTA2VjE1NEg4MlYxNzhaTTU4IDE1NEg4MlYxMzBINThWMTU0Wk0zNCAxMzBINThWMTA2SDI1MFY4Mkg1OFY1OEgzNFY4MkgxMFYxMDZIMzRWMTMwWk01OCA1OEg4MlYzNEg1OFY1OFpNODIgMzRIMTA2VjEwSDgyVjM0WiIgZmlsbD0iI0Q2NUUzOCIvPgo8L3N2Zz4K") 0 34, pointer;
}

.carousel-slide[data-role="next"]:hover,
.rp-tile[data-role="next"]:hover {
  cursor: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5NiIgaGVpZ2h0PSI2NyIgdmlld0JveD0iMTAgMTAgMjQwIDE2OCI+CjxwYXRoIGQ9Ik0xNzggMTc4SDE1NFYxNTRIMTc4VjE3OFpNMjAyIDE1NEgxNzhWMTMwSDIwMlYxNTRaTTIyNiAxMzBIMjAyVjEwNkgxMFY4MkgyMDJWNThIMjI2VjgySDI1MFYxMDZIMjI2VjEzMFpNMjAyIDU4SDE3OFYzNEgyMDJWNThaTTE3OCAzNEgxNTRWMTBIMTc4VjM0WiIgZmlsbD0iI0Q2NUUzOCIvPgo8L3N2Zz4K") 96 34, pointer;
}

/* Center slide cursor, from the Figma "8bit-crosshair" component (node 56:79) */
.carousel-slide[data-role="center"]:hover {
  cursor: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MCIgaGVpZ2h0PSI4MCIgdmlld0JveD0iMCAwIDI0MCAyNDAiPgo8cGF0aCBkPSJNMTMyIDI0MEgxMDhWMTU2SDEzMlYyNDBaTTEwOCAxNTZIODRWMTMySDEwOFYxNTZaTTE1NiAxNTZIMTMyVjEzMkgxNTZWMTU2Wk04NCAxMzJIMFYxMDhIODRWMTMyWk0yNDAgMTMySDE1NlYxMDhIMjQwVjEzMlpNMTMyIDg0SDE1NlYxMDhIMTMyVjg1SDEwOFYxMDhIODRWODRIMTA4VjBIMTMyVjg0WiIgZmlsbD0iI0Q2NUUzOCIvPgo8L3N2Zz4K") 40 40, auto;
}

.carousel-slide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: top;
  background: #000;
}

/* "THE STUDIO" label at bottom of the carousel */
.studio-label {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  padding: 48px;
  background: linear-gradient(to top, rgba(0,0,0,0.75) 0%, transparent 100%);
  pointer-events: none;
}

.studio-label h2 {
  font-size: 58px;
  line-height: 54px;
  letter-spacing: 1.16px;
  text-align: left;
}

/* Pagination dots */
.carousel-pagination {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pagination-dot {
  height: 2px;
  border-radius: 0;
  cursor: pointer;
  transition: width 0.3s ease, background 0.3s ease;
  width: 14px;
  background: var(--gray-inactive);
  padding: 0;
}

.pagination-dot.is-active {
  width: 60px;
  background: var(--terracotta);
}

/* ============================================================
   SHOWROOM PAGE
   ============================================================ */
.showroom-gallery {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 24px var(--page-pad) 120px;
}

/* ============================================================
   RECENT PROJECT STORIES
   Figma: https://www.figma.com/design/KWppWGIEe8PSNTO8ao7Zpu/R2C?node-id=68-95
   Uses its own accent (#d65e38) rather than --terracotta — matches the
   design file exactly rather than the button/eyebrow accent used elsewhere.
   ============================================================ */
.project-stories-label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 24px;
  line-height: normal;
  letter-spacing: 0.48px;
  color: #d65e38;
}

/* About page section titles (What Sets Us Apart, Who We Build For) —
   flush-left rather than centred */
.project-stories-label--center {
  text-align: left;
}

.project-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}

.project-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  height: 220px;
  padding: 0 44px;
  border-radius: 8px;
  border: 1px solid #3e3e3e;
  overflow: hidden;
  background: var(--bg);
  transition: border-color 0.3s ease, border-width 0.3s ease, padding 0.35s ease;
}

.project-card:hover {
  border-color: #d65e38;
  border-width: 2px;
  padding: 16px 44px 28px;
}

/* Card image is sized/offset larger than its container (Figma's pan-and-zoom
   crop technique) so the hover state can zoom out and pan left smoothly.
   object-fit:cover on top keeps any source photo's own aspect ratio intact. */
.project-card img {
  position: absolute;
  max-width: none;
  width: 74.21%;
  height: 279.62%;
  top: -71.69%;
  left: 40.85%;
  object-fit: cover;
  object-position: center;
  transition: width 0.45s ease, height 0.45s ease, top 0.45s ease, left 0.45s ease;
  z-index: 0;
}

.project-card:hover img {
  width: 49.91%;
  height: 188.06%;
  top: -44.19%;
  left: 53%;
}

.project-card-fade {
  position: absolute;
  inset: 0;
  background: linear-gradient(to right, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.15) 55%, transparent 100%);
  z-index: 1;
}

.project-card-name {
  position: relative;
  z-index: 2;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 42px;
  line-height: 36px;
  letter-spacing: 0.84px;
  color: var(--white);
  text-transform: uppercase;
  transform: translateY(5px);
  transition: transform 0.3s ease;
}

.project-card:hover .project-card-name {
  transform: translateY(0);
}

/* ============================================================
   PROJECT GALLERY
   Figma: https://www.figma.com/design/KWppWGIEe8PSNTO8ao7Zpu/R2C?node-id=69-132
   Bento-style mosaic: a large card + a stacked column on the top row,
   three equal cards on the bottom row. Fluid widths (flex:1) instead of
   Figma's fixed 588px so it holds up at any viewport width.
   ============================================================ */
.project-gallery {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 120px var(--page-pad);
  background: var(--bg);
}

.project-gallery h2 {
  font-size: 24px;
  line-height: normal;
  letter-spacing: 0.48px;
  color: var(--terracotta);
}

/* the VPIN Noire page runs its heading white rather than accented */
body.page-vpin-noire .project-gallery h2 {
  color: var(--white);
}

/* About page "The Shop" — white and flush-left, matching the titles above */
.project-gallery .project-gallery-heading--center {
  text-align: left;
  color: var(--white);
}

#the-shop {
  padding-top: 200px;
}

@media (max-width: 768px) {
  /* 200px is disproportionate on a short mobile viewport */
  #the-shop { padding-top: 100px; }
}

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

.gallery-row {
  display: flex;
  gap: 16px;
}

.gallery-row--top {
  height: 580px;
}

.gallery-card {
  position: relative;
  display: block;
  flex: 1;
  min-width: 0;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  overflow: hidden;
  background: var(--bg);
  cursor: pointer;
  transition: border-color 0.3s ease, border-width 0.3s ease;
}

/* matches the Recent Project Stories card hover */
.gallery-card:hover {
  border-color: #d65e38;
  border-width: 2px;
}

.gallery-card img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  transform: scale(1);
  transition: transform 0.35s ease;
}

.gallery-card:hover img {
  transform: scale(1.12);
}

/* Case-study galleries use full photos rather than cut-out PNGs, so fill the tile */
.project-gallery--photos .gallery-card img {
  object-fit: cover;
}

.gallery-col {
  flex: 2;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.gallery-col > .gallery-row {
  flex: 1;
  min-height: 0;
}

.gallery-row--split .gallery-card:first-child {
  flex: 3;
}

.gallery-row--split .gallery-card:last-child {
  flex: 2;
}

/* ============================================================
   PROJECT GALLERY MODAL
   ============================================================ */
.gallery-modal {
  position: fixed;
  inset: 0;
  z-index: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px;
  background: rgba(0, 0, 0, 0.96);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}

.gallery-modal.is-open {
  opacity: 1;
  pointer-events: all;
}

.gallery-modal-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  width: 100%;
  max-width: 1100px;
}

.gallery-modal-title {
  position: absolute;
  top: 32px;
  left: 32px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--white);
}

.gallery-modal-image {
  position: relative;
  width: 100%;
  height: 680px;
  border-radius: 16px;
  overflow: hidden;
  background: var(--bg);
}

.gallery-modal-image img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* one scrollable row, so long photo lists don't push the modal off-screen;
   "safe" keeps the first thumbs reachable once the row overflows */
.gallery-modal-thumbs {
  display: flex;
  justify-content: safe center;
  gap: 12px;
  max-width: 100%;
  overflow-x: auto;
  padding-bottom: 4px;
}

.gallery-modal-thumb {
  flex-shrink: 0;
  width: 72px;
  height: 72px;
  padding: 0;
  border-radius: 8px;
  overflow: hidden;
  border: 2px solid transparent;
  background: var(--bg);
  cursor: pointer;
  transition: border-color 0.2s ease;
}

.gallery-modal-thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0.5;
  transition: opacity 0.2s ease;
}

.gallery-modal-thumb:hover img {
  opacity: 0.8;
}

.gallery-modal-thumb.is-active {
  border-color: #d65e38;
}

.gallery-modal-thumb.is-active img {
  opacity: 1;
}

/* Bare pixel-X icon, no button chrome — same treatment as the arrows,
   from the Figma "close" component (node 56:78) */
.gallery-modal-close {
  position: absolute;
  top: 32px;
  right: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #808080;
  transition: color 0.2s ease;
}

.gallery-modal-close:hover {
  color: var(--white);
}

/* Bare pixel-chevron icon, no button chrome — matches the studio
   carousel's prev/next cursor treatment exactly, just larger and clickable */
.gallery-modal-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #d65e38;
  transition: color 0.2s ease, transform 0.2s ease;
}

.gallery-modal-arrow:hover {
  color: var(--white);
}

.gallery-modal-arrow--prev {
  left: 32px;
}

.gallery-modal-arrow--prev:hover {
  transform: translate(-6px, -50%);
}

.gallery-modal-arrow--next {
  right: 32px;
}

.gallery-modal-arrow--next:hover {
  transform: translate(6px, -50%);
}

.gallery-modal-arrow svg {
  display: block;
  width: 48px;
  height: 34px;
}

/* ============================================================
   PROJECT DETAIL PAGES
   ============================================================ */
.project-hero {
  position: relative;
  height: 520px;
  overflow: hidden;
}

.project-hero img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.project-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, var(--bg) 0%, transparent 30%);
  pointer-events: none;
}

.project-content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
  max-width: 750px;
  padding: var(--section-py) var(--page-pad);
}

.project-content p {
  font-size: 16px;
  line-height: 26px;
  letter-spacing: 0.16px;
  color: rgba(255, 255, 255, 0.6);
}

.project-back {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.65px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
  transition: color 0.2s ease;
}

.project-back:hover {
  color: var(--terracotta);
}

/* ============================================================
   PRODUCT STICKY BAR — VPIN Noire
   Apple product-page pattern: a second sticky bar directly under the
   global nav, hidden until the hero scrolls past, showing the product
   name and in-page section tabs on one row (no buttons).
   ============================================================ */
.product-bar {
  /* fixed, not sticky — a sticky bar stays in normal flow and would
     occupy its own height between the navbar and the hero even while
     invisible, pushing the hero down. */
  position: fixed;
  top: calc(var(--navbar-h) + 20px);
  left: 0;
  right: 0;
  z-index: 190;
  width: 66.6667%; /* 8/12 columns */
  margin: 0 auto;
  border-radius: 60px;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.75);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.18);
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 0.3s ease, transform 0.3s ease, top 0.3s ease;
}

.product-bar.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: all;
}

.product-bar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 40px;
  padding: 18px 32px;
  overflow-x: auto;
  scrollbar-width: none;
}

.product-bar-inner::-webkit-scrollbar {
  display: none;
}

.product-bar-name {
  flex-shrink: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: 0.5px;
  color: var(--white);
  text-transform: uppercase;
  white-space: nowrap;
}

.product-bar-tabs {
  display: flex;
  align-items: center;
  gap: 28px;
  flex-shrink: 0;
}

.product-bar-tabs a {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 14px;
  letter-spacing: 0.3px;
  color: rgba(255, 255, 255, 0.5);
  white-space: nowrap;
  transition: color 0.2s ease;
}

.product-bar-tabs a:hover {
  color: rgba(255, 255, 255, 0.85);
}

.product-bar-tabs a.is-active {
  color: var(--white);
}

/* ============================================================
   PROJECT HERO — VPIN Noire
   Figma: https://www.figma.com/design/KWppWGIEe8PSNTO8ao7Zpu/R2C?node-id=73-341
   Frame is a fixed 1440x861 composition (not a fluid page-pad section).
   Horizontal placement (left/width) is that frame's exact px value
   converted to a % of the hero's own width, so it stays fluid at any
   viewport; vertical placement (top/height) uses the frame's fixed px
   values directly. The Figma frame itself clips the cutout image ~181px
   short of its full height (visible in the source as the machine's front
   legs being cut off) — the hero here is taller than that 861px frame
   specifically so the image renders in full instead of clipping.
   The photo gets a scroll-linked parallax offset (see PROJECT HERO
   PARALLAX in scripts.js) so it slides over the wordmark behind it at a
   different rate than the page scrolls, rather than staying locked to it.
   ============================================================ */
.ph-hero {
  position: relative;
  height: 1066px;
  overflow: hidden;
  background: var(--bg);
}

.ph-title {
  position: absolute;
  top: 96px;     /* Figma 110px, shifted up 14px with the rest of the group */
  left: var(--page-pad);  /* flush with the section-text column below */
  width: calc(100% - var(--page-pad));
  z-index: 1;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(56px, var(--ph-title-size, 11.2vw), 160px);
  line-height: 0.914;
  letter-spacing: 2px;
  color: var(--white);
  text-transform: uppercase;
  white-space: nowrap;
}

.ph-body {
  position: absolute;
  top: 306px;    /* Figma 320px, shifted up 14px with the rest of the group */
  left: var(--page-pad);  /* flush with the section-text column below */
  width: 33%;
  min-width: 300px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 32px;
}

.ph-text p {
  font-size: 16px;
  line-height: 26px;
  letter-spacing: 0.16px;
  color: rgba(255, 255, 255, 0.85);
}

.ph-image {
  position: absolute;
  top: 187px;   /* Figma 181px; nudged from 167px to sit lower */
  left: 36%;     /* nudged right from 29% */
  width: 49.2%;  /* 708px / 1440px */
  height: 861px; /* fixed px — the hero is taller than the original 861px
                    frame specifically so this doesn't get clipped */
  z-index: 4;    /* above the title and body copy */
  /* the cutout overlaps the body copy/CTA, and its transparent areas would
     otherwise swallow clicks on the button underneath */
  pointer-events: none;
}

.ph-image img {
  display: block;
  height: 100%;
  width: auto;
  max-width: none;
  margin: 0 auto;
  transform: translateY(var(--ph-parallax-y, 0px));
  will-change: transform;
  /* bottom 30% fades into the black page — a mask rather than a black
     overlay, so the wordmark behind the cutout's transparent areas stays
     untouched */
  -webkit-mask-image: linear-gradient(to top, transparent 0%, #000 30%);
  mask-image: linear-gradient(to top, transparent 0%, #000 30%);
}

/* opt out of the fade per page (VPIN Modern) */
.ph-hero--no-fade .ph-image img {
  -webkit-mask-image: none;
  mask-image: none;
}

/* On-load reveal — same slide-up + fade as the homepage hero
   (.hero-text), staggered across the hero's four elements. The rise is
   applied to .ph-image (the container) rather than its <img>, since the
   image's own transform is already driven by the parallax handler. */
.ph-title,
.ph-image,
.ph-body .btn-primary {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.8s ease, transform 0.8s ease;
}

.ph-title.is-visible,
.ph-image.is-visible,
.ph-body .btn-primary.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.ph-title { transition-delay: 0.1s; }
.ph-image { transition-delay: 0.4s; }
.ph-text  { transition-delay: 0.7s; }
.ph-body .btn-primary { transition-delay: 1s; }

/* ============================================================
   CASE STUDY — VPIN Noire project page
   One-off narrative build-out (see WORKLOG.md). All section text
   blocks reuse .section-text for the shared scroll-reveal treatment.
   ============================================================ */

/* Cinematic intro — scroll-driven word-by-word fill */
.cs-intro {
  display: flex;
  flex-direction: column;
  gap: 48px;
  padding: 0 var(--page-pad) calc(var(--section-py) * 1.5);
}

.intro-copy {
  max-width: 1100px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(24px, 3.2vw, 44px);
  line-height: 1.35;
  letter-spacing: 0.2px;
}

/* Each word is wrapped in its own span by scripts.js, then lit one at a
   time as the section scrolls through the viewport. */
.intro-copy .intro-word {
  color: rgba(255, 255, 255, 0.2);
  transition: color 0.4s ease;
}

.intro-copy .intro-word.is-lit {
  color: var(--white);
}

.intro-images {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}

.intro-images img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 8px;
}

/* single image in place of the pair — spans the content grid, uncropped */
.intro-image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 8px;
}

/* ============================================================
   DESIGN SECTION
   Figma: https://www.figma.com/design/KWppWGIEe8PSNTO8ao7Zpu/R2C?node-id=77-380
   1440x1091 frame: centred heading at y132, copy 668px wide, and the
   mockup (1180x885) at y217 — wide enough that it overlaps the copy,
   which is the point: it parallaxes up over the text on scroll.
   ============================================================ */
.ds {
  position: relative;
  height: 1091px;
  overflow: hidden;
  background: var(--bg);
}

.ds-text {
  position: absolute;
  top: 132px;
  left: 50%;
  /* keeps the .section-text scroll-reveal offset while staying centred */
  transform: translateX(-50%) translateY(28px);
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 30px;
  width: 100%;
  max-width: 1200px;
  padding: 0 var(--page-pad);
  text-align: center;
}

.ds-text.is-visible {
  transform: translateX(-50%) translateY(0);
}

.ds-text p {
  max-width: 668px;
  font-size: 16px;
  line-height: 26px;
  letter-spacing: 0.16px;
  color: rgba(255, 255, 255, 0.6);
}

.ds-image {
  position: absolute;
  top: 217px;
  left: 50%;
  z-index: 2;
  width: 1180px;
  max-width: 100%;
  height: 885px;
  transform: translateX(-50%) translateY(var(--ds-parallax-y, 0px));
  will-change: transform;
}

.ds-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* fits the whole image inside the rising container instead of cropping it */
.ds--contain .ds-image img {
  object-fit: contain;
}

/* wider rising image box for pages whose design photo needs more width */
.ds--wide .ds-image {
  width: 1272px;
}

/* at 1272px wide the 16:9 photo letterboxes inside the 885px box, leaving
   ~75px of empty black under it — trim the section so Manufacturing
   follows closer */
@media (min-width: 1025px) {
  .ds.ds--wide { height: 1020px; }
}

/* image fades into the page at its base, per the design */
.ds-image::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent 84%, var(--bg) 100%);
}

/* edge-to-edge single photo, used as a placeholder section on case-study
   pages until real content fills that slot */
.cs-full-photo img {
  display: block;
  width: 100%;
  max-height: 900px;
  object-fit: cover;
}

/* ============================================================
   PRODUCT VIEWER
   Apple product-page pattern — a vertical pill stack where one item is
   expanded at a time to reveal its copy, stepped by clicking a pill or
   with the up/down arrows, alongside a stage image that crossfades to
   match the active pill.
   ============================================================ */
.pv {
  display: flex;
  flex-direction: column;
  gap: 48px;
  padding: var(--section-py) var(--page-pad);
  /* sits behind the pure-black .pv-inner card, so the grey only shows
     around its edges */
  background: linear-gradient(to bottom, var(--bg), #101010);
}

/* extra breathing room around "THE PROCESS" section on the About page */
#in-house {
  padding-top: calc(var(--section-py) * 1.5);
  padding-bottom: calc(var(--section-py) * 1.5);
}

.pv-inner {
  display: grid;
  grid-template-columns: 4fr 8fr; /* 4/12 controls, 8/12 stage */
  grid-template-rows: auto 1fr;
  gap: 80px 40px;
  align-items: start;
  padding: 40px;
  border-radius: 24px;
  background: var(--bg);
}

/* header sits above the controls in the left column; the stage spans
   both rows alongside it */
.pv-header {
  grid-column: 1;
  grid-row: 1;
}

/* the accordion viewer's header is a small in-card label; the alt's is a
   full section heading, so it keeps the standard h2 sizing */
.pv:not(.pv-alt) .pv-header h2 {
  font-size: 28px;
  line-height: normal;
  letter-spacing: 0.56px;
}

.pv-alt .pv-header {
  gap: 24px;
  align-items: center;
  text-align: center;
}

.pv-alt .pv-header p {
  max-width: 620px;
  font-size: 16px;
  line-height: 26px;
  letter-spacing: 0.16px;
  color: rgba(255, 255, 255, 0.6);
}

.pv-controls {
  grid-column: 1;
  grid-row: 2;
  display: flex;
  align-items: flex-start;
  gap: 20px;
}

.pv-arrows {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex-shrink: 0;
  padding-top: 6px;
}

.pv-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
  color: var(--white);
  cursor: pointer;
  transition: background 0.2s ease;
}

.pv-arrow:hover {
  background: rgba(255, 255, 255, 0.18);
}

.pv-list {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  min-width: 0;
  flex: 1;
}

.pv-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 100%;
}

.pv-pill {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  max-height: 56px;
  padding: 14px 24px 14px 16px;
  border-radius: 60px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--white);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 16px;
  letter-spacing: 0.2px;
  text-align: left;
  overflow: hidden;
  cursor: pointer;
  transition: background 0.2s ease, max-height 0.3s ease,
              padding 0.3s ease, opacity 0.2s ease;
}

/* The active item's pill collapses away so only its description shows —
   the panel copy leads with the feature name, so the pill would just be
   repeating it. */
.pv-item.is-active .pv-pill {
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  opacity: 0;
  pointer-events: none;
}

.pv-pill:hover {
  background: rgba(255, 255, 255, 0.14);
}

/* "+" glyph, drawn with two bars inside a ring — becomes a solid
   terracotta dot once its pill is the active one */
.pv-icon {
  position: relative;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, 0.6);
  transition: background 0.25s ease, border-color 0.25s ease;
}

.pv-icon::before,
.pv-icon::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--white);
  transform: translate(-50%, -50%);
  transition: opacity 0.25s ease;
}

.pv-icon::before { width: 10px; height: 1.5px; }
.pv-icon::after  { width: 1.5px; height: 10px; }

.pv-item.is-active .pv-icon {
  background: var(--terracotta);
  border-color: var(--terracotta);
}

.pv-item.is-active .pv-icon::before,
.pv-item.is-active .pv-icon::after {
  opacity: 0;
}

.pv-panel {
  position: relative;
  width: 100%;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.35s ease, opacity 0.35s ease;
  opacity: 0;
}

.pv-item.is-active .pv-panel {
  opacity: 1;
}

/* Close button, pinned to the top-right of the expanded panel — the panel
   copy is inset on that side so the two never collide. */
.pv-close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 0.7);
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease;
}

.pv-close:hover {
  background: rgba(255, 255, 255, 0.2);
  color: var(--white);
}

.pv-panel p {
  position: relative;
  padding: 20px 52px 20px 24px;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.06);
  font-size: 15px;
  line-height: 24px;
  color: rgba(255, 255, 255, 0.7);
  max-width: 460px;
}

.pv-panel strong {
  font-weight: 600;
  color: var(--white);
}

.pv-stage {
  grid-column: 2;
  grid-row: 1 / span 2;
  position: relative;
  height: 560px;
  border-radius: 16px;
  overflow: hidden;
}

.pv-stage img,
.pv-stage video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.02);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

/* Ken Burns — the slide on stage drifts and slowly pushes in. The
   animation owns `transform` while active, so it replaces the base
   rule's scale-in settle rather than fighting it; re-adding .is-active
   on a pill change restarts it from the top. */
.pv-stage img.is-active,
.pv-stage video.is-active {
  opacity: 1;
  animation: pv-ken-burns 12s ease-out forwards;
}

/* pan + a slow pull back; the scale never drops to 1 so the drift can't
   expose an edge of the frame */
@keyframes pv-ken-burns {
  from { transform: scale(1.2) translate(-3%, -2%); }
  to   { transform: scale(1.06) translate(3%, 2%); }
}

@media (prefers-reduced-motion: reduce) {
  .pv-stage img.is-active,
  .pv-stage video.is-active {
    animation: none;
    transform: scale(1);
  }
}

/* the cover shot is composed to sit whole in the frame — everything else
   fills the stage */
.pv-stage .pv-cover {
  object-fit: contain;
}

/* ------------------------------------------------------------
   Product viewer — ALT layout
   Media sits alone in an unstyled container with a caption box floating
   over it; the pills sit in a row below the container as selectors
   rather than expanding accordions.
   ------------------------------------------------------------ */
.pv-alt {
  background: var(--bg);
  /* spacing is set per-child below rather than by a uniform flex gap,
     so the pills can sit closer to the media than the header does */
  gap: 0;
}

/* the whole section runs at 10/12, centred — header, media, and pills all
   share the same measure so they stay aligned */
.pv-alt .pv-header,
.pv-alt .pv-inner,
.pv-alt .pv-controls {
  width: 83.3333%;
  margin-left: auto;
  margin-right: auto;
}

.pv-alt .pv-inner {
  display: block;
  position: relative;
  margin-top: 48px;
  padding: 0;
  background: none;
  border-radius: 0;
}

.pv-alt .pv-stage {
  width: 100%;
  height: 620px;
  border-radius: 16px;
}

/* caption box floats over the lower-left of the media */
.pv-captions {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 16px;
  z-index: 2;
  pointer-events: none;
}

.pv-caption {
  position: relative;
  max-width: 520px;
  padding: 22px 52px 22px 26px;
  border-radius: 20px;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity 0.35s ease, transform 0.35s ease, visibility 0.35s;
  pointer-events: auto;
}

/* all captions stack in the same spot; only the active one shows */
.pv-caption + .pv-caption {
  position: absolute;
  left: 0;
  bottom: 0;
}

.pv-caption.is-active {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.pv-caption p {
  font-size: 15px;
  line-height: 24px;
  color: var(--white);
}

.pv-caption strong {
  font-weight: 600;
  color: var(--white);
}

/* pills sit below the container, in a row */
.pv-alt .pv-controls {
  grid-column: auto;
  grid-row: auto;
  margin-top: 32px;
  align-items: center;
  justify-content: center;
}

.pv-alt .pv-arrows {
  display: none;
}

/* phone-only next/previous tab carets (styled in the 768px block) */
.pv-scroll-caret {
  display: none;
}

/* the list itself is the chrome — a single glassy bar holding the pills,
   with the active one sitting inside it as a white thumb */
.pv-alt .pv-list {
  flex: 0 0 auto;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  padding: 5px 8px;
  border-radius: 60px;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255, 255, 255, 0.12);
}

/* pills are bare inside the bar — border is reserved (transparent) even
   when inactive so the active state's outline only changes color, never
   the box size, avoiding a size "pop" on click */
.pv-alt .pv-pill {
  padding: 10px 28px;
  background: none;
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-weight: 300;
  color: rgba(255, 255, 255, 0.65);
  transition: background 0.2s ease, max-height 0.3s ease,
              padding 0.3s ease, opacity 0.2s ease, border-color 0.2s ease;
}

.pv-alt .pv-item {
  width: auto;
}

/* alt uses a real line icon per stage instead of the shared "+" ring, so
   the ring's border and bars are cleared. Strokes are currentColor, so
   they follow the pill's text — light on the bar, black on the active
   white pill. */
.pv-alt .pv-icon {
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 0;
  background: none;
}

.pv-alt .pv-icon::before,
.pv-alt .pv-icon::after {
  display: none;
}

/* outranks the shared `.pv-item.is-active .pv-icon` accent fill, which
   would otherwise paint a terracotta block behind the line icon */
.pv-alt .pv-item.is-active .pv-icon {
  background: none;
  border-color: transparent;
}

/* the pill is a selector now — it never collapses into a panel */
.pv-alt .pv-item.is-active .pv-pill {
  max-height: 48px;
  padding: 6px 28px;
  opacity: 1;
  pointer-events: auto;
  background: none;
  border-color: var(--terracotta);
  color: var(--terracotta);
  font-weight: 400;
}

.pv-alt .pv-item.is-active .pv-label {
  color: var(--white);
}

/* Shared photo-grid pattern — Design, Materials, Construction, Finishing */
.cs-design,
.cs-materials,
.cs-construction,
.cs-finishing {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: var(--section-py) var(--page-pad);
}

.cs-photo-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.cs-photo-grid--five {
  grid-template-columns: repeat(5, 1fr);
}

.cs-photo-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.cs-photo-card img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 6px;
  background: #111;
}

.cs-photo-card figcaption {
  font-size: 13px;
  line-height: 20px;
  color: rgba(255, 255, 255, 0.5);
}

/* Stat tiles — shared by the CNC callout + Build Statistics */
.cs-stat-row {
  display: flex;
  flex-wrap: wrap;
  gap: 40px;
}

.cs-stats {
  display: flex;
  flex-direction: column;
  gap: 48px;
  padding: 0 var(--page-pad) 110px;
}

/* the stats row spans the full content width, one equal column per stat,
   each stat's number and label centred on each other */
.cs-stats-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 32px;
}

.cs-stat-tile {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.cs-stats-grid .cs-stat-tile {
  position: relative;
  align-items: center;
  text-align: center;
}

/* hairline rule between stats — sits in the gap, skipped on the first
   tile of each row so no divider hangs off the left edge */
.cs-stats-grid .cs-stat-tile::before {
  content: '';
  position: absolute;
  top: 50%;
  left: -16px;
  transform: translateY(-50%);
  width: 1px;
  height: 56px;
  background: rgba(255, 255, 255, 0.15);
}

.cs-stats-grid .cs-stat-tile:first-child::before {
  display: none;
}

/* Proxima Nova rather than Halyard here — the kit only carries Halyard
   in 400/700, so a true light weight isn't available on the display face. */
.cs-stat-number {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 56px;
  line-height: 1;
  letter-spacing: 0.5px;
  color: var(--terracotta);
}

.cs-stat-label {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 15px;
  line-height: 24px;
  letter-spacing: 0.15px;
  color: rgba(255, 255, 255, 0.6);
}

/* Before / after slider — Custom Artwork */
.cs-artwork {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: var(--section-py) var(--page-pad);
}

.cs-ba-slider {
  width: 100%;
}

.cs-ba-frame {
  position: relative;
  width: 100%;
  height: 560px;
  border-radius: 8px;
  overflow: hidden;
  user-select: none;
}

.cs-ba-before,
.cs-ba-after {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.cs-ba-after-wrap {
  position: absolute;
  inset: 0;
  width: 50%;
  overflow: hidden;
}

.cs-ba-after-wrap .cs-ba-after {
  width: 200%;
  max-width: none;
}

.cs-ba-label {
  position: absolute;
  bottom: 24px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--white);
  background: rgba(0, 0, 0, 0.5);
  padding: 8px 14px;
  border-radius: 60px;
  pointer-events: none;
}

.cs-ba-label--before { left: 24px; }
.cs-ba-label--after { right: 24px; }

.cs-ba-handle {
  position: absolute;
  top: 0;
  left: 50%;
  width: 2px;
  height: 100%;
  background: var(--white);
  transform: translateX(-50%);
  cursor: ew-resize;
}

.cs-ba-handle-grip {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--terracotta);
  border: 3px solid var(--white);
}

.cs-ba-handle-grip::before,
.cs-ba-handle-grip::after {
  content: '';
  position: absolute;
  top: 50%;
  width: 0;
  height: 0;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
}

.cs-ba-handle-grip::before {
  left: 10px;
  border-right: 6px solid var(--white);
  transform: translateY(-50%);
}

.cs-ba-handle-grip::after {
  right: 10px;
  border-left: 6px solid var(--white);
  transform: translateY(-50%);
}

/* Final reveal */
.cs-reveal {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: var(--section-py) var(--page-pad);
}

.cs-reveal-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 260px;
  gap: 16px;
}

.cs-reveal-grid img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 6px;
}

.cs-reveal-lg {
  grid-column: span 2;
  grid-row: span 2;
}

/* Interactive features */
.cs-features {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: var(--section-py) var(--page-pad);
}

.cs-feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px 40px;
}

.cs-feature-grid li {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0.4px;
}

.cs-feature-icon {
  flex-shrink: 0;
  color: var(--terracotta);
}

/* Behind the details */
.cs-details {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: var(--section-py) var(--page-pad);
}

.cs-details-list {
  gap: 80px;
}

/* Client testimonial */
.cs-testimonial {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: var(--section-py) var(--page-pad) calc(var(--section-py) * 1.5);
}

/* matches the intro statement's treatment — large display type at a
   generous measure, left-aligned, rather than a centred pull-quote */
.cs-quote {
  position: relative;
  max-width: 1100px;
}

/* type comes from .intro-copy, which also drives the word-by-word fill */
.cs-quote p {
  margin-bottom: 32px;
}

.cs-quote-mark {
  display: block;
  font-family: var(--font-display);
  font-size: 96px;
  line-height: 1;
  color: var(--terracotta);
  margin-bottom: 8px;
}

.cs-quote cite {
  display: block;
  font-family: var(--font-body);
  font-style: normal;
  font-weight: 300;
  font-size: 15px;
  line-height: 24px;
  letter-spacing: 0.15px;
  color: var(--terracotta);
}

/* Process timeline */
.cs-timeline {
  display: flex;
  flex-direction: column;
  gap: 48px;
  padding: var(--section-py) var(--page-pad);
}

.cs-timeline-list {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding-left: 32px;
}

.cs-timeline-list::before {
  content: '';
  position: absolute;
  top: 6px;
  bottom: 6px;
  left: 5px;
  width: 1px;
  background: rgba(255, 255, 255, 0.15);
}

.cs-timeline-list li {
  position: relative;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 20px;
  letter-spacing: 0.3px;
}

.cs-timeline-list li::before {
  content: '';
  position: absolute;
  top: 6px;
  left: -32px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--terracotta);
}

/* Build gallery masonry */
.cs-gallery {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: var(--section-py) var(--page-pad);
}

.cs-masonry {
  columns: 4;
  column-gap: 16px;
}

.cs-masonry-item {
  display: block;
  width: 100%;
  margin-bottom: 16px;
  break-inside: avoid;
  border-radius: 6px;
  overflow: hidden;
  border: none;
  padding: 0;
  cursor: pointer;
  background: #111;
}

.cs-masonry-item:nth-child(3n) img { aspect-ratio: 1 / 1; }
.cs-masonry-item:nth-child(3n+1) img { aspect-ratio: 3 / 4; }
.cs-masonry-item:nth-child(3n+2) img { aspect-ratio: 4 / 3; }

.cs-masonry-item img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.35s ease;
}

.cs-masonry-item:hover img {
  transform: scale(1.06);
}

/* Specs table — grouped rows in two columns, accent group headings and
   dashed rules between rows */
.cs-specs {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: var(--section-py) var(--page-pad);
}

/* same small left-aligned label as the Build Gallery heading */
.cs-specs-header h2 {
  font-size: 24px;
  line-height: normal;
  letter-spacing: 0.48px;
}

.cs-specs-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0 72px;
}

.cs-spec-table {
  width: 100%;
  border-collapse: collapse;
}

.cs-spec-table th,
.cs-spec-table td {
  padding: 13px 0;
  text-align: left;
  vertical-align: top;
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 15px;
  line-height: 22px;
}

/* label column is fixed so values line up down the table */
.cs-spec-table th {
  width: 38%;
  padding-right: 24px;
  color: rgba(255, 255, 255, 0.9);
}

.cs-spec-table td {
  color: rgba(255, 255, 255, 0.5);
}

.cs-spec-table tr {
  border-bottom: 1px dashed rgba(255, 255, 255, 0.16);
}

.cs-spec-group th {
  width: auto;
  padding: 32px 0 12px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--terracotta);
}

.cs-spec-group {
  border-bottom-style: solid;
  border-bottom-color: rgba(255, 255, 255, 0.16);
}

/* the first group in a column shouldn't push itself down */
.cs-spec-col > .cs-spec-table:first-child .cs-spec-group th {
  padding-top: 0;
}

/* FAQ accordion — styled to match the specs table: small left-aligned
   heading, full-width rows, dashed rules, light 15px text */
.cs-faq {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: var(--section-py) var(--page-pad);
}

.cs-faq-header h2 {
  font-size: 24px;
  line-height: normal;
  letter-spacing: 0.48px;
}

.cs-faq-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0 72px;
  align-items: start;
}

/* each column stacks independently so opening one answer doesn't push
   down the item beside it */
.cs-faq-col {
  display: flex;
  flex-direction: column;
}

.cs-faq-item {
  border-bottom: 1px dashed rgba(255, 255, 255, 0.16);
}

.cs-faq-question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 13px 0;
  text-align: left;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 15px;
  line-height: 22px;
  color: rgba(255, 255, 255, 0.9);
}

.cs-faq-toggle {
  position: relative;
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  margin-left: 24px;
}

.cs-faq-toggle::before,
.cs-faq-toggle::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--terracotta);
  transform: translate(-50%, -50%);
  transition: transform 0.25s ease;
}

.cs-faq-toggle::before { width: 16px; height: 2px; }
.cs-faq-toggle::after { width: 2px; height: 16px; }

.cs-faq-item.is-open .cs-faq-toggle::after {
  transform: translate(-50%, -50%) rotate(90deg);
  opacity: 0;
}

.cs-faq-answer {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}

.cs-faq-answer p {
  padding-bottom: 13px;
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 15px;
  line-height: 22px;
  color: rgba(255, 255, 255, 0.5);
  max-width: 640px;
}

/* Related projects */
.cs-related {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: var(--section-py) var(--page-pad) calc(var(--section-py) * 1.5);
}

.cs-related-grid {
  grid-template-columns: repeat(3, 1fr);
}

/* ============================================================
   CONTACT FORM
   ============================================================ */
.contact {
  display: flex;
  flex-direction: column;
  gap: 60px;
  padding: 120px var(--page-pad) 60px;
}

.contact-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
  text-align: center;
}

.contact-header h2 {
  font-size: 58px;
  line-height: 54px;
  letter-spacing: 1.16px;
}

.contact-header p {
  max-width: 750px;
  font-size: 16px;
  line-height: 26px;
  letter-spacing: 0.16px;
  color: rgba(255, 255, 255, 0.6);
}

.contact-form {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.form-row {
  display: flex;
  gap: 24px;
}

.form-field { flex: 1; }

.form-field input,
.form-field textarea {
  width: 100%;
  background: var(--field-gradient);
  border: var(--field-border);
  border-radius: 6px;
  color: var(--white);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 14px;
  line-height: 24px;
  padding: 20px 24px;
  outline: none;
  transition: border-color 0.2s ease;
  -webkit-appearance: none;
  appearance: none;
}

.form-field input::placeholder,
.form-field textarea::placeholder {
  color: rgba(255, 255, 255, 0.4);
}

.form-field input:focus,
.form-field textarea:focus {
  border-color: var(--terracotta);
}

.form-field--textarea { width: 100%; }

.form-field--textarea textarea {
  height: 232px;
  resize: vertical;
}

.form-honeypot {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.form-actions {
  display: flex;
  justify-content: center;
}

/* send-message button rests in the colour the hover pixel-grid effect fills
   with (see ButtonPixelGridEffect in scripts.js) */
.submit-btn { background: rgb(220, 120, 80); }
.submit-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.form-success {
  padding: 40px 0;
  text-align: center;
  font-family: var(--font-display);
  font-size: 18px;
  letter-spacing: 0.5px;
  color: var(--terracotta);
}

/* ============================================================
   FOOTER
   ============================================================ */
.site-footer {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 48px var(--page-pad);
}

.footer-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 32px;
}

.footer-info {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.footer-name {
  font-size: 13px;
  line-height: 22px;
  letter-spacing: 0.13px;
  /* 0.5 (not the site's usual 0.4) to clear the 4.5:1 contrast minimum
     against the black footer background */
  color: rgba(255, 255, 255, 0.5);
}

.footer-address {
  font-style: normal;
  font-size: 13px;
  line-height: 22px;
  letter-spacing: 0.13px;
  color: rgba(255, 255, 255, 0.5);
  text-align: left;
}

/* button reveals the number only once clicked — see FOOTER PHONE REVEAL in
   scripts.js — so basic scrapers that don't run JS never see the digits */
.footer-phone-btn {
  align-self: flex-start;
  font-family: inherit;
  font-size: 13px;
  line-height: 22px;
  letter-spacing: 0.13px;
  color: rgba(255, 255, 255, 0.5);
  text-decoration: underline;
  text-underline-offset: 2px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  transition: color 0.2s ease;
}

.footer-phone-btn:hover {
  color: var(--terracotta);
}

.footer-phone-link {
  font-size: 13px;
  line-height: 22px;
  letter-spacing: 0.13px;
  color: rgba(255, 255, 255, 0.5);
  transition: color 0.2s ease;
}

.footer-phone-link:hover {
  color: var(--terracotta);
}

.footer-social {
  display: flex;
  align-items: center;
  gap: 20px;
}

.footer-social-link {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--white);
  opacity: 0.7;
  transition: opacity 0.2s ease, color 0.2s ease;
}

.footer-social-link:hover {
  opacity: 1;
  color: var(--terracotta);
}

/* ============================================================
   GSAP CARD CAROUSEL — adapted from codepen.io/GreenSock/pen/RwKwLWK
   Cards flow through the center (scale/opacity pop in-and-out),
   which naturally reads as one big prominent center card with
   smaller faded cards passing on either side. Driven only by the
   Prev/Next buttons and dragging (no scroll-jacking).
   ============================================================ */
.gsap-showcase * {
  box-sizing: border-box;
}
.gsap-showcase {
  display: none;
  background: #111;
  position: relative;
  height: 760px;
  padding: 0;
  margin: 0;
}
.gsap-showcase .gallery {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.gsap-showcase .cards {
  position: absolute;
  width: 26.4rem;
  height: 33.6rem;
  top: 45%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.gsap-showcase .cards li {
  list-style: none;
  padding: 0;
  margin: 0;
  width: 26.4rem;
  aspect-ratio: 9/16;
  position: absolute;
  background-size: contain;
  background-repeat: no-repeat;
  top: 0;
  left: 0;
  border-radius: 16px;
}

.gsap-showcase .actions {
  position: absolute;
  bottom: 32px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
}

.gsap-showcase .actions button {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.8px;
  color: var(--white);
  padding: 12px 20px;
  transition: color 0.2s ease;
}

.gsap-showcase .actions button:hover { color: var(--terracotta); }

.gsap-showcase .drag-proxy {
  visibility: hidden;
  position: absolute;
}

.btn-particle-canvas {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  border-radius: 60px;
  display: none;
}

.btn-particle-canvas.active {
  display: block;
}

/* Hide solid wipe when particle effect is active */
.btn-primary:has(.btn-particle-canvas.active)::before {
  display: none;
}

.btn-particle-canvas {
  z-index: -1;
}

/* ============================================================
   ABOUT PAGE
   ============================================================ */
.about-shop {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: var(--section-py) var(--page-pad);
}

.about-shop-photos {
  display: flex;
  gap: 16px;
}

.about-shop-photos img {
  flex: 1;
  width: 100%;
  height: 480px;
  object-fit: cover;
  min-width: 0;
}

.about-shop-address {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 15px;
  letter-spacing: 0.3px;
  color: rgba(255, 255, 255, 0.6);
}

.about-audience {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 100px var(--page-pad);
  background: var(--bg);
}

.about-audience-grid {
  display: flex;
  height: 360px;
}

.about-audience-card {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  padding: 0 44px;
  overflow: hidden;
  border: 1px solid #3e3e3e;
  transition: border-color 0.3s ease, padding 0.35s ease;
}

.about-audience-card:first-child {
  border-radius: 8px 0 0 8px;
  border-right-width: 0;
}

.about-audience-card:last-child {
  border-radius: 0 8px 8px 0;
}

/* title sits flush against the bottom by default, like the showroom
   gallery tiles; hover opens up room below it for the description and
   shows the orange outline, matching the gallery tiles' hover state */
.about-audience-card:hover {
  border-color: #d65e38;
  border-width: 2px;
  padding: 0 44px 40px;
}

.about-audience-card img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  transform: scale(1);
  filter: blur(0);
  transition: transform 0.35s ease, filter 0.35s ease;
}

/* same hover zoom + blur as the "WHAT SETS US APART" cards above */
.about-audience-card:hover img {
  transform: scale(1.12);
  filter: blur(12px);
}

.about-audience-card::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 41%, #000 100%);
  transition: background 0.35s ease;
}

.about-audience-card:hover::after {
  background: rgba(0, 0, 0, 0.7);
}

.about-audience-text {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 0;
  width: 100%;
  transition: gap 0.35s ease;
}

/* opens the gap above the description only once it's revealed on hover,
   so the collapsed wrapper doesn't push the title up while hidden */
.about-audience-card:hover .about-audience-text {
  gap: 24px;
}

.about-audience-text h3 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 42px;
  line-height: 36px;
  letter-spacing: 0.84px;
  color: var(--white);
  transform: translateY(4px);
}

.about-audience-desc-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.35s ease;
}

.about-audience-desc-wrap p {
  overflow: hidden;
  font-size: 16px;
  line-height: 26px;
  color: var(--white);
  opacity: 0;
  transition: opacity 0.25s ease;
}

.about-audience-card:hover .about-audience-desc-wrap {
  grid-template-rows: 1fr;
}

.about-audience-card:hover .about-audience-desc-wrap p {
  opacity: 1;
  transition: opacity 0.3s ease 0.1s;
}

/* ============================================================
   MATERIALS FAN
   Cards sit stacked/overlapping at center by default; --fan-progress
   (set on .materials-fan-stage by MATERIALS FAN in scripts.js as the
   section scrolls through the viewport) drives each card's spread and
   rotation apart from 0 (fanned) to 1 (fully spread, flat).
   ============================================================ */
.materials-fan {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 88px;
  padding: var(--section-py) var(--page-pad);
  background: var(--bg);
  overflow: hidden;
}

.materials-fan-text {
  align-items: center;
  max-width: 800px;
  text-align: center;
}

.materials-fan-text h2 {
  white-space: nowrap;
}

.materials-fan-stage {
  --fan-progress: 0;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 420px;
}

.material-card {
  position: absolute;
  width: 160px;
  aspect-ratio: 299 / 931;
  border-radius: 12px;
  overflow: hidden;
  /* spread offsets are viewport-relative (capped at the desktop px
     values), so the outer cards stay on-screen at any width instead of
     spreading past the edge of narrow viewports */
  transform: translateX(calc((var(--i) - 2) * (min(28px, 3vw) + var(--fan-progress) * (min(220px, 13.5vw) - min(28px, 3vw)))));
}

.material-card img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 768px) {
  .materials-fan-stage { height: 320px; }
  .material-card { width: 120px; }
  /* the heading is only forced onto one line where there's room for it —
     at mobile font sizes "BUILT FROM THE BEST" doesn't fit and would
     otherwise get clipped on both sides */
  .materials-fan-text h2 { white-space: normal; }
}

.about-apart {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 60px 100px;
  background: var(--bg);
}

.about-apart-grid {
  display: flex;
  height: 400px;
}

.about-apart-card {
  position: relative;
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0%;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  padding: 24px;
  overflow: hidden;
  border-top: 1px solid #3e3e3e;
  border-bottom: 1px solid #3e3e3e;
  border-left: 1px solid #3e3e3e;
  transition: flex-grow 0.4s ease;
}

/* Accordion effect — hovered card grows 20% wider (flex-grow 1.2 of 4),
   the other three shrink evenly to absorb the difference (0.9333 each).
   Row layout only exists above the 768px mobile breakpoint, where cards
   stack vertically at a fixed height instead — scoped so flex-grow never
   fights that fixed height. */
@media (min-width: 769px) {
  .about-apart-grid:has(.about-apart-card:hover) .about-apart-card:not(:hover) {
    flex-grow: 0.9333;
  }

  .about-apart-grid .about-apart-card:hover {
    flex-grow: 1.2;
  }
}

.about-apart-card:first-child {
  border-top-left-radius: 8px;
  border-bottom-left-radius: 8px;
}

.about-apart-card:last-child {
  border-right: 1px solid #3e3e3e;
  border-top-right-radius: 8px;
  border-bottom-right-radius: 8px;
}

.about-apart-card img {
  position: absolute;
  max-width: none;
  object-fit: cover;
  z-index: 0;
  filter: blur(0);
  transition: filter 0.35s ease;
}

.about-apart-card:hover img {
  filter: blur(12px);
}

/* Per-card crop/zoom/offset, matching the exact image transforms from the
   Figma source (each photo is framed differently, not a uniform center-crop) */
.about-apart-grid .about-apart-card:nth-child(1) img {
  width: 151.79%;
  height: 87.38%;
  top: -20.69%;
  left: -27.51%;
}

.about-apart-grid .about-apart-card:nth-child(2) img {
  width: 126.61%;
  height: 64.7%;
  top: 0.16%;
  left: -8.71%;
  transform: scaleX(-1);
}

.about-apart-grid .about-apart-card:nth-child(3) img {
  width: 152.98%;
  height: 78.28%;
  top: 0;
  left: -46.91%;
}

.about-apart-grid .about-apart-card:nth-child(4) img {
  width: 128.19%;
  height: 65.6%;
  top: -0.02%;
  left: -8.32%;
}

.about-apart-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 42%, #000 87%);
  z-index: 1;
}

.about-apart-text {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
}

.about-apart-headline {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 16px;
  line-height: normal;
  letter-spacing: 0.32px;
  text-transform: uppercase;
  color: var(--white);
}

.about-apart-desc-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.35s ease;
}

.about-apart-desc-wrap p {
  overflow: hidden;
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 0.14px;
  color: rgba(255, 255, 255, 0.75);
  opacity: 0;
  transition: opacity 0.25s ease;
}

.about-apart-card:hover .about-apart-desc-wrap {
  grid-template-rows: 1fr;
}

.about-apart-card:hover .about-apart-desc-wrap p {
  opacity: 1;
  transition: opacity 0.3s ease 0.1s;
}

/* About hero — ORIGIN STORY, text left, cabinet image right */
.hero--about {
  min-height: 780px;
}

.hero--about h1 {
  font-size: clamp(56px, 8vw, 115px);
  line-height: 0.913;
}

/* About — closing "latest work" band: image left, copy and CTA right */
.about-latest {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 60px;
  padding: var(--section-py) var(--page-pad);
  background: var(--bg);
}

.about-latest-image {
  flex: 1;
  display: flex;
  justify-content: center;
  min-width: 0;
}

.about-latest-image img {
  display: block;
  width: 100%;
  max-width: 416px;
  height: auto;
  -webkit-mask-image: linear-gradient(to bottom, #000 89%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 89%, transparent 100%);
}

.about-latest-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 70px;
  min-width: 0;
}

.about-latest-text {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.about-latest-text h2 {
  font-size: clamp(36px, 4vw, 58px);
  line-height: 0.93;
  letter-spacing: 1.16px;
}

.about-latest-text p {
  max-width: 503px;
  font-size: 16px;
  line-height: 26px;
  letter-spacing: 0.16px;
  color: rgba(255, 255, 255, 0.6);
}

.about-cta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 32px;
  padding: var(--section-py) var(--page-pad);
  text-align: left;
}

.about-cta p {
  max-width: 540px;
  color: rgba(255, 255, 255, 0.7);
}

/* ============================================================
   RESPONSIVE
   ============================================================ */

/* --- Tablet --- */
@media (max-width: 1024px) {
  :root {
    --page-pad: 60px;
    --section-py: 60px;
  }

  .hero { min-height: 640px; }
  .hero--compact { min-height: 440px; }
  .hero h1 { font-size: 72px; line-height: 68px; }
  .word-cycle,
  .word-cycle-display { height: 68px; }

  h2 { font-size: 56px; line-height: 54px; }

  .split-image { min-height: 480px; }

  .carousel-container { height: 480px; }
  .carousel-track { width: 480px; }

  .nav-menu li a { font-size: 44px; }

  .services-list { flex-direction: column; gap: 10px; }
  .services-list li { white-space: normal; }

  .project-card { height: 200px; padding: 0 32px; }
  .project-card:hover { padding: 16px 32px 26px; }
  .project-card-name { font-size: 34px; line-height: 32px; }

  .project-hero { height: 400px; }

  .gallery-row--top { height: 420px; }

  .gallery-modal-image { height: 460px; }

  /* Product sticky bar */
  .product-bar { width: calc(100% - 2 * var(--page-pad)); }

  /* Build statistics */
  .cs-stats-grid { gap: 24px; }
  .cs-stat-number { font-size: 46px; }

  /* Design */
  .ds { height: 820px; }
  .ds-text { top: 90px; gap: 20px; }
  .ds-image { top: 170px; width: 100%; height: 660px; }

  /* Product viewer */
  .pv-inner { grid-template-columns: minmax(280px, 1fr) 1fr; gap: 20px 28px; padding: 28px; }
  .pv-stage { height: 440px; }

  /* alt runs full width below desktop — 8/12 gets too narrow to read */
  .pv-alt .pv-header,
  .pv-alt .pv-inner,
  .pv-alt .pv-controls { width: 100%; }
  .pv-alt .pv-stage { height: 460px; }

  /* the pill bar inherits flex-shrink:0 from the shared .pv-list rule
     (needed for its desktop single-row layout), which stops it from ever
     respecting .pv-controls' width here and wrapping onto multiple rows —
     causing page-wide horizontal overflow on narrow screens */
  .pv-alt .pv-list { flex-shrink: 1; max-width: 100%; }

  /* Project hero (VPIN Noire) — same layout, scaled ~0.72x + headroom so
     the image still renders in full at this frame height */
  .ph-hero { height: 790px; }
  .ph-title { top: 70px; }
  .ph-body { top: 220px; min-width: 260px; gap: 24px; }
  .ph-image { top: 140px; height: 620px; }

  /* Case study */
  .cs-photo-grid { grid-template-columns: repeat(2, 1fr); }
  .cs-photo-grid--five { grid-template-columns: repeat(3, 1fr); }
  .cs-reveal-grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 220px; }
  .cs-reveal-lg { grid-column: span 2; grid-row: span 1; }
  .cs-feature-grid { grid-template-columns: repeat(2, 1fr); }
  .cs-ba-frame { height: 420px; }
  .cs-masonry { columns: 3; }
  .cs-related-grid { grid-template-columns: repeat(2, 1fr); }
}

/* --- Mobile --- */
@media (max-width: 768px) {
  :root {
    --page-pad: 24px;
    --section-py: 48px;
    --gap: 16px;
    --navbar-h: 68px;
  }

  /* Nav */
  .nav-inner { padding: 20px var(--page-pad); }
  .navbar.is-scrolled .nav-inner { padding-top: 12px; padding-bottom: 12px; }
  .nav-logo img { height: 20px; }

  .nav-menu {
    align-items: flex-end;
    padding: 100px var(--page-pad) 40px;
    background: rgba(0, 0, 0, 0.6);
  }
  .nav-menu ul {
    gap: 36px;
  }
  .nav-menu li a {
    display: block;
    font-size: 38px;
    letter-spacing: 0.76px;
    text-align: right;
  }
  .nav-menu li a::before { display: none; }
  .nav-badge { font-size: 10px; padding: 3px 10px; top: 8px; }

  /* Buttons */
  .btn-primary {
    width: 100%;
    justify-content: center;
    align-self: stretch;
  }

  /* Hero */
  .hero {
    flex-direction: column;
    min-height: auto;
    gap: 0;
    padding-bottom: 48px;
  }
  .hero-content {
    order: 2;
    padding: 0 var(--page-pad) 0;
    transform: none;
    gap: 32px;
  }
  .hero-image {
    order: 1;
    flex: none;
    height: 450px;
  }
  .hero--compact .hero-image {
    height: 320px;
  }
  .hero h1 { font-size: clamp(32px, 11vw, 44px); line-height: clamp(32px, 11vw, 44px); letter-spacing: 1px; }
  .word-cycle,
  .word-cycle-display { height: clamp(32px, 11vw, 44px); }
  .word-cycle {
    width: 100% !important;
    max-width: 100%;
  }
  .hero-content > p,
  .hero-text p { font-size: 15px; line-height: 24px; max-width: none; }
  /* no parallax on phones (see IMAGE PARALLAX in scripts.js), so no
     overscan either — the box sits flush so the top of the photo shows */
  .hero-image img {
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    transform: none;
    object-position: top;
  }
  .hero-image-fade {
    background: linear-gradient(to top, var(--bg) 0%, transparent 20%);
  }

  /* Split sections (Fully Custom / Customer Build) */
  .split-section { flex-direction: column; }
  .split-image { min-height: 320px; }
  .split-content--right,
  .split-content--left {
    padding: 48px var(--page-pad);
    gap: 40px;
  }
  h2 { font-size: 40px; line-height: 38px; letter-spacing: 0.9px; }
  .services-list { flex-direction: column; gap: 10px; }
  .services-list li { white-space: normal; }
  .image-fade--left {
    background: linear-gradient(to bottom, var(--bg) 0%, transparent 18%);
  }

  /* About page */
  .about-shop-photos { flex-direction: column; }
  .about-shop-photos img { height: 260px; }
  .about-audience { padding: 55px var(--page-pad); } /* 100px less 45% */
  .about-audience-grid { flex-direction: column; height: auto; gap: 12px; }
  .about-audience-card,
  .about-audience-card:first-child,
  .about-audience-card:last-child { flex: none; height: 520px; border-width: 1px; border-radius: 8px; padding: 0 24px 24px; }
  /* the copy is always shown on phones, so keep the title/paragraph gap
     open rather than only on hover */
  .about-audience-text,
  .about-audience-card:hover .about-audience-text { gap: 16px; }
  .about-audience-text h3 { font-size: 28px; line-height: 30px; }
  .about-audience-desc-wrap { grid-template-rows: 1fr; }
  .about-audience-desc-wrap p { opacity: 1; font-size: 14px; line-height: 22px; }
  .about-audience-card::after { background: linear-gradient(to bottom, rgba(0, 0, 0, 0.2) 0%, #000 100%); }
  .hero--about { min-height: 0; }
  .about-latest { flex-direction: column; gap: 32px; }
  .about-latest-content { gap: 32px; }
  .about-apart { padding: 40px var(--page-pad); }
  .about-apart-grid { flex-direction: column; height: auto; gap: 12px; }
  .about-apart-card { flex: 0 0 auto; height: 220px; border-radius: 8px; border-right: 1px solid #3e3e3e; }

  /* Trusted vendors */
  .trusted-vendors { padding: 60px var(--page-pad); gap: 28px; }
  .logo-track {
    display: grid;
    grid-template-columns: 1fr;
    align-items: center;
    justify-items: center;
    width: 100%;
    gap: 0;
  }
  .vendor-logo { height: auto; width: 100%; max-width: 208px; }

  /* Studio carousel */
  .studio { gap: 32px; }
  .carousel-container { height: 340px; }
  .carousel-track { width: 74vw; max-width: 300px; }
  .studio-label { padding: 24px; }
  .studio-label h2 { font-size: 32px; line-height: 30px; }

  /* Showroom page */
  .showroom-gallery { gap: 24px; }

  /* Recent project stories */
  .project-stories-label { font-size: 18px; }
  .project-gallery h2 { font-size: 18px; }
  .project-grid { grid-template-columns: 1fr; gap: 16px; }
  .project-card { height: 180px; padding: 0 24px; }
  .project-card:hover { padding: 16px 24px 24px; }
  .project-card-name { font-size: 28px; line-height: 26px; letter-spacing: 0.5px; }

  /* Project detail pages */
  .project-hero { height: 280px; }
  .project-content { padding: 48px var(--page-pad); gap: 16px; }

  /* Project gallery — collapse the bento mosaic to a single column */
  .project-gallery { gap: 24px; padding: 0 var(--page-pad) 48px; }
  .gallery-grid { gap: 16px; }
  .gallery-row {
    flex-direction: column;
    height: auto;
    gap: 16px;
  }
  .gallery-col { gap: 16px; }
  .gallery-card,
  .gallery-row--split .gallery-card:first-child,
  .gallery-row--split .gallery-card:last-child {
    flex: none;
    height: 220px;
  }

  /* Project gallery modal */
  .gallery-modal { padding: 24px; }
  .gallery-modal-title { top: 16px; left: 16px; font-size: 16px; }
  .gallery-modal-image { height: 300px; }
  .gallery-modal-thumb { width: 52px; height: 52px; }
  .gallery-modal-close { top: 16px; right: 16px; }
  .gallery-modal-close svg { width: 20px; height: 20px; }
  .gallery-modal-arrow svg { width: 28px; height: 20px; }
  .gallery-modal-arrow--prev { left: 12px; }
  .gallery-modal-arrow--next { right: 12px; }

  /* Contact form */
  .contact { padding: 60px var(--page-pad); gap: 40px; }
  .contact-header { gap: 20px; align-items: flex-start; text-align: left; }
  .contact-header h2 { font-size: 36px; line-height: 36px; }
  .contact-header p { font-size: 15px; }
  .contact-form { gap: 16px; }
  .form-row { flex-direction: column; gap: 16px; }
  .form-field input,
  .form-field textarea { padding: 16px 18px; }
  .form-actions { justify-content: center; }

  /* Footer */
  .site-footer { padding: 40px var(--page-pad); gap: 28px; }
  .footer-top { flex-direction: column; align-items: flex-start; gap: 24px; }

  /* Product sticky bar */
  .product-bar { width: calc(100% - 2 * var(--page-pad)); }
  .product-bar-inner { gap: 24px; padding: 14px 20px; }
  .product-bar-tabs { gap: 20px; }

  /* Project hero (VPIN Noire) — drop the layered layout, stack in flow */
  .ph-hero {
    display: flex;
    flex-direction: column;
    height: auto;
    min-height: 0;
    gap: 24px;
    padding: 48px var(--page-pad);
  }
  .ph-title {
    position: static;
    order: 0;
    font-size: clamp(32px, 11vw, 48px);
    line-height: 1;
    letter-spacing: 1px;
    white-space: normal;
  }
  .ph-image {
    position: static;
    order: 1;
    left: auto;
    top: auto;
    width: 100%;
    height: 320px;
    overflow: hidden;
    display: flex;
    justify-content: center;
  }
  .ph-image img { transform: none; }
  .ph-body {
    position: static;
    order: 2;
    transform: none;
    /* drop the desktop 33% / min-width column so the copy and CTA span
       the full content width */
    width: 100%;
    min-width: 0;
    max-width: none;
    gap: 20px;
  }
  .ph-text p { font-size: 15px; line-height: 24px; }

  /* Case study */
  .cs-intro { gap: 32px; }
  .intro-images { grid-template-columns: 1fr; }

  /* Product viewer — stack the stage above the pills, drop the arrows
     (the pills themselves are the control at this size) */
  /* single column — reset the desktop grid placement so the rows flow
     header, stage, controls */
  .pv-inner { grid-template-columns: 1fr; grid-template-rows: none; gap: 24px; padding: 24px; }
  .pv-header { grid-column: auto; grid-row: auto; }
  .pv-controls { grid-column: auto; grid-row: auto; }
  .pv-stage { grid-column: auto; grid-row: auto; height: 320px; }
  .pv-arrows { display: none; }
  .pv-pill { font-size: 15px; padding: 12px 20px 12px 14px; }
  .pv-panel p { max-width: none; }

  /* the manufacturing-viewer tab bar becomes a single scrollable row
     (Apple product-page pattern) instead of wrapping onto multiple —
     the bar itself scrolls horizontally, so the page never does */
  .pv-alt .pv-list {
    flex-wrap: nowrap;
    justify-content: flex-start;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(to right, black calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, black calc(100% - 28px), transparent);
  }
  .pv-alt .pv-list::-webkit-scrollbar { display: none; }
  .pv-alt .pv-pill { flex: 0 0 auto; white-space: nowrap; }

  /* carets over the bar's faded edges — they hint that the tabs scroll
     sideways and, tapped, step to the next/previous tab. Injected by JS
     (see PRODUCT VIEWER in scripts.js), which adds .can-advance while the
     last tab isn't selected and .can-retreat once past the first. They sit
     on the controls wrapper rather than inside the list so the list's
     fade mask and its own scrolling don't affect them. */
  .pv-alt .pv-controls { position: relative; }
  /* offset parent for the active-tab scroll maths in scripts.js */
  .pv-alt .pv-list { position: relative; }
  .pv-alt .pv-scroll-caret {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 50%;
    width: 44px;
    height: 44px;
    transform: translateY(-50%);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease, visibility 0.2s;
  }
  .pv-alt .pv-scroll-caret--next { right: 4px; }
  .pv-alt .pv-scroll-caret--prev { left: 4px; }
  .pv-alt .pv-scroll-caret::before {
    content: '';
    width: 8px;
    height: 8px;
    border-top: 2px solid var(--white);
    border-right: 2px solid var(--white);
    opacity: 0.85;
  }
  .pv-alt .pv-scroll-caret--next::before { margin-left: -4px; transform: rotate(45deg); }
  .pv-alt .pv-scroll-caret--prev::before { margin-left: 4px; transform: rotate(-135deg); }
  .pv-alt .pv-controls.can-advance .pv-scroll-caret--next,
  .pv-alt .pv-controls.can-retreat .pv-scroll-caret--prev {
    opacity: 1;
    visibility: visible;
  }
  /* once the left caret is up, fade the bar's left edge too so it reads
     over the tabs the same way the right one does */
  .pv-alt .pv-controls.can-retreat .pv-list {
    -webkit-mask-image: linear-gradient(to right, transparent, black 44px, black calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, transparent, black 44px, black calc(100% - 28px), transparent);
  }
  .cs-photo-grid,
  .cs-photo-grid--five { grid-template-columns: 1fr 1fr; }
  .cs-reveal-grid { grid-template-columns: 1fr; grid-auto-rows: 240px; }
  .cs-reveal-lg { grid-column: span 1; grid-row: span 1; }
  .cs-feature-grid { grid-template-columns: 1fr; gap: 16px; }
  /* Design */
  .ds { height: 560px; }
  .ds-text { top: 56px; gap: 16px; }
  .ds-text p { font-size: 15px; line-height: 24px; }
  .ds-image { top: 190px; height: 360px; }

  /* specs collapse to one column, label above value */
  .cs-specs-grid { grid-template-columns: 1fr; }
  .cs-faq-list { grid-template-columns: 1fr; }
  .cs-spec-table th,
  .cs-spec-table td { display: block; width: 100%; padding-right: 0; }
  .cs-spec-table th { padding: 14px 0 2px; }
  .cs-spec-table td { padding: 0 0 14px; }
  .cs-spec-group th { padding: 28px 0 10px; }
  .cs-spec-col + .cs-spec-col .cs-spec-table:first-child .cs-spec-group th { padding-top: 28px; }

  /* single stacked column — the divider turns horizontal, centred in the
     48px gap above each tile (the base rule still hides it on the first) */
  .cs-stats-grid { grid-template-columns: 1fr; gap: 48px; }
  .cs-stats-grid .cs-stat-tile::before {
    top: -24px;
    left: 50%;
    transform: translateX(-50%);
    width: 56px;
    height: 1px;
  }
  .cs-stat-number { font-size: 42px; }
  .cs-ba-frame { height: 320px; }
  .cs-ba-handle-grip { width: 36px; height: 36px; }
  .cs-masonry { columns: 2; }
  .cs-details-list { gap: 32px; }
  .cs-related-grid { grid-template-columns: 1fr; }
  .cs-timeline-list li { font-size: 17px; }
}

/* --- Small phones --- */
@media (max-width: 400px) {
  .btn-primary { padding: 14px 24px; font-size: 12px; }
}

/* ============================================================
   DESIGN — STATIC FULL-WIDTH VARIANT (.ds--static)
   No parallax and no overlap: heading, copy and image stack in normal
   flow, so the image always starts below however many lines the copy
   wraps to. The image runs edge to edge at its natural aspect ratio (no
   cropping, no base fade).
   ============================================================ */
.ds.ds--static {
  height: auto;
  padding: 132px 0 0;
}

.ds--static .ds-text {
  position: relative;
  top: auto;
  left: auto;
  margin: 0 auto;
  transform: translateY(28px);
}

.ds--static .ds-text.is-visible {
  transform: translateY(0);
}

.ds--static .ds-image {
  position: relative;
  top: auto;
  left: auto;
  width: 100%;
  max-width: none;
  height: auto;
  margin-top: 64px;
  transform: none;
  will-change: auto;
}

.ds--static .ds-image img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
}

.ds--static .ds-image::after {
  display: none;
}

/* ============================================================
   DESIGN — DUAL STACKED IMAGES (.ds--dual)
   Stacks two .ds-image boxes below the copy in normal flow instead of
   the single absolutely-positioned/parallax image, each kept at the
   same fixed size as the default .ds-image box.
   ============================================================ */
.ds.ds--dual {
  height: auto;
  padding: 90px 0 60px;
}

.ds--dual .ds-text {
  position: relative;
  top: auto;
  left: auto;
  margin: 0 auto;
  transform: translateY(28px);
}

.ds--dual .ds-text.is-visible {
  transform: translateY(0);
}

.ds--dual .ds-images {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  margin-top: 60px;
}

.ds--dual .ds-image {
  position: relative;
  top: auto;
  left: auto;
  width: 1180px;
  max-width: 100%;
  height: auto;
  transform: none;
  will-change: auto;
}

.ds--dual .ds-image img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 16px;
}

.ds--dual .ds-image::after {
  display: none;
}

/* phones: inset to the page margins like the gallery and content below,
   instead of running edge to edge */
@media (max-width: 768px) {
  .ds--dual .ds-images { padding: 0 var(--page-pad); }
}

@media (max-width: 1024px) {
  .ds.ds--static { height: auto; padding-top: 90px; }
  .ds--static .ds-image { top: auto; height: auto; margin-top: 48px; }
}

@media (max-width: 768px) {
  .ds.ds--static { height: auto; padding-top: 56px; }
  .ds--static .ds-image { top: auto; height: auto; margin-top: 40px; }
}

/* ============================================================
   PROJECT HERO — STACKED (two-line) TITLE
   Long project names break onto two lines at the shared title size
   instead of shrinking. The body copy and CTA drop by one title line
   (line-height .914 x the title's font-size) so they clear the second line.
   ============================================================ */
.ph-hero--stacked .ph-body {
  top: calc(306px + 0.914 * clamp(56px, 11.2vw, 160px));
}

@media (max-width: 1024px) {
  .ph-hero--stacked .ph-body {
    top: calc(220px + 0.914 * clamp(56px, 11.2vw, 160px));
  }
}

/* ============================================================
   PROJECT HERO — LOWERED IMAGE (.ph-hero--img-low)
   Hero photo sits 170px lower and 40px further right; the hero grows by
   the same 170px so the image isn't clipped at the bottom.
   ============================================================ */
.ph-hero--img-low {
  height: 1236px;
}

.ph-hero--img-low .ph-image {
  top: 357px;
  left: calc(36% + 40px);
}

@media (max-width: 1024px) {
  .ph-hero--img-low { height: 960px; }
  .ph-hero--img-low .ph-image { top: 310px; }
}

@media (max-width: 768px) {
  .ph-hero--img-low { height: auto; }
}

/* ============================================================
   RELATED PROJECTS CAROUSEL (.rp) — bottom of every case study
   Showroom project tiles (588px wide, same look) as a looping carousel.
   The two middle tiles sit centred and fully opaque; the tiles either
   side are faded and run off canvas. Clicking a faded tile advances the
   carousel that way (8-bit arrow cursors and pagination dots are the home
   page studio carousel's). Built by RELATED PROJECTS CAROUSEL in scripts.js.
   ============================================================ */
.rp {
  --rp-gap: 16px;
  --rp-w: min(588px, 46vw);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
  padding: 60px 0 var(--section-py);
  overflow: hidden;
}

.rp .project-stories-label {
  align-self: flex-start;
  padding-left: var(--page-pad);
  color: var(--white);
}

.rp-viewport {
  position: relative;
  width: 100%;
  height: 220px;
}

.rp-track {
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* every tile starts at the page centre; --d (its slot 0-3) slides it into
   place: slots 1 and 2 are the centred pair, 0 and 3 sit either side */
.rp-tile {
  position: absolute;
  top: 0;
  left: 50%;
  width: var(--rp-w);
  height: 100%;
  transform: translateX(calc(-1 * var(--rp-w) - var(--rp-gap) / 2 + (var(--d, 1) - 1) * (var(--rp-w) + var(--rp-gap))));
  transition: transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.6s ease;
  /* the ring holds extra tiles waiting off-canvas — only slots 0-3 show */
  opacity: 0;
  pointer-events: none;
}

.rp-tile[data-slot="1"],
.rp-tile[data-slot="2"] {
  opacity: 1;
  pointer-events: auto;
}

.rp-tile[data-slot="0"],
.rp-tile[data-slot="3"] {
  opacity: 0.35;
  pointer-events: auto;
}

.rp-tile .project-card {
  height: 100%;
  cursor: inherit;
}

/* side tiles show the 8-bit arrow cursor; the two middle tiles are plain links */
.rp-tile[data-role="center"] .project-card {
  cursor: pointer;
}

@media (max-width: 768px) {
  .rp-viewport { height: 200px; }

  /* one tile wide with the neighbours peeking in at the sides */
  .rp { --rp-w: 72vw; }
  .rp-tile {
    transform: translateX(calc(-0.5 * var(--rp-w) + (var(--d, 1) - 1) * (var(--rp-w) + var(--rp-gap))));
  }

  .rp-tile[data-slot="2"] { opacity: 0.35; }
  .rp-tile[data-slot="3"] { opacity: 0; pointer-events: none; }
}

/* ============================================================
   MOBILE — LEFT-ALIGNED TEXT
   Every title and paragraph reads flush-left on phones (except the
   Trusted Vendors label, which stays centred over its logos); the desktop
   centred blocks (Design, Manufacturing/Process,
   Materials, contact header) drop their centring here. Placed last so
   it wins over the base rules above.
   ============================================================ */
@media (max-width: 768px) {
  .ds-text,
  .pv-alt .pv-header,
  .materials-fan-text,
  .contact-header {
    text-align: left;
  }

  .ds-text,
  .pv-alt .pv-header,
  .materials-fan-text,
  .contact-header {
    align-items: flex-start;
  }

  /* these sit in centring flex columns, so stretch them to the content
     width or they'd shrink to their text and stay centred as a block */
  .materials-fan-text {
    align-self: stretch;
  }
}

/* ============================================================
   MOBILE — NO BUTTON ANIMATIONS
   The pixel-grid fill and the terracotta wipe are hover effects; on
   phones a tap fires them and they stick, so both are switched off.
   ============================================================ */
@media (max-width: 768px) {
  .btn-primary .btn-particle-canvas,
  .btn-primary .btn-particle-canvas.active {
    display: none;
  }
  .btn-primary::before {
    display: none;
  }
}

/* ============================================================
   SHOWROOM — LARGER CARD TITLES ON PHONES
   Project names on the showroom's Recent Project Stories cards run 20%
   larger than the shared phone size (the related-projects carousel on
   case studies keeps the original).
   ============================================================ */
@media (max-width: 768px) {
  .showroom-gallery .project-card-name { font-size: 34px; line-height: 31px; letter-spacing: 0.6px; }

  /* the photo fills the card at full size but is slid right behind the
     title (its right side runs off the card), with its left edge
     feathered into the black card instead of ending in a hard line */
  .showroom-gallery .project-card img,
  .showroom-gallery .project-card:hover img {
    top: 0;
    left: 25%;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 40%;
    -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 35%);
    mask-image: linear-gradient(to right, transparent 0%, #000 35%);
  }
}

/* ============================================================
   MOBILE — GALLERY SWIPE CAROUSEL
   On phones the case-study Build Gallery becomes one horizontal row you
   swipe with your thumb instead of a stack of photos (About's The Shop
   and the Showroom gallery keep the stacked layout). The nested rows/columns are
   flattened with display: contents so every card is a direct item of the
   scrolling row; each card snaps into place, and the next one peeks in
   from the right to show there's more. The row runs to the screen edges
   (cancelling the section padding) while snapping stays on the margin.
   Tapping a photo still opens the gallery modal.
   ============================================================ */
@media (max-width: 768px) {
  #build-gallery .gallery-grid {
    flex-direction: row;
    gap: 12px;
    margin: 0 calc(var(--page-pad) * -1);
    padding: 0 var(--page-pad);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding: 0 var(--page-pad);
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  #build-gallery .gallery-grid::-webkit-scrollbar { display: none; }

  #build-gallery .gallery-row,
  #build-gallery .gallery-col {
    display: contents;
  }

  #build-gallery .gallery-card,
  #build-gallery .gallery-row--split .gallery-card:first-child,
  #build-gallery .gallery-row--split .gallery-card:last-child {
    flex: 0 0 84%;
    height: 280px;
    scroll-snap-align: start;
  }
}
