/* ============================================================================
   HACKUITY NAVBAR  ·  nav.css  ·  v1.10.1
   ----------------------------------------------------------------------------
   Variant B — the bar pill NEVER changes height (74 desktop / 80 tablet+mobile).
   The mega-menu is a separate surface behind it, tucked up by the amount Figma
   draws, and it is the only thing that resizes when you switch heads.

   Values read from Figma 7Dm6a0NkHsli9Q8VTy4FAx via the Figma MCP server.

   ── Breakpoints: this file is written DESKTOP-UP ──────────────────────────
   The base (no media query) is the COLLAPSED layout — hamburger, one-column
   mega-menu, 193px link rail. Desktop is an override on top of it:

     base            collapsed          ->  Webflow `main`
     min-width 1280  horizontal row     ->  Webflow `large`   (section 6)
     min-width 1440  link padding 16    ->  Webflow `xl`      (section 6b)
     max-width 767   bottom bar+drawer  ->  Webflow `small`   (section 7)
     max-width 479   portrait           ->  Webflow `tiny`    (section 8)

   That is not a style preference. Webflow has no max-width tier between 992
   and 1279 — above `main` its tiers only run upward — so a max-width 1279
   block has nowhere to land in the Designer. Shaped this way, every tier here
   maps 1:1 onto a Webflow breakpoint, which is what lets the Style panel and
   this file hold the same rules without either one being mentally inverted.
   Read the desktop values in section 6, not at the top of a rule.
   The bar is aligned to Webflow's `.container-1280` — a 1280px content box with a
   32px gutter (16px at <=767) — so the pill's edges land on the page's own content
   edges instead of running full-bleed.

   ── What is left in this file ─────────────────────────────────────────────
   As of v1.7.0 the look of the navbar lives in the WEBFLOW STYLE PANEL — 93
   rules covering layout, spacing, radius, type and colour, bound to the `Nav`
   and `Color` variable collections. Edit those in the Designer, not here.

   What stays here is everything the Style panel cannot express:
     · the component baseline (section 2) — it must load AFTER Webflow's
       normalize to do its job, which is the whole reason it cannot move
     · the state and motion layer — `[data-nav-swap]`, `[data-nav-state]`,
       `nv-is-*` combos, descendant selectors, the panel crossfade, and the
       mobile scroll reveal (section 7)
     · transitions (durations and easings come from --nv-* tokens)
     · --nv-shadow, backdrop-filter, grid-template-areas, @font-face,
       prefers-reduced-motion
   `nav-panel.css` is a generated local mirror of the Webflow half, so
   embed.html and preview.html still render standalone. It is NOT shipped.

   ── Tokens duplicated with Webflow ────────────────────────────────────────
   These eleven are declared BOTH here and in Webflow's `Nav` collection,
   because rules on both sides use them. Change one, change the other:

     --nv-bar-h  --nv-blur  --nv-font  --nv-link-pad  --nv-panel-tuck
     --nv-radius-6  --nv-rail-w  --nv-space-5  --nv-space-7  --nv-space-8
     --nv-space-10

   The rest of the :root block is no longer read by anything in this file; it
   is kept only so `nav-panel.css` resolves when previewing standalone.

   ── Webflow / CDN contract ────────────────────────────────────────────────
   1. Every class is namespaced `nv-`. Every custom property is namespaced
      `--nv-`. Nothing here selects a bare element (no `body`, `ul`, `a`, `*`),
      so this file cannot touch anything outside the component.
   2. There is NO reset and NO normalize — Webflow injects its own. What used
      to be the reset now lives as scoped rules under "component baseline",
      which is what keeps Webflow's `ul{padding-left:40px}` and friends out.
   3. State is expressed only as `nv-is-*` classes and `data-nav-*` attributes,
      both written by nav.js. No `:has()`, no container queries.
   4. Load order: this file AFTER Webflow's own CSS.

   <link rel="stylesheet"
         href="https://cdn.jsdelivr.net/gh/OWNER/REPO@v1.10.1/nav.css">
   ========================================================================= */


/* ============================================================================
   0. FONTS
   Relative URLs — on jsDelivr they resolve next to this file, so `fonts/` must
   ship in the same tag. Delete this whole block if Webflow hosts Aeonik.
   TODO Aeonik-Bold is still .otf (~161KB); convert to woff2 before launch.
   ========================================================================= */
