/* =====================================================================
   tour.css — Task 40 · 游戏式引导引擎样式（spotlight 巡览）
   ---------------------------------------------------------------------
   全部取色走 var(--...)（tokens.css 单一事实源），本文件零裸色值。
   变暗原理：高亮环本身透明 + 9999px 外阴影铺满视口；环的边框盒＝"洞"，
   正好罩住目标 → 目标不变暗、不改动目标布局/尺寸、不用遮罩挖洞。
   ===================================================================== */

:root {
  /* 变暗层：--color-neutral-900 的 55% 不透明度（与规格要求的 .55 等价）。
     用 color-mix 从 token 派生 → 既守住"零裸色值"，又保留单一事实源。 */
  --tour-scrim: color-mix(in srgb, var(--color-neutral-900) 55%, transparent);
  --tour-arrow: 12px;
}

/* ---------------- 引导层骨架（整层不吃事件：不劫持页面交互） ---------------- */
.tour-root {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  pointer-events: none;
}

/* ---------------- 高亮环：透明的"目标同几何"元素，靠外阴影变暗全屏 ---------------- */
.tour-ring {
  position: fixed;
  /* Task 55 · 层级全局化：变暗环＝--z-scrim(9900)，在目标/抽屉/气泡之下。
     该值来自 tokens.css，**两个视口下恒为同一个值**（不受媒体查询影响）。 */
  z-index: var(--z-scrim);
  pointer-events: none;
  outline: 2px solid var(--color-primary);
  outline-offset: 0;
  animation: tour-breathe 2s ease-in-out infinite;
  /* 兜底（老浏览器无 color-mix）：用 tokens 里已有的遮罩色 */
  box-shadow: 0 0 0 9999px var(--color-scrim);
  /* 主流浏览器：等价于 --color-neutral-900 的 55% 不透明度（面积≤0.15 档 = 全黑幕）*/
  box-shadow: 0 0 0 9999px var(--tour-scrim);
}

@keyframes tour-breathe {
  0%, 100% { outline-color: var(--color-primary); outline-offset: 0; }
  50%      { outline-color: var(--color-primary-border-soft); outline-offset: 4px; }
}

/* 高亮元素：仅提升自身层级；只有本身是 static 时才补 position:relative（不动布局/尺寸） */
.tour-target { z-index: var(--z-target); }
.tour-target[data-tour-static="1"] { position: relative; }
aside.left.tour-target { z-index: var(--z-target); }

/* ---------------- Task 55 · 面积分级三档变暗（由 tour.js 判定，body 状态类） ---------------- */
/* ≤0.15（小目标）→ 全黑幕 55%：沿用上面 .tour-ring 的基规则，无需额外声明。
   0.15–0.35 → 黑幕 28%：目标之外仍可读。
   >0.35（大目标）→ **不铺黑幕**：改用 2px 主色描边 + 左侧书签条（见 F3），
                    以消除"框体过长"的整圈外框。取色依旧从 token 派生，零裸色值。*/
body.tour-dim-light .tour-ring {
  /* 兜底（无 color-mix） */
  box-shadow: 0 0 0 9999px var(--color-scrim);
  box-shadow: 0 0 0 9999px color-mix(in srgb, var(--color-neutral-900) 28%, transparent);
}
body.tour-dim-off .tour-ring {
  /* 兜底（无 color-mix） */
  box-shadow: none;
  outline: none;
}

/* ---------------- Task 55 · F3：大目标"正向强调"（不画完整外框） ---------------- */
/* 仅在与 .tour-dim-off 同时出现时生效：outline:none 消除整圈外框，
   只保留上边缘强调线 + 左侧书签竖条 → 指向明确且不"过长"。 */
body.tour-dim-off .tour-ring.tour-ring--emph {
  /* 关键：描边不走"内容盒外扩"，否则环的 border-box 会比 target+6px 大 3/4px
     → 既有 [A-1]「环↔目标对齐 maxΔ ≤2px」会被破坏。border-box 下 width/height
     已含描边 → 几何不变量保持。 */
  box-sizing: border-box;
  outline: none;
  border-top: 3px solid var(--color-primary);
  border-left: 6px solid var(--color-primary);
  border-right: 0;
  border-bottom: 0;
  border-radius: 0;
}

