/* ============================================================
   主题变量
   浅色为默认值，[data-theme="dark"] 覆盖。
   Canvas 需要的颜色也在这里定义，供 JS 通过 getComputedStyle 读取。
   ============================================================ */
:root {
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #fbfcfd;
  --line: #e3e6ea;
  --text: #14161a;
  --text-2: #62676f;
  --text-3: #6f757e;   /* 对 --surface 4.6:1 / --surface-2 4.5:1，满足 WCAG AA */
  --accent: #0091ff;
  --accent-ink: #ffffff;
  --ok: #12a594;
  --warn: #f76b15;
  --danger: #e5484d;
  --radius: 12px;
  --shadow: 0 1px 2px rgba(20, 22, 26, .05), 0 8px 24px rgba(20, 22, 26, .07);
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* 画布相关（JS 读取） */
  --cv-backdrop: #eef0f3;   /* 画布外的背景 */
  --cv-surface: #ffffff;   /* 画布底板（未认领格） */
  --cv-border: #c8cdd4;    /* 画布外框 */
  --cv-grid: rgba(0, 0, 0, .07);
  --cv-grid-strong: rgba(0, 0, 0, .16);
  --cv-hover: #0091ff;
  --mm-empty: 245, 247, 250;  /* 小地图空白区 RGB */

  /* 图片图层（JS 通过 imgColors() 读取，按主题缓存）
     注意：图片**像素本身**不随主题变色 —— 那是用户付费买的原图。
     这里只定义外框 / 占位底色 / 失败提示 / 标签这几个"周边装饰"，
     深浅主题下都要保证能看清。 */
  --img-border: #b9c0c9;      /* 图片外框 */
  --img-accent: #0091ff;      /* 待放置预览的虚线框 */
  --img-bg: rgba(0, 145, 255, .10);      /* 加载中占位 */
  --img-label-fg: #6f757e;    /* 尺寸标签文字 */
  --img-err: #e5484d;         /* 加载失败文字 */
  --img-err-bg: rgba(229, 72, 77, .14);  /* 加载失败占位 */
}

[data-theme="dark"] {
  --bg: #0e1116;
  --surface: #161b22;
  --surface-2: #1c2128;
  --line: #2b323b;
  --text: #e6edf3;
  --text-2: #9aa4b0;
  --text-3: #7b8493;   /* 对 --surface 5.0:1，满足 WCAG AA 正文要求 */
  --accent: #1f8fff;
  --accent-ink: #04121f;
  --ok: #2dd4bf;
  --warn: #ff9f4a;
  --danger: #ff6b6e;
  --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px rgba(0, 0, 0, .45);

  --cv-backdrop: #0b0e12;
  --cv-surface: #151a21;
  --cv-border: #39414c;
  --cv-grid: rgba(255, 255, 255, .08);
  --cv-grid-strong: rgba(255, 255, 255, .18);
  --cv-hover: #1f8fff;
  --mm-empty: 27, 32, 39;

  /* 图片图层装饰色（深色）：外框要够亮才能在深色底上勾出边界；
     占位底色改用中性灰蓝，避免深色下"泛蓝光"刺眼。 */
  --img-border: #4b5563;
  --img-accent: #1f8fff;
  --img-bg: rgba(255, 255, 255, .08);
  --img-label-fg: #9aa4b0;
  --img-err: #ff6b6e;
  --img-err-bg: rgba(255, 107, 110, .16);

  color-scheme: dark;
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}
button { font: inherit; cursor: pointer; }

#app { display: flex; flex-direction: column; height: 100vh; }

/* ── 顶栏 ─────────────────────────────────────────── */
.topbar {
  display: flex; align-items: center; gap: 20px;
  padding: 10px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  z-index: 30;
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 10px; }

/* LOGO：双图预置（logo-black.png / logo-white.png 各约 5KB，首屏一次性加载并解码）。
   主题切换只切 opacity —— 走合成器，零请求、零重解码、零滤镜运算。
   不要改回 content:url()：那会随主题替换 <img> 的内容源，每次切换都重新发请求
   并重新解码生成位图（连续切 N 次 = 2N 次加载/解码，解码产物驻留内存，
   正是"越切越卡"的直接来源）；也不要叠加 filter:invert()：那会强制生成独立
   合成层并做全像素滤镜运算，每次切换都要重算。
   两图堆叠 + opacity 过渡，视觉尺寸不变（34x34、1:1、.brand 的 gap:10px）；
   黑/白 LOGO 对各自底色的对比度约 21:1 / 17:1（WCAG 图形对象要求 3:1），两主题均清晰。 */
.logo {
  width: 34px;
  height: 34px;
  flex: none;
  display: block;
  object-fit: contain;   /* 兜底：即使源图比例异常也不拉伸 */
  aspect-ratio: 1 / 1;   /* 强制正方形 */
}
.logo-slot {
  position: relative;    /* 两张 logo 的绝对定位基准 */
  flex: none;
  width: 34px;
  height: 34px;
  display: block;
}
.logo-slot .logo {
  position: absolute; inset: 0;   /* 两图完全重叠，由 opacity 决定显隐 */
  /* 切换走合成器，成本极低 */
  transition: opacity .12s linear;
}
.logo-dark { opacity: 0; }
[data-theme="dark"] .logo-light { opacity: 0; }
[data-theme="dark"] .logo-dark { opacity: 1; }
/* 动效尊重系统"减少动态效果"设置 */
@media (prefers-reduced-motion: reduce) {
  .logo-slot .logo { transition: none; }
}

.brand-text { min-width: 0; }
.brand h1 { margin: 0; font-size: 15px; letter-spacing: -.2px; }
.brand p { margin: 0; font-size: 11px; color: var(--text-3); }

