/* =========================================================
   工具箱 · 样式表
   ---------------------------------------------------------
   配色策略：纯黑白，只用黑 / 白 / 灰阶，不引入任何彩色。
   层次靠「字重 + 填充 + 对比度」拉开，不靠颜色。
   深浅两套模式，同一套设计变量切换。
   ========================================================= */

:root {
  /* ---- 亮色（默认）：白底黑字 ---- */
  --paper:       #fbfbfa;   /* 页面底色，带一点暖，不用纯白 */
  --surface:     #ffffff;   /* 卡片、输入框 */
  --ink:         #151515;   /* 主文字，不用纯黑 */
  --ink-2:       #5c5c60;   /* 次要文字 */
  --ink-3:       #8e8e94;   /* 元信息、标签 */
  --line:        #e4e4e2;   /* 分隔线、边框 */
  --line-strong: #c9c9c5;   /* 悬停时的边框 */
  --fill:        #151515;   /* 实心按钮底色 */
  --on-fill:     #ffffff;   /* 实心按钮文字 */

  /* 告诉浏览器现在是亮色：输入框、下拉框、滚动条这些由浏览器
     自己画的部件会跟着用亮色，不会在深色页面里突兀地亮一块。 */
  color-scheme: light;

  /* ---- 字号 ---- */
  --fs-body: 1rem;
  --fs-sm:   .875rem;
  --fs-xs:   .8125rem;
  --fs-h1:   clamp(1.6rem, 1.2rem + 1.6vw, 2.1rem);
  --lh: 1.7;

  /* ---- 间距 ---- */
  --sp-1: .25rem;
  --sp-2: .5rem;
  --sp-3: .75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;

  /* ---- 布局 ---- */
  /* 页面宽度。和主站（style.css）保持一致，两边都是 64rem。
     改一个务必改另一个，否则跨站跳转时容器会宽窄不一。 */
  --wrap: 64rem;
  --radius: 6px;   /* 全站统一一种圆角，不混用 */

  /* ---- 字体（全部系统字体，零外部依赖）---- */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
               "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;
}

/* ---- 深色：按了页头开关手动选的这套 ----
   黑底白字，仍然是黑白。
   ⚠️ 下面这 9 个颜色和再下面 @media 里那份必须一模一样，
   改一个务必改另一个，不然「手动深色」和「跟随系统深色」
   会长得不一样。 */
:root[data-theme="dark"] {
  --paper:       #0f0f0f;
  --surface:     #171717;
  --ink:         #ededed;
  --ink-2:       #a2a2a6;
  --ink-3:       #6f6f74;
  --line:        #262626;
  --line-strong: #3d3d3d;
  --fill:        #ededed;
  --on-fill:     #0f0f0f;
  color-scheme: dark;
}

/* ---- 深色：没按过开关时跟着系统走 ----
   也是禁用 JS 时的兜底（那样就切不了了，至少系统是深色时它还深）。
   :not([data-theme]) 是关键 —— 手动选过亮色的人，
   哪怕系统是深色，也不该被这份规则拉回去。 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --paper:       #0f0f0f;
    --surface:     #171717;
    --ink:         #ededed;
    --ink-2:       #a2a2a6;
    --ink-3:       #6f6f74;
    --line:        #262626;
    --line-strong: #3d3d3d;
    --fill:        #ededed;
    --on-fill:     #0f0f0f;
    color-scheme: dark;
  }
}

/* =========================================================
   基础
   ========================================================= */

*, *::before, *::after { box-sizing: border-box; }

/* 根元素必须自己铺一层底色。
   不写这条的话，页面之外的「画布」底色由 color-scheme 推导 ——
   切换深浅色时它会比页面内容先一步跳变（白变纯黑），而它不属于
   DOM、不在视图快照里，动画收尾撤掉快照的那一帧就会闪出这块纯黑。
   写在 html 上，底色就成了页面的一部分，跟着快照一起参与动画。 */
