/* Gradual onboarding — progressive UI reveal.
 *
 * The game root carries `data-onboarding-show="space separated list"` listing
 * the element classes (without the `ob-el-` prefix) that should be visible
 * for the current stage. Anything not in the list is hidden. Stage 1 emits
 * an empty list (everything hidden); stage 8 emits all names.
 *
 * To add a new toggleable element:
 *   1. Stick `class="ob-el-<name>"` on the JSX element.
 *   2. Add a rule below using `:not([data-onboarding-show~="<name>"])`.
 *   3. Add the name as a flag in misc/onboardingStages.js per-stage map.
 */

/* Hide each labelled element when its name is NOT in the show list. The
 * tilde-equals attribute selector `[attr~=name]` matches a space-separated
 * token, which is exactly what `data-onboarding-show="a b c"` produces.
 *
 * Use `visibility: hidden` (not `display: none`) so each element retains
 * its layout slot. The cards stay anchored to the same screen position
 * through all eight stages — pieces fade in around them rather than the
 * hand jumping every time something reveals.
 */
#game.onboarding-active .ob-el-playerBars,
#game.onboarding-active .ob-el-scoreBanners,
#game.onboarding-active .ob-el-turnIndicator,
#game.onboarding-active .ob-el-lastPlayedCard,
#game.onboarding-active .ob-el-ownCastle,
#game.onboarding-active .ob-el-opponentCastle,
#game.onboarding-active .ob-el-walls,
#game.onboarding-active .ob-el-ownBricks,
#game.onboarding-active .ob-el-ownBuilders,
#game.onboarding-active .ob-el-ownAttackStat,
#game.onboarding-active .ob-el-ownMagicStat,
#game.onboarding-active .ob-el-oppBricks,
#game.onboarding-active .ob-el-oppBuilders,
#game.onboarding-active .ob-el-oppAttackStat,
#game.onboarding-active .ob-el-oppMagicStat,
#game.onboarding-active .ob-el-opponentResources,
body .navbar {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity 0.32s ease,
    transform 0.36s cubic-bezier(0.22, 1, 0.36, 1),
    visibility 0s linear;
  will-change: opacity, transform;
}

#game.onboarding-active:not([data-onboarding-show~="playerBars"]) .ob-el-playerBars,
#game.onboarding-active:not([data-onboarding-show~="scoreBanners"]) .ob-el-scoreBanners,
#game.onboarding-active:not([data-onboarding-show~="turnIndicator"]) .ob-el-turnIndicator,
#game.onboarding-active:not([data-onboarding-show~="lastPlayedCard"]) .ob-el-lastPlayedCard,
#game.onboarding-active:not([data-onboarding-show~="ownCastle"]) .ob-el-ownCastle,
#game.onboarding-active:not([data-onboarding-show~="opponentCastle"]) .ob-el-opponentCastle,
#game.onboarding-active:not([data-onboarding-show~="walls"]) .ob-el-walls,
/* Per-resource flags so we reveal bricks → bricks+builders → the rest. */
#game.onboarding-active:not([data-onboarding-show~="ownBricks"]) .ob-el-ownBricks,
#game.onboarding-active:not([data-onboarding-show~="ownBuilders"]) .ob-el-ownBuilders,
#game.onboarding-active:not([data-onboarding-show~="ownAttackStat"]) .ob-el-ownAttackStat,
#game.onboarding-active:not([data-onboarding-show~="ownMagicStat"]) .ob-el-ownMagicStat,
#game.onboarding-active:not([data-onboarding-show~="oppBricks"]) .ob-el-oppBricks,
#game.onboarding-active:not([data-onboarding-show~="oppBuilders"]) .ob-el-oppBuilders,
#game.onboarding-active:not([data-onboarding-show~="oppAttackStat"]) .ob-el-oppAttackStat,
#game.onboarding-active:not([data-onboarding-show~="oppMagicStat"]) .ob-el-oppMagicStat {
  visibility: hidden !important;
  opacity: 0 !important;
  transform: translateY(8px) scale(0.985);
}

/* Hide the opponent's whole resource block with visibility:hidden so it
 * keeps its layout slot — display:none would let the enemy castle shift
 * upward when there's nothing under it. The per-icon ob-el-opp* rules
 * above also use visibility:hidden, so descendants stay invisible too;
 * the empty wrapper carries no background/border, so the player just
 * sees blank space (matching where the resources will appear at stage 6). */
#game.onboarding-active:not([data-onboarding-show~="opponentResources"]) .ob-el-opponentResources {
  visibility: hidden !important;
  opacity: 0 !important;
  transform: translateY(8px) scale(0.985);
}