/* 主题切换按钮 */
.theme-btn {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 0 10px 0 8px; font-size: 12px; color: var(--text-2);
}
.theme-btn svg { flex: none; display: block; }
.theme-btn .ico-moon { display: none; }
[data-theme="dark"] .theme-btn .ico-sun { display: none; }
[data-theme="dark"] .theme-btn .ico-moon { display: block; }
/* 键盘可达性：清晰的焦点环 */
.theme-btn:focus-visible,
.ib:focus-visible,
.search input:focus-visible,
.fld input:focus-visible,
.fld textarea:focus-visible,
.m:focus-visible,
.r:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.stats { display: flex; gap: 4px; margin-left: 4px; }
.stat {
  display: flex; flex-direction: column; align-items: center;
  padding: 2px 12px; border-left: 1px solid var(--line);
}
.stat:first-child { border-left: 0; }
.stat b { font-size: 15px; font-variant-numeric: tabular-nums; letter-spacing: -.3px; }
.stat span { font-size: 10px; color: var(--text-3); }
.stat.price b { color: var(--danger); }

.tools { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.ib {
  min-width: 30px; height: 30px; padding: 0 8px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface); color: var(--text-2);
  font-size: 15px; line-height: 1;
  transition: .12s;
}
.ib:hover { background: var(--surface-2); color: var(--text); border-color: var(--text-3); }
.ib:active { transform: translateY(1px); }
.ib.on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.ib.wide { font-size: 12px; }

