/* ===========================================================================
 * Moment Architecture — base stylesheet
 * Fonts loaded externally via Adobe Fonts kit kvr4rli.css
 * --------------------------------------------------------------------------
 * Two page templates:
 *   .page--hero  full-bleed media hero only (home, studio, work, thoughts)
 *   .page--doc   hero shrunk to ~viewport, content beneath, footer (about,
 *                contact, recognition, more, thoughts/<post>, work/<slug>)
 * ========================================================================*/

:root {
  --c-bg: #ffffff;
  --c-fg: #1a1a1a;
  --c-fg-muted: rgba(26, 26, 26, 0.55);
  --c-fg-faint: rgba(26, 26, 26, 0.30);
  --c-rule:    rgba(26, 26, 26, 0.10);

  --c-on-hero:        #ffffff;
  --c-on-hero-muted:  rgba(255, 255, 255, 0.62);
  --c-on-hero-faint:  rgba(255, 255, 255, 0.35);

  --c-footer-bg: #1a1a1a;
  --c-footer-fg: #ffffff;
  --c-button-bg: #1a1a1a;
  --c-button-fg: #ffffff;

  /* Client decision 2026-05-21: BC Alphapipe is no longer used for any text;
   * the only brand mark is the header logo PNG. All text uses Avenir Next. */
  --font-display: "avenir-next-lt-pro", "Avenir Next", "Avenir", system-ui, sans-serif;
  --font-body:    "avenir-next-lt-pro", "Avenir Next", "Avenir", system-ui, sans-serif;
  --font-meta:    "avenir-next-lt-pro", "Avenir Next", "Avenir", system-ui, sans-serif;

  /* Sizes match the live momentarch.ca exactly at 1440 viewport (measured
   * via Playwright). Clamp lower bounds handle mobile; the upper bound
   * is always the live's measured pixel value so desktop is pixel-faithful. */
  --fs-display:    clamp(40px, 4.87vw, 70px);  /* home "Moment Architecture" */
  --fs-h1:         clamp(28px, 2.78vw, 40px);  /* page--doc hero title */
  --fs-hero-eyebrow: clamp(20px, 2.08vw, 30px); /* "We Are" */
  --fs-hero-sublink: clamp(20px, 2.08vw, 30px); /* Work / Studio / Thoughts list */
  --fs-menu:       clamp(28px, 2.78vw, 40px);  /* off-canvas menu items */
  --fs-h2:         clamp(24px, 2.4vw, 34px);
  --fs-h3:         17px;                       /* matches live "ABOUT MY WORK" */
  --fs-body:       16px;
  --fs-small:      14px;
  --fs-meta:       12px;
  --ls-display:    0.029em;  /* ≈2px on 70px */
  --ls-menu:       0.045em;  /* ≈1.8px on 40px */

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 16px;
  --space-4: 24px;
  --space-5: 40px;
  --space-6: 64px;
  --space-7: 96px;
  --space-8: 128px;
  --space-9: 160px;

  --pad-x:       clamp(20px, 4vw, 56px);
  --pad-y-hero:  clamp(40px, 6vw, 80px);

  --max-narrow: 640px;
  --max-text:   720px;
  --max-wide:   1200px;
  --max-edge:   1600px;

  --header-h: 120px;

  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --t-fast:  200ms;
  --t-med:   400ms;
  --t-slow:  800ms;
  --t-xslow: 1400ms;
}

/* ---- reset ---- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.55;
  color: var(--c-fg);
  background: var(--c-bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, h4, h5, h6, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, video, picture { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
input, textarea { font: inherit; color: inherit; }

::selection { background: var(--c-fg); color: var(--c-bg); }

/* ===========================================================================
 *  Site header (sticky, transparent over hero, solid over content)
 * ========================================================================*/

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--pad-x);
  color: var(--c-on-hero);
  pointer-events: none;
  transition: background-color var(--t-med) var(--ease-out),
              color var(--t-med) var(--ease-out);
}
.site-header > * { pointer-events: auto; }

.site-header.is-light { color: var(--c-fg); }
.site-header.is-solid {
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--c-fg);
  border-bottom: 1px solid var(--c-rule);
}

/* Hamburger toggle */
.menu-toggle {
  --bar-w: 26px;
  --bar-h: 1.5px;
  width: 44px;
  height: 44px;
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 6px;
  margin-left: -10px;
  border-radius: 4px;
  transition: opacity var(--t-fast);
}
.menu-toggle:hover { opacity: 0.7; }
.menu-toggle span {
  display: block;
  width: var(--bar-w);
  height: var(--bar-h);
  background: currentColor;
  transition: transform var(--t-med) var(--ease-out),
              opacity var(--t-fast),
              width var(--t-med) var(--ease-out);
}
.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7.5px) rotate(45deg); width: var(--bar-w); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }

/* Brand wordmark — top-right */
.brand {
  display: inline-flex;
  align-items: center;
  transition: opacity var(--t-fast);
}
.brand:hover { opacity: 0.75; }
.brand-logo {
  display: block;
  width: 220px;
  height: 88px;
  background: url("/assets/logo-white.svg") right center / contain no-repeat;
  transition: opacity var(--t-fast);
}
/* When the header sits on a light background (scrolled past the hero into the
 * solid fixed menu bar, OR the white off-canvas menu is open), swap the same
 * logo element's artwork to the black version. */
