:root {
    color-scheme: light;
    /* ===== 设计令牌(P0-1.1 令牌化:亮色值 = 历史硬编码值,零视觉变化) ===== */
    --c-bg: #f5f7fa;            /* 页面底 */
    --c-surface: #fff;           /* 卡片/表面 */
    --c-surface-alt: #f8f9fa;    /* 次级表面 */
    --c-text: #343a40;
    --c-text-secondary: #495057;
    --c-text-muted: #6c757d;
    --c-text-faint: #adb5bd;
    --c-border: #dee2e6;
    --c-border-light: #e9ecef;
    --c-primary: #2563eb;
    --c-primary-deep: #1d4ed8;
    --c-success: #28a745;
    --c-success-deep: #2e9e5b;
    --c-success-bg: #d4edda;
    --c-success-text: #155724;
    --c-danger: #dc3545;
    --c-danger-deep: #d9534f;
    --c-danger-bg: #f8d7da;
    --c-danger-text: #721c24;
    --c-warn: #ffc107;
    --c-warn-bg: #fff3cd;
    --c-warn-text: #7a5c00;
    --c-warn-accent: #b8860b;
    --c-accent-purple: #8e7cc3;
    --c-accent-purple-bg: #efeaff;
    --c-accent-purple-text: #6a4fb6;
    --c-info-bg: #eef3fb;
    --c-info-border: #b9c6dd;
    --c-panel-bg: #f1f3f5;
    --c-surface-warm: #fffdf5;
    --c-warn-bg-soft: #fff8e6;
    --c-success-soft: #ecfdf5;
    --c-danger-soft: #fff1f2;
    /* ===== 裸 hex 收口(取色 = 各用途原有硬编码值,亮色零视觉变化) ===== */
    --c-primary-hover: #5a6268;      /* secondary 按钮 hover(中灰,深于 --c-text-muted) */
    --c-text-secondary-deep: #2c4a80;/* info 提示文字(深蓝) */
    --c-warn-text-deep: #7a5800;     /* 告警提示文字(深褐) */
    --c-warn-border: #e0a800;        /* 告警提示边框 */
    --c-badge-warn-text: #856404;    /* ⚠ 徽章文字 */
    --c-badge-warn-border: #ffeeba;  /* ⚠ 徽章边框 */
    --c-warn-icon: #f0a020;          /* ⏳ 待修左条(暖橙) */
    --c-warn-text-strong: #7a5200;   /* 待修文字/说明 */
    --c-warn-text-alt: #b45309;      /* 🤖+⏳ 双标并存时的说明文字 */
    --c-accent-purple-faint: #fbfaff;/* 🤖 标记行底(极淡) */
    --c-accent-purple-overlap: #b08df0;/* 🤖+⏳ 左条过渡色(双标并存) */
    --c-review-wrong-bg: #fff5f5;    /* 回顾·答错行底 */
    --c-ai-connected-text: #1e7e46;  /* AI 已连接文字 */
    --c-ai-connected-bg: #e9f7ef;    /* AI 已连接底 */
    --c-border-hairline: #eef0f3;    /* 极浅分隔边框(卡片内的极淡分隔) */
    /* ===== 题库卡配色(👤 2026-09-11 选定的 5 色 + 默认灰)=====
       每色一对:--c-bank-<名字> = 底色,--c-bank-<名字>-border = 边框。
       ⚠️ 成对出现、只在这里定义;卡片靠 [data-color] 取值(见 .bank-item[data-color=...])。
       底色刻意压到"低饱和":卡片里还要放徽章与按钮,底色一浓就抢内容。
       蓝/绿/红/琥珀的底色复用了既有的用途令牌,边框为卡片新加。 */
    --c-bank-blue: var(--c-info-bg);
    --c-bank-blue-border: #b9c6dd;
    --c-bank-green: var(--c-success-soft);
    --c-bank-green-border: #a7e0c1;
    --c-bank-red: var(--c-danger-soft);
    --c-bank-red-border: #f3c0c6;
    --c-bank-amber: var(--c-warn-bg-soft);
    --c-bank-amber-border: #ecd39a;
    --c-bank-teal: #eef7f8;
    --c-bank-teal-border: #a9cfd6;
    /* ===== 内容区内边距(统一,三页共用;改动只改这两行) ===== */
    --pad-x: 24px;                   /* 左右留白 */
    --pad-top: 16px;                 /* 标题栏与首模块之间的呼吸位 */
    --pad-bottom: 32px;
    /* ===== 宽度档位(见 DESIGN.md §13;唯一来源,勿在别处写死像素) ===== */
    --reading-width: 640px;   /* 阅读档:刷题容器 / 结果页 / 首页与题库页模块 */
    --modal-sm: 500px;        /* 表单/确认类弹窗 */
    --modal-lg: 760px;        /* 导入预览 / 题库编辑 */
    --page-width: 1000px;     /* 全局 .container */
    /* --- 以下为「无等价令牌」的独立颜色,亮色值 = 原硬编码值,保证零视觉变化 --- */
    --c-star-border: #fd7e14;        /* ☆ 收藏 hover 边框(亮橙) */
    --c-star-text: #b4690e;          /* ★ 收藏激活文字(深橙) */
    --c-star-bg: #fff8e1;            /* ★ 收藏激活底 */
    --c-option-exp-text: #fd7e14;    /* 选项解释文字(橙色,逐题模式) */
    --c-star-hover-bg: #fffaf0;      /* ☆ 收藏 hover 底 */
    --c-input-border: #ced4da;       /* 表单输入边框 */
    --c-review-unanswered-border: #c3e6cb; /* 回顾·未作答行边框 */
    --c-selected-text: #2c5282;      /* 编辑器选中行文字(深蓝) */
    --c-selected-bg-strong: #e7f0ff; /* 待修+选中行底 */
    --c-selected-text-strong: #1c3d7c;/* 待修+选中行文字 */
    --c-accent-purple-tint: #fbf7ff; /* 🤖+⏳ 双标并存行底(比 faint 更紫) */
}

/* Zquiz · 期末周刷题 样式 */

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: "Microsoft YaHei", "PingFang SC", sans-serif;
    line-height: 1.6;
    color: var(--c-text);
    background-color: var(--c-bg);
    padding: 24px;
}

.container {
    max-width: var(--page-width);
    margin: 0 auto;
    background-color: var(--c-surface);
    border-radius: 6px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
    /* 注意:不能设 overflow:hidden —— 祖先裁剪会让 header 的 position:sticky 失效。
       圆角由子元素各自处理(手机端 container 无圆角)。 */
}

header {
    background-color: var(--c-primary);
    color: #fff;
    /* 收窄:标题栏只承载品牌 + 导航 | AI 状态键 + 主题键 */
    padding: 8px 12px;
    /* 品牌 / 导航 / AI 状态键 / 主题键同处一条(否则 nav 会作为独立一条横在标题栏与内容之间,
       形成"导入题库卡片上方一大块空白";👤 反馈实测 99px)。
       ⚠️ 必须用 flex,不能用三栏 grid:手机端 nav 是 position:fixed 会脱离文档流,
       grid 仍会给它保留一列 → 品牌被挤半行(实测反馈过的排版错乱)。flex 下缺席的子项自动退出排布。
       (2026-09-14 曾为"让 AI 键落在正中"短暂用过 grid `1fr auto 1fr`;当天 👤 又要求
        "AI 键挨着主题键" ⇒ 不再需要中列,回到 flex 两段式:左组 | 右组。) */
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    /* 悬浮:吸顶常驻,长列表滚动时站名与主题键始终可达(👤 反馈);
       阴影用来与内容分层,否则同一块蓝底会看起来"粘"在内容上 */
    position: sticky;
    top: 24px;              /* 桌面 body 有 24px padding,偏移对齐才不露背景带 */
    z-index: 20;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
}

/* 品牌块:logo + 右下角小字。用 h1 保留"页面唯一一级标题"的语义,
   small 作副题并右对齐到 logo 末端,形成从属关系(👤 要求小字在 logo 右下) */
h1.brand {
    min-width: 0;              /* 窄屏可收缩,不把右侧那组挤出屏幕 */
    font-size: 16px;
    font-weight: 600;
    line-height: 1.2;
}

/* 小字紧跟在 logo 后面的右下角:同一行、按基线对齐,所以它天然贴在 logo 的右下,
   且不会像右对齐块那样在 logo 下方多占一行(👤 两次反馈)。 */
.brand-tagline {
    margin-left: 6px;
    font-size: 10px;
    font-weight: 400;
    color: rgba(255, 255, 255, 0.75);
    white-space: nowrap;
}

/* 桌面:nav 是标题栏内的一行(样式由 header 的 grid 定位;此处只做外观) */
nav {
    display: flex;
    justify-content: center;   /* 导航按钮组在标题栏中部 */
    background: none;
    border-bottom: none;
    gap: 4px;
}

.nav-btn {
    flex: none;
    /* 导航文字不折行:中文每个字都能断行,不写这句的话"导航的 min-content"会被算成
       三个字各占一行那么窄 —— 标题栏左组据此收缩,实测 769~860px 处导航溢出到 AI 状态键底下。
       写上它,导航宽度才是它真实需要的宽度,标题栏左组也才收缩不到不该缩的地方。 */
    white-space: nowrap;
    padding: 6px 12px;
    border: none;              /* 必须显式写:否则浏览器默认按钮边框会露成黑边 */
    background: none;
    cursor: pointer;
    font-family: inherit;
    border-radius: 6px;
    font-size: 14px;
    color: rgba(255, 255, 255, 0.8);
}

.nav-btn:hover {
    background-color: rgba(255, 255, 255, 0.12);
}

.nav-btn.active {
    background-color: #fff;
    color: var(--c-primary);
    border-bottom: none;
}

/* 品牌靠左(右组靠右由 header 的 space-between 负责) */


/* 内容区统一内边距:三个分区共用同一套值(👤 要求"以后统一")。
   顶部必须留一点呼吸位 —— 曾一次设成 0,结果刷题/题库页内容直接贴住标题栏。 */
main {
    padding: var(--pad-top) var(--pad-x) var(--pad-bottom);
}

.section {
    display: none;
}

.section.active {
    display: block;
}

h2 {
    margin-bottom: 24px;
    color: var(--c-text);
    font-size: 24px;
}

h3 {
    margin-bottom: 16px;
    color: var(--c-text-secondary);
    font-size: 16px;
}

.info-card {
    background-color: var(--c-surface-alt);
    border-radius: 6px;
    padding: 24px;
    margin-bottom: 24px;
}

.info-card ul {
    margin-left: 24px;
}

.info-card li {
    margin-bottom: 8px;
}

#file-input {
    display: none;
}

/* ⚠️ 这里原先给 #upload-btn 硬写了主色实心(id 特指度压过类)—— 于是首页出现了**两个蓝按钮**,
   主次被抹平(👤 2026-09-13 重构时发现)。现在它就是一个普通的次要按钮,
   样式一律走 .action-btn.secondary,别再单独特判。 */


/* ==================== 刷题设置(重设计:三级结构 + 分段控件) ====================
   顺序 = 决策顺序:题源 → 范围 → 模式 → (折叠)题型/随机。
   题源与模式每次都要选,裸露;题型与随机低频,收进 details。 */
.quiz-settings {
    background-color: var(--c-surface-alt);
    border-radius: 12px;
    padding: 16px;
    margin-bottom: 16px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    /* 与刷题容器/结果页/首页模块同宽(阅读档)。原先没有 max-width,
       桌面上会撑满 952px,比首页与题库页宽出一截 —— 三页同宽是硬要求。 */
    max-width: var(--reading-width);
    margin-left: auto;
    margin-right: auto;
}

/* 分段控件:一行多选一,替代竖排 radio,省行数 */
.seg {
    display: flex;
    gap: 2px;
    padding: 2px;
    background: var(--c-border-light);
    border-radius: 6px;
}

.seg label {
    flex: 1;
    position: relative;
    cursor: pointer;
}

/* 隐藏原生圆点,选中态由整段高亮表达(与刷题选项卡片同一套语言) */
.seg input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.seg span {
    display: block;
    text-align: center;
    padding: 8px 4px;
    font-size: 14px;
    color: var(--c-text-secondary);
    border-radius: 4px;
    white-space: nowrap;
}

.seg input:checked + span {
    background: var(--c-surface);
    color: var(--c-primary);
    font-weight: 600;
}

/* 分段控件在 :focus-visible 时给出键盘可达性反馈(原生 input 已隐藏) */
.seg input:focus-visible + span {
    outline: 2px solid var(--c-primary);
    outline-offset: 1px;
}

.setting-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.setting-row label {
    font-size: 14px;
    color: var(--c-text-muted);
    flex: none;
}

.setting-row select {
    flex: 1;
}

/* 随机出题顺序:单开关,裸露(👤 反馈:折叠碍事,故题型与随机都不再收进 details)。
   注意 .seg label 是 flex:1,这里必须显式 flex:none,否则会被拉满整行。 */
.setting-check {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    color: var(--c-text-secondary);
    flex: none;
    min-height: 40px;   /* 触控目标下限(界面规范 §8) */
}

.action-btn {
    background-color: var(--c-primary);
    color: white;
    border: none;
    padding: 12px 24px;
    border-radius: 6px;
    cursor: pointer;
    font-size: 16px;
    transition: background-color 0.3s;
}

.action-btn:hover {
    background-color: var(--c-primary-deep);
}

.action-btn.secondary {
    background-color: var(--c-text-muted);
}

.action-btn.secondary:hover {
    background-color: var(--c-primary-hover);
}

/* 「正在进行」态(目前只有「🤖 AI 整理输入框」用):**按钮仍然可点**(再点一次 = 取消)。
   ⚠️ 绝不能用 `disabled` 表示忙 —— 被 disabled 的按钮不再派发 click,文案里的"点击取消"就成了空话
      (👤 2026-09-14 报的 bug)。这里用 `.is-busy` 换配色,并用 box-shadow 描边(不占布局,避免整排按钮抖动)。 */
.action-btn.is-busy {
    background-color: var(--c-surface);
    color: var(--c-primary);
    box-shadow: inset 0 0 0 1px var(--c-primary);
}
.action-btn.is-busy:hover {
    background-color: var(--c-surface-alt);
}

.status-message {
    margin-top: 16px;
    padding: 8px 16px;
    border-radius: 6px;
    display: none;
}

.status-message.success {
    background-color: var(--c-success-bg);
    color: var(--c-success-text);
    display: block;
}

.status-message.error {
    background-color: var(--c-danger-bg);
    color: var(--c-danger-text);
    display: block;
}

.quiz-container {
    background-color: var(--c-surface-alt);
    border-radius: 6px;
    padding: 16px 24px 24px;   /* 顶部收到 16:上面是吸顶标题栏,不需要再留 24px */
    margin-top: 8px;           /* 原 24px:与 main 的 --pad-top 叠加后题干区离标题栏 64px,太空 */
    max-width: var(--reading-width);   /* 阅读宽度:选项行不拉满千像素 */
    margin-left: auto;
    margin-right: auto;
}

.question-content {
    margin-bottom: 24px;
}

.question-content h3 {
    margin-bottom: 8px;
    color: var(--c-text);
}

.explanation {
    color: var(--c-success);
    font-style: italic;
    margin-bottom: 8px;
}

.options-container {
    margin-bottom: 24px;
}

.option-item {
    position: relative;
    margin-bottom: 16px;
    padding: 8px;
    border-radius: 6px;
    transition: background-color 0.3s;
}

.option-item:hover {
    background-color: var(--c-border-light);
}

.option-item input[type="radio"],
.option-item input[type="checkbox"] {
    /* 原生圆点隐藏:选中态由卡片高亮表达(👤 验收反馈);保留可聚焦可切换 */
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}

.option-label {
    font-weight: 500;
    color: var(--c-primary);
}

.option-text {
    color: var(--c-text-secondary);
}

.option-explanation {
    color: var(--c-option-exp-text);
    font-style: italic;
    margin-top: 4px;
    padding-left: 25px;
}

.answer-feedback {
    background-color: var(--c-surface-alt);
    border-radius: 6px;
    padding: 16px;
    margin-bottom: 24px;
}

.answer-feedback p {
    margin-bottom: 8px;
}

/* 操作区:左侧题目元信息(序号/题型/收藏/连对),右侧动作按钮。
   元信息从题目头部下移到这里 —— 头部不再占一行,题目可直接贴顶(👤 反馈)。 */
.quiz-controls {
    display: flex;
    align-items: center;      /* meta 行与按钮组共用一条中线 */
    gap: 8px;
    margin-top: 12px;
}

/* 刷题状态栏左区:答题卡(进度)+ 智能切题 同一行(👤 定调 2026-09-11)。
   两行结构已取消 —— 收藏搬去题干上方后,左区只剩一组动作,不再需要第二行。 */
.quiz-meta {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 1px;
    min-width: 0;
    font-size: 14px;
    color: var(--c-text-muted);
}

/* 状态行:左区只剩「智能切题」一个按钮。
   🚨 这里**必须 nowrap**:折行 = 状态栏变高(👤 报的 bug 就是这个现象)。
   防折行的根本办法是不往这里放会随内容变宽的东西 —— 见下面「下一题」的固定宽度规则。 */
