:root{--ink:#1f2329;--mut:#6b7280;--line:#e5e7eb;--bg:#f6f7f9;--blue:#185fa5;--blue-bg:#e6f1fb;
--green:#0f6e56;--green-bg:#e1f5ee;--amber:#854f0b;--amber-bg:#faeeda;--red:#a32d2d;--red-bg:#fcebeb;
--purple:#534ab7;--purple-bg:#eeedfe;--orange:#8a4b0a;--orange-bg:#fdf0e6}
*{box-sizing:border-box}
body{margin:0;font-family:system-ui,-apple-system,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;
color:var(--ink);background:var(--bg);font-size:14px;line-height:1.6}
/* ---------- 登录页 ---------- */
#login-view{position:fixed;inset:0;background:var(--bg);display:flex;align-items:center;justify-content:center;z-index:50}
.login-card{background:#fff;border:1px solid var(--line);border-radius:12px;padding:32px 34px;width:370px;
box-shadow:0 8px 30px rgba(20,24,30,.08)}
.login-card h1{margin:0;font-size:20px;font-weight:600}
.login-card .sub{color:var(--mut);font-size:13px;margin:4px 0 18px}
.login-mark{font-size:34px;margin-bottom:6px}
.login-err{color:var(--red);font-size:13px;min-height:20px;margin-top:8px}
/* ---------- 应用框架：侧边栏 + 顶栏 ---------- */
#app-shell{display:flex;min-height:100vh}
#sidebar{width:212px;flex-shrink:0;background:#f1f2f4;border-right:1px solid var(--line);
display:flex;flex-direction:column;position:sticky;top:0;height:100vh}
.side-brand{padding:15px 16px;font-weight:600;font-size:15px;display:flex;align-items:center;gap:8px;
border-bottom:1px solid var(--line)}
.logo-dot{font-size:18px}
#side-nav{flex:1;overflow:auto;padding-bottom:10px}
.nav-sec{font-size:11px;color:var(--mut);padding:14px 16px 2px;letter-spacing:.4px}
#side-nav .tab{display:block;width:100%;text-align:left;padding:7px 16px;border:none;background:none;
border-radius:6px;color:var(--ink);font-size:13.5px;cursor:pointer;margin:1px 0;
/* 09-29 起导航项是 <a>（真链接才能中键/Ctrl 新开）—— 补两条 anchor 缺省样式：
   text-decoration 由 UA 给下划线；box-sizing 必须 border-box，
   否则 width:100% + 左右 padding 会撑出侧栏（button 的 UA 默认就是 border-box）。 */
