/* EchoLine - 淡雅简洁，移动端优先 */

:root {
  --bg: #f8f6f3;
  --bg-card: #fff;
  --text: #3d3a36;
  --text-muted: #7a756e;
  --accent: #8b7355;
  --accent-soft: #c4b5a0;
  --border: #e8e4df;
  --highlight: #e8e0d5;
  --rec: #c0503a; /* 录音（跟读）：偏咖的红，和米色、咖色搭 */
  --good: #3d7a4f; /* 填空答对：偏暗的绿 */
  --ok: #b0761c; /* 填空答错：琥珀橙，不用红，不像在批评 */
  --safe-top: env(safe-area-inset-top, 0);
  --safe-bottom: env(safe-area-inset-bottom, 0);
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  color: var(--text);
  background: var(--bg);
  -webkit-tap-highlight-color: transparent;
}

#app {
  min-height: 100%;
  padding-top: var(--safe-top);
  padding-bottom: var(--safe-bottom);
}

/* Pages */
.page {
  display: none;
  min-height: 100vh;
  flex-direction: column;
}

.page.active {
  display: flex;
}

/* ---------- 剧集列表页 ---------- */
#episode-list-page {
  padding: 1rem 1rem 2rem;
}

.header {
  text-align: center;
  margin-bottom: 1.5rem;
  padding: 1rem 0;
}

.header h1 {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--text);
  letter-spacing: 0.02em;
}

.subtitle {
  margin: 0.25rem 0 0;
  font-size: 0.9rem;
  color: var(--text-muted);
}

.episode-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.episode-list li {
  margin: 0;
}

.episode-link {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 1rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  text-decoration: none;
  font-size: 1rem;
  transition: background 0.15s, border-color 0.15s;
}

.episode-link:active {
  background: var(--highlight);
}

.episode-thumb {
  flex: 0 0 auto;
  width: 96px;
  height: 54px;
  border-radius: 6px;
  background: var(--border);
  background-size: cover;
  background-position: center;
}

.episode-thumb.loaded {
  background-color: transparent;
}

.episode-info {
  flex: 1 1 auto;
  min-width: 0;
}

.episode-link .title {
  font-weight: 500;
  display: block;
}

.episode-link .meta {
  font-size: 0.85rem;
  color: var(--text-muted);
  margin-top: 0.25rem;
  display: block;
}

.empty-hint {
  text-align: center;
  color: var(--text-muted);
  font-size: 0.9rem;
  padding: 2rem 1rem;
}

.empty-hint.hidden {
  display: none;
}

/* ---------- 播放页 ---------- */
#player-page {
  height: 100vh;
  overflow: hidden;
}

.back-link {
  flex-shrink: 0;
  padding: 0.75rem 1rem;
  color: var(--accent);
  text-decoration: none;
  font-size: 0.9rem;
}

.back-link:active {
  opacity: 0.8;
}

.video-section {
  flex: 0 0 auto;
  position: relative;
  width: 100%;
  background: #1a1a1a;
  /* 高度由视频（最高 45vh）加控制栏决定，不再整体截断，否则控制栏下面的 A/B 按钮会被切掉 */
}

#video {
  display: block;
  width: 100%;
  max-height: 45vh;
  object-fit: contain;
}

.video-controls-overlay {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem 1rem;
  background: rgba(248, 246, 243, 0.98);
  border-top: 1px solid var(--border);
}

.mode-buttons {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
}

