/* ===================================================================
   Lani Atelier — Global Site Stylesheet
   -------------------------------------------------------------------
   Consolidates styles previously inline in every page so they are
   available regardless of which page Barba.js renders into <main>.
   Loaded after tokens.css on every HTML page.
   =================================================================== */

/* ── Reset ── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html {
  /* Lenis owns smooth scroll site-wide; the native CSS smoothing would
     stack on top of its RAF-driven interpolation and feel glued. */
  background: var(--bg);
  overflow-x: hidden;   /* single scroll context — the documentElement */
}

body {
  background: var(--bg);
  color: var(--ink-body);
  font-family: var(--ff-synonym);
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
}

/* ── Reveal utility (IntersectionObserver-driven) ── */
.reveal {
  opacity: 0;
  transform: translateY(22px) translateZ(0);
  transition: opacity 1s ease, transform 1s var(--ease-reveal);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.reveal.vis { opacity: 1; transform: translateY(0) translateZ(0); }

/* Custom cursor styles are injected by /cursor.js (the script also
   conditions itself to hover:fine pointers and creates the #cur element
   on demand). The four states — default navy dot, terracotta link dot,
   terracotta ←/→ gallery glyphs — live there alongside the rAF lerp. */

/* ── Top progress bar (Barba transition loader) ── */
#bar {
  position: fixed;
  top: 0; left: 0;
  height: 1px;
  z-index: 500;
  background: var(--azure);
  width: 0%;
  opacity: 0.5;
  transition: width .08s linear;
}

/* ── Page background (legacy, home) ── */
#page-bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--bg);
  pointer-events: none;
}

/* ═══════════════════════════════════════════════════════════════════
   Persistent site header + mobile menu
   ═══════════════════════════════════════════════════════════════════ */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 52px;
  height: 80px;
  background: transparent;
  border: none;
  pointer-events: none;
  transition: transform .4s cubic-bezier(0.16,1,0.3,1),
              opacity .8s cubic-bezier(0.4, 0, 0.2, 1);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  will-change: transform;
}
.site-header.sh-hidden { transform: translateY(-100%); }
/* Set during FLIP morph (transitions.js beforeLeave) — instant snap to
   opacity 0 (the override `opacity 0s` defeats the .8s base transition).
   Removed at flipMorph Stage 2 onStart; the base .8s opacity transition
   then drives the gentle fade-in alongside the rising hero title. */
.site-header.sh-flip-hidden {
  opacity: 0;
  transition: transform .4s cubic-bezier(0.16,1,0.3,1),
              opacity 0s;
}

.sh-logo {
  font-family: var(--ff-day);
  font-size: 32px;
  letter-spacing: 0.05em;
  color: var(--bg);
  text-decoration: none;
  pointer-events: auto;
  transition: color 0.4s ease;
  position: absolute;
  left: 52px; top: 50%;
  transform: translateY(-50%);
  white-space: nowrap;
  transform-origin: left center;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  opacity: 0;
  will-change: transform;
}

.sh-nav { display: flex; gap: 36px; align-items: center; pointer-events: auto; }
/* Menu links: no decorative underlines — state is signalled via opacity
   alone. Default cream on dark photos / navy on light backgrounds is set
   by the theme rules below; .header-dark is toggled by initHeaderTheme()
   based on each section's [data-header-theme] attribute. */
.sh-link {
  font-family: var(--ff-synonym);
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: lowercase;
  color: var(--bg);
  text-decoration: none;
  opacity: 0.7;
  transition: opacity .3s ease, color 0.4s ease, font-weight 0s;
  position: relative;
}
.sh-link:hover { opacity: 1; color: var(--terracotta); }
.sh-link.active {
  opacity: 1;
  color: var(--terracotta);
}
.site-header.header-dark .sh-link { color: var(--navy); }
.site-header.header-dark .sh-link:hover { color: var(--terracotta); }
.site-header.header-dark .sh-link.active { color: var(--terracotta); }

.sh-mob-btn {
  display: none;
  position: absolute;
  top: 26px; right: 20px;
  width: 44px; height: 44px;
  background: none;
  border: none;
  pointer-events: auto;
  padding: 0;
}
.sh-mob-btn span {
  position: absolute;
  left: 11px;
  width: 22px; height: 1px;
  background: var(--bg);
  transform-origin: center center;
  border-radius: 0.5px;
  transition: background-color 0.4s ease;
  will-change: transform, opacity;
}
.sh-mob-btn span:nth-child(1) { top: 15px; }
.sh-mob-btn span:nth-child(2) { top: 21px; }
.sh-mob-btn span:nth-child(3) { top: 27px; }

.site-header.header-dark .sh-logo { color: var(--navy); }
.site-header.header-dark .sh-mob-btn span { background: var(--navy); }
.site-header.menu-open .sh-logo { color: var(--navy) !important; }

.sh-mob-overlay {
  position: fixed;
  top: 0; left: 0;
  width: 100vw;
  height: 100dvh;
  z-index: 9999;
  background: transparent;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 52px;
  pointer-events: none;
  visibility: hidden;
}
.sh-mob-overlay.is-open { pointer-events: auto; visibility: visible; }
.sh-mob-close { display: none; }
.sh-mob-close::before, .sh-mob-close::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 20px; height: 1px;
  background: var(--navy);
}
.sh-mob-close::before { transform: translate(-50%, -50%) rotate(45deg); }
.sh-mob-close::after  { transform: translate(-50%, -50%) rotate(-45deg); }

.sh-mob-links { display: flex; flex-direction: column; position: relative; z-index: 1; }
/* Mobile overlay sits on the cream wave panel — links are always navy.
   No dividers: rhythm comes from generous padding and opacity contrast. */
.sh-mob-link {
  font-family: var(--ff-day);
  font-size: clamp(30px, 8.5vw, 48px);
  letter-spacing: 0.04em;
  color: var(--navy);
  text-decoration: none;
  padding: 16px 0;
  display: block;
  opacity: 0.5;
  transition: opacity .3s ease, color .3s ease;
}
.sh-mob-link:hover { opacity: 1; }
.sh-mob-link.active {
  opacity: 1;
  color: var(--navy-soft);
  font-weight: 400;
}
.sh-mob-tagline {
  font-family: var(--ff-synonym);
  font-size: 9px;
  letter-spacing: 0.30em;
  text-transform: uppercase;
  color: var(--ink-mute);
  opacity: 0.55;
  padding: 24px 0 0;
}

@media (min-width: 769px) {
  .sh-logo { font-size: 44px; letter-spacing: 0.05em; }
}
@media (max-width: 768px) {
  .site-header { padding: 0 24px; }
  .sh-logo { left: 24px; top: 50%; transform: translateY(-50%); }
  .sh-nav { display: none; }
  .sh-mob-btn { display: block; top: 50%; transform: translateY(-50%); }

  /* Mobile nav overlay — magazine-style asymmetric layout. Links
     align with the logo's 24px left margin (instead of the desktop
     52px) so the eye reads down a single vertical baseline. The
     overlay's flex-column then pushes the tagline to the absolute
     bottom-left corner, leaving generous breathing space between
     the centred link list and the corner-anchored studio mark. */
  .sh-mob-overlay {
    padding: 0 24px;
  }
  .sh-mob-link {
    /* ~20% smaller than desktop's clamp(30px, 8.5vw, 48px). */
    font-size: clamp(24px, 6.8vw, 38px);
    /* More vertical breathing room between links. */
    padding: 22px 0;
  }
  .sh-mob-tagline {
    position: absolute;
    /* Respect iOS home-indicator inset; floor at 24px so it never
       collides with the overlay edge on devices without an inset. */
    bottom: max(24px, env(safe-area-inset-bottom, 24px));
    left: 24px;
    font-size: 12px;
    letter-spacing: 0.15em;
    padding: 0;
  }
}

/* Helper: a brand mark used in a couple of page templates */
.sh-brand {
  font-family: var(--ff-day);
  font-size: clamp(28px, 4vw, 52px);
  font-weight: 400;
  letter-spacing: 0.05em;
  color: var(--navy);
  text-decoration: none;
}

/* ═══════════════════════════════════════════════════════════════════
   Persistent footer (rendered on every page)
   ═══════════════════════════════════════════════════════════════════ */