text-decoration:none;box-sizing:border-box}
#side-nav .tab:hover{background:#e4e6e9}
#side-nav .tab.active{background:#dcdee3;font-weight:600}
/* 侧栏底部「导航开新标签页」开关（09-29） */
.side-opt{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--mut);
cursor:pointer;user-select:none;margin-bottom:2px}
.side-opt input{margin:0;cursor:pointer;accent-color:var(--blue)}
.side-opt:hover{color:var(--ink)}
.side-foot{padding:10px 14px;border-top:1px solid var(--line);font-size:13px}
.side-foot-btns{display:flex;gap:6px;margin-top:6px}
#content-wrap{flex:1;min-width:0}
#topbar{background:#1a1a1a;color:#fff;padding:9px 24px;display:flex;justify-content:space-between;
align-items:center;gap:16px;flex-wrap:wrap}
.topbar-title{font-size:13px;color:#c9ccd1}
#topbar .head-filters label{color:#c9ccd1}
#topbar .head-filters select{background:#303030;color:#fff;border-color:#555}
main{max-width:1920px;margin:0 auto;padding:20px 32px 60px;width:100%}
.page{display:none}.page.active{display:block}
h3{font-size:14.5px;font-weight:500;margin:20px 0 8px}
.hint{background:var(--blue-bg);border-left:3px solid var(--blue);padding:9px 14px;border-radius:6px;
color:#0c447c;font-size:13px;margin:8px 0 14px}
/* FB 通道告警横幅（09-28）：常驻在 main 顶部，正常时整条 hidden。
   红=连败/静默停摆（数据已经不可信），黄=少量连败（正在退避，可能自愈）。 */
.fb-alert{display:flex;gap:10px;align-items:center;flex-wrap:wrap;
border-radius:8px;padding:9px 14px;font-size:13px;margin:0 0 6px;line-height:1.5}
.fb-alert.bad{background:var(--red-bg);border-left:3px solid var(--red);color:var(--red)}
.fb-alert.warn{background:var(--amber-bg);border-left:3px solid var(--amber);color:var(--amber)}
.fb-alert .fb-a-ico{font-size:15px;line-height:1}
.fb-alert .fb-a-tx{flex:1;min-width:220px}
.fb-alert .fb-a-tx b{font-weight:600}
.fb-alert .fb-a-btns{display:flex;gap:8px;align-items:center;flex-shrink:0}
.fb-alert button.mini{background:transparent;border:1px solid currentColor;color:inherit;
border-radius:6px;padding:2px 9px;font-size:12px;cursor:pointer}
.fb-alert button.mini:hover{filter:brightness(.95)}
.fb-alert .fb-a-sub{font-size:12px;opacity:.85;display:block;margin-top:2px}
.fbh-row{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap;margin:3px 0}
.fbh-row .fbh-lv{font-weight:600}
.bar{display:flex;gap:10px;align-items:center;margin:10px 0;flex-wrap:wrap}
.card{background:#fff;border:1px solid var(--line);border-radius:10px;padding:14px 16px;margin:10px 0}
.card.inner{background:var(--bg);border-radius:8px;margin:8px 0}
.card h3{margin:2px 0 10px}
table{border-collapse:collapse;width:100%;font-size:13px;background:#fff}
th,td{border-bottom:1px solid var(--line);padding:7px 9px;text-align:left;vertical-align:top}
th{color:var(--mut);font-weight:400;white-space:nowrap;background:#fafbfc}
td code{background:var(--bg);padding:1px 5px;border-radius:4px;font-size:12px}
.tbl.tier{max-width:420px}
.tbl.tier td,.tbl.tier th{padding:4px 8px;font-size:12.5px}
.chip{display:inline-block;border-radius:20px;padding:0 9px;font-size:12px;white-space:nowrap}
.chip.paid_ok,.chip.active{background:var(--green-bg);color:var(--green)}
.chip.pending{background:var(--amber-bg);color:var(--amber)}
.chip.organic_only,.chip.draft,.chip.paused{background:#eceff3;color:var(--mut)}
.chip.expired,.chip.rejected{background:var(--red-bg);color:var(--red)}
.chip.licensed,.chip.localized,.chip.ready,.chip.testing,.chip.winner,.chip.live{background:var(--blue-bg);color:var(--blue)}
.chip.retired,.chip.killed{background:var(--red-bg);color:var(--red)}
.chip.atag{background:var(--purple-bg);color:var(--purple)}
.chip.ptag{background:var(--orange-bg);color:var(--orange)}
/* CT 弹窗里的三态（2026-09-28）：ok=通过/候选、warn=需要注意（含"等执行开关"）、
   kill=建议停。原本只写成 chip ok / chip pending，没定义就退化成没有底色的一串字，
   在斩杀弹窗里「建议停」和「候选」长得一样 —— 而这两个是相反的动作。 */
.chip.ok{background:var(--green-bg);color:var(--green)}
.chip.warn{background:var(--amber-bg);color:var(--amber)}
.chip.kill{background:var(--red-bg);color:var(--red)}
form{display:flex;flex-direction:column;gap:8px;margin:10px 0}
form input,form select,button,.bar input,.bar select{font:inherit;padding:7px 10px;border:1px solid var(--line);
border-radius:8px;background:#fff}
button{cursor:pointer}
button:hover{border-color:var(--blue);color:var(--blue)}
details summary{cursor:pointer;color:var(--blue);font-size:13px;margin-top:8px}
label{font-size:13px;display:flex;gap:6px;align-items:center}
.split{display:grid;grid-template-columns:1.6fr 1fr;gap:16px;align-items:start}
.hidden{display:none!important}
.kpis{display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin:12px 0}
.kpi{background:#fff;border:1px solid var(--line);border-radius:10px;padding:12px 14px}
.kpi .v{font-size:20px;font-weight:500}
.kpi .l{color:var(--mut);font-size:12px}
/* 销售曲线（09-25 晚 英杰，Shopify 风格双线图） */
.sc-wrap{position:relative}
.sc-tip{position:absolute;top:4px;display:none;pointer-events:none;background:#fff;
  border:1px solid var(--line);border-radius:8px;padding:6px 10px;font-size:12px;line-height:1.5;
  box-shadow:0 4px 14px rgba(0,0,0,.10);white-space:nowrap;z-index:5;transform:translateX(-50%)}
.toast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%);background:#222;color:#fff;
padding:9px 18px;border-radius:8px;font-size:13px;z-index:300}
.mini{font-size:12px;padding:2px 9px}
.mini.danger{color:var(--red)}
.ghost{border-color:transparent;background:none;color:var(--mut)}
.head-row{display:flex;justify-content:space-between;align-items:flex-end;gap:16px;flex-wrap:wrap}
.head-filters{display:flex;gap:14px;align-items:center;padding-bottom:12px;flex-wrap:wrap}
.head-filters label{font-size:13px;color:var(--mut);gap:6px}
.head-filters select{max-width:240px}
.inline-form{background:var(--bg);border:1px solid var(--line);border-radius:10px;padding:12px}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.fx-bar{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;margin-bottom:10px}
.langbox{display:flex;gap:8px;align-items:center;flex-wrap:wrap;
background:#fff;border:1px solid var(--line);border-radius:8px;padding:5px 10px}
.langbox.scroll{max-height:92px;overflow:auto;align-items:flex-start}
.langbox .inl{display:flex;gap:4px;align-items:center;font-size:13px}
.langbox .inl span{text-transform:uppercase}
.group-h{margin:26px 0 8px;font-size:15px;font-weight:500;border-left:4px solid var(--blue);padding-left:10px}
.camp{background:#fff;border:1px solid var(--line);border-radius:10px;margin:8px 0;overflow:hidden}
.camp summary{cursor:pointer;padding:11px 14px;display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.camp summary:hover{background:var(--bg)}
.camp-name{min-width:200px}
.camp-m{color:var(--mut);font-size:13px}
.camp table{margin:0;border-top:1px solid var(--line)}

/* ---------- 广告管理：一行筛选栏 + 紧凑多选下拉 ---------- */
.bar.nowrap{flex-wrap:nowrap;overflow-x:auto;padding:8px 10px;margin-left:-10px;margin-right:-10px;
  position:sticky;top:0;z-index:35;background:var(--bg);
  box-shadow:0 1px 0 var(--line);scrollbar-width:thin}
.pop{position:relative;flex:none}
.pop-btn{white-space:nowrap}
.pop-panel{display:none;position:fixed;z-index:60;background:#fff;max-height:70vh;overflow:auto;
  border:1px solid var(--line);border-radius:8px;box-shadow:0 8px 24px rgba(20,24,30,.14);
  padding:8px;min-width:220px;max-width:340px}
.pop.open .pop-panel{display:block}
.pop-tools{display:flex;gap:6px;margin-bottom:6px;align-items:center}
.pop-q{flex:1;min-width:0;padding:4px 8px;font-size:13px}
.pop-list{max-height:260px;overflow:auto;display:flex;flex-direction:column;gap:2px}
.pop-list label.inl{font-size:13px;white-space:nowrap}

/* ---------- 广告管理：树形表格 ---------- */
.camptbl{width:100%}
.camptbl td,.camptbl th{vertical-align:top}
.camptbl .lv0{min-width:260px}
.camptbl .lv1{padding-left:30px}
.camptbl .lv2{padding-left:58px}
.camptbl tr.camp-row{cursor:pointer}
.camptbl tr.camp-row:hover td{background:#f5f7fa}
.camptbl tr.adset-row td{background:#fafbfd}
.camptbl tr.is-paused td,.camptbl tr.is-paused td code{color:var(--mut)}
.camptbl tr.is-paused:hover td{background:#f5f7fa}
/* 需求 4（09-25）：展开中的系列行用协调的浅蓝底，跟广告组行(#fafbfd)/悬停(#f5f7fa)区分开；
   放在 is-paused:hover 之后，同特异性下后者规则胜出 —— 展开+暂停的行也吃浅蓝、不吃灰 */
.camptbl tr.camp-row.open-camp td{background:#e8f1fb}
.camptbl tr.camp-row.open-camp td code{color:inherit}
/* 需求 8（09-24 英杰）：只给系列行上色还不够 —— 展开后的广告组/广告行仍是白底，
   跟下一个未展开的系列混在一起。给展开系列名下的所有子行再铺一层更浅的蓝，
   整块区域一眼成组；比系列行(#e8f1fb)浅一档，层级仍然分明。 */
.camptbl tr.in-open td{background:#f0f6fc}
.camptbl tr.in-open:hover td{background:#e8f1fb}
/* 需求 4（09-24 英杰）：FB↗ 是操作入口不是外链装饰，用正文黑色，别抢视觉 */
.camptbl a.fb-post-link{color:var(--ink)}
.camptbl a.cr-roas{color:inherit}
/* ⚠️ 成熟度四色必须带 .camptbl a.cr-roas 前缀压过上面的 color:inherit ——
   09-24 英杰报「ROAS 不变色」根因：.mat-g 等单类选择器特异性(0,1,0)
   干不过 .camptbl a.cr-roas(0,2,1)，颜色全被 inherit 吃了。 */
.camptbl a.cr-roas.mat-g{color:#1a7f37}
.camptbl a.cr-roas.mat-p{color:#8250df}
.camptbl a.cr-roas.mat-b{color:#0969da}
.camptbl a.cr-roas.mat-k{color:#000}
/* 需求 7（09-24 英杰）：结构徽标三态统一都有色 —— ASC 绿 / CBO 黄 / ABO 蓝 */
.chip.abo{background:var(--blue-bg);color:var(--blue)}
/* 需求 3（09-24 英杰）：重复在投的素材 ×N 标签，用货号同款底色（橙） */
.chip.dupchip{background:var(--orange-bg);color:var(--orange);font-weight:600}
/* 需求 1（09-24 英杰）：素材成熟度四档（按累计花费）—— 绿/紫/蓝/黑 */
.mat-g{color:#1a7f37}.mat-p{color:#8250df}.mat-b{color:#0969da}.mat-k{color:#000}
a.cr-roas.mat-k{color:#000}
/* 需求 2（09-24 英杰）：概览环比 —— 数值下方小字灰显，广告规模除外 */
.ov-delta{color:var(--mut);font-size:11px;margin-top:1px}
/* 09-25 晚 英杰：销售曲线上方合计行 —— 销售额/订单/日均（今日实时同理），带环比 */
.ov-tot{display:flex;flex-wrap:wrap;gap:6px 28px;margin:2px 0 8px}
.ov-tot .ov-tot-item{display:flex;flex-direction:column;min-width:96px}
.ov-tot .ov-tot-item .l{color:var(--mut);font-size:11px}
.ov-tot .ov-tot-item b{font-size:17px;line-height:1.25}
.ov-tot .ov-delta{margin-top:0}
/* 今日实时合计行里「昨天整日」那格弱化（对照值，不是主角） */
.ov-tot .ov-tot-item.mut b{font-size:14px;color:var(--mut);font-weight:600}
.caret{display:inline-block;font-size:9px;color:var(--mut);margin-right:7px;transition:transform .12s}
.caret.open{transform:rotate(90deg)}
.grp-tools{margin-left:8px}
.grp-tools .mini{font-size:11px}
/* 日预算汇总行（09-24 英杰）：每组表格底部，日预算列下方对齐 */
.camptbl tfoot tr.bud-foot td{border-top:1px dashed var(--line,#ddd);background:transparent}
.camptbl td code{font-size:12px;word-break:break-all}
.up{color:var(--green);font-size:12px}
.down{color:var(--red);font-size:12px}
.good{color:var(--green)}
.bad{color:var(--red)}
.sug{background:var(--amber-bg);border-radius:8px;padding:7px 12px;margin:6px 0;font-size:13px;color:var(--amber)}
.small{color:var(--mut);font-size:12px}
tr.recent td{background:var(--blue-bg)}
.tbl tr.rowlink{cursor:pointer}
.tbl tr.rowlink:hover td{background:#f5f7fa}
.tbl tr.rowlink td:first-child b{color:var(--blue)}
.metric-row{display:flex;gap:14px;flex-wrap:wrap;font-size:12.5px;color:var(--mut);margin:3px 0}
.metric-row b{color:var(--ink)}
.sharebar{height:6px;background:#eceff3;border-radius:6px;overflow:hidden;margin:3px 0;max-width:130px}
.sharebar i{display:block;height:100%;background:var(--blue)}
.est{background:var(--amber-bg);color:var(--amber);font-size:11px;padding:0 5px;border-radius:4px}
.roas-link{cursor:pointer;border-bottom:1px dashed var(--line);padding-bottom:1px}
.roas-link:hover{background:var(--blue-bg)}
.roas-link:hover b{color:var(--blue)}
/* 可排序表格（货号看板） */
.tblwrap{overflow-x:auto}
.tbl th.sortable{cursor:pointer;user-select:none;white-space:nowrap}
/* 素材流水线的素材名/归集行链接：保持正文黑色（09-23 英杰「素材名不要蓝色」），
   可点性靠 hover 下划线提示 —— 蓝色留给真正的外链（FB 帖子等） */
.mt-name,.mt-gkey{color:var(--ink);text-decoration:none}
.mt-name:hover,.mt-gkey:hover{text-decoration:underline}
.tbl th.sortable:hover{color:var(--blue)}
.tbl th.sortable .sortmark{opacity:.4;font-size:10px;margin-left:2px}
.tbl th.sortable.on{color:var(--blue)}
.tbl th.sortable.on .sortmark{opacity:1}
.tbl td.num{text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}
.tbl th.num{text-align:right;white-space:nowrap}
/* 09-25 英杰需求 a：勾选列原来被 min-width:200px 撑出一大段空白 ——
   收紧成勾选框的自然宽度，把 200px 的最小宽度挪到真正的货号列上 */
.pbtbl td:first-child{width:26px}
.pbtbl td.pb-name{min-width:200px}
.pbtbl tr:hover td{background:#f7f9fc}
.tbl input{font-size:12px}
.modal{position:fixed;inset:0;background:rgba(20,24,30,.45);display:flex;align-items:center;
justify-content:center;z-index:100;padding:20px}
.modal-box{background:#fff;border-radius:12px;padding:18px 22px;max-width:900px;width:100%;
max-height:86vh;overflow:auto}
.modal-box h3{margin-top:14px}
/* 弹窗表单（Shopify 风格） */
.modal-form{display:flex;flex-direction:column;gap:8px;margin:0}
.form-sec{font-size:13px;font-weight:600;color:var(--mut);border-bottom:1px solid var(--line);
padding-bottom:4px;margin:14px 0 4px;display:flex;gap:8px;align-items:baseline}
.form-sec:first-child{margin-top:2px}
.form-sec .small{font-weight:400}
.field{display:flex;flex-direction:column;gap:3px;min-width:0}
.field label{font-size:12.5px;color:var(--ink);display:block;margin:0}
.field label i{font-style:normal;color:var(--mut);font-weight:400}
.modal-head{display:flex;justify-content:space-between;align-items:center;
border-bottom:1px solid var(--line);padding-bottom:10px;margin-bottom:12px}
.modal-head h3{margin:0;font-size:16px;font-weight:600;flex:1;min-width:0;
overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.modal-x{border:none;background:none;font-size:22px;color:var(--mut);cursor:pointer;
line-height:1;padding:0 4px}
.modal-x:hover{color:var(--ink)}
/* 编辑弹窗的「上一条 / 下一条」：贴右上，序号显示当前位置 */
.mn-nav{display:flex;align-items:center;gap:8px;margin-left:auto;margin-right:12px}
.mn-nav .mn-idx{color:var(--mut);white-space:nowrap}
.mn-nav button[disabled]{opacity:.4;cursor:not-allowed}
.mn-nav button[disabled]:hover{border-color:var(--line);color:inherit}
.modal-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:14px;
padding-top:12px;border-top:1px solid var(--line)}
button.primary{background:#1a1a1a;color:#fff;border-color:#1a1a1a}
button.primary:hover{background:#444;border-color:#444;color:#fff}
button.dangerbtn{background:#d72c0d;color:#fff;border-color:#d72c0d}
button.dangerbtn:hover{background:#b02c0d;border-color:#b02c0d;color:#fff}
.confirm-body{font-size:14px;color:var(--ink)}
.confirm-body b{color:var(--red)}
.confirm-body input{font:inherit;padding:7px 10px;border:1px solid var(--line);border-radius:8px;width:100%}
/* 概览页 */
#ov-kpis .kpi .v{font-size:22px;font-weight:600}
/* 顶栏 select 宽度 */
#topbar .head-filters select{max-width:220px}
/* 隐藏兼容：按钮带 hidden 类时不显示 */
button.hidden{display:none!important}
.prow{padding:4px 0;border-bottom:1px dashed var(--line)}
.tier-row{display:flex;gap:8px;align-items:center;margin:4px 0;flex-wrap:wrap}
.tier-row input{width:110px}
#asset-detail{position:sticky;top:12px}
#pg-out{max-height:56vh;overflow:auto}

/* ---------- 时间范围选择器（全局统一） ---------- */
.range{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.range select{padding:6px 9px;min-width:120px}
.range-hint{color:var(--mut);font-size:12px;white-space:nowrap}
.range-custom{display:none;gap:6px;align-items:center}
.range-custom.on{display:flex}
.range-custom input[type=date]{font:inherit;padding:6px 8px;border:1px solid var(--line);
border-radius:8px;background:#fff;color:var(--ink)}
.range-custom .tilde{color:var(--mut)}
/* 快捷时间范围（chip 形态，用于概览/货号看板这类高频切换） */
.rchips{display:flex;gap:4px;flex-wrap:wrap}
.rchips button{font-size:12px;padding:3px 10px;border-radius:20px;border:1px solid var(--line);
background:#fff;color:var(--mut)}
.rchips button.on{background:#1a1a1a;border-color:#1a1a1a;color:#fff}

/* ---------- 货号看板：单行紧凑行 ---------- */
.tbl.pbtbl td{padding:5px 9px}
.tbl.pbtbl th{padding:6px 9px}
/* 列头上方汇总行：加总列求和，ROAS/CPA 按整体口径重算 */
.pbtbl tr.pb-sum td{background:#eef4fb;border-bottom:2px solid var(--line);
  font-size:12.5px;padding:6px 9px}
.pbtbl tr.pb-sum td.pb-name{color:var(--mut)}
/* 配置页分类树的上下移按钮 */
.cat-node .ord{display:none;gap:2px}
.cat-node:hover .ord{display:inline-flex}
.cat-node .ord-btn{padding:0 5px;font-size:11px;line-height:16px;min-width:18px}
/* 09-25 英杰需求 b：货号列太宽把后面的列挤得换行 —— 品名列限宽，
   品名内部再截断（长英文品名不再把整行撑爆） */
.pb-name{white-space:nowrap;max-width:300px;overflow:hidden;text-overflow:ellipsis}
/* 需求 h：货号/品名链接保持黑字（继承行内颜色），hover 才出现下划线 */
.pb-link{color:inherit;text-decoration:none}
.pb-link:hover code,.pb-link:hover .pn{text-decoration:underline}
/* 需求 e：货号展开的广告树（与广告管理同源渲染，缩进一格背景区分） */
.pb-tree{padding:2px 0 6px}
.pb-tree .group-h{margin:10px 0 4px;font-size:13.5px}
.pb-tree .camptbl{background:#fff}
/* 09-25 晚 英杰：系列块之间拉开 —— 每个系列行上边加 2px 分隔线（隔开相邻系列），
   展开中的系列块整块染蓝、名字加重，一眼看出哪些行属于点开的那个系列 */
/* 09-26 凌晨 英杰：竖条全撤（太压抑）。分隔只靠「展开块底部一条浅蓝横线」——
   CSS 里画在下一条系列行（camp-row）的顶边，视觉上就是上一个展开块的最下边；
   块末恰好在表尾时用 last-child 兜底。头行/内行的浅蓝底色保留（只辅助分组）。 */
.pb-tree tr.camp-row>td{border-top:1px solid #a8c8e8}
.pb-tree tr.camp-row.open-camp td.lv0 code{font-weight:700}
.pb-tree tr.in-open>td{background:#f5f9fd}
.pb-tree tr.in-open:last-child>td,
.pb-tree tr.camp-row.open-camp:last-child>td{border-bottom:1px solid #a8c8e8}
.pbtbl tr.pb-tree-row>td{padding:0 12px 10px 34px;background:#fafbfd;
  border-bottom:1px solid var(--line)}
.pb-caret{cursor:pointer}
/* P4 广告写入：行内操作按钮（默认藏在状态格里，hover 行时浮现，避免表格变吵） */
.wbtns{display:inline-flex;gap:3px;margin-left:6px;vertical-align:middle}
tr .wbtn{opacity:0;transition:opacity .12s}
tr:hover .wbtn,.wbtn:focus{opacity:1}
.wbtn{font-size:11px;padding:1px 6px;min-width:0}
.wbtns .wbtn:first-child{margin-left:0}
/* 「不可写状态」说明（09-23）：父级已暂停 / FB 侧异常时**替代**「启用」按钮。
   为什么不是给按钮加个禁用态：对 effective_status 点启用根本写不进去（对象自己
   本来就是 ACTIVE），给了入口就是骗人 —— 那天英杰点了，FB 回「已经启用」。 */
.wnote{cursor:help;font-size:11px;font-weight:600;border-radius:9px;padding:1px 7px;
background:var(--amber-bg);color:var(--amber);white-space:nowrap}
/* 「并入」标签（英杰 09-23 需求）：合并出来的副本和原件**同名**（只差 -合并 后缀），
   列表里分不清 —— 这个标签就是给它们的身份证，点了看溯源与源对象的历史数据。 */
.chip.merged-chip{cursor:pointer;background:var(--blue-bg);color:var(--blue);font-weight:600}
.chip.merged-chip:hover{filter:brightness(.96)}
/* 09-25 需求 g：分类独立成列后，品名截断不再吃掉标签 */
.pb-name .pn{color:var(--mut);margin-left:7px;font-size:12.5px;
  display:inline-block;max-width:170px;overflow:hidden;text-overflow:ellipsis;
  vertical-align:bottom;white-space:nowrap}
.pb-name .pb-tag{font-size:11px;color:var(--mut);border:1px solid var(--line);
border-radius:10px;padding:0 6px;margin-left:6px}
.pbtbl td.num{white-space:nowrap}
.pbtbl .sub7{color:var(--mut);font-size:11.5px}

/* ---------- 配置页：默认设置卡 ---------- */
.def-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:10px}
.def-grid .field{max-width:280px}

/* ---------- 品类级联筛选（货号看板） ---------- */
.cascade{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.cascade select{min-width:118px;max-width:190px}
.cascade .cas-x{font-size:12px;padding:4px 8px}

/* ---------- 分类树管理（配置页） ---------- */
.cat-wrap{display:grid;grid-template-columns:minmax(300px,360px) 1fr;gap:14px;align-items:start}
@media (max-width:1200px){.cat-wrap{grid-template-columns:1fr}}
.cat-tree{border:1px solid var(--line);border-radius:8px;background:#fff;padding:8px;
max-height:62vh;overflow:auto}
.cat-node{display:flex;align-items:center;gap:6px;padding:3px 6px;border-radius:6px;
cursor:pointer;font-size:13px;white-space:nowrap}
.cat-node:hover{background:#f1f2f4}
.cat-node.on{background:var(--blue-bg);color:#0c447c;font-weight:600}
.cat-node .tg{width:13px;flex-shrink:0;color:var(--mut);font-size:10px;text-align:center}
.cat-node .nm{overflow:hidden;text-overflow:ellipsis}
.cat-node .cnt{margin-left:auto;color:var(--mut);font-size:11.5px;font-variant-numeric:tabular-nums}
.cat-node.on .cnt{color:#0c447c}
.cat-node .src{font-size:10px;color:var(--mut);border:1px solid var(--line);border-radius:8px;
padding:0 5px;flex-shrink:0}
.cat-node .src.manual{color:var(--purple);border-color:var(--purple)}
.cat-side{border:1px solid var(--line);border-radius:8px;background:#fff;padding:10px 12px}
.cat-hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.cat-acts{margin-left:auto;display:flex;gap:6px}
.cat-add{margin-bottom:8px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.cat-hit{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);border-radius:14px;
padding:1px 9px;margin:2px 4px 2px 0;font-size:12px;cursor:pointer;background:#fff}
.cat-hit:hover{border-color:var(--blue);color:var(--blue)}
.cat-prod{display:flex;align-items:center;gap:8px;padding:4px 4px;border-bottom:1px solid var(--line);
font-size:12.5px}
.cat-prod:last-child{border-bottom:none}
.cat-prod .pn2{color:var(--mut);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:420px}
.cat-prod .cat-x{margin-left:auto}
.cat-empty{color:var(--mut);font-size:12.5px;padding:10px 2px}
.cat-prods{max-height:46vh;overflow:auto}


/* ---------- 权限矩阵（用户/角色） ---------- */
.perm-title{font-weight:600;font-size:15px;margin-bottom:10px}
.perm-note{background:#f5f8ff;border-left:3px solid var(--blue);padding:8px 12px;border-radius:0 6px 6px 0;
 font-size:12.5px;margin-bottom:14px;line-height:1.6}
.perm-block{margin-bottom:16px}
.perm-block-t{font-weight:600;font-size:13px;margin-bottom:8px;padding-left:2px;color:#333}
.perm-group{margin-bottom:10px}
.perm-group-t{font-size:12px;color:var(--mut);margin-bottom:4px;padding-left:2px}
.perm-row{display:flex;align-items:center;gap:10px;padding:3px 0;border-bottom:1px dashed var(--line)}
.perm-row:last-child{border-bottom:none}
.perm-name{flex:1;font-size:13px}
.perm-sel{min-width:96px}
.scope-row{display:flex;gap:16px;flex-wrap:wrap;font-size:13px;margin-bottom:8px}
.scope-row label{display:inline-flex;align-items:center;gap:5px;cursor:pointer}
.scope-sites{display:flex;flex-wrap:wrap;gap:8px;max-height:180px;overflow:auto;padding:6px 2px}
.scope-site{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;border:1px solid var(--line);
 border-radius:14px;padding:2px 10px;cursor:pointer;background:#fff}
.scope-site:hover{border-color:var(--blue)}
.mini-sel{font-size:12px;padding:2px 4px;border:1px solid var(--line);border-radius:6px;background:#fff;max-width:140px}

/* ---------- P7-1 结构体检（Campaigns 页） ---------- */
.audit-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.audit-scale{color:var(--mut);margin:6px 0 2px;line-height:1.7}
.audit-check{border-top:1px solid var(--line);padding:6px 0}
.audit-check:first-of-type{border-top:none}
.audit-check>summary{cursor:pointer;display:flex;align-items:center;gap:8px;flex-wrap:wrap;
font-size:13px;padding:3px 0;list-style:none}
.audit-check>summary::-webkit-details-marker{display:none}
.audit-check>summary::before{content:"\25B8";color:var(--mut);font-size:11px;flex-shrink:0;
transition:transform .12s}
.audit-check[open]>summary::before{transform:rotate(90deg)}
.audit-check>summary:hover{color:var(--blue)}
.audit-check .tbl{margin-top:6px}
.audit-check .tbl td{vertical-align:top}

/* ===== P6 建计划编排（快速投放页）===== */
.warn{color:var(--amber)}
.orch-block{background:var(--red-bg);border-radius:6px;padding:8px 10px;margin:8px 0;font-size:13px}
.orch-block ul{margin:4px 0 0 18px;padding:0}
.orch-block li{margin:2px 0}
.orch-sec{border-top:1px solid var(--line);padding:7px 0;margin-top:6px}
.orch-sec:first-of-type{border-top:none}
.orch-sec>summary{cursor:pointer;font-size:13px;font-weight:600;list-style:none;padding:2px 0;
display:flex;align-items:center;gap:6px}
.orch-sec>summary::-webkit-details-marker{display:none}
.orch-sec>summary::before{content:"\25B8";color:var(--mut);font-size:11px;transition:transform .12s}
.orch-sec[open]>summary::before{transform:rotate(90deg)}
.orch-sec>summary:hover{color:var(--blue)}
.orch-json{background:#f7f8fa;border:1px solid var(--line);border-radius:6px;padding:10px;
max-height:420px;overflow:auto;font-size:12px;line-height:1.5;white-space:pre;margin-top:6px}

/* ---------- 规则引擎：决策台账（P5 可视化） ----------
   存在的理由：英杰说"我看不到他们是在…我没有一个整体的概念"。所以这一块的核心
   不是把动作清单排得更好看，而是回答三个问题：该不该管（基调卡的量表）、
   走到哪一步（漏斗）、为什么（逐条 why + 跟哪条线比）。
   颜色沿用站内既有约定：预算加=红(bad)、降=绿(good)（国内涨红跌绿的习惯）。 */
.vl-chip{display:inline-block;border-radius:20px;padding:0 9px;font-size:12px;
white-space:nowrap;background:#eceff3;color:var(--mut)}
.vl-chip.up{background:var(--green-bg);color:var(--green)}
.vl-chip.down,.vl-chip.stop{background:var(--red-bg);color:var(--red)}
.vl-chip.blocked{background:var(--amber-bg);color:var(--amber)}
.vl-chip.queued{background:var(--blue-bg);color:var(--blue)}
.vl-chip.hold{background:#eceff3;color:var(--mut)}
.vl-chip.out{background:#f2f3f5;color:#9aa1ab}

/* 基调卡：广告占比落在目标区间哪一侧，一眼看出来 */
.tone-card{background:var(--bg);border:1px solid var(--line);border-radius:10px;
padding:12px 14px;margin:8px 0}
.tone-head{display:flex;gap:14px;align-items:center;flex-wrap:wrap;font-size:13.5px;font-weight:500}
.tone-head b{color:var(--ink)}
.gauge{position:relative;height:22px;margin:12px 0 2px;background:#f7f8fa;
border:1px solid var(--line);border-radius:6px}
.gauge .band{position:absolute;top:0;bottom:0;background:var(--green-bg);
border-left:1px dashed #9dc9b6;border-right:1px dashed #9dc9b6}
.gauge .pin{position:absolute;top:-3px;width:2px;height:26px;background:var(--ink)}
.gauge .pin::after{content:"";position:absolute;top:-5px;left:-4px;width:10px;height:10px;
border-radius:50%;background:var(--ink)}
.gauge-lbl{display:flex;justify-content:space-between;font-size:11px;color:var(--mut)}

/* 漏斗：四层逐级收窄，外加"没上来的那几堆人" */
.fstep{display:flex;gap:10px;align-items:center;margin:6px 0;font-size:12.5px}
.fstep .fl{min-width:96px;color:var(--mut)}
.fstep .fbar{flex:1;height:14px;background:#eceff3;border-radius:4px;overflow:hidden;min-width:70px}
.fstep .fbar i{display:block;height:100%;border-radius:4px;background:var(--blue)}
.fstep .fn{min-width:56px;text-align:right;font-weight:600;font-variant-numeric:tabular-nums}
.fstep .fnote{flex:1.4;min-width:0;font-size:12px;color:var(--mut)}
.fdrop{background:var(--amber-bg);border-radius:8px;padding:7px 11px;margin:5px 0;
font-size:12.5px;color:var(--amber)}
.fdrop.info{background:var(--blue-bg);color:#0c447c}
.lg-tools{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin:10px 0 6px}
.lg-tools .vl-chip{cursor:pointer;border:1px solid transparent}
.lg-tools .vl-chip.on{border-color:var(--ink);font-weight:600}
.lg-tools input{padding:4px 8px;font-size:12.5px;min-width:150px}
.lgtbl td,.lgtbl th{font-size:12.5px}
.lgtbl td.obj{min-width:200px;max-width:320px;word-break:break-all}
/* 勾选列（素材列表 → 合并向导；预览页的来源广告）。窄、居中，不抢戏。 */
.lgtbl th.pick,.lgtbl td.pick{width:26px;text-align:center;padding-left:4px;padding-right:4px}
.lgtbl td.pick input{cursor:pointer;margin:0}
.lgtbl tr.is-act td{background:#f6fbf8}
.modal-box.wide{max-width:1440px}
/* ---------- 素材流水线（A1） ---------- */
/* 阶段筛选：药丸按钮，选中态用深色描边 + 加粗，和「货号看板」的品类级联保持一致的观感 */
.mchip{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);background:#fff;
color:var(--ink);border-radius:20px;padding:3px 11px;font-size:12.5px;cursor:pointer;
white-space:nowrap;line-height:1.5}
.mchip:hover{background:#f1f2f4}
.mchip b{font-variant-numeric:tabular-nums;color:var(--mut);font-weight:600}
.mchip.on{border-color:var(--ink);background:#eef0f2;font-weight:600}
.mchip.on b{color:var(--ink)}
/* 判定：合格 / 不合格 / 待判。三个状态必须一眼分开 —— 这是整页的结论 */
.gchip{display:inline-block;border-radius:20px;padding:1px 9px;font-size:12px;white-space:nowrap;font-weight:600}
.gchip.ok{background:var(--green-bg);color:var(--green)}
.gchip.bad{background:var(--red-bg);color:var(--red)}
.gchip.mute{background:#eceff3;color:var(--mut);font-weight:400}
#mt-baseline-note{margin-left:8px}
#mt-curve{background:#fff;overflow-x:auto}
#mt-curve svg{display:block;min-width:520px}

/* ---------- 素材筛选（四道闸门） ----------
   参数编辑器一条一条列，每条左边名称、中间输入、下面说明 —— 一屏能扫完 20 多项，
   比塞进表格里再横向滚动好用得多。说明文字常驻（不靠 tooltip），因为这个页面
   的核心价值就是"让人看懂每个参数在干什么"。 */
.scfunnel{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:12px}
.scr{display:flex;align-items:center;gap:6px;border:1px solid var(--line);
  border-radius:10px;padding:6px 12px;background:#fff}
.scgrp{border:1px solid var(--line);border-radius:10px;margin-bottom:12px;overflow:hidden;background:#fff}
.scgrp-h{background:#f6f7f8;border-bottom:1px solid var(--line);padding:7px 12px;
  font-weight:600;font-size:13px}
.scgrp-b{padding:4px 12px 10px}
.scitem{display:grid;grid-template-columns:240px 130px 1fr;gap:10px;align-items:center;
  padding:7px 0;border-bottom:1px dashed #f0f1f2}
.scitem:last-child{border-bottom:none}
.scitem-l{font-size:13px}
.scitem-i input[type=number],.scitem-i input[type=text],.scitem-i input:not([type]){max-width:100%}
.scitem-h{color:var(--mut);line-height:1.5}
@media(max-width:1100px){.scitem{grid-template-columns:1fr;gap:3px}}

/* ---------- 花费总览（站点 × 月矩阵 + 逐日明细） ----------
   矩阵是「宽而矮」的表（10 站 × 12 月），必须能横向滚；格子是入口（点开看逐日），
   所以要给出可点的视觉反馈。日明细里的分布条用「Meta 蓝 / Google 绿」，
   和站点表里的占比标色呼应。 */
.tbl-wrap{overflow-x:auto}
.tbl.sp-tbl th,.tbl.sp-tbl td{padding:5px 8px;font-size:12.5px;text-align:right;white-space:nowrap}
.tbl.sp-tbl th:first-child,.tbl.sp-tbl td:first-child{text-align:left}
.tbl.sp-tbl td.sp-cell{cursor:pointer;font-variant-numeric:tabular-nums}
.tbl.sp-tbl td.sp-cell:hover{background:var(--blue-bg)}
.tbl tr.tot td{background:#fafbfc;font-weight:600;border-top:2px solid var(--line)}
.tbl.sp-day td.num{font-variant-numeric:tabular-nums;text-align:right}
.sp-bar{display:inline-flex;height:9px;width:120px;border-radius:3px;overflow:hidden;
  background:#f0f1f3;vertical-align:middle}
.sp-bar i{display:block;height:100%}
.sp-bar i.m{background:var(--blue)}
.sp-bar i.g{background:var(--green)}
.sp-bar i.o{background:#c9ccd1}
/* 「未收敛」标注（09-23 定论）：Meta 同步每站每 ~24h 一次，排期时刻落在各站**当地日
   的中途**，所以已结束的那一天要等下一个周期才回填 —— 最近 1~2 天在库里必然是残值。
   这些样式只负责把话说明白，不改任何金额口径。 */
.tbl.sp-day tr.unsettled td{background:var(--amber-bg)}
.sp-chip{display:inline-block;margin-left:5px;padding:0 5px;border-radius:8px;
  background:var(--amber-bg);color:var(--amber);font-size:11px;font-weight:600}
.sp-dot{color:var(--amber);cursor:help}

/* 素材流水线汇总行（09-23 三批需求 3）：悬在列名上方，当前筛选整体的花费/ROAS */
.mt-tot th{background:#f6f7f9;border-bottom:2px solid var(--line);white-space:nowrap}

/* ============================================================
   视觉升级层（09-24，Airwallex 设计语言移植）
   只动 CSS，不碰任何 HTML/JS —— web_check 断言的 DOM 与类名原样
   保留；颜色语义（涨红跌绿、状态 chip）也不动。它的设计语言 =
   大量留白 + 极轻的边框 + 分层阴影 + 克制的微交互，全部可纯 CSS
   表达；它的"快"来自构建链/CDN，与本站无关，不移植。
   规则统一追加在本段，利用层叠顺序覆盖上面的旧观感，方便回退。 */
:root{
  --r-sm:8px;--r-md:12px;--r-lg:16px;
  --sh-1:0 1px 2px rgba(23,30,38,.04),0 2px 6px rgba(23,30,38,.05);
  --sh-2:0 4px 10px rgba(23,30,38,.06),0 12px 28px rgba(23,30,38,.08);
  --sh-3:0 24px 64px rgba(23,30,38,.18);
  --ease:cubic-bezier(.25,.6,.3,1);
  --line-soft:#edf0f3;
}
body{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
::selection{background:var(--blue-bg)}
h3{font-weight:600;letter-spacing:-.01em}
/* 焦点环：键盘可达性 + Airwallex 式聚焦反馈（按钮只认键盘焦点，
   避免鼠标点完留一圈） */
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--blue);
  box-shadow:0 0 0 3px rgba(24,95,165,.12)}
button:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
/* 输入与按钮：过渡 + hover 面（替代旧的"hover 变蓝字"，更收敛） */
form input,form select,button,.bar input,.bar select,.range-custom input[type=date],
.pop-q,.confirm-body input{
  transition:border-color .15s var(--ease),box-shadow .15s var(--ease),
  background .15s var(--ease),color .15s var(--ease),transform .12s var(--ease)}
input:hover,select:hover{border-color:#c6cfd8}
button:hover{border-color:#c6cfd8;background:#f6f8fa;color:var(--ink)}
button.primary:hover{transform:translateY(-1px);box-shadow:0 6px 16px rgba(23,30,38,.18)}
button.primary:active{transform:translateY(0);box-shadow:none}
button.dangerbtn:hover{transform:translateY(-1px);box-shadow:0 6px 16px rgba(215,44,13,.24)}
button.dangerbtn:active{transform:translateY(0);box-shadow:none}
/* 侧边栏：白底 + 柔和选中态（左侧细蓝条 = 当前位置） */
#sidebar{background:#fff}
#side-nav .tab{transition:background .15s var(--ease),color .15s var(--ease)}
#side-nav .tab:hover{background:#f1f4f7}
#side-nav .tab.active{background:#e8eef6;color:#0c447c;
  box-shadow:inset 3px 0 0 var(--blue)}
/* 顶栏：深色翻白（Airwallex 是浅色导航）。旧的深色 select 覆盖
   在这里同特异性压回浅色 */
#topbar{background:#fff;color:var(--ink);border-bottom:1px solid var(--line-soft);
  box-shadow:0 1px 0 rgba(23,30,38,.02)}
.topbar-title{color:var(--mut)}
#topbar .head-filters label{color:var(--mut)}
#topbar .head-filters select{background:#fff;color:var(--ink);border-color:var(--line)}
/* 卡片：轻边框 + 一层薄阴影；KPI 悬浮时轻抬（可点卡片才动，
   大区块 .card 保持静止，避免整页"呼吸"） */
.card{border-color:var(--line-soft);box-shadow:var(--sh-1)}
.kpi{border-color:var(--line-soft);box-shadow:var(--sh-1);
  transition:box-shadow .2s var(--ease),transform .2s var(--ease)}
.kpi:hover{box-shadow:var(--sh-2);transform:translateY(-2px)}
.kpi .v{font-weight:600;letter-spacing:-.01em}
.login-card{border-radius:var(--r-lg);border-color:var(--line-soft);box-shadow:var(--sh-2)}
.camp{border-color:var(--line-soft);transition:box-shadow .2s var(--ease)}
.camp:hover{box-shadow:var(--sh-1)}
/* 表格：表头字重提一档 + 行悬浮过渡（数据密度不变，质感变） */
th{font-weight:500;letter-spacing:.02em}
tbody tr{transition:background .12s var(--ease)}
/* 弹层：背景磨砂 + 深阴影（同一时刻最多一个弹窗，性能无虞） */
.modal{background:rgba(15,23,32,.48);backdrop-filter:blur(3px)}
.modal-box{border-radius:var(--r-lg);box-shadow:var(--sh-3)}
.pop-panel{box-shadow:var(--sh-2)}
.toast{box-shadow:var(--sh-2)}
/* 细滚动条（数据页横向滚动的观感提升明显） */
*{scrollbar-width:thin;scrollbar-color:#ccd3db transparent}
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-thumb{background:#ccd3db;border-radius:8px}
::-webkit-scrollbar-thumb:hover{background:#b4bdc7}
::-webkit-scrollbar-track{background:transparent}
/* 系统级"减少动态效果"时全部静止 */
@media (prefers-reduced-motion:reduce){
  *{transition:none!important;animation:none!important}
}



/* ================= 09-24 批次 ================= */

/* ---- 时间范围弹层（概览 + 花费逐日，学 Shopify 的单控件单窗口） ---- */
.rng-wrap{position:relative;display:inline-block}
.rng-btn{display:inline-flex;align-items:center;gap:8px;padding:7px 14px;border:1px solid var(--line);
  border-radius:8px;background:#fff;cursor:pointer;font-size:13px;line-height:1.4}
.rng-btn:hover{border-color:var(--blue);box-shadow:0 1px 4px rgba(9,105,218,.12)}
.rng-ico{font-size:14px;opacity:.75}
.rng-chev{font-size:10px;color:var(--mut);transition:transform .15s}
.rng-btn[aria-expanded="true"] .rng-chev,.rng-wrap:has(.rng-pop:not([hidden])) .rng-chev{transform:rotate(180deg)}
.rng-pop{position:absolute;top:calc(100% + 6px);left:0;z-index:60;width:300px;max-width:calc(100vw - 24px);
  background:#fff;border:1px solid var(--line);border-radius:10px;box-shadow:0 8px 28px rgba(16,24,40,.14);
  padding:12px 14px;cursor:default}
.rng-sec + .rng-sec{border-top:1px solid var(--line);margin-top:10px;padding-top:10px}
.rng-t{font-size:11px;color:var(--mut);margin-bottom:6px;letter-spacing:.05em}
.rng-chips{display:flex;flex-wrap:wrap;gap:6px}
.rng-chips button{padding:5px 11px;border:1px solid var(--line);border-radius:16px;background:#fff;
  cursor:pointer;font-size:12px}
.rng-chips button:hover{border-color:var(--blue);color:var(--blue)}
.rng-chips button.on{background:var(--blue-bg);border-color:var(--blue);color:var(--blue);font-weight:600}
.rng-pop input[type="month"],.rng-pop input[type="date"]{padding:5px 8px;border:1px solid var(--line);
  border-radius:6px;font-size:12px}
.rng-custom{display:flex;align-items:center;gap:6px;flex-wrap:wrap}

/* ---- 概览切换加载反馈（需求2）：半透明 + 顶部呼吸条，看得出在动 ---- */
.ov-loading{position:relative;opacity:.45;pointer-events:none;min-height:60px;transition:opacity .15s}
.ov-loading::before{content:"";position:absolute;top:-6px;left:0;right:0;height:3px;border-radius:3px;
  background:linear-gradient(90deg,transparent,var(--blue),transparent);
  background-size:40% 100%;background-repeat:no-repeat;animation:ovbar 1s linear infinite}
@keyframes ovbar{0%{background-position:-40% 0}100%{background-position:140% 0}}

/* ---- 花费总览「全部」视角 + 逐日汇总行 ---- */
.sp-all{display:flex;flex-direction:column;line-height:1.35}
.sp-all .small{white-space:nowrap}
.sp-all span{white-space:nowrap;text-align:left}
.sp-all .pct{font-style:normal;color:var(--muted,#6b7280);font-size:11px;margin-left:2px}
.sp-all .sp-rev{color:var(--muted,#6b7280);font-size:11px;
  border-bottom:1px dashed var(--line,#e5e7eb);margin-bottom:1px}
tr.sp-head-sum td{background:var(--blue-bg,#eef4fd);border-bottom:1px solid var(--line);
  font-size:12px;padding:5px 8px}
/* 标准时间选择器的两组快捷之间的分隔竖线（09-25 全站统一） */
.rng-sep{display:inline-block;width:1px;align-self:stretch;min-height:22px;
  background:var(--line,#e5e7eb);margin:2px 6px}

/* ---- 操作日志 ---- */
#oplog-card .bar{gap:10px;flex-wrap:wrap}
#oplog-card label{display:inline-flex;align-items:center;gap:4px}
#oplog-card input,#oplog-card select{padding:4px 6px;border:1px solid var(--line);border-radius:6px;font-size:12px}

/* ================= 手机端适配（09-24 需求8：概览 / 花费总览 / 配置优先） =================
   策略：侧栏收成顶部横向滚动条；表格统一横向滚动；KPI 双列；触控目标 ≥ 36px；
   弹层全宽贴边。只动「能安全动」的部分，不动任何 id/结构。 */
/* ---------- 货号组多选下拉（09-25 需求7） ---------- */
.pgmulti{position:relative;display:inline-block}
.pgm-btn{min-height:30px;padding:4px 10px;border:1px solid var(--line);border-radius:6px;
  background:#fff;cursor:pointer;font-size:12.5px;color:var(--ink)}
.pgm-btn:disabled{color:var(--mut);cursor:not-allowed}
.pgm-pop{position:absolute;z-index:70;top:calc(100% + 4px);left:0;min-width:240px;max-height:280px;
  overflow:auto;background:#fff;border:1px solid var(--line);border-radius:8px;
  box-shadow:0 8px 24px rgba(20,24,30,.14);padding:6px}
.pgm-it{display:flex;align-items:center;gap:6px;padding:5px 6px;border-radius:6px;
  font-size:12.5px;cursor:pointer;white-space:nowrap}
.pgm-it:hover{background:var(--bg)}
.pgm-it input{width:auto;margin:0}
/* ==================== 手机端（09-25 深夜整体重做：移动优先） ====================
   ⚠️ 骨架 bug（09-25 凌晨截图实锤）：#app-shell 是 flex 横排，#m-topbar 塞在
   里面当 flex 子项 → 没占满整行，变成左侧一条竖着的黑柱，顶栏/内容全被挤右。
   手机端改块级布局：顶栏全宽 sticky、侧栏固定抽屉、内容独占全宽。 */
@media (max-width:768px){
  html{font-size:14px}
  body{overflow-x:hidden;-webkit-text-size-adjust:100%}
  body.m-nav-open{overflow:hidden}                       /* 抽屉开着时锁背景滚动 */
  #app-shell{display:block}

  /* —— 顶部导航栏：全宽深色，标题居中，安全区适配 —— */
  #m-topbar{position:sticky;top:0;width:100%;z-index:65;background:#1a1a1a;color:#fff;
    display:flex;align-items:center;gap:8px;min-height:48px;
    padding:calc(6px + env(safe-area-inset-top)) 10px 6px}
  #m-topbar .m-title{flex:1;text-align:center;font-size:15px;font-weight:600;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  #m-topbar::after{content:"";width:44px}                /* 配平左侧按钮，让标题真居中 */
  #m-nav-btn{background:none;border:none;color:#fff;font-size:22px;line-height:1;
    padding:10px;cursor:pointer;min-width:44px;min-height:44px;display:flex;align-items:center;justify-content:center}

  /* —— 侧栏 → 抽屉：大触摸目标、dvh + 底部安全区 —— */
  aside#sidebar{position:fixed;left:0;top:0;bottom:0;width:82%;max-width:320px;
    height:100vh;height:100dvh;z-index:80;transform:translateX(-104%);
    transition:transform .24s cubic-bezier(.2,.7,.3,1);overflow-y:auto;
    flex-direction:column;flex-shrink:0;box-shadow:8px 0 32px rgba(0,0,0,.28);
    padding-bottom:env(safe-area-inset-bottom)}
  body.m-nav-open aside#sidebar{transform:none}
  #m-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:75;
    opacity:0;transition:opacity .2s ease;pointer-events:none}
  body.m-nav-open #m-backdrop{opacity:1;pointer-events:auto}
  aside#sidebar .tab{min-height:46px;font-size:14.5px;padding:11px 14px}
  aside#sidebar .side-foot{flex-direction:row;align-items:center;gap:8px;flex-wrap:wrap;
    padding-bottom:calc(8px + env(safe-area-inset-bottom))}
  /* 窄屏抽屉里三个东西（开关 + whoami + 两个按钮）一字排开会溢出 ⇒ 开关独占一行 */
  aside#sidebar .side-opt{flex:1 0 100%;min-height:32px;margin-bottom:0;font-size:13px}
  aside#sidebar .side-foot-btns{display:flex;gap:8px}
  aside#sidebar .side-foot-btns .mini{min-height:40px}
  #content-wrap{width:100%}

  /* —— PC 头部：手机上收缩成一行紧凑筛选（长标题隐藏，导航栏已有标题）
     右缘渐隐 = 提示「这一行可以横滑」—— 否则「账号」被切一半没头没脑 —— */
  #topbar{flex-wrap:nowrap;gap:8px;padding:8px 10px;overflow-x:auto;-webkit-overflow-scrolling:touch;
    -webkit-mask-image:linear-gradient(90deg,#000 88%,transparent);
    mask-image:linear-gradient(90deg,#000 88%,transparent)}
  #topbar .topbar-title{display:none}
  #topbar .head-filters{flex-wrap:nowrap;gap:6px;margin-left:auto}
  #topbar .head-filters label{display:flex;align-items:center;gap:4px;white-space:nowrap;font-size:12px}
  #topbar .head-filters select{max-width:130px}

  /* —— 主区与卡片 —— */
  main{padding:10px 10px calc(48px + env(safe-area-inset-bottom))}
  .card{padding:12px;border-radius:12px}
  .card h3{font-size:15px;line-height:1.5}

  /* —— KPI：两列大数字，说明小字紧凑，环比高亮保留 —— */
  .kpis{grid-template-columns:repeat(2,1fr);gap:8px;margin:10px 0}
  .kpi{padding:11px 12px;border-radius:12px}
  .kpi .v{font-size:17px;letter-spacing:-.01em}
  .kpi .l{font-size:10.5px;line-height:1.5}
  .kpi .ov-delta{font-size:10.5px;margin-top:3px}
  /* 卡数为奇数时末卡跨两列，不落单 */
  .kpis .kpi:last-child:nth-child(odd){grid-column:1/-1}

  /* —— 表格横向滚动（数据表在窄屏横滚比挤压列更可读） —— */
  .tbl-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .tbl{min-width:560px}
  .sp-tbl{min-width:640px}
  .sp-day{min-width:720px}

  /* —— 控件：触摸目标 ≥40px；表单 16px 防 iOS 聚焦自动放大 —— */
  .bar{flex-wrap:wrap;gap:8px}
  button,.mini,.rng-btn{min-height:40px}
  .mini{padding:7px 12px;font-size:12.5px}
  select,input[type="date"],input[type="month"],input[type="text"],input[type="number"]{
    min-height:40px;font-size:16px}
  .rng-chips button{min-height:42px;padding:8px 14px}

  /* —— 时间弹层贴满宽；概览时间条改一行（按钮 + 说明并排） —— */
  .rng-pop{position:fixed;left:8px;right:8px;top:auto;width:auto;max-width:none;z-index:80}
  #ov-range-bar{flex-direction:row;align-items:center;justify-content:space-between;
    gap:8px;flex-wrap:wrap}

  /* —— 弹窗贴边；split 竖排 —— */
  .modal-form{max-width:calc(100vw - 20px)!important;margin:10px!important}
  .split{display:block}
  .split > .card{margin-bottom:10px}
  /* 登录卡固定 370px 在小屏会溢出 */
  .login-card{width:calc(100vw - 32px);max-width:370px;padding:24px 20px}
}
@media (max-width:380px){
  .kpis{grid-template-columns:1fr}
  .rng-chips button{padding:6px 10px}
}
/* ⚠️ 09-25 修复：下面两条曾因花括号错位漏到媒体查询外变成全局规则，
   把 PC 端左侧导航拍成横向。抽屉方案下移动端导航保持竖排，此块已删除。 */
/* PC 端隐藏手机专用元素 */
@media (min-width:769px){
  #m-topbar,#m-backdrop{display:none}
}

/* ---------- 广告模板：5 标签页表单 + 载荷预览（2026-09-29） ----------
   重排的用意是"一目了然"：按**投放对象**分页（基本/系列/广告组/受众/交付与排期），
   而不是按"有哪些字段"分页。不可改的字段一律**显示但禁用**并写明原因 ——
   找不到的框比改不了的框更糟。 */
.tp-tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--line);margin:0 0 14px}
.tp-tab{border:1px solid transparent;border-bottom:none;background:none;padding:6px 12px;
  font-size:13px;color:var(--mut);cursor:pointer;border-radius:7px 7px 0 0}
.tp-tab:hover{background:#eef0f3;color:var(--ink)}
.tp-tab.on{background:#fff;border-color:var(--line);color:var(--blue);font-weight:600;
  margin-bottom:-1px;padding-bottom:7px}
.tp-pane{padding:2px 2px 0}
.tp-pane.hidden{display:none}
.tp-h{font-size:13px;font-weight:600;color:var(--mut);margin:14px 0 8px;
  border-top:1px dashed var(--line);padding-top:12px}
.tp-pane>.tp-h:first-child{border-top:none;padding-top:0;margin-top:0}
.tp-tip{background:var(--blue-bg);color:#0c447c;border-left:3px solid var(--blue);
  border-radius:6px;padding:8px 12px;font-size:12.5px;line-height:1.6;margin:12px 0 4px}
.fld{display:flex;flex-direction:column;gap:3px;margin-bottom:10px;min-width:0}
.fld>span:first-child{font-size:12.5px;color:var(--mut);display:flex;align-items:center;gap:6px}
.fld em{font-style:normal;font-size:11px;color:#9aa3ae;background:#f0f1f3;
  border-radius:4px;padding:0 5px}
.fld input,.fld select{width:100%}
.fld.disabled input,.fld.disabled select{background:#f2f3f5;color:#9aa3ae;cursor:not-allowed}
.fld.disabled>span:first-child{color:#9aa3ae}
.fld-note{font-style:normal;font-size:11.5px;color:var(--mut);line-height:1.5;margin-top:1px;
  display:block;white-space:pre-wrap}
.fld.warn .fld-note{color:var(--amber)}
.fld.err .fld-note{color:var(--red)}
.fld-pair{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--mut)}
.fld-pair input{width:72px;flex:none}
.chk{display:flex;align-items:center;gap:6px;font-size:13px;margin:6px 0 2px}
/* 多选 checkbox 组（模板表单的「特殊广告类别」）。
   原来是单选 select —— 存了多个类别的模板一编辑就被截成一个（静默丢数据）。 */
.catchk{display:flex;flex-wrap:wrap;gap:4px 14px;font-size:12.5px;margin:2px 0}
.catchk label{display:flex;align-items:center;gap:5px;white-space:nowrap}
.catchk input{width:auto;flex:none;margin:0}
.fld.disabled .catchk{opacity:.55}
.tp-preview{margin:16px 0 6px;border-top:1px solid var(--line);padding-top:14px}
.pv-head{font-size:13px;font-weight:600;margin-bottom:8px;display:flex;align-items:center;gap:8px;
  flex-wrap:wrap}
.pv-layer{font-size:12.5px;font-weight:600;color:var(--mut);margin:10px 0 5px}
.pv-tbl{width:100%;border-collapse:collapse;font-size:12.5px}
.pv-tbl th,.pv-tbl td{border:1px solid var(--line);padding:5px 8px;text-align:left;vertical-align:top}
.pv-tbl th{background:#f4f5f7;color:var(--mut);font-weight:500;white-space:nowrap}
.pv-ok{color:var(--green)}
.pv-locked{color:var(--purple)}
.pv-warn{color:var(--amber)}
.pv-error{color:var(--red)}
.pv-off{color:var(--mut)}
.pv-param{font-family:ui-monospace,Consolas,monospace;font-size:11.5px;color:#3b4a5a}
.pv-issues{font-size:12.5px;line-height:1.7;margin-top:8px}
.pv-issues .e{color:var(--red)}
.pv-issues .w{color:var(--amber)}
.tp-actions{display:flex;gap:8px;align-items:center;margin-top:14px;
  border-top:1px solid var(--line);padding-top:14px}

/* ---------- 广告详情 / 受控编辑弹窗（2026-09-30 英杰） ----------
   与产品文案同一原则：界面上要把「为什么不能改」写出来，不能只给个灰框。
   颜色沿用 :root 里的语义色变量（绿=可改/通过，红=拦下，琥珀=有代价）。 */
.chip.badx{background:var(--red-bg);color:var(--red)}
.adx-top{border:1px solid var(--line);border-radius:10px;padding:10px 12px;background:#fbfcfd}
.adx-name{font-size:15px;font-weight:600;margin-bottom:2px;word-break:break-all}
.adx-lvrow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px}
.adx-lv{border:1px solid var(--line);border-radius:8px;padding:4px 10px;background:#fff;
  display:flex;align-items:center;gap:6px;font-size:12.5px}
.adx-lv-t{color:var(--mut)}
.adx-lv.on{border-color:#bfe3d4;background:var(--green-bg)}
.adx-lv.on b{color:var(--green)}
.adx-lv.off{border-color:#f2c9c9;background:var(--red-bg)}
.adx-lv.off b{color:var(--red)}
.adx-lv.na b{color:var(--mut)}
.adx-h4{font-size:13px;font-weight:600;margin:14px 0 6px;padding-bottom:4px;
  border-bottom:1px solid var(--line)}
.adx-fields,.adx-kids{width:100%;border-collapse:collapse;font-size:13px}
.adx-fields th{width:158px;text-align:left;font-weight:500;color:var(--mut);padding:5px 8px 5px 0;
  vertical-align:top;white-space:nowrap}
.adx-fields td{padding:5px 0;vertical-align:top}
.adx-kids td{border-bottom:1px solid var(--line);padding:5px 8px;vertical-align:middle}
.adx-in{padding:4px 7px;border:1px solid var(--line);border-radius:6px;font:inherit;
  font-size:13px;background:#fff;color:var(--ink);max-width:340px}
input.adx-in[type=number]{max-width:120px}
.adx-ro{color:var(--ink)}
.adx-why{color:var(--mut);font-size:12px;margin-top:2px;max-width:640px;line-height:1.5}
/* 可改字段的注意事项：与 .adx-why（只读理由）同字号、不同前缀符号，视觉上是一对。 */
.adx-help{color:var(--mut);font-size:12px;margin-top:2px;max-width:640px;line-height:1.5}
.adx-help::before{content:"※ "}
.adx-lvtag{background:var(--amber-bg);color:var(--amber)}
.adx-note{border-radius:8px;padding:8px 10px;margin:8px 0;font-size:12.5px;line-height:1.6}
.adx-note.warn{background:var(--amber-bg);color:var(--amber)}
.adx-note.bad{background:var(--red-bg);color:var(--red)}
.adx-sum{margin:6px 0 10px;padding-left:20px;font-size:12.5px;line-height:1.75}
.adx-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:8px 14px;
  margin:8px 0}
.adx-grid label{font-size:12.5px;color:var(--mut);display:flex;flex-direction:column;gap:3px}
.adx-grid .adx-in{max-width:none;width:100%}
.adx-chk{display:flex;align-items:flex-start;gap:6px;font-size:12.5px;margin:8px 0}
.adx-adv{margin:10px 0;font-size:12.5px}
.adx-adv summary{cursor:pointer;color:var(--blue)}
.adx-json{width:100%;min-height:150px;font-family:ui-monospace,Consolas,monospace;font-size:12px;
  border:1px solid var(--line);border-radius:8px;padding:8px;margin-top:6px;background:#fbfcfd}
.adx-result{margin-top:14px}
.adx-block{border:1px solid var(--line);border-radius:10px;padding:10px 12px;margin:8px 0;
  font-size:13px;background:#fff}
.adx-block h4{margin:0 0 6px;font-size:13px}
.adx-block.ok{border-color:#bfe3d4;background:var(--green-bg)}
.adx-block.warn{border-color:#f0ddb8;background:var(--amber-bg)}
.adx-block.bad{border-color:#f2c9c9;background:var(--red-bg)}
.adx-block ul{margin:6px 0;padding-left:20px}
.adx-diff{line-height:1.8}
.adx-add{color:var(--green);font-weight:600}
.adx-del{color:var(--red);text-decoration:line-through}
.adx-warn{border-top:1px dashed rgba(0,0,0,.12);padding-top:6px;margin-top:6px}
.adx-err{color:var(--red);font-size:13px}
.adx-actions{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-top:14px;
  border-top:1px solid var(--line);padding-top:12px}
.adx-forcezone{display:inline-flex}
.adx-force-c{border:1px solid var(--red);border-radius:8px;padding:10px;background:var(--red-bg);
  display:flex;flex-direction:column;gap:8px;font-size:12.5px}
.adx-force-c button{align-self:flex-start}
