/* Portfolio project page, v3 (2026-10-24): Direction A refined. Written by tools/publish.py.
   Signature moments: full-screen hero with the title rising in, a Then/Now wipe
   you scrub by scrolling, a pinned horizontal film of the build, an editorial
   mosaic of the finished rooms with subtle parallax, and a full-bleed next project.
   Motion is driven by js/pv-motion.js through the --p / --q custom properties.
   Everything reads with JS off and under prefers-reduced-motion. */

:root {
  --pv-head: 78px;
  --pv-ink: #141826;
  --pv-ink-2: #1C2133;
  --pv-text: #4B4F58;
  --pv-line: rgba(255, 255, 255, 0.16);
  --pv-ease: cubic-bezier(0.2, 0.7, 0.1, 1);
  --pv-gut: clamp(1.25rem, 4vw, 3rem);
}
@media (max-width: 768px) { :root { --pv-head: 66px; } }

.pv-wrap { max-width: 1360px; margin: 0 auto; padding-left: var(--pv-gut); padding-right: var(--pv-gut); }

.pv-eyebrow {
  font-family: var(--font-sans); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.28em; text-transform: uppercase; color: var(--brown); margin: 0 0 1.1rem;
}
.pv-eyebrow--light { color: var(--light-blue); }

/* ---------- 1. Hero: full screen, title rises in, parallax on scroll ---------- */

.pv-hero {
  position: relative; margin-top: var(--pv-head);
  height: calc(100svh - var(--pv-head)); min-height: 520px;
  overflow: hidden; background: var(--pv-ink); color: #fff;
}
.pv-hero__media {
  position: absolute; inset: 0;
  transform: translate3d(0, calc(var(--p, 0) * 22%), 0);
  will-change: transform;
}
.pv-hero__media img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  animation: pv-in 2.4s var(--pv-ease) both;
}
@keyframes pv-in { from { transform: scale(1.14); filter: brightness(0.55); } to { transform: scale(1.02); filter: none; } }

.pv-hero::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top, rgba(10, 12, 20, 0.88) 0%, rgba(10, 12, 20, 0.55) 38%, rgba(10, 12, 20, 0) 68%);
}
.pv-hero__content {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding-bottom: clamp(2.5rem, 7vh, 5rem);
  opacity: calc(1 - var(--p, 0) * 1.8);
  transform: translate3d(0, calc(var(--p, 0) * -40px), 0);
}
.pv-hero .pv-eyebrow { color: #E3E9F4; animation: pv-fade 1s 0.2s var(--pv-ease) both; }
.pv-title {
  font-family: var(--font-serif); font-weight: 400; color: #fff;
  font-size: clamp(2.5rem, 6vw, 5.4rem); line-height: 1.03; letter-spacing: -0.025em;
  max-width: 16ch; margin: 0; text-wrap: balance;
}
.pv-title .w { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: 0.08em; margin-bottom: -0.08em; }
.pv-title .w > span { display: inline-block; animation: pv-rise 1.15s var(--pv-ease) both; animation-delay: calc(0.35s + var(--i) * 65ms); }
@keyframes pv-rise { from { transform: translateY(108%); } to { transform: none; } }
@keyframes pv-fade { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.pv-hero__cue {
  position: absolute; z-index: 2; right: var(--pv-gut); bottom: clamp(2.5rem, 7vh, 5rem);
  display: flex; flex-direction: column; align-items: center; gap: 0.8rem;
  font-family: var(--font-sans); font-size: 0.62rem; letter-spacing: 0.32em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.75); writing-mode: vertical-rl;
  opacity: calc(1 - var(--p, 0) * 4);
}
.pv-hero__cue::after {
  content: ''; width: 1px; height: 64px; background: #fff;
  transform-origin: top; animation: pv-cue 2.4s ease-in-out infinite;
}
@keyframes pv-cue { 0% { transform: scaleY(0); transform-origin: top; } 45% { transform: scaleY(1); transform-origin: top; } 55% { transform: scaleY(1); transform-origin: bottom; } 100% { transform: scaleY(0); transform-origin: bottom; } }

/* ---------- 2. Intro: big lead, story, facts row ---------- */

.pv-intro { padding-block: clamp(4rem, 10vw, 8.5rem) clamp(3rem, 7vw, 5.5rem); }
.pv-intro__grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: clamp(2rem, 6vw, 6.5rem); align-items: start; }
.pv-lead {
  font-family: var(--font-serif); font-size: clamp(1.55rem, 2.7vw, 2.4rem); line-height: 1.28;
  color: var(--navy); letter-spacing: -0.012em; margin: 0; text-wrap: pretty;
}
.pv-body p { color: var(--pv-text); font-size: 1.06rem; line-height: 1.85; margin-bottom: 1.2rem; }

