/* ──────────────────────────────────────────────────────────────────────────
   Interactive guided tour (demo) — overlay / spotlight / narrator styles.

   The overlay is a single #demoRoot element rendered by _demo_overlay.html.
   It is hidden by the [hidden] attribute when no tour is running, so these
   rules only apply once an engine instance calls .start().

   Z-index layering (low → high), all anchored to viewport via position:fixed:
     9000  #demoLock          — invisible click/touch trap
     9020  #demoSpotlight     — SVG with a hole punched out of a dim layer
     9030  #demoRing          — accent ring around the spotlight target
     9040  #demoNarrator      — text card + control buttons
     9050  #demoExitDock      — sticky exit button (always reachable)
   ────────────────────────────────────────────────────────────────────────── */

#demoRoot {
  position: fixed;
  inset: 0;
  z-index: 9000;
  pointer-events: none;
}
#demoRoot[hidden] { display: none !important; }

/* Full-screen click/touch trap.  Transparent so the spotlight beneath shows
   through, but pointer-events:auto means it eats every click and touch.
   touch-action:none kills pinch-zoom + pull-to-refresh on mobile. */
#demoLock {
  position: fixed;
  inset: 0;
  z-index: 9010;
  pointer-events: auto;
  touch-action: none;
  background: transparent;
  cursor: not-allowed;
}

/* SVG dim layer with a rect-shaped hole around the highlighted element.
   The hole is morphed via attribute updates in JS; the CSS transition makes
   the morph smooth. */
#demoSpotlight {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  z-index: 9020;
  pointer-events: none;
}
#demoSpotlightHole {
  transition: x 280ms cubic-bezier(.4,0,.2,1),
              y 280ms cubic-bezier(.4,0,.2,1),
              width 280ms cubic-bezier(.4,0,.2,1),
              height 280ms cubic-bezier(.4,0,.2,1);
}

/* Accent ring sits on top of the spotlight to outline the highlighted area
   in the project accent colour.  Position is updated from JS in lockstep
   with the spotlight hole. */
#demoRing {
  position: fixed;
  z-index: 9030;
  pointer-events: none;
  border-radius: 8px;
  box-shadow:
    0 0 0 2px var(--accent),
    0 0 24px 4px rgba(67, 224, 163, .35);
  opacity: 0;
  transition: top 280ms cubic-bezier(.4,0,.2,1),
              left 280ms cubic-bezier(.4,0,.2,1),
              width 280ms cubic-bezier(.4,0,.2,1),
              height 280ms cubic-bezier(.4,0,.2,1),
              opacity 200ms ease;
}
#demoRing.visible { opacity: 1; }

/* Subtle pulsing breathe — keeps the eye on the highlighted target. */
@keyframes demoRingBreathe {
  0%, 100% { box-shadow: 0 0 0 2px var(--accent), 0 0 24px 4px rgba(67, 224, 163, .30); }
  50%      { box-shadow: 0 0 0 2px var(--accent), 0 0 30px 8px rgba(67, 224, 163, .55); }
}
#demoRing.visible { animation: demoRingBreathe 2.4s ease-in-out infinite; }

/* Narrator card — text + Pause/Next/Exit/Don't-show controls.  Floats near
   the highlighted element on desktop (top/left set from JS); pinned to the
   bottom of the viewport on mobile (see media query below).
   Flex column so the text body can scroll (flex:1, overflow:auto) while the
   button row stays glued to the bottom edge — critical on mobile where a
   long welcome text would otherwise push the buttons below the visible area. */
#demoNarrator {
  position: fixed;
  z-index: 9040;
  pointer-events: auto;
  width: min(440px, calc(100vw - 32px));
  background: var(--bg2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1rem 1.1rem 0.85rem;
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.45),
              0 0 0 1px rgba(67, 224, 163, 0.18);
  color: var(--text);
  animation: demoNarratorIn 220ms cubic-bezier(.2,.8,.2,1);
  display: flex;
  flex-direction: column;
  /* Cap card height so it can never run off the viewport.  The button row
     below uses flex-shrink:0 so it always reserves its own space; the text
     body absorbs the squeeze and scrolls when needed. */
  max-height: calc(100vh - 80px);
}
@keyframes demoNarratorIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

#demoNarrator.demo-narrator-centered {
  top: 50% !important;
  left: 50% !important;
  transform: translate(-50%, -50%);
}

#demoNarrator .demo-narr-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  margin-bottom: .55rem;
  flex-shrink: 0;          /* header never gets squeezed */
}
#demoNarrator .demo-narr-progress {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--accent);
  text-transform: uppercase;
}
#demoNarrator .demo-narr-title {
  font-size: .72rem;
  color: var(--text2);
  font-weight: 600;
}
/* Text body absorbs the squeeze when the card hits its max-height: scrolls
   internally rather than pushing the button row off-screen.  min-height:0
   is required for overflow to take effect inside a flex column. */
#demoNarrator .demo-narr-text {
  font-size: .92rem;
  line-height: 1.55;
  color: var(--text);
  margin: 0 0 .85rem;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* Button row pinned at the bottom of the card.  flex-shrink:0 guarantees
   it always reserves its own height regardless of how much text is above. */
