/*
  Onboarding Beacons
  ==================
  Numbered, gently-pulsing dots that draw attention to features without
  blocking interaction. Hovering opens a sleek popover with an accented
  title strip, paragraph, optional bullets, and prev/next navigation.

  Z-INDEX HIERARCHY
  - .onboarding-beacon: 50 (above content, below tooltips)
  - .onboarding-popover-backdrop: 99998
  - .onboarding-popover: 99999 (above the help-tooltip backdrop)

  Color tokens reuse existing CSS variables when available so the beacons
  pick up theme changes (light/dark) automatically.
*/

/* -----------------------------------------------------------------------
   Header pill toggle
   ----------------------------------------------------------------------- */

.onboarding-tips-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  /* Sized to match the icon-only buttons (.icon-btn) sitting beside it
     in the header so the row of utilities reads as a single visual
     family rather than this one chunk standing out. */
  padding: 0.25rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--border, rgba(0, 0, 0, 0.12));
  background: var(--bg, #ffffff);
  color: var(--text, #1f2937);
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease, color 160ms ease, box-shadow 160ms ease;
}

.onboarding-tips-toggle i {
  width: 12px;
  height: 12px;
  flex: 0 0 auto;
}

.onboarding-tips-toggle:hover {
  border-color: var(--accent, #6366f1);
  color: var(--accent, #6366f1);
}

.onboarding-tips-toggle.is-on {
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.12), rgba(139, 92, 246, 0.12));
  border-color: rgba(99, 102, 241, 0.45);
  color: var(--accent, #6366f1);
  box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.08);
}

.onboarding-tips-toggle.is-on:hover {
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.18), rgba(139, 92, 246, 0.18));
}

/* -----------------------------------------------------------------------
   Beacons
   -----------------------------------------------------------------------
   The beacon is a 22px dot with two concentric pulse rings behind it.
   The pulses are pure CSS keyframe animations, lightweight enough to run
   continuously without affecting interaction.
*/

.has-onboarding-beacon {
  /* Anchors need a positioning context so the beacon can sit on a
     corner. We avoid touching anchors that are already positioned by
     using the lighter-weight `position: relative` only when not set. */
  position: relative;
}

.onboarding-beacon {
  position: absolute;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
  cursor: pointer;
  /* Default placement is top-right, just hanging off the corner of the
     anchor so it doesn't cover content. Overridden by data-placement. */
  top: -8px;
  right: -8px;
  pointer-events: auto;
}

.onboarding-beacon[data-placement="top-left"] {
  top: -8px;
  left: -8px;
  right: auto;
}
.onboarding-beacon[data-placement="bottom-right"] {
  bottom: -8px;
  right: -8px;
  top: auto;
}
.onboarding-beacon[data-placement="bottom-left"] {
  bottom: -8px;
  left: -8px;
  top: auto;
  right: auto;
}
/* Inline-end places the dot to the right of the anchor instead of on
   top of it. Useful for anchors inside a flex row where the corner
   would clip neighbours. */
.onboarding-beacon[data-placement="inline-end"] {
  position: relative;
  display: inline-flex;
  margin-left: 6px;
  top: 0;
  right: 0;
  vertical-align: middle;
}

/* Floating mode: beacon lives on document.body and tracks its anchor's
   bounding rect on scroll/resize. Used for anchors that can't reliably
   host an absolutely-positioned child (table cells, thead, table rows).
   Top/left are set inline by JS; we just override the positioning model
   here so the inline values are interpreted against the viewport. */
.onboarding-beacon.is-floating {
  position: fixed;
  top: 0;
  left: 0;
  right: auto;
  bottom: auto;
  /* Floating beacons sit above table headers but below modals/tooltips.
     Bumped from 50 because table headers often use sticky positioning
     with a higher stacking context. */
  z-index: 60;
}

/* Floating-mode placement variants are positioned entirely by JS (top/left
   inline styles), so no per-placement positional rules are needed here.
   We still want the inline-end variant to drop its left margin since
   the JS positions the beacon to the right of the anchor explicitly. */
.onboarding-beacon.is-floating[data-placement="inline-end"] {
  position: fixed;
  display: inline-flex;
  margin-left: 0;
}

/* The dot itself: small, brand-colored, with a clear number. */
.onboarding-beacon-dot {
  position: relative;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  color: #ffffff;
  font-size: 11px;
  font-weight: 700;
  line-height: 22px;
  text-align: center;
  box-shadow: 0 2px 6px rgba(99, 102, 241, 0.45), inset 0 0 0 1.5px rgba(255, 255, 255, 0.85);
  z-index: 2;
  transition: transform 160ms ease, box-shadow 160ms ease;
}

