/* ==========================================================================
   每日单词 · 组件样式
   --------------------------------------------------------------------------
   依赖 tokens.css。应用代码直接复用这些类名，设计与实现共用同一份样式，
   避免"设计稿一套、代码另一套"的漂移。
   ========================================================================== */

/* ---------- 基础 ---------- */
*,
*::before,
*::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: var(--leading-normal);
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

/* 统一的键盘焦点环：只在键盘导航时出现，鼠标点击不显示 */
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* ==========================================================================
   按钮
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-full);
  font-family: inherit;
  font-size: var(--text-body);
  font-weight: var(--weight-semibold);
  line-height: 1;
  padding: 11px var(--space-5);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.btn:active { transform: scale(0.97); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }

.btn--primary { background: var(--primary); color: var(--on-primary); }
.btn--primary:hover:not(:disabled) { background: var(--primary-hover); }
.btn--primary:active:not(:disabled) { background: var(--primary-active); }

.btn--secondary {
  background: var(--surface-2);
  color: var(--ink);
  border-color: var(--border-strong);
}
.btn--secondary:hover:not(:disabled) { background: var(--hover-wash); }

.btn--ghost { background: transparent; color: var(--primary); }
.btn--ghost:hover:not(:disabled) { background: var(--primary-wash); }

.btn--danger { background: var(--status-critical); color: #fff; }
.btn--danger:hover:not(:disabled) { filter: brightness(0.92); }

.btn--sm { padding: 7px var(--space-4); font-size: var(--text-sm); }
.btn--lg { padding: 15px var(--space-8); font-size: var(--text-h3); }
.btn--block { display: flex; width: 100%; }

/* ==========================================================================
   朗读按钮 —— 应用最核心的交互，单列一组样式
   状态：默认 / hover / 播放中（外扩声波）/ 带朗读次数角标
   ========================================================================== */
.speak {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;                 /* 44px 是移动端可点区域下限，不要再小 */
  height: 44px;
  flex: none;
  border: none;
  border-radius: var(--radius-full);
  background: var(--primary-wash);
  color: var(--primary);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
.speak:hover { background: var(--primary-wash-strong); }
.speak:active { transform: scale(0.92); }
.speak svg { width: 21px; height: 21px; }

.speak--sm { width: 34px; height: 34px; }
.speak--sm svg { width: 17px; height: 17px; }
.speak--lg { width: 56px; height: 56px; }
.speak--lg svg { width: 26px; height: 26px; }

/* 实心变体：用在单词卡这种需要视觉重心的地方 */
.speak--solid { background: var(--primary); color: var(--on-primary); }
.speak--solid:hover { background: var(--primary-hover); }

/* 播放中：一圈向外扩散的声波，播放结束后由 JS 移除 .is-playing */
.speak.is-playing::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-full);
  border: 2px solid var(--primary);
  animation: speak-ripple 900ms var(--ease) infinite;
}
@keyframes speak-ripple {
  0%   { transform: scale(1);   opacity: 0.55; }
  100% { transform: scale(1.6); opacity: 0; }
}

/* 朗读次数角标：次数是推荐算法的输入，所以在界面上明示 */
.speak__count {
  position: absolute;
  top: -2px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--radius-full);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--ink-secondary);
  font-size: 10px;
  font-weight: var(--weight-semibold);
  line-height: 16px;
  text-align: center;
}

/* 英/美音切换的小标签，贴在音标旁 */
.accent-tag {
  font-size: 10px;
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 1px 5px;
}

/* ==========================================================================
   标签 Chip：词性、场景、难度
   ========================================================================== */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 3px var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  color: var(--ink-secondary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: 1.5;
}
.chip--primary { background: var(--primary-wash); color: var(--primary); }
.chip--outline { background: transparent; border: 1px solid var(--border); }

/* ==========================================================================
   卡片外壳
   ========================================================================== */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

/* ==========================================================================
   单词卡 —— 首页今日推荐的主角
   正面：单词 + 双音标 + 朗读；点击翻转看释义与例句
   ========================================================================== */
.word-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.word-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.word-card__word {
  margin: 0;
  font-size: var(--text-display);
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  letter-spacing: -0.02em;
}

