/* ══════════════════════════════════════════════════════════════════════════
   Onboarding, 2026-09-22 — the first run after signup
   ──────────────────────────────────────────────────────────────────────────
   Five steps over the live app rather than a slideshow beside it: the reader
   does the thing on the real control, and the tour only darkens everything
   that is not the control in question.

   A file of its own for the same reason chrome.css is one — every rule here
   is additive, nothing in style.css or chrome.css is edited, and it loads
   last so equal specificity resolves this way.

   Colours come from the :root tokens in style.css. Where a weight is needed
   that the palette does not name, color-mix derives it rather than inventing
   a hex — there is no success green here, so a completed task is stated in
   --brand, which is the palette's own "this is true" colour.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  --ob-card-w: 372px;
  --ob-gap: 14px;               /* card to spotlight */
  --ob-dim: 0.66;               /* how dark the rest of the app goes */
}

/* ── 1. The spotlight ──────────────────────────────────────────────────────
   One SVG over the whole window: a dark rect with a mask, and a hole in the
   mask per target. The contrast between the lit area and the dark around
   it is the main signal — but the card is parked centre-window (see below),
   so a control lit only at the edge of the screen, with the map still
   animating behind everything, needs a second, deliberately loud signal: a
   ring that swings hard between a thin dim line and a thick bright glow,
   rather than a subtle breathe — a small change was still losing to the
   map's own motion.

   A mask rather than a ring of four divs or a giant
   box-shadow because a step can highlight TWO things at once (the button
   that opens a pane, and the pane it opened) and overlapping box-shadows
   would darken each other's holes.

   pointer-events: none throughout — the app underneath stays live, which is
   the whole point of asking the reader to do the task on it. */

#eik-ob-scrim {
  position: fixed; inset: 0; z-index: 100;
  pointer-events: none;
  width: 100%; height: 100%;
  /* The layer fades OUT, swaps which holes it carries while nobody can see
     it, and fades back IN. Cheaper to follow than a hole sliding across the
     window, and it removes the whole class of problems that came with
     easing a shape between two unrelated targets. */
  transition: opacity .2s ease;
}
#eik-ob-scrim.ob-out { opacity: 0; }
#eik-ob-scrim .ob-dim { fill: var(--brand-deep); fill-opacity: var(--ob-dim); }
#eik-ob-scrim .ob-hole { fill: #000; }        /* black in a mask = cut away */
/* Drawn over the dim layer, not into the mask, so it reads as a ring on
   the lit control rather than a second cut. transform-box so the growth
   scales from the ring's own centre, not the SVG's 0,0 corner. */
#eik-ob-scrim .ob-hole-ring {
  stroke: var(--brand);
  transform-box: fill-box; transform-origin: center;
  animation: eik-ob-pulse 1.1s ease-in-out infinite;
}
@keyframes eik-ob-pulse {
  0%, 100% {
    stroke-width: 2px; stroke-opacity: .35; transform: scale(1);
    filter: drop-shadow(0 0 0 color-mix(in srgb, var(--brand) 75%, transparent));
  }
  50% {
    stroke-width: 7px; stroke-opacity: 1; transform: scale(1.05);
    filter: drop-shadow(0 0 16px color-mix(in srgb, var(--brand) 75%, transparent));
  }
}

/* The holes themselves are never animated. Between steps they are re-cut
   while the layer is transparent; within a step they are re-measured every
   frame and set directly, so a hole stays welded to a control that moves
   under it (a drawer sliding in, a resize) with no lag at all. */

/* ── 2. The card ───────────────────────────────────────────────────────────
   Placed beside whatever is lit, on the side with the most room. */

#eik-ob-card {
  position: fixed; z-index: 101;
  width: var(--ob-card-w); max-width: calc(100vw - 32px);
  box-sizing: border-box;
  background: var(--surface); color: var(--text);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  box-shadow: 0 18px 48px rgba(5,28,35,.28), 0 2px 6px rgba(5,28,35,.12);
  font-family: var(--font-sans);
  padding: 18px 20px 16px;
  display: flex; flex-direction: column;
}
/* The entrance fades in from a CLASS the JS takes off again on a timer, so
   the resting state — no class — is the visible one. Fading from opacity 0
   on the base rule looked equivalent and is not: an animation only advances
   while the page is compositing, so a tour opened in a tab that is not
   drawing frames holds its first keyframe and the whole thing is invisible
   with no way back. setTimeout keeps running when the compositor does not,
   which makes removal the reliable direction. */
@keyframes eik-ob-in { from { opacity: 0; } to { opacity: 1; } }
#eik-ob-card.ob-fresh { animation: eik-ob-in .22s ease; }

/* Docked in a corner of an open page: the task line says what to do there,
   so the blurb the reader already read goes, and the card covers less. */
#eik-ob-card.ob-docked .ob-blurb { display: none; }
#eik-ob-card.ob-docked .ob-name { margin-bottom: 8px; }
#eik-ob-card.ob-docked .ob-foot { padding-top: 10px; }

