/* ============================================================
 * front.bundle.css —— 由 .workbuddy/build_front_css.py 自动生成，请勿手改
 *
 * 内容 = 前台 7 个本地 CSS 按 front_css_links() 的顺序拼接。
 * 重新生成：python .workbuddy/build_front_css.py --write
 *
 * 为什么不含 FontAwesome：它从不改动、带 1 年 immutable 缓存，
 * 合并进来会让「改一个本地 CSS」触发整包重下。详见脚本头部说明。
 * ============================================================ */

/* ---- assets/css/design-token.css ---- */
/**
 * 统一设计令牌（Design Tokens）—— 主题「晨曦 Aurora」
 *
 * @description 全站唯一的视觉源头：配色 / 圆角 / 阴影 / 字体 / 尺寸。
 *              改这里就能整体换肤；组件样式只准引用变量，不准写死颜色。
 *
 * 品牌色：青碧（Teal-Cyan）—— 主色 #0F9488，强调渐变 #14B8A6 → #0EA5E9
 * 点缀色：琥珀 #F59E0B —— 用于价格、促销等需要抓眼的位置
 *
 * 同时保留一套旧变量名（--bg-primary / --accent 等）以兼容历史代码。
 */

:root {
  /* 让浏览器原生控件（数字输入框的上下箭头、滚动条、日期选择器、下拉框）
     跟随当前主题配色。不设的话暗色模式下这些控件仍是亮色的，格外刺眼。
     注意这里是「跟随站点主题」而不是 system：主题由 data-theme 手动切换，
     下面深色块里会覆盖成 dark。 */
  color-scheme: light;

  /* ==================== 字体 ==================== */
  --font-sans: -apple-system, BlinkMacSystemFont, "PingFang SC", "HarmonyOS Sans SC",
               "Microsoft YaHei", "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  /* ==================== 表面（Surface） ==================== */
  --bg:        #F5F7F8;   /* 页面底色 */
  --bg-soft:   #EDF1F2;   /* 交替区块 / 悬浮态 */
  --card:      #FFFFFF;   /* 卡片 */
  --card-soft: #F8FAFA;   /* 卡片内嵌区 */

  /* ==================== 文字 ==================== */
  --text:      #12201E;   /* 主文字 */
  --text-2:    #5B6B68;   /* 次级文字 */
  --text-3:    #95A5A2;   /* 辅助 / 占位 */
  --text-inv:  #FFFFFF;   /* 反色文字（主色底上） */

  /* ==================== 品牌 ==================== */
  --primary:        #0F9488;
  --primary-hover:  #0B7369;
  --primary-soft:   #E4F5F2;
  --primary-ring:   rgba(15, 148, 136, .16);
  --primary-shadow: rgba(15, 148, 136, .28);

  --brand-400: #2DD4BF;
  --brand-500: #14B8A6;
  --brand-600: #0F9488;

  /* ==================== 功能色 ==================== */
  --success: #16A34A;
  --warning: #D97706;
  --danger:  #DC2626;
  --info:    #0EA5E9;
  --accent:  #F59E0B;   /* 点缀：价格 / 促销 */

  --success-soft: rgba(22, 163, 74, .12);
  --warning-soft: rgba(217, 119, 6, .12);
  --danger-soft:  rgba(220, 38, 38, .10);
  --info-soft:    rgba(14, 165, 233, .12);
  /* 语义边框：表单校验 / 提示条 / 状态卡描边 */
  --success-border: rgba(22, 163, 74, .34);
  --danger-border:  rgba(220, 38, 38, .30);
  --warning-border: rgba(217, 119, 6, .34);
  --info-border:    rgba(14, 165, 233, .30);

  /* ==================== 描边 ==================== */
  --border:       #E3E9E8;
  --border-hover: #CBD5D3;

  /* ==================== 圆角 ==================== */
  --radius:      18px;
  --radius-md:   14px;
  --radius-sm:   12px;
  --radius-xs:   8px;
  --radius-pill: 999px;

  /* ==================== 阴影（分层） ==================== */
  --shadow-xs: 0 1px 2px rgba(16, 32, 30, .04);
  --shadow-sm: 0 1px 2px rgba(16, 32, 30, .04), 0 1px 4px rgba(16, 32, 30, .04);
  --shadow:    0 1px 2px rgba(16, 32, 30, .04), 0 6px 18px rgba(16, 32, 30, .06);
  --shadow-hover: 0 10px 30px rgba(16, 32, 30, .12);
  --shadow-lg: 0 20px 52px rgba(16, 32, 30, .14);
  --shadow-brand: 0 8px 22px rgba(15, 148, 136, .26);

  /* ==================== 渐变 ==================== */
  --grad-brand: linear-gradient(135deg, #14B8A6 0%, #0EA5E9 100%);
  --grad-soft:  linear-gradient(160deg, #E4F5F2 0%, #EDF1F2 100%);
  --grad-warm:  linear-gradient(135deg, #F59E0B 0%, #EF4444 100%);

  /* ==================== 第三方品牌色 ==================== */
  /* 支付宝蓝、微信绿等属「品牌识别色」，不应随主题变，但要有名字可引用 */
  --alipay:        #1677FF;
  --alipay-hover:  #0958D9;
  --alipay-ring:   rgba(22, 119, 255, .28);
  --alipay-ring-2: rgba(22, 119, 255, .34);
  --wechat:        #22C55E;

  /* ==================== 语义扩展（组件一律引用这些，禁止写死） ==================== */
  --text-onbrand:  #FFFFFF;                 /* 品牌色 / 实色底上的文字 */
  --fill-white:    #FFFFFF;                 /* 纯白填充（如按钮高光） */
  --bg-sunken:     var(--bg);               /* 内凹区域（金额框、确认框） */
  --scrim:         rgba(16, 32, 30, .42);   /* 遮罩：弹窗 / 抽屉 */
  --scrim-strong:  rgba(16, 32, 30, .66);   /* 遮罩：强调层 */
  /* 随机背景图蒙层：拆成 rgb 三元组 + 独立 alpha，alpha 由后台「背景蒙版浓度」注入
     （templates/partials/head.php 把它写成 --bg-scrim-a）。
     拆开的原因：以前写死 rgba(...,.88) 时底图被盖得几乎看不见，等于没设背景。 */
  --bg-scrim-rgb:  245, 247, 248;           /* 浅色下的提亮蒙层色 */
  --bg-scrim-a:    .55;                     /* 默认浓度，可被后台配置覆盖 */
  --glass:         rgba(255, 255, 255, .06);/* 深色面板上的玻璃层 */
  --hairline:      rgba(16, 32, 30, .08);   /* 极细分隔线 */

  --grad-success-soft: linear-gradient(135deg, rgba(22, 163, 74, .18), rgba(22, 163, 74, .04));
  --grad-warning-soft: linear-gradient(135deg, rgba(217, 119, 6, .18), rgba(217, 119, 6, .04));
  --grad-alipay: linear-gradient(135deg, var(--alipay) 0%, var(--alipay-hover) 100%);

  /* ==================== 尺寸 / 节奏 ==================== */
  --nav-h: 64px;
  --container-max: 1200px;   /* 留白更足，观感更开阔 */
  --section-y: 72px;         /* 区块间距拉开，页面更有呼吸感 */
  --gutter: 24px;            /* 统一左右留白 */

  /* ==================== 动效 ==================== */
  --ease: cubic-bezier(.22, .61, .36, 1);
  --dur: .22s;
  --dur-fast: .14s;
  --dur-slow: .34s;

  /* ==================== 层级（z-index） ====================
   * 为什么要有这一层：
   *   以前全站散着 1 / 90 / 95 / 98 / 100 / 200 / 900 / 999 / 1000 / 1200 / 2000 / 3000
   *   十二种值，互相之间没有章法。新组件要盖住老组件，唯一的办法就是「猜一个更大的数」
   *   —— 于是数值一路膨胀到 3000，而「分享弹窗被底部 TabBar 挡住」这类问题照样反复出现。
   *
   *   更麻烦的是层叠上下文：给 body 的直接子元素加 z-index 会让它自成一个层叠上下文，
   *   里面的弹窗再高的 z-index 也只在「这一层」里有效，出不去（见 base.css 的说明）。
   *
   * 用法：**只准引用变量，不准写死数字**。要新增一层，先在这里定名字，
   * 而不是在某个组件里随手写 9999。
   */
  --z-behind:  -1;   /* 装饰层：页面背景图，压在所有内容之下 */
  --z-base:     1;   /* 内容抬高（如 hero 文字盖在背景图上） */
  --z-sticky:  90;   /* 页面内吸底条：商品详情页操作条、后台顶栏 */
  --z-fab:     95;   /* 悬浮操作按钮（FAB） */
  --z-tabbar:  98;   /* 移动端底部 TabBar */
  --z-nav:    100;   /* 顶部导航栏 */
  --z-dropdown: 200; /* 下拉菜单 */
  --z-overlay: 400;  /* 遮罩（弹窗/抽屉背后的暗层） */
  --z-drawer: 450;   /* 抽屉 / 侧栏（在遮罩之上） */
  --z-modal:  500;   /* 弹窗本体 */
  --z-popover: 600;  /* 气泡 / 提示层 */
  --z-toast:  700;   /* 全局吐司提示：永远在最上层 */

  /* ==================== 焦点环 ==================== */
  --focus-ring:        var(--primary);
  --focus-ring-width:  2px;
  --focus-ring-offset: 2px;

  /* ==================== 间距节奏 ====================
   * 统一用这套刻度，不要再随手写 13px / 17px 之类的散值 ——
   * 间距一散，页面看着就「不齐」，而这种不齐很难一眼看出原因。
   */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-8: 32px;
  --sp-10: 40px;
  --sp-12: 48px;

  /* ==================== 响应式断点（约定值） ====================
   * ⚠️ CSS 的 @media 不支持 var()，所以这里只是**约定**，靠人工遵守。
   *    全站统一用这四个值，不要再引入 780 / 820 / 900 这种散断点 ——
   *    断点一散，同一屏幕宽度下各组件的布局会在不同时刻跳变，观感是「散架」的。
   *
   *   --bp-sm  640px  手机横屏 / 小平板
   *   --bp-md  768px  平板竖屏（主流断点）
   *   --bp-lg 1024px  小桌面 / 平板横屏
   *   --bp-xl 1280px  常规桌面
   */
  --bp-sm: 640px;
  --bp-md: 768px;
  --bp-lg: 1024px;
  --bp-xl: 1280px;

  /* ==================== 旧变量名（兼容历史代码） ==================== */
  --bg-primary:   var(--bg);
  --bg-secondary: var(--bg-soft);
  --bg-card:      var(--card);
  --text-primary: var(--text);
  --text-secondary: var(--text-2);
  --accent-hover: var(--primary-hover);
  --pay-box-bg:   var(--primary-soft);
  --pay-box-hover: rgba(15, 148, 136, .08);
}

/* ==================== 深色主题 ==================== */
[data-theme="dark"] {
  /* 与 :root 的 color-scheme 成对：切到深色主题时原生控件一并变深 */
  color-scheme: dark;

  --bg:        #0C1114;
  --bg-soft:   #131A1E;
  --card:      #161E23;
  --card-soft: #1B242A;

  --text:      #E6EDF0;
  --text-2:    #9AAAB3;
  --text-3:    #6B7C86;
  --text-inv:  #06231F;

  --primary:        #2DD4BF;
  --primary-hover:  #5EEAD4;
  --primary-soft:   rgba(45, 212, 191, .14);
  --primary-ring:   rgba(45, 212, 191, .22);
  --primary-shadow: rgba(45, 212, 191, .30);

  --brand-400: #5EEAD4;
  --brand-500: #2DD4BF;
  --brand-600: #14B8A6;

  --success: #4ADE80;
  --warning: #FBBF24;
  --danger:  #F87171;
  --info:    #38BDF8;
  --accent:  #FBBF24;

  --success-soft: rgba(74, 222, 128, .14);
  --warning-soft: rgba(251, 191, 36, .14);
  --danger-soft:  rgba(248, 113, 113, .14);
  --info-soft:    rgba(56, 189, 248, .14);

  --success-border: rgba(74, 222, 128, .38);
  --danger-border:  rgba(248, 113, 113, .34);
  --warning-border: rgba(251, 191, 36, .38);
  --info-border:    rgba(56, 189, 248, .34);

  --border:       rgba(255, 255, 255, .10);
  --border-hover: rgba(255, 255, 255, .20);

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, .30);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, .34);
  --shadow:    0 2px 6px rgba(0, 0, 0, .34), 0 10px 26px rgba(0, 0, 0, .26);
  --shadow-hover: 0 14px 38px rgba(0, 0, 0, .44);
  --shadow-lg: 0 24px 60px rgba(0, 0, 0, .52);
  --shadow-brand: 0 8px 24px rgba(45, 212, 191, .26);

  --grad-brand: linear-gradient(135deg, #2DD4BF 0%, #38BDF8 100%);
  --grad-soft:  linear-gradient(160deg, rgba(45, 212, 191, .10) 0%, #131A1E 100%);

  /* 深色下的语义覆盖 */
  --grad-success-soft: linear-gradient(135deg, rgba(74, 222, 128, .20), rgba(74, 222, 128, .05));
  --grad-warning-soft: linear-gradient(135deg, rgba(251, 191, 36, .20), rgba(251, 191, 36, .05));
  --scrim:        rgba(0, 0, 0, .62);
  --scrim-strong: rgba(0, 0, 0, .78);
  --bg-scrim-rgb:  12, 17, 20;             /* 深色下的压暗蒙层色 */
  --bg-scrim-a:    .72;
  --hairline:     rgba(255, 255, 255, .08);
  --glass:        rgba(255, 255, 255, .04);

  /* 暗色下主色/功能色（青、绿、蓝）都变成亮色，白字对比度不足，
     叠在这些亮底上的文字改用深青黑（与 --text-inv 暗色值一致） */
  --text-onbrand: #06231F;
  /* 暖色点缀在暗色下收一点，避免亮橙红在深背景上刺眼；配白字对比度也更好 */
  --grad-warm: linear-gradient(135deg, #B45309 0%, #B91C1C 100%);
}

/* ---- assets/css/base.css ---- */
/**
 * 基础样式重置 —— 主题「晨曦 Aurora」
 *
 * @description 全站基础层：重置、排版、容器、按钮、表单、卡片、工具类
 *              所有颜色 / 圆角 / 阴影一律取自 design-token.css
 */

* { margin: 0; padding: 0; box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* 锚点跳转时给固定导航栏让位。少了这一句，点目录/页内锚点跳过去，
     目标标题正好被顶栏压在底下 —— 表现为「跳过去了但看不见」。 */
  scroll-padding-top: calc(var(--nav-h) + 16px);
}

body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
  line-height: 1.65;
  font-size: 15px;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* 顶部一道极淡的品牌光晕，让浅色页面不至于太"平" */
body::before {
  content: '';
  position: fixed;
  inset: 0 0 auto 0;
  height: 320px;
  background: radial-gradient(120% 100% at 50% 0%, var(--primary-soft) 0%, transparent 68%);
  pointer-events: none;
  /* -1：压在所有内容之下。原来是 0，靠下面 body > * 的 z-index:1 才不盖住正文；
     现在下面那条不再给 z-index，这里必须改成 -1，否则会盖在内容之上。 */
  z-index: var(--z-behind);
}

/* ⚠️ 这里**不能**给 z-index。
   一旦 body 的直接子元素（<main> / <footer> / .tabbar …）带上 z-index，
   它自己就成了独立的层叠上下文：里面 z-index:1200 的弹窗会被「困」在这一层，
   对外只按父级的 1 参与比较 —— 结果底部 TabBar（98）反而盖在弹窗之上，
   工具页的分享海报弹窗就是这么被挡住的。
   去掉 z-index（保持 auto，不创建层叠上下文）后，弹窗的层级才在根上下文生效。 */
body > * { position: relative; }

::selection {
  background: var(--primary);
  color: var(--text-onbrand);
}

a {
  text-decoration: none;
  color: inherit;
  -webkit-tap-highlight-color: transparent;
}
a:hover { text-decoration: none; }

ul { list-style: none; }

/* height:auto 不能省：只写 max-width:100% 时，若 <img> 自带 width/height 属性
   或别处给它定了高，等比缩放会被破坏，图片会被压扁 / 拉长。
   （带具体类名的规则如 .good-thumb{height:54px} 优先级更高，不受这条影响。） */
img { display: block; max-width: 100%; height: auto; }

button, input, select, textarea { font-family: inherit; }

/* 焦点环 —— 鼠标要安静，键盘要清晰
   原写法把 :focus 和 :focus-visible 一起设成 none，理由只是「点击后残留一圈线不好看」。
   但这两个选择器的语义完全不同：
     · :focus        鼠标点击、脚本 focus() 都会命中  → 不显示 outline（满足观感）
     · :focus-visible 只在键盘导航（Tab）时命中       → **必须**显示
   一起干掉之后，键盘用户 Tab 到按钮、链接、自定义控件上完全看不出焦点在哪
   （输入框还有 border + box-shadow 兜着，按钮和链接则一点反馈都没有）。
   现在拆开：鼠标点击依旧安静，键盘导航有清晰的品牌色焦点环。 */
:focus { outline: none; }

:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-xs);
}

/* 滚动条：细而克制 */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border-hover);
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background: var(--text-3); }

