/* ==========================================================================
 * 语音播放按钮组件（两个规格，主题中立，CSS 变量驱动）
 * ==========================================================================
 * 设计原则：
 *   1) 纯 HTML+CSS，无图片、无外链字体；SVG 喇叭内嵌
 *   2) 所有颜色使用 CSS 变量；页面可覆盖同名变量适配自己的主题
 *   3) 播放态由追加 class="playing" 控制；移除该 class 即停
 *   4) 圆角跟随 var(--speak-radius)，默认 50%，页面可改为 var(--radius, 14px) 等
 *   5) 移动端 -webkit-tap-highlight-color 透明，去除默认高亮
 *   6) 动画节奏舒缓（≥1.5s/周期），不频闪
 *
 * 用法：
 *   小型（38px，光圈扩散，无声波）：
 *     <button class="speak-btn speak-sm" data-speak="文字" aria-label="播放"></button>
 *   大型（78px，光圈扩散，默认）：
 *     <button class="speak-btn speak-lg" data-speak="文字" aria-label="播放"></button>
 *   大型（78px，声波跳动）：
 *     <button class="speak-btn speak-lg" data-anim="wave" data-speak="文字" aria-label="播放"></button>
 *
 * 主题变量（在 :root 或 .theme-X 中覆盖）：
 *   --speak-bg-idle-from / --speak-bg-idle-to   静态背景渐变
 *   --speak-fg-idle                              静态前景色（图标色）
 *   --speak-bg-playing-from / --speak-bg-playing-to  播放中背景渐变
 *   --speak-fg-playing                           播放中前景色
 *   --speak-ring                                 光圈/声波主色
 *   --speak-shadow                               投影色
 *   --speak-radius                               圆角（默认 50%，跟随时改为 var(--radius)）
 * ========================================================================== */

/* 默认变量（暗色主题，主题切换页面可整体覆盖） */
:root {
  --speak-bg-idle-from:    rgba(255, 255, 255, 0.10);
  --speak-bg-idle-to:      rgba(255, 255, 255, 0.04);
  --speak-fg-idle:         rgba(255, 255, 255, 0.88);
  --speak-bg-playing-from: #5b78d6;
  --speak-bg-playing-to:   #2a3b7a;
  --speak-fg-playing:      #ffffff;
  --speak-ring:            #8fb6ff;
  --speak-shadow:          rgba(0, 0, 0, 0.25);
  --speak-radius:          50%;
}

/* ============ 基础样式（两种规格共享） ============ */
.speak-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  padding: 0;
  margin: 0;
  border: 0;
  cursor: pointer;
  /* 按钮圆角风格：跟随页面通用圆角规范；默认圆形（圆形按钮也可与方角按钮混排时单独覆盖） */
  border-radius: var(--speak-radius, 50%);
  background: linear-gradient(145deg, var(--speak-bg-idle-from), var(--speak-bg-idle-to));
  color: var(--speak-fg-idle);
  box-shadow: 0 2px 6px var(--speak-shadow);
  -webkit-tap-highlight-color: transparent;            /* 移动端清除默认高亮 */
  user-select: none;
  -webkit-user-select: none;
  outline: none;
  /* 过渡：背景/色值 0.25s、位移/缩放 0.18s —— 节奏舒缓 */
  transition: transform .18s ease,
              box-shadow .18s ease,
              background .25s ease,
              color .25s ease;
}
.speak-btn > svg { display: block; pointer-events: none; }

/* hover：轻微上抬 + 投影加深 + 图标变白 */
.speak-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px var(--speak-shadow);
  color: var(--speak-fg-playing);
}
/* active：下沉缩放，提供"按下去"的物理感 */
.speak-btn:active { transform: scale(.94); }
/* 键盘聚焦：仅键盘可见的高亮环（鼠标点击不出现） */
.speak-btn:focus-visible {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--speak-ring) 55%, transparent),
              0 4px 12px var(--speak-shadow);
}
.speak-btn[disabled],
.speak-btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
  pointer-events: none;
}

/* ============ 规格 A：小型 38px ============ */
/* 用途：首页六大模块卡 / 底部按钮 / 今日推荐 / 勋章 / 模块内部小旁白等
   动画：仅柔和外圈光圈扩散，禁止声波跳动（多按钮并排不杂乱） */
.speak-btn.speak-sm { width: 38px; height: 38px; }
.speak-btn.speak-sm > svg { width: 18px; height: 18px; }

/* ============ 规格 B：大型 78px ============ */
/* 用途：绘本阅读 / 跟读训练 / 迪士尼课件主播放键
   动画：默认光圈扩散；data-anim="wave" 切换为声波跳动 */
