/* Hero product animation — a real desktop with two Petal remote windows,
   the meeting pill, and live remote pointers. Moving the mouse across the
   stage wipes between a macOS desktop and a Windows desktop showing the
   SAME scene (--reveal-x, set by the inline script in index.html). Scales
   fluidly via container query units so nothing ever truncates.

   Window-chrome values are ground-truthed against the REAL app: the
   RemoteWindowHeader.svelte component rendered live in apps/desktop's
   /dev/components harness (computed styles + screenshot, 2026-07-31):
   - header: exactly 44px tall, padding 0 14px 0 16px, left-cluster gap 14px,
     right-cluster gap 8px; solid identity-color bg, dark per-identity ink;
     border-bottom = ink 22%, inset top highlight = ink 18%.
   - traffic dots: 12px, gap 8px, inset 0 0 0 .5px rgba(0,0,0,.25); close is
     disabled on a remote window -> opacity .56 + saturate(.35).
   - title: 14px Albert Sans 600; " by <owner>" at weight 500, ink 62%.
   - right cluster: icon-only collapse chevrons (15px, ink 82%) + the
     View/Control/Draw mode switcher (.mode-switcher: 30px track, 3px
     padding, radius 9, bg ink 8% + 1px border ink 14%; segments 24px tall,
     radius 6; active segment bg ink 16% + 1px border ink 18% + shadow
     0 1px 2px black/.35 and inset 0 1px 0 white/.07; inactive icon ink 58%,
     active ink ~98%). At hero scale the segments are icon-only (the real
     86px labeled segments can't fit a ~294px-wide mini window), but the
     segmented-pill shape + active treatment are verbatim.
   - window shell: 4px identity border, 10px radius (compositor.rs).
   Scale: the mini desktop renders windows at ~0.71x of an implied ~415px
   real window, so 1 real px = 0.111cqw. All chrome below uses that ratio.

   Pill / Avatar / ControlButton / Pointer / NamePill values are verbatim
   from Pill.svelte, Avatar.svelte, ControlButton.svelte, Pointer.svelte,
   NamePill.svelte (see each section). Identity palette from tokens.css /
   identityColor.ts: --id-blue #6e8bff (ink #081129), --id-plum #f06cc9
   (ink #2b071b). */

/* Registered so the wipe boundary transitions smoothly between updates. */
@property --reveal-x {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 104%;
}

.demo-stage {
  --id-blue: #6e8bff;
  --ink-blue: #081129;
  --id-plum: #f06cc9;
  --ink-plum: #2b071b;
  --reveal-x: 104%;
  position: relative;
  width: 100%;
  margin: 34px auto 0;
  aspect-ratio: 1160 / 660;
  container-type: inline-size;
  border-radius: 20px;
  overflow: hidden;
  background: #0b0d12;
  box-shadow:
    0 50px 90px -30px rgba(20, 15, 25, 0.35),
    0 14px 34px -16px rgba(20, 15, 25, 0.28);
  border: 1px solid rgba(20, 18, 28, 0.16);
  transition: --reveal-x 110ms linear;
}

.demo-stage:focus-visible {
  outline: 2px solid var(--id-blue);
  outline-offset: 3px;
}

@media (max-width: 720px) {
  .demo-stage { margin-top: 22px; }
}

/* ---- OS layers ------------------------------------------------------ */

/* Each OS layer is its own stacking context (isolation + z-index) so the
   window/pill/pointer z-indexes inside one layer can never paint above the
   other layer — the win layer's clip-path already made IT atomic, which
   otherwise let the mac layer's z-indexed children bleed over it. */
.demo-os {
  position: absolute;
  inset: 0;
  isolation: isolate;
}

.demo-os--mac { z-index: 1; }
.demo-os--win { z-index: 2; }

/* macOS: original abstract aurora gradient in the style of recent macOS
   default wallpapers (not a reproduction of any Apple artwork). */