.site-header.is-solid .brand-logo,
.site-header.is-light .brand-logo,
body.has-menu-open .brand-logo { background-image: url("/assets/logo-black.svg"); }
/* When menu is open the header sits over the white off-canvas — flip the
 * hamburger / close button color to dark too. */
body.has-menu-open .site-header { color: #1a1a1a; }

@media (max-width: 720px) {
  .brand-logo { width: 160px; height: 64px; }
}

/* ===========================================================================
 *  Off-canvas menu (full-screen overlay)
 * ========================================================================*/

/* Off-canvas menu: WHITE background, dark text (matches live momentarch.ca).
 * Open it via the hamburger; close via the same button (now an X) or ESC. */
.off-canvas {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: #ffffff;
  color: #1a1a1a;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t-med) var(--ease-out),
              visibility var(--t-med);
}
.off-canvas.is-open {
  opacity: 1;
  visibility: visible;
}
.off-canvas ul {
  display: flex;
  flex-direction: column;
  gap: 22px;
  text-align: center;
}
.off-canvas li a {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--fs-menu);
  line-height: 1.5;
  letter-spacing: var(--ls-menu);
  color: rgba(26, 26, 26, 0.55);
  transition: color var(--t-med) var(--ease-out),
              transform var(--t-slow) var(--ease-out);
  transform: translateY(20px);
  opacity: 0;
}
.off-canvas.is-open li a {
  opacity: 1;
  transform: translateY(0);
}
.off-canvas.is-open li:nth-child(1) a { transition-delay:  80ms; }
.off-canvas.is-open li:nth-child(2) a { transition-delay: 140ms; }
.off-canvas.is-open li:nth-child(3) a { transition-delay: 200ms; }
.off-canvas.is-open li:nth-child(4) a { transition-delay: 260ms; }
.off-canvas.is-open li:nth-child(5) a { transition-delay: 320ms; }
.off-canvas.is-open li:nth-child(6) a { transition-delay: 380ms; }
.off-canvas li a:hover,
.off-canvas li a:focus-visible { color: #1a1a1a; }
.off-canvas li.is-current a    { color: rgba(26, 26, 26, 0.95); }

/* prevent scroll while menu open */
body.has-menu-open { overflow: hidden; }

/* ===========================================================================
 *  Hero (full-bleed media + bottom-left caption)
 * ========================================================================*/

.hero {
  position: relative;
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  color: var(--c-on-hero);
  background: #1a1a1a;
}
.page--doc .hero {
  min-height: clamp(420px, 72vh, 760px);
}

.hero__media,
.hero__media-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.hero__media {
  opacity: 0;
  transition: opacity var(--t-xslow) var(--ease-out);
}
.hero__media.is-ready { opacity: 1; }

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg,
              rgba(0,0,0,0.35) 0%,
              rgba(0,0,0,0.05) 25%,
              rgba(0,0,0,0.05) 60%,
              rgba(0,0,0,0.55) 100%);
  pointer-events: none;
}

/* Hero caption — positioning matches live momentarch.ca exactly.
 *   left: 200px on a 1920 virtual canvas → 10.4vw, capped at 200px.
 *   Top values come from the live slider canvas:
 *     "We Are"             top:709.5 / 1080  ≈ 65.7%
 *     "Moment Architecture" top:769.5
 *     sub-links            top:839.5 / 889.5 / 939.5  (50px stride)
 *   line-height across every element is exactly 58px, which is smaller
 *   than the font-size for the 70px title — letters intentionally overflow
 *   their line-box, that's the live's design intent. */
.hero__caption {
  position: absolute;
  z-index: 2;
  /* left: 200px on 1440 viewport — clamp preferred = 200/1440 ≈ 13.9vw */
  left: clamp(40px, 13.9vw, 240px);
  right: var(--pad-x);
  bottom: var(--pad-y-hero);
  max-width: 1200px;
}
.page--hero .hero__caption {
  top: 56.8%;       /* live: 511/900 at 1440×900 viewport */
  bottom: auto;
  transform: none;
}
.hero__eyebrow {
  font-family: var(--font-body);
  font-size: var(--fs-hero-eyebrow);     /* 30px desktop */
  font-weight: 500;                       /* Avenir Next Medium — matches live */
  line-height: 58px;
  letter-spacing: var(--ls-display);     /* 2px @ 70px ≈ 0.029em */
  color: var(--c-on-hero);
  margin: 0 0 2px 0;                      /* live top stride 60 - lh 58 = 2px */
  opacity: 0;
  transform: translateY(12px);
  animation: rise var(--t-slow) var(--ease-out) 200ms forwards;
}
.hero__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-display);           /* 70px desktop */
  line-height: 58px;                       /* SAME line-height as eyebrow per live */
  letter-spacing: var(--ls-display);
  white-space: nowrap;                     /* live keeps "Moment Architecture" on 1 line */
  margin: 0 0 12px 0;                      /* live top stride 70 - lh 58 = 12px */
  max-width: none;
  opacity: 0;
  transform: translateY(16px);
  animation: rise var(--t-slow) var(--ease-out) 300ms forwards;
}
.page--doc .hero__title {
  font-size: var(--fs-h1);                 /* 40px on inner pages */
  font-weight: 400;
  white-space: normal;
  line-height: 58px;
  margin: 0;
}

