/* §07 finale — HIT → iris → reset, plus the footer. Owned by the finale builder.
   Default (no JS / reduced) = the static "back to full" composition. .is-live (motion JS) = the metered scene;
   .is-docked (live + island.js) = the pay-off: the fresh wordmark above a first-launch pinned panel that the
   download hangs from. .is-fresh (after the reset) = a fresh window: the fill still means used, like the app, so it
   creeps up to 12% in the teal zone while the caption says "back to full"; .is-drain = the reset drain (full → fresh)
   while the iris opens. #iris is a global fixed layer created by finale.js, scoped under #iris. */

.s--finale{padding-bottom:0}
.s--finale .pin{position:relative;min-height:100svh;display:flex;flex-direction:column;padding-bottom:clamp(28px,5vh,64px)}
.s--finale .fin-rh{padding-top:calc(var(--band-h) + 20px)}
.s--finale .pin > .cm-banners{top:calc(var(--band-h) + 6px)} /* the reset banner: under the band, clear of the meter's label row */
.s--finale .fin-body{container-type:inline-size;flex:1;display:flex;flex-direction:column;gap:clamp(28px,4.4vh,52px);padding-top:clamp(24px,4.4vh,64px)}

/* ---------- the meter: one pinned-table row at poster scale ---------- */
.s--finale .fin-meter{position:relative;width:fit-content;max-width:100%}
.s--finale .fin-label{display:flex;justify-content:space-between;gap:24px;margin-bottom:clamp(12px,2vh,22px);
  font:500 var(--t-label)/1.2 var(--f-mono);letter-spacing:.08em;text-transform:uppercase;font-variant-numeric:tabular-nums;color:var(--fg-text-2)}
.s--finale .fin-cap{color:var(--teal-ink)}
.s--finale:not(.is-live) .fin-lab{display:none}
.s--finale .fin-fc{display:none}

/* Three stacked copies. Ink: a 3px stroke, of which the 1.5px outside the glyph shows. Hollow: the page colour
   over the glyph (a plain text-stroke would draw the variable font's overlapping contours). Fill: the hard-stop
   zones, painted once and revealed by a counter-translated clip, so scrubbing the fill only moves composited layers. */