.quiz-status {
    display: flex;
    flex-direction: row;
    align-items: center;
    flex-wrap: nowrap;
    gap: 6px;
    line-height: 1.1;
    min-width: 0;
}

.quiz-status #question-number {
    font-size: 14px;
    font-weight: 600;
    color: var(--c-text-secondary);
}

/* 标签行三件的统一高度(👤 要求"统一高度")。
   ⚠️ 三件(答题卡 / 题型徽章 / 收藏)的高度**只能从这里取** —— 各自硬编码就会重新漂移成
   28/20/22 那种高低不齐;手机档只改这一个值,三件一起变。 */
:root {
    --tag-row-h: 28px;
}

/* 题干上方的标签行:[答题卡(含进度)] [题型] [☆收藏](👤 定调 2026-09-11)。
   ⚠️ 铁律:这排按钮的宽窄变化**不得影响下面题干的宽度**。
   做法 = 本行 `nowrap`,且每个子项 `flex: 0 0 auto`(各自按内容占宽、谁也别想靠伸缩挤别人);
   题干是块级 <h3>、宽度取父容器 100%,与这行里放了几个按钮无关。 */
.question-tags {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: nowrap;        /* 禁止折行:折行会让本行变高,把题干往下推 */
    margin-bottom: 6px;
}
.question-tags > * {
    flex: 0 0 auto;
}

/* 题型徽章:放在题干之前(👤 要求),小号弱化,不抢题干视线。
   ⚠️ 它和答题卡/收藏同处一行,**三者必须等高**(👤 要求"统一高度")——
   先前徽章靠 padding+line-height 撑出 20px,与相邻按钮的 28px 参差,一行看着高低不齐。
   改为 inline-flex 居中 + 与按钮同一套 min-height。 */
.question-type-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--tag-row-h);
    padding: 0 10px;
    border-radius: 999px;
    background: var(--c-panel-bg);
    color: var(--c-text-muted);
    font-size: 12px;          /* 与旁边两个按钮同字号:三件等高也要等"视觉重量",11px 会显得小一号 */
    line-height: 1.2;
}

/* 行内轻提示:替代 alert 的窄条(琥珀底),出现在状态栏上方 */
.quiz-hint {
    margin: 0 0 6px;
    padding: 6px 10px;
    border-radius: 6px;
    background: var(--c-warn-bg-soft);
    color: var(--c-warn-text-deep);
    font-size: 13px;
    text-align: center;
}

/* 智能切题:带框胶囊按钮(👤 要求"有框的按钮"),文案即作用,不用用户猜。
   中号尺寸(👤 定调 2026-09-11"合理放大"):mini 版只有 15px 高,手机上点不准也看不出是可点的按钮,
   故统一到 28px 高 / 13px 字 —— 明确是按钮,又不抢「下一题」的位置。 */
.auto-next {
    margin-left: 0;
    padding: 0 12px;
    min-height: var(--tag-row-h);
    border: 1px solid var(--c-border);
    border-radius: 999px;
    background: var(--c-surface);
    color: var(--c-text-muted);
    font-family: inherit;
    font-size: 12px;          /* 与标签行三件统一 */
    line-height: 1.3;
    cursor: pointer;
    white-space: nowrap;
}

/* 开启态:主色描边 + 主色文字 + 淡底,一眼可辨 */
.auto-next.is-on {
    border-color: var(--c-primary);
    color: var(--c-primary);
    background: var(--c-info-bg);
    font-weight: 600;
}

/* 收藏按钮:住在标签行第三位(👤 定调)。
   ⚠️ 必须与答题卡、题型徽章**等高**(👤 要求"统一高度"):三个不同高度(28/20/22)排一行
   看起来高高低低。字号提到 12px、min-height 与按钮一致,并清掉自带的 margin-left:auto。 */
.question-tags .favorite-btn {
    margin-left: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0 10px;
    min-height: var(--tag-row-h);
    font-size: 12px;
    line-height: 1.2;
    border-radius: 999px;
}

/* ⚠️ 不要给 .quiz-actions 用 margin-left:auto 把它推右 —— 那会让它在 flex 兄弟
   (可收缩的 .quiz-meta)旁边被压到 0 宽,里面的按钮跟着塌成 w=0(实测:disp=block 但 w=0,
   表现为"按钮不见了")。改为 auto 外边距 + flex:0 0 auto 明确要求"按内容占宽"。 */
.quiz-actions {
    display: flex;
    gap: 8px;
    flex: 0 0 auto;          /* 按内容占宽,绝不被压缩 */
    margin-left: auto;       /* 靠右 */
    min-width: 0;
}

/* 按钮本身按文字宽度,不收缩 */
.quiz-actions .action-btn {
    flex: 0 0 auto;
    white-space: nowrap;
}

/* 🚨 「下一题」在两种文案下必须有**相同宽度**(👤 报的 bug):
   多选未判分时它变成「确认答案」,文案变长 → 按钮变宽 → 左区被挤窄 →
   左区折行 → 刷题状态栏变高、答题卡与智能切题从左右变上下(👤 实测)。
   治本 = 预留能装下最长文案的最小宽度,并让文字居中;两种状态宽度一致,左区永远不会被挤。
   算宽依据:13px 字号下「确认答案」4 字 ≈ 52px + 左右内边距(9px×2)+ 边框 ≈ 72px,取 76px 留余量。 */
.quiz-actions #next-question-btn {
    min-width: 76px;
    text-align: center;
}

/* 「确认答案」态(👤 方案):多选已勾选、尚未判分时,「下一题」变橘色描边。
   为何不实心橘:--c-warn(#ffc107) 上白字对比度仅 1.63,不可读;
   且末题判分后是蓝色 .ready,两套实心强调色会互相打架。故用描边 + 橘字。 */
.quiz-actions #next-question-btn.confirming {
    background-color: var(--c-warn-bg-soft);
    border: 1px solid var(--c-warn-accent);
    color: var(--c-warn-text-alt);
    font-weight: 600;
}


/* 末题判分完成 →「结束刷题 / 交卷」变色,提示"可以收尾了"(👤 要求)。
   用强调色 + 轻微脉冲,与普通次要按钮区分开。 */
.quiz-actions #end-quiz-btn.ready {
    background-color: var(--c-primary);
    color: #fff;
    font-weight: 600;
    animation: end-ready-pulse 1.6s ease-in-out infinite;
}

@keyframes end-ready-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0); }
    50%      { box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.18); }
}

/* 尊重"减少动态效果"偏好 */
@media (prefers-reduced-motion: reduce) {
    .quiz-actions #end-quiz-btn.ready { animation: none; }
}

/* 翻页按钮的禁用态:仍占位(位置稳定),仅弱化。
   用原生 :disabled —— 它能真正阻止程序化 click,并给无障碍正确语义;
   外观在此显式接管,不依赖浏览器默认禁用样式。 */
.quiz-actions .action-btn:disabled {
    opacity: 0.45;
    cursor: default;
}

.quiz-actions button {
    flex: none;
}

.hidden {
    display: none !important;
}

.quiz-result {
    max-width: var(--reading-width);
    margin-left: auto;
    margin-right: auto;
    background-color: var(--c-surface-alt);
    border-radius: 6px;
    padding: 24px;
    margin-top: 24px;
}

/* ==================== 结果页(重设计:1 行大字 + 1 行 chips) ====================
   原则:数字即主张,标签退让。全部统计信息从 5 行压成 1 行大字 + 1 行 chip。 */
.result-stat {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
}

.result-accuracy {
    font-size: 24px;
    font-weight: 700;
    line-height: 1.2;
    color: var(--c-text);
}

.result-accuracy.ok { color: var(--c-success-text); }
.result-accuracy.bad { color: var(--c-danger-text); }

.result-caption {
    font-size: 14px;
    color: var(--c-text-muted);
}

.result-answered {
    color: var(--c-text-muted);
}

.result-chips {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 10px;
}

.chip {
    font-size: 12px;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--c-border-light);
    color: var(--c-text-secondary);
    white-space: nowrap;
}

.chip.ok { background: var(--c-success-bg); color: var(--c-success-text); }
.chip.bad { background: var(--c-danger-bg); color: var(--c-danger-text); }

.empty-message {
    text-align: center;
    color: var(--c-text-muted);
    font-style: italic;
}

.bank-group {
    margin-bottom: 12px;
}

.bank-toggle {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    background-color: var(--c-surface-alt);
    border: 1px solid var(--c-border-light);
    border-left: 4px solid var(--c-primary);
    border-radius: 6px;
    padding: 12px 16px;
    cursor: pointer;
    font-size: 14px;
    color: var(--c-text);
    text-align: left;
    transition: background-color 0.2s;
    font-family: inherit;
}

.bank-toggle:hover {
    background-color: var(--c-info-bg);
}

.bank-chevron {
    display: inline-block;
    color: var(--c-primary);
    transition: transform 0.2s ease;
}

.bank-toggle.expanded .bank-chevron {
    transform: rotate(90deg);
}

.bank-toggle-name {
    font-weight: 600;
    flex: 1;
}

.bank-count-badge {
    font-size: 12px;
    background-color: var(--c-border-light);
    color: var(--c-text-secondary);
    padding: 2px 8px;
    border-radius: 10px;
}

.bank-errors {
    background-color: var(--c-surface-alt);
    border-radius: 6px;
    padding: 8px;
    margin-top: 8px;
}

.bank-errors.collapsed {
    display: none;
}


/* ==================== 题目卡片(错题 / 收藏 共用一套设计)====================
   👤 定调 2026-09-11:两卡统一。差别只在左条颜色(错题=红、收藏=星橙),
   以及收藏卡展开区多一行"正确答案"。
   结构:.q-card > .q-card-tags(题型 + 徽章 + 收藏 + 删除) + h4 题干 + 选项 + details 答案。

   ⚠️ 标签行在**题干之上、自成一行**,且按钮不得反过来影响题干宽度 ——
   与刷题页 `.question-tags` 同一条规矩(见 DESIGN.md 8.1 附近的宽度陷阱)。 */
/* ⚠️ 两张卡**共用同一个基础类** `.question-card`(不再是"错题卡叫 error-item、收藏卡叫别的"),
   否则任何按类选卡的代码(或未来的样式)都会漏掉其中一种。
   修饰类只表达差异:`.error-card` = 左条红,`.fav-item` = 左条星橙。 */
.question-card {
    background-color: var(--c-surface);
    border-radius: 6px;
    padding: 16px;
    margin-bottom: 16px;
    border-left: 4px solid var(--c-danger);
}
.question-card.fav-item {
    border-left-color: var(--c-star-border);
}

/* 题干上方那一行:题型/徽章在左,收藏与删除靠右(动作归动作,标签归标签) */
.question-card-tags {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: nowrap;            /* 禁止折行:折行会把这行变高、把题干往下推 */
    margin-bottom: 6px;
}
.question-card-tags .question-card-fav {
    margin-left: auto;            /* 把两个动作按钮推到右侧 */
}

/* 卡片里的小按钮:统一高度/字号(与刷题页标签行同一套尺寸),
   ⚠️ 必须显式写 border,否则会露出浏览器默认黑边 */
.question-card-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 26px;
    padding: 0 10px;
    border: 1px solid var(--c-border);
    border-radius: 999px;
    background: var(--c-surface);
    color: var(--c-text-muted);
    font-family: inherit;
    font-size: 12px;
    line-height: 1.2;
    cursor: pointer;
    white-space: nowrap;
    flex: 0 0 auto;
}
/* 标签行里的状态徽章(如「📕 在错题本」)也要与按钮等高 —— 它是唯一非按钮成员,
   不拉齐就会出现 19 vs 26 的落差(实测过)。只作用于卡片标签行内的 .badge,
   不去动别处的徽章(库卡徽章、回顾页徽章各有一套尺寸)。 */
.question-card-tags .badge {
    display: inline-flex;
    align-items: center;
    min-height: var(--tag-row-h);
    padding: 0 8px;
    flex: 0 0 auto;
    white-space: nowrap;
}

.question-card-fav {
    color: var(--c-star-text);
    border-color: var(--c-star-border);
}
.question-card-fav:hover {
    background: var(--c-star-hover-bg);
}
/* 删除:危险动作做成"描边红"而不是实心红 —— 它紧挨着收藏按钮,
   实心红会把这一行的视觉重心全吸走(收藏才是这里的常用动作) */
.question-card-del {
    color: var(--c-danger);
    border-color: var(--c-danger);
}
.question-card-del:hover {
    background: var(--c-danger-bg);
    color: var(--c-danger-text);
}

.question-card h4 {
    margin-bottom: 8px;
    color: var(--c-text);
}

.question-card p {
    margin-bottom: 4px;
}

/* 选项:一行流式展示(错题复盘要看得到选项,但不必做成卡片块) */
.error-options {
    color: var(--c-text-secondary);
    margin-bottom: 8px;
}

/* 题型标:置于题干之前,小字弱化,只做定位不抢视线 */
/* 题型标:行内元素参与标签行(原先是块级 p,单独占一行) */
.error-type-line {
    font-size: 12px;
    font-weight: 600;
    color: var(--c-text-muted);
    flex: 0 0 auto;
    white-space: nowrap;
}

.question-card .correct-answer {
    color: var(--c-success);
    font-weight: 500;
}

.question-card .your-answer {
    color: var(--c-danger);
    font-weight: 500;
}


@media (max-width: 768px) {
    .container {
        border-radius: 0;
    }
    
    nav {
        flex-wrap: wrap;
    }
    
    .nav-btn {
        flex: 1 1 50%;
        padding: 8px;
        font-size: 14px;
    }
    
    /* 注意:此处曾有 .quiz-controls { flex-direction: column },是"旧版竖排操作条"的遗留。
       手机端操作条的权威定义在文件后段的 P0-1.5 刷题聚焦块里(固定底栏 + 单行)。
       两处同特异性会让"后一处胜出"变得隐晦,故删除本条。 */
}


.action-btn.small {
    padding: 8px 16px;
    font-size: 14px;
}

.banks-list {
    max-height: 600px;
    overflow-y: auto;
}

/* 题库卡(👤 2026-09-11 定稿):**去掉左侧蓝装饰条**,改为"低饱和底色 + 同色系边框"。
   - 默认(不设色 / 设「灰」)= 白底 + 普通边框,与站内其它卡片完全一致;
   - 选了色 → 卡片带上 data-color,底色与边框从成对令牌取(见 :root 的 --c-bank-*)。
   ⚠️ 卡片里还要放状态徽章与底部按钮,所以底色必须低饱和;不要把饱和度往上调。 */
.bank-item {
    background-color: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: 6px;
    padding: 16px;
    margin-bottom: 16px;
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.bank-item[data-color="blue"]  { background-color: var(--c-bank-blue);  border-color: var(--c-bank-blue-border); }
.bank-item[data-color="green"] { background-color: var(--c-bank-green); border-color: var(--c-bank-green-border); }
.bank-item[data-color="red"]   { background-color: var(--c-bank-red);   border-color: var(--c-bank-red-border); }
.bank-item[data-color="amber"] { background-color: var(--c-bank-amber); border-color: var(--c-bank-amber-border); }
.bank-item[data-color="teal"]  { background-color: var(--c-bank-teal);  border-color: var(--c-bank-teal-border); }
/* 「灰」是显式的一档,同时也是缺省表现 —— 无需额外规则,写在这里只为说明它存在 */

/* 卡片内的控件改成"半透明白",跟着卡片底色自动适配 ——
   写死 --c-panel-bg 会在彩色底上突兀,而每个色配一套按钮色是维护地狱。 */
/* ⚠️ 只覆盖**未展开**的那颗:`:not(.open)` 不能省 ——
   展开态(.open)必须是"实心主色 + 白字";若被这条半透明白底盖住,就成了**白字压在白底上**,
   浅色卡片上完全看不见(👤 反馈:"点错题/收藏后字体与背景区分不开")。 */
.bank-item[data-color] .bank-card-foot .foot-toggle:not(.open) {
    background: rgba(255, 255, 255, 0.62);
}
html[data-theme="dark"] .bank-item[data-color] .bank-card-foot .foot-toggle:not(.open) {
    background: rgba(255, 255, 255, 0.08);
}

.bank-info h3 {
    margin-bottom: 8px;
    color: var(--c-text);
    font-size: 16px;
}

.bank-info p {
    color: var(--c-text-muted);
    margin: 0;
    font-size: 14px;
}

.bank-item .bank-actions {
    display: flex;
    gap: 8px;
}

.bank-item .bank-actions button {
    flex: none;
    padding: 8px 12px;
    font-size: 14px;
}


/* 首页最外层模块与刷题页同宽 —— 否则首页卡片会撑满 1000px 容器,
   比刷题/结果页(阅读档)明显更宽(👤 反馈"首页明显比后俩页宽")。
   ⚠️ 这里限的是**宽度档位**,与 main 的内边距无关,不要靠调 padding 去解决。 */
#home-section > .operation-card,
#home-section > .home-about,
#home-section > .install-hint,
#banks-section > .banks-header,
#banks-section > .banks-list {
    max-width: var(--reading-width);
    margin-left: auto;
    margin-right: auto;
}