html {
  -webkit-text-size-adjust: 100%;
  background: var(--paper);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

::selection {
  background: var(--ink);
  color: var(--paper);
}

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 var(--sp-5);
}

/* 键盘用户跳过导航直达正文 */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
}
.skip:focus {
  left: var(--sp-4);
  top: var(--sp-4);
  z-index: 10;
  padding: var(--sp-2) var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--ink);
  border-radius: var(--radius);
  font-size: var(--fs-sm);
}

/* =========================================================
   页头
   ========================================================= */

.site-header {
  border-bottom: 1px solid var(--line);
}

.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  min-height: 4rem;      /* 64px，保证单行 */
}

.brand {
  font-size: 1rem;
  font-weight: 650;
  letter-spacing: .01em;
}

.nav {
  display: flex;
  gap: var(--sp-5);
  font-size: var(--fs-sm);
}
.nav a { color: var(--ink-2); }
.nav a:hover { color: var(--ink); }
.nav a[aria-current="page"] {
  color: var(--ink);
  font-weight: 600;
}

/* =========================================================
   首页：引导语 + 工具卡片
   ========================================================= */

.intro {
  padding: var(--sp-7) 0 var(--sp-6);
}
.intro h1 {
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-h1);
  font-weight: 650;
  line-height: 1.3;
  letter-spacing: -.01em;
}
.intro p {
  max-width: 40rem;
  margin: 0;
  color: var(--ink-2);
}

.tools {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  /* 所有行等高：这样还没填内容的空卡片也和其他卡片一样大，不会塌下去 */
  grid-auto-rows: 1fr;
  gap: var(--sp-4);
  margin: 0 0 var(--sp-7);
  padding: 0;
  list-style: none;
}

.card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  height: 100%;
  padding: var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color .15s ease;
}

a.card:hover { border-color: var(--line-strong); }
a.card:hover .card-title { text-decoration: underline; text-underline-offset: 3px; }
a.card:active { transform: translateY(1px); }

.card-tag {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--ink-3);
  letter-spacing: .04em;
}

.card-title {
  margin: 0;
  font-size: 1.0625rem;
  font-weight: 600;
}

.card-desc {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--ink-2);
}

/* 尚未实现的工具：虚线边框 + 灰色标题，一眼看出不可点 */
.card--soon {
  background: transparent;
  border-style: dashed;
}
.card--soon .card-title { color: var(--ink-3); }

.card-badge {
  align-self: flex-start;
  margin-top: auto;
  padding: .1rem .5rem;
  font-family: var(--font-mono);
  font-size: .75rem;
  color: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* =========================================================
   工具页
   ========================================================= */

.back {
  display: inline-block;
  margin-bottom: var(--sp-5);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--ink-3);
}
.back:hover { color: var(--ink); }

.tool-head {
  padding: var(--sp-6) 0 var(--sp-5);
}
.tool-head h1 {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-h1);
  font-weight: 650;
  line-height: 1.3;
  letter-spacing: -.01em;
}
.tool-head p {
  max-width: 44rem;
  margin: 0;
  color: var(--ink-2);
}

.tool-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-4);
}

