/* ==========================================================================
   Jason Anderson Studio — Design System
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

@font-face {
  font-family: 'Noto Sans CJK SC Local';
  src: url('../assets/fonts/NotoSansCJKsc-Regular.otf') format('opentype');
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
}

@font-face {
  font-family: 'Noto Sans CJK JP Local';
  src: url('../assets/fonts/NotoSansCJKjp-Regular.otf') format('opentype');
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
}

:root {
  --bg: #000000;
  --bg-raised: #141414;
  --bg-input: #0a0a0a;
  --text: #f7f8f6;
  --text-dim: rgba(247, 248, 246, 0.72);
  --text-faint: rgba(247, 248, 246, 0.5);
  --border: rgba(247, 248, 246, 0.25);
  --border-strong: rgba(247, 248, 246, 0.5);
  --focus: #f7f8f6;
  --scrub-accent: #e8b34a;

  --font-accent: 'Times New Roman', Times, Georgia, serif;
  --font-sans: 'Inter', 'Helvetica Neue', Arial, sans-serif;

  /* Revision (2026-09-06) — client asked for a full pass giving the whole
     site more editorial breathing room. Widened the outer gutter a touch
     (max 100px → 120px) — every section below is inset from this, so a
     more generous margin on large screens compounds through the site
     rather than needing to be redone section by section. */
  --gutter: clamp(24px, 6.5vw, 120px);
  --service-indent: clamp(24px, 5.5vw, 96px);
  --container-max: 1760px;

  --nav-h: clamp(72px, 8vw, 104px);
}

/* Light mode — the same pair, inverted: Alabaster ground with Black text
   and logos. Everything on the site is built from these tokens (no
   hardcoded colors elsewhere in this file), so this one block is the
   entire light theme. Toggled via [data-theme="light"] on <html>, see
   initThemeToggle() in main.js and the anti-flash inline script in <head>. */
:root[data-theme="light"] {
  --bg: #f7f8f6;
  --bg-raised: #ececea;
  --bg-input: #ffffff;
  --text: #000000;
  --text-dim: rgba(0, 0, 0, 0.72);
  --text-faint: rgba(0, 0, 0, 0.5);
  --border: rgba(0, 0, 0, 0.2);
  --border-strong: rgba(0, 0, 0, 0.45);
  --focus: #000000;
  --scrub-accent: #b8862c;
}

* {
  box-sizing: border-box;
}

/* Guarantee the native `hidden` attribute always wins, even on elements
   whose class also sets `display` (e.g. .booking-form { display: grid }) —
   without this, the cascade lets that class override [hidden]. */
[hidden] {
  display: none !important;
}

html {
  background: var(--bg);
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

html[data-i18n-pending] body { visibility: hidden; }

body.nav-open,
body.language-open {
  overflow: hidden;
}

/* Locally hosted CJK typefaces keep regional glyph forms consistent. */
html:lang(zh-Hans) {
  --font-sans: 'Noto Sans CJK SC Local', 'PingFang SC', sans-serif;
  --font-accent: 'Noto Sans CJK SC Local', 'PingFang SC', sans-serif;
}

html:lang(ja) {
  --font-sans: 'Noto Sans CJK JP Local', 'Hiragino Sans', sans-serif;
  --font-accent: 'Noto Sans CJK JP Local', 'Hiragino Sans', sans-serif;
}

html:lang(zh-Hans) body {
  font-family: 'Noto Sans CJK SC Local', 'PingFang SC', sans-serif;
}

html:lang(ja) body {
  font-family: 'Noto Sans CJK JP Local', 'Hiragino Sans', sans-serif;
}

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

img, video {
  height: auto;
  object-fit: contain;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font-family: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

input, textarea {
  font-family: inherit;
  color: inherit;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

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

/* Focus visibility */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 1px solid var(--focus);
  outline-offset: 3px;
}

/* ==========================================================================
   Header
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: var(--nav-h);
  padding: 0 var(--gutter);
  background: var(--bg);
  border-bottom: 1px solid transparent;
}

.header-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  margin: -8px;
}

/* Revision (2026-09-06) — client asked for the icon to read as two lines,
   with the open state as a plus sign rather than the classic X. Switched
   from a flex stack of bars to two absolutely-positioned bars sharing
   one center point, so the same two bars can either sit apart as two
   horizontal strokes or cross at the center as a "+".

   Revision (2026-09-06, same day) — client then asked for the resting
   icon to be the plus sign itself (live on the site at all times, not
   only revealed on interaction), with selecting it popping open the
   Home/About/Services/etc. nav and turning the icon into the two-line
   mark instead — i.e. the two states swapped from the first pass. Also
   widened the gap between the two lines in that open state per the
   client's note. */
.hamburger {
  justify-self: start;
  position: relative;
  width: 42px; /* 26px visual + 8px padding on each side (border-box) */
  height: 34px;
  padding: 0;
  margin: 0;
}

.hamburger .bar {
  position: absolute;
  left: 8px;
  right: 8px;
  top: 17px;
  height: 1px;
  background: var(--text);
  transition: transform 0.35s cubic-bezier(0.65, 0, 0.35, 1), top 0.35s cubic-bezier(0.65, 0, 0.35, 1);
}

/* Resting state — the plus sign, live on the page. */
.hamburger .bar:nth-child(1) {
  transform: translateY(0) rotate(0deg);
}
.hamburger .bar:nth-child(2) {
  transform: translateY(0) rotate(90deg);
}

/* Open state — the nav overlay (Home / About / Services / etc.) is
   showing, and the plus separates into two flat lines. Spaced a bit
   wider apart (6px each way, 12px total) than the first pass. */
.hamburger[aria-expanded="true"] .bar:nth-child(1) {
  transform: translateY(-6px) rotate(0deg);
}
.hamburger[aria-expanded="true"] .bar:nth-child(2) {
  transform: translateY(6px) rotate(0deg);
}

.site-logo {
  justify-self: center;
  width: clamp(72px, 8vw, 108px);
  color: var(--text);
}

.site-logo svg {
  width: 100%;
  height: auto;
}

/* Header logo — living mark. A continuous, slow breathe (scale + a
   gentle dip in opacity) so the mark reads as alive rather than static,
   without ever leaving its spot in the header. Header only: see
   logo_anim_html() in generate_site.py; the footer's mark stays the
   plain, still LOGO_INLINE. One 5s loop, forever. */
.site-header .site-logo .logo-anim {
  display: block;
  animation: logo-breathe 5s cubic-bezier(0.45, 0, 0.55, 1) infinite;
  transform-origin: 50% 50%;
  will-change: transform;
}

@keyframes logo-breathe {
  0%, 100% { transform: scale(1); opacity: 1; }
  50%      { transform: scale(1.1); opacity: 0.86; }
}

@media (prefers-reduced-motion: reduce) {
  .site-header .site-logo .logo-anim {
    animation: none;
  }
}

.header-right {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: clamp(4px, 1vw, 14px);
}

.theme-btn {
  position: relative;
  width: 38px;
  height: 38px;
  color: var(--text);
}

.theme-icon {
  position: absolute;
  inset: 8px;
  display: flex;
  transition: opacity 0.3s ease, transform 0.4s ease;
}

.theme-icon svg {
  width: 100%;
  height: 100%;
}

/* Dark mode (default): sun is the call-to-action ("switch to light").
   Light mode: moon takes over ("switch to dark"). */
.theme-icon-moon {
  /* The mobile treatment keeps the crescent's generous drawing area; the
     desktop alignment override below uses the globe's visual height. */
  inset: 6px;
  opacity: 0;
  transform: rotate(-90deg) scale(0.6);
}

:root[data-theme="light"] .theme-icon-sun {
  opacity: 0;
  transform: rotate(90deg) scale(0.6);
}

:root[data-theme="light"] .theme-icon-moon {
  opacity: 1;
  transform: rotate(0) scale(1);
}

/* Desktop header utility alignment: keep both theme marks within the same
   visual height as the globe and lift them slightly onto the same baseline. */
@media (min-width: 601px) {
  .theme-icon-sun {
    inset: 9px;
    transform: translateY(-2px);
  }

  .theme-icon-moon {
    inset: 9px;
    transform: translateY(-2px) rotate(-90deg) scale(0.6);
  }

  :root[data-theme="light"] .theme-icon-sun {
    transform: translateY(-2px) rotate(90deg) scale(0.6);
  }

  :root[data-theme="light"] .theme-icon-moon {
    transform: translateY(-2px) rotate(0) scale(1);
  }
}

.lang-wrap {
  position: relative;
}

.lang-btn {
  width: 38px; /* 22px visual + 8px padding on each side (border-box) */
  height: 38px;
  color: var(--text);
}

.lang-btn svg {
  width: 100%;
  height: 100%;
  stroke-width: 1;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The header utility marks share one fine, precisely rounded stroke. The
   crescent remains a true crescent, but reads as an airy outline rather than
   a filled silhouette. */
.theme-icon svg {
  stroke-width: 1;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.theme-icon-moon svg {
  fill: none;
  stroke: currentColor;
}

.lang-menu {
  position: absolute;
  top: calc(100% + 14px);
  right: 0;
  z-index: 70;
  min-width: 220px;
  padding: 20px 22px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.22);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s linear 0.2s;
}

.lang-wrap:hover .lang-menu,
.lang-wrap:focus-within .lang-menu,
.lang-wrap.is-open .lang-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.lang-menu-label {
  display: block;
  font-family: var(--font-sans);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 12px;
}

.lang-menu ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.lang-menu button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 7px 2px;
  font-family: var(--font-sans);
  font-size: 0.92rem;
  color: var(--text-dim);
  text-align: left;
  transition: color 0.15s ease;
}

.lang-menu button:hover,
.lang-menu button:focus-visible {
  color: var(--text);
}

.lang-menu button.is-active {
  color: var(--text);
}

.lang-menu button.is-active::after {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text);
  flex-shrink: 0;
}

@media (max-width: 640px) {
  .lang-menu {
    right: -8px;
    min-width: 200px;
  }
}

/* The compact picker is retained in the document for graceful fallback, but
   the live selector now opens the same full-screen menu language as primary
   navigation. */
.lang-menu {
  display: none !important;
}

/* ==========================================================================
   Opening sequence — homepage only.
   Rebuilt 2026-09-06: the old push-through-the-mark zoom is gone. The
   client sent a recording of &Tradition's own site loader — their seal
   mark traces its own outline in one continuous line, then the line
   solidifies into the real mark, holds, and clears. The JAS mark is a
   single unbroken path (see assets/jas-logo.svg — one "M ... z" built
   entirely from straight horizontal/vertical runs), so the same idea
   works as ONE continuous stroke tracing the whole monogram, rather
   than needing to be split into separate pieces the way a multi-part
   mark (a ring, lettering, an inner glyph, each drawn in turn) would
   require.

   The draw itself is pure CSS: stroke-dasharray/stroke-dashoffset both
   set to 13690 — this exact path's total length. That number isn't a
   guess or a runtime measurement; every segment in the path is a
   straight horizontal or vertical run (v/h/V/H commands only), so the
   length is an exact sum of those runs, computed once and hardcoded
   here (see the comment on .intro-mark path below). Setting dasharray
   and dashoffset to the same value produces a single dash exactly as
   long as the whole path, pulled entirely off its start — animating
   dashoffset to 0 "draws" it. initIntroOverlay() in main.js adds two
   classes in sequence: "is-drawing" (the line draws, then crossfades
   into the real filled mark as it finishes) and, after the solid mark
   has held for a beat, "is-leaving".

   Revision (same day) — three client notes after the first pass:
   1. Slow the draw down — was 1.15s, now 2.5s, a much more deliberate
      trace instead of a quick flourish.
   2. Smaller and more editorial — the mark's resting size came down
      (clamp(160px, 22vw, 360px) → clamp(110px, 13vw, 200px)) and the
      stroke got finer (18 → 11 units, against the path's own ~800-unit
      scale) so the drawing phase reads as a delicate line rather than a
      bold one.
   3. The exit is no longer a fade — .intro-overlay now lifts away
      bottom-to-top (transform: translateY(-100%)) like scrolling down
      past a panel to reveal the homepage underneath it, rather than
      dissolving in place.
   4. This now plays on EVERY load of the homepage — including a plain
      refresh — and is never skipped for prefers-reduced-motion. Both
      explicit client asks, so the once-per-session sessionStorage gate
      and the reduced-motion bailout that used to live here are gone
      (see initIntroOverlay() in main.js and the removed
      INTRO_INIT_SCRIPT in generate_site.py) — .intro-overlay always
      renders and always runs, full stop.

   New timing: draw 0→2.5s, crossfade to the solid mark 2.4→3.05s, hold
   to 3.6s, lift-away 3.6→4.6s. Sits on var(--bg) so there's no seam
   with the page it's covering. */

.intro-overlay {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--bg);
  transform: translateY(0);
  transition: transform 1s cubic-bezier(0.65, 0, 0.35, 1);
}

.intro-overlay.is-leaving {
  transform: translateY(-100%);
  pointer-events: none;
}

.intro-mark {
  width: clamp(110px, 13vw, 200px);
  color: var(--text);
}

.intro-mark svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible; /* the stroke sits half outside the path's own
    fill-only edge (stroke is centered on the line), so let it draw
    past the tight viewBox bounds instead of clipping mid-line */
}

.intro-mark path {
  fill: currentColor;
  fill-opacity: 0;
  stroke: currentColor;
  stroke-opacity: 1;
  stroke-width: 11;
  stroke-linejoin: miter;
  /* See the revision note above — 13690 is this path's exact total
     length (v/h/V/H segments only, no curves, so no approximation). */
  stroke-dasharray: 13690;
  stroke-dashoffset: 13690;
  transition:
    stroke-dashoffset 2.5s cubic-bezier(0.65, 0, 0.35, 1),
    fill-opacity 0.65s ease 2.4s,
    stroke-opacity 0.65s ease 2.4s;
}

.intro-overlay.is-drawing .intro-mark path {
  stroke-dashoffset: 0;
  fill-opacity: 1;
  stroke-opacity: 0; /* fades out exactly as the fill fades in, so the
    mark lands on the same crisp solid shape used everywhere else on
    the site — no leftover hairline outline once it's done drawing */
}

html.intro-active,
html.intro-active body {
  overflow: hidden;
  height: 100%;
}

/* ==========================================================================
   Nav overlay
   ========================================================================== */

.nav-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--nav-h) var(--gutter) 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition: opacity 0.35s ease, transform 0.35s ease, visibility 0s linear 0.35s;
}

.nav-overlay.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition: opacity 0.35s ease, transform 0.35s ease;
}

.nav-overlay-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-overlay-list li + li {
  /* Revision (2026-09-06) — widened as part of a full-site spacing pass:
     these links run at display scale (up to 5.2rem), and 14px of gap at
     that size read as crowded rather than considered. */
  margin-top: clamp(10px, 2.2vw, 26px);
}

.nav-overlay-list a {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  gap: 0.22em;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: clamp(2.6rem, 7.4vw, 5.2rem);
  line-height: 1.08;
  /* Revision (2026-09-06) — a slight negative tracking read fine on most
     of these words at this size, but let a couple of narrow-letter runs
     (the r-t-f in "Portfolio") crowd into each other. Normal tracking
     keeps every word in this list spaced the same, "Portfolio" included. */
  letter-spacing: normal;
  color: var(--text);
}

/* Revision (2026-09-06) — this list already has its own focus treatment
   (the underline sweep just below) standing in for a focus ring, so the
   site-wide gold outline (a:focus-visible above) was
   doubling up as a distracting box around the whole word. Suppressed
   here only — the default outline still shows everywhere else on the
   site. */
.nav-overlay-list a:focus-visible {
  outline: none;
}

/* Underline sweeps in from the left as the navigation's sole hover cue. */
.nav-overlay-list a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: 0.08em;
  height: 1px;
  background: currentColor;
  transition: right 0.45s cubic-bezier(0.65, 0, 0.35, 1);
}

.nav-overlay-list a:hover::after,
.nav-overlay-list a:focus-visible::after {
  right: 0;
}

/* These links stay within the site, so they deliberately do not use the
   convention of an up-right arrow that signals an external destination. */
.nav-overlay-list .nav-arrow {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .nav-overlay-list a::after {
    transition: none;
  }
}

.nav-overlay-foot {
  margin-top: clamp(40px, 8vw, 96px);
  padding-bottom: clamp(24px, 5vw, 56px);
  display: flex;
  gap: clamp(16px, 3vw, 32px);
  flex-wrap: wrap;
}

.nav-overlay-foot a {
  font-size: 0.9rem;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
}

/* Language selection intentionally shares the navigation overlay's scale,
   pacing, and transition so switching locale feels like part of the same
   editorial system rather than a secondary utility. */
.language-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--nav-h) var(--gutter) 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition: opacity 0.35s ease, transform 0.35s ease, visibility 0s linear 0.35s;
}

.language-overlay.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition: opacity 0.35s ease, transform 0.35s ease;
}

.language-overlay-list button {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  width: auto;
  padding: 0;
  font-family: var(--font-sans);
  font-size: clamp(2.6rem, 7.4vw, 5.2rem);
  font-weight: 500;
  line-height: 1.08;
  letter-spacing: normal;
  color: var(--text);
  text-align: left;
}

