/* ══════════════════════════════════════════════════════════════
   有用工具箱 · 全站统一样式（design tokens + 公共组件）
   ──────────────────────────────────────────────────────────────
   来源：把 2026 年新增工具页（video-tools / audio-tools / image-tools /
   pdf-tools / parquet-tools / noise-reduction / media-convert /
   mp4-to-mp3）里那套视觉规范抽出来，作为全站唯一来源。

   接入方式（详见 static/THEME.md）：
     1) 在 <head> 里加 <link rel="stylesheet" href="static/theme.css">；
     2) 页面只保留自己特有的样式；
     3) 顶部导航统一用 .topbar 结构。


   ⚠ 两条必须理解的级联规则，否则会踩坑：

   （一）公共组件放在 @layer theme 里。
        分层样式**永远输给页面自身未分层的规则**（先比层级、再比优先级），
        所以本文件只提供默认值：页面自己定义了同名类或同名 token 就听页面的，
        深色模式（[data-theme="dark"]）不会被弄坏。

   （二）「基础排版 + 容器」刻意**不放进 layer**。
        旧页面里普遍有一句未分层的 *{margin:0;padding:0}，
        若把 .wrap 的 padding 放进 layer，会被那句通配符盖掉、内容贴边；
        未分层 + 类选择器优先级高于通配符，才能稳稳生效。
   ══════════════════════════════════════════════════════════════ */

/* ════════ 基础排版与容器：未分层（原因见规则二）════════════════ */

*,*::before,*::after{box-sizing:border-box}
body{
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;
  background:var(--bg);color:var(--text);font-size:14px;min-height:100vh;
  -webkit-font-smoothing:antialiased;
}
a{text-decoration:none}
/* 容器尺寸也走 :where()（优先级 0）：页面自己写的 .container/.app 等
   具体规则的宽高与内边距依然生效，只兜底「页面没定义」的情况。 */
:where(.wrap){max-width:1080px;margin:0 auto;padding:16px}
:where(.wrap.narrow){max-width:860px}
:where(.wrap.wide){max-width:1400px}
.hidden{display:none !important}
@media (max-width:640px){
  :where(.wrap){padding:10px}
}

@keyframes tk-slide{0%{margin-left:-35%}100%{margin-left:100%}}

/* ════════ 深色模式的公共组件兜底（未分层，优先级高于 layer 内的组件）════════
   多数旧页面的深色是「选择器式」写法（[data-theme="dark"] body{...!important}），
   并没有重定义 --card/--border 这些 token。于是 theme.css 的顶栏、标签、返回按钮
   仍取浅色值，在暗色页面上会出现一条白条。
   这里按各页面模板用的那套深色值（#0f1117 底 / #171b23 面 / rgba(255,255,255,.09) 描边）
   把 chrome 补成深色；页面自己写的 [data-theme="dark"] 规则若更靠后或带 !important，
   依然会覆盖这里。 */
