/* tutorial.css — the guided tutorial's four surfaces (src/client/ui/tutorial/): the lobby "Learn to play" card,
   the in-match coach card, the mission-result screen, and the DOM highlight applied to existing HUD controls.
   Render-only: nothing here is read by the sim. Link this AFTER game.css and lobby.css — the lobby card leans on the
   --lb-* properties #lobby declares, and the in-match card has to win over game.css's #game descendants. */

/* ============================== 1. LOBBY — the second card in #spPanel ============================== */
/* .lb-card-body carries margin-top:-36px so it can ride up over .lb-card-img's fade. This card has NO image, so that
   negative margin would drag the whole body out of the card's top edge and under .lb-chip. Zero it and pay for the
   chip's own height instead (chip: top 12px + ~21px tall). */
#lobby .lb-card-learn .lb-card-body { margin-top: 0; padding-top: 44px; gap: 12px; }
#lobby .lb-card-learn { border-color: rgba(92, 200, 255, .28); }
#lobby .lb-card-learn:hover { border-color: var(--lb-cyan); }
#lobby .lb-card-learn .lb-chip { color: #bfe6ff; border-color: rgba(92, 200, 255, .45); }
#lobby .lb-card-learn .lb-card-sub { min-height: 16px; }

/* completion tick — inline in the heading and in each mission's title, shown by removing [hidden] */
#lobby .lb-done { color: var(--lb-good); font-size: .72em; margin-left: 7px; vertical-align: middle; }
#lobby .lb-done[hidden] { display: none; }

/* mission list: a vertical stack of buttons, each a title line + one line of "what you'll do" */
#lobby .lb-missions { display: flex; flex-direction: column; gap: 7px; }
#lobby .lb-mission {
  display: flex; flex-direction: column; gap: 2px; text-align: left; cursor: pointer;
  background: rgba(255, 255, 255, .03); border: 1px solid var(--lb-line); border-radius: 9px; padding: 9px 12px;
  color: var(--lb-ink); font-family: var(--lb-font);
}
#lobby .lb-mission:hover { border-color: var(--lb-line2); background: rgba(92, 200, 255, .08); }
#lobby .lb-mission:focus-visible { outline: 2px solid var(--lb-cyan); outline-offset: 2px; }
#lobby .lb-mission b { font: 700 13px var(--lb-font); letter-spacing: .02em; }
#lobby .lb-mission span { font: 500 11.5px var(--lb-font); color: var(--lb-muted); }
#lobby .lb-mission[disabled] { opacity: .45; cursor: not-allowed; }   /* a mission the player has not unlocked yet */
#lobby .lb-mission.done b { color: #bdf0d6; }
#lobby #tutResetBtn { align-self: flex-start; padding-left: 0; }      /* .lb-back centres itself; here it hangs off the CTA */
#lobby #tutResetBtn[hidden] { display: none; }

/* ============================== 1b. THE LEADER LINE ==============================
   Drawn from the card to the control the card names (src/client/ui/tutorial/pointer.mjs). z49: under #tutCard (50) so
   the card is never crossed by its own line, over every HUD panel (top is #emojiPicker 48) so the line is not buried
   under the thing it points at. pointer-events:none on the SVG AND on every child — the steps that draw a line are
   the steps that ask the player to click the target. */
#tutLine { position: absolute; inset: 0; z-index: 49; width: 100%; height: 100%; overflow: visible;
  pointer-events: none; }
#tutLine[hidden] { display: none !important; }
#tutLine * { pointer-events: none; vector-effect: non-scaling-stroke; }
#tutLinePath { fill: none; stroke: #5cc8ff; stroke-width: 2; stroke-linecap: round;
  filter: drop-shadow(0 0 6px rgba(92, 200, 255, .55)); }
#tutLineDot { fill: #5cc8ff; }
#tutLineRing { fill: none; stroke: #5cc8ff; stroke-width: 1.5; opacity: .45; }
/* Draw ON, once, when the line moves to a new target. The path carries pathLength="1", so one unit IS the whole line
   however long it happens to be — a fixed pixel dasharray was shorter than a card-to-corner line and left it visibly
   half-drawn. Paired with the camera glide s 620 ms. */
#tutLine.tut-line-in #tutLinePath { stroke-dasharray: 1; animation: tut-draw .42s ease-out forwards; }
#tutLine.tut-line-in #tutLineRing { animation: tut-ring 1.6s ease-in-out .3s infinite; }
@keyframes tut-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes tut-ring { 0%, 100% { r: 9; opacity: .45; } 50% { r: 13; opacity: .12; } }

/* The live reading (#tutVal): the step's own number, as it stands, in the player's own game. Monospace and tabular so
   a value that ticks does not reflow the sentence around it — a number that jitters horizontally is a number nobody
   reads. Given its own weight because it is the sentence that does the teaching, not the prose above it. */