/* 音标行：英美各一条，各自带独立的朗读按钮 */
.phonetics { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.phonetic {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-ipa);
  font-size: var(--text-body);
  color: var(--ink-secondary);
}

.word-card__meaning {
  font-size: var(--text-h3);
  font-weight: var(--weight-medium);
  color: var(--ink);
}

/* 例句：左侧一条主色竖线，和释义区分开 */
.example {
  border-left: 2px solid var(--primary-wash-strong);
  padding-left: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.example__en { color: var(--ink-secondary); }
.example__zh { color: var(--ink-muted); font-size: var(--text-sm); }

.word-card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
  font-size: var(--text-xs);
  color: var(--ink-muted);
}

/* 收藏星标 */
.star {
  border: none;
  background: transparent;
  padding: var(--space-1);
  cursor: pointer;
  color: var(--ink-muted);
  line-height: 0;
  transition: color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.star:hover { transform: scale(1.15); }
.star.is-on { color: var(--status-warning); }
.star svg { width: 22px; height: 22px; }

/* ==========================================================================
   可点区域外扩
   --------------------------------------------------------------------------
   有些控件视觉上必须小：音标旁的喇叭要让位给音标本身，词行末尾的星标不能喧宾
   夺主，顶栏图标不该压过标题。但手指落点的精度跟图形大小没有关系。
   这里用一层完全不可见的伪元素把命中范围撑到 44×44，视觉一点不变。
   WCAG 2.2 里 24×24 是 AA 门槛，44×44 是 AAA——这么做等于白拿 AAA。

   两个前提：宿主必须 position: relative；祖先不能用 overflow: hidden 把它裁掉。
   相邻控件的间距要大于两边各自外扩的量，否则命中区会互相抢，
   所以 .topbar__actions 的间距跟着调大了。
   ========================================================================== */
.speak--sm,
.star,
.icon-btn { position: relative; }

/* .speak 的 ::after 被"播放中声波"占了，所以这里用 ::before */
.speak--sm::before,
.star::after,
.icon-btn::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

/* 小号按钮只往上下扩：它们常常横向紧挨着，左右扩会互相抢命中区 */
.btn--sm { position: relative; }
.btn--sm::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

/* 熟练度：5 个小点，答对升级答错降级；同时用 title 提供文字说明 */
.level { display: inline-flex; gap: 3px; align-items: center; }
.level__dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  border: 1px solid var(--border);
}
.level__dot.is-on { background: var(--primary); border-color: var(--primary); }

/* ==========================================================================
   短语卡 —— 日常用语，比单词卡更横向
   ========================================================================== */
.phrase-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-4) var(--space-5);
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.phrase-card__body { flex: 1; min-width: 0; }
.phrase-card__en {
  font-size: var(--text-h3);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-snug);
}
.phrase-card__zh { color: var(--ink-secondary); font-size: var(--text-sm); }

/* ==========================================================================
   分类瓷砖 —— 分类页的入口
   左侧一条分类色带 + 掌握度进度环；颜色只是辅助，文字始终在场
   ========================================================================== */
.cat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--space-3);
}

