/* 07_pitch: experimental pitch build, NOT Questum house style. Questum's web system: 06_production-context/web/ */
/* Ad field (2026-10-01): pitch section 3, "one idea, dozens of versions". Replaces the four-slot gen-scene on the pitch
   page (gen-scene stays for demo.html). Approved in _review/2026-10-01-ad-grid-mocks (proto3.html?layer=cells, round 19).
   A pinned stage: the original ad starts at the episode phone's height and settles as it reaches the centre; then
   one perfect circle grows from its centre and generates the versions around it (Dip's grid-tool layout). Each version
   is empty until the circle reaches it: its pixels are born at the edge, load, take the picture's colours and dissolve
   into the picture. All drawn by ad-field.js from the scroll. */
.af-track { position: relative; height: 320vh; }   /* the original settles before the pin; the pinned part is the circle and the hold */
.af-sticky { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; }
.af-stage { position: absolute; inset: 0; contain: strict; }
.af-tiles { position: absolute; inset: 0; }

/* the original: laid out at its starting (large) size and scaled down, so the picture is never upscaled */
.af-main { position: absolute; z-index: 3; margin: 0; overflow: hidden; background: #111; will-change: transform; transform-origin: 50% 50%; }
.af-main img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* its starting box before ad-field.js places it (the script lays it out the moment the curtain lifts): never the
   picture's own 1080 × 1920 size; the figure's dark ground shows until the picture arrives */
.af-main { --af-start-h: min(calc(100svh - 200px), 1400px); height: var(--af-start-h); width: calc(var(--af-start-h) * 9 / 16);
  left: calc(50% - var(--af-start-h) * 9 / 32); top: calc(50% + 10px - var(--af-start-h) / 2); }
@media (max-width: 639px) { .af-main { --af-start-h: min(calc(100lvh - 24px), calc(100svh - 160px), 608px, calc((100vw - 48px) * 16 / 9)); top: calc(50% - var(--af-start-h) / 2); } }
/* the note under the settled original: placed on whole pixels by ad-field.js, fades and rises once the original settles */
.af-stage .af-note { position: absolute; z-index: 4; left: 0; right: 0; margin: 0 auto; max-width: min(520px, calc(100% - 48px)); text-align: center; text-wrap: balance;
  opacity: 0; will-change: opacity, transform; }

/* phones: the original's approach is a scroll-driven animation on the compositor (Fable, 2026-10-06; a script-written
   scale moved it only on the page's own 60 Hz updates, a frame behind the scroll, so it skipped frames on 120 Hz screens).
   q = 0 as the track's top meets the screen's foot (entry 0%), q = 1 as it meets the screen's top (contain 0%: the track is
   taller than the screen); the kit's settle curve; --af-s-end from ad-field.js, which sets .af-sda where the browser can
   (else it drives the same curve itself). At rest (.is-native) it is laid out unscaled on the same rectangle. */
@media (max-width: 639px) { @supports (animation-timeline: view()) {
  .af-track { view-timeline-name: --af-approach; view-timeline-axis: block; }
  .af-main.af-sda { animation: af-approach linear both; animation-timeline: --af-approach; animation-range: entry 0% contain 0%; animation-timing-function: cubic-bezier(.33, 0, .15, 1); }
  .af-main.af-sda.is-native { animation: none; }
  @keyframes af-approach { from { transform: scale(1); } to { transform: scale(var(--af-s-end, 1)); } }
} }
/* the GPU canvas leaves the compositor while no version is being drawn */
.af-gl.af-gl-idle { visibility: hidden; }

/* a finished real version: the image itself (ad-field.js), over its canvases */
.af-tile .pic { display: none; object-fit: cover; }
.af-tile.done .pic { display: block; }

/* one version: hidden until the circle reaches it; while the circle crosses it, its pixels and picture are composed by
   ad-field.js into one canvas (.live); once finished it is its plain picture (.sharp) */
.af-tile { position: absolute; overflow: hidden; visibility: hidden; contain: strict; }
.af-tile.on, .af-tile.done { visibility: visible; }
.af-tile > * { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.af-tile .sharp, .af-tile.done .live { display: none; }
.af-tile.done .sharp { display: block; }
/* (no hairline round the finished versions: the .hair element was removed, Dip, 2026-10-15) */

@media (max-width: 639px) {
  .af-track { height: 200vh; height: 200lvh; }                          /* phones: a shorter run, in lvh: a pinned screen is scrolled with Safari's toolbar collapsed */
  .af-sticky { height: 100vh; height: 100lvh; }
  .af-stage .af-note { display: none; }                                  /* phones: the grid fills the screen; the note is left out (Dip) */
}
@media (prefers-reduced-motion: reduce) {
  .af-main { animation: none; }
  .af-track { height: auto; }
  .af-stage .af-note { opacity: 1; }
  .af-sticky { position: relative; height: 100vh; height: 100svh; }
}
