/* ==========================================================================
   data source — GLASS NAV
   The three-pill navigation from glass-v2.html, cut down to ship on the
   homepage. Everything is namespaced `gv-`.

   ── WHY THE NAMESPACE ──────────────────────────────────────────────────────
   `liquid.css` and the GENERATED `liquid-hero-v2.css` both own `.nav`,
   `.nav-inner`, `.nav-links`, `.brand*`, `.glass` and `.pane`, and the scene
   generator injects hero-v2 AFTER every hand-written link in liquid.html — so
   anything sharing those names would lose the cascade to a generated file that
   gets rewritten on the next `node tools/build-scene-variants.js`. Prefixing
   sidesteps the whole question: hero-v2 never says `gv-`, so load order stops
   mattering and neither file has to be touched.

   The old `.nav*` rules in both files now match nothing, because the markup
   they targeted is gone. They are left in place deliberately — `liquid-hero-v2.css`
   is generated and hand-edits there are lost on the next build.

   ── THE MATERIAL (measured off workflows.io, 2026-08-21) ────────────────────
   Their glass is NOT a fill plus a blur — the pill's own background is
   `rgba(255,255,255,.02)`. It is four shadow layers plus a 5px backdrop blur:
   a white hairline ring, an ambient outer bloom, and an OPPOSED pair of insets
   (cool shade top-left, specular bottom-right) that bevels the surface with no
   gradient painting and no extra element.
   Transitions: material .38s cubic-bezier(.22,1,.36,1); the width collapse
   .45s cubic-bezier(.65,0,.35,1).
   ========================================================================== */

.gv-nav {
  /* Scoped, not on :root — liquid.css owns the page tokens and this must not
     reach past the header. --ink/--accent/--sans are inherited from there on
     purpose, so the nav can never drift from the rest of the brand. */
  --gv-ring:  rgba(255, 255, 255, .95);
  --gv-bloom: rgba(11, 18, 32, .05);
  --gv-shade: rgba(203, 214, 230, .45);
  --gv-spec:  rgba(255, 255, 255, .60);
  --gv-fill:  rgba(255, 255, 255, .04);
  --gv-sheet: rgba(255, 255, 255, .72);

  --gv-panel: rgba(238, 242, 246, .78);
  --gv-card:  rgba(255, 255, 255, .82);
  --gv-hair:  rgba(11, 18, 32, .07);

  --gv-mat: cubic-bezier(.22, 1, .36, 1);
  --gv-geo: cubic-bezier(.65, 0, .35, 1);

  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 90;
  padding: 14px 26px 0;
  font-family: var(--sans);

  opacity: 0;
  transform: translateY(-14px);
}

.gv-nav.is-ready {
  opacity: 1;
  transform: none;
  transition: opacity .6s var(--gv-mat), transform .6s var(--gv-mat);
}

/* The temperature flip. `color` MUST be re-declared alongside the tokens:
   redefining --ink alone changes nothing for inherited text, because `color`
   was already resolved further up and inheritance passes the COMPUTED colour
   down, not the variable reference. Missing it fails PARTIALLY — anything with
   an explicit `color: var(--ink)` flips while plain inherited text stays
   dark-on-dark, which reads as a bug in one component rather than a missing
   line here. */
.gv-nav [data-theme="dark"] {
  color: #F4F7FC;

  --ink: #F4F7FC;
  --gv-ring:  rgba(255, 255, 255, .16);
  --gv-bloom: rgba(0, 0, 0, .55);
  --gv-shade: rgba(0, 0, 0, .55);
  --gv-spec:  rgba(255, 255, 255, .10);
  --gv-fill:  rgba(255, 255, 255, .05);
  --gv-sheet: rgba(255, 255, 255, .05);

  --gv-panel: rgba(20, 25, 34, .74);
  --gv-card:  rgba(30, 36, 48, .80);
  --gv-hair:  rgba(255, 255, 255, .08);
}