.mode-btn {
  padding: 0.35rem 0.45rem;
  font-size: 0.78rem;
  white-space: nowrap;
  color: var(--text);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.mode-btn.active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

/* A/B 按钮紧跟在模式按钮下面一行，只在 AB 模式显示 */
.ab-controls {
  flex-basis: 100%;
  display: flex;
  gap: 0.35rem;
  margin-top: 0.1rem;
}

.ab-btn {
  padding: 0.35rem 0.8rem;
  font-size: 0.78rem;
  white-space: nowrap;
  color: var(--text);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.ab-btn.set-a {
  background: #4a9;
  color: #fff;
  border-color: #4a9;
}

.ab-btn.set-b {
  background: #557ac5;
  color: #fff;
  border-color: #557ac5;
}

.controls-right {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.subtitle-mode-control,
.speed-control {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.subtitle-mode-control label,
.speed-control label {
  font-size: 0.85rem;
  color: var(--text-muted);
  white-space: nowrap;
  min-width: 2em;
  text-align: right;
}

.subtitle-mode-control select,
.speed-control select {
  padding: 0.3rem 0.5rem;
  font-size: 0.85rem;
  color: var(--text);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
}

.subtitle-section {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}

.subtitle-list {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 1rem;
}

.subtitle-line {
  padding: 0.75rem 1rem;
  margin-bottom: 0.5rem;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.15s;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  border: 1px solid transparent;
}

.subtitle-line:active {
  background: var(--highlight);
}

.subtitle-line.current {
  background: var(--highlight);
  border-color: var(--accent-soft);
}

.subtitle-line .timestamp {
  flex-shrink: 0;
  font-size: 0.68rem;
  color: var(--text-muted);
  opacity: 0.4;
  font-variant-numeric: tabular-nums;
  user-select: none;
  min-width: 3.5em;
  text-align: right;
}

/* 单句循环图标（?dev=1）：序号下面一个小图标，序号还按原来的基线对齐 */
.subtitle-line .ts-col {
  flex-shrink: 0;
  display: inline-flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.3rem;
}

.subtitle-line .loop-one-icon {
  width: 19px;
  height: 19px;
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.subtitle-line .text-wrap {
  flex: 1;
  min-width: 0;
}

.subtitle-line .text {
  font-size: 1.05rem;
  line-height: 1.5;
  color: var(--text);
  display: block;
}

.subtitle-line .text-zh {
  font-size: 0.95rem;
  color: var(--text-muted);
  margin-top: 0.15rem;
  display: block;
}

.subtitle-line.loop-a {
  border-left: 3px solid #4a9;
}

.subtitle-line.loop-b {
  border-left: 3px solid #557ac5;
}

.subtitle-line.loop-a .text::before {
  content: 'A ';
  color: #4a9;
  font-weight: 700;
  font-size: 0.8em;
}

.subtitle-line.loop-b .text::before {
  content: 'B ';
  color: #557ac5;
  font-weight: 700;
  font-size: 0.8em;
}

/* ---------- 跟读（?dev=1，js/shadowing.js） ---------- */

/* 正在循环的那一句右边一列：星（登录了才有）在上、麦克风在下；点的范围都是 44 像素见方 */
.subtitle-line.has-mic {
  padding-right: 0.25rem;
}

.line-acts {
  flex-shrink: 0;
  align-self: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: -0.6rem 0;
}

.line-acts .fav-star {
  margin: 0;
}

.shadow-mic {
  position: relative;
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 0;
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
  cursor: pointer;
  touch-action: manipulation;
}

.shadow-mic svg {
  width: 23px;
  height: 23px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* 录音中：红底白方块（照 iPhone「语音备忘录」的停止键），外面一圈慢慢散开 */
.shadow-mic.rec svg {
  display: none;
}

.shadow-mic.rec::before {
  content: "";
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--rec);
  animation: rec-ring 1.4s ease-out infinite;
}

.shadow-mic.rec::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 2px;
  background: #fff;
}

@keyframes rec-ring {
  0% { box-shadow: 0 0 0 0 rgba(192, 80, 58, 0.25); }
  100% { box-shadow: 0 0 0 9px rgba(192, 80, 58, 0); }
}

/* 声波：录音时红色、新的在右边往左滚；播放录音时整条摊开，播过的部分变深 */
.shadow-wave {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 2px;
  height: 28px;
  margin-top: 0.5rem;
  overflow: hidden;
}

.shadow-wave i {
  flex: 0 0 3px;
  min-height: 3px;
  border-radius: 2px;
  background: var(--rec);
}

.shadow-wave.mine {
  justify-content: flex-start;
}

.shadow-wave.mine i {
  background: var(--accent-soft);
}

.shadow-wave.mine i.done {
  background: var(--accent);
}

/* 句子下面的录音条：录音时只有声波；录过以后左边一个圆的播放键（照 iPhone 信息里的语音消息） */
.shadow-take {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.4rem;
}

.shadow-take .shadow-wave {
  flex: 1;
  min-width: 0;
  margin-top: 0;
}

.shadow-play {
  flex: 0 0 auto;
  width: 2.75rem;
  height: 2.75rem;
  margin: -0.5rem -0.35rem -0.5rem -0.6rem;
  padding: 0;
  border: 0;
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  touch-action: manipulation;
}

.shadow-play span {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
}

.shadow-play svg {
  width: 12px;
  height: 12px;
  fill: #fff;
}

/* 打分测试版：逐词标颜色（照 ELSA：读得好绿色，一般橙色，没读准红色下划线，漏读红色删除线） */
.w-good { color: #3d7a4f; }
.w-ok { color: #b0761c; }
.w-bad {
  color: var(--rec);
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
}
.w-miss {
  color: var(--rec);
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
  opacity: 0.85;
}

/* 录音那一行下面：左边总分，竖线，右边两行两列四项，最右 ⓘ（照模拟页第六版；360 宽的手机也排得下一行） */
.shadow-score {
  margin-top: 0.5rem;
  font-size: 0.8rem;
  color: var(--text-muted);
}
.shadow-score .why { display: block; line-height: 1.4; }
.score-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-variant-numeric: tabular-nums;
}
.score-row .total {
  display: flex;
  align-items: baseline;
  gap: 0.1rem;
  color: var(--text);
  white-space: nowrap;
}
.score-row .total b {
  font-size: 1.6rem;
  font-weight: 600;
  line-height: 1;
}
.score-row .parts {
  display: grid;
  grid-template-columns: auto auto;
  gap: 0.1rem 0.9rem;
  padding-left: 0.75rem;
  border-left: 1px solid var(--accent-soft);
  font-size: 0.78rem;
  line-height: 1.45;
}
.score-row .parts span { white-space: nowrap; }
.score-row .parts em {
  font-style: normal;
  color: var(--text);
  margin-left: 0.3rem;
}
/* ⓘ：照 iPhone 的 info.circle，点的范围 44 像素见方 */
.score-info {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  margin: -0.5rem -0.75rem -0.5rem -0.6rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  cursor: pointer;
}
.score-info svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
}
.score-info svg .dot { fill: currentColor; stroke: none; }
/* 点 ⓘ 展开的说明 */
.score-help {
  margin-top: 0.55rem;
  padding: 0.6rem 0.75rem;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.65);
  line-height: 1.5;
}
.score-help dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.15rem 0.75rem;
  margin: 0;
}
.score-help dt { color: var(--text); white-space: nowrap; }
.score-help dd { margin: 0; }
.score-help dl + dl {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
}

/* 拿不到麦克风时，这一句下面一行提示（不弹窗） */
.shadow-err {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.82rem;
  line-height: 1.4;
  color: var(--rec);
}

/* 视频下面那一行：录音时字变红，前面一个闪的小红点 */
.range-hint.rec {
  color: var(--rec);
}

.range-hint.rec::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 0.35rem;
  border-radius: 50%;
  background: var(--rec);
  vertical-align: 0.1em;
  animation: rec-blink 1.2s ease-in-out infinite;
}

@keyframes rec-blink {
  50% { opacity: 0.25; }
}

@media (prefers-reduced-motion: reduce) {
  .shadow-mic.rec::before,
  .range-hint.rec::before { animation: none; }
}

/* ---------- 点一句就循环、段落循环（先放在 ?dev=1 后面） ---------- */

/* 视频下面那一行：左边「段落循环」，右边字幕和语速 */
.line-tools-on .mode-buttons {
  display: none;
}

.line-tools-on .controls-right {
  flex-direction: row;
  gap: 0.9rem;
}

.line-tools-on .video-controls-overlay {
  flex-wrap: wrap;
  row-gap: 0.35rem;
}

.tool-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.4rem 0.6rem;
  min-height: 2.2rem;
  font-family: inherit;
  font-size: 0.85rem;
  white-space: nowrap;
  color: var(--text);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  touch-action: manipulation;
}

