/* ==========================================================================
   LEXORA — GTM infrastructure for consumer brands selling B2B
   Square corners, hairline rules, corner "ticks", a pinned horizontal
   timeline. Hedvig Letters Serif display, Inter body, #0C0C0D primary,
   #1F6F63 accent. Tokens first, then one block per section, in page order.
   ========================================================================== */

/* -------------------------------- fonts ---------------------------------
   Self-hosted, from assets/fonts/. They used to come from Google's CDN, which
   sends every visitor's IP to Google on the first paint, before any consent
   could be asked for -- the thing LG München 3 O 17493/20 is about. These are
   the same files Google serves (woff2, downloaded from fonts.gstatic.com),
   split into the two latin subsets with Google's own unicode ranges, so a
   page with no eastern-european characters never fetches the second file.

   Both are variable fonts: Inter carries a weight axis (100-900, so the three
   weights the site uses come out of one file), Hedvig an optical-size axis.
   font-display: swap keeps text readable while they load.

   To update: fetch the css2 URL with a current browser user agent, take the
   woff2 links for latin and latin-ext, and replace the files. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/inter-latin.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: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/inter-latin-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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Hedvig Letters Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/hedvig-letters-serif-latin.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: "Hedvig Letters Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/hedvig-letters-serif-latin-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-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ------------------------------- tokens --------------------------------- */
:root {
  /* type */
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-heading: "Hedvig Letters Serif", Georgia, "Times New Roman", serif;

  --h1-size: 3.5rem;  --h1-leading: 1.2;
  --h2-size: 3rem;    --h2-leading: 1.2;
  --h3-size: 2.25rem; --h3-leading: 1.2;
  --h4-size: 1.75rem; --h4-leading: 1.3;
  --heading-tracking: -.01em;
  --tagline-tracking: .05em;
  --body-leading: 1.5;

  --text-tiny: .75rem;
  --text-small: .875rem;
  --text-regular: 1rem;
  --text-medium: 1.125rem;
  --text-xlarge: 1.25rem;
  --text-large: 1.375rem;
  --text-huge: 2rem;

  /* colour — LEXORA
     primary #0C0C0D, accent #1F6F63. The teal clears 5.98:1 against white in
     both directions, so unlike the previous orange it needs no darkened
     variant to carry text, and a filled accent surface carries WHITE.
     The neutrals below are mirrored cool (R and B swapped, green untouched, so
     luminance and every measured contrast hold) — they were warm-biased to sit
     under the orange and fought the teal. */
  --brand-primary: #0c0c0d;
  --brand-accent: #1f6f63;
  --brand-accent-deep: #1a5d53;   /* hover / pressed */
  --brand-accent-ink: #1f6f63;    /* accent as *text* on light: 6.0:1 */
  /* the text colour a FILLED accent surface carries — white here, at 5.98:1.
     A light accent flips this back to near-black; ?accent reports which. */
  --brand-accent-on: #ffffff;

  --color-bg-page: #fff;
  --color-bg-section: #f6f7f8;
  --color-bg-section-alt: #f5f6f7;
  --color-bg-subtle: #fbfcfc;
  --color-bg-tool-band: #f2f4f6;
  --color-badge-bg: #eff7f6;
  --color-badge-border: #cbe4e0;

  --color-ink: #292a2b;
  --color-body: #292a2b;
  --color-headline: var(--brand-primary);
  --color-headline-invert: #fcfcfc;
  --color-muted: #696c6f;
  --color-muted-meta: #5c5f62;
  --color-muted-text: #515457;
  --color-neutral-darkest: var(--brand-primary);
  --color-neutral-light: #b3b6b9;

  --color-line: #dde0e3;
  --color-line-card: #e0e4e8;
  --color-line-soft: #e5e8eb;
  --color-line-divider: #d1d5d9;
  --color-line-input: #dde0e3;

  --color-accent: var(--brand-accent);
  --color-ink-strong: #1c1d1e;
  /* the accent tint for ANY near-black ground — the hero photograph and the
     footer both. The raw accent manages only 3.3:1 there, so surfaces on dark
     must use this, never --brand-accent. */
  --color-link-on-dark: #7faca6;
  --color-dark-bg: var(--brand-primary);
  --color-dark-card: #1c1b1c;
  --color-dark-panel: #161516;
  --color-dark-border: #2b2c2e;

  --color-footer-bg: var(--brand-primary);
  --color-footer-text: #e3e6e9;
  --color-footer-heading: #fafbfc;
  --color-footer-tag: var(--color-link-on-dark);   /* 3.3:1 with the raw accent */
  --color-footer-divider: #2f3437;

  --color-white-12: #ffffff1f;
  --color-white-25: #ffffff40;
  --color-white-60: #fff9;
  --color-white-80: #fffc;

  /* buttons */
  --btn-height: 3rem;
  --btn-primary-bg: #fff;
  --btn-primary-text: var(--brand-primary);
  --btn-primary-hover-bg: var(--brand-accent);
  --btn-primary-hover-text: var(--brand-accent-on);
  --btn-dark-bg: var(--brand-primary);

  /* layout */
  --container-max: 80rem;
  --section-pad: 6.25rem;   /* 100px block */
  --section-inline: 5rem;   /* 80px inline */
  --section-gap-mobile: 4rem;
  --nav-height: 3.75rem;
  --radius-full: 999px;
  --z-nav: 100;

  /* motion */
  --duration-fast: .2s;
  --duration-base: .4s;
  --duration-slow: .7s;
  --duration-reveal: .9s;
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --stagger-step: 60ms;
  --sig-duration: 9s;
  /* the problem scenes' loop: one cycle, one curve */
  --loop-time: 8s;
  --loop-ease: cubic-bezier(.32, .72, 0, 1);
  --popup-speed: .15s;
  --popup-ease: cubic-bezier(.65, 0, .35, 1);
}

/* ------------------------------- reset ---------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
html.no-scroll { overflow: hidden; }
body {
  margin: 0;
  background: var(--color-bg-page);
  color: var(--color-body);
  font-family: var(--font-body);
  font-size: var(--text-regular);
  line-height: var(--body-leading);
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul, ol { margin: 0; padding: 0; list-style: none; }
p { margin: 0; }
h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: 400;
  color: var(--color-headline);
  letter-spacing: var(--heading-tracking);
}
h1 { font-size: var(--h1-size); line-height: var(--h1-leading); }
h2 { font-size: var(--h2-size); line-height: var(--h2-leading); }
h3 { font-family: var(--font-body); font-size: var(--text-large); line-height: 1.3; color: var(--color-ink); }

.skip-link {
  position: fixed; top: .5rem; left: .5rem; z-index: 101;
  padding: .5rem 1rem; background: #fff; color: var(--color-ink);
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }

/* section rhythm */
.rail { padding: var(--section-pad) var(--section-inline); }
.container { max-width: var(--container-max); margin-inline: auto; }

/* corner ticks — the small hairline crosses at box corners */
.ticks { position: relative; }
.ticks > .tick-b { position: absolute; inset: 0; pointer-events: none; }
.ticks > .tick-b::before,
.ticks > .tick-b::after {
  content: ""; position: absolute; width: 9px; height: 9px;
  border-color: var(--brand-accent); border-style: solid;
}
.ticks > .tick-b::before { top: -1px; left: -1px; border-width: 1px 0 0 1px; }
.ticks > .tick-b::after  { bottom: -1px; right: -1px; border-width: 0 1px 1px 0; }
/* Specificity, not decoration: the base rule above is `.ticks > .tick-b::before`
   (0,2,1), so a bare `.tick-b--light::before` (0,1,1) lost and every "light"
   tick was drawn in raw accent teal on near-black -- 3.3:1, the exact case
   the colour comments warn against. Matching the base selector fixes it. */
.ticks > .tick-b--light::before, .ticks > .tick-b--light::after { border-color: var(--color-white-25); }

/* noise overlay used on the dark surfaces */
.noise { position: relative; }
.noise::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .35;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='.06'/%3E%3C/svg%3E");
}

/* ------------------------------- buttons -------------------------------- */
.btn {
  display: inline-flex; align-items: center; gap: 1rem;
  height: var(--btn-height); padding-left: 20px;
  border: 1px solid var(--btn-primary-bg);
  background: var(--btn-primary-bg); color: var(--btn-primary-text);
  font-size: var(--text-regular); font-weight: 500;
  transition: background var(--duration-fast), color var(--duration-fast), border-color var(--duration-fast);
}
.btn__tile {
  display: grid; place-items: center;
  width: 46px; height: calc(var(--btn-height) - 2px);
  background: var(--color-neutral-darkest); color: #fff;
  transition: background var(--duration-fast);
}
.btn--light:hover { background: var(--btn-primary-hover-bg); color: var(--btn-primary-hover-text); border-color: var(--btn-primary-hover-bg); }
.btn--light:hover .btn__tile { background: var(--brand-accent-deep); }

.arrow-link {
  display: inline-flex; align-items: center; gap: .25rem;
  font-size: var(--text-small); color: var(--color-muted-text);
  border-bottom: 1px solid transparent;
  transition: color var(--duration-fast), border-color var(--duration-fast);
}
.arrow-link:hover { color: var(--brand-accent-ink); border-color: currentColor; }
.arrow-link--dark { color: var(--color-headline); font-size: var(--text-regular); }
.arr { transition: transform var(--duration-fast); }
a:hover > .arr { transform: translate(2px, -2px); }