.tut-val { margin: 0; padding: 6px 9px; border-radius: 7px;
  background: rgba(92, 200, 255, .08); border-left: 2px solid #5cc8ff;
  font: 600 12.5px ui-monospace, 'Cascadia Mono', Menlo, monospace; font-variant-numeric: tabular-nums;
  color: #cfe9fb; }
.tut-val[hidden] { display: none; }

/* ============================== 2. IN-MATCH — the coach card ============================== */
/* z-index 50 puts the card over EVERY HUD panel: the ladder in game.css tops out at #emojiPicker 48 (then #actMenu 46,
   .clickFx 45, #boatTip 44, the toasts 42, #spawnBar/#peaceVote 40, #atkForce 36 …). It stays BELOW #overEnd (60) on
   purpose — when the match actually ends, the end screen owns the screen, not the tutor. */
#tutCard {
  position: absolute; z-index: 50; box-sizing: border-box;
  width: min(330px, calc(100vw - 28px));
  background: #101b2e; border: 1px solid #28395a; border-left: 3px solid #5cc8ff; border-radius: 12px;
  padding: 12px 14px 13px; color: #e8eef7;
  font-family: 'Chakra Petch', 'Segoe UI', system-ui, sans-serif;
  box-shadow: 0 14px 38px rgba(0, 0, 0, .55);
  transition: opacity .16s ease, transform .18s ease;
}
/* There is NO scrim and NO cut-out: the card is the only thing that takes a pointer, so the map, the attack slider and
   every panel the step is TALKING about stay clickable underneath it. */
#tutCard { pointer-events: auto; }
/* If this stylesheet 404s, an unhidden absolute card is a nuisance; an unhidden #tutEnd (inset:0, opaque) would cover
   every live match. #leaderPage already shipped exactly that bug, so both surfaces carry their own !important hide. */
#tutCard[hidden] { display: none !important; }

/* ---- placement: one rule per data-card value, set by the step definition ---- */
#tutCard[data-card="left"]   { left: 14px;  top: 50%; transform: translateY(-50%); }
/* 88px, not 14px, and this is a bug fix rather than a margin. #zoom is right:18px and 54px wide (game.css), i.e. it
   occupies 18-72px from the right edge at exactly this vertical position — so a right-slotted card at 14px sits ON
   the + and − buttons at z50 against their z16, and elementFromPoint at #zIn's own centre returned the card at both
   1280x800 and 1024x640. Seven steps use this slot, including the two that ask the player to click a marked island
   and a marked teammate. There used to be a [data-spot="zoom"] variant holding 88px for this case; it was dead code,
   because the one step that highlights the zoom column is left-slotted. The whole slot clears the column now. */
#tutCard[data-card="right"]  { right: 88px; top: 50%; transform: translateY(-50%); }
#tutCard[data-card="top"]    { top: 100px;  left: 50%; transform: translateX(-50%); }   /* clears #balbar + #atkForce (top 62) */
#tutCard[data-card="bottom"] { bottom: 84px; left: 50%; transform: translateX(-50%); }  /* clears #atk (bottom 14 + 44 tall) */
#tutCard[data-card="center"] { top: 50%; left: 50%; transform: translate(-50%, -50%); }
/* DOCKED: the card has been placed against the element it explains (pointer.mjs dockCard), so its position comes from
   inline left/top and nothing here may fight it. The named slots above are the fallback, for steps whose subject is
   the MAP rather than a control — and for touch, where the card is a full-width sheet with nowhere to dock. */
/* ⚠ AND NO TRANSFORM TRANSITION WHILE DOCKED. Every slot above positions the card with a translate; docking
   positions it with left/top and cancels the translate. With `transition: transform .18s` still in force, that
   cancellation ANIMATES — so for 180ms the card is drawn up to 165px left and 105px above where its own geometry
   says it is, and pointer.mjs measures it in exactly that window. Measured: the reserve card reported a box whose
   bottom was 109px when it was really at 12px, and the leader line was drawn from a point in open space. */
#tutCard[data-card="dock"] { transform: none; transition: opacity .16s ease; }

/* ---- yielded: the action menu or the emoji picker opened UNDER the card. Fade rather than hide, so the player keeps
   the sentence they were reading, and drop pointer-events so the card cannot eat the tap it just asked for. ---- */
#tutCard.tut-yield { opacity: .22; pointer-events: none; }

