/* ============================================================
   funnel-themes.css · the two cinematic funnels (4 October 2026)

   Chosen from the ten ad landing variations:
     split   (02)  two photo halves; the half you pick becomes the
                   pipeline's photo side, the form takes the other.
     reveal  (08)  the huge words over a full-bleed photo; the word
                   you pick becomes the pipeline's heading and the
                   photo stays behind every step.

   Live since 5 October 2026: /sales and both pipelines wear "reveal"
   (THEME in pipelines.mjs). A skin over pipeline.css; the questions,
   rules and engine do not change. Loaded only by /sales, /residential
   and /commercial, so @view-transition below opts in exactly the pages
   that share these names. /thank-you is a site page and does not load
   it: the submit is a plain navigation.

   Motion has one source: View Transitions.
     across pages  the ad click (and Back to /sales) morphs the photo
                   (plate-<id>, reveal-ground) and the word (word-<id>)
                   from one document to the next.
     across steps  pipeline.js wraps each step change in
                   startViewTransition and marks html[data-pl-dir];
                   the photo settles in, the copy rises, the form
                   slides the way the visitor is going.
   Reduced motion removes all of it: the swap is instant.
   ============================================================ */

@view-transition { navigation: auto; }

:root { --vt-ease: cubic-bezier(0.32, 0.72, 0, 1); --vt-out: cubic-bezier(0.23, 1, 0.32, 1); }

/* ------------------------------------------------------------
   Named layers
   ------------------------------------------------------------ */
.pl-bar { view-transition-name: pl-bar; }
.t-split [data-pl-steps], .t-reveal [data-pl-steps] { view-transition-name: pl-form; }
.t-split .pl-aside__copy, .t-reveal .pl-aside__copy { view-transition-name: pl-copy; }
/* Named layers paint above the page, so in reveal the photo would cover
   the panel the form sits on. The panel gets a layer of its own, above
   the photo. */
.t-reveal .pl-main { view-transition-name: pl-panel; }

.pl-is-residential .pl-plate img,
.ld-half--residential .ld-ph { view-transition-name: plate-residential; }
.pl-is-commercial .pl-plate img,
.ld-half--commercial .ld-ph { view-transition-name: plate-commercial; }

/* Reveal: the photo is the whole ground, and its tint has to travel with
   it. A photo layer without its scrim paints over the page's tint for
   the length of the transition and flashes bright. So the named layer
   is the frame that holds both. */
.t-reveal .pl-plate img { view-transition-name: none; }
.t-reveal .pl-plate, .ld-ground { view-transition-name: reveal-ground; }

.ld-w--residential .ld-w__t, .pl-is-residential .pl-word { view-transition-name: word-residential; }
.ld-w--commercial .ld-w__t, .pl-is-commercial .pl-word { view-transition-name: word-commercial; }

/* ------------------------------------------------------------
   Motion
   ------------------------------------------------------------ */
::view-transition-group(*) { animation-duration: .7s; animation-timing-function: var(--vt-ease); }
::view-transition-old(root) { animation: vt-fade-out .3s var(--vt-out) both; }
::view-transition-new(root) { animation: vt-fade-in .5s var(--vt-out) .1s both; }

/* A photo is cropped, never stretched, while its frame changes shape. */
::view-transition-old(plate-residential), ::view-transition-new(plate-residential),
::view-transition-old(plate-commercial), ::view-transition-new(plate-commercial),
::view-transition-old(reveal-ground), ::view-transition-new(reveal-ground) {
  width: 100%; height: 100%; object-fit: cover;
}

/* Between steps the photo changes: the old one goes, the new one
   settles in from a slight push, the way a cut lands in a film. Across
   pages it is the same photo, so the default crossfade is invisible
   and only the frame moves. */
html[data-pl-dir]::view-transition-old(plate-residential),
html[data-pl-dir]::view-transition-old(plate-commercial),
html[data-pl-dir]::view-transition-old(reveal-ground) { animation: vt-fade-out .8s var(--vt-ease) both; }
html[data-pl-dir]::view-transition-new(plate-residential),
html[data-pl-dir]::view-transition-new(plate-commercial),
html[data-pl-dir]::view-transition-new(reveal-ground) { animation: vt-settle 1.1s var(--vt-ease) both; }

/* The word not chosen has nowhere to go on the next page: it leaves
   first and fast, so only the chosen word is seen travelling. */
::view-transition-old(word-residential):only-child,
::view-transition-old(word-commercial):only-child,
::view-transition-old(pl-form):only-child,
::view-transition-old(pl-copy):only-child { animation: vt-fade-out .18s var(--vt-out) both; }