.language-overlay-list button:focus-visible {
  outline: none;
}

.language-overlay-list button::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: 0.08em;
  height: 1px;
  background: currentColor;
  transition: right 0.45s cubic-bezier(0.65, 0, 0.35, 1);
}

.language-overlay-list button:hover::after,
.language-overlay-list button:focus-visible::after,
.language-overlay-list button.is-active::after {
  right: 0;
}

/* ==========================================================================
   Page header (eyebrow + rule)
   ========================================================================== */

.page-header {
  display: flex;
  align-items: baseline;
  gap: clamp(24px, 4.5vw, 56px);
  padding: clamp(32px, 5.5vw, 56px) var(--gutter) 0;
}

.page-header .eyebrow {
  font-family: var(--font-accent);
  font-style: italic;
  font-size: clamp(1.2rem, 2.1vw, 1.6125rem); /* -25% from clamp(1.6rem, 2.8vw, 2.15rem) — daintier page-title treatment */
  white-space: nowrap;
}

.page-header h1.eyebrow {
  margin: 0;
  font-weight: 400;
  line-height: inherit;
}

.not-found-content {
  min-height: min(60vh, 560px);
  padding: clamp(80px, 12vw, 160px) var(--gutter) clamp(100px, 13vw, 180px);
}

.not-found-content h1 {
  margin: 0 0 clamp(36px, 5vw, 64px);
  font-family: var(--font-sans);
  font-size: clamp(2.5rem, 6vw, 5rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.1;
}

.not-found-links {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 2.5rem;
}

.not-found-links a {
  border-bottom: 1px solid var(--border-strong);
  padding-bottom: 0.3rem;
  font-family: var(--font-accent);
  font-style: italic;
  font-size: clamp(1.2rem, 2vw, 1.6rem);
}

.page-header .rule {
  flex: 1;
  height: 1px;
  background: var(--border);
  margin-bottom: 0.4em;
}

/* ==========================================================================
   Typography helpers
   ========================================================================== */

.display-heading {
  font-family: var(--font-sans);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.05;
}

.section-title {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(1.9rem, 3.4vw, 2.75rem);
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.6em;
  margin: 0;
}

.section-title .index {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 0.62em;
  color: var(--text-dim);
}

.section-title .bracket {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 0.4em;
  color: var(--text-dim);
}

.prose {
  font-family: var(--font-sans);
  font-size: clamp(1.05rem, 1.6vw, 1.35rem);
  line-height: 1.65;
  color: var(--text);
  max-width: 62ch;
}

.eyebrow-serif {
  font-family: var(--font-sans);
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 1.1em 2em;
  border: 1px solid var(--border-strong);
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 500;
  color: var(--text);
  transition: background 0.25s ease, color 0.25s ease, border-color 0.25s ease;
  white-space: nowrap;
}

.btn:hover,
.btn:focus-visible {
  background: var(--text);
  color: var(--bg);
  border-color: var(--text);
}

.btn-solid {
  background: var(--text);
  color: var(--bg);
  border-color: var(--text);
}

.btn-solid:hover,
.btn-solid:focus-visible {
  background: transparent;
  color: var(--text);
}

.btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn[disabled]:hover {
  background: none;
  color: var(--text);
}

/* On phone screens, the primary calls to action use a quieter, more
   editorial proportion. The same treatment is shared by the landing-page,
   services, and contact calls to action. */
@media (max-width: 600px) {
  .hero > .hero-actions .btn,
  .cta-band .hero-actions .btn,
  .contact-availability > .btn {
    padding: 0.9em 1.6em;
    font-size: 0.85rem;
    letter-spacing: 0.01em;
  }
}

.text-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-bottom: 1px solid var(--border-strong);
  padding-bottom: 0.15em;
  transition: opacity 0.2s ease;
}

.text-link:hover {
  opacity: 0.72;
}

/* ==========================================================================
   Sections generic
   ========================================================================== */

main {
  min-height: 60vh;
}

.section {
  padding: clamp(56px, 9vw, 116px) var(--gutter);
}

.section + .section {
  padding-top: 0;
}

.divider {
  height: 1px;
  background: var(--border);
  border: none;
  margin: 0;
}

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

.site-footer {
  position: relative;
  /* Revision (2026-09-06) — widened again as part of a full-site spacing
     pass (was clamp(44px, 6.5vw, 72px) / clamp(20px, 3vw, 32px)). */
  padding: clamp(52px, 7.5vw, 88px) var(--gutter) clamp(24px, 3.5vw, 40px);
  display: grid;
  /* Revision (2026-09-06) — the "Professionals" column (just a single
     "Book a call" link, duplicating the consultation CTA already above
     the footer) was removed, leaving three link columns instead of four.
     Widened each column's share of the row (1fr → 1.15fr) so the three
     remaining columns spread out to fill the row evenly alongside the
     email signup block, rather than leaving a gap where the fourth
     column used to sit. */
  grid-template-columns: minmax(240px, 2.2fr) repeat(3, minmax(120px, 1.15fr));
  gap: clamp(28px, 4.5vw, 48px);
}

/* Full-bleed dividers (site-footer's top edge, section tops, the accordion
   list, project-nav) are drawn as an inset ::before/::after instead of a
   literal border so they stop at the same left/right edge as the page
   content (matching .page-header .rule and .footer-bottom's border-top),
   rather than running the full width of the viewport. */
.site-footer::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--gutter);
  right: var(--gutter);
  height: 1px;
  background: var(--border);
}

.footer-col h3,
.footer-newsletter h3 {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.95rem;
  margin: 0 0 1.3rem;
}

.footer-accordion-toggle {
  width: 100%;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  text-align: left;
  font: inherit;
  font-weight: inherit;
  cursor: default;
}

.footer-accordion-icon {
  display: none;
}

.footer-newsletter p {
  margin: 0 0 1.5rem;
  font-size: 0.95rem;
  color: var(--text-dim);
  max-width: 34ch;
}

.footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.footer-col li + li {
  margin-top: 0.8rem;
}

.footer-col a {
  font-size: 0.95rem;
  color: var(--text-dim);
  transition: color 0.2s ease;
}

.footer-col a:hover {
  color: var(--text);
}

.footer-col a.ext {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.footer-col a.ext svg {
  width: 11px;
  height: 11px;
}

.newsletter-form {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  border-bottom: 1px solid var(--border-strong);
  padding-bottom: 10px;
  max-width: 420px;
}

.newsletter-form input[type="email"] {
  flex: 1;
  background: transparent;
  border: none;
  padding: 6px 0;
  font-size: 0.95rem;
  color: var(--text);
}

.newsletter-form input[type="email"]::placeholder {
  color: var(--text-faint);
}

.newsletter-form button {
  font-size: 0.95rem;
  font-weight: 300;
  letter-spacing: 0.005em;
  white-space: nowrap;
  padding-bottom: 6px;
}

.newsletter-form button:hover {
  opacity: 0.72;
}

.footer-newsletter p.newsletter-fineprint {
  margin-top: 0.9rem;
  font-family: var(--font-accent);
  font-style: italic;
  font-size: 0.809rem; /* 0.735rem + 10% */
  color: var(--text-faint);
  max-width: 60ch;
  line-height: 1.5;
}

.newsletter-fineprint a {
  text-decoration: underline;
}

.form-status {
  margin-top: 0.75rem;
  font-size: 0.85rem;
  min-height: 1.2em;
}

.form-status[data-state="success"] {
  /* The default light theme makes this black; dark mode keeps the message
     readable by following the active text color. */
  color: var(--text);
}

.form-status[data-state="error"] {
  color: #C84743;
}

.footer-bottom {
  grid-column: 1 / -1;
  border-top: 1px solid var(--border);
  margin-top: clamp(20px, 4vw, 36px);
  padding-top: clamp(20px, 4vw, 32px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}

.footer-bottom .site-logo {
  width: 161.7px; /* 129.375px + 25% again — clearly bigger than the header
    logo's own max width (108px, from .site-logo's clamp) */
  color: var(--text);
}

.footer-bottom small {
  color: var(--text-dim);
  font-size: 0.65rem; /* 0.765rem - 15% */
}

@media (max-width: 980px) {
  .site-footer {
    grid-template-columns: 1fr 1fr;
  }
  .footer-newsletter {
    grid-column: 1 / -1;
  }
}

@media (max-width: 600px) {
  .site-footer {
    /* These two measured intervals keep the footer's lower composition
       balanced: legal copy → accordions, then accordions → brand lockup. */
    --footer-section-gap: 2.5rem;
    --footer-lockup-gap: 1.25rem;
    display: block;
    padding: 48px 16px 2.5rem;
  }

  .site-footer::before {
    left: 16px;
    right: 16px;
  }

  .footer-newsletter {
    margin-bottom: var(--footer-section-gap);
  }

  .footer-newsletter h3 {
    font-size: 1.05rem;
    margin-bottom: 1.8rem;
  }

  .footer-newsletter p {
    max-width: none;
    font-size: 1rem;
  }

  .newsletter-form {
    max-width: none;
  }

  .footer-newsletter p.newsletter-fineprint {
    max-width: none;
    margin-top: 1.6rem;
    font-size: 0.82rem;
    line-height: 1.45;
  }

  .footer-accordion {
    border-bottom: 1px solid var(--border);
  }

  .footer-accordion:first-of-type {
    border-top: 1px solid var(--border);
  }

  .footer-col h3 {
    margin: 0;
  }

  .footer-accordion-toggle {
    padding: 1.8rem 0;
    font-size: 0.9rem;
    font-weight: 500;
    line-height: 1.2;
    cursor: pointer;
  }

  .footer-accordion-toggle:disabled {
    cursor: default;
  }

  .footer-accordion-icon {
    position: relative;
    display: block;
    width: 14px;
    height: 14px;
    flex: none;
  }

  .footer-accordion-icon::before,
  .footer-accordion-icon::after {
    content: "";
    position: absolute;
    background: currentColor;
    transition: transform 0.25s ease, opacity 0.25s ease;
  }

  .footer-accordion-icon::before {
    top: 6px;
    left: 0;
    width: 14px;
    height: 1px;
  }

  .footer-accordion-icon::after {
    top: 0;
    left: 6px;
    width: 1px;
    height: 14px;
  }

  .footer-accordion.is-open .footer-accordion-icon::after {
    opacity: 0;
    transform: scaleY(0.3);
  }

  .footer-accordion-panel {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.28s ease;
  }

  .footer-accordion-panel > ul {
    min-height: 0;
    overflow: hidden;
  }

  .footer-accordion.is-open .footer-accordion-panel {
    grid-template-rows: 1fr;
  }

  .footer-accordion-panel ul {
    padding: 0;
  }

  .footer-accordion.is-open .footer-accordion-panel ul {
    padding-bottom: 1.25rem;
  }

  .footer-col li + li {
    margin-top: 0.65rem;
  }

  .footer-col a {
    font-size: 0.95rem;
  }

  .footer-bottom {
    display: block;
    border-top: 0;
    margin-top: var(--footer-section-gap);
    padding-top: 0;
    text-align: center;
  }

  .footer-bottom .site-logo {
    display: block;
    /* Fallback: main.js refines this to the exact rendered width of the
       copyright lockup below it, including any font-loading adjustment. */
    width: 12.5rem;
    margin: 0 auto var(--footer-lockup-gap);
  }

  .footer-bottom small {
    /* The sans-serif legal line has a larger visual x-height than the
       italic fine print above, so it needs a smaller numeric value to
       read at the same optical scale. */
    font-size: 0.68rem;
    line-height: 1.5;
  }

  .footer-legal {
    width: fit-content;
    margin: 0 auto;
  }
}

/* ==========================================================================
   Home
   ========================================================================== */

.hero {
  /* Revision (2026-09-06) — bumped alongside the kicker/h1 spacing below
     for a bit more overall breathing room around the whole block. */
  padding: clamp(64px, 13vw, 156px) var(--gutter) clamp(56px, 9vw, 108px);
}

.hero .kicker {
  font-family: var(--font-accent);
  font-style: italic;
  /* Revision (2026-09-06) — client asked for the hero text to sit closer
     to editorial/luxury proportions: a touch smaller (~10%) with more
     air around it, rather than reading as a bold marketing headline.
     Margin widened further the same day for even more room below it. */
  font-size: clamp(1.35rem, 2.3vw, 1.7rem);
  line-height: 1.4;
  color: var(--text-dim);
  max-width: 46ch;
  margin: 0 0 2rem;
}

.hero h1 {
  font-family: var(--font-sans);
  font-weight: 700;
  /* Revision (2026-09-06) — sized down ~10% from clamp(2.6rem, 7vw,
     5.6rem) and given a looser line-height (1.04 → 1.2, widened once
     more the same day) — a quieter, more restrained headline with real
     breathing room between lines reads closer to a fashion/furniture
     studio's own editorial voice than a bold, tightly-set startup
     headline does. */
  font-size: clamp(2.3rem, 6.3vw, 5rem);
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin: 0 0 3.2rem; /* widened alongside the size/line-height change
    above, so the extra negative space reads consistently between the
    kicker, the headline's own lines, and the button below it. */
  max-width: 34ch; /* the explicit <br> in the markup (build_pages.py) is
  what forces "At the intersection of fashion," onto its own line —
    this max-width is just a safety net so neither half ever wraps
    again on its own at narrower widths. */
}

/* The extra editorial break is a phone-only treatment; keep desktop's
   original two-line composition intact. */
.mobile-break {
  display: none;
}

/* The partnership-description break is an English phone-only treatment. */
.mobile-cta-break {
  display: none;
}

.hero .hero-subline {
  font-family: var(--font-accent);
  font-style: italic;
  font-size: clamp(1rem, 1.3vw, 1.15rem);
  color: var(--text-dim);
  max-width: 40ch;
  line-height: 1.5;
  margin: 0 0 2.2rem;
}

.hero .lede {
  font-family: var(--font-sans);
  font-size: clamp(1.1rem, 1.8vw, 1.4rem);
  color: var(--text-dim);
  max-width: 52ch;
  line-height: 1.6;
  margin: 0 0 2.4rem;
}

.hero-actions {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.home-row {
  position: relative;
  padding: clamp(56px, 9vw, 116px) var(--gutter);
}

.home-row::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--gutter);
  right: var(--gutter);
  height: 1px;
  background: var(--border);
}

.home-row-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 24px;
  margin-bottom: clamp(32px, 5.5vw, 56px);
  flex-wrap: wrap;
}

.home-row-head .section-title {
  margin: 0;
}

/* ==========================================================================
   "The Practice" — homepage brief overview of the six services, between
   the portfolio carousel and Philosophy. A two-column horizontal split
   (like .featured-project / .hz-layout elsewhere on the homepage) rather
   than a stacked header-row + list: a headline and "View Services" link
   on the left, the six-service list on the right. No hairlines between
   rows, by design — client compared a lined and unlined version and
   preferred the quieter, unlined one as more editorial. Each descriptor
   ("Defining the foundation" etc.) stays hidden until its row is
   hovered, and only on inputs that actually support hover — touch and
   keyboard-only visitors see every descriptor plainly, all the time, so
   the content is never gated behind an interaction they can't perform.
   ========================================================================== */

.practice-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(40px, 6vw, 96px);
  align-items: start;
}

.practice-copy-col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(28px, 4vw, 44px);
}

.practice-heading {
  font-size: clamp(1.8rem, 3.1vw, 2.6rem);
  line-height: 1.18;
  max-width: 34ch; /* wide enough that the explicit <br> in the markup
    (build_pages.py) is what breaks the line, not this safety net */
}

.practice-list {
  display: flex;
  flex-direction: column;
}

.practice-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.85em;
  padding: clamp(14px, 2.2vw, 22px) 0;
}

.practice-name {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(1.1rem, 1.8vw, 1.4rem);
  color: var(--text);
}

.practice-reveal {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 400;
  color: var(--text-dim);
  font-size: clamp(1rem, 1.5vw, 1.2rem);
}

/* The hide/reveal-on-hover treatment only kicks in for inputs that can
   actually hover (a mouse or trackpad) — everyone else (touch, keyboard
   nav, any device main.js can't assume has a pointer) just sees the
   descriptor sitting there already, same as before. */
