/* ============================================================
   My IELTS Journey · 样式表
   ------------------------------------------------------------
   视觉方向：iPhone / iOS（需求指定的方向）
   设计要点：
     · 三级灰度层次（主文字 / 次文字 / 三级文字）拉开主次
     · 只有两个颜色承载含义：蓝 = 你现在的位置，橙 = 目标与考期
     · 三种容器区分层级：英雄区（无卡）→ 数据条（无卡）→ 分组卡
     · 动效只保留一处：四科标尺生长到位
   ============================================================ */

/* ============================================================
   1. 设计令牌
   ============================================================ */

:root {
  color-scheme: light;

  /* ---- iOS 系统色（浅色）---- */
  --ios-blue:   #007AFF;
  --ios-green:  #34C759;
  --ios-indigo: #5856D6;
  --ios-orange: #FF9500;
  --ios-pink:   #FF2D55;
  --ios-purple: #AF52DE;
  --ios-red:    #FF3B30;
  --ios-teal:   #5AC8FA;
  --ios-yellow: #FFCC00;
  --ios-gray:   #8E8E93;

  /* ---- 三级灰度层次（结构靠它，不靠颜色）---- */
  --label:   #000000;
  --label-2: rgba(60, 60, 67, .60);
  --label-3: rgba(60, 60, 67, .30);

  /* ---- 背景与容器 ---- */
  --bg:      #F2F2F7;
  --surface: #FFFFFF;

  /* ---- 背景水印（Born to win）----
     三档渐变：左上 Apple 蓝 → 中间靛 → 右下偏紫。
     想整体调浓/调淡，把这三个 alpha 一起改就行（现在约 0.17~0.24）。
     ⚠️ 2026-09-18：第一版给了 0.062，实测只有 5% 的浓度，用户反馈"根本看不见"。
     所以调到现在的档位 —— 灰字压在它上面时对比度只从 3.29 降到 2.93，代价很小。 */
  /* 水印浓淡（浅色主题）：
     ⚠️ 2026-09-19 从 .24/.20/.17 降到了 .13/.115/.10 —— 因为水印从"内容底下"
     挪到了"内容上面"（见 body::before 的说明），现在它要压在**白色卡片**上，
     原来的浓度压在白卡片上会蓝得刺眼。现在的值是这样定的：
     白卡片上大约有 30/255 的浅蓝染色（看得见、又不脏），灰底上同样约 30/255。 */
  --wm-a: rgba(0, 122, 255, .15);
  --wm-b: rgba(88, 86, 214, .135);
  --wm-c: rgba(140, 92, 210, .115);

  /* ---- 分割线与填充 ---- */
  --sep:    rgba(60, 60, 67, .26);
  --fill-1: rgba(120, 120, 128, .20);
  --fill-2: rgba(120, 120, 128, .12);
  --fill-3: rgba(120, 120, 128, .07);

  /* ---- 含义色：全页只有这两个 ---- */
  --now:  var(--ios-blue);     /* 蓝：你现在的位置 / 可交互 */
  --goal: var(--ios-orange);   /* 橙：目标分 / 考期 */

  /* ---- 科目色（只用在 8px 圆点上）---- */
  --c-listening: var(--ios-blue);
  --c-reading:   var(--ios-green);
  --c-writing:   var(--ios-orange);
  --c-speaking:  var(--ios-purple);
  --c-full:      var(--ios-indigo);   /* 套卷（一整份试卷） */
  --c-vocab:     var(--ios-teal);
  --c-grammar:   var(--ios-pink);
  --c-other:     var(--ios-gray);

  /* ---- 字号阶梯（iOS 规范）---- */
  --fs-hero:    34px;
  --fs-title:   22px;
  --fs-body:    17px;
  --fs-callout: 15px;
  --fs-foot:    13px;
  --fs-caption: 11px;

  /* ---- 圆角 ---- */
  --r-card:  10px;
  --r-btn:   12px;
  --r-field: 10px;

  --nav-bg: rgba(249, 249, 249, .80);
  --bar-bg: rgba(249, 249, 249, .82);
  --shadow-sheet: 0 12px 40px rgba(0, 0, 0, .18);

  /* 导航栏高度。标签栏的粘性阈值必须和它相等 ——
     写死成别的数字（比如原来的 56px）会让标签栏被强行下推，
     压住下面大标题的顶部。两处共用这一个变量就不会错位。 */
  --nav-h: 48px;

  /* 内容区宽度：默认跟着屏幕走、上限 1080px ——
     原来写死 820px，1280 的桌面上两边各空 230px；iPad 横屏（1024）也白空 102px。
     ⚠️ main / .tabs / .foot 共用这一个值，改的时候一起看。 */
  --content-w: min(1080px, calc(100vw - 48px));

  /* 四科标尺「名字」那一列的宽度。
     ⚠️ .bandRows 和 .bandAxis 必须用同一个值（轴线要和横条对齐），所以抽成变量。
     中文两三个字 46px 够用；英文 Listening / Speaking 更长，在下面按语言放宽。 */
  --band-name-w: 46px;
  /* ---- 兼容 README 里"调色盘"提到的名字 ---- */
  --primary:      var(--now);
  --primary-soft: rgba(0, 122, 255, .12);
  --muted:        var(--label-2);
  --line:         var(--sep);
  --success:      var(--ios-green);
  --warn:         var(--goal);
  --danger:       var(--ios-red);
  --radius:       var(--r-card);
  --shadow:       none;
}

html[data-theme="dark"] {
  color-scheme: dark;

  /* ---- iOS 系统色（深色，Apple 官方变体）---- */
  --ios-blue:   #0A84FF;
  --ios-green:  #30D158;
  --ios-indigo: #5E5CE6;
  --ios-orange: #FF9F0A;
  --ios-pink:   #FF375F;
  --ios-purple: #BF5AF2;
  --ios-red:    #FF453A;
  --ios-teal:   #64D2FF;
  --ios-yellow: #FFD60A;
  --ios-gray:   #98989D;

  --label:   #FFFFFF;
  --label-2: rgba(235, 235, 245, .60);
  --label-3: rgba(235, 235, 245, .30);

  /* 深色不用纯黑，用深灰 + 略亮的卡片 —— 和微信深色模式的观感一致。
     Apple 官方的 secondarySystemBackground / systemGray5 正好是这两个值。 */
  --bg:      #1C1C1E;   /* 底色（原来是 #000000 纯黑） */
  --surface: #2C2C2E;   /* 卡片，比底色略亮一档 */

  /* 深色下换成"发光的浅蓝紫"，同样靠这三个令牌调浓淡 */
  /* 深色下同样要跟着降（水印现在压在卡片上）。实测：.22 时卡片上最强处
     比原来亮 49/255，偏强；降到 .18 约 40/255，和浅色主题的手感一致。 */
  --wm-a: rgba(120, 190, 255, .18);
  --wm-b: rgba(150, 150, 250, .16);
  --wm-c: rgba(190, 150, 250, .14);

  --sep:    rgba(84, 84, 88, .60);
  --fill-1: rgba(120, 120, 128, .40);
  --fill-2: rgba(120, 120, 128, .28);
  --fill-3: rgba(120, 120, 128, .16);

  --nav-bg: rgba(28, 28, 30, .82);
  --bar-bg: rgba(28, 28, 30, .88);
  --shadow-sheet: 0 12px 40px rgba(0, 0, 0, .6);

  --primary-soft: rgba(10, 132, 255, .20);
}

/* ============================================================
   2. 基础
   ============================================================ */

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--label);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
               "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", sans-serif;
  font-size: var(--fs-body);
  line-height: 1.42;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3 { margin: 0; font-weight: 600; }

/* hidden 属性必须永远生效。
   浏览器默认样式里的 [hidden] 优先级很低，只要元素自己写了 display（比如
   .bandAxis 的 display: grid），hidden 就会被无视。加这条兜底，
   以后凡是用 el.hidden = true 隐藏元素都不会失效。 */
[hidden] { display: none !important; }

/* 所有数字用等宽数位 —— 数据类界面必须的，列才能对齐 */
.kpiValue, .statVal, .bandVal, .ringVal, .barVal, .hbarTop b,
.timerDisplay, .miniStats b, .bandAxis, .countdown, td.num, .progressTop {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

/* iOS 的按压反馈是"变暗"，不是缩放 */
button:active { opacity: .55; }
button:disabled { opacity: .35; }

/* ============================================================
   3. 导航栏（毛玻璃）
   ============================================================ */

.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  /* 高度写死成 --nav-h，只用横向内边距，垂直靠 flex 居中 ——
     这样实际高度一定等于 --nav-h，下面的标签栏才能严丝合缝地贴在它下面 */
  height: var(--nav-h);
  padding: 0 16px;
  background: var(--nav-bg);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid var(--sep);
}

.brand { display: flex; align-items: center; gap: 9px; min-width: 0; }

