/* =============================================================================
   Ingo Systems site — plain HTML/CSS/JS + three.js
   Values here mirror the reference build (header grid, title rotations, cue pill,
   stage insets); tune the carousel itself in js/carousel.js â†’ CONFIG.
   ========================================================================== */

:root {
  color: #000;
  background: #fff;
  font-family: Montserrat, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-synthesis: none;
  text-rendering: optimizeLegibility;

  --header-pad: 24px;
  /* --header-height is what the hero and the carousel stage subtract, so it has
     to stay the pill's full footprint: top offset + pill height. */
  --nav-top: 16px;
  --nav-height: 56px;
  --nav-btn-size: 40px;
  --nav-inset: 8px;
  --nav-max-width: 1080px;
  --nav-accent: #db0508;
  --header-height: calc(var(--nav-top) + var(--nav-height));
  --social-icon-size: 28px;

  --theme-accent: #000;
  --header-ink: var(--theme-accent);
  --header-hover-ink: #000;
  --accent-hover-fill: #000;
  --divider-color: #d3d2d2;

  /* Entrance is driven by one class on <body>; these are the resting values. */
  --enter-ease: cubic-bezier(0.22, 1, 0.36, 1);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

/* Anchors land below the floating pill instead of underneath it. */
section[id] {
  scroll-margin-top: calc(var(--header-height) + 14px);
}

/* font-family and color are re-asserted here on purpose: sections.css ships a
   `body { font-family: DM Sans; color: ... }` rule, and an element selector on
   body beats the inherited value from :root. This file loads after it, so the
   hero keeps its own type; .site below hands DM Sans back to those sections. */
body {
  background: #fff;
  color: #000;
  font-family: Montserrat, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  overflow-x: hidden;
}

/* Everything below the hero is ported from the reference build and styled by its own
   compiled Tailwind in sections.css. This wrapper restores that subtree's type. */
.site {
  font-family: "DM Sans", ui-sans-serif, system-ui, sans-serif;
  color: hsl(var(--foreground, 30 12% 20%));
}

/* Scroll reveals. Each element's start state stays in its own inline style —
   the values GSAP authored — so this only supplies the easing; js/sections.js
   clears those inline properties once the element is on screen. */
.site [data-reveal] {
  transition:
    opacity 0.8s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.8s cubic-bezier(0.22, 1, 0.36, 1),
    filter 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Scroll-linked, driven frame by frame in js/sections.js rather than by a class. */
.site [data-curtain] {
  transform-origin: bottom;
}


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

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

/* The header is only a centring track. Everything visible lives in .nav-shell,
   so the bar can be transparent edge to edge and float over the hero. */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 20;
  width: 100%;
  display: flex;
  justify-content: center;
  padding: var(--nav-top) var(--header-pad) 0;
  pointer-events: none;
}

/* Only the actual controls take pointer events — the bar itself must not
   swallow drags meant for the carousel behind it. */
.nav-shell,
.nav-drawer {
  pointer-events: auto;
}

/* -- the glass pill -- */

.nav-shell {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: min(var(--nav-max-width), 100%);
  height: var(--nav-height);
  padding: 0 var(--nav-inset);
  border-radius: 999px;

  /* Two layers make the "glass": a highlight sweep that reads as light falling
     across the surface, over a flat translucent tint. Whatever scrolls under
     it is blurred and saturated so the pill picks up the page's colour. */
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.62), rgba(255, 255, 255, 0.12) 46%, rgba(255, 255, 255, 0.4)),
    rgba(246, 246, 248, 0.55);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  box-shadow:
    0 20px 44px -22px rgba(0, 0, 0, 0.45),
    0 2px 10px -4px rgba(0, 0, 0, 0.12),
    inset 0 1px 0 rgba(255, 255, 255, 0.7);

  opacity: 0;
  transform: translateY(-26px);
  transition:
    opacity 0.62s var(--enter-ease),
    transform 0.76s var(--enter-ease);
}

/* A 1px gradient rim, brightest at the top-left corner. Painted as a masked
   ring rather than a border so it can fade along its own length. */
.nav-shell::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(
    140deg,
    rgba(255, 255, 255, 0.95),
    rgba(255, 255, 255, 0.25) 38%,
    rgba(255, 255, 255, 0.08) 62%,
    rgba(255, 255, 255, 0.7)
  );
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  pointer-events: none;
}

body.is-ready .nav-shell {
  opacity: 1;
  transform: translateY(0);
}

/* Past the hero fold the pill sits over content far more often than over
   white, so it tightens up: more tint, a firmer shadow. */
body.is-scrolled .nav-shell {
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.16) 46%, rgba(255, 255, 255, 0.46)),
    rgba(244, 244, 247, 0.72);
  box-shadow:
    0 22px 50px -22px rgba(0, 0, 0, 0.55),
    0 2px 12px -4px rgba(0, 0, 0, 0.16),
    inset 0 1px 0 rgba(255, 255, 255, 0.75);
}

/* Blur is the whole effect; without it the tint alone would let the page read
   straight through the bar, so opaque up the background instead. Last, so it
   also wins over the scrolled state above. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nav-shell,
  body.is-scrolled .nav-shell,
  .nav-drawer {
    background: rgba(250, 250, 251, 0.97);
  }
}

.nav-logo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  height: 44px;
  padding: 5px 18px 5px 14px;
  border-radius: 999px;
  background: #0f172a;
  box-shadow: 0 4px 16px rgba(15, 23, 42, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(255, 255, 255, 0.15);
  transition: transform 0.24s var(--enter-ease), background 0.24s ease, box-shadow 0.24s ease;
  text-decoration: none;
}

.nav-logo:hover {
  transform: translateY(-1px) scale(1.04);
  background: #1e293b;
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.35);
}

.nav-logo img,
.nav-logo-img {
  height: 32px;
  width: auto;
  max-height: 34px;
  object-fit: contain;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3));
}

/* -- links -- */

.nav-links {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  gap: 4px;
  min-width: 0;
}

.nav-links a {
  position: relative;
  z-index: 1;
  padding: 9px 14px;
  border-radius: 999px;
  color: #4b4b4f;
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.01em;
  white-space: nowrap;
  text-decoration: none;
  transition: color 0.24s ease;
}

.nav-links a[aria-current="page"] {
  color: #000;
}

.nav-links a:not([aria-current="page"]):hover {
  color: var(--header-hover-ink);
}

/* Starts at zero width, so it only appears once main.js has measured the
   active link — no flash of a pill parked at the left edge. */
.nav-indicator {
  position: absolute;
  top: 50%;
  left: 0;
  z-index: 0;
  width: 0;
  height: calc(var(--nav-btn-size) - 4px);
  border-radius: 999px;
  /* Needs a dark hairline as well as the white fill: over the white hero a
     white-on-white pill would have nothing but its shadow to show for it. */
  background: rgba(255, 255, 255, 0.85);
  box-shadow:
    inset 0 0 0 1px rgba(16, 16, 20, 0.08),
    0 6px 14px -8px rgba(0, 0, 0, 0.55);
  pointer-events: none;
  translate: 0 -50%;
  transition:
    translate 0.36s var(--enter-ease),
    width 0.36s var(--enter-ease);
}