.search { position: relative; }
.search input {
  width: 250px; height: 30px; padding: 0 11px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface-2); color: var(--text); font: inherit; font-size: 12.5px;
  outline: none; transition: .12s;
}
.search input:focus { background: #fff; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(0,145,255,.12); }
.results {
  position: absolute; top: 34px; right: 0; width: 340px; max-height: 340px; overflow: auto;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: var(--shadow); padding: 4px; z-index: 40;
}
.results .r {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 9px; border-radius: 7px; cursor: pointer;
}
.results .r:hover { background: var(--surface-2); }
.results .r i { width: 12px; height: 12px; border-radius: 3px; flex: none; box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); }
.results .r .t { min-width: 0; }
.results .r .t b { display: block; font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.results .r .t span { font-size: 11px; color: var(--text-3); font-family: var(--mono); }
.results .empty { padding: 14px; text-align: center; color: var(--text-3); font-size: 12px; }

/* ── 画布区 ───────────────────────────────────────── */
.stage { position: relative; flex: 1; overflow: hidden; }
#cv { display: block; width: 100%; height: 100%; cursor: grab; touch-action: none; }
#cv.dragging { cursor: grabbing; }

.hover {
  position: absolute; z-index: 20; pointer-events: none;
  background: rgba(20,22,26,.93); color: #fff;
  padding: 6px 9px; border-radius: 7px; font-size: 11.5px; line-height: 1.45;
  box-shadow: 0 6px 20px rgba(0,0,0,.25); max-width: 240px;
}
.hover .c { font-family: var(--mono); opacity: .65; font-size: 10.5px; }
.hover .n { font-weight: 600; }
.hover .m { opacity: .85; }

.legend {
  position: absolute; left: 12px; bottom: 12px; z-index: 20;
  display: flex; align-items: center; gap: 14px;
  padding: 6px 11px; border-radius: 8px;
  background: var(--surface); opacity: .92; backdrop-filter: blur(8px);
  border: 1px solid var(--line); font-size: 11px; color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.legend span { display: flex; align-items: center; gap: 5px; }
.dot { width: 9px; height: 9px; border-radius: 2.5px; display: inline-block; }
.dot.free { background: var(--cv-surface); box-shadow: inset 0 0 0 1px var(--cv-border); }
.dot.mine { background: var(--accent); }

.minimap {
  position: absolute; right: 12px; bottom: 12px; z-index: 20;
  border: 1px solid var(--line); border-radius: 8px; overflow: hidden;
  background: var(--surface); box-shadow: var(--shadow); cursor: crosshair;
  line-height: 0;
}
.minimap canvas { width: 280px; height: 200px; image-rendering: pixelated; }
.mmvp {
  position: absolute; border: 1.5px solid var(--accent);
  background: rgba(0,145,255,.10); pointer-events: none; border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(255,255,255,.7) inset;
}

.loading {
  position: absolute; top: 12px; left: 50%; transform: translateX(-50%); z-index: 25;
  display: flex; align-items: center; gap: 7px;
  padding: 5px 12px; border-radius: 20px;
  background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow);
  font-size: 11.5px; color: var(--text-2);
}
.loading i {
  width: 11px; height: 11px; border-radius: 50%;
  border: 2px solid var(--line); border-top-color: var(--accent);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── 认领面板 ─────────────────────────────────────── */
.panel {
  position: absolute; top: 0; right: 0; bottom: 0; width: 348px; z-index: 50;
  background: var(--surface); border-left: 1px solid var(--line);
  box-shadow: -8px 0 28px rgba(20,22,26,.08);
  display: flex; flex-direction: column;
  animation: slide .2s cubic-bezier(.2,.7,.3,1);
}
@keyframes slide { from { transform: translateX(16px); opacity: 0; } }
.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px 16px; border-bottom: 1px solid var(--line);
}
.panel-head h2 { margin: 0; font-size: 14px; }
.panel-body { flex: 1; overflow: auto; padding: 16px; }

/* hidden 属性的 display:flex/block 会覆盖它，必须显式声明 none */
.panel[hidden], .hover[hidden], .results[hidden], .loading[hidden],
.cart[hidden], .modal[hidden], .cart-marks[hidden] { display: none !important; }

.coord {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; margin-bottom: 16px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 10px;
  font-family: var(--mono); font-size: 12.5px;
}
.coord .sw { width: 18px; height: 18px; border-radius: 5px; box-shadow: inset 0 0 0 1px rgba(0,0,0,.15); }
.coord .free { background: var(--cv-surface); box-shadow: inset 0 0 0 1px var(--cv-border); }

.fld { margin-bottom: 15px; }
.fld label {
  display: flex; align-items: baseline; justify-content: space-between;
  font-size: 12px; color: var(--text-2); margin-bottom: 6px;
}
.fld label em { font-style: normal; font-size: 11px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.fld input, .fld textarea {
  width: 100%; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface-2); color: var(--text); font: inherit; font-size: 13px;
  outline: none; resize: vertical; transition: .12s;
}
.fld input:focus, .fld textarea:focus { background: #fff; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(0,145,255,.12); }
.fld.over input, .fld.over textarea { border-color: var(--danger); }
.fld .hint { font-size: 11px; color: var(--danger); margin-top: 5px; display: none; }
.fld.over .hint { display: block; }

.swatches { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; }
.swatches button {
  aspect-ratio: 1; border-radius: 7px; border: 1.5px solid transparent;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); transition: .12s;
}
.swatches button:hover { transform: scale(1.08); }
.swatches button.on { border-color: var(--text); box-shadow: inset 0 0 0 1px rgba(0,0,0,.2), 0 0 0 2px #fff inset; }

.pay {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px; margin: 16px 0 10px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 10px;
}
.pay .amt { font-size: 22px; font-weight: 650; letter-spacing: -.6px; color: var(--danger); }
.pay .amt small { font-size: 12px; font-weight: 500; }
.pay .meta { text-align: right; font-size: 11px; color: var(--text-3); line-height: 1.5; }

.btn {
  width: 100%; height: 42px; border: 0; border-radius: 10px;
  background: var(--accent); color: var(--accent-ink);
  font-size: 14px; font-weight: 600; transition: .12s;
}
.btn:hover { filter: brightness(1.06); }
.btn:active { transform: translateY(1px); }
.btn:disabled { background: var(--line); color: var(--text-3); cursor: not-allowed; transform: none; }
.btn.ghost { background: var(--surface); color: var(--text-2); border: 1px solid var(--line); height: 36px; font-size: 13px; font-weight: 500; }

.msgbox {
  padding: 10px 12px; border-radius: 9px; font-size: 12.5px; line-height: 1.6;
  margin-bottom: 14px;
}
.msgbox.ok { background: rgba(18,165,148,.12); color: var(--ok); }
.msgbox.err { background: rgba(229,72,77,.12); color: var(--danger); }
[data-theme="dark"] .msgbox.ok { color: #5eead4; }
[data-theme="dark"] .msgbox.err { color: #ff9d9f; }
.msgbox.info { background: var(--surface-2); color: var(--text-2); border: 1px solid var(--line); }

.claimed { text-align: center; padding: 22px 8px; }
.claimed .big { font-size: 40px; margin-bottom: 10px; }
.claimed .nm { font-size: 15px; font-weight: 650; margin-bottom: 5px; }
.claimed .ms { font-size: 13px; color: var(--text-2); line-height: 1.6; word-break: break-word; }
.claimed .tm { font-size: 11px; color: var(--text-3); margin-top: 9px; font-family: var(--mono); }

.mini-list { display: flex; flex-direction: column; gap: 6px; }
.mini-list .m {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 9px;
  cursor: pointer; background: var(--surface-2); transition: .12s;
}
.mini-list .m:hover { background: var(--surface); border-color: var(--line); }
.mini-list .m i { width: 13px; height: 13px; border-radius: 4px; flex: none; box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); }
.mini-list .m .x { font-family: var(--mono); font-size: 11px; color: var(--text-3); }
.mini-list .m .y { margin-left: auto; font-size: 12px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 130px; }

.empty-state { text-align: center; padding: 40px 12px; color: var(--text-3); }
.empty-state .ic { font-size: 34px; margin-bottom: 10px; opacity: .5; }
.empty-state p { margin: 0; font-size: 12.5px; line-height: 1.7; }

@media (max-width: 860px) {
  .panel { width: 100%; }
  .search input { width: 150px; }
  .stats .stat:nth-child(2) { display: none; }
  .minimap { display: none; }
}

/* ============================================================
   购物车
   ============================================================ */
.cart-btn { position: relative; padding: 0 8px; display: inline-flex; align-items: center; }
.cart-count {
  position: absolute; top: -5px; right: -5px; min-width: 16px; height: 16px;
  padding: 0 4px; border-radius: 8px;
  background: var(--danger); color: #fff;
  font-size: 10px; font-weight: 600; line-height: 16px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.cart-badge {
  display: inline-block; min-width: 20px; padding: 0 6px;
  border-radius: 10px; background: var(--surface-2); border: 1px solid var(--line);
  font-size: 11px; font-weight: 600; color: var(--text-2); text-align: center;
}

.cart {
  position: absolute; top: 0; right: 0; bottom: 0; width: 380px; z-index: 55;
  background: var(--surface); border-left: 1px solid var(--line);
  box-shadow: -8px 0 28px rgba(20, 22, 26, .12);
  display: flex; flex-direction: column;
  animation: slide .2s cubic-bezier(.2, .7, .3, 1);
}
.cart-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 9px 16px; border-bottom: 1px solid var(--line);
  background: var(--surface-2); font-size: 12px;
}
.cart-tools-right { display: flex; gap: 12px; }
.linkbtn {
  border: 0; background: none; padding: 0;
  color: var(--text-3); font-size: 12px; text-decoration: underline;
}
.linkbtn:hover { color: var(--text); }
.linkbtn.danger:hover { color: var(--danger); }

.chk { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; }
.chk input { width: 14px; height: 14px; accent-color: var(--accent); cursor: pointer; margin: 0; }

.cart-body { flex: 1; overflow: auto; padding: 10px 12px; }
.cart-item {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 10px; margin-bottom: 8px;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface-2); transition: .12s;
}
.cart-item:hover { border-color: var(--text-3); }
.cart-item.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 7%, var(--surface-2)); }
.cart-item.invalid { opacity: .62; border-style: dashed; }
.cart-item.invalid .ci-name { text-decoration: line-through; }