/* ==================== 通用工具类 ==================== */
.hidden { display: none !important; }
/* 注意：这里**不要**再定义 .show { display: block !important }。
   全站有 33 个页面靠 classList.add('show') 做淡入（.toast.show / .report-modal.show /
   .modal-overlay.show …），一旦存在 !important 的全局 .show，这些容器会被强制
   display:block，淡入动画和 flex 居中布局全部失效。旧入口遗留的这条规则已删除。 */

/* ==================== Toast 提示 ====================
 * utils.js 的 showToast() 往 <body> 里塞一个 .toast 元素，
 * 但这条规则此前只定义在 admin.css（后台），前台 33 个工具页调 showToast
 * 其实什么都没显示。前台样式放到这里，补齐这个缺口。 */
.toast {
  position: fixed;
  left: 50%;
  bottom: 2rem;
  z-index: var(--z-toast);
  max-width: min(88vw, 420px);
  padding: .75rem 1.25rem;
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  font-size: .9rem;
  line-height: 1.5;
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transform: translateX(-50%) translateY(100px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ==================== 容器 ==================== */
.container {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 20px;
}

main {
  /* 内页顶部/底部预留呼吸空间：导航与内容、内容与页脚不再贴死。
     首页/关于（page-has-hero）的 hero 必须顶到导航栏，padding 归零。 */
  padding: 28px 0 56px;
}
body.page-has-hero main { padding: 0; }

/* ==================== 排版 ==================== */
h1, h2, h3, h4 {
  line-height: 1.3;
  letter-spacing: -.2px;
  font-weight: 700;
}

/* ==================== 内页页头（统一「大气」版式） ==================== */
/* 首页有 Hero，内页若只放一个 1.4rem 的小标题会显得局促。
   这里把内页页头也做成有呼吸感的「小 Hero」：更大的字号 + 品牌竖条 + 底部渐变细线。 */
.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.25rem;
  flex-wrap: wrap;
  margin-bottom: 2rem;
  padding-bottom: 1.4rem;
  position: relative;
}
.page-header::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, var(--primary) 0%, transparent 62%);
  opacity: .45;
}
.page-header h1 {
  font-size: clamp(1.6rem, 2.6vw, 2.05rem);
  font-weight: 780;
  letter-spacing: -.9px;
  display: flex;
  align-items: center;
  gap: .6rem;
  line-height: 1.2;
}
.page-header h1 .fas,
.page-header h1 .far,
.page-header h1 .fab {
  color: var(--primary);
  font-size: .82em;
}
.page-header p {
  font-size: .95rem;
  color: var(--text-3);
  margin-top: .5rem;
}
/* 页头右侧的说明/操作 */
.page-header .page-header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* ==================== 按钮 ==================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 0.7rem 1.6rem;
  font-size: 0.92rem;
  font-weight: 600;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  cursor: pointer;
  transition: all var(--dur) var(--ease);
  text-decoration: none;
  white-space: nowrap;
}

.btn-primary {
  background: var(--grad-brand);
  color: var(--text-inv);
  box-shadow: var(--shadow-brand);
}
.btn-primary:hover {
  color: var(--text-inv);
  transform: translateY(-2px);
  box-shadow: 0 12px 28px var(--primary-shadow);
}
.btn-primary:active { transform: translateY(0); }

.btn-secondary {
  background: var(--card);
  color: var(--text-2);
  border-color: var(--border);
  box-shadow: var(--shadow-xs);
}
.btn-secondary:hover {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--primary-soft);
  transform: translateY(-1px);
}

.btn-ghost {
  background: transparent;
  color: var(--text-2);
  border: 1px solid var(--border);
}
.btn-ghost:hover {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--primary-soft);
  transform: translateY(-1px);
}

.btn-danger {
  background: var(--danger-soft);
  color: var(--danger);
}
.btn-danger:hover { background: var(--danger); color: var(--text-onbrand); }

.btn-sm { padding: 0.4rem 1rem; font-size: 0.82rem; }
.btn-block { width: 100%; }

/* 让 .btn-* 单独使用（不带 .btn）时也有完整外观 */
.btn-primary,
.btn-secondary,
.btn-ghost,
.btn-danger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 0.7rem 1.5rem;
  border-radius: var(--radius-pill);
  font-size: .92rem;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid transparent;
  text-decoration: none;
  transition: all var(--dur) var(--ease);
  white-space: nowrap;
}
.btn-full { width: 100%; }

/* ==================== 表单 ==================== */
.form-group { margin-bottom: 16px; }

.form-label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: 6px;
}
.form-label .req { color: var(--danger); }

.form-input,
.form-select,
.form-textarea,
.form-control {
  width: 100%;
  padding: 10px 14px;
  font-size: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--text);
  transition: border-color var(--dur), box-shadow var(--dur);
  font-family: inherit;
}

.form-input:focus,
.form-select:focus,
.form-textarea:focus,
.form-control:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-ring);
}

/* ==================== 卡片 ==================== */
.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}

/* 相邻卡片留白。
   .card 本身没有外边距，两张卡上下相邻时会直接贴死
   （个人中心「每日签到」卡紧贴「账户充值」卡就是这么来的）。
   相邻 margin 会折叠，已经在别处设过 margin-bottom 的地方不会变成双倍。 */
.card + .card { margin-top: 1.25rem; }

.card-title {
  font-size: .98rem;
  font-weight: 650;
  padding: .9rem 1.1rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: .45rem;
}
.card-title .fas { color: var(--primary); }

/* ==================== 空状态 ==================== */
.empty-state {
  text-align: center;
  padding: 3.5rem 1.5rem;
  color: var(--text-3);
  background: var(--card);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
}
.empty-state i {
  font-size: 2.6rem;
  opacity: .35;
  display: block;
  margin-bottom: .8rem;
}
.empty-state p { font-size: .9rem; }

/* ==================== 徽章 ==================== */
.badge {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .2rem .65rem;
  border-radius: var(--radius-pill);
  font-size: .74rem;
  font-weight: 600;
  background: var(--primary-soft);
  color: var(--primary);
}

/* ==================== 网格 ==================== */
.grid { display: grid; gap: 16px; }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

/* ==================== 辅助类 ==================== */
.text-center { text-align: center; }
.flex-center { display: flex; align-items: center; justify-content: center; }
.flex-between { display: flex; align-items: center; justify-content: space-between; }
.gap-1 { gap: 8px; }
.gap-2 { gap: 16px; }
.mt-1 { margin-top: 8px; }
.mt-2 { margin-top: 16px; }
.mb-1 { margin-bottom: 8px; }
.mb-2 { margin-bottom: 16px; }
.p-1 { padding: 8px; }
.p-2 { padding: 16px; }

/* 数字（价格 / 统计）用等宽字形，避免跳动 */
.num, .tabular { font-variant-numeric: tabular-nums; }

/* ==================== 响应式 ==================== */
@media (max-width: 992px) {
  .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 768px) {
  .container { padding: 0 16px; }
  main.container { padding: 16px 16px 32px; }
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
  .page-header h1 { font-size: 1.2rem; }
  .btn-primary,
  .btn-secondary,
  .btn-ghost,
  .btn-danger { min-height: 44px; }
}

/* ==================== 无障碍：尊重系统的「减少动态效果」 ====================
 * 前庭功能障碍 / 晕动症用户会在系统里开「减少动态效果」。不响应这个设置，
 * 页面上的位移、缩放、轮播就会让他们不适。
 * 这里做全局兜底，把动画与过渡压到近乎为 0，而不是逐个组件去改一遍。
 * （homepage.css 里另有针对 hero 的细化处理，两者不冲突。） */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==================== 触摸设备：点击目标最小 44px ====================
 * 只在「视口 ≤768px」的断点里给 min-height 并不够 —— 平板和触屏笔记本
 * 同样靠手指操作，而它们的宽度往往大于 768px。
 * 用 (hover: none) 判断「没有精确指针」比猜宽度准得多。
 * 刻意不含 .btn-sm：那是表格行内、分页器里的紧凑按钮，撑到 44px 会把布局顶散。 */
@media (hover: none) {
  .btn,
  .btn-primary,
  .btn-secondary,
  .btn-ghost,
  .btn-danger {
    min-height: 44px;
  }
}

/* ---- assets/css/navigation.css ---- */
/**
 * 导航与页脚 —— 主题「晨曦 Aurora」
 *
 * @description 顶栏（玻璃拟态）、页脚、移动端底部 TabBar、主题切换按钮
 */

/* ==================== 顶部导航 ==================== */
.navbar {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  height: var(--nav-h);
  background: color-mix(in srgb, var(--card) 82%, transparent);
  backdrop-filter: saturate(180%) blur(16px);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
  border-bottom: 1px solid var(--border);
  transition: box-shadow var(--dur) var(--ease), background var(--dur) var(--ease);
}

/* 不支持 color-mix 的浏览器回退 */
@supports not (background: color-mix(in srgb, red 50%, blue)) {
  .navbar { background: var(--card); }
}

.navbar.scrolled {
  box-shadow: var(--shadow-sm);
  border-bottom-color: var(--border-hover);
}

.nav-inner {
  height: 100%;
  display: flex;
  align-items: center;
  gap: 24px;
}

/* Logo */
.logo {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: .2px;
  flex-shrink: 0;
}

.logo-icon {
  width: 34px;
  height: 34px;
  border-radius: 11px;
  background: var(--grad-brand);
  color: var(--text-onbrand);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-brand);
  flex-shrink: 0;
}
.logo-icon svg { width: 18px; height: 18px; }

/* 导航链接 */
.nav-links {
  display: flex;
  gap: 4px;
  margin-left: auto;
}

.nav-links a {
  position: relative;
  font-size: 14.5px;
  color: var(--text-2);
  font-weight: 550;
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  transition: color var(--dur), background var(--dur);
}

.nav-links a:hover {
  color: var(--text);
  background: var(--bg-soft);
}

.nav-links a.active {
  color: var(--primary);
  background: var(--primary-soft);
  font-weight: 650;
}

/* 顶栏右侧操作区 */
.nav-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

/* 主题切换按钮 */
.theme-toggle {
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--card);
  color: var(--text-2);
  cursor: pointer;
  transition: all var(--dur) var(--ease);
  flex-shrink: 0;
}
.theme-toggle:hover {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--primary-soft);
  transform: rotate(18deg);
}
.theme-toggle .fa-sun { display: none; }
[data-theme="dark"] .theme-toggle .fa-sun { display: inline-block; }
[data-theme="dark"] .theme-toggle .fa-moon { display: none; }

/* CTA 按钮 */
.nav-cta {
  flex-shrink: 0;
  padding: 9px 20px;
  border: none;              /* <button> 复用此类时吃掉浏览器默认边框（打赏按钮） */
  appearance: none;
  border-radius: var(--radius-pill);
  background: var(--grad-brand);
  color: var(--text-inv);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.2;          /* button 与 a 的行高基线对齐 */
  box-shadow: var(--shadow-brand);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
  cursor: pointer;
}
.nav-cta:hover {
  color: var(--text-inv);
  transform: translateY(-2px);
  box-shadow: 0 12px 26px var(--primary-shadow);
}

/* ==================== 页脚 ==================== */
.footer {
  background: var(--bg-soft);
  border-top: 1px solid var(--border);
  padding: 52px 0 24px;
  /* 与内容的间距由 main 的 padding-bottom 统一供给（base.css），
     这里不再加 margin-top —— 双份间距会把页面撑出一大截 */
  margin-top: 0;
  position: relative;
}
.footer::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--grad-brand);
  opacity: .5;
}

.footer-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 36px;
}

.footer .logo { margin-bottom: 12px; }

.footer-desc {
  font-size: 13px;
  color: var(--text-2);
  line-height: 1.8;
  max-width: 320px;
}

.footer h4 {
  font-size: 13.5px;
  font-weight: 650;
  color: var(--text);
  margin-bottom: 14px;
}

.footer li { margin-bottom: 9px; }

.footer li a {
  font-size: 13px;
  color: var(--text-2);
  transition: color var(--dur);
}
.footer li a:hover { color: var(--primary); }

.footer-bottom {
  margin-top: 44px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 12px;
  color: var(--text-3);
}
.footer-bottom a { color: inherit; }
.footer-bottom a:hover { color: var(--primary); }
.footer-version {
  font-variant-numeric: tabular-nums;
  opacity: .6;
}

/* ==================== 移动端底部 TabBar ==================== */
.tabbar {
  display: none;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-tabbar);
  background: color-mix(in srgb, var(--card) 92%, transparent);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  border-top: 1px solid var(--border);
  box-shadow: 0 -6px 22px var(--hairline);
  padding: 6px 6px calc(6px + env(safe-area-inset-bottom));
}

@supports not (background: color-mix(in srgb, red 50%, blue)) {
  .tabbar { background: var(--card); }
}

.tabbar a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 5px 0 3px;
  font-size: 10.5px;
  color: var(--text-3);
  font-weight: 550;
  transition: color var(--dur);
  position: relative;
}

.tabbar a.active { color: var(--primary); font-weight: 650; }

/* 激活项顶部小圆点 */
.tabbar a.active::before {
  content: '';
  position: absolute;
  top: 0;
  width: 22px;
  height: 3px;
  border-radius: 0 0 4px 4px;
  background: var(--grad-brand);
}

.tabbar svg { width: 22px; height: 22px; }

