/* NIX — landing. Dieter Rams / Braun classic.
   Grid: 8px. No shadows, no radii, no gradients. One accent. */

@font-face {
  font-family: "PP Neue Montreal";
  src: url("../fonts/PPNeueMontreal-Light.woff2") format("woff2"),
       url("../fonts/PPNeueMontreal-Light.woff") format("woff");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "PP Neue Montreal";
  src: url("../fonts/PPNeueMontreal-Book.woff2") format("woff2"),
       url("../fonts/PPNeueMontreal-Book.woff") format("woff");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light dark;
  /* black & white for now — colour comes later */
  --nix-paper: #FFFFFF;    /* page ground */
  --nix-surface: #FFFFFF;  /* cards and chips, lifted by shadow */
  --nix-ink: #1A1A1A;      /* dark surfaces + type inside cards */
  --nix-on-ink: #FFFFFF;   /* type on ink surfaces */
  --nix-ink-soft: #8A8886;
  --nix-text: #1A1A1A;
  --nix-text-soft: #6B6965;
  --nix-orange: #1A1A1A; /* accent runs black while the site is monochrome */
  --nix-rule: #E4E2DE;

  --font-sans: "PP Neue Montreal", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 32px;
  --space-6: 48px;
  --space-8: 64px;

  --ease-out-expo: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-pop: cubic-bezier(0.34, 1.56, 0.64, 1);
}


/* ---- Dark theme ------------------------------------------------------- */

html[data-theme="dark"] {
  --nix-paper: #131312;
  --nix-surface: #201F1E;
  --nix-ink: #F4F3F1;
  --nix-on-ink: #131312;
  --nix-ink-soft: #A6A4A0;
  --nix-text: #F4F3F1;
  --nix-text-soft: #B3B1AD;
  --nix-orange: #F4F3F1;
  --nix-rule: #2E2D2B;
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) {
    --nix-paper: #131312;
    --nix-surface: #201F1E;
    --nix-ink: #F4F3F1;
    --nix-on-ink: #131312;
    --nix-ink-soft: #A6A4A0;
    --nix-text: #F4F3F1;
    --nix-text-soft: #B3B1AD;
    --nix-orange: #F4F3F1;
    --nix-rule: #2E2D2B;
  }
}

/* the ink logo turns white on the dark ground */
html[data-theme="dark"] .site-head__logo,
html[data-theme="dark"] .preloader__emblem {
  filter: brightness(0) invert(1);
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .site-head__logo,
  html:not([data-theme="light"]) .preloader__emblem {
    filter: brightness(0) invert(1);
  }
}

/* theme toggle: an outline dot that fills when the lights go out.
   Lives in the footer, next to the language switch */
.theme-toggle {
  width: 18px;
  height: 18px;
  padding: 0;
  border: 1.5px solid var(--nix-text);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}

html[data-theme="dark"] .theme-toggle {
  background: var(--nix-text);
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .theme-toggle {
    background: var(--nix-text);
  }
}

.theme-toggle:focus-visible {
  outline: 2px solid var(--nix-orange);
  outline-offset: 3px;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* THE DOCUMENT DOES NOT SCROLL. The story scrolls inside .page.
   Safari puts the page in a scroll view whose top inset is the status bar. The
   inset moves the LAYOUT VIEWPORT down, but not the content: whatever the
   document scrolls keeps riding up UNDER the bar, and stays visible there. And
   everything anchored to the layout viewport — fixed and sticky alike — is
   clipped to it, so no bar, no overpaint and no shield can ever be painted over
   that content. Measured on an iPhone, three times, before believing it.
   The only cure is to leave no content that CAN ride up there. A scroll
   container lives inside the viewport and clips its own content to its own box,
   so the band above it can only ever show the root canvas — which is paper.
   Costs Safari's toolbar auto-collapse and tap-status-bar-to-top. Worth it. */
html {
  height: 100%;
  overflow: hidden;
  /* the band under the status bar shows this, and nothing else, forever */
  background: var(--nix-paper);
}

body {
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--nix-paper);
  color: var(--nix-text);
  font-family: var(--font-sans);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* nothing moves behind the preloader — on the scroller, since the body no
   longer scrolls and cannot be locked */
body.is-loading .page {
  overflow: hidden;
}

/* White surfaces keep ink type — the shadow belongs to the grey ground only */
.nav-mode__option,
.plan,
.voice,
.btn {
  text-shadow: none;
}

.plan,
.voice {
  color: var(--nix-ink);
}

/* ---- Preloader --------------------------------------------------------
   The brand statement assembles itself, holds, then the whole sheet
   wipes upward revealing the page. */

.preloader {
  position: fixed;
  inset: 0;
  z-index: 88;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--nix-paper);
  padding: var(--space-8) var(--space-6);
}

.preloader__block {
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
}

.preloader__mark {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.preloader__emblem {
  height: 35px;
  width: auto;
  display: block;
  align-self: center;
  transform: scale(0);
  opacity: 0;
  transition: opacity 200ms ease-out 1000ms,
              transform 450ms var(--ease-pop) 1000ms;
}

.preloader__word {
  display: block;
  overflow: hidden; /* mask for the reveal */
  font-size: clamp(56px, 9vw, 104px);
  font-weight: 400; /* Book — only real weight; no faux bold */
  line-height: 1;
  letter-spacing: -0.02em;
}

.preloader__word-inner {
  display: inline-block;
  transform: translateY(110%);
  transition: transform 900ms var(--ease-out-expo);
}

.preloader__rule {
  border: 0;
  height: 1px;
  background: var(--nix-rule);
  position: relative;
  overflow: hidden;
  margin: var(--space-3) 0 var(--space-2);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 800ms var(--ease-in-out) 450ms;
}

.preloader__rule::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 18%;
  height: 100%;
  background: var(--nix-orange);
  transform: translateX(-100%);
}

.preloader--play .preloader__rule::after {
  animation: rule-scan 0.75s var(--ease-in-out) 1.35s 1 both;
}

@keyframes rule-scan {
  from { transform: translateX(-100%); }
  to { transform: translateX(680%); }
}

.preloader__tagline {
  font-size: clamp(17px, 2.2vw, 22px);
  font-weight: 300; /* Light */
  line-height: 1.45;
  letter-spacing: 0.005em;
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 700ms var(--ease-out-expo) 800ms,
              transform 700ms var(--ease-out-expo) 800ms;
}

/* assembly */
.preloader--play .preloader__word-inner {
  transform: none;
}

.preloader--play .preloader__emblem {
  opacity: 1;
  transform: scale(1);
}

.preloader--play .preloader__rule {
  transform: scaleX(1);
}

.preloader--play .preloader__tagline {
  opacity: 1;
  transform: none;
}

/* exit: the sheet wipes upward */
.preloader--exit {
  transform: translateY(-100%);
  transition: transform 800ms var(--ease-in-out);
}

.preloader--exit .preloader__block {
  transform: translateY(24px);
  opacity: 0.6;
  transition: transform 800ms var(--ease-in-out),
              opacity 800ms var(--ease-in-out);
}

/* ---- Header ---------------------------------------------------------- */

/* The stack, and it is load-bearing in both directions:
     menu overlay 80  — the header's own sheet, so it opens BENEATH the mark
     site-head    85
     preloader    88  — must cover the bar, or the menu button shows during the intro
     paper grain  90  — must wash OVER the bar, or the bar reads a shade darker
                        than the page it sits on (the grain lightens everything
                        under it, and an opaque bar above it gets none)
     app wall 95 / app doc 96 — the viewer covers everything
   Raise the bar past 88 and the preloader leaks. Past 90 and the bar goes dark.
   Both happened. */
.site-head {
  position: relative;
  z-index: 85;
  padding: var(--space-3) var(--space-6);
  display: flex;
  align-items: center;
  justify-content: center;
}

.site-head__brand {
  display: inline-block;
  line-height: 0;
}

.site-head__logo {
  height: 34px;
  width: auto;
  display: block;
}

/* ---- Page ------------------------------------------------------------ */

/* The scroller. Everything that scrolls, scrolls in here — see the note on
   html above. min-height:0 is what lets a flex item shrink enough to scroll at
   all; without it this box grows to its content and the page never moves. */
.page {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* hidden, not clip: paired with a scrollable axis, `clip` computes to `hidden`
     anyway (checked in both engines), so say so. The old warning about
     overflow-x:hidden was about the BODY, where it conferred scroll-container
     semantics and broke a sticky header. This is a scroll container already, and
     nothing here is sticky. The ribbon runs 100vw and needs the clip. */
  overflow-x: hidden;
  scroll-behavior: smooth;
  overscroll-behavior-y: none;
  -webkit-overflow-scrolling: touch;
  display: flex;
  /* column, NOT row. The footer lives in here now (it has to — outside the
     scroller a body that cannot scroll pins it to the foot of the screen for the
     whole story). Beside the chooser it stole its width and sat in a column of
     its own down the right-hand edge. */
  flex-direction: column;
  align-items: center;
  padding: var(--space-6) var(--space-3);
}

/* the chooser floats in whatever room the footer leaves it */
.page > .nav-mode {
  margin: auto 0;
}

@media (prefers-reduced-motion: reduce) {
  .page {
    scroll-behavior: auto;
  }
}

/* ---- Navigation mode switch ------------------------------------------
   A Braun slide switch: two positions, one thumb, an LED that lights
   up when assistance is on. */

.nav-mode {
  text-align: center;
}

.nav-mode__label {
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--nix-text-soft);
  margin-bottom: 10px;
}

.nav-mode__sub {
  font-size: clamp(26px, 4vw, 40px);
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--nix-text);
  margin-bottom: var(--space-6);
}

.nav-mode__switch {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
  width: min(760px, 92vw);
  margin: 0 auto;
}