.demo-os--mac {
  background:
    radial-gradient(80% 95% at 84% -4%, rgba(255, 158, 96, 0.85), transparent 58%),
    radial-gradient(95% 115% at 2% 6%, rgba(126, 84, 214, 0.9), transparent 62%),
    radial-gradient(120% 95% at 66% 106%, rgba(226, 85, 130, 0.85), transparent 56%),
    linear-gradient(158deg, #38286f 0%, #64399c 46%, #c25a78 100%);
}

/* Windows: original abstract blue "bloom" gradient in the spirit of the
   Windows 11 default (not a reproduction). Clipped to the right of the
   wipe boundary; the boundary is slanted ~6deg for a nicer wipe. */
.demo-os--win {
  background:
    radial-gradient(62% 72% at 52% 58%, rgba(96, 160, 235, 0.95), transparent 62%),
    radial-gradient(42% 52% at 64% 40%, rgba(148, 216, 246, 0.8), transparent 58%),
    radial-gradient(85% 85% at 28% 84%, rgba(38, 88, 168, 0.65), transparent 62%),
    linear-gradient(165deg, #0c3068 0%, #0a1d42 60%, #061026 100%);
  clip-path: polygon(
    calc(var(--reveal-x) + 3%) -2%,
    120% -2%,
    120% 102%,
    calc(var(--reveal-x) - 3%) 102%
  );
}

/* Glowing seam at the wipe boundary (matches the clip slant). */
.demo-reveal-line {
  position: absolute;
  top: -4%;
  bottom: -4%;
  left: var(--reveal-x);
  width: 0.35cqw;
  min-width: 2px;
  transform: translateX(-50%) skewX(-6deg);
  background: rgba(255, 255, 255, 0.85);
  box-shadow: 0 0 1.4cqw rgba(255, 255, 255, 0.55);
  pointer-events: none;
  z-index: 3;
}

/* ---- macOS menu bar -------------------------------------------------- */

.demo-menubar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  /* Floored at 19px so the 19px top corner radii below never get clamped
     (border-radius shrinks when it exceeds the box height). */
  height: max(2.7cqw, 19px);
  /* WebKit bug (confirmed in Safari 2026-07-31 with corner screenshots): a
     backdrop-filter element ignores the ancestor's border-radius +
     overflow:hidden clip and paints square corners outside the stage's
     20px rounding. Chromium clips fine. Fix: round this element's own top
     corners to the stage's inner radius (20px stage radius - 1px border),
     which every engine honors for the element's own backdrop. */
  border-radius: 19px 19px 0 0;
  display: flex;
  align-items: center;
  gap: 1.5cqw;
  /* Floor the side padding so the clock never rides into the stage's
     fixed 20px corner rounding at narrow widths. */
  padding: 0 max(1.5cqw, 14px);
  font-family: -apple-system, BlinkMacSystemFont, var(--font-ui);
  font-size: 1.2cqw;
  font-weight: 500;
  line-height: 1;
  color: rgba(22, 22, 30, 0.92);
  background: rgba(252, 252, 255, 0.44);
  -webkit-backdrop-filter: blur(14px) saturate(1.7);
  backdrop-filter: blur(14px) saturate(1.7);
  white-space: nowrap;
}

.demo-menubar__apple {
  width: 1.5cqw;
  height: 1.5cqw;
  min-width: 7px;
  min-height: 7px;
  flex-shrink: 0;
  display: block;
}

.demo-menubar__app { font-weight: 700; }

.demo-menubar__spacer { flex: 1; }

.demo-menubar__status {
  display: flex;
  align-items: center;
  gap: 1.3cqw;
}

.demo-menubar__status svg {
  width: 1.6cqw;
  height: 1.6cqw;
  min-width: 8px;
  min-height: 8px;
  display: block;
}

.demo-menubar__status .demo-menubar__batt {
  width: 2.5cqw;
  height: 1.25cqw;
  min-width: 12px;
  min-height: 6px;
}

/* ---- Windows taskbar (Win11: centered icons + right tray clock) ------ */

.demo-taskbar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  /* Same WebKit backdrop-filter corner-bleed fix as .demo-menubar: own
     bottom radii (stage 20px - 1px border) + a height floor so the radii
     never clamp. */
  height: max(5.2cqw, 19px);
  border-radius: 0 0 19px 19px;
  display: flex;
  align-items: center;
  padding: 0 max(1.6cqw, 14px); /* same corner-radius floor as the menubar */
  background: rgba(246, 249, 253, 0.78);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  backdrop-filter: blur(16px) saturate(1.4);
  border-top: 1px solid rgba(255, 255, 255, 0.5);
}