.site-footer { background: var(--navy); color: #ECE7DB; padding: 80px 56px 36px; }
.foot-top {
  padding-bottom: 52px;
  border-bottom: 1px solid #e1b19d;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 32px;
  margin-bottom: 0;
}
.foot-brand {
  font-family: var(--ff-day);
  font-weight: 300;
  font-size: clamp(64px, 8vw, 124px);
  line-height: 0.9;
  letter-spacing: -0.02em;
  color: #ECE7DB;
  margin-bottom: 0;
}
.foot-tagline {
  font-family: var(--ff-day);
  font-style: italic;
  font-size: 18px;
  letter-spacing: 0;
  text-transform: none;
  color: rgba(236,231,219,0.7);
}
.foot-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 48px;
  padding: 44px 0;
  margin-bottom: 0;
  border-bottom: 1px solid #e1b19d;
}
.foot-col { display: flex; flex-direction: column; gap: 0; }
.foot-col-label {
  font-family: var(--ff-synonym);
  font-weight: 500;
  font-size: 10px;
  letter-spacing: 0.30em;
  text-transform: uppercase;
  color: rgba(236,231,219,0.55);
  margin-bottom: 18px;
}
.foot-col a, .foot-col span {
  display: block;
  font-family: var(--ff-synonym);
  font-weight: 300;
  font-size: 14px;
  letter-spacing: 0.06em;
  line-height: 2.2;
  color: rgba(236,231,219,0.85);
  text-decoration: none;
  transition: color .3s, font-weight 0s;
}
.foot-col a:hover { color: #E1B19D; font-weight: 500; }
.foot-bottom {
  padding-top: 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--ff-synonym);
  font-weight: 300;
  color: rgba(236,231,219,0.5);
}
.foot-copy {
  font-size: 10px;
  letter-spacing: 0.12em;
  color: rgba(236,231,219,0.5);
}

@media (max-width: 900px) {
  .site-footer { padding: 52px 24px 36px; }
  .foot-top { flex-direction: column; align-items: flex-start; gap: 20px; }
  .foot-brand { font-size: clamp(40px, 11vw, 72px); }
  .foot-tagline { font-size: 16px; }
  .foot-grid { grid-template-columns: 1fr; gap: 28px; }
  .foot-bottom { flex-direction: column; gap: 12px; text-align: center; }
}

/* ═══════════════════════════════════════════════════════════════════
   Shared split-hero (used by about / projects / press)
   ═══════════════════════════════════════════════════════════════════ */
.split-hero {
  margin-top: 0;
  display: grid;
  grid-template-columns: 38% 1fr;
  height: 55vh;
  min-height: 400px;
  position: relative;
}
.sh-left {
  background: var(--bg);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 52px;
}
.sh-eyebrow {
  font-size: 9px;
  letter-spacing: .42em;
  text-transform: lowercase;
  color: var(--terracotta);
  display: flex;
  align-items: center;
  gap: 12px;
  font-weight: 400;
}
.sh-eyebrow::before {
  content: '';
  width: 18px;
  height: 1px;
  background: var(--terracotta);
  display: block;
}
.sh-title {
  font-family: var(--ff-day);
  font-size: clamp(42px, 6vw, 84px);
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--navy);
  line-height: .95;
}
.sh-count {
  font-family: var(--ff-synonym);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .18em;
  color: var(--ink-mute);
  margin-top: 16px;
}
.sh-right { position: relative; overflow: hidden; }
.sh-right-inner {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  transition: transform 1.4s cubic-bezier(.22,1,.36,1);
}
.sh-right:hover .sh-right-inner { transform: scale(1.04); }
.sh-seam {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  background: linear-gradient(to right, var(--bg) 0%, transparent 10%);
}

@media (max-width: 900px) {
  .split-hero { grid-template-columns: 1fr; height: auto; }
  .sh-left { min-height: 45vh; padding: 36px 24px; }
  .sh-right { height: 50vh; }
}

/* Home hero variant: 50/50 split, larger display type, paired ZH line.
   Right side is a flat colour block until a real photo is dropped onto
   .sh-right-inner via background-image. */
.split-hero--home { grid-template-columns: 1fr 1fr; height: 100vh; }
.split-hero--home .sh-title {
  font-size: clamp(40px, 5.6vw, 78px);
  letter-spacing: -0.02em;
}
.split-hero--home .sh-title-zh {
  margin-top: 22px;
  font-family: var(--ff-taipei-sans);
  font-size: clamp(15px, 1.4vw, 20px);
  font-weight: 300;
  letter-spacing: 0.18em;
  color: var(--ink-mute);
}
.sh-right-inner--placeholder { background: var(--bg-deep); }
/* Quiet variant — used by about / projects / press hero panels where the
   client opted out of a photo. Matches the page background so the right
   half visually dissolves, leaving only the title in the left column. */
.sh-right-inner--quiet { background: var(--bg); }
@media (max-width: 900px) {
  .split-hero--home { grid-template-columns: 1fr; height: auto; }
  .split-hero--home .sh-title-zh { margin-top: 16px; }
}

/* Generic constrained content container (used by about) */
.container { max-width: 1200px; margin: 0 auto; padding: 0 52px; }
@media (max-width: 900px) { .container { padding: 0 24px; } }

/* ═══════════════════════════════════════════════════════════════════
   Page: home  — hero carousel + editorial magazine flow
   ═══════════════════════════════════════════════════════════════════ */
#hero { margin-top: 0; position: relative; height: 100vh; }
.hero-sticky { position: sticky; top: 0; height: 100vh; overflow: hidden; }
.hero-frame {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity 1.2s ease;
}
.hero-frame.active { opacity: 1; }
.hero-overlay {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(to top,
    rgba(8,24,40,0.72) 0%,
    rgba(8,24,40,0.15) 55%,
    rgba(8,24,40,0.25) 100%);
}
.hero-brand {
  position: absolute;
  top: 44px; left: 52px;
  z-index: 10;
  font-family: var(--ff-day);
  font-size: clamp(28px, 4vw, 52px);
  font-weight: 400;
  letter-spacing: 0.05em;
  color: rgba(255,255,255,0.92);
  text-decoration: none;
}
.hero-caption {
  position: absolute;
  bottom: 60px; left: 52px; right: 52px;
  z-index: 5;
}
.hero-caption h1 {
  font-family: var(--ff-day);
  font-size: clamp(28px, 4.5vw, 58px);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -0.01em;
  color: #fff;
  opacity: 0;
  animation: fadeUp 1s .4s ease forwards;
}
.hero-caption h1 em {
  font-style: italic;
  color: var(--azure-light);
  font-weight: 300;
  font-size: .85em;
  letter-spacing: .02em;
}
.hero-scroll {
  margin-top: 28px;
  display: flex;
  align-items: center;
  gap: 14px;
  opacity: 0;
  animation: fadeUp 1s .9s ease forwards;
}
.scroll-line { width: 32px; height: 1px; background: rgba(255,255,255,0.3); }
.scroll-label {
  font-size: 9px;
  letter-spacing: .3em;
  text-transform: lowercase;
  color: rgba(255,255,255,0.45);
}
.seq-dots {
  position: absolute;
  right: 28px; top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: 6px;
  z-index: 10;
}
.sd {
  width: 2px; height: 2px;
  border-radius: 50%;
  background: rgba(255,255,255,0.3);
  transition: height .3s, background .3s;
}
.sd.on {
  height: 16px;
  border-radius: 1px;
  background: rgba(255,255,255,0.8);
}

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ───────────────────────────────────────────────────────────────────
   Atelier landing rows — magazine rhythm.
   Each row picks one of four layouts via data-layout, breaking the
   regular 50/50 grid so text weaves around photos of varying size.
   Only the image <a> is clickable; project meta hides until hover.
   ─────────────────────────────────────────────────────────────────── */
.atelier-section {
  padding: clamp(120px, 16vw, 200px) 0 clamp(140px, 18vw, 240px);
  background: var(--bg);
}

.atelier-row {
  position: relative;
  margin: 0 auto;
}
.atelier-row + .atelier-row { margin-top: clamp(140px, 18vw, 260px); }

/* ── Text column shared rules ── */
.atelier-row-text { max-width: 34em; }
.atelier-row-h {
  font-family: var(--ff-taipei-sans);
  font-weight: 400;
  font-size: clamp(28px, 3.2vw, 40px);
  line-height: 1.3;
  letter-spacing: 0.06em;
  color: var(--navy);
  margin-bottom: 28px;
}
.atelier-row-body {
  font-family: var(--ff-taipei-sans);
  font-weight: 500;
  font-size: 15px;
  line-height: 1.8;
  letter-spacing: 0.05em;
  color: var(--ink-body);
}

/* ── Image column — only this <a> is clickable ── */
.atelier-row-media {
  position: relative;
  display: block;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  -webkit-tap-highlight-color: transparent;
}
.atelier-row-media:focus-visible {
  outline: 2px solid var(--azure-light);
  outline-offset: 6px;
}
.atelier-row-img {
  display: block;
  width: 100%;
  background-size: cover;
  background-position: center;
  transition: transform 1.2s cubic-bezier(.22, 1, .36, 1);
  will-change: transform;
}
/* Subtle scrim that fades in alongside the meta for legibility on
   light photos. Lives as a pseudo-element on .atelier-row-media. */
.atelier-row-media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(8,24,40,0.45) 0%, transparent 45%);
  opacity: 0;
  transition: opacity .5s ease;
  pointer-events: none;
}
.atelier-row-media:hover .atelier-row-img,
.atelier-row-media:focus-visible .atelier-row-img {
  transform: scale(1.04);
}
.atelier-row-media:hover::after,
.atelier-row-media:focus-visible::after {
  opacity: 1;
}

