/* ==========================================================================
   SVG Blaze theme — public/static/css/theme.css
   海外工具站主题：Blaze Orange + Deep Slate，仅覆盖 Bootstrap 5.3，不改结构。
   用法：在 layout.ts <head> 中 Bootstrap 之后引入本文件即可。
   约定：前台 SSR 专用，以 .sb- 前缀避免污染 /dashboard /user 的 Vue SPA。
   ========================================================================== */

:root {
  --sb-bg: #f8fafc;
  --sb-surface: #ffffff;
  --sb-ink: #0f172a;
  --sb-ink-2: #1e293b;
  --sb-muted: #64748b;
  --sb-line: #e2e8f0;
  --sb-primary: #f97316;
  --sb-primary-hover: #ea580c;
  --sb-primary-active: #c2410c;
  --sb-primary-soft: #fff7ed;
  --sb-primary-border: #fed7aa;
  --sb-radius: 16px;
  --sb-radius-lg: 20px;
  --sb-shadow: 0 12px 32px rgba(15, 23, 42, 0.08);
  --sb-shadow-lg: 0 24px 64px rgba(15, 23, 42, 0.14);
  --sb-font: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;

  /* Bootstrap 变量映射：让 btn-primary / badge / link 直接变品牌色 */
  --bs-primary: var(--sb-primary);
  --bs-primary-rgb: 249, 115, 22;
  --bs-link-color: var(--sb-primary-active);
  --bs-link-color-rgb: 194, 65, 12;
  --bs-link-hover-color: var(--sb-primary-hover);
  --bs-border-radius: 12px;
  --bs-border-radius-lg: var(--sb-radius);
  --bs-body-font-family: var(--sb-font);
  --bs-body-color: var(--sb-ink-2);
  --bs-body-bg: var(--sb-bg);
}

/* 锚点定位留白：顶栏是 sticky-top（约 59px = 42px 内容 + 16px 内边距 + 1px 边框），
   浏览器默认把锚点目标对齐到视口顶端，标题会被顶栏压住。scroll-padding-top 让自动滚动
   （点击 #tools / #about / #faq、或从工具页跳回首页锚点）预留顶栏高度 + 呼吸间隙。
   只作用于锚点滚动，不改任何布局尺寸。改顶栏高度（如调整 navbar padding / 按钮尺寸）时同步这里。 */
html {
  scroll-behavior: smooth;
  scroll-padding-top: 4rem;
}

body.sb-body {
  font-family: var(--sb-font);
  background: var(--sb-bg);
  color: var(--sb-ink-2);
  -webkit-font-smoothing: antialiased;
}

body.sb-body ::selection {
  background: rgba(249, 115, 22, 0.22);
}

body.sb-body h1,
body.sb-body h2,
body.sb-body h3 {
  color: var(--sb-ink);
  letter-spacing: -0.02em;
}

body.sb-body a:focus-visible,
body.sb-body button:focus-visible,
body.sb-body .btn:focus-visible {
  outline: 3px solid rgba(249, 115, 22, 0.4);
  outline-offset: 2px;
}

/* ---------- Buttons / badges：只换皮，不改 Bootstrap 行为 ---------- */

body.sb-body .btn-primary {
  --bs-btn-bg: var(--sb-primary);
  --bs-btn-border-color: var(--sb-primary);
  --bs-btn-hover-bg: var(--sb-primary-hover);
  --bs-btn-hover-border-color: var(--sb-primary-hover);
  --bs-btn-active-bg: var(--sb-primary-active);
  --bs-btn-active-border-color: var(--sb-primary-active);
  --bs-btn-disabled-bg: #fdba74;
  --bs-btn-disabled-border-color: #fdba74;
  font-weight: 700;
  box-shadow: 0 8px 20px rgba(249, 115, 22, 0.28);
}

body.sb-body .btn-primary:hover {
  transform: translateY(-1px);
}

body.sb-body .btn-outline-secondary {
  --bs-btn-bg: #fff;
  --bs-btn-color: var(--sb-ink-2);
  --bs-btn-border-color: var(--sb-line);
  /* hover / active 是深墨色皮肤。工具页的选项区（.sb-ico-sizes 尺寸胶囊、.sb-bg-choice 背景色）
     都各自覆盖了这两态，别据此以为「选中就该是黑的」——那正是背景色选项选 White 却变黑的根因。 */
  --bs-btn-hover-bg: var(--sb-ink);
  --bs-btn-hover-border-color: var(--sb-ink);
  --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: var(--sb-ink);
  --bs-btn-active-border-color: var(--sb-ink);
  --bs-btn-active-color: #fff;
  font-weight: 600;
}

body.sb-body .text-bg-primary {
  background-color: var(--sb-primary) !important;
}

body.sb-body .sb-badge-soft {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  background: rgba(249, 115, 22, 0.12);
  border: 1px solid rgba(249, 115, 22, 0.35);
  color: #fff;
  font-weight: 600;
  font-size: 0.82rem;
  letter-spacing: 0.01em;
  padding: 0.42rem 0.8rem;
  border-radius: 999px;
}

/* ---------- Header：白底 blur，替代默认纯黑 navbar ---------- */

.sb-header {
  background: rgba(255, 255, 255, 0.88) !important;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--sb-line);
}