.ci-check { margin-top: 2px; }
.ci-swatch {
  width: 30px; height: 30px; border-radius: 7px; flex: none;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .15);
}
.ci-main { flex: 1; min-width: 0; }
.ci-name { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ci-msg { font-size: 11.5px; color: var(--text-2); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ci-coord { font-family: var(--mono); font-size: 10.5px; color: var(--text-3); margin-top: 3px; }
.ci-right { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex: none; }
.ci-price { font-size: 13px; font-weight: 600; color: var(--danger); font-variant-numeric: tabular-nums; }
.ci-del {
  border: 0; background: none; padding: 2px; color: var(--text-3);
  font-size: 11px; text-decoration: underline;
}
.ci-del:hover { color: var(--danger); }
.ci-tag {
  padding: 1px 6px; border-radius: 4px; font-size: 10px;
  background: rgba(229, 72, 77, .12); color: var(--danger);
}
.ci-tag.lock { background: rgba(247, 107, 21, .14); color: var(--warn); }

.cart-foot { border-top: 1px solid var(--line); padding: 12px 16px; background: var(--surface-2); }
.cart-sum { display: flex; align-items: baseline; justify-content: space-between; font-size: 12.5px; color: var(--text-2); }
.cart-sum b { color: var(--text); font-variant-numeric: tabular-nums; }
.cart-total { font-size: 13px; }
.cart-total b { font-size: 19px; color: var(--danger); letter-spacing: -.5px; margin-left: 4px; }
.cart-quota { font-size: 11px; color: var(--text-3); margin: 5px 0 9px; }
.cart-foot .btn:disabled { background: var(--line); color: var(--text-3); cursor: not-allowed; }

.cart-empty { text-align: center; padding: 46px 16px; color: var(--text-3); }
.cart-empty .ic { font-size: 34px; margin-bottom: 10px; opacity: .5; }
.cart-empty p { margin: 0; font-size: 12.5px; line-height: 1.8; }

/* 画布上的"已加入购物车"标记 */
.cart-mark {
  position: absolute; z-index: 15; pointer-events: none;
  width: 26px; height: 26px; margin: -13px 0 0 -13px;
  border: 2px solid var(--warn); border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; color: var(--warn); font-weight: 700;
  background: color-mix(in srgb, var(--warn) 18%, transparent);
}
.cart-marks { position: absolute; inset: 0; z-index: 15; pointer-events: none; overflow: hidden; }

/* 验证码弹窗 */
.modal {
  position: fixed; inset: 0; z-index: 80;
  display: flex; align-items: center; justify-content: center;
  background: rgba(10, 12, 16, .55); backdrop-filter: blur(2px);
}
.modal-box {
  width: 320px; padding: 20px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: 0 20px 60px rgba(0, 0, 0, .3);
}
.modal-box h3 { margin: 0 0 5px; font-size: 15px; }
.modal-desc { margin: 0 0 14px; font-size: 12.5px; color: var(--text-2); }
.captcha-row { display: flex; align-items: center; gap: 10px; }
.captcha-q {
  flex: 1; padding: 8px 12px; border-radius: 8px;
  background: var(--surface-2); border: 1px solid var(--line);
  font-family: var(--mono); font-size: 15px; font-weight: 600; text-align: center;
  letter-spacing: 1px; user-select: none;
}
.captcha-row input {
  width: 82px; height: 36px; padding: 0 10px; text-align: center;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface-2); color: var(--text);
  font: inherit; font-size: 14px; outline: none;
}
.captcha-row input:focus { border-color: var(--accent); background: #fff; }
[data-theme="dark"] .captcha-row input:focus { background: var(--surface); }
.modal-msg { min-height: 18px; margin-top: 8px; font-size: 11.5px; color: var(--danger); }
.modal-actions { display: flex; gap: 8px; margin-top: 8px; }
.modal-actions .btn { flex: 1; height: 38px; font-size: 13px; }

@media (max-width: 860px) {
  .cart { width: 100%; }
}

/* ============================================================
   支付渠道选择器
   ============================================================ */
.pay-channels { display: flex; flex-wrap: wrap; gap: 7px; }
.pay-channels .pc {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 13px; border: 1.5px solid var(--line); border-radius: 9px;
  background: var(--surface-2); color: var(--text-2);
  font-size: 12.5px; transition: .12s;
  /* 触摸目标：桌面 38px，移动端媒体查询里升到 44px（见文件末尾） */
  min-height: 38px;
}
.pay-channels .pc:hover { border-color: var(--text-3); color: var(--text); }
.pay-channels .pc.on {
  border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface-2));
  font-weight: 600;
}
/* 键盘可达性：与 .ib / .search input 保持一致的焦点环 */
.pay-channels .pc:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pay-channels .hint { font-size: 12px; color: var(--text-3); }

/* ── 购物车结算区的支付方式 ─────────────────────────────
 * 抽屉宽度有限（移动端 100%），渠道按钮用 flex:1 均分，
 * 保证两个渠道并排铺满、不换行错位，也不横向溢出。
 */
.cart-pay { margin: 0 0 9px; }
.cart-pay-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  font-size: 11.5px; color: var(--text-3); margin-bottom: 6px;
}
.cart-pay-head em {
  font-style: normal; font-size: 11px; color: var(--text-3);
  padding: 1px 6px; border: 1px solid var(--line); border-radius: 5px;
}
.cart-pay .pay-channels .pc { flex: 1 1 0; justify-content: center; min-width: 0; }
.cart-pay .pay-channels .pc[data-ch="mock"] { flex: 0 1 auto; }
/* 渠道列表还在加载时的占位，避免结算按钮"突然长出"一排按钮造成布局跳动 */
.cart-pay .pay-loading { font-size: 12px; color: var(--text-3); padding: 8px 0; }

/* ── 支付进行中弹窗 ───────────────────────────────────── */
.pay-qr {
  margin: 12px 0; padding: 11px; border-radius: 10px;
  background: var(--surface-2); border: 1px solid var(--line);
  font-family: var(--mono); font-size: 11px; color: var(--text-2);
  word-break: break-all; line-height: 1.6; text-align: center;
}
.pay-timer {
  font-size: 11.5px; color: var(--text-3); text-align: center;
  font-variant-numeric: tabular-nums; margin-top: 4px;
}
.pay-timer b { color: var(--warn); font-variant-numeric: tabular-nums; }
.pay-timer.urgent b { color: var(--danger); }

/* ── 移动端适配 ────────────────────────────────────────
 * 触摸目标 ≥44px（iOS HIG / WCAG 2.5.5），渠道按钮横向均分不溢出。
 */
