/* ==========================================================================
   CRUX VISUALS — DESIGN SYSTEM (v2 — cinematic architectural art direction)
   Palette:  ink #0B0B0A (foundation) · ink-soft #17160F (elevated dark panel)
             paper/ivory #F3EEE3 (contrast) · cream #EDE6D6 (light card bg)
             line #DCD5C5 (light) · line-ondark rgba(243,238,227,.14)
             stone → brass #A6875A (sole accent, used sparingly)
             grey #726D63 (text on light) · grey-light #A39D8E (text on dark)
   Type:     Display  — 'Fraunces' (editorial serif)
             Body     — 'Inter'
             Mono     — 'IBM Plex Mono' (drafting / technical labels)
             Mark     — 'Michroma' (wordmark / logo)

   Default foundation is LIGHT (ivory) for readability of dense content —
   the homepage deliberately overrides specific sections to the dark/ink
   foundation via the `.section--dark` utility for a cinematic rhythm.
   The header and footer are dark on every page as a consistent bookend.
   ========================================================================== */

:root {
  --ink: #0B0B0A;
  --ink-soft: #17160F;
  --paper: #F3EEE3;
  --cream: #EDE6D6;
  --line: #DCD5C5;
  --line-ondark: rgba(243, 238, 227, 0.14);
  --stone: #A6875A;      /* sole accent (brass) — use sparingly */
  --grey: #726D63;       /* secondary text on light backgrounds */
  --grey-light: #A39D8E; /* secondary text on dark backgrounds */

  --font-display: 'Fraunces', Georgia, serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono: 'IBM Plex Mono', 'Courier New', monospace;

  --container: 1440px;
  --gutter: clamp(20px, 4vw, 64px);

  --ease-1: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-2: cubic-bezier(0.65, 0, 0.35, 1);

  --dur-s: 0.4s;
  --dur-m: 0.8s;
  --dur-l: 1.4s;
}

/* ---------------------------------- reset ---------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
body, h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
ul, ol { list-style: none; margin: 0; padding: 0; }
a { color: inherit; text-decoration: none; }
img, video { max-width: 100%; display: block; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; padding: 0; }
input, textarea, select { font: inherit; color: inherit; }
svg { display: block; }
[hidden] { display: none !important; }

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

body.lock-scroll { overflow: hidden; height: 100vh; }

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* ---------------------------------- type ---------------------------------- */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1.05;
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--grey);
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.eyebrow::before {
  content: '';
  width: 22px;
  height: 1px;
  background: var(--stone);
  display: inline-block;
}

.h-display {
  font-size: clamp(40px, 7vw, 92px);
  font-optical-sizing: auto;
}
.h-section {
  font-size: clamp(30px, 4.2vw, 54px);
}
.h-sub {
  font-size: clamp(22px, 2.6vw, 32px);
}

.lede {
  font-size: clamp(16px, 1.4vw, 19px);
  color: var(--grey);
  max-width: 46ch;
  line-height: 1.6;
}

.mono-label {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  color: var(--grey);
  text-transform: uppercase;
}

/* ---------------------------------- layout ---------------------------------- */
.wrap {
  max-width: var(--container);
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

section { position: relative; }
.section-pad { padding: clamp(72px, 10vw, 148px) 0; }
.hairline { border-top: 1px solid var(--line); }

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gutter);
}
@media (max-width: 860px) {
  .grid-2 { grid-template-columns: 1fr; }
}

/* ---------------------------------- buttons ---------------------------------- */
.btn {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 16px 26px;
  border: 1px solid var(--ink);
  transition: background var(--dur-s) var(--ease-1), color var(--dur-s) var(--ease-1), transform 0.2s var(--ease-1);
  white-space: nowrap;
}
.btn-primary {
  background: var(--ink);
  color: var(--paper);
}
.btn-primary:hover { background: transparent; color: var(--ink); }
.btn-ghost {
  background: transparent;
  color: var(--ink);
}
.btn-ghost:hover { background: var(--ink); color: var(--paper); }
.btn .arrow { transition: transform var(--dur-s) var(--ease-1); }
.btn:hover .arrow { transform: translateX(4px); }

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

/* ---------------------------------- dark-section context ---------------------------------- */
/* Applied to specific homepage sections (hero, services, showcase) to flip
   the foundation to near-black — the cinematic beats in an otherwise light,
   editorial site. Header and footer are dark on every page (see their own
   rules) so these beats always read as part of one continuous system. */
.section--dark {
  background: var(--ink);
  color: var(--paper);
}
.section--dark h1, .section--dark h2, .section--dark h3, .section--dark h4 { color: var(--paper); }
.section--dark .eyebrow { color: var(--grey-light); }
.section--dark .lede { color: var(--grey-light); }
.section--dark .mono-label { color: var(--grey-light); }
.section--dark.hairline, .section--dark .hairline { border-color: var(--line-ondark); }
.section--dark .btn-primary { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.section--dark .btn-primary:hover { background: transparent; color: var(--paper); }
.section--dark .btn-ghost { color: var(--paper); border-color: var(--line-ondark); }
.section--dark .btn-ghost:hover { background: var(--paper); color: var(--ink); }
.section--dark .idx { color: var(--stone); }
.section--dark .service-row { border-color: var(--line-ondark); }
.section--dark .pillar { border-color: var(--line-ondark); }
.section--dark .pillar p { color: var(--grey-light); }

/* ---------------------------------- nav ---------------------------------- */
/* Persistent dark-glass bar on every page, regardless of what's beneath it —
   keeps ivory nav text legible whether it's floating over a dark hero or a
   light inner-page background, without needing per-section contrast logic. */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 500;
  padding: 20px var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: rgba(11, 11, 10, 0.42);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid transparent;
  transition: transform var(--dur-m) var(--ease-1), background var(--dur-s), border-color var(--dur-s);
}
.site-header.is-solid {
  background: rgba(11, 11, 10, 0.82);
  border-bottom: 1px solid var(--line-ondark);
}
.site-header.is-hidden { transform: translateY(-110%); }
.site-header .logo-mark { color: var(--paper); }
.site-header .nav-links a { color: var(--paper); }
.site-header .nav-links a::after { background: var(--paper); }
.site-header .nav-toggle span { background: var(--paper); }
.site-header .nav-controls__label { color: var(--paper); }