@media (hover: hover) and (pointer: fine) {
  .practice-reveal {
    opacity: 0;
    transform: translateX(-8px);
    transition: opacity 0.35s ease, transform 0.35s ease;
  }

  .practice-row:hover .practice-reveal {
    opacity: 1;
    transform: translateX(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .practice-reveal {
    transition: none;
  }
}

@media (max-width: 900px) {
  .practice-layout {
    grid-template-columns: 1fr;
    gap: clamp(32px, 6vw, 48px);
  }

  .practice-heading {
    max-width: none;
  }
}

/* Phone composition — the desktop line breaks above are useful on a wide
   canvas, but on a narrow screen they split the headlines into short,
   accidental-looking fragments. Let the copy find its own editorial three
   line measure instead, with a slightly narrower side inset like the
   approved mobile references. The service rows use quieter, compact type
   so their number, name, and italic descriptor stay together as one line
   in English; translated languages are allowed to wrap naturally. */
@media (max-width: 600px) {
  /* One shared mobile content edge: section padding and every page-level
     divider now resolve from this token, so a rule can never stop short of
     or extend beyond the copy it frames. Components with intentionally
     edge-to-edge internal rules retain their own local overrides. */
  :root {
    --gutter: 16px;
  }

  /* The menu is intentionally a touch more generous than the former phone
     scale, giving each destination the same assured rhythm as desktop. */
  .nav-overlay-list li + li {
    margin-top: clamp(16px, 4.2vw, 24px);
  }

  .nav-overlay-list a,
  .language-overlay-list button {
    font-size: 2.86rem;
  }

  /* Header geometry uses the same 16px content edge as the hero below.
     The controls retain 38px touch targets, while their 20–21px line marks
     sit quieter than the hero JAS logo. */
  .site-header {
    height: 64px;
    padding: 0 16px;
  }

  .site-header .site-logo {
    width: 91px;
  }

  .site-header .header-btn {
    margin: 0;
    padding: 0;
  }

  .hamburger,
  .theme-btn,
  .lang-btn {
    width: 38px;
    height: 38px;
  }

  .hamburger .bar {
    left: 0;
    right: auto;
    width: 17px;
    top: 19px;
    height: 0.8px;
  }

  .theme-icon-sun {
    inset: 8px;
  }

  .theme-icon-moon {
    /* The crescent's outline has a deliberately generous internal curve;
       give it a larger drawing area so its visible mark matches the globe. */
    inset: 6px;
  }

  .site-header .lang-btn {
    padding: 7.5px;
  }

  .theme-icon svg,
  .lang-btn svg {
    stroke-width: 0.8;
  }

  .header-right {
    /* The controls retain their full targets but sit edge-to-edge, bringing
       the moon visually close to the globe without moving the centered logo. */
    gap: 0;
  }

  .desktop-break {
    display: none;
  }

  .mobile-cta-break {
    display: none;
  }

  /* This intentional English-only break creates the balanced three-line
     headline in the mobile art direction. Other languages keep their
     natural flow, avoiding an English word order imposed on a translation. */
  html:lang(en) .mobile-break {
    display: block;
  }

  .hero {
    padding-left: 16px;
    padding-right: 16px;
  }

  .hero .kicker {
    font-size: clamp(1.05rem, 4.5vw, 1.2rem);
    line-height: 1.35;
    margin-bottom: 1.5rem;
  }

  .hero h1 {
    font-size: clamp(1.8rem, 9vw, 2.2rem);
    line-height: 1.2;
    max-width: none;
    margin-bottom: 2.9rem;
  }

  .practice-layout {
    display: flex;
    flex-direction: column;
    gap: 0;
  }

  .practice-copy-col {
    /* Flatten the intro on phones so the existing link can follow the
       service list without duplicating it in the document. */
    display: contents;
  }

  .practice-heading {
    order: 1;
    font-size: clamp(1.7rem, 7.6vw, 2rem);
    line-height: 1.17;
    max-width: none;
  }

  .practice-list {
    order: 2;
    margin-top: 2.25rem;
  }

  .practice-copy-col .text-link {
    order: 3;
    align-self: flex-start;
    margin-top: 3.5rem;
  }

  .practice-row {
    gap: 0.5rem;
    padding: 1.15rem 0;
  }

  /* The landing and Services consultation sections use the same mobile
     type scale and measure. Only their alignment differs: centered here,
     left-aligned on Services. Contact already uses this same heading scale. */
  .cta-band.home-cta h2,
  .cta-band.cta-left h2 {
    font-size: 1.6rem;
    max-width: 22ch;
    line-height: 1.3;
  }

  .cta-band.home-cta h2 {
    margin: 0 auto 2rem;
  }

  .cta-band.home-cta .prose {
    margin: 0 auto 2.6rem;
  }

  html:lang(en) .home-cta-copy .mobile-cta-break {
    display: none;
  }

  .practice-name {
    font-size: clamp(1.05rem, 4.7vw, 1.15rem);
  }

  .practice-reveal {
    font-size: clamp(0.85rem, 3.6vw, 0.95rem);
  }

  html:lang(en) .practice-name,
  html:lang(en) .practice-reveal {
    white-space: nowrap;
  }

}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(24px, 4.5vw, 48px);
}

.stat {
  border-top: 1px solid var(--border);
  padding-top: 1.5rem;
}

.stat .num {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: clamp(2rem, 4vw, 3.2rem);
  display: block;
}

.stat .label {
  font-family: var(--font-sans);
  color: var(--text-dim);
  font-size: 0.95rem;
}

.industry-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6em 1.2em;
  font-family: var(--font-sans);
  font-size: clamp(1.1rem, 1.8vw, 1.4rem);
  color: var(--text-dim);
}

.services-teaser {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
}

.services-teaser a {
  background: var(--bg);
  padding: clamp(28px, 3.5vw, 44px);
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  min-height: 264px;
  transition: background 0.25s ease;
}

.services-teaser a:hover {
  background: var(--bg-raised);
}

.services-teaser .n {
  font-family: var(--font-sans);
  color: var(--text-dim);
}

.services-teaser .t {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 1.4rem;
}

.services-teaser .d {
  font-family: var(--font-sans);
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--text-dim);
  max-width: 30ch;
  margin: 0;
}

.services-teaser .arrow {
  margin-top: auto;
  align-self: flex-end;
  font-size: 1.4rem;
}

.cta-band {
  position: relative;
  padding: clamp(72px, 11vw, 148px) var(--gutter);
  text-align: center;
}

.cta-band::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--gutter);
  right: var(--gutter);
  height: 1px;
  background: var(--border);
}

.cta-band h2 {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(2rem, 5vw, 3.6rem);
  max-width: 36ch; /* widened from 24ch so this wraps to 2 lines, not 3 */
  margin: 0 auto 2rem;
  line-height: 1.15;
}

.cta-band .prose {
  margin: 0 auto 2.6rem;
  max-width: 100ch; /* wide enough to hold this line on one row on desktop */
  text-align: center;
}

.cta-band .hero-actions {
  justify-content: center;
}

/* Left-aligned variant — used on the Services page, directly under the
   numbered service list, so the CTA reads as part of the same left
   column as the page's eyebrow and body copy rather than a centered
   band like the homepage's. Same copy, weight, and button styling;
   only the alignment changes. */
.cta-band.cta-left {
  text-align: left;
}

.cta-band.cta-left h2 {
  margin: 0 0 2rem;
}

.cta-band.cta-left .prose {
  margin: 0 0 2.6rem;
  text-align: left;
}

.cta-band.cta-left .hero-actions {
  justify-content: flex-start;
}

@media (max-width: 900px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .services-teaser { grid-template-columns: 1fr; }
}

/* ==========================================================================
   About
   ========================================================================== */

/* About reuses the Services accordion component (.service-item et al,
   built below in "Services (accordion)") so each section — Philosophy,
   Ethos, Founder — expands/collapses the same way Services does;
   see initAccordion("[data-about-item]", ...) in main.js. Structure,
   spacing and the page-header border fix all come from .service-item /
   ".page-header + .service-item" — .about-block itself carries no rules
   of its own any more.

   Revision (2026-09-06) — .about-block used to add its own roomier
   padding on top of .service-item's, so About's closed rows stood
   noticeably taller than Services'. Client asked for the two pages to
   match, so that override is gone: About now sits on the exact same
   clamp(28px, 4vw, 40px) padding as Services, and the two pages' row
   heights track each other by construction, not by kept-in-sync values. */

/* ==========================================================================
   Services (accordion)
   ========================================================================== */

/* Group labels divide the six services without changing the existing
   accordion rows or their interaction. */
.service-section-heading {
  position: relative;
  padding: clamp(48px, 7vw, 84px) var(--gutter) clamp(18px, 2.4vw, 28px);
}

.service-section-heading::after {
  content: "";
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: 0;
  height: 1px;
  background: var(--border);
}

.service-section-heading h2 {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(1.25rem, 2vw, 1.7rem);
  letter-spacing: 0.08em;
  line-height: 1.2;
}

.service-section-heading p {
  margin: clamp(10px, 1.3vw, 16px) 0 0;
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 400;
  color: var(--text-dim);
  font-size: clamp(1rem, 1.55vw, 1.3rem);
  line-height: 1.45;
}

.service-section-heading + .service-item::before {
  content: none;
}

.service-item {
  position: relative;
  padding: clamp(32px, 4.5vw, 48px) var(--gutter) clamp(32px, 4.5vw, 48px) calc(var(--gutter) + var(--service-indent));
}

/* Dividers between items are drawn as inset ::before/::after lines (see the
   .site-footer comment above) rather than a literal border, so they stop at
   the same left/right edge as the item's own text instead of running the
   full width of the viewport. */
.service-item::before {
  content: "";
  position: absolute;
  top: 0;
  left: calc(var(--gutter) + var(--service-indent));
  right: var(--gutter);
  height: 1px;
  background: var(--border);
}

/* Same fix as .about-block above: the first .service-item sits right
   after .page-header's own rule, so its border-top read as a stray
   second line under the "Services" eyebrow. */
.page-header + .service-item::before {
  content: none;
}

.service-item:last-child::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: var(--gutter);
  right: var(--gutter);
  height: 1px;
  background: var(--border);
}

/* When an accordion is the last element on a page, the footer supplies the
   closing rule. Keeping the item's own closing rule here would stack both
   1px lines at the same edge (or a fraction apart on mobile), making it look
   heavier than every other divider. */
main > .service-item:last-child::after {
  content: none;
}

.service-toggle {
  width: 100%;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  text-align: left;
}

.service-toggle-title {
  display: flex;
  align-items: baseline;
  gap: 0.7em;
  flex-wrap: wrap;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(1.5rem, 3.2vw, 2.4rem);
}

.service-toggle-title .bracket {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 400;
  color: var(--text-dim);
  font-size: 0.5em;
  white-space: nowrap;
}

.service-icon {
  position: relative;
  width: 20px;
  height: 20px;
  flex: none;
  margin-top: 0.5em;
}

.service-icon::before,
.service-icon::after {
  content: "";
  position: absolute;
  background: var(--text);
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.service-icon::before {
  left: 0;
  top: 50%;
  width: 100%;
  height: 1px;
  transform: translateY(-50%);
}

.service-icon::after {
  top: 0;
  left: 50%;
  width: 1px;
  height: 100%;
  transform: translateX(-50%);
}

.service-item.is-open .service-icon::after {
  transform: translateX(-50%) rotate(90deg);
  opacity: 0;
}

.service-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.35s ease;
}

.service-body-inner {
  overflow: hidden;
}

.service-item.is-open .service-body {
  grid-template-rows: 1fr;
}

.service-body .prose {
  padding-top: clamp(20px, 3vw, 30px);
  font-size: 1.25rem;
  font-weight: 300;
}

@media (max-width: 600px) {
  .service-body .prose {
    font-size: clamp(1.05rem, 1.6vw, 1.35rem);
  }
}

.service-body .process-copy .prose {
  margin: 0;
  padding-top: 0;
}

.service-body .process-copy .prose:first-child {
  padding-top: clamp(20px, 3vw, 30px);
}

.service-body .process-copy .prose + .prose {
  margin-top: 1em;
}

.service-body .process-copy .prose strong {
  font-weight: 600;
}

@media (max-width: 600px) {
  /* Keep every service name intact on compact screens. Descriptors become a
     deliberate second editorial line, so the title never breaks mid-name. */
  .service-toggle {
    align-items: flex-start;
    gap: 12px;
  }

  .service-toggle-title {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0.22rem;
    flex: 1;
    min-width: 0;
    font-size: clamp(1.25rem, 5.5vw, 1.45rem);
  }

  .service-toggle-title > span:not(.bracket) {
    grid-column: 1;
    grid-row: 1;
  }

  html:lang(en) .service-toggle-title > span:not(.bracket) {
    white-space: nowrap;
  }

  .service-toggle-title .bracket {
    grid-column: 1;
    grid-row: 2;
    font-size: 0.75em;
  }

  .service-icon {
    width: 14px;
    height: 14px;
    margin-top: 0.4em;
  }
}

/* ==========================================================================
   Portfolio — editorial cards, featured spread, and shared art frames
   ========================================================================== */

.portfolio-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding: clamp(32px, 5.5vw, 52px) var(--gutter) 0;
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
}

.filter-btn {
  border: 1px solid var(--border);
  padding: 0.6em 1.3em;
  font-size: 0.9rem;
  font-family: var(--font-sans);
  color: var(--text-dim);
  transition: all 0.2s ease;
}

.filter-btn:hover {
  color: var(--text);
  border-color: var(--border-strong);
}

.filter-btn.is-active {
  background: var(--text);
  color: var(--bg);
  border-color: var(--text);
}

/* Shared frame for generated artwork and photography. Placeholder SVGs can
   occupy a composed frame; supplied photography and video always retain
   their natural proportions and are never cropped to fit a template. */
.art-frame {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--bg-raised);
}

.art-frame svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}

.art-frame:has(> img),
.art-frame:has(> video) {
  aspect-ratio: auto !important;
  overflow: visible;
  background: transparent;
}

.art-frame > img,
.art-frame > video {
  position: relative;
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
  transition: none;
}

/* ---- Featured spread (homepage "Selected work" + top of Portfolio) ---- */

.featured-project {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: clamp(28px, 4.5vw, 48px) var(--gutter) clamp(56px, 7.5vw, 88px);
  display: grid;
  grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}

.featured-project.is-filtered-out {
  display: none;
}

.fp-visual {
  aspect-ratio: 4 / 5;
  width: min(100%, 390px);
}

.fp-visual:hover svg {
  transform: scale(1.045);
}

.fp-eyebrow {
  display: block;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 1.1rem;
}

/* The Bistro Collection credit line (homepage-only, see bistro_featured_html()
   in build_pages.py) uses title case instead of the uppercase category-label
   style the rest of the site's eyebrows share (.ec-eyebrow, .ph-eyebrow, and
   .fp-eyebrow elsewhere, incl. Portfolio's own featured spread) — scoped here
   so this one instance changes without affecting that shared convention. */
.bistro-eyebrow {
  text-transform: none;
  letter-spacing: 0.02em;
}

.fp-title {
  margin: 0 0 1.4rem;
}

.fp-title a {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.15rem, 3.5vw, 3.35rem);
  line-height: 1.08;
  color: var(--text);
}

.fp-desc {
  font-family: var(--font-sans);
  color: var(--text-dim);
  font-size: clamp(0.98rem, 1.2vw, 1.08rem);
  line-height: 1.65;
  max-width: 44ch;
  margin: 0 0 2.1rem;
}

.fp-credits {
  font-family: var(--font-sans);
  font-size: 0.82rem;
  color: var(--text-faint);
  max-width: 44ch;
  line-height: 1.5;
  margin: -0.9rem 0 2.1rem;
}

.fp-cta {
  font-family: var(--font-accent);
  font-style: italic;
  font-size: 1.05rem;
  color: var(--text);
  border-bottom: 1px solid var(--border-strong);
  padding-bottom: 0.2em;
  transition: opacity 0.2s ease;
}

.fp-cta:hover {
  opacity: 0.7;
}

@media (max-width: 900px) {
  .featured-project {
    grid-template-columns: 1fr;
  }
  .fp-visual {
    aspect-ratio: 4 / 3;
    width: min(100%, 520px);
  }
}

/* ---- Selected work carousel (homepage) — "pull" filmstrip, v8, 2026-09-06 ----
   The client called a halt to the iterative tuning of the two-column
   "spread" (v7, which lived here as .fs-*) and sent a recording of a
   different mechanic entirely: a single row of same-size images, the
   current one centered at full strength, its neighbors peeking in at the
   row's edges, dimmed. Advancing — automatically, by dragging, or by
   clicking a peeking neighbor — slides the whole row sideways by exactly
   one tile so the next image centers itself. No per-slide layout math, no
   stacked panels, no aspect-ratio juggling between differently-shaped
   slots: every .pc-tile is the same fixed 4:5 box. The desktop strip uses
   a calculated three-tile composition, while phones use a deliberately
   larger centered image with only narrow, cropped glimpses of its neighbors.

   The project name lives ABOVE the strip (the client's explicit ask this
   time, versus v7's copy block beside it) and cross-fades to match
   whichever tile is currently centered, same pattern as v7's .fs-copy-slide.
   The actual centering math and the pointer-drag "pull" interaction live
   in initPullCarousel() in main.js; this stylesheet only owns the resting
   look of each piece and the crossfade/dim transitions between states.

   Revision (2026-09-06, same day) — first pass read as too cramped and
   too contained: the client wants real air between the tiles, exactly
   three ever visible, and the left/right neighbors flush against the
   browser's own edges (half in frame, half literally off the page) —
   not just peeking inside a padded column. Two changes get there:

   1. .pc-viewport breaks out of .home-row's own gutter to full viewport
      width (the standard `width: 100vw` + negative-margin bleed — safe
      here because body already carries `overflow-x: hidden`), so there
      is no leftover inset for a "peek" to stop short of.
   2. --pc-gap (the space between tiles) and .pc-tile's width are no
      longer set independently — tile width is solved FROM the gap via
      calc((100vw - 2 * gap) / 2). That's not an arbitrary ratio: it's
      the one width where "half tile + gap + full tile + gap + half
      tile" exactly fills the viewport, which is what makes the
      neighbors land exactly half-cut-off at the true edges (any wider
      and a 4th tile would creep into view; any narrower and the
      neighbors wouldn't reach the edge at all). Turning up --pc-gap is
      now the single knob for "more air between tiles" — the tile width
      recalculates itself to keep the halves flush.

   Revision (2026-09-06) — --pc-gap now lives on .pc itself (was on
   .pc-track alone), because .pc-caption below needs the same value to
   size itself to the same width as .pc-tile — a custom property only
   reaches elements that descend from wherever it's declared, and
   .pc-track / .pc-caption are siblings, not one inside the other. */