/* ================================ HEADER ================================= */
/* The header carries an ink variable and the ground it sits on. Over the hero
   the ink is white on near-black; the moment the page scrolls, the mobile menu
   opens, or ANY dropdown opens, the bar turns white and the pair swaps.
   --nav-ground exists so anything that FILLS with --nav-ink can put the right
   colour back on top without re-deriving it through the same selector chain --
   that chain is easy to get wrong, and a white label on a white fill is
   invisible rather than merely ugly. */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: var(--z-nav);
  --nav-ink: var(--color-ink);
  --nav-ground: #fff;
  color: var(--nav-ink);
  transition: background-color var(--duration-fast) var(--ease-out);
}
.site-header--solid,
.site-header.is-scrolled,
.site-header.menu-open,
.site-header.nav-open { background: #fff; }

.site-header--overlay:not(.is-scrolled):not(.menu-open):not(.nav-open) {
  --nav-ink: #fff;
  --nav-ground: var(--brand-primary);
}

.bar {
  display: flex; align-items: center; gap: 2rem;
  height: var(--nav-height);
  padding: 8px 16px;
}
/* Logo: the supplied lockup, white over the hero and navy once the header
   turns solid. Both files are in the DOM and swapped with display, matching
   the states that drive --nav-ink. Sources are trimmed to their ink bounds,
   so the height below is the actual cap height of the mark. */
/* The griffin overshoots the letters top and bottom — the wordmark is only
   ~71.5% of the lockup's height. So the height set here is NOT the perceived
   size: 30px of lockup reads as a 21.5px cap height next to the 14px nav. */
.logo { display: inline-flex; align-items: center; }
.logo img { height: 30px; width: auto; }
/* class-only selectors here would lose to `.logo img`, so both variants are
   qualified to keep every rule in this swap at the same specificity */
.logo .logo-light { display: block; }
.logo .logo-dark { display: none; }

.site-header.is-scrolled .logo-light,
.site-header.menu-open .logo-light,
.site-header.nav-open .logo-light,
.site-header:not(.site-header--overlay) .logo-light { display: none; }

.site-header.is-scrolled .logo-dark,
.site-header.menu-open .logo-dark,
.site-header.nav-open .logo-dark,
.site-header:not(.site-header--overlay) .logo-dark { display: block; }

.logo--footer img { height: 36px; }

.nav { margin-inline: auto; }
.links { display: flex; align-items: center; gap: 2.5rem; }
.link-item { position: static; }
.link {
  display: inline-flex; align-items: center; gap: .375rem;
  height: var(--nav-height); line-height: 1.2;
  font-size: var(--text-small); color: var(--nav-ink);
  transition: color var(--duration-fast);
}
button.link { cursor: pointer; }
.link:hover, .link:active { color: var(--brand-accent-ink); }
/* over the hero the accent is too dark to read — use the light tint */
.site-header--overlay:not(.is-scrolled):not(.menu-open):not(.nav-open) .link:hover,
.site-header--overlay:not(.is-scrolled):not(.menu-open):not(.nav-open) .link:active { color: var(--color-link-on-dark); }
.link-item.is-open .link { color: var(--brand-accent-ink); }
/* while one link is hovered, the others fall back to plain ink */
.links:has(.link:hover) .link:not(:hover) { color: var(--nav-ink); }

.nav-caret {
  width: 7px; height: 7px; margin-top: -3px;
  border-right: 1px solid currentColor; border-bottom: 1px solid currentColor;
  transform: rotate(45deg); opacity: .7;
  transition: transform var(--duration-fast);
}
/* open menu: the caret turns to point up rather than staying down. Rotating
   the same 7px corner from 45deg to -135deg keeps it one element, and
   margin-top compensates for the box pivoting about its centre. */
.link-item.is-open .nav-caret { transform: rotate(-135deg); margin-top: 2px; }

/* ============================ MEGA MENU POPUP ============================
   attio.com's construction, squared off. One card serves every menu: rather
   than swapping panels it animates its own width, height and x-position to
   whichever menu is active, with the panels stacked in a single grid cell so
   the outgoing and incoming overlap. The incoming panel slides in from the
   direction you travelled. Their timing exactly: 0.15s, cubic-bezier(.65,0,.35,1).
   Theirs is a 16px-rounded card; ours is square with the site's hairline. */
.popup {
  position: absolute; top: var(--nav-height); left: 0;
  padding-top: .5rem;
  opacity: 0; visibility: hidden; pointer-events: none;
  /* the standalone `translate` property, as attio.com uses — it animates
     independently of any transform the panels apply */
  translate: var(--popup-x, 0) 0;
  transition: opacity var(--popup-speed) var(--popup-ease),
              visibility var(--popup-speed) var(--popup-ease),
              translate var(--popup-speed) var(--popup-ease);
}
.site-header.nav-open .popup { opacity: 1; visibility: visible; pointer-events: auto; }

.popup__card {
  width: var(--popup-width, 40rem); height: var(--popup-height, 20rem);
  overflow: hidden;
  background: #fff; border: 1px solid var(--color-line);
  box-shadow: 0 18px 50px rgba(12, 12, 13, .10);
  transition: width var(--popup-speed) var(--popup-ease),
              height var(--popup-speed) var(--popup-ease);
}
/* every panel occupies the same cell, so they cross over rather than reflow */
.popup__stack { display: grid; }
.popup__panel {
  grid-area: 1 / 1; width: max-content; max-width: calc(100vw - 4rem);
  opacity: 0; pointer-events: none;
  transition: opacity var(--popup-speed) var(--popup-ease),
              transform var(--popup-speed) var(--popup-ease);
}
.popup__panel[data-active] { opacity: 1; pointer-events: auto; transform: none; }
/* direction of travel: the new panel enters from the side you came from */
.popup[data-dir="right"] .popup__panel:not([data-active]) { transform: translateX(1.5rem); }
.popup[data-dir="left"]  .popup__panel:not([data-active]) { transform: translateX(-1.5rem); }

.popup__cols { display: flex; align-items: stretch; }
/* Columns size to their own content within bounds, so each menu gets a genuinely
   different card width and the morph has something to travel. Left at flex:1 they
   inherited the old full-bleed behaviour and blew the card out to 2320px. */
.popup__cols .dropdown__col {
  flex: 0 0 auto; min-width: 12rem;
  outline: 1px solid var(--color-line); outline-offset: -.5px;
}

/* These were removed with the old full-bleed dropdown block by mistake. Without
   them the items laid out in a row instead of a column, so a panel measured
   1979x48 and the card fell back to its 40rem/20rem defaults. */
.dropdown__header {
  margin: 0; padding: .75rem 1.5rem;
  font-size: var(--text-small); text-transform: uppercase; letter-spacing: .02em;
  color: var(--color-muted); border-bottom: 1px solid var(--color-line-divider);
  transition: color var(--duration-fast);
}
.dropdown__header--link { display: block; }
.dropdown__header--link:hover { color: var(--brand-accent-ink); }
.dropdown__col:has(.dropdown__item:hover) .dropdown__header { color: var(--brand-accent-ink); }
/* Rules between the items instead of gap, running the full column width so
   they meet the column dividers and the panel reads as one grid rather than
   floating text. Same hairline weight as the column outline — one rule weight
   throughout is what keeps it from looking busy. */
.dropdown__items { display: flex; flex-direction: column; gap: 0; padding: 0; }
.dropdown__item {
  display: flex; flex-direction: column; gap: .25rem;
  padding: 1rem 1.5rem;
}
.dropdown__item + .dropdown__item { border-top: 1px solid var(--color-line); }
.dropdown__item:hover .dropdown__title,
.dropdown__item:hover .dropdown__subtitle { color: var(--brand-accent-ink); }
/* nowrap on purpose: the columns then take the width of their longest label,
   so each menu gets a different card size and the morph has something to do.
   Wrapped, every column hit the same cap and all three cards were 816x305 —
   the animation was running but had nowhere to travel. */
.popup__cols .dropdown__title,
.popup__cols .dropdown__subtitle { white-space: nowrap; }

/* right side */
.actions { display: flex; align-items: center; gap: .75rem; }

.pill {
  display: inline-flex; align-items: center;
  padding: 12px 24px; font-size: var(--text-small);
  border: 1px solid currentColor;
  transition: background var(--duration-fast), color var(--duration-fast), border-color var(--duration-fast);
}
.pill--login { background: transparent; border-color: var(--color-line); color: var(--color-ink); }
.pill--login:hover { border-color: var(--color-ink); }
.pill--cta { background: var(--brand-primary); color: #fff; border-color: var(--brand-primary); }
.pill--cta:hover { background: var(--brand-accent); color: var(--brand-accent-on); border-color: var(--brand-accent); }

/* over the hero the pills invert */
.site-header--overlay:not(.is-scrolled):not(.menu-open):not(.nav-open) .pill--login {
  background: rgba(0, 0, 0, .1); border-color: #fff; color: #fff;
}
.site-header--overlay:not(.is-scrolled):not(.menu-open):not(.nav-open) .pill--login:hover {
  border-color: var(--color-link-on-dark); color: var(--color-link-on-dark);
}
.site-header--overlay:not(.is-scrolled):not(.menu-open):not(.nav-open) .pill--cta {
  background: #fff; border-color: #fff; color: var(--color-neutral-darkest);
}
.site-header--overlay:not(.is-scrolled):not(.menu-open):not(.nav-open) .pill--cta:hover {
  background: var(--brand-accent); border-color: var(--brand-accent); color: var(--brand-accent-on);
}

.menu-toggle { display: none; color: var(--nav-ink); width: 28px; height: 28px; flex-direction: column; justify-content: center; gap: 6px; }
.menu-toggle span { display: block; height: 1px; background: currentColor; }

/* mobile menu */
.mobile { display: none; background: #fff; color: var(--color-ink); border-top: 1px solid var(--color-line-soft); padding: 1rem; max-height: calc(100vh - var(--nav-height)); overflow: auto; }
.mobile-row {
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  padding: .875rem 0; border-bottom: 1px solid var(--color-line-soft);
  font-size: var(--text-medium); text-align: left;
}
.mobile-group { display: none; padding: .5rem 0 1rem; }
.mobile-group.is-open { display: block; }
.mobile-group__item { display: block; padding: .5rem 0; font-size: var(--text-small); color: var(--color-muted-text); }
.mobile-group__header { margin: .5rem 0 0; font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); text-transform: uppercase; color: var(--color-muted); }
.mobile-actions { display: flex; gap: .75rem; padding: 1rem 0; }
.mobile-actions .pill { flex: 1; justify-content: center; }
.mobile-actions .pill--login { background: transparent; border-color: var(--color-line); }
.mobile-actions .pill--cta { background: var(--color-neutral-darkest); color: #fff; border-color: var(--color-neutral-darkest); }
.mobile-langs { display: flex; padding-bottom: .5rem; }
.mobile-langs .lang { --nav-ink: var(--color-ink); font-size: var(--text-small); }

/* ================================= HERO ================================== */
.hero {
  position: relative; display: flex; flex-direction: column; justify-content: flex-end;
  min-height: 100svh; padding: calc(var(--nav-height) + 2rem) var(--section-inline) 0;
  color: #fff; overflow: hidden;
}
.hero__bg {
  position: absolute; inset: 0; overflow: hidden;
  /* The poster sits under the video so the hero is never empty — during load,
     if the file fails, and under reduced motion where the video is pulled.
     The gradients stay as the last fallback beneath both. */
  background-image:
    url("assets/hero-poster.jpg"),
    radial-gradient(120% 90% at 78% 28%, #7a6a5c 0%, #3a332e 42%, #161413 78%),
    linear-gradient(200deg, #211d1a 0%, #0c0c0d 100%);
  background-size: cover; background-position: center;
}
.hero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  display: block; pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  /* leaves the poster showing — a still hero rather than no hero */
  .hero__video { display: none; }
}
/* Three scrims, each sized from a measurement rather than by eye. Sampling 24
   frames of hero.mp4 gave the worst-case luminance behind each text zone, and
   the alpha each needs to clear AA: subline .46, the case-studies link .61,
   the logo-bar label .79, the nav .61. The headline needs none — large white
   type only has to clear 3:1. The horizontal gradient alone left the bottom
   bar and the nav short, hence the top and bottom scrims.
   Re-measure if the video is ever swapped: a brighter clip breaks this. */
.hero__shade {
  position: absolute; inset: 0;
  background:
    /* nav */
    linear-gradient(to bottom, rgba(12, 12, 13, .70) 0%, transparent 18%),
    /* logo bar */
    linear-gradient(to top, rgba(12, 12, 13, .88) 0%, rgba(12, 12, 13, .88) 12%, transparent 34%),
    /* headline / subline side */
    linear-gradient(90deg, rgba(12, 12, 13, .92) 0%, rgba(12, 12, 13, .66) 45%, rgba(12, 12, 13, .34) 100%);
}
.hero__copy { position: relative; display: flex; flex-direction: column; gap: 20px; max-width: 38rem; padding-bottom: 6rem; }
.hero__h1 { color: #fff; }
/* the descriptor above the h1: the same eyebrow every sub page opens with, in
   the accent tint that clears 4.5:1 on the hero. A serif line under the h1
   was tried first and competed with it -- two heading-face lines read as a
   two-part headline, not headline plus category. */
.hero__eyebrow {
  font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking);
  text-transform: uppercase; color: var(--color-link-on-dark);
}
.hero__sub { font-size: var(--text-xlarge); line-height: 1.2; color: var(--color-white-80); }
.hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.75rem; margin-top: .5rem; }
/* the secondary action is a text link, white, with the site's arrow idiom;
   it points down because it scrolls to the system section on this page */
.hero__more {
  display: inline-flex; align-items: center; gap: .375rem;
  font-size: var(--text-regular); color: #fff;
  border-bottom: 1px solid var(--color-white-25);
  transition: border-color var(--duration-fast), color var(--duration-fast);
}
.hero__more:hover { color: var(--color-link-on-dark); border-color: currentColor; }
.hero__more .arr { transition: transform var(--duration-fast); }
.hero__more:hover .arr { transform: translateY(2px); }

/* ============================== SIGNAL STRIP =============================
   Sits at the hero's foot where the trust bar used to be. Deliberately not a
   placed graphic: it is one hairline, a tick rule, five square nodes and a
   travelling accent marker — the same primitives as the rest of the page, so
   it stays sharp and legible at any width with no viewBox or crop tricks, and
   picks up the brand tokens for free. */
.sig {
  position: relative;
  margin-inline: calc(var(--section-inline) * -1);
  padding: 1.5rem var(--section-inline) 1.375rem;
  border-top: 1px solid var(--color-white-12);
}
.sig__band { position: relative; }

/* the rule the whole thing hangs on, with a faint measuring tick pattern */
.sig__band::before {
  content: ""; position: absolute; left: 0; right: 0; top: 4px; height: 1px;
  background:
    repeating-linear-gradient(to right,
      rgba(255, 255, 255, .22) 0 1px, transparent 1px 14px),
    var(--color-white-12);
}

/* Stages are placed on exact quarter points rather than distributed with
   space-between — that spaced the *boxes*, so the wider labels ("Message")
   pushed the nodes off the even intervals and the pass highlight stopped
   lining up with the runner. */
.sig__track {
  position: relative; height: 2.0625rem;
  margin: 0; padding: 0; list-style: none;
}
.sig__stage {
  position: absolute; top: 0; left: calc(var(--i) * 25%);
  display: flex; flex-direction: column; align-items: flex-start; gap: .875rem;
}
.sig__stage--end { left: auto; right: 0; align-items: flex-end; }

.sig__node {
  width: 9px; height: 9px; margin-top: 0;
  border: 1px solid rgba(255, 255, 255, .55);
  background: var(--brand-primary);
  transition: none;
  animation: sig-pass var(--sig-duration) linear infinite;
  animation-delay: calc(var(--i) * var(--sig-duration) / 4);
}
.sig__stage--end .sig__node { background: var(--color-link-on-dark); border-color: var(--color-link-on-dark); }

.sig__label {
  font-size: .625rem; letter-spacing: var(--tagline-tracking);
  text-transform: uppercase; color: var(--color-neutral-light);
  white-space: nowrap; line-height: 1;
}
.sig__stage--end .sig__label { color: var(--color-link-on-dark); }   /* on the dark hero */

/* one accent marker running the length of the rule */
.sig__runner {
  position: absolute; top: 0; left: 0; width: 9px; height: 9px;
  background: var(--color-link-on-dark);
  animation: sig-run var(--sig-duration) linear infinite;
}
.sig__runner::after {
  content: ""; position: absolute; right: 100%; top: 4px; width: 4.5rem; height: 1px;
  background: linear-gradient(to left, var(--color-link-on-dark), transparent);
}

@keyframes sig-run { from { left: 0; } to { left: calc(100% - 9px); } }
@keyframes sig-pass {
  0%, 100% { border-color: rgba(255, 255, 255, .55); }
  2%       { border-color: var(--color-link-on-dark); }
  14%      { border-color: rgba(255, 255, 255, .55); }
}

@media (max-width: 900px) {
  /* four labels do not fit; the rule, the nodes and the runner still read */
  .sig { padding-block: 1.25rem 1.125rem; }
  .sig__stage:not(.sig__stage--end):not(:first-child) .sig__label { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .sig__node, .sig__runner { animation: none; }
  .sig__runner { display: none; }
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ================================ PROBLEMS ===============================
   Three cards after oxygen-agent.com: a diagram scene on top, title and copy
   below, the card itself a soft glass surface (a faint gradient, a low
   shadow, a white inset edge), and the scene built from real elements with
   depth, small chips and boxes that cast a shadow, not flat lines. Kept
   square, like everything else on the site; theirs are rounded.

   Each scene is HTML in src/_includes/prob-*.njk, laid out in container-query
   units (cqw, 1% of the scene's width) on a 16:9 ground, so it scales with
   the card and the spoke angles stay true. Each has its own motion, running
   only while on screen (.is-in from main.js): the scattered chips snap into a
   grid every 8s and a map frame appears; dots travel every spoke inward to
   the founder without pause; the gaps in the wiring close every 8s. Under
   prefers-reduced-motion everything rests in its problem state. */
.problems__inner { display: flex; flex-direction: column; gap: 64px; max-width: var(--container-max); margin-inline: auto; }
.problems__header { display: flex; flex-direction: column; gap: 12px; }
.problems__header h2 { max-width: 44rem; }
.problems__lede { max-width: 44rem; font-size: var(--text-medium); color: var(--color-muted-text); }
.problems__row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
.problems__card {
  display: flex; flex-direction: column;
  border: 1px solid var(--color-line-card);
  background: linear-gradient(160deg, #fff 0%, #f7f9f9 60%, #f2f5f5 100%);
  box-shadow:
    0 1px 2px rgba(12, 12, 13, .03),
    0 18px 40px -28px rgba(12, 12, 13, .22),
    inset 0 1px 0 #fff;
}
/* the ground under every scene: a fine dot grid, fading out at the edges,
   so the elements read as placed on something rather than floating */
.problems__vis {
  padding: 1.25rem 1.25rem 1rem;
  background-image: radial-gradient(rgba(12, 12, 13, .13) 1px, transparent 1.2px);
  background-size: 14px 14px; background-position: 7px 7px;
  mask-image: radial-gradient(ellipse 70% 80% at 50% 50%, #000 55%, transparent 100%);
}
.problems__text { display: flex; flex-direction: column; gap: .75rem; padding: .75rem 1.5rem 1.75rem; }
.problems__text p:last-child { font-size: var(--text-regular); color: var(--color-muted-text); }
.problems__idx { font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); text-transform: uppercase; color: var(--brand-accent-ink); }

/* --- the scene ground: a 16:9 box, everything inside positioned in cqw --- */
.scene {
  position: relative; container-type: inline-size; aspect-ratio: 16 / 9; overflow: visible;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .06em; text-transform: uppercase; line-height: 1;
  color: var(--color-muted-text);
  --chip-shadow: 0 1px 1px rgba(12, 12, 13, .05), 0 6px 14px -8px rgba(12, 12, 13, .22);
}
/* cqw on the children measures the scene; on .scene itself it would measure
   the next container up, which is none, so the font size lives here */
.scene > * { position: absolute; left: var(--x, 0); top: var(--y, 0); font-size: 2.8cqw; }
.scene .chip, .scene .node, .scene .tool, .scene .hub {
  display: inline-flex; align-items: center; justify-content: center; gap: 1.6cqw;
  background: #fff; border: 1px solid var(--color-line-card);
  box-shadow: var(--chip-shadow); white-space: nowrap;
}
.scene svg { width: 3.6cqw; height: 3.6cqw; fill: none; stroke: currentColor; stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; }

/* --- 01 market: chips, scatter to grid --- */
.scene .chip { min-width: 18cqw; height: 7.5cqw; padding: 0 1.5cqw; }
.scene .chip--fit { border-color: var(--brand-accent); color: var(--brand-accent-ink); }
.scene__frame {
  left: 4cqw; top: 6cqw; width: 91.5cqw; height: 43.5cqw;
  border: 1px dashed var(--brand-accent); opacity: 0;
}
.scene .chip { animation: chip-settle var(--loop-time) var(--loop-ease) var(--loop-d, 0s) infinite paused; }
.scene__frame { animation: frame-show var(--loop-time) var(--loop-ease) var(--loop-d, 0s) infinite paused; }
.scene.is-in .chip, .scene.is-in .scene__frame { animation-play-state: running; }
@keyframes chip-settle {
  0%, 38%   { transform: translate(var(--tx), var(--ty)) rotate(var(--r)); }
  48%, 86%  { transform: none; }
  96%, 100% { transform: translate(var(--tx), var(--ty)) rotate(var(--r)); }
}
@keyframes frame-show {
  0%, 44%   { opacity: 0; }
  52%, 84%  { opacity: 1; }
  92%, 100% { opacity: 0; }
}

/* --- 02 hub: spokes with travelling dots, nodes with counts, the founder --- */
.scene .spoke {
  left: 50cqw; top: 28.125cqw; width: var(--l); height: 1px;
  background: var(--color-line-divider);
  transform-origin: 0 50%; transform: rotate(var(--a));
}
.scene .spoke__dot {
  position: absolute; top: 50%; left: 100%;
  width: 1.8cqw; height: 1.8cqw; margin: -.9cqw 0 0 -.9cqw;
  background: var(--brand-accent);
  animation: dot-travel 2.4s cubic-bezier(.4, 0, .6, 1) var(--d, 0s) infinite paused;
}
.scene.is-in .spoke__dot { animation-play-state: running; }
@keyframes dot-travel {
  0%   { left: 100%; opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { left: 6%; opacity: 0; }
}
.scene .node { min-width: 24cqw; height: 8cqw; padding: 0 2.5cqw; transform: translate(-50%, -50%); }
.scene .node__badge {
  position: absolute; right: -1.5cqw; top: -3cqw;
  min-width: 6cqw; height: 4.6cqw; padding: 0 1.2cqw;
  display: grid; place-items: center;
  background: var(--brand-accent); color: #fff; font-weight: 500; letter-spacing: 0;
  box-shadow: var(--chip-shadow);
}
.scene .hub {
  left: 50cqw; top: 28.125cqw; width: 26cqw; height: 9.5cqw;
  transform: translate(-50%, -50%);
  border-color: var(--color-ink); color: var(--color-ink);
  box-shadow: var(--chip-shadow), 0 0 0 4cqw rgba(255, 255, 255, .55);
}

/* --- 03 data: tool boxes and broken wiring --- */
.scene .tool { width: 36cqw; height: 10cqw; padding: 0 1cqw; }
/* each wire is two ink stubs with a gap of a third in the middle; the accent
   piece that fills the gap is the moving part */
.scene .wire { display: block; }
.scene .wire--h { width: 12cqw; height: 1px; }
.scene .wire--v { width: 1px; height: 24cqw; }
.scene .wire::before, .scene .wire::after { content: ""; position: absolute; background: var(--color-ink); }
.scene .wire--h::before, .scene .wire--h::after { top: 0; width: 33%; height: 1px; }
.scene .wire--h::before { left: 0; } .wire--h::after { right: 0; }
.scene .wire--v::before, .scene .wire--v::after { left: 0; height: 33%; width: 1px; }
.scene .wire--v::before { top: 0; } .wire--v::after { bottom: 0; }
.scene .wire b {
  position: absolute; display: block; background: var(--brand-accent); opacity: 0;
  animation: gap-close var(--loop-time) var(--loop-ease) var(--loop-d, 0s) infinite paused;
}
.scene .wire--h b { left: 33%; top: -1px; width: 34%; height: 3px; }
.scene .wire--v b { top: 33%; left: -1px; height: 34%; width: 3px; }
.scene.is-in .wire b { animation-play-state: running; }
@keyframes gap-close {
  0%, 38%   { opacity: 0; }
  48%, 86%  { opacity: 1; }
  96%, 100% { opacity: 0; }
}
.problems__card:nth-child(3) .scene { --loop-d: -4s; }

@media (prefers-reduced-motion: reduce) {
  .scene .chip, .scene .scene__frame, .scene .spoke__dot, .scene .wire b { animation: none; }
  .scene .chip { transform: translate(var(--tx), var(--ty)) rotate(var(--r)); }
  .scene .spoke__dot { display: none; }
}

/* =============================== TRUST WALL ==============================
   A bar, not a section: half the block padding, the heading set as a caption
   in tracked caps rather than a display line, and under it a wall of client
   tiles on an over-wide track that scrolls (clay.com's construction, squared
   off: sharp corners, one hairline, no shadow). The track is duplicated in
   main.js so translateX(-50%) lands exactly on the seam. Client names are set
   as text rather than logo files: no assets to license or keep current, and it
   sits closer to the page's typographic character. */
.trust { padding-block: 4rem; border-bottom: 1px solid var(--color-line); }
.trust__head { margin-bottom: 2.5rem; }
.trust__title {
  max-width: none; text-align: center;
  font-family: var(--font-body); font-size: var(--text-tiny); font-weight: 500; line-height: 1.5;
  letter-spacing: var(--tagline-tracking); text-transform: uppercase; color: var(--color-muted);
}
.mosaic__viewport {
  overflow: hidden;
  margin-inline: calc(var(--section-inline) * -1);
  /* fade the cut edges so the track reads as continuing, not clipped */
  mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.mosaic__grid {
  display: grid; grid-auto-flow: column dense;
  grid-template-rows: repeat(2, 5.5rem);
  /* fixed columns, 11rem so the longer marks do not wrap; auto would size
     each column to the widest item crossing it */
  grid-auto-columns: 11rem;
  gap: 12px; width: max-content;
  margin: 0; padding: 0 var(--section-inline); list-style: none;
  animation: mosaic-run 72s linear infinite;
}
.mosaic__viewport:hover .mosaic__grid,
.mosaic__viewport:focus-within .mosaic__grid { animation-play-state: paused; }
@keyframes mosaic-run { to { transform: translateX(-50%); } }

.tile {
  display: grid; place-content: center; gap: .25rem;
  padding: 1rem 1.25rem; text-align: center;
  background: var(--color-bg-page);
  border: 1px solid var(--color-line-card);
}
.tile__mark { font-size: 1.0625rem; font-weight: 600; letter-spacing: .01em; color: var(--color-ink); }
.tile__note { font-size: var(--text-small); color: var(--color-muted); }

@media (prefers-reduced-motion: reduce) {
  .mosaic__grid { animation: none; }
  .mosaic__viewport { overflow-x: auto; }
}
@media (max-width: 640px) {
  .mosaic__grid { grid-template-rows: repeat(2, 5rem); grid-auto-columns: 9.5rem; }
  .tile { padding: .75rem 1rem; }
}

/* ========================== SECTION HEADING HELPERS ====================== */
.sh__title { max-width: 44rem; }

/* ================================ DARK CTA =============================== */
.cta { background: var(--color-dark-bg); color: var(--color-neutral-light); padding: 60px var(--section-inline); }
.cta__frame { max-width: var(--container-max); margin-inline: auto; }
.cta__box { border: 1px solid var(--color-dark-border); }
.cta__photo-layout { display: flex; align-items: stretch; gap: 40px; }
.cta__photo {
  position: relative; flex: 0 0 22rem; min-height: 20rem;
  background: radial-gradient(90% 80% at 60% 30%, #443a33 0%, #1f1b19 60%, #0c0c0d 100%);
}
.cta__photo-name { position: absolute; left: 1.5rem; bottom: 1.5rem; font-size: var(--text-small); color: #fff; }
.cta__photo-name i { font-style: normal; color: var(--color-white-60); }
.cta__copy { display: flex; flex-direction: column; justify-content: center; align-items: flex-start; gap: 2rem; padding: 3rem 3rem 3rem 0; }
.cta__copy h2 { color: var(--color-headline-invert); }

/* =============================== INSIGHTS ================================ */
.insights__inner { max-width: var(--container-max); margin-inline: auto; }
.insights__head { display: flex; flex-direction: column; gap: 1rem; margin-bottom: 3.5rem; }
.insights__lede { max-width: 42rem; font-size: var(--text-medium); color: var(--color-muted-text); }
.insights__cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
.post { display: flex; flex-direction: column; gap: .625rem; height: 100%; }
.post__media {
  height: 11rem; background: linear-gradient(150deg, #e6edec, #c5d2d0);
  border: 1px solid var(--color-line-card);
  transition: opacity var(--duration-fast);
}
.post:hover .post__media { opacity: .8; }
.post__tag { font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); text-transform: uppercase; color: var(--brand-accent-ink); }
.post__title { font-family: var(--font-body); font-size: var(--text-medium); line-height: 1.35; color: var(--color-headline); }
.post__excerpt { font-size: var(--text-small); color: var(--color-muted-text); }
.post__meta { margin-top: auto; padding-top: .75rem; font-size: var(--text-small); color: var(--color-muted-meta); }
.insights__more { margin-top: 3rem; }

/* ============================ MID-PAGE / FINAL CTA =======================
   The old newsletter block's composition (tempo.xyz, squared off): one image
   filling an inset frame, the heading top-left, the copy and the action
   bottom-right. Used twice on the homepage, mid-page and as the closer.

   Dark type over the picture: measured across a 4x4 grid the photograph runs
   0.34-0.82 luminance, never dark enough for white body text, which would
   need a .57-.87 scrim and bury the image. Dark type clears AA everywhere on
   it instead, 7.2:1 at the darkest cell, with no scrim at all. Swap the image
   and re-measure: a dark one flips this back to white. */
.midcta { padding: 0 var(--section-inline) var(--section-pad); background: var(--color-bg-page); }
.midcta__frame {
  position: relative; overflow: hidden;
  max-width: var(--container-max); margin-inline: auto;
  min-height: 40rem; padding: 3.5rem;
  display: grid; grid-template-rows: auto 1fr auto;
  color: var(--brand-primary);
  background: linear-gradient(150deg, #cfe2e4 0%, #9dc3c4 55%, #7ba8a6 100%);
}
.midcta__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.midcta__title {
  position: relative; grid-row: 1; max-width: 16ch;
  font-size: clamp(2.5rem, 5vw, 4rem); line-height: 1; letter-spacing: -.03em;
  color: var(--brand-primary);
}
.midcta__panel {
  position: relative; grid-row: 3; justify-self: end;
  width: min(34rem, 100%); display: flex; flex-direction: column; align-items: flex-start; gap: 1.75rem;
}
.midcta__lede {
  font-family: var(--font-heading); font-size: clamp(1.25rem, 2vw, 1.625rem);
  line-height: 1.3; color: var(--brand-primary);
}
/* the closer sits directly on the footer, so it keeps only the top gap */
.midcta--final { padding-top: var(--section-pad); }

@media (max-width: 640px) {
  .midcta__frame { min-height: 30rem; padding: 1.5rem; }
  .midcta__panel { width: 100%; }
}

/* ============================== BLOG INDEX ==============================
   One row per post on a hairline, the same idiom as the routes list that used
   to sit on the Solutions page. A grid rather than a card wall: with a
   handful of posts, a wall of empty cards looks like a shop with no stock. */
.entries__inner { display: flex; flex-direction: column; gap: 2.5rem; max-width: var(--container-max); margin-inline: auto; }
.entries__list { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--color-line-divider); }
.entry {
  display: grid; grid-template-columns: minmax(0, 11rem) minmax(0, 1fr) auto;
  align-items: start; gap: 1.5rem 2rem;
  padding: 2rem 0; border-bottom: 1px solid var(--color-line-divider);
  transition: padding-left var(--duration-fast);
}
.entry:hover { padding-left: .5rem; }
.entry__meta { display: flex; flex-direction: column; gap: .375rem; font-size: var(--text-small); color: var(--color-muted); }
.entry__tag { font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); text-transform: uppercase; color: var(--brand-accent-ink); }
.entry__title { font-family: var(--font-heading); font-size: 1.5rem; line-height: 1.2; color: var(--color-headline); }
.entry:hover .entry__title { color: var(--brand-accent-ink); }
.entry__sub { grid-column: 2; font-size: var(--text-small); color: var(--color-muted-text); max-width: 42rem; }
.entry__arr { color: var(--color-muted); transition: transform var(--duration-fast); }
.entry:hover .entry__arr { color: var(--brand-accent-ink); transform: translateX(3px); }
.entries__note { max-width: 42rem; font-size: var(--text-small); color: var(--color-muted); }

@media (max-width: 640px) {
  .entry { grid-template-columns: 1fr auto; gap: .5rem 1rem; }
  .entry__meta { grid-column: 1 / -1; flex-direction: row; gap: .75rem; }
  .entry__sub { grid-column: 1 / -1; }
}

/* ================================ ARTICLE ===============================
   One measure column, generous leading, and the diagrams allowed to break out
   wider than the text. Deliberately not .legal: a legal page is a reference
   and an article is read start to finish, so the rhythm is different. */
.post-body { padding-top: 0; }
.post-body__inner { max-width: 40rem; margin-inline: auto; }
.post-body__inner > p {
  margin-top: 1.5rem;
  font-size: var(--text-medium); line-height: 1.65; color: var(--color-muted-text);
}
.post-body__inner > p:first-child { margin-top: 0; }
.post-lead { font-size: var(--text-large) !important; color: var(--color-ink) !important; }
.post-body__inner h2 {
  margin-top: 3.5rem;
  font-family: var(--font-heading); font-size: 1.75rem; line-height: 1.2; color: var(--color-headline);
}
.post-body__inner a { color: var(--brand-accent-ink); text-decoration: underline; text-underline-offset: 2px; }
.post-body__inner a:hover { color: var(--brand-accent-deep); }
.post-body__inner q { font-style: italic; }
.post-body__inner em { font-style: italic; color: var(--color-ink); }

.post-list { margin: 1.5rem 0 0; padding: 0; list-style: none; counter-reset: post; }
.post-list li {
  position: relative; counter-increment: post;
  margin-top: 1.25rem; padding-left: 2.75rem;
  font-size: var(--text-regular); line-height: 1.6; color: var(--color-muted-text);
}
.post-list li::before {
  content: counter(post, decimal-leading-zero);
  position: absolute; left: 0; top: .125rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); color: var(--brand-accent-ink);
}
.post-list strong { color: var(--color-ink); font-weight: 500; }

/* the diagrams break the measure: they need the width more than the column does */
.fx-fig { margin: 2.5rem 0 0; }
@media (min-width: 60rem) {
  .fx-fig { width: min(52rem, 88vw); margin-left: calc((40rem - min(52rem, 88vw)) / 2); }
}
.fx-fig figcaption { margin-top: .75rem; font-size: var(--text-small); color: var(--color-muted); }

.post-note, .post-credit {
  margin-top: 2.5rem !important; padding: 1rem 1.25rem;
  font-size: var(--text-small) !important; line-height: 1.6;
}
.post-note { background: var(--color-bg-section); border-left: 2px solid var(--brand-accent); }
.post-credit { color: var(--color-muted) !important; border-top: 1px solid var(--color-line-soft); padding-left: 0; padding-right: 0; }

/* --- the diagrams themselves: hairline boxes, mono labels, accent for the
       one thing the figure is about --- */
.fx { display: block; width: 100%; height: auto; overflow: visible; }
.fx__box { fill: var(--color-bg-page); stroke: var(--color-line-divider); stroke-width: 1; vector-effect: non-scaling-stroke; }
.fx__box--soft { fill: var(--color-bg-section); }
.fx__box--pick { fill: var(--color-badge-bg); stroke: var(--brand-accent); }
.fx__box--dotted { fill: none; stroke: var(--color-line-divider); stroke-dasharray: 3 3; }
.fx__line { stroke: var(--color-line-divider); stroke-width: 1; vector-effect: non-scaling-stroke; }
.fx__rule { stroke: var(--color-line-soft); stroke-width: 1; vector-effect: non-scaling-stroke; }
.fx__arrow { stroke: var(--color-line-divider); stroke-width: 1; stroke-dasharray: 2 4; vector-effect: non-scaling-stroke; }
.fx__t { font-family: var(--font-body); font-size: 13px; fill: var(--color-muted-text); }
.fx__t--mid { font-size: 14px; font-weight: 500; fill: var(--color-headline); }
.fx__t--key {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 10px; letter-spacing: .04em; text-transform: uppercase; fill: var(--color-muted);
}
.fx__t--val { font-size: 14px; fill: var(--color-ink); }
.fx__t--pick { fill: var(--brand-accent-ink); }
.fx__t--cap { font-size: 12px; fill: var(--color-muted); }
.fx__pip { fill: none; stroke: var(--color-line-divider); stroke-width: 1; vector-effect: non-scaling-stroke; }
.fx__pip--on { fill: var(--color-line-divider); }
.fx__pip--pick { fill: var(--brand-accent); stroke: var(--brand-accent); }

@media (max-width: 40rem) {
  .fx__t { font-size: 15px; }
  .fx__t--key { font-size: 12px; }
  .fx__t--mid, .fx__t--val { font-size: 16px; }
  .fx__t--cap { font-size: 14px; }
}

/* ============================== LEGAL PAGES ==============================
   Shared shell for imprint / privacy / terms. One measure column, no cards
   competing for attention: these pages are read start to finish, not scanned.

   The header on these pages is `site-header--solid` from the first pixel — no
   hero sits behind it — so it gets a hairline the homepage does not need, and
   the page reserves --nav-height at the top for the fixed bar.
========================================================================== */
.site-header--solid { border-bottom: 1px solid var(--color-line-soft); }

/* deliberately NOT .rail: main.js tags every rail child with a scroll
   reveal, and a legal document should be readable the instant it loads —
   not slide in. The padding is the rail's, the behaviour is not. */
.legal {
  padding: calc(var(--nav-height) + var(--section-pad)) var(--section-inline) var(--section-pad);
}
.legal__inner { max-width: 52rem; margin-inline: auto; }




.legal__body { display: flex; flex-direction: column; gap: 3.5rem; padding-top: 3.5rem; }
.legal__block { display: flex; flex-direction: column; gap: 1rem; }
.legal__h2 { font-size: var(--text-large); font-family: var(--font-body); color: var(--color-headline); }
.legal__block p { font-size: var(--text-regular); line-height: var(--body-leading); color: var(--color-muted-text); }
.legal__block a { color: var(--brand-accent-ink); text-decoration: underline; text-underline-offset: 2px; }
.legal__block a:hover { color: var(--brand-accent-deep); }

/* Editorial note — a remark about the document, not part of it. */
.legal__aside {
  border-left: 2px solid var(--color-line-divider);
  padding-left: 1rem;
  font-size: var(--text-small) !important;
  color: var(--color-muted) !important;
}

/* Facts table. Label/value rows, hairline-separated, squared like the rest
   of the site. Collapses to stacked rows below the measure. */
.legal-facts { margin: 0; border-top: 1px solid var(--color-line-soft); }
.legal-facts__row {
  display: grid; grid-template-columns: 14rem 1fr; gap: 1.5rem;
  padding: 1rem 0; border-bottom: 1px solid var(--color-line-soft);
}
.legal-facts dt { font-size: var(--text-small); color: var(--color-muted); }
.legal-facts dd { margin: 0; font-size: var(--text-regular); color: var(--color-ink); }
.legal-facts address { font-style: normal; line-height: var(--body-leading); }
.legal-facts a { color: var(--brand-accent-ink); }
.legal-facts a:hover { color: var(--brand-accent-deep); }
.legal-facts__note { color: var(--color-muted); font-size: var(--text-small); }

/* Unfilled legal field. Deliberately loud: an imprint that ships with an
   invented VAT number is worse than one with a visible gap, so the gap is
   made impossible to miss rather than styled to blend in. */
.legal__next { display: flex; flex-wrap: wrap; gap: 2rem; padding-top: 1rem; }

/* the footer's own link to the page you are already on */
.site-footer .foot-legal a[aria-current="page"] { color: var(--color-footer-heading); }

/* ============================ SUB PAGE SHELL ============================
   The first sub page sets this: no hero, so the page opens on a heading block
   with a hairline under it, and the header is solid from the top. Every other
   sub page inherits it. */
.page { border-bottom: 1px solid var(--color-line); padding-top: calc(var(--nav-height) + var(--section-pad)); }
.page__inner, .page__head { display: flex; flex-direction: column; gap: 1rem; max-width: var(--container-max); margin-inline: auto; }
.page__meta { font-size: var(--text-small); color: var(--color-muted); }
.page__eyebrow {
  font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking);
  text-transform: uppercase; color: var(--brand-accent-ink);
}
.page__title { font-size: clamp(2.5rem, 5vw, 4rem); line-height: 1.05; letter-spacing: -.03em; }
/* A legal page does not need the marketing heading size. Unifying the markup
   pushed Impressum from 48px to 64px; this puts it back without reintroducing
   a second set of heading classes. */
.page__head--legal .page__title { font-size: var(--h2-size); line-height: var(--h2-leading); }
.page__lede { max-width: 42rem; font-size: var(--text-medium); color: var(--color-muted-text); }
/* A mood band under the page head: container width, a wide letterbox, no
   type over it, so nothing has to be measured for contrast. Solutions has
   one; any page can take it by adding .page__mood after .page__head. */
.page__mood {
  max-width: var(--container-max); margin: 3.5rem auto 0;
  aspect-ratio: 21 / 7; overflow: hidden;
  border: 1px solid var(--color-line-card);
}
.page__mood img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 640px) { .page__mood { margin-top: 2rem; aspect-ratio: 16 / 9; } }

/* ================================ CONTACT =============================== */
.contact__inner {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  max-width: var(--container-max); margin-inline: auto;
  background: var(--color-line); border: 1px solid var(--color-line);
}
.contact__col { display: flex; flex-direction: column; padding: 2.5rem; background: var(--color-bg-page); }
.contact__head { font-family: var(--font-heading); font-size: 1.5rem; color: var(--color-headline); }
.contact__note { margin-top: .375rem; font-size: var(--text-small); color: var(--color-muted); }
.contact__note--after { margin-top: 1rem; }
.contact__note a { color: var(--brand-accent-ink); border-bottom: 1px solid currentColor; }

/* Fields carry a bottom rule only, like the newsletter input — one input idiom
   across the site rather than a boxed variant just for this page. */
.cform { display: flex; flex-direction: column; gap: 1.5rem; margin-top: 2rem; }
.cform__row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
.cform__field { display: flex; flex-direction: column; gap: .375rem; min-width: 0; }
.cform__field label { font-size: var(--text-small); color: var(--color-ink); }
.cform__opt { color: var(--color-muted); }
.cform__field input,
.cform__field textarea {
  padding: .625rem 0; background: transparent; color: var(--color-ink);
  border: 0; border-bottom: 1px solid var(--color-line-divider);
  font-family: inherit; font-size: var(--text-regular); resize: vertical;
}
.cform__field input::placeholder,
.cform__field textarea::placeholder { color: var(--color-neutral-light); }
.cform__field input:focus,
.cform__field textarea:focus { outline: none; border-bottom-color: var(--brand-accent); }
.cform__submit { align-self: flex-start; margin-top: .5rem; }
.cform__trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.cform__status { font-size: var(--text-small); color: var(--color-muted); }
.cform__status[data-state="error"] { color: var(--brand-accent-ink); }
.cform__status[data-state="success"] { color: var(--color-ink); }
.cform__submit:disabled { opacity: .6; cursor: default; }

/* cal.com renders its own widget in here; it needs a height to size against */
.cal { flex: 1; min-height: 34rem; margin-top: 2rem; }
.cal__fallback { font-size: var(--text-small); color: var(--color-muted-text); }
.cal__fallback a { color: var(--brand-accent-ink); border-bottom: 1px solid currentColor; }

@media (max-width: 900px) {
  .contact__inner { grid-template-columns: 1fr; }
  .contact__col { padding: 2rem 1.5rem; }
  .cal { min-height: 30rem; }
}
@media (max-width: 640px) {
  .cform__row { grid-template-columns: 1fr; }
}

/* ================================= ABOUT ================================ */
/* The thesis carries the page where a track record would normally sit, so it
   gets display type and a measure short enough to actually read. */
.thesis { border-bottom: 1px solid var(--color-line); }
.thesis__inner {
  display: grid; grid-template-columns: 1fr 1.4fr; gap: 3.5rem;
  max-width: var(--container-max); margin-inline: auto;
}
.thesis__lead {
  font-family: var(--font-heading); font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.15; letter-spacing: -.01em; color: var(--color-headline);
}
.thesis__body { display: flex; flex-direction: column; gap: 1.25rem; max-width: 38rem; }
.thesis__body p { font-size: var(--text-medium); color: var(--color-muted-text); }

.people { background: var(--color-bg-subtle); border-bottom: 1px solid var(--color-line); }
.people__inner { display: flex; flex-direction: column; gap: 3.5rem; max-width: var(--container-max); margin-inline: auto; }
.people__head { display: flex; flex-direction: column; gap: .75rem; }
.people__head h2 { max-width: 40rem; }

/* One founder, so the card lies down instead of standing in a column. A lone
   card in a two-up grid reads as a gap where a second person should be. */
.person--lead { display: grid; grid-template-columns: 15rem 1fr; gap: 3rem; align-items: start; max-width: 52rem; }
.person__text { display: flex; flex-direction: column; gap: .375rem; }
/* Square, not the 4:5 a team page usually uses: the source is a 394px square
   and cover-cropping it to 4:5 would take 40px off each shoulder. Square also
   matches the rest of the site, which has no rounded corner anywhere. The
   photo's own background is white, so it gets a white ground and a hairline
   to read as a framed portrait rather than a head floating on the section. */
.person__portrait {
  width: 100%; aspect-ratio: 1; margin: 0; overflow: hidden;
  background: #fff; border: 1px solid var(--color-line-card);
}
.person__portrait img {
  /* Crop the source photo's dark edge while retaining the square frame. */
  width: calc(100% + 4px); max-width: none; height: calc(100% + 4px);
  margin: -2px; object-fit: cover;
}

.person__name { font-family: var(--font-heading); font-size: 1.5rem; color: var(--color-headline); }
.person__role {
  font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking);
  text-transform: uppercase; color: var(--brand-accent-ink); margin-bottom: .5rem;
}
.person__body { max-width: 32rem; font-size: var(--text-small); color: var(--color-muted-text); }
.person__body + .person__body { margin-top: .625rem; }
.person__link { margin-top: 1rem; align-self: flex-start; }

/* -------------------------------- values -------------------------------- */
/* The site's hairline-grid idiom again: 1px gaps over a line-coloured ground,
   same construction as the contact split and the 404 destinations. */
.values { border-bottom: 1px solid var(--color-line); }
.values__inner { display: flex; flex-direction: column; gap: 3.5rem; max-width: var(--container-max); margin-inline: auto; }
.values__head { display: flex; flex-direction: column; gap: .75rem; }
.values__note { max-width: 38rem; color: var(--color-muted); }
.values__grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px;
  background: var(--color-line); border: 1px solid var(--color-line);
}
.value { display: flex; flex-direction: column; gap: .5rem; padding: 2rem 1.75rem; background: var(--color-bg-page); }
.value__idx {
  font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking);
  text-transform: uppercase; color: var(--color-muted);
}
.value__name { font-family: var(--font-heading); font-size: 1.5rem; color: var(--color-headline); }
.value__body { font-size: var(--text-small); color: var(--color-muted-text); }

/* -------------------------------- roles --------------------------------- */
.roles { background: var(--color-bg-subtle); }
.roles__inner { display: grid; grid-template-columns: 20rem 1fr; gap: 3rem; max-width: var(--container-max); margin-inline: auto; }
.roles__box {
  display: flex; flex-direction: column; gap: .875rem; max-width: 44rem;
  padding: 2.5rem; background: var(--color-bg-page); border: 1px solid var(--color-line-card);
}
.roles__status { font-family: var(--font-heading); font-size: 1.75rem; line-height: 1.2; color: var(--color-headline); }
.roles__body { color: var(--color-muted-text); }
.roles__link { margin-top: .75rem; align-self: flex-start; }

@media (max-width: 1100px) {
  .values__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .thesis__inner { grid-template-columns: 1fr; gap: 1.75rem; }
  .person--lead { grid-template-columns: 1fr; gap: 1.75rem; }
  .person__portrait { max-width: 13rem; }
  .roles__inner { grid-template-columns: 1fr; gap: 1.5rem; }
  .roles__box { padding: 2rem 1.5rem; }
}
@media (max-width: 640px) {
  .values__grid { grid-template-columns: 1fr; }
}

/* ================================ FOOTER ================================= */
.site-footer { background: var(--color-footer-bg); color: var(--color-footer-text); font-size: var(--text-small); }
.site-footer .inner { display: flex; flex-direction: column; gap: 64px; max-width: var(--container-max); margin-inline: auto; padding: var(--section-pad) var(--section-inline); }
.site-footer .content { display: flex; gap: 40px; flex-wrap: wrap; }
.brand-col { flex: 0 0 18rem; display: flex; flex-direction: column; gap: 32px; }
.logo--footer { color: #fff; }
.brand-col__label { color: var(--color-footer-tag); }
.brand-col a:hover { text-decoration: underline; }
.social {
  display: grid; place-items: center; width: 2rem; height: 2rem;
  border: 1px solid var(--color-white-25); color: #fff; font-size: var(--text-small);
}
.social:hover { background: var(--color-white-12); }
/* one track per column, however many there are: the count was hard-coded at
   five and left two empty tracks behind when two columns were removed */
.link-cols { flex: 1; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 24px; }
.link-col { display: flex; flex-direction: column; gap: .625rem; }
.link-col__head { color: var(--color-footer-tag); font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); }
.link-col a { color: var(--color-footer-heading); }
.link-col a:hover { text-decoration: underline; }
.divider { width: 100%; height: 1px; margin: 0; border: 0; background: var(--color-footer-divider); opacity: .5; }
.credits { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 24px; }
/* NOT .legal: that class is the legal pages' section shell, which carries
   160px of top padding -- the footer's link row inherited it and grew to
   281px of empty space on every page of the site. */
.foot-legal { display: flex; flex-wrap: wrap; gap: 24px; margin: 0; padding: 0; list-style: none; }
.foot-legal a:hover { text-decoration: underline; }

/* the legal pages call the consent dialog inline, and mark what is not yet
   true as a note rather than leaving it unsaid */
.legal__inline-btn {
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: var(--brand-accent-ink);
  text-decoration: underline; text-underline-offset: 2px;
}
.legal__inline-btn:hover { color: var(--brand-accent-deep); }
.legal__note {
  margin-top: 1rem; padding: .875rem 1rem;
  background: var(--color-bg-section); border-left: 2px solid var(--brand-accent);
  font-size: var(--text-small);
}
.ctable-wrap { overflow-x: auto; margin: 1.5rem 0; }
.ctable { width: 100%; border-collapse: collapse; font-size: var(--text-small); }
.ctable th, .ctable td { padding: .75rem .875rem; text-align: left; vertical-align: top; border: 1px solid var(--color-line-card); }
.ctable thead th { background: var(--color-bg-section); font-weight: 500; color: var(--color-headline); white-space: nowrap; }
.ctable td { color: var(--color-muted-text); }
.ctable code { font-size: .8125rem; }

/* ================================ CONSENT ===============================
   A bar at the bottom edge and a settings dialog, both in the site's own
   vocabulary: squared, one hairline, no shadow theatre. The two decisions are
   deliberately identical buttons -- the EDPB reads a loud Accept beside a
   quiet Reject as a dark pattern, so neither is emphasised, and Settings is
   the quiet one because it is not a decision.

   The bar is a landmark, not a modal: it does not trap focus and does not
   block the page, so someone who wants to read the privacy policy first can. */
/* A small card in the corner rather than a bar across the page: it has to be
   noticed, not obeyed, and it must not bury the first screen. Legally nothing
   changes -- both decisions are still one click at the same level, in the
   same button, and there is still no way to dismiss it without deciding. */
.cbar {
  /* bottom right: every page sets its copy and its buttons on the left, so
     the card lands on empty ground instead of over the hero's call to action */
  position: fixed; right: var(--section-inline); bottom: 1.5rem; z-index: 200;
  width: min(25rem, calc(100vw - var(--section-inline) * 2));
  padding: 1.375rem 1.5rem 1.25rem;
  background: var(--color-bg-page);
  border: 1px solid var(--color-line);
  box-shadow: 0 1px 2px rgba(12, 12, 13, .04), 0 24px 48px -28px rgba(12, 12, 13, .35);
  animation: cbar-in .5s var(--ease-out) both;
}
.cbar[hidden] { display: none; }
@keyframes cbar-in { from { opacity: 0; transform: translateY(12px); } }
@media (prefers-reduced-motion: reduce) { .cbar { animation: none; } }

.cbar__eyebrow {
  font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking);
  text-transform: uppercase; color: var(--color-muted);
}
.cbar__body { margin-top: .5rem; font-size: var(--text-small); line-height: 1.5; color: var(--color-muted-text); }
.cbar__actions { display: flex; gap: .5rem; margin-top: 1.125rem; }
.cbar__actions .cbtn { flex: 1; justify-content: center; }
.cbar__links {
  display: flex; flex-wrap: wrap; gap: .25rem .875rem;
  margin-top: .875rem; padding-top: .875rem;
  border-top: 1px solid var(--color-line-soft);
  font-size: var(--text-tiny);
}
.cbar__links a, .cbar__link {
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: var(--color-muted);
  text-decoration: underline; text-underline-offset: 2px;
}
.cbar__links a:hover, .cbar__link:hover { color: var(--brand-accent-ink); }

.cbtn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 2.5rem; padding: 0 1rem;
  border: 1px solid var(--color-ink); background: var(--color-bg-page);
  font-family: inherit; font-size: var(--text-small); font-weight: 500; color: var(--color-ink);
  cursor: pointer;
  transition: background var(--duration-fast), color var(--duration-fast), border-color var(--duration-fast);
}
.cbtn:hover { background: var(--color-ink); color: #fff; }
.cbtn:focus-visible { outline: 2px solid var(--brand-accent); outline-offset: 2px; }

/* --- the settings dialog --- */
.cdlg { position: fixed; inset: 0; z-index: 210; display: grid; place-items: center; padding: 1.25rem; }
.cdlg[hidden] { display: none; }
.cdlg__scrim { position: absolute; inset: 0; background: rgba(12, 12, 13, .55); }
.cdlg__panel {
  position: relative; width: min(38rem, 100%); max-height: 86vh; overflow-y: auto;
  padding: 2.5rem; background: var(--color-bg-page); border: 1px solid var(--color-line);
}
.cdlg__close {
  position: absolute; top: .75rem; right: .75rem;
  width: 2.25rem; height: 2.25rem;
  border: 0; background: transparent; color: var(--color-muted);
  font-size: 1.5rem; line-height: 1; cursor: pointer;
}
.cdlg__close:hover { color: var(--color-ink); }
.cdlg__title { font-family: var(--font-heading); font-size: var(--h4-size); color: var(--color-headline); }
.cdlg__body { margin-top: .75rem; font-size: var(--text-small); line-height: 1.55; color: var(--color-muted-text); }
.cgroups { display: flex; flex-direction: column; margin: 2rem 0 0; padding: 0; list-style: none; border-top: 1px solid var(--color-line-divider); }
.cgroup { padding: 1.125rem 0; border-bottom: 1px solid var(--color-line-divider); }
.cgroup__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.cgroup__name { font-size: var(--text-medium); color: var(--color-headline); }
.cgroup__always { font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); text-transform: uppercase; color: var(--color-muted); }
.cgroup__body { margin-top: .5rem; max-width: 34rem; font-size: var(--text-small); line-height: 1.55; color: var(--color-muted-text); }
.cdlg__actions { display: flex; flex-wrap: wrap; gap: .625rem; margin-top: 1.75rem; }

/* a square switch, because the site has no round corners anywhere else */
.cswitch { position: relative; flex: none; cursor: pointer; }
.cswitch input { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.cswitch__track {
  display: block; width: 3rem; height: 1.5rem;
  border: 1px solid var(--color-line-divider); background: var(--color-bg-section);
  transition: background var(--duration-fast), border-color var(--duration-fast);
}
.cswitch__track::after {
  content: ""; display: block; width: 1.125rem; height: 1.125rem; margin: .125rem;
  background: var(--color-muted);
  transition: transform var(--duration-fast), background var(--duration-fast);
}
.cswitch input:checked + .cswitch__track { background: var(--color-badge-bg); border-color: var(--brand-accent); }
.cswitch input:checked + .cswitch__track::after { background: var(--brand-accent); transform: translateX(1.5rem); }
.cswitch input:focus-visible + .cswitch__track { outline: 2px solid var(--brand-accent); outline-offset: 2px; }

/* the footer's way back into the dialog, set as one of the legal links */
.foot-legal__btn {
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: inherit;
}
.foot-legal__btn:hover { text-decoration: underline; }

/* --- the calendar slot before consent --- */
.cal__gate {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1rem;
  padding: 2.5rem 2rem;
  border: 1px dashed var(--color-line-divider); background: var(--color-bg-section);
}
.cal__gate-text { max-width: 26rem; font-size: var(--text-small); line-height: 1.55; color: var(--color-muted-text); }
.cal__gate-alt { font-size: var(--text-small); }

@media (max-width: 640px) {
  .cbar { left: var(--section-inline); right: var(--section-inline); bottom: 1rem; width: auto; }
  .cdlg__panel { padding: 1.5rem; }
}

/* ====================== MARKET SIZE ESTIMATOR (tool) =====================
   Assumptions on the left, the funnel they produce on the right, and the
   globe under both. The two halves are one hairline grid so a change on the
   left is read against the numbers it moved. */
.mkt {
  display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 9fr); gap: 1px;
  max-width: var(--container-max); margin-inline: auto;
  background: var(--color-line); border: 1px solid var(--color-line);
}
.mkt__form, .mkt__out { display: flex; flex-direction: column; gap: 1.5rem; padding: 2.5rem; background: var(--color-bg-page); }
.mkt__head { font-family: var(--font-heading); font-size: 1.5rem; color: var(--color-headline); }
.mkt__field { display: flex; flex-direction: column; gap: .375rem; min-width: 0; }
.mkt__field label { font-size: var(--text-small); color: var(--color-ink); }
.mkt__row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
.mkt__field input, .mkt__field select {
  width: 100%; padding: .625rem 0; min-width: 0;
  background: transparent; color: var(--color-ink);
  border: 0; border-bottom: 1px solid var(--color-line-divider);
  font-family: inherit; font-size: var(--text-medium);
}
.mkt__field select { padding-right: 1.5rem; appearance: none; cursor: pointer; }
.mkt__field input:focus, .mkt__field select:focus { outline: none; border-bottom-color: var(--brand-accent); }
/* the unit sits in the rule with the number rather than in the label, so the
   field reads as one quantity */
.mkt__unit { display: flex; align-items: baseline; gap: .5rem; border-bottom: 1px solid var(--color-line-divider); }
.mkt__unit input { border-bottom: 0; }
.mkt__unit:focus-within { border-bottom-color: var(--brand-accent); }
.mkt__unit span { font-size: var(--text-small); color: var(--color-muted); }
.mkt__reset { align-self: flex-start; margin-top: auto; }

.mkt__funnel { display: flex; flex-direction: column; gap: 1.5rem; margin: 0; padding: 0; list-style: none; }
.mkt__step { display: flex; flex-direction: column; gap: .25rem; }
.mkt__value { font-family: var(--font-heading); font-size: 2.5rem; line-height: 1; color: var(--color-headline); }
.mkt__step--fit .mkt__value { color: var(--brand-accent-ink); }
.mkt__label { font-size: var(--text-small); color: var(--color-ink); }
.mkt__bar { display: block; height: 4px; margin: .5rem 0 .25rem; background: var(--color-bg-section); }
.mkt__bar i { display: block; height: 100%; width: 0; background: var(--color-line-divider); transition: width var(--duration-base) var(--ease-out); }
.mkt__step--fit .mkt__bar i { background: var(--brand-accent); }
.mkt__step--reach .mkt__bar i { background: var(--color-ink); }
.mkt__note { font-size: var(--text-small); color: var(--color-muted); }
.mkt__sentence {
  padding: .875rem 1rem; background: var(--color-bg-section);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--text-tiny); line-height: 1.6; color: var(--color-muted-text);
}
.mkt__money { display: flex; flex-direction: column; gap: .75rem; margin-top: auto; }
.mkt__money-head { font-size: var(--text-small); color: var(--color-ink); }
.mkt__table { width: 100%; border-collapse: collapse; font-size: var(--text-small); }
.mkt__table th, .mkt__table td { padding: .625rem 0; text-align: left; border-top: 1px solid var(--color-line-soft); color: var(--color-muted-text); }
.mkt__table th { width: 3rem; font-weight: 500; color: var(--color-ink); }
.mkt__num { text-align: right; color: var(--color-headline); }

/* --- the globe: dark band, dots on canvas, drawn by market-size.js --- */
.globe-sec {
  --globe-dot: rgba(255, 255, 255, .55);
  --globe-marker: #7faca6;
  padding: var(--section-pad) var(--section-inline);
  background: var(--color-dark-bg); color: var(--color-neutral-light);
}
.globe-sec__inner { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 3rem; align-items: center; max-width: var(--container-max); margin-inline: auto; }
.globe-sec__text { display: flex; flex-direction: column; gap: 1rem; max-width: 30rem; }
.globe-sec__text h2 { color: var(--color-headline-invert); }
.globe-wrap { justify-self: center; width: min(32rem, 100%); }
.globe { display: block; width: 100%; aspect-ratio: 1; }

.tool-note { background: var(--color-bg-subtle); border-top: 1px solid var(--color-line); }
.tool-note__inner { display: flex; flex-direction: column; gap: 1rem; max-width: 46rem; margin-inline: auto; }
.tool-note__inner p { font-size: var(--text-regular); line-height: var(--body-leading); color: var(--color-muted-text); }
.cta__text { max-width: 34rem; color: var(--color-neutral-light); }

@media (max-width: 1000px) {
  .mkt { grid-template-columns: 1fr; }
  .globe-sec__inner { grid-template-columns: 1fr; gap: 2.5rem; }
}
@media (max-width: 640px) {
  .mkt__form, .mkt__out { padding: 1.75rem 1.25rem; }
  .mkt__row { grid-template-columns: 1fr; }
  .mkt__value { font-size: 2rem; }
}

/* =========================== PAGE TRANSITIONS ============================
   The shell is what router.js swaps. It carries no styling of its own; the
   rules here are only what the transition needs: a paint boundary so the two
   shells can be composited independently, and the veil that darkens the
   outgoing page. Everything positional is set inline by the router and
   cleared when the transition ends. */
/* The background is what makes the transition work: while the two shells
   overlap, a transparent incoming page would let the outgoing one show
   through it. Sections paint their own grounds on top of this one. */
.shell { isolation: isolate; background: var(--color-bg-page); }
.shell-veil {
  position: absolute; inset: 0; z-index: 9;
  background: #000; opacity: 0; pointer-events: none;
  transition: opacity 1200ms cubic-bezier(.77, 0, .175, 1);
}
@media (prefers-reduced-motion: reduce) {
  .shell-veil { display: none; }
}

/* =============================== REVEALS ================================= */
.reveal-motion .rail [data-reveal] {
  opacity: 0; transform: translateY(18px);
  transition: opacity var(--duration-reveal) var(--ease-out), transform var(--duration-reveal) var(--ease-out);
  transition-delay: var(--d, 0ms);
}
.reveal-motion .rail [data-reveal].is-visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  .reveal-motion .rail [data-reveal] { opacity: 1; transform: none; }
}