/* 应用标记：圆角方块里一根阶梯上升的线 + 终点圆点，表示"进度"。
   用矢量图而不是 emoji —— emoji 在不同系统上长相不一，也显得随意。 */
.brandMark {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: linear-gradient(150deg, #4C9BFF 0%, #007AFF 48%, #4B4BE8 100%);
  box-shadow: 0 1px 2px rgba(0, 70, 180, .30);
}
.brandMark svg { width: 100%; height: 100%; display: block; }
.brandMark-lg {
  width: 84px;
  height: 84px;
  border-radius: 22px;
  margin: 0 auto 18px;
  box-shadow: 0 12px 30px -12px color-mix(in srgb, var(--now) 78%, transparent);
}

.brand h1 { font-size: var(--fs-body); font-weight: 600; white-space: nowrap; letter-spacing: -.012em; }
.brand .sub { margin: 0; font-size: var(--fs-foot); color: var(--label-2); }

.topActions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }

/* 考期倒计时：用"目标橙"，和页面里所有"目标"信息同一含义 */
.countdown {
  font-size: var(--fs-foot);
  font-weight: 600;
  color: var(--goal);
  background: color-mix(in srgb, var(--goal) 13%, transparent);
  padding: 4px 10px;
  border-radius: 999px;
  white-space: nowrap;
}
.countdown:empty { display: none; }

#btnAuth {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 2px;
  border: none;
  background: transparent;
  color: var(--now);
  font-size: var(--fs-body);
  font-weight: 400;
  font-family: inherit;
  cursor: pointer;
  max-width: 46vw;
  overflow: hidden;
  white-space: nowrap;
}
#btnAuth .navLabel { overflow: hidden; text-overflow: ellipsis; }

.iconBtn {
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--now);
  font-size: var(--fs-body);
  font-family: inherit;
  cursor: pointer;
  padding: 0;
}

/* ============================================================
   4. 标签栏
   桌面：iOS 18 风格顶部分段控件 ／ 手机：底部标签栏
   ============================================================ */

.tabs {
  position: sticky;
  /* 必须等于导航栏高度，见 :root 里 --nav-h 的说明 */
  top: var(--nav-h);
  z-index: 20;
  display: flex;
  gap: 2px;
  padding: 8px 16px 14px;
  max-width: var(--content-w);
  margin: 0 auto;
  background: var(--bg);
}

.tabs::before {
  content: '';
  position: absolute;
  left: 16px;
  right: 16px;
  top: 8px;
  height: calc(100% - 22px);
  background: var(--fill-2);
  border-radius: 9px;
  z-index: -1;
}

.tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  flex: 1 1 0;
  min-width: 0;
  padding: 6px 8px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--label);
  font-size: var(--fs-foot);
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
}

.tab.is-active {
  background: var(--surface);
  font-weight: 600;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .10), 0 0 0 .5px rgba(0, 0, 0, .04);
}
html[data-theme="dark"] .tab.is-active { background: var(--fill-1); box-shadow: none; }

.tab svg {
  width: 17px;
  height: 17px;
  flex: 0 0 auto;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ============================================================
   5. 主区域与大标题
   ============================================================ */

main {
  max-width: var(--content-w);
  margin: 0 auto;
  padding: 0 16px 44px;
}

.view { display: none; }
.view.is-active { display: block; }

.largeTitle {
  font-size: var(--fs-hero);
  font-weight: 700;
  letter-spacing: -.026em;
  line-height: 1.14;
  margin: 2px 0 2px;
}

.viewSub {
  margin: 0 0 20px;
  font-size: var(--fs-foot);
  color: var(--label-2);
}

.viewHead {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.viewHead .largeTitle { margin-bottom: 0; }
.viewHead .viewSub { margin: 2px 0 0; }

/* 只有标题、下面还跟着 .viewSub 的页面：这层包裹不要再叠一份 20px 下边距，
   否则副标题会被推得离标题很远（.viewHead 原本是给"标题 + 按钮"用的）。 */
.viewHead.terse { margin-bottom: 0; }

.section { margin-bottom: 22px; }
.section:last-child { margin-bottom: 0; }

/* ============================================================
   6. 分组卡（列表和图表用）
   ============================================================ */

.cardHead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 0 16px 7px;
  flex-wrap: wrap;
}
.cardHead h2 {
  font-size: var(--fs-foot);
  font-weight: 400;
  color: var(--label-2);
}
.hint { font-size: var(--fs-foot); color: var(--label-3); }

.card {
  background: var(--surface);
  border-radius: var(--r-card);
  padding: 16px;
  min-width: 0;
  overflow: hidden;
}
.card.flush { padding: 0; }
.card.flush .tableWrap { margin: 0; }

.grid { display: block; }

/* ============================================================
   7. 英雄区：唯一的高光位置（无卡片）
   ------------------------------------------------------------
   四科共用 0–9 分制是雅思独有的结构，所以把"四科对照标尺"
   放在这里，一根橙色竖线贯穿四行代表目标分。
   ============================================================ */

.hero {
  margin: 0 0 26px;
  padding: 0 4px;
}

.heroTop {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}

.heroStill { font-size: var(--fs-callout); color: var(--label-2); }
.heroDays {
  font-size: 46px;
  font-weight: 700;
  letter-spacing: -.035em;
  line-height: 1;
  color: var(--goal);
}
.heroDaysUnit {
  font-size: var(--fs-callout);
  font-weight: 600;
  color: var(--goal);
  margin-left: 4px;
}
.heroTarget {
  font-size: var(--fs-foot);
  color: var(--label-2);
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.heroTarget b { color: var(--goal); font-weight: 600; }

/* 目标色小色块：让"橙色 = 目标"这个关联不用图例也能看懂 */
.goalSwatch {
  display: inline-block;
  width: 2px;
  height: 13px;
  border-radius: 1px;
  background: var(--goal);
}

/* ---- 四科对照标尺 ---- */
.bandChart { position: relative; }

/* 行高固定 20px（不用 row-gap，靠单元格高度形成节奏），
   这样轨道之间的真实间距是确定的 11px，刻度溢出 6px 就能连成竖线 */
.bandRows {
  display: grid;
  grid-template-columns: var(--band-name-w) 1fr 38px;
  column-gap: 10px;
}

.bandName {
  height: 20px;
  display: flex;
  align-items: center;
  font-size: var(--fs-foot);
  color: var(--label-2);
  white-space: nowrap;
}

.bandTrack {
  position: relative;
  height: 9px;
  align-self: center;
  border-radius: 4.5px;
  background: var(--fill-1);
}
.bandTrack i {
  display: block;
  height: 100%;
  border-radius: 4.5px;
  background: var(--now);
  /* 全页唯一保留的动效：数据变了，标尺生长到位 */
  transition: width .7s cubic-bezier(.32, .72, 0, 1);
}

/* 目标刻度：每一行画在**本行那一科**的目标分上（四科目标不一样时，
   刻度就不在同一条竖线上——这正是"刻度和本行分数对齐"的意思）。
   上下各溢出 6px，正好盖住 11px 的行间距，单看一行时也是个完整的标记。 */
.bandTick {
  position: absolute;
  top: -6px;
  bottom: -6px;
  width: 2px;
  margin-left: -1px;
  border-radius: 1px;
  background: var(--goal);
}

.bandVal {
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  font-size: var(--fs-callout);
  font-weight: 600;
  color: var(--label);
}
.bandVal.is-empty { color: var(--label-3); font-weight: 400; }

.bandAxis {
  display: grid;
  grid-template-columns: var(--band-name-w) 1fr 38px;
  column-gap: 10px;
  margin-top: 7px;
}
/* 刻度数字按"分数的真实位置"摆放（0/3/4.5/6/9 不是等距的，
   所以不能用 space-between 均分，得用百分比定位）。 */
.bandAxisInner {
  grid-column: 2;
  position: relative;
  height: 15px;
  font-size: var(--fs-caption);
  color: var(--label-3);
}
.bandAxisInner span {
  position: absolute;
  top: 0;
  white-space: nowrap;
}

/* 空状态提示。⚠️ 必须写 grid-column: 1 / -1：
   .bandRows 是三列网格（名字 46px / 轨道 1fr / 分数 38px），
   这段文字如果不跨列，会被自动排进第一列，也就是被挤进 46px 宽的
   名字列里 —— 每行只能放两三个字，看起来就是"竖排文字"。 */
.bandEmpty {
  grid-column: 1 / -1;
  font-size: var(--fs-callout);
  color: var(--label-2);
  line-height: 1.6;
  padding: 4px 0 4px;
  max-width: 46em;
}

/* 平均分的口径切换（英雄区右下角的小分段控件）。
   复用 .segSwitch / .segBtn（和登录页那个"验证码/密码"是同一套），
   只是这里要小一号、并且不要 .segSwitch 自带的下外边距。 */
.avgModeBar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.segMini { flex: 0 0 auto; margin-bottom: 0; padding: 2px; }
.segMini .segBtn { flex: 0 0 auto; padding: 5px 11px; font-size: var(--fs-foot); }

/* ============================================================
   8. 数据条：数字直接排在灰底上，不用卡片
   ============================================================ */

.statStrip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--sep);
  border-radius: var(--r-card);
  overflow: hidden;
  margin-bottom: 26px;
}
html[data-theme="dark"] .statStrip { background: var(--surface); }