.tool-btn:active {
  background: var(--highlight);
}

/* 段落循环中 */
.tool-btn.on {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

/* 正在选起点、终点 */
.tool-btn.picking {
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.tool-icon {
  flex-shrink: 0;
  width: 1.05em;
  height: 1.05em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* 段落循环的提示：选的时候说怎么选，循环中写明第几句到第几句。
   手机上排在按钮那一行下面；屏幕宽（电脑）时放在按钮右边的空白里，不多占一行 */
.range-hint {
  order: 3;
  flex-basis: 100%;
  font-size: 0.85rem;
  color: var(--accent);
}

@media (min-width: 640px) {
  .range-hint {
    order: 0;
    flex: 1 1 auto;
    min-width: 0;
  }
}

.range-hint[hidden] {
  display: none;
}

/* 段落循环：不写 A、B 字母；从起点到结束句连成一整块浅米色底，左边一条浅咖色竖线不断开 */
.line-tools-on .subtitle-line.loop-a .text::before,
.line-tools-on .subtitle-line.loop-b .text::before {
  content: none;
}

.line-tools-on .subtitle-line.loop-a,
.line-tools-on .subtitle-line.loop-b {
  border-left: 1px solid transparent;
}

.line-tools-on .subtitle-line.in-range {
  margin-bottom: 0;
  border: 0;
  border-left: 3px solid var(--accent-soft);
  border-radius: 0;
  padding-top: calc(0.75rem + 1px);
  padding-bottom: calc(0.75rem + 1px);
  background: #f3ece2; /* 和页面的米色、咖色同一个色系，只比页面底色深一点点 */
}

.line-tools-on .subtitle-line.in-range.current {
  background: #ebe1d3;
}

.line-tools-on .subtitle-line.range-first {
  border-top-left-radius: 8px;
  border-top-right-radius: 8px;
}

.line-tools-on .subtitle-line.range-last {
  margin-bottom: 0.5rem;
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
}

/* ---------- 账号（?dev=1）：底部入口、我的、登录、邀请和重置链接 ---------- */
.tabbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  display: flex;
  background: var(--bg);
  border-top: 1px solid var(--border);
  padding: 0 env(safe-area-inset-right, 0) var(--safe-bottom) env(safe-area-inset-left, 0);
}

.tabbar[hidden],
#player-page.active ~ .tabbar,
#auth-page.active ~ .tabbar {
  display: none;
}

.tabbar button {
  flex: 1;
  padding: 0.55rem 0 0.5rem;
  border: 0;
  background: none;
  color: var(--text-muted);
  font-size: 0.8rem;
  font-family: inherit;
  white-space: nowrap;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  cursor: pointer;
}

/* 底部入口的图标：没选中的是空心线条，选中的是实心（照 iPhone 的标签栏，2026-11-05 Weiwei 定） */
.tabbar .ico {
  width: 1.4rem;
  height: 1.4rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linejoin: round;
}

.tabbar button.active {
  color: var(--accent);
  font-weight: 600;
}

.tabbar button.active .ico-fill {
  fill: currentColor;
}

/* 练习的靶心：选中时外圈实心，中间留一个底色的圆点 */
.tabbar button.active .ico-hole {
  fill: var(--bg);
  stroke: var(--bg);
}

/* 有底部入口时，列表页底下留出它的高度 */
.has-tabbar #episode-list-page,
#practice-page,
#mine-page,
#auth-page {
  padding: 1rem 1rem calc(4.5rem + var(--safe-bottom));
}