/* Inner-page hero titles (Contact / About / Recognition / More etc.).
 * Live serves these as Roboto Medium 500 / 40px / 58px lh / 2px ls.
 * Map Roboto 500 → avenir-next-lt-pro 500 (per font memory).
 *
 * Positioning: Slider Revolution doesn't use % — it uses a formula
 *   top = anchor + 0.5 × viewport_height
 * (verified empirically at 3 viewport heights: 900→721, 1000→771, 1080→811).
 * For Contact the anchor is 271px → CSS: calc(271px + 50vh). This auto-
 * scales correctly across all viewport heights (matches live's 923.5px
 * at 1305-tall viewports). */
body[data-page="contact"] .hero__caption {
  top: calc(271px + 50vh);
  left: clamp(20px, 13.9vw, 200px);   /* live caps at literal 200px, not 240 */
  bottom: auto;
  transform: none;
}
body[data-page="about"]   .hero__caption,
body[data-page="recognition"] .hero__caption,
body[data-page="more"]    .hero__caption,
body[data-page="work-detail"] .hero__caption,
body[data-page="thought-detail"] .hero__caption {
  /* TBD — each page needs its own anchor measured from live. Using
   * Contact's anchor as a placeholder until those measurements land. */
  top: calc(271px + 50vh);
  left: clamp(20px, 13.9vw, 200px);
  bottom: auto;
  transform: none;
}
body[data-page="contact"] .hero__title,
body[data-page="about"]   .hero__title,
body[data-page="recognition"] .hero__title,
body[data-page="more"]    .hero__title,
body[data-page="work-detail"] .hero__title,
body[data-page="thought-detail"] .hero__title {
  font-family: var(--font-display);
  font-size: 40px;
  font-weight: 700;
  line-height: 58px;
  letter-spacing: 0.05em;                    /* 2px on 40px */
  white-space: nowrap;
  margin: 0;
}
/* Branch/detail pages (Work projects + Thoughts articles): render the hero
 * title in all-caps. Done via text-transform so the source text stays
 * proper-case (keeps the hero's aria-label / SEO / copy-paste intact). */
body[data-page="work-detail"] .hero__title,
body[data-page="thought-detail"] .hero__title {
  text-transform: uppercase;
}
/* Work-detail hero titles: rendered in title-case (not all-caps) at 60px
 * desktop / 35px mobile, with the caption nudged 30px higher than the shared
 * anchor. Applies to every Work project page, per client request. */
body[data-page="work-detail"] .hero__caption {
  top: calc(241px + 50vh);   /* 30px higher than the shared 271px anchor */
}
body[data-page="work-detail"] .hero__title {
  font-size: 60px;
  letter-spacing: 0;
  text-transform: none;
}
/* Work-detail pages have an eyebrow above the title ("Work · Multi-family
 * residential") that the other inner pages don't. Tighten it so it pairs
 * cleanly with the 40px project title at the same caption anchor. */
body[data-page="work-detail"] .hero__eyebrow {
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  margin: 0 0 14px 0;
  color: rgba(255, 255, 255, 0.78);
}
@media (max-width: 720px) {
  .hero__title { white-space: normal; line-height: 1.1; }
  /* Inner-page hero titles scale down on mobile to match live (23-26px
   * range, peaking at ~26px around 414w devices). */
  body[data-page="contact"] .hero__title,
  body[data-page="about"] .hero__title,
  body[data-page="recognition"] .hero__title,
  body[data-page="more"] .hero__title,
  body[data-page="work-detail"] .hero__title,
  body[data-page="thought-detail"] .hero__title {
    font-size: clamp(22px, 6.2vw, 26px);
    line-height: 1.2;
    letter-spacing: 0.026em;
    white-space: normal;
  }
  body[data-page="work-detail"] .hero__title {
    font-size: 35px;
    letter-spacing: 0;
    white-space: normal;
  }
  /* Work landing page: nudge the hero caption (Work title + project links)
   * up 30px on mobile only. */
  body[data-page="work"] .hero__caption {
    top: calc(56.8% - 30px);
  }
}
.hero__links {
  display: flex;
  flex-direction: column;
  gap: 0;                                  /* spacing handled by line-height */
  font-family: var(--font-body);
  font-size: var(--fs-hero-sublink);       /* 30px desktop */
  font-weight: 200;                         /* Avenir Next Ultra Light — true thin, matches live's Roboto 100 */
  line-height: 50px;                        /* live's 50px top-to-top stride */
  letter-spacing: var(--ls-display);
}
.hero__links li {
  opacity: 0;
  transform: translateY(10px);
  animation: rise var(--t-slow) var(--ease-out) forwards;
}
.hero__links li:nth-child(1) { animation-delay: 460ms; }
.hero__links li:nth-child(2) { animation-delay: 540ms; }
.hero__links li:nth-child(3) { animation-delay: 620ms; }
.hero__links li:nth-child(4) { animation-delay: 700ms; }
.hero__links li:nth-child(5) { animation-delay: 780ms; }
.hero__links li:nth-child(6) { animation-delay: 860ms; }

.hero__links a {
  display: inline-block;
  color: rgba(255, 255, 255, 0.92);       /* near-white; thinness comes from font-weight 200 now */
  position: relative;
  padding: 0;
  transition: color var(--t-med) var(--ease-out);
}
.hero__links a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-med) var(--ease-out);
}
.hero__links a:hover,
.hero__links a:focus-visible {
  color: var(--c-on-hero);
}
.hero__links a:hover::after,
.hero__links a:focus-visible::after {
  transform: scaleX(1);
}