.pc {
  --pc-gap: clamp(84px, 22vw, 388px);
  --pc-tile-width: calc((100vw - (2 * var(--pc-gap))) / 2);
}

/* Revision (2026-09-06) — the caption used to sit in a page-wide heading
   ABOVE the strip. The client asked to see it attached to the centered
   image instead, smaller and more editorial, with nothing ever shown
   for the peeking left/right neighbors (this one crossfading slot is
   the only place a caption ever appears). .pc-caption breaks out to the
   full viewport the same way .pc-viewport does — see the note above —
   so that its inner column, sized to .pc-tile's exact width via the same
   --pc-gap formula, centers itself in the same coordinate space as the
   active tile and lines up flush under it at any viewport width. */
.pc-caption {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  margin-top: clamp(20px, 2.6vw, 32px);
}

/* Revision (2026-09-06) — the static "Selected Work" eyebrow is gone;
   the client asked for the brand/client name instead, crossfading above
   the project name the same way the project name already crossfaded on
   its own, plus a "View Project" link below both. All three lines live
   inside one .pc-title-slide per project so they fade together as a
   single unit — same is-active toggle in initPullCarousel() as before,
   just more content riding along with it. Kept deliberately quiet
   (small tracked label, a single italic serif line, an underlined
   italic link) rather than loud, per the client's "minimal, elegant,
   chic" note.

   Revision (2026-09-06, same day) — now the inner column that the
   caption's own width and centering live on (moved out of .pc-heading,
   which is gone), sized to match .pc-tile exactly so the text block
   reads as attached to the image above rather than spanning the page. */
.pc-title-slides {
  position: relative;
  /* Revision (2026-09-06) — briefly widened this column past the tile's
     own width with a clamp() floor, to give the pc-desc line more room
     on narrow phones. That broke the thing this column exists for: with
     width matched to .pc-tile and both centered the same way, the two
     share a left edge for free — widen only this one and its centered
     block drifts left of the tile above it. Reverted to matching the
     tile exactly; the two-line rule for pc-desc below is now handled by
     clamping its height instead of by giving it more width. */
  width: var(--pc-tile-width);
  margin: 0 auto;
  text-align: left;
  min-height: 10rem; /* reserves height for brand + project (up to two
    lines once the tile gets narrow) + the fixed-height two-line pc-desc
    + CTA, all stacked, so different slides' line lengths crossfading
    in/out never shift the layout below. Measured against the tallest
    real slide at each width, not guessed (2026-09-06). */
}

@media (max-width: 480px) {
  .pc {
    /* A phone needs a different composition from the desktop's
       half-neighbor geometry: make the active artwork the focal point
       and let just slim edge-to-edge fragments of the adjacent work show.
       At 375px this resolves to a ~199px image with ~51px of white space,
       matching the supplied editorial reference. */
    --pc-gap: clamp(44px, 13.5vw, 65px);
    --pc-tile-width: clamp(188px, 53vw, 255px);
  }

  .pc-title-slides {
    /* The wider mobile artwork gives its matched caption column room to
       breathe, so it no longer needs the oversized reserve used by the
       former very narrow tiles. */
    min-height: 11.25rem;
  }
}

.pc-title-slide {
  position: absolute;
  inset: 0 auto auto 0;
  max-width: 100%;
  margin: 0;
  opacity: 0;
  transition: opacity 0.7s ease;
  pointer-events: none;
}

.pc-title-slide.is-active {
  opacity: 1;
  pointer-events: auto;
}

.pc-brand {
  /* Revision (2026-09-06) — client asked to drop the all-caps treatment;
     letter-spacing pulled in to match, since the wide 0.13em tracking
     was sized for uppercase and reads too loose on mixed-case text. */
  margin: 0 0 0.4rem;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--text-dim);
}

.pc-project {
  margin: 0 0 0.6rem;
}

.pc-project a {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.1rem, 1.7vw, 1.5rem);
  line-height: 1.28;
  color: var(--text);
  transition: opacity 0.2s ease;
}

.pc-project a:hover {
  opacity: 0.72;
}

/* Revision (2026-09-06) — the client sent a reference (a title, then a
   short preview line, then a "read more" link) and asked for the same
   under each carousel project — see caption_desc on CAROUSEL_SLIDES /
   CAROUSEL_PROJECT_CAPTIONS in build_pages.py for the copy itself
   (placeholder preview copy for now, per the client — final copy to
   follow). Sits between the project title and the CTA, plain sans body
   copy (not the italic serif accent font the title/CTA use) so it reads
   as description text, not another display line.

   Revision (2026-09-06, same day) — "two lines, always" is now a hard
   rule enforced by CSS rather than by hand-tuning copy length per
   breakpoint: a fixed height of exactly two line-boxes plus the
   line-clamp/box-orient combo below crops anything longer with an
   ellipsis. That means the column can go back to matching the tile's
   width exactly (see .pc-title-slides above) without the caption ever
   growing past two lines on narrow phones — it just truncates instead. */
.pc-desc {
  margin: 0 0 0.7rem;
  font-family: var(--font-sans);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-dim);
  height: 2.6rem;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.pc-cta {
  /* Revision (2026-09-06) — sized up from 0.74rem and given the same
     underline weight (border-strong, not the fainter text-faint it had)
     and arrow convention as the standalone .text-link CTAs elsewhere on
     the page ("View Services →", "About the studio →") — still italic
     serif, per the client, not switched to those links' sans face. Sits
     between .text-link's 1rem (a bigger, standalone CTA) and the old
     0.74rem: noticeably larger, proportionate to the card it belongs to
     rather than competing with a page-level link. */
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-accent);
  font-style: italic;
  font-size: 0.9rem;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border-strong);
  padding-bottom: 0.15em;
  transition: opacity 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.pc-cta:hover {
  opacity: 1;
  color: var(--text);
  border-color: var(--text);
}

.pc-viewport {
  position: relative;
  overflow: hidden;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

.pc-track {
  /* --pc-gap itself now lives on .pc (see above) — this is the one
    "more air" / "photo size" knob, since .pc-tile's width is solved
    FROM it (see the revision note above .pc-viewport): turning it up
    does two things at once, more room between tiles and smaller tiles,
    while the flush-at-the-true-edge / exactly-3-visible geometry holds
    automatically no matter what it's set to. Raised twice (2026-09-06):
    first from clamp(28px, 6vw, 84px) to clamp(64px, 17vw, 300px) to
    bring the photos down to ~75% of their original size, then to
    clamp(84px, 22vw, 388px), another ~15% down from that (~64% of the
    original). */
  display: flex;
  align-items: center;
  gap: var(--pc-gap);
  will-change: transform;
  transition: transform 0.85s cubic-bezier(0.65, 0, 0.35, 1);
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
}

.pc-track.is-dragging {
  transition: none;
  cursor: grabbing;
}

.pc-tile {
  /* Revision (2026-09-06) — the peeking left/right neighbors used to sit
     at opacity: 0.32 with a grayscale(0.4) filter, dimmed and desaturated
     to push focus onto the centered tile. The client asked for every
     tile to read in full color, same strength as the center image — the
     half-cut-off position and size at the viewport edges (see
     .pc-viewport above) already read as "not the focus" on their own,
     so there's no dimming left to distinguish is-active from not. */
  position: relative;
  flex: 0 0 auto;
  display: block;
  width: var(--pc-tile-width); /* The desktop width is solved so that
    [half tile][gap][full tile][gap][half tile] exactly fills 100vw;
    phones override this with the larger editorial composition above. */
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--bg-raised);
}

.pc-tile.is-active {
  cursor: default;
}

.pc-media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  pointer-events: none;
  -webkit-user-drag: none;
  user-select: none;
}

@media (prefers-reduced-motion: reduce) {
  .pc-track,
  .pc-tile,
  .pc-title-slide {
    transition: none;
  }
}

/* ---- Haussmann feature (homepage "In Motion" — automatic slideshow) ----
   The only real photography on the site, shown as a self-advancing
   sequence rather than a static grid, to demonstrate dynamic movement.
   Auto-advance/crossfade/scrub logic lives in initHaussmannGallery() in
   main.js; the current image also carries the sitewide scroll-parallax
   (see "Editorial parallax" below). */

.haussmann-feature .hz-flag {
  font-family: var(--font-sans);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  color: var(--text-dim);
  white-space: nowrap;
}

.hz-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(32px, 5.5vw, 80px);
  align-items: center;
}

.hz-frame {
  aspect-ratio: 4 / 5;
  outline-offset: 4px;
}

.hz-slide {
  opacity: 0;
  z-index: 0;
  transition-property: transform, opacity;
  transition-duration: 0s, 1.1s;
  transition-timing-function: linear, ease;
}

.hz-slide.is-active {
  opacity: 1;
  z-index: 1;
}

.hz-arrow {
  position: absolute;
  z-index: 3;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(24, 11, 7, 0.35);
  backdrop-filter: blur(2px);
  border: 1px solid rgba(247, 248, 246, 0.4);
  border-radius: 50%;
  width: 40px;
  height: 40px;
  color: #f7f8f6;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}

.hz-frame:hover .hz-arrow,
.hz-frame:focus-within .hz-arrow {
  opacity: 1;
}

.hz-arrow:hover {
  border-color: #f7f8f6;
}

.hz-arrow svg {
  width: 16px;
  height: 16px;
}

.hz-arrow-prev { left: 16px; }
.hz-arrow-next { right: 16px; }

.hz-scrub {
  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: rgba(247, 248, 246, 0.18);
}

.hz-scrub span {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--scrub-accent);
}

@keyframes hz-fill {
  from { width: 0%; }
  to   { width: 100%; }
}

.hz-eyebrow {
  display: block;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 1.1rem;
}

.hz-title {
  margin: 0 0 1.4rem;
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.4rem, 4.6vw, 4.2rem);
  line-height: 1.08;
  color: var(--text);
}

.hz-desc {
  font-family: var(--font-sans);
  color: var(--text-dim);
  font-size: clamp(1.02rem, 1.4vw, 1.18rem);
  line-height: 1.65;
  max-width: 46ch;
  margin: 0 0 1.9rem;
}

.hz-credits {
  display: flex;
  flex-wrap: wrap;
  gap: 1.8rem;
  margin: 0 0 1.6rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--border);
}

.hz-credits dt {
  font-family: var(--font-sans);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 0.2rem;
}

.hz-credits dd {
  font-family: var(--font-sans);
  font-size: 0.95rem;
  color: var(--text);
  margin: 0;
}

.hz-note {
  font-family: var(--font-sans);
  font-style: italic;
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--text-faint);
  max-width: 46ch;
  margin: 0;
}

@media (max-width: 900px) {
  .hz-layout {
    grid-template-columns: 1fr;
  }
  .hz-frame {
    aspect-ratio: 4 / 3;
  }
  .hz-arrow {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hz-slide {
    transition: none;
  }
  .hz-scrub {
    display: none;
  }
}

/* ---- Editorial grid (remaining projects on the Portfolio page) ---- */

.editorial-grid {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 var(--gutter) clamp(64px, 10vw, 112px);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: clamp(22px, 3vw, 40px);
  row-gap: clamp(48px, 6vw, 72px);
}

.editorial-card.is-hidden {
  display: none;
}

.ec-visual {
  aspect-ratio: 4 / 5;
  margin-bottom: clamp(20px, 2.8vw, 30px);
}

.ec-visual:hover svg {
  transform: scale(1.045);
}

.ec-body {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}

.ec-eyebrow {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.ec-title {
  margin: 0.15rem 0 0.3rem;
}

.ec-title a {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.5rem, 2.4vw, 2rem);
  color: var(--text);
}

.ec-desc {
  font-family: var(--font-sans);
  color: var(--text-dim);
  font-size: 0.96rem;
  line-height: 1.55;
  max-width: 42ch;
  margin: 0 0 0.4rem;
}

.ec-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  font-family: var(--font-sans);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--text-dim);
  padding-bottom: 0.15em;
  border-bottom: 1px solid var(--border);
  transition: color 0.2s ease, border-color 0.2s ease, gap 0.2s ease;
}

.ec-cta svg {
  width: 11px;
  height: 11px;
}

.ec-cta:hover {
  color: var(--text);
  border-color: var(--border-strong);
  gap: 11px;
}

@media (max-width: 960px) {
  .editorial-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 720px) {
  .editorial-grid { grid-template-columns: 1fr; }
}

/* Portfolio — a quiet editorial index. The feature / four-project rhythm
   follows the supplied portfolio template while keeping the individual
   projects compact enough to read as a considered whole. */
body[data-page="portfolio"] .page-header {
  max-width: none;
  margin: 0;
  padding-top: clamp(36px, 5vw, 70px);
}

body[data-page="portfolio"] .portfolio-filters {
  max-width: 1440px;
  justify-content: center;
  gap: clamp(20px, 3.2vw, 48px);
  padding-top: clamp(38px, 6vw, 78px);
  padding-bottom: clamp(24px, 4vw, 52px);
}

body[data-page="portfolio"] .filter-btn {
  position: relative;
  padding: 0 0 0.35rem;
  border: 0;
  color: var(--text-faint);
  font-size: 0.78rem;
  letter-spacing: 0.03em;
  background: transparent;
}

body[data-page="portfolio"] .filter-btn::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.2s ease;
}

body[data-page="portfolio"] .filter-btn:hover,
body[data-page="portfolio"] .filter-btn.is-active {
  color: var(--text);
  background: transparent;
}

body[data-page="portfolio"] .filter-btn.is-active::after {
  transform: scaleX(1);
}

body[data-page="portfolio"] .featured-project {
  width: min(100% - (2 * var(--gutter)), 1600px);
  max-width: none;
  margin: 0 auto;
  padding: clamp(12px, 2vw, 28px) 0 clamp(96px, 13vw, 188px);
  grid-template-columns: minmax(0, 1.76fr) minmax(280px, 1fr);
  gap: clamp(48px, 5.5vw, 108px);
  align-items: center;
}

body[data-page="portfolio"] .fp-visual {
  width: 100%;
  max-width: none;
  margin: 0;
  justify-self: start;
}

body[data-page="portfolio"] .fp-copy {
  max-width: 34rem;
}

body[data-page="portfolio"] .fp-eyebrow {
  margin-bottom: 0.85rem;
  font-size: 0.68rem;
}

body[data-page="portfolio"] .fp-title {
  margin-bottom: 1rem;
}

body[data-page="portfolio"] .fp-title a {
  font-size: clamp(2rem, 3.1vw, 3rem);
}

body[data-page="portfolio"] .fp-desc {
  margin-bottom: 1.6rem;
  font-size: 0.98rem;
  line-height: 1.7;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

body[data-page="portfolio"] .fp-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-sans);
  font-size: 0.78rem;
  font-style: normal;
  letter-spacing: 0.04em;
}

body[data-page="portfolio"] .fp-cta svg {
  width: 11px;
  height: 11px;
  transform: rotate(45deg);
}

body[data-page="portfolio"] .editorial-grid {
  width: calc(100% - (2 * var(--gutter)));
  max-width: none;
  margin: 0 auto;
  padding: 0 0 clamp(100px, 14vw, 210px);
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: clamp(20px, 3.3vw, 52px);
  row-gap: clamp(92px, 14vw, 200px);
}

body[data-page="portfolio"] .portfolio-wide-project {
  width: calc(100% - (2 * var(--gutter)));
  max-width: 1600px;
  margin: 0 auto;
  padding: 0 0 clamp(100px, 14vw, 210px);
  display: grid;
  grid-template-columns: minmax(280px, 1fr) minmax(0, 1.76fr);
  gap: clamp(48px, 5.5vw, 108px);
  align-items: center;
}

body[data-page="portfolio"] .portfolio-wide-project.is-hidden {
  display: none;
}

body[data-page="portfolio"] .portfolio-wide-copy {
  max-width: 34rem;
}

body[data-page="portfolio"] .portfolio-wide-copy .ec-eyebrow {
  font-size: 0.68rem;
}

body[data-page="portfolio"] .portfolio-wide-copy .ec-title a {
  font-size: clamp(2rem, 3.1vw, 3rem);
}

body[data-page="portfolio"] .portfolio-wide-copy .ec-desc {
  max-width: 44ch;
  font-size: 0.98rem;
  line-height: 1.7;
}

