/* line-clamp 兼容 */
.line-clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}


/* =========================================================================
   表单控件统一外观
   - .form-control: input / select / button 共享基础外观（高 40px、字号 14px、圆角、灰边）
   - .form-select:  在 form-control 之上去掉浏览器原生外观，自绘下拉箭头
   - .btn-primary:  spark 主按钮（深蓝填色），同高度，搜索/提交场景的发起按钮
   - .btn-secondary: 灰边白底，次级按钮
   规范见 DESIGN.md §3
   ========================================================================= */

.form-control {
  /* 关键：box-sizing 让 padding/border 算入 height，否则 select 在 macOS 上会比 button 矮 1-2 px */
  box-sizing: border-box;
  height: 2.5rem;                 /* 40px，与按钮等高 */
  padding: 0 0.75rem;
  font-size: 0.875rem;            /* 14px，与 text-sm 一致 */
  line-height: 1.25rem;
  color: #1e293b;                 /* slate-800 */
  background-color: #fff;
  border: 1px solid #cbd5e1;      /* slate-300 */
  border-radius: 0.5rem;          /* rounded-lg */
  outline: none;
  vertical-align: middle;          /* form 内 inline 对齐基线 */
  transition: border-color .15s, box-shadow .15s;
}
.form-control::placeholder { color: #94a3b8; }   /* slate-400 */
.form-control:focus,
.form-control:focus-visible {
  border-color: #18A9C4;          /* spark-500 */
  box-shadow: 0 0 0 3px rgba(24, 169, 196, 0.25);
}
.form-control:disabled {
  background-color: #f8fafc;      /* slate-50 */
  color: #94a3b8;
  cursor: not-allowed;
}

/* 给左侧绝对定位图标（搜索图标 / 日历图标等）让出空间。
   不能直接用 Tailwind 的 .pl-9 —— 因 .form-control 的 `padding` 简写在
   style.css 后加载，会重置左 padding 抹掉 pl-9 的效果（具体表现：图标和
   placeholder 第一个字重叠）。这里在 .form-control 之后定义同优先级的
   修饰类，源顺序更后 → 稳定生效。 */
.form-control--icon-left { padding-left: 2.25rem; }

/* 增强表格（data-enhance）的可排序表头视觉
   ── enhance_table.js 给 th[data-sort] 自动加 .et-sortable + 注入 .et-sort-ind
   排序指示器，这里只补一点 hover / cursor / 无障碍提示。 */
table[data-enhance] th.et-sortable {
  cursor: pointer;
  user-select: none;
  transition: background-color .12s;
}
table[data-enhance] th.et-sortable:hover {
  background-color: rgba(24, 169, 196, 0.08); /* spark-500 / 8% */
}
.dark table[data-enhance] th.et-sortable:hover {
  background-color: rgba(24, 169, 196, 0.18);
}

/* 数字输入框专属：去掉浏览器原生上下箭头（spinner），避免与右侧自定义单位（元 / %）叠加；
   数字右对齐 + 等宽，符合金额排版直觉。配合 form-control 一起用：
   <input type="number" class="form-control form-control--num">。 */
.form-control--num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
  /* 右内边距留给绝对定位的单位（元 / %）—— form-control 的 padding 简写
     默认 0.75rem,Tailwind 的 pr-8 utility 因加载顺序被它覆盖,这里在 num
     变体里显式留出 2rem(32px)空间,数字右对齐时不会撞到单位。 */
  padding-right: 2rem;
}
.form-control--num::-webkit-inner-spin-button,
.form-control--num::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
/* placeholder 强制左对齐 —— 避免「金额」占位符和右侧绝对定位的单位（元 / %）
   重叠；用户实际输入数字时仍按 text-align:right 右对齐，符合金额视觉规则。 */
.form-control--num::placeholder { text-align: left; }
.form-control--num::-webkit-input-placeholder { text-align: left; }
.form-control--num::-moz-placeholder { text-align: left; }
.form-control--num:-ms-input-placeholder { text-align: left; }

