/* styles.css */
/* ===========================================================================
   Fonts, served from this origin.
   ---------------------------------------------------------------------------
   These used to come from fonts.googleapis.com, which meant a DNS lookup, a
   TLS handshake and 51KB of render-blocking stylesheet to a third party
   before the browser could paint anything. Declaring them here puts them in
   the same bundle as the rest of the CSS: no extra request at all, and the
   woff2 files come from a connection the browser has already opened.

   Latin and latin-ext only - the Google stylesheet declared 119 faces across
   every script it supports, and this site is in English.

   Regenerate with scratchpad/selfhost.mjs if the type ever changes.
   =========================================================================== */

@font-face {
  font-family: 'Google Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/google-sans-400-normal-ext.woff2') format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: 'Google Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/google-sans-400-normal.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Google Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/google-sans-500-normal-ext.woff2') format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: 'Google Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/google-sans-500-normal.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Google Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/google-sans-600-normal-ext.woff2') format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: 'Google Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/google-sans-600-normal.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Google Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/google-sans-700-normal-ext.woff2') format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: 'Google Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/google-sans-700-normal.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-400-normal-ext.woff2') format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-400-normal.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-500-normal-ext.woff2') format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-500-normal.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-600-normal-ext.woff2') format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-600-normal.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Instrument Serif';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/instrument-serif-400-italic-ext.woff2') format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: 'Instrument Serif';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/instrument-serif-400-italic.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/instrument-serif-400-normal-ext.woff2') format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/instrument-serif-400-normal.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* ===========================================================================
   Trabbly HR — marketing site
   ---------------------------------------------------------------------------
   Deliberately not another blue SaaS page. The category is a sea of light-blue
   gradients and stock photographs of people laughing at laptops; this leans the
   other way — deep ink, a serif with an actual voice, and real numbers set in
   mono because the product's whole argument is that its numbers are right.

   Palette is the Trabbly brand: ink #004742, teal #14706A, spring #63E77F,
   over warm paper rather than pure white.
   =========================================================================== */

:root {
  --ink: #04231f;
  --ink-2: #004742;
  --teal: #14706a;
  --teal-soft: #3fae94;
  --spring: #63e77f;
  --paper: #faf7f1;
  --paper-2: #f3efe6;
  --line: #e3ddd0;
  --graphite: #1c2a27;
  --muted: #5f6f6b;
  --muted-light: rgba(255, 255, 255, 0.62);

  --display: 'Instrument Serif', 'Iowan Old Style', Georgia, serif;
  --sans: 'Google Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

  --wrap: 1180px;
  --r: 18px;
}

/* ── Reset ───────────────────────────────────────────────────────────────── */

/* The `hidden` attribute is display:none in the UA stylesheet, and any author
   rule that sets `display` overrides it. `.form { display: grid }` did, so
   the demo page showed its details form, its code screen and its confirmation
   all at the same time. Kept here rather than beside that one rule, because
   the next `display` on a hideable element would bring the bug straight
   back. */
[hidden] {
  display: none !important;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}
* {
  margin: 0;
}
html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* Every page opens on a dark hero and ends on a dark footer, so the
     canvas behind them is dark too. Without a background of its own, html
     takes the canvas from body - and rubber-banding past either end of
     the page flashed the paper colour against the dark band it was
     attached to. */
  background: var(--ink);
}
body {
  font-family: var(--sans);
  background: var(--paper);
  color: var(--graphite);
  font-size: 17px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img,
svg {
  display: block;
  max-width: 100%;
}
a {
  color: inherit;
  text-decoration: none;
}
button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: #fff;
  padding: 12px 18px;
  z-index: 999;
}
.skip:focus {
  left: 12px;
  top: 12px;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: 24px;
}

/* ── Type scale ──────────────────────────────────────────────────────────── */
.h2 {
  font-family: var(--display);
  font-weight: 400;
  /* Up from 3.35rem. A section heading was only ~70% of the hero's 4.8rem,
     which is close enough that scrolling past one did not feel like arriving
     somewhere new. At 3.75 the steps read as a scale — hero, section, body —
     rather than as two sizes of large. */
  font-size: clamp(2.15rem, 4.8vw, 3.75rem);
  line-height: 1.06;
  letter-spacing: -0.018em;
  color: var(--ink);
  max-width: 20ch;

  /* Explicit, because there was none: the browser default for an h2 is about
     0.83em, so at this size every section title carried ~45px of accidental
     space beneath it. That is the gap under "What your Monday morning looks
     like" — not a layout decision, just an unset property. */
  margin: 0 0 26px;
}
.h2--light {
  color: #fff;
}
.h2 em {
  font-style: italic;
  color: var(--teal);
}

.eyebrow {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--spring);
  margin-bottom: 18px;
}
.eyebrow--dark {
  color: var(--teal);
}

.body {
  color: var(--muted);
  font-size: 1.02rem;
  margin-top: 18px;
  max-width: 58ch;
}
.body--wide {
  max-width: 66ch;
}
.mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 20px;
  border-radius: 12px;
  font-size: 0.92rem;
  font-weight: 700;
  border: 1px solid transparent;
  cursor: pointer;
  transition:
    transform 0.18s cubic-bezier(0.2, 0.8, 0.3, 1),
    background 0.18s,
    border-color 0.18s,
    box-shadow 0.18s;
  white-space: nowrap;
}
.btn:hover {
  transform: translateY(-2px);
}
.btn:active {
  transform: translateY(0);
}
.btn--lg {
  padding: 15px 30px;
  border-radius: 14px;
  font-size: 1rem;
}
.btn--full {
  width: 100%;
}
.btn--spring {
  background: var(--spring);
  color: var(--ink);
  box-shadow: 0 10px 30px -12px rgba(99, 231, 127, 0.85);
}
.btn--spring:hover {
  background: #7bf094;
  box-shadow: 0 16px 38px -14px rgba(99, 231, 127, 0.95);
}
.btn--solid {
  background: var(--ink-2);
  color: #fff;
}
.btn--solid:hover {
  background: var(--teal);
}
.btn--outline {
  border-color: rgba(255, 255, 255, 0.28);
  color: #fff;
}
.btn--outline:hover {
  border-color: var(--spring);
  color: var(--spring);
}
.gap .btn--outline,
.price .btn--outline,
.mods .btn--outline {
  border-color: var(--line);
  color: var(--ink);
}
.gap .btn--outline:hover,
.price .btn--outline:hover {
  border-color: var(--teal);
  color: var(--teal);
}
.btn--ghost {
  color: #fff;
  opacity: 0.82;
}
.btn--ghost:hover {
  opacity: 1;
}

/* ── Texture ─────────────────────────────────────────────────────────────── */
.grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.28;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}

/* ── Nav ─────────────────────────────────────────────────────────────────── */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  /* Padding on the bar, not on the pill: on a narrow screen this is what
     insets the glass from the viewport edges, and on a wide one the wrap's own
     max-width has already done that job. */
  padding: 0 16px;
  transition: padding 0.3s cubic-bezier(0.2, 0.8, 0.3, 1);
}
.nav.is-stuck {
  padding-top: 12px;
}
.nav__inner {
  display: flex;
  align-items: center;
  gap: 28px;
  height: 76px;
  border: 1px solid transparent;
  transition:
    height 0.3s cubic-bezier(0.2, 0.8, 0.3, 1),
    background 0.3s,
    border-color 0.3s,
    border-radius 0.3s,
    box-shadow 0.3s;
}
.nav__logo {
  height: 30px;
  width: auto;
}

/* Frosted glass rather than a solid bar, and dark rather than paper: every
   page is dark behind the header, so a pale bar was a bright slab cutting
   across it. The saturate() is what stops a blurred backdrop going grey and
   flat - without it this reads as fog, not glass.

   The pill is .nav__inner, not .nav, so it detaches from the edges and reads
   as floating over the page rather than bolted to the top of it. Staying dark
   also means the logo and the links keep the colours they already had, so
   nothing has to swap mid-scroll. */
.nav.is-stuck .nav__inner {
  height: 62px;
  border-radius: 20px;
  background: rgba(7, 40, 36, 0.5);
  backdrop-filter: blur(20px) saturate(170%);
  -webkit-backdrop-filter: blur(20px) saturate(170%);
  border-color: rgba(255, 255, 255, 0.12);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.09) inset,
    0 18px 44px -20px rgba(0, 0, 0, 0.6);
}
/* Opaque where the browser cannot blur, otherwise it is unreadable text
   floating over the page. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nav.is-stuck .nav__inner {
    background: rgba(7, 40, 36, 0.94);
  }
}
.nav__links {
  display: flex;
  gap: 26px;
  margin-left: auto;
  font-size: 0.9rem;
  font-weight: 600;
}
.nav__links a {
  color: rgba(255, 255, 255, 0.78);
  transition: color 0.18s;
}
.nav__links a:hover {
  color: var(--spring);
}
.nav__actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* ── Hero ────────────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  background: linear-gradient(165deg, #04231f 0%, #004742 52%, #0b5c52 100%);
  color: #fff;
  padding: 168px 0 110px;
  overflow: hidden;
}
.hero__glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(120px);
  pointer-events: none;
}
.hero__glow--a {
  width: 620px;
  height: 620px;
  background: rgba(99, 231, 127, 0.24);
  top: -240px;
  right: -160px;
}
.hero__glow--b {
  width: 520px;
  height: 520px;
  background: rgba(63, 174, 148, 0.22);
  bottom: -260px;
  left: -180px;
}
.hero__glow--c {
  width: 560px;
  height: 560px;
  background: rgba(99, 231, 127, 0.18);
  top: -200px;
  left: 40%;
}
.hero__inner {
  position: relative;
}
.hero__title {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.6rem, 6.6vw, 5.1rem);
  line-height: 1.02;
  letter-spacing: -0.022em;
  max-width: 16ch;
}
.hero__title em {
  font-style: italic;
  color: var(--spring);
}
.hero__lede {
  margin-top: 26px;
  max-width: 60ch;
  color: var(--muted-light);
  font-size: 1.06rem;
}
.hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 36px;
}
.hero__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 48px;
  list-style: none;
  padding: 0;
  margin-top: 64px;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  padding-top: 28px;
}
.hero__facts strong {
  display: block;
  font-family: var(--display);
  font-size: 2.6rem;
  line-height: 1;
  color: var(--spring);
}
.hero__facts span {
  display: block;
  margin-top: 6px;
  font-size: 0.82rem;
  color: var(--muted-light);
}

/* ── The gap ─────────────────────────────────────────────────────────────── */
.gap {
  padding: 104px 0;
  background: var(--paper);
}
.gap__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(255px, 100%), 1fr));
  gap: 20px;
  margin-top: 48px;
}
.gap__card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 26px 24px;
}
.gap__card h3 {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink);
}
.gap__who {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--teal);
  margin: 4px 0 14px;
  letter-spacing: 0.01em;
}
.gap__card p:last-child {
  font-size: 0.94rem;
  color: var(--muted);
}
.gap__card--us {
  background: linear-gradient(160deg, var(--ink-2), var(--teal));
  border-color: transparent;
  color: #fff;
}
.gap__card--us h3 {
  color: #fff;
}
.gap__card--us .gap__who {
  color: var(--spring);
}
.gap__card--us p:last-child {
  color: rgba(255, 255, 255, 0.78);
}

/* ── Payslip ─────────────────────────────────────────────────────────────── */
.slip {
  padding: 104px 0;
  background: var(--ink);
  color: #fff;
}
.slip__lede {
  margin-top: 18px;
  max-width: 62ch;
  color: var(--muted-light);
  font-size: 1rem;
}
.slip__panel {
  margin-top: 46px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 22px;
  overflow: hidden;
}
.slip__controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 24px;
  padding: 22px 26px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(0, 0, 0, 0.16);
}
.seg {
  display: inline-flex;
  background: rgba(255, 255, 255, 0.07);
  border-radius: 999px;
  padding: 4px;
}
.seg__btn {
  border: 0;
  background: none;
  color: rgba(255, 255, 255, 0.66);
  padding: 8px 18px;
  border-radius: 999px;
  font-size: 0.88rem;
  font-weight: 700;
  cursor: pointer;
  transition:
    background 0.2s,
    color 0.2s;
}
.seg__btn.is-on {
  background: var(--spring);
  color: var(--ink);
}
.slider {
  flex: 1;
  min-width: 260px;
}
.slider__label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.8rem;
  color: var(--muted-light);
  margin-bottom: 8px;
}
.slider__label output {
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--spring);
}
.slider input {
  width: 100%;
  appearance: none;
  height: 4px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.18);
  outline: none;
}
.slider input::-webkit-slider-thumb {
  appearance: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--spring);
  cursor: grab;
  border: 3px solid var(--ink);
  box-shadow: 0 0 0 1px var(--spring);
}
.slider input::-moz-range-thumb {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--spring);
  cursor: grab;
  border: 3px solid var(--ink);
}

.slip__body {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.slip__col {
  padding: 26px;
}
.slip__col--sep {
  border-left: 1px solid rgba(255, 255, 255, 0.1);
}
.slip__ch {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
  margin-bottom: 16px;
}
.lines {
  margin: 0;
}
.lines .line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 9px 0;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.1);
  font-size: 0.93rem;
}
.lines .line span {
  color: rgba(255, 255, 255, 0.72);
}
.lines .line small {
  display: block;
  font-size: 0.7rem;
  color: rgba(255, 255, 255, 0.36);
}
.lines .line b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  white-space: nowrap;
}
.lines .line--gross b {
  color: #fff;
}
.lines .line--minus b {
  color: #ffb4a8;
}
.net {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: 18px;
  padding: 15px 18px;
  border-radius: 12px;
  background: rgba(99, 231, 127, 0.12);
  border: 1px solid rgba(99, 231, 127, 0.3);
}
.net span {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--spring);
}
.net strong {
  font-size: 1.45rem;
  font-weight: 600;
  color: var(--spring);
}
.net--cost {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.16);
}
.net--cost span,
.net--cost strong {
  color: #fff;
}
.slip__note {
  margin-top: 14px;
  font-size: 0.78rem;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.44);
}
.slip__disclaim {
  padding: 16px 26px 22px;
  font-size: 0.74rem;
  color: rgba(255, 255, 255, 0.34);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

/* ── Country layer ───────────────────────────────────────────────────────── */
.layer {
  padding: 104px 0;
  background: var(--paper-2);
}
.layer__grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: 64px;
  align-items: start;
}
.ticks {
  list-style: none;
  padding: 0;
  margin-top: 26px;
  display: grid;
  gap: 10px;
}
.ticks li {
  position: relative;
  padding-left: 26px;
  font-size: 0.94rem;
  color: var(--muted);
}
.ticks li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--spring);
  box-shadow: 0 0 0 3px rgba(99, 231, 127, 0.22);
}
.ticks--light li {
  color: var(--muted-light);
}

.layer__cards {
  display: grid;
  gap: 16px;
}
.ccard {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 22px;
}
.ccard header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}
.flag {
  font-size: 1.6rem;
  line-height: 1;
}
.ccard h3 {
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--ink);
}
.ccard header p {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--teal-soft);
}
.ccard ul {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 9px;
}
.ccard li {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  font-size: 0.86rem;
  padding-bottom: 9px;
  border-bottom: 1px dashed var(--line);
}
.ccard li:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}
.ccard li span {
  color: var(--muted);
}
.ccard li em {
  font-style: normal;
  font-weight: 600;
  color: var(--ink);
  text-align: right;
}
.ccard--next {
  background: transparent;
  border-style: dashed;
}
.ccard--next p {
  font-size: 0.88rem;
  color: var(--muted);
}

/* ── Modules ─────────────────────────────────────────────────────────────── */
.mods {
  padding: 104px 0;
  background: var(--paper);
}
.mods__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr));
  gap: 1px;
  margin-top: 48px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
.mod {
  background: var(--paper);
  padding: 24px 22px;
  transition: background 0.22s;
}
.mod:hover {
  background: #fff;
}
.mod h3 {
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.32rem;
  color: var(--ink);
  margin-bottom: 6px;
}
.mod p {
  font-size: 0.88rem;
  color: var(--muted);
  line-height: 1.55;
}

/* ── Door ────────────────────────────────────────────────────────────────── */
.door {
  padding: 104px 0;
  background: linear-gradient(160deg, #04231f, #0b463f);
  color: #fff;
}
.door__grid {
  display: grid;
  grid-template-columns: 1fr 0.85fr;
  gap: 64px;
  align-items: center;
}
.feed {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--r);
  overflow: hidden;
}
.feed__head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 14px 18px;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--spring);
  animation: pulse 2s infinite;
}
@keyframes pulse {
  0%,
  100% {
    opacity: 1;
    box-shadow: 0 0 0 0 rgba(99, 231, 127, 0.5);
  }
  50% {
    opacity: 0.7;
    box-shadow: 0 0 0 7px rgba(99, 231, 127, 0);
  }
}
.feed__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 18px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  font-size: 0.9rem;
}
.feed__row:last-child {
  border-bottom: 0;
}
.feed__row b {
  flex: 1;
  font-weight: 600;
}
.feed__row time {
  font-family: var(--mono);
  font-size: 0.84rem;
  color: rgba(255, 255, 255, 0.6);
}
.feed__row i {
  font-style: normal;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--spring);
  min-width: 48px;
  text-align: right;
}
.feed__row--muted {
  opacity: 0.42;
}
.feed__row--muted i {
  color: rgba(255, 255, 255, 0.5);
}
.pip {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.25);
}
.pip--ok {
  background: var(--spring);
}