body[data-page="portfolio"] .portfolio-wide-copy .ec-cta {
  font-size: 0.78rem;
}

body[data-page="portfolio"] .portfolio-wide-visual {
  aspect-ratio: 16 / 9;
  width: 100%;
  max-width: none;
  margin: 0;
  justify-self: end;
}

/* Keep the two editorial projects that need more room in the same wide,
   image-and-copy rhythm as the Bistro and Solid Wood feature spreads. */
body[data-page="portfolio"] .editorial-card--wide {
  grid-column: 1 / -1;
  width: 100%;
  margin: 0;
  display: grid;
  grid-template-columns: minmax(0, 1.76fr) minmax(280px, 1fr);
  gap: clamp(48px, 5.5vw, 108px);
  align-items: center;
}

body[data-page="portfolio"] .editorial-card--wide.is-hidden {
  display: none;
}

body[data-page="portfolio"] .editorial-card--wide .ec-visual {
  grid-column: 1;
  grid-row: 1;
  aspect-ratio: 16 / 9;
  width: 100%;
  max-width: none;
  margin: 0;
}

body[data-page="portfolio"] .editorial-card--wide .ec-body {
  grid-column: 2;
  grid-row: 1;
  max-width: 34rem;
  gap: 0.5rem;
}

body[data-page="portfolio"] .editorial-card--wide .ec-eyebrow {
  font-size: 0.68rem;
}

body[data-page="portfolio"] .editorial-card--wide .ec-title a {
  font-size: clamp(2rem, 3.1vw, 3rem);
}

body[data-page="portfolio"] .editorial-card--wide .ec-desc {
  max-width: 44ch;
  font-size: 0.98rem;
  line-height: 1.7;
}

body[data-page="portfolio"] .editorial-card--wide .ec-cta {
  font-size: 0.78rem;
}

body[data-page="portfolio"] .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-visual {
  grid-column: 2;
}

body[data-page="portfolio"] .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-body {
  grid-column: 1;
}

body[data-page="portfolio"] .editorial-card--wide[data-project-slug="the-bauhaus"] {
  grid-template-columns: minmax(280px, 1fr) minmax(0, 1.76fr);
}

body[data-page="portfolio"] .ec-visual {
  margin-bottom: 1rem;
}

body[data-page="portfolio"] .ec-body {
  gap: 0.5rem;
}

body[data-page="portfolio"] .ec-eyebrow {
  font-size: 0.62rem;
  letter-spacing: 0.11em;
}

body[data-page="portfolio"] .ec-title {
  margin: 0.15rem 0 0.25rem;
}

body[data-page="portfolio"] .ec-title a {
  font-size: clamp(1.25rem, 1.6vw, 1.55rem);
}

body[data-page="portfolio"] .ec-desc {
  margin-bottom: 0.35rem;
  font-size: 0.84rem;
  line-height: 1.58;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

body[data-page="portfolio"] .ec-cta {
  font-size: 0.72rem;
  font-weight: 500;
}

body[data-page="portfolio"] .ec-cta svg {
  transform: rotate(45deg);
}

@media (max-width: 960px) {
  body[data-page="portfolio"] .featured-project,
  body[data-page="portfolio"] .portfolio-wide-project {
    grid-template-columns: 1fr 1fr;
    gap: clamp(32px, 7vw, 72px);
  }

  body[data-page="portfolio"] .editorial-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 720px) {
  body[data-page="portfolio"] .portfolio-filters {
    justify-content: flex-start;
    gap: 18px 24px;
  }

  body[data-page="portfolio"] .featured-project,
  body[data-page="portfolio"] .portfolio-wide-project {
    width: 100%;
    margin-left: 0;
    margin-right: 0;
    grid-template-columns: 1fr;
    gap: 28px;
  }

  /* Keep the featured horizontal project on the same mobile content edges
     as the horizontal project below it, with a little more breathing room
     around the featured Bistro Collection. */
  body[data-page="portfolio"] .featured-project {
    --portfolio-mobile-inset: clamp(24px, 6vw, 32px);
    width: calc(100% - (2 * var(--portfolio-mobile-inset)));
    margin-left: auto;
    margin-right: auto;
  }

  body[data-page="portfolio"] .portfolio-wide-project {
    --portfolio-mobile-inset: clamp(24px, 6vw, 32px);
    width: calc(100% - (2 * var(--portfolio-mobile-inset)));
    margin-left: auto;
    margin-right: auto;
  }

  body[data-page="portfolio"] .fp-visual {
    width: min(100%, 440px);
  }

  body[data-page="portfolio"] .editorial-grid {
    grid-template-columns: 1fr;
    row-gap: 72px;
  }

  body[data-page="portfolio"] .portfolio-wide-visual {
    aspect-ratio: 16 / 9;
    order: 0;
  }

  body[data-page="portfolio"] .editorial-card--wide {
    grid-template-columns: 1fr;
    gap: 28px;
  }

  /* Keep the feature-card type scale consistent with the regular mobile
     project cards, while leaving the larger desktop presentation intact. */
  body[data-page="portfolio"] .featured-project .fp-eyebrow,
  body[data-page="portfolio"] .portfolio-wide-copy .ec-eyebrow,
  body[data-page="portfolio"] .editorial-card--wide .ec-eyebrow {
    font-size: 0.62rem;
  }

  body[data-page="portfolio"] .featured-project .fp-title a,
  body[data-page="portfolio"] .portfolio-wide-copy .ec-title a,
  body[data-page="portfolio"] .editorial-card--wide .ec-title a {
    font-size: clamp(1.25rem, 1.6vw, 1.55rem);
  }

  body[data-page="portfolio"] .featured-project .fp-desc,
  body[data-page="portfolio"] .portfolio-wide-copy .ec-desc,
  body[data-page="portfolio"] .editorial-card--wide .ec-desc {
    max-width: 42ch;
    font-size: 0.84rem;
    line-height: 1.58;
  }

  body[data-page="portfolio"] .featured-project .fp-cta,
  body[data-page="portfolio"] .portfolio-wide-copy .ec-cta,
  body[data-page="portfolio"] .editorial-card--wide .ec-cta {
    font-size: 0.72rem;
  }

  body[data-page="portfolio"] .editorial-card--wide .ec-visual,
  body[data-page="portfolio"] .editorial-card--wide .ec-body {
    grid-column: 1;
  }

  body[data-page="portfolio"] .editorial-card--wide[data-project-slug="cite-radieuse"] .ec-visual {
    grid-row: 1;
  }

  body[data-page="portfolio"] .editorial-card--wide[data-project-slug="cite-radieuse"] .ec-body {
    grid-row: 2;
  }

  body[data-page="portfolio"] .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-body {
    grid-row: 1;
  }

  body[data-page="portfolio"] .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-visual {
    grid-column: 1;
    grid-row: 2;
  }

  body[data-page="portfolio"] .editorial-card--wide[data-project-slug="the-bauhaus"] {
    grid-template-columns: 1fr;
  }

  /* Stack the horizontal portfolio cards like the rest of the mobile cards:
     image first, then the project copy. */
  body[data-page="portfolio"] .portfolio-wide-project[data-project-slug="solid-wood"] .portfolio-wide-visual,
  body[data-page="portfolio"] .portfolio-wide-project[data-project-slug="eichler-post-and-beam"] .portfolio-wide-visual {
    order: 0;
  }

  body[data-page="portfolio"] .portfolio-wide-project[data-project-slug="solid-wood"] .portfolio-wide-copy,
  body[data-page="portfolio"] .portfolio-wide-project[data-project-slug="eichler-post-and-beam"] .portfolio-wide-copy {
    order: 1;
  }

  body[data-page="portfolio"] .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-visual {
    grid-column: 1;
    grid-row: 1;
  }

  body[data-page="portfolio"] .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-body {
    grid-row: 2;
  }
}

/* Keep newly added portfolio work in the compact editorial-card rhythm. */
body[data-page="portfolio"] .editorial-card[data-project-slug="bottle-table-lamp"] {
  width: auto;
  margin-left: 0;
  margin-right: 0;
  grid-column: auto;
  display: block;
  grid-template-columns: none;
  gap: 0;
  align-items: initial;
}

body[data-page="portfolio"] .editorial-card[data-project-slug="bottle-table-lamp"] .ec-visual {
  aspect-ratio: 4 / 5;
  width: 100%;
  max-width: none;
  margin: 0 0 1rem;
  grid-column: auto;
  grid-row: auto;
  justify-self: auto;
}

body[data-page="portfolio"] .editorial-card[data-project-slug="bottle-table-lamp"] .ec-body {
  max-width: none;
  grid-column: auto;
  grid-row: auto;
}

body[data-page="portfolio"] .editorial-card[data-project-slug="bottle-table-lamp"] .ec-eyebrow {
  font-size: 0.62rem;
}

body[data-page="portfolio"] .editorial-card[data-project-slug="bottle-table-lamp"] .ec-title a {
  font-size: clamp(1.25rem, 1.6vw, 1.55rem);
}

body[data-page="portfolio"] .editorial-card[data-project-slug="bottle-table-lamp"] .ec-desc {
  max-width: 42ch;
  font-size: 0.84rem;
  line-height: 1.58;
}

body[data-page="portfolio"] .editorial-card[data-project-slug="bottle-table-lamp"] .ec-cta {
  font-size: 0.72rem;
}

/* Portfolio sequence: keep the opening four-card row and the continuation
   row in the same order as the approved editorial reference. */
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="opening"] > :nth-child(1) { order: 1; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="opening"] > :nth-child(2) { order: 3; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="opening"] > :nth-child(3) { order: 2; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="opening"] > :nth-child(4) { order: 4; }

body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="stories-of-biarritz"] { order: 1; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="sunroom"] { order: 2; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="portobello-road"] { order: 3; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="smith-house"] { order: 4; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="bottle-table-lamp"] { order: 5; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="flaneur"] { order: 6; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="the-bauhaus"] { order: 7; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="split-rail-series"] { order: 8; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="palm-springs"] { order: 9; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="cite-radieuse"] { order: 10; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="neutra-vdl"] { order: 11; }
body[data-page="portfolio"] .editorial-grid[data-portfolio-segment="continuation"] [data-project-slug="la-palma"] { order: 12; }

/* ---- Portfolio rhythm from the supplied mockup --------------------------- */
body[data-page="portfolio"] .portfolio-flow {
  width: 100%;
}

body[data-page="portfolio"] .portfolio-flow .portfolio-section {
  width: 100%;
}

body[data-page="portfolio"] .portfolio-flow .featured-project,
body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project {
  padding-bottom: clamp(48px, 7vw, 96px);
}

body[data-page="portfolio"] .portfolio-flow .editorial-grid {
  padding-bottom: clamp(100px, 14vw, 210px);
}

body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project {
  grid-template-columns: minmax(0, 1.76fr) minmax(280px, 1fr);
}

body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project .portfolio-wide-visual {
  grid-column: 1;
  grid-row: 1;
  justify-self: start;
}

body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project .portfolio-wide-copy {
  grid-column: 2;
  grid-row: 1;
}

body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="the-bauhaus"] {
  grid-template-columns: minmax(0, 1.76fr) minmax(280px, 1fr);
}

body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-visual {
  grid-column: 1;
}

body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-body {
  grid-column: 2;
}

body[data-page="portfolio"] .portfolio-flow .portfolio-section--remaining {
  padding-bottom: clamp(60px, 10vw, 140px);
}

@media (max-width: 720px) {
  body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project .portfolio-wide-visual {
    grid-column: 1;
    grid-row: 1;
    order: 0;
  }

  body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project .portfolio-wide-copy {
    grid-column: 1;
    grid-row: 2;
    order: 1;
  }

  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-visual {
    grid-column: 1;
    grid-row: 1;
  }

  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-body {
    grid-column: 1;
    grid-row: 2;
  }
}

@media (min-width: 721px) {
  body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project[data-project-slug="solid-wood"],
  body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project[data-project-slug="case-study-house-16"] {
    grid-template-columns: minmax(280px, 1fr) minmax(0, 1.76fr);
  }

  body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project[data-project-slug="solid-wood"] .portfolio-wide-copy,
  body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project[data-project-slug="case-study-house-16"] .portfolio-wide-copy {
    grid-column: 1;
    grid-row: 1;
  }

  body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project[data-project-slug="solid-wood"] .portfolio-wide-visual,
  body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project[data-project-slug="case-study-house-16"] .portfolio-wide-visual {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
  }

  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="republique"] {
    grid-template-columns: minmax(280px, 1fr) minmax(0, 1.76fr);
  }

  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="republique"] .ec-body {
    grid-column: 1;
    grid-row: 1;
  }

  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="republique"] .ec-visual {
    grid-column: 2;
    grid-row: 1;
  }
}

@media (max-width: 720px) {
  /* Restore a single full-width mobile column after the desktop wide-card
     rules so horizontal projects match the regular mobile card rhythm. */
  body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project,
  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide {
    grid-template-columns: 1fr;
  }

  body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project .portfolio-wide-visual {
    width: 100%;
    max-width: none;
    grid-column: 1;
    grid-row: 1;
  }

  body[data-page="portfolio"] .portfolio-flow .portfolio-wide-project .portfolio-wide-copy {
    width: 100%;
    max-width: 34rem;
    grid-column: 1;
    grid-row: 2;
  }

  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide .ec-visual {
    width: 100%;
    max-width: none;
    grid-column: 1;
    grid-row: 1;
  }

  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide .ec-body {
    width: 100%;
    max-width: 34rem;
    grid-column: 1;
    grid-row: 2;
  }

  /* The Bauhaus sits in an inline editorial grid, so reset both the
     containing grid and the card itself to prevent a narrow desktop track
     from surviving at mobile widths. */
  body[data-page="portfolio"] .portfolio-flow [data-portfolio-section="bauhaus"] .editorial-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="the-bauhaus"] {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: minmax(0, 1fr);
    width: 100%;
    min-width: 0;
    max-width: none;
    gap: 28px;
    align-items: start;
  }

  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-visual,
  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-body {
    width: 100%;
    min-width: 0;
    max-width: none;
  }

  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-visual {
    grid-column: 1;
    grid-row: 1;
    justify-self: stretch;
  }

  body[data-page="portfolio"] .portfolio-flow .editorial-card--wide[data-project-slug="the-bauhaus"] .ec-body {
    grid-column: 1;
    grid-row: 2;
  }
}

/* ---- Cursor-follow "View Project" pill (desktop, pointer devices only) --- */

.view-pill {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 200;
  pointer-events: none;
  background: var(--text);
  color: var(--bg);
  font-family: var(--font-sans);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  padding: 0.7em 1.2em;
  border-radius: 999px;
  opacity: 0;
  transform: translate(-9999px, -9999px);
  transition: opacity 0.18s ease;
  white-space: nowrap;
}

.view-pill.is-visible {
  opacity: 1;
}

/* ---- Scroll reveal (portfolio cards, featured spread, project page) ---- */

[data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}

[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { transition: none; }
  .art-frame svg, .art-frame img { transition: none; }
}

/* ---- Editorial parallax ----
   A quiet scroll-linked drift on the site's largest editorial images
   (the Haussmann slideshow, each case-study hero) — not the smaller
   hover-driven cards, so it never fights a hover transform. The element
   is pre-scaled so the drift never reveals an edge; initParallax() in
   main.js writes the translateY each frame. See build_pages.py for
   where data-parallax is applied. */

[data-parallax] {
  transform: scale(1.12);
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  [data-parallax] { transform: none; }
}

/* ==========================================================================
   Project detail (case study) pages
   ========================================================================== */

.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  z-index: 70;
  background: transparent;
}

.progress-bar span {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--text);
  transition: width 0.1s linear;
}

.project-topbar {
  position: relative;
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: clamp(22px, 3vw, 32px) var(--gutter) 0;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 24px;
}

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--font-sans);
  font-size: 0.85rem;
  color: var(--text-dim);
  transition: color 0.2s ease;
}

.back-link:hover {
  color: var(--text);
}

.project-hero {
  padding: clamp(28px, 4.2vw, 44px) var(--gutter) clamp(22px, 3.5vw, 36px);
  max-width: 68ch;
}

.ph-eyebrow {
  display: block;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 1.1rem;
}

.ph-title {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.15rem, 3.5vw, 3.35rem);
  line-height: 1.12;
  margin: 0 0 1.15rem;
}

.ph-desc {
  font-family: var(--font-sans);
  color: var(--text-dim);
  max-width: 58ch;
  margin: 0;
}

.project-hero-art {
  width: min(960px, calc(100% - (2 * var(--gutter))));
  margin: 0 auto clamp(52px, 7vw, 84px);
  aspect-ratio: 3 / 2;
}

@media (max-width: 720px) {
  .project-hero-art {
    width: calc(100% - (2 * var(--gutter)));
    aspect-ratio: 4 / 3;
  }
}

/* Project view selector — the story remains the primary, editorial reading
   experience while the gallery offers a faster visual scan of the same work. */
.project-view-switch {
  display: flex;
  justify-content: flex-end;
  padding: 0 var(--gutter) clamp(32px, 5vw, 64px);
}