/* 导入卡:上内边距压掉一截(👤 2026-09-14:"「导入题库」上面的空白行缩小")——
   卡头自己还有 38px 最小高,这里只管卡片自己的内边距;左右和下边不动,免得输入框变窄。 */
.operation-card {
    background-color: var(--c-surface-alt);
    border-radius: 6px;
    padding: 24px;
}
.home-import { padding-top: 14px; }

.operation-card h3 {
    margin-bottom: 16px;
    color: var(--c-text);
}

/* 版本信息 + 简介(👤 2026-09-14:在导入模块上方加一块)。
   ⚠️ 手机一屏要同时装下它和导入卡 ⇒ 只给两行:标题行(名字 + 版本)与一句简介。
      别往里加第二句介绍、也别加图标 —— 加什么都是从导入卡的高度里抢。 */
.home-about {
    margin-bottom: 12px;
    /* 灰底 + 圆角 = 与导入卡(.operation-card)和其他模块**同一套观感**(👤 2026-09-14:
       原来它是一段裸文字浮在白底上,跟周围格格不入)。色值取同一个令牌,别各写各的灰。 */
    background-color: var(--c-surface-alt);
    border-radius: 6px;
    padding: 10px 14px;
}
.home-about-title {
    margin: 0;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 6px;
    font-size: 16px;
    font-weight: 600;
    color: var(--c-text);
}
.home-about-ver {
    font-size: 12px;
    font-weight: 400;
    color: var(--c-text-faint);   /* 版本是次要信息,别跟站名抢重 */
}
/* 第二行 = 本次更新内容。排版要点(👤 要求"注意排版、字数"):
   - 标签「本次更新」用淡色、不换行(它是路标,不是内容);
   - 正文 13px / 行高 1.5,靠 ` · ` 分隔 —— 与站内其它计数文案同一套写法;
   - 手机档它可能折成两行,这正是**两行封顶**的边界:再加一条更新就会把导入卡顶出屏幕
     (守卫按 40 字上限卡住,见 src/version.js)。 */
.home-about-note {
    margin: 4px 0 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--c-text-secondary);
}
.home-about-tag {
    margin-right: 6px;
    color: var(--c-text-faint);
    font-size: 12px;
    white-space: nowrap;
}

/* ==================== 首页(👤 2026-09-13 重构:简洁易读、主次得当、手机优先)====================
   层次:① 主任务(粘贴 → 解析预览)② 补救路径(AI 理顺格式,折叠)③ 参考(格式说明,折叠)。
   两条硬规则:全页只有一个主色实心按钮;次要动作永远比它小一号。 */
.home-import .paste-actions {
    display: flex;
    flex-direction: column;      /* 手机:主键独占一行(拇指最好按) */
    gap: 8px;
    margin-top: 10px;
}
/* 唯一的主 CTA:更高、字号更大、实心主色 */
.paste-primary {
    min-height: 48px;
    font-size: 16px;
    font-weight: 600;
    width: 100%;
}
/* 次要动作:两个等宽的小按钮,描边,不与主键争视觉重量 */
.paste-actions-minor {
    display: flex;
    gap: 8px;
}
.paste-actions-minor .action-btn {
    flex: 1 1 0;
    min-height: 40px;
    padding: 0 12px;
    font-size: 14px;
}
/* 撤销:一行内联,用细分隔线与主体分开(它属于"这批数据",不是另一件事) */
.import-undo-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px dashed var(--c-border-light);
}
.import-undo-row .meta-note { flex: 1 1 auto; margin: 0; font-size: 12px; }
.import-undo-row .action-btn { flex: 0 0 auto; }

/* 桌面:主键不拉满(它已经靠颜色和高度分主次),三个动作并排一行 */
@media (min-width: 769px) {
    .home-import .paste-actions { flex-direction: row; align-items: center; }
    .paste-primary { width: auto; min-width: 180px; flex: 0 0 auto; }
    .paste-actions-minor { flex: 1 1 auto; }
    .paste-actions-minor .action-btn { flex: 0 1 160px; }
}


/* 模态框样式 */
.modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
}

/* 二级弹窗(从另一个弹窗里打开的)必须**压在上面**。
   ⚠️ 所有 .modal 同为 z-index:1000 时,谁在上面只看 DOM 顺序 ——
   而「重命名 / 创建题库 / AI 设置」在 HTML 里都排在「题库编辑」之前,
   于是从编辑器里点重命名,对话框会被编辑器盖住、根本没法操作(👤 反馈的 bug)。
   分层:二级 1100 > 一级 1000 > 答题卡抽屉 1200(抽屉本就该在最上)。 */
#rename-bank-modal,
#create-bank-modal,
#ai-settings-modal {
    z-index: 1100;
}

.modal-content {
    background-color: var(--c-surface);
    border-radius: 12px;
    padding: 32px;
    max-width: var(--modal-sm);
    width: 90%;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}

.modal-content h3 {
    margin-bottom: 24px;
    color: var(--c-text);
}

.form-group {
    margin-bottom: 24px;
}

.form-group label {
    display: block;
    margin-bottom: 8px;
    color: var(--c-text-secondary);
    font-weight: 500;
}

.form-input {
    width: 100%;
    padding: 8px;
    border: 1px solid var(--c-input-border);
    border-radius: 6px;
    font-size: 16px;
    font-family: inherit;
}

.form-input:focus {
    outline: none;
    border-color: var(--c-primary);
    box-shadow: 0 0 0 3px rgba(74, 108, 247, 0.1);
}

.modal-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
}

@media (max-width: 768px) {

    .bank-item {
        flex-direction: column;
        align-items: flex-start;
    }

    .bank-item .bank-actions {
        margin-top: 16px;
        width: 100%;
        flex-wrap: wrap;
    }

    .bank-item .bank-actions button {
        flex: 1;
        min-width: calc(50% - 4px);
    }
}


/* 输入框 = 一个盒子(边框/圆角/聚焦环都挂在 `.paste-box` 上,里面就是 textarea 自己)。
   ⚠️ 边框挂在盒子上而不是 textarea 上:聚焦时换的是盒子的边色,
      语义上"整个输入区被激活",也免得角标那种框外元素与 textarea 的边线纠缠。 */
.paste-box {
    position: relative;          /* 抓手的定位参照 */
    border: 1px solid var(--c-border);
    border-radius: 6px;
    background: var(--c-surface);
    /* 底边多留 18px:抓手住在那条带子里,不压文字(压在文字上迟早遮住某一行) */
    padding: 6px 6px 18px;
}
.paste-box:focus-within { border-color: var(--c-primary); }   /* 聚焦环跟着盒子走 */

/* 放大输入框的抓手(👤 2026-09-14:"调节输入框大小的按钮放大一点")。
   ⚠️ 原生那只角(`resize: vertical` 给的)是浏览器画的:小、手机按不到、而且**改不大** ——
      所以关掉原生,自己放一个 26×26(手机 32×32)的,拖它改高度;键盘也能用(↑↓)。 */
.paste-grip {
    position: absolute;
    right: 3px;
    bottom: 3px;
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;                 /* 必须显式写,否则露浏览器默认黑边 */
    background: none;
    color: var(--c-text-faint);
    cursor: ns-resize;
    touch-action: none;           /* 手机上别把拖拽当成滚动 */
    border-radius: 6px;
}
.paste-grip svg { width: 16px; height: 16px; }
.paste-grip:hover,
.paste-grip:focus-visible { color: var(--c-primary); background: var(--c-surface-alt); }
/* 「清空」= 卡头那一行**行尾**的小药丸(👤 2026-09-14)。
   外形向同行的「?」圆键看齐:同高 24px、同描边色、同圆角气质(一个带词、一个只带符号),
   于是这一行读起来是"标题 · 说明 · 动作"三件,而不是"标题旁边趴着一块无关的按钮"。
   ⚠️ `margin-left: auto` 才是"贴行尾":卡头是 flex-start(标题与「?」必须挨着),
      不能改用 space-between —— 那会把标题顶到最左、「?」甩到最右。
   ⚠️ `border` 必须显式声明(不许留空),否则露浏览器默认黑边。
   ⚠️ 它是**擦除**类动作,所以 hover 才露红;静态态保持安静的灰描边。 */
.paste-clear {
    margin-left: auto;           /* 贴到这一行的最右边 */
    flex: none;
    display: inline-flex;
    align-items: center;
    height: 24px;                /* 与「?」圆键同高 */
    padding: 0 10px;
    border: 1px solid var(--c-border);
    border-radius: 999px;
    background: none;
    color: var(--c-text-secondary);
    font-family: inherit;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background-color 0.15s;
}
.paste-clear:hover {
    border-color: var(--c-danger);
    color: var(--c-danger);
    background: var(--c-danger-soft);
}

#paste-input {
    display: block;
    width: 100%;
    box-sizing: border-box;
    border: none;
    background: none;
    border-radius: 0;
    padding: 0 2px;
    font-size: 16px;   /* >=16px:避免 iOS 聚焦自动放大 */
    line-height: 1.7;
    resize: none;                 /* 原生调节角关掉:换成 .paste-grip,见上 */
    min-height: 120px;
    font-family: inherit;
    word-break: break-word;
    overflow-wrap: anywhere;
    /* 🚨 必须是 pre-wrap,**不能是 pre**(👤 2026-09-13 报"提示字显示不全"):
       `pre` = 保留换行但**关掉自动换行** —— 长行会横向溢出、右边被裁(实测框宽 340,
       一行内容 760,每行只看得到前半截)。`pre-wrap` 两件事都做:粘贴进来的原始换行照旧保留,
       超宽的行自动折行。UA 给 textarea 的默认值本来就是 pre-wrap,这条只是别把它改坏。 */
    white-space: pre-wrap;
}

#paste-input:focus {
    outline: none;   /* 聚焦环由 .paste-box:focus-within 负责(见上) */
}

.paste-actions {
    margin-top: 8px;
    display: flex;
    gap: 8px;
}

.modal-lg {
    max-width: var(--modal-lg);
}

.preview-summary {
    color: var(--c-text-secondary);
    font-size: 14px;
    margin-bottom: 12px;
}

.preview-toolbar {
    display: flex;
    gap: 24px;
    margin-bottom: 8px;
    font-size: 14px;
    color: var(--c-text-secondary);
}

.inline-label {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    cursor: pointer;
}

/* 编辑器「只看待补答案」标签:与上一按钮留出间隔(原为内联 margin) */
.editor-pending-label {
    margin-left: 10px;
}

.preview-list {
    max-height: 46vh;
    overflow-y: auto;
    border: 1px solid var(--c-border-light);
    border-radius: 6px;
    padding: 8px;
    background: var(--c-surface-alt);
}

/* 预览工具栏紧凑按钮(原内联 padding/字号) */
.preview-tools-btn {
    padding: 4px 10px;
    font-size: 0.85em;
}

.preview-item {
    background-color: var(--c-surface);
    border: 1px solid var(--c-border-light);
    border-radius: 6px;
    padding: 8px 12px;
    margin-bottom: 8px;
}

.preview-item.warn {
    border-color: var(--c-warn);
    background: var(--c-surface-warm);
}

.preview-item-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

.preview-num {
    font-weight: bold;
    color: var(--c-primary);
    font-size: 14px;
}

.badge {
    display: inline-block;
    font-size: 12px;
    padding: 2px 8px;
    border-radius: 10px;
    background: var(--c-border-light);
    color: var(--c-text-secondary);
}

.badge.warn-badge {
    background: var(--c-warn-bg);
    color: var(--c-badge-warn-text);
    border: 1px solid var(--c-badge-warn-border);
}

.preview-conf {
    margin-left: auto;
    font-size: 12px;
    color: var(--c-text-faint);
}

.preview-stem {
    width: 100%;
    box-sizing: border-box;
    border: 1px solid var(--c-border-light);
    border-radius: 6px;
    padding: 8px 8px;
    font-size: 14px;
    line-height: 1.5;
    font-family: inherit;
    resize: vertical;
}

.preview-stem:focus {
    outline: none;
    border-color: var(--c-primary);
}

.preview-options {
    font-size: 12px;
    color: var(--c-text-secondary);
    margin: 8px 0;
    line-height: 1.8;
}

.preview-edit-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    color: var(--c-text-secondary);
    flex-wrap: wrap;
}

.preview-answer {
    width: 90px;
    border: 1px solid var(--c-border);
    border-radius: 6px;
    padding: 4px 8px;
    font-size: 14px;
}

.preview-answer:focus {
    outline: none;
    border-color: var(--c-primary);
}

.preview-analysis {
    font-size: 12px;
    color: var(--c-text-faint);
    flex: 1;
    min-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* 多题库导入横幅:说清"这个文件里有几个库、要怎么导"(👤 要求:导入时自动认出多题库) */
.preview-multi-banner {
    margin: 0 0 10px;
    padding: 10px 12px;
    border: 1px solid var(--c-primary);
    border-radius: 8px;
    background: var(--c-info-bg);
}
.preview-multi-text {
    margin: 0 0 8px;
    font-size: 13px;
    font-weight: 600;
    color: var(--c-primary);
}
.preview-multi-modes {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}
/* 预览条目上的库名徽章:让用户能核对"切分对不对",而不是盲信 */
.badge.bank-badge {
    border-color: var(--c-primary);
    color: var(--c-primary);
    background: var(--c-info-bg);
}

.preview-import-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
    font-size: 14px;
    color: var(--c-text-secondary);
    flex-wrap: wrap;
}

.preview-import-row .bank-select {
    min-width: 180px;
}

/* 多行题干正常换行显示 */
.question-content h3 {
    white-space: pre-line;
}

/* ==================== 套题模式 + 答题回顾 ==================== */

.review-toolbar {
    margin: 8px 0;
    font-size: 14px;
    color: var(--c-text-secondary);
}

.answer-review {
    max-height: 50vh;
    overflow-y: auto;
    text-align: left;
    border: 1px solid var(--c-border-light);
    border-radius: 6px;
    padding: 8px;
    background: var(--c-surface-alt);
    margin-bottom: 16px;
}

.review-item {
    background-color: var(--c-surface);
    border: 1px solid var(--c-border-light);
    border-radius: 6px;
    padding: 8px 12px;
    margin-bottom: 8px;
}

.review-item.review-wrong {
    border-color: var(--c-danger);
    background: var(--c-review-wrong-bg);
}

.review-item.review-unanswered {
    border-color: var(--c-warn);
    background: var(--c-surface-warm);
}

.review-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

.review-num {
    font-weight: bold;
    color: var(--c-primary);
    font-size: 14px;
}

.badge.ok-badge {
    background: var(--c-success-bg);
    color: var(--c-success-text);
    border: 1px solid var(--c-review-unanswered-border);
}

.review-stem {
    font-size: 14px;
    color: var(--c-text);
    margin: 4px 0;
    white-space: pre-line;
}

.review-options {
    font-size: 12px;
    color: var(--c-text-muted);
    margin: 8px 0;
    line-height: 1.8;
}

.review-answers {
    font-size: 14px;
    color: var(--c-text-secondary);
    margin: 4px 0;
}

.review-analysis {
    font-size: 12px;
    color: var(--c-text-faint);
    margin: 4px 0 0;
    line-height: 1.6;
}


/* ==================== 收藏夹 + 错题闭环提示 ==================== */

.favorite-btn {
    margin-left: auto;
    background: none;
    border: 1px solid var(--c-border);
    border-radius: 999px;
    padding: 3px 12px;
    font-size: 14px;
    color: var(--c-text-muted);
    cursor: pointer;
    transition: background-color 0.2s, color 0.2s, border-color 0.2s, transform 0.2s;
    font-family: inherit;
}

.favorite-btn:hover {
    border-color: var(--c-star-border);
    color: var(--c-star-border);
}

.favorite-btn.active {
    background: var(--c-star-bg);
    border-color: var(--c-star-border);
    color: var(--c-star-text);
    font-weight: 600;
}

.favorite-meta {
    font-size: 12px;
    color: var(--c-text-faint);
    margin-bottom: 8px;
}

.mastery-note {
    color: var(--c-success);
    font-size: 14px;
}

.question-card .mastery-note {
    font-size: 12px;
    margin: 8px 0 0;
}


/* 编辑器布局 */
.editor-layout {
    display: grid;
    grid-template-columns: 220px 1fr;
    gap: 16px;
    margin-top: 12px;
}