/* head — the count, and the way out */
.ob-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.ob-count {
  font-family: var(--font-mono);
  font-size: 12px; font-weight: 600; letter-spacing: .04em;
  color: var(--brand); white-space: nowrap;
}
.ob-x {
  margin-left: auto; flex: none;
  width: 26px; height: 26px; border: 0; border-radius: 50%;
  background: transparent; color: var(--text-muted);
  font-size: 19px; line-height: 1; cursor: pointer;
}
.ob-x:hover { background: var(--surface-grey); color: var(--text); }

/* the six pips: where you are, and what you did when you were there */
.ob-pips { display: flex; gap: 4px; margin-bottom: 14px; }
.ob-pip {
  height: 3px; flex: 1; border-radius: 2px;
  background: color-mix(in srgb, var(--text) 12%, transparent);
  transition: background .25s ease;
}
.ob-pip[data-state="now"]  { background: var(--brand); }
.ob-pip[data-state="done"] { background: var(--brand-line); }
.ob-pip[data-state="skipped"] {
  background: repeating-linear-gradient(90deg,
    color-mix(in srgb, var(--text) 26%, transparent) 0 3px,
    transparent 3px 6px);
}

/* body — the feature, and what it is for */
.ob-name {
  font-family: var(--font-display);
  font-size: 19px; line-height: 1.25; font-weight: 600;
  margin: 0 0 6px;
}
/* The step name takes the focus only so that a screen reader starts there; it is not a control. */
.ob-name:focus { outline: none; }
.ob-blurb {
  font-size: 13.5px; line-height: 1.5; color: var(--text-body);
  margin: 0 0 14px;
}

/* the task */
.ob-task {
  display: flex; gap: 10px; align-items: flex-start;
  background: var(--surface-stone);
  border: 1px solid var(--border-soft);
  border-radius: 8px; padding: 11px 12px;
  transition: background .3s ease, border-color .3s ease;
}
.ob-tick {
  flex: none; width: 18px; height: 18px; margin-top: 1px;
  border-radius: 50%;
  border: 1.5px solid color-mix(in srgb, var(--text) 30%, transparent);
  display: grid; place-items: center;
  transition: background .3s ease, border-color .3s ease;
}
.ob-tick svg { width: 11px; height: 11px; opacity: 0; transition: opacity .2s ease .08s; }
.ob-tick svg path { stroke: var(--surface); stroke-width: 2.6; fill: none;
  stroke-linecap: round; stroke-linejoin: round; }
.ob-tasktext { font-size: 13px; line-height: 1.45; }
.ob-tasklabel {
  display: block; font-size: 10.5px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-muted); margin-bottom: 3px;
}
.ob-tasklabel:empty { display: none; }

/* done — stated three ways at once, because this is the moment the tour has
   to be unambiguous about: the ground, the tick, and the words. */
.ob-task[data-done="1"] {
  background: var(--brand-soft);
  border-color: color-mix(in srgb, var(--brand-line) 40%, transparent);
}
.ob-task[data-done="1"] .ob-tick { background: var(--brand); border-color: var(--brand); }
.ob-task[data-done="1"] .ob-tick svg { opacity: 1; }
.ob-task[data-done="1"] .ob-tasklabel { color: var(--brand); }
.ob-task[data-done="1"] .ob-todo { display: none; }
.ob-praise { display: none; color: var(--text); }
.ob-task[data-done="1"] .ob-praise { display: block; }

/* foot — back on the left, next on the right.
   margin-top:auto pins it to the bottom of the card. */
.ob-foot { display: flex; align-items: center; gap: 2px;
  margin-top: auto; padding-top: 14px; }
.ob-btn {
  font: inherit; font-size: 13px; font-weight: 500;
  border-radius: 7px; padding: 8px 15px; cursor: pointer;
  border: 1px solid transparent; background: transparent;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.ob-back { color: var(--text-muted); padding-left: 0; padding-right: 10px; }
.ob-back:hover { color: var(--text); }
.ob-back[hidden] { display: none; }
.ob-go {
  margin-left: auto;
  background: var(--brand); color: var(--surface);
  border-color: var(--brand);
}
.ob-go:hover { background: var(--brand-line); border-color: var(--brand-line); }

/* The map's own intro card sits where the first step's card wants to be, so
   it stands down for the duration. onboarding.js also presses its dismiss
   button, so the app's state agrees with what is on screen. */
body.eik-ob-live #orient { display: none; }

/* ── 4. The replay ─────────────────────────────────────────────────────────
   An item in the account menu, so the tour can be taken again. */
#eik-ob-replay { cursor: pointer; }

/* ── 5. Narrow windows and reduced motion ──────────────────────────────────
   The app already says it is best on a desktop; the tour does not add a
   second opinion, it just stops trying to sit beside things and centres. */
@media (max-width: 900px) {
  #eik-ob-card { width: calc(100vw - 24px); }
}
@media (prefers-reduced-motion: reduce) {
  #eik-ob-card.ob-fresh { animation: none; }
  #eik-ob-scrim { transition: none; }
  #eik-ob-scrim .ob-hole-ring { animation: none; stroke-width: 4px; stroke-opacity: 1; }
}