.stat {
  background: var(--bg);
  padding: 13px 12px 14px;
  min-width: 0;
}
html[data-theme="dark"] .stat { background: var(--bg); }

.statVal {
  font-size: var(--fs-title);
  font-weight: 700;
  letter-spacing: -.022em;
  line-height: 1.15;
  color: var(--label);
}
.statVal small { font-size: var(--fs-foot); font-weight: 600; color: var(--label-2); margin-left: 3px; }
.statLabel {
  font-size: var(--fs-foot);
  color: var(--label-2);
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 今日目标的细进度线 */
.statBar {
  height: 3px;
  border-radius: 2px;
  background: var(--fill-1);
  margin-top: 7px;
  overflow: hidden;
}
.statBar i {
  display: block;
  height: 100%;
  border-radius: 2px;
  background: var(--now);
  transition: width .7s cubic-bezier(.32, .72, 0, 1);
}
.statBar.is-done i { background: var(--ios-green); }

/* 兼容旧的 KPI 结构（其他视图仍可能用到） */
.kpis { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 22px; }
.kpi { background: var(--surface); border-radius: var(--r-card); padding: 14px 16px; min-width: 0; }
.kpi .kpiLabel { font-size: var(--fs-foot); color: var(--label-2); display: flex; align-items: center; gap: 5px; }
.kpi .kpiValue { font-size: var(--fs-title); font-weight: 700; letter-spacing: -.022em; margin-top: 2px; line-height: 1.15; }
.kpi .kpiUnit { font-size: var(--fs-callout); font-weight: 600; color: var(--label-2); margin-left: 3px; }
.kpi .kpiFoot { font-size: var(--fs-caption); color: var(--label-3); margin-top: 2px; }

/* 旧的进度环（保留样式，仪表盘已不用）*/
.ringWrap { display: flex; justify-content: center; padding: 4px 0 6px; }
.ring { width: 160px; height: 160px; }
.ringBg { fill: none; stroke: var(--fill-2); stroke-width: 12; }
.ringFg { fill: none; stroke: var(--now); stroke-width: 12; stroke-linecap: round; transition: stroke-dashoffset .7s cubic-bezier(.32, .72, 0, 1); }
.ringVal { font-size: 30px; font-weight: 700; fill: var(--label); text-anchor: middle; letter-spacing: -.02em; }
.ringSub { font-size: var(--fs-caption); fill: var(--label-2); text-anchor: middle; }

.miniStats { display: flex; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--sep); }
.miniStats div { flex: 1; text-align: center; }
.miniStats div + div { border-left: 1px solid var(--sep); }
.miniStats b { display: block; font-size: var(--fs-body); font-weight: 600; }
.miniStats span { font-size: var(--fs-caption); color: var(--label-2); }

/* ============================================================
   9. 图表
   ============================================================ */

.bars { display: flex; align-items: stretch; gap: 7px; height: 150px; }
.barCol { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 0; }
.barVal { font-size: var(--fs-caption); color: var(--label-2); font-weight: 500; height: 13px; line-height: 13px; }
.barTrack { flex: 1; width: 100%; display: flex; align-items: flex-end; }
.barFill {
  width: 100%;
  border-radius: 5px;
  background: var(--fill-1);
  min-height: 3px;
  transition: height .6s cubic-bezier(.32, .72, 0, 1);
}
.barCol.is-today .barFill { background: var(--now); }
.barLabel { font-size: var(--fs-caption); color: var(--label-3); }
.barCol.is-today .barLabel { color: var(--now); font-weight: 600; }

.hbar { margin-bottom: 14px; }
.hbar:last-child { margin-bottom: 0; }
.hbarTop { display: flex; justify-content: space-between; font-size: var(--fs-callout); margin-bottom: 6px; }
.hbarTop b { font-weight: 600; }
.hbarTrack { height: 8px; background: var(--fill-2); border-radius: 4px; overflow: hidden; }
.hbarTrack i { display: block; height: 100%; border-radius: 4px; transition: width .6s cubic-bezier(.32, .72, 0, 1); }

.lineChart { width: 100%; height: auto; display: block; overflow: visible; }
.lineChart .grid { stroke: var(--sep); stroke-width: 1; stroke-dasharray: 2 5; }
.lineChart .axis { font-size: 9px; fill: var(--label-3); }
/* 连线要比圆点"粗"一点才看得出是连起来的 ——
   原来是线 2.5px、点半径 3.5px（直径 7px），点比线抢眼，看着像一串散点。 */
.lineChart .line { fill: none; stroke: var(--now); stroke-width: 3; stroke-linejoin: round; stroke-linecap: round; }
.lineChart .dot { stroke: var(--surface); stroke-width: 1.2; }
.lineChart .xlab { font-size: 9px; fill: var(--label-3); text-anchor: middle; }

.legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: var(--fs-foot); color: var(--label-2); margin-top: 10px; }
.legend i { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 5px; }

/* 空状态：不是装饰，是邀请 —— 说清下一步做什么 */
.empty {
  text-align: center;
  color: var(--label-2);
  font-size: var(--fs-callout);
  padding: 26px 16px;
  line-height: 1.55;
}

/* ============================================================
   10. 列表行
   ============================================================ */

.taskList { list-style: none; margin: 0 -16px; padding: 0; }

.taskItem {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 11px 16px;
  min-height: 44px;
  position: relative;
}
.taskItem + .taskItem::before {
  content: '';
  position: absolute;
  top: 0;
  left: 16px;
  right: 0;
  height: 1px;
  background: var(--sep);
}

.taskItem.is-done .taskText { color: var(--label-3); text-decoration: line-through; }

.check {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  margin: 1px 0 0;
  border: 1.8px solid var(--label-3);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  color: transparent;
  font-family: inherit;
  padding: 0;
}
.check:hover { border-color: var(--now); }
.taskItem.is-done .check { background: var(--now); border-color: var(--now); color: #fff; }

.taskMain { flex: 1; min-width: 0; }
.taskText { font-size: var(--fs-body); word-break: break-word; line-height: 1.35; }

.taskMeta {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 4px;
  font-size: var(--fs-foot);
  color: var(--label-2);
}

.tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 6px;
  font-size: var(--fs-caption);
  font-weight: 500;
  background: var(--fill-2);
  color: var(--label-2);
  white-space: nowrap;
}
.tag-subj {
  background: color-mix(in srgb, var(--c, var(--ios-gray)) 14%, transparent);
  color: var(--c, var(--ios-gray));
}
.tag.p-high { background: color-mix(in srgb, var(--ios-red) 14%, transparent);    color: var(--ios-red); }
.tag.p-mid  { background: color-mix(in srgb, var(--goal) 16%, transparent);       color: var(--goal); }
.tag.p-low  { background: var(--fill-2); color: var(--label-2); }
.tag.ok     { background: color-mix(in srgb, var(--ios-green) 14%, transparent);  color: var(--ios-green); }

.taskActions { display: flex; gap: 6px; flex-shrink: 0; align-items: center; }

.miniBtn {
  padding: 6px 12px;
  border: none;
  border-radius: 8px;
  background: var(--fill-2);
  color: var(--now);
  font-size: var(--fs-foot);
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
}
.miniBtn.del { color: var(--label-2); }

/* ============================================================
   11. 进度条
   ============================================================ */

.progressWrap { margin-bottom: 16px; }
.progressTop { display: flex; justify-content: space-between; font-size: var(--fs-foot); color: var(--label-2); margin-bottom: 7px; }
.progressTop b { color: var(--label); font-weight: 600; }
.progressTrack { height: 7px; background: var(--fill-2); border-radius: 3.5px; overflow: hidden; }
.progressFill { height: 100%; border-radius: 3.5px; background: var(--now); transition: width .6s cubic-bezier(.32, .72, 0, 1); }

/* ============================================================
   12. 胶囊筛选
   ============================================================ */

.quickAdd, .filters { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }

.chip {
  padding: 7px 14px;
  border: none;
  border-radius: 999px;
  background: var(--fill-2);
  color: var(--label);
  font-size: var(--fs-callout);
  font-weight: 400;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
}
.chip.is-active { background: var(--now); color: #fff; font-weight: 500; }

/* ============================================================
   13. 按钮
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 11px 20px;
  border: none;
  border-radius: var(--r-btn);
  background: var(--now);
  color: #fff;
  font-size: var(--fs-body);
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  min-height: 44px;
}
.btn.ghost { background: var(--fill-2); color: var(--now); }
.btn.danger { background: var(--fill-2); color: var(--ios-red); }
.btn.small { padding: 7px 14px; font-size: var(--fs-callout); min-height: 34px; }
.btn.big { padding: 13px 22px; }
.btn.block { width: 100%; }

.btnRow { display: flex; gap: 10px; flex-wrap: wrap; }
.btnRow .btn { flex: 1 1 auto; }

/* ============================================================
   14. 表单控件
   ============================================================ */

input, select, textarea {
  font-family: inherit;
  font-size: var(--fs-body);
  color: var(--label);
  background: var(--fill-2);
  border: none;
  border-radius: var(--r-field);
  padding: 10px 13px;
  outline: none;
  width: 100%;
  -webkit-appearance: none;
  appearance: none;
}
input:focus, select:focus, textarea:focus {
  box-shadow: 0 0 0 3.5px color-mix(in srgb, var(--now) 28%, transparent);
}
textarea { resize: vertical; line-height: 1.45; }
::placeholder { color: var(--label-3); }

select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1.5 1.75L6 6.25l4.5-4.5' fill='none' stroke='%238E8E93' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
}

input.dpField { min-height: 44px; }

.row { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.row input:not([type]), .row input[type="text"] { flex: 1 1 200px; min-width: 0; }
.row select { flex: 0 0 auto; width: auto; min-width: 116px; }

.field { margin-bottom: 16px; }
.field:last-child { margin-bottom: 0; }
.field > label, .dlgLabel {
  display: block;
  font-size: var(--fs-foot);
  font-weight: 400;
  color: var(--label-2);
  margin-bottom: 6px;
  padding-left: 3px;
}

.formGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(178px, 1fr));
  gap: 14px;
  align-items: end;
}
.formGrid label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: var(--fs-foot);
  font-weight: 400;
  color: var(--label-2);
  padding-left: 3px;
}
.formGrid .wide { grid-column: 1 / -1; }
.formFoot {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding-top: 2px;
}

.dateNav { display: flex; align-items: center; gap: 6px; }
.cardHead .dateNav h2 { font-size: var(--fs-title); font-weight: 600; white-space: nowrap; letter-spacing: -.02em; color: var(--label); }

/* ============================================================
   15. 计时器
   ============================================================ */

.timerSubject { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; margin-bottom: 16px; }

.timerDisplay {
  font-size: clamp(52px, 15vw, 76px);
  font-weight: 300;
  text-align: center;
  letter-spacing: -.045em;
  line-height: 1.06;
}
.is-running .timerDisplay { color: var(--now); font-weight: 400; }

.timerSub { text-align: center; font-size: var(--fs-foot); color: var(--label-2); margin-bottom: 20px; }
.timerBtns { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }

/* ============================================================
   16. 评分选择器
   ============================================================ */

.picker { display: flex; gap: 8px; flex-wrap: wrap; }

.pickBtn {
  flex: 1 1 0;
  min-width: 56px;
  padding: 9px 0;
  border: none;
  border-radius: var(--r-btn);
  background: var(--fill-2);
  cursor: pointer;
  text-align: center;
  font-family: inherit;
  color: var(--label);
}
.pickBtn .pe { font-size: 22px; display: block; line-height: 1.15; }
.pickBtn .pl { font-size: var(--fs-caption); color: var(--label-2); display: block; }
.pickBtn.is-active { background: var(--now); }
.pickBtn.is-active .pl { color: rgba(255, 255, 255, .85); font-weight: 500; }

/* ============================================================
   16.5 状态日历
   ============================================================ */

.calHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 34px;
  margin-bottom: 12px;
}
.calMonth {
  font-size: var(--fs-body);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}

/* 状态页默认只显示日历（编辑界面点某天才出现），所以日历可以画大一点撑住整页 */
.calGrid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 6px;
}

.calDow {
  text-align: center;
  font-size: var(--fs-foot);
  color: var(--label-3);
  padding-bottom: 6px;
}

.calCell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 78px;
  padding: 8px 0;
  border: none;
  border-radius: 12px;
  background: transparent;
  color: var(--label);
  font-family: inherit;
  cursor: pointer;
}
.calCell.is-today { background: color-mix(in srgb, var(--now) 13%, transparent); }
.calCell.is-selected { background: var(--now); color: #fff; }
.calCell.is-future { opacity: .28; cursor: default; }

.calNum {
  font-size: var(--fs-body);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.calMark {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  height: 24px;
}
.calEmo { font-size: 18px; font-style: normal; line-height: 1; }

/* 窄屏：格子宽度会掉到 40px 上下，两个 18px 表情并排就顶出去了。
   表情用 min(14px, 3.6vw) 跟着屏幕缩 —— 实测 360px 屏格子 39px、
   两个表情（Windows 的 emoji 比字号宽，约 1.36 倍）需要 ≈2.7×字号 + 1px，
   3.6vw 在 320 / 360 / 430px 三档都留得出余量。别改成固定值。 */
@media (max-width: 430px) {
  .calCell { min-height: 64px; gap: 2px; padding: 6px 0; }
  .calEmo { font-size: min(14px, 3.4vw); }
  .calMark { gap: 1px; height: 20px; }
  .calGrid { gap: 4px; }
}

/* 没记录的日子：一个空的灰色圆环 */
.calDot {
  display: block;
  width: 12px;
  height: 12px;
  border: 2px solid var(--label-3);
  border-radius: 50%;
}
.calCell.is-selected .calDot { border-color: rgba(255, 255, 255, .75); }

/* ============================================================
   自建日期选择器（.dp）
   ------------------------------------------------------------
   原生 <input type="date"> 的弹窗是**浏览器画的**，语言跟系统走，网页里切不成英文
   （用户反馈"小日历里还是中文"）—— 所以 app.js 里照 iPhone 的样子自己画了一个
   （见 dpEnsure / dpRender / setupDatePickers）。
   面板挂在 body 上 + position:fixed：卡片都是 overflow:hidden，挂卡片里面会被裁掉。
   z-index 80：比顶栏(30)/标签栏(20,40)/水印(1) 高，比弹窗(100) 低。
   ============================================================ */
.dp {
  position: fixed;
  z-index: 80;
  width: 272px;
  padding: 10px 12px 12px;
  border-radius: 14px;
  background: var(--surface);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .20), 0 0 0 .5px rgba(0, 0, 0, .06);
}
html[data-theme="dark"] .dp {
  box-shadow: 0 12px 32px rgba(0, 0, 0, .55), 0 0 0 .5px rgba(255, 255, 255, .08);
}
.dpHead { display: flex; align-items: center; justify-content: space-between; gap: 4px; margin-bottom: 6px; }
/* 标题是个按钮：点它切到"选年月"那一层，所以要有按压反馈 */
.dpMonth {
  border: none;
  background: transparent;
  color: var(--label);
  font-family: inherit;
  font-size: var(--fs-callout);
  font-weight: 600;
  letter-spacing: -.01em;
  padding: 4px 8px;
  border-radius: 8px;
  cursor: pointer;
}
/* 第二层：年份 ‹ › + 12 个月（点标题切换过来）*/
.dpYearRow { display: flex; align-items: center; justify-content: space-between; gap: 4px; margin-bottom: 6px; }
.dpYear { font-size: var(--fs-callout); font-weight: 600; font-variant-numeric: tabular-nums; }
.dpMonthGrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.dpMonthBtn {
  height: 42px;
  border: none;
  border-radius: 10px;
  background: var(--fill-3);
  color: var(--label);
  font-family: inherit;
  font-size: var(--fs-foot);
  font-weight: 500;
  cursor: pointer;
}
.dpMonthBtn.is-sel { background: var(--now); color: #fff; font-weight: 600; }
.dpGrid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dpDow { text-align: center; font-size: var(--fs-caption); color: var(--label-3); padding-bottom: 4px; }
.dpDay {
  height: 34px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--label);
  font-family: inherit;
  font-size: var(--fs-foot);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.dpDay.is-today { color: var(--now); font-weight: 700; }
.dpDay.is-sel { background: var(--now); color: #fff; font-weight: 600; }
.dpFoot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 8px; }

/* ⚠️ 2026-09-19：原来这里还有「某一天的详情」那一套（.calEditBtn / .calDetail /
   .calRow / .calNone / .calNote）。用户把状态页改成"默认只留日历、点某天直接进编辑界面"
   之后，那个只读详情整块删掉了，这些类没有任何地方再用，所以一起删了。
   以后要做"只读详情"再重新加，别直接复活这一套。 */

/* ============================================================
   17. 表格
   ============================================================ */

.tableWrap { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 0 -16px; }

/* 超过 8 行时由脚本加上这个类（高度也由脚本锁成 8 行）：
   竖着也能滚，表头钉在顶上别跟着滚走 */
.tableWrap.is-scroll {
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--fill-1) transparent;
}
.tableWrap.is-scroll thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface);
}
.tableWrap.is-scroll::-webkit-scrollbar { width: 6px; }
.tableWrap.is-scroll::-webkit-scrollbar-track { background: transparent; }
.tableWrap.is-scroll::-webkit-scrollbar-thumb { background: var(--fill-1); border-radius: 3px; }