.sb-header .navbar-brand {
  color: var(--sb-ink) !important;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.sb-logo-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: linear-gradient(135deg, #fb923c, #ea580c);
  color: #fff;
  font-size: 0.95rem;
  box-shadow: 0 6px 14px rgba(249, 115, 22, 0.35);
}

/* 左上角品牌图（logo.svg）。SVG 自带圆角橙底与配色，所以不套 .sb-logo-mark 的渐变底和投影 ——
   两者叠在一起会出现「渐变方块 + 里面再一个 logo」的双层观感。
   不加 border-radius：图像自身圆角约 5.75px（rx 92/512 缩放后），元素再裁 9px 会把橙角削掉一圈。
   flex: none 保证窄屏被品牌名挤压时不被压扁。 */
.sb-logo-img {
  display: block;
  flex: none;
  width: 32px;
  height: 32px;
}

.sb-header .navbar-nav {
  gap: 0.35rem;
}

.sb-header .nav-link {
  color: var(--sb-muted) !important;
  font-weight: 600;
  border-radius: 10px;
  padding: 0.5rem 0.8rem !important;
}

.sb-header .nav-link:hover {
  color: var(--sb-ink) !important;
  background: #f1f5f9;
}

.sb-header .nav-link.active {
  color: var(--sb-primary-active) !important;
  background: var(--sb-primary-soft);
}

.sb-header .sb-lang-btn {
  border-color: var(--sb-line);
  color: var(--sb-ink-2);
  font-weight: 600;
  background: #fff;
}

.sb-header .sb-lang-btn:hover {
  border-color: var(--sb-primary);
  color: var(--sb-primary-active);
}

/* 语言切换 + 汉堡：统一高度，移动端并排靠右 */
.sb-nav-actions {
  gap: 0.5rem;
  margin-left: auto;
}

.sb-header .sb-lang-btn,
.sb-header .sb-nav-toggler {
  height: 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 11px;
}

/* 桌面端（≥992px）隐藏汉堡，恢复 Bootstrap 默认行为 */
@media (min-width: 992px) {
  .sb-header .sb-nav-toggler {
    display: none;
  }
}

/* 汉堡按钮：去掉默认粗黑 focus 圈，改用柔和橙色描边 */
.sb-header .sb-nav-toggler {
  width: 42px;
  padding: 0;
  border: 1px solid var(--sb-line) !important;
  color: var(--sb-ink-2);
  background: #fff;
  box-shadow: none !important;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.sb-header .sb-nav-toggler:hover {
  border-color: var(--sb-primary) !important;
}

.sb-header .sb-nav-toggler:focus,
.sb-header .sb-nav-toggler:focus-visible,
.sb-header .sb-nav-toggler:active {
  outline: none !important;
  box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.25) !important;
}

.sb-header .sb-nav-toggler .navbar-toggler-icon {
  width: 1.3em;
  height: 1.3em;
}

/* ---------- Hero：深 slate + 网格纹 + 橙色光晕 ---------- */

.sb-hero {
  position: relative;
  overflow: hidden;
  background: radial-gradient(640px 280px at 18% 0%, rgba(249, 115, 22, 0.22), transparent 65%),
    radial-gradient(720px 340px at 88% 20%, rgba(56, 189, 248, 0.14), transparent 60%),
    linear-gradient(180deg, #0f172a 0%, #16213a 100%);
  color: #e2e8f0;
}

.sb-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 36px 36px;
  mask-image: radial-gradient(ellipse 90% 90% at 50% 10%, #000 55%, transparent 100%);
  pointer-events: none;
}

.sb-hero .container {
  position: relative;
  z-index: 1;
}

.sb-hero h1 {
  color: #fff !important;
  font-weight: 800;
}

.sb-hero .sb-hero-sub {
  color: #cbd5e1 !important;
  font-size: 1.1rem;
}

.sb-hero .sb-hero-sub strong {
  color: #fff;
  font-weight: 700;
}

.sb-format-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.sb-format-pills span {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 0.3rem 0.65rem;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

.sb-format-pills span.sb-hot {
  background: var(--sb-primary);
  border-color: var(--sb-primary);
  box-shadow: 0 6px 16px rgba(249, 115, 22, 0.45);
}

.sb-trust {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 1.5rem;
  color: #94a3b8;
  font-size: 0.9rem;
}

.sb-trust i {
  color: #fdba74;
}

/* ---------- About / Why ---------- */

.sb-about {
  background: var(--sb-bg);
}

.sb-eyebrow {
  display: inline-block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sb-primary-active);
}

.sb-about-text {
  color: var(--sb-ink-2);
  font-size: 1.02rem;
  line-height: 1.75;
}

/* ---------- Tools：核心工具介绍卡 ---------- */

.sb-tools {
  background: linear-gradient(180deg, #ffffff 0%, var(--sb-bg) 100%);
}

.sb-tool-tile {
  background: var(--sb-surface);
  border: 1px solid var(--sb-line);
  border-radius: var(--sb-radius);
  box-shadow: 0 2px 10px rgba(15, 23, 42, 0.04);
  transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
}

.sb-tool-tile:hover {
  transform: translateY(-4px);
  border-color: var(--sb-primary-border);
  box-shadow: var(--sb-shadow);
}

.sb-tool-tag {
  display: inline-flex;
  align-items: center;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--sb-primary-active);
  background: var(--sb-primary-soft);
  border: 1px solid var(--sb-primary-border);
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
}

/* ---------- 工具页（转换器） ---------- */

/* 浅色渐变收尾处与 body 背景同为 --sb-bg，无需再画分界线（加了反而像一条多余的横杠） */
.sb-tool-hero {
  background: linear-gradient(180deg, #ffffff 0%, var(--sb-bg) 100%);
}

.sb-tool-panel {
  background: var(--sb-surface);
  border: 1px solid var(--sb-line);
  border-radius: var(--sb-radius-lg);
  box-shadow: var(--sb-shadow-lg);
}

.sb-dropzone {
  border: 2px dashed var(--sb-primary-border);
  background: var(--sb-primary-soft);
  border-radius: var(--sb-radius);
  padding: 2rem 1.5rem;
  text-align: center;
  color: var(--sb-ink-2);
  transition: border-color 0.15s ease, background 0.15s ease;
}

.sb-dropzone:hover,
.sb-dropzone.sb-dragover {
  border-color: var(--sb-primary);
  background: #ffedd5;
}

.sb-drop-icon {
  width: 52px;
  height: 52px;
  border-radius: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #fff;
  border: 1px solid var(--sb-primary-border);
  color: var(--sb-primary);
  font-size: 1.35rem;
  box-shadow: 0 8px 18px rgba(249, 115, 22, 0.18);
}

.sb-opt-label {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--sb-muted);
}

/* 选项标签旁的说明图标（模式提示等）：跟标签同色、跟标签一起被 letter-spacing 影响，
   所以单独把字距收回来，免得图标与文字之间多出一道缝 */
.sb-hint-icon {
  cursor: help;
  letter-spacing: normal;
  font-size: 0.95rem;
  color: var(--sb-muted);
}

.sb-hint-icon:hover,
.sb-hint-icon:focus-visible {
  color: var(--sb-primary);
}

/* tooltip 需要放宽：模式说明是一整句，默认 max-width 200px 会竖成一条。
   左对齐 + 限宽 280px，长句才好读。 */
.tooltip-inner {
  max-width: 280px;
  text-align: left;
}

/* 下载菜单：三个格式项，按钮与菜单同宽；菜单项左对齐、行高放松便于点选 */
.sb-ai-download .dropdown-menu {
  min-width: 100%;
}

.sb-ai-download .dropdown-item {
  padding: 0.5rem 0.9rem;
}

/* ICO 尺寸多选：胶囊按钮组，选中态用主题橙。
   .btn-check 是绝对定位的隐藏 input，不参与 flex 排布，所以只有 label 可见。 */
.sb-ico-sizes .btn {
  background: #fff;
  border-color: var(--sb-line);
  border-radius: 999px;
  color: var(--sb-ink-2);
  font-size: 0.9rem;
  font-weight: 600;
  padding: 0.35rem 0.9rem;
}

.sb-ico-sizes .btn:hover {
  border-color: var(--sb-primary-border);
  color: var(--sb-primary-active);
}

/* 「选中 = 主题橙」的唯一定义：背景色选项（.sb-bg-choice）与 ICO 尺寸胶囊共用这一条。
   两处都基于 .btn-outline-secondary，而它的 active 皮肤是 --sb-ink（近黑）——
   哪一边漏了这条，就会出现「选中 White 反而变黑」的语义倒错。别再拆成两份。 */
.sb-ico-sizes .btn-check:checked + .btn,
.sb-ico-sizes .btn-check:active + .btn,
.sb-bg-choice .btn-check:checked + .btn,
.sb-bg-choice .btn-check:active + .btn {
  background: var(--sb-primary);
  border-color: var(--sb-primary);
  color: #fff;
}

/* CDN 不可达时 Bootstrap 的 focus 圈也没了，自补一个可见焦点 */
.sb-ico-sizes .btn-check:focus-visible + .btn,
.sb-bg-choice .btn-check:focus-visible + .btn {
  outline: 2px solid var(--sb-primary);
  outline-offset: 2px;
  box-shadow: none;
}

/* 背景色选项是方形分段按钮组，只借用上面的选中皮肤，不套用尺寸胶囊的圆角与内边距。
   悬停必须一并覆盖：否则鼠标滑过就闪回 .btn-outline-secondary 的黑色 hover 皮肤。 */
.sb-bg-choice .btn:hover {
  background: var(--sb-surface);
  border-color: var(--sb-primary-border);
  color: var(--sb-primary-active);
}

.sb-code-input {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85rem;
}

/* AI 生成器：代码框与左侧预览框等高。高度刻意写死为同一个 --sb-result-frame-h，
   而不是用 flex 撑高 —— flex 只在两侧都拉伸时等高，而两侧下方的按钮高度不同时就会错位。
   resize: none 是因为拖拽会直接破坏等高关系。 */
.sb-ai-code {
  height: var(--sb-result-frame-h, 240px);
  resize: none;
}

/* AI 生成器：生成期间整片禁用表控件（脚本给 fieldset 打 disabled，见 ai-generator.js 的 setBusy）。
   归零 border/padding/margin 是因为 Bootstrap reboot 也这么做，而 CDN 不可达时重启样式失效，
   UA 默认的 fieldset 边框会顶开布局（与本文件末尾 *{box-sizing} 那条同一动机）。 */
.sb-ai-fieldset {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

/* AI 生成器：背景色板。
   用 radio + 色点（label 包住 input，点击面积即整个色点）。
   选中态用双环（先画一圈页面底色再画主色）而不是 border 变色，
   这样在白色 / 深色色点上都能看出选中，且不改变色点本身的颜色。 */
.sb-swatches {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
}

.sb-swatch {
  position: relative;
  display: inline-flex;
  cursor: pointer;
}

/* input 铺满 label 并透明化：保留键盘焦点与无障碍语义，视觉全靠 .sb-swatch-dot */
.sb-swatch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.sb-swatch-dot {
  display: block;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--sb-line);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.12);
  transition: box-shadow 0.15s ease;
}

.sb-swatch input:checked + .sb-swatch-dot,
.sb-swatch input:focus-visible + .sb-swatch-dot {
  box-shadow:
    0 0 0 2px var(--sb-surface),
    0 0 0 4px var(--sb-primary);
}

/* 背景形状选「透明」时颜色不生效，由 ai-generator.js 打上 data-disabled 置灰。
   生成期间整片 fieldset 被禁用，色板不属 Bootstrap 控件、拿不到 :disabled 的灰底，
   故并入同一条规则（置灰但不 pointer-events 之外的交互都由 fieldset 负责）。 */
.sb-swatches[data-disabled="true"],
.sb-ai-fieldset:disabled .sb-swatches {
  opacity: 0.4;
  pointer-events: none;
}

/* 色点与「更多」取色板在生成期间一并去掉手型光标，免得看着还能点 */
.sb-ai-fieldset:disabled .sb-swatch,
.sb-ai-fieldset:disabled .sb-swatch input {
  cursor: default;
}

/* 「更多」：色点默认是彩虹渐变（提示「这里可选任意颜色」）；用户取色后由 JS 把
   --sb-swatch-color 设成所选颜色并加上 .is-active，色点就变成实际颜色。
   它不在 radio 集合里（值任意），所以选中态走 .is-active 而不是 :checked。 */
.sb-swatch-more .sb-swatch-dot {
  background: conic-gradient(#ef4444, #f59e0b, #22c55e, #06b6d4, #6366f1, #ec4899, #ef4444);
}

.sb-swatch-more.is-active .sb-swatch-dot {
  background: var(--sb-swatch-color, #ffffff);
  box-shadow:
    0 0 0 2px var(--sb-surface),
    0 0 0 4px var(--sb-primary);
}

/* 取色板铺满色点：点它即弹出系统调色板。清掉 UA 默认边框/内边距，
   视觉仍全部交给下面的 .sb-swatch-dot（透明度已由 .sb-swatch input 归零）。 */
.sb-swatch-more input[type="color"] {
  border: 0;
  padding: 0;
  background: none;
}

/* 输入源 Tab：胶囊式，明确表达「文件 / 代码 二选一」。
   不依赖 Bootstrap pill JS（自行切换 .active），故这里只需管外观。 */
.sb-input-tabs {
  gap: 0.5rem;
  border-bottom: 1px solid var(--sb-line);
  padding-bottom: 0.85rem;
}

.sb-input-tabs .nav-link {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--sb-line);
  border-radius: 999px;
  background: #fff;
  color: var(--sb-ink-2);
  font-size: 0.9rem;
  font-weight: 600;
  padding: 0.4rem 1.05rem;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.sb-input-tabs .nav-link:hover {
  border-color: var(--sb-primary-border);
  color: var(--sb-primary-active);
}

.sb-input-tabs .nav-link.active {
  background: var(--sb-primary);
  border-color: var(--sb-primary);
  color: #fff;
}

/* 面板显隐自带规则，不依赖 Bootstrap 的 .fade/.show 过渡类
   （.fade:not(.show) 会把 opacity 压成 0，自实现切换时反而看不见内容） */
.sb-input-panes > .tab-pane {
  display: none;
}

.sb-input-panes > .tab-pane.active {
  display: block;
}

/* 结果对比：左「原图」→ 右「转换结果」 */
.sb-result {
  border-top: 1px solid var(--sb-line);
  padding-top: 1.25rem;
  /* 预览框固定高度：左右两框永远等高。用固定高度而非 min-height，是因为
     只有 min-height 时「已选图未转换」会让左框（大图）远高于右框（一行占位文字）。 */
  --sb-result-frame-h: 240px;
}

.sb-result-grid {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 1rem;
  /* 不能用 center：左右两列会被各自的内容高度决定，高的一侧不再与另一侧对齐。
     用 start 让两列顶部（也就是两个预览框的顶边）严格对齐。 */
  align-items: start;
}

.sb-result-item {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  min-width: 0;
}

/* 棋盘格底：输入 SVG 与输出 PNG 都可能透明，白底会误导成「不透明」。
   ICO 的尺寸缩略图共用同一组底纹，同一份棋盘格不写两处以免走样。 */
.sb-result-frame,
.sb-ico-thumb {
  background-color: #fff;
  background-image:
    linear-gradient(45deg, #e5e7eb 25%, transparent 25%),
    linear-gradient(-45deg, #e5e7eb 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #e5e7eb 75%),
    linear-gradient(-45deg, transparent 75%, #e5e7eb 75%);
  background-size: 16px 16px;
  background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}

.sb-result-frame {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: var(--sb-result-frame-h, 240px);
  padding: 0.5rem;
  border: 1px solid var(--sb-line);
  border-radius: 12px;
}

.sb-result-meta {
  font-size: 0.8rem;
  color: var(--sb-muted);
  font-variant-numeric: tabular-nums;
  text-align: center;
  /* 未出结果时右侧尺寸为空，占一行高度以免左右两列参差 */
  min-height: 1.5em;
}

.sb-result-placeholder {
  text-align: center;
  padding: 0.5rem;
}

.sb-result-arrow {
  /* 两列顶部对齐后，箭头单独在行内垂直居中 */
  align-self: center;
  color: var(--sb-primary);
  font-size: 1.15rem;
}

/* ---------- ICO：原图 + 各尺寸，统一 48px 小图标同一行 ---------- */

/* 原图卡片与尺寸卡片并排；顶部对齐，两者的缩略图因此落在同一水平线上 */
.sb-ico-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: 1rem;
}

/* 「勾了几档」的结果组：一行尺寸卡片。
   align-self: stretch 让它撑满整行高度（= 左侧原图卡片），占位块因此能与之等高，
   不必写死像素值，改字号也不会错位 */
.sb-ico-group {
  display: flex;
  flex-direction: column;
  align-self: stretch;
  gap: 0.35rem;
  min-width: 0;
}

/* 尺寸卡片容器：勾几档摆几张，一行放不下自动换行 */
.sb-ico-grid {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.75rem;
}

/* 未出结果时的占位块。左侧原图卡片已成框，右侧只裸一行文字会明显缺一块，
   故同样补上虚框。flex: 1 填满已被 stretch 的 .sb-ico-group ——
   高度就跟着行高（= 原图卡片）走，文字垂直居中对齐 */
.sb-ico-group > .sb-result-placeholder {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.75rem 1rem;
  border: 1px dashed var(--sb-line);
  border-radius: 10px;
}

/* 卡片：两行 —— 图片在上、文字 / 按钮在下，图片上方不放任何标题。
   宽度让内容自己决定（原图卡片的「原图 512×512」比尺寸卡片的「16×16 ⤓」略宽，
   硬拉成等宽反而会挤字）*/
.sb-ico-cell {
  display: flex;
  flex: none;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem;
  border: 1px solid var(--sb-line);
  border-radius: 10px;
}

/* 缩略图固定 48×48：原图与各档尺寸用同一个小图标尺寸，才好横向对比。
   棋盘格底由上方共用规则提供。 */
.sb-ico-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 6px;
}

.sb-ico-thumb img {
  max-width: 100%;
  max-height: 100%;
}

/* 只有光栅化出来的尺寸缩略图才像素化：高清屏下 16px 会被放大渲染，
   默认的双线性插值会把它糊成一团。原图是矢量渲染，插值反而更平滑 */
.sb-ico-grid .sb-ico-thumb img {
  image-rendering: pixelated;
}

/* 卡片第二行（原图的「原图 512×512」、尺寸的「16×16 ⤓」）。
   高度统一锁死 —— 两侧内容不同（一边纯文字、一边带按钮），
   不锁就有 1.6rem 与 1rem 级的高度差，卡片底边会参差 */
.sb-ico-meta,
.sb-ico-cell-meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  min-height: 1.6rem;
  font-size: 0.75rem;
  color: var(--sb-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* 「原图」标签：与右侧尺寸标注同字重，两侧第二行看起来才是一套 */
.sb-ico-meta-label {
  font-weight: 600;
  color: var(--sb-ink-2);
}

.sb-ico-cell-size {
  font-weight: 600;
  color: var(--sb-ink-2);
}

/* 单个尺寸的下载按钮：与尺寸标注同处第二行，做成无边框无底色的图标按钮，不抢视线。
   高度仍锁 1.6rem，与 .sb-ico-meta 的 min-height 对齐，两侧第二行才严格等高。
   去框后按钮宽度只剩「图标 + 内边距」，故把水平内边距留足到 0.5rem
   （约 27px 宽，高于 24px 的可点目标下限），别为了好看把它收窄 */
.sb-ico-cell-dl {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 1.6rem;
  padding: 0 0.5rem;
  border: 0;
  background: none;
  color: var(--sb-primary-active);
  font-size: 0.7rem;
  line-height: 1;
  transition: color 0.15s ease;
}

/* 无底色可换，hover 只靠颜色反馈。用 primary-hover 而非更浅的 primary：
   后者在白色卡片上只有 ~2.8:1，掉到非文本对比度的 3:1 以下 */
.sb-ico-cell-dl:not(:disabled):hover {
  color: var(--sb-primary-hover);
}

/* 过期 / 转换中的禁用态：与主下载按钮同进退，不给 hover 反馈 */
.sb-ico-cell-dl:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* CDN 不可达时 Bootstrap 的 focus 圈也没了，自补一个可见焦点 */
.sb-ico-cell-dl:focus-visible {
  outline: 2px solid var(--sb-primary);
  outline-offset: 2px;
}

/* 转换状态提示：ok/warn/error 三态，避免用颜色以外的信息（无障碍） */
.sb-status {
  margin-top: 0.85rem;
  margin-bottom: 0;
  font-size: 0.85rem;
  line-height: 1.5;
  border-radius: 8px;
}

.sb-status:empty {
  display: none;
}

.sb-status-ok,
.sb-status-warn,
.sb-status-error,
.sb-status-info {
  padding: 0.6rem 0.85rem;
  border: 1px solid transparent;
}

.sb-status-ok {
  background: #ecfdf5;
  border-color: #a7f3d0;
  color: #065f46;
}

.sb-status-warn {
  background: #fffbeb;
  border-color: #fde68a;
  color: #92400e;
}

.sb-status-error {
  background: #fef2f2;
  border-color: #fecaca;
  color: #991b1b;
}

.sb-status-info {
  background: #f8fafc;
  border-color: var(--sb-line);
  color: var(--sb-ink-2);
}

/* 预览图本身保持透明：棋盘格底由外层的 .sb-result-frame 提供。
   高度上限跟随框高（减去 padding 0.5rem×2 与边框 1px×2 = 18px） */
.sb-preview-img {
  display: block;
  max-width: 100%;
  /* 18px 的 padding/边框用 rem 表达：若写死 8px，用户调大默认字号时
     padding 会变宽而预算不变，图片就会溢出固定高度的框被裁 */
  max-height: calc(var(--sb-result-frame-h, 240px) - 1rem - 2px);
  width: auto;
  height: auto;
}

/* 全局兜底：Bootstrap reboot 里是 [hidden]{display:none!important}，CDN 不可达时失效。
   本页多处靠 .hidden 属性切换显隐（预览图、结果区、占位文案），其中
   .sb-preview-img / .sb-result-placeholder / .sb-result 都带自己的 display 声明，
   同特异性下作者样式会赢过裸 [hidden]，导致该藏的藏不住（占位文案与结果图并排）。 */
[hidden] {
  display: none !important;
}

/* 同一动机：reboot 的 *{box-sizing:border-box} 在 CDN 不可达时也失效，
   会让定高容器（.sb-result-frame 等）凭空多出 padding+border 的高度而不再等高。 */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* ---------- Sections / feature cards ---------- */

.sb-section-title {
  font-weight: 800;
}

.sb-section-sub {
  color: var(--sb-muted);
}

.sb-feature-card {
  border: 1px solid var(--sb-line);
  border-radius: var(--sb-radius);
  background: #fff;
  box-shadow: 0 2px 10px rgba(15, 23, 42, 0.04);
  transition: transform 0.16s ease, box-shadow 0.16s ease;
}

.sb-feature-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--sb-shadow);
}

.sb-feature-icon {
  width: 44px;
  height: 44px;
  border-radius: 13px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--sb-primary-soft);
  border: 1px solid var(--sb-primary-border);
  color: var(--sb-primary-active);
  font-size: 1.15rem;
}

.sb-step-num {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--sb-ink);
  color: #fff;
  font-weight: 800;
  font-size: 0.95rem;
  flex-shrink: 0;
}

.sb-step-card {
  background: #fff;
  border: 1px solid var(--sb-line);
  border-radius: var(--sb-radius);
  padding: 1.25rem;
  height: 100%;
}

.sb-showcase {
  background: var(--sb-ink);
  border-radius: var(--sb-radius-lg);
  color: #e2e8f0;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.sb-showcase .sb-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.82rem;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
}

/* ---------- FAQ：保持 Bootstrap accordion 行为，只换皮 ---------- */

.sb-faq .accordion-item {
  border: 1px solid var(--sb-line);
  border-radius: 14px !important;
  overflow: hidden;
  margin-bottom: 0.75rem;
}

.sb-faq .accordion-button {
  font-weight: 700;
  color: var(--sb-ink);
}

.sb-faq .accordion-button:not(.collapsed) {
  background: var(--sb-primary-soft);
  color: var(--sb-primary-active);
  box-shadow: none;
}

.sb-faq .accordion-button:focus {
  border-color: var(--sb-primary-border);
  box-shadow: 0 0 0 0.2rem rgba(249, 115, 22, 0.18);
}

.sb-faq .accordion-body {
  color: var(--sb-muted);
}

/* ---------- CTA + Footer ---------- */

.sb-cta {
  background: linear-gradient(135deg, #fff7ed 0%, #ffedd5 55%, #fed7aa 100%);
  border: 1px solid var(--sb-primary-border);
  border-radius: var(--sb-radius-lg);
}

.sb-footer {
  background: var(--sb-ink);
  color: #94a3b8;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.sb-footer a {
  color: #cbd5e1;
  text-decoration: none;
}

.sb-footer a:hover {
  color: #fff;
}

.sb-footer .sb-footer-title {
  color: #fff;
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.sb-footer .sb-footer-brand {
  color: #fff;
  font-weight: 800;
}

/* 页脚链接列（Tools / Legal 两栏）：竖排，链接撑满整列宽度。
   替代原来的 Bootstrap `d-flex flex-column gap-2` —— 一是把间距收进 CSS 一处控制，
   二是窄屏要按触摸目标重排，用工具类写不进媒体查询。 */
.sb-footer-links {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.sb-footer-links a {
  display: block;
}

/* 品牌列的联系方式（邮箱 + X）：**横排左对齐**，与 .sb-footer-links 的竖排相反。
   邮箱贴左，X 跟在其后保持固定间隙 —— 试过两端对齐（space-between），宽屏下两个链接会被
   甩到列的两头、中间空成一片，观感散，故回到左对齐 + 固定间距。
   `gap` 取 1.25rem 是视觉舒适值：太近（<0.75rem）两个图标标识会糊成一条，太远（>2rem）
   又会被误读成两块不相关的内容。
   两者合计约 246px，窄屏品牌列可用宽约 351px（375px 视口）—— 放得下就不拆行。
   留 wrap 是给 320px 极窄屏与未来加账号时的兜底：真放不下时优雅折行，而不是横向溢出。 */
.sb-footer-contacts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.25rem;
}

.sb-footer-contacts a {
  display: inline-flex;
  align-items: center;
}

/* 窄屏（<lg，页脚在此断点转为堆叠）把链接撑成触摸目标。
   原来每个链接只有 21px 高 —— 就是文字本身的高度，行距 29px，手指点「Privacy」容易
   落到相邻项上。这里把行距交给 min-height、gap 归零（否则白留一道 8px 反而更散）。
   取 44px 而非 WCAG 2.2 的 24px 下限：44px 是 Apple HIG 与 Material 的通行值。
   桌面指针设备无此问题，故只在窄屏生效。 */
@media (max-width: 991.98px) {
  .sb-footer-links {
    gap: 0;
  }

  .sb-footer-links a,
  .sb-footer-contacts a {
    display: flex;
    align-items: center;
    min-height: 2.75rem;
  }
}

/* ---------- 法律页正文（markdown 渲染结果，见 views/pages/legal.ts） ---------- */

/* 单列阅读区：容器不铺卡片底色，正文直接落在页面背景上 */
.sb-legal {
  padding: 3.5rem 0 4.5rem;
}

/* 正文排版：markdown 只吐裸标签（h2/p/ul/table/code），样式全部由这里给。
   不要依赖 Bootstrap 的 .container 之外的默认排版，否则列表与代码块会贴边。 */
.sb-prose {
  color: var(--sb-ink-2);
  line-height: 1.75;
  font-size: 1.0125rem;
}

.sb-prose h2 {
  margin: 2.5rem 0 0.9rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--sb-line);
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--sb-ink);
}

/* 首个二级标题紧接 H1，不需要再来一条分隔线 */
.sb-prose > h2:first-child {
  margin-top: 0.75rem;
  padding-top: 0;
  border-top: 0;
}

.sb-prose h3 {
  margin: 1.75rem 0 0.6rem;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--sb-ink);
}