.account-body {
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
}

.account-form {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.account-form h2 {
  margin: 0 0 0.2rem;
  font-size: 1.05rem;
  font-weight: 600;
  text-align: center;
}

.account-lead {
  margin: -0.3rem 0 0.2rem;
  font-size: 0.9rem;
  color: var(--text-muted);
  text-align: center;
  overflow-wrap: anywhere;
}

.account-field {
  width: 100%;
  padding: 0.75rem 0.85rem;
  font-size: 1rem; /* 不小于 16px，iPhone 点输入框时不会自动放大页面 */
  font-family: inherit;
  color: var(--text);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.account-field:focus {
  outline: 2px solid var(--accent-soft);
  outline-offset: -1px;
}

.account-primary {
  width: 100%;
  padding: 0.75rem;
  font-size: 1rem;
  font-weight: 600;
  font-family: inherit;
  white-space: nowrap;
  color: #fff;
  background: var(--accent);
  border: 0;
  border-radius: 8px;
  cursor: pointer;
}

.account-primary:disabled {
  opacity: 0.6;
}

.account-msg {
  min-height: 1.4em;
  margin: 0;
  font-size: 0.88rem;
  color: #a5523a;
  text-align: center;
}

.account-msg.ok {
  color: var(--text-muted);
}

.account-who {
  margin: 0 0 1.2rem;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.9rem;
  overflow-wrap: anywhere;
}

/* 像 iPhone 设置那样的一组一组 */
.account-group {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 1rem;
}

.account-cell {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 0.85rem 1rem;
  font-size: 1rem;
  font-family: inherit;
  color: var(--text);
  background: none;
  border: 0;
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

.account-cell + .account-cell,
.account-cell + .account-sub {
  border-top: 1px solid var(--border);
}

.account-cell:active {
  background: var(--highlight);
}

.account-cell.center {
  justify-content: center;
  color: var(--accent);
}

.account-chev {
  color: var(--accent-soft);
}

.account-sub {
  padding: 0.75rem 1rem 0.5rem;
}

.account-who {
  padding: 1.6rem 0 0.4rem;
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--text);
}

.account-hint {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.75rem;
  min-height: 1.3em;
  margin: -0.35rem 0 0;
  font-size: 0.8rem;
  color: var(--text-muted);
}

.account-hint .met {
  color: var(--accent);
  font-weight: 600;
}

.account-bars {
  display: inline-flex;
  gap: 3px;
}

.account-bars i {
  width: 1.6rem;
  height: 4px;
  border-radius: 2px;
  background: var(--border);
}

.account-bars i.on {
  background: var(--accent);
}

.account-textlink {
  align-self: center;
  padding: 0.2rem;
  border: 0;
  background: none;
  color: var(--accent);
  font-size: 0.9rem;
  font-family: inherit;
  white-space: nowrap;
  cursor: pointer;
}

.account-help {
  margin: 0;
  font-size: 0.88rem;
  color: var(--text-muted);
  text-align: center;
}

/* ---------- 收藏（?dev=1，登录了才有） ---------- */

/* 播放页：星的位置一直留着，出现、消失时句子不重新换行；点的范围 44 像素见方 */
.subtitle-list.fav-on .subtitle-line {
  padding-right: 0.25rem;
}

.fav-star {
  flex-shrink: 0;
  align-self: center;
  width: 2.75rem;
  height: 2.75rem;
  margin: -0.6rem 0;
  padding: 0;
  border: 0;
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
  cursor: pointer;
  visibility: hidden;
}

.fav-star svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linejoin: round;
  transition: transform 0.18s;
}

.fav-star.saved svg {
  fill: currentColor;
}

.fav-star.pop svg {
  transform: scale(1.25);
}

/* 正在放的那一句出空心星；收藏过的一直是实心星 */
.subtitle-line.current .fav-star,
.fav-every .fav-star,
.fav-star.saved {
  visibility: visible;
}

.fav-every .subtitle-line:not(.current) .fav-star:not(.saved) svg {
  stroke: var(--accent-soft);
}

@media (prefers-reduced-motion: reduce) {
  .fav-star svg { transition: none; }
  .fav-star.pop svg { transform: none; }
}

/* 我的：「收藏」那一行右边的句数 */
.account-value {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* 收藏页：和看剧同一种播放页（上面视频，下面收藏的句子），版式沿用播放页的 */
#favorites-page,
#mistakes-page {
  height: 100vh;
  overflow: hidden;
}

#favorites-page.active ~ .tabbar,
#mistakes-page.active ~ .tabbar {
  display: none;
}