/* ── Project meta — hidden until hover, anchored bottom-right ── */
.atelier-row-meta {
  position: absolute;
  bottom: 28px;
  right: 32px;
  left: auto;
  text-align: right;
  max-width: calc(100% - 64px);
  margin: 0;
  font-family: var(--ff-synonym);
  font-weight: 300;
  font-size: 10px;
  letter-spacing: 0.30em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 1px 12px rgba(8, 24, 40, 0.55);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
  opacity: 0;
  transform: translateY(10px);
  transition:
    opacity .5s ease .12s,
    transform .6s cubic-bezier(.22, 1, .36, 1) .12s;
}
.atelier-row-media:hover .atelier-row-meta,
.atelier-row-media:focus-visible .atelier-row-meta {
  opacity: 1;
  transform: translateY(0);
}

/* ════════════════════════════════════════════════════════════════════
   Layout variants — desktop/tablet (>=901px)
   ════════════════════════════════════════════════════════════════════ */

/* ── 01 · magazine-hero
       Text in a wide column, full-width image below.
       The opening statement of the page rhythm. */
.atelier-row[data-layout="magazine-hero"] {
  max-width: 1320px;
  padding: 0 52px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 80px;
}
.atelier-row[data-layout="magazine-hero"] .atelier-row-text {
  max-width: 52ch;
}
.atelier-row[data-layout="magazine-hero"] .atelier-row-img {
  aspect-ratio: 21 / 10;
}

/* ── 02 · asym-right
       Image bleeds off the left edge, text floats top-right. */
.atelier-row[data-layout="asym-right"] {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 120px;
  align-items: center;
  padding: 0 52px 0 0;
}
.atelier-row[data-layout="asym-right"] .atelier-row-media {
  transform: translateX(-6%);
}
.atelier-row[data-layout="asym-right"] .atelier-row-img {
  aspect-ratio: 4 / 3;
}
.atelier-row[data-layout="asym-right"] .atelier-row-text {
  padding-top: 56px;
}

/* ── 03 · split-left
       Large image left, narrow text right, baseline-aligned. */
.atelier-row[data-layout="split-left"] {
  max-width: 1400px;
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: 90px;
  align-items: end;
  padding: 0 96px 0 52px;
}
.atelier-row[data-layout="split-left"] .atelier-row-img {
  aspect-ratio: 3 / 2;
}
.atelier-row[data-layout="split-left"] .atelier-row-text {
  padding-bottom: 88px;
}

/* ── 04 · full-stage
       Centred caption above, near-full-width cinematic image below. */
.atelier-row[data-layout="full-stage"] {
  display: flex;
  flex-direction: column;
  padding: 0;
}
.atelier-row[data-layout="full-stage"] .atelier-row-text {
  max-width: 640px;
  margin: 0 auto 72px;
  padding: 0 24px;
  text-align: center;
}
.atelier-row[data-layout="full-stage"] .atelier-row-media {
  width: calc(100% - 104px);
  margin: 0 auto;
}
.atelier-row[data-layout="full-stage"] .atelier-row-img {
  aspect-ratio: 21 / 9;
}

/* Desktop-only single-line caption for the full-stage row. The
   sentence "我們致力於將對生活的熱愛…超越日常的空間體驗。" is the
   page's horizontal punchline — wrapping it to two lines breaks the
   cinematic stretch the layout is designed for. Widen the centred
   container and pin `white-space: nowrap` on the body specifically.
   Scoped to ≥1024px and to the full-stage variant only, so the
   shorter rows (magazine-hero / asym-right / split-left) keep their
   normal wrapping and so mobile/tablet — where the text container
   collapses to full width below 900px (line 675) — never tries to
   push a 600px+ line off-screen. */
@media (min-width: 1024px) {
  .atelier-row[data-layout="full-stage"] .atelier-row-text {
    max-width: 1200px;
  }
  .atelier-row[data-layout="full-stage"] .atelier-row-body {
    white-space: nowrap;
  }
}

/* ════════════════════════════════════════════════════════════════════
   Mobile — all four layouts collapse to a single column.
   Text always above image; force meta visible (no hover on touch).
   ════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  .atelier-section { padding: 80px 0 120px; }
  .atelier-row + .atelier-row { margin-top: 96px; }

  .atelier-row[data-layout] {
    display: flex;
    flex-direction: column;
    grid-template-columns: 1fr;
    gap: 32px;
    padding: 0 24px;
    max-width: none;
    align-items: stretch;
  }
  .atelier-row[data-layout] .atelier-row-text {
    max-width: none;
    padding: 0;
    text-align: left;
    margin: 0;
  }
  .atelier-row[data-layout] .atelier-row-media {
    width: 100%;
    margin: 0;
    transform: none !important;
  }
  .atelier-row[data-layout] .atelier-row-img {
    aspect-ratio: 4 / 3;
  }

  /* No hover on touch — keep meta visible by default */
  .atelier-row-meta {
    opacity: 1;
    transform: none;
    transition: none;
    right: 16px;
    bottom: 14px;
    max-width: calc(100% - 32px);
    font-size: 8px;
    letter-spacing: 0.22em;
  }
  .atelier-row-media::after {
    opacity: 1;
    background: linear-gradient(to top, rgba(8,24,40,0.5) 0%, transparent 50%);
  }
}

@media (hover: none) {
  /* Touch devices that aren't narrow (e.g. tablets) — also keep meta on */
  .atelier-row-meta { opacity: 1; transform: none; transition: none; }
  .atelier-row-media::after { opacity: 1; }
}

/* Home preloader (shown only on the very first session entry) */
#preloader {
  position: fixed;
  inset: 0;
  z-index: 99999;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  pointer-events: all;
}
.pl-panel {
  position: absolute;
  left: 0; right: 0;
  height: 50%;
  background: #E5E0D4;
  will-change: transform;
}
.pl-panel--top { top: 0; }
.pl-panel--bottom { bottom: 0; }

/* The Barba leave/enter cover is now a JS-driven cross-fade
   (opacity + translateY on [data-barba="container"]), so the previous
   #page-curtain / .pc-panel styles have been removed. The persistent
   body { background: var(--bg) } provides background continuity during
   the brief gap between leave-complete and enter-start. */
.pl-brand {
  position: relative;
  z-index: 2;
  font-family: var(--ff-day);
  font-size: clamp(28px, 3.8vw, 54px);
  font-weight: 300;
  letter-spacing: -0.02em;
  color: #2F4E6F;
  white-space: nowrap;
  opacity: 0;
}

@media (max-width: 960px) {
  #hero { margin-top: 0; height: 100vh; }
  .hero-brand { top: 20px; left: 20px; font-size: 22px; letter-spacing: 0.05em; font-weight: 300; }
  .hero-caption { left: 24px; right: 24px; bottom: 48px; }
  .seq-dots { display: none; }
}
@media (max-width: 767px) {
  .hero-brand { top: 36px; left: 20px; font-size: 24px; height: 52px; display: flex; align-items: center; }
}

/* ═══════════════════════════════════════════════════════════════════
   Page: about — intro, director, philosophy
   ═══════════════════════════════════════════════════════════════════ */