.panel {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.panel-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

textarea {
  width: 100%;
  min-height: 20rem;
  padding: var(--sp-4);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  line-height: 1.65;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  resize: vertical;
}
textarea::placeholder { color: var(--ink-3); }
textarea:focus-visible {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 1px var(--ink);
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}

.btn {
  padding: .5rem 1rem;
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color .15s ease, opacity .15s ease;
}
.btn:hover { border-color: var(--ink); }
.btn:active { transform: translateY(1px); }

.btn--primary {
  color: var(--on-fill);
  background: var(--fill);
  border-color: var(--fill);
}
.btn--primary:hover { opacity: .85; }

/* 状态提示：用字重和左侧竖线表达，不用颜色 */
.status {
  min-height: 1.6em;
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.status[data-kind="error"] {
  padding-left: var(--sp-3);
  border-left: 2px solid var(--ink);
  color: var(--ink);
  font-weight: 600;
}
.status[data-kind="ok"] {
  padding-left: var(--sp-3);
  border-left: 2px solid var(--line-strong);
}

.note {
  margin-top: var(--sp-7);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.note h2 {
  margin: 0 0 var(--sp-3);
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
}
.note ul { margin: 0; padding-left: 1.3em; }
.note li { margin-bottom: var(--sp-2); }

kbd {
  padding: .05rem .35rem;
  font-family: var(--font-mono);
  font-size: .8em;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
}

/* ---- Python 在线运行：代码区 + 输出控制台 ---- */

/* 输出控制台。空的时候用伪元素显示占位文字，是"空状态"而不是死白 */
.console {
  min-height: 20rem;
  max-height: 32rem;
  padding: var(--sp-4);
  overflow-y: auto;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  line-height: 1.65;
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.console:empty::before {
  content: "运行结果会显示在这里";
  color: var(--ink-3);
}

/* 输出里的三种行：普通输出 / 报错 / 系统提示 */
.console .out { color: var(--ink); }
.console .err {
  padding-left: var(--sp-3);
  border-left: 2px solid var(--ink);
  color: var(--ink);
  font-weight: 600;
}
.console .sys { color: var(--ink-3); }

/* 运行时加载条 */
.loader {
  display: none;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.loader.is-on { display: flex; }
.loader-track {
  flex: 1;
  height: 2px;
  background: var(--line);
  overflow: hidden;
}
.loader-bar {
  display: block;
  width: 30%;
  height: 100%;
  background: var(--ink);
  animation: slide 1.1s ease-in-out infinite;
}
@keyframes slide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(400%); }
}

/* =========================================================
   关于页
   ========================================================= */

.prose {
  max-width: 40rem;
  padding: var(--sp-6) 0 var(--sp-7);
}
.prose h1 {
  margin: 0 0 var(--sp-5);
  font-size: var(--fs-h1);
  font-weight: 650;
  line-height: 1.3;
  letter-spacing: -.01em;
}
.prose h2 {
  margin: var(--sp-6) 0 var(--sp-3);
  font-size: 1.0625rem;
  font-weight: 600;
}
.prose p { margin: 0 0 var(--sp-4); color: var(--ink-2); }
.prose ul { margin: 0 0 var(--sp-4); padding-left: 1.3em; color: var(--ink-2); }
.prose li { margin-bottom: var(--sp-2); }

/* =========================================================
   进制转换
   ========================================================= */

.conv-list {
  max-width: 46rem;
  margin: 0 0 var(--sp-5);
  padding: 0;
  list-style: none;
}

.conv-row {
  display: grid;
  grid-template-columns: 5.5rem 1fr auto;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) 0;
}

.conv-row label {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

/* 正在输入的那一行，标签加粗，一眼看得出是哪一格 */
.conv-row.is-source label {
  color: var(--ink);
  font-weight: 600;
}

.conv-row input {
  width: 100%;
  padding: .5rem .75rem;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.conv-row input::placeholder { color: var(--ink-3); }
.conv-row input:focus-visible {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 1px var(--ink);
}

.btn--tiny {
  padding: .3rem .6rem;
  font-size: var(--fs-xs);
}

/* 一个简单的复选开关 */
.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  cursor: pointer;
}
.switch input { margin: 0; }

/* 勾选组换行时，和上面一组拉开点距离 */
.radio-group--block { margin-top: var(--sp-4); }

/* 数字输入框，用在参数行里。
   宽度写死，不用 100%：它在 auto 列里，百分比算不出来。 */
.num {
  width: 6.5rem;
  padding: .4rem .6rem;
  font: inherit;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.num:focus-visible {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 1px var(--ink);
}

/* 数字输入那一行单独排一下。
   默认的三列是「标签 | 1fr | 单位」，输入框被 1fr 撑满整行，
   单位就被顶到最右边，中间空一大片。
   换成 auto 列，输入框只占自己需要的宽度，单位紧跟在后面。

   带上 .opt-list 前缀是为了提高优先级：
   窄屏那条 .opt-row 规则写在文件更后面，不加前缀会被它盖掉。 */
.opt-list .opt-row--num {
  grid-template-columns: 5.5rem auto 1fr;
  column-gap: var(--sp-3);
}

/* 光改列宽还不够。单位那一格用的是 .opt-row .val，
   它带着 min-width: 4.5rem 和 text-align: right，那是给滑块行做的
   （数值右对齐看着整齐），但放到这里会把「位」顶到整行最右边。
   所以要单独把这两条掰回来。 */
.opt-list .opt-row--num .val {
  min-width: 0;
  text-align: left;
}

/* =========================================================
   图片压缩
   ========================================================= */

/* 小节的标题，比正文小一号 */
.section-label {
  margin: var(--sp-5) 0 var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--ink-3);
  letter-spacing: .04em;
}

/* 同一页里两块功能区之间的分隔线 */
.sep {
  height: 1px;
  margin: var(--sp-7) 0 var(--sp-5);
  background: var(--line);
}

/* 跟在标题下面的一段说明 */
.hint {
  max-width: 34rem;
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-sm);
  line-height: 1.7;
  color: var(--ink-2);
}

/* 选择区：能点，也能把文件拖进来 */
.drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 10rem;
  padding: var(--sp-6);
  text-align: center;
  background: var(--surface);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color .15s ease, border-style .15s ease;
}
.drop:hover,
.drop.is-over {
  border-color: var(--ink);
  border-style: solid;
}
.drop-text { font-size: var(--fs-sm); color: var(--ink); }
.drop-hint {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--ink-3);
}