.editor-list-panel {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.editor-question-list {
    flex: 1;
    max-height: 62vh;          /* 表单搬走后列表就是主角,给它更多高度(👤:原来太矮,下面一大片空白) */
    overflow-y: auto;
    border: 1px solid var(--c-border-light);
    border-radius: 6px;
    background: var(--c-surface-alt);
    padding: 8px;
}

/* ---------- 题目列表工具行 + 筛选面板(👤 2026-09-12 重构)----------
   工具行 = 筛选(点开面板)+ 去重 + 计数。三个都是"小工具",统一做成 32px 描边胶囊:
   与库卡/内容区的大按钮拉开层级,一眼看出"这是列表的控制器,不是内容"。 */
/* 工具行的外层:**sticky 悬浮**(👤 要求:列表滚动时这一行一直贴在顶上)+ 筛选悬浮面板的定位锚。
   sticky 本身就是"已定位"元素,绝对定位的子元素以它为包含块,所以面板挂在这里是对的;
   ⚠️ 面板**不能**放进 .editor-toolbar 里 —— 手机档工具行要横向滚动(overflow-x:auto),
      滚动容器会把绝对定位的面板裁掉。 */
/* 工具条吸顶(👤 2026-09-13:要在滚动区**最顶上**贴死,上面不许有缝)。
   缝的来源:滚动容器有上内边距,`top:0` 只是贴到内容区顶部,那 12px 的 padding 会把滚过去的列表透出来。
   做法:① `top` 取负的上内边距 → 正好贴到滚动区上边缘;② 负的横向边距 + 同值自身内边距,
   让底色**铺满整条**(左右也不露缝),同时内容仍与下方列表左对齐。 */
.editor-toolbar-wrap {
    position: sticky;
    top: calc(-1 * var(--editor-pad-top, 0px));
    z-index: 20;                /* 压在列表之上、筛选面板(60)之下 */
    margin: calc(-1 * var(--editor-pad-top, 0px)) calc(-1 * var(--editor-pad-x, 0px)) 6px;
    padding: var(--editor-pad-top, 0px) var(--editor-pad-x, 0px) 8px;
    background: var(--c-surface);
    border-bottom: 1px solid var(--c-border-light);   /* 吸顶后与列表有一条分界,内容从下面滑过去 */
}
.editor-toolbar {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.list-tool {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: 24px;          /* 矮一档:它是"控制器",不该和内容抢高度(👤 要求) */
    padding: 0 9px;
    border: 1px solid var(--c-border);
    border-radius: 999px;
    background: var(--c-surface);
    color: var(--c-text-secondary);
    font-family: inherit;
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    white-space: nowrap;
}
.list-tool:hover { border-color: var(--c-primary); color: var(--c-primary); background: var(--c-info-bg); }
/* 有筛选生效时按钮自己就带记号(小圆点计数),不用点开也知道"列表被筛过" */
.list-tool.active {
    border-color: var(--c-primary);
    color: var(--c-primary);
    background: var(--c-info-bg);
    font-weight: 600;
}
.list-tool-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--c-primary);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
}
.list-tool-caret { font-size: 10px; opacity: 0.7; }
.editor-toolbar-count { margin-left: auto; }   /* 计数贴右:它是"结果",与左边的控制区分开 */

/* 筛选面板 = **悬浮卡片**(👤 要求):点开时浮在列表之上,不把列表往下挤。
   桌面两列排组(4 组 → 2 行),手机一列;整体高度靠"矮 chip + 紧间距"压住。 */
.filter-panel {
    position: absolute;
    top: calc(100% + 6px);      /* 贴在工具行正下方 */
    left: 0;
    z-index: 60;                /* 压在列表/批量栏之上(与回收站浮层同层) */
    width: min(440px, 92vw);
    max-height: 62vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 10px 12px;
    border: 1px solid var(--c-border);
    border-radius: 8px;
    background: var(--c-surface);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.16);
    display: grid;
    grid-template-columns: 1fr 1fr;   /* 桌面:两组一行,高度直接砍半 */
    gap: 8px 14px;
    align-items: start;
}
.filter-group {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin: 0;
}
.filter-group-title {
    flex: 0 0 3.2em;
    padding-top: 5px;          /* 与 chip 文字 baseline 对齐 */
    font-size: 12px;
    color: var(--c-text-faint);
}
.filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    flex: 1 1 auto;
}
.filter-chip {
    display: inline-flex;
    align-items: center;
    min-height: 22px;          /* 矮 chip:一行放得下更多条件,面板才压得扁(👤 要求) */
    padding: 0 8px;
    border: 1px solid var(--c-border);
    border-radius: 999px;
    background: var(--c-surface);
    color: var(--c-text-secondary);
    font-family: inherit;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    white-space: nowrap;
}
.filter-chip:hover { border-color: var(--c-primary); color: var(--c-primary); }
/* 选中:实心主色底 —— "已生效的条件"必须一眼数得清(只靠描边色差太弱) */
.filter-chip.active {
    border-color: var(--c-primary);
    background: var(--c-primary);
    color: #fff;
    font-weight: 600;
}
.filter-foot {
    grid-column: 1 / -1;        /* 跨满两列 */
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 2px;
    padding-top: 8px;
    border-top: 1px dashed var(--c-border-light);
}
.filter-foot .meta-note { margin: 0; flex: 1 1 auto; }
.filter-clear {
    flex: 0 0 auto;
    min-height: 22px;
    padding: 0 8px;
    border: 1px solid var(--c-border);
    border-radius: 999px;
    background: var(--c-surface);
    color: var(--c-text-muted);
    font-family: inherit;
    font-size: 12px;
    cursor: pointer;
}
.filter-clear:hover { border-color: var(--c-danger); color: var(--c-danger-text); background: var(--c-danger-bg); }

/* ---------- 批量操作栏(选中 ≥1 才出现)—— **就在工具行里**(👤 要求:放到筛选/去重后面)----------
   不做成底部独立栏:那会再吃掉一条高度,还会把列表挤短;放进工具行后,"控制器"只有一处。 */
.bulk-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-left: auto;      /* 贴工具行右端:左边是常驻工具,右边是"选中后才出现"的动作 */
}
.bulk-count {
    flex: 0 0 auto;
    font-size: 12px;
    font-weight: 600;
    color: var(--c-primary);
    white-space: nowrap;
}
.bulk-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 24px;       /* 与工具键同高,整行才齐 */
    padding: 0 10px;
    border: 1px solid var(--c-border);
    border-radius: 8px;
    background: var(--c-surface);
    color: var(--c-text-secondary);
    font-family: inherit;
    font-size: 13px;
    cursor: pointer;
    white-space: nowrap;
}
.bulk-btn:hover { border-color: var(--c-primary); color: var(--c-primary); background: var(--c-info-bg); }
/* 主键「编辑」:唯一实心(选中即最可能的意图) */
.bulk-btn.primary {
    border-color: var(--c-primary);
    background: var(--c-primary);
    color: #fff;
}
.bulk-btn.primary:hover { background: var(--c-primary-deep); border-color: var(--c-primary-deep); color: #fff; }
.bulk-btn.primary:disabled {
    border-color: var(--c-border);
    background: var(--c-surface-alt);
    color: var(--c-text-faint);
    cursor: not-allowed;
}
/* 危险键「删除」:描边红,不抢主键的位置 */
.bulk-btn.danger { border-color: var(--c-danger); color: var(--c-danger-text); }
.bulk-btn.danger:hover { background: var(--c-danger-bg); }

/* 列表末尾的「＋」:新增题目这一行本身(👤 要求:按钮变成列表末尾的加号) */
.editor-list-add {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 40px;
    margin-top: 4px;
    border: 1px dashed var(--c-border);   /* 虚线 = "这里还能再加一行" */
    border-radius: 6px;
    background: none;
    color: var(--c-text-muted);
    font-family: inherit;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}
.editor-list-add:hover {
    border-color: var(--c-primary);
    color: var(--c-primary);
    background: var(--c-info-bg);
}

/* 题目列表(👤 2026-09-12 重构):每行 = 复选框 + 序号 + 题干 + 标签徽章。
   行本身是 <label>:点行里任何地方都等于勾选 —— 手机上不用去戳那个小方块。
   动作不在行里(渲染 N 行就是 N 份按钮,又吵又难点):选中之后统一出现在批量操作栏。 */
.q-row {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 36px;
    padding: 5px 8px;
    border-radius: 6px;
    cursor: default;            /* 整行不可点(👤 要求:只有复选框能选中) */
    user-select: none;          /* 扫读时别把文字拖成一片蓝 */
}
.q-row:hover { background: var(--c-info-bg); }
/* 待修改 / AI 整理过的题:只用**底色 + 徽章**表达,不加左侧色条
   (👤 2026-09-12:"题目条左边的蓝条…很丑" —— 列表里一排竖条像栅栏,状态交给徽章说) */
/* 待修改(缺答案 / 选项不足):淡黄底 + 警示色文字。**.q-row.ai-gen 已删** —— 它只负责一根紫色左条,
   现在 AI 标记由 🤖 徽章表达(不留死 CSS)。 */
.q-row.needs-fix { background: var(--c-warn-bg-soft); }
.q-row.needs-fix .q-row-text { color: var(--c-warn-text-strong); }
/* 当前题(单击高亮):淡底 + 加粗,**没有左侧色条**(👤 说那根蓝条很丑)。
   双击才会翻开编辑卡片 —— 高亮本身只是"我正看着这一道"。 */
.q-row.current { background: var(--c-selected-bg-strong); }
.q-row.current .q-row-text { font-weight: 600; color: var(--c-selected-text); }
/* 已勾选:整行淡蓝底,一眼看出"这几道要被处理" */
.q-row.picked { background: var(--c-info-bg); }
.q-row.picked .q-row-text { color: var(--c-primary); }
.q-row-check {
    flex: 0 0 auto;
    width: 18px;
    cursor: pointer;            /* 唯一可点的地方,光标要说得明白 */
    height: 18px;
    margin: 0;
    accent-color: var(--c-primary);   /* 勾选态用主色,和全站一致 */
    cursor: pointer;
}
.q-row-no {
    flex: 0 0 auto;
    min-width: 1.6em;
    text-align: right;
    font-size: 12px;
    color: var(--c-text-faint);
    font-variant-numeric: tabular-nums;   /* 序号右对齐且等宽,竖着扫下来是齐的 */
}
.q-row-text {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 14px;
    color: var(--c-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;        /* 一行一道题:列表是"扫"的地方,不是"读"的地方 */
}
.q-row-badges {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;            /* 窄屏徽章自己换行,不挤题干 */
    justify-content: flex-end;
}
.q-badge {
    display: inline-flex;
    align-items: center;
    height: 18px;
    padding: 0 6px;
    border-radius: 999px;
    border: 1px solid var(--c-border);
    background: var(--c-surface);
    color: var(--c-text-muted);
    font-size: 11px;
    line-height: 1;
    white-space: nowrap;
}
.q-badge.type { border-color: var(--c-border-light); color: var(--c-text-secondary); }
.q-badge.warn { border-color: var(--c-warn-border, var(--c-border)); color: var(--c-warn-text, var(--c-text-secondary)); background: var(--c-warn-bg-soft); }
.q-badge.ai   { border-color: var(--c-ai-border, var(--c-border)); color: var(--c-ai-text, var(--c-text-secondary)); background: var(--c-ai-bg-soft, var(--c-info-bg)); }
.q-badge.dim  { color: var(--c-text-faint); }

.editor-form-panel {
    min-width: 0;
}

#editor-form .form-group {
    margin-bottom: 12px;
}

#editor-form textarea,
.editor-option-input {
    width: 100%;
    box-sizing: border-box;
    border: 1px solid var(--c-border);
    border-radius: 6px;
    padding: 8px 8px;
    font-size: 14px;
    font-family: inherit;
    line-height: 1.5;
}

#editor-form textarea:focus,
.editor-option-input:focus,
#editor-answer:focus {
    outline: none;
    border-color: var(--c-primary);
}

.editor-inline-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.editor-inline-row select {
    padding: 4px 8px;
    border: 1px solid var(--c-border);
    border-radius: 6px;
    font-size: 14px;
}

.editor-option-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

.editor-option-letter {
    font-weight: 600;
    color: var(--c-primary);
    width: 20px;
}

.editor-option-actions {
    display: flex;
    gap: 8px;
    margin-top: 8px;
}

.editor-nav-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 16px 0;
    flex-wrap: wrap;
}

.editor-position {
    font-size: 14px;
    color: var(--c-text-faint);
}

@media (max-width: 768px) {
    .editor-layout {
        grid-template-columns: 1fr;
    }
}


/* ==================== 手机适配补丁(题库管理 + 模态框) ==================== */

/* 格式说明等 pre 长行换行,防止整页横向溢出(真机 375px 实测问题) */
.operation-card pre {
    white-space: pre-wrap;
    word-break: break-word;
    font-size: 12px;
    line-height: 1.65;
    overflow-x: auto;
}

/* 导入撤销卡片按钮竖排 */
.undo-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 8px;
}
.undo-actions .action-btn {
    width: 100%;
}

@media (max-width: 768px) {
    .operation-card {
        padding: 16px 16px;
    }
    .modal-content {
        padding: 24px 16px;
    }
    .modal-actions {
        flex-wrap: wrap;
    }
    .preview-item-head {
        flex-wrap: wrap;
    }
    .preview-actions-row,
    .inline-label {
        flex-wrap: wrap;
    }
}

/* ==================== 模态框手机适配:超高可滚动(编辑器超屏修复) ==================== */
.modal {
    overflow-y: auto;
}
.modal-content {
    margin: auto; /* flex + margin auto:矮时居中,高时可滚动 */
}
.editor-inline-row {
    flex-wrap: wrap;
}
.editor-option-row .editor-option-input {
    flex: 1;
    min-width: 0;
    width: auto;
}
@media (max-width: 768px) {
    .editor-question-list {
        max-height: 30vh;
    }
    .modal-content {
        width: 95%;
    }
}

/* ==================== 方案 A:大卡片即点即判(手机刷题交互) ==================== */

/* 选项整行卡片:整行可点,触达 ≥44px */
.option-item {
    position: relative;
    display: block;
    border: 2px solid var(--c-border-light);
    border-radius: 10px;
    padding: 12px 16px;
    margin-bottom: 8px;
    cursor: pointer;
    background-color: var(--c-surface);
    transition: border-color 0.15s, background-color 0.15s;
}
.option-item:hover {
    border-color: var(--c-info-border);
}
.option-item.selected {
    border-color: var(--c-primary);
    background: var(--c-info-bg);
}
.option-item.correct-card {
    border-color: var(--c-success-deep);
    background: var(--c-success-soft);
}
.option-item.wrong-card {
    border-color: var(--c-danger-deep);
    background: var(--c-danger-soft);
}
.option-item input {
    accent-color: var(--c-primary);
}
.option-item label {
    display: flex;
    gap: 8px;
    align-items: flex-start;
    font-size: 14px;
    line-height: 1.55;
    cursor: pointer;
}
.option-item .option-label {
    font-weight: 700;
    color: var(--c-primary);
}
.option-item.correct-card .option-label {
    color: var(--c-success-deep);
}
.option-item.wrong-card .option-label {
    color: var(--c-danger-deep);
}

@media (max-width: 768px) {
    /* 拇指热区:主操作按钮全屏宽大按钮 */
    #submit-answer-btn,
    #next-question-btn,
    #prev-question-btn,
    #end-quiz-btn {
        width: 100%;
        padding: 16px;
        font-size: 16px;
    }
}

.prompt-toggle {
    background: none;
    border: 1px solid var(--c-info-border);
    border-radius: 999px;
    padding: 3px 8px;
    font-size: 12px;
    color: var(--c-primary);
    cursor: pointer;
}
.prompt-content {
    margin-top: 8px;
    padding: 8px;
    background-color: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: 6px;
    font-size: 12px;
    line-height: 1.6;
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 300px;
    overflow-y: auto;
    color: var(--c-text-secondary);
}
.prompt-content.hidden {
    display: none;
}

/* ==================== 文件常驻提示块 + 预览筛选 ==================== */
.file-notice {
    border-radius: 6px;
    padding: 8px 12px;
    font-size: 14px;
    line-height: 1.6;
    margin-bottom: 12px;
}
.file-notice.warning {
    background: var(--c-warn-bg-soft);
    border: 1.5px solid var(--c-warn-border);
    color: var(--c-warn-text-deep);
}
.file-notice.info {
    background: var(--c-info-bg);
    border: 1.5px solid var(--c-primary);
    color: var(--c-text-secondary-deep);
}
.file-notice.hidden {
    display: none;
}

/* ==================== 0.9.0 · AI 兜底 ==================== */
.preview-ai-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
    flex-wrap: wrap;
}
.ai-progress {
    flex: 1;
    min-width: 80px;
    height: 8px;
    background: var(--c-border-light);
    border-radius: 6px;
    overflow: hidden;
}
.ai-progress-fill {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, var(--c-primary), var(--c-accent-purple));
    transition: width 0.3s;
}
.ai-progress-text {
    font-size: 12px;
    color: var(--c-text-faint);
    white-space: nowrap;
}
/* AI 拟答(模式二):琥珀色 = "AI 给了内容,请核验",与模式一的紫标(改了格式)区分开 */
.badge.ai-answer-badge {
    background: var(--c-warn-bg);
    color: var(--c-warn-text-deep);
    border: 1px solid var(--c-warn-border);
}

.badge.ai-badge {
    background: var(--c-accent-purple-bg);
    color: var(--c-accent-purple-text);
}
.preview-item.ai-touched {
    box-shadow: inset 3px 0 0 var(--c-accent-purple);
    background: var(--c-accent-purple-tint);
}


.file-notice-actions {
    margin: 8px 0 4px;
}
.file-notice-hint {
    font-size: 0.85em;
    color: var(--c-text-faint);
    margin: 4px 0 0;
}