.intro {
  padding: 100px 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 80px;
  align-items: center;
}
.intro-img { position: relative; overflow: hidden; }
.intro-img-inner {
  width: 100%;
  aspect-ratio: 4/5;
  background: linear-gradient(150deg, #D4C8B4 0%, #A49080 40%, #5A4838 100%);
}
.intro-img-inner img { width: 100%; height: 100%; object-fit: cover; display: block; }
.intro-eyebrow {
  font-family: var(--ff-synonym);
  font-size: 12px;
  letter-spacing: .26em;
  text-transform: lowercase;
  color: var(--terracotta);
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 24px;
  font-weight: 500;
}
.intro-eyebrow::before {
  content: '';
  width: 22px;
  height: 1px;
  background: var(--terracotta);
  display: block;
}
.intro-h {
  font-family: var(--ff-day);
  font-size: clamp(26px, 3vw, 38px);
  font-weight: 400;
  line-height: 1.3;
  color: var(--navy);
  letter-spacing: -0.01em;
  margin: 0;
  font-synthesis: style;
}
.intro-h em {
  font-family: var(--ff-taipei-sans);
  font-weight: 500;
  font-style: normal;
  font-synthesis: style;
  font-size: 1.2rem;
  letter-spacing: 0.2em;
  color: var(--ink-mute);
  opacity: 0.8;
  display: block;
  margin-top: 0.5rem;
}
.intro-p {
  font-family: var(--ff-taipei-sans);
  font-size: 14px;
  font-weight: 500;
  line-height: 2;
  color: var(--ink-body);
  margin-top: 22px;
  letter-spacing: 0.05em;
}
.intro-p + .intro-p { margin-top: 14px; }

.director {
  padding: 80px 0;
  border-top: 1px solid var(--rule);
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 60px;
  align-items: start;
}
.director-photo { position: relative; }
.director-photo-inner {
  width: 100%;
  aspect-ratio: 3/4;
  background: linear-gradient(145deg, #BCC4D0 0%, #7A90A8 40%, #324C60 100%);
  overflow: hidden;
}
.director-photo-inner img { width: 100%; height: 100%; object-fit: cover; display: block; }
.director-name {
  font-family: var(--ff-synonym);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: .12em;
  color: var(--navy);
  margin-top: 16px;
}
.director-name .zh {
  font-family: var(--ff-taipei-sans);
  font-weight: 500;
}
.director-title {
  font-family: var(--ff-synonym);
  font-size: 11px;
  font-weight: 300;
  letter-spacing: .2em;
  text-transform: lowercase;
  color: var(--ink-mute);
  margin-top: 4px;
}
.director-quote {
  font-family: var(--ff-taipei-sans);
  font-size: clamp(16px, 1.6vw, 19px);
  font-weight: 400;
  font-style: normal;
  line-height: 1.9;
  letter-spacing: 0.05em;
  color: var(--navy);
  margin: 0 0 32px;
  max-width: 480px;
}
.director-quote::before {
  content: "\201C";
  display: block;
  margin: 0 0 24px;
  color: var(--terracotta);
  font-family: var(--ff-day), serif;
  font-size: 56px;
  line-height: 0.6;
}
.director-body {
  font-family: var(--ff-taipei-sans);
  font-size: 14px;
  font-weight: 500;
  line-height: 2;
  color: var(--ink-body);
  letter-spacing: 0.05em;
}
.director-body + .director-body { margin-top: 14px; }

.founder-intro {
  padding: clamp(100px, 12vw, 160px) 0;
  background: var(--bg);
}
.founder-intro-inner {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 52px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(48px, 6vw, 96px);
  align-items: center;
}
.founder-photo-inner {
  width: 100%;
  aspect-ratio: 4/5;
  background: linear-gradient(150deg, #D4C8B4 0%, #A49080 40%, #5A4838 100%);
  overflow: hidden;
}
.founder-photo-inner img { width: 100%; height: 100%; object-fit: cover; display: block; }
.founder-quote {
  font-family: var(--ff-taipei-sans);
  font-size: clamp(16px, 1.6vw, 19px);
  font-weight: 500;
  font-style: normal;
  line-height: 1.9;
  letter-spacing: 0.05em;
  color: var(--navy);
  margin: 0 0 32px;
  max-width: 480px;
}
.founder-quote::before {
  content: "\201C";
  display: block;
  margin: 0 0 24px;
  color: var(--terracotta);
  font-family: var(--ff-day), serif;
  font-size: 56px;
  line-height: 0.6;
}
.founder-name {
  font-family: var(--ff-synonym);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: .12em;
  color: var(--navy);
}
.founder-name .zh {
  font-family: var(--ff-taipei-sans);
  font-weight: 500;
}
.founder-title {
  font-family: var(--ff-synonym);
  font-size: 11px;
  font-weight: 300;
  letter-spacing: .2em;
  text-transform: lowercase;
  color: var(--ink-mute);
  margin-top: 4px;
}
.founder-read-more {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  margin-top: 36px;
  padding: 6px 0;
  font-family: var(--ff-synonym);
  font-weight: 500;
  font-size: 10px;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--navy);
  border-bottom: 1px solid var(--navy);
  text-decoration: none;
  width: max-content;
  transition: gap .35s cubic-bezier(.22,1,.36,1), color .35s ease, border-color .35s ease;
}
.founder-read-more::after {
  content: "\2192";
  font-family: var(--ff-day);
  font-size: 14px;
  color: var(--navy);
  transition: transform .35s cubic-bezier(.22,1,.36,1), color .35s ease;
}
.founder-read-more:hover { color: var(--terracotta); border-color: var(--terracotta); }
.founder-read-more:hover::after { transform: translateX(6px); color: var(--terracotta); }

.feat-project {
  padding: clamp(80px, 10vw, 140px) 0;
  background: var(--bg);
}
.feat-project-inner {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 52px;
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(48px, 6vw, 96px);
  align-items: stretch;
}
.feat-project-text {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 32px 0;
  /* No min-height — the grid row is sized by the image's natural height,
     and space-between spreads the text to match. A fixed floor caused the
     image container to stretch past the image on iPad widths, exposing
     --bg-mid beneath the photo. */
}
.feat-project-h {
  font-family: var(--ff-day);
  font-size: clamp(48px, 6vw, 88px);
  font-weight: 400;
  letter-spacing: -0.015em;
  line-height: 1.02;
  color: var(--navy);
  margin: 0;
}
.feat-project-p {
  font-family: var(--ff-taipei-sans);
  font-size: 14px;
  font-weight: 400;
  line-height: 2;
  letter-spacing: 0.05em;
  color: var(--ink-body);
  margin: 0 0 28px;
  max-width: 420px;
}
.feat-project-img {
  display: block;
  overflow: hidden;
  background: var(--bg-mid);
  /* Don't stretch to the grid row — the text column drives the row when
     its content is taller, and we'd rather have the text breathe than
     reveal --bg-mid below the photo. */
  align-self: start;
}
.feat-project-img picture { display: block; width: 100%; }
.feat-project-img img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform 1.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.feat-project-img:hover img { transform: scale(1.04); }

.press-feature {
  padding: clamp(80px, 10vw, 140px) 0;
  background: var(--bg);
}
.press-feature-inner {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 52px;
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.4fr);
  gap: clamp(48px, 6vw, 96px);
  align-items: stretch;
}
.press-feature-text {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 32px 0;
  min-height: 460px;
}
.press-feature-h {
  font-family: var(--ff-day);
  font-size: clamp(48px, 5.6vw, 80px);
  font-weight: 400;
  letter-spacing: -0.015em;
  line-height: 1;
  color: var(--navy);
  margin: 0;
}
.press-feature-card {
  display: block;
  position: relative;
  width: 100%;
  overflow: hidden;
  background: var(--bg-mid);
}
.press-feature-card img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.press-feature-card:hover img { transform: scale(1.04); }
.press-feature-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}
.press-feature-date {
  font-family: var(--ff-synonym);
  font-size: 13px;
  font-weight: 300;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 0;
}
.press-feature-quote {
  font-family: var(--ff-taipei-sans);
  font-size: clamp(17px, 1.6vw, 21px);
  font-weight: 400;
  font-style: normal;
  line-height: 1.85;
  letter-spacing: 0.05em;
  color: var(--navy);
  margin: 0;
  white-space: nowrap;
}
.press-feature-quote::before {
  content: "\201C";
  display: block;
  margin: 0 0 24px;
  color: var(--terracotta);
  font-family: var(--ff-day), serif;
  font-size: 56px;
  line-height: 0.6;
}
.press-feature-cta { margin-top: 8px; }

.philosophy { padding: 80px 0 48px; border-top: 1px solid var(--rule); }
.philosophy-top { margin-bottom: 80px; }
.philosophy-h {
  font-family: var(--ff-day);
  font-size: clamp(26px, 3vw, 38px);
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--navy);
  line-height: 1.1;
}
.philosophy-h em { font-style: italic; color: var(--ink-mute); }

.phil-pairs { position: relative; }
.phil-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 clamp(48px, 6vw, 92px);
  padding: 80px 0 88px;
  border-top: 1px solid var(--rule);
}
.phil-pairs .phil-pair:first-child { border-top: none; }
.phil-pair .phil-block--b { padding-top: clamp(60px, 8vw, 110px); }
.phil-pair--rev .phil-block--a { padding-top: clamp(60px, 8vw, 110px); }
.phil-pair--rev .phil-block--b { padding-top: 0; }

.phil-block { position: relative; }
.phil-num {
  position: absolute;
  top: 0; left: 0;
  font-family: var(--ff-day);
  font-size: clamp(112px, 15vw, 176px);
  font-weight: 300;
  color: #A2998B;
  -webkit-text-stroke: 0px transparent;
  opacity: 0.22;
  mix-blend-mode: multiply;
  z-index: 0;
  line-height: 0.88;
  letter-spacing: -0.02em;
  pointer-events: none;
  user-select: none;
  will-change: transform;
}
.phil-content { position: relative; z-index: 1; padding-top: clamp(84px, 10vw, 124px); }
.phil-eyebrow {
  font-family: var(--ff-synonym);
  font-size: 9px;
  letter-spacing: 0.38em;
  text-transform: uppercase;
  color: var(--terracotta);
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
}
.phil-eyebrow::before {
  content: '';
  width: 16px; height: 1px;
  background: var(--terracotta);
  display: block;
  flex-shrink: 0;
}
.phil-title {
  font-family: var(--ff-day);
  font-size: clamp(22px, 2.8vw, 36px);
  font-weight: 300;
  letter-spacing: -0.01em;
  color: var(--navy);
  line-height: 1.15;
  margin-bottom: 18px;
}
.phil-title .zh {
  font-family: var(--ff-taipei-sans);
  font-weight: 300;
  letter-spacing: 0.12em;
}
.phil-body {
  font-family: var(--ff-taipei-sans);
  font-size: 13.5px;
  font-weight: 500;
  line-height: 2;
  color: var(--ink-body);
  letter-spacing: 0.05em;
  max-width: 340px;
}