table { width: 100%; border-collapse: collapse; font-size: var(--fs-callout); min-width: 520px; }
th, td { padding: 10px 16px; text-align: left; white-space: nowrap; }
th { font-size: var(--fs-foot); color: var(--label-2); font-weight: 400; border-bottom: 1px solid var(--sep); }
td { border-bottom: 1px solid var(--sep); }
tbody tr:last-child td { border-bottom: none; }
td.num { text-align: right; }

/* ============================================================
   18. 弹窗
   ============================================================ */

.dialog {
  border: none;
  padding: 0;
  background: var(--surface);
  color: var(--label);
  width: min(520px, calc(100vw - 32px));
  max-height: 88vh;
  border-radius: 14px;
  box-shadow: var(--shadow-sheet);
  overflow: hidden;
}
.dialog::backdrop { background: rgba(0, 0, 0, .4); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); }
.dialogInner { padding: 18px 20px 20px; overflow-y: auto; max-height: 88vh; }

.dialog .cardHead {
  padding: 0 0 14px;
  margin: 0 0 18px;
  border-bottom: 1px solid var(--sep);
  align-items: center;
}
.dialog .cardHead h2 { font-size: var(--fs-body); font-weight: 600; color: var(--label); }

.dlgField {
  display: block;
  margin-bottom: 16px;
  font-size: var(--fs-foot);
  font-weight: 400;
  color: var(--label-2);
  padding-left: 3px;
}
.dlgField input, .dlgField select { margin-top: 6px; font-size: var(--fs-body); font-weight: 400; }
.sep { border: none; border-top: 1px solid var(--sep); margin: 18px 0; }

/* ============================================================
   19. 提示 / 页脚
   ============================================================ */

.tip {
  margin: 14px 0 0;
  font-size: var(--fs-foot);
  line-height: 1.5;
  color: var(--label-2);
  background: var(--fill-3);
  border-radius: 8px;
  padding: 10px 12px;
}
.tip b { color: var(--label); font-weight: 600; }

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(28px + env(safe-area-inset-bottom));
  transform: translate(-50%, 16px);
  background: rgba(30, 30, 30, .92);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  color: #fff;
  padding: 11px 20px;
  border-radius: 14px;
  font-size: var(--fs-callout);
  font-weight: 500;
  opacity: 0;
  pointer-events: none;
  transition: opacity .22s ease, transform .22s ease;
  z-index: 100;
  max-width: calc(100vw - 40px);
  text-align: center;
  line-height: 1.4;
}
html[data-theme="dark"] .toast { background: rgba(230, 230, 235, .92); color: #000; }
.toast.is-show { opacity: 1; transform: translate(-50%, 0); }

.foot {
  max-width: var(--content-w);
  margin: 0 auto;
  text-align: center;
  font-size: var(--fs-foot);
  color: var(--label-3);
  padding: 8px 16px 34px;
}

/* ============================================================
   20. 登录 / 注册
   ============================================================ */

.authBadge {
  font-size: var(--fs-foot);
  line-height: 1.5;
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 18px;
}
.authBadge.is-demo   { background: color-mix(in srgb, var(--goal) 13%, transparent);       color: var(--goal); }
.authBadge.is-server { background: color-mix(in srgb, var(--ios-green) 14%, transparent);  color: var(--ios-green); }
.authBadge.is-warn   { background: color-mix(in srgb, var(--ios-red) 13%, transparent);    color: var(--ios-red); }

.codeInput {
  font-size: 30px;
  font-weight: 600;
  letter-spacing: .3em;
  text-indent: .3em;
  text-align: center;
  padding: 14px 10px;
}

.authUserBox {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px;
  border-radius: var(--r-card);
  background: var(--fill-3);
  margin-bottom: 18px;
  min-width: 0;
}
/* ---- 头像 ---- */
.avatar {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--now);
  color: #fff;
  font-weight: 500;
  line-height: 1;
  overflow: hidden;
  user-select: none;
  -webkit-user-select: none;
}
.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.avatar-22 { width: 22px; height: 22px; font-size: 12px; font-weight: 600; }
.avatar-48 { width: 48px; height: 48px; font-size: 24px; }
.avatar-64 { width: 64px; height: 64px; font-size: 32px; }
.avatar-96 { width: 96px; height: 96px; font-size: 48px; }

/* 设置弹窗里的头像入口 */
.avatarRow { display: flex; justify-content: center; margin-bottom: 20px; }
.avatarBtn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  border: none;
  background: transparent;
  cursor: pointer;
  font-family: inherit;
  padding: 0;
}
.avatarEditHint { font-size: var(--fs-foot); color: var(--now); }

/* 更换头像面板 */
.avatarPreviewWrap { display: flex; justify-content: center; margin-bottom: 18px; }

/* 预览圆圈下面的说明。没改动时是"当前头像"，一旦动了就变成醒目的"预览效果" ——
   因为那个圆圈长得和真头像一样，不写清楚会被当成"已经换好了"。 */
.avatarCaption {
  margin: 0 0 18px;
  text-align: center;
  font-size: var(--fs-foot);
  color: var(--label-3);
  line-height: 1.45;
}
.avatarCaption.is-draft { color: var(--now); font-weight: 600; }

/* 还没保存时给预览圈套一圈虚线，表示"这只是草稿" */
.avatarPreviewWrap.is-draft .avatar {
  outline: 2px dashed var(--now);
  outline-offset: 4px;
}
.avatarHint { margin: 8px 0 0; text-align: center; }

.avatarSection { margin-bottom: 20px; }
.avatarSection:last-of-type { margin-bottom: 4px; }
.avatarSectionTitle {
  font-size: var(--fs-foot);
  color: var(--label-2);
  margin-bottom: 9px;
  padding-left: 3px;
}

.emojiGrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(42px, 1fr));
  gap: 7px;
}
.emojiPick {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 10px;
  background: var(--fill-2);
  font-size: 22px;
  line-height: 1;
  font-family: inherit;
  cursor: pointer;
  padding: 0;
}
.emojiPick.is-active { background: var(--now); }

.colorGrid { display: flex; gap: 11px; flex-wrap: wrap; }
.colorPick {
  position: relative;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  font-family: inherit;
}
.colorPick.is-active::after { content: '✓'; }

.authUserInfo { min-width: 0; }
.authEmail { font-size: var(--fs-body); font-weight: 500; word-break: break-all; }

.authSentRow { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }

.authDemoBox {
  margin-top: 16px;
  padding: 16px 14px;
  border-radius: var(--r-card);
  background: color-mix(in srgb, var(--goal) 10%, transparent);
  text-align: center;
}
.authDemoLabel { font-size: var(--fs-foot); color: var(--label-2); margin-bottom: 8px; }
.authDemoCode {
  font-size: 34px;
  font-weight: 700;
  letter-spacing: .14em;
  color: var(--goal);
  cursor: pointer;
  user-select: all;
  -webkit-user-select: all;
  line-height: 1.25;
}

.authSyncRow {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-foot);
  color: var(--label-2);
  padding: 0 3px 18px;
  line-height: 1.4;
}
.authSyncDot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; background: var(--ios-green); }
.authSyncDot.is-local { background: var(--goal); }

/* ============================================================
   21. 登录门禁
   ============================================================ */

.gate {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px 20px calc(28px + env(safe-area-inset-bottom));
  /* 不写底色：让 body 上的 Born to win 水印能透到登录页来 */
  background: transparent;
}
.gate[hidden] { display: none; }

.gateInner { width: 100%; max-width: 380px; }

.gateBrand { text-align: center; margin-bottom: 24px; }

.gateIcon {
  width: 78px;
  height: 78px;
  margin: 0 auto 16px;
  border-radius: 18px;
  background: var(--now);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 40px;
  line-height: 1;
  box-shadow: 0 10px 26px -10px color-mix(in srgb, var(--now) 70%, transparent);
}

.gateTitle { font-size: 26px; font-weight: 700; letter-spacing: -.022em; line-height: 1.2; }

/* 登录方式切换（iOS 分段控件） */
.segSwitch {
  display: flex;
  gap: 2px;
  padding: 2px;
  background: var(--fill-2);
  border-radius: 9px;
  margin-bottom: 18px;
}
.segBtn {
  flex: 1 1 0;
  padding: 7px 8px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--label);
  font-size: var(--fs-foot);
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
}
.segBtn.is-active {
  background: var(--surface);
  font-weight: 600;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .10), 0 0 0 .5px rgba(0, 0, 0, .04);
}
html[data-theme="dark"] .segBtn.is-active { background: var(--fill-1); box-shadow: none; }

/* 设置里的"登录密码"区块 */
#pwdForm input + input { margin-top: 8px; }
.pwdStateRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.pwdStateRow .hint { flex: 1 1 auto; line-height: 1.45; }

body.is-gate { padding-bottom: 20px; }

/* ============================================================
   22. 宽屏（两列）
   ============================================================ */

