/* 2 · Windows */
.v2{background:var(--cream);color:var(--ink)}
/* the first window and its pinned frame are sized by the LARGE viewport (lvh, as the stage is: scroll/scroll.css), which
   never changes while a phone slides its toolbar; plain vh first, for browsers without lvh (06.10.2026).
   Where the value also holds a var() (the section's colours just below, both sky boxes further down, the stage's track
   in scroll/scroll.css) the lvh line sits in an @supports block of its own instead of second in the rule. A value with
   var() in it is accepted whatever its units, so there the second line always won, and a browser without lvh (Safari
   before 15.4, Chrome before 108, Firefox before 101) then threw it away WITH the vh line: no height at all. The sky
   boxes were 0 px tall there, so no window had a sky (shown in Chrome with a made-up unit in place of lvh) */
.v2-open{height:230vh;height:230lvh}
.v2-open__st{position:sticky;top:0;display:grid;height:100vh;height:100lvh;overflow:hidden}
/* Safari's bars on iOS 26 (06.10.2026): they are clear glass, and what shows through the top one is the page just ABOVE
   the pinned frame, which is this section behind it, not the window. So the section is night down to where the white
   starts to close in and cream from there: a hard stop at 48lvh, under the 49.4lvh the frame has travelled by then
   (0.38 of its 130lvh: v2.js). None of it can show inside the screen: until 49.4lvh the window covers its whole frame,
   and from there the frame has passed the night part. ?fx=bars (site-header.js): plain cream, as before */
html:not(.fx-bars) .v2-open{background:linear-gradient(to bottom,var(--night) 48vh,var(--cream) 48vh)}
@supports (height:1lvh){html:not(.fx-bars) .v2-open{background:linear-gradient(to bottom,var(--night) 48lvh,var(--cream) 48lvh)}}
/* (06.10.2026, seen on Noki's phone) The stop above is right for the top bar only: the bottom bar shows this section a
   screen further down, which was cream under the night window. So on iOS v2.js lays one flat night box over the whole
   section, behind the pinned frame (.has-bar), and fades it out as the white starts to close in: both bars are night
   while the window fills its frame and cream from then on. 1 px tall, stretched by a transform: no picture to draw */