[data-theme="dark"] .topbar{background:#171b23;border-color:rgba(255,255,255,.09);box-shadow:none}
[data-theme="dark"] .topbar h1{color:#e6edf3}
[data-theme="dark"] .topbar h1 .dot{background:#3fb950}
[data-theme="dark"] .tag{background:rgba(63,185,80,.14);border-color:rgba(63,185,80,.3);color:#3fb950}
[data-theme="dark"] .home-link{background:#21262d;border-color:rgba(255,255,255,.15);color:#c9d1d9}
[data-theme="dark"] .home-link:hover{border-color:#58a6ff;color:#58a6ff}
[data-theme="dark"] .icon-btn{background:#21262d;border-color:rgba(255,255,255,.15);color:#c9d1d9}
[data-theme="dark"] .icon-btn:hover{background:#2d333b;border-color:#58a6ff;color:#58a6ff}
[data-theme="dark"] .card{background:#171b23;border-color:rgba(255,255,255,.09)}
[data-theme="dark"] .spacer{color:#8b949e}

/* ════════ 设计变量与公共组件：放在 layer 里兜底 ═════════════════ */
@layer theme {

  /* ---------- 设计变量 ---------- */
  :root{
    --bg:#f5f6fa;          /* 页面底色 */
    --card:#ffffff;        /* 卡片 */
    --border:#e4e7ef;      /* 描边 */
    --text:#24292f;        /* 正文 */
    --sub:#7a8294;         /* 次要文字 */
    --accent:#3b6ef6;      /* 主色 */
    --accent-h:#2d5de0;    /* 主色 hover */
    --active:#eef3ff;      /* 选中/浅底 */
    --ok:#1f9d55;          /* 成功 */
    --warn:#b7791f;        /* 警告 */
    --err:#d64545;         /* 错误 */
    --shadow:0 1px 3px rgba(20,30,60,.05);
    --mono:ui-monospace,Consolas,"SF Mono",Menlo,monospace;
  }

  /* ---------- 顶栏 ---------- */
  .topbar{
    display:flex;align-items:center;gap:10px;flex-wrap:wrap;
    background:var(--card);border:1px solid var(--border);border-radius:12px;
    padding:12px 14px;margin-bottom:14px;box-shadow:var(--shadow);
  }
  .topbar h1{font-size:17px;font-weight:700;display:flex;align-items:center;gap:8px}
  /* 窄容器（如 OTP 验证器那种窄栏布局）里让标题/标签先收缩省略，
     而不是把「返回首页」挤到第二行 —— 导航始终留在同一行。 */
  .topbar > *{flex-shrink:0}
  .topbar > h1,.topbar > .tag{flex-shrink:1;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
  .topbar h1 .dot{width:9px;height:9px;border-radius:50%;background:#28c76f;display:inline-block;flex-shrink:0}
  .tag{
    font-size:12px;color:var(--ok);background:#eaf7f0;border:1px solid #d2ecdd;
    border-radius:6px;padding:3px 8px;white-space:nowrap;
  }
  .spacer{flex:1}
  .home-link{
    display:inline-flex;align-items:center;gap:5px;color:var(--sub);font-size:13px;
    border:1px solid var(--border);border-radius:8px;padding:8px 12px;
    transition:all .15s;background:#fff;white-space:nowrap;
  }
  .home-link:hover{border-color:var(--accent);color:var(--accent)}

  /* ---------- 卡片 ---------- */
  .card{
    background:var(--card);border:1px solid var(--border);border-radius:12px;
    padding:18px;margin-bottom:14px;box-shadow:var(--shadow);
  }
  .card.flat{padding:14px}
  .chead{display:flex;align-items:baseline;gap:10px;margin-bottom:14px;flex-wrap:wrap}
  .chead .ct{font-size:15px;font-weight:700}
  .chead .cd{font-size:12.5px;color:var(--sub)}

  /* ---------- 拖拽/选择区 ---------- */
  .drop{
    border:2px dashed #ccd3e3;border-radius:12px;padding:34px 20px;text-align:center;
    cursor:pointer;transition:all .18s;background:#fbfcfe;
  }
  .drop:hover{border-color:var(--accent);background:var(--active)}
  .drop.over{border-color:var(--accent);background:var(--active);transform:scale(1.005)}
  .drop .ico{font-size:32px;line-height:1;margin-bottom:12px}
  .drop .t1{font-size:15px;font-weight:600;margin-bottom:6px}
  .drop .t2{font-size:12.5px;color:var(--sub);line-height:1.7}

  /* ---------- 文件信息行 ---------- */
  .fileinfo{
    display:flex;align-items:center;gap:12px;padding:12px 14px;
    border:1px solid var(--border);border-radius:10px;background:#fbfcfe;
  }
  .fileinfo .fico{font-size:22px;flex-shrink:0}
  .fileinfo .fmeta{flex:1;min-width:0}
  .fileinfo .fname{font-size:14px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fileinfo .fdesc{font-size:12.5px;color:var(--sub);margin-top:3px;line-height:1.6}
  .fileinfo .fdesc b{color:var(--text)}
  .fileinfo .fdesc .codec{color:var(--accent);font-weight:600}

  /* ---------- 选项行 ---------- */
  .opt-row,.row{display:flex;align-items:center;gap:12px;padding:10px 0;flex-wrap:wrap}
  .opt-row + .opt-row,.row + .row{border-top:1px solid #f2f4f9}
  .opt-label,.rlabel{width:92px;flex-shrink:0;color:var(--sub);font-size:13px}
  .opt-body,.rbody{flex:1;min-width:220px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
  .hint{font-size:12.5px;color:var(--sub);line-height:1.7}
  .hint b{color:var(--text)}
  .hint.strong{color:var(--accent)}
  .hint.warn{color:var(--warn)}
  .hint code,.alert code,.tip code{
    font-family:var(--mono);font-size:11.5px;background:#f2f4f9;padding:1px 5px;border-radius:4px;
  }

  /* ---------- 分段控件 ---------- */
  .seg{display:flex;border:1px solid var(--border);border-radius:8px;overflow:hidden;background:#fff;flex-wrap:wrap}
  .seg button{
    border:0;background:#fff;color:var(--text);padding:8px 13px;cursor:pointer;
    font-size:12.5px;font-family:inherit;transition:all .15s;white-space:nowrap;
  }
  .seg button + button{border-left:1px solid var(--border)}
  .seg button:hover:not(.on){color:var(--accent)}
  .seg button.on{background:var(--accent);color:#fff}

  /* ---------- 表单控件 ---------- */
  select,input[type=text],input[type=number],input[type=search]{
    border:1px solid var(--border);border-radius:8px;
    background:#fff;color:var(--text);font-size:13px;font-family:inherit;outline:0;
  }
  select{cursor:pointer}
  select:focus,input:focus,textarea:focus{border-color:var(--accent)}
  select:disabled,input:disabled{background:#f6f7fa;color:#b6bccc;cursor:not-allowed}
  input[type=color]{width:38px;height:34px;padding:2px;border:1px solid var(--border);border-radius:8px;background:#fff;cursor:pointer}
  input[type=range]{flex:1;min-width:130px;max-width:280px;accent-color:var(--accent);cursor:pointer}
  input[type=range]:disabled{opacity:.45;cursor:not-allowed}
  input[type=checkbox],input[type=radio]{accent-color:var(--accent);width:15px;height:15px;cursor:pointer}
  textarea{
    border:1px solid var(--border);border-radius:8px;background:#fff;color:var(--text);
    font-size:13px;font-family:inherit;outline:0;padding:8px 10px;
  }
  .val{font-variant-numeric:tabular-nums;font-size:12.5px;font-weight:600;min-width:44px;text-align:right}
  .chk{display:inline-flex;align-items:center;gap:6px;font-size:13px;cursor:pointer;user-select:none;white-space:nowrap}

  /* ---------- 按钮 ---------- */
  .btn{
    border:1px solid var(--border);background:#fff;color:var(--text);
    padding:9px 15px;border-radius:8px;cursor:pointer;font-size:13px;
    font-family:inherit;transition:all .15s;white-space:nowrap;
  }
  .btn:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
  .btn:disabled{opacity:.5;cursor:not-allowed}
  .btn.primary{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:600}
  .btn.primary:hover:not(:disabled){background:var(--accent-h);border-color:var(--accent-h);color:#fff}
  .btn.ghost{color:var(--sub)}
  .btn.danger{border-color:#f3d3d3;color:var(--err)}
  .btn.danger:hover:not(:disabled){border-color:var(--err);color:var(--err)}
  .btn.sm{padding:6px 11px;font-size:12.5px}
  .actions{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-top:14px}
  .icon-btn{
    background:#fff;border:1px solid var(--border);color:var(--sub);width:38px;height:38px;
    border-radius:10px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;
    font-size:1.05rem;transition:all .15s;padding:0;
  }
  .icon-btn:hover{background:var(--active);color:var(--accent);border-color:#c9d8ff}

  /* ---------- 进度 ---------- */
  .bar{height:8px;border-radius:99px;background:#eef0f6;overflow:hidden;margin-top:14px}
  .bar > i{display:block;height:100%;width:0;border-radius:99px;background:linear-gradient(90deg,#5b8cff,#3b6ef6);transition:width .18s ease}
  .bar.indet > i{width:35% !important;animation:tk-slide 1.1s ease-in-out infinite;transition:none}
  .status-line{margin-top:8px;font-size:12.5px;color:var(--sub)}
  .log-line{
    margin-top:6px;font-family:var(--mono);font-size:11.5px;color:#9aa1b1;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }

  /* ---------- 提示块 ---------- */
  .alert{border-radius:10px;padding:14px;font-size:13px;line-height:1.75;margin-top:12px}
  .alert.err{border:1px solid #f3d3d3;background:#fdf6f6;color:#8a3030}
  .alert.warn{border:1px solid #f0e2c4;background:#fdfaf3;color:#7a5b17}
  .alert.ok{border:1px solid #d2ecdd;background:#f6fcf9;color:#1c6b40}
  .alert .at{font-weight:700;margin-bottom:6px;display:flex;align-items:center;gap:6px}
  .alert ul{margin:6px 0 0 18px}
  .alert li{margin:3px 0}
  .alert .btn{margin-top:10px}

  /* ---------- 结果区 ---------- */
  .result{border:1px solid #d2ecdd;background:#f6fcf9;border-radius:10px;padding:14px}
  .result .rhead{font-size:13.5px;font-weight:700;color:var(--ok);margin-bottom:10px}
  .result video{width:100%;max-height:340px;display:block;border-radius:6px;background:#000;margin-bottom:12px}
  .result audio{width:100%;height:34px;display:block;margin-bottom:12px}
  .result img{max-width:100%;max-height:300px;display:block;margin:0 auto 12px;border-radius:6px;border:1px solid var(--border);background:#fff}
  .rmeta{font-size:12.5px;color:var(--sub);margin-bottom:12px;line-height:1.75;word-break:break-all}
  .rmeta b{color:var(--text)}
  .rmeta code{font-family:var(--mono);font-size:11.5px;background:rgba(0,0,0,.045);padding:1px 5px;border-radius:4px}
  .reportpre{
    font-family:var(--mono);font-size:12px;line-height:1.7;background:#fff;
    border:1px solid var(--border);border-radius:8px;padding:12px;max-height:340px;
    overflow:auto;white-space:pre;margin-bottom:12px;
  }

  /* ---------- 底部说明 ---------- */
  .tip{
    background:var(--card);border:1px solid var(--border);border-radius:12px;
    padding:16px 18px;font-size:12.5px;color:var(--sub);line-height:1.9;
    box-shadow:var(--shadow);margin-top:14px;
  }
  .tip h2{font-size:13.5px;color:var(--text);margin-bottom:8px}
  .tip b{color:var(--text)}
  .tip ul{margin:4px 0 4px 18px}
  .tip li{margin:3px 0}

  /* ---------- 工具类 ---------- */
  .mono{font-family:var(--mono)}
  .muted{color:var(--sub)}
  .center{text-align:center}

  /* ---------- 窄屏微调（仅组件部分） ---------- */
  @media (max-width:640px){
    .tag{display:none}
    .card{padding:14px}
    .drop{padding:26px 14px}
    .opt-label,.rlabel{width:auto;min-width:64px}
    .opt-body,.rbody{min-width:0}
    input[type=range]{max-width:100%}
  }
}

/* ════════════ 间距兜底：未分层 + :where()（原因见下）════════════

   旧页面里普遍有一句未分层的 `*{margin:0;padding:0}`。CSS 级联是
   「先比层级、再比优先级」，所以分层里的 .topbar{padding:12px 14px}
   会被那句通配符直接清零 —— 表现就是顶栏/标签/返回按钮被压扁、
   padding 为 0（实测顶栏高度 62px → 40px）。

   解决办法：把「会被 reset 清零的间距属性」单独用未分层的 :where() 再声明一次。
   :where() 优先级为 0：
     · 与 *{padding:0} 同级 → 本文件在后面 → 压过通配符 reset ✓
     · 低于页面自己写的 .card{padding:32px} 等具体规则 → 页面自定义间距依然生效 ✓
   所以这里只补间距，不动颜色/边框，页面自身的主题与布局不受影响。 */
:where(.topbar){padding:12px 14px;margin-bottom:14px}
:where(.topbar h1){gap:8px}
:where(.tag){padding:3px 8px}
:where(.home-link){padding:8px 12px}
:where(.icon-btn){padding:0}
:where(.card){padding:18px;margin-bottom:14px}
:where(.card.flat){padding:14px}
:where(.chead){margin-bottom:14px}
:where(.drop){padding:34px 20px}
:where(.drop .ico){margin-bottom:12px}
:where(.drop .t1){margin-bottom:6px}
:where(.fileinfo){padding:12px 14px}
:where(.fileinfo .fdesc){margin-top:3px}
:where(.opt-row),:where(.row){padding:10px 0}
:where(.seg button){padding:8px 13px}
:where(select),:where(input[type=text]),:where(input[type=number]),:where(input[type=search]){padding:0 9px;min-height:34px}
:where(input[type=number]){width:84px}
:where(textarea){padding:8px 10px}
:where(input[type=color]){padding:2px}
:where(.hint code),:where(.alert code),:where(.tip code){padding:1px 5px}
:where(.btn){padding:9px 15px}
:where(.btn.sm){padding:6px 11px}
:where(.actions){margin-top:14px}
:where(.bar){margin-top:14px}
:where(.status-line){margin-top:8px}
:where(.log-line){margin-top:6px}
:where(.alert){padding:14px;margin-top:12px}
:where(.alert .at){margin-bottom:6px}
:where(.alert ul),:where(.tip ul){margin:6px 0 0 18px}
:where(.alert li),:where(.tip li){margin:3px 0}
:where(.alert .btn){margin-top:10px}
:where(.result){padding:14px}
:where(.result .rhead){margin-bottom:10px}
:where(.result audio),:where(.result video),:where(.result img){margin-bottom:12px}
:where(.rmeta){margin-bottom:12px}
:where(.reportpre){padding:12px;margin-bottom:12px}
:where(.tip){padding:16px 18px;margin-top:14px}
:where(.tip h2){margin-bottom:8px}
:where(.fileinfo .fname),:where(.card .fname){margin-top:0}


   <div class="topbar">
     <h1><span class="dot"></span>工具名称</h1>
     <span class="tag">一句话说明（用它承载页面原本的副标题）</span>
     <div class="spacer"></div>
     <a class="home-link" href="index.html" title="返回工具箱首页">← 返回首页</a>
   </div>

   页面容器用 <div class="wrap"> … </div>（需要差异用 wrap narrow / wrap wide）；
   子目录页面（负鼠/、jqueryApi/）里返回链接写 ../index.html。
   等宽文本（日志、报告、码值）用 .reportpre 或 .mono，不要自己写 font-family。
   ══════════════════════════════════════════════════════════════ */