/* ============================== 404 / NOT FOUND ==========================
   Reuses the sub-page shell (.page + .page__head) so the header state and the
   opening rhythm match every other sub page, then hangs one dark panel under
   the lede. The panel is the hero's signal strip failing: same hairline, same
   9px nodes, same micro-caps — a request that gets routed, looked up and then
   dead-ends. Building a second visual idiom just for the error page would have
   made the site feel like two sites. */
.nf-panel {
  position: relative;
  max-width: var(--container-max);
  margin: 3.5rem auto 0;
  padding: 2.5rem;
  background: var(--color-dark-bg);
  color: var(--color-footer-text);
}

.nf-panel__label {
  font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking);
  text-transform: uppercase; color: var(--color-neutral-light);
}
.nf-panel__path { margin-top: .5rem; }
.nf-panel__path code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--text-medium);
  color: var(--color-footer-heading);
  /* the path is whatever the visitor typed — it must never widen the panel */
  overflow-wrap: anywhere;
}

/* -- the failing strip -- */
.nf-band { margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--color-white-12); }

.nf-track { --nf-duration: 4.5s; --nf-break: 66.666%; position: relative; }

/* two rules, not one: solid up to the break, then a dashed run that goes
   nowhere. The break sits exactly on the third node so the dash starts where
   the lookup failed. */
