.sec-hero { --h: 980px; background: rgba(19,19,19,1); overflow: hidden; clip-path: inset(0); }
/* curtain hero: full-bleed photo held still behind the section, revealed by
   two cream panels sliding apart.
   The backdrop is a position:fixed LAYER clipped by the section's clip-path,
   not background-attachment:fixed. A fixed background cannot be promoted to a
   compositor layer, so every scroll frame had to repaint this full-bleed
   photo, which is the stutter. clip-path clips descendants WITHOUT becoming
   their containing block, so the layer stays viewport-anchored and the
   parallax reads exactly the same while scrolling becomes a pure composite.
   Same reason it now works on iOS, where attachment:fixed is broken. */
.sec-hero::before { content: ""; position: fixed; inset: 0; z-index: 0;
  background: url("../images/gal-03.jpg") center / cover no-repeat;
  filter: brightness(.20); }
.cur-curtain { position: absolute; top: 0; bottom: 0; width: 50.5%; background: var(--cream); z-index: 3; }
.cur-l { left: 0; animation: cur-open-l 1.4s cubic-bezier(.75,0,.2,1) .4s forwards; }
.cur-r { right: 0; animation: cur-open-r 1.4s cubic-bezier(.75,0,.2,1) .4s forwards; }
@keyframes cur-open-l { to { transform: translateX(-101%); } }
@keyframes cur-open-r { to { transform: translateX(101%); } }
.cur-center { inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
.cur-center > * { position: static; margin: 0; }
/* OPTIONAL client logo, leading the curtain reveal one beat ahead of the
   kicker (1.35s vs 1.5s), so the brand lands before the copy. Both placements
   in this kit (here and .foot-logo in style.css) sit on dark ground, so a
   dark-on-transparent wordmark is forced to white with the filter rather than
   shipping a second inverted asset: brightness(0) flattens antialiased greys
   to black, invert(1) takes the lot to white, neither touches alpha. Drop the
   filter if the client's mark is already light, and delete the <img> from the
   hero markup if they have no wordmark. `.cur-center > *` zeroes margins,
   hence the two-class selector to win the gap under the mark back. */
.cur-center .cur-logo { width: clamp(170px, 21vw, 290px); height: auto;
  margin: 0 0 30px; filter: brightness(0) invert(1);
  opacity: 0; animation: cur-fade 1s ease 1.35s forwards; }
.cur-kicker { font-family: var(--font-mont); font-size: 12px; letter-spacing: .3em; text-transform: uppercase; opacity: 0; animation: cur-fade 1s ease 1.5s forwards; }
.cur-title { font-family: var(--font-serif); font-size: 104px; line-height: 1.04; max-width: 1000px; margin: 26px 0 30px; opacity: 0; animation: cur-fade 1.2s ease 1.7s forwards; }
.cur-sub { font-size: 19px; line-height: 1.55; max-width: 560px; opacity: 0; animation: cur-fade 1s ease 2s forwards; }
.cur-btn { margin-top: 38px; padding: 16px 30px; border-color: var(--cream-text); color: var(--cream-text); opacity: 0; animation: cur-fade 1s ease 2.2s forwards; }
.cur-btn:hover { background: var(--cream); border-color: var(--cream); color: var(--ink); }
.cur-corner { bottom: 96px; font-family: var(--font-mont); font-size: 11px; letter-spacing: .26em; text-transform: uppercase; opacity: 0; animation: cur-fade 1s ease 2.4s forwards; }
.cur-bl { left: 0; }
.cur-br { right: 0; }
@keyframes cur-fade { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }
.sec-intro { --h: 1010px; background: #1F1F1F; color: var(--cream-text); }
/* expanding-panels intro (variant 03, 2026-07-15) */
.xpn-kicker { left: 0; top: 88px; font-family: var(--font-mont); font-size: 12px; font-weight: 500; letter-spacing: .32em; text-transform: uppercase; }
.xpn-title { left: 0; top: 128px; width: 680px; font-size: 52px; }
.xpn-lede { left: 820px; top: 152px; width: 380px; font-size: 15px; }
/* sits under the lede, left edge aligned to it; clears .xpn-panels at 370 */
.xpn-cta { left: 820px; top: 280px; }
.xpn-panels { left: 0; top: 370px; width: 1200px; height: 540px; display: flex; gap: 12px; }
.xpn-panel { position: relative; flex: 1; overflow: hidden; display: block; text-decoration: none; transition: flex .75s cubic-bezier(.5,0,.2,1); }
/* width/height 100% are REQUIRED, not belt and braces. An absolutely positioned
   REPLACED element with inset:0 and auto sizing does not stretch to the box the
   way a div does: it keeps its intrinsic size and the over-constrained edge is
   simply ignored. So the box WAS the photo's natural size, object-fit:cover had
   nothing to crop, and the panel's overflow:hidden did the cropping instead by
   lopping off the bottom. On a phone that clipped 161 to 219px off each of these
   three, which is where the faces are: the cards showed background and the tops
   of people's heads. Desktop hid it because the panel there is ~540px tall and
   the photos land within a few px of that.

   The selector carries .sec-intro to reach (0,2,1). style.css's mobile blanket
   sets `.cv .ph { height: auto }` at (0,2,0) to reflow canvas children, and a
   bare `.xpn-panel img` is only (0,1,1), so it lost and these stayed at their
   natural height on exactly the layout where it mattered. */
.sec-intro .xpn-panel img,
.sec-intro .xpn-panel video { position: absolute; inset: 0; width: 100%; height: 100%;
  transition: transform .75s ease; }
/* Scroll-in scrim. The panel copy is white and several of the client's own
   uploads are bright, so each panel darkens to .80 as it enters the viewport
   (script.js observes .xpn-panel and adds .is-in per panel, not per section).
   Both layers carry z-index 1 deliberately: the <img> is positioned with
   z-index auto, so a bare ::before would paint UNDER the photo, and lifting
   only ::before would bury the gradient that shapes the bottom of the card.
   At 1 they sit above the photo, in DOM order (flat scrim, then gradient),
   and still below the copy at z-index 2. */
.xpn-panel::before { content: ""; position: absolute; inset: 0; z-index: 1;
  background: rgba(19,19,19,1); opacity: 0; transition: opacity .85s ease; }
.xpn-panel.is-in::before { opacity: .80; }
.xpn-panel::after { content: ""; position: absolute; inset: 0; z-index: 1; background: linear-gradient(180deg, rgba(19,19,19,.10) 0%, rgba(19,19,19,0) 30%, rgba(19,19,19,0) 52%, rgba(19,19,19,.62) 100%); }
/* mobile-only control (see the max-width:900px block); desktop reveals the
   description on hover and must not grow a plus sign */
.xpn-plus { display: none; }
.xpn-num { position: absolute; z-index: 2; top: 22px; left: 24px; color: var(--cream-text); font-family: var(--font-mont); font-size: 12px; letter-spacing: .22em; }
.xpn-name { position: absolute; z-index: 2; left: 24px; right: 24px; bottom: 24px; color: var(--cream-text); font-family: var(--font-serif); font-size: 29px; line-height: 1.15; margin: 0; font-weight: 400; }
.xpn-desc { position: absolute; z-index: 2; left: 24px; bottom: 104px; max-width: 330px; color: var(--cream-text); font-size: 14px; line-height: 1.6; margin: 0; opacity: 0; transform: translateY(12px); transition: opacity .5s ease .18s, transform .5s ease .18s; }
/* Hover behaviour is fenced behind (hover: hover) because a touch screen KEEPS
   the :hover state on whatever was tapped last. Without the fence, tapping the
   plus to close a description left `.xpn-panel:hover .xpn-desc { opacity: 1 }`
   holding it visible: the class toggled off, the text stayed on screen, and it
   only vanished once something else was tapped. The scale(1.05) stuck the same
   way. Same rule the portal calendar's chips are written under; iOS reports
   hover:none, verified there. */
@media (hover: hover) {
  .xpn-panel:hover { flex: 2.4; }
  .xpn-panels:hover .xpn-panel:not(:hover) { flex: .78; }
  .xpn-panel:hover img,
  .xpn-panel:hover video { transform: scale(1.05); }
  .xpn-panel:hover .xpn-desc { opacity: 1; transform: none; }
}
.sec-signature-offer { --h: 100vh; background: rgba(19,19,19,1); overflow: hidden; }
/* horizon signature offer (variant 04, 2026-07-15): window-height, fixed-attachment photo, baseline-anchored type, reveal on scroll */
.hzn-bg { position: absolute; inset: 0; z-index: 0;
  background: url("../images/sig-offer-bg.jpg") 50% 40% / cover no-repeat fixed rgba(19,19,19,1); }
.hzn-bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, rgba(19,19,19,.94) 8%, rgba(19,19,19,.55) 38%, rgba(19,19,19,.18) 70%); }
.hzn-base { left: 0; right: 0; bottom: 84px; }
.hzn-base > * { position: static; margin: 0; }
.hzn-kicker { font-family: var(--font-mont); font-size: 11px; letter-spacing: .34em; text-transform: uppercase; opacity: 0; }
.hzn-rule { height: 1px; background: rgba(245,245,245,.45); margin: 22px 0 40px; transform-origin: left; transform: scaleX(0); }
.hzn-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 60px; }
.hzn-title { font-family: var(--font-serif); font-size: 104px; line-height: .98; max-width: 720px; opacity: 0; transform: translateY(28px); }
.hzn-side { width: 330px; flex: none; padding-bottom: 10px; opacity: 0; transform: translateY(24px); }
.hzn-copy { font-size: 16px; line-height: 1.75; opacity: .88; }
.hzn-btn { margin-top: 28px; padding: 16px 28px; }
.sec-signature-offer.is-in .hzn-kicker { animation: hzn-fade 1s ease .1s forwards; }
.sec-signature-offer.is-in .hzn-rule { animation: hzn-draw 1.4s cubic-bezier(.6,0,.2,1) .25s forwards; }
.sec-signature-offer.is-in .hzn-title { animation: hzn-rise 1.1s cubic-bezier(.2,.7,.2,1) .45s forwards; }
.sec-signature-offer.is-in .hzn-side { animation: hzn-rise 1.1s cubic-bezier(.2,.7,.2,1) .65s forwards; }
@keyframes hzn-fade { to { opacity: .7; } }
@keyframes hzn-draw { to { transform: scaleX(1); } }
@keyframes hzn-rise { to { opacity: 1; transform: none; } }
/* statement + moving gallery: veiled drift (slow continuous belt, photos surface
   from a cream veil at one edge and dissolve into the other; the photo passing
   center leads at full color; arrows skip the belt one photo; JS in script.js) */
