  :root{ --bg:#f4f6f9; --card:#fff; --line:#e2e8f0; --ink:#1e293b; --muted:#64748b;
         --blue:#2563eb; --red:#c0392b; --green:#15803d; --amber:#a05a00;
         --top-h:96px; --tab-h:41px; --right-w:minmax(380px,38%) }
  *{box-sizing:border-box}
  html{height:100%}
  /* 应用式外壳：整页不滚动 —— 左栏「内容区」内部滚动；右栏「菜单 + 预览」整体常驻 */
  body{height:100%;font-family:Segoe UI,"Microsoft YaHei",Arial,sans-serif;margin:0;background:var(--bg);color:var(--ink);
       font-size:13px;display:flex;flex-direction:column;overflow:hidden}
  button{font:inherit;cursor:pointer;border:1px solid var(--line);background:#fff;padding:5px 11px;border-radius:6px;color:var(--ink);white-space:nowrap}
  button:hover{border-color:#c3ced9}
  button:disabled{opacity:.42;cursor:default}
  button.primary{background:var(--blue);color:#fff;border-color:var(--blue)}
  button.primary:hover{background:#1d4ed8}
  button.danger{color:var(--red);border-color:#f0c5bd}
  button.danger:hover{background:#fdecea}
  button.mini{padding:2px 8px;font-size:11px;border-radius:5px}
  select,input[type=number],input[type=text]{font:inherit;padding:3px 5px;border:1px solid var(--line);border-radius:4px;background:#fff;color:var(--ink)}
  select{padding:4px 6px;max-width:230px}

  /* ============ 1. 标题行（菜单）—— v17 起落在右栏顶部，与模型预览同栏 ============ */
  .topbar{flex:0 0 auto;z-index:40;background:#0f172a;color:#fff;border-radius:10px;
          padding:9px 14px;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 14px;
          box-shadow:0 2px 8px rgba(15,23,42,.16)}
  .topbar .brand{display:flex;align-items:center;gap:12px;min-width:0;flex-wrap:wrap}
  .topbar .actions{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
  .topbar h1{margin:0;font-size:15px;font-weight:700;letter-spacing:.01em;white-space:nowrap}
  .topbar h1 .ver{font-size:10.5px;font-weight:600;color:#93c5fd;background:#1e3a8a;border-radius:9px;padding:1px 7px;margin-left:6px;vertical-align:1px}
  .topbar .sp{flex:1;min-width:0}
  .topbar .sep{width:1px;height:20px;background:#334155;margin:0 1px}
  .topbar button{background:#1e293b;color:#e2e8f0;border-color:#334155;padding:5px 11px}
  .topbar button:hover{border-color:#64748b;background:#26334a}
  .topbar button.primary{background:var(--blue);border-color:var(--blue);color:#fff}
  .topbar button.primary:hover{background:#1d4ed8}
  .topbar select{background:#1e293b;color:#e2e8f0;border-color:#334155;padding:5px 7px;max-width:260px}
  /* 顶栏里的下拉一律用深色底 —— 否则 select.anysel 的浅黄底 + 浅色字会把内容「吃掉」 */
  .topbar select.anysel{background:#1e293b;color:#e2e8f0;border-color:#334155}
  .topbar .lab{font-size:11px;color:#94a3b8;margin-right:-4px}
  .filetag{font-size:11px;color:#cbd5e1;background:#1e293b;border:1px solid #334155;border-radius:11px;padding:3px 10px;max-width:280px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .vlight{font-size:11.5px;font-weight:600;border-radius:11px;padding:3px 10px;white-space:nowrap;
          background:#14532d;color:#86efac;border:1px solid #166534}
  .vlight.warn{background:#4a2f0b;color:#fdba74;border-color:#78350f}
  .vlight.err{background:#511d1d;color:#fca5a5;border-color:#7f1d1d}
  .vlight.idle{background:#1e293b;color:#94a3b8;border-color:#334155}

  /* ============ 2. 模型预览框（右上角 · 常驻 · 实时） ============ */
  .preview{flex:0 1 auto;min-height:0;max-height:100%;display:flex;flex-direction:column;overflow:auto;
           background:var(--card);border:1px solid var(--line);border-radius:9px;padding:9px 11px 10px;
           box-shadow:0 2px 7px -4px rgba(15,23,42,.18)}
  .preview .pvhead{display:flex;flex-wrap:nowrap;align-items:center;gap:8px;margin-bottom:4px}
  .preview .pvhead b{font-size:12px}
  #pvStat,#zStat{font-size:11.5px;color:var(--muted);line-height:1.55;margin-top:6px}
  #pvStat b,#zStat b{color:var(--ink)}
  .preview .pvctl{display:flex;flex-wrap:wrap;align-items:center;gap:9px;font-size:11px;color:var(--muted)}
  .preview .pvctl label{display:inline-flex;align-items:center;gap:4px;cursor:pointer}
  /* v17：预览区独占右栏 —— 图按右栏宽度自适应并在框内居中，高度留个上限 */
  .preview .pvbody{border:1px solid var(--line);border-radius:6px;background:#fbfcfe;margin-top:4px;
                   min-height:120px;display:flex;align-items:center;justify-content:center;overflow:hidden}
  #plotSvg{display:block;width:100%;height:auto;max-height:min(52vh,520px)}
  .preview.collapsed .pvbody,.preview.collapsed #pvStat,.preview.collapsed .pvleg,.preview.collapsed .pvctl{display:none}
  .pvleg{display:flex;gap:9px;flex-wrap:wrap;align-items:center;color:var(--muted);font-size:11px;margin-top:5px}
  .pvleg label{display:inline-flex;align-items:center;gap:4px;cursor:pointer}
  .pvleg input[type=color]{width:14px;height:14px;padding:0;border:1px solid var(--line);border-radius:3px;background:#fff;cursor:pointer}
  .plotkey{display:inline-flex;align-items:center;gap:4px;background:#f1f5f9;border:1px solid var(--line);border-radius:4px;padding:1px 6px}
  .plotkey i{display:inline-block;width:14px;height:10px;border:1px solid rgba(15,23,42,.28);border-radius:2px}
  svg g.seg rect,svg g.seg polygon{transition:stroke .12s,stroke-width .12s}
  svg g.seg:hover rect,svg g.seg:hover polygon{stroke:#2563eb;stroke-width:1.6;stroke-opacity:1}

  /* ============ 3. 选项卡（左栏顶部常驻；内容区自己滚，所以不必 sticky） ============ */
  .tabs{display:flex;gap:2px;flex:0 0 auto;min-width:0;
        background:var(--card);border:1px solid var(--line);border-radius:9px 9px 0 0;
        padding:0 8px;overflow-x:auto}
  .tab{display:inline-flex;align-items:center;gap:6px;border:none;background:none;border-radius:0;
       padding:10px 14px 9px;font-weight:600;font-size:13px;color:var(--muted);
       border-bottom:2.5px solid transparent;cursor:pointer;font-family:inherit;white-space:nowrap}
  .tab:hover{color:var(--ink);background:#f8fafc}
  .tab.active{color:var(--blue);border-bottom-color:var(--blue);background:none}
  .tab .cnt{font-size:10px;color:var(--muted);background:#f1f5f9;border-radius:9px;padding:1px 6px;font-weight:600}
  .tab.active .cnt{background:#dbeafe;color:#1d4ed8}
  .tab.vlight-on .cnt{background:#dcfce7;color:#15803d}
  .tab.vlight-warn .cnt{background:#fef3c7;color:#a05a00}
  .tab.vlight-err .cnt{background:#fee2e2;color:#c0392b}

  /* ============ 应用外壳：顶部全宽工具栏 + 下方两栏（左=内容，右=预览） ============ */
  .shell{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:10px;padding:10px 14px 14px}
  .work{flex:1 1 auto;min-height:0;display:grid;grid-template-columns:minmax(0,1fr) var(--right-w);gap:0 14px}
  /* 左栏：选项卡常驻顶部 + 内容区内部滚动 */
  .colL{display:flex;flex-direction:column;min-height:0;min-width:0}
  /* 右栏：模型预览吃掉余高 */
  .colR{display:flex;flex-direction:column;min-height:0;min-width:0}
  /* 窄屏（<1040px）退回「上下堆叠」：预览排到最上，整页恢复滚动 */
  @media (max-width:1040px){
    body{height:auto;overflow:auto}
    .work{display:flex;flex-direction:column;gap:10px}
    .colR{order:-1}
    .main{overflow:visible}
    .preview{max-height:none}
    .tabs{border-radius:9px}
    .topbar{position:sticky;top:0;z-index:50}
  }

  /* ============ 内容区（左栏，独立滚动容器） ============ */
  .main{flex:1 1 auto;padding:12px 14px 40px;overflow-y:auto;min-height:0;min-width:0}
  .panel{display:none}
  .panel.active{display:block}
  .pagehead{display:flex;align-items:flex-start;gap:10px;flex-wrap:wrap;margin:0 0 10px}
  .pagehead .pt{font-size:15px;font-weight:700;margin:0 0 3px;color:#0f172a}
  .pagehead .ps{font-size:11px;color:var(--muted);line-height:1.6}
  .pagehead .pact{margin-left:auto;display:flex;gap:7px;flex-wrap:wrap;align-items:center}
  .toolrow{display:flex;flex-wrap:wrap;align-items:center;gap:7px;margin:0 0 9px;font-size:11.5px;color:var(--muted)}
  /* 轴元素页的「添加」操作条：粘在左栏内容区底部。
     原因：元素一多，「＋ 轴段」在页头就要一路滚回顶部才点得到 —— 用户明确提过。
     用 position:sticky 而不是 fixed（fixed 会跑出滚动容器、盖住右栏）。 */
  .bottombar{position:sticky;bottom:-1px;display:flex;gap:7px;flex-wrap:wrap;align-items:center;
             margin:12px 0 0;padding:9px 10px;background:var(--panel,#fff);
             border-top:1px solid var(--line,#dbe6f3);box-shadow:0 -6px 12px -8px rgba(15,40,80,.18);z-index:2}
  .bottombar .bbtip{margin-left:auto;font-size:11px;color:var(--muted)}
  .bar{padding:6px 10px;border-radius:6px;margin:0 0 10px;font-size:12px;display:none;white-space:pre-wrap;line-height:1.5}
  .bar.ok{background:#e7f7ee;color:#15803d;border:1px solid #b6e6c9}
  .bar.warn{background:#fff4e5;color:#a05a00;border:1px solid #f3d9a8}
  .bar.err{background:#fdecea;color:#c0392b;border:1px solid #f3c0b9}

  table{border-collapse:collapse;width:100%;margin-bottom:10px;background:var(--card)}
  th,td{border:1px solid var(--line);padding:4px 6px;text-align:center;font-size:12px}
  th{background:#f1f5f9;position:sticky;top:0;z-index:2}
  th .thu{font-weight:400;color:#94a3b8;font-size:10px;display:block;line-height:1.3}
  th .thn{font-weight:400;color:#2563eb;font-size:10px;display:block;line-height:1.3}
  input[type=number]{width:78px}
  select.matsel{background:#eef7ff;border-color:#bfdbfe;font-weight:600;color:#1d4ed8;max-width:200px}
  select.anysel{background:#fff8e6;border-color:#f0dca8}
  input.auto{background:#f1f5f9;color:var(--muted)}
  input.bad{border-color:var(--red);background:#fdecea}
  select.stiffmass{background:#eef7ff;border-color:#bfdbfe}
  select.stiffnone{background:#fff4e5;border-color:#f3d9a8;color:#a05a00}
  select.stiffzero{background:#fdecea;border-color:#f3c0b9;color:var(--red);font-weight:600}
  tr.grp td{border-top:2px solid #dbe6f3;background:#f7fafd}
  .chip{border:1px solid var(--line);background:#fff;border-radius:12px;padding:3px 10px;font-size:11.5px;cursor:pointer;color:var(--muted);font-family:inherit}
  .chip.on{background:#e8f1ff;border-color:#bfdbfe;color:#1d4ed8;font-weight:600}
  .libbar{display:flex;gap:7px;flex-wrap:wrap;align-items:center;margin-bottom:8px}
  .libtable tr.own td{background:#f7fbf8}
  .libtable tr.user td{background:#fdf9f2}
  .card{border:1px solid var(--line);border-radius:8px;padding:11px 13px;margin-bottom:11px;background:var(--card)}
  .card h3{margin:0 0 9px;font-size:13.5px;font-weight:700;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
  .card h3::before{content:"";width:3px;height:14px;background:var(--blue);border-radius:2px;flex:0 0 auto}
  .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(168px,1fr));gap:8px}
  .field label{display:block;color:var(--muted);font-size:11px;margin-bottom:2px}
  .grid4{display:grid;grid-template-columns:repeat(4,1fr);gap:4px;max-width:340px}
  /* 轴承系数矩阵：带「行标题 / 列标题」的表格布局（1 列标题轨 + N 列数据列） */
  .brgtbl{display:grid;grid-template-columns:112px repeat(4,minmax(0,1fr));gap:4px;max-width:520px;align-items:center}
  .brgtbl-c{font-size:10px;color:var(--muted);text-align:right;padding-right:2px}
  .brgtbl-h{font-size:11px;font-weight:600;color:var(--accent);text-align:center;
            background:#eef2f7;border:1px solid var(--line);border-radius:4px;padding:3px 0}
  .brgtbl-r{font-size:11px;color:var(--muted);text-align:right;padding-right:4px;white-space:nowrap}
  .brgtbl-d{min-width:0}
  .brgtbl-d input{width:100%}
  textarea{width:100%;min-height:180px;font-family:Consolas,Menlo,monospace;font-size:11px;
           border:1px solid var(--line);border-radius:6px;padding:8px;white-space:pre;background:#fbfcfe}
  .hint{color:var(--muted);font-size:11px;line-height:1.6;background:#f8fafc;border:1px solid var(--line);border-left:3px solid #cbd5e1;border-radius:6px;padding:9px 11px;margin:9px 0}
  .hint ul{margin:7px 0 1px;padding-left:18px}
  .hint li{margin:3px 0}
  .hint li::marker{color:#94a3b8}
  .hint code{background:#e2e8f0;padding:1px 4px;border-radius:3px}
  .hint b{color:var(--ink)}
  .pill{display:inline-block;background:#f1f5f9;color:var(--muted);border-radius:10px;padding:1px 8px;font-size:11px}
  .legend{display:flex;gap:14px;flex-wrap:wrap;color:var(--muted);font-size:11px;margin:-2px 0 9px}
  .legend i{display:inline-block;width:10px;height:10px;border-radius:2px;margin-right:4px;vertical-align:-1px}
  .empty{color:var(--muted);padding:14px;text-align:center;background:var(--card);
         border:1px dashed var(--line);border-radius:8px;font-size:12px;line-height:1.7}
  .selcol{width:26px}

  /* 导出弹窗 */
  .modal{position:fixed;inset:0;z-index:60;background:rgba(15,23,42,.5);display:none;align-items:flex-start;justify-content:center;padding:40px 16px}
  .modal.on{display:flex}
  .modal .box{background:var(--card);border-radius:10px;width:min(1000px,100%);max-height:calc(100vh - 80px);
              display:flex;flex-direction:column;box-shadow:0 20px 50px rgba(15,23,42,.35)}
  .modal .mh{display:flex;align-items:center;gap:9px;padding:12px 16px;border-bottom:1px solid var(--line)}
  .modal .mh b{font-size:14px}
  .modal .mb{padding:14px 16px;overflow:auto}
  .modal textarea{min-height:380px}

  /* 模型图「放大」弹窗：把右栏那张图放到近全屏看（图层与纵向放大沿用右栏设置，形状完全一致）。
     用 .zoom 覆盖 .modal 的顶部对齐 / 内边距，让盒子撑满视口。 */
  .zoom{align-items:stretch;padding:16px}
  .zoom .zbox{background:var(--card);border-radius:11px;width:min(1680px,100%);margin:0 auto;
              height:min(94vh,1080px);display:flex;flex-direction:column;overflow:hidden;
              box-shadow:0 20px 50px rgba(15,23,42,.42)}
  .zoom .zfig{flex:1 1 auto;min-height:0;display:flex;align-items:center;justify-content:center;
              overflow:auto;background:#fbfcfe;border:1px solid var(--line);border-radius:8px;
              margin:0 14px;padding:4px}
  /* 放大窗口自己的图层工具条 —— 与右栏预览是【同一份状态的两套控件】：
     改任一处都由 plotCtrlsMirror() 同步到另一处，免得「大图里藏了一层、关掉弹窗右栏又亮回来」。 */
  .zoom .zctl{flex:0 0 auto;display:flex;flex-wrap:wrap;align-items:center;gap:5px 11px;
              font-size:12.5px;color:var(--muted);padding:8px 16px 0}
  .zoom .zctl label{display:inline-flex;align-items:center;gap:5px;cursor:pointer}
  .zoom .zctl .zhint{font-size:11.5px;color:#94a3b8}
  /* 大图按容器宽度铺满；height:auto 由 viewBox 比例反算。
     ⚠ 天坑：`<svg>` 上如果已经写了 width/height 属性，CSS 的 `height:auto` 在 Chrome 里
       不会自动按 viewBox 比例反算，而是沿用那个属性值 —— 于是框被拉得比容器还高，
       .zfig 长出滚动条、图也会被推到视口外。所以必须再压一道 `max-height:100%`。
       （preserveAspectRatio="xMidYMid meet" 保证内容本身始终等比，不会变形。） */
  #plotBig{display:block;width:100%;height:auto;max-height:100%}
  .zoom .zfoot{flex:0 0 auto;padding:9px 14px 12px;overflow:auto;max-height:26vh}
  /* 大窗口里说明与图例都放大一档，远看也认得清 */
  .zoom .zfoot #zStat{font-size:12.5px}
  .zoom .zfoot .pvleg{margin-top:4px;font-size:12px}
  .zoom .zfoot .plotkey{padding:2px 7px}
  /* ⚠ 窄屏（<=1040px）下右栏预览改成「整幅铺满」，宽度会反超被 min(1680px,100%) 卡住的弹窗 ——
     那样点「放大」反而看到一张更小的图。这里把弹窗的水平内缩全部收掉，让大图吃掉整幅视口宽度。
     ⚠⚠ 这一块必须写在上面那些 .zoom 基础规则【之后】：同特异性下后出现的才生效，
        写在前面（例如塞进顶部那个 @media 里）会被 .zfig{margin:0 14px} 覆盖掉 —— 白改。 */
  @media (max-width:1040px){
    .zoom{padding:0}
    .zoom .zbox{height:min(96vh,1080px);border-radius:0;width:100%}
    .zoom .zfig{margin:0}
    .zoom .zctl{padding:6px 10px 0}
    .zoom .zfoot{padding:6px 10px 8px}
  }