/* The copy and the form keep their place; only their contents move. */
::view-transition-group(pl-copy), ::view-transition-group(pl-form) { animation: none; }
::view-transition-old(pl-copy) { animation: vt-lift-out .28s var(--vt-out) both; }
::view-transition-new(pl-copy) { animation: vt-lift-in .6s var(--vt-ease) .12s both; }

/* The old form is gone before the new one is readable, so the two sets
   of questions never sit on top of each other. */
html[data-pl-dir="fwd"]::view-transition-old(pl-form) { animation: vt-out-left .2s var(--vt-out) both; }
html[data-pl-dir="fwd"]::view-transition-new(pl-form) { animation: vt-in-right .62s var(--vt-ease) .16s both; }
html[data-pl-dir="back"]::view-transition-old(pl-form) { animation: vt-out-right .2s var(--vt-out) both; }
html[data-pl-dir="back"]::view-transition-new(pl-form) { animation: vt-in-left .62s var(--vt-ease) .16s both; }
::view-transition-group(pl-panel) { animation-duration: .6s; }

/* Anything arriving with no partner on the old page (the form panel and
   the pipeline's copy after the ad click) comes in after the departures
   have cleared. */
::view-transition-new(pl-copy):only-child,
::view-transition-new(pl-panel):only-child { animation: vt-lift-in .6s var(--vt-ease) .14s both; }

@keyframes vt-fade-out { to { opacity: 0; } }
@keyframes vt-fade-in { from { opacity: 0; } }
@keyframes vt-settle { from { opacity: 0; transform: scale(1.06); } }
@keyframes vt-lift-out { to { opacity: 0; transform: translateY(-10px); } }
@keyframes vt-lift-in { from { opacity: 0; transform: translateY(14px); } }
@keyframes vt-out-left { to { opacity: 0; transform: translateX(-28px); } }
@keyframes vt-out-right { to { opacity: 0; transform: translateX(28px); } }
@keyframes vt-in-right { from { opacity: 0; transform: translateX(40px); } }
@keyframes vt-in-left { from { opacity: 0; transform: translateX(-40px); } }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}

/* ============================================================
   The landing pages
   ============================================================ */