/* Two quiet cards; the chosen one sits a little prouder and lights its LED */
.nav-mode__option {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: var(--space-6) var(--space-3);
  border: 0;
  border-radius: 24px;
  /* pure white card lifted off the white page by layered shadow */
  background: var(--nix-surface);
  box-shadow: 0 1px 2px rgba(26, 26, 26, 0.06),
              0 14px 36px -14px rgba(26, 26, 26, 0.16);
  font-family: var(--font-sans);
  text-align: center;
  cursor: pointer;
  transition: box-shadow 250ms ease,
              transform 250ms var(--ease-out-expo);
}

.nav-mode__option:hover {
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(26, 26, 26, 0.06),
              0 22px 48px -16px rgba(26, 26, 26, 0.22);
}


.nav-mode__option-title {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 17px;
  letter-spacing: 0.02em;
  color: var(--nix-ink);
}

.nav-mode__option-desc {
  max-width: 280px;
  font-size: 14px;
  font-weight: 300;
  line-height: 1.55;
  color: var(--nix-ink-soft);
}

.nav-mode__option:focus-visible {
  outline: 2px solid var(--nix-orange);
  outline-offset: 2px;
}

@media (max-width: 480px) {
  .nav-mode__switch {
    grid-template-columns: 1fr;
  }
}

/* Card icon (Lucide): dim by default, wakes on hover/focus */
.nav-mode__icon {
  display: inline-flex;
  color: var(--nix-ink);
  opacity: 0.55;
  transition: opacity 300ms ease, transform 300ms var(--ease-pop);
}
.nav-mode__icon svg {
  width: 26px;
  height: 26px;
}

.nav-mode__option:hover .nav-mode__icon,
.nav-mode__option:focus-visible .nav-mode__icon {
  opacity: 1;
  transform: translateY(-1px);
}

/* Leaving the selector */
.nav-mode {
  transition: opacity 350ms var(--ease-out-expo),
              transform 350ms var(--ease-out-expo);
}

.nav-mode.is-off {
  opacity: 0;
  transform: translateY(-10px);
  pointer-events: none;
}

/* ---- Voice: the guided-tour dock -------------------------------------- */

.voice {
  position: fixed;
  left: 50%;
  bottom: 20px;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 14px;
  width: min(520px, calc(100vw - 32px));
  padding: 12px 12px 12px 22px;
  background: var(--nix-surface);
  border-radius: 999px;
  box-shadow: 0 2px 10px rgba(26, 26, 26, 0.16);
  opacity: 0;
  transform: translateX(-50%) translateY(14px);
  transition: opacity 450ms var(--ease-out-expo),
              transform 450ms var(--ease-out-expo);
}

.voice.is-on {
  opacity: 1;
  transform: translateX(-50%);
}

.voice__wave {
  flex: 1;
  min-width: 0;
  height: 36px;
}

.voice__led {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--nix-orange);
  animation: voice-led 2s ease-in-out infinite;
}

@keyframes voice-led {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

.voice__back {
  flex: none;
  padding: 10px 24px;
  border: 0;
  border-radius: 999px;
  background: var(--nix-ink);
  color: var(--nix-paper);
  font-family: var(--font-sans);
  font-size: 13px;
  cursor: pointer;
}

.voice__back:focus-visible {
  outline: 2px solid var(--nix-orange);
  outline-offset: 2px;
}

/* The section being read carries an orange rule in the margin */
.is-reading {
  position: relative;
}

.is-reading::after {
  content: "";
  position: absolute;
  left: -28px;
  top: 12px;
  bottom: 12px;
  width: 2px;
  background: var(--nix-orange);
}

/* the closing band clips its margins and owns a ::before ember —
   dock the rule inside it */
.cta-band.is-reading::after {
  left: 14px;
  top: 20px;
  bottom: 20px;
}

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

@media (max-width: 720px) {
  .is-reading::after {
    left: -12px;
  }
}

/* ---- Landing (manual mode) -------------------------------------------- */

.page--flow {
  display: block;
  padding: 0 var(--space-6) var(--space-8);
}

.landing__inner {
  max-width: 1080px;
  margin: 0 auto;
}

.landing__block,
.landing__hero,
.cta-band {
  scroll-margin-top: 88px;
}

.landing__block {
  min-height: 80svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  margin-bottom: var(--space-6);
}

/* body copy: a centred column with both edges flush, not ragged */
.landing__block .landing__text {
  text-align: justify;
  text-align-last: center;
  margin-left: auto;
  margin-right: auto;
}

/* Hero */
.landing__hero {
  position: relative;
  /* fill the first screen: viewport minus header (73px) */
  min-height: calc(100svh - 73px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding: 0;
  max-width: 880px;
  margin: 0 auto;
  text-align: center;
}

/* the two auto margins split the free space: text block floats centred
   between the header and the half-buried orbit */
.landing__hero .landing__lead {
  margin-top: auto;
}

/* only the top arc of the orbit shows; the rest dissolves at the fold.
   Full bleed: the outer ring spans the viewport, capped on huge screens. */
.orbit-well {
  --size: min(1240px, calc(100vw - 72px));
  margin-top: auto;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  /* never taller than half the orbit, never deeper than half the screen */
  height: min(calc(var(--size) / 2 + 32px), 48svh);
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 96%);
  mask-image: linear-gradient(to bottom, #000 55%, transparent 96%);
}

.landing__hero .landing__text--intro {
  margin-left: auto;
  margin-right: auto;
}

.landing__hero .landing__cta {
  justify-content: center;
}

.landing__cta {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-4);
  flex-wrap: wrap;
}

.btn {
  display: inline-block;
  padding: 14px 36px;
  border: 0;
  border-radius: 999px;
  font-family: var(--font-sans);
  font-size: 14px;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  transition: transform 200ms var(--ease-out-expo),
              box-shadow 200ms var(--ease-out-expo),
              background 200ms ease;
}

.btn--primary {
  background: var(--nix-ink);
  color: var(--nix-on-ink);
  box-shadow: 0 1px 3px rgba(26, 26, 26, 0.14);
}

.btn--primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 6px rgba(26, 26, 26, 0.16);
}

.btn--ghost {
  background: var(--nix-surface);
  color: var(--nix-ink);
  box-shadow: 0 1px 3px rgba(26, 26, 26, 0.07);
}

.btn--ghost:hover {
  background: var(--nix-surface);
}

.btn--paper {
  background: var(--nix-paper);
  color: var(--nix-ink);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.22);
}

.btn--paper:hover {
  transform: translateY(-1px);
}

/* Two-column story blocks: copy narrow, visual wide */
.landing__split {
  display: grid;
  grid-template-columns: 2fr 3fr;
  gap: var(--space-8);
  align-items: center;
}

/* Visual: the ERP constellation — apps wired into one hub */
.erp {
  display: block;
  width: 100%;
  height: auto;
}

.erp__lines line {
  stroke: var(--nix-rule);
  stroke-width: 1;
}

.erp__pulse {
  fill: var(--nix-orange);
}

.erp__chips rect {
  fill: var(--nix-surface);
  filter: drop-shadow(0 1px 1px rgba(26, 26, 26, 0.06))
          drop-shadow(0 8px 14px rgba(26, 26, 26, 0.1));
}

.erp__chips text {
  font-family: var(--font-sans);
  font-size: 13px;
  fill: var(--nix-text);
  text-anchor: middle;
}

.erp__hub rect {
  fill: var(--nix-ink);
  filter: drop-shadow(0 2px 5px rgba(26, 26, 26, 0.16));
}

.erp__hub text {
  font-family: var(--font-sans);
  font-size: 17px;
  fill: var(--nix-paper);
  text-anchor: middle;
}

.erp__hub-led {
  fill: var(--nix-orange);
  animation: voice-led 2s ease-in-out infinite;
}

.erp__caption {
  margin-top: var(--space-2);
  font-size: 13px;
  font-weight: 300;
  color: var(--nix-text-soft);
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .erp__pulse {
    display: none;
  }
  .erp__hub-led {
    animation: none;
  }
}

.landing__explore {
  margin-top: var(--space-3);
}

/* ---- Appverse: infinite canvas of Odoo apps --------------------------- */

.appverse {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: var(--nix-paper);
  opacity: 0;
  transition: opacity 350ms var(--ease-out-expo);
}

.appverse.is-on {
  opacity: 1;
}

.appverse__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  cursor: grab;
  touch-action: none;
}

.appverse__canvas.is-dragging {
  cursor: grabbing;
}

.appverse__top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-6);
  pointer-events: none;
}

.appverse__hint {
  font-size: 13px;
  font-weight: 300;
  letter-spacing: 0.02em;
  color: var(--nix-text-soft);
}

.appverse__close {
  pointer-events: auto;
  padding: 10px 28px;
  border: 0;
  border-radius: 999px;
  background: var(--nix-ink);
  color: var(--nix-paper);
  font-family: var(--font-sans);
  font-size: 13px;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(26, 26, 26, 0.14);
  transition: transform 200ms var(--ease-out-expo);
}

.appverse__close:hover {
  transform: translateY(-1px);
}

.appverse__close:focus-visible {
  outline: 2px solid var(--nix-orange);
  outline-offset: 2px;
}

@media (max-width: 600px) {
  .appverse__top {
    padding: var(--space-2) var(--space-3);
  }
}

/* The signs: five lines of recognition */
.signs__list {
  list-style: none;
  margin-top: var(--space-4);
}

.signs__list li {
  font-size: clamp(19px, 2.4vw, 26px);
  font-weight: 300;
  line-height: 1.4;
  color: #4A4846;
  margin-bottom: var(--space-3);
  max-width: 640px;
}

.signs__turn {
  margin-top: var(--space-6);
  font-size: clamp(19px, 2.4vw, 26px);
  font-weight: 400;
  line-height: 1.4;
  color: var(--nix-text);
  max-width: 640px;
}

/* The name: ERP explained */
.erp-name__def {
  margin: var(--space-4) 0;
  font-size: clamp(22px, 3vw, 32px);
  font-weight: 400;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--nix-text);
  max-width: 720px;
}

.erp-name__thats {
  margin-top: var(--space-3);
  font-size: 17px;
  font-weight: 400;
  color: var(--nix-text);
}

/* Mid-page CTA */
.landing__midcta {
  text-align: center;
  margin-bottom: 120px;
}

