/* ══════════════════════════════════════════════════════════════════════
   稿战记 · 移动端适配层（≤880px：手机 / 平板竖屏）

   ⚠️ 加载位置很重要：必须放在页面内联 <style> **之后**（也就是 </body> 前）。
      本文件与页面内联样式权重相同，靠"后来者胜出"才能覆盖它们；
      放进 <head> 会被页面自己的内联样式盖掉，白改。

   ⚠️ 只动布局（列数 / 间距 / 滚动），不动配色与语义色铁律：
      绿=到账达成，红=逾期危险，紫=待收，琥珀=现在可催。

   ⚠️ 桌面端（>880px）完全不受影响——所有规则都包在媒体查询里，
      唯一的例外是 .sb-toggle / .sb-scrim 两个新节点，默认 display:none。
   ══════════════════════════════════════════════════════════════════════ */

/* 汉堡按钮与遮罩：桌面端不占位、不可见 */
.sb-toggle{display:none;}
.sb-scrim{display:none;}

@media (max-width:880px){

  /* ══════════ 1. 骨架：侧栏从「固定一列」改成「抽屉」 ══════════
     这是这一层要解决的头号问题：390px 的手机上，228px 的固定侧栏
     吃掉 58% 的宽度，正文只剩 160px，一行字竖着排。 */
  .shell{grid-template-columns:minmax(0,1fr);height:100vh;height:100dvh;}
  .main{width:100%;min-width:0;}

  .sidebar{
    position:fixed;top:0;left:0;bottom:0;z-index:70;
    width:min(84vw,300px);
    transform:translateX(-102%);
    transition:transform 270ms var(--ease);
    box-shadow:0 0 0 0.5px rgba(0,0,0,.30), 30px 0 70px -22px rgba(24,14,44,.58);
    padding:calc(12px + env(safe-area-inset-top)) 12px calc(14px + env(safe-area-inset-bottom));
    overscroll-behavior:contain;
  }
  .sidebar.open{transform:none;}

  /* 手指触控区：32px 高的行在手机上点不准，全部抬到 44px 左右 */
  .sidebar .nav{padding:12px 12px;font-size:15px;}
  .sidebar .nav-sub .nav{font-size:14px;padding:10px 12px;}
  .sidebar .navlabel{padding:15px 10px 6px;}
  .sidebar .nav .n{font-size:11.5px;min-width:24px;}
  .side-brand{padding:2px 8px 15px;}
  .side-brand b{font-size:17.5px;}
  .brandmark{width:38px;height:38px;border-radius:11px;}
  .brandmark svg{width:25px;height:25px;}
  .side-foot{padding:13px 8px 4px;}
  .side-id b{max-width:150px;font-size:13.5px;}
  .sm-i{padding:9px 9px;}

  .sb-scrim{display:block;position:fixed;inset:0;z-index:65;
    background:rgba(26,18,40,.46);backdrop-filter:blur(1.5px);
    opacity:0;pointer-events:none;transition:opacity 240ms var(--ease);}
  body.sb-open .sb-scrim{opacity:1;pointer-events:auto;}
  body.sb-open{overflow:hidden;}
  body.sb-open .sidebar{transform:none;}

  .sb-toggle{display:flex;flex-direction:column;justify-content:center;gap:4px;
    width:38px;height:38px;flex:0 0 auto;padding:0 9px;cursor:pointer;
    border:0.5px solid var(--hairline-strong);border-radius:var(--r-sm);
    background:var(--card);transition:background 150ms var(--ease);}
  .sb-toggle:active{background:var(--surface);}
  .sb-toggle span{display:block;height:1.6px;border-radius:2px;background:var(--ink);}
  .sb-toggle span:nth-child(2){width:70%;}

  /* ══════════ 2. 顶栏与内容区 ══════════ */
  .topbar{padding:9px 12px;gap:8px;flex-wrap:wrap;}
  /* flex-basis:0 —— 让标题只吃"剩余空间"。
     若用 auto，它的基准宽度是整串文字，会把「＋新建订单」挤到第二行，
     顶栏就会变成三行（标题行 / 按钮行 / 搜索行），白白吃掉 1/6 屏。 */
  .topbar .crumb{flex:1 1 0;min-width:0;white-space:nowrap;overflow:hidden;
    text-overflow:ellipsis;font-size:12.5px;}
  .topbar .crumb b{font-size:13px;}
  .topbar>.btn{padding:8px 12px;font-size:13px;}
  /* 搜索框：换到第二行占满整宽（原来 232px 固定宽在 390px 上必然溢出） */
  .topbar .gsearch{margin-left:0;order:9;width:100%;}
  .topbar .gsearch input{width:100%;}
  /* 统计看板顶栏没有搜索框，但有一个 4 段的时间范围开关：
     它带内联 margin-left:auto，硬留在第一行会把顶栏撑成 4 行。让它独占一行。 */
  .topbar .seg{order:8;flex:1 1 100%;}
  /* ⚠️ 用 > 选直接子项：.seg 里还有一层 .caret2 的 <span>（"自定义 ▾" 的小三角），
     它也是 span，被同一条规则命中后会吃到大 padding，把这一行撑到 62px 高。 */
  .topbar .seg>span{flex:1;text-align:center;white-space:nowrap;}
  .topbar .seg .caret2{flex:0 0 auto;padding:0;}
  .toolrow .gsearch,.toolbar .gsearch{margin-left:0;width:100%;}
  .toolrow .gsearch input,.toolbar .gsearch input,.toolrow input,.toolbar input{width:100%;}

  .content{padding:14px 14px calc(48px + env(safe-area-inset-bottom));}
  .page-head{flex-wrap:wrap;gap:8px 12px;margin-bottom:14px;}
  .page-head h2{font-size:17.5px;}
  .page-head p{font-size:12.5px;}
  .page-head .acts{margin-left:0;width:100%;}
  .page-head .acts .btn{flex:1;text-align:center;justify-content:center;}

  /* ══════════ 3. 多列网格 → 单列 / 两列 ══════════ */
  .kpis,.kpis4,.kpis.k4{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;}
  .kpi{padding:13px 13px;}
  .kpi .k{font-size:11px;}
  .kpi .v{font-size:20px;margin-top:4px;}
  .kpi .d{font-size:10px;}

  .cols{grid-template-columns:minmax(0,1fr);gap:14px;}
  .grid{grid-template-columns:minmax(0,1fr);gap:12px;}
  .grid>*{grid-column:auto !important;}      /* 看板卡片的内联 span 8 / span 4 全部失效 */
  .grid2{grid-template-columns:minmax(0,1fr);gap:12px;}
  .heatwrap{grid-template-columns:minmax(0,1fr);gap:14px;}

  /* 工作台 Hero：三列（本月已收 | 进度环 | 四宫格）变纵向 */
  .hero{grid-template-columns:minmax(0,1fr);grid-template-areas:"main" "ring" "stats" "sprint";}
  .hero-main{grid-template-columns:minmax(0,1fr);}
  .hm-col{padding:16px 16px 13px;}
  .hm-col+.hm-col{border-left:0;border-top:0.5px solid var(--hairline);padding-left:16px;
    padding-top:14px;}
  .hm-num b{font-size:33px;}
  .hm-num s{font-size:16px;}
  .hero-ring{width:116px;height:116px;margin:4px 0 2px;}
  .hero-ring svg{width:116px;height:116px;}
  .hero-stats{grid-template-columns:1fr 1fr;border-left:0;border-top:0.5px solid var(--hairline);}
  .hs{padding:11px 15px;}
  .hero-sprint{flex-wrap:wrap;padding:11px 15px;gap:8px 12px;}

  /* 设置类页面的字段行：176px 标签列在手机上会把控件挤扁。
     同上：字段行里也有「放第 2 列」的 .hint，统一钉回第 1 列，避免隐式列。 */
  .fieldrow{grid-template-columns:minmax(0,1fr);gap:7px;padding:13px 0;}
  .fieldrow>*{grid-column:1 !important;}
  .fieldrow>label{font-size:13.5px;}
  .fieldrow .ctl{gap:8px;}
  .fieldrow .ctl .inp{max-width:none;}
  .fieldrow .ctl .seg{width:100%;}

  /* 系统设置「实时预览」那一行 */
  .prev-row{grid-template-columns:3px minmax(0,1fr) auto;gap:5px 10px;align-items:center;}
  .prev-row .bar{grid-column:1;grid-row:1 / span 2;height:auto;min-height:36px;}
  .prev-row .no{grid-column:2;grid-row:1;padding-left:0;}
  .prev-row .fee{grid-column:3;grid-row:1;}
  .prev-row .who{grid-column:2;grid-row:2;}
  .prev-row .prev-badge{grid-column:3;grid-row:2;justify-self:end;}

  /* 工作台「今日摘要」：左边一句话 + 右边四个数字，手机上一行放不下，
     硬挤的结果是标题被压成一列一个字（"今天 / 有 4 / 件要"）。改成上下两块。 */
  .brief{flex-direction:column;align-items:stretch;gap:13px;}
  .brief-l h2{font-size:15px;line-height:1.5;}
  .brief-l p{font-size:12.5px;}
  .brief-r{margin-left:0;display:grid;grid-template-columns:1fr 1fr;gap:12px 10px;}
  .bk{text-align:left;}
  .bk b{font-size:18px;}

  /* ══════════ 4. 工作台待办行：7 列 → 4 行卡片式 ══════════ */
  .todo{grid-template-columns:3px minmax(0,1fr) auto;gap:4px 10px;
    padding:12px 14px 13px 0;align-items:start;}
  .todo .bar{grid-column:1;grid-row:1 / span 4;height:auto;align-self:stretch;min-height:44px;}
  .todo .no{grid-column:2;grid-row:1;padding-left:13px;}
  .todo .fee{grid-column:3;grid-row:1;font-size:13px;}
  .todo .who{grid-column:2;grid-row:2;padding-left:13px;}
  .todo .dl{grid-column:3;grid-row:2;font-size:12px;}
  .todo .req{grid-column:2 / 4;grid-row:3;padding-left:13px;white-space:normal;
    font-size:12px;line-height:1.5;}
  .todo .go{grid-column:2 / 4;grid-row:4;text-align:left;padding-left:13px;margin-top:5px;}
  .todo .go button{width:100%;padding:10px 12px;font-size:13px;}

  /* 分组头：描述换到第二行，指标与链接留在第一行 */
  .grp-h{flex-wrap:wrap;gap:7px 9px;padding:11px 14px;}
  .grp-h .desc{flex:1 1 100%;order:3;white-space:normal;}
  .grp-h .r{gap:9px;}
  .grp-h .r a{white-space:nowrap;}
  .later{flex-wrap:wrap;gap:6px 8px;padding:11px 14px;line-height:1.6;}
  .later a{margin-left:0;flex:1 1 100%;text-align:right;}

  /* ══════════ 5. 表格 ══════════
     两种模式，由 <table> 上有没有 data-card 决定：
     ① 有 data-card → 每行变一张卡片（列名靠 td[data-lab] 显示），适合列多的台账；
     ② 无 data-card → 保持表格，在卡片内横向滚动（权限矩阵这类宽表兜底）。 */
  .card{overflow-x:auto;}
  .card-b{overflow-x:auto;}
  table.t:not([data-card]){min-width:600px;}
  table.t th,table.t td{padding:9px 8px;}

  table.t[data-card]{table-layout:auto;min-width:0;}
  table.t[data-card] thead{display:none;}
  table.t[data-card],
  table.t[data-card] tbody,
  table.t[data-card] tr,
  table.t[data-card] td{display:block;width:auto;}
  table.t[data-card] tr{border:0.5px solid var(--hairline);border-radius:var(--r-md);
    background:var(--card);margin:0 0 10px;padding:4px 13px;box-shadow:var(--shadow-1);}
  table.t[data-card] tr:last-child{margin-bottom:0;}
  table.t[data-card] tr:hover{background:var(--card);}
  table.t[data-card] td{display:flex;flex-wrap:wrap;justify-content:space-between;
    align-items:baseline;gap:4px 12px;text-align:right;
    padding:7px 0;border-bottom:0.5px dashed var(--hairline);
    white-space:normal;overflow:visible;text-overflow:clip;
    font-size:13px;line-height:1.5;}
  table.t[data-card] td:last-child{border-bottom:0;}
  table.t[data-card] td[data-lab]::before{content:attr(data-lab);flex:0 0 auto;
    font-size:11.5px;color:var(--ink-3);text-align:left;
    font-family:var(--font-sans);font-weight:400;letter-spacing:0;}
  /* 单号 / 机构这类主字段：值加重，跟在标签后面 */
  table.t[data-card] td.c-no,table.t[data-card] td.c-org{color:var(--ink);}
  table.t[data-card] td>small{flex:1 1 100%;text-align:left;font-size:10.5px;
    color:var(--ink-3);overflow-wrap:anywhere;}
  table.t[data-card] td.num{font-size:14px;}
  /* 操作列：标签不显示，按钮铺开 */
  table.t[data-card] td.c-drag{display:none;}      /* 拖拽手柄：手机上拖不动，藏掉 */
  table.t[data-card] td[data-lab=""]{justify-content:flex-end;padding-top:9px;}
  table.t[data-card] td[data-lab=""]>button,
  table.t[data-card] td[data-lab=""] .rowacts,
  table.t[data-card] td[data-lab=""] .actions-cell{flex:1 1 100%;}
  table.t[data-card] td[data-lab=""] .rowacts,
  table.t[data-card] td[data-lab=""] .actions-cell{display:flex;justify-content:flex-end;
    flex-wrap:wrap;gap:14px;}
  table.t[data-card] td[data-lab=""] .actions-cell{gap:18px;}
  table.t[data-card] td[data-lab=""] .linkbtn{font-size:12.5px;padding:5px 0;}
  /* 收款进度：让进度条单独占一行铺满，比挤在标签右边那一条细线看得清 */
  table.t[data-card] td .pay-mini{flex:1 1 100%;min-width:0;}
  table.t[data-card] .empty-row{display:block;text-align:center;border:0;padding:26px 0;}

  /* 已结算的按机构分组：组头小计在手机上换行 */
  .grp-hd{flex-wrap:wrap;gap:6px 10px;}

  /* ══════════ 6. 弹窗 → 底部抽屉 ══════════
     ⚠️ 滚动交给 app.css 定好的 .modal-b（纵向 flex 的中间那层），
     这里**不能**再给 .modal 加 overflow-y:auto —— 那会变成两层滚动条。 */
  .mask{align-items:flex-end;padding:0;}
  .modal,.modal.wide{width:100%;max-width:100%;border-radius:16px 16px 0 0;
    max-height:92vh;max-height:92dvh;overflow:hidden;
    animation:sheetUp 250ms var(--ease);}
  @keyframes sheetUp{from{opacity:.65;transform:translateY(30px);}to{opacity:1;transform:none;}}
  .modal-h{position:sticky;top:0;z-index:3;background:var(--card);
    padding:15px 16px calc(13px + 0px);}
  .modal-h b{font-size:15px;}
  .modal-h .x{font-size:22px;padding:0 6px;}
  .modal-b{padding:15px 16px;}
  .modal-f{position:sticky;bottom:0;z-index:3;flex-wrap:wrap;padding:12px 16px calc(12px + env(safe-area-inset-bottom));}
  .modal-f .btn{flex:1 1 auto;text-align:center;justify-content:center;padding:11px 14px;font-size:13.5px;}
  /* 表单型弹窗：两列（76px 标签 + 控件）在手机上挤不下，改上下结构。
     ⚠️ 只改 grid-template-columns 是不够的：页面里还有 .due-sum / .span2 / .ro
     这类「放在第 2 列」的类，哪怕模板只有一列，它们也会撑出一个**隐式第二列**，
     结果还是两列（实测：206px + 148px）。所以子元素一律钉回第 1 列。 */
  .modal-b.form{grid-template-columns:minmax(0,1fr);gap:9px;}
  .modal-b.form>*{grid-column:1 !important;}
  .modal-b.form>label{text-align:left;font-size:12px;color:var(--ink-3);}
  .modal-b.form .ro{overflow-wrap:anywhere;}
  .modal-b.form input,.modal-b.form select,.modal-b.form textarea{font-size:16px;}
  .modal-b.form .inp{font-size:16px;}   /* ≥16px 防 iOS 聚焦自动放大 */
  .kv2{grid-template-columns:76px minmax(0,1fr);gap:7px 10px;}

  /* 输入框统一 ≥16px，否则 iOS Safari 一聚焦就整页放大 */
  .inp,.ta,input,select,textarea{font-size:16px;}
  .gsearch input,.topbar input{font-size:15px;}

  /* ══════════ 7. 杂项 ══════════ */
  .stabs{overflow-x:auto;flex-wrap:nowrap;-webkit-overflow-scrolling:touch;scrollbar-width:none;}
  .stabs::-webkit-scrollbar{display:none;}
  .stabs button{flex:0 0 auto;white-space:nowrap;}
  .stabs .void-note{margin-left:8px;flex:0 0 auto;}
  .fbar{gap:7px;}
  .fbar .lab{width:100%;margin:0 0 -2px;}
  .fbar .fsearch{flex:1 1 100%;}
  .fbar .fsearch input{width:100%;font-size:16px;padding:8px 30px 8px 30px;}
  .fbar .fsearch .clr{width:26px;height:26px;right:6px;font-size:16px;line-height:24px;}
  .fbar .selwrap{flex:1 1 44%;min-width:0;}
  .fbar .selwrap select{width:100%;}
  .fbar .spacer{display:none;}
  .fbar .res{flex:1 1 100%;}
  .tabs,.seg{display:flex;width:100%;}
  .tabs button,.seg button,.seg span{flex:1;text-align:center;white-space:nowrap;padding:8px 6px;}
  .toolrow>.btn,.toolbar>.btn{flex:1 1 auto;text-align:center;}
  .chips{gap:6px;}
  .card-h{padding:12px 14px;flex-wrap:wrap;}
  .card-h .r{margin-left:0;flex:1 1 100%;}
  .card-b{padding:13px 14px;}
  /* 到期提醒条：手机上文字先占满一行，按钮铺满第二行，别挤成一小条 */
  .lic-bar{flex-wrap:wrap;gap:6px 9px;font-size:12.5px;padding:10px 13px;}
  .lic-bar .sp{display:none;}
  .lic-bar button{width:100%;text-align:center;padding:8px 12px;}
  .lic-pill{font-size:12px;padding:4px 10px;}
  #toast{bottom:calc(24px + env(safe-area-inset-bottom));max-width:88vw;}
  /* 设计预览用的 Tweaks 浮标：在手机上会盖住图表，收起来 */
  #tw-btn,#tw-panel{display:none;}

  /* ══════════ 8. 触摸目标：手指不是鼠标 ══════════
     桌面按钮 29px 高、行内链接 26px、色板 22px，鼠标没问题，
     手机上（尤其单手持机、走路时）基本点不准。统一抬到 34px 左右。 */
  .btn{padding:10px 13px;min-height:34px;display:inline-flex;align-items:center;justify-content:center;}
  .btn.sm{min-height:32px;padding:8px 11px;}
  .linkbtn{min-height:32px;display:inline-flex;align-items:center;padding:4px 0;}
  .stabs button{padding:11px 13px 12px;}
  .seg button,.seg span{padding:10px 8px;}
  .chip{padding:8px 14px;}
  .swatches b{width:30px;height:30px;}
  .switch .track{width:44px;height:26px;}
  .switch .track::after{width:22px;height:22px;}
  .switch input:checked + .track::after{transform:translateX(18px);}
  .side-sw{width:30px;height:30px;font-size:14px;}
  .modal-h .x{padding:0 8px;}
  /* 卡片里的状态下拉（行内改状态用）也要够高 */
  table.t[data-card] select{min-height:34px;font-size:15px;padding:6px 8px;}

  /* 订单详情：收款记录一行放不下时换行；备注框给足高度（手机键盘弹起来要看得见） */
  .dt-pay{flex-wrap:wrap;}
  .dt-pay .c{margin-left:auto;}
  .dt-note{min-height:140px;font-size:16px;}
  .hn{margin-left:6px;}
  .deny{padding:20px 14px;}
  .deny-card{padding:22px 18px 18px;}
  .deny-card h2{font-size:18px;}
  .deny-act .btn{flex:1;}
  /* 统计看板：本年热量日历 53 列会挤成 6px 的小点，给每格一个最小宽度后横向滚动 */
  .heatwrap>div:first-child{overflow-x:auto;-webkit-overflow-scrolling:touch;}
  .heat-hint{margin-left:0;flex:1 1 100%;}
}

/* ── 更窄的手机（≤560px）：再收一档 ── */
@media (max-width:560px){
  .content{padding:12px 11px calc(48px + env(safe-area-inset-bottom));}
  .topbar{padding:8px 11px;gap:7px;}
  .topbar>.btn{padding:7px 10px;font-size:12.5px;}
  .kpis,.kpis4,.kpis.k4{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;}
  .kpi{padding:11px 12px;}
  .hm-num b{font-size:29px;}
  .page-head .acts .btn{font-size:12.5px;padding:9px 10px;}
  .modal-h,.modal-b,.modal-f{padding-left:13px;padding-right:13px;}
  table.t[data-card] td{font-size:12.5px;}
  .sb-toggle{width:36px;height:36px;}
}

/* ── SVG 改图页（整页是一个 iframe）：手机上要撑满，别留内边距 ──
   body.page-frame 比 .content 多一个选择器层级，所以能盖住上面两条 .content 的 padding，
   不受它们出现位置影响。工具本身的布局由 iframe 内部自理。 */
body.page-frame .content{padding:0;overflow:hidden;}
body.page-frame #svgFrame{width:100%;height:100%;min-height:0;}