@property --fin-bg{syntax:"<color>";inherits:true;initial-value:#EDEEE9}
.s--finale .fin-markbox{position:relative;display:grid;justify-items:start;--fin-bg:var(--bg);transition:--fin-bg 400ms var(--ease-edit);
  font-size:min(var(--t-mark),calc(100cqi / 9.1))} /* one line at wdth 120 is 9.08em: fit the grid exactly */
.s--finale .fin-mark{
  grid-area:1/1;margin:-.1em 0 -.08em;padding:.1em .02em .08em 0;white-space:nowrap;
  font:900 1em/var(--lh-mark) var(--f-display);font-stretch:120%;letter-spacing:var(--tr-mark);
  transition:letter-spacing .3s var(--ease-settle);user-select:none;
}
.s--finale .fin-mark--o{color:var(--fg-text);-webkit-text-stroke:3px var(--fg-text)}
.s--finale .fin-mark--h{color:var(--fin-bg)}
.s--finale .fin-clip{grid-area:1/1;overflow:hidden;margin-block:-.3em;padding-block:.3em}
.s--finale .fin-mark--f{color:transparent;background:var(--teal);-webkit-background-clip:text;background-clip:text}
.s--finale .fin-mark .ch{display:inline;font-stretch:clamp(50%,calc(120% * (1 - .55 * var(--sq,0))),150%)}
.s--finale .fin-markbox.is-hot .fin-mark{letter-spacing:calc(var(--tr-mark) - .01em)}
.s--finale .fin-markbox.is-hot .fin-mark--o{color:var(--red-ink);-webkit-text-stroke:6px var(--red-ink)}
html[data-night] .s--finale .fin-markbox.is-hot .fin-mark--o{color:var(--red);-webkit-text-stroke-color:var(--red)}

.s--finale .fin-bar{position:relative;height:6px;margin-top:clamp(14px,2.4vh,26px);border-radius:3px;background:var(--rule-c);overflow:hidden}
.s--finale .fin-bar__fill{position:absolute;inset:0;background:var(--teal)}
.s--finale .fin-scale{position:relative;height:30px;margin-top:10px;font:500 11px/1 var(--f-mono);color:var(--fg-text-2);font-variant-numeric:tabular-nums}
.s--finale .fin-scale::before{content:"";position:absolute;left:0;right:0;top:0;height:7px;opacity:.5;border-right:1px solid currentColor;
  background:linear-gradient(90deg,currentColor 1px,transparent 1px) 0 0/5% 4px repeat-x,linear-gradient(90deg,currentColor 1px,transparent 1px) 0 0/25% 7px repeat-x}
.s--finale .fin-scale span{position:absolute;top:14px;transform:translateX(-50%)}
.s--finale .fin-scale span:nth-child(1){left:0;transform:none}
.s--finale .fin-scale span:nth-child(2){left:25%}
.s--finale .fin-scale span:nth-child(3){left:50%}
.s--finale .fin-scale span:nth-child(4){left:75%}
.s--finale .fin-scale span:nth-child(5){left:100%;transform:translateX(-100%)}
.s--finale .fin-head{display:none}

/* live: hard-stop zones (teal · lavender · amber · red) revealed up to the fill by transforms alone */
.s--finale.is-live .fin-cap{display:none}
.s--finale.is-live .fin-fc{display:block;text-transform:none;letter-spacing:.02em}
.s--finale .fin-fc.is-amber{color:var(--amber-ink)}
.s--finale .fin-fc.is-red{color:var(--red-ink);font-weight:700}
html[data-night] .s--finale .fin-fc.is-amber{color:var(--amber)}
html[data-night] .s--finale .fin-fc.is-red{color:var(--red)}
/* JS writes the pair of transforms inline (a clip moved left by 100−fill %, its content moved back right), so a scrub
   restyles four elements and repaints nothing; these are the empty-meter defaults until it does. They are layers only
   while the section is near the screen (.is-near), so the rest of the page doesn't carry them. */
.s--finale.is-live .fin-clip,.s--finale.is-live .fin-bar__fill{transform:translate(-100%,0)}
.s--finale.is-live .fin-mark--f,.s--finale.is-live .fin-bar__fill>i{transform:translate(100%,0)}
.s--finale.is-near .fin-clip,.s--finale.is-near .fin-mark--f,.s--finale.is-near .fin-bar__fill,.s--finale.is-near .fin-bar__fill>i,.s--finale.is-near .fin-head{will-change:transform}
.s--finale.is-live .fin-mark--f,.s--finale.is-live .fin-bar__fill>i{background-image:linear-gradient(90deg,var(--teal) 0 60%,var(--lav) 60% 75%,var(--amber) 75% 85%,var(--red) 85% 100%)}
.s--finale.is-live .fin-bar__fill{overflow:hidden;background:none}
/* the idle breath steps in whole percents; between steps the compositor glides every moving layer there */
.s--finale.is-breath .fin-clip,.s--finale.is-breath .fin-mark--f,.s--finale.is-breath .fin-bar__fill,.s--finale.is-breath .fin-bar__fill>i{
  transition:transform .45s var(--ease-settle)}
/* fresh: the caption says why the meter is back at the start; the playhead steps aside only while the reset drains
   the fill (its chip already reads the fresh value) and settles back in on it */
.s--finale.is-live.is-drain .fin-head{opacity:0}
.s--finale.is-live.is-fresh .fin-lab{display:none}
.s--finale.is-live.is-fresh .fin-cap{display:block}
.s--finale .fin-bar__fill>i{position:absolute;inset:0}
.s--finale.is-live .fin-head{display:block;position:absolute;left:0;top:4%;bottom:calc(-1 * (clamp(14px,2.4vh,26px) + 6px));width:0;pointer-events:none;transition:opacity .3s var(--ease-settle)}
.s--finale .fin-head__line{position:absolute;left:-.5px;top:0;bottom:0;width:1px;background:var(--fg-text)}
.s--finale .fin-head__chip{position:absolute;left:0;bottom:0;transform:translate(-24px,calc(100% + 5px));width:48px;height:20px;text-align:center;border-radius:10px;
  background:var(--black);color:var(--teal);font:600 11px/20px var(--f-mono);white-space:nowrap;font-variant-numeric:tabular-nums;letter-spacing:.02em}
.s--finale .fin-meter[data-zone="lav"] .fin-head__chip{color:var(--lav)}
.s--finale .fin-meter[data-zone="amber"] .fin-head__chip{color:var(--amber)}
.s--finale .fin-meter[data-zone="red"] .fin-head__chip{color:var(--red);font-weight:800}
.s--finale .fin-meter[data-zone="red"] .fin-head__line{background:var(--red-ink)}
html[data-night] .s--finale .fin-head__chip{background:var(--fg);color:var(--ink)}

/* ---------- after the reset (static: H2 then the requirements on the left; the download, Windows and the repo
   hanging from a hairline on the right) ---------- */
.s--finale .after{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:var(--col-gap);align-items:end}
.s--finale .after h2{grid-column:1 / span 7;grid-row:1;color:var(--fg-text)}
.s--finale .after h2 em{color:var(--fg-text)}
.s--finale .fin-go{grid-column:8 / -1;grid-row:1 / span 2;min-width:0}
.s--finale .fin-notes{grid-column:1 / span 7;grid-row:2;align-self:start;margin-top:28px;min-width:0}
.s--finale .fin-bn{position:relative;margin-bottom:28px}
.s--finale .fin-bn .cm-banners{position:static;width:min(340px,100%);margin-inline:auto}
.s--finale.is-live .fin-bn{display:none}
.s--finale .fin-dock{display:none}
.s--finale .fin-go .cta-hang{position:relative;justify-content:center} /* one axis: banner, download, Windows, repo */
.s--finale .cta:not([data-cta-bound]){--cta-w:min(440px,100%);background:var(--black);border-radius:0 0 30px 30px} /* no JS: cta.js never draws the shape */
.s--finale.is-live:not(.is-docked) .fin-go .cta-hang{border-top-color:transparent} /* island.js missing: the hairline draws in */
.s--finale.is-live:not(.is-docked) .fin-go .cta-hang::before{content:"";position:absolute;left:0;right:0;top:-1px;height:1px;background:var(--rule-c);transform:scaleX(var(--hang,1));transform-origin:0 50%}
.s--finale .req strong,.s--finale .fin-howto strong{font-weight:600;color:var(--fg-text)}
.s--finale .fin-howto{margin-top:10px;font:400 13px/1.55 var(--f-mono);color:var(--fg-text-2);font-variant-numeric:tabular-nums;max-width:56ch}
.s--finale .fin-howto code{font:inherit;color:var(--fg-text);background:var(--paper-2);padding:1px 5px;border-radius:4px}
.s--finale .fin-howto::before{content:"";display:inline-block;width:18px;height:1px;margin-right:10px;vertical-align:.3em;background:currentColor}

/* docked: a hairline is the screen's top edge; the app's notch sits on it and opens pinned, like first launch,
   and the download hangs from the panel's flat bottom (both are #000, so they read as one shape). */
.s--finale.is-docked .after{position:relative;align-items:start;row-gap:28px}
.s--finale.is-docked .after::before{content:"";position:absolute;left:0;right:0;top:0;height:1px;background:var(--rule-c);transform:scaleX(var(--hang,1));transform-origin:0 50%}
.s--finale.is-docked .after h2{grid-column:1 / 6;grid-row:1;padding-top:clamp(22px,3.4vh,40px);font-size:min(var(--t-h2),6.7cqi)} /* "Fresh window." is 5.96em: fits 5 columns */
.s--finale.is-docked .fin-notes{grid-column:1 / 6;grid-row:2;align-self:end;margin-top:0}
.s--finale.is-docked .fin-go{grid-column:6 / -1;grid-row:1 / span 2}
.s--finale.is-docked .fin-dock{display:block;position:relative;z-index:2}
.s--finale .fin-cam{position:relative;transform-origin:50% 0}
.s--finale.is-docked .fin-win-hang .cta-ghost{width:min(300px,calc(var(--fin-s,1) * 460px - 84px))} /* inside the download's flat bottom */
.s--finale.is-docked .fin-go .cta-hang{z-index:1;border-top:0;margin:-1px auto 0;width:calc(var(--fin-s,1) * 460px);max-width:100%;justify-content:center}

/* ---------- Windows: the Mac tab's forecast. Its ghost (the same NotchShape, dashed) hangs from the download's flat
   bottom; hover or focus closes the dashes and fills it (the forecast becoming real). On Windows it is real already. */
.s--finale .fin-win-hang{position:relative;z-index:0;display:flex;justify-content:center;margin-top:-4px}
.s--finale .fin-go .cta-hang{position:relative;z-index:1}
.s--finale .fin-win-hang .cta-ghost{width:min(300px,calc(100% - 84px));height:52px;container-type:inline-size}   /* the shared .cta-ghost (base.css) */
html[data-os="windows"] .s--finale .cta-ghost__label{font-size:17px}

/* ---------- open source: the shared GitHub chip (base.css .gh-chip) hangs last in the download stack, and a
   hand-written margin note (the hero's "psst — it's live." answered) points back at it from the right. An empty
   spacer as wide as the note keeps the chip on the stack's axis; it gives way first when the column is narrow. */
.s--finale .fin-oss{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:24px}
.s--finale .fin-oss::before{content:"";flex:0 1 var(--oss-note,236px)}
.s--finale .fin-oss__note{display:flex;align-items:flex-start;gap:4px;flex:none;width:var(--oss-note,236px);margin:0;color:var(--fg-text-2);pointer-events:none}
.s--finale .fin-oss__ink{width:52px;height:28px;flex:none;overflow:visible;margin-top:-4px}
.s--finale .fin-oss__note span{margin-top:10px;font:400 22px/1.1 var(--f-serif);font-style:italic;letter-spacing:-.005em;white-space:nowrap;rotate:-4deg;transform-origin:0 50%}
/* static (no pin, room to spare) and phones: the note drops under the chip, its arrow turned to point up at it */
.s--finale:not(.is-docked) .fin-oss{flex-direction:column;gap:14px}
.s--finale:not(.is-docked) .fin-oss::before{display:none}
.s--finale:not(.is-docked) .fin-oss__note{width:auto;padding-left:34px}
.s--finale:not(.is-docked) .fin-oss__ink{scale:1 -1;rotate:90deg;margin-top:0}
.s--finale:not(.is-docked) .fin-oss__note span{margin:22px 0 0 -12px}

/* ---------- footer ---------- */
.fin-foot{position:relative;background:var(--night);color:var(--fg-2);padding:64px max(var(--gutter),env(safe-area-inset-right)) 64px max(var(--gutter),env(safe-area-inset-left));border-top:1px solid var(--rule-night);
  font:400 14px/1.5 var(--f-display);font-stretch:100%}
.fin-foot__row,.fin-foot__legal{max-width:calc(var(--maxw) - 2 * var(--gutter));margin-inline:auto}
/* identity + requirements on top, the links below (eight links never fit a middle column, even at 1920) */
.fin-foot__row{display:grid;grid-template-columns:auto minmax(0,1fr);gap:28px 32px;align-items:center}
.fin-foot__id{display:flex;align-items:center;gap:10px;color:var(--fg)}
.fin-foot__id span{white-space:nowrap}
.fin-foot__nav{grid-row:2;grid-column:1 / -1}
.fin-foot__id img{width:20px;height:20px;flex:none}
.fin-foot__nav ul{display:flex;flex-wrap:wrap;justify-content:flex-start;gap:6px 26px;margin:0;padding:0;list-style:none}
.fin-foot__nav a{position:relative;display:inline-block;padding:4px 0;color:var(--fg);text-decoration:none;white-space:nowrap}
.fin-foot__nav a::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--teal);transform:scaleX(0);transform-origin:0 50%;
  transition:transform .5s var(--ease-edit)}