.demo-taskbar__center {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 1.7cqw;
}

.demo-task-icon {
  position: relative;
  width: 2.6cqw;
  height: 2.6cqw;
  min-width: 12px;
  min-height: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.demo-task-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

.demo-task-icon--start { color: #0f6cc6; }
.demo-task-icon--search { color: rgba(28, 32, 44, 0.78); }
.demo-task-icon--petal { color: #d6447f; }

/* running-app indicator dash under the Petal icon */
.demo-task-icon--active::after {
  content: '';
  position: absolute;
  bottom: -0.75cqw;
  left: 50%;
  transform: translateX(-50%);
  width: 1.1cqw;
  height: 0.28cqw;
  min-height: 2px;
  border-radius: 99px;
  background: rgba(28, 32, 44, 0.55);
}

.demo-taskbar__clock {
  margin-left: auto;
  font-family: var(--font-ui);
  font-size: 1.05cqw;
  font-weight: 500;
  line-height: 1.45;
  text-align: right;
  color: rgba(22, 26, 36, 0.9);
  white-space: nowrap;
}

/* ---- Remote windows --------------------------------------------------
   Real anatomy (compositor.rs + RemoteWindowHeader.svelte): borderless
   native panel, 4px identity border at 10px radius, 44px header filled
   SOLID with the owner's identity color, dark per-identity ink. All
   values below at 1 real px = 0.111cqw. */

.demo-window {
  position: absolute;
  border: 0.44cqw solid;
  border-radius: 1.11cqw;
  overflow: hidden;
  /* Forces its own compositing layer so the browser rounds the border's
     outer curve and the overflow:hidden clip to the SAME sub-pixel grid.
     Without this, cqw's fractional computed px (e.g. a 3.5px border on a
     7.35px radius) can round independently for each, leaving a hairline
     seam of the desktop gradient right where the curve meets the flat top
     edge — directly above the header. Doesn't touch `transform` itself, so
     it can't fight the demo-bob keyframes below. */
  backface-visibility: hidden;
  box-shadow: 0 2.6cqw 4.4cqw -1.8cqw rgba(0, 0, 0, 0.6);
  /* Regional backdrop matching the children: identity color behind the
     header strip, editor-dark below. Any antialiased seam pixel between
     the border's inner curve and a child's edge then shows the matching
     color instead of the desktop gradient (the top-corner sliver bug). */
  background: linear-gradient(
    180deg,
    var(--hdr-bg) 0,
    var(--hdr-bg) 4.3cqw,
    #101216 4.3cqw,
    #101216 100%
  );
  animation: demo-bob 7s ease-in-out infinite;
}

/* Windows re-chrome: slightly tighter ~8px corners. */
.demo-os--win .demo-window {
  border-radius: 0.89cqw;
}

/* Header top radii must track the win layer's tighter outer radius
   (0.89cqw - 0.44cqw border). */
.demo-os--win .demo-window__header {
  border-radius: 0.45cqw 0.45cqw 0 0;
}

.demo-window--a {
  left: 4%;
  top: 15%;
  width: 52%;
  height: 44%;
  border-color: var(--id-blue);
  --hdr-bg: var(--id-blue);
  --hdr-ink: var(--ink-blue);
  z-index: 2;
  animation-delay: 0s;
}

.demo-window--b {
  left: 38%;
  top: 37%;
  width: 56%;
  height: 47%;
  border-color: var(--id-plum);
  --hdr-bg: var(--id-plum);
  --hdr-ink: var(--ink-plum);
  z-index: 4;
  animation-delay: -3.4s;
}

@keyframes demo-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-0.8%); }
}

/* Header: was 44px (4.9cqw); trimmed ~5px more compact per request ->
   4.3cqw (~39px). Padding 0 14px 0 16px -> 0 1.55cqw 0 1.78cqw unchanged. */