.fav-video-wrap {
  position: relative;
  background: #1a1a1a;
}

#fav-video,
#mis-video {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: 45vh;
  object-fit: contain;
  background: #1a1a1a;
}

/* 停着时画面中间一个播放键（没有系统进度条，拖不出这一句）。练习的片段里也用它（js/scenes.js） */
.fav-play,
.scene-play {
  position: absolute;
  inset: 0;
  width: 100%;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.fav-play[hidden],
.scene-play[hidden] {
  display: none;
}

.fav-play span,
.scene-play span {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  background: rgba(248, 246, 243, 0.85);
  position: relative;
}

.fav-play span::after,
.scene-play span::after {
  content: "";
  position: absolute;
  left: 1.35rem;
  top: 1.05rem;
  border-style: solid;
  border-width: 0.7rem 0 0.7rem 1.1rem;
  border-color: transparent transparent transparent var(--accent);
}

.fav-controls .range-hint {
  flex: 1 1 auto;
  order: 0;
  flex-basis: auto;
  min-width: 0;
}

.fav-controls {
  justify-content: flex-end;
}

.fav-line .fav-src {
  display: block;
  font-size: 0.78rem;
  color: var(--text-muted);
  opacity: 0.75;
  margin-top: 0.35rem;
  font-variant-numeric: tabular-nums;
}

/* 收藏页的出处一行（2026-11-06）：「S08E09 · 第 34 句 · 中级 ›」整行能点，回到看剧里这一句。
   能点的范围往上下撑开到 44 像素高，看起来和原来的小字一样占地方 */
.fav-line .fav-go {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  margin: -0.5rem 0 -0.85rem;
  padding: 0.85rem 0.6rem 0.85rem 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--accent);
  text-align: left;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.fav-line .fav-go-level {
  color: var(--text-muted);
  opacity: 0.75;
  white-space: pre;
}

.fav-line .fav-go-chev {
  font-size: 1rem;
  line-height: 1;
  margin-left: 0.25rem;
}

.fav-line .fav-go:active {
  opacity: 0.6;
}

#fav-list .fav-star {
  visibility: visible;
}

#fav-list.subtitle-list .subtitle-line,
#mis-list.subtitle-list .subtitle-line {
  padding-right: 0.25rem;
}

.fav-empty {
  text-align: center;
  color: var(--text-muted);
  padding: 3.5rem 1rem;
}

.fav-empty b {
  display: block;
  color: var(--text);
  font-size: 1.05rem;
  font-weight: 600;
  margin-bottom: 0.35rem;
}

.fav-empty span {
  font-size: 0.9rem;
}

/* ---------- 练习（?dev=1，js/scenes.js）：选等级、片段列表、片段播放页、看剧里的场景标题 ---------- */
.practice-body {
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
}

/* 一排等级按钮（分段控件）：练习列表顶上一整行，收藏页放在「‹ 我的」那一行右边 */
.seg-ctl {
  display: flex;
  background: var(--highlight);
  border-radius: 8px;
  padding: 2px;
}

.seg-ctl button {
  border: 0;
  background: none;
  padding: 0.3rem 0.5rem;
  border-radius: 6px;
  font-family: inherit;
  font-size: 0.8rem;
  color: var(--text-muted);
  white-space: nowrap;
  cursor: pointer;
}

.seg-ctl button.on {
  background: var(--bg-card);
  color: var(--text);
  font-weight: 600;
  box-shadow: 0 1px 2px rgba(61, 58, 54, 0.12);
}

.practice-levels {
  margin: 0.5rem 0 0.2rem;
}