.project-topbar .project-view-switch {
  position: absolute;
  top: calc(50% + clamp(8px, 1vw, 16px));
  left: 50%;
  transform: translate(-50%, -50%);
  flex: 0 0 auto;
  padding: 0;
}

.project-view-label {
  font-family: var(--font-sans);
  font-style: normal;
  font-size: 0.85rem;
  font-weight: 400;
  line-height: 1.2;
  color: var(--text-dim);
  white-space: nowrap;
}

.project-view-switch {
  align-items: center;
  gap: clamp(12px, 1.5vw, 24px);
}

.project-view-controls {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  width: 116px;
  height: 50px;
  justify-content: center;
  padding: 5px;
  box-sizing: border-box;
  border: 1px solid color-mix(in srgb, var(--border) 46%, transparent);
  border-radius: 999px;
  background: var(--bg-input);
}

.project-view-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 50px;
  height: 38px;
  padding: 0;
  border-radius: 13px;
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  line-height: 1;
  transition: background 0.2s ease, color 0.2s ease;
}

.project-view-toggle:hover {
  color: var(--text);
}

.project-view-toggle.is-active {
  color: var(--text);
  background: var(--bg-raised);
}

.project-view-icon {
  position: relative;
  display: block;
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
}

.project-view-icon-story::before,
.project-view-icon-story::after {
  content: "";
  position: absolute;
  background: currentColor;
}

.project-view-icon-story::before {
  top: 1px;
  left: 0;
  width: 3px;
  height: 3px;
  box-shadow: 0 6px 0 currentColor, 0 12px 0 currentColor;
}

.project-view-icon-story::after {
  top: 2px;
  left: 7px;
  width: 10px;
  height: 1px;
  box-shadow: 0 6px 0 currentColor, 0 12px 0 currentColor;
}

.project-view-icon-gallery {
  width: 16px;
  height: 14px;
  flex-basis: 16px;
  background:
    linear-gradient(currentColor 0 0) 0 0 / 4px 4px no-repeat,
    linear-gradient(currentColor 0 0) 6px 0 / 4px 4px no-repeat,
    linear-gradient(currentColor 0 0) 12px 0 / 4px 4px no-repeat,
    linear-gradient(currentColor 0 0) 0 10px / 4px 4px no-repeat,
    linear-gradient(currentColor 0 0) 6px 10px / 4px 4px no-repeat,
    linear-gradient(currentColor 0 0) 12px 10px / 4px 4px no-repeat;
}

.project-story-content {
  display: contents;
}

.project-image-gallery {
  width: 100%;
  max-width: 1160px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-auto-rows: clamp(7rem, 10vw, 11rem);
  gap: clamp(12px, 1.6vw, 24px);
  padding: 0 var(--gutter) clamp(64px, 10vw, 124px);
}

.project-gallery-tile {
  position: relative;
  display: block;
  min-width: 0;
  overflow: hidden;
  padding: 0;
  background: var(--bg-raised);
  cursor: zoom-in;
}

.project-gallery-tile:nth-child(1) {
  grid-column: span 7;
  grid-row: span 2;
}

.project-gallery-tile:nth-child(2),
.project-gallery-tile:nth-child(3) {
  grid-column: span 5;
}

/* Inline project grid view. Story and Grid share the same page shell; only
   the content region changes. Every thumbnail retains its source ratio and
   opens the same image in the lightbox below. */
.project-grid-view {
  width: min(calc(100% - (2 * var(--gutter))), 1240px);
  margin: 0 auto;
  padding: clamp(48px, 7vw, 96px) 0 clamp(72px, 10vw, 132px);
}

.project-grid-view-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: start;
  gap: clamp(12px, 1.8vw, 28px);
}

.project-grid-tile {
  display: block;
  min-width: 0;
  margin: 0;
  padding: clamp(3px, 0.35vw, 6px);
  border: 0;
  border-radius: 0;
  background: var(--bg-raised);
  cursor: zoom-in;
  transition: transform 0.25s ease, opacity 0.25s ease;
}

.project-grid-tile:hover {
  transform: translateY(-3px);
}

.project-grid-tile img,
.project-grid-tile video {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
}

main.project-editorial-page.is-grid-view .project-editorial-layout,
main.project-editorial-page.is-grid-view .project-nav,
main.project-editorial-page.is-grid-view .progress-bar {
  display: none;
}

main.project-editorial-page.is-grid-view .project-grid-view {
  display: block;
}

@media (max-width: 760px) {
  .project-topbar {
    align-items: center;
    justify-content: center;
    padding-top: clamp(34px, 8vw, 48px);
    padding-bottom: clamp(18px, 4vw, 28px);
  }

  .project-topbar .back-link {
    display: none;
  }

  .project-topbar .project-view-switch {
    position: static;
    top: auto;
    right: auto;
    bottom: auto;
    left: auto;
    transform: none;
    margin: 0 auto;
  }

  .project-grid-view-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.project-gallery-visual,
.project-lightbox-visual {
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.project-gallery-visual svg,
.project-gallery-visual img,
.project-gallery-visual video,
.project-lightbox-visual svg,
.project-lightbox-visual img,
.project-lightbox-visual video {
  display: block;
  width: 100%;
  height: 100%;
}

.project-gallery-visual img,
.project-gallery-visual video {
  object-fit: contain;
  transition: none;
}

/* A small set of distinct compositions lets each story keep its own pace,
   rather than applying one repeated case-study template to every project. */
@media (min-width: 901px) {
  main[data-project-layout="bauhaus"].project-editorial-page .project-editorial-closing {
    grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr);
    gap: clamp(92px, 12vw, 214px);
  }

  main[data-project-layout="bauhaus"].project-editorial-page .project-editorial-closing > .art-frame:first-child {
    width: min(100%, 360px);
    justify-self: start;
  }

  main[data-project-layout="bauhaus"].project-editorial-page .project-editorial-closing > .art-frame:nth-child(2) {
    width: min(100%, 460px);
    justify-self: end;
    margin-top: 0;
  }

  main[data-project-layout="bauhaus"].project-editorial-page .project-editorial-details {
    align-items: center;
  }

  main[data-project-layout="bauhaus"].project-editorial-page .project-credits {
    align-self: center;
  }

  main[data-project-layout="cite-radieuse"].project-editorial-page .project-editorial-closing {
    grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr);
    gap: clamp(92px, 12vw, 214px);
    align-items: start;
  }

  main[data-project-layout="cite-radieuse"].project-editorial-page .project-editorial-closing > .art-frame:first-child {
    width: min(100%, 460px);
    justify-self: start;
  }

  main[data-project-layout="cite-radieuse"].project-editorial-page .project-editorial-closing > .art-frame:nth-child(2) {
    width: min(100%, 560px);
    justify-self: end;
    margin-top: 0;
  }

  main[data-project-layout="atelier"] .project-secondary-grid {
    grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
    align-items: center;
  }

  main[data-project-layout="atelier"] .project-image-gallery .project-gallery-tile:nth-child(1) {
    grid-column: span 5;
  }

  main[data-project-layout="atelier"] .project-image-gallery .project-gallery-tile:nth-child(2),
  main[data-project-layout="atelier"] .project-image-gallery .project-gallery-tile:nth-child(3) {
    grid-column: span 7;
  }

  main[data-project-layout="bistro"] .project-hero-art {
    width: min(100%, 500px);
    margin-left: calc(var(--gutter) + clamp(0px, 5vw, 72px));
    aspect-ratio: 4 / 5;
  }

  main[data-project-layout="bistro"] .project-secondary-grid {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
    align-items: end;
  }

  main[data-project-layout="bistro"] .project-image-gallery .project-gallery-tile:nth-child(1) {
    grid-column: span 8;
  }

  main[data-project-layout="bistro"] .project-image-gallery .project-gallery-tile:nth-child(2),
  main[data-project-layout="bistro"] .project-image-gallery .project-gallery-tile:nth-child(3) {
    grid-column: span 4;
  }

  main[data-project-layout="fielding"] .project-body,
  main[data-project-layout="marlow"] .project-body {
    grid-template-columns: minmax(200px, 0.7fr) minmax(0, 1.3fr);
  }

  main[data-project-layout="fielding"] .project-narrative,
  main[data-project-layout="marlow"] .project-narrative {
    grid-column: 2;
    grid-row: 1;
  }

  main[data-project-layout="fielding"] .project-credits,
  main[data-project-layout="marlow"] .project-credits {
    grid-column: 1;
    grid-row: 1;
  }

  main[data-project-layout="fielding"] .project-secondary-grid {
    grid-template-columns: minmax(0, 1.22fr) minmax(0, 0.78fr);
    align-items: start;
  }

  main[data-project-layout="hearth"] .project-secondary-grid {
    grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.28fr);
    align-items: end;
  }

  main[data-project-layout="hearth"] .project-image-gallery .project-gallery-tile:nth-child(1) {
    grid-column: span 9;
  }

  main[data-project-layout="hearth"] .project-image-gallery .project-gallery-tile:nth-child(2),
  main[data-project-layout="hearth"] .project-image-gallery .project-gallery-tile:nth-child(3) {
    grid-column: span 3;
  }

  main[data-project-layout="kestrel"] .project-secondary-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(44px, 8vw, 148px);
  }

  main[data-project-layout="kestrel"] .project-image-gallery .project-gallery-tile:nth-child(1) {
    grid-column: span 6;
  }

  main[data-project-layout="kestrel"] .project-image-gallery .project-gallery-tile:nth-child(2),
  main[data-project-layout="kestrel"] .project-image-gallery .project-gallery-tile:nth-child(3) {
    grid-column: span 6;
  }

  main[data-project-layout="marlow"] .project-secondary-grid {
    grid-template-columns: minmax(0, 1.28fr) minmax(0, 0.72fr);
    align-items: center;
  }

  main[data-project-layout="marlow"] .project-image-gallery .project-gallery-tile:nth-child(1) {
    grid-column: span 5;
  }

  main[data-project-layout="marlow"] .project-image-gallery .project-gallery-tile:nth-child(2),
  main[data-project-layout="marlow"] .project-image-gallery .project-gallery-tile:nth-child(3) {
    grid-column: span 7;
  }

  main[data-project-layout="montauk"].project-editorial-page .project-editorial-closing {
    grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
    gap: clamp(92px, 12vw, 214px);
    align-items: start;
  }

  main[data-project-layout="montauk"].project-editorial-page .project-editorial-closing > .art-frame:first-child {
    width: min(100%, 360px);
    justify-self: start;
  }

  main[data-project-layout="montauk"].project-editorial-page .project-editorial-closing > .art-frame:nth-child(2) {
    width: min(100%, 560px);
    justify-self: end;
    margin-top: 0;
  }

  main[data-project-name="Thames"].project-editorial-page .project-editorial-closing:nth-of-type(4) {
    grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
    gap: clamp(92px, 12vw, 214px);
    align-items: start;
  }

  main[data-project-name="Thames"].project-editorial-page .project-editorial-closing:nth-of-type(4) > .art-frame:first-child {
    width: min(100%, 360px);
    justify-self: start;
  }

  main[data-project-name="Thames"].project-editorial-page .project-editorial-closing:nth-of-type(4) > .art-frame:nth-child(2) {
    width: min(100%, 560px);
    justify-self: end;
    margin-top: 0;
  }

  main[data-project-name="Thames"].project-editorial-page .project-editorial-closing:nth-of-type(6) {
    grid-template-columns: minmax(0, 1.22fr) minmax(0, 0.78fr);
    gap: clamp(92px, 12vw, 214px);
    align-items: start;
  }

  main[data-project-name="Thames"].project-editorial-page .project-editorial-closing:nth-of-type(6) > .art-frame:first-child {
    width: min(100%, 560px);
    justify-self: start;
  }

  main[data-project-name="Thames"].project-editorial-page .project-editorial-closing:nth-of-type(6) > .art-frame:nth-child(2) {
    width: min(100%, 360px);
    justify-self: end;
    margin-top: clamp(24px, 3.5vw, 56px);
  }
}

.project-lightbox {
  position: fixed;
  z-index: 300;
  inset: 0;
  display: grid;
  place-items: center;
  padding: clamp(16px, 3.5vw, 52px);
  background: var(--bg);
}

.project-lightbox-dialog {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  width: min(100%, 1180px);
  height: min(100%, 820px);
  min-height: 0;
}

.project-lightbox-header,
.project-lightbox-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 46px;
}

.project-lightbox-count {
  margin: 0;
  color: var(--text-faint);
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.08em;
}

.project-lightbox-close,
.project-lightbox-control {
  display: grid;
  width: 38px;
  height: 38px;
  place-items: center;
  padding: 0;
  color: var(--text);
  font-size: 1.55rem;
  font-weight: 300;
  line-height: 1;
  transition: color 0.2s ease, opacity 0.2s ease;
}

.project-lightbox-close:hover,
.project-lightbox-control:hover:not(:disabled) {
  color: var(--text-dim);
}

.project-lightbox-control:disabled {
  cursor: default;
  opacity: 0.25;
}

.project-lightbox-controls {
  justify-content: flex-start;
  gap: 2px;
}

.project-lightbox-media {
  display: grid;
  min-height: 0;
  place-items: center;
  overflow: hidden;
  background: transparent;
}

.project-lightbox-visual {
  max-width: 100%;
  max-height: 100%;
}

.project-lightbox-visual img,
.project-lightbox-visual video {
  object-fit: contain;
}

body.project-lightbox-open {
  overflow: hidden;
}

@media (max-width: 640px) {
  .project-view-switch {
    justify-content: flex-start;
    padding-bottom: 28px;
  }

  .project-image-gallery {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: 40vw;
    gap: 10px;
    padding-bottom: 72px;
  }

  .project-gallery-tile:nth-child(1) {
    grid-column: span 2;
    grid-row: span 2;
  }

  .project-gallery-tile:nth-child(2),
  .project-gallery-tile:nth-child(3) {
    grid-column: span 1;
  }

  .project-lightbox {
    padding: 12px;
  }

  .project-lightbox-dialog {
    height: 100%;
  }
}

.project-body {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 var(--gutter) clamp(52px, 7vw, 80px);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(220px, 300px);
  gap: clamp(36px, 6.5vw, 92px);
  align-items: start;
}

.project-narrative .prose {
  margin: 0 0 1.6rem;
  max-width: 66ch;
}

.pull-quote {
  margin: clamp(32px, 4.5vw, 52px) 0 0;
  padding-left: clamp(20px, 2.5vw, 28px);
  border-left: 1px solid var(--border-strong);
  font-family: var(--font-accent);
  font-style: italic;
  font-size: clamp(1.3rem, 2.2vw, 1.7rem);
  line-height: 1.45;
  color: var(--text);
  max-width: 46ch;
}

/* Homepage "Philosophy" row reuses the case-study pull-quote styling —
   sits directly under .home-row-head, which already supplies the spacing
   above, and runs a touch wider to match the rest of the home-row grid. */
.home-pull-quote {
  margin-top: 0;
  max-width: 56ch;
}

/* On wide screens, Philosophy retains its concise heading / action row.
   The link is placed after the quote in the markup so a phone's reading and
   interaction order is naturally heading, statement, action. */
.home-row.philosophy {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 24px;
}

.home-row.philosophy .home-row-head {
  grid-column: 1;
  grid-row: 1;
  display: block;
}

.home-row.philosophy .home-pull-quote {
  grid-column: 1 / -1;
  grid-row: 2;
}

.home-row.philosophy .philosophy-cta {
  grid-column: 2;
  grid-row: 1;
  align-self: end;
  margin-bottom: clamp(32px, 5.5vw, 56px);
}

@media (max-width: 600px) {
  .home-row.philosophy {
    display: flex;
    flex-direction: column;
  }

  .home-row.philosophy .home-row-head {
    display: block;
    margin-bottom: 2rem;
  }

  .home-row.philosophy .home-pull-quote {
    margin: 0;
  }

  .home-row.philosophy .philosophy-cta {
    align-self: flex-start;
    margin: 2.15rem 0 0;
  }
}

.project-credits {
  border-top: 1px solid var(--border);
  padding-top: clamp(24px, 3.5vw, 32px);
  position: sticky;
  top: calc(var(--nav-h) + 24px);
}

.project-credits h2 {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.95rem;
  margin: 0 0 1.4rem;
}