.pv-facts {
  display: grid; grid-template-columns: 1fr 1fr 1.2fr 2fr; gap: 0 clamp(1rem, 3vw, 2.5rem);
  margin: clamp(3rem, 7vw, 5.5rem) 0 0; padding-top: 1.25rem; border-top: 1px solid var(--navy);
}
.pv-facts dt { font-family: var(--font-sans); font-size: 0.64rem; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase; color: var(--gray); margin-bottom: 0.45rem; }
.pv-facts dd { margin: 0; font-family: var(--font-serif); font-size: 1.12rem; line-height: 1.45; color: var(--black); }
.pv-facts dd small { display: block; font-family: var(--font-body); font-size: 0.85rem; color: var(--gray); margin-top: 0.2rem; }

@media (max-width: 860px) {
  .pv-intro__grid { grid-template-columns: 1fr; }
  .pv-facts { grid-template-columns: 1fr 1fr; gap: 1.5rem 1.25rem; }
  .pv-facts > div:last-child { grid-column: 1 / -1; }
}

/* ---------- 3. Then / Now: scroll scrubs a wipe from the before to the after ---------- */

.pv-then { position: relative; height: 230vh; background: var(--pv-ink); }
.pv-then__stick { position: sticky; top: var(--pv-head); height: calc(100svh - var(--pv-head)); overflow: hidden; }
.pv-then__img { position: absolute; inset: 0; margin: 0; }
.pv-then__img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pv-then__stick::after { content: ''; position: absolute; inset: auto 0 0 0; height: 40%; z-index: 3; pointer-events: none;
  background: linear-gradient(to top, rgba(10, 12, 20, 0.75), rgba(10, 12, 20, 0)); }
.pv-then__img--then {
  clip-path: inset(0 calc(var(--wp, 0) * 100%) 0 0);
  --wp: clamp(0, (var(--p, 0) - 0.15) / 0.7, 1);
}
.pv-then__img--then img { filter: saturate(0.85); }
.pv-then__line {
  --wp: clamp(0, (var(--p, 0) - 0.15) / 0.7, 1);
  position: absolute; top: 0; bottom: 0; z-index: 3; width: 2px; margin-left: -1px;
  left: calc((1 - var(--wp)) * 100%); background: #fff; box-shadow: 0 0 24px rgba(0, 0, 0, 0.5);
}
.pv-then__tag {
  position: absolute; z-index: 4; top: clamp(1.25rem, 4vh, 2.5rem);
  font-family: var(--font-serif); font-size: clamp(2.6rem, 7vw, 6rem); line-height: 1; color: #fff;
  text-shadow: 0 2px 30px rgba(0, 0, 0, 0.45); letter-spacing: -0.02em;
}
.pv-then__tag--then { left: var(--pv-gut); opacity: calc(1.6 - var(--wp, 0) * 2); --wp: clamp(0, (var(--p, 0) - 0.15) / 0.7, 1); }
.pv-then__tag--now { right: var(--pv-gut); opacity: calc(var(--wp, 0) * 2 - 0.4); --wp: clamp(0, (var(--p, 0) - 0.15) / 0.7, 1); }
.pv-then__cap {
  position: absolute; z-index: 4; left: var(--pv-gut); right: var(--pv-gut); bottom: clamp(1.25rem, 4vh, 2.5rem);
  max-width: 46ch; color: rgba(255, 255, 255, 0.92); font-size: 0.95rem; line-height: 1.55;
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
}
.pv-then__cap b { display: block; font-family: var(--font-sans); font-size: 0.64rem; letter-spacing: 0.24em; text-transform: uppercase; color: var(--light-blue); margin-bottom: 0.35rem; font-weight: 600; }

/* ---------- 4. The build: pinned horizontal film on desktop, swipe row on phones ---------- */

