/* ===================================================================
   春森菌种选育管理系统 —— 主样式
   设计语言与「春森菌业智慧管理系统统一平台」保持一致：
   克制的圆角 + 描边 + 投影；蓝色主色；不堆装饰。
   =================================================================== */
:root {
    --blue-50:  #eef4ff;
    --blue-100: #dbe7ff;
    --blue-200: #bfd4ff;
    --blue-500: #3b82f6;
    --blue-600: #2563eb;
    --blue-700: #1d4ed8;
    --blue-800: #1e40af;
    --ink-900:  #0f172a;
    --ink-800:  #1f2937;
    --ink-700:  #374151;
    --ink-600:  #4b5563;
    --ink-500:  #6b7280;
    --ink-400:  #9ca3af;
    --line:     #e4e9f2;
    --line-2:   #eef1f7;
    --bg:       #f4f7fc;
    --card:     #ffffff;
    --ok:       #16a34a;
    --ok-bg:    #e9f9ef;
    --warn:     #d97706;
    --warn-bg:  #fef6e7;
    --bad:      #dc2626;
    --bad-bg:   #fdecec;
    --muted-bg: #f1f4f9;
    --radius:   10px;
    --radius-sm: 7px;
    --shadow-1: 0 1px 2px rgba(16, 32, 64, .05), 0 1px 3px rgba(16, 32, 64, .04);
    --shadow-2: 0 4px 14px rgba(16, 32, 64, .07);
    --shadow-3: 0 12px 34px rgba(16, 32, 64, .12);
    --nav-h:    56px;
    --side-w:   216px;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
    font-family: "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", system-ui, -apple-system, "Segoe UI", sans-serif;
    background: var(--bg); color: var(--ink-800); font-size: 14px; line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}
a { color: var(--blue-600); text-decoration: none; }
a:hover { color: var(--blue-700); }
h1, h2, h3, h4 { margin: 0; font-weight: 600; color: var(--ink-900); }
table { border-collapse: collapse; width: 100%; }
.mono { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 12.5px; }
.muted { color: var(--ink-500); }
.nowrap { white-space: nowrap; }
.right { text-align: right; }
.center { text-align: center; }