/* A pill that STRADDLES a light/dark seam — this page's benchmarks band carries
   a light chart card over its right half — cannot be fixed by either theme:
   ink text vanishes on the dark side, white text on the light side. So it stops
   being translucent for exactly that stretch and carries its own ground. Text
   stays ink, which is now legible because the pill is opaque. Set from
   glass-nav.js, which measures how much of each pill the overlay covers. */
.gv-nav [data-ground="mixed"] {
  --gv-fill:  rgba(255, 255, 255, .88);
  --gv-ring:  rgba(255, 255, 255, 1);
  --gv-shade: rgba(203, 214, 230, .50);
  --gv-spec:  rgba(255, 255, 255, .70);
  --gv-bloom: rgba(11, 18, 32, .22);
}

/* ── the material ───────────────────────────────────────────────────────── */

.gv-glass {
  background: var(--gv-fill);
  -webkit-backdrop-filter: blur(5px) saturate(140%);
  backdrop-filter: blur(5px) saturate(140%);
  border-radius: 10px;
  box-shadow:
    inset 0 0 0 .9px var(--gv-ring),
    0 0 14px var(--gv-bloom),
    inset  7px  7px 17px var(--gv-shade),
    inset -7px -7px 17px var(--gv-spec);
  transition:
    background .38s var(--gv-mat),
    box-shadow .38s var(--gv-mat),
    color      .38s var(--gv-mat);
}

/* ── layout: three groups, collapsing to one cluster ────────────────────── */

.gv-inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  max-width: 1420px;
  margin: 0 auto;
  transition: width .45s var(--gv-geo), gap .45s var(--gv-geo);
}

.gv-nav.is-stuck .gv-inner { width: fit-content; gap: 8px; }

.gv-group {
  display: flex;
  align-items: center;
  height: 46px;
  padding: 0 6px;
  border: 0;
  font: inherit;
  color: inherit;
}

.gv-brand { gap: 9px; padding: 0 13px; }

/* two cuts of the mark, cross-faded by theme: the ink badge dies on black and
   the white emblem dies on white, and a CSS filter cannot fake it because the
   badge is blue linework, not a monochrome glyph */
.gv-mark { position: relative; width: 21px; height: 21px; flex: none; }

.gv-badge {
  position: absolute;
  inset: 0;
  width: 21px;
  height: 21px;
  /* stops the global `img { max-width: 100% }` clamping the badge to a
     shrink-to-fit parent that is itself sized by the badge */
  max-width: none;
  transition: opacity .38s var(--gv-mat);
}
.gv-badge-white { opacity: 0; }
.gv-nav [data-theme="dark"] .gv-badge-ink { opacity: 0; }
.gv-nav [data-theme="dark"] .gv-badge-white { opacity: 1; }

.gv-word {
  font-family: var(--brand-face, "Orbitron", "Michroma", sans-serif);
  font-weight: 400;
  font-size: 13px;
  letter-spacing: .01em;
  white-space: nowrap;
  color: var(--ink);
  max-width: 120px;
  overflow: hidden;
  transition:
    max-width .45s var(--gv-geo),
    opacity   .22s var(--gv-mat),
    margin    .45s var(--gv-geo),
    color     .38s var(--gv-mat);
}
.gv-nav.is-stuck .gv-word { max-width: 0; opacity: 0; margin-left: -9px; }

/* ── the link pill ──────────────────────────────────────────────────────── */

.gv-pill { display: flex; align-items: center; gap: 2px; padding: 0 10px; }

.gv-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: 5px;
  height: 34px;
  padding: 0 13px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 13.5px;
  color: var(--ink);
  cursor: pointer;
  border-radius: 8px;
  white-space: nowrap;
  text-decoration: none;
  transition: color .38s var(--gv-mat);
}

/* the hovered item gets its own small pane */
.gv-link::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 8px;
  background: var(--gv-sheet);
  box-shadow: inset 0 0 0 .9px var(--gv-ring);
  opacity: 0;
  transform: scale(.94);
  transition: opacity .28s var(--gv-mat), transform .28s var(--gv-mat);
}
.gv-link:hover::before,
.gv-link[aria-expanded="true"]::before { opacity: 1; transform: scale(1); }
.gv-link > * { position: relative; }

