/* Public marketing surface — foundation.
   The landing page shares the application's colour tokens, with its own
   surface roles scoped to .landing. It does not load application chrome
   or switch themes: the marketing art direction stays consistent.
   Content is visible by default; JavaScript progressively adds motion.

   Files in this directory, in load order (see landing.html):
     base.css      palette, type, buttons, footer, shared chapter layout
     nav.css       the marketing header: full-width bar, scroll glass, phone menu
     surfaces.css  light editorial sections and dark product surfaces
     panels.css    light sections as paper panels resting on the navy ground
     ui.css        the product-UI vocabulary the mockups are drawn in
     devices.css   the iPhone and laptop shells
     hero.css      opening scene
     sections.css  platform, trust, faq, cta
     device.css    01 · one device
     alerts.css    02 · alerts (threshold dialog + phone notification)
     errors.css    error lifecycle
     updates.css   03 · fleet rollout (dialog + globe + site progress)
     onboarding.css hardware-to-cloud story
     teams.css     the people and workflows behind the product */

.landing {
  /* ---- Brand anchors (01-tokens/colors.css) ---- */
  --lp-hull: var(--business-primary);
  --lp-abyss: var(--primary-dark);
  --lp-current: var(--primary-color);
  --lp-shoal: var(--primary-lighter);
  --lp-harbour: var(--business-secondary);
  --lp-cyan: var(--business-accent);

  /* ---- Status (dark-mode brightened, as in the product's dark theme) ---- */
  --lp-green: color-mix(in srgb, var(--business-success) 80%, white);
  --lp-amber: color-mix(in srgb, var(--business-warning) 80%, white);
  --lp-red: color-mix(in srgb, var(--business-danger) 75%, white);

  /* ---- Surfaces: one navy family, closer to the light = more raised ---- */
  --lp-ground: color-mix(in srgb, var(--business-footer) 82%, var(--lp-hull));
  --lp-ground-raised: color-mix(in srgb, var(--business-footer) 92%, var(--lp-harbour));
  --lp-bg: var(--lp-ground);
  --lp-panel: #0b1130;              /* mockup dialogs, cards */
  --lp-panel-raised: #101a44;       /* lifted panel, hover */
  --lp-panel-sunken: #070c22;       /* recessed screen background */

  /* ---- Ink ---- */
  --lp-ink-strong: #fff;    
  --lp-ink: #dbe7f5;
  --lp-mute: #8fa3c7;
  --lp-faint: #5b6785;

  /* ---- Lines ---- */
  --lp-line: rgb(255 255 255 / 12%);
  --lp-line-strong: rgb(255 255 255 / 18%);
  --lp-line-faint: rgb(255 255 255 / 7%);

  /* ---- Type ---- */
  --lp-font: "IBM Plex Sans", "Segoe UI", sans-serif;
  --lp-mono: "IBM Plex Mono", ui-monospace, monospace;

  /* One readable scale across the illustrated product dialogs. */
  --lp-ui-title: clamp(1rem, .9rem + .25vw, 1.125rem);
  --lp-ui-body: clamp(.875rem, .85rem + .12vw, .9375rem);
  --lp-ui-label: .875rem;
  --lp-ui-small: .8125rem;

  /* ---- Shape (DESIGN.md: radii step 8 → 12 → 16 → 24) ---- */
  --lp-radius-sm: 8px;
  --lp-radius-md: 12px;
  --lp-radius-lg: 16px;
  --lp-radius-xl: 24px;

  /* ---- Depth ---- */
  --lp-shadow-panel: 0 20px 56px -16px rgb(0 0 0 / 45%), inset 0 1px 0 rgb(255 255 255 / 8%);
  --lp-shadow-float: 0 32px 80px -24px rgb(0 0 0 / 55%), inset 0 1px 0 rgb(255 255 255 / 10%);
  --lp-glow-cyan: 0 0 28px color-mix(in srgb, var(--lp-cyan) 25%, transparent);

  /* ---- Rhythm ---- */
  --lp-gutter: 1.25rem;

  /* The sticky header's box. nav.css fills it; hero.css pulls the opening
     scene up underneath it. */
  --lp-nav-height: 4.5rem;

  /* The floor is the phone's value, not a safety net: 7vw only overtakes it
     past ~1029px, so every viewport narrower than that gets exactly the floor.
     A desktop-sized band there reads as a page with holes in it. */
  --lp-section-y: clamp(3.25rem, 7vw, 6.5rem);
  --lp-container: 82rem;

  /* ---- Motion (mirrors MOTION in js/landing.js) ---- */
  --lp-dur-quick: 350ms;
  --lp-dur-accent: 500ms;   /* fades and pops */
  --lp-dur-base: 800ms;
  --lp-dur-arrival: 1000ms; /* entrances and line draws */
  --lp-dur-slow: 1400ms;
  --lp-dur-chrome: 450ms;   /* nav surface changes */
  --lp-ease-enter: cubic-bezier(.2, .7, .3, 1);      /* power3.out */
  --lp-ease-emphasis: cubic-bezier(.16, 1, .3, 1);   /* power4.out */

  margin: 0;
  background: linear-gradient(
    180deg,
    var(--lp-ground) 0,
    var(--lp-ground) 100rem,
    var(--lp-ground-raised) 44%,
    var(--business-footer) 72%,
    var(--lp-ground) calc(100% - 100rem),
    var(--lp-ground) 100%
  );
  color: var(--lp-ink);
  font-family: var(--lp-font);
  font-size: 1rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  color-scheme: dark;
  overflow-x: clip;
}