@keyframes rise {
  to { opacity: 1; transform: translateY(0); }
}

/* Down-scroll arrow */
.hero__scroll {
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: clamp(18px, 3vw, 28px);
  transform: translateX(-50%);
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-on-hero-muted);
  opacity: 0;
  animation: pulse-down 2.4s ease-in-out 1.4s infinite,
             fade-in var(--t-slow) var(--ease-out) 1.2s forwards;
}
.hero__scroll svg { width: 18px; height: 18px; }
.hero__scroll:hover { color: var(--c-on-hero); }
@keyframes pulse-down {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50%      { transform: translateX(-50%) translateY(6px); }
}
@keyframes fade-in { to { opacity: 1; } }

/* Branch/detail heroes (Work projects + Thoughts articles): upgrade the small
 * scroll cue into a larger frosted-glass round button with a gently bobbing
 * arrow. The button stays still; only the arrow inside bobs — feels lighter
 * and more refined than bouncing the whole control. */
body[data-page="work-detail"]   .hero__scroll,
body[data-page="thought-detail"] .hero__scroll {
  width: 60px;
  height: 60px;
  bottom: clamp(24px, 4vw, 44px);
  border: 1.5px solid rgba(255, 255, 255, 0.45);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  color: rgba(255, 255, 255, 0.92);
  /* drop the whole-button pulse; keep only the fade-in entrance */
  animation: fade-in var(--t-slow) var(--ease-out) 1.2s forwards;
  transition: border-color 0.35s var(--ease-out),
              background-color 0.35s var(--ease-out),
              color 0.35s var(--ease-out),
              box-shadow 0.35s var(--ease-out);
}
body[data-page="work-detail"]   .hero__scroll svg,
body[data-page="thought-detail"] .hero__scroll svg {
  width: 24px;
  height: 24px;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  animation: arrow-bob 2.2s ease-in-out 1.6s infinite;
}
body[data-page="work-detail"]   .hero__scroll:hover,
body[data-page="thought-detail"] .hero__scroll:hover {
  border-color: #fff;
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.25);
}
@keyframes arrow-bob {
  0%, 100% { transform: translateY(-3px); }
  50%      { transform: translateY(3px); }
}
@media (prefers-reduced-motion: reduce) {
  body[data-page="work-detail"]   .hero__scroll svg,
  body[data-page="thought-detail"] .hero__scroll svg { animation: none; }
}

/* ===========================================================================
 *  Work-page slide sections — replicates live's 6-slide Slider Revolution
 *  as stacked 100vh sections with background images + project links.
 *  Scroll-snap binds the wheel to one slide per gesture (slider-like feel).
 * ========================================================================*/
/* Work-page header: every slide is a full-bleed dark image, so the
 * header stays transparent + white-logo throughout (don't flip to
 * solid white when scrolled past the first hero). */
body[data-page="work"] .site-header.is-solid,
body[data-page="studio"] .site-header.is-solid,
body[data-page="thoughts"] .site-header.is-solid {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  color: var(--c-on-hero);
  border-bottom: none;
}
body[data-page="work"] .site-header.is-solid .brand-logo,
body[data-page="studio"] .site-header.is-solid .brand-logo,
body[data-page="thoughts"] .site-header.is-solid .brand-logo { background-image: url("/assets/logo-white.svg"); }
/* Disable native scroll-snap on the slide-scroll index pages — JS handler
 * in ma-ui.js takes over with custom cubic-bezier ease for a cinematic feel. */
html:has(body[data-page="work"]),
html:has(body[data-page="studio"]),
html:has(body[data-page="thoughts"]) { scroll-behavior: auto; }
.work-slide {
  position: relative;
  display: block;
  min-height: 100vh;
  min-height: 100svh;
  color: var(--c-on-hero);
  text-decoration: none;
  overflow: hidden;
  isolation: isolate;
}
.work-slide__bg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  z-index: 0;
  filter: brightness(0.92);              /* slight darken for white-text legibility */
}
.work-slide__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
              rgba(0,0,0,0.20) 0%,
              rgba(0,0,0,0.05) 30%,
              rgba(0,0,0,0.55) 100%);
  pointer-events: none;
  z-index: 1;
}
/* Caption matches inner-page hero positioning exactly (Contact / About
 * / Recognition / More): left 200px capped + top = calc(271px + 50vh). */
.work-slide__caption {
  position: absolute;
  z-index: 2;
  left: clamp(20px, 13.9vw, 200px);
  top: calc(271px + 50vh);              /* desktop anchor (unchanged) */
  max-width: 1200px;
  pointer-events: none;
}
.work-slide__title {
  font-family: var(--font-display);
  font-size: 65px;
  font-weight: 700;
  line-height: 58px;
  letter-spacing: 0;
  text-transform: none;                 /* title-case, matches work-detail hero */
  margin: 0;
  white-space: nowrap;
  transform: translateX(0);
  transition: transform 600ms var(--ease-out);
}
.work-slide:hover .work-slide__title,
.work-slide:focus-visible .work-slide__title {
  transform: translateX(8px);
}

@media (max-width: 720px) {
  .work-slide__caption { left: 24px; right: 24px; top: auto; bottom: 110px; }
  .work-slide__title { font-size: 35px; line-height: 1.2; white-space: normal; }
}