.cat-tile {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  padding-left: calc(var(--space-4) + 4px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  overflow: hidden;
  text-align: left;
  font-family: inherit;
  color: inherit;
  transition: transform var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
.cat-tile:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
/* 左侧 4px 分类色带，颜色由 --tile-color 传入 */
.cat-tile::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: var(--tile-color, var(--primary));
}
.cat-tile__icon { font-size: 26px; line-height: 1; flex: none; }
.cat-tile__body { flex: 1; min-width: 0; }
.cat-tile__name {
  font-weight: var(--weight-semibold);
  font-size: var(--text-body);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 窄栅格下（手机两列）不允许"25 词"折行，宁可省略号 */
.cat-tile__meta {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 掌握度进度环：conic-gradient 画环，中间数字兜底表达（不靠颜色单独传意） */
.ring {
  position: relative;
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: var(--radius-full);
  background: conic-gradient(var(--tile-color, var(--primary)) calc(var(--pct, 0) * 1%),
                             var(--surface-sunken) 0);
}
.ring::after {
  content: attr(data-label);
  position: absolute;
  inset: 4px;
  border-radius: var(--radius-full);
  background: var(--surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: var(--weight-semibold);
  color: var(--ink-secondary);
}

/* ==========================================================================
   进度条 / 打卡
   ========================================================================== */
/* 进度槽用同色系浅步进，状态在整条上都能读出来 */
.meter {
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  overflow: hidden;
}
.meter__fill {
  height: 100%;
  border-radius: var(--radius-full);
  background: var(--primary);
  transition: width var(--dur-slow) var(--ease);
}
.meter--good .meter__fill { background: var(--status-good); }

.progress-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
  font-size: var(--text-sm);
  color: var(--ink-secondary);
}

/* 连续打卡徽章 */
.streak {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-full);
  background: var(--primary-wash);
  color: var(--primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

/* ---------- 7 天学习热力图 ---------- */
/* 单一蓝色顺序色阶，浅→深表示学习量；每格带 title 兜底 */
.heatmap { display: flex; gap: 6px; }
.heatmap__cell {
  flex: 1;
  aspect-ratio: 1;
  max-width: 40px;
  border-radius: var(--radius-sm);
  background: var(--seq-0);
  border: 1px solid var(--border);
}
.heatmap__cell[data-level="1"] { background: var(--seq-1); }
.heatmap__cell[data-level="2"] { background: var(--seq-2); }
.heatmap__cell[data-level="3"] { background: var(--seq-3); }
.heatmap__cell[data-level="4"] { background: var(--seq-4); }
.heatmap__cell[data-level="5"] { background: var(--seq-5); }
.heatmap__labels {
  display: flex;
  gap: 6px;
  margin-top: var(--space-1);
  font-size: 10px;
  color: var(--ink-muted);
}
.heatmap__labels span { flex: 1; max-width: 40px; text-align: center; }

/* 热力图图例 */
.heat-legend {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--ink-muted);
}
.heat-legend__swatches { display: flex; gap: 3px; }
.heat-legend__swatches i {
  width: 12px; height: 12px;
  border-radius: 3px;
  border: 1px solid var(--border);
}

/* ==========================================================================
   练习：四选一 / 拼写
   正确与错误同时用图标 + 文字表达，不依赖颜色单独传意
   ========================================================================== */
.quiz-options { display: flex; flex-direction: column; gap: var(--space-3); }

.quiz-option {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-4);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: var(--text-body);
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease);
}
.quiz-option:hover { border-color: var(--border-strong); background: var(--hover-wash); }

/* 选项序号 A/B/C/D */
.quiz-option__key {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px; height: 26px;
  flex: none;
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  color: var(--ink-secondary);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
}
.quiz-option__text { flex: 1; }
.quiz-option__mark { flex: none; line-height: 0; }

.quiz-option.is-selected { border-color: var(--primary); background: var(--primary-wash); }
.quiz-option.is-selected .quiz-option__key { background: var(--primary); color: var(--on-primary); }

.quiz-option.is-correct {
  border-color: var(--status-good);
  background: color-mix(in srgb, var(--status-good) 10%, var(--surface));
}
.quiz-option.is-correct .quiz-option__mark { color: var(--status-good); }

.quiz-option.is-wrong {
  border-color: var(--status-critical);
  background: color-mix(in srgb, var(--status-critical) 10%, var(--surface));
}
.quiz-option.is-wrong .quiz-option__mark { color: var(--status-critical); }

/* 结果提示条：图标 + 文案，颜色只是强化 */
.feedback {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}
.feedback--good {
  background: color-mix(in srgb, var(--status-good) 12%, var(--surface));
  color: var(--ink);
}
.feedback--bad {
  background: color-mix(in srgb, var(--status-critical) 12%, var(--surface));
  color: var(--ink);
}

/* 拼写输入：字母格 */
.spell { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.spell__slot {
  width: 38px; height: 46px;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--border);
  border-bottom-width: 2.5px;
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  font-size: var(--text-h2);
  font-weight: var(--weight-semibold);
  text-transform: lowercase;
}
.spell__slot.is-active { border-color: var(--primary); background: var(--primary-wash); }
.spell__slot.is-filled { background: var(--surface); }

/* ==========================================================================
   统计卡（stat tile）
   大数字用比例数字，不用等宽——等宽在大字号下会显得松散
   ========================================================================== */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-3);
}
.stat {
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.stat__label {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  margin-bottom: var(--space-1);
}
.stat__value {
  font-size: 1.75rem;
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
}
.stat__delta {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-top: var(--space-1);
  font-size: var(--text-xs);
  color: var(--ink-secondary);
}
/* 这里原本还有 .stat__delta--up（绿色上升色）和 .stat__spark（28px 迷你折线图），
   两条都没有任何调用点，已删除。设计系统声称自己是单一真源，就不该包含应用里
   并不存在的能力——留着会让人以为统计卡支持趋势和折线图，其实都没有。
   spark 的职能也跟统计页已有的 14 天热力图重叠。真要用时再加回来成本很低。 */

/* 首屏主数字：全页只允许出现一个 */
.hero-figure {
  font-size: 3rem;
  font-weight: var(--weight-bold);
  line-height: var(--leading-tight);
  letter-spacing: -0.02em;
}

/* ==========================================================================
   词表行 —— 分类页里的紧凑列表
   ========================================================================== */
.word-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
}
.word-row:last-child { border-bottom: none; }
.word-row:hover { background: var(--hover-wash); }
.word-row__body { flex: 1; min-width: 0; }
.word-row__en {
  font-weight: var(--weight-semibold);
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.word-row__ipa {
  font-family: var(--font-ipa);
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  color: var(--ink-muted);
}
.word-row__zh { font-size: var(--text-sm); color: var(--ink-secondary); }

/* ==========================================================================
   导航
   ========================================================================== */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  height: var(--topbar-h);
  padding: 0 var(--space-4);
  background: color-mix(in srgb, var(--bg) 85%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}
.topbar__title { font-size: var(--text-h3); font-weight: var(--weight-semibold); }
/* 间距 8px 而不是 4px：图标按钮的命中区各自往外扩了 3px，
   4px 的间距会让相邻两个按钮的命中区叠在一起。 */
.topbar__actions { display: flex; align-items: center; gap: var(--space-2); }

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px; height: 38px;
  border: none;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--ink-secondary);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease);
}
.icon-btn:hover { background: var(--hover-wash); }
.icon-btn svg { width: 20px; height: 20px; }