.demo-window__header {
  height: 4.3cqw;
  /* Explicit top radii = the parent's INNER corner curve (outer 1.11cqw
     radius minus the 0.44cqw border). Relying on the parent's
     overflow:hidden inner-curve clip alone leaves the header's square
     corner meeting the border's rounded inner edge with an antialiased
     seam — a sliver of desktop showed through at the top corners (user
     screenshot, 2026-07-31). The header must curve itself. */
  border-radius: 0.67cqw 0.67cqw 0 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.78cqw;
  padding: 0 1.55cqw 0 1.78cqw;
  background: var(--hdr-bg);
  color: var(--hdr-ink);
  border-bottom: 1px solid color-mix(in srgb, var(--hdr-ink) 22%, transparent);
  /* Drag handle: the whole header (minus its controls) drags the window,
     like a real title bar. touch-action:none so touch drags emit
     pointermoves; user-select off so a drag never selects the title. */
  cursor: grab;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  /* The real header's `inset 0 1px 0` ink-18% top highlight is intentionally
     DROPPED at hero scale: against the thick 0.44cqw identity border it
     renders as a distinct darker ring just inside the border (measured
     rgb(92,117,216) vs border rgb(110,139,255)) — an ugly double-outline.
     One clean identity-color border instead. */
}

.demo-window__header:active { cursor: grabbing; }

/* left cluster gap: 14px -> 1.55cqw */
.demo-window__header-left {
  display: flex;
  align-items: center;
  gap: 1.55cqw;
  min-width: 0;
}

/* Traffic dots: 12px -> 1.33cqw, gap 8px -> 0.89cqw, inset hairline;
   close disabled on a remote window -> dimmed + desaturated. */
.demo-traffic {
  display: flex;
  gap: 0.89cqw;
  flex-shrink: 0;
}

.demo-traffic span {
  width: 1.33cqw;
  height: 1.33cqw;
  min-width: 5px;
  min-height: 5px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.25);
}

.demo-traffic .t-red {
  background: #ff5f57;
  opacity: 0.56;
  filter: saturate(0.35);
}
.demo-traffic .t-yellow { background: #febc2e; }
.demo-traffic .t-green { background: #28c840; }

/* "<source> by <owner>" — 14px -> 1.55cqw, Albert Sans 600; owner at
   weight 500, ink 62%. Fits fully at every width (never ellipsizes). */
.demo-window__title {
  font-family: var(--font-ui);
  font-size: 1.55cqw;
  font-weight: 600;
  line-height: 1;
  color: var(--hdr-ink);
  white-space: nowrap;
  min-width: 0;
}

.demo-window__title span {
  font-weight: 500;
  color: color-mix(in srgb, var(--hdr-ink) 62%, transparent);
}

/* Right cluster, compact state (real component <=470px window width):
   icon-only collapse chevrons (15px) + overflow dots (16px), transparent
   buttons, ink at 82%, cluster gap 8px -> 0.89cqw (the icon-only buttons
   are 40px wide in the app; here the icons carry small padding instead). */
.demo-window__actions {
  display: flex;
  align-items: center;
  gap: 1.33cqw;
  flex-shrink: 0;
  color: color-mix(in srgb, var(--hdr-ink) 82%, transparent);
}

.demo-window__actions svg {
  display: block;
  flex-shrink: 0;
}

/* The View / Control / Draw mode switcher — Petal's signature header
   control, real values from RemoteWindowHeader.svelte's .mode-switcher /
   .active-indicator / .mode-segment (see the file-top comment), rendered
   icon-only at hero scale. Pure cqw (no big px floors) so the header's
   proportions hold at every stage width. */
.demo-mode {
  display: flex;
  align-items: center;
  padding: 0.33cqw;                      /* 3px */
  border-radius: 1cqw;                   /* 9px */
  background: color-mix(in srgb, var(--hdr-ink) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--hdr-ink) 14%, transparent);
  flex-shrink: 0;
}

.demo-mode__seg {
  width: 2.9cqw;
  height: 2.66cqw;                       /* 24px */
  min-width: 10px;
  min-height: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 0.67cqw;                /* 6px */
  color: color-mix(in srgb, var(--hdr-ink) 58%, transparent);
}

.demo-mode__seg--active {
  background: color-mix(in srgb, var(--hdr-ink) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--hdr-ink) 18%, transparent);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.07);
  color: var(--hdr-ink);
}

