/* =====================================================================
   艾灸智能诊断系统 · 设计系统
   移动优先，温暖中医调性
   ===================================================================== */
:root {
  --bg: #F5F2ED;
  --bg-alt: #EFEAE2;
  --card: #FFFFFF;
  --primary: #6B8E7F;
  --primary-deep: #4F6E60;
  --primary-soft: #EDF3F0;
  --accent: #D4915C;
  --accent-deep: #B5763F;
  --accent-soft: #FBF1E7;
  --danger: #C46A5A;
  --danger-soft: #F9EFED;
  --warn-soft: #FDF6EC;
  --warn-text: #B8843A;
  --text: #2E2B26;
  --text-sub: #7D766D;
  --text-faint: #A39C92;
  --line: #E8E3DA;
  --line-soft: #F0EBE3;
  --zhou: #C4714A;
  --cheng: #5B7FA6;
  --ma: #5F8A78;
  --r-lg: 18px;
  --r-md: 14px;
  --r-sm: 10px;
  --shadow: 0 4px 16px rgba(46, 43, 38, .06);
  --shadow-lg: 0 10px 30px -12px rgba(46, 43, 38, .18);
  --sans: "Noto Sans SC", "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", sans-serif;
  --serif: "Noto Serif SC", "Songti SC", "STSong", "SimSun", serif;
}
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; }
body {
  font-family: var(--sans);
  background: var(--bg-alt);
  color: var(--text);
  font-size: 15px; line-height: 1.7;
  display: flex; justify-content: center;
  -webkit-font-smoothing: antialiased;
}
.app {
  width: 100%; max-width: 480px; min-height: 100vh; min-height: 100dvh;
  background: var(--bg); display: flex; flex-direction: column;
  position: relative; box-shadow: 0 0 40px rgba(0,0,0,.05);
}
button { font-family: inherit; cursor: pointer; border: none; background: none; }
a { color: inherit; text-decoration: none; }
.hidden { display: none !important; }