@media (max-width: 860px) {
  .pay-channels .pc { min-height: 44px; }
  .cart-pay .pay-channels .pc { padding: 10px 8px; font-size: 13px; }
  .pay-qr { font-size: 10.5px; padding: 9px; }
}

/* ── 页脚：ICP 备案号与数据码（工信部合规要求，页面底部必须展示）───────
 * 说明：#app 是 height:100vh 的纵向 flex 容器，.stage 撑满剩余空间，
 * 页脚作为普通流式块放在最后一行即可，不占画布高度。
 * 对比度：--text-3 对 --surface 为 4.6:1（浅色）/ 5.0:1（深色），
 * 满足 WCAG AA 正文要求。 */
.site-foot {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 14px 10px;
  background: var(--surface);
  border-top: 1px solid var(--line);
  color: var(--text-3);
  font-size: 12px;
  line-height: 1.4;
}
.site-foot .beian {
  color: var(--text-3);
  text-decoration: none;
  cursor: pointer;
  transition: color .12s linear;
  /* 32 位数据码在窄屏必须允许换行，否则会撑破布局 */
  overflow-wrap: anywhere;
}
.site-foot a.beian:hover { color: var(--accent); text-decoration: underline; }
.site-foot .beian:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
.site-foot .foot-sep { opacity: .55; }
.site-foot .foot-copy { opacity: .85; }

/* 画布区让出页脚高度 */
@media (max-width: 640px) {
  .site-foot { font-size: 11px; gap: 6px; padding: 7px 10px 9px; }
}

/* ============================================================
   图片图层（抽屉 UI）
   ------------------------------------------------------------
   与 .cart 同一套结构（绝对定位右侧抽屉），z-index 取 58：
   高于购物车(55)与认领面板(50)，低于支付弹窗(80)，
   这样"抽屉里发起支付 → 支付弹窗盖住抽屉"的层级关系是对的。

   配色一律走 CSS 变量，明暗双主题自动切换，无需另写 dark 规则。
   ============================================================ */
.img-btn { display: inline-flex; align-items: center; gap: 5px; }
.img-btn svg { flex: none; display: block; }

/* hidden 属性必须显式压过 display:flex/block，否则抽屉关不掉 */
.img-drawer[hidden], .img-pane[hidden] { display: none !important; }

.img-drawer {
  position: absolute; top: 0; right: 0; bottom: 0; width: 380px; z-index: 58;
  background: var(--surface); border-left: 1px solid var(--line);
  box-shadow: -8px 0 28px rgba(20, 22, 26, .12);
  display: flex; flex-direction: column;
  animation: slide .2s cubic-bezier(.2, .7, .3, 1);
}

.img-tabs {
  display: flex; gap: 6px; padding: 10px 16px 0;
  border-bottom: 1px solid var(--line); background: var(--surface-2);
}
.img-tab {
  flex: 1; height: 34px; border: 0; border-bottom: 2px solid transparent;
  background: none; color: var(--text-3);
  font-size: 13px; font-weight: 600; transition: .12s;
}
.img-tab:hover { color: var(--text); }
.img-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
.img-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.img-pane { flex: 1; overflow: auto; padding: 16px; }

/* ── 选图区 ── */
.img-drop {
  border: 1.5px dashed var(--line); border-radius: 12px;
  background: var(--surface-2); text-align: center; padding: 30px 16px;
  cursor: pointer; transition: .12s;
}
.img-drop:hover { border-color: var(--accent); }
.img-drop .ic { font-size: 34px; margin-bottom: 10px; opacity: .75; }
.img-drop .t { margin: 0 0 5px; font-size: 13.5px; font-weight: 600; }
.img-drop .s { margin: 0 0 14px; font-size: 11.5px; color: var(--text-3); line-height: 1.6; }
.img-drop .btn { height: 38px; }

