/* CICI MUSIC — 尽量简单，手机也能用 */
* { box-sizing: border-box; }
body {
  margin: 0; background: #f4f6f9; color: #1b2430;
  font: 15px/1.6 "Microsoft YaHei UI", "PingFang SC", system-ui, sans-serif;
}
.hidden { display: none !important; }
h1 { font-size: 26px; margin: 0 0 4px; }
h2 { font-size: 16px; margin: 0 0 12px; }
.sub { color: #7b8794; font-size: 13px; margin: 0; }
.msg { color: #c0392b; min-height: 20px; margin: 10px 0 0; font-size: 13px; }
.center { text-align: center; }

.panel {
  background: #fff; border: 2px solid #c3cedb; border-radius: 10px;
  padding: 18px 20px; margin: 0 auto 14px; max-width: 760px;
}
main { padding: 0 14px 60px; }

/* 登录（现在是首页最下面那块，不再是整页） */
#login { margin: 4px auto 0; max-width: 420px; }
#login input, #login button { width: 100%; margin-top: 12px; }

/* 首页：未登录也能看的那一版 */
#landing .wrap { padding: 0 14px 60px; }
#landing header .hright { color: #7b8794; font-size: 13px; }
.tagline { margin-right: 8px; }
@media (max-width: 640px) { .tagline { display: none; } }
.hero { font-size: 30px; line-height: 1.25; margin: 0 0 8px; }
.steps { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
         margin-top: 14px; color: #0a5aa0; font-weight: 600; font-size: 15px; }
.steps .arw { color: #b9cbe0; font-weight: 400; }
/* 首页的方案卡：只是展示，不能点 */
.scheme.pubcard { cursor: default; }
.scheme.pubcard:hover { border-color: #e3e8ee; background: #fcfdfe; }
.scheme .tg.gray { color: #9aa7b4; }

/* 首页「第一次使用 · 四步」 */
.flow { display: flex; flex-direction: column; gap: 8px; }
.flow > div {
  display: flex; gap: 10px; align-items: flex-start;
  background: #f7f9fc; border: 1px solid #dbe3ec;
  border-radius: 8px; padding: 9px 12px; font-size: 14px;
}
.flow > div > b:first-child {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  background: #0a5aa0; color: #fff; font-size: 13px;
  display: flex; align-items: center; justify-content: center;
}
/* 弹窗里那套步骤要更紧凑、左对齐（弹窗本身是居中的） */
#box-reg .flow { text-align: left; margin: 2px 0 4px; }
#box-reg .flow > div { padding: 7px 10px; font-size: 13px; gap: 8px; }
#box-reg .flow > div > b:first-child { width: 19px; height: 19px; font-size: 12px; }
.mono { font-family: Consolas, monospace; }

/* 客服 QQ */
.qqbox { border-color: #cfe4ff; background: #f7fbff; }
.qqrow { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.qqico {
  background: #12b7f5; color: #fff; font-size: 12px; font-weight: 700;
  border-radius: 6px; padding: 3px 8px; letter-spacing: .5px;
}
.qqnum { font-size: 21px; font-weight: 700; color: #0a5aa0; letter-spacing: 1px; }
.qqline { margin-top: 12px; }
.qqline b { color: #0a5aa0; font-size: 14px; }

/* 顶栏 */
header {
  display: flex; justify-content: space-between; align-items: center;
  background: #fff; border-bottom: 1px solid #e3e8ee;
  padding: 12px 20px; margin-bottom: 14px; position: sticky; top: 0; z-index: 5;
}
.brand { font-weight: 700; letter-spacing: .5px; }
.hright { display: flex; align-items: center; gap: 10px; }
.bal { color: #0a5aa0; }
.bal b { font-size: 17px; }
.who { color: #46586a; font-size: 13px; }
.who b { color: #0a5aa0; font-size: 15px; }
/* 必填星号 */
.req { color: #c0392b; font-weight: 600; }

/* 控件 */
/* 输入框统一样式。⚠ 这里必须把 password 也列上 ——
   漏了它，密码框会退回浏览器默认样式（又窄又没圆角，和旁边的用户名框一大一小）。 */
input[type=text], input:not([type]), input[type=file], input[type=password] {
  font: inherit; padding: 9px 11px; border: 1.5px solid #a9b8c9;
  border-radius: 7px; width: 100%; background: #fff;
}
input[type=file] { padding: 7px; background: #fafbfc; }
/* 登录框里用户名和密码是上下两个，得留点缝 */
#box-user { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
button {
  font: inherit; padding: 9px 18px; border-radius: 7px; border: 1.5px solid #a9b8c9;
  background: #fff; cursor: pointer;
}
button:hover:not(:disabled) { border-color: #9fb3c8; }
button.primary { background: #0a5aa0; border-color: #0a5aa0; color: #fff; font-weight: 600; }
button.primary:hover:not(:disabled) { background: #0b69bb; }
button:disabled { opacity: .45; cursor: not-allowed; }
button.ghost { border-color: transparent; color: #5b6b7c; padding: 6px 10px; }
.row { display: flex; align-items: center; gap: 12px; margin-top: 14px; }
.row.right { justify-content: flex-end; }

/* 选歌清单（批量选） */
.picklist { margin-top: 10px; }
.picklist .frow {
  display: flex; align-items: center; gap: 10px; padding: 5px 8px;
  border-bottom: 1px solid #dbe3ec;
}
.picklist .frow:hover { background: #f9fbfe; }
.picklist .fname { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
button.mini { padding: 3px 9px; font-size: 12px; border-radius: 6px; }
button.x { color: #9aa7b4; }
button.x:hover { color: #c0392b; border-color: #e3b7b0; }

/* 方案 */
/* 筛选按钮（方案列表上方那排） */
.filters { display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
           margin: 0 0 10px; }
.fbtn { padding: 5px 14px; font-size: 13px; border-radius: 20px;
        border: 1.5px solid #a9b8c9; background: #fff; color: #5b6b7c; cursor: pointer; }
.fbtn:hover { border-color: #9fb3c8; }
.fbtn.on { background: #0a5aa0; border-color: #0a5aa0; color: #fff; font-weight: 600; }
.fnote { color: #b06000; font-size: 13px; }

/* 方案：一行固定 3 个（12 个方案 = 4 行，正好跟「每次最多勾 3 个」对齐）。
   窄屏自动降成 2 列 / 1 列，免得挤成一团。 */
.schemes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
@media (max-width: 1080px) { .schemes { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 720px)  { .schemes { grid-template-columns: 1fr; } }
.scheme {
  display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px;
  border: 2px solid #c3cedb; border-radius: 8px; cursor: pointer; background: #fcfdfe;
}
.scheme:hover { border-color: #b9cbe0; background: #f7fbff; }
.scheme.on { border-color: #0a5aa0; background: #eef6ff; }
.scheme input { margin: 3px 0 0; flex: 0 0 auto; }
.scheme .nm { font-weight: 600; }
.scheme .tg { color: #0a7a0a; font-size: 12px; margin-left: 6px; }
.scheme .dc { color: #66727f; font-size: 13px; }

/* 任务 */
.jobs .job { border: 2px solid #c3cedb; border-radius: 8px; padding: 12px 14px; margin-bottom: 10px; }
.jobs .job.done { border-color: #b7e0b7; background: #f7fdf7; }
.jobs .job.failed { border-color: #f0c4c4; background: #fdf7f7; }
.job .top { display: flex; justify-content: space-between; gap: 10px; }
.job .st { font-size: 13px; color: #66727f; }
.bar { height: 6px; background: #e8edf3; border-radius: 3px; overflow: hidden; margin: 9px 0; }
.bar > i { display: block; height: 100%; background: #0a5aa0; transition: width .4s; }
.job .files { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.job .files a {
  display: inline-block; padding: 6px 12px; border-radius: 6px;
  background: #0a5aa0; color: #fff; text-decoration: none; font-size: 13px;
}
.job .files a.listen { background: #5b6b7c; }
.job .hint { display: block; margin-top: 8px; color: #b06000; font-size: 13px; }
.job .warn { display: block; margin-top: 8px; color: #c0392b; font-size: 13px; }

/* 流水 */
#ledger table { width: 100%; border-collapse: collapse; font-size: 13px; }
#ledger th, #ledger td { text-align: left; padding: 6px 8px; border-bottom: 1px solid #dbe3ec; }
#ledger .plus { color: #0a7a0a; }
#ledger .minus { color: #c0392b; }
.toggle { cursor: pointer; user-select: none; }

/* 弹窗 */
.modal {
  position: fixed; inset: 0; background: rgba(20,30,45,.45);
  display: flex; align-items: center; justify-content: center; padding: 16px; z-index: 20;
}
.modal .panel { width: 100%; max-width: 420px; margin: 0; }
.modal label { display: block; margin: 10px 0; }
.modal label input { margin-top: 4px; }

/* ══════════════════════════════════════════════════════════════════
   CICI 主题：深褐 + 金
   ══════════════════════════════════════════════════════════════════
   配色取自 CICIMUSIC 2.0 的界面：
       #F0C040 金   #2C1518 深褐   #C0392B 砖红   底＝暖黑
   ⚠ 整块挂在 body.cici 下。后台管理页 body 没这个类，保持亮色 ——
     数据表格亮色看得更清楚。
   ⚠ 装饰图（hero_spec.png / grain.png）是用 _gen_art.py 【代码画的】，
     不是下载的素材 —— 所以没有任何授权问题。
   ══════════════════════════════════════════════════════════════════ */
/* ── 背景（2026-09-28 重做）
   之前是 #46383c —— 一个【灰调褐】：饱和度太低，大面积铺开就是浑浊，
   既不是暖的中性色，也不是有意图的深色，是最没质感的一类底色。

   重做思路：复古唱片的质感来自【有光源、有纵深】，不是靠一个平色。
     · 底色换成暖胡桃（饱和、偏红棕），读起来像木/皮革
     · 顶部一大片暖光，像射灯打在墙上
     · 两侧极淡的暖色和冷色，破掉大面积死平
     · 底部压暗成暗角，把视线收进中间
   ⚠ 全部用 background-image 叠，不动任何组件颜色 —— 换回来只改这一段就行。
*/
body.cici {
  /* 让浏览器按深色渲染【原生控件】—— 音频播放器、滚动条、下拉框。
     不写这行的话 <audio controls> 是一块白条，在深底上非常跳。 */
  color-scheme: dark;
  background-color: #171109;
  background-image:
    radial-gradient(1500px 850px at 50% -18%, rgba(255,186,80,.10), transparent 70%),
    radial-gradient(900px 800px at -12% 38%, rgba(198,98,50,.09), transparent 72%),
    radial-gradient(900px 800px at 112% 62%, rgba(150,96,168,.075), transparent 72%),
    linear-gradient(180deg, #221813 0%, #171109 48%, #0e0a09 100%);
  /* ⚠ 这里原来还有一行 background-image 旧渐变 —— 它排在多层背景【后面】，
     会把上面那组全盖掉。2026-09-28 删掉。改背景时注意别再留这种僵尸声明。 */
  background-attachment: fixed;
  color: #e6dcd2;
}
/* 极淡的颗粒，铺在背景上 —— 不然大面积纯色会发闷 */
body.cici::after {
  content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image: url(/static/grain.png); opacity: .2;
}
/* ⚠ 这里【不能】把 .modal 也列进来 —— 它必须是 position:fixed 才能居中悬浮，
   写成 relative 会让弹窗掉到页面底部去。 */
body.cici #landing, body.cici #main { position: relative; z-index: 1; }

/* 两侧的竖向电平柱：把左右空白聚一下。
   固定定位（滚动时不动，像背景的一部分）。
   ⚠ 用 repeat-y 铺满整屏高度，而不是给图片一个固定高 —— 屏幕有高有矮，
     固定高在矮屏上会留白、在高屏上会截断。图本身首尾是接得上的（见 _gen_side.py）。
   ⚠ 贴边那头浓、往里淡：mask 从左往右渐隐；右边那块整体 scaleX(-1) 翻过来，
     翻完就变成「贴右边浓、往里淡」，两边共用同一张图和同一个 mask。
   ⚠ z-index 要压过 body::after 那层颗粒（同样是 0，DOM 顺序会在颗粒下面）。
   ⚠ 以前的 side_wave.png 只有 0.07 不透明度 —— 等于没有，作者说「看不到图」。 */
body.cici .side-art {
  position: fixed; top: 0; bottom: 0; width: 190px; z-index: 1;
  pointer-events: none; opacity: .2;
  background-image: url(/static/side_eq.png);
  background-repeat: repeat-y;
  background-size: 100% auto;
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 26%, transparent 100%);
  mask-image: linear-gradient(90deg, #000 0, #000 26%, transparent 100%);
}
body.cici .side-art.l { left: 0; }
body.cici .side-art.r { right: 0; transform: scaleX(-1); }
@media (max-width: 1440px) { body.cici .side-art { width: 140px; opacity: .28; } }
@media (max-width: 1180px) { body.cici .side-art { display: none; } }

/* ── 顶栏 ── */
body.cici header {
  position: sticky; top: 0; z-index: 30;
  background: rgba(12,8,6,.94);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid rgba(240,192,64,.34);
  padding: 13px 26px; margin-bottom: 0;
}
body.cici .brand {
  display: flex; align-items: center; gap: 11px;
  color: #f0c040; font-size: 18px; font-weight: 800; letter-spacing: .4px;
}
body.cici .logo {
  width: 34px; height: 34px; border-radius: 9px; display: block;
  box-shadow: 0 0 0 1px rgba(240,192,64,.6), 0 0 16px rgba(240,192,64,.2),
              0 2px 8px rgba(0,0,0,.5);
}
body.cici .hright { gap: 14px; }
body.cici .bal { color: #cfbfb1; }
body.cici .bal b { color: #f0c040; }
body.cici .who { color: #b3a294; }
body.cici .who b { color: #f0c040; }

/* ── 按钮 ── */
body.cici button { background: #2c1518; border-color: rgba(240,192,64,.28); color: #e5d3a8; }
body.cici button:hover:not(:disabled) { border-color: #f0c040; color: #f0c040; }
body.cici button.primary {
  background: linear-gradient(#f9d874, #e0a91e);
  border-color: #c9971a; color: #231114; font-weight: 800;
  box-shadow: 0 4px 16px rgba(240,192,64,.26);
}
body.cici button.primary:hover:not(:disabled) { background: linear-gradient(#ffe391, #f0c040); }
body.cici button.ghost { background: transparent; border-color: transparent; color: #a2938a; }
body.cici button.ghost:hover:not(:disabled) { color: #f0c040; background: rgba(240,192,64,.06); }
body.cici button.mini { background: #33191c; border-color: rgba(240,192,64,.55); }
body.cici button.x { background: transparent; color: #b3a294; }
body.cici button.x:hover { color: #ff7a6b; border-color: rgba(255,122,107,.4); }
body.cici button.big { font-size: 17px; padding: 14px 36px; border-radius: 11px; }

/* ── 主视觉：左文右图两栏 ── */
body.cici .hero { padding: 64px 26px 76px; }
body.cici .hero-in {
  max-width: 1120px; margin: 0 auto;
  display: grid; grid-template-columns: 1.06fr .94fr;
  gap: 50px; align-items: center;
}
body.cici .hero-txt, body.cici .hero-art { min-width: 0; }
body.cici .hero-art img {
  width: 100%; display: block; opacity: .92;
  filter: drop-shadow(0 0 46px rgba(240,192,64,.22));
}
body.cici .kicker {
  margin: 0 0 18px; font-size: 12px; font-weight: 700;
  letter-spacing: .22em; color: #d0a03a; text-transform: uppercase;
}
body.cici .hero h1 {
  /* 2026-09-28 作者把标题换成两句更长的口号（「让 AI 音乐走进千家万户 /
     让每个人都有自己的主题曲」），54px 会在「千家万/户」处硬断成两行。
     降到 38px 后两行各自都是一行，正好占满左栏。改这个值前先数一下字数。 */
  margin: 0 0 22px; font-size: 38px; line-height: 1.25;
  letter-spacing: -.5px; color: #fff;
}
body.cici .lead { margin: 0 0 32px; font-size: 17px; line-height: 1.75; color: #d3c1b2; max-width: 540px; }
body.cici .lead b { color: #f0c040; }
body.cici .cta { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
body.cici .cta-hint { font-size: 14px; color: #a8968a; }
@media (max-width: 900px) {
  body.cici .hero { padding: 42px 22px 54px; }
  body.cici .hero-in { grid-template-columns: 1fr; gap: 26px; }
  body.cici .hero h1 { font-size: 36px; }
}

/* ── 登录后的工作台横幅 ──
   首页那张频谱图（hero_spec.png）只活在 #landing 里，一登录就整块隐藏，
   客人会觉得「换了个网站」。这里把它压缩成一条横幅铺在 #main 顶部，
   配上同一套金/褐配色，两版就接上了。 */
body.cici .studio { padding: 38px 26px 22px; }
body.cici .studio-in {
  max-width: 1120px; margin: 0 auto;
  display: grid; grid-template-columns: 1fr 360px; gap: 34px; align-items: center;
}
body.cici .studio-txt, body.cici .studio-art { min-width: 0; }
body.cici .studio-art img {
  width: 100%; display: block; opacity: .85;
  filter: drop-shadow(0 0 34px rgba(240,192,64,.18));
}
body.cici .studio h1 { margin: 0 0 12px; font-size: 31px; line-height: 1.2; color: #fff; }
body.cici .studio .kicker { margin: 0 0 12px; }
body.cici .studio .lead { margin: 0; font-size: 14px; line-height: 1.7; }
@media (max-width: 900px) {
  body.cici .studio { padding: 26px 22px 14px; }
  body.cici .studio-in { grid-template-columns: 1fr; gap: 18px; }
  body.cici .studio h1 { font-size: 24px; }
  body.cici .studio-art { max-width: 300px; }
}
/* ⚠ 登录后顶栏比首页多 4 个按钮（你好/积分/充值/资料/退出），
   窄屏一行塞不下会顶出一条横向滚动条 —— 首页没这问题，所以以前没发现。
   让它换行就行。 */
@media (max-width: 700px) {
  body.cici header { flex-wrap: wrap; gap: 8px; padding: 10px 16px; }
  body.cici header .hright { flex-wrap: wrap; gap: 8px; }
}

/* ── 区块 ── */
body.cici .sec { max-width: 1172px; margin: 0 auto; padding: 0 26px 48px; }
body.cici .sec-head {
  display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap;
  margin-bottom: 20px; padding-bottom: 13px;
  border-bottom: 1px solid rgba(240,192,64,.3);
}
body.cici .sec-head h2 { margin: 0; font-size: 22px; color: #f0c040; }
body.cici .sec-head .sub { margin: 0; }

/* ── 方案卡 ──
   ⚠ 固定 3 列 —— 作者要求「3 个一行，共 4 行」（12 个方案）。
     别改成 4 列，那会变成 3 行。 */
body.cici .schemes { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 900px) { body.cici .schemes { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 560px) { body.cici .schemes { grid-template-columns: 1fr; } }
body.cici .scard {
  position: relative; padding: 16px 16px 15px; border-radius: 13px; overflow: hidden;
  background: linear-gradient(168deg, #3b2422, #2a1716);
  border: 2px solid rgba(240,192,64,.5);
  box-shadow: 0 1px 0 rgba(255,255,255,.04) inset, 0 8px 20px rgba(0,0,0,.34);
  transition: border-color .15s, transform .15s;
}
body.cici .scard:hover { transform: translateY(-2px); border-color: rgba(240,192,64,.55); }
/* 「更多优质方案敬请期待」占位卡（后台停用了某些档时才出现，见 app.js 的 MORE_CARD）。
   ⚠ 类名 only 客户页用 —— style.css 前后台共用，别把样式挂到通用类上。
   虚线的边框 + 压低对比：看着像"位置留着，但还没上"，不抢真方案的视觉。 */
body.cici .scard.more {
  display: flex; align-items: center; justify-content: center; text-align: center;
  min-height: 128px; cursor: default; box-shadow: none;
  background: rgba(255,255,255,.02);
  border-style: dashed; border-color: rgba(240,192,64,.26);
}
body.cici .scard.more:hover { transform: none; border-color: rgba(240,192,64,.26); }
body.cici .scard.more .more-in {
  color: #a8833a; font-size: 14px; line-height: 1.95; letter-spacing: 1.5px;
}
body.cici.light .scard.more { background: rgba(0,0,0,.012); border-color: rgba(180,140,30,.3); }
body.cici.light .scard.more:hover { border-color: rgba(180,140,30,.3); }
body.cici.light .scard.more .more-in { color: #a07a20; }
body.cici .scard.ok { border-color: rgba(240,192,64,.4); }
body.cici .scard.ok::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 2px;
  background: linear-gradient(90deg, transparent, #f0c040, transparent);
}
body.cici .sc-badge {
  position: absolute; top: 11px; right: 11px;
  font-size: 11px; font-weight: 800; letter-spacing: .04em;
  color: #231114; background: linear-gradient(#f9d874, #e0a91e);
  border-radius: 20px; padding: 2px 9px;
}
body.cici .sc-name {
  font-size: 13px; color: #c0b1a4; line-height: 1.4;
  margin-bottom: 12px; padding-right: 56px; min-height: 36px;
}
body.cici .sc-nums { display: flex; align-items: baseline; gap: 7px; }
body.cici .sc-nums b {
  font-size: 30px; font-weight: 800; line-height: 1;
  color: #f0c040; font-variant-numeric: tabular-nums;
}
body.cici .sc-nums i { font-style: normal; font-size: 13px; color: #b3a294; }
body.cici .sc-nums.dim { display: block; font-size: 14px; color: #a89a8c; padding: 6px 0; }
body.cici .sc-lab { font-size: 11px; color: #a89a8c; letter-spacing: .1em; margin-top: 5px; }

/* ── 规则 / 客服 两栏 ── */
body.cici .cols {
  display: grid; grid-template-columns: 1.35fr 1fr; gap: 16px;
  max-width: 1172px; margin: 0 auto; padding: 0 26px 46px;
}
@media (max-width: 820px) { body.cici .cols { grid-template-columns: 1fr; } }
body.cici .card {
  background: linear-gradient(168deg, #271316, #1c0d0f);
  border: 2px solid rgba(240,192,64,.42); border-radius: 14px; padding: 22px 24px;
  box-shadow: 0 0 0 1px rgba(240,192,64,.05), 0 10px 26px rgba(0,0,0,.34);
}
body.cici .card h3 { margin: 0 0 14px; font-size: 16px; color: #f0c040; }
body.cici .rules { list-style: none; margin: 0; padding: 0; }
body.cici .rules li {
  position: relative; padding: 8px 0 8px 18px; color: #cbbfb5;
  border-bottom: 1px solid rgba(240,192,64,.08);
}
body.cici .rules li:last-child { border-bottom: none; }
body.cici .rules li::before {
  content: ''; position: absolute; left: 3px; top: 17px;
  width: 5px; height: 5px; border-radius: 50%; background: #f0c040;
}
body.cici .rules b { color: #f0c040; }
body.cici .qqbox { border-color: rgba(240,192,64,.32); }
body.cici .qqnum { color: #f0c040; font-size: 24px; }
body.cici .qqline b { color: #f0c040; }

body.cici footer {
  text-align: center; padding: 26px 20px 52px; color: #6b5c53; font-size: 13px;
  border-top: 1px solid rgba(240,192,64,.09);
}
body.cici footer .dot { margin: 0 9px; color: #4a3d38; }

/* ── 面板（登录后的主界面用） ──
   ⚠ 只限 #main 里的 —— 写成 body.cici .panel 会连弹窗一起影响：
     它的优先级(0,2,1)高过 .modal .panel(0,2,0)，会把弹窗从 420px 撑成 1172px。
   ⚠ 宽度 1120 + 外边距 26 是为了和上面的 .studio 横幅左右对齐（横幅内容也是 1120）。 */
body.cici #main { padding: 0 26px 8px; }
body.cici #main .panel {
  background: linear-gradient(168deg, #261215, #1c0d0f);
  border: 2px solid rgba(240,192,64,.5); border-radius: 14px;
  box-shadow: 0 0 0 1px rgba(240,192,64,.06), 0 12px 30px rgba(0,0,0,.42);
  max-width: 1120px;
}
/* 标题下的金色细线 —— 和首页「方案与实测分数」那条对齐，
   登录后不然整页就没有一条横线了，看着空。 */
body.cici #main .panel h2 {
  padding-bottom: 11px; margin-bottom: 14px;
  border-bottom: 1px solid rgba(240,192,64,.3);
}
body.cici h1, body.cici h2 { color: #f0c040; }
body.cici .sub { color: #a2907f; }
body.cici .msg { color: #ff7a6b; }
body.cici .req { color: #ff7a6b; }
body.cici .mono { color: #f0c040; }

/* ── 控件 ── */
body.cici input[type=text], body.cici input:not([type]),
body.cici input[type=file], body.cici input[type=password] {
  background: #170c0e; border-color: rgba(240,192,64,.24); color: #f0c040;
}
body.cici input::placeholder { color: #9a8878; }
body.cici input:focus {
  outline: none; border-color: #f0c040;
  box-shadow: 0 0 0 3px rgba(240,192,64,.12);
}
body.cici input[type=file] { background: #170c0e; color: #b9a89b; }

/* ── 注册步骤 ── */
body.cici .flow > div { background: #221012; border-color: rgba(240,192,64,.13); color: #cbb89e; }
body.cici .flow > div > b:first-child { background: #f0c040; color: #231114; }

/* ── 方案勾选卡（登录后） ── */
body.cici .fbtn { background: #221012; border-color: rgba(240,192,64,.2); color: #cbb89e; }
body.cici .fbtn:hover { border-color: rgba(240,192,64,.5); }
body.cici .fbtn.on {
  background: linear-gradient(#f9d874, #e0a91e);
  border-color: #c9971a; color: #231114; font-weight: 700;
}
body.cici .fnote { color: #b98b3a; }
body.cici .scheme { background: #321d1e; border-color: rgba(240,192,64,.4); }
body.cici .scheme:hover { border-color: rgba(240,192,64,.45); background: #3d2426; }
body.cici .scheme.on { border-color: #f0c040; background: #331619; }
body.cici .scheme .nm { color: #f0dcb0; }
body.cici .scheme .tg { color: #6fd68f; }
body.cici .scheme .tg.gray { color: #b3a294; }
body.cici .scheme .dc { color: #a2907f; }

/* ── 星级（支持半星）──
   底下一层暗星，上面盖一层金星，用 width 裁切 —— 所以 4.5 这种半星画得出来。
   用 ❤ 之类字符拼是做不到的，那些只能整数颗。 */
.stars { position: relative; display: inline-block; line-height: 1;
         letter-spacing: 2px; color: rgba(240,192,64,.16); }
.stars i { position: absolute; left: 0; top: 0; overflow: hidden;
           white-space: nowrap; color: #f0c040; font-style: normal; }
.srows { margin-top: 9px; display: flex; flex-direction: column; gap: 3px; }
.srow { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.srow .sk { color: #b3a294; width: 42px; flex: 0 0 auto; }

/* ── 选歌清单 ── */
body.cici .picklist .frow { border-bottom-color: rgba(240,192,64,.1); }
body.cici .picklist .frow:hover { background: #221012; }

/* ── 任务 ── */
body.cici .jobs .job { background: #1a0e10; border-color: rgba(240,192,64,.13); }
body.cici .jobs .job.done { border-color: rgba(46,204,113,.38); background: #12170e; }
body.cici .jobs .job.failed { border-color: rgba(192,57,43,.5); background: #1a0d0d; }
body.cici .job .st { color: #b3a294; }
body.cici .bar { background: #281416; }
body.cici .bar > i { background: linear-gradient(90deg, #d9a41f, #f0c040); }
body.cici .job .files a { background: #39191d; color: #f0dcb0; }
body.cici .job .files a:hover { background: #4a2227; }
body.cici .job .files a.listen { background: #221012; color: #a2938a; }
body.cici .job .hint { color: #d8a13c; }
body.cici .job .warn { color: #ff7a6b; }

/* ── 流水表 ── */
body.cici #ledger th, body.cici #ledger td {
  border-bottom-color: rgba(240,192,64,.09); color: #cbb89e;
}
body.cici #ledger th { color: #f0c040; }
body.cici #ledger .plus { color: #6fd68f; }
body.cici #ledger .minus { color: #ff7a6b; }

/* ── 弹窗 ── */
body.cici .modal { background: rgba(6,4,4,.8); backdrop-filter: blur(3px); }
body.cici .modal .panel { background: linear-gradient(168deg, #2b1619, #1e0e10); }

/* ══════════════════════════════════════════════════════════════════
   维护中
   ══════════════════════════════════════════════════════════════════
   两处共用这一套样式，别在两边各写一份：
     ① maintenance.html —— 服务端直接把 / 换成的那一页（新来的访客）
     ② index.html 里的 #maint —— 客户【早就开着页面】时，接口返回 503
        由 app.js 切到这一块（同一个网址，不跳转）
   所以 body 上要挂 .mpage 才能整页居中，不然 index.html 的正文也会被居中。
   ══════════════════════════════════════════════════════════════════ */
body.cici.mpage {
  min-height: 100vh; display: flex; align-items: center;
  justify-content: center; padding: 40px 22px;
}
body.cici .mwrap {
  position: relative; z-index: 1; max-width: 560px; width: 100%;
  text-align: center;
}
body.cici #maint { min-height: 74vh; display: flex; align-items: center;
                   justify-content: center; padding: 50px 22px; }
body.cici .mlogo {
  display: flex; align-items: center; justify-content: center; gap: 11px;
  color: #f0c040; font-size: 18px; font-weight: 800; margin-bottom: 28px;
}
body.cici .mlogo .logo {
  width: 34px; height: 34px; border-radius: 9px; display: block;
  box-shadow: 0 0 0 1px rgba(240,192,64,.6), 0 0 16px rgba(240,192,64,.2);
}
body.cici .mcard {
  background: linear-gradient(168deg, #271316, #1c0d0f);
  border: 2px solid rgba(240,192,64,.5); border-radius: 16px;
  padding: 38px 30px 30px;
  box-shadow: 0 0 0 1px rgba(240,192,64,.06), 0 16px 40px rgba(0,0,0,.45);
}
body.cici .mtag {
  display: inline-block; font-size: 12px; font-weight: 800; letter-spacing: .1em;
  color: #231114; background: linear-gradient(#f9d874, #e0a91e);
  border-radius: 20px; padding: 3px 12px; margin-bottom: 18px;
}
body.cici .mcard h1 { margin: 0 0 10px; font-size: 34px; color: #fff; letter-spacing: -.5px; }
body.cici .mlead { margin: 0 0 24px; color: #cfbfb1; font-size: 15px; line-height: 1.7; }
body.cici .mnote {
  color: #cbb89e; font-size: 14px; line-height: 1.7; margin: 0 0 22px;
  padding: 12px 16px; background: rgba(240,192,64,.06);
  border-left: 3px solid rgba(240,192,64,.5); border-radius: 0 8px 8px 0;
  text-align: left;
}
body.cici .mqq { margin: 0; font-size: 14px; color: #a2907f; }
body.cici .mqq b { color: #f0c040; font-size: 18px; letter-spacing: .5px; }
body.cici .mfoot { margin-top: 22px; font-size: 12px; color: #6b5c53; }


/* ══════════════════════════════════════════════════════════════
   四个系列用【颜色】区分（2026-09-28 作者要求）
   A/B/C/D 是四套完全不同的思路，一屏扫过去要能一眼分清。
   边框染系列色 + 方案名跟着上色；选中时再加粗一档。

   ⚠ 优先级是这里唯一的坑：.scard.ok（3 个类）会盖掉 .fam-X（2 个类），
   导致 12 张「双80」卡片的边框全被抢回金色。所以每条都必须把
   .ok / .on 这些状态类一起写进去，凑到 4 个类才压得住。
   ══════════════════════════════════════════════════════════════ */
body.cici .scard[class*="fam-"], body.cici .scheme[class*="fam-"] {
  border-style: solid; border-width: 2px;
}

body.cici .scard.fam-A, body.cici .scard.fam-A.ok,
body.cici .scheme.fam-A, body.cici .scheme.fam-A.on { border-color: #f0cf4a; }
body.cici .scard.fam-B, body.cici .scard.fam-B.ok,
body.cici .scheme.fam-B, body.cici .scheme.fam-B.on { border-color: #3fbf7f; }
body.cici .scard.fam-C, body.cici .scard.fam-C.ok,
body.cici .scheme.fam-C, body.cici .scheme.fam-C.on { border-color: #e0523f; }
body.cici .scard.fam-D, body.cici .scard.fam-D.ok,
body.cici .scheme.fam-D, body.cici .scheme.fam-D.on { border-color: #4d9fe0; }

body.cici .fam-A .nm, body.cici .fam-A .sc-name { color: #f7dd7a; }
body.cici .fam-B .nm, body.cici .fam-B .sc-name { color: #6fd8a3; }
body.cici .fam-C .nm, body.cici .fam-C .sc-name { color: #f28b78; }
body.cici .fam-D .nm, body.cici .fam-D .sc-name { color: #7fc0f5; }

/* 选中：边框再加粗，铺一层极淡的系列色底 */
body.cici .scheme[class*="fam-"].on {
  /* 边框宽度必须和未选中一致（作者要求），选中状态用外圈光晕表达 */
  box-shadow: 0 0 0 3px rgba(240,192,64,.34), 0 10px 24px rgba(0,0,0,.45);
}
body.cici .scheme.fam-A.on { background: #2e2712; }
body.cici .scheme.fam-B.on { background: #102a20; }
body.cici .scheme.fam-C.on { background: #2e1412; }
body.cici .scheme.fam-D.on { background: #12283b; }


/* 「推荐」角标 —— 作者指定 A1/B2/C1/D1 四档 */
body.cici .rec {
  display: inline-block; margin-left: 7px; padding: 0 7px;
  font-size: 11px; font-weight: 800; line-height: 17px; vertical-align: 1px;
  color: #241114; background: linear-gradient(#f9d874, #e0a91e);
  border-radius: 20px; letter-spacing: .04em;
}
body.cici .sc-rec {
  display: inline-block; margin-left: 7px; padding: 0 7px;
  font-size: 11px; font-weight: 800; line-height: 17px; vertical-align: 1px;
  color: #241114; background: linear-gradient(#f9d874, #e0a91e); border-radius: 20px;
}

/* D 族那条「慢」的提示。深底上用暖黄，和正文区分开 */
body.cici .dc.note, body.cici .sc-note {
  margin-top: 8px; padding: 7px 9px; border-radius: 7px;
  background: rgba(240,192,64,.09); border-left: 3px solid rgba(240,192,64,.6);
  color: #d8c49a; font-size: 12px; line-height: 1.6;
}


/* ══════════════════════════════════════════════════════════════
   2026-09-28 作者要求的一轮排版调整
   ① 说明文字挪到星星下面 —— 各档带不带说明不一样，放上面会让星星错位
   ② 12 张卡的名称/星星必须对齐、边框一样粗
   ③ 名称 + 三行星 + 星标全部放大
   ④「推荐」要更醒目
   ⑤ 整体字号放大
   ══════════════════════════════════════════════════════════════ */

/* 卡片：统一高度基线，行内自动拉齐（grid 的 align-items 默认就是 stretch） */
body.cici .scard, body.cici label.scard {
  /* 统一高度基线 —— 要到最长的那张（A1 有 3 行说明、D 有 2 行提示）也塞得下。
     改小了这个值，带说明的那几张又会把整行撑高，12 张就不一样大了。 */
  min-height: 300px;
}

/* 标题行：勾选框 + 名称 + 推荐 + 【折后价 + 折扣 + 划线原价】。
   ⚠ gap 从 9px 收到 6px（2026-10-08）：三样价格挤进来之后，
      9px 在 1440px（卡片到顶 351px）下会超出 ~10px、被 .scard 的
      overflow:hidden 静默裁掉。收间距是最不显眼的腾地方办法。 */
body.cici .sc-head {
  display: flex; align-items: center; gap: 6px; margin-bottom: 13px;
}
body.cici .sc-head input[type=checkbox] {
  flex: 0 0 auto; width: 19px; height: 19px; margin: 0;
  accent-color: #f0c040; cursor: pointer;
}
body.cici .sc-head .sc-name { margin: 0; padding: 0; min-height: 0; flex: 0 0 auto; }
body.cici .sc-head .sc-badge { position: static; margin-left: auto; }

/* ③ 名称放大 */
body.cici .sc-name { font-size: 32px; font-weight: 800; line-height: 1.15; letter-spacing: .01em; }

/* ③ 星星那三行放大 */
body.cici .srows { margin-top: 11px; gap: 6px; }
body.cici .srow { font-size: 14px; gap: 10px; }
body.cici .srow .sk { width: 54px; font-size: 14px; }
body.cici .stars { font-size: 15px; letter-spacing: 1px; }

/* ④ 推荐角标：更大、更亮、带一点发光。
   ⚠ 内边距 13 → 11（2026-10-08）：给头部的三样价格腾地方，见 .sc-head 那条。 */
body.cici .rec {
  margin-left: 3px; padding: 0 11px; font-size: 14px; line-height: 25px;
  color: #2a1408; background: linear-gradient(#ffe89a, #f0b62a);
  border-radius: 20px; font-weight: 800; letter-spacing: .06em;
  box-shadow: 0 0 8px rgba(240,192,64,.55);
}

/* ⑤ 价格角标：每一档都挂（作者要求 A/B/C 的 1 积分也写出来）。
   颜色跟着系列走（A 黄 / B 绿 / C 红 / D 蓝），和卡片边框同色系 ——
   一屏 12 张卡扫下来，先靠颜色分系列，再看数字分价格。
   公共部分写一次，颜色四条各给各的；边框用 currentColor 跟着文字色走。 */
body.cici .price {
  margin-left: 3px; padding: 0 11px; font-size: 13px; line-height: 24px;
  border-radius: 20px; font-weight: 700; letter-spacing: .02em;
  border: 1px solid currentColor;
}
body.cici .fam-A .price { color: #f0cf4a; background: rgba(240,207,74,.13); }
body.cici .fam-B .price { color: #3fbf7f; background: rgba(63,191,127,.13); }
body.cici .fam-C .price { color: #e0523f; background: rgba(224,82,63,.13); }
body.cici .fam-D .price { color: #4d9fe0; background: rgba(77,159,224,.15); }

/* 说明 / D 族提示：统一挪到最下面 */
body.cici .sc-note {
  margin-top: 11px; padding: 8px 10px; border-radius: 7px;
  background: rgba(255,255,255,.045); border-left: 3px solid rgba(240,192,64,.42);
  color: #b9ab9d; font-size: 12.5px; line-height: 1.65;
}
body.cici .sc-note.warnbox {
  background: rgba(240,192,64,.1); border-left-color: #f0c040; color: #e0cda2;
}

/* ② 边框粗细统一（含选中态）*/
body.cici .scard, body.cici label.scard { border-width: 2px; }

/* ⑤ 整体字号放大 */
body.cici .sub { font-size: 14.5px; }
body.cici h2 { font-size: 19px; }
body.cici .job .top b { font-size: 16px; }
body.cici .job .st { font-size: 14px; }
body.cici .job .sub { font-size: 14px; }
body.cici .job .files a { font-size: 14px; padding: 7px 13px; }
body.cici .fbtn { font-size: 14.5px; padding: 7px 17px; }
body.cici #landing .lead { font-size: 16px; }
/* 分数：原来用 30~33px 当视觉主体，现在让位给编号，缩到 19px。
   改大改小都在这一行，两处（.sc-nums b 有多处声明）都跟着走。 */
body.cici .sc-nums b { font-size: 19px; font-weight: 700; }

/* 任务分页 */
body.cici .pager {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid #dbe3ec22;
}
body.cici .pgbtn {
  font: inherit; font-size: 14px; padding: 6px 13px; cursor: pointer;
  border-radius: 7px; border: 1px solid rgba(240,192,64,.35);
  background: transparent; color: #d8c49a;
}
body.cici .pgbtn:hover { border-color: rgba(240,192,64,.7); }
body.cici .pgbtn.on {
  background: linear-gradient(#f9d874, #e0a91e); color: #2a1408;
  font-weight: 800; border-color: transparent;
}
body.cici .pgbtn:disabled { opacity: .35; cursor: default; }
body.cici .pager .sub { margin-left: auto; }

/* ⚠ 覆盖：老的 .scheme 是「左边勾选框、右边文字」的横向 flex 布局，
   现在的卡片是纵向多行（标题/分数/星星/说明），必须改回块级。
   specificity 要压过 body.cici .scheme（3 个类）—— 这里是 4 个。 */
body.cici label.scard.scheme {
  display: block; padding: 16px 17px 15px;
}
body.cici label.scard.scheme:hover { transform: translateY(-2px); }

/* 编号放大后，卡片内容比统一基线矮了一截，下半部分就空出一块。
   把卡片改成纵向 flex、说明用 margin-top:auto 锚到底部 ——
   这样「名称/分数/星星」贴顶对齐（12 张卡的星星仍然一条线），
   空出来的部分落在说明下面，看着是【有意留白】而不是没排满。 */
body.cici .scard, body.cici label.scard {
  display: flex; flex-direction: column;
}
body.cici .sc-note { margin-top: auto; }

/* ⚠ 2026-10-08：底部只剩说明 / D 族提示，包进 .sc-foot。
   只留【一个】margin-top:auto —— .sc-note 自己也有一个，
   两条会均分空白、把这块浮到卡片中间去。 */
body.cici .sc-foot {
  margin-top: auto; display: flex; flex-direction: column; gap: 8px;
}
body.cici .sc-foot .sc-note { margin-top: 0; }
/* 「折后价 + 折扣 + 被划掉的原价」= 一个整体（作者要求），
   整组挤在一起放进卡片头部那一行，组内间距比头部其它元素更紧。 */
body.cici .sc-head .priceline {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 3px;
}
body.cici .sc-head .priceline .price { margin-left: 0; }
body.cici .sc-head .priceline .was {
  font-size: 11px; color: #a89a8c; font-weight: 400;
  text-decoration: line-through; text-decoration-thickness: 1px;
}
/* 折扣徽标：夹在「折后价」和「被划掉的原价」中间（作者 2026-10-08 要求），
   三样合起来是一个整体：`2 积分  6.7折  原价 3 积分`。
   ⚠ 卡片是 3 列网格、.scard 是 overflow:hidden —— 头部排太长会被【静默裁掉】，
      所以这个徽标比 .price 收一点，也不许被压扁（flex:0 0 auto）。 */
body.cici .sc-head .off {
  flex: 0 0 auto;
  margin-left: 0; padding: 0 6px; line-height: 20px;
  font-size: 12px; font-weight: 800; letter-spacing: .02em;
  color: #241114; background: linear-gradient(#f9d874, #e0a91e);
  border-radius: 20px;
}

/* ⚠ 头部这几个徽标里的字【不许换行】（2026-10-08）。
   为什么：.sc-head 是 nowrap，但徽标是 flex 项、默认可收缩。头部挤不下时
   徽标被压到比文字还窄，文字就在【徽标内部】折成两行 → 徽标变高 → 头部变高
   → 下面 12 张卡的星星行跟着错位。
   实测：D1 的价钱徽标宽 62px 就折行、C3 的 63px 不折 —— 差 1px，
   来自网格列 .328/.344 那种分数像素。所以这毛病是随机的、卡一卡就错位。
   加了 nowrap 之后徽标不会低于文字宽度，头部高度恒等于最高的那个（编号 30px），
   星星永远对齐。宽屏本来就不会挤，等于没改。
   ⚠ 写在 .priceline 上就够了（white-space 会继承给它里面那三个），
      另外三个仍然单列，免得以后有人把它们拆出来单放就漏了。 */
body.cici .sc-head .priceline,
body.cici .sc-head .price,
body.cici .sc-head .rec,
body.cici .sc-head .off { white-space: nowrap; }

/* ⚠ 窄屏兜底（2026-10-08），两档。
   卡片头部是一行 flex：勾选框 + 编号 + 推荐 + 【折后价 + 折扣 + 划线原价】。
   实测卡片内容区要 ≥ 约 315px 才放得下一行（宽屏、卡片到顶 351px 时够）。
   窄过这个宽度就分两档处理，不多不少：

   第一档 ≤1300：还放得下，只把这行收紧凑（间距 + 徽标内边距 + 编号略小）。
   第二档 ≤1140：一行真的放不下了 —— 放开换行，**但给一个固定的 min-height**，
     让【每张卡】都占两行的高度，否则只有塞不下的那几张变高、12 张卡的星星行
     又错位（那正是 2026-10-08 修掉的那个毛病）。
     ⚠ 别改成两列去解决：上面 .schemes 那条注释里写着作者要求
       「3 个一行，共 4 行」，改列数会违背它。
     ⚠ min-height 必须够放下两行 —— 实测两行最高 58.9px（编号那行 + row-gap + 价格
       那行），所以取 64px。取小了会出现「两张卡 58.9、其余 54」，
       星星行照样错位（910px 实测踩到过）。
     ⚠ 阈值 1140 是量出来的：卡片宽在视口 ~1200 以下才开始缩，一行要 ~288px 内容
       （卡片 ≥ 322px、视口 ≥ ~1130）。开早了会在还放得下的时候白垫高 20px。 */
@media (max-width: 1300px) {
  body.cici .sc-head { gap: 5px; }
  body.cici .sc-name { font-size: 29px; }
  body.cici .rec { padding: 0 9px; }
  body.cici .sc-head .price { padding: 0 9px; }
  body.cici .sc-head .off { padding: 0 5px; }
  body.cici .sc-head .priceline .was { font-size: 10.5px; }
}
@media (max-width: 1140px) {
  body.cici .sc-head {
    flex-wrap: wrap; align-content: flex-start;
    row-gap: 3px; min-height: 64px; margin-bottom: 11px;
  }
  body.cici .sc-name { font-size: 26px; }
  body.cici .rec { padding: 0 8px; font-size: 13px; line-height: 22px; }
  body.cici .sc-head .priceline { gap: 2px; }
  body.cici .sc-head .price { padding: 0 8px; font-size: 12px; }
  body.cici .sc-head .off { padding: 0 5px; font-size: 11px; }
  body.cici .sc-head .priceline .was { font-size: 11px; }
}


/* ══════════════════════════════════════════════════════════════
   2026-09-28 美术升级（第 5/6/8 条）
   只做【不改变布局、不吃 CPU、不推翻已有决定】的三条。
   ══════════════════════════════════════════════════════════════ */

/* ⑧ 卡片悬停：金色光晕 + 微抬。
   原来只有 translateY(-2px)，太微弱；加一圈跟着系列色走的柔光，
   鼠标扫过时能明确知道这张可以点。用 ::after 画，不动布局。 */
body.cici .scard { transition: transform .18s ease, box-shadow .18s ease; }
body.cici .scard:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 26px rgba(0,0,0,.42), 0 0 0 1px rgba(240,192,64,.25),
              0 0 22px rgba(240,192,64,.18);
  z-index: 2;
}
body.cici label.scard.scheme:hover { border-color: rgba(240,192,64,.62); }

/* ⑥ 按钮质感：顶部一道内高光（模拟受光面）+ 按下时下沉。
   原来是纯渐变，平。 */
body.cici button.primary {
  position: relative; overflow: hidden;
  background-image: linear-gradient(#ffd978, #e8b02a 52%, #cf9a18);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.5), 0 2px 6px rgba(0,0,0,.3);
  transition: transform .1s ease, box-shadow .12s ease, filter .12s ease;
}
body.cici button.primary:hover { filter: brightness(1.06); }
body.cici button.primary:active {
  transform: translateY(1px);
  box-shadow: inset 0 2px 5px rgba(0,0,0,.28);
}

/* ⑤ 主视觉：给那张频谱图加一层极慢的呼吸。
   ⚠ 不换成 SVG/CSS 波形 —— 那张图是 _gen_art.py 代码画的，换掉要重做整套配色，
     而且纯 CSS 波形在深色底上很难做到这个质感。这里只加 4.5 秒一次的
     极缓明暗 + 上下 6px 浮动，看得出活着但不抢注意力。
   加了 prefers-reduced-motion 保护：系统里关掉动效的人不会看到它。 */
@keyframes cici-breathe {
  0%, 100% { transform: translateY(0);     filter: drop-shadow(0 0 0 rgba(240,192,64,0)); }
  50%      { transform: translateY(-7.2px); filter: drop-shadow(0 0 22px rgba(240,192,64,.36)); }
}
@keyframes cici-drift {
  0%, 100% { transform: translateY(0);     opacity: .9; }
  50%      { transform: translateY(-4px);  opacity: 1; }
}
body.cici .hero-art img, body.cici .studio-art img {
  animation: cici-breathe 4.5s ease-in-out infinite;
}
body.cici .side-art { animation: cici-drift 6s ease-in-out infinite; }
body.cici .side-art.r { animation-name: cici-drift-r; }
@keyframes cici-drift-r {
  0%, 100% { transform: scaleX(-1) translateY(0);    opacity: .9; }
  50%      { transform: scaleX(-1) translateY(-4px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  body.cici .hero-art img, body.cici .studio-art img { animation: none; }
}


/* ══════════════════════════════════════════════════════════════
   浅色模式（2026-09-28 作者要求）
   ══════════════════════════════════════════════════════════════
   做法说明：整套界面是「深褐底 + 金色字」，金色 #f0c040 在 CSS 里出现 28 次。
   直接改那 28 处会牵动浅色/深色两套，风险大。这里用【覆盖块】：
   给 body 加 .light 类，下面这组规则把「页面/卡片/文字/边框」换成浅色系，
   再把金色换成深琥珀（#9a6b12），金色在奶油底上等于看不见。

   ⚠ 深色是默认，浅色是叠加层 —— 不想保留浅色模式时，删掉这个块 + 那个按钮即可。
   ⚠ 四个系列色在浅底上要另外给一套更深的，黄色系（fam-A）在奶油底上尤其看不见。
   ══════════════════════════════════════════════════════════════ */
body.cici.light {
  color-scheme: light;
  background-color: #f4efe6;
  background-image:
    radial-gradient(1400px 800px at 50% -18%, rgba(255,236,190,.85), transparent 70%),
    radial-gradient(900px 800px at -12% 38%, rgba(214,160,120,.16), transparent 72%),
    radial-gradient(900px 800px at 112% 62%, rgba(170,150,200,.14), transparent 72%),
    linear-gradient(180deg, #fbf7f0 0%, #f4efe6 48%, #e9e1d3 100%);
  color: #3a2e26;
}
body.cici.light::after { opacity: .05; }
body.cici.light .side-art { opacity: .1; }

/* 头部栏 */
body.cici.light header {
  background: rgba(255,252,246,.93);
  border-bottom: 1px solid rgba(154,107,18,.35);
}
body.cici.light .hright { color: #6b5b4d; }
body.cici.light .who { color: #6b5b4d; }
body.cici.light .bal b { color: #9a6b12; }
body.cici.light button.ghost { color: #6b5b4d; }
body.cici.light button.ghost:hover { color: #9a6b12; }

/* 卡片 */
body.cici.light .scard,
body.cici.light label.scard.scheme {
  background: linear-gradient(168deg, #fffdf9, #f7f1e7);
  box-shadow: 0 1px 0 #fff inset, 0 6px 16px rgba(120,100,80,.13);
}
body.cici.light .scard.ok::before { background: linear-gradient(90deg, transparent, #d9a520, transparent); }
body.cici.light .sc-name { color: #3a2e26; }
body.cici.light .sc-nums b { color: #9a6b12; }
body.cici.light .sc-nums i { color: #a8988a; }
body.cici.light .sc-lab { color: #8a7a6a; }
body.cici.light .srow .sk { color: #7a6a5c; }
body.cici.light .sc-note {
  background: rgba(120,100,80,.07); border-left-color: rgba(154,107,18,.45); color: #6b5b4d;
}
body.cici.light .sc-note.warnbox {
  background: rgba(217,165,32,.14); border-left-color: #d9a520; color: #6b5424;
}
body.cici.light .rec { box-shadow: 0 0 0 rgba(0,0,0,0), 0 1px 3px rgba(120,100,80,.3); }
/* 价签浅色版：底色跟卡片选中态的浅底同一套，文字用各系列在奶油底上
   够深的那一档（黄色系尤其要压深，不然看不见）。 */
body.cici.light .fam-A .price { color: #9a6b12; background: #fdf6e3; }
body.cici.light .fam-B .price { color: #2e8b57; background: #eef8f2; }
body.cici.light .fam-C .price { color: #c0392b; background: #fdeeec; }
body.cici.light .fam-D .price { color: #1c5f9e; background: #e8f2fb; }
/* 「折后价 + 折扣 + 划线原价」那一组的浅色版（深色版在上面的 .sc-foot 那段）。 */
body.cici.light .sc-head .priceline .was { color: #7a6a5c; }
body.cici.light .sc-head .off {
  color: #fff; background: linear-gradient(#e3b747, #c9a227);
}

/* 四个系列色 —— 浅底上要用更深的一套，尤其黄色系 */
body.cici.light .scard.fam-A, body.cici.light .scard.fam-A.ok,
body.cici.light .scheme.fam-A, body.cici.light .scheme.fam-A.on { border-color: #c9a227; }
body.cici.light .scard.fam-B, body.cici.light .scard.fam-B.ok,
body.cici.light .scheme.fam-B, body.cici.light .scheme.fam-B.on { border-color: #2e8b57; }
body.cici.light .scard.fam-C, body.cici.light .scard.fam-C.ok,
body.cici.light .scheme.fam-C, body.cici.light .scheme.fam-C.on { border-color: #c0392b; }
body.cici.light .scard.fam-D, body.cici.light .scard.fam-D.ok,
body.cici.light .scheme.fam-D, body.cici.light .scheme.fam-D.on { border-color: #2f6fb5; }
body.cici.light .fam-A .nm, body.cici.light .fam-A .sc-name { color: #a37f10; }
body.cici.light .fam-B .nm, body.cici.light .fam-B .sc-name { color: #1f6b41; }
body.cici.light .fam-C .nm, body.cici.light .fam-C .sc-name { color: #a32a1e; }
body.cici.light .fam-D .nm, body.cici.light .fam-D .sc-name { color: #235a94; }
body.cici.light .scheme.fam-A.on { background: #fdf6e3; }
body.cici.light .scheme.fam-B.on { background: #eef8f2; }
body.cici.light .scheme.fam-C.on { background: #fdeeec; }
body.cici.light .scheme.fam-D.on { background: #eef4fb; }
body.cici.light .scheme.fam-A.on, body.cici.light .scheme.fam-B.on,
body.cici.light .scheme.fam-C.on, body.cici.light .scheme.fam-D.on {
  box-shadow: 0 0 0 3px rgba(154,107,18,.22), 0 8px 18px rgba(120,100,80,.18);
}

/* 面板 / 任务卡 / 输入 */
body.cici.light .panel, body.cici.light .jobs .job, body.cici.light .card {
  background: #fffdf9; border-color: #ddd2c0;
}
body.cici.light .jobs .job.done { background: #f2fbf4; border-color: #b7ddc2; }
body.cici.light .jobs .job.failed { background: #fdf3f2; border-color: #ecc4c0; }
body.cici.light .job .top b { color: #3a2e26; }
body.cici.light .job .st, body.cici.light .job .sub { color: #7a6a5c; }
body.cici.light .job .files a { background: #9a6b12; }
body.cici.light .job .files a.listen { background: #7a6a5c; }
/* ⚠ 这串 input 选择器必须把上面 450 / 459 行的【原样抄一遍】，
   不能图省事写成 body.cici.light input。
   原因：`input[type=text]` 里的属性选择器和类一样算进优先级，
   基础规则是 (0,3,1)，简写的是 (0,2,2) —— 简写那条根本压不住，
   浅色模式下输入框会一直是黑底金字。
   第一次没查出来是因为输入框只在弹窗里，截图扫不到。 */
body.cici.light input[type=text], body.cici.light input:not([type]),
body.cici.light input[type=file], body.cici.light input[type=password],
body.cici.light input, body.cici.light select, body.cici.light textarea {
  background: #fffdf9; border-color: #cfc2ae; color: #3a2e26;
}
body.cici.light input::placeholder { color: #9a8878; }
body.cici.light input:focus {
  border-color: #9a6b12; box-shadow: 0 0 0 3px rgba(154,107,18,.14);
}
/* 上文件那个按钮原生就是灰底，浅色下给个浅底深字 */
body.cici.light input[type=file] { background: #fffdf9; color: #6b5b4d; }
body.cici.light .fbtn { background: #fffdf9; border-color: #d5c9b6; color: #6b5b4d; }
body.cici.light .fbtn.on { background: linear-gradient(#f9d874, #e0a91e); color: #3a2410; border-color: #c9971a; }
body.cici.light .fnote { color: #8a6a2a; }
body.cici.light .sub { color: #7a6a5c; }
body.cici.light h2 { color: #3a2e26; }
body.cici.light .sec-head h2 { color: #3a2e26; }
body.cici.light .hero h1, body.cici.light .studio-txt h1 { color: #2e241d; }
body.cici.light .kicker { color: #9a6b12; }
body.cici.light .lead { color: #6b5b4d; }
body.cici.light .lead b { color: #9a6b12; }
body.cici.light .cta-hint { color: #8a7a6a; }
body.cici.light footer { color: #8a7a6a; }
body.cici.light .rules li { color: #4a3e34; }
body.cici.light .qqnum { color: #9a6b12; }
body.cici.light .pager { border-top-color: #ddd5c6; }
body.cici.light .pgbtn { border-color: #d5c9b6; color: #6b5b4d; background: #fffdf9; }
body.cici.light .pgbtn.on { background: linear-gradient(#f9d874, #e0a91e); color: #3a2410; }
body.cici.light .studio { background: #fbf7f0; }
body.cici.light #maint .mwrap { color: #3a2e26; }

/* 主题切换按钮 */
body.cici #btn-theme { font-size: 14px; }


/* ══════════════════════════════════════════════════════════════
   主视觉频谱波形：每根柱子各自不规则呼吸（2026-09-28 作者要求）
   ══════════════════════════════════════════════════════════════
   原来是 hero_spec.png（900x300，宽高比 3:1）一整张图，只能整块动。
   改成 DOM 柱子 —— 形状和参差都由 app.js 的 buildWave() 生成，
   这里只管画和动。

   ⚠ 动画用 scaleY（从底部缩放），不改 height。56 根柱子一起改 height 会触发
     重排，CPU 直接吃满；transform 走合成层，几乎不花代价。
   ⚠ transform-origin 必须是 bottom，否则柱子会从中间往两头缩，像被压扁。
   ══════════════════════════════════════════════════════════════ */
body.cici .hero-art, body.cici .studio-art { aspect-ratio: 3 / 1; }
body.cici .wave {
  display: flex; align-items: flex-end; justify-content: center;
  gap: 3px; width: 100%; height: 100%;
  opacity: .92;
  filter: drop-shadow(0 0 40px rgba(240,192,64,.22));
}
body.cici .wave i {
  flex: 1 1 0; min-width: 2px;
  height: var(--h);
  transform-origin: bottom center;
  border-radius: 2px 2px 1px 1px;
  background: linear-gradient(180deg, #ffeaa8 0%, #f0c040 45%, #a8741a 100%);
  animation: cici-bar var(--t) ease-in-out infinite;
  animation-delay: var(--d);
}
@keyframes cici-bar {
  0%, 100% { transform: scaleY(1); }
  50%      { transform: scaleY(var(--lo)); }
}
@media (prefers-reduced-motion: reduce) {
  body.cici .wave i { animation: none; }
}

/* 浅色模式：金柱在奶油底上要压深一档才看得见 */
body.cici.light .wave { filter: drop-shadow(0 0 28px rgba(180,130,20,.2)); opacity: .95; }
body.cici.light .wave i {
  background: linear-gradient(180deg, #f7dd8e 0%, #d9a520 45%, #94700f 100%);
}


/* ══════════════════════════════════════════════════════════════
   示例试听（2026-09-28）
   四个推荐档各截 15 秒，素材在 /static/samples/demo_XX.mp3
   ══════════════════════════════════════════════════════════════ */
body.cici .demo {
  /* 5 个：原曲 + 四个系列。窄屏逐级降到 3 / 2 / 1 列。 */
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 10px; max-width: 1172px; margin: 0 auto; padding: 0 26px;
}
body.cici .ditem {
  background: linear-gradient(168deg, #3b2422, #2a1716);
  border: 2px solid rgba(240,192,64,.5);
  border-radius: 13px; padding: 11px 12px 12px;
}
body.cici .dhead { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
body.cici .dhead b { font-size: 19px; font-weight: 800; line-height: 1.1; }
body.cici .dnum {
  margin-left: auto; font-size: 13px; color: #b3a294;
  font-variant-numeric: tabular-nums;
}
/* 播放器占满整宽。原生控件在深底上是深色皮肤，配色和卡片是一路的 */
body.cici .ditem audio { width: 100%; height: 34px; display: block; outline: none; }
body.cici .demo-note { max-width: 1172px; margin: 12px auto 0; padding: 0 26px; }

/* 原曲：中性色。它不是系列，是拿来对照的基准，不该跟四个系列抢颜色 */
body.cici .ditem.fam-src { border-color: rgba(232,222,210,.42); }
body.cici .ditem.fam-src b { color: #e8ded2; }
body.cici.light .ditem.fam-src { border-color: #b8aa96; }
body.cici.light .ditem.fam-src b { color: #4a3e34; }

/* 四个系列各自的颜色，和方案卡一致 */
body.cici .ditem.fam-A { border-color: #f0cf4a; }
body.cici .ditem.fam-A b { color: #f7dd7a; }
body.cici .ditem.fam-B { border-color: #3fbf7f; }
body.cici .ditem.fam-B b { color: #6fd8a3; }
body.cici .ditem.fam-C { border-color: #e0523f; }
body.cici .ditem.fam-C b { color: #f28b78; }
body.cici .ditem.fam-D { border-color: #4d9fe0; }
body.cici .ditem.fam-D b { color: #7fc0f5; }

@media (max-width: 1150px) { body.cici .demo { grid-template-columns: repeat(3, minmax(0,1fr)); } }
@media (max-width: 780px)  { body.cici .demo { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 520px)  { body.cici .demo { grid-template-columns: 1fr; padding: 0 20px; } }

/* 浅色模式 */
body.cici.light .ditem { background: linear-gradient(168deg, #fffdf9, #f7f1e7); }
body.cici.light .dnum { color: #7a6a5c; }
body.cici.light .ditem.fam-A { border-color: #c9a227; } body.cici.light .ditem.fam-A b { color: #a37f10; }
body.cici.light .ditem.fam-B { border-color: #2e8b57; } body.cici.light .ditem.fam-B b { color: #1f6b41; }
body.cici.light .ditem.fam-C { border-color: #c0392b; } body.cici.light .ditem.fam-C b { color: #a32a1e; }
body.cici.light .ditem.fam-D { border-color: #2f6fb5; } body.cici.light .ditem.fam-D b { color: #235a94; }


/* 试听板块放进「面板」里时（登录后的工作台用的是 .panel），
   去掉它自带的外边距 —— 面板本身已经有内边距，再加一层会缩进两次。 */
body.cici .demo-slot.panel .demo { padding: 0; }
body.cici .demo-slot.panel .sec-head { margin-bottom: 16px; }


/* ⚠ 浅色模式必须带 #main 再来一遍。
   上面那条 body.cici #main .panel 里有【ID】，优先级(1,2,1)高过任意多的类 ——
   只写 body.cici.light .panel 是盖不住的，登录后的面板会一直是深色。
   （这就是作者报的那个 bug：浅色模式下登录，主页面板还是深色。） */
body.cici.light #main .panel {
  background: #fffdf9;
  border-color: #ddd2c0;
  box-shadow: 0 1px 0 #fff inset, 0 6px 16px rgba(120,100,80,.13);
}
body.cici.light #main .panel h2 { border-bottom-color: rgba(154,107,18,.35); }


/* ── 浅色模式漏掉的几处（2026-09-28 作者报 bug 后补）──────────────
   上一版只覆盖了「页面/卡片/文字/边框」，漏了任务卡、进度条、流水表、
   文件列表这些【只在客户有任务时才出现】的地方 —— 没有任务就看不到，
   所以当时截图没暴露出来。
   其中 #ledger 还带 ID，优先级比类高，必须显式带上。
   ⚠ 以后加浅色覆盖，把 style.css 里所有 body.cici 的深色背景规则过一遍，
     别只看当前页面上能看到的元素。 */
body.cici.light .bar { background: #e8e0d3; }
body.cici.light .bar > i { background: linear-gradient(90deg, #c9971a, #e0a91e); }
body.cici.light .picklist .frow { border-bottom-color: rgba(120,100,80,.18); }
body.cici.light .picklist .frow:hover { background: #f4efe6; }
body.cici.light #ledger th, body.cici.light #ledger td {
  border-bottom-color: rgba(120,100,80,.18); color: #4a3e34;
}
body.cici.light #ledger th { color: #9a6b12; }
body.cici.light #ledger .plus { color: #1f6b41; }
body.cici.light #ledger .minus { color: #a32a1e; }
body.cici.light .job .files a { background: #9a6b12; color: #fffdf9; }
body.cici.light .job .files a:hover { background: #a97a20; }
body.cici.light .job .files a.listen { background: #7a6a5c; color: #fffdf9; }
body.cici.light .job .hint { color: #8a6a2a; }
body.cici.light .job .warn { color: #a32a1e; }
body.cici.light .modal { background: rgba(60,48,40,.35); }


/* ── 浅色模式：按钮 / 注册流程框 / 维护卡（第三批补漏）──────────
   按钮那几条原来完全没覆盖 —— 主按钮是金色（两套主题都好看），
   但普通按钮和 .mini 是深色底，在浅色模式下是一块块黑方块。
   ⚠ primary 必须显式写回来：上面的 body.cici.light button 和
     body.cici button.primary 优先级相同(都是 3 个类)，全靠先后顺序 ——
     我的块在后面，会把金色按钮压成白的。 */
body.cici.light button { background: #fffdf9; border-color: #cfc2ae; color: #4a3e34; }
body.cici.light button:hover:not(:disabled) { border-color: #9a6b12; color: #9a6b12; }
body.cici.light button.primary {
  background: linear-gradient(#f9d874, #e0a91e);
  border-color: #c9971a; color: #241114;
  box-shadow: 0 3px 10px rgba(154,107,18,.28);
}
body.cici.light button.primary:hover:not(:disabled) { background: linear-gradient(#ffe391, #f0c040); }
body.cici.light button.ghost { background: transparent; border-color: transparent; color: #6b5b4d; }
body.cici.light button.ghost:hover:not(:disabled) { color: #9a6b12; background: rgba(154,107,18,.08); }
body.cici.light button.mini { background: #fffdf9; border-color: #c9b9a0; color: #4a3e34; }
body.cici.light button.x { background: transparent; color: #7a6a5c; }
body.cici.light button.x:hover { color: #a32a1e; border-color: rgba(163,42,30,.4); }
body.cici.light .flow > div { background: #fffdf9; border-color: #ddd2c0; color: #4a3e34; }
body.cici.light .mcard { background: #fffdf9; }

/* ── 浅色模式：弹窗体 + 方案卡悬浮（第四批）────────────────────
   弹窗（登录 / 充值 / 资料 / 维护）是挂在 body 下的，不在 #main 里面，
   所以前面那条治 #main .panel 的规则管不到它，一直还是深色面板。
   方案卡悬浮同理 —— .scheme:hover 会把卡片点成深红 #3d2426。 */
body.cici.light .modal .panel {
  background: #fffdf9;
  border-color: #ddd2c0;
  box-shadow: 0 18px 44px rgba(120,100,80,.22);
}
body.cici.light .scheme:hover { background: #fff8ec; border-color: rgba(154,107,18,.55); }

/* ── 首页公告栏（2026-10-14 加）────────────────────────────
   位置：顶部横幅下方、主视觉之前；未登录 / 登录后各一处（同一个 class）。
   配色沿用站点那套金色，不发明新颜色。
   ⚠ style.css 前后台共用：下面这些类只有客户页用，后台不引用。
   ⚠ body 上深色是 .cici、浅色是 .cici.light —— 浅色那组必须显式覆盖回来，
     否则会同时命中"深色"那组规则（旧的那几处也是这么写的）。 */

.notice-slot {
  display: flex; align-items: flex-start; gap: 10px;
  max-width: 1172px; margin: 6px auto 18px; padding: 10px 26px;
  border: 1px solid rgba(154,107,18,.28);
  border-left: 4px solid #e0a91e;
  border-radius: 8px; background: rgba(240,192,64,.12);
  color: #5a4526; font-size: 13.5px; line-height: 1.65;
}
/* 登录后那一处在 <main> 里 —— 宽度跟着 #main 里的面板走（1120，见 body.cici #main .panel），
   和上面的横幅、下面的选歌/勾方案面板左右对齐。 */
#main .notice-slot { max-width: 1120px; }
.notice-slot .nt-tag {
  flex: 0 0 auto; padding: 1px 7px; margin-top: 2px; border-radius: 4px;
  background: #e0a91e; color: #fffdf9; font-weight: 700; font-size: 12px;
  letter-spacing: .5px;
}
.notice-slot .nt-body {
  flex: 1 1 auto; white-space: pre-wrap; word-break: break-word;
}
@media (max-width: 700px) {
  /* ⚠ 左右【不要】加 margin：这块在 #main 里，#main 自己已有 26px 内边距，
     再加 12px 就会比上面的横幅、下面的面板多缩进一截（对齐会歪）。 */
  .notice-slot { margin: 8px auto 14px; padding: 9px 14px; font-size: 13px; }
}

/* 深色主题 */
body.cici .notice-slot {
  border-color: rgba(240,192,64,.30);
  border-left-color: #f0c040;
  background: rgba(240,192,64,.07);
  color: #d8c9b6;
}
body.cici .notice-slot .nt-tag { background: #f0c040; color: #241a12; }

/* 浅色主题：body 上同时有 .cici 和 .light，上面那组也会命中，所以显式覆盖回来 */
body.cici.light .notice-slot {
  border-color: rgba(154,107,18,.28);
  border-left-color: #e0a91e;
  background: rgba(240,192,64,.12);
  color: #5a4526;
}
body.cici.light .notice-slot .nt-tag { background: #e0a91e; color: #fffdf9; }