@font-face {
  font-family: "Aeonik";
  src: url("fonts/Aeonik-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap
}

@font-face {
  font-family: "Aeonik";
  src: url("fonts/Aeonik-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap
}

@font-face {
  font-family: "Aeonik";
  src: url("fonts/Aeonik-Bold.otf") format("opentype");
  font-weight: 700;
  font-style: normal;
  font-display: swap
}


/* ============================================================================
   1. TOKENS
   Kept on :root because `.nv-logo--standalone` (and, before v1.9.2, `.nv-scrim`)
   is a sibling of `.nv-wrap`, not a descendant — a component-scoped block
   would not reach it.
   The `--nv-` prefix is what keeps them from colliding with Webflow variables.
   ========================================================================= */
:root {
  /* colour lives in section 1b, NOT here — see the note there. */

  /* spacing */
  --nv-space-1: 4px;
  --nv-space-2: 8px;
  --nv-space-3: 12px;
  --nv-space-4: 16px;
  --nv-space-5: 24px;
  --nv-space-6: 32px;
  --nv-space-7: 40px;
  --nv-space-8: 48px;
  --nv-space-10: 80px;

  /* radius */
  --nv-radius-5: 12px;
  --nv-radius-6: 16px;
  --nv-radius-6-max: 24px;
  --nv-radius-full: 9999px;

  /* type */
  --nv-font: "Aeonik", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* geometry */
  --nv-button-h: 48px;
  --nv-bar-h: 80px;
  /* 80 = 16 + 48 + 16. Desktop takes it to 74 in section 6. */
  --nv-bar-top: 40px;

  /* container — mirrors Webflow's `.container-1280`, which is
       width:100%; max-width:84rem (1344); padding-inline:2rem (32)  ->  1280 content.
     --nv-container-max IS that 1280 content box (the pill's own width), and
     --nv-container-pad is the gutter outside it. Webflow drops the gutter to
     1rem at <=767, and so does the mobile block below. */
  --nv-container-max: 1280px;
  --nv-container-pad: 32px;
  --nv-panel-tuck: 22px;
  /* tablet: bar bottom 120, Figma panel top 98. Desktop 20, mobile 24. */
  --nv-rail-w: 193px;
  /* tablet: Figma 767 + 193 = 960 */
  --nv-menu-left: 223.535px;
  /* 24 bar padding + 175.535 logo + 24 gap */
  --nv-link-pad: var(--nv-space-5);
  /* horizontal only — the spacing between links. 24 here because the tablet
     rail is 193px wide and has the room. Desktop squeezes it: see section 6. */
  --nv-blur: 20px;
  --nv-scrim-blur: 10px;
  /* the mobile backdrop behind the drawer — Figma's "BG Blur" effect, half
     the bar's. Not a Nav variable: the scrim is styled entirely here (the
     Style panel cannot express backdrop-filter), so nothing in Webflow reads
     it. Used in section 7 only. */
  --nv-ease: cubic-bezier(.4, 0, .2, 1);
  --nv-dur: 300ms;

  /* panel swap — desktop only. The surface morphs its height with --nv-dur
     while the OUTGOING panel fades and slides against the travel direction and
     the INCOMING one slides in behind it. The in-delay is what makes them
     overlap rather than queue: out runs 0-180, in runs 80-340.
     nav.js reads --nv-swap-out-dur so the cleanup timer cannot drift from the
     transition it is waiting on — change the number here, only here. */
  --nv-swap-shift: 40px;
  /* horizontal travel when moving between two heads. 24 read as a twitch on a
     1280 panel — the eye needs roughly a card's worth of movement before it
     registers as travel rather than a settle. Above ~56 the incoming column
     starts arriving visibly clipped by .nv-panels' overflow. */
  --nv-swap-rise: 8px;
  /* vertical travel when the menu opens from closed */
  --nv-swap-in-dur: 260ms;
  --nv-swap-in-delay: 80ms;
  --nv-swap-out-dur: 180ms;
  --nv-swap-in-ease: cubic-bezier(.22, 1, .36, 1);
  --nv-swap-out-ease: cubic-bezier(.4, 0, 1, 1);

  /* mobile reveal — <=767 only. The bottom bar starts parked off-screen and
     slides in once the page has been scrolled past --nv-reveal-at, then slides
     back out above it. nav.js reads all four; section 7 holds the geometry.
       --nv-reveal-at    how far down the page the bar arrives. Any length
                         nav.js can resolve — vh, %, px, rem, or a bare number
                         read as px. This is the one knob worth touching.
       --nv-reveal-hyst  slack on the way back up, so a scroll that stops dead
                         on the threshold cannot flutter the bar in and out.
       --nv-reveal-dur   the slide. Faster than --nv-dur on purpose: the bar is
                         arriving unasked, so it has to be over before it reads
                         as something the page is doing TO you.
       --nv-reveal-ease  decelerate, no overshoot. A spring on a nav surface
                         reads as a toy; this arrives fast and settles. */
  --nv-reveal-at: 0;
  --nv-reveal-hyst: 40px;
  --nv-reveal-dur: 360ms;
  --nv-reveal-ease: cubic-bezier(.16, 1, .3, 1);

  /* breakpoints — nav.js reads these, so they are declared in one place only.
     Unitless on purpose: JS parses the number. These are the LAST pixel of the
     tier below, so each is the exact complement of its media query:
       nav.js `w > 1279 -> desktop`   <->   @media (min-width:1280px)
       nav.js `w > 767  -> tablet`    <->   @media (max-width:767px)
     Change one and you must change the other. */
  --nv-bp-tablet: 1279;
  --nv-bp-mobile: 767;
}


/* ============================================================================
   1b. COLOUR — bound to Webflow's "Color" variable collection
   ----------------------------------------------------------------------------
   THESE ARE DELIBERATELY NOT ON :root, and that is the entire mechanism.

   A custom property is substituted against the element it is DECLARED on. Put
   `--nv-surface: var(--_color---white)` on :root and it resolves once, against
   :root, and freezes at the Base value — Webflow writes its Dark mode as
   `.dark-theme { --_color---white: #1c1c1e }`, which is BELOW :root and can
   never reach back up. Declared here instead, on the four elements the
   component actually roots at, the lookup happens inside `.dark-theme` and the
   whole navbar flips for free: no JS, no media query, no second palette.

   The four selectors were every top-level node in nav.html — .nv-wrap plus
   the three that are siblings of it. `.nv-scrim` moved inside the header in
   v1.9.2 and would inherit anyway; it stays listed, harmlessly, so the
   declaration does not depend on where the Designer keeps it. Everything
   else inherits.

   Second value in each var() is the fallback, used verbatim anywhere the
   Webflow variables are absent (embed.html, preview.html, a non-Webflow host).
   Those fallbacks are the original Figma values, so the component still looks
   right standing on its own.

   Webflow's Variables panel is now the single source of truth for these: a
   client retinting "Color" retints the navbar, in both modes, with no code
   change here. Do not re-hardcode a colour into this file.

   Three colours have no variable and stay literal on purpose:
     --nv-accent-contrast  white button label; it sits on Accent 9, which is
                           the same in both modes, so it must NOT flip.
     --nv-scrim-bg         the TABLET dim; a dark scrim reads correctly in
                           both modes. Below 768 the scrim is not a dim at
                           all — section 7 swaps it for a frosted backdrop
                           through --nv-overlay-scrim, a variable of its
                           own (see it below). `.nv-scrim` is in the
                           selector list below precisely so that lookup
                           happens inside `.dark-theme`.
     .nv-promo-media       has no fill of its own — it uses --nv-surface.
   ========================================================================= */
.nv-skip-link,
.nv-logo--standalone,
.nv-wrap,
.nv-scrim {
  --nv-accent-9: var(--_color---accent--accent-9, #8a68e9);
  --nv-accent-9-hover: var(--_color---accent--accent-10, #7a55e4);
  --nv-accent-alpha-11: var(--_color---accent--alpha-11, rgba(42, 0, 107, .933));
  /* active nav item — Accent Alpha 3, not Violet Alpha 3: only the accent
     ramp has a Dark value, and #3700ff1c is invisible on a dark ground. */
  --nv-violet-alpha-3: var(--_color---accent--alpha-3, rgba(55, 0, 255, .11));
  /* the pill's glow and the panel divider. Figma's dark navbar (4423:6218)
     draws the glow with Colors/Gray/4 at #323232, so Gray 4 was given that
     Dark value in Webflow — base #e8e8e8 is untouched. */
  --nv-gray-4: var(--_color---gray--gray-4, #e8e8e8);
  /* promo column ground */
  --nv-gray-alpha-2: var(--_color---gray--gray-alpha-2, rgba(0, 0, 0, .02));
  --nv-neutral-alpha-3: var(--_color---neutral--alpha-3, rgba(0, 0, 0, .06));
  /* the bar pill itself. Figma draws the light bar with White Alpha 9 (70%
     white) and the dark bar with Gray Alpha 4 (rgba(253,253,234,.1)) — two
     different variables, which one token cannot follow. Resolved in Webflow
     instead: White Alpha 9 now carries Gray Alpha 4's colour as its Dark
     value, so both modes are exact and the light bar keeps its 70%. */
  --nv-white-alpha-9: var(--_color---white-alpha-9, rgba(255, 255, 255, .698));
  /* the mobile drawer's backdrop (section 7). Figma draws it with White
     Alpha 9, but that variable's Dark value is the bar pill's pale tint
     (rgba(253,253,234,.1)) and a pale frost over a dark page reads wrong.
     So the backdrop has a variable of its own — "Overlays / Scrim" in the
     Color collection: 70% white in Base, 70% black in Dark — and White
     Alpha 9 is untouched. Must match the Webflow CSS name exactly or the
     fallback wins in both modes. */
  --nv-overlay-scrim: var(--_color---overlays--scrim, rgba(255, 255, 255, .7));
  --nv-text-primary: var(--_color---text-primary, #202020);
  --nv-text-heading: var(--_color---text-primary, #1d1d21);
  --nv-text-secondary: var(--_color---secondary, #646464);
  --nv-text-disabled: var(--_color---text-disabled, rgba(0, 0, 0, .27));
  --nv-text-logo: var(--_color---misc--brand-font, #1d0443);
  --nv-surface: var(--_color---white, #ffffff);
  --nv-icon-tile-bg: var(--_color---accent--accent-2, #f0ebff);
  --nv-info-9: var(--_color---semantic--info-9, #0090ff);

  /* no variable — see the note above */
  --nv-accent-contrast: #ffffff;
  --nv-scrim-bg: rgba(32, 32, 32, .28);

  /* colour-bearing, so it has to live here rather than with the geometry */
  --nv-shadow: 0 0 10px 0 var(--nv-gray-4);
}


/* ============================================================================
   2. COMPONENT BASELINE
   This replaces the old global reset. Every selector is anchored to an `nv-`
   class, so Webflow's normalize keeps its job everywhere else on the page.
   ========================================================================= */
.nv-wrap,
.nv-wrap *,
.nv-wrap *::before,
.nv-wrap *::after,
.nv-scrim,
.nv-skip-link,
.nv-logo--standalone,
.nv-logo--standalone * {
  box-sizing: border-box
}

.nv-wrap,
.nv-logo--standalone,
.nv-skip-link {
  font-family: var(--nv-font);
  color: var(--nv-text-primary);
  -webkit-font-smoothing: antialiased;
}

/* anchors — Webflow styles "All Links"; opt out inside the component.
   .nv-menu-btn is in this list because the native build renders the toggle as
   an <a href="#">, not the <button> nav.html declares — see NOTES.md § 12.3. */
.nv-skip-link,
.nv-logo,
.nv-link,
.nv-btn,
.nv-card,
.nv-promo-cta,
.nv-menu-btn {
  color: inherit;
  text-decoration: none;
}

/* buttons — Webflow's normalize leaves UA button styling in place */
.nv-link,
.nv-menu-btn {
  font: inherit;
  /* size, weight and line-height too — the old
                                global `button{font:inherit}` did exactly this */
  color: inherit;
  background: none;
  border: 0;
  margin: 0;
  padding: 0;
  text-align: left;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.nv-card.nv-is-disabled {
  cursor: default
}

/* the <ul> — this is the rule that survives Webflow's ul{padding-left:40px} */
.nv-menu {
  margin: 0;
  padding: 0;
  list-style: none
}

/* headings + paragraphs inside the panels */
.nv-group-label,
.nv-promo-title,
.nv-promo-sub,
.nv-todo {
  margin: 0
}

/* inline SVG icons fill their box */
.nv-wrap svg,
.nv-logo--standalone svg {
  display: block;
  width: 100%;
  height: 100%
}

/* Webflow wraps every Embed element in a <div class="w-embed">. After the port
   the icons are Embeds, so that wrapper has to drop out of the layout — left in
   flow the SVG would measure 100% of an auto-height div and collapse to nothing.
   Harmless outside Webflow: there is no .w-embed there. */
.nv-wrap .w-embed,
.nv-logo--standalone .w-embed {
  display: contents
}

.nv-skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  background: var(--nv-surface);
  padding: 12px 16px;
  border-radius: var(--nv-radius-6);
}

.nv-skip-link:focus {
  left: 16px;
  top: 16px
}

.nv-wrap :where(a, button):focus-visible,
.nv-logo--standalone:focus-visible,
.nv-skip-link:focus-visible {
  outline: 2px solid var(--nv-accent-9);
  outline-offset: 3px;
  border-radius: var(--nv-radius-6);
}


/* ============================================================================
   3. LOGO — now entirely in the Webflow Style panel.
   The box is 175.535 x 34 (Figma I153:845;5531:23300) and the children are
   percentages of it, so the mobile 222 x 43 lockup is the same asset at a
   bigger font-size. Edit .nv-logo / .nv-logo-mark / .nv-logo-word in Webflow.
   Three placements, one shown at a time: --inbar (desktop, tablet), and on
   mobile --standalone at the top of the page plus --drawer at the top of the
   open drawer (v1.9.0). The one thing this file adds for the drawer copy is a
   runtime-state rule in section 7 — it goes with the list on drill-in.
   ========================================================================= */


/* ============================================================================
   4. SHELL
   .nv-bar is its own pill and never resizes. .nv-shell is a stacking wrapper
   with no surface of its own.
   ========================================================================= */

.nv-bar {
  -webkit-backdrop-filter: blur(var(--nv-blur));
  backdrop-filter: blur(var(--nv-blur));
  box-shadow: var(--nv-shadow);
}

/* z-index:auto here on purpose — .nv-body must NOT create a stacking context,
   or the lifted desktop link row could never paint above the bar pill.
   Here the list lives inside the body, so the body is the clipped animator and
   carries the tuck and the surface. Desktop lifts the link row up into the bar
   and hands the clipping to .nv-panels instead — see section 6.
   nav.js picks the right element per breakpoint. */
.nv-body {
  grid-template-columns: minmax(0, 1fr) var(--nv-rail-w);
  top: calc(-1 * var(--nv-panel-tuck));
  transition: height var(--nv-dur) var(--nv-ease);
  box-shadow: var(--nv-shadow);
}

/* Tablet only: the body must NEVER scroll — scrolling it would drag the
   193px rail along with the mega-menu. Only .nv-panels moves. The mobile
   block below overrides this, because there the body IS the scroller. */
.nv-body.nv-is-scrollable {
  overflow: hidden
}

.nv-panels {
  transition: none;
  top: 0;
  box-shadow: none;
}

.nv-panels.nv-is-scrollable {
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain
}


/* ---------- link list: rail on the right — natural height, pinned to the top
     of the row, so it stays put while the left column scrolls. Desktop lifts
     this into the bar as a horizontal row; see section 6. ---------- */
.nv-menu {
  top: auto;
  padding-top: var(--nv-space-5);
  /* 24 */
}

.nv-link {
  padding: var(--nv-space-5) var(--nv-link-pad);
  /* vertical 24 = the 74px row height and the active highlight.
     horizontal is --nv-link-pad, which IS the spacing between links. */
  font-size: 16px;
  line-height: 26px;
  /* line-height stays 26 on purpose: 24 + 26 + 24 is the 74px row. */
  font-weight: 700;
  color: var(--nv-text-primary);
  transition: color var(--nv-dur) var(--nv-ease), background-color var(--nv-dur) var(--nv-ease);
}

.nv-link:hover {
  color: var(--nv-accent-9)
}

.nv-item.nv-is-active .nv-link {
  background: var(--nv-violet-alpha-3);
  /* Colors/Violet Alpha/3 — square, full row height */
  color: var(--nv-accent-9);
}

.nv-btn {
  transition: background-color var(--nv-dur) var(--nv-ease);
}

.nv-menu-btn {
  padding: 0 var(--nv-space-5);
  color: var(--nv-accent-alpha-11);
  transition: background-color var(--nv-dur) var(--nv-ease);
}

.nv-menu-btn[data-nav-state="menu"] .nv-ico--menu {
  display: block
}

.nv-menu-btn[data-nav-state="close"] .nv-ico--close {
  display: block
}

.nv-menu-btn[data-nav-state="back"] .nv-ico--back {
  display: block
}


/* ============================================================================
   5. PANELS
   ========================================================================= */

.nv-panel[hidden] {
  display: none
}


/* ---------- panel swap (desktop) ----------
   Hover one head, then another, and the panel does not blink: the old content
   fades and slides out of the way while the new content slides in behind it,
   and the surface morphs its height between the two.

   How it holds together:

   · The INCOMING panel stays in normal flow, so it — and only it — dictates
     .nv-panels' height. The OUTGOING one is lifted to position:absolute, which
     takes it out of flow, so the height animation is never a tug-of-war.
   · Direction comes from `data-nav-swap` on .nv-panels, written by nav.js from
     the two heads' positions in the link row: `next` = moved right, `prev` =
     moved left, plus `open`/`close` for the first and last step. One attribute
     drives both halves, so the two panels can never travel the same way.
   · The start states are separate classes (.nv-is-enter / .nv-is-out) that
     nav.js applies a frame apart. The base state below is the resting state,
     which is what both panels transition TOWARD or AWAY FROM.

   Base `transform` stays `none`, not `translate3d(0,0,0)`: a permanent
   transform makes the panel a containing block for fixed/absolute descendants,
   and .nv-panel-inner holds a Webflow component whose internals we do not own.
   Nothing here reaches inside that slot — the whole effect is applied to
   .nv-panel, the wrapper this file owns. */
.nv-panel {
  transition: none;
}

/* start of the enter — committed with `transition:none` so it lands in one
   frame instead of animating INTO the offset it is about to animate out of */
.nv-panel.nv-is-enter {
  opacity: 0;
  transition: none;
}

.nv-panels[data-nav-swap="next"]>.nv-panel.nv-is-enter {
  transform: translate3d(var(--nv-swap-shift), 0, 0)
}

.nv-panels[data-nav-swap="prev"]>.nv-panel.nv-is-enter {
  transform: translate3d(calc(var(--nv-swap-shift) * -1), 0, 0)
}

/* opening from closed reads as an unfold, not a sideways swipe */
.nv-panels[data-nav-swap="open"]>.nv-panel.nv-is-enter {
  transform: translate3d(0, calc(var(--nv-swap-rise) * -1), 0)
}

/* the outgoing panel, parked out of flow for the length of its fade.
   max-height + overflow keep it from lengthening .nv-panels' scroll area while
   the surface shrinks under it; pointer-events stop it from swallowing a hover
   aimed at the panel arriving underneath. */
.nv-panel.nv-is-leave {
  position: static;
  top: 0;
  left: 0;
  right: 0;
  max-height: none;
  overflow: visible;
  pointer-events: auto;
  transition:
    opacity var(--nv-swap-out-dur) var(--nv-swap-out-ease),
    transform var(--nv-swap-out-dur) var(--nv-swap-out-ease);
}

.nv-panel.nv-is-leave.nv-is-out {
  opacity: 0
}

.nv-panels[data-nav-swap="next"]>.nv-panel.nv-is-leave.nv-is-out {
  transform: translate3d(calc(var(--nv-swap-shift) * -1), 0, 0)
}

.nv-panels[data-nav-swap="prev"]>.nv-panel.nv-is-leave.nv-is-out {
  transform: translate3d(var(--nv-swap-shift), 0, 0)
}

/* closing: the surface collapsing is the movement. A slide on top of it just
   fights the height transition, so the last panel only fades. */
.nv-panels[data-nav-swap="close"]>.nv-panel.nv-is-leave.nv-is-out {
  transform: none
}

/* promo column — media beside the copy below 1280. Desktop turns it into the
   424-wide stacked column from Figma 87:298; see section 6. */
.nv-promo {
  grid-template-areas: "media head" "media cta";
}

.nv-promo-cta {
  color: var(--nv-accent-contrast);
}

.nv-card {
  transition: background-color var(--nv-dur) var(--nv-ease);
}

a.nv-card:hover {
  background: var(--nv-icon-tile-bg)
}

.nv-card.nv-is-disabled .nv-card-title,
.nv-card.nv-is-disabled .nv-card-desc {
  color: var(--nv-text-disabled)
}

/* Partners — Figma 212:7450 is a 3 x 1fr grid, so its column is 517.33 wide
   and the descriptions sit on one line. */
.nv-panel--thirds .nv-groups {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--nv-space-10);
  padding: var(--nv-space-8) var(--nv-space-7) var(--nv-space-7);
}

.nv-panel--thirds .nv-group {
  max-width: none
}

.nv-panel--thirds .nv-split {
  justify-self: center
}

/* Figma draws Platform's divider 404 tall against a 420 tall column */
.nv-panel[data-nav-panel="platform"] .nv-split {
  align-self: flex-start;
  height: 404px
}

/* The page scrim behind the tablet drawer: a dim. Section 7 restyles it for
   mobile, where the Figma frame frosts the page instead. Since v1.9.2 it is
   the LAST CHILD of .nv-wrap, so its 99 now ranks inside the header's own
   stacking context (the header is z-index 100): the Style panel gives
   .nv-shell z-index 100 to keep the bar and the drawer above it, and the
   header as a whole still clears .nv-logo--standalone (98). Still fixed to
   the viewport — .nv-wrap has no transform once revealed (section 7). */
.nv-scrim {
  position: fixed;
  inset: 0;
  z-index: 99;
  background: var(--nv-scrim-bg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--nv-dur) var(--nv-ease);
}

.nv-scrim.nv-is-open {
  opacity: 1;
  pointer-events: auto
}


/* ============================================================================
   6. DESKTOP — >= 1280px   (keep in sync with --nv-bp-tablet, which is 1279)
   Everything above this block is the COLLAPSED layout: hamburger, one-column
   mega-menu, 193px link rail on the right. That is the base state, and the
   mobile block below inherits from it.

   Written as min-width on purpose. Webflow has no max-width tier between 992
   and 1279 — above `main` its tiers only run upward, `large` (>=1280) and
   `xl` (>=1440) — so this file is shaped desktop-up to map 1:1 onto the
   Designer's breakpoints. See NOTES.md § 12.

   Open state: link row lifted into the bar, mega-menu below it.
   ========================================================================= */
@media (min-width:1280px) {
  :root {
    --nv-bar-h: 74px;
    /* 74 = 24 + 26 + 24 */
    --nv-panel-tuck: 20px;
    /* desktop: bar bottom 114, Figma panel top 94 */
    --nv-link-pad: 12px;
    /* Between 1280 and 1439 the container is narrower than its 1280 cap
       (vw - 64), bottoming out at 1216 at exactly 1280px of viewport. The row
       still fits, but only on 12px link padding:

         24 padL + 175.535 logo + 24 gap + 695 links + 91 Login + 8 + 158 Demo
         + 16 padR = 1191.5, inside 1216 with 24px to spare.

       At 16px it would be 31.5px over. Section 6b restores 16 at 1440. */
  }

  /* the link row is lifted up into the bar, so .nv-body must NOT clip — the
     height animation moves onto .nv-panels instead, and the surface with it.
     nav.js picks the right element per breakpoint. */
  .nv-body {
    grid-template-columns: none;
    top: auto;
    transition: none;
    box-shadow: none;
  }

  .nv-body.nv-is-scrollable {
    overflow: visible
  }

  .nv-panels {
    top: calc(-1 * var(--nv-panel-tuck));
    /* tuck behind the pill */
    transition: height var(--nv-dur) var(--nv-ease);
    box-shadow: var(--nv-shadow);
  }

  /* ---------- link list: desktop row, lifted into the bar ---------- */
  .nv-menu {
    top: calc(-1 * var(--nv-bar-h));
    padding-top: 0;
  }

  /* ---------- panel swap — desktop only. See the note in section 5. ------- */
  .nv-panel {
    transition:
      opacity var(--nv-swap-in-dur) var(--nv-swap-in-ease) var(--nv-swap-in-delay),
      transform var(--nv-swap-in-dur) var(--nv-swap-in-ease) var(--nv-swap-in-delay);
  }

  .nv-panel.nv-is-leave {
    position: absolute;
    max-height: 100%;
    overflow: hidden;
    pointer-events: none;
  }

  /* promo column — Figma 87:298, 424 wide, self-stretch */
  .nv-promo {
    grid-template-areas: "head" "media" "cta";
  }

  .nv-promo+.nv-groups {
    padding-left: 0
  }
}


/* ============================================================================
   6b. WIDE DESKTOP — >= 1440px   (Webflow's `xl` tier)
   At 1440 and up the container reaches its 1280 cap and stops shrinking, so
   the row gets back the 31.5px it was short of and the link padding returns
   to 16. Nothing else in the bar moves — this block sets one token and stops.
   ========================================================================= */
@media (min-width:1440px) {
  :root {
    --nv-link-pad: 16px;
  }
}


/* ============================================================================
   7. MOBILE — <= 767px   (keep in sync with --nv-bp-mobile)
   The bar moves to the BOTTOM and the drawer becomes a SEPARATE surface that
   sits above it, tucked 24px behind. Drilling into a menu replaces the link
   list with that menu's panel and the hamburger becomes a back chevron.
   ========================================================================= */
@media (max-width:767px) {
  :root {
    --nv-panel-tuck: 24px;
    /* mobile: drawer bottom 794, bar top 770 */
    --nv-container-pad: 16px;
    /* Webflow drops .container-1280 to padding-inline:1rem here */
  }

  /* ---- reveal on scroll ---------------------------------------------------
     The bar is parked below the viewport edge, and nav.js slides it in once the
     page has been scrolled past --nv-reveal-at (section 1).

     The travel is the bar's own height (100% — .nv-body is absolute at this
     tier, so the drawer does not count toward it), plus the 24px the wrap sits
     above the viewport bottom, plus 16 to clear --nv-shadow's 10px blur. That
     24 mirrors `bottom: var(--nv-space-5)` in the Webflow Style panel — move
     one, move the other.

     `visibility` is what takes the bar out of the tab order and off the
     accessibility tree while it is away; an off-screen transform alone still
     leaves it focusable. It is transitioned with a DELAY rather than a
     duration, so it flips at the end of the slide out and at the start of the
     slide in. Section 9 zeroes that delay, so reduced motion just cuts.

     Tucked is the DEFAULT here rather than a class nav.js adds, so the bar
     cannot flash into view before the script boots. That does make the reveal
     depend on nav.js — which the mobile nav already does at every level: the
     drawer, the drilldown and the panel hiding are all script-driven. The
     Webflow Designer never runs custom code, so the canvas is unaffected. */
  .nv-wrap {
    transform: translateY(calc(100% + var(--nv-space-5) + var(--nv-space-4)));
    visibility: hidden;
    transition: transform var(--nv-reveal-dur) var(--nv-reveal-ease),
      visibility 0s linear var(--nv-reveal-dur);
  }

  .nv-wrap.nv-is-revealed {
    transform: none;
    visibility: visible;
    transition: transform var(--nv-reveal-dur) var(--nv-reveal-ease),
      visibility 0s linear 0s;
  }

  .nv-menu-btn {
    padding: 0
  }

  .nv-menu-btn[data-nav-state="back"] {
    background: var(--nv-icon-tile-bg)
  }

  /* drawer: own surface, above the bar, tucked 24 behind it */
  .nv-body {
    top: auto;
    bottom: calc(var(--nv-bar-h) - var(--nv-panel-tuck));
    /* 80 - 24 = 56 */
    -webkit-backdrop-filter: blur(var(--nv-blur));
    backdrop-filter: blur(var(--nv-blur));
    box-shadow: var(--nv-shadow);
    transition: height var(--nv-dur) var(--nv-ease);
  }

  /* backdrop: 70% white over a 10px blur (Figma "BG Blur"), so the page
     reads as frosted rather than dimmed; 70% black in Dark. The colour is
     the "Overlays / Scrim" Webflow variable, through the alias declared on
     this element in 1b; the blur is --nv-scrim-blur (section 1). The
     standalone logo is z-index 98, under this, so it blurs with the page —
     which is how the frame draws it. The base opacity transition fades the
     blur in with the colour. Mobile only: the tablet drawer keeps the dim
     above. */
  .nv-scrim {
    background: var(--nv-overlay-scrim);
    -webkit-backdrop-filter: blur(var(--nv-scrim-blur));
    backdrop-filter: blur(var(--nv-scrim-blur));
  }

  /* FIX — the drawer is the scroller on mobile.
     This overrides `.nv-body.nv-is-scrollable{overflow:hidden}` from the tablet
     block above (equal specificity, later source order). Without it the tablet
     rule leaked down here and pinned the drawer shut, which is why a tall panel
     such as "Platform overview" could not be scrolled and why the 7th link
     ("Company") was unreachable below the fold on a 375x667 screen. */
  .nv-body.nv-is-scrollable {
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }

  /* the 40px bottom padding lives on the inner scroll content so it does not
     fight the height animation, and so the last row clears the tucked pill */
  .nv-body:not(.nv-is-drilled) .nv-menu {
    padding-bottom: var(--nv-space-7)
  }

  .nv-body.nv-is-drilled .nv-panels {
    padding-bottom: var(--nv-space-7)
  }

  .nv-menu {
    padding-top: 0
  }

  .nv-body.nv-is-drilled .nv-menu {
    display: none
  }

  /* The drawer logo is a sibling of the list, not part of it (a link inside
     role="list" would be announced as a bogus eighth item), so it needs its
     own drill-in rule. The Figma sub-screens (167:4529 etc.) open straight on
     their group list — no logo. Its size and centring are in the Style panel
     (.nv-logo.nv-logo--drawer, mirrored in nav-panel.css). */
  .nv-body.nv-is-drilled .nv-logo--drawer {
    display: none
  }

  .nv-link {
    font-size: 20px;
    line-height: 28px;
  }

  .nv-item.nv-is-active .nv-link {
    background: none;
    color: var(--nv-text-primary)
  }

  .nv-promo {
    grid-template-areas: "head" "media" "cta";
  }

  /* Carried over from before the desktop-up flip, deliberately. The old tablet
     block wrote `.nv-groups, .nv-promo+.nv-groups` as ONE selector, which gave
     the promo-adjacent groups (0,2,0) specificity — enough to outrank the
     `.nv-groups` rule directly above. Only the Platform panel has a promo, so
     on mobile that one panel keeps 48/40/40 padding and a 40 gap while the
     other five sit at 24. That reads like an accident rather than a decision,
     but it is what shipped, and the flip is meant to change nothing.
     DELETE THIS RULE to make mobile uniform — nothing else depends on it. */
  .nv-promo+.nv-groups {
    padding: var(--nv-space-8) var(--nv-space-7) var(--nv-space-7);
    gap: var(--nv-space-7);
  }
}


/* ============================================================================
   8. MOBILE PORTRAIT — <= 479px
   Figma's mobile artboard is 402 wide, already inside the block above.
   ========================================================================= */
@media (max-width:479px) {
  /* no further changes required */
}


/* ============================================================================
   9. REDUCED MOTION — scoped, so it cannot disable animation page-wide
   ========================================================================= */
@media (prefers-reduced-motion:reduce) {

  .nv-wrap,
  .nv-wrap *,
  .nv-scrim,
  .nv-logo--standalone {
    transition-duration: .001ms !important;
    animation-duration: .001ms !important;
    /* --nv-swap-in-delay would otherwise survive the duration reset and leave
       an 80ms hole between the two panels */
    transition-delay: 0ms !important;
    animation-delay: 0ms !important;
  }
}