/* ===========================================================================
 *  Project detail pages — pixel-faithful replica of live momentarch.ca
 *  Layout (measured at 1440 viewport):
 *    - Outer body  bg #2C2C2C (dark gray, visible above/below content row)
 *    - Content row bg #EBECED (cool light gray)
 *    - Inner column: left padding 113px (7.85vw), max image-row width 1214px
 *    - Spec labels: BC Alphapipe Bold 35px / line-height 42px / stacked
 *    - Spec values + body + tagline + consultant items: Avenir Next 200
 *      16px / line-height 30.08px (≈1.88)
 *    - Spec-to-spec vertical stride: 112px
 *    - Divider: 130px wide solid line
 *    - 3-image row: 3 × 398px wide, 10px gaps (= 1214px total)
 *    - Disclaimer / image credit: 12px italic, Avenir Next 200
 *    - Consultants title: BC Alphapipe Bold 16px (NOT 35px — different from
 *      spec labels)
 * ========================================================================*/
body[data-page="work-detail"],
body[data-page="thought-detail"] {
  background: #2C2C2C;
}
.project-content {
  background: #EBECED;
  color: #2C2C2C;
  padding: clamp(40px, 5vw, 72px) 0 clamp(40px, 5vw, 72px);
}
.project-content__inner {
  /* Align content left edge with the hero title's left (200px @ 1440vp,
   * matching .hero__caption clamp). Right padding kept symmetric. */
  padding: 0 clamp(20px, 13.9vw, 200px);
}
.proj-spec {
  margin: 0 0 30px 0;
}
.proj-spec__label {
  font-family: var(--font-display);
  font-size: 35px;
  font-weight: 700;
  line-height: 42px;
  letter-spacing: 0;
  margin: 0 0 10px 0;
  color: #2C2C2C;
}
.proj-spec__value {
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 400;                       /* live's "SF-Pro 200" family is already a Light cut; weight 400 matches its rendered density */
  line-height: 30.08px;
  letter-spacing: 0;
  margin: 0;
  color: #2C2C2C;
}
.proj-spec__value em {
  font-style: italic;
}
.proj-spec__value--indent {
  padding-left: 80px;
}
.proj-divider {
  width: 130px;
  height: 1px;
  background: #2C2C2C;
  border: none;
  margin: 50px 0;
}
.project-content--spec-sm .proj-spec__label {
  font-size: 24px;
  line-height: 1.25;
}
.proj-body__head {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 0;
  color: #2C2C2C;
  margin: 0 0 18px 0;
  max-width: 1216px;         /* 80% of the 1520px content column @1920 */
}
.proj-body__head:not(:first-child) {
  margin-top: 50px;
}
.proj-body p {
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 400;
  line-height: 30.08px;
  color: #2C2C2C;
  margin: 0 0 30px 0;
  max-width: 1216px;         /* 80% of the 1520px content column @1920 */
}
.proj-body p:last-child {
  margin-bottom: 0;
}
.proj-disclaimer {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 400;
  font-style: italic;
  line-height: 22.56px;
  color: #2C2C2C;
  margin: 50px 0 0 0;
  max-width: 1216px;         /* 80% of the 1520px content column @1920 */
}
.proj-images {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin: 80px 0 50px 0;
}
.proj-images img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 398 / 212;
  object-fit: cover;
}
/* Photo-heavy 3-col layout (Bob) — taller photo ratio */
.proj-images--photos img { aspect-ratio: 398 / 266; }
/* 2-up large layout (West Oak Rental) */
.proj-images--two {
  grid-template-columns: repeat(2, 1fr);
}
.proj-images--two img { aspect-ratio: 602 / 423; }
/* Asymmetric 1-tall + 2-stacked layout (West Oak Townhomes) */
.proj-images--asym {
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 1fr;
}
.proj-images--asym img:nth-child(1) {
  grid-row: 1 / span 2;
  aspect-ratio: 602 / 688;
  height: 100%;
}
.proj-images--asym img:nth-child(2),
.proj-images--asym img:nth-child(3) {
  aspect-ratio: 602 / 339;
}
.proj-consultants {
  margin: 50px 0 0 0;
}
.proj-consultants__title {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 700;
  line-height: 19.2px;
  letter-spacing: 0;
  margin: 0 0 20px 0;
  color: #2C2C2C;
}
.proj-consultants p {
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 400;
  line-height: 30.08px;
  color: #2C2C2C;
  margin: 0;
}
.proj-images-credit {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 400;
  font-style: italic;
  line-height: 22.56px;
  color: #2C2C2C;
  margin: 30px 0 0 0;
}
/* ===========================================================================
 *  Thoughts article pages — long-form editorial layout.
 *  Composes inside .project-content wrapper (shared with project pages),
 *  so it inherits the light-gray bg + 200px left padding.
 * ========================================================================*/