/* ==================== 响应式 ==================== */
@media (max-width: 768px) {
  .tabbar { display: flex; }
  body { padding-bottom: calc(64px + env(safe-area-inset-bottom)); }

  /* 移动端顶部保留简化导航栏：左边 logo，右侧主题切换 + 打赏/用户中心按钮。
     中间导航链接在窄屏上没有空间，直接隐藏（用户通过底部 TabBar 切换主入口）。
     之前 .navbar { display: none; } 导致商品详情页等 H5 页面顶部光秃秃很难看。 */
  .navbar {
    position: sticky;
    top: 0;
  }
  .nav-links { display: none; }
  .nav-inner { gap: 12px; }
  .logo {
    font-size: 16px;
    gap: 8px;
  }
  .logo-icon {
    width: 32px;
    height: 32px;
    border-radius: 10px;
  }
  .logo-icon svg { width: 16px; height: 16px; }
  .nav-actions {
    gap: 8px;
    margin-left: auto;
  }
  .nav-cta {
    padding: 8px 16px;
    font-size: 13px;
  }
  .theme-toggle {
    width: 34px;
    height: 34px;
  }
  .footer { padding: 36px 0 20px;}
  .footer-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 14px;
    text-align: center;
  }
  .footer-grid > div:first-child { grid-column: 1 / -1; }
  .footer .logo { justify-content: center; }
  .footer-desc { max-width: none; }
  .footer h4 { font-size: 12.5px; margin-bottom: 10px; }
  .footer li { margin-bottom: 7px; }
  .footer-bottom {
    margin-top: 28px;
    justify-content: center;
    text-align: center;
  }
}

/* ---- assets/css/auth.css ---- */
/**
 * 认证页面（登录 / 注册 / 忘记密码 / 重置密码）—— 主题「晨曦 Aurora」
 */

.auth-page {
  min-height: calc(100vh - var(--nav-h) - 200px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 20px;
}

.auth-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 36px 32px;
  width: 100%;
  max-width: 420px;
  box-shadow: var(--shadow-hover);
  position: relative;
  overflow: hidden;
}

/* 顶部品牌渐变条 */
.auth-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--grad-brand);
}

.auth-header {
  text-align: center;
  margin-bottom: 26px;
}

.auth-icon-wrapper {
  width: 66px;
  height: 66px;
  border-radius: 20px;
  background: var(--primary-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 28px;
  margin: 0 auto 16px;
  border: 1px solid var(--primary-ring);
}
.auth-icon-wrapper i,
.auth-icon-wrapper .fas {
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.auth-title {
  font-size: 22px;
  font-weight: 750;
  color: var(--text);
  margin-bottom: 4px;
}

.auth-subtitle {
  font-size: 13px;
  color: var(--text-3);
}

.auth-error {
  background: var(--danger-soft);
  border: 1px solid var(--danger-border);
  color: var(--danger);
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  margin-bottom: 16px;
}

.auth-success {
  background: var(--success-soft);
  border: 1px solid var(--success-border);
  color: var(--success);
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  margin-bottom: 16px;
}

.auth-links {
  text-align: center;
  margin-top: 18px;
  font-size: 13px;
  color: var(--text-2);
}

.auth-links a {
  color: var(--primary);
  font-weight: 600;
}

.auth-links a:hover { text-decoration: underline; }

@media (max-width: 768px) {
  .auth-page { padding: 28px 16px; }
  .auth-card { padding: 28px 20px; }
}

/* ---- assets/css/homepage.css ---- */
/**
 * 首页样式 —— 主题「晨曦 Aurora」
 *
 * @description Hero、通用区块、服务卡片、首页三栏（天气 / 工具 / 商城）、日历
 */

/* ==================== Hero ==================== */
.hero {
  padding: 128px 0 92px;
  text-align: center;
  position: relative;
  overflow: hidden;
}

/* 双色极光：两个错位的径向光斑，比单一渐变更有层次 */
.hero::before,
.hero::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  pointer-events: none;
  opacity: .62;
}
.hero::before {
  width: 820px;
  height: 500px;
  top: -220px;
  left: 50%;
  transform: translateX(-80%);
  background: radial-gradient(circle, color-mix(in srgb, var(--primary) 38%, transparent) 0%, transparent 70%);
  animation: auroraA 14s var(--ease) infinite alternate;
}
.hero::after {
  width: 740px;
  height: 460px;
  top: -170px;
  left: 50%;
  transform: translateX(-14%);
  background: radial-gradient(circle, color-mix(in srgb, var(--info) 32%, transparent) 0%, transparent 70%);
  animation: auroraB 17s var(--ease) infinite alternate;
}

@keyframes auroraA {
  from { transform: translateX(-80%) scale(1); }
  to   { transform: translateX(-72%) scale(1.08); }
}
@keyframes auroraB {
  from { transform: translateX(-14%) scale(1); }
  to   { transform: translateX(-22%) scale(1.06); }
}
@media (prefers-reduced-motion: reduce) {
  .hero::before, .hero::after { animation: none; }
}

.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 18px;
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 26px;
  position: relative;
  z-index: var(--z-base);
  background: var(--primary-soft);
  color: var(--primary);
  border: 1px solid var(--primary-ring);
  box-shadow: var(--shadow-xs);
}

.hero-badge .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--primary);
  display: inline-block;
  box-shadow: 0 0 0 4px var(--primary-ring);
}

.hero h1 {
  font-size: clamp(2.4rem, 5.2vw, 3.9rem);
  font-weight: 800;
  letter-spacing: -1.6px;
  color: var(--text);
  line-height: 1.14;
  margin-bottom: 20px;
  position: relative;
  z-index: var(--z-base);
}

/* 高亮词：品牌渐变文字 */
.hero h1 em {
  font-style: normal;
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.hero .sub {
  font-size: clamp(1rem, 1.6vw, 1.18rem);
  color: var(--text-2);
  line-height: 1.7;
  margin-bottom: 36px;
  position: relative;
  z-index: var(--z-base);
  max-width: 680px;
  margin-left: auto;
  margin-right: auto;
}

.hero-actions {
  display: flex;
  justify-content: center;
  gap: 16px;
  margin-bottom: 58px;
  flex-wrap: wrap;
  position: relative;
  z-index: var(--z-base);
}

.hero-actions .btn,
.hero-actions a.btn {
  padding: 15px 34px;
  font-size: 1.02rem;
}

.hero-stats {
  display: flex;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  position: relative;
  z-index: var(--z-base);
}

.hero-stats .stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 132px;
  padding: 18px 24px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.hero-stats .stat:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-hover);
}

.hero-stats .num {
  font-size: 2.05rem;
  font-weight: 800;
  color: var(--text);
  letter-spacing: -.6px;
  display: flex;
  align-items: baseline;
  gap: 1px;
  font-variant-numeric: tabular-nums;
}

.hero-stats .num i {
  font-style: normal;
  font-size: 1rem;
  font-weight: 600;
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.hero-stats .label {
  font-size: 12.5px;
  color: var(--text-3);
}

/* ==================== 通用区块 ==================== */
.section { padding: var(--section-y) 0; }

.section-tint { background: var(--bg-soft); }

.section-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 38px;
  flex-wrap: wrap;
}

.section-head h2 {
  font-size: clamp(1.45rem, 2.4vw, 1.72rem);
  font-weight: 780;
  letter-spacing: -.5px;
  color: var(--text);
}
/* 标题左侧品牌竖条 */
.section-head h2::before {
  content: '';
  display: inline-block;
  width: 4px;
  height: 20px;
  border-radius: 3px;
  background: var(--grad-brand);
  margin-right: 12px;
  vertical-align: -3px;
}

.section-head .sub {
  font-size: 13px;
  color: var(--text-3);
}

.section-head .more {
  margin-left: auto;
  font-size: 13px;
  font-weight: 600;
  color: var(--primary);
  text-decoration: none;
  transition: opacity var(--dur);
}
.section-head .more:hover { opacity: .75; }

/* ==================== 滚动渐入 ==================== */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .55s var(--ease), transform .55s var(--ease);
}
.reveal.visible { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* ==================== 平台服务卡片 ==================== */
.svc-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.svc-card {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 28px 26px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  transition: all .28s var(--ease);
  text-decoration: none;
  position: relative;
  overflow: hidden;
}

/* 顶部品牌渐变条（hover 时展开） */
.svc-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--grad-brand);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .3s var(--ease);
}
.svc-card:hover::before { transform: scaleX(1); }

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

.svc-icon {
  width: 54px;
  height: 54px;
  border-radius: 16px;
  background: var(--primary-soft);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.35rem;
  flex-shrink: 0;
  transition: all .28s var(--ease);
}
.svc-card:hover .svc-icon {
  background: var(--grad-brand);
  color: var(--text-onbrand);
  transform: scale(1.07) rotate(-5deg);
  box-shadow: var(--shadow-brand);
}

.svc-text { flex: 1; min-width: 0; }
.svc-text h3 {
  font-size: 15.5px;
  font-weight: 680;
  color: var(--text);
  margin-bottom: 3px;
}
.svc-text p {
  font-size: 13px;
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.svc-card .arrow {
  color: var(--text-3);
  font-size: 18px;
  transition: all .28s var(--ease);
  flex-shrink: 0;
}
.svc-card:hover .arrow { color: var(--primary); transform: translateX(5px); }

/* ==================== 首页三栏布局 ==================== */
.home-main {
  display: grid;
  grid-template-columns: 290px 1fr 1fr;
  gap: 20px;
  /* 三栏等高：默认值就是 stretch，这里显式写出来并加注释。
     之前是 align-items:start —— 每列各按内容收缩，工具列 4 行把另外两列甩开一大截。
     现在列高由最高的列（推荐工具）决定，其余两列拉伸对齐。 */
  align-items: stretch;
}

.home-left,
.home-center,
.home-center > .goods-section,
.home-right > .goods-section {
  /* 列本身是 flex 纵向；中间/右侧的卡片都撑满所在列，
     与最高列（左侧天气+日历）底边对齐。 */
  min-height: 0;
}
.home-center > .goods-section,
.home-right > .goods-section { flex: 1 1 auto; height: 100%; }

/* 左列：天气保持自然高度，日历吃掉剩余高度（grid 行距均匀铺开填满卡片） */
.home-left > .calendar-card {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
.home-left > .calendar-card .cal-grid {
  flex: 1 1 auto;
  align-content: space-evenly;
}
/* 天气卡也允许拉伸（若它成为最高内容），内容纵向居中避免下方留白 */
.home-left > .weather-card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.home-left,
.home-center,
.home-right {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* ==================== 天气卡片 ==================== */
.weather-card {
  background: var(--grad-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px 20px;
  text-align: center;
  box-shadow: var(--shadow-sm);
}

.weather-card .w-icon {
  font-size: 2.8rem;
  margin-bottom: 8px;
  line-height: 1;
}
.weather-card .w-icon i {
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.weather-card .w-temp {
  font-size: 2.1rem;
  font-weight: 800;
  color: var(--text);
  margin-bottom: 4px;
  font-variant-numeric: tabular-nums;
}

.weather-card .w-desc { font-size: 14px; color: var(--text-2); margin-bottom: 6px; }
.weather-card .w-city { font-size: 13px; color: var(--text-3); }

/* ==================== 日历卡片 ==================== */
.calendar-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px;
  box-shadow: var(--shadow-sm);
}

.cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.cal-title { font-size: 14px; font-weight: 650; color: var(--text); }

.cal-nav { display: flex; gap: 4px; }

.cal-nav button {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: transparent;
  cursor: pointer;
  color: var(--text-2);
  transition: all var(--dur) var(--ease);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .7rem;
}
.cal-nav button:hover {
  border-color: var(--primary);
  background: var(--primary-soft);
  color: var(--primary);
}

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}

/* ==================== 三栏内的分区卡片 ==================== */
.goods-section {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: var(--shadow-sm);
  height: 100%;
}

.goods-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}

.goods-head .g-icon {
  width: 36px;
  height: 36px;
  border-radius: 11px;
  background: var(--primary-soft);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
}

.goods-head h3 { font-size: 15px; font-weight: 650; color: var(--text); flex: 1; }

.goods-head .g-more {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--primary);
  text-decoration: none;
  transition: opacity var(--dur);
}
.goods-head .g-more:hover { opacity: .75; }

/* ==================== 工具网格（首页） ==================== */
.tool-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}

