/* 教程引擎样式
 * 容器策略：所有 UI 都 fixed 在 body 上，z-index 高于 Modal(6000) 让教程在弹窗打开时仍可见。
 * 气泡/任务条/退出按钮用 left:50% + transform 居中 + max-width 500px，确保在手机屏（含限宽 #app）内可见。
 * 透明遮罩 z-index 5000 低于 Modal，让 Modal 打开时用户能正常交互弹窗。
 *
 * box 与弹窗关系（动态分层，tutorial-engine _syncModalZAboveTutorialBox）：
 *   - 教程引导链上的弹窗（索引 < _guidedModalTopCount）：spotlight(9001)/引导圈(9002) 在弹窗(6002+) 之上。
 *   - 用户自发多开的弹窗（索引 >= _guidedModalTopCount）：临时抬到 9200+，盖过 bubble(9100)。
 */

.tutorial-hidden {
  display: none !important;
}

/* 2026-06-04 宝宝原话「下拉层级还比不过引导框」根因：教程 4 ring 在 _freeGuideLayer (fixed z=9002)
   高于 #modal-container (z=6000) stacking context；modal 内的 settings-font-panel (absolute z=20)
   被 modal-container 6000 stacking 封装，物理 z 永远低于 ring 9002 → ring 边框盖过 panel 选项条目。
   修法：用 :has 选择 — 教程态 + 字体下拉打开时，临时整层 hide 4 ring（panel 操作完关回去后还原）。
   :has() Chrome 105+ 支持，宝宝主用 Chrome 没问题；其他 popup 类（颜色选择器 等）后续按需扩展。 */

body:has(#modal-container .modal-overlay:not([data-closing]) .settings-font-panel:not(.hidden)) .tutorial-free-guide-layer {
  display: none !important;
}

/* ========== 透明遮罩 - 接收外围点击 → 推进 ========== */

.tutorial-overlay {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 5000;
  background: transparent;
  pointer-events: auto;
  cursor: pointer;
}

/* 开局媒体场景 = 借用真游戏引擎跑临时教程故事，DOM 由 GameEngine 接管，
 * 教程引擎只在媒体场景期间隐藏 overlay/bubble/spotlight，让玩家在真实游戏页面里推进。 */

/* spotlight 框住的目标元素：即便被 disabled / 半透明，视觉上强制清晰；
   disabled 状态本身保留防止玩家点错地方跳出教程 */

.tutorial-spotlight-target,
.tutorial-spotlight-target[disabled] {
  opacity: 1 !important;
}

/* ========== 镂空高亮 - box-shadow 形成视口黑遮罩 ========== */

/* spotlight 框住的范围：
 *   - 目标在 modal 外（顶栏 nav 按钮等） → spotlight 框住按钮本身
 *   - 目标在 modal 内（弹窗里的具体项目） → spotlight 框住整个 modal 容器，弹窗整体亮起来
 * 弹窗内具体目标交给 .tutorial-indicator 脉冲圈单独指示。 */

.tutorial-spotlight {
  position: fixed;
  border-radius: 8px;
  pointer-events: none;
  z-index: 9001;
  /* 主页面在教程进行时仍要清晰可见——黑罩仅用轻度压暗（0.28）让 spotlight 框醒目即可，
     不再吃掉主区可读性。彩色脉冲边框 + indicator 才是真正吸引视线的元素。 */
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.28);
  transition: top 0.18s ease, left 0.18s ease, width 0.18s ease, height 0.18s ease;
}

.tutorial-spotlight::after {
  content: '';
  position: absolute;
  top: -3px;
  right: -3px;
  bottom: -3px;
  left: -3px;
  border-radius: inherit;
  border: 2px solid var(--accent-color);
  box-shadow: 0 0 0 1px var(--accent-color);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent-color) 35%, transparent);
  animation: tutorial-pulse 1.4s ease-in-out infinite;
  pointer-events: none;
}

@keyframes tutorial-pulse {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
  }

  50% {
    opacity: 0.45;
    transform: scale(1.04);
  }
}

/* ========== 弹窗内目标的脉冲指示器 - 只显示边框圈，不做黑罩 ========== */

/* 弹窗整体被 spotlight 镂空亮起后，弹窗里具体要点的元素用这个圈再次强调位置。
 * z-index 比 modal-overlay(6001+) 高，比教程 bubble(9100) 低；不阻挡点击。 */