/* ── Trust ───────────────────────────────────────────────────────────────── */
.trust {
  padding: 104px 0;
  background: var(--paper-2);
}
.trust__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 20px;
  margin-top: 48px;
}
.tcard {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 26px 24px;
}
.tcard h3 {
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 10px;
}
.tcard p {
  font-size: 0.92rem;
  color: var(--muted);
}

/* ── Pricing ─────────────────────────────────────────────────────────────── */
.price {
  padding: 104px 0;
  background: var(--paper);
}
.price__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 20px;
  margin-top: 48px;
  /* stretch, not start. `.plan` is already a flex column with `flex: 1` on its
     list, so every card was ready to fill the row and this one line was
     stopping it — leaving three cards of three different heights with their
     buttons at three different depths. */
  align-items: stretch;
}
.plan {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 30px 26px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.plan h3 {
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.7rem;
  color: var(--ink);
}
.plan__for {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--teal);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.plan__num {
  font-family: var(--display);
  font-size: 2.6rem;
  color: var(--ink);
  margin: 18px 0 6px;
  line-height: 1;
}
.plan__num small {
  font-family: var(--sans);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--muted);
  margin-left: 6px;
}
.plan ul {
  list-style: none;
  padding: 0;
  margin: 18px 0 26px;
  display: grid;
  gap: 10px;
  flex: 1;
}
.plan li {
  position: relative;
  padding-left: 24px;
  font-size: 0.9rem;
  color: var(--muted);
}
.plan li::before {
  content: '✓';
  position: absolute;
  left: 0;
  color: var(--teal-soft);
  font-weight: 700;
}
.plan--feature {
  background: linear-gradient(165deg, var(--ink-2), var(--teal));
  border-color: transparent;
  color: #fff;
  position: relative;
  box-shadow: 0 30px 60px -30px rgba(0, 71, 66, 0.55);
}
.plan--feature h3,
.plan--feature .plan__num {
  color: #fff;
}
.plan--feature .plan__for {
  color: var(--spring);
}
.plan--feature li {
  color: rgba(255, 255, 255, 0.82);
}
.plan--feature li::before {
  color: var(--spring);
}
.plan--feature .plan__num small {
  color: rgba(255, 255, 255, 0.65);
}
.plan__flag {
  position: absolute;
  top: -12px;
  left: 26px;
  background: var(--spring);
  color: var(--ink);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: 999px;
}

/* ── Pricing controls ────────────────────────────────────────────────────── */
.pricebar__lead {
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--muted);
}
.pricebar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
}
.seg--light {
  background: var(--paper-2);
  border: 1px solid var(--line);
}
.seg--light .seg__btn {
  color: var(--muted);
}
.seg--light .seg__btn.is-on {
  background: var(--ink-2);
  color: #fff;
}

.switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  user-select: none;
}
.switch input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.switch__track {
  width: 42px;
  height: 24px;
  border-radius: 999px;
  background: var(--line);
  position: relative;
  transition: background 0.2s;
  flex-shrink: 0;
}
.switch__knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.2s;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.switch input:checked + .switch__track {
  background: var(--teal);
}
.switch input:checked + .switch__track .switch__knob {
  transform: translateX(18px);
}
.switch input:focus-visible + .switch__track {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
}
.switch__text {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--muted);
}
.switch__text em {
  font-style: normal;
  margin-left: 6px;
  background: rgba(99, 231, 127, 0.22);
  color: var(--ink-2);
  font-weight: 700;
  font-size: 0.76rem;
  padding: 2px 8px;
  border-radius: 999px;
}

.plan__bench {
  font-size: 0.78rem;
  color: var(--muted);
  margin: 0 0 4px;
  padding-bottom: 14px;
  border-bottom: 1px dashed var(--line);
}
.plan__bench b {
  color: var(--ink);
  text-decoration: line-through;
  text-decoration-color: rgba(0, 0, 0, 0.25);
}
.plan--feature .plan__bench {
  color: rgba(255, 255, 255, 0.62);
  border-bottom-color: rgba(255, 255, 255, 0.2);
}
.plan--feature .plan__bench b {
  color: #fff;
  text-decoration-color: rgba(255, 255, 255, 0.45);
}
.price__fine {
  margin-top: 26px;
  font-size: 0.8rem;
  color: var(--muted);
  text-align: center;
  max-width: 70ch;
  margin-inline: auto;
}

/* ── FAQ ─────────────────────────────────────────────────────────────────── */
.faq {
  padding: 104px 0;
  background: var(--paper-2);
}
.faq__wrap {
  max-width: 860px;
}
.faq__list {
  margin-top: 40px;
  border-top: 1px solid var(--line);
}
.faq details {
  border-bottom: 1px solid var(--line);
}
.faq summary {
  list-style: none;
  cursor: pointer;
  padding: 22px 40px 22px 0;
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--ink);
  position: relative;
}
.faq summary::-webkit-details-marker {
  display: none;
}
.faq summary::after {
  content: '+';
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 1.4rem;
  font-weight: 400;
  color: var(--teal);
  transition: transform 0.22s;
}
.faq details[open] summary::after {
  transform: translateY(-50%) rotate(45deg);
}
.faq details p {
  padding: 0 40px 24px 0;
  font-size: 0.95rem;
  color: var(--muted);
  max-width: 68ch;
}

/* ── CTA ─────────────────────────────────────────────────────────────────── */
.cta {
  position: relative;
  padding: 104px 0;
  background: linear-gradient(160deg, #04231f 0%, #004742 60%, #0b5c52 100%);
  color: #fff;
  overflow: hidden;
}
.cta__grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  align-items: start;
}

/* The closing band on content pages. It used to carry the whole demo form,
   which meant two copies of twelve fields to keep in step and a header button
   that only scrolled you down the page. The form now lives on /demo and this
   is a single centred column that sends you there. */
.cta__band {
  position: relative;
  max-width: 660px;
  margin-inline: auto;
  text-align: center;
}
/* .h2 carries max-width: 20ch and .slip__lede 62ch, neither with auto margins.
   Inside a centred band the text centres within each element's own box, but
   the box still sits flush-left - which put the heading about 70px left of the
   buttons and the lede beneath it. Centre the boxes, not just their text. */
.cta__band .h2,
.cta__band .slip__lede,
.cta__band .cta__fine {
  margin-inline: auto;
}
.cta__acts {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 28px;
}
.cta__fine {
  margin-top: 18px;
  font-size: 0.85rem;
  color: rgba(255, 255, 255, 0.55);
}
/* Centred rather than left-aligned, since the band is. */
.cta__band .mascot--cta {
  margin-inline: auto;
}

/* The demo page is nothing but this section, so it needs the top clearance a
   page hero would normally provide under the fixed header. */
.cta--page {
  padding-top: 148px;
  padding-bottom: 88px;
}
.cta--page .eyebrow {
  color: var(--spring);
}

/* The demo page keeps the two-column split - pitch left, form right - so it
   only needs the email line styled. */
.demo__email {
  margin-top: 22px;
  font-size: 0.92rem;
  color: var(--muted-light);
}
.demo__email a {
  color: var(--spring);
}
.demo__email a:hover {
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* ── Section CTAs ─────────────────────────────────────────────────────────
   A solid/outlined pair closing a content section. btn--edge is the outlined
   half for light backgrounds: btn--outline is a white border with white text,
   built for the dark hero, and disappears on paper. */
.acts {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 46px;
}
.btn--edge {
  border-color: rgba(4, 35, 31, 0.22);
  color: var(--ink);
}
.btn--edge:hover {
  border-color: var(--teal);
  color: var(--teal);
  background: rgba(20, 112, 106, 0.05);
}
.form {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.13);
  border-radius: 20px;
  padding: 26px;
  display: grid;
  gap: 14px;
}
.form__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.form label,
.form .field {
  display: grid;
  gap: 6px;
  font-size: 0.78rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.66);
}
.field__label {
  font-size: 0.78rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.66);
}
.form input,
.form select,
.form textarea {
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 11px;
  padding: 11px 13px;
  color: #fff;
  /* 16px exactly, and not a pixel less. Safari zooms the whole page in when a
     focused field is smaller than that, which then leaves the rest of the form
     off-screen with no way back except pinching. The fix is the type size, not
     a maximum-scale on the viewport — that would also block the pinch. */
  font-size: 1rem;
  font-weight: 500;
  transition:
    border-color 0.18s,
    background 0.18s;
}

/* ── Field-level errors ────────────────────────────────────────────────────
   Against the field they belong to, not collected at the top: a list of
   problems above a nine-field form makes you hunt for the one it means. */
.field__err {
  font-size: 0.76rem;
  font-weight: 500;
  line-height: 1.45;
  color: #ffb4a8;
}
/* An empty slot must take no space, or every field carries a phantom gap. */
.field__err:empty {
  display: none;
}
.form input.is-bad,
.form select.is-bad,
.form textarea.is-bad {
  border-color: #ff8f7e;
  background: rgba(255, 92, 70, 0.1);
}
.form input::placeholder,
.form textarea::placeholder {
  color: rgba(255, 255, 255, 0.3);
}
.form input:focus,
.form select:focus,
.form textarea:focus {
  outline: none;
  border-color: var(--spring);
  background: rgba(0, 0, 0, 0.32);
}
.form select option {
  background: var(--ink);
}
.form textarea {
  resize: vertical;
}
.form .btn {
  margin-top: 4px;
}
.form__fine {
  font-size: 0.74rem;
  color: rgba(255, 255, 255, 0.4);
  text-align: center;
}
/* Hidden until it has something to say. A permanently reserved line of empty
   space reads as a rendering fault, and a message that appears in place is
   easier to notice than one that fades into a gap that was always there. */
.form__msg {
  display: none;
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.5;
  text-align: center;
  color: rgba(255, 255, 255, 0.62);
}
.form__msg:not(:empty) {
  display: block;
}
.form__msg.is-ok,
.form__msg.is-bad {
  padding: 10px 14px;
  border-radius: 11px;
}
.form__msg.is-ok {
  color: var(--spring);
  background: rgba(99, 231, 127, 0.12);
  border: 1px solid rgba(99, 231, 127, 0.28);
}
.form__msg.is-bad {
  color: #ffc7bd;
  background: rgba(255, 92, 70, 0.12);
  border: 1px solid rgba(255, 120, 100, 0.3);
}
.hp {
  position: absolute !important;
  left: -9999px !important;
  opacity: 0;
  height: 0;
  width: 0;
}

/* ── Footer ──────────────────────────────────────────────────────────────── */
.foot {
  background: var(--ink);
  color: rgba(255, 255, 255, 0.6);
  padding: 64px 0 28px;
}
.foot__inner {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 40px;
}
.foot__brand img {
  height: 26px;
  margin-bottom: 16px;
}
.foot__brand p {
  font-size: 0.88rem;
  max-width: 34ch;
}

/* Social icons. Inline SVG so they inherit colour and cost no extra request.
   40px targets - a 20px icon is under the minimum comfortable tap size, and
   the footer is where thumbs are least accurate. */
.foot__social {
  display: flex;
  gap: 8px;
  margin-top: 22px;
}
.foot__social a {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 11px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: rgba(255, 255, 255, 0.62);
  transition:
    color 0.2s,
    border-color 0.2s,
    background 0.2s,
    transform 0.2s;
}
.foot__social svg {
  width: 17px;
  height: 17px;
  fill: currentColor;
}
.foot__social a:hover {
  color: var(--ink);
  background: var(--spring);
  border-color: var(--spring);
  transform: translateY(-2px);
}
.foot__social a:focus-visible {
  outline: 2px solid var(--spring);
  outline-offset: 3px;
}
.foot__col {
  display: grid;
  gap: 9px;
  align-content: start;
}
.foot__col h4 {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #fff;
  margin-bottom: 4px;
}
.foot__col a {
  font-size: 0.9rem;
  transition: color 0.18s;
}
.foot__col a:hover {
  color: var(--spring);
}
.foot__now {
  font-size: 0.9rem;
  color: var(--spring);
  font-weight: 600;
}
.foot__soon {
  font-size: 0.9rem;
  opacity: 0.42;
}
.foot__base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px;
  margin-top: 48px;
  padding-top: 22px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.36);
}

/* ── Inner-page hero ─────────────────────────────────────────────────────── */
.phero {
  position: relative;
  background: linear-gradient(165deg, #04231f 0%, #004742 100%);
  color: #fff;
  padding: 150px 0 80px;
  overflow: hidden;
}
.phero h1 {
  font-family: var(--display);
  font-weight: 400;
  /* 5.2vw is 20px on a phone, so this sat on its 2.3rem floor at every
     mobile width - a page heading barely bigger than the paragraph under
     it. Scaled from the viewport properly it still reaches the same 4rem
     ceiling by tablet. */
  font-size: clamp(2.75rem, 10.5vw, 4rem);
  line-height: 1.04;
  letter-spacing: -0.02em;
  max-width: 18ch;
}
.phero h1 em {
  font-style: italic;
  color: var(--spring);
}
.phero p {
  margin-top: 20px;
  max-width: 58ch;
  color: var(--muted-light);
  font-size: 1.04rem;
}
.phero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 30px;
}

/* ── Nav active state ────────────────────────────────────────────────────── */
.nav__links a.is-here {
  color: var(--spring);
}

/* ── Calculator additions ────────────────────────────────────────────────── */
.calc__country {
  display: grid;
  gap: 6px;
  min-width: 210px;
}
.calc__country span {
  font-size: 0.8rem;
  color: var(--muted-light);
}
.calc__country select {
  appearance: none;
  background: rgba(0, 0, 0, 0.28)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2363E77F' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E")
    no-repeat right 14px center;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 11px;
  padding: 11px 38px 11px 14px;
  color: #fff;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
}
.calc__country select:focus {
  outline: none;
  border-color: var(--spring);
}
.calc__country option,
.calc__country optgroup {
  background: var(--ink);
  color: #fff;
}

/* ── Country picker with flags ──────────────────────────────────────────────
   Only present on a device with a fine pointer, where the native select cannot
   show a flag. The button deliberately matches .calc__country select exactly,
   so nothing moves when the picker takes over. */
.calc__country select.cpick__native {
  display: none;
}
.cpick {
  position: relative;
}
.cpick__btn {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  appearance: none;
  background: rgba(0, 0, 0, 0.28)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2363E77F' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E")
    no-repeat right 14px center;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 11px;
  padding: 11px 38px 11px 14px;
  color: #fff;
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.cpick__btn:hover {
  border-color: rgba(255, 255, 255, 0.34);
}
.cpick__btn:focus-visible,
.cpick__btn[aria-expanded='true'] {
  outline: none;
  border-color: var(--spring);
}
.cpick__flag {
  width: 21px;
  height: 16px;
  flex-shrink: 0;
  border-radius: 2px;
  object-fit: cover;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16);
}
.cpick__btnflag {
  display: flex;
  flex-shrink: 0;
}
.cpick__value {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cpick__list {
  position: absolute;
  z-index: 40;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  min-width: 240px;
  max-height: 320px;
  overflow-y: auto;
  padding: 6px;
  background: var(--ink);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 12px;
  box-shadow: 0 26px 52px -22px rgba(0, 0, 0, 0.75);
}
.cpick__group {
  padding: 9px 10px 5px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-light);
}
.cpick__opt {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  color: #fff;
  font-size: 0.93rem;
  font-weight: 500;
  cursor: pointer;
}
.cpick__opt.is-active {
  background: rgba(99, 231, 127, 0.16);
}
.cpick__opt[aria-selected='true'] {
  font-weight: 700;
}
.cpick__opt[aria-selected='true']::after {
  content: '';
  width: 6px;
  height: 6px;
  margin-left: auto;
  border-radius: 50%;
  background: var(--spring);
  flex-shrink: 0;
}
@media (prefers-reduced-motion: reduce) {
  .cpick__opt {
    transition: none;
  }
}

.soon {
  padding: 54px 26px;
  text-align: center;
}
.soon h3 {
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.8rem;
  color: #fff;
  margin-bottom: 10px;
}
.soon p {
  max-width: 46ch;
  margin: 0 auto 22px;
  color: var(--muted-light);
  font-size: 0.96rem;
}
.soon form {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  max-width: 460px;
  margin: 0 auto;
}
.soon input[type='email'] {
  flex: 1;
  min-width: 220px;
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 11px;
  padding: 12px 14px;
  color: #fff;
  font-size: 0.95rem;
}
.soon input::placeholder {
  color: rgba(255, 255, 255, 0.32);
}
.soon input:focus {
  outline: none;
  border-color: var(--spring);
}

/* ── Comparison table ────────────────────────────────────────────────────── */
.cmp {
  margin-top: 44px;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: #fff;
}
.cmp table {
  width: 100%;
  border-collapse: collapse;
  min-width: 720px;
}
.cmp th,
.cmp td {
  padding: 15px 18px;
  text-align: left;
  border-bottom: 1px solid var(--line);
  font-size: 0.9rem;
  vertical-align: top;
}
.cmp thead th {
  background: var(--paper-2);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  position: sticky;
  top: 0;
}
.cmp thead th.is-us {
  background: var(--ink-2);
  color: #fff;
}
.cmp tbody th {
  font-weight: 700;
  color: var(--ink);
  width: 210px;
}
.cmp td {
  color: var(--muted);
}
.cmp td.is-us {
  background: rgba(99, 231, 127, 0.07);
  color: var(--ink);
  font-weight: 600;
}
.cmp tr:last-child th,
.cmp tr:last-child td {
  border-bottom: 0;
}