.tool-card {
  padding: 14px 12px;
  background: var(--card-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  text-align: center;
  transition: all .25s var(--ease);
  text-decoration: none;
  display: block;
}

.tool-card:hover {
  border-color: var(--primary);
  background: var(--primary-soft);
  transform: translateY(-3px);
  box-shadow: var(--shadow-hover);
}

.tool-card .tool-icon {
  font-size: 1.6rem;
  margin-bottom: 8px;
}
.tool-card .tool-icon i {
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.tool-card .tool-name {
  font-size: 13px;
  font-weight: 650;
  color: var(--text);
  margin-bottom: 3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tool-card .tool-desc {
  font-size: 11.5px;
  color: var(--text-3);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ==================== 商城上新（首页） ==================== */
.goods {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}

/* 商品卡片与上方「推荐工具」卡片保持同一套底与框：
   浅底(--card-soft) + 1px 边线(--border) + 同档圆角，静止时就看得见轮廓。
   之前这里写的是 border: 1px solid transparent —— 不 hover 就完全没有框，
   和旁边工具卡片放一起像个没做完的占位。 */
.good-card {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  padding: 8px;
  border-radius: var(--radius-md);
  background: var(--card-soft);
  border: 1px solid var(--border);
  transition: all var(--dur) var(--ease);
}
.good-card:hover {
  background: var(--primary-soft);
  border-color: var(--primary);
  transform: translateY(-3px);
  box-shadow: var(--shadow-hover);
}

.good-thumb {
  width: 54px;
  height: 54px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  flex-shrink: 0;
  background: var(--bg-soft);
  display: flex;
  align-items: center;
  justify-content: center;
}
.good-thumb img { width: 100%; height: 100%; object-fit: cover; }
.good-thumb .no-img { color: var(--text-3); font-size: 1.5rem; }

.good-info { flex: 1; min-width: 0; }

.good-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.good-price {
  font-size: 13px;
  font-weight: 750;
  background: var(--grad-warm);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  font-variant-numeric: tabular-nums;
}

/* 右侧商城卡片：内容区吃掉卡片「剩余」高度。
   ★ 不能给 .goods 写 height:100% —— 那样会连 goods-head 一起顶出去，
     底部两件商品会溢出卡片边框（踩过）。正确做法是卡片自身做纵向 flex：
     标题栏固定高度，商品区 flex:1 + min-height:0 吃掉剩下的空间。 */
.home-right > .goods-section {
  display: flex;
  flex-direction: column;
}
.home-right > .goods-section > .goods-head { flex: 0 0 auto; }
.home-right > .goods-section > .goods {
  flex: 1 1 auto;
  min-height: 0;
  height: auto;
  /* 6 个商品 2 列 × 3 行，行高按剩余空间均分；
     minmax(0, 1fr) 允许行收缩，空间不足时不会把内容挤出卡片 */
  grid-template-rows: repeat(3, minmax(0, 1fr));
}
.home-right .good-card {
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 6px;
  padding: 8px;
  text-align: center;
  height: 100%;
  overflow: hidden;
}
.home-right .good-info { flex: 0 0 auto; }
.home-right .good-thumb {
  width: 56px;
  height: 56px;
  flex: 0 1 auto;
  min-height: 0;   /* 空间不够时缩略图先缩，保证商品名/价格不被切掉 */
}

/* ==================== 日历 / 天气补齐 ==================== */
.cal-week {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  margin-bottom: 4px;
}
.cal-week span {
  text-align: center;
  font-size: 11px;
  color: var(--text-3);
  padding: 2px 0;
}

.calendar-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  padding: 4px 0;
  border-radius: var(--radius-xs);
  cursor: pointer;
  transition: background var(--dur), color var(--dur);
  min-height: 34px;
}
.calendar-day:hover { background: var(--bg-soft); }

.calendar-day .day-num {
  font-size: 13px;
  font-weight: 650;
  color: var(--text);
  line-height: 1.2;
}
.calendar-day .day-lunar {
  font-size: 9px;
  color: var(--text-3);
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.calendar-day .day-lunar.special { color: var(--primary); }

.calendar-day.today {
  background: var(--grad-brand);
  box-shadow: var(--shadow-brand);
}
.calendar-day.today .day-num,
.calendar-day.today .day-lunar { color: var(--text-onbrand); }
.calendar-day.today .day-lunar.special { color: var(--text-onbrand); }

.calendar-day.selected { box-shadow: inset 0 0 0 2px var(--primary); }

.weather-card .w-extra {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  font-size: 12px;
  color: var(--text-2);
}
.weather-card .w-extra .fas { color: var(--primary); margin-right: 3px; }

/* ==================== 响应式 ==================== */
/* ---- 内容动态列宽：按显示块数用类控制（原来用内联 style，
     内联优先级最高会压死移动端媒体查询 —— 手机上 290px 1fr 1fr 直接挤碎） ---- */
.home-main.cols-3 { grid-template-columns: 290px 1fr 1fr; }
.home-main.cols-2 { grid-template-columns: 290px 1fr; }  /* 天气列固定窄，剩余给另一块 */
.home-main.cols-1 { grid-template-columns: 1fr; }

@media (max-width: 992px) {
  .svc-grid { grid-template-columns: repeat(2, 1fr); }
  .home-main.cols-3,
  .home-main.cols-2 { grid-template-columns: 1fr 1fr; }
  .home-left { grid-column: 1 / -1; flex-direction: row; }
  .home-left > * { flex: 1; }
  .tool-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 768px) {
  .hero { padding: 56px 0 44px; }
  .hero h1 { letter-spacing: -.8px; }
  .hero .sub { font-size: .96rem; margin-bottom: 26px; }
  .hero-actions { margin-bottom: 38px; gap: 12px; }
  .hero-actions .btn,
  .hero-actions a.btn { padding: 13px 26px; font-size: .96rem; flex: 1 1 140px; }
  /* Hero 统计条：手机上一排固定 2 个（2×2）。
     原来是 flex 换行 + min-width:96px，390px 屏会挤成一行 3 个，视觉很乱 */
  .hero-stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .hero-stats .stat { min-width: 0; padding: 14px 12px; }
  .hero-stats .num { font-size: 1.5rem; }
  .section-head { margin-bottom: 22px; }
  .section-head h2 { font-size: 1.3rem; }
  .svc-card { padding: 18px 16px; gap: 14px; }
  .svc-grid { grid-template-columns: 1fr; }
  /* 内容动态：手机上全部通栏单列——推荐工具/商城上新挤在半列里
     会把标题挤成竖排字（「常/用/工/具」）、空状态文案断行，必须各自独占一行 */
  .home-main.cols-3,
  .home-main.cols-2,
  .home-main.cols-1 { grid-template-columns: 1fr; gap: 14px; }
  .home-left { display: contents; }               /* 让天气/日历成为 grid 直接子项 */
  .home-left > * { grid-column: 1 / -1; }         /* 各自通栏 */
  .tool-grid { grid-template-columns: repeat(2, 1fr); }
  .goods { grid-template-columns: repeat(2, 1fr); }
  .section { padding: 36px 0; }
  .section-head h2 { font-size: 1.2rem; }
  .calendar-day { min-height: 32px; padding: 3px 0; }
  .calendar-day .day-num { font-size: 12px; }
  .calendar-day .day-lunar { font-size: 8px; }
}

/* ---- assets/css/content.css ---- */
/**
 * 商城与用户中心样式
 */

/* ==================== 通用页面头 ==================== */
/* 卡片化：内页（用户中心/订单/地址/工具中心）没有 hero，标题原先裸排在
   随机背景图上，文字直接压图非常难看。统一给卡片底。 */
.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.5rem;
  flex-wrap: wrap;
  gap: 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.15rem 1.4rem;
  box-shadow: var(--shadow-xs);
  position: relative;
}
/* base.css 给 .page-header 配的渐变下划线在卡片里多余，关掉 */
.page-header::after { content: none; }

.page-header h1 {
  font-size: 1.5rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.page-header p {
  color: var(--text-2);
  margin-top: 0.25rem;
}

/* ==================== 商城头部 ====================
   已与 .page-header 统一：商城/购物车页的头部标记改用 page-header 类，
   这里保留一份「同款卡」规则兜底（旧缓存/第三方页引用 shop-header 时不再裸排）。
   2026-09-27：全站内页顶栏统一为 page-header 卡片样式。 */
.shop-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.5rem;
  flex-wrap: wrap;
  gap: 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.15rem 1.4rem;
  box-shadow: var(--shadow-xs);
  position: relative;
}
.shop-header::after { content: none; }

.shop-header h1 {
  font-size: 1.5rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.shop-header h1 .fas { color: var(--primary); font-size: .82em; }

.shop-header p {
  color: var(--text-2);
  margin-top: 0.25rem;
}

/* ==================== 商品网格 ==================== */
/* ==================== 商城公告条 ====================
 * 后台「商城设置 → 商城公告」的出口；此前后台能存值、前台没有任何渲染，
 * 所以一直是「设了没效果」。留空时整块不输出（见 shop.php）。 */
.shop-notice {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  padding: .7rem .95rem;
  margin-bottom: 1rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius-sm);
  background: var(--primary-soft);
  color: var(--text-2);
  font-size: .86rem;
  line-height: 1.65;
}
.shop-notice > .fas { color: var(--primary); margin-top: .2rem; flex-shrink: 0; }
.shop-notice-body { min-width: 0; word-break: break-word; }

.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1rem;
}

.product-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  transition: transform 0.2s, box-shadow 0.2s;
  display: block;
}

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

.product-image {
  aspect-ratio: 1/1;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.product-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.product-image .no-img {
  font-size: 2rem;
  color: var(--text-3);
}

.product-info {
  padding: 0.75rem 1rem 1rem;
}

.product-name {
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 0.35rem;
}

.product-price {
  font-size: 1rem;
  font-weight: 700;
  color: var(--primary);
}

.product-meta {
  font-size: 0.75rem;
  color: var(--text-3);
  margin-top: 0.25rem;
}

/* ==================== 购物车 ==================== */
.cart-item {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.cart-item-image {
  width: 80px;
  height: 80px;
  border-radius: var(--radius-xs);
  overflow: hidden;
  background: var(--bg);
  flex-shrink: 0;
}

.cart-item-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cart-item-info {
  flex: 1;
  min-width: 0;
}

.cart-item-name {
  font-weight: 600;
  font-size: 0.9rem;
}

.cart-item-sku {
  font-size: 0.8rem;
  color: var(--text-2);
  margin-top: 0.25rem;
}

.cart-item-price {
  font-weight: 700;
  color: var(--primary);
  margin-top: 0.25rem;
}

/* ==================== 个人中心 ==================== */
.user-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.5rem;
  box-shadow: var(--shadow);
  margin-bottom: 1.5rem;
}

.user-card-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

/* 余额 / 积分两个数值块：桌面端定宽靠右并排；窄屏各占一半，**仍然是一行**。
   加了「我的积分」这块之后，三个块按内容宽度挤，一旦放不下就整块折行，
   把整张卡片撑成两排 —— 这里把数值块的伸缩规则定死，避免wrap到第二排。 */
.user-card-header .user-info { flex: 1 1 200px; }
.user-card-header .user-balance {
  flex: 0 1 auto;
  min-width: 132px;
  padding-left: 1rem;
  border-left: 1px solid var(--border);
}
@media (max-width: 640px) {
  .user-card-header { gap: .9rem; }
  .user-card-header .user-info { flex: 1 1 100%; }
  .user-card-header .user-balance {
    flex: 1 1 calc(50% - .45rem);
    text-align: left;
    padding-left: .85rem;
  }
}

.user-avatar {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  object-fit: cover;
}

.user-info {
  flex: 1;
  min-width: 0;
}

.user-name {
  font-weight: 600;
  font-size: 1.1rem;
}

.user-email {
  font-size: 0.85rem;
  color: var(--text-2);
  margin-top: 0.25rem;
}

.user-balance {
  text-align: right;
}

.user-balance-label {
  font-size: 0.75rem;
  color: var(--text-3);
}

.user-balance-value {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--primary);
}

/* 快捷入口 */
.quick-actions {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.quick-action {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
  text-align: center;
  box-shadow: var(--shadow);
  display: block;
}

.quick-action-icon {
  font-size: 1.5rem;
  color: var(--primary);
  margin-bottom: 0.5rem;
}

.quick-action-title {
  font-weight: 600;
  font-size: 0.9rem;
}

.quick-action-meta {
  font-size: 0.75rem;
  color: var(--text-3);
}

/* 余额日志 */
.balance-log {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.balance-log-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem;
  background: var(--bg);
  border-radius: var(--radius-xs);
}

.balance-log-icon {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.balance-log-info {
  flex: 1;
}

.balance-log-type {
  font-weight: 500;
  font-size: 0.9rem;
}

.balance-log-time {
  font-size: 0.75rem;
  color: var(--text-3);
}

.balance-log-amount {
  font-weight: 700;
}

.balance-log-amount.positive { color: var(--success); }
.balance-log-amount.negative { color: var(--danger); }

/* ==================== 订单列表 ==================== */
.order-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.order-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  box-shadow: var(--shadow);
  cursor: pointer;
}

.order-card-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.75rem;
}

.order-meta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.order-no {
  font-weight: 600;
  font-size: 0.9rem;
}

.order-type {
  font-size: 0.75rem;
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius);
  background: var(--primary-soft);
  color: var(--primary);
}

.order-card-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.order-product {
  font-size: 0.9rem;
  font-weight: 500;
}

.order-count {
  font-size: 0.8rem;
  color: var(--text-3);
  margin-left: 0.5rem;
}

.order-time {
  font-size: 0.75rem;
  color: var(--text-3);
  margin-top: 0.25rem;
}

.order-amount {
  font-weight: 700;
  color: var(--primary);
}

/* ==================== 支付页面 ==================== */
.pay-container { max-width: 600px; margin: 0 auto; }
.pay-header { text-align: center; margin-bottom: 1.5rem; }
.pay-title { font-size: 1.5rem; font-weight: 700; margin-bottom: 0.25rem; }
.pay-subtitle { color: var(--text-2); }
.pay-amount-box { background: var(--bg-sunken); border-radius: var(--radius-sm); padding: 1.25rem; margin-bottom: 1.5rem; }
.pay-amount-row { display: flex; justify-content: space-between; padding: 0.5rem 0; }
.pay-amount-label { color: var(--text-2); }
.pay-btn-full { width: 100%; padding: 0.85rem; border: none; border-radius: var(--radius-sm); font-size: 1rem; font-weight: 600; cursor: pointer; }
.pay-btn-success { background: var(--success); color: var(--text-onbrand); display: block; text-align: center; }
.pay-btn-alipay { background: var(--alipay); color: var(--text-onbrand); }
.pay-btn-alipay:hover { background: var(--alipay-hover); }
.pay-alert { background: var(--danger-soft); border-radius: var(--radius-sm); padding: 1rem; margin-bottom: 1rem; display: none; }
.pay-alert-content { display: flex; align-items: center; gap: 0.5rem; color: var(--danger); margin-bottom: 0.75rem; }
.pay-confirm-btn { background: var(--primary); color: var(--text-onbrand); border: none; padding: 0.6rem 1.5rem; border-radius: var(--radius-xs); cursor: pointer; }
.modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: var(--scrim); display: none; align-items: center; justify-content: center; z-index: var(--z-overlay); }

/* ==================== 支付方式选择 ==================== */
.pay-methods-section { margin-bottom: 1.5rem; }
.pay-methods-title { font-weight: 600; margin-bottom: 0.75rem; }
.pay-method-item { display: flex; align-items: center; justify-content: space-between; padding: 1rem; border: 1px solid var(--border); border-radius: var(--radius-sm); margin-bottom: 0.75rem; cursor: pointer; transition: all 0.2s; }
.pay-method-item:hover { border-color: var(--primary); }
.pay-method-item.selected { border-color: var(--primary); background: var(--primary-soft); }
.pay-method-left { display: flex; align-items: center; gap: 0.75rem; }
.pay-method-icon { font-size: 1.5rem; width: 40px; text-align: center; }
.pay-method-icon.balance { color: var(--accent); }
.pay-method-icon.alipay { color: var(--alipay); }
.pay-method-info p { font-size: 0.9rem; }
.pay-method-info p:first-child { font-weight: 600; }
.pay-method-info p:last-child { color: var(--text-2); font-size: 0.8rem; }
.pay-method-check { color: var(--primary); display: none; }
.pay-method-disabled { opacity: 0.5; cursor: not-allowed; }
.pay-form { margin-bottom: 1rem; }
.pay-confirm-box { text-align: center; padding: 1.5rem; background: var(--bg-sunken); border-radius: var(--radius-sm); margin-bottom: 1rem; display: none; }
.pay-confirm-icon { font-size: 2rem; color: var(--primary); margin-bottom: 0.5rem; }
.pay-confirm-text { font-weight: 600; }
.pay-confirm-subtext { color: var(--text-2); font-size: 0.9rem; margin: 0.25rem 0 1rem; }
.pay-cancel-link { display: block; text-align: center; color: var(--text-2); margin-top: 1rem; font-size: 0.9rem; }
.pay-cancel-link:hover { color: var(--text); }
.modal-btn { background: var(--primary); color: var(--text-onbrand); border: none; padding: 0.6rem 2rem; border-radius: var(--radius-xs); cursor: pointer; }

/* ==================== 支付结果页 ==================== */
.pay-result-container { max-width: 600px; margin: 3rem auto; }
.pay-result-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 3rem 2rem; text-align: center; }
.pay-result-icon { width: 100px; height: 100px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 1.5rem; font-size: 3rem; }
.pay-result-icon.success { background: var(--grad-success-soft); color: var(--success); }
.pay-result-icon.warning { background: var(--grad-warning-soft); color: var(--warning); }
.pay-result-title { font-size: 1.75rem; font-weight: 700; margin-bottom: 1rem; }
.pay-result-title.success { color: var(--success); }
.pay-result-title.warning { color: var(--warning); }
.pay-result-message { font-size: 1rem; color: var(--text-2); margin-bottom: 2rem; line-height: 1.6; }
.pay-result-details { background: var(--glass); border-radius: var(--radius-sm); padding: 1.5rem; margin-bottom: 2rem; text-align: left; }
.pay-result-detail-item { display: flex; justify-content: space-between; padding: 0.75rem 0; border-bottom: 1px solid var(--border); }
.pay-result-detail-item:last-child { border-bottom: none; }
.pay-result-detail-label { color: var(--text-2); }
.pay-result-detail-value { font-weight: 600; }
.pay-result-actions { display: flex; gap: 1rem; justify-content: center; }
.pay-result-actions .btn { min-width: 120px; }
@media (max-width: 480px) {
  .pay-result-card { padding: 2rem 1.5rem; }
  .pay-result-actions { flex-direction: column; }
  .pay-result-actions .btn { width: 100%; }
}

/* ==================== 关于页面（ab- 前缀，避免与 homepage.css 的 .hero-* 互撞） ====================
   旧版这里用的是 .about-hero / .hero-badge / .hero-stats / .stat-value 之类泛名：
   homepage.css 也有 .hero-badge / .hero-stats，而前台样式栈里 content.css 排在后面，
   结果 about 页的规则反过来盖住首页 hero。全部加 ab- 前缀后各管各的。 */