.nf-track::before,
.nf-track::after {
  content: ""; position: absolute; top: 4px; height: 1px;
}
.nf-track::before {
  left: 0; right: calc(100% - var(--nf-break));
  background:
    repeating-linear-gradient(to right, rgba(255, 255, 255, .22) 0 1px, transparent 1px 14px),
    var(--color-white-12);
}
.nf-track::after {
  left: var(--nf-break); right: 0;
  background: repeating-linear-gradient(to right, var(--color-white-25) 0 3px, transparent 3px 9px);
}

/* Absolute thirds rather than space-between — distributing the boxes lets the
   wider labels drag the nodes off the interval, which is the bug the hero
   strip already hit once. */
.nf-stages { position: relative; height: 2.0625rem; margin: 0; padding: 0; list-style: none; }
.nf-stage {
  position: absolute; top: 0; left: calc(var(--i) * 33.3333%);
  display: flex; flex-direction: column; align-items: flex-start; gap: .875rem;
}
.nf-stage--dead { left: auto; right: 0; align-items: flex-end; }

.nf-node {
  width: 9px; height: 9px;
  border: 1px solid rgba(255, 255, 255, .55);
  background: var(--brand-primary);
  animation: nf-pass var(--nf-duration) linear infinite;
  animation-delay: calc(var(--i) * var(--nf-duration) * .275);
}
/* the dead end: a crossed box, drawn from gradients so it stays crisp and
   needs no glyph or extra asset */