/* Industries: editorial rows — big names, hairlines, quiet hover */
.inds {
  margin-top: var(--space-4);
  border-top: 1px solid var(--nix-rule);
}

.ind {
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: var(--space-4);
  align-items: baseline;
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--nix-rule);
}

.inds .ind.is-in {
  transition: opacity 700ms var(--ease-out-expo),
              filter 700ms var(--ease-out-expo),
              transform 350ms var(--ease-out-expo);
}

.inds .ind.is-in:hover {
  transform: translateX(var(--space-2));
}

.ind__name {
  font-size: clamp(19px, 2.4vw, 26px);
  font-weight: 400;
  letter-spacing: -0.01em;
  display: flex;
  align-items: center;
  gap: 14px;
}

.ind__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--nix-orange);
  flex: none;
  transform: scale(0);
  transition: transform 350ms var(--ease-pop);
}

.ind:hover .ind__dot {
  transform: scale(1);
}

.ind__desc {
  font-size: 15px;
  font-weight: 300;
  line-height: 1.55;
  color: var(--nix-text-soft);
  transition: color 350ms ease;
}

.ind:hover .ind__desc {
  color: #4A4846;
}

/* Closing script line under the final CTA */
.cta-band__script {
  margin-top: var(--space-4);
  font-size: 14px;
  font-weight: 300;
  line-height: 1.6;
  color: #B8B6B3;
  max-width: 480px;
  margin-left: auto;
  margin-right: auto;
}

/* Odoo pricing link inside the plans note */
.plans__link {
  color: var(--nix-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---- How to start -----------------------------------------------------
   One panel, three tabs under it. The panel is the screen; the tabs are the
   steps. It walks itself, but the tabs are real buttons — someone who only
   cares what it costs can jump straight to step two. */

.start2 {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  width: min(600px, 100%);
  margin: var(--space-8) auto 0;
}

.start2__panel {
  position: relative;
  width: 100%;
  padding: var(--space-4);
  border-radius: 20px;
  background: var(--nix-surface);
  box-shadow: 0 2px 4px rgba(26, 26, 26, 0.06),
              0 22px 46px -16px rgba(26, 26, 26, 0.22);
  text-align: left;
}

.start2__panel-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: 10px;
}

.start2__panel-title {
  font-size: 17px;
  color: var(--nix-ink);
}

.start2__panel-meta {
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--nix-ink-soft);
  white-space: nowrap;
}

/* the step's own clock, so the wait is visible rather than just felt */
.start2__bar {
  display: block;
  height: 1px;
  margin-bottom: var(--space-3);
  background: var(--nix-rule);
}

.start2__bar-fill {
  display: block;
  width: 0;
  height: 100%;
  background: var(--c, var(--nix-text-soft));
}

.start2__rows {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-height: 96px; /* three rows — hold it, or the tabs jump between steps */
}

/* what we actually do at this stop, ticked off one at a time */
.start2__row {
  position: relative;
  padding-left: 28px;
  font-size: 14px;
  font-weight: 300;
  line-height: 1.4;
  color: var(--nix-ink);
  opacity: 0.32;
  animation: erp2-row-in 420ms var(--ease-out-expo) both;
  animation-delay: calc(var(--d, 0) * 70ms);
  transition: opacity 420ms var(--ease-out-expo);
}

.start2__row.is-on {
  opacity: 1;
}

.start2__row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 2px;
  width: 15px;
  height: 15px;
  border: 1.5px solid var(--nix-rule);
  border-radius: 4px;
  transition: background 300ms ease, border-color 300ms ease;
}

/* the tick, drawn from two borders — it snaps in once the box fills */
.start2__row::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 5px;
  width: 5px;
  height: 8px;
  border-right: 1.5px solid #FFFFFF;
  border-bottom: 1.5px solid #FFFFFF;
  transform: rotate(45deg) scale(0);
  transition: transform 300ms var(--ease-pop);
}

.start2__row.is-on::before {
  background: var(--c, var(--nix-ink));
  border-color: var(--c, var(--nix-ink));
}

.start2__row.is-on::after {
  transform: rotate(45deg) scale(1);
}

/* the tabs. Content-sized, so the three steps read as three different things */
.start2__tabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
}

.start2__tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border: 0;
  border-radius: 12px;
  background: var(--nix-surface);
  color: var(--nix-text-soft);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 400;
  cursor: pointer;
  opacity: 0.5;
  transition: color 380ms ease, background 380ms ease,
              opacity 380ms ease, transform 380ms var(--ease-out-expo);
}

.start2__tab:hover {
  opacity: 0.85;
}

/* the tint moves inside: a filled chip instead of a coloured outline */
.start2__tab.is-active {
  color: var(--nix-ink);
  background: rgba(var(--c-rgb, 26, 26, 26), 0.16);
  opacity: 1;
  transform: translateY(-2px);
}

.start2__tab.is-active .start2__tab-num {
  color: var(--c, inherit);
  opacity: 1;
}

.start2__tab:focus-visible {
  outline: 2px solid var(--nix-orange);
  outline-offset: 3px;
}

.start2__tab-num {
  font-size: 11px;
  letter-spacing: 0.08em;
  opacity: 0.75;
  transition: color 380ms ease, opacity 380ms ease;
}

/* every box ticked — the step gets stamped before we move on */
.start2__burst {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: 20px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 280ms ease;
}

.start2__panel.is-sealed .start2__burst {
  opacity: 1;
}

/* veils the ticked list rather than replacing it — the work stays visible
   underneath the stamp */
.start2__burst::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 20px;
  background: var(--nix-surface);
  opacity: 0.86;
}

.start2__seal {
  position: relative;
  display: grid;
  place-items: center;
  width: 76px;
  height: 76px;
  border-radius: 50%;
  background: var(--c, var(--nix-ink));
  box-shadow: 0 14px 34px -10px rgba(26, 26, 26, 0.45);
  transform: scale(0.35);
  opacity: 0;
  transition: transform 560ms var(--ease-pop), opacity 260ms ease;
}

.start2__panel.is-sealed .start2__seal {
  transform: scale(1);
  opacity: 1;
}

.start2__seal::after {
  content: "";
  width: 16px;
  height: 30px;
  margin-top: -6px;
  border-right: 3px solid #FFFFFF;
  border-bottom: 3px solid #FFFFFF;
  transform: rotate(45deg);
}

.start2__confetti {
  position: absolute;
  left: 50%;
  top: 38%;
  width: 0;
  height: 0;
  pointer-events: none;
  perspective: 700px; /* the strips tumble, and a tumble needs depth to read */
}

.start2__bit {
  position: absolute;
  left: 0;
  top: 0;
  width: 7px;
  height: 10px;
  border-radius: 2px;
  opacity: 0; /* the Web Animation owns it from here */
}

@media (prefers-reduced-motion: reduce) {
  .start2__bit { display: none; }
  .start2__seal { transition: none; }
}

/* The app grid answers the hand: one press and the whole catalogue lands */
.appgrid {
  cursor: pointer;
}

/* ---- The app wall -----------------------------------------------------
   Press any app in the grid and the catalogue opens as a plane you can throw
   in any direction. It never ends — which is the section's claim, handed to
   the reader instead of told to them. */

.appwall {
  position: fixed;
  inset: 0;
  z-index: 95;
  overflow: hidden;
  background: var(--nix-paper);
  cursor: grab;
  opacity: 0;
  visibility: hidden;
  transition: opacity 380ms var(--ease-out-expo), visibility 380ms;
}

.appwall[data-state="open"] {
  opacity: 1;
  visibility: visible;
}

.appwall.is-dragging {
  cursor: grabbing;
}

/* the plane has no edges — it fades out instead of stopping */
.appwall__plane {
  position: absolute;
  inset: 0;
  -webkit-mask-image: radial-gradient(ellipse 78% 78% at 50% 50%, #000 55%, transparent 100%);
  mask-image: radial-gradient(ellipse 78% 78% at 50% 50%, #000 55%, transparent 100%);
}

.appwall__tile {
  position: absolute;
  left: 0;
  top: 0;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  width: 110px;
  margin: 26px 0 0 14px;
  will-change: transform;
  user-select: none;
  -webkit-user-drag: none;
}

/* the icon answers the hand, not the tile: the tile's transform is written
   inline every frame by the drag loop, so a hover rule there would never win —
   and a transition on it would smear the drag */
.appwall__tile img {
  width: 54px;
  height: 54px;
  border-radius: 14px;
  pointer-events: none;
  transition: transform 200ms var(--ease-out-expo);
}

.appwall__tile:hover img {
  transform: scale(1.1);
}

.appwall__tile:hover span {
  color: var(--nix-text);
}

.appwall__tile span {
  font-size: 11px;
  font-weight: 300;
  letter-spacing: 0.01em;
  color: var(--nix-text-soft);
  white-space: nowrap;
  pointer-events: none;
}

.appwall__hint {
  position: absolute;
  left: 50%;
  bottom: 32px;
  transform: translateX(-50%);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--nix-text-soft);
  opacity: 0.65;
  pointer-events: none;
  transition: opacity 500ms ease;
}

/* once you have touched it, you know */
.appwall.is-touched .appwall__hint {
  opacity: 0;
}

.appwall__close {
  position: absolute;
  top: 22px;
  right: 26px;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--nix-text);
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 250ms ease;
}

.appwall__close:hover {
  opacity: 1;
}

.appwall__close svg {
  width: 22px;
  height: 22px;
}

/* The story behind must not scroll under the wall, or under the frame. The lock
   goes on the scroller, not on the body: the body has nothing left to lock. */
body.is-walled .page,
body.is-framed .page {
  overflow: hidden;
}

/* ---- The app viewer ---------------------------------------------------
   Press an app and its Odoo page opens over the site. Handing a visitor to
   odoo.com and hoping they come back is not a plan. */

.appdoc {
  position: fixed;
  inset: 0;
  z-index: 96;
  display: flex;
  flex-direction: column;
  background: var(--nix-paper);
  opacity: 0;
  visibility: hidden;
  transition: opacity 320ms var(--ease-out-expo), visibility 320ms;
}