.ab-hero {
  position: relative;
  padding: 92px 0 68px;
  text-align: center;
  overflow: hidden;
}
/* 与首页 hero 同语言的双色极光，尺寸收敛些，不与标题抢视线 */
.ab-hero::before,
.ab-hero::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  pointer-events: none;
  opacity: .55;
}
.ab-hero::before {
  width: 620px; height: 380px;
  top: -200px; left: 50%;
  transform: translateX(-85%);
  background: radial-gradient(circle, color-mix(in srgb, var(--primary) 34%, transparent) 0%, transparent 70%);
}
.ab-hero::after {
  width: 560px; height: 340px;
  top: -160px; left: 50%;
  transform: translateX(-10%);
  background: radial-gradient(circle, color-mix(in srgb, var(--primary-hover) 28%, transparent) 0%, transparent 70%);
}
.ab-hero > .container { position: relative; z-index: var(--z-base); }

.ab-hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 16px;
  border-radius: var(--radius-pill);
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 13px;
  font-weight: 600;
}
.ab-hero-title {
  margin: 20px 0 0;
  font-size: clamp(2.1rem, 5vw, 3.1rem);
  font-weight: 800;
  letter-spacing: -1.2px;
  color: var(--text);
}
.ab-hero-title em {
  font-style: normal;
  background: var(--grad-brand);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.ab-hero-sub {
  margin: 14px auto 0;
  max-width: 620px;
  color: var(--text-2);
  font-size: 1.05rem;
  line-height: 1.8;
}
.ab-hero-actions {
  display: flex;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 28px;
}
.ab-stats {
  display: flex;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 44px;
}
.ab-stat {
  min-width: 132px;
  padding: 18px 20px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
}
.ab-stat-num {
  font-size: 2rem;
  font-weight: 800;
  line-height: 1.1;
  background: var(--grad-brand);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.ab-stat-num i { font-style: normal; font-size: .62em; }
.ab-stat-label { margin-top: 4px; font-size: 13px; color: var(--text-3); }

/* ---- 我们是谁 ---- */
.ab-prose {
  max-width: 780px;
  color: var(--text-2);
  font-size: 1rem;
  line-height: 1.9;
}
.ab-prose p { margin-bottom: 1rem; }
.ab-prose p:last-child { margin-bottom: 0; }

/* ---- 平台能力 ---- */
.ab-cap-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
.ab-cap {
  padding: 26px 24px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.ab-cap:hover {
  transform: translateY(-4px);
  border-color: var(--primary);
  box-shadow: var(--shadow-hover);
}
.ab-cap-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px; height: 48px;
  margin-bottom: 14px;
  border-radius: var(--radius-sm);
  background: var(--grad-brand);
  color: var(--text-onbrand);
  font-size: 1.2rem;
  box-shadow: var(--shadow-brand);
}
.ab-cap h3 { margin: 0 0 8px; font-size: 1.08rem; font-weight: 700; color: var(--text); }
.ab-cap p { margin: 0; color: var(--text-2); font-size: .93rem; line-height: 1.75; }

/* ---- 联系我们 ---- */
.ab-contact-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 18px;
}
.ab-contact {
  padding: 22px 18px;
  text-align: center;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.ab-contact:hover { border-color: var(--primary); transform: translateY(-2px); }
.ab-contact-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px; height: 46px;
  margin-bottom: 12px;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 1.15rem;
}
.ab-contact h4 { margin: 0 0 6px; font-size: .98rem; font-weight: 600; color: var(--text); }
.ab-contact p { margin: 0; font-size: .9rem; color: var(--text-2); word-break: break-all; }
.ab-contact a { color: var(--primary); }
.ab-contact a:hover { text-decoration: underline; }

/* ---- 条款（原生 details 折叠，无需额外 JS） ---- */
.ab-legal { max-width: 820px; display: flex; flex-direction: column; gap: 12px; }
.ab-legal-item {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.ab-legal-item summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 20px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  list-style: none;
  transition: background var(--dur) var(--ease);
}
.ab-legal-item summary::-webkit-details-marker { display: none; }
.ab-legal-item summary::after {
  content: '\f078';
  font-family: 'Font Awesome 6 Free';
  font-weight: 900;
  margin-left: auto;
  color: var(--text-3);
  font-size: .8rem;
  transition: transform var(--dur) var(--ease);
}
.ab-legal-item[open] summary::after { transform: rotate(180deg); }
.ab-legal-item summary:hover { background: var(--bg-soft); }
.ab-legal-item summary i { color: var(--primary); }
.ab-legal-body {
  padding: 0 20px 18px;
  color: var(--text-2);
  font-size: .93rem;
  line-height: 1.85;
}
.ab-legal-body p { margin-bottom: .6rem; }
.ab-legal-body p:last-child { margin-bottom: 0; }
.ab-icp { margin-top: 4px; font-size: .88rem; color: var(--text-3); }
.ab-icp a { color: var(--text-2); }
.ab-icp a:hover { color: var(--primary); }

@media (max-width: 900px) {
  .ab-cap-grid { grid-template-columns: repeat(2, 1fr); }
  .ab-contact-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 768px) {
  .ab-hero { padding: 60px 0 44px; }
  .ab-cap-grid { grid-template-columns: 1fr; }
  .ab-stats { gap: 10px; }
  .ab-stat { flex: 1 1 130px; min-width: 0; padding: 14px 12px; }
  .ab-stat-num { font-size: 1.5rem; }
}


/* ==================== 空状态 ==================== */
.empty-state {
  text-align: center;
  padding: 4rem 1rem;
  color: var(--text-3);
}

.empty-state i {
  font-size: 3rem;
  margin-bottom: 1rem;
  opacity: 0.5;
}

/* ==================== 支付页面 ==================== */
.pay-container {
  max-width: 520px;
  margin: 0 auto;
  padding: 8px 0 20px;
}

.pay-container > .card {
  overflow: hidden;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 18px;
  background: var(--card);
  box-shadow: var(--shadow-sm);
}

.pay-header {
  padding: 30px 32px 24px;
  text-align: center;
  border-bottom: 1px solid var(--border);
}

.pay-icon {
  width: 58px;
  height: 58px;
  border-radius: 16px;
  background: var(--primary-soft);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  margin: 0 auto 15px;
}

.pay-title {
  margin: 0 0 6px;
  font-size: 1.35rem;
  font-weight: 750;
  letter-spacing: 0;
}

.pay-subtitle {
  margin: 0;
  color: var(--text-3);
  font-size: .88rem;
}

.pay-amount-box {
  margin: 20px 24px 26px;
  padding: 20px 22px 18px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--bg-soft);
}

.pay-amount-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 36px;
}

.pay-amount-row + .pay-amount-row {
  margin-top: 8px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.pay-amount-label {
  color: var(--text-2);
  font-size: .88rem;
}

.pay-amount-value {
  color: var(--primary);
  font-size: 2.35rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0;
}

.pay-methods-section {
  margin: 0 24px 20px;
}

.pay-methods-title {
  margin: 0 0 10px;
  color: var(--text);
  font-size: .9rem;
  font-weight: 700;
}

.pay-method-item {
  min-height: 66px;
  margin-bottom: 10px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  cursor: pointer;
  transition: border-color .2s, background .2s, box-shadow .2s;
}

.pay-method-item:last-child { margin-bottom: 0; }
.pay-method-item:hover {
  border-color: var(--primary);
  box-shadow: 0 4px 14px rgba(15, 148, 136, .1);
}
.pay-method-item.selected {
  border-color: var(--primary);
  background: var(--primary-soft);
  box-shadow: inset 0 0 0 1px var(--primary);
}
.pay-method-left { gap: 12px; }
.pay-method-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  font-size: 1.15rem;
  background: var(--bg-soft);
}
.pay-method-icon.balance { color: var(--accent); }
.pay-method-icon.alipay { color: #1677ff; background: #eaf3ff; }
.pay-method-info p { margin: 0; font-size: .9rem; line-height: 1.35; }
.pay-method-info p:first-child { font-weight: 700; }
.pay-method-info p:last-child { margin-top: 3px; color: var(--text-3); font-size: .78rem; }
.pay-method-check { color: var(--primary); font-size: 1.05rem; }
.pay-method-disabled { opacity: .55; cursor: not-allowed; }

.pay-form { margin: 0 24px 12px; }
.pay-btn-full {
  width: 100%;
  min-height: 46px;
  padding: 0 16px;
  border: 0;
  border-radius: 11px;
  font-size: .94rem;
  font-weight: 700;
  cursor: pointer;
  transition: filter .2s, transform .2s;
}
.pay-btn-full:not(:disabled):hover { filter: brightness(.97); }
.pay-btn-full:not(:disabled):active { transform: translateY(1px); }
.pay-btn-full:disabled {
  color: var(--text-3);
  background: var(--bg-soft);
  border: 1px solid var(--border);
  cursor: not-allowed;
}
#payBtn {
  width: calc(100% - 48px);
  margin: 0 24px 12px;
}
.pay-btn-success { background: var(--success); color: var(--text-onbrand); display: block; text-align: center; }
.pay-btn-alipay { background: var(--alipay); color: var(--text-onbrand); }
.pay-btn-alipay:hover { background: var(--alipay-hover); }

.pay-alert {
  margin: 0 24px 14px;
  padding: 14px;
  border-radius: 12px;
  background: var(--danger-soft);
}
.pay-alert-content { margin-bottom: 10px; }
.pay-confirm-box {
  margin: 0 24px 14px;
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg-soft);
}
.pay-confirm-icon { font-size: 1.7rem; }
.pay-confirm-text { margin: 0; font-weight: 700; }
.pay-confirm-subtext { margin: 5px 0 14px; font-size: .84rem; }
.pay-confirm-btn { min-height: 40px; padding: 0 18px; border-radius: 10px; }
.pay-cancel-link {
  display: block;
  margin: 4px 0 22px;
  color: var(--text-3);
  text-align: center;
  font-size: .84rem;
}
.pay-cancel-link:hover { color: var(--text); }

/* ==================== 响应式 ==================== */
@media (max-width: 768px) {
  .shop-header { flex-direction: column; align-items: flex-start; }
  .quick-actions { grid-template-columns: repeat(2, 1fr); }
  .page-header { padding: 1rem 1.1rem; }
  .cart-item { flex-direction: column; align-items: flex-start; }
  .pay-container { padding: 0 12px 16px; }
  .pay-header { padding: 26px 22px 22px; }
  .pay-amount-box,
  .pay-methods-section,
  .pay-form,
  .pay-alert,
  .pay-confirm-box { margin-left: 16px; margin-right: 16px; }
  #payBtn { width: calc(100% - 32px); margin-left: 16px; margin-right: 16px; }
  .pay-amount-value { font-size: 2rem; }
}

/* ==================== 工具页容器（tools/ 63 个页面共用） ====================
 * 工具页是直接访问的独立页（tools/xxx.php），不经过单入口 layout 的 <main>。
 * 这里自己承担 .container 的职责（限宽 + 左右留白 + 上下间距），
 * 不要再套一层 .container，否则限宽和留白会被叠加两次。 */
.tool-page {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 24px 20px 48px;
}

.tool-page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.tool-header-left { min-width: 0; }

.tool-page-title {
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 10px;
}

.tool-page-title i { color: var(--primary); }

.tool-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tool-action-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 0 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text-2);
  font-size: 0.88rem;
  cursor: pointer;
  transition: all .2s;
}

.tool-action-btn:hover {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--primary-soft);
}

.tool-share-btn { color: var(--primary); border-color: var(--primary); }

.tool-page-body { min-width: 0; }

/* ==================== 海报分享弹窗 ==================== */
.poster-modal-content { max-width: 420px; padding: 0; text-align: left; overflow: hidden; }
.poster-modal-body { padding: 16px; }

.poster-preview-wrapper {
  background: var(--bg-soft);
  border-radius: var(--radius-sm);
  padding: 12px;
  margin-bottom: 16px;
  min-height: 180px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.poster-canvas { width: 100%; }
.poster-canvas img { width: 100%; border-radius: var(--radius-sm); display: block; }

.poster-actions { display: flex; gap: 10px; }

.poster-btn {
  flex: 1;
  min-height: 44px;
  border: none;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: all .2s;
}

.poster-btn-primary { background: var(--primary); color: var(--text-onbrand); }
.poster-btn-primary:hover { background: var(--primary-hover); }

.poster-btn-secondary {
  background: var(--bg-soft);
  color: var(--text-2);
  border: 1px solid var(--border);
}

/* 海报卡片（html2canvas 渲染目标） */
.poster-card {
  width: 320px;
  background: var(--card);
  border-radius: var(--radius);
  overflow: hidden;
  font-size: 0.9rem;
}

.poster-header {
  padding: 16px;
  background: var(--primary);
  color: var(--text-onbrand);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.poster-site-logo { font-weight: 700; }

.poster-tool-badge {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  opacity: .95;
}

.poster-body { padding: 20px 16px; text-align: center; color: var(--text); }

.poster-footer {
  padding: 14px 16px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 12px;
  justify-content: space-between;
}

.poster-qr-img { width: 64px; height: 64px; border-radius: 6px; }

.poster-qr-text {
  font-size: 0.72rem;
  color: var(--text-3);
  text-align: center;
  margin-top: 4px;
}

.poster-site-name { font-weight: 700; color: var(--text); }
.poster-slogan { font-size: 0.78rem; color: var(--text-2); }

.poster-default-icon,
.poster-quote-icon,
.poster-fortune-icon,
.poster-counter-icon,
.poster-wheel-icon,
.poster-answer-icon,
.poster-poem-icon,
.poster-tab-icon { font-size: 2.6rem; margin-bottom: 10px; }

.poster-quote-title,
.poster-fortune-label,
.poster-counter-label,
.poster-wheel-label,
.poster-answer-label,
.poster-poem-title,
.poster-tab-title {
  font-size: 1.05rem;
  font-weight: 700;
  margin-bottom: 8px;
}

.poster-quote-content,
.poster-fortune-detail,
.poster-counter-hint,
.poster-wheel-hint,
.poster-answer-hint {
  font-size: 0.88rem;
  color: var(--text-2);
  line-height: 1.7;
}

.poster-counter-num,
.poster-fortune-result,
.poster-wheel-result,
.poster-counter-time {
  font-size: 2rem;
  font-weight: 800;
  color: var(--primary);
  margin: 6px 0;
}

.poster-tab-features {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
  margin-top: 10px;
}

.poster-tab-feature {
  font-size: 0.75rem;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--primary-soft);
  color: var(--primary);
}

.poster-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: var(--text-2);
  font-size: 0.88rem;
  padding: 40px 0;
}

/* 工具页移动端适配 */
@media (max-width: 768px) {
  .tool-page { padding: 16px 16px 32px; }
  .tool-page-title { font-size: 1.15rem; }
  .tool-action-btn .btn-text { display: none; }
  .tool-action-btn { padding: 0 12px; }
  .poster-card { width: 100%; }
  .poster-modal-content { max-width: 100%; }
  .poster-actions { flex-direction: column; }
}

/* ==================== 前台弹窗组件 ====================
 * 此前 .modal-content / .modal-success / .modal-icon / .modal-title / .modal-message
 * 在前台 CSS 中均无定义（只有 admin.css 有同名类），
 * 导致 pay.php 支付成功弹窗渲染为半透明黑底上的裸文字。
 *
 * 同理 .modal 基类此前也只有 admin.css 有：templates/footer.php 的赞赏弹窗
 * 和 tools/_footer.php 的海报弹窗都写 class="modal hidden"，前台缺这条规则时
 * 弹窗内容会直接摊在页面流里。这里补齐整套弹窗壳。
 */
.modal {
  position: fixed;
  inset: 0;
  /* 1200：高于底部 TabBar(98) / 顶部导航(100) / 底部购买条(90)。
     前提是它所在的那条链路上没有别的层叠上下文 —— 见 base.css 里 body > * 的说明。 */
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  background: var(--scrim-strong);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
/* 默认隐藏靠 .hidden（base.css: display:none !important），语义与后台一致 */
.modal.hidden { display: none !important; }

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--border);
}
.modal-header .modal-title { margin: 0; text-align: left; }
.modal-header-actions { display: flex; align-items: center; gap: .5rem; }
.modal-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  background: var(--card);
  color: var(--text-2);
  cursor: pointer;
  transition: all .2s;
}
.modal-close:hover { border-color: var(--danger); color: var(--danger); }