/* -- round action buttons -- */

.nav-actions {
  display: flex;
  align-items: center;
  gap: 7px;
  flex: 0 0 auto;
  margin-left: auto;
}

.nav-btn {
  display: grid;
  place-items: center;
  width: var(--nav-btn-size);
  height: var(--nav-btn-size);
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: #101014;
  color: #fff;
  cursor: pointer;
  font-family: inherit;
  text-decoration: none;
  box-shadow: 0 6px 16px -8px rgba(0, 0, 0, 0.85);
  transition:
    background-color 0.22s ease,
    transform 0.22s var(--enter-ease);
}

.nav-btn:hover {
  background: var(--nav-accent);
  transform: translateY(-1px);
}

.nav-btn svg {
  width: 19px;
  height: 19px;
}

/* One button, two glyphs — aria-pressed is the single source of truth for
   which one shows, so the label and the icon can never disagree. */
.nav-sound__off,
.nav-sound[aria-pressed="false"] .nav-sound__on {
  display: none;
}

.nav-sound[aria-pressed="false"] .nav-sound__off {
  display: block;
}

.nav-sound[aria-pressed="false"] {
  background: #2c2c33;
  color: rgba(255, 255, 255, 0.55);
}

/* Until the first click the sound is armed but the browser has it muted, so
   the button breathes to say it wants pressing. */
.nav-sound.is-locked {
  animation: nav-sound-pulse 2.4s ease-in-out infinite;
}

@keyframes nav-sound-pulse {
  0%,
  100% {
    box-shadow:
      0 6px 16px -8px rgba(0, 0, 0, 0.85),
      0 0 0 0 rgba(219, 5, 8, 0.5);
  }
  50% {
    box-shadow:
      0 6px 16px -8px rgba(0, 0, 0, 0.85),
      0 0 0 7px rgba(219, 5, 8, 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .nav-sound.is-locked {
    animation: none;
  }
}

/* Three bars drawn from one element: the middle is the box itself, the outer
   two are its pseudo-elements — which is what lets them rotate into an X. */
.nav-burger,
.nav-burger::before,
.nav-burger::after {
  display: block;
  width: 15px;
  height: 1.6px;
  border-radius: 2px;
  background: currentColor;
  transition:
    transform 0.28s var(--enter-ease),
    opacity 0.18s ease;
}

.nav-burger {
  position: relative;
}

.nav-burger::before,
.nav-burger::after {
  content: "";
  position: absolute;
  left: 0;
}

.nav-burger::before {
  top: -5px;
}
.nav-burger::after {
  top: 5px;
}

.site-header.is-open .nav-burger {
  background: transparent;
}

.site-header.is-open .nav-burger::before {
  transform: translateY(5px) rotate(45deg);
}

.site-header.is-open .nav-burger::after {
  transform: translateY(-5px) rotate(-45deg);
}

/* -- drawer -- */

/* Hangs off the header, not the pill: nesting one backdrop-filter inside
   another makes the inner element sample its parent's blur instead of the
   page. The `right` value is the same centring maths the pill does, so the
   panel lines up under the pill's right edge at any width. */
.nav-drawer {
  position: absolute;
  top: calc(var(--nav-top) + var(--nav-height) + 10px);
  right: calc(50% - min(var(--nav-max-width), 100% - var(--header-pad) * 2) / 2);
  z-index: 19;
  width: min(320px, calc(100% - var(--header-pad) * 2));
  padding: 14px;
  border-radius: 26px;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.66), rgba(255, 255, 255, 0.16) 50%, rgba(255, 255, 255, 0.44)),
    rgba(246, 246, 248, 0.72);
  backdrop-filter: blur(22px) saturate(180%);
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  box-shadow:
    0 26px 60px -26px rgba(0, 0, 0, 0.55),
    inset 0 1px 0 rgba(255, 255, 255, 0.7);

  opacity: 0;
  visibility: hidden;
  transform: translateY(-12px) scale(0.98);
  transform-origin: top right;
  transition:
    opacity 0.26s ease,
    transform 0.32s var(--enter-ease),
    visibility 0s linear 0.32s;
}

.site-header.is-open .nav-drawer {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
  transition-delay: 0s;
}

.nav-drawer__links {
  display: grid;
  gap: 2px;
}

.nav-drawer__links a {
  padding: 12px 14px;
  border-radius: 14px;
  color: #17171a;
  font-size: 0.95rem;
  font-weight: 600;
  text-decoration: none;
  transition:
    background-color 0.18s ease,
    color 0.18s ease;
}

.nav-drawer__links a:hover {
  background: rgba(255, 255, 255, 0.7);
  color: #000;
}

.nav-drawer__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding: 12px 14px 4px;
  border-top: 1px solid rgba(0, 0, 0, 0.08);
}

.header-location {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--header-ink);
  cursor: default;
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  text-transform: uppercase;
  user-select: none;
  transition: color 0.16s ease;
}

/* Icon is masked rather than an <img> so it inherits the ink colour. */
.header-location::before {
  content: "";
  display: block;
  width: 8px;
  height: 9px;
  flex: 0 0 auto;
  background-color: currentColor;
  mask: url(../assets/icons/location.svg) center / contain no-repeat;
  -webkit-mask: url(../assets/icons/location.svg) center / contain no-repeat;
}

.header-contact {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 9px;
  min-width: 0;
}

.email-copy {
  appearance: none;
  position: relative;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--header-ink);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}

.social-link {
  display: inline-grid;
  place-items: center;
  width: var(--social-icon-size);
  height: var(--social-icon-size);
  color: var(--header-ink);
  text-decoration: none;
}

.social-link img {
  width: 17px;
  height: 17px;
}

/* Tiny toast after the email is copied to the clipboard. */
.copy-toast {
  position: fixed;
  top: 58px;
  right: var(--header-pad);
  z-index: 30;
  padding: 7px 11px;
  border-radius: 999px;
  background: #000;
  color: #fff;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition:
    opacity 0.24s ease,
    transform 0.24s ease;
}

.copy-toast.is-on {
  opacity: 1;
  transform: translateY(0);
}

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

/* Full viewport height, not viewport minus header: the header is fixed, so it
   overlays this section rather than sitting above it. Subtracting its height
   would leave the hero ending 68px short and float the explore cue. */
.work-hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  overflow: hidden;
  padding: calc(var(--header-height) + 34px) 0 40px;
  background-color: #fff;
}

/* ------------------------------------------------------- carousel stage -- */

/* The stage bleeds well past the hero box so cards can enter/leave off-screen
   without the canvas edge clipping them. */
.carousel-stage {
  --scene-top-extra: 320px;
  --scene-bottom-extra: 180px;

  position: absolute;
  inset: calc(var(--header-height) - var(--scene-top-extra)) 0 0;
  z-index: 0;
  overflow: visible;
  opacity: 0;
  transition: opacity 0.52s var(--enter-ease) 0.15s;
}