/* ---------------- 气泡 ---------------- */
.tour-tip {
  position: fixed;
  /* Task 55 · 引导气泡永远最上层（全局 token，与媒体查询无关） */
  z-index: var(--z-tip);
  pointer-events: auto;
  box-sizing: border-box;
  width: max-content;
  max-width: min(320px, calc(100vw - 20px));
  padding: var(--space-3-5) var(--space-4);
  background: var(--color-bg-surface);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  font-family: var(--font-sans);
  animation: tour-in .22s ease-out both;
}
.tour-tip:focus { outline: none; box-shadow: var(--shadow-xl), var(--shadow-focus); }

@keyframes tour-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}

.tour-title {
  font-size: var(--font-size-base);
  font-weight: var(--weight-semibold);
  line-height: var(--line-snug);
  color: var(--color-text-primary);
}
.tour-desc {
  margin-top: var(--space-1);
  font-size: var(--font-size-sm);
  line-height: var(--line-snug);
  color: var(--color-text-secondary);
}
.tour-foot {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3-5);
}
.tour-spacer { flex: 1; }

.tour-btn {
  font-family: var(--font-sans);
  cursor: pointer;
  border-radius: var(--radius-pill);
  transition: background-color .2s ease-out, color .2s ease-out, border-color .2s ease-out;
}
.tour-btn-primary {
  font-size: var(--font-size-sm);
  font-weight: var(--weight-medium);
  padding: var(--space-1-5) var(--space-3);
  border: 1px solid var(--color-primary);
  background: var(--color-primary);
  color: var(--color-on-primary);
}
.tour-btn-primary:hover { background: var(--color-primary-hover); border-color: var(--color-primary-hover); }
.tour-btn-ghost {
  font-size: var(--font-size-xs);
  padding: var(--space-1) var(--space-1-5);
  border: 1px solid transparent;
  background: transparent;
  color: var(--color-text-tertiary);
}
.tour-btn-ghost:hover { color: var(--color-primary); border-color: var(--color-primary-border-soft); }

/* ---------------- 指向箭头（旋转小方块，两个方向复用） ---------------- */
.tour-arrow {
  position: absolute;
  width: var(--tour-arrow);
  height: var(--tour-arrow);
  background: var(--color-bg-surface);
  border-left: 1px solid var(--color-border);
  border-top: 1px solid var(--color-border);
  transform: rotate(45deg);
}
.tour-arrow[data-side="top"]    { transform: rotate(225deg); }
.tour-arrow[data-side="right"]  { transform: rotate(135deg); }
.tour-arrow[data-side="left"]   { transform: rotate(-45deg); }

/* ---------------- 顶部「引导」入口（低调可重看） ---------------- */
/* 注：窄屏下顶栏本身会溢出（布局视口被撑宽），故这里始终用最小尺寸，
   尽量不为顶栏增加宽度。 */
.app-header .tour-entry {
  font-size: var(--font-size-2xs);
  line-height: var(--line-snug);
  padding: var(--space-0-5) var(--space-1-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-text-tertiary);
  cursor: pointer;
  flex: 0 0 auto;
}
.app-header .tour-entry:hover {
  color: var(--color-primary);
  border-color: var(--color-primary-border-soft);
  background: var(--color-primary-tint-4);
}

/* Task 48 · 审计页顶部同款「引导」入口（同一颗按钮，另一种页头容器） */
.site-header .nav { display: flex; align-items: center; gap: var(--space-2); }
.site-header .tour-entry {
  font-size: var(--font-size-2xs);
  line-height: var(--line-snug);
  padding: var(--space-0-5) var(--space-1-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-text-tertiary);
  cursor: pointer;
  flex: 0 0 auto;
}
.site-header .tour-entry:hover {
  color: var(--color-primary);
  border-color: var(--color-primary-border-soft);
  background: var(--color-primary-tint-4);
}

/* ---------------- Task 48 · 主链进度章（第 N / M 步） ---------------- */
/* 跨页时进度接着走，用户始终知道“整条链到哪儿了”。取色全部走 token，零裸色值。 */
.tour-step {
  display: inline-block;
  margin-bottom: var(--space-1-5);
  padding: var(--space-0-5) var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--color-primary-tint-4);
  color: var(--color-primary);
  font-family: var(--font-sans);
  font-size: var(--font-size-2xs);
  font-weight: var(--weight-medium);
  line-height: var(--line-snug);
  white-space: nowrap;
}

/* =============================================================
   Task 49 · 等待态（动作已发、结果未回）
   -------------------------------------------------------------
   等待期**没有变暗层**（由 chain.js 调 ClearResSpot.dim(false) 撤掉 ring）。
   只留两样东西：① 一颗不吃事件的轻提示；② 20s 超时后的兜底出口。
   全部取色走 token → 新增样式零裸色值。
   ============================================================= */