/* ==================== 导入模块重构(状态区合一 + 救援区) ==================== */
.card-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}
.card-link {
    background: none;
    border: 1px solid var(--c-border);
    border-radius: 999px;
    padding: 3px 8px;
    font-size: 0.85em;
    color: var(--c-text-secondary);
    cursor: pointer;
}
.card-link.ai-connected {
    border-color: var(--c-success-deep);
    color: var(--c-ai-connected-text);
    background: var(--c-ai-connected-bg);
    font-weight: 600;
}
/* 品牌 + 导航的左组:标题栏左侧一整块(👤 2026-09-14)。
   存在的理由:标题栏是 space-between,**只有正中的孩子才会落在中间**;nav 单独当孩子会被平摊,
   AI 状态键就偏到 2/3 处。手机档 nav 是 position:fixed 会脱离本组,组内只剩品牌 —— 不影响。
   ⚠️ 本组不许加 transform / filter / backdrop-filter:那会让 fixed 的 nav 以本组为包含块。 */
.header-left {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;              /* 手机档必须能收缩(否则品牌把右侧那组挤出屏幕) */
}

/* 桌面档:左组与导航都不许被压。
   ⚠️ 为什么必须写在这里:媒体查询不加优先级,全靠源序 —— 放在文件上半部分会被上面这条
      基规则的 `min-width: 0` 盖掉(实测踩过一次:规则明明写了却不生效)。
   ① 左组抬到 min-content:grid 的 1fr 列按剩余空间算,平板竖屏那种"窄桌面"(769~1050px)
      算出来的列宽比"品牌 + 导航"实际所需还窄 —— 内容会溢到 AI 状态键底下;
   ② 导航本来就是 .header-left 的弹性子项(默认可缩),一压按钮里的字就换行
      (实测 769px 处导航被从 236px 压到 188px、品牌小字折成两行、标题栏从 48px 涨到 54px)。
      导航是"固定宽度的三颗按钮",宽度不是拿来伸缩的。 */
@media (min-width: 769px) {
    .header-left { min-width: min-content; }
    /* 导航不缩(它是固定宽度的三颗按钮),让**品牌**去吸收"窄桌面"那几十像素的缺口:
       品牌缩了只是小字折到第二行(标题栏 48→54px),导航缩了却是按钮里的字溢出到 AI 状态键底下。
       实测 769~866px 这段(平板竖屏刚过断点)两个选择都出现,取前者。 */
    header nav { flex: none; }
}

/* 标题栏右侧一组 = AI 状态键 + 主题键(👤 2026-09-14:AI 已连接键在主题键**左边**)。
   两件都是"App 级设置",挨着放成一组;左侧一组仍是品牌 + 导航。 */
.header-right {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
}

/* 标题栏中间的 AI 状态键(👤 2026-09-14 从导入卡片挪来)。
   ⚠️ 蓝底标题栏上不能沿用卡片的描边样式(白底描边在蓝底上像一块脏补丁)——改用半透明白胶囊,
   与 nav 的未选中态同一套观感;连上以后沿用站内的"已连接"绿(暗色下自动切深色令牌)。 */
.header-ai {
    flex: 0 1 auto;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    background: rgba(255, 255, 255, 0.14);
    border-color: rgba(255, 255, 255, 0.38);
    color: #fff;
}
.header-ai:hover { background: rgba(255, 255, 255, 0.24); }
.header-ai.ai-connected {
    background: var(--c-ai-connected-bg);
    border-color: var(--c-success-deep);
    color: var(--c-ai-connected-text);
}

/* ---- 「导入题库」右边的「?」= 支持的题目格式悬浮面板 ----
   它搬过两次家:👤 2026-09-13 从首页底部的常驻折叠块收成「?」;👤 2026-09-14 从卡片右上角
   挪到**标题右边**(贴着标题 = 一眼看出它说的是这件事)。
   ⚠️ 与回收站同一套路:浮层用 absolute(不占文档流)+ `[open]` 显式控制显隐
      —— 本机 chromium 上闭合的 details **仍会渲染 children**(DESIGN §3.7 记过这个坑)。 */
.home-help { position: relative; display: inline-flex; }
/* 首页导入卡的卡头 = **自己一套**(不再靠弹窗那条漏过来的规则):👤 2026-09-13 要求
   「?」在"输入框模块的右上角",而漏过来的 `padding: 0 48px 0 8px` + `justify-content:center`
   会把控件永远挤在中间(右边还空着 48px)。这里回到 §3.7 的口径:h3 在左、动作组贴右、无多余右侧留白;
   底部分隔线 / 44px 最小高 / 15px 标题保持**原来的观感**(👤 没要求改观感,就不改)。 */
.home-import .card-head {
    position: relative;          /* 手机档悬浮面板(static 的 .home-help)的定位参照 */
    display: flex;
    align-items: center;
    /* ⚠️ flex-start,不是 space-between(👤 2026-09-14 把「?」挪到标题右边之后):
       space-between 会把**两个孩子分别顶到左右两端**,标题与「?」被拉开一整行 ——
       而「?」说明的就是"导入题库"这件事,它必须贴着标题。 */
    justify-content: flex-start;
    gap: 8px;
    flex-wrap: wrap;
    /* 38px:够放进 28px 的「清空」与 24px 的「?」,又不至于在标题上方留一条空带
       (👤 2026-09-14:"「导入题库」上面的空白行缩小")。 */
    min-height: 38px;
    padding: 0;
    margin-bottom: 8px;
    /* 🚫 这里原来有一条 `border-bottom` 做"卡头与输入框的分隔线",👤 2026-09-14 要求删掉:
       卡头的灰底 + 标题本身就分得开,再加一条线只是噪音。 */
}
.home-import .card-head h3 { margin: 0; font-size: 15px; }
.home-help-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border: 1px solid var(--c-border);
    border-radius: 50%;              /* 圆形,与相邻的胶囊「⚙ AI 设置」区分开 */
    background: none;
    color: var(--c-text-secondary);
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    list-style: none;                /* 去掉 summary 的三角 */
}
.home-help-btn::-webkit-details-marker { display: none; }
.home-help-btn:hover,
.home-help[open] .home-help-btn {
    border-color: var(--c-primary);
    color: var(--c-primary);
}
.home-help-panel {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;                         /* 触发器在标题右边(左半侧),面板贴它的**左**边才对位 */
    z-index: 60;                     /* 悬浮菜单档(见 DESIGN §3.8) */
    width: min(440px, calc(100vw - 32px));
    max-height: 60vh;                /* 悬浮面板不许撑高页面 */
    overflow-y: auto;
    padding: 12px 14px;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);   /* 阴影只给悬浮层,卡片静态态不加 */
}
.home-help:not([open]) > .home-help-panel { display: none; }   /* 🚨 闭合时必须显式隐藏 */
.home-help-panel > p:first-child { margin-top: 0; }
.home-help-panel > p:last-child { margin-bottom: 0; }
.home-help-title {
    margin-bottom: 6px;
    font-weight: 600;
    color: var(--c-text);
}
.home-help-panel pre {
    margin: 10px 0;
    padding: 10px;
    overflow-x: auto;
    background: var(--c-surface-alt);
    border-radius: 6px;
    font-size: 12px;
    line-height: 1.55;
    white-space: pre;
}
/* 🚨 手机档:面板不按触发器定位,改为锚定**整张卡片头部**(`.home-help` 取消定位,
   面板左右都贴头部的边 —— 手机上面板本来就该占满宽度)。
   ⚠️ 这条是踩坑留下的:触发器当年在卡片最右,面板 358px 宽按它右对齐后左边缘跑到屏幕外
   (实测 left = -97px)。触发器如今搬到了标题右边,锚定卡片头部这一招仍然更稳。 */
@media (max-width: 768px) {
    .home-help { position: static; }
    .home-help-panel {
        left: 0;
        right: 0;
        width: auto;
        max-height: 50vh;   /* 更矮一点:手机上一屏还要留出卡片与状态行 */
    }
}
/* 卡片内背景说明小字(原为 index.html 内联 style,无暗色适配) */
.meta-note {
    font-size: 0.85em;
    color: var(--c-text-faint);
}

.status-line {
    margin: 8px 0 4px;
    padding: 8px 12px;
    border-radius: 6px;
    font-size: 0.9em;
    background: var(--c-panel-bg);
    color: var(--c-text-faint);
}
.status-line.success { background: var(--c-success-bg); color: var(--c-success-text); }
.status-line.warning { background: var(--c-warn-bg); color: var(--c-warn-text); }
.status-line.error   { background: var(--c-danger-bg); color: var(--c-danger-text); }
.status-line button { margin: 4px 8px 2px 0; }
/* 按需提示区(AI 兜底:复制提示词交给聊天 AI)。
   👤 2026-09-14:救援区整块删掉,这条路收进状态行下方,**平时占 0 高度**;
   只有真的用得上才长出来(解析不出题 / 没配 AI Key / AI 整理失败),由 bank.js 一起显隐。
   ⚠️ 按钮与说明是一件事的两半,必须同进同出 —— 只露按钮不说发给谁,等于把活儿甩给用户猜。
   ⚠️ 高度不占位靠 `.hidden`(display:none),不是 `visibility` —— 后者照样占布局高度。 */
.ai-fallback {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    padding: 10px 12px;
    background: var(--c-surface-alt);
    border-radius: 8px;
}
.ai-fallback.hidden { display: none; }
.ai-fallback .action-btn { min-height: 40px; padding: 0 12px; font-size: 14px; }
.ai-fallback-note {
    flex: 1 1 160px;             /* 说明吃掉剩余宽度,窄屏自动折到按钮下一行 */
    margin: 0;
    font-size: 12px;
    line-height: 1.5;
    color: var(--c-text-secondary);
}
.ai-fallback .prompt-toggle { flex: 0 0 auto; }
.ai-fallback .prompt-content { flex: 1 1 100%; }   /* 提示词正文整行铺开 */

/* 预览视图切换(双 tab) */
.preview-view-switch {
    display: inline-flex;
    border: 1px solid var(--c-border);
    border-radius: 6px;
    overflow: hidden;
}
.view-tab {
    border: none;
    background-color: var(--c-surface);
    padding: 4px 12px;
    font-size: 0.85em;
    color: var(--c-text-faint);
    cursor: pointer;
}
.view-tab + .view-tab { border-left: 1px solid var(--c-border); }
.view-tab.active {
    background: var(--c-primary);
    color: #fff;
    font-weight: 600;
}
.view-tab span { opacity: 0.85; }

@media (max-width: 600px) {
    /* ⚠️ 老的"所有按钮 flex:1 1 auto 等宽"会把主键与次键拉成一样大,主次就没了 ——
       现在分工交给 .paste-primary / .paste-actions-minor 自己定义(见首页那一节) */
    .paste-box { padding: 3px 8px 8px; }   /* 内边距跟着盒子走(边框在盒子上) */
    #paste-input { min-height: 120px; }
    /* 手机档把「清空」放大一档(24px 高对指头偏细),仍明显小于下排的 40px 次要按钮 */
    .paste-clear { height: 28px; padding: 0 12px; font-size: 13px; }
    /* 🚨 一屏装下「简介 + 导入卡」两个模块:输入框默认矮一档(5 行),要写长文就拖右下角抓手放大。
       实测 360×640 小屏(减掉底部导航 51px 还有 589px 可见)也放得下,见 DESIGN §3.11。 */
    #paste-input { height: 132px; }
    .paste-grip { width: 32px; height: 32px; }
    .paste-grip svg { width: 18px; height: 18px; }
}

/* 工具栏分组标签:看 / 选 / 🤖 三组,一眼分清视图与勾选 */
.preview-toolbar .tool-group {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.preview-toolbar .tool-label {
    font-size: 12px;
    color: var(--c-text-faint);
    background: var(--c-panel-bg);
    border-radius: 6px;
    padding: 2px 8px;
    font-weight: 600;
}

/* 编辑器说明行:AI 与待修双状态并存时逐行显示 */
.editor-ai-note {
    margin: 0 0 8px;
    font-size: 0.85em;
    font-weight: 600;
}

.editor-ai-note.fix-note {
    color: var(--c-warn-text-alt);
}

/* 编辑器:历史标记(人工旗标,保存不消,仅 × 删除) */
.editor-hist-row { margin: 0 0 8px; }
.hist-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: var(--c-panel-bg);
    color: var(--c-text-faint);
    border: 1px solid var(--c-border);
    border-radius: 999px;
    padding: 3px 8px 3px 12px;
    font-size: 0.85em;
    font-weight: 600;
}
.hist-chip button {
    border: none;
    background: var(--c-text-faint);
    color: #fff;
    border-radius: 50%;
    width: 18px;
    height: 18px;
    line-height: 1;
    cursor: pointer;
    font-size: 14px;
    padding: 0;
}

/* 错题本:收藏/删除操作行 */

/* 编辑器说明行:AI 与待修双状态并存时逐行显示 */
.editor-ai-note.stacked > div { margin: 0 0 4px; }

/* ==================== P0-1.2 手机版全出血适配(≤768px 提高显示效率) ==================== */
@media (max-width: 768px) {
    /* 页面与容器:去四边空白/圆角/阴影,内容贴边 */
    body {
        padding: 0;
    }
    /* 手机全出血:标题栏吸到屏幕顶。布局本身已是 flex(见 header 规则),
       这里只把间距收到 8px:标题栏里是"品牌 | AI 状态键 + 主题键"两段,
       12px 在 360px 屏上会把品牌小字挤到第二行(标题栏 40→54px)。 */
    header {
        top: 0;
        gap: 8px;
    }
    .container {
        max-width: 100%;
        border-radius: 0;
        box-shadow: none;
        min-height: 100vh;
    }
    /* 手机:同一套令牌取小档 —— 改内边距只需改这里与 :root,不必再找散落的写死值 */
    :root {
        --pad-x: 12px;
        --pad-top: 12px;
        --pad-bottom: 24px;
    }
    section h2 {
        font-size: 20px;
        margin-bottom: 12px;
    }
    h3 {
        font-size: 16px;
    }

    /* 卡片:收紧内边距,列表密排 */
    .operation-card {
        padding: 16px 12px;
        margin-bottom: 12px;
    }
    /* ⚠️ 必须写在 .operation-card 之后(源序):首页导入卡的上内边距再压一档 ——
       "「导入题库」上面的空白行缩小"(👤 2026-09-14)。只压顶,左右/下不动,免得输入框变窄。 */
    .home-import { padding-top: 8px; }
    .operation-card h3 {
        margin-top: 0;
        margin-bottom: 8px;
    }
    .banks-list,
    .editor-question-list,
    .favorites-list {
        font-size: 14px;
    }

    /* 表单与按钮:高度触控友好但不臃肿 */
    .action-btn {
        padding: 9px 16px;
        font-size: 14px;
    }
    .form-input,
    select,
    textarea {
        font-size: 16px;  /* 防 iOS 聚焦缩放 */
    }

    /* 题库管理双栏在窄屏本就单列;分组头部收紧 */
    .bank-toggle {
        padding: 8px 8px;
    }

    /* 粘贴框与状态行紧凑 */
    .paste-box { padding: 2px 6px 6px; }
    #paste-input {
        rows: auto;
        min-height: 90px;
        font-size: 16px;
    }
    .status-line {
        margin: 8px 0 4px;
        padding: 8px 8px;
        font-size: 14px;
    }

    /* 预览/编辑器条目紧凑 */
    .preview-item {
        padding: 8px;
    }
    .preview-stem {
        font-size: 14px;
    }
    .q-row {
        padding: 8px 8px;
        font-size: 14px;
    }

    /* 首页 hero 收紧 */

}

/* ==================== P0-1.3 导航图标化 + 手机底部固定导航栏 ==================== */
.nav-btn {
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    gap: 8px;
}
.nav-ico { display: inline-flex; }
span.nav-ico svg.nav-ico, svg.nav-ico { width: 16px; height: 16px; display: block; }

@media (max-width: 768px) {
    /* 底部固定 tab 栏:拇指区操作,内容区留出等高空间 */
    /* 手机:nav 脱离标题栏,成为底部固定 tab 栏。
       桌面那套"透明融入标题栏"的样式必须在此显式覆盖,否则底栏会变成透明背景。 */
    nav {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 100;
        background-color: var(--c-surface-alt);   /* 覆盖桌面的 background:none */
        border-top: 1px solid var(--c-border-light);
        box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.06);
        padding: 2px 0 max(2px, env(safe-area-inset-bottom));
        gap: 0;                                    /* 覆盖桌面的 gap:4px */
    }
    .nav-btn {
        flex: 1 1 20%;
        flex-direction: column;
        gap: 1px;
        padding: 8px 2px 4px;
        font-size: 12px;
        border-radius: 6px;
        color: var(--c-text-secondary);            /* 覆盖桌面的白色文字 */
    }
    .nav-btn:hover {
        background-color: var(--c-border-light);   /* 覆盖桌面的半透明白 */
    }
    svg.nav-ico { width: 22px; height: 22px; }
    .nav-btn.active {
        color: var(--c-primary);
        background: var(--c-surface);
        border-bottom: none;
    }
    /* 标题栏里的 AI 状态键:窄屏再收一档,免得把品牌挤掉 */
    .header-ai { padding: 3px 7px; font-size: 11px; }

    /* 内容区给底部栏让位(栏高约 54px + 安全区) */
    main {
        padding-bottom: calc(70px + env(safe-area-inset-bottom));
    }
    .modal-content {
        /* 模态框也不被底栏遮挡 */
        margin-bottom: calc(60px + env(safe-area-inset-bottom));
    }
}