.onboarding-beacon:hover .onboarding-beacon-dot,
.onboarding-beacon.is-active .onboarding-beacon-dot {
  transform: scale(1.08);
  box-shadow: 0 3px 10px rgba(99, 102, 241, 0.55), inset 0 0 0 1.5px rgba(255, 255, 255, 1);
}

/* -----------------------------------------------------------------------
   Icon beacon variants ('bulb' and 'brain')
   -----------------------------------------------------------------------
   These styles share the same anchor shell as the dot variant but swap
   the centered numeric circle for a brand-coloured icon plus a small
   numbered badge tucked into the bottom-right. The icon and badge
   together still register as "tip #N" but feel more inspiring than a
   bare numeric chip.

   The .onboarding-beacon[data-beacon-style="bulb|brain"] selector lets
   the same outer animations (pulse rings, hover scale) keep working.
   We bump the beacon's outer hit area slightly so the icon has room to
   breathe without changing the anchor's offset rules.
*/

.onboarding-beacon[data-beacon-style="bulb"],
.onboarding-beacon[data-beacon-style="brain"] {
  width: 28px;
  height: 28px;
  /* Nudge slightly further off the anchor corner so the larger icon
     does not clip neighbouring content. */
  top: -10px;
  right: -10px;
}

.onboarding-beacon[data-beacon-style="bulb"][data-placement="top-left"],
.onboarding-beacon[data-beacon-style="brain"][data-placement="top-left"] {
  top: -10px;
  left: -10px;
}
.onboarding-beacon[data-beacon-style="bulb"][data-placement="bottom-right"],
.onboarding-beacon[data-beacon-style="brain"][data-placement="bottom-right"] {
  bottom: -10px;
  right: -10px;
}
.onboarding-beacon[data-beacon-style="bulb"][data-placement="bottom-left"],
.onboarding-beacon[data-beacon-style="brain"][data-placement="bottom-left"] {
  bottom: -10px;
  left: -10px;
}

.onboarding-beacon-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  color: #ffffff;
  box-shadow:
    0 2px 6px rgba(99, 102, 241, 0.45),
    inset 0 0 0 1.5px rgba(255, 255, 255, 0.85);
  z-index: 2;
  transition: transform 160ms ease, box-shadow 160ms ease;
}

.onboarding-beacon-icon svg {
  width: 18px;
  height: 18px;
  display: block;
}

/* Numbered badge tucked into the bottom-right of the icon. White chip
   with brand-coloured digit so it stays legible on busy backgrounds. */
.onboarding-beacon-number {
  position: absolute;
  bottom: -4px;
  right: -4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #ffffff;
  color: #4f46e5;
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.2), inset 0 0 0 1px rgba(99, 102, 241, 0.45);
  z-index: 3;
}

.onboarding-beacon[data-beacon-style="bulb"]:hover .onboarding-beacon-icon,
.onboarding-beacon[data-beacon-style="bulb"].is-active .onboarding-beacon-icon,
.onboarding-beacon[data-beacon-style="brain"]:hover .onboarding-beacon-icon,
.onboarding-beacon[data-beacon-style="brain"].is-active .onboarding-beacon-icon {
  transform: scale(1.08);
  box-shadow:
    0 3px 10px rgba(99, 102, 241, 0.55),
    inset 0 0 0 1.5px rgba(255, 255, 255, 1);
}

/* The pulse rings on icon variants need to be a touch larger so they
   ring the bigger icon rather than just its centre. */
.onboarding-beacon[data-beacon-style="bulb"] .onboarding-beacon-pulse,
.onboarding-beacon[data-beacon-style="brain"] .onboarding-beacon-pulse {
  width: 28px;
  height: 28px;
}

/* The pulse rings: two of them, second one on a delay so the radar
   effect is continuous without feeling busy. Subtle by default. */
.onboarding-beacon-pulse {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(99, 102, 241, 0.45);
  transform: translate(-50%, -50%) scale(1);
  opacity: 0.55;
  /* Slowed from 2500ms to 3750ms so the pulse feels ambient and
     self-serve rather than insistent. Delay below scales by the same
     factor to keep the staggered double-ring rhythm. */
  animation: onboarding-pulse 3750ms ease-out infinite;
  z-index: 1;
  pointer-events: none;
}

.onboarding-beacon-pulse-delayed {
  animation-delay: 1875ms;
}

@keyframes onboarding-pulse {
  0%   { transform: translate(-50%, -50%) scale(0.85); opacity: 0.55; }
  70%  { transform: translate(-50%, -50%) scale(2.4);  opacity: 0;    }
  100% { transform: translate(-50%, -50%) scale(2.4);  opacity: 0;    }
}