/* 轻提示：pointer-events:none → 不吃事件、不挡阅读、不挡滚动；跟随鼠标旁，不居中盖屏 */
.tour-toast {
  position: fixed;
  z-index: var(--z-modal);
  pointer-events: none;
  max-width: min(220px, calc(100vw - 24px));
  padding: var(--space-1-5) var(--space-3);
  background: var(--color-neutral-900);
  color: var(--color-neutral-0);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-lg);
  font-family: var(--font-sans);
  font-size: var(--font-size-xs);
  line-height: var(--line-snug);
  white-space: nowrap;
  animation: tour-in .16s ease-out both;
}

/* 超时兜底出口：底部居中的小胶囊（可点 → pointer-events:auto，但是小面不是全屏） */
.tour-wait-exit {
  position: fixed;
  z-index: var(--z-modal);
  left: 50%;
  bottom: var(--space-4);
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  max-width: calc(100vw - 24px);
  padding: var(--space-2) var(--space-3);
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-xl);
  font-family: var(--font-sans);
  font-size: var(--font-size-xs);
  color: var(--color-text-secondary);
}
.tour-wait-exit-msg { white-space: nowrap; }
.tour-wait-exit-btn {
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--color-border);
  background: var(--color-bg-surface);
  color: var(--color-text-secondary);
  font-size: var(--font-size-xs);
  white-space: nowrap;
}
.tour-wait-exit-btn:hover {
  color: var(--color-primary);
  border-color: var(--color-primary-border-soft);
  background: var(--color-primary-tint-4);
}
.tour-wait-exit-btn[data-wait-act="skip"] {
  border-color: transparent;
  color: var(--color-text-tertiary);
}

/* ---------------- 手机：气泡改为底部固定浮层 ---------------- */
/* 窄屏：气泡本身就是底部浮层 → 兜底出口改到顶部，避免两层叠在一处 */
@media (max-width: 640px) {
  .tour-wait-exit {
    left: var(--space-3);
    right: var(--space-3);
    bottom: auto;
    top: var(--space-3);
    transform: none;
    flex-wrap: wrap;
    justify-content: center;
    border-radius: var(--radius-xl);
  }
  .tour-wait-exit-msg { display: none; }

  /* Task 55 · F4：气泡更醒目（**仅外观**——层级规则一律不放媒体查询，见 tokens.css） */
  .tour-title { font-size: var(--font-size-lg); }
  .tour-tip { padding: var(--space-4) var(--space-5); }
  .tour-desc { font-size: var(--font-size-md); }
  .tour-btn-primary { min-height: 40px; padding: var(--space-2) var(--space-4); font-size: var(--font-size-md); }
  .tour-btn-ghost { min-height: 40px; font-size: var(--font-size-sm); }
}

.tour-sheet .tour-tip {
  left: var(--space-3);
  right: var(--space-3);
  top: auto;
  bottom: var(--space-3);
  width: auto;
  max-width: none;
}
.tour-sheet .tour-arrow { display: none; }

/* Task 55 · F4 配套避让：底部浮层会压住「靠近视口底部」的高亮目标时，
   tour.js 置 tour-sheet-top → 气泡改停靠顶部（与 dim-off 规则同值，不冲突）。 */
body.tour-sheet-top.tour-sheet .tour-tip { top: var(--space-3); bottom: auto; }

/* Task 55 · F4：大目标（不铺黑幕）且为 sheet 模式时，气泡改停靠顶部，
   避免底部浮层压住被强调的大区块。.tour-sheet 由 tour.js 按布局视口判定 → 天然可靠，
   不受"媒体查询在真机不命中"影响。 */
/* Task 55.1（Clawy 修正）：取消"大目标时气泡停靠顶部"——实测会盖住目标顶部
   （第 3 步把「1 查数据」整张卡盖掉），改为保持默认底部停靠。 */

@media (max-width: 620px) {
  .app-header .tour-entry { padding: var(--space-0-5) var(--space-1); }
}

/* ---------------- 动效降级 ---------------- */
@media (prefers-reduced-motion: reduce) {
  .tour-ring { animation: none; }
  .tour-tip { animation: none; }
  .tour-btn { transition: none; }
}


/* 目标在固定底栏时，气泡让到顶部（否则底部浮层必然压住它） */
body.tour-tip--top .tour-tip {
  top: var(--space-3) !important;
  bottom: auto !important;
  max-height: 168px;
  overflow: auto;
}
body.tour-tip--top .tour-tip .tour-arrow { display: none !important; }
