/* Collos landing.
 *
 * One type family (DM Sans), one icon set (Material Symbols Rounded), and one
 * material rule: surfaces are white paper with a hairline edge and a shadow you
 * have to look for. The palette is still Collos — navy ink, periwinkle wash,
 * brand blue — because the app, the screenshots and this page have to read as
 * one product; only the *language* is borrowed from the reference.
 *
 * Two deliberate departures from the reference, and why:
 *
 * - Text is navy, not near-black. `#183468` is read off the logo and carries
 *   more brand than `#1a1a1a` does, at the same contrast.
 * - The nav CTA and the hero CTA are the reference's dark pill even though
 *   brand blue exists. The dark pill is the site's action colour and brand blue
 *   is its accent; splitting them means one button is always the loudest thing
 *   on screen, which is what makes the pages scan.
 */

:root {
  --blue: #2f63d6;
  --blue-dark: #1b3f96;
  --ink: #183468;
  --muted: #5d7099;
  --cloud: #f3f7fe;
  --line: #e3eaf8;
  --white: #fff;
  --mint: #4fa98a;
  --blush: #dd6b6b;
  /* One family for everything: DM Sans holds headings and body at every weight. */
  --display: "DM Sans", "Avenir Next", Avenir, "Helvetica Neue", Arial, sans-serif;
  --body: "DM Sans", "Avenir Next", Avenir, "Helvetica Neue", Arial, sans-serif;
  --periwinkle: #9abff3;
  --periwinkle-deep: #d5e3fb;
  --periwinkle-wash: #eaf1fe;
  --mint-wash: #e8f5ef;
  --blush-wash: #fcecec;
  /* The paper material: hairline edge, barely-there shadow, lift on hover. */
  --hairline: rgba(24, 52, 104, 0.09);
  --card-shadow: 0 2px 12px rgba(24, 52, 104, 0.05);
  --card-shadow-lift: 0 8px 28px rgba(24, 52, 104, 0.1);
  /* The action colour: near-black pill, white text, white circular chevron. */
  --action: linear-gradient(180deg, #2c2c2c 0%, #111111 100%);
  --glow-a: #60b1ff;
  --glow-b: #319aff;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  color: var(--ink);
  background: var(--cloud);
  font-family: var(--body);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}
a { color: inherit; text-decoration: none; }
h1, h2, h3 { font-family: var(--display); font-weight: 500; }
.shell { width: min(1120px, calc(100% - 48px)); margin: 0 auto; }
/* The one anchored offset in the site: every jump target clears the sticky bar. */
section[id], footer[id] { scroll-margin-top: 104px; }

/* ---- the two details every page owes a keyboard ---------------------------- */
/* One ring, drawn the same way on every interactive thing: links, buttons, the
   FAQ disclosures and the below-fold anchors. `:focus-visible` rather than
   `:focus`, so a mouse never sees it. */
a:focus-visible, button:focus-visible, summary:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--blue); outline-offset: 3px; border-radius: 10px;
}
/* On the navy bands the brand blue sits too close to the background, so the ring
   inverts there rather than being invisible. */
.tour-section :focus-visible, .cta-card :focus-visible, .site-footer :focus-visible { outline-color: var(--white); }
::selection { background: var(--periwinkle-deep); color: var(--ink); }
/* Every image is a real capture at a known size, so none of them may overflow a
   narrow column or stretch out of proportion. */
img { max-width: 100%; }

/* Material Symbols is loaded for one weight and one fill; anything else falls
   back to the ligature name in plain text. */