.thought-body {
  max-width: 1216px;          /* 80% of the 1520px content column @1920 */
  color: #2C2C2C;
}
.thought-body p {
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 400;
  line-height: 30.08px;
  color: #2C2C2C;
  margin: 0 0 30px 0;
}
.thought-body p.lede {
  font-family: var(--font-body);
  font-size: 18px;
  font-weight: 500;
  line-height: 1.6;
  margin-bottom: 36px;
  color: #2C2C2C;
}
.thought-body h2 {
  font-family: var(--font-display);
  font-size: clamp(24px, 2.5vw, 32px);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 0;
  color: #2C2C2C;
  margin: 56px 0 24px 0;
}
.thought-body h3 {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0;
  color: #2C2C2C;
  margin: 40px 0 16px 0;
}
.thought-body ol,
.thought-body ul {
  margin: 0 0 30px 0;
  padding-left: 28px;
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 400;
  line-height: 30.08px;
  color: #2C2C2C;
}
.thought-body ol > li {
  margin-bottom: 18px;
}
.thought-body ol > li > h3 {
  margin: 0 0 8px 0;
}
.thought-body ul.refs {
  list-style: none;
  padding-left: 0;
  font-size: 13px;
  color: var(--c-fg-muted);
  margin-top: 50px;
}
.thought-body ul.refs li {
  font-style: italic;
  margin-bottom: 4px;
}
.thought-quote {
  font-family: var(--font-display);
  font-size: clamp(22px, 2.6vw, 32px);
  font-weight: 700;
  line-height: 1.3;
  margin: 60px 0;
  padding: 28px 0;
  border-top: 1px solid #2C2C2C;
  border-bottom: 1px solid #2C2C2C;
  text-align: center;
  color: #2C2C2C;
}
/* "Listen to this article" voice-reading bar (news-site style). */
.audio-read {
  display: flex;
  align-items: center;
  gap: 16px;
  max-width: 560px;
  margin: 4px 0 44px 0;
  padding: 14px 18px 14px 14px;
  border: 1px solid rgba(44, 40, 36, 0.16);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.55);
}
.audio-read__btn {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  border: 0;
  border-radius: 50%;
  background: #2C2C2C;
  color: #fff;
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: transform 160ms var(--ease-out), background 160ms var(--ease-out);
}
.audio-read__btn:hover { transform: scale(1.06); background: #000; }
.audio-read__i { width: 20px; height: 20px; fill: currentColor; }
.audio-read__i--pause { display: none; }
.audio-read.is-playing .audio-read__i--play { display: none; }
.audio-read.is-playing .audio-read__i--pause { display: block; }
.audio-read__main { flex: 1 1 auto; min-width: 0; }
.audio-read__label {
  display: block;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #6a6258;
  margin-bottom: 9px;
}
.audio-read__row { display: flex; align-items: center; gap: 12px; }
.audio-read__bar {
  flex: 1 1 auto;
  height: 4px;
  border-radius: 2px;
  background: rgba(44, 40, 36, 0.16);
  cursor: pointer;
  position: relative;
}
.audio-read__fill {
  display: block;
  width: 0;
  height: 100%;
  border-radius: 2px;
  background: #2C2C2C;
}
.audio-read__time {
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: #6a6258;
}
.thought-media {
  margin: 40px 0;
  max-width: 1000px;
}
.thought-media iframe {
  aspect-ratio: 16 / 9;
  width: 100%;
  height: auto;
  border: 0;
  display: block;
}
.thought-media audio {
  width: 100%;
  max-width: 500px;
  display: block;
}
.thought-body strong { font-weight: 700; }
.thought-body em { font-style: italic; }
/* Section divider — matches the horizontal rules in the source manuscript. */
.thought-rule {
  border: 0;
  border-top: 1px solid #C7C2B8;
  margin: 44px 0;
}

.proj-footer-nav {
  padding: clamp(40px, 5vw, 80px) clamp(20px, 7.85vw, 113px) clamp(56px, 7vw, 96px);
  text-align: left;
}
.proj-footer-nav a {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #2C2C2C;
  display: inline-block;
  padding-bottom: 3px;
  border-bottom: 1px solid #2C2C2C;
  transition: opacity var(--t-med) var(--ease-out);
}
.proj-footer-nav a:hover { opacity: 0.55; }

@media (max-width: 720px) {
  .proj-spec__label { font-size: 26px; line-height: 1.2; }
  .project-content--spec-sm .proj-spec__label { font-size: 24px; line-height: 1.25; }
  .proj-spec__value--indent { padding-left: 40px; }
  .proj-images { grid-template-columns: 1fr; }
  .proj-images img { aspect-ratio: 16/9; }
  .proj-divider { width: 100px; margin: 36px 0; }
}

/* Custom cursor enhancement — cursor-ring morphs into a minimalist mouse
 * glyph in two contexts; both share the same 26×40 outline so they feel
 * like one family:
 *   .is-scroll  scroll-wheel dot animating top→middle  (inner-page heros)
 *   .is-view    click line on top, depressing 2px       (work-slide hover)
 *
 * Selectors include `body.cursor-hovering .cursor-ring.is-*` because the
 * work-slide is an <a> — without that, the generic .cursor-hovering 50×50
 * rule wins on specificity and squashes the mouse shape. */
.cursor-ring.is-view,
.cursor-ring.is-scroll,
body.cursor-hovering .cursor-ring.is-view,
body.cursor-hovering .cursor-ring.is-scroll {
  width: 26px;
  height: 40px;
  border-radius: 13px;
  border-color: rgba(255, 255, 255, 0.92);
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* (A) Work-slide hover: top of mouse depressing like a pressed button */
.cursor-ring.is-view::after {
  content: '';
  position: absolute;
  inset: auto;
  left: 50%;
  top: 8px;
  width: 8px;
  height: 2px;
  border-radius: 1px;
  background: rgba(255, 255, 255, 0.95);
  transform: translateX(-50%);
  opacity: 1;
  display: block;
  animation: mouse-click 1.6s ease-in-out infinite;
}
@keyframes mouse-click {
  0%, 100% { transform: translate(-50%, 0);    opacity: 1;   }
  40%      { transform: translate(-50%, 2px);  opacity: 0.3; }
  60%      { transform: translate(-50%, 2px);  opacity: 0.3; }
}

/* (B) Inner-page hero hover: scroll-wheel dot top→middle */
.cursor-ring.is-scroll::after {
  content: '';
  position: absolute;
  inset: auto;
  left: 50%;
  top: 8px;
  width: 3px;
  height: 7px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.95);
  transform: translateX(-50%);
  opacity: 1;
  display: block;
  animation: scroll-wheel 1.6s ease-in-out infinite;
}
@keyframes scroll-wheel {
  0%, 100% { transform: translate(-50%, 0);     opacity: 1;    }
  60%      { transform: translate(-50%, 14px);  opacity: 0.15; }
}

/* Hero scroll cue — small letter-spaced label above the down arrow.
 * Auto-fades after first user scroll (via body.has-scrolled class added
 * by ma-ui.js). Lives over the hero, white text on dark scrim. */
.hero__cue {
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: clamp(60px, 7vw, 90px);
  transform: translateX(-50%);
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  animation: fade-in var(--t-slow) var(--ease-out) 1.5s forwards;
  transition: opacity 700ms var(--ease-out);
}
body.has-scrolled .hero__cue {
  opacity: 0;
  animation: none;                 /* cancel the fade-in animation so opacity transition can take over */
}
/* Work / Thoughts detail heroes use the larger 60px round scroll button, so
 * lift the cue label to sit cleanly above it: button bottom (clamp 24–44px)
 * + button height (60px) + a fixed 16px gap. Tracks the button at every
 * viewport so the two never overlap and read as one stacked "label + dial". */
body[data-page="work-detail"]   .hero__cue,
body[data-page="thought-detail"] .hero__cue {
  bottom: calc(clamp(24px, 4vw, 44px) + 76px);
}

/* ===========================================================================
 *  Page body sections (used by about, contact, recognition, more, post)
 * ========================================================================*/

.section {
  padding: clamp(72px, 10vw, 144px) var(--pad-x);
}
.section--narrow .section__inner {
  max-width: var(--max-text);
  margin-inline: auto;
}
.section--wide .section__inner {
  max-width: var(--max-wide);
  margin-inline: auto;
}

/* About page — match production: white panel, content left-aligned to the
 * hero-title left edge (same offset as the project-detail pages, e.g.
 * work/bob-and-michaels-place), 16px body text in an ~820px column. */
body[data-page="about"] .section { padding-inline: 0; }
body[data-page="about"] .section--narrow .section__inner {
  max-width: none;
  margin-inline: 0;
  padding: 0 clamp(20px, 13.9vw, 200px);
}
body[data-page="about"] .section__inner > p {
  max-width: 820px;
  font-size: 16px;
  line-height: 30px;
}
body[data-page="about"] .section__inner > .lede { max-width: 820px; }

/* More page — two single-family projects side by side (matches production). */
.more-projects {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(28px, 3.5vw, 64px);
  align-items: start;
  margin-top: var(--space-5);
}
.more-project { display: block; color: inherit; text-decoration: none; }
.more-project img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  margin-bottom: var(--space-4);
}
.more-project h2 { margin: 0 0 var(--space-2); }
.more-project__note { color: var(--c-fg-muted); margin-bottom: var(--space-3); }
@media (max-width: 760px) {
  .more-projects { grid-template-columns: 1fr; gap: var(--space-6); }
}