/* ---------------- 顶栏 ---------------- */
.topbar { flex: none; background: var(--bg); position: sticky; top: 0; z-index: 20; }
.accentbar { height: 4px; background: linear-gradient(90deg, var(--primary), var(--accent)); }
.nav {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-bottom: 1px solid transparent;
  transition: border-color .2s;
}
.nav.scrolled { border-bottom-color: var(--line); background: rgba(245,242,237,.92); backdrop-filter: blur(10px); }
.nav .back {
  width: 34px; height: 34px; flex: none; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  background: var(--card); border: 1px solid var(--line); color: var(--text-sub);
}
.nav .back:active { background: var(--bg-alt); }
.brand { display: flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 700; flex: 1; min-width: 0; }
.brand .logo {
  width: 28px; height: 28px; border-radius: 9px; flex: none;
  background: var(--primary-soft); color: var(--primary);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--serif); font-size: 15px; font-weight: 700;
}
.nav .who {
  font-size: 11.5px; color: var(--text-sub); flex: none;
  background: var(--card); border: 1px solid var(--line);
  padding: 4px 10px; border-radius: 999px; max-width: 100px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------------- 内容区 ---------------- */
.content { flex: 1; padding: 16px 16px 130px; overflow-x: hidden; }
.screen { animation: fadein .3s ease; }
@keyframes fadein { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ---------------- 首页 Hero ---------------- */
.hero { text-align: center; padding: 26px 0 4px; }
.hero .mark {
  width: 84px; height: 84px; border-radius: 26px; margin: 0 auto 18px;
  background: linear-gradient(140deg, var(--primary-soft), #fff);
  border: 1px solid #DFE9E4;
  display: flex; align-items: center; justify-content: center;
}
.hero h1 { font-family: var(--serif); font-size: 26px; font-weight: 600; letter-spacing: 1px; margin-bottom: 8px; color: var(--text); }
.hero .sub { font-size: 13.5px; color: var(--text-sub); line-height: 1.8; }

/* ---------------- 卡片 ---------------- */
.card { background: var(--card); border-radius: var(--r-md); box-shadow: var(--shadow); padding: 16px; margin-bottom: 12px; }
.card-title { font-size: 14.5px; font-weight: 700; margin-bottom: 10px; display: flex; align-items: center; gap: 7px; }
.card-title::before { content: "❖"; color: var(--accent); font-size: 11px; }
.card ul { list-style: none; font-size: 13px; color: var(--text-sub); line-height: 1.95; }
.card ul li { padding-left: 15px; position: relative; }
.card ul li::before { content: "·"; position: absolute; left: 3px; color: var(--accent); font-weight: 700; }

/* ---------------- 大师卡 ---------------- */
.master-card {
  display: flex; gap: 13px; align-items: flex-start;
  background: var(--card); border-radius: var(--r-md); box-shadow: var(--shadow);
  padding: 15px 16px; margin-bottom: 10px;
  border-left: 3px solid transparent;
}
.master-card.m-zhou { border-left-color: var(--zhou); }
.master-card.m-cheng { border-left-color: var(--cheng); }
.master-card.m-ma { border-left-color: var(--ma); }
.avatar {
  width: 46px; height: 46px; border-radius: 14px; flex: none;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--serif); font-size: 20px; font-weight: 700; color: #fff;
}
.a-zhou { background: var(--zhou); } .a-cheng { background: var(--cheng); } .a-ma { background: var(--ma); }
.master-card .m-name { font-size: 15.5px; font-weight: 700; }
.master-card .m-title { font-size: 11.5px; color: var(--text-sub); margin-top: 2px; }
.master-card .m-book { font-size: 11.5px; color: var(--primary); margin-top: 4px; }
.master-card .m-desc { font-size: 12.5px; color: var(--text-sub); line-height: 1.8; margin-top: 7px; }
.chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.chip {
  font-size: 11px; padding: 3px 9px; border-radius: 999px;
  background: var(--bg-alt); color: var(--text-sub);
}
.chip.green { background: var(--primary-soft); color: var(--primary-deep); }
.chip.orange { background: var(--accent-soft); color: var(--accent-deep); }
.chip.warn { background: var(--warn-soft); color: var(--warn-text); }
.chip.danger { background: var(--danger-soft); color: var(--danger); }
/* 可点击的特征 chip（舌面象手填 / 反馈反应多选） */
.chip.pick {
  cursor: pointer; padding: 6px 11px; font-size: 12px;
  border: 1px solid var(--line); transition: background .16s, color .16s, border-color .16s;
  -webkit-tap-highlight-color: transparent;
}
.chip.pick.on {
  background: var(--primary); color: #fff;
  border-color: var(--primary); font-weight: 600;
}

/* ---------------- 按钮 ---------------- */
.btn {
  width: 100%; border: none; border-radius: 13px; padding: 15px;
  font-size: 15.5px; font-weight: 700; font-family: inherit; letter-spacing: .5px;
  transition: all .18s; display: flex; align-items: center; justify-content: center; gap: 8px;
}
.btn:active { transform: scale(.985); }
.btn-primary { background: var(--primary); color: #fff; box-shadow: 0 6px 16px -8px rgba(107,142,127,.9); }
.btn-primary:disabled { background: #C9D4CF; color: #EDF3F0; box-shadow: none; }
.btn-accent { background: var(--accent); color: #fff; box-shadow: 0 6px 16px -8px rgba(212,145,92,.9); }
.btn-ghost { background: transparent; color: var(--text-sub); border: 1.5px solid var(--line); }
.btn-sm { padding: 12px; font-size: 14px; }
.btn-row { display: flex; gap: 10px; }

.bottombar {
  position: fixed; bottom: 0; left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 480px; z-index: 30;
  background: rgba(245,242,237,.94); backdrop-filter: blur(12px);
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  display: flex; gap: 10px;
  transition: transform .25s ease, opacity .25s;
}
.bottombar.hide { transform: translateX(-50%) translateY(110%); opacity: 0; pointer-events: none; }

/* ---------------- 进度 ---------------- */
.step { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.step .label { font-size: 13px; font-weight: 700; flex: none; }
.step .label em { font-style: normal; color: var(--text-sub); font-weight: 400; font-size: 11.5px; }
.progress { flex: 1; height: 5px; background: var(--line); border-radius: 3px; overflow: hidden; }
.progress i { display: block; height: 100%; background: linear-gradient(90deg, var(--primary), #8FAF9F); border-radius: 3px; transition: width .4s ease; }

.section { display: flex; align-items: center; gap: 8px; margin: 18px 0 12px; }
.section .bar { width: 4px; height: 16px; border-radius: 2px; background: var(--primary); flex: none; }
.section h2 { font-size: 16px; font-weight: 700; }
.section .tip { margin-left: auto; font-size: 11px; color: var(--warn-text); background: var(--warn-soft); padding: 3px 8px; border-radius: 6px; }

/* ---------------- 题目卡 ---------------- */
.qcard { background: var(--card); border-radius: var(--r-md); padding: 15px; box-shadow: var(--shadow); margin-bottom: 11px; }
.qcard.invalid { border: 1.5px solid var(--danger); background: var(--danger-soft); }
.qcard .q { font-size: 14.5px; font-weight: 600; line-height: 1.65; margin-bottom: 11px; }
.qcard .q .num { color: var(--accent); margin-right: 6px; font-size: 12px; font-weight: 700; }
.qcard .q-hint { font-size: 11.5px; color: var(--text-faint); margin: -6px 0 9px; line-height: 1.7; }
.qcard .q-src { font-size: 11px; color: var(--text-faint); margin-top: 9px; padding-top: 8px; border-top: 1px dashed var(--line); line-height: 1.7; }
.opts { display: flex; flex-direction: column; gap: 8px; }
.opts.two { flex-direction: row; }
.opts.two .opt { flex: 1; justify-content: center; }
.opt {
  border: 1.5px solid var(--line); border-radius: 11px; padding: 12px 14px;
  font-size: 13.5px; color: var(--text); transition: all .16s; background: #fff;
  display: flex; align-items: center; gap: 9px; text-align: left;
}
.opt .radio { width: 16px; height: 16px; border-radius: 50%; border: 1.5px solid var(--line); flex: none; position: relative; transition: all .16s; }
.opt.selected { border-color: var(--primary); background: var(--primary-soft); font-weight: 600; }
.opt.selected .radio { border-color: var(--primary); }
.opt.selected .radio::after { content: ""; position: absolute; inset: 3px; border-radius: 50%; background: var(--primary); }
.opt.yes-selected { border-color: var(--danger); background: var(--danger-soft); font-weight: 600; }
.opt.yes-selected .radio { border-color: var(--danger); }
.opt.yes-selected .radio::after { content: ""; position: absolute; inset: 3px; border-radius: 50%; background: var(--danger); }

.alert { border-radius: 11px; padding: 12px 14px; font-size: 12.5px; line-height: 1.75; margin-bottom: 12px; }
.alert.danger { background: var(--danger-soft); color: var(--danger); border: 1px solid #EAD5D0; }
.alert.warn { background: var(--warn-soft); color: var(--warn-text); }
.alert.info { background: var(--primary-soft); color: var(--primary-deep); }
.alert strong { display: block; margin-bottom: 4px; font-size: 13px; }

/* ---------------- 拍照 ---------------- */
.shot-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 14px; }
.shot {
  position: relative; aspect-ratio: 3/4; border-radius: var(--r-md);
  border: 1.5px dashed #D6CFC3; background: var(--card);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  overflow: hidden; color: var(--text-sub); font-size: 12.5px; transition: all .18s;
}
.shot:active { border-color: var(--primary); background: var(--primary-soft); }
.shot.filled { border-style: solid; border-color: var(--primary); }
.shot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.shot .shot-tag {
  position: absolute; top: 8px; left: 8px; z-index: 2;
  font-size: 10.5px; font-weight: 700; color: #fff;
  background: rgba(46,43,38,.62); padding: 3px 9px; border-radius: 999px;
  backdrop-filter: blur(4px);
}
.shot .shot-retake {
  position: absolute; bottom: 8px; right: 8px; z-index: 2;
  font-size: 11px; color: #fff; background: rgba(46,43,38,.62);
  padding: 5px 11px; border-radius: 999px; backdrop-filter: blur(4px);
}
.shot .shot-icon { width: 34px; height: 34px; opacity: .45; }
.shot .shot-sub { font-size: 11px; color: var(--text-faint); }

.tips-list { font-size: 12.5px; color: var(--text-sub); line-height: 1.9; list-style: none; }
.tips-list li { padding-left: 16px; position: relative; }
.tips-list li::before { content: "·"; position: absolute; left: 4px; color: var(--accent); font-weight: 700; }

/* ---------------- 结果页 ---------------- */
.verdict {
  background: linear-gradient(135deg, #6B8E7F, #55705F);
  border-radius: var(--r-md); padding: 22px 18px; text-align: center; color: #fff;
  margin-bottom: 14px; box-shadow: 0 8px 24px -12px rgba(107,142,127,.8);
}
.verdict .lab { font-size: 11px; letter-spacing: 3px; opacity: .82; margin-bottom: 8px; }
.verdict .who { font-family: var(--serif); font-size: 23px; font-weight: 600; letter-spacing: 1px; }
.verdict .pct { font-size: 12.5px; opacity: .93; margin-top: 8px; }
.verdict .pct b { font-size: 15px; }
.verdict.danger { background: linear-gradient(135deg, #C46A5A, #A9543F); }

.badge {
  display: flex; align-items: center; gap: 10px; background: var(--card);
  border-radius: var(--r-md); box-shadow: var(--shadow); padding: 14px 16px; margin-bottom: 12px;
}
.badge .bd-icon { width: 38px; height: 38px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 17px; flex: none; font-weight: 700; }
.badge .bd-txt { flex: 1; min-width: 0; }
.badge .bd-txt .bd-t { font-size: 14px; font-weight: 700; }
.badge .bd-txt .bd-s { font-size: 11.5px; color: var(--text-sub); margin-top: 3px; line-height: 1.6; }
.badge .tag { font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: 999px; flex: none; }
.tag-high { color: var(--primary-deep); background: var(--primary-soft); }
.tag-mid { color: var(--warn-text); background: var(--warn-soft); }
.tag-low { color: var(--text-sub); background: var(--bg-alt); }
.tag-danger { color: var(--danger); background: var(--danger-soft); }

.sec-t { font-size: 12.5px; font-weight: 700; color: var(--text-sub); letter-spacing: 1.5px; margin: 18px 0 10px 2px; }
.panel { background: var(--card); border-radius: var(--r-md); box-shadow: var(--shadow); padding: 16px; }
.panel p.para { font-size: 13px; color: var(--text-sub); line-height: 1.95; margin: 0 0 10px; }
.panel p.para:last-child { margin-bottom: 0; }
.panel p.para b { color: var(--text); }

.rank-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.rank-row:last-child { margin-bottom: 0; }
.rank-row .nm { font-size: 12.5px; width: 74px; flex: none; color: var(--text-sub); }
.rank-row .track { flex: 1; height: 7px; background: var(--line); border-radius: 4px; overflow: hidden; }
.rank-row .track i { display: block; height: 100%; border-radius: 4px; transition: width .5s ease; }
.rank-row .pc { font-size: 12.5px; font-weight: 700; width: 40px; text-align: right; flex: none; }

.info-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; padding: 12px 0; border-bottom: 1px dashed var(--line); font-size: 13px; }
.info-row:last-child { border-bottom: none; padding-bottom: 0; }
.info-row:first-child { padding-top: 0; }
.info-row .k { color: var(--text-sub); flex: none; }
.info-row .v { font-weight: 600; text-align: right; }

/* 穴位条目 */
.point-item { border-bottom: 1px dashed var(--line); padding: 13px 0; }
.point-item:last-child { border-bottom: none; padding-bottom: 0; }
.point-item:first-child { padding-top: 0; }
.point-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.point-head .pn { font-family: var(--serif); font-size: 16px; font-weight: 700; }
.point-head .pcode { font-size: 11px; color: var(--text-faint); }
.point-head .pmin { margin-left: auto; font-size: 13px; font-weight: 700; color: var(--accent-deep); flex: none; }
.point-body { font-size: 12.5px; color: var(--text-sub); line-height: 1.8; }
.point-body .lbl { color: var(--text-faint); }
.point-why { font-size: 11.5px; color: var(--text-faint); line-height: 1.75; margin-top: 6px; padding-left: 2px; }
.point-why summary { cursor: pointer; color: var(--primary); font-size: 11.5px; list-style: none; }
.point-why summary::-webkit-details-marker { display: none; }
.point-why summary::before { content: "▸ "; }
.point-why[open] summary::before { content: "▾ "; }

/* ---- 背 / 正面子方案（一次施灸拆成两段，先背面再正面） ---- */
.plan-sec { margin-bottom: 10px; border-left: 3px solid var(--accent); }
.plan-sec:last-of-type { margin-bottom: 0; }
.plan-sec-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding-bottom: 8px; border-bottom: 1px dashed var(--line); }
.plan-sec-step { flex: none; font-size: 15px; font-weight: 700; color: var(--accent-deep); line-height: 1; }
.plan-sec-title { font-family: var(--serif); font-size: 15.5px; font-weight: 600; }
.plan-sec-meta { margin-left: auto; font-size: 11.5px; color: var(--text-faint); white-space: nowrap; }
.plan-sec-hint { font-size: 12px; color: var(--text-sub); line-height: 1.7; padding: 8px 0 2px; }
.plan-sec-foot { padding-top: 10px; margin-top: 6px; border-top: 1px dashed var(--line); }
.point-jump { margin-top: 8px; }
.btn-xs { font-size: 11.5px; padding: 6px 11px; border-radius: 8px; width: auto; }

/* 阶段 */
.phase { padding: 12px 0; border-bottom: 1px dashed var(--line); }
.phase:last-child { border-bottom: none; padding-bottom: 0; }
.phase:first-child { padding-top: 0; }
.phase-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.phase-badge { font-size: 10.5px; font-weight: 700; color: #fff; background: var(--accent); padding: 3px 9px; border-radius: 999px; flex: none; }
.phase-badge.s2 { background: #7A9C8B; }
.phase-badge.s3 { background: var(--primary-deep); }
.phase-badge.dim { background: var(--line); color: var(--text-faint); }
.phase-name { font-family: var(--serif); font-size: 14.5px; font-weight: 600; }
.phase-goal { font-size: 11.5px; color: var(--text-faint); }
.phase-plan { font-size: 13px; line-height: 1.85; color: var(--text-sub); margin-top: 6px; }

/* 折叠 */
.acc { background: var(--card); border-radius: var(--r-md); box-shadow: var(--shadow); overflow: hidden; margin-bottom: 10px; }
.acc summary { padding: 14px 16px; font-size: 13.5px; font-weight: 600; cursor: pointer; list-style: none; display: flex; align-items: center; gap: 9px; }
.acc summary::-webkit-details-marker { display: none; }
.acc summary::after { content: "展开"; margin-left: auto; color: var(--text-faint); font-size: 11px; font-weight: 400; }
.acc[open] summary::after { content: "收起"; }
.acc .body { padding: 0 16px 15px; font-size: 12.5px; color: var(--text-sub); line-height: 1.9; }
.acc .body p { margin: 0 0 8px; }
.acc .body p:last-child { margin-bottom: 0; }
.acc .body b { color: var(--text); }

.disclaimer {
  font-size: 11.5px; color: var(--text-faint); line-height: 1.85;
  background: var(--bg-alt); border-radius: 12px; padding: 13px 15px; margin: 14px 0 0;
}
.disclaimer b { color: var(--text-sub); }

/* ---------------- 时间线 ---------------- */
.tl { position: relative; padding-left: 26px; }
.tl::before { content: ""; position: absolute; left: 7px; top: 6px; bottom: 6px; width: 1.5px; background: var(--line); }
.tl-item { position: relative; margin-bottom: 14px; }
.tl-item::before {
  content: ""; position: absolute; left: -23px; top: 7px;
  width: 11px; height: 11px; border-radius: 50%; background: var(--card);
  border: 2.5px solid var(--line); box-sizing: border-box;
}
.tl-item.t-screening::before { border-color: var(--primary); }
.tl-item.t-plan::before { border-color: var(--accent); }
.tl-item.t-feedback::before { border-color: #8FAF9F; }
.tl-item.t-photo::before { border-color: #B9AFA0; }
.tl-item.t-appointment::before { border-color: #C9A227; }
.tl-card { background: var(--card); border-radius: var(--r-sm); padding: 12px 14px; box-shadow: var(--shadow); }
.tl-card .tl-t { font-size: 13.5px; font-weight: 700; }
.tl-card .tl-s { font-size: 12px; color: var(--text-sub); margin-top: 4px; line-height: 1.7; }
.tl-card .tl-at { font-size: 11px; color: var(--text-faint); margin-top: 6px; }
.tl-card img { width: 100%; max-height: 150px; object-fit: cover; border-radius: 8px; margin-top: 8px; }

.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 14px; }
.stat { background: var(--card); border-radius: var(--r-sm); padding: 11px 6px; text-align: center; box-shadow: var(--shadow); }
.stat .v { font-family: var(--serif); font-size: 20px; font-weight: 700; color: var(--primary-deep); }
.stat .k { font-size: 10.5px; color: var(--text-faint); margin-top: 2px; }

/* ---------------- 反馈打分 ---------------- */
.scale { display: flex; gap: 6px; }
.scale .dot {
  flex: 1; aspect-ratio: 1; border-radius: 10px; border: 1.5px solid var(--line);
  background: #fff; display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700; color: var(--text-faint); transition: all .16s;
}
.scale .dot.on { border-color: var(--primary); background: var(--primary-soft); color: var(--primary-deep); }
.scale.heat .dot.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-deep); }

.field { margin-bottom: 14px; }
.field label { display: block; font-size: 13.5px; font-weight: 600; margin-bottom: 7px; }
.field .hint { font-size: 11.5px; color: var(--text-faint); margin-bottom: 7px; }
.field input, .field textarea, .field select {
  width: 100%; border: 1.5px solid var(--line); border-radius: 11px;
  padding: 12px 13px; font-size: 14.5px; font-family: inherit; color: var(--text);
  background: #fff; transition: border-color .16s;
}
.field input:focus, .field textarea:focus, .field select:focus { outline: none; border-color: var(--primary); }
.field textarea { min-height: 82px; resize: vertical; line-height: 1.7; }

/* ---------------- Toast / Loading ---------------- */
.toast {
  position: fixed; left: 50%; bottom: 108px; transform: translateX(-50%) translateY(10px);
  background: rgba(46,43,38,.9); color: #fff; font-size: 13.5px;
  padding: 11px 20px; border-radius: 12px; z-index: 200;
  opacity: 0; pointer-events: none; transition: all .25s;
  max-width: 86vw; text-align: center; line-height: 1.6;
  backdrop-filter: blur(8px);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

.loading {
  position: fixed; inset: 0; z-index: 300; display: none;
  align-items: center; justify-content: center; flex-direction: column; gap: 16px;
  background: rgba(245,242,237,.86); backdrop-filter: blur(6px);
}
.loading.show { display: flex; }
.loading .spinner {
  width: 40px; height: 40px; border-radius: 50%;
  border: 3px solid var(--line); border-top-color: var(--primary);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading .txt { font-size: 13.5px; color: var(--text-sub); }

.empty { text-align: center; padding: 40px 20px; color: var(--text-faint); font-size: 13.5px; line-height: 1.9; }
.empty .big { font-size: 34px; margin-bottom: 10px; opacity: .35; }

/* ---------------- 弹层（预约前的今日打卡门槛） ----------------
   只服务「点预约入口 → 今天还没打卡」这一种场景，所以样式做窄。
   z-index 取 260：压在 toast（200）之上、loading（300）之下。

   ⚠️ 这套类名必须与下方「底部抽屉」的 .modal 系列**分开命名**（2026-09-22 事故）：
   抽屉那边有一条 `.modal { position: fixed; inset: 0; z-index: 150; display: none; }`，
   而抽屉靠 `.modal.show` 才显示。本弹层的卡片是没有 .show 的，
   如果它也叫 .modal，同一优先级下**后出现的 display:none 会赢**，
   卡片被整块隐藏 —— 用户看到的是「点预约 → 屏幕暗一下 → 什么都没发生」，
   表现成「无法预约门店」，且永远点不到「去记录今日打卡」，等于彻底走不通。
   为什么原来的测试拦不住它？**不是** jsdom 算不了层叠 —— 实测它算得出来
   （加载 app.css 后 getComputedStyle 能给出 .gate-card→block、.modal→none）。
   真原因是当时门槛的 11 项断言只查了「DOM 在场」与文案，**压根没查 computed 样式**。
   → 回归锁见 tests/test-flow-v2.js：① 真实 getComputedStyle 断言；
     ② §CSS 层叠检查（静态扫 app.css，比对 .gate-card 与 .modal 的最终 display）。
   注意：jsdom 用 resources:'usable' 加载 CSS 是异步的，**必须等 styleSheets[0]
   规则数 > 50 再断言**，否则 getComputedStyle 返回空串，`display !== 'none'` 会假通过。 */
.gate-mask {
  position: fixed; inset: 0; z-index: 260; display: flex;
  align-items: center; justify-content: center; padding: 22px;
  background: rgba(46,43,38,.42); backdrop-filter: blur(3px);
}
.gate-card {
  width: 100%; max-width: 360px; background: var(--card);
  border-radius: 18px; box-shadow: var(--shadow-lg); padding: 20px 18px 16px;
  animation: gateIn .18s ease-out;
}
@keyframes gateIn { from { opacity: 0; transform: translateY(8px) scale(.985); } }
.gate-title { font-size: 16.5px; font-weight: 700; margin-bottom: 9px; }
.gate-body { font-size: 13px; color: var(--text-sub); line-height: 1.85; }
.gate-actions { display: flex; gap: 10px; margin-top: 16px; }
.gate-actions .btn { flex: 1; text-decoration: none; }
.gate-actions .btn-ghost { flex: 0 0 34%; }

@media (max-width: 360px) {
  .hero h1 { font-size: 23px; }
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
}

/* =====================================================================
   会员登录 / 预约 / 管理后台
   ===================================================================== */

/* ---------------- 分段切换（登录·注册 / 后台标签页） ---------------- */
.seg {
  display: flex; gap: 4px; background: var(--bg-alt);
  border-radius: 12px; padding: 4px; margin-bottom: 14px;
}
.seg button {
  flex: 1; padding: 10px 6px; border-radius: 9px;
  font-size: 13.5px; font-weight: 600; color: var(--text-sub);
  transition: all .16s;
}
.seg button.on { background: var(--card); color: var(--primary-deep); box-shadow: var(--shadow); }

.tabs { display: flex; gap: 18px; border-bottom: 1px solid var(--line); margin-bottom: 14px; }
.tabs button {
  padding: 10px 2px; font-size: 14px; font-weight: 600; color: var(--text-sub);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tabs button.on { color: var(--primary-deep); border-bottom-color: var(--primary); }

/* ---------------- 服务项目 ---------------- */
.srv {
  display: flex; gap: 12px; align-items: flex-start;
  background: var(--card); border-radius: var(--r-md); box-shadow: var(--shadow);
  padding: 13px 14px; margin-bottom: 9px; border: 1.5px solid transparent;
  transition: border-color .16s, background .16s;
}
.srv.on { border-color: var(--primary); background: var(--primary-soft); }
.srv .srv-t { font-size: 14px; font-weight: 700; }
.srv .srv-d { font-size: 11.5px; color: var(--text-sub); line-height: 1.7; margin-top: 3px; }
.srv .srv-meta { display: flex; gap: 10px; align-items: center; margin-top: 6px; font-size: 11.5px; color: var(--text-faint); }
.srv .srv-price { margin-left: auto; flex: none; font-size: 14px; font-weight: 700; color: var(--accent-deep); }

/* ---------------- 日期条 ---------------- */
.date-strip { display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 8px; scrollbar-width: none; }
.date-strip::-webkit-scrollbar { display: none; }
.dchip {
  flex: none; width: 56px; padding: 9px 0; border-radius: 12px; text-align: center;
  background: var(--card); border: 1.5px solid var(--line); transition: all .16s;
}
.dchip .dw { font-size: 10.5px; color: var(--text-faint); }
.dchip .dd { font-size: 15px; font-weight: 700; margin-top: 1px; }
.dchip .dm { font-size: 9.5px; color: var(--text-faint); }
.dchip.on { background: var(--primary); border-color: var(--primary); }
.dchip.on .dw, .dchip.on .dm { color: rgba(255,255,255,.85); }
.dchip.on .dd { color: #fff; }

/* ---------------- 时段 ---------------- */
.slot-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.slot {
  padding: 12px 4px; border-radius: 11px; text-align: center;
  border: 1.5px solid var(--line); background: var(--card);
  font-size: 13.5px; font-weight: 600; transition: all .16s;
}
.slot small { display: block; font-size: 10px; font-weight: 400; color: var(--text-faint); margin-top: 2px; }
.slot:disabled { background: var(--bg-alt); color: var(--text-faint); border-color: var(--line-soft); cursor: not-allowed; }
.slot:disabled small { color: var(--text-faint); }
.slot.on { background: var(--primary); border-color: var(--primary); color: #fff; }
.slot.on small { color: rgba(255,255,255,.85); }

/* ---------------- 预约单 ---------------- */
.appt {
  background: var(--card); border-radius: var(--r-md); box-shadow: var(--shadow);
  padding: 14px; margin-bottom: 10px; border-left: 3px solid var(--line);
}
.appt.s-booked { border-left-color: var(--accent); }
.appt.s-confirmed { border-left-color: var(--primary); }
.appt.s-done { border-left-color: #8FAF9F; }
.appt.s-canceled { border-left-color: var(--line); opacity: .72; }
.appt.s-noshow { border-left-color: var(--danger); }
.appt .ap-head { display: flex; align-items: center; gap: 8px; }
.appt .ap-t { font-size: 14px; font-weight: 700; flex: 1; min-width: 0; }
.appt .ap-when { font-family: var(--serif); font-size: 15px; margin-top: 5px; }
.appt .ap-meta { font-size: 11.5px; color: var(--text-sub); line-height: 1.75; margin-top: 5px; }
.appt .ap-act { display: flex; gap: 8px; margin-top: 10px; }

.st-badge { font-size: 10.5px; font-weight: 700; padding: 4px 10px; border-radius: 999px; flex: none; }
.st-booked { color: var(--accent-deep); background: var(--accent-soft); }
.st-confirmed { color: var(--primary-deep); background: var(--primary-soft); }
.st-done { color: var(--text-sub); background: var(--bg-alt); }
.st-canceled { color: var(--text-faint); background: var(--bg-alt); }
.st-noshow { color: var(--danger); background: var(--danger-soft); }
/* 待门店缴费激活（2026-09-23 两段式养护卡）：刻意用「待办」的暖色，
   与「已激活」的绿色（st-confirmed）拉开距离 —— 这两者必须一眼可辨，
   因为「这张卡现在能不能用」完全取决于它是哪一个。
   （2026-09-24 机器人模块撤下后不再有「扫码施灸」这一步，颜色区分的意义不变。） */
.st-pending { color: var(--warn-text); background: var(--warn-soft); }

/* ---------------- 管理后台 ---------------- */
.adm-stat { display: grid; grid-template-columns: repeat(2, 1fr); gap: 9px; margin-bottom: 14px; }
.adm-stat .s {
  background: var(--card); border-radius: var(--r-sm); box-shadow: var(--shadow);
  padding: 12px 13px;
}
.adm-stat .s .v { font-family: var(--serif); font-size: 22px; font-weight: 700; color: var(--primary-deep); }
.adm-stat .s .k { font-size: 11.5px; color: var(--text-faint); margin-top: 2px; }
.adm-stat .s.warn .v { color: var(--accent-deep); }

.adm-row {
  background: var(--card); border-radius: var(--r-sm); box-shadow: var(--shadow);
  padding: 12px 13px; margin-bottom: 8px;
}
.adm-row .r1 { display: flex; align-items: center; gap: 8px; }
.adm-row .nm { font-size: 14px; font-weight: 700; flex: 1; min-width: 0; }
.adm-row .ph { font-size: 11.5px; color: var(--text-faint); margin-top: 3px; }
.adm-row .r2 { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.adm-row .ap-meta { font-size: 11.5px; color: var(--text-sub); line-height: 1.7; margin-top: 4px; }
.adm-row .ap-act { display: flex; gap: 7px; margin-top: 9px; flex-wrap: wrap; }

.btn-xs {
  padding: 7px 12px; font-size: 12px; font-weight: 600; border-radius: 9px;
  border: 1.5px solid var(--line); color: var(--text-sub); background: var(--card);
}
.btn-xs.primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.btn-xs.accent { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-xs.danger { background: var(--danger-soft); border-color: #EAD5D0; color: var(--danger); }
.btn-xs:disabled { opacity: .45; }

.filter-bar { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 8px; scrollbar-width: none; }
.filter-bar::-webkit-scrollbar { display: none; }
.fchip {
  flex: none; padding: 7px 13px; border-radius: 999px; font-size: 12px;
  background: var(--card); border: 1.5px solid var(--line); color: var(--text-sub);
}
.fchip.on { background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 600; }

.sub-t { font-size: 12px; font-weight: 700; color: var(--text-sub); letter-spacing: 1px; margin: 14px 0 8px 2px; }

/* 底部导航（会员侧）：由 #bottombar 承载，四个 tab 等分 */
.tabbar {
  /* ⚠️ 列数**跟着 TAB_ITEMS 走**，别写死 4 列：2026-09-23 底栏从 4 项变 5 项
     （新增「到店施灸」在正中间），写死 4 列会让第 5 项掉到第二行。
     auto-fit + minmax(0,1fr) 的实际列数 = 子项数，以后加减项都不用回来改这里。 */
  flex: 1; display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: 4px;
}
.tabbar button {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 6px 2px; font-size: 10.5px; color: var(--text-faint); border-radius: 10px;
}
.tabbar button.on { color: var(--primary-deep); font-weight: 700; background: var(--primary-soft); }
.tabbar button svg { width: 19px; height: 19px; }
/* 底栏承载导航时收紧内边距，避免底栏过高挤压内容 */
.bottombar.as-tabs { padding: 6px 10px calc(6px + env(safe-area-inset-bottom)); }

/* 首页功能入口 */
.entry-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.entry {
  background: var(--card); border-radius: var(--r-md); box-shadow: var(--shadow);
  padding: 15px 14px; text-align: left;
}
.entry .e-ico { font-size: 20px; }
.entry .e-t { font-size: 14px; font-weight: 700; margin-top: 7px; }
.entry .e-s { font-size: 11.5px; color: var(--text-sub); line-height: 1.65; margin-top: 3px; }
.entry.primary { background: linear-gradient(140deg, var(--primary), var(--primary-deep)); }
.entry.primary .e-t, .entry.primary .e-s { color: #fff; }
.entry.primary .e-s { opacity: .88; }

/* ---------------- 底部抽屉 ----------------
   ⚠️ .modal 是**全局类名**，且这里是「默认 display:none，靠 .show 打开」的口径。
   任何不带 .show 的浮层都**不要**复用 .modal，否则会被这里的 display:none 整块隐藏
   （2026-09-22 预约门槛弹层就踩过这个坑，已改用 .gate-* 系列）。
   抽屉目前只有 admin.html 的 #modal 在用。 */
.modal { position: fixed; inset: 0; z-index: 150; display: none; }
.modal.show { display: block; }
.modal .mask { position: absolute; inset: 0; background: rgba(46,43,38,.42); }
.modal .sheet {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: 0;
  width: 100%; max-width: 480px; background: var(--bg);
  border-radius: 18px 18px 0 0; max-height: 90vh; overflow-y: auto;
  padding: 0 16px calc(22px + env(safe-area-inset-bottom));
  animation: sheetup .26s ease;
  box-shadow: 0 -8px 30px rgba(46,43,38,.18);
}
@keyframes sheetup { from { transform: translateX(-50%) translateY(24px); opacity: .5; } to { transform: translateX(-50%); opacity: 1; } }
.modal .sheet-head {
  position: sticky; top: 0; background: var(--bg); z-index: 2;
  display: flex; align-items: center; gap: 10px; padding: 16px 0 12px;
  border-bottom: 1px solid var(--line); margin-bottom: 14px;
}
.modal .sheet-head h3 { font-size: 16px; font-weight: 700; flex: 1; min-width: 0; }
.modal .close-x {
  width: 32px; height: 32px; border-radius: 10px; background: var(--card);
  border: 1px solid var(--line); color: var(--text-sub); flex: none;
  display: flex; align-items: center; justify-content: center; font-size: 15px;
}

/* ---------------- 首页顶部倡导横幅（2026-09-22） ---------------- */
/* 通栏浅色条，紧贴导航栏之下。可手动关闭；关闭后由底部小链接区再打开。 */
.notice-bar {
  flex: none;
  display: flex; align-items: flex-start; gap: 10px;
  padding: 11px 16px;
  background: var(--accent-soft);
  border-bottom: 1px solid #F0E1D2;
}
.notice-bar .nb-text {
  flex: 1; min-width: 0;
  font-family: var(--serif); font-size: 12.5px; line-height: 1.7;
  color: var(--accent-deep); letter-spacing: .2px;
}
.notice-bar .nb-close {
  flex: none; width: 22px; height: 22px; border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; color: var(--accent-deep); background: rgba(255,255,255,.6);
}
.notice-bar .nb-close:active { background: #fff; }

/* ---------------- 今日艾灸任务提醒卡 ---------------- */
.remind-card {
  background: var(--card); border-radius: var(--r-md);
  box-shadow: var(--shadow); padding: 14px 15px; margin-bottom: 12px;
  border-left: 3px solid var(--accent);
}
.remind-card .rc-head { display: flex; align-items: center; gap: 7px; }
.remind-card .rc-bell { font-size: 14px; }
.remind-card .rc-title { font-size: 14.5px; font-weight: 700; flex: 1; min-width: 0; }
.remind-card .rc-time {
  flex: none; font-size: 11px; padding: 3px 8px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent-deep); font-weight: 600;
}
.remind-card .rc-line { font-size: 13.5px; font-weight: 600; margin-top: 9px; }
.remind-card .rc-sub { font-size: 12px; color: var(--text-sub); margin-top: 4px; }
.remind-card .rc-actions { display: flex; gap: 10px; margin-top: 13px; }
.remind-card .rc-actions .btn { padding: 11px; font-size: 13.5px; }

/* ---------------- 首页底部小链接区 + 提醒设置面板 ---------------- */
.mini-links {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin: 14px 0 4px; font-size: 12.5px;
}
.mini-links button {
  color: var(--text-sub); font-size: 12.5px;
  text-decoration: underline; text-underline-offset: 3px;
}
.mini-links .sep { color: var(--text-faint); }

.remind-panel .rp-note {
  font-size: 12px; color: var(--text-sub); line-height: 1.85;
  background: var(--bg-alt); border-radius: var(--r-sm); padding: 10px 12px;
}
.remind-panel .rp-switch {
  display: flex; align-items: center; gap: 9px;
  font-size: 13.5px; font-weight: 600; margin: 13px 0 4px; cursor: pointer;
}
.remind-panel .rp-switch input { width: 16px; height: 16px; accent-color: var(--primary); }
.remind-panel .rp-label { font-size: 12px; color: var(--text-sub); margin-top: 10px; }
.remind-panel #rpTime {
  width: 100%; margin-top: 8px; padding: 11px 12px;
  border: 1.5px solid var(--line); border-radius: var(--r-sm);
  background: var(--card); font-family: inherit; font-size: 14px; color: var(--text);
}
.remind-panel .rp-state { font-size: 11.5px; color: var(--text-faint); margin-top: 10px; text-align: center; }

/* =====================================================================
   施灸执行表（2026-09-22）
   ---------------------------------------------------------------------
   方案页把「灸哪里 / 怎么灸 / 灸多久 / 哪天灸哪天不灸」做成表格先行，
   依据与判断排到表格之后。只定义表格本身，配色沿用页面既有变量；
   窄屏靠 .tbl-wrap 横向滚动兜底，不压缩到读不了。
   ===================================================================== */
.sec-t.sub-sec { font-size: 12px; letter-spacing: 1px; margin: 16px 0 8px 2px; }
.sec-t.sub-sec .sec-note {
  font-weight: 500; letter-spacing: 0; font-size: 11.5px;
  color: var(--text-faint); margin-left: 6px;
}
.tbl-wrap {
  background: var(--card); border-radius: var(--r-md); box-shadow: var(--shadow);
  overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 0 0 12px;
}
table.tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
table.tbl th {
  text-align: left; font-weight: 600; font-size: 11.5px; color: var(--text-sub);
  background: var(--bg-alt); padding: 9px 10px; border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
table.tbl td {
  padding: 10px; border-bottom: 1px solid var(--line-soft);
  vertical-align: top; line-height: 1.7; color: var(--text);
}
table.tbl tr:last-child td { border-bottom: none; }
table.tbl td.nowrap { white-space: nowrap; }
table.tbl td.how { font-size: 12px; color: var(--text-sub); }
table.tbl td .sub { font-size: 11px; color: var(--text-faint); line-height: 1.6; margin-top: 3px; }

/* ---------------- 进度卡 + 四列排班表（2026-09-25 第二轮，2026-09-26 第五轮改列结构） ----------------
   目标：手机一屏横向放下 4 列，**不出现左右滑动**。
   手段：缩短表头（间隔 → 建议时间 / 预约状态 → 进度状态）、方案简写、固定列宽 + 压缩内边距；
   刻意**不用**「把字号调到很小」那一招 —— 字号只从 12.5 降到 12，宽度主要靠字段压缩。
   第五轮变更：卡片主信息换成「方案共 N 次」（最左、加重），周次降为次要小字；
   去掉与表格下方说明重复的 .wk-sub。 */
.wk-card { padding: 13px 14px; }
.wk-head { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.wk-head .wk-cnt { font-size: 16px; font-weight: 800; color: var(--primary-deep); }
.wk-head .wk-sep { color: var(--line); }
.wk-head .wk-no { font-size: 12.5px; font-weight: 700; color: var(--text-sub); }
.wk-head .wk-done { margin-left: auto; font-size: 12.5px; font-weight: 700; color: var(--primary-deep); }
.wk-bar { margin: 9px 0 0; height: 6px; }
.wk-note { margin-top: 8px; font-size: 11.5px; color: var(--text-faint); line-height: 1.75; }

/* 固定列宽 → 表格宽度恒等于容器宽度，不会触发 .tbl-wrap 的横向滚动 */
.tbl-wrap.course-wrap { overflow-x: visible; }
table.tbl.course-tbl { table-layout: fixed; font-size: 12px; }
table.tbl.course-tbl th { padding: 8px 5px; font-size: 11px; }
table.tbl.course-tbl td { padding: 8px 5px; vertical-align: middle; line-height: 1.55; }
table.tbl.course-tbl col.c-seq { width: 17%; }
table.tbl.course-tbl col.c-time { width: 22%; }
table.tbl.course-tbl col.c-plan { width: 33%; }
table.tbl.course-tbl col.c-book { width: 28%; }
table.tbl.course-tbl td.c-plan { color: var(--text-sub); word-break: break-word; }
table.tbl.course-tbl td .sub { margin-top: 2px; font-size: 10.5px; }
/* 进度状态徽标在窄列里再收一点内边距，保证 4 列不挤爆 */
table.tbl.course-tbl td .st-badge { padding: 3px 8px; }
.c-on { color: var(--primary-deep); font-weight: 700; }
.c-off { color: var(--text-faint); }

/* =====================================================================
   拍照链路（2026-09-26 第六轮）：取景引导框 / 来源抽屉 / 预览大图 / 页内相机
   ===================================================================== */

/* ---------------- 空态取景引导框 ----------------
   叠在 .shot 卡片里的一层虚线轮廓，让人一眼知道「舌头/脸要放进哪个范围」。
   ⚠️ 只有空态显示：paintShot() 重拍时只删 img 与 span，**不会删这个 svg**，
      所以「拍完就消失」必须由 CSS 负责（.shot.filled 那条）。
   这里是绝对定位元素，会盖在普通流里的图标/文字之上 —— 所以下面给它们补 z-index。 */
.shot .shot-guide { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
.shot .shot-guide ellipse { fill: none; stroke: #C9C1B4; stroke-width: 1.1; stroke-dasharray: 4 3; }
.shot .shot-guide path { fill: none; stroke: #DAD3C8; stroke-width: 1.1; stroke-linecap: round; }
.shot.filled .shot-guide { display: none; }
.shot .shot-icon, .shot > span { position: relative; z-index: 1; }

/* ---------------- 来源抽屉（capture.html 专属的 .cap-* 系列） ----------------
   ⚠️ **刻意不复用 .modal**：那是全站保留给 admin.html 抽屉的类名（默认 display:none，
   靠 .show 打开），test-flow-v2.js 有一条全站反向锁钉着「只有 admin.html 能用它」——
   2026-09-22 预约门槛弹层就是复用 .modal 忘了带 .show，整块隐形。
   所以拍照来源抽屉自带一套 .cap-*，默认态与打开方式都写在自己名下。 */
.cap-choose { position: fixed; inset: 0; z-index: 150; display: none; }
.cap-choose.show { display: block; }
.cap-choose .cap-mask { position: absolute; inset: 0; background: rgba(46,43,38,.42); }
.cap-choose .cap-sheet {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: 0;
  width: 100%; max-width: 480px; background: var(--bg);
  border-radius: 18px 18px 0 0; max-height: 90vh; overflow-y: auto;
  padding: 0 16px calc(22px + env(safe-area-inset-bottom));
  animation: sheetup .26s ease;
  box-shadow: 0 -8px 30px rgba(46,43,38,.18);
}
.cap-choose .cap-head {
  position: sticky; top: 0; background: var(--bg); z-index: 2;
  display: flex; align-items: center; gap: 10px; padding: 16px 0 12px;
  border-bottom: 1px solid var(--line); margin-bottom: 14px;
}
.cap-choose .cap-head h3 { font-size: 16px; font-weight: 700; flex: 1; min-width: 0; }
.cap-choose .cap-x {
  width: 32px; height: 32px; border-radius: 10px; background: var(--card);
  border: 1px solid var(--line); color: var(--text-sub); flex: none;
  display: flex; align-items: center; justify-content: center; font-size: 15px;
}
.cap-choose .cap-hint {
  font-size: 12px; color: var(--text-sub); line-height: 1.8;
  background: var(--bg-alt); border-radius: var(--r-sm);
  padding: 10px 12px; margin-bottom: 12px;
}
.cap-choose .cap-item {
  display: block; width: 100%; text-align: center;
  font-size: 15px; font-weight: 700; letter-spacing: .5px; color: var(--text);
  background: var(--card); border: 1.5px solid var(--line);
  border-radius: var(--r-md); padding: 15px; margin-bottom: 10px;
}
.cap-choose .cap-item:active { background: var(--primary-soft); border-color: var(--primary); }
/* 「取消」不跟两个主选项抢注意力：去掉底框，只留文字 */
.cap-choose .cap-item.ghost {
  background: transparent; border-color: transparent;
  color: var(--text-sub); font-weight: 500; margin-bottom: 0;
}
.cap-choose .cap-item.ghost:active { background: var(--bg-alt); }

/* ---------------- 拍完的预览大图 ----------------
   刻意**不复用 .modal**：那个类默认 display:none 且靠 .show 打开，
   但这层要的是「深色全屏 + flex 纵向三段（标题 / 图 / 底部操作）」，语义不同。
   深色底上的文字色在这里就地写死，别引用浅色主题的 --text-*，否则会看不见。 */
.pv-layer {
  position: fixed; inset: 0; z-index: 160;
  display: none; flex-direction: column;
  background: rgba(28,26,23,.95);
  padding: max(12px, env(safe-area-inset-top)) 14px calc(14px + env(safe-area-inset-bottom));
}
.pv-layer.show { display: flex; }
.pv-head {
  flex: none; display: flex; align-items: center; gap: 10px;
  padding: 4px 2px 12px; color: rgba(255,255,255,.94);
  font-size: 14.5px; font-weight: 700; letter-spacing: .5px;
}
.pv-head #pvTitle { flex: 1; min-width: 0; }
.pv-x {
  flex: none; width: 32px; height: 32px; border-radius: 10px;
  background: rgba(255,255,255,.12); color: #fff; font-size: 16px;
  display: flex; align-items: center; justify-content: center;
}
.pv-x:active { background: rgba(255,255,255,.22); }
.pv-body { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; }
.pv-body img {
  max-width: 100%; max-height: 100%; object-fit: contain;
  border-radius: var(--r-md); background: #000;
}
.pv-foot { flex: none; padding-top: 12px; }
.pv-meta { font-size: 12px; line-height: 1.8; color: rgba(255,255,255,.7); margin-bottom: 12px; }
.pv-meta .pv-warn { margin-top: 5px; color: #F0C08A; }
.pv-meta .pv-tip { margin-top: 5px; color: rgba(255,255,255,.5); }
.pv-actions { display: flex; gap: 10px; }
.pv-actions .btn { flex: 1; }
/* 深色层里 ghost 按钮要换配色，不然浅色边框+灰字几乎看不见 */
.pv-actions .btn-ghost { color: rgba(255,255,255,.9); border-color: rgba(255,255,255,.32); }

/* ---------------- 页内相机（带取景框） ----------------
   能用 getUserMedia 就用它：实时看得到引导框，拍不准立刻调整。
   用不了（非安全上下文 / 无权限 / 无设备）时由 JS 回退系统相机，这层不参与。 */
.cam-layer { position: fixed; inset: 0; z-index: 170; display: none; background: #000; overflow: hidden; }
.cam-layer.show { display: block; }
/* 前置摄像头预览镜像（scaleX(-1)）：自拍时像照镜子，手往哪边动画面就往哪边动。
   ⚠️ 只影响**显示**——快门走 canvas.drawImage()，取的是视频原始帧，不受 CSS transform 影响，
   所以存下来/上传给视觉模型的那张图仍是**真实朝向**（与原生相机一致：预览镜像、成片不镜像）。 */
.cam-layer video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transform: scaleX(-1); }
.cam-guide { position: absolute; inset: 0; pointer-events: none; }
.cam-guide svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.cam-guide ellipse { fill: none; stroke: rgba(255,255,255,.92); stroke-width: .9; stroke-dasharray: 3 2.4; }
.cam-tip {
  position: absolute; left: 18px; right: 18px; bottom: 138px; text-align: center;
  font-size: 12.5px; line-height: 1.75; color: #fff; text-shadow: 0 1px 8px rgba(0,0,0,.7);
}
.cam-bar {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 16px 20px calc(24px + env(safe-area-inset-bottom));
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  background: linear-gradient(to top, rgba(0,0,0,.6), transparent);
}
/* .btn 默认 width:100%，在 flex 行里会把快门挤没 —— 两侧按钮必须回到内容宽度 */
.cam-bar .btn-ghost {
  flex: none; width: auto; padding: 9px 15px; font-size: 13px; font-weight: 600;
  color: #fff; background: rgba(255,255,255,.16); border-color: transparent;
}
.cam-bar .btn-ghost:active { background: rgba(255,255,255,.3); }
.cam-shutter {
  flex: none; width: 68px; height: 68px; border-radius: 50%;
  background: #fff; border: 4px solid rgba(255,255,255,.45);
  box-shadow: 0 0 0 2px rgba(0,0,0,.2); transition: transform .12s;
}
.cam-shutter:active { transform: scale(.93); }