/* ── 预览条 ── */
.img-preview {
  display: flex; align-items: center; gap: 10px;
  padding: 9px; margin-bottom: 16px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 10px;
}
.img-preview img {
  width: 52px; height: 52px; flex: none;
  border-radius: 7px; object-fit: cover; background: var(--bg);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
}
.img-preview-meta { flex: 1; min-width: 0; }
.img-preview-meta b {
  display: block; font-size: 12.5px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.img-preview-meta span { font-size: 11px; color: var(--text-3); font-family: var(--mono); }

/* ── 尺寸 / 坐标输入行 ── */
.img-size-row { display: flex; align-items: center; gap: 7px; }
.img-size-row input {
  flex: 1; min-width: 0; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface-2); color: var(--text); font: inherit; font-size: 13px;
  outline: none; transition: .12s;
}
.img-size-row input:focus { background: #fff; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(0,145,255,.12); }
[data-theme="dark"] .img-size-row input:focus { background: var(--surface); }
.img-size-row .x { color: var(--text-3); font-size: 13px; flex: none; }
.img-size-row .linkbtn { flex: none; white-space: nowrap; }

/* .fld > .hint 默认 display:none，这里改为常显（放置越界等状态提示） */
.img-size-row + .hint { display: block; font-size: 11px; color: var(--text-3); margin-top: 6px; }
#imgPosMsg { color: var(--text-3); }
#imgPosMsg.over { color: var(--danger); }

.img-quota { font-size: 11.5px; color: var(--text-3); margin: 0 0 12px; }

/* ── 上传进度 ── */
.img-progress { display: flex; align-items: center; gap: 9px; margin-bottom: 12px; }
.img-progress .bar {
  flex: 1; height: 6px; border-radius: 3px;
  background: var(--line); overflow: hidden;
}
.img-progress .bar i {
  display: block; height: 100%; width: 0;
  background: var(--accent); border-radius: 3px;
  transition: width .18s linear;
}
.img-progress span {
  font-size: 11px; color: var(--text-2); flex: none;
  font-variant-numeric: tabular-nums;
}

/* ── 我的图片 ── */
.img-mine-list { display: flex; flex-direction: column; gap: 8px; }
.img-mine-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--surface-2);
}
.mi-thumb {
  width: 42px; height: 42px; flex: none;
  border-radius: 7px; overflow: hidden;
  background: var(--bg); display: flex; align-items: center; justify-content: center;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
}
.mi-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mi-main { flex: 1; min-width: 0; }
.mi-coord {
  font-family: var(--mono); font-size: 11.5px; color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mi-size { font-size: 10.5px; color: var(--text-3); margin-top: 2px; }
.mi-right { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; flex: none; }
.mi-right .linkbtn { font-size: 11.5px; }
.mi-del[data-armed] { color: var(--danger); font-weight: 600; }

/* 画布点选锚点时给个十字光标，明确"现在点哪儿" */
canvas.img-picking { cursor: crosshair; }

/* ── 移动端：抽屉全宽 + 触摸目标 ≥44px ──
   iOS HIG / WCAG 2.5.5 要求触摸目标不小于 44px。
   这里同时保证"顶栏文字标签隐藏、只留图标"，避免窄屏顶栏被挤爆换行。 */
@media (max-width: 860px) {
  .img-drawer { width: 100%; }
  .img-drop { padding: 26px 14px; }
  .img-drop .btn { height: 44px; }
  .img-size-row input { min-height: 44px; }
  .img-size-row .linkbtn {
    min-height: 44px; display: inline-flex; align-items: center;
    padding: 0 10px; flex: none;
  }
  .img-tab { height: 44px; }
  .img-mine-item .linkbtn { min-height: 44px; display: inline-flex; align-items: center; }
  /* 数字输入框在 iOS 聚焦会缩放页面：字号必须 ≥16px */
  .img-size-row input { font-size: 16px; }
  .img-preview img { width: 46px; height: 46px; }
}
@media (max-width: 520px) {
  .img-btn-label { display: none; }
  .img-btn { padding: 0 9px; }
}

/* ── 图片图层：上传 UI ─────────────────────────────────────────────
 * 双主题走 CSS 变量，触摸目标 ≥44px 满足移动端可用性。 */
.img-add-btn { font-size: 17px; line-height: 1; }

.img-box { max-width: 520px; width: min(92vw, 520px); }
.img-step {
  font-size: 13px; color: var(--text-2); margin: 8px 0 4px;
  padding: 6px 10px; border-radius: 6px; background: var(--surface-2);
}
.img-quota { font-size: 12.5px; color: var(--text-3); margin-bottom: 10px; }
.img-file-label {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 18px; cursor: pointer;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface-2); color: var(--text);
  font-size: 14px; transition: border-color .12s linear;
}
.img-file-label:hover { border-color: var(--accent); }
/* 原生 file input 隐藏但保留可访问性（label 已可点） */
.img-file {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.img-file:focus-visible + .img-preview,
.img-file:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.img-file-label:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }

.img-preview {
  margin-top: 12px; min-height: 60px;
  display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--line); border-radius: 8px; background: var(--surface-2);
  overflow: hidden;
}
.img-preview:empty { display: none; }
.img-preview img {
  max-width: 100%; max-height: 190px; display: block;
  image-rendering: auto;
}
.img-info { margin-top: 8px; font-size: 12.5px; color: var(--text-2); overflow-wrap: anywhere; }
.img-hint { margin: 10px 0 0; font-size: 12px; color: var(--text-3); line-height: 1.6; }

@media (max-width: 640px) {
  .img-box { max-width: 100%; }
  .img-preview img { max-height: 140px; }
}

/* ── 分享功能 ───────────────────────────────────────────────────
 * 沿用既有 .ib / .modal / .modal-box 与 CSS 变量，明暗主题自动跟随，
 * 不新增任何硬编码颜色。触摸目标 ≥44px，移动端 chip 排成两行不挤压。 */
.share-btn { display: inline-flex; align-items: center; gap: 5px; }
.share-label { font-size: 12px; }

.share-box { width: 340px; max-width: calc(100vw - 32px); }

/* 渠道按钮：4 列网格，桌面端一行，移动端两行 */
.sh-chips {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin: 12px 0 16px;
}
.sh-chip {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px;
  /* 触摸目标下限 44px */
  min-height: 64px;
  padding: 8px 4px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition: border-color .12s linear, background .12s linear, transform .08s ease;
}
.sh-chip:hover { border-color: var(--text-3); }
.sh-chip:active { transform: translateY(1px); }
.sh-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sh-chip.is-limited { opacity: .55; }
.sh-chip-label { font-size: 12px; line-height: 1.2; text-align: center; }

/* 复制链接行 */
.sh-url-label {
  display: block; margin-bottom: 6px;
  font-size: 12px; color: var(--text-2);
}
.sh-url-row { display: flex; gap: 8px; }
.sh-url {
  flex: 1; min-width: 0;
  height: 36px; padding: 0 10px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--surface-2); color: var(--text-2);
  font-family: var(--mono); font-size: 12px;
}
.sh-url:focus-visible { outline: 2px solid var(--accent); outline-offset: -1px; }
.sh-copy-btn { flex: none; height: 36px; }

/* 说明文案：可长可短，用弱化色，不抢注意力 */
.sh-note {
  margin: 10px 0 0;
  font-size: 11.5px; line-height: 1.65;
  color: var(--text-3);
}

@media (max-width: 640px) {
  .share-box { width: 100%; padding: 18px 16px; }
  /* 移动端：分享入口只留图标，标签隐藏，给画布让出宽度 */
  .share-label { display: none; }
  .share-btn { padding: 0 10px; }
  .sh-chips { grid-template-columns: repeat(3, 1fr); gap: 10px; }
  .sh-chip { min-height: 72px; }
  .sh-chip-label { font-size: 12.5px; }
}

@media (max-width: 380px) {
  .sh-chips { grid-template-columns: repeat(2, 1fr); }
}

/* 无障碍：尊重系统的减少动效设置 */
@media (prefers-reduced-motion: reduce) {
  .sh-chip { transition: none; }
  .sh-chip:active { transform: none; }
}