/* Header logo — the actual CRUX VISUALS wordmark artwork (real vector
   paths, see the inline <svg> in index.html), not a font recreation.
   Scoped to the header only; the larger footer logo-mark is unaffected
   and keeps its own text-based treatment. */
.site-header .logo-mark {
  display: flex;
  align-items: center;
}
.site-header .logo-mark__svg {
  width: 118px;
  height: auto;
  display: block;
  fill: var(--paper);
}

.logo-mark {
  font-family: 'Michroma', var(--font-body), sans-serif;
  font-size: 13.5px;
  letter-spacing: 0.03em;
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.logo-mark .mark-dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--stone);
  display: inline-block;
  transform: translateY(-5px);
}

/* Full desktop link row kept in the DOM (real internal links, no-JS/SEO
   fallback) but not shown — the header now always uses the minimal
   Menu / two-stroke / four-dot control group below, at every breakpoint. */
.nav-desktop { display: none; }
.nav-links { display: flex; gap: 34px; }
.nav-links a {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  position: relative;
  padding-bottom: 4px;
}
.nav-links a::after {
  content: '';
  position: absolute; left: 0; bottom: 0;
  width: 0; height: 1px;
  background: var(--ink);
  transition: width var(--dur-s) var(--ease-1);
}
.nav-links a:hover::after, .nav-links a.is-active::after { width: 100%; }

.nav-controls {
  display: flex;
  align-items: center;
  gap: 18px;
}
.nav-controls__label {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Two-stroke control — opens the existing nav overlay (.mobile-menu).
   Two horizontal strokes of DIFFERENT lengths, stacked with their right
   edges flush: shorter stroke on top, longer stroke below. */
.nav-toggle {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 5px;
  z-index: 900;
  position: relative;
}
.nav-toggle span {
  height: 1px;
  background: var(--ink);
  display: block;
  transition: transform var(--dur-s) var(--ease-1), opacity var(--dur-s);
}
.nav-toggle span:first-child { width: 12px; }
.nav-toggle span:last-child { width: 20px; }

/* Close/X control — inner pages only (see about/services/contact/work
   pages). Lives inside .nav-controls, right after the hamburger. Since
   the whole .site-header is position:fixed, this sits fixed with it
   automatically (vertically centered in the header, true top-right,
   visible while scrolling) with no extra positioning of its own. Same
   thin two-stroke X visual as the menu overlay's own close control
   (.mobile-menu__close), in the header's paper color for the same
   contrast the hamburger already has. margin-left adds extra breathing
   room beyond .nav-controls' own 18px gap (shared with the homepage's
   Menu/hamburger/four-dot cluster, so left untouched) — 18+10=28px
   between the hamburger and the X specifically, without affecting that
   shared gap anywhere else. */
.page-close {
  position: relative;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  margin-left: 10px;
  cursor: pointer;
}
.page-close span {
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1px;
  background: var(--paper);
}
.page-close span:first-child { transform: rotate(45deg); }
.page-close span:last-child { transform: rotate(-45deg); }

/* Four-dot circular control — separate from the two-stroke toggle above;
   opens the contact/details panel (.details-panel). */
.details-toggle {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: repeat(2, 1fr);
  place-items: center;
  gap: 4px;
  width: 34px;
  height: 34px;
  padding: 9px;
  border-radius: 50%;
  background: var(--paper);
  z-index: 900;
  flex-shrink: 0;
}
.details-toggle span {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--ink);
  display: block;
}

.mobile-menu {
  position: fixed;
  inset: 0;
  background: var(--ink);
  color: var(--paper);
  z-index: 800;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 110px var(--gutter) 40px;
  transform: translateY(-100%);
  transition: transform var(--dur-m) var(--ease-2);
  overflow-y: auto;
}
.mobile-menu.is-open { transform: translateY(0); }

.mobile-menu__body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 40px;
  flex: 1;
  min-height: 0;
}
.mobile-menu__nav { flex: 0 1 auto; }
.mobile-menu-links { display: flex; flex-direction: column; gap: 6px; }
.mobile-menu-links a {
  font-family: var(--font-display);
  font-size: clamp(38px, 8vw, 64px);
  padding: 10px 0;
  display: inline-block;
  opacity: 0;
  transform: translateY(24px);
}
.mobile-menu.is-open .mobile-menu-links a { opacity: 1; transform: translateY(0); transition: opacity .6s var(--ease-1), transform .6s var(--ease-1); }
.mobile-menu-links a:nth-child(1) { transition-delay: .08s; }
.mobile-menu-links a:nth-child(2) { transition-delay: .14s; }
.mobile-menu-links a:nth-child(3) { transition-delay: .20s; }
.mobile-menu-links a:nth-child(4) { transition-delay: .26s; }
.mobile-menu-links a:nth-child(5) { transition-delay: .32s; }

/* Right column — the house is sized/placed via this flex column (this
   is what produced the approved scale/position: matches
   desktop-menu-reference.png). The social row is a separate sibling,
   positioned independently (absolute, see #mobile-menu-social-content
   below) — not centered under the house. */
.mobile-menu__visual {
  flex: 1 1 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  align-self: flex-end;
}

/* Client-supplied architectural artwork (crux-menu-architecture-dark.png),
   used unedited. Purely decorative (aria-hidden). */