.modal-content {
  background: var(--card);
  border-radius: var(--radius);
  padding: 2rem 1.5rem;
  max-width: 380px;
  width: 90%;
  text-align: center;
  box-shadow: var(--shadow-hover);
}
/* 带 .modal-header 的弹窗（海报 / 赞赏）走左对齐版式，内边距交给内容容器 */
.modal-small { max-width: 360px; padding: 0; text-align: left; overflow: hidden; }

.modal-icon {
  font-size: 3rem;
  margin-bottom: 1rem;
  line-height: 1;
}

.modal-success .modal-icon { color: var(--success); }
.modal-error .modal-icon { color: var(--danger); }

.modal-title {
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: .5rem;
}

.modal-message {
  font-size: .92rem;
  color: var(--text-2);
  line-height: 1.7;
  margin-bottom: 1.5rem;
}

/* 赞赏弹窗（templates/partials/site-footer.php 输出） */
.donate-content { padding: 1.25rem 1.5rem 1.5rem; text-align: center; }
.donate-icon { color: var(--danger); }
.donate-message {
  font-size: .9rem;
  color: var(--text-2);
  line-height: 1.7;
  margin-bottom: 1rem;
}
.donate-methods { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }
.donate-method { flex: 1 1 140px; max-width: 180px; }
.donate-method-title {
  font-size: .82rem;
  color: var(--text-3);
  margin-bottom: .5rem;
}
.donate-qr { width: 100%; height: auto; border-radius: var(--radius-sm); }

/* ==================== 按钮补齐 ====================
 * .btn-primary / .btn-secondary / .btn-ghost 此前只有配色，
 * 缺少 .btn 提供的 padding / 圆角 / display，单独使用时渲染成浏览器原生按钮。
 */
.btn-primary,
.btn-secondary,
.btn-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 0.7rem 1.6rem;
  font-size: 0.92rem;
  font-weight: 550;
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: all .2s;
  text-decoration: none;
  white-space: nowrap;
}

.btn-full { width: 100%; }

@media (max-width: 768px) {
  .btn-primary,
  .btn-secondary,
  .btn-ghost { min-height: 44px; }
  .modal-content { padding: 1.5rem 1.25rem; }
}

/* ==================== 订单详情（orders.php?id=N） ====================
 * 此前订单卡片点击跳转 orders?id=N，但页面从不读取 id，
 * 现在补详情分支，这里配套样式。
 */
.card-title {
  font-size: .98rem;
  font-weight: 650;
  padding: .9rem 1.1rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: .45rem;
}
.card-title .fas { color: var(--primary); }

.order-status-bar {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  margin-bottom: 1rem;
  box-shadow: var(--shadow);
}

.order-status-badge {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .35rem .85rem;
  border-radius: 999px;
  font-size: .82rem;
  font-weight: 600;
  white-space: nowrap;
}
.order-status-badge .fas { font-size: .5rem; }

.order-flow {
  display: flex;
  align-items: center;
  gap: .35rem;
  flex: 1 1 260px;
  min-width: 0;
  overflow-x: auto;
}
.order-flow-step {
  display: flex;
  align-items: center;
  gap: .35rem;
  flex: 0 0 auto;
  color: var(--text-3);
  font-size: .78rem;
}
.order-flow-step .dot {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .68rem;
  flex-shrink: 0;
}
.order-flow-step.done { color: var(--primary); font-weight: 600; }
.order-flow-step.done .dot {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--text-onbrand);
}

.order-detail-card { margin-bottom: 1rem; overflow: hidden; }

.od-item-list { padding: .35rem 0; }
.od-item {
  display: flex;
  align-items: center;
  gap: .85rem;
  padding: .8rem 1.1rem;
}
.od-item + .od-item { border-top: 1px solid var(--border); }

.od-item-thumb {
  width: 52px;
  height: 52px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-3);
  overflow: hidden;
}
.od-item-thumb img { width: 100%; height: 100%; object-fit: cover; }

.od-item-main { flex: 1; min-width: 0; }
.od-item-name { font-weight: 600; font-size: .9rem; line-height: 1.4; }
.od-item-sku { font-size: .76rem; color: var(--text-3); margin-top: .2rem; }
.od-item-qty { font-size: .78rem; color: var(--text-2); margin-top: .2rem; }
.od-item-price { font-weight: 650; font-size: .92rem; white-space: nowrap; }

.od-total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .85rem 1.1rem;
  border-top: 1px solid var(--border);
  background: var(--bg-soft);
  font-size: .88rem;
}
.od-total strong { font-size: 1.15rem; color: var(--danger); }

.od-info { padding: .5rem 0; }
.od-info-row {
  display: flex;
  gap: 1rem;
  padding: .5rem 1.1rem;
  font-size: .86rem;
}
.od-info-row .k { flex: 0 0 78px; color: var(--text-3); }
.od-info-row .v { flex: 1; min-width: 0; color: var(--text); word-break: break-all; }
.od-tracking { font-family: ui-monospace, Menlo, Consolas, monospace; letter-spacing: .3px; }

.od-actions {
  display: flex;
  gap: .6rem;
  flex-wrap: wrap;
  margin-top: .5rem;
}
.od-actions .btn-primary,
.od-actions .btn-secondary,
.od-actions .btn-ghost { padding: .65rem 1.3rem; font-size: .88rem; }

@media (max-width: 768px) {
  .order-status-bar { padding: .85rem .9rem; gap: .75rem; }
  .order-flow { flex-basis: 100%; }
  .od-item { padding: .75rem .9rem; }
  .od-info-row { padding: .45rem .9rem; flex-direction: column; gap: .15rem; }
  .od-info-row .k { flex: none; }
  .od-actions .btn-primary,
  .od-actions .btn-secondary,
  .od-actions .btn-ghost { flex: 1 1 auto; min-width: 0; }
}

/* ==================== 商品详情（product.php） ====================
 * shop.php 此前链接 ?id=N 但无人读取，详情页缺失；这里配套样式。
 * H5 优先：单列 + 底部固定购买条（避开 iPhone 安全区）。
 */
.product-detail { padding-bottom: calc(84px + env(safe-area-inset-bottom)); }
.pd-layout { display: grid; grid-template-columns: 1fr; gap: 1.25rem; }

/* 图片区 */
.pd-gallery { min-width: 0; }
.pd-main-img {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  color: var(--text-3);
  font-size: 3rem;
}
/* 商品主图：cover 会把长图（竖版详情图）上下裁掉，
   详情页要看清整张图，改成 contain —— 完整展示，留白用卡片底色补上。 */
.pd-main-img img { width: 100%; height: 100%; object-fit: contain; }

.pd-thumbs {
  display: flex;
  gap: .5rem;
  margin-top: .7rem;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.pd-thumbs::-webkit-scrollbar { display: none; }
.pd-thumb {
  width: 62px;
  height: 62px;
  flex: 0 0 auto;
  padding: 0;
  border: 2px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  overflow: hidden;
  cursor: pointer;
  transition: border-color .18s;
}
.pd-thumb.active { border-color: var(--primary); }
.pd-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* 信息区 */
.pd-info { min-width: 0; }
.pd-name { font-size: 1.25rem; font-weight: 700; line-height: 1.4; }

.pd-price { margin-top: .75rem; display: flex; align-items: baseline; gap: .3rem; }
.pd-price-now { font-size: 1.6rem; font-weight: 700; color: var(--danger); }
.pd-price-unit { font-size: .82rem; color: var(--text-3); }

.pd-meta {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: .6rem;
  font-size: .78rem;
  color: var(--text-3);
}

.pd-sku { margin-top: 1.25rem; }
.pd-sku-label,
.pd-qty-label {
  font-size: .85rem;
  font-weight: 600;
  margin-bottom: .55rem;
  display: block;
}
.pd-sku-list { display: flex; gap: .5rem; flex-wrap: wrap; }
.pd-sku-item {
  padding: .5rem .9rem;
  min-height: 44px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--text);
  font-size: .85rem;
  cursor: pointer;
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  transition: all .18s;
}
.pd-sku-item small { font-size: .7rem; color: var(--text-3); font-weight: 400; }
.pd-sku-item em { font-size: .68rem; color: var(--danger); font-style: normal; }
.pd-sku-item:hover { border-color: var(--primary); }
.pd-sku-item.active {
  border-color: var(--primary);
  background: var(--primary-soft);
  color: var(--primary);
  font-weight: 600;
}

.pd-qty { margin-top: 1.25rem; }
.pd-qty-box {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--card);
}
.pd-qty-box button {
  width: 44px;
  height: 44px;
  border: none;
  background: transparent;
  color: var(--text);
  font-size: 1.1rem;
  cursor: pointer;
}
.pd-qty-box button:hover { background: var(--bg-soft); color: var(--primary); }
.pd-qty-box input {
  width: 56px;
  height: 44px;
  border: none;
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
  text-align: center;
  background: var(--card);
  color: var(--text);
  font-size: .95rem;
  -moz-appearance: textfield;
}
.pd-qty-box input::-webkit-outer-spin-button,
.pd-qty-box input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.pd-desc { margin-top: 1.5rem; }
.pd-desc-title {
  font-size: .9rem;
  font-weight: 650;
  display: flex;
  align-items: center;
  gap: .4rem;
  padding-bottom: .5rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: .75rem;
}
.pd-desc-title .fas { color: var(--primary); }
.pd-desc-body { font-size: .88rem; color: var(--text-2); line-height: 1.8; }
.pd-desc-body img { max-width: 100%; height: auto; border-radius: var(--radius-xs); }

/* 底部固定购买条 */
.pd-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .6rem .9rem calc(.6rem + env(safe-area-inset-bottom));
  background: var(--card);
  border-top: 1px solid var(--border);
  box-shadow: 0 -6px 22px var(--hairline);
}
.pd-bar-cart {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 54px;
  color: var(--text-2);
  text-decoration: none;
  font-size: .68rem;
}
.pd-bar-cart .fas { font-size: 1.05rem; }
.pd-bar-btn {
  flex: 1;
  min-height: 44px;
  padding: .6rem .8rem;
  font-size: .88rem;
}

/* 移动端：底部已有全局 TabBar（62px，z-index 98），
 * 购买条必须上移一层，否则会被 TabBar 盖住。 */
@media (max-width: 768px) {
  .pd-bar { bottom: calc(62px + env(safe-area-inset-bottom)); }
  .product-detail { padding-bottom: calc(150px + env(safe-area-inset-bottom) * 2); }
}

@media (min-width: 860px) {
  .pd-layout { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 2rem; }
  .product-detail { padding-bottom: 0; }
  .pd-bar {
    position: static;
    max-width: var(--container-max);
    margin: 2rem auto 0;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: .85rem 1rem;
  }
  .pd-bar-btn { flex: 0 1 200px; }
}

/* ==================== 账户充值（user.php） ====================
 * 此前 api/recharge.php + recharge_orders 表已存在，但前台没有充值入口，
 * 用户只能靠后台改余额。这里补上充值面板。
 */
.recharge-card { margin-bottom: 1.25rem; overflow: hidden; }
.recharge-body { padding: 1rem 1.1rem 1.1rem; }

.recharge-amounts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .55rem;
  margin-bottom: .9rem;
}
.recharge-amt {
  min-height: 46px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--text);
  font-size: .95rem;
  font-weight: 600;
  cursor: pointer;
  transition: all .18s;
}
.recharge-amt:hover { border-color: var(--primary); color: var(--primary); }
.recharge-amt.active {
  border-color: var(--primary);
  background: var(--primary-soft);
  color: var(--primary);
}

.recharge-custom {
  position: relative;
  margin-bottom: .9rem;
}
.recharge-cur {
  position: absolute;
  left: .9rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-2);
  font-weight: 600;
  pointer-events: none;
}
.recharge-custom input {
  width: 100%;
  min-height: 46px;
  padding: .6rem .9rem .6rem 1.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font-size: 1rem;
  outline: none;
}
.recharge-custom input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-ring);
}

.recharge-submit { min-height: 46px; font-weight: 600; }
.recharge-tip {
  font-size: .76rem;
  color: var(--text-3);
  margin-top: .7rem;
  text-align: center;
}

@media (min-width: 640px) {
  .recharge-amounts { grid-template-columns: repeat(6, 1fr); }
}
@media (max-width: 768px) {
  .recharge-custom input { font-size: 16px; }
}

/* ==================== 商城工具条 / 搜索 / 分页 ==================== */
.shop-toolbar {
  display: flex;
  gap: .7rem;
  flex-wrap: wrap;
  margin-bottom: 1.1rem;
}

.shop-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 260px;
  min-width: 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0 .4rem 0 0;
  box-shadow: var(--shadow-xs);
  transition: border-color var(--dur), box-shadow var(--dur);
}
.shop-search:focus-within {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-ring);
}
.shop-search > .fas {
  padding: 0 .2rem 0 .95rem;
  color: var(--text-3);
  font-size: .85rem;
}
.shop-search input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  color: var(--text);
  font-size: .9rem;
  padding: .62rem .3rem;
  font-family: inherit;
}
.shop-search button {
  flex-shrink: 0;
  border: none;
  cursor: pointer;
  background: var(--grad-brand);
  color: var(--text-inv);
  font-size: .85rem;
  font-weight: 600;
  padding: .45rem 1.1rem;
  border-radius: var(--radius-pill);
  transition: opacity var(--dur);
}
.shop-search button:hover { opacity: .88; }

/* ---- 价格区间 + 仅看有货 ----
   沿用搜索框的胶囊 + 卡片观感，避免筛选区像从别处搬来的控件。 */
.shop-filter {
  display: flex;
  align-items: center;
  gap: .45rem;
  flex: 0 1 auto;
  flex-wrap: wrap;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: .3rem .5rem .3rem .95rem;
  box-shadow: var(--shadow-xs);
  font-size: .87rem;
  color: var(--text-2);
}

.shop-filter-label {
  color: var(--text-3);
  font-size: .82rem;
  flex-shrink: 0;
}
.shop-filter-sep { color: var(--text-3); }

.shop-filter-price {
  width: 5.2rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  background: var(--bg-soft);
  color: var(--text);
  font-size: .85rem;
  font-family: inherit;
  padding: .34rem .5rem;
  transition: border-color var(--dur), box-shadow var(--dur);
}
.shop-filter-price:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-ring);
}

.shop-filter-stock {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  cursor: pointer;
  white-space: nowrap;
  font-size: .85rem;
}
.shop-filter-stock input { accent-color: var(--primary); cursor: pointer; }

.shop-filter-apply {
  border: none;
  cursor: pointer;
  background: var(--primary-soft);
  color: var(--primary);
  font-size: .85rem;
  font-weight: 600;
  padding: .4rem 1rem;
  border-radius: var(--radius-pill);
  transition: background-color var(--dur), color var(--dur);
}
.shop-filter-apply:hover {
  background: var(--primary);
  color: var(--text-onbrand);
}

/* 窄屏：筛选区单独占一行，输入框与按钮放宽到好点按的尺寸 */
@media (max-width: 640px) {
  .shop-filter { flex: 1 1 100%; }
  .shop-filter-price { width: 4.6rem; min-height: 38px; }
  .shop-filter-apply { min-height: 38px; flex: 1 1 auto; }
}

.shop-sort {
  flex: 0 0 auto;
  padding: .6rem 2rem .6rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--text-2);
  font-size: .87rem;
  font-family: inherit;
  cursor: pointer;
  box-shadow: var(--shadow-xs);
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2395A5A2' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .8rem center;
  background-size: 14px;
}
.shop-sort:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-ring);
}