.gv-caret { width: 9px; height: 9px; opacity: .45; transition: transform .3s var(--gv-mat); }
.gv-link[aria-expanded="true"] .gv-caret { transform: rotate(180deg); }

/* ── the CTA pill ───────────────────────────────────────────────────────── */

/* The reference pairs one label with one accent square as a SINGLE link. The
   old homepage nav carried two actions (Sign in, Start free) and dropping one
   to match the reference would be a regression, so sign-in sits beside the
   lockup rather than inside it. */
.gv-cta { gap: 14px; padding: 0 6px 0 16px; }

.gv-signin {
  font-size: 13.5px;
  color: var(--ink-3);
  text-decoration: none;
  white-space: nowrap;
  transition: color .38s var(--gv-mat);
}
.gv-signin:hover { color: var(--ink); }
.gv-nav [data-theme="dark"] .gv-signin { color: rgba(255, 255, 255, .62); }
.gv-nav [data-theme="dark"] .gv-signin:hover { color: #fff; }

.gv-start {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
}

.gv-cta-text {
  font-size: 13.5px;
  color: var(--ink);
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
  white-space: nowrap;
  transition: color .38s var(--gv-mat);
}

.gv-square {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 7px;
  background: var(--accent);
  color: #fff;
  box-shadow: 0 2px 10px rgba(37, 99, 235, .35);
  transition: transform .3s var(--gv-mat), box-shadow .3s var(--gv-mat);
}
.gv-square svg { width: 14px; height: 14px; display: block; }
.gv-cta:hover .gv-square {
  transform: translate(1px, -1px);
  box-shadow: 0 6px 18px rgba(37, 99, 235, .45);
}

/* ==========================================================================
   THE MEGA-MENU
   Shell (one filter, a frame) → cards (no filter) → rows.
   ========================================================================== */

.gv-layer {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  justify-content: center;
  pointer-events: none;
}

.gv-menu { position: relative; display: none; pointer-events: auto; }
.gv-menu.is-open { display: block; }

/* THE GLOW. A blurred, scaled, brand-tinted layer BEHIND the panel. A
   box-shadow can only ever darken its ground, so it can never read as light
   leaving the panel — which is the part of the reference worth copying. */
.gv-bloom {
  position: absolute;
  inset: 6px 10px 2px;
  border-radius: 26px;
  background:
    radial-gradient(60% 70% at 30% 40%, rgba(79, 141, 255, .30), transparent 70%),
    radial-gradient(55% 65% at 78% 62%, rgba(255, 255, 255, .85), transparent 72%),
    linear-gradient(180deg, rgba(255, 255, 255, .70), rgba(214, 227, 245, .55));
  filter: blur(26px);
  opacity: 0;
  transform: scale(.92) translateY(-6px);
  transition: opacity .42s var(--gv-mat) .06s, transform .42s var(--gv-mat) .06s;
}
.gv-menu.is-open .gv-bloom { opacity: 1; transform: scale(1.04) translateY(6px); }

.gv-nav [data-theme="dark"] .gv-bloom {
  background:
    radial-gradient(60% 70% at 30% 40%, rgba(79, 141, 255, .38), transparent 70%),
    radial-gradient(55% 65% at 78% 62%, rgba(120, 170, 255, .22), transparent 72%),
    linear-gradient(180deg, rgba(120, 160, 220, .18), rgba(20, 30, 48, .5));
}

.gv-shell {
  position: relative;
  display: flex;
  gap: 7px;
  padding: 7px;
  border-radius: 21px;
  background: var(--gv-panel);
  border: 1px solid var(--gv-ring);
  -webkit-backdrop-filter: blur(9px) saturate(135%);
  backdrop-filter: blur(9px) saturate(135%);
  box-shadow:
    0 0 14px var(--gv-bloom),
    inset  7px  7px 18px var(--gv-shade),
    inset -7px -7px 18px var(--gv-spec);
  opacity: 0;
  transform: translateY(-8px) scale(.985);
  transition: opacity .3s var(--gv-mat), transform .34s var(--gv-mat),
              background .38s var(--gv-mat), box-shadow .38s var(--gv-mat);
}
.gv-menu.is-open .gv-shell { opacity: 1; transform: none; }

/* flat children of the shell: no backdrop-filter of their own, ever — the
   shell already blurred the ground, and repeating the filter per card is what
   turns a pretty panel into a scroll-janking one */
.gv-card {
  background: var(--gv-card);
  border: 1px solid var(--gv-hair);
  border-radius: 14px;
}

.gv-col { padding: 14px 16px 18px; width: 400px; }

/* The visual column is a flex track, not fixed tiles: the left column's row
   count drives the shell height, so fixed tiles leave a dead band underneath
   whenever the two columns disagree. */
.gv-side {
  width: 268px;
  padding: 6px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.gv-menu-title { font-size: 12px; color: var(--ink-3); margin: 0 0 12px; }

/* The row keeps its 10px of horizontal padding so the hover highlight is wider
   than the text, then pulls it back out with an equal negative margin. Without
   the pull-back the padding pushes the icon 10px right of the column's own
   "Product" heading; with it, the icon's left edge and the heading's left edge
   sit on the same line, which is what the reference does. The negative margin
   stays inside .gv-col's 16px padding, so nothing overflows the card. */
.gv-row {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 9px 10px;
  margin-inline: -10px;
  border-radius: 11px;
  text-decoration: none;
  color: var(--ink);
  opacity: 0;
  transform: translateY(6px);
  transition: background .22s var(--gv-mat);
}
.gv-menu.is-open .gv-row {
  animation: gvRowIn .42s var(--gv-mat) forwards;
  animation-delay: calc(60ms + var(--i) * 45ms);
}
@keyframes gvRowIn { to { opacity: 1; transform: none; } }

.gv-row:hover { background: rgba(11, 18, 32, .04); }
.gv-nav [data-theme="dark"] .gv-row:hover { background: rgba(255, 255, 255, .06); }

/* The icon chip is the same material as the pills, at chip scale — a flat
   5%-black circle read as unfinished next to them. Note the light direction:
   shade top-left, specular bottom-right, matching .gv-glass exactly. A small
   raised control is conventionally lit from the top-left, but consistency with
   the surface it sits on matters more than the convention — one light source
   across the whole component is what stops it looking like assembled parts. */
.gv-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 50%;
  color: var(--ink-3);
  background: linear-gradient(158deg, #FFFFFF 0%, #F1F4F9 52%, #E7ECF4 100%);
  box-shadow:
    inset 0 0 0 .9px rgba(255, 255, 255, .95),   /* rim */
    inset  2px  2px 5px rgba(11, 18, 32, .06),   /* shade, top-left */
    inset -2px -2px 5px rgba(255, 255, 255, .95),/* specular, bottom-right */
    0 1px 2px rgba(11, 18, 32, .07),             /* contact */
    0 4px 10px -3px rgba(11, 18, 32, .13);       /* lift */
  transition:
    transform .28s var(--gv-mat),
    box-shadow .28s var(--gv-mat),
    color .28s var(--gv-mat);
}

/* A hairline white pick-out under the glyph. This is the "polished" part — it
   reads as the stroke catching the same light the chip does, and it costs one
   composited filter on a 15px icon. */
.gv-icon svg {
  width: 15px;
  height: 15px;
  display: block;
  filter: drop-shadow(0 1px 0 rgba(255, 255, 255, .85));
}

/* the chip answers the row, so the whole row feels like one control */
.gv-row:hover .gv-icon {
  transform: translateY(-1px);
  color: var(--accent);
  box-shadow:
    inset 0 0 0 .9px rgba(255, 255, 255, 1),
    inset  2px  2px 5px rgba(11, 18, 32, .05),
    inset -2px -2px 6px rgba(255, 255, 255, 1),
    0 1px 2px rgba(37, 99, 235, .10),
    0 6px 14px -3px rgba(37, 99, 235, .22);
}

.gv-nav [data-theme="dark"] .gv-icon {
  background: linear-gradient(158deg, rgba(255, 255, 255, .12) 0%, rgba(255, 255, 255, .05) 52%, rgba(255, 255, 255, .02) 100%);
  box-shadow:
    inset 0 0 0 .9px rgba(255, 255, 255, .14),
    inset  2px  2px 5px rgba(0, 0, 0, .45),
    inset -2px -2px 5px rgba(255, 255, 255, .09),
    0 1px 2px rgba(0, 0, 0, .40),
    0 4px 10px -3px rgba(0, 0, 0, .55);
}
.gv-nav [data-theme="dark"] .gv-icon svg {
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, .55));
}
.gv-nav [data-theme="dark"] .gv-row:hover .gv-icon {
  box-shadow:
    inset 0 0 0 .9px rgba(255, 255, 255, .22),
    inset  2px  2px 5px rgba(0, 0, 0, .40),
    inset -2px -2px 6px rgba(255, 255, 255, .14),
    0 6px 14px -3px rgba(79, 141, 255, .30);
}