/* Respect users who prefer reduced motion: keep the dot, drop the pulse. */
@media (prefers-reduced-motion: reduce) {
  .onboarding-beacon-pulse {
    animation: none;
    opacity: 0.25;
    transform: translate(-50%, -50%) scale(1.4);
  }
}

/* -----------------------------------------------------------------------
   Tab peek beacons
   -----------------------------------------------------------------------
   Small numbered chips that appear on tab buttons whose pane contains
   tip anchors but isn't currently active. Without these, tips inside an
   inactive tab are mounted but invisible and only discoverable through
   Next/Previous navigation. The peek tells the user "more tips live in
   here", and clicking it activates the tab and opens that tip's popover.

   Visually: same purple accent as real beacons, but flat (no pulse) so
   they don't compete for attention with the live beacons on the page.
*/

.tab-button.has-onboarding-peek {
  position: relative;
}

.onboarding-tab-peek {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: 6px;
  vertical-align: middle;
}

.onboarding-tab-peek-dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  color: #ffffff;
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(99, 102, 241, 0.4), inset 0 0 0 1px rgba(255, 255, 255, 0.7);
  transition: transform 140ms ease, box-shadow 140ms ease;
}

.onboarding-tab-peek-dot:hover {
  transform: scale(1.12);
  box-shadow: 0 2px 6px rgba(99, 102, 241, 0.55), inset 0 0 0 1px rgba(255, 255, 255, 0.9);
}

/* -----------------------------------------------------------------------
   Popover
   -----------------------------------------------------------------------
   Title strip with the number badge + title + progress, body with a
   generous font, optional bullets, prev/next nav, divider, and a
   footnote with the global hide-all link.
*/

.onboarding-popover-backdrop {
  position: fixed;
  inset: 0;
  background: transparent;
  z-index: 99998;
  pointer-events: none;
  opacity: 0;
  transition: opacity 120ms ease;
}

.onboarding-popover-backdrop.is-visible {
  pointer-events: auto;
  opacity: 1;
  background: rgba(15, 23, 42, 0.04);
}

.onboarding-popover {
  position: fixed;
  z-index: 99999;
  background: var(--bg-alt, #ffffff);
  border: 1px solid var(--border, rgba(0, 0, 0, 0.1));
  border-radius: 14px;
  box-shadow:
    0 20px 50px rgba(15, 23, 42, 0.18),
    0 4px 12px rgba(15, 23, 42, 0.08);
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  transition: opacity 140ms ease, transform 140ms ease;
  overflow: hidden;
}

.onboarding-popover.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.onboarding-popover-strip {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.7rem 0.85rem 0.7rem 0.7rem;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  color: #ffffff;
}

.onboarding-popover-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.22);
  color: #ffffff;
  font-size: 0.8rem;
  font-weight: 700;
  flex: 0 0 auto;
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.7);
}

.onboarding-popover-title {
  font-size: 1.12rem;
  font-weight: 600;
  letter-spacing: 0.005em;
  flex: 1 1 auto;
  /* The title is editorial, not a label, so let it wrap if very long. */
  line-height: 1.3;
}

.onboarding-popover-progress {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  opacity: 0.85;
  white-space: nowrap;
}

.onboarding-popover-close {
  appearance: none;
  border: none;
  background: rgba(255, 255, 255, 0.18);
  color: #ffffff;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background 140ms ease;
}

.onboarding-popover-close:hover {
  background: rgba(255, 255, 255, 0.32);
}