body.is-ready .carousel-stage {
  opacity: 1;
}

.carousel-canvas {
  display: block;
  width: 100%;
  height: calc(100% + var(--scene-bottom-extra));
  cursor: default;
  touch-action: none;
  user-select: none;
}

.carousel-canvas--hovering {
  cursor: grab;
}

.carousel-canvas--dragging {
  cursor: grabbing;
}

/* ------------------------------------------------------- title and meta -- */

/* Fixed height on purpose: it reserves the vertical band the phones occupy, so
   .hero-meta lands at their feet instead of directly under the title. */
.hero-intro {
  position: relative;
  z-index: 1;
  width: 100%;
  height: calc(min(66vh, 650px) - 68px);
  margin: 0 auto;
  text-align: center;
  pointer-events: none;
}

.hero-intro h1 {
  margin: 0 auto;
  width: 100%;
  color: #000;
  font-family: Anton, Impact, Haettenschweiler, "Arial Narrow Bold", sans-serif;
  font-size: clamp(2.2rem, 5.5vw, 6.8rem);
  font-weight: 900;
  line-height: 0.85;
  letter-spacing: -0.02em;
  text-transform: uppercase;

  opacity: 0;
  transform: translateY(28px);
  transition:
    opacity 0.7s var(--enter-ease) 0.1s,
    transform 0.9s var(--enter-ease) 0.1s;
}

body.is-ready .hero-intro h1 {
  opacity: 1;
  transform: translateY(0);
}

/* preserve-3d + the two opposite rotateY values are what fan the title
   slightly outward from the centre. */
.hero-title-line {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.15em;
  transform-style: preserve-3d;
  perspective: 700px;
}

.hero-title-word,
.hero-title-static {
  display: inline-block;
  transform-style: preserve-3d;
}

.hero-title-word-item {
  display: block;
  white-space: nowrap;
  transform-style: preserve-3d;
  will-change: opacity, transform;
}

/* One character of the curved title. */
.hero-title-line .ch {
  display: inline-block;
  will-change: transform;
}

.hero-title-word-item--in {
  animation: hero-title-word-in 0.56s var(--enter-ease) both;
}

.hero-title-word-item--out {
  position: absolute;
  inset: 0;
  animation: hero-title-word-out 0.56s var(--enter-ease) both;
}

/* Off-screen clone used to measure the next word's width before swapping. */
.hero-title-measure {
  position: absolute;
  left: 0;
  top: 0;
  width: auto !important;
  visibility: hidden;
  pointer-events: none;
  white-space: nowrap;
}

@keyframes hero-title-word-in {
  0% {
    opacity: 0;
    transform: translateY(0.42em);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes hero-title-word-out {
  0% {
    opacity: 1;
    transform: translateY(0);
  }
  to {
    opacity: 0;
    transform: translateY(-0.42em);
  }
}

.hero-meta {
  position: relative;
  z-index: 4;
  pointer-events: none;
  width: min(960px, calc(100vw - 32px));
  display: grid;
  grid-template-columns: minmax(0, 1fr) min(220px, 18vw) minmax(0, 1fr);
  align-items: center;
  justify-content: center;
  margin: clamp(40px, 6vh, 80px) auto 0;
  color: #0f172a;
  font-size: clamp(0.85rem, 1.15vw, 1.25rem);
  font-weight: 700;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.05em;

  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 0.7s var(--enter-ease) 0.24s,
    transform 0.9s var(--enter-ease) 0.24s;
}

body.is-ready .hero-meta {
  opacity: 1;
  transform: translateY(0);
}

.hero-meta span {
  white-space: nowrap;
  background: rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.06);
}

.hero-meta span:first-child {
  grid-column: 1;
  justify-self: end;
  text-align: right;
}

.hero-meta span:last-child {
  grid-column: 3;
  justify-self: start;
  text-align: left;
}

@media (max-width: 768px) {
  .hero-meta {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 24px;
  }
  .hero-meta span:first-child,
  .hero-meta span:last-child {
    justify-self: center;
    text-align: center;
  }
}

/* ------------------------------------------------------------ character -- */

.hero-character-dom {
  position: absolute;
  left: 50%;
  /* Tuned so the feet clear the explore pill and the head still rides up into
     the title, the way the reference composition stacks them. */
  bottom: 13%;
  height: clamp(400px, 70vh, 800px);
  width: auto;
  max-width: none;
  z-index: 2;
  pointer-events: none;

  opacity: 0;
  transform: translate(-50%, 46px);
  transition:
    opacity 0.8s var(--enter-ease) 0.2s,
    transform 1s var(--enter-ease) 0.2s;
}

body.is-ready .hero-character-dom {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* ---------------------------------------------------------- explore cue -- */

.explore-cue {
  position: absolute;
  left: 50%;
  bottom: 10px;
  z-index: 3;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 5px;
  width: 58px;
  height: 112px;
  padding: 18px 8px 0;
  border-radius: 999px;
  background-color: var(--theme-accent);
  color: #fff;
  font-size: 0.56rem;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.04em;

  opacity: 0;
  translate: 0 92px;
  transform: translate(-50%, var(--cue-lift, 0px));
  transition:
    background 0.16s ease,
    opacity 0.76s var(--enter-ease) 0.4s,
    translate 0.86s var(--enter-ease) 0.4s,
    transform 0.26s var(--enter-ease);
}

body.is-ready .explore-cue {
  opacity: 1;
  translate: 0 0;
}

.explore-cue:hover {
  background: var(--accent-hover-fill);
  --cue-lift: -8px;
}

.explore-arrow {
  flex: 0 0 auto;
  width: 13px;
  height: 22px;
  background: #fff;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 24' fill='none' stroke='%23fff' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.5 3V19.5M2 15l4.5 4.5L11 15'/%3E%3C/svg%3E")
    center / contain no-repeat;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 24' fill='none' stroke='%23fff' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.5 3V19.5M2 15l4.5 4.5L11 15'/%3E%3C/svg%3E")
    center / contain no-repeat;
  animation: explore-arrow-bob 2.1s ease-in-out infinite;
}

@keyframes explore-arrow-bob {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(4px);
  }
}

/* --------------------------------------------------------------- ticker -- */

.hero-marquee {
  display: none;
  overflow: hidden;
  width: 100%;
  padding: 12px 0;
  margin-top: clamp(44px, 8vh, 76px);
}

.hero-marquee__track {
  display: inline-flex;
  white-space: nowrap;
  will-change: transform;
  /* The copy is duplicated in JS, so -50% lands exactly on a seam. */
  animation: hero-marquee-scroll 18s linear infinite;
}

@keyframes hero-marquee-scroll {
  to {
    transform: translateX(-50%);
  }
}

.hero-marquee__copy {
  font-weight: 600;
  font-size: clamp(11.5px, 3.2vw, 15px);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #1a1a1a;
  white-space: pre;
}

/* -------------------------------------------------------- services rails -- */

/* Two rails now share the ported card markup: engineering on top, marketing
   under it. These few rules cover only what the compiled sections.css cannot —
   the rail headings, and the colour treatment that keeps the six editorial
   photographs from reading as repeats across seventeen cards. */

.site .svc-rail-head {
  max-width: 56rem;
  margin: 96px auto 0;
  padding: 0 24px;
  text-align: center;
}

.site .svc-rail-head__eyebrow {
  display: block;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: rgba(23, 23, 26, 0.75);
}

.site .svc-rail-head h3 {
  margin: 18px 0 0;
  font-size: clamp(1.6rem, 3.2vw, 2.4rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.12;
  color: #17171a;
}

.site .svc-rail-head p {
  margin: 14px auto 0;
  max-width: 40rem;
  font-size: 0.98rem;
  line-height: 1.6;
  color: rgba(23, 23, 26, 0.7);
}

/* -------------------------------------------------------- footer mark -- */

/* The ported footer carried the other studio's logo file. There is no logo
   asset for this one yet, so the mark is the favicon plus the name set as a
   wordmark — swap the whole span for an <img> once a real logo exists. */
.site .ft-word {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: Montserrat, ui-sans-serif, system-ui, sans-serif;
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  color: #fff;
}

.site .ft-word img {
  width: 22px;
  height: auto;
}

/* ------------------------------------------------------------ partners -- */

/* Real partner logos, so the panels that used to carry stock photography are
   gone: a logo needs clean, light space around it, not a photograph behind a
   colour wash. Three cards, each with the mark on its own surface. */

.pt-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: 24px;
  max-width: 840px;
  margin: 56px auto 0;
  width: 100%;
}

.pt-card {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1 1 360px;
  max-width: 400px;
  overflow: hidden;
  border-radius: 26px;
  background: #fff;
  box-shadow:
    inset 0 0 0 1px rgba(23, 23, 26, 0.07),
    0 18px 40px -30px rgba(15, 23, 42, 0.9);
  transition:
    transform 0.34s var(--enter-ease),
    box-shadow 0.34s ease;
}

.pt-card:hover {
  transform: translateY(-6px);
  box-shadow:
    inset 0 0 0 1px rgba(23, 23, 26, 0.07),
    0 30px 54px -30px rgba(15, 23, 42, 1);
}

/* A band of the partner's own colour along the top edge, widening on hover. */
.pt-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: var(--pt-accent);
  transform: scaleX(0.24);
  transform-origin: left;
  transition: transform 0.4s var(--enter-ease);
}