@media (min-width: 760px) {
  .grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; }
  .grid .section { margin-bottom: 0; }
  .grid .span-2 { grid-column: span 2; }
}

/* ============================================================
   23. 手机
   ============================================================ */

@media (max-width: 640px) {
  body { padding-bottom: calc(50px + env(safe-area-inset-bottom)); }

  .largeTitle { font-size: 30px; }
  .heroDays { font-size: 40px; }
  .topbar { padding: 0 14px; }
  .brand h1 { font-size: 16px; }
  main { padding: 0 16px 28px; }

  /* 底部标签栏 */
  .tabs {
    position: fixed;
    left: 0; right: 0; bottom: 0; top: auto;
    z-index: 40;
    gap: 0;
    padding: 6px 4px calc(4px + env(safe-area-inset-bottom));
    background: var(--bar-bg);
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    border-top: 1px solid var(--sep);
    max-width: none;
    margin: 0;
  }
  .tabs::before { display: none; }

  .tab {
    flex-direction: column;
    gap: 2px;
    padding: 4px 2px;
    font-size: 10px;
    font-weight: 400;
    border-radius: 0;
    color: var(--ios-gray);
    box-shadow: none !important;
    background: transparent !important;
  }
  .tab svg { width: 25px; height: 25px; stroke-width: 1.6; }
  .tab.is-active { color: var(--now); font-weight: 500; }

  /* 弹窗从底部升起 */
  .dialog {
    position: fixed;
    inset: auto 0 0 0;
    margin: 0;
    width: 100%;
    max-width: 100%;
    max-height: 92vh;
    border-radius: 12px 12px 0 0;
    padding-bottom: env(safe-area-inset-bottom);
  }
  .dialog::before {
    content: '';
    display: block;
    width: 36px;
    height: 5px;
    border-radius: 3px;
    background: var(--fill-1);
    margin: 8px auto 0;
  }
  .dialogInner { padding: 10px 16px 20px; max-height: 92vh; }

  .card { padding: 14px; }
  .taskList { margin: 0 -14px; }
  .taskItem { padding: 10px 14px; }
  .taskItem + .taskItem::before { left: 14px; }
  .tableWrap { margin: 0 -14px; }
  #btnAuth { font-size: 16px; max-width: 40vw; }

  .grid { display: block; }
  .section { margin-bottom: 18px; }
  .bars { height: 130px; gap: 5px; }

  /* 数据条在手机上是两列 */
  .statStrip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .quickAdd { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 6px; scrollbar-width: none; }
  .quickAdd::-webkit-scrollbar { display: none; }
  .quickAdd .chip { flex: 0 0 auto; }

  .row .btn { flex: 1 1 100%; }
  .btn.big { flex: 1 1 calc(50% - 5px); }
  .formFoot { flex-direction: column; align-items: stretch; }
  .formFoot .btn { width: 100%; }
  .taskActions { flex-direction: column; align-items: flex-end; gap: 4px; }
  .picker { gap: 6px; }
  .pickBtn { min-width: 0; }
  .foot { padding-bottom: 8px; }
  .toast { bottom: calc(70px + env(safe-area-inset-bottom)); }
}

/* ---- 手机（≤500px）：倒计时搬出顶栏 ----
   2026-09-19 用户要求：把「距考试 N 天」挪到页面标题行的右边（就是原来「每日计划」
   放「回到今天」按钮的那个位置），别挤着顶栏的用户名和头像。
   现在由 app.js 的 placeCountdown() 把 #countdown 这个节点挪进当前页面的 .viewHead，
   所以顶栏恢复一行、也不用再给它加高（上一版那个"两行网格"方案已作废）。
   这里只留一条兜底：品牌名放不下时用省略号收尾，而不是溢出压到别人身上。 */
@media (max-width: 500px) {
  .brand { flex: 1 1 auto; }
  .brandMark { flex: 0 0 auto; }
  /* h1 也要能"吃掉"剩下的空隙（不然有空位它也不长，白留一截空白） */
  .brand h1 { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
}

/* 状态页有未保存的改动时，「保存」按钮轻轻呼吸一下（用户要的「忘了点保存」保险）。
   没改动时按钮是灰的（disabled），所以这个动画只在真有改动时出现；
   系统开了「减少动态效果」的话，下面那条 media query 会把它关掉。 */
@keyframes statusPulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--now) 42%, transparent); }
  50%      { box-shadow: 0 0 0 7px color-mix(in srgb, var(--now) 0%, transparent); }
}
.btn.is-dirty { animation: statusPulse 1.7s ease-in-out infinite; }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ============================================================
   23. 背景水印：Born to win
   ------------------------------------------------------------
   照 Apple 官网英雄区的做法重新设计：
   · **无衬线大字 + 很紧的字距**（-0.035em）—— 这是"苹果味"最主要来源，
     换成衬线斜体就会变成杂志风。
   · **字形用渐变填充**（background-clip: text），蓝 → 靛紫斜着扫过去，
     字里有颜色走向，不是一块死灰。这是 Apple 大标题的招牌手法。
   · **底部最实、往上淡出**（mask），像从页面底边长出来，避免生硬切边。
   · 整句完整落在屏幕内（不再被两边裁掉），所以"Born to win"是能读全的。

   强度靠三个令牌控制，想更淡/更浓只改这几个数：
     --wm-a  左上（Apple 蓝）
     --wm-b  中间（靛）
     --wm-c  右下（紫）

   为什么这样写：
   · z-index:1（2026-09-19 改，原来是 -1）—— **现在是压在内容上面**。
     原来放内容底下，卡片是不透明的，用户反馈"经常被挡住看不见"：
     主界面只有卡片缝里露出一点点。改成正 z-index 之后，水印像真水印一样
     画在所有内容之上（卡片、文字、表格都压过去），
     pointer-events:none 保证点不到它、不挡任何操作；
     导航栏(z=30)、标签栏(z=20)、弹窗(z=100)、toast(z=50)、专注界面(z=40)
     的 z-index 都比它高，所以这些"窗户"不会被水印糊住。
     ⚠️ 浓度必须跟着降（见 --wm-a/b/c）：现在它压在白卡片上，
     原来的 .24 会蓝得刺眼。
   · pointer-events:none —— 点不到它，不会挡住任何按钮。
   · color:transparent 配合 background-clip —— 万一浏览器不支持这个特性，
     结果是"不显示"（安全），不会退化成一坨突兀的实心字。
   · position:fixed —— 固定元素不计入文档滚动区域，
     所以就算字比屏幕宽，也不会撑出横向滚动条。
   · 原生 <dialog> 走的是浏览器顶层（top layer），水印压不到它，弹窗里照样干净。
   ============================================================ */

