/*!
 * web/assets/css/index/03-global-fix.css
 * 全局内边距修复 / 动画 / 订单状态配色
 *
 * 本文件由 tools/split_spa.py 从单文件 SPA 机械拆出，请勿手工改动切分边界。
 * 加载顺序由入口 HTML 统一控制（经典 script 共享全局词法环境）。
 */

/* ===== 全局内边距修复：防止文字紧靠边缘 ===== */
.page{padding-left:16px!important;padding-right:16px!important}
.page .ep-cell-group{margin-left:0;margin-right:0}
.ep-cell__title,.ep-cell__label,.ep-cell__value{padding-left:4px;padding-right:4px}
.section-title{padding:0 4px}
/* ===== 全局交互动画 ===== */
.el-dialog{animation:dialogFadeIn .25s ease-out}
.el-dialog__wrapper{background:rgba(0,0,0,.5)}
@keyframes dialogFadeIn{from{opacity:0;transform:translateY(-20px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}
.ep-popup{transition:transform .3s cubic-bezier(.16,1,.3,1),opacity .3s ease}
.el-button{transition:all .15s ease}
.el-button:active{transform:scale(.96)}
/* 2026-10-05（#346）：`.el-tag` 原先**无条件**画成手型光标 + 按压缩放，于是「未发货」
   「免费名额：3」「共 0 单 · 可退 0 单」这类纯状态角标也看起来能点（实测 /help 一页
   就有 63 个角标被当成"点不准的触摸目标"，而它们根本不该被点）。
   可点性交回真正带点击的标签：标了 role=button / is-link / filt-on 的、在筛选条里的、
   以及模板里自己写了 cursor 的（那条本来就是行内声明，样式表盖不过它）。 */
.el-tag{transition:all .15s ease;pointer-events:none}
.el-tag[role=button],.el-tag.is-link,.el-tag.filt-on,.filter-bar .el-tag,.el-tag[style*="cursor:pointer"],.el-tag[style*="cursor: pointer"]{cursor:pointer}
/* 上面那句只把**光标**改对了，命中区没跟着改：Vue 仍然把 EP Tag 根节点上的那个框架自带
   click 监听挂在 `.el-tag` 上（实测：patchProp 里对 span.el-tag 调 addEventListener('click')）。
   #331 那条「挂了监听就算真控件」的判据于是把每一枚**装饰角标**当成触摸目标 ——
   /contract-manage 的「PDF」「正常」、/feedback 的「待处理」全被记成"点不准的控件"，
   而它们本来就不该被点。这里把同一份可点白名单一次说满：装饰角标不吃命中，
   拇指直接落到整行；能点的（role=button / is-link / filt-on / 筛选条 / 行内声明 cursor）照旧。
   `.el-select__tags .el-tag` 与 `.el-tag__close` 必须显式恢复：多选框的 chip 和它那个 × 是真控件。 */
.el-tag[role=button],.el-tag.is-link,.el-tag.filt-on,.el-tag[style*="cursor:pointer"],.el-tag[style*="cursor: pointer"],.filter-bar .el-tag,.el-select__tags .el-tag,.el-tag .el-tag__close{pointer-events:auto}
.el-tag[role=button]:active,.el-tag.is-link:active,.el-tag.filt-on:active,.filter-bar .el-tag:active{transform:scale(.93)}
.ep-cell{transition:background-color .15s ease}
.ep-cell:active{background-color:rgba(0,122,255,.06)}
.form-card{transition:transform .15s ease,box-shadow .2s ease}
.form-card:active{transform:scale(.99)}
.el-switch{transition:transform .12s ease}
.el-switch:active{transform:scale(.94)}
.el-select-dropdown__item{transition:background-color .15s ease}
/* 弹窗内容淡入 */
.el-drawer{animation:drawerSlideIn .3s ease-out}
@keyframes drawerSlideIn{from{transform:translateX(100%)}to{transform:translateX(0)}}
/* 列表项进入动画 */
.ep-cell-group .ep-cell{animation:cellFadeIn .3s ease-out both}
@keyframes cellFadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
.ep-cell-group .ep-cell:nth-child(1){animation-delay:.02s}
.ep-cell-group .ep-cell:nth-child(2){animation-delay:.04s}
.ep-cell-group .ep-cell:nth-child(3){animation-delay:.06s}
.ep-cell-group .ep-cell:nth-child(4){animation-delay:.08s}
.ep-cell-group .ep-cell:nth-child(5){animation-delay:.10s}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
.kanban{display:grid;gap:12px}@media(min-width:768px){.kanban{grid-template-columns:1fr 1fr 1fr}}@media(max-width:767px){.kanban{grid-template-columns:1fr}}
.kanban-col{background:var(--cd);border-radius:var(--rl);padding:12px;box-shadow:var(--sh)}.kanban-col h3{font-size:14px;font-weight:600;margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid var(--bd)}
.kanban-card{border-radius:var(--rm);border:1px solid var(--bd);padding:10px;margin-bottom:8px;cursor:pointer;transition:all .1s}.kanban-card:active{transform:scale(.98)}.kanban-card .style{font-size:16px;font-weight:600;color:var(--tc)}.kanban-card .info{font-size:12px;color:var(--ts);margin-top:4px;display:flex;gap:8px;flex-wrap:wrap}
.card-footer{display:flex;justify-content:space-between;align-items:center;margin-top:6px;font-size:12px;color:var(--ts)}
.status-badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600;line-height:1.6;white-space:nowrap;border:1px solid transparent}
/* 订单/通用状态配色：一眼即可区分不同状态（#2 优化） */
.status-pending,.status-pending_pay{background:#FDE8E8;color:#B82020;border-color:#F5C0C0}
.status-paid{background:#E6F0FF;color:#0A5BD6;border-color:#B9D4FF}
.status-processing{background:#F0E9FF;color:#6B2FBF;border-color:#D9C7FB}
.status-completed,.status-done{background:#E6F7EC;color:#1A8A4A;border-color:#B6E6C7}
.status-shipped{background:#E3F6F6;color:#0E7C86;border-color:#B2E6E6}
.status-partial{background:#FFF1D6;color:#B26A00;border-color:#FFE0A3}
.status-partial-pay{background:#F0E9FF;color:#6B2FBF;border-color:#D9C7FB}
.status-refunded{background:#FDECEC;color:#C0392B;border-color:#F6C9C9}
.status-hold{background:#EAF1FF;color:#2756D6;border-color:#C3D4FB}
.status-cancelled,.status-void{background:#F0F0F2;color:#6B6B70;border-color:#DCDCE0}
.status-unshipped{background:#F2F3F5;color:#8A8A8E;border-color:#E0E0E3}
/* 暗色模式配色（与明色模式语义一致，仅色值加深以适配深色背景）
   #448（2026-11-01）：这一族原来裹在 @media(prefers-color-scheme:dark) 里、选择器写 body:not(.light) ——
   两个信号都不是产品真正用的那个：主题由 40-app-root.js 把 dark 类挂在 <html> 上（auto 档自己去读系统）。
   表现就是「系统浅档 + 手动切暗黑」的机器上一条都不生效，实测暗档订单列表的状态胶囊仍是 #FDE8E8 一片浅。
   现在一律按 .dark 判；跟随系统那一档由 JS 负责，CSS 不再自己猜第二次。 */
.dark .status-pending,.dark .status-pending_pay{background:#3A1414;color:#FF8A80;border-color:#5E2121}
.dark .status-paid{background:#10294D;color:#7FB2FF;border-color:#1E3F66}
.dark .status-processing{background:#2C2150;color:#C4A6FF;border-color:#43306E}
.dark .status-completed,.dark .status-done{background:#103024;color:#5FD99A;border-color:#1C5138}
.dark .status-shipped{background:#0E3A3E;color:#5FD3D9;border-color:#16585E}
.dark .status-partial{background:#3A2E10;color:#FFC46B;border-color:#5A4514}
.dark .status-partial-pay{background:#2C2150;color:#C4A6FF;border-color:#43306E}
.dark .status-refunded{background:#3A1414;color:#FF8A80;border-color:#5E2121}
.dark .status-hold{background:#16264E;color:#90B4FF;border-color:#22386E}
.dark .status-cancelled,.dark .status-void{background:#2A2A2E;color:#A0A0A6;border-color:#3E3E44}
.dark .status-unshipped{background:#26262A;color:#9A9AA0;border-color:#3A3A40}
.credit-banner{background:linear-gradient(135deg,#FF3B30,#FF9500);color:#fff;padding:10px 14px;border-radius:var(--rm);margin-bottom:12px;font-size:13px;display:flex;justify-content:space-between;align-items:center}
.credit-banner .btn{background:rgba(255,255,255,.25);padding:4px 12px;border-radius:14px;font-size:12px;color:#fff;cursor:pointer;border:none;white-space:nowrap}
.fab{position:fixed;bottom:calc(80px + env(safe-area-inset-bottom));right:20px;z-index:60;transition:transform .15s ease,box-shadow .2s ease}.fab:active{transform:scale(.92)}
/* 2026-09-15：商品页第二个悬浮按钮（其他系统销售单），叠在主 FAB 上方。
   ⚠️ 同日二次反馈后已不再使用（入口并入「+」弹出的选择层），保留类定义仅为兼容旧缓存页面。 */
.fab--2{bottom:calc(140px + env(safe-area-inset-bottom))}
@media(min-width:768px){.fab--2{bottom:calc(90px + env(safe-area-inset-bottom))}}
/* 2026-09-15（送审反馈）：PC 端 .fab 原为 bottom:30px，正好压在页面底部版权条（#gp-site-footer，
   约 48px 高）上，导致「添加」按钮被版权文字遮挡、点不到。抬高到版权条之上。 */
@media(min-width:768px){.fab{bottom:calc(74px + env(safe-area-inset-bottom));right:24px;left:auto}}
/* #649（2026-10-23）：反馈悬浮按钮（#gp-fb-fab）与这颗「新增」停在同一个右下角，按钮 z=1950 压它 z=60，
   业主读到的是「这一页的新增点不到」。组件里的 JS 让位清单（FAB_KEEP_OUT）在**切页进来**的那十页都生效，
   而冷启动的第一页实测 reclamp 跑了三次仍没挪（观察器时机不可靠）—— 所以确定性的一条放在 CSS 里：
   按钮在场（body 上的 gp-fb-present 由 feedback-fab 自己挂/摘）就把右下角动作抬到它上方。
   抬起量 = 吸底手机页签 61 + 按钮 44 + 两侧留白 8+8 ≈ 121，再留一档取 132；桌面档原底部 74 同理 +52。
   ⚠️ 以后新增一枚 fixed + bottom/right 的右下角动作：除了登记进 FAB_KEEP_OUT，这里也要加一条，
   判据 tools/check_media_security.php（A18 第⑨组）拿 CSS 现扫出来的那张表逐条比对，少一条判红。 */
body.gp-fb-present .fab{bottom:calc(132px + env(safe-area-inset-bottom))}
@media(min-width:768px){body.gp-fb-present .fab{bottom:calc(126px + env(safe-area-inset-bottom))}}
.cust-stat{background:var(--cd);border-radius:8px;padding:10px 12px;display:flex;flex-direction:column;gap:2px}.cust-stat b{font-size:16px;color:var(--tc)}.cust-stat span{font-size:11px;color:var(--ts)}

/* ============ 弹层滚动锁（2026-09-12 新增） ============
   弹窗打开时页面不可滚，只允许弹层内部滚动；关闭弹窗后页面恢复。
   实现走「html 上加类」而不是改 body 内联 overflow，避免与 Element Plus
   自身的 useLockscreen 抢同一个内联值导致解锁后页面卡死（详见 41-scroll-lock.js 注释）。 */
html.wb-scroll-locked,html.wb-scroll-locked body{overflow:hidden!important;overscroll-behavior:none}
html.wb-scroll-locked .main,html.wb-scroll-locked .content-area,html.wb-scroll-locked .page,html.wb-scroll-locked .layout{overflow:hidden!important;overscroll-behavior:none}
/* 遮罩层阻断滚动穿透（触控板惯性滚动不会带到后面的页面） */
.ep-pop__mask,.ep-as__mask,.ep-overlay-mask,.el-overlay{overscroll-behavior:contain}
/* 弹层自身保持可滚（内容超出时在弹层内滚） */
.ep-pop,.ep-as,.el-dialog__body,.el-drawer__body{overscroll-behavior:contain;-webkit-overflow-scrolling:touch}

/* ============ 表单行标签对齐统一（2026-09-12 新增） ============
   根因：标准表单行 .ep-field 的标签固定 88px（.ep-field__label{width:88px}），
   但全站 24 个页面用内联样式另写了 78 个「标签+控件」行，标签宽度散落在 60/70/72/80px，
   同一个弹窗里不同行的控件起点最多相差 28px —— 这就是送审截图反复标注的「UI没有对齐」。
   为什么不在 JS 里逐行改：78 处内联样式分散在 24 个文件，且打印/预览区也用了同样的
   内联写法，逐个改风险远大于收益。这里用「作用域限定在弹层内部」的 CSS 一次性归一：
     · 只命中弹层（el-dialog__body / ep-pop / ep-as）内的 flex 行，绝不触碰打印预览区；
     · 只命中标签宽度恰为 60/70/72/80px 的那几种写法，不误伤其它 span。
   浅色/暗色都走 --ts，配色也随之统一。 */
.el-dialog__body div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:60px"],
.el-dialog__body div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:70px"],
.el-dialog__body div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:72px"],
.el-dialog__body div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:80px"],
.ep-pop div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:60px"],
.ep-pop div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:70px"],
.ep-pop div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:72px"],
.ep-pop div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:80px"],
.ep-as div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:60px"],
.ep-as div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:70px"],
.ep-as div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:72px"],
.ep-as div[style*="display:flex"][style*="align-items:center"][style*="padding"] > span[style*="min-width:80px"]{
  width:88px!important;min-width:88px!important;flex:none!important;
  font-size:13px!important;color:var(--ts)!important;
}

/* 当前套餐卡片（2026-09-12 新增，见 pages/packages.js） */
.pkg-cur{background:var(--cd);border:1px solid var(--pc);border-radius:12px;padding:14px;margin-bottom:10px}
.pkg-cur--expired{border-color:var(--dc)}

/* ============ 套装下单方式：整宽可选卡片（2026-09-12 新增） ============
   背景：原用 el-radio-group + flex-direction:column，但 EP 的 .el-radio-group 自带
   align-items:center，列方向下会把单选项**水平居中**，看起来浮在弹窗正中；
   说明文字又跟在整组下方、与具体选项脱节（送审截图「UI混乱」）。
   改成两枚整宽卡片：左对齐、说明内联，点整张卡片即选中。 */
.bundle-mode{display:flex;flex-direction:column;gap:8px}
.bundle-mode__opt{
  display:flex;align-items:flex-start;gap:8px;
  padding:10px 12px;border:1px solid var(--bd);border-radius:10px;
  background:var(--cd);cursor:pointer;
  transition:border-color .15s ease,background-color .15s ease;
}
.bundle-mode__opt.on{border-color:var(--pc);background:rgba(0,122,255,.06)}
.bundle-mode__opt input[type=radio]{margin:3px 0 0;flex:none;accent-color:var(--pc)}
.bundle-mode__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.bundle-mode__t{font-size:14px;color:var(--tc)}
.bundle-mode__h{font-size:11px;color:var(--ts);line-height:1.6}
.bundle-empty{
  margin:0 12px 6px;padding:14px 12px;
  border:1px dashed var(--bd);border-radius:8px;
  font-size:12px;color:var(--ts);text-align:center;
}
/* 同一类坑的全局兜底：弹层内凡是用列方向排布的 el-radio-group，
   都把它从 EP 默认的 align-items:center 改成左对齐，否则单选项一律居中。 */
.el-dialog__body .el-radio-group[style*="flex-direction:column"],
.ep-pop .el-radio-group[style*="flex-direction:column"],
.ep-as .el-radio-group[style*="flex-direction:column"]{align-items:flex-start}

/* ============ 套餐支付方式选择（2026-09-12 新增，见 pages/packages.js） ============ */
.pkg-pay-opt{display:flex;align-items:flex-start;gap:8px;padding:10px 12px;border:1px solid var(--bd);
  border-radius:10px;background:var(--cd);cursor:pointer;margin-bottom:8px;
  transition:border-color .15s ease,background-color .15s ease}
.pkg-pay-opt.on{border-color:var(--pc);background:rgba(0,122,255,.06)}
.pkg-pay-opt.dis{opacity:.55;cursor:not-allowed}
.pkg-pay-opt input[type=radio]{margin:3px 0 0;flex:none;accent-color:var(--pc)}
.pkg-pay-opt__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.pkg-pay-opt__t{font-size:14px;color:var(--tc)}
.pkg-pay-opt__h{font-size:11px;color:var(--ts);line-height:1.6}

/* ===== 2026-09-12（送审反馈 #1）：子账户无权限提示条 =====
   权限改为 fail-closed 后，未分配权限的子账户会看到较空的侧栏/底部菜单，
   这里给出可操作说明，避免被误判为「系统坏了」。 */
.perm-empty-tip{display:flex;align-items:flex-start;gap:8px;margin:8px 12px 0;padding:10px 12px;
  border-radius:10px;background:var(--warn-bg,#fff7e6);color:var(--warn-tc,#8a5a00);
  border:1px solid var(--warn-bd,#ffe0a3);font-size:12.5px;line-height:1.7}
.perm-empty-tip .el-icon{flex:none;margin-top:2px;font-size:15px}
:root.dark .perm-empty-tip{background:#3a2c10;color:#ffd591;border-color:#5c4620}

/* ===== 2026-09-12（送审反馈 #2）：公司（套餐）到期提醒条 =====
   替换原「积分不足」条；按 level 分级：warn=30天内橙色，urgent=15天内红色加急，expired=红色。 */
.expiry-banner{display:flex;align-items:center;gap:10px;margin:8px 12px 0;padding:9px 12px;
  border-radius:10px;font-size:13px;line-height:1.6;border:1px solid transparent}
.expiry-banner__txt{flex:1;min-width:0;display:flex;align-items:center;gap:6px}
.expiry-banner__txt b{margin-right:2px}
.expiry-banner__sub{font-size:12px;opacity:.85;flex:none}
.expiry-banner .btn{flex:none}
.expiry-banner--warn{background:var(--warn-bg,#fff7e6);color:var(--warn-tc,#8a5a00);border-color:#ffe0a3}
.expiry-banner--danger{background:#fef0f0;color:#c0392b;border-color:#fbc4c4}
.expiry-banner--urgent{font-weight:700}
.expiry-banner--urgent .expiry-banner__txt b{
  background:#e5484d;color:#fff;border-radius:4px;padding:0 5px;font-size:11px;font-weight:700;letter-spacing:.5px}
:root.dark .expiry-banner--warn{background:#3a2c10;color:#ffd591;border-color:#5c4620}
:root.dark .expiry-banner--danger{background:#3d1f1f;color:#ff9a9a;border-color:#6b3232}