.practice-levels button {
  flex: 1;
  padding: 0.3rem 0;
}

/* 每集一组，上面写集号和英文片名 */
.practice-ep {
  margin: 1.1rem 0.2rem 0.4rem;
  font-size: 0.78rem;
  color: var(--text-muted);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.practice-ep b {
  margin-right: 0.35rem;
  color: var(--text);
  font-weight: 600;
}

.practice-group {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

.practice-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  padding: 0.7rem 0.9rem;
  border: 0;
  background: none;
  font-family: inherit;
  color: var(--text);
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}

.practice-row + .practice-row {
  border-top: 1px solid var(--border);
}

.practice-row:active {
  background: var(--highlight);
}

.practice-row .tx {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.practice-row .t1 {
  font-size: 1rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

.practice-row .t2 {
  font-size: 0.78rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
}

.practice-row .chev {
  color: var(--accent-soft);
  font-size: 1.1rem;
}

/* 各集的列表：集号加粗，右边写这个等级有几段（练过几段） */
.practice-row .ep-code {
  font-weight: 600;
}

.practice-row .cnt {
  font-size: 0.85rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* 一集的片段：左上角「‹ 练习」，下面集号、片名和「中高级 · 19 段」 */
.practice-back {
  display: inline-block;
  margin: 0.1rem 0 0.4rem;
  padding: 0.25rem 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--accent);
  white-space: nowrap;
  cursor: pointer;
}

/* 字号和下面片段列表的两行一样（2026-11-05 Weiwei：几行字大小不一，看着乱）：集号片名同片段名，「初级 · 4 段」同「10 句 · 27 秒」；
   左边和片段名对齐 */
.practice-ep-head {
  margin: 0.25rem calc(0.9rem + 1px) 0.9rem;
}

.practice-ep-head .name {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  font-size: 1rem;
  color: var(--text);
}

.practice-ep-head .name b {
  flex: none;
  font-weight: 600;
}

/* 英文片名小一号、浅灰（2026-11-05 Weiwei：太挤、字太多）；长名字折行时第二行和片名第一个字母对齐，不顶到集号下面 */
.practice-ep-head .name span {
  min-width: 0;
  font-size: 0.85rem;
  color: var(--text-muted);
}

/* 吸顶（?dev=1，2026-11-05 Weiwei 定，照 iPhone 的导航栏：往上滑时标题那一栏一直在最上面）。
   练习页的等级按钮、一集里的「‹ 练习」和集号片名、看剧列表的「EchoLine 老友记英语学习」。
   底色和页面一样，左右伸到屏幕边；内容滑到它下面时多一条细线（body.scrolled，js/nav.js） */
.practice-sticky {
  position: sticky;
  top: var(--safe-top);
  z-index: 3;
  margin: -1rem -1rem 0;
  padding: 0.6rem 1rem 0.5rem;
  background: var(--bg);
}

.practice-sticky .practice-ep-head {
  margin-bottom: 0.2rem;
}

.has-tabbar #episode-list-page .header {
  position: sticky;
  top: var(--safe-top);
  z-index: 3;
  margin: -1rem -1rem 0.75rem;
  padding: 1rem 1rem 0.75rem;
  background: var(--bg);
}

.has-tabbar.scrolled .practice-sticky,
.has-tabbar.scrolled #episode-list-page .header {
  box-shadow: 0 1px 0 var(--border);
}

/* 主屏幕图标打开时状态栏那一条：内容滑上去时不从状态栏下面露出来 */
.has-tabbar::before {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--safe-top);
  background: var(--bg);
  z-index: 4;
}

.practice-ep-head .meta {
  margin-top: 0.1rem;
  font-size: 0.78rem;
  color: var(--text-muted);
}

/* 等级按钮下面「共 N 段」：跟着列表滑走 */
.practice-total {
  margin: 0.45rem 0.2rem 0;
  font-size: 0.78rem;
  color: var(--text-muted);
}

.practice-empty {
  padding: 2rem 0;
  text-align: center;
  font-size: 0.9rem;
  color: var(--text-muted);
}

/* 片段播放页：上面写场景名和「S08E09 · 10 句 · 27 秒」，只显示这一段的句子 */
.scene-head {
  flex-shrink: 0;
  padding: 0 1rem 0.6rem;
}

.scene-name {
  font-size: 1rem;
  font-weight: 600;
}

.scene-meta {
  font-size: 0.78rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.scene-video-wrap {
  position: relative;
}

#player-page.scene-mode #video {
  cursor: pointer;
}

#player-page.scene-mode .subtitle-line.off-scene {
  display: none;
}

/* 看剧：每个片段开头一行场景名，和左边的序号对齐（句子留白 + 边框）（2026-11-05 Weiwei 定，原来和台词对齐） */
.scene-title {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  width: 100%;
  min-height: 2.75rem;
  margin: 0;
  padding: 0.6rem 0.25rem 0.1rem calc(1rem + 1px);
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}