.vgal { background: var(--cream); padding: 13vh 0 15vh; }
.vgal-head { text-align: center; padding: 0 10vw 9vh; }
.vgal-kicker { font-family: var(--font-mont); font-size: 12px; letter-spacing: .35em; text-transform: uppercase; margin: 0 0 26px; }
.vgal-title { font-family: var(--font-serif); font-size: clamp(36px, 3.2vw, 48px); line-height: 1.12; text-transform: uppercase; margin: 0 auto; max-width: 820px; }
.vgal-belt { position: relative; overflow: hidden; }
.vgal-belt::before, .vgal-belt::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 16vw; z-index: 2; pointer-events: none;
}
.vgal-belt::before { left: 0; background: linear-gradient(90deg, var(--cream), rgba(245,245,245,0)); }
.vgal-belt::after { right: 0; background: linear-gradient(270deg, var(--cream), rgba(245,245,245,0)); }
.vgal-track { display: flex; align-items: center; gap: 4.5vw; width: max-content; padding-right: 4.5vw; will-change: transform; }
.vgal-track img,
.vgal-track video {
  display: block; width: auto; object-fit: cover;
  transition: filter 1.4s ease, transform 1.4s ease;
  filter: brightness(.94) saturate(.88); transform: scale(.985);
}
.vgal-track :is(img, video):nth-child(odd) { height: 54vh; }
.vgal-track :is(img, video):nth-child(even) { height: 44vh; }
.vgal-track img.lead,
.vgal-track video.lead { filter: brightness(1) saturate(1); transform: scale(1); }
/* testimonial: type takeover (one giant serif quote at a time, lines lift in, arrows + timing bar) */
/* --h grown 900 -> 1000 for this build: the second quote's last kit line
   wraps to two rows at 74px, and at 900 it painted through the bottom-anchored
   byline (71px overlap). Mobile is unaffected (.sec height:auto blanket). */