/* 业绩预测页表格内的精简数字输入框 —— 不走 form-control 体系（密度更高），
   主要目的：① 去掉 number 微调箭头（节省空间，避免和 placeholder 挤）；
   ② tabular-nums 让数字等宽，行小计对齐顺眼。
   字号/边距/边框颜色继续由 Tailwind utility class 控制，便于在模板里按需微调。 */
.bf-input {
  font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
}
.bf-input::-webkit-inner-spin-button,
.bf-input::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* select 专属：去原生外观 + 右侧自绘下拉箭头 */
.form-select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding-right: 2rem;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'></polyline></svg>");
  background-repeat: no-repeat;
  background-position: right 0.625rem center;
  background-size: 1rem;
  cursor: pointer;
}
.form-select::-ms-expand { display: none; }

/* =========================================================================
   线索销售映射：手机端卡片、桌面端表格。
   这里不用 Tailwind 的 md:table-cell 等类，因为线上加载的是预编译 tailwind.css，
   新增 utility 若未重建会失效。
   ========================================================================= */
.lead-map-head { display: none; }
.lead-map-body { display: block; padding: .75rem; }
.lead-map-row {
  display: block;
  margin-top: .75rem;
  overflow: hidden;
  border: 1px solid #e2e8f0;          /* slate-200 */
  border-radius: .75rem;
  background: #fff;
}
.lead-map-row:first-child { margin-top: 0; }
.lead-map-member {
  display: block;
  padding: .75rem 1rem;
  background: rgba(248, 250, 252, .72); /* slate-50 */
}
.lead-map-cell {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .75rem 1rem;
}
.lead-map-label {
  display: inline-block;
  flex-shrink: 0;
  font-size: .75rem;
  line-height: 1rem;
  color: #64748b;                     /* slate-500 */
}
.lead-map-value { text-align: right; }
.lead-map-control {
  width: 11rem;
  max-width: 62%;
}
.lead-map-control .form-control { width: 100%; }
.lead-map-check { min-height: 3rem; }
.lead-map-empty {
  display: block;
  padding: 3rem 1rem;
  text-align: center;
}
.dark .lead-map-row {
  border-color: #334155;              /* slate-700 */
  background: #1e293b;                /* slate-800 */
}
.dark .lead-map-member {
  background: rgba(15, 23, 42, .3);   /* slate-900 */
}
.dark .lead-map-label { color: #94a3b8; } /* slate-400 */

@media (min-width: 768px) {
  .lead-map-head { display: table-header-group; }
  .lead-map-body {
    display: table-row-group;
    padding: 0;
  }
  .lead-map-row {
    display: table-row;
    margin-top: 0;
    overflow: visible;
    border: 0;
    border-radius: 0;
    background: transparent;
  }
  .lead-map-row + .lead-map-row { border-top: 1px solid #f1f5f9; }
  .dark .lead-map-row + .lead-map-row { border-top-color: #334155; }
  .lead-map-member,
  .lead-map-cell {
    display: table-cell;
    padding: .625rem 1rem;
    vertical-align: middle;
    background: transparent;
  }
  .lead-map-label { display: none; }
  .lead-map-value { text-align: left; }
  .lead-map-control {
    width: auto;
    max-width: none;
  }
  .lead-map-control-id { width: 9rem; }
  .lead-map-control-name { width: 7rem; }
  .lead-map-control-kind { min-width: 6.5rem; }
  .lead-map-check { text-align: center; }
  .lead-map-empty { display: table-cell; }
}

/* 按钮统一高度 + 风格 */
.btn-primary,
.btn-secondary {
  box-sizing: border-box;          /* 与 form-control 一致，确保 height 严格 = 40px */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 2.5rem;                 /* 与 form-control 等高 */
  padding: 0 1.25rem;
  font-size: 0.875rem;
  font-weight: 500;
  border-radius: 0.5rem;
  border: 1px solid transparent;
  cursor: pointer;
  vertical-align: middle;
  transition: background-color .15s, border-color .15s, color .15s;
  white-space: nowrap;
}
.btn-primary {
  color: #fff;
  background-color: #06628C;      /* spark-700 */
}
.btn-primary:hover  { background-color: #054E70; }    /* spark-800 */
.btn-primary:disabled {
  background-color: #cbd5e1; cursor: not-allowed;
}
.btn-secondary {
  color: #475569;                 /* slate-600 */
  background-color: #fff;
  border-color: #cbd5e1;          /* slate-300 */
}
.btn-secondary:hover {
  background-color: #f8fafc;      /* slate-50 */
  color: #06628C;                 /* spark-700 */
  border-color: #06628C;
}

.payment-entry-menu > summary {
  list-style: none;
}
.payment-entry-menu > summary::-webkit-details-marker {
  display: none;
}
.payment-entry-menu[open] .payment-entry-chevron {
  transform: rotate(180deg);
}


/* =========================================================================
   iOS Safari focus 表单控件时自动放大问题修复
   ----------------------------------------------------------
   iOS WebKit 在 form 控件字号 < 16px 时，focus 会强制 zoom in（"为了让用户看清"），
   zoom 后页面横向溢出视口，需要拖动才能点到右侧发送按钮。
   解法：移动端把所有 input/textarea/select 字号兜底到 16px。桌面保持紧凑的 14px。
   用 !important 是因为 Tailwind 的 .text-sm 等 utility 直接写在元素上，
   只有 !important 才能保证移动端覆盖 inline-class 的字号。
   ========================================================================= */
@media (max-width: 767px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="file"]),
  textarea,
  select {
    font-size: 16px !important;
  }
}


/* =========================================================================
   .prose-chat — 智能问答 / 模拟器评估官 等 LLM 输出气泡内的 Markdown 排版
   仅约束气泡内的子元素；不污染全局；颜色与 spark/accent 色板一致
   ========================================================================= */
.prose-chat > *:first-child { margin-top: 0; }
.prose-chat > *:last-child { margin-bottom: 0; }
.prose-chat p { margin: 0.5em 0; line-height: 1.65; }
.prose-chat strong { font-weight: 600; color: #06628C; }   /* spark-700 */
.prose-chat em { font-style: italic; }
.prose-chat code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 0.875em;
  padding: 0.1em 0.35em;
  background: #E6F4F8;
  color: #054E70;
  border-radius: 4px;
}
.prose-chat pre {
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  padding: 0.75em 1em;
  overflow-x: auto;
  margin: 0.75em 0;
  font-size: 0.85em;
}
.prose-chat pre code { background: none; padding: 0; color: inherit; }
.prose-chat ul, .prose-chat ol { margin: 0.5em 0; padding-left: 1.5em; }
.prose-chat ul { list-style: disc; }
.prose-chat ol { list-style: decimal; }
.prose-chat li { margin: 0.25em 0; line-height: 1.6; }
.prose-chat li > p { margin: 0.25em 0; }
.prose-chat blockquote {
  border-left: 3px solid #18A9C4;
  background: #E6F4F8;
  padding: 0.5em 0.85em;
  margin: 0.75em 0;
  color: #475569;
  border-radius: 0 6px 6px 0;
}
.prose-chat h1, .prose-chat h2, .prose-chat h3, .prose-chat h4 {
  font-weight: 600;
  color: #06628C;
  margin: 0.85em 0 0.4em;
  line-height: 1.35;
}
.prose-chat h1 { font-size: 1.15em; }
.prose-chat h2 { font-size: 1.08em; }
.prose-chat h3 { font-size: 1.02em; }
.prose-chat h4 { font-size: 1em; }
.prose-chat a {
  color: #06628C;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.prose-chat a:hover { color: #054E70; }
.prose-chat hr {
  border: none;
  border-top: 1px solid #e2e8f0;
  margin: 1em 0;
}
.prose-chat table {
  border-collapse: collapse;
  margin: 0.75em 0;
  font-size: 0.9em;
  /* 宽表格在窄屏（手机）气泡内横向滚动，不撑破气泡 / 视口 */
  display: block;
  overflow-x: auto;
  max-width: 100%;
}
.prose-chat th, .prose-chat td {
  border: 1px solid #e2e8f0;
  padding: 0.4em 0.6em;
  text-align: left;
}
.prose-chat th { background: #f1f5f9; font-weight: 600; }


/* =========================================================================
   .typing-dots — LLM 流式响应「正在思考」三点动画占位
   ========================================================================= */
.typing-dots > span {
  animation: typing-blink 1.4s infinite both;
}
.typing-dots > span:nth-child(2) { animation-delay: 0.2s; }
.typing-dots > span:nth-child(3) { animation-delay: 0.4s; }
@keyframes typing-blink {
  0%, 80%, 100% { opacity: 0.25; transform: translateY(0); }
  40%           { opacity: 1;    transform: translateY(-2px); }
}


/* =========================================================================
   Dark mode 全局兜底（渐进式）
   ----------------------------------------------------------
   策略：业务模板大部分没显式补 dark: 前缀，单独改太重；这里靠"全局
   后置规则"把常用 utility 类在 .dark 上下文里重映射，目标是"全站立刻看得过去"。
   后续给具体模板补 dark: 变体时，更细的 utility 优先级更高，会自然覆盖这里。
   设计原则：
   - 卡片仍用"亮一档"的 slate-800 而非纯黑 → 内容仍清晰
   - 品牌色 spark-* / 辅助色 accent-* 不动（两个模式都成立）
   - 浅 spark-50/100 在深色下会刺眼 → 降到 spark-700 透明度版
   - 文字色 600/700/800/900 整体抬亮到 slate-100/200/300
   ========================================================================= */

/* —— 容器背景 —— */
.dark .bg-white            { background-color: rgb(30 41 59); }      /* slate-800 */
.dark .bg-slate-50         { background-color: rgb(15 23 42); }      /* slate-900 */
.dark .bg-slate-100        { background-color: rgb(30 41 59); }      /* slate-800 */
.dark .bg-slate-200        { background-color: rgb(15 23 42); }      /* slate-900 — PDF viewer 等浅灰底 */
.dark .bg-spark-50         { background-color: rgba(24, 169, 196, 0.12); } /* spark-500 @ 12% — 浅光晕，不发蓝糊 */
.dark .bg-spark-100        { background-color: rgba(24, 169, 196, 0.22); }
.dark .bg-accent-yellow-20 { background-color: rgba(255, 199, 87, 0.15); }
.dark .bg-accent-orange-20 { background-color: rgba(250, 110, 31, 0.15); }

/* —— 带 opacity 的 Tailwind 类（如 bg-slate-50/40、hover:bg-spark-50/40）兜底 ——
   Tailwind 的 `bg-slate-50/40` 实际生成的 class 是 `bg-slate-50\/40`，
   与 `bg-slate-50` 是不同的 CSS 类，上面的兜底匹配不到。
   用属性选择器精准捕获 `bg-slate-50/X` `bg-white/X` `bg-spark-50/X` 三类常见的浅底透明用法。 */
.dark [class*="bg-slate-50/"],
.dark [class*="bg-white/"] {
  background-color: rgba(15, 23, 42, 0.4) !important;   /* slate-900 @ 40%，与原 light 透明度类似 */
}
.dark [class*="bg-slate-100/"] {
  background-color: rgba(30, 41, 59, 0.5) !important;   /* slate-800 半透明 */
}
.dark [class*="bg-spark-50/"] {
  background-color: rgba(24, 169, 196, 0.12) !important;
}
/* accent-yellow / -orange 的斜杠透明度写法（如 bg-accent-yellow/30）：步进 token 有
   .dark .bg-accent-*-20 兜底，但斜杠版是另一个 class，需单独按属性选择器补深色。 */
.dark [class*="bg-accent-yellow/"] {
  background-color: rgba(255, 199, 87, 0.16) !important;
}
.dark [class*="bg-accent-orange/"] {
  background-color: rgba(250, 110, 31, 0.16) !important;
}
/* hover 状态版本 */
.dark [class*="hover:bg-slate-50/"]:hover,
.dark [class*="hover:bg-white/"]:hover {
  background-color: rgba(30, 41, 59, 0.6) !important;
}
.dark [class*="hover:bg-spark-50/"]:hover {
  background-color: rgba(24, 169, 196, 0.22) !important;
}

/* —— 边框 —— */
.dark .border-slate-100    { border-color: rgb(51 65 85); }          /* slate-700 */
.dark .border-slate-200    { border-color: rgb(51 65 85); }
.dark .border-slate-300    { border-color: rgb(71 85 105); }         /* slate-600 */
.dark .border-spark-100    { border-color: rgba(24, 169, 196, 0.4); }
.dark .border-spark-200    { border-color: rgba(24, 169, 196, 0.5); }
.dark .border-spark-700    { border-color: rgb(105 184 205); }       /* spark-300 — 深色下边框需要亮才看得见 */

/* divide-*（行间分隔线 = border 模拟） */
.dark .divide-slate-100 > * + * { border-color: rgb(51 65 85); }
.dark .divide-slate-200 > * + * { border-color: rgb(51 65 85); }

/* —— 文字色（统一原则：提亮一档而非压暗）—— */
.dark .text-slate-900      { color: rgb(248 250 252); }              /* slate-50 — 最亮 */
.dark .text-slate-800      { color: rgb(241 245 249); }              /* slate-100 */
.dark .text-slate-700      { color: rgb(226 232 240); }              /* slate-200 */
.dark .text-slate-600      { color: rgb(203 213 225); }              /* slate-300 */
.dark .text-slate-500      { color: rgb(203 213 225); }              /* slate-300 — 副文也要看得清 */
.dark .text-slate-400      { color: rgb(148 163 184); }              /* slate-400 不变 — 浅底辅助文 */
.dark .text-slate-300      { color: rgb(148 163 184); }              /* 极弱文也别太弱 */

/* spark 主色文字在深底上偏暗，提到 spark-300（青亮档） */
.dark .text-spark-700      { color: rgb(105 184 205); }              /* spark-300 */
.dark .text-spark-800      { color: rgb(60 160 185); }               /* spark-400 */
.dark .text-spark-500      { color: rgb(154 207 223); }              /* spark-200 */

/* accent 棕色在深底上几乎看不见，改用亮黄 */
.dark .text-accent-brown   { color: rgb(255, 221, 154); }            /* accent-yellow-60 */

/* accent-orange-700（#9A3E0C）是浅底上的「错误/危险文字」深橙；
   深底上它太暗看不清，回退到亮一档 accent-orange-80（#FB8B4C），在 slate-800/900 上对比 ~6.8:1 */
.dark .text-accent-orange-700 { color: #FB8B4C; }

/* radar_chart macro 的 SVG 文字：维度名 #334155 / 分数 #06628C 在深底卡片上几乎看不见。
   SVG fill 用 CSS 类覆盖（CSS fill 优先级高于 fill 属性），深色下提亮到 slate-300 / spark-300。 */
.dark .rc-label { fill: #cbd5e1; }
.dark .rc-score { fill: #6FB8CD; }

/* 业务看板图表（_board_kit trend_chart/donut、_effective_rate）内联 SVG 描边/文字：
   网格线 #E2E8F0 在暗底过亮、右轴/数据值标签 #06628C 在暗底过暗（几乎看不见）。
   仅 .dark 覆盖；light 模式继续用元素上的内联 stroke/fill（presentation attribute
   优先级低于 CSS class 规则 → 暗色生效、亮色零改动）。 */
.dark .ch-grid { stroke: #334155; }       /* slate-700：暗底低调网格线 */
.dark .ch-axis-accent { fill: #6FB8CD; }  /* spark-300：右轴 / 数据值标签暗底提亮 */

/* —— hover 状态 —— */
.dark .hover\:bg-slate-50:hover  { background-color: rgb(51 65 85); }   /* slate-700 */
.dark .hover\:bg-slate-100:hover { background-color: rgb(51 65 85); }
.dark .hover\:bg-spark-50:hover  { background-color: rgba(24, 169, 196, 0.22); }
.dark .hover\:bg-accent-yellow-40:hover { background-color: rgba(255, 199, 87, 0.28); }
.dark .hover\:text-spark-700:hover { color: rgb(154 207 223); }      /* spark-200 — hover 时更亮 */
.dark .hover\:text-spark-800:hover { color: rgb(105 184 205); }
.dark .hover\:text-accent-brown:hover { color: rgb(255 221 154); }

/* —— peer-checked 选中态（单选卡 / 选项卡）在深色模式的兜底 ——
   Tailwind 把这些 variant 编译成独立 class（如 .peer:checked~.peer-checked\:bg-spark-50），
   全局 .dark .bg-spark-50 兜底匹配不到，必须按变体补一遍：选中态的底色 + 文字色都要覆盖。
   注：此前本段注释误用 Jinja 的 `#}` 收尾，导致整段被 CSS 注释吞掉而失效，已修正为 `*/`。 */
.dark .peer\:checked ~ .peer-checked\:bg-spark-50,
.dark .peer-checked\:bg-spark-50,
.dark [class*="peer-checked:bg-spark-50/"] {
  background-color: rgba(24, 169, 196, 0.18) !important;
}
.dark .peer-checked\:bg-accent-yellow-20,
.dark [class*="peer-checked:bg-accent-yellow/"] {
  background-color: rgba(255, 199, 87, 0.18) !important;
}
.dark .peer-checked\:bg-accent-orange-20,
.dark [class*="peer-checked:bg-accent-orange/"] {
  background-color: rgba(250, 110, 31, 0.18) !important;
}
.dark .peer-checked\:bg-slate-100 { background-color: rgb(51 65 85) !important; }
.dark .peer-checked\:text-spark-700,
.dark .peer-checked\:text-spark-800 { color: rgb(154 207 223) !important; }    /* spark-200 在深底更亮 */
.dark .peer-checked\:text-slate-700 { color: rgb(226 232 240) !important; }     /* slate-200 */
.dark .peer-checked\:text-accent-brown { color: rgb(255, 221, 154) !important; }

/* nav 顶部 dropdown 面板（base.html 里的 .top-dd-panel 内层 white 卡） */
.dark .top-dd-panel > div  { background-color: rgb(30 41 59); border-color: rgb(51 65 85); }

/* 表单控件：dark 下底色变深，placeholder 提亮 */
.dark .form-control,
.dark input[type="text"]:not([class*="bg-"]),
.dark input[type="password"]:not([class*="bg-"]),
.dark input[type="email"]:not([class*="bg-"]),
.dark input[type="tel"]:not([class*="bg-"]),
.dark input[type="search"]:not([class*="bg-"]),
.dark input[type="number"]:not([class*="bg-"]),
.dark textarea:not([class*="bg-"]),
.dark select:not([class*="bg-"]) {
  background-color: rgb(30 41 59);     /* slate-800 */
  color: rgb(241 245 249);
  border-color: rgb(71 85 105);        /* slate-600 */
}
.dark .form-control::placeholder,
.dark input::placeholder,
.dark textarea::placeholder { color: rgb(100 116 139); }   /* slate-500 */

/* prose-chat 在 dark 下：code / pre / blockquote / table 提亮 */
.dark .prose-chat code      { background: rgba(24, 169, 196, 0.2); color: rgb(194 226 236); }
.dark .prose-chat pre       { background: rgb(15 23 42); border-color: rgb(51 65 85); color: rgb(226 232 240); }
.dark .prose-chat blockquote{ background: rgba(24, 169, 196, 0.15); color: rgb(203 213 225); border-color: rgb(24 169 196); }
.dark .prose-chat th        { background: rgb(30 41 59); }
.dark .prose-chat th,
.dark .prose-chat td        { border-color: rgb(51 65 85); }
.dark .prose-chat hr        { border-top-color: rgb(51 65 85); }
.dark .prose-chat strong,
.dark .prose-chat h1,
.dark .prose-chat h2,
.dark .prose-chat h3,
.dark .prose-chat h4        { color: rgb(60 160 185); }   /* spark-400 */
.dark .prose-chat a         { color: rgb(105 184 205); }  /* spark-300 */

/* btn-secondary 在深色下用深底亮字 */
.dark .btn-secondary {
  background-color: rgb(30 41 59);
  color: rgb(203 213 225);
  border-color: rgb(71 85 105);
}
.dark .btn-secondary:hover {
  background-color: rgb(51 65 85);
  color: rgb(24 169 196);
  border-color: rgb(24 169 196);
}

/* 阴影在深色下减弱（深底+大阴影会糊成一片） */
.dark .shadow-sm  { box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.4); }
.dark .shadow,
.dark .shadow-md  { box-shadow: 0 4px 8px -2px rgba(0, 0, 0, 0.5); }
.dark .shadow-lg,
.dark .shadow-xl  { box-shadow: 0 10px 20px -5px rgba(0, 0, 0, 0.55); }
.dark .hover\:shadow-lg:hover { box-shadow: 0 12px 24px -8px rgba(0, 0, 0, 0.6); }

/* Hero 渐变在 dark 下整体调暗 + 偏深蓝，避免大面积亮蓝色块在深底上突兀
   原渐变是 #18A9C4 → #06628C（亮青蓝 → 深蓝），dark 下改为 spark-800 → spark-900 实色渐变 */
.dark .bg-spark-gradient {
  background-image: linear-gradient(135deg, #054E70 0%, #033A55 100%);
}

/* S 纹样水印（hero 区背景大写 S 字平铺）在 dark 下更柔和 */
.dark .bg-spark-gradient .text-white\/10 { color: rgba(255, 255, 255, 0.04); }
.dark .bg-spark-gradient .opacity-10 { opacity: 0.06; }

/* hero 底部 V 形条带：下层多边形 fill=currentColor，颜色必须与页面背景严格一致，
   才能形成「页面切入 hero」的无缝效果。明暗各取 body 的背景色。
   放在 style.css（非 Tailwind 构建产物）里，避免依赖 dark: 类是否被编译。 */
.brand-hero-v { color: #f8fafc; }        /* = body bg-slate-50 */
.dark .brand-hero-v { color: #0f172a; }  /* = body dark:bg-slate-900 */

/* 分享链接「有效期」预设 chip —— 替代浏览器原生 date 控件（原生日历无法定制、各端不一） */
.expiry-chip {
  padding: 0.375rem 0.75rem;
  border-radius: 0.5rem;
  border: 1px solid #cbd5e1;          /* slate-300 */
  font-size: 0.875rem;
  line-height: 1.25rem;
  color: #475569;                      /* slate-600 */
  background: #fff;
  cursor: pointer;
  transition: border-color .12s, background-color .12s, color .12s;
}
.expiry-chip:hover { border-color: #18A9C4; }       /* spark-500 */
.expiry-chip-on {
  border-color: #06628C;                            /* spark-700 */
  background: #06628C;
  color: #fff;
}
.dark .expiry-chip { background: #1e293b; border-color: #334155; color: #cbd5e1; }
.dark .expiry-chip:hover { border-color: #18A9C4; }
.dark .expiry-chip-on { background: #06628C; border-color: #06628C; color: #fff; }

/* =========================================================================
   复选框 / 单选框 —— 去原生外观，对齐 spark 色板（与 .form-control / .form-select
   同一表单控件体系）。原生 checkbox 各系统观感不一、偏简陋，统一自绘。
   ========================================================================= */
.form-checkbox,
.form-radio {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  box-sizing: border-box;
  flex-shrink: 0;
  width: 1.05rem;
  height: 1.05rem;
  margin: 0;
  padding: 0;
  border: 1.5px solid #cbd5e1;          /* slate-300 */
  background-color: #fff;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 0.72rem;
  cursor: pointer;
  vertical-align: middle;
  position: relative;
  transition: background-color .12s ease, border-color .12s ease;
}
.form-checkbox { border-radius: 0.3rem; }
.form-radio { border-radius: 50%; }
.form-checkbox:hover,
.form-radio:hover { border-color: #06628C; }          /* spark-700 */
.form-checkbox:checked,
.form-checkbox:indeterminate,
.form-radio:checked {
  background-color: #06628C;                          /* spark-700 */
  border-color: #06628C;
}
.form-checkbox:checked {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
}
.form-checkbox:indeterminate {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round'><line x1='5' y1='12' x2='19' y2='12'/></svg>");
}
.form-radio:checked::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 50%;
  background-color: #fff;
  transform: translate(-50%, -50%);
}
.form-checkbox:focus-visible,
.form-radio:focus-visible {
  outline: 2px solid rgba(6, 98, 140, .45);
  outline-offset: 1px;
}
.form-checkbox:disabled,
.form-radio:disabled { opacity: .5; cursor: not-allowed; }
.dark .form-checkbox,
.dark .form-radio { background-color: #0f172a; border-color: #475569; }   /* slate-900 / slate-600 */
.dark .form-checkbox:hover,
.dark .form-radio:hover { border-color: #3ba4d0; }
.dark .form-checkbox:checked,
.dark .form-checkbox:indeterminate,
.dark .form-radio:checked { background-color: #06628C; border-color: #06628C; }

/* 页面内可编辑字段（inline_edit.js）：键盘聚焦态 —— 与 dblclick / 单击同等可达 */
.inline-edit[data-editable="1"] { border-radius: 3px; }
.inline-edit[data-editable="1"]:focus-visible {
  outline: 2px solid #18A9C4;
  outline-offset: 2px;
}

/* =========================================================================
   iOS 安全区 —— 贴底元素（聊天输入条等）避让 home indicator。
   之前各聊天页用了 .pb-safe 但全站从未定义，在刘海/灵动岛机型上输入条会被
   home indicator 压住，这里补上真实实现。
   ========================================================================= */
.pb-safe { padding-bottom: env(safe-area-inset-bottom); }

/* =========================================================================
   品牌 S 纹样水印 —— 单张可平铺 SVG 背景。
   替代 brand_hero 宏里 240 个 <span>S</span> DOM 节点（与登录页 .login-s-pattern
   同款做法），每个用到 hero 的页面省去数百个布局盒子。
   ========================================================================= */
.brand-s-pattern {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='72' height='72'><text x='8' y='52' font-family='system-ui,-apple-system,sans-serif' font-size='48' font-weight='900' fill='rgba(255,255,255,0.10)'>S</text></svg>");
  background-repeat: repeat;
  background-position: top left;
}
.dark .brand-s-pattern {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='72' height='72'><text x='8' y='52' font-family='system-ui,-apple-system,sans-serif' font-size='48' font-weight='900' fill='rgba(255,255,255,0.05)'>S</text></svg>");
}

/* =========================================================================
   懒渲染卡片 —— content-visibility:auto 跳过屏幕外卡片的 layout/paint。
   错题速练 sprint.html 一次 SSR N 张 hidden 卡片，首屏 paint 成本随题数线性
   增长；加上后浏览器只渲染当前可视那张，其余按 contain-intrinsic-size 占位。
   注意：必须给 intrinsic size 估值，否则滚动条会乱跳。
   ========================================================================= */
.lazy-card {
  content-visibility: auto;
  contain-intrinsic-size: 600px;
}


/* =========================================================================
   .ftgl — 自动化开关（toggle switch）
   ------------------------------------------------------------------------
   anomaly_config / followup_config / benchmark_rules 三页过去各自内嵌了一份
   60 行 CSS（且 .ftgl-track 硬编码 #06628C），改色板要三处同步。统一到这里。
   调用方：
     <label class="ftgl">
       <input type="checkbox" name="...">
       <span class="ftgl-track"></span>
       <span class="ftgl-knob"></span>
     </label>
   ========================================================================= */
.ftgl { position: relative; display: inline-block; width: 44px; height: 24px;
        flex-shrink: 0; vertical-align: middle; }
.ftgl input { position: absolute; inset: 0; width: 100%; height: 100%;
              margin: 0; opacity: 0; cursor: pointer; z-index: 2; }
.ftgl-track { position: absolute; inset: 0; background: #cbd5e1;
              border-radius: 9999px; transition: background-color .2s; }
.ftgl input:checked + .ftgl-track { background: #06628C; }   /* spark-700 */
.dark .ftgl-track { background: #475569; }                    /* slate-600 */
.ftgl-knob { position: absolute; left: 2px; top: 2px; width: 20px; height: 20px;
             background: #fff; border-radius: 9999px;
             box-shadow: 0 1px 3px rgba(0,0,0,.3);
             transition: transform .2s; pointer-events: none; }
.ftgl input:checked ~ .ftgl-knob { transform: translateX(20px); }
.ftgl input:focus-visible ~ .ftgl-knob {
  outline: 2px solid #06628C; outline-offset: 2px;
}
.ftgl input:disabled ~ .ftgl-knob,
.ftgl input:disabled + .ftgl-track { opacity: .55; cursor: not-allowed; }