.ld { position: relative; min-height: 100dvh; color: #F4F1EC; overflow: hidden; background: var(--sc-canvas); }
/* The same lockup, size and position as .bar__mark on the home page
   (theme.css): centred in a --bar-h band, with its fluid phone sizes.
   Keep these in step with .bar__mark. */
.ld-brand {
  position: absolute; z-index: 4; top: 0; left: var(--gutter); height: var(--bar-h);
  display: inline-flex; align-items: center; gap: .6rem;
  color: inherit; text-decoration: none;
}
.ld-brand img { width: 4.5rem; height: auto; display: block; }
.ld-brand b { font-family: var(--sc-font-display); font-weight: 700; font-size: 1.625rem; letter-spacing: -.02em; white-space: nowrap; }
.ld-brand:hover { opacity: .82; }
/* On a phone the home bar also drops the wordmark, to make room for its
   quote control. This page has nothing else up there, so it keeps it. */
@media (max-width: 620px) {
  .ld-brand { gap: .5rem; left: 1rem; }
  .ld-brand img { width: clamp(2.1rem, 9vw, 2.75rem); }
  .ld-brand b { font-size: clamp(.875rem, 3.6vw, 1.125rem); }
}
.ld-ph { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.ld-proof { margin: 0; font-size: .8125rem; color: rgba(244, 241, 236, .62); }

/* --- split ------------------------------------------------- */
.ld--split { display: grid; grid-template-columns: 1fr 1fr; }
.ld-half {
  position: relative; isolation: isolate; overflow: hidden;
  min-height: 100dvh; display: flex; align-items: flex-end;
  padding: clamp(1.75rem, 4vw, 4rem);
  color: #F4F1EC; text-decoration: none;
}
.ld-half .ld-ph { z-index: -3; transition: transform 1.4s var(--vt-ease); }
.ld-half::before { content: ""; position: absolute; inset: 0; z-index: -2; background: linear-gradient(180deg, rgba(11, 33, 7, .08) 30%, rgba(11, 33, 7, .86) 100%); }
/* The half not being pointed at dims, so the choice reads before the click. */
.ld-half::after { content: ""; position: absolute; inset: 0; z-index: -1; background: rgba(11, 33, 7, .55); opacity: 0; transition: opacity .6s var(--vt-ease); }
.ld-t { display: flex; flex-direction: column; gap: .75rem; }
.ld-t b {
  display: flex; align-items: center; gap: 1rem;
  font-family: var(--sc-font-display); font-weight: 600;
  font-size: clamp(2.6rem, 1.5rem + 3.6vw, 4.75rem); letter-spacing: -.035em; line-height: 1;
}
.ld-t b svg { width: 1.75rem; height: 1.75rem; transition: transform .4s var(--vt-ease); }
.ld-t > span { font-size: 1.0625rem; line-height: 1.5; color: rgba(244, 241, 236, .84); max-width: 32ch; }
.ld-q {
  position: absolute; z-index: 4; top: 1.6rem; left: 50%; transform: translateX(-50%); margin: 0;
  padding: .6rem 1.1rem; border-radius: 999px; background: var(--sc-canvas);
  font-family: var(--sc-font-display); font-size: .9375rem; font-weight: 600; white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) {
  .ld-half:hover .ld-ph { transform: scale(1.035); }
  .ld-half:hover .ld-t b svg { transform: translateX(6px); }
  .ld--split:has(.ld-half:hover) .ld-half:not(:hover)::after { opacity: 1; }
}
.ld-half:focus-visible { outline: 3px solid var(--sc-accent); outline-offset: -6px; }
@media (max-width: 760px) {
  .ld--split { grid-template-columns: 1fr; }
  .ld-half { min-height: 50dvh; }
  .ld-q { display: none; }
}

/* --- reveal ------------------------------------------------ */
.ld-ground { position: absolute; inset: 0; z-index: 0; }
.ld--reveal .ld-ph { z-index: 0; opacity: 0; transform: scale(1.04); transition: opacity .8s var(--vt-ease), transform 1.6s var(--vt-ease); }
.ld--reveal[data-on="residential"] .ld-bg--residential,
.ld--reveal[data-on="commercial"] .ld-bg--commercial { opacity: 1; transform: none; }
.ld-scrim { position: absolute; inset: 0; z-index: 1; background: linear-gradient(90deg, rgba(11, 33, 7, .88), rgba(11, 33, 7, .35)); }
.ld-c {
  position: relative; z-index: 2; min-height: 100dvh;
  display: flex; flex-direction: column; justify-content: center; gap: .5rem;
  padding: 7rem var(--gutter) 3.5rem;
}
.ld-k { margin: 0 0 .75rem; font-size: .6875rem; letter-spacing: .2em; text-transform: uppercase; font-weight: 600; color: var(--sc-ink-soft); }
.ld-w {
  width: fit-content; display: flex; align-items: center; gap: 1.5rem;
  font-family: var(--sc-font-display); font-weight: 600;
  font-size: clamp(3.4rem, 1rem + 9vw, 10rem); letter-spacing: -.05em; line-height: .95;
  color: rgba(244, 241, 236, .3); text-decoration: none;
  transition: color .45s var(--vt-ease);
}
.ld-cue {
  font-family: var(--sc-font-text); font-size: .9375rem; font-weight: 700; letter-spacing: 0;
  color: var(--sc-accent-ink); background: var(--sc-accent); border-radius: 999px; padding: .6rem 1rem;
  opacity: 0; transform: translateX(-8px);
  transition: opacity .3s var(--vt-out), transform .3s var(--vt-out);
}
.ld--reveal[data-on="residential"] .ld-w--residential,
.ld--reveal[data-on="commercial"] .ld-w--commercial { color: #F4F1EC; }
.ld--reveal[data-on="residential"] .ld-w--residential .ld-cue,
.ld--reveal[data-on="commercial"] .ld-w--commercial .ld-cue { opacity: 1; transform: none; }
.ld-w:focus-visible { outline: 3px solid var(--sc-accent); outline-offset: 6px; border-radius: 6px; }
.ld--reveal .ld-proof { margin-top: 2rem; }
/* A phone cannot hover: both words stay lit and both say Start. */
@media (hover: none) {
  .ld-w { color: #F4F1EC; }
  .ld-cue { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .ld-half .ld-ph, .ld-half::after, .ld-t b svg, .ld--reveal .ld-ph, .ld-w, .ld-cue { transition: none; }
  .ld--reveal .ld-ph { transform: none; }
}

/* ============================================================
   split · the pipeline
   ============================================================ */
.t-split .pl { max-width: none; margin: 0; padding: 0; gap: 0; }
.t-split .pl-aside {
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 1.5rem;
  padding: clamp(1.75rem, 4vw, 4rem);
}
.t-split .pl-plate { display: block; position: absolute; inset: 0; z-index: -2; margin: 0; border-radius: 0; aspect-ratio: auto; }
.t-split .pl-aside::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(11, 33, 7, .1) 25%, rgba(11, 33, 7, .9) 100%);
  transition: background-color .6s var(--vt-ease);
}
.t-split .pl-aside h1 { font-size: clamp(2.2rem, 1.4rem + 2.8vw, 3.75rem); max-width: 14ch; }
.t-split .pl-aside__lede { color: rgba(244, 241, 236, .86); }
.t-split .pl-main { width: 100%; max-width: 46rem; justify-self: center; padding: clamp(2rem, 6vh, 4.5rem) clamp(1.5rem, 4.5vw, 5rem) 6rem; }

/* The details step: the photo darkens and carries the incentives, which
   scroll inside it, so the two halves keep their shape to the end. */
.t-split .pl[data-last] .pl-aside { justify-content: flex-start; }
.t-split .pl[data-last] .pl-aside::before { background-color: rgba(11, 33, 7, .7); }
.t-split .pl[data-last] .pl-incentives {
  margin-top: 0; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 0 .5rem 2.5rem 0;
  /* The list runs under a soft edge rather than a hard cut, which is
     also the cue that it scrolls. */
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 3rem), transparent);
  mask-image: linear-gradient(180deg, #000 calc(100% - 3rem), transparent);
}

@media (min-width: 960px) {
  .t-split .pl, .t-split .pl[data-bare] {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); justify-content: stretch; align-items: start;
    min-height: calc(100dvh - 4.25rem);
  }
  .t-split .pl-aside, .t-split .pl[data-last] .pl-aside { position: sticky; top: 4.25rem; height: calc(100dvh - 4.25rem); }
  /* Commercial was the right-hand half on the landing page; it stays on the right. */
  .t-split.pl-is-commercial .pl-aside { order: 2; }
}
@media (max-width: 959px) {
  .t-split .pl-aside { display: flex; min-height: 44vh; order: 0; }
  /* The band is short, so the copy sits high on the photo, often on sky:
     the tint starts darker to keep the green label legible there. */
  .t-split .pl-aside::before { background-image: linear-gradient(180deg, rgba(11, 33, 7, .5) 0%, rgba(11, 33, 7, .92) 75%); }
  .t-split .pl[data-last] .pl-aside { min-height: 0; }
  .t-split .pl-main { padding: 1.75rem var(--gutter) 7.5rem; }
}

/* ============================================================
   reveal · the pipeline
   ============================================================ */
/* The aside stays in flow here: a sticky box is a stacking context,
   and a full-bleed photo inside one would paint over the form. */
.t-reveal .pl-aside { position: static; }
.t-reveal .pl-plate { display: block; position: fixed; inset: 0; z-index: -2; margin: 0; border-radius: 0; aspect-ratio: auto; }
.t-reveal .pl-plate::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(90deg, rgba(11, 33, 7, .92) 0%, rgba(11, 33, 7, .6) 55%, rgba(11, 33, 7, .74) 100%);
}
/* Sized to its column, not the viewport: "Commercial" is the longer
   word, and at a viewport size it ran under the form panel. 16cqi keeps
   ten letters inside the column at every width. */