.demo-mode__seg svg {
  width: 1.66cqw;                        /* 15px icons */
  height: 1.66cqw;
  min-width: 7px;
  min-height: 7px;
  display: block;
}

/* Windows caption cluster (min / max / close, top-RIGHT). Close is
   dimmed to mirror the disabled close on the macOS chrome. */
.demo-caption {
  display: flex;
  align-items: center;
  gap: 1.33cqw;
  margin-left: 0.67cqw;
  padding-left: 1.33cqw;
  border-left: 1px solid color-mix(in srgb, var(--hdr-ink) 22%, transparent);
}

.demo-caption svg {
  width: 1.44cqw;
  height: 1.44cqw;
  min-width: 7px;
  min-height: 7px;
}

.demo-caption .demo-cap-close { opacity: 0.45; }

/* ---- Code-editor window content -------------------------------------- */

.demo-window__body {
  position: relative;
  height: calc(100% - 4.3cqw);
  /* Bottom mirror of the header's explicit top radii (same seam class). */
  border-radius: 0 0 0.67cqw 0.67cqw;
}

.demo-os--win .demo-window__body {
  border-radius: 0 0 0.45cqw 0.45cqw;
}

.demo-code {
  text-align: left; /* .stage centers text; pre lines must not be centered */
  background: #101216;
  padding: 0.9cqw 1.2cqw;
  overflow: hidden;
  font-family: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 1.22cqw;
  line-height: 1.8;
  color: #ccd3de;
}

.demo-code pre {
  margin: 0;
  white-space: pre;
  font: inherit;
}

.demo-code .ln {
  display: inline-block;
  width: 2ch;
  margin-right: 1.4ch;
  text-align: right;
  color: rgba(255, 255, 255, 0.22);
}