.v2-open.has-bar{position:relative}
.v2-bar{position:absolute;left:0;top:0;width:100%;height:1px;transform-origin:0 0;background:var(--night);pointer-events:none;will-change:opacity;transition:opacity .2s linear}
.v2-open__win{position:relative;display:grid;place-items:center;background:var(--night);color:#fff;text-align:center;clip-path:inset(var(--i,0px) var(--j,0px) var(--i,0px) var(--j,0px) round var(--r,0px))}
.v2-open__gl{position:absolute;inset:0;opacity:var(--g,0);background:var(--sky);background-attachment:fixed}
.v2-open__h{position:relative;max-width:14ch;padding:0 24px;font-size:clamp(40px,3.6vw + 16px,80px);line-height:1.02;font-weight:700;letter-spacing:-.035em;text-wrap:balance;opacity:var(--t,0);transform:translate3d(0,calc((1 - var(--t,0)) * 24px),0)}
.v2-chs{display:grid;gap:clamp(90px,12vw,170px);padding:clamp(70px,9vw,120px) 0 clamp(90px,12vw,160px)}
.v2-ch{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:clamp(16px,2vw,28px);align-items:center}
.v2-win{grid-column:1/8;grid-row:1;position:relative;display:grid;place-items:center;min-height:clamp(340px,34vw,500px);padding:clamp(28px,4vw,56px);border-radius:28px;overflow:hidden;background:var(--sky);background-attachment:fixed;box-shadow:inset 0 0 0 1px rgba(255,255,255,.06)}
.v2-win .ui{--ui-fs:clamp(13px,.4vw + 10px,16px);width:100%;max-width:420px}
.v2-win .ui-shop{max-width:520px}
.v2-tx{grid-column:9/13;grid-row:1}
.v2-ch.is-r .v2-win{grid-column:6/13}
.v2-ch.is-r .v2-tx{grid-column:1/5}
.v2-ph{--w:min(56%,270px);position:absolute;left:50%;top:14%;translate:-50% 0}
.v2-h3{font-size:clamp(28px,1.4vw + 18px,44px);line-height:1.06;font-weight:600;letter-spacing:-.03em;text-wrap:balance}
.v2-p{margin-top:16px;font-size:17px;line-height:1.58;color:var(--mu);text-wrap:pretty}
.v2-gu{padding-top:0}
.v2 .v2-gu .rb-gu__ph{position:relative;height:clamp(460px,44vw,600px);border-radius:28px;overflow:hidden;background:var(--sky);background-attachment:fixed}
.v2 .v2-gu .rb-gu__ph .rb-ph{--w:min(76%,270px);position:absolute;left:50%;top:12%;translate:-50% 0;filter:none}
.v2-cta .rb-cta{background:var(--sky);background-attachment:fixed}
/* the windows show a sky fixed to the screen, and any transform turns that into a picture stuck to the window (CSS
   Transforms: fixed is treated as scroll). So they never move to arrive: they open from a clip, like the first one */
.rb .v2-win[data-rv],.rb .v2-gu .rb-gu__ph[data-rv],.rb .v2-cta .rb-cta[data-rv]{transform:none;clip-path:inset(8% 6% round var(--wr,28px));transition:opacity .9s var(--e) var(--rd,0s),clip-path 1.2s var(--e) var(--rd,0s)}
.rb .v2-win[data-rv].is-in,.rb .v2-gu .rb-gu__ph[data-rv].is-in,.rb .v2-cta .rb-cta[data-rv].is-in{clip-path:inset(0 round var(--wr,28px))}
.v2-cta .rb-cta{--wr:32px}
/* the sky through every window: one layer fixed to the screen inside each window near it, cut by the window's clip-path
   (v2.js), so it looks as background-attachment:fixed does, on phones too, and is moved by the compositor instead of
   repainted on every scrolled frame. It drifts back and forth a few px, 6 s each way on a sine, barely there
   (RB_SKY_T.drift: { px, secs } on the page). Oversized by the drift, so its edges never show.
   (06.10.2026) Its box is the LARGE viewport (100lvh), not the visible screen: iOS resized every sky layer and re-fitted
   its picture each time the toolbar slid (411x765 to 411x683). On a computer the two are the same box. ?fx=vhsky (v2.js
   puts .fx-vhsky on #rb): the visible screen, as before (but not for the first window's pair below, which must match).
   (06.10.2026) The fixed box paints NOTHING itself: the picture is its ::before, in a layer of its own. iOS Safari lays
   every fixed and sticky box out again on each frame of a toolbar slide (and on many frames of a fling) and then draws
   that box's own painting again, though nothing changed; what the box only holds in another layer is left alone.
   Measured in Simulator Safari, turning round in the chapters: with the picture on the box, every live sky was drawn
   again on 81 to 100% of the slide's frames (273 re-draws in the leg); in the ::before, on none (6). No plain colour
   under the picture either (the window's own night is behind it: .has-fsky), so the box gives iOS 26 Safari no solid
   colour to fill its bars with. ?fx=flatsky (.fx-flatsky on #rb): the picture on the box itself, as before */
.v2-fsky{position:fixed;top:calc(-1 * var(--sky-dx,10px));left:calc(-1 * var(--sky-dx,10px));right:calc(-1 * var(--sky-dx,10px));height:calc(100vh + 2 * var(--sky-dx,10px));z-index:-1;display:none;pointer-events:none;animation:v2Drift var(--sky-dt,6s) cubic-bezier(.37,0,.63,1) infinite alternate}
@supports (height:1lvh){.v2-fsky{height:calc(100lvh + 2 * var(--sky-dx,10px))}}
.v2-fsky::before{content:"";position:absolute;inset:0;background:var(--sky);background-color:transparent;will-change:transform}
.fx-flatsky .v2-fsky{background:var(--sky)}
.fx-flatsky .v2-fsky::before{content:none}
.fx-vhsky :not(.has-psky)>.v2-fsky{bottom:calc(-1 * var(--sky-dx,10px));height:auto}
.has-fsky>.v2-fsky{display:block}
.has-fsky{background:var(--night)!important}
.v2-open__gl.has-fsky{background:none!important}
@keyframes v2Drift{from{transform:translate3d(calc(-1 * var(--sky-dx,10px)),0,0)}to{transform:translate3d(var(--sky-dx,10px),0,0)}}
@media (prefers-reduced-motion:reduce){.v2-fsky{animation:none}}
/* touch screens (06.10.2026; v2.js puts the classes on #rb). .sky-still: no sway, and so no oversize: with it, iOS Safari
   re-drew two or three of these full-screen layers in the same frame on 34 to 43% of a fling's frames, without it on 1
   to 5%; pausing it changed nothing, it has to be absent (?fx=drift puts it back). .sky-n: each layer is laid out at
   1/N of its size and scaled up N times (N = --sky-n, the screen's whole device pixels per CSS px), so Safari keeps
   1.2 MB per layer instead of 10 to 11; the picture has one pixel per CSS px, so none of it is lost (?fx=bigsky: full
   size). Only where the sway is off: the scale would multiply it. Half a pixel over, so a screen that doesn't divide by
   N leaves no gap along its right and bottom edges */
.sky-still{--sky-dx:0px}
.sky-still .v2-fsky{animation:none}
.sky-n .v2-fsky{right:auto;width:calc(100% / var(--sky-n,1) + .5px);height:calc(100vh / var(--sky-n,1) + .5px);transform:scale(var(--sky-n,1));transform-origin:0 0}
@supports (height:1lvh){.sky-n .v2-fsky{height:calc(100lvh / var(--sky-n,1) + .5px)}}
/* the first window's own sky (06.10.2026, v2.js): not fixed to the screen but an ordinary child of the pinned frame, the
   same box, in a layer of its own that is always there; its opacity (the glow coming out) is written on it by v2.js,
   so its holder is plain (no group to blend) and the picture is on the layer itself, not in a ::before (that would be
   a group again). On computers the window's fixed layer comes on over it once the white is in; on touch screens there
   is none and the sky leaves with its frame (v2.js). ?fx=fixedsky: the fixed layer alone and the holder's --g, as before */
.v2-open__gl.has-psky{opacity:1;background:none}
.v2-fsky.v2-psky{position:absolute;display:block;opacity:0;will-change:opacity;background:var(--sky);background-color:transparent}
.v2-fsky.v2-psky::before{content:none}
/* ?fx=panels (06.10.2026), an experiment that is off unless named: the first window closes with cream panels moved by the
   compositor instead of a clip-path that changes on every frame (a rounded mask over a full-screen layer on the phone's
   graphics chip). Four bars slide in from beyond the screen's edges (moved, never scaled: a scaled layer's outer edge
   is drawn soft, and that left a half-dark hairline along the screen's edge) and four corner pieces scale from its
   corners: the same insets and radius as the clip at every step, since all three are k times a constant (v2.js).
   Nothing in it is painted. A bar is a plain colour. A corner piece is a plain cream square, 34 px, cut by a clip of
   its own (the square less a quarter disc of 32 px), a pixel into both bars so no hairline can show; Safari keeps
   such a cut as a shape beside the layer, so scaling it draws nothing. (As a painted picture of the cut-out, Safari
   drew all four again on every frame as they scaled: 6.2 ms of layer hand-over a frame on an M3, against 0.65 with
   the clip.) The window keeps its night as a plain colour in a layer of its own (will-change), so nothing full-screen
   is painted for it either. --pi, --pj: the insets at the end */
.fx-panels .v2-open__win{clip-path:none;will-change:opacity}
.v2-pn{position:absolute;z-index:2;background:var(--cream);pointer-events:none;will-change:transform}
.v2-pn--t,.v2-pn--b{left:0;right:0;height:var(--pi,0px)}
.v2-pn--l,.v2-pn--r{top:0;bottom:0;width:var(--pj,0px)}
.v2-pn--t{top:0;transform:translate3d(0,-100%,0)}.v2-pn--b{bottom:0;transform:translate3d(0,100%,0)}
.v2-pn--l{left:0;transform:translate3d(-100%,0,0)}.v2-pn--r{right:0;transform:translate3d(100%,0,0)}
.v2-pn--c{width:34px;height:34px;transform:scale(0)}
.v2-pn--tl{left:calc(var(--pj,0px) - 1px);top:calc(var(--pi,0px) - 1px);transform-origin:calc(1px - var(--pj,0px)) calc(1px - var(--pi,0px));clip-path:path("M0 0H34V1.016A32 32 0 0 0 1.016 34H0Z")}
.v2-pn--tr{right:calc(var(--pj,0px) - 1px);top:calc(var(--pi,0px) - 1px);transform-origin:calc(33px + var(--pj,0px)) calc(1px - var(--pi,0px));clip-path:path("M34 0H0V1.016A32 32 0 0 1 32.984 34H34Z")}
.v2-pn--bl{left:calc(var(--pj,0px) - 1px);bottom:calc(var(--pi,0px) - 1px);transform-origin:calc(1px - var(--pj,0px)) calc(33px + var(--pi,0px));clip-path:path("M0 34H34V32.984A32 32 0 0 1 1.016 0H0Z")}
.v2-pn--br{right:calc(var(--pj,0px) - 1px);bottom:calc(var(--pi,0px) - 1px);transform-origin:calc(33px + var(--pj,0px)) calc(33px + var(--pi,0px));clip-path:path("M34 34H0V32.984A32 32 0 0 0 32.984 0H34Z")}
/* "What your guests will love": on desktop the heart's window sits beside the four (base.css's two columns); from 980 px
   down, where base.css stacks them, the heart comes first, in a window above the four */
@media (max-width:980px){.v2 .v2-gu .rb-gu__in{grid-template-columns:minmax(0,1fr);gap:clamp(40px,5vw,64px)}.v2 .v2-gu .rb-gu__ph{order:-1;height:clamp(360px,32vw,460px)}}
/* the windows' own backgrounds only stand in where the fixed layer isn't (off screen, or no IntersectionObserver): they
   scroll, so no fixed background is left on the page for the browser to repaint as it scrolls. The stage's foot and the
   night below it meet with no hairline (a fractional-pixel gap let the page's cream through, under the demo's link) */
.v2-open__gl,.v2-win,.v2 .v2-gu .rb-gu__ph,.v2-cta .rb-cta{background-attachment:scroll}
.rb{box-shadow:0 -3px 0 var(--night)}
@media (max-width:860px){.v2-ch .v2-win,.v2-ch.is-r .v2-win,.v2-ch .v2-tx,.v2-ch.is-r .v2-tx{grid-column:1/-1}.v2-tx,.v2-ch.is-r .v2-tx{grid-row:2;margin-top:28px}}
/* the lava sky, a review switch: ?sky=lava (rest2/lava.js, fetched only then). One stack per window near the screen, in
   its layer fixed to the screen: the night, then the three lights, each an <img> of a small painted picture over a box
   15% larger than the screen on every side; only transform and opacity change, so the compositor moves the pictures and
   nothing is painted again. The stack replaces the picture and its drift (at rest they are the same picture) */
.v2-fsky.is-lava{inset:0;width:auto;height:auto;transform:none;animation:none}
.lava-ready .v2-fsky.is-lava{background:none}
.lava-ready .v2-fsky.is-lava::before{content:none}
.lava{position:absolute;inset:0;overflow:hidden;pointer-events:none;contain:strict}
.lava__base{position:absolute;inset:0;width:100%;height:100%;display:block;max-width:none;will-change:transform}
.lava__mv{position:absolute;left:-15%;top:-15%;width:130%;height:130%;display:block}
.lava__sh{position:absolute;inset:0;display:block}
.lava__l{position:absolute;inset:0;width:100%;height:100%;display:block;max-width:none;user-select:none;-webkit-user-drag:none;will-change:transform}
.lava__alt{opacity:0;will-change:opacity}