@media (max-width: 900px) {
  .intro { grid-template-columns: 1fr; gap: 40px; padding: 60px 0; }
  .director { grid-template-columns: 1fr; gap: 32px; padding: 60px 0; }
  .director-photo-inner { aspect-ratio: 4/3; }
  .founder-intro-inner { grid-template-columns: 1fr; gap: 40px; padding: 0 24px; }
  .founder-quote { margin-bottom: 24px; }
  .feat-project-inner { grid-template-columns: 1fr; gap: 32px; padding: 0 24px; }
  .feat-project-text { padding: 0; gap: 28px; }
  .press-feature-inner { padding: 0 24px; gap: 28px; grid-template-columns: 1fr; }
  .press-feature-text { min-height: 0; padding: 0; }
  .press-feature-card { aspect-ratio: 16/10; }
  .press-feature-quote { white-space: normal; font-size: 19px; }
  .press-feature-cta { align-self: flex-start; }
  .phil-pair { grid-template-columns: 1fr; padding: 56px 0 64px; gap: 52px 0; }
  .phil-pair .phil-block--b,
  .phil-pair--rev .phil-block--a { padding-top: 0; }
  .phil-num { font-size: clamp(80px, 18vw, 112px); }
  .phil-body { max-width: 100%; }
}

/* ═══════════════════════════════════════════════════════════════════
   Page: projects — filter row + two-column grid
   ═══════════════════════════════════════════════════════════════════ */
.projects-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(56px, 6vw, 96px) clamp(40px, 4vw, 64px);
  grid-auto-rows: min-content;
  max-width: 1400px;
  margin: 0 auto;
  padding: 64px 52px;
}
.proj-card {
  text-decoration: none;
  display: block;
  position: relative;
  transition: opacity .22s ease;
  /* Don't stretch to row height — when a card shares a row with a taller
     sibling (different aspect-ratio + column span combo), default
     align-self:stretch makes this card taller than its image, and the
     meta row beneath would float into the gap. */
  align-self: start;
}
.proj-card-img { width: 100%; overflow: hidden; position: relative; }
/* Hover scale is driven by GSAP in initProjects() (transitions.js).
   No CSS `transition: transform` here: a CSS-owned tween on the same
   property the FLIP morph reads via getBoundingClientRect would latch
   onto a mid-tween rect on click and snap on morph start. */
.proj-card-img-inner {
  width: 100%; height: 100%;
  will-change: transform;
}

/* Meta row — sits below the image, always visible. Left text column
   (eyebrow location · type + project name), right num badge. */
.proj-card-info {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  padding: 22px 4px 0;
}
.proj-card-text { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.proj-card-eyebrow {
  font-family: var(--ff-synonym);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--navy);
  display: flex;
  align-items: center;
  gap: 8px;
}
.proj-card-eyebrow .dot {
  display: inline-block;
  width: 3px; height: 3px;
  border-radius: 50%;
  background: var(--navy);
  opacity: 0.55;
}
.proj-card-name {
  font-family: var(--ff-day);
  font-size: 24px;
  font-weight: 400;
  letter-spacing: -0.005em;
  line-height: 1.05;
  color: var(--navy);
  margin: 0;
  transition: color .35s var(--ease-quint);
}
.proj-card:hover .proj-card-name,
.proj-card:focus-visible .proj-card-name { color: var(--terracotta); }
.proj-card-num {
  font-family: var(--ff-synonym);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  color: var(--terracotta);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
  padding-top: 6px;
}
.proj-card.hidden { display: none; }

@media (prefers-reduced-motion: reduce) {
  .proj-card-name { transition: none; }
}

.filter-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  padding: 24px 52px;
  border-bottom: 1px solid var(--rule);
}
.filter-btn {
  font-family: var(--ff-synonym);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .26em;
  text-transform: uppercase;
  padding: 12px 20px;
  border: 1px solid var(--rule);
  color: var(--ink-mute);
  background: none;
  cursor: pointer;
  transition: background .25s, color .25s, border-color .25s;
}
.filter-btn.active {
  background: var(--navy);
  color: var(--bg);
  border-color: var(--navy);
}
/* Hover changes text colour only — border stays put (user-tested). */
.filter-btn:hover { color: var(--terracotta); }
.filter-btn.active:hover { color: var(--terracotta); }

@media (max-width: 900px) {
  .projects-grid { gap: 2.5rem; padding: 28px 24px; }
  .proj-card-info { padding: 16px 0 0; gap: 16px; }
}
@media (max-width: 540px) {
  .projects-grid { grid-template-columns: 1fr; gap: 2rem; padding: 20px; }
}
@media (max-width: 767px) {
  .filter-row { padding: 16px 20px !important; }
}

/* ═══════════════════════════════════════════════════════════════════
   Page: press
   ═══════════════════════════════════════════════════════════════════ */
.press-list { max-width: 1200px; margin: 0 auto; padding: 0 52px; }
.press-item {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 72px;
  align-items: center;
  padding: 80px 0;
  border-bottom: 1px solid var(--rule);
  opacity: 0; /* GSAP reveals */
}
.press-item:nth-child(even) { direction: rtl; }
.press-item:nth-child(even) > * { direction: ltr; }
.press-img { overflow: hidden; position: relative; }
.press-img-inner {
  width: 100%;
  aspect-ratio: 4/3;
  transition: transform .8s cubic-bezier(.22,1,.36,1);
}
.press-item:hover .press-img-inner { transform: scale(1.03); }
.press-pub {
  font-family: var(--ff-synonym);
  font-size: 14px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--azure);
  margin-bottom: 10px;
  font-weight: 500;
}
.press-year {
  font-family: var(--ff-synonym);
  font-size: 12px;
  letter-spacing: .18em;
  color: var(--terracotta);
  margin-bottom: 24px;
  font-weight: 500;
}
.press-quote {
  font-family: var(--ff-day);
  font-size: clamp(16px, 1.6vw, 19px);
  font-weight: 400;
  font-style: normal;
  line-height: 1.9;
  color: var(--navy);
  margin: 0 0 32px;
  max-width: 480px;
}
.press-quote::before {
  content: "\201C";
  display: block;
  margin: 0 0 24px;
  color: var(--terracotta);
  font-family: var(--ff-day), serif;
  font-size: 56px;
  line-height: 0.6;
}
.press-quote.zh {
  font-family: var(--ff-taipei-sans);
  letter-spacing: 0.05em;
}
.press-desc {
  font-family: var(--ff-taipei-sans);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.9;
  color: var(--ink-body);
  margin-top: 20px;
  letter-spacing: 0.05em;
}
.press-read-more {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 20px;
  font-family: var(--ff-synonym);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--navy);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 3px;
  transition: color .3s, border-color .3s;
}
.press-read-more:hover { color: var(--terracotta); border-color: var(--terracotta); }

@media (max-width: 900px) {
  .press-list { padding: 0 24px; }
  .press-item {
    grid-template-columns: 1fr;
    gap: 32px;
    padding: 52px 0;
    direction: ltr !important;
  }
  .press-item:nth-child(even) > * { direction: ltr; }
}

/* ═══════════════════════════════════════════════════════════════════
   Page: contact — namespaced so global <main> stays untouched
   ═══════════════════════════════════════════════════════════════════ */
main[data-barba-namespace="contact"] {
  margin-top: 0;
  display: grid;
  grid-template-columns: 38% 1fr;
  position: relative;
  min-height: 100vh;
}
main[data-barba-namespace="contact"] .contact-content {
  order: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 52px;
  background: var(--bg);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform: translateZ(0);
}
.contact-eyebrow {
  font-family: var(--ff-synonym);
  font-size: 12px;
  letter-spacing: .32em;
  text-transform: lowercase;
  color: var(--terracotta);
  display: flex;
  align-items: center;
  gap: 14px;
  font-weight: 500;
  margin-bottom: 24px;
}
.contact-eyebrow::before {
  content: '';
  width: 22px;
  height: 1px;
  background: var(--terracotta);
  display: block;
}
.contact-h {
  font-family: var(--ff-day);
  font-size: clamp(42px, 6vw, 84px);
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--navy);
  line-height: .95;
  margin: 0;
}
.contact-h em {
  font-style: italic;
  color: var(--azure);
  display: block;
  font-size: .85em;
  letter-spacing: .02em;
}
.contact-p {
  font-family: var(--ff-taipei-sans);
  font-size: 14px;
  font-weight: 500;
  line-height: 2;
  color: var(--ink-body);
  max-width: 360px;
  margin: 20px 0 36px;
  letter-spacing: 0.05em;
}

main[data-barba-namespace="contact"] .contact-img {
  order: 2;
  position: relative;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform: translateZ(0);
}
.contact-img-inner {
  position: absolute;
  inset: 0;
  background: linear-gradient(155deg, #B8C8D4 0%, #7A9AAC 35%, #4A7A90 65%, #1E5468 100%);
  background-size: cover;
  background-position: center;
  transition: transform 1.4s cubic-bezier(.22,1,.36,1);
}
.contact-img:hover .contact-img-inner { transform: scale(1.04); }
.contact-img-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  background: linear-gradient(to left, transparent 90%, var(--bg) 100%);
}
.email-label {
  font-family: var(--ff-synonym);
  font-size: 12px;
  letter-spacing: .3em;
  text-transform: lowercase;
  color: #7b7777;
  margin-bottom: 10px;
  font-weight: 400;
}
.email-link {
  font-family: var(--ff-synonym);
  font-size: 18px;
  font-weight: 500;
  letter-spacing: .06em;
  color: var(--navy);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 14px;
  display: inline-block;
  transition: color .3s, border-color .3s;
}
.email-link:hover { color: var(--azure); border-color: var(--azure); }

