/* ==========================================================================
   LiDAR Scanner — Frutiger Aero / Y2K skin.
   One stylesheet, no libraries, no image files: every bubble, gloss, bevel and
   pane of glass below is drawn with gradients.

   Lineage: Windows XP Luna → Vista/7 Aero glass, Mac OS X Aqua gel buttons and
   pinstripes, iOS 1-6 glossy tiles.
   ========================================================================== */

:root {
  /* --- the wallpaper ------------------------------------------------------ */
  --sky-top: #2e9fe0;
  --sky-mid: #8fd8f7;
  --sky-low: #d8f3ff;
  --grass-1: #a8e04a;
  --grass-2: #4f9c12;

  /* --- ink ---------------------------------------------------------------- */
  --ink: #08283c;
  --ink-soft: #2c5e7d;
  --ink-faint: #5b849c;

  /* --- chrome ------------------------------------------------------------- */
  --aqua: #1b8fd8;
  --aqua-deep: #0a5f9e;
  --lime: #2ea3e8;
  --lime-deep: #0a5f9e;
  --hot: #ff7a18;

  --glass-edge: rgba(255, 255, 255, .92);
  --glass-line: rgba(9, 70, 110, .28);

  --font-body: 'Segoe UI', Frutiger, 'Frutiger Linotype', Tahoma, Verdana, sans-serif;
  --font-display: 'Segoe UI Light', 'Segoe UI', Frutiger, Tahoma, sans-serif;

  --wrap: 1180px;
  --radius: 14px;
  --ease: cubic-bezier(.22, .61, .36, 1);
}

/* --------------------------------------------------------- reset + base -- */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  color: var(--ink);
  font: 400 16px/1.65 var(--font-body);
  background: var(--sky-mid);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* A column at least as tall as the window, so a short page still pins its
     footer to the bottom edge instead of leaving a strip of wallpaper below. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
body > .layout { flex: 1 0 auto; }

