/* ============================================================
    排座系统 · 界面样式
    设计语言：浅灰蓝底 + 白色圆角卡片 + 现代蓝主色 + 轻阴影
    全局约束：.planBox ol 的边框保持 1px、不加内边距 —— 拖拽的坐标换算依赖它
    目录：设计令牌 → 基础 → 图标 → 顶部工具条 → 搜索 → 列设置 →
    名单区 → 排座区（工具条/批量桌椅/排/本排设置/单元格/操作浮层/端区）→
    拖拽占位与插入指示 → 座椅 → 走廊条 → 桌面 → 拖动期抑制 →
    模式提示/轻提示 → 确认弹窗 → 展示模式 → 打印
    ============================================================ */

/* ---------- 设计令牌 ---------- */
:root{
    --font:"Segoe UI","PingFang SC","Microsoft YaHei UI","Microsoft YaHei",system-ui,-apple-system,sans-serif;
    --bg:#f2f5fa;
    --surface:#ffffff;
    --surface-2:#f6f8fc;
    --line:#e5eaf2;
    --line-2:#cbd5e3;
    --ink:#16233b;
    --ink-2:#5a6a82;
    --ink-3:#93a1b5;
    --accent:#2563eb;
    --accent-deep:#1a4fd6;
    --accent-soft:#eaf1ff;
    --danger:#d3382f;
    --danger-soft:#fdeeee;
    --ok:#178a50;
    --ok-soft:#e7f6ee;
    --amber:#d9a441;
    --r-lg:14px;
    --r-md:9px;
    --r-sm:6px;
    --sh-1:0 1px 2px rgba(23,36,61,.05),0 2px 6px rgba(23,36,61,.05);
    --sh-2:0 10px 28px rgba(23,36,61,.16),0 2px 8px rgba(23,36,61,.08);
    /* 行色带：极淡的明暗交替 */
    --tint:#fcfdff; --edge:#e2e8f1;
}