/* Navbar — controlled via a body attribute set by main.js after each HTMX
 * swap (the layout is rendered once but state changes per-stage, so this
 * one needs JS plumbing). Same visibility:hidden so its slot at the top
 * of the page stays put, only the contents disappear. */
body[data-onboarding-hide-nav="true"] .navbar {
  visibility: hidden !important;
  opacity: 0 !important;
  transform: translateY(-8px);
}

#game.onboarding-active .onboarding-reveal-enter,
body .navbar.onboarding-reveal-enter {
  animation: onboardingRevealFade 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes onboardingRevealFade {
  0% {
    opacity: 0;
    transform: translateY(10px) scale(0.985);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

body .navbar.navbar-onboarding-reveal {
  visibility: visible !important;
  opacity: 1 !important;
  transform: none !important;
}

body .navbar.navbar-onboarding-reveal::before,
body .navbar.navbar-onboarding-reveal .navbar-bracket {
  animation: onboardingNavbarFrameReveal 0.52s cubic-bezier(0.22, 1, 0.36, 1) both;
}

body .navbar.navbar-onboarding-reveal .navbar-brand,
body .navbar.navbar-onboarding-reveal .navbar-online,
body .navbar.navbar-onboarding-reveal .navbar-center,
body .navbar.navbar-onboarding-reveal .navbar-right,
body .navbar.navbar-onboarding-reveal .burger {
  opacity: 0;
  transform: translateY(10px);
}

body .navbar.navbar-onboarding-reveal .navbar-brand {
  animation: onboardingNavbarItemReveal 0.72s cubic-bezier(0.22, 1, 0.36, 1) 0.24s both;
}

body .navbar.navbar-onboarding-reveal .navbar-online {
  animation: onboardingNavbarItemReveal 0.72s cubic-bezier(0.22, 1, 0.36, 1) 0.42s both;
}

body .navbar.navbar-onboarding-reveal .navbar-center {
  animation: onboardingNavbarItemReveal 0.78s cubic-bezier(0.22, 1, 0.36, 1) 0.58s both;
}

body .navbar.navbar-onboarding-reveal .navbar-right {
  animation: onboardingNavbarItemReveal 0.78s cubic-bezier(0.22, 1, 0.36, 1) 0.76s both;
}

body .navbar.navbar-onboarding-reveal .burger {
  animation: onboardingNavbarItemReveal 0.68s cubic-bezier(0.22, 1, 0.36, 1) 0.9s both;
}

@keyframes onboardingNavbarFrameReveal {
  0% {
    opacity: 0;
    transform: translateY(-10px) scaleY(0.94);
    filter: brightness(0.8);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scaleY(1);
    filter: brightness(1);
  }
}

@keyframes onboardingNavbarItemReveal {
  0% {
    opacity: 0;
    transform: translateY(10px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ─────────────────────────────────────────────────────────────────────── */
/* Brick-flight animation on card play.
 *
 * When the player plays a brick-costing card during stages 1-3, JS
 * (public/main.js, see onboarding-brick-flight IIFE) adds these
 * transient classes and spawns flying brick particles between the
 * counter and the played card's cost icon — so the player visually ties
 * "10 bricks gone from my pool" to "10 bricks landed on this card". */

/* Brick counter pulses larger for the duration of the flight. */
.onboarding-brick-emphasize {
  animation: onboardingBrickEmphasize 1.1s cubic-bezier(0.4, 0, 0.2, 1);
  transform-origin: center;
}
@keyframes onboardingBrickEmphasize {
  0%   { transform: scale(1); }
  15%  { transform: scale(1.7); }
  75%  { transform: scale(1.5); }
  100% { transform: scale(1); }
}

/* The played card's brick cost icon bumps each time a flying brick
 * lands on it — short and snappy. */
.onboarding-cost-bump {
  animation: onboardingCostBump 0.32s ease-out;
  display: inline-block;
  transform-origin: center;
}
@keyframes onboardingCostBump {
  0%   { transform: scale(1);   filter: brightness(1); }
  45%  { transform: scale(1.6); filter: brightness(1.6); }
  100% { transform: scale(1);   filter: brightness(1); }
}

/* The flying brick particle itself — JS spawns a styled img and toggles
 * `.flying` on the next frame to animate it. */
.onboarding-flying-brick {
  position: fixed;
  width: 24px;
  height: 24px;
  z-index: 10020;          /* above the spotlight overlay */
  pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.55));
  transition:
    left 0.45s cubic-bezier(0.45, 0.05, 0.55, 0.95),
    top 0.45s cubic-bezier(0.45, 0.05, 0.55, 0.95);
}
.onboarding-flying-brick.landed {
  transition: opacity 0.18s ease;
  opacity: 0;
}

/* ─────────────────────────────────────────────────────────────────────── */
/* OnboardingHand — dedicated layout for the lesson's small hand.
 *
 * The regular .hand uses `flex-grow:1` on every card except :last-child
 * (which is fixed at 100px), so a 2-card hand puts card-0 stretched across
 * ~525px on the left and card-1 fixed at 100px on the right. Worse, the
 * Card component sets `style="flex-grow:1; width:undefined"` inline, which
 * beats any class-based CSS — that's why the previous `.hand:has()` fix
 * didn't work. We override with !important here. */

.onboarding-hand {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10px;
  box-sizing: border-box;
  margin-bottom: 10px;
}

.onboarding-hand-row {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  gap: 18px;
}

/* Beat the inline `style="flex-grow:1; width:undefined"` Card.jsx applies
 * to cards in slots 0-5 (and the `width:100px` it applies to slot 6).
 * Inline style → can only be overridden with !important. */
.onboarding-hand .card-container {
  flex-grow: 0 !important;
  width: 100px !important;
  position: relative;
  isolation: isolate;
}

/* Smooth scale on hover — no layout shift since width is fixed. */
.onboarding-hand .card-container {
  transition: transform 0.2s ease, z-index 0s;
}
.onboarding-hand .card-container:hover,
.onboarding-hand .card-container:focus {
  transform: translateY(-12px) scale(1.06);
  z-index: 10;
}

/* Landscape phones: cards shrink to 70px to mirror the regular hand sizing
 * pattern in landscape-mobile.css. */
@media (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {
  .onboarding-hand .card-container {
    width: 70px !important;
  }
  .onboarding-hand-row {
    gap: 12px;
  }
}

/* Partial onboarding hands (4-6 visible cards) still render through the
 * regular Hand component so mobile can keep its default/coverflow behavior.
 * On wider layouts, JS adds .onboarding-wide-fit when the measured hand width
 * is large enough to show the same centered fixed-width lesson layout. */
.hand.onboarding-wide-fit {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 18px;
}

.hand.onboarding-wide-fit .card-container {
  flex-grow: 0 !important;
  width: 100px !important;
  position: relative;
  isolation: isolate;
}

.hand.onboarding-wide-fit .card-container:hover,
.hand.onboarding-wide-fit .card-container:focus {
  transform: translateY(-12px) scale(1.06);
  z-index: 10;
}

@media (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {
  .hand.onboarding-wide-fit {
    gap: 12px;
  }
  .hand.onboarding-wide-fit .card-container {
    width: 70px !important;
  }
}

/* ─────────────────────────────────────────────────────────────────────── */
/* Onboarding caption — text on the darkened overlay, positioned right next
 * to the highlighted element. The shared speech.jsx bubble is hidden
 * entirely for onboarding; main.js clones its contents into a fresh
 * `#onboarding-caption` element placed near the spotlight target. */

/* Hide the bubble itself while in onboarding mode. The wrapper still
 * exists in the DOM (server-side render needs it as the OOB swap target)
 * but it's visually suppressed. */
.advisor-wrapper[data-tutorial-step^="onboarding-"] {
  display: none !important;
}

/* Just plain text on the dark overlay — no panel, no border, no padding.
 * Matches the look of the academy lightning caption: a warm cream label
 * with a strong text-shadow so it stays readable on top of the dimmed
 * background. The caption is anchored next to the spotlighted target by
 * main.js. */
.onboarding-caption {
  position: fixed;
  z-index: 10013;                     /* above .academy-spotlight-overlay (9000) */
  pointer-events: none;               /* never block the highlighted target */
  max-width: 320px;
  color: #ffe9a8;                     /* warm cream — academy palette */
  font-family: sans-serif;
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.35;
  text-align: center;
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.95),
    0 0 8px rgba(0, 0, 0, 0.75),
    0 0 14px rgba(0, 0, 0, 0.55);
  /* No background, no border, no padding — academy-style floating label. */
  background: transparent;
  border: 0;
  padding: 0;
}
.onboarding-caption .onboarding-caption-text {
  display: block;
}

/* Mobile: anchor to the bottom of the viewport. */
@media (max-width: 600px) {
  .onboarding-caption {
    max-width: calc(100vw - 24px);
    left: 12px !important;
    right: 12px !important;
    top: auto !important;
    bottom: 24px;
    font-size: 1rem;
  }
}