.pt-card:hover::before {
  transform: scaleX(1);
}

.pt-no {
  position: absolute;
  top: 22px;
  right: 24px;
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  color: rgba(23, 23, 26, 0.28);
}

/* The logo sits on a faint tint of its own brand colour, which keeps three
   very different marks looking like one set. */
/* Fixed, not min-height: with three different logo caps a growing box put
   each card's divider at a different line, which read as sloppy alignment. */
.pt-logo {
  display: grid;
  place-items: center;
  height: 232px;
  padding: 30px 40px;
  background: linear-gradient(
    170deg,
    color-mix(in srgb, var(--pt-accent) 9%, #fff),
    color-mix(in srgb, var(--pt-accent) 3%, #fff)
  );
}

/* One wordmark is 2.7:1, one is 1.8:1 and one is square. A single max-height
   would leave the square mark looking half the size of the wide one, so each
   card sets its own cap and they end up reading at the same weight. */
.pt-logo img {
  width: auto;
  max-width: var(--pt-logo-w, 78%);
  max-height: var(--pt-logo-h, 104px);
  object-fit: contain;
  filter: saturate(1.02);
  transition: transform 0.4s var(--enter-ease);
}

.pt-card:hover .pt-logo img {
  transform: scale(1.05);
}

.pt-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
  padding: 26px 28px 30px;
  border-top: 1px solid rgba(23, 23, 26, 0.07);
}

.pt-role {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--pt-accent);
}

.pt-card h3 {
  margin: 0;
  font-size: 1.28rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: #17171a;
}

.pt-card p {
  margin: 0;
  font-size: 0.92rem;
  line-height: 1.6;
  color: rgba(23, 23, 26, 0.66);
}

.pt-since {
  margin-top: auto;
  padding-top: 16px;
  font-size: 0.78rem;
  font-weight: 600;
  color: rgba(23, 23, 26, 0.45);
}

@media (max-width: 900px) {
  .pt-grid {
    grid-template-columns: 1fr;
    gap: 16px;
  }

  .pt-logo {
    min-height: 170px;
  }
}

/* ---------------------------------------------------------- erp mockup -- */

/* The product preview inside the browser chrome is markup, not a screenshot,
   so it stays sharp at any width and its numbers can be edited in the HTML.
   Every size is in cqw — 1% of the frame's own width — which makes the whole
   dashboard scale as one piece instead of reflowing into a phone layout at
   small sizes. That is what a screenshot would do, and this has to read as a
   screenshot. */

.site .erp-frame {
  container-type: size;
}

.site .erp-shell {
  --erp-brand: #2f4bd8;
  --erp-ink: #10131c;
  --erp-muted: #6b7280;
  --erp-line: #e8eaf0;
  --erp-paid: #16a34a;
  --erp-due: #f59e0b;
  --erp-over: #ef4444;

  position: absolute;
  inset: 0;
  display: flex;
  overflow: hidden;
  background: #f6f7fb;
  color: var(--erp-ink);
  font-family: "DM Sans", ui-sans-serif, system-ui, sans-serif;
  text-align: left;
  letter-spacing: 0;
}

/* -- sidebar -- */

.site .erp-side {
  display: flex;
  flex-direction: column;
  width: 17cqw;
  flex: 0 0 auto;
  padding: 1.7cqw 1.3cqw;
  background: #fff;
  border-right: 1px solid var(--erp-line);
}

