/* BeautyBooking v1.10 — hybrid K1 "Lada przy oknie" (built on v1.3 direction A; v1.4–v1.10 in DESIGN-RULES.md). */

@font-face{font-family:Cormorant;font-style:normal;font-weight:600;font-display:swap;src:url(assets/cormorant-normal-600.woff2) format('woff2')}

:root{
  --paper:#f7f6f2;--white:#fffefa;--ink:#253b33;--green:#3d6b5c;--sage:#eaf0e9;--body:#5b675f;--line:#dce1d8;--hover:#355545;--link:#9aa69d;
  --counter:#eeeee7;--app:#f2f2f6;--field:#7c8a7f;--error:#923f35;
  /* v1.9 (owner 25.09): Helvetica Neue for the whole page (the system face on Apple devices, Arial elsewhere); the
     wordmark keeps Cormorant. The green line keeps its thin italic (Helvetica Neue Thin Italic = weight 100). */
  --serif:'Helvetica Neue',Helvetica,Arial,sans-serif;--sans:'Helvetica Neue',Helvetica,Arial,sans-serif;--brand:Cormorant,'Cormorant Garamond',Georgia,serif;
  --ease-out:cubic-bezier(.16,1,.3,1);--ease-rcrut:cubic-bezier(.85,0,.15,1);
  --r-sm:8px;--r-md:12px;--r-lg:20px;--r-xl:28px;
  --shadow-ui:0 24px 48px rgb(37 59 51 / 10%);
  --shadow-lie:0 0 0 1px rgb(37 59 51 / 7%),1px 2px 3px rgb(52 62 54 / 12%),4px 8px 16px -4px rgb(52 62 54 / 12%),14px 30px 56px -14px rgb(52 62 54 / 26%);
}

*{box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:112px;-webkit-text-size-adjust:100%}
body{margin:0;background:var(--paper);color:var(--ink);font:400 16px/26px var(--sans);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
button,input,textarea,output{font:inherit;color:inherit}
button{cursor:pointer}
a{color:inherit;text-decoration:none}
button,a,input,summary{-webkit-tap-highlight-color:transparent}
img{display:block;max-width:100%}
svg{width:24px;height:24px;fill:currentColor;flex-shrink:0}
.svg-library{position:absolute;width:0;height:0;overflow:hidden}
h1,h2,h3,p,figure,ol,ul{margin:0}
h1,h2{font-family:var(--serif);font-weight:500;letter-spacing:-.03em;text-wrap:balance}
h1 em,h2 em{font-style:italic;font-weight:100;letter-spacing:-.02em;color:var(--green)}
h3{font-size:18px;line-height:26px;font-weight:600;letter-spacing:-.005em;text-wrap:balance}
p,li,figcaption{text-wrap:pretty}
h2{font-size:clamp(30px,2.75vw,40px);line-height:1.1}
.lead{font-size:18px;line-height:28px;color:var(--body);max-width:600px}
.wrap{width:calc(100% - 128px);max-width:1216px;margin-inline:auto}
.section{padding-block:112px 128px}
::selection{color:var(--white);background:var(--green)}
:where(a,button,input,textarea,summary,[tabindex]):focus-visible{outline:2px solid var(--green);outline-offset:3px}
[hidden]{display:none!important}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.skip-link{position:fixed;top:16px;left:16px;z-index:200;background:var(--ink);color:var(--white);padding:12px 16px;transform:translateY(-200%);border-radius:var(--r-sm)}
.skip-link:focus{transform:none}
.noscript-note{margin-top:24px;padding:16px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--white);font-size:14px;line-height:20px}
.noscript-note a,.faq a,.access-control a{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:4px;text-decoration-color:var(--link)}
.faq a:hover,.access-control a:hover{color:var(--green);text-decoration-color:currentColor}
a,button,summary{transition:color 400ms var(--ease-out),background-color 400ms var(--ease-out),border-color 400ms var(--ease-out),box-shadow 400ms var(--ease-out),transform 400ms var(--ease-out),text-decoration-color 400ms var(--ease-out)}

/* One action shape: a 48px pill, ink on paper, no arrows. */
.button{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:48px;padding:0 24px;border:1px solid transparent;border-radius:9999px;font-size:15px;line-height:20px;font-weight:600;white-space:nowrap}
.button-dark{background:var(--ink);color:var(--white);box-shadow:0 1px 0 rgb(255 255 255 / 12%) inset,0 6px 16px rgb(37 59 51 / 14%)}
.button-dark:hover{background:var(--hover);box-shadow:0 1px 0 rgb(255 255 255 / 12%) inset,0 10px 24px rgb(37 59 51 / 18%);transform:scale(1.02)}
/* v1.8 (beUI Button pattern): the same pill, a springy press. */
.button{transition:color 400ms var(--ease-out),background-color 400ms var(--ease-out),box-shadow 400ms var(--ease-out),transform 450ms cubic-bezier(.34,1.56,.64,1)}
.button:active{transform:scale(.96);box-shadow:none;transition-duration:400ms,400ms,120ms,120ms}
button:disabled,button[aria-disabled=true]{cursor:default;opacity:.45}

/* Navigation: */
.island{display:flex;align-items:center;gap:32px;width:max-content;max-width:calc(100% - 32px);margin:24px auto 0;padding:8px 8px 8px 24px;border:1px solid rgb(220 225 216 / 80%);border-radius:9999px;background:rgb(250 249 245 / 90%);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);box-shadow:0 10px 30px rgb(37 59 51 / 8%)}
.site-header{position:sticky;top:24px;z-index:30}
.brand{display:inline-flex;align-items:center;min-height:48px;font-family:var(--brand);font-size:27px;line-height:32px;font-weight:600;letter-spacing:-.01em;white-space:nowrap}
.desktop-nav{display:flex;align-items:center;gap:28px}
.desktop-nav a,.login-link{display:inline-flex;align-items:center;min-height:48px;font-size:14px;line-height:20px;font-weight:500}
.desktop-nav a:hover,.login-link:hover{color:var(--green)}
[aria-current=location]{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:8px;text-decoration-color:var(--green)}
/* v1.8: with JS one underline glides between the links instead of jumping (beUI Tabs "underline"). */
.desktop-nav{position:relative}
.nav-indicator{position:absolute;left:0;bottom:6px;width:1px;height:1px;background:var(--green);opacity:0;transform-origin:0 0;transition:transform 520ms cubic-bezier(.34,1.3,.64,1),opacity 300ms var(--ease-out);pointer-events:none}
.desktop-nav.has-indicator a[aria-current=location]{text-decoration-color:transparent}
/* After scrolling the island narrows: 64 → 52 px, the action 48 → 40 px. */
.site-header.island{transition:padding 400ms var(--ease-out),gap 400ms var(--ease-out),box-shadow 400ms var(--ease-out)}
.site-header .brand{transition:font-size 400ms var(--ease-out),min-height 400ms var(--ease-out)}
.site-header .nav-cta,.site-header .login-link,.site-header .desktop-nav a{transition:min-height 400ms var(--ease-out),color 400ms var(--ease-out),background-color 400ms var(--ease-out),box-shadow 400ms var(--ease-out),transform 450ms cubic-bezier(.34,1.56,.64,1)}
.site-header.is-compact{padding:6px 6px 6px 20px;gap:24px}
.site-header.is-compact .brand{font-size:23px;min-height:40px}
.site-header.is-compact .nav-cta,.site-header.is-compact .login-link,.site-header.is-compact .desktop-nav a{min-height:40px}
.nav-actions{display:flex;align-items:center;gap:16px}
.nav-cta{font-size:14px;padding:0 20px}
.cta-short{display:none}
.menu-toggle,.menu-close{position:relative;display:grid;place-items:center;width:48px;height:48px;padding:0;border-radius:9999px;border:1px solid var(--line);background:transparent;flex-shrink:0}
.menu-toggle:hover,.menu-close:hover{background:var(--sage)}
.menu-toggle span,.menu-close span{position:absolute;left:14px;right:14px;top:calc(50% - .75px);height:1.5px;background:var(--ink);transition:transform 500ms var(--ease-out)}
.menu-toggle span:first-child,.menu-close span:first-child{transform:translateY(-4px)}
.menu-toggle span:last-child,.menu-close span:last-child{transform:translateY(4px)}
.menu-toggle[aria-expanded=true] span:first-child,.menu-dialog.is-open .menu-close span:first-child{transform:rotate(45deg)}
.menu-toggle[aria-expanded=true] span:last-child,.menu-dialog.is-open .menu-close span:last-child{transform:rotate(-45deg)}
.menu-dialog{position:fixed;inset:0;width:100%;max-width:none;height:100dvh;max-height:none;margin:0;padding:0 0 32px;border:0;background:rgb(247 246 242 / 94%);-webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);color:var(--ink);opacity:0;transition:opacity 500ms var(--ease-out);overflow:auto;overscroll-behavior:contain}
.menu-dialog::backdrop{background:transparent}
.menu-dialog[open]{display:flex;flex-direction:column}
.menu-dialog.is-open{opacity:1}
.menu-dialog.is-closing{opacity:0}
.menu-dialog-top{flex:none}
.menu-dialog-links{width:100%;max-width:680px;margin:auto;padding:48px 24px}
.mobile-menu{display:flex;flex-direction:column;align-items:flex-start;gap:12px}
.menu-item{display:block;overflow:hidden;padding:8px;margin:-8px;max-width:100%}
.mobile-menu a{display:block;font-family:var(--serif);font-size:36px;line-height:42px;font-weight:500;letter-spacing:-.02em;padding:6px 0;transform:translateY(40px);opacity:0;transition:opacity 600ms var(--ease-out),transform 600ms var(--ease-out),color 400ms var(--ease-out);transition-delay:var(--menu-delay,100ms)}
.mobile-menu a:hover{color:var(--green)}
.menu-dialog.is-open .mobile-menu a{transform:none;opacity:1}
.mobile-menu .menu-login{margin-top:20px}
.mobile-menu .menu-login a{font-family:var(--sans);font-size:16px;line-height:24px;font-weight:600;min-height:48px;display:inline-flex;align-items:center;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:6px}
.menu-caption{text-align:center;font-size:14px;line-height:20px;color:var(--body);padding-inline:24px}
body:has(dialog[open]){overflow:hidden}

/* ---------- Hero: text on the left, the counter scene on the right (hybrid K1) ---------- */
/* v1.10 (critic v1.10 P2-5, owner 25.09): wide stone surfaces get a 3344 px copy of the same slab on 2x screens
   (Lanczos 2x + light unsharp: no new detail, but no bilinear softening; +42 KB, LCP measured). */
.hero{position:relative;isolation:isolate;margin-top:-90px;overflow:clip;background:url(assets/counter-v18-1672.webp) 50% 0/cover no-repeat,var(--counter);background:image-set(url(assets/counter-v18-1672.webp) 1x,url(assets/counter-v110-3344.webp) 2x) 50% 0/cover no-repeat,var(--counter)}
/* v1.10 round 7 (critic v1.10 r4 P1-1, owner 26.09): the hero's counter has the window's light: a wide soft wedge from the
   upper left behind the text, falling off about 12% toward the lower right (ChatGPT Images, order 17: an edit of the same
   slab). Below 1101 px the portrait counter stays. */
.hero{background:url(assets/counter-hero-light-1672.webp) 50% 0/cover no-repeat,var(--counter);background:image-set(url(assets/counter-hero-light-1672.webp) 1x,url(assets/counter-hero-light-3344.webp) 2x) 50% 0/cover no-repeat,var(--counter)}
/* The counter fades into paper under the fold instead of a hard edge. */
.hero::after{content:'';position:absolute;inset:auto 0 0;height:96px;z-index:-1;background:linear-gradient(rgb(247 246 242 / 0),var(--paper))}
/* Phone width follows the window height: */
.hero-inner{--pw:clamp(323px,calc((100svh - 210px) * .4776),372px);position:relative;display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);column-gap:32px;align-items:center;width:calc(100% - 128px);max-width:1216px;min-height:max(760px,min(100svh,980px));margin-inline:auto;padding-block:112px 48px}
/* Short windows (1280x800): 16px less on top keeps the phone off the bottom edge. */
@media (min-width:1101px) and (max-height:840px){.hero-inner{padding-top:96px}.prop-card{left:calc(var(--pw) * 1.0);top:calc(var(--pw) * .87)}}
/* r11 (S1, critic r21 P1-1): under 840 px of height the phone is 6% smaller (294 px: caption clear of the island, frame ≥ 16 px above the window's edge, UI ≈ 0.70) and the card pokes out ≤ 24 px, QR whole. */
@media (min-width:1101px) and (max-height:839px){.hero-inner{--pw:284px}.hero .hero-scene{margin-top:77px}}
/* r9 (critic medium r18 P2-5): below 840 px of height the card moves 0.15 pw up and 0.05 pw left (it still touches, never slides under, the phone). */
.hero-copy{position:relative;z-index:4;max-width:500px}
.hero h1{font-size:min(54px,calc((min(100vw - 128px,1216px) - 32px) * .0448));line-height:1.06;letter-spacing:-.03em}
.hero h1 em{display:block}
/* v1.10 (owner 25.09, critic v1.10 P2-5): the hero's green line in Light Italic (300); Thin (100) on the stone was at the
   edge of legibility. The other green lines stay Thin. */
.hero h1 em{font-weight:300}
/* v1.12 r7 (critic medium r16 P1-2; rule 19a): the green line keeps to one line. Its size follows the text column
   (the line is ~10.5 em wide in Helvetica Neue Light Italic; /11.4 leaves room for Arial on Windows). */
.hero h1 em{font-size:min(1em,(min(100vw - 128px,1216px) - 32px) * 5 / 12 / 11.4)}
.hero-description{max-width:440px;margin-top:24px;font-size:18px;line-height:28px;color:var(--body)}
.hero-actions{display:flex;align-items:center;gap:20px;margin-top:32px;flex-wrap:wrap}
.hero-note{font-size:14px;line-height:20px;color:var(--body)}
.hero-note strong{font-weight:600;color:var(--green)}
/* v1.12 r2 (critic medium v1.12 P2-4): the decisive fact reads as a fact, not as fine print (same words, owner's note). */
/* r11 (S1, critic r21 P2-2; replaces r7's 18 px): the note in one size; "0% prowizji" stands out by weight and colour only. */
.hero-note{font-size:15px;line-height:22px;max-width:440px}
/* r18 (S1, critic r28 P3-1): the note no wider than the description's measure. */
.hero-note strong{font-size:inherit;line-height:inherit}
.nowrap{white-space:nowrap}

/* One scale for every object: --pw is the phone width (5.27 px per mm at 372 px). */
.hero-scene{position:relative;align-self:start;height:calc(var(--pw) * 2.094 + 16px);margin-top:16px}
.hero-device{position:absolute;z-index:3;left:0;top:0;width:var(--pw);margin:0}
.device{position:relative;display:block;width:100%;aspect-ratio:372/779;padding:0;border:0;background:transparent;border-radius:calc(var(--pw) * .163);cursor:zoom-in}
.device-screen{position:absolute;left:calc(var(--pw) * .03226);top:calc(var(--pw) * .03226);width:calc(var(--pw) * .93548);height:auto;border-radius:calc(var(--pw) * 0.1314);background:var(--app)}
/* Photographed phone (ChatGPT Images, same counter and window; v1.7: lies flat with a short contact shadow,
   squashed to the real display aspect, offsets from assets-work/phone-v17/device-photo.json): */
.device-body{position:absolute;left:calc(var(--pw) * -0.0317);top:calc(var(--pw) * -0.0519);width:calc(var(--pw) * 1.1256);max-width:none;height:auto;pointer-events:none}
.device:hover .device-body{filter:brightness(1.02)}
.hero-device figcaption{position:absolute;left:0;top:auto;bottom:calc(100% + var(--pw) * .0519 + 11px);width:max-content;font-size:13px;line-height:18px;font-weight:500;color:var(--green)}
/* r18 (S1, critic r28 P3-3): the caption in the labels' green at every width (was ink on desktop and tablets). */
/* r13 (S1, critic r23 P2-1, P3-3): the caption on the visible metal frame's left edge (the device box; the photo's box also holds the side buttons), in the headline's ink. */
/* r11 (S1, critic r21 P1-2): one place for the caption at every width: right above the frame's top left corner, aligned
   to the frame's left edge, 11 px above it, 13 px / 500 (on phones on the text's axis instead). From 1101 px the scene
   stands 34 px lower so the caption clears the island. */
/* r16 (S1, critic r26 P3-1): from 1101 px a wider text column (5.3 : 6.7, ≈ 523 px at 1440) and a larger headline (56 px),
   the green line still in one line; the headline column still ends ≥ 64 px before the frame. (5.6 : 6.4 with 58 px took the
   phone down to ~286 px: the product's legibility wins over 2 px of headline.) */
@media(min-width:1101px){
  .hero-inner{grid-template-columns:minmax(0,5.3fr) minmax(0,6.7fr)}
  .hero-copy{max-width:530px}
  .hero h1{font-size:min(56px,calc((min(100vw - 128px,1216px) - 32px) * .0473))}
  .hero h1 em{font-size:min(1em,(min(100vw - 128px,1216px) - 32px) * 5.3 / 12 / 11.4)}
}
@media(min-width:1101px){.hero-scene{margin-top:64px;margin-left:44px}.hero-inner{min-height:calc(max(760px,min(100svh,980px)) + 96px);padding-bottom:144px}}
/* r15 (S1, critic r25 P3-2): the hero is 96 px taller than the first screen, so its fade into the paper starts under the window's edge. */
/* r14 (S1, critic r24 P2-1, P2-2, P3-2; replaces r13's −20 px): from 1280 px the card keeps ≥ 16 px from the visible frame in
   every phase of its drift and pointer lean (38 px at rest; drift −9 px, lean −12 px) and bleeds clearly off the window
   (≥ 40 px), its name and QR inside; the phone's scale follows the width left for phone + gap + card (1440: 321 px, frame
   ≥ 32 px above the window's edge). */
@media(min-width:1280px){
  .hero-inner{--pw:min(clamp(323px,calc((100svh - 210px) * .4776),372px),(100vw - 12px - (100vw - min(100vw - 128px,1216px)) / 2 - (min(100vw - 128px,1216px) - 32px) * 5.3 / 12 - 76px) / 2.35)}
  /* r18 (S1, critic r28 register change R7/R8): the card slides ~20 px under the phone's metal (only its blank left
     margin is hidden), the phone casting a contact shadow on it; the whole card in the window with ≥ 32 px to the right.
     So that the name keeps ≥ 16 px from the metal in every phase, the card here drifts and leans only vertically. */
  .hero-scene .prop-card{left:calc(var(--pw) * .948 - 5px);top:calc(var(--pw) * .73);--depth:0px}
  .hero-scene .prop-card .prop-drift{--drift:drift-paper-y}
  .hero-device .device-body{filter:drop-shadow(8px 4px 10px rgb(52 40 28 / .22))}
  /* r15 (S1, critic r25 P2-3): the card's middle at the 13:45–15:30 rows (it lay below 15:30); the window's edge cuts the print halfway between the QR and the card's right edge (the phone's scale follows) */
}
@media(min-width:1280px) and (max-height:839px){.hero-inner{--pw:min(284px,(100vw - 12px - (100vw - min(100vw - 128px,1216px)) / 2 - (min(100vw - 128px,1216px) - 32px) * 5.3 / 12 - 76px) / 2.35,(100svh - 172px) / 2.24)}}
/* r12 (S1, critic r22 P2-1): the scene 44 px to the right, so the headline's column ends ≥ 64 px before the frame; the card may leave the window, its QR stays in. */

/* v1.8 (critic P1-1, owner 25.09): the caption says whose view it is, so the salon's day with other clients' names
   is never read as what a client sees. It stands beside the phone's top in the stage labels' voice: under the phone it
   fell below the first screen at 900 and 800 px windows. Phones: above the phone. */

/* Props: outer layer follows the pointer, inner layer drifts with RCRUT keyframes. */
.scene-prop{position:absolute;z-index:1;pointer-events:none;transform:translate3d(calc(var(--scene-mx,0) * var(--depth,10px)),calc(var(--scene-my,0) * var(--depth,10px)),0);transition:transform .9s var(--ease-out)}
.hero[data-motion=paused] .scene-prop{transform:none}
.prop-drift{animation:var(--drift) var(--dur) var(--ease-rcrut) var(--delay,0s) infinite normal both;animation-play-state:paused}
[data-motion=running] .prop-drift{animation-play-state:running}
.scene-prop img{width:100%;height:auto}
/* The card lies beside the phone (never under it, because it drifts). */
/* v1.8: the card is a stack, the same as in Figma (BB-Landing, "02 · Scena — warstwy"): blank card photo, the production
   print (one file, rotated with the card), shading (multiply) and highlight (screen). A new card design = a new print file.
   The light maps are blend-neutral outside the face and masked by the photo's alpha, so a cut-out card never shows a box. */
.card-stack{position:relative;display:block;width:100%;aspect-ratio:837/595}
.card-stack.card-step1{aspect-ratio:923/692}
.card-stack img{position:absolute;display:block;max-width:none}
.card-stack .card-base,.card-stack .card-shade,.card-stack .card-glow{inset:0;width:100%;height:100%}
.card-stack .card-print{object-fit:cover;transform:rotate(8.55deg);border-radius:3.013%/4.85%}
.card-stack .card-shade{mix-blend-mode:multiply}
.card-stack .card-glow{mix-blend-mode:screen}
.card-land .card-print{left:3.7634%;top:9.042%;width:87.2401%;height:76.2353%}
.card-step1 .card-print{left:10.455%;top:18.6127%;width:79.1116%;height:65.5491%}
.card-land .card-shade,.card-land .card-glow{-webkit-mask:url(assets/card-land-base-v18b.webp) 0 0/100% 100%;mask:url(assets/card-land-base-v18b.webp) 0 0/100% 100%}
.prop-card{--depth:12px;--drift:drift-paper;--dur:27s;width:calc(var(--pw) * 1.3722);left:calc(var(--pw) * 1.05);top:calc(var(--pw) * 1.02);z-index:2}
/* v1.11 (round 9, direction A): no scissors in the hero. The phone and the card are the proof; the scissors only said
   "beauty", which the card and the lead already say, and at 432 px they competed with the phone. */

@keyframes drift-paper-y{0%,18%{transform:none}33%,51%{transform:translate(0,5px) rotate(.3deg)}66%,84%{transform:translate(0,9px) rotate(-.2deg)}100%{transform:none}}
@keyframes drift-paper{0%,18%{transform:none}33%,51%{transform:translate(-9px,5px) rotate(.5deg)}66%,84%{transform:translate(4px,10px) rotate(-.35deg)}100%{transform:none}}
@keyframes drift-keyboard{0%,20%{transform:none}36%,54%{transform:translate(11px,-6px) rotate(-.8deg)}70%,86%{transform:translate(-6px,7px) rotate(.55deg)}100%{transform:none}}