/* ── Module groups ───────────────────────────────────────────────────────── */
.group {
  margin-top: 60px;
}
.group__head {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 26px;
}
.group__head h3 {
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.9rem;
  color: var(--ink);
}
.group__head p {
  font-size: 0.9rem;
  color: var(--muted);
}
.group__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
  gap: 22px;
}
.feature h4 {
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 6px;
}
.feature p {
  font-size: 0.9rem;
  color: var(--muted);
  line-height: 1.58;
}

/* ── Stat strip ──────────────────────────────────────────────────────────── */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  margin-top: 44px;
}
.stat {
  background: #fff;
  padding: 26px 22px;
}
.stat b {
  display: block;
  font-family: var(--display);
  font-weight: 400;
  font-size: 2.4rem;
  line-height: 1;
  color: var(--teal);
}
.stat span {
  display: block;
  margin-top: 8px;
  font-size: 0.85rem;
  color: var(--muted);
}

/* ── Prose blocks on inner pages ─────────────────────────────────────────── */
.split {
  display: grid;
  /* minmax(0, 1fr), not 1fr. A 1fr track takes its minimum from its content,
     so one wide descendant — here the comparison table, which is deliberately
     720px and meant to scroll inside its own container — stops the column ever
     shrinking to the viewport, and the whole column overflows on a phone. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 60px;
  align-items: start;
  margin-top: 60px;
}
.split--tight {
  gap: 44px;
}
@media (max-width: 940px) {
  .split {
    grid-template-columns: minmax(0, 1fr);
    gap: 36px;
  }
}

.callout {
  border-left: 3px solid var(--spring);
  padding: 4px 0 4px 20px;
  margin: 26px 0;
}
.callout p {
  font-family: var(--display);
  font-size: 1.35rem;
  line-height: 1.35;
  color: var(--ink);
  max-width: 32ch;
}

/* ── Long-form pages (privacy, terms) ────────────────────────────────────── */
.doc {
  padding: 130px 0 90px;
  background: var(--paper);
}
.doc__wrap {
  max-width: 760px;
}
.doc h1 {
  max-width: none;
}
.doc__stamp {
  margin-top: 14px;
  font-size: 0.85rem;
  color: var(--muted);
}
.doc__draft {
  margin: 30px 0 8px;
  padding: 16px 18px;
  border-radius: 12px;
  background: #fff6e6;
  border: 1px solid #f0dcb4;
  font-size: 0.9rem;
  color: #6b5320;
  line-height: 1.6;
}
.doc h2 {
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.65rem;
  color: var(--ink);
  margin-top: 42px;
  margin-bottom: 10px;
}
.doc p,
.doc li {
  color: var(--muted);
  font-size: 0.98rem;
}
.doc p {
  margin-bottom: 14px;
}
.doc ul {
  margin: 0 0 18px;
  padding-left: 20px;
  display: grid;
  gap: 10px;
}
.doc a {
  color: var(--teal);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.doc strong {
  color: var(--ink);
}
.doc__back {
  margin-top: 52px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}

/* ── Reveal ──────────────────────────────────────────────────────────────── */
/* Only hidden when JavaScript is actually running. An earlier version hid these
   unconditionally, which meant a script error — or simply opening the file over
   file:// where module imports are blocked — rendered the whole page blank.
   Content must survive its own animation failing. */
.js .reveal {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 0.7s cubic-bezier(0.2, 0.8, 0.3, 1),
    transform 0.7s cubic-bezier(0.2, 0.8, 0.3, 1);
  transition-delay: var(--d, 0ms);
}
.reveal.is-in {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
  }
}

/* ── Responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 940px) {
  .layer__grid,
  .door__grid,
  .cta__grid {
    grid-template-columns: 1fr;
    gap: 44px;
  }
  .foot__inner {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 760px) {
  body {
    font-size: 16px;
  }
  .nav__inner {
    gap: 16px;
  }
  .hero {
    padding: 130px 0 84px;
  }
  .hero__facts {
    gap: 30px;
  }
  .hero__facts strong {
    font-size: 2rem;
  }
  .slip__body {
    grid-template-columns: 1fr;
  }
  .slip__col--sep {
    border-left: 0;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
  }
  .form__row {
    grid-template-columns: 1fr;
  }
  /* The card's own padding is the first thing to give: on a 390px screen it
     was taking 52px of the 350px available to the fields inside it. */
  .form {
    padding: 20px;
  }
  .done {
    padding: 30px 20px;
  }
  .foot__inner {
    grid-template-columns: 1fr;
    gap: 30px;
  }
  .gap,
  .slip,
  .layer,
  .mods,
  .door,
  .trust,
  .price,
  .faq,
  .cta {
    padding: 72px 0;
  }
}

/* ── Narrow phones ────────────────────────────────────────────────────────
   With the burger gone the header is three items in a row, so they have to
   fit unaided. At 360px the default sizes overflow by roughly 100px; this
   claws it back from padding rather than dropping "Sign in", which is the
   only route to the app from the marketing site. */
@media (max-width: 560px) {
  .nav__inner {
    gap: 10px;
  }
  .nav__logo {
    height: 25px;
  }
  .nav__links {
    gap: 14px;
    font-size: 0.84rem;
  }
  .nav__actions {
    gap: 4px;
  }
  /* The ghost button carries no background, so its padding is buying nothing
     here - it can read as a plain link and give the space back. */
  .nav__actions .btn--ghost {
    padding: 6px 4px;
    font-size: 0.84rem;
  }
  .nav__actions .btn--solid {
    padding: 9px 14px;
    font-size: 0.84rem;
  }

  .form {
    padding: 16px;
    border-radius: 16px;
  }
  .done {
    padding: 26px 16px;
  }
  .done__title {
    font-size: 1.6rem;
  }
  /* The dialling-code button and the number share a row down to here. Below
     it the number field is left with about 12 characters, so the code moves
     to its own line and the number gets the full width. */
  .tel {
    grid-template-columns: 1fr;
  }
  .dial__btn {
    width: 100%;
    justify-content: flex-start;
  }
  .dial__pop {
    width: 100%;
  }
  /* The code is transcribed digit by digit, so it keeps its size — but 0.42em
     of tracking on six digits overflows a narrow field. */
  .verify__field input {
    font-size: 1.3rem;
    letter-spacing: 0.24em;
  }
}

/* ── Responsive backstops ─────────────────────────────────────────────────
   Every known overflow is fixed at its source above. This is the guard for
   the ones nobody has found yet: on a marketing site a single stray element
   dragging the page sideways ruins every section, not just its own.

   clip rather than hidden - hidden on the body creates a scroll container,
   which would break position: sticky anywhere inside it. Fallback first for
   browsers without clip. */
html,
body {
  overflow-x: hidden;
}
@supports (overflow: clip) {
  html,
  body {
    overflow-x: clip;
  }
}

/* Nothing may be wider than its column. Long unbroken strings - an email
   address, a URL in a legal page - are the usual culprit. */
img,
svg,
video,
table {
  max-width: 100%;
}
p,
li,
h1,
h2,
h3,
h4 {
  overflow-wrap: break-word;
}

@media (max-width: 620px) {
  /* Side-by-side CTAs wrap to two ragged half-width buttons at this size.
     Stacked and full width they read as a deliberate pair and give a thumb
     something to actually hit. */
  .acts,
  .cta__acts,
  .hero__cta,
  .stage__cta {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .acts .btn,
  .cta__acts .btn,
  .hero__cta .btn,
  .stage__cta .btn {
    width: 100%;
  }
  /* btn--lg is 30px of horizontal padding on a 312px screen; the label needs
     that room more than the button does. */
  .btn--lg {
    padding: 14px 18px;
  }
}

/* ── Demo form: country picker, verification step ────────────────────────────
   Built here rather than pulled in: a select with 200 options is unusable, and
   a library for one field on one page is not worth the bytes. */

.opt {
  font-weight: 400;
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.4);
}

/* ── Select ────────────────────────────────────────────────────────────────
   The native arrow sits hard against the last character on Chrome and inside
   the border on Safari. Drawing our own means the gap can be chosen, and it
   is the same arrow as the dialling-code button below. */
.sel {
  position: relative;
  display: grid;
}
.sel select {
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  padding-right: 44px;
  cursor: pointer;
}
.sel__caret {
  position: absolute;
  right: 15px;
  top: 50%;
  transform: translateY(-50%);
  width: 12px;
  height: 8px;
  color: rgba(255, 255, 255, 0.5);
  pointer-events: none;
}

/* ── Phone ─────────────────────────────────────────────────────────────────
   Dialling code and number are one field wearing two controls. The code is a
   searchable button rather than a select, because a native dropdown of 230
   dialling codes can be scrolled but not searched. */
.tel {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 8px;
}
.dial {
  position: relative;
}
.dial__btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 100%;
  /* Room on the right for the caret, which is positioned against .dial so it
     lands in the same place whether the button is auto or full width. */
  padding: 11px 36px 11px 13px;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 11px;
  color: #fff;
  font: inherit;
  font-size: 1rem;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition:
    border-color 0.18s,
    background 0.18s;
}
.dial__btn:hover,
.dial__btn[aria-expanded='true'] {
  border-color: rgba(255, 255, 255, 0.3);
  background: rgba(0, 0, 0, 0.32);
}
.dial__btn:focus-visible {
  outline: none;
  border-color: var(--spring);
}
.dial__flag {
  font-size: 1.1rem;
  line-height: 1;
}
.dial__code {
  font-variant-numeric: tabular-nums;
}
.dial__pop {
  position: absolute;
  z-index: 30;
  top: calc(100% + 6px);
  left: 0;
  /* Never wider than the phone it is on. */
  width: min(330px, 80vw);
  display: grid;
  gap: 6px;
  padding: 8px;
  background: #0d3a35;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 12px;
  box-shadow: 0 20px 44px -20px rgba(0, 0, 0, 0.7);
}

.pick {
  position: relative;
  display: grid;
  gap: 6px;
}
.pick__label {
  font-size: 0.82rem;
  color: rgba(255, 255, 255, 0.72);
}

/* Chips sit above the input rather than inside it: inside, a long list pushes
   the caret around and the field stops behaving like a text box. */
.pick__chips:not(:empty) {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 2px;
}
.pick__chips .chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 6px 3px 10px;
  border-radius: 999px;
  background: rgba(99, 231, 127, 0.16);
  border: 1px solid rgba(99, 231, 127, 0.3);
  color: #fff;
  font-size: 0.8rem;
}
.pick__chips .chip__name {
  max-width: 22ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pick__chips .chip button {
  border: 0;
  background: none;
  color: rgba(255, 255, 255, 0.6);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  /* A 24px target: the × glyph alone is about 8px, which is not a thing a
     thumb can reliably hit. */
  min-width: 24px;
  min-height: 24px;
  display: grid;
  place-items: center;
  padding: 0;
}
.pick__chips .chip button:hover {
  color: #fff;
}

.pick__input {
  width: 100%;
}

.pick__list {
  position: absolute;
  z-index: 20;
  top: 100%;
  left: 0;
  right: 0;
  margin: 4px 0 0;
  padding: 4px;
  list-style: none;
  max-height: 216px;
  overflow-y: auto;
  background: #0d3a35;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 10px;
  box-shadow: 0 20px 44px -20px rgba(0, 0, 0, 0.7);
}
/* Inside the dialling-code popover the list is already in a panel, so it drops
   the panel of its own and just scrolls. */
.pick__list--inline {
  position: static;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  max-height: 244px;
}
.pick__list li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 7px;
  font-size: 0.88rem;
  color: rgba(255, 255, 255, 0.82);
  cursor: pointer;
}
.pick__list li:not(.pick__none):hover,
.pick__list li.is-active {
  background: rgba(99, 231, 127, 0.16);
  color: #fff;
}
/* Flags are emoji, not images: nothing to download, nothing to 404, and a
   platform without a flag font falls back to the two letters, which is a
   reasonable thing to see. */
.pick__flag {
  font-size: 1.1rem;
  line-height: 1;
}
/* Country names run long — "United States Minor Outlying Islands". Truncate
   rather than wrap, so every row stays one line high. */
.pick__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pick__dial {
  color: rgba(255, 255, 255, 0.48);
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}
.pick__list .pick__none {
  padding: 10px;
  font-size: 0.85rem;
  color: rgba(255, 255, 255, 0.5);
  cursor: default;
}

/* ── Verification step ───────────────────────────────────────────────────── */
.verify__lead {
  font-size: 0.92rem;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.74);
  margin: 0;
}
.verify__lead b {
  color: #fff;
}

/* Wide tracking and a big size: a code is transcribed digit by digit, so the
   digits need to be individually legible rather than merely readable. */
.verify__field input {
  font-size: 1.5rem;
  letter-spacing: 0.42em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.verify__acts {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  justify-content: center;
}
.linkish {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 0.84rem;
  color: var(--spring);
  cursor: pointer;
}
.linkish:hover:not(:disabled) {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.linkish:disabled {
  color: rgba(255, 255, 255, 0.34);
  cursor: default;
}

/* ── Done ──────────────────────────────────────────────────────────────────
   The last thing they see, so it gets a moment rather than a one-line "thanks":
   confirmation of what happened, what happens next, and the one page worth
   reading while they wait. */
.done {
  text-align: center;
  padding: 34px 26px;
}
.done__tick {
  width: 52px;
  height: 52px;
  margin: 0 auto 16px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(99, 231, 127, 0.18);
  color: var(--spring);
}
.done__tick svg {
  width: 24px;
  height: 24px;
  /* Drawn on arrival — the tick is the whole point of the screen. */
  stroke-dasharray: 30;
  stroke-dashoffset: 30;
  animation: tick 0.5s cubic-bezier(0.65, 0, 0.35, 1) 0.12s forwards;
}
@keyframes tick {
  to {
    stroke-dashoffset: 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .done__tick svg {
    animation: none;
    stroke-dashoffset: 0;
  }
}
.done__title {
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.9rem;
  color: #fff;
  margin: 0 0 10px;
}
.done__text {
  font-size: 0.94rem;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.72);
  margin: 0 auto;
  max-width: 42ch;
}
.done__text b {
  color: #fff;
  font-weight: 600;
}
.done__next {
  margin: 18px auto 0;
  padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  max-width: 42ch;
  font-size: 0.88rem;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.58);
}

/* ===========================================================================
   The plan comparison table.
   ---------------------------------------------------------------------------
   Built by pricing.js from the catalogue, so nothing here assumes how many
   plans or rows there are. It sits inside a .layer band, which is --paper-2,
   so the table itself is --paper to lift off it.

   The first column is a <th scope="row"> rather than a <td>: a comparison
   table is read across, and a screen reader announcing the capability before
   each tick is the difference between it being usable and being noise.
   =========================================================================== */
.cmp__scroll {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--paper);
}
/* Scoped to a table. This block was written for a later markup pattern,
   .cmp__scroll > table.cmp, which no page ever shipped. Unscoped, its
   min-width landed on the div.cmp that the pricing and compare pages do use
   as their horizontal scroll container, so the container could not shrink to
   the viewport, never scrolled, and the table was clipped out of reach. */