/* ============ 顶栏 ============ */
.nav {
    height: var(--nav-h); position: fixed; top: 0; left: 0; right: 0; z-index: 80;
    background: linear-gradient(90deg, var(--blue-800) 0%, var(--blue-600) 62%, #3b82f6 100%);
    display: flex; align-items: center; gap: 14px; padding: 0 18px;
    box-shadow: 0 2px 10px rgba(21, 52, 116, .18);
}
.nav .brand { display: flex; align-items: center; gap: 10px; color: #fff; font-weight: 600; font-size: 15.5px; letter-spacing: .3px; }
.nav .brand .logo {
    width: 30px; height: 30px; border-radius: 8px; background: rgba(255,255,255,.16);
    display: flex; align-items: center; justify-content: center; font-size: 15px; font-weight: 700;
    border: 1px solid rgba(255,255,255,.25); flex: 0 0 auto;
}
.nav .brand small { display: block; font-size: 10.5px; opacity: .72; font-weight: 400; letter-spacing: 1.2px; }
.nav .plat {
    margin-left: 10px; font-size: 12.5px; color: rgba(255,255,255,.9);
    border: 1px solid rgba(255,255,255,.3); background: rgba(255,255,255,.08);
    padding: 4px 11px; border-radius: 20px;
}
.nav .plat:hover { background: rgba(255,255,255,.18); color: #fff; }
.nav .right { margin-left: auto; display: flex; align-items: center; gap: 10px; color: #fff; }
.nav .right .who { font-size: 13px; opacity: .93; }
.nav .btn-ghost {
    color: #fff; border: 1px solid rgba(255,255,255,.36); background: rgba(255,255,255,.08);
    padding: 5px 12px; border-radius: 7px; font-size: 13px; cursor: pointer; display: inline-block;
}
.nav .btn-ghost:hover { background: rgba(255,255,255,.18); color: #fff; }

/* ============ 侧栏 ============ */
.side {
    position: fixed; top: var(--nav-h); bottom: 0; left: 0; width: var(--side-w);
    background: #fff; border-right: 1px solid var(--line); padding: 12px 10px 30px;
    overflow-y: auto; z-index: 70;
}
.side .grp { font-size: 11.5px; color: var(--ink-400); letter-spacing: .6px; padding: 13px 10px 5px; }
.side a {
    display: flex; align-items: center; gap: 9px; padding: 8px 11px; border-radius: 8px;
    color: var(--ink-700); font-size: 13.5px; margin-bottom: 2px; transition: background .15s, color .15s;
}
.side a:hover { background: var(--blue-50); color: var(--blue-700); }
.side a.on { background: var(--blue-600); color: #fff; font-weight: 600; box-shadow: 0 2px 8px rgba(37,99,235,.28); }
.side a .ic { width: 16px; text-align: center; opacity: .9; flex: 0 0 auto; }
.side a .badge {
    margin-left: auto; background: var(--bad); color: #fff; font-size: 11px;
    padding: 0 6px; border-radius: 20px; line-height: 17px;
}
.side a.on .badge { background: rgba(255,255,255,.28); }
.side .foot { margin-top: 18px; padding: 12px 11px 0; border-top: 1px solid var(--line-2); font-size: 11.5px; color: var(--ink-400); line-height: 1.9; }

/* ============ 主区 ============ */
.main { margin-left: var(--side-w); padding: calc(var(--nav-h) + 18px) 20px 44px; }
.wrap { max-width: 1480px; margin: 0 auto; }
.page-head { display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.page-head h2 { font-size: 19px; }
.page-head .sub { color: var(--ink-500); font-size: 13px; }
.page-head .spacer { margin-left: auto; }

/* ============ 卡片 ============ */
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-1); }
.card + .card { margin-top: 16px; }
.card-hd { padding: 13px 16px; border-bottom: 1px solid var(--line-2); display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.card-hd h3 { font-size: 15px; }
.card-hd .spacer { margin-left: auto; }
.card-hd .hint { color: var(--ink-500); font-size: 12px; }
.card-bd { padding: 16px; }
.card-bd.tight { padding: 0; }

/* ============ KPI ============ */
.kpis { display: grid; grid-template-columns: repeat(6, 1fr); gap: 12px; }
.kpis.c5 { grid-template-columns: repeat(5, 1fr); }
.kpis.c4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1240px) { .kpis, .kpis.c5, .kpis.c4 { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 720px)  { .kpis, .kpis.c5, .kpis.c4 { grid-template-columns: repeat(2, 1fr); } }
.kpi { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; box-shadow: var(--shadow-1); }
.kpi .lab { color: var(--ink-500); font-size: 12.5px; display: flex; align-items: center; gap: 6px; }
.kpi .val { font-size: 26px; font-weight: 700; color: var(--ink-900); line-height: 1.25; margin-top: 4px; font-variant-numeric: tabular-nums; }
.kpi .val small { font-size: 13px; font-weight: 500; color: var(--ink-500); margin-left: 3px; }
.kpi .foot { font-size: 12px; color: var(--ink-400); margin-top: 2px; }
.kpi.accent { background: linear-gradient(135deg, var(--blue-700), var(--blue-500)); border-color: transparent; }
.kpi.accent .lab, .kpi.accent .foot { color: rgba(255,255,255,.82); }
.kpi.accent .val { color: #fff; }

/* ============ 徽标 ============ */
.tag { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; padding: 2px 8px; border-radius: 20px; line-height: 1.6; border: 1px solid transparent; white-space: nowrap; }
.tag.ok    { color: var(--ok);   background: var(--ok-bg);   border-color: #cdeedb; }
.tag.bad   { color: var(--bad);  background: var(--bad-bg);  border-color: #f7d4d4; }
.tag.warn  { color: var(--warn); background: var(--warn-bg); border-color: #f6e2bd; }
.tag.muted { color: var(--ink-500); background: var(--muted-bg); border-color: #e3e8f0; }
.tag.blue  { color: var(--blue-700); background: var(--blue-50); border-color: var(--blue-100); }
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; vertical-align: middle; }
.dot.ok { background: var(--ok); } .dot.bad { background: var(--bad); }
.dot.warn { background: var(--warn); } .dot.muted { background: var(--ink-400); }

/* ============ 按钮 ============ */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    padding: 7px 14px; border-radius: var(--radius-sm); font-size: 13.5px; cursor: pointer;
    border: 1px solid var(--line); background: #fff; color: var(--ink-800);
    transition: all .15s; white-space: nowrap; font-family: inherit;
}
.btn:hover { border-color: var(--blue-200); color: var(--blue-700); background: var(--blue-50); }
.btn.primary { background: var(--blue-600); border-color: var(--blue-600); color: #fff; }
.btn.primary:hover { background: var(--blue-700); border-color: var(--blue-700); color: #fff; }
.btn.danger { color: var(--bad); border-color: #f2c9c9; background: #fff; }
.btn.danger:hover { background: var(--bad-bg); border-color: var(--bad); color: var(--bad); }
.btn.ok { color: var(--ok); border-color: #bfe6cd; background: #fff; }
.btn.ok:hover { background: var(--ok-bg); border-color: var(--ok); }
.btn.sm { padding: 4px 10px; font-size: 12.5px; border-radius: 6px; }
.btn.link { border: none; background: none; padding: 2px 4px; color: var(--blue-600); }
.btn.link:hover { background: none; text-decoration: underline; color: var(--blue-700); }
.btn[disabled] { opacity: .55; cursor: not-allowed; }

/* ============ 表格 ============ */
.tbl { font-size: 13.5px; }
.tbl th { text-align: left; font-weight: 600; color: var(--ink-600); font-size: 12.5px; padding: 10px 12px; background: #f8fafd; border-bottom: 1px solid var(--line); white-space: nowrap; }
.tbl td { padding: 10px 12px; border-bottom: 1px solid var(--line-2); vertical-align: middle; }
.tbl tbody tr:hover { background: #fafcff; }
.tbl tbody tr:last-child td { border-bottom: none; }
.tbl .num { text-align: right; font-variant-numeric: tabular-nums; }
.tbl .acts { white-space: nowrap; text-align: right; }
.tbl-wrap { overflow-x: auto; }
.tbl.zebra tbody tr:nth-child(even) { background: #fbfcff; }
.tbl.zebra tbody tr:nth-child(even):hover { background: #f5f9ff; }

/* ---- 单行列表（总览页一屏化） ----
   原来「最近登记 / 最近种性 / 最近事务」是「主行 + 副行」两行堆叠的结构，
   每条 57~59px，5 条就要 297px；而一屏模式下 1440×900 每张卡片总高只有 ~213px，
   被藏掉 135px（探针实测）。改成单行后每条 ~33px，5 条 165px，留有余量。
   第二列的文字一律走 .ellip 单行省略 + title 悬停可看全文，不用换行撑高。 */
.tbl.one-line td { padding: 7px 10px; }
.ellip { max-width: 230px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ============ 表单 ============ */
.field { margin-bottom: 13px; }
.field label { display: block; font-size: 12.5px; color: var(--ink-600); margin-bottom: 5px; }
.field label .req { color: var(--bad); margin-left: 3px; }
.field .tip { font-size: 11.5px; color: var(--ink-400); margin-top: 4px; line-height: 1.7; }
.inp, select.inp, textarea.inp {
    width: 100%; padding: 8px 11px; border: 1px solid var(--line); border-radius: var(--radius-sm);
    font-size: 13.5px; font-family: inherit; color: var(--ink-800); background: #fff; outline: none;
    transition: border-color .15s, box-shadow .15s;
}
.inp:focus { border-color: var(--blue-500); box-shadow: 0 0 0 3px var(--blue-50); }
.inp:disabled, .inp[readonly] { background: #f8fafd; color: var(--ink-500); }
textarea.inp { resize: vertical; min-height: 62px; }
select.inp { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--ink-400) 50%), linear-gradient(135deg, var(--ink-400) 50%, transparent 50%); background-position: calc(100% - 15px) 52%, calc(100% - 10px) 52%; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; padding-right: 28px; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 14px; }
.grid4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0 14px; }
@media (max-width: 900px) { .grid3, .grid4 { grid-template-columns: 1fr 1fr; } }
@media (max-width: 620px) { .grid2, .grid3, .grid4 { grid-template-columns: 1fr; } }
.form-section { border-top: 1px dashed var(--line); margin: 18px 0 14px; padding-top: 14px; }
.form-section:first-child { border-top: none; margin-top: 0; padding-top: 0; }
.form-section h4 { font-size: 13.5px; color: var(--blue-700); display: flex; align-items: center; gap: 7px; margin-bottom: 12px; }
.form-section h4::before { content: ""; width: 3px; height: 14px; border-radius: 2px; background: var(--blue-600); }

/* ============ 弹层 ============ */
.mask { position: fixed; inset: 0; background: rgba(15,23,42,.45); display: none; align-items: center; justify-content: center; z-index: 200; padding: 20px; }
.mask.on { display: flex; }
.modal { background: #fff; border-radius: 12px; width: 100%; max-width: 620px; max-height: 92vh; display: flex; flex-direction: column; box-shadow: var(--shadow-3); overflow: hidden; }
.modal.wide { max-width: 900px; }
.modal.slim { max-width: 440px; }
.modal-hd { padding: 15px 18px; border-bottom: 1px solid var(--line-2); display: flex; align-items: center; gap: 10px; }
.modal-hd h3 { font-size: 16px; }
.modal-hd .x { margin-left: auto; cursor: pointer; color: var(--ink-400); font-size: 20px; line-height: 1; background: none; border: none; }
.modal-hd .x:hover { color: var(--ink-700); }
.modal-bd { padding: 18px; overflow-y: auto; }
.modal-ft { padding: 13px 18px; border-top: 1px solid var(--line-2); display: flex; gap: 10px; justify-content: flex-end; background: #fbfcfe; }

/* ============ 提示 ============ */
.toasts { position: fixed; top: 68px; right: 20px; z-index: 400; display: flex; flex-direction: column; gap: 9px; }
.toast { background: #fff; border: 1px solid var(--line); border-left: 4px solid var(--blue-600); padding: 11px 15px; border-radius: 8px; box-shadow: var(--shadow-2); font-size: 13.5px; min-width: 220px; max-width: 380px; animation: slidein .22s ease-out; }
.toast.ok { border-left-color: var(--ok); } .toast.bad { border-left-color: var(--bad); } .toast.warn { border-left-color: var(--warn); }
@keyframes slidein { from { opacity: 0; transform: translateX(18px); } to { opacity: 1; transform: none; } }
.alert { padding: 10px 14px; border-radius: 8px; font-size: 13.5px; margin-bottom: 14px; border: 1px solid; }
.alert.bad { background: var(--bad-bg); border-color: #f7d4d4; color: #9c1f1f; }
.alert.info { background: var(--blue-50); border-color: var(--blue-100); color: var(--blue-800); }
.alert.warn { background: var(--warn-bg); border-color: #f6e2bd; color: #8a5300; }
.alert.ok { background: var(--ok-bg); border-color: #cdeedb; color: #14663a; }
.empty { text-align: center; color: var(--ink-400); padding: 42px 10px; font-size: 13.5px; }

/* ============ 分页 / 工具条 ============ */
.pager { display: flex; gap: 6px; align-items: center; padding: 13px 16px; flex-wrap: wrap; }
.pager a, .pager span { min-width: 32px; height: 30px; padding: 0 9px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--line); border-radius: 6px; font-size: 13px; background: #fff; color: var(--ink-600); }
.pager a:hover { border-color: var(--blue-200); color: var(--blue-700); background: var(--blue-50); }
.pager .on { background: var(--blue-600); border-color: var(--blue-600); color: #fff; }
.pager .info { border: none; background: none; color: var(--ink-400); }
.toolbar { display: flex; gap: 9px; align-items: center; flex-wrap: wrap; }
.toolbar .spacer { margin-left: auto; }
.toolbar .inp, .toolbar select.inp { width: auto; min-width: 118px; }
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; background: #fff; }
.seg a { padding: 6px 14px; font-size: 13.5px; color: var(--ink-600); border-right: 1px solid var(--line); }
.seg a:last-child { border-right: none; }
.seg a.on { background: var(--blue-50); color: var(--blue-700); font-weight: 600; }

/* ============ 档案页 ============ */
.detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 26px; }
@media (max-width: 820px) { .detail-grid { grid-template-columns: 1fr; } }
.dl { display: grid; grid-template-columns: 116px 1fr; gap: 0; font-size: 13.5px; }
.dl dt { color: var(--ink-500); padding: 6px 0; font-size: 12.5px; }
.dl dd { margin: 0; padding: 6px 0; color: var(--ink-800); word-break: break-word; }
.dl dd .tag { vertical-align: middle; }
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); padding: 0 16px; background: #fbfcff; flex-wrap: wrap; }
.tabs button { border: none; background: none; padding: 11px 14px; font-size: 13.5px; color: var(--ink-600); cursor: pointer; font-family: inherit; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.tabs button.on { color: var(--blue-700); font-weight: 600; border-bottom-color: var(--blue-600); }
.tab-pane { display: none; }
.tab-pane.on { display: block; }
.timeline { padding: 4px 0; }
.tl-item { position: relative; padding: 0 0 16px 20px; border-left: 2px solid var(--line); margin-left: 6px; }
.tl-item:last-child { border-left-color: transparent; padding-bottom: 0; }
.tl-item::before { content: ""; position: absolute; left: -6px; top: 5px; width: 10px; height: 10px; border-radius: 50%; background: var(--blue-600); border: 2px solid #fff; box-shadow: 0 0 0 2px var(--blue-100); }
.tl-item .hd { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.tl-item .dt { font-size: 12px; color: var(--ink-500); font-variant-numeric: tabular-nums; }
.tl-item .bd { font-size: 13px; color: var(--ink-700); margin-top: 3px; line-height: 1.8; }

/* ============ 保藏位置卡 ============ */
.pos-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; }
.pos { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px 13px; background: #fff; }
.pos .top { display: flex; align-items: center; gap: 8px; }
.pos .top .nm { font-weight: 600; font-size: 13.5px; color: var(--ink-900); }
.pos .top .spacer { margin-left: auto; }
.pos .path { font-size: 12.5px; color: var(--blue-700); background: var(--blue-50); border: 1px solid var(--blue-100); border-radius: 6px; padding: 6px 9px; margin: 9px 0; line-height: 1.7; word-break: break-all; }
.pos .meta { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 12.5px; color: var(--ink-600); }
.pos .meta b { color: var(--ink-800); font-weight: 600; }

/* ============ 图表（纯 CSS 条形，无需外部库） ============ */
.bars { display: flex; flex-direction: column; gap: 9px; }
.bar-row { display: grid; grid-template-columns: 108px 1fr 62px; gap: 10px; align-items: center; font-size: 13px; }
/* 标签列固定宽度以保证各行条形起点对齐；标签过长时换行显示，绝不省略号截断
   （单位名称动辄 10 字以上，截断后等于看不见到底是哪一家） */
.bar-row .nm { color: var(--ink-700); text-align: right; line-height: 1.4; word-break: break-word; }
.bar-row .track { background: var(--muted-bg); border-radius: 5px; height: 20px; overflow: hidden; }
.bar-row .fill { height: 100%; border-radius: 5px; background: linear-gradient(90deg, var(--blue-500), var(--blue-700)); min-width: 3px; transition: width .4s; }
.bar-row .vl { font-variant-numeric: tabular-nums; color: var(--ink-600); }
.bar-row .fill.g2 { background: linear-gradient(90deg, #22c55e, #15803d); }
.bar-row .fill.g3 { background: linear-gradient(90deg, #f59e0b, #b45309); }
.bar-row .fill.g4 { background: linear-gradient(90deg, #8b5cf6, #6d28d9); }
.bar-row .fill.g5 { background: linear-gradient(90deg, #06b6d4, #0e7490); }

/* ============ 登录页 ============ */
.login-page { min-height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #0f2a5e 0%, #1d4ed8 55%, #3b82f6 100%); padding: 24px; }
.login-shell { width: 100%; max-width: 900px; background: #fff; border-radius: 14px; overflow: hidden; display: grid; grid-template-columns: 1fr 390px; box-shadow: 0 22px 60px rgba(6,22,56,.38); }
@media (max-width: 820px) { .login-shell { grid-template-columns: 1fr; max-width: 420px; } .login-side { display: none !important; } }
.login-side { background: linear-gradient(150deg, #12306b 0%, #1d4ed8 100%); color: #fff; padding: 36px 32px; }
.login-side h1 { color: #fff; font-size: 22px; line-height: 1.45; letter-spacing: .4px; }
.login-side .sub { color: rgba(255,255,255,.78); font-size: 13px; margin-top: 10px; line-height: 1.9; }
.login-side .stats { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; margin-top: 26px; }
.login-side .st { background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.18); border-radius: 9px; padding: 10px 12px; }
.login-side .st b { display: block; font-size: 21px; font-weight: 700; }
.login-side .st span { font-size: 12px; color: rgba(255,255,255,.8); }
.login-side .flow { margin-top: 24px; font-size: 12.5px; color: rgba(255,255,255,.82); line-height: 2; }
.login-side .flow i { color: #8fc0ff; font-style: normal; }
.login-form { padding: 38px 34px; display: flex; flex-direction: column; justify-content: center; }
.login-form h2 { font-size: 19px; margin-bottom: 4px; }
.login-form .tip { color: var(--ink-500); font-size: 12.5px; margin-bottom: 20px; }
.login-form .inp { padding: 10px 12px; font-size: 14px; }
.login-form .btn.primary { width: 100%; padding: 11px; font-size: 15px; margin-top: 5px; }
.login-foot { margin-top: 18px; text-align: center; font-size: 12px; color: var(--ink-400); line-height: 1.9; }
.login-form .row { display: flex; align-items: center; justify-content: space-between; font-size: 12.5px; color: var(--ink-500); margin-bottom: 14px; }
.login-form .row label { display: flex; align-items: center; gap: 5px; cursor: pointer; }

/* ============ 标签打印 ============ */
.label-sheet { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
@media (max-width: 900px) { .label-sheet { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .label-sheet { grid-template-columns: 1fr; } }
.label-card { border: 1px dashed var(--line); border-radius: 8px; padding: 10px; background: #fff; display: flex; gap: 10px; align-items: center; }
.label-card .qr { flex: 0 0 auto; }
.label-card .qr svg { display: block; width: 74px; height: 74px; }
.label-card .info { min-width: 0; flex: 1; }
.label-card .info .t { font-size: 13.5px; font-weight: 600; color: var(--ink-900); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.label-card .info .c { font-size: 12px; color: var(--ink-500); font-family: ui-monospace, Consolas, monospace; }
.label-card .info .m { font-size: 11.5px; color: var(--ink-500); margin-top: 3px; }

/* ============ 指标竖柱（12 个月趋势的紧凑表达） ============
   为什么不用「12 行横条」：横条每行 20px + 9px 间距 = 29px，12 行要 348px，
   在「一屏模式」下必然把卡片撑破。竖柱的高度是自适应的，且趋势读起来更直观。
   柱子用绝对定位 + 百分比高度：父元素是 flex 分配的确定高度，
   绝对定位的百分比才不会退化成 0（这是 flex 子项百分比高度的可靠写法）。 */
.mbars { display: grid; grid-template-columns: repeat(12, 1fr); gap: 5px; height: 100%; min-height: 92px; }
.mb { display: flex; flex-direction: column; min-width: 0; }
.mb-track { position: relative; flex: 1 1 auto; min-height: 36px; }
.mb-track i {
    position: absolute; left: 0; right: 0; bottom: 0; min-height: 2px;
    background: linear-gradient(180deg, var(--blue-500), var(--blue-700));
    border-radius: 3px 3px 0 0; transition: height .4s;
}
.mb-vl { font-size: 11px; color: var(--ink-500); text-align: center; line-height: 1.5; font-variant-numeric: tabular-nums; }
.mb-lb { font-size: 10px; color: var(--ink-400); text-align: center; line-height: 1.4; }

/* ============ 一屏模式（数据总览） ============
   ★★★ 2026-10-01 张总要求：「后台数据总览，内容显示在一屏内，减少鼠标上下滚动」。
   做法是把主区高度锁死为「视口 − 顶栏」，三块网格用 flex 各分 1/3，
   页面本身永远不出现纵向滚动条。三个边界必须一起处理，否则会得到"比原来还差"的结果：
     1) grid2/grid3 在 HTML 里带着 inline 的 margin-top:16px;gap:16px，
        CSS 类选择器压不过 inline，必须用 !important 才能收回那 32px；
     2) 卡片要变成 flex 容器（头固定 + 体自适应），否则内部内容一多变高、把外层顶破；
     3) 卡片体留 overflow:auto 作为兜底 —— 正常数据量下不会出现滚动条，
        只在极端情况（某类数据突然爆量）下才启用，避免内容被硬裁掉。
   只在「够宽且够高」时启用：窄屏/矮屏（笔记本竖屏、手机）仍走原来的流式布局，
   否则一屏模式会把内容压成一条条看不见字。 */
@media (min-width: 1150px) and (min-height: 700px) {
    body.screen-fit .main { height: calc(100vh - var(--nav-h)); padding: 14px 20px; overflow: hidden; }
    body.screen-fit .wrap { height: 100%; display: flex; flex-direction: column; gap: 9px; }
    body.screen-fit .page-head { flex: 0 0 auto; margin-bottom: 0; align-items: center; }
    body.screen-fit .alert { flex: 0 0 auto; margin-bottom: 0; }

    body.screen-fit .kpis { flex: 0 0 auto; gap: 11px; }
    body.screen-fit .grid2,
    body.screen-fit .grid3 { flex: 1 1 0; min-height: 0; gap: 11px !important; margin-top: 0 !important; }
    body.screen-fit .grid2 > *,
    body.screen-fit .grid3 > * { min-width: 0; height: 100%; }
    body.screen-fit .grid2 > .card,
    body.screen-fit .grid3 > .card { margin-top: 0; height: 100%; display: flex; flex-direction: column; overflow: hidden; }

    body.screen-fit .card-hd { flex: 0 0 auto; padding: 7px 14px; }
    body.screen-fit .card-bd { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 10px 14px; }
    body.screen-fit .card-bd.tight { padding: 0; }

    /* 只压留白与柱条高度，正文与表头字号一律不动 —— 总览是上机场景，
       字号再压就影响读数，而留白压缩几乎不损失可读性。 */
    body.screen-fit .kpi { padding: 8px 13px; }
    body.screen-fit .kpi .val { font-size: 23px; }
    body.screen-fit .kpi .foot { font-size: 11.5px; }
    body.screen-fit .bars { gap: 3px; }
    body.screen-fit .bar-row { font-size: 12.5px; }
    body.screen-fit .bar-row .track { height: 15px; }
    body.screen-fit .tbl th { padding: 4px 10px; }
    body.screen-fit .tbl td { padding: 4px 10px; }
    body.screen-fit .tbl.one-line td { padding: 4px 10px; }
}

/* ============ 移动端适配 ============
   ★★★ 2026-10-01 补：线上首次部署后实测，390px 视口下 dashboard 的文档宽度是
   **749px**、strains 473px、档案页 459px —— 三页全部横向滚动，手机上必须左右拖着看。
   根因：全站只有 kpis/grid2/detail-grid/label-sheet 这几处降列，**没有任何一条规则
   处理固定 216px 的侧栏**；而 .main 是 `margin-left: var(--side-w)`，
   于是在 390px 屏幕上主区只剩 390−216−40 = 134px，栅格子项再被 min-content 顶开。
   （当时那版渲染验收只断言了「HTTP 200 + 无 JS 报错」，所以这个缺陷一路全绿通过。）
   下面这层只改 CSS：DOM 顺序本来就是 nav → side → main，
   把侧栏在窄屏改成 static 就自然落到顶栏下方，不需要动任何 JS/HTML。
   ========================================================================== */
@media (max-width: 820px) {
    /* 侧栏宽度归零 —— 这是整层适配的支点 */
    :root { --side-w: 0px; }

    /* 顶栏：窄屏放不下的元素一律收起。
       原来「品牌副标题 + 统一门户 + 姓名/角色」会把 56px 的顶栏撑到 78px（溢出 22px）。 */
    .nav { padding: 0 12px; gap: 8px; }
    .nav .brand { font-size: 14.5px; }
    .nav .brand small { display: none; }
    .nav .plat { display: none; }
    .nav .right { gap: 8px; }
    .nav .right .who { display: none; }
    .nav .btn-ghost { padding: 5px 11px; font-size: 12.5px; }

    /* 侧栏：由「固定竖条」改为「顶栏下方的横向可滚动导航条」——功能不减，
       只是把纵向列表摊平成一行。分组标题与版本页脚在横条里没有意义，隐藏。 */
    .side {
        position: static; width: auto; height: auto; margin-top: var(--nav-h);
        display: flex; align-items: center; gap: 6px;
        padding: 8px 12px; border-right: none; border-bottom: 1px solid var(--line);
        overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .side::-webkit-scrollbar { display: none; }
    .side .grp, .side .foot { display: none; }
    .side a { flex: 0 0 auto; margin-bottom: 0; white-space: nowrap; padding: 7px 12px; font-size: 13px; }
    .side a .badge { display: none; }

    /* 主区：取消左侧留白。顶栏高度已由 .side 的 margin-top 承担，此处不再叠加 */
    .main { margin-left: 0; padding: 14px 12px 40px; }
    .wrap { max-width: 100%; }

    /* 栅格子项允许收缩 —— 否则 min-content 会把格子顶宽，又撑出横向滚动条 */
    .kpi, .grid2 > *, .grid3 > * { min-width: 0; }
    .card-bd { padding: 13px; }
    .page-head h2 { font-size: 17.5px; }
    .dl { grid-template-columns: 96px 1fr; }
    .dl dt { font-size: 12px; }
    .tabs { padding: 0 10px; }
    .tabs button { padding: 10px 11px; font-size: 13px; }
    .bar-row { grid-template-columns: 84px 1fr 52px; gap: 8px; font-size: 12.5px; }
    .form-section h4 { font-size: 13px; }

    /* 表格：给单元格设最小宽度，让超宽表格改由 .tbl-wrap 横向滚动，
       而不是把每一列都压成一字一行。
       实测（2026-10-01，390px）：不加这条时菌株台账的「CS-XY-2610-0001」折成 3 行、
       「线上验收临时菌株」折成 3 行、种类「蜜环菌」也折成 3 行；
       保藏临期表的「位置」列（一号冷藏冰箱 / 冻存盒01 / 第5行第8列）更被压到一行两个字。
       .tbl-wrap 本来就是 overflow-x:auto，让表格在框内横滚才是它存在的意义。 */
    .tbl-wrap > table.tbl th,
    .tbl-wrap > table.tbl td { min-width: 74px; }
    .tbl-wrap > table.tbl th:first-child,
    .tbl-wrap > table.tbl td:first-child { min-width: 104px; }
    /* 横向滚动条做成细样式，避免在窄屏上占掉一行高度 */
    .tbl-wrap::-webkit-scrollbar { height: 5px; }
    .tbl-wrap::-webkit-scrollbar-thumb { background: #c9d4e6; border-radius: 3px; }

    /* ★ 总览页那三张「单行列表」在手机上必须放行换行。
       它们是为桌面一屏模式设计的 nowrap 结构：不换行就把 390px 视口撑到 470px，
       文档级横向滚动条立刻出现（实测 dashboard 470 vs 390）。
       一屏模式只在 min-width:1150px 生效，手机上本来就与它无关，
       所以这里直接恢复自然换行即可 —— 桌面行为不受影响。
       注意特异性：`.tbl.one-line td`(0,2,1) 高于 `.nowrap`(0,1,0)，
       写在这里能真的压过内联类，无需 !important。 */
    .tbl.one-line td { white-space: normal; }
    .ellip { max-width: none; white-space: normal; }
}

/* 更窄机型（微信内嵌浏览器常见 360px）：KPI 缩小一号，避免数字被挤断换行 */
@media (max-width: 420px) {
    .kpi { padding: 12px; }
    .kpi .val { font-size: 22px; }
    .kpi .lab { font-size: 12px; }
    .login-page { padding: 14px; }
    .login-form { padding: 28px 20px; }
}

@media print {
    .nav, .side, .no-print, .toasts { display: none !important; }
    .main { margin: 0; padding: 0; }
    body { background: #fff; }
    .label-sheet { grid-template-columns: repeat(3, 1fr); gap: 4px; }
    .label-card { border: 1px solid #999; page-break-inside: avoid; }
    .card { border: none; box-shadow: none; }
}