.mobile-menu__illustration {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-width: 0;
  opacity: 0;
  transform: translateX(16px);
  transition: opacity .8s var(--ease-1), transform .8s var(--ease-1);
  transition-delay: .3s;
}
.mobile-menu.is-open .mobile-menu__illustration { opacity: 1; transform: translateX(0); }
.mobile-menu__illustration img {
  width: auto;
  height: auto;
  max-width: 1500px;
  max-height: 72vh;
  /* Content-aware background removal (see the #cx-dark-cutout SVG
     filter in index.html) — no vignette, feather, glow, or crop mask. */
  filter: url(#cx-dark-cutout);
}
@media (max-width: 900px) {
  .mobile-menu__illustration { display: none; }
  /* Once the illustration/social column is hidden above, .mobile-menu__body
     has only the nav list left in it — but it still had flex:1 and
     align-items:center from the desktop layout (which vertically centers
     the nav + visual as one balanced block). With no visual column to
     balance against, that centered nav was overflowing symmetrically
     above and below its allotted box, bleeding down into the contact
     footer below it. On mobile the nav and footer now simply stack
     top-to-bottom at their natural size instead — .mobile-menu's
     existing overflow-y:auto scrolls the whole overlay on the shortest
     screens rather than letting content overlap. */
  .mobile-menu { justify-content: flex-start; }
  .mobile-menu__body { flex: 0 0 auto; align-items: flex-start; }
}

/* Same fix as above, but keyed on available height rather than width —
   on a short laptop viewport the desktop layout (illustration + nav,
   centered as one block via .mobile-menu__body's align-items:center)
   can be taller than the space left after the "Call Our Office" footer,
   now that the footer runs two phone numbers over multiple lines. When
   that happens the centered block overflows symmetrically and bleeds
   into the footer below it, same failure mode as the narrow-width case.
   Stacking from the top and letting .mobile-menu's own overflow-y:auto
   scroll the overlay avoids it without touching the wide/tall desktop
   layout at all. */
@media (min-width: 901px) and (max-height: 800px) {
  .mobile-menu { justify-content: flex-start; }
  .mobile-menu__body { flex: 0 0 auto; align-items: flex-start; }
}

.mobile-menu-foot {
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid rgba(243, 238, 227, 0.14);
  display: flex;
  flex-direction: column;
  gap: 26px;
}
/* Desktop only (≥901px, where the social row lives under the
   architectural visual instead of here): compensates the footer's
   on-screen position for the social row's absence from this container.
   .mobile-menu uses justify-content:space-between, so a shorter footer
   here means a taller body above it, which would otherwise push this
   whole block (border + contact text) further down than the approved
   desktop position. On mobile the social row IS back in this container
   (below), so no compensation is needed there. */
@media (min-width: 901px) {
  .mobile-menu-foot { padding-bottom: 78px; }
}
.mobile-menu-foot__info {
  display: flex;
  flex-wrap: wrap;
  gap: 24px 48px;
}
.mobile-menu-foot__col {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--grey-light);
}
.mobile-menu-foot__col h5 {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--grey-light);
  margin-bottom: 10px;
  font-weight: 400;
}
.mobile-menu-foot__col a,
.mobile-menu-foot__col p {
  display: block;
  color: var(--paper);
  margin-bottom: 4px;
}
/* Two individually-clickable phone numbers on one line (e.g. "India :
   +91 ... / +91 ..."), matching the single-link layout it replaced. */
.mobile-menu-foot__col .phone-line {
  display: block;
  margin-bottom: 4px;
  color: var(--paper);
}

/* Large circular social buttons — own row, generous spacing, monochrome. */
.mobile-menu-foot__social { display: flex; flex-wrap: wrap; gap: 16px; }

/* The copy of this row that sits in the lower-right of the desktop menu,
   vertically aligned with the "FIND US" address line (below the
   divider, on the right side). Positioned independently of the house
   image (absolute, relative to .mobile-menu). */
#mobile-menu-social-content {
  position: absolute;
  left: 68%;
  bottom: 129px;
  /* Wider than the base .mobile-menu-foot__social gap (16px, still used
     by the mobile copy of this row) — desktop-only, more breathing room
     between circles per the reference. */
  gap: 26px;
  opacity: 0;
  transform: translateX(16px);
  transition: opacity .8s var(--ease-1), transform .8s var(--ease-1);
  transition-delay: .38s;
}
.mobile-menu.is-open #mobile-menu-social-content { opacity: 1; transform: translateX(0); }
/* Mobile (≤900px, same breakpoint the architectural visual hides at):
   the visual-column copy has no room and would otherwise get squeezed
   into an overlapping grid next to the nav, so it's hidden in favor of
   the footer copy below the contact info — the approved mobile layout.
   Desktop (≥901px) is the reverse: the footer copy is hidden in favor
   of this one under the visual, the approved desktop layout. */
@media (max-width: 900px) {
  #mobile-menu-social-content { display: none; }
}
@media (min-width: 901px) {
  #mobile-menu-social-mobile { display: none; }
}
/* On the same short laptop heights the nav-menu overlap fix above
   already targets, the desktop social row above (independently
   bottom-anchored to the whole overlay, not to the footer) no longer
   lines up with the footer beneath it once the footer runs taller —
   it ends up floating away from both the illustration and the footer
   content instead of reading as part of either. Showing the existing
   footer-embedded copy of the same row instead — already laid out and
   styled correctly for that context on mobile — keeps the icons
   genuinely inside the footer without moving anything by hand, and
   without touching the illustration's normal size or position. */
@media (min-width: 901px) and (max-height: 800px) {
  #mobile-menu-social-content { display: none; }
  #mobile-menu-social-mobile { display: flex; }
  /* .mobile-menu-foot__info and #mobile-menu-social-mobile are siblings
     appended in that order (see renderMenuFooter() in contact-config.js);
     switching this container to a row lets the social icons sit as a
     fourth column to the right of "Find Us" instead of stacking below
     the info row, matching the approved footer layout. */
  .mobile-menu-foot {
    padding-bottom: 40px;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
  }
}
.mobile-menu-foot__social a {
  width: 52px;
  height: 52px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1px solid rgba(243, 238, 227, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--paper);
  transition: background var(--dur-s) var(--ease-1), color var(--dur-s) var(--ease-1), border-color var(--dur-s) var(--ease-1);
}
.mobile-menu-foot__social a svg { width: 20px; height: 20px; }
.mobile-menu-foot__social-glyph {
  font-family: var(--font-mono);
  font-size: 15px;
  letter-spacing: 0.01em;
}
.mobile-menu-foot__social a:hover {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--paper);
}

/* X close control — belongs only to the open nav overlay. Separate element
   from the header's own two-stroke icon, which never changes shape. */
.mobile-menu__close {
  position: absolute;
  top: 20px;
  right: var(--gutter);
  width: 22px;
  height: 22px;
  z-index: 810;
}
.mobile-menu__close span {
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1px;
  background: var(--paper);
}
.mobile-menu__close span:first-child { transform: rotate(45deg); }
.mobile-menu__close span:last-child { transform: rotate(-45deg); }

/* ---------------------------------- menu shutter transition ---------------------------------- */
/* Six full-height vertical panels that sweep in/out before the nav overlay
   (.mobile-menu, z-index 800) opens/closes — above the first page and
   header (z-index 500) but below the overlay's own content. Inert by
   default (pointer-events:none, hidden); JS toggles .is-active only for
   the duration of the transition itself. */