table.cmp {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  font-size: 15px;
}
.cmp thead th {
  padding: 18px 14px;
  text-align: center;
  border-bottom: 1px solid var(--line);
  vertical-align: bottom;
}
.cmp thead th:first-child {
  text-align: left;
  width: 44%;
  font-size: 12px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.cmp__plan {
  display: block;
  font-family: var(--display);
  font-size: 21px;
  line-height: 1.1;
  color: var(--graphite);
}
.cmp__rate {
  display: block;
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.cmp__group th {
  padding: 13px 14px 9px;
  text-align: left;
  background: var(--paper-2);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}
.cmp tbody th[scope='row'] {
  padding: 13px 14px;
  text-align: left;
  font-weight: 500;
  border-top: 1px solid var(--line);
}
.cmp tbody td {
  padding: 13px 14px;
  text-align: center;
  border-top: 1px solid var(--line);
}
.cmp__feat {
  display: block;
  color: var(--graphite);
}
.cmp__blurb {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  line-height: 1.45;
  font-weight: 400;
  color: var(--muted);
}
.cmp__yes {
  color: var(--teal);
  font-weight: 700;
  font-size: 17px;
}
.cmp__no {
  color: var(--muted);
  opacity: 0.4;
}
.cmp tbody tr:hover th[scope='row'],
.cmp tbody tr:hover td {
  background: rgba(20, 112, 106, 0.04);
}
.cmp tbody tr.cmp__group:hover th {
  background: var(--paper-2);
}

@media (max-width: 640px) {
  .cmp thead th:first-child {
    width: 50%;
  }
  .cmp__plan {
    font-size: 17px;
  }
}

/* ===========================================================================
   Floating actions — WhatsApp, and back to top.
   ---------------------------------------------------------------------------
   Injected by site.js so both appear on every page. Bottom-right, stacked,
   and deliberately quiet: they sit over the content for the whole visit, so
   anything that pulses or bounces becomes irritating by the second scroll.
   =========================================================================== */
.fab {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.fab__btn {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border: none;
  border-radius: 999px;
  cursor: pointer;
  transition:
    transform 0.2s cubic-bezier(0.2, 0.8, 0.3, 1),
    box-shadow 0.2s,
    opacity 0.2s;
}
.fab__btn:hover {
  transform: translateY(-2px);
}
.fab__btn:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 3px;
}
.fab__btn[hidden] {
  display: none;
}

/* WhatsApp's own green, because a recoloured WhatsApp button reads as a
   generic chat widget and loses the recognition that makes it worth having. */
.fab__btn--chat {
  background: #25d366;
  color: #fff;
  box-shadow: 0 10px 24px -10px rgba(37, 211, 102, 0.75);
}
.fab__btn--chat:hover {
  box-shadow: 0 16px 30px -12px rgba(37, 211, 102, 0.85);
}

.fab__btn--top {
  background: #fff;
  color: var(--graphite);
  border: 1px solid var(--line);
  box-shadow: 0 10px 24px -14px rgba(4, 35, 31, 0.45);
  animation: fab-in 0.22s ease-out;
}
@keyframes fab-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .fab__btn {
    transition: none;
    animation: none;
  }
  .fab__btn:hover {
    transform: none;
  }
}

@media (max-width: 640px) {
  .fab {
    right: 14px;
    bottom: 14px;
  }
  .fab__btn {
    width: 42px;
    height: 42px;
  }
}

/* ── Products menu ───────────────────────────────────────────────────────────
   There is no longer a single page that lists everything, so the trigger is a
   button rather than a link. It opens on hover and on focus in CSS alone,
   which means it works with JavaScript switched off and on a touch screen,
   where a tap focuses the button. JavaScript only adds the niceties: the
   aria state, Escape, and closing when you click elsewhere.

   Icons are CSS masks rather than inline SVG because this markup is repeated
   in twelve HTML files; keeping the paths here means one place to change them
   and twelve pages that stay small. */
.menu {
  position: relative;
  display: flex;
  align-items: center;
}
.menu__btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: rgba(255, 255, 255, 0.78);
  transition: color 0.18s;
}
.menu__btn {
  /* It is a button; it should not look like one. */
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  cursor: pointer;
}
.menu__btn:hover,
.menu:focus-within .menu__btn,
.menu.is-open .menu__btn {
  color: var(--spring);
}
@media (hover: hover) and (pointer: fine) {
  .menu:hover .menu__btn {
    color: var(--spring);
  }
}
.menu__caret {
  width: 10px;
  height: 7px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.26s cubic-bezier(0.2, 0.8, 0.3, 1);
}
.menu:focus-within .menu__caret,
.menu.is-open .menu__caret {
  transform: rotate(180deg);
}
@media (hover: hover) and (pointer: fine) {
  .menu:hover .menu__caret {
    transform: rotate(180deg);
  }
}

.menu__panel {
  position: absolute;
  top: calc(100% + 18px);
  left: 50%;
  width: 620px;
  padding: 12px;
  border-radius: 20px;
  /* Nearly opaque, not glass. A translucent panel reads fine over the dark
     hero and becomes unreadable the moment it opens over a paper section —
     and the blur that was meant to rescue it is the first thing a browser
     drops when it cannot composite. The tint still picks up the brand. */
  background: rgba(6, 36, 32, 0.975);
  backdrop-filter: blur(22px) saturate(170%);
  -webkit-backdrop-filter: blur(22px) saturate(170%);
  border: 1px solid rgba(255, 255, 255, 0.13);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.08) inset,
    0 30px 70px -26px rgba(0, 0, 0, 0.7);
  /* Closed state. visibility (not display) so the panel can animate, and so
     the links inside leave the tab order while it is shut. */
  visibility: hidden;
  opacity: 0;
  transform: translate(-50%, -10px) scale(0.985);
  transform-origin: top center;
  transition:
    opacity 0.24s cubic-bezier(0.2, 0.8, 0.3, 1),
    transform 0.24s cubic-bezier(0.2, 0.8, 0.3, 1),
    visibility 0s linear 0.24s;
}
.menu:focus-within .menu__panel,
.menu.is-open .menu__panel {
  visibility: visible;
  opacity: 1;
  transform: translate(-50%, 0) scale(1);
  transition-delay: 0s, 0s, 0s;
}
/* Hover opens it, but only where there is a real pointer. On a touch screen a
   tap fires mouseenter too, which would open the panel and let the click that
   follows immediately toggle it shut again. */
@media (hover: hover) and (pointer: fine) {
  .menu:hover .menu__panel {
    visibility: visible;
    opacity: 1;
    transform: translate(-50%, 0) scale(1);
    transition-delay: 0s, 0s, 0s;
  }
  .menu:hover .menu__item {
    animation: menu-item-in 0.3s cubic-bezier(0.2, 0.8, 0.3, 1) forwards;
    animation-delay: calc(60ms + var(--i) * 34ms);
  }
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .menu__panel {
    background: rgb(6, 36, 32);
  }
}

/* The hover bridge. Without it the 18px gap between the pill and the panel is
   dead ground, and the menu closes while the pointer is crossing it. */
.menu__panel::before {
  content: '';
  position: absolute;
  inset: -20px 0 100% 0;
}

.menu__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
}
.menu__item {
  display: grid;
  grid-template-columns: 34px 1fr;
  gap: 13px;
  align-items: start;
  padding: 12px 13px;
  border-radius: 13px;
  transition: background 0.18s;
}
.menu__item:hover,
.menu__item:focus-visible {
  background: rgba(255, 255, 255, 0.07);
}
.menu__ico {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.09);
  transition:
    background 0.18s,
    border-color 0.18s;
}
.menu__item:hover .menu__ico {
  background: rgba(99, 231, 127, 0.16);
  border-color: rgba(99, 231, 127, 0.4);
}
.menu__ico::before {
  content: '';
  width: 18px;
  height: 18px;
  background-color: var(--spring);
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}
.menu__item b {
  display: block;
  font-size: 0.88rem;
  font-weight: 600;
  color: #fff;
  line-height: 1.3;
}
.menu__item i {
  display: block;
  margin-top: 3px;
  font-style: normal;
  font-size: 0.78rem;
  font-weight: 400;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.55);
}

/* Each item arrives a beat after the one before it, but only on the way in —
   closing all at once reads as dismissal, which is what it is. */
.menu__item {
  opacity: 0;
  transform: translateY(6px);
}
.menu:focus-within .menu__item,
.menu.is-open .menu__item {
  animation: menu-item-in 0.3s cubic-bezier(0.2, 0.8, 0.3, 1) forwards;
  animation-delay: calc(60ms + var(--i) * 34ms);
}
@keyframes menu-item-in {
  to {
    opacity: 1;
    transform: none;
  }
}

.menu__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: 10px;
  padding: 13px 13px 4px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 0.8rem;
}
.menu__foot a {
  color: rgba(255, 255, 255, 0.6);
  transition: color 0.18s;
}
.menu__foot a:hover {
  color: var(--spring);
}
.menu__foot strong {
  color: var(--spring);
  font-weight: 600;
}

.menu__ico--leave {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2.5'/%3E%3Cpath d='M8 2.5v4M16 2.5v4M3 10h18M9 15.5l2 2 4-4.5'/%3E%3C/svg%3E");
}
.menu__ico--time {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 6.8V12l3.6 2.1'/%3E%3C/svg%3E");
}
.menu__ico--payroll {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 2.5h12v19l-3-2-3 2-3-2-3 2z'/%3E%3Cpath d='M9.5 8h5M9.5 12h5'/%3E%3C/svg%3E");
}
.menu__ico--performance {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='8.6'/%3E%3Ccircle cx='12' cy='12' r='4.4'/%3E%3Ccircle cx='12' cy='12' r='.9'/%3E%3C/svg%3E");
}
.menu__ico--hiring {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9.5' cy='8' r='3.6'/%3E%3Cpath d='M3 20c0-3.5 2.9-5.6 6.5-5.6'/%3E%3Cpath d='M17 12.5v7M13.5 16h7'/%3E%3C/svg%3E");
}
.menu__ico--analytics {
  --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 20.5h18'/%3E%3Cpath d='M6 20.5V12M11 20.5V5.5M16 20.5v-6M20.5 20.5V9'/%3E%3C/svg%3E");
}

/* The products panel is a desktop dropdown only. Below this width the whole
   header collapses into a drawer instead - see the burger and drawer rules
   at the end of this file. */
@media (max-width: 860px) {
  .menu__panel {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .menu__panel,
  .menu__caret {
    transition: none;
  }
  .menu__item {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* ── Closing split ───────────────────────────────────────────────────────────
   The old closer was a centred heading, a centred paragraph and centred
   buttons on a flat gradient — the same shape at the bottom of every page, and
   the weakest thing on any of them. This answers the page's last open question
   instead, with the ask on one side and a straight answer on the other. */
.close__grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 0.92fr;
  gap: 64px;
  align-items: center;
}
.close__grid .h2 {
  max-width: 14ch;
}
.close__lede {
  max-width: 46ch;
  margin: 0;
  font-size: 1rem;
  line-height: 1.62;
  color: var(--muted-light);
}
.close__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 30px;
}

.kit {
  padding: 8px 26px 22px;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: 0 30px 70px -34px rgba(0, 0, 0, 0.6);
}
.kit__ttl {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 18px 0 4px;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
}
.kit__row {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 14px;
  align-items: start;
  padding: 15px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.kit__row svg {
  width: 20px;
  height: 20px;
  margin-top: 1px;
  color: var(--spring);
}
.kit__row--ask svg {
  color: rgba(255, 255, 255, 0.4);
}
.kit__row b {
  display: block;
  font-size: 0.92rem;
  color: #fff;
}
.kit__row span {
  display: block;
  margin-top: 3px;
  font-size: 0.83rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.55);
}

@media (max-width: 940px) {
  .close__grid {
    grid-template-columns: 1fr;
    gap: 40px;
  }
  .close__grid .h2 {
    max-width: 18ch;
  }
}

/* ── Split page hero ─────────────────────────────────────────────────────────
   Shared by the feature pages: the claim on one side, the product doing the
   thing on the other. Lives here rather than in a page stylesheet because
   more than one page needs it. */
.phero--split {
  padding: 132px 0 86px;
}
.phero__grid {
  position: relative;
  display: grid;
  grid-template-columns: 1.04fr 0.96fr;
  gap: 56px;
  align-items: center;
}
.phero--split h1 {
  max-width: 15ch;
}
.phero--split p {
  max-width: 47ch;
}

/* The feed is seeded with five rows and then replaces its oldest, so it never
   changes height once it is on screen. */
.feed__cap {
  margin: 14px 0 0;
  font-size: 0.76rem;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.45);
}
.feed__cap b {
  color: rgba(255, 255, 255, 0.72);
  font-weight: 600;
}

@media (max-width: 940px) {
  .phero--split {
    padding: 120px 0 72px;
  }
  .phero__grid {
    grid-template-columns: 1fr;
    gap: 40px;
  }
}

/* ── Figures strip: a note under the numbers ─────────────────────────────── */
.figures__as {
  margin: 26px 0 0;
  font-size: 0.74rem;
  color: var(--muted);
}

/* ── Section lede ────────────────────────────────────────────────────────────
   The paragraph under a section heading. It was defined inside one page's
   stylesheet and then used on three pages, so on two of them it was silently
   rendering as an unstyled full-width paragraph. */
.lede {
  max-width: 58ch;
  margin: 0 0 40px;
  font-size: 1rem;
  line-height: 1.62;
  color: var(--muted);
}
.slip .lede,
.cta .lede {
  color: var(--muted-light);
}

/* ── Seeded stat cards ───────────────────────────────────────────────────────
   Three dark cards of label-and-figure rows, for a dark section. Used by the
   leave page for statutory entitlements and by the case study for what going
   first actually cost us. */
.seed__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin-top: 46px;
}
.seed {
  padding: 22px 24px;
  border-radius: var(--r);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.seed__where {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--spring);
  margin-bottom: 14px;
}
.seed__line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 0.84rem;
  color: rgba(255, 255, 255, 0.62);
}
.seed__line b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.9rem;
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
}
.seed__line:first-of-type {
  border-top: 0;
}

@media (max-width: 900px) {
  .seed__grid {
    grid-template-columns: 1fr;
  }
}

.seed__note {
  margin: 12px 0 0;
  font-size: 0.8rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.55);
}

/* ── Header fit on a phone ───────────────────────────────────────────────────
   The header is three groups on one row with no burger, and below 560px they
   stopped fitting: the brand was being squeezed to zero width and the demo
   button ran off the right edge. A fixed-position header can overflow the
   viewport without changing the document's scroll width, so nothing caught it.

   Pricing and Customers come out of the row first — both are in the products
   panel footer and in the page footer, while the Products control is the only
   thing in the header that reaches all six product pages. */
@media (max-width: 560px) {
  .nav__links > a {
    display: none;
  }
}
@media (max-width: 420px) {
  .nav__logo {
    height: 22px;
  }
  /* "Book a demo" becomes "Book". The destination is unchanged. */
  .btn__long {
    display: none;
  }
}

/* ── Burger and drawer ───────────────────────────────────────────────────────
   Below 860px the header collapses to a logo and a burger, and everything it
   held slides in from the left. The drawer is built by site.js from the nav
   that is already in the markup, so there is one list of products in the HTML
   rather than a desktop copy and a mobile copy that drift apart.

   All of it is gated on .js, which the inline bootstrap script sets. With
   JavaScript off the header keeps the links it always had, so the site never
   ends up with a burger that cannot open.
   =========================================================================== */

.burger {
  display: none;
  position: relative;
  width: 42px;
  height: 42px;
  margin-left: auto;
  padding: 0;
  border: 0;
  border-radius: 12px;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.burger i {
  position: absolute;
  left: 11px;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: #fff;
  transition:
    transform 0.34s cubic-bezier(0.5, -0.4, 0.4, 1.4),
    opacity 0.18s ease;
}
.burger i:nth-child(1) {
  top: 14px;
}
.burger i:nth-child(2) {
  top: 20px;
}
.burger i:nth-child(3) {
  top: 26px;
}
/* Into a cross: the outer bars meet in the middle and cross, the middle one
   goes. The translate has to come before the rotate or they arrive bent. */
.burger.is-on i:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.burger.is-on i:nth-child(2) {
  opacity: 0;
  transform: scaleX(0.4);
}
.burger.is-on i:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

.drawer {
  position: fixed;
  inset: 0;
  z-index: 200;
  visibility: hidden;
  transition: visibility 0s linear 0.42s;
}
.drawer.is-open {
  visibility: visible;
  transition-delay: 0s;
}
.drawer__veil {
  position: absolute;
  inset: 0;
  width: 100%;
  border: 0;
  padding: 0;
  background: rgba(2, 18, 16, 0.58);
  opacity: 0;
  cursor: pointer;
  transition: opacity 0.38s ease;
}
.drawer.is-open .drawer__veil {
  opacity: 1;
}

.drawer__panel {
  position: absolute;
  inset: 0 auto 0 0;
  width: min(318px, 82vw);
  display: flex;
  flex-direction: column;
  padding: 18px 20px 24px;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  background: linear-gradient(170deg, #06302a 0%, #04231f 100%);
  border-right: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: 30px 0 70px -30px rgba(0, 0, 0, 0.7);
  transform: translateX(-100%);
  transition: transform 0.42s cubic-bezier(0.3, 0.9, 0.3, 1);
}
.drawer.is-open .drawer__panel {
  transform: none;
}

.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 18px;
  margin-bottom: 6px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.drawer__head img {
  height: 26px;
  width: auto;
}
.drawer__close {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.07);
  color: rgba(255, 255, 255, 0.7);
  cursor: pointer;
}
.drawer__close svg {
  width: 17px;
  height: 17px;
}

.drawer__label {
  margin: 16px 0 6px;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.38);
}

.drawer__item {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 13px;
  align-items: center;
  padding: 12px 10px;
  margin: 0 -10px;
  border-radius: 12px;
  transition: background 0.18s;
}
.drawer__item:active {
  background: rgba(255, 255, 255, 0.07);
}
.drawer__item .menu__ico {
  width: 30px;
  height: 30px;
  border-radius: 9px;
}
.drawer__item .menu__ico::before {
  width: 16px;
  height: 16px;
}
.drawer__item b {
  font-size: 0.92rem;
  font-weight: 600;
  color: #fff;
}
.drawer__plain {
  display: block;
  padding: 12px 10px;
  margin: 0 -10px;
  border-radius: 12px;
  font-size: 0.95rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.82);
}

.drawer__actions {
  display: grid;
  gap: 10px;
  margin-top: auto;
  padding-top: 22px;
}
.drawer__actions .btn {
  width: 100%;
  justify-content: center;
}

/* Each row arrives a beat after the one above it, once the panel itself has
   started moving. Only on the way in. */
.drawer__item,
.drawer__plain,
.drawer__actions {
  opacity: 0;
  transform: translateX(-10px);
}
.drawer.is-open .drawer__item,
.drawer.is-open .drawer__plain,
.drawer.is-open .drawer__actions {
  animation: drawer-row 0.36s cubic-bezier(0.2, 0.8, 0.3, 1) forwards;
  animation-delay: calc(130ms + var(--i, 0) * 38ms);
}
@keyframes drawer-row {
  to {
    opacity: 1;
    transform: none;
  }
}

/* Keyed on .has-drawer, which site.js sets only once the burger is in the
   page — not on .js, which is true the moment the document loads. If the
   script fails for any reason, the header keeps the links it always had
   rather than hiding them for a burger that never arrived. */