.tutorial-indicator {
  position: fixed;
  border-radius: 8px;
  pointer-events: none;
  z-index: 9002;
  border: 2px solid var(--accent-color);
  box-shadow: 0 0 0 2px var(--accent-color),
    0 0 12px var(--accent-color);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-color) 30%, transparent),
    0 0 12px color-mix(in srgb, var(--accent-color) 45%, transparent);
  animation: tutorial-pulse 1.4s ease-in-out infinite;
  transition: top 0.18s ease, left 0.18s ease, width 0.18s ease, height 0.18s ease;
}

/* ========== 面包说话框（指导模式）========== */

/* 位置/大小由 JS 实时算 #app-scale-inner rect 来设置，永远在 #app 范围内 */

.tutorial-bubble {
  position: fixed;
  z-index: 9100;
  /* base 居中：动画结束后 transform 回到这里，避免气泡偏右出框 */
  transform: translateX(-50%);
  background: var(--bg-secondary);
  color: var(--text-primary);
  border: 1px solid var(--accent-color);
  border: 1px solid color-mix(in srgb, var(--accent-color) 30%, var(--border-color));
  border-radius: 12px;
  /* padding-right 给右上角 close x（22x22@right:6) 留出 28px 留白防文字与按钮重叠 */
  padding: 10px 32px 12px 12px;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5);
  display: flex;
  gap: 10px;
  font-size: var(--ui-fs-12);
  line-height: 1.55;
  pointer-events: none;
  box-sizing: border-box;
  /* 高度上限由 JS 按当前可放置区域算（见 tutorial-engine.js _capBubbleHeight）。
     内容比上限高时在气泡内部滚动，绝不往屏幕外面长。 */
  overflow: hidden;
  animation: tutorial-bubble-in 0.28s ease-out;
}

.tutorial-bubble-content {
  min-height: 0;
  overflow-y: auto;
  pointer-events: auto;
  -webkit-overflow-scrolling: touch;
  /* 只有这一块会滚，滚到头不带动底下的页面 */
  overscroll-behavior: contain;
  /* 内容超出上限要滚动时，底部留一点，最后一行不会被切成半个字 */
  padding-bottom: 2px;
}

@keyframes tutorial-bubble-in {
  from {
    transform: translateX(-50%) scale(0.92);
    opacity: 0;
  }

  to {
    transform: translateX(-50%) scale(1);
    opacity: 1;
  }
}

.tutorial-bubble--has-actions {
  pointer-events: auto;
}

/* readOnly 纯讲解 step（点任意位置推进）：box 自身轻微脉冲提示用户"可继续"，
   避免宝宝抱怨「导入自定义美化这里就被卡死了」=没继续按钮看着像卡死。
   不加任何文字（按规范不能 AI 编 UI 文案），只用视觉脉冲 + cursor:pointer 暗示。 */

.tutorial-bubble--tap-anywhere {
  cursor: pointer;
  pointer-events: auto;
  animation: tutorial-bubble-tap-pulse 1.6s ease-in-out infinite;
}

@keyframes tutorial-bubble-tap-pulse {
  0%, 100% {
    transform: translateX(-50%) scale(1);
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5),
                0 0 0 0 color-mix(in srgb, var(--accent-color) 35%, transparent);
  }

  50% {
    transform: translateX(-50%) scale(1.015);
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5),
                0 0 0 6px color-mix(in srgb, var(--accent-color) 18%, transparent);
  }
}

.tutorial-bubble-avatar {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 2px solid var(--accent-color);
  border: 2px solid color-mix(in srgb, var(--accent-color) 60%, transparent);
  overflow: hidden;
  background: var(--bg-tertiary);
  display: flex;
  align-items: center;
  justify-content: center;
}

.tutorial-bubble-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

.tutorial-bubble-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.tutorial-bubble-name {
  font-size: var(--ui-fs-10);
  color: var(--accent-color);
  font-weight: 600;
  letter-spacing: 0.04em;
}

.tutorial-bubble-text {
  white-space: pre-wrap;
  word-break: break-word;
}

.tutorial-bubble-tap-hint {
  font-size: var(--ui-fs-10);
  color: var(--text-secondary);
  text-align: right;
  margin-top: 2px;
  animation: tutorial-tap-blink 1.4s ease-in-out infinite;
}