.site .erp-brand {
  display: flex;
  align-items: center;
  gap: 0.7cqw;
  font-size: 1.35cqw;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.site .erp-mark {
  display: grid;
  place-items: center;
  width: 2.4cqw;
  height: 2.4cqw;
  border-radius: 0.7cqw;
  background: var(--erp-brand);
  color: #fff;
  font-size: 1.3cqw;
  font-weight: 700;
}

.site .erp-nav {
  display: flex;
  flex-direction: column;
  gap: 0.15cqw;
  margin-top: 2cqw;
}

.site .erp-nav-item {
  display: flex;
  align-items: center;
  gap: 0.8cqw;
  padding: 0.72cqw 0.8cqw;
  border-radius: 0.6cqw;
  color: var(--erp-muted);
  font-size: 1.05cqw;
  font-weight: 500;
}

.site .erp-nav-item i {
  width: 1.1cqw;
  height: 1.1cqw;
  border-radius: 0.3cqw;
  background: currentColor;
  opacity: 0.35;
}

.site .erp-nav-item.is-on {
  background: rgba(47, 75, 216, 0.09);
  color: var(--erp-brand);
  font-weight: 600;
}

.site .erp-nav-item.is-on i {
  opacity: 1;
}

.site .erp-side-foot {
  margin-top: auto;
  padding-top: 1cqw;
  border-top: 1px solid var(--erp-line);
  color: var(--erp-muted);
  font-size: 0.92cqw;
}

/* -- main column -- */

.site .erp-main {
  display: flex;
  flex-direction: column;
  gap: 1.2cqw;
  flex: 1 1 auto;
  min-width: 0;
  padding: 1.5cqw 1.6cqw;
}

.site .erp-top {
  display: flex;
  align-items: center;
  gap: 1cqw;
}

.site .erp-search {
  flex: 1 1 auto;
  padding: 0.8cqw 1.1cqw;
  border: 1px solid var(--erp-line);
  border-radius: 0.7cqw;
  background: #fff;
  color: var(--erp-muted);
  font-size: 1cqw;
}

.site .erp-top-right {
  display: flex;
  align-items: center;
  gap: 0.7cqw;
}

.site .erp-chip {
  padding: 0.5cqw 0.9cqw;
  border-radius: 999px;
  background: rgba(47, 75, 216, 0.1);
  color: var(--erp-brand);
  font-size: 0.9cqw;
  font-weight: 600;
}

.site .erp-avatar {
  width: 2.3cqw;
  height: 2.3cqw;
  border-radius: 999px;
  background: linear-gradient(135deg, #cbd2e6, #9aa6c9);
}

/* -- kpi row -- */

.site .erp-kpis {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1cqw;
}

.site .erp-kpi {
  display: flex;
  flex-direction: column;
  gap: 0.25cqw;
  padding: 1cqw 1.1cqw;
  border: 1px solid var(--erp-line);
  border-radius: 0.9cqw;
  background: #fff;
}

.site .erp-kpi-label {
  color: var(--erp-muted);
  font-size: 0.88cqw;
  font-weight: 500;
}

.site .erp-kpi strong {
  font-size: 2cqw;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.site .erp-kpi-note {
  font-size: 0.82cqw;
}

.site .erp-up {
  color: var(--erp-paid);
}
.site .erp-down {
  color: var(--erp-over);
}

/* -- cards -- */

.site .erp-grid {
  display: grid;
  grid-template-columns: 1.35fr 1fr;
  gap: 1cqw;
  flex: 1 1 auto;
  min-height: 0;
}

.site .erp-card {
  display: flex;
  flex-direction: column;
  gap: 0.8cqw;
  padding: 1cqw 1.1cqw;
  border: 1px solid var(--erp-line);
  border-radius: 0.9cqw;
  background: #fff;
  min-height: 0;
}

.site .erp-card h4 {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.8cqw;
  margin: 0;
  font-size: 1.05cqw;
  font-weight: 600;
}

.site .erp-muted {
  color: var(--erp-muted);
  font-size: 0.88cqw;
  font-weight: 500;
}

/* -- attendance bars -- */

.site .erp-bars {
  display: flex;
  align-items: flex-end;
  gap: 0.9cqw;
  flex: 1 1 auto;
  min-height: 0;
}

.site .erp-bar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45cqw;
  flex: 1 1 0;
  height: 100%;
}

.site .erp-bar-track {
  position: relative;
  width: 100%;
  flex: 1 1 auto;
  border-radius: 0.45cqw;
  background: #f1f2f7;
  overflow: hidden;
}

.site .erp-bar-fill {
  position: absolute;
  inset: auto 0 0 0;
  border-radius: 0.45cqw;
  background: linear-gradient(180deg, var(--erp-brand), #5f78ea);
}

.site .erp-bar span {
  color: var(--erp-muted);
  font-size: 0.82cqw;
}

/* -- fees donut -- */

.site .erp-donut-row {
  display: flex;
  align-items: center;
  gap: 1.2cqw;
  flex: 1 1 auto;
}

.site .erp-donut {
  position: relative;
  display: grid;
  place-items: center;
  width: 7.4cqw;
  height: 7.4cqw;
  flex: 0 0 auto;
  border-radius: 999px;
  background: conic-gradient(
    var(--erp-paid) 0 78%,
    var(--erp-due) 78% 92%,
    var(--erp-over) 92% 100%
  );
}

/* The hole is a masked-out disc rather than a second element. */
.site .erp-donut::before {
  content: "";
  position: absolute;
  width: 5cqw;
  height: 5cqw;
  border-radius: 999px;
  background: #fff;
}

.site .erp-donut span {
  position: relative;
  font-size: 1.35cqw;
  font-weight: 700;
}

.site .erp-legend {
  display: flex;
  flex-direction: column;
  gap: 0.55cqw;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.95cqw;
}

.site .erp-legend li {
  display: flex;
  align-items: center;
  gap: 0.55cqw;
  color: var(--erp-muted);
}

.site .erp-legend b {
  margin-left: auto;
  color: var(--erp-ink);
  font-weight: 600;
}

.site .erp-legend i {
  width: 0.85cqw;
  height: 0.85cqw;
  border-radius: 999px;
}

.site .erp-dot--paid {
  background: var(--erp-paid);
}
.site .erp-dot--due {
  background: var(--erp-due);
}
.site .erp-dot--over {
  background: var(--erp-over);
}

/* -- list cards -- */

.site .erp-rows {
  display: flex;
  flex-direction: column;
  gap: 0.15cqw;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site .erp-rows li {
  display: flex;
  align-items: center;
  gap: 0.7cqw;
  padding: 0.62cqw 0;
  border-top: 1px solid var(--erp-line);
  font-size: 0.95cqw;
}

.site .erp-rows li:first-child {
  border-top: 0;
}

.site .erp-period {
  display: grid;
  place-items: center;
  width: 1.9cqw;
  height: 1.9cqw;
  flex: 0 0 auto;
  border-radius: 0.45cqw;
  background: rgba(47, 75, 216, 0.1);
  color: var(--erp-brand);
  font-size: 0.8cqw;
  font-weight: 700;
}

.site .erp-avatar-sm {
  width: 1.9cqw;
  height: 1.9cqw;
  flex: 0 0 auto;
  border-radius: 999px;
  background: linear-gradient(135deg, #d7dcec, #a8b2d1);
}

.site .erp-subject {
  flex: 1 1 auto;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.site .erp-room {
  color: var(--erp-muted);
  font-size: 0.85cqw;
}

.site .erp-tag {
  padding: 0.28cqw 0.7cqw;
  border-radius: 999px;
  font-size: 0.78cqw;
  font-weight: 600;
}

.site .erp-tag--paid {
  background: rgba(22, 163, 74, 0.12);
  color: var(--erp-paid);
}
.site .erp-tag--partial {
  background: rgba(245, 158, 11, 0.14);
  color: #b45309;
}
.site .erp-tag--pending {
  background: rgba(239, 68, 68, 0.12);
  color: var(--erp-over);
}

/* Below the phone breakpoint the two-column card grid is unreadable at this
   scale, so the frame shows the top half of the dashboard only. */
@media (max-width: 640px) {
  .site .erp-side {
    display: none;
  }

  .site .erp-kpis {
    grid-template-columns: repeat(2, 1fr);
  }

  .site .erp-grid {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------------------ tech fan -- */

/* The stack deck reuses the industries fan's card shell, so it only needs the
   face: a logo over its name. Hover colour is done here rather than with a
   Tailwind group variant because sections.css is a compiled build and the
   arbitrary-property variant this needs was never generated into it. */

/* Photograph, brand wash, scrim — the same three layers the services cards
   use, so a stack card belongs to the same set as everything above it. */
.site .tech-frame {
  position: absolute;
  inset: 0;
  isolation: isolate;
}

.site .tech-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.site .tech-wash {
  position: absolute;
  inset: 0;
  mix-blend-mode: color;
}

/* Keeps the white logo legible over whatever the frame happens to be doing
   underneath it. */
.site .tech-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.78), rgba(0, 0, 0, 0.42) 55%, rgba(0, 0, 0, 0.28));
  transition: background 0.35s ease;
}

.site [data-industry-card]:hover .tech-scrim {
  background: linear-gradient(to top, rgba(0, 0, 0, 0.66), rgba(0, 0, 0, 0.3) 55%, rgba(0, 0, 0, 0.16));
}

.site .tech-card {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  aspect-ratio: 4 / 3;
  padding: 10px;
}

/* Only the outward strip of a fanned card is visible in the arc, so the face
   is pushed into that strip — left for cards left of centre, right for the
   others, the way a playing card prints its rank in the corner. Done with a
   transform rather than alignment so it can animate back to the middle when
   the card lifts clear of its neighbours. */
.site .tech-card {
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}

.site .tech-card--l {
  transform: translateX(-26%);
}

.site .tech-card--r {
  transform: translateX(26%);
}

.site [data-industry-card]:hover .tech-card {
  transform: none;
}

/* White over the photograph, not the brand colour: the wash already carries
   the brand, and a coloured mark on its own coloured frame disappears. */
.site .tech-card svg {
  width: clamp(24px, 2.4vw, 34px);
  height: clamp(24px, 2.4vw, 34px);
  color: #fff;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.55));
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

/* The card, not the icon, owns the hover: the whole face is the target. */
.site [data-industry-card]:hover .tech-card svg {
  transform: scale(1.12);
}

/* Sized to fit inside the visible strip rather than the whole card, so the
   name reads without waiting for a hover. */
.site .tech-card span {
  font-size: clamp(0.54rem, 0.72vw, 0.68rem);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 1px 5px rgba(0, 0, 0, 0.6);
}

/* The wash blends in colour only, so the photograph keeps its own light and
   grain and simply changes gel — the same trick a gaffer plays on set. It has
   to blend against the image alone, hence isolation on the frame. */
.svc-art {
  isolation: isolate;
}

.svc-wash {
  mix-blend-mode: color;
}

.svc-wash--violet {
  background: linear-gradient(135deg, #2b1a5e, #6d28d9 55%, #4c1d95);
}
.svc-wash--emerald {
  background: linear-gradient(135deg, #06382a, #0f9d68 55%, #115e4a);
}
.svc-wash--amber {
  background: linear-gradient(135deg, #4a2a06, #e08a09 55%, #92400e);
}
.svc-wash--cyan {
  background: linear-gradient(135deg, #06333f, #0ea5c4 55%, #155e75);
}
.svc-wash--indigo {
  background: linear-gradient(135deg, #16205e, #4f46e5 55%, #312e81);
}
.svc-wash--teal {
  background: linear-gradient(135deg, #07352f, #0fa598 55%, #115e59);
}
.svc-wash--crimson {
  background: linear-gradient(135deg, #4a0a12, #e11d48 55%, #9f1239);
}
.svc-wash--orange {
  background: linear-gradient(135deg, #4a1f05, #f97316 55%, #9a3412);
}
.svc-wash--magenta {
  background: linear-gradient(135deg, #45093a, #db2777 55%, #9d174d);
}

/* Same frame, different crop: pairs drawn from one photograph never show the
   same part of it. */
.svc-pos--l {
  object-position: 22% center;
}
.svc-pos--cl {
  object-position: 38% center;
}
.svc-pos--cr {
  object-position: 62% center;
}
.svc-pos--r {
  object-position: 78% center;
}

@media (max-width: 640px) {
  .site .svc-rail-head {
    margin-top: 64px;
    padding: 0 20px;
  }
}

/* --------------------------------------------------------------- mobile -- */

@media (max-width: 860px) {
  :root {
    --header-pad: 14px;
    --nav-top: max(12px, env(safe-area-inset-top));
    --nav-height: 54px;
  }

  /* The links row is what doesn't fit; the drawer already carries the same
     six, so drop it rather than shrinking type past readability. */
  .nav-links,
  .nav-btn--cta {
    display: none;
  }

  .nav-shell {
    justify-content: space-between;
  }

  /* Full-bleed panel here — a 320px card would look stranded on a phone. */
  .nav-drawer {
    right: var(--header-pad);
    left: var(--header-pad);
    width: auto;
    transform-origin: top center;
  }

  .work-hero {
    padding: calc(var(--header-height) + 48px) 0 0;
  }

  .hero-intro h1 {
    font-size: clamp(2.2rem, 13vw, 4.8rem);
    /* 0.78 is tight enough to collide once the title stacks — the descender of
       one line lands in the cap height of the next. */
    line-height: 0.92;
  }

  /* Side by side the two halves overflow a phone. The reference build dodges
     this by baking the title into a WebGL cylinder that scales itself; in
     plain CSS, stacking is the honest equivalent. */
  .hero-title-line {
    flex-direction: column;
    align-items: center;
    gap: 0.04em;
  }

  .hero-title-word,
  .hero-title-static {
    transform: none;
    text-align: center;
  }

  /* The cycling word needs its own line box here, or the absolutely positioned
     outgoing copy overlaps the static half below it. */
  .hero-title-word {
    min-height: 0.92em;
  }

  .hero-meta {
    width: calc(100vw - 28px);
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 16px;
    font-size: 0.78rem;
  }

  .hero-meta span:first-child,
  .hero-meta span:last-child {
    justify-self: auto;
    text-align: center;
    transform: none;
  }

  /* Stacked layout puts the meta labels in the character's path, and the
     character paints over them. Raise and shrink it so its feet land above
     the labels instead. */
  .hero-character-dom {
    height: 44vh;
    bottom: 38%;
  }

  .carousel-canvas {
    touch-action: pan-y;
  }

  .explore-cue {
    display: none;
  }

  .hero-marquee {
    display: block;
  }
}

/* =========================================================== portfolio == */

/* portfolio.html only. It does not load the ported Tailwind build, so nothing
   here may lean on it — every rule below stands on its own. The project
   artwork is drawn in markup rather than photographed: no borrowed imagery,
   and each card stays crisp at any size. */

.pf-page {
  background: #f6f6f7;
  color: #17171a;
  font-family: Montserrat, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
}

.pf-main {
  width: 100%;
  max-width: 100%;
  margin: 0 auto;
  padding: calc(var(--header-height) + 40px) 0 0;
  overflow-x: hidden;
}

.pf-hero,
.pf-filters,
.pf-grid {
  max-width: 1240px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 24px;
  padding-right: 24px;
}

.pf-eyebrow {
  margin: 0 0 18px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: rgba(23, 23, 26, 0.6);
}

.pf-hero h1 {
  margin: 0;
  font-family: Anton, Impact, sans-serif;
  font-size: clamp(2.6rem, 7vw, 5.2rem);
  font-weight: 400;
  line-height: 0.94;
  letter-spacing: -0.01em;
  text-transform: uppercase;
}

.pf-lede {
  margin: 22px 0 0;
  max-width: 44rem;
  font-size: 1.02rem;
  line-height: 1.65;
  color: rgba(23, 23, 26, 0.7);
}

.pf-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin: 34px 0 0;
  padding: 0;
  list-style: none;
}

.pf-stats li {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 12px 18px;
  border-radius: 999px;
  background: #fff;
  box-shadow: 0 1px 0 rgba(23, 23, 26, 0.06), 0 12px 26px -22px rgba(15, 23, 42, 0.7);
}

.pf-stats strong {
  font-size: 1.15rem;
  font-weight: 800;
}

.pf-stats span {
  font-size: 0.82rem;
  color: rgba(23, 23, 26, 0.6);
}

/* -- filters -- */

.pf-filters {
  position: sticky;
  top: calc(var(--header-height) + 10px);
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 54px 0 26px;
  padding: 8px;
  border-radius: 999px;
  width: fit-content;
  background: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.9), 0 16px 34px -26px rgba(15, 23, 42, 0.8);
}

.pf-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: rgba(23, 23, 26, 0.66);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.86rem;
  font-weight: 600;
  transition:
    background-color 0.22s ease,
    color 0.22s ease;
}

.pf-chip span {
  font-size: 0.72rem;
  opacity: 0.6;
}

.pf-chip:hover {
  color: #17171a;
}

.pf-chip.is-on {
  background: #101014;
  color: #fff;
}

/* -- the wall -- */

/* Masonry by CSS columns. The tiles are real screenshots at their natural
   heights, so forcing a uniform aspect would crop every one of them; columns
   let each keep its own height and the wall stay dense. */
.pf-grid {
  column-count: 4;
  column-gap: 14px;
  margin-bottom: 90px;
}

.pf-card {
  break-inside: avoid;
  margin: 0 0 14px;
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 0.6s var(--enter-ease),
    transform 0.7s var(--enter-ease);
}

.pf-card.is-in {
  opacity: 1;
  transform: none;
}

.pf-card[hidden] {
  display: none;
}

.pf-shot {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: 14px;
  background: #eceef2;
  box-shadow: 0 1px 0 rgba(23, 23, 26, 0.06), 0 14px 30px -26px rgba(15, 23, 42, 0.8);
  transition:
    transform 0.4s var(--enter-ease),
    box-shadow 0.4s ease;
}

.pf-shot img {
  display: block;
  width: 100%;
  height: auto;
}

.pf-card:hover .pf-shot {
  transform: translateY(-4px);
  box-shadow: 0 1px 0 rgba(23, 23, 26, 0.06), 0 26px 46px -26px rgba(15, 23, 42, 1);
}

/* Category chip and the detail panel both stay out of the way until hover —
   the point of the wall is the work, not the labelling. */
.pf-kind {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(12, 12, 16, 0.72);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: #fff;
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0;
  transform: translateY(-6px);
  transition:
    opacity 0.28s ease,
    transform 0.32s var(--enter-ease);
}

.pf-over {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 22px 18px 18px;
  background: linear-gradient(to top, rgba(8, 8, 12, 0.94), rgba(8, 8, 12, 0.6) 60%, transparent);
  opacity: 0;
  transform: translateY(10px);
  transition:
    opacity 0.3s ease,
    transform 0.4s var(--enter-ease);
}

.pf-card:hover .pf-kind,
.pf-card:hover .pf-over {
  opacity: 1;
  transform: none;
}

.pf-over b {
  font-size: 1rem;
  font-weight: 700;
  color: #fff;
  line-height: 1.2;
}

.pf-over em {
  font-style: normal;
  font-size: 0.82rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.82);
}

.pf-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 2px;
}

.pf-tags i {
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.3);
  font-style: normal;
  font-size: 0.62rem;
  font-weight: 600;
  color: #fff;
}

.pf-meta {
  padding: 12px 4px 0;
}

.pf-meta b {
  display: block;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.pf-meta span {
  font-size: 0.78rem;
  color: rgba(23, 23, 26, 0.55);
}

@media (max-width: 1180px) {
  .pf-grid {
    column-count: 3;
  }
}

@media (max-width: 820px) {
  .pf-grid {
    column-count: 2;
  }
}

/* -- closing CTA + footer -- */

.pf-cta {
  max-width: 640px;
  margin: 0 auto 90px;
  text-align: center;
}

.pf-cta h2 {
  margin: 0;
  font-size: clamp(1.6rem, 3.6vw, 2.4rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
}

.pf-cta p {
  margin: 14px 0 26px;
  font-size: 0.98rem;
  color: rgba(23, 23, 26, 0.68);
}

.pf-cta-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 16px 30px;
  border-radius: 999px;
  background: #101014;
  color: #fff;
  font-size: 0.9rem;
  font-weight: 700;
  text-decoration: none;
  box-shadow: 0 14px 30px -18px rgba(0, 0, 0, 0.9);
  transition:
    background-color 0.22s ease,
    transform 0.22s var(--enter-ease);
}

.pf-cta-btn:hover {
  background: var(--nav-accent);
  transform: translateY(-2px);
}

.pf-cta-btn svg {
  width: 16px;
  height: 16px;
}

.pf-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  max-width: 1180px;
  margin: 0 auto;
  padding: 26px 24px 40px;
  border-top: 1px solid rgba(23, 23, 26, 0.1);
  font-size: 0.82rem;
  color: rgba(23, 23, 26, 0.6);
}

.pf-foot a {
  color: #17171a;
  font-weight: 600;
  text-decoration: none;
}

.pf-foot a:hover {
  color: var(--nav-accent);
}

@media (max-width: 640px) {
  .pf-main {
    padding-left: 16px;
    padding-right: 16px;
  }

  .pf-filters {
    width: 100%;
    justify-content: flex-start;
    overflow-x: auto;
    flex-wrap: nowrap;
    border-radius: 18px;
  }

  .pf-grid {
    grid-template-columns: 1fr;
  }
}

/* ----------------------------------------------------- dev tune panel -- */
/* Delete this block together with the tune-panel code in js/main.js. */

#tune-panel {
  position: fixed;
  top: 78px;
  left: 16px;
  z-index: 100;
  width: 236px;
  max-height: calc(100vh - 100px);
  overflow-y: auto;
  display: grid;
  gap: 6px;
  padding: 12px;
  border-radius: 10px;
  background: rgba(20, 20, 20, 0.93);
  color: #fff;
  font-size: 11px;
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
}

#tune-panel.is-hidden {
  display: none;
}

#tune-panel strong {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.55;
}

#tune-panel label {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 8px;
}

#tune-panel label b {
  font-weight: 500;
  opacity: 0.7;
}

#tune-panel input {
  grid-column: 1 / -1;
  width: 100%;
  accent-color: #fff;
}

#tune-panel button {
  margin-top: 6px;
  padding: 6px;
  border: 0;
  border-radius: 6px;
  background: #fff;
  color: #000;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

/* ------------------------------------------------------ reduced motion -- */

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

/* =============================================================================
   Opening Intro Loader — Sleek Black Background + Logo Zoom In Reveal
   ========================================================================== */

#ngo-intro-loader {
  position: fixed;
  inset: 0;
  z-index: 999999;
  background: #080c14;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1), visibility 0.8s ease;
  pointer-events: all;
}

.ngo-intro-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  animation: ngo-logo-appear 0.9s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.ngo-intro-logo {
  height: clamp(60px, 9vw, 105px);
  width: auto;
  object-fit: contain;
  filter: drop-shadow(0 10px 30px rgba(0, 0, 0, 0.5));
  will-change: transform, opacity, filter;
}

.ngo-intro-ring {
  position: absolute;
  width: clamp(180px, 25vw, 300px);
  height: clamp(180px, 25vw, 300px);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(37, 99, 235, 0.35) 0%, rgba(249, 44, 83, 0.22) 50%, transparent 70%);
  filter: blur(32px);
  animation: ngo-ring-pulse 1.4s ease-in-out infinite alternate;
}

#ngo-intro-loader.is-zooming .ngo-intro-wrap {
  animation: ngo-logo-zoomout 0.9s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

#ngo-intro-loader.is-done {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

@keyframes ngo-logo-appear {
  0% {
    opacity: 0;
    transform: scale(0.6);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes ngo-ring-pulse {
  0% { transform: scale(0.8); opacity: 0.4; }
  100% { transform: scale(1.25); opacity: 1; }
}

@keyframes ngo-logo-zoomout {
  0% {
    opacity: 1;
    transform: scale(1);
    filter: blur(0px);
  }
  30% {
    opacity: 1;
    transform: scale(1.15);
    filter: blur(0px);
  }
  100% {
    opacity: 0;
    transform: scale(5.5);
    filter: blur(20px);
  }
}

/* ============================================================= brand mark ==
   The logo used to sit inside the nav pill at 28px, squeezed between the
   links, where it read as an icon rather than a brand. It now lives in the
   page corner, outside the pill, at a size you can actually read.
   ========================================================================== */

.brand-mark {
  position: fixed;
  top: 12px;
  left: 22px;
  z-index: 25;
  display: block;
  width: clamp(140px, 12.5vw, 196px);
  padding: 10px 14px;
  border-radius: 18px;
  background: transparent;
  transform-origin: top left;
  transition:
    width 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    padding 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    top 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    left 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    background-color 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    backdrop-filter 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}

.brand-mark img {
  display: block;
  width: 100%;
  height: auto;
  transition:
    opacity 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.5s cubic-bezier(0.16, 1, 0.3, 1),
    filter 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}

.brand-mark .brand-mark__scrolled {
  position: absolute;
  top: 50%;
  left: 12px;
  width: calc(100% - 24px);
  transform: translateY(-50%) scale(0.9);
  opacity: 0;
  pointer-events: none;
}

.brand-mark:hover {
  transform: translateY(-2px);
}

/* Scrolled: smooth scale down to match navbar height + glass pill background */
body.is-scrolled .brand-mark {
  top: 14px;
  left: 24px;
  width: clamp(118px, 9.5vw, 146px);
  padding: 6px 12px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.75),
    0 10px 25px -14px rgba(0, 0, 0, 0.5);
}

body.is-scrolled .brand-mark:hover {
  transform: translateY(-2px) scale(1.02);
}

body.is-scrolled .brand-mark .brand-mark__default {
  opacity: 0;
  transform: scale(0.9);
}

body.is-scrolled .brand-mark .brand-mark__scrolled {
  opacity: 1;
  transform: translateY(-50%) scale(1);
}

/* The footer sits on near-black, so it uses the light-on-dark original. */
.ft-logo {
  display: block;
  width: clamp(170px, 17vw, 236px);
  height: auto;
  margin-bottom: 6px;
}

/* Below roughly 1600px a full-width pill reaches the corner and lands under
   the mark. The reserve is applied to BOTH sides so the pill simply gets
   narrower and stays centred, rather than being shoved off-centre. */
@media (max-width: 1600px) {
  .site-header {
    padding-left: calc(clamp(138px, 12.5vw, 196px) + 58px);
    padding-right: calc(clamp(138px, 12.5vw, 196px) + 58px);
  }
}

/* Reserving that space costs the pill width, and eight links stop fitting
   well before the old 860px breakpoint did. Tighten them through the middle
   range, then hand them to the drawer once tightening is not enough. */
@media (max-width: 1400px) {
  .nav-links {
    gap: 0;
  }

  .nav-links a {
    padding: 9px 10px;
    font-size: 0.78rem;
  }
}

@media (max-width: 1120px) {
  .nav-links,
  .nav-btn--cta {
    display: none !important;
  }

  .nav-shell {
    justify-content: flex-end;
    width: auto;
  }
}

@media (max-width: 900px) {
  .site-header {
    display: flex !important;
    justify-content: flex-end !important;
    padding-top: 10px !important;
    padding-right: 12px !important;
    padding-left: 110px !important;
    pointer-events: none !important;
  }

  .nav-shell {
    width: auto !important;
    min-width: unset !important;
    max-width: none !important;
    height: 44px !important;
    padding: 0 6px !important;
    border-radius: 999px !important;
    display: inline-flex !important;
    flex-direction: row !important;
    align-items: center !important;
    justify-content: flex-end !important;
    pointer-events: auto !important;
  }

  .nav-actions {
    display: flex !important;
    flex-direction: row !important;
    align-items: center !important;
    gap: 6px !important;
    flex-wrap: nowrap !important;
    margin: 0 !important;
  }

  .nav-btn {
    width: 36px !important;
    height: 36px !important;
    flex: 0 0 36px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
  }

  .brand-mark {
    top: 10px;
    left: 10px;
    width: 108px;
    padding: 6px 8px;
    border-radius: 14px;
  }

  body.is-scrolled .brand-mark {
    top: 10px;
    left: 8px;
    width: 92px;
    padding: 4px 6px;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
  }

  body.is-scrolled .brand-mark .brand-mark__default {
    opacity: 0;
    transform: scale(0.9);
  }

  body.is-scrolled .brand-mark .brand-mark__scrolled {
    top: 50%;
    left: 6px;
    width: calc(100% - 12px);
    opacity: 1;
    transform: translateY(-50%) scale(1);
  }

  .ft-logo {
    width: 168px;
  }
}
