/* ── Guided onboarding (js/onboarding.js) ───────────────────────────────────────
   Blocking panel for FROZEN beats + a small non-blocking banner for LIVE beats. Sized so the
   Continue button never falls off a 360x640 phone (bodies are kept to ~2 short paragraphs).

   This lives in a REAL stylesheet (not inline in the html) so build.sh can cache-bust it with
   ?v=<sha> like the js. Inline css rides on the html, which is only `no-cache` — an edge/browser
   copy could still serve the OLD css beside the NEW js, which is exactly how a fixed layout came
   back as the blocking modal on the deployed dev site. Shared verbatim by index.html and
   mobile/index.html (identical rules; onboarding.js sizes itself at runtime). */
/* z-index 15: ABOVE the map and the top bars (10) it docks beneath, but BELOW every menu and overlay.
   The lowest of those is the job overlay at 20 (then research 22, defeat/victory 25, prestige 30,
   settings 35, feedback 36, achievements 40, start menu 50, confirm 55, loading 60, guides 100, save
   string 4000; the mobile shell puts its sheets at 3900+ and re-stamps job/defeat/victory/guide at
   5000). So opening ANY menu covers the lesson instead of the lesson covering the menu. It used to sit
   at 5200, on top of the lot, which is how it ended up over the Settings sheet and its New Game button.
   Onboarding._applySpark keeps the mobile Build button (3800) above the lesson too, which is fine: the
   lesson is docked at the top and that button is bottom-left, so they never overlap. */
#onb-overlay {
  position: fixed; left: 0; right: 0; top: 0; z-index: 15;
  display: flex; justify-content: center;
  padding: 0 10px; box-sizing: border-box;
  /* NO backdrop and NO pointer capture: a lesson that says "click the forest" must not cover or
     swallow the map. Only the panel itself takes clicks (see #onb-panel). */
  pointer-events: none; background: none;
}
/* ── ONE LOOK, TWO CHAINS ─────────────────────────────────────────────────────
   Every rule below names BOTH the opening chain's card (#onb-panel, js/onboarding.js) and a later
   lesson's (#les-banner, js/lessons.js). They are two nodes because they behave differently — the
   opening chain freezes the world and cannot be dismissed; a lesson lets the year run and carries a
   close cross — but they must never LOOK different, and when the lesson had its own block of CSS in
   index.html they drifted into two visibly different tutorials: warm brown against cool purple,
   560px against 430px, 21/17px type against 18/14px, and docked over the top bar instead of over the
   map. Keep the shared frame here; put only genuine differences in the #les-banner-only rules. */
#onb-panel,
#les-banner {
  width: min(94vw, 430px); box-sizing: border-box;
  background: rgba(20,18,28,0.96); border: 2px solid var(--gold-dim);
  padding: 10px 14px 12px; color: var(--text);
  box-shadow: 0 6px 18px rgba(0,0,0,0.55), 0 0 0 1px #07060b;
  font-family: 'VT323','Courier New',monospace;
}
#onb-panel { pointer-events: auto; max-height: 46vh; overflow-y: auto; }
/* A TASK beat is deliberately smaller + more transparent — the map behind it is the subject. */
#onb-overlay.onb-task #onb-panel { max-height: 34vh; background: rgba(20,18,28,0.9); }
#onb-title,
#les-banner .les-title { font-size: 21.5px; color: var(--gold); margin: 0 0 4px; letter-spacing: 0.04em; display: block; font-weight: normal; }
#onb-body p,
#les-banner .les-body p { font-size: 17px; line-height: 1.28; margin: 0 0 6px; color: var(--text); }
#onb-body .onb-count { color: var(--gold); font-size: 19px; margin-top: 2px; }
#onb-lore,
#les-banner .les-lore { font-size: 15px; font-style: italic; color: var(--ghost); margin: 6px 0 8px; line-height: 1.22; }
#onb-foot,
#les-banner .les-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
#onb-step,
#les-banner .les-step { font-size: 15px; color: var(--ghost); }
#onb-next,
#les-banner .les-go {
  background: var(--gold-dim); color: var(--text); border: 1px solid var(--gold);
  font-family: inherit; font-size: 18px; padding: 6px 15px; cursor: pointer;
}
#onb-next:hover,
#les-banner .les-go:hover { background: rgba(200,160,64,0.3); }

/* ── What is genuinely different about a later lesson ──────────────────────────
   It is docked by js/lessons.js with the same _dockTop() measurement the opening card uses (forced
   inline, so a stale cached stylesheet cannot move it back over the top bar). It never pauses the
   game, so it must not eat clicks either: the card is pointer-transparent and only its own two
   buttons take events, leaving the map underneath live. And it CAN be dismissed, which the opening
   chain cannot — hence the close cross and the padding that keeps the title clear of it. */