/* No `scroll-behavior` here, deliberately: asking the document to scroll
   smoothly animates every programmatic scroll, including the scroll to the top
   that ScrollTrigger performs to measure the page. The first pinned chapter is
   then measured at the visitor's own offset and pins a screenful early. The
   navigation half of js/landing.js smooths activated anchors instead, and
   `scroll-padding-top` still keeps a target clear of the sticky nav. */
html:has(.landing) {
  scroll-padding-top: 5.5rem;
  background: var(--business-footer);
}

.landing *, .landing *::before, .landing *::after {
  box-sizing: border-box;
}

.landing img, .landing svg {
  display: block;
  max-width: 100%;
}

.landing img {
  height: auto;
}

.landing a {
  color: inherit;
  text-decoration: none;
}

.landing button {
  font: inherit;
}

.landing figure {
  margin: 0;
}

.landing :focus-visible {
  outline: 3px solid var(--lp-cyan);
  outline-offset: 4px;
  border-radius: 4px;
}

.landing ::selection {
  background: var(--lp-cyan);
  color: var(--lp-hull);
}

/* Layout primitives */

.landing__container {
  width: 100%;
  max-width: var(--lp-container);
  padding-inline: var(--lp-gutter);
  margin-inline: auto;
}

/* The container of a chapter that js/landing.js pins. Same content box, but
   full-bleed and centred with padding instead of auto margins: ScrollTrigger
   copies a pinned element's margins into its spacer once, when the pin is
   created, and never re-reads them — so a container that is centred by
   `margin-inline: auto` can end up pinned against the left edge for good. */
.landing__container--pinned {
  max-width: none;
  padding-inline: calc(max(0px, (100% - var(--lp-container)) / 2) + var(--lp-gutter));

  /* A pinned scene cannot be scrolled, so on a short screen it is scaled to the
     room it has instead of losing the chapter. js/landing.js measures the room
     and sets the factor on the section; without it the scene is untouched. */
  transform: scale(var(--lp-scene-fit, 1));
  transform-origin: top center;
}

.landing__section {
  position: relative;
  padding-block: var(--lp-section-y);
}

/* One light pool per demo. It travels with the pinned composition and
   fades to transparent before its edges, without a blur filter or render loop.
   The horizontal spread is bounded by the available page gutter. */