.shop-result-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  font-size: .84rem;
  color: var(--text-2);
  background: var(--primary-soft);
  border: 1px solid var(--primary-ring);
  border-radius: var(--radius-sm);
  padding: .55rem .9rem;
  margin-bottom: 1rem;
}
.shop-result-bar b { color: var(--primary); font-variant-numeric: tabular-nums; }
.shop-result-bar a { color: var(--text-3); font-size: .8rem; }
.shop-result-bar a:hover { color: var(--danger); }

.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  flex-wrap: wrap;
  margin-top: 2rem;
}
.pager-btn,
.pager-num {
  min-width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 .55rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--text-2);
  font-size: .86rem;
  font-weight: 600;
  transition: all var(--dur) var(--ease);
  font-variant-numeric: tabular-nums;
}
.pager-btn:hover,
.pager-num:hover {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--primary-soft);
}
.pager-num.active {
  background: var(--grad-brand);
  border-color: transparent;
  color: var(--text-inv);
  box-shadow: var(--shadow-brand);
}
.pager-btn.disabled {
  opacity: .4;
  pointer-events: none;
}
.pager-gap { color: var(--text-3); padding: 0 .2rem; }

/* ==================== 结算卡片（购物车） ==================== */
.checkout-card { margin-top: 1rem; }

.checkout-card-more {
  margin-left: auto;
  font-size: .78rem;
  font-weight: 600;
  color: var(--primary);
}
.checkout-card-more:hover { opacity: .75; }

.checkout-card-body { padding: .9rem 1.1rem; }

.addr-empty {
  display: flex;
  align-items: center;
  gap: .7rem;
  flex-wrap: wrap;
  font-size: .86rem;
  color: var(--text-2);
  background: var(--warning-soft);
  border: 1px solid var(--warning-border);
  border-radius: var(--radius-sm);
  padding: .75rem .9rem;
}
.addr-empty > i { color: var(--warning); }
.addr-empty .btn-primary { margin-left: auto; padding: .5rem 1.1rem; font-size: .84rem; }

.addr-picker { display: flex; flex-direction: column; gap: .55rem; }

.addr-option {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .75rem .9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-soft);
  cursor: pointer;
  transition: all var(--dur) var(--ease);
}
.addr-option:hover { border-color: var(--primary); }
.addr-option.active {
  border-color: var(--primary);
  background: var(--primary-soft);
  box-shadow: 0 0 0 3px var(--primary-ring);
}
.addr-option input { position: absolute; opacity: 0; pointer-events: none; }

.addr-option-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .15rem; }
.addr-option-line { font-size: .88rem; color: var(--text-2); }
.addr-option-line strong { color: var(--text); margin-right: .4rem; }
.addr-option-detail { font-size: .8rem; color: var(--text-3); }

.addr-option-tick {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 1px solid var(--border-hover);
  display: flex;
  align-items: center;
  justify-content: center;
  color: transparent;
  font-size: .7rem;
  transition: all var(--dur) var(--ease);
}
.addr-option.active .addr-option-tick {
  background: var(--grad-brand);
  border-color: transparent;
  color: var(--text-onbrand);
}

.addr-tag {
  display: inline-block;
  font-style: normal;
  font-size: .68rem;
  font-weight: 600;
  padding: .1rem .45rem;
  border-radius: var(--radius-xs);
  background: var(--primary-soft);
  color: var(--primary);
  margin-left: .35rem;
}

.checkout-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 1.1rem;
}
.checkout-total { display: flex; align-items: baseline; gap: .6rem; }
.checkout-total span { font-size: .85rem; color: var(--text-2); }
.checkout-total strong {
  font-size: 1.6rem;
  font-weight: 800;
  background: var(--grad-warm);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  font-variant-numeric: tabular-nums;
}
.checkout-balance { font-size: .82rem; color: var(--text-3); }
.checkout-balance b { color: var(--text); font-variant-numeric: tabular-nums; }

.checkout-actions {
  display: flex;
  gap: .6rem;
  flex-wrap: wrap;
  padding: 0 1.1rem 1.1rem;
}
.checkout-actions .btn-primary,
.checkout-actions .btn-alipay { flex: 1 1 160px; min-height: 46px; font-weight: 600; }

.btn-alipay {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: .7rem 1.5rem;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  background: var(--grad-alipay);
  color: var(--text-onbrand);
  font-size: .92rem;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 8px 22px var(--alipay-ring);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
  white-space: nowrap;
}
.btn-alipay:hover {
  color: var(--text-onbrand);
  transform: translateY(-2px);
  box-shadow: 0 12px 28px var(--alipay-ring-2);
}

/* ==================== 收货地址簿（address.php） ==================== */
.addr-page { padding-top: 1.5rem; padding-bottom: 3rem; }

.addr-list { display: flex; flex-direction: column; gap: .8rem; }

.addr-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 1rem 1.1rem;
  transition: all var(--dur) var(--ease);
}
.addr-card:hover { box-shadow: var(--shadow-hover); }
.addr-card.is-default {
  border-color: var(--primary);
  background: linear-gradient(180deg, var(--primary-soft) 0%, var(--card) 60%);
}

.addr-main { margin-bottom: .7rem; }
.addr-line {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  margin-bottom: .3rem;
}
.addr-name { font-weight: 700; font-size: .98rem; color: var(--text); }
.addr-phone { font-size: .88rem; color: var(--text-2); font-variant-numeric: tabular-nums; }
.addr-detail { font-size: .85rem; color: var(--text-2); line-height: 1.6; }

.addr-ops { display: flex; gap: .5rem; flex-wrap: wrap; }
.addr-op {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  min-height: 36px;
  padding: .35rem .8rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--text-2);
  font-size: .8rem;
  cursor: pointer;
  transition: all var(--dur) var(--ease);
}
.addr-op:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-soft); }
.addr-op.danger:hover { border-color: var(--danger); color: var(--danger); background: var(--danger-soft); }

.addr-fab {
  position: fixed;
  right: 18px;
  bottom: calc(78px + env(safe-area-inset-bottom));
  width: 54px;
  height: 54px;
  border: none;
  border-radius: 50%;
  background: var(--grad-brand);
  color: var(--text-onbrand);
  font-size: 1.15rem;
  cursor: pointer;
  box-shadow: var(--shadow-brand);
  z-index: var(--z-fab);
  transition: transform var(--dur) var(--ease);
}
.addr-fab:hover { transform: scale(1.07); }

@media (min-width: 861px) {
  .addr-fab { position: static; margin: 1.2rem auto 0; display: block; }
}

.addr-modal { max-width: 420px; text-align: left; }
.addr-modal .modal-title { text-align: center; margin-bottom: 1rem; }

.addr-check {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: .85rem;
  color: var(--text-2);
  cursor: pointer;
  margin-bottom: 1.1rem;
  user-select: none;
}
.addr-check input { width: 16px; height: 16px; accent-color: var(--primary); }

.addr-modal-ops { display: flex; gap: .6rem; }
.addr-modal-ops .btn-ghost,
.addr-modal-ops .btn-primary { flex: 1; min-height: 44px; }

/* ==================== 主题统一修补 ====================
 * 把散落在各内页组件里的旧硬编码阴影/色值收敛到令牌上。
 */
.svc-card,
.tool-card,
.product-card,
.nav-card { box-shadow: var(--shadow-sm); }

.product-price,
.pd-price-now,
.od-total strong,
.good-price {
  font-variant-numeric: tabular-nums;
}

@media (max-width: 768px) {
  .shop-search { flex-basis: 100%; }
  .shop-sort { flex: 1 1 100%; }
  .checkout-actions .btn-primary,
  .checkout-actions .btn-alipay { flex: 1 1 100%; }
  .addr-op { flex: 1 1 auto; justify-content: center; }
}

/* ==================== 工具中心（tools.php） ==================== */
.tool-search {
  position: relative;
  display: flex;
  align-items: center;
  margin-bottom: 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0 .4rem 0 0;
  box-shadow: var(--shadow-xs);
  transition: border-color var(--dur), box-shadow var(--dur);
}
.tool-search:focus-within {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-ring);
}
.tool-search > .fas {
  padding: 0 .2rem 0 1rem;
  color: var(--text-3);
  font-size: .85rem;
}
.tool-search input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  color: var(--text);
  font-size: .92rem;
  padding: .68rem .3rem;
  font-family: inherit;
}
.tool-search button {
  flex-shrink: 0;
  border: none;
  cursor: pointer;
  background: var(--grad-brand);
  color: var(--text-inv);
  font-size: .85rem;
  font-weight: 600;
  padding: .48rem 1.2rem;
  border-radius: var(--radius-pill);
  transition: opacity var(--dur);
}
.tool-search button:hover { opacity: .88; }

.tool-cats {
  display: flex;
  gap: .5rem;
  overflow-x: auto;
  padding-bottom: .5rem;
  margin-bottom: 1.25rem;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.tool-cats::-webkit-scrollbar { display: none; }

.tool-cat {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .45rem .95rem;
  min-height: 38px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--text-2);
  font-size: .85rem;
  white-space: nowrap;
  transition: all var(--dur) var(--ease);
}
.tool-cat:hover { border-color: var(--primary); color: var(--primary); }
.tool-cat.active {
  background: var(--grad-brand);
  border-color: transparent;
  color: var(--text-inv);
  font-weight: 650;
  box-shadow: var(--shadow-brand);
}
.tool-cat span {
  font-size: .72rem;
  opacity: .7;
  font-variant-numeric: tabular-nums;
}

/* 「推荐工具」区块：后台指定、独立于分类列表，
   故视觉上要能和下面的普通分类区块区分开（暖色标题 + 强调边框）。
   注意它只在「纯浏览态」（无搜索词、无分类筛选）出现，
   且里面的工具已从各自分类中剔除，两边不会重复。 */
.recommended-tools-group {
  padding: 1.1rem 1.15rem .35rem;
  border: 1px solid color-mix(in srgb, var(--warning, #f59e0b) 26%, transparent);
  border-radius: var(--radius-md, 12px);
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--warning, #f59e0b) 7%, transparent),
    transparent 70%
  );
}

.recommended-tools-group .tool-group-title .fas { color: var(--warning, #f59e0b); }

.tool-group { margin-bottom: 2rem; }

.tool-group-title {
  font-size: 1rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: .45rem;
  margin-bottom: 1rem;
}
.tool-group-title .fas { color: var(--primary); }
.tool-group-count {
  font-size: .72rem;
  font-weight: 600;
  color: var(--text-3);
  background: var(--bg-soft);
  border-radius: var(--radius-pill);
  padding: .1rem .5rem;
}

/* 工具中心：横版卡片（左图标 + 右上工具名 / 右下描述）。
   与首页那套竖版 .tool-card 分开 —— 首页是窄侧栏里的两列小格，
   横排在那么窄的列里会被挤成一条，所以这里用 .tool-grid-wide 做作用域，
   只改工具中心，首页不受影响。
   列数：桌面 auto-fill 自适应，1200px 容器下落在 5 列（4~6 之间）；
   768px 以下强制两列（移动端需求）。 */
.tool-grid-wide {
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 12px;
}

/* 卡片尺寸统一：名称恒 1 行 + 描述恒 2 行（见下方 min-height），
   内容高度本身就固定了；这里再补一个 min-height 兜底，字体渲染有差异也不会高低不一。 */
.tool-grid-wide .tool-card {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .7rem .85rem;
  min-height: 76px;
  text-align: left;
}

.tool-grid-wide .tool-card .tool-icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  margin: 0;
  border-radius: var(--radius-sm, 12px);
  background: var(--primary-soft);
  font-size: 1.15rem;
  transition: background var(--dur);
}
/* 悬停时卡片底色变成 --primary-soft，图标块再保持同色就糊成一团，
   翻成实底把它「顶」出来，既保住对比又像一次轻微反馈。 */
.tool-grid-wide .tool-card:hover .tool-icon { background: var(--card); }

.tool-grid-wide .tool-card .tool-body {
  flex: 1;
  min-width: 0;
}

.tool-grid-wide .tool-card .tool-name {
  font-size: 13.5px;
  line-height: 1.3;
  min-height: 1.3em;   /* 名称恒占一行（空名称也不塌），卡片高度才不会飘 */
  font-weight: 650;
  color: var(--text);
  margin-bottom: 2px;
}

/* 描述固定占「两行」的位置 —— 这是卡片尺寸统一的关键。
   只写 line-clamp 只是「最多两行」，1 行的描述会让卡片矮一截，
   同屏里出现 68px / 86px 两种高度，一眼就看出没对齐。
   用 min-height 把两行的高度先占住（line-height 1.45 × 2 = 2.9em），
   超出的部分再交给 line-clamp 截断。 */
.tool-grid-wide .tool-card .tool-desc {
  font-size: 11.5px;
  color: var(--text-3);
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

@media (max-width: 768px) {
  .tool-grid-wide {
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
  }
  .tool-grid-wide .tool-card {gap: .55rem;padding: .6rem .65rem;min-height: 70px;}
  .tool-grid-wide .tool-card .tool-icon { width: 36px; height: 36px; font-size: 1rem; }
  .tool-grid-wide .tool-card .tool-name { font-size: 12.5px; }
  .tool-grid-wide .tool-card .tool-desc {font-size: 11px;}
  .tool-search input { font-size: 16px; }
}

@media (max-width: 420px) {
  .tool-grid-wide .tool-card { gap: .5rem; padding: .55rem .6rem; min-height: 68px; }
  .tool-grid-wide .tool-card .tool-icon { width: 32px; height: 32px; font-size: .95rem; }
}

/* ==================== 移动端顶部区域（内页页头 / 商城工具条 / 商品详情） ====================
 * 小屏常见问题：页头标题偏大撑两行、搜索框与排序挤在一行互相压扁、
 * 商品图区过高把首屏顶下去。这里统一在 768px 以下做一遍收敛。
 */
@media (max-width: 768px) {
  /* 页头：标题降一档，副标题收紧，整体更「贴顶」 */
  .page-header,
  .shop-header {
    padding: .85rem 1rem;
    margin-bottom: 1rem;
    gap: .5rem;
  }
  .page-header h1,
  .shop-header h1 { font-size: 1.15rem; letter-spacing: -.4px; }
  .page-header p,
  .shop-header p { font-size: .82rem; margin-top: .2rem; }
  .page-header .page-header-actions { width: 100%; }

  /* 搜索框独占一行，排序框固定宽度不再被压扁 */
  .shop-toolbar { gap: .55rem; margin-bottom: .9rem; }
  .shop-search { flex: 1 1 100%; }
  .shop-sort { flex: 0 0 auto; min-width: 116px; padding: .55rem 1.8rem .55rem .8rem; }

  /* 商品图：两列网格 + 高度上限，首屏不至于被一张长图占满 */
  .product-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .7rem; }
  .product-card:hover { transform: none; }
  .product-info { padding: .6rem .7rem .8rem; }
  .product-name { font-size: .82rem; }
  .product-price { font-size: .92rem; }

  /* 详情页：图片区限高，价格 / 标题不再被顶到屏幕外 */
  .pd-main-img { aspect-ratio: 4 / 3; }
  .pd-thumbs { margin-top: .5rem; }
  .pd-thumb { width: 52px; height: 52px; }
  .pd-name { font-size: 1.1rem; }
  .pd-price-now { font-size: 1.4rem; }
}

@media (max-width: 480px) {
  .page-header h1,
  .shop-header h1 { font-size: 1.05rem; }
  .shop-notice { font-size: .82rem; padding: .6rem .8rem; }
  .pd-main-img { aspect-ratio: 1; }
}

/* ==================== 账户设置页 ==================== */
.profile-page { max-width: 680px; }

/* ⚠️ 本页「全贴着卡片边框」的总病根：
   `.card` 全局**没有内边距**（body 里只有 .card-title 自带 padding），
   所以卡片正文（头像、表单、按钮）默认零边距、直接顶在卡片边框上。
   其它页面同理，按需给 .checkout-card-body 加 padding（见 content.css:1974）。
   这里也按同一约定，只给设置页加，不动全局 .card。 */
.profile-page .card { padding: 1.15rem 1.25rem 1.35rem; }
/* 标题顶格：负 margin 抵消卡片 padding，下边线仍贯穿整卡，与正文同一缩进 */
.profile-page .card-title {
  margin: -1.15rem -1.25rem .95rem;
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}
/* 头像区分隔线顶格，和 card-title 的下边线对齐成一条通栏线 */
.profile-page .profile-avatar-block {
  margin: 0 -1.25rem;
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}
/* 登录信息里两个表单之间的分隔线同样顶格 */
.profile-page .profile-sep { margin: 1.3rem -1.25rem; }

/* 头像区：左大图 + 右表单。**侧栏必须 flex:1 且 min-width:0**，
   少了就会退化成「内容缩在左边一截、右侧一片空白」，看起来像全贴着边。 */
.profile-avatar-block {
  display: flex;
  align-items: flex-start;
  gap: 1.2rem;
  padding-bottom: 1.3rem;
  border-bottom: 1px solid var(--border);
}

.profile-avatar-big {
  width: 88px;
  height: 88px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--border);
  background: var(--bg-soft);
  flex: 0 0 auto;
}

.profile-avatar-side {
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
}

.profile-upload-row {
  display: flex;
  align-items: center;
  gap: .75rem;
  flex-wrap: wrap;
}

.file-btn { display: inline-flex; align-items: center; cursor: pointer; margin: 0; }
.file-btn[disabled] { opacity: .6; cursor: default; }

.profile-upload-tip { font-size: .78rem; color: var(--text-3); }
.profile-upload-tip-block { margin: .45rem 0 0; }

.profile-avatar-url-group { margin-top: 1rem; margin-bottom: 0; }
.profile-avatar-url-group .form-input { width: 100%; }

.profile-sep {
  border: 0;
  border-top: 1px solid var(--border);
  margin: 1.3rem 0;
}

/* 个人中心卡片：用户名右侧的「设置」按钮 */
.user-name-row {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
}

.user-card-settings {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .8rem;
  padding: .22rem .7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-2);
  text-decoration: none;
}

