/* ============================================================================
   intro.css — LAPTOP intro-tour overlay (D-058; recomposed as a centred card, D-070).

   Chrome for the overlay that shows the shared tour deck ON TOP of the widget
   while it boots (the widget is blurred/shaded behind). On the laptop the deck
   is presented as a NARROW, CENTRED CARD floated over the blurred widget — not
   a full-viewport column (which read as a stretched phone on a wide screen).
   The DECK itself (slides, navigator, tokens) is styled by tour.css; this file
   styles only the backdrop, the card frame, the always-present ×, and the
   boot→ready button.

   Every rule here is scoped under #intro, which exists ONLY in this laptop
   overlay — the phone page (mobile.html) mounts the same deck into #phone — so
   nothing here can touch the phone layout. Theme-aware via tour.css tokens.

   States are driven by attributes set by intro.js:
     #intro[data-mode="full"|"min"]   full deck (first visit) vs minimal card (return)
     #intro[data-ready="0"|"1"]        widget still booting vs ready to enter
     <html>[data-tour-open]            overlay is up → blur/shade the widget behind
   ========================================================================== */

/* blur + shade the widget behind the overlay (loaded or still booting) */
html[data-tour-open] #root {
  filter: blur(8px) saturate(.9);
  transform: scale(1.015);
  pointer-events: none;
  transition: filter .35s ease, transform .35s ease;
}

/* ---------------------------------------------------------------- overlay -- */
/* the backdrop: a soft shaded field that lets the blurred widget read through,
   with the reading card floated in its centre (both axes) */