.gv-row-name { font-size: 15px; font-weight: 450; }
.gv-row-note { font-size: 12.5px; color: var(--ink-3); }

/* ── the featured row ────────────────────────────────────────────────────
   One row carries emphasis. It works only because everything around it is
   neutral, so the treatment is deliberately restrained: a filled accent chip
   and a faint wash, not a border, a badge and a colour change all at once. */
.gv-row-lead {
  background: linear-gradient(100deg, rgba(37, 99, 235, .07), rgba(37, 99, 235, .03) 70%, transparent);
  box-shadow: inset 0 0 0 1px rgba(37, 99, 235, .10);
}
.gv-row-lead:hover { background: linear-gradient(100deg, rgba(37, 99, 235, .11), rgba(37, 99, 235, .05) 70%, transparent); }
.gv-row-lead .gv-row-name { font-weight: 550; }
.gv-row-lead .gv-row-note { color: var(--accent-ink, #1D4ED8); opacity: .85; }

/* The chip inverts: accent fill, white glyph. Its glyph pick-out has to flip
   too — a white drop-shadow under a white glyph is invisible, so it becomes a
   dark one, keeping the same "catching the light" read on a dark surface. */
.gv-row-lead .gv-icon {
  background: linear-gradient(158deg, #4F8DFF 0%, #2563EB 55%, #1D4ED8 100%);
  color: #fff;
  box-shadow:
    inset 0 0 0 .9px rgba(255, 255, 255, .35),
    inset  2px  2px 5px rgba(0, 0, 0, .10),
    inset -2px -2px 5px rgba(255, 255, 255, .30),
    0 1px 2px rgba(29, 78, 216, .30),
    0 5px 12px -3px rgba(37, 99, 235, .45);
}
.gv-row-lead .gv-icon svg { filter: drop-shadow(0 1px 0 rgba(0, 0, 0, .22)); }

/* the neutral-row hover tints the glyph to accent; on a filled accent chip that
   would repaint white-on-accent to accent-on-accent, so hold it white */
.gv-row-lead:hover .gv-icon {
  color: #fff;
  transform: translateY(-1px);
  box-shadow:
    inset 0 0 0 .9px rgba(255, 255, 255, .45),
    inset  2px  2px 5px rgba(0, 0, 0, .10),
    inset -2px -2px 6px rgba(255, 255, 255, .38),
    0 1px 2px rgba(29, 78, 216, .30),
    0 8px 18px -4px rgba(37, 99, 235, .55);
}

.gv-nav [data-theme="dark"] .gv-row-lead {
  background: linear-gradient(100deg, rgba(79, 141, 255, .18), rgba(79, 141, 255, .07) 70%, transparent);
  box-shadow: inset 0 0 0 1px rgba(79, 141, 255, .22);
}
.gv-nav [data-theme="dark"] .gv-row-lead .gv-row-note { color: #9DC0FF; opacity: 1; }

.gv-tile {
  display: grid;
  place-items: center;
  align-content: center;
  flex: 1;
  min-height: 104px;
  border-radius: 10px;
  position: relative;
  overflow: hidden;
}
.gv-tile-a { background: linear-gradient(150deg, #DCE9FF, #EEF3FB 55%, #E4EBFF); }
.gv-tile-b { background: linear-gradient(150deg, #F4F6FA, #E9EEF6); }
.gv-nav [data-theme="dark"] .gv-tile-a { background: linear-gradient(150deg, #1B2A47, #16203A 55%, #1E2C4C); }
.gv-nav [data-theme="dark"] .gv-tile-b { background: linear-gradient(150deg, #191F2B, #141922); }

/* the sheen that crosses the tiles as the panel opens */
.gv-tile::after {
  content: "";
  position: absolute;
  inset: -40%;
  background: linear-gradient(100deg, transparent 38%, rgba(255, 255, 255, .85) 50%, transparent 62%);
  transform: translateX(-60%);
}
.gv-menu.is-open .gv-tile::after {
  animation: gvSheen 1.6s var(--gv-mat) .18s forwards;
}
.gv-menu.is-open .gv-tile-b::after { animation-delay: .3s; }
@keyframes gvSheen { to { transform: translateX(60%); } }

.gv-tile-word {
  position: relative;
  font-family: var(--brand-face, "Orbitron", "Michroma", sans-serif);
  font-size: 15px;
  letter-spacing: .02em;
  color: var(--ink-2);
}
.gv-tile-sub {
  position: relative;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-top: 4px;
}

/* ==========================================================================
   THE COMPACT NAV
   The link pill can't survive a narrow viewport, but hiding it and stopping
   there leaves a phone with no navigation at all.
   ========================================================================== */

.gv-burger { display: none; background: none; cursor: pointer; }
.gv-burger svg { display: block; }

.gv-sheet {
  position: absolute;
  top: calc(100% + 10px);
  left: 26px;
  right: 26px;
  padding: 8px;
  border-radius: 18px;
  background: var(--gv-panel);
  -webkit-backdrop-filter: blur(9px) saturate(135%);
  backdrop-filter: blur(9px) saturate(135%);
  box-shadow:
    inset 0 0 0 1px var(--gv-ring),
    0 14px 40px rgba(11, 18, 32, .16),
    inset -7px -7px 18px var(--gv-spec);
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity .28s var(--gv-mat), transform .3s var(--gv-mat);
}
.gv-nav.is-open .gv-sheet { opacity: 1; transform: none; pointer-events: auto; }

.gv-sheet a {
  display: block;
  padding: 13px 14px;
  border-radius: 11px;
  font-size: 15px;
  color: var(--ink);
  text-decoration: none;
}
.gv-sheet a:hover { background: rgba(11, 18, 32, .05); }
.gv-nav [data-theme="dark"] .gv-sheet a:hover { background: rgba(255, 255, 255, .07); }

@media (min-width: 1081px) {
  .gv-sheet { display: none; }
}

@media (max-width: 1080px) {
  .gv-pill { display: none; }
  .gv-burger { display: flex; }
  .gv-nav.is-stuck .gv-inner { width: 100%; }      /* nothing to consolidate onto */
  .gv-nav.is-stuck .gv-word { max-width: 120px; opacity: 1; margin-left: 0; }
}

@media (max-width: 860px) {
  .gv-nav { padding: 10px 16px 0; }
  .gv-sheet { left: 16px; right: 16px; }
  .gv-col { width: min(78vw, 400px); }
  .gv-side { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .gv-nav *,
  .gv-nav { animation: none !important; transition-duration: .01ms !important; }
  .gv-row { opacity: 1; transform: none; }
}