.user-card-settings:hover {
  color: var(--primary);
  border-color: var(--primary);
}

.user-signature {
  font-size: .82rem;
  color: var(--text-3);
  margin-top: .18rem;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 420px) {
  .profile-page .card { padding: 1rem .9rem 1.15rem; }
  .profile-page .card-title {
    margin: -1rem -.9rem .9rem;
    padding-left: .9rem;
    padding-right: .9rem;
  }
  .profile-page .profile-avatar-block {
    margin: 0 -.9rem;
    padding-left: .9rem;
    padding-right: .9rem;
  }
  .profile-page .profile-sep { margin: 1.1rem -.9rem; }
  .profile-avatar-block { gap: .9rem; }
  .profile-avatar-big { width: 72px; height: 72px; }
}

/* ---- assets/css/tools.css ---- */
/**
 * 工具页共用组件样式 —— 供 tools/ 下 60+ 个独立工具页面使用
 *
 * @description 这些组件（结果卡片 / 标签页 / 上传区 / 状态文字…）在工具页里
 *              被反复使用了几百次，但历史上只有「作者顺手写了内联样式的工具页」
 *              才有样子，其余页面全是浏览器默认外观（裸 input、没边距的裸按钮）。
 *              本文件把它们收拢为一套统一组件，让所有工具页外观一致。
 *
 * 颜色 / 圆角 / 阴影一律取自 design-token.css，因此深色模式自动跟随。
 * 只做「补齐缺失样式」，不改动任何页面的 DOM 结构。
 */

/* ==================== 结果卡片（result-grid / result-card / result-item） ==================== */
/* 用法：<div class="result-grid"> <div class="result-card"><span class="result-label">..</span><span class="result-value">..</span></div> ... </div> */
.result-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
  margin: 12px 0;
}

.result-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 14px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-xs);
  min-width: 0;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.result-card:hover {
  border-color: var(--primary);
  transform: translateY(-1px);
}

.result-label {
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--text-3);
  text-transform: none;
}

.result-value {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  word-break: break-all;
  line-height: 1.4;
}

/* 单行结果条：<div class="result-item"><span>标签</span><code>值</code><button…></div> */
.result-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-xs);
  flex-wrap: wrap;
}
.result-item > span:first-child {
  font-size: .8rem;
  font-weight: 600;
  color: var(--text-3);
  flex: 0 0 auto;
}
.result-item > code {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: .84rem;
  color: var(--text);
  background: var(--bg-soft);
  border-radius: var(--radius-xs);
  padding: 4px 8px;
  word-break: break-all;
}

/* ==================== 二级标签页（工具箱里嵌套一层） ==================== */
/* 一个工具里有「一级分类 → 二级功能」时用：外层照常 .u-tabs 选一级，
   一级面板里再放一个 .u-tabs.u-tabs-sub 选二级，二级面板用 .u-sub-panel。
   JS 侧的坑：一级切换**只能**查 #容器 > .u-tab-btn，不能全局查 .u-tab-btn，
   否则会把二级标签的 active 一起摘掉（切走再切回就白屏）。
   参考实现：tools/formatconvert.php */
.u-tabs.u-tabs-sub {
  margin-bottom: 14px;
  padding-bottom: 8px;
}
.u-tabs.u-tabs-sub .u-tab-btn {
  min-height: 34px;
  padding: 6px 13px;
  font-size: .85rem;
}

.u-sub-panel { display: none; }
.u-sub-panel.active { display: block; }

/* ==================== 遗留前缀标签页（别名，保持旧页面外观一致） ==================== */
/* img-/cl-/bi-/ck-/pr-/rs-/te- 这些前缀的选项卡历史上没有样式，只有 btn-primary/
   btn-secondary 在撑；这里补齐选中态与按钮排布，视觉与 .u-tab-btn 一致。
   注意：这些页面的面板显隐靠各面板自己的内联 style="display:none"（由 JS 切换），
   所以这里**不能**给 -panel 加 display:none，否则会把默认面板也一起隐藏。
   新写的工具不要再加前缀，直接用 .u-tab-btn / .u-tab-panel。
   （fc- 已随「格式转换」改用统一类而退役；.tool-tab-* 那套也随之删掉了。） */
.img-tab, .cl-tab, .bi-tab, .ck-tab,
.pr-tab, .rs-tab, .te-tab {
  font-weight: 600;
}

.img-tab.active, .cl-tab.active, .bi-tab.active, .ck-tab.active,
.pr-tab.active, .rs-tab.active, .te-tab.active {
  box-shadow: var(--shadow-brand);
}

/* ==================== 统一标签页容器 ==================== */
/* 历史上每个工具各写一套前缀（img-/cl-/te-/pr-/rs-/bi-/ck-/texttool- 的 tool-tab-*、
   color-tab-content…），类名不同、功能完全一样。
   现在统一成这一套：一级 .u-tabs/.u-tab-btn/.u-tab-panel，二级 .u-tabs-sub/.u-sub-panel。
   新写的工具直接用这些，别再起新前缀。 */
.u-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding-bottom: 10px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--border);
}

.u-tab-btn {
  appearance: none;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-2);
  font-size: .9rem;
  font-weight: 600;
  font-family: inherit;
  padding: 8px 16px;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: all var(--dur) var(--ease);
  white-space: nowrap;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.u-tab-btn:hover {
  color: var(--primary);
  background: var(--primary-soft);
}
.u-tab-btn.active {
  background: var(--grad-brand);
  color: var(--text-inv);
  box-shadow: var(--shadow-brand);
}

.u-tab-panel { display: none; }
.u-tab-panel.active { display: block; }

/* ==================== 上传区（upload-area） ==================== */
.upload-area {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 32px 16px;
  border: 2px dashed var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-soft);
  color: var(--text-3);
  cursor: pointer;
  text-align: center;
  transition: all var(--dur) var(--ease);
}
.upload-area:hover,
.upload-area.dragover {
  border-color: var(--primary);
  background: var(--primary-soft);
  color: var(--primary);
}
.upload-area > i {
  font-size: 1.9rem;
  opacity: .75;
}
.upload-area > p {
  font-size: .88rem;
  margin: 0;
}

/* ==================== 状态文字 ==================== */
.success-text,
.error-text,
.info-text,
.warning-text {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: .88rem;
  line-height: 1.6;
  margin: 8px 0;
}
.success-text > i, .error-text > i, .info-text > i, .warning-text > i { flex: 0 0 auto; }

.success-text { color: var(--success); }
.error-text   { color: var(--danger); }
.info-text    { color: var(--text-3); }
.warning-text { color: var(--warning); }

.info-text {
  background: var(--info-soft);
  border: 1px solid var(--info-border);
  border-radius: var(--radius-xs);
  padding: 8px 12px;
  display: block;
}

/* ==================== 通用内容分区 ==================== */
.tool-section {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
  padding: 18px;
  margin-bottom: 16px;
}
.tool-section > h3,
.tool-section > h4 {
  font-size: .98rem;
  font-weight: 700;
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.tool-section > h3 > i,
.tool-section > h4 > i { color: var(--primary); }

/* ==================== 输入补充 ==================== */
/* 工具页里大量 <select> 没带 class，浏览器默认外观与已样式化的 .form-input 不一致 */
.tool-page-body select,
.tool-section select {
  appearance: none;
  -webkit-appearance: none;
  padding: 10px 34px 10px 14px;
  font-size: 14px;
  font-family: inherit;
  color: var(--text);
  background-color: var(--card);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2395A5A2' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 15px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.tool-page-body select:focus,
.tool-section select:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-ring);
}

/* 工具页里的 label 默认无间距，和输入框贴在一起 */
.tool-page-body label:not(.form-switch):not(.tool-item) {
  display: inline-block;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
}

/* textarea 默认不能竖向拉伸到乱七八糟的样子，但保留可调整 */
.tool-page-body textarea.form-input { resize: vertical; line-height: 1.6; }
.tool-page-body textarea.form-input[readonly] {
  background: var(--bg-soft);
  color: var(--text-2);
}

/* 等宽输出框（代码 / 哈希 / JSON 结果） */
.tool-page-body .mono,
.tool-page-body code { font-family: var(--font-mono); }

/* ==================== 图标按钮 / 附加按钮 ==================== */
.btn-search,
.btn-locate {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  min-height: 42px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--text-2);
  font-size: .95rem;
  cursor: pointer;
  transition: all var(--dur) var(--ease);
}
.btn-search:hover,
.btn-locate:hover {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--primary-soft);
}

.btn-cancel {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: .7rem 1.5rem;
  font-size: .92rem;
  font-weight: 600;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text-2);
  cursor: pointer;
  transition: all var(--dur) var(--ease);
}
.btn-cancel:hover { border-color: var(--primary); color: var(--primary); }

/* ==================== 工具页专属小元件 ==================== */
/* 符号面板按钮（tools/symbols.php） */
.sy-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  font-size: 1.2rem;
  background: var(--card-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  color: var(--text);
  cursor: pointer;
  transition: all var(--dur) var(--ease);
}
.sy-btn:hover {
  background: var(--primary-soft);
  border-color: var(--primary);
  color: var(--primary);
}

/* ==================== 工具保存失败提示 ==================== */
/* 位于工具页标题下方（tools/_header.php 输出）。
   只在保存失败时显示：默认隐藏（没有 data-state 属性），
   由 assets/js/tool-content-save.js 在失败时打上 data-state="error"。
   保存成功是后台自动行为，不向用户提示，因此没有 ok / idle 态。 */
.tool-save-state {
  display: none;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  padding: 4px 10px;
  font-size: .78rem;
  line-height: 1.4;
  border-radius: var(--radius-pill);
  max-width: 100%;
}
.tool-save-state > i { flex: 0 0 auto; font-size: .8rem; }
.tool-save-state .tool-save-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tool-save-state[data-state="error"] {
  display: inline-flex;
  background: var(--danger-soft);
  color: var(--danger);
}

@media (max-width: 768px) {
  .tool-save-state { font-size: .74rem; padding: 3px 9px; }
  .tool-save-state .tool-save-text { white-space: normal; }
}
/* ==================== 响应式 ==================== */
@media (max-width: 768px) {
  .result-grid { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 8px; }
  .result-card { padding: 10px 12px; }
  .result-value { font-size: .95rem; }

  .u-tabs { gap: 4px; }
  .u-tab-btn {
    font-size: .84rem;
    padding: 7px 13px;
    min-height: 38px;
  }

  .tool-section { padding: 14px; }
  .upload-area { padding: 24px 12px; }
}


/* ==================== 裸控件兜底（只管没写 class 的） ==================== */
/*
 * 为什么需要这一段：
 *   60+ 个工具页里大量 <input> / <button> 是纯裸标签 —— 只有写了
 *   class="form-input" / "btn" 的才吃得到样式，其余全是浏览器默认外观
 *   （灰底方块 input、没圆角没阴影的 button），这就是「很多工具页看着没有层次感」的根源。
 *
 * 为什么用 :not([class])：
 *   只兜底**一个 class 都没有**的控件。凡是页面自己用了组件类
 *   （.form-input / .btn / .tool-* / 自定义类）的一律不碰，不会覆盖既有设计。
 *   想让某个控件保持原样，给它加任意 class 即可。
 */
.tool-page-body input:not([class]),
.tool-page-body textarea:not([class]),
.tool-section input:not([class]),
.tool-section textarea:not([class]) {
  width: 100%;
  padding: 10px 14px;
  font-size: 14px;
  font-family: inherit;
  color: var(--text);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-xs);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.tool-page-body input:not([class])::placeholder,
.tool-page-body textarea:not([class])::placeholder,
.tool-section input:not([class])::placeholder,
.tool-section textarea:not([class])::placeholder { color: var(--text-3); }

.tool-page-body input:not([class]):focus,
.tool-page-body textarea:not([class]):focus,
.tool-section input:not([class]):focus,
.tool-section textarea:not([class]):focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-ring);
}

/* 勾选项/单选项不该被拉成整行 */
.tool-page-body input[type="checkbox"]:not([class]),
.tool-page-body input[type="radio"]:not([class]),
.tool-section input[type="checkbox"]:not([class]),
.tool-section input[type="radio"]:not([class]) {
  width: auto;
  box-shadow: none;
  padding: 0;
}

.tool-page-body button:not([class]),
.tool-section button:not([class]) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 40px;
  padding: 9px 18px;
  font-size: 14px;
  font-family: inherit;
  font-weight: 600;
  color: var(--text-onbrand);
  background: var(--grad-brand);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-xs);
  cursor: pointer;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.tool-page-body button:not([class]):hover,
.tool-section button:not([class]):hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}
.tool-page-body button:not([class]):active,
.tool-section button:not([class]):active { transform: translateY(0); }

/* 裸标题（工具页里直接写 <h3> 的分区标题）给一点层级 */
.tool-page-body h2:not([class]),
.tool-page-body h3:not([class]),
.tool-page-body h4:not([class]) {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 18px 0 10px;
  font-size: .98rem;
  font-weight: 700;
  color: var(--text);
}
.tool-page-body h2:not([class]) > i,
.tool-page-body h3:not([class]) > i,
.tool-page-body h4:not([class]) > i { color: var(--primary); }