.sb-prose p {
  margin: 0 0 1.05rem;
}

.sb-prose ul,
.sb-prose ol {
  margin: 0 0 1.05rem;
  padding-left: 1.35rem;
}

.sb-prose li {
  margin-bottom: 0.4rem;
}

.sb-prose li > ul,
.sb-prose li > ol {
  margin-top: 0.4rem;
  margin-bottom: 0;
}

.sb-prose strong {
  color: var(--sb-ink);
}

.sb-prose a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

.sb-prose hr {
  margin: 2.5rem 0;
  border-color: var(--sb-line);
  opacity: 1;
}

/* 表格：窄屏可横向滚动，不要撑破正文列 */
.sb-prose table {
  width: 100%;
  margin: 0 0 1.25rem;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

.sb-prose th,
.sb-prose td {
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--sb-line);
  text-align: left;
  vertical-align: top;
}

.sb-prose th {
  background: var(--sb-primary-soft);
  color: var(--sb-ink);
  font-weight: 600;
  white-space: nowrap;
}

/* 行内代码与代码块：等宽字体，别用 Bootstrap 的默认粉色 */
.sb-prose code {
  padding: 0.15rem 0.35rem;
  border-radius: 6px;
  background: #f1f5f9;
  color: var(--sb-ink);
  font-size: 0.875em;
  word-break: break-word;
}