.menu-shutter {
  position: fixed;
  inset: 0;
  z-index: 750;
  pointer-events: none;
  visibility: hidden;
}
.menu-shutter.is-active {
  pointer-events: auto;
  visibility: visible;
}
.menu-shutter__panel {
  position: fixed;
  top: 0;
  height: 100vh;
  /* 1px wider than an exact sixth so adjoining panels overlap slightly —
     removes any hairline seam from sub-pixel rounding. */
  width: calc(100% / 6 + 1px);
  /* Same off-white/cream used by the logo — deliberately NOT the same
     black as the page/menu, so the sweep reads as a clearly visible
     black → cream → black transition rather than blending in. */
  background: var(--paper);
  /* Each panel stays pinned to its own fixed column (position/width never
     change) and is revealed by growing horizontally from its own left
     edge — bounded strictly within its own sixth of the screen, so it
     can never bleed into a neighboring column or merge into one block.
     Height is always the full 100vh, so there is no vertical staircase;
     only the horizontal fill (a clean, self-contained wipe per column)
     varies, staggered left to right. */
  transform: scaleX(0);
  transform-origin: left;
}
.menu-shutter__panel:nth-child(1) { left: calc(100% / 6 * 0); }
.menu-shutter__panel:nth-child(2) { left: calc(100% / 6 * 1); }
.menu-shutter__panel:nth-child(3) { left: calc(100% / 6 * 2); }
.menu-shutter__panel:nth-child(4) { left: calc(100% / 6 * 3); }
.menu-shutter__panel:nth-child(5) { left: calc(100% / 6 * 4); }
.menu-shutter__panel:nth-child(6) { left: calc(100% / 6 * 5); }

/* ---------------------------------- details panel (four-dot control) ---------------------------------- */
/* Right-side slide-in, ~25% of the viewport — NOT a full-screen overlay,
   so the page stays visible behind it. Subtle grid texture over the same
   dark --ink fill keeps the existing panel/menu visual language. */
.details-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 25vw;
  min-width: 340px;
  max-width: 460px;
  background-color: var(--ink);
  background-image:
    linear-gradient(rgba(243, 238, 227, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(243, 238, 227, 0.05) 1px, transparent 1px);
  background-size: 36px 36px;
  color: var(--paper);
  z-index: 800;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 90px 40px 40px;
  box-shadow: -30px 0 60px rgba(0, 0, 0, 0.35);
  transform: translateX(100%);
  transition: transform var(--dur-m) var(--ease-2);
  overflow-y: auto;
}
.details-panel.is-open { transform: translateX(0); }
.details-panel__inner {
  display: flex;
  flex-direction: column;
  gap: 40px;
}
.details-panel__col h4 {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--grey-light);
  margin-bottom: 14px;
}
.details-panel__col a,
.details-panel__col p {
  display: block;
  font-family: var(--font-body);
  font-size: 17px;
  margin-bottom: 6px;
  color: var(--paper);
}
/* Two individually-clickable phone numbers on one line, matching the
   single-link layout it replaced. */
.details-panel__col .phone-line {
  display: block;
  font-family: var(--font-body);
  font-size: 17px;
  margin-bottom: 6px;
  color: var(--paper);
}
.phone-line a.phone-link {
  display: inline;
  margin-bottom: 0;
}
.details-panel__close {
  position: absolute;
  top: 20px;
  right: 40px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--grey-light);
}
.details-panel__close:hover { color: var(--paper); }
@media (max-width: 760px) {
  /* 25% would be unusably narrow on phones — take most of the width
     instead, same slide-from-right panel, same content/layout. */
  .details-panel { width: 86vw; min-width: 0; max-width: none; padding: 90px 28px 32px; }
}

/* ---------------------------------- logo hero (first 100vh page) ---------------------------------- */
.site-header { opacity: 1; transition: transform var(--dur-m) var(--ease-1), background var(--dur-s), border-color var(--dur-s); }

/* The first full-viewport section of the homepage: a large, continuously
   looping CRUX VISUALS mark animation. Sits in normal document flow (not
   an overlay) — the visitor leaves it by scrolling down to the next
   section, same as any other full-height section. */
.logo-hero {
  position: relative;
  width: 100vw;
  height: 100vh;
  min-height: 100vh;
  background: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* Phase 02-03 — a small point that expands into a drafting reticle,
   before the construction lines appear. */
.intro-reticle {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  pointer-events: none;
}
.intro-reticle-dot {
  position: absolute;
  width: 8px;
  height: 8px;
  margin: -4px 0 0 -4px;
  border-radius: 50%;
  background: var(--paper);
  opacity: 0;
}
.intro-reticle-ring {
  position: absolute;
  width: 90px;
  height: 90px;
  margin: -45px 0 0 -45px;
  border: 1px solid var(--paper);
  border-radius: 50%;
  opacity: 0;
  transform: scale(0.3);
}
.intro-reticle-ring::before,
.intro-reticle-ring::after {
  content: '';
  position: absolute;
  background: var(--paper);
}
.intro-reticle-ring::before { top: 50%; left: -16px; right: -16px; height: 1px; transform: translateY(-0.5px); }
.intro-reticle-ring::after { left: 50%; top: -16px; bottom: -16px; width: 1px; transform: translateX(-0.5px); }

/* Phase 01 — the void: near-invisible construction lines, faint white on black */
.intro-void { position: absolute; inset: 0; pointer-events: none; }
.intro-void-line { position: absolute; background: var(--paper); opacity: 0; }
.intro-void-line--h { top: 42%; left: 10%; right: 10%; height: 1px; }
.intro-void-line--v { left: 50%; top: 20%; bottom: 20%; width: 1px; }

.intro-stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  transform-origin: 50% 50%;
  perspective: 900px;
}

/* One SVG (viewBox 0 0 1080 660) holds the real vector logo: dot symbol,
   wordmark and tagline together, exactly as authored — no reconstruction. */
.intro-master-svg {
  /* viewBox is tightly cropped to the artwork itself (see index.html), so
     this width maps almost directly to the visible logo's own width —
     not a loosely-padded bounding box. */
  width: min(900px, 90vw, 160vh);
  height: auto;
  display: block;
  overflow: visible;
  transform-style: preserve-3d;
}
.dot-wrap path,
.intro-symbol-group path,
.intro-wordmark-group path {
  fill: var(--paper);
}
.intro-tagline-group path {
  fill: var(--grey-light);
}