.landing-demo-light {
  --lp-light-spread: max(var(--lp-gutter), calc((100vw - var(--lp-container)) / 2 + var(--lp-gutter)));

  position: relative;
  isolation: isolate;
}

.landing-demo-light::before {
  content: "";
  position: absolute;
  inset: -8rem calc(-1 * var(--lp-light-spread));
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    ellipse closest-side at 50% 48%,
    rgb(92 162 204 / 20%) 0%,
    rgb(35 107 172 / 28%) 28%,
    rgb(24 78 150 / 16%) 55%,
    rgb(24 78 150 / 5%) 78%,
    rgb(24 78 150 / 0%) 100%
  );
}

@keyframes landing-light-drift {
  from {
    transform: translateY(-1rem);
    opacity: .65;
  }

  to {
    transform: translateY(1rem);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .landing-demo-light::before {
    animation: landing-light-drift 8s ease-in-out infinite alternate;
    animation-play-state: paused;
  }

  .landing-demo-light.is-light-visible::before {
    animation-play-state: running;
  }
}

.landing__skip {
  position: fixed;
  top: 1rem;
  left: 1rem;
  z-index: 100;
  padding: .75rem 1.25rem;
  background: var(--lp-cyan);
  color: var(--lp-hull);
  font-weight: 600;
  transform: translateY(-200%);
  border-radius: var(--lp-radius-sm);
}

.landing__skip:focus {
  transform: translateY(0);
}

.landing__progress {
  position: fixed;
  inset: 0 0 auto;
  height: 2px;
  background: linear-gradient(90deg, var(--lp-shoal), var(--lp-cyan));
  z-index: 60;
  transform: scaleX(0);
  transform-origin: left;
  pointer-events: none;
}

/* Typography — one superfamily, hierarchy carried by weight and tracking (DESIGN.md). */

/* Eyebrow: taxonomy, not decoration.

   No leading mark. It used to carry a 24x2px rule, which reads as a dash in
   front of every label and is one of the loudest "generated page" tells there
   is. The label does not need an ornament to be an eyebrow — the mono face,
   the caps and the tracking already say "this is a category, not a sentence".

   Mono is deliberate and it is already the page's voice for machine-ish
   labels (the demo captions use it). Setting it against the tightly
   negative-tracked display headline is what marks the two as different kinds
   of text. Muted rather than cyan, so eleven of these do not shout. */
.landing__eyebrow {
  display: block;
  margin: 0 0 1.25rem;
  color: var(--lp-mute);
  font-family: var(--lp-mono);
  font-size: .6875rem;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: .16em;
  text-transform: uppercase;
}

.landing__headline {
  margin: 0;
  color: var(--lp-ink-strong);
  font-size: clamp(2.5rem, 5vw, 4.5rem);
  line-height: 1.04;
  font-weight: 700;
  letter-spacing: -.03em;
  text-wrap: balance;
}

.landing__headline--section {
  font-size: clamp(2rem, 3.6vw, 3.25rem);
  line-height: 1.1;
  letter-spacing: -.025em;
}

.landing__headline--small {
  font-size: clamp(1.6rem, 2.6vw, 2.25rem);
  line-height: 1.15;
  letter-spacing: -.02em;
}

.landing__headline em {
  font-style: normal;
  color: var(--lp-cyan);
}

.landing__sub {
  max-width: 34rem;
  margin: 1.25rem 0 0;
  color: var(--lp-mute);
  font-size: 1.125rem;
  line-height: 1.6;
  text-wrap: pretty;
}

.landing__label {
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--lp-mute);
}

.landing__mono {
  font-family: var(--lp-mono);
  font-variant-numeric: tabular-nums;
}

/* The cyan rule that draws itself under a headline (promo CTA beat). */
.landing__rule {
  display: block;
  width: 6rem;
  height: 3px;
  margin: 1.75rem 0;
  background: var(--lp-cyan);
  border-radius: 2px;
  transform-origin: left;
}