.project-credits dl {
  /* Revision (2026-09-06) — used to have a bottom margin reserving space
     for the "Start a project" CTA that sat below it; that button (and
     the pull-quote beside it in .project-narrative) were removed at the
     client's request, so dl is now the last element in this aside. */
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.project-credits dl > div {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.project-credits dt {
  font-family: var(--font-sans);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.project-credits dd {
  font-family: var(--font-sans);
  font-size: 0.95rem;
  color: var(--text);
  margin: 0;
}

@media (max-width: 900px) {
  .project-body { grid-template-columns: 1fr; }
  .project-credits { position: static; }
}

.project-secondary-grid {
  width: 100%;
  max-width: 1160px;
  margin: 0 auto;
  padding: 0 var(--gutter) clamp(56px, 8vw, 88px);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(24px, 3.5vw, 40px);
}

.project-secondary-grid .art-frame {
  aspect-ratio: 4 / 5;
}

@media (max-width: 640px) {
  .project-secondary-grid { grid-template-columns: 1fr; }
}

/* Bistro Collection — a restrained, sequential case study that moves from
   the room to the object, then to the campaign language around it. */
main[data-project-layout="bistro"] .project-hero {
  max-width: 62ch;
}

main[data-project-layout="bistro"] .bistro-hero {
  width: min(100%, 500px);
  aspect-ratio: 4 / 5;
  background: #21150e;
}

.bistro-project-intro .project-narrative {
  max-width: 56ch;
}

.bistro-editorial-pair {
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 var(--gutter) clamp(76px, 10vw, 132px);
  display: grid;
  grid-template-columns: minmax(0, 1.18fr) minmax(0, 0.68fr);
  align-items: center;
  gap: clamp(40px, 8vw, 136px);
}

.bistro-pair-image {
  width: 100%;
  margin: 0;
}

.bistro-pair-image-large {
  justify-self: start;
}

.bistro-pair-image-small {
  width: min(100%, 72%);
  justify-self: end;
}

.bistro-editorial-pair-reverse {
  grid-template-columns: minmax(0, 0.68fr) minmax(0, 1.18fr);
}

.bistro-editorial-pair-reverse .bistro-pair-image-large {
  grid-column: 2;
  grid-row: 1;
  justify-self: end;
}

.bistro-editorial-pair-reverse .bistro-pair-image-small {
  grid-column: 1;
  grid-row: 1;
  justify-self: start;
}

.bistro-story-copy-block {
  width: 100%;
  max-width: 590px;
  margin: 0 auto;
  padding: 0 var(--gutter) clamp(76px, 10vw, 132px);
  font-family: var(--font-accent);
  font-size: clamp(1.1rem, 1.55vw, 1.32rem);
  line-height: 1.52;
}

.bistro-story-copy-block p {
  margin: 0 0 1.7rem;
}

.bistro-story-copy-block p:last-child {
  margin-bottom: 0;
}

.bistro-section-label {
  display: block;
  margin-bottom: 1.25rem;
  color: var(--text-faint);
  font-family: var(--font-sans);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.bistro-story-copy-block-end {
  padding-bottom: clamp(84px, 11vw, 148px);
}

@media (min-width: 901px) {
  main[data-project-layout="bistro"] .project-image-gallery .project-gallery-tile:nth-child(1) {
    grid-column: span 5;
  }

  main[data-project-layout="bistro"] .project-image-gallery .project-gallery-tile:nth-child(2),
  main[data-project-layout="bistro"] .project-image-gallery .project-gallery-tile:nth-child(3) {
    grid-column: span 7;
  }

  main[data-project-layout="bistro"] .project-image-gallery .project-gallery-tile:nth-child(4),
  main[data-project-layout="bistro"] .project-image-gallery .project-gallery-tile:nth-child(5) {
    grid-column: span 6;
  }
}

@media (max-width: 720px) {
  main[data-project-layout="bistro"] .bistro-hero {
    width: min(100%, 420px);
    margin-left: auto;
  }

  .bistro-editorial-pair,
  .bistro-editorial-pair-reverse {
    display: grid;
    grid-template-columns: 1fr;
    gap: 28px;
    padding-bottom: 64px;
  }

  .bistro-editorial-pair-reverse .bistro-pair-image-large,
  .bistro-editorial-pair-reverse .bistro-pair-image-small {
    grid-column: auto;
    grid-row: auto;
  }

  .bistro-editorial-pair-reverse .bistro-pair-image-large,
  .bistro-editorial-pair-reverse .bistro-pair-image-small {
    justify-self: start;
  }

  .bistro-pair-image-small {
    width: min(100%, 78%);
    justify-self: end;
  }

  .bistro-story-copy-block {
    font-size: 1.08rem;
    padding-bottom: 72px;
  }
}

.project-nav {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.project-nav::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--gutter);
  right: var(--gutter);
  height: 1px;
  background: var(--border);
}

.project-nav-link {
  padding: clamp(36px, 6vw, 60px) var(--gutter);
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  transition: background 0.25s ease;
}

.project-nav-link.prev {
  border-right: 1px solid var(--border);
  align-items: flex-start;
  text-align: left;
}

.project-nav-link.next {
  align-items: flex-end;
  text-align: right;
}

.project-nav-link:hover {
  background: transparent;
}

.pn-label {
  font-family: var(--font-sans);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.pn-title {
  font-family: var(--font-accent);
  font-style: italic;
  font-size: clamp(1.3rem, 2.6vw, 1.8rem);
  color: var(--text);
}

@media (max-width: 640px) {
  .project-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .project-nav-link.prev { border-right: none; border-bottom: none; }
  .project-nav-link { padding-inline: var(--gutter); }
  .pn-title { font-size: clamp(1.08rem, 4.7vw, 1.35rem); }
}

/* Project pages — restrained editorial sequence
   The composition mirrors the project-page template: a generous lead image,
   an unhurried introduction, material/details, a three-image study, closing
   copy, and an asymmetric final pair. Supplied images retain their source
   dimensions throughout; sizing is governed by available space, never a crop. */
main.project-editorial-page .project-editorial-layout {
  padding-bottom: clamp(72px, 10vw, 148px);
}

main.project-editorial-page .project-editorial-lead {
  width: min(100% - (2 * var(--gutter)), 1120px);
  margin: clamp(32px, 5vw, 72px) auto clamp(64px, 9vw, 132px);
}

main.project-editorial-page .project-editorial-lead .project-hero-art {
  width: 100%;
  margin: 0;
  display: flex;
  justify-content: center;
  background: transparent;
}

main.project-editorial-page .project-editorial-lead .project-hero-art:has(> img),
main.project-editorial-page .project-editorial-lead .project-hero-art:has(> video) {
  aspect-ratio: auto !important;
}

main.project-editorial-page .project-editorial-lead .project-hero-art > img,
main.project-editorial-page .project-editorial-lead .project-hero-art > video {
  width: auto;
  max-width: 100%;
  max-height: min(78svh, 860px);
}

main[data-project-layout="bauhaus"].project-editorial-page .project-editorial-lead .project-hero-art > video {
  width: 100%;
  height: auto;
  max-width: 100%;
  max-height: none;
  display: block;
}

main.project-editorial-page .project-editorial-lead .project-hero-art:not(:has(> img)):not(:has(> video)) {
  aspect-ratio: 16 / 9;
}

main.project-editorial-page .project-editorial-introduction {
  width: min(100% - (2 * var(--gutter)), 1120px);
  margin: 0 auto clamp(74px, 11vw, 160px);
  text-align: center;
}

main.project-editorial-page .project-hero {
  max-width: none;
  margin: 0;
  padding: 0;
}

main.project-editorial-page .ph-eyebrow {
  margin-bottom: 0.35rem;
  font-size: 0.7rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}

main.project-editorial-page .ph-title {
  max-width: none;
  margin: 0 auto 1.15rem;
  font-size: clamp(2.2rem, 3.4vw, 3.35rem);
  line-height: 1.08;
  white-space: nowrap;
}

@media (max-width: 760px) {
  main.project-editorial-page .ph-title {
    font-size: clamp(1.75rem, 6vw, 2.35rem);
  }
}

main.project-editorial-page .ph-desc {
  max-width: 68ch;
  margin: 0 auto;
}

main.project-editorial-page .project-editorial-details {
  width: min(100% - (2 * var(--gutter)), 1120px);
  margin: 0 auto clamp(78px, 11vw, 168px);
  display: grid;
  grid-template-columns: minmax(0, 0.76fr) minmax(240px, 0.64fr);
  gap: clamp(48px, 12vw, 180px);
  align-items: start;
}

main.project-editorial-page .project-editorial-details > .art-frame {
  width: min(100%, 460px);
  justify-self: start;
}

main.project-editorial-page .project-editorial-details > .art-frame:not(:has(> img)):not(:has(> video)) {
  aspect-ratio: 4 / 5;
}

/* Case Study House #16 adds a second horizontal hero between its details
   block and the first image study. Keep it full-width within the editorial
   measure while preserving the source image's native ratio. */
main[data-project-layout="case-study-house-16"].project-editorial-page .project-editorial-secondary-hero {
  width: min(100% - (2 * var(--gutter)), 1120px);
  margin: 0 auto clamp(82px, 12vw, 178px);
}

main[data-project-layout="case-study-house-16"].project-editorial-page .project-editorial-secondary-hero > .art-frame {
  width: 100%;
  margin: 0;
}

main[data-project-layout="case-study-house-16"].project-editorial-page .project-editorial-secondary-hero > .art-frame > img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
}

main.project-editorial-page .project-credits {
  position: static;
  align-self: start;
  border-top: 1px solid var(--border);
  padding-top: 1.4rem;
}

main.project-editorial-page .project-credits h2 {
  margin-bottom: 1.6rem;
  font-size: 0.95rem;
  letter-spacing: 0;
  text-transform: none;
}

main.project-editorial-page .project-credits dl {
  gap: 1.25rem;
}

main.project-editorial-page .project-credits dd {
  font-size: 0.94rem;
}

main.project-editorial-page .project-credits dt {
  font-size: 0.82rem;
  letter-spacing: 0;
  text-transform: none;
}

main.project-editorial-page .project-editorial-study {
  --carousel-slide: clamp(520px, 38.5vw, 665px);
  --carousel-gap: clamp(140px, 13.5vw, 240px);
  width: 100vw;
  max-width: none;
  margin: 0 0 clamp(82px, 12vw, 178px);
  margin-left: 50%;
  transform: translateX(-50%);
  padding: 0 max(0px, calc((100vw - var(--carousel-slide)) / 2));
  box-sizing: border-box;
  display: flex;
  gap: var(--carousel-gap);
  align-items: start;
  overflow-x: auto;
  overflow-y: visible;
  scrollbar-width: none;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: max(0px, calc((100vw - var(--carousel-slide)) / 2));
  overscroll-behavior-x: contain;
  outline: none;
}

main.project-editorial-page .project-editorial-study::-webkit-scrollbar {
  display: none;
}

main.project-editorial-page .project-editorial-study > .art-frame {
  flex: 0 0 var(--carousel-slide);
  width: var(--carousel-slide);
  max-width: none;
  margin: 0;
  scroll-snap-align: center;
  scroll-snap-stop: always;
  transition: none;
}

main.project-editorial-page .project-editorial-study > .art-frame.is-active {
  flex-basis: var(--carousel-slide);
  width: var(--carousel-slide);
}

main.project-editorial-page .project-editorial-study > .art-frame > img,
main.project-editorial-page .project-editorial-study > .art-frame > video {
  width: 100%;
  height: auto;
  object-fit: contain;
}

main.project-editorial-page .project-editorial-copy {
  width: min(100% - (2 * var(--gutter)), 1120px);
  margin: 0 auto clamp(64px, 12vw, 176px);
  padding: 0;
  text-align: center;
}

main.project-editorial-page .project-editorial-copy .project-narrative,
main.project-editorial-page .project-editorial-copy .bistro-story-copy-block {
  max-width: none;
}

main.project-editorial-page .project-editorial-copy .prose,
main.project-editorial-page .project-editorial-copy p {
  max-width: none;
  margin: 0 auto 1.35rem;
}

/* One reading scale for every project page, matching Bistro Collection.
   Width and spacing are deliberately controlled by the existing rules. */
main[data-project-layout] .ph-desc,
main.project-editorial-page .project-editorial-copy .prose,
main.project-editorial-page .project-editorial-copy p {
  font-size: clamp(0.95rem, 1.05vw, 1.12rem);
  line-height: 1.6;
}

main.project-editorial-page .project-editorial-copy p:last-child {
  margin-bottom: 0;
}

main.project-editorial-page .project-editorial-copy-detail {
  max-width: 660px;
  margin-bottom: clamp(82px, 12vw, 178px);
}

main.project-editorial-page .bistro-section-label {
  margin-bottom: 1.4rem;
  font-size: 0.68rem;
}

main.project-editorial-page .project-editorial-closing {
  width: min(100% - (2 * var(--gutter)), 1320px);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1.23fr) minmax(0, 1fr);
  gap: clamp(100px, 9vw, 200px);
  align-items: start;
}

/* Keep the same section break after an image pair when another story beat
   follows it. The final pair already ends at the layout's footer spacing. */
main.project-editorial-page .project-editorial-closing:not(:last-child) {
  margin-bottom: clamp(82px, 12vw, 178px);
}

/* The layout supplies the final breath before project navigation. Avoid
   stacking that space with the last study or paragraph's own margin. */
main.project-editorial-page .project-editorial-layout > section:last-child {
  margin-bottom: 0;
}

main.project-editorial-page .project-editorial-closing > .art-frame {
  width: 100%;
}

main.project-editorial-page .project-editorial-closing > .art-frame:not(:has(> img)):not(:has(> video)) {
  aspect-ratio: 4 / 5;
}

main.project-editorial-page .project-editorial-closing > .art-frame:nth-child(2) {
  margin-top: clamp(24px, 3.5vw, 56px);
}

main.project-editorial-page .project-nav {
  margin-top: 0;
}

@media (max-width: 760px) {
  main.project-editorial-page .project-editorial-lead {
    margin-top: 28px;
  }

  main.project-editorial-page .project-editorial-lead .project-hero-art > img,
  main.project-editorial-page .project-editorial-lead .project-hero-art > video {
    max-height: 68svh;
  }

  main.project-editorial-page .project-editorial-details,
  main.project-editorial-page .project-editorial-closing {
    grid-template-columns: 1fr;
    gap: 32px;
  }

  main.project-editorial-page .project-editorial-details > .art-frame {
    width: min(100%, 400px);
    margin: 0 auto;
    justify-self: center;
  }

  main.project-editorial-page .project-editorial-closing > .art-frame {
    max-width: 100%;
    margin: 0 auto;
    justify-self: center;
  }

  main.project-editorial-page .project-editorial-closing > .art-frame:nth-child(2) {
    width: min(100%, 82%);
    margin: 0 auto;
    justify-self: center;
  }

  main.project-editorial-page .project-editorial-copy {
    text-align: center;
  }

  main.project-editorial-page .project-editorial-copy .prose,
  main.project-editorial-page .project-editorial-copy p {
    margin-left: auto;
    margin-right: auto;
    text-align: center;
  }

  main[data-project-layout="bistro"].project-editorial-page .project-editorial-copy .prose {
    text-align: center;
  }

  main[data-project-layout="bistro"].project-editorial-page .project-editorial-closing > .art-frame,
  main[data-project-layout="bistro"].project-editorial-page .project-editorial-closing > .art-frame:nth-child(2) {
    width: min(100%, 88%);
    margin: 0 auto;
    justify-self: center;
  }

  main[data-project-layout="oblique"].project-editorial-page .project-editorial-closing > .art-frame,
  main[data-project-layout="oblique"].project-editorial-page .project-editorial-closing > .art-frame:nth-child(2) {
    margin: 0 auto;
    justify-self: center;
  }
}

@media (min-width: 901px) {
  main[data-project-name="République"].project-editorial-page .project-editorial-closing {
    grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr);
    gap: clamp(92px, 12vw, 214px);
    align-items: start;
  }

  main[data-project-name="République"].project-editorial-page .project-editorial-closing > .republique-pair-small {
    width: min(100%, 460px);
    justify-self: start;
    margin-top: clamp(24px, 3.5vw, 56px);
  }

  main[data-project-name="République"].project-editorial-page .project-editorial-closing > .republique-pair-large {
    width: min(100%, 560px);
    justify-self: end;
    margin-top: 0;
  }
}

@media (max-width: 760px) {
  main[data-project-name="République"].project-editorial-page .project-editorial-closing > .republique-pair-small,
  main[data-project-name="République"].project-editorial-page .project-editorial-closing > .republique-pair-large {
    width: min(100%, 88%);
    margin: 0 auto;
    justify-self: center;
  }
}

@media (max-width: 760px) {
  main.project-editorial-page .project-editorial-study {
    --carousel-slide: min(80vw, 460px);
    --carousel-gap: 24px;
    padding-left: max(0px, calc((100vw - var(--carousel-slide)) / 2));
    padding-right: max(0px, calc((100vw - var(--carousel-slide)) / 2));
    scroll-padding-inline: max(0px, calc((100vw - var(--carousel-slide)) / 2));
  }
}

/* Keep the approved editorial text measures independent of the shared type scale. */
main[data-project-layout="bistro"].project-editorial-page .ph-desc,
main[data-project-layout="solid-wood"].project-editorial-page .ph-desc,
main[data-project-layout="oblique"].project-editorial-page .ph-desc {
  max-width: none;
}

main[data-project-layout="bistro"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="solid-wood"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="oblique"].project-editorial-page .project-editorial-copy-detail {
  max-width: none;
}

/* Keep the same generous text measure used by Bistro, Solid Wood, and
   Oblique so the remaining project introductions do not gain extra side
   inset at the smaller type scale. */
main[data-project-layout="ojai"].project-editorial-page .ph-desc,
main[data-project-layout="bottle"].project-editorial-page .ph-desc,
main[data-project-layout="biarritz"].project-editorial-page .ph-desc,
main[data-project-layout="smith-house"].project-editorial-page .ph-desc,
main[data-project-layout="bauhaus"].project-editorial-page .ph-desc,
main[data-project-layout="ojai"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="bottle"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="biarritz"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="smith-house"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="bauhaus"].project-editorial-page .project-editorial-copy-detail {
  max-width: none;
}

/* Match the Bistro Collection's full editorial measure on the remaining
   project pages that use the wider desktop reading layout. */
main[data-project-layout="a-deux"].project-editorial-page .ph-desc,
main[data-project-layout="haussmann"].project-editorial-page .ph-desc,
main[data-project-layout="portobello"].project-editorial-page .ph-desc,
main[data-project-layout="flaneur"].project-editorial-page .ph-desc,
main[data-project-layout="brownstone"].project-editorial-page .ph-desc,
main[data-project-layout="case-study-house-16"].project-editorial-page .ph-desc,
main[data-project-layout="montauk"].project-editorial-page .ph-desc,
main[data-project-layout="cite-radieuse"].project-editorial-page .ph-desc,
main[data-project-layout="eichler"].project-editorial-page .ph-desc,
main[data-project-layout="24-7"].project-editorial-page .ph-desc,
main[data-project-layout="cabo-da-roca"].project-editorial-page .ph-desc,
main[data-project-layout="palm-springs"].project-editorial-page .ph-desc,
main[data-project-layout="a-deux"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="haussmann"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="portobello"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="flaneur"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="brownstone"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="case-study-house-16"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="montauk"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="cite-radieuse"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="eichler"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="24-7"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="cabo-da-roca"].project-editorial-page .project-editorial-copy-detail,
main[data-project-layout="palm-springs"].project-editorial-page .project-editorial-copy-detail {
  max-width: none;
}

@media (min-width: 761px) {
  main[data-project-layout="solid-wood"].project-editorial-page .ph-title {
    max-width: none;
    white-space: nowrap;
  }
}

main.project-editorial-page .project-editorial-study[data-project-study-carousel] {
  --carousel-slide: clamp(340px, 26vw, 450px);
  --carousel-gap: clamp(140px, 18vw, 300px);
  display: block;
  width: 100vw;
  max-width: none;
  margin-left: 50%;
  padding: 0;
  overflow: hidden;
  scroll-snap-type: none;
  scroll-padding-inline: 0;
  overscroll-behavior-x: auto;
}

main.project-editorial-page .project-editorial-study[data-project-study-carousel] .project-editorial-study-track {
  display: flex;
  align-items: flex-start;
  gap: var(--carousel-gap);
  width: max-content;
  will-change: transform;
  transition: transform 0.85s cubic-bezier(0.65, 0, 0.35, 1);
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
}

main.project-editorial-page .project-editorial-study[data-project-study-carousel] .project-editorial-study-track.is-dragging {
  transition: none;
  cursor: grabbing;
}

main.project-editorial-page .project-editorial-study[data-project-study-carousel] .project-editorial-study-track > .art-frame {
  flex: 0 0 var(--carousel-slide);
  width: var(--carousel-slide);
  max-width: none;
  margin: 0;
  scroll-snap-align: none;
  scroll-snap-stop: normal;
  transition: none;
}

main.project-editorial-page .project-editorial-study[data-project-study-carousel] .project-editorial-study-track > .art-frame > img,
main.project-editorial-page .project-editorial-study[data-project-study-carousel] .project-editorial-study-track > .art-frame > video {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
  pointer-events: none;
}

@media (max-width: 760px) {
  main.project-editorial-page .project-editorial-study[data-project-study-carousel] {
    --carousel-slide: min(68vw, 360px);
    --carousel-gap: clamp(28px, 8vw, 56px);
  }
}

/* Mobile project refinements — keep the Oblique detail copy centered, keep
   its inline film free of the browser start overlay, and center both of
   Smith House's closing images. */
@media (max-width: 760px) {
  main[data-project-layout="oblique"].project-editorial-page .project-editorial-copy,
  main[data-project-layout="oblique"].project-editorial-page .project-editorial-copy .prose,
  main[data-project-layout="oblique"].project-editorial-page .project-editorial-copy p {
    text-align: center;
  }

  main[data-project-layout="oblique"].project-editorial-page video::-webkit-media-controls-start-playback-button {
    display: none !important;
  }

  main[data-project-layout="bottle"].project-editorial-page .project-editorial-closing > .art-frame,
  main[data-project-layout="bottle"].project-editorial-page .project-editorial-closing > .art-frame:nth-child(2),
  main[data-project-layout="smith-house"].project-editorial-page .project-editorial-closing > .art-frame,
  main[data-project-layout="smith-house"].project-editorial-page .project-editorial-closing > .art-frame:nth-child(2) {
    width: min(100%, 82%);
    margin: 0 auto;
    justify-self: center;
  }
}

/* ==========================================================================
   Contact
   ========================================================================== */

.contact-layout {
  padding: clamp(64px, 11vw, 140px) var(--gutter) clamp(72px, 11vw, 140px);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(36px, 6.5vw, 108px);
  align-items: start; /* was center — "Get in Touch" and "Currently
    accepting..." have different content heights, so centering each
    column independently left their headings misaligned; top-aligning
    both starts them at the same line */
}

@media (max-width: 900px) {
  .contact-layout {
    grid-template-columns: 1fr;
    gap: clamp(32px, 6vw, 56px);
  }
}

.contact-hero {
  padding: 0;
}

.contact-hero h1 {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(1.6rem, 3vw, 2.4rem); /* matches .contact-availability h2 */
  margin: 0 0 1.4rem;
}

.contact-hero .phone-link,
.contact-hero .email-link {
  display: block;
  width: fit-content;
  font-family: var(--font-sans);
  font-size: clamp(0.9rem, 1.95vw, 1.275rem); /* -25% from clamp(1.2rem, 2.6vw, 1.7rem) */
  border-bottom: 1px solid var(--border-strong);
  padding-bottom: 0.15em;
}

.contact-hero .phone-link {
  margin-bottom: 0.6em;
  color: var(--text-dim);
}

.contact-response-time {
  margin: 1rem 0 0;
  color: var(--text-dim);
  font-size: 0.9rem;
  line-height: 1.5;
}

.contact-availability {
  padding: 0;
}

.contact-availability h2 {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  max-width: 22ch;
  line-height: 1.3;
  margin: 0 0 1.9rem;
}

/* ==========================================================================
   Consultation
   ========================================================================== */

.consult-layout {
  padding: clamp(48px, 7.5vw, 84px) var(--gutter) clamp(72px, 10.5vw, 128px);
  display: grid;
  grid-template-columns: minmax(260px, 1.3fr) minmax(280px, 414px);
  gap: clamp(36px, 6.5vw, 88px);
  align-items: start;
}

/* On desktop, let the page introduction lead into a full-width booking
   surface so the custom calendar has room for its editorial layout while
   keeping the mobile booking card unchanged. */
@media (min-width: 901px) {
  .consult-layout {
    display: block;
  }

  .consult-layout .consult-booking-live {
    width: 100%;
    max-width: none;
    margin-top: clamp(48px, 6vw, 76px);
  }

  .consult-intro .consult-intro-copy,
  .consult-booking-live .calendar-legacy-intro {
    max-width: none;
    white-space: nowrap;
  }
}

.consult-intro h1 {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(2rem, 4.4vw, 3.2rem);
  margin: 0 0 1.6rem;
  line-height: 1.15;
}

.consult-intro .prose {
  margin-bottom: 2.3rem;
}

.consult-steps {
  list-style: none;
  margin: 2.3rem 0 0;
  padding: 2rem 0 0;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
}

.consult-steps li {
  display: flex;
  gap: 0.9em;
  font-family: var(--font-sans);
  color: var(--text-dim);
  font-size: 0.98rem;
}

.consult-steps .step-n {
  font-family: var(--font-sans);
  font-style: normal;
  font-weight: 600;
  color: var(--text);
}

.consult-booking {
  max-width: 414px;
  border: 1px solid var(--border);
  padding: clamp(18px, 2.3vw, 25px);
}

.consult-booking-live {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-height: 315px;
}

.consult-booking-live .calendar-legacy-title {
  margin-top: 0;
}

.calendar-live-eyebrow {
  color: var(--text-faint);
  font-size: 0.71rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.calendar-legacy-title {
  margin: 1.25rem 0 0.75rem;
  font-family: var(--font-sans);
  font-size: 1.25rem;
  line-height: 1.2;
}

.calendar-legacy-intro {
  margin: 0 0 1.4rem;
  color: var(--text-dim);
}

.consult-booking-live h2 {
  margin: 1.25rem 0 0.75rem;
  font-family: var(--font-sans);
  font-size: 1.25rem;
  line-height: 1.2;
}

.consult-booking-live .prose {
  margin: 0;
  color: var(--text-dim);
}

.calendar-live-link {
  margin-top: auto;
  width: 100%;
  justify-content: space-between;
}

.calendar-live-note {
  margin: 1rem 0 0;
  color: var(--text-faint);
  font-family: var(--font-sans);
  font-size: 0.75rem;
  line-height: 1.45;
}

.calendar-status {
  width: 100%;
  margin: 1.2rem 0 1.4rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
  color: var(--text-faint);
  font-family: var(--font-sans);
  font-size: 0.78rem;
  line-height: 1.45;
}

.calendar-status.is-error {
  color: var(--text-dim);
}

.cal-head {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(11px, 2.3vw, 21px);
  margin-bottom: 0.98rem;
}

.cal-head .cal-month {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 1.01rem;
  min-width: 10ch;
  text-align: center;
}

.cal-nav {
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  transition: border-color 0.2s ease, opacity 0.2s ease;
}

.cal-nav svg {
  width: 13px;
  height: 13px;
}

.cal-nav:hover {
  border-color: var(--border-strong);
}

.cal-nav:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.cal-head-rule {
  width: 100%;
  height: 1px;
  background: var(--border);
  margin-bottom: 0.98rem;
}

.date-step {
  width: min(100%, 720px);
  margin: 0 auto;
}

.cal-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 5px;
  margin-bottom: 5px;
}

.cal-weekdays span {
  text-align: center;
  font-size: 0.69rem;
  letter-spacing: 0.03em;
  color: var(--text-faint);
  text-transform: uppercase;
}

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 5px;
}