/* ==================== P0-1.4 暗色模式(变量层整体换肤) ==================== */
html[data-theme="dark"] {
    --c-bg: #121417;
    --c-surface: #1c1f24;
    --c-surface-alt: #22262c;
    --c-text: #e9ecef;
    --c-text-secondary: #ced4da;
    --c-text-muted: #adb5bd;
    --c-text-faint: #868e96;
    --c-border: #3f444b;
    --c-border-light: #2c3138;
    --c-primary: #3b82f6;
    --c-primary-deep: #60a5fa;
    --c-success: #3fbf6a;
    --c-success-deep: #4cd07d;
    --c-success-bg: #1d3a26;
    --c-success-text: #8fe3a8;
    --c-danger: #e05260;
    --c-danger-deep: #e8737f;
    --c-danger-bg: #43202a;
    --c-danger-text: #ff9a9a;
    --c-warn: #ffd666;
    --c-warn-bg: #423a15;
    --c-warn-text: #ffd666;
    --c-warn-accent: #e0b34c;
    --c-accent-purple: #a08fd6;
    --c-accent-purple-bg: #2a2440;
    --c-accent-purple-text: #c3b3ff;
    --c-info-bg: #1e2632;
    --c-info-border: #3a4a63;
    --c-panel-bg: #262a30;
    --c-surface-warm: #242320;
    --c-warn-bg-soft: #3a3320;
    --c-success-soft: #0a2e1f;
    --c-danger-soft: #3f0d18;
    /* ===== 裸 hex 收口 · 暗色对应值 =====
       这些在收口前是硬编码亮色 tint,暗色下无法换肤(过亮/刺眼)。
       取值优先复用本表已有的、已验证的暗色语义色,避免引入新色感。 */
    --c-primary-hover: #4a5058;       /* 中灰 hover(暗色下用深一档灰) */
    --c-text-secondary-deep: #a8c0e8; /* info 文字提亮 */
    --c-warn-text-deep: #ffd666;      /* 同暗色 --c-warn-text */
    --c-warn-border: #8a7333;
    --c-badge-warn-text: #ffd666;
    --c-badge-warn-border: #5c4f1f;
    --c-warn-icon: #e0b34c;           /* 同暗色 --c-warn-accent */
    --c-warn-text-strong: #ffd666;
    --c-warn-text-alt: #e0b34c;
    --c-accent-purple-faint: #232030;
    --c-accent-purple-overlap: #7d68b8;
    --c-review-wrong-bg: #3f0d18;     /* 同暗色 --c-danger-soft */
    --c-ai-connected-text: #8fe3a8;   /* 同暗色 --c-success-text */
    --c-ai-connected-bg: #1d3a26;     /* 同暗色 --c-success-bg */
    --c-border-hairline: #2c3138;     /* 同暗色 --c-border-light */
    --c-star-border: #f0a500;          /* 暗色下并入主色橙 */
    --c-star-text: #ffd666;
    --c-star-bg: #3a3320;
    --c-star-hover-bg: #302a1c;
    --c-option-exp-text: #ffd666;
    --c-input-border: #3f444b;
    --c-review-unanswered-border: #2f5c3d;
    --c-selected-text: #b9ccec;
    --c-selected-text-strong: #b9ccec;
    --c-selected-bg-strong: #26313f;
    --c-accent-purple-tint: #2a2440;
    /* 题库卡配色 · 暗色:同色相同样低饱和,但整体压暗(浅底直接套用会刺眼) */
    --c-bank-blue: #1b2430;
    --c-bank-blue-border: #33465e;
    --c-bank-green: #16281f;
    --c-bank-green-border: #2f5140;
    --c-bank-red: #2b1d21;
    --c-bank-red-border: #573039;
    --c-bank-amber: #2a2418;
    --c-bank-amber-border: #55482a;
    --c-bank-teal: #17262a;
    --c-bank-teal-border: #2e4c53;
}
html[data-theme="dark"] {
    color-scheme: dark;
}
/* 暗色下阴影收敛(硬编码阴影在暗底上过重) */
html[data-theme="dark"] .container {
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
}

/* 主题键 = **一个**简约按钮(👤 2026-09-14:原来"自动|亮|暗"三格分段控件太占地方)。
   点一次换一档:自动 → 亮 → 暗 → 自动;三枚图标由 data-theme-pref 决定显示哪一枚。
   ⚠️ 住在标题栏蓝底上,沿用半透明白那一套(令牌是为浅色表面设计的,直接套会在蓝底上糊掉);
   ⚠️ 边框必须显式声明(否则露浏览器默认黑边);尺寸对齐左侧的 AI 状态键(高 28px)。 */
.theme-toggle {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 28px;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.38);
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
    cursor: pointer;
}
.theme-toggle:hover { background: rgba(255, 255, 255, 0.24); }
.theme-ico { width: 16px; height: 16px; display: none; }
.theme-toggle[data-theme-pref="auto"] .ico-auto,
.theme-toggle[data-theme-pref="light"] .ico-light,
.theme-toggle[data-theme-pref="dark"] .ico-dark { display: block; }

/* 刷题进行中 / 出结果后:隐藏配置区与「开始刷题」。
   ⚠️ 这条**必须全屏宽生效**,不能只写在手机媒体查询里 ——
   否则会在桌面上出现"结果页上方还挂着一个开始刷题按钮"(👤 反馈)。
   条件同时覆盖 #quiz-container(作答中)与 #quiz-result(结果页)。 */
#quiz-section.active:has(#quiz-container:not(.hidden)) #quiz-settings,
#quiz-section.active:has(#quiz-container:not(.hidden)) #start-quiz-btn,
#quiz-section.active:has(#quiz-container:not(.hidden)) #quiz-status:empty,
#quiz-section.active:has(#quiz-result:not(.hidden)) #quiz-settings,
#quiz-section.active:has(#quiz-result:not(.hidden)) #start-quiz-btn,
#quiz-section.active:has(#quiz-result:not(.hidden)) #quiz-status:empty {
    display: none;
}

/* ==================== P0-1.5 刷题聚焦模式(手机:题目居中 + 底部固定操作条) ==================== */
@media (max-width: 768px) {
    /* 聚焦布局:quiz 容器占满首屏,题干+选项垂直居中 */
    #quiz-section.active:has(#quiz-container:not(.hidden)) {
        display: flex;
        flex-direction: column;
        min-height: calc(100vh - 76px);  /* 顶栏 + 底部 tab */
    }
    #quiz-section.active:has(#quiz-container:not(.hidden)) #quiz-container {
        flex: 1;
        display: flex;
        flex-direction: column;
        margin-top: 0;
        /* 🚨 必须清掉桌面的居中 auto 边距(`.quiz-container` 的 margin-left/right: auto)。
           本元素在此布局里是 **flex 子项**,而 flex 子项的 auto 横向边距会**吃掉全部剩余空间**,
           元素既不拉伸、又被压到最小内容宽 —— 实测 390px 手机上容器只剩 82px,
           题干与选项全成一条窄柱(👤 报的"很窄很突兀",且**与题干长短无关,每一题都窄**)。
           宽度改由 flex 拉伸决定,故 auto 边距在这里没有任何意义。 */
        margin-left: 0;
        margin-right: 0;
        padding: 8px 0 12px;
        background: transparent;
    }
    /* 同理:结果页也是同一 flex 容器里的子项,auto 边距会让它塌成窄条 */
    #quiz-section.active:has(#quiz-result:not(.hidden)) #quiz-result {
        margin-left: 0;
        margin-right: 0;
    }
    /* 题干直接贴顶(头部已并到下方操作区) */
    #quiz-section.active:has(#quiz-container:not(.hidden)) .question-content {
        margin-top: 0;
    }
    #quiz-section.active:has(#quiz-container:not(.hidden)) #question-text {
        margin-top: 0;
        font-size: 16.5px;
        line-height: 1.55;
    }
    #quiz-section.active:has(#quiz-container:not(.hidden)) #answer-feedback:not(.hidden) {
        margin-top: 8px;
    }
    #quiz-section.active:has(#quiz-container:not(.hidden)) .quiz-controls {
        margin-top: auto;
    }

    /* 操作条固定于底部 tab 栏上方,不随内容滚动。
       手机端**单行**:元信息在左(可压缩),按钮在右(不被压缩)。
       连对徽标已删除,故窄屏能容下;按钮改为自然宽度(不再 flex:1 平分),
       结束刷题等次要按钮因此收窄。 */
    .quiz-controls {
        position: fixed;
        left: 0;
        right: 0;
        bottom: calc(52px + env(safe-area-inset-bottom));
        z-index: 90;
        display: flex;
        flex-direction: row;      /* 单行 */
        flex-wrap: nowrap;
        align-items: center;      /* 左区与按钮组中线对齐 */
        gap: 6px;
        margin-top: 0;
        padding: 6px 8px;         /* 上下各 6:略增高便于点按(👤 要求「增高一点」) */
        background: var(--c-surface);
        border-top: 1px solid var(--c-border);
        box-shadow: 0 -1px 6px rgba(0, 0, 0, 0.05);
    }
    /* 元信息:占剩余空间,空间不足时收缩而不是把按钮挤走 */
    .quiz-meta {
        flex: 1 1 auto;
        min-width: 0;
        gap: 6px;
        font-size: 12px;
    }
    /* 手机档:统一高度收半档(28 → 26) */
    :root { --tag-row-h: 26px; }
    /* 手机档:按钮收小半档(26px),但仍明确是按钮。
       ⚠️ 标签行三件(答题卡/题型/收藏)必须**一起**收 —— 只改其中一个就又不等高了。 */
    .auto-next,
    .question-tags .question-type-badge,
    .question-tags .favorite-btn {
        min-height: var(--tag-row-h);
        padding: 0 10px;
        font-size: 12px;
    }
    /* 答题卡入口的 min-height 在它自己的基础规则里(文件更靠后),这里只需收字号 */
    .question-tags .answer-card-open {
        font-size: 12px;
    }
    /* ⚠️ 左区只剩一个按钮,且状态行禁止折行(👤 报的 bug:折行会让状态栏变高、按钮上下排列)。
       故这里既不设 white-space:nowrap/overflow:hidden(会把按钮文字挤掉),
       也不加 gap —— 左区只需"一个按钮待在左边"。 */
    .quiz-status { white-space: normal; }
    .quiz-meta { gap: 0; }
    /* 按钮组:自然宽度,不收缩 —— 保证"下一题/结束刷题"始终可点 */
    .quiz-actions {
        flex: 0 0 auto;
        flex-wrap: nowrap;
        gap: 6px;
        margin-left: 0;
        width: auto;
    }
    /* 按钮收窄到文字宽度。⚠️ 上面那条"拇指热区"规则用 #id 给了 width:100%,
       特异性高于本类选择器 —— 只写 .quiz-actions .action-btn { width:auto } 会被它压住,
       实测两模式三键各占 236px(整行),三键放不进一行就换行,表现为"只看得到一个按钮"。
       故此处用同等特异性的 #id 选择器覆盖。 */
    .quiz-actions #prev-question-btn,
    .quiz-actions #submit-answer-btn,
    .quiz-actions #next-question-btn,
    .quiz-actions #end-quiz-btn {
        flex: 0 0 auto;
        width: auto;
        margin: 0;
        /* 加高便于点按(约 34px);左右收窄以维持单行(👤 要求:增高、收窄) */
        padding: 9px 10px;
        font-size: 13px;
        line-height: 1.15;
    }
    /* 单行放不下时优先压缩较宽的"上一题/下一题",保证三个按钮都在一行 */
    .quiz-actions #prev-question-btn,
    .quiz-actions #next-question-btn {
        flex: 0 1 auto;
        min-width: 0;
    }
    #quiz-container {
        /* 预留:状态栏(约 42) + 底部 tab 安全区 */
        padding-bottom: calc(56px + env(safe-area-inset-bottom));
    }
}

/* ==================== 验收修复(Y04/Y05) ==================== */
/* 标题栏现为常驻应用栏(站名 + AI 状态键 + 主题键),不再随分区隐藏 —— 见 header 规则 */
/* 修复2:刷题聚焦时选项被固定操作条遮挡 —— 容器预留操作条+底栏高度,可完整滚动 */
@media (max-width: 768px) {
    #quiz-section.active:has(#quiz-container:not(.hidden)) #quiz-container {
        padding-bottom: calc(64px + env(safe-area-inset-bottom));  /* 操作条 50 + 底栏 54 的重叠区 */
    }
    /* 反馈面板与选项之间不被操作条盖住:给反馈区也留出空间 */
    #quiz-section.active:has(#quiz-container:not(.hidden)) #answer-feedback:not(.hidden) {
        margin-bottom: calc(46px + env(safe-area-inset-bottom));
    }
}

/* ==================== 交互规范(Vercel web-interface-guidelines 精选适配) ==================== */
/* 触控:去掉双击缩放延迟与安卓点按高亮 */
button, select, label, .option-item, .bank-toggle, .preview-item, .q-row {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}
/* 键盘可见焦点环(鼠标点击不出现) */
:focus-visible {
    outline: 2px solid var(--c-primary);
    outline-offset: 2px;
    border-radius: 2px;
}
/* 弹窗滚动不穿透背景 */
.modal-content {
    overscroll-behavior: contain;
}
/* 尊重减动效偏好 */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}
/* 状态不只靠颜色:错题本删除钮有文字,收藏有 ★/☆,标记有图标 —— 已符合,此处仅固化规则 */

/* ==================== 0.10.0 视觉语言对齐(slate/emerald/rose) ==================== */
.option-item.correct::after,
.option-item.incorrect::after {
    position: absolute;
    top: 10px;
    right: 12px;
    font-size: 15px;
    font-weight: 700;
    line-height: 1;
}
.option-item.correct::after { content: '✔'; color: var(--c-success); }
.option-item.incorrect::after { content: '❌'; color: var(--c-danger); }

@keyframes feedback-in {
    from { opacity: 0; transform: translateY(-6px); }
    to { opacity: 1; transform: translateY(0); }
}
#answer-feedback:not(.hidden) {
    animation: feedback-in 0.18s ease;
}
#answer-feedback {
    background: var(--c-info-bg);
    border-radius: 6px;
    padding: 8px 12px;
}
body, .container, .operation-card, .modal-content, .quiz-container, nav {
    transition: background-color 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}

/* ==================== P0-1.8 信息架构:3 tab + 题库页/首页重排 ==================== */
/* 题库页头部 = 标题 + **一行三键**(👤 要求:导出题库 / ＋ 创建题库 / 🗑 回收站 与标题同排)。
   靠右不靠"挂在某个键上的 auto 边距"(那会把相邻两键顶开一道缝),而是标题吃满右侧空隙
   (h3 的 margin-right:auto)—— 三个键间的 gap 恒定,整组自然贴右。 */
.banks-header {
    display: flex;
    flex-wrap: wrap;           /* 窄屏:整组一起换行,组内不拆 */
    gap: 8px;
    align-items: center;
    margin-bottom: 16px;
}
.banks-header h3 {
    /* h3 默认自带上下外边距,这里显式归零 —— 否则它会比按钮高出一截,看着不像"同一行" */
    margin: 0 auto 0 0;
}
.banks-header-actions {
    display: flex;
    flex-wrap: nowrap;         /* 三键要么一起在这一行,要么整组一起下去 */
    align-items: center;
    gap: 6px;
}
.recycle-menu {
    position: relative;        /* 浮层的定位锚点 */
    flex: 0 0 auto;
}
/* 三键同一套外形:紧凑胶囊(同高/同圆角/同字号/同内边距)。
   刻意比正文按钮小一号 —— 它们是"页面级工具",不该和库卡里的操作按钮一样重。 */
.banks-header .header-tool,
.banks-header .header-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 32px;
    padding: 0 11px;
    border: 1px solid var(--c-border);   /* 按钮必须显式声明 border,否则露出默认黑边 */
    border-radius: 999px;
    background: var(--c-surface);
    color: var(--c-text-secondary);
    font-family: inherit;
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    white-space: nowrap;
    list-style: none;          /* 回收站是 <summary>,去掉默认三角 */
}
.recycle-pop > summary::-webkit-details-marker { display: none; }
.banks-header .header-tool:hover {
    border-color: var(--c-primary);
    color: var(--c-primary);
    background: var(--c-info-bg);
}
/* 「＋ 创建题库」是这一行**唯一**的实心主键:外形与另两键一致,只靠填充色区分主次 */
.banks-header .header-cta {
    border-color: var(--c-primary);
    background: var(--c-primary);
    color: #fff;
}
.banks-header .header-cta:hover {
    background: var(--c-primary-deep);
    border-color: var(--c-primary-deep);
}
.recycle-pop[open] > summary {
    border-color: var(--c-primary);
    color: var(--c-primary);
    background: var(--c-info-bg);
}
/* ⚠️ 显式控制开合,不依赖 `<details>` 的默认行为:
   实测(2026-09-12)在本机 chromium 上,闭合的 details 仍会把 children 渲染出来
   (open=false 但面板有 44px 高、文字可读)—— 这是原生 details 的 content-visibility 没生效。
   所以自己用 [open] 选择器控制显隐,行为才确定。 */