.sb-prose pre {
  margin: 0 0 1.25rem;
  padding: 1rem 1.1rem;
  border-radius: 12px;
  background: #0f172a;
  overflow-x: auto;
}

.sb-prose pre code {
  padding: 0;
  background: none;
  color: #e2e8f0;
  font-size: 0.8125rem;
  word-break: normal;
}

/* 引用块：用于「最后更新」之类的提示行 */
.sb-prose blockquote {
  margin: 0 0 1.25rem;
  padding: 0.75rem 1.1rem;
  border-left: 3px solid var(--sb-primary);
  border-radius: 0 10px 10px 0;
  background: var(--sb-primary-soft);
  color: var(--sb-ink-2);
}

.sb-prose blockquote p:last-child {
  margin-bottom: 0;
}

/* ---------- 画廊：公开作品网格 ---------- */

/* 卡片本身是 <button>（点开弹窗），因此要显式清掉浏览器给按钮的默认样式，
   并让它表现得像站内其他卡片（与 .sb-tool-tile 同一套皮肤）。 */
.sb-gallery-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.6rem;
  background: var(--sb-surface);
  border: 1px solid var(--sb-line);
  border-radius: var(--sb-radius);
  box-shadow: 0 2px 10px rgba(15, 23, 42, 0.04);
  text-align: left;
  cursor: pointer;
  transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
}