.cal-day {
  aspect-ratio: 1;
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-size: 0.83rem;
  color: var(--text);
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.cal-day.is-empty {
  border-color: transparent;
  cursor: default;
}

.cal-day.is-past {
  color: var(--text-faint);
  cursor: not-allowed;
  opacity: 0.4;
}

.cal-day.is-available:hover {
  border-color: var(--border-strong);
}

.cal-day.is-loading {
  color: var(--text-faint);
  cursor: wait;
  opacity: 0.45;
}

.cal-day.is-selected {
  background: var(--text);
  color: var(--bg);
  border-color: var(--text);
}

.cal-day.is-today {
  border-color: var(--border-strong);
}

.slots-panel {
  /* Used to sit stacked below the calendar (hence a top divider/margin) —
     now it's a full step swap instead: .date-step hides when this shows,
     so it just fills the same card with no divider needed above it. */
  min-height: 300px;
  width: min(100%, 560px);
  margin: 0 auto;
}

.slots-panel h3 {
  font-family: var(--font-sans);
  font-size: 0.98rem;
  font-weight: 700;
  margin: 0 0 0.92rem;
}

.slots-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
  gap: 7px;
}

.calendar-empty-state {
  margin: 0;
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: 0.9rem;
}

.slot-btn {
  border: 1px solid var(--border);
  padding: 0.58em 0.4em;
  font-size: 0.87rem;
  text-align: center;
  transition: all 0.2s ease;
}

.slot-btn:hover {
  border-color: var(--border-strong);
}

.slot-btn.is-selected {
  background: var(--text);
  color: var(--bg);
  border-color: var(--text);
}

.booking-form {
  display: grid;
  gap: 14px;
}

.field label {
  display: block;
  font-size: 0.8rem;
  color: var(--text-dim);
  margin-bottom: 0.4rem;
}

.field input,
.field textarea {
  width: 100%;
  background: var(--bg-input);
  border: 1px solid var(--border);
  padding: 0.75em 0.9em;
  font-size: 0.95rem;
  color: var(--text);
}

.field textarea {
  resize: vertical;
  min-height: 80px;
}

.field input::placeholder,
.field textarea::placeholder {
  color: var(--text-faint);
}

.booking-summary {
  font-size: 0.9rem;
  color: var(--text-dim);
  font-family: var(--font-sans);
}

.booking-summary strong {
  color: var(--text);
  font-style: normal;
  font-family: var(--font-sans);
}

.integration-note {
  margin-top: 1.5rem;
  padding: 0.9rem 1rem;
  border: 1px dashed var(--border-strong);
  font-size: 0.78rem;
  color: var(--text-faint);
  font-family: var(--font-sans);
  line-height: 1.5;
}

@media (max-width: 900px) {
  .consult-layout { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Simple content pages (legal / client portal)
   ========================================================================== */

.simple-page {
  padding: clamp(48px, 7.5vw, 96px) var(--gutter) clamp(72px, 10.5vw, 136px);
  /* Revision (2026-09-06) — widened from 900px at the client's request:
     Privacy Policy / Terms of Use were wrapping into a tall stack of
     short paragraphs at the same narrow measure as About/Services. Left
     edge is unchanged (still the same padding-left: var(--gutter) as
     every other page); only how far the text runs to the right changed,
     so longer paragraphs read as fewer, longer lines instead. */
  max-width: 1320px;
}

.simple-page h1 {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(2rem, 4.4vw, 3rem);
  margin: 0 0 1.7rem;
}

.simple-page h2 {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 1.3rem;
  margin: 2.7rem 0 1rem;
}

.simple-page p,
.simple-page li {
  font-family: var(--font-sans);
  color: var(--text-dim);
  line-height: 1.7;
  font-size: 1.02rem;
}

.simple-page p + p {
  margin-top: 1.1rem;
}

.simple-page .updated {
  color: var(--text-faint);
  font-size: 0.88rem;
  margin-bottom: 2.8rem;
}

/* ==========================================================================
   Brand Discovery — the choice screen and questionnaire panel that sit
   inside the consultation calendar, between picking a time slot and the
   booking form (see js/main.js → showDiscoveryChoice / showDiscoveryPanel).
   ========================================================================== */

.link-back {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--font-sans);
  font-size: 0.8rem;
  color: var(--text-faint);
  margin-bottom: 1.2rem;
  transition: color 0.2s ease;
}

.link-back:hover {
  color: var(--text);
}

.discovery-choice h3,
.discovery-panel-title {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 1.2rem;
  margin: 0 0 0.7rem;
}

.discovery-choice > .prose,
.discovery-panel > .prose {
  font-size: 0.92rem;
  max-width: 46ch;
  margin-bottom: 1.5rem;
}

.choice-options {
  display: grid;
  gap: 10px;
}

.choice-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3rem;
  width: 100%;
  border: 1px solid var(--border);
  padding: 1rem 1.15rem;
  text-align: left;
  transition: border-color 0.2s ease, background 0.2s ease;
}

.choice-card:hover {
  border-color: var(--border-strong);
  background: var(--bg-raised);
}

.choice-title {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--text);
}

.choice-sub {
  font-family: var(--font-sans);
  font-size: 0.8rem;
  color: var(--text-faint);
}

.discovery-panel .discovery-groups {
  margin-bottom: 1.4rem;
}

.discovery-panel [data-discovery-continue] {
  width: 100%;
}

/* Discovery questions reuse the Services accordion (.service-item), scaled
   down to fit the narrower calendar column instead of a full page width. */
.discovery-panel .service-item {
  padding: clamp(18px, 3vw, 24px) 0;
}

/* This narrower reuse of .service-item has no horizontal gutter of its own
   (it's already inset by the calendar card's padding), so its divider lines
   should run edge-to-edge of the item itself rather than inheriting the
   page-wide gutter inset above. */
.discovery-panel .service-item::before,
.discovery-panel .service-item:last-child::after {
  left: 0;
  right: 0;
}

.discovery-panel .service-toggle-title {
  font-size: clamp(0.95rem, 2vw, 1.05rem);
  gap: 0.5em;
}

.discovery-questions {
  list-style: disc;
  margin: 0 0 1.1rem;
  padding-left: 1.15em;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.discovery-questions li {
  font-family: var(--font-sans);
  font-size: 0.88rem;
  color: var(--text-dim);
  line-height: 1.5;
}

@media (max-width: 600px) {
  /* The Services accordion stacks its title spans on mobile. Keep the
     discovery number and heading together in this narrower panel instead. */
  .discovery-panel .service-toggle-title {
    display: flex;
    flex-wrap: nowrap;
    align-items: baseline;
    gap: 0.5em;
  }

  .discovery-panel .service-toggle-title > span {
    white-space: nowrap;
  }

  .discovery-panel .service-toggle-title .n {
    flex: none;
  }

  .discovery-panel .discovery-questions {
    margin-top: 1rem;
  }
}

.optional-tag {
  font-weight: 400;
  color: var(--text-faint);
}
