/* lobby-tour.css — "The Playable Internet" guided tour: a spotlight + the
   DexHero's coachmark. Non-blocking (pointer-events:none on the dim) so the
   lobby stays fully playable while the DexHero shows you around. */

/* Dim overlay — an SVG mask that cuts the crisp spotlight hole PLUS a soft model
   vignette, so the model can read "over" the dark on steps that spotlight another
   surface. pointer-events:none → the lobby stays clickable. */
.tour-dim {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    z-index: 1390;
    pointer-events: none;
    transition: opacity 220ms ease;
}
.tour-dim--out { opacity: 0; }
/* Forge/Create route steps: the real page panel renders at z-index ~40 (below the
   dim), so drop the dim + the lifted model out of the way and let the live panel
   show through. The cyan ring (1391) + coachmark (1400) still float above it. */
body.tour-panel-mode .tour-dim { opacity: 0; pointer-events: none; }
/* Drop the lifted model BELOW the menu/panels (z:40-1100) instead of hiding it,
   so the DexHero stays visible in the scene behind the open menu/page. */
body.tour-panel-mode .tour-model-layer { z-index: 5; }
/* Menu-walk steps (desktop): the lifted world canvas (z:1395) paints scene glow
   OVER the dropdown (z:1100), which reads as a see-through menu. Lift the dropdown
   above the dim + canvas so it renders fully solid; the cyan ring rides just above
   it to mark the current row, and the coachmark (z:1400) stays on top. Desktop-only:
   the mobile sheet already sits at z:10050. */
@media (min-width: 769px) {
    body.tour-menu-mode .lobby-connect-pop { z-index: 1396; }
    body.tour-menu-mode .tour-spot { z-index: 1397; }
}
@media (max-width: 768px) {
    /* The mobile Start-here sheet is z:10050 (shell.css) — ABOVE the tour chrome's
       default z:1391-1400. Raise the coachmark + hand over it so the menu steps'
       instructions and their Next/Skip/Back are never buried behind the sheet.
       `body` prefix: these sit BEFORE the base .tour-pop/.tour-hand rules in this
       file, so at equal specificity the base z-index would win — the extra type
       selector makes the mobile lift beat source order. */
    body .tour-pop  { z-index: 10060; }
    body .tour-hand { z-index: 10061; }
    /* Menu-walk steps: the sheet keeps its normal full size — the top-pinned
       coachmark (placePopMobileTop, z:10060) simply OVERLAYS its upper edge
       rather than the sheet being shortened to make room. The cyan ring is lifted
       over the sheet (z:10050) so the spotlighted row actually reads ringed.
       Gated on tour-menu-mode (the menu walk), which — unlike panel-mode — keeps
       the dim ON so the background stays shaded. */
    body.tour-menu-mode .tour-spot { z-index: 10055; }
}
@media (max-width: 640px) {
    /* Route steps (Forge/Create): at phone widths the full-screen panel covers
       the app header — but the forge-open stop RINGS the header FORGE button.
       The nav can't be z-lifted over the panel (it's trapped inside the
       .lobby-root isolation:isolate stacking context, which sits below the
       panels overlay), so instead start the panel BELOW the ticker+nav while
       the tour is in panel-mode — same geometry as tablet widths — keeping the
       real header, and the button being pointed at, on screen. */
    body.tour-panel-mode .panel--right,
    body.tour-panel-mode .panel--left,
    body.tour-panel-mode .panel--codex,
    body.tour-panel-mode .panel--overlay {
        top: calc(var(--ticker-h) + var(--nav-h));
        bottom: 0;
        height: auto;
        max-height: none;
    }
    /* Forge step: the paste form sits mid-panel and the content otherwise just
       fits, so there's nothing to scroll. Give the body a tall bottom pad during
       the tour so `reveal: 'top'` can scroll the ringed form UP to the panel
       top — leaving the lower half as clear room for the bottom-right coachmark
       + mascot (the empty pad is where they float). */
    body.tour-panel-mode .panel__body:has(.forge) { padding-bottom: 46vh; }
}
/* The live model canvas is reparented here during the tour so the model + pad
   render ABOVE the dim (below the bubble). Transparent canvas → only the figure
   shows over the darkened background. */