@media (max-width: 860px) {
  .has-drawer .nav__links,
  .has-drawer .nav__actions {
    display: none;
  }
  .has-drawer .burger {
    display: block;
  }
}
@media (min-width: 861px) {
  .drawer {
    display: none;
  }
}

body.is-drawer-open {
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .burger i,
  .drawer,
  .drawer__veil,
  .drawer__panel {
    transition: none;
  }
  .drawer__item,
  .drawer__plain,
  .drawer__actions {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* ── Header on a phone ───────────────────────────────────────────────────────
   The bar carries 16px of its own padding so the glass pill insets from the
   edges when it sticks, and .wrap adds 24px on top — which left the logo 40px
   in while the page content started at 24px. Inside the bar the wrap gives
   back what the bar already spent, so the two line up.

   The logo also shrank twice on the way down, to fit a header that had to hold
   five items. It holds two now, so it can have its size back. */
@media (max-width: 860px) {
  .has-drawer .nav__inner {
    padding-inline: 8px;
  }
  .has-drawer .nav__logo {
    height: 30px;
  }
}

/* hero.css */
/* ===========================================================================
   Hero stage.
   ---------------------------------------------------------------------------
   The brief the rest of the site failed: not another dark gradient with two
   blurred circles behind it. The background here is a ledger — ruled lines and
   a faint column grid, drifting — because the subject is arithmetic about
   money, and a ledger is what that has always looked like.

   The payslip sits in real perspective with layered depth. Everything is
   transforms and a couple of keyframes; there is no library and no canvas.
   =========================================================================== */

.stage {
  position: relative;
  isolation: isolate;
  background: #04231f;
  color: #fff;
  padding: 132px 0 0;
  overflow: hidden;
  --mx: 70%;
  --my: 30%;
}

/* ── Ruled ledger, drifting ─────────────────────────────────────────────── */
.stage__rule {
  position: absolute;
  inset: -60px 0;
  z-index: 0;
  background-image:
    repeating-linear-gradient(to bottom, rgba(255, 255, 255, 0.055) 0 1px, transparent 1px 46px),
    repeating-linear-gradient(to right, rgba(255, 255, 255, 0.035) 0 1px, transparent 1px 120px);
  animation: ledger 26s linear infinite;
  mask-image: radial-gradient(120% 90% at 60% 20%, #000 30%, transparent 78%);
}
@keyframes ledger {
  to {
    transform: translateY(46px);
  }
}

/* A single warm pool of light that follows the cursor. One light source reads
   as a lit room; three blurred circles read as a template. */
.stage__spot {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    620px circle at var(--mx) var(--my),
    rgba(99, 231, 127, 0.16),
    transparent 62%
  );
  transition: background 0.5s ease-out;
}

.stage__wash {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(165deg, transparent 40%, rgba(0, 71, 66, 0.75) 100%),
    linear-gradient(to bottom, rgba(4, 35, 31, 0.2), transparent 30%);
}

.stage__inner {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1.02fr 1fr;
  gap: 48px;
  align-items: center;
  padding-bottom: 92px;
}

/* ── Copy ────────────────────────────────────────────────────────────────── */

/* A plain category label rather than a badge. The deck animating beside it
   already says the product is live; a "LIVE" pill was saying it twice. */
.stage__eyebrow {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--spring);
  margin-bottom: 24px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.stage__eyebrow::after {
  content: '';
  flex: 1;
  max-width: 68px;
  height: 1px;
  background: linear-gradient(to right, rgba(99, 231, 127, 0.55), transparent);
}

.stage__kicker {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 6px 14px 6px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.78);
  margin-bottom: 26px;
}
.stage__kicker b {
  background: var(--spring);
  color: var(--ink);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 999px;
}

/* Two lines, always, and it must not wrap past them or the hero gets
   top-heavy. The sizes below are measured rather than chosen: the longest line
   is "Your people. Your business." at 18.6ch in Instrument Serif with this
   tracking, and the copy column is 572px at the 1180px wrap. 4.1rem puts that
   line at 559px, inside the column, so it holds one line; 4.8rem put it at
   655px and broke it in two. The 2.2rem floor is the same sum for a 360px
   phone. Changing the words means measuring again. */
.stage h1 {
  font-family: var(--display);
  font-weight: 400;
  /* 3.9rem rather than 4.1: at 4.1 the first line measured 560px against a
     572px column, which held in theory and broke in practice the moment a
     fallback face rendered a shade wider. 3.9 puts it at 533px, and the nowrap
     below makes one line a guarantee rather than an outcome. */
  font-size: clamp(2.2rem, 5vw, 3.9rem);
  line-height: 0.98;
  letter-spacing: -0.03em;
  max-width: 19ch;
}
/* Each sentence holds its own line. Released below 620px, where the viewport
   is narrower than the words and wrapping is the only honest option. */
.stage h1 .h1__line {
  white-space: nowrap;
}
.stage h1 em {
  font-style: italic;
  color: var(--spring);
  position: relative;
  white-space: nowrap;
}
/* Hand-drawn underline rather than a border: the wobble is the point. */
.stage h1 em::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.06em;
  height: 0.14em;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 12' preserveAspectRatio='none'%3E%3Cpath d='M2 8.5C36 3.5 78 2.5 118 5.5c26 2 54 3 80 1.5' stroke='%2363E77F' stroke-width='3.4' fill='none' stroke-linecap='round' opacity='.55'/%3E%3C/svg%3E")
    no-repeat center / 100% 100%;
  animation: draw 1.1s 0.5s cubic-bezier(0.2, 0.8, 0.3, 1) both;
}
@keyframes draw {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}

.stage__lede {
  margin-top: 24px;
  max-width: 48ch;
  font-size: 1.05rem;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.62);
}
.stage__lede strong {
  color: #fff;
  font-weight: 600;
}

.stage__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 34px;
}

/* ── The rig ─────────────────────────────────────────────────────────────── */
.stage__viz {
  position: relative;
  min-height: 480px;
  display: grid;
  place-items: center;
  /* Room on the right for the mascot to clear the deck. */
  padding-right: 46px;
}

/* The rig is wider than the payslip on purpose: the extra 150px on the left is
   a gutter for the satellite cards, so they sit beside the payslip instead of
   on top of its text. They overlap its edge by a few pixels — enough to read as
   layered, not enough to cover a number. */
.rig {
  position: relative;
  width: min(430px, 100%);
  transform: perspective(1400px) rotateY(-14deg) rotateX(6deg);
  transform-style: preserve-3d;
  will-change: transform;
  animation: rig-in 1s cubic-bezier(0.2, 0.8, 0.3, 1) both;
}
@keyframes rig-in {
  from {
    opacity: 0;
    transform: perspective(1400px) rotateY(-26deg) rotateX(12deg) translateY(30px);
  }
}

/* Layers sit at different depths so the parallax actually separates them. */
.slab {
  border-radius: 20px;
  background: linear-gradient(168deg, #0d3d38, #072c28);
  border: 1px solid rgba(255, 255, 255, 0.13);
  box-shadow:
    0 40px 90px -30px rgba(0, 0, 0, 0.75),
    0 0 0 1px rgba(255, 255, 255, 0.03) inset;
}

.slab--ghost {
  position: absolute;
  inset: 26px -32px -26px 32px;
  transform: translateZ(-70px);
  opacity: 0.5;
  background: linear-gradient(168deg, #0a332f, #061f1c);
}

/* No backdrop-filter here. It creates a stacking context, which flattens the
   parent's preserve-3d in every browser — so translateZ stopped ordering the
   satellite cards and the payslip painted over them. */
.slab--main {
  position: relative;
  padding: 20px;
  transform: translateZ(0);
}

.rig__top {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
}
.rig__code {
  font-family: var(--mono);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  padding: 5px 9px;
  border-radius: 7px;
  background: rgba(99, 231, 127, 0.14);
  color: var(--spring);
  border: 1px solid rgba(99, 231, 127, 0.28);
}
.rig__name {
  font-size: 0.86rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.8);
}
.rig__period {
  margin-left: auto;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.32);
}

.rig__gross {
  padding: 20px 0 16px;
}
.rig__gross span {
  display: block;
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.38);
  margin-bottom: 4px;
}
.rig__gross b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 2.05rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: #fff;
}

.rig__rows {
  display: grid;
  gap: 2px;
  min-height: 132px;
}
.rig__row {
  display: grid;
  grid-template-columns: 1fr 44px auto;
  align-items: center;
  gap: 12px;
  padding: 7px 0;
  font-size: 0.82rem;
  opacity: 1;
  transform: none;
  transition:
    opacity 0.34s ease,
    transform 0.34s cubic-bezier(0.2, 0.8, 0.3, 1);
}
.rig__row.is-in {
  opacity: 0;
  transform: translateX(18px);
}
.rig__row.is-out {
  opacity: 0;
  transform: translateX(-14px);
}
.rig__label {
  color: rgba(255, 255, 255, 0.62);
}
.rig__bar {
  height: 4px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}
.rig__bar i {
  display: block;
  height: 100%;
  width: var(--w);
  border-radius: 3px;
  background: linear-gradient(90deg, rgba(255, 180, 168, 0.5), #ffb4a8);
  animation: bar 0.7s 0.15s cubic-bezier(0.2, 0.8, 0.3, 1) both;
}
@keyframes bar {
  from {
    width: 0;
  }
}
.rig__amt {
  color: #ffb4a8;
  font-size: 0.8rem;
  white-space: nowrap;
}

/* Net pay floats in front of the card. This is the number the whole page is
   about, so it gets the depth and the light. */
.rig__net {
  position: relative;
  margin-top: 16px;
  padding: 15px 18px;
  border-radius: 14px;
  background: linear-gradient(135deg, rgba(99, 231, 127, 0.2), rgba(99, 231, 127, 0.07));
  border: 1px solid rgba(99, 231, 127, 0.36);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  transform: translateZ(46px);
  box-shadow: 0 22px 40px -18px rgba(99, 231, 127, 0.42);
}
.rig__net span {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--spring);
}
.rig__net b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--spring);
}

.rig__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: auto;
  padding-top: 14px;
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.38);
}
.rig__foot b {
  font-family: var(--mono);
  color: rgba(255, 255, 255, 0.72);
  font-weight: 500;
}

/* Cost tag pinned to the ghost slab behind, to show it is a separate thing. */
.rig__tag {
  position: absolute;
  right: -26px;
  bottom: -18px;
  transform: translateZ(-40px);
  background: #0a332f;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 12px;
  padding: 10px 14px;
  box-shadow: 0 20px 40px -20px rgba(0, 0, 0, 0.8);
}
.rig__tag span {
  display: block;
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.36);
}
.rig__tag b {
  font-family: var(--mono);
  font-size: 0.98rem;
  color: #fff;
  font-weight: 500;
}

/* ── Mascot ──────────────────────────────────────────────────────────────
   Sits behind the deck, one shoulder and the head clearing its edge, so it
   reads as looking over the product rather than standing beside it.

   Background image, not <img>: a missing file then renders as nothing instead
   of a broken-image icon, and the hero survives a bad deploy. */
.mascot {
  position: absolute;
  right: -10px;
  bottom: 10px;
  width: 108px;
  height: 170px;
  /* In front of the rig, not behind it. .slab--ghost is a half-opacity card
     offset 32px further right than the main slab, so a mascot underneath it
     got a dark green wash over whichever part it covered - the toy came out
     bisected down the ghost's edge. Sitting in front reads as a plush leaning
     on the corner of the card, which is the look anyway. */
  z-index: 1;
  background: url('../img/meet-trabbly-01.png') no-repeat center bottom / contain;
  /* Shadow tight and low so it falls onto the card it is resting against. */
  filter: drop-shadow(-8px 14px 20px rgba(0, 0, 0, 0.55));
  animation: bob 5.5s ease-in-out infinite;
  pointer-events: none;
}
/* Front view, sitting above the closing pitch. Static position rather than
   absolute — it should push the heading down, not float over it. */
.mascot--cta {
  position: static;
  width: 84px;
  height: 132px;
  margin-bottom: 6px;
  right: auto;
  bottom: auto;
  background-image: url('../img/meet-trabbly-01.png');
  filter: drop-shadow(0 18px 26px rgba(0, 0, 0, 0.4));
}

/* Back view on the 404 — it is looking the other way too. */
.mascot--404 {
  position: static;
  width: 98px;
  height: 154px;
  margin: 0 auto 18px;
  right: auto;
  bottom: auto;
  background-image: url('../img/meet-trabbly.png');
  scale: -1 1;
  filter: drop-shadow(0 20px 30px rgba(0, 0, 0, 0.45));
}

/* Barely there — a couple of pixels. Enough to feel alive, not enough to
   pull the eye off the numbers. */
@keyframes bob {
  0%,
  100% {
    transform: translateY(0) rotate(0deg);
  }
  50% {
    transform: translateY(-9px) rotate(-1.2deg);
  }
}

/* ── The deck ────────────────────────────────────────────────────────────
   Three slides sharing one surface. Absolute so they occupy the same space
   without the container resizing between them, which would make the whole
   hero jump every seven seconds. */
.deck {
  position: relative;
  min-height: 428px;
}
.slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: translateY(14px) scale(0.985);
  pointer-events: none;
  transition:
    opacity 0.5s ease,
    transform 0.5s cubic-bezier(0.2, 0.8, 0.3, 1);
}
.slide.is-on {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.slide .slab--main {
  height: 100%;
  display: flex;
  flex-direction: column;
}

/* ── Org chart ───────────────────────────────────────────────────────────── */
.org {
  position: relative;
  flex: 1;
  padding: 18px 0 6px;
}
.org__wires {
  position: absolute;
  left: 0;
  right: 0;
  top: 52px;
  height: 96px;
  width: 100%;
  pointer-events: none;
}
.org__wires path {
  fill: none;
  stroke: rgba(99, 231, 127, 0.34);
  stroke-width: 1.4;
  stroke-dasharray: 620;
  stroke-dashoffset: 620;
}
.slide.is-play .org__wires path {
  animation: org-draw 0.9s 0.25s ease-out forwards;
}
@keyframes org-draw {
  to {
    stroke-dashoffset: 0;
  }
}

.org__lead {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 11px;
  justify-content: center;
  padding: 11px 14px;
  border-radius: 13px;
  background: rgba(99, 231, 127, 0.11);
  border: 1px solid rgba(99, 231, 127, 0.3);
  width: fit-content;
  margin: 0 auto;
}
.org__who {
  display: grid;
  gap: 1px;
}
.org__who b {
  font-size: 0.84rem;
  font-weight: 700;
  color: #fff;
}
.org__who i {
  font-style: normal;
  font-size: 0.66rem;
  color: rgba(255, 255, 255, 0.48);
}

.org__row {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 9px;
  margin-top: 74px;
}
.org__node {
  display: grid;
  justify-items: center;
  gap: 5px;
  padding: 12px 6px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.11);
  text-align: center;
  opacity: 0;
  transform: translateY(10px);
}
.slide.is-play .org__node {
  animation: node-in 0.5s cubic-bezier(0.2, 0.8, 0.3, 1) forwards;
  animation-delay: calc(0.55s + var(--i) * 0.11s);
}
@keyframes node-in {
  to {
    opacity: 1;
    transform: none;
  }
}
.org__node b {
  font-size: 0.72rem;
  font-weight: 700;
  color: #fff;
  line-height: 1.2;
}
.org__node i {
  font-style: normal;
  font-size: 0.62rem;
  color: rgba(255, 255, 255, 0.42);
}

.avatar {
  width: 32px;
  height: 32px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--ink);
  background: linear-gradient(140deg, var(--spring), #3fae94);
  flex-shrink: 0;
}
.avatar--lg {
  width: 38px;
  height: 38px;
  border-radius: 12px;
  font-size: 0.78rem;
}

/* ── Clock and week ──────────────────────────────────────────────────────── */
.clock {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 0 18px;
}
.clock__now span {
  display: block;
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.38);
  margin-bottom: 3px;
}
.clock__now b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 2.05rem;
  font-weight: 500;
  color: #fff;
  letter-spacing: -0.02em;
}
.clock__stamps {
  display: flex;
  gap: 8px;
}
.stamp {
  display: grid;
  gap: 2px;
  padding: 8px 11px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
}
.stamp i {
  font-style: normal;
  font-size: 0.6rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.38);
}
.stamp b {
  font-size: 0.86rem;
  color: #fff;
  font-weight: 500;
}
.stamp--in {
  background: rgba(99, 231, 127, 0.12);
  border-color: rgba(99, 231, 127, 0.3);
}
.stamp--in b {
  color: var(--spring);
}

.week {
  flex: 1;
  padding: 4px 0 10px;
}
.week__ttl {
  display: block;
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.32);
  margin-bottom: 10px;
}
.week__bars {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 9px;
  height: 78px;
  align-items: end;
}
.week__bars span {
  display: grid;
  gap: 6px;
  justify-items: center;
  align-content: end;
  height: 100%;
  font-size: 0.62rem;
  color: rgba(255, 255, 255, 0.4);
}
.week__bars i {
  display: block;
  width: 100%;
  height: 0;
  border-radius: 5px 5px 3px 3px;
  background: linear-gradient(to top, rgba(99, 231, 127, 0.28), rgba(99, 231, 127, 0.72));
}
.slide.is-play .week__bars i {
  animation: grow 0.65s cubic-bezier(0.2, 0.8, 0.3, 1) forwards;
  animation-delay: 0.3s;
}
@keyframes grow {
  to {
    height: var(--h);
  }
}
.week__bars .is-leave i {
  background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.22));
}
.week__bars .is-now i {
  background: linear-gradient(to top, rgba(99, 231, 127, 0.4), var(--spring));
}
.week__bars .is-now {
  color: var(--spring);
  font-weight: 700;
}