.appdoc[data-state="open"] {
  opacity: 1;
  visibility: visible;
}

.appdoc__bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 0 0 auto;
  padding: 14px var(--space-3) 14px var(--space-6);
  border-bottom: 1px solid var(--nix-rule);
}

.appdoc__title {
  font-size: 15px;
  color: var(--nix-text);
}

.appdoc__out {
  margin-left: auto;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--nix-text-soft);
  text-decoration: none;
  transition: color 200ms ease;
}

.appdoc__out:hover {
  color: var(--nix-text);
}

.appdoc__close {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--nix-text);
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 200ms ease;
}

.appdoc__close:hover {
  opacity: 1;
}

.appdoc__close svg {
  width: 20px;
  height: 20px;
}

.appdoc__frame {
  flex: 1 1 auto;
  width: 100%;
  border: 0;
  background: #FFFFFF;
}

/* ---- FAQ --------------------------------------------------------------
   Same hairlines as the rail. An answer is a disclosure, not a card. */

.faq {
  width: min(720px, 100%);
  margin: var(--space-8) auto 0;
  text-align: left;
  border-top: 1px solid var(--nix-rule);
}

.faq__item {
  border-bottom: 1px solid var(--nix-rule);
}

.faq__q {
  position: relative;
  list-style: none;
  cursor: pointer;
  padding: var(--space-3) var(--space-6) var(--space-3) var(--space-2);
  font-size: 18px;
  font-weight: 400;
  transition: color 250ms ease;
}

.faq__q::-webkit-details-marker {
  display: none;
}

.faq__q:hover {
  color: var(--nix-text);
}

/* a chevron, drawn from two borders — it turns over when the answer opens */
.faq__q::after {
  content: "";
  position: absolute;
  right: var(--space-3);
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  opacity: 0.5;
  transform: translateY(-70%) rotate(45deg);
  transition: transform 300ms var(--ease-in-out);
}

.faq__item[open] .faq__q::after {
  transform: translateY(-30%) rotate(-135deg);
}

.faq__q:focus-visible {
  outline: 2px solid var(--nix-orange);
  outline-offset: -2px;
}

.faq__a {
  padding: 0 var(--space-6) var(--space-4) var(--space-2);
  font-size: 15px;
  font-weight: 300;
  line-height: 1.6;
  color: var(--nix-text-soft);
  max-width: 62ch;
}

.faq__item[open] .faq__a {
  animation: soft-rise 380ms var(--ease-out-expo);
}

@keyframes soft-rise {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* Plans note */
.plan__pitch {
  margin-bottom: var(--space-3);
  font-size: 13px;
  font-weight: 300;
  line-height: 1.5;
  color: var(--nix-ink-soft);
}

/* Pro shows the whole catalogue, moving. A card cannot hold 27 rows, and a
   scrollbar would say "here is a list"; this says "the list does not end". */
.plan__stream {
  position: relative;
  /* flex-basis 0, NOT auto. With auto the basis is the content height — and the
     content is 2 copies of 23 rows, ~2200px — so overflow:hidden clipped it but
     the card still grew to that height. Basis 0 means the stream contributes
     nothing to the card's intrinsic height; it just fills whatever the grid
     leaves once the tallest card (Essential) has set the row. */
  flex: 1 1 0;
  min-height: 240px;
  overflow: hidden;
  margin: var(--space-2) 0 var(--space-3);
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
}

.plan__stream-track {
  animation: plan-stream 36s linear infinite;
}

/* margin, not flex gap: the loop slides exactly half the track, and a gap
   between the two copies would be one gap short of that */
.plan__stream-row {
  margin-bottom: var(--space-2);
}

@keyframes plan-stream {
  from { transform: translateY(0); }
  to { transform: translateY(-50%); }
}

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

/* AI Native: the tide sits in its own dark well inside the light card, so the
   wireframe has a night to glow against */
.plan__tide {
  position: relative;
  flex: 1 1 0;
  min-height: 210px;
  margin: var(--space-2) 0 var(--space-3);
  overflow: hidden;
  border-radius: 14px;
  background: #0E0E10;
  cursor: crosshair;
}

.plan__tide-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* the horizon fades out, and the corners fall away */
.plan__tide::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(ellipse 70% 60% at 50% 55%, transparent 30%, rgba(14, 14, 16, 0.85) 100%);
}

.plan__tide-mark {
  position: absolute;
  z-index: 2;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  color: #FFFFFF;
  pointer-events: none;
  animation: tide-pulse 3.4s var(--ease-in-out) infinite;
}

.plan__tide-mark svg {
  width: 30px;
  height: 30px;
  filter: drop-shadow(0 0 10px rgba(135, 90, 123, 0.9))
          drop-shadow(0 0 22px rgba(0, 160, 157, 0.55));
}

@keyframes tide-pulse {
  0%, 100% { opacity: 0.82; transform: translate(-50%, -50%) scale(1); }
  50% { opacity: 1; transform: translate(-50%, -50%) scale(1.08); }
}

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

.plans__note {
  margin-top: var(--space-3);
  font-size: 13px;
  font-weight: 300;
  color: var(--nix-text-soft);
  max-width: 560px;
}

/* Plan bullets */
.plan__list {
  list-style: none;
  margin-top: var(--space-2);
}

.plan__list li {
  position: relative;
  padding-left: 18px;
  font-size: 14px;
  font-weight: 300;
  line-height: 1.5;
  color: var(--nix-text-soft);
  margin-bottom: 8px;
}

.plan__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--nix-orange);
}

.plan--enterprise .plan__list li {
  color: var(--nix-on-ink);
  opacity: 0.62;
}

.plan--enterprise .plan__list li::before {
  background: currentColor;
}

/* Closing band */
/* the closing section is plain text now; the class remains for the tour */

.cta-band__title {
  font-size: clamp(26px, 4vw, 40px);
  font-weight: 400;
  color: var(--nix-paper);
  letter-spacing: -0.01em;
}

.cta-band__text {
  font-size: 16px;
  font-weight: 300;
  color: #B8B6B3;
  margin: var(--space-2) 0 var(--space-4);
}


.landing__lead {
  font-size: clamp(26px, 4vw, 40px);
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: -0.01em;
}

.landing__headline {
  /* same scale as the hero lead */
  font-size: clamp(26px, 4vw, 40px);
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin-bottom: var(--space-2);
}

.landing__text {
  font-size: 17px;
  font-weight: 300;
  line-height: 1.6;
  max-width: 560px;
}

.landing__text--intro {
  margin-top: var(--space-2);
  font-size: 19px;
  color: var(--nix-text-soft);
}

.landing__text + .landing__text {
  margin-top: var(--space-2);
}

/* Plans */
.plans {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.plan {
  border-radius: 20px;
  background: var(--nix-surface);
  box-shadow: 0 1px 2px rgba(26, 26, 26, 0.05),
              0 14px 36px -14px rgba(26, 26, 26, 0.16);
  padding: var(--space-4) var(--space-3);
  display: flex;
  flex-direction: column;
}

.plan__name {
  font-size: 18px;
  font-weight: 400;
  margin-bottom: var(--space-1);
}

.plan__desc {
  font-size: 14px;
  font-weight: 300;
  line-height: 1.55;
  color: var(--nix-text-soft);
}

.plan__contact {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
  transition: opacity 200ms ease;
}
.plan__contact:hover {
  opacity: 0.7;
}

.plan__note {
  margin-left: 7px;
  font-size: 12px;
  font-weight: 300;
  letter-spacing: 0;
  color: var(--nix-text-soft);
}

/* Odoo app modules configured by each plan, pinned to the card's bottom. */
.plan__apps {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: auto;
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--nix-rule);
}
.plan__app {
  width: 36px;
  height: 36px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(128, 128, 128, 0.12);
  box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.16);
}
.plan__app img {
  width: 64%;
  height: 64%;
  display: block;
}

/* Vertical module list: icon + name + what we do with it. */
.plan__inc {
  margin: 2px 0 var(--space-1);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--nix-text-soft);
}
.plan--enterprise .plan__inc {
  color: var(--nix-on-ink);
  opacity: 0.55;
}

/* the AI Native card flips with the theme — white card on dark, black card on
   light — so its copy follows --nix-on-ink, not the page's soft grey, which
   was washing out against the white */
.plan--enterprise .plan__pitch {
  color: var(--nix-on-ink);
  opacity: 1;
}
.plan__mods {
  list-style: none;
  padding: 0;
  margin: var(--space-2) 0 var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.plan__mod {
  display: flex;
  align-items: center;
  gap: 11px;
}

.plan__mod--link {
  cursor: pointer;
  transition: opacity 200ms ease;
}

.plan__mod--link:hover {
  opacity: 0.75;
}

.plan__mod--link:hover .plan__mod-name {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.plan__mod .plan__app {
  flex: 0 0 auto;
}
.plan__mod-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.plan__mod-name {
  font-size: 14px;
  font-weight: 400;
  line-height: 1.3;
}
.plan__mod-desc {
  font-size: 12.5px;
  font-weight: 300;
  line-height: 1.4;
  color: var(--nix-text-soft);
}
.plan--enterprise .plan__mod-desc {
  color: var(--nix-on-ink);
  opacity: 0.6;
}
.plan--enterprise .plan__apps {
  border-bottom-color: rgba(244, 243, 241, 0.16);
}

.plan__cta {
  display: block;
  margin-top: auto;
  padding: 11px 16px;
  border-radius: 11px;
  text-align: center;
  text-decoration: none;
  font-family: var(--font-sans);
  font-size: 14px;
  letter-spacing: 0.01em;
  color: inherit;
  border: 1px solid currentColor;
  transition: background-color 200ms ease;
}
.plan__cta:hover {
  background: rgba(128, 128, 128, 0.12);
}

/* Social proof: owners in their own words (below the industries wheel). */
.quotes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
  width: min(960px, 100%);
  margin: var(--space-8) auto 0;
}
.quote {
  position: relative;
  margin: 0;
  padding: var(--space-4) var(--space-3);
  border-radius: 20px;
  background: var(--nix-surface);
  box-shadow: 0 1px 2px rgba(26, 26, 26, 0.05),
              0 14px 36px -14px rgba(26, 26, 26, 0.16);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  text-align: left;
}
.quote::before {
  content: "\201C";
  font-family: var(--font-sans);
  font-size: 44px;
  line-height: 0.7;
  color: var(--nix-text-soft);
  opacity: 0.35;
}
.quote__text {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 300;
  line-height: 1.55;
}
.quote__by {
  margin-top: auto;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--nix-text-soft);
}
.quotes .quote:nth-child(1) { transition-delay: 60ms; }
.quotes .quote:nth-child(2) { transition-delay: 160ms; }
.quotes .quote:nth-child(3) { transition-delay: 260ms; }