.t-reveal .pl-aside__copy { container-type: inline-size; }
.t-reveal .pl-word {
  margin: 0 0 1.25rem; width: fit-content; max-width: 100%;
  font-family: var(--sc-font-display); font-weight: 600;
  font-size: min(16cqi, 8rem); letter-spacing: -.05em; line-height: .95;
  color: #F4F1EC;
}
.t-reveal .pl-aside h1 { font-size: clamp(1.6rem, 1.15rem + 1.5vw, 2.5rem); }
/* No backdrop blur: a View Transition snapshots the panel without its
   backdrop, so a blurred panel would arrive clear and then pop. A denser
   tint gives the same separation and survives the cut. */
.t-reveal .pl-main {
  position: relative; padding: clamp(1.5rem, 3vw, 2.75rem); border-radius: 18px;
  background: rgba(8, 24, 5, .8);
  box-shadow: inset 0 0 0 1px rgba(244, 241, 236, .14), 0 30px 80px rgba(0, 0, 0, .35);
}
.t-reveal .pl-pick__box { background: rgba(4, 14, 3, .55); }
@media (min-width: 960px) {
  .t-reveal .pl { align-items: start; padding-top: clamp(2.5rem, 8vh, 5rem); }
  .t-reveal .pl-aside__copy { position: sticky; top: calc(4.25rem + 2.5rem); }
}
@media (max-width: 720px) {
  .t-reveal .pl-main { padding: 1.25rem; border-radius: 14px; }
}