/* Phase 05 — a literal light sweep across the assembled mark: a narrow,
   soft-light-blended reflection streak, closer to a controlled reflection
   passing over a precision-machined surface than a glow or bloom effect. */
.intro-sheen {
  position: absolute;
  top: -30%;
  left: -70%;
  width: 16%;
  height: 220%;
  background: linear-gradient(100deg, transparent 0%, rgba(243, 238, 227, 0.55) 48%, rgba(243, 238, 227, 0.55) 52%, transparent 100%);
  transform: skewX(-18deg) translateX(0);
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: soft-light;
  z-index: 3;
}

/* Each letter is a <g> (one or more real vector paths); clip-path
   percentages need to resolve against the letter's own geometry (fill-box),
   not the whole SVG viewport, for a true per-letter wipe. */
.intro-letter {
  clip-path: inset(0 100% 0 0);
  transform-box: fill-box;
}

/* Tagline reveals as one unit (quotes, letters and its own small accent
   marks together) — deliberately subtler than the letter-by-letter
   wordmark wipe, per the brief. */
.intro-tagline-group {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: 50% 50%;
}

.intro-skip {
  position: absolute;
  bottom: 32px;
  right: var(--gutter);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--grey-light);
  padding: 10px 8px;
  opacity: 0;
  z-index: 10;
  animation: fadeIn 0.4s 0.25s var(--ease-1) forwards;
}
.intro-skip:hover { color: var(--paper); }
@keyframes fadeIn { to { opacity: 1; } }

/* Reduced motion: everything present immediately, no wipes, no scatter */
@media (prefers-reduced-motion: reduce) {
  .intro-skip { opacity: 1; animation: none; }
  .intro-letter { clip-path: inset(0 0 0 0); }
  .intro-tagline-group { opacity: 1; }
  .dot-wrap { transform: none !important; opacity: 1 !important; }
  .intro-sheen { display: none; }
}

/* ---------------------------------- hero (cinematic, dark) ---------------------------------- */
.hero {
  min-height: 100vh;
  min-height: 100svh; /* avoids mobile browser-chrome jump on load */
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-top: 140px;
  padding-bottom: 64px;
  position: relative;
  overflow: hidden;
}
@media (max-width: 640px) {
  .hero { min-height: 92svh; padding-top: 120px; padding-bottom: 48px; }
}
.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}
.hero-media .render-placeholder { height: 100%; aspect-ratio: auto; }
.hero-media .render-placeholder img {
  animation: hero-kenburns 22s ease-out forwards;
  object-position: center 78%;
}
@media (max-width: 760px) {
  .hero-media .render-placeholder img { object-position: center 66%; }
}
@keyframes hero-kenburns {
  from { transform: scale(1.1); }
  to { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-media .render-placeholder img { animation: none; }
}
/* Tint + vignette so ivory headline type stays legible over any image */
.hero-media::before {
  content: '';
  position: absolute; inset: 0;
  background: rgba(11, 11, 10, 0.38);
  z-index: 1;
}
.hero-media::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(11,11,10,0.22) 0%, rgba(11,11,10,0.1) 32%, rgba(11,11,10,0.55) 78%, rgba(11,11,10,0.92) 100%);
  z-index: 1;
}

/* Subtle architectural corner brackets — a faint drafting/viewfinder cue */
.hero::before, .hero::after,
.hero-frame::before, .hero-frame::after {
  content: '';
  position: absolute;
  width: 22px; height: 22px;
  border-color: rgba(243, 238, 227, 0.34);
  z-index: 2;
  pointer-events: none;
}
.hero::before { top: 96px; left: var(--gutter); border-top: 1px solid; border-left: 1px solid; }
.hero::after { top: 96px; right: var(--gutter); border-top: 1px solid; border-right: 1px solid; }
.hero-frame { position: absolute; inset: 0; pointer-events: none; z-index: 2; }
.hero-frame::before { bottom: 24px; left: var(--gutter); border-bottom: 1px solid; border-left: 1px solid; }
.hero-frame::after { bottom: 24px; right: var(--gutter); border-bottom: 1px solid; border-right: 1px solid; }
@media (max-width: 760px) {
  .hero::before, .hero::after, .hero-frame::before, .hero-frame::after { display: none; }
}

.hero-head { max-width: 1040px; position: relative; z-index: 2; }
.hero-kicker {
  font-family: 'Michroma', var(--font-body), sans-serif;
  font-size: clamp(11px, 1.1vw, 13px);
  letter-spacing: 0.28em;
  color: var(--grey-light);
  display: block;
}
.hero-headline {
  margin-top: 20px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(48px, 9vw, 116px);
  line-height: 0.98;
  letter-spacing: -0.01em;
  color: var(--paper);
}
.hero-headline .hero-period { color: var(--stone); }
.hero-sub {
  margin-top: 26px;
  font-size: clamp(16px, 1.5vw, 20px);
  color: var(--grey-light);
  max-width: 42ch;
  line-height: 1.6;
}
.hero-foot {
  position: relative;
  z-index: 2;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 24px;
  margin-top: 48px;
  flex-wrap: wrap;
}
.hero-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--grey-light);
  text-align: right;
}
.hero-meta span { display: block; }
.hero-meta span + span { margin-top: 4px; color: var(--stone); }
@media (max-width: 760px) {
  .hero-foot { align-items: flex-start; }
  .hero-meta { text-align: left; }
}

/* ---------------------------------- placeholders ---------------------------------- */
.render-placeholder {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10;
  background: var(--cream);
  overflow: hidden;
}
.render-placeholder img { width: 100%; height: 100%; object-fit: cover; }
.render-placeholder video { width: 100%; height: 100%; object-fit: cover; }
.render-placeholder .ph-tag {
  position: absolute;
  top: 14px; left: 14px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--stone);
  background: rgba(250,248,244,0.85);
  padding: 5px 9px;
  border: 1px solid var(--line);
}