/* 底部 tab bar：移动端主导航，选中态用颜色 + 加粗 + 文字三重表达 */
.tabbar {
  display: flex;
  height: var(--tabbar-h);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--border);
}
.tabbar__item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  border: none;
  background: transparent;
  color: var(--ink-muted);
  font-family: inherit;
  font-size: 10px;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease);
}
.tabbar__item svg { width: 21px; height: 21px; }
.tabbar__item.is-active { color: var(--primary); font-weight: var(--weight-semibold); }

/* ==========================================================================
   空态 / 骨架屏 / Toast
   ========================================================================== */
.empty {
  text-align: center;
  padding: var(--space-12) var(--space-6);
  color: var(--ink-muted);
}
.empty__icon { font-size: 40px; margin-bottom: var(--space-3); }
.empty__title {
  font-size: var(--text-h3);
  font-weight: var(--weight-semibold);
  color: var(--ink-secondary);
  margin-bottom: var(--space-1);
}

.skeleton {
  background: linear-gradient(90deg,
              var(--surface-sunken) 25%,
              var(--hover-wash) 37%,
              var(--surface-sunken) 63%);
  background-size: 400% 100%;
  animation: skeleton 1.4s ease infinite;
  border-radius: var(--radius-sm);
}
@keyframes skeleton {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

.toast {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--ink);
  color: var(--ink-inverse);
  font-size: var(--text-sm);
  box-shadow: var(--shadow-lg);
}

/* ==========================================================================
   响应式：手机优先，桌面上内容居中并留白
   ========================================================================== */
@media (min-width: 768px) {
  .cat-grid { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
}