/* Testimonials ribbon: an auto-scrolling marquee of quote cards. */
.ribbon {
  /* Breaks out of the 1080px column — more of it is in play than you can read
     at once. NO margin-left: calc(50% - 50vw) here. That trick assumes block
     layout; .landing__block is a centred flex column, so the negative margin
     feeds back into the centring and shifts the ribbon by half again, dragging
     its left fade off-screen. A 100vw flex item centred in a centred column
     already lands exactly on the viewport. */
  width: 100vw;
  margin-top: var(--space-8);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 11%, #000 89%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 11%, #000 89%, transparent);
}
.ribbon__track {
  display: flex;
  width: max-content;
  animation: ribbon-scroll 90s linear infinite;
}
/* the ribbon itself no longer fades in as one block — its cards do, left to
   right, the way the menu cards arrive */
.ribbon.reveal {
  opacity: 1;
  transform: none;
  filter: none;
}
.ribbon .vcard {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 520ms var(--ease-out-expo),
              transform 520ms var(--ease-out-expo);
  transition-delay: calc(var(--k, 0) * 90ms);
}
.ribbon.is-in .vcard {
  opacity: 1;
  transform: none;
}
.ribbon:hover .ribbon__track {
  animation-play-state: paused;
}
@keyframes ribbon-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
.vcard {
  flex: 0 0 auto;
  width: 320px;
  margin: 0 8px;
  padding: var(--space-6) var(--space-4);
  border-radius: 22px;
  background: var(--nix-surface);
  box-shadow: 0 1px 2px rgba(26, 26, 26, 0.05),
              0 14px 36px -14px rgba(26, 26, 26, 0.16);
  display: flex;
  flex-direction: column;
  text-align: center;
  white-space: normal;
  text-decoration: none;
  color: inherit;
  transition: transform 260ms var(--ease-out-expo),
              box-shadow 260ms var(--ease-out-expo);
}
.vcard:hover {
  transform: translateY(-3px);
  box-shadow: 0 2px 4px rgba(26, 26, 26, 0.06),
              0 22px 48px -16px rgba(26, 26, 26, 0.22);
}
.vcard__ind {
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--nix-text-soft);
}
.vcard__text {
  margin: var(--space-3) 0 0;
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 300;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.vcard__name {
  margin-top: auto;
  padding-top: var(--space-3);
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 400;
}
.vcard__co {
  margin-top: 2px;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--nix-text-soft);
}
.vcard__avatar {
  align-self: center;
  margin-top: 12px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: #fff;
}
@media (prefers-reduced-motion: reduce) {
  .ribbon__track { animation: none; }
}

/* Enterprise: the black Braun unit in the lineup */
.plan--enterprise {
  background: var(--nix-ink);
  color: var(--nix-on-ink);
}

.plan--enterprise .plan__name {
  color: var(--nix-paper);
}

.plan--enterprise .plan__name::after {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  margin-left: 8px;
  vertical-align: middle;
}

.plan--enterprise .plan__desc {
  color: var(--nix-on-ink);
  opacity: 0.62;
}

.plan--enterprise .plan__note {
  color: var(--nix-on-ink);
  opacity: 0.62;
}

.landing__back {
  margin-top: 0;
}

/* Scroll reveal */
.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 900ms var(--ease-out-expo) 140ms,
              transform 900ms var(--ease-out-expo) 140ms,
              filter 900ms var(--ease-out-expo) 140ms;
}

.reveal.is-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

@media (max-width: 720px) {
  .plans,
  .inds,
  .quotes {
    grid-template-columns: 1fr;
  }
  /* the tabs drop their labels — three numbers still read as three steps,
     and the panel title already says which one you are on */
  .start2__tab-label {
    display: none;
  }
  .start2__tab {
    padding: 10px 18px;
  }
  .landing__midcta {
    margin-bottom: var(--space-8);
  }
  .page--flow {
    padding: 0 var(--space-3) var(--space-6);
  }
  .landing__split {
    grid-template-columns: 1fr;
    gap: var(--space-4);
  }
  .landing__hero {
    min-height: calc(100svh - 57px - 24px);
    padding: var(--space-4) 0;
  }
  .landing__block {
    margin-bottom: var(--space-8);
  }
}

/* ---- Footer ---------------------------------------------------------- */

.foot {
  padding: var(--space-3) var(--space-6);
}

.foot__line {
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--nix-text-soft);
  text-align: center;
}

.lang {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  letter-spacing: 0.08em;
}

.lang__opt {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  color: var(--nix-text-soft);
  opacity: 0.65;
  cursor: pointer;
  transition: opacity 250ms ease, color 250ms ease;
}

.lang__opt:hover,
.lang__opt.is-on {
  opacity: 1;
  color: var(--nix-text);
}

.lang__opt:focus-visible {
  outline: 2px solid var(--nix-orange);
  outline-offset: 3px;
}

.lang__sep {
  color: var(--nix-rule);
}

/* ---- Page reveal (under the wipe) ------------------------------------ */

.site-head__brand,
.nav-mode,
.foot__line {
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 600ms var(--ease-out-expo) 350ms,
              transform 600ms var(--ease-out-expo) 350ms;
}

.nav-mode {
  transform: none;
  transition-delay: 200ms;
}

.foot__line {
  transform: translateY(6px);
  transition-delay: 550ms;
}

body.is-ready .site-head__brand,
body.is-ready .nav-mode,
body.is-ready .foot__line {
  opacity: 1;
  transform: none;
}

/* ---- Reduced motion --------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .preloader {
    display: none;
  }
  .site-head__brand,
  .nav-mode,
  .foot__line {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ---- Small screens ---------------------------------------------------- */

@media (max-width: 600px) {
  .site-head {
    padding: var(--space-2) var(--space-3);
  }
  .preloader {
    padding: var(--space-6) var(--space-3);
  }
  .foot {
    padding: var(--space-2) var(--space-3);
  }
  .preloader__emblem {
    height: 26px;
  }
}

/* ==== Design life pass ================================================= */

/* Ink selection */
::selection {
  background: var(--nix-orange);
  color: var(--nix-paper);
}

/* Paper grain — barely-there print texture over everything */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  opacity: 0.028;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* The bar is FIXED, not sticky.
   Sticky only holds if every ancestor keeps overflow:visible and the browser
   agrees where the scrollport begins. On iOS Safari — collapsing toolbar, notch,
   translucent status bar — neither is dependable, and the page kept climbing
   over the bar and showing through the strip above it. Fixed answers to the
   viewport and to nothing else: no ancestor can take it hostage.
   It costs us the space it used to occupy, which is given back below. */
body.is-flow .site-head {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 85;  /* the stack is explained where .site-head is defined — read it */
  background: var(--nix-paper);
  /* Earns its keep only as a home-screen app, where the inset is real and the
     bar does start at the top of the screen. In a Safari tab it is 0 and this
     reads as plain padding. */
  padding-top: calc(var(--space-3) + env(safe-area-inset-top, 0px));
}

/* No overpaint here, and there must never be one again: the bar cannot paint
   above its own top edge on an iPhone. A 200px slab of paper was tried and the
   device clipped all but the 3px that fell inside the layout viewport. Nothing
   anchored to that viewport can reach the band under the status bar — the cure
   is that the document no longer scrolls, so nothing is up there to cover.
   See the note on html. */

/* out of flow — the story starts below the bar. The height is measured, not
   guessed: change the logo or the padding and this still lines up. */
body.is-flow .page--flow {
  padding-top: var(--head-h, 82px);
}

/* Content has to dissolve into the bar, not be guillotined by it. The AI Native
   card is white with a 20px radius: sliding under a hard edge, its rounded
   bottom read as a white slab bolted to the header. This fades the paper down
   over whatever passes beneath. */
body.is-flow .site-head::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: 28px;
  pointer-events: none;
  background: linear-gradient(to bottom, var(--nix-paper), transparent);
}

/* Hero: headline words rise out of a mask, one by one */
.landing__lead .w {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
}

.landing__lead .w__i {
  display: inline-block;
  transform: translateY(115%);
  transition: transform 900ms var(--ease-out-expo);
  transition-delay: calc(var(--d, 0) * 90ms);
}

.landing.lead-in .landing__lead .w__i {
  transform: none;
}





/* Hero orbit: the Odoo catalogue circling the NIX mark on two rings */
.orbit {
  /* --size inherits from .orbit-well */
  position: relative;
  width: var(--size, 640px);
  height: var(--size, 640px);
  /* satellites overhang the box by half a chip — the top margin absorbs it */
  margin: 32px auto 0;
}

.orbit__ring {
  position: absolute;
  border: 1px solid var(--nix-rule);
  border-radius: 50%;
}

.orbit__ring--outer { inset: 0; }
.orbit__ring--inner { inset: 19%; } /* inner orbit radius = 31% of size */

/* satellites ride the rings; counter-rotation keeps the icons upright */
.orbit__sat {
  position: absolute;
  top: 50%;
  left: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--nix-surface);
  /* realistic: tight contact shadow + falling ambient shadow */
  box-shadow: 0 1px 1px rgba(26, 26, 26, 0.06),
              0 4px 8px -2px rgba(26, 26, 26, 0.08),
              0 14px 28px -10px rgba(26, 26, 26, 0.14);
  will-change: transform;
}