/* ---------------------------------- selected work ---------------------------------- */
.work-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gutter);
  margin-top: 56px;
}
.work-card { display: block; }
.work-card:nth-child(3n+1) { grid-column: span 2; }
.work-card .render-placeholder { aspect-ratio: 16/9; }
.work-card:nth-child(3n+1) .render-placeholder { aspect-ratio: 21/9; }
.work-card figcaption {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: 18px;
  gap: 16px;
}
.work-card h3 { font-size: clamp(20px, 2vw, 26px); font-weight: 400; }
.work-card .work-cat { font-family: var(--font-mono); font-size: 11px; letter-spacing: .08em; color: var(--grey); text-transform: uppercase; white-space: nowrap; }
.work-card .ph-wrap { overflow: hidden; position: relative; }
.work-card .render-placeholder { transition: transform var(--dur-l) var(--ease-1); }
.work-card:hover .render-placeholder { transform: scale(1.035); }
.work-card .view-tag {
  position: absolute;
  top: 16px; right: 16px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper);
  background: rgba(14,14,14,0.72);
  padding: 8px 12px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity var(--dur-s) var(--ease-1), transform var(--dur-s) var(--ease-1);
  pointer-events: none;
}
.work-card:hover .view-tag, .work-card:focus-visible .view-tag { opacity: 1; transform: translateY(0); }
@media (hover: none) {
  .work-card .view-tag { display: none; }
}

/* ---------------------------------- editorial case list (homepage featured work) ---------------------------------- */
.case-list { margin-top: 24px; }
.case-item {
  display: grid;
  grid-template-columns: 38% 62%;
  align-items: center;
  min-height: 66vh;
  border-top: 1px solid var(--line);
}
.case-item:last-child { border-bottom: 1px solid var(--line); }
.case-item.is-reverse { direction: rtl; }
.case-item.is-reverse > * { direction: ltr; }
.case-item__meta {
  padding: 40px var(--gutter);
}
.case-item__index {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--stone);
  letter-spacing: 0.08em;
}
.case-item__cat {
  display: block;
  margin-top: 10px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--grey);
}
.case-item__title {
  margin-top: 18px;
  font-size: clamp(28px, 3.4vw, 46px);
  font-weight: 400;
  max-width: 14ch;
}
.case-item__link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 26px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  padding-bottom: 4px;
  border-bottom: 1px solid var(--ink);
}
.case-item__link .arrow { transition: transform var(--dur-s) var(--ease-1); }
.case-item__link:hover .arrow { transform: translateX(4px); }
.case-item__media {
  display: block;
  height: 66vh;
  overflow: hidden;
  position: relative;
  clip-path: inset(0 0 0 14%);
  transition: clip-path 1.1s var(--ease-1);
}
.case-item.is-visible .case-item__media { clip-path: inset(0 0 0 0%); }
.case-item.is-reverse .case-item__media { clip-path: inset(0 14% 0 0); }
.case-item.is-reverse.is-visible .case-item__media { clip-path: inset(0 0% 0 0); }
@media (prefers-reduced-motion: reduce) {
  .case-item__media, .case-item.is-reverse .case-item__media { clip-path: inset(0); transition: none; }
}
.case-item__media .render-placeholder { height: 100%; aspect-ratio: auto; }
.case-item__media .render-placeholder img { transition: transform 1.1s var(--ease-1); }
.case-item__media:hover .render-placeholder img { transform: scale(1.045); }

@media (max-width: 900px) {
  .case-item, .case-item.is-reverse { grid-template-columns: 1fr; direction: ltr; min-height: auto; }
  .case-item__media { height: 52vh; order: -1; }
  .case-item__meta { padding: 28px var(--gutter) 36px; }
  .case-item__title { max-width: none; }
}

@media (max-width: 760px) {
  .work-grid { grid-template-columns: 1fr; }
  .work-card:nth-child(3n+1) { grid-column: span 1; }
  .work-card:nth-child(3n+1) .render-placeholder { aspect-ratio: 16/10; }
}

/* ---------------------------------- moving project strip ---------------------------------- */
/* Full-bleed, continuously-scrolling image strip. Two identical groups
   sit side by side in the track; animating exactly one group-width to
   the left and looping makes the seam invisible — no jump, no visible
   start/end. */
.marquee-strip {
  position: relative;
  width: 100%;
  overflow: hidden;
  background: var(--ink);
  padding: clamp(28px, 4vw, 48px) 0;
  /* Let vertical page scroll pass through untouched on touch devices;
     horizontal drag/swipe is captured manually in marquee-drag.js. */
  touch-action: pan-y;
}
.marquee-strip__track {
  display: flex;
  width: max-content;
  animation: marquee-scroll 42s linear infinite;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
}
.marquee-strip:hover .marquee-strip__track { animation-play-state: paused; }
.marquee-strip.is-dragging .marquee-strip__track { cursor: grabbing; }
.marquee-strip.is-cursor-active,
.marquee-strip.is-cursor-active .marquee-strip__track { cursor: none; }
.marquee-drag-indicator {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: var(--cream);
  color: var(--ink);
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  pointer-events: none;
  opacity: 0;
  transform: translate(0, 0) translate(-50%, -50%) scale(0.7);
  transition: opacity 0.25s ease, transform 0.25s ease;
  will-change: transform, opacity;
}
.marquee-strip.is-cursor-active .marquee-drag-indicator {
  opacity: 1;
  transform: translate(0, 0) translate(-50%, -50%) scale(1);
}
.marquee-strip.is-dragging .marquee-drag-indicator { opacity: 0; }
.marquee-strip__group {
  display: flex;
  flex-shrink: 0;
}
/* Fixed width (≈6–7 items visible at once on a desktop viewport) and
   height essentially unchanged from before; object-fit:cover keeps each
   image centered so nothing important is cropped from typical
   architectural compositions (subject centered/lower-third), just the
   outer edges. */
.marquee-strip__item {
  position: relative;
  flex-shrink: 0;
  width: clamp(190px, 15vw, 260px);
  height: clamp(260px, 38vw, 440px);
  overflow: hidden;
  background: var(--cream);
}
.marquee-strip__item img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  -webkit-user-drag: none;
  user-select: none;
  -webkit-user-select: none;
  pointer-events: none;
}
@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .marquee-strip__track { animation: none; }
}
@media (max-width: 760px) {
  /* Multiple images visible on mobile too (~2.5–3), not one huge image. */
  .marquee-strip__item { width: clamp(110px, 34vw, 160px); height: clamp(150px, 46vw, 220px); }
  .marquee-strip__track { animation-duration: 30s; }
}