/* Dark-editor syntax palette */
.demo-code .k { color: #cf8ef5; }              /* keywords */
.demo-code .f { color: #7cb3ff; }              /* fn / method names */
.demo-code .t { color: #e8c07b; }              /* types */
.demo-code .s { color: #9ad38a; }              /* strings */
.demo-code .n { color: #d19a66; }              /* literals */
.demo-code .p { color: #8b93a3; }              /* punctuation */
.demo-code .c { color: #5f6b7a; font-style: italic; }  /* comments */

/* ---- Chrome-style browser window content ------------------------------
   Theo shares a browser showing the Petal docs. Recognizably "a browser"
   through the chrome alone — dark-theme tab strip with a rounded active
   tab, back/forward/reload, a pill omnibox with a padlock, the vertical
   three-dot menu — no third-party logos or wordmarks anywhere. */

.demo-browser {
  display: flex;
  flex-direction: column;
  background: #202124;                    /* tab-strip / frame */
  text-align: left;
  overflow: hidden;
}

.demo-browser__tabs {
  display: flex;
  align-items: flex-end;
  gap: 0.22cqw;
  height: 3.4cqw;
  min-height: 16px;
  padding: 0.55cqw 0.9cqw 0;
  flex-shrink: 0;
}

.demo-tab {
  display: flex;
  align-items: center;
  gap: 0.62cqw;
  height: 2.65cqw;
  min-height: 13px;
  padding: 0 1cqw;
  border-radius: 0.9cqw 0.9cqw 0 0;
  font-family: var(--font-ui);
  font-size: 1.15cqw;
  font-weight: 500;
  line-height: 1;
  color: #9aa0a6;
  white-space: nowrap;
}

.demo-tab--active {
  background: #35363a;                    /* = toolbar, like the real thing */
  color: #e8eaed;
}

.demo-tab__fav {
  width: 1.3cqw;
  height: 1.3cqw;
  min-width: 6px;
  min-height: 6px;
  flex-shrink: 0;
  color: #d6447f;                         /* petal-mark favicon */
}

.demo-tab__dot {
  width: 1.1cqw;
  height: 1.1cqw;
  min-width: 5px;
  min-height: 5px;
  border-radius: 50%;
  background: #5f6368;                    /* generic favicon placeholder */
  flex-shrink: 0;
}

.demo-tab__x {
  width: 1.15cqw;
  height: 1.15cqw;
  min-width: 5px;
  min-height: 5px;
  opacity: 0.75;
  flex-shrink: 0;
}

.demo-tab__new {
  width: 1.35cqw;
  height: 1.35cqw;
  min-width: 6px;
  min-height: 6px;
  margin: 0 0 0.75cqw 0.65cqw;
  color: #9aa0a6;
  flex-shrink: 0;
}

.demo-browser__bar {
  display: flex;
  align-items: center;
  gap: 0.95cqw;
  height: 3.6cqw;
  min-height: 17px;
  padding: 0 1.1cqw;
  background: #35363a;                    /* toolbar */
  flex-shrink: 0;
}

.demo-nav {
  width: 1.5cqw;
  height: 1.5cqw;
  min-width: 7px;
  min-height: 7px;
  color: #c4c7cc;
  flex-shrink: 0;
}

.demo-nav--dim { opacity: 0.38; }         /* no forward history */
.demo-nav--menu { margin-left: 0.15cqw; }

.demo-omnibox {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.7cqw;
  height: 2.5cqw;
  min-height: 12px;
  padding: 0 1.1cqw;
  border-radius: 999px;
  background: #202124;                    /* omnibox pill */
  font-family: var(--font-ui);
  font-size: 1.15cqw;
  font-weight: 500;
  line-height: 1;
  color: #e8eaed;
  white-space: nowrap;
}

.demo-omnibox svg {
  width: 1.1cqw;
  height: 1.1cqw;
  min-width: 5px;
  min-height: 5px;
  color: #9aa0a6;
  flex-shrink: 0;
}

/* Real, functional: opens the actual Petal docs in a new tab. Lives in the
   window's own top bar (.demo-window__actions), not the browser toolbar —
   inherits the header's ink color like every other header action, so it
   reads as part of Petal's chrome rather than the browser's. Carries a
   visible "Open URL" label (not just a hover tooltip) — the one labeled
   action in an otherwise icon-only header, by explicit request. */
.demo-open-url {
  display: flex;
  align-items: center;
  gap: 0.5cqw;
  color: inherit;
  flex-shrink: 0;
  opacity: 0.9;
  transition: opacity 120ms ease;
}

.demo-open-url:hover { opacity: 1; }

.demo-open-url svg {
  width: 1.66cqw;
  height: 1.66cqw;
  min-width: 8px;
  min-height: 8px;
  display: block;
  flex-shrink: 0;
}

.demo-open-url__label {
  font-family: var(--font-ui);
  font-size: 1.3cqw;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}

/* The docs page itself: dark Petal-styled page, one real heading + intro
   line, then skeleton bars (non-text, so nothing can truncate). */
.demo-browser__page {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.85cqw;
  padding: 1.1cqw 1.6cqw;
  background: #0f1115;
  overflow: hidden;
}

.demo-page__nav {
  display: flex;
  align-items: center;
  gap: 0.7cqw;
  font-family: var(--font-ui);
  font-size: 1.15cqw;
  color: #f2f4f8;
  white-space: nowrap;
  margin-bottom: 0.35cqw;
}

.demo-page__nav svg {
  width: 1.35cqw;
  height: 1.35cqw;
  min-width: 6px;
  min-height: 6px;
  color: #d6447f;
}

.demo-page__nav b { font-weight: 700; }

.demo-page__crumb {
  color: #8b93a3;
  padding-left: 0.7cqw;
  border-left: 1px solid rgba(255, 255, 255, 0.14);
}

.demo-page__h {
  font-family: var(--font-ui);
  font-size: 1.9cqw;
  font-weight: 700;
  line-height: 1.1;
  color: #f2f4f8;
  white-space: nowrap;
}

.demo-page__p {
  font-family: var(--font-ui);
  font-size: 1.2cqw;
  font-weight: 400;
  line-height: 1.45;
  color: #9aa4b2;
  max-width: 100%;
}

.demo-skel {
  height: 0.95cqw;
  min-height: 4px;
  border-radius: 99px;
  background: rgba(255, 255, 255, 0.08);
}

.demo-skel--btn {
  width: 22%;
  height: 2.1cqw;
  min-height: 9px;
  margin-top: 0.3cqw;
  border-radius: 0.6cqw;
  background: rgba(214, 68, 127, 0.32);   /* petal-tinted CTA block */
}

/* ---- Meeting pill ---------------------------------------------------
   The real large pill: 58px capsule, gradient #16171a->#0a0a0b, NO border,
   shadow 0 10px 26px -10px rgba(0,0,0,.7); contents = one 33px avatar
   with an identity ring + 40px circular controls (mic, camera,
   screenshare, leave, expand). */
.demo-pill {
  position: absolute;
  left: 50%;
  bottom: 6%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 0.97cqw;
  height: 5cqw;
  min-height: 30px;
  padding: 0 1.3cqw;
  border-radius: 999px;
  background: linear-gradient(180deg, #16171a, #0a0a0b);
  box-shadow: 0 0.86cqw 2.2cqw -0.86cqw rgba(0, 0, 0, 0.7);
  z-index: 5;
}

/* Sits above the Win11 taskbar instead of overlapping it. */
.demo-os--win .demo-pill {
  bottom: 11%;
}

/* Avatar: tinted fallback = dark gradient fill, identity-colored initial;
   ring = separate hairline circle inset -2px (not a plain border). */
.demo-avatar {
  position: relative;
  width: 2.85cqw;
  height: 2.85cqw;
  min-width: 17px;
  min-height: 17px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-ui);
  font-size: max(1.05cqw, 8px);
  font-weight: 600;
  line-height: 1;
  flex-shrink: 0;
  background: linear-gradient(160deg, #1a1c20, #0d0e10);
}

.demo-avatar--blue {
  color: var(--id-blue);
  --ring: var(--id-blue);
}

.demo-avatar::after {
  content: "";
  position: absolute;
  inset: -7%;
  border-radius: 50%;
  border: 1.5px solid var(--ring);
}

/* Control circles: rgba(255,255,255,.07) fill, icons at 50% of the
   circle, stroke rgba(255,255,255,.88) — verbatim from ControlButton. */
.demo-ctl {
  width: 3.45cqw;
  height: 3.45cqw;
  min-width: 20px;
  min-height: 20px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: rgba(255, 255, 255, 0.07);
  color: rgba(255, 255, 255, 0.88);
}

.demo-ctl svg {
  width: 50%;
  height: 50%;
  display: block;
}

/* Screensharing active — the one control that gets color (live tint). */
.demo-ctl--live {
  background: rgba(127, 240, 163, 0.18);
  color: #7ff0a3;
}

/* ---- Telepointers ---------------------------------------------------
   Exact pointer path from Pointer.svelte; NamePill formula from
   NamePill.svelte: gradient fill toward #f5f6f7 at the top, per-identity
   dark ink via color-mix, 800 weight, .045em tracking.

   Each participant's pointer works inside the OTHER person's shared
   window (that's the product: interacting with someone else's window):
   Mira (blue) roams Theo's shared browser; Theo (plum) roams Mira's
   compositor.rs window. Waypoints stay below each window's header. */
.demo-pointer {
  position: absolute;
  display: flex;
  align-items: flex-start;
  gap: 0.52cqw;
  filter: drop-shadow(0 0 0.6cqw rgba(0, 0, 0, 0.5));
}

.demo-pointer--mira { z-index: 5; }
.demo-pointer--theo { z-index: 3; }

.demo-pointer svg {
  width: 2.2cqw;
  height: 2.2cqw;
  min-width: 12px;
  min-height: 12px;
  flex-shrink: 0;
  overflow: visible;
}

.demo-pointer__label {
  margin-top: 1.4cqw;
  font-family: var(--font-ui);
  font-size: 1.85cqw;
  font-weight: 800;
  letter-spacing: 0.045em;
  line-height: 1;
  padding: 0.48em 0.86em 0.38em;
  border-radius: 999px;
  white-space: nowrap;
}

.demo-pointer--mira svg { fill: var(--id-blue); }
.demo-pointer--mira .demo-pointer__label {
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--id-blue) 92%, #f5f6f7),
    var(--id-blue)
  );
  color: color-mix(in srgb, var(--id-blue) 16%, #0c0c0e);
}

.demo-pointer--theo svg { fill: var(--id-plum); }
.demo-pointer--theo .demo-pointer__label {
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--id-plum) 92%, #f5f6f7),
    var(--id-plum)
  );
  color: color-mix(in srgb, var(--id-plum) 16%, #0c0c0e);
}

/* Motion is JS-driven (index.html inline script), not CSS keyframes: 3rd
   naturalness pass — hand-tuned keyframe percentages kept reading as
   "twitch, freeze, twitch". Each pointer's choreography (holds + darts) is
   authored in coordinates relative to the WINDOW it roams in, converted
   through that window's live rect every frame, so pointers ride along when
   their window is dragged or bobs. Darts follow a minimum-jerk velocity
   profile along a gently curved path; holds carry a tiny enveloped drift.
   The left/top below are only the no-JS / pre-JS resting pose (stage %),
   matching each choreography's window-relative rest point; the script
   zeroes them and takes over via transform. */
.demo-pointer--mira {
  left: 48%;
  top: 60%;
}
.demo-pointer--theo {
  left: 12%;
  top: 30%;
}

/* ---- Live remote edit (Theo TYPES in Mira's file) ---------------------
   Sequenced by the inline script against Theo's pointer timeline: he lands
   beside `w.tracked = true;`, freezes, his label flips to "(Theo...)", a
   plum selection sweeps `true` (.is-sel, CSS transition), the word empties
   and a caret appears (.is-typing), `false` types in character by
   character (JS rewrites .demo-edit__word), then a quick re-select +
   instant flip back reads as undo before he darts away. The word sits at
   end-of-line so the extra character of `false` never reflows anything. */
.demo-edit {
  position: relative;
  display: inline-block;
  z-index: 0; /* own stacking context so the selection can sit UNDER the text */
}

.demo-edit__sel {
  position: absolute;
  inset: -0.08em -0.12em;
  z-index: -1;
  border-radius: 0.15em;
  background: var(--id-plum);
  opacity: 0;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 260ms cubic-bezier(0.3, 0.3, 0.3, 1), opacity 120ms linear;
}

.demo-edit.is-sel .demo-edit__sel {
  opacity: 0.45;
  transform: scaleX(1);
}

/* The editable literal keeps its literal color whatever JS types into it. */
.demo-code .demo-edit__word {
  color: #d19a66;
  white-space: pre;
}

/* Insertion caret: constant-width inline box (so showing it never shifts
   the `;`), visible + blinking only while typing. */
.demo-edit__caret {
  display: inline-block;
  width: 0.09em;
  height: 1.05em;
  margin-left: 0.06em;
  vertical-align: -0.18em;
  border-radius: 0.04em;
  background: var(--id-plum);
  opacity: 0;
}

.demo-edit.is-typing .demo-edit__caret {
  animation: demo-caret 850ms steps(1) infinite;
}

@keyframes demo-caret {
  0%, 54% { opacity: 1; }
  55%, 100% { opacity: 0; }
}

/* Click ripple — real values: 14px ring near the pointer tip, border
   color-mix(id 72%, transparent), scale .4->3.2, opacity .36->0. One-shot:
   the script adds .is-on the instant a dart lands, so the click reads as
   the reason the pointer stopped. */
.demo-ripple {
  position: absolute;
  top: 0.26cqw;
  left: 0.26cqw;
  width: 1.2cqw;
  height: 1.2cqw;
  min-width: 6px;
  min-height: 6px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, currentColor 72%, transparent);
  transform: scale(0.4);
  opacity: 0;
}

.demo-pointer--mira .demo-ripple { color: var(--id-blue); }
.demo-pointer--theo .demo-ripple { color: var(--id-plum); }

.demo-ripple.is-on {
  animation: demo-ripple-once 0.65s ease-out;
}

@keyframes demo-ripple-once {
  0% { transform: scale(0.4); opacity: 0.36; }
  100% { transform: scale(3.2); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .demo-window,
  .demo-ripple,
  .demo-edit__caret {
    animation: none !important;
  }

  /* The script also checks the media query itself: no choreography, no
     typing — pointers sit at their window-relative rest pose (still
     following a user-initiated drag), the edit stays on `true`. */

  /* The OS reveal still works — it just snaps instead of animating. */
  .demo-stage {
    transition: none;
  }

  .demo-edit__sel {
    transition: none;
  }
}