/* 原图 / 压缩后 并排 */
.preview-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-4);
  margin-bottom: var(--sp-4);
}

.preview-box {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-width: 0;
}

.preview-img {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 11rem;
  padding: var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.preview-img img {
  display: block;
  max-width: 100%;
  max-height: 16rem;
}

/* 参数行 */
.opt-list {
  max-width: 34rem;
  margin: 0 0 var(--sp-5);
  padding: 0;
  list-style: none;
}

.opt-row {
  display: grid;
  grid-template-columns: 5.5rem 1fr auto;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-2) 0;
}
.opt-row > label {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.opt-row .val {
  min-width: 4.5rem;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--ink-3);
  text-align: right;
}

input[type="range"] {
  width: 100%;
  accent-color: var(--ink);
}

.radio-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
}
.switch.is-off {
  opacity: .4;
  cursor: not-allowed;
}

/* 结果条：左边一条粗竖线，和状态提示的样式是同一套语言 */
.result {
  max-width: 34rem;
  margin-bottom: var(--sp-5);
  padding: var(--sp-4);
  font-size: var(--fs-sm);
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 2px solid var(--ink);
  border-radius: var(--radius);
}

/* =========================================================
   页脚
   ========================================================= */

.site-footer {
  margin-top: var(--sp-7);
  padding: var(--sp-5) 0;
  border-top: 1px solid var(--line);
  font-size: var(--fs-xs);
  color: var(--ink-3);
}
.site-footer .wrap {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--sp-3);
}
.site-footer p { margin: 0; }
.site-footer a:hover { color: var(--ink); }

/* =========================================================
   窄屏
   ========================================================= */

@media (max-width: 800px) {
  /* 工具页的双栏在手机上必须塌成单栏 */
  .tool-grid { grid-template-columns: 1fr; }
  textarea { min-height: 14rem; }
}

@media (max-width: 600px) {
  .intro { padding: var(--sp-6) 0 var(--sp-5); }
  .tools { grid-template-columns: 1fr; }
  .site-header .wrap { min-height: 3.5rem; }

  /* 图片压缩：两张预览竖排；参数行的三列收窄，别挤在一块 */
  .preview-pair { grid-template-columns: 1fr; }
  .opt-list { max-width: none; }
  .opt-row { grid-template-columns: 4.5rem 1fr auto; gap: var(--sp-2); }
  .opt-row .val { min-width: 3.5rem; }
}

/* =========================================================
   减少动效
   ========================================================= */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
  }
}