/* ---------------------------------- services ---------------------------------- */
.service-row {
  display: grid;
  grid-template-columns: 90px 1fr 1fr;
  gap: var(--gutter);
  padding: 34px var(--gutter, 0);
  margin: 0 calc(var(--gutter) * -1);
  align-items: baseline;
  transition: background var(--dur-s) var(--ease-1);
  position: relative;
}
.service-row .idx {
  font-family: var(--font-mono);
  color: var(--stone);
  font-size: 14px;
  transition: transform var(--dur-s) var(--ease-1);
}
.service-row h3 {
  font-size: clamp(22px, 2.4vw, 30px);
  font-weight: 400;
  transition: transform var(--dur-s) var(--ease-1), color var(--dur-s) var(--ease-1);
}
.service-row p { color: var(--grey); max-width: 48ch; transition: opacity var(--dur-s) var(--ease-1); }
.section--dark .service-row p { color: var(--grey-light); }
@media (hover: hover) {
  .service-row:hover { background: rgba(166, 135, 90, 0.06); }
  .service-row:hover .idx { transform: translateX(4px); color: var(--stone); }
  .service-row:hover h3 { transform: translateX(8px); }
}
@media (max-width: 760px) {
  .service-row { grid-template-columns: 1fr; gap: 10px; margin: 0; padding: 24px 0; }
}

/* ---------------------------------- showcase (animation/walkthrough) ---------------------------------- */
.showcase {
  position: relative;
  aspect-ratio: 16/8;
  overflow: hidden;
  margin-top: 48px;
}
.showcase .render-placeholder { height: 100%; aspect-ratio: auto; }
.showcase-play {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
}
.play-ring {
  width: 92px; height: 92px;
  border: 1px solid var(--paper);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--paper);
  transition: transform var(--dur-s) var(--ease-1), background var(--dur-s);
}
.showcase:hover .play-ring { transform: scale(1.08); background: rgba(250,248,244,0.1); }

/* ---------------------------------- pillars / why ---------------------------------- */
.pillars {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gutter);
  margin-top: 56px;
}
/* Modifier for a 4-item pillars grid (e.g. About "What Makes Us
   Different") — balanced 2x2 rather than 3-across-with-orphan. */
.pillars--4 { grid-template-columns: repeat(2, 1fr); }
.pillar { border-top: 1px solid var(--line); padding-top: 22px; }
.pillar .idx { font-family: var(--font-mono); font-size: 12px; color: var(--stone); }
.pillar h3 { margin-top: 14px; font-size: 21px; font-weight: 400; }
.pillar p { margin-top: 10px; color: var(--grey); font-size: 15px; }
@media (max-width: 860px) {
  .pillars { grid-template-columns: 1fr; }
}

/* ---------------------------------- global collab ---------------------------------- */
.collab { background: var(--ink); color: var(--paper); }
.collab .eyebrow { color: var(--grey-light); }
.collab .eyebrow::before { background: var(--stone); }
.collab .lede { color: var(--grey-light); }
.collab-grid {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: var(--gutter);
  margin-top: 48px;
  align-items: start;
}
.collab-list { display: flex; flex-direction: column; }
.collab-list li {
  padding: 20px 0;
  border-top: 1px solid var(--line-ondark);
  display: flex;
  gap: 20px;
  align-items: baseline;
}
.collab-list li:last-child { border-bottom: 1px solid var(--line-ondark); }
.collab-list .t { font-family: var(--font-mono); font-size: 12px; color: var(--stone); white-space: nowrap; }
@media (max-width: 860px) { .collab-grid { grid-template-columns: 1fr; } }

/* ---------------------------------- final CTA ---------------------------------- */
.final-cta { text-align: center; padding: clamp(90px, 14vw, 180px) 0; }
.final-cta h2 { max-width: 18ch; margin: 0 auto; }
.final-cta .cta-row { justify-content: center; margin-top: 40px; }

/* ---------------------------------- custom cursor ---------------------------------- */
/* Small ring + dot, smoothed to follow the pointer, expanding with a text
   label over interactive elements. Disabled entirely on touch devices and
   when the browser reports no fine pointer / hover support, or when the
   cursor script hasn't initialised — the native cursor is always the
   fallback, never removed until the custom one is confirmed running. */
/* Minimal circular cursor: a thin cream ring + small dot. mix-blend-mode
   lives on this outer container (not the ring/dot/label themselves) —
   this element is the one that gets transform:translate(...) from
   cursor.js for movement, and a transform creates a new stacking context
   for its children, which would otherwise isolate their blend-mode from
   the actual page and make it invisible. Blending the whole container
   instead makes the cream ring/dot/text invert against whatever sits
   beneath them, so the same color reads correctly on both the light
   Selected Projects section and dark hero/menu areas with no per-section
   overrides. Replaces the previous solid black label pill (rectangular,
   looked out of place over light sections) with plain inverting text,
   keeping the ring's existing expand-on-hover motion. */
.cx-cursor {
  position: fixed;
  top: 0; left: 0;
  width: 0; height: 0;
  pointer-events: none;
  z-index: 9999;
  mix-blend-mode: difference;
}
.cx-cursor__ring {
  position: absolute;
  width: 30px; height: 30px;
  margin: -15px 0 0 -15px;
  border: 1px solid var(--paper);
  border-radius: 50%;
  /* Hard guarantee the ring can never visually become non-circular: the
     label lives inside it (see cursor.js), so however long its text is,
     overflow:hidden clips it to this circle — border-radius:50% always
     wins, no hover state can produce a rectangle/pill. */
  overflow: hidden;
  transition: width 0.28s var(--ease-1), height 0.28s var(--ease-1), margin 0.28s var(--ease-1);
}
.cx-cursor__dot {
  position: absolute;
  width: 5px; height: 5px;
  margin: -2.5px 0 0 -2.5px;
  border-radius: 50%;
  background: var(--paper);
  transition: opacity 0.2s var(--ease-1);
}
.cx-cursor__label {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 46px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.35;
  color: var(--paper);
  /* Wraps onto two lines ("View" / "Project") instead of one long line —
     keeps the circle small instead of growing to fit a wide single line. */
  white-space: normal;
  opacity: 0;
  transition: opacity 0.2s var(--ease-1);
}
/* Small and subtle by default (matches the plain ring + dot, just larger)
   — MENU, nav links and buttons either show no text or a short word, so
   they don't need a big circle. Only the two-line "View Project" label
   gets a touch more room, via its own modifier below. */
.cx-cursor.is-expanded .cx-cursor__ring { width: 64px; height: 64px; margin: -32px 0 0 -32px; }
.cx-cursor.is-expanded.is-cursor-view .cx-cursor__ring { width: 72px; height: 72px; margin: -36px 0 0 -36px; }
/* Center dot stays visible in every state, including hover — it no
   longer fades out when the ring expands/shows a label. */