/* The page-level status dot is gone, and so is the rule that briefly replaced
   it. An eyebrow now carries no leading mark at all — see the note above
   .landing__eyebrow. The dots that remain are all inside the product mockups,
   where they stand for real device indicators rather than decorating a
   label. */

.landing__steps {
  display: grid;
  gap: .9rem;
  list-style: none;
  padding: 0;
  margin: 1.75rem 0;
}

.landing__steps li {
  position: relative;
  padding-left: 1.25rem;
  color: var(--lp-ink);
  font-size: 1rem;
  line-height: 1.5;
}

.landing__steps li::before {
  content: "";
  position: absolute;
  top: .5625rem;
  left: 0;
  width: .375rem;
  height: .375rem;
  border-radius: 50%;
  background: var(--lp-cyan);
}

.landing__text-link {
  display: inline-flex;
  align-items: center;
  gap: .7rem;
  color: var(--lp-ink-strong);
  font-size: .9375rem;
  font-weight: 600;
  padding-block: .35rem;
  border-bottom: 1px solid var(--lp-line-strong);
  transition: border-color 180ms ease, gap 180ms ease;
}

.landing__text-link:hover {
  border-color: var(--lp-cyan);
  gap: 1rem;
}

.landing__text-link i {
  font-size: .75rem;
  color: var(--lp-cyan);
}

.landing__desktop-break {
  display: none;
}

/* Buttons — the dark-mode primary is Shoal Blue (DESIGN.md: The Anchor-Is-Not-The-Action Rule). */

.landing-btn {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  gap: .75rem;
  min-height: 3rem;
  padding: .75rem 1.5rem;
  border: 1px solid transparent;
  border-radius: var(--lp-radius-md);
  color: var(--lp-ink-strong);
  font-size: .9375rem;
  font-weight: 600;
  letter-spacing: -.005em;
  white-space: nowrap;
  transition:
    transform var(--lp-dur-quick) var(--lp-ease-emphasis),
    box-shadow var(--lp-dur-quick) var(--lp-ease-emphasis),
    background-color var(--lp-dur-quick) ease,
    border-color var(--lp-dur-quick) ease;
}

.landing-btn i {
  font-size: .8rem;
}

.landing-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 28px -12px color-mix(in srgb, var(--lp-shoal) 55%, transparent);
}

.landing-btn:active {
  transform: translateY(0);
}

/* The trailing arrow advances; the outbound icon does not (it means
   "leaves the site", not "continues"). */
.landing-btn i.fa-arrow-right,
.landing-btn i.fa-arrow-down {
  transition: transform var(--lp-dur-quick) var(--lp-ease-emphasis);
}

.landing-btn:hover i.fa-arrow-right {
  transform: translateX(3px);
}

.landing-btn:hover i.fa-arrow-down {
  transform: translateY(3px);
}

.landing-btn--primary {
  background: var(--lp-shoal);
  box-shadow: 0 10px 30px color-mix(in srgb, var(--lp-shoal) 35%, transparent);
}

.landing-btn--primary:hover {
  background: color-mix(in srgb, var(--lp-shoal) 82%, white);
  box-shadow: 0 14px 36px color-mix(in srgb, var(--lp-shoal) 45%, transparent);
}

.landing-btn--ghost {
  border-color: var(--lp-line-strong);
  background: rgb(255 255 255 / 4%);
}

.landing-btn--ghost:hover {
  background: rgb(255 255 255 / 9%);
  border-color: rgb(255 255 255 / 28%);
}

.landing-btn--light {
  background: var(--lp-ink-strong);
  color: var(--lp-hull);
}

.landing a.landing-btn--light {
  color: var(--lp-hull);
}

.landing-btn--light:hover {
  background: var(--lp-cyan);
}