.fin-foot__nav a:hover::after,.fin-foot__nav a:focus-visible::after{transform:scaleX(1)}
.fin-foot__top span{display:inline-block;transition:transform .35s var(--ease-settle)}
.fin-foot__top:hover span,.fin-foot__top:focus-visible span{transform:translateY(-3px)}
.fin-foot__req{justify-self:end;text-align:right;font:400 13px/1.6 var(--f-mono);font-variant-numeric:tabular-nums}
.fin-foot__req span{white-space:nowrap}
.fin-foot__legal{margin-top:44px;padding-top:18px;border-top:1px solid var(--rule-night);font:400 12px/1.5 var(--f-mono);color:var(--fg-2)}
.fin-foot__meter{position:absolute;left:0;right:0;bottom:0;height:1px;overflow:hidden}
.fin-foot__meter i{display:block;height:100%;background:var(--teal);transform-origin:0 50%;transform:scaleX(0)}
.fin-foot [data-stars]:not([hidden])::before{content:"★ "}
/* stacked pay-off (tablet and phone): H2, then the hairline with the notch on it, the panel, the download */
@media (max-width:1023px){
  .s--finale .after{display:block}
  .s--finale .after h2{margin-bottom:32px}
  .s--finale.is-docked .after::before{display:none}
  .s--finale.is-docked .after h2{padding-top:0;margin-bottom:28px;font-size:var(--t-h2)}
  .s--finale.is-docked .fin-dock::before{content:"";position:absolute;left:0;right:0;top:0;height:1px;background:var(--rule-c);transform:scaleX(var(--hang,1));transform-origin:0 50%}
  .s--finale .fin-notes{margin-top:32px}
  .s--finale.is-docked .fin-notes{margin-top:28px}
  .s--finale .fin-win-hang{margin-bottom:4px}
}