.cx-cursor.is-expanded .cx-cursor__label { opacity: 1; }
body.cx-cursor-active, body.cx-cursor-active a, body.cx-cursor-active button, body.cx-cursor-active .work-card {
  cursor: none;
}
@media (hover: none), (pointer: coarse) {
  .cx-cursor { display: none !important; }
}
@media (prefers-reduced-motion: reduce) {
  .cx-cursor { display: none !important; }
}

/* ---------------------------------- footer ---------------------------------- */
/* Dark ink bookend on every page, mirroring the header. */
.site-footer {
  background: var(--ink);
  color: var(--paper);
  border-top: 1px solid var(--line-ondark);
  padding: 64px 0 32px;
}
.footer-top {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: var(--gutter);
}
/* Footer wordmark: same authored SVG artwork as the header logo (see
   .site-header .logo-mark__svg), not the plain-text Michroma fallback
   used elsewhere — keeps the footer mark visually identical to the
   real brand mark instead of a font recreation. */
.footer-col .logo-mark--footer { display: block; margin-bottom: 8px; }
.footer-col .logo-mark--footer .logo-mark__svg { width: 150px; height: auto; display: block; fill: var(--paper); }
.footer-col h4 { font-family: var(--font-mono); font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: var(--grey-light); margin-bottom: 16px; }
.footer-col a, .footer-col p { display: block; margin-bottom: 8px; color: var(--paper); font-size: 14px; }
.footer-col a:hover { color: var(--stone); }
.footer-col p { color: var(--grey-light); }
.footer-bottom {
  margin-top: 56px;
  padding-top: 22px;
  border-top: 1px solid var(--line-ondark);
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--grey-light);
  letter-spacing: .04em;
  flex-wrap: wrap;
  gap: 10px;
}
@media (max-width: 860px) {
  .footer-top { grid-template-columns: 1fr 1fr; row-gap: 32px; }
}

/* ---------------------------------- scroll reveal ---------------------------------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.9s var(--ease-1), transform 0.9s var(--ease-1);
}
[data-reveal].is-visible { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* ---------------------------------- page hero (inner pages) ---------------------------------- */
.page-head {
  padding-top: 160px;
  padding-bottom: 56px;
}
.page-head .h-display { margin-top: 20px; }
.page-head .lede { margin-top: 22px; }

/* ---------------------------------- portfolio filters ---------------------------------- */
.filter-bar {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin: 40px 0 8px;
}
.filter-btn {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 10px 18px;
  border: 1px solid var(--line);
  color: var(--grey);
  transition: all var(--dur-s) var(--ease-1);
}
.filter-btn.is-active, .filter-btn:hover { border-color: var(--ink); color: var(--ink); }

.portfolio-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gutter);
  margin-top: 40px;
}
.portfolio-grid .work-card { transition: opacity var(--dur-s) var(--ease-1), transform var(--dur-s) var(--ease-1); }
.portfolio-grid .work-card.is-hidden { display: none; }
@media (max-width: 760px) {
  .portfolio-grid { grid-template-columns: 1fr; }
}

/* ---------------------------------- about ---------------------------------- */
.about-figure { margin-top: 64px; }
.about-quote {
  font-family: var(--font-display);
  font-size: clamp(24px, 3vw, 36px);
  line-height: 1.35;
  max-width: 24ch;
  margin-top: 20px;
}

/* ---------------------------------- contact ---------------------------------- */
.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 100px);
  margin-top: 56px;
}
.field { margin-bottom: 26px; }
.field label {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--grey);
  margin-bottom: 10px;
}
.field input, .field select, .field textarea {
  width: 100%;
  border: none;
  border-bottom: 1px solid var(--line);
  background: transparent;
  padding: 10px 2px;
  font-size: 16px;
  transition: border-color var(--dur-s);
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--ink); }
.field textarea { resize: vertical; min-height: 100px; }
.contact-direct { display: flex; flex-direction: column; gap: 18px; margin-top: 8px; }
.contact-direct a { display: flex; align-items: center; gap: 14px; font-family: var(--font-mono); font-size: 14px; padding: 16px 0; border-bottom: 1px solid var(--line); }
.form-note { margin-top: 18px; font-size: 13px; color: var(--grey); display: none; }
.form-note.is-visible { display: block; }
.form-note.is-error { color: #B3261E; }
@media (max-width: 860px) { .contact-grid { grid-template-columns: 1fr; } }

/* ---------------------------------- project detail page ---------------------------------- */
/* Title/category scaled to match the project-title scale used elsewhere
   on the site (.case-item__title / .case-item__cat on the homepage)
   instead of the larger page-hero .h-display/.eyebrow scale — same font
   family, weight, line-height and letter-spacing (all inherited,
   untouched here), just sized like a project title rather than a page
   headline so it doesn't read heavier than the rest of the site. */
#proj-title { font-size: clamp(28px, 3.4vw, 46px); }
#proj-cat { font-size: 11px; letter-spacing: 0.14em; }
.project-hero-media { margin-top: 24px; }
.project-meta {
  display: flex;
  gap: 48px;
  flex-wrap: wrap;
  margin-top: 32px;
  padding-top: 28px;
  border-top: 1px solid var(--line);
}
.project-meta .m-label { font-family: var(--font-mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--grey); margin-bottom: 6px; }
.project-gallery { display: flex; flex-direction: column; gap: var(--gutter); margin-top: var(--gutter); }
.back-link {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--grey); margin-top: 130px;
}
.back-link:hover { color: var(--ink); }

/* ---------------------------------- back to top ---------------------------------- */
.back-to-top {
  position: fixed;
  right: 24px;
  bottom: 24px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--paper);
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 300;
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity var(--dur-s) var(--ease-1), transform var(--dur-s) var(--ease-1), background var(--dur-s) var(--ease-1);
}
.back-to-top.is-visible { opacity: 1; pointer-events: auto; transform: translateY(0); }
.back-to-top svg { width: 16px; height: 16px; }
.back-to-top:hover { background: var(--ink); color: var(--paper); }
@media (max-width: 760px) {
  .back-to-top { right: 16px; bottom: 16px; width: 38px; height: 38px; }
  .back-to-top svg { width: 14px; height: 14px; }
}