/* ════════════════════════════════════════════════════════════════════
   移动端适配层（2026-10-18）
   ────────────────────────────────────────────────────────────────────
   设计原则：**追加，不改写**。上面所有既有规则与视觉风格保持原样，
   这里只在断点内做覆盖，改动最小化、回滚只需删掉本段。

   断点体系（按设备实际宽度划分，非等比缩放）：
     ≤ 860px  平板竖屏 / 小笔记本 —— 沿用既有规则（抽屉转全宽等）
     ≤ 640px  大多数手机（375/390/412/430）
     ≤ 520px  窄屏手机（360/393）与小屏（414 横屏余量）
     ≤ 380px  小屏设备（320/344/360）
     ≥ 861px  桌面 —— 完全沿用原样，不做任何降级

   覆盖的四类问题：
     1) 输入框 <16px 在 iOS Safari 聚焦时自动放大页面
     2) 顶栏工具区在窄屏换行后仍横向溢出
     3) hover 效果在触屏上「粘住」不消失
     4) 刘海屏 / 手势条遮挡 + 100vh 在移动浏览器失真
   ════════════════════════════════════════════════════════════════════ */

/* ── 全局：消除横向溢出 ─────────────────────────────────────────
 * 移动端最常见的「整页可左右滑动」多半来自某个子元素比视口宽。
 * 这里给 html/body 加 clip 而不是 hidden：hidden 会让部分浏览器
 * 把 overflow 传播到滚动容器，导致 position:sticky 失效。 */
html, body {
  max-width: 100%;
  overflow-x: clip;
  /* 移动端浏览器地址栏收缩会导致 100vh 抖动，用 dvh 更稳 */
  min-height: 100dvh;
}

/* 所有表单控件统一 16px：小于 16px 时 iOS Safari 聚焦会强制放大页面，
   放大后用户找不到「完成」按钮，页面看起来像坏了。
   只在触屏宽度下改字号，桌面端视觉不变。 */
@media (max-width: 860px) {
  input, textarea, select, button {
    /* 防止聚焦缩放：iOS 对 <16px 的输入框必缩，16px 是唯一可靠阈值 */
    font-size: 16px !important;
  }
  /* 但视觉上仍要保持原有的紧凑感：只对非输入控件放开行高 */
  input[type="checkbox"], input[type="radio"] {
    font-size: initial !important;
  }
}

/* ── ≤ 640px：主流手机 ──────────────────────────────────────────── */
@media (max-width: 640px) {
  .topbar {
    /* 顶栏是移动端最容易溢出的地方：gap 过大 + 多个按钮横排 */
    gap: 10px;
    padding: 8px 10px;
    /* 允许换行，但让工具区独占一行，避免挤在品牌名旁边 */
    row-gap: 8px;
  }
  .brand-text h1 { font-size: 15px; }
  .brand-text p { font-size: 11px; }

  /* 统计条：4 个格子在 375px 下每个只剩 ~80px，「已认领/待认领/我的」放不下。
     横向滚动比硬挤更合理：保留全部信息，用手势扫。 */
  .stats {
    order: 3;
    width: 100%;
    flex: 1 1 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 14px;
    padding-bottom: 2px;
  }
  .stats::-webkit-scrollbar { display: none; }
  .stats .stat { flex: 0 0 auto; }
  /* 取消 860px 下隐藏第二条的规则，手机上全部显示 */
  .stats .stat:nth-child(2) { display: flex; }

  /* 工具区独占一行，按钮可换行且不溢出 */
  .tools {
    order: 2;
    width: 100%;
    flex-wrap: wrap;
    gap: 6px;
  }
  /* 触摸目标下限 44px（WCAG 2.5.5 / Apple HIG） */
  .ib {
    min-width: 44px;
    height: 44px;
    padding: 0 10px;
  }
  .ib.wide { font-size: 12.5px; padding: 0 12px; }
  /* 拖动阶段禁用 hover 态：触屏上 :hover 会在抬手后保持高亮 */
  .ib:hover { background: var(--surface); color: var(--text-2); border-color: var(--line); }
  .ib:active { background: var(--surface-2); transform: scale(.96); }

  /* 搜索框：不再固定 250px 宽，用弹性占满剩余空间 */
  .search { flex: 1 1 100%; }
  .search input {
    width: 100%;
    min-width: 0;
    height: 40px;
  }
  /* 结果下拉：手机上是全屏宽，不再是 340px 的浮层，避免溢出屏幕 */
  .results {
    position: static;
    width: 100%;
    max-height: 46vh;
    margin-top: 6px;
    box-shadow: none;
    border: 1px solid var(--line);
    border-radius: 8px;
  }

  /* 坐标悬浮提示：手机上容易糊住画布，缩小并降低透明度 */
  .coord { max-width: 150px; font-size: 11px; }

  /* 抽屉类（.panel/.cart/.img-drawer）：860px 已转 100%，
     这里补齐底部安全区，避免被手势条压住 */
  .panel, .cart, .img-drawer {
    padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
  }

  /* 弹窗：手机上顶到边缘更省空间，但保留圆角不显突兀 */
  .modal-box { width: calc(100vw - 24px); }
  .share-box { padding: 16px 14px; }

  /* 页脚：手机端单列居中，避免三段文字挤在一行 */
  .site-foot {
    padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
    font-size: 11px;
    line-height: 1.7;
  }
}