/* ---------- mobile ---------- */
@media (max-width:767px){
  .s--finale .fin-body{padding-top:clamp(24px,4vh,40px);gap:36px}
  .s--finale .fin-markbox{font-size:min(28vw,calc(100cqi / 4.56))} /* "Claude" is 4.51em */
  .s--finale .fin-mark{line-height:.84}
  .s--finale .fin-w{display:block}
  .s--finale .fin-sp{display:none}
  .s--finale.is-docked .fin-dock{margin-inline:calc(-1 * var(--gutter))}
  .s--finale .cta--xl .cta__label{font-size:clamp(18px,5.6vw,24px)} /* fits the tab under a 320px-wide panel */
  .s--finale.is-fresh .fin-fc{display:none} /* keep the label one line: the caption says it all */
  .s--finale.is-docked .fin-oss{flex-direction:column;gap:14px}   /* as static (above) */
  .s--finale.is-docked .fin-oss::before{display:none}
  .s--finale.is-docked .fin-oss__note{width:auto;padding-left:34px}
  .s--finale.is-docked .fin-oss__ink{scale:1 -1;rotate:90deg;margin-top:0}
  .s--finale .fin-oss__note span{font-size:20px;margin:22px 0 0 -12px}
  .fin-foot{padding-block:48px}
  .fin-foot__row{grid-template-columns:1fr;gap:28px;align-items:start}
  .fin-foot__nav{grid-row:auto}
  .fin-foot__id span{white-space:normal}
  .fin-foot__nav ul{gap:4px 20px}
  .fin-foot__req{justify-self:start;text-align:left}
  .fin-foot__req span{white-space:normal}
}