body::before {
  content: 'Born to win';
  position: fixed;
  left: 50%;
  bottom: -.14em;
  transform: translateX(-50%);
  z-index: 1;   /* 压在内容上面；导航/标签栏/弹窗的 z-index 都比它高，不会糊住它们 */
  /* 用 Latin 无衬线栈：macOS 是 Helvetica Neue，Windows 退到 Segoe UI。
     不要用 body 那套（第一顺位是系统字体，Windows 上会落到中文字体，
     拉丁字母会变丑）。 */
  font-family: "Helvetica Neue", "Segoe UI Variable Display", "Segoe UI",
               Helvetica, Arial, system-ui, sans-serif;
  font-weight: 700;
  /* 18vw 让整句刚好占满屏宽（再大就会被两边裁掉） */
  font-size: clamp(64px, 18vw, 232px);
  line-height: .88;
  letter-spacing: -.035em;
  white-space: nowrap;
  /* 必须让盒子贴住文字宽度。position:fixed + left:50% 会把收缩宽度限制在半屏，
     渐变就按半屏平铺、右半边又回到蓝色 —— 实测发现的。 */
  width: max-content;
  background-image: linear-gradient(115deg,
    var(--wm-a) 0%, var(--wm-b) 52%, var(--wm-c) 100%);
  background-size: 100% 100%;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-mask-image: linear-gradient(to top,
    #000 0%, #000 38%, rgba(0, 0, 0, .45) 72%, transparent 100%);
  mask-image: linear-gradient(to top,
    #000 0%, #000 38%, rgba(0, 0, 0, .45) 72%, transparent 100%);
}

/* ⚠️ 这条必须写在上面那段 body::before **后面** —— 同一优先级时后写的赢，
   写在前面会被基础规则整个盖掉（我第一版就写进了上面那个 ≤640px 块里，
   结果 bottom 还是 -9px、水印照样被标签栏挡住）。 */
@media (max-width: 640px) {
  body::before {
    /* 手机上的水印要抬到"底部标签栏之上"才看得见：
       实测 360×720 时水印占 y672~720，而标签栏正好是 y660~720（高 60px），
       整句被完全盖住，只有 6/255 从毛玻璃里透出来，等于没有。 */
    bottom: calc(64px + env(safe-area-inset-bottom));
    /* 320px 的小屏上，原来 clamp 的 64px 下限会让整句超出屏幕
       （这句宽 = 5.16 × 字号，64px 就是 330px > 320px，两边会被裁掉） */
    font-size: clamp(42px, 18vw, 232px);
  }
}

/* 英文界面（i18n.js 会把 <html lang> 改成 en）：
   科目名从"听力"变成"Listening"，标尺名字列要放宽，否则会被截断。 */
html[lang="en"] {
  --band-name-w: 70px;
}

/* 桌面（≥641px）把水印再调淡一档 —— 用户反馈"电脑版的 born to win 太透了"。
   ⚠️ 手机（≤640px）**不动**：那边的浓度是按"抬到标签栏上方之后"单独调过的。
   两套令牌都要覆盖：浅色在 :root，深色在 html[data-theme="dark"]。
   （用户当前用的是深色主题，所以深色那组才是他实际看到的。） */
@media (min-width: 641px) {
  :root {
    --wm-a: rgba(0, 122, 255, .12);
    --wm-b: rgba(88, 86, 214, .108);
    --wm-c: rgba(140, 92, 210, .092);
  }
  html[data-theme="dark"] {
    --wm-a: rgba(120, 190, 255, .145);
    --wm-b: rgba(150, 150, 250, .128);
    --wm-c: rgba(190, 150, 250, .112);
  }
}

/* ============================================================
   24. 时间轴：一天最多 4 条，多出来的上下滚动
   ============================================================ */

.tlList { padding-bottom: 2px; }

/* 24. 会限高滚动的列表（时间轴 / 最近练习 / 练习历史）
   ------------------------------------------------------------
   ⚠️ 这里的选择器必须是 .taskList.is-scroll，不能只写 .tlList ——
   练习历史的 <ul> 只有 .taskList 没有 .tlList，
   只写 .tlList 的话它会被限高却没有 overflow-y，第 9 条以后直接被裁掉、滚都滚不到。
   （这个 bug 出过一次，用户反馈"为什么没做"。改选择器前先想清楚。） */
.tlList { padding-bottom: 2px; }

.taskList.is-scroll {
  overflow-y: auto;
  overscroll-behavior: contain;
  /* 下面两行是 Firefox 的写法。注意：Chrome 一旦看到 scrollbar-width，
     就会忽略 ::-webkit-scrollbar 那几条，改用系统细滚动条 —— 两边观感一致，
     所以这里同时留着，Safari 走 webkit 那套。 */
  scrollbar-width: thin;
  scrollbar-color: var(--fill-1) transparent;
}
.taskList.is-scroll::-webkit-scrollbar { width: 6px; }
.taskList.is-scroll::-webkit-scrollbar-track { background: transparent; }
.taskList.is-scroll::-webkit-scrollbar-thumb {
  background: var(--fill-1);
  border-radius: 3px;
}
.taskList.is-scroll::-webkit-scrollbar-thumb:hover { background: var(--label-3); }

/* 科目是主角：大一号、加粗、带科目色圆点 */
.sesMain { flex: 1; min-width: 0; }

.sesSubj {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: 1.3;
  color: var(--label);
  word-break: break-word;
}
.sesDot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--c, var(--now));
}

/* 时长 / 时间 / 备注都是配角，压在第二行 */
.sesMeta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 3px;
  font-size: var(--fs-foot);
  color: var(--label-2);
  font-variant-numeric: tabular-nums;
}
.sesMeta .sesMin { font-weight: 500; }
.sesMeta .sesTime { color: var(--label-3); }

.tlHint { margin: 10px 0 0; }
.tlHint:empty { display: none; }

/* 时间轴的日期条：‹ [日期选择器] › + 今天/昨天 的提示 */
.tlDateBar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
/* ⚠️ 日期框现在是 `type="text"` + `.dpField`（见 app.js 的 dpUpgrade），
   所以选择器用 `.dpField`，不能再用 `input[type="date"]`（改了类型就不匹配了）。
   右边那 38px 是留给"自画的日历小图标"的，直接写在这里 ——
   免得依赖两条规则的先后顺序（以前靠"后写的赢"这种脆弱写法）。 */
.tlDateBar input.dpField {
  width: auto;
  flex: 0 0 auto;
  min-height: 38px;
  padding: 6px 38px 6px 10px;
  font-size: var(--fs-callout);
  font-weight: 500;
}

/* 日期框右侧那个"日历"小标志 —— **自己画的**，不是浏览器自带那个。
   为什么不用原生的（`::-webkit-calendar-picker-indicator`）：
   · 它样式不受控、各浏览器长得不一样，dark 模式下还会糊成一团；
   · 用户看不到它就会以为这不是日期框（2026-09-19 用户反馈："小日历的标志怎么没有了"）。
   整块输入框都可点（点哪儿都弹我们自己的面板，见 app.js 的 setupDatePickers），
   所以这个图标纯装饰、不会被浏览器抢去弹原生日历。
   ⚠️ 右边那 38px 的 padding 由各处的尺寸规则自己写（`.tlDateBar input.dpField`、`#calJumpDate`），
      这里只管"画图标"，不碰 padding —— 以前靠两条规则的先后顺序来压，太脆。 */
input.dpField {
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='17' height='17' viewBox='0 0 24 24' fill='none' stroke='%238E8E93' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.2' y='5' width='17.6' height='15.5' rx='3.2'/%3E%3Cpath d='M3.2 10h17.6M8 3.2v3.4M16 3.2v3.4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
  background-size: 17px 17px;
}
/* 原生那个仍然藏掉：它跟我们的面板会打架 */
.dpField::-webkit-calendar-picker-indicator { display: none; }
.tlDateHint { margin-left: 2px; }

/* 「‹ 日期框 ›」包成一组，不许被 flex 拆到两行 ——
   手机上出现过"›"孤零零掉到下一行（用户反馈）。 */
.dpGroup { display: flex; align-items: center; gap: 8px; flex: 0 1 auto; min-width: 0; }
/* 手机上：返回日历 / 回到今天 在第一行，日期三件套+提示 独占第二行 */
@media (max-width: 430px) {
  #statusDateBar { row-gap: 10px; }
  #statusDateBar > .dpGroup { order: 3; flex: 1 1 100%; }
  #statusDateBar #statusBackToCal { order: 1; }
  #statusDateBar #statusToday { order: 2; margin-left: auto; }
}

/* 状态日历右上角那个"跳到某一天"的日期框：和日期条里那个同款尺寸。
   ⚠️ `.cardHead` 是 baseline 对齐，input 不写 align-self:center 会歪一大截。 */
#calJumpDate {
  width: auto;
  align-self: center;
  min-height: 38px;
  /* ⚠️ 右边要留出 38px 给那个日历小图标（见 .dpField 那条规则），
     这里要是不写，图标会压在日期文字上（这条是 id 选择器，优先级比 .dpField 高）。 */
  padding: 6px 38px 6px 10px;
  font-size: var(--fs-callout);
  font-weight: 500;
}

/* ============================================================
   25. 登录页补充：忘记密码 / 底部提示
   ============================================================ */

.linkBtn {
  display: block;
  margin: 10px auto 0;
  padding: 4px 6px;
  border: none;
  background: transparent;
  color: var(--now);
  font: inherit;
  font-size: var(--fs-foot);
  cursor: pointer;
}
.linkBtn:hover { text-decoration: underline; }

.resetLead { margin: 0 0 14px; line-height: 1.5; }
.resetLead b { color: var(--label); font-weight: 600; }
.resetBack { margin-top: 14px; }
#resetPwd + .dlgField,
#authResetArea .dlgField + .dlgField { margin-top: 12px; }

/* 底部提示：两句话分开排，第一句是本页的主承诺，稍亮一点 */
#authTip .tipLine { margin: 0; }
#authTip .tipLine + .tipLine { margin-top: 7px; }
#authTip .tipLine:first-child { color: var(--label); font-weight: 500; }

.setupLead { margin: 0 0 14px; line-height: 1.55; }
.setupLead b { color: var(--label); font-weight: 600; }

#pwdSetupDialog .btnRow { justify-content: flex-end; }

/* ============================================================
   26. 圆形裁剪头像
   ------------------------------------------------------------
   圆环固定不动，照片在下面被拖动 / 缩放 —— 圆环里露出来的就是最终头像。
   几何尺寸（圆环直径、照片大小和位置）全由 app.js 的 cropGeom 算好写在
   行内样式上，这里只管长相。
   ============================================================ */

.cropStage {
  position: relative;
  width: min(300px, 100%);
  aspect-ratio: 1 / 1;
  margin: 0 auto 12px;
  border-radius: 12px;
  overflow: hidden;              /* 把圆环那一大圈 box-shadow 裁在框内 */
  background: #111;
  cursor: grab;
  /* 手机上拖照片时别把整个弹窗带着滚 */
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.cropStage.is-dragging { cursor: grabbing; }

.cropImg {
  position: absolute;
  left: 0;
  top: 0;
  max-width: none;               /* 关键：别被通用规则限制住 */
  -webkit-user-drag: none;
  user-select: none;
  -webkit-user-select: none;
  pointer-events: none;          /* 拖动交给舞台处理，免得拖出"图片幽灵" */
}

/* 圆形取景环：外圈用超大 spread 的 box-shadow 压暗，内圈留一道白边 */
.cropRing {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, .55),
              0 0 0 1.5px rgba(255, 255, 255, .95) inset;
}