/* Window light: */
.hero-light{--pw:clamp(323px,calc((100svh - 210px) * .4776),372px);--inner:min(100% - 128px,1216px);--phone-right:calc((100% - var(--inner)) / 2 + (var(--inner) - 32px) * 5.3 / 12 + 32px + 44px + var(--pw));position:absolute;inset:0;z-index:2;overflow:hidden;pointer-events:none;mix-blend-mode:multiply;opacity:.26;-webkit-mask-image:linear-gradient(90deg,transparent var(--phone-right),#000 calc(var(--phone-right) + var(--pw) * .3));mask-image:linear-gradient(90deg,transparent var(--phone-right),#000 calc(var(--phone-right) + var(--pw) * .3))}
.hero-light video{position:absolute;top:0;right:0;width:auto;height:100%;min-width:100%;object-fit:cover;object-position:100% 0}
/* r16: the leaf light covers the first screen only (the hero is now 96 px taller than the window). */
@media(min-width:1101px){.hero .hero-light{bottom:auto;height:100svh}}

/* Entrance: */
@keyframes text-in{from{opacity:0;transform:translateY(8px)}}
.motion-ready .hero-copy>*{animation:text-in 700ms var(--ease-out) both}
.motion-ready .hero-copy>:nth-child(2){animation-delay:90ms}
.motion-ready .hero-copy>:nth-child(3){animation-delay:180ms}
/* v1.9: Text Blur Reveal (AI Canvas): each word rises 22 px out of a 14 px blur, 650 ms, 100 ms apart; the
   description and the action follow the last word. First visit of a session only (the wake flag). */
@keyframes blur-in{from{opacity:0;transform:translateY(22px);filter:blur(14px)}}
.motion-ready .hero-copy>h1.blur-reveal{animation:none}
.motion-ready .hero h1.blur-reveal .w{display:inline-block;animation:blur-in 650ms cubic-bezier(.21,.47,.32,.98) both}
.motion-ready .hero-copy:has(.blur-reveal)>:nth-child(2){animation-delay:750ms}
.motion-ready .hero-copy:has(.blur-reveal)>:nth-child(3){animation-delay:850ms}

/* v1.5 phone wake: */
.device-glint{display:none;position:absolute;left:calc(var(--pw) * -0.0317);top:calc(var(--pw) * -0.0519);width:calc(var(--pw) * 1.1256);aspect-ratio:669/1331;pointer-events:none;mix-blend-mode:screen;background:linear-gradient(112deg,transparent 44%,rgb(255 253 246 / .22) 47.5%,rgb(255 253 246 / .7) 49.2%,rgb(255 253 246 / .18) 51%,transparent 55%) 110% 0/320% 100% no-repeat;opacity:0}
/* v1.10 round 7 (critic v1.10 r4 idea 2, owner 26.09): the window's reflection on the glass is its own layer
   (ChatGPT Images, order 16: the reflection alone on black, mapped onto the body layer), added with screen at most ~0.12
   over the list and moved 10 px against the screen while the hero passes, as real glass does. Clipped to the glass. */
.device-reflect{position:absolute;left:calc(var(--pw) * -0.0317);top:calc(var(--pw) * -0.0519);width:calc(var(--pw) * 1.1256);aspect-ratio:669/1331;pointer-events:none;mix-blend-mode:screen;opacity:.3;clip-path:inset(calc(var(--pw) * .0841) calc(var(--pw) * .1262) calc(var(--pw) * .1262) calc(var(--pw) * .0639) round calc(var(--pw) * .1314))}
.device-reflect img{display:block;width:100%;height:auto}
@supports (animation-timeline:view()){.motion-ready .device-reflect img{--par:10px;animation:parallax linear both;animation-range:cover;animation-timeline:--hero-view}}
.glint-glass{clip-path:inset(calc(var(--pw) * .0841) calc(var(--pw) * .1262) calc(var(--pw) * .1262) calc(var(--pw) * .0639) round calc(var(--pw) * .1314))}
.glint-frame{-webkit-mask:url(assets/device-photo-v17.webp) 0 0/100% 100%;mask:url(assets/device-photo-v17.webp) 0 0/100% 100%}
@keyframes screen-wake{from{filter:brightness(.1) saturate(.4)}60%{filter:brightness(.92) saturate(.95)}}
@keyframes glint-sweep{0%{opacity:1;background-position:110% 0}85%{opacity:1}100%{opacity:0;background-position:-10% 0}}
/* v1.8 (owner, 25.09): "Marta books herself". The rows below 12:45 make room and Marta's row appears next to her card.
   Layers are cut from two real renders of the same frame (Figma 5636:2189 before, 5599:2057 after); the end state is
   the hero screenshot pixel for pixel, then the layers hide. The one exception to "the UI stands still".
   v1.10 (critic v1.9 P1-1, owner 25.09): one directed event after the headline instead of a fourth effect inside it.
   A window glint crosses Marta's card, 150 ms later her visit appears (--m-delay: 2.1 s after load from 1101 px;
   on tablets and phones when the list is on screen). Once per session; a click on the card replays it (desktop).
   JS: moment-armed shows the before state, moment-play runs it, moment-late = played after the wake (no wake here). */
.moment{display:none}
@keyframes moment-slide{from{transform:translateY(-22.3776%)}to{transform:none}}
@keyframes moment-fade{to{opacity:0}}
@keyframes moment-out{from,to{visibility:hidden}}
.hero.moment-armed .moment{display:block;position:absolute;left:calc(var(--pw) * .03226);top:calc(var(--pw) * .03226);width:calc(var(--pw) * .93548);aspect-ratio:393/852;border-radius:calc(var(--pw) * 0.1314);overflow:hidden;pointer-events:none}
.motion-ready:not(.phone-awake) .hero.moment-armed .moment{animation:screen-wake 1300ms cubic-bezier(.3,0,.2,1) 150ms both}
.motion-ready:not(.phone-awake) .hero.moment-armed.moment-play:not(.moment-late) .moment{animation:screen-wake 1300ms cubic-bezier(.3,0,.2,1) 150ms both,moment-out 1ms linear calc(var(--m-delay) + 2100ms) forwards}
.motion-ready .hero.moment-armed.moment-play.moment-late .moment{animation:moment-out 1ms linear calc(var(--m-delay) + 2100ms) forwards}
.moment img{position:absolute;display:block;max-width:none}
.moment-list{position:absolute;left:4.0712%;top:43.8967%;width:91.8575%;height:33.5681%;overflow:hidden}
.moment-slot{left:0;top:0;width:100%;height:22.3776%}
.moment-block{left:0;top:22.3776%;width:100%;height:100%;transform:translateY(-22.3776%)}
.moment-fab{left:80.916%;top:67.3709%;width:18.3206%;height:auto}
.moment-axis{left:35.6234%;top:83.0986%;width:6.1069%;height:auto}
.hero.moment-play .moment-block{animation:moment-slide 620ms cubic-bezier(.16,1,.3,1) var(--m-delay) both}
.hero.moment-play .moment-slot,.hero.moment-play .moment-axis{animation:moment-fade 560ms cubic-bezier(.16,1,.3,1) calc(var(--m-delay) + 420ms) both}
/* v1.12 r6 (critic medium r15 P1-2, idea 1): a scene with a gap. The rows slide apart (620 ms) and the empty 12:45 stands
   for ~0.8 s; then the window glint crosses Marta's card and, 150 ms later, her row as it fills the gap. All of it
   inside the camera's hold on the row and the card (28–80% of 4 s from 1101 px). */
.hero.moment-play .moment-slot,.hero.moment-play .moment-axis{animation-delay:calc(var(--m-delay) + 1420ms)}
/* v1.10 (critic v1.10 P1-1, owner 25.09): the camera leans in. The whole scene grows 3.5% around Marta's row (12:45,
   at 1.0 pw from the phone's top) with the RCRUT curve, holds while her visit appears, then settles back. Scale is its
   own property, so the pointer layer and the drift (transform) and the parallax (translate) keep working. */
@keyframes moment-push{0%{scale:1}38%,62%{scale:1.035}100%{scale:1}}
/* v1.10 round 7 (critic v1.10 r4 idea 1, owner 26.09): one event of light joins the card and the calendar. As Marta's
   row lands, the window glint that crossed her card 150 ms earlier crosses the glass along that row (colourless, peak
   0.45, a band one row high); from 1101 px the camera leans in to 5% and ends on the row. */
@keyframes moment-push-wide{0%{scale:1}38%,62%{scale:1.05}100%{scale:1}}
.row-glint{display:none;position:absolute;left:calc(var(--pw) * .03226);top:calc(var(--pw) * (.03226 + 2.028 * .439));width:calc(var(--pw) * .93548);height:calc(var(--pw) * 2.028 * .075);pointer-events:none;mix-blend-mode:screen;background:linear-gradient(100deg,transparent 40%,rgb(255 253 246 / .14) 46%,rgb(255 253 246 / .45) 50%,rgb(255 253 246 / .14) 54%,transparent 60%) 110% 0/300% 100% no-repeat;opacity:0}
/* r9 (critic medium r18 P2-2, idea 2): while the camera holds on Marta's row, the other rows dim under a veil (a
   transparent layer over the screen, no pixel of the screenshot changes); the 12:45 row stays at full brightness, then all returns. */
/* r10 (critic medium r19 P2-3): from 1201 px too, the island's CTA folds away while the hero's button is on screen (one dark button in the first screen). */
.site-header.hero-cta-on-screen .nav-cta{max-width:0;padding-inline:0;border-width:0;opacity:0;visibility:hidden}
.row-trace{position:absolute;left:calc(var(--pw) * .03226);top:calc(var(--pw) * (.03226 + 2.028 * .439));width:calc(var(--pw) * .93548);height:calc(var(--pw) * 2.028 * .075);pointer-events:none;mix-blend-mode:screen;background:linear-gradient(100deg,rgb(255 253 246 / .18) 0,rgb(255 253 246 / .1) 45%,rgb(255 253 246 / 0) 85%);opacity:0}
/* r13 (S1, critic r23 P2-2): after the moment, and at once with reduced motion or on a later visit, Marta's row keeps a
   faint trace of it in the light on the glass (a pale green tint over the row, multiply; no text, no UI drawn). */
.hero.moment-play .row-trace{animation:trace-in 7000ms var(--ease-out) calc(var(--m-delay) + 2000ms) both}
@keyframes trace-in{0%{opacity:0}10%,55%{opacity:1}100%{opacity:0}}
/* r15 (S1, critic r25 P2-2; replaces r13's lasting tint): the trace is light on the glass that fades back to the clean screenshot within ~7 s; without the moment (reduced motion, later visits) the screen stays clean. */
.device::after{content:'';position:absolute;left:calc(var(--pw) * .03226);top:calc(var(--pw) * .03226);width:calc(var(--pw) * .93548);aspect-ratio:393/852;border-radius:calc(var(--pw) * .1314);pointer-events:none;opacity:0;background:linear-gradient(rgb(244 244 247 / 0) 0 33.4%,rgb(244 244 247 / 28%) 33.5% 43.8%,rgb(244 244 247 / 0) 43.9% 51.4%,rgb(244 244 247 / 28%) 51.5% 77%,rgb(244 244 247 / 0) 77.1% 100%)}
/* r11 (S1 P2-4): the veil covers only the visit list (20%), never the status bar, the header or the week strip. */
@keyframes row-focus{0%{opacity:0}18%,78%{opacity:1}100%{opacity:0}}
.hero.moment-play .device::after{animation:row-focus 1700ms cubic-bezier(.3,0,.2,1) calc(var(--m-delay) + 1300ms) both}
.hero.moment-play .row-glint{display:block;animation:glint-sweep 800ms cubic-bezier(.45,0,.2,1) calc(var(--m-delay) + 1380ms) both}
.hero-scene{--m-origin-x:calc(var(--pw) * .55)}
.hero.moment-play .hero-scene{transform-origin:var(--m-origin-x) var(--pw);animation:moment-push 2800ms var(--ease-rcrut) calc(var(--m-delay) - 500ms) both}
/* v1.12 (critic MAX r10 P2-4): from 1101 px the camera stays on Marta's row ~1.3 s after it lands (3.6 s, hold 30–78%). */
@keyframes moment-push-wide-hold{0%{scale:1}28%,80%{scale:1.08}100%{scale:1}}
@media(min-width:1101px){.hero.moment-play .hero-scene{animation-name:moment-push-wide-hold;animation-duration:4000ms}}
/* v1.12 r2 (critic medium v1.12 idea 3): 8% and ~2 s on Marta's row (the 2x export stays sharp at 1.08). */
/* v1.12 r3 (critic MAX r12 P2-1): up to 1600 px the 8% push carried the card's QR past the window's right edge for ~2 s.
   There the camera leans in 3.5% around a point right of the card (2.05 pw from the phone's left edge), so the QR stays
   in the window and the phone does not reach the text; the hold on Marta's row is unchanged. */
@keyframes moment-push-narrow-hold{0%{scale:1}28%,80%{scale:1.035}100%{scale:1}}
@media(min-width:1101px) and (max-width:1600px){.hero.moment-play .hero-scene{--m-origin-x:calc(var(--pw) * 2.12);animation-name:moment-push-narrow-hold}}
/* v1.10 round 7 (critic v1.10 r4 idea 4): the card's highlight follows the pointer a little, like the window's
   reflection when you lean over the counter (4% x 3% of the card, the mask stays on the card). */
@media(min-width:1101px) and (hover:hover) and (pointer:fine){
  .prop-card .card-glow{--gx:calc(var(--scene-mx,0) * var(--pw) * 1.3722 * .04);--gy:calc(var(--scene-my,0) * var(--pw) * .975 * .03);translate:var(--gx) var(--gy);-webkit-mask-position:calc(var(--gx) * -1) calc(var(--gy) * -1);mask-position:calc(var(--gx) * -1) calc(var(--gy) * -1);transition:translate .9s var(--ease-out),-webkit-mask-position .9s var(--ease-out),mask-position .9s var(--ease-out)}
}
/* The card glint: window light (screen) masked by the card photo's alpha, like .glint-frame on the phone. */
.card-glint{position:absolute;inset:0;display:none;pointer-events:none;mix-blend-mode:screen;background:linear-gradient(112deg,transparent 38%,rgb(255 253 246 / .2) 45%,rgb(255 253 246 / .75) 50%,rgb(255 253 246 / .2) 55%,transparent 62%) 110% 0/300% 100% no-repeat;opacity:0;-webkit-mask:url(assets/card-land-base-v18b.webp) 0 0/100% 100%;mask:url(assets/card-land-base-v18b.webp) 0 0/100% 100%}
.hero.moment-play .card-glint{display:block;animation:glint-sweep 1100ms cubic-bezier(.45,0,.2,1) calc(var(--m-delay) + 1000ms) both}
@media(min-width:1101px) and (hover:hover){.hero.moment-replayable .prop-card{pointer-events:auto;cursor:pointer}}
/* v1.10 (owner 25.09, "ruch także na telefonie"): the screen wakes on every width (was from 761 px). */
.motion-ready .device-screen{animation:screen-wake 1300ms cubic-bezier(.3,0,.2,1) 150ms both}
.motion-ready.phone-awake .device-screen{animation:none}
/* v1.11 (critic MAX r6 P2-6): the entrance glint ends with the last word (~1.35 s), before the camera push at 1.6 s. */
.motion-ready .device-glint{display:block;animation:glint-sweep 1100ms cubic-bezier(.45,0,.2,1) 250ms both}
/* Phones: glass glint only. The frame glint is masked by the body photo, and a CSS mask fetches it a second time
   (CORS mode): 50 KB that delayed the hero counter, the LCP element on phones. */
@media(max-width:760px){.motion-ready .glint-frame{display:none}}

/* ---------- Private access: one stage, four real steps ---------- */
.access{background:var(--paper)}
.access-grid{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);grid-template-areas:"stage head" "stage list";column-gap:88px;align-items:start}
.access-head{grid-area:head}
.access-head .lead{margin-top:24px}
/* v1.5: the stage is the hero counter (cached file); the card melts into it, screens lie on it. */
.access-stage{grid-area:stage;position:sticky;top:112px;display:grid;min-height:min(640px,calc(100svh - 160px));padding:40px;border-radius:var(--r-xl);background:url(assets/counter-v18-1672.webp) 38% 60%/cover no-repeat,var(--counter);background:image-set(url(assets/counter-v18-1672.webp) 1x,url(assets/counter-v110-3344.webp) 2x) 38% 60%/cover no-repeat,var(--counter);box-shadow:inset 0 0 0 1px rgb(37 59 51 / 5%)}
/* No ghosts: old frame leaves fast (140 ms), the new one starts only then (v1.8: the 40 ms delay let both show). */
.stage-item{grid-area:1 / 1;display:grid;align-content:center;justify-items:center;gap:16px;margin:0;opacity:0;visibility:hidden;transform:translateY(10px) scale(.985);transition:none}
.stage-item.is-leaving{transition:opacity 140ms ease-in,visibility 0s linear 140ms,transform 0s linear 140ms}
.stage-item.is-active{opacity:1;visibility:visible;transform:none;transition:opacity 300ms var(--ease-out) 140ms,transform 480ms var(--ease-out) 140ms,visibility 0s}
.stage-label{font-size:13px;line-height:18px;font-weight:600;color:var(--green)}
/* v1.10 round 5 (critic v1.10 r3 P2-1, owner 26.09): no rounded panel with an outline ("a slide"); the stage is the
   counter running off the window's left edge, like the pricing counter. The content box keeps its width, so the cqw
   geometry holds; absolute layers add the bleed. */
.access-stage{--bleed:calc((100vw - min(100vw - 128px,1216px)) / 2);container-type:inline-size;overflow:hidden;margin-left:calc(var(--bleed) * -1);padding-left:calc(40px + var(--bleed));border-radius:0;box-shadow:none}
@media(max-width:1100px){.access-stage{--bleed:48px}}
/* v1.10 round 7 (critic v1.10 r4 idea 5, owner 26.09: "one counter, one camera"). From 901 px the four steps are one
   long piece of the counter that the camera slides along (RCRUT, stops on each step): the salon's silver phone, Marta's
   card between the phones, the client's graphite phone, each screen real and under its glass. Nothing fades through
   anything and the card never moves under a phone; step 3 to 4 changes only the client's screen (a short wake).
   Units: cqw = 1% of the stage's content width (578 px at 1440); pw 65.74cqw = 380 px (UI 0.9). The strip starts at
   the content's left edge; camera 1 centres the card (with the edges of both phones), camera 2 shows the salon phone
   with the named half of the card, camera 3 the client phone with the QR half. */
.access-stage{--pw:65.74cqw;--py:calc(20% - var(--pw) * .03226);--card-x:74cqw;--client-x:158cqw;--cam1:calc(-66.8cqw - var(--bleed) / 2);--cam2:0px;--cam3:calc(-128.4cqw + 20px)}
.stage-strip{position:absolute;top:0;bottom:0;left:calc(var(--bleed) + 40px);width:240cqw;z-index:0;translate:var(--cam1) 0;transition:translate 950ms var(--ease-rcrut);pointer-events:none}
.stage-strip::before{content:'';position:absolute;top:0;bottom:0;left:calc(-1 * (var(--bleed) + 40px) - 10cqw);right:-10cqw;background:url(assets/counter-v18-1672.webp) 50% 60%/cover no-repeat,var(--counter);background:image-set(url(assets/counter-v18-1672.webp) 1x,url(assets/counter-v110-3344.webp) 2x) 50% 60%/cover no-repeat,var(--counter)}
/* v1.11 r2 (critic medium v1.11 P1-3): at step 1 the camera stands closer to Marta's card (scale 1.24 around the card's
   centre), so the sleeping phones leave the frame but for their metal edges; it pulls back as it travels to step 2. */
.stage-strip{transform-origin:119cqw 50%;transition:translate 950ms var(--ease-rcrut),scale 950ms var(--ease-rcrut)}
.access-stage[data-step="1"] .stage-strip{scale:1.24}
/* v1.12 r8 (critic medium r17 P1-2): step 1 is a close-up of the card, not the hero's postcard again: scale 1.6 around
   the card's left third, name and number sharp (1100 px print), the QR cut by the frame's edge. */
.access-stage[data-step="1"] .stage-strip{scale:1.6;transform-origin:86cqw 50%}
/* v1.12 r2 (critic medium v1.12 P1-1): at step 1 the client's sleeping phone lies further along the counter, out of the
   frame (it was a black slab at the frame's right edge, the heaviest shape on the page). It slides back with the camera
   move, while it is outside the frame of step 2, and is in place before the camera reaches it at step 3. */
.access-stage[data-step="1"]{--client-x:176cqw}
/* r10 (critic medium r19 P1-2): at step 4 the client's phone lies lower, so the window's lower edge cuts its screen right
   under the last row of the service menu (the real screenshot is empty below it). */
@media(min-width:901px){.access-stage[data-step="4"] :is(.strip-screen-pin,.strip-screen-booking,.strip-reflect-klientka,.strip-body-klientka){translate:0 calc(80svh - var(--pw) * 1.36)}}
.strip-body-klientka{transition:left 950ms var(--ease-rcrut),translate 950ms var(--ease-rcrut)}
/* v1.12 r6 (critic medium r15 P2-4): at step 1 the salon's sleeping phone also lies further along, out of the frame (its
   frame edge at the window's left edge read as a render fault); it slides back with the camera move to step 2. */
.access-stage[data-step="1"] :is(.strip-screen-salon,.strip-reflect-salon,.strip-body-salon){translate:-40cqw 0}
/* r9 (critic medium r18 P1-3): at step 1 the salon's sleeping phone also fades out fast (200 ms), so no black slab crosses the close-up of the card while the camera is still moving there (fast scrolling back to step 1). */
.access-stage[data-step="1"] :is(.strip-screen-salon,.strip-reflect-salon,.strip-body-salon){opacity:0}
.strip-body-salon{transition:translate 950ms var(--ease-rcrut),opacity 200ms var(--ease-out)}
.access-stage[data-step="1"] .strip-reflect-salon{transition:opacity 200ms var(--ease-out),translate 950ms var(--ease-rcrut)}
.strip-body-salon{transition:translate 950ms var(--ease-rcrut)}
:is(.strip-screen-pin,.strip-screen-booking,.strip-reflect-klientka,.strip-body-klientka){transition:left 950ms var(--ease-rcrut)}
.access-stage[data-step="2"] .stage-strip{translate:var(--cam2) 0}
.access-stage:is([data-step="3"],[data-step="4"]) .stage-strip{translate:var(--cam3) 0}
.strip-card{position:absolute;z-index:1;left:var(--card-x);top:calc(50% - 32cqw);width:calc(var(--pw) * 1.3722);transition:translate 700ms var(--ease-rcrut)}
.strip-card .card-stack{width:100%}
/* First view: the card is put down once, from 60 px nearer the viewer's edge of the counter (never under a phone). */
.access-stage.is-dealing .strip-card{translate:0 60px}
.strip-screen{position:absolute;z-index:3;top:calc(var(--py) + var(--pw) * .03226);width:calc(var(--pw) * .93548);max-width:none;height:auto;border-radius:calc(var(--pw) * .1314);background:var(--app)}
.strip-screen-salon{left:calc(var(--pw) * .03226)}
.strip-screen-pin,.strip-screen-booking{left:calc(var(--client-x) + var(--pw) * .03226)}
@keyframes screen-switch{from{filter:brightness(.45) saturate(.6)}}
/* v1.10 round 8 (critic v1.10 r5 P1-1): a phone the camera is not stopped on sleeps (black glass under the window
   reflection), so no cut UI words stand at the frame's edges; its screen wakes as the camera arrives (600 ms into the
   950 ms pan). From 3 to 4 only the screen changes; the booking screen stays lit while it fades out to step 3. */
@keyframes strip-wake{from{filter:brightness(0) saturate(0)}60%{filter:brightness(.92) saturate(.95)}}
.strip-screen{filter:brightness(0) saturate(0);transition:filter 200ms var(--ease-out),opacity 260ms var(--ease-out),left 950ms var(--ease-rcrut),translate 950ms var(--ease-rcrut)}
.strip-screen-booking{opacity:0}
.access-stage[data-step="2"] .strip-screen-salon,.access-stage:is([data-step="3"],[data-step="4"]) .strip-screen-pin{filter:none;animation:strip-wake 900ms cubic-bezier(.3,0,.2,1) 550ms both}
.access-stage[data-step="3"] .strip-screen-booking{filter:none}
.access-stage[data-step="4"] .strip-screen-booking{opacity:1;filter:none;animation:strip-wake 900ms cubic-bezier(.3,0,.2,1) 550ms both}
.access-stage[data-step="4"][data-prev="3"] .strip-screen-booking{animation:screen-switch 520ms cubic-bezier(.3,0,.2,1) 60ms both}
.strip-reflect{position:absolute;z-index:3;top:calc(var(--py) - var(--pw) * .0519);width:calc(var(--pw) * 1.1256);aspect-ratio:669/1331;pointer-events:none;mix-blend-mode:screen;opacity:.3;clip-path:inset(calc(var(--pw) * .0841) calc(var(--pw) * .1262) calc(var(--pw) * .1262) calc(var(--pw) * .0639) round calc(var(--pw) * .1314))}
.strip-reflect img{display:block;width:100%;height:auto}
/* v1.11 (round 9): a sleeping phone is dark glass, not a hole. While its screen is off, the window's reflection shows at
   .6 (as a switched-off iPhone by a window does); when the camera stops on it and it wakes, the reflection eases back
   to the .3 of a lit screen. */
.strip-reflect{opacity:.85;transition:opacity 700ms var(--ease-out) 450ms,left 950ms var(--ease-rcrut),translate 950ms var(--ease-rcrut);background:linear-gradient(118deg,rgb(226 222 212 / 62%) 0%,rgb(200 196 186 / 44%) 30%,rgb(160 157 150 / 30%) 60%,rgb(120 118 112 / 22%) 100%)}
/* v1.12 r3 (critic MAX r12 P2-2): sleeping glass is dark grey with the window's sheen over its whole diagonal (.85), not black slabs crossing the frame in the camera move. */
.access-stage[data-step="2"] .strip-reflect-salon,.access-stage:is([data-step="3"],[data-step="4"]) .strip-reflect-klientka{opacity:.3}
.strip-reflect-salon{left:calc(var(--pw) * -.0317)}
/* At step 1 only the salon phone's right edge is in frame, so its sheen band lies along that edge. */
.strip-reflect-salon{background:linear-gradient(242deg,rgb(226 222 212 / 55%) 0%,rgb(200 196 186 / 40%) 30%,rgb(160 157 150 / 28%) 60%,rgb(120 118 112 / 22%) 100%)}
.strip-reflect-klientka{left:calc(var(--client-x) - var(--pw) * .0317)}
.strip-body{position:absolute;z-index:4;max-width:none;height:auto}
.strip-body-salon{left:calc(var(--pw) * -.0317);top:calc(var(--py) - var(--pw) * .0519);width:calc(var(--pw) * 1.1256)}
.strip-body-klientka{left:calc(var(--client-x) - var(--pw) * .0222);top:calc(var(--py) - var(--pw) * .0057);width:calc(var(--pw) * 1.0939)}
/* The figures hold the fixed label and a zoom button over the object of their frame. */
.stage-item{position:absolute;inset:0;z-index:5;grid-area:auto}
.stage-item,.stage-item.is-active{transform:none}
/* v1.10 round 6 (critic v1.10 r4 P2-8): the label stays in one place for all four steps. */
.stage-item .stage-label{position:absolute;left:calc(var(--bleed) + 40px);top:34px;margin:0}
/* v1.12 r4 (critic medium r13 P1-4): from 901 px the counter fills the left of the window top to bottom while the steps
   are read (sticky, 100svh; the island floats over it), like "Możliwości": no stone rectangle with edges. The phones
   are placed from the stage's top (r8, critic medium r17 P1-3: --py puts the screen's top 20% below the window's top; earlier 100% − 82cqw, cut where the old 640 px
   stage did, just under the real screens' content), the card from its middle; the label moves under the island. */
@media(min-width:901px){
  #jak-to-dziala{padding-block:0}
  .access-stage{top:0;min-height:100svh}
  /* r9 (critic medium r18 P1-2; restores r7): the counter's lower edge fades out over 100 px when the stage unpins, no line through the phone */
  .access-stage{-webkit-mask-image:linear-gradient(#000 calc(100% - 100px),transparent);mask-image:linear-gradient(#000 calc(100% - 100px),transparent)}
  .stage-item .stage-label{top:112px}
  .access-head{padding-top:clamp(112px,16svh,160px)}
  .access-list{padding-bottom:35svh}
}
.stage-hit{position:absolute;padding:0;border:0;background:transparent;cursor:zoom-in;border-radius:calc(var(--pw) * .1314)}
.stage-hit:focus-visible{outline:2px solid var(--green);outline-offset:4px}
.stage-hit-card{left:calc(var(--bleed) / 2 + 40px + 10.6cqw);top:calc(50% - 26.2cqw);width:78.7cqw;height:48.8cqw;border-radius:calc(var(--pw) * .04)}
.stage-hit-salon{left:calc(var(--bleed) + 40px + var(--pw) * .03226);top:calc(var(--py) + var(--pw) * .03226);width:calc(var(--pw) * .93548);height:calc(var(--pw) * 2.028)}
.stage-hit-client{left:calc(var(--bleed) + 40px + var(--client-x) + var(--cam3) + var(--pw) * .03226);top:calc(var(--py) + var(--pw) * .03226);width:calc(var(--pw) * .93548);height:calc(var(--pw) * 2.028)}
html:not(.access-js) .stage-item:not(#stage-1){display:none}
.access-list{grid-area:list;position:relative;margin-top:40px}
/* v1.9 (beUI Bounce Sidebar): the rail stays grey; one green dot jumps on a short arc to the active step's number
   (spring 280/18/0.3, softened for long jumps as in the source). Wide screens only; the phone deck has no rail. */
.access-dot{position:absolute;left:-3px;top:0;z-index:1;width:8px;height:8px;border-radius:50%;background:var(--green);box-shadow:0 0 0 4px var(--paper);pointer-events:none;will-change:transform}
/* v1.8: below 901 px every step shows its own frame under its text (no shared stage, no taps needed). */
.step-shot{display:none}
.deck-dots{display:none}

.access-steps{list-style:none;padding:0;margin:0;display:grid}
.access-step{position:relative;min-height:18vh;padding:4px 0 32px 28px;border-left:2px solid var(--line);transition:border-color 300ms var(--ease-out)}
.step-trigger{display:grid;grid-template-columns:auto 1fr;column-gap:14px;align-items:baseline;width:100%;padding:0;border:0;background:transparent;text-align:left;cursor:pointer}
.step-no{grid-row:span 2;font-family:var(--serif);font-size:28px;line-height:32px;font-weight:300;letter-spacing:-.02em;color:var(--body);font-variant-numeric:lining-nums;transition:color 300ms var(--ease-out)}
.access-step.is-active .step-no{color:var(--green)}
.step-where{font-size:13px;line-height:18px;font-weight:600;color:var(--green)}
.step-trigger strong{font-size:19px;line-height:28px;font-weight:600;color:var(--ink)}
.step-text{margin:8px 0 0 30px;max-width:400px;font-size:16px;line-height:26px;color:var(--body)}
.access-control{margin-top:8px;padding-top:24px;border-top:1px solid var(--line);font-size:16px;line-height:26px;color:var(--ink)}
.access-control a{margin-left:8px;color:var(--body)}
/* Without JavaScript every step shows its own image. */
html:not(.access-js) .access-stage{position:static;gap:40px}
html:not(.access-js) .stage-item{grid-area:auto;opacity:1;visibility:visible}
@media print{.stage-item{grid-area:auto!important;opacity:1!important;visibility:visible!important}}

/* ---------- Pause (v1.11, round 9): one sentence in light type on the page's paper, nothing else ---------- */
/* S3 „Pauza” (register S3-1…S3-4, rounds 48–52). One sentence in light type on the paper, nothing else.
   Sentence: phones — three lines („Klientka widzi / wolne terminy, / nie cudze wizyty.”), clamp(40px, 12.5vw, 56px); from
   761 px — two lines, one half of the antithesis each, 6.9vw + 0.5rem (follows text-only zoom), at most 112 px from 1101 px
   (the first line never passes the 1216 px column). „wolne terminy” never splits (&nbsp;). „nie cudze wizyty.” in the green
   italic (h2 em: 100 from 761 px, 200 on phones — a line stronger than a hair).
   Supporting sentence: one sentence per line on every width („Ty widzisz cały dzień salonu. / Ona tylko to, …”); 18/28 on
   phones, 20/30 on tablets, 21/32 from 1101 px.
   Paper: optically even above and below (S2's bottom padding counts above, S4's soft entry of stone below): phones 64/72 px,
   761–900 64 px, 901–1100 112/0 px (S4's stone starts ~150 px into its section), from 1101 px 140 px. */
.pause{display:flex;align-items:center;padding-block:64px 72px}
.pause-line{max-width:13em;font-size:clamp(40px,12.5vw,56px);line-height:1.08;font-weight:300;letter-spacing:-.035em;color:var(--ink)}
.pause-sub{max-width:520px;margin-top:28px;font-size:18px;line-height:28px;color:var(--body)}
.pause-sub1{display:block}
/* the italic's stroke follows the type size, not the layout break: 200 up to ~80 px (≤ 1100 px), 100 at 100–112 px (r52) */
@media(max-width:1100px){.pause-line em{font-weight:200}}
/* ≤ 360 px: the list after the colon keeps its own line („co może zarezerwować: / usługi, osoby i wolne godziny.”) (r52) */
@media(max-width:360px){.pause-sub2{display:block}}
/* r53 (S3-2, S3-4 register changes): ≤ 360 px the supporting sentence in 16/26 — three lines as at 390; from 1101 px the
   italic stays 200 on 1× screens (100 draws a ~1 px stroke there), 100 only on dense screens (≥ 1.5 dppx) */
@media(max-width:360px){.pause-sub{font-size:16px;line-height:26px}.pause-sub2{display:inline}}
@media(min-width:1101px) and (max-resolution:1.49dppx){.pause-line em{font-weight:200}}
@media(min-width:761px){.pause-l1{display:block}.pause-line{max-width:none;text-wrap:nowrap;font-size:calc(6.9vw + .5rem)}.pause-sub{max-width:34em;margin-top:32px;font-size:20px;line-height:30px}}
@media(min-width:761px) and (max-width:900px){.pause{padding-block:64px}}
@media(min-width:901px) and (max-width:1100px){.pause{padding-block:112px 0}}
@media(min-width:1101px){.pause{padding-block:140px}.pause-line{font-size:min(calc(6.9vw + .5rem),112px)}.pause-sub{margin-top:36px;font-size:21px;line-height:32px}}

/* ---------- Możliwości: one real screen at a time (v1.11, round 9; references oguz.design and Grain) ---------- */
/* The page's ground is paper here: the stone returns only as a piece of the hero's counter under the screens, the way
   Grain lays every UI fragment on a crop of its one photograph. */
.tools{position:relative;overflow-x:clip;background:var(--paper)}
.tools-head{display:grid;gap:20px;max-width:720px}
.frag-shot{position:relative;display:block;width:100%;padding:0;border:0;border-radius:var(--r-lg);background:var(--app)}
button.frag-shot{cursor:zoom-in}
.frag-shot img{width:100%;height:auto}
/* v1.10 round 7 (critic v1.10 r4 P2-5): the screens lie on the counter with a photographed contact shadow: the shadow of a
   thin white plate on the same stone (ChatGPT Images, order 18), the plate itself removed, as a 9-slice ring. */
.frag-shot>img{border-radius:inherit}
.frag-shot::before{content:'';position:absolute;inset:-1px -18px -20px -5px;z-index:-1;border-style:solid;border-width:31px 47px 49px 34px;border-image:url(assets/plate-shadow-v110.webp) 47 72 76 53 stretch;pointer-events:none}
.feat{margin-top:56px}
.feat-item h3{font-size:28px;line-height:34px;font-weight:500;letter-spacing:-.02em;color:var(--ink)}
.feat-item p{margin-top:12px;max-width:360px;font-size:18px;line-height:28px;color:var(--body)}
.tools-sms{max-width:360px;font-size:15px;line-height:22px;color:var(--body)}
.tools-sms strong{font-weight:600;color:var(--ink)}
/* A piece of the hero counter in window light (the hero file, already cached), cropped to its lit part. */
.feat-tile,.feat-shot{position:relative;background:url(assets/counter-hero-light-1672.webp) 18% 30%/260% auto no-repeat,var(--counter)}
/* v1.12 (critic MAX r10 P2-2): on 2× screens the tile takes the hero's 3344 file (already fetched there), so the stone keeps its grain. */
@media(min-width:1101px){.feat-tile{background:image-set(url(assets/counter-hero-light-1672.webp) 1x,url(assets/counter-hero-light-3344.webp) 2x) 18% 30%/260% auto no-repeat,var(--counter)}}
.plate-clients{aspect-ratio:393/484;overflow:hidden}
.plate-clients img{height:100%;object-fit:cover;object-position:top}
/* Client cards: first name and number only (production renderer), the same window light on every card whatever its
   angle, and the card's thickness as a light and a dark rim. */
.client-pile{--cw:170px;position:absolute;display:block;width:calc(var(--cw) * 1.3);height:calc(var(--cw) * 1.7);filter:drop-shadow(1px 2px 2px rgb(52 62 54 / 18%)) drop-shadow(8px 14px 18px rgb(52 62 54 / 20%))}
.pile-card{position:absolute;left:50%;top:50%;width:var(--cw);aspect-ratio:560/346;margin:calc(var(--cw) * -.309) 0 0 calc(var(--cw) * -.5);border-radius:5.5%/8.9%;overflow:hidden;cursor:pointer;transform:translate(calc(var(--cw) * var(--x)),calc(var(--cw) * var(--y))) rotate(var(--r));transition:transform 640ms cubic-bezier(.3,1.35,.5,1)}
.pile-card img{display:block;width:100%;height:100%}
.pile-card::before{content:'';position:absolute;inset:-45%;z-index:1;background:linear-gradient(135deg,rgb(255 255 255 / 55%) 0%,rgb(255 255 255 / 0) 42%,rgb(0 0 0 / 0) 58%,rgb(40 30 25 / 32%) 100%);transform:rotate(calc(var(--r) * -1));mix-blend-mode:soft-light;pointer-events:none}
.pile-card::after{content:'';position:absolute;inset:0;z-index:2;border-radius:inherit;box-shadow:inset 1px 1px 0 rgb(255 255 255 / 55%),inset -1.5px -1.5px 0 rgb(77 58 50 / 22%);pointer-events:none}
.pile-card:nth-child(1){--x:-.05;--y:-.3;--r:-4deg}.pile-card:nth-child(2){--x:.08;--y:.3;--r:3deg}.pile-card:nth-child(3){--x:-.02;--y:.5;--r:-2deg}
.client-pile.is-closed .pile-card{transform:translate(calc(var(--cw) * var(--x) * .12),calc(var(--cw) * var(--y) * .12)) rotate(calc(var(--r) * .25))}
.pile-card:nth-child(2){transition-delay:60ms}.pile-card:nth-child(3){transition-delay:120ms}
.client-pile.is-settled .pile-card{transition-delay:0ms}
.pile-card.is-lift{z-index:10;transform:none;scale:1.05}

/* From 1101 px: the notes scroll on the left, the counter stays on the right. The note in the middle of the window is
   in focus; its screen lies flat at scale 1.1 (the day plan fits a 900 px window whole), the neighbours tilt away
   like plates in perspective and dim (oguz.design). One camera move, RCRUT 800 ms. */
@media(min-width:1101px){
  .feat{--th:min(720px,100svh - 140px);--bleed:calc((100vw - min(100vw - 128px,1216px)) / 2);display:grid;grid-template-columns:minmax(0,4fr) minmax(0,8fr);column-gap:48px;align-items:start}
  .feat-list{padding-block:calc(var(--th) * .12) calc(var(--th) * .3)}
  /* v1.12 (critic MAX r10 P2-10): an inactive note stays readable: only its heading dims, by colour (--field ≈3.4:1 at 28 px), the text keeps --body. */
  /* v1.12 r2 (critic medium v1.12 P1-3): a note every ~0.38 of the stage, less paper between them. */
  .feat-item{min-height:calc(var(--th) * .38);display:flex;flex-direction:column;justify-content:center}
  .feat-item h3{color:var(--field);transition:color 500ms var(--ease-out)}
  .feat-item.is-active h3{color:var(--ink)}
  .feat-item .feat-shot{display:none}
  .tools-sms{margin-top:8px}
  /* v1.11 r2 (critic medium v1.11 P1-1): the counter piece has no rounded frame and runs off the window's right edge,
     like the steps' counter; the screen in focus is larger (UI ≈ 1.2). */
  /* v1.12 r3 (critic MAX r12 P1-2): the stone fills the right of the window top to bottom while the notes scroll (the island floats over it); no stone rectangle with edges in the window. */
  .feat-stage{position:sticky;top:0;height:100svh;margin-right:calc(var(--bleed) * -1)}
  /* v1.12 r4 (critic medium r13 P2-5): the section ends where its stone does (no paper under the unpinning stone). */
  #mozliwosci{padding-bottom:0;padding-top:0}
  .feat{margin-top:0}
  .feat-list{padding-top:clamp(112px,16svh,150px)}
  .feat-list .tools-head{margin-bottom:clamp(40px,8svh,96px)}
  .feat-list{padding-bottom:50svh}
  .feat-tile{height:100%;overflow:hidden;perspective:1800px;perspective-origin:50% 50%}

  /* v1.12 r6 (critic medium r15 P1-4): the stone's left edge fades into the paper over 120 px, like the hero's light, instead of a cut line. */
  /* v1.12 r7 (critic medium r16 P1-3; replaces r6's left mask): one logic of the stone's edges. The whole section lies
     on the hero's counter (fixed to the window, so it never scales past the window like one tall photo would), the notes
     too, as the hero's text does; top and bottom meet the paper in soft 120 px fades; no stone rectangle, no cut line. */
  .tools{isolation:isolate;background:url(assets/counter-hero-light-1672.webp) 50% 50%/cover fixed no-repeat,var(--counter);background:image-set(url(assets/counter-hero-light-1672.webp) 1x,url(assets/counter-hero-light-3344.webp) 2x) 50% 50%/cover fixed no-repeat,var(--counter)}
  .tools::before,.tools::after{content:'';position:absolute;left:0;right:0;height:80px;z-index:4;pointer-events:none}
  /* r8 (critic medium r17 P2-1): the tilted plates vanish before they reach the island (mask from 96 to 136 px); fades 80 px */
  .feat-tile{-webkit-mask-image:linear-gradient(transparent 96px,#000 136px);mask-image:linear-gradient(transparent 96px,#000 136px)}
  .tools::before{top:0;background:linear-gradient(var(--paper),rgb(247 246 242 / 0))}
  .tools::after{bottom:0;background:linear-gradient(rgb(247 246 242 / 0),var(--paper))}
  .feat-tile,.feat-shot{background:none}
  /* v1.12 r6 (critic medium r15 P1-4): the screen in focus fills ~70% of the window's height (day plan 532 px wide at 900). */
  /* r9 (critic medium r18 P1-4; replaces r6's 70%): every plate at the hero's UI scale (its width = the hero screen's width), centred between the island and the window's bottom. */
  .feat-tile .plate{--w:calc(clamp(323px,(100svh - 176px) * .4776,372px) * .93548);left:calc((100% - var(--bleed)) / 2);position:absolute;z-index:1;top:50%;width:var(--w);margin-left:calc(var(--w) / -2);translate:0 -50%;transform-origin:50% 50%;transition:transform 800ms var(--ease-rcrut),opacity 800ms var(--ease-rcrut),filter 800ms var(--ease-rcrut);opacity:0;pointer-events:none}
  /* v1.12 (critic MAX r10 P2-3): opacity and filter follow the transform's curve and time: the plate tilts, it does not cross-fade. */
  .feat[data-feat="1"] .plate[data-plate="1"],.feat[data-feat="2"] .plate[data-plate="2"],.feat[data-feat="3"] .plate[data-plate="3"]{z-index:3;opacity:1;transform:none;pointer-events:auto}
  .feat[data-feat="3"] .plate[data-plate="3"]{transform:translateX(calc(var(--w) * -.1))}
  .feat .feat-tile .plate{top:calc(50% + 44px)}
  /* The neighbours: the previous screen tilted away above, the next below, only their near edge in the tile. */
  .feat[data-feat="2"] .plate[data-plate="1"],.feat[data-feat="3"] .plate[data-plate="2"]{z-index:2;opacity:.5;filter:saturate(.75);transform:translateY(calc(var(--th) * -.56)) rotateX(60deg) scale(.82)}
  .feat[data-feat="1"] .plate[data-plate="2"],.feat[data-feat="2"] .plate[data-plate="3"]{z-index:2;opacity:.5;filter:saturate(.75);transform:translateY(calc(var(--th) * .56)) rotateX(-60deg) scale(.82)}
  /* v1.12 (critic MAX r10 idea 3): a tilting plate catches the window's light for a moment, like Marta's card in the hero.
     The band is parked off the plate on both sides at rest (active: right, neighbours: left), so it only crosses the
     screen while the plate moves (same 800 ms RCRUT); peak 0.35, colourless, nothing lies on the UI at rest. */
  .feat-tile .plate::after{content:'';position:absolute;inset:0;z-index:2;border-radius:inherit;pointer-events:none;mix-blend-mode:screen;background:linear-gradient(100deg,transparent 42%,rgb(255 253 246 / .12) 47%,rgb(255 253 246 / .35) 50%,rgb(255 253 246 / .12) 53%,transparent 58%) 0 0/300% 100% no-repeat;transition:background-position 800ms var(--ease-rcrut)}
  .feat[data-feat="1"] .plate[data-plate="1"]::after,.feat[data-feat="2"] .plate[data-plate="2"]::after,.feat[data-feat="3"] .plate[data-plate="3"]::after{background-position:100% 0}
  .feat[data-feat="1"] .plate[data-plate="3"]{transform:translateY(calc(var(--th) * .8)) rotateX(-64deg) scale(.7)}
  .feat[data-feat="3"] .plate[data-plate="1"]{transform:translateY(calc(var(--th) * -.8)) rotateX(64deg) scale(.7)}
  /* v1.12 r5 (critic medium r14 P1-1): the cards are objects at the list's scale, in the stone's free lower right quarter beside the list (not in its upper corner). */
  /* the list's crop runs down to Katarzyna's row, so two of the three cards beside it have their "karta" row in view (Marta's is the page's own card) */
  .feat-tile .plate-clients{aspect-ratio:393/484}
  /* r7: Anna's and Katarzyna's cards one above the other, not overlapping, fully inside the window */
  .feat-tile .client-pile .pile-card:nth-child(1){--x:0;--y:-.4;--r:-3deg}
  .feat-tile .client-pile .pile-card:nth-child(2){--x:.04;--y:.4;--r:2deg}
  .feat-tile .client-pile{--cw:clamp(190px,14vw,220px);z-index:3;right:3%;top:60%;margin-top:calc(var(--cw) * -.85);opacity:0;translate:0 24px;transition:opacity 600ms var(--ease-out),translate 800ms var(--ease-rcrut)}
  .feat[data-feat="3"] .feat-tile .client-pile{opacity:1;translate:0 0;transition-delay:450ms}
  .feat-item .client-pile{display:none}
}
/* Below 1101 px: each note has its own piece of the counter with its screen, flat, one under the other. */
@media(max-width:1100px){
  .feat-stage{display:none}
  .feat{display:block;margin-top:40px}
  .feat-item+.feat-item{margin-top:56px}
  /* v1.11 r2 (critic medium v1.11 P2-3): each piece of counter runs edge to edge of the window. */
  .feat-shot{margin:20px calc(50% - 50vw) 0;padding:clamp(28px,6vw,48px) 16px;display:flex;justify-content:center}
  /* v1.12 r6 (critic medium r15 P2-5): one continuous piece of the hero's counter under all three notes and their
     screens (no three separate strips, no seams between them); the notes' text lies on the light stone, as in the
     hero. The strip runs edge to edge of the window. */
  .tools{isolation:isolate}
  .feat-list{position:relative;padding-block:40px}
  /* r7 (critic medium r16 P2-2): the strip's ends fade into the paper (no hard line, no gap before the pricing) */
  .feat-list::before{content:'';position:absolute;top:0;bottom:-72px;left:calc(50% - 50vw);right:calc(50% - 50vw);z-index:-1;-webkit-mask-image:linear-gradient(transparent,#000 80px,#000 calc(100% - 120px),transparent);mask-image:linear-gradient(transparent,#000 80px,#000 calc(100% - 120px),transparent);background:url(assets/counter-pion-light-1024.webp) 38% 50%/cover no-repeat,var(--counter)}
  .feat-shot{background:none}
  .feat-shot .plate{width:min(100%,432px)}
  .feat-item[data-feat="3"] .feat-shot{flex-direction:column;align-items:center;gap:28px;padding-bottom:40px}
  .feat-item .client-pile{--cw:min(170px,40vw);position:relative}
  .tools-sms{margin-top:40px}
}

/* ---------- Pricing ---------- */
.pricing{background:var(--paper);overflow-x:clip}
/* S5 (state since r65–r68): the cotton-paper sheet (9-slice `paper-a5-v112`, retouched flat corner and soft shadow) lies on
   the page's paper — no counter, no props (direction A). From 1025 px the text column is as tall as the sheet (no sticky
   column), with the heading and lead at its top and "Jak zaczniesz" at its foot (S5-3). */
.price-scene{position:relative;display:flex;justify-content:center;padding:8px 0 24px}
/* v1.10 round 6 (critic v1.10 r4 P2-7): the stone starts 48 px left of the sheet (it lay on the very edge of the slab). */
.price-stage{position:relative;z-index:1;width:min(520px,100%)}
/* v1.10 (owner 25.09, critic v1.9 P2-3): true scale from the sheet (visible paper about 465 px of the 499 px stage = A5,
   148 mm): pen 14 cm = 72.5% of the stage, nail file 14 cm = 49.9%. The pen lies over the sheet's lower right corner,
   clear of the small print, and drifts (it lies on top); the file lies still under the sheet's edge (rule 11). */
.pricing-grid{display:grid;grid-template-columns:minmax(420px,1fr) minmax(0,640px);gap:64px 64px;align-items:start}
#pricing-title{font-variant-numeric:lining-nums}
.pricing-copy .lead{margin-top:24px}
/* v1.8: the price card is a sheet of heavy cotton paper (ChatGPT Images, own shadow) laid on the page; the text and
   the team slider are the product's. 9-slice keeps the paper edge and shadow crisp at any height. */
.price-card{position:relative;isolation:isolate;padding:44px 72px 72px 52px}
/* v1.10 (critic v1.10 P2-4, owner 26.09): cotton rag paper with visible fibre, soft edges and the lower right corner
   lifted (ChatGPT Images, order 14). The corner slices hold the edges and the curl unstretched (right 170, bottom 130 px). */
.price-card::before{content:'';position:absolute;inset:0;z-index:-1;border-style:solid;border-width:17px 97px 74px 15px;border-image:url(assets/paper-a5-v110.webp) 30 170 130 26 fill stretch}
/* v1.9 team slider: bunui Bendy Slider in the v1.8 language (owner 25.09, variant B2). The same paper track and green
   fill as v1.8; the ink bar bends at the ends (first and last quarter, max 10 px) and grows while pressed. The answer
   sits in the track ("Pracuję solo", "2 osoby" … "15 osób"): the value and the icon spring across the bar near the ends.
   A native range input lies on top (keyboard, screen readers); its 24 px thumb maps 1:1 to the bar (inset 12 px). */
.team-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px}
.team-selector label{display:block;font-size:16px;line-height:22px;font-weight:600}
.team-selector label>span{display:block;margin-top:2px;font-size:13px;line-height:18px;font-weight:400;color:var(--body)}
.team-range{--fill:0px;position:relative;height:48px;margin-top:14px;border-radius:12px;background:linear-gradient(90deg,rgb(61 107 92 / 16%) var(--fill),transparent 0),rgb(37 59 51 / 5%);box-shadow:inset 0 0 0 1px rgb(37 59 51 / 12%);touch-action:pan-y;user-select:none;-webkit-user-select:none}
.team-dots{position:absolute;inset:0;pointer-events:none}
.team-dots i{position:absolute;bottom:7px;width:3px;height:3px;margin-left:-1.5px;border-radius:50%;background:rgb(37 59 51 / 30%)}
.team-knob{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none}
.team-knob path{fill:none;stroke:var(--ink);stroke-width:4;stroke-linecap:round}
/* v1.10: the bar follows the finger at once while pressed and springs back straight on release (CSS d transition;
   where d does not animate it simply snaps). */
.team-range.is-ready:not(.is-pressed) .team-knob path{transition:d 420ms cubic-bezier(.34,1.56,.64,1)}
.team-icon,.team-value{position:absolute;top:0;bottom:0;left:0;display:flex;align-items:center;pointer-events:none}
.team-range.is-ready .team-icon,.team-range.is-ready .team-value{transition:transform 520ms cubic-bezier(.34,1.56,.64,1)}
.team-icon svg{width:18px;height:18px;color:rgb(37 59 51 / 75%)}
.team-value{width:max-content;font-size:14px;line-height:20px;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap}
.team-range input{appearance:none;-webkit-appearance:none;position:absolute;inset:0;display:block;width:100%;height:100%;margin:0;padding:0;opacity:0;background:transparent;cursor:pointer;touch-action:pan-y}
.team-range input::-webkit-slider-thumb{appearance:none;-webkit-appearance:none;width:24px;height:48px}
.team-range input::-moz-range-thumb{width:24px;height:48px;border:0}
.team-range:has(input:focus-visible){outline:2px solid var(--green);outline-offset:3px}
.price-amount{display:flex;align-items:flex-end;gap:12px;margin-top:24px;padding-top:24px;border-top:1px solid rgb(37 59 51 / 12%)}
.price-amount strong{font-family:var(--serif);font-size:84px;line-height:.9;font-weight:300;letter-spacing:-.05em;font-variant-numeric:lining-nums tabular-nums}
.price-amount>span{padding-bottom:8px;font-size:15px;line-height:20px;color:var(--body)}
.price-vat{margin-top:10px;font-size:14px;line-height:20px;color:var(--body);font-variant-numeric:tabular-nums}
.price-card .button{width:100%;margin-top:22px}
/* The bill: how the amount is made, in the sheet's small print voice, figures in a column. */
.price-bill{margin:18px 0 0;padding:14px 0 0;border-top:1px dashed rgb(37 59 51 / 22%);display:grid;gap:6px;font-size:14px;line-height:20px;color:var(--body);font-variant-numeric:tabular-nums lining-nums}
.price-bill>div{display:flex;justify-content:space-between;gap:16px}
.price-bill>div[hidden]{display:none}
.price-bill dt span{color:var(--field)}
.price-bill dd{margin:0;color:var(--ink)}
.included{list-style:none;padding:0;margin:22px 0 0;display:grid;gap:8px}
.included li{display:flex;align-items:center;gap:10px;font-size:14px;line-height:20px}
.included svg{width:16px;height:16px;color:var(--green)}
.price-small{margin-top:20px;font-size:12px;line-height:18px;color:var(--body)}
.price-small a{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px;text-decoration-color:var(--link)}
.price-small a:hover{color:var(--green);text-decoration-color:currentColor}
/* Start steps live under the calculator: price and the next move in one place. */
.start-steps{margin-top:48px;padding-top:32px;border-top:1px solid rgb(37 59 51 / 14%);max-width:520px}
/* The start list's position beside the sheet is set by S5-3 (r65: the text column as tall as the sheet, steps at its foot;
   the earlier sticky column of v1.11 is gone). */
.start-steps h3{font-size:17px;line-height:24px}
.start-steps .timeline{list-style:none;padding:0;margin:20px 0 0;display:grid;gap:18px}
.start-steps li{display:grid;grid-template-columns:36px 1fr;column-gap:12px;align-items:start}
.timeline-no{font-family:var(--serif);font-size:30px;line-height:28px;font-weight:300;letter-spacing:-.02em;color:var(--green);font-variant-numeric:lining-nums}
.start-steps p{font-size:15px;line-height:24px;color:var(--body)}
.start-steps strong{font-weight:600;color:var(--ink)}

/* ---------- FAQ: hairline lists in two groups ---------- */
/* r65 (critic r74 P3-3, Astra): the intro always stands above the questions; no sticky side column at 901–1100 px. */
.faq-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:48px 64px;align-items:start}
.faq-intro{position:static}
.faq-intro p{margin-top:24px;color:var(--body)}
.faq-intro a{overflow-wrap:anywhere}
.faq-groups{display:grid;gap:48px}
.faq-group-title{padding-bottom:12px;font-size:13px;line-height:18px;font-weight:600;letter-spacing:.04em;color:var(--green);border-bottom:1px solid rgb(37 59 51 / 40%)}
/* v1.10 round 8 (critic v1.10 r5 P1-3): from 1101 px the two groups stand side by side under the heading, so the last
   plain stretch before the final is half as long; questions and answers are unchanged. */
/* r65 (critic r74 P3-3, Astra): two groups side by side from 1000 px (1024: 2 × 432 px, questions at most two lines). */
@media(min-width:1000px){.faq-groups{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:64px}}
/* r65 (critic r74 P2-1, Astra; replaces r8 / rule 84 for S6): a quiet register on the page's paper — 1 px at 12% ink under every
   question (the last too, so each column ends on a line), 40% under the group title, 20 px per question. */
details{border-bottom:1px solid rgb(37 59 51 / 12%)}
summary{list-style:none;display:flex;justify-content:space-between;align-items:center;gap:24px;min-height:48px;padding:20px 0;font-size:17px;line-height:26px;font-weight:500;cursor:pointer}
summary::-webkit-details-marker{display:none}
summary>span{display:grid;place-items:center;width:32px;height:32px;flex-shrink:0;border-radius:9999px;color:var(--green);transition:transform 400ms var(--ease-out),background-color 400ms var(--ease-out)}
summary>span svg{width:18px;height:18px}
/* r65 (critic r74 P3-1): hover only with a precise pointer, so a tapped question never stays green. */
@media(hover:hover) and (pointer:fine){summary:hover{color:var(--green)}summary:hover>span{background:var(--sage)}}
details[open] summary>span{transform:rotate(45deg)}
details p{padding:0 56px 24px 0;color:var(--body)}
/* v1.5: answers open at the pace of the plus (progressive). */
@supports selector(::details-content){
  details{interpolate-size:allow-keywords}
  details::details-content{height:0;overflow:clip;opacity:0;transition:height 420ms var(--ease-out),opacity 320ms var(--ease-out),content-visibility 420ms allow-discrete}
  details[open]::details-content{height:auto;opacity:1}
}

/* ---------- Final: evening at the same window (v1.11, round 9, direction A; references Grain, Lightship) ---------- */
/* Full width like the hero, no rounded panel. The text stands in the hero's left column; on the right Marta's visit is
   in the salon's phone and her card lies beside it, in the lower, warmer light of the end of the day. */
.final-cta{--pw:min(clamp(220px,20vw,300px),372px);position:relative;overflow:hidden;isolation:isolate;display:flex;align-items:center;min-height:calc(var(--pw) * 2.094 + 208px);background:url(assets/counter-evening-v112i-1672.webp) 50% 50%/cover no-repeat,var(--counter);background:image-set(url(assets/counter-evening-v112i-1672.webp) 1x,url(assets/counter-evening-v112i-3344.webp) 2x) 50% 50%/cover no-repeat,var(--counter)}
/* The same slab in late-afternoon light (ChatGPT Images, order 20: an edit of the hero's counter): lower, warmer light
   from the left, cooler shade on the right. With JS it is fetched only when the final comes near. */
.js .final-cta:not(.is-near){background-image:none}
.final-scene{position:absolute;inset:0;z-index:0;pointer-events:none}
/* The same photographed card as in the hero, never rotated in CSS (light stays upper left); it drifts beside the phone,
   never under it (rule 11). Phone and card share one --pw (true scale). */
.final-phone{position:absolute;left:calc(50% + 16px);top:50%;width:var(--pw);aspect-ratio:372/779;margin-top:calc(var(--pw) * -1.047)}
.final-card{--drift:drift-paper;--dur:27s;position:absolute;left:calc(50% + 16px + var(--pw) * 1.02);top:calc(50% + var(--pw) * .02);width:calc(var(--pw) * 1.3722)}
.final-phone img{position:absolute;display:block;max-width:none;height:auto}
.final-phone-screen{left:calc(var(--pw) * .03226);top:calc(var(--pw) * .03226);width:calc(var(--pw) * .93548);border-radius:calc(var(--pw) * .1314);background:var(--app)}
.final-phone-body{left:calc(var(--pw) * -0.0317);top:calc(var(--pw) * -0.0519);width:calc(var(--pw) * 1.1256)}
/* v1.10 round 8 (critic v1.10 r5 P2-3): the moment's echo. Once, when the final comes into view (from 1101 px), the
   window glint crosses Marta's card and 150 ms later the band of her 12:45 row on the phone, with no camera push. */
.final-cta.is-echo .card-glint{display:block;animation:glint-sweep 1100ms cubic-bezier(.45,0,.2,1) 300ms both}
.final-cta.is-echo .row-glint{display:block;animation:glint-sweep 800ms cubic-bezier(.45,0,.2,1) 450ms both}
.final-light{position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none;mix-blend-mode:multiply;opacity:.26;-webkit-mask-image:linear-gradient(90deg,transparent 62%,#000 86%);mask-image:linear-gradient(90deg,transparent 62%,#000 86%)}
.final-light video{position:absolute;top:0;right:0;width:auto;height:100%;min-width:100%;object-fit:cover;object-position:100% 0;transform:scaleX(1.6);transform-origin:100% 50%}
/* v1.12 r2 (critic medium v1.12 idea 5): the same leaf shadows, drawn 1.6x longer to the right: low evening sun. */
.final-inner{position:relative;z-index:1;display:grid;justify-items:start;width:calc(100% - 128px);max-width:1216px;margin:0 auto;padding-block:104px;text-align:left}
.final-inner>*{max-width:min(460px,100%)}
/* The text column always ends before the phone (which starts 16 px right of the middle). */
@media(min-width:761px){.final-cta .final-inner>*{max-width:min(460px,calc(50vw - 88px))}}
@media(min-width:1101px){.final-cta .final-inner>*{max-width:min(460px,calc(50vw - 120px))}}
.final-inner h2 em{display:block;font-weight:300}
/* v1.11 r2 (critic medium v1.11 P1-2): the final's green line in Light Italic like the hero's (Thin was faint on the stone). */
.final-lead{margin-top:24px;max-width:520px;font-size:18px;line-height:28px;color:var(--body)}
.final-inner .button{margin-top:32px}
.final-note{margin-top:16px;max-width:460px;font-size:14px;line-height:20px;color:var(--body)}
/* v1.12 r3 (critic MAX r12 P1-1, idea 1): the evening's only warmth is one patch of low sun in the shape of the window
   (four panes, the mullion's soft shadow between them), lying on the card and the stone beside it; the plate itself is
   the hero's, evenly ~10% darker and cooler. The patch stands still while the card drifts under it. The phone's screen
   stays the brightest thing in the scene. The final's text is darker (#3d4a42) on the darker stone (≥ 4.5:1). */
.final-lead,.final-note{color:#3d4a42}
/* v1.12 r7 (critic medium r16 P2-3): the card keeps its pink in the evening (sun layer at .5), only its tone warms a little. */
/* v1.12 r6 (critic medium r15 P1-3): the window-shaped sun lies on the card only (the card's evening layer, masked by the card), not spilling over the stone. */
/* v1.12 r2 (critic medium v1.12 P1-4): the close is not a smaller copy of the hero. From 1280 px the phone moves 80 px
   nearer the text and grows towards the hero's scale (1440: 337 px, hero 357 px), the card's QR still inside the window. */
/* v1.12 r8 (critic medium r17 P1-1, idea 1; replaces r7's whole counter): the close is the "after" at the hero's scale:
   the salon's phone (1440: ~337 px) and the card beside it, the phone 80 px nearer the text; the stone ~18% darker than
   the hero's, so the screen is the brightest thing and casts a faint glow on the stone (a blurred copy of the screen,
   screen blend, .12, reaching ~40 px past the frame). The only motion is the echo glint on the 12:45 row. */
/* v1.12 r9 (critic medium r18 P1-1, idea 1; replaces r8's repeat of the hero): the close is a close-up of the "after".
   From 1280 px the camera stands 1.2x nearer than in the hero: Marta's 12:45 row in the scene's optical middle, the
   window's lower edge cutting the phone under the 15:30 row; the card lies in the foreground on the phone's lower right
   (over it, never under it: rule 11), its QR whole in the window. The evening is a warm low wedge of light across the
   card, not a general darkening (plate: the hero's file, saturation kept, exposure 0.98 → 0.84). */
/* r10 (critic medium r19 P1-1, idea 1; replaces r9's close-up): the whole phone in view with its 19:40 under the island,
   at the hero's scale; the card beside it on the counter at the frame's lower right, over no part of the screen; the
   warm low wedge crosses the card only; the screen stays the brightest thing (glow). */
@media(min-width:1280px){
  .final-cta{--pw:min(clamp(323px,calc((100svh - 176px) * .4776),372px),calc((50vw + 40px) / 2.255))}
  .final-cta{background:linear-gradient(112deg,rgb(128 128 128 / 0) 58%,rgb(255 176 104 / .7) 72%,rgb(128 128 128 / 0) 88%),image-set(url(assets/counter-evening-v112i-1672.webp) 1x,url(assets/counter-evening-v112i-3344.webp) 2x) 50% 50%/cover no-repeat,var(--counter);background-blend-mode:soft-light,normal}
  .js .final-cta:not(.is-near){background:var(--counter)}
  .final-phone{left:calc(50% - 64px)}
  .final-card{left:calc(50% - 64px + var(--pw) * 1.03);top:calc(50% + var(--pw) * .1)}
}
.final-glow{position:absolute;left:calc(var(--pw) * -.08);top:calc(var(--pw) * -.08);width:calc(var(--pw) * 1.16);height:calc(var(--pw) * 2.2);border-radius:calc(var(--pw) * .2);background:url(assets/calendar-evening-v112.webp) 50% 50%/86% auto no-repeat;filter:blur(calc(var(--pw) * .09));mix-blend-mode:screen;opacity:.12;pointer-events:none}
/* v1.12 (critic MAX r10 P1-1): the evening is on the objects too, not only on the stone. One low light from the left for
   the whole scene: a warm edge on the phone's frame and the card's left side, a cooler, darker right side, and a long
   cast shadow to the right (a lying phone ~8 mm high at low sun; the card, <1 mm, only a little longer than at noon).
   The layers are masked by the objects' own photos, so the screen (emissive) and the stone stay untouched. */
/* v1.12 r6 (critic medium r15 P1-3): the long evening shadow follows the phone's own outline (a drop shadow of its photo), not a blurred rectangle, which read as a cut vertical band. */
.final-phone-body{filter:drop-shadow(calc(var(--pw) * .12) calc(var(--pw) * .03) calc(var(--pw) * .045) rgb(52 38 26 / .28))}
.final-warm{position:absolute;left:calc(var(--pw) * -0.0317);top:calc(var(--pw) * -0.0519);width:calc(var(--pw) * 1.1256);aspect-ratio:669/1331;background:linear-gradient(100deg,rgba(255,178,104,.9) 0,rgba(255,178,104,.35) 9%,rgba(128,128,128,0) 30%,rgba(128,128,128,0) 62%,rgba(34,42,60,.55) 100%);mix-blend-mode:soft-light;-webkit-mask:url(assets/device-photo-v17.webp) 0 0/100% 100%;mask:url(assets/device-photo-v17.webp) 0 0/100% 100%}
.final-card .card-base{filter:drop-shadow(calc(var(--pw) * .04) calc(var(--pw) * .01) calc(var(--pw) * .016) rgba(58,40,24,.26))}
.card-stack .card-eve{display:none}
.final-card .card-eve{display:block;position:absolute;inset:0;background:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 140'><filter id='b' filterUnits='userSpaceOnUse' x='0' y='0' width='200' height='140'><feGaussianBlur stdDeviation='4'/></filter><g filter='url(%23b)' fill='rgb(255,186,118)'><polygon points='30,30 94,23 101,68 37,76'/><polygon points='101,22 165,15 172,60 108,67'/><polygon points='38,81 102,73 109,118 45,126'/><polygon points='109,72 173,64 180,109 116,117'/></g></svg>") 30% 40%/150% auto no-repeat,linear-gradient(100deg,rgba(255,178,104,.35) 0,rgba(128,128,128,0) 40%);mix-blend-mode:soft-light;opacity:.5;-webkit-mask:url(assets/card-land-base-v18b.webp) 0 0/100% 100%;mask:url(assets/card-land-base-v18b.webp) 0 0/100% 100%}

.footer{padding-block:56px 32px}
.footer-top{display:flex;align-items:center;justify-content:space-between;gap:24px;padding-bottom:28px;border-bottom:1px solid var(--line)}
.footer-top p,.footer-top>a:last-child{font-size:14px;line-height:20px;color:var(--body)}
.footer-bottom{display:flex;justify-content:space-between;gap:24px;padding-top:24px;font-size:13px;line-height:18px;color:var(--body)}
.footer-bottom nav{display:flex;gap:24px;font-size:14px;line-height:20px}
.footer a:hover{color:var(--green)}

/* ---------- Invitation dialog ---------- */
.invitation-dialog{width:min(860px,calc(100% - 32px));max-width:none;max-height:calc(100dvh - 32px);padding:0;border:0;border-radius:var(--r-xl);background:var(--paper);color:var(--ink);box-shadow:0 32px 96px rgb(21 45 38 / 28%);overflow:auto;overscroll-behavior:contain}
.invitation-dialog::backdrop{background:rgb(21 43 36 / 48%);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.invitation-layout{display:grid;grid-template-columns:.85fr 1.15fr}
/* v1.10 (critic v1.9 idea 4): the welcome panel is a piece of the same counter (the file is already cached), with
   Marta's card lying still at its lower edge from 1101 px; texts unchanged, on the light stone. */
.invitation-welcome{position:relative;overflow:hidden;display:flex;flex-direction:column;justify-content:space-between;gap:48px;padding:36px;background:url(assets/counter-v18-1672.webp) 24% 50%/cover no-repeat,var(--counter);background:image-set(url(assets/counter-v18-1672.webp) 1x,url(assets/counter-v110-3344.webp) 2x) 24% 50%/cover no-repeat,var(--counter)}
.invitation-card{display:none}
@media(min-width:1101px){
  .invitation-welcome{gap:28px;padding-bottom:0}
  .invitation-card{display:block;flex:none;width:86%;margin:-8px -22% -13% auto}
}
.invitation-wordmark{font-family:var(--brand);font-size:26px;line-height:32px;font-weight:600}
.invitation-kicker{font-size:13px;line-height:18px;font-weight:600;letter-spacing:.04em;color:var(--green);margin-bottom:12px}
.invitation-welcome h2{font-size:36px;line-height:1.06;margin-bottom:20px}
.invitation-welcome h2 em{display:block}
.invitation-welcome p:not(.invitation-kicker){font-size:15px;line-height:24px;color:var(--body)}
.invitation-welcome #invitation-description{color:var(--ink)}
.invitation-welcome .invitation-signature{font-family:var(--serif);font-size:18px;line-height:24px;font-style:italic;font-weight:400;color:var(--green)}
.invitation-body{padding:48px 36px 28px;min-width:0}
.dialog-close{position:absolute;right:8px;top:8px;z-index:2;width:48px;height:48px;display:grid;place-items:center;border:1px solid transparent;background:transparent;border-radius:9999px}
.dialog-close:hover{background:var(--sage)}
.invitation-form-heading{font-weight:600;font-size:18px;line-height:28px;margin-bottom:4px}
.invitation-required{font-size:14px;line-height:20px;color:var(--body);margin-bottom:24px}
.invitation-fields{border:0;padding:0;margin:0;min-width:0;display:grid;gap:16px}
.form-field label{display:flex;align-items:baseline;gap:4px;margin-bottom:8px;font-size:14px;line-height:20px;font-weight:600}
.field-optional{margin-left:auto;font-weight:400;color:var(--body)}
.form-field :is(input,textarea){width:100%;min-height:48px;padding:12px 16px;border:1px solid var(--field);border-radius:var(--r-md);background:var(--white);font-size:16px;line-height:24px}
.form-field textarea{display:block;min-height:96px;max-height:256px;resize:vertical}
.form-field :is(input,textarea)::placeholder{color:var(--body)}
.form-field :is(input,textarea):hover{border-color:var(--green)}
.form-field :is(input,textarea):focus{border-color:var(--green);outline:2px solid var(--green);outline-offset:2px}
.form-field :is(input,textarea)[aria-invalid=true]{border-color:var(--error);box-shadow:0 0 0 1px var(--error)}
.form-field :is(input,textarea)[aria-invalid=true]:focus{outline-color:var(--error)}
.field-error{font-size:14px;line-height:20px;color:var(--error);margin-top:8px}
/* v1.9 (beUI Input): pill fields with an icon; an error shakes the field once and its message comes out of a blur;
   a field that passes the same validation as the submit gets a drawn check when you leave it. */
.field-box{position:relative}
.field-box input{border-radius:9999px;padding-left:46px;padding-right:44px}
.field-icon{position:absolute;left:16px;top:50%;width:18px;height:18px;margin-top:-9px;color:var(--body);pointer-events:none}
.field-ok{position:absolute;right:16px;top:50%;width:20px;height:20px;margin-top:-10px;fill:none;stroke:var(--green);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:24;stroke-dashoffset:24;pointer-events:none}
.field-box.is-valid .field-ok{stroke-dashoffset:0;transition:stroke-dashoffset 350ms ease-out}
@keyframes field-shake{14%{transform:translateX(-6px)}28%{transform:translateX(6px)}43%{transform:translateX(-4px)}57%{transform:translateX(4px)}71%{transform:translateX(-2px)}86%{transform:none}}
.field-box.is-shaking{animation:field-shake 450ms linear}
@keyframes error-in{from{opacity:0;transform:translateY(-4px);filter:blur(4px)}}
.field-error:not([hidden]){animation:error-in 200ms var(--ease-out)}
.form-trap{position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden}
.invitation-submit{width:100%;margin-top:8px}
.invitation-fields:disabled{opacity:.65}
.form-status{font-size:14px;line-height:20px;margin-top:16px;padding:14px 16px;border:1px solid #caa49c;border-radius:var(--r-md);color:var(--error)}
.form-status[data-kind=preview],.form-status[data-kind=pending]{background:var(--sage);color:var(--ink);border-color:var(--line)}
.invitation-privacy{font-size:14px;line-height:20px;text-align:center;margin-top:12px}
.invitation-privacy a{display:inline-flex;align-items:center;min-height:48px;text-decoration:underline;text-underline-offset:4px}
.invitation-preview-note{font-size:13px;line-height:20px;text-align:center;color:var(--body)}
.invitation-success{min-height:480px;display:flex;flex-direction:column;align-items:flex-start;justify-content:center}
.success-mark{display:grid;place-items:center;width:48px;height:48px;background:var(--sage);color:var(--green);border-radius:9999px;margin-bottom:24px}
.invitation-success h3{font-family:var(--serif);font-size:34px;line-height:38px;font-weight:500;margin-bottom:16px}
.invitation-success p{color:var(--body);margin-bottom:24px}

/* ---------- Product preview dialog ---------- */
.product-preview{cursor:zoom-in}
.product-dialog{padding:16px;border:0;border-radius:var(--r-xl);background:var(--paper);color:var(--ink);width:min(480px,calc(100% - 32px));max-width:none;max-height:calc(100dvh - 32px);box-shadow:0 24px 96px rgb(21 45 38 / 32%)}
.product-dialog[open]{display:flex;flex-direction:column;overflow:hidden}
.product-dialog::backdrop{background:rgb(19 43 35 / 55%);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.invitation-dialog[open],.product-dialog[open]{animation:dialog-in 500ms var(--ease-out)}
@keyframes dialog-in{from{opacity:0;transform:translateY(12px) scale(.985)}}
.preview-header{display:flex;align-items:flex-start;justify-content:space-between;flex:none;gap:16px;margin-bottom:12px}
.preview-header h2{font-size:30px;line-height:34px;margin-bottom:4px}
.preview-header p{font-size:13px;line-height:18px;color:var(--body)}
.preview-close{display:grid;place-items:center;width:48px;height:48px;flex-shrink:0;border:1px solid var(--line);border-radius:9999px;background:var(--white)}
.preview-close:hover{background:var(--sage)}
.preview-tools{flex:none;margin-bottom:12px}
.preview-zoom{min-height:44px;display:inline-flex;align-items:center;padding:0 16px;border:1px solid var(--line);border-radius:9999px;background:var(--white);font-size:14px;line-height:20px;font-weight:600}
.preview-zoom:hover{background:var(--sage)}
.preview-tools p{font-size:13px;line-height:18px;color:var(--body);margin-top:8px}
.preview-media{position:relative;min-height:0;overflow:auto;overscroll-behavior:contain;border-radius:var(--r-md)}
#preview-image{display:block;width:100%;max-width:393px;height:auto;margin:auto;border-radius:var(--r-md)}
.preview-media.is-zoomed #preview-image{width:786px;max-width:none}
.preview-media.is-loading{min-height:360px;background:var(--sage)}
.preview-media.is-loading::before,.preview-media.is-loading::after{content:'';position:absolute;inset:24px 24px auto;height:80px;background:#d7dfd2;border-radius:var(--r-sm);animation:skeleton-breathe 1.6s var(--ease-out) infinite alternate}
.preview-media.is-loading::after{inset:128px 24px 24px;height:auto;background:#e0e7dc}
.preview-media.is-loading img,.preview-media.is-error img{visibility:hidden}
.preview-status{position:absolute;inset:40% 16px auto;padding:16px;background:var(--paper);border:1px solid var(--line);border-radius:var(--r-sm);z-index:1;font-size:14px;line-height:20px;text-align:center}
.preview-media.is-error{min-height:240px}
.preview-media:focus-visible{outline-offset:-4px}
@keyframes skeleton-breathe{from{opacity:.5}to{opacity:1}}

/* Reveal: only product crops settle in (12 px, 700 ms, once). Content is visible without JS. */
[data-reveal]{transition:opacity 700ms var(--ease-out),transform 700ms var(--ease-out)}
.motion-ready [data-reveal]:not(.is-visible){opacity:0;transform:translateY(12px)}

/* ---------- Responsive ---------- */
@media(min-width:1201px){.menu-toggle{display:none}}

@media(max-width:1200px){
  .island{gap:24px}
  .desktop-nav,.login-link{display:none}
  .wrap,.hero-inner,.final-inner{width:calc(100% - 96px)}
  .pricing-grid{gap:48px 56px}
  .faq-grid{gap:40px 48px}
  .access-grid{column-gap:56px}
}

/* Tablets: the hero stacks; card and phone stay together in true scale, the shears leave. */
/* v1.12 (critic MAX r10 P2-8): the stacked hero is for portrait tablets and narrow windows only. An iPad in landscape
   (1000–1100 px wide) keeps the desktop grid (below), so the calendar's visits are in the first screen. */
@media(max-width:999px),(max-width:1100px) and (orientation:portrait){
  .hero-inner{grid-template-columns:minmax(0,1fr);justify-items:center;min-height:auto;padding-block:130px 24px;text-align:center}
  .hero-copy{max-width:640px}
  .hero h1{font-size:min(54px,calc((100vw - 96px) / 10))}
  .hero h1 em{font-size:min(1em,min(640px,100vw - 96px) / 11.4)}
  .hero-description{margin-inline:auto}
  .hero-actions{justify-content:center}
  /* Tablets: the phone and the card (1.965 pw wide) keep 48px from each edge. */
  .hero-inner{--pw:min(clamp(323px,calc((100svh - 152px) * .4776),372px),calc((100vw - 96px) / 1.965))}
  .hero-scene{width:calc(var(--pw) * 2.008);margin-top:16px}
  /* v1.10 (critic v1.9 P1-2): tall sections get a portrait counter instead of a landscape strip stretched about 8x.
     Critic v1.10 P2-1: the first portrait file was another stone (porous travertine); this one is the desktop's smooth
     limestone in portrait (ChatGPT Images edit of blat-hero-bez-lisci, order 13; 1024x1536, 24 KB). */
  .hero{background-image:url(assets/counter-pion-light-1024.webp)}
  /* Tablets (v1.7): the phone stands in the middle, the landscape card lies under its lower right corner, still
     (it never drifts under the phone), with the name and QR clear of the phone and the small brand line fully under it (never cut by its edge). */
  .hero-scene{height:calc(var(--pw) * 2.83 + 16px)}
  .hero-device{left:calc(var(--pw) * .504)}
  .hero-scene{--m-origin-x:calc(var(--pw) * 1.054)}
  .prop-card{width:calc(var(--pw) * 1.3722);left:calc(var(--pw) * .63);top:calc(var(--pw) * 1.85);transform:none}
  .prop-card .prop-drift{animation:none}
}
/* r11 (S1, critic r21 P2-1): portrait tablets: the phone (300 px) and Marta's still card beside it, its name and whole QR right
   of the frame at the height of the 12:45–15:30 rows (it may slip 0.05 pw under the frame: rule 11 allows a still card),
   the pair centred under the centred text, in the first screen. */
@media(min-width:761px) and (max-width:1100px) and (orientation:portrait){
  /* r12 (S1, critic r22 P1-2): the pair centred, 16 px between the frame and the card, one alignment (caption above the frame) */
  .hero-inner{--pw:276px}
  .hero-scene{width:calc(var(--pw) * 2.45 + 16px);height:calc(var(--pw) * 2.094 + 16px);margin-left:auto;margin-right:auto}
  .hero-device{left:calc(var(--pw) * .0317)}
  .prop-card{left:calc(var(--pw) * 1.08 + 28px);top:calc(var(--pw) * .38)}
  /* r15 (S1, critic r25 P2-1): the copy aligned left on the phone frame's axis (one left edge for text and scene) */
  .hero-copy{justify-self:start;text-align:left;margin-left:calc((100% - var(--pw) * 2.45 - 16px) / 2 + var(--pw) * .0317 + 4px);max-width:min(640px,100%)}
  .hero-description{margin-inline:0}
  .hero-actions{justify-content:flex-start}
  /* r13 (S1, critic r23 P2-4): the card's middle at the 11:30–12:45 rows, where the camera of the moment stands */
  .hero-scene{margin-top:74px;translate:4px 0}
}
@media(min-width:1000px) and (max-width:1100px) and (orientation:landscape){
  .hero-inner{--pw:min(clamp(276px,calc((100svh - 210px) * .4776),372px),calc((100vw - 128px) * 7 / 12 / 1.62));padding-block:130px 32px}
  /* r11: the phone stands 36 px lower so its caption clears the island */
  .hero-scene{margin-top:52px}
  .hero-scene{height:calc(var(--pw) * 2.83 + 16px)}
  /* the landscape card lies still under the phone's lower right corner (rule 3a), so its QR never leaves the window */
  /* v1.12 r2 (critic medium v1.12 P1-2): at 768 px of height the calendar and the card cannot both fit at a readable
     scale (the card whole would need a ~220 px phone), so the calendar wins and the card lies whole below the phone,
     under the fold, instead of a pink scrap at the window's edge. */
  .prop-card{width:calc(var(--pw) * 1.3722);left:calc(var(--pw) * .3);top:calc(var(--pw) * 2.16);transform:none}
  /* v1.12 r3 (critic MAX r12 P2-4): the text starts under the island, not centred on the tall scene. */
  .hero-copy{align-self:start;padding-top:40px}
  /* r7 (critic medium r16 P2-1): the phone stands at the column's right edge (48 px from the window), its caption on its left, at the date strip, towards the text */
  .hero-device{left:auto;right:60px}
  /* r11 (S1, critic r21 P2-1/P2-3): the card lies whole, still, in the empty lower left quarter under the text column, in the first screen (to the phone's right it would leave the window) */
  /* r12 (S1, critic r22 P2-2): 32 px under the note, right next to the phone (its QR corner towards the frame); its lower edge may leave the window, name and QR stay in */
  /* r13 (S1, critic r23 P2-3): the whole card in the window, 16 px under the note and ≥ 16 px above the window's edge */
  .hero-inner{--pw:250px}
  .hero-copy{padding-top:0}
  /* r14 (S1, critic r24 P2-4): the card right next to the frame (20 px), 16 px under the note: one still life */
  /* r16 (S1, critic r26 P2-5): ≥ 48 px from the frame, nearer the button's axis */
  .prop-card{left:calc(var(--pw) * -.56 - 88px);top:calc(var(--pw) * 1.29 + 14px)}
  /* r8 (critic medium r17 P2-4): the caption above the phone, aligned to its left edge */
  /* r9 (critic medium r18 P2-4; replaces r8): left of the phone at the date strip, as at 1440 */
  /* r10 (critic medium r19 P2-4): right above the frame's top left corner */
  .hero-scene{height:calc(var(--pw) * 3.16 + 16px)}
  .prop-card .prop-drift{animation:none}
}
@media(max-width:1100px){
  .hero-light,.final-light{display:none}
  .final-cta{background:linear-gradient(160deg,rgb(128 128 128 / 0) 55%,rgb(255 176 104 / .6) 75%,rgb(128 128 128 / 0) 95%),url(assets/counter-pion-light-1024.webp) 50% 50%/cover no-repeat,var(--counter);background-blend-mode:soft-light,normal}
  /* Tablets: the plan, then the client list cascading from its lower edge (the team picker leaves, as on phones). */
}

@media(max-width:1024px){
  .pricing-grid{grid-template-columns:minmax(0,1fr);row-gap:0}
  .pricing-copy{display:contents}
  .price-scene{order:1;margin-top:40px;padding:0}
  .price-stage{width:min(520px,100%)}
  .start-steps{order:2}
}

/* One column: heading, stage, then the steps; only the active step keeps its text. */
@media(max-width:900px){
  .wrap,.hero-inner,.final-inner{width:calc(100% - 64px)}
  .section{padding-block:88px 96px}
  .access-grid{grid-template-columns:minmax(0,1fr);grid-template-areas:"head" "stage" "list"}
  .access-stage{position:relative;top:auto;min-height:0;margin-top:40px;padding:32px 24px}
  .access-stage{display:none}
  .access-step,.access-step.is-active{border-left-color:var(--line)}
  .access-dot{display:none}
  .access-step .step-no,.access-step.is-active .step-no{color:var(--green)}
  .step-trigger{cursor:auto}
  .step-shot{display:grid;place-items:center;margin:16px 0 0 30px;padding:24px 16px;border-radius:var(--r-lg);background:url(assets/counter-pion-light-1024.webp) 38% 60%/cover no-repeat,var(--counter)}
  .step-shot img{width:min(100%,420px);height:auto;border-radius:var(--r-lg);box-shadow:var(--shadow-lie)}
  .step-shot-card{padding:0;overflow:hidden}
  .step-shot-card img{width:100%;border-radius:0;box-shadow:none;filter:brightness(1.035)}
  .access-list{margin-top:32px}
  .access-step{min-height:0;padding-bottom:20px}
  /* v1.9 (AI Canvas Slide Deck): on phones the four steps are a deck of cards, each with its own screen. The stack
     offsets were the source's (y 0/11/20, scale 1/.962/.926); v1.10: the back cards peek out on the right (app.js). */
  .access-steps{position:relative;display:block;max-width:460px;margin-inline:auto;height:var(--deck-h,540px);counter-reset:step}
  .access{overflow-x:clip}
  .access-step>*{flex-shrink:0}
  .access-step{position:absolute;inset:0;display:flex;flex-direction:column;padding:22px 22px 18px;border:0;border-radius:20px;background:var(--white);counter-increment:step;transform-origin:50% 100%;transition:transform 600ms cubic-bezier(.22,1.2,.36,1),opacity 400ms var(--ease-out),box-shadow 400ms var(--ease-out);touch-action:pan-y;user-select:none;-webkit-user-select:none}
  /* v1.10 round 6 (critic v1.10 r4 P2-3): cards behind the front one show clean edges, not their screens. */
  .access-step .step-shot{transition:opacity 200ms var(--ease-out)}
  .access-step:not(.is-front) .step-shot{opacity:0}
  .access-step.is-front{box-shadow:0 12px 40px rgb(37 59 51 / 16%),0 0 0 1px rgb(37 59 51 / 6%)}
  .access-step.is-dragging,.access-step.no-anim{transition:none}
  .step-trigger{display:flex;flex-direction:column;align-items:stretch}
  /* v1.10 round 5 (critic v1.10 r3 P2-3, owner 26.09): the place label in sentence case, as on desktop (the letter-spaced
     capitals read as a library component); the frame runs to the card's edges (no card inside a card). */
  .step-where{order:0;display:flex;justify-content:space-between;font-size:13px;line-height:18px;font-weight:600;color:var(--green)}
  .step-where::after{color:var(--body)}
  /* v1.12 r2 (critic medium v1.12 P2-2): one number per card (no "1 / 4"), half the size; the frame takes more of the card. */
  .step-where::after{content:none}
  .step-no{order:1;margin-top:8px;font-size:42px;line-height:.9;font-weight:100;letter-spacing:-.04em;color:var(--green)}
  .step-trigger strong{order:2;margin-top:12px;font-size:21px;line-height:26px;letter-spacing:-.01em}
  .step-text{margin:6px 0 0;font-size:14px;line-height:21px}
  .step-shot{margin:auto -22px -18px;height:290px;padding:0;border-radius:0 0 20px 20px;overflow:hidden;background:var(--app)}
  .step-shot img{width:100%;height:100%;object-fit:cover;object-position:50% 0;border-radius:0;box-shadow:none}
  .step-shot-card img{object-position:50% 50%}
  /* r8 (critic medium r17 P1-2): on phones too, step 1 is a close-up of the card (1.6: name and number, QR cut by the edge), not the hero's card again */
  /* r10 (critic medium r19 P2-1): one counter under the whole deck card; the card is the hero's cut-out with its own shadow lying on it (no second stone, no seam), close-up with the QR cut by the edge */
  .step-shot-card{position:relative;background:none;overflow:hidden;display:block}
  .step-shot-card .card-stack{position:absolute;left:4%;top:8%;width:128%}
  .step-shot-card .card-stack :is(.card-base,.card-shade,.card-glow){transform:none}
  .step-shot-card img{filter:none;box-shadow:none}
  /* r9 (critic medium r18 P2-1): the deck's cards are pieces of the portrait counter, not white SaaS cards */
  .access-step{background:url(assets/counter-pion-light-1024.webp) 50% 30%/cover no-repeat,var(--counter)}
  .deck-dots{display:flex;justify-content:center;gap:6px;margin-top:36px}
  .deck-dots button{position:relative;width:6px;height:6px;padding:0;border:0;border-radius:3px;background:rgb(37 59 51 / 22%);transition:width 400ms cubic-bezier(.34,1.3,.64,1),background-color 300ms}
  .deck-dots button::before{content:'';position:absolute;inset:-19px -8px}
  .deck-dots button[aria-current=step]{width:24px;background:var(--green)}
  /* One frame proportion for every step, so the stage does not leave empty space around the card. */
  .faq-grid{grid-template-columns:minmax(0,1fr)}
  .faq-intro{position:static}
  .site-header .brand,.menu-dialog-top .brand{font-size:24px}
}

/* v1.10 round 5 (critic v1.10 r3 P2-4, owner 26.09): tablets also get one action in the first screen. The island takes
   a fixed width, so hiding its action never moves the wordmark or the menu button. */
@media(min-width:761px) and (max-width:1100px){
  .site-header.island{width:min(480px,calc(100% - 48px));justify-content:space-between}
  .site-header .nav-cta{max-width:220px;overflow:hidden;white-space:nowrap}
  .site-header.hero-cta-on-screen .nav-cta{max-width:0;padding-inline:0;border-width:0;opacity:0;visibility:hidden}
  .site-header.cta-slides .nav-cta{transition:max-width 420ms var(--ease-out),padding 420ms var(--ease-out),opacity 260ms var(--ease-out),visibility 420ms,min-height 400ms var(--ease-out),transform 450ms cubic-bezier(.34,1.56,.64,1)}
}

/* Phones: */
@media(max-width:760px){
  html{scroll-padding-top:96px}
  .wrap,.hero-inner,.final-inner{width:calc(100% - 32px)}
  h2{font-size:28px;line-height:32px}
  /* v1.12 (critic MAX r10 P2-13): the sheet is narrower here, so its edge and photographed shadow shrink with it (x0.78):
     on a 3x screen the 130/170 px slices are enlarged 1.34x instead of 1.7x. The generation has no larger original. */
  .price-card::before{border-width:13px 76px 58px 12px}
  /* v1.12 (critic MAX r10 P2-9): a note's heading is one step below the section's H2, like the steps' titles in the deck. */
  .feat-item h3{font-size:21px;line-height:26px;letter-spacing:-.01em}
  .lead{font-size:17px;line-height:26px}
  .island{margin-top:16px;gap:12px;padding:6px 6px 6px 16px}
  .site-header{top:16px}
  .nav-actions{gap:8px}
  .brand{font-size:23px;line-height:28px}
  .nav-cta{padding:0 16px}
  .nav-cta .cta-full{display:none}
  .nav-cta .cta-short{display:inline}
  /* v1.10 (critic v1.10 P2-4): one action in the first screen. The island spans the width, so hiding its action
     never moves the wordmark or the menu button; the action collapses while the hero button is on screen. */
  .site-header.island{width:calc(100% - 32px);justify-content:space-between}
  /* v1.10: the compact island (after scrolling) keeps the phone sizes; its desktop 23 px wordmark and 24 px gap made it
     330 px wide at 320 px (a horizontal scroll since v1.8, missed because QA looked only at the top of the page). */
  .site-header.is-compact{padding:6px 6px 6px 16px;gap:12px}
  .site-header.is-compact .brand{font-size:23px}
  .site-header .nav-cta{max-width:160px;overflow:hidden;white-space:nowrap}
  .site-header.hero-cta-on-screen .nav-cta{max-width:0;padding-inline:0;border-width:0;opacity:0;visibility:hidden}
  .site-header.cta-slides .nav-cta{transition:max-width 420ms var(--ease-out),padding 420ms var(--ease-out),opacity 260ms var(--ease-out),visibility 420ms,min-height 400ms var(--ease-out),transform 450ms cubic-bezier(.34,1.56,.64,1)}
  .menu-dialog-links{padding:32px 24px}
  .mobile-menu a{font-size:32px;line-height:38px}
  .hero{margin-top:-78px;background-image:url(assets/counter-pion-light-1024.webp);background-position:30% 0}
  /* v1.10 (critic v1.10 P1-2, owner 25.09): tighter spacing and a slightly smaller phone (320 -> 292 px, UI 0.70), so
     at 390x844 the rows 11:30-13:45 are in the first screen and Marta's moment plays without scrolling. */
  .hero-inner{padding-block:110px 0;justify-items:stretch;text-align:left}
  /* r15 (S1, critic r25 P1-1): the headline ≥ 32 px under the island on phones */
  .hero h1{font-size:min(34px,calc((100vw - 32px) / 10));line-height:1.08;letter-spacing:-.03em}
  .hero h1 em{font-size:min(1em,(100vw - 32px) / 11.4)}
  .hero-description{margin:12px 0 0;font-size:16px;line-height:24px}
  .hero-actions{flex-direction:column;align-items:stretch;gap:12px;margin-top:18px}
  .hero-scene{--pw:min(250px,70vw);width:var(--pw);height:calc(var(--pw) * 3.1);margin:94px auto 0;justify-self:center}
  /* r14 (S1, critic r24 P3-1): at 390 the phone is 250 px, so Marta's row ends ≥ 90 px above the window's edge */
  .hero-device{left:0}
  .hero-scene{--m-origin-x:calc(var(--pw) * .55)}
  /* r11 (S1 P1-2): on phones the caption sits on the text's axis (16 px from the window), 11 px above the frame; no camera push here, so it never jumps */
  /* r12 (S1, critic r22 P1-1; replaces r11's text axis): on phones too the caption sits on the frame's left edge */
  .hero-device figcaption{bottom:calc(100% + var(--pw) * .0519 + 16px);margin-bottom:0}
  /* r15 (S1, critic r25 P3-1): 16 px above the frame, ≥ 40 px under the note */
  .hero.moment-play .hero-scene{animation:none}
  /* v1.8 (critic P1-3): the pair stays on phones. The same still card lies under the phone's lower edge, as on tablets,
     shifted left so its face (name and QR) fits the screen; its shadow may leave it on the right. */
  /* r13 (S1, critic r23 P1-2): the card lies whole on the counter: 100vw − 32 px wide (a little under true scale), centred, ≥ 40 px of stone under it */
  .prop-card{width:calc(100vw - 32px);left:calc((var(--pw) - 100vw) / 2 + 16px);top:calc(var(--pw) * 2.2)}
  .hero-scene{height:calc(var(--pw) * 2.2 + (100vw - 32px) * .711 + 40px)}
  /* r12 (S1, critic r22 P2-4): the card's printed strip starts below the frame (rule 3a: never cut by it) */
  .access-stage{padding:24px 16px;background-image:url(assets/counter-pion-light-1024.webp)}
  .stage-item{gap:12px}
  .access-control a{display:inline-block;margin:8px 0 0}
  .section{padding-block:56px 72px}
  .price-card{padding:32px 52px 60px 36px}
  .price-scene{padding:0}
  .price-stage{width:min(500px,100%)}
  .price-amount strong{font-size:72px}
  summary{padding:20px 0;font-size:16px;line-height:24px}
  details p{padding-right:0}
  .final-cta{background:linear-gradient(160deg,rgb(128 128 128 / 0) 55%,rgb(255 176 104 / .6) 75%,rgb(128 128 128 / 0) 95%),url(assets/counter-pion-light-1024.webp) 50% 50%/cover no-repeat,var(--counter);background-blend-mode:soft-light,normal}
  /* v1.8: the card stays on phones, whole and still, under the note (the shears and the light leave). */
  /* v1.11 r2 (critic medium v1.11 P1-4): Marta's card stays on phones, still, under the note, running off the section's
     lower edge (the flex column must stretch, or the scene collapses to zero width). */
  .final-cta{display:flex;flex-direction:column;align-items:stretch;min-height:0}
  .final-scene{position:static;order:2;display:flex;justify-content:center;padding:0 0 40px;margin-bottom:0}
  /* r7 (critic medium r16 P2-2): the card lies whole above the section's edge (no straight cut through the object) */
  .final-phone,.final-light{display:none}
  .final-card{position:static;width:min(70%,300px)}
  .final-inner{max-width:720px}
  .final-inner{padding-block:64px 32px}
  .footer{padding-block:40px 28px}
  .footer-top{flex-wrap:wrap;gap:12px 24px}
  .footer-top p{order:3;width:100%}
  .footer-bottom{flex-wrap:wrap}
  .footer-bottom nav{gap:16px;flex-wrap:wrap}
  .invitation-layout{grid-template-columns:1fr}
  .invitation-welcome{padding:24px;gap:0;background-image:url(assets/counter-pion-light-1024.webp)}
  .invitation-wordmark,.invitation-signature{display:none}
  .invitation-welcome .invitation-kicker{padding-right:40px}
  .invitation-welcome h2{font-size:30px}
  .invitation-welcome h2 em{display:inline}
  .invitation-body{padding:24px}
  .invitation-form-heading{display:none}
  .invitation-required{margin-bottom:16px}
  .invitation-success{min-height:320px}
  .product-dialog{padding:12px}
  .preview-header h2{font-size:26px;line-height:30px}
}

/* r11 (S1, critic r21 P3-1): at 320 × 700 Marta's 12:45 row plays in the first screen: tighter steps between the lines of the copy (no text changes). */
@media(max-width:360px){
  /* r12 (S1, critic r22 P2-3): a shorter stack of copy (15 px lead, 13 px note) and a 196 px phone, so Marta's row ends ≥ 48 px above the window's edge and the caption keeps 24 px from the note */
  .hero-inner{padding-top:102px}
  .hero-description{margin-top:8px;font-size:15px;line-height:22px}
  .hero-actions{margin-top:12px;gap:8px}
  .hero-note{font-size:13px;line-height:19px}
  .hero-note .nowrap{white-space:normal}
  /* r13 (S1 P3-2): the note breaks into two even lines, not one sentence per line */
  .hero-scene{--pw:196px;margin-top:79px}
  .hero-scene .hero-device figcaption{bottom:calc(100% + var(--pw) * .0519 + 11px)}
  /* r14 (S1, critic r24 P2-6): 196 px, the visits' text legible at 320 */
  .hero h1{font-size:26px}
}
@media(max-width:370px){
  .island,.site-header.is-compact{gap:10px;padding:6px 6px 6px 12px}
  .site-header.is-compact .brand{font-size:20px}
  .nav-actions{gap:6px}
  .site-header .brand,.menu-dialog-top .brand{font-size:20px}
  .nav-cta{padding:0 12px;font-size:13px}
  .menu-toggle,.menu-close{width:44px;height:44px}
  .mobile-menu a{font-size:28px;line-height:34px}
  .invitation-body,.invitation-welcome{padding:16px}
  .price-card{padding:28px 44px 56px 30px}
  .team-head{flex-direction:column;align-items:flex-start;gap:6px}
}

/* v1.8 (critic P2-7): the wordmark touched the action (4 px); at 320 px the island was also 4 px wider than the window. */
@media(max-width:340px){
  .nav-actions{gap:4px}
  .site-header.is-compact .brand{font-size:18.5px}
  .site-header .brand,.menu-dialog-top .brand{font-size:18.5px}
  .nav-cta{padding:0 10px}
}

/* v1.10 (owner 25.09): scroll parallax. Props lying on the counter slide a little against it while the section passes
   (from +d entering to -d leaving, so at rest in the middle of the screen they sit where the layout puts them).
   It uses the translate property, so it adds to the pointer layer and the drift (both transform). Each section gives
   its own view timeline: .final-cta clips (overflow:hidden), so view() on its children would never progress.
   Only objects that lie on top: never the nail file under the sheet, never the hero card under the phone (rule 11). */
@keyframes parallax{from{translate:0 var(--par)}to{translate:0 calc(var(--par) * -1)}}
@supports (animation-timeline:view()){
  .hero{view-timeline:--hero-view block}
  .final-cta{view-timeline:--final-view block}
  /* The shorthand resets animation-timeline and animation-range, so both follow it in the same rule. */
  .motion-ready :is(.prop-card,.final-card){animation:parallax linear both;animation-range:cover}
  .motion-ready :is(.prop-card){animation-timeline:--hero-view}
  .motion-ready .final-card{animation-timeline:--final-view}
  .prop-card,.final-card{--par:14px}
  @media(max-width:1100px){.motion-ready .prop-card{animation:none}}
}

/* Reduced motion: no drift, no pointer layer, no entrance, instant dialogs. */
@media(prefers-reduced-motion:reduce){
  .moment{display:none!important}
  .button,.nav-indicator,.site-header.island,.site-header .brand{transition:none}
  .button:hover,.button:active{transform:none}
  .hero-light,.final-light{display:none!important}
  .pile-card{transition:none}
  .feat-tile .plate::after{display:none}
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition:none!important}
  .scene-prop{transform:none!important}
  .motion-ready [data-reveal]:not(.is-visible){opacity:1;transform:none}
  .menu-dialog{opacity:1}
  .mobile-menu a{opacity:1;transform:none}
}
@media(prefers-reduced-transparency:reduce){.island,.menu-dialog{background:var(--paper);backdrop-filter:none;-webkit-backdrop-filter:none}}
@media(forced-colors:active){
  :where(a,button,input,textarea,summary,[tabindex]):focus-visible,.form-field :is(input,textarea):focus{outline:3px solid Highlight;outline-offset:2px}
  .button,.menu-toggle,.menu-close,.preview-zoom{border:1px solid ButtonText}
  .island,details,.price-card,.access-stage,.form-field :is(input,textarea){border-color:CanvasText}
  .menu-toggle span,.menu-close span{background:ButtonText;forced-color-adjust:none}
}
@media print{
  .site-header{position:static}
  .menu-toggle,.skip-link,dialog,dialog[open],.scene-prop{display:none!important}
  .hero{margin-top:0}
  .motion-ready [data-reveal]:not(.is-visible){opacity:1;transform:none}
  .motion-ready .hero-copy>*,.device-screen,.hero h1 .w{animation:none}
  .device-glint{display:none!important}
  .section{padding-block:32px}
  .access-step,.frag,.price-card,details{break-inside:avoid}
}
a:active,.desktop-nav a:active,.footer a:active{transform:translateY(1px)}

/* r14 (S1, critic r24 P2-3, P2-5): up to 999 px and on portrait tablets the caption is centred over the phone (one axis
   for the scene, one for the text). */
@media(max-width:760px){.hero-scene .hero-device figcaption{left:50%;right:auto;translate:-50% 0;text-align:center}}
/* r15: on portrait tablets the caption is back on the frame's left edge, the same axis as the left-aligned copy (critic r25 P2-1). */

/* ---------- r16 (S1, critic r26; owner 26.09 "opis pod telefon"): the hero on phones ----------
   Order: headline → caption on the text axis → the phone large (screen ≈ 335 px at 390, UI ≈ 0.85; ≈ 0.75 at 320), its
   metal close to the window's sides → Marta's card slid under the phone's lower edge (the printed strip wholly under it,
   rule 3a) → description, button and note. The window's lower edge cuts the phone between the 13:45 and 15:30 rows. */
@media(max-width:760px){
  .hero-copy{display:contents}
  .hero h1{order:1}
  .hero-scene{order:2}
  .hero-description{order:3;margin-top:28px}
  .hero-actions{order:4;margin-bottom:8px}
  .hero-scene{--pw:min(calc(100vw - 32px),372px);--cw:calc(100vw - 64px);width:var(--pw);height:calc(var(--pw) * 2.19 + var(--cw) * .56 + 24px);margin:62px 0 0;margin-inline:calc((100% - var(--pw)) / 2);justify-self:start}
  /* centred also when the phone is wider than the text column (≤ 360 px): auto margins would left-align it */
  .hero-scene .hero-device figcaption{left:calc((var(--pw) - 100vw) / 2 + 16px);translate:none;text-align:left;bottom:calc(100% + var(--pw) * .0519 + 12px)}
  .hero-scene .prop-card{width:var(--cw);left:calc((var(--pw) - 100vw) / 2 + 48px);top:calc(var(--pw) * 2.19 - var(--cw) * .15)}
}
@media(max-width:360px){.hero-scene{--pw:calc(100vw - 6px)}}

/* ---------- r17 (S1, critic r27; register of settled requirements) ---------- */
@media(max-width:760px){
  /* caption ≥ 32 px under the headline and 13 px above the visible metal (the device box), in the labels' green (rule 3b) */
  .hero-scene{margin-top:80px}
  .hero-scene .hero-device figcaption{bottom:calc(100% + 13px);color:var(--green)}
  /* ≈ 32 px from the card to the description */
  .hero-description{margin-top:8px}
}
/* ≤ 360 px: the visible metal ≥ 12 px from both window edges (UI ≈ 0.70) */
@media(max-width:360px){.hero-scene{--pw:calc(100vw - 24px)}}
/* portrait tablets 761–1100: the 1024 layout — headline across, then copy on the left with the card under it and the
   phone on the right (its frame starting ≤ 45% of the window's height), one scene instead of a phone pushed under the text */
@media(min-width:761px) and (max-width:1100px) and (orientation:portrait){
  .hero-inner{--pw:260px;grid-template-columns:minmax(0,1fr) calc(var(--pw) * 1.13);grid-template-rows:auto auto 1fr;column-gap:32px;justify-items:start;align-items:start;text-align:left;padding-bottom:140px}
  .hero-copy{display:contents}
  .hero h1{grid-column:1 / -1;grid-row:1;font-size:min(48px,calc((100vw - 64px) / 13))}
  .hero-description{grid-column:1;grid-row:2;margin:32px 0 0}
  .hero-actions{grid-column:1;grid-row:3;justify-content:flex-start;margin-top:24px}
  .hero-scene{grid-column:2;grid-row:2 / span 2;width:var(--pw);height:calc(var(--pw) * 2.094 + 16px);margin:72px 0 0;translate:none}
  .hero-scene .hero-device{left:0}
  /* the card on the copy's left edge, 16 px under the note: its left, relative to the scene = inner left − scene left */
  .hero-scene .prop-card{left:calc(var(--pw) * 1.13 + 64px - 100vw);top:calc(var(--pw) * .78)}
}
@media(min-width:901px) and (max-width:1100px) and (orientation:portrait){
  .hero-scene .prop-card{left:calc(var(--pw) * 1.13 + 96px - 100vw)}
}

/* r18 (S1, critic r28 P3-2): on phones the phone's lower edge casts a soft contact shadow on the card slid under it */
@media(max-width:760px){.hero-device .device-body{filter:drop-shadow(0 8px 10px rgb(52 40 28 / .28))}}
/* r18 (S1, critic r28 P2-2): iPad in landscape — a ~520 px text column with a 46 px headline, the card on the text axis
   16–24 px under the note, no dead strip between the column and the phone */
@media(min-width:1000px) and (max-width:1100px) and (orientation:landscape){
  .hero-inner{grid-template-columns:520px minmax(0,1fr)}
  .hero h1{font-size:46px}
  .hero h1 em{font-size:min(1em,520px / 11.4)}
  .hero-copy{max-width:520px}
  .hero-scene .prop-card{left:-552px;top:calc(var(--pw) * 1.29 + 26px)}
  .hero-actions{margin-top:20px;gap:12px}
}

/* ---------- r19 (S1, critic r29) ---------- */
/* R19/R7 (critic r29 register change): from 1280 px the card slid under the metal lies still — no drift, no lean, no
   scroll parallax (rule 11: nothing moves under a still object); only its highlight follows the pointer. */
@media(min-width:1280px){
  .hero-scene .prop-card{animation:none;translate:none;transform:none}
  .hero-scene .prop-card .prop-drift{animation:none;transform:none}
}
/* P2-1: iPad in landscape — the card 8% smaller, 16 px under the note, its print and shadow ≥ 28 px above the window's edge
   (the column rises 12 px: description 18 px, button 14 px under the text before it). */
@media(min-width:1000px) and (max-width:1100px) and (orientation:landscape){
  .hero-description{margin-top:18px}
  .hero-actions{margin-top:14px}
  .hero-scene .prop-card{width:calc(var(--pw) * 1.3722 * .92);top:calc(var(--pw) * 1.29 + 8px)}
}
/* P2-2: portrait tablets — the card's right edge 28 px from the phone's metal (the metal starts ≈ .03 pw into the frame,
   the print ends ≈ .0446 pw before the card box), same height as before: one scene, not two specimens. */
@media(min-width:761px) and (max-width:1100px) and (orientation:portrait){
  .hero-scene .prop-card{left:calc(var(--pw) * -1.2976 - 28px)}
}
/* P3-1: ≤ 360 px — the window's edge must cut between rows: below the 18:00 row and the + button, not through them.
   Headline 25 px, 32 px from it to the caption, the caption 8 px above the metal (R4 allows ≤ 14): the metal starts ≈ 240 px. */
@media(max-width:360px){
  .hero h1{font-size:25px}
  .hero-scene{margin-top:58px}
  .hero-scene .hero-device figcaption{bottom:calc(100% + 8px)}
}

/* ---------- r20 (S1, critic r30) ---------- */
/* R7 (critic r30 register change): the card turns clockwise, so its lowest printed line reaches deeper under the phone
   than the name; every printed glyph now keeps ≥ 12 px from the metal (the tuck ≈ 10 px, ≥ 32 px to the window's right). */
@media(min-width:1280px){.hero-scene .prop-card{left:calc(var(--pw) * .948 + 5px)}}
/* P3-2: at 1440 the text block's centre sits on the 12:45–13:45 rows, not on the frame's centre. */
@media(min-width:1101px) and (min-height:840px){.hero-copy{top:-24px}}
/* P2-2, P3-1: on phones 32 px from the headline to the caption and 8 px from the caption to the metal, so at 390×844 the
   18:00 row and the + button stay whole above the window's edge (R4). */
@media(max-width:760px){
  .hero-scene{margin-top:58px}
  .hero-scene .hero-device figcaption{bottom:calc(100% + 8px)}
}

/* ---------- r21 (S1, critic r31) ---------- */
/* P2-1: iPad in landscape — the phone 8% larger (270 px), its metal 48 px from the window's right edge, the same margin
   as the text on the left; it rises 20 px, so the frame still ends above the window's edge. The card keeps its place
   and size (R15), now in fixed units so that the larger phone does not move it. */
@media(min-width:1000px) and (max-width:1100px) and (orientation:landscape){
  .hero-inner{--pw:270px}
  .hero-scene{margin-top:32px}
  .hero-device{right:0}
  .hero-scene .prop-card{width:316px;top:351px}
}
/* P2-2: on tablets the caption belongs to the phone — 14 px above the metal (R4 axis unchanged: the metal's left edge,
   ≥ 40 px under the island). At 768 the scene stands 20 px lower so the caption is not level with the description's
   first line; the card stays where it was. */
@media(min-width:761px) and (max-width:1100px){.hero-scene .hero-device figcaption{bottom:calc(100% + 14px)}}
@media(min-width:761px) and (max-width:1100px) and (orientation:portrait){
  .hero-scene{margin-top:92px}
  .hero-scene .prop-card{top:calc(var(--pw) * .78 - 20px)}
}
/* P3-1: on phones the fade into paper starts ≥ 32 px under the note (72 px fade in a 104 px bottom margin). */
@media(max-width:760px){
  .hero-inner{padding-bottom:104px}
  .hero::after{height:72px}
}

/* ---------- r22 (S1, critic r32) ---------- */
/* P3-1: the moment's veil (R13, over the visit list) keeps the + button at full colour: a round hole in its mask where the
   button stands (centre 90.1% × 71.7% of the screen, radius ≈ 7.5% of the screen's width). */
.device::after{-webkit-mask:radial-gradient(circle calc(var(--pw) * .0701) at 90.08% 71.7%,transparent 97%,#000 100%);mask:radial-gradient(circle calc(var(--pw) * .0701) at 90.08% 71.7%,transparent 97%,#000 100%)}
/* P2-1 (critic r32 register change R15): iPad in landscape — the card lies in the strip between the text and the phone,
   its right edge 72 px from the metal, 16 px under the note: card and calendar in one field of view. */
@media(min-width:1000px) and (max-width:1100px) and (orientation:landscape){.hero-scene .prop-card{left:-265px}}
/* P2-2, P3-2 (R4, R14): portrait tablets — the caption in the gap between the headline and the description (≈ 9 px from
   each, 14 px line), the metal 14 px under it; the scene at the column's right edge, so the metal is 32 px from the window
   like the text; the card moves with the scene (still 28 px from the metal) and keeps its height. */
@media(min-width:761px) and (max-width:1100px) and (orientation:portrait){
  .hero-scene{margin-top:37px;justify-self:end}
  .hero-scene .hero-device figcaption{line-height:14px}
  .hero-scene .prop-card{top:calc(var(--pw) * .78 + 35px)}
}

/* ---------- r23 (S1, critic r33) ---------- */
/* R4 (critic r33 register change): on phones 24 px from the headline to the caption (≤ 360 px: 20 px), 8 px from the
   caption to the metal — the + button keeps a clear margin above the window's edge (390: ≥ 16 px, 320: ≥ 12 px). */
@media(max-width:760px){.hero-scene{margin-top:50px}}
@media(max-width:360px){.hero-scene{margin-top:46px}}
/* P3-3: portrait tablets — the fade into paper starts ≈ 40 px under the phone, the hero shorter by the dead band. */
@media(min-width:761px) and (max-width:1100px) and (orientation:portrait){.hero-inner{padding-bottom:120px}.hero::after{height:72px}}

/* ---------- r24 (S1, critic r34) ---------- */
/* P2-1: the camera's hold on Marta's row is sharp. One keyframe animation kept the scene's layer animating (rasterised
   at scale 1 and stretched) through the whole hold; now the push is two animations — in, then (app.js, after the hold)
   out — so during the hold nothing runs and the browser redraws the scene at the zoomed scale. Same timing and curve. */
@keyframes push-in{from{scale:1}to{scale:var(--m-peak)}}
@keyframes push-out{from{scale:var(--m-peak)}to{scale:1}}
@media(min-width:761px){
  .hero-scene{--m-peak:1.035;--m-in:1064ms;--m-hold:672ms;--m-out:1064ms}
  .hero.moment-play .hero-scene{animation:push-in var(--m-in) var(--ease-rcrut) calc(var(--m-delay) - 500ms) both}
  .hero.moment-play.moment-push-out .hero-scene{animation:push-out var(--m-out) var(--ease-rcrut) both}
}
@media(min-width:1101px){.hero-scene{--m-peak:1.08;--m-in:1120ms;--m-hold:2080ms;--m-out:800ms}}
@media(min-width:1101px) and (max-width:1600px){.hero-scene{--m-peak:1.035}}
/* P3-1: the veil's opening on Marta's row has soft edges (≈ 12 px, 2% of the screen's height), so it never reads as a
   selection drawn in the UI; 28% and the list-only extent (R13) unchanged. */
.device::after{background:linear-gradient(rgb(244 244 247 / 0) 0 33.4%,rgb(244 244 247 / 28%) 33.5% 42.6%,rgb(244 244 247 / 0) 44.6% 50.6%,rgb(244 244 247 / 28%) 52.6% 77%,rgb(244 244 247 / 0) 77.1% 100%)}
/* P3-2: on phones the card lies centred under the frame (32 px from both window edges). */
@media(max-width:760px){.hero-scene .prop-card{left:calc((var(--pw) - 100vw) / 2 + 32px)}}

/* ---------- r25 (S2 „Jak to działa”, critic r35) ---------- */
@media(min-width:901px){
  /* P2-1, P3-1: Marta's card lies ~10 cqw further left on the counter — at step 1 its QR stands clear of the counter's edge,
     at steps 3–4 no broken printed words stand at the window's left edge (the frame starts at the QR). */
  .access-stage{--card-x:64.3cqw}
  .stage-hit-card{left:calc(var(--bleed) / 2 + 40px - 4.9cqw)}
  /* P2-2, P2-3: the counter fades into the page's paper along its right edge (96 px), never a hard seam cutting objects;
     its lower edge fades over 32 px only, placed between rows of the menu. */
  .access-stage{-webkit-mask-image:linear-gradient(#000 calc(100% - 32px),transparent),linear-gradient(to left,transparent,#000 96px);-webkit-mask-composite:source-in;mask-image:linear-gradient(#000 calc(100% - 32px),transparent),linear-gradient(to left,transparent,#000 96px);mask-composite:intersect}
  /* P1-1: at steps 2 and 3 the phone lies lower, so the window's lower edge cuts its screen just under the content
     (under „Potwierdź aktywację”, under „…nikt o niego nie poprosi”), not through half an empty grey screen. */
  .access-stage[data-step="2"] :is(.strip-screen-salon,.strip-reflect-salon,.strip-body-salon){translate:0 var(--t2)}
  .access-stage[data-step="3"] :is(.strip-screen-pin,.strip-screen-booking,.strip-reflect-klientka,.strip-body-klientka){translate:0 var(--t3)}
  .access-stage{--t2:calc(80svh - 32px - var(--pw) * 1.19);--t3:calc(80svh - 32px - var(--pw) * 1.088)}
  /* P2-3: at step 4 the lower fade falls between the menu's second and third rows */
  .access-stage[data-step="4"] :is(.strip-screen-pin,.strip-screen-booking,.strip-reflect-klientka,.strip-body-klientka){translate:0 calc(80svh - 16px - var(--pw) * 1.2205)}
  /* P2-4: the step in the camera's frame reads first: the other steps' numbers and titles in the field grey (as the notes
     of „Możliwości”, rule 46), their text unchanged; the change runs on the camera's curve. */
  .access-step:not(.is-active) :is(.step-no,.step-trigger strong){color:var(--field)}
  .step-trigger strong{transition:color 950ms var(--ease-rcrut)}
  .step-no{transition:color 950ms var(--ease-rcrut)}
  /* P3-4: the scene's label names the place; the step's kicker repeated it (it stays on phones, which have no label). */
  .step-where{display:none}
}
/* P2-3: ≤ 80 px of paper between the counter's end and the pause (the section overlaps the pause's top padding by 60 px). */
@media(min-width:901px){#jak-to-dziala{margin-bottom:-60px}}
/* P2-5: on phones the step-1 card is framed at 1.15 (was 1.28), its QR whole and ≥ 16 px inside the deck card; the cut
   falls on the card's right margin. */
@media(max-width:900px){.step-shot-card .card-stack{left:-4%;width:115%}}
/* On phones the deck's step-2 screen shows at 84% so the card's edge cuts under „Potwierdź aktywację” (rule 14), not through it;
   the screen's own background (#f2f2f6) fills the sides. */
@media(max-width:900px){.access-step[data-step="2"] .step-shot img{width:84%;margin-inline:auto;display:block}}

/* ---------- r26 (S2, critic r36) ---------- */
@media(min-width:901px){
  /* P1-1 (register S2-3, critic r36): the edge mask fades only the stone — the card and phones end ≥ 16 px before it at
     every stop (or leave the frame), never half-transparent. P2-1: the counter's foot fades out between 40 and 16 px
     above its edge, inside the gap between the menu's second and third rows (no ghost of the third row). */
  .access-stage{-webkit-mask-image:linear-gradient(#000 calc(100% - 40px),transparent calc(100% - 16px)),linear-gradient(to left,transparent,#000 96px);mask-image:linear-gradient(#000 calc(100% - 40px),transparent calc(100% - 16px)),linear-gradient(to left,transparent,#000 96px)}
  .stage-strip{transition:translate 950ms var(--ease-rcrut),scale 950ms var(--ease-rcrut),transform-origin 950ms var(--ease-rcrut)}
  /* step 1: the whole card in the field before the mask (close-up 1.2; 1.12 and 1.1 on narrower windows) */
  .access-stage[data-step="1"] .stage-strip{scale:var(--s1);translate:calc(var(--cam1) + var(--c1dx)) 0}
  .access-stage{--s1:1.2;--c1dx:-26px}
  /* step 2: the card slides out with the camera and fades fast, as the salon phone does at step 1 (r9) */
  .access-stage:not([data-step="1"]) .strip-card{opacity:0}
  .access-stage[data-step="1"]{--client-x:215cqw}
  .strip-card{transition:translate 700ms var(--ease-rcrut),opacity 200ms var(--ease-out)}
  /* P2-2: steps 2–4 — the camera closer to the phone (1.25: UI ≈ 1.13), the frame's top in the upper third, the cut under
     the content as S2-1 requires (offsets recomputed for the scale about the counter's top) */
  .access-stage{--s2:1.25;--c3dx:-130px;--f4:28px}
  .access-stage[data-step="2"] .stage-strip{scale:var(--s2);transform-origin:calc(var(--pw) * .531) 0}
  .access-stage:is([data-step="3"],[data-step="4"]) .stage-strip{scale:var(--s2);transform-origin:calc(var(--client-x) + var(--pw) * .5248) 0;translate:calc(var(--cam3) + var(--c3dx)) 0}
  .access-stage{--t2:calc((100svh - 32px) / var(--s2) - 20svh - var(--pw) * 1.19);--t3:calc((100svh - 32px) / var(--s2) - 20svh - var(--pw) * 1.088)}
  .access-stage[data-step="4"] :is(.strip-screen-pin,.strip-screen-booking,.strip-reflect-klientka,.strip-body-klientka){translate:0 calc((100svh - var(--f4)) / var(--s2) - 20svh - var(--pw) * 1.2205)}
  /* the scene's label 14 px above the phone's metal, on its left edge (as the hero's caption) */
  #stage-2 .stage-label{left:calc(var(--bleed) + 40px + var(--pw) * .531 * (1 - var(--s2)));top:calc(var(--s2) * (20svh - var(--pw) * .03226 + var(--t2)) - 32px)}
  #stage-3 .stage-label{left:calc(var(--bleed) + 40px + var(--cam3) + var(--c3dx) + var(--client-x) + var(--pw) * .5248 * (1 - var(--s2)));top:calc(var(--s2) * (20svh - var(--pw) * .03226 + var(--t3)) - 32px)}
  #stage-4 .stage-label{left:calc(var(--bleed) + 40px + var(--cam3) + var(--c3dx) + var(--client-x) + var(--pw) * .5248 * (1 - var(--s2)));top:calc(var(--s2) * (20svh - var(--pw) * .03226 + (100svh - var(--f4)) / var(--s2) - 20svh - var(--pw) * 1.2205) - 32px)}
  /* the zoom buttons over the scaled screens */
  .stage-hit-salon{left:calc(var(--bleed) + 40px + var(--pw) * (.531 * (1 - var(--s2)) + var(--s2) * .03226));width:calc(var(--pw) * .93548 * var(--s2));height:calc(var(--pw) * 2.028 * var(--s2));top:calc(var(--s2) * (20svh + var(--t2)))}
  .stage-hit-client{left:calc(var(--bleed) + 40px + var(--cam3) + var(--c3dx) + var(--client-x) + var(--pw) * (.5248 * (1 - var(--s2)) + var(--s2) * .03226));width:calc(var(--pw) * .93548 * var(--s2));height:calc(var(--pw) * 2.028 * var(--s2));top:calc(var(--s2) * (20svh + var(--t3)))}
}
@media(min-width:1400px){.access-stage{--c3dx:-170px}}
@media(min-width:1101px) and (max-width:1399px){.access-stage{--c3dx:-145px}}
@media(min-width:1101px) and (max-width:1399px){.access-stage{--s1:1.12}}
@media(min-width:901px) and (max-width:1100px){.access-stage{--s1:1.1;--f4:19px;--c3dx:-135px;-webkit-mask-image:linear-gradient(#000 calc(100% - 36px),transparent calc(100% - 16px)),linear-gradient(to left,transparent,#000 96px);mask-image:linear-gradient(#000 calc(100% - 36px),transparent calc(100% - 16px)),linear-gradient(to left,transparent,#000 96px)}}
/* P2-3, P2-4, P2-5, P3-1, P3-2 (S2-6 at 768, 390 and 320): the deck's frames keep the proportion that works at 390
   (358 × 290), so every width shows the same part of each screen: the whole button with room under it at step 2, the
   app's own margins, the card's print whole at step 1, the step-4 cut under the menu field. */
@media(max-width:900px){
  .step-shot{height:auto;aspect-ratio:358 / 290}
  .access-step[data-step="2"] .step-shot img{height:auto;object-fit:fill}
}

/* ---------- r27 (S2, critic r37) ---------- */
/* P2-1, P3-4: at step 1 the scene's label lies on the counter 14 px above the card's upper-left corner (the rotated print's
   corner is at 8.35% × 0.49% of the card's box), as the phones' labels do at steps 2–4; it travels with the card. The
   figure's own label stays for screen readers. */
.strip-label{display:none}
@media(min-width:901px){
  .strip-label{display:block;position:absolute;left:8.35%;bottom:calc(99.51% + 14px / var(--s1));white-space:nowrap;font-size:calc(13px / var(--s1));line-height:calc(18px / var(--s1));font-weight:600;color:var(--green);transition:opacity 200ms var(--ease-out)}
  .access-stage:not([data-step="1"]) .strip-label{opacity:0}
  #stage-1 .stage-label{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}
  /* S2-4 (critic r37 register change): an inactive step fades as a whole — its title in the text's own colour (never
     weaker than the description under it), its number in the field grey; the active title in ink. */
  .access-step:not(.is-active) .step-trigger strong{color:var(--body)}
  .access-step:not(.is-active) .step-no{color:var(--field)}
}
/* P3-1: a phone wakes in one move from black to its screen (900 ms after the camera stops), no grey plateau */
@keyframes strip-wake{from{filter:brightness(0) saturate(0)}to{filter:brightness(1) saturate(1)}}
/* P3-2: the deck's step numbers in Light (rule 19a), a thin hairline read as a stroke */
@media(max-width:900px){.step-no{font-weight:300}}
/* P2-4: at 761–900 px the deck stands on the text's axis, not centred */
@media(min-width:761px) and (max-width:900px){.access-steps{margin-inline:0}}

/* ---------- r28 (S2, critic r38) ---------- */
@media(min-width:901px){
  /* S2-1 (critic r38 register change): the pinned counter is 40 px taller than the window, so at the stops the window's
     edge cuts the phone cleanly; the foot's fade (40→16 px) lies below the window and shows only as the scene leaves.
     At step 4 the cut falls between the menu's second and third rows. */
  .access-stage{min-height:calc(100svh + 40px);--py:calc(20svh - var(--pw) * .03226);--f4:0px}
  #jak-to-dziala{margin-bottom:-100px}
}
/* S2-3 / S2-8 (critic r38 register change): at 901–1100 px the counter's edge mask is 48 px, which leaves room for the step-1
   close-up at 1.2 and for a larger phone at steps 2–4 (1.45: the frame's top ≤ 38% of the window). */
@media(min-width:901px) and (max-width:1100px){
  .access-stage{--s1:1.2;--s2:1.45;--f4:0px;--c1dx:-13px;-webkit-mask-image:linear-gradient(#000 calc(100% - 40px),transparent calc(100% - 16px)),linear-gradient(to left,transparent,#000 48px);mask-image:linear-gradient(#000 calc(100% - 40px),transparent calc(100% - 16px)),linear-gradient(to left,transparent,#000 48px)}
}
/* P2-4, P3-2 (S2-6): on phones the deck's screens are plates lying on the card's stone — 12 px of stone at the sides, 8 px
   above, rounded corners, the photographed plate shadow of „Możliwości” (rule 15b) — each cut in its own gap: under the
   button (step 2), under the note (step 3), between the menu field and the search field (step 4). */
@media(max-width:900px){
  .step-shot:not(.step-shot-card){display:block;padding:8px 12px 0;background:none;overflow:visible}
  .step-shot .shot-plate{width:100%;margin-inline:auto;border-radius:14px;background:var(--app)}
  .access-step .step-shot .shot-plate img{display:block;width:100%;height:auto;margin:0;object-fit:cover;object-position:50% 0;border-radius:inherit}
  .access-step[data-step="2"] .step-shot .shot-plate{width:80%}
  .access-step[data-step="2"] .shot-plate img{aspect-ratio:786 / 720}
  .access-step[data-step="3"] .shot-plate img{aspect-ratio:786 / 642}
  .access-step[data-step="4"] .shot-plate img{aspect-ratio:786 / 608}
}
/* P3-1: at 761–900 px the deck is centred again (owner 25.09: „talia na tablecie na środku”; r38 had put it on the text axis) */
@media(min-width:761px) and (max-width:900px){.access-steps{margin-inline:auto}}

/* ---------- r29 (S2, critic r39) ---------- */
@media(max-width:900px){
  /* P2-1: the step-2 plate at the PIN plate's scale (12 px of stone at the sides): the activation screen cropped from just
     above „Karta Marty” (y 110 of the 2× crop) to the gap under „Potwierdź aktywację” (y 707) */
  .access-step[data-step="2"] .step-shot .shot-plate{width:100%}
  .access-step[data-step="2"] .shot-plate img{aspect-ratio:786 / 597;object-position:50% 74.8%}
  /* P3-3: step 1 — the card lies right under the text (no empty stone above it): the frame fills the card's free height */
  .step-shot-card{aspect-ratio:auto;flex:1 1 auto;min-height:260px;margin-top:12px}
  .step-shot-card .card-stack{top:0}
}
/* P3-4: at ≤ 360 px the step-4 plate ends ≥ 6 px under the menu field (still above the search field) */
@media(max-width:360px){.access-step[data-step="4"] .shot-plate img{aspect-ratio:786 / 610}}
/* P2-2 (critic r39 register change S2-3): step 1 — the card centred in the stone field (equal room to the window's edge
   and to the mask, each ≥ 56 px at 1440): close-up 1.07 (1101–1399: 1.0), still ≥ 1.3× the hero's card */
@media(min-width:1101px){.access-stage{--s1:1.07;--c1dx:-15px}}
@media(min-width:1101px) and (max-width:1399px){.access-stage{--s1:1;--c1dx:-8px}}

/* ---------- r30 (S2, critic r40) ---------- */
/* S2-1 (critic r40 register change): the counter's foot fades within the ~6 px gap under the menu's second row (at the
   window's edge at the stops, 40 px above the stage's end), so no pixel of the third row shows, not even as it leaves. */
@media(min-width:901px){
  .access-stage{-webkit-mask-image:linear-gradient(#000 calc(100% - 43px),transparent calc(100% - 37px)),linear-gradient(to left,transparent,#000 96px);mask-image:linear-gradient(#000 calc(100% - 43px),transparent calc(100% - 37px)),linear-gradient(to left,transparent,#000 96px)}
}
@media(min-width:901px) and (max-width:1100px){
  .access-stage{-webkit-mask-image:linear-gradient(#000 calc(100% - 43px),transparent calc(100% - 37px)),linear-gradient(to left,transparent,#000 48px);mask-image:linear-gradient(#000 calc(100% - 43px),transparent calc(100% - 37px)),linear-gradient(to left,transparent,#000 48px)}
  /* S2-3 (critic r40 register change): step 1 at 1.1 — room on both sides of the card, still ≥ 1.3× the hero's card */
  .access-stage{--s1:1.1;--c1dx:-2px}
}
/* S2-6 (critic r40 register change): the deck's plates fill the card's free height under the text. Step 4 sets the deck's
   height: its plate runs from the wizard's tabs to the gap under the second service (two services with time and price).
   Steps 2 and 3 show the full screens, their bottom fixed in the gap under the content, growing upwards to the screen's
   title (and beyond it, to the status bar, where there is room). */
@media(max-width:900px){
  .step-shot:not(.step-shot-card){flex:1 1 auto;display:flex;flex-direction:column;margin:12px -22px -18px;aspect-ratio:auto;height:auto;padding:8px 12px 12px}
  .access-step[data-step="4"] .shot-plate img{aspect-ratio:786 / 905}
  .access-step:is([data-step="2"],[data-step="3"]) .step-shot .shot-plate{flex:1 1 auto;position:relative;overflow:hidden;min-height:200px}
  .access-step:is([data-step="2"],[data-step="3"]) .shot-plate img{position:absolute;left:0;bottom:0;aspect-ratio:auto;height:auto;object-fit:fill}
  .access-step[data-step="2"] .shot-plate img{translate:0 calc((1704 - 1027) / 1704 * 100%)}
  .access-step[data-step="3"] .shot-plate img{translate:0 calc((1704 - 952) / 1704 * 100%)}
  /* P3-3: step 1 — the card bleeds on the right only (its lower-left corner ≥ 12 px inside, QR ≥ 16 px from the right) */
  .step-shot-card .card-stack{left:3.5%;width:108%}
}
@media(max-width:360px){.access-step[data-step="4"] .shot-plate img{aspect-ratio:786 / 905}}
@media(max-width:900px){
  /* step 1: the card centred in the free height (bleeding on the right only) */
  .step-shot-card{display:flex;align-items:center}
  .step-shot-card .card-stack{position:relative;left:auto;top:auto;flex:none;margin-left:3.5%}
}
@media(max-width:900px){
  /* a plate never taller than its screen above the cut (no empty app strip above the status bar) */
  .step-shot:not(.step-shot-card){container-type:inline-size}
  .access-step[data-step="2"] .step-shot .shot-plate{max-height:calc(100cqw * 1027 / 786);margin-top:auto}
  .access-step[data-step="3"] .step-shot .shot-plate{max-height:calc(100cqw * 952 / 786);margin-top:auto}
}

/* ---------- r31 (S2, critic r41) ---------- */
@media(max-width:900px){
  /* P3-1 (S2-6): one bottom margin (12 px) and one photographed shadow for the plates of steps 2–4 — the crop moves to an
     inner box, so the plate's 9-slice shadow is not clipped; step 4 (the tallest by content) sets the deck's height */
  .access-step:is([data-step="2"],[data-step="3"]) .step-shot .shot-plate{overflow:visible;min-height:120px}
  .shot-crop{display:block;border-radius:inherit}
  .access-step:is([data-step="2"],[data-step="3"]) .shot-crop{position:absolute;inset:0;overflow:hidden}
  .step-shot-card{min-height:180px}
}
@media(min-width:901px){
  /* P3-2: the counter ends in a slab edge — its last 4 px darken like the stone's contact shadow, over a short cut */
  .access-stage{-webkit-mask-image:linear-gradient(#000 calc(100% - 38px),transparent calc(100% - 37px)),linear-gradient(to left,transparent,#000 96px);mask-image:linear-gradient(#000 calc(100% - 38px),transparent calc(100% - 37px)),linear-gradient(to left,transparent,#000 96px)}
  .access-stage::after{content:'';position:absolute;left:0;right:0;top:calc(100% - 42px);height:5px;z-index:4;pointer-events:none;background:linear-gradient(rgb(70 76 68 / 0),rgb(70 76 68 / .26))}
  /* P3-3: the client's phone shows only after it has crossed the edge mask (no black slab sliding through the mask):
     hidden at steps 1–2, it appears 700 ms into the camera's move (150 ms), and leaves at once */
  :is(.strip-body-klientka,.strip-screen-pin){transition:left 950ms var(--ease-rcrut),translate 950ms var(--ease-rcrut),filter 200ms var(--ease-out),opacity 150ms var(--ease-out) 700ms}
  .access-stage:is([data-step="1"],[data-step="2"]) :is(.strip-body-klientka,.strip-screen-pin,.strip-reflect-klientka){opacity:0;transition:left 950ms var(--ease-rcrut),translate 950ms var(--ease-rcrut),filter 200ms var(--ease-out),opacity 120ms var(--ease-out)}
  /* P2-2: at 901–1100 the phones of steps 2–4 stand ≥ 40 px from the window's left edge */
  .access-stage{--c2dx:0px}
  .access-stage[data-step="2"] .stage-strip{translate:calc(var(--cam2) + var(--c2dx)) 0}
  #stage-2 .stage-label{left:calc(var(--bleed) + 40px + var(--c2dx) + var(--pw) * .531 * (1 - var(--s2)))}
  .stage-hit-salon{left:calc(var(--bleed) + 40px + var(--c2dx) + var(--pw) * (.531 * (1 - var(--s2)) + var(--s2) * .03226))}
}
@media(min-width:901px) and (max-width:1100px){
  .access-stage{--c2dx:28px;--c3dx:-107px;-webkit-mask-image:linear-gradient(#000 calc(100% - 38px),transparent calc(100% - 37px)),linear-gradient(to left,transparent,#000 48px);mask-image:linear-gradient(#000 calc(100% - 38px),transparent calc(100% - 37px)),linear-gradient(to left,transparent,#000 48px)}
}

/* ---------- r32 (S2, critic r42) ---------- */
@media(max-width:900px){
  /* P2-2: the step-1 card no longer sets the deck's height (it was in the flow, 275 px): it is centred absolutely in the
     free height, so step 4 (two services) sets it and its plate ends 12 px above the card's edge like plates 2–3 */
  .step-shot-card .card-stack{position:absolute;left:3.5%;top:50%;translate:0 -50%;margin-left:0}
}
@media(max-width:900px){
  /* the free height of step 4's card goes above its plate (the plate ends 12 px above the card's edge like plates 2–3) */
  .access-step[data-step="4"] .step-shot .shot-plate{margin-top:auto}
  /* P3-3: step 1 — the card lies 56 px under the text (not centred in the free height); its QR stays whole */
  .step-shot-card{align-items:flex-start}
  .step-shot-card .card-stack{top:44px;translate:none}
}
@media(min-width:901px){
  /* P3-1: coming from step 2, the label of step 3 appears with the client's phone, not before it on empty stone; the phone
     comes in over 300 ms */
  .access-stage[data-prev="2"] #stage-3.is-active{transition:opacity 300ms var(--ease-out) 850ms,transform 480ms var(--ease-out) 850ms,visibility 0s}
  :is(.strip-body-klientka,.strip-screen-pin){transition:left 950ms var(--ease-rcrut),translate 950ms var(--ease-rcrut),filter 200ms var(--ease-out),opacity 300ms var(--ease-out) 650ms}
}
/* P3-4: a card that leaves the top of the deck drops its text in 120 ms, so no two texts are seen at once while dealing */
@media(max-width:900px){
  .access-step>:not(.step-shot){transition:opacity 120ms var(--ease-out)}
  .access-step:not(.is-front)>:not(.step-shot){opacity:0}
}

/* ---------- r33 (S2, critic r43) ---------- */
/* P3-1 (S2-6): the step-1 card in the deck lies at the optical centre of the free height — 44% of the free stone above it,
   56% below (the card is 76.77% of the frame's width tall: 108% width × 595/837) */
@media(max-width:900px){
  .step-shot-card{container-type:inline-size}
  .step-shot-card .card-stack{top:calc((100% - 76.77cqw) * .44)}
}

/* ---------- r34 (S2, critic r43 P2-1; Astra consultation 27.09) ----------
   The scene leaves without any object being cut by the counter's edge: the whole group of objects (card, phones,
   screens, reflections, shadows — not the stone) fades out on the last 160 px of scroll, ending 64 px before the scene
   unpins; on the way back it returns only once the scene is pinned again. Driven by scroll position (app.js), not time. */
@media (min-width: 901px) {
  #jak-to-dziala .access-list{padding-bottom:calc(35svh + var(--s2-exit-tail, 0px))}
  #access-stage .s2-exit-objects{position:absolute;inset:0;opacity:var(--s2-exit-alpha, 1);pointer-events:none;transition:none}
  #access-stage .stage-item > .stage-label{opacity:var(--s2-exit-alpha, 1);transition:none}
  #access-stage.s2-exit-empty :is(.s2-exit-objects, .stage-item){visibility:hidden !important}
}

/* ---------- r35 (S2, critic r44) ---------- */
@media(min-width:901px){
  /* P2-1 (S2-5, critic r44 register change): with the objects the stone too fades into the page's paper, in the same
     scroll window and before the release — no empty slab crosses the window, the counter's edge is never seen */
  #access-stage{opacity:var(--s2-exit-alpha,1)}
  /* P3-1: the pan 2→3 never shows an empty frame — the client's phone comes in 430 ms into the move (120 ms), while the
     salon's phone is still leaving at the window's left edge (they overlap for ~60 ms) */
  :is(.strip-body-klientka,.strip-screen-pin){transition:left 950ms var(--ease-rcrut),translate 950ms var(--ease-rcrut),filter 200ms var(--ease-out),opacity 120ms var(--ease-out) 430ms}
  .access-stage[data-prev="2"] #stage-3.is-active{transition:opacity 300ms var(--ease-out) 550ms,transform 480ms var(--ease-out) 550ms,visibility 0s}
  /* P3-3: step 1 — the card's centre at ~45% of the window's height (optical centre of the stone field) */
  .access-stage[data-step="1"] .stage-strip{translate:calc(var(--cam1) + var(--c1dx)) -5svh}
}
/* P3-5: the deck's descriptions share one height (the longest), so the screens start on one line across the cards */
@media(max-width:900px){.access-step .step-text{min-height:var(--text-h,0px)}}

/* ---------- r36 (S2, critic r45) ---------- */
@media(max-width:900px){
  /* P3-1 (S2-6, critic r45 register change): no plate shows the status bar — plate 3 is anchored at the top of the
     screen's first panel (y 72 of 1704), its bottom falls in the empty space under the note */
  .access-step[data-step="3"] .step-shot .shot-plate{max-height:none}
  .access-step[data-step="3"] .shot-plate img{top:0;bottom:auto;translate:0 calc(-72 / 1704 * 100%)}
}
@media(min-width:901px){
  /* P2-1: the pause's sentence enters the window as the scene reaches the paper's tone (app.js sets --s2-pull) */
  #jak-to-dziala{margin-bottom:calc(-100px - var(--s2-pull, 0px))}
  #access-stage.s2-exit-empty{pointer-events:none}
}
/* P3-2: a screen wakes like a light switched on — a fast rise (500 ms, ease-out) instead of a slow-in 900 ms curve that lingered
   in grey mid-tones */
.access-stage[data-step="2"] .strip-screen-salon,.access-stage:is([data-step="3"],[data-step="4"]) .strip-screen-pin{animation:strip-wake 500ms var(--ease-out) 550ms both}
.access-stage[data-step="4"] .strip-screen-booking{animation:strip-wake 500ms var(--ease-out) 550ms both}
.access-stage[data-step="4"][data-prev="3"] .strip-screen-booking{animation:screen-switch 520ms cubic-bezier(.3,0,.2,1) 60ms both}

/* ---------- r37 (S2, critic r46) ---------- */
@media(min-width:901px){
  /* P2-1: a phone's screen lights up only once the camera has stopped (950 ms move) — never grey on a moving phone */
  .access-stage[data-step="2"] .strip-screen-salon,.access-stage:is([data-step="3"],[data-step="4"]) .strip-screen-pin{animation:strip-wake 500ms var(--ease-out) 950ms both}
  .access-stage[data-step="4"] .strip-screen-booking{animation:strip-wake 500ms var(--ease-out) 950ms both}
  .access-stage[data-step="4"][data-prev="3"] .strip-screen-booking{animation:screen-switch 520ms cubic-bezier(.3,0,.2,1) 60ms both}
  /* P3-2: step 1 — the card at the optical centre of the stone field (44% of the empty stone above it, 56% below) */
  .access-stage[data-step="1"] .stage-strip{translate:calc(var(--cam1) + var(--c1dx)) -1svh}
}
/* P3-1: on a portrait tablet the deck is wider (560 px), so the screens' fine lines are at least as legible as at 390 */
@media(min-width:761px) and (max-width:900px){.access-steps{max-width:560px}}


/* ---------- r44 (S4 „Możliwości”, critic r54) ---------- */
/* P1-1: ≤ 1100 px the section's heading stands apart — a clear break before the first note („Plan dnia”) */
@media(max-width:1100px){.tools-head + .feat-item{margin-top:40px}}
@media(max-width:360px){.tools-head + .feat-item{margin-top:32px}}
@media(min-width:1101px){
  /* P2-1: at rest only the plate in focus is on the stone; the neighbours are seen only while they tilt away (800 ms) */
  .feat[data-feat="2"] .plate[data-plate="1"],.feat[data-feat="3"] .plate[data-plate="2"],.feat[data-feat="1"] .plate[data-plate="2"],.feat[data-feat="2"] .plate[data-plate="3"]{opacity:0}
  /* P2-2: the plates at ~1.18× the hero's screen — the rows' second lines ≥ 11 px, the whole plate in the window */
  .feat-tile .plate{--w:calc(clamp(323px,(100svh - 176px) * .4776,372px) * .93548 * 1.18)}
}
/* P3-1: the team picker (a white sheet) lies in the same app margin as the day plan and the client list */
.plate[data-plate="2"],.feat-item[data-feat="2"] .plate{padding:4%;background:var(--app)}
.plate[data-plate="2"] img,.feat-item[data-feat="2"] .plate img{border-radius:12px}

/* v1.12 r45 (S4, critic medium r55). P2-2: the plates' photographed shadow in S4 is shorter and lighter (the same 9-slice
   ring, right and bottom slices at ~2/3 of their length, 60% opacity), so the plate lies flat like Marta's card; S2 keeps its ring.
   P3-1: the client list ends in white above the divider under Katarzyna's row (crop 393/482). */
.tools .frag-shot::before{inset:-1px -12px -13px -5px;border-width:31px 32px 33px 34px;opacity:.6}
.plate-clients,.feat-tile .plate-clients{aspect-ratio:393/482}
/* P2-1: on tablets every note and its plate are one pair in one row: the note on the left, top-aligned with the plate,
   the plate against the column's right edge; no strip of empty stone beside a centred plate. */
@media(min-width:761px) and (max-width:1100px){
  .feat-item{display:grid;grid-template-columns:minmax(0,1fr) min(432px,56%);column-gap:32px;align-items:start}
  .feat-item h3,.feat-item p{grid-column:1}
  .feat-item h3{grid-row:1}
  .feat-item p{grid-row:2;align-self:start}
  .feat-item>.feat-shot{grid-column:2;grid-row:1 / span 3;margin:0;padding:0;display:flex;flex-direction:column;align-items:stretch}
  .feat-item .feat-shot .plate{width:100%}
  .feat-item[data-feat="3"] .feat-shot{align-items:center;gap:28px;padding-bottom:0}
  .feat-item[data-feat="3"] .feat-shot .plate{align-self:stretch}
  .feat-item+.feat-item{margin-top:72px}
}
/* P2-4: from 1101 px the plate sits 72 px right of the notes column's gutter (≈120–150 px from the text), every plate on
   one axis; the free stone to its right holds Anna's and Katarzyna's cards at the hero card's scale (up to 360 px),
   24 px from the plate and at least 16 px from the window's edge. */
@media(min-width:1101px){
  .feat-tile{container-type:inline-size;--px:72px}
  .feat .feat-tile .plate{left:calc(var(--px) + var(--w) / 2)}
  .feat[data-feat="3"] .plate[data-plate="3"]{transform:none}
  .feat-tile .client-pile{--w:calc(clamp(323px,(100svh - 176px) * .4776,372px) * .93548 * 1.18);--free:calc(100cqw - var(--edge,0px) - var(--px) - var(--w));--cw:min(360px,(var(--free) - 40px) / 1.07);right:auto;left:calc(var(--px) + var(--w) + 24px + (var(--free) - 40px - var(--cw) * 1.07) / 2 - var(--cw) * .135);top:calc(50% + 44px)}
}
@media(min-width:1101px) and (max-width:1200px){.feat-tile{--edge:16px}}
/* v1.12 r46 (S4, critic r56 P3-1): the shortened ring is softened, so its right and bottom slices start in the stone's tone and fade out, no band of even width. */
.tools .frag-shot::before{inset:-1px -16px -17px -5px;filter:blur(5px);opacity:.55}

/* v1.12 r46 (S4, critic r56 P2-1, P2-2, P3-2; Astra 27.09): Anna's and Katarzyna's cards are two more pieces of Marta's
   printed card — the same stack (blank card photo with its own shadow, the production print, shade, glow), at the
   photographed angle (no CSS rotation, rule 10), one under the other without overlap, the second 8–12 px to the right.
   No lift on click; the pair arrives once with one 8 px shift. Sizes are the composition's width (print = 87.24% of it). */
.client-pile{display:flex;flex-direction:column;align-items:flex-start;gap:16px;width:auto;height:auto;filter:none;--off:12px}
.pile-card{position:relative;left:auto;top:auto;margin:0;width:var(--W,300px);aspect-ratio:837/595;border-radius:0;overflow:visible;cursor:auto;transform:none;scale:none;transition:none}
.pile-card::before,.pile-card::after{content:none}
.pile-card+.pile-card{margin-left:var(--off)}
.pile-card .card-stack{isolation:isolate}
.client-pile.is-closed .pile-card{transform:none}
.feat-item .client-pile{transition:translate 450ms var(--ease-out),opacity 450ms var(--ease-out)}
.feat-item .client-pile.is-closed{translate:0 8px;opacity:.001}
/* P3-2: the SMS note closes the list of notes as a lower-rank postscript: under note 3, after a thin line. */
.tools-sms{margin-top:32px;padding-top:20px;border-top:1px solid color-mix(in srgb,var(--field) 45%,transparent)}
@media(max-width:1100px){
  .feat-item .client-pile{position:relative;--W:min(320px,100% - var(--off))}
  .feat-item[data-feat="3"] .tools-sms{margin-top:40px}
}
@media(max-width:760px){
  .feat-item .client-pile{--W:min(336px,100% - var(--off));margin-top:24px}
}
@media(min-width:761px) and (max-width:1100px){
  .feat-item[data-feat="3"]{grid-template-rows:auto auto auto 1fr}
  .feat-item[data-feat="3"]>.feat-shot{grid-row:1 / span 4}
  .feat-item[data-feat="3"]>.client-pile{grid-column:1;grid-row:3;margin-top:24px}
  .feat-item[data-feat="3"]>.tools-sms{grid-column:1;grid-row:4;align-self:start}
}
@media(min-width:1101px){
  .feat-item .tools-sms{margin-top:32px}
  .feat-tile .client-pile{--off:8px;--W:min(413px,var(--free) - 40px);left:calc(var(--px) + var(--w) + 16px + (var(--free) - 40px - var(--W)) / 2);right:auto;top:calc(50% + 44px);margin-top:calc((var(--W) * 595 / 837 * 2 + 16px) / -2);translate:0 8px;transition:opacity 450ms var(--ease-out),translate 450ms var(--ease-out)}
  .feat[data-feat="3"] .feat-tile .client-pile{translate:0 0}
}
@media(prefers-reduced-motion:reduce){.client-pile,.feat-tile .client-pile{transition:none}.feat-item .client-pile.is-closed{translate:none;opacity:1}}

/* v1.12 r47 (S4, critic r57). P3-1: the list's crop ends in the white under the divider below Katarzyna's row (the
   list scrolls on), >= 16 px (390) / 20 px (1440) of white under her row, nothing of the next row (393/496).
   P2-1 (S4-8 changed at the critic's proposal): from 1101 px the list leads, the cards follow it: Anna's card starts at
   the list plate's top edge and the pair is no taller than the plate. */
.plate-clients,.feat-tile .plate-clients{aspect-ratio:393/496}
@media(min-width:1101px){
  .feat-tile .client-pile{--off:8px;--gap:12px;--ph:calc(var(--w) * 496 / 393);--W:min(413px,var(--free) - 40px,(var(--ph) - var(--gap)) * 837 / 1190);gap:var(--gap);top:calc(50% + 44px - var(--ph) / 2);margin-top:0}
}
/* P3-2: at 761–900 px the cards take the whole note column: the visible card (94.9% of the photo) ends 16 px before the list plate. */
@media(min-width:761px) and (max-width:900px){
  .feat-item .client-pile{--off:8px;--W:calc((100% + 16px - var(--off)) / .9486)}
}

/* v1.12 r48 (S4, critic r58). P2-2: on tablets the note of "Plan dnia" and "Zespół" travels with its plate through the
   whole row (sticky under the island + 40 px, until the plate's bottom); note 3 has the cards under it, so it stays put. */
@media(min-width:761px) and (max-width:1100px){
  .feat-item:not([data-feat="3"]) .feat-note{position:sticky;top:126px}
}
/* P2-3 (S4-7 changed at the critic's proposal): on phones the pair is a lighter mass than the list — the two
   compositions and the 8 px gap are at most 0.8 of the list plate's height (plate = column × 496/393), Anna at the
   column's left edge, Katarzyna at its right, no overlap. */
@media(max-width:760px){
  .feat-item .client-pile{--W:calc(100% * .71 - 6px);gap:8px}
  .feat-item .pile-card+.pile-card{margin-left:0;align-self:flex-end}
}
/* An inactive note's heading keeps >= 3:1 (large text) on the brightest stone under it. */
@media(min-width:1101px){.feat-item h3{color:#6f7e74}.feat-item.is-active h3{color:var(--ink)}}

/* v1.12 r49 (S4, critic r59 P1-1): the note's heading and text are one block (.feat-note), so on tablets the whole note
   sticks, unsticks and leaves with the bottom of its row as one piece; the heading never slides onto its text. */
@media(min-width:761px) and (max-width:1100px){
  .feat-item>.feat-note{grid-column:1;grid-row:1 / span 2;align-self:start}
}
/* S4-11: the SMS note is a lower-rank postscript (15/22), not a fourth note (.feat-item p had been setting it to 18/28). */
.feat-item .tools-sms{margin-top:32px;max-width:360px;font-size:15px;line-height:22px}
@media(max-width:1100px){.feat-item[data-feat="3"] .tools-sms{margin-top:40px}}
@media(min-width:761px) and (max-width:1100px){
  .feat-item:not([data-feat="3"])>.feat-note{grid-row:1 / span 3;margin-bottom:80px}
}
/* P2-2 (critic r59): with note 3 in focus the stone meets the paper 24–160 px under the lowest object (the list plate and
   the pair end on one line, S4-8): a full-width fade inside the pinned stage, anchored to the plate's bottom; the stage
   stays pinned as long as before (the notes' 50svh run is unchanged). */
@media(min-width:1101px){
  .feat-stage{--w:calc(clamp(323px,(100svh - 176px) * .4776,372px) * .93548 * 1.18)}
  .feat-stage::after{content:'';position:absolute;z-index:5;left:-100vw;right:0;top:calc(50% + 44px + var(--w) * 496 / 393 / 2 + 24px);bottom:0;pointer-events:none;background:linear-gradient(rgb(247 246 242 / 0),var(--paper) 136px);opacity:0;transition:opacity 450ms var(--ease-out)}
  .feat[data-feat="3"] .feat-stage::after{opacity:1}
}
@media(min-width:1101px) and (prefers-reduced-motion:reduce){.feat-stage::after{transition:none}}
/* S4-12 (r49 measurement): on the phones' lit stone the postscript needs a slightly darker body tone for >= 4.5:1. */
.feat-item .tools-sms{color:#4f5a53}

/* v1.12 r50 (S4, critic r60 P2-2): no crossfade. A plate is an object, it never turns translucent: the incoming plate
   is fully opaque from its first frame and slides in above the outgoing one (z 3 over 2) along the same RCRUT 800 ms;
   the outgoing plate tilts away fully opaque and leaves the frame (its rest position is outside the tile), and only
   then, when it is out of view, its opacity drops to 0 (S4-4: at rest one plate). */
@media(min-width:1101px){
  .feat-tile .plate{transition:transform 800ms var(--ease-rcrut),filter 800ms var(--ease-rcrut),opacity 0s linear 800ms}
  .feat[data-feat="1"] .plate[data-plate="1"],.feat[data-feat="2"] .plate[data-plate="2"],.feat[data-feat="3"] .plate[data-plate="3"]{transition:transform 800ms var(--ease-rcrut),filter 800ms var(--ease-rcrut),opacity 0s}
  .feat[data-feat="2"] .plate[data-plate="1"],.feat[data-feat="3"] .plate[data-plate="2"],.feat[data-feat="3"] .plate[data-plate="1"]{opacity:0;transform:translateY(calc(-50svh - 60%)) rotateX(60deg) scale(.82)}
  .feat[data-feat="1"] .plate[data-plate="2"],.feat[data-feat="2"] .plate[data-plate="3"],.feat[data-feat="1"] .plate[data-plate="3"]{opacity:0;transform:translateY(calc(50svh + 60%)) rotateX(-60deg) scale(.82)}
}

/* v1.12 r50 (S4-10, the designer's photo 27.09): Katarzyna's card is a second blank card of the same series — its own
   photo at 3.95° with its own shadow and light maps (card_geometry + card_light_maps + card_layers, the photo scaled so
   the card face has the same pixels as Marta's). Only the print is rotated to the photo; the photo never is (rule 10).
   Its composition is 793/837 of Anna's width, so both cards have the same physical size. */
.card-stack.card-land2{aspect-ratio:793/549}
.card-land2 .card-print{left:2.2573%;top:5.173%;width:92.0303%;height:83.2423%;transform:rotate(3.95deg)}
.card-land2 .card-shade,.card-land2 .card-glow{-webkit-mask:url(assets/card-land2-base.webp) 0 0/100% 100%;mask:url(assets/card-land2-base.webp) 0 0/100% 100%}
.pile-card[data-client="katarzyna"]{width:calc(var(--W,300px) * 793 / 837);aspect-ratio:793/549}

/* v1.12 r50 (owner 27.09: „Przywróć światło liści”; returns the 25.09 decision, rule 21b, replacing rule 36 for S4):
   the hero's leaf loop over "Możliwości" from 1101 px, in the pinned tile (a window of the hero's height, so the leaves
   are the hero's size), under the plates and cards (no shadow ever falls on the UI), strongest on the free stone to the
   right, fading towards the bottom; paused off screen and with reduced motion, like the hero's. */
.tools-light{display:none}
@media(min-width:1101px){
  .tools-light{display:block;position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none;mix-blend-mode:multiply;opacity:.26;-webkit-mask-image:linear-gradient(90deg,transparent 18%,#000 55%),linear-gradient(transparent 8%,#000 22%,#000 62%,transparent 88%);-webkit-mask-composite:source-in;mask-image:linear-gradient(90deg,transparent 18%,#000 55%),linear-gradient(transparent 8%,#000 22%,#000 62%,transparent 88%);mask-composite:intersect}
  .tools-light video{position:absolute;top:0;right:0;width:auto;height:100%;min-width:100%;object-fit:cover;object-position:100% 0}
}
@media(prefers-reduced-motion:reduce){.tools-light{display:none!important}}

/* v1.12 r51 (S4, critic r61 P2-1): no plate is ever cut by a straight line in the stone — the tile has no top mask any
   more (it cut the outgoing plate 96–136 px from the top); the outgoing plate leaves under the island and past the
   window's top edge. And never two plates partly out of frame at once: the outgoing one leaves in 450 ms (accelerating),
   the incoming one starts 150 ms later along RCRUT 800 ms (it is off frame for its first ~400 ms). */
@media(min-width:1101px){
  .feat-tile{-webkit-mask-image:none;mask-image:none}
  .feat-tile .plate{transition:transform 450ms cubic-bezier(.55,0,.85,.35),filter 450ms linear,opacity 0s linear 450ms}
  .feat[data-feat="1"] .plate[data-plate="1"],.feat[data-feat="2"] .plate[data-plate="2"],.feat[data-feat="3"] .plate[data-plate="3"]{transition:transform 800ms var(--ease-rcrut) 150ms,filter 800ms var(--ease-rcrut) 150ms,opacity 0s linear 150ms}
}

/* v1.12 r52 (S4, critic r62 P2-1; S4-8 "the list leads"): the pair of cards follows the list plate. In 2->3 the cards
   come in (the 8 px shift, 450 ms) only 150 ms after the plate has landed (150 ms start + 800 ms RCRUT); in 3->2 (and
   3->1) they are gone at once (a switch, like the plates' opacity), before the list plate moves. */
@media(min-width:1101px){
  .feat-tile .client-pile{transition:opacity 0s,translate 0s;transition-delay:0ms}
  .feat[data-feat="3"] .feat-tile .client-pile{transition:opacity 450ms var(--ease-out),translate 450ms var(--ease-out);transition-delay:1100ms}
}
/* r52 (critic r62 P3-1): at notes 1–2 the leaf light's strongest shadow lies just right of the plate (20–35% of the free
   stone) and fades towards the window's right edge; at note 3 it returns under the cards. The stops are registered
   lengths, so they travel with the plates (800 ms RCRUT). The light stays under the plates, never on the UI. */
@property --l1{syntax:'<length-percentage>';inherits:false;initial-value:18%}
@property --l2{syntax:'<length-percentage>';inherits:false;initial-value:55%}
@property --l3{syntax:'<length-percentage>';inherits:false;initial-value:100%}
@property --l4{syntax:'<length-percentage>';inherits:false;initial-value:100%}
@media(min-width:1101px){
  .tools-light{--w:calc(clamp(323px,(100svh - 176px) * .4776,372px) * .93548 * 1.18);--free:calc(100% - var(--px,72px) - var(--w));-webkit-mask-image:linear-gradient(90deg,transparent var(--l1),#000 var(--l2),#000 var(--l3),transparent var(--l4)),linear-gradient(transparent 8%,#000 22%,#000 62%,transparent 88%);mask-image:linear-gradient(90deg,transparent var(--l1),#000 var(--l2),#000 var(--l3),transparent var(--l4)),linear-gradient(transparent 8%,#000 22%,#000 62%,transparent 88%);transition:--l1 800ms var(--ease-rcrut),--l2 800ms var(--ease-rcrut),--l3 800ms var(--ease-rcrut),--l4 800ms var(--ease-rcrut)}
  .feat:not([data-feat="3"]) .tools-light{--l1:calc(var(--px,72px) + var(--w));--l2:calc(var(--px,72px) + var(--w) + var(--free) * .2);--l3:calc(var(--px,72px) + var(--w) + var(--free) * .35);--l4:calc(var(--px,72px) + var(--w) + var(--free) * .8)}
  .feat[data-feat="3"] .tools-light{--l1:18%;--l2:55%;--l3:100%;--l4:calc(100% + 1px)}
}
/* The loop's leaves sit in its upper right, so at notes 1–2 the loop itself moves down 22% of its height: the leaves fall
   beside the plate at its mid-height (inside the band above), and return with the plates at note 3. */
@media(min-width:1101px){
  .tools-light video{transition:translate 800ms var(--ease-rcrut)}
  .feat:not([data-feat="3"]) .tools-light video{translate:0 22%}
}

/* v1.12 r53 (S4, critic r63 P1-1): the leaf light never shows a straight edge. The loop carries its own soft fade
   (top 0–30%, bottom 75–100% of the video), so moving it down 22% never exposes the frame's top border; the band at
   notes 1–2 ramps in from under the plate (60 px before its right edge, hidden by the plate) over ~190 px. */
@media(min-width:1101px){
  .tools-light video{-webkit-mask-image:linear-gradient(transparent,#000 30%,#000 75%,transparent);mask-image:linear-gradient(transparent,#000 30%,#000 75%,transparent)}
  .feat:not([data-feat="3"]) .tools-light{--l1:calc(var(--px,72px) + var(--w) - 60px);--l2:calc(var(--px,72px) + var(--w) + var(--free) * .3);--l3:calc(var(--px,72px) + var(--w) + var(--free) * .45);--l4:calc(var(--px,72px) + var(--w) + var(--free) * .95)}
}
/* r53 (critic r63 P3-2): the low "Zespół" plate stands with its note as a pair — its top on the note's top line (the
   note is centred in the window when in focus), not centred in the window; scale (S4-5) and axis (S4-8) unchanged. */
@media(min-width:1101px){.feat .feat-tile .plate[data-plate="2"]{top:calc(50% - 51px + var(--w) * .416)}}
/* r53: the incoming plate's start is set by app.js (held 300 ms, then placed inside the frame), so the CSS transition of
   the active plate has no delay of its own; the cards follow the list 150 ms after it lands (300 + 800 ms). */
@media(min-width:1101px){
  .feat[data-feat="1"] .plate[data-plate="1"],.feat[data-feat="2"] .plate[data-plate="2"],.feat[data-feat="3"] .plate[data-plate="3"]{transition:transform 800ms var(--ease-rcrut),filter 800ms var(--ease-rcrut),opacity 0s}
  .feat[data-feat="3"] .feat-tile .client-pile{transition-delay:1250ms}
}

/* v1.12 r55 (S5, critic r65). P2-1: from 1025 px the text column is as tall as the sheet (no sticky column), with
   "Jak zaczniesz" pressed to its foot, so both columns end on one line while the whole sheet is in view.
   P3-1: the sheet's paper (not its shadow) stands on the grid's right line: the stage sits at the column's right edge,
   17 px out (the right slice's shadow). P2-2: 1000–1024 px in landscape has the two columns (like the hero); below
   that the steps share the sheet's centred axis. */
@media(min-width:1025px){
  .pricing-copy{position:static;align-self:stretch;display:flex;flex-direction:column}
  .pricing-copy .start-steps{margin-top:auto}
  .pricing-copy .lead{margin-bottom:48px}
  .price-scene{justify-content:flex-end;margin-right:-17px}
}
@media(min-width:1000px) and (max-width:1024px) and (orientation:landscape){
  .pricing-grid{grid-template-columns:minmax(0,1fr) minmax(0,520px);column-gap:48px}
  .pricing-copy{display:flex;flex-direction:column;align-self:stretch}
  .pricing-copy .lead{margin-bottom:40px}
  .pricing-copy .start-steps{margin-top:auto;order:0}
  .price-scene{order:0;margin-top:0;justify-content:flex-end;margin-right:-17px}
}
@media(max-width:1024px) and (min-width:761px){
  .start-steps{width:min(520px,100%);max-width:none;margin-inline:auto}
}
/* r55 (critic r65 P3-4): one person = no bill ritual: "Prowizja od wizyt 0 zł" stands in the rhythm of the gross line,
   the dashed rule appears from 2 people, when the bill really adds something up. */
.price-bill.is-solo{margin-top:10px;padding-top:0;border-top:0}
/* r55 (S5, critic r65 P3-2 + P3-3, Astra 28.09): the sheet lies flat — the lifted lower-right corner (left from the pen
   removed in v1.11) is rebuilt from shifted, unmirrored straight pieces of the same photo's right and bottom edges, and
   the shadow is recomposited (no darkened rim) and softer (right/bottom peak ~0.17 instead of ~0.46), so the phone's
   enlarged slice no longer shows a band. Same 9-slice cuts and widths. */
.price-card::before{border-image-source:url(assets/paper-a5-v112.webp)}
/* r55: the last step ends on the paper's foot (the card's bottom border holds ~21 px of shadow below the paper, and the
   scene has 24 px of padding under the card), not on the grid row's foot. */
@media(min-width:1025px){.pricing-copy{padding-bottom:40px}}
@media(min-width:1000px) and (max-width:1024px) and (orientation:landscape){.pricing-copy{padding-bottom:40px}}

/* v1.12 r56 (S5, critic r66). P2-1: from 1025 px the heading is on the exhibition scale of the page's other section
   headings (~62 px at 1440) and the lead 20/30, so the left column is one composition beside the sheet's "161" and the
   paper between the lead and "Jak zaczniesz" shrinks. P3-1: the paper (not paper + shadow) sits on the grid / column
   edges — the retouched sheet's shadow reaches 22 px (desktop) / 17 px (phones) past the paper on the right, ~3 px on
   the left. P2-2: 761–999 px (and tablets upright) — heading, lead, paper and steps share one left edge and the paper's
   width. P3-2: balanced question, "· 1 osoba" unbroken. P3-4: one rhythm step (8 px) between the gross line and the
   commission row. */
@media(min-width:1025px){
  #cennik .pricing-copy h2{font-size:clamp(48px,4.3vw,62px);line-height:1.06;letter-spacing:-.03em}
  #cennik .pricing-copy .lead{font-size:20px;line-height:30px}
  .price-scene{margin-right:-22px}
}
@media(min-width:1000px) and (max-width:1024px) and (orientation:landscape){.price-scene{margin-right:-22px}}
@media(max-width:1024px) and (min-width:761px) and (orientation:portrait),(max-width:999px) and (min-width:761px){
  #cennik{--pw:min(503px,100%)}
  #cennik .pricing-copy h2,#cennik .pricing-copy .lead,.start-steps{width:var(--pw);margin-inline:auto}
  .price-scene{display:block}
  .price-stage{width:calc(var(--pw) + 25px);margin-left:calc((100% - var(--pw)) / 2 - 3px)}
}
@media(max-width:760px){
  .price-scene{display:block}
  .price-stage{width:calc(100% + 20px);margin-left:-3px}
}
.price-card label{text-wrap:balance}
.price-vat-who{white-space:nowrap}
.price-bill.is-solo{margin-top:18px}

/* v1.12 r57 (S5, critic r67). P2-1: the heading breaks by sense — each sentence on its own line everywhere; from 1025 px
   (exhibition size) in four lines "Jedna cena / za salon. / Bez prowizji / od wizyt.", never "Bez" at a line's end.
   P2-2: the lead's second sentence starts a line from 761 px and "Bez publicznego" never splits. P3-1: numbers keep
   their units (nbsp in the markup and in app.js). */
#pricing-title .ph-s{display:block}
@media(min-width:1025px){#pricing-title .ph-l{display:block}}
@media(min-width:1000px) and (max-width:1024px) and (orientation:landscape){#pricing-title .ph-l{display:block}}
@media(min-width:761px){#cennik .lead .pl-s{display:block}}

/* v1.12 r58 (S5, critic r68). P2-2 + P3-1: on phones and at 1000–1024 px in landscape the lead breaks by sense in three
   lines ("35 zł netto miesięcznie / za każdą kolejną osobę. / Bez publicznego katalogu."); at 1000–1024 px landscape the
   heading is ~46 px (the hero's H1 on a landscape iPad), the lead 18/28. P3-2: a leading "1" of the amount is pulled
   onto the sheet's text axis (its side-bearing, -0.06 em). */
@media(max-width:760px){#cennik .lead .pl-s,#cennik .lead .pl-p{display:block}}
@media(min-width:1000px) and (max-width:1024px) and (orientation:landscape){
  #cennik .pricing-copy h2{font-size:46px;line-height:1.08;letter-spacing:-.025em}
  #cennik .pricing-copy .lead{font-size:18px;line-height:28px}
  #cennik .lead .pl-p{display:block}
}
.price-amount strong.starts-1{margin-left:-.06em}
/* r58 (S5, critic r68 P2-3, Astra 28.09): the sheet lies in the page's window light — a static correction of the paper
   itself (not a blend layer, which near white barely shows): +0.4% at the upper left to -3% at the lower right in linear
   light, the fibre's own detail lifted up to 8% in the lit part only (not under the fine print), a contrast floor kept
   for the fine print; alpha and shadow identical to paper-a5-v112 (provenance in reviews/v1.12-work/astra-s5-swiatlo/kandydat/). */
.price-card::before{border-image-source:url(assets/paper-a5-v112w.webp)}

/* v1.12 r58 — S4 accessibility correction (frozen section, colour only): the S4 contrast of r58–r59 was measured against
   the BRIGHTEST stone pixel under the text, which is the best case for dark text (Astra 28.09). Measured again against the
   darkest pixel under each line (contrast2.mjs/.py), the notes on the stone fell to 3.3:1 (text) and 2.9:1 (inactive
   headings). Darker tones of the same green-grey keep the worst pixel >= 4.5:1 (>= 3:1 for the 28 px headings). */
.tools .feat-note p{color:#49524c}
.feat-item .tools-sms{color:#454f49}
@media(min-width:1101px){.feat-item h3{color:#6b796f}.feat-item.is-active h3{color:var(--ink)}}

/* v1.12 r59 (S5, critic r69). P2-1: nothing on the sheet is lifted — the only shadow in the section is the sheet's own:
   the button is a flat dark pill printed on the paper (its spring on press stays as motion), and the slider's track is a
   field a shade darker in the paper's warm ink, with no grey outline. P3-2: from 1025 px the price facts stand on their
   own line of the fine print. S5-3 (changed at the critic's proposal): the text column keeps the sheet's one-person
   height, so "Jak zaczniesz" stays still when the bill grows and the sheet extends downward. */
.price-card .button-dark,.price-card .button-dark:hover{box-shadow:0 1px 0 rgb(255 255 255 / 12%) inset}
.team-range{background:linear-gradient(90deg,rgb(61 107 92 / 18%) var(--fill),transparent 0),rgb(92 74 52 / 6%);box-shadow:none}
@media(min-width:1025px){#price-terms{display:block}}
@media(min-width:1025px),(min-width:1000px) and (max-width:1024px) and (orientation:landscape){
  .pricing-copy{align-self:start;height:var(--solo-h,auto)}
}
/* r59 (critic r69 P3-3): every text of S5 >= 4.5:1 against the darkest paper pixel — the bill's "4 × 35 zł" takes the body
   tone (it was --field, 2.9–3.0:1); the track's dots >= 3:1 against the new warm track (non-text contrast). */
.price-bill dt span{color:var(--body)}
.team-dots i{background:rgb(37 59 51 / 60%)}
/* r59 (S5, critic r69 P2-2, Astra 28.09): the sheet has a thickness — a soft line along its own outline (light on the
   top and left, a narrow darker profile on the bottom and right, ~1.7 px CSS on desktop / ~1.3 px on phones) and a
   stronger fall of the light on the empty margins only (+1.2% at the upper left to -8% at the lower right, fading out
   towards the content); the whole text area of the source is identical pixel for pixel, alpha and shadow unchanged
   (paper-a5-v112t.webp = Astra's lossless master re-encoded q95 with identical alpha; provenance in
   reviews/v1.12-work/astra-s5-grubosc/kandydat/). */
.price-card::before{border-image-source:url(assets/paper-a5-v112t.webp)}
/* r59: the gross line may run close to the sheet's right edge at 15 people (390 px), where the thickness retouch darkens
   the paper a little — a touch darker tone keeps its worst pixel >= 4.5:1. */
.price-vat{color:#56615a}

/* v1.12 r60 (S5, critic r70). P2-1: the button on the sheet is the same content-width pill as in the hero and the final,
   on the sheet's left text axis — the amount reads first, the button is a clear call, not the heaviest patch on paper.
   P3-1 (Astra 28.09): under the text column the paper's fine grain is halved (Gaussian σ 3 px split, 24 px smootherstep
   feather), light, thickness edge, alpha and shadow unchanged (paper-a5-v112g.webp; reviews/v1.12-work/astra-s5-ziarno/). */
.price-card .button{width:auto}
.price-card::before{border-image-source:url(assets/paper-a5-v112g.webp)}

/* v1.12 r61 (S5, critic r71). P3-1: the units' last line ("/ miesiąc") sits on the digits' baseline at every width and
   amount (last-baseline alignment instead of a bottom padding). P3-2: the slider's bar is an object over the track —
   4 px above and below the field (drawn in app.js), same ink, no shadow; while dragged or focused it thickens 4 → 6 px. */
.price-amount{align-items:last baseline}
.price-amount>span{padding-bottom:0}
.team-knob path{transition:stroke-width 150ms var(--ease-out)}
.team-range.is-pressed .team-knob path,.team-range:has(input:focus-visible) .team-knob path{stroke-width:6}
@media(prefers-reduced-motion:reduce){.team-knob path{transition:none}}

/* v1.12 r61 (S5, critic r71 P2-1, Astra 28.09): during the slider demo one interpolation drives the bar (rAF), the
   CSS springs do not lag behind it. */
/* Jedna interpolacja: rAF. Obecne sprężyny nie opóźniają kreski. */
#cennik .team-range.is-demo .team-knob path,
#cennik .team-range.is-demo .team-icon,
#cennik .team-range.is-demo .team-value {
  transition:none;
}

@media (prefers-reduced-motion:reduce) {
  #cennik .team-range .team-knob path,
  #cennik .team-range .team-icon,
  #cennik .team-range .team-value {
    transition:none;
  }
}

/* r61 (critic r71 P2-2, Astra 28.09): the sheet lies in the window light of the page — a plain, static gradient on the
   section's paper from 1101 px (about +1.9% at the upper left to -2.75% at the lower right, no blending), fading to the
   plain paper within 160 px at the section's top and bottom (no seam with S4 and S6); the paper under the text column keeps
   its tone (a soft 64 px cover), so the text's contrast does not move. */
@supports (mask-composite:intersect) {
  @media screen and (min-width:1101px) and (forced-colors:none) {
    #cennik {
      position:relative;
      isolation:isolate;
    }

    #cennik::before {
      content:"";
      position:absolute;
      inset:0;
      z-index:0;
      pointer-events:none;

      background:linear-gradient(
        135deg,
        #f9f8f4 0%,
        #f9f8f4 16%,
        var(--paper) 45%,
        #f4f3ef 84%,
        #f4f3ef 100%
      );

      /* Dokładnie neutralne granice; wygaszenie przez 160 px. */
      mask-image:linear-gradient(
        to bottom,
        transparent 0,
        #000 160px,
        #000 calc(100% - 160px),
        transparent 100%
      );
    }

    #cennik > .pricing-grid {
      position:relative;
      z-index:1;
    }

    #cennik .pricing-copy {
      position:relative;
      isolation:isolate;
    }

    /* Papier pod tekstem pozostaje w obecnym kolorze. */
    #cennik .pricing-copy::before {
      content:"";
      position:absolute;
      inset:-80px;
      z-index:-1;
      pointer-events:none;
      background:var(--paper);

      mask-image:
        linear-gradient(
          to right,
          transparent,
          #000 64px,
          #000 calc(100% - 64px),
          transparent
        ),
        linear-gradient(
          to bottom,
          transparent,
          #000 64px,
          #000 calc(100% - 64px),
          transparent
        );
      mask-composite:intersect;
    }
  }
}

/* v1.12 r62 (S5, critic r72 P2-1): the window light on the section's paper is continuous — no cover under the text
   column (it drew a lightless rectangle where the light is strongest); the text keeps >= 4.5:1 (lighter paper under
   dark text only raises contrast; measured again). */
#cennik .pricing-copy::before{content:none}

/* v1.12 r62 (S5, Astra 28.09): after the owner's heading "Płacisz za salon, nie za wizyty." the text column keeps S5-3
   (shared top with the paper, steps at the paper's foot at one person, still when the bill grows): from 1025 px the heading
   is set by sense in three lines ("Płacisz / za salon, / nie za wizyty.", 68 px at 1440, 64 px at 1280), the steps 16/26
   with each step's title above its text; lead unchanged. */
@media (min-width: 1025px),
       (min-width: 1000px) and (max-width: 1024px)
       and (orientation: landscape) {
  #cennik .pricing-copy {
    align-self: start;
    height: auto;
    min-height: var(--solo-h, 0px);
    padding-bottom: 40px;
  }

  #cennik .pricing-copy > * {
    flex-shrink: 0;
  }

  #pricing-title .ph-l,
  #pricing-title .ph-part {
    display: block;
  }
}

@media (min-width: 1025px) {
  #cennik .pricing-copy h2 {
    font-size: clamp(56px, calc(32px + 2.5vw), 68px);
    line-height: 1.06;
    letter-spacing: -.03em;
  }

  #cennik .pricing-copy .lead {
    font-size: 20px;
    line-height: 30px;
    margin: 24px 0 48px;
  }

  #cennik .pricing-copy .start-steps {
    width: 100%;
    max-width: 520px;
    margin: auto 0 0;
    padding-top: 24px;
  }

  #cennik .start-steps h3 {
    font-size: 18px;
    line-height: 26px;
  }

  #cennik .start-steps .timeline {
    margin-top: 20px;
    gap: 20px;
  }

  #cennik .start-steps p {
    font-size: 16px;
    line-height: 26px;
  }

  #cennik .start-steps strong {
    display: block;
    margin-bottom: 4px;
  }
}

@media (min-width: 1000px) and (max-width: 1024px)
       and (orientation: landscape) {
  #cennik .pricing-copy h2 {
    font-size: 46px;
    line-height: 1.08;
    letter-spacing: -.025em;
  }

  #cennik .pricing-copy .lead {
    font-size: 18px;
    line-height: 28px;
    margin: 24px 0 40px;
  }

  /* Kroki zachowują obecny skład:
     15/24, tytuł w akapicie, odstęp między krokami 18px,
     padding nad H3 32px. */
}