.sec-testimonial { --h: 1000px; background: #282828; overflow: hidden; }
.tt-topline {
  left: 0; right: 0; top: 74px;
  display: flex; justify-content: space-between; align-items: baseline;
  border-bottom: 1px solid rgba(245,245,245,.25); padding-bottom: 22px;
}
.tt-kicker { margin: 0; font-family: var(--font-mont); font-size: 12px; letter-spacing: .28em; text-transform: uppercase; opacity: .7; }
.tt-counter { margin: 0; font-family: var(--font-serif); font-size: 22px; }
.tt-counter .tt-total { opacity: .45; }
.tt-slides { left: 0; right: 0; top: 200px; height: 460px; }
.tt-slide { position: absolute; inset: 0; visibility: hidden; }
.tt-slide.is-on { visibility: visible; }
/* The reveal mask must clip wider than the line box: line-height 1.12 is
   TIGHTER than the font's own metrics (half-leading is negative), so
   descenders in y/g/q/p sit ~3px below the line box and overflow:hidden
   was shearing them off. Pad the clip box down and pull the same amount
   back with a negative margin, so line rhythm is byte-identical and only
   the clip region grows. Kept in em so the mobile clamp() size inherits
   the fix. The slide-in start must clear the taller box: 110% of the span
   no longer covers it, hence 125%. */
.tt-line {
  display: block; overflow: hidden;
  font-family: var(--font-serif); font-size: 74px; line-height: 1.12;
  padding-bottom: .1em; margin-bottom: -.1em;
}
.tt-line > span { display: block; transform: translateY(125%); }
.tt-slide.is-on .tt-line > span { animation: tt-line-in .9s cubic-bezier(.2,.7,.2,1) forwards; }
.tt-slide.is-out .tt-line > span { animation: tt-line-out .5s ease forwards; }
@keyframes tt-line-in { from { transform: translateY(125%); } to { transform: translateY(0); } }
@keyframes tt-line-out { from { transform: translateY(0); } to { transform: translateY(-110%); } }
.tt-byline { left: 0; bottom: 120px; display: flex; align-items: center; gap: 20px; }
.tt-by-photo { width: 64px; height: 64px; border-radius: 50%; object-fit: cover; }
.tt-by-name { font-family: var(--font-italic); font-size: 24px; margin: 0; }
.tt-by-tag { font-family: var(--font-mont); font-size: 11px; letter-spacing: .22em; text-transform: uppercase; opacity: .55; margin: 4px 0 0; }
.tt-by-block { transition: opacity .4s ease; }
.tt-arrows { right: 0; bottom: 158px; display: flex; gap: 54px; }
.tt-arrow { background: none; border: 0; padding: 8px 0; cursor: pointer; color: var(--cream-text); display: block; }
.tt-arrow svg { display: block; width: 88px; height: 10px; overflow: visible; }
.tt-arrow svg line, .tt-arrow svg polyline {
  stroke: currentColor; stroke-width: 1.2; fill: none;
  transition: transform .4s ease;
}
.tt-arrow:hover svg line, .tt-arrow:hover svg polyline { transform: translateX(6px); }
.tt-prev:hover svg line, .tt-prev:hover svg polyline { transform: translateX(-6px); }
.tt-progress { left: 0; right: 0; bottom: 74px; height: 1px; background: rgba(245,245,245,.2); }
.tt-progress i { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: var(--cream-text); }
.tt-progress i.run { animation: tt-fill 6.5s linear forwards; }
@keyframes tt-fill { from { width: 0; } to { width: 100%; } }
/* about: margin axis (variant 05, 2026-07-15) — hard left text axis, rotated
   spine label, numbered marginalia, full-height photo bleeding off the right
   edge with a spinning badge; entrances gated by .is-in from the shared
   reveal observer in script.js */
.sec-about { --h: 900px; background: #E7E7E7; overflow: hidden; }
.abx-spine { left: -8px; top: 120px; writing-mode: vertical-rl; transform: rotate(180deg); font-family: var(--font-mont); font-size: 11px; letter-spacing: .4em; text-transform: uppercase; color: var(--accent); opacity: 0; }
.abx-title { left: 120px; top: 110px; font-family: var(--font-serif); font-weight: 400; font-size: 104px; line-height: 1.04; opacity: 0; transform: translateY(24px); }
.abx-para { left: 120px; top: 370px; width: 400px; font-size: 16px; line-height: 1.75; letter-spacing: .02em; opacity: 0; transform: translateY(24px); }
.abx-sub { left: 120px; top: 576px; width: 400px; font-size: 16px; line-height: 1.75; letter-spacing: .02em; opacity: 0; transform: translateY(24px); }
.abx-cta { left: 120px; top: 712px; opacity: 0; transform: translateY(24px); }
.abx-cta .btn { padding: 15px 26px; }
.abx-notes { left: 600px; top: 432px; width: 200px; opacity: 0; transform: translateY(24px); }
.abx-note { border-top: 1px solid rgba(22,22,22,.22); padding: 16px 0 24px; cursor: default; transition: border-color .4s ease; }
.abx-note:hover { border-color: var(--accent); }
.abx-note:hover .w { font-family: var(--font-italic); }
.abx-note .n { display: block; font-family: var(--font-mont); font-size: 10px; letter-spacing: .3em; color: var(--accent); margin-bottom: 6px; }
.abx-note .w { display: block; font-family: var(--font-serif); font-size: 21px; line-height: 1.25; }
.abx-tall { left: 860px; top: 0; width: calc(340px + var(--gutter)); height: 900px; overflow: hidden; opacity: 0; transform: translateX(90px); }
.abx-tall img,
.abx-tall video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; opacity: 0; transition: opacity .8s ease; animation: abx-drift 26s ease-in-out infinite alternate; }
.abx-tall img.is-on,
.abx-tall video.is-on { opacity: 1; }
.abx-tall :is(img, video):nth-child(3) { object-position: 0 50%; }
/* owner portrait: an inset slot straddling the tall photo's left edge */
.abx-owner { left: 715px; top: 292px; width: 300px; height: 384px; z-index: 2;
             overflow: hidden; opacity: 0; transform: translateY(24px);
             box-shadow: 0 18px 46px rgba(25, 21, 17, .3); }
.abx-owner img { width: 100%; height: 100%; object-fit: cover; display: block; }
.abx-owner figcaption { position: absolute; left: 0; right: 0; bottom: 0;
             font-family: var(--font-mont); font-size: 9px; font-weight: 500;
             letter-spacing: .26em; text-transform: uppercase; text-align: center;
             padding: 9px 8px; background: rgba(15, 13, 11, .74); color: #fff; }
.sec-about.is-in .abx-spine { animation: abx-fade 1s ease .2s forwards; }
.sec-about.is-in .abx-title { animation: abx-rise 1s ease .3s forwards; }
.sec-about.is-in .abx-para { animation: abx-rise 1s ease .5s forwards; }
.sec-about.is-in .abx-sub { animation: abx-rise 1s ease .62s forwards; }
.sec-about.is-in .abx-notes { animation: abx-rise 1s ease .68s forwards; }
.sec-about.is-in .abx-cta { animation: abx-rise 1s ease .75s forwards; }
.sec-about.is-in .abx-tall { animation: abx-glide 1.3s cubic-bezier(.5,0,.2,1) both; }
.sec-about.is-in .abx-owner { animation: abx-rise 1s ease .9s forwards; }
@keyframes abx-rise { to { opacity: 1; transform: none; } }
@keyframes abx-fade { to { opacity: 1; } }
@keyframes abx-glide { to { opacity: 1; transform: none; } }
@keyframes abx-drift { from { transform: scale(1); } to { transform: scale(1.09); } }
/* case studies: filmstrip (chosen variant 03, 2026-07-15) — window-height
   panel, strip steps only via the arrows (no user scroll/drag) */
.sec-stats-or-features { --h: auto; height: 100vh; min-height: 840px; padding: 0; background: #363636; display: flex; flex-direction: column; justify-content: center; }
.fcs-head { width: 1200px; margin: 0 auto; display: flex; align-items: flex-end; justify-content: space-between; }
.fcs-eyebrow { font-family: var(--font-mont); font-size: 13px; letter-spacing: .24em; text-transform: uppercase; color: rgba(245,245,245,.55); margin: 0; }
.fcs-title { font-family: var(--font-serif); font-size: 64px; line-height: 1.05; margin: 12px 0 0; }
.fcs-arrows { display: flex; gap: 54px; padding-bottom: 12px; }
.fcs-arrow { background: none; border: 0; padding: 8px 0; cursor: pointer; color: var(--cream-text); display: block; }
.fcs-arrow svg { display: block; width: 110px; height: 12px; overflow: visible; }
.fcs-arrow svg line, .fcs-arrow svg polyline {
  stroke: currentColor; stroke-width: 1.2; fill: none;
  transition: transform .4s ease;
}
.fcs-next:hover svg line, .fcs-next:hover svg polyline { transform: translateX(6px); }
.fcs-prev:hover svg line, .fcs-prev:hover svg polyline { transform: translateX(-6px); }
.fcs-arrow:disabled { opacity: .3; cursor: default; }
.fcs-arrow:disabled svg line, .fcs-arrow:disabled svg polyline { transform: none; }
.fcs-strip { margin-top: 36px; overflow-x: hidden; }
.fcs-track { display: flex; gap: 44px; width: max-content; padding: 34px var(--gutter) 0; }
.fcs-card { position: relative; width: 440px; flex: 0 0 auto; text-decoration: none; color: inherit; display: block; }
.fcs-frame { position: relative; display: block; width: 100%; height: 430px; overflow: hidden; }
.fcs-frame img,
.fcs-frame video { width: 100%; height: 100%; object-fit: cover; transition: transform .8s; }
.fcs-card:hover .fcs-frame img,
.fcs-card:hover .fcs-frame video { transform: scale(1.05); }
.fcs-num { position: absolute; top: -34px; left: -14px; z-index: 2; font-family: var(--font-italic); font-size: 120px; line-height: 1; color: var(--cream-text); pointer-events: none; text-shadow: 0 2px 30px rgba(19,19,19,.55); }
.fcs-meta { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-top: 20px; border-top: 1px solid rgba(245,245,245,.22); padding-top: 16px; }
.fcs-name { font-family: var(--font-serif); font-size: 27px; }
.fcs-metric { font-family: var(--font-italic); font-size: 27px; color: rgba(245,245,245,.9); white-space: nowrap; }
.fcs-what { display: block; margin-top: 6px; font-family: var(--font-mont); font-size: 11px; letter-spacing: .2em; text-transform: uppercase; color: rgba(245,245,245,.5); }
.fcs-cap { display: flex; flex-direction: column; justify-content: center; align-items: flex-start; width: 400px; height: 430px; margin-top: 34px; border: 1px solid rgba(245,245,245,.25); padding: 44px; flex: 0 0 auto; }
.fcs-cap p { font-family: var(--font-serif); font-size: 34px; line-height: 1.2; margin: 0; }
.fcs-cap .btn { margin-top: 28px; }
.fcs-progress { width: 1200px; margin: 36px auto 0; height: 1px; background: rgba(245,245,245,.18); position: relative; }
.fcs-bar { position: absolute; left: 0; top: -1px; height: 3px; width: 12%; background: var(--accent); transition: width .45s ease; }
/* blog journal drawers (variant 04, 2026-07-15): one-open hover accordion,
   height is constant because exactly one drawer is open at all times */
.sec-faq { --h: 950px; background: #F7F7F7; }
.dw-flow { inset: 0; padding: 74px 60px 0; }
.dw-head { text-align: center; margin-bottom: 44px; }
.dw-kicker { font-family: var(--font-italic); font-size: 30px; margin: 0 0 6px; color: var(--accent); }
.dw-title { font-family: var(--font-serif); font-size: 62px; line-height: 1.02; margin: 0; text-transform: uppercase; letter-spacing: .02em; }
.dw-item {
  display: block; text-decoration: none; color: inherit; cursor: pointer;
  border-top: 1px solid rgba(22,22,22,.35); overflow: hidden;
  height: 88px; transition: height .6s cubic-bezier(.4,0,.2,1);
}
.dw-item:last-of-type { border-bottom: 1px solid rgba(22,22,22,.35); }
.dw-item.is-open { height: 268px; }
.dw-bar {
  display: grid; grid-template-columns: 92px 1fr 210px 40px; align-items: center;
  height: 88px; padding: 0 8px;
}
.dw-no { font-family: var(--font-mont); font-size: 12px; letter-spacing: .18em; }
.dw-name { font-family: var(--font-serif); font-size: 31px; line-height: 1.1; transition: color .45s ease; }
.dw-item.is-open .dw-name { font-family: var(--font-italic); color: var(--accent); }
.dw-cat { font-family: var(--font-mont); font-size: 11px; letter-spacing: .22em; text-transform: uppercase; text-align: right; opacity: .75; }
.dw-plus { position: relative; width: 16px; height: 16px; justify-self: end; transition: transform .6s cubic-bezier(.4,0,.2,1); }
.dw-plus::before, .dw-plus::after { content: ''; position: absolute; background: var(--ink); }
.dw-plus::before { left: 0; right: 0; top: 7px; height: 1px; }
.dw-plus::after { top: 0; bottom: 0; left: 7px; width: 1px; }
.dw-item.is-open .dw-plus { transform: rotate(45deg); }
.dw-body {
  display: grid; grid-template-columns: 330px 1fr auto; column-gap: 44px; align-items: center;
  padding: 0 8px 32px; opacity: 0; transform: translateY(12px);
  transition: opacity .55s ease .12s, transform .55s ease .12s;
}
.dw-item.is-open .dw-body { opacity: 1; transform: none; }
.dw-body img,
.dw-body video { width: 330px; height: 148px; object-fit: cover; display: block; }
.dw-x { display: block; font-size: 15px; line-height: 1.7; margin: 0; max-width: 480px; }
.dw-read { font-family: var(--font-mont); font-size: 12px; letter-spacing: .2em; text-transform: uppercase; border-bottom: 1px solid var(--ink); padding-bottom: 4px; white-space: nowrap; }
.dw-foot { display: flex; justify-content: center; padding-top: 46px; }
/* used by the mobile FAQ accordion, where the body toggles display and so
   cannot transition (see the max-width:900px block) */
@keyframes dw-open { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
/* event types: hover-expanding accordion (variant 03, 2026-07-15) */
.sec-event-types { --h: 880px; background: #1F1F1F; }
.pda-head { left: 0; top: 62px; width: 1200px; display: flex; align-items: baseline; justify-content: space-between; gap: 40px; }
.pda-title { font-family: var(--font-serif); font-size: 52px; line-height: 1.05; margin: 0; }
.pda-plats { display: flex; gap: 24px; font-size: 15px; align-items: baseline; }
.pda-plats span { opacity: .55; }
.pda-plats a { color: inherit; text-decoration: none; border-bottom: 1px solid rgba(245,245,245,.4); padding-bottom: 3px; transition: border-color .3s; }
.pda-plats a:hover { border-color: var(--cream-text); }
.pda-panels { left: 0; top: 168px; width: 1200px; height: 540px; display: flex; gap: 14px; }
.pda-panel {
  position: relative; flex: 1; overflow: hidden; text-decoration: none; color: var(--cream-text);
  transition: flex .65s cubic-bezier(.6,0,.25,1); cursor: pointer;
}
.pda-panel img,
.pda-panel video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  filter: grayscale(.85) brightness(.62); transition: filter .65s ease, transform .65s ease;
}
.pda-panel:hover { flex: 2.4; }
.pda-panel:hover img,
.pda-panel:hover video { filter: grayscale(0) brightness(.85); transform: scale(1.03); }
.pda-panel::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, rgba(19,19,19,.85), rgba(19,19,19,0) 55%); }
.pda-no { position: absolute; top: 22px; left: 24px; z-index: 2; font-family: var(--font-italic); font-size: 22px; opacity: .9; }
.pda-spine {
  position: absolute; bottom: 26px; left: 24px; z-index: 2;
  writing-mode: vertical-rl; transform: rotate(180deg);
  font-family: var(--font-serif); font-size: 26px; line-height: 1.15; white-space: nowrap;
  transition: opacity .4s ease;
}
.pda-card {
  position: absolute; left: 24px; right: 24px; bottom: 24px; z-index: 2;
  opacity: 0; transform: translateY(14px); transition: opacity .5s ease .15s, transform .5s ease .15s;
}
.pda-panel:hover .pda-spine { opacity: 0; }
.pda-panel:hover .pda-card { opacity: 1; transform: none; }
.pda-name { display: block; font-family: var(--font-serif); font-size: 30px; line-height: 1.15; margin: 0 0 8px; }
.pda-meta { display: block; font-family: var(--font-mont); font-size: 11px; letter-spacing: .2em; text-transform: uppercase; opacity: .75; margin: 0 0 14px; }
.pda-listen {
  display: inline-block; border-bottom: 1px solid var(--cream-text); padding-bottom: 3px;
  font-family: var(--font-mont); font-size: 12px; letter-spacing: .18em; text-transform: uppercase;
}
.pda-under { left: 0; top: 744px; width: 1200px; display: flex; align-items: center; justify-content: space-between; gap: 40px; }
.pda-blurb { max-width: 560px; font-size: 15px; line-height: 1.65; opacity: .75; margin: 0; }
/* call to action: ruled plaque (statement round winner 2026-07-15) */
.sec-call-to-action { --h: 900px; background: rgba(19,19,19,1); }
.sec-call-to-action::before { content: ""; position: absolute; inset: 0; background: url("../images/cta-bg.jpg") center / cover no-repeat fixed; opacity: 0.28; }
.plq-frame {
  position: absolute; text-align: center; padding: 88px 70px 76px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.plq-rule { position: absolute; background: rgba(243,243,243,.5); }
.plq-r-top    { left: 0; right: 0; top: 0; height: 1px; transform: scaleX(0); transition: transform 1.1s cubic-bezier(.65,0,.25,1) .2s; }
.plq-r-bottom { left: 0; right: 0; bottom: 0; height: 1px; transform: scaleX(0); transition: transform 1.1s cubic-bezier(.65,0,.25,1) .35s; }
.plq-r-left   { top: 0; bottom: 0; left: 0; width: 1px; transform: scaleY(0); transition: transform 1.1s cubic-bezier(.65,0,.25,1) .5s; }
.plq-r-right  { top: 0; bottom: 0; right: 0; width: 1px; transform: scaleY(0); transition: transform 1.1s cubic-bezier(.65,0,.25,1) .65s; }
.sec-call-to-action.is-in .plq-r-top, .sec-call-to-action.is-in .plq-r-bottom { transform: scaleX(1); }
.sec-call-to-action.is-in .plq-r-left, .sec-call-to-action.is-in .plq-r-right { transform: scaleY(1); }
.plq-tick { position: absolute; width: 14px; height: 14px; opacity: 0; transition: opacity .6s ease 1.5s; }
.plq-tick::before, .plq-tick::after { content: ""; position: absolute; background: var(--cream-text); }
.plq-tick::before { width: 14px; height: 1px; top: 7px; }
.plq-tick::after { width: 1px; height: 14px; left: 7px; }
.plq-tl { left: -7px; top: -7px; } .plq-tr { right: -7px; top: -7px; }
.plq-bl { left: -7px; bottom: -7px; } .plq-br { right: -7px; bottom: -7px; }
.sec-call-to-action.is-in .plq-tick { opacity: 1; }
.plq-kicker {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -50%);
  background: #131313; padding: 6px 26px; margin: 0; white-space: nowrap;
  font-family: var(--font-mont); font-size: 11px; letter-spacing: .34em; text-transform: uppercase;
  opacity: 0; transition: opacity .8s ease 1.2s;
}
.sec-call-to-action.is-in .plq-kicker { opacity: .7; }
.plq-big {
  font-size: 92px; line-height: 1.04; margin: 0; letter-spacing: .015em;
  text-transform: uppercase; color: var(--cream-text);
  opacity: 0; transform: translateY(20px); transition: opacity 1s cubic-bezier(.2,.7,.2,1) .9s, transform 1s cubic-bezier(.2,.7,.2,1) .9s;
}
.plq-big em { text-transform: none; }
.sec-call-to-action.is-in .plq-big { opacity: 1; transform: none; }
.plq-sub {
  font-size: 20px; line-height: 1.5; max-width: 560px; margin: 30px 0 0; color: var(--cream-text);
  opacity: 0; transform: translateY(16px); transition: opacity 1s cubic-bezier(.2,.7,.2,1) 1.2s, transform 1s cubic-bezier(.2,.7,.2,1) 1.2s;
}
.sec-call-to-action.is-in .plq-sub { opacity: .88; transform: none; }
.plq-btn {
  position: absolute; left: 50%; bottom: 0; transform: translate(-50%, 50%);
  background: #131313; padding: 15px 38px; white-space: nowrap;
  opacity: 0; transition: opacity .8s ease 1.6s, background-color .5s, border-color .5s, color .5s;
}
.sec-call-to-action.is-in .plq-btn { opacity: 1; }
.plq-btn:hover { background: var(--cream); }

/* MOBILE (additive layer; see style.css) */
@media (max-width: 900px) {
  /* curtain hero */
  .sec-hero { height: 100svh; min-height: 600px; clip-path: inset(0); }
  .sec-hero .cv { height: 100%; }
  /* mobile can't honor background-attachment:fixed; pin the ::before to the
     viewport instead (clip-path on .sec-hero clips it to the hero box) so the
     photo stays fixed on phones exactly like desktop */
  .sec-hero::before { position: fixed; background-attachment: scroll; }
  .sec-hero .cur-center { position: absolute; left: 22px; right: 22px; top: 0; bottom: 0; }
  .cur-center .cur-logo { width: clamp(150px, 46vw, 230px); margin-bottom: 22px; }
  .cur-title { font-size: clamp(40px, 11.5vw, 54px); margin: 22px 0 24px; }
  .cur-sub { font-size: 16px; max-width: 330px; }
  .cur-corner { display: none; }

  /* expanding panels intro → stacked cards. The description is behind a plus,
     like the FAQ: on a phone the number, the description and the package name
     were all on the card at once and it read as clutter. Desktop is untouched
     and keeps its hover reveal (.xpn-plus is display:none up there). */
  .sec-intro .cv { display: flex; flex-direction: column; padding: 64px 22px; }
  .sec-intro .xpn-title { font-size: 32px; margin: 16px 0 18px; }
  .sec-intro .xpn-lede { margin-bottom: 36px; }
  .sec-intro .xpn-panels { position: static; width: auto; height: auto;
                           flex-direction: column; gap: 14px; }
  /* A 4/3 card shrinks with the viewport while the description does the
     opposite (narrower column, more wrapped lines), so the two collide at the
     bottom of the range: measured at 320px the number and the description
     OVERLAPPED by 5px, and the description sat 4px off the package name even
     on a large phone. min-height decouples the card from the width so the
     copy always has room. The ratio is DROPPED rather than kept alongside it:
     min-height wins at every phone width anyway (4/3 gives 290 even at 430),
     and leaving both in let the box derive its WIDTH from the forced height,
     which put 32px of horizontal scroll on the page. */
  .sec-intro .xpn-panels .xpn-panel { flex: none; aspect-ratio: auto; min-height: 300px; width: 100%; }
  /* clears a package name that has wrapped to two lines, which is what happens
     to "Premium Drop-Off Package" once the phone is narrow */
  .sec-intro .xpn-desc { opacity: 0; transform: translateY(8px); bottom: 92px;
                         font-size: 13px; max-width: none; right: 24px; }
  .sec-intro .xpn-panel.is-open .xpn-desc { opacity: 1; transform: none; }
  /* The scrim rides the PLUS here, not the scroll. It exists to make the
     description readable, so with the description hidden it was darkening the
     client's photos for nothing. Desktop keeps the scroll-in scrim, because
     that is where the hover reveal needs it. */
  .sec-intro .xpn-panel.is-in::before { opacity: 0; }
  .sec-intro .xpn-panel.is-open::before { opacity: .80; }
  /* With the flat scrim gone until the plus is tapped, the package NAME was
     left as white type on a bright photo (worst on 02 and 03, which are lit
     backdrops). This deepens the gradient that already exists for that job
     instead of dimming the whole card: a touch at the very top for the number
     and the plus, nothing across the middle where the faces are, and a real
     band along the bottom where the name sits. */
  .sec-intro .xpn-panel::after {
    background: linear-gradient(180deg, rgba(19,19,19,.30) 0%, rgba(19,19,19,0) 24%,
                rgba(19,19,19,0) 40%, rgba(19,19,19,.90) 100%); }
  /* the tap target: 44px box, plus sign drawn with two 1px bars like .dw-plus */
  .xpn-plus { display: block; position: absolute; z-index: 3; top: 12px; right: 12px;
              width: 44px; height: 44px; transition: transform .45s cubic-bezier(.4,0,.2,1); }
  .xpn-plus::before, .xpn-plus::after { content: ''; position: absolute; background: var(--cream-text); }
  .xpn-plus::before { left: 14px; right: 14px; top: 21px; height: 1px; }
  .xpn-plus::after { top: 14px; bottom: 14px; left: 21px; width: 1px; }
  .sec-intro .xpn-panel.is-open .xpn-plus { transform: rotate(45deg); }
  .sec-intro .xpn-name { font-size: 24px; }
  /* <=375px: "Premium Drop-Off Package" wraps to two lines and the name rises
     into the desc's fixed 56px anchor; lift the desc clear. 390+ keeps the
     kit spacing untouched. */
  @media (max-width: 375px) {
    .sec-intro .xpn-desc { bottom: 92px; }
  }

  /* signature offer */
  .sec-signature-offer .cv { min-height: 88svh; display: flex; padding: 96px 22px 56px; }
  /* pin the photo to the viewport on mobile (see .sec-hero note) */
  .sec-signature-offer { clip-path: inset(0); }
  .hzn-bg { position: fixed; background-attachment: scroll; }
  /* MOBILE ONLY, desktop keeps its gradient (owner). The photo here is one of
     his printed photo-strip TEMPLATES, so it carries its own white script
     lettering, and the desktop gradient is bottom-weighted: .94 at the foot but
     only .18 by 70% up, which is exactly where the phone stacks the title. Two
     sets of white script landed on each other. Flat .80 across the whole layer
     fixes it without touching the photo. */
  .sec-signature-offer .hzn-bg::after { background: rgba(19,19,19,.80); }
  .sec-signature-offer .hzn-base { align-self: flex-end; width: 100%; }
  .hzn-row { flex-direction: column; align-items: flex-start; gap: 26px; }
  .hzn-title { font-size: clamp(44px, 13vw, 58px); }
  .hzn-side { width: auto; padding-bottom: 0; }

  /* statement + belt */
  .vgal { padding: 10vh 0 12vh; }
  .vgal-head { padding: 0 22px 7vh; }
  .vgal-title { font-size: 26px; }
  .vgal-track :is(img, video):nth-child(odd) { height: 42vh; }
  .vgal-track :is(img, video):nth-child(even) { height: 34vh; }

  /* testimonial type takeover */
  .sec-testimonial .cv { display: flex; flex-direction: column; padding: 56px 22px 48px; }
  /* The slides box must fit the TALLEST quote or the overflow paints through
     the byline (this build's second quote wraps to ~310px at 390w against the
     old fixed 250px). Grid-stacking keeps the slides overlapped for the
     crossfade while the box sizes to content at every width. */
  .sec-testimonial .tt-slides { position: relative; width: 100%; height: auto; min-height: 250px; margin-top: 30px; display: grid; }
  .sec-testimonial .tt-slide { position: relative; inset: auto; grid-area: 1 / 1; }
  /* size lives on .tt-line, not the span: its em drives the descender pad */
  .tt-line { font-size: clamp(24px, 7.8vw, 32px); }
  .sec-testimonial .tt-byline { margin-top: 8px; }
  .tt-by-photo { width: 52px; height: 52px; }
  .sec-testimonial .tt-arrows { margin-top: 26px; }
  .sec-testimonial .tt-progress { position: relative; width: 100%; height: 1px; margin-top: 26px; }

  /* about: margin axis → single column */
  .sec-about .cv { display: flex; flex-direction: column; padding: 64px 22px; }
  .sec-about .abx-spine { writing-mode: horizontal-tb; transform: none; order: 1; }
  .sec-about .abx-title { order: 2; font-size: clamp(44px, 13vw, 58px); margin: 12px 0 22px; }
  .sec-about .abx-para { order: 3; }
  .sec-about .abx-sub { order: 4; margin-top: 18px; }
  .sec-about .abx-notes { order: 5; margin-top: 26px; }
  .sec-about .abx-owner { order: 5; position: relative; width: 100%; height: auto;
                          aspect-ratio: 4 / 5; margin-top: 26px; }
  .sec-about .abx-tall { order: 6; position: relative; width: 100%; height: auto;
                         aspect-ratio: 3 / 4; margin: 28px 0 6px; }
  .sec-about .abx-cta { order: 7; }

  /* case studies filmstrip */
  .sec-stats-or-features { height: auto; min-height: 0; padding: 64px 0 56px; }
  .fcs-head { width: auto; flex-direction: column; align-items: flex-start;
              gap: 18px; padding: 0 22px; }
  .fcs-title { font-size: 36px; }
  .fcs-arrows { gap: 40px; padding-bottom: 0; }
  .fcs-strip { overflow-x: auto; }
  .fcs-track { gap: 26px; padding: 30px 22px 0; }
  .fcs-card { width: min(74vw, 300px); }
  .fcs-frame { height: 300px; }
  .fcs-num { font-size: 72px; top: -24px; left: -6px; }
  .fcs-name, .fcs-metric { font-size: 20px; }
  .fcs-cap { width: min(74vw, 300px); height: 300px; margin-top: 30px; padding: 30px; }
  .fcs-cap p { font-size: 24px; }
  .fcs-progress { width: auto; margin: 30px 22px 0; }

  /* journal drawers → all open, single column */
  .sec-faq .cv { padding: 0; }
  .dw-flow { padding: 60px 22px 64px; }
  .dw-kicker { font-size: 24px; }
  .dw-title { font-size: 38px; }
  /* FAQ: a real tap accordion (script.js toggles .is-open under 900px).
     Height stays auto and the BODY is what collapses, because the answers are
     different lengths and a fixed open height either clips the long ones or
     leaves a gap under the short ones. display none/grid cannot be
     transitioned, so the fade is an animation on open, which can never clip
     whatever the answer's height turns out to be. */
  .sec-faq .dw-item, .sec-faq .dw-item.is-open { height: auto; }
  .dw-bar { grid-template-columns: 44px 1fr auto; height: auto; padding: 16px 0 10px; }
  .dw-cat { display: none; }
  .dw-plus { display: block; }   /* the affordance that says the row opens */
  .dw-name { font-size: 21px; }
  .sec-faq .dw-body { display: none; grid-template-columns: 1fr; row-gap: 14px;
                       opacity: 1; transform: none; padding: 0 0 24px; }
  .sec-faq .dw-item.is-open .dw-body { display: grid; animation: dw-open .32s ease both; }
  /* Photos are DESKTOP ONLY (owner, 2026-08-11). On a phone the 170px image sat
     between the question and its answer, so a tapped row pushed its own answer
     toward the fold and the accordion read as if it had done nothing. */
  .dw-body img,
  .dw-body video { display: none; }
  .dw-foot { padding-top: 40px; }

  /* event-type panels → stacked, cards always on */
  .sec-event-types .cv { display: flex; flex-direction: column; padding: 56px 22px 60px; }
  .pda-head { width: auto; flex-direction: column; align-items: flex-start; gap: 14px; }
  .pda-title { font-size: 32px; }
  .pda-panels { width: auto; height: auto; flex-direction: column; gap: 12px; margin-top: 32px; }
  .sec-event-types .pda-panels .pda-panel { flex: none; height: 210px; }
  .pda-panel img,
  .pda-panel video { filter: grayscale(.2) brightness(.75); }
  .pda-spine { display: none; }
  .pda-card { opacity: 1; transform: none; }
  .pda-name { font-size: 22px; }
  .pda-under { width: auto; flex-direction: column; align-items: flex-start;
               gap: 20px; margin-top: 32px; }

  /* ruled plaque (inline geometry on the frame → !important) */
  .sec-call-to-action { clip-path: inset(0); }
  .sec-call-to-action::before { position: fixed; background-attachment: scroll; }
  .sec-call-to-action .cv { display: flex; padding: 90px 22px 100px; }
  .sec-call-to-action .plq-frame { position: relative; left: auto !important; top: auto !important;
      width: 100% !important; height: auto !important; padding: 72px 18px 64px; }
  .plq-big { font-size: clamp(32px, 9.5vw, 42px); }
  .plq-sub { font-size: 16px; margin-top: 22px; }
  .plq-kicker { width: 250px; white-space: normal; line-height: 1.7; }
  .sec-call-to-action .plq-btn { position: absolute; width: auto; }
}