/* ── ≤ 520px：窄屏 ──────────────────────────────────────────────── */
@media (max-width: 520px) {
  .topbar { gap: 8px; padding: 8px; }
  .tools { gap: 5px; }
  .brand-text p { display: none; }   /* 让位给按钮，省一行高度 */
  .img-btn-label { display: none; }
  .img-btn { padding: 0 9px; }
  .theme-label { display: none; }
  .theme-btn { padding: 0 11px; }
  .share-label { display: none; }
  .share-btn { padding: 0 11px; }

  /* 画布小地图在手机上太占地方，860px 已隐藏，这里确认一次 */
  .minimap { display: none; }

  /* 底部浮动控件（小地图框/坐标/工具）上移，避开安全区 */
  .mm-box, .coord { bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
}

/* ── ≤ 380px：小屏（iPhone SE / 老安卓）────────────────────────────
 * 320px 是当前主流里最窄的宽度，几像素的差别就会导致换行。 */
@media (max-width: 380px) {
  .topbar { padding: 6px; gap: 6px; row-gap: 6px; }
  .tools { gap: 4px; }
  .ib { min-width: 42px; height: 42px; padding: 0 8px; }
  .ib.wide { font-size: 12px; padding: 0 10px; }
  .brand-text h1 { font-size: 14px; }
  .logo { width: 28px; height: 28px; }

  .search input { height: 38px; }

  /* 分享渠道在 320px 下两列即可，避免每格过窄导致标签换行 */
  .sh-chips { grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .sh-chip { min-height: 66px; }
  .sh-chip-label { font-size: 11.5px; }

  .modal-box { width: calc(100vw - 16px); padding: 14px; }
  .img-preview img { max-height: 110px; }
}

/* ── 触屏：去掉 hover 依赖，改用 active 反馈 ──────────────────────
 * 触屏设备上 :hover 会在点击后保持选中态，视觉上像「卡住」。
 * 用 @media (hover: none) 精确命中「无悬停能力」的设备（触屏），
 * 在这些设备上把 hover 效果抵消掉，只保留 :active 的按压反馈。
 * 有鼠标的设备（hover: hover）不受影响，桌面端视觉完全不变。 */
@media (hover: none) {
  .ib:hover,
  .btn:hover,
  .linkbtn:hover,
  .sh-chip:hover,
  .img-file-label:hover {
    background: var(--surface);
    color: var(--text-2);
    border-color: var(--line);
  }
  .pay-channels .pc:hover { border-color: var(--line); color: var(--text-2); }
  /* 触摸设备的按压反馈 */
  .ib:active, .btn:active, .sh-chip:active, .pay-channels .pc:active {
    opacity: .75;
  }
}

/* ── 安全区域（刘海屏 / 手势条）───────────────────────────────────
 * env() 在不支持的浏览器上整条声明失效，等于不生效，不会出错。 */
@supports (padding: max(0px)) {
  .topbar {
    padding-top: calc(8px + env(safe-area-inset-top, 0px));
  }
  .site-foot {
    padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  }
}

/* ── 横屏手机：高度极矮，隐藏次要元素腾出画布高度 ──────────────────
 * iPhone 横屏可视高度只有 ~375px，顶栏若换行会吃掉近半屏。 */
@media (max-width: 900px) and (orientation: landscape) {
  .stats { display: none; }
  .topbar { padding-top: 5px; padding-bottom: 5px; }
  .brand-text p { display: none; }
  .results { max-height: 60vh; }
}

/* ── 平板：两栏布局，抽屉不再全宽 ────────────────────────────────
 * 861~1180px 区间（如 iPad 横屏 1024px）抽屉仍 348/380px，
 * 会盖掉近一半画布。改成固定比例 + 更宽上限更合理。 */
@media (min-width: 861px) and (max-width: 1180px) {
  .panel { width: 320px; }
  .cart { width: 340px; }
  .img-drawer { width: 340px; }
  /* 小地图在中等宽度下与右侧抽屉会重叠，移到左下并缩小 */
  .minimap { transform: scale(.85); transform-origin: left bottom; }
}

/* ── 图片：按屏幕尺寸自适应 ──────────────────────────────────────
 * logo 走 max-width 而非固定 width：小屏缩小、大屏不变形。
 * srcset 在此收益有限（两张图都只有 ~5KB，请求开销大于收益），
 * 真正的高 DPR 适配已在 canvas 层完成（state.dpr 上限 2）。 */
@media (max-width: 380px) {
  .logo { width: 28px; height: 28px; }
  .logo-slot { width: 28px; height: 28px; }
}

/* ── 减少重排：固定尺寸的元素避免运行时因内容变化而重排 ────────── */
@media (max-width: 860px) {
  /* topbar 高度由内容决定，滚动时高度变化会触发整页重排。
     固定最小高度让滚动更稳（内容超出时仍会自然撑高）。 */
  .topbar { min-height: 52px; }
  /* 避免数字跳动引起的重排：等宽数字 */
  .stat b { font-variant-numeric: tabular-nums; }
}

/* ── 触摸体验细节（第二轮补充）──────────────────────────────────── */

/* 去掉移动浏览器点击时的灰色高亮块。
 * 默认的 -webkit-tap-highlight-color 是一块半透明灰，
 * 在密集按钮上会显得脏且与主题不搭。这里统一关掉，
 * 按压反馈改由 :active 的 scale/opacity 提供。 */
a, button, input, textarea, select, .ib, .btn, .linkbtn, .sh-chip, .pay-channels .pc {
  -webkit-tap-highlight-color: transparent;
}

/* 抑制页面级橡皮筋：画布内部已有自己的手势处理，
 * 若外层还能回弹，会与拖动画布的手势打架。 */
@media (max-width: 860px) {
  body {
    overscroll-behavior: none;
    /* 禁止长按选中/弹出菜单，避免拖动画布时误触「全选」 */
    -webkit-user-select: none;
    user-select: none;
  }
  /* 输入框必须可以选中文本，否则复制粘贴失效 */
  input, textarea {
    -webkit-user-select: text;
    user-select: text;
  }
}

/* 按钮点击区：视觉尺寸不变，但扩大可点击范围。
 * 用伪元素扩大热区而不改 padding，视觉零变化，是更「改动最小」的做法。 */
@media (hover: none) {
  .tools .ib::after {
    content: '';
    position: absolute;
    inset: -4px;   /* 四周各扩 4px，44px 按钮实际热区达 52px */
    border-radius: 10px;
  }
  .tools .ib { position: relative; }
}

/* 数字用等宽字形：统计数字每次刷新（如「1,399,999」）宽度变化会导致重排 */
.stat b, .zoom-label, .coord { font-variant-numeric: tabular-nums; }

/* 小屏设备上减少阴影层级，降低 GPU 合成压力 */
@media (max-width: 640px) {
  .results, .modal-box { box-shadow: 0 6px 24px rgba(0, 0, 0, .18); }
  .modal { backdrop-filter: none; }   /* 移动端 GPU 合成开销明显，直接关掉 */
}