.nf-node--x {
  border-color: var(--color-white-25);
  background:
    linear-gradient(to bottom right, transparent 42%, var(--color-white-60) 42% 58%, transparent 58%),
    linear-gradient(to bottom left,  transparent 42%, var(--color-white-60) 42% 58%, transparent 58%),
    var(--brand-primary);
  animation: none;
}

.nf-label {
  font-size: .625rem; letter-spacing: var(--tagline-tracking);
  text-transform: uppercase; color: var(--color-neutral-light);
  white-space: nowrap; line-height: 1;
}
.nf-stage--dead .nf-label { color: var(--color-white-60); }

/* the marker runs, reaches the break, flickers and dies */
.nf-runner {
  position: absolute; top: 0; left: 0; width: 9px; height: 9px;
  background: var(--color-link-on-dark);
  animation: nf-run var(--nf-duration) linear infinite;
}
.nf-runner::after {
  content: ""; position: absolute; right: 100%; top: 4px; width: 4.5rem; height: 1px;
  background: linear-gradient(to left, var(--color-link-on-dark), transparent);
}

@keyframes nf-run {
  0%        { left: 0; opacity: 0; }
  4%        { left: 0; opacity: 1; }
  55%       { left: var(--nf-break); opacity: 1; }
  70%       { left: calc(var(--nf-break) + 1.75rem); opacity: 1; }
  76%       { left: calc(var(--nf-break) + 1.75rem); opacity: .2; }
  82%       { left: calc(var(--nf-break) + 1.75rem); opacity: 1; }
  88%, 100% { left: calc(var(--nf-break) + 1.75rem); opacity: 0; }
}
@keyframes nf-pass {
  0%, 100% { border-color: rgba(255, 255, 255, .55); }
  2%       { border-color: var(--color-link-on-dark); }
  16%      { border-color: rgba(255, 255, 255, .55); }
}

