:root{
  --sheet-w: 297mm;
  --page-h: 420mm;
  --line: #1a1a1a;
  --accent: #2b6cb0;
  --bg: #eef1f5;
  --panel: #fff;
}
*{box-sizing:border-box;margin:0;padding:0;}
html,body{height:100%;font-family:"Microsoft YaHei","SimSun",system-ui,sans-serif;color:#222;background:var(--bg);}
button{font-family:inherit;cursor:pointer;border:1px solid #c4ccd6;background:#fff;border-radius:6px;padding:6px 10px;font-size:13px;}
button:hover{background:#f1f4f8;}
button.primary{background:var(--accent);color:#fff;border-color:var(--accent);}
button.primary:hover{background:#245a93;}
button.danger{border-color:#e06a6a;color:#c0392b;}
button:disabled{opacity:.45;cursor:not-allowed;background:#f3f5f8;}
button:disabled:hover{background:#f3f5f8;}

/* 操作轻提示（复制 / 剪切 / 撤销 …） */
#toast{
  position:fixed;left:50%;bottom:28px;transform:translate(-50%,12px);
  background:rgba(28,36,48,.92);color:#fff;font-size:13px;line-height:1;
  padding:10px 16px;border-radius:8px;box-shadow:0 6px 20px rgba(0,0,0,.22);
  opacity:0;pointer-events:none;transition:opacity .16s ease,transform .16s ease;z-index:9999;
}
#toast.on{opacity:1;transform:translate(-50%,0);}

/* 面板内说明文字 */
.panehint{font-size:12px;line-height:1.6;color:#8a94a0;background:#f7fafc;border:1px solid #e6eaef;
  border-radius:6px;padding:6px 8px;margin-bottom:10px;}
.panehint b{color:#4a596b;}

/* 顶栏 */
.topbar{display:flex;align-items:center;justify-content:space-between;padding:10px 16px;background:#fff;border-bottom:1px solid #d7dde5;flex:0 0 auto;}
.brand{font-size:18px;font-weight:800;}
.tools{display:flex;gap:8px;align-items:center;flex-wrap:wrap;}
.tools label{font-size:13px;display:flex;align-items:center;gap:4px;}
.tools select{padding:5px 6px;border-radius:6px;border:1px solid #c4ccd6;font-size:13px;}

/* 三栏 */
.app{display:flex;height:calc(100vh - 53px);}
.left{width:280px;display:flex;flex-direction:column;border-right:1px solid #d7dde5;background:var(--panel);}
.center{flex:1;overflow:auto;background:#dfe4ea;padding:20px;}
.right{width:320px;border-left:1px solid #d7dde5;background:var(--panel);display:flex;flex-direction:column;}
.panel{padding:12px;border-bottom:1px solid #e6eaef;}
.panel.grow{flex:1;overflow:auto;}
.panel h3{font-size:14px;margin-bottom:10px;color:#334;}

/* 题型面板 */
.palette{display:grid;grid-template-columns:1fr 1fr;gap:8px;}
.palette .pbtn{display:flex;flex-direction:column;align-items:center;gap:2px;padding:12px 6px;border:1px dashed #9fb3c8;border-radius:8px;background:#f7fafc;font-size:13px;}
.palette .pbtn .ic{font-size:20px;}
.palette .pbtn:hover{background:#eaf2fb;border-color:var(--accent);}

/* 结构列表 */
.structure{display:flex;flex-direction:column;gap:8px;}
.struct-item{display:flex;align-items:center;gap:8px;border:1px solid #d7dde5;border-radius:8px;padding:8px 10px;background:#fff;}
.struct-item.sel{border-color:var(--accent);box-shadow:0 0 0 2px #cfe2f5;}
.struct-item .handle{cursor:grab;color:#9aa7b3;font-size:16px;}
.struct-item .nm{flex:1;font-size:13px;font-weight:600;}
.struct-item .acts{display:flex;gap:4px;}
.struct-item .acts button{padding:3px 7px;font-size:12px;}
.struct-item.dragging{opacity:.4;}
.struct-item.drop-before{border-top:2px solid var(--accent);}
.struct-item.drop-after{border-bottom:2px solid var(--accent);}

/* 属性面板 */
.props{font-size:13px;}
.props .hint{color:#8a94a0;font-size:12px;line-height:1.55;margin:7px 0 0;}
.props label{display:block;margin:9px 0;font-size:12.5px;color:#3b4757;}
.props input[type=text],.props input[type=number],.props select,.props textarea{
  width:100%;padding:6px 8px;border:1px solid #c4ccd6;border-radius:6px;font-size:13px;margin-top:4px;font-family:inherit;
}
.props textarea{min-height:90px;resize:vertical;}
/* 两列并排：align-items:flex-end 让输入框底部对齐 ——
   否则一侧标签换行成两行时，两个输入框会一高一低错位 */
.props .row{display:flex;gap:8px;align-items:flex-end;}
.props .row > *{flex:1;min-width:0;}
.qlist{margin:8px 0;border:1px solid #e6eaef;border-radius:8px;padding:8px;}
.qrow{display:flex;align-items:center;gap:8px;margin:6px 0;}
.qrow span{font-size:13px;min-width:48px;}
.qrow input{width:70px;}
.qrow button{padding:3px 8px;font-size:12px;}
/* 解答题每题的图片配置卡片 */
.qcard{border:1px dashed #cfe2f5;border-radius:8px;padding:6px 8px;margin:8px 0;}
/* 当前指向的那一题（Ctrl+V 贴图目标）在属性面板里高亮 */
.qcard.on{border-color:#2b6cb0;border-style:solid;background:#f5f9ff;}
.qcard .qcur{
  font-style:normal;font-size:11px;color:#fff;background:#2b6cb0;
  border-radius:8px;padding:0 6px;margin-left:4px;
}
/* 题卡行内不换行：标签（含「当前」角标）整块排，放不下时整块掉到下一行，
   不会出现「第 1 题 / 当前」被拆成两行的错位 */
.qcard .qrow{flex-wrap:wrap;row-gap:4px;}
.qcard .qrow > span{white-space:nowrap;display:inline-flex;align-items:center;flex:0 0 auto;}
.qcard .qrow label{white-space:nowrap;margin:0;}
.qcard .qrow input[type=number]{width:70px;}
.qcard .qrow span{min-width:auto;}
.qcard input[type=file]{width:100%;font-size:12px;}
.img-thumb{margin-top:4px;border:1px solid #e6eaef;border-radius:6px;padding:4px;background:#fafcfe;text-align:center;}
.img-thumb img{max-width:100%;max-height:110px;display:block;margin:0 auto;}
.props .addbtn{margin-top:6px;width:100%;border-style:dashed;}

/* 预览舞台 */
.stage-wrap{min-height:100%;display:flex;justify-content:center;align-items:flex-start;}
.stage{position:relative;padding:14px 0;}
/* .sheet 仅作多页容器，单页由 .page 承载（固定纸张，item 2） */
.sheet{
  background:transparent;
  box-shadow:none;
  padding:0;
  width:auto;
}
.page{
  background:#fff;
  box-shadow:0 4px 18px rgba(0,0,0,.18);
  margin:0 auto 14px;
  position:relative;
  box-sizing:border-box;
  display:flex;
  align-items:stretch;
}
.page .col{flex:1 1 0;min-width:0;}

/* 定位点（四角）：方块 / 三角；仅出现在「有题目内容的面」上，绝对定位不占排版流。
   位置（内缩量）与边长由 preview.js 按「预留页边距带」内联设置 —— 保证定位点永远落在
   页边距带内、不覆盖任何内容。
   打印时强制输出底色，否则多数浏览器会丢弃黑色块。 */
.page .cmark{position:absolute;background:#000;pointer-events:none;-webkit-print-color-adjust:exact;print-color-adjust:exact;}
/* 三角：直角贴外角，斜边朝内（右上/右下角镜像） */
.page .cmark.tri.tl{clip-path:polygon(0 0,100% 0,0 100%);}
.page .cmark.tri.tr{clip-path:polygon(0 0,100% 0,100% 100%);}
.page .cmark.tri.bl{clip-path:polygon(0 0,0 100%,100% 100%);}
.page .cmark.tri.br{clip-path:polygon(100% 0,100% 100%,0 100%);}

/* ===== 答题卡内部元素 ===== */
/* 每个题型区块统一加黑色边框（item 1）；font-size 作基准，子元素用 em 继承，
   这样「通用样式」里调字号就能整体生效（修复：字号无反应） */
.blk{margin-bottom:6mm;break-inside:avoid;-webkit-column-break-inside:avoid;border:1.5px solid var(--line);border-radius:4px;padding:6px 10px 10px;font-size:14px;}
.blk-title{font-size:1.07em;font-weight:800;margin:2px 0 6px 0;padding-left:8px;border-left:5px solid var(--accent);}

/* 考生信息（边框由外层 .blk 统一提供）；对齐用 --jc 驱动 flex 容器（修复：对齐无反应） */
.info-box{border:none;border-radius:4px;padding:0;}
.info-box .ib-title{font-size:1.14em;font-weight:800;letter-spacing:3px;text-align:center;margin-bottom:6px;}
.info-fields{display:flex;flex-wrap:wrap;gap:14px 22px;justify-content:var(--jc,flex-start);}
.info-field{display:flex;align-items:baseline;gap:6px;}
.info-field .lab{font-weight:700;white-space:nowrap;}
.info-field .il{display:inline-block;border-bottom:1.5px solid var(--line);}

/* 考号填涂区 + 右侧手写栏 */
/* 考生信息栏：填涂区与手写栏同一行 —— 填涂区宽度由 info.js 按「格子可填涂所需」给出，
   余下宽度全部交给手写栏（下划线自动拉满），即「适量压榨右侧空间」 */
.info-body{display:flex;gap:3.2mm;align-items:flex-start;justify-content:var(--jc,flex-start);}
.info-body .exam-grid{flex:0 0 auto;margin-top:0;}
/* 手写栏（有填涂区时）：整列占满剩余宽度，下划线 flex 拉满，右侧不留白；
   设定的宽度作为最小宽度（被压缩时由 info.js 折算出新的 min-width） */
.info-fields-col{display:flex;flex-direction:column;gap:10px;flex:1 1 auto;min-width:0;justify-content:center;align-items:var(--jc,stretch);}
.info-field-row{display:flex;align-items:baseline;gap:6px;}
.info-field-row .lab{font-weight:700;white-space:nowrap;}
.info-field-row .il{display:inline-block;border-bottom:1.5px solid var(--line);flex:1 1 auto;min-width:0;}

.exam-grid{border:1.5px solid var(--line);border-radius:4px;padding:0.4em 0.5em;min-width:0;box-sizing:border-box;}
/* width:100% + table-layout:fixed：各数字格等宽；格宽 = 填涂区宽 ÷ 位数。
   填涂区自身的宽度由 info.js 按「气泡需要的宽度」算出（见 .ebrk 的 --brk） */
.exam-grid table{border-collapse:collapse;font-size:0.82em;margin:0 auto;width:100%;table-layout:fixed;}
/* 数字格左右不留 padding：格宽 = 方框边长 + 自适应间距（间距全由 info.js 的 cellGapMM 控制），
   这样画出来的方框尺寸就是 JS 算出的尺寸，不会因为 padding 挤到邻居格 */
.exam-grid td,.exam-grid th{border:1px solid #b9c2cc;padding:0.18em 0;text-align:center;}
.exam-grid .eg-head{font-weight:700;letter-spacing:0.4em;padding:0.32em;}
.exam-grid .write{height:1.7em;}
/* 考号填涂格：边长由 --brk（mm）直接给定 ——
   尺寸取决于「可用宽度 ÷ 位数」，与字号解耦，因此位数再多也能先把格子撑到可填涂的大小；
   格内数字按边长等比取字号，保证格子变小时数字仍清晰。
   box-sizing:border-box 保证 --brk 就是「含边框的外框尺寸」，不会撑破单元格。 */
.exam-grid .ebrk{
  box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;
  width:var(--brk,4mm);height:var(--brk,4mm);
  border:0.2mm solid #333;font-size:calc(var(--brk,4mm) * 0.62);line-height:1;vertical-align:middle;
}

/* 选择题 填涂/手写 */
/* row-gap 由 --hg 驱动（选择题的「行间距」设置，默认 1mm ≈ 原来的 4px） */
/* 行间距 --hg 同时决定「行与行」和「标题与第一行」的间距：
   grid 的 row-gap 只作用在行与行之间，第一行之前不会自动加 ——
   所以这里补上 padding-top（用 padding 而非 margin，避免与 .blk-title 的
   margin-bottom 发生外边距折叠）。-4px 抵消 .scq 自身的 2px 上下内边距，
   使「标题→第一行」与「行→行」的内容间隙相等。 */
.sc-grid{display:grid;gap:var(--hg,4px) 12px;align-items:start;
  padding-top:max(0px, calc(var(--hg,4px) - 4px));}
/* 题号与选项分离：选项在 .opts 内自动换行，第 2 行起对齐到第一个选项下方 */
.scq{display:flex;align-items:flex-start;gap:5px;padding:2px 0;min-width:0;}
.scq .scn{font-weight:800;min-width:1.6em;flex:0 0 auto;}
.scq .opts{display:flex;flex-wrap:wrap;gap:3px 6px;min-width:0;flex:1 1 auto;justify-content:var(--jc,flex-start);}
.scq .bub{display:inline-flex;align-items:center;gap:2px;}
.scq .bracket{display:inline-flex;align-items:center;justify-content:center;min-width:1.35em;height:1.35em;padding:0 0.1em;font-size:0.9em;border:1.5px solid #333;}
.scq.hw .hw-line{flex:1;border-bottom:1.5px solid var(--line);min-height:14px;min-width:40px;}
/* 手写作答框（A-D 识别）：学生把字母写进方框，导出模板后扫描端做结构分类 */
.scq.wb .wbox{width:26px;height:32px;border:1.8px solid #333;flex:0 0 auto;box-sizing:border-box;background:#fff;}

/* 填空 */
/* line-height 也跟随「行间距」--> 修复：小题内换行后（第一行与第二行）行距不生效 */
/* 行距统一：line-height 决定每一行的行距（含折行后的行）。
   .fill-q 之间不再额外加 margin —— 否则「题与题之间 = line-height + margin」
   会变成行距的两倍（实测 16mm 设成 32.1mm），正是「行距不均匀」的根因。
   行框相接后，题间行距 = 题内行距 = --fg，天然均匀。 */
.fill-q{line-height:max(1.4em, var(--fg,6mm));margin:0;}
/* 行内流式：一行没排满就继续往同一行放，排满才换行。
   每个小题是原子块（inline-block）→ 换行时整块下移，不会把「（2）」和它的空格拆开；
   max-width:100% 保证单个小题自身过宽时内部换行，而不是撑出纸张。 */
.fb-item{display:inline-block;max-width:100%;margin-right:3mm;vertical-align:top;}
.fb-tag{margin-right:1px;}
.fill-blank{display:inline-block;border-bottom:1.5px solid var(--line);vertical-align:middle;margin:0 4mm 0 2mm;width:30mm;height:16px;}

/* 解答 */
.ans-box{border:2px solid var(--line);border-radius:4px;break-inside:avoid;margin-bottom:4mm;overflow:hidden;}
.ans-box .ah{font-size:1em;font-weight:800;padding:6px 10px;border-bottom:1px solid var(--line);}
/* item 1：每题可插入图片（题干图），置于作答区上方 */
.ans-box .ans-img{padding:5px 10px;}
.ans-box .ans-img + .ab{border-top:1px dashed #cbd3dc;}
.ans-box .ab{display:block;position:relative;overflow:hidden;}
/* 横线样式（item 4）：在作答区内画等距横线，间距由 --lg 控制（item 5） */
.ans-box .ab.lined{
  background-image:repeating-linear-gradient(to bottom,
    transparent 0,
    transparent calc(var(--lg,8mm) - 1px),
    #cdd5df calc(var(--lg,8mm) - 1px),
    #cdd5df var(--lg,8mm));
}

/* 作答区内的叠加图片：定位层铺满整个作答区（inset:0），flex 九宫格对齐，
   图片宽度 % + max-height:100%（此时 100% = 作答区高度，解析稳定）。
   不用 transform 定位 —— transform 元素在打印管线里的裁切/定位不可靠
   （实测：屏幕预览裁切正常，Ctrl+P 打印预览里图片会压过边框）。
   兜底：.ab 自带 overflow:hidden，任何媒体下图片都绝不越过作答区边框。 */
.ans-box .ans-ov{
  position:absolute;inset:0;z-index:2;pointer-events:none;
  display:flex;min-height:0;
}
.ans-box .ans-ov img{display:block;height:auto;max-height:100%;object-fit:contain;}
.ans-box .ans-ov.pos-tl{align-items:flex-start;justify-content:flex-start;}
.ans-box .ans-ov.pos-tc{align-items:flex-start;justify-content:center;}
.ans-box .ans-ov.pos-tr{align-items:flex-start;justify-content:flex-end;}
.ans-box .ans-ov.pos-ml{align-items:center;justify-content:flex-start;}
.ans-box .ans-ov.pos-mc{align-items:center;justify-content:center;}
.ans-box .ans-ov.pos-mr{align-items:center;justify-content:flex-end;}
.ans-box .ans-ov.pos-bl{align-items:flex-end;justify-content:flex-start;}
.ans-box .ans-ov.pos-bc{align-items:flex-end;justify-content:center;}
.ans-box .ans-ov.pos-br{align-items:flex-end;justify-content:flex-end;}
/* 当前指向的作答区（Ctrl+V 贴图目标）：细蓝框提示，仅编辑态可见，打印时不输出 */
.ans-box .ab.on{outline:2px solid #2b6cb0;outline-offset:-2px;}
.ans-box .ab.on::after{
  content:'当前题';position:absolute;top:2px;right:3px;z-index:6;
  font-size:10px;color:#fff;background:#2b6cb0;border-radius:8px;padding:0 6px;line-height:15px;
}

/* 作答区「拖动调高度」把手：绝对定位贴在作答区下边缘，不占高度、不影响分页测量。
   拖动中只改 DOM height（实时反馈），松手才写回 config（一次拖动 = 一个撤销点）。 */
.rz-grip{
  position:absolute;left:0;right:0;bottom:0;height:12px;
  display:flex;align-items:center;justify-content:center;
  cursor:ns-resize;touch-action:none;z-index:5;
}
.rz-grip .rz-bar{
  width:46px;height:3px;border-radius:2px;background:#2b6cb0;
  opacity:0;transition:opacity .12s ease;
}
.rz-grip:hover .rz-bar{opacity:.85;}
.rz-grip:hover{background:rgba(43,108,176,.06);}
.rz-grip.on{background:rgba(43,108,176,.10);}
.rz-grip.on .rz-bar{opacity:1;}
.rz-grip .rz-tag{
  margin-left:8px;font-size:11px;color:#1c4e80;background:#fff;
  border:1px solid #cfe2f5;border-radius:10px;padding:1px 7px;
  opacity:0;transition:opacity .12s ease;white-space:nowrap;
}
.rz-grip.on .rz-tag{opacity:1;}
/* 拖动过程中禁止选中文字，光标统一为上下拉伸 */
body.rz-drag{user-select:none;-webkit-user-select:none;cursor:ns-resize;}

/* 自定义（边框由外层 .blk 统一提供） */
.custom-box{border:none;border-radius:4px;padding:0;break-inside:avoid;}
.custom-box .ch{font-size:1em;font-weight:800;margin-bottom:4px;}
.custom-box .cb{font-size:1em;line-height:1.7;white-space:pre-wrap;min-height:20px;}

/* 图片（item 1）：本地压缩为 dataURL，仅存浏览器缓存，随打印 / 导出 PDF 输出 */
.img-wrap{overflow:hidden;break-inside:avoid;}
.img-el{max-width:100%;height:auto;vertical-align:middle;}
.img-empty{border:1px dashed #9fb3c8;border-radius:6px;padding:18px;text-align:center;color:#8a99a8;background:#f7fafc;}

/* ---------- 设置 / 检查更新 ---------- */
#setModal{
  position:fixed;inset:0;z-index:10000;background:rgba(20,24,30,.5);
  display:flex;align-items:flex-start;justify-content:center;
  padding:64px 16px;overflow:auto;
}
#setModal[hidden]{display:none;}   /* 注意：必须有这条 —— 上面的 display:flex 会盖掉 UA 的 [hidden] 规则 */
.setbox{background:#fff;border-radius:12px;max-width:560px;width:100%;padding:18px 22px;box-shadow:0 12px 48px rgba(0,0,0,.32);}
.sethd{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px;}
.sethd h3{margin:0;font-size:15px;}
.setrow{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:10px 0;font-size:13px;}
.setrow label{display:inline-flex;align-items:center;gap:6px;}
.setrow .hint{font-size:12px;color:#5a6b7c;}
#setResult{border:1px solid #c4ccd6;border-radius:8px;padding:10px 12px;margin:10px 0;font-size:12.5px;line-height:1.65;background:#f7fafc;}
#setResult.hit{border-color:#9ad3a8;background:#ebfbee;}
#setResult pre{margin:8px 0 0;white-space:pre-wrap;word-break:break-word;max-height:200px;overflow:auto;font-size:12px;background:#fff;border:1px solid #dde4ec;border-radius:6px;padding:8px;font-family:inherit;}
#setResult a{color:var(--accent);}
.setnote{font-size:12px;color:#5a6b7c;border-top:1px solid #e3e8ef;padding-top:10px;margin-top:12px;line-height:1.7;}
#btn-settings.hasUpdate{border-color:#e8a33d;color:#a06a00;background:#fff9db;}

/* 打印 */
@media print{
  @page{margin:0;}
  body{background:#fff;}
  .topbar,.left,.right{display:none !important;}
  .app{display:block;height:auto;}
  .center{overflow:visible;background:#fff;padding:0;}
  .stage-wrap{padding:0;}
  .stage{padding:0;}
  .sheet{box-shadow:none;width:auto;padding:0;}
  /* 每面固定尺寸卡片 => 每页打印一张，自动双面顺序（item 2） */
  /* overflow:hidden 兜住 mm→px 舍入产生的亚像素溢出（否则末尾会多吐一张空白页） */
  .page{box-shadow:none;margin:0;break-after:page;page-break-after:always;overflow:hidden;}
  /* 最后一张卡片不再强制分页 —— 「只有正面有内容」时 PDF 必须只有一页 */
  .page:last-child{break-after:auto;page-break-after:auto;}
  .blk,.ans-box,.custom-box,.info-box{break-inside:avoid;}
  /* 拖动把手只是编辑辅助，绝不能出现在打印 / PDF 上 */
  .rz-grip{display:none !important;}
  /* 「当前题」选中框与角标同样只是编辑辅助 */
  .ans-box .ab.on{outline:none !important;}
  .ans-box .ab.on::after{display:none !important;}
  #toast{display:none !important;}
  #setModal{display:none !important;}   /* 设置弹窗绝不能印到卷子上 */
}