.rig__net--leave b {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.rig__net--leave b i {
  font-style: normal;
  font-size: 0.72rem;
  font-weight: 500;
  color: rgba(99, 231, 127, 0.66);
}

.rig__dots {
  display: flex;
  gap: 7px;
  justify-content: center;
  margin-top: 26px;
}
.rig__dot {
  width: 26px;
  height: 4px;
  border-radius: 3px;
  border: 0;
  padding: 0;
  background: rgba(255, 255, 255, 0.18);
  cursor: pointer;
  transition:
    background 0.3s,
    width 0.3s;
}
.rig__dot.is-on {
  background: var(--spring);
  width: 40px;
}

/* ── Ticker ──────────────────────────────────────────────────────────────── */
.ticker {
  position: relative;
  z-index: 2;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  background: rgba(0, 0, 0, 0.24);
  overflow: hidden;
  padding: 13px 0;
  mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}
.ticker__strip {
  display: flex;
  gap: 0;
  width: max-content;
  animation: ticker var(--ticker-duration, 60s) linear infinite;
}
.ticker:hover .ticker__strip {
  animation-play-state: paused;
}
@keyframes ticker {
  to {
    transform: translateX(-50%);
  }
}
.ticker__item {
  font-family: var(--mono);
  font-size: 0.74rem;
  color: rgba(255, 255, 255, 0.42);
  padding: 0 26px;
  white-space: nowrap;
  position: relative;
}
.ticker__item::after {
  content: '';
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: rgba(99, 231, 127, 0.5);
}

/* ── Responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 960px) {
  .stage__inner {
    grid-template-columns: 1fr;
    gap: 56px;
    padding-bottom: 64px;
  }
  .stage h1 {
    max-width: 19ch;
  }
  .stage__viz {
    min-height: auto;
  }
  .rig {
    transform: perspective(1400px) rotateY(-8deg) rotateX(4deg);
  }
}

@media (max-width: 620px) {
  .stage {
    padding-top: 112px;
  }
  /* The second line is two sentences now, and at full size it runs off the
     side of a phone. It wraps here instead; the hand-drawn underline tracks a
     single line, so it steps aside rather than smearing across two. */
  .stage h1 em,
  .stage h1 .h1__line {
    white-space: normal;
  }
  .stage h1 em::after {
    display: none;
  }
  /* No room to hide behind anything on a phone; it would just sit on the
     numbers. The CTA and 404 ones are in normal flow, so they stay. */
  .mascot {
    display: none;
  }
  .mascot--cta,
  .mascot--404 {
    display: block;
    width: 78px;
    height: 122px;
  }
  .stage__viz {
    padding-right: 0;
  }
  .rig,
  .rig__net {
    transform: none;
  }
  .slab--ghost {
    display: none;
  }
  .deck {
    min-height: 452px;
  }
  .clock {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .stage__rule,
  .ticker__strip,
  .rig,
  .rig__bar i,
  .stage h1 em::after,
  .org__wires path,
  .org__node,
  .week__bars i {
    animation: none !important;
  }
  .org__node {
    opacity: 1;
    transform: none;
  }
  .week__bars i {
    height: var(--h);
  }
  .stage__spot {
    transition: none;
  }
}

/* sections.css */
/* ===========================================================================
   Homepage sections that do something.
   =========================================================================== */

/* ── Figures strip ───────────────────────────────────────────────────────── */
.figures {
  background: var(--paper);
  padding: 46px 0;
  border-bottom: 1px solid var(--line);
}
.figures__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 28px;
}
.figure {
  border-left: 2px solid rgba(20, 112, 106, 0.22);
  padding-left: 18px;
}
.figure b {
  display: block;
  font-family: var(--display);
  font-weight: 400;
  font-size: 3rem;
  line-height: 1;
  color: var(--teal);
  font-variant-numeric: tabular-nums;
}
.figure span {
  display: block;
  margin-top: 7px;
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--muted);
  max-width: 22ch;
}
@media (max-width: 760px) {
  .figures__grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 24px;
  }
  .figure b {
    font-size: 2.3rem;
  }
}

/* ── Positioning chart ───────────────────────────────────────────────────── */
.plot {
  display: grid;
  grid-template-columns: 1.25fr 1fr;
  gap: 44px;
  align-items: center;
  margin-top: 46px;
}
/* Clipped, not visible. A rotated end-anchored axis label was drawing upward
   out of the viewBox and landing on the paragraph above it. */
.plot svg {
  width: 100%;
  height: auto;
  overflow: hidden;
}

.plot__grid line {
  stroke: var(--line);
  stroke-width: 1;
  stroke-dasharray: 3 6;
}
.plot__axis line {
  stroke: rgba(28, 42, 39, 0.35);
  stroke-width: 1.4;
}
.plot__axis path {
  fill: rgba(28, 42, 39, 0.35);
}
.plot__ax {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  fill: var(--muted);
}
.plot__ax--end {
  text-anchor: end;
}
.plot__ay {
  text-anchor: middle;
}

/* The hole in the market. Drawn as a soft dashed field rather than a hard
   shape, because it is an absence, not a thing. */
.plot__hole ellipse {
  fill: rgba(99, 231, 127, 0.09);
  stroke: rgba(20, 112, 106, 0.35);
  stroke-width: 1.4;
  stroke-dasharray: 5 7;
}
.plot__hole text {
  font-family: var(--display);
  font-style: italic;
  font-size: 17px;
  fill: var(--teal);
  text-anchor: middle;
}

.plot__dot circle {
  fill: #fff;
  stroke: var(--line);
  stroke-width: 1.5;
}
.plot__dot text {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  fill: var(--ink);
  text-anchor: middle;
}
.plot__cap {
  font-size: 11px !important;
  font-weight: 500 !important;
  fill: var(--muted) !important;
}

.plot__dot--us circle {
  fill: var(--ink-2);
  stroke: var(--teal);
  stroke-width: 2;
}
.plot__dot--us text {
  fill: #fff;
}
.plot__halo {
  fill: none !important;
  stroke: var(--spring) !important;
  stroke-width: 1.5 !important;
  opacity: 0.5;
}

/* Everything lands on scroll, in reading order, us last. */
.plot__dot,
.plot__hole {
  opacity: 0;
  transform: scale(0.82);
  transform-origin: center;
  transform-box: fill-box;
}
.plot.is-in .plot__dot,
.plot.is-in .plot__hole {
  animation: pop 0.62s cubic-bezier(0.2, 1.3, 0.4, 1) forwards;
  animation-delay: calc(var(--i) * 130ms);
}
@keyframes pop {
  to {
    opacity: 1;
    transform: scale(1);
  }
}
.plot.is-in .plot__halo {
  animation: halo 2.6s 1.3s ease-out infinite;
}
@keyframes halo {
  0% {
    r: 40;
    opacity: 0.55;
  }
  70%,
  100% {
    r: 66;
    opacity: 0;
  }
}

.plot__key {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 16px;
}
.plot__key li {
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--muted);
  padding-left: 16px;
  border-left: 2px solid var(--line);
}
.plot__key b {
  display: block;
  color: var(--ink);
  font-size: 0.92rem;
  margin-bottom: 2px;
}
.plot__key .is-us {
  border-left-color: var(--spring);
}
.plot__key .is-us b {
  color: var(--teal);
}

@media (max-width: 900px) {
  .plot {
    grid-template-columns: 1fr;
    gap: 30px;
  }
}

/* ── Employee journey ────────────────────────────────────────────────────
   The hero promises to manage the whole employee journey and nothing on the
   page showed it. Six stops on one line, because the line is the argument:
   it is continuous, so the handovers that usually leak do not exist. */
.journey {
  background: var(--paper-2);
  padding: 104px 0;
}

.track {
  position: relative;
  list-style: none;
  margin: 56px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 22px;
}

/* The thread everything hangs off. Drawn left to right on arrival. */
.track__line {
  position: absolute;
  top: 21px;
  left: 4%;
  right: 4%;
  height: 2px;
  background: linear-gradient(to right, var(--teal-soft), var(--teal), var(--teal-soft));
  transform: scaleX(0);
  transform-origin: left;
  border-radius: 2px;
}
.track.is-in .track__line {
  animation: thread 1.15s 0.15s cubic-bezier(0.3, 0.8, 0.3, 1) forwards;
}
@keyframes thread {
  to {
    transform: scaleX(1);
  }
}

.stop {
  position: relative;
  opacity: 0;
  transform: translateY(12px);
}
.track.is-in .stop {
  animation: stop-in 0.5s cubic-bezier(0.2, 0.8, 0.3, 1) forwards;
  animation-delay: calc(0.35s + var(--i) * 0.13s);
}
@keyframes stop-in {
  to {
    opacity: 1;
    transform: none;
  }
}

.stop__pin {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 14px;
  background: #fff;
  border: 2px solid var(--teal);
  color: var(--teal);
  margin-bottom: 16px;
  box-shadow: 0 8px 18px -8px rgba(20, 112, 106, 0.4);
}
.stop__pin svg {
  width: 21px;
  height: 21px;
}
/* The last stop is the payslip — the one everybody is waiting for. */
.stop:last-child .stop__pin {
  background: var(--ink-2);
  border-color: var(--ink-2);
  color: var(--spring);
}

.stop__when {
  display: block;
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--teal-soft);
  margin-bottom: 5px;
}
.stop__title {
  display: block;
  font-size: 0.98rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.25;
  margin-bottom: 7px;
}
.stop__body {
  display: block;
  font-size: 0.83rem;
  line-height: 1.52;
  color: var(--muted);
}

@media (max-width: 1050px) {
  .track {
    grid-template-columns: repeat(3, 1fr);
    gap: 34px 22px;
  }
  .track__line {
    display: none;
  }
}
@media (max-width: 680px) {
  .track {
    grid-template-columns: 1fr;
    gap: 26px;
  }
  .stop {
    display: grid;
    grid-template-columns: 44px 1fr;
    gap: 16px;
    align-items: start;
  }
  .stop__pin {
    margin-bottom: 0;
    grid-row: span 3;
  }
}

@media (prefers-reduced-motion: reduce) {
  .track__line,
  .stop {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ── Five stops, not six ─────────────────────────────────────────────────────
   .track is built for six columns and draws its thread between 4% and 96%,
   which is roughly where the first and last of six pins sit. With five, the
   pin centres move, so the thread is measured from them instead: a pin is 44px
   wide at the start of its column, so its centre is 22px in, and the last
   column begins one column width from the right. Guarded above the breakpoint
   where .track collapses to three and then one, and the thread is hidden. */
@media (min-width: 1051px) {
  .track--5 {
    grid-template-columns: repeat(5, 1fr);
  }
  .track--5 .track__line {
    left: 22px;
    right: calc((100% - 4 * 22px) / 5 - 22px);
  }
}

/* The sprite itself never renders; only <use> references do. */
.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}
/* ── Year switch ─────────────────────────────────────────────────────────── */
.years {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: 40px;
  align-items: center;
  margin-top: 44px;
  padding: 30px;
  border-radius: 22px;
  background: var(--ink);
  color: #fff;
  box-shadow: 0 40px 80px -40px rgba(4, 35, 31, 0.7);
}
.years__head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 22px;
}
.years__head .seg {
  background: rgba(255, 255, 255, 0.07);
}
.years__note {
  font-size: 0.76rem;
  color: rgba(255, 255, 255, 0.4);
}

.band {
  display: grid;
  grid-template-columns: 1fr 96px 42px;
  align-items: center;
  gap: 12px;
  padding: 7px 0;
  font-size: 0.8rem;
  animation: band-in 0.45s cubic-bezier(0.2, 0.8, 0.3, 1) both;
  animation-delay: calc(var(--i) * 55ms);
}
@keyframes band-in {
  from {
    opacity: 0;
    transform: translateX(-10px);
  }
}
.band__range {
  color: rgba(255, 255, 255, 0.66);
  font-size: 0.76rem;
}
.band__track {
  height: 5px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}
.band__track i {
  display: block;
  height: 100%;
  width: var(--w);
  max-width: 100%;
  border-radius: 3px;
  background: linear-gradient(90deg, rgba(99, 231, 127, 0.45), var(--spring));
}
.band__rate {
  text-align: right;
  color: #fff;
  font-size: 0.8rem;
}

.years__out {
  display: grid;
  gap: 12px;
}
.years__stat {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 14px 16px;
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
}
.years__stat span {
  font-size: 0.76rem;
  color: rgba(255, 255, 255, 0.55);
}
.years__stat b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.28rem;
  font-weight: 500;
  color: #fff;
}
.years__stat--net {
  background: rgba(99, 231, 127, 0.12);
  border-color: rgba(99, 231, 127, 0.32);
}
.years__stat--net span,
.years__stat--net b {
  color: var(--spring);
}
.years__delta {
  font-size: 0.8rem;
  color: rgba(255, 255, 255, 0.5);
  line-height: 1.5;
}

@media (max-width: 860px) {
  .years {
    grid-template-columns: 1fr;
    gap: 28px;
    padding: 22px;
  }
}

/* ── Door feed ───────────────────────────────────────────────────────────── */
.scan {
  display: grid;
  grid-template-columns: 8px 1fr auto auto;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  font-size: 0.88rem;
  transition:
    opacity 0.45s ease,
    transform 0.45s cubic-bezier(0.2, 0.8, 0.3, 1);
}
.scan.is-new {
  opacity: 0;
  transform: translateY(-10px);
}
.scan__pip {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--spring);
}
.scan.is-skip .scan__pip {
  background: rgba(255, 255, 255, 0.22);
}
.scan.is-out .scan__pip {
  background: #7fd4ff;
}
.scan__name {
  font-weight: 600;
  color: #fff;
}
.scan.is-skip .scan__name {
  color: rgba(255, 255, 255, 0.4);
}
.scan__at {
  font-size: 0.8rem;
  color: rgba(255, 255, 255, 0.5);
}
.scan__tag {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--spring);
  min-width: 72px;
  text-align: right;
}
.scan.is-out .scan__tag {
  color: #7fd4ff;
}
.scan.is-skip .scan__tag {
  color: rgba(255, 255, 255, 0.3);
}

/* ── Isolation proof ─────────────────────────────────────────────────────── */
.proof {
  border-radius: 18px;
  background: #04231f;
  border: 1px solid rgba(255, 255, 255, 0.12);
  overflow: hidden;
  box-shadow: 0 30px 60px -30px rgba(4, 35, 31, 0.6);
}
.proof__bar {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 11px 15px;
  background: rgba(255, 255, 255, 0.05);
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
}
.proof__bar i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
}
.proof__bar b {
  margin-left: 8px;
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.42);
}
.proof__q {
  padding: 15px 18px 6px;
  font-family: var(--mono);
  font-size: 0.76rem;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.55);
}
.proof__q em {
  font-style: normal;
  color: var(--spring);
}
.proof__out {
  padding: 6px 18px 18px;
  display: grid;
  gap: 2px;
}
.proof__row,
.proof__done {
  opacity: 0;
  transform: translateY(6px);
  transition:
    opacity 0.4s ease,
    transform 0.4s cubic-bezier(0.2, 0.8, 0.3, 1);
}
.proof__row.is-in,
.proof__done.is-in {
  opacity: 1;
  transform: none;
}
.proof__row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 14px;
  padding: 6px 0;
  font-size: 0.76rem;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.07);
}
.proof__t {
  color: rgba(255, 255, 255, 0.68);
}
.proof__m {
  color: rgba(255, 255, 255, 0.4);
}
.proof__o {
  color: var(--spring);
}
.proof__done {
  margin-top: 12px;
  padding: 10px 13px;
  border-radius: 10px;
  background: rgba(99, 231, 127, 0.12);
  border: 1px solid rgba(99, 231, 127, 0.3);
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--spring);
}

@media (prefers-reduced-motion: reduce) {
  .band,
  .scan,
  .proof__row,
  .proof__done {
    animation: none !important;
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
    stroke-dashoffset: 0 !important;
  }
}

/* product.css */
/* ===========================================================================
   Animated product mockups.
   ---------------------------------------------------------------------------
   Built rather than screenshotted. A screenshot is a dead rectangle that goes
   stale the moment the UI moves, leaks whatever data was on screen, and weighs
   400KB. These are markup: crisp at any size, animated, weightless, and they
   cannot accidentally publish somebody's salary.

   Each one lives in a browser frame, tilted a couple of degrees the way the
   category does it, and plays when it scrolls into view.
   =========================================================================== */

.product {
  background: var(--paper);
  padding: 104px 0;
  overflow: hidden;
}

.showcase + .showcase {
  margin-top: 110px;
}
/* "A working day with Trabbly." measures 553px against the 552px that 20ch
   buys at this size: one pixel over, which would wrap and leave "Trabbly."
   alone on a second line. Scoped here rather than widening every heading. */
.product .h2 {
  max-width: 22ch;
}

.showcase {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: 60px;
  align-items: center;
}
.showcase--flip {
  grid-template-columns: 1.15fr 0.85fr;
}
.showcase--flip .showcase__copy {
  order: 2;
}