.scene-title span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.scene-title svg {
  display: none;
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* 正在放的那一段：深咖色、带循环图标；正在循环的那一段再加粗 */
.scene-title.cur,
.scene-title.on {
  color: var(--accent);
}

.scene-title.on {
  font-weight: 600;
}

.scene-title.cur svg,
.scene-title.on svg {
  display: block;
}

/* 收藏页：「‹ 我的」那一行右边一排等级按钮 */
.fav-top {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding-right: 1rem;
}

.practice-row .done {
  color: var(--accent);
  font-size: 0.78rem;
  white-space: nowrap;
}

/* 片段右上角的页签「跟读 扮演」，和「‹ 练习」同一行 */
#player-page.scene-mode {
  position: relative;
}

.scene-tabs {
  position: absolute;
  top: 0.4rem;
  right: 1rem;
  z-index: 1;
}

.scene-tabs button {
  padding: 0.3rem 0.75rem;
  font-size: 0.82rem;
}

/* ---------- 扮演（?dev=1，js/roleplay.js） ---------- */
/* 视频下面那一行只留字幕和语速，「正在播放原声」「正在录音」写在它下面（和段落循环的提示同一个位置） */
.role-hint {
  display: none;
}

.role-mode .role-hint:not([hidden]) {
  display: block;
}

.role-mode .range-btn,
.role-mode .range-hint:not(.role-hint) {
  display: none;
}

.role-mode .video-controls-overlay {
  justify-content: flex-end;
}

.role-panel {
  padding: 0.6rem 1rem 0.75rem;
  background: rgba(248, 246, 243, 0.98);
  border-top: 1px solid var(--border);
}

.role-panel[hidden] {
  display: none;
}

.role-ask {
  margin: 0 0 0.55rem;
  font-size: 0.9rem;
}

.role-err {
  margin: 0 0 0.55rem;
  font-size: 0.82rem;
  line-height: 1.4;
  color: var(--rec);
}

.role-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.65rem;
}

.role-chip {
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--accent-soft);
  border-radius: 999px;
  background: var(--bg-card);
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--text);
  white-space: nowrap;
  cursor: pointer;
}

.role-chip.on {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.role-chip small {
  margin-left: 0.25rem;
  font-size: 0.75rem;
  opacity: 0.75;
}

.role-primary,
.role-secondary {
  padding: 0.5rem 1.1rem;
  border-radius: 8px;
  font-family: inherit;
  font-size: 0.95rem;
  white-space: nowrap;
  cursor: pointer;
}

.role-primary {
  border: 0;
  background: var(--accent);
  color: #fff;
}

.role-primary:disabled {
  opacity: 0.4;
  cursor: default;
}

.role-secondary {
  border: 1px solid var(--accent-soft);
  background: var(--bg-card);
  color: var(--accent);
}

.role-end b {
  display: block;
  margin-bottom: 0.55rem;
  font-size: 1rem;
  font-weight: 600;
}

.role-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* 台词前面的名字：小一号、加粗、灰色；用户扮演的句子左边一条深咖色竖线，名字也是深咖色 */
.subtitle-line .role-who {
  margin-right: 0.35rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
}

.role-mode .subtitle-line.role-mine {
  border-left: 3px solid var(--accent);
  border-radius: 0 8px 8px 0;
  padding-left: calc(1rem - 3px);
}

.role-mode .subtitle-line.role-mine .role-who {
  color: var(--accent);
}

.role-mode .subtitle-line .fav-star,
.role-mode .subtitle-line .line-acts {
  display: none;
}

/* 录音中的那一句右边：红底白方块的停止键（和跟读的一样）。
   用户的句子右边一直留着它的位置，停止键出现、消失时台词不重新折行，不会上下跳 */
.role-mode .subtitle-list .subtitle-line.role-mine {
  position: relative;
  padding-right: 3rem;
}

.role-stop {
  position: absolute;
  right: 0.25rem;
  top: 50%;
  width: 2.75rem;
  height: 2.75rem;
  margin: -1.375rem 0 0;
  padding: 0;
  border: 0;
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.role-stop::before {
  content: "";
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--rec);
  animation: rec-ring 1.4s ease-out infinite;
}

.role-stop::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 2px;
  background: #fff;
}

@media (prefers-reduced-motion: reduce) {
  .role-stop::before { animation: none; }
}

/* ---------- 填空（?dev=1，js/fill.js） ---------- */
/* 视频下面那一行只留字幕和语速；进度和小结在它下面（和扮演的选角色同一个位置） */
.fill-mode .range-btn,
.fill-mode .range-hint {
  display: none;
}

