/* Vater, public landing page. Palette A «Verktøykassa», dark editorial with ground drift.
   Tokens: this file is the edit-first source; src/Varde.Monitor/wwwroot/varde.css
   and src/Varde.Onboarding/wwwroot/site.css carry a value-synced light-surface
   subset (token NAMES there are legacy: --beacon now holds libelle green).
   The shared token block below is the contract both stylesheets implement verbatim. */

:root{
  /* brand */
  --graphite:#23282b; --steel:#3a4145; --steel2:#2e3538; --steel3:#1e2326;
  --chalk:#f3f2ec; --chalk2:#e9e7de;
  --libelle:#cde23c; --libelle-ink:#1d2114; --warn:#e2543c; --amber:#e0a02e;
  /* spacing, 4px base */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px; --s8:64px; --s9:96px; --s10:128px; --s11:192px;
  --section:clamp(3rem,8vw,8rem); --gutter:clamp(1rem,4vw,2.5rem);
  /* type ramp */
  --font-display:Bahnschrift,'DIN Alternate','Franklin Gothic Medium',Seravek,sans-serif;
  --font-body:Seravek,'Gill Sans','Segoe UI',Calibri,sans-serif;
  --t-xs:.75rem; --t-sm:.875rem; --t-md:1rem; --t-lg:clamp(1.05rem,1vw + .9rem,1.25rem);
  --t-xl:clamp(1.35rem,1.6vw + 1rem,1.75rem); --t-2xl:clamp(1.75rem,2.4vw + 1rem,2.5rem);
  --t-3xl:clamp(2.2rem,3.6vw + 1rem,3.6rem); --t-4xl:clamp(2.8rem,5vw + 1rem,5.2rem);
  --track-tight:-.02em; --track-normal:0; --track-wide:.16em;
  --lh-display:1.02; --lh-body:1.6; --measure:62ch;
  /* radius */
  --r-sm:6px; --r:10px; --r-lg:16px;
  /* motion */
  --ease-out:cubic-bezier(.23,1,.32,1); --dur-ui:160ms; --dur-in:620ms; --rise:14px;
}

/* landing (dark) colour roles: six roles, one accent */
:root{ --canvas:#23282b; --surface:#2e3538; --ink:#f3f2ec; --ink-soft:#b9c0bb; --accent:var(--libelle); --accent-ink:var(--libelle-ink);
  --line:rgb(243 242 236 / .12); --edge:inset 0 1px 0 rgb(255 255 255 / .06);
  --e1:0 1px 2px rgb(10 12 12 / .35), 0 6px 18px rgb(10 12 12 / .30);
  --e2:0 2px 4px rgb(10 12 12 / .40), 0 16px 40px rgb(10 12 12 / .38);
  --e3:0 4px 8px rgb(10 12 12 / .45), 0 32px 72px rgb(10 12 12 / .45); }

/* page-local sizes: the fixed header overlays every pinned stage; the dock sits over the page bottom.
   --wrap is fluid: 1160px up to 1318px wide (today's column), then 88vw, capped at 1560px. */
:root{ --header-h:60px; --dock-h:88px; --dim:.45; --wrap:clamp(1160px,88vw,1560px); }
/* large viewports: the shared ramp caps at 1600px, so this block picks the ramp up where it stops and
   lets it keep growing to 1920px. The display sizes (--t-lg..--t-4xl) are continuous at 1600px, they
   resume exactly at their caps; --t-xs/sm/md are fixed rem values and step up by at most 1px there.
   Below 1600px nothing changes, so 1280px stays as it is. */
@media (min-width:1600px){
  :root{
    --t-xs:.8rem; --t-sm:.9375rem; --t-md:1.0625rem;
    --t-lg:clamp(1.25rem,.75vw + .5rem,1.4rem); --t-xl:clamp(1.75rem,1.75vw,2.1rem);
    --t-2xl:clamp(2.5rem,2vw + .5rem,2.9rem); --t-3xl:clamp(3.6rem,2vw + 1.6rem,4rem);
    --t-4xl:clamp(5.2rem,2vw + 3.2rem,5.6rem);
  }
}