.showcase__tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--teal);
  margin-bottom: 14px;
}
.showcase__tag svg {
  width: 18px;
  height: 18px;
}
.showcase__copy h3 {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1.8rem, 3vw, 2.5rem);
  line-height: 1.08;
  color: var(--ink);
  max-width: 16ch;
}
.showcase__copy p {
  margin-top: 16px;
  font-size: 0.98rem;
  line-height: 1.62;
  color: var(--muted);
  max-width: 42ch;
}
.showcase__list {
  list-style: none;
  padding: 0;
  margin: 20px 0 0;
  display: grid;
  gap: 9px;
}
.showcase__list li {
  position: relative;
  padding-left: 24px;
  font-size: 0.9rem;
  color: var(--muted);
}
.showcase__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: var(--spring);
  box-shadow: 0 0 0 3px rgba(99, 231, 127, 0.2);
}

/* ── Browser frame ───────────────────────────────────────────────────────── */
.shot {
  position: relative;
  border-radius: 16px;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow:
    0 40px 80px -34px rgba(4, 35, 31, 0.28),
    0 4px 12px -4px rgba(4, 35, 31, 0.06);
  overflow: hidden;
  transform: perspective(1800px) rotateY(-4deg) rotateX(2deg) rotate(-0.6deg);
  transition: transform 0.6s cubic-bezier(0.2, 0.8, 0.3, 1);
}
.showcase--flip .shot {
  transform: perspective(1800px) rotateY(4deg) rotateX(2deg) rotate(0.6deg);
}
.shot:hover {
  transform: perspective(1800px) rotateY(0) rotateX(0) rotate(0);
}

.shot__bar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  background: var(--paper-2);
  border-bottom: 1px solid var(--line);
}
.shot__bar i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #d9d2c4;
}
.shot__url {
  margin-left: 10px;
  flex: 1;
  max-width: 260px;
  padding: 4px 11px;
  border-radius: 6px;
  background: #fff;
  border: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 0.64rem;
  color: var(--muted);
}

/* ── Shared app chrome inside the frame ──────────────────────────────────── */
.app {
  display: grid;
  grid-template-columns: 52px 1fr;
  min-height: 340px;
}
.app__rail {
  background: var(--ink);
  padding: 14px 0;
  display: grid;
  justify-items: center;
  align-content: start;
  gap: 14px;
}
.app__rail .dot {
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.1);
}
.app__rail .dot.is-on {
  background: var(--spring);
}
.app__body {
  padding: 16px 18px 20px;
}
.app__head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 16px;
}
.app__head b {
  font-size: 0.92rem;
  color: var(--ink);
}
/* Namespaced. This was `.who`, which collided with the `.who` section class
   added later — the section's `padding: 96px 0` landed on a 26px avatar and
   stretched it into a green bar down the whole mockup. */
.app__avatar {
  margin-left: auto;
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: linear-gradient(140deg, var(--spring), var(--teal-soft));
  display: grid;
  place-items: center;
  font-size: 0.6rem;
  font-weight: 700;
  color: var(--ink);
}

/* ── Dashboard ───────────────────────────────────────────────────────────── */
.tiles {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 9px;
}
.tile {
  padding: 11px 12px;
  border-radius: 11px;
  background: var(--paper);
  border: 1px solid var(--line);
}
.tile span {
  display: block;
  font-size: 0.58rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 4px;
}
.tile b {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.15rem;
  color: var(--ink);
  font-weight: 600;
}
.tile--live b {
  color: var(--teal);
}

.chart {
  margin-top: 14px;
  padding: 14px;
  border-radius: 12px;
  border: 1px solid var(--line);
}
.chart__ttl {
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 12px;
}
.chart__bars {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 10px;
  align-items: end;
  height: 92px;
}
/* Two rows: the bar's area, then its label. The rows have to be declared,
   because the bar's height is a percentage and a percentage of an implicit
   content-sized row resolves to nothing — which is why these bars have been
   rendering at zero height rather than rising. */
.chart__bars span {
  display: grid;
  grid-template-rows: 1fr auto;
  gap: 6px;
  justify-items: center;
  height: 100%;
  font-size: 0.56rem;
  color: var(--muted);
}
/* Drawn at full height by default; only hidden once JavaScript confirms it is
   running and can animate them back. A chart that depends on a scroll observer
   firing is a chart that is sometimes just empty. */
.chart__bars i {
  align-self: end;
  width: 100%;
  height: var(--h);
  border-radius: 5px 5px 2px 2px;
  background: linear-gradient(to top, rgba(20, 112, 106, 0.28), var(--teal));
}
.js .chart__bars i {
  height: 0;
}
.js .is-playing .chart__bars i {
  animation: rise 0.8s cubic-bezier(0.2, 0.8, 0.3, 1) forwards;
  animation-delay: calc(var(--i) * 80ms);
}
@keyframes rise {
  to {
    height: var(--h);
  }
}

/* ── People directory ────────────────────────────────────────────────────── */
.search {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: var(--paper);
  margin-bottom: 14px;
  font-size: 0.76rem;
  color: var(--muted);
}
.search .caret {
  display: inline-block;
  width: 1px;
  height: 13px;
  background: var(--teal);
  animation: blink 1.1s steps(1) infinite;
}
@keyframes blink {
  50% {
    opacity: 0;
  }
}

.roster {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 9px;
}
.person {
  padding: 12px;
  border-radius: 11px;
  border: 1px solid var(--line);
  display: grid;
  justify-items: center;
  gap: 3px;
  text-align: center;
}
.js .person {
  opacity: 0;
  transform: translateY(8px);
}
.js .is-playing .person {
  animation: fade-up 0.45s cubic-bezier(0.2, 0.8, 0.3, 1) forwards;
  animation-delay: calc(var(--i) * 70ms);
}
@keyframes fade-up {
  to {
    opacity: 1;
    transform: none;
  }
}
.person .pic {
  width: 34px;
  height: 34px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  font-size: 0.66rem;
  font-weight: 700;
  color: #fff;
  margin-bottom: 5px;
}
.person b {
  font-size: 0.72rem;
  color: var(--ink);
}
.person i {
  font-style: normal;
  font-size: 0.6rem;
  color: var(--muted);
}
.person .flag {
  margin-top: 4px;
  font-size: 0.54rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 2px 6px;
  border-radius: 999px;
  background: var(--paper-2);
  color: var(--muted);
}

/* ── Attendance ──────────────────────────────────────────────────────────── */
.att__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.att__src {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--teal);
}
.att__src i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--spring);
  box-shadow: 0 0 0 3px rgba(99, 231, 127, 0.25);
}
.att__tot {
  font-size: 0.68rem;
  color: var(--muted);
}

.att {
  display: grid;
  gap: 4px;
}
.att__row {
  display: grid;
  grid-template-columns: 52px 46px 46px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 9px;
  background: var(--paper);
  border: 1px solid var(--line);
  font-size: 0.72rem;
}
.js .att__row {
  opacity: 0;
  transform: translateX(-8px);
}
.js .is-playing .att__row {
  animation: att-in 0.42s cubic-bezier(0.2, 0.8, 0.3, 1) forwards;
  animation-delay: calc(var(--i) * 90ms);
}
@keyframes att-in {
  to {
    opacity: 1;
    transform: none;
  }
}
.att__day {
  font-weight: 700;
  color: var(--ink);
}
.att__in,
.att__out {
  font-size: 0.68rem;
  color: var(--muted);
}
.att__bar {
  height: 5px;
  border-radius: 3px;
  background: rgba(20, 112, 106, 0.1);
  overflow: hidden;
}
.att__bar i {
  display: block;
  height: 100%;
  width: var(--w);
  border-radius: 3px;
  background: linear-gradient(90deg, rgba(20, 112, 106, 0.45), var(--teal));
}
.att__h {
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
/* A day on approved leave is not a short day. */
.att__row.is-off {
  background: repeating-linear-gradient(-45deg, var(--paper-2) 0 6px, transparent 6px 12px);
}
.att__row.is-off .att__h {
  color: var(--muted);
  font-weight: 500;
}
.att__row.is-now {
  border-color: rgba(99, 231, 127, 0.5);
  background: linear-gradient(110deg, rgba(99, 231, 127, 0.13), var(--paper) 60%);
}
.att__row.is-now .att__h {
  color: var(--teal);
}

/* ── Payroll run ─────────────────────────────────────────────────────────── */
.run__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.run__when {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--ink);
}
.run__state {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--teal);
  background: rgba(99, 231, 127, 0.18);
  padding: 4px 10px;
  border-radius: 999px;
}

.run {
  border: 1px solid var(--line);
  border-radius: 11px;
  overflow: hidden;
}
.run__cols,
.run__row,
.run__total {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1fr;
  gap: 8px;
  padding: 8px 12px;
  align-items: center;
}
.run__cols {
  background: var(--paper-2);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
}
.run__cols span:not(:first-child),
.run__row span:not(:first-child) {
  text-align: right;
}
.run__row {
  border-top: 1px solid var(--line);
  font-size: 0.72rem;
}
.js .run__row {
  opacity: 0;
}
.js .is-playing .run__row {
  animation: fade-up 0.4s ease-out forwards;
  animation-delay: calc(var(--i) * 90ms);
}
.run__who {
  font-weight: 600;
  color: var(--ink);
}
.run__neg {
  color: #b4573f;
}
.run__net {
  font-weight: 600;
  color: var(--ink);
}
.run__total {
  grid-template-columns: 1fr auto;
  border-top: 1px solid var(--line);
  background: var(--ink);
  color: #fff;
}
.run__total span {
  font-size: 0.66rem;
  color: rgba(255, 255, 255, 0.6);
}
.run__total b {
  font-size: 0.92rem;
  color: var(--spring);
  font-weight: 600;
}

.run__cta {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 12px;
}
.run__btn {
  background: var(--spring);
  color: var(--ink);
  font-size: 0.7rem;
  font-weight: 700;
  padding: 8px 16px;
  border-radius: 999px;
}
.run__note {
  font-size: 0.62rem;
  color: var(--muted);
}

/* ── Leave calendar ──────────────────────────────────────────────────────── */
.cal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--ink);
}
.cal__head span {
  font-size: 0.62rem;
  font-weight: 500;
  color: var(--muted);
}
.cal__dow,
.cal__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 5px;
}
.cal__dow {
  margin-bottom: 5px;
}
.cal__dow span {
  text-align: center;
  font-size: 0.56rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.cal__grid b {
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border-radius: 7px;
  background: var(--paper);
  border: 1px solid var(--line);
  font-size: 0.62rem;
  font-weight: 500;
  color: var(--muted);
}
.js .cal__grid b {
  opacity: 0;
  transform: scale(0.86);
}
.js .is-playing .cal__grid b {
  animation: cell-in 0.3s ease-out forwards;
  animation-delay: calc(var(--i) * 12ms);
}
@keyframes cell-in {
  to {
    opacity: 1;
    transform: none;
  }
}
.cal__grid b.is-leave {
  background: rgba(99, 231, 127, 0.24);
  border-color: rgba(20, 112, 106, 0.3);
  color: var(--ink-2);
  font-weight: 700;
}
.cal__grid b.is-sick {
  background: rgba(255, 180, 168, 0.35);
  border-color: rgba(200, 90, 70, 0.28);
  color: #8a3a2a;
  font-weight: 700;
}
.cal__grid b.is-hol {
  background: var(--ink-2);
  border-color: var(--ink-2);
  color: #fff;
  font-weight: 700;
}
.cal__grid b.is-out {
  opacity: 0.28 !important;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 12px;
  font-size: 0.62rem;
  color: var(--muted);
}
.legend span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.legend i {
  width: 9px;
  height: 9px;
  border-radius: 3px;
}

/* ── Responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
  .showcase,
  .showcase--flip {
    grid-template-columns: 1fr;
    gap: 32px;
  }
  .showcase--flip .showcase__copy {
    order: 0;
  }
  .shot,
  .showcase--flip .shot {
    transform: none;
  }
  .showcase + .showcase {
    margin-top: 68px;
  }
  .tiles {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (prefers-reduced-motion: reduce) {
  .chart__bars i,
  .person,
  .cal__grid b,
  .search .caret {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .chart__bars i {
    height: var(--h);
  }
}

/* ── Phones ───────────────────────────────────────────────────────────────
   The mockups are the one thing on the site with fixed-width columns, and at
   360px the .wrap leaves about 215px inside the app body. Four columns of
   monospaced currency need roughly 55px each plus gaps - about 60px more than
   exists. Rather than let the page scroll sideways, the mockups tighten. */
@media (max-width: 620px) {
  .app {
    grid-template-columns: 44px 1fr;
    min-height: 0;
  }
  .app__body {
    padding: 14px;
  }

  /* Three across becomes two: at 66px a card is narrower than the name on it. */
  .roster {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Deductions is the column to lose. Gross in and net out still tell the
     whole story, and the missing figure is the difference between them. */
  .run__cols,
  .run__row,
  .run__total {
    grid-template-columns: 1.4fr 1fr 1fr;
    gap: 6px;
    padding: 8px 10px;
    font-size: 0.66rem;
  }
  .run__cols span:nth-child(3),
  .run__row span:nth-child(3) {
    display: none;
  }

  /* Clock-in and clock-out keep their own columns; the bar gives up its
     minimum so the row can never be the widest thing on the page. */
  .att__row {
    grid-template-columns: 44px 42px 42px minmax(0, 1fr);
    gap: 7px;
    padding: 8px;
    font-size: 0.66rem;
  }
  .att__row > :last-child {
    display: none;
  }

  .run__cta {
    flex-wrap: wrap;
    gap: 8px;
  }
  .run__note {
    font-size: 0.62rem;
  }
}

/* logos.css */
/* ===========================================================================
   Logo wall.
   ---------------------------------------------------------------------------
   ⚠ The marks currently in the markup are PLACEHOLDERS — invented companies,
   none of them customers. Replace or delete before launch. See README.

   Styled the way the category does it: muted, evenly spaced, drifting slowly,
   masked to fade at both edges so it reads as a longer list than it is.
   =========================================================================== */

.logos {
  background: var(--paper);
  padding: 44px 0 52px;
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}

/* ── Inside the hero ─────────────────────────────────────────────────────
   The base styles above are for a light band. Dropped into the dark hero
   without an override they painted a pale stripe across it — which is what
   made it look like a mistake rather than a design.

   Static, not scrolling. A marquee down there competes with a hero that is
   already animating three slides; two things moving is one too many. */
.logos--hero {
  position: relative;
  z-index: 2;
  background: none;
  border-bottom: 0;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  padding: 26px 0 30px;
  margin-top: 6px;
}
.logos--hero .logos__lead {
  color: rgba(255, 255, 255, 0.34);
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  opacity: 1;
  margin-bottom: 20px;
}
/* Drifting slowly enough to read as ambient rather than as something
   demanding to be watched. The duration is tuned to the strip's actual width
   so the speed stays constant if logos are added or removed — 4 names at
   roughly 250px each, four times through, at about 26px per second. Two
   passes would loop seamlessly on their own; four keeps the rail from looking
   sparse now there are half as many distinct names. */
.logos--hero .logos__strip {
  animation: logo-drift 78s linear infinite;
  will-change: transform;
}
.logos--hero:hover .logos__strip {
  animation-play-state: paused;
}

/* The spacing this lost when the row was briefly static. Without horizontal
   padding every mark runs into its neighbour and the icons read as belonging
   to the wrong name. */
.logos--hero .logo {
  padding: 0 30px;
  gap: 11px;
  color: #fff;
  opacity: 0.34;
  font-size: 0.98rem;
  font-weight: 600;
  letter-spacing: 0.005em;
}
.logos--hero .logo:hover {
  opacity: 0.66;
}
.logos--hero .logo svg {
  width: 19px;
  height: 19px;
  color: rgba(99, 231, 127, 0.6);
}

/* A hairline between marks, so the eye groups each icon with its own word
   rather than splitting the difference. */
.logos--hero .logo::after {
  content: '';
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 15px;
  background: rgba(255, 255, 255, 0.12);
}
.logos--hero .logo {
  position: relative;
}

@media (max-width: 900px) {
  .logos--hero .logo {
    font-size: 0.88rem;
    padding: 0 20px;
  }
  .logos--hero .logos__strip {
    animation-duration: 46s;
  }
}

.logos__lead {
  text-align: center;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  opacity: 0.7;
  margin-bottom: 30px;
}

.logos__rail {
  mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
}

.logos__strip {
  display: flex;
  align-items: center;
  width: max-content;
  animation: logo-drift 46s linear infinite;
}
/* Stop when someone wants to actually read one. */
.logos__rail:hover .logos__strip {
  animation-play-state: paused;
}
@keyframes logo-drift {
  to {
    transform: translateX(-50%);
  }
}

.logo {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 0 34px;
  white-space: nowrap;
  font-size: 1.06rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--graphite);
  /* Muted rather than full colour, so the wall supports the page instead of
     competing with it. */
  opacity: 0.42;
  transition: opacity 0.25s;
}
.logo:hover {
  opacity: 0.8;
}
.logo svg {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  color: var(--teal);
}

@media (prefers-reduced-motion: reduce) {
  .logos__strip {
    animation: none;
  }
}

@media (max-width: 620px) {
  .logo {
    padding: 0 22px;
    font-size: 0.94rem;
  }
}

/* bento.css */
/* ===========================================================================
   Bento grid.
   ---------------------------------------------------------------------------
   Six cells filling a 4 × 3 grid exactly. Explicit placement rather than
   auto-flow, because auto-flow left an orphan hanging on its own row the
   moment a span did not divide neatly.

       ┌───────────────┬───────┬────────┐
       │               │       │ modules│
       │  One person   │  toy  ├────────┤
       │  One record   │       │ audit  │
       ├───────────────┼───────┴────────┤
       │    payroll    │   who asks     │
       └───────────────┴────────────────┘
   =========================================================================== */

.bento-wrap {
  background: var(--paper);
  padding: 104px 0;
}
/* "Bring it together with Trabbly." measures 586px in Instrument Serif at this
   size, past the 20ch (552px) cap .h2 carries everywhere else, so it would
   wrap mid-phrase. Scoped here rather than widening every section heading. */
.bento-wrap .h2 {
  max-width: 22ch;
}

.bento {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  /* minmax rather than fixed: .cell sets overflow: hidden, so a row that
     cannot grow clips longer copy with no error anywhere. The heights are
     still the design; the auto ceiling is a safety net. */
  grid-template-rows: minmax(178px, auto) minmax(178px, auto) minmax(214px, auto);
  gap: 14px;
  margin-top: 48px;
}

.cell {
  position: relative;
  overflow: hidden;
  border-radius: 20px;
  background: #fff;
  border: 1px solid var(--line);
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  transition:
    transform 0.3s cubic-bezier(0.2, 0.8, 0.3, 1),
    box-shadow 0.3s,
    border-color 0.3s;
}
.cell:hover {
  transform: translateY(-4px);
  border-color: rgba(20, 112, 106, 0.35);
  box-shadow: 0 22px 44px -24px rgba(4, 35, 31, 0.28);
}

.cell__ico {
  width: 25px;
  height: 25px;
  color: var(--teal);
  flex-shrink: 0;
  margin-bottom: 2px;
}
/* Isometric icons carry their own colour in the polygons, so they must not
   inherit the flat icon's stroke tint — and they earn more room. */
.cell__ico--3d {
  width: 54px;
  height: 54px;
  color: inherit;
  margin-bottom: 6px;
  filter: drop-shadow(0 8px 12px rgba(4, 35, 31, 0.22));
}
.cell > b {
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.25;
}
.cell > span {
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--muted);
}