.material-symbols-rounded {
  font-family: "Material Symbols Rounded";
  font-weight: normal;
  font-style: normal;
  font-size: 24px;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  display: inline-block;
  white-space: nowrap;
  word-wrap: normal;
  direction: ltr;
  font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 24;
  -webkit-font-feature-settings: "liga";
  -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------------- navbar */
/* Flat bar with a dashed hairline under it. The dashed rule is the reference's
   divider, and it is the cheapest way to make a plain header look drawn rather
   than assembled. */
.nav-wrap {
  position: sticky; top: 0; z-index: 50;
  background: rgba(243, 247, 254, 0.92);
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
}
.site-nav {
  position: relative;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  width: 100%; max-width: 1100px;
  margin: 0 auto; padding: 24px 40px;
}
.site-nav::after {
  content: "";
  position: absolute; left: 40px; right: 40px; bottom: 0; height: 1px;
  background-image: linear-gradient(to right, rgba(24, 52, 104, 0.16) 2px, transparent 2px);
  background-size: 6px 1px;
  background-repeat: repeat-x;
}
.brand { display: inline-flex; align-items: center; gap: 9px; font-family: var(--display); font-size: 20px; font-weight: 700; letter-spacing: -0.3px; }
.brand-mark { display: block; width: 30px; height: 30px; border-radius: 10px; object-fit: cover; }
.nav-links { display: flex; align-items: center; gap: 36px; }
.nav-links a { font-size: 14px; font-weight: 400; opacity: 0.65; transition: opacity 180ms ease-out; }
.nav-links a:hover { opacity: 1; }

/* The pill: 5px on the left so the 24px circle sits inside the radius. */
.nav-cta {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 5px 16px 5px 5px;
  border: 0; border-radius: 40px;
  background: var(--action);
  color: var(--white);
  font-family: var(--body); font-size: 13px; font-weight: 500; white-space: nowrap;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
  transition: transform 200ms ease-out, box-shadow 200ms ease-out, filter 200ms ease-out;
}
.nav-cta:hover { transform: translateY(-1px); box-shadow: 0 8px 22px rgba(0, 0, 0, 0.22); filter: brightness(1.1); }
.nav-cta-arrow {
  display: flex; width: 24px; height: 24px; flex: 0 0 auto;
  align-items: center; justify-content: center;
  border-radius: 50%; background: var(--white);
}
.nav-cta-arrow svg { width: 11px; height: 11px; stroke: #111; stroke-width: 2.4; fill: none; }

/* Hamburger: three rules that fold into an X. Mobile only. */
.hamburger {
  display: none; flex-direction: column; justify-content: center; gap: 5px;
  width: 24px; height: 24px; padding: 0;
  border: 0; background: none; cursor: pointer;
}
.hamburger span { display: block; width: 24px; height: 2px; border-radius: 2px; background: var(--ink); transition: transform 300ms ease-out, opacity 300ms ease-out; }
.hamburger.active span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hamburger.active span:nth-child(2) { opacity: 0; }
.hamburger.active span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* --------------------------------------------------------- mobile nav */
/* A sibling of the header rather than a child, and not a `.nav-links` state:
   the sticky bar carries a `backdrop-filter`, which makes it the containing
   block for fixed descendants and would trap a full-screen overlay inside it. */
.mobile-nav {
  position: fixed; inset: 0; z-index: 40;
  display: none; flex-direction: column;
  padding: 96px 24px 24px;
  background: var(--cloud);
  transform: translateX(100%);
  transition: transform 500ms cubic-bezier(0.77, 0, 0.175, 1), visibility 500ms;
  /* Kept out of the tab order while it is off-screen. */
  visibility: hidden;
}
.mobile-nav.open { transform: translateX(0); visibility: visible; }
.mobile-nav a {
  padding: 24px 0;
  border-bottom: 1px solid rgba(24, 52, 104, 0.12);
  font-family: var(--display); font-size: 38px; font-weight: 800; letter-spacing: -1.5px;
  text-align: left;
}
.mobile-nav .nav-cta {
  align-self: flex-start; margin-top: 32px; padding: 8px 22px 8px 8px;
  border-bottom: 0;
  font-family: var(--body); font-size: 20px; font-weight: 500; letter-spacing: -0.6px;
}
.mobile-nav .nav-cta-arrow { width: 32px; height: 32px; }
.mobile-nav .nav-cta-arrow svg { width: 14px; height: 14px; }
/* The overlay owns the viewport while it is open, so the page must not scroll
   behind it. */
body.nav-open { overflow: hidden; }

/* ------------------------------------------------------------------ hero */
.hero { position: relative; padding: 64px 0 40px; overflow: clip; }
.hero-glow { position: absolute; inset: 0; pointer-events: none; }
/* Three soft pools of brand light. They float, slowly, because the reference's
   decorations move and a completely static hero reads as a mockup. Kept faint
   on purpose: these sit behind the headline, and anything heavier eats the
   contrast of the two-tone type in front of it. */
.glow { position: absolute; border-radius: 50%; filter: blur(70px); opacity: 0.2; animation: floatGlow 11s ease-in-out infinite; }
.glow-a { top: -180px; left: -140px; width: 560px; height: 560px; background: radial-gradient(circle, var(--glow-a) 0%, transparent 70%); }
.glow-b { top: -120px; left: 180px; width: 420px; height: 420px; background: radial-gradient(circle, var(--glow-b) 0%, transparent 70%); opacity: 0.13; animation-delay: 0.3s; }
.glow-c { top: 220px; right: -160px; width: 480px; height: 480px; background: radial-gradient(circle, var(--periwinkle) 0%, transparent 70%); opacity: 0.16; animation-duration: 7.5s; }

/* A dot field, drawn once and masked to the device, so the empty half of the
   hero has a material instead of a gradient. Two copies of the same field sit
   on top of each other: the faint one is the room, the bright one is only
   visible under the pointer (script.js moves the mask), which is the cheapest
   way to say "this page is listening" without animating anything. */
.hero-grid {
  position: absolute; inset: 0;
  background-image: radial-gradient(rgba(47, 99, 214, 0.55) 1.1px, transparent 1.2px);
  background-size: 26px 26px;
  -webkit-mask-image: radial-gradient(600px 500px at 68% 46%, #000 0%, rgba(0, 0, 0, 0.4) 62%, transparent 100%);
          mask-image: radial-gradient(600px 500px at 68% 46%, #000 0%, rgba(0, 0, 0, 0.4) 62%, transparent 100%);
  opacity: 0.5;
}
.hero-grid-hot {
  background-image: radial-gradient(rgba(24, 52, 104, 0.6) 1.5px, transparent 1.6px);
  -webkit-mask-image: radial-gradient(200px 200px at var(--gx, 68%) var(--gy, 46%), #000 0%, rgba(0, 0, 0, 0.4) 46%, transparent 100%);
          mask-image: radial-gradient(200px 200px at var(--gx, 68%) var(--gy, 46%), #000 0%, rgba(0, 0, 0, 0.4) 46%, transparent 100%);
  opacity: 0;
  transition: opacity 500ms ease-out;
}
.hero-glow.aiming .hero-grid-hot { opacity: 0.7; }
/* The light the pointer carries: brand blue, never white. A white pool over a
   light page is a washed-out patch, and it would sit under the muted standfirst
   where contrast is already the thing being protected. */
.hero-spot {
  position: absolute; left: 0; top: 0; width: 720px; height: 720px;
  margin: -360px 0 0 -360px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(47, 99, 214, 0.17) 0%, rgba(47, 99, 214, 0.07) 50%, transparent 100%);
  opacity: 0;
  will-change: transform;
  transition: opacity 420ms ease-out;
}
.hero-glow.aiming .hero-spot { opacity: 1; }
/* Grain. Every large gradient on a light background bands on a cheap panel, and
   banding is the single clearest tell of a gradient that was stepped rather
   than photographed. One SVG turbulence tile at 6% kills it for nothing, and it
   gives the flat brand blue the tooth of paper — which is the material the rest
   of the page is already made of. */
.hero-grain {
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 160px 160px;
  mix-blend-mode: multiply;
  opacity: 0.06;
}
.hero-inner { position: relative; z-index: 1; display: grid; grid-template-columns: 0.95fr 1.05fr; align-items: center; gap: 56px; }
.hero-badge {
  display: inline-flex; align-items: center; gap: 8px;
  margin: 0 0 22px; padding: 8px 14px;
  border: 1px solid var(--hairline); border-radius: 99px;
  background: var(--white); box-shadow: var(--card-shadow);
  color: var(--muted); font-size: 11.5px; font-weight: 600;
}
.hero-badge span { color: var(--blue); }
h1 {
  max-width: 560px; margin: 0 0 20px;
  font-size: clamp(36px, 4.2vw, 54px); line-height: 1.08; letter-spacing: -1.8px; font-weight: 600;
}
/* Two-tone headline. The second line is deliberately quieter than the first,
   but not so light that it loses contrast against the cloud background. */
h1 .tone { color: #6d87b5; }
h2 em, h1 em { color: var(--blue); font-style: normal; }
.hero-lede { max-width: 470px; color: var(--muted); font-size: 17px; line-height: 1.65; letter-spacing: -0.2px; }
.hero-actions { display: flex; align-items: center; gap: 24px; margin-top: 30px; }
/* Same pill anatomy as the nav CTA, one size up: circle on the left, label, and
   6px of padding so the circle clears the 40px radius. */
.button-glass {
  display: inline-flex; align-items: center; gap: 11px;
  min-height: 52px; padding: 6px 24px 6px 6px;
  border-radius: 40px;
  background: var(--action); color: var(--white);
  font-size: 14px; font-weight: 500;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
  transition: transform 200ms ease-out, box-shadow 200ms ease-out, filter 200ms ease-out;
}
.button-glass:hover { transform: translateY(-1px); box-shadow: 0 8px 22px rgba(0, 0, 0, 0.22); filter: brightness(1.1); }
.button-glass-arrow {
  display: flex; width: 40px; height: 40px; flex: 0 0 auto;
  align-items: center; justify-content: center;
  border-radius: 50%; background: var(--white);
}
.button-glass-arrow svg { width: 15px; height: 15px; stroke: #111; stroke-width: 2.2; fill: none; }
.text-link { color: var(--blue); font-size: 13px; font-weight: 600; }
.text-link:hover { text-decoration: underline; }
.mobile-note { display: flex; align-items: center; justify-content: center; gap: 7px; margin: 17px 0 0; color: var(--muted); font-size: 11px; line-height: 1.5; }
/* One muted sentence, no bullet. It used to open with a blush bullet, but the
   bullet rule was written as `.mobile-note span`, which also caught the text
   span beside it and turned the whole line red. */
.mobile-note-text { text-align: left; }
/* The copy arrives in the order a reader takes it in: badge, headline,
   standfirst, buttons, note. 70ms apart and 14px of travel — enough that the
   column reads as being written rather than switched on, small enough that
   nobody is ever waiting for it. */
.hero-copy > * { animation: riseIn 720ms cubic-bezier(0.22, 0.61, 0.36, 1) both; }
.hero-copy > *:nth-child(1) { animation-delay: 40ms; }
.hero-copy > *:nth-child(2) { animation-delay: 110ms; }
.hero-copy > *:nth-child(3) { animation-delay: 180ms; }
.hero-copy > *:nth-child(4) { animation-delay: 250ms; }
.hero-copy > *:nth-child(5) { animation-delay: 320ms; }
@keyframes riseIn {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

/* The cards sit on the product's own surface: the two annotations are the app's
   own copy at card scale, and everything behind them is light. Nothing in this
   composition is a shape the app does not have. */
/* Four layers, front to back: the product, two annotations, the aurora, the
   ambient light. Depth is what a flat panel cannot give — an abstract blue
   rounded square says "graphic", and a device standing in front of moving light
   says "product". Each layer travels at its own rate, both on its own clock and
   against the pointer, which is what makes the depth readable; see `heroDepth`
   in script.js. */
.hero-stage { position: relative; min-height: 700px; }

/* The aurora: the brand's blue, in motion, behind the device.

   This replaces two turned rounded squares. The squares were the third attempt
   at a shape behind the hero and the honest problem with all three was the
   same: a hard-edged slab of flat brand blue is a graphic, and a graphic behind
   a product photo reads as a placeholder. Light does not have that problem. A
   conic sweep of the brand blues, blurred past the point where any band is
   visible and faded out by its own mask, has no edge to judge and no rectangle
   to collide with the device — it reads as the room the device is standing in.
   It is also the one thing on the page that is unmistakably alive: it turns a
   full revolution every 84 seconds, which is slow enough that you notice it has
   moved rather than watch it move.

   The two blooms are the accents from the app itself — periwinkle above,
   the blush of the evening note below — kept at a whisper, because they are
   here to keep the blue from going dead, not to be a second idea. */
.aurora {
  position: absolute;
  left: 50%; top: 46%;
  /* Taller than it is wide, deliberately. A round pool at this size reaches far
     enough left to sit under the muted half of the headline, which is exactly
     the text whose contrast cannot afford a tint behind it. Standing the light
     up as a column keeps the glow where the device is and lets it go as high and
     as low as it likes. */
  width: min(760px, 138%); height: min(1040px, 188%);
  /* `translate`, not `transform: translate(-50%, -50%)`, and this one line is
     the difference between light and a bug.

     The individual transform properties compose in a fixed order — translate,
     then rotate, then scale, then `transform` — which puts `transform`
     innermost: a `translate(-50%, -50%)` written there is rotated along with
     everything else. The moment a `rotate` animation starts on that same
     element, the offset swings around the anchor instead of the element turning
     on the spot. That is precisely what this layer did in its first version —
     it was not a glow drifting gently, it was a glow orbiting the device once
     every 84 seconds, which is why its blue kept surfacing in the wrong corner
     of the hero and never behind the phone where it belonged. `translate` is a
     separate property and cannot be rotated by a sibling, so the layer stays
     where it is put. */
  translate: -50% -50%;
  border-radius: 50%;
  -webkit-mask-image: radial-gradient(closest-side, #000 40%, rgba(0, 0, 0, 0.66) 74%, transparent 100%);
          mask-image: radial-gradient(closest-side, #000 40%, rgba(0, 0, 0, 0.66) 74%, transparent 100%);
  pointer-events: none;
}
/* The turn gets an element of its own, for the reason above: this way the sweep
   and the movement are two properties on two boxes — `rotate` here, `transform`
   on the parent, which script.js owns for the pointer drift — and nothing has to
   compose with anything.

   Every stop is a mid or dark brand blue, and there is no pale one anywhere in
   the turn. A conic places its stops by angle alone, so a pale stop is not a
   highlight you can put somewhere: it is a pale sector, and the rotation drags
   it across the whole hero once a cycle. Blue all the way round means the turn
   varies the light instead of periodically cancelling it. */
.aurora-turn {
  position: absolute; inset: 0; border-radius: inherit;
  background: conic-gradient(from 200deg at 50% 50%, #2f63d6 0deg, #5b95f2 70deg, #2b5ed2 150deg, #7fb0ff 228deg, #3f7fe8 300deg, #2f63d6 360deg);
  animation: auroraSpin 84s linear infinite;
  will-change: rotate;
}
/* Each layer also declares the opacity `--fade-to` animates to, because under
   `prefers-reduced-motion` the animation does not run and the declared value is
   the one that paints. */
.aurora-a {
  /* 38px of blur, not the 52 it started with: past about 40 the sweep's bands
     average out into one flat field, and a flat field is a colour rather than
     light — nothing in it moves, so nothing about it reads as alive. Enough
     blur to lose the stop edges, not enough to lose the variation. */
  filter: blur(38px) saturate(120%);
  opacity: 0.66;
  --fade-to: 0.66;
  animation: heroFade 1200ms ease-out both;
}
.aurora-b {
  left: 57%; top: 33%;
  width: min(520px, 96%); height: min(520px, 96%);
  background: radial-gradient(circle at 50% 50%, rgba(154, 191, 243, 0.95) 0%, rgba(154, 191, 243, 0) 70%);
  filter: blur(46px);
  opacity: 0.42;
  --fade-to: 0.42;
  animation: heroFade 1400ms ease-out both, auroraDrift 17s ease-in-out 1.2s infinite alternate;
}
.aurora-c {
  left: 43%; top: 67%;
  width: min(440px, 82%); height: min(440px, 82%);
  background: radial-gradient(circle at 50% 50%, rgba(221, 107, 107, 0.55) 0%, rgba(221, 107, 107, 0) 70%);
  filter: blur(52px);
  opacity: 0.16;
  --fade-to: 0.16;
  animation: heroFade 1500ms ease-out both, auroraDrift 23s ease-in-out 0.6s infinite alternate-reverse;
}
/* A full turn, not a wobble: anything shorter reads as the page twitching. */
@keyframes auroraSpin { to { rotate: 360deg; } }
/* Breathing, not drifting: 4% of scale and a few pixels, so the light looks like
   it is being lit rather than pushed around. These offsets are relative to the
   `translate` that already centres each bloom — the animation only nudges it,
   which also matters during its delay, when the base position is all there is. */
@keyframes auroraDrift {
  from { transform: translate(-2%, -2%) scale(0.97); }
  to { transform: translate(4%, 4%) scale(1.05); }
}
/* The entrance every layer shares. It ends at `--fade-to`, not at 1, and that
   is not a detail: with `fill-mode: both` this animation keeps the element's
   final value forever, so ending on `opacity: 1` silently overwrote each
   layer's own opacity — which is how a 40%-opacity bloom was painting at full
   strength. Each layer now names the value it wants to keep. */
@keyframes heroFade {
  from { opacity: 0; }
  to { opacity: var(--fade-to, 1); }
}

/* ------------------------------------------------------------- the phone */
/* The product at hero scale, in the app's own bezel: navy border, the corner
   proportion the desktop frame uses, and a shadow deep enough that it reads as
   an object standing in front of the brand shape rather than a picture pasted
   onto it. What is inside is the running app — see
   `scripts/capture-app-screenshots.mjs` — so the hero cannot advertise a screen
   the build does not have, which is how the hand-drawn version drifted.

   The bezel sits on `.hero-phone-body` rather than on `.hero-phone` because the
   entrance animation moves the whole frame while the pointer tilt rotates only
   the body: two animations, two elements, no fight over one `transform`. */
.hero-phone {
  position: absolute;
  left: 50%; top: 34px;
  width: 300px;
  margin: 0;
  transform: translateX(-50%);
  animation: heroRise 800ms cubic-bezier(0.22, 0.61, 0.36, 1) 140ms both;
}
/* The device never fully settles: 7px of rise and fall over nine seconds.

   Three movements meet on the phone, and each one owns its own element so none
   of them can overwrite another: `.hero-phone` carries the entrance (an
   animation, so it owns `transform`), this wrapper carries the idle float, and
   `.hero-phone-body` is left for the pointer tilt, which script.js writes
   inline. Two animations on one property would not compose — the later one
   simply replaces the earlier — and a phone that only moves while the mouse is
   on it is a phone that is off. */
.hero-phone-drift { display: block; animation: idleFloat 9s ease-in-out 1s infinite; }
@keyframes idleFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-7px); }
}
.hero-phone-body {
  display: block;
  position: relative;
  border: 10px solid var(--ink);
  border-radius: 46px;
  background: var(--ink);
  overflow: hidden;
  box-shadow:
    0 40px 90px rgba(24, 52, 104, 0.26),
    0 8px 20px rgba(24, 52, 104, 0.1),
    /* Light spilling off the screen: the device is standing in the aurora, so it
       should be the brightest thing in it rather than a cut-out on top of it. */
    0 0 110px rgba(47, 99, 214, 0.22);
  transform: translate3d(0, 0, 0);
  will-change: transform;
  transition: transform 500ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.hero-phone-body img { display: block; width: 100%; height: auto; }
/* Arriving, not fading in: the frame rises the last few pixels into place. */
@keyframes heroRise {
  from { opacity: 0; transform: translateX(-50%) translateY(28px) scale(0.985); }
  to { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
}
/* The reference's one shared animation: a 10px rise with a 3 degree tilt. */
@keyframes floatSlow {
  0%, 100% { transform: translateY(0px) rotate(0deg); }
  50% { transform: translateY(-10px) rotate(3deg); }
}
/* The ambient glows are blur fields with no shape to speak of, so the rotation
   only moved them off-centre. They translate instead. */
@keyframes floatGlow {
  0%, 100% { transform: translateY(0px); }
  50% { transform: translateY(-10px); }
}

/* The paper material. Every card on this site is one of these. */
.card {
  border: 1px solid var(--hairline);
  border-radius: 18px;
  background: var(--white);
  box-shadow: var(--card-shadow);
  transition: transform 200ms ease-out, box-shadow 200ms ease-out, border-color 200ms ease-out;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--card-shadow-lift); }

/* The two annotations. They are the part of the composition that is laid out by
   hand, and they are here because a still cannot show them: what a note is for,
   and who the circle holds. Everything they say is the app's own copy. */
/* 27%, not the 41% it was first placed at: at 41% the card landed across the
   app's own "Add" pill, which is a control, and half-covering a control reads as
   a collision. Up here it overlaps the empty right-hand side of the recipient
   row instead — the card still sits on the device, and nothing it covers was
   something a person would want to read. */
.card-note { position: absolute; right: -14px; top: 27%; display: flex; align-items: center; gap: 11px; width: clamp(148px, 35%, 210px); padding: 14px 16px; z-index: 3; animation: floatSlow 5s ease-in-out 1s infinite; }
.note-icon { display: grid; width: 34px; height: 34px; flex: 0 0 auto; place-items: center; border-radius: 50%; color: var(--blush); background: var(--blush-wash); font-size: 18px; }
.card-note strong { display: block; font-size: 12.5px; font-weight: 600; }
.card-note small { color: var(--muted); font-size: 10.5px; }
/* Lifted off the bottom edge for the same reason: at 72px it sat over the app's
   own tab bar. Now it lands on the moment rows, which are content rather than
   chrome, and the device's nav stays legible underneath. */
.card-circle { position: absolute; left: -14px; bottom: 118px; display: flex; align-items: center; gap: 12px; width: clamp(148px, 35%, 210px); padding: 13px 16px; z-index: 2; animation: floatSlow 4.5s ease-in-out 0.3s infinite; }
.circle-logo { width: 40px; height: 40px; flex: 0 0 auto; border-radius: 50%; object-fit: cover; }
.card-circle strong { display: block; font-size: 12.5px; font-weight: 600; }
.card-circle small { color: var(--muted); font-size: 10.5px; }

/* -------------------------------------------------------- stack strip */
.stack-strip { margin-top: 30px; padding: 20px 0 8px; border-top: 1px dashed rgba(24, 52, 104, 0.18); display: flex; align-items: center; justify-content: space-between; gap: 24px; }
.stack-strip p { margin: 0; color: var(--muted); font-size: 12px; }
.stack-strip ul { display: flex; flex-wrap: wrap; gap: 34px; margin: 0; padding: 0; list-style: none; }
.stack-strip li { color: #9aa7bb; font-family: var(--display); font-size: 14px; font-weight: 600; letter-spacing: 0.2px; }

/* ------------------------------------------------------------- sections */
.eyebrow { margin: 0 0 18px; color: var(--blue); font-size: 11px; font-weight: 700; letter-spacing: 1.6px; font-family: var(--body); }
h2 { margin-top: 0; font-weight: 600; }
.section { padding: 120px 0 110px; }
/* A three-column poster: label, headline, standfirst. The headline column is
   the widest because the headline is the only thing here that can break badly. */
.section-intro { display: grid; grid-template-columns: 0.6fr 1.35fr 1fr; align-items: end; gap: 45px; }
.section-intro .eyebrow { align-self: start; }
.section-intro h2, .showcase h2, .tour-copy h2, .cta h2 { margin: 0; font-size: clamp(32px, 4vw, 50px); line-height: 1.06; letter-spacing: -2px; }
.section-intro h2 { font-size: clamp(30px, 3.4vw, 42px); letter-spacing: -1.8px; }
.section-intro > p:last-child, .showcase-copy > p:not(.eyebrow) { margin: 0; color: var(--muted); font-size: 15px; line-height: 1.7; }
.feature-icon { display: grid; width: 48px; height: 48px; place-items: center; border-radius: 50%; margin-bottom: 26px; font-size: 22px; }
.feature-sky { color: var(--blue); background: var(--periwinkle-wash); }
.feature-blush { color: var(--blush); background: var(--blush-wash); }
.feature-mint { color: var(--mint); background: var(--mint-wash); }
.showcase { display: grid; grid-template-columns: 0.8fr 1fr; gap: 90px; align-items: center; padding: 115px 0; }
.showcase-copy > p:not(.eyebrow) { margin: 21px 0 30px; max-width: 390px; }
.check-list { display: grid; gap: 18px; margin: 0; padding: 0; list-style: none; }
.check-list li { display: flex; gap: 11px; align-items: flex-start; }
.check-list li > span:first-child { display: grid; width: 22px; height: 22px; flex: 0 0 auto; place-items: center; border-radius: 50%; color: var(--mint); background: var(--mint-wash); font-size: 13px; }
.check-list strong, .check-list small { display: block; }
.check-list strong { margin-bottom: 3px; font-size: 13px; font-weight: 600; }
.check-list small { color: var(--muted); font-size: 11px; }
.dashboard-frame { width: min(100%, 300px); margin: auto; overflow: hidden; border: 8px solid var(--ink); border-radius: 34px; background: var(--cloud); box-shadow: 18px 25px 50px rgba(24, 52, 104, 0.12); }
.dashboard-frame img { display: block; width: 100%; height: auto; }
/* ------------------------------------------------------- the real app */
/* The dark band in the middle of the page, and the one place the site shows
   the product itself at full size rather than describing it. Navy, because the
   app's own frame and hero card are navy, and the captures inside the bezels
   are the app's blue at the same value. */
.tour-section { padding: 110px 0; color: var(--white); background: var(--ink); }
.tour-inner { display: grid; grid-template-columns: 1fr 1.06fr; align-items: center; gap: 80px; }
.tour-section .eyebrow { color: var(--periwinkle); }
.tour-section h2 em { color: var(--periwinkle); }
.tour-copy > p:not(.eyebrow):not(.tour-caption) { max-width: 400px; margin: 22px 0 0; color: #aeb9cc; font-size: 15px; line-height: 1.7; }
/* The two beats, as a list rather than a paragraph: this band is the section a
   reader skims, so each line carries one fact. */
.tour-beats { display: grid; gap: 14px; margin: 30px 0 0; padding: 0; list-style: none; }
.tour-beats li { display: flex; align-items: baseline; gap: 12px; }
.tour-beats strong { flex: 0 0 74px; color: var(--white); font-family: var(--display); font-size: 13.5px; font-weight: 600; letter-spacing: -0.2px; }
.tour-beats span { color: #aeb9cc; font-size: 13px; line-height: 1.55; }
/* Deliberately quiet: it is a statement of provenance, not a selling point. */
.tour-caption { max-width: 400px; margin: 30px 0 0; padding-top: 20px; border-top: 1px dashed #33507e; color: #8fa6ce; font-size: 11.5px; line-height: 1.7; }
/* Two frames, the second one stepped up and forward. The overlap is the whole
   composition: it says "in order" without an arrow, and it keeps the pair the
   height of one phone instead of two. */
.tour-frames { position: relative; display: flex; align-items: flex-end; justify-content: center; gap: 0; }
.tour-frame { margin: 0; width: 40%; max-width: 220px; }
.tour-frame img { display: block; width: 100%; height: auto; border: 7px solid #0f2450; border-radius: 30px; background: var(--blue); box-shadow: 0 26px 60px rgba(0, 0, 0, 0.45); }
.tour-frame figcaption { margin-top: 16px; color: var(--periwinkle); font-size: 10px; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase; text-align: center; }
.tour-frame-back { transform: translateY(34px) rotate(-3deg); }
.tour-frame-back img { opacity: 0.92; }
.tour-frame-front { position: relative; z-index: 2; width: 46%; max-width: 250px; margin-left: -26px; }
.tour-frame-front figcaption { color: var(--white); }
.cta { padding: 105px 0; }
.cta-card { display: grid; grid-template-columns: 1fr 0.75fr; gap: 50px; align-items: end; padding: 56px; border-radius: 22px; color: var(--white); background: linear-gradient(135deg, #24427f, #183468); border-color: transparent; }
.cta-card:hover { transform: none; box-shadow: var(--card-shadow-lift); }
.cta-card .eyebrow { color: #bcd0ff; }
.cta-card h2 em { color: var(--periwinkle); }
.cta-card > div:last-child > p { max-width: 300px; margin-bottom: 22px; color: #dce7ff; font-size: 14px; line-height: 1.6; }
/* The closing block has two actions now: the product, and the source beside it
   as a quiet link rather than a second pill. Two equally loud buttons is how a
   page ends up with no primary action at all. */
.cta-actions { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.cta-secondary { color: #bcd0ff; font-size: 13px; font-weight: 600; transition: color 180ms ease-out; }
.cta-secondary:hover { color: var(--white); text-decoration: underline; }

/* ------------------------------------------------------------------ buttons */
.button {
  display: inline-flex; min-height: 48px; align-items: center; justify-content: center; gap: 10px;
  padding: 0 22px; border-radius: 40px;
  font-family: var(--body); font-size: 13.5px; font-weight: 600;
  transition: transform 200ms ease-out, box-shadow 200ms ease-out, background-color 200ms ease-out, filter 200ms ease-out;
}
.button:hover { transform: translateY(-1px); }
.button-blue { color: var(--white); background: var(--blue); box-shadow: 0 4px 15px rgba(47, 99, 214, 0.22); }
.button-blue:hover { background: var(--blue-dark); filter: brightness(1.04); }
.button-outline { border: 1px solid var(--hairline); color: var(--ink); background: var(--white); box-shadow: var(--card-shadow); }
.button-outline:hover { border-color: rgba(24, 52, 104, 0.2); }
.button-light { color: var(--blue); background: var(--white); box-shadow: 0 4px 15px rgba(0, 0, 0, 0.14); }
.button-primary { color: var(--white); background: var(--action); box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15); }
.button-primary:hover { filter: brightness(1.1); }

/* ---------------------------------------------------------------- footer */
.site-footer { padding: 60px 0 23px; border-top: 1px dashed rgba(24, 52, 104, 0.18); }
.footer-grid { display: grid; grid-template-columns: 1.2fr 0.6fr 1fr; gap: 70px; padding-bottom: 56px; }
.footer-brand { margin-bottom: 16px; }
.footer-grid p { max-width: 240px; color: var(--muted); font-size: 12px; line-height: 1.65; }
.footer-grid a:not(.brand) { display: block; margin-top: 12px; color: var(--muted); font-size: 12px; transition: color 180ms ease-out; }
.footer-grid a:not(.brand):hover { color: var(--blue); }
.footer-heading { margin-bottom: 17px; color: var(--ink) !important; font-size: 11px !important; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; }
.footer-bottom { display: flex; justify-content: space-between; padding-top: 20px; border-top: 1px solid var(--line); color: var(--muted); font-size: 10px; }

/* ---------------------------------------------------------- legal pages */
.legal { max-width: 780px; padding: 58px 0 104px; }
.legal .eyebrow { margin-bottom: 14px; }
.legal h1 { margin-bottom: 18px; font-size: clamp(34px, 4.6vw, 50px); line-height: 1.06; letter-spacing: -2px; }
.legal-lede { max-width: 620px; color: var(--muted); font-size: 16px; line-height: 1.7; }
.legal-updated { margin: 20px 0 0; color: #9aa7bb; font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; }
.legal-body { margin-top: 50px; }
.legal-body section { padding-top: 30px; border-top: 1px solid var(--line); margin-top: 30px; }
.legal-body section:first-child { padding-top: 0; border-top: 0; margin-top: 0; }
.legal-body h2 { margin-bottom: 12px; font-size: 19px; letter-spacing: -0.5px; font-weight: 600; }
.legal-body p { max-width: 700px; margin-bottom: 14px; color: var(--muted); font-size: 14px; line-height: 1.75; }
.legal-body ul { display: grid; gap: 9px; margin: 0 0 14px; padding-left: 19px; }
.legal-body li { color: var(--muted); font-size: 14px; line-height: 1.7; }
.legal-body strong { color: var(--ink); }
.legal-body a { color: var(--blue); font-weight: 600; }
.legal-body a:hover { text-decoration: underline; }
.legal-back { margin-top: 48px; }
/* The two legal pages keep the old two-element header; it is styled inline on
   those pages, so nothing here duplicates it. */

/* --------------------------------------------------- how it works steps */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 64px; }
.step-card { position: relative; display: flex; flex-direction: column; padding: 25px; }
.step-card-lift { transform: translateY(-18px); background: rgba(234, 241, 254, 0.75); border-color: var(--periwinkle-deep); }
.step-number { position: absolute; top: 25px; right: 25px; color: #aeb9cc; font-size: 11px; font-weight: 700; }
.step-card h3 { margin: 0 0 9px; font-size: 17px; letter-spacing: -0.4px; font-weight: 600; }
.step-card p { max-width: 280px; margin: 0 0 22px; color: var(--muted); font-size: 13px; line-height: 1.65; }
/* The little UI fragment at the foot of each step is the app's own language:
   recipient chips, a plan row, a progress bar. Nothing invented. */
.step-ui { display: grid; gap: 8px; margin-top: auto; padding-top: 20px; border-top: 1px solid var(--line); }
/* The tone dot a moment wears in the app, kept here because the step cards use
   it too. It is the only fragment of the old hand-drawn hero card that still has
   a job: everything else on that card is now the real capture. */
.plan-dot { width: 8px; height: 8px; border-radius: 50%; }
.plan-dot-blush { background: var(--blush); }
.plan-dot-mint { background: var(--mint); }
.chip { display: inline-flex; align-items: center; gap: 9px; width: fit-content; padding: 5px 14px 5px 5px; border: 1px solid var(--hairline); border-radius: 99px; background: var(--white); color: var(--ink); font-size: 12px; font-weight: 600; box-shadow: var(--card-shadow); }
.chip-on { color: var(--white); background: var(--blue); border-color: transparent; box-shadow: 0 4px 15px rgba(47, 99, 214, 0.22); }
.chip-face { display: block; width: 24px; height: 24px; flex: 0 0 auto; border-radius: 50%; object-fit: cover; background: var(--periwinkle-wash); }
.chip-on .chip-face { box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.45); }
.mini-row { display: flex; align-items: center; gap: 9px; padding: 9px 12px; border: 1px solid var(--hairline); border-radius: 12px; background: var(--white); font-size: 12px; font-weight: 600; }
.mini-row em { margin-left: auto; color: var(--muted); font-size: 10.5px; font-style: normal; font-weight: 600; }
.mini-row-open { background: #fbfcfe; color: var(--muted); }
.mini-progress { display: block; height: 7px; border-radius: 99px; background: var(--periwinkle-deep); overflow: hidden; }
.mini-progress span { display: block; width: 25%; height: 100%; border-radius: 99px; background: linear-gradient(90deg, var(--blue), #60b1ff); }
.mini-caption { color: var(--muted); font-size: 10.5px; }

/* ---------------------------------------------------------------- plans */
#plans { padding-bottom: 40px; }
.plans { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-top: 64px; }
.plan-card { position: relative; display: flex; flex-direction: column; padding: 30px; }
.plan-card-pro { border-color: rgba(47, 99, 214, 0.3); background: rgba(234, 241, 254, 0.8); box-shadow: 0 2px 12px rgba(47, 99, 214, 0.08); }
.plan-badge { position: absolute; top: 22px; right: 22px; margin: 0; padding: 5px 10px; border-radius: 99px; color: var(--white); background: var(--blue); font-size: 9.5px; font-weight: 700; letter-spacing: 1px; }
.plan-name { margin: 0; color: var(--muted); font-family: var(--display); font-size: 14px; font-weight: 600; letter-spacing: 0.2px; }
.plan-price { display: flex; align-items: baseline; gap: 9px; margin: 12px 0 0; }
.plan-amount { font-family: var(--display); font-size: 44px; font-weight: 600; letter-spacing: -1.8px; font-variant-numeric: tabular-nums; }
.plan-period { color: var(--muted); font-size: 12.5px; font-weight: 500; font-variant-numeric: tabular-nums; }
.plan-note { margin: 12px 0 0; color: var(--muted); font-size: 13px; line-height: 1.6; }
.plan-alt { margin: 10px 0 0; color: var(--muted); font-size: 12.5px; }
.plan-alt strong { color: var(--ink); }
.plan-save { display: inline-block; margin-left: 6px; padding: 4px 9px; border-radius: 99px; color: var(--mint); background: var(--mint-wash); font-size: 10px; font-weight: 700; }
.plan-list { display: grid; gap: 12px; margin: 24px 0 28px; padding: 0; list-style: none; }
.plan-list li { position: relative; padding-left: 27px; color: var(--muted); font-size: 13.5px; line-height: 1.62; }
.plan-list li strong { color: var(--ink); }
.plan-list li::before { content: ""; position: absolute; left: 0; top: 3px; width: 18px; height: 18px; border-radius: 50%; background: var(--mint-wash); }
.plan-list li::after { content: "\2713"; position: absolute; left: 0; top: 3px; display: flex; align-items: center; justify-content: center; width: 18px; height: 18px; color: var(--mint); font-size: 10px; font-weight: 700; }
.plan-card .button { width: 100%; margin-top: auto; }
.plan-fine { margin: 15px 0 0; color: #9aa7bb; font-size: 11px; line-height: 1.65; }
.plans-note { max-width: 720px; margin: 30px auto 0; color: var(--muted); font-size: 13px; line-height: 1.75; text-align: center; }

/* ----------------------------------------------------------- docs strip */
.docs-strip { padding-bottom: 40px; }
.docs-card { display: flex; align-items: center; justify-content: space-between; gap: 44px; padding: 40px 44px; border-radius: 22px; background: var(--white); }
.docs-card .eyebrow { margin-bottom: 12px; }
.docs-card h3 { margin: 0 0 9px; font-size: 25px; letter-spacing: -1px; font-weight: 600; }
.docs-copy p { max-width: 580px; margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.72; }
.docs-card .button { flex: none; }

/* ------------------------------------------------------------------ faq */
.faq-grid { display: grid; grid-template-columns: 0.72fr 1.28fr; gap: 70px; align-items: start; }
.faq-intro h2 { margin: 0 0 18px; font-size: clamp(32px, 4vw, 50px); line-height: 1.06; letter-spacing: -2px; font-weight: 600; }
.faq-intro > p:not(.eyebrow) { max-width: 330px; margin: 0 0 20px; color: var(--muted); font-size: 14px; line-height: 1.72; }
.faq-list { display: grid; gap: 12px; }
.faq-item { border: 1px solid var(--hairline); border-radius: 18px; background: var(--white); box-shadow: var(--card-shadow); transition: border-color 180ms ease-out, box-shadow 180ms ease-out; }
.faq-item[open] { border-color: var(--periwinkle-deep); box-shadow: var(--card-shadow-lift); }
.faq-item summary { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 19px 22px; font-family: var(--display); font-size: 15.5px; font-weight: 600; letter-spacing: -0.3px; cursor: pointer; list-style: none; }
.faq-item summary::-webkit-details-marker { display: none; }
/* The plus/minus is a Material Symbol rather than a typed character, so it
   matches the icons in the steps above it. */
/* The `/ ""` after each icon name is CSS alt text: the marker is decoration and
   the disclosure already announces its own state, so a screen reader should not
   hear the ligature name read out as if it were part of the question. */
.faq-item summary::after {
  content: "add" / ""; display: grid; flex: 0 0 auto; width: 25px; height: 25px; place-items: center;
  border-radius: 50%; color: var(--blue); background: var(--periwinkle-wash);
  font-family: "Material Symbols Rounded"; font-size: 16px; font-weight: normal;
  font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 24;
}
.faq-item[open] summary::after { content: "remove" / ""; }
.faq-item p { max-width: 640px; margin: 0; padding: 0 22px 21px; color: var(--muted); font-size: 13.5px; line-height: 1.75; }
.faq-item a { color: var(--blue); font-weight: 600; }
.faq-item a:hover { text-decoration: underline; }

/* Shared code styling — the FAQ and the docs page both quote real values. */
code { padding: 1px 5px; border-radius: 6px; color: var(--ink); background: var(--periwinkle-wash); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.92em; }

/* ---------------------------------------------------------- docs page */
.docs-hero { padding: 46px 0 0; }
.docs-hero h1 { max-width: 720px; margin: 0 0 18px; font-size: clamp(34px, 4.6vw, 54px); line-height: 1.04; letter-spacing: -2.2px; font-weight: 600; }
.docs-hero p.docs-lede { max-width: 620px; margin: 0; color: var(--muted); font-size: 16px; line-height: 1.72; }
.docs-layout { display: grid; grid-template-columns: 250px 1fr; gap: 70px; padding: 46px 0 110px; align-items: start; }
.docs-aside { position: sticky; top: 110px; }
.docs-aside p { margin: 0 0 12px; color: #9aa7bb; font-size: 10.5px; font-weight: 700; letter-spacing: 1.1px; text-transform: uppercase; }
.docs-toc { display: grid; gap: 2px; }
.docs-toc a { padding: 9px 12px; border-radius: 11px; color: var(--muted); font-size: 12.5px; font-weight: 500; transition: color 180ms ease-out, background-color 180ms ease-out; }
.docs-toc a:hover { color: var(--blue); background: var(--periwinkle-wash); }
.docs-body { min-width: 0; }
.docs-body > section { padding-top: 34px; border-top: 1px solid var(--line); margin-top: 34px; }
.docs-body > section:first-child { padding-top: 0; border-top: 0; margin-top: 0; }
.docs-body h2 { margin: 0 0 13px; font-size: 22px; letter-spacing: -0.7px; font-weight: 600; }
.docs-body h3 { margin: 24px 0 9px; font-size: 15.5px; letter-spacing: -0.3px; font-weight: 600; }
.docs-body p { max-width: 700px; margin: 0 0 14px; color: var(--muted); font-size: 14px; line-height: 1.78; }
.docs-body ul { display: grid; gap: 9px; max-width: 700px; margin: 0 0 16px; padding-left: 20px; }
.docs-body li { color: var(--muted); font-size: 14px; line-height: 1.72; }
.docs-body li strong, .docs-body p strong { color: var(--ink); }
.docs-body a { color: var(--blue); font-weight: 600; }
.docs-body a:hover { text-decoration: underline; }
.docs-body pre { max-width: 700px; margin: 0 0 16px; padding: 17px 19px; border-radius: 15px; background: var(--ink); color: #dce7ff; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12.5px; line-height: 1.75; overflow-x: auto; }
.docs-body pre code { padding: 0; color: inherit; background: none; }
.docs-note { max-width: 700px; margin: 0 0 16px; padding: 17px 19px; border: 1px solid var(--periwinkle-deep); border-radius: 16px; background: var(--periwinkle-wash); color: var(--ink); font-size: 13px; line-height: 1.72; }
.docs-note strong { display: block; margin-bottom: 4px; }
.docs-table { width: 100%; max-width: 700px; margin: 0 0 16px; border-collapse: collapse; font-size: 12.5px; }
.docs-table th, .docs-table td { padding: 11px 12px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
.docs-table th { color: var(--ink); font-weight: 600; font-size: 11px; letter-spacing: 0.6px; text-transform: uppercase; }
.docs-table td { color: var(--muted); line-height: 1.65; }
.docs-table td code { white-space: nowrap; }
.docs-meta { margin: 14px 0 0; color: #9aa7bb; font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; }

/* ------------------------------------------------------------- arrival */
/* Every block below the fold arrives once, when it first comes into view, and
   then forgets it ever had an entrance: script.js drops both classes when the
   transition has run, so nothing is left holding a transform or a transition
   that would fight the hover lift on the cards inside it.

   Both classes are added by script.js and never written in the markup, so a
   reader without JavaScript — or with motion reduced — gets the page fully
   composed rather than a page with invisible sections in it. An entrance that
   can hide content when the script fails is not an entrance. */
.reveal { opacity: 0; transform: translateY(20px); }
.reveal-in {
  opacity: 1; transform: none;
  transition:
    opacity 720ms cubic-bezier(0.22, 0.61, 0.36, 1) var(--reveal-delay, 0ms),
    transform 720ms cubic-bezier(0.22, 0.61, 0.36, 1) var(--reveal-delay, 0ms);
}

/* --------------------------------------------------------- responsive */
@media (max-width: 1080px) {
  .nav-links { gap: 26px; }
  .steps, .plans { grid-template-columns: 1fr; }
  .step-card-lift { transform: none; }
  .step-card p { max-width: 400px; }
  .faq-grid { grid-template-columns: 1fr; gap: 40px; }
  .faq-intro > p:not(.eyebrow) { max-width: 470px; }
  .docs-layout { grid-template-columns: 1fr; gap: 32px; }
  .docs-aside { position: static; }
  .docs-toc { display: flex; flex-wrap: wrap; gap: 6px; }
  .docs-toc a { padding: 7px 13px; border: 1px solid var(--line); border-radius: 99px; }
}
@media (max-width: 980px) {
  .hero-inner { grid-template-columns: 1fr; gap: 40px; }
  .hero-copy { text-align: center; }
  .hero-badge { margin-inline: auto; }
  .hero-lede { margin: 0 auto; }
  .hero-actions { justify-content: center; }
  .mobile-note { justify-content: center; }
  .hero-stage { max-width: 460px; margin: 0 auto; width: 100%; min-height: 640px; }
  /* Stacked, the copy sits above the device and the stage is centred, so the
     field follows it: the 68% that lands under the phone in the two-column
     layout would otherwise light up the right-hand third of a phone screen. */
  .hero-grid {
    -webkit-mask-image: radial-gradient(460px 560px at 50% 72%, #000 0%, rgba(0, 0, 0, 0.4) 62%, transparent 100%);
            mask-image: radial-gradient(460px 560px at 50% 72%, #000 0%, rgba(0, 0, 0, 0.4) 62%, transparent 100%);
  }
  .hero-phone { width: 262px; }
  .card-note, .card-circle { width: min(192px, 54%); }
}
/* Below 768px the row of links cannot hold four labels, so it becomes the
   full-screen overlay and the hamburger takes over. */
@media (max-width: 768px) {
  .shell { width: min(100% - 36px, 560px); }
  .site-nav { padding: 20px; }
  .site-nav::after { left: 20px; right: 20px; }
  .nav-links { display: none; }
  /* The bar's own CTA goes; the overlay's copy of it has to come back, or the
     broad `display: none` here would hide the one action on the phone. */
  .nav-cta { display: none; }
  .mobile-nav .nav-cta { display: inline-flex; }
  .hamburger { display: flex; }
  .mobile-nav { display: flex; }
  .hero { padding-top: 40px; }
  h1 { font-size: clamp(34px, 9vw, 48px); letter-spacing: -1.6px; }
  .hero-stage { min-height: 580px; }
  .aurora { width: min(560px, 152%); height: min(560px, 152%); }
  .aurora-b { width: min(400px, 108%); height: min(400px, 108%); }
  .aurora-c { width: min(340px, 92%); height: min(340px, 92%); }
  .hero-grid { background-size: 22px 22px; }
  .hero-phone { width: 236px; top: 26px; }
  /* Anchored to opposite corners of the device on a phone, so the overlap reads
     as annotations stuck to it rather than two cards drifting over its middle. */
  /* Only 4px proud of the stage on a phone: the shell already eats 14px of the
     viewport on each side, so the −18px the desktop rules use put the circle
     card 7px off the left edge of a 390px screen — a card cut in half by the
     viewport, which reads as a bug rather than as a card. */
  .card-note { top: 30%; right: -4px; width: min(162px, 52%); }
  .card-circle { bottom: 52px; left: -4px; width: min(162px, 52%); }
  .stack-strip { flex-direction: column; gap: 14px; padding-bottom: 0; }
  .stack-strip ul { justify-content: center; gap: 20px; }
  .section { padding: 85px 0; }
  .section-intro { display: block; text-align: center; }
  .section-intro > p:last-child { margin: 20px auto 0; max-width: 390px; }
  .step-card, .step-card-lift { min-height: 205px; transform: none; text-align: center; }
  .feature-icon { margin: 0 auto 22px; }
  .step-card p { margin: 0 auto; }
  .showcase { display: flex; flex-direction: column; gap: 49px; padding: 85px 0; }
  .showcase-copy { text-align: center; }
  .showcase-copy > p:not(.eyebrow) { margin: 18px auto 27px; }
  .check-list { text-align: left; max-width: 330px; margin: auto; }
  .dashboard-frame { width: min(100%, 370px); }
  .tour-section { padding: 85px 0; }
  .tour-inner { display: flex; flex-direction: column; align-items: stretch; gap: 46px; text-align: center; }
  .tour-copy > p:not(.eyebrow):not(.tour-caption) { margin: 18px auto 0; }
  .tour-beats { max-width: 330px; margin: 26px auto 0; text-align: left; }
  .tour-caption { max-width: 330px; margin: 26px auto 0; }
  .tour-frames { padding-left: 0; }
  .tour-frame { width: 44%; max-width: 190px; }
  .tour-frame img { border-width: 5px; border-radius: 24px; }
  .tour-frame-front { width: 50%; max-width: 210px; margin-left: -16px; }
  .cta { padding: 75px 0; }
  .cta-card { display: block; padding: 37px 28px; text-align: center; }
  .cta-card > div:last-child > p { margin: 23px auto 20px; }
  .cta-actions { flex-direction: column; gap: 16px; }
  .cta-card .button { width: 100%; }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 35px 25px; }
  .footer-grid > div:first-child { grid-column: 1 / -1; }
  .footer-bottom { gap: 15px; }
  .site-footer { padding-top: 50px; }
  .legal { padding: 40px 0 72px; }
  .legal-body { margin-top: 34px; }
  .legal-body section { padding-top: 24px; margin-top: 24px; }
  .legal-back { width: 100%; }
  #plans { padding-bottom: 24px; }
  .docs-strip { padding-bottom: 24px; }
  #faq { padding-top: 80px; }
  .plans-note { text-align: left; }
  .plan-card { padding: 24px; }
  .plan-badge { top: 18px; right: 18px; }
  .docs-card { display: block; padding: 30px 24px; text-align: center; }
  .docs-card .button { width: 100%; margin-top: 22px; }
  .faq-item summary { padding: 16px 17px; font-size: 14.5px; }
  .faq-item p { padding: 0 17px 18px; }
  .docs-hero { padding-top: 34px; }
  .docs-layout { padding: 34px 0 72px; }
}
@media (max-width: 480px) {
  .shell { width: min(100% - 28px, 560px); }
  h1 { font-size: clamp(30px, 8.6vw, 40px); letter-spacing: -1.2px; }
  .hero-actions { flex-direction: column; gap: 16px; }
  .button-glass { width: 100%; justify-content: center; }
  .mobile-note { align-items: flex-start; text-align: left; }
  .section-intro h2, .showcase h2, .tour-copy h2, .cta h2, .faq-intro h2 { letter-spacing: -1.2px; }
  .plan-amount { font-size: 38px; }
  .stack-strip ul { gap: 14px; }
  .stack-strip li { font-size: 13px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* Nothing arrives, nothing drifts, nothing floats, and the pointer listeners
     in script.js are never attached at this setting — so the light stays put and
     the page still looks like itself once it has settled, it just does not
     perform. The aurora keeps its shape and loses its clock: a still pool of
     brand light behind the device, which is what the hero looks like at rest
     anyway. `.reveal` is forced visible as a last resort: script.js never adds
     it here, but a stylesheet that can hide content should have said out loud
     that it will not hide it for this reader. */
  .aurora, .aurora-turn, .hero-phone, .hero-phone-drift, .glow, .card-note, .card-circle { animation: none; }
  .hero-phone-body { transition: none; }
  .hero-spot, .hero-grid-hot { display: none; }
  .hero-copy > *, .reveal { animation: none !important; opacity: 1 !important; transform: none !important; }
  .button, .button-glass, .nav-cta, .card, .faq-item, .nav-links a { transition: none; }
  .button-glass:hover, .button:hover, .nav-cta:hover, .card:hover { transform: none; }
}