#les-banner {
  position: fixed; left: 50%; transform: translateX(-50%);
  z-index: 15; display: none; pointer-events: none;
  padding-right: 40px;
}
#les-banner button { pointer-events: auto; }
#les-banner .les-hint { font-size: 17px; color: var(--gold); margin: 0 0 6px; line-height: 1.28; }
#les-banner .les-x {
  position: absolute; top: 6px; right: 8px; width: 24px; height: 24px; line-height: 1;
  font-family: inherit; font-size: 18px; cursor: pointer;
  color: var(--ghost); background: none; border: 1px solid transparent;
}
#les-banner .les-x:hover { color: var(--gold); border-color: var(--gold-dim); }
#onb-banner {
  position: fixed; z-index: 14; left: 50%; transform: translateX(-50%);   /* under the panel, under every menu */
  max-width: min(92vw, 460px); box-sizing: border-box;
  background: #14121c; border: 1px solid var(--gold); border-left: 4px solid var(--gold);
  padding: 6px 12px; color: var(--text); font-family: 'VT323','Courier New',monospace;
  box-shadow: 3px 3px 0 rgba(0,0,0,0.5); pointer-events: none;
}
#onb-banner-title { display: block; font-size: 18px; color: var(--gold); letter-spacing: 0.04em; }
#onb-banner-hint { display: block; font-size: 17px; color: var(--text); opacity: 0.9; }

/* A south-docked lesson (Onboarding sets this while a `dock: 'bottom'` beat is showing) sits where the
   mobile Build button lives, so the button gets out of its way. Hidden rather than painted over: the
   lesson deliberately sits BELOW everything in the 3800+ band so a menu always wins over it, and the
   one beat that docks here is the opening wood lesson, where there is not a resource to build with
   anyway. The class is cleared everywhere the panel hides, so the button can never stay lost. */
body.onb-dock-bottom #mproto-build-fab { display: none !important; }

/* Spark: applied by Onboarding._applySpark to the route to a build the current lesson is asking for —
   the mobile Build button and the specific build card. box-shadow only, so it cannot shift layout or
   cover a neighbouring card, and it sits on top of whatever border/shadow the target already has. */
@keyframes onb-spark {
  0%, 100% { box-shadow: 0 0 0 1px rgba(232,196,96,0.5),  0 0 5px 0 rgba(232,196,96,0.28); }
  50%      { box-shadow: 0 0 0 2px rgba(255,224,140,0.95), 0 0 16px 4px rgba(232,196,96,0.6); }
}
.onb-spark { animation: onb-spark 1.1s ease-in-out infinite; position: relative; z-index: 2; }
/* Still clearly marked, just not moving, for anyone who asked the OS for less motion. */
@media (prefers-reduced-motion: reduce) {
  .onb-spark { animation: none; box-shadow: 0 0 0 2px rgba(255,224,140,0.9), 0 0 12px 2px rgba(232,196,96,0.5); }
}

/* ── Not yet yours ────────────────────────────────────────────────────────────
   Two shapes of "the lesson has not handed you this yet", both GREYED rather than hidden, so the
   player reads them as coming rather than missing.

   .onb-locked — a sidebar tab and its panel before the beat that teaches it (updateSidebarTabVisibility
   in ui.js; only Jobs uses it today, because Jobs is the one tab that can never be display:none — it is
   what the hidden-tab fallback falls back to).

   .onb-blocked — a control the lesson has taken away for the length of a beat (Onboarding._applyGates).
   Hold the Pass during the deployment lessons: starting the battle there hides the squad board and the
   Squads button with it, stranding every squad objective for the rest of the fight.
   pointer-events is the visual half only — a programmatic .click() ignores it, so the click handlers
   guard themselves as well (combat.js, tryMenuConfirm in loop.js). */
.sidebar-tab.onb-locked,
.tab-panel.onb-locked,
#begin-battle-btn.onb-blocked {
  filter: grayscale(1);
  pointer-events: none;
  cursor: default;
}
.sidebar-tab.onb-locked { opacity: 0.34; }
.tab-panel.onb-locked   { opacity: 0.3; user-select: none; }
/* A build card the current beat is not asking for (Onboarding.buildLock). NOT pointer-events:none —
   the card must still take the press so it can answer "not for this lesson" instead of feeling dead,
   and the handler refuses the build itself. */
.build-card.onb-locked {
  filter: grayscale(1);
  opacity: 0.32;
  cursor: default;
}
#begin-battle-btn.onb-blocked { opacity: 0.4; box-shadow: none; }
/* The gold "click me next" glint sweep lives on the button's ::after, NOT on the button, so silencing
   it has to name the pseudo-element — killing the animation on the element itself leaves a blocked
   button still flashing an invitation to press it. !important because index.html's own ::after rule
   is inline in the html and this stylesheet cannot rely on load order beating it. */
#begin-battle-btn.onb-blocked::after { animation: none !important; opacity: 0 !important; }