/* ---------- the iris (global, fixed) ----------
   Composited: .iris__ap is painted once (clear hole · soft vignette · a rim of light · black) and only scaled; four
   black sheets slide in to cover the screen outside it. The live page shows through the closing aperture.
   --iz hard-cuts red → amber → teal (never transitioned: a tween between them passes through orange). */
#iris{position:fixed;inset:0;z-index:var(--z-iris);display:none;overflow:hidden;contain:strict;pointer-events:auto;--ly:20px;--ls:9px;--iz:var(--red)}
#iris.is-on{display:block}
#iris[data-zone="amber"]{--iz:var(--amber);--izb:color-mix(in oklab,var(--amber) 60%,#fff)} /* amber dimmed on black reads brown: its beam is the paler light */
#iris[data-zone="teal"]{--iz:var(--teal)}
#iris .iris__b{position:absolute;left:0;top:0;width:100%;height:100%;background:#000;will-change:transform}
#iris .iris__ap{position:absolute;left:0;top:0;width:512px;height:512px;margin:-256px 0 0 -256px;will-change:transform;
  background:radial-gradient(circle closest-side,transparent 0 36%,rgb(0 0 0/.1) 45%,rgb(0 0 0/.46) 56.2%,rgb(255 255 255/.2) 58.9%,#000 60%)}
#iris .iris__beam{position:absolute;left:50%;top:var(--ly);width:min(1400px,160vw);height:115vh;margin-left:max(-700px,-80vw);opacity:0;transform-origin:50% 0;pointer-events:none;
  background:radial-gradient(ellipse 34% 78% at 50% 0,color-mix(in srgb,var(--izb,var(--iz)) 26%,transparent),color-mix(in srgb,var(--izb,var(--iz)) 7%,transparent) 55%,transparent 80%)}