@keyframes tutorial-tap-blink {
  0%, 100% {
    opacity: 0.45;
    transform: translateY(0);
  }

  50% {
    opacity: 1;
    transform: translateY(2px);
  }
}

.tutorial-bubble-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  flex-wrap: wrap;
  margin-top: 4px;
}

.tutorial-bubble-actions .btn {
  min-width: 76px;
}

/* ========== 教程模式下的立绘：顶天立地（撑满高度，宽度允许溢出由容器裁切） ========== */

.game-media-layer.is-tutorial .game-media-character {
  /* 撑满容器高度；宽度按图比例算可能超出容器，由 game-media-layer 的 overflow 裁切 */
  max-height: 100%;
  height: 100%;
  max-width: none;
  /* 改 cover 让人物撑满整个画面，halfBody 图人物在中心，左右多余背景可被裁 */
  object-fit: cover;
  /* 锚在底中：人物脚部贴底、头部顶屏 */
  object-position: center top;
}

/* ========== 教程模式下的选项按钮：高对比度卡片，序号用 accent 色突出 ========== */

.game-media-layer.is-tutorial .choice-area .choice-btn {
  background: var(--accent-color);
  background: color-mix(in srgb, var(--accent-color) 10%, var(--bg-secondary));
  color: var(--text-primary);
  border: 1.5px solid var(--accent-color);
  border: 1.5px solid color-mix(in srgb, var(--accent-color) 55%, var(--border-color));
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  font-weight: 500;
}

.game-media-layer.is-tutorial .choice-area .choice-btn:active {
  background: var(--accent-color);
  background: color-mix(in srgb, var(--accent-color) 22%, var(--bg-secondary));
}

.game-media-layer.is-tutorial .choice-area .choice-btn b {
  color: var(--accent-color);
  font-weight: 800;
  font-size: 1.15em;
  margin-right: 0.2em;
}

/* ========== 关闭教程 x（挂在 box 右上角，跟 box 走，无论 box 在哪都能关）========== */

/* 宝宝原话「把关闭教程变成 x 放在哐哐面包的 box 上，这样无论在哪里都可以关」：
   x 作为 _bubble 的 absolute 子元素，跟着 box 一起渲染/隐藏/移动，不再独立 fixed 定位。
   _bubble 默认是 position:fixed 自带定位上下文，absolute x 直接按 _bubble 边界定位。 */

.tutorial-bubble-close {
  position: absolute;
  top: 4px;
  right: 6px;
  width: 22px;
  height: 22px;
  padding: 0;
  margin: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-secondary);
  font-size: 18px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  pointer-events: auto;
  z-index: 1;
}

.tutorial-bubble-close:hover {
  color: var(--text-primary);
  background: var(--accent-color);
  background: color-mix(in srgb, var(--accent-color) 18%, transparent);
}

.tutorial-bubble-close:active {
  background: var(--accent-color);
  background: color-mix(in srgb, var(--accent-color) 28%, transparent);
}

/* ========== 卡死点我：救急悬浮按钮 ========== */

/* 教程期间任何一步只要因为设备兼容问题定位错误、看不到气泡/引导目标，用户就会卡住走不下去。
   这个按钮独立于教程的引导链路：z-index 压过教程自身能用到的所有层级（含 above-tutorial
   的 9500），全局点击拦截器对它整条豁免（不受"选美化只能点美化"这类限制），点击直接进入
   下一步，不需要真的完成当前步骤要求的操作。
   默认位置水平居中、偏上方（跟关闭教程 × 一样落在内容区域中央附近，不贴屏幕边缘）——
   贴边会导致两个问题：可拖拽空间被挤没大半（往贴的那一侧基本挪不动，用户反馈"拖拽方向
   莫名其妙"）、拖到极限时按钮大半个身子被裁到视口外只剩一条窄边可见。
   可拖拽挪开，避免正好挡住这一步真正要看的内容。 */

.tutorial-rescue-fab {
  position: fixed;
  top: 12%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2147483647;
  padding: 8px 14px;
  border: 1px solid var(--accent-color);
  border-radius: 999px;
  background: var(--bg-secondary);
  color: var(--text-primary);
  font-size: 13px;
  font-weight: bold;
  white-space: nowrap;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.tutorial-rescue-fab:active {
  cursor: grabbing;
}

.tutorial-rescue-fab.tutorial-rescue-fab--dragging {
  opacity: 0.85;
}