/* ---------- 基础 ---------- */
[v-cloak]{display:none;}
body{margin: 0 auto 4em;min-width: 1280px;width: fit-content;background: linear-gradient(180deg,#edf1f8,var(--bg) 320px);color: var(--ink);font-family: var(--font);font-size: 13px;}
ul {list-style: none;padding: 0;text-align: center;}
input,select,textarea{font: inherit;color: var(--ink);background: var(--surface);border: 1px solid var(--line-2);border-radius: var(--r-sm);padding: 3px 8px;height: 28px;box-sizing: border-box;vertical-align: middle;transition: border-color .12s, box-shadow .12s;}
input:hover,select:hover,textarea:hover{border-color: var(--accent);}
input:focus,select:focus,textarea:focus{outline: none;border-color: var(--accent);box-shadow: 0 0 0 3px var(--accent-soft);}
select{padding: 3px 4px;}
textarea{height: auto;padding: 10px 12px;line-height: 1.8;}
input[type=number]{width: 52px;text-align: center;font-variant-numeric: tabular-nums;}
input[type=checkbox],input[type=radio]{height: auto;accent-color: var(--accent);}
button{font: inherit;font-size: 12px;line-height: 1;white-space: nowrap;min-width: 26px;height: 26px;padding: 0 9px;border: 1px solid var(--line-2);border-radius: var(--r-sm);background: var(--surface);color: var(--ink);cursor: pointer;transition: background-color .12s,border-color .12s,color .12s,box-shadow .12s,transform .06s;}
button:hover{border-color: var(--accent);color: var(--accent);background: var(--accent-soft);}
button:active{transform: translateY(1px);}
button:focus-visible{outline: 2px solid var(--accent);outline-offset: 1px;}
button:disabled{opacity: .38;cursor: not-allowed;border-color: var(--line);background: var(--surface-2);color: var(--ink-3);transform: none;box-shadow: none;}
.danger:hover{border-color: var(--danger);color: var(--danger);background: var(--danger-soft);}
/* 主次按钮分级：只有 .primary 是深蓝主色，其余为次级；.danger 常态即红字 */
.planToolbar button,.actionArea .button button,.unreserved .button .group button{font-size: 13px;height: 29px;}
.planToolbar .primary,.actionArea .button .primary,.unreserved .button .group .primary{background: linear-gradient(180deg,#3b74f0,var(--accent));border-color: var(--accent-deep);color: #fff;box-shadow: 0 1px 2px rgba(37,99,235,.35);}
.planToolbar .primary:hover,.actionArea .button .primary:hover,.unreserved .button .group .primary:hover{background: linear-gradient(180deg,#2f66e8,var(--accent-deep));color: #fff;border-color: var(--accent-deep);}
.settingChild .danger,.endZone .danger,.lineSetting .danger,.topBar .danger{color: var(--danger);}

/* ---------- 图标（data-ico） ---------- */
/* 字形直接写在元素的 data-ico 属性上（如 data-ico="⚙"），CSS 只负责用 attr() 取出来 + 排版，
    加图标时不用再写一堆 content 规则。统一挑 Segoe UI Symbol 里的单色符号（避开彩色 emoji），
    与原本就在用的 ⚙（排设置）、✎（行尾）是同一套风格。
    范围：只给主界面（顶栏、名单区、场地工具条、弹窗、分区标题）加；
    单个字的按钮（锁 / 删 / 加 / 收）和所有悬停浮层（齿轮菜单、座 / 桌浮层、行尾面板）都不加——小面板会被撑宽显得乱 */
[data-ico]::before{content: attr(data-ico);display: inline-block;margin-right: 4px;font-size: 1.08em;line-height: 1;vertical-align: -1px;opacity: .8;transition: opacity .12s;}
[data-ico]:hover::before{opacity: 1;}
/* 开关按钮（桌条 / 详细信息 / 展示模式）的 ::before 已经被状态圆点占用了：图标放前面，圆点改到 ::after */
.planBox .planToolbar .toggle[data-ico]::before{content: attr(data-ico);width: auto;height: auto;border-radius: 0;background: none;margin-right: 5px;vertical-align: -1px;}
.planBox .planToolbar .toggle[data-ico]::after{content: "";display: inline-block;width: 7px;height: 7px;border-radius: 50%;background: var(--line-2);margin-left: 6px;vertical-align: 1px;transition: background-color .12s;}
.planBox .planToolbar .toggle[data-ico].on::after{background: var(--accent);}

/* ---------- 顶部工具条（整条不悬浮：随页面滚走；只有搜索框 fixed 留在顶部） ---------- */
/* 本条不能加 backdrop-filter —— 它会给 fixed 后代当包含块，里面的搜索框就跟着顶栏一起滚走了 */
.topBar{margin: 14px auto 0;width: 1280px;box-sizing: border-box;padding: 10px 16px;display: flex;align-items: center;gap: 12px;background: rgba(255,255,255,.94);border: 1px solid var(--line);border-radius: var(--r-lg);box-shadow: var(--sh-1);}
.topBar h1{display: flex;align-items: center;gap: 10px;font-size: 16px;margin: 0;font-weight: 700;letter-spacing: .03em;}
.topBar h1::before{content: "座";width: 26px;height: 26px;border-radius: 8px;background: linear-gradient(135deg,#3b74f0,var(--accent-deep));color: #fff;font-size: 13px;font-weight: 700;display: inline-flex;align-items: center;justify-content: center;box-shadow: 0 2px 6px rgba(37,99,235,.35);}
.topBar .saveState{font-size: 12px;color: var(--ink-2);margin-right: auto;padding: 3px 10px;border-radius: 999px;background: var(--surface-2);}
.topBar .saveState.saved{color: var(--ok);background: var(--ok-soft);}
.topBar .saveState.waiting{color: var(--accent);background: var(--accent-soft);}
.topBar .saveState.error,.topBar .saveState.off{color: var(--danger);background: var(--danger-soft);}
.topBar .tools{display: flex;align-items: center;padding-right: 12px;border-left: 1px solid var(--line);}
.topBar .tools button{height: 30px;padding: 0 11px;border-radius: 8px;font-size: 13px;border-color: transparent;background: transparent;color: var(--ink-2);}
.topBar .tools button:hover{background: var(--accent-soft);color: var(--accent);border-color: transparent;}
.topBar .tools button:disabled:hover{background: transparent;}
.topBar .tools .danger{color: var(--danger);}
.topBar .tools .danger:hover{background: var(--danger-soft);color: var(--danger);}
.topBar .file{display: inline-flex;align-items: center;height: 30px;padding: 0 11px;font-size: 13px;border-radius: 8px;border: 1px solid transparent;background: transparent;color: var(--ink-2);cursor: pointer;transition: background-color .12s,color .12s;}
.topBar .file input{display: none;}
.topBar .file:hover{background: var(--accent-soft);color: var(--accent);}

/* ---------- 搜索：页面里唯一悬浮的常驻元素（fixed 定在顶栏右端、与按钮同高） ----------
    查找框挂在顶栏外（展示模式也保留），本身 fixed 所以视觉与挂在顶栏里时一致。
    top 24 = 顶栏 margin-top 14 + padding 10；right 与顶栏内容区右边缘（内边距 16）对齐，
    窗口比 1280 窄时退化为贴视口右 12px。z-index 28：高于页内所有浮层（最高 6），
    低于批量弹层遮罩 popMask(29)，弹层打开时点它照样算「点外关闭」。 ---------- */
.search{position: fixed;top: 24px;right: max(12px,calc(50% - 624px));z-index: 28;display: flex;align-items: center;gap: 6px;height: 30px;width: 168px;box-sizing: border-box;padding: 0 12px 0 8px;border: 1px solid var(--line);border-radius: 999px;background: rgba(255,255,255,.94);backdrop-filter: blur(10px);box-shadow: var(--sh-1);transition: border-color .12s,box-shadow .12s,background-color .12s;}
.search::before{content: "查";flex: 0 0 auto;width: 20px;height: 20px;line-height: 20px;text-align: center;border-radius: 50%;background: var(--accent-soft);color: var(--accent);font-size: 11px;font-weight: 700;}
.search:focus-within{border-color: var(--accent);background: #fff;box-shadow: 0 0 0 3px var(--accent-soft);}
.search .searchName{flex: 1 1 auto;width: auto;min-width: 0;height: 26px;font-size: 12px;border: 0;background: transparent;padding: 0 2px;box-shadow: none;}
.search .searchName:hover,.search .searchName:focus{border: 0;box-shadow: none;}
/* 查找候选下拉：锚定胶囊下方右缘，比胶囊宽一点放得下「第N排 M号」；打印/展示随胶囊开关 */
.searchPop{position: absolute;top: calc(100% + 6px);right: 0;width: 236px;max-height: 50vh;overflow: auto;margin: 0;padding: 4px;list-style: none;background: rgba(255,255,255,.98);border: 1px solid var(--line);border-radius: 10px;box-shadow: var(--sh-2);}
.searchPop li{display: flex;align-items: center;justify-content: space-between;gap: 10px;padding: 6px 10px;border-radius: 7px;font-size: 13px;cursor: pointer;}
.searchPop li:hover{background: var(--accent-soft);}
.searchPop li .name{min-width: 0;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}
.searchPop li .pos{flex: 0 0 auto;font-size: 12px;color: var(--ink-2);}
.searchPop li.off{cursor: default;justify-content: center;color: var(--ink-2);}
.searchPop li.off:hover{background: none;}

/* ---------- 列设置 ---------- */
.columnPanel{margin: 12px auto 0;width: 1280px;padding: 10px 14px;box-sizing: border-box;background: var(--surface);border: 1px solid var(--line);border-radius: var(--r-lg);box-shadow: var(--sh-1);display: flex;align-items: center;gap: 10px;flex-wrap: wrap;}
.columnPanel .colChips{display: flex;align-items: center;gap: 8px;flex-wrap: wrap;}
.columnPanel .colChip{display: flex;align-items: center;gap: 6px;padding: 4px 9px;background: var(--surface-2);border: 1px solid var(--line-2);border-radius: var(--r-md);cursor: grab;transition: border-color .12s,box-shadow .12s;font-size: 13px;}
.columnPanel .colChip:hover{border-color: var(--accent);}
.columnPanel .colChip.ready{border-color: var(--accent);box-shadow: 0 0 0 3px var(--accent-soft);}
.columnPanel .colChip.dragging{opacity: .4;}
.columnPanel .colChip .label{text-wrap: nowrap;}
.columnPanel .colChip .move{display: inline-block;width: 1.2em;height: 1.2em;background: url(../assets/move.png) center / auto 1em no-repeat;cursor: grab;transform: rotate(90deg);}
.columnPanel .colChip input{width: 6em;height: 24px;padding: 0 2px;text-align: center;border: 0;border-bottom: 1px dashed transparent;border-radius: 0;background: transparent;font-size: 13px;}
.columnPanel .colChip input:hover{border-bottom-color: var(--line-2);}
.columnPanel .colChip input:focus{outline: none;border-bottom: 1px solid var(--accent);box-shadow: none;}
.columnPanel .colChip .del{display: inline-block;width: 1.15em;height: 1.15em;vertical-align: -3px;cursor: pointer;background: url(../assets/delLine.png) center / contain no-repeat;transition: transform .12s;}
.columnPanel .colChip .del:hover{transform: scale(1.2);}
.columnPanel .colChip .del.off{opacity: .2;cursor: not-allowed;}
.columnPanel .addCol{height: 30px;}
.columnPanel .hint{font-size: 12px;color: var(--ink-3);}

/* ---------- 名单区（输入 + 名单 两张卡片） ---------- */
.infoCenter{margin: 12px auto;width: 1280px;padding: 0;background: none;border: 0;box-shadow: none;overflow: visible;display: flex;justify-content: space-between;gap: 14px;}
.infoCenter .actionArea{width: 100%;box-sizing: border-box;background: var(--surface);border: 1px solid var(--line);border-radius: var(--r-lg);box-shadow: var(--sh-1);padding: 14px;}
.infoCenter .actionArea textarea{display: block;width: 100%;height: 20em;border-radius: var(--r-md);box-sizing: border-box;white-space: pre;font-size: 13px;font-family: var(--font);color: var(--ink);background: var(--surface-2);resize: vertical;scrollbar-width: thin;scrollbar-color: var(--line-2) transparent;transition: border-color .12s, box-shadow .12s;}
.infoCenter .actionArea textarea:focus,.infoCenter .unreserved .displayArea:focus-within{outline: none;border-color: var(--accent);box-shadow: 0 0 0 3px var(--accent-soft);}
.infoCenter .button{margin: 10px 0 0;text-align: right;display: flex;align-items: center;justify-content: space-between;}
.infoCenter .button span{font-size: 13px;font-weight: 600;color: var(--ink-2);display: flex;align-items: center;}
.infoCenter .button .group{display: flex;align-items: center;gap: 6px;}
.infoCenter .unreserved{width: 100%;box-sizing: border-box;background: var(--surface);border: 1px solid var(--line);border-radius: var(--r-lg);box-shadow: var(--sh-1);padding: 14px;}
.infoCenter .unreserved .displayArea{width: 100%;height: 20em;overflow: auto;box-sizing: border-box;background: var(--surface);border: 1px solid var(--line);border-radius: var(--r-md);padding: 0;scrollbar-width: thin;scrollbar-color: var(--line-2) transparent;transition: border-color .12s,box-shadow .12s;}
.infoCenter .unreserved ul{display: flex;justify-content: flex-start;flex-wrap: wrap;margin: 0;padding: 10px;}
.infoCenter .unreserved li{border: 1px solid var(--line-2);position: relative;min-width: 3em;margin: 4px;border-radius: var(--r-md);padding: 3px 9px;background: var(--surface);font-size: 13px;cursor: grab;box-shadow: 0 1px 2px rgba(23,36,61,.06);transition: box-shadow .12s,border-color .12s;}
.infoCenter .unreserved li:hover{border-color: var(--accent);box-shadow: 0 2px 8px rgba(23,36,61,.12);}
.infoCenter .unreserved li i{font-style: normal;color: var(--ink-3);font-size: 11px;margin-left: 3px;font-variant-numeric: tabular-nums;}
.infoCenter .unreserved li.prohibit{opacity: .45;cursor: grab;box-shadow: none;}
.infoCenter .unreserved .more{position: absolute;left: 0;top: 100%;width: max-content;max-width: 20em;text-wrap: nowrap;background: var(--surface);color: var(--ink);font-size: 12px;line-height: 1.6;display: none;padding: 7px 10px;text-align: left;z-index: 4;border: 1px solid var(--line);border-radius: var(--r-md);box-shadow: var(--sh-2);}
.infoCenter .unreserved li:hover .more,.infoCenter .unreserved li.hoverHold .more{display:block;}
.infoCenter .unreserved table{min-width: 100%;border-collapse: collapse;font-size: 13px;}
.infoCenter .unreserved table thead th{position: sticky;top: 0;z-index: 2;background: var(--surface-2);color: var(--ink-2);font-weight: 600;font-size: 12px;text-align: left;padding: 8px 9px;box-shadow: inset 0 -1px 0 var(--line-2);white-space: nowrap;}
.infoCenter .unreserved table tr{position: relative;}
.infoCenter .unreserved table tr:hover{background: #e0e7fd!important;}
.infoCenter .unreserved table tbody tr:nth-child(2n){background: var(--accent-soft);}
.infoCenter .unreserved table td{border: 0;border-bottom: 1px solid var(--line);padding: 6px 9px;text-wrap: nowrap;}
.infoCenter .unreserved table td:nth-child(1){color: var(--ink-2);font-variant-numeric: tabular-nums;text-align: right;}
.infoCenter .unreserved table thead th:nth-child(1){text-align: right;}
.infoCenter .unreserved table td.name{font-weight: 600;}
.infoCenter .unreserved table td input{width: 100%;min-width: 4em;height: 24px;padding: 0 4px;font-size: 13px;}
.infoCenter .unreserved table tr.addRow td{border-bottom: 0;text-align: left;padding: 7px 9px;}
.infoCenter .unreserved table tr.addRow:hover{background: transparent;}
.infoCenter .unreserved table select{height: 22px;width: 56px;font-size: 12px;padding: 0 2px;}
.infoCenter .unreserved table tr[draggable=true]{cursor: grab;}
.infoCenter .unreserved table tr[draggable=true]:hover{background: var(--accent-soft);}
.infoCenter .unreserved table tbody tr.prohibit{background: #f4f6fa;color: var(--ink-3);}
.infoCenter .unreserved table tbody tr.prohibit td{border-bottom-color: #edf0f6;}
/* 拖拽手柄：跟「删」同格（原来单独占首列）；行内块尺寸 + 背景图，紧跟删按钮 */
.infoCenter .unreserved table tbody tr .action .move{display: inline-block;width: 1.1em;height: 1.2em;margin-right: 7px;vertical-align: -3px;background: url(../assets/move.png) center / auto 1em no-repeat;cursor: grab;}
.infoCenter .unreserved table tbody tr .action .del{display: inline-block;width: 1.15em;height: 1.15em;vertical-align: -3px;cursor: grab;background: url(../assets/delLine.png) center / contain no-repeat;transition: transform .12s;}
.infoCenter .unreserved table tbody tr.prohibit .action .del{opacity: 0.2;cursor: not-allowed;}
.infoCenter .unreserved .tag{font-style: normal;font-size: 11px;font-weight: 400;color: var(--ink-2);background: var(--surface-2);border: 1px solid var(--line);border-radius: 999px;padding: 1px 7px;margin-left: 5px;}
/* 列表内拖拽排序：插入位置箭头指示 */
.infoCenter .unreserved table tbody tr.ready{background: var(--accent-soft);}
.infoCenter .unreserved table tr.ready td:first-child::after{content: "";position: absolute;left: -0.5em;top: -0.5em;width: 1em;height: 1em;transform: rotate(45deg);border-top: 2px solid var(--accent);border-right: 2px solid var(--accent);background: var(--surface);z-index: 3;}
.infoCenter .unreserved table tr.ready td:first-child::before{content: "";position: absolute;left: 0;top: -1px;width: 100%;height: 2px;background: var(--accent);}
.infoCenter .unreserved .button{margin-top: 10px;}

/* ---------- 排座区 ---------- */
/* 悬停浮层（座/桌/廊按钮、座位详情、本排齿轮、行尾 ✎）都是 :hover 显隐。
    CSS 的 :hover 一移开就立刻还原，没法延迟；所以每条 :hover 规则都配一条 .hoverHold 孪生规则，
    由 js/utils.js 的 bindHoverHold 在鼠标离开时挂上、1 秒后再摘掉，做到「延迟一秒隐藏」；
    鼠标移到另一个悬停对象上时旧浮层立即摘掉（同一时刻只留一套浮层）。
    新增悬停浮层时，记得同时补 .hoverHold 那条。 */
.planBox{margin: 14px auto 0;--cell-w:4.4em;}
.planBox.details{--cell-w:9.6em;}

/* 场地工具条：布局生成 / 排操作 / 显示开关 / 统计 / 批量桌椅 */
.planBox .planToolbar{position:relative;background: var(--surface);border: 1px solid var(--line);border-radius: var(--r-lg);padding: 10px 14px;box-sizing: border-box;display: flex;align-items: center;gap: 14px;flex-wrap: wrap;box-shadow: var(--sh-1);font-size: 13px;color: var(--ink-2);width: 1280px;margin: 0 auto;}
.planBox .planToolbar .sep{width: 1px;align-self: stretch;background: var(--line);}
.planBox .planToolbar .grp{display: flex;align-items: center;gap: 9px;}
.planBox .planToolbar .title{font-size: 14px;font-weight: initial;letter-spacing: .1em;color: var(--ink-2);line-height: 1;padding: 2px 0;}
.planBox .planToolbar .row{display: flex;align-items: flex-end;gap: 9px;}
.planBox .planToolbar .field{display: flex;flex-direction: column;gap: 4px;align-items: flex-start;}
.planBox .planToolbar .field label{font-size: 11px;line-height: 1;color: var(--ink-3);}
.planBox .planToolbar .field .row{display: inline-flex;gap: 4px;}
.planBox .planToolbar .field input[type=number]{width: 56px;}
.planBox .planToolbar .grp select{font-size: 13px;height: 28px;}
.planBox .planToolbar .gen{padding: 0 16px;font-weight: 600;}
.planBox .planToolbar .toggle{height: 28px;padding: 0 12px;border-radius: 999px;color: var(--ink-2);background: var(--surface-2);}
.planBox .planToolbar .toggle::before{content: "";display: inline-block;width: 7px;height: 7px;border-radius: 50%;background: var(--line-2);margin-right: 6px;vertical-align: 1px;transition: background-color .12s;}
.planBox .planToolbar .toggle.on{background: var(--accent-soft);border-color: var(--accent);color: var(--accent);font-weight: 600;}
.planBox .planToolbar .toggle.on::before{background: var(--accent);}
.planBox .planToolbar .stat, .infoCenter .group .stat{font-size: 12px;color: var(--accent);background: var(--accent-soft);border-radius: 999px;padding: 4px 12px;font-variant-numeric: tabular-nums;font-weight: initial;}

/* 批量桌椅：工具条右侧触发按钮 + 下拉弹层（选完模式弹层收起，按钮保持高亮显示所选模式） */
.planBox .batchWrap{position: relative;margin-left: auto;}
.planBox .batchToggle{height: 28px;padding: 0 13px;border-radius: 999px;color: var(--ink-2);background: var(--surface-2);}
.planBox .batchToggle .caret{font-style: normal;font-size: 10px;margin-left: 5px;color: var(--ink-3);}
.planBox .batchToggle:hover .caret{color: var(--accent);}
.planBox .batchToggle.armed{background: #fdf3df;border-color: var(--amber);color: #9a6b12;font-weight: 600;}
.planBox .batchToggle.armed .caret{color: #c79434;}
.planBox .popMask{position: fixed;inset: 0;z-index: 29;}
.planBox .batchPop{position: absolute;top: calc(100% + 8px);right: 0;z-index: 30;width: 336px;text-align: left;background: var(--surface);border: 1px solid var(--line);border-radius: var(--r-lg);box-shadow: var(--sh-2);padding: 11px;}
.planBox .batchPop .popHead{display: flex;align-items: center;justify-content: space-between;gap: 8px;font-size: 13px;font-weight: 700;color: var(--ink);margin-bottom: 9px;}
.planBox .batchPop .popClose{width: 22px;height: 22px;padding: 0;border: 0;background: transparent;color: var(--ink-3);font-size: 13px;line-height: 1;border-radius: var(--r-sm);}
.planBox .batchPop .popClose:hover{border: 0;background: var(--danger-soft);color: var(--danger);}
.planBox .batchPop .popField{display: flex;align-items: center;gap: 6px;font-size: 12px;color: var(--ink-2);}
.planBox .batchPop .popField input{width: 52px;height: 26px;}
.planBox .batchPop .popDesc{margin: 9px 0 0;font-size: 11px;line-height: 1.5;color: var(--ink-3);}
/* 四个模式排成 2×2，比竖着四条长卡片短一半；box-sizing 与 white-space 必须写——
    按钮全局是 nowrap，不写的话说明文字不换行、把卡片撑得溢出弹层（表现为四个选项戳到弹层外面） */
.planBox .batchPop .popGrid{display: grid;grid-template-columns: 1fr 1fr;gap: 6px;}
.planBox .batchOpt{display: block;box-sizing: border-box;width: 100%;height: auto;padding: 7px 9px;margin: 0;text-align: left;border-radius: var(--r-md);background: var(--surface-2);white-space: normal;}
.planBox .batchOpt b{display: block;font-size: 12.5px;color: var(--ink);white-space: nowrap;}
.planBox .batchOpt i{display: block;font-style: normal;font-size: 11px;color: var(--ink-3);margin-top: 3px;line-height: 1.45;white-space: normal;}
.planBox .batchOpt.armed{background: var(--accent-soft);border-color: var(--accent);}
.planBox .batchOpt.armed b{color: var(--accent);}
.planBox .batchOpt.danger.armed{background: var(--danger-soft);border-color: var(--danger);}
.planBox .batchOpt.danger.armed b{color: var(--danger);}
/* 批量选位中：所有桌块呼吸高亮，点击即定基准列 */
.planBox .desk>li.batchTarget{cursor: pointer;border-color: var(--accent);animation: batchPulse 1.2s ease-in-out infinite;z-index: 1;}
@keyframes batchPulse{0%,100%{box-shadow: 0 0 0 2px var(--accent-soft);}50%{box-shadow: 0 0 0 4px rgba(37,99,235,.28);}}

/* 排（.plan）与行头：排序锁 + 顺序号 */
.planBox .plan{margin: 12px 0 0;}
.planBox .plan>li{margin: 0 0 10px;position: relative;box-sizing: border-box;border: 1px solid var(--edge);border-radius: var(--r-lg);padding: 14px 58px;background: var(--tint);box-shadow: var(--sh-1);transition: box-shadow .15s,border-color .15s;}
.planBox .plan>li:nth-child(2n){--tint:#f7fafd;}
.planBox .plan>li:hover{border-color: #b9cdf2;box-shadow: 0 4px 18px rgba(37,99,235,.10);}
/* SortableJS 整排拖动：拖起时的半透明本体与原位占位 */
.planBox .plan>li.rowChosen{cursor: grabbing;}
.planBox .plan>li.rowGhost{opacity: .35;background: var(--accent-soft);border-color: var(--accent);border-style: dashed;}
/* forceFallback 拖影：跟随鼠标的整排克隆 */
.planBox .plan .rowFallback{opacity: .95;cursor: grabbing;box-shadow: 0 14px 34px rgba(30,58,138,.28);border-color: var(--accent);background: #fff;}
.planBox .plan .rowHead{position:absolute;left:12px;top:0;bottom:0;margin:auto;height:max-content;display:flex;flex-direction:column;align-items:center;gap:4px;}
.planBox .plan .rowHead .rowLock{width:1.9em;height:1.9em;padding:0;line-height:1.6em;border-radius:9px;border:1px solid var(--accent);background:var(--accent-soft);color:var(--accent);font-size:13px;font-weight:700;text-align:center;cursor:pointer;transition:border-color .15s,color .15s,background .15s;}
.planBox .plan .rowHead .rowLock:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-soft);box-shadow:0 0 0 3px var(--accent-soft);}
.planBox .plan .rowHead .rowLock.on{border-color:var(--danger);background:var(--danger);color:#fff;}
.planBox .plan .rowLock:active{transform:scale(.94)}
.planBox .plan .rowHead .number{height:1.9em;min-width:1.9em;margin: 0;padding:0 4px;line-height:calc(1.9em - 2px);border-radius:9px;border:0;background:var(--accent-soft);color:var(--accent);font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;text-align:center;}
.planBox .plan>li.rowGap{margin-top:var(--row-gap);}
.planBox .plan>li.rowGap::before{content:"";position:absolute;left:1px;right:1px;top:calc(var(--row-gap) * -1 + 3px);height:calc(var(--row-gap) - 6px);background:repeating-linear-gradient(-45deg,#e7edf6 0 3px,#f6f9fd 3px 7px);border-top:1px dashed var(--line-2);border-bottom:1px dashed var(--line-2);pointer-events:none;}
.planBox .plan>li.locked{border-style:dashed;}
.planBox .plan>li.locked .settingChild,.planBox .plan>li.locked .endZone,.planBox .plan>li.locked .grip{display:none}
.planBox .plan input[type=number]{width: 40px;}

/* 本排设置：平时只是右侧一枚齿轮，悬停齿轮本身才弹出垂直分组菜单；
    不随整行悬停自动展开——展开层会溢出到相邻排，且与下一排齿轮同为定位元素
    时按 DOM 顺序后者在上，导致下一排齿轮盖住上一排的菜单 */
.planBox .lineSetting{position: absolute;right: 10px;top: 50%;transform: translateY(-50%);width: 30px;height: 30px;margin: 0;padding: 0 4px;text-align: left;z-index: 5;text-wrap: nowrap;box-sizing: border-box;display: flex;flex-direction: column;justify-content: center;align-items: center;gap: 5px;font-size: 12px;color: var(--ink-2);background: var(--surface);border: 1px solid var(--line-2);border-radius: var(--r-md);opacity: .55;box-shadow: var(--sh-1);transition: width .12s,height .12s,opacity .12s;}
.planBox .lineSetting::before{content: "⚙";font-size: 14px;line-height: 1;color: var(--ink-2);}
.planBox .lineSetting>li{display: none;}
.planBox .lineSetting:hover,.planBox .lineSetting.hoverHold{width: fit-content;height: auto;max-width: min(360px, calc(100vw - 140px));padding: 9px;justify-content: flex-start;align-items: stretch;opacity: 1;border-color: var(--accent);box-shadow: var(--sh-2);z-index: 6;}
.planBox .lineSetting:hover::before,.planBox .lineSetting.hoverHold::before{display: none;}
/* 面板限宽 + 组内换行：靠屏幕右缘的排打开时不再被视口裁掉 */
.planBox .lineSetting:hover>li,.planBox .lineSetting.hoverHold>li{display: flex;align-items: center;gap: 4px;flex-wrap: wrap;}
.planBox .lineSetting select,.planBox .lineSetting button{height: 22px;font-size: 12px;}
.planBox .lineSetting input[type=number]{width: 38px;height: 22px;font-size: 12px;}
.planBox .lineSetting .grpTitle{display: none;font-size: 11px;color: var(--ink-3);border-bottom: 1px solid var(--line);padding-bottom: 3px;margin-bottom: 1px;}
.planBox .lineSetting:hover .grpTitle,.planBox .lineSetting.hoverHold .grpTitle{display: block;}
.planBox .lineSetting select.aislePick{flex: 1;min-width: 0;}

/* 单元格容器：与桌面排共用同一套网格轨道，块的位置由 gridColumn 决定（边框 1px、无内边距，拖拽换算依赖） */
.planBox ol{padding: 0;display: grid;list-style: none;margin: 0 auto;width: max-content;position: relative;background-color: #eef2f8;border: 1px solid var(--edge);}
.planBox ol:hover{background-color: #e6edf6;border-color: #b9cdf2;}
.planBox ol>li{min-width: 0;font-size: 14px;border: 1px solid var(--line-2);box-sizing: border-box;position: relative;background: var(--surface);transition: background-color .12s,border-color .12s,box-shadow .12s,transform .12s;cursor: grab;}
.planBox ol>li:hover{z-index: 3;}
.planBox ol>li .main{position: relative;line-height: 1.5em;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 2px 0.4em;box-sizing: border-box;margin: 0;min-width: 100%;text-align: center;height: 2em;font-weight: 600;color: var(--ink);}
.planBox ol>li:hover .main{width: fit-content;background: var(--accent-soft);}
.planBox ol>li .main i{position: absolute;left: 0;top: 0;font-size: 9px;line-height: 1em;padding: 0;border-radius: 999px;background: var(--accent-soft);color: var(--accent);font-style: normal;font-weight: 700;font-variant-numeric: tabular-nums;}
.planBox ol>li .more {text-wrap: nowrap;text-align: left;padding: 6px;border: 1px solid var(--line);margin: 6px;border-radius: var(--r-md);overflow: hidden;box-sizing: border-box;background: var(--surface-2);font-size: 13px;}
.planBox ol>li .more.easy {position: absolute;left: -1px;top: 100%;z-index: 4;width: max-content;max-width: 360px;min-width: 100%;margin: 0;border-radius: 0 0 var(--r-md) var(--r-md);display: none;line-height: 1.6;box-shadow: var(--sh-2);cursor: auto;}
.planBox ol>li:hover .more.details,.planBox ol>li.hoverHold .more.details{overflow: auto;width: fit-content;position: relative;z-index: 2;border-radius: 0;border-color: #2563eb;background: var(--surface);min-width: calc(100% - 12px);}
.planBox ol>li:hover .more.easy,.planBox ol>li.hoverHold .more.easy {display: block;background: var(--surface);}
.planBox ol>li .more .hide{display: none;color: var(--ink-2);}
.planBox ol>li .more .empty{color: var(--ink-3);display: inline-block;text-align: center;width: 100%;}
.planBox ol>li:hover .more .hide,.planBox ol>li.hoverHold .more .hide{display: revert;}

/* 操作浮层：贴在单元格上方向上弹出，与格子之间不留空隙；按「座/桌」「廊」分两行 */
.planBox .settingChild {text-wrap: nowrap;width: max-content;max-width: 360px;background: var(--surface);border: 1px solid var(--line);position: absolute;z-index: 4;left: -1px;bottom: 100%;display: none;box-sizing: border-box;padding: 6px;gap: 4px;flex-direction: column;align-items: flex-start;border-radius: var(--r-md);box-shadow: var(--sh-2);cursor: auto;}
.planBox .settingChild li,.planBox .settingChild .grp{display: flex;gap: 4px;flex-wrap: wrap;align-items: center;}
.planBox .settingChild .cap{font-size: 10px;line-height: 1;color: var(--accent);background: var(--accent-soft);border-radius: 4px;padding: 3px 5px;font-weight: 700;}
.planBox .settingChild button{height: 29px;min-width: 0;padding: 0 10px;font-size: 13px;border-radius: var(--r-sm);border-color: transparent;background: var(--surface-2);}
.planBox .settingChild button:hover{background: var(--accent-soft);color: var(--accent);border-color: transparent;}
.planBox .settingChild button:disabled{background: var(--surface-2);}
.planBox .settingChild .danger{color: var(--danger);}
.planBox .settingChild .danger:hover{background: var(--danger-soft);color: var(--danger);}
.planBox ol>li:hover .settingChild,.planBox ol>li.hoverHold .settingChild{display: flex;}

/* 排两端操作区（endZone）：竖条把手贴排外侧，面板复用 settingChild 结构（grp/cap 分组、上方弹出） */
.planBox .endZone{position: absolute;left: 100%;top: 0;text-wrap: nowrap;text-align: left;width: 2em;height: 100%;border: 1px solid var(--line);border-left: 0;border-radius: 0 var(--r-md) var(--r-md) 0;background-color: var(--surface);box-shadow: var(--sh-1);opacity: 0;box-sizing: border-box;}
/* 行首操作区：与行尾同款竖条，反贴在排左缘外侧 */
.planBox .endZone.head{left: auto;right: 100%;border: 1px solid var(--line);border-right: 0;border-radius: var(--r-md) 0 0 var(--r-md);}
.planBox .endZone .units{font-size: 12px;color: var(--ink-2);padding: 0 2px;}
.planBox ol:hover .endZone,.planBox ol.hoverHold .endZone{opacity: 1;background-color: var(--surface);border-color: #b9cdf2;}
.planBox .endZone:hover .main{background: transparent;width: auto;}
/* 图标改为 CSS 字符直接显示在 .main 占位层里，不再依赖 edit.png 背景图（图片加载失败会只剩空白方块） */
.planBox .endZone .main{display: flex;align-items: center;justify-content: center;}
.planBox .endZone .main::before{content: "✎";font-size: 13px;line-height: 1;color: var(--accent);}

/* ---------- vue-draggable-plus 拖拽占位 ---------- */
.sortable-ghost{opacity: .35;background: var(--accent-soft);}
.sortable-chosen{cursor: grabbing;}
.infoCenter .unreserved .displayArea.droptarget{border-color: var(--accent);box-shadow: 0 0 0 3px var(--accent-soft);}

/* ---------- 插入方向指示：座位左/右半边各亮一条边（桌子没有插入指示，拖桌只做弹开与对调） ---------- */
.planBox .seat>li.insertBefore{box-shadow: -3px 0 0 var(--accent), 0 0 0 2px rgba(37,99,235,.25);}
.planBox .seat>li.insertAfter{box-shadow: 3px 0 0 var(--accent), 0 0 0 2px rgba(37,99,235,.25);}

/* ---------- 座椅 ---------- */
.planBox .seat{margin: 0 auto;min-height: 2em;}
.planBox .seat .main{line-height: 2em;padding: 0 0.4em;}
.planBox .seat>li:not(.occupied){background: rgba(255,255,255,.55);border-style: dashed;border-color: var(--line-2);color: var(--ink-3);}
.planBox .seat>li:not(.occupied) .main{font-weight: 400;}
.planBox .seat>li:not(.occupied) .main i{background: var(--surface-2);color: var(--ink-3);}
.planBox .seat>li.occupied{background: linear-gradient(180deg,#f8faff,#eef4ff);border-color: #c3d5f7;}
.planBox .seat>li.occupied .main{color: var(--ink);}
.planBox .seat li.ready{background:var(--surface);border-style: solid;border-color: var(--accent);box-shadow: 0 0 0 3px rgba(37,99,235,.22);transform: scale(1.06);position: relative;z-index: 2;}
/* 查找命中：琥珀色描边，区别于拖拽指示 */
.planBox .seat>li.found{box-shadow: 0 0 0 3px var(--amber);z-index: 2;}
.infoCenter .unreserved table tbody tr.found{outline: 2px solid var(--amber);outline-offset: -2px;}
.infoCenter .unreserved li.found{border-color: var(--amber);box-shadow: 0 0 0 2px #f2dcae;}
/* 查找命中的字符标注（名单姓名列、候选下拉里 v-html 输出的自定义元素 keyword，移植自 jzzc） */
keyword{font-style: normal;font-weight: 700;color: #7a5200;background: #f2dcae;border-radius: 3px;padding: 0 1px;}
/* 点击搜索结果跳转：目标闪三下（叠在 .found 描边上，tr 用 outline 版本） */
@keyframes locateFlash{0%,100%{box-shadow:0 0 0 3px var(--amber);}40%{box-shadow:0 0 0 9px rgba(217,119,6,.5);}}
@keyframes locateFlashRow{0%,100%{outline:2px solid var(--amber);outline-offset:-2px;}40%{outline:4px solid #d97706;outline-offset:-4px;}}
.planBox .seat>li.locateFlash,.infoCenter .unreserved li.locateFlash{animation: locateFlash .55s ease-in-out 3;z-index: 3;}
.infoCenter .unreserved table tr.locateFlash{animation: locateFlashRow .55s ease-in-out 3;}
.planBox .seat li.leave:hover *:not(.main,.details,.details br){display: none;}
.planBox .seat li.leave{opacity: .45;border-style: dashed;}
/* 座位右缘拖拽手柄：有人的座位可拖动调宽（空位固定 1 位不显示） */
.planBox .seat .grip{position: absolute;right: -4px;top: -1px;bottom: -1px;width: 7px;cursor: col-resize;z-index: 3;opacity: .5;}
.planBox .seat>li:hover .grip{background: var(--accent);}
/* 详细显示：列宽由 --cell-w 统一放大，此处只让标签常显 */
.planBox.details .seat .more .hide{display: inline;}

/* ---------- 走廊条：走廊从隐形空隙变成可见、可拖动的一格 ----------
    放在座椅/桌面样式之后，确保背景不被 .seat>li:not(.occupied) 等规则覆盖 */
.planBox .seat>li.aisleStrip,.planBox .desk>li.aisleStrip{background: repeating-linear-gradient(-45deg,#e7edf6 0 3px,#f6f9fd 3px 7px);border: 1px dashed var(--line-2);border-left: 0;border-right: 0;min-width: 0;cursor: grab;}
.planBox .seat>li.aisleStrip:active,.planBox .desk>li.aisleStrip:active{cursor: grabbing;}
.planBox .aisleStrip .grip{position: absolute;right: -4px;top: -1px;bottom: -1px;width: 7px;cursor: col-resize;z-index: 3;opacity: .5;}
.planBox .aisleStrip .grip:hover{background: var(--accent);}

/* ---------- 桌面 ---------- */
.planBox .desk {min-height: 1.5em;border-color: var(--edge);margin: 0 auto 8px;}
.planBox .desk>li{background: linear-gradient(180deg,#f5f8fe,#e9effb);border-color: #c9d6ee;cursor: grab;}
.planBox .desk .main{height: 1.5em;line-height: 1.5em;padding: 0;font-size: 12px;font-weight: 600;letter-spacing: .08em;color: #33507e;}
.planBox .desk li.moving{opacity: .4;}
.planBox .desk .grip{position: absolute;right: -4px;top: -1px;bottom: -1px;width: 7px;cursor: col-resize;z-index: 3;opacity: .5;}
.planBox .desk>li:hover .grip{background: var(--accent);}

/* ---------- 圆桌 / 方桌：按桌渲染，座位绕桌一圈 ----------
    桌块尺寸与座位落点全由 rows 计算出的 CSS calc 表达式给出（长度以 var(--cell-w) 计，
    详细信息模式下随 --cell-w 一起放大）；桌面本体宽高走 --tW / --tH。
    圆桌座位按 sin/cos 落在圆周上（1 号位 12 点方向），方桌座位绝对定位在四边。
    通用 ol>li 的悬停触发规则在这里必须改走 .tSeat 自己的 hover——
    否则悬停桌块会把整圈座位的浮层同时弹出来 */
.planBox ol.tables{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:16px;padding:12px;width:auto;min-height:2em;margin:0 auto 8px;border:0;background:transparent;}
.planBox ol.tables:hover{background:transparent;border-color:var(--edge);}
.planBox ol.tables>li{position:relative;flex:0 0 auto;border:0;background:transparent;cursor:default;}
.planBox ol.tables>li.frozen .tBody{border-style:dashed;}
/* 内衬：围桌座位与桌面在内区里按原有几何定位（座位样式里的百分比都相对内衬解析），
   旁听席外圈带宽 --obT/R/B/L 由块样式给出（该边没有旁听时为 0） */
.planBox .tRing{position:absolute;left:var(--obL,0em);top:var(--obT,0em);right:var(--obR,0em);bottom:var(--obB,0em);}
.planBox .tBody{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:var(--tW);height:var(--tH);display:flex;align-items:center;justify-content:center;background:linear-gradient(180deg,#f5f8fe,#e9effb);border:1px solid #c9d6ee;color:#33507e;font-size:12px;font-weight:600;letter-spacing:.08em;box-sizing:border-box;}
.planBox ol.tables.k-round .tBody{border-radius:50%;}
.planBox ol.tables.noDesk .tBody{display:none;}
.planBox .tSeats{margin:0;padding:0;}
.planBox .tSeat{position:absolute;left:0;top:0;width:var(--cell-w);box-sizing:border-box;margin:0;border:1px solid var(--line-2);background:rgba(255,255,255,.55);font-size:14px;cursor:grab;z-index:1;transition:background-color .12s,border-color .12s,box-shadow .12s;}
.planBox .tSeat:active{cursor:grabbing;}
.planBox .tSeat{transform:translate(-50%,-50%);}
.planBox .tSeat:not(.occupied){border-style:dashed;color:var(--ink-3);}
.planBox .tSeat:not(.occupied) .tFace{font-weight:400;}
.planBox .tSeat.occupied{background:linear-gradient(180deg,#f8faff,#eef4ff);border-color:#c3d5f7;}
.planBox .tFace{position:relative;box-sizing:border-box;height:2em;line-height:2em;padding:0 3px;text-align:center;font-weight:600;}
/* 名字超长省略放内层：浮层（settingChild）挂在 tFace 上，外层不能裁剪 */
.planBox .tName{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
/* 打印数据列（桌型座位）：屏幕隐藏，打印时随 body.printCols 显示（姓名下方逐行） */
.planBox .tFace .printCols{display:none;font-size:10px;line-height:1.35;text-align:center;padding:0 3px;white-space:normal;}
.planBox .tFace .printCols span{display:block;}
.planBox .tSeat.occupied .tFace{color:var(--ink);}
.planBox .tFace i{position:absolute;left:0;top:0;font-size:9px;line-height:1em;padding:0 1px;border-radius:999px;background:var(--accent-soft);color:var(--accent);font-style:normal;font-weight:700;font-variant-numeric:tabular-nums;}
.planBox .tSeat:not(.occupied) .tFace i{background:var(--surface-2);color:var(--ink-3);}
.planBox .tFace .units{font-size:11px;color:var(--ink-2);white-space:nowrap;}
.planBox .tSeat.found{box-shadow:0 0 0 3px var(--amber);z-index:2;}
.planBox .tSeat.ready{border-style:solid;border-color:var(--accent);box-shadow:0 0 0 3px rgba(37,99,235,.22);z-index:2;}
.planBox .tSeat.locateFlash{animation:locateFlash .55s ease-in-out 3;z-index:3;}
/* 座位浮层：通用规则是 ol>li:hover 触发，在桌块里会连带弹出一整圈，这里收紧成各自 hover；
   （.hoverHold 孪生规则由 bindHoverHold 的 .tSeat 命中，延迟 1 秒隐藏） */
.planBox ol.tables .tSeat .settingChild{display:none;}
.planBox ol.tables .tSeat:hover .settingChild,.planBox ol.tables .tSeat.hoverHold .settingChild{display:flex;}

/* ---------- 旁听席：绕桌块外圈（回字 / 倒U，随布局激活边）；工具条与面板的每边输入 ---------- */
.planBox .tObs{margin:0;padding:0;}
.planBox .lineSetting .sideLab,.planToolbar .sideLab{font-size:11px;color:var(--ink-3);}
.planBox .lineSetting .sideNum{width:34px;height:22px;font-size:12px;padding:0 2px;text-align:center;}
.planToolbar .sideNum{width:38px;padding:0 2px;text-align:center;}

/* ---------- 拖动期间：隐藏悬浮层、压掉悬停噪声，光标统一 grabbing ----------
    座/廊按钮与详情浮层只属于悬停交互，拖动时只会挡视线 */
.planBox.dragging .settingChild,.planBox.dragging .more.easy{display:none !important;}
.planBox.dragging ol>li:hover .main{width: auto;background: transparent;}
.planBox.dragging,.planBox.dragging *{cursor: grabbing !important;}

/* ---------- 拖动中的模式提示：键帽徽章列出各模式（含 Alt+Shift 整体弹开），当前生效的那个高亮 ---------- */
.dragHint{position: fixed;top: 14px;left: 50%;transform: translateX(-50%);z-index: 40;display: flex;align-items: center;gap: 12px;background: rgba(255,255,255,.96);backdrop-filter: blur(8px);border: 1px solid var(--line-2);border-radius: 999px;box-shadow: var(--sh-2);padding: 7px 16px;font-size: 12px;color: var(--ink-2);pointer-events: none;white-space: nowrap;animation: hintIn .18s ease-out;}
@keyframes hintIn{from{opacity: 0;transform: translate(-50%,-8px);}to{opacity: 1;transform: translate(-50%,0);}}
.dragHint .mode{display: inline-flex;align-items: center;gap: 5px;opacity: .55;}
.dragHint .mode.on{opacity: 1;font-weight: 600;color: var(--accent-deep);}
.dragHint .key{font-style: normal;font-size: 11px;line-height: 1;padding: 3px 6px;border: 1px solid var(--line-2);border-bottom-width: 2px;border-radius: 4px;background: var(--surface-2);color: var(--ink-2);}
.dragHint .mode.on .key{border-color: var(--accent);color: var(--accent);background: var(--accent-soft);}

/* ---------- 轻提示 ---------- */
.actionNote{position: fixed;left: 50%;bottom: 26px;transform: translateX(-50%);z-index: 30;background: var(--surface);border: 1px solid var(--accent);border-radius: 999px;box-shadow: var(--sh-2);padding: 9px 18px;font-size: 13px;color: var(--accent-deep);max-width: 80vw;text-align: center;animation: noteIn .16s ease-out;}
@keyframes noteIn{from{opacity: 0;transform: translate(-50%,8px);}to{opacity: 1;transform: translate(-50%,0);}}

/* ---------- 页面内警告弹窗（替代原生 confirm） ----------
    视觉：顶部锚定卡片 + 左对齐正文 + 描边「取消」/ 红色渐变「确定」 */
.confirmModal{position: fixed;inset: 0;z-index: 100;display: flex;align-items: flex-start;justify-content: center;padding-top: 18vh;background: rgba(15,23,42,.35);backdrop-filter: blur(3px);animation: fadeIn .18s ease-out;}
@keyframes fadeIn{from{opacity: 0;}to{opacity: 1;}}
.confirmModal .dialogCard{box-sizing: border-box;min-width: 320px;max-width: 480px;background: var(--surface);border: 1px solid #fff;border-radius: 12px;box-shadow: var(--sh-2),0 24px 64px rgba(15,23,42,.2);padding: 20px 24px 16px;animation: cardIn .2s ease-out;}
@keyframes cardIn{from{opacity: 0;transform: translateY(-8px);}to{opacity: 1;transform: none;}}
.confirmModal .dialogMessage{font-size: 15px;line-height: 1.7;color: var(--ink);white-space: pre-line;text-align: left;}
.confirmModal .dialogActions{display: flex;justify-content: flex-end;gap: 10px;margin-top: 1.1em;}
.confirmModal .dialogActions button{height: 34px;padding: 0 18px;font-size: 14px;font-weight: 500;border-radius: 8px;transition: background-color .12s,border-color .12s,color .12s,box-shadow .12s,transform .12s,filter .12s;}
.confirmModal .cancel{background: var(--surface);border: 1px solid var(--line-2);color: var(--ink);}
.confirmModal .cancel:hover{border-color: var(--accent);color: var(--accent);background: var(--accent-soft);}
.confirmModal .danger{background: linear-gradient(180deg,#ef4444,#dc2626);border: 0;color: #fff;box-shadow: 0 3px 8px rgba(220,38,38,.35),inset 0 1px 0 rgba(255,255,255,.25);}
.confirmModal .danger:hover{background: linear-gradient(180deg,#e83c3c,#cf2020);border: 0;color: #fff;box-shadow: 0 5px 14px rgba(220,38,38,.45),inset 0 1px 0 rgba(255,255,255,.25);}
.confirmModal .danger:active{transform: translateY(1px);filter: brightness(.96);}
.confirmModal .danger:focus-visible{outline: 2px solid var(--danger);outline-offset: 2px;}
.confirmModal .primary{background:linear-gradient(180deg,#3b74f0,var(--accent));border:0;color:#fff;box-shadow:0 3px 8px rgba(37,99,235,.35),inset 0 1px 0 rgba(255,255,255,.25);}
.confirmModal .primary:hover{background:linear-gradient(180deg,#2f66e8,var(--accent-deep));border:0;color:#fff;box-shadow:0 5px 14px rgba(37,99,235,.45),inset 0 1px 0 rgba(255,255,255,.25);}
.confirmModal .primary:active{transform:translateY(1px);filter:brightness(.96);}
.confirmModal .primary:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
/* 导出弹窗：两张表的勾选 + 座次图细项 */
.confirmModal .exportCard{min-width:420px;max-width:480px;}
.confirmModal .exportTitle{font-size:16px;font-weight:700;color:var(--ink);margin-bottom:12px;}
.confirmModal .exportGroup{border:1px solid var(--line);border-radius:10px;background:var(--surface-2);padding:6px 12px;}
.confirmModal .exportChart{margin-top:10px;border:1px solid var(--line);border-radius:10px;background:var(--surface);padding:6px 12px 10px;}
.confirmModal .exportCap{font-size:12px;font-weight:700;color:var(--ink-2);margin:4px 0 2px;}
.confirmModal .exportCheck{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--ink);line-height:2;cursor:pointer;user-select:none;}
.confirmModal .exportCheck input{width:14px;height:14px;margin:0;flex:none;}
.confirmModal .exportCols{display:flex;flex-wrap:wrap;gap:0 14px;}
.confirmModal .exportCheck:hover{color:var(--accent);}

/* ---------- 展示模式：只看座次图（类挂 body） ----------
    隐藏名单区与全部编辑界面，Esc 或右上角按钮退出；
    查找框挂在顶栏外所以展示模式继续可用；轻提示（.actionNote）也保留，负责「未入座 / 无命中」的反馈 */
/* 退出按钮；查找框下移一行的旧方案已废弃（fixed 胶囊不受顶栏隐藏影响，无需避让） */
body .exitDisplay{position:fixed;right:18px;top:14px;z-index:60;height:34px;padding:0 16px;font-size:13px;border-radius:999px;border:1px solid var(--line);background:rgba(255,255,255,.94);color:var(--ink-2);cursor:pointer;box-shadow:var(--sh-1);transition:border-color .12s,color .12s;}
body .exitDisplay:hover{border-color:var(--accent);color:var(--accent);}
body.display .planBox{margin:0}
body.display .planBox .plan{margin:2em auto}
body.display .planBox .plan>li{box-shadow:none;border-color:#bbb;padding:10px 12px 10px 44px}
body.display .planBox .plan .rowHead{left:12px}

body.display .topBar,
body.display .infoCenter,
body.display .dragHint,
body.display .columnPanel,
body.display .planBox .planToolbar,
body.display .planBox .plan>li.blank,
body.display .planBox .plan .rowLock,
body.display .planBox .lineSetting,
body.display .planBox .settingChild,
body.display .planBox .endZone,
body.display .planBox .desk .grip,
body.display .planBox .aisleStrip .grip,
body.display .planBox .seat .grip{display: none!important;}

/* 打印专属层（屏幕上一律隐藏）：顶部序号尺与座位格附加数据列，
    按导出弹窗的座次图选项借 body 上的打印态类显示（watch 同步）。
    盒子必须和座位 ol 一致（max-content + auto 居中 + 1px 透明边框补 ol 的边框），列才一格对一格；
    --cell-w 是 em、随元素字号解析：11px 只能写在 span 上，div 必须和 ol 同字号，否则整条尺列宽变窄、整体错位 */
.planBox .printRuler{display:none;width:max-content;margin:0 auto 4px;border:1px solid transparent;line-height:13px;height:15px;color:#333;text-align:center}
.planBox .printRuler span{font-size:11px;background:#e8eef8;border:1px solid #b9cdf2;border-radius:2px;overflow:hidden}
/* 全图顶端尺的外层：打印几何复刻排卡片的水平带（1px 边框 + 44/12 内边距），里面的尺再同款居中，与第一排座位条逐列对齐 */
.planBox .printTopWrap{display:none;padding: 10px 12px 10px 44px;border: 1px solid transparent;}
.planBox .seat .printCols{display:none;font-size:10px;line-height:1.35;text-align:left;padding:0 3px;white-space:normal}
.planBox .seat .printCols span{display:block}
    
/* ---------- 打印：只输出座次图 ---------- */
@media print{
    body{min-width:auto;width:auto;margin:0;background:#fff}
    .planBox{margin:0}
    .planBox .plan{margin:0 auto}
    .planBox .plan>li{box-shadow:none;break-inside:avoid;border-color:var(--accent);background:#fff;padding:10px 12px 10px 44px}
    .planBox .plan .rowHead{left:12px}
    .planBox .plan .number{background:#fff;color:#333}
    .planBox ol{background:#fff;border-color:#bbb;border-radius:0}
    .planBox .seat>li:not(.occupied){background:#fff;border-color:#999}
    .planBox .seat>li.occupied{background:#fff;border-color:#666}
    .planBox .tSeat:not(.occupied){background:#fff;border-color:#999}
    .planBox .tSeat.occupied{background:#fff;border-color:#666}
    .planBox .tFace{color:#333}
    /* 座位格打印排版：姓名允许换行、格子高度自适应（不再 2em 定高截断成「张晓…」）；顺序号从左上角标改为行内首项（顺序号 + 姓名同 Excel 的「1 张三」一行，超长换行不截断） */
    /* .planBox .seat .main{display:flex;flex-wrap:wrap;justify-content:center;align-items:baseline;white-space:normal;overflow:visible;height:auto;min-height:2em;line-height:1.3;padding:3px;font-size:12px;word-break:break-all}
    .planBox .seat .main i{position:static;order:-1;display:inline;padding:0;margin-right:2px}
     */
    /* 座次图选项作用于打印（导出弹窗勾选 → watch 挂 body 类）：桌子 / 顺序号显隐，顶部序号尺与附加数据列按勾选显示 */
    body.printChartTop .planBox .printTopWrap{display:block}
    body.printChartTop .planBox .printRuler.chartTop{display:grid;margin: 0 auto;}
    body.printRowTop .planBox .printRuler.rowTop{display:grid}
    body.printCols .planBox .seat .printCols{display:block}
    body.printCols .planBox .tFace{height:auto;min-height:2em}
    body.printCols .planBox .tFace .printCols{display:block}
    body.printNoDesk .planBox .desk{display:none!important}
    body.printNoDesk .planBox .tBody{display:none!important}
    body.printNoOrder .planBox .seat .main i{display:none!important}
    body.printNoOrder .planBox .tFace i{display:none!important}
    /* 走廊条：斜纹背景打印不出来，补个文字标记，别剩一个看不懂的虚线空框 */
    /* .planBox .aisleStrip::after{content:"走廊";display:block;text-align:center;font-size:10px;line-height:1.2;color:#999;padding-top:3px} */

    /* 隐藏全部交互层 */
    .topBar,
    .search,
    .columnPanel,
    .infoCenter,
    .actionNote,
    .dragHint,
    .confirmModal,
    .planBox .planToolbar,
    .planBox .plan>li.blank,
    .planBox .plan .rowLock,
    .planBox .lineSetting,
    .planBox .settingChild,
    .planBox .endZone,
    .planBox .desk .grip,
    .planBox .aisleStrip .grip,
    .planBox .seat .grip{display:none!important}

}

@page{size:a4 landscape;margin:8mm}
