/* ============================================================
   Austad — landing page
   Tokens trace to austad_agency/tooling/design-decisions.md
   ============================================================ */

/* ---------- headline skin ----------
   Registered so the gradient stops are real colours to the engine and can be
   transitioned. A plain --var holding a colour cannot animate: the browser
   sees an untyped token and swaps it in one frame, which would pop the title
   while the photo behind it is still 700 ms into its cross-fade.
   Values live on .hero per mode; the transition is declared there too, since
   that is the element the change happens on. Descendants inherit the
   mid-flight value. */
@property --skin-hi     {syntax:"<color>";inherits:true;initial-value:#FFFDF6}
@property --skin-mid    {syntax:"<color>";inherits:true;initial-value:#FFE9C4}
@property --skin-lo     {syntax:"<color>";inherits:true;initial-value:#EDBE7E}
@property --skin-term-hi{syntax:"<color>";inherits:true;initial-value:#FFE7BE}
@property --skin-term-lo{syntax:"<color>";inherits:true;initial-value:#F08B34}
@property --skin-glow   {syntax:"<color>";inherits:true;initial-value:rgb(224 122 44 / .34)}

:root{
  /* type — locked 15 Aug */
  --font-display:"Bricolage Grotesque", system-ui, -apple-system, sans-serif;
  --font-body:"DM Sans", system-ui, -apple-system, sans-serif;

  /* page (below the hero) — constant across modes */
  --page:#FAFAF8;
  --ink:#15171A;
  --muted:#5C6268;
  --line:#E3E2DE;

  /* hero — overwritten per mode by [data-mode] below */
  --hero-ink:#F4FAFF;
  --hero-accent:#5FB6E4;
  --hero-root:#0B1620;
  --hero-scrim:linear-gradient(to bottom, rgb(9 26 40 / .56) 0%, rgb(9 26 40 / .18) 36%, rgb(9 26 40 / 0) 60%);

  /* motion */
  --ease-out-expo:cubic-bezier(.16,1,.30,1);
  --dur-reveal:900ms;

  --gutter:clamp(20px, 5vw, 64px);
  --maxw:1180px;

  /* Fallback for the frosted chip if the root ever loses its data-mode —
     arctic's ice. The three landscapes override both tokens below. */
  --lift-ink:#F4FAFF;
  --lift-rgb:95 182 228;

  /* Grain sits inside the letterforms, blended soft-light over the ramp: sand
     in the desert, snow on the ice. Kept in every mode so nothing has to
     fade in or out at the switch — only the colours travel. */
  --skin-grain: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='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E");
}

/* --lift-rgb is a bare triplet, not a colour, so the same accent can be
   drawn at several alphas — rgb(var(--lift-rgb) / .16) and so on. */
[data-mode="savanna"]{
  --lift-ink:#FFF4E2; --lift-rgb:242 169 78;
  --hero-ink:#FFF4E2; --hero-accent:#F2A94E; --hero-root:#170F0C;
  --hero-scrim:radial-gradient(ellipse 88% 62% at 50% 28%, rgb(28 14 18 / .58) 0%, rgb(28 14 18 / .32) 54%, rgb(28 14 18 / 0) 80%),linear-gradient(to bottom, rgb(28 14 18 / .46) 0%, rgb(28 14 18 / .30) 40%, rgb(28 14 18 / .12) 66%, rgb(28 14 18 / 0) 88%);
}
[data-mode="desert"]{
  --lift-ink:#FFF8ED; --lift-rgb:224 122 44;
  --hero-ink:#FFF8ED; --hero-accent:#E07A2C; --hero-root:#1E120A;
  --hero-scrim:radial-gradient(ellipse 88% 62% at 50% 28%, rgb(46 24 10 / .64) 0%, rgb(46 24 10 / .36) 54%, rgb(46 24 10 / 0) 80%),linear-gradient(to bottom, rgb(46 24 10 / .50) 0%, rgb(46 24 10 / .34) 40%, rgb(46 24 10 / .14) 66%, rgb(46 24 10 / 0) 88%);
}
[data-mode="arctic"]{
  --lift-ink:#F4FAFF; --lift-rgb:95 182 228;
  --hero-ink:#F4FAFF; --hero-accent:#5FB6E4; --hero-root:#0B1620;
  --hero-scrim:radial-gradient(ellipse 88% 62% at 50% 28%, rgb(9 26 40 / .60) 0%, rgb(9 26 40 / .34) 54%, rgb(9 26 40 / 0) 80%),linear-gradient(to bottom, rgb(9 26 40 / .48) 0%, rgb(9 26 40 / .32) 40%, rgb(9 26 40 / .13) 66%, rgb(9 26 40 / 0) 88%);
}

/* Headline skin per mode. Scoped to .hero on purpose — [data-mode] also
   matches the toggle buttons and the <picture> elements, and none of those
   want these. Light at the top of the glyph, weathered at the foot; the
   swapped word carries the accent so the eye lands on the thing that changed. */
.hero[data-mode="desert"]{
  --skin-hi:#FFFDF4; --skin-mid:#F8DCAB; --skin-lo:#D98A3C;
  --skin-term-hi:#FFE0B0; --skin-term-lo:#E8721B;
  --skin-glow:rgb(224 122 44 / .34);
}
.hero[data-mode="savanna"]{
  --skin-hi:#FFFCF2; --skin-mid:#FFE9C0; --skin-lo:#E9BE7C;
  --skin-term-hi:#FFE2AE; --skin-term-lo:#F2A94E;
  --skin-glow:rgb(242 169 78 / .30);
}
.hero[data-mode="arctic"]{
  --skin-hi:#FFFFFF; --skin-mid:#E6F3FD; --skin-lo:#AFD6F0;
  --skin-term-hi:#DAF0FF; --skin-term-lo:#5FB6E4;
  --skin-glow:rgb(95 182 228 / .28);
}

/* ---------- base ---------- */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;background:var(--page);color:var(--ink);
  font-family:var(--font-body);font-size:17px;line-height:1.6;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
img{max-width:100%;display:block}
h1,h2,h3{font-family:var(--font-display);font-weight:800;letter-spacing:.009em;line-height:1.11;margin:0}
p{margin:0}
a{color:inherit}

.wrap{max-width:var(--maxw);margin:0 auto;padding-inline:var(--gutter)}
.wrap.narrow{max-width:760px}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
/* For hyphenated compounds that must not split across lines. */
.nowrap{white-space:nowrap}
.skip{
  position:absolute;left:12px;top:-60px;z-index:100;background:var(--ink);color:#fff;
  padding:10px 16px;border-radius:8px;text-decoration:none;transition:top 160ms ease;
}
.skip:focus{top:12px}
:focus-visible{outline:2px solid var(--hero-accent);outline-offset:3px;border-radius:4px}

/* ============================================================
   LOADER
   ============================================================ */
.loader{
  position:fixed;inset:0;z-index:90;background:#000;
  display:grid;place-items:center;perspective:900px;
  transition:opacity 360ms ease;
}
.loader.is-done{opacity:0;pointer-events:none}
.cluster{position:relative;transform-style:preserve-3d;transition:transform 360ms cubic-bezier(.5,0,.35,1),opacity 260ms ease}
.tile{position:absolute;transform-style:preserve-3d;backface-visibility:hidden;will-change:transform}
.tile i{position:absolute;inset:0;background:#FFF4E2}
.no-js .loader{display:none}

/* ============================================================
   HEADER
   ============================================================ */
.site-header{
  position:fixed;top:0;left:0;right:0;z-index:60;
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:16px;
  padding:18px var(--gutter);
  color:var(--hero-ink);
  transition:background 400ms ease,color 400ms ease,box-shadow 400ms ease,padding 300ms ease;
}
.site-header.is-solid{
  background:rgb(250 250 248 / .92);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  color:var(--ink);box-shadow:0 1px 0 var(--line);padding-block:12px;
}
.wordmark{
  font-family:var(--font-display);font-weight:800;
  font-size:clamp(12px,1.05vw,16px);
  letter-spacing:.13em;text-transform:uppercase;text-decoration:none;
  justify-self:start;white-space:nowrap;
}

/* centre slot: toggle over the hero, nav links once solid */
.header-center{justify-self:center}

/* One glass bar holding all the links, with a single pill sliding between
   them. The nav only ever appears over the solid header, so the glass is
   tuned for a light backdrop — a translucent ink wash, not a white one. */
.nav{
  position:relative;display:none;gap:2px;font-size:15px;white-space:nowrap;
  padding:5px;border-radius:999px;
  background:rgb(21 23 26 / .06);
  border:1px solid rgb(21 23 26 / .10);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
}
.nav a{
  position:relative;z-index:1;          /* above the pill */
  display:inline-flex;align-items:center;
  padding:8px 14px;border-radius:999px;text-decoration:none;
  opacity:.6;transition:opacity 220ms ease;
}
.nav a:hover,.nav a.is-active{opacity:1}

/* Inset by the bar's own padding so it sits inside the glass rather than on
   its edge. Width and offset come from the active link, in JS — the links
   are different widths, so neither can be expressed here. */
.nav-pill{
  position:absolute;top:5px;left:0;height:calc(100% - 10px);width:0;
  border-radius:999px;
  background:rgb(255 255 255 / .92);
  box-shadow:0 1px 3px rgb(21 23 26 / .12);
  opacity:0;
  transition:transform 420ms var(--ease-out-expo),
             width 420ms var(--ease-out-expo),
             opacity 220ms ease;
}
.nav-pill.is-on{opacity:1}
/* First placement should appear where it belongs rather than sliding in
   from the left edge; JS drops this class once it has landed. */
.nav-pill.is-placing{transition:opacity 220ms ease}

.header-right{justify-self:end;display:flex;align-items:center;gap:12px}
.site-header .nav-cta{display:none}
@media (min-width:680px){.site-header.is-solid .nav-cta{display:inline-flex}}

/* Filled rather than outlined. It only ever appears on the solid header,
   which is near-white — an outlined disc there is a white circle on a white
   bar, and the mark inside it was carrying the whole shape on its own. */
.social-link{
  width:38px;height:38px;border-radius:999px;flex:none;
  align-items:center;justify-content:center;
  color:#fff;border:1px solid #0A66C2;
  background:#0A66C2;text-decoration:none;
  transition:transform 200ms var(--ease-out-expo),background 200ms ease,border-color 200ms ease;
}
.social-link svg{width:17px;height:17px;fill:currentColor}
.social-link:hover{transform:translateY(-2px);background:#0B5AA8;border-color:#0B5AA8}
.social-link:active{transform:translateY(0)}

/* Blog link — deliberately outside the nav bar. That bar is a scrollspy for
   the homepage's sections; a link to a different page in it would leave the
   pill pointing at something that isn't there. It also has to survive below
   1080px, where the bar hides, or the blog would be unreachable on a phone. */
.nav-blog{
  display:none;align-items:center;height:36px;padding:0 15px;flex:none;
  border-radius:999px;text-decoration:none;white-space:nowrap;
  font-size:14.5px;font-weight:500;
  border:1px solid transparent;
  transition:background 200ms ease,border-color 200ms ease,transform 200ms var(--ease-out-expo);
}
.site-header.is-solid .nav-blog{
  display:inline-flex;
  background:rgb(21 23 26 / .06);border-color:rgb(21 23 26 / .10);
}
.site-header.is-solid .nav-blog:hover{background:rgb(21 23 26 / .12);transform:translateY(-1px)}
.site-header.is-solid .nav-blog[aria-current="page"]{
  background:#fff;border-color:rgb(21 23 26 / .12);
  box-shadow:0 1px 3px rgb(21 23 26 / .12);
}

/* 1180px, not 900: the header is a 1fr/auto/1fr grid, so the centre column
   is mirrored on both sides. With four links the bar is ~527px wide, which
   leaves too little either side for the right-hand cluster — it ran ~95px
   off-screen at 900, and adding the Blogg pill pushed the cluster into the
   gutter until 1180. Measured, not guessed: at exactly 1180 the cluster's
   right edge lands on the gutter with nothing to spare. Below this the nav
   hides and Blogg + the CTA carry the header alone. */
@media (min-width:1180px){
  .site-header.is-solid .nav{display:flex}
}
/* The toggle belongs to the hero — it switches a landscape you can only see
   up there. Once the page has scrolled past, it goes entirely rather than
   shrinking: a control that changes something off-screen is just noise.
   visibility, not display, so it can fade rather than blink out — but
   visibility alone would keep the box, and the reserved width squeezed the
   CTA next to it into a wrapped blob, so the width collapses with it. The
   negative margin swallows .header-right's gap, which a zero-width flex item
   would otherwise leave behind. */
.site-header.is-solid .toggle{
  opacity:0;visibility:hidden;pointer-events:none;
  /* min-width:0 is load-bearing: a flex item defaults to min-width:auto,
     which refuses to shrink below its content and left a visible sliver of
     the pill behind despite max-width:0. */
  max-width:0;min-width:0;padding-inline:0;border-width:0;margin-left:-12px;overflow:hidden;
}
.site-header.is-solid .nav{opacity:0}
/* Must match the display breakpoint above, or the nav would be laid out but
   permanently transparent between the two. */
@media (min-width:1180px){
  .site-header.is-solid .nav{opacity:1;transition:opacity 320ms ease 120ms}
}
.toggle{transition:opacity 260ms ease,visibility 260ms ease,max-width 320ms var(--ease-out-expo),padding 260ms ease,margin 260ms ease,background 400ms ease,border-color 400ms ease}

/* mode toggle — broader and labelled, so it reads as something to try */
.toggle{
  display:flex;gap:3px;padding:5px;border-radius:999px;
  background:rgb(255 255 255 / .14);border:1px solid rgb(255 255 255 / .26);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);

  /* Load-bearing, and the reason the collapse above is smooth. The default
     is max-width:none, and none -> 0px is not interpolatable: the browser
     drops it from the transition entirely and applies 0 on the first frame.
     The pill's content vanished instantly while opacity was still 1, leaving
     a 10px sliver of padding and glass sitting at the right edge of the
     header for a quarter of a second. A real length here interpolates.
     Three labelled modes measure ~316px; this is the same number with room
     to spare, and it never clips because it is never the smaller value. */
  max-width:380px;
}
.site-header.is-solid .toggle{background:rgb(21 23 26 / .06);border-color:rgb(21 23 26 / .14)}
.toggle button{
  display:inline-flex;align-items:center;gap:8px;cursor:pointer;
  min-height:38px;padding:0 16px;
  border:0;border-radius:999px;background:transparent;color:inherit;
  font-family:var(--font-body);font-size:14px;font-weight:500;letter-spacing:.01em;
  transition:background 240ms ease;
}
.toggle button:hover{background:rgb(255 255 255 / .16)}
.site-header.is-solid .toggle button:hover{background:rgb(21 23 26 / .07)}
.toggle button[aria-pressed="true"]{background:rgb(255 255 255 / .3)}
.site-header.is-solid .toggle button[aria-pressed="true"]{background:rgb(21 23 26 / .13)}
.toggle svg{width:14px;height:14px;flex:none}
.toggle .glyph{fill:none;stroke:currentColor;stroke-width:2.1}
.toggle button[aria-pressed="true"] .glyph{fill:currentColor}
.toggle .lab{line-height:1}

/* narrow screens: glyphs only, but keep the accessible names */
@media (max-width:620px){
  .toggle button{padding:0 11px;min-height:34px}
  .toggle .lab{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
}


/* ============================================================
   BUTTONS
   ============================================================ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;
  font-family:var(--font-body);font-weight:500;font-size:16px;
  padding:14px 26px;border-radius:999px;text-decoration:none;white-space:nowrap;
  background:var(--ink);color:var(--page);border:1px solid var(--ink);
  transition:transform 200ms var(--ease-out-expo),background 200ms ease,box-shadow 200ms ease;
}
.btn:hover{transform:translateY(-2px);box-shadow:0 8px 22px rgb(0 0 0 / .16)}
.btn:active{transform:translateY(0)}
.btn-sm{padding:9px 17px;font-size:14.5px}
.btn-lg{padding:17px 34px;font-size:17px}
.btn-glass{
  background:rgb(255 255 255 / .16);color:var(--hero-ink);
  border:1px solid rgb(255 255 255 / .34);
  -webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);
}
.btn-glass:hover{background:rgb(255 255 255 / .26)}

/* ============================================================
   HERO
   ============================================================ */
.hero{
  position:relative;min-height:100svh;
  display:flex;flex-direction:column;align-items:center;
  background:var(--hero-root);color:var(--hero-ink);
  overflow:hidden;isolation:isolate;
  transition:background 700ms ease,
             --skin-hi 700ms ease, --skin-mid 700ms ease, --skin-lo 700ms ease,
             --skin-term-hi 700ms ease, --skin-term-lo 700ms ease,
             --skin-glow 700ms ease;
}
.hero-media{position:absolute;inset:0;z-index:-2}
.world{
  position:absolute;inset:0;opacity:0;
  transition:opacity 800ms var(--ease-out-expo);
}
.world.is-active{opacity:1}
.world img{
  width:100%;height:100%;object-fit:cover;object-position:center 55%;
  transform:scale(1.06);
  will-change:transform;
}
.scrim{position:absolute;inset:0;z-index:-1;background:var(--hero-scrim);transition:background 700ms ease}

/* Sits with the scrim at z-index -1 but later in DOM order, so the stack reads
   image → scrim → effect → copy. The headline stays clear of it.
   pointer-events stays none so nothing here can shadow the hero CTA; frost's
   melt is driven from the hero listener in hero-effects.js instead. */
.fx{
  position:absolute;inset:0;z-index:-1;pointer-events:none;
  opacity:0;transition:opacity 700ms ease;
}
/* Driven by JS, not by the mode. An effect with a start delay would otherwise
   finish its fade during the hold and arrive at full opacity — a pop. The
   class goes on when the instance is actually built, so the fade always
   covers the effect's own first frames. */
.fx.is-live{opacity:1}
.fx-src{display:none}
.fx-content{position:absolute;inset:0}
.fx-out{position:absolute;inset:0;width:100%;height:100%}

/* Frost never covers the title. Fitted to the measured headline + subline box
   (x 29–71%, y 12–31%) with a 2.5% pad: the smallest ellipse containing a
   rectangle needs radii of half-extent × √2, divided by the 68% stop so the
   corners land inside the solid-clear zone. Leaves y 5–38% clear down the
   centre and feathers out from there; the CTA catches only the outer edge.
   Masking the canvas beats fighting the shader — the melt cannot reopen what
   was never frozen, and no per-frame work is added. */
.fx[data-fx="arctic"] .fx-out{
  -webkit-mask-image:radial-gradient(ellipse 50% 25% at 50% 21%, transparent 0%, transparent 68%, #000 100%);
          mask-image:radial-gradient(ellipse 50% 25% at 50% 21%, transparent 0%, transparent 68%, #000 100%);
}

.hero-copy{
  width:100%;max-width:960px;margin:0 auto;
  padding:clamp(96px,12vh,140px) var(--gutter) 0;
  text-align:center;
}
.headline{
  font-size:clamp(30px,3.5vw,56px);
  /* Plain greedy wrapping, deliberately not balance: the balancer reads the
     whole phrase before it picks its break points, so a shorter term pulls
     earlier words across with it — "klima" moved "AI agenter" down a line
     where "forhold" and "tempo" left it up, and the title changed shape with
     the landscape. Greedy fills each line left to right and never lets later
     content reach back, so every word ahead of the term breaks identically in
     all three modes and only the term itself moves. Measured across widths
     340–1700: balance differs from 440 up, "pretty" still differs at 360 and
     440, greedy is stable at all of them.

     22ch is what greedy needs to keep the phrase at two lines on desktop.
     Narrow screens wrap to three; the reserve below keeps that from moving
     anything under the headline. */
  text-wrap:wrap;margin:0 auto;max-width:22ch;
  /* Inherited, so it follows the words wherever the split puts them — and it
     still paints under a transparent fill, which is what keeps the title
     legible over the photo once the glyphs are only a clipped gradient. */
  text-shadow:0 2px 26px rgb(0 0 0 / .26), 0 0 38px var(--skin-glow);
}

/* The skin goes on whatever element actually holds the glyphs — the words
   once main.js has split them, the h1 itself if it never ran. Not both: a
   gradient painted by the h1 is not affected by a word's opacity or blur, so
   the reveal would animate transparent letters over a title that is already
   fully visible. .is-split is the switch, set by the splitter. */
.headline:not(.is-split),
.headline.is-split .word{
  background-image:var(--skin-grain),
                   linear-gradient(178deg, var(--skin-hi) 8%, var(--skin-mid) 52%, var(--skin-lo) 100%);
  background-size:160px 160px, 100% 100%;
  background-blend-mode:soft-light, normal;
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
}
/* Per word, so the ramp runs top-to-bottom of the line rather than across the
   whole two-line block — every line gets the same lit top and shaded foot. */
.headline.is-split .term-key{
  background-image:var(--skin-grain),
                   linear-gradient(178deg, var(--skin-term-hi) 6%, var(--skin-term-lo) 96%);
}

/* Swap-out and back in, with the text change landing at the invisible middle.
   An animation rather than a transition: .word carries a staggered
   transition-delay from the reveal, and the swap must not inherit it. */
@keyframes term-swap{
  0%  {opacity:1;transform:none;filter:none}
  40% {opacity:0;transform:translateY(-.34em);filter:blur(9px)}
  60% {opacity:0;transform:translateY(.30em);filter:blur(9px)}
  100%{opacity:1;transform:none;filter:none}
}
.headline .term.is-swapping{animation:term-swap 640ms var(--ease-out-expo)}
.subline{
  margin:1.05em auto 0;max-width:52ch;
  font-size:clamp(15px,1.1vw,17px);line-height:1.5;opacity:1;
  text-shadow:0 1px 16px rgb(0 0 0 / .45);
}
.hero-cta{margin-top:1.6em}
/* .micro removed from the hero — the reassurance lives in the final CTA.
   Three stacked lines pushed the block onto bright ice and failed contrast. */

@media (max-height:780px){
  .hero-copy{padding-top:clamp(84px,10vh,110px)}
  .subline{margin-top:.9em}
  .hero-cta{margin-top:1.25em}
}

.scroll-cue{
  position:absolute;bottom:26px;left:50%;transform:translateX(-50%);
  color:var(--hero-ink);opacity:.55;
}
.scroll-cue svg{width:22px;height:22px;animation:bob 2.4s ease-in-out infinite}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(5px)}}

/* ============================================================
   SECTIONS
   ============================================================ */
.section{padding:clamp(72px,10vw,132px) 0}
[id]{scroll-margin-top:92px}
.section h2{font-size:clamp(26px,3.2vw,42px);max-width:20ch;margin-bottom:.75em}
.lead{font-size:clamp(16px,1.3vw,19px);color:var(--muted);max-width:60ch;margin-bottom:1.1em}

/* ---------- pinned statement ----------
   Two elements doing two jobs: .statement is the scroll track and owns the
   height, .statement-pin is what actually sticks. Sticky positions against
   the nearest scrolling ancestor and can never leave its parent's box, so
   the track's extra height IS the pin duration — 200svh holds the line for
   one full viewport of scrolling. svh rather than vh so a phone's collapsing
   address bar cannot make the pin taller than the screen it sits on. */
.statement{background:var(--ink);color:var(--page);height:200svh}
.statement-pin{
  position:sticky;top:0;height:100svh;
  display:grid;place-items:center;
  padding-inline:var(--gutter);text-align:center;
}
.statement-line{
  font-family:var(--font-display);font-weight:800;
  font-size:clamp(32px,4.8vw,68px);line-height:1.1;letter-spacing:-.014em;
  text-wrap:balance;max-width:32ch;
}
/* The setup states the problem; this states the way out, so it is lifted
   into a frosted chip of its own. width:fit-content on a block is what lets
   it both break to a new line and hug its own text — an inline-block would
   flow on after the sentence, a plain block would stretch the full measure.
   Arctic's ice tokens rather than the warm accent: it is the one cool colour
   in the palette, so it reads as a turn rather than more of the same. */
.statement-lift{
  /* Two line-heights of gap — far enough that the chip reads as a separate
     beat answering the problem, not as part of the same block. In em, so the
     pause scales with the type instead of collapsing at the small end of the
     clamp. There is room for it: the pin is a full viewport and the block
     sits centred in it. */
  display:block;width:fit-content;margin:2.2em auto 0;
  padding:.2em .62em;border-radius:999px;
  color:var(--lift-ink);
  /* Tinted glass: the landscape's accent washed over a neutral white base,
     so the pane still reads as glass rather than as coloured plastic. */
  background:linear-gradient(rgb(var(--lift-rgb) / .16), rgb(var(--lift-rgb) / .05)),
             rgb(255 255 255 / .05);
  border:1px solid rgb(255 255 255 / .16);
  -webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);
  /* Top-edge highlight is what sells it as glass rather than a flat tint. */
  box-shadow:inset 0 1px 0 rgb(255 255 255 / .20), 0 24px 70px rgb(var(--lift-rgb) / .12);
}

/* Glass needs something behind it or the blur is a no-op on flat black. The
   wash gives the frost something to pick up, and carries the landscape's
   accent so the section shifts with the toggle.

   Anchored to the bottom of the line block — which is the chip's own bottom
   edge, the chip being the last thing in it — rather than to a percentage of
   the pin. A fixed percentage only lines up at one viewport: the chip's
   position within the pin moves as the em-based gap grows against a
   vh-based pin, which is what made the glow bloom around the chip at some
   widths and sit below it at others.

   On the paragraph rather than inside the chip on purpose: backdrop-filter
   ignores an element's own descendants, so a glow nested in the chip would
   not be there for the chip to refract. */
.statement-line{position:relative}
.statement-line::after{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  left:50%;bottom:0;width:min(880px,150%);aspect-ratio:2.3;
  transform:translate(-50%,44%);
  background:radial-gradient(ellipse 50% 50% at 50% 50%, rgb(var(--lift-rgb) / .16), transparent 70%);
}
.statement-pin > *{position:relative}

/* ---------- use cases ---------- */
.usecases{background:var(--page);padding-block:clamp(72px,10vw,132px)}
/* One line, so no max-width — a measure would only fight the nowrap. The
   line needs 14× the font size: below ~440px that exceeds the column and
   would push the page sideways, so down there it is allowed to wrap. */
.usecases h2{font-size:clamp(26px,3.2vw,42px);margin-bottom:.9em;white-space:nowrap}
@media (max-width:440px){.usecases h2{white-space:normal}}

/* One column on a phone, 2×2 from 720px. */
.uc-grid{display:grid;gap:20px;grid-template-columns:1fr}
@media (min-width:720px){.uc-grid{grid-template-columns:1fr 1fr}}

.uc-card{
  display:flex;flex-direction:column;
  background:#fff;border:1px solid var(--line);border-radius:18px;
  padding:30px 30px 34px;
  /* scale() rather than width/height: it is composited, so hovering a card
     cannot reflow the grid or nudge its neighbours. */
  transition:transform 320ms var(--ease-out-expo),
             box-shadow 320ms ease,
             border-color 320ms ease;
}
/* hover:hover keeps this off touch screens, where :hover sticks after a tap
   and would leave a card stuck open. */
@media (hover:hover){
  .uc-card:hover{
    transform:scale(1.025);
    border-color:rgb(21 23 26 / .14);
    box-shadow:0 18px 44px rgb(21 23 26 / .09);
    /* Rises above the neighbours it now overlaps. */
    position:relative;z-index:1;
  }
}

.uc-num{
  font-family:var(--font-display);font-weight:800;font-size:13px;
  letter-spacing:.14em;color:var(--muted);margin-bottom:22px;
}
.uc-card h3{font-size:21px;margin-bottom:.55em}
.uc-card p{color:var(--muted);font-size:15.5px}

/* ---------- how it works ----------
   Black, so the page alternates dark/light down its length rather than
   running three near-identical light sections together. */
.steps{background:var(--ink);color:var(--page)}

.steps-list{
  position:relative;list-style:none;margin:0;padding:0;
  display:grid;gap:44px;grid-template-columns:1fr;
}
@media (min-width:820px){.steps-list{grid-template-columns:repeat(3,1fr);gap:32px}}
.steps-list > li{position:relative;padding-top:30px}

/* The rail joining the numbers: a dim track with an accent line drawing
   across it once the section reveals. Three columns only — stacked, the
   numbers are not on a shared row for a line to connect. */
@media (min-width:820px){
  .steps-list::before,
  .steps-list::after{
    content:"";position:absolute;top:47px;height:1px;pointer-events:none;
  }
  .steps-list::before{left:0;right:0;background:rgb(250 250 248 / .16)}
  .steps-list::after{
    left:0;width:0;background:rgb(var(--lift-rgb));
    box-shadow:0 0 12px rgb(var(--lift-rgb) / .7);
  }
  .js .steps-list.is-in::after{
    width:100%;transition:width 1500ms var(--ease-out-expo) 260ms;
  }
}

.num{
  position:relative;z-index:1;               /* masks the rail behind it */
  display:inline-grid;place-items:center;width:34px;height:34px;margin-bottom:18px;
  border-radius:999px;
  background:var(--ink);
  color:var(--lift-ink);
  border:1px solid rgb(var(--lift-rgb) / .55);
  box-shadow:0 0 0 5px var(--ink), 0 0 22px rgb(var(--lift-rgb) / .28);
  font-family:var(--font-display);font-weight:800;font-size:15px;
}
/* Each number brightens in turn as the rail passes it. */
.js .steps-list.is-in .num{
  animation:step-light 700ms var(--ease-out-expo) both;
  animation-delay:calc(360ms + var(--i) * 480ms);
}
@keyframes step-light{
  from{border-color:rgb(250 250 248 / .18);box-shadow:0 0 0 5px var(--ink), 0 0 0 rgb(var(--lift-rgb) / 0)}
}

/* Sits on the same row as the number, so it is a second bead on the rail
   rather than something the line runs through — hence the opaque ink base
   under the translucent fill, and the z-index to mask the line behind it. */
.step-when{
  position:relative;z-index:1;
  display:inline-block;margin:0 0 14px 8px;
  padding:5px 12px;border-radius:999px;
  background:linear-gradient(rgb(250 250 248 / .07), rgb(250 250 248 / .07)), var(--ink);
  border:1px solid rgb(250 250 248 / .14);
  font-size:12.5px;letter-spacing:.04em;color:rgb(250 250 248 / .74);
  vertical-align:6px;
}
.steps-list h3{font-size:21px;margin-bottom:.5em}
.steps-list p{color:rgb(250 250 248 / .62);font-size:15.5px}


/* ---------- track record ----------
   Standing capability on the left, one-off deliveries on the right. The
   left column is deliberately narrower: it is a scannable list, not
   something to read through. */
.record{background:var(--page)}
.record-grid{display:grid;gap:36px;grid-template-columns:1fr}
@media (min-width:900px){
  .record-grid{grid-template-columns:minmax(230px,.78fr) 1.22fr;gap:52px}
}

.expertise-head{
  font-size:13px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);margin-bottom:6px;
}
.expertise-list{list-style:none;margin:0;padding:0}
.expertise-list li{
  display:grid;gap:5px;
  padding:17px 0 17px 20px;
  border-top:1px solid var(--line);
  position:relative;
}
/* Decorative accent marker — the landscape's colour reaches this section
   without putting it behind any text, where it would not clear contrast
   on a light ground. */
.expertise-list li::before{
  content:"";position:absolute;left:0;top:calc(17px + .58em);
  width:9px;height:1px;background:rgb(var(--lift-rgb));
}
.ex-k{font-family:var(--font-display);font-weight:800;font-size:16px;line-height:1.25}
.ex-v{color:var(--muted);font-size:14.5px;line-height:1.45}

.deliveries{display:grid;gap:20px;align-content:start}
.delivery{
  background:#fff;border:1px solid var(--line);border-radius:18px;
  padding:28px 28px 30px;
  transition:transform 320ms var(--ease-out-expo),
             box-shadow 320ms ease,
             border-color 320ms ease;
}
@media (hover:hover){
  .delivery:hover{
    transform:scale(1.015);
    border-color:rgb(21 23 26 / .14);
    box-shadow:0 18px 44px rgb(21 23 26 / .09);
  }
}
.delivery-tag{
  display:inline-block;margin-bottom:16px;
  padding:5px 11px;border-radius:999px;
  background:rgb(21 23 26 / .05);border:1px solid rgb(21 23 26 / .08);
  font-size:12.5px;letter-spacing:.04em;color:var(--muted);
}
.delivery h3{font-size:21px;margin-bottom:.6em}
.delivery p{color:var(--muted);margin-bottom:.9em}
.stat{color:var(--ink)!important;font-size:15px;margin-bottom:0!important}
.stat strong{font-family:var(--font-display);font-weight:800;font-size:30px;line-height:1;margin-right:8px;vertical-align:-2px}

.faq{background:#fff}
.faq details{border-top:1px solid var(--line)}
.faq details:last-of-type{border-bottom:1px solid var(--line)}
.faq summary{
  cursor:pointer;list-style:none;padding:20px 44px 20px 0;position:relative;
  font-family:var(--font-display);font-weight:600;font-size:17px;line-height:1.4;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:"";position:absolute;right:8px;top:50%;width:11px;height:11px;
  border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
  transform:translateY(-70%) rotate(45deg);transition:transform 240ms var(--ease-out-expo);
}
.faq details[open] summary::after{transform:translateY(-30%) rotate(-135deg)}
.faq details p{padding:0 44px 22px 0;color:var(--muted);font-size:15.5px}

.final{background:var(--ink);color:var(--page);text-align:center}
.final h2{margin-inline:auto}
.final .lead{color:rgb(250 250 248 / .7);margin-inline:auto;margin-bottom:2em}
.final .btn{background:var(--page);color:var(--ink);border-color:var(--page)}

.site-footer{background:var(--ink);color:rgb(250 250 248 / .55);padding:0 0 44px;font-size:14px}
.site-footer .wrap{display:flex;flex-wrap:wrap;gap:12px;justify-content:space-between;
  border-top:1px solid rgb(250 250 248 / .12);padding-top:26px}
.footer-links{display:flex;flex-wrap:wrap;gap:20px}
.site-footer a{color:inherit;transition:color 200ms ease}
.site-footer a:hover{color:rgb(250 250 248 / .92)}

/* ============================================================
   REVEALS — content is visible by default; JS opts in to hiding
   ============================================================ */
.js .reveal{opacity:0;transform:translateY(18px)}
.js .reveal.is-in{opacity:1;transform:none;
  transition:opacity var(--dur-reveal) ease,transform var(--dur-reveal) var(--ease-out-expo)}
.js .reveal-words .word{display:inline-block;opacity:0;transform:translateY(.32em);filter:blur(6px)}
.js .reveal-words.is-in .word{opacity:1;transform:none;filter:none;
  transition:opacity 520ms ease,transform 520ms var(--ease-out-expo),filter 520ms ease;
  transition-delay:calc(var(--i) * 70ms)}

@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
  .js .reveal,.js .reveal-words .word{opacity:1!important;transform:none!important;filter:none!important}
  .world img{transform:none}
  .scroll-cue svg{animation:none}
}