@media (max-width: 900px) {
  main[data-barba-namespace="contact"] {
    grid-template-columns: 1fr;
    min-height: auto;
  }
  main[data-barba-namespace="contact"] .contact-content {
    order: 1;
    min-height: 50vh;
    padding: 96px 24px 36px;
  }
  main[data-barba-namespace="contact"] .contact-img {
    order: 2;
    min-height: 300px;
    height: 55vw;
  }
}
@media (max-width: 767px) {
  main[data-barba-namespace="contact"] .contact-content { padding-top: 200px; }
}

/* ═══════════════════════════════════════════════════════════════════
   Page: project (detail pages — namespace="project")
   ═══════════════════════════════════════════════════════════════════ */
.proj-header {
  margin-top: 0;
  padding: calc(80px + 12vh) 52px 36px;
  border-bottom: 1px solid var(--rule);
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: 40px;
}
/* Breadcrumb + title column. Flex w/ explicit gap so the back-link
   can never collide with .proj-title (which uses line-height:1 — its
   line box is tight and a sibling sitting flush above it has no slack
   to absorb a transform or a clamp() upper-bound on smaller screens). */
.proj-header > div:first-child {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
}
.proj-breadcrumb {
  font-size: 10px;
  letter-spacing: .2em;
  text-transform: lowercase;
  color: var(--ink-mute);
}
.proj-breadcrumb a { color: var(--azure); text-decoration: none; transition: color .3s; }
.proj-breadcrumb a:hover { color: var(--navy); }
.proj-title {
  font-family: var(--ff-day);
  font-size: clamp(26px, 3.6vw, 48px);
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--navy);
  line-height: 1;
  margin: 0;
}
.proj-title .zh {
  font-family: var(--ff-taipei-sans);
  font-weight: 300;
  letter-spacing: 0.04em;
  margin-right: 6px;
}
.proj-meta { text-align: right; display: flex; flex-direction: column; gap: 5px; }
.proj-meta-item {
  font-family: var(--ff-taipei-sans);
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--ink-mute);
}
.proj-meta-item strong { color: var(--navy); font-weight: 400; }

.proj-hero { width: 100%; overflow: hidden; }
.proj-hero .ph {
  width: 100%;
  aspect-ratio: 16/9;
  background: var(--bg-mid);
  overflow: hidden;
  will-change: transform;
}
.proj-hero .ph div, .proj-hero .ph img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Transition lives on the base class so the scale-down on mouse-leave
     is as slow + organic as the scale-up — the brief calls this out
     specifically. Same easing as .atelier-row-img on the landing
     page, so the entire site shares one canonical hover-zoom feel. */
  transition: transform 1.2s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.proj-hero:hover .ph div, .proj-hero:hover .ph img { transform: scale(1.04); }

.article { max-width: 1100px; margin: 0 auto; padding: 80px 52px 120px; }
.a-intro {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 64px;
  align-items: start;
  margin-bottom: 72px;
  padding-bottom: 72px;
  border-bottom: 1px solid var(--rule);
}
.a-meta-row { margin-bottom: 22px; }
.a-ml {
  font-family: var(--ff-synonym);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: .08em;
  color: #7b7777;
  margin-bottom: 4px;
}
.a-mv {
  font-family: var(--ff-taipei-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.05em;
  color: var(--navy);
}
.a-h {
  font-family: var(--ff-day);
  font-size: clamp(18px, 2.2vw, 26px);
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--navy);
  line-height: 1.35;
  margin-bottom: 20px;
}
.a-p {
  font-family: var(--ff-taipei-sans);
  font-size: 14px;
  font-weight: 500;
  line-height: 2;
  color: var(--ink-body);
  letter-spacing: 0.05em;
}
.a-p + .a-p { margin-top: 14px; }

.img-block { overflow: hidden; background: var(--bg-mid); }
.img-block > div:not(.p-cap), .img-block > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Canonical media-zoom timing — see .atelier-row-img / .proj-hero. */
  transition: transform 1.2s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.img-block:hover > div:not(.p-cap), .img-block:hover > img { transform: scale(1.04); }

/* Captioned img-block: image keeps its aspect ratio, caption sits below */
.m-pair-lg > .img-block:has(> .p-cap),
.m-pair-sm > .img-block:has(> .p-cap),
.m-two    > .img-block:has(> .p-cap) {
  overflow: visible;
  aspect-ratio: auto;
  background: transparent;
}
.m-pair-lg > .img-block:last-child:has(> .p-cap)  > div:not(.p-cap):first-child { aspect-ratio: 3/4; height: auto; overflow: hidden; background: var(--bg-mid); }
.m-pair-lg > .img-block:first-child:has(> .p-cap) > div:not(.p-cap):first-child { aspect-ratio: 4/3; height: auto; overflow: hidden; background: var(--bg-mid); }
.m-pair-sm > .img-block:last-child:has(> .p-cap)  > div:not(.p-cap):first-child { aspect-ratio: 4/3; height: auto; overflow: hidden; background: var(--bg-mid); }
.m-pair-sm > .img-block:first-child:has(> .p-cap) > div:not(.p-cap):first-child { aspect-ratio: 3/4; height: auto; overflow: hidden; background: var(--bg-mid); }
.m-two    > .img-block:has(> .p-cap)              > div:not(.p-cap):first-child { aspect-ratio: 4/5; height: auto; overflow: hidden; background: var(--bg-mid); }

.m-img .p-cap,
.img-block .p-cap {
  margin-top: 0.5rem;
  margin-bottom: 0;
}

.p-full { margin-bottom: 6px; }
.p-full .img-block { width: 100%; aspect-ratio: 3/2; }

.p-two { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 6px; }
.p-two .img-block { aspect-ratio: 4/5; }

.p-lg-sm {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: 6px;
  align-items: start;
  margin-bottom: 6px;
}
.p-lg-sm .img-block:first-child { aspect-ratio: 4/3; }
.p-lg-sm .img-block:last-child  { aspect-ratio: 3/4; }

.p-sm-lg {
  display: grid;
  grid-template-columns: 1fr 1.6fr;
  gap: 6px;
  align-items: start;
  margin-bottom: 6px;
}
.p-sm-lg .img-block:first-child { aspect-ratio: 3/4; }
.p-sm-lg .img-block:last-child  { aspect-ratio: 4/3; }

.p-offset-l { width: 62%; margin-bottom: 6px; }
.p-offset-l .img-block { aspect-ratio: 4/3; }
.p-offset-r { width: 62%; margin-left: auto; margin-bottom: 6px; }
.p-offset-r .img-block { aspect-ratio: 4/3; }
.p-mid { width: 75%; margin: 0 auto 6px; }
.p-mid .img-block { aspect-ratio: 3/2; }

.p-cap {
  font-family: var(--ff-taipei-sans);
  font-size: 10px;
  letter-spacing: 0.18em;
  color: var(--ink-mute);
  margin-bottom: 48px;
}
.p-cap.right { text-align: right; }
.p-cap.center { text-align: center; }

/* ─── Editorial layout (proj-editorial) ───
   12-column grid for hand-tuned project pages. Sections opt in by
   wrapping content in <section class="proj-editorial proj-natural">,
   then each row uses .ed-row with .ed-c-X-Y spans on its children.
   Vertical staggers (.ed-d-*) break top-alignment so paired photos
   feel composed, not gridded. */
.proj-editorial {
  padding: 80px 0 120px;
  background: var(--bg);
}
.ed-row {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: 24px;
  row-gap: 16px;
  align-items: center;
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 52px;
}
.ed-row + .ed-row { margin-top: 140px; }
.ed-row + .ed-row.ed-gap-xl,
.ed-row.ed-gap-xl + .ed-row { margin-top: 240px; }
.ed-row + .ed-row.ed-gap-sm { margin-top: 96px; }

.ed-row .img-block { width: 100%; }
.ed-row .img-block img { display: block; width: 100%; height: auto; }