.eyebrow {
  font-family: var(--font-meta);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c-fg-muted);
  margin-bottom: var(--space-3);
}

.section h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h2);
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin-bottom: var(--space-5);
}
.section h3 {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--fs-h3);
  line-height: 1.3;
  margin-bottom: var(--space-3);
}
.section p + p { margin-top: var(--space-3); }
.section p { color: var(--c-fg); }
.section p.lede {
  font-size: clamp(18px, 1.6vw, 22px);
  line-height: 1.5;
}

.section + .section { border-top: 1px solid var(--c-rule); }

/* Recognition list */
.awards-list { display: block; }
.awards-list li {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-4);
  align-items: start;
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--c-rule);
}
.awards-list li:last-child { border-bottom: 0; }
.awards-list .award-meta {
  font-family: var(--font-meta);
  font-size: var(--fs-small);
  color: var(--c-fg-muted);
  margin-top: var(--space-1);
}
.awards-list .award-link {
  align-self: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--c-fg);
  border: 1px solid var(--c-rule);
  transition: background var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
.awards-list .award-link:hover {
  background: var(--c-fg);
  color: var(--c-bg);
  transform: translateX(2px);
}

/* ===========================================================================
 *  Card grids (work index, thoughts index, more)
 * ========================================================================*/

.cards {
  display: grid;
  gap: clamp(24px, 4vw, 56px);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
}
.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  color: var(--c-fg);
}
.card__media {
  position: relative;
  aspect-ratio: 4/3;
  overflow: hidden;
  background: #f4f4f2;
}
.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.2s var(--ease-out),
              opacity var(--t-slow) var(--ease-out);
}
.card:hover .card__media img { transform: scale(1.04); }

.card__meta {
  font-family: var(--font-meta);
  font-size: var(--fs-meta);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-fg-muted);
}
.card__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(22px, 2.2vw, 30px);
  line-height: 1.15;
  letter-spacing: -0.01em;
}
.card__excerpt {
  font-size: var(--fs-small);
  color: var(--c-fg-muted);
  line-height: 1.5;
}