.sb-gallery-card:hover {
  transform: translateY(-4px);
  border-color: var(--sb-primary-border);
  box-shadow: var(--sb-shadow);
}

/* 键盘可达：CDN 不可达时 Bootstrap 的 focus 圈也没了，自补一个可见焦点 */
.sb-gallery-card:focus-visible {
  outline: 2px solid var(--sb-primary);
  outline-offset: 2px;
}

/* 缩略图区：固定方形，内部图片按 contain 居中。
   锁定高度是「网格对齐」的关键 —— 作品的 viewBox 千奇百怪，
   若不锁定，一行里每张卡片会因图片高矮不同而参差。 */
.sb-gallery-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  padding: 0.5rem;
  border-radius: 10px;
  /* 透明底作品放在棋盘格上，才能看出哪些区域是透明的（与弹窗大图一致） */
  background-color: #fff;
  background-image:
    linear-gradient(45deg, #eef2f7 25%, transparent 25%, transparent 75%, #eef2f7 75%),
    linear-gradient(45deg, #eef2f7 25%, transparent 25%, transparent 75%, #eef2f7 75%);
  background-size: 14px 14px;
  background-position: 0 0, 7px 7px;
}

.sb-gallery-thumb img {
  max-width: 100%;
  max-height: 100%;
  /* SVG 常带固有尺寸，contain 保证长边撑满而不裁切 */
  object-fit: contain;
}

.sb-gallery-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  font-size: 0.72rem;
  color: var(--sb-muted);
}