/* Column spans (start / end, end is exclusive in grid syntax) */
.ed-c-1-3   { grid-column: 1 / 4; }
.ed-c-1-4   { grid-column: 1 / 5; }
.ed-c-1-5   { grid-column: 1 / 6; }
.ed-c-1-6   { grid-column: 1 / 7; }
.ed-c-1-7   { grid-column: 1 / 8; }
.ed-c-1-9   { grid-column: 1 / 10; }
.ed-c-1-11  { grid-column: 1 / 12; }
.ed-c-2-4   { grid-column: 2 / 5; }
.ed-c-2-5   { grid-column: 2 / 6; }
.ed-c-2-6   { grid-column: 2 / 7; }
.ed-c-2-7   { grid-column: 2 / 8; }
.ed-c-2-8   { grid-column: 2 / 9; }
.ed-c-3-7   { grid-column: 3 / 8; }
.ed-c-3-8   { grid-column: 3 / 9; }
.ed-c-3-9   { grid-column: 3 / 10; }
.ed-c-3-11  { grid-column: 3 / 12; }
.ed-c-3-13  { grid-column: 3 / 14; }
.ed-c-4-6   { grid-column: 4 / 7; }
.ed-c-4-9   { grid-column: 4 / 10; }
.ed-c-4-12  { grid-column: 4 / 13; }
.ed-c-5-8   { grid-column: 5 / 9; }
.ed-c-5-10  { grid-column: 5 / 11; }
.ed-c-5-11  { grid-column: 5 / 12; }
.ed-c-5-12  { grid-column: 5 / 13; }
.ed-c-6-11  { grid-column: 6 / 12; }
.ed-c-7-10  { grid-column: 7 / 11; }
.ed-c-7-12  { grid-column: 7 / 13; }
.ed-c-8-12  { grid-column: 8 / 13; }
.ed-c-9-12  { grid-column: 9 / 13; }
.ed-c-9-11  { grid-column: 9 / 12; }
.ed-c-1-13  { grid-column: 1 / -1; }

/* Vertical staggers */
.ed-d-60    { margin-top: 60px; }
.ed-d-80    { margin-top: 80px; }
.ed-d-100   { margin-top: 100px; }
.ed-d-120   { margin-top: 120px; }
.ed-d-140   { margin-top: 140px; }
.ed-d-180   { margin-top: 180px; }

/* Aspect-ratio presets for placeholder pages (overridden by .proj-natural).
   Apply directly to .img-block to give gradient placeholders a height. */
.ed-ar-l    { aspect-ratio: 3 / 2; }    /* standard landscape */
.ed-ar-lw   { aspect-ratio: 16 / 9; }   /* wide landscape */
.ed-ar-43   { aspect-ratio: 4 / 3; }    /* slightly squarer landscape */
.ed-ar-sq   { aspect-ratio: 1 / 1; }    /* square */
.ed-ar-45   { aspect-ratio: 4 / 5; }    /* slight portrait */
.ed-ar-p    { aspect-ratio: 3 / 4; }    /* portrait */
.ed-ar-pt   { aspect-ratio: 2 / 3; }    /* tall portrait */

/* Full-bleed escape from the 1400px container */
.ed-bleed {
  grid-column: 1 / -1;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}
.ed-bleed .img-block,
.ed-bleed .img-block img { width: 100%; }

/* Editorial captions — josefin, sit directly under the photo they label.
   Captions live inside the column wrapper alongside their .img-block so
   they always anchor to the bottom-left of a specific photo, regardless
   of staggers on neighbouring items. */
.ed-cap {
  font-family: var(--ff-synonym);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: lowercase;
  color: var(--ink-mute);
  margin-top: 10px;
}
.ed-cap.--right { text-align: right; }

/* Editorial chapter text — reuses .a-h / .a-p inside, just constrains placement */
.ed-text .a-h { margin-bottom: 18px; }
.ed-text .a-p { margin-bottom: 16px; }
.ed-text .a-p:last-child { margin-bottom: 0; }

.a-mid { max-width: 600px; margin: 52px auto 32px; }

/* Next-project gallery — depth-of-field carousel.
   Replaces the legacy single-link `.next-proj` block. JS-built slides
   are absolutely positioned over .ng-stage; classes (is-center /
   is-prev / is-next / is-far-prev / is-far-next) drive the transforms.
   Curve is the shared --ease-quint. */
.next-gallery {
  border-top: 1px solid var(--rule);
  padding: 40px 0 80px;
  overflow: hidden;
  position: relative;
}
.next-gallery-head {
  max-width: 1400px;
  margin: 0 auto 20px;
  padding: 0 clamp(24px, 4vw, 52px);
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 24px;
}
.ng-title {
  font-family: var(--ff-day);
  font-size: 28px;
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--navy);
  margin: 0;
}
.ng-stage {
  position: relative;
  width: 100%;
  height: 500px;
  perspective: 1600px;
}
.ng-track {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
}
.ng-slide {
  position: absolute;
  top: 0;
  left: 50%;
  /* Cap at 750px so the 3:2 image lands at 750×500 — exact match to the
     500px stage, no leftover bg-mid band beneath the photo. */
  width: clamp(500px, 56vw, 750px);
  height: 100%;
  margin-left: calc(clamp(500px, 56vw, 750px) / -2);
  transform-origin: center center;
  will-change: transform, opacity;
  transition:
    transform 1.1s var(--ease-quint),
    opacity   0.9s var(--ease-quint);
  cursor: pointer;
  user-select: none;
}
.ng-slide.is-center { cursor: default; z-index: 3; }
.ng-slide.is-prev,
.ng-slide.is-next  { z-index: 2; }
.ng-slide.is-far   { z-index: 1; }
.ng-slide.is-center  { transform: translateX(0)     scale(1);    opacity: 1; }
.ng-slide.is-prev    { transform: translateX(-78%)  scale(0.62); opacity: 0.55; }
.ng-slide.is-next    { transform: translateX(78%)   scale(0.62); opacity: 0.55; }
.ng-slide.is-far-prev { transform: translateX(-130%) scale(0.5); opacity: 0; pointer-events: none; }
.ng-slide.is-far-next { transform: translateX(130%)  scale(0.5); opacity: 0; pointer-events: none; }

.ng-slide-img {
  position: relative;
  width: 100%;
  aspect-ratio: 3/2;       /* landscape — matches actual project cover crops */
  height: auto;
  max-height: 100%;
  background: var(--bg-mid);
  overflow: hidden;
}
.ng-slide-img img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}

/* Meta sits below the slide so its position is independent of the
   slide's transform-origin. Only the centered slide reveals it, after
   a 350ms delay so the text fades in once the image has settled. */
.ng-slide-meta {
  position: absolute;
  left: 0; right: 0;
  top: 100%;
  margin-top: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
}
.ng-slide.is-center .ng-slide-meta {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity   0.7s var(--ease-quint) 0.35s,
    transform 0.7s var(--ease-quint) 0.35s;
}
.ng-slide-num {
  font-family: var(--ff-synonym);
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--terracotta);
  margin-bottom: 4px;
}
.ng-slide-name {
  font-family: var(--ff-day);
  font-size: 20px;
  font-weight: 400;
  letter-spacing: -0.005em;
  color: var(--navy);
  line-height: 1.1;
  text-decoration: none;
}

/* Magazine rhythm */
.m-two { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-bottom: 4px; }
.m-two .img-block { aspect-ratio: 4/5; overflow: hidden; }

.m-spread {
  display: grid;
  gap: 64px;
  align-items: start;
  margin-top: 96px;
  margin-bottom: 96px;
}
.m-spread.--l { grid-template-columns: 58% 1fr; }
.m-spread.--r { grid-template-columns: 1fr 58%; }
.m-img { overflow: hidden; }
.m-img .img-block { width: 100%; aspect-ratio: 4/3; overflow: hidden; }
.m-img .img-block:hover div { transform: scale(1.04); }
.m-txt { display: flex; flex-direction: column; justify-content: center; padding-top: 20px; }
.m-txt .a-h { margin-bottom: 18px; }
.m-txt .a-p + .a-p { margin-top: 14px; }
.m-txt .p-cap { margin-top: 24px; margin-bottom: 0; }

.m-pair-lg {
  display: grid;
  grid-template-columns: 1.65fr 1fr;
  gap: 4px;
  align-items: start;
  margin-bottom: 4px;
}
.m-pair-lg .img-block:first-child { aspect-ratio: 4/3; overflow: hidden; }
.m-pair-lg .img-block:last-child  { aspect-ratio: 3/4; overflow: hidden; }
.m-pair-sm {
  display: grid;
  grid-template-columns: 1fr 1.65fr;
  gap: 4px;
  align-items: start;
  margin-bottom: 4px;
}
.m-pair-sm .img-block:first-child { aspect-ratio: 3/4; overflow: hidden; }
.m-pair-sm .img-block:last-child  { aspect-ratio: 4/3; overflow: hidden; }

.m-two + .p-cap,
.m-pair-lg + .p-cap,
.m-pair-sm + .p-cap { margin-bottom: 72px; }

/* ─── Photo-based projects: opt out of forced aspect-ratios ───
   Real-photo projects opt in by adding `proj-natural` to <main>.
   Layout containers (.p-full, .m-two, .p-offset-r) keep their grid
   role but stop enforcing a shape on .img-block — the photo's own
   ratio decides the height. .m-two switches to align-items:start
   so paired photos with different ratios stack at their tops
   instead of stretching to match. */
.proj-natural .proj-hero .ph,
.proj-natural .proj-hero .ph img {
  aspect-ratio: auto;
  height: auto;
}
.proj-natural .article .p-full .img-block,
.proj-natural .article .m-two  .img-block,
.proj-natural .article .p-offset-r .img-block,
.proj-natural .article .p-mid .img-block,
.proj-editorial.proj-natural .img-block,
.proj-natural .proj-editorial .img-block {
  aspect-ratio: auto;
}
.proj-natural .article .img-block,
.proj-editorial.proj-natural .img-block,
.proj-natural .proj-editorial .img-block { background: transparent; }
.proj-natural .article .img-block > img,
.proj-editorial.proj-natural .img-block > img,
.proj-natural .proj-editorial .img-block > img {
  width: 100%;
  height: auto;
  object-fit: initial;
}
.proj-natural .article .m-two { align-items: start; }