#demoNarrator .demo-narr-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  align-items: center;
  flex-shrink: 0;
}
#demoNarrator .demo-btn {
  font: inherit;
  font-size: .82rem;
  font-weight: 600;
  padding: .42rem .85rem;
  border-radius: 7px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  transition: border-color .12s, color .12s, background .12s;
}
#demoNarrator .demo-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}
#demoNarrator .demo-btn:disabled,
#demoNarrator .demo-btn[disabled] {
  opacity: .35;
  cursor: not-allowed;
}
#demoNarrator .demo-btn:disabled:hover,
#demoNarrator .demo-btn[disabled]:hover {
  border-color: var(--border);
  color: var(--text);
}
#demoNarrator .demo-btn-primary {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
}
#demoNarrator .demo-btn-primary:hover {
  background: var(--accent);
  color: var(--bg);
  filter: brightness(1.08);
}
#demoNarrator .demo-btn-ghost {
  margin-left: auto;
  font-size: .72rem;
  color: var(--text3);
  border-color: transparent;
  padding: .35rem .55rem;
}
#demoNarrator .demo-btn-ghost:hover {
  color: var(--text);
  border-color: var(--border);
}

/* Sticky exit dock — a separate element, fixed top-right, so the user can
   bail at any time even if the narrator is mid-animation or off-screen on
   a small viewport. */
#demoExitDock {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 9050;
  pointer-events: auto;
}
#demoExitDock .demo-exit-btn {
  font: inherit;
  font-size: .82rem;
  font-weight: 700;
  padding: .55rem 1rem;
  border-radius: 8px;
  border: 1.5px solid var(--accent);
  background: var(--bg2);
  color: var(--accent);
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .35),
              0 0 0 1px rgba(67, 224, 163, 0.20);
  transition: background .12s, color .12s, transform .1s;
  backdrop-filter: blur(6px);
}
#demoExitDock .demo-exit-btn:hover {
  background: var(--accent);
  color: var(--bg);
  transform: translateY(-1px);
}

/* Mobile (≤600 px): narrator pinned to the viewport bottom in a full-width
   strip; exit dock shrinks but stays in the corner.  Removes the floating
   placement that becomes cramped on small screens.

   The two killer issues we fix here:
   1. iOS URL bar / Android gesture bar can cover content at `bottom: 12px`
      → use `env(safe-area-inset-bottom)` so the card bottom always sits
      above the home-indicator / URL bar.
   2. A long welcome paragraph plus three buttons used to push the buttons
      below the visible area → cap card height at viewport-minus-safe-area
      and let .demo-narr-text scroll inside (rules in the base styles
      above).  100dvh — when supported — accounts for the dynamic URL bar
      shrinking on iOS Safari; falls back to 100vh otherwise. */
@media (max-width: 600px) {
  #demoNarrator {
    top: auto !important;
    left: 8px !important;
    right: 8px !important;
    bottom: calc(8px + env(safe-area-inset-bottom, 0px)) !important;
    transform: none !important;
    width: auto !important;
    max-width: none !important;
    padding: .85rem .9rem .75rem;
    max-height: calc(100vh - 80px - env(safe-area-inset-bottom, 0px));
    max-height: calc(100dvh - 80px - env(safe-area-inset-bottom, 0px));
  }
  #demoNarrator.demo-narrator-centered {
    transform: none;
  }
  #demoNarrator .demo-narr-text { font-size: .88rem; }
  /* Buttons stretched to fill the row evenly so each is a comfortable tap
     target; "Don't show" stays the rightmost ghost button via min-content. */
  #demoNarrator .demo-narr-buttons { gap: .5rem; }
  #demoNarrator .demo-btn { flex: 1 1 auto; min-height: 40px; }
  #demoNarrator .demo-btn-ghost {
    flex: 0 0 auto;
    margin-left: 0;            /* override the desktop "push to right" */
  }
  #demoExitDock {
    top: calc(8px + env(safe-area-inset-top, 0px));
    right: 8px;
  }
  #demoExitDock .demo-exit-btn { padding: .45rem .75rem; font-size: .75rem; }
}

/* While the demo is running, swallow scrollbar visibility on the body so the
   page does not jump if scrolling gets blocked.  We do not set overflow:hidden
   because programmatic scrollIntoView relies on the scroll context staying
   active. */
body.demo-active {
  overscroll-behavior: contain;
}

/* Light theme refinements — the dark dim layer becomes lighter so the page
   below is still legible behind the spotlight. */
[data-theme="light"] #demoSpotlight rect[fill] {
  fill: rgba(15, 24, 32, 0.45);
}
[data-theme="light"] #demoNarrator {
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.18),
              0 0 0 1px rgba(67, 224, 163, 0.20);
}

/* The 💡 Guide button used inside lab UIs (panel + canvas-toolbar).  Inherits
   colour from the toolbar / panel button styles where it is dropped, but we
   give it a soft accent tint so it is visually discoverable. */
.demo-launch-btn {
  --demo-launch-tint: rgba(67, 224, 163, 0.10);
  background: var(--demo-launch-tint);
}
.demo-launch-btn:hover {
  --demo-launch-tint: rgba(67, 224, 163, 0.20);
}