.fill-mode .video-controls-overlay {
  justify-content: flex-end;
}

.fill-panel {
  padding: 0.6rem 1rem 0.65rem;
  background: rgba(248, 246, 243, 0.98);
  border-top: 1px solid var(--border);
}

.fill-panel[hidden] {
  display: none;
}

.fill-progress {
  margin: 0;
  font-size: 0.85rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.fill-end b {
  display: block;
  font-size: 1rem;
  font-weight: 600;
}

.fill-end p {
  margin: 0.3rem 0 0;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.fill-end .role-primary {
  margin-top: 0.6rem;
}

/* 台词：原来的文字换成填空这一份（英文一律显示，空着一处；下面是选项） */
.fill-mode .subtitle-line .text-wrap,
.fill-mode .subtitle-line .fav-star,
.fill-mode .subtitle-line .line-acts {
  display: none;
}

.subtitle-line .fill-wrap {
  flex: 1;
  min-width: 0;
}

.fill-blank {
  display: inline-block;
  min-width: 4.5em;
  border-bottom: 1.5px solid var(--accent);
  text-align: center;
  line-height: 1.2;
  vertical-align: baseline;
}

.fill-blank:empty::before {
  content: "\00a0";
}

.fill-blank.right {
  min-width: 0;
  padding: 0 0.15em;
  color: var(--good);
  border-color: var(--good);
  font-weight: 600;
}

.fill-blank.wrong {
  min-width: 0;
  padding: 0 0.15em;
  color: var(--ok);
  border-color: var(--ok);
  font-weight: 600;
}

.fill-opts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.6rem;
}

.fill-opts button {
  min-height: 2.5rem;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--accent-soft);
  border-radius: 8px;
  background: var(--bg-card);
  font-family: inherit;
  font-size: 0.95rem;
  color: var(--text);
  white-space: nowrap;
  cursor: pointer;
}

.fill-opts button:disabled {
  color: var(--text-muted);
  opacity: 1;
  cursor: default;
}

.fill-opts button.right {
  border-color: var(--good);
  color: var(--good);
  font-weight: 600;
}

.fill-opts button.wrong {
  border-color: var(--ok);
  color: var(--ok);
  text-decoration: line-through;
}

.fill-verdict {
  display: block;
  margin-top: 0.45rem;
  font-size: 0.85rem;
}

.fill-verdict.right {
  color: var(--good);
}

.fill-verdict.wrong {
  color: var(--ok);
}

/* 填空、错题本不放画面（2026-11-05 Weiwei：画面不动，占地方）。点句子照样出声，没有单句音频的集用视频自己的声音 */
.fill-mode .scene-video-wrap,
#mistakes-page .fav-video-wrap {
  display: none;
}

/* 播放页、收藏页、错题本页钉在看得见的那一块里，整页不能上下滑（2026-11-06）：
   原来页面高 100vh / 100dvh，再加上 #app 上下给刘海和底部横条留的空，整页比屏幕高出几十像素；
   从滑到下面的列表点进来时页面停在往上推过的位置，右上角「跟读 填空 扮演」被顶出屏幕。
   改成固定在屏幕上、上下各让出安全区，不靠 vh 算高度，iPad、iPhone 的 Safari 工具栏收起展开都对得上 */
.has-tabbar #player-page,
.has-tabbar #favorites-page,
.has-tabbar #mistakes-page {
  position: fixed;
  top: var(--safe-top);
  bottom: var(--safe-bottom);
  left: 0;
  right: 0;
  height: auto;
  min-height: 0;
}

/* 点词（?dev=1，js/gloss.js）：有释义的词下面一条浅咖色虚线；点开时这个词（分开的短语几段一起）带浅咖底色 */
.gl {
  text-decoration: underline dashed var(--accent-soft);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  border-radius: 3px;
  cursor: pointer;
}

.gl.on {
  background: rgba(139, 115, 85, 0.16);
  text-decoration-color: var(--accent);
}

/* 跟读打分标了红线的词，不再叠一条虚线 */
.w-bad .gl,
.w-miss .gl {
  text-decoration: none;
}

/* 释义行：在这一句下面（双语时在中文后面），词照词典写法、咖色，后面是中文意思。
   放进一张白色小卡片，和中文字幕分开（2026-11-06 Weiwei：没有底色时埋在双语后面看不出来） */
.gloss-line {
  display: table;
  margin-top: 0.45rem;
  padding: 0.35rem 0.65rem;
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--text);
  background: var(--bg-card);
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(61, 58, 54, 0.1);
}

.gloss-line b {
  color: var(--accent);
  font-weight: 600;
  margin-right: 0.5em;
}

/* 扮演进行中不提供点词 */
.gloss-off .gl {
  text-decoration: none;
  cursor: inherit;
}

.gloss-off .gloss-line {
  display: none;
}