.onboarding-popover-body {
  padding: 0.95rem 1rem 0.6rem;
  color: var(--text, #1f2937);
  /* Larger than the existing helpTooltip so the explanation feels
     deliberate, not crammed. */
  font-size: 1.06rem;
  line-height: 1.55;
}

.onboarding-popover-paragraph {
  margin: 0 0 0.65rem 0;
}

.onboarding-popover-bullets {
  margin: 0;
  padding-left: 1.1rem;
  /* Match the body paragraph: same font-size, same color, same weight.
     A muted bullets block was reading as secondary information when in
     fact the bullets are the actionable "how to use it" beats. */
  font-size: 1.06rem;
  line-height: 1.55;
  color: inherit;
}

.onboarding-popover-bullets li {
  margin: 0.3rem 0;
}

.onboarding-popover-nav {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.45rem 1rem 0.7rem;
}

.onboarding-popover-nav-btn {
  appearance: none;
  border: 1px solid var(--border, rgba(0, 0, 0, 0.12));
  background: var(--bg, #ffffff);
  color: var(--text, #1f2937);
  font-size: 0.85rem;
  font-weight: 500;
  padding: 0.4rem 0.75rem;
  border-radius: 8px;
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}

.onboarding-popover-nav-btn:hover:not([disabled]) {
  background: rgba(99, 102, 241, 0.08);
  border-color: rgba(99, 102, 241, 0.4);
  color: var(--accent, #6366f1);
}

.onboarding-popover-nav-btn[disabled] {
  opacity: 0.38;
  cursor: not-allowed;
}

.onboarding-popover-nav-btn.is-primary {
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  border-color: transparent;
  color: #ffffff;
}

.onboarding-popover-nav-btn.is-primary:hover:not([disabled]) {
  filter: brightness(1.05);
  color: #ffffff;
}

.onboarding-popover-divider {
  height: 1px;
  background: var(--border, rgba(0, 0, 0, 0.08));
  margin: 0 1rem;
}

.onboarding-popover-footnote {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 1rem 0.85rem;
  color: var(--text-muted, #6b7280);
  font-size: 0.78rem;
  line-height: 1.4;
}

.onboarding-popover-hide-all-link {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--accent, #6366f1);
  font-size: 0.78rem;
  font-weight: 500;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
  text-decoration-color: rgba(99, 102, 241, 0.4);
  text-underline-offset: 2px;
  /* "Hide all tips" should always read on a single line. Without this
     it wrapped to two lines in narrower popovers because the footer
     row uses justify-content: space-between and the link was the only
     shrinkable element. */
  white-space: nowrap;
  flex: 0 0 auto;
}

/* Footnote text on the left can shrink/wrap if needed; the link stays
   one-line via the rule above. */
.onboarding-popover-footnote > span {
  flex: 1 1 auto;
  min-width: 0;
}

.onboarding-popover-hide-all-link:hover {
  text-decoration-color: var(--accent, #6366f1);
}

/* -----------------------------------------------------------------------
   Dark theme support
   -----------------------------------------------------------------------
   The app uses [data-theme="dark"] (or .dark) on a high-level ancestor.
   We override the few hard-coded fallbacks that don't pick up cleanly
   from CSS variables.
*/

[data-theme="dark"] .onboarding-popover,
.dark .onboarding-popover {
  background: #1e293b;
  border-color: rgba(255, 255, 255, 0.08);
  box-shadow:
    0 20px 50px rgba(0, 0, 0, 0.5),
    0 4px 12px rgba(0, 0, 0, 0.35);
}

[data-theme="dark"] .onboarding-popover-body,
.dark .onboarding-popover-body {
  color: #e2e8f0;
}

[data-theme="dark"] .onboarding-popover-bullets,
.dark .onboarding-popover-bullets {
  color: #cbd5e1;
}

[data-theme="dark"] .onboarding-popover-nav-btn,
.dark .onboarding-popover-nav-btn {
  background: #0f172a;
  border-color: rgba(255, 255, 255, 0.12);
  color: #e2e8f0;
}

[data-theme="dark"] .onboarding-popover-divider,
.dark .onboarding-popover-divider {
  background: rgba(255, 255, 255, 0.08);
}

[data-theme="dark"] .onboarding-popover-footnote,
.dark .onboarding-popover-footnote {
  color: #94a3b8;
}

[data-theme="dark"] .onboarding-tips-toggle,
.dark .onboarding-tips-toggle {
  background: #0f172a;
  border-color: rgba(255, 255, 255, 0.12);
  color: #e2e8f0;
}

[data-theme="dark"] .onboarding-tips-toggle.is-on,
.dark .onboarding-tips-toggle.is-on {
  color: #c7d2fe;
  border-color: rgba(165, 180, 252, 0.45);
}

/* -----------------------------------------------------------------------
   Page-wide dim while a tip is open
   -----------------------------------------------------------------------
   When a popover is open we want the surrounding UI to recede slightly
   so the popover (and the beacon it points at) read as the focal point
   without being intrusive. We dim by ~12% via a body::before overlay
   instead of mutating opacity on the actual UI, which would interfere
   with text rendering and z-stacked elements.

   The popover lives at z-index 99999 and the backdrop at 99998, so we
   pin the dim layer just below the backdrop (99997) to keep tip chrome
   crisp on top. Pointer-events are off so clicks still flow to the
   backdrop (which closes the popover).
*/
body.has-active-onboarding-tip::before {
  content: "";
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.12);
  z-index: 99997;
  pointer-events: none;
  animation: onboarding-dim-in 160ms ease-out;
}

@keyframes onboarding-dim-in {
  from { background: rgba(15, 23, 42, 0); }
  to   { background: rgba(15, 23, 42, 0.12); }
}

/* Slightly stronger dim in dark theme so the contrast still reads. */
[data-theme="dark"] body.has-active-onboarding-tip::before,
.dark body.has-active-onboarding-tip::before {
  background: rgba(0, 0, 0, 0.32);
}
