/* Act 2 and Act 3 mockups (Oct 8 2026). Act 1 is the Build 2 hero. Acts 2 and 3 are Mike's backdrop films, each under
   a glass pane with a solid margin all round (the film blurred through it) carrying an opaque sheet whose words build
   as you scroll: typography on Act 2 (04 · Good → Great), the contact on Act 3. One fixed scene; a runway of scroll drives it. */
@font-face { font-family: "Archivo"; src: url("../../fonts/archivo-var-latin.woff2") format("woff2"); font-weight: 100 900; font-stretch: 62% 125%; font-display: swap; }
@font-face { font-family: "Instrument Serif"; src: url("../../fonts/instrument-serif-latin.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Instrument Serif"; font-style: italic; src: url("../../fonts/instrument-serif-italic-latin.woff2") format("woff2"); font-display: swap; }
/* Act 2's faces (Mike, Oct 10: "strip the old fonts except the ones used on act three. that will be our only ones we
   keep", "then include the new fonts that pro suggested"): Archivo and Instrument Serif are Act 3's; pro's open faces are
   Instrument Sans, Newsreader and Manrope (research/pro-act2-color-type-oct10.md). ?font= picks the hook's treatment */
@font-face { font-family: "Instrument Sans"; src: url("../../fonts/instrument-sans-latin.woff2") format("woff2"); font-weight: 400 700; font-stretch: 75% 100%; font-display: swap; }
@font-face { font-family: "Instrument Sans"; font-style: italic; src: url("../../fonts/instrument-sans-italic-latin.woff2") format("woff2"); font-weight: 400 700; font-stretch: 75% 100%; font-display: swap; }
@font-face { font-family: "Newsreader"; src: url("../../fonts/newsreader-latin.woff2") format("woff2"); font-weight: 200 800; font-display: swap; }
@font-face { font-family: "Newsreader"; font-style: italic; src: url("../../fonts/newsreader-italic-latin.woff2") format("woff2"); font-weight: 200 800; font-display: swap; }
@font-face { font-family: "Manrope"; src: url("../../fonts/manrope-latin.woff2") format("woff2"); font-weight: 200 800; font-display: swap; }
:root { --ink: #f6f1ea; --dark: #2a211b; --wall: #e6d8c6; --paper: #f6f0e7; --muted: rgba(42, 33, 27, .62); --accent: #7a3826;
        --sans: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif; --serif: "Instrument Serif", "Iowan Old Style", Georgia, serif;
        --vh: 100svh; --margin: clamp(14px, 4.4vw, 76px); --g: 0; }
* { box-sizing: border-box; }
html { background: #1d1813; color: var(--dark); }
body { margin: 0; font-family: var(--sans); -webkit-font-smoothing: antialiased; overflow-x: hidden; }
a { color: inherit; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip { position: fixed; left: 12px; top: -60px; z-index: 60; padding: 10px 14px; background: var(--dark); color: var(--ink); text-decoration: none; }
.skip:focus { top: 12px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* the header, as on the hero page; on a dark backdrop it turns to light ink */
.top { position: fixed; top: 0; right: 0; z-index: 50; display: flex; align-items: baseline; gap: 24px; padding: max(20px, env(safe-area-inset-top)) clamp(16px, 3vw, 40px) 0; transition: color .6s ease; }
.top a, .top button { font: 500 12px/1 var(--sans); letter-spacing: .16em; text-transform: uppercase; color: var(--dark); text-decoration: none; background: none; border: 0; padding: 8px 0; cursor: pointer;
                      text-shadow: 0 0 10px rgba(246, 241, 234, .9), 0 0 3px rgba(246, 241, 234, .7); transition: color .6s ease, text-shadow .6s ease; }
.top button { opacity: .78; } .top button:hover { opacity: 1; } .top button[hidden] { display: none; }
.sig { position: fixed; right: clamp(16px, 3vw, 40px); bottom: max(18px, env(safe-area-inset-bottom)); z-index: 49; text-align: right; color: var(--dark); line-height: 1; pointer-events: none;
       text-shadow: 0 0 10px rgba(246, 241, 234, .9), 0 0 3px rgba(246, 241, 234, .7); transition: color .6s ease, text-shadow .6s ease; }
.sig span { display: block; font: 500 9.5px/1 var(--sans); letter-spacing: .34em; margin: 0 -.34em 6px 0; }
.sig b { display: block; font: 800 21px/1 var(--sans); letter-spacing: .06em; }
html[data-tone="dark"] .top a, html[data-tone="dark"] .top button, html[data-tone="dark"] .sig { color: #f4ede2; text-shadow: 0 0 12px rgba(0, 0, 0, .55); }
@media (max-width: 1080px) {
  .top { left: 0; }
  .sig { position: static; margin-right: auto; display: flex; align-items: baseline; gap: .6em; padding: 8px 0; text-align: left; }
  .sig span { display: inline; margin: 0; font-size: 9.5px; letter-spacing: .3em; }
  .sig b { display: inline; font-size: 14px; }
}

/* the scene: fixed for the whole runway; the page's own height is only the runway */
#pin { position: relative; }
.scene { position: fixed; inset: 0; height: max(var(--vh), 100lvh); overflow: hidden; z-index: 1; background: var(--wall); }
/* (hardening, Oct 10) the scroll is only a runway, and the walls change its length as the story plays, so it has no scrollbar
   (a thumb that jumps and shrinks is a tell); the scene covers the largest phone viewport, so a toolbar collapsing leaves no gap */
html { scrollbar-width: none; overflow-anchor: none; }
html::-webkit-scrollbar { display: none; }
.layer { position: absolute; inset: 0; overflow: hidden; }
.backdrop { z-index: 1; }
.backdrop3 { z-index: 0; }   /* Act 3's film waits under Act 2's; the Act 2 to 3 transition hides Act 2's when it is done */
.hero { z-index: 2; }
.layer img, .layer video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; display: block; }
/* the hero's phone rule, exactly as on the hero page: full width, its own 9:16, centred, wall above and below */
@media (orientation: portrait) { .hero .media img, .hero .media video { inset: 50% 0 auto 0; height: auto; aspect-ratio: 9 / 16; transform: translateY(-50%); } }
.media { position: absolute; inset: 0; overflow: hidden; background: var(--wall); }
.media video { opacity: 0; transition: opacity .25s ease; }
.media video.ready { opacity: 1; }
.backdrop video { opacity: 0; transition: opacity .3s ease; }
.backdrop video.ready { opacity: 1; }
.fx { position: absolute; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; z-index: 3; opacity: 0; }
.fx.on { opacity: 1; }
.fx3 { z-index: 4; }
html.view3 .fx3 { z-index: 11; }   /* (pass 41) while the Act 3 transition acts on the story's final view (pro's band), its canvas is over the spread */

/* ---- the glass: a real pane, not a UI card. It never reaches the screen's edge. ---- */
.glass { position: absolute; z-index: 10; inset: var(--margin); border-radius: 10px; overflow: hidden;
         opacity: var(--g); transform: translate3d(0, calc((1 - var(--g)) * 3.5vh - var(--lift, 0px)), 0) scale(calc(.985 + .015 * var(--g)));
         -webkit-backdrop-filter: blur(calc(var(--g) * 22px)) saturate(1.18); backdrop-filter: blur(calc(var(--g) * 22px)) saturate(1.18);
         background: linear-gradient(160deg, rgba(255, 255, 255, .085), rgba(255, 255, 255, .02) 38%, rgba(255, 255, 255, 0) 62%, rgba(255, 255, 255, .05));
         box-shadow: inset 0 1px 0 rgba(255, 255, 255, .55), inset 0 0 0 1px rgba(255, 255, 255, .16), inset 0 -1px 0 rgba(0, 0, 0, .12), 0 40px 90px rgba(10, 6, 2, .28);
         pointer-events: none; }
.glass.live { pointer-events: auto; }
html[data-tone="dark"] .glass { background: linear-gradient(160deg, rgba(255, 255, 255, .07), rgba(10, 14, 20, .1) 38%, rgba(10, 14, 20, .14) 62%, rgba(255, 255, 255, .04)); }
/* the pane's thickness: a faint bright edge on one side, a darker one on the other */
.glass::before { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
                 background: linear-gradient(90deg, rgba(255, 255, 255, .22), transparent 1.2%, transparent 98.6%, rgba(0, 0, 0, .08)),
                             linear-gradient(180deg, rgba(255, 255, 255, .18), transparent 1.6%, transparent 98.4%, rgba(0, 0, 0, .1)); }
/* a long, soft reflection across the pane that drifts with scroll (set by the script) */
.glass::after { content: ""; position: absolute; inset: -40%; pointer-events: none; opacity: .5;
                background: linear-gradient(115deg, transparent 42%, rgba(255, 255, 255, .09) 47%, rgba(255, 255, 255, .02) 52%, transparent 58%);
                transform: translate3d(var(--sheen, 0%), 0, 0); }
.grain { position: absolute; inset: 0; pointer-events: none; opacity: .5; mix-blend-mode: soft-light; background-image: var(--grain, none); }

/* the sheet: opaque paper on the glass; it scrolls inside the glass on a short screen */
.glass .well { position: absolute; inset: 0; overflow-y: auto; overscroll-behavior: contain; display: grid; place-items: center; padding: clamp(14px, 4vw, 56px); scrollbar-width: none; }
.glass .well::-webkit-scrollbar { display: none; }
.sheet { position: relative; width: min(600px, 100%); color: var(--dark); border-radius: 4px; padding: clamp(26px, 4.6vw, 52px) clamp(22px, 4.6vw, 54px) clamp(24px, 4vw, 44px);
         background: var(--paper); box-shadow: 0 1px 0 rgba(255, 255, 255, .7) inset, 0 24px 60px rgba(20, 12, 4, .22), 0 2px 6px rgba(20, 12, 4, .12); }
.sheet .paper { position: absolute; inset: 0; border-radius: inherit; pointer-events: none; background-image: var(--grain, none); opacity: .32; mix-blend-mode: soft-light; }
/* the paper is alive: a slow fold of light moves over it, never stopping */
.sheet .light { position: absolute; inset: 0; border-radius: inherit; pointer-events: none; overflow: hidden; }
.sheet .light::before { content: ""; position: absolute; inset: -60%; background: radial-gradient(closest-side, rgba(255, 250, 238, .55), rgba(255, 250, 238, 0)); width: 70%; height: 70%;
                        animation: drift 17s ease-in-out infinite alternate; mix-blend-mode: soft-light; }
@keyframes drift { 0% { transform: translate(-10%, 0%); } 50% { transform: translate(60%, 30%); } 100% { transform: translate(120%, 70%); } }
@media (prefers-reduced-motion: reduce) { .sheet .light::before { animation: none; } }
.sheet > *:not(.paper):not(.light):not(.sr) { position: relative; }
.kicker { font: 500 10.5px/1 var(--sans); letter-spacing: .3em; text-transform: uppercase; color: var(--muted); margin: 0 0 18px; }
.sheet h2 { margin: 0 0 12px; font: 400 clamp(40px, 5.6vw, 64px)/.98 var(--serif); letter-spacing: -.012em; }
.sheet h2 em { font-style: italic; color: var(--accent); }
.sheet .lede { margin: 0 0 30px; font-size: 15.5px; line-height: 1.55; color: var(--muted); max-width: 38ch; }
.fields { display: grid; grid-template-columns: 1fr 1fr; gap: 22px 24px; }
.field { display: grid; gap: 8px; }
.field.full { grid-column: 1 / -1; }
.field > span { font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase; color: var(--muted); }
.field input, .field textarea { font: 16px/1.45 var(--sans); color: var(--dark); background: transparent; border: 0; border-radius: 0; padding: 6px 0 9px; outline: none; caret-color: var(--accent); width: 100%; }
.field textarea { resize: none; min-height: 84px; }
.field .rule { height: 1px; background: rgba(42, 33, 27, .42); transform-origin: 0 50%; transition: background-color .3s ease; }
.field:focus-within .rule { background: var(--dark); }
.field:focus-within > span { color: var(--dark); }
.note { margin: 20px 0 0; font-size: 12.5px; color: var(--muted); }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px; margin-top: 24px; }
.send { font: 600 12.5px/1 var(--sans); letter-spacing: .16em; text-transform: uppercase; color: var(--ink); background: var(--dark); border: 0; border-radius: 999px; padding: 16px 26px; cursor: pointer; transition: transform .25s ease, background-color .25s ease; }
.send:hover { transform: translateY(-1px); background: #3a2d24; }
.actions small { font-size: 12px; color: var(--muted); flex: 1 1 220px; }
.direct { margin: 22px 0 0; font-size: 13.5px; color: var(--muted); }
.after { margin: 0; font-size: 14px; line-height: 1.5; color: var(--muted); }
.after:not(:empty) { margin-top: 16px; }
@media (max-width: 560px) { .fields { grid-template-columns: 1fr; } .sheet h2 { font-size: 42px; } }

/* ---- the three ways the words arrive (one per mockup; ?text= swaps) ---- */
/* every built piece carries --e (0..1), written by the script as you scroll */
[data-b] { --e: 1; }
/* outline: the words are etched in the glass as outlines, then fill solid; the paper arrives under them */
html[data-text="outline"] .sheet { background: rgba(246, 240, 231, calc(var(--paperE, 1))); box-shadow: 0 1px 0 rgba(255, 255, 255, calc(.7 * var(--paperE, 1))) inset, 0 24px 60px rgba(20, 12, 4, calc(.22 * var(--paperE, 1))), 0 2px 6px rgba(20, 12, 4, calc(.12 * var(--paperE, 1))); }
html[data-text="outline"] .sheet .paper { opacity: calc(.32 * var(--paperE, 1)); }
html[data-text="outline"] .sheet .light { opacity: var(--paperE, 1); }
html[data-text="outline"] [data-b] { color: rgba(42, 33, 27, var(--e)); -webkit-text-stroke: calc((1 - var(--e)) * 1px) rgba(255, 252, 245, calc((.95 - .95 * var(--e)) * var(--etch, 1))); }
html[data-text="outline"] h2 em[data-b] { color: rgba(122, 56, 38, var(--e)); }
html[data-text="outline"] .send[data-b] { background: rgba(42, 33, 27, var(--e)); color: rgba(246, 241, 234, var(--e)); box-shadow: 0 0 0 1px rgba(255, 252, 245, calc((.9 - .9 * var(--e)) * var(--etch, 1))) inset; }
html[data-text="outline"] .rule[data-b] { background: rgba(255, 252, 245, calc(.9 - .5 * var(--e))); transform: scaleX(var(--e)); }
html[data-text="outline"] .field:focus-within .rule[data-b] { background: var(--dark); }
/* lines: each line rises out of its own slot, editorial, one after another */
html[data-text="lines"] [data-b]:not(.rule) { clip-path: inset(0 0 calc((1 - var(--e)) * 100%) 0); transform: translate3d(0, calc((1 - var(--e)) * .7em), 0); opacity: calc(.2 + .8 * var(--e)); }
html[data-text="lines"] .rule[data-b] { transform: scaleX(var(--e)); }
html[data-text="lines"] .sheet { clip-path: inset(calc((1 - var(--paperE, 1)) * 100%) 0 0 0 round 4px); }
/* blur: the words condense out of blur, the way breath clears from glass */
html[data-text="blur"] [data-b]:not(.rule) { filter: blur(calc((1 - var(--e)) * 9px)); opacity: var(--e); letter-spacing: calc((1 - var(--e)) * .06em); }
html[data-text="blur"] .rule[data-b] { transform: scaleX(var(--e)); opacity: var(--e); }
html[data-text="blur"] .sheet { opacity: var(--paperE, 1); filter: blur(calc((1 - var(--paperE, 1)) * 14px)); }

.stamp { position: fixed; left: 10px; bottom: 8px; z-index: 55; font: 10px/1 ui-monospace, Menlo, monospace; color: rgba(42, 33, 27, .6); pointer-events: none; transition: opacity .3s ease; }
html[data-tone="dark"] .stamp { color: rgba(244, 237, 226, .6); }
.switch { position: fixed; right: 10px; top: 50%; z-index: 56; display: none; }
.sheet h2 [data-b] { display: inline-block; }
.rule { display: block; }

/* the sheet's layout: an editorial spread on wide screens (headline left, form right), one column below that */
.glass .well { padding: clamp(12px, 3.2vh, 44px) clamp(12px, 3vw, 44px); }
.sheet { padding: clamp(24px, 4.2vh, 46px) clamp(22px, 4vw, 52px) clamp(22px, 3.6vh, 40px); }
.sheet h2 { grid-area: head; } .sheet .lede { grid-area: lede; } .sheet form { grid-area: form; } .sheet .direct { grid-area: direct; }
@media (min-width: 1100px) {
  .sheet { width: min(980px, 100%); display: grid; grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr); column-gap: clamp(40px, 4.5vw, 72px);
           grid-template-areas: "head form" "lede form" "direct form"; grid-template-rows: auto auto 1fr; align-items: start; }
  .sheet h2 { font-size: clamp(48px, 4.6vw, 70px); margin-top: -4px; }
  .sheet .lede { margin-bottom: 0; }
  .sheet .direct { align-self: end; margin-top: 28px; }
}
@media (max-height: 820px) and (min-width: 1100px) { .field textarea { min-height: 64px; } .fields { gap: 18px 22px; } .actions { margin-top: 18px; } }
/* narrow screens: the glass clears the header row and keeps a clear margin on every side; glass shows round the sheet */
@media (max-width: 1080px) {
  .glass { inset: calc(max(20px, env(safe-area-inset-top)) + 46px) 18px max(18px, env(safe-area-inset-bottom)) 18px; }
  .glass .well { padding: 16px; place-items: start center; }
}

/* ---- the Transitions menu: two line selectors that spill from the header's top right ---- */
.top button.open { opacity: 1; }
.tmenu { position: fixed; z-index: 70; top: calc(max(20px, env(safe-area-inset-top)) + 34px); right: clamp(16px, 3vw, 40px);
         width: max-content; max-width: calc(100vw - 32px); padding: 16px 18px 14px; border-radius: 8px;
         background: rgba(246, 240, 231, .97); -webkit-backdrop-filter: blur(18px) saturate(1.1); backdrop-filter: blur(18px) saturate(1.1);
         box-shadow: 0 1px 0 rgba(255, 255, 255, .6) inset, 0 0 0 1px rgba(42, 33, 27, .08), 0 18px 48px rgba(20, 12, 4, .22);
         color: var(--dark); transform-origin: 100% 0; animation: tmenu .22s cubic-bezier(.2, .7, .2, 1); }
.tmenu[hidden] { display: none; }
@keyframes tmenu { from { opacity: 0; transform: translate3d(0, -6px, 0) scale(.98); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .tmenu { animation: none; } }
.tline { display: grid; grid-template-columns: 9.8em auto; align-items: baseline; gap: 4px 14px; padding: 9px 0; }
.tline + .tline { border-top: 1px solid rgba(42, 33, 27, .12); }
.tline.act { border-top-color: rgba(42, 33, 27, .34); margin-top: 6px; padding-top: 15px; }   /* Act 3's pair, set apart from Act 2's */
.tlabel { font: 500 9.5px/1 var(--sans); letter-spacing: .26em; text-transform: uppercase; color: var(--muted); }
.topts { display: flex; flex-wrap: wrap; gap: 4px 16px; }
.topts button { font: 400 13.5px/1.2 var(--sans); color: var(--muted); background: none; border: 0; padding: 4px 0 5px; cursor: pointer;
                box-shadow: inset 0 -1px 0 transparent; transition: color .2s ease, box-shadow .2s ease; }
.topts button:hover { color: var(--dark); }
.topts button.on { color: var(--dark); box-shadow: inset 0 -1px 0 var(--dark); }
@media (max-width: 1080px) {
  .top { gap: 16px; }
  .top a, .top button { font-size: 11px; letter-spacing: .12em; }
  .tmenu { top: calc(max(20px, env(safe-area-inset-top)) + 40px); right: 12px; left: 12px; width: auto; }
  .tline { grid-template-columns: 1fr; }
}

/* ---- the Act 3 glass arrives the way its transition did, once the backdrop has landed (Mike, Oct 8: "for act 3, the
   glass should mirror whatever the transition selected is", "it should happen AFTER the act 3 backdrop arrives so like a
   sequence and not altogether"). The stage sets data-arrive and drives the values below; --etch lets the etched words
   (outline style) wait for the glass, --shadow lets the pane's shadow settle in after it lands. ---- */
.glass[data-arrive] { opacity: 1; transform: none;
  -webkit-backdrop-filter: blur(calc(var(--frost, 1) * 22px)) saturate(calc(1 + .18 * var(--frost, 1)));
          backdrop-filter: blur(calc(var(--frost, 1) * 22px)) saturate(calc(1 + .18 * var(--frost, 1)));
  background: linear-gradient(160deg, rgba(255, 255, 255, calc(.085 * var(--frost, 1))), rgba(255, 255, 255, calc(.02 * var(--frost, 1))) 38%, rgba(255, 255, 255, 0) 62%, rgba(255, 255, 255, calc(.05 * var(--frost, 1))));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, calc(.55 * var(--rim, 1))), inset 0 0 0 1px rgba(255, 255, 255, calc(.16 * var(--rim, 1))),
              inset 0 0 calc(var(--rimglow, 0) * 26px) rgba(255, 246, 232, calc(var(--rimglow, 0) * .32)),
              inset 0 -1px 0 rgba(0, 0, 0, calc(.12 * var(--frost, 1))), 0 40px 90px rgba(10, 6, 2, calc(.28 * var(--shadow, 1))),
              0 0 calc(var(--glow, 0) * 160px) calc(var(--glow, 0) * 30px) rgba(255, 246, 232, calc(var(--glow, 0) * .8)); }
html[data-tone="dark"] .glass[data-arrive] { background: linear-gradient(160deg, rgba(255, 255, 255, calc(.07 * var(--frost, 1))), rgba(10, 14, 20, calc(.1 * var(--frost, 1))) 38%, rgba(10, 14, 20, calc(.14 * var(--frost, 1))) 62%, rgba(255, 255, 255, calc(.04 * var(--frost, 1)))); }
.glass[data-arrive] .grain { opacity: calc(.5 * var(--frost, 1)); }
/* Split, Slide, Sheets in: two halves of the pane, each the whole pane clipped to its half, travelling as the film's did */
.glass.ghost { --shadow: 0; pointer-events: none; }
.glass.ghost.half-l { clip-path: inset(0 50% 0 0 round 10px 0 0 10px); }
.glass.ghost.half-r { clip-path: inset(0 0 0 50% round 0 10px 10px 0); }
.glass.ghost.half-t { clip-path: inset(0 0 50% 0 round 10px 10px 0 0); }
.glass.ghost.half-b { clip-path: inset(50% 0 0 0 round 0 0 10px 10px); }
/* The line: the pane's light as one hairline across its middle, before the pane opens from it */
.glass .gline { position: absolute; left: 0; right: 0; top: 50%; height: 1px; margin-top: -.5px; z-index: 2; pointer-events: none;
                background: rgba(255, 253, 248, .95); transform: scaleX(var(--lx, 0)); opacity: var(--lo, 0);
                /* light with a faint dark edge either side, as a cut edge in glass: it reads on the bright walls as well as at night */
                box-shadow: 0 1px 0 rgba(30, 20, 10, .3), 0 -1px 0 rgba(30, 20, 10, .14), 0 0 14px 1px rgba(255, 246, 232, .45); }
/* Light flash: the pane arrives as warm white light and settles into glass */
.glass .gflash { position: absolute; inset: 0; pointer-events: none; background: #fff6e8; opacity: var(--flash, 0); }

/* ---- liquid glass (Mike, Oct 8: "apple style liquid glass"): the pane is drawn by js/glass.mjs on .glassfx from the
   film under it; the DOM pane keeps its box, its arrival and its sheet, and draws nothing itself. Rounder corners, as
   a slab of glass has. ?glass=frost (and reduced motion, or no WebGL2) keeps V1's frosted pane. ---- */
.glassfx { position: absolute; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; z-index: 9; opacity: 0; }
.glassfx.on { opacity: 1; }
/* the panes' corners, one radius for everything that sits on or matches the glass (Mike, Oct 10: "lets shrink the radii a
   little bit on the main backdrop"; was 24 px, 20 px narrower than 1080) */
:root { --glass-r: 20px; }
@media (max-width: 1080px) { :root { --glass-r: 16px; } }
html[data-glass="liquid"] .glass { border-radius: var(--glass-r); }
html[data-glass="liquid"] .glass, html[data-glass="liquid"] .glass[data-arrive],
html[data-tone="dark"][data-glass="liquid"] .glass, html[data-tone="dark"][data-glass="liquid"] .glass[data-arrive] {
  background: none; -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: none; }
html[data-glass="liquid"] .glass::before, html[data-glass="liquid"] .glass::after, html[data-glass="liquid"] .glass > .grain { display: none; }
/* Light flash still arrives as white light: the overlay and its glow stay in the page */
html[data-glass="liquid"] .glass[data-arrive="flash"], html[data-tone="dark"][data-glass="liquid"] .glass[data-arrive="flash"] { box-shadow: 0 0 calc(var(--glow, 0) * 160px) calc(var(--glow, 0) * 30px) rgba(255, 246, 232, calc(var(--glow, 0) * .8)); }

/* ?perf=1: the frame-time readout */
.perf { position: fixed; left: 10px; top: 76px; z-index: 60; padding: 7px 9px; border-radius: 6px; background: rgba(0, 0, 0, .62); color: #f4ede2;
        font: 10.5px/1.45 ui-monospace, Menlo, monospace; white-space: pre; pointer-events: none; }

/* ---- Act 2 (js/spread.mjs): Mike's copy 04 on one pane of the liquid glass, laid out after his playbook (Oct 8: "run
   this playbook almost exactly"): "Operations + Design" over a hairline and the hook, big, on the left; the two
   paragraphs at one size in the middle with "Let's talk" under them on a hairline (Mike: "lose the opertaions
   branding websites custom tools footer"); "Operations + Design" and "LET'S TALK" in WATT's own Archivo, heavier and
   expanded like the mark (Mike: "operations anddeisgn font isn't great", "the lets talk should also be like maybe archiivo?
   or something heavier"), the paragraphs bigger ("the two paragraphs are too small"). The script places the columns and sizes the hook (--hs). One accent, on "both ways." only.
   ?case=caps|sentence, ?font= (pro's duet unless chosen, Oct 10). ---- */
.defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.spread { position: absolute; inset: 0; z-index: 10; pointer-events: none;
          --sink: #1c1510; --sacc: #8a3a16; --ring: rgba(28, 21, 16, .72);
          --hf: "Instrument Sans", var(--sans); --hw: 450; --hst: 100%; --hlh: 1.02; --hls: -.038em; --hv: normal;
          --cf: var(--sans); --cfam: var(--sans); --cw: 400; --cv: normal; --cls: 0em; --clh: 1.55; --cscale: 1;
          --cs: clamp(17px, calc(.55vw + 11.4px), 22px);
          color: var(--sink); }
.spread-probe { position: absolute; visibility: hidden; pointer-events: none; padding: max(20px, env(safe-area-inset-top)) 0 max(18px, env(safe-area-inset-bottom)); }
html[data-tone="dark"] .spread { --sink: #f3eadb; --sacc: #e2a262; --ring: rgba(243, 234, 219, .82); --hw: 520; --cw: 390; }
/* the hook's colours, per Act 2 backdrop, from pro's colour study (Mike, Oct 10: "and update our hero colors"): ink for the
   hook and copy, an accent for "both ways." (and "Great", Mike, Oct 9) */
html[data-bg="trees"] .spread { --sink: #1c2a22; --sacc: #304a3d; --ring: rgba(28, 42, 34, .72); }
html[data-bg="submerged"] .spread { --sink: #173c40; --sacc: #1f5a5b; --ring: rgba(23, 60, 64, .72); }
html[data-bg="night"] .spread { --sink: #f3eee5; --sacc: #bed2c7; --ring: rgba(243, 238, 229, .82); }

/* a leaf: a pane of the approved glass, placed by the script; liquid glass draws it, V1's frost stands in without WebGL2 */
.leaf { inset: auto; --g: 1; opacity: 1; transform: none; }
.leaf-b, html[data-tone="dark"] .leaf-b { background: none; -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: none; }
.leaf-b::before, .leaf-b::after, .leaf-b > .grain { display: none; }
.page { position: absolute; }
/* "Operations + Design" as pro's study sets it (V4 pass 31; Mike, Oct 11: "let's update the 'operations + design' across
   the board (all your act 2's) to match the way pro has it"): Inter 500 in tracked capitals, 10 px (8 px at 900 px wide
   or less), the "+" eight pixels clear on each side, in the hook's ink */
.eyebrow { position: relative; display: inline-flex; align-items: center; gap: 0; margin: 0 0 calc(var(--hs, 100px) * .42); padding-bottom: .95em;
           font: 500 10px/1.25 "Inter", var(--sans); font-stretch: 100%; font-variation-settings: normal; letter-spacing: .18em; text-transform: uppercase;
           color: var(--sink); }
.eyebrow .sr { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: pre; margin: 0 8px; }
@media (max-width: 900px) { .eyebrow { font-size: 8px; letter-spacing: .14em; } }

.eb { display: inline-block; }
.eb-ops, .eb-des { margin-right: 0; }
.eb-plus { display: none; }
.eb-plus { position: relative; flex: none; width: .66em; height: .66em; }
.eb-plus i { position: absolute; background: currentColor; transform-origin: 50% 50%; }
.eb-plus i:first-child { left: 0; right: 0; top: 50%; height: 1px; margin-top: -.5px; transform: scaleX(0); }
.eb-plus i:last-child { top: 0; bottom: 0; left: 50%; width: 1px; margin-left: -.5px; transform: scaleY(0); }
.eb-rule { position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: currentColor; opacity: .38; transform-origin: var(--po, 50%) 50%; transform: scaleX(0); }
/* the hook: three big lines; line three is italic, and "both ways." keeps the accent */
.hook { position: relative; font: var(--hw) var(--hs, 100px)/var(--hlh) var(--hf); font-stretch: var(--hst, 100%); font-variation-settings: var(--hv); letter-spacing: var(--hls); }

.hl { display: block; width: max-content; white-space: nowrap; }
.hl1 { margin-left: -.025em; } .hl2 { margin-left: -.012em; } .hl3 { margin-left: -.03em; }
 
.hook em { font-style: italic; }
.hook .acc { color: var(--sacc); }
.sw { position: relative; display: inline-block; }
/* no backface-visibility: hidden here any more: it put each swapping word on a layer of its own (nothing turns in 3D now),
   drawn small and stretched when the hook is scaled up, so the big hook read blurry (Mike, Oct 10) */
.sw .old, .sw .new { display: inline-block; transform-origin: 50% 84%; }
.hl3 .sw .old { font-size: calc(1em * var(--wfit, 1)); }   /* "without saying." at the width of the other lines (stage.mjs fitEnding) */
.sw .new { position: absolute; left: 0; top: 0; white-space: nowrap; visibility: hidden; }
.k { display: inline-block; }
.hi, .bw { display: inline-block; }
.hl { position: relative; }
.bl { display: inline-block; width: 0; height: 0; vertical-align: baseline; }
/* the copy: both paragraphs one face, one size, one leading, a blank line between */
.copy { font: var(--cw) calc(var(--cs) * var(--cscale))/var(--clh) var(--cf); font-variation-settings: var(--cv); letter-spacing: var(--cls); hanging-punctuation: first last; }
html[data-spread="stack"] .spread { --cs: 17px; --clh: 1.5; }
html[data-spread] .spread[data-fit] { --clh: 1.45; }             /* the phone's fitting steps (spread.mjs measure) */
html[data-spread] .spread[data-fit="3"] { --cs: 15px; }
html[data-spread] .spread[data-fit="4"] { --cs: 14px; }
.cp { margin: 0; text-wrap: pretty; }
.cp + .cp { margin-top: calc(1em * var(--clh)); }
[data-fit="2"] .cp + .cp, [data-fit="3"] .cp + .cp, [data-fit="4"] .cp + .cp { margin-top: calc(.5em * var(--clh)); }
.copy .wd { display: inline-block; transform-origin: 50% 60%; }
/* the copy's outline layer: the same paragraphs drawn only as a one-pixel ring round each letter's own shape (index.html
   #ring), so the overlapping contours inside variable fonts never show as seams; each word's outline shows before its ink */
.copy { position: relative; }
/* the copy's setting (?copy=; Mike, Oct 9: "maybe make the paragraph text all uppercase? and more editorial font? right
   now it is font is boring"): WATT's grotesque in tracked capitals, the hook's serif in tracked capitals, or as before */
/* lowercase (Mike, Oct 9: "make the copy lowercase also"): Archivo at its normal width, set plainly */
html[data-copy="sans"] :is(.copy, .sb-t) { font-family: var(--cfam, var(--sans)); font-weight: 400; font-stretch: 100%; font-variation-settings: normal;
                               text-transform: none; letter-spacing: 0; font-size: calc(var(--cs) * .9); line-height: 1.5; }
/* the copy at its normal weight again (Mike, Oct 10: "let's change the text back from 'bold' for the copy") */
html[data-copy="caps"] :is(.copy, .sb-t) { font-family: var(--cfam, var(--sans)); font-weight: 500; font-stretch: 112%; font-variation-settings: normal;
                               text-transform: uppercase; letter-spacing: .075em; font-size: calc(var(--cs) * .72); line-height: 1.85; }
.copy-ol { position: absolute; inset: 0; pointer-events: none; color: #000; filter: url(#ring); display: none; }
.copy-ol .wd { opacity: 0; }
.ring-ink { flood-color: var(--ring); }
/* ---- the plate (?motion=plate, js/plate.mjs; Mike, Oct 9, after OFFFORM): the hook on a backing plate in the middle
   of the glass, opened from a line; the copy rises from the bottom a sentence at a time, splits round the plate and joins
   again above it. ---- */

/* the plate's colour is taken from the Act 2 film it sits on, chosen with the backdrop (Mike, Oct 9: "make sure the plate
   is color appropriate for each background. have it automatically selected"): the olive of the trees' shade, the deep
   teal of the pool under the water line, and at night WATT's own cream on the wall, with the type in ink */
.spread { --plate: #1e2116; --plate-ink: #f3eadb; --plate-acc: #e2a262; }
html[data-bg="submerged"] .spread { --plate: #0f2e30; --plate-acc: #e9b872; }
html[data-bg="night"] .spread { --plate: #efe6d6; --plate-ink: #1c1510; --plate-acc: #a4561f; }

/* square corners and no inner border (Mike, Oct 9: "remove the rounded edges", "and remove the inside border") */

/* the raised card (?tile=, plate.mjs; Mike, Oct 9: "what if we tried a raised tile kinda like this on top the glass?",
   "use the same rounded radii as our exterior glass radii", then on the first, thick version: "nah lol that looks really
   bad", "i think a card that looks raised", "not the thick tile", "so maybe something that it's a bit better designed").
   No edge showing: the card is raised by its light and its shadow alone. Its face catches the glass's upper-left key (a
   hairline of light along the top, a little more light toward the top left, a crisp hairline edge), and as it lifts a
   soft, layered shadow, warm like the film's light and falling a little down and to the right, gathers under it on the
   frost. Corners: the glass's own radius (--gr, as .glass) */

.spread { --tile: #f4f0e8; }
html[data-bg="night"] .spread { --tile: #fbf8f2; }

/* the card on the plate: light, like the reference, the hook on it in ink; the plate round it takes the same curve */

/* the sheet (?tile=sheet, the default since Oct 10; Mike, on the glass card: "this glass in plate needs to change", "it looks
   like shit", "maybe update it for a color matched neutral toned sheet ?"): the card raised as before, in a neutral tone
   matched to the Act 2 film (pro's tones: warm mineral on the trees wall, bone on Submerged, smoked teal at night), the
   hook on it in that film's ink and accent, so nothing changes colour when the sheet shuts at the finale */
.spread { --sheet: #e8dbc5; }
html[data-bg="submerged"] .spread { --sheet: #f3eee5; }   /* pro's bone (Mike, Oct 10: "white on that water one is kinda harsh lets go with the 'bone' color pro suggested", "i meant submerged") */
html[data-bg="night"] .spread { --sheet: #14272d; }

/* the card as a second layer of glass (?tile=glass): the liquid glass draws it; the DOM card only stands in on V1's
   frosted pane, which cannot draw a layer; the line it opens from is drawn in the glass's ink */

   /* "Great" in the accent too (Mike, Oct 9: "make 'great' in the hook be the same color as 'both ways'") */

.stream { position: absolute; inset: 0; pointer-events: none; }
/* the copy larger on the desktop (Mike, Oct 9: "make the copy larger font size on the desktop", "so it's not so gd small");
   on a phone it runs in the narrow column either side of the plate */
html[data-spread="spread"] .stream { --cs: clamp(17px, 1.3vw, 23px); }   /* Mike, after it went bigger: "it's way the fuck too big now" */
html[data-spread="stack"] .stream { --cs: 15.5px; }
.sb { position: absolute; left: 0; top: 0; visibility: hidden; }
.sb-t { margin: 0; text-align: center; color: var(--sink); font: var(--cw) calc(var(--cs) * var(--cscale))/var(--clh) var(--cf); font-variation-settings: var(--cv); letter-spacing: var(--cls); text-wrap: balance; }
.sb-probe { position: absolute; left: 0; top: 0; visibility: hidden; }
/* the finale's copy on the glass (Mike: "bring the whole copy back with the cool animation random shit", "just put this
   shit on glass"; on a phone "return the text for the body to a smaller size"): in the glass's ink, its words landing as
   outlines (#ring-plate, made by plate.mjs) and then inking in */
.card-copy { position: absolute; left: 0; top: 0; margin: 0; color: var(--sink); visibility: hidden; }
html[data-spread="spread"] .card-copy { --cs: clamp(17px, 1.25vw, 22px); text-align: left; }
html[data-spread="stack"] .card-copy { --cs: 14.5px; }
.card-copy .wd { display: inline-block; transform-origin: 50% 60%; }
.card-ol { position: absolute; inset: 0; pointer-events: none; color: #000; filter: url(#ring-plate); display: none; }
.card-ol .wd { opacity: 0; }
.ln { position: absolute; left: 0; width: 100%; text-wrap: nowrap; white-space: pre; }
.ln > span { position: absolute; top: 0; white-space: pre; }
/* (V4 pass 32) none of these reach into pro's study (#pro): its eight-study modules keep pro's own class talk on one link,
   styled by pro's stylesheet; :where() adds nothing to these rules' specificity, so the stories' own overrides still win */
/* "Let's Talk": a hairline that draws out under it (--tu), and an arrow that draws (--ta); on hover the arrow steps on
   and the hairline brightens. (V4 pass 31, Mike, Oct 11: "'Let's talk' should be 'Let's Talk'", "the let's talk arrow
   looks like shit", "the arrow is a bit far from the text and the line is kinda long": one treatment across Act 2, the
   ↗ of pro's link drawn at the letters' weight, half a space from the words, the hairline ending at its tip) */
.talk:where(:not(#pro *)) { position: relative; display: inline-flex; align-items: center; gap: .42em; margin-top: calc(var(--cs) * var(--clh) * 1.7);
        padding: 12px 0 15px; font: 400 clamp(15px, 1.1vw, 18px)/1 var(--sans); letter-spacing: 0; text-transform: none;
        color: var(--sink); text-decoration: none; pointer-events: auto; -webkit-tap-highlight-color: transparent; }
.talk:where(:not(#pro *))[inert] { pointer-events: none; }
.talk:where(:not(#pro *)) .lbl { display: inline-block; }
.t-arrow { flex: none; width: .6em; height: .6em; overflow: visible; transition: transform .45s cubic-bezier(.22, 1, .36, 1); }
.t-arrow path { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-dasharray: 1; stroke-dashoffset: calc(1 - var(--ta, 1)); vector-effect: non-scaling-stroke; }
.t-rule { position: absolute; left: 0; right: 0; bottom: 4px; height: 1px; background: currentColor; opacity: .5; transform-origin: 0 50%; transform: scaleX(var(--tu, 1)); transition: opacity .35s ease; }
.talk:where(:not(#pro *)):hover .t-arrow, .talk:where(:not(#pro *)):focus-visible .t-arrow { transform: translate3d(2px, -2px, 0); }
.talk:where(:not(#pro *)):hover .t-rule, .talk:where(:not(#pro *)):focus-visible .t-rule { opacity: 1; }
.talk:where(:not(#pro *)):focus-visible { outline: none; }
.talk:where(:not(#pro *)):focus-visible::after { content: ""; position: absolute; inset: 2px -10px; border: 1px solid currentColor; border-radius: 3px; opacity: .6; }

/* ?bare=1: the page inside a comparison frame */
html[data-bare] .top, html[data-bare] .sig, html[data-bare] .stamp, html[data-bare] .skip { display: none; }

/* ---- the hook in WATT's own Archivo (Mike, Oct 9: "archivo that we use the WATT could be great", "hook choices should not
   be this handwriting ass font", "it should be something editorial"): heavy and expanded like the mark, or Black at its
   normal width, or condensed like a headline; never italic (Archivo has no italic, and the accent carries the turn) ---- */
html[data-font="archivo"][lang] .spread { --hf: "Archivo", var(--sans); --hw: 800; --hst: 125%; --hlh: .98; --hls: -.012em; --hv: normal; }
html[data-font="archivoblack"][lang] .spread { --hf: "Archivo", var(--sans); --hw: 900; --hst: 100%; --hlh: .94; --hls: -.03em; --hv: normal; }
html[data-font="archivocond"][lang] .spread { --hf: "Archivo", var(--sans); --hw: 820; --hst: 72%; --hlh: .92; --hls: -.008em; --hv: normal; }

html[data-font^="archivo"][lang] .spread em:where(:not(#pro *)), html[data-font^="archivo"][lang] .spread .hook em:where(:not(#pro *)) { font-style: normal; }
html[data-font^="archivo"][lang] .spread { --cfam: var(--sans); }   /* the copy in Archivo too, as it was */
/* ---- pro's treatments (Oct 10, research/pro-act2-color-type-oct10.md): the duet (Instrument Sans 450, normal width, with
   "both ways." in Newsreader's real italic), all sans (Manrope 500), editorial (Newsreader 400 and its italic); the
   copy in Act 3's Archivo 400 in all three (Mike, Oct 10: "let's use the act three font for ht ecopy on act 2") ---- */
html[data-font="duet"][lang] .spread { --hf: "Instrument Sans", var(--sans); --hw: 450; --hst: 100%; --hlh: 1.02; --hls: -.038em; --hv: normal; --cfam: var(--sans); }
html[data-font="duet"][lang] .spread .hook .hl3 { font-family: "Newsreader", var(--serif); font-style: italic; font-weight: 400; font-size: 1.11em;
                                                  letter-spacing: -.029em; font-variation-settings: "opsz" 72; }
html[data-font="allsans"][lang] .spread { --hf: "Manrope", var(--sans); --hw: 500; --hst: 100%; --hlh: 1.02; --hls: -.045em; --hv: normal; --cfam: var(--sans); }
html[data-font="allsans"][lang] .spread .hook em { font-style: normal; }
html[data-font="editorial"][lang] .spread { --hf: "Newsreader", var(--serif); --hw: 400; --hst: 100%; --hlh: 1.02; --hls: -.021em; --hv: "opsz" 72; --cfam: var(--sans); }
html[data-font="editorial"][lang] .spread .hook .hl3 { font-size: 1.03em; letter-spacing: -.02em; }
html[data-font="duet"][lang][data-tone="dark"] .spread { --hw: 430; }   /* light type over the dark film reads heavier (backlit) */

/* ---- Static (?motion=static, js/static.mjs; Mike, Oct 10: "the layout matches pro's suggestion, the second card for the
   copy", "bring over the naimation that was created for act 3's contact page", "except instead of the white paper we
   have the second pane of glass just under the two copy paragrpahs"). Pro's page 3: the hook big on the left, the copy
   on a quieter reading pane on the right (body 18-21 px at 1.55 on the desktop, 17.5 px at 1.53 on a phone, the three
   sentences 8 px apart, 26 px before the scope paragraph); the pieces build as Act 3's do (outline, then ink) ---- */

/* the turn (static.mjs): the old word and the new one share one slot, so the line never jumps as one gives way */

/* "Great" in the hook's italic, as "both ways." is (Mike, Oct 10: "and make Great italic") */

/* "Let's talk" under the paragraphs on the panel (Mike, Oct 10: "let's remove let's talks island just keep it part of the
   paragraphs") */

/* "Operations + Design" and "Let's talk" in the copy's own face, weight and size, as written, no tracking; the "+" is the
   face's own (Mike, Oct 10: "let's make 'lets talk' a normal size and boldness", "also 'operations and design' looks like
   shit", "just do a normal font for that as well", "stop throwing all these fucking five different fonts in one pane") */

/* "Let's talk" in capitals (Mike, Oct 10: "all caps for lets talk"), and its arrow drawn at the letters' own stroke weight
   ("and make the arrow the same weight") */

/* the underline ends at the arrow's tip (Mike, Oct 10: "the underline now is too long for that"): the baseline marker was
   a fourth item in the row and added one more gap after the arrow */

   /* wider side margins (Mike, Oct 10: "give me more of a margin from the left and right") */

/* stacked, the hook is two even lines, "Great care should" over "go both ways." at matching sizes (Mike, Oct 10: "on layouts
   where the shit is stacked vertically the hook should be two lines instead of three", "it should be Great care should /
   go both ways", "if we have go on that line make them the same size"): the three lines run on as one, broken after
   "should" (static.mjs's .st-br), and static.mjs sizes it by its widest line */

/* a short phone: the spacing tightens before the type steps down (static.mjs measure); still clear of the rim */

/* Act 3's build, on Static's own pieces ([data-sb]): outline (each piece etches on as a light hairline once the glass is
   there, --etch, and fills in), lines (rises and wipes up) or blur (comes into focus), as ?text= picks; the words are
   inline blocks so they can move, and no build touches the tracking */

/* room above and below each word that builds, so its repaint (and the lines wipe) covers the ascenders and descenders:
   the "g" of "go" hung below its box and kept its unbuilt state (Mike, Oct 10: "the g in go is cutoff on the bottom") */

/* on the panel the copy's etched state is a finer, fainter hairline than the hook's, in the copy's own ink: a 1 px stroke
   filled the copy's stems and the words read as bold type before they inked in */

/* the copy's panel (Mike, Oct 10, with Apple Weather: "instead of the glass panes as the copy backdrops can we do something
   more like these panels?"): flat and rounded, laid over the frost, no rim, shine or shadow. Dark text on every backdrop
   but Night (Mike, Oct 10: "dark text on the everything but the night backdrop"): on Trees and Submerged the panel is the
   film's light neutral sheet (the plate's: warm mineral, pro's bone) and the copy is in the film's ink; on Night it stays a
   darker shade of the film with the copy in bone */

/* the wall (stage.mjs): while Act 2's text is still playing the page ends there, so no rubber-band bounce against it */
html.walled { overscroll-behavior-y: none; }
/* (Oct 14; Mike, on his Mac: "everything is fucking offset") Safari bounced the whole page against the story's stop; no bounce anywhere on this page */
html, body { overscroll-behavior-y: none; }