/* Cover cards (home + listing) when carrying a real photo */
.featured-card-img.is-natural,
.proj-card-img-inner.is-natural {
  aspect-ratio: auto;
  background-image: none !important;
}
.featured-card-img.is-natural > img,
.proj-card-img-inner.is-natural > img {
  display: block;
  width: 100%;
  height: auto;
}

/* Project Gallery — horizontal "all photos" strip between .article and the
   next-project carousel. Items are populated by initProjGallery() in
   transitions.js (clones of every .article .img-block). Each clone gets its
   source aspect-ratio set inline so portrait + landscape images sit at one
   height with varying widths. Dormant on current pages — no .pg-track is
   rendered in the HTML — but retained as opt-in styling. */
.proj-gallery {
  padding: 8rem 0 4rem;
  background-color: var(--bg-mid);
  border-top: 1px solid var(--rule);
  overflow: hidden;
}
.pg-header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
  margin-bottom: 3rem;
  padding: 0 52px;
}
.pg-label {
  font-family: var(--ff-synonym);
  font-size: 1.2rem;
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: lowercase;
  color: var(--navy);
}
.pg-track {
  display: flex;
  gap: 2rem;
  overflow-x: auto;
  padding: 0 52px 2rem;
  -ms-overflow-style: none;    /* IE / old Edge */
  scrollbar-width: none;       /* Firefox */
  -webkit-overflow-scrolling: touch;
}
.pg-track::-webkit-scrollbar { display: none; }   /* Chrome / Safari */
.pg-track.dragging a { pointer-events: none; }

.pg-item {
  flex: 0 0 auto;
  height: 55vh;
  width: auto;
}
.pg-item .img-block {
  height: 100%;
  width: auto;
  /* aspect-ratio is set inline by JS from each source img-block. */
}
.pg-item img {
  height: 100%;
  width: auto;
  object-fit: cover;
}

@media (max-width: 900px) {
  .proj-header { padding: 72px 24px 28px; grid-template-columns: 1fr; }
  .proj-title { font-size: 32px; }
  .proj-meta { text-align: left; flex-direction: row; flex-wrap: wrap; gap: 12px; }
  .article { padding: 48px 24px 80px; }
  .a-intro { grid-template-columns: 1fr; gap: 32px; }
  .p-two { grid-template-columns: 1fr; }
  .p-two .img-block { aspect-ratio: 4/3; }
  .p-lg-sm, .p-sm-lg { grid-template-columns: 1fr; }
  .p-lg-sm .img-block:last-child,
  .p-sm-lg .img-block:first-child { aspect-ratio: 4/3; }
  .p-offset-l, .p-offset-r { width: 88%; margin-left: 0; }
  .p-mid { width: 100%; }

  /* Editorial collapses to a single readable column on small screens.
     All staggers and asymmetric spans flatten so the reading rhythm
     comes from sequence + vertical breathing, not from grid placement. */
  .proj-editorial { padding: 48px 0 80px; }
  .ed-row { grid-template-columns: 1fr; padding: 0 24px; column-gap: 0; row-gap: 24px; }
  .ed-row + .ed-row { margin-top: 80px; }
  .ed-row + .ed-row.ed-gap-xl,
  .ed-row.ed-gap-xl + .ed-row { margin-top: 100px; }
  .ed-row > [class*="ed-c-"] { grid-column: 1 / -1; }
  .ed-row > [class*="ed-d-"] { margin-top: 0; }
  .ed-cap { align-self: start; padding-bottom: 0; padding-top: 4px; }

  /* Next-project gallery — drop side peek further on small screens so
     the centered slide still owns the frame. Stage/slide sizes match
     the design system spec (section 8). */
  .next-gallery { padding: 64px 0 88px; }
  .next-gallery-head {
    padding: 0 24px;
    flex-direction: column;
    align-items: flex-start;
    gap: 24px;
  }
  .ng-stage { height: clamp(320px, 70vw, 460px); }
  .ng-slide { width: clamp(260px, 78vw, 420px); margin-left: calc(clamp(260px, 78vw, 420px) / -2); }
  .ng-slide.is-prev { transform: translateX(-92%) scale(0.5); opacity: 0.35; }
  .ng-slide.is-next { transform: translateX(92%)  scale(0.5); opacity: 0.35; }

  .m-spread { grid-template-columns: 1fr; gap: 32px; margin-top: 56px; margin-bottom: 56px; }
  .m-spread.--r .m-img { order: 1; }
  .m-spread.--r .m-txt { order: 2; }
  .m-two { grid-template-columns: 1fr 1fr; }
  .m-pair-lg, .m-pair-sm { grid-template-columns: 1fr; }
  .m-pair-lg .img-block:last-child,
  .m-pair-sm .img-block:first-child { aspect-ratio: 4/3; }

  .proj-gallery { padding: 5rem 0 3rem; }
  .pg-header { padding: 0 24px; gap: 0.3rem; margin-bottom: 1.5rem; }
  .pg-label  { font-size: 1rem; }
  .pg-track  { padding: 0 24px 1.5rem; gap: 1rem; }
  .pg-item   { height: 40vh; }
}

/* ───────────────────────────────────────────────────────────
   Featured Projects — asymmetric masonry on landing page.
   12-col grid with grid-auto-flow:dense; per-card parallax driven by
   GSAP ScrollTrigger (transitions.js initFeaturedParallax). Hover
   scale lives on .featured-card-img while parallax transforms the
   parent .featured-card so the two transforms never fight.
   ─────────────────────────────────────────────────────────── */
.featured-section {
  padding: clamp(120px, 16vw, 200px) 0 clamp(140px, 18vw, 240px);
  background: var(--bg);
}
.featured-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(56px, 6vw, 96px) clamp(40px, 4vw, 64px);
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 52px;
}
.featured-card {
  position: relative;
  display: block;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  -webkit-tap-highlight-color: transparent;
  /* Same rationale as .proj-card: prevent grid stretch so the absolute
     meta row pins to the image bottom, never to a stretched empty area. */
  align-self: start;
}
.featured-card:focus-visible {
  outline: 2px solid var(--azure-light);
  outline-offset: 6px;
}
.featured-card-img {
  width: 100%;
  /* position: relative so the bottom-scrim ::after anchors to this
     element's box (and tracks its hover scale) rather than jumping
     to .featured-card the moment transform creates a containing block. */
  position: relative;
  background-size: cover;
  background-position: center;
  transition: transform 1.2s cubic-bezier(.22, 1, .36, 1);
  will-change: transform;
}
.featured-card:hover .featured-card-img,
.featured-card:focus-visible .featured-card-img { transform: scale(1.04); }

/* Bottom scrim — same treatment as .proj-card-img::after. Fades in
   alongside the meta so the card reads clean at rest and the meta gets
   a darkened ground only when the user is actually engaging. */
.featured-card-img::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 40%;
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.58) 0%,
    rgba(0, 0, 0, 0.32) 50%,
    rgba(0, 0, 0, 0)    100%
  );
  opacity: 0;
  transition: opacity .5s ease .12s;
  pointer-events: none;
}
.featured-card:hover .featured-card-img::after,
.featured-card:focus-visible .featured-card-img::after { opacity: 1; }

/* Meta is absolutely pinned to the card's bottom edge so its position is
   independent of the image aspect ratio (16:9 vs 3:4 vs 4:3 all align). The
   24px 30px padding keeps the text 24px above the bottom and 30px in from the
   sides; flex spreads name <-> year on a single baseline. */
.featured-card-meta {
  position: absolute !important;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 24px 30px !important;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  font-family: var(--ff-synonym);
  font-weight: 300;
  font-size: 10px;
  letter-spacing: .30em;
  text-transform: uppercase;
  color: #fff;
  /* Three-layer shadow — see .proj-card-name for the rationale. */
  text-shadow:
    0 1px 1px  rgba(0, 0, 0, .85),
    0 1px 2px  rgba(0, 0, 0, .60),
    0 2px 14px rgba(0, 0, 0, .45);
  pointer-events: none;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity .5s ease .12s, transform .6s cubic-bezier(.22, 1, .36, 1) .12s;
}
.featured-card:hover .featured-card-meta,
.featured-card:focus-visible .featured-card-meta {
  opacity: 1;
  transform: translateY(0);
  color: #fff;
}

@media (max-width: 900px) {
  .featured-grid {
    grid-template-columns: 1fr;
    padding: 0 24px;
    gap: 48px;
  }
  .featured-card {
    grid-column: 1 / -1 !important;
    grid-row: auto !important;
    transform: none !important;
  }
  .featured-card-img:not(.is-natural) { aspect-ratio: 4/3 !important; }
  .featured-card-img::after {
    opacity: 1;
    transition: none;
  }
  .featured-card-meta {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .featured-card { transform: none !important; }
  .featured-card-img { transition: none; }
  .featured-card-img::after { transition: none; }
}