.nf-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 1.5rem;
  margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--color-white-12);
}
/* --color-link-on-dark is the only accent tint that clears 4.5:1 on the
   near-black panel; the raw accent manages 3.3:1 and must not be used here. */
.nf-actions__link { color: var(--color-footer-text); font-size: var(--text-regular); }
.nf-actions__link:hover { color: var(--color-link-on-dark); }

/* -- destinations -- */
.nf-next__inner { max-width: var(--container-max); margin-inline: auto; }
.nf-next__head { display: flex; flex-direction: column; gap: .5rem; margin-bottom: 2.5rem; }
.nf-next__note { font-size: var(--text-medium); color: var(--color-muted-text); }

/* the site's hairline-grid idiom: 1px gaps over a line-coloured ground */
.nf-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  background: var(--color-line); border: 1px solid var(--color-line);
}
.nf-card {
  display: flex; flex-direction: column; gap: .5rem;
  padding: 1.75rem; background: var(--color-bg-page);
  transition: background var(--duration-fast);
}
.nf-card:hover { background: var(--color-bg-section); }
.nf-card__idx {
  font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking);
  /* --color-neutral-light is a DARK-ground token (9.6:1 there, 2.0:1 on white).
     On this white card it needs the light-ground muted token instead: 5.3:1. */
  color: var(--color-muted);
}
.nf-card__title { font-family: var(--font-heading); font-size: var(--text-large); color: var(--color-headline); }
.nf-card__sub { font-size: var(--text-small); color: var(--color-muted-text); }
.nf-card__arr { margin-top: auto; padding-top: 1.5rem; color: var(--brand-accent-ink); transition: transform var(--duration-fast); }
.nf-card:hover .nf-card__arr { transform: translateX(3px); }