.orbit__sat--outer {
  --r: calc(var(--size) / 2);
  width: 64px;
  height: 64px;
  margin: -32px 0 0 -32px;
  border-radius: 20px;
  animation: orbit-cw 90s linear infinite;
}

.orbit__sat--inner {
  --r: calc(var(--size) * 0.31);
  width: 54px;
  height: 54px;
  margin: -27px 0 0 -27px;
  border-radius: 17px;
  animation: orbit-ccw 60s linear infinite;
}

.orbit__sat img {
  width: 58%;
  height: 58%;
  display: block;
}

/* the brand dot out for a walk on the outer ring */
.orbit__spark {
  position: absolute;
  top: 50%;
  left: 50%;
  --r: calc(var(--size) / 2);
  --a: 140deg;
  width: 8px;
  height: 8px;
  margin: -4px 0 0 -4px;
  border-radius: 50%;
  background: var(--nix-orange);
  box-shadow: 0 1px 4px rgba(26, 26, 26, 0.25);
  animation: orbit-cw 36s linear infinite;
}

@keyframes orbit-cw {
  from {
    transform: rotate(var(--a, 0deg)) translateX(var(--r))
               rotate(calc(-1 * var(--a, 0deg)));
  }
  to {
    transform: rotate(calc(var(--a, 0deg) + 360deg)) translateX(var(--r))
               rotate(calc(-1 * var(--a, 0deg) - 360deg));
  }
}

@keyframes orbit-ccw {
  from {
    transform: rotate(var(--a, 0deg)) translateX(var(--r))
               rotate(calc(-1 * var(--a, 0deg)));
  }
  to {
    transform: rotate(calc(var(--a, 0deg) - 360deg)) translateX(var(--r))
               rotate(calc(-1 * var(--a, 0deg) + 360deg));
  }
}

@media (max-width: 600px) {
  .orbit__sat--outer {
    width: 50px;
    height: 50px;
    margin: -25px 0 0 -25px;
    border-radius: 16px;
  }
  .orbit__sat--inner {
    width: 44px;
    height: 44px;
    margin: -22px 0 0 -22px;
    border-radius: 14px;
  }
}

/* The tangle: disconnected tools passing the same data around in knots */
.tangle {
  width: min(560px, 92vw);
  height: auto;
  margin: var(--space-8) auto 0;
  overflow: visible;
}

.tangle__lines path {
  fill: none;
  stroke: var(--nix-rule);
  stroke-width: 1;
}

.tangle__dots circle {
  fill: var(--nix-text-soft);
}

.tangle__nodes rect {
  fill: var(--nix-surface);
  filter: drop-shadow(0 1px 1px rgba(26, 26, 26, 0.06))
          drop-shadow(0 8px 14px rgba(26, 26, 26, 0.1));
}

.tangle__nodes text {
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.01em;
  fill: var(--nix-text-soft);
  text-anchor: middle;
}

@media (prefers-reduced-motion: reduce) {
  .tangle__dots {
    display: none;
  }
}

/* Two layouts: wide 3x2 on desktop, tall 2x3 (bigger tiles) on phones. */
.tangle--m {
  display: none;
}
@media (max-width: 600px) {
  .tangle--d {
    display: none;
  }
  .tangle--m {
    display: block;
    width: min(250px, 86vw);
  }
  /* Reserve space so the wheel below never jumps as the copy changes. */
  .dialw-copy {
    min-height: 7em;
  }
  .dialw-copy__pain,
  .dialw-copy__fix { font-size: 15px; }
  /* App tiles match the hero outer-ring size (~50px) on phones. */
  .appgrid {
    grid-template-columns: repeat(6, minmax(0, 50px));
    gap: clamp(6px, 1.8vw, 12px);
  }
}

/* The ERP: a live app-slider on the left (function names rolling by) wired into
   ONE system on the right, whose contents track whichever app is active. */