.landing-btn--small {
  min-height: 2.5rem;
  padding: .5rem 1.1rem;
  font-size: .875rem;
  border-radius: var(--lp-radius-sm);
}

/* Badges — status colour only where it reports a state (The Signal Rule). */

.landing-badge {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .3rem .6rem;
  border-radius: 6px;
  background: color-mix(in srgb, var(--lp-shoal) 22%, transparent);
  color: #9fd8f2;
  font-size: .75rem;
  font-weight: 600;
  white-space: nowrap;
}

.landing-badge--amber {
  background: color-mix(in srgb, var(--lp-amber) 16%, transparent);
  color: var(--lp-amber);
}

.landing-badge--green {
  background: color-mix(in srgb, var(--lp-green) 14%, transparent);
  color: var(--lp-green);
}

.landing-badge--red {
  background: color-mix(in srgb, var(--lp-red) 14%, transparent);
  color: var(--lp-red);
}

.landing-badge--mute {
  background: rgb(255 255 255 / 6%);
  color: var(--lp-ink);
}

/* Shared two-column chapter layout: copy beside a built visual. */

.landing-chapter__inner {
  display: grid;
  align-items: center;
  gap: 3rem;
}

.landing-chapter__copy {
  min-width: 0;
}

.landing-chapter__visual {
  min-width: 0;
  position: relative;
}

/* Footer */

.landing-footer {
  padding-block: 3rem 1.5rem;
  background: var(--lp-hull);
  border-top: 1px solid var(--lp-line-faint);
}

.landing-footer__main {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 2rem;
  padding-bottom: 2rem;
}

.landing-footer__lockup {
  width: 8rem;
}

.landing-footer__main p {
  flex-basis: 100%;
  margin: 0;
  color: var(--lp-mute);
  font-size: .9rem;
}

.landing-footer__back {
  color: var(--lp-ink);
  font-size: .8rem;
  font-weight: 500;
}

.landing-footer__back:hover {
  color: var(--lp-cyan);
}

.landing-footer__back i {
  margin-left: .6rem;
  font-size: .7rem;
}

.landing-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--lp-line-faint);
  color: var(--lp-mute);
  font-size: .8rem;
}

.landing-footer__links {
  display: flex;
  gap: 1.5rem;
}

.landing-footer__links a:hover {
  color: var(--lp-cyan);
}

.landing-footer__byline {
  font-size: .625rem;
  font-weight: 600;
  letter-spacing: .16em;
}

/* Breakpoints — mobile first (DESIGN.md: The Mobile-Baseline Rule). */

@media (width >= 36rem) {
  .landing {
    --lp-gutter: 2rem;
  }

  .landing__desktop-break {
    display: initial;
  }
}

@media (width >= 56rem) {
  .landing {
    --lp-gutter: 3rem;
    --lp-section-y: 7.5rem;
  }

  .landing-chapter__inner {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: 4rem;
  }

  .landing-chapter__inner--reverse .landing-chapter__copy {
    order: 2;
  }

  .landing-footer__main {
    flex-wrap: nowrap;
  }

  .landing-footer__main p {
    flex-basis: auto;
  }

  .landing-footer__back, .landing-footer__byline {
    margin-left: auto;
  }
}

@media (width >= 75rem) {
  .landing {
    --lp-section-y: 8.5rem;
  }

  .landing-chapter__inner {
    gap: 6rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* One switch, so no component has to remember to opt out. GSAP is already
     gated by the matchMedia context in js/landing.js; this covers CSS. */
  .landing {
    --lp-dur-quick: 0ms;
    --lp-dur-accent: 0ms;
    --lp-dur-base: 0ms;
    --lp-dur-arrival: 0ms;
    --lp-dur-slow: 0ms;
    --lp-dur-chrome: 0ms;
  }

  .landing *, .landing *::before, .landing *::after {
    transition: none;
    transition-duration: 1ms !important;
    animation: none;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}