@media (max-width: 1000px) {
  .nf-grid, .nf-grid--3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 900px) {
  .nf-panel { padding: 2rem 1.5rem; }
  /* three labels do not fit; the rule, the nodes and the dead end still read */
  .nf-stage:not(:first-child):not(.nf-stage--dead) .nf-label { display: none; }
}
@media (max-width: 640px) {
  .nf-grid { grid-template-columns: 1fr; }
  .nf-panel { margin-top: 2.5rem; }
  .nf-band, .nf-actions { margin-top: 2rem; }
}
@media (prefers-reduced-motion: reduce) {
  /* a marker frozen at the break reads as a rendering bug, so remove it */
  .nf-runner { display: none; }
}


/* ------------------------- language switcher ---------------------------
   Two languages, so both are shown and the active one is simply the one that
   is not dimmed. The dropdown this replaced came from scaile.tech, which runs
   three languages -- there it earns the click, here the open menu would have
   held a single item.

   No box: the bar already carries an outlined Login and a filled Book a Call,
   and a third framed control on the same row turns the right-hand side into
   competing rectangles. This is the least important control there.

   Nothing hardcodes a colour -- --nav-ink flips to white over the hero. */
.lang { display: inline-flex; align-items: center; font-size: var(--text-small); line-height: 1; }
.lang__opt {
  padding: 0 .5rem;
  color: var(--nav-ink);
  /* .65, not the .5 that looked right: the inactive code is still a link, so
     it owes 4.5:1. Dimming --color-ink to .5 on white measures 3.03:1 and
     fails; .65 measures 4.62:1 and 8.42:1 over the hero, and still reads as
     clearly recessive next to the active one at 14.38:1. */
  opacity: .65;
  transition: opacity var(--duration-fast), color var(--duration-fast);
}
.lang__opt:first-child { padding-left: 0; }
.lang__opt:last-child { padding-right: 0; }
.lang__opt.is-active { opacity: 1; }
.lang__opt:hover { opacity: 1; color: var(--brand-accent-ink); }
.site-header--overlay:not(.is-scrolled):not(.menu-open):not(.nav-open) .lang__opt:hover { color: var(--color-link-on-dark); }
.lang__sep { width: 1px; height: .75rem; background: currentColor; color: var(--nav-ink); opacity: .3; }


/* ============================ HAIRLINE GRID =============================
   The site's card idiom: 1px gaps over a line-coloured ground, every cell on
   the page colour. It existed as five private copies (contact split, values,
   404 destinations, steps, fit) before the sixth use made it a utility. The
   older copies still work and were left alone; new grids use this. */
.hgrid {
  display: grid; grid-template-columns: repeat(var(--cols, 4), minmax(0, 1fr)); gap: 1px;
  margin: 0; padding: 0; list-style: none;
  background: var(--color-line); border: 1px solid var(--color-line);
}
.hgrid > * { background: var(--color-bg-page); }
/* Column counts live HERE, on the class, never as an inline style="--cols:3"
   on the element: an inline custom property outranks every media query below,
   so the grid would keep its desktop column count on a phone. It did -- both
   new grids overflowed a 375px viewport by ~30px until this was moved. */

/* ================================= TOOLS =================================
   Two client-side tools. Radio questions for the Motion Finder, a checklist
   with a live score for the Scorecard. Same hairline vocabulary as the rest;
   the score panel sticks so the number moves while the visitor ticks. */
.btn--dark { background: var(--color-neutral-darkest); color: #fff; border-color: var(--color-neutral-darkest); }
.btn--dark .btn__tile { background: var(--brand-accent); color: var(--brand-accent-on); }
.btn--dark:hover { background: var(--brand-accent-deep); border-color: var(--brand-accent-deep); }

.tool__inner { max-width: var(--container-max); margin-inline: auto; }
.tool__inner--split { display: grid; grid-template-columns: 1fr 22rem; gap: 3rem; align-items: start; }
.tool__note { max-width: 40rem; margin-bottom: 2rem; font-size: var(--text-small); color: var(--color-muted); }

.quiz { display: flex; flex-direction: column; gap: 1px; background: var(--color-line); border: 1px solid var(--color-line); }
.quiz__q { margin: 0; padding: 1.75rem; border: 0; background: var(--color-bg-page); }
/* a <legend> is drawn ON the fieldset's top edge, so the container's line
   colour showed through beside it. Floating it full-width pulls it back into
   normal flow; the option list clears it. */
.quiz__legend { float: left; width: 100%; display: flex; align-items: baseline; gap: .75rem; padding: 0; margin-bottom: 1rem; font-family: var(--font-heading); font-size: 1.25rem; color: var(--color-headline); }
.quiz__opts, .check__list { clear: both; }
.quiz__num { font-family: var(--font-body); font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); color: var(--brand-accent-ink); }
.quiz__count { margin-left: auto; font-family: var(--font-body); font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); color: var(--color-muted); }
.quiz__opts { display: flex; flex-direction: column; gap: .5rem; }
.quiz__opt, .check {
  display: flex; align-items: flex-start; gap: .75rem; padding: .75rem 1rem; cursor: pointer;
  border: 1px solid var(--color-line-card); font-size: var(--text-small); color: var(--color-ink);
  transition: border-color var(--duration-fast), background var(--duration-fast);
}
.quiz__opt:hover, .check:hover { border-color: var(--brand-accent); }
.quiz__opt:has(:checked), .check:has(:checked) { border-color: var(--brand-accent); background: var(--color-badge-bg); }
.quiz__opt input, .check input { margin: .2em 0 0; accent-color: var(--brand-accent); flex: none; }
.check__list { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; }
.quiz__actions { padding: 1.75rem; background: var(--color-bg-page); }
/* the note sits inside the hairline container on the scorecard, so it needs the page ground like every other cell */
.quiz > .tool__note { margin: 0; padding: 1.5rem 1.75rem 0; background: var(--color-bg-page); }

/* result */
.quiz__result { margin-top: 2rem; padding: 2.5rem; border: 1px solid var(--color-line); background: var(--color-bg-subtle); }
.quiz__result-eyebrow, .score__eyebrow { font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); text-transform: uppercase; color: var(--brand-accent-ink); }
.quiz__result-name { margin-top: .5rem; font-family: var(--font-heading); font-size: var(--h3-size); line-height: 1.1; color: var(--color-headline); }
.quiz__result-why { margin-top: 1rem; max-width: 44rem; font-size: var(--text-medium); color: var(--color-muted-text); }
.quiz__result-sub { margin-top: 1.5rem; font-size: var(--text-small); color: var(--color-muted); }
.quiz__bars { display: flex; flex-direction: column; gap: .5rem; margin: 1.75rem 0 0; max-width: 32rem; }
.quiz__bar { display: grid; grid-template-columns: 11rem 1fr; align-items: center; gap: 1rem; font-size: var(--text-small); color: var(--color-muted-text); }
.quiz__bar.is-top { color: var(--color-headline); }
.quiz__bar-track { display: block; height: 6px; background: var(--color-line); }
.quiz__bar-track > span { display: block; height: 100%; background: var(--color-neutral-light); transition: width var(--duration-base) var(--ease-out); }
.quiz__bar.is-top .quiz__bar-track > span { background: var(--brand-accent); }
.quiz__links { display: flex; flex-wrap: wrap; align-items: center; gap: 1.5rem; margin-top: 1.75rem; }
.quiz__restart { border-bottom: 1px solid transparent; }

/* score panel */
.score { position: sticky; top: calc(var(--nav-height) + 1.5rem); padding: 2rem; border: 1px solid var(--color-line); background: var(--color-bg-page); }
.score__value { margin-top: .5rem; font-family: var(--font-heading); font-size: 3.5rem; line-height: 1; color: var(--color-headline); }
.score__of { font-size: 1rem; color: var(--color-muted); }
.score__bar { height: 6px; margin-top: 1rem; background: var(--color-line); }
.score__bar > span { display: block; height: 100%; background: var(--brand-accent); transition: width var(--duration-base) var(--ease-out); }
.score__band { margin-top: 1.5rem; font-family: var(--font-heading); font-size: 1.375rem; color: var(--color-headline); }
.score__text { margin-top: .625rem; font-size: var(--text-small); color: var(--color-muted-text); }

.nf-grid--2 { grid-template-columns: repeat(2, 1fr); }
.nf-grid--3 { grid-template-columns: repeat(3, 1fr); }

@media (max-width: 1000px) {
  .tool__inner--split { grid-template-columns: 1fr; }
  .score { position: static; }
}
@media (max-width: 640px) {
  .quiz__q, .quiz__actions, .quiz__result, .score { padding: 1.5rem 1.25rem; }
  .check__list { grid-template-columns: 1fr; }
  .quiz__bar { grid-template-columns: 1fr; gap: .25rem; }
  .nf-grid--2, .nf-grid--3 { grid-template-columns: 1fr; }
}

/* ======================= THE B2B GROWTH SYSTEM (layers) ==================
   gonimbly.com's "Modern RevTech Stack", with one change: their heading
   runs full width above; here it sits in the narrow left column with the
   intro, and the whole column is sticky, so the heading is what stays put
   while the stack scrolls past. */
.system { border-top: 1px solid var(--color-line); }
.system__inner { max-width: var(--container-max); margin-inline: auto; }
.system__wrap { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 11fr); gap: 3rem; align-items: start; }
.system__intro { position: sticky; top: calc(var(--nav-height) + 2rem); display: flex; flex-direction: column; gap: 1rem; max-width: 24rem; font-size: var(--text-medium); color: var(--color-muted-text); }
.system__intro h2 { margin-bottom: 1rem; overflow-wrap: anywhere; }  /* "Wachstumssystem" is wider than the column at this size; the German word carries a &shy; and this catches whatever else does not fit */
.system__list { margin: 0; padding: 0; list-style: none; border: 1px solid var(--color-ink); }
.layer { display: grid; grid-template-columns: 1fr 1fr; min-height: 20rem; }
.layer + .layer { border-top: 1px solid var(--color-ink); }
.layer__text { display: flex; flex-direction: column; gap: .75rem; padding: 1.5rem; }
.layer__idx {
  align-self: flex-start; padding: .125rem .5rem;
  border: 1px solid var(--color-line-divider);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); color: var(--color-muted);
}
.layer__title { font-family: var(--font-body); font-size: var(--text-large); font-weight: 500; line-height: 1.3; color: var(--color-headline); }
.layer__body { margin-top: auto; padding-top: 2rem; font-size: var(--text-regular); color: var(--color-muted-text); }
.layer__media { position: relative; overflow: hidden; border-left: 1px solid var(--color-ink); }
.layer__media img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: transform var(--duration-slow) var(--ease-out);
}
.layer:hover .layer__media img { transform: scale(1.04); }

@media (max-width: 1000px) {
  .system__wrap { grid-template-columns: 1fr; }
  .system__intro { position: static; max-width: 42rem; }
  .system__intro h2 { max-width: 40rem; }
}
@media (max-width: 640px) {
  .layer { grid-template-columns: 1fr; min-height: 0; }
  .layer__media { min-height: 12rem; border-left: 0; border-top: 1px solid var(--color-ink); }
  .layer__body { padding-top: 1.25rem; }
}

/* =========================== SOLUTIONS: FOUR AREAS =======================
   gonimbly.com/solutions: the section heading stays put on the left while the
   numbered areas scroll past on the right, and every capability is a row on a
   hairline that opens to one line of copy. Theirs is JavaScript and rounded;
   this is <details>, so it works with scripts off, and squared like the rest
   of the site. The marker is the FAQ's plus/minus, scaled down. */
.areas__wrap { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 11fr); gap: 3rem; align-items: start; max-width: var(--container-max); margin-inline: auto; }
.areas__intro { position: sticky; top: calc(var(--nav-height) + 2rem); display: flex; flex-direction: column; gap: 1rem; max-width: 24rem; }
.areas__intro p { font-size: var(--text-medium); color: var(--color-muted-text); }
.areas__list { display: flex; flex-direction: column; gap: 4rem; }

.area { display: flex; flex-direction: column; gap: 1.5rem; scroll-margin-top: calc(var(--nav-height) + 2rem); }
.area__head { display: flex; flex-direction: column; gap: .5rem; }
.area__idx {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); color: var(--color-muted);
}
.area__name { font-family: var(--font-heading); font-size: 1.75rem; line-height: 1.15; color: var(--color-headline); }
.area__promise { font-size: var(--text-medium); color: var(--brand-accent-ink); }
.area__lead { max-width: 40rem; font-size: var(--text-regular); color: var(--color-muted-text); }
.area__caps { display: flex; flex-direction: column; }

/* the row: the title in a box at the left, the rule running out to the
   marker at the right end, exactly as on theirs */