/* ---- head: chapter · counter · overflow ---- */
.tut-hd { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
.tut-ch { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font: 700 10px 'Chakra Petch', sans-serif; letter-spacing: .14em; text-transform: uppercase; color: #5cc8ff; }
.tut-count { font: 700 11px ui-monospace, monospace; color: #6f82a0; font-variant-numeric: tabular-nums; }
#tutMenuBtn { background: none; border: none; color: #8da2be; font: 700 16px system-ui; line-height: 1;
  padding: 0 2px; cursor: pointer; }
#tutMenuBtn:hover { color: #fff; }

.tut-ttl  { margin: 0 0 5px; font: 700 16px 'Chakra Petch', system-ui; color: #fff; letter-spacing: .01em; }
.tut-body { margin: 0; font: 500 13.5px/1.5 'Chakra Petch', system-ui; color: #cdd9ea; }
/* the hint is the second-chance line ("stuck? try…") — amber so it reads as a different voice from the instruction */
.tut-hint { margin: 9px 0 0; padding: 7px 10px; border-left: 2px solid rgba(224, 162, 58, .55);
  background: rgba(224, 162, 58, .1); border-radius: 0 7px 7px 0;
  font: 500 12.5px/1.45 'Chakra Petch', system-ui; color: #e8c07a; }
.tut-hint[hidden] { display: none; }

/* ---- progress meter for "do it N times" objectives; same shape as .pv-track so it reads as the same product ---- */
.tut-meter { position: relative; height: 22px; margin-top: 10px; background: #0c1424; border: 1px solid #1d2c45;
  border-radius: 6px; overflow: hidden; }
.tut-meter[hidden] { display: none; }
.tut-fill { position: absolute; inset: 0 auto 0 0; width: 0%; background: #2a6f8e; transition: width .18s linear; }
/* ⚠ A BINARY OBJECTIVE GETS A READOUT, NOT A PROGRESS BAR. "Wipe out Rook" has no partial credit before you engage
   him, so every bar drawn for it has been a lie in one direction or the other (see the note in missions.mjs). A row
   that declares a LABEL but no METER keeps the number and loses the track. */
.tut-meter[data-bar="none"] { background: #0a1120; border-color: #16243a; }
.tut-meter[data-bar="none"] .tut-fill { display: none; }
.tut-lab { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font: 700 11px ui-monospace, monospace; color: #fff; text-shadow: 0 1px 2px #000; pointer-events: none; }

/* ---- actions ---- */
.tut-act { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.tut-ghost, .tut-go { border-radius: 8px; padding: 8px 14px; min-height: 34px;
  font: 700 12.5px 'Chakra Petch', system-ui; cursor: pointer; }
.tut-ghost { background: rgba(255, 255, 255, .06); border: 1px solid #28395a; color: #9fb2cc; }
.tut-ghost:hover { background: rgba(255, 255, 255, .12); color: #fff; }
.tut-ghost[hidden] { display: none; }
.tut-ghost[disabled] { opacity: .4; cursor: not-allowed; pointer-events: none; }
.tut-go { margin-left: auto; background: #2f86d6; border: 1px solid #2f86d6; color: #fff; }
.tut-go:hover { background: #3a97ea; }
/* "Continue" while the objective is unmet: still visible, obviously inert — a greyed button the player can see is a
   promise the step will end, where a hidden one reads as a dead tutorial. */
.tut-go[disabled] { background: #1e2c44; border-color: #24344f; color: #6f86a6; cursor: not-allowed; }
#tutCard button:focus-visible { outline: 2px solid #5cc8ff; outline-offset: 2px; }

/* ---- ⋯ overflow menu, anchored inside the card so it inherits its stacking position ---- */
#tutMenu { position: absolute; top: 34px; right: 10px; z-index: 1; display: flex; flex-direction: column;
  min-width: 186px; background: #0c1424; border: 1px solid #28395a; border-radius: 9px; overflow: hidden;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .6); }
#tutMenu[hidden] { display: none !important; }
#tutMenu button { background: none; border: none; border-bottom: 1px solid #1d2c45; color: #cdd9ea;
  padding: 10px 13px; min-height: 40px; text-align: left; font: 600 12.5px 'Chakra Petch', system-ui; cursor: pointer; }
#tutMenu button:last-child { border-bottom: none; }
#tutMenu button:hover { background: rgba(255, 255, 255, .07); color: #fff; }
#tutMQuit:hover { background: rgba(224, 83, 61, .35); color: #fff; }

/* ============================== 3. IN-MATCH — the mission result ============================== */
/* 62 is ABOVE #overEnd (60): a tutorial mission can end because the underlying match ended, and the player must see
   "mission complete / retry", not the generic victory screen with the tutor's buttons trapped behind it. */
#tutEnd {
  position: absolute; inset: 0; z-index: 62; background: rgba(10, 11, 14, .93);
  color: #e8eef7; font-family: 'Chakra Petch', 'Segoe UI', system-ui, sans-serif;
  animation: tut-fade .25s ease-out;
}
#tutEnd[hidden] { display: none !important; }
#tutEnd .mid { position: absolute; top: 40%; left: 50%; transform: translate(-50%, -50%);
  text-align: center; width: min(560px, 92%); }
#tutEnd .ttl { font: 800 clamp(30px, 6vw, 50px) 'Chakra Petch', system-ui; letter-spacing: .02em;
  margin-bottom: 10px; color: #f0d889; text-shadow: 0 6px 30px #000; }
#tutEnd .sub { color: #cdd3df; font-size: clamp(14px, 2.4vw, 18px); line-height: 1.5; }
#tutEnd.fail .ttl { color: #e2624a; }
.tut-end-act { position: absolute; bottom: 12%; left: 50%; transform: translateX(-50%);
  display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; width: min(560px, 92%); }
.tut-end-act button { border: 1px solid #28395a; border-radius: 10px; background: rgba(255, 255, 255, .07);
  color: #cdd9ea; padding: 12px 22px; min-height: 44px; font: 700 14px 'Chakra Petch', system-ui; cursor: pointer; }
.tut-end-act button:hover { background: rgba(255, 255, 255, .14); color: #fff; }
.tut-end-act button:focus-visible { outline: 2px solid #5cc8ff; outline-offset: 2px; }
#tutNextMis { background: #2f86d6; border-color: #2f86d6; color: #fff; }
#tutNextMis:hover { background: #3a97ea; }
#tutNextMis[hidden], #tutRetry[hidden] { display: none; }
@keyframes tut-fade { from { opacity: 0; } to { opacity: 1; } }

/* ============================== 4. THE DOM HIGHLIGHT ============================== */
/* .tut-spot is stamped on elements this stylesheet does NOT own (#atk, #zoom, #leaveBtn, a leaderboard row, a chat tab).
   It is therefore restricted to outline + box-shadow + border-radius, all of which paint outside the border box:
     · no position / margin / padding / width  -> it cannot reflow the HUD it is pointing at (a highlight that moves the
       button is a highlight that teaches the wrong place to press);
     · no z-index / transform / opacity / filter / will-change -> none of those create a stacking context here, so the
       target keeps its own place in the ladder and elementFromPoint(centre) still returns the control, not the tutor.
   The pulse animates box-shadow only, for the same reason. */
.tut-spot {
  outline: 2px solid #5cc8ff; outline-offset: 3px; border-radius: 10px;
  box-shadow: 0 0 0 3px rgba(92, 200, 255, .2), 0 0 22px 4px rgba(92, 200, 255, .4);
  animation: tut-pulse 1.5s ease-in-out infinite;
}
@keyframes tut-pulse {
  50% { box-shadow: 0 0 0 6px rgba(92, 200, 255, .08), 0 0 30px 8px rgba(92, 200, 255, .62); }
}

/* ============================== 5. TOUCH ============================== */
/* Gated on html.is-touch (main.mjs sets it from pointer:coarse), never on a width query: a phone in LANDSCAPE is 844px
   wide and every max-width rule this project ever wrote missed it, handing a thumb the desktop HUD. See game.css §TOUCH. */
html.is-touch #tutCard {
  left: 8px; right: 8px; width: auto; top: auto;
  bottom: calc(96px + env(safe-area-inset-bottom));   /* above #atk (10px) and #atkChips (54px), both safe-area-shifted */
  transform: none; max-height: 38vh; overflow: auto; -webkit-overflow-scrolling: touch;
  padding: 11px 13px 12px;
}
/* When the step is pointing at the bottom furniture, a bottom sheet is standing ON the answer. Go to the top instead —
   #balbar shrinks on touch and #atkForce tucks under it, so the top strip is the free one. */
html.is-touch #tutCard[data-spot="atk"],
html.is-touch #tutCard[data-spot="atkchips"],
html.is-touch #tutCard[data-spot="zoom"] {
  top: calc(64px + env(safe-area-inset-top)); bottom: auto; max-height: 34vh;
}
html.is-touch #tutCard button { min-height: 44px; min-width: 44px; }
html.is-touch #tutMenuBtn { padding: 0 10px; }
html.is-touch .tut-act { gap: 10px; }
html.is-touch .tut-ttl { font-size: 15px; }
html.is-touch #tutMenu { right: 8px; min-width: 200px; }
html.is-touch #tutMenu button { min-height: 46px; }
html.is-touch #tutEnd .mid { top: 36%; }
html.is-touch .tut-end-act { bottom: calc(8% + env(safe-area-inset-bottom)); }
html.is-touch .tut-spot { outline-width: 3px; }   /* a 2px ring is invisible under a finger at arm's length */

/* ============================== 6. REDUCED MOTION ============================== */
/* The pulse and the card's slide are decoration; the ring and the placement carry the meaning, so only the movement goes. */
@media (prefers-reduced-motion: reduce) {
  .tut-spot { animation: none; }
  #tutCard { transition: none; }
  #tutEnd { animation: none; }
  .tut-fill { transition: none; }
}