/* ── Placement ───────────────────────────────────────────────────────────── */
.cell--hero {
  grid-column: 1 / 3;
  grid-row: 1 / 3;
}
.cell--toy {
  grid-column: 3;
  grid-row: 1 / 3;
}
.cell--modules {
  grid-column: 4;
  grid-row: 1;
}
.cell--audit {
  grid-column: 4;
  grid-row: 2;
}
/* The payroll card carries the most copy of the six, so it takes the widest
   cell. In the narrow column it measured 70px past the bottom. */
.cell--accent {
  grid-column: 1 / 3;
  grid-row: 3;
}
.cell--photo {
  grid-column: 3 / 5;
  grid-row: 3;
}

/* ── Hero cell ───────────────────────────────────────────────────────────── */
.cell--hero {
  background: linear-gradient(158deg, #04231f 0%, var(--ink-2) 60%, #0b5c52 100%);
  border-color: transparent;
  justify-content: center;
  padding: 34px;
}
.cell--hero h3 {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1.9rem, 3.1vw, 2.7rem);
  line-height: 1.02;
  color: #fff;
  letter-spacing: -0.02em;
}
.cell--hero p {
  margin-top: 13px;
  max-width: 42ch;
  font-size: 0.92rem;
  line-height: 1.58;
  color: rgba(255, 255, 255, 0.64);
}
.cell__link {
  display: inline-block;
  margin-top: 17px;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--spring);
}
.cell__link:hover {
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* ── The toy ─────────────────────────────────────────────────────────────
   Given a whole cell rather than tucked in a corner. It is the one asset
   nobody else in this category has, so it may as well be seen.

   The spotlight is drawn in CSS behind the cutout, so the light in the cell
   and the light on the toy agree. */
.cell--toy {
  padding: 0;
  background:
    radial-gradient(70% 55% at 50% 42%, rgba(99, 231, 127, 0.24), transparent 70%),
    linear-gradient(165deg, #0d3d38, #04231f);
  border-color: transparent;
}

/* Bottom inset clears the caption gradient; the render is a seated 3/4 pose,
   so it is anchored to the floor of the cell rather than centred in it.

   Three things stop the cutout reading as pasted on:
     · a grade that warms its creams toward the cell's palette
     · a drop shadow in the cell's own dark green, not black
     · a mask that dissolves the last few percent, so the silhouette meets the
       floor instead of stopping dead against it */
.cell__mascot {
  position: absolute;
  inset: 7% 12% 22% 12%;
  background: url('../img/meet-trabbly.png') no-repeat center bottom / contain;
  filter: saturate(1.06) contrast(1.04) drop-shadow(0 18px 22px rgba(3, 26, 23, 0.6));
  -webkit-mask-image: linear-gradient(to bottom, #000 88%, transparent 99%);
  mask-image: linear-gradient(to bottom, #000 88%, transparent 99%);
  animation: cell-bob 6s ease-in-out infinite;
  z-index: 2;
}

/* The aura. A blurred copy of the same artwork, so the halo is made of the
   toy's own colours rather than a guessed green — that is what makes the
   silhouette sit in the light of the box instead of on top of it. */
.cell__glow {
  position: absolute;
  inset: 7% 12% 22% 12%;
  background: url('../img/meet-trabbly.png') no-repeat center bottom / contain;
  filter: blur(20px) saturate(1.9) brightness(1.35);
  opacity: 0.5;
  animation: cell-bob 6s ease-in-out infinite;
  z-index: 1;
}

/* A contact shadow on the floor. Without it the cutout reads as pasted on;
   it counter-animates against the bob so the toy looks like it is lifting
   off something rather than the whole scene sliding. */
.cell__shadow {
  position: absolute;
  left: 50%;
  bottom: 20%;
  width: 52%;
  height: 22px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(50% 50%, rgba(0, 0, 0, 0.55), transparent 70%);
  filter: blur(6px);
  animation: cell-bob-shadow 6s ease-in-out infinite;
}
@keyframes cell-bob {
  0%,
  100% {
    transform: translateY(0) rotate(0);
  }
  50% {
    transform: translateY(-9px) rotate(-1.5deg);
  }
}
@keyframes cell-bob-shadow {
  0%,
  100% {
    transform: translateX(-50%) scale(1);
    opacity: 0.55;
  }
  50% {
    transform: translateX(-50%) scale(0.86);
    opacity: 0.32;
  }
}

/* ── Photo cell ──────────────────────────────────────────────────────────
   Until the photograph lands this is a tinted panel with its caption, which
   reads as a designed block rather than a missing asset. */
.cell--photo {
  padding: 0;
  border-color: transparent;
  background: linear-gradient(150deg, var(--teal) 0%, var(--ink-2) 100%);
}
/* A drawn illustration, not a photograph.
 *
 * This pointed at people-1.jpg, which was never shot — so the cell rendered as
 * a bare gradient with a caption floating on it. A stock photo would also have
 * needed the grayscale-and-luminosity treatment below to stop it importing
 * whatever colours the shoot happened to have; drawn artwork is already in the
 * palette and stays sharp at any size.
 *
 * Sat high in the cell and stopped short of the bottom, because the caption
 * has a gradient scrim down there and artwork under text is just noise. */
.cell__img {
  position: absolute;
  inset: 8% 6% 24%;
  background-image: url('/assets/img/solo-hr.svg');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}

/* Above the mascot layers, which now stack to z-index 2. */
.cell__over {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 3;
  padding: 20px;
  display: grid;
  gap: 3px;
  background: linear-gradient(to top, rgba(4, 35, 31, 0.9), transparent);
}
.cell__over b {
  color: #fff;
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1.28;
}
.cell__over i {
  font-style: normal;
  font-size: 0.79rem;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.7);
}

/* The two cells in the narrow fourth column carry no icon. With one they
   measured past the bottom of a 178px row, and the column reads better as a
   pair of plain text cards than as one iconed and one not. */
.cell--modules,
.cell--audit {
  justify-content: center;
}

.cell--accent {
  background: linear-gradient(150deg, rgba(99, 231, 127, 0.24), rgba(20, 112, 106, 0.1));
  border-color: rgba(20, 112, 106, 0.24);
  justify-content: center;
}

/* ── Responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 1040px) {
  .bento {
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: repeat(5, minmax(172px, auto));
  }
  .cell--hero {
    grid-column: 1 / 3;
    grid-row: 1;
  }
  .cell--toy {
    grid-column: 1;
    grid-row: 2 / 4;
  }
  .cell--modules {
    grid-column: 2;
    grid-row: 2;
  }
  .cell--audit {
    grid-column: 2;
    grid-row: 3;
  }
  .cell--accent {
    grid-column: 1 / 3;
    grid-row: 4;
  }
  .cell--photo {
    grid-column: 1 / 3;
    grid-row: 5;
  }
  .cell--hero {
    min-height: 250px;
  }
}

@media (max-width: 620px) {
  .bento {
    grid-template-columns: 1fr;
    grid-template-rows: none;
    grid-auto-rows: minmax(158px, auto);
  }
  .cell,
  .cell--hero,
  .cell--toy,
  .cell--modules,
  .cell--audit,
  .cell--accent,
  .cell--photo {
    grid-column: 1;
    grid-row: auto;
  }
  .cell--toy,
  .cell--photo {
    min-height: 250px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cell__mascot,
  .cell__glow,
  .cell__shadow {
    animation: none;
  }
}

/* finish.css */
/* ===========================================================================
   The sections that turn a feature tour into a sales page.
   ---------------------------------------------------------------------------
   Segmentation and the marketplace strip. The homepage had
   four consecutive answers to "what does it do" and none at all to "is it for
   me" or "what does it cost" — which is where a visitor either self-qualifies
   or leaves.
   =========================================================================== */

/* ── Marketplace strip ───────────────────────────────────────────────────── */
.connects {
  background: var(--paper-2);
  padding: 96px 0;
}
.connects__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: center;
}

.connects__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 10px;
}
.conn {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 15px 18px;
  border-radius: 14px;
  background: #fff;
  border: 1px solid var(--line);
  transition:
    border-color 0.24s,
    transform 0.24s cubic-bezier(0.2, 0.8, 0.3, 1);
}
.conn:hover {
  transform: translateX(3px);
  border-color: rgba(20, 112, 106, 0.3);
}
.conn__ico {
  width: 24px;
  height: 24px;
  color: var(--teal);
}
.conn span {
  display: grid;
  gap: 2px;
}
.conn b {
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--ink);
}
.conn i {
  font-style: normal;
  font-size: 0.79rem;
  color: var(--muted);
}
.conn em {
  font-style: normal;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--paper-2);
  padding: 4px 9px;
  border-radius: 999px;
}
/* Only one of these is actually built, and it says so. */
.conn--live {
  border-color: rgba(20, 112, 106, 0.32);
  background: linear-gradient(120deg, rgba(99, 231, 127, 0.13), #fff 60%);
}
.conn__tag {
  background: var(--spring) !important;
  color: var(--ink) !important;
}

/* ── Responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 960px) {
  .connects__grid {
    grid-template-columns: 1fr;
    gap: 34px;
  }
}

@media (max-width: 620px) {
  .connects {
    padding: 68px 0;
  }
}

/* hub.css */
/* ===========================================================================
   Integrations hub.
   ---------------------------------------------------------------------------
   Trabbly in the middle, partners on an ellipse around it, wavy cubics between.
   Node positions and curve endpoints come from the same trigonometry in the
   generator, so every line lands on its node rather than near it.
   =========================================================================== */

.hub-wrap {
  background: var(--paper-2);
  padding: 104px 0 96px;
  overflow: hidden;
}

.hub {
  position: relative;
  margin-top: 40px;
  aspect-ratio: 960 / 560;
}

/* ── Wires ───────────────────────────────────────────────────────────────── */
.hub__wires {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.hub__wire {
  fill: none;
  stroke: rgba(20, 112, 106, 0.3);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-dasharray: 900;
  stroke-dashoffset: 900;
}
.hub.is-on .hub__wire {
  animation: hub-draw 1.15s cubic-bezier(0.3, 0.8, 0.3, 1) forwards;
  animation-delay: calc(var(--i) * 90ms);
}
@keyframes hub-draw {
  to {
    stroke-dashoffset: 0;
  }
}

/* Pulses travelling outward along each wire, so the diagram reads as data
   moving rather than as a static wiring chart. Motion comes from
   <animateMotion> in the markup, which follows the path by reference — the dot
   and the line therefore cannot drift apart the way a duplicated CSS
   offset-path would. Held back until the wires have finished drawing. */
.hub__pulse {
  fill: var(--spring);
  opacity: 0;
  filter: drop-shadow(0 0 5px rgba(99, 231, 127, 0.9));
  visibility: hidden;
}
.hub.is-on .hub__pulse {
  visibility: visible;
}

/* ── Core ────────────────────────────────────────────────────────────────── */
.hub__core {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  justify-items: center;
  gap: 8px;
  width: 168px;
  height: 168px;
  align-content: center;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 38%, #0d5c57, var(--ink) 72%);
  box-shadow:
    0 0 0 10px rgba(99, 231, 127, 0.07),
    0 0 0 22px rgba(99, 231, 127, 0.04),
    0 26px 50px -22px rgba(4, 35, 31, 0.6);
  z-index: 2;
}
.hub__core img {
  width: 42px;
  height: auto;
  position: relative;
  z-index: 1;
}
.hub__name {
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #fff;
  position: relative;
  z-index: 1;
}

/* A ring expanding out of the core on a slow loop — the source the pulses are
   leaving from. */
.hub__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid rgba(99, 231, 127, 0.55);
  opacity: 0;
}
.hub.is-on .hub__ring {
  animation: core-ring 3.8s ease-out infinite;
}
@keyframes core-ring {
  0% {
    transform: scale(0.9);
    opacity: 0.55;
  }
  70%,
  100% {
    transform: scale(1.5);
    opacity: 0;
  }
}

/* ── Pins ────────────────────────────────────────────────────────────────── */
.pin {
  position: absolute;
  transform: translate(-50%, -50%);
  display: grid;
  justify-items: center;
  gap: 5px;
  width: 132px;
  text-align: center;
  z-index: 3;
  opacity: 0;
}
.hub.is-on .pin {
  animation: pin-in 0.5s cubic-bezier(0.2, 1.2, 0.4, 1) forwards;
  animation-delay: calc(0.45s + var(--i) * 90ms);
}
@keyframes pin-in {
  from {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.7);
  }
  to {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
}

.pin__disc {
  position: relative;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 19px;
  background: #fff;
  border: 1px solid var(--line);
  color: var(--muted);
  box-shadow: 0 12px 24px -14px rgba(4, 35, 31, 0.35);
  transition:
    transform 0.26s cubic-bezier(0.2, 0.8, 0.3, 1),
    border-color 0.26s,
    color 0.26s;
}
.pin__fallback {
  width: 25px;
  height: 25px;
}

/* The partner's real mark, laid over the drawn fallback. A missing file paints
   nothing, so the icon underneath simply stays visible — the row is never a
   line of broken images while logos are being collected.

   The fallback has to go when a mark IS present, though: brand logos are
   transparent, so the grey icon showed through the gaps in them, which is
   visible as a shadow behind Slack's arms and between the Microsoft squares.
   All four referenced files exist, so nothing is left blank; a pin with no
   logo keeps its drawn icon exactly as before. */
.pin__disc:has(.pin__logo) .pin__fallback {
  display: none;
}

.pin__logo {
  position: absolute;
  inset: 13px;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

/* Each pin drifts on its own offset, so the ring breathes instead of sitting
   there. Small numbers — this is behind the reading, not in front of it. */
.pin__disc {
  animation: pin-float 6.5s ease-in-out infinite;
  animation-delay: calc(var(--i) * -0.9s);
}
@keyframes pin-float {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-6px);
  }
}
.pin:hover .pin__disc {
  animation-play-state: paused;
  transform: translateY(-5px) scale(1.06);
  border-color: var(--teal);
  color: var(--teal);
}

/* Built today gets the brand colour. Planned stays grey — the difference is
   the whole point of showing status at all. */
.pin--live .pin__disc {
  border-color: rgba(20, 112, 106, 0.4);
  color: var(--teal);
  background: linear-gradient(150deg, rgba(99, 231, 127, 0.18), #fff 65%);
}

.pin__name {
  font-size: 0.84rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.2;
}
.pin__what {
  font-size: 0.68rem;
  color: var(--muted);
  line-height: 1.3;
}

/* ── Responsive ──────────────────────────────────────────────────────────
   Below tablet the ellipse stops working — the pins collide with the core.
   Falls back to a plain grid, which is honest about what it is. */
@media (max-width: 900px) {
  .hub {
    aspect-ratio: auto;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 26px 12px;
    margin-top: 34px;
  }
  .hub__wires {
    display: none;
  }
  .hub__core {
    position: static;
    transform: none;
    grid-column: 1 / -1;
    width: 100%;
    height: auto;
    border-radius: 20px;
    padding: 26px;
    flex-direction: row;
  }
  .pin {
    position: static;
    transform: none;
    width: auto;
    opacity: 1;
  }
  .hub.is-on .pin {
    animation: none;
  }
}

@media (max-width: 480px) {
  .pin__name {
    font-size: 0.78rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hub__wire {
    stroke-dashoffset: 0;
    animation: none !important;
  }
  .pin {
    opacity: 1;
    animation: none !important;
  }
}