.sb-gallery-scene {
  font-weight: 700;
  color: var(--sb-primary-active);
  /* 场景文案（如「字体图标」）比尺寸长，窄卡片下先保证尺寸不被挤掉 */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 弹窗大图：与缩略图同一套棋盘格。
   弹窗用 modal-lg，图的高度上限与之相称 —— 太高会让下面的下载按钮推出视口，
   太矮则宽弹窗里只剩一片空白。 */
.sb-gallery-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 280px;
  padding: 1.25rem;
  border: 1px solid var(--sb-line);
  border-radius: var(--sb-radius);
  background-color: #fff;
  background-image:
    linear-gradient(45deg, #eef2f7 25%, transparent 25%, transparent 75%, #eef2f7 75%),
    linear-gradient(45deg, #eef2f7 25%, transparent 25%, transparent 75%, #eef2f7 75%);
  background-size: 18px 18px;
  background-position: 0 0, 9px 9px;
}

.sb-gallery-stage img {
  max-width: 100%;
  /* 与 modal-lg 的比例相称：弹窗宽了而图仍是小尺寸，四周会留出大片空白 */
  max-height: 380px;
  object-fit: contain;
}

.sb-gallery-modal {
  border: none;
  border-radius: var(--sb-radius-lg);
  box-shadow: var(--sb-shadow-lg);
}

/* 弹窗内的文字统一居中，与居中的图片、按钮排成一条中轴。
   ⚠️ 必须限定在 #sbGalleryModal 内：.sb-status 是站内共用类
   （工具页 / AI 生成器页的转换状态也用它），直接改它会把别处一起带歪。 */
#sbGalleryModal .sb-status,
#sbGalleryModal .sb-gallery-modal-meta {
  text-align: center;
}

/* 分页：改用站内橙色主色（Bootstrap 默认是蓝） */
.sb-pagination .page-link {
  color: var(--sb-primary-active);
  border-color: var(--sb-line);
}

.sb-pagination .page-item.active .page-link {
  background: var(--sb-primary);
  border-color: var(--sb-primary);
  color: #fff;
}

.sb-pagination .page-item.disabled .page-link {
  color: var(--sb-muted);
}

@media (max-width: 575.98px) {
  /* 窄屏下弹窗近乎全屏，380px 的图会把下载按钮挤出视口，故再收一档 */
  .sb-gallery-stage {
    min-height: 200px;
    padding: 0.75rem;
  }

  .sb-gallery-stage img {
    max-height: 240px;
  }
}

/* ---------- 通用 ---------- */

.sb-muted {
  color: var(--sb-muted) !important;
}

.sb-divider {
  border-color: var(--sb-line) !important;
}

@media (max-width: 991.98px) {
  .sb-hero {
    text-align: left;
  }

  .sb-hero .sb-trust {
    justify-content: flex-start !important;
  }

  /* 折叠后的下拉菜单与顶部栏留出间隙，不再贴顶 */
  .sb-header .navbar-collapse {
    margin-top: 0.85rem;
    padding-top: 0.85rem;
    border-top: 1px solid var(--sb-line);
  }

  .sb-header .navbar-nav {
    gap: 0.25rem;
  }

  .sb-header .navbar-nav .nav-item {
    width: 100%;
  }

  .sb-header .navbar-collapse .nav-link {
    padding: 0.7rem 0.85rem !important;
  }

  /* 工具页：结果对比在窄屏改为上下堆叠，箭头转 90°，框高略降以免占屏过多 */
  .sb-result {
    --sb-result-frame-h: 200px;
  }

  .sb-result-grid {
    grid-template-columns: 1fr;
  }

  /* 只对单图布局转箭头：ICO 是横向小图标行，自带换行，箭头转 90° 反而指错方向 */
  .sb-result-grid .sb-result-arrow {
    transform: rotate(90deg);
    justify-self: center;
  }

  .sb-dropzone {
    padding: 1.5rem 1rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  body.sb-body .btn-primary:hover,
  .sb-feature-card:hover {
    transform: none;
  }
}