#intro.tour-overlay {
  position: fixed; inset: 0; z-index: 1000000;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: color-mix(in srgb, var(--bg, #0e1117) 62%, transparent);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  color: var(--ink, #e6e6df);
  font-family: var(--sans, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);
  overflow: hidden;
  animation: tour-in .35s ease both;
}
#intro.tour-overlay.i-gone { animation: tour-out .3s ease both; }
@keyframes tour-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes tour-out { from { opacity: 1; } to { opacity: 0; } }

/* ------------------------------------------------------------------- card -- */
/* the contained reading panel: narrow, portrait, lifted off the blurred widget
   by a hairline border + layered shadow + a faint top highlight (instrument-
   panel feel). Holds the deck body and the boot bar as one object. */
#intro .tour-card {
  position: relative;
  display: flex; flex-direction: column;
  width: min(500px, 100%);
  height: min(680px, 100%);
  background: var(--surface, #161b22);
  border: 1px solid var(--line, rgba(139,152,166,.16));
  border-radius: 22px; overflow: hidden;
  box-shadow:
    0 34px 84px -30px rgba(0, 0, 0, .74),
    0 10px 30px -14px rgba(0, 0, 0, .5),
    inset 0 1px 0 color-mix(in srgb, var(--ink, #e6e6df) 8%, transparent);
  animation: card-in .42s cubic-bezier(.2, .7, .2, 1) both;
}
@keyframes card-in {
  from { opacity: 0; transform: translateY(12px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* always-present close — anchored to the card's own corner, not the viewport */
#intro .tour-x {
  position: absolute; top: 12px; right: 12px; z-index: 12;
  width: 34px; height: 34px; border-radius: 999px;
  display: grid; place-items: center; font-size: 21px; line-height: 1;
  background: color-mix(in srgb, var(--surface-2, #1c232d) 78%, transparent);
  border: 1px solid var(--line, rgba(139, 152, 166, .16));
  color: var(--muted, #8b98a6); cursor: pointer;
  transition: color .15s, border-color .15s, background .15s, transform .15s;
}
#intro .tour-x:hover {
  color: var(--ink, #e6edf3); border-color: var(--accent, #4c8dff);
  background: var(--surface-2, #1c232d); transform: scale(1.06);
}

/* the deck fills the card body; its navigator pins to the body's bottom */
#intro .tour-stage { position: relative; flex: 1 1 auto; min-height: 0; width: 100%; }
#intro .tour-deck  { position: absolute; inset: 0; }

/* the laptop host (index.html) has no global box-sizing reset the way the phone
   page does, so the deck's slides would render content-box — flex-basis:100% +
   padding overflowing the card and clipping text. Scope a border-box reset to
   the overlay's deck (a no-op on the phone, which is already border-box). */
#intro .flp-deck, #intro .flp-deck *,
#intro .flp-deck *::before, #intro .flp-deck *::after { box-sizing: border-box; }

/* deck fit to the narrower desktop column (all scoped to the laptop overlay) */
#intro .slide      { padding: 42px 36px 92px; }   /* bottom clears the pinned navigator */
#intro .slide-top  { padding-right: 30px; }        /* keep the eyebrow rule clear of the × */
#intro .nav        { background: linear-gradient(to top, var(--surface, #161b22) 48%, transparent); }
/* in the shorter desktop card, centre the cover/outro instead of bottom-packing
   them (bottom-packing collided the long gloss with the navigator) */
#intro .slide[data-kind="cover"] .slide-body,
#intro .slide[data-kind="outro"] .slide-body { justify-content: safe center; }

/* minimal (return-visit) card: a single centred cover slide, shorter panel */
#intro[data-mode="min"] .tour-card  { height: min(600px, 100%); }
#intro[data-mode="min"] .slide      { justify-content: center; }
#intro[data-mode="min"] .slide-body { justify-content: safe center; }

/* ------------------------------------------------------- bottom boot bar -- */
/* the card's footer: the loading→ready action, seamless with the card surface */
#intro .tour-cta {
  flex: 0 0 auto; z-index: 11;
  /* gap:0 — the note row owns its own spacing (it collapses to zero height off the end
     slides, and a flex gap would leave a phantom 7px behind it) */
  display: flex; flex-direction: column; align-items: center; gap: 0;
  padding: 14px 22px 18px;
  background: var(--surface, #161b22);
  border-top: 1px solid var(--line, rgba(139, 152, 166, .12));
}
#intro .tour-go {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; max-width: 320px; padding: 13px 24px; border-radius: 999px;
  font-size: 14.5px; font-weight: 650; letter-spacing: .01em;
  border: 1px solid var(--line, rgba(139, 152, 166, .16));
  background: var(--surface-2, #1c232d); color: var(--muted, #8b98a6);
  cursor: default; transition: background .3s, color .3s, border-color .3s, box-shadow .3s;
}
#intro .tour-sub {
  font-size: 12px; color: var(--muted, #8b98a6); min-height: 1em;
  margin-top: 7px;
  font-family: var(--mono, ui-monospace, Menlo, monospace); letter-spacing: .02em;
}

/* the model note (D-097; placement D-103): in the boot bar ABOVE the primary
   action, on the first and last slide only. In the bar rather than on a slide
   because it must survive both modes (full deck / cover-only return card) and
   because the bar is precisely the dead time it fills — but under the button it
   sat last in the card and dimmed the moment the blue button lit up, which is how
   it went unnoticed. Above the button it is on the way to the action instead of
   past it. Opens in a new tab (tour.js): a same-tab navigation would discard the
   half-loaded Pyodide runtime this bar is waiting on. */
#intro .tour-note {
  width: 100%; max-width: 320px;
  overflow: hidden; max-height: 0; opacity: 0;
  transition: max-height .32s ease, opacity .24s ease;
}
#intro[data-note="1"] .tour-note { max-height: 160px; opacity: 1; }
#intro .tour-note-in { padding-bottom: 12px; }
#intro .note-link { padding: 9px 11px; gap: 10px; }
#intro .note-lead { font-size: 13px; }
#intro .note-sub  { font-size: 11.5px; }
/* the accent-tinted edge is what makes it register as an offer next to the big
   button below it — the plain --line border read as a divider */
#intro .note-link {
  border-color: color-mix(in srgb, var(--accent, #4c8dff) 32%, transparent);
  background: color-mix(in srgb, var(--accent, #4c8dff) 7%, var(--surface-2, #1c232d));
}
@media (prefers-reduced-motion: reduce) {
  #intro .tour-note { transition: none; }
}

/* COMPACT form — one accent line instead of the panel. The panel costs the bar
   ~95px; the line costs ~30px. Two windows cannot afford the panel:
     • narrow (< 548px, where the card stops being 500px and starts shrinking) —
       the cover's gloss then wraps to roughly twice as many lines;
     • short (< 800px tall) — the card is viewport-bound rather than 680px.
   Measured in both: with the panel the cover's "step through" hint ran INTO the
   navigator (26px narrow, 84px at 620px tall); with the line it clears. The deck
   was already at its fit limit below ~625px tall before this link existed — the
   compact form keeps that boundary where it was rather than moving it up. */
@media (max-width: 548px), (max-height: 799px) {
  /* the bar carries one row more than it was designed for — tighten its own box too */
  #intro .tour-cta     { padding: 11px 16px 14px; }
  #intro .tour-sub     { margin-top: 5px; }
  #intro .tour-note-in { padding-bottom: 8px; }
  #intro[data-note="1"] .tour-note { max-height: 60px; }
  #intro .note-link { padding: 4px 0; gap: 8px; background: none; border: none; }
  #intro .note-link:hover { background: none; }
  #intro .note-sub  { display: none; }
  #intro .note-tag  { padding: 2px 5px; font-size: 9px; }
  #intro .note-lead { font-size: 12.5px; color: var(--accent, #4c8dff); }
  #intro .note-ar   { font-size: 13px; }
}

/* booting: a spinner + muted status; the button does nothing */
#intro .tour-go .tour-spin {
  width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: tour-spin 0.9s linear infinite; opacity: .8;
}
@keyframes tour-spin { to { transform: rotate(360deg); } }
#intro .tour-go .tour-dot { display: none; }

/* ready: primary blue, green dot, one gentle pulse to catch the eye */
#intro[data-ready="1"] .tour-go {
  background: var(--accent, #4c8dff); color: #fff; cursor: pointer;
  border-color: var(--accent, #4c8dff);
  box-shadow: 0 6px 20px -6px color-mix(in srgb, var(--accent, #4c8dff) 70%, transparent);
  animation: tour-pulse 1.1s ease 1;
}
#intro[data-ready="1"] .tour-go:hover { filter: brightness(1.06); }
#intro[data-ready="1"] .tour-go .tour-spin { display: none; }
#intro[data-ready="1"] .tour-go .tour-dot {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  background: #46d17f; box-shadow: 0 0 0 3px color-mix(in srgb, #46d17f 35%, transparent);
}
@keyframes tour-pulse {
  0% { transform: scale(1); } 40% { transform: scale(1.045); } 100% { transform: scale(1); }
}

/* the whole backdrop becomes a dismiss target only AFTER ready (intro.js gates
   the click); a subtle cursor hint once it's live */
#intro[data-ready="1"].tour-overlay { cursor: default; }

@media (prefers-reduced-motion: reduce) {
  #intro.tour-overlay, #intro.tour-overlay.i-gone, #intro .tour-card,
  #intro[data-ready="1"] .tour-go { animation: none; }
  #intro .tour-go .tour-spin { animation: none; }
  html[data-tour-open] #root { transition: none; }
}