.speak-btn.speak-lg { width: 78px; height: 78px; }
.speak-btn.speak-lg > svg { width: 36px; height: 36px; }

/* ============ 播放态：柔和外圈光圈扩散（小/大通用） ============
   双层错相位扩散：1.8s 一周期，无频闪；尺寸自适应按钮大小。 */
.speak-btn::before,
.speak-btn::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
}
.speak-btn.playing {
  background: linear-gradient(145deg, var(--speak-bg-playing-from), var(--speak-bg-playing-to));
  color: var(--speak-fg-playing);
}
.speak-btn.playing::before {
  border: 2px solid var(--speak-ring);
  animation: speak-ring 1.8s ease-out infinite;
}
.speak-btn.playing::after {
  border: 2px solid var(--speak-ring);
  animation: speak-ring 1.8s ease-out infinite;
  animation-delay: .9s;        /* 与 before 错相位，视觉更连贯 */
}
@keyframes speak-ring {
  0%   { inset: 0;     opacity: .55; }
  100% { inset: -12px; opacity: 0;   }
}

/* ============ 大型额外：声波跳动动画（仅 data-anim="wave" 启用） ============
   通过 SVG 内的 .speak-wave 路径 scaleY 上下伸缩模拟"声波"。
   与外圈光圈互斥：data-anim="wave" 时关闭光圈，专注声波。 */
.speak-btn.speak-lg[data-anim="wave"] .speak-wave {
  transform-origin: 12px 12px;
  animation: speak-wave 1.2s ease-in-out infinite;
}
@keyframes speak-wave {
  0%, 100% { transform: scaleY(0.42); }
  50%      { transform: scaleY(1);    }
}
/* 静态时声波线低位浅淡；播放时变高亮（color 由 .playing 接管） */
.speak-btn .speak-wave {
  opacity: .55;
  transition: opacity .2s;
  transform-origin: 12px 12px;
}
.speak-btn.playing .speak-wave { opacity: 1; }

/* 小型不需要声波，强制隐藏（防御性写法：若有人误用 speak-sm + .speak-wave） */
.speak-btn.speak-sm .speak-wave { display: none; }

/* wave 模式下，光圈扩散与声波同时存在会显得花哨；用户已选 wave，关掉外圈光圈 */
.speak-btn.speak-lg[data-anim="wave"].playing::before,
.speak-btn.speak-lg[data-anim="wave"].playing::after {
  animation: none;
  opacity: 0;
}

/* ============ 父容器内的定位辅助（不强制，使用方按需覆盖） ============ */
/* 模块卡 / 今日推荐 / 底部按钮 的右上角定位 —— 父需 position:relative */
.mod-card .speak-btn,
.pick-card .speak-btn,
.home-btn .speak-btn { position: absolute; top: 8px; right: 8px; z-index: 2; }
.mod-card .speak-btn { top: 6px; right: 6px; }
.home-btn .speak-btn { top: 4px; right: 4px; }

/* 锁定态模块卡隐藏喇叭 */
.mod-card.locked .speak-btn { display: none; }

/* 文字主区给喇叭让出右侧空间，避免压字 */
.mod-card > span:not(.mod-icon):not(.speak-btn) { padding-right: 40px; }
.pick-card .pick-info { padding-right: 40px; }
.home-btn { position: relative; padding-right: 40px; text-align: left; }

/* ============ 小屏适配：仅缩小型，大型保持 78px 不变 ============ */
@media (max-width: 480px) {
  .speak-btn.speak-sm { width: 36px; height: 36px; }
  .speak-btn.speak-sm > svg { width: 17px; height: 17px; }
  .mod-card > span:not(.mod-icon):not(.speak-btn) { padding-right: 36px; }
  .home-btn { padding-right: 38px; }
  .pick-card .pick-info { padding-right: 36px; }
}
@media (max-width: 380px) {
  .speak-btn.speak-sm { width: 32px; height: 32px; }
  .speak-btn.speak-sm > svg { width: 15px; height: 15px; }
  .mod-card > span:not(.mod-icon):not(.speak-btn) { padding-right: 32px; }
  .home-btn { padding-right: 34px; }
  .pick-card .pick-info { padding-right: 32px; }
}

/* ============ 可访问性：用户偏好减少动画时停用所有动效 ============ */
@media (prefers-reduced-motion: reduce) {
  .speak-btn,
  .speak-btn::before,
  .speak-btn::after,
  .speak-btn .speak-wave {
    animation: none !important;
    transition: none !important;
  }
  .speak-btn.playing::before,
  .speak-btn.playing::after { opacity: 0; }
}