/* ---------- base ---------- */
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:var(--canvas);color:var(--ink);font:var(--t-md)/1.65 var(--font-body);letter-spacing:.005em;-webkit-font-smoothing:antialiased}
::selection{background:var(--accent);color:var(--accent-ink)}
:root{caret-color:var(--accent);scrollbar-color:var(--steel) var(--steel3)}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
a{color:inherit;text-underline-offset:.18em;text-decoration-thickness:1px}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 var(--gutter)}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.display{font-family:var(--font-display);font-weight:700;line-height:var(--lh-display);letter-spacing:var(--track-tight);text-wrap:balance;margin:0}
.display--xl{font-size:var(--t-4xl)} .display--lg{font-size:var(--t-3xl)} .display--md{font-size:var(--t-2xl)}
.lede{font-size:var(--t-lg);max-width:var(--measure);color:var(--ink-soft);text-wrap:pretty;margin:0}
/* section label only: both eyebrows live in an .act-head, which sets the row's own bottom margin */
.eyebrow{font-family:var(--font-display);text-transform:uppercase;letter-spacing:var(--track-wide);font-size:var(--t-xs);color:var(--accent);margin:0}
.accent{color:var(--accent)}
.amt{font-variant-numeric:tabular-nums}
.grain{position:fixed;inset:0;pointer-events:none;z-index:1;opacity:.045;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
.btn{display:inline-flex;align-items:center;font-family:var(--font-display);font-weight:700;border-radius:var(--r);padding:.8rem 1.4rem;text-decoration:none;white-space:nowrap;transition:transform var(--dur-ui) var(--ease-out),background-color var(--dur-ui) var(--ease-out);box-shadow:var(--e1),var(--edge)}
.btn-primary{background:var(--accent);color:var(--accent-ink)}
.btn-lg{padding:1rem 2rem;font-size:var(--t-lg)}
.btn:active{transform:translateY(1px)}
@media (hover:hover) and (pointer:fine){.btn-primary:hover{background:#d8ea5a}}
.link-cta{font-family:var(--font-display);font-size:var(--t-sm);color:var(--ink-soft);text-decoration:underline;text-decoration-color:var(--line);transition:color var(--dur-ui) var(--ease-out),text-decoration-color var(--dur-ui) var(--ease-out)}
.link-cta:active{transform:translateY(1px)}
@media (hover:hover) and (pointer:fine){.link-cta:hover{color:var(--accent);text-decoration-color:var(--accent)}}

/* ---------- header ---------- */
/* fixed, not sticky: every pinned stage reserves --header-h at its top, and the hero must not
   start 60px lower at scroll 0 than it sits once pinned (a 1280x640 viewport has no room for that) */
.site-header{position:fixed;top:0;left:0;right:0;z-index:10;background:color-mix(in srgb,var(--steel3) 88%,transparent);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 1px 0 rgb(255 255 255 / .06)}
.site-header .wrap{display:flex;align-items:center;justify-content:space-between;height:var(--header-h)}
.wordmark{display:inline-flex;align-items:center;gap:var(--s3);font-family:var(--font-display);font-weight:700;letter-spacing:.22em;font-size:1.05rem;text-decoration:none;color:var(--ink)}
.libelle{display:inline-block;width:34px;height:12px;border-radius:99px;background:var(--steel2);box-shadow:var(--edge),0 0 0 1px rgb(255 255 255 / .08);position:relative;flex:0 0 auto}
.libelle::before{content:"";position:absolute;top:2px;left:calc(50% - 6px);width:12px;height:6px;border-radius:99px;background:var(--accent);box-shadow:inset 0 1px 0 rgb(255 255 255 / .35)}
.libelle::after{content:"";position:absolute;top:0;bottom:0;left:50%;width:0;border-left:1px dashed rgb(243 242 236 / .3)}
/* sits beside the wordmark, but outside its <a> (the wordmark's aria-label would hide it) */
.site-header .devtag{margin-right:auto}
.devtag{display:inline-block;margin-left:var(--s3);font-size:var(--t-xs);font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--amber);background:rgb(224 160 46 / .15);border-radius:99px;padding:.18rem .6rem;line-height:1.4}
.nav-login{font-family:var(--font-display);font-size:var(--t-sm);text-decoration:none;color:var(--ink);border:1px solid var(--line);border-radius:var(--r-sm);padding:.45rem .9rem;white-space:nowrap;transition:color var(--dur-ui) var(--ease-out),border-color var(--dur-ui) var(--ease-out),transform var(--dur-ui) var(--ease-out)}
.nav-login:active{transform:translateY(1px)}
@media (hover:hover) and (pointer:fine){.nav-login:hover{border-color:var(--accent);color:var(--accent)}}

/* ---------- section rail: fixed quick-nav, left, vertically centred ---------- */
.rail-nav{position:fixed;left:clamp(10px,1.4vw,26px);top:50%;translate:0 -50%;z-index:8}
/* dot pitch and size grow a little with the viewport (28px rows at 1280, 34px at 1920) */
.rail-nav ul{list-style:none;margin:0;padding:0;display:grid;gap:clamp(var(--s2),.6vw,var(--s3))}
.rail-nav a{position:relative;display:flex;align-items:center;min-height:clamp(28px,1.75vw,34px);padding:0 var(--s1);border-radius:99px;text-decoration:none;color:var(--ink-soft)}
.rail-nav .dot{flex:0 0 auto;width:clamp(6px,.4vw,8px);height:clamp(6px,.4vw,8px);border-radius:50%;background:var(--ink-soft);opacity:.5;transition:opacity var(--dur-ui) var(--ease-out),scale var(--dur-ui) var(--ease-out),background-color var(--dur-ui) var(--ease-out)}
/* the label is an out-of-flow overlay chip: it never widens the link's hit area over the content
   column, it stays in the accessibility tree (opacity, not display/visibility), and it only shows
   on hover or keyboard focus. The active state is the accent dot alone, so nothing sits over the
   content column at rest. */
.rail-nav .lbl{position:absolute;left:100%;top:50%;margin-left:var(--s3);white-space:nowrap;pointer-events:none;font-family:var(--font-display);font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;line-height:1;padding:.42rem .65rem;border-radius:99px;background:color-mix(in srgb,var(--steel3) 84%,transparent);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);box-shadow:var(--e1),var(--edge);opacity:0;translate:-6px -50%;transition:opacity var(--dur-ui) var(--ease-out),translate var(--dur-ui) var(--ease-out),color var(--dur-ui) var(--ease-out)}
.rail-nav a:focus-visible .lbl{opacity:1;translate:0 -50%;color:var(--ink)}
.rail-nav a.is-active{color:var(--ink)}
.rail-nav a.is-active .dot{background:var(--accent);opacity:1;scale:1.5}
@media (hover:hover) and (pointer:fine){
  .rail-nav a:hover .lbl{opacity:1;translate:0 -50%;color:var(--ink)}
  .rail-nav a:hover .dot{opacity:1}
}

/* ---------- acts: shared stage ---------- */
/* scroll-margin-top: an anchored act must land below the fixed header, not under it */
.act{position:relative;scroll-margin-top:var(--header-h)}
/* the fixed header covers the top of every pinned stage, so the stage centres its content below it */
.stage{position:sticky;top:0;height:100svh;overflow:hidden;display:grid;align-items:center;padding-top:var(--header-h)}
.stage>.wrap{width:100%}

/* ---------- focus panels (problemet + kontroller): scroll moves the focus, panels never move ---------- */
.panels{display:grid;gap:clamp(var(--s4),1.2vw,var(--s5))}
.panels--3{grid-template-columns:repeat(3,1fr)}
.panels--5{grid-template-columns:repeat(5,1fr)}
/* the panels scale with the stage: a viewport-relative min-height, copy at the top, the surface grows
   into the space below (no index numerals: refuse list) */
.panel{position:relative;background:var(--surface);border-radius:var(--r-lg);padding:clamp(var(--s4),1.7vw,var(--s6));box-shadow:var(--e1),var(--edge)}
/* the lit state: a soft sheen and a brighter edge light on a pseudo layer, so only opacity ever animates */
.panel::before{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;background:linear-gradient(165deg,rgb(243 242 236 / .075),rgb(243 242 236 / .025) 45%,transparent 72%);box-shadow:inset 0 1px 0 rgb(255 255 255 / .18),inset 0 0 0 1px rgb(255 255 255 / .05)}
.panel>*{position:relative}
.panel-lead{display:block;font-family:var(--font-display);font-size:var(--t-xl);letter-spacing:var(--track-tight);line-height:1.1;color:var(--ink);margin:0 0 var(--s3);text-wrap:balance}
.panel p{margin:0;color:var(--ink-soft);text-wrap:pretty}
/* three panels carry a whole pinned stage, so they get the roomier cut and the taller floor */
.panels--3 .panel{padding:clamp(var(--s6),2.4vw,var(--s7));min-height:clamp(14rem,46svh,32rem)}
.panels--3 .panel p{font-size:var(--t-lg)}
.panels--5 .panel{min-height:clamp(20rem,62svh,42rem)}
.panel h3{font-family:var(--font-display);font-size:var(--t-lg);margin:0 0 var(--s4);letter-spacing:var(--track-tight);line-height:1.1;text-wrap:balance}
.panel ul{list-style:none;padding:0;margin:0;display:grid;gap:clamp(var(--s3),.8vw,var(--s4))}
.panel li{padding-top:var(--s2);border-top:1px solid var(--line)}
.panel li b{display:block;color:var(--ink);font-family:var(--font-display);font-weight:700;font-size:var(--t-sm)}
.panel li span{display:block;color:var(--ink-soft);font-size:var(--t-sm);line-height:1.45;text-wrap:pretty}
/* the always-lit headline row of a pinned act: eyebrow over a display h2, never animated */
.act-head{margin:0 0 clamp(var(--s5),3vh,var(--s7))}
.act-head .eyebrow{margin:0 0 var(--s3)}
.act--pin{height:250vh}
.act--ctrl{height:320vh}

/* ---------- act 1: hero ---------- */
.act--hero{height:240vh}
/* the grid fills the stage under the header: the copy/mock row centres itself in the free height and
   the level, the instrument, sits on the ground line above a viewport-relative foot. So a taller
   viewport lifts the row and lengthens the instrument's gap, and never leaves a dead band at the bottom */
.hero-grid{display:grid;grid-template-columns:1.2fr 1fr;grid-template-rows:1fr auto;gap:var(--s6) clamp(var(--s7),4vw,var(--s9));align-items:center;position:relative;z-index:5;min-height:calc(100svh - var(--header-h));padding-top:var(--s4);padding-bottom:clamp(var(--s5),9vh,128px)}
.hero-copy .display--xl{font-size:clamp(2.4rem,3.4vw + 1rem,4rem)}
.hero-copy .lede{margin:var(--s5) 0 var(--s6)}
.cta-row{display:flex;align-items:center;gap:var(--s5);flex-wrap:wrap;margin:0}
.line{display:block;overflow:hidden;padding-bottom:.08em;margin-bottom:-.08em}
.line>span{display:block}
/* wider than any viewport (with slack for the scrollbar), centred, clipped by the stage: no edge line on wide screens */
.plane{position:absolute;left:50%;translate:-50% 0;width:max(1800px,100vw + 4rem);max-width:none;bottom:0;pointer-events:none}
.plane--back{height:52vh;background:radial-gradient(60% 80% at 30% 100%,#2b3134 0,transparent 70%),radial-gradient(50% 70% at 75% 100%,#262c2f 0,transparent 70%);z-index:0}
.plane--mid{height:34vh;background:linear-gradient(180deg,transparent,#1a1e20 55%);clip-path:polygon(0 60%,18% 40%,35% 55%,55% 30%,72% 48%,88% 34%,100% 52%,100% 100%,0 100%);z-index:1}
.plane--front{height:22vh;background:#15181a;clip-path:polygon(0 70%,25% 55%,40% 68%,60% 50%,80% 64%,100% 46%,100% 100%,0 100%);z-index:3}
/* the planes sink into the hero ground; the handoff to the next act's ground is the body drift */
.floor{position:absolute;left:0;right:0;bottom:0;height:clamp(200px,26vh,320px);background:linear-gradient(180deg,transparent,#1e1b18);z-index:4}
/* the mock scales as one object: its font-size is the module (14px at 1280, 19px at 1920) and every
   inner size is in em, so the card grows with the viewport instead of floating small in a big stage */
.mock{background:var(--surface);border-radius:var(--r-lg);padding:1.15em;font-size:clamp(.875rem,.78vw + .25rem,1.2rem);box-shadow:var(--e3),var(--edge)}
.mock-top{display:flex;justify-content:space-between;align-items:center;padding:.3em .6em 1.15em;color:var(--ink-soft)}
.mock-top b{color:var(--ink);font-family:var(--font-display);font-size:1.15em}
.mock-grid{display:grid;grid-template-columns:1fr 1fr;gap:.85em}
.mcard{background:#272d31;border:1px solid var(--line);border-radius:var(--r);padding:.85em 1.15em;color:var(--ink-soft);box-shadow:var(--edge)}
.mcard b{display:block;color:var(--ink);font-family:var(--font-display);font-size:1.15em;margin-bottom:.3em}
.mcard .amt{display:block;font-weight:700;color:var(--ink)}
.chip{display:inline-block;margin-top:.55em;font-family:var(--font-display);font-size:.86em;font-weight:700;letter-spacing:.05em;text-transform:uppercase;border-radius:99px;padding:.14em .65em;line-height:1.5}
.chip.red{background:var(--warn);color:#2a1410}
.chip.amber{background:var(--amber);color:#241a05}
.chip.green{background:var(--accent);color:var(--accent-ink)}
.askew-1{rotate:-2.1deg;border-color:var(--warn)} .askew-2{rotate:1.6deg;border-color:var(--amber)} .askew-3{rotate:-1.2deg;border-color:var(--amber)}
.mock-foot{padding:1.15em .6em .3em;font-size:.86em;color:var(--ink-soft)}
/* the instrument: a full-width libelle under the hero row. The bubble's rest position is the centre
   mark; the hero timeline pulls it left at p=0 and lets it settle. cqw is what lets a transform
   travel a fraction of the track (percent translate would refer to the bubble's own width).
   Bubble and track thicken with the viewport (64x12 at 1280, 84x16 at 1920+). */
.level{grid-column:1/-1;--bw:clamp(64px,4.4vw,84px);--bh:clamp(12px,.85vw,16px)}
.level-row{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s4);margin-bottom:var(--s2);font-family:var(--font-display);font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase}
.level-label{color:var(--ink-soft)}
.level-states{display:grid;text-align:right}
.level-states>*{grid-area:1/1}
.state{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.08em;font-size:var(--t-xs);white-space:nowrap}
.state--askew{color:var(--amber)} .state--level{color:var(--accent);opacity:0}
.level-track{position:relative;height:calc(var(--bh) + 6px);border-radius:99px;background:var(--steel3);box-shadow:var(--edge),0 0 0 1px rgb(255 255 255 / .08),inset 0 2px 6px rgb(10 12 12 / .5);container-type:inline-size}
.level-track::before{content:"";position:absolute;top:0;bottom:0;left:50%;border-left:1px dashed rgb(243 242 236 / .35)}
/* two bracket ticks, the tolerance window on a real spirit level */
.level-track::after{content:"";position:absolute;top:2px;bottom:2px;left:calc(50% - var(--bw) / 2 - 6px);width:calc(var(--bw) + 12px);border-left:1px solid rgb(243 242 236 / .18);border-right:1px solid rgb(243 242 236 / .18)}
.level-bubble{position:absolute;top:3px;left:calc(50% - var(--bw) / 2);width:var(--bw);height:var(--bh);border-radius:99px;background:var(--accent);box-shadow:inset 0 1px 0 rgb(255 255 255 / .4),0 1px 2px rgb(10 12 12 / .4);z-index:1}
/* kinetic headline: time-based, plays on load; the page-top position keeps it visible thereafter (greet form) */
.line>span{animation:rise-line var(--dur-in) var(--ease-out) both;animation-delay:calc(var(--i) * 90ms)}
@keyframes rise-line{from{translate:0 110%} to{translate:0 0}}

/* ---------- act 4 + 5 + 6: flow, definition lists, reveals ---------- */
.act--flow{padding:var(--section) 0}
.act--flow .display{margin:0 0 var(--s7)}
/* anchor target inside a flow section: keep its heading clear of the fixed header */
.sub{margin-top:var(--s9);scroll-margin-top:calc(var(--header-h) + var(--s5))}
.steps,.defs{display:grid;grid-template-columns:minmax(10rem,.8fr) 2fr;column-gap:var(--s7);row-gap:0;margin:0}
.steps>div,.defs>div{display:grid;grid-template-columns:subgrid;grid-column:1/-1;column-gap:inherit;border-top:1px solid var(--line)}
.steps dt,.defs dt{font-family:var(--font-display);font-size:var(--t-xl);letter-spacing:var(--track-tight);line-height:1.15;padding:var(--s5) 0;margin:0;text-wrap:balance}
.steps dd,.defs dd{color:var(--ink-soft);max-width:var(--measure);padding:var(--s5) 0;margin:0;text-wrap:pretty}
@supports not (grid-template-columns:subgrid){.steps>div,.defs>div{display:contents} .steps dt,.defs dt,.steps dd,.defs dd{border-top:1px solid var(--line)}}
/* close: one heading, one CTA, generous room above */
.act--close{padding:calc(var(--section) * 1.5) 0 var(--section);text-align:center}
.act--close .display{margin:0 auto var(--s6);max-width:18ch}
.act--close .cta-row{justify-content:center}
/* gated on .js (set by vater-scroll.js): if the script never loads the reveals stay visible */
.js [data-in]>*{opacity:0;translate:0 var(--rise);transition:opacity var(--dur-in) var(--ease-out),translate var(--dur-in) var(--ease-out)}
[data-in].is-in>*{opacity:1;translate:0 0}
.js h2[data-in]{opacity:0;translate:0 var(--rise);transition:opacity var(--dur-in) var(--ease-out),translate var(--dur-in) var(--ease-out)}
h2[data-in].is-in{opacity:1;translate:0 0}

/* ---------- footer ---------- */
/* bottom padding reserves the dock's height so the fixed dock never sits over the contact line */
.site-footer{background:#1a1e20;padding:var(--s8) 0 calc(var(--s8) + var(--dock-h));color:var(--ink-soft);position:relative}
.site-footer .wrap{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:var(--s4) var(--s6)}
.site-footer .wordmark{color:var(--ink)}
.suite{font-size:var(--t-sm);letter-spacing:.04em}
.contact{margin:0;font-size:var(--t-sm)}
.contact a{transition:color var(--dur-ui) var(--ease-out)}
@media (hover:hover) and (pointer:fine){.contact a:hover{color:var(--accent)}}

/* ---------- CTA dock: fixed bottom pill, shown once the hero has scrolled off ---------- */
.cta-dock{position:fixed;left:0;right:0;bottom:var(--s5);z-index:9;display:flex;justify-content:center;padding:0 var(--gutter);pointer-events:none}
/* wrap + centre: between roughly 480 and 545px the note and the button together are wider than the
   viewport, and a nowrap single row pushed the pill past the right edge */
.dock-pill{pointer-events:auto;display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--s5);padding:var(--s2) var(--s2) var(--s2) var(--s5);border-radius:99px;background:color-mix(in srgb,var(--steel3) 84%,transparent);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:var(--e2),inset 0 1px 0 rgb(255 255 255 / .12)}
.dock-note{font-size:var(--t-sm);color:var(--ink-soft)}
.dock-pill .btn{padding:.65rem 1.2rem;font-size:var(--t-md)}
/* large viewports: the hero's own display clamp caps at 4rem by 1412px, so it too resumes at 1600px
   (64px there, 72px at 1920); CTA, kontroller body copy and the dock follow the wider ramp. */
@media (min-width:1600px){
  .hero-copy .display--xl{font-size:clamp(4rem,2.5vw + 1.5rem,4.75rem)}
  .hero-copy .btn{padding:.9rem 1.6rem;font-size:1.0625rem}
  .link-cta{font-size:var(--t-md)}
  .level-row,.state{font-size:.875rem}
  .panel li b,.panel li span{font-size:var(--t-md)}
  .dock-note{font-size:var(--t-md)}
  .dock-pill .btn{padding:.75rem 1.4rem}
}

/* ---------- scroll-driven mechanics ---------- */
@supports (animation-timeline: view()) {
  /* named act timelines, hoisted to body so the ground drift and the dock can follow whichever act is in progress.
     --mock is hoisted too: in the unpinned hero branch the level (a sibling of the mock) follows it. */
  body{timeline-scope:--hero,--mock,--pin,--ctrl,--slik,--lev,--close}
  .act--hero{view-timeline-name:--hero;view-timeline-axis:block}
  .act--close{view-timeline-name:--close}
  .act--pin{view-timeline-name:--pin}
  .act--ctrl{view-timeline-name:--ctrl}
  [data-act=slik]{view-timeline-name:--slik}
  [data-act=levering]{view-timeline-name:--lev}
  .mock{view-timeline-name:--mock}

  /* hero: scroll levels the page */
  .askew-1,.askew-2,.askew-3,.level-bubble,.state--askew,.state--level,.plane--back,.plane--mid{animation-timeline:--hero;animation-range:contain 0% contain 100%;animation-fill-mode:both;animation-timing-function:var(--ease-out)}
  .askew-1{animation-name:level-1} .askew-2{animation-name:level-2} .askew-3{animation-name:level-3}
  @keyframes level-1{0%,20%{rotate:-2.1deg;border-color:var(--warn)} 70%,100%{rotate:0deg;border-color:var(--line)}}
  @keyframes level-2{0%,25%{rotate:1.6deg;border-color:var(--amber)} 75%,100%{rotate:0deg;border-color:var(--line)}}
  @keyframes level-3{0%,30%{rotate:-1.2deg;border-color:var(--amber)} 80%,100%{rotate:0deg;border-color:var(--line)}}
  /* the bubble starts with its left edge 8% into the track and is centred by 60% of the act, before the last card levels */
  .level-bubble{animation-name:bubble} @keyframes bubble{0%,12%{translate:calc(-42cqw + var(--bw) / 2) 0} 60%,100%{translate:0 0}}
  .state--askew{animation-name:fade-out} @keyframes fade-out{0%,45%{opacity:1} 60%,100%{opacity:0}}
  .state--level{animation-name:fade-in} @keyframes fade-in{0%,55%{opacity:0} 70%,100%{opacity:1}}
  .plane--back{animation-name:px-back} @keyframes px-back{from{translate:-50% 0} to{translate:-50% -90px}}
  .plane--mid{animation-name:px-mid} @keyframes px-mid{from{translate:-50% 0} to{translate:-50% -50px}}

  /* CTA dock: hidden through the hero, fades in over the first 60% of the hero's exit, then fades
     back out as the close section (which carries the same CTA) comes on screen, so the two are
     never on screen together. dock-out is listed last so it wins over dock-in while the close is up;
     its implicit start keyframe is the underlying value, i.e. whatever dock-in resolved to.
     visibility rides along so the dock is not a tab stop while invisible. It is discrete, so it is
     held on an explicit late stop rather than interpolated: anything strictly between two differing
     endpoints would flip mid-range and make the dock focusable before it is readable. */
  .cta-dock{animation:dock-in linear both,dock-out linear both;animation-timeline:--hero,--close;animation-range:exit 0% exit 60%,cover 0% cover 45%}
  @keyframes dock-in{0%{opacity:0;translate:0 12px;visibility:hidden} 60%{visibility:visible} 100%{opacity:1;translate:0 0;visibility:visible}}
  @keyframes dock-out{to{opacity:0;translate:0 12px;visibility:hidden}}

  /* focus panels: linear ramps, 6% wide, the incoming ramp leads the outgoing one by 2% so the
     brightest panel never drops below ~.91 at a crossover and the stage never reads as all-dim.
     With --dim .45 the crossover value is .45 + (5/6)(.55) ≈ .91. */
  .panel--focus,.panel--focus::before{animation-fill-mode:both;animation-timing-function:linear;animation-range:contain 0% contain 100%}
  .act--pin .panel--focus,.act--pin .panel--focus::before{animation-timeline:--pin}
  .act--ctrl .panel--focus,.act--ctrl .panel--focus::before{animation-timeline:--ctrl}
  /* problemet: three panels, 1 lit 0-30%, 2 lit 30-62%, 3 lit 62-100% */
  .act--pin .focus-1,.act--pin .focus-1::before{animation-name:p3-1} .act--pin .focus-2,.act--pin .focus-2::before{animation-name:p3-2} .act--pin .focus-3,.act--pin .focus-3::before{animation-name:p3-3}
  @keyframes p3-1{0%,29%{opacity:1} 35%,100%{opacity:var(--dim)}}
  @keyframes p3-2{0%,25%{opacity:var(--dim)} 31%,61%{opacity:1} 67%,100%{opacity:var(--dim)}}
  @keyframes p3-3{0%,57%{opacity:var(--dim)} 63%,100%{opacity:1}}
  /* kontroller: five panels, each lit for a fifth of the act, the last one stays lit */
  .act--ctrl .focus-1,.act--ctrl .focus-1::before{animation-name:p5-1} .act--ctrl .focus-2,.act--ctrl .focus-2::before{animation-name:p5-2} .act--ctrl .focus-3,.act--ctrl .focus-3::before{animation-name:p5-3} .act--ctrl .focus-4,.act--ctrl .focus-4::before{animation-name:p5-4} .act--ctrl .focus-5,.act--ctrl .focus-5::before{animation-name:p5-5}
  @keyframes p5-1{0%,19%{opacity:1} 25%,100%{opacity:var(--dim)}}
  @keyframes p5-2{0%,15%{opacity:var(--dim)} 21%,39%{opacity:1} 45%,100%{opacity:var(--dim)}}
  @keyframes p5-3{0%,35%{opacity:var(--dim)} 41%,59%{opacity:1} 65%,100%{opacity:var(--dim)}}
  @keyframes p5-4{0%,55%{opacity:var(--dim)} 61%,79%{opacity:1} 85%,100%{opacity:var(--dim)}}
  @keyframes p5-5{0%,75%{opacity:var(--dim)} 81%,100%{opacity:1}}
  /* the sheen layer is inside the panel, so its own opacity is what fades the edge light and the gradient in and out;
     the dim floor is 0 there (a dimmed panel is flat), the panel itself keeps the .45 floor */
  .panel--focus::before{--dim:0}

  /* ground drift: each act holds its ground for the first half of its run, then drifts to the next act's ground.
     forwards fill means an act's animation only applies once it has started; later acts win over earlier ones.
     The close section and the footer sit on the levering drift's end colour, #1a1e20. */
  body{background-color:#1e1b18;
    animation:drift-hero linear forwards,drift-pin linear forwards,drift-ctrl linear forwards,drift-slik linear forwards,drift-lev linear forwards;
    animation-timeline:--hero,--pin,--ctrl,--slik,--lev;
    /* slik is shorter than a viewport, so it drifts over its cover range (kontroller end to levering start); the pinned acts and levering use contain */
    animation-range:contain 0% contain 100%,contain 0% contain 100%,contain 0% contain 100%,cover 0% cover 100%,contain 0% contain 100%}
  @keyframes drift-hero{0%,50%{background-color:#1e1b18} 100%{background-color:#23282b}}
  @keyframes drift-pin{0%,55%{background-color:#23282b} 100%{background-color:#2e3538}}
  @keyframes drift-ctrl{0%,70%{background-color:#2e3538} 100%{background-color:#3a4145}}
  @keyframes drift-slik{0%,40%{background-color:#3a4145} 100%{background-color:#23282b}}
  @keyframes drift-lev{0%,60%{background-color:#23282b} 100%{background-color:#1a1e20}}
}

/* ---------- no scroll timelines: finished, leveled state, fully readable ---------- */
@supports not (animation-timeline: view()) {
  /* overflow-x clip (not hidden: it makes no scroll container) keeps the wider-than-viewport planes from widening the page once the stage no longer clips them */
  .act--hero{height:auto;min-height:100vh;overflow-x:clip}
  /* a sticky 100vh stage would clip the hero grid whenever the grid is taller than the viewport */
  .act--hero .stage{position:static;height:auto;min-height:100svh;overflow:visible}
  /* content-sized hero: the dock never fades out here, so the level must not sit under it at the viewport bottom */
  .hero-grid{grid-template-rows:none;min-height:0}
  .askew-1,.askew-2,.askew-3{rotate:0deg;border-color:var(--line)}
  .state--askew{display:none} .state--level{opacity:1}
  .act--pin,.act--ctrl{height:auto}
  .act--pin .stage,.act--ctrl .stage{position:static;height:auto;overflow:visible;padding:var(--section) 0}
  /* overflow:clip is what keeps the wider-than-viewport planes off the page width above; a browser
     without it would scroll sideways, so drop the planes here too and let the drift carry the depth */
  .plane{display:none}
  .cta-dock{opacity:1;visibility:visible}
  /* the dock never fades out here, so the close section reserves room: its own CTA must not
     end up sitting against the docked one */
  .act--close{padding-bottom:calc(var(--section) + var(--dock-h))}
}

/* ---------- responsive ---------- */
/* Unpinned hero. The hero grid can exceed the viewport in two ways: it stacks to one column at
   <=900px, and on a short viewport even the two-column grid is taller than 100vh. A pinned
   100vh stage with overflow:hidden would cut off the bottom of the hero (the level the whole
   leveling story resolves into), and nothing could scroll it into view. So in both cases
   the hero flows and the mock and the level animate on the mock's own --mock view timeline instead. */
/* 639px, not 640: a 1280x640 viewport must still get the pinned hero (the threshold is «shorter than 640») */
@media (max-width:900px), (max-height:639px){
  .act--hero{height:auto}
  /* overflow must be visible here: a hidden-overflow stage would become the mock's scroll container and its view timeline would never advance */
  .act--hero .stage{position:relative;height:auto;min-height:100svh;overflow:visible;align-items:start;padding-top:var(--header-h)}
  /* flowing hero: content-sized rows again, the level follows the mock instead of sitting on a ground line */
  .hero-grid{grid-template-rows:none;min-height:0;padding-top:var(--s5);padding-bottom:var(--s9)}
  .floor{display:none}
  /* nothing clips the 1800px-wide planes once the stage's overflow is visible, so they would
     push the page sideways; the ground drift carries the depth here instead */
  .plane{display:none}
  @supports (animation-timeline: view()) {
    .askew-1,.askew-2,.askew-3,.level-bubble,.state--askew,.state--level{animation-timeline:--mock;animation-range:contain 10% contain 80%}
  }
}
/* problemet unpins on the same 639px cut as the hero and the kontroller act: a stage shorter than
   that clips its own three panels, and nothing could scroll the cut-off part into view. */
@media (max-width:900px), (max-height:639px){
  .act--pin{height:auto}
  .act--pin .stage{position:static;height:auto;overflow:visible;padding:var(--section) 0}
  .act--pin .panel--focus,.act--pin .panel--focus::before{animation:none!important;opacity:1}
}
/* the five-panel row needs the full viewport height at 1280x640, and the 3+2 layout below 1100px
   needs more; shorter than that the act flows instead. The 639px cut matches the hero's, so a
   600-639px viewport does not keep a pinned stage that clips its own panels. */
@media (max-width:900px), (max-height:639px), (max-width:1100px) and (max-height:819px){
  .act--ctrl{height:auto}
  .act--ctrl .stage{position:static;height:auto;overflow:visible;padding:var(--section) 0}
  .act--ctrl .panel--focus,.act--ctrl .panel--focus::before{animation:none!important;opacity:1}
}
/* tight pinned stage (a short viewport, or the two-row 3+2 kontroller layout up to 1100px): the
   panels fill it on their own, so both pinned acts put the head back on one baseline row at the
   smaller display size */
@media (min-width:901px) and (max-height:819px), (min-width:901px) and (max-width:1100px){
  .act-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s2) var(--s6)}
  .act-head .eyebrow{margin:0}
  .act-head .display{font-size:var(--t-2xl)}
}
/* short pinned stage: the CTA dock is fixed over the page bottom and does not fade out while a pinned
   act is on screen, so the stage reserves the dock's own footprint (--dock-h is the pill's height plus
   its bottom offset) and centres the panels in what is left. Above 760px there is slack enough that
   the panels already clear the dock. */
@media (min-width:901px) and (max-height:760px){
  .act--pin .stage,.act--ctrl .stage{padding-bottom:var(--dock-h)}
  /* the reserved strip comes off the kontroller stage, which is the tightest of the two: its
     one-liners step down a size and the list tightens so the five panels still fit the shorter box */
  .panels--5 .panel li b,.panels--5 .panel li span{font-size:var(--t-xs)}
  .panels--5 .panel ul{gap:var(--s2)}
}
@media (min-width:901px) and (max-width:1100px){
  /* two rows of panels: content-sized, a viewport-relative floor on each row would overrun the stage */
  .panels--5 .panel{min-height:0}
  .panels--5{grid-template-columns:repeat(6,1fr)}
  .panels--5>.panel{grid-column:span 2}
  .panels--5>.panel:nth-child(n+4){grid-column:span 3}
}
@media (max-width:900px){
  .rail-nav{display:none}
  .hero-grid{grid-template-columns:1fr;gap:var(--s6)}
  /* the focus acts already flow here, see the unpin branches above */
  .panels--3,.panels--5{grid-template-columns:1fr}
  .panels--3 .panel,.panels--5 .panel{min-height:0}
  .steps,.defs{grid-template-columns:1fr}
  .steps>div,.defs>div{grid-template-columns:1fr}
  .steps dd,.defs dd{padding-top:0}
  @supports not (grid-template-columns:subgrid){.steps dd,.defs dd{border-top:0}}
}
@media (max-width:700px){
  .hero-copy .display--xl{font-size:var(--t-2xl)}
  .plane{display:none}
  /* the hero already flows here, see the unpinned-hero branch above */
  .mcard{padding:var(--s3)}
  .chip{white-space:nowrap}
  .cta-row{gap:var(--s4)}
  .panel{padding:var(--s5)}
}
/* the note is dropped well before the pill would need two rows, so the dock stays a single pill */
@media (max-width:640px){
  .dock-note{display:none}
  .dock-pill{padding:var(--s2)}
}
@media (max-width:480px){
  .wordmark{gap:var(--s2);letter-spacing:.18em}
  .devtag{font-size:.65rem;padding:.14rem .45rem;margin-left:var(--s2)}
  .nav-login{padding:.4rem .6rem;font-size:var(--t-xs)}
  .level-row{font-size:.65rem}
}

/* ---------- reduced motion: fewer and gentler, opacity only ---------- */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  body{animation:none!important;background:var(--canvas)}
  .askew-1,.askew-2,.askew-3,.level-bubble,.state--askew,.state--level,.plane--back,.plane--mid,.line>span,.panel--focus,.panel--focus::before,.cta-dock{animation:none!important}
  .askew-1,.askew-2,.askew-3{rotate:0deg;border-color:var(--line)} .level-bubble{translate:0 0} .state--askew{display:none} .state--level{opacity:1}
  .act--hero,.act--pin,.act--ctrl{height:auto}
  .act--hero .stage,.stage{position:static;height:auto;min-height:0;overflow:visible;padding:var(--section) 0}
  .act--hero .stage{padding-top:calc(var(--header-h) + var(--s6))}
  /* same reason as the no-timelines branch: the dock stays put, so the level keeps clear of the viewport bottom */
  .hero-grid{grid-template-rows:none;min-height:0}
  .panel--focus,.panel--focus::before{opacity:1}
  .cta-dock{opacity:1;translate:0 0;visibility:visible}
  /* same as the no-timelines branch: the dock stays put, so the close CTA needs room under it */
  .act--close{padding-bottom:calc(var(--section) + var(--dock-h))}
  [data-in]>*,h2[data-in]{translate:0 0;transition-property:opacity}
  /* the -50% keeps the out-of-flow chip centred on its dot; only the 6px slide is dropped */
  .rail-nav .lbl{translate:0 -50%;transition-property:opacity,color} .rail-nav .dot{transition-property:opacity,background-color}
  .btn:active,.nav-login:active,.link-cta:active{transform:none}
  .plane{display:none}
}