.erp2 {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(24px, 6vw, 70px);
  width: min(620px, 92vw);
  margin: var(--space-8) auto 0;
}
.erp2__viewport {
  flex: 0 0 auto;
  width: 176px;
  height: 168px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 24%, #000 76%, transparent);
          mask-image: linear-gradient(to bottom, transparent, #000 24%, #000 76%, transparent);
}
.erp2__track {
  display: flex;
  flex-direction: column;
  gap: 12px;
  will-change: transform;
}
.erp2__app {
  flex: 0 0 44px;
  margin-inline: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  background: var(--nix-surface);
  color: var(--nix-text-soft);
  font-family: var(--font-sans);
  font-size: 14px;
  letter-spacing: 0.01em;
  opacity: 0.5;
  transition: color 380ms ease, box-shadow 380ms ease,
              opacity 380ms ease, transform 380ms var(--ease-out-expo);
}
/* with the outline gone, the selected app steps forward instead */
.erp2__app.is-active {
  color: var(--nix-ink);
  opacity: 1;
  transform: scale(1.05);
  box-shadow: 0 2px 4px rgba(26, 26, 26, 0.08),
              0 14px 30px -12px rgba(26, 26, 26, 0.3);
}
.erp2__wire {
  position: relative;
  flex: 0 0 auto;
  width: clamp(40px, 8vw, 84px);
  height: 2px;
  background: repeating-linear-gradient(to right, var(--nix-text-soft) 0 2px, transparent 2px 8px);
}
.erp2__wire::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-radius: 50%;
  background: var(--nix-ink);
  animation: erp2-flow 2.2s linear infinite;
}
@keyframes erp2-flow {
  0% { left: -4px; opacity: 0; }
  15% { opacity: 1; }
  85% { opacity: 1; }
  100% { left: 100%; opacity: 0; }
}
.erp2__panel {
  flex: 0 0 auto;
  width: 224px;
  padding: 16px;
  border-radius: 16px;
  background: var(--nix-surface);
  box-shadow: 0 2px 4px rgba(26, 26, 26, 0.06),
              0 22px 46px -16px rgba(26, 26, 26, 0.22);
}
.erp2__panel-top {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 12px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--nix-rule);
}
.erp2__panel-title {
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--nix-ink);
  white-space: nowrap;
}
.erp2__panel-search {
  flex: 1;
  height: 14px;
  border-radius: 7px;
  border: 1.5px solid var(--nix-rule);
}
.erp2__rows {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
@keyframes erp2-row-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}
.erp2__row {
  display: flex;
  align-items: center;
  gap: 10px;
  animation: erp2-row-in 460ms var(--ease-out-expo) both;
}
.erp2__row:nth-child(2) { animation-delay: 90ms; }
.erp2__row:nth-child(3) { animation-delay: 180ms; }
.erp2__row:nth-child(4) { animation-delay: 270ms; }
.erp2__dot {
  flex: 0 0 auto;
  width: 12px;
  height: 12px;
  border-radius: 4px;
  border: 1.5px solid var(--nix-text-soft);
}
.erp2__label {
  flex: 1;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--nix-text-soft);
}
.erp2__pill {
  flex: 0 0 auto;
  width: 26px;
  height: 7px;
  border-radius: 3.5px;
  background: var(--nix-ink-soft);
}
/* Right-panel rows tinted with Odoo app palette colors. */
.erp2__row:nth-child(1) .erp2__dot { border-color: #00A09D; background: #00A09D; }
.erp2__row:nth-child(1) .erp2__pill { background: #00A09D; width: 28px; }
.erp2__row:nth-child(2) .erp2__dot { border-color: #F4A460; background: #F4A460; }
.erp2__row:nth-child(2) .erp2__pill { background: #F4A460; width: 18px; }
.erp2__row:nth-child(3) .erp2__dot { border-color: #875A7B; background: #875A7B; }
.erp2__row:nth-child(3) .erp2__pill { background: #875A7B; width: 23px; }
@media (prefers-reduced-motion: reduce) {
  .erp2__wire::after { display: none; }
  .erp2__track { transition: none !important; }
  .erp2__row { animation: none; }
}
@media (max-width: 620px) {
  .erp2 { gap: 16px; }
  .erp2__viewport { width: 130px; }
  .erp2__panel { width: 178px; }
}

@media (prefers-reduced-motion: reduce) {
  .hub__dots {
    display: none;
  }
}

/* The cycle: three stations on a ring — the third one never ends */
.cycle {
  width: min(560px, 92vw);
  height: auto;
  margin: var(--space-8) auto 0;
  overflow: visible;
}

.cycle__ring {
  fill: none;
  stroke: var(--nix-rule);
  stroke-width: 1;
}

.cycle__dots circle {
  fill: var(--nix-text-soft);
}

.cycle__stations circle {
  fill: var(--nix-surface);
  stroke: var(--nix-rule);
  stroke-width: 1;
  filter: drop-shadow(0 1px 1px rgba(26, 26, 26, 0.08))
          drop-shadow(0 4px 8px rgba(26, 26, 26, 0.1));
}

.cycle__nums text,
.cycle__labels text {
  font-family: var(--font-sans);
  font-size: 10px;
  letter-spacing: 0.12em;
  fill: var(--nix-text-soft);
  text-anchor: middle;
}

@media (prefers-reduced-motion: reduce) {
  .cycle__dots {
    display: none;
  }
}

/* The settle: one line goes from noise to order — the whole story in one stroke */
.settle {
  width: min(560px, 92vw);
  height: auto;
  margin: var(--space-8) auto 0;
  overflow: visible;
}

.settle__lines path {
  fill: none;
  stroke: url(#settle-grad);
  stroke-width: 1.4;
  stroke-linejoin: round;
}
.settle__g0 { stop-color: var(--nix-rule); }
.settle__g1 { stop-color: #00A09D; }

.settle__dots circle {
  fill: #00A09D;
}

.settle__stations circle {
  fill: #00A09D;
  stroke: #00A09D;
  stroke-width: 1;
  filter: drop-shadow(0 0 7px rgba(0, 160, 157, 0.55))
          drop-shadow(0 4px 8px rgba(26, 26, 26, 0.1));
}

.settle__labels text {
  font-family: var(--font-sans);
  font-size: 10px;
  letter-spacing: 0.12em;
  fill: var(--nix-text-soft);
  text-anchor: middle;
}

@media (prefers-reduced-motion: reduce) {
  .settle__dots {
    display: none;
  }
}

/* The plans: three units in the lineup — cards, because this is the offer */
.landing__block .plans {
  width: min(960px, 100%);
  margin-top: var(--space-8);
  text-align: left;
}

.landing__block .plans .landing__text,
.landing__block .plans p {
  text-align: left;
  text-align-last: auto;
}

.plans .plan:nth-child(2) { transition-delay: 90ms; }
.plans .plan:nth-child(3) { transition-delay: 180ms; }

.plan__icon {
  width: 24px;
  height: 24px;
  margin-bottom: var(--space-2);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.55;
}

/* Plan header: icon and name on one row. */
.plan__head {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-bottom: var(--space-2);
}

.plan__head .plan__icon,
.plan__head .plan__name {
  margin-bottom: 0;
}

/* Horizontal industry-icon picker sitting above the dial's marker. Shows only
   icons; the active one is boxed and bright, its neighbours fade out sideways. */
.indpick {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: var(--space-7, 3.5rem) auto 14px;
}
.indpick__viewport {
  position: relative;
  width: 240px;
  max-width: 78vw;
  height: 54px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 27%, #000 73%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 27%, #000 73%, transparent);
}
.indpick__frame {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 52px;
  height: 44px;
  transform: translate(-50%, -50%);
  border: 1.5px solid var(--nix-text-soft);
  border-radius: 12px;
  pointer-events: none;
  z-index: 2;
}
.indpick__track {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  display: flex;
  align-items: center;
  transition: transform 560ms var(--ease-out-expo);
}
.indpick__slot {
  flex: 0 0 60px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--nix-text-soft);
  opacity: 0.3;
  transform: scale(0.78);
  transition: opacity 420ms ease, transform 420ms ease, color 420ms ease;
}
.indpick__slot.is-active {
  color: var(--nix-ink);
  opacity: 1;
  transform: scale(1);
}
.indpick__slot svg {
  width: 26px;
  height: 26px;
  display: block;
}
.indpick__label {
  margin-top: 10px;
  font-family: var(--font-sans);
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--nix-ink);
  text-align: center;
}
@keyframes indpick-label-in {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}
.indpick__label.is-swap { animation: indpick-label-in 360ms var(--ease-out-expo) both; }
@media (prefers-reduced-motion: reduce) {
  .indpick__track,
  .indpick__slot { transition: none; }
  .indpick__label.is-swap { animation: none; }
}

/* The industry wheel: a dial you can spin. It auto-advances one industry at a
   time, and you can drag it round to pick yours. */
.dialw {
  --r: 118px;
  position: relative;
  width: min(280px, 74vw);
  aspect-ratio: 1 / 1;
  margin: 0 auto var(--space-6);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.dialw__wheel {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid var(--nix-rule);
  cursor: grab;
  transition: transform 640ms var(--ease-out-expo);
}
.dialw__wheel.is-dragging {
  cursor: grabbing;
  transition: none;
}
.dialw__tick {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2px;
  height: 9px;
  margin: -4.5px 0 0 -1px;
  border-radius: 1px;
  background: var(--nix-rule);
  transform: rotate(var(--t)) translateY(calc(-1 * var(--r)));
}
.dialw__tick.is-major {
  height: 14px;
  margin-top: -7px;
  background: var(--nix-text-soft);
}
.dialw__marker {
  position: absolute;
  top: -9px;
  left: 50%;
  width: 0;
  height: 0;
  margin-left: -6px;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 9px solid var(--nix-text);
  z-index: 2;
}
.dialw__core {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 60px;
  height: 60px;
  margin: -30px 0 0 -30px;
  border-radius: 50%;
  background: var(--ind-color, var(--nix-text-soft));
  box-shadow: 0 0 30px -4px var(--ind-color, transparent);
  transition: background-color 600ms ease, box-shadow 600ms ease;
  pointer-events: none;
}
/* Per-industry pain point + Odoo fix; fixed height so the wheel never jumps. */
.dialw-copy {
  max-width: 540px;
  margin: 0 auto;
  min-height: 3.7em;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  text-align: center;
}
.dialw-copy__pain,
.dialw-copy__fix {
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 16px;
  line-height: 1.5;
}
.dialw-copy__pain { color: var(--nix-text-soft); }
.dialw-copy__fix { color: var(--nix-ink); }
@keyframes dialw-copy-in {
  from { opacity: 0; transform: translateY(5px); }
  to { opacity: 1; transform: none; }
}
.dialw-copy__pain.is-swap,
.dialw-copy__fix.is-swap { animation: dialw-copy-in 440ms var(--ease-out-expo) both; }
.dialw-copy__fix.is-swap { animation-delay: 70ms; }
@media (prefers-reduced-motion: reduce) {
  .dialw-copy__pain.is-swap,
  .dialw-copy__fix.is-swap { animation: none; }
}
.dialw__hint {
  position: absolute;
  bottom: -30px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--nix-text-soft);
  opacity: 0.55;
  white-space: nowrap;
}
@media (prefers-reduced-motion: reduce) {
  .dialw__wheel { transition: none; }
}

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

/* The app grid: the whole catalogue is there — only your parts are lit */
.appgrid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 64px));
  gap: clamp(14px, 2.4vw, 22px);
  justify-content: center;
  margin: var(--space-8) auto 0;
}

.appgrid__cell {
  aspect-ratio: 1;
  border: 1px solid var(--nix-rule);
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 700ms ease, border-color 700ms ease,
              box-shadow 700ms ease;
}

.appgrid__cell.is-on {
  border-color: transparent;
  background: var(--nix-surface);
  box-shadow: 0 1px 1px rgba(26, 26, 26, 0.06),
              0 4px 8px -2px rgba(26, 26, 26, 0.08),
              0 14px 28px -10px rgba(26, 26, 26, 0.14);
}

.appgrid__cell img {
  width: 55%;
  height: 55%;
  display: block;
  opacity: 0;
  transition: opacity 700ms ease;
}

.appgrid__cell.is-on img {
  opacity: 1;
}

/* Line reveal: section text rises line by line — smooth, staggered */
.lines.reveal:not(.is-in) {
  opacity: 1;
  filter: none;
  transform: none;
}

.lines .lw {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.6em);
  transition: opacity 750ms var(--ease-out-expo),
              transform 750ms var(--ease-out-expo);
  transition-delay: calc(var(--line, 0) * 110ms);
}

.lines.is-in .lw {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .lines .lw {
    transition: none;
    opacity: 1;
    transform: none;
  }
}

/* Reveals: blur joins the rise */
.landing__headline.reveal:not(.is-in),
.signs__list li.reveal:not(.is-in),
.signs__turn.reveal:not(.is-in),
.start2.reveal:not(.is-in),
.plan.reveal:not(.is-in),
.ind.reveal:not(.is-in),
.landing__midcta.reveal:not(.is-in) {
  filter: blur(5px);
}

/* Signs: hanging counters, deeper stagger */
.signs__list {
  counter-reset: sign;
}

.signs__list li {
  counter-increment: sign;
  position: relative;
  padding-left: 56px;
}

.signs__list li::before {
  content: "0" counter(sign);
  position: absolute;
  left: 0;
  top: 0.5em;
  font-size: 12px;
  letter-spacing: 0.12em;
  color: var(--nix-orange);
}

.signs__list li:nth-child(1) { transition-delay: 60ms; }
.signs__list li:nth-child(2) { transition-delay: 140ms; }
.signs__list li:nth-child(3) { transition-delay: 220ms; }
.signs__list li:nth-child(4) { transition-delay: 300ms; }
.signs__list li:nth-child(5) { transition-delay: 380ms; }


/* Odoo constellation: tiles drift, gently and out of phase */
.erp {
  pointer-events: auto;
}

/* scroll assembly: the system comes together as you read */
.erp__hub {
  opacity: 0;
  transform: scale(0.72);
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 450ms var(--ease-out-expo),
              transform 550ms var(--ease-pop);
}

.erp.is-hub-built .erp__hub {
  opacity: 1;
  transform: scale(1);
}

.erp__pulses {
  opacity: 0;
  transition: opacity 500ms ease 200ms;
}

.erp.is-flowing .erp__pulses {
  opacity: 1;
}

.erp__chips > g {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 500ms var(--ease-out-expo),
              transform 300ms var(--ease-out-expo);
}

.erp__chips > g.is-built {
  opacity: 1;
}

.erp__chips > g > * {
  animation: tile-float 7s ease-in-out infinite;
  animation-delay: var(--fd, 0s);
  transform-box: fill-box;
  transform-origin: center;
}

.erp__chips > g:hover {
  transform: translateY(-3px) scale(1.05);
}

.erp__chips > g:nth-child(2n) { --fd: -2.4s; }
.erp__chips > g:nth-child(3n) { --fd: -4.1s; }
.erp__chips > g:nth-child(5n) { --fd: -5.6s; }

@keyframes tile-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

/* Cards answer the hand */
.plan {
  position: relative;
  overflow: hidden;
}

.plan.is-in {
  transition: opacity 700ms var(--ease-out-expo),
              filter 700ms var(--ease-out-expo),
              transform 350ms var(--ease-out-expo),
              box-shadow 350ms var(--ease-out-expo);
}

.plan::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--nix-orange);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 450ms var(--ease-in-out);
}

.plan:hover {
  transform: translateY(-4px);
  box-shadow: 0 2px 8px rgba(26, 26, 26, 0.10);
}

.plan:hover::before {
  transform: scaleX(1);
}

/* App marquee: the catalogue threaded on a wire — the diagram's
   connection language, in motion */
.app-marquee {
  position: relative;
  overflow: hidden;
  margin-bottom: 120px;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
}

.app-marquee::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 17px; /* through the icon centers, like the hub lines */
  height: 1px;
  background: var(--nix-rule);
}

.app-marquee__track {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  width: max-content;
  animation: marquee 44s linear infinite;
}