img { max-width: 100%; height: auto; display: block; }
a { color: var(--aqua-deep); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 {
  font-family: var(--font-display); font-weight: 300; line-height: 1.15;
  margin: 0 0 .5em; color: #06304a;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .9);
}
h1 { font-size: clamp(38px, 6.5vw, 68px); letter-spacing: -.5px; }
h2 { font-size: clamp(25px, 3.4vw, 36px); }
h3 { font-size: 19px; font-weight: 600; }
h4 { font-size: 16px; font-weight: 600; }
p { margin: 0 0 1em; }

code, kbd { font-family: Consolas, 'Cascadia Mono', 'Courier New', monospace; font-size: .9em; }
code {
  color: #0a4a72; background: rgba(255, 255, 255, .72);
  border: 1px solid rgba(255, 255, 255, .9); box-shadow: 0 1px 2px rgba(8, 60, 95, .18);
  padding: .1em .45em; border-radius: 5px;
}

.wrap { width: min(100% - 32px, var(--wrap)); margin-inline: auto; }
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.muted { color: var(--ink-soft); }
.small { font-size: 14px; }

.sr-only {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 100;
  background: var(--aqua-deep); color: #fff; padding: 10px 16px; border-radius: 0 0 10px 10px;
  transition: top .2s;
}
.skip-link:focus { top: 0; }

svg { width: 1em; height: 1em; vertical-align: -.13em; fill: none; }

:focus-visible { outline: 2px solid #fff; outline-offset: 2px; box-shadow: 0 0 0 4px var(--aqua); }

/* ================================================================ scene == */
/* The wallpaper. Still not a single image file — but flat gradients alone read
   as plastic, so every layer here is backed by procedural fractal noise: SVG
   feTurbulence rendered inline as a data URI. That is what makes the clouds
   billow, the water ripple and the grass hold a texture instead of a colour.
   Depth comes from stacking: haze, light, two cloud decks, a specular water
   band, two rows of grass at different focus, then grain and a vignette over
   the lot. */
.scene { position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; }

/* Closing vignette — the corners fall off, the way a real lens does. */
.scene::after {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(125% 105% at 50% 38%, rgba(255, 255, 255, 0) 52%, rgba(5, 45, 70, .26) 100%);
}

.scene .sky {
  position: absolute; inset: 0;
  /* The photograph first, the old painted sky underneath it as a fallback: if
     the file is missing the layer is simply skipped and the gradient shows. */
  background-image:
    url('../images/bg-city.jpg'),
    linear-gradient(180deg,
      #1d7fc4 0%, #2e9fe0 14%, #63c2ee 30%, var(--sky-mid) 46%,
      #c2ecfb 58%, var(--sky-low) 68%, #bfe9fb 84%, #8fd0ee 100%);
  background-size: cover, auto;
  background-position: center center, center;
  background-repeat: no-repeat, no-repeat;
}

/* Sun: hot core, warm halo and a faint lens ghost across the frame. */
.scene .sun {
  position: absolute; top: -16vh; right: -8vw; width: 66vw; height: 66vw; max-width: 940px; max-height: 940px;
  background:
    radial-gradient(circle, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, .92) 9%,
      rgba(255, 250, 214, .6) 19%, rgba(255, 238, 176, .3) 32%, rgba(255, 255, 255, 0) 62%);
  filter: blur(3px);
}
.scene .sun::after {
  content: ''; position: absolute; left: -70%; top: 78%; width: 26%; height: 26%; border-radius: 50%;
  background: radial-gradient(circle, rgba(190, 235, 255, .35), rgba(255, 255, 255, 0) 68%);
  filter: blur(6px);
}

/* God rays, fanned out from the sun and faded off with a mask. */
.scene .rays {
  position: absolute; inset: -25% -10% 42% -10%;
  background: repeating-conic-gradient(from 172deg at 84% -6%,
    rgba(255, 255, 255, .13) 0deg 1.1deg,
    rgba(255, 255, 255, 0) 1.1deg 4.6deg);
  filter: blur(7px);
  -webkit-mask-image: radial-gradient(62% 85% at 84% 0%, #000 0%, rgba(0, 0, 0, .5) 42%, transparent 74%);
          mask-image: radial-gradient(62% 85% at 84% 0%, #000 0%, rgba(0, 0, 0, .5) 42%, transparent 74%);
}

/* Two cloud decks. The far one is small, slow and hazy; the near one is larger,
   brighter and drifts faster, which is what sells the distance between them. */
.scene .clouds { display: none;
  position: absolute; left: -25%; right: -25%; top: 3%; height: 34%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='240'%3E%3Cfilter id='c' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.013 0.036' numOctaves='3' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 -2.6 0 0 0 1.32'/%3E%3CfeGaussianBlur stdDeviation='3'/%3E%3C/filter%3E%3Crect width='420' height='240' filter='url(%23c)'/%3E%3C/svg%3E");
  background-size: 62% 100%;
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 14%, #000 66%, transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0%, #000 14%, #000 66%, transparent 100%);
  opacity: .66;
  /* The drop shadow is what gives a flat white shape an underside. It is baked
     once, because the layer is moved with transform rather than by shifting the
     background — the difference between re-blurring every frame and not. */
  filter: blur(2px) drop-shadow(0 5px 7px rgba(70, 135, 180, .3));
  will-change: transform;
  animation: drift 240s linear infinite;
}
.scene .clouds-2 {
  top: 5%; height: 28%;
  background-size: 116% 100%;
  opacity: .92;
  filter: blur(.6px) drop-shadow(0 9px 14px rgba(64, 128, 175, .38));
  animation-duration: 150s; animation-direction: reverse;
}
@keyframes drift { to { transform: translate3d(22%, 0, 0); } }

/* Mist lying on the water. It used to be densest at the top of this band,
   which on the photograph is exactly where the skyline sits — so the city was
   the thing getting fogged. Now it starts at nothing up by the horizon and
   thickens as it comes down over the water, which is where haze actually
   collects. The ripple texture rides the bottom with it. */
.scene .horizon {
  position: absolute; left: 0; right: 0; bottom: 0; height: 46%;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='300'%3E%3Cfilter id='w' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.014 0.16' numOctaves='3' seed='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 -1.1 0 0 0 0.52'/%3E%3C/filter%3E%3Crect width='600' height='300' filter='url(%23w)'/%3E%3C/svg%3E"),
    linear-gradient(180deg,
      rgba(255, 255, 255, 0) 0%,
      rgba(255, 255, 255, .12) 34%,
      rgba(255, 255, 255, .3) 66%,
      rgba(236, 250, 255, .5) 100%);
  background-size: 100% 55%, auto;
  background-repeat: repeat-x, no-repeat;
  background-position: bottom, bottom;
}

/* Grass, in two rows at different depths. The far row is small and soft, the
   near row is tall and only just out of focus — that gap is the depth of
   field, and it is what stops the bottom edge reading as a flat green stripe. */
.scene .blades { display: none; position: absolute; left: 0; right: 0; bottom: 0; }
.scene .blades i {
  position: absolute; bottom: -2vh;
  transform-origin: bottom center;
  border-radius: 50% 50% 0 0 / 92% 92% 0 0;
}

/* Far row: hazier, desaturated by the same aerial perspective as the sky. */
.scene .blades.far { height: 15vh; filter: blur(2.4px); opacity: .75; }
.scene .blades.far i {
  width: 2.4vh; height: 15vh;
  background: linear-gradient(180deg, rgba(206, 246, 140, 0) 0%, rgba(146, 205, 74, .8) 52%, rgba(78, 146, 26, .92) 100%);
}
.scene .blades.far i:nth-child(1) { left: 4%; transform: rotate(-13deg) scaleY(1.15); }
.scene .blades.far i:nth-child(2) { left: 11%; transform: rotate(7deg) scaleY(.8); }
.scene .blades.far i:nth-child(3) { left: 26%; transform: rotate(-6deg) scaleY(1.3); }
.scene .blades.far i:nth-child(4) { left: 41%; transform: rotate(11deg) scaleY(.9); }
.scene .blades.far i:nth-child(5) { left: 58%; transform: rotate(-9deg) scaleY(1.2); }
.scene .blades.far i:nth-child(6) { left: 72%; transform: rotate(5deg) scaleY(.85); }
.scene .blades.far i:nth-child(7) { left: 84%; transform: rotate(-11deg) scaleY(1.25); }
.scene .blades.far i:nth-child(8) { left: 94%; transform: rotate(9deg) scaleY(.95); }

/* Near row: darker at the root, rim-lit along one edge by the sun. */
.scene .blades.near { height: 26vh; filter: blur(1.1px); }
.scene .blades.near i {
  width: 4.6vh; height: 26vh;
  background:
    linear-gradient(100deg, rgba(255, 255, 255, .5) 0%, rgba(255, 255, 255, 0) 26%),
    linear-gradient(180deg, rgba(196, 244, 118, 0) 0%, rgba(126, 196, 42, .95) 46%, rgba(46, 104, 10, .98) 100%);
}
.scene .blades.near i:nth-child(1) { left: -1%; transform: rotate(-16deg) scaleY(1.2); }
.scene .blades.near i:nth-child(2) { left: 19%; transform: rotate(9deg) scaleY(.9); }
.scene .blades.near i:nth-child(3) { left: 48%; transform: rotate(-7deg) scaleY(1.05); }
.scene .blades.near i:nth-child(4) { left: 68%; transform: rotate(13deg) scaleY(.82); }
.scene .blades.near i:nth-child(5) { left: 89%; transform: rotate(-10deg) scaleY(1.15); }

/* Film grain over everything: the single cheapest way to stop a page of
   gradients looking like plastic. */
.scene .grain {
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' seed='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.5 0 0 0 0 0.5 0 0 0 0 0.5 0 0 0 0.6 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: .05;
}

/* Rising bubbles: a highlight dot and a rim, nothing more. */
.scene .bubbles { position: absolute; inset: 0; }
.scene .bubbles b {
  position: absolute; bottom: -14vh; border-radius: 50%;
  background:
    radial-gradient(circle at 32% 28%, rgba(255, 255, 255, .95) 0%, rgba(255, 255, 255, .35) 18%, rgba(255, 255, 255, .06) 42%, rgba(255, 255, 255, 0) 60%),
    radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0) 58%, rgba(255, 255, 255, .5) 78%, rgba(190, 235, 255, .25) 100%);
  box-shadow: inset 0 -6px 12px rgba(120, 205, 255, .35);
  animation: rise linear infinite;
}
@keyframes rise {
  from { transform: translate3d(0, 0, 0) scale(.9); opacity: 0; }
  12%  { opacity: .85; }
  88%  { opacity: .7; }
  to   { transform: translate3d(6vw, -125vh, 0) scale(1.1); opacity: 0; }
}
.scene .bubbles b:nth-child(1) { left: 6%;  width: 46px; height: 46px; animation-duration: 26s; }
.scene .bubbles b:nth-child(2) { left: 17%; width: 22px; height: 22px; animation-duration: 19s; animation-delay: -11s; }
.scene .bubbles b:nth-child(3) { left: 29%; width: 64px; height: 64px; animation-duration: 34s; animation-delay: -7s; }
.scene .bubbles b:nth-child(4) { left: 38%; width: 16px; height: 16px; animation-duration: 16s; }
.scene .bubbles b:nth-child(5) { left: 52%; width: 38px; height: 38px; animation-duration: 23s; animation-delay: -14s; }
.scene .bubbles b:nth-child(6) { left: 63%; width: 28px; height: 28px; animation-duration: 21s; animation-delay: -5s; }
.scene .bubbles b:nth-child(7) { left: 74%; width: 54px; height: 54px; animation-duration: 30s; animation-delay: -18s; }
.scene .bubbles b:nth-child(8) { left: 86%; width: 20px; height: 20px; animation-duration: 17s; animation-delay: -9s; }
.scene .bubbles b:nth-child(9) { left: 93%; width: 34px; height: 34px; animation-duration: 27s; animation-delay: -21s; }

/* ================================================================ glass == */
/* The workhorse: an Aero pane. Bright rim, top-half shine, coloured shadow. */
.glass {
  position: relative;
  /* Opaque enough that a pane keeps its contrast even where the wallpaper
     behind it is at its brightest. */
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .93) 0%, rgba(255, 255, 255, .78) 49%,
                            rgba(226, 244, 255, .74) 51%, rgba(255, 255, 255, .86) 100%);
  border: 1px solid var(--glass-edge);
  border-radius: var(--radius);
  /* Three shadows, not one: a tight contact shadow that pins the pane to the
     page, a mid one for body, and a wide soft one for ambient occlusion. Then
     bounce light along the bottom inside edge, which is what makes a surface
     read as thick rather than printed on. */
  box-shadow:
    0 1px 2px rgba(6, 48, 78, .3),
    0 8px 16px rgba(8, 62, 100, .22),
    0 26px 50px rgba(8, 56, 92, .26),
    inset 0 1px 0 rgba(255, 255, 255, .98),
    inset 0 -14px 22px -14px rgba(255, 255, 255, .85),
    inset 0 0 0 1px rgba(120, 190, 230, .35);
}
/* The shine: a highlight over the top half with a curved lower edge. */
.glass::before {
  content: ''; position: absolute; left: 1px; right: 1px; top: 1px; height: 46%;
  border-radius: 13px 13px 46% 46% / 13px 13px 20px 20px;
  background: linear-gradient(180deg, rgba(255, 255, 255, .88) 0%, rgba(255, 255, 255, .34) 62%, rgba(255, 255, 255, .12) 100%);
  pointer-events: none;
}
/* A single sharp glint travelling down the top-left corner — the giveaway that
   this is a curved, polished surface catching the sun. */