.tour-model-layer {
    position: fixed;
    inset: 0;
    z-index: 1395;
    pointer-events: none;
    transition: opacity 220ms ease;
}
.tour-dim rect[data-hole] {
    transition: x 280ms cubic-bezier(0.22, 1, 0.36, 1),
                y 280ms cubic-bezier(0.22, 1, 0.36, 1),
                width 280ms cubic-bezier(0.22, 1, 0.36, 1),
                height 280ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Focus ring — glowing cyan outline + slow pulse over the spotlight target
   (identical to before; the SVG above owns the shading now). */
.tour-spot {
    position: fixed;
    z-index: 1391;
    border-radius: 14px;
    pointer-events: none;
    box-shadow:
        0 0 0 1.5px rgba(110, 231, 255, 0.9),
        0 0 22px 4px rgba(6, 182, 212, 0.45);
    transition: left 280ms cubic-bezier(0.22, 1, 0.36, 1),
                top 280ms cubic-bezier(0.22, 1, 0.36, 1),
                width 280ms cubic-bezier(0.22, 1, 0.36, 1),
                height 280ms cubic-bezier(0.22, 1, 0.36, 1),
                opacity 220ms ease;
    animation: tour-pulse 2.2s ease-in-out infinite;
}
.tour-spot--out { opacity: 0; }

@keyframes tour-pulse {
    0%, 100% { box-shadow: 0 0 0 1.5px rgba(110,231,255,0.9), 0 0 18px 3px rgba(6,182,212,0.4); }
    50%      { box-shadow: 0 0 0 1.5px rgba(110,231,255,1),   0 0 30px 8px rgba(6,182,212,0.6); }
}

/* Coachmark — the DexHero speaking. Mirrors .gh-star-pop (dark glass + blur). */
.tour-pop {
    position: fixed;
    z-index: 1400;
    width: min(320px, calc(100vw - 24px));
    padding: 13px 14px 12px;
    border-radius: 14px;
    border: 1px solid rgba(110, 231, 255, 0.26);
    background: linear-gradient(180deg, rgba(12, 16, 26, 0.98), rgba(7, 10, 18, 0.99));
    -webkit-backdrop-filter: blur(16px) saturate(130%);
    backdrop-filter: blur(16px) saturate(130%);
    box-shadow: 0 20px 56px rgba(0, 0, 0, 0.6), 0 0 26px rgba(6, 182, 212, 0.12);
    color: var(--ink-0, #eaf2f6);
    opacity: 0;
    transform: translateY(6px) scale(0.98);
    transition: opacity 150ms ease, transform 150ms ease, left 200ms ease, top 200ms ease;
}
.tour-pop[data-open="1"] { opacity: 1; transform: translateY(0) scale(1); }

/* Speech-bubble tail — the coachmark is the DexHero speaking, so its bottom-
   RIGHT corner grows a tail that bridges down-right toward its head (the bubble
   sits up-and-left of the head, exactly like the real lobby speech bubble). Two
   layers: ::before is the cyan outline, ::after a 1px-smaller dark fill so a thin
   ring shows. data-tail=down → tail below (bubble above the head); data-tail=up →
   tail above (bubble dropped below the head). */
.tour-pop[data-tail]::before,
.tour-pop[data-tail]::after {
    content: ''; position: absolute; width: 0; height: 0;
    border-style: solid; pointer-events: none;
}
.tour-pop[data-tail="down"]::before {
    bottom: -16px; right: 26px;
    border-width: 16px 0 0 18px;
    border-color: rgba(110, 231, 255, 0.45) transparent transparent transparent;
}
.tour-pop[data-tail="down"]::after {
    bottom: -14px; right: 27px;
    border-width: 14px 0 0 16px;
    border-color: rgba(8, 11, 19, 0.99) transparent transparent transparent;
}
.tour-pop[data-tail="up"]::before {
    top: -16px; right: 26px;
    border-width: 0 0 16px 18px;
    border-color: transparent transparent rgba(110, 231, 255, 0.45) transparent;
}
.tour-pop[data-tail="up"]::after {
    top: -14px; right: 27px;
    border-width: 0 0 14px 16px;
    border-color: transparent transparent rgba(12, 16, 26, 0.98) transparent;
}
/* Centered-below tail — used when the loadout is open and the bubble sits
   centered high above the model; points straight down at the head. */
.tour-pop[data-tail="down-center"]::before {
    bottom: -16px; left: 50%; margin-left: -9px;
    border-width: 16px 9px 0 9px;
    border-color: rgba(110, 231, 255, 0.45) transparent transparent transparent;
}
.tour-pop[data-tail="down-center"]::after {
    bottom: -14px; left: 50%; margin-left: -8px;
    border-width: 14px 8px 0 8px;
    border-color: rgba(8, 11, 19, 0.99) transparent transparent transparent;
}
/* Down-right tail — mobile corner coachmark: bubble sits above the bottom-right
   mascot, tail on its lower-right edge pointing down at the avatar. */
.tour-pop[data-tail="down-right"]::before {
    bottom: -16px; right: 26px; margin-left: 0;
    border-width: 16px 9px 0 9px;
    border-color: rgba(110, 231, 255, 0.45) transparent transparent transparent;
}
.tour-pop[data-tail="down-right"]::after {
    bottom: -14px; right: 27px; margin-left: 0;
    border-width: 14px 8px 0 8px;
    border-color: rgba(8, 11, 19, 0.99) transparent transparent transparent;
}
/* Centered-above tail — bubble sits below the head (head too high for an above
   bubble); points straight up at the head. */
.tour-pop[data-tail="up-center"]::before {
    top: -16px; left: 50%; margin-left: -9px;
    border-width: 0 9px 16px 9px;
    border-color: transparent transparent rgba(110, 231, 255, 0.45) transparent;
}
.tour-pop[data-tail="up-center"]::after {
    top: -14px; left: 50%; margin-left: -8px;
    border-width: 0 8px 14px 8px;
    border-color: transparent transparent rgba(12, 16, 26, 0.98) transparent;
}
/* Side tails — bubble sits beside the head; the tail is on the head-facing edge,
   vertically centered, pointing back at the head. data-tail=right → bubble is
   LEFT of the head (tail on its right edge); data-tail=left → bubble is RIGHT. */
.tour-pop[data-tail="right"]::before {
    top: 50%; right: -16px; margin-top: -11px;
    border-width: 11px 0 11px 18px;
    border-color: transparent transparent transparent rgba(110, 231, 255, 0.45);
}
.tour-pop[data-tail="right"]::after {
    top: 50%; right: -13px; margin-top: -9px;
    border-width: 9px 0 9px 15px;
    border-color: transparent transparent transparent rgba(8, 11, 19, 0.99);
}
.tour-pop[data-tail="left"]::before {
    top: 50%; left: -16px; margin-top: -11px;
    border-width: 11px 18px 11px 0;
    border-color: transparent rgba(110, 231, 255, 0.45) transparent transparent;
}
.tour-pop[data-tail="left"]::after {
    top: 50%; left: -13px; margin-top: -9px;
    border-width: 9px 15px 9px 0;
    border-color: transparent rgba(8, 11, 19, 0.99) transparent transparent;
}

/* While the tour is live, the DexHero speaks the tutorial — silence its default
   idle speech bubble ("Give me a brain…") so there's only one voice on screen. */
body.lobby-tour-live #lobby-stage-speaking-bubble,
body.lobby-tour-live #lobby-stage-bubble {
    opacity: 0 !important;
    pointer-events: none !important;
}

/* During the tour the coachmark bubble hovers near the centre/model, so the loadout
   slots' hover-titles flip AWAY from it: side columns point OUTWARD, the bottom
   weapon row points DOWN — otherwise the bubble covers them. */
body.lobby-tour-live .blh__col--left .blh__tip {
    left: auto; right: calc(100% + 8px);
    transform: translateY(-50%) translateX(4px);
}
body.lobby-tour-live .blh__col--left .blh__slot:hover .blh__tip { transform: translateY(-50%) translateX(0); }
body.lobby-tour-live .blh__col--right .blh__tip {
    right: auto; left: calc(100% + 8px);
    transform: translateY(-50%) translateX(-4px);
}
body.lobby-tour-live .blh__col--right .blh__slot:hover .blh__tip { transform: translateY(-50%) translateX(0); }
body.lobby-tour-live .blh__row--bottom .blh__tip {
    bottom: auto; top: calc(100% + 8px);
    transform: translateX(-50%) translateY(-4px);
}
body.lobby-tour-live .blh__row--bottom .blh__slot:hover .blh__tip { transform: translateX(-50%) translateY(0); }

/* Talk step: the chat bar is intentionally near-black (a recessed "hole" fill),
   which reads as a dark void inside the bright spotlight. Lift ONLY its background
   to a clearly-lit navy + a soft cyan rim — NO outer/dark shadow (that would
   blacken the transparent gap around it). */
.lobby-stage__chat.tour-lit {
    background: linear-gradient(180deg, rgba(26, 38, 58, 0.97), rgba(18, 28, 46, 0.97)) !important;
    border-color: rgba(110, 231, 255, 0.5);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

.tour-pop__head { display: flex; align-items: center; gap: 8px; }
.tour-pop__glyph { width: 22px; height: 22px; flex: 0 0 auto; color: var(--acc-cyan, #29d3e6); display: inline-flex; }
.tour-pop__glyph svg { width: 22px; height: 22px; filter: drop-shadow(0 0 6px rgba(6, 182, 212, 0.5)); }
.tour-pop__title { flex: 1; font-weight: 800; font-size: 13.5px; line-height: 1.2; }
.tour-pop__skip,
.tour-pop__back {
    flex: 0 0 auto; border: 0; background: none; color: var(--ink-3, #8a93a0);
    font-size: 11px; cursor: pointer; padding: 2px 4px; border-radius: 6px;
}
.tour-pop__back { margin-right: 2px; }
.tour-pop__skip:hover,
.tour-pop__back:hover { color: #fff; background: rgba(255, 255, 255, 0.06); }

.tour-pop__body {
    margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-1, #c9d2dc);
    min-height: 2.2em;   /* hold height so the typewriter doesn't jump the card */
}
/* Mid-weight emphasis inside the body — heavier than the copy (400), lighter than
   the title (800), and a touch brighter so the phrase reads as a proper noun. */
.tour-pop__em { font-weight: 650; color: var(--ink-0, #eaf2f6); }
.tour-pop__hint {
    margin-top: 8px; font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase;
    color: var(--acc-cyan, #29d3e6); opacity: 0.85;
}

.tour-pop__foot { display: flex; align-items: center; justify-content: space-between; margin-top: 12px; }
.tour-pop__dots { display: inline-flex; gap: 5px; }
.tour-pop__dot { width: 6px; height: 6px; border-radius: 50%; background: rgba(255, 255, 255, 0.18); transition: background 160ms ease, transform 160ms ease; }
.tour-pop__dot.is-on { background: var(--acc-cyan, #29d3e6); transform: scale(1.25); box-shadow: 0 0 8px rgba(6, 182, 212, 0.6); }

.tour-pop__next {
    border: 1px solid rgba(110, 231, 255, 0.5); border-radius: 9px;
    background: linear-gradient(180deg, rgba(20, 46, 64, 0.9), rgba(10, 26, 40, 0.92));
    color: #d8f6ff; font-weight: 700; font-size: 12px; padding: 7px 16px; cursor: pointer;
    transition: border-color 140ms ease, box-shadow 140ms ease, transform 100ms ease;
}
.tour-pop__next:hover { border-color: rgba(110, 231, 255, 0.85); box-shadow: 0 0 16px rgba(6, 182, 212, 0.3); }
.tour-pop__next:active { transform: translateY(1px); }

/* Animated tap-hand — "click me to open my gear". A 3D-ish white hand that presses
   down over the model with a cyan ripple on each tap, + a static hint label below. */
.tour-hand {
    position: fixed;
    z-index: 1399;
    width: 48px;
    height: 56px;
    pointer-events: none;
    opacity: 0;
    transition: opacity 220ms ease;
}
/* The hand itself taps; the label below it stays still. */
.tour-hand__tap {
    position: relative;
    width: 48px;
    height: 56px;
    transform-origin: 50% 12%;
    filter: drop-shadow(0 7px 9px rgba(0, 0, 0, 0.5));
    animation: tour-hand-tap 1.5s cubic-bezier(0.4, 0, 0.3, 1) infinite;
}
.tour-hand__label {
    position: absolute;
    top: calc(100% + 5px);
    left: 50%;
    transform: translateX(-50%);
    white-space: nowrap;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: #cfe6f5;
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.75);
}
.tour-hand__icon {
    width: 100%; height: 100%; display: block;
    color: #f2f7fc;
}
.tour-hand__ripple {
    position: absolute; left: 50%; top: 7px;
    width: 30px; height: 30px; margin: -15px 0 0 -15px;
    border-radius: 50%;
    border: 2px solid rgba(110, 231, 255, 0.95);
    opacity: 0;
    animation: tour-hand-ripple 1.5s ease-out infinite;
}
@keyframes tour-hand-tap {
    0%, 100% { transform: translateY(0) scale(1); }
    38%      { transform: translateY(9px) scale(0.9); }
    52%      { transform: translateY(9px) scale(0.9); }
    70%      { transform: translateY(0) scale(1); }
}
@keyframes tour-hand-ripple {
    0%, 34% { transform: scale(0.3); opacity: 0; }
    46%     { opacity: 0.85; }
    100%    { transform: scale(1.6); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .tour-hand__tap { animation: none; }
    .tour-hand__ripple { animation: none; opacity: 0.5; }
}

/* Snowball the DexHero lobs at the surface it's pointing to, + the impact splat. */
.tour-snowball {
    position: fixed; left: 0; top: 0; width: 18px; height: 18px; z-index: 1402;
    border-radius: 50%; pointer-events: none; will-change: transform;
    background: radial-gradient(circle at 34% 30%, #ffffff 0%, #eef6ff 46%, #b9d4ea 100%);
    box-shadow: 0 0 12px rgba(185, 222, 255, 0.75), inset -2px -2px 4px rgba(120, 160, 200, 0.5);
}
.tour-splat { position: fixed; z-index: 1402; width: 0; height: 0; pointer-events: none; }
.tour-splat::before {
    content: ''; position: absolute; left: 0; top: 0; width: 10px; height: 10px;
    transform: translate(-50%, -50%); border-radius: 50%;
    border: 2px solid rgba(222, 240, 255, 0.95);
    animation: tour-splat-ring 440ms ease-out forwards;
}
@keyframes tour-splat-ring {
    from { width: 10px; height: 10px; opacity: 0.95; }
    to   { width: 52px; height: 52px; opacity: 0; }
}
.tour-splat i {
    position: absolute; left: 0; top: 0; width: 5px; height: 5px; border-radius: 50%;
    background: radial-gradient(circle, #fff, #d3e8ff); transform: translate(-50%, -50%);
    animation: tour-splat-p 560ms cubic-bezier(0.2, 0.7, 0.3, 1) forwards;
}
@keyframes tour-splat-p {
    from { transform: translate(-50%, -50%); opacity: 1; }
    to   { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .tour-spot { animation: none; transition: opacity 150ms ease; }
    .tour-pop { transition: opacity 120ms ease; }
    .tour-snowball, .tour-splat { display: none; }
}

/* ── Mobile: bottom-right DexHero mascot ─────────────────────────────────────
   A small live model of the visitor's OWN DexHero, pinned to the bottom-right
   corner (thumb-reach) so the coachmark reads as it speaking to you from there.
   Created only on phones by ensureHeroAvatar(); z below .tour-pop (10060) but
   above the Start-here sheet (10050). Geometry mirrors AV_BOTTOM/AV_SIZE in
   lobby-tour.js — keep them in sync. */
.tour-hero-avatar {
    position: fixed;
    right: 10px;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 76px);
    width: 84px;
    height: 84px;
    z-index: 10059;
    pointer-events: none;
    opacity: 0;
    transform: translateY(10px) scale(0.9);
    transition: opacity 240ms ease, transform 240ms ease;
    filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.55));
}
.tour-hero-avatar[data-open="1"] { opacity: 1; transform: none; }
.tour-hero-avatar model-viewer,
.tour-hero-avatar img,
.tour-hero-avatar__glyph {
    width: 100%;
    height: 100%;
    background: transparent;
    --poster-color: transparent;
}
.tour-hero-avatar img { object-fit: contain; }
.tour-hero-avatar__glyph {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--acc-cyan, #29d3e6);
}
.tour-hero-avatar__glyph svg { width: 64%; height: 64%; }