.pv-film { position: relative; background: var(--pv-ink); color: #fff; }
.pv-film__stick { position: sticky; top: var(--pv-head); height: calc(100svh - var(--pv-head)); overflow: hidden; display: flex; flex-direction: column; justify-content: center; gap: clamp(1.25rem, 3vh, 2.25rem); }
.pv-film__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 2rem; width: 100%; }
.pv-film__head h2 { color: #fff; font-size: clamp(2rem, 4.2vw, 3.6rem); line-height: 1.05; margin: 0; letter-spacing: -0.02em; }
.pv-film__count { font-family: var(--font-sans); font-size: 0.78rem; letter-spacing: 0.2em; color: rgba(255, 255, 255, 0.6); white-space: nowrap; font-variant-numeric: tabular-nums; }
.pv-film__count b { color: #fff; font-weight: 600; font-size: 1.6rem; letter-spacing: 0.04em; margin-right: 0.3rem; }
.pv-film__track { display: flex; gap: clamp(0.9rem, 1.6vw, 1.5rem); padding: 0 var(--pv-gut); will-change: transform; }
.pv-film__frame { --fh: min(54vh, 520px); flex: none; width: calc(var(--fh) * var(--ar)); margin: 0; }
.pv-film__frame img { display: block; width: 100%; height: var(--fh); object-fit: cover; cursor: zoom-in; background: var(--pv-ink-2); }
.pv-film__frame figcaption {
  margin-top: 0.7rem; font-size: 0.82rem; line-height: 1.5; color: rgba(255, 255, 255, 0.72);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.pv-film__frame figcaption a { color: var(--light-blue); }
.pv-film__bar { margin: 0 var(--pv-gut); height: 1px; background: var(--pv-line); }
.pv-film__bar span { display: block; height: 100%; background: #fff; transform-origin: left; transform: scaleX(var(--p, 0)); }

/* phones and reduced motion: no pinning, a native swipe row */
.pv-film.is-static .pv-film__stick { position: static; height: auto; padding-block: clamp(3.5rem, 10vw, 5rem); }
.pv-film.is-static .pv-film__track { overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; transform: none !important; }
.pv-film.is-static .pv-film__track::-webkit-scrollbar { display: none; }
.pv-film.is-static .pv-film__frame { scroll-snap-align: start; --fh: min(46vh, 380px); max-width: 84vw; }
.pv-film.is-static .pv-film__frame:last-child { margin-right: var(--pv-gut); }

/* ---------- 5. The finished rooms: editorial mosaic, parallax inside each frame ---------- */

.pv-after { padding-block: clamp(4rem, 9vw, 7.5rem); }
.pv-after__head { display: flex; justify-content: space-between; align-items: flex-end; gap: 2rem; margin-bottom: clamp(2rem, 4vw, 3.25rem); }
.pv-after__head h2 { font-size: clamp(2rem, 4.2vw, 3.6rem); line-height: 1.05; margin: 0; letter-spacing: -0.02em; }
.pv-after__head p { margin: 0; max-width: 34ch; color: var(--pv-text); }
.pv-mrow { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: clamp(0.75rem, 1.4vw, 1.25rem); height: clamp(240px, 34vw, 560px); margin-bottom: clamp(0.75rem, 1.4vw, 1.25rem); }
.pv-mrow--full { height: clamp(300px, 50vw, 760px); }
.pv-cell { position: relative; margin: 0; overflow: hidden; background: var(--border-light); }
.pv-cell img {
  position: absolute; left: 0; top: -9%; width: 100%; height: 118%; object-fit: cover; cursor: zoom-in;
  transform: translate3d(0, calc((var(--q, 0.5) - 0.5) * -14%), 0) scale(1.001);
  transition: scale 1.2s var(--pv-ease);
}
.pv-cell:hover img { scale: 1.04; }
.pv-cell figcaption {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; padding: 2.5rem 1rem 0.9rem;
  color: #fff; font-size: 0.82rem; line-height: 1.45;
  background: linear-gradient(to top, rgba(10, 12, 20, 0.72), rgba(10, 12, 20, 0));
  opacity: 0; transform: translateY(8px); transition: opacity 0.5s var(--pv-ease), transform 0.5s var(--pv-ease);
}
.pv-cell:hover figcaption, .pv-cell:focus-within figcaption { opacity: 1; transform: none; }
@media (hover: none) { .pv-cell figcaption { opacity: 1; transform: none; } }
@media (max-width: 700px) {
  .pv-mrow, .pv-mrow--full { grid-template-columns: 1fr; height: auto; }
  .pv-cell { grid-column: auto !important; aspect-ratio: 4 / 3; }
  .pv-after__head { flex-direction: column; align-items: flex-start; }
}

/* ---------- 6. The work + approvals: sticky label beside the text ---------- */

.pv-work { border-top: 1px solid var(--border-light); padding-block: clamp(4rem, 8vw, 6.5rem); }
.pv-work__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: clamp(2rem, 6vw, 6rem); }
.pv-work__label { position: sticky; top: calc(var(--pv-head) + 2rem); align-self: start; }
.pv-work__label h2 { font-size: clamp(1.9rem, 3.4vw, 2.8rem); margin: 0; }
.pv-work__text p { color: var(--pv-text); line-height: 1.9; }
.pv-work__text p b { color: var(--navy); font-weight: 500; }
@media (max-width: 860px) { .pv-work__grid { grid-template-columns: 1fr; } .pv-work__label { position: static; } }

/* ---------- 7. Next project: full-bleed, big type ---------- */

.pv-next { position: relative; display: block; height: clamp(420px, 78vh, 820px); overflow: hidden; background: var(--pv-ink); color: #fff; text-decoration: none; }
.pv-next img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transform: scale(calc(1.18 - var(--p, 0) * 0.16)); transition: filter 0.8s var(--pv-ease); filter: brightness(0.62); }
.pv-next:hover img { filter: brightness(0.75); }
.pv-next__inner { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; padding-bottom: clamp(2.5rem, 8vh, 5.5rem); }
.pv-next__title { font-family: var(--font-serif); font-size: clamp(2.4rem, 6.5vw, 6rem); line-height: 1.02; letter-spacing: -0.025em; max-width: 16ch; color: #fff; margin: 0; }
.pv-next__go {
  display: inline-flex; align-items: center; gap: 0.9rem; margin-top: 1.6rem;
  font-family: var(--font-sans); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase;
}
.pv-next__go::after { content: '→'; display: grid; place-items: center; width: 52px; height: 52px; border: 1px solid rgba(255, 255, 255, 0.6); border-radius: 50%; font-size: 1.1rem; letter-spacing: 0; transition: background 0.4s, color 0.4s, transform 0.4s var(--pv-ease); }
.pv-next:hover .pv-next__go::after { background: #fff; color: var(--pv-ink); transform: translateX(6px); }

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .pv-hero__media, .pv-hero__content, .pv-cell img, .pv-next img { transform: none !important; }
  .pv-hero__media img, .pv-title .w > span, .pv-hero .pv-eyebrow, .pv-hero__cue::after { animation: none; }
  .pv-hero__content { opacity: 1; }
}

/* ======================= v3 additions ======================= */

/* hero video (flagships): same frame as the photo hero */
.pv-hero__media video { width: 100%; height: 100%; object-fit: cover; display: block; animation: pv-in 2.4s var(--pv-ease) both; }

/* film: fades into the light sections above and below, sideways hint, "see all" tile */
.pv-film::before, .pv-film::after { content: ''; position: absolute; left: 0; right: 0; height: 140px; pointer-events: none; z-index: 1; }
.pv-film::before { top: -140px; background: linear-gradient(to bottom, rgba(20, 24, 38, 0), var(--pv-ink)); }
.pv-film::after { bottom: -140px; background: linear-gradient(to top, rgba(20, 24, 38, 0), var(--pv-ink)); }
.pv-film__hint {
  font-family: var(--font-sans); font-size: 0.66rem; font-weight: 600; letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--light-blue); display: inline-flex; align-items: center; gap: 0.6rem; margin-top: 0.9rem;
  opacity: calc(1 - var(--p, 0) * 6);
}
.pv-film__hint::after { content: '→'; font-size: 1rem; letter-spacing: 0; animation: pv-nudge 1.6s ease-in-out infinite; }
@keyframes pv-nudge { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(8px); } }
.pv-film.is-static .pv-film__hint { opacity: 1; }
.pv-film__all {
  --fh: min(54vh, 520px); flex: none; width: calc(var(--fh) * 0.75); height: var(--fh); margin: 0;
  display: grid; place-content: center; gap: 0.75rem; text-align: center; cursor: pointer;
  border: 1px solid var(--pv-line); background: var(--pv-ink-2); color: #fff; font: inherit;
}
.pv-film__all b { font-family: var(--font-serif); font-weight: 400; font-size: clamp(2.4rem, 5vw, 4rem); line-height: 1; }
.pv-film__all span { font-family: var(--font-sans); font-size: 0.68rem; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--light-blue); }
.pv-film__all:hover, .pv-film__all:focus-visible { background: var(--navy); outline: none; }
.pv-film.is-static .pv-film__all { --fh: min(46vh, 380px); scroll-snap-align: start; }
.pv-allbuild { padding-block: clamp(2.5rem, 5vw, 4rem); background: var(--pv-ink); }
.pv-allbuild__grid { columns: 4 220px; column-gap: 0.9rem; }
.pv-allbuild figure { break-inside: avoid; margin: 0 0 0.9rem; }
.pv-allbuild img { width: 100%; height: auto; display: block; cursor: zoom-in; }
.pv-allbuild figcaption { font-size: 0.76rem; line-height: 1.45; color: rgba(255, 255, 255, 0.7); margin-top: 0.4rem; }
.pv-allbuild h3 { color: #fff; margin: 0 0 1.5rem; font-size: clamp(1.4rem, 2.6vw, 2rem); }

/* photos open up from a thin slice as they arrive (reveal.js adds .rv-in) */
.rv-on .pv-open { opacity: 1; transform: none; }
.rv-on .pv-open > img { clip-path: inset(46% 0 46% 0); transition: clip-path 1.25s var(--pv-ease), scale 1.2s var(--pv-ease); }
.rv-on .pv-open.rv-in > img { clip-path: inset(0 0 0 0); }

/* pull quote */
.pv-quote { padding-block: clamp(4rem, 10vw, 8rem); text-align: center; }
.pv-quote blockquote { margin: 0 auto; max-width: 22ch; font-family: var(--font-serif); font-style: italic; font-size: clamp(2rem, 4.6vw, 3.8rem); line-height: 1.18; color: var(--navy); letter-spacing: -0.015em; text-wrap: balance; }
.pv-quote blockquote::before { content: '“'; display: block; font-size: 1.6em; line-height: 0.6; color: var(--brown); font-style: normal; margin-bottom: 0.2em; }

/* the work: a scroll-along timeline, the step at mid-screen lights up */
.pv-steps { position: relative; padding-left: 2rem; }
.pv-steps::before { content: ''; position: absolute; left: 0.35rem; top: 0.6rem; bottom: 0.6rem; width: 1px; background: var(--border-light); }
.pv-steps::after { content: ''; position: absolute; left: 0.35rem; top: 0.6rem; width: 1px; height: calc(var(--done, 0) * (100% - 1.2rem)); background: var(--navy); transition: height 0.4s var(--pv-ease); }
.pv-step { position: relative; margin: 0 0 1.6rem; color: var(--pv-text); line-height: 1.85; transition: opacity 0.5s var(--pv-ease); }
.pv-step::before { content: ''; position: absolute; left: -1.95rem; top: 0.55rem; width: 11px; height: 11px; border-radius: 50%; background: var(--paper, #fff); border: 1px solid var(--light-blue); transition: background 0.4s, border-color 0.4s, transform 0.4s var(--pv-ease); z-index: 1; }
.js-steps .pv-step { opacity: 0.42; }
.js-steps .pv-step.is-on, .js-steps .pv-step.is-past { opacity: 1; }
.pv-step.is-on::before, .pv-step.is-past::before { background: var(--navy); border-color: var(--navy); }
.pv-step.is-on::before { transform: scale(1.35); }
.pv-step b { color: var(--navy); font-weight: 500; }

/* "inside this house" hub cards */
.pv-hub { padding-block: clamp(3.5rem, 8vw, 6rem); border-top: 1px solid var(--border-light); }
.pv-hub__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: clamp(0.75rem, 1.4vw, 1.25rem); margin-top: 2rem; }
.pv-hub__card { position: relative; display: block; aspect-ratio: 4 / 5; overflow: hidden; background: var(--pv-ink); color: #fff; text-decoration: none; }
.pv-hub__card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: scale 1.2s var(--pv-ease), filter 0.6s; filter: brightness(0.78); }
.pv-hub__card:hover img { scale: 1.05; filter: brightness(0.9); }
.pv-hub__card span { position: absolute; left: 1.1rem; right: 1.1rem; bottom: 1rem; z-index: 1; font-family: var(--font-serif); font-size: 1.35rem; line-height: 1.2; text-shadow: 0 2px 18px rgba(0, 0, 0, 0.5); }
.pv-hub__card small { display: block; font-family: var(--font-sans); font-size: 0.62rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--light-blue); margin-bottom: 0.4rem; }
.pv-hub__head h2 { font-size: clamp(2rem, 4.2vw, 3.2rem); margin: 0; letter-spacing: -0.02em; }

/* short build sets: a plain vertical grid instead of the film */
.pv-buildgrid { padding-block: clamp(3.5rem, 8vw, 6rem); background: var(--pv-ink); color: #fff; }
.pv-buildgrid h2 { color: #fff; margin: 0 0 2rem; font-size: clamp(2rem, 4.2vw, 3.2rem); }

/* approvals box inherited from styles.css, give it room */
.pv-approvals { padding-block: 0 clamp(3rem, 6vw, 5rem); }

@media (prefers-reduced-motion: reduce) {
  .rv-on .pv-open > img { clip-path: none; transition: none; }
  .pv-film__hint::after { animation: none; }
  .js-steps .pv-step { opacity: 1; }
}

.pv-film__track::after { content: ""; flex: 0 0 calc(var(--pv-gut) - clamp(0.9rem, 1.6vw, 1.5rem)); }
@media (max-width: 700px) {
  .pv-hub__grid { grid-template-columns: 1fr 1fr; }
  .pv-hub__card { aspect-ratio: 3 / 4; }
  .pv-hub__card span { font-size: 1rem; left: 0.75rem; right: 0.75rem; bottom: 0.7rem; }
}

/* ======================= v3.1 fixes (2026-10-24) ======================= */

/* Then / Now: the whole photo, over a soft blurred fill of itself */
.pv-then__img { background: var(--pv-ink); }
.pv-then__img .pv-then__fill { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: blur(34px) brightness(0.45) saturate(1.1); transform: scale(1.15); }
.pv-then__img .pv-then__photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.pv-then__img--then img.pv-then__photo { filter: saturate(0.85); }
/* captions swap with the wipe: Before fades out past the middle, After fades in */
.pv-then__cap { --wp: clamp(0, (var(--p, 0) - 0.15) / 0.7, 1); opacity: calc(1 - var(--wp) * 2.2); transition: none; }
.pv-then__cap--now { left: auto; right: var(--pv-gut); text-align: right; opacity: calc(var(--wp) * 2.2 - 1.2); }
.pv-then__cap--now b { margin-left: auto; }

/* expand icon on every clickable photo */
.pv-film__frame, .pv-cell, .pv-bfig, .pv-allbuild figure { position: relative; }
.pv-film__frame::after, .pv-cell::after, .pv-bfig::after, .pv-allbuild figure::after {
  content: ''; position: absolute; top: 10px; right: 10px; z-index: 3; width: 34px; height: 34px; border-radius: 50%; pointer-events: none;
  background: rgba(20, 24, 38, 0.55) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7'/%3E%3C/svg%3E") center / 15px no-repeat;
  opacity: 0.85; transition: opacity 0.3s, transform 0.3s var(--pv-ease);
}
.pv-film__frame:hover::after, .pv-cell:hover::after, .pv-bfig:hover::after, .pv-allbuild figure:hover::after { opacity: 1; transform: scale(1.1); }

/* small build sets: whole photos in a masonry grid with captions */
.pv-bgrid { columns: var(--cols, 3) 260px; column-gap: clamp(0.9rem, 1.6vw, 1.4rem); }
.pv-bfig { break-inside: avoid; margin: 0 0 clamp(0.9rem, 1.6vw, 1.4rem); }
.pv-bfig img { display: block; width: 100%; height: auto; cursor: zoom-in; background: var(--pv-ink-2); }
.pv-bfig figcaption { margin-top: 0.55rem; font-size: 0.84rem; line-height: 1.5; color: rgba(255, 255, 255, 0.75); }
.pv-bfig figcaption a { color: var(--light-blue); }
.pv-film__frame img { cursor: zoom-in; }

/* phones: a portrait screen fits portrait and landscape photos better filled than letterboxed */
@media (max-width: 700px) {
  .pv-then__img .pv-then__photo { object-fit: cover; }
}

/* hub cards: a dark fade under the title so it reads on light photos */
.pv-hub__card::after { content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(to top, rgba(10, 12, 20, 0.85) 0%, rgba(10, 12, 20, 0.35) 45%, rgba(10, 12, 20, 0) 70%); }
.pv-hub__card img { filter: none; }
.pv-hub__card:hover img { filter: brightness(1.05); }
@media (max-width: 700px) { .pv-hub__card span { font-size: 0.92rem; line-height: 1.25; } }

/* ======================= 2026-10-31 (Nathan) ======================= */

/* Then / Now: the After rises from the bottom of the frame as you scroll, instead of wiping sideways */
.pv-then__img--then { clip-path: inset(0 0 calc(var(--wp, 0) * 100%) 0); }
.pv-then__line { left: 0; right: 0; width: auto; height: 2px; margin-left: 0; top: auto; bottom: calc(var(--wp, 0) * 100%); }
.pv-then__cap { bottom: auto; top: calc(clamp(1.25rem, 4vh, 2.5rem) + clamp(2.6rem, 7vw, 6rem) + 0.9rem); }   /* the Before caption sits under "Then", clear of the rising After */
/* "Now" and its caption sit bottom-left in the revealed After (the chat widget owns the bottom-right corner) */
.pv-then__cap--now { top: auto; bottom: clamp(1.25rem, 4vh, 2.5rem); left: var(--pv-gut); right: auto; text-align: left; max-width: 40ch; }
.pv-then__cap--now b { margin-left: 0; }
.pv-then__tag--now { top: auto; right: auto; left: var(--pv-gut); bottom: calc(clamp(1.25rem, 4vh, 2.5rem) + 4.5rem); }
@media (max-width: 700px) { .pv-then__tag--now { bottom: calc(clamp(1.25rem, 4vh, 2.5rem) + 5.5rem); } .pv-then__cap--now { right: 5.5rem; } }

/* More projects like this: the hub card grid, filled by js/project-next.js; replaces the "See all projects" band */
.pv-related__head { display: flex; justify-content: space-between; align-items: flex-end; gap: 1.5rem; flex-wrap: wrap; }
.pv-related__all { font-family: var(--font-sans); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--navy); text-decoration: none; white-space: nowrap; }
.pv-related__all:hover { text-decoration: underline; }
.pv-related .pv-hub__grid:empty { display: none; }

/* Watch: kept clips in their own shape (portrait phone clips two or three across, landscape full row) */
.pv-clips { padding-block: clamp(3rem, 7vw, 5.5rem); border-top: 1px solid var(--border-light); }
.pv-clips__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: clamp(0.9rem, 1.6vw, 1.4rem); align-items: start; }
.pv-clip { margin: 0; }
.pv-clip:not(.pv-clip--portrait) { grid-column: 1 / -1; }
.pv-clip video { display: block; width: 100%; aspect-ratio: var(--ar, 16/9); background: var(--pv-ink); object-fit: contain; }
.pv-clip--portrait { max-width: 420px; justify-self: center; width: 100%; }
.pv-clip figcaption { margin-top: 0.55rem; font-size: 0.84rem; line-height: 1.5; color: var(--pv-text); }

/* The build: a real grid (CSS columns let a tall figure spill out of the section in WebKit), two across, one on phones */
.pv-bgrid { columns: auto; display: grid; grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr)); gap: clamp(0.9rem, 1.6vw, 1.4rem); align-items: start; }
.pv-bfig { margin: 0; }
@media (max-width: 700px) { .pv-bgrid { grid-template-columns: 1fr; } }