.recycle-pop:not([open]) > .recycle-pop-panel { display: none; }

/* 「加到主屏」引导(P0-1.4):只在手机档出现,且**已经在独立窗口里跑的时候自动隐藏**。
   ⚠️ 隐藏靠两条:display-mode 媒体查询(现代浏览器)+ html.is-standalone(main.js,兜老 iOS)。 */
.install-hint {
    display: none;
}
@media (max-width: 768px) {
    .install-hint {
        display: block;
        margin: 16px 0 0;
        padding: 10px 12px;
        border: 1px dashed var(--c-border);
        border-radius: 8px;
        background: var(--c-surface-alt);
        color: var(--c-text-faint);
        font-size: 12px;
        line-height: 1.6;
    }
    .install-hint b { color: var(--c-text-secondary); font-weight: 600; }
}
@media (display-mode: standalone) {
    .install-hint { display: none !important; }
}
html.is-standalone .install-hint { display: none !important; }

/* 悬浮面板:绝对定位在触发器下方,贴右边对齐;本身可滚,不撑高页面 */
.recycle-pop-panel {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 60;               /* 要压在库卡之上 */
    width: min(360px, 86vw);
    max-height: 60vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: 8px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.16);
    padding: 8px 12px;
    text-align: left;
}
/* 手机档:浮层贴屏宽,别缩成一条窄柱 */
@media (max-width: 768px) {
    .recycle-pop-panel {
        width: auto;
        left: auto;
        right: 0;
        min-width: min(320px, 92vw);
    }
    /* 手机档:三键统一放大到 **40px 高**(触摸下限),但左右内边距收到 9px、键间距收到 5px ——
       高度要够、横向要省。实测(2026-09-12):11px/6px 时 360px 宽会差 5px 放不下而换行,
       收到 9px/5px 后 360px 宽也能和标题并排(320px 才会整组换行)。 */
    .banks-header-actions { gap: 5px; }
    .banks-header .header-tool,
    .banks-header .header-cta { min-height: 40px; padding: 0 9px; }
}
/* 导入卡在首页:去双栏遗留,全宽。
   注意:**不要再给它 margin-top** —— 曾写 24px,叠加在 main 的顶部呼吸位之上,
   成了"导入题库卡片上方多一块空白"(👤 反馈)。顶部间距统一由 --pad-top 控制。 */
@media (max-width: 768px) {
    /* 手机档把标题也收一档,给三键腾出同一行的空间(360px 宽也能并排) */
    .banks-header h3 { font-size: 15px; }
    .banks-header { gap: 6px; }
}

/* 回收站条目 */
.recycle-item {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding: 8px 4px;
    border-bottom: 1px solid var(--c-border-light);
    font-size: 14px;
    color: var(--c-text-secondary);
}
.recycle-item span { flex: 1; }

/* ==================== P0-1.9 库卡布局:标题徽章行 + 底部三键 + 展开面板 ==================== */
.bank-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 4px;
}
.bank-badges .badge {
    font-size: 12px;
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--c-panel-bg);
    color: var(--c-text-secondary);
}
.bank-badges .err-badge { background: var(--c-danger-bg); color: var(--c-danger-text); }
.bank-badges .fav-badge { background: var(--c-warn-bg); color: var(--c-warn-text); }
.bank-card-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 12px;
}
.bank-card-foot .foot-toggle {
    background: var(--c-panel-bg);
    border: none;
    border-radius: 6px;
    padding: 7px 10px;
    font-size: 13px;
    color: var(--c-text-secondary);
    cursor: pointer;
    font-family: inherit;
}
.bank-card-foot .foot-toggle b { color: var(--c-text); }
.bank-card-foot .foot-toggle.fav { margin-left: auto; }
.bank-card-foot .foot-toggle.open {
    background: var(--c-primary);
    color: #fff;
}
.bank-card-foot .foot-toggle.open b { color: #fff; }
.bank-card-foot .action-btn.small {
    padding: 7px 10px;
    font-size: 13px;
}
.bank-panel-title {
    margin: 0 0 8px;
    font-size: 14px;
    color: var(--c-text-secondary);
}
.bank-errors-panel,
.bank-favorites-panel,
.bank-versions-panel {
    background: var(--c-surface-alt);
    border-radius: 6px;
    padding: 12px;
    margin: -6px 0 8px;
}
/* 版本记录条目(题库设置内):信息占满、右侧两个动作(恢复 / 删除)。
   信息用 flex:1 而不是固定宽:手机上它会换行,动作按钮仍保持一行可点。 */
.version-item {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding: 8px 4px;
    border-bottom: 1px solid var(--c-border-light);
    font-size: 13px;
    color: var(--c-text-secondary);
}
.version-item:last-child { border-bottom: none; }
.version-info { flex: 1 1 auto; min-width: 0; }
/* 删除键做成小巧的方形危险键:与「恢复此版」并排,不能抢主动作 */
.version-del {
    flex: 0 0 auto;
    border: 1px solid var(--c-border);   /* 必须显式声明 border,否则露出默认黑边 */
    background: none;
    border-radius: 6px;
    padding: 4px 8px;
    color: var(--c-text-muted);
    cursor: pointer;
    font-family: inherit;
    font-size: 12px;
    line-height: 1.4;
}
.version-del:hover {
    border-color: var(--c-danger);
    background: var(--c-danger-bg);
    color: var(--c-danger-text);
}

/* 题库卡配色色板(编辑器内):每个色块直接用**卡片同款**底+框,所见即所得 */
.bank-color-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.bank-color-swatch {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-height: 28px;
    padding: 0 10px;
    border: 1px solid var(--c-border);
    border-radius: 999px;
    background: var(--c-surface);
    color: var(--c-text-secondary);
    font-family: inherit;
    font-size: 12px;
    cursor: pointer;
    white-space: nowrap;
}
/* 色块本体:与卡片同一对令牌,保证"色板上看到的 = 卡片上的" */
.bank-color-dot {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    border: 1px solid var(--c-border);
    background: var(--c-surface);
}
.bank-color-swatch[data-color="blue"]  .bank-color-dot { background: var(--c-bank-blue);  border-color: var(--c-bank-blue-border); }
.bank-color-swatch[data-color="green"] .bank-color-dot { background: var(--c-bank-green); border-color: var(--c-bank-green-border); }
.bank-color-swatch[data-color="red"]   .bank-color-dot { background: var(--c-bank-red);   border-color: var(--c-bank-red-border); }
.bank-color-swatch[data-color="amber"] .bank-color-dot { background: var(--c-bank-amber); border-color: var(--c-bank-amber-border); }
.bank-color-swatch[data-color="teal"]  .bank-color-dot { background: var(--c-bank-teal);  border-color: var(--c-bank-teal-border); }
/* 选中态:主色描边 + 加粗(不只靠颜色区分选中) */
.bank-color-swatch.active {
    border-color: var(--c-primary);
    color: var(--c-primary);
    font-weight: 600;
    background: var(--c-info-bg);
}

/* ---------- 题库设置:分块排版(👤 2026-09-12 重新规划) ----------
   一块 = 一个小标题 + 该块自己的控件。块的顺序按"作用对象"排:
   配色 → 本库 → 全部题库 → 错题本 → 版本记录 → 危险操作(最后,且单独染色)。
   块与块之间只用一条浅分隔线,不再给整页加外框:设置页里 6 条边框会变成栅栏。 */
.bank-admin {
    display: flex;
    flex-direction: column;
}
.admin-block {
    padding: 14px 0;
    border-top: 1px solid var(--c-border-light);
}
.admin-block:first-child {
    border-top: none;
    padding-top: 4px;
}
.admin-block-title {
    margin: 0 0 8px;
    font-size: 13px;
    font-weight: 600;
    color: var(--c-text-muted);
}
/* 动作行:按钮**按内容宽 + 统一下限**(不是撑满整行 —— 一颗"清空错题本"拉满 728px
   会在设置页里显得像个主操作,而它只是一次偶尔的数据导出)。桌面一行装得下就并排,
   装不下自动换行。 */
.admin-btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
/* 设置页的按钮:比主操作区小一号(这里是"偶尔来一次"的地方),圆角方框 + 悬停染主色 */
.admin-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;      /* 桌面:宽度跟着文案走(手机档才改成填满整行) */
    min-width: 150px;    /* 同一行几个按钮宽度一致,不会因为"重命名"三个字比"导出本库"窄而参差 */
    min-height: 40px;
    padding: 0 14px;
    border: 1px solid var(--c-border);
    border-radius: 8px;
    background: var(--c-surface);
    color: var(--c-text-secondary);
    font-family: inherit;
    font-size: 14px;
    cursor: pointer;
    transition: border-color 0.15s, background-color 0.15s, color 0.15s;
}
.admin-btn:hover {
    border-color: var(--c-primary);
    color: var(--c-primary);
    background: var(--c-info-bg);
}
/* 危险动作:描边红 + 红字(不用实心红 —— 设置页里实心红按钮太吵,但也不能混进普通按钮里认不出来) */
.admin-btn.danger {
    border-color: var(--c-danger);
    color: var(--c-danger-text);
}
.admin-btn.danger:hover {
    background: var(--c-danger-bg);
}
/* 危险区:整块淡红底 + 红标题,与上面几块一眼分开(👤 反复强调防误点) */
.admin-danger-block {
    margin: 8px 0 4px;
    padding: 14px;
    border: 1px solid var(--c-danger-bg);
    border-radius: 8px;
    background: var(--c-danger-soft);
}
.admin-danger-block .admin-block-title {
    color: var(--c-danger-text);
}
/* 设置项:文案在控件**左边**(与编辑器表单同一口诀),窄屏整体换行不横向滚动 */
.admin-field {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 8px;
}
.admin-field > label {
    flex: 0 0 auto;
    font-size: 13px;
    color: var(--c-text-secondary);
}
.admin-field select {
    flex: 0 1 200px;
    min-height: 40px;   /* 与同一块的按钮等高,基线才对得齐 */
    padding: 0 8px;
    border: 1px solid var(--c-border);
    border-radius: 6px;
    background: var(--c-surface);
    color: var(--c-text);
    font-family: inherit;
    font-size: 14px;
}
/* 块里的说明文字:浏览器给 <p> 的默认上下边距在这个紧凑排版里太大,统一收一道 */
.admin-block .meta-note,
#editor-versions-host .meta-note {
    margin: 0 0 10px;
    line-height: 1.5;
}
/* 版本记录在设置页里也是一个块:去掉卡片态底色/圆角,只留与其它块一致的分隔线 */
#editor-versions-host .bank-versions-panel {
    margin: 0;
    padding: 14px 0;
    border-top: 1px solid var(--c-border-light);
    border-radius: 0;
    background: none;
}
#editor-versions-host:empty {
    display: none;   /* 没挂上面板时不占一条空分隔线 */
}

/* 库卡四象限布局(👤 定稿) */
.bank-item {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    row-gap: 8px;
}
.bank-card-foot {
    grid-column: 1 / -1;
    display: flex;
    justify-content: space-between;  /* 左下错题 / 右下收藏 */
    align-items: center;
}
.bank-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
}

/* ==================== 答题卡抽屉(P0-6.1)====================
   入口 = 刷题状态栏里的进度("3/10")本身:要跳题时视线本来就在那儿,零新增常驻元素。
   规范见 DESIGN.md §3.2。 */

/* 入口(答题卡):中号按钮(👤 定调 2026-09-11"合理放大")。
   从"文字点亮"升级为**有框按钮**:进度数字本身就是用户找的东西,做成按钮才看得出能点 ——
   原先的迷你形态找不到入口,等于这功能没做。开启态用主色描边与「智能切题」同一套语言。 */
.answer-card-open {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    padding: 0 10px;              /* 与题型徽章/收藏一致的三件内边距 */
    min-height: var(--tag-row-h);
    border-radius: 999px;
    /* 显式字号,不用 `font: inherit`(会继承父级 14px)。
       12px = 标签行三件(答题卡/题型/收藏)的统一字号 —— 等高之外还要等视觉重量 */
    font-family: inherit;
    font-size: 12px;
    color: inherit;
    cursor: pointer;
    white-space: nowrap;
}
.answer-card-open:hover,
.answer-card-open:focus-visible {
    border-color: var(--c-primary);
    color: var(--c-primary);
    background: var(--c-info-bg);
}
.answer-card-open-chevron {
    font-size: 10px;
    color: var(--c-text-faint);
    line-height: 1;
}
.answer-card-open:hover .answer-card-open-chevron,
.answer-card-open:focus-visible .answer-card-open-chevron {
    color: var(--c-primary);
}

/* 遮罩:点空白即收起 */
.answer-card-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 1200;
}

/* 抽屉:底部弹出。比遮罩高一档,故不会被挡住 */
.answer-card-drawer {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1201;
    max-height: 62vh;
    overflow-y: auto;
    background: var(--c-surface);
    border-top-left-radius: 16px;
    border-top-right-radius: 16px;
    padding: 12px var(--pad-x) calc(16px + env(safe-area-inset-bottom));
    box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.25);
}

.answer-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 10px;
}
.answer-card-summary {
    font-size: 12px;
    color: var(--c-text-muted);
}
.answer-card-close {
    border: none;
    background: none;
    padding: 2px 6px;
    font-size: 16px;
    line-height: 1;
    color: var(--c-text-muted);
    cursor: pointer;
    border-radius: 6px;
}
.answer-card-close:hover {
    background: var(--c-border-light);
    color: var(--c-text);
}

/* 题号网格:一行 6 格,格子够大,"6 列 × 5 行"在一屏内看完全卷 */
.answer-card-grid {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 8px;
}

/* 格子三态:颜色 + 记号双通道,不只靠颜色区分 */
.answer-card-cell {
    position: relative;
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--c-border);
    border-radius: 10px;
    background: var(--c-surface-alt);
    font-size: 14px;
    font-weight: 600;
    color: var(--c-text-secondary);
    cursor: pointer;
    padding: 0;
}
.answer-card-cell.correct {
    background: var(--c-success-bg);
    border-color: var(--c-success);
    color: var(--c-success-text);
}
.answer-card-cell.wrong {
    background: var(--c-danger-bg);
    border-color: var(--c-danger);
    color: var(--c-danger-text);
}
/* 未答:虚线框 —— 一眼区分"没做"和"做了但没判" */
.answer-card-cell.blank {
    background: var(--c-surface);
    border-style: dashed;
    color: var(--c-text-muted);
}
/* 已选未判分(**套题模式交卷前专用**):中性实底 + 实线 +
   左上角小三角 —— 只表达"选过了",不表达对错。
   ⚠️ 该状态**绝不能用绿/红**:套题交卷前标对错 = 直接在卡上泄题(👤 报的 bug)。 */
.answer-card-cell.picked {
    background: var(--c-panel-bg);
    border-color: var(--c-text-faint);
    color: var(--c-text-secondary);
}
.answer-card-cell.picked::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    border-top: 8px solid var(--c-text-faint);
    border-right: 8px solid transparent;
    border-top-left-radius: 9px;
    pointer-events: none;
}
/* 当前题:外圈描边,不覆盖三态底色(当前题也可能是已答对的题) */
.answer-card-cell.current {
    outline: 2px solid var(--c-primary);
    outline-offset: 1px;
}

/* 题型角标:右上角一个极小的字,单/多/判 */
.answer-card-type {
    position: absolute;
    top: 2px;
    right: 4px;
    font-size: 9px;
    font-weight: 400;
    line-height: 1;
    color: var(--c-text-faint);
}
.answer-card-cell.correct .answer-card-type { color: var(--c-success-text); }
.answer-card-cell.wrong .answer-card-type { color: var(--c-danger-text); }

.answer-card-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 12px;
    font-size: 11px;
    color: var(--c-text-muted);
}
.answer-card-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.answer-card-swatch {
    width: 10px;
    height: 10px;
    border-radius: 3px;
    border: 1px solid var(--c-border);
    background: var(--c-surface);
}
.answer-card-swatch.current { outline: 2px solid var(--c-primary); outline-offset: 1px; }
.answer-card-swatch.correct { background: var(--c-success-bg); border-color: var(--c-success); }
.answer-card-swatch.wrong { background: var(--c-danger-bg); border-color: var(--c-danger); }
.answer-card-swatch.picked { background: var(--c-panel-bg); border-color: var(--c-text-faint); }
.answer-card-swatch.blank { border-style: dashed; }

/* ==================== 题库编辑器重构(👤 2026-09-11:手机优先)====================
   结构:.editor-head(库名+进度) / .editor-body(可滚动) / .editor-foot(固定操作栏)
   设计要点:
   ① **窄屏优先**:手机不靠"两栏 + 横向挤",而是纵向分区、按重要性排序;
   ② **触摸友好**:手机上所有可点元素 ≥44px(苹果 HIG / 安卓 Material 的通行下限);
   ③ **逻辑合理**:题目级操作(改/删这一题)与题库级操作(整库设置)彻底分开 ——
      原先「删除本题」和「保存本题」同排、题库设置夹在题号导航里,手机上极易误操作;
   ④ **不丢东西**:窄屏隐藏的题号列表由头部按钮拉出;次要字段(解释/解析)折叠但不搬走。 */