.cropHint { margin: 0 0 12px; text-align: center; }

.cropZoomRow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}
.cropZoomEnd { flex: 0 0 auto; font-size: var(--fs-foot); color: var(--label-2); }
.cropZoomRow input[type="range"] {
  flex: 1 1 auto;
  width: auto;
  min-height: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
  accent-color: var(--now);
}
/* 通用 input 规则里写了 appearance:none，滑块必须自己画，否则看不见 */
.cropZoomRow input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background: var(--fill-1);
}
.cropZoomRow input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 22px;
  height: 22px;
  margin-top: -9px;
  border: none;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .28);
}
.cropZoomRow input[type="range"]::-moz-range-track {
  height: 4px;
  border-radius: 2px;
  background: var(--fill-1);
}
.cropZoomRow input[type="range"]::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .28);
}

/* 「确定 / 取消」靠右 */
.avatarFoot { margin-top: 18px; justify-content: flex-end; }

/* ============================================================
   28. 练习记录补充：套卷 / 历史日期条 / 自定义科目
   ============================================================ */

/* 表头右侧并排两个小按钮（总览 + 回到今天） */
.headBtns { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.headBtns .btn.is-active { background: var(--now); color: #fff; }

/* 套卷那组"四科分数" */
.fldLabel {
  display: block;
  font-size: var(--fs-foot);
  color: var(--label-2);
  margin-bottom: 8px;
}
.bandGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 10px 12px;
}
.bandGrid label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-foot);
  color: var(--label-2);
  white-space: nowrap;
}
.bandGrid input {
  width: 100%;
  min-width: 0;
  padding: 8px 10px;
  font-size: var(--fs-callout);
  text-align: left;
}
#fldBands .hint { margin: 8px 0 0; }

/* 分数走势：五张小图（听说读写 + 套卷） */
.scoreGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 18px 24px;
}
.scoreCell { min-width: 0; }

/* 只有两张小图的格子（状态趋势：心情 / 精力）用 auto-fill：
   它会保留那些空掉的轨道，所以两张图的宽度**和分数走势里每张完全一样**
   （用 auto-fit 的话空轨道会被收掉，两张图就各自撑得更宽了）。 */
.scoreGrid-fill { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.scoreCellHead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 2px;
}
.scoreCellName { font-size: var(--fs-callout); font-weight: 600; color: var(--label); }
.scoreCellEmpty {
  padding: 26px 0;
  text-align: center;
  font-size: var(--fs-foot);
  color: var(--label-3);
}

/* 自定义科目标签旁边的"其他"兜底色 */
.customList { margin-top: 6px; }

/* 计时器最后的"＋ 自定义"按钮：虚线感、比真科目轻 */
.chip.chipAdd {
  background: transparent;
  color: var(--label-2);
  box-shadow: inset 0 0 0 1px var(--fill-1);
}
.customListTitle {
  font-size: var(--fs-foot);
  color: var(--label-3);
  margin: 14px 0 8px;
}
.customRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 0;
}
.customRow + .customRow { border-top: 1px solid var(--sep); }
.customRowBtns { display: flex; gap: 6px; flex: 0 0 auto; }
/* 正在编辑的那一行给点底色，免得不知道在改哪个 */
.customRow.is-editing {
  background: var(--fill-3);
  border-radius: 8px;
  padding-left: 8px;
  padding-right: 8px;
}

/* ============================================================
   27. 设置里的"目标总分"：数值 + 一个加号
   ------------------------------------------------------------
   原来是 number 输入框，带一对上下小箭头（用户嫌它难看、也点不准）。
   现在总分不手填 —— 它是四科目标按雅思算法算出来的，所以这里只显示结果，
   旁边一个加号展开四科的下拉框。
   ============================================================ */

.targetHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 6px;
  padding: 4px 4px 4px 13px;
  min-height: 42px;
  background: var(--fill-2);
  border-radius: var(--r-field);
}

.targetTotal {
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--label);
  font-variant-numeric: tabular-nums;
}
.targetTotal.is-empty { font-weight: 400; color: var(--label-3); }

.targetPlus {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  padding: 0;
  border: none;
  border-radius: 9px;
  background: var(--surface);
  color: var(--now);
  font-family: inherit;
  font-size: 19px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform .22s cubic-bezier(.32, .72, 0, 1);
}
html[data-theme="dark"] .targetPlus { background: var(--fill-1); }
/* 展开时把加号转 45° 变成 ×，一看就知道再点能收起 */
.targetPlus.is-open { transform: rotate(45deg); }

.targetDetail {
  margin-top: 10px;
  padding: 12px;
  background: var(--fill-3);
  border-radius: 10px;
}
/* ⛔ 原来还有一条 .targetDetailHint（四科面板里那句说明文字），
   2026-09-20 用户要求删掉那句话，这条规则也一起删了 —— 别再写回去。 */

.targetGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: 10px 12px;
}
.targetField {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: var(--fs-foot);
  color: var(--label-2);
}
.targetField select {
  width: auto;
  min-width: 84px;
  padding: 7px 30px 7px 10px;
  font-size: var(--fs-foot);
  font-weight: 500;
}

#cropTip { margin: 10px 0 0; text-align: center; }
#cropTip:empty { display: none; }

/* ============================================================
   29. 宽屏：把内容区放宽
   ------------------------------------------------------------
   原来固定 820px，1280 宽的屏幕上左右各空 ~230px（用户反馈"两边太空"）。
   这里只放宽内容区，布局本身不动；窄屏完全不受影响。
   ============================================================ */

@media (min-width: 1180px) {
  :root { --content-w: 1080px; }
}

/* ============================================================
   29b. 平板横屏模式（iPad 这类设备）
   ------------------------------------------------------------
   用户要求："ipad 要做一个横屏时的模式，因为 ipad 用户习惯横屏使用"。
   实测的问题：iPad 10.2 横屏（1024 宽）下内容只有 820px，**两边各空 102px**，
   而且所有卡片都是一栏、又宽又长 —— 横向空间完全没用上。

   处理（**只在这一档生效**，桌面 >1180 和竖屏 <=900 都不受影响）：
   · 内容宽度改成 min(1080px, 100vw - 48px)，把屏幕用起来（见上面 --content-w）；
   · 卡片排成两栏（.pageGrid / .grid），密集但不挤；
   · 状态页在横屏下**日历和编辑界面左右并排**（不用来回切）。
   ============================================================ */

@media (min-width: 900px) and (max-width: 1180px) and (orientation: landscape) {
  .pageGrid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 20px;
    align-items: start;
  }
  .pageGrid > .section { margin-bottom: 0; }
  .pageGrid > .span-2 { grid-column: 1 / -1; }

  /* 面板页本来就有 .grid：横屏时把"各占整行"的 span-2 放开，真正两栏排 */
  .grid { align-items: start; }
  .grid .span-2 { grid-column: auto; }

  /* 状态页：没在编辑时日历独占整行；点开某天 → 日历和编辑界面并排 */
  .pageGrid > #statusCalSection { grid-column: 1 / -1; }
  body.is-editing .pageGrid > #statusCalSection { grid-column: auto; }
}

/* ============================================================
   30. 专注计时：点「开始」后进入
   ------------------------------------------------------------
   "只保留背景"是这么做的：把整个 #appRoot 藏起来 ——
   Born to win 水印挂在 body 上、不在 #appRoot 里面，
   所以背景色和水印都还在，界面干干净净。
   ============================================================ */

body.is-focus #appRoot { display: none; }

.focus {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 20px calc(24px + env(safe-area-inset-bottom));
  /* 不写底色：让 body 的背景和水印透上来 */
}
.focusInner { width: 100%; max-width: 560px; text-align: center; }

.focusSubj {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-title);
  font-weight: 600;
  color: var(--label-2);
  margin-bottom: 2px;
}
.focusTime {
  font-size: clamp(56px, 15vw, 132px);
  font-weight: 700;
  letter-spacing: -.03em;
  line-height: 1.08;
  color: var(--label);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}
.focusState {
  margin-top: 6px;
  font-size: var(--fs-callout);
  color: var(--label-3);
  min-height: 1.4em;
}
.focusBtns {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 30px;
}
.focusBtns .btn { flex: 1 1 auto; min-width: 128px; padding: 13px 20px; }
.focusExit {
  margin-top: 26px;
  padding: 8px 14px;
  border: none;
  background: transparent;
  color: var(--label-3);
  font: inherit;
  font-size: var(--fs-foot);
  cursor: pointer;
}
.focusExit:hover { color: var(--label-2); }