/* The build: four photos, then a "see all" tile in the same grid (the pinned film is retired) */
.pv-bgrid .pv-bgrid__all { width: 100%; height: 100%; min-height: clamp(220px, 28vw, 360px); margin: 0; display: grid; place-content: center; gap: 0.75rem; text-align: center; border: 1px solid var(--pv-line); background: var(--pv-ink-2); color: #fff; cursor: pointer; font: inherit; }
.pv-bgrid .pv-bgrid__all b { font-family: var(--font-serif); font-weight: 400; font-size: clamp(2.4rem, 5vw, 4rem); line-height: 1; }
.pv-bgrid .pv-bgrid__all span { font-family: var(--font-sans); font-size: 0.68rem; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase; color: var(--light-blue); }
.pv-bgrid .pv-bgrid__all:hover, .pv-bgrid .pv-bgrid__all:focus-visible { background: var(--navy); outline: none; }

/* ======================= 2026-10-31 (Eli): template fixes that hold on every page ======================= */

/* Then / Now: the big words stay on the photo; the small eyebrow and caption sit in a dark panel so they read on any photo
   (a bright sky made the Before caption unreadable). "Now" takes the same top-left spot as "Then" (they crossfade), so a
   caption of any length can never run into it; the After caption stays bottom-left, clear of the chat widget. */
.pv-then__cap {
  width: fit-content; max-width: min(46ch, calc(100% - 2 * var(--pv-gut)));
  padding: 0.7rem 0.95rem 0.8rem; border-radius: 4px;
  background: rgba(10, 12, 20, 0.72); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  color: #fff; text-shadow: none;
}
.pv-then__cap b { color: var(--light-blue); }
.pv-then__cap--now { max-width: min(40ch, calc(100% - 2 * var(--pv-gut))); }
.pv-then__tag--now { top: clamp(1.25rem, 4vh, 2.5rem); bottom: auto; left: var(--pv-gut); right: auto; }
@media (max-width: 700px) {
  .pv-then__tag--now { top: clamp(1.25rem, 4vh, 2.5rem); bottom: auto; }
  .pv-then__cap--now { max-width: calc(100% - var(--pv-gut) - 5.5rem); }   /* clear of the chat bubble */
}

/* The build: every tile the same 4:3 shape, filled, so landscape next to portrait never leaves a hole.
   Tapping a tile still opens the whole photo in the lightbox; the curate crop decides what the tile shows. */
.pv-bgrid { align-items: stretch; }
.pv-bfig img { aspect-ratio: 4 / 3; height: auto; object-fit: cover; object-position: center; }
.pv-bgrid .pv-bgrid__all { aspect-ratio: 4 / 3; min-height: 0; height: auto; }
/* odd counts: three photos sit three across; one photo is one tile, not half a row */
.pv-bgrid:has(> .pv-bfig:nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.pv-bgrid:has(> .pv-bfig:only-child) { grid-template-columns: minmax(0, 1fr); max-width: 760px; }
/* four photos and a "+N" tile: the tile becomes a slim full-width bar instead of a lone half row */
.pv-bgrid:has(> .pv-bgrid__all:nth-child(5)) .pv-bgrid__all { grid-column: 1 / -1; aspect-ratio: auto; min-height: 0; padding: 1.4rem 1rem; grid-auto-flow: column; place-content: center; align-items: baseline; gap: 1rem; }
.pv-bgrid:has(> .pv-bgrid__all:nth-child(5)) .pv-bgrid__all b { font-size: clamp(1.8rem, 3.4vw, 2.6rem); }
@media (max-width: 700px) {
  .pv-bgrid, .pv-bgrid:has(> .pv-bfig:nth-child(3):last-child) { grid-template-columns: 1fr; }
}
/* "See all build photos": the same even tiles instead of uneven columns */
.pv-allbuild__grid { columns: auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.9rem; }
.pv-allbuild figure { margin: 0; }
.pv-allbuild img { aspect-ratio: 4 / 3; object-fit: cover; }

/* Card labels (More projects like this, hub): the same rule as Then/Now. Big titles can sit on the photo; the small label
   needs real contrast, so the fade under the text is deeper and reaches higher, and the label is near-white. */
.pv-hub__card::after { background: linear-gradient(to top, rgba(10, 12, 20, 0.92) 0%, rgba(10, 12, 20, 0.78) 38%, rgba(10, 12, 20, 0.35) 62%, rgba(10, 12, 20, 0) 85%); }
.pv-hub__card small { color: #dbe3f0; font-weight: 600; text-shadow: 0 1px 6px rgba(0, 0, 0, 0.6); }