.glass::after {
  content: ''; position: absolute; left: 0; top: 0; width: 52%; height: 62%;
  border-radius: var(--radius) 0 60% 0;
  background: linear-gradient(133deg, rgba(255, 255, 255, .55) 0%, rgba(255, 255, 255, .12) 38%, rgba(255, 255, 255, 0) 62%);
  pointer-events: none;
}
.glass > * { position: relative; z-index: 1; }

/* =============================================================== buttons == */
.btn {
  display: inline-flex; align-items: center; gap: .55em;
  position: relative; overflow: hidden;
  padding: 12px 26px; border-radius: 999px;
  font: 600 15px/1 var(--font-body); letter-spacing: .2px;
  color: #fff; text-shadow: 0 1px 1px rgba(0, 45, 75, .55);
  border: 1px solid var(--aqua-deep); cursor: pointer;
  background: linear-gradient(180deg, #86d8ff 0%, #2ea3e8 49%, #0f81cf 51%, #5cc4ff 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .95),
    inset 0 -8px 14px rgba(255, 255, 255, .28),
    0 1px 1px rgba(4, 40, 66, .35),
    0 5px 10px rgba(8, 70, 115, .3),
    0 14px 24px rgba(8, 60, 100, .22);
  transition: transform .15s var(--ease), filter .15s, box-shadow .15s;
}
/* Gel highlight, the Aqua trademark. Kept off the text's own band so the label
   stays crisp. */
.btn::before {
  content: ''; position: absolute; left: 2px; right: 2px; top: 1px; height: 42%;
  border-radius: 999px 999px 50% 50% / 999px 999px 14px 14px;
  background: linear-gradient(180deg, rgba(255, 255, 255, .8), rgba(255, 255, 255, .06));
  pointer-events: none;
}
.btn > * { position: relative; z-index: 1; }
.btn:hover { filter: brightness(1.08) saturate(1.1); transform: translateY(-1px); text-decoration: none; }
.btn:active { transform: translateY(1px); filter: brightness(.94); box-shadow: inset 0 2px 6px rgba(0, 50, 85, .45); }

/* The download button is the green one, the way installers always were. */
.btn-primary {
  border-color: var(--lime-deep);
  background: linear-gradient(180deg, #8ed9ff 0%, #2ba0e6 49%, #0d6fb4 51%, #5fc0f4 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .9),
    inset 0 -8px 14px rgba(255, 255, 255, .22),
    0 6px 14px rgba(8, 70, 115, .35);
  text-shadow: 0 1px 1px rgba(4, 40, 66, .55);
}

.btn-ghost {
  color: #0a4368; text-shadow: 0 1px 0 rgba(255, 255, 255, .9);
  border-color: rgba(255, 255, 255, .95);
  background: linear-gradient(180deg, rgba(255, 255, 255, .95) 0%, rgba(255, 255, 255, .6) 49%,
                                      rgba(224, 243, 255, .55) 51%, rgba(255, 255, 255, .82) 100%);
  box-shadow: inset 0 1px 0 #fff, 0 6px 14px rgba(8, 70, 115, .22);
}

/* ================================================================ header == */
/* There is no top bar: the wordmark heads the sidebar instead, as its own
   glossy plaque. */
.side-brand {
  display: flex; align-items: center; gap: 11px;
  padding: 12px 14px;
  font-family: var(--font-display); font-size: 22px; font-weight: 600; color: #06304a;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .95);
}
.side-brand em { font-style: normal; color: var(--lime-deep); }
.side-brand:hover { text-decoration: none; filter: brightness(1.03); }

.logo { display: inline-flex; align-items: center; gap: 10px; font-family: var(--font-display); font-size: 21px; font-weight: 600; }
.logo em { font-style: normal; color: var(--lime-deep); }
.logo:hover { text-decoration: none; }

/* ================================================================ layout == */
/* Sidebar on the left, content on the right — the shape every fan site of the
   era used. The sidebar rides along as you scroll. */
.layout { display: grid; gap: 20px; align-items: start; grid-template-columns: 1fr; padding-top: 20px; }
@media (min-width: 940px) {
  .layout { grid-template-columns: 250px minmax(0, 1fr); gap: 26px; }
  .sidebar { position: sticky; top: 18px; }
}
/* Sections inside the layout already sit in the constrained column, so their
   own .wrap must stop constraining them a second time. */
.layout .wrap { width: auto; margin-inline: 0; }

.sidebar { display: grid; gap: 16px; align-content: start; }

/* Stacked layout. With no top bar, navigation has to stay reachable, so the
   sidebar's blocks are unwrapped and reordered individually: wordmark and
   contents above the content, the download widget below it. */
@media (max-width: 939px) {
  .layout { padding-top: 14px; }
  .sidebar { display: contents; }
  .side-brand { order: 1; }
  .side-contents { order: 2; }
  .layout > main { order: 3; }
  .side-build { order: 4; }
  .side-nav { grid-template-columns: 1fr 1fr; }
}

.side-block { padding: 0; overflow: hidden; }
.side-block h2 {
  margin: 0; padding: 9px 14px; font-size: 15px; font-weight: 600;
  border-radius: 13px 13px 0 0;
  color: #fff; text-shadow: 0 1px 1px rgba(4, 40, 66, .5);
  background: linear-gradient(180deg, #8ed5ff 0%, #2f9fe0 47%, #1173b8 53%, #63c1f2 100%);
  border-bottom: 1px solid #0f5f96;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .75);
}

.side-nav { list-style: none; margin: 0; padding: 6px; display: grid; gap: 2px; }
.side-nav a {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border-radius: 8px;
  font-size: 14px; font-weight: 600; color: #14536f;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .8);
  border: 1px solid transparent; transition: all .15s;
}
.side-nav a:hover {
  text-decoration: none; color: #06304a;
  border-color: rgba(255, 255, 255, .95);
  background: linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(214, 240, 255, .72));
  box-shadow: inset 0 1px 0 #fff, 0 2px 5px rgba(8, 62, 100, .18);
}
/* Darker than the caption bars: white text sits in the top half of this
   gradient, so the top half is what has to carry the contrast. */
.side-nav a.active {
  color: #fff; text-shadow: 0 1px 1px rgba(20, 50, 3, .6);
  border-color: #35680d;
  background: linear-gradient(180deg, #63c1f2 0%, #1a8ed0 47%, #0a5f9e 53%, #38a9e0 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), 0 2px 5px rgba(8, 62, 100, .3);
}
.side-nav svg { width: 14px; height: 14px; flex: 0 0 auto; color: var(--lime-deep); }
.side-nav a:hover svg { color: var(--aqua-deep); }
.side-nav a.active svg { color: #fff; }

.side-body { padding: 14px; display: grid; gap: 12px; }
.side-facts { margin: 0; display: grid; gap: 5px; font-size: 13px; }
.side-facts > div { display: flex; justify-content: space-between; gap: 10px; }
.side-facts dt { color: var(--ink-faint); }
.side-facts dd { margin: 0; font-weight: 600; color: #06304a; }
.side-body .btn { width: 100%; justify-content: center; font-size: 13px; padding: 10px 14px; }
.side-note { margin: 0; font-size: 12px; color: var(--ink-faint); text-align: center; }

/* ================================================================== hero == */
.lidar-hero { padding: clamp(20px, 3vw, 34px) 0 clamp(26px, 4vw, 44px); }
.hero-grid { display: grid; gap: 34px; align-items: center; grid-template-columns: 1fr; }

/* The photograph is busy where the headline sits, so the copy carries its own
   patch of haze: a soft light bloom with no edges, bleeding well past the text.
   Enough to read against a skyline, invisible as a shape. */
.hero-copy { position: relative; }
.hero-copy::before {
  content: ''; position: absolute; inset: -40px -60px -30px -50px; z-index: -1;
  background: radial-gradient(72% 70% at 38% 50%,
    rgba(255, 255, 255, .88) 0%,
    rgba(255, 255, 255, .7) 42%,
    rgba(255, 255, 255, .32) 68%,
    rgba(255, 255, 255, 0) 85%);
  pointer-events: none;
}
/* Two columns only once the content column itself is wide enough for them. */
@media (min-width: 1240px) { .hero-grid { grid-template-columns: 1fr 1.02fr; } }

.eyebrow {
  display: inline-block; margin-bottom: 12px; padding: 5px 14px; border-radius: 999px;
  font-size: 12px; font-weight: 700; letter-spacing: 1.6px; text-transform: uppercase;
  color: #0a4368; text-shadow: 0 1px 0 rgba(255, 255, 255, .9);
  background: linear-gradient(180deg, rgba(255, 255, 255, .95), rgba(198, 234, 255, .65));
  border: 1px solid rgba(255, 255, 255, .95);
  box-shadow: inset 0 1px 0 #fff, 0 2px 6px rgba(8, 62, 100, .2);
}

/* Mirror reflection under the title — pure 2006. The copy is flipped in place
   (default transform origin) directly below the real text, and the gradient is
   authored upside down so that, once mirrored, it is strongest at the waterline
   and gone a third of the way down. */
.hero-title { position: relative; margin-bottom: .5em; }
.hero-title::after {
  content: attr(data-echo); position: absolute; left: 0; right: 0; top: 100%;
  transform: scaleY(-1);
  background: linear-gradient(180deg, rgba(6, 48, 74, 0) 74%, rgba(6, 48, 74, .2) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  text-shadow: none; pointer-events: none; user-select: none;
  filter: blur(.5px);   /* the water is never perfectly still */
}
.lead { color: #124b6b; font-size: 17px; margin-bottom: 24px; max-width: 56ch; text-shadow: 0 1px 0 rgba(255, 255, 255, .7); }

.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; }

.hero-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 0; margin: 26px 0 0; padding: 4px;
}
.hero-stats > div { padding: 10px 14px; text-align: center; border-right: 1px solid rgba(120, 190, 230, .4); }
.hero-stats > div:last-child { border-right: 0; }
.hero-stats dt { font-size: 11px; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase; color: var(--ink-faint); }
.hero-stats dd { margin: 4px 0 0; font-family: var(--font-display); font-size: 20px; font-weight: 600; color: #06304a; }

/* ---------------------------------------------------------- aero window -- */
.aero-window {
  padding: 6px; border-radius: 12px;
  background: linear-gradient(180deg, rgba(255, 255, 255, .8) 0%, rgba(206, 238, 255, .6) 50%, rgba(255, 255, 255, .7) 100%);
  border: 1px solid rgba(255, 255, 255, .95);
  box-shadow:
    0 26px 55px rgba(6, 55, 95, .45),
    inset 0 1px 0 rgba(255, 255, 255, .98),
    inset 0 0 0 1px rgba(120, 190, 230, .4);
}
.titlebar {
  display: flex; align-items: center; gap: 10px; height: 34px; padding: 0 6px 0 10px;
  border-radius: 8px 8px 0 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, .9) 0%, rgba(255, 255, 255, .45) 48%,
                                      rgba(198, 232, 252, .5) 52%, rgba(255, 255, 255, .7) 100%);
  border: 1px solid rgba(255, 255, 255, .8); border-bottom: 0;
  font-size: 13px; font-weight: 600; color: #0a4368; text-shadow: 0 1px 0 rgba(255, 255, 255, .95);
}
.titlebar .dot {
  width: 12px; height: 12px; border-radius: 50%; flex: 0 0 auto;
  background: radial-gradient(circle at 34% 28%, rgba(255, 255, 255, .95), rgba(255, 255, 255, 0) 55%),
              linear-gradient(180deg, #7fe0ff, #0a5f9e);
  border: 1px solid rgba(255, 255, 255, .8);
}
.titlebar .tb-name { flex: 1 1 auto; }
.win-buttons { display: flex; gap: 4px; }
.win-buttons i {
  width: 26px; height: 20px; border-radius: 4px; border: 1px solid rgba(255, 255, 255, .9);
  background: linear-gradient(180deg, rgba(255, 255, 255, .95), rgba(196, 230, 252, .7));
  box-shadow: inset 0 1px 0 #fff, 0 1px 3px rgba(8, 62, 100, .25);
  position: relative;
}
.win-buttons i::after {
  content: ''; position: absolute; left: 50%; top: 50%; width: 8px; height: 2px;
  transform: translate(-50%, -50%); background: #2a6c92;
}
.win-buttons i:nth-child(2)::after { height: 7px; border: 1px solid #2a6c92; background: none; width: 8px; }
.win-buttons i:nth-child(3) {
  background: linear-gradient(180deg, #ffb4a2, #e2452a 52%, #ff8a72);
  border-color: #a82914;
}
.win-buttons i:nth-child(3)::after { background: #fff; transform: translate(-50%, -50%) rotate(45deg); box-shadow: 0 0 0 0 #fff; }
.win-buttons i:nth-child(3)::before {
  content: ''; position: absolute; left: 50%; top: 50%; width: 8px; height: 2px; background: #fff;
  transform: translate(-50%, -50%) rotate(-45deg);
}

/* The scanner viewport: deliberately the one dark surface on the page. */
.window-body {
  position: relative; height: clamp(280px, 42vw, 400px); overflow: hidden;
  border: 1px solid rgba(10, 60, 95, .55); border-radius: 0 0 8px 8px;
  background: radial-gradient(120% 90% at 50% 0%, #0d2b3d 0%, #04121c 60%, #01070c 100%);
  box-shadow: inset 0 2px 12px rgba(0, 0, 0, .85);
  cursor: crosshair;
}
.window-body canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.scan-hint {
  position: absolute; left: 0; right: 0; bottom: 14px; margin: 0; text-align: center;
  font-size: 13px; color: #9fe4ff; text-shadow: 0 0 10px rgba(60, 190, 255, .8);
  animation: pulse 2.4s ease-in-out infinite; transition: opacity .5s;
}
.window-body.scanned .scan-hint { opacity: 0; }
@keyframes pulse { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }

/* ============================================================= sections == */
.section { padding: clamp(34px, 5vw, 60px) 0; }
.section-title { margin-bottom: 26px; }
.strip { padding: 10px 0 clamp(20px, 3vw, 34px); }

.lidar-item { display: flex; flex-wrap: wrap; align-items: center; gap: 22px; padding: 20px 24px; }
.lidar-item figure { margin: 0; text-align: center; }
.lidar-item figcaption { font-size: 12px; color: var(--ink-faint); margin-top: 8px; }
.lidar-item p { margin: 0; color: #124b6b; flex: 1 1 260px; }

/* Textures as glossy iOS-style tiles. */
.pixel {
  image-rendering: pixelated; width: 84px; height: 84px; padding: 6px;
  border-radius: 18px; border: 1px solid rgba(255, 255, 255, .95);
  background: linear-gradient(180deg, #ffffff 0%, #dceefb 48%, #bfe0f6 52%, #eaf7ff 100%);
  box-shadow: inset 0 1px 0 #fff, inset 0 -6px 10px rgba(255, 255, 255, .7), 0 6px 12px rgba(8, 62, 100, .3);
}

/* ---------------------------------------------------- panel caption bars -- */
/* The signature move of the era: every box wears a glossy green title strip
   pulled out to its own edges. --pad keeps the negative margins honest. */
.caption-bar {
  margin: calc(var(--pad) * -1) calc(var(--pad) * -1) 18px;
  padding: 10px var(--pad);
  border-radius: 13px 13px 0 0;
  color: #fff; font-weight: 600; text-shadow: 0 1px 1px rgba(4, 40, 66, .5);
  background: linear-gradient(180deg, #8ed5ff 0%, #2f9fe0 47%, #1173b8 53%, #63c1f2 100%);
  border-bottom: 1px solid #0f5f96;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .75), 0 2px 5px rgba(8, 62, 100, .22);
}

.feature-grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); }
.feature { --pad: 22px; padding: var(--pad); transition: transform .25s var(--ease), box-shadow .25s; }
.feature:hover {
  transform: translateY(-4px);
  box-shadow: 0 22px 40px rgba(8, 62, 100, .34), inset 0 1px 0 rgba(255, 255, 255, .98),
              inset 0 0 0 1px rgba(120, 190, 230, .5);
}
.feature h3 {
  margin: calc(var(--pad) * -1) calc(var(--pad) * -1) 16px;
  padding: 9px var(--pad); font-size: 17px;
  border-radius: 13px 13px 0 0;
  color: #fff; text-shadow: 0 1px 1px rgba(4, 40, 66, .5);
  background: linear-gradient(180deg, #8ed5ff 0%, #2f9fe0 47%, #1173b8 53%, #63c1f2 100%);
  border-bottom: 1px solid #0f5f96;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .75);
}
.feature p { color: #14536f; font-size: 15px; margin: 0; }

.lidar-split { display: grid; gap: 20px; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) { .lidar-split { grid-template-columns: 1.15fr 1fr; } }

.panel { --pad: 26px; padding: var(--pad); }
.panel h2 {
  font-size: 20px; font-weight: 600;
  margin: calc(var(--pad) * -1) calc(var(--pad) * -1) 18px;
  padding: 10px var(--pad);
  border-radius: 13px 13px 0 0;
  color: #fff; text-shadow: 0 1px 1px rgba(4, 40, 66, .5);
  background: linear-gradient(180deg, #8ed5ff 0%, #2f9fe0 47%, #1173b8 53%, #63c1f2 100%);
  border-bottom: 1px solid #0f5f96;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .75);
}
/* A second strip inside the same pane reads as a sub-section, so it gets all
   four corners rounded and a little air above it. */
.panel > h2:not(:first-child) { margin-top: 28px; border-radius: 10px; border-bottom-color: #0f5f96; }
.panel-actions { margin-top: 22px; }

.kbd-list { list-style: none; margin: 0 0 6px; padding: 0; display: grid; gap: 11px; }
.kbd-list li { display: flex; gap: 13px; align-items: baseline; color: #14536f; font-size: 15px; }
kbd {
  flex: 0 0 auto; min-width: 62px; text-align: center; color: #0a3f60; font-weight: 700;
  padding: 5px 9px; border-radius: 7px;
  background: linear-gradient(180deg, #ffffff 0%, #e6f4ff 50%, #cfe8fa 100%);
  border: 1px solid rgba(255, 255, 255, .95);
  box-shadow: inset 0 1px 0 #fff, 0 2px 0 rgba(120, 175, 205, .8), 0 4px 8px rgba(8, 62, 100, .28);
}

.steps { color: #14536f; padding-left: 1.25em; display: grid; gap: 7px; margin: 0 0 16px; font-size: 15px; }
.steps li::marker { color: var(--aqua-deep); font-weight: 700; }

.specs { margin: 0; display: grid; }
.specs > div {
  display: flex; justify-content: space-between; gap: 16px; padding: 9px 10px;
  border-bottom: 1px solid rgba(120, 190, 230, .4);
}
.specs > div:nth-child(odd) { background: rgba(255, 255, 255, .38); }   /* Aqua pinstripe rows */
.specs > div:last-child { border-bottom: 0; }
.specs dt { color: var(--ink-soft); font-size: 14px; flex: 0 0 auto; }
.specs dd { margin: 0; font-weight: 600; font-size: 14px; text-align: right; color: #06304a; min-width: 0; overflow-wrap: anywhere; }

/* ========================================================= version pages == */
.page-head { padding: clamp(34px, 6vw, 66px) 0 clamp(16px, 2vw, 26px); }
.page-head h1 { font-size: clamp(34px, 5.5vw, 56px); }

/* Same haze patch as the hero: the archive heading also sits over the skyline. */
.page-head .wrap { position: relative; }
.page-head .wrap::before {
  content: ''; position: absolute; inset: -30px -60px -20px -50px; z-index: -1;
  background: radial-gradient(78% 78% at 34% 50%,
    rgba(255, 255, 255, .9) 0%,
    rgba(255, 255, 255, .72) 42%,
    rgba(255, 255, 255, .34) 68%,
    rgba(255, 255, 255, 0) 86%);
  pointer-events: none;
}

.version-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 20px; }
.release { --pad: 26px; padding: var(--pad); }
.release.is-latest {
  border-color: rgba(255, 255, 255, .98);
  box-shadow:
    0 20px 42px rgba(8, 62, 100, .34),
    0 0 0 2px rgba(46, 163, 232, .55),
    inset 0 1px 0 rgba(255, 255, 255, .98);
}

.release-head {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px;
  margin: calc(var(--pad) * -1) calc(var(--pad) * -1) 16px;
  padding: 9px var(--pad);
  border-radius: 13px 13px 0 0;
  background: linear-gradient(180deg, #8ed5ff 0%, #2f9fe0 47%, #1173b8 53%, #63c1f2 100%);
  border-bottom: 1px solid #0f5f96;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .75);
}
.release-head h2 {
  display: flex; align-items: center; gap: 12px; margin: 0; font-size: 24px; font-weight: 600;
  color: #fff; text-shadow: 0 1px 1px rgba(4, 40, 66, .5);
}
.release-date { color: #e8f6ff; font-size: 14px; text-shadow: 0 1px 1px rgba(4, 40, 66, .5); }

/* The badge rides on the green caption bar, so it is light-on-green, not the
   other way round. */
.badge {
  font-size: 11px; font-weight: 700; letter-spacing: 1.4px; text-transform: uppercase;
  padding: 4px 12px; border-radius: 999px;
  border: 1px solid #12699f; text-shadow: 0 1px 0 rgba(255, 255, 255, .9);
  box-shadow: inset 0 1px 0 #fff, 0 2px 5px rgba(8, 62, 100, .35);
}
.badge-latest { color: #0a4a75; background: linear-gradient(180deg, #ffffff, #dcf1ff 49%, #b6e2fb 51%, #f2fbff); }
.badge-legacy {
  color: #3d5a68; border-color: #7f9aa8;
  background: linear-gradient(180deg, #ffffff, #e4edf2 49%, #cfdde6 51%, #f7fbfd);
}

.release-summary { color: #124b6b; margin: 12px 0 18px; }
.release-specs { margin-bottom: 18px; border-top: 1px solid rgba(120, 190, 230, .4); border-radius: 8px; overflow: hidden; }

.changes-title { color: #06304a; font-size: 16px; margin-bottom: 8px; }
.changes { margin: 0 0 20px; padding-left: 1.25em; color: #14536f; font-size: 15px; display: grid; gap: 5px; }
.changes li::marker { color: var(--lime-deep); }

.release-actions { display: flex; flex-wrap: wrap; gap: 12px; }
.release-actions .btn { font-size: 14px; padding: 10px 20px; }

.archive-note { margin: 22px 0 0; font-size: 15px; text-align: center; color: #14536f; text-shadow: 0 1px 0 rgba(255, 255, 255, .8); }

.notes { margin: 0; padding-left: 1.25em; color: #14536f; display: grid; gap: 9px; font-size: 15px; }
.notes li::marker { color: var(--aqua-deep); }

/* ================================================================ footer == */
/* margin-top:auto pushes it to the bottom on short pages; the padding that used
   to sit under it is gone, so the pane meets the bottom edge with no gap. */
.site-footer { flex: 0 0 auto; margin-top: auto; padding: clamp(30px, 5vw, 60px) 0 0; }
.footer-glass { padding: 32px 28px 24px; border-radius: 16px 16px 0 0; }
.footer-grid { display: grid; gap: 28px; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.site-footer h4 { color: #06304a; margin-bottom: 12px; }
/* The wordmark is white up in the green bar; down here it sits on glass. */
.site-footer .logo {
  margin-bottom: 10px; color: #0a4a75; text-shadow: 0 1px 0 rgba(255, 255, 255, .95);
}
.site-footer .logo em { color: var(--aqua-deep); }
.site-footer .muted { color: #2c5e7d; }
.plain, .social { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.plain a { color: #14536f; font-size: 15px; font-weight: 500; }
.plain a:hover { color: var(--aqua-deep); }

/* Dock-style glossy icon buttons. */
.social { grid-auto-flow: column; justify-content: start; gap: 8px; }
.social a {
  display: grid; place-items: center; width: 40px; height: 40px; font-size: 18px;
  color: #0a4368; border-radius: 11px; border: 1px solid rgba(255, 255, 255, .95);
  background: linear-gradient(180deg, #ffffff 0%, #ddeffc 48%, #bcdff5 52%, #eaf7ff 100%);
  box-shadow: inset 0 1px 0 #fff, 0 4px 9px rgba(8, 62, 100, .3);
  transition: transform .18s var(--ease), filter .18s;
}
.social a:hover { transform: translateY(-3px) scale(1.06); filter: brightness(1.06); }

.footer-bottom {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px;
  margin-top: 26px; padding-top: 18px; border-top: 1px solid rgba(120, 190, 230, .5);
  color: var(--ink-soft); font-size: 13px;
}
.footer-bottom p { margin: 0; }

/* =============================================================== reveals == */
.reveal { opacity: 0; transform: translateY(20px); transition: opacity .55s var(--ease), transform .55s var(--ease); }
.reveal.is-visible { opacity: 1; transform: none; }

/* ============================================================ responsive == */
@media (max-width: 520px) {
  .footer-bottom { flex-direction: column; }
  .panel, .lidar-item, .release, .footer-glass { --pad: 18px; padding: var(--pad); }
  .specs > div { flex-direction: column; gap: 2px; }
  .specs dd { text-align: left; }
  .kbd-list li { flex-direction: column; gap: 6px; }
  .release-actions .btn { width: 100%; justify-content: center; }
  .hero-stats > div { border-right: 0; border-bottom: 1px solid rgba(120, 190, 230, .4); }
  .hero-stats > div:last-child { border-bottom: 0; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .reveal { opacity: 1; transform: none; }
  .scene .bubbles { display: none; }
}

/* ====================================================== guestbook bubbles = */
/* Signatures from the blog's guestbook, shown as speech bubbles — the shape
   every messenger of that decade used, tail and all. */
.gb-bubble .side-body { display: grid; gap: 10px; }
.bubble-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }

.bubble {
  position: relative;
  padding: 9px 11px 8px;
  border-radius: 12px;
  background: linear-gradient(180deg, #ffffff 0%, #eaf6ff 52%, #dcefff 100%);
  border: 1px solid rgba(255, 255, 255, .95);
  box-shadow:
    0 1px 2px rgba(6, 48, 78, .22),
    0 6px 12px rgba(8, 62, 100, .16),
    inset 0 1px 0 #fff;
}
/* The tail, drawn as a rotated square tucked under the lower-left corner. */
.bubble::after {
  content: ''; position: absolute; left: 16px; bottom: -5px;
  width: 12px; height: 12px;
  background: #dcefff;
  border-right: 1px solid rgba(255, 255, 255, .95);
  border-bottom: 1px solid rgba(255, 255, 255, .95);
  transform: rotate(45deg);
  box-shadow: 2px 2px 3px rgba(6, 48, 78, .12);
}

.bubble-text {
  margin: 0 0 5px; font-size: 13px; line-height: 1.45; color: #123c58;
  overflow-wrap: anywhere;
}
.bubble-who {
  margin: 0; display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; font-size: 11px;
}
.bubble-name { font-weight: 600; color: var(--aqua-deep); overflow-wrap: anywhere; }
.bubble-when { color: var(--ink-faint); white-space: nowrap; font-size: 10px; }

/* Shown when the guestbook is empty or out of reach — the block itself stays,
   so the invitation to sign never disappears. */
.bubble-note {
  margin: 0; font-size: 12px; line-height: 1.45; color: var(--ink-soft);
  text-align: center;
}
.gb-bubble .btn { width: 100%; justify-content: center; font-size: 13px; padding: 9px 14px; }
.bubble-more { font-size: 12px; }

/* The `hidden` attribute only carries a browser default of display:none, which
   any author rule outranks — and .btn above sets a display of its own, so the
   empty "more" button would sit there as a blank pill. Restated here, after
   the rules it has to beat, for every hidden thing in the block. */
.gb-bubble [hidden] { display: none; }