.app-marquee:hover .app-marquee__track {
  animation-play-state: paused;
}

.app-marquee__item {
  position: relative; /* above the wire */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  flex: none;
}

.app-marquee__item img {
  width: 34px;
  height: 34px;
  display: block;
  padding: 2px;
  background: var(--nix-paper);
  border-radius: 9px;
}

.app-marquee__item span {
  font-size: 13px;
  font-weight: 300;
  color: var(--nix-text-soft);
  white-space: nowrap;
}

@keyframes marquee {
  to { transform: translateX(-50%); }
}

/* Final band: a faint orange ember in the dark */

/* Off-screen ambient motion sleeps */
.app-marquee.is-paused .app-marquee__track,
.erp.is-paused .erp__chips > g > *,
.erp.is-paused .erp__hub-led,
.orbit.is-paused .orbit__sat,
.orbit.is-paused .orbit__spark {
  animation-play-state: paused;
}

/* Calm for those who ask for it */
@media (prefers-reduced-motion: reduce) {
  .erp__hub,
  .erp__chips > g,
  .erp__pulses {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .erp__chips > g > *,
  .preloader--play .preloader__rule::after,
  .app-marquee__track,
  .orbit__sat,
  .orbit__spark {
    animation: none;
  }
  .landing__headline.reveal:not(.is-in),
  .signs__list li.reveal:not(.is-in),
  .signs__turn.reveal:not(.is-in),
  .start2.reveal:not(.is-in),
  .plan.reveal:not(.is-in),
  .ind.reveal:not(.is-in),
  .landing__midcta.reveal:not(.is-in) {
    filter: none;
  }
  .landing__lead .w__i {
    transform: none;
    transition: none;
  }
}

@media (max-width: 720px) {
  .ind {
    grid-template-columns: 1fr;
    gap: var(--space-1);
  }
  .signs__list li {
    padding-left: 40px;
  }
}


/* ---- Header menu: the dot opens a full-screen overlay with three cards ---- */
.site-menu__trigger {
  position: absolute;
  right: var(--space-6);
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  padding: 0;
  border: 1.5px solid var(--nix-text);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background 0.2s ease;
}
.site-menu__trigger:focus-visible {
  outline: 2px solid var(--nix-text);
  outline-offset: 3px;
}

/* Open, the same button becomes the cross. The overlay used to carry its own —
   sitting under a header that now paints above it, and drifting from the real
   one besides. One button, two states. */
.site-menu__trigger::before,
.site-menu__trigger::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 18px;
  height: 1.5px;
  background: var(--nix-text);
  transform: translate(-50%, -50%) scaleX(0);
  transition: transform 260ms var(--ease-out-expo);
}

.site-menu__trigger[aria-expanded="true"] {
  border-color: transparent;
}

.site-menu__trigger[aria-expanded="true"]::before {
  transform: translate(-50%, -50%) rotate(45deg) scaleX(1);
}

.site-menu__trigger[aria-expanded="true"]::after {
  transform: translate(-50%, -50%) rotate(-45deg) scaleX(1);
}

/* the overlay: a full sheet holding the three menu cards */
.site-menu-overlay {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* SAFE centre. Three stacked cards do not fit a phone, and a plain `center`
     overflows in both directions in a scroll container — the top of the stack
     becomes unreachable, which is why the first card was living under the logo.
     `safe` falls back to flex-start the moment the content stops fitting. */
  justify-content: safe center;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  gap: var(--space-6);
  /* the header sits above this overlay, so leave it its own room */
  padding: calc(var(--head-h, 82px) + var(--space-3)) var(--space-6) var(--space-8);
  background: var(--nix-paper);
  opacity: 0;
  visibility: hidden;
  transition: opacity 360ms var(--ease-out-expo), visibility 360ms;
}
.site-menu-overlay[data-state="open"] {
  opacity: 1;
  visibility: visible;
}

/* the NIX logo stays put (top-centre, matching the header) while the menu is open */
.site-menu-overlay__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
  width: min(1000px, 92vw);
}

.menu-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-2);
  padding: var(--space-8) var(--space-3);
  border-radius: 24px;
  background: var(--nix-surface);
  box-shadow: 0 1px 2px rgba(26, 26, 26, 0.06),
              0 14px 36px -14px rgba(26, 26, 26, 0.16);
  text-decoration: none;
  color: var(--nix-ink);
  transition: transform 260ms var(--ease-out-expo),
              box-shadow 260ms var(--ease-out-expo);
}
.menu-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 2px 4px rgba(26, 26, 26, 0.06),
              0 24px 52px -16px rgba(26, 26, 26, 0.24);
}
.menu-card__icon { color: var(--nix-ink); opacity: 0.62; line-height: 0; }
.menu-card__icon svg { width: 28px; height: 28px; }
.menu-card__name { font-size: 22px; letter-spacing: -0.01em; }
.menu-card__desc {
  font-size: 14px;
  line-height: 1.5;
  color: var(--nix-ink-soft);
  max-width: 220px;
}

/* the two things a visitor may want to change about the page itself, at the
   foot of the menu */
.site-menu-overlay__foot {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.tools__theme {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--nix-text-soft);
}

/* not built yet — the card still explains itself, it just doesn't pretend
   to be a door */
.menu-card--soon {
  cursor: default;
  opacity: 0.5;
}
.menu-card--soon:hover {
  transform: none;
  box-shadow: 0 1px 2px rgba(26, 26, 26, 0.06),
              0 14px 36px -14px rgba(26, 26, 26, 0.16);
}
.menu-card__soon {
  margin-top: var(--space-1);
  padding: 4px 10px;
  border: 1px solid var(--nix-rule);
  border-radius: 999px;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--nix-ink-soft);
}

/* cards rise in when the overlay opens */
.site-menu-overlay .menu-card,
.site-menu-overlay__foot {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 500ms var(--ease-out-expo),
              transform 500ms var(--ease-out-expo);
}
.site-menu-overlay[data-state="open"] .menu-card:nth-child(1) { transition-delay: 80ms; }
.site-menu-overlay[data-state="open"] .menu-card:nth-child(2) { transition-delay: 160ms; }
.site-menu-overlay[data-state="open"] .menu-card:nth-child(3) { transition-delay: 240ms; }
.site-menu-overlay[data-state="open"] .site-menu-overlay__foot { transition-delay: 320ms; }
.site-menu-overlay[data-state="open"] .menu-card,
.site-menu-overlay[data-state="open"] .site-menu-overlay__foot {
  opacity: 1;
  transform: none;
}
.site-menu-overlay[data-state="open"] .menu-card--soon {
  opacity: 0.5;
}

@media (max-width: 720px) {
  .site-menu-overlay__grid { grid-template-columns: 1fr; width: min(420px, 92vw); }
  .menu-card { padding: var(--space-4) var(--space-3); }
}


/* ---- nav-mode entrance: staggered rise as the preloader lifts --------- */
@keyframes nixNavRise {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes nixIconIn {
  from { opacity: 0; transform: scale(0.6) rotate(-14deg); }
  to   { opacity: 0.55; transform: scale(1) rotate(0deg); }
}
body.is-ready .nav-mode__sub {
  animation: nixNavRise 760ms var(--ease-out-expo) 460ms backwards;
}
body.is-ready .nav-mode__option {
  animation: nixNavRise 800ms var(--ease-out-expo) backwards;
}
body.is-ready .nav-mode__option:nth-child(1) { animation-delay: 640ms; }
body.is-ready .nav-mode__option:nth-child(2) { animation-delay: 780ms; }
body.is-ready .nav-mode__option:nth-child(1) .nav-mode__icon {
  animation: nixIconIn 620ms var(--ease-pop) 760ms backwards;
}
body.is-ready .nav-mode__option:nth-child(2) .nav-mode__icon {
  animation: nixIconIn 620ms var(--ease-pop) 900ms backwards;
}
@media (prefers-reduced-motion: reduce) {
  body.is-ready .nav-mode__sub,
  body.is-ready .nav-mode__option,
  body.is-ready .nav-mode__icon { animation: none; }
}


/* ---- Hero entrance: text first (heading -> intro -> CTAs one by one), then
       the orbit fills in — rings settle, then the app chips ease in smoothly,
       one by one. Keyed to .lead-in so children stay hidden until reveal. --- */
.landing__hero .landing__text--intro {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 760ms var(--ease-out-expo),
              transform 760ms var(--ease-out-expo);
}
.landing.lead-in .landing__hero .landing__text--intro {
  transition-delay: 320ms;
  opacity: 1;
  transform: none;
}

/* CTAs: one button, then the other */
.landing__hero .landing__cta .btn {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 640ms var(--ease-out-expo),
              transform 640ms var(--ease-out-expo);
}
.landing.lead-in .landing__hero .landing__cta .btn:nth-child(1) { transition-delay: 480ms; }
.landing.lead-in .landing__hero .landing__cta .btn:nth-child(2) { transition-delay: 640ms; }
.landing.lead-in .landing__hero .landing__cta .btn {
  opacity: 1;
  transform: none;
}

/* orbit reveal, in strict order: outer ring -> outer apps (together) ->
   inner ring -> inner apps (together) -> spark. Pure fades. */
.orbit__ring,
.orbit__sat,
.orbit__spark {
  opacity: 0;
  transition: opacity 640ms var(--ease-out-expo);
}
.landing.lead-in .orbit__ring--outer { transition-delay: 560ms; }
.landing.lead-in .orbit__sat--outer  { transition-delay: 860ms; }
.landing.lead-in .orbit__ring--inner { transition-delay: 1200ms; }
.landing.lead-in .orbit__sat--inner  { transition-delay: 1500ms; }
.landing.lead-in .orbit__spark { transition-delay: 1980ms; }
.landing.lead-in .orbit__ring,
.landing.lead-in .orbit__sat,
.landing.lead-in .orbit__spark { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .landing__hero .landing__text--intro,
  .landing__hero .landing__cta .btn,
  .orbit__ring,
  .orbit__spark,
  .orbit__sat { opacity: 1; transform: none; transition: none; }
}