#iris .iris__lens{position:absolute;left:50%;top:var(--ly);width:var(--ls);height:var(--ls);margin:calc(var(--ls) / -2) 0 0 calc(var(--ls) / -2);border-radius:50%;overflow:hidden;
  background:radial-gradient(circle at 36% 34%,rgb(90 110 255/.5) 0 14%,transparent 26%),#0A0B10;box-shadow:inset 0 0 0 1px rgb(255 255 255/.07);opacity:0}
#iris .iris__glint{position:absolute;inset:0;background:linear-gradient(110deg,transparent 30%,rgb(255 255 255/.85) 50%,transparent 70%);transform:translateX(-120%)}
#iris .iris__ring{position:absolute;left:50%;top:var(--ly);width:40px;height:40px;margin:-20px 0 0 -20px;overflow:visible;opacity:0;transform:rotate(-90deg)}
#iris .iris__ring .trk{fill:none;stroke:rgb(255 255 255/.1);stroke-width:2.5}
#iris .iris__ring .val{fill:none;stroke:var(--iz);stroke-width:2.5;stroke-linecap:round;stroke-dasharray:100}
/* the drain: a poster-size session number in the wordmark's face; its box never changes size (no layout shift),
   the digits are centred by a translate */
#iris .iris__mid{position:absolute;left:0;right:0;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;align-items:center;gap:clamp(14px,2.4vh,26px);pointer-events:none}
#iris .iris__num{position:relative;margin:0;width:100%;height:.8em;opacity:0;color:var(--iz);
  font:900 clamp(112px,19vw,300px)/.8 var(--f-display);font-stretch:120%;letter-spacing:-.04em;font-variant-numeric:tabular-nums}
#iris .iris__nb{position:absolute;left:50%;top:0;display:flex;align-items:flex-start;translate:-50% 0;white-space:nowrap}
#iris .iris__n{letter-spacing:-.075em}
#iris .iris__pc{font-size:.4em;line-height:1;margin:.04em 0 0 .06em;letter-spacing:0}
#iris .iris__txt{margin:0;font:500 15px/1 var(--f-mono);letter-spacing:.08em;color:var(--fg-2);opacity:0;white-space:nowrap}
