/* Shared page chrome: the glass nav, the footer, and long-form prose.
   Lifted out of index.html's inline <style> so a second page can use the same
   header and footer without duplicating them. index.html still carries its own
   landing-page-specific rules inline. */

/* Smooth in-page navigation. scroll-padding-top offsets the sticky glass nav
   so a targeted heading is not hidden underneath it. */
html { scroll-behavior: smooth; scroll-padding-top: 96px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* Uses `clip`, not `hidden`, so `position:sticky` on the nav keeps working
   (a scroll container on an ancestor would break it). */
body { background: var(--ae-bg); overflow-x: clip; }

/* Skip link: off-screen until it takes focus, then pinned over the nav.
   WCAG 2.4.1 - without it a keyboard user re-tabs the brand, the nav links
   and the CTA on every page load before reaching content. */
.skiplink {
  position: absolute; left: 50%; top: 0; transform: translate(-50%,-120%);
  z-index: 40; padding: 12px 20px;
  border-radius: 0 0 var(--ae-radius-card) var(--ae-radius-card);
  background: var(--ae-cta); color: #fff; font-weight: 600; text-decoration: none;
  transition: transform var(--ae-select);
}
.skiplink:focus-visible { transform: translate(-50%,0); }

/* Frosted glass top panel - a contained floating panel, no border.
   Two things make it read as a material rather than a blurred rectangle:
   a saturation boost (so colour passing beneath it stays alive instead of
   going grey), and a soft top highlight plus a low shadow, which together
   suggest a physical pane catching light. There is deliberately no border:
   the highlight does the edge definition that a hairline would, without a
   hard line to notice.

   The panel is inset from the viewport and rounded, matching the app's own
   Liquid Glass chrome. --nav-inset controls the breathing room. */
.navwrap {
  position: sticky; top: 0; z-index: 20;
  --nav-inset: 14px;
  --nav-max: 1080px;
  padding: var(--nav-inset) var(--ae-space-xl) 0;
  /* The sticky element must not clip, or the panel's shadow gets cut off. */
  pointer-events: none;
}
.navwrap > * { pointer-events: auto; }

/* The glass pane. Sized and centred to match .brandbar exactly, so the
   material sits under the content rather than spanning the viewport. */
.navglass {
  /* Own stacking context, above the document. Without an explicit z-index the
     pane sits at `auto` and a descendant of <main> that establishes its own
     backdrop root (.doc__tldr carries backdrop-filter) escapes this pane's
     filtered backdrop, punching an unblurred hole through the middle of the
     panel while the edges still frost correctly. */
  z-index: 1;
  position: absolute;
  top: var(--nav-inset); left: var(--ae-space-xl); right: var(--ae-space-xl);
  bottom: 0;
  max-width: var(--nav-max); margin: 0 auto;
  border-radius: var(--ae-radius-hero, 24px);
  pointer-events: none;
  /* Frosted, not merely blurred. Three things do the work:
     - a wide blur (50px), so shapes behind become fields of colour rather
       than readable text. 34px was not enough: body copy passing under the
       panel on the privacy page stayed legible and fought the nav labels.
       Blur radius has to exceed the x-height of the text behind it.
     - saturate, so that colour stays alive instead of going grey
     - a translucent white veil, which is what actually frosts the pane
     The veil is the important one. Blur alone left the hero subhead readable
     straight through the panel, which reads as clear glass and collided with
     the nav labels. */
  -webkit-backdrop-filter: blur(50px) saturate(1.7);
          backdrop-filter: blur(50px) saturate(1.7);
  background: linear-gradient(
    180deg,
    color-mix(in srgb, #fff 74%, transparent),
    color-mix(in srgb, #fff 66%, transparent) 52%,
    color-mix(in srgb, var(--ae-bg) 70%, transparent));
  /* Inner top highlight + inner bottom shade = a lit pane. The outer shadow
     is what lifts it off the page in place of a border. */
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff 62%, transparent),
    inset 0 -1px 0 color-mix(in srgb, var(--ae-purple-900, #0D0C22) 5%, transparent),
    0 1px 2px color-mix(in srgb, var(--ae-purple-900, #0D0C22) 4%, transparent),
    0 8px 28px color-mix(in srgb, var(--ae-purple-900, #0D0C22) 7%, transparent);
}

/* A very short blur ramp just below the panel, so the page does not resume
   at a hard line under the shadow. Three masked layers is enough at this
   scale (::before, one <i>, ::after); the seven-layer ramp was for the old
   full-bleed band. */
.navblur {
  position: absolute; left: 0; right: 0;
  top: 100%; height: 20px;
  pointer-events: none;
}
.navblur::before, .navblur::after, .navblur > i { content: ""; position: absolute; inset: 0; }
.navblur::before {
  z-index: 1;
  -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
  -webkit-mask: linear-gradient(#000, #0000 62%);
          mask: linear-gradient(#000, #0000 62%);
}
.navblur > i:nth-of-type(1) {
  z-index: 2;
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  -webkit-mask: linear-gradient(#0000 30%, #000 58%, #0000 88%);
          mask: linear-gradient(#0000 30%, #000 58%, #0000 88%);
}
.navblur::after {
  z-index: 3;
  -webkit-backdrop-filter: blur(1px); backdrop-filter: blur(1px);
  -webkit-mask: linear-gradient(#0000 55%, #000 82%, #0000);
          mask: linear-gradient(#0000 55%, #000 82%, #0000);
}

/* No backdrop-filter support: the glass would be fully transparent and the
   nav text would sit on raw hero gradient. Fall back to a solid-enough pane. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .navglass { background: color-mix(in srgb, var(--ae-bg) 93%, transparent); }
}

.brandbar {
  /* Above the glass pane and the ramp beneath it. At a lower z-index the
     layers paint over the wordmark and the CTA and blur the chrome itself. */
  position: relative; z-index: 10;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--ae-space-xl);       /* keeps the nav clear of the CTA */
  padding: 10px var(--ae-space-lg);
  max-width: var(--nav-max); margin: 0 auto;
}
.brand { display: flex; align-items: center; gap: 10px; font-weight: 600; letter-spacing: -.01em; }
.brand a { color: inherit; text-decoration: none; display: flex; align-items: center; gap: 10px; }
.brandmark { width: 30px; height: 30px; display: block; }
/* Full-strength text, not --ae-text-dim. Over the frosted pane a dark frame
   passing beneath can pull the surface to ~rgb(152,152,167), where the dim
   token measured 3.36:1 - under the 4.5:1 AA floor. At .82 alpha the links
   still read as secondary next to the wordmark but hold contrast over any
   backdrop the glass admits. */
.brandbar nav { display: flex; gap: var(--ae-space-lg); font-size: 15px;
                color: color-mix(in srgb, var(--ae-text) 82%, transparent);
                margin-left: auto; }
@media (max-width: 760px) { .brandbar nav { display: none } }
/* These links first appear at 761px, which on an iPad is still a touch
   target, so they carry the full 44px hit area. Padding rather than height
   so the row keeps its look; the gap shrinks to absorb it. */
.brandbar nav a { text-decoration: none; display: flex; align-items: center;
                  min-height: 44px; padding-inline: 6px; }
.brandbar nav a:hover { color: var(--ae-text); }

/* The nav CTA. Lives here, not in index.html's inline style, because the
   panel is on both pages - privacy.html was rendering it unstyled.
   min-height keeps the 44px touch target (WCAG 2.5.8) after the panel's
   padding was tightened; the pill's own padding alone left it at 38px. */
.nav-cta { padding: 9px 18px; font-size: 14px;
           min-height: 44px; display: inline-flex; align-items: center; }

footer { padding: clamp(26px,3vh,36px) 0; border-top: 1px solid var(--ae-hairline);
         color: var(--ae-text-dim); font-size: 14px; text-align: center; }
/* Footer links are standalone navigation rather than inline prose, so they
   carry the 44px hit area. inline-flex + padding keeps the separator dots on
   the same line instead of stacking the row. */
footer a { color: var(--ae-text-dim); display: inline-flex; align-items: center;
           min-height: 44px; padding-inline: 4px; }
footer a:hover { color: var(--ae-text); }

/* ---- Load-in reveal -------------------------------------------------------
   A short blur + rise as the page paints, staggered down the hero so the eye
   is led headline -> subhead -> buttons -> specs -> demo rather than having
   everything appear at once.

   `both` keeps the 0% state applied during the delay: without it a staggered
   element paints fully visible, then jumps back to hidden when its turn comes.

   Only above-the-fold chrome uses this. Sections further down already reveal
   on scroll via IntersectionObserver in demo.js, and animating those on load
   would fire them all while off-screen. */
@keyframes ae-rise {
  from { opacity: 0; filter: blur(10px); transform: translateY(10px); }
  to   { opacity: 1; filter: blur(0);    transform: translateY(0); }
}

.ae-rise {
  /* Composited properties only (opacity/filter/transform), so the stagger
     does not trigger layout on load. */
  will-change: opacity, filter, transform;
  animation: ae-rise .6s cubic-bezier(.2,.8,.2,1) both;
  animation-delay: var(--ae-rise-delay, 0s);
}
/* Drop the compositing hints once the reveal is done. `both` fill leaves the
   final keyframe applied forever, so without this every hero element keeps a
   promoted layer and a live blur filter for the whole session. The animation
   only ever plays once on load, so there is nothing to re-arm. */
.ae-rise.is-done { will-change: auto; filter: none; transform: none; }

/* Reduce Motion: land on the finished state immediately. The content must
   still be visible - dropping the animation without this would leave
   opacity:0 from the keyframe's `both` fill. */
@media (prefers-reduced-motion: reduce) {
  .ae-rise { animation: none; opacity: 1; filter: none; transform: none; }
}

/* The nav reveal is applied to .navwrap's CHILDREN, never to .navwrap itself.
   Two separate reasons, both load-bearing:

   1. `filter`/`transform` on .navwrap would create a containing block and
      break `position: sticky` while the animation runs.
   2. An *opacity* animation on .navwrap breaks `backdrop-filter` on the glass
      pane inside it. `animation-fill-mode: both` keeps the animation active
      forever, and an active opacity animation makes .navwrap a stacking
      context that isolates the backdrop root, so .navglass has nothing behind
      it to sample. Measured: content passing under the panel went from
      stddev 1.3 (properly frosted) to 14.4 (essentially unfiltered).

   Fading the children instead leaves .navwrap a plain sticky box, which is
   what both the sticky behaviour and the backdrop root need. */
@keyframes ae-fade { from { opacity: 0 } to { opacity: 1 } }
.ae-rise--nav > .navglass,
.ae-rise--nav > .navblur,
.ae-rise--nav > .brandbar { animation: ae-fade .5s ease-out both; }
@media (prefers-reduced-motion: reduce) {
  .ae-rise--nav > .navglass,
  .ae-rise--nav > .navblur,
  .ae-rise--nav > .brandbar { animation: none; opacity: 1; }
}