/* ===========================================================================
 *  Forms (contact)
 * ========================================================================*/

.form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: 720px;
}
.field {
  position: relative;
}
.field input,
.field textarea {
  width: 100%;
  padding: 18px 20px;
  border: 1px solid var(--c-rule);
  border-radius: 2px;
  background: #fff;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--c-fg);
  transition: border-color var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out);
}
.field textarea {
  min-height: 160px;
  resize: vertical;
}
.field input::placeholder,
.field textarea::placeholder {
  color: var(--c-fg-faint);
  font-family: var(--font-meta);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: var(--fs-small);
}
.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--c-fg);
}
.field label.label-above {
  display: block;
  font-family: var(--font-meta);
  font-size: var(--fs-meta);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c-fg-muted);
  margin-bottom: var(--space-2);
}

.field--honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 18px 32px;
  background: var(--c-button-bg);
  color: var(--c-button-fg);
  font-family: var(--font-meta);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  border: 1px solid var(--c-button-bg);
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: color var(--t-med) var(--ease-out);
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  background: #fff;
  transform: translateY(100%);
  transition: transform var(--t-med) var(--ease-out);
  z-index: 0;
}
.btn:hover::before { transform: translateY(0); }
.btn:hover { color: var(--c-fg); }
.btn > * { position: relative; z-index: 1; }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

.fx-form-status {
  font-size: var(--fs-small);
  margin-top: var(--space-3);
}
.fx-form-status.is-busy { color: var(--c-fg-muted); }
.fx-form-status.is-ok   { color: #047857; }
.fx-form-status.is-err  { color: #b91c1c; }

/* ===========================================================================
 *  Footer
 * ========================================================================*/

.site-footer {
  background: var(--c-footer-bg);
  color: var(--c-footer-fg);
  padding: clamp(40px, 5vw, 64px) var(--pad-x) clamp(28px, 3vw, 36px);
  font-size: var(--fs-small);
}
.site-footer__inner {
  max-width: var(--max-edge);
  margin-inline: auto;
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr 1fr;
  align-items: end;
}
.footer-brand {
  font-family: "bc-alphapipe", var(--font-display);   /* match the logo wordmark font */
  font-weight: 400;
  font-size: clamp(20px, 2vw, 26px);
  letter-spacing: -0.01em;
}
.footer-social {
  display: flex;
  gap: 14px;
  margin-top: var(--space-3);
}
.footer-social a {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.25);
  transition: background var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out);
}
.footer-social a:hover { background: #fff; color: #1a1a1a; }
.footer-social svg { width: 14px; height: 14px; }
.footer-contact {
  text-align: right;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  color: rgba(255,255,255,0.85);
}
.footer-contact a:hover { color: #fff; text-decoration: underline; text-underline-offset: 4px; }
.site-footer__copy {
  grid-column: 1 / -1;
  padding-top: var(--space-5);
  border-top: 1px solid rgba(255,255,255,0.15);
  color: rgba(255,255,255,0.55);
  font-size: var(--fs-meta);
  letter-spacing: 0.04em;
}

@media (max-width: 720px) {
  .site-footer__inner { grid-template-columns: 1fr; }
  .footer-contact { text-align: left; }
}

/* ===========================================================================
 *  Custom cursor (desktop pointer devices only)
 * ========================================================================*/

/* Custom cursor — desktop-only.
 * Note: no mix-blend-mode. It looks clever but forces the GPU to recomposite
 * the entire video layer on every cursor move, which causes visible stutter
 * during home-page playback. A drop-shadow + outline keeps the cursor
 * legible on both light and dark backgrounds without GPU pressure. */
@media (hover: hover) and (pointer: fine) {
  body { cursor: none; }
  a, button, label, input, textarea, .menu-toggle { cursor: none; }
  .cursor-dot, .cursor-ring {
    position: fixed;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: 9999;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    will-change: transform;
  }
  .cursor-dot {
    width: 6px;
    height: 6px;
    background: #fff;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
    transition: opacity 200ms ease;
  }
  .cursor-ring {
    width: 30px;
    height: 30px;
    border: 1px solid rgba(255, 255, 255, 0.85);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.18),
                inset 0 0 0 1px rgba(0, 0, 0, 0.18);
    transition: width 250ms var(--ease-out),
                height 250ms var(--ease-out),
                opacity 200ms ease;
  }
  body.cursor-hovering .cursor-ring {
    width: 50px;
    height: 50px;
  }
  body.cursor-hidden .cursor-dot,
  body.cursor-hidden .cursor-ring { opacity: 0; }
}

/* ===========================================================================
 *  Page-transition loader
 * ========================================================================*/

.page-loader {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: #0a0a0a;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 600ms var(--ease-out),
              visibility 600ms;
}
.page-loader.is-active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
.page-loader__mark {
  width: 56px;
  height: 56px;
  border: 2px solid rgba(255,255,255,0.15);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 800ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Initial intro: dark veil that lifts on page load */
.page-intro {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: #0a0a0a;
  transform-origin: top;
  animation: intro-lift 900ms 200ms var(--ease-in-out) forwards;
  pointer-events: none;
}
@keyframes intro-lift {
  to { transform: scaleY(0); }
}

/* ===========================================================================
 *  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;
  }
  .hero__eyebrow, .hero__title, .hero__links li { opacity: 1; transform: none; }
}