.cap { border-bottom: 1px solid var(--color-line-divider); }
.cap summary {
  display: flex; align-items: center; gap: 1rem;
  padding: .875rem 0; list-style: none; cursor: pointer;
}
.cap summary::-webkit-details-marker { display: none; }
.cap__name {
  padding: .3125rem .625rem;
  border: 1px solid var(--color-line-card); background: var(--color-bg-page);
  font-size: var(--text-small); color: var(--color-ink);
  transition: background var(--duration-fast), border-color var(--duration-fast), color var(--duration-fast);
}
.cap summary:hover .cap__name { border-color: var(--brand-accent); color: var(--brand-accent-ink); }
.cap[open] .cap__name { background: var(--color-badge-bg); border-color: var(--brand-accent); color: var(--brand-accent-ink); }
.cap__mark { position: relative; flex: none; width: 11px; height: 11px; margin-left: auto; color: var(--color-muted); }
.cap__mark::before, .cap__mark::after {
  content: ""; position: absolute; inset: 50% 0 auto; height: 1px; background: currentColor;
  transition: transform var(--duration-fast);
}
.cap__mark::after { transform: rotate(90deg); }
.cap[open] .cap__mark { color: var(--brand-accent-ink); }
.cap[open] .cap__mark::after { transform: rotate(0deg); }
.cap__body { padding: 0 0 1.125rem; max-width: 42rem; font-size: var(--text-regular); color: var(--color-muted-text); }

@media (max-width: 1000px) {
  .areas__wrap { grid-template-columns: 1fr; }
  .areas__intro { position: static; max-width: 42rem; }
}
/* ============================ PROCESS (figures) ==========================
   Four isometric hairline drawings, one per step, that move. The
   construction is linear.app's -- inline SVG, one <g> per moving part, a CSS
   transform with their ease-out curve -- drawn in this site's vocabulary:
   squared, 1px, accent for what moves. Each figure is its step's verb:
   Diagnose, a cluster rises out of the field; Architect, parts rise out of a
   blueprint; Build, layers close into one block; Operate, the accounts that
   need a human lift out of the row.

   The motion is on hover only (unlike the problem scenes, which loop): a
   transition to the resolved state while the pointer is on the step, back
   when it leaves. --fig-d staggers parts inside one figure. Under
   prefers-reduced-motion nothing moves; the accent still marks the point. */
.proc { border-top: 1px solid var(--color-line); }
.proc__inner { max-width: var(--container-max); margin-inline: auto; }
.proc__head { display: flex; flex-direction: column; gap: 1rem; }
.proc__lede { max-width: 42rem; font-size: var(--text-medium); color: var(--color-muted-text); }
.proc__row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; margin: 4rem 0 0; padding: 0; list-style: none; }
.proc__step { display: flex; flex-direction: column; padding: 0 2rem 0 0; }
.proc__step + .proc__step { padding-left: 2rem; border-left: 1px solid var(--color-line); }
.proc__step h3 + p { margin-top: .75rem; font-size: var(--text-regular); color: var(--color-muted-text); }
.fig__label {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); text-transform: uppercase;
  color: var(--color-muted);
}
/* a fixed box height, so the four titles sit on one line whatever the column
   width (the first column has no left padding and is wider); the drawing
   scales inside it, left-aligned via preserveAspectRatio */
.fig__svg { display: block; width: 100%; max-width: 18rem; height: 12rem; margin: 2rem 0 2.5rem; overflow: visible; }
.fig__svg .f { fill: var(--color-bg-page); stroke: rgba(12, 12, 13, .45); stroke-width: 1; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.fig__svg .ground { fill: none; stroke: rgba(12, 12, 13, .22); stroke-dasharray: 2 3; vector-effect: non-scaling-stroke; }
.fig__svg .a { stroke: var(--brand-accent); }
.fig__svg .node { fill: var(--brand-accent); }
/* every moving group: linear.app's curve, staggered by --fig-d where set (not
   --d, which the scroll reveal already uses and which inherits into the SVG) */
.fig__rise, .fig__lift, .fig__layer, .fig__ghost {
  transform-box: fill-box;
  transition: transform .7s cubic-bezier(.32, .72, 0, 1), opacity .7s cubic-bezier(.32, .72, 0, 1);
  transition-delay: var(--fig-d, 0s);
}
.proc__step:hover .fig__rise { transform: translateY(-14px); }
.proc__step:hover .fig__lift { transform: translateY(-18px); }
/* the blueprint's parts: absent at rest, rise out of their footprints */
.fig__ghost { opacity: 0; transform: translateY(10px); }
.proc__step:hover .fig__ghost { opacity: 1; transform: none; }
/* the layers: drawn 26 units apart, they close to touching (10 high) */
.proc__step:hover .fig__layer--1 { transform: translateY(16px); }
.proc__step:hover .fig__layer--2 { transform: translateY(32px); }
.proc__step:hover .fig__layer--3 { transform: translateY(48px); }

@media (max-width: 1100px) {
  .proc__row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3rem 0; }
  .proc__step:nth-child(odd) { padding-left: 0; border-left: 0; }
}
@media (max-width: 640px) {
  .proc__row { grid-template-columns: 1fr; gap: 3rem; }
  .proc__step, .proc__step + .proc__step { padding: 0; border-left: 0; }
  .proc__step + .proc__step { padding-top: 3rem; border-top: 1px solid var(--color-line); }
}
@media (prefers-reduced-motion: reduce) {
  .fig__rise, .fig__lift, .fig__layer, .fig__ghost { transition: none; }
  .fig__ghost { opacity: 1; transform: none; }
  .proc__step:hover .fig__rise, .proc__step:hover .fig__lift, .proc__step:hover [class*="fig__layer--"] { transform: none; }
}

/* ====================== OUTCOMES / CAPABILITIES (orbit) ==================
   gonimbly.com's "Turn obstacles into outcomes": a centre button, seven
   blocks fanned on an ellipse around it, a dashed line from the centre to
   each block's inner edge, and the block's line of copy revealed on hover.
   main.js (orbit) sets --x/--y per block from the field's width, the same
   ellipse as theirs (0.38w by 0.17w), and draws the lines; the fly-out is a
   CSS transition to those variables, fired when the field scrolls into view.
   Below 62rem the blocks are a plain list with the copy always visible. */
.orbit__inner { max-width: var(--container-max); margin-inline: auto; }
.orbit__head { display: flex; flex-direction: column; align-items: center; gap: 1rem; text-align: center; }
.orbit__head h2 { max-width: 40rem; }
.orbit__lede { max-width: 40rem; font-size: var(--text-medium); color: var(--color-muted-text); }
.orbit__list { margin: 0; padding: 0; list-style: none; }
.orb__idx {
  display: grid; place-items: center; flex: none; width: 1.75rem; height: 1.75rem;
  background: var(--color-neutral-darkest); color: #fff;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .5625rem; letter-spacing: .04em;
}
.orb__bar { position: relative; border: 1px solid var(--color-ink); background: var(--color-bg-page); }
.orb__bar:focus-visible { outline: 2px solid var(--brand-accent); outline-offset: 2px; }
.orb__title { display: block; padding: .5rem .75rem; font-size: var(--text-regular); color: var(--color-headline); white-space: nowrap; }
.orb__desc { padding: .75rem; font-size: var(--text-small); line-height: 1.45; color: var(--color-muted-text); border-top: 1px solid var(--color-ink); }

@media (max-width: 61.9375rem) {
  .orbit__field { display: flex; flex-direction: column; gap: 2.5rem; margin-top: 3rem; }
  .orbit__center { align-self: center; }
  .orbit__list { display: grid; grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); gap: 1rem; }
  .orb { display: flex; align-items: flex-start; gap: .5rem; }
  .orb__bar { flex: 1; }
  .orb__title { white-space: normal; }
  .orbit__lines { display: none; }
}
@media (min-width: 62rem) {
  .orbit__field { position: relative; height: 32rem; margin-top: 3rem; }
  .orbit__lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; color: var(--color-ink); }
  .orbit__lines line { stroke: currentColor; stroke-width: 1; stroke-dasharray: 4 4; opacity: 0; transition: opacity var(--duration-slow) var(--ease-out) .5s; }
  .orbit__field.is-live .orbit__lines line { opacity: .3; }
  /* the glow behind the centre button, as on theirs, from the page's own tint */
  .orbit__center { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 2; }
  .orbit__center::before {
    content: ""; position: absolute; inset: -4rem -6rem; z-index: -1; pointer-events: none;
    background: radial-gradient(closest-side, rgba(31, 111, 99, .10), transparent);
  }
  .orb {
    position: absolute; left: 50%; top: 50%; width: max-content; min-width: 15rem;
    display: flex; align-items: flex-start; gap: .5rem;
    transform: translate(-50%, -50%);
    opacity: 0;
    transition: transform .8s var(--ease-out) calc(var(--i) * 50ms), opacity .5s var(--ease-out) calc(var(--i) * 50ms);
  }
  /* blocks on the left of the centre carry their index on the right, so the
     index always faces the line; main.js sets .orb--left from the position */
  .orb--left { flex-direction: row-reverse; }
  .orbit__field.is-live .orb { opacity: 1; transform: translate(calc(-50% + var(--x, 0px)), calc(-50% + var(--y, 0px))); }
  .orb__bar { flex: 1; transition: background-color var(--duration-fast); }
  .orb__desc {
    position: absolute; left: -1px; right: -1px; top: 100%; z-index: 3;
    margin: 0; background: var(--color-bg-page); border: 1px solid var(--color-ink); border-top: 0;
    clip-path: inset(0 0 100% 0); transition: clip-path .3s var(--ease-out);
  }
  .orb:hover .orb__bar, .orb:focus-within .orb__bar { background: var(--color-badge-bg); z-index: 4; }
  .orb:hover .orb__desc, .orb:focus-within .orb__desc { clip-path: inset(0 0 0 0); }
  .orb:hover, .orb:focus-within { z-index: 5; }
}
@media (prefers-reduced-motion: reduce) {
  .orb, .orbit__lines line { transition: none; }
}

/* ============================ CASE STUDY (proof) =========================
   One wide card split main | facts. The result figures are set large; they
   are the brief's XX placeholders until a case study exists. */
.case { background: var(--color-bg-subtle); border-top: 1px solid var(--color-line); border-bottom: 1px solid var(--color-line); }
.case__inner { display: flex; flex-direction: column; gap: 3.5rem; max-width: var(--container-max); margin-inline: auto; }
.case__card { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); border: 1px solid var(--color-line-soft); background: var(--color-bg-page); }
.case__main { display: flex; flex-direction: column; gap: 1.25rem; padding: 3rem; border-right: 1px solid var(--color-line-soft); }
.case__cat { font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); text-transform: uppercase; color: var(--brand-accent-ink); }
.case__title { font-family: var(--font-heading); font-size: var(--h4-size); line-height: 1.25; color: var(--color-headline); }
.case__cta { margin-top: auto; padding-top: 1.5rem; align-self: flex-start; }
.case__facts { display: flex; flex-direction: column; margin: 0; }
.case__fact { display: grid; grid-template-columns: 7rem minmax(0, 1fr); gap: 1.5rem; padding: 1.75rem 2.5rem; }
.case__fact + .case__fact { border-top: 1px solid var(--color-line-soft); }
.case__fact dt { font-size: var(--text-tiny); letter-spacing: var(--tagline-tracking); text-transform: uppercase; color: var(--color-muted); padding-top: .25rem; }
.case__fact dd { margin: 0; font-size: var(--text-regular); color: var(--color-muted-text); }
.case__results { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.5rem; margin: 0; padding: 0; list-style: none; }
.case__results li { display: flex; flex-direction: column; gap: .25rem; }
.case__results b { font-family: var(--font-heading); font-weight: 400; font-size: 2.25rem; line-height: 1; color: var(--color-headline); }
.case__results span { font-size: var(--text-small); color: var(--color-muted); }

@media (max-width: 1000px) {
  .case__card { grid-template-columns: 1fr; }
  .case__main { border-right: 0; border-bottom: 1px solid var(--color-line-soft); }
}
@media (max-width: 640px) {
  .case__main { padding: 1.75rem 1.25rem; }
  .case__fact { grid-template-columns: 1fr; gap: .5rem; padding: 1.25rem; }
  .case__results { grid-template-columns: 1fr; gap: 1rem; }
}

/* =============================== RESPONSIVE ============================== */
@media (max-width: 1200px) {
  :root { --h1-size: 3rem; --h2-size: 2.5rem; --section-inline: 2.5rem; }
  .links { gap: 1.25rem; }
}

@media (max-width: 1000px) {
  .nav, .actions .lang, .actions .pill { display: none; }

  .legal-facts__row { grid-template-columns: 1fr; gap: .375rem; }
  .menu-toggle { display: flex; }
  .site-header.menu-open .mobile { display: block; }
  .bar { justify-content: space-between; }
  .logo { margin-right: auto; }

  .problems__row, .insights__cards { grid-template-columns: 1fr; gap: 2.5rem; }
  .cta__photo-layout { flex-direction: column; gap: 0; }
  .cta__photo { flex: none; width: 100%; min-height: 16rem; }
  .cta__copy { padding: 2.5rem; }
  .brand-col { flex: 1 1 100%; }
  .link-cols { grid-auto-flow: row; grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  :root { --h1-size: 2.5rem; --h2-size: 2rem; --h4-size: 1.375rem; --section-pad: var(--section-gap-mobile); --section-inline: 1.25rem; }
  .hero { min-height: 92svh; }
  .hero__copy { padding-bottom: 3rem; }
  .logo img { height: 26px; }
  .logo--footer img { height: 30px; }
  .credits { flex-direction: column; align-items: flex-start; }
  .link-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