.modal#edit-bank-modal {
    /* 编辑器独占整屏滚动:自身不滚,滚 .editor-body —— 否则头部与底部操作栏会被滚走 */
    overflow: hidden;
    align-items: stretch;
}
.modal#edit-bank-modal .modal-content {
    display: flex;
    flex-direction: column;
    max-height: 100%;
    min-height: 0;
    padding: 0;                /* 内边距交给各分区,头部/底部才能贴边 */
    overflow: hidden;
}

/* ---------- 头部:库名 + 进度 + 快捷动作 ---------- */
/* 头部收矮(👤 要求"省空间"):只留 关闭 + 库名 + 进度,动作全部下沉到标签页
   高度按内容定,手机上约 44px(与一个触摸目标同高,不再额外占位) */
.editor-head {
    position: relative;        /* 关闭键绝对定位的参照 */
    display: flex;
    align-items: stretch;
    justify-content: center;
    padding: 2px;
    border-bottom: 1px solid var(--c-border-light);
    background: var(--c-surface);
    flex: 0 0 auto;
    min-height: 40px;          /* 内容 40 + 上下 padding 2+2 = 整条 44 */
}
/* 库名**真正居中**:不能靠 flex 的"左右元素等宽"(关闭键只有一个,永远居不正)——
   改为标题占满整宽居中、关闭键绝对定位压在右上角。 */
.editor-head h3 {
    margin: 0;
    font-size: 15px;
    line-height: 1.2;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 48px;           /* 给关闭键留位,长库名也不会压到它 */
    min-width: 0;
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.editor-head-position {
    font-size: 12px;
    color: var(--c-text-faint);
    white-space: nowrap;
}
.editor-head-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
}
.editor-close-x {
    border: none;              /* 按钮必须显式声明 border,否则露出默认黑边 */
    background: none;
    padding: 0;
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    position: absolute;        /* 压在右上角,不参与居中计算 */
    top: 2px;
    right: 2px;
    font-size: 16px;
    line-height: 1;
    color: var(--c-text-muted);
    cursor: pointer;
    border-radius: 6px;
}
.editor-close-x:hover { background: var(--c-border-light); color: var(--c-text); }

/* ---------- 标签条:编辑题目 / 题库设置 ---------- */
.editor-tabs {
    display: flex;
    flex: 0 0 auto;
    border-bottom: 1px solid var(--c-border-light);
    background: var(--c-surface);
}
.editor-tab {
    flex: 1 1 0;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    padding: 0 10px;
    font-size: 14px;
    color: var(--c-text-muted);
    cursor: pointer;
    border-bottom: 2px solid transparent;   /* 选中态用下划线,不只靠颜色 */
    white-space: nowrap;
}
.editor-tab input { display: none; }        /* 视觉由 label 承担,语义仍归 radio */
.editor-tab-count { color: var(--c-text-faint); font-size: 12px; }
.editor-tab:has(input:checked) {
    color: var(--c-primary);
    font-weight: 600;
    border-bottom-color: var(--c-primary);
}
.editor-tab:has(input:focus-visible) { outline: 2px solid var(--c-primary); outline-offset: -2px; }

/* 标签页切换:题目页 = 题号列表 + 当前题;设置页 = 整库设置 */
/* 主体:标签页决定内部怎么排(外层不再自己分栏),同时它是**唯一滚动区** */
.editor-body {
    /* 内边距提成变量:吸顶的工具条要靠它做**负向抵消**(见 .editor-toolbar-wrap),
       两边必须同源 —— 各写各的数字,缝就回来了(👤 反馈过"悬浮时上面有个缝")。 */
    --editor-pad-x: 16px;
    --editor-pad-top: 12px;
    display: block;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--editor-pad-top) var(--editor-pad-x) 16px;
}
.editor-body > .editor-panel { display: none; }
.editor-body[data-tab="question"] > .editor-list-panel,
.editor-body[data-tab="question"] > .editor-question-panel { display: block; }
.editor-body[data-tab="bank"] > .editor-bank-panel { display: block; }
/* ⚠️ 桌面档**不再**是"左 220px 列表 + 右表单"两栏:表单已搬进编辑卡片,那套 grid 会把
   整个题目页压进 220px 的窄列(用户实测"瘦高、右边一大片空白")。列表现在吃满整宽。 */

/* ---------- 编辑卡片:一道题的完整编辑面(👤 2026-09-12 重构)----------
   它是**二级弹窗**(1100 > 编辑器 1000,见 §3.8):从题库编辑器里打开,必须压在编辑器之上。
   三段式:头部(题号 + 上/下一题 + ✕)/ 可滚动主体(六个字段)/ 底部固定(取消 + 保存)。 */
#question-card-modal { z-index: 1100; }
/* ⚠️ 容器类名是 .edit-card,**不能**叫 .question-card:那个名字属于错题/收藏卡,
   它自带 4px 红色左边条 —— 借用它就会让编辑卡片左边凭空长出一道红条(👤 反馈"很丑",已改) */
.edit-card {
    display: flex;
    flex-direction: column;
    width: 94%;
    max-width: var(--modal-sm);
    max-height: 88vh;
    padding: 0;                 /* 卡片自己管三段的内边距,padding 会破坏"底部固定" */
    overflow: hidden;           /* 滚动只发生在 .card-body */
}
/* 🚨 必须限定在 .edit-card 里(2026-09-13 发现):`.card-head` 这个类名**两处共用**
   (首页导入卡 + 编辑题目弹窗),而这条规则写在文件更后面 —— 于是整条泄漏到了首页卡头上:
   `justify-content:center`(标题与右上角控件被挤在中间)、`padding:0 48px 0 8px`(右边空出
   48px,那是给弹窗 ✕ 留的位置)、底边框、44px 最小高。表现就是"右上角控件永远贴不到右上角"。
   → 弹窗自己用 `.edit-card .card-head`,首页卡头在下面自己写一条(见 .home-import 那一节)。 */
.edit-card .card-head {
    position: relative;         /* 关闭键绝对定位的参照 */
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex: 0 0 auto;
    min-height: 44px;
    padding: 0 48px 0 8px;      /* 右侧留出 40px 关闭键的位置 */
    border-bottom: 1px solid var(--c-border-light);
}
.edit-card .card-head h3 {
    margin: 0;                  /* 基础 .modal-content h3 有 24px 下边距,这里必须归零 */
    font-size: 15px;
    font-weight: 600;
    color: var(--c-text);
    white-space: nowrap;
}
.card-nav {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border: 1px solid var(--c-border);
    border-radius: 8px;
    background: var(--c-surface);
    color: var(--c-text-secondary);
    font-family: inherit;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
}
.card-nav:hover:not(:disabled) { border-color: var(--c-primary); color: var(--c-primary); background: var(--c-info-bg); }
.card-nav:disabled { color: var(--c-text-faint); cursor: not-allowed; opacity: 0.6; }
.card-body {
    flex: 1 1 auto;
    min-height: 0;              /* flex 子项要能真的滚,这一行不能少 */
    overflow-y: auto;
    padding: 14px 16px 4px;
}
.card-foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    flex: 0 0 auto;
    padding: 12px 16px;
    border-top: 1px solid var(--c-border-light);
    background: var(--c-surface);
}
/* 撤销键放最左(它跟"保存/取消"不是一伙的:那两个管这张卡,它管之前的编辑) */
.card-undo { margin-right: auto; }
.card-undo:disabled { opacity: 0.5; cursor: not-allowed; }

/* 版本记录里的「撤销上一步 / 重做」一行(会话内;跨会话用下面的列表) */
.version-step-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin: 0 0 8px;
    padding-bottom: 8px;
    border-bottom: 1px dashed var(--c-border-light);
}
.version-step-row .meta-note { flex: 1 1 auto; margin: 0; font-size: 12px; }

/* 题库页的"上次导入"信息行(从首页搬来,只作展示)。
   👤 2026-09-13 二改:位置从**列表上方**挪到**列表最末尾** —— 它是一条归档备注,
   排在库卡前面会抢位置;挪到末尾后与题库卡同列(同走阅读档宽度)、同一层级。 */
.banks-last-import {
    margin: 12px auto 0;
    max-width: var(--reading-width);
    font-size: 12px;
    color: var(--c-text-faint);
}

/* ---------- 主体:唯一滚动区 ---------- */
.editor-panel { min-width: 0; }
.editor-panel-title {
    margin: 0 0 8px;
    font-size: 13px;
    font-weight: 600;
    color: var(--c-text-muted);
}
.editor-panel-count,
.editor-panel-hint {
    font-weight: 400;
    color: var(--c-text-faint);
}
/* 题库设置现在是独立标签页,占满主体宽度 */

/* ---------- 底部固定操作栏 ---------- */
.editor-foot {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--c-border-light);
    background: var(--c-surface);
}
.editor-foot-actions { display: flex; gap: 8px; }

/* ---------- 题目内容区:文案在**输入框左边**,字段占剩余宽度(👤 要求) ---------- */
/* 一行一个字段:左标签定宽(对齐),右字段自适应。
   ⚠️ 用 flex + 固定标签宽而不是表格:窄屏可以整体换行,不必横向滚动。 */
.editor-field {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}
.editor-field > label,
.editor-field > .form-label {
    flex: 0 0 auto;
    width: 4.5em;              /* 容下"题目解释""题型与答案";对齐全靠它 */
    padding-top: 8px;          /* 与第一行输入文字基线对齐 */
    color: var(--c-text-secondary);
    font-size: 14px;
    line-height: 1.3;
}
.editor-field-body {
    flex: 1 1 auto;
    min-width: 0;
}
/* 选项区没有文案:占满整宽 */
.editor-field-plain > .editor-field-body { flex: 1 1 100%; }
.editor-answer-row {
    display: flex;
    gap: 8px;
}
.editor-answer-row select { flex: 0 0 auto; }
.editor-answer-row input { flex: 1 1 auto; min-width: 0; }
.editor-more {
    margin: 4px 0 12px;
    border: 1px solid var(--c-border-light);
    border-radius: 6px;
    padding: 8px 10px;
}
.editor-more > summary {
    cursor: pointer;
    font-size: 13px;
    color: var(--c-text-muted);
}
.editor-more[open] > summary { margin-bottom: 10px; }
.editor-bank-details > summary {
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    color: var(--c-text-secondary);
}
.editor-bank-details[open] > summary { margin-bottom: 8px; }
/* 「删除本题」自带危险色,且与「下一题」拉开距离 —— 防误触 */
.editor-delete-current {
    margin-left: auto;
    color: var(--c-danger);
    border-color: var(--c-danger);
}

/* ---------- 手机档:单列 + 大触达 ---------- */
@media (max-width: 768px) {
    .modal#edit-bank-modal .modal-content {
        width: 100%;
        max-width: none;
        height: 100%;
        margin: 0;
        border-radius: 0;
    }
    .editor-body {
        --editor-pad-x: 12px;
        padding: var(--editor-pad-top) var(--editor-pad-x) 16px;
    }
    /* 手机档:工具行**只允许一行**(👤 要求:「🗑 删除」必须和筛选/去重同一行)——
       挤不下时横向滑动,而不是把批量栏甩到第二行。外边距收紧,把宽度让给按钮。 */
    .editor-toolbar {
        flex-wrap: nowrap;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
        gap: 5px;
    }
    .editor-toolbar::-webkit-scrollbar { display: none; }
    .editor-toolbar .list-tool,
    .editor-toolbar .bulk-btn { flex: 0 0 auto; padding: 0 8px; }
    .bulk-bar { flex: 0 0 auto; margin-left: 2px; gap: 5px; }
    .bulk-count { font-size: 11px; }

    /* 手机档:列表**取消自己的滚动**(👤 反馈"列表太矮、下面一大片空白")——
       原来它被卡在 46vh 的小框里,框下留白;现在让 .editor-body 当唯一滚动容器,列表该多长就多长。 */
    .editor-question-list {
        max-height: none;
        overflow: visible;
        flex: none;
    }
    /* 题库页同理(👤 2026-09-13 反馈"题库滑到最下面再往上滑,底部仍然有悬浮的白条"):
       库列表原来被卡在 max-height:600px 的内滚框里 —— 手机上于是有**两个滚动区**(页面 + 列表框),
       滑到框底再往上滑时页面几乎不动,框底下面是 70px 空白,再接固定的底部 tab 栏,看着就是
       "一条悬浮的白条"。手机档让它**不自己滚**(整页当唯一滚动容器):卡片一直长下去,
       末尾接「上次导入」行,没有"卡在半截"的框底,也没有框下那块空白。
       ⚠️ 桌面档保留 600px 内滚:桌面上列表长了会把「＋ 创建题库」推得很远,内滚更合适。 */
    .banks-list {
        max-height: none;
        overflow: visible;
    }
    /* 题号列表:只留标题一行(它只用来跳题),展开后最多 34vh,不挤掉正在编辑的内容 */
    .editor-list-panel .editor-list-body { display: none; }
    .editor-list-panel.open .editor-list-body { display: block; }
    .editor-list-panel.open .editor-list-caret { transform: rotate(90deg); }
    .editor-list-panel .editor-question-list {
        max-height: 34vh;
        flex: none;
    }
    /* 触摸目标:手机上输入框/按钮不低于 44px */
    #editor-form textarea,
    #editor-form input[type="text"],
    .editor-option-input,
    .editor-answer-row select,
    .editor-answer-row input {
        min-height: 44px;
        font-size: 16px;       /* ≥16px 可避免 iOS 聚焦时自动放大页面 */
    }
    .editor-option-actions .action-btn,
    .editor-nav-row .action-btn,
    .editor-foot .action-btn,
    .editor-head-actions .action-btn,
    /* 设置页按钮:手机档改成**填满整行**(拇指友好 —— 手机上一行两颗各占一半,单颗独占一行),
       并覆盖桌面档的 40px(手机上 40 是下限里偏紧的一档)。 */
    .admin-btn {
        flex: 1 1 140px;
        min-height: 44px;
        padding: 0 14px;
    }
    /* 复选框放大到 24px:现在它是**唯一**的选中入口,必须自己就足够好点 */
    .q-row { min-height: 44px; }
    .q-row-check { width: 24px; height: 24px; }
    /* 零散控件也要够得着:色块、AI 补答案、关闭 ✕、移出规则下拉、复选框 */
    .bank-color-swatch { min-height: 44px; padding: 0 12px; }
    .editor-list-del { min-width: 44px; font-size: 14px; }
    /* 选中行右端的「保存」也要够得着(👤 定的 44 阈值) */
    /* 控制条(筛选/去重/批量)在手机上矮一档:👤 明确要求"太高占空间"。
       34px 仍高于误触底线里偏紧的一档,且这些键横向很宽、彼此有间距,实打实好点。 */
    .bulk-btn { min-height: 34px; padding: 0 12px; font-size: 13px; }
    .list-tool { min-height: 34px; }
    .filter-chip { min-height: 30px; }
    /* 编辑卡片底部的保存/取消是**主要动作**,仍守 44;只有它俩守 */
    .card-foot .action-btn { min-height: 44px; }
    .card-nav { width: 36px; height: 36px; }
    .editor-list-add { min-height: 44px; }
    .version-item .action-btn,
    .version-item .version-del { min-height: 44px; }
    .version-item .version-del { min-width: 44px; }
    .editor-tab { min-height: 44px; }
    /* 左标签在手机上收窄一档:文案仍完整,字段能多出一列字的宽度 */
    .editor-field > label,
    .editor-field > .form-label { width: 4em; font-size: 13px; padding-top: 12px; }
    #editor-add-btn { min-height: 44px; }
    .editor-ai-answer-row .action-btn,
    .editor-option-actions .action-btn { min-height: 44px; }
    .editor-close-x {
        /* 这里是 40 不是 44:头部是"省空间"的地方,44 会让整条涨到 49px。
           40px 依然远超误触阈值(拇指目标下限通常 40–44),换来的是一行多出的可读面积。 */
        width: 40px;
        height: 40px;
        font-size: 18px;
    }
    .admin-field select {
        min-height: 44px;
        font-size: 16px;   /* ≥16px 防 iOS 聚焦缩放 */
    }
    .admin-danger-block { padding: 12px; }
    /* 复选框:label 整行可点(单点 13px 的方框太苛刻),方框本身也放大到 20px */
    #edit-bank-modal .inline-label {
        display: inline-flex;
        align-items: center;
        gap: 8px;
        min-height: 44px;
        font-size: 14px;
    }
    #edit-bank-modal .inline-label input[type="checkbox"] {
        width: 20px;
        height: 20px;
        flex: 0 0 auto;
    }
    #edit-bank-modal .editor-more > summary,
    #edit-bank-modal .editor-bank-details > summary {
        min-height: 44px;
        display: flex;
        align-items: center;
    }
    /* 底部栏最右侧永远是「保存本题」——拇指落点固定 */
    .editor-foot { gap: 6px; }
    .editor-foot-actions { flex: 1 1 auto; justify-content: flex-end; }
    .editor-foot .action-btn { padding: 0 16px; }
    .editor-nav-row .editor-position { flex: 1 1 auto; text-align: center; }
}
/* 桌面:题号列表常显 —— 隐藏那个开合标题,免得鼠标用户误点收起 */
@media (min-width: 769px) {
    .editor-list-panel .editor-list-body { display: block; }
}
