/* QSL 卡片申请网站 —— 全站样式表
   手写、无依赖：不用 CDN、框架或网络字体，完全离线可用。
   移动优先（360px 起可用）；宽表格在窄屏切换为堆叠卡片式布局。

   风格：清透的个人业余电台名片风（浅色 Soft UI）。
   - 背景是浅灰白 / 雾蓝白，带极轻的渐变；大量留白。
   - 内容装在白色大圆角卡片里，配非常柔和的投影和细灰边线，轻盈悬浮。
   - 主色深海军蓝：标题、正文、选中态。
   - 点缀色珊瑚红：像设备指示灯一样**少量**使用（小圆点、主按钮、重要提示）。
   - 不做传统无线电仪表盘、赛博科技风、重工业风或复杂后台风。

   配色规则（改样式请守住这四条）：
   1. --ink / --navy 是主色：标题、主要文字、选中态、导航当前项。
   2. --coral 是点缀色：一屏内只出现一两次，用作「指示灯」小圆点或唯一主按钮。
   3. 状态色只用于状态，且**必须同时有文字**（不能只靠颜色区分）。
   4. 管理页可以提高对比度，但不要引入第二套配色。

   排版：全站无衬线。呼号是视觉主体 —— 大号粗体、字距略紧（--tracking-tight）；
   副标题用小号大写英文或细字中文，并拉大字距（--tracking-wide），做出电台名片感。 */

/* ==== 1. 设计令牌 ======================================================== */
:root {
  /* ==== 清透毛玻璃（Glassmorphism）====
     参考 https://qsl.nebulae.cool 的做法：
     - 底色是很浅的灰白，四角各放一团极淡的彩色光斑（蓝/紫/红/绿），
       光斑既是「通透感」的来源，也是毛玻璃卡片的模糊对象；
     - 内容装在半透明白卡里，配 12–14px 背景模糊和一层几乎看不见的白描边；
     - 文字用近黑的石板色，辅助文字用冷灰，保证在浅底上读得清；
     - 主动作用蓝色实心，是全页唯一的「强色块」。 */

  /* 底色：浅灰白 + 四角柔和光斑 */
  --bg: #f3f4f6;
  --bg-tint-1: #f8fafd;
  --bg-tint-2: #eef3f8;
  --surface: #ffffff;
  --surface-2: #f5f8fc;      /* 卡片图片区底色：冷白 */
  --surface-3: #eaf0f7;

  /* 文字：石板色 + 冷灰
     辅助文字比参考站的 #64748b 再压深一档：#64748b 压在页面底 #f3f4f6 上只有
     4.32，达不到 AA 4.5。深一档后是 5.0+，肉眼几乎看不出差别但合规。 */
  --text: #1e293b;
  --muted: #5b6b80;
  --muted-soft: #5f6e83;

  /* 边框：极淡的冷灰 */
  --border: #e2e8f0;
  --border-strong: #cbd5e1;

  /* 主色：蓝色（参考站 --primary / --primary-dark） */
  --navy: #1e293b;           /* 标题/强调文字 = 石板色 */
  --navy-deep: #0f172a;
  --navy-mid: #3b82f6;       /* 蓝色点缀：图标、链接、焦点环 */
  --navy-bright: #2563eb;
  --navy-soft: rgba(59, 130, 246, 0.16);
  --navy-tint: #eff6ff;      /* blue-50 */
  --navy-tint-strong: #dbeafe;  /* blue-100：核心入口卡底色 */

  /* 行动色：实心按钮用橙红，是整页唯一的强色块，只服务「申请 / 提交 / 确认」
     这类主动作。白字压 #e11d48 是 4.70，达 WCAG AA。
     其余蓝色系令牌（--coral / --navy-mid）继续做点缀，不动。 */
  --coral: #3b82f6;
  --coral-solid: #e11d48;
  --coral-solid-hover: #be123c;
  --coral-deep: #1d4ed8;
  --coral-soft: rgba(59, 130, 246, 0.18);
  --coral-tint: #eff6ff;

  /* 呼号右上角的信号点（参考站用红色发光点） */
  --signal-dot: #ef4444;

  /* 实心按钮上的文字色 */
  --btn-primary-text: #ffffff;
  --btn-brand-text: #ffffff;
  --btn-danger-text: #ffffff;

  /* 毛玻璃：卡片、页头、固定条共用 */
  --glass-bg: rgba(255, 255, 255, 0.72);
  --glass-bg-hover: rgba(255, 255, 255, 0.88);
  --glass-border: rgba(255, 255, 255, 0.85);
  --glass-blur: 14px;
  --glass-shadow: 0 8px 32px rgba(31, 38, 135, 0.07);
  --glass-shadow-hover: 0 16px 44px rgba(31, 38, 135, 0.12);

  /* 页头 / 手机端固定条底色 */
  --header-bg: rgba(255, 255, 255, 0.72);
  --header-bg-solid: #ffffff;
  --cta-bg: rgba(255, 255, 255, 0.86);

  /* 状态色（低饱和，配文字使用） */
  --ok: #1f7a53;
  --ok-tint: #e6f4ec;
  --warn: #8a5a0c;
  --warn-tint: #fbf1de;
  --danger: #c0392b;
  --danger-tint: #fbeceb;
  --neutral: #64748b;
  --neutral-tint: #eef1f5;
  --cancelled: #6b7280;
  --cancelled-tint: #f1f2f4;
  /* 状态胶囊：浅蓝灰 */
  --pill-bg: #edf4fb;
  --pill-text: #34618a;

  /* 投影：毛玻璃本身的投影很轻，靠 blur 和大范围低透明度营造悬浮感 */
  --shadow-xs: 0 1px 2px rgba(31, 38, 135, 0.05);
  --shadow: 0 4px 14px rgba(31, 38, 135, 0.07);
  --shadow-lift: 0 8px 32px rgba(31, 38, 135, 0.07);
  --shadow-hover: 0 18px 44px rgba(31, 38, 135, 0.14);
  --shadow-inset: inset 0 1px 0 rgba(255, 255, 255, 0.75);

  /* 卡片背景：半透明白（真正的毛玻璃在 .card 规则里配 backdrop-filter） */
  --card-bg: var(--glass-bg);
  --card-bg-hover: var(--glass-bg-hover);

  /* 动效：统一 180–240ms，缓动 cubic-bezier(.2,.8,.2,1) */
  --ease-out-soft: cubic-bezier(0.2, 0.8, 0.2, 1);
  --dur-fast: 180ms;
  --dur-base: 220ms;

  /* 大圆角 */
  --radius-lg: 24px;
  --radius: 16px;
  --radius-sm: 12px;
  --radius-pill: 999px;

  /* 卡片图片比例：兜底 3/4（竖版）。每张卡的真实比例由模板写进
     style="--card-ratio: 宽 / 高"，见 Card.aspect_ratio。 */
  --card-ratio: 3 / 4;

  /* 排版 */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Display", "Segoe UI",
    system-ui, "Microsoft YaHei UI", "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB",
    "Source Han Sans SC", "Noto Sans CJK SC", sans-serif;
  --font-mono: ui-monospace, "SFMono-Regular", "Cascadia Mono", Consolas,
    "Liberation Mono", monospace;
  --tracking-tight: -0.02em;   /* 大号呼号：字距略紧 */
  --tracking-wide: 0.14em;     /* 小号大写副标题：字距拉开 */
}

/* ==== 2. 基础排版 ======================================================== */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  /* 背景：浅灰白底 + 四角柔和光斑（参考 qsl.nebulae.cool）。
     四团光斑分别是天蓝、薰衣草紫、淡珊瑚、薄荷绿，透明度 0.4–0.6、50% 处淡出。
     它们既是「通透感」的来源，也是毛玻璃卡片的模糊对象 ——
     如果背景是纯色，backdrop-filter 模糊出来还是纯色，卡片就和实心白卡没区别。 */
  background-color: var(--bg);
  background-image:
    radial-gradient(at 0% 0%, rgba(186, 230, 253, 0.6) 0px, transparent 50%),
    radial-gradient(at 100% 0%, rgba(221, 214, 254, 0.6) 0px, transparent 50%),
    radial-gradient(at 100% 100%, rgba(254, 202, 202, 0.45) 0px, transparent 50%),
    radial-gradient(at 0% 100%, rgba(167, 243, 208, 0.45) 0px, transparent 50%);
  background-attachment: fixed;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  /* 刻意不写 overflow-x: hidden：
     那会把「某处撑破布局」变成静默裁切，反而更难发现。
     正确的做法是让撑破的元素自己收缩（见 .steps li 的 min-width: 0）。 */
}

/* 全站无衬线。标题比正文重、字距略紧，做出「名片」的紧凑感。 */
h1, h2, h3, h4 {
  font-family: var(--font-sans);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: var(--tracking-tight);
  margin: 0 0 0.6em;
  color: var(--navy);
}
h1 { font-size: 1.55rem; }
h2 { font-size: 1.2rem; }
h3 { font-size: 1.02rem; }
h4 { font-size: 0.95rem; }

/* 小号大写英文副标题：字距拉开，营造专业电台名片感。 */
.eyebrow,
.subtitle-cap {
  display: block;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--muted-soft);
  margin: 0 0 6px;
}

/* 呼号：全站视觉主体。大号、粗体、字距略紧。 */
.callsign-display {
  font-family: var(--font-sans);
  font-weight: 800;
  letter-spacing: var(--tracking-tight);
  line-height: 1.05;
  color: var(--navy);
  overflow-wrap: anywhere;
}

p { margin: 0 0 0.85em; }
a { color: var(--navy-mid); text-decoration: none; }
a:hover, a:focus { text-decoration: underline; }
img { max-width: 100%; height: auto; }
hr { border: 0; border-top: 1px solid var(--border); margin: 1.25rem 0; }

.muted { color: var(--muted); }
.small { font-size: 0.875rem; }
.nowrap { white-space: nowrap; }

/* 主内容容器：全站唯一限宽处。 */
.container {
  width: 100%;
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 16px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 20;
  padding: 8px 14px;
  background: var(--navy-bright);
  color: var(--btn-brand-text);
  border-radius: 0 0 var(--radius-sm) 0;
}
.skip:focus { left: 0; }

/* ==== 3. 页头 / 导航 / 页脚 ============================================== */
/* 页头：平时是近乎透明的底（不挡背景光斑），滚动后浮现毛玻璃与底部细边线。 */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition:
    border-color var(--dur-base) ease,
    box-shadow var(--dur-base) ease,
    background-color var(--dur-base) ease;
}
.site-header.is-scrolled {
  background: var(--header-bg);
  border-bottom-color: var(--glass-border);
  box-shadow: 0 4px 18px rgba(31, 38, 135, 0.06);
  backdrop-filter: blur(12px) saturate(160%);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header.is-scrolled { background: var(--header-bg-solid); }
}
.site-header a { color: var(--text); }

.site-header .container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  padding-top: 10px;
  padding-bottom: 10px;
}

/* 站名即呼号：字距略紧、粗体，作为名片抬头。 */
.brand {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-size: 1.02rem;
  font-weight: 800;
  letter-spacing: var(--tracking-tight);
  color: var(--navy);
  white-space: nowrap;
}
.brand:hover { color: var(--navy-mid); text-decoration: none; }
.brand .brand-sub {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--muted-soft);
}

.site-nav { flex: 1 1 100%; order: 3; }
.site-nav ul { display: flex; flex-wrap: wrap; gap: 2px 4px; list-style: none; margin: 0; padding: 0; }
.site-nav a {
  display: inline-block;
  padding: 7px 13px;
  border-radius: var(--radius-pill);
  color: var(--muted);
  font-size: 0.9375rem;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.site-nav a:hover { background: var(--surface-2); color: var(--navy); text-decoration: none; }
.site-nav a.is-current {
  background: var(--navy-tint);
  color: var(--navy);
  font-weight: 600;
}

.header-side { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-left: auto; }
.header-side form { margin: 0; }
.header-link {
  color: var(--muted);
  font-size: 0.875rem;
  padding: 6px 10px;
  border-radius: var(--radius-pill);
}
.header-link:hover { background: var(--surface-2); color: var(--navy); text-decoration: none; }
.header-link-muted { color: var(--muted-soft); }
.header-side .btn {
  background: var(--surface);
  border-color: var(--border-strong);
  color: var(--text);
}
.header-side .btn:hover { background: var(--surface-2); color: var(--text); }

.site-main { padding: 24px 16px 56px; }

.site-footer {
  margin-top: 8px;
  padding: 24px 0;
  border-top: 1px solid var(--border);
  background: transparent;
  color: var(--muted);
  font-size: 0.875rem;
}
.site-footer p { margin: 0 0 4px; }

/* 备案号行：法律要求必须展示，但不该抢视线 —— 用与辅助文字同级的冷灰，
   悬停时加深并出现下划线，明示「可点进工信部备案系统查询」。 */
.site-footer .beian {
  margin-top: 8px;
  font-size: 0.75rem;
}
.site-footer .beian a {
  color: var(--muted-soft);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.site-footer .beian a:hover {
  color: var(--navy-bright);
  border-bottom-color: currentColor;
}
.site-footer .beian .beian-sep {
  margin: 0 6px;
  color: var(--muted-soft);
}

/* ==== 4. 卡片 / 区块 ==================================================== */
/* 毛玻璃卡片基类：半透明白 + 背景模糊 + 一层几乎看不见的白描边。
   参考 qsl.nebulae.cool 的做法 —— 通透感的来源是「背后的彩色光斑被模糊之后
   透过卡片渗出来」，所以卡片本身必须半透明，且背景必须有内容可模糊。
   不支持 backdrop-filter 的浏览器退回接近纯白的实底，保证文字可读。 */
.card,
.form-panel,
.station-hero,
.info-card,
.manage-toolbar,
.action-panel {
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(160%);
  backdrop-filter: blur(var(--glass-blur)) saturate(160%);
  border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .card,
  .form-panel,
  .station-hero,
  .info-card,
  .manage-toolbar,
  .action-panel {
    background: rgba(255, 255, 255, 0.95);
  }
}

.card {
  margin-bottom: 18px;
  padding: 20px 18px;
  border-radius: var(--radius-lg);
}

.card > :last-child { margin-bottom: 0; }

/* 表单专用区域：同样毛玻璃，阴影略强，让填写区成为焦点。 */
.form-panel {
  margin-bottom: 18px;
  padding: 24px 18px;
  border-radius: var(--radius-lg);
  box-shadow: 0 10px 38px rgba(31, 38, 135, 0.09);
}

.card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 14px;
}
.card-head h2, .card-head h3 { margin: 0; }

/* 分组标题：图标在模板里给出（统一线性风格），这里只负责对齐与颜色。 */
.card-head h2 {
  display: flex;
  align-items: center;
  gap: 9px;
}
.card-head h2 .ico { color: var(--navy-mid); font-size: 1.05em; }

.page-title { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.lead { font-size: 1.02rem; color: var(--muted); }
.stack > * + * { margin-top: 12px; }

.kv { display: grid; grid-template-columns: 1fr; gap: 4px 16px; margin: 0; }
.kv dt { color: var(--muted); font-size: 0.875rem; }
.kv dd { margin: 0 0 10px; overflow-wrap: anywhere; }

@media (min-width: 600px) {
  .kv { grid-template-columns: 9rem 1fr; }
  .kv dd { margin-bottom: 0; }
  .kv dt, .kv dd { border-bottom: 1px solid var(--border); padding-bottom: 8px; }
}

.hero-actions { display: flex; flex-wrap: wrap; gap: 10px; margin: 18px 0 6px; }

/* 申请成功页的「接下来」清单：把下一步动作写成明确的几条，
   减少同一人反复填写造成的管理负担。 */
.next-steps {
  margin-top: 16px;
  padding: 14px 16px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--navy-mid);
}
.next-steps-title {
  margin: 0 0 8px;
  font-size: 0.9375rem;
  color: var(--navy);
}
.next-steps-list {
  margin: 0;
  padding-left: 1.15em;
  color: var(--muted);
  font-size: 0.9375rem;
  line-height: 1.7;
}
.next-steps-list li + li { margin-top: 6px; }
.next-steps-list strong { color: var(--text); }

/* ==== 4b. 电台名片 / 呼号展示（主页） ================================== */
/* 呼号是视觉主体：大号粗体、字距略紧。整块是**浅色**的白色大圆角名片，
   而不是深色色块 —— 深色底会显得厚重，与「清透」的整体气质相反。 */
.station-hero {
  position: relative;
  margin-bottom: 18px;
  padding: 34px 22px 28px;
  border-radius: var(--radius-lg);
  text-align: center;
  overflow: hidden;
}
/* 顶部一条极细的渐变线：像设备面板上的波段指示条，克制地点一下色。 */
.station-hero::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, #6366f1, #a855f7, #ec4899);
}

/* 「中华人民共和国个人业余电台」这类小号大写副标题，字距拉开。 */
.station-hero .eyebrow,
.station-hero .station-eyebrow {
  display: block;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--muted-soft);
  margin: 0 0 10px;
}

/* 呼号：参考站的做法是从深到浅的竖向渐变文字 + 末尾一个发光小圆点。
   用 background-clip: text 实现；不支持时自动退回纯色（见下方 @supports）。 */
.station-hero .station-callsign,
.station-hero h1 {
  position: relative;
  display: inline-block;
  margin: 0;
  font-size: clamp(2.6rem, 12vw, 4.2rem);
  font-weight: 800;
  letter-spacing: -0.045em;
  line-height: 1.02;
  color: var(--navy-deep);
  overflow-wrap: anywhere;
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .station-hero .station-callsign,
  .station-hero h1 {
    background: linear-gradient(135deg, #0f172a 0%, #475569 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}

/* 呼号右上角的信号点：红色 + 柔光，像对讲机上的发射指示灯。 */
.callsign-dot {
  position: absolute;
  top: 0.1em;
  right: -0.22em;
  width: 0.09em;
  height: 0.09em;
  min-width: 7px;
  min-height: 7px;
  border-radius: 50%;
  background: var(--signal-dot);
  box-shadow: 0 0 0.14em var(--signal-dot), 0 0 0.4em rgba(239, 68, 68, 0.7);
}

.station-hero .station-name {
  margin: 12px 0 0;
  font-size: clamp(1rem, 3.6vw, 1.2rem);
  font-weight: 600;
  color: var(--text);
  letter-spacing: 0;
}

.station-hero .station-intro {
  margin: 12px auto 0;
  max-width: 46ch;
  color: var(--muted);
  font-size: 0.9375rem;
  line-height: 1.75;
}

.station-hero .hero-actions {
  justify-content: center;
  margin: 22px 0 0;
}

/* 「在线/可换卡」状态小圆点：珊瑚红指示灯，全站只在这里和少量提示出现。 */
.status-dot {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--muted);
}
.status-dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--coral);
  box-shadow: 0 0 0 4px var(--coral-soft);
}
.status-dot.is-idle::before { background: var(--muted-soft); box-shadow: 0 0 0 4px var(--neutral-tint); }

/* ==== 4c. （已移除）主页单张卡片展示框 ==================================
   原来主页顶部有一个「居中大尺寸卡片展示框」（.qsl-showcase / .qsl-frame），
   按用户要求删掉了 —— 主页不再突出某一张卡片，卡片统一在「卡片浏览」页查看。
   相关样式已一并删除，避免留下无用的死代码。
   如需恢复，参考 git 历史里的这一节。 */

/* 联系信息卡片：邮寄地址放在这里，区块内留白清楚。 */
.contact-card { border-left: 3px solid var(--navy-bright); }
.contact-card .contact-row + .contact-row { margin-top: 16px; }
.contact-card .contact-label {
  display: block;
  margin-bottom: 4px;
  color: var(--muted-soft);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}
.contact-card .contact-value { margin: 0; overflow-wrap: anywhere; font-size: 1rem; }
.contact-card .address-block {
  padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  line-height: 1.85;
  /* 地址要便于抄写：用等宽字体让数字与门牌对齐。 */
  font-family: var(--font-mono);
  font-size: 0.9375rem;
}

/* 地址标题行：左侧说明文字，右侧「复制邮寄地址」次级按钮。
   按钮刻意用最轻的次级样式 —— 它是便利功能，不能比「申请 QSL 卡片」更抢眼。 */
.contact-card .contact-label-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px 12px;
  margin-bottom: 6px;
}
.contact-card .contact-label-row .contact-label { margin-bottom: 0; }

.addr-copy {
  padding: 4px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--muted);
  font: inherit;
  font-size: 0.875rem;
  line-height: 1.5;
  cursor: pointer;
  transition:
    color var(--dur-fast) ease,
    border-color var(--dur-fast) ease,
    background-color var(--dur-fast) ease;
}
.addr-copy:hover {
  color: var(--navy-bright);
  border-color: var(--navy-bright);
  background: var(--navy-tint);
}
/* 复制成功：只把文字换成「已复制」并短暂变色，不做动画，避免抢注意力。 */
.addr-copy.is-copied {
  color: var(--ok);
  border-color: var(--ok);
  background: var(--ok-tint);
}
/* 不支持 clipboard API 时脚本会隐藏按钮，而不是留一个点了没反应的按钮。 */
.addr-copy[hidden] { display: none; }

/* ==== 5. 按钮 =========================================================== */
.btn {
  display: inline-block;
  padding: 10px 18px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.72);
  color: var(--text);
  font: inherit;
  line-height: 1.3;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  text-align: center;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.btn:hover { background: var(--surface-2); text-decoration: none; }

/* 主按钮 = 橙红：全站只有「申请 QSL 卡片 / 提交申请 / 确认妥收」这类主动作才用它，
   一屏通常一个。白字压 #e11d48 是 4.70，达 WCAG AA。 */
.btn-primary {
  background: var(--coral-solid);
  border-color: var(--coral-solid);
  color: var(--btn-primary-text);
  font-weight: 600;
  box-shadow: 0 2px 8px rgba(225, 29, 72, 0.26);
}
.btn-primary:hover {
  background: var(--coral-solid-hover);
  border-color: var(--coral-solid-hover);
  color: var(--btn-primary-text);
  box-shadow: 0 4px 14px rgba(225, 29, 72, 0.34);
}

/* 次按钮 = 蓝色实心：用于「查询」「筛选」这类非破坏性动作。
   注意这里不能再用 --navy：它现在是石板色文字，拿来做底色会变成一块近黑的方砖。 */
.btn-brand { background: var(--navy-bright); border-color: var(--navy-bright); color: var(--btn-brand-text); font-weight: 600; }
.btn-brand:hover { background: #1d4ed8; border-color: #1d4ed8; color: var(--btn-brand-text); }

.btn-danger { background: transparent; border-color: var(--danger); color: var(--danger); }
.btn-danger:hover { background: var(--danger); border-color: var(--danger); color: var(--btn-danger-text); }

.btn-small { padding: 7px 14px; font-size: 0.875rem; }
.btn:disabled, .btn[disabled] { opacity: 0.5; cursor: not-allowed; box-shadow: none; }
.btn:disabled:hover, .btn[disabled]:hover { background: var(--surface); }

/* ==== 6. 表单 =========================================================== */
.form-row { margin-bottom: 18px; }
.form-row > label, .field-legend { display: block; font-weight: 600; margin-bottom: 6px; color: var(--text); }
.form-row .help { margin: 6px 0 0; color: var(--muted); font-size: 0.875rem; }

/* 两个短字段同排（邮编 + 电话）。窄屏自动退回上下排列，
   避免手机上两个输入框各剩半屏宽、点不准。 */
.form-row-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 16px;
}
.form-row-pair > .form-row { margin-bottom: 18px; }
@media (max-width: 560px) {
  .form-row-pair { grid-template-columns: 1fr; column-gap: 0; }
}

/* 申请人备注（管理页详情）：保留申请人自己的换行，超长连写也不撑破表格。
   overflow-wrap 用 anywhere 而不是 break-all：只在放不下时才断，正常中文不受影响。 */
.remark-body { white-space: normal; overflow-wrap: anywhere; }

/* 申请列表里的「有备注」小标：低调但能一眼扫到，不去抢状态徽章的注意力。 */
.note-flag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: var(--radius-pill);
  background: var(--coral-tint);
  color: var(--coral-deep);
  font-size: 0.72rem;
  line-height: 1.6;
  white-space: nowrap;
}

/* 必填标记：珊瑚色星号 + 「必填」胶囊，和主按钮同族，形成呼应。
   胶囊文字用 --coral-deep（浅色下 #b93d2f）：压 #fdeeec 有 4.94，
   用原来的 #d95749 只有 3.44，小字不达标。 */
.req { color: var(--coral-deep); font-weight: 700; }
.req-note {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: var(--coral-tint);
  color: var(--coral-deep);
  font-size: 0.75rem;
  font-weight: 600;
  vertical-align: 1px;
}
.optional-tag {
  margin-left: 6px;
  color: var(--muted-soft);
  font-size: 0.8125rem;
  font-weight: 400;
}
.form-section-title {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 26px 0 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
  font-size: 1rem;
}
.form-section-title .ico { color: var(--navy-mid); font-size: 1.05em; }
.form-panel > .form-section-title:first-of-type { margin-top: 0; }
.form-legend { margin: 0 0 20px; color: var(--muted); font-size: 0.875rem; }

/* 表单字段：宽大、圆角、留白足，重点照顾手机点按。 */
input[type="text"], input[type="password"], input[type="email"], input[type="date"],
input[type="search"], input[type="tel"], input[type="number"], input[type="url"],
select, textarea {
  width: 100%;
  max-width: 100%;
  padding: 13px 15px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  line-height: 1.45;
  transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;
}
input[type="text"]:hover, input[type="password"]:hover, input[type="email"]:hover,
input[type="date"]:hover, input[type="search"]:hover, input[type="tel"]:hover,
input[type="number"]:hover, input[type="url"]:hover, select:hover, textarea:hover {
  border-color: var(--navy-bright);
}
input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus,
input[type="date"]:focus, input[type="search"]:focus, input[type="tel"]:focus,
input[type="number"]:focus, input[type="url"]:focus, select:focus, textarea:focus {
  background: var(--surface);
}
textarea { min-height: 6rem; resize: vertical; }

input:focus-visible, select:focus-visible, textarea:focus-visible,
a:focus-visible, button:focus-visible, .btn:focus-visible, .card-option:focus-within {
  outline: 3px solid var(--navy-soft);
  outline-offset: 1px;
  border-color: var(--navy-mid);
}

.field-error { margin: 4px 0 0; padding: 0; color: var(--danger); font-size: 0.875rem; list-style: none; }
.field-error li { margin: 0; }

.form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 8px; }

.filter-bar { display: grid; grid-template-columns: 1fr; gap: 10px 14px; align-items: end; }
.filter-bar .form-row { margin-bottom: 0; }

@media (min-width: 720px) {
  .filter-bar { grid-template-columns: repeat(3, minmax(0, 1fr)) auto auto; }
}

/* 单个输入框 + 按钮的查询条（查询申请页）。 */
.lookup-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 12px; }
.lookup-bar .form-row { flex: 1 1 200px; margin-bottom: 0; }

/* ==== 7. 消息提示 ======================================================= */
.msgs { max-width: 1080px; margin: 0 auto 16px; padding: 0 16px; }
.msgs:empty { display: none; }

.msg {
  margin-bottom: 10px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--muted);
  border-radius: var(--radius-sm);
}
.msg.success { border-left-color: var(--ok); color: var(--ok); }
.msg.error { border-left-color: var(--danger); color: var(--danger); }
.msg.warning { border-left-color: var(--warn); color: var(--warn); }
.msg.info { border-left-color: var(--navy-mid); color: var(--navy); }
.msg.debug { border-left-color: var(--muted); color: var(--muted); }

/* ==== 8. 状态徽章 ======================================================= */
/* 状态永远「文字 + 颜色」双通道：色弱用户也能靠文字分辨。
   徽章左侧带一个小圆点作为色彩锚点，但文字始终在。 */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 11px 3px 9px;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
}
.badge::before {
  content: "";
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.75;
}
/* 状态徽章：文字 + 颜色双通道。
   已寄出=暖橙、已妥收=绿、已取消=灰 —— 语义沿用，只是色值调浅适配毛玻璃底。 */
.badge-pending {
  background: var(--neutral-tint);
  border-color: var(--border-strong);
  color: var(--neutral);
}
.badge-preparing {
  background: var(--navy-tint);
  border-color: var(--border-strong);
  color: var(--navy-bright);
}
.badge-shipped {
  background: var(--warn-tint);
  border-color: rgba(138, 90, 12, 0.28);
  color: var(--warn);
}
.badge-received {
  background: var(--ok-tint);
  border-color: rgba(31, 122, 83, 0.28);
  color: var(--ok);
}
.badge-cancelled {
  background: var(--cancelled-tint);
  border-color: var(--border-strong);
  color: var(--cancelled);
}
.badge-unknown {
  background: var(--surface-2);
  border-color: var(--border);
  color: var(--muted);
}

/* ==== 8c. 查询结果卡片（查询页） ======================================== */
/* 每条申请一张卡：头部是卡片类型/日期/状态，中间是进度条，底部是操作。 */
.query-results { margin: 0; padding: 0; list-style: none; }
.query-results > li + li { margin-top: 14px; }

.query-item {
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
}

.query-item-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px 12px;
  margin-bottom: 6px;
}
.query-item-head .query-cards { font-weight: 700; margin-right: 10px; color: var(--navy); }

.query-item-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}
.query-item-foot form { margin: 0; }

/* ==== 8b. 横向状态进度条 ================================================ */
/* 结构：.steps > .step（四步）+ .step.is-done / .step.is-current / .step.is-cancelled
   圆点之间用 .step::before 画连接线，第一个 step 不画。

   窄屏不要溢出（真实缺陷，已修）：四个中文标签的最窄宽度加起来会超过 360px，
   flex 默认 min-width:auto 不允许收缩，于是整条撑破容器。所以每一步都要
   min-width: 0 并且允许标签换行。 */
.steps {
  display: flex;
  width: 100%;
  margin: 0;
  padding: 4px 0 0;
  list-style: none;
}

.steps li {
  position: relative;
  flex: 1 1 0;
  min-width: 0;             /* 关键：否则 flex 子项不肯收缩，整条会溢出 */
  max-width: 25%;
  padding: 26px 2px 0;
  text-align: center;
}

/* 连接线：从左邻圆点中心画到本圆点中心。 */
.steps li::before {
  content: "";
  position: absolute;
  top: 13px;
  right: 50%;
  width: 100%;
  height: 3px;
  background: var(--border-strong);
}
.steps li:first-child::before { content: none; }

/* 圆点。 */
.steps li::after {
  content: "";
  position: absolute;
  top: 6px;
  left: 50%;
  width: 17px;
  height: 17px;
  margin-left: -8.5px;
  border: 3px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface);
  box-sizing: border-box;
}

.steps .step-label {
  display: block;
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.35;
  overflow-wrap: anywhere;   /* 允许在任意位置断行，窄屏才不会溢出 */
}
.steps .step-date { display: block; color: var(--muted-soft); font-size: 0.75rem; }

/* 每一步的状态同时用「颜色 + 文字」表达：
   - is-done    已完成：深蓝实心 + 标签前加 ✓
   - is-current 当前：深蓝实心 + 光晕 + 标签前加 ● 并加粗
   - todo       未开始：空心灰点
   文字标记让色弱用户同样能分辨，不依赖颜色单独承载信息。 */
.steps li.is-done .step-label::before,
.steps li.is-current .step-label::before {
  display: inline-block;
  margin-right: 3px;
  font-weight: 700;
}
.steps li.is-done .step-label::before { content: "✓"; color: var(--ok); }
.steps li.is-current .step-label::before { content: "●"; color: var(--navy-bright); font-size: 0.7em; }

/* 已完成：深蓝实心点 + 深蓝连接线。 */
.steps li.is-done::before { background: var(--navy-bright); }
.steps li.is-done::after { background: var(--navy-bright); border-color: var(--navy-bright); }
.steps li.is-done .step-label { color: var(--navy-bright); font-weight: 600; }

/* 当前步骤：深蓝圆点 + 外圈光晕。 */
.steps li.is-current::before { background: var(--navy-bright); }
.steps li.is-current::after {
  background: var(--navy-bright);
  border-color: var(--navy-bright);
  box-shadow: 0 0 0 4px var(--navy-soft);
}
.steps li.is-current .step-label { color: var(--navy-bright); font-weight: 700; }

/* 已取消：整条中性灰，表示流程中断（不是「完成」也不是「进行中」）。
   额外用文字标记「×」把「取消」这件事说清楚，不靠灰颜色暗示。 */
.steps.is-cancelled li::before,
.steps.is-cancelled li::after {
  background: var(--surface-3);
  border-color: var(--border-strong);
  box-shadow: none;
}
.steps.is-cancelled li .step-label { color: var(--muted); font-weight: 600; }
.steps.is-cancelled li .step-label::before { content: none; }
.steps.is-cancelled li.is-current .step-label::before {
  content: "×";
  color: var(--muted);
  font-weight: 700;
}

/* 窄屏：四个中文标签会互相挤并撑破容器，因此缩小字号与圆点、收紧间距，
   并给标签留出可换行的宽度。绝不能让页面出现横向滚动。 */
@media (max-width: 560px) {
  .steps li { padding: 22px 1px 0; }
  .steps li::before { top: 11px; height: 2px; }
  .steps li::after {
    top: 5px;
    width: 14px;
    height: 14px;
    margin-left: -7px;
    border-width: 2px;
  }
  .steps li.is-current::after { box-shadow: 0 0 0 3px var(--navy-soft); }
  .steps .step-label { font-size: 0.6875rem; letter-spacing: -0.01em; }
  .steps .step-date { font-size: 0.625rem; }
}

/* 结果卡片在窄屏不要被内部内容撑破。 */
@media (max-width: 560px) {
  .query-item { padding: 12px; }
  .query-item-head { align-items: flex-start; }
  .query-item-head > :first-child { min-width: 0; flex: 1 1 100%; }
  .query-cards { display: block; }
}

/* ==== 9. 卡片目录 / 卡片选择 ============================================ */
/* 卡片图片**按每张卡自己的真实比例**显示，不用统一框高。
   QSL 卡片实物既有竖版也有横版：统一 3/4 会让横版卡上下空掉约 51%（实测），
   写死 3/2 + cover 又会把竖版卡的呼号裁掉。所以比例由模型算出来
   （Card.aspect_ratio），模板写成 style="--card-ratio: 1200 / 1600"，
   样式只负责用它。横版卡片额外跨两列，避免在窄列里被压得很小。

   历史教训（别再改回去）：
   1) 写死 aspect-ratio: 3/2 + object-fit: cover → 竖版卡只显示中间约一半；
   2) 统一 3/4 → 横版卡在竖框里空掉约 51% 高度；
   3) 统一框高 190px → 竖版卡被缩得比横版明显小，视觉上不齐。 */
.card-grid {
  --card-ratio: 3 / 4;         /* 兜底：取不到单卡比例时按竖版 */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.card-grid > li { margin: 0; }

/* 横版卡片跨两列：否则在 200px 宽的列里只能显示成一条细缝。 */
.card-grid > li.is-landscape { grid-column: span 2; }

/* 列宽会随容器变化，窄屏下没有两列可跨，必须退回单列（否则会溢出）。 */
@media (max-width: 420px) {
  .card-grid > li.is-landscape { grid-column: span 1; }
}

/* 图片区：按卡片自己的比例留白，浅灰白底。
   不给不同卡片用不同底色，避免和卡片原图打架。 */
.card-image-frame {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  overflow: hidden;            /* 让图片放大时被框裁切，不撑动布局 */
}

.card-item {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 11px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
}

.card-item img, .card-thumb {
  display: block;
  border-radius: 6px;
}
.card-item img {
  width: 100%;
  height: auto;
  /* 比例来自 --card-ratio（每张卡片自己的真实宽高比，模板里写进 style）；
     取不到时兜底竖版 3/4。contain 保证完整显示，绝不裁掉呼号。 */
  aspect-ratio: var(--card-ratio, 3 / 4);
  object-fit: contain;
}

.card-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 8px;
  border: 1px dashed var(--border-strong);
  color: var(--muted-soft);
  font-size: 0.8125rem;
  text-align: center;
}

/* 卡片名称固定在底部，不随图片比例上下跳动。 */
.card-name {
  display: block;
  margin-top: auto;
  padding-top: 10px;
  font-weight: 700;
  color: var(--navy);
  overflow-wrap: anywhere;
}
.card-note { display: block; margin-top: 3px; color: var(--muted); font-size: 0.875rem; overflow-wrap: anywhere; }

/* 可勾选的卡片选项（申请页）。
   与卡片浏览页用同一套图片展示框（统一高度 + 浅灰白底）。 */
.card-option {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 11px;
  background: var(--card-bg);
  border: 2px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
  cursor: pointer;
}
.card-option:hover {
  border-color: var(--navy-bright);
}

/* 申请页的卡片图与浏览页共用同一套框：按卡片自己的比例 + contain，
   不裁切也不留大片空白。 */
.card-option img {
  width: 100%;
  height: auto;
  aspect-ratio: var(--card-ratio, 3 / 4);
  object-fit: contain;
}

/* 原生复选框：视觉上移除（整张卡可点），但保留在无障碍树里供键盘/读屏使用。 */
.card-option input[type="checkbox"] {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  opacity: 0;
  pointer-events: none;
}

/* 选中态：深蓝描边 + 极浅蓝背景 + 外圈柔光。 */
.card-option:has(input:checked) {
  background: var(--navy-tint);
  border-color: var(--navy-bright);
  box-shadow: 0 0 0 3px var(--navy-soft), var(--shadow);
}

/* 勾选标记：右上角圆形深蓝勾，选中时淡入 + 轻微放大。 */
.card-option::after {
  content: "";
  position: absolute;
  top: 16px;
  right: 16px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: transparent;
  opacity: 0;
  transform: scale(0.7);
  pointer-events: none;
  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='%23ffffff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.5 5.5L20 7'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 15px 15px;
}
.card-option:has(input:checked)::after {
  opacity: 1;
  transform: scale(1);
  background-color: var(--navy-bright);
}

/* 键盘聚焦：整卡显示焦点环（复选框已视觉隐藏，必须在这里补上）。 */
.card-option:focus-within {
  outline: 3px solid var(--navy-soft);
  outline-offset: 2px;
}

/* 回退（不支持 :has() 的浏览器）：勾选后图片/占位框描边。 */
.card-option input:checked + img,
.card-option input:checked ~ img,
.card-option input:checked ~ .card-thumb {
  outline: 3px solid var(--navy-bright);
  outline-offset: 2px;
}
.card-option input:checked { outline: 3px solid var(--navy-bright); outline-offset: 2px; }

/* ==== 10. 表格：窄屏堆叠，宽屏常规；容器内允许横向滚动 =================== */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; margin-bottom: 12px; }

table.data { width: 100%; border-collapse: collapse; background: var(--surface); font-size: 0.9375rem; }
table.data th, table.data td { padding: 9px 10px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }
table.data thead th { background: var(--surface-2); color: var(--muted); font-size: 0.8125rem; font-weight: 600; white-space: nowrap; }
table.data tbody tr:last-child td { border-bottom: 0; }

/* 手机（≤720px）：宽表格改为一张张堆叠卡片，靠 data-label 显示列名。 */
@media (max-width: 720px) {
  .table-wrap { overflow-x: visible; }

  table.data.stack, table.data.stack tbody, table.data.stack tr, table.data.stack td {
    display: block;
    width: 100%;
  }
  table.data.stack thead { display: none; }
  table.data.stack { background: transparent; font-size: 1rem; }

  table.data.stack tr {
    margin-bottom: 12px;
    padding: 8px 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
  }

  table.data.stack td { display: flex; flex-wrap: wrap; gap: 4px 10px; padding: 4px 0; border-bottom: 0; }

  table.data.stack td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 5.5rem;
    color: var(--muted);
    font-size: 0.8125rem;
    line-height: 1.7;
  }

  table.data.stack td[data-label=""] { display: block; }
  table.data.stack td[data-label=""]::before { content: none; }
}

.pager { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 12px; }
.pager .pager-state { color: var(--muted); font-size: 0.875rem; }

/* 表格里的行内表单（查询页的「确认妥收」）不要撑开行高。 */
.table-actions form { margin: 0; }

/* ==== 11. 概览方块与提示条 ============================================== */
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 12px; margin-bottom: 16px; }

.tile {
  display: block;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  color: var(--text);
}
.tile:hover { border-color: var(--navy-bright); text-decoration: none; }
.tile .tile-count { display: block; font-size: 1.5rem; font-weight: 700; line-height: 1.4; }
.tile .tile-label { display: block; color: var(--muted); font-size: 0.875rem; }

.notice {
  margin-bottom: 16px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--navy-mid);
  border-radius: var(--radius-sm);
}
.notice.warn { border-left-color: var(--warn); color: var(--warn); }
.notice.danger { border-left-color: var(--danger); color: var(--danger); }
.notice p:last-child { margin-bottom: 0; }

.admin-only { color: var(--danger); font-size: 0.8125rem; font-weight: 600; }

.thumb-row { display: flex; flex-wrap: wrap; gap: 14px; margin: 0 0 12px; padding: 0; list-style: none; }
.thumb-row li { width: 160px; max-width: 100%; }

/* ==== 11b. 线性图标系统 ================================================ */
/* 统一风格的小图标：只用描边、粗细一致、不带填充，避免混用 Emoji。
   用法：<span class="ico ico-address" aria-hidden="true"></span> 然后后面跟文字。 */
.ico {
  display: inline-block;
  flex: 0 0 auto;
  width: 1.15em;
  height: 1.15em;
  vertical-align: -0.18em;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  /* 用 currentColor 上色：把 SVG 的 stroke 写成 currentColor 不行（背景图拿不到），
     所以用 mask + background-color，这样图标自动跟随文字颜色。 */
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
  -webkit-mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
  mask-size: contain;
}

/* 每个图标的形状由 mask 提供（描边风格、1.75 粗细、圆头圆角）。 */
.ico-address {
  -webkit-mask-image: var(--ico-pin);
  mask-image: var(--ico-pin);
}
.ico-mail {
  -webkit-mask-image: var(--ico-mail);
  mask-image: var(--ico-mail);
}
.ico-phone {
  -webkit-mask-image: var(--ico-phone);
  mask-image: var(--ico-phone);
}
.ico-globe {
  -webkit-mask-image: var(--ico-globe);
  mask-image: var(--ico-globe);
}
.ico-card {
  -webkit-mask-image: var(--ico-card);
  mask-image: var(--ico-card);
}
.ico-search {
  -webkit-mask-image: var(--ico-search);
  mask-image: var(--ico-search);
}
.ico-send {
  -webkit-mask-image: var(--ico-send);
  mask-image: var(--ico-send);
}
.ico-clock {
  -webkit-mask-image: var(--ico-clock);
  mask-image: var(--ico-clock);
}
.ico-note {
  -webkit-mask-image: var(--ico-note);
  mask-image: var(--ico-note);
}

/* 图标形状统一在这里定义（描边风格，currentColor 由 .ico 的 background-color 决定）。 */
:root {
  --ico-pin: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21s7-5.5 7-11a7 7 0 1 0-14 0c0 5.5 7 11 7 11z'/%3E%3Ccircle cx='12' cy='10' r='2.6'/%3E%3C/svg%3E");
  --ico-mail: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='2.5'/%3E%3Cpath d='M3.5 7l8.5 6 8.5-6'/%3E%3C/svg%3E");
  --ico-phone: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.5 3.5h3l1.5 4-2 1.5a12 12 0 0 0 6 6l1.5-2 4 1.5v3a2 2 0 0 1-2.2 2A17 17 0 0 1 4.5 5.7 2 2 0 0 1 6.5 3.5z'/%3E%3C/svg%3E");
  --ico-globe: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M3.5 9.5h17M3.5 14.5h17M12 3.2c2.6 3 2.6 14.6 0 17.6M12 3.2c-2.6 3-2.6 14.6 0 17.6'/%3E%3C/svg%3E");
  --ico-card: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='7.5' y='2.8' width='9' height='18.4' rx='1.8'/%3E%3Cpath d='M9.8 7.2h4.4M9.8 11h4.4M9.8 14.8h2.8'/%3E%3C/svg%3E");
  --ico-search: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.4 15.4L21 21'/%3E%3C/svg%3E");
  --ico-send: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 3L10.5 13.5M21 3l-6.8 18-3.7-7.5L3 9.8 21 3z'/%3E%3C/svg%3E");
  --ico-clock: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7.2V12l3.4 2.1'/%3E%3C/svg%3E");
  --ico-note: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='3.5' width='16' height='17' rx='2.5'/%3E%3Cpath d='M8 9h8M8 12.5h8M8 16h5'/%3E%3C/svg%3E");
}

/* 图标 + 文字的行内组合。 */
.icon-line { display: inline-flex; align-items: flex-start; gap: 9px; }
.icon-line .ico { margin-top: 0.28em; color: var(--navy-mid); }

/* ==== 11c. 管理页：同一设计语言，但提高对比度、强调效率 ================ */
/* 管理页不追求柔美，重点是「读得清、点得准」：
   加深文字与边框、去掉装饰性渐变、压缩留白。 */
.manage .card { box-shadow: var(--shadow-xs); }
.manage h1, .manage h2 { color: var(--navy); }

.manage-toolbar {
  margin-bottom: 18px;
  padding: 16px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
}
.manage-toolbar .filter-bar { gap: 12px 14px; }
.manage-toolbar .toolbar-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.manage-toolbar label { color: var(--text); }

/* 标签行内的补充说明（例如「支持部分匹配」）。
   为什么塞进 label 而不是单独一行 .help：筛选条是 align-items: end 的网格，
   某一列多出一行说明就会被整体顶高，标签和输入框跟相邻列错开约 28px。
   放进 label 里，所有列的行高一致，标签和控件天然对齐。 */
.label-hint {
  margin-left: 8px;
  color: var(--muted-soft);
  font-size: 0.8125rem;
  font-weight: 400;
}

/* 状态操作区：顶部一条珊瑚色线，明确「这里会改变数据」。 */
.action-panel {
  padding: 18px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-top: 3px solid var(--coral);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
}
.action-panel .form-row:last-of-type { margin-bottom: 12px; }

/* 快速状态筛选：胶囊标签，当前项深蓝实心。 */
.status-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 14px; }
.status-chips a {
  display: inline-block;
  padding: 6px 13px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  color: var(--text);
  font-size: 0.8125rem;
  font-weight: 500;
}
.status-chips a:hover { border-color: var(--navy-bright); color: var(--navy); text-decoration: none; }
.status-chips a.is-current {
  background: var(--navy-bright);
  border-color: var(--navy-bright);
  color: var(--btn-brand-text);
  font-weight: 600;
}

/* ==== 13. 卡片交互动效 ================================================== */
/* 目标：卡片「像从卡册里被轻轻抽出」。
   只上移 4–5px、不放大整张卡片；图片单独轻微放大 1.015，制造细腻的层次。
   全站统一 220ms + cubic-bezier(.2,.8,.2,1)。 */

.card,
.card-item,
.card-option,
.query-item,
.tile {
  transition:
    transform var(--dur-base) var(--ease-out-soft),
    box-shadow var(--dur-base) var(--ease-out-soft),
    border-color var(--dur-base) ease;
}

.card:hover,
.card-item:hover,
.card-option:hover,
.query-item:hover {
  transform: translateY(-5px);
  box-shadow: var(--shadow-hover);
  border-color: #b9d0e5;
}

/* 卡片图片框：悬停时出现极淡的深蓝内描边（比外框描边更克制）。 */
.card-item .card-image-frame,
.card-option .card-image-frame {
  transition: box-shadow var(--dur-base) ease;
}
.card-item:hover .card-image-frame,
.card-option:hover .card-image-frame {
  box-shadow: inset 0 0 0 1px rgba(23, 59, 94, 0.14);
}

/* 图片本身轻微放大。放在框里裁切，避免撑动布局。 */
.card-item img,
.card-option img {
  transition: transform var(--dur-base) var(--ease-out-soft);
}
.card-item:hover img,
.card-option:hover img {
  transform: scale(1.015);
}

/* 主按钮「申请 QSL 卡片」：比卡片更明确，但动效更克制（180ms、上移 2px）。 */
.btn-primary {
  transition:
    transform var(--dur-fast) var(--ease-out-soft),
    box-shadow var(--dur-fast) ease,
    background-color var(--dur-fast) ease;
}
.btn-primary:hover {
  transform: translateY(-2px);
  background: var(--coral-solid-hover);
  border-color: var(--coral-solid-hover);
  box-shadow: 0 10px 20px rgba(232, 106, 91, 0.28);
}
.btn-primary:active {
  transform: translateY(0);
  box-shadow: 0 4px 10px rgba(232, 106, 91, 0.2);
}

/* 次级按钮：深蓝文字 + 浅蓝悬停背景（比纯白块更清楚）。 */
.btn {
  transition:
    transform var(--dur-fast) var(--ease-out-soft),
    background-color var(--dur-fast) ease,
    border-color var(--dur-fast) ease,
    color var(--dur-fast) ease,
    box-shadow var(--dur-fast) ease;
}
.btn:not(.btn-primary):not(.btn-brand):not(.btn-danger) {
  color: var(--navy-bright);
  border-color: rgba(59, 130, 246, 0.35);
}
.btn:not(.btn-primary):not(.btn-brand):not(.btn-danger):hover {
  background: #eff6ff;
  border-color: var(--navy-bright);
  color: var(--navy-bright);
  transform: translateY(-1px);
}

/* 导航当前项：背景与颜色平滑切换。 */
.site-nav a,
.status-chips a,
.header-link {
  transition:
    background-color var(--dur-fast) ease,
    color var(--dur-fast) ease,
    border-color var(--dur-fast) ease;
}

/* 输入框聚焦：边框与阴影平滑出现。 */
input[type="text"], input[type="password"], input[type="email"], input[type="date"],
input[type="search"], input[type="tel"], input[type="number"], input[type="url"],
select, textarea {
  transition:
    border-color var(--dur-fast) ease,
    background-color var(--dur-fast) ease,
    box-shadow var(--dur-fast) ease;
}

/* 卡片选中态：描边、背景、勾选标记同步淡入。 */
.card-option::after,
.card-option input[type="checkbox"] {
  transition:
    opacity var(--dur-fast) ease,
    transform var(--dur-fast) var(--ease-out-soft);
}

/* ==== 13b. 首屏入场动画 ================================================ */
/* 标题、卡片、按钮依次淡入；只播一次，滚动不重复触发。
   总时长控制在 350ms 内。

   关键：填充模式必须是 backwards，不能用 both。
   用 both 的话，动画结束后会**永久保留**最后一帧的 transform: translateY(0)，
   而 CSS 动画的优先级高于普通声明 —— 于是 `.info-card:hover { transform:
   translateY(-3px) }` 永远被压住，悬停上移看起来完全没实现（实测位移恒为 0）。
   backwards 只在延迟阶段占位，播完就交还控制权，悬停位移才生效。 */
@keyframes qsl-fade-up {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.enter {
  animation: qsl-fade-up 320ms var(--ease-out-soft) backwards;
}
/* 卡片按 60ms 间隔依次进入（用 --i 控制序号，模板里给）。 */
.enter-item {
  animation: qsl-fade-up 320ms var(--ease-out-soft) backwards;
  animation-delay: calc(var(--i, 0) * 60ms);
}

/* 尊重系统「减少动态效果」：全部直接显示，不做位移与缩放。 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  /* 注意：这里原来还写了一条 .card:hover { transform: none }。
     但整站的卡片悬停位移靠的其实是 :where(.card, .card-item…) 这类规则，
     :where() 优先级为 0，一条普通选择器就能压住它；
     结果这份清单要么漏项、要么互相打架。统一交给下面那条通配规则处理。 */
  .card-item:hover img,
  .card-option:hover img {
    transform: none;
  }
  /* 凡是悬停位移，一律取消；阴影/颜色变化保留（不动画，但反馈还在）。 */
  [class*="card"]:hover,
  [class*="item"]:hover,
  .btn:hover,
  .tile:hover {
    transform: none !important;
  }
}

/* ==== 13c. 主页三张信息卡 ============================================== */
/* 浏览卡片 / 提交申请 / 查询进度。
   「提交申请」用深蓝描边 + 更高权重，突出网站的核心目的。 */
.info-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 18px;
}
@media (max-width: 720px) {
  .info-cards { grid-template-columns: 1fr; gap: 10px; }

  /* 手机上把四角光斑换成一条极简的竖向渐变：
     大面积 fixed 背景 + 多层 radial-gradient 在低端机上会拖慢滚动，
     视觉上在小屏也几乎看不出四角差异（参考站也是这么处理的）。 */
  body {
    background-image: linear-gradient(180deg, #f7f8fa 0%, #eef1f6 100%);
  }
}

.info-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 20px;
  border-radius: var(--radius-lg);
  color: var(--text);
  text-decoration: none;
  /* 整张卡片就是链接：光标与悬停反馈要让人看得出来「这里可以点」。 */
  cursor: pointer;
  transition:
    transform var(--dur-base) var(--ease-out-soft),
    box-shadow var(--dur-base) var(--ease-out-soft),
    background-color var(--dur-base) ease,
    border-color var(--dur-base) ease;
}
.info-card:hover {
  text-decoration: none;
  color: var(--text);
  transform: translateY(-3px);
  background: var(--glass-bg-hover);
  box-shadow: var(--glass-shadow-hover);
}
.info-card:focus-visible {
  outline: 3px solid var(--navy-soft);
  outline-offset: 2px;
}

/* 图标容器：彩色渐变小方块（参考站的 .icon-box 做法）。
   三张卡各用一种颜色，让「浏览 / 申请 / 查询」在余光里就能靠颜色区分；
   颜色只出现在这一小块，不扩散到卡片其他部分。 */
.info-card .info-card-ico {
  width: 2.75rem;
  height: 2.75rem;
  margin-bottom: 10px;
  padding: 0.7rem;
  box-sizing: border-box;
  border-radius: 14px;
  color: #1d4ed8;
  background: linear-gradient(135deg, #bfdbfe 0%, #93c5fd 100%);
  box-shadow: 0 4px 10px rgba(31, 38, 135, 0.08);
}
.info-cards > .info-card:nth-child(2) .info-card-ico {
  color: #b45309;
  background: linear-gradient(135deg, #fde68a 0%, #fcd34d 100%);
}
.info-cards > .info-card:nth-child(3) .info-card-ico {
  color: #15803d;
  background: linear-gradient(135deg, #bbf7d0 0%, #86efac 100%);
}

.info-card .info-card-title {
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--navy);
}

.info-card .info-card-text {
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.6;
}

/* 核心入口「提交申请」：在同样的毛玻璃基底上，用一层更浓的白 + 蓝色描边抬权重。
   不换颜色 —— 三张卡共用一套玻璃质感，只靠「更亮 + 有描边」区分主次。 */
.info-card-primary {
  background: rgba(255, 255, 255, 0.86);
  border-color: rgba(59, 130, 246, 0.45);
  box-shadow: 0 12px 36px rgba(59, 130, 246, 0.16);
}
.info-card-primary:hover {
  background: rgba(255, 255, 255, 0.95);
  border-color: rgba(59, 130, 246, 0.7);
  box-shadow: 0 18px 46px rgba(59, 130, 246, 0.22);
}
.info-card-primary .info-card-title {
  color: var(--navy);
  font-size: 1.12rem;
}
.info-card-primary .info-card-text { color: var(--text); }

/* 手机端单列堆叠时，把「提交申请」提到最上面：
   小屏幕上「先后顺序」比「视觉权重」更能决定用户点哪个。 */
@media (max-width: 720px) {
  .info-card-primary { order: -1; }
}

/* ==== 13d. 状态胶囊 / 移动端固定按钮 ================================== */
/* 「共 3 款在架」这类计数：浅蓝灰胶囊，比单独一行灰字清楚。 */
.status-pill {
  display: inline-block;
  padding: 4px 12px;
  background: var(--pill-bg);
  border-radius: var(--radius-pill);
  color: var(--pill-text);
  font-size: 0.8125rem;
  font-weight: 600;
  white-space: nowrap;
}

/* 手机端：主页与卡片浏览页底部固定「申请 QSL 卡片」按钮。
   申请页不加固定按钮（会挡住表单提交区），所以用 .no-sticky-cta 排除。 */
.mobile-cta { display: none; }
/* 固定条的高度（含安全区内边距）：页脚要让出这段，否则会被压在按钮下面。 */
:root { --cta-h: 64px; }

@media (max-width: 720px) {
  .mobile-cta {
    display: block;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 30;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
    /* 底色走令牌：深色模式必须一起换，否则深色页脚上压一条白条。 */
    background: var(--cta-bg);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-top: 1px solid var(--border);
  }
  .mobile-cta .btn { width: 100%; }

  /* 给固定按钮留出空间：主区域和页脚都要让，否则滚到底时页脚最后两行
     会被固定按钮盖住（实测 360/390px 下页脚呼号那行被压掉一半）。 */
  body.has-mobile-cta .site-main { padding-bottom: 24px; }
  body.has-mobile-cta .site-footer {
    padding-bottom: calc(24px + var(--cta-h) + env(safe-area-inset-bottom, 0px));
  }
}

/* 手机端：申请页提交按钮铺满；桌面端不铺满。 */
@media (max-width: 720px) {
  .form-panel .form-actions .btn-primary { width: 100%; }
}

/* ==== 14. 打印（申请详情页等） ========================================== */
@media print {
  :root {
    --bg: #fff;
    --surface: #fff;
    --surface-2: #fff;
    --text: #000;
    --muted: #444;
    --border: #999;
    --shadow: none;
    --shadow-lift: none;
    --shadow-hover: none;
  }

  body { background: #fff; color: #000; font-size: 12pt; }
  body { background-image: none !important; }

  .skip, .site-header, .site-footer, .no-print, .msgs, .hero-actions, .pager,
  .status-chips, .manage-toolbar, .action-panel { display: none; }
  .container, .site-main { max-width: none; padding: 0; }

  .card, .form-panel { border: 1px solid #999; border-radius: 0; box-shadow: none; break-inside: avoid; }
  .station-hero { background: #fff !important; color: #000; border: 1px solid #999; }
  .station-hero h1, .station-hero .station-callsign, .station-hero .station-intro { color: #000; }
  table.data th, table.data td { border: 1px solid #999; }
  a { color: #000; text-decoration: none; }

  /* 打印时进度条要能看清黑白对比。 */
  .steps li::before, .steps li::after { background: #fff !important; border-color: #000 !important; }
  .steps li.is-done::before { background: #000 !important; }
  .steps li.is-done::after, .steps li.is-current::after { background: #000 !important; }
  .steps .step-label { color: #000 !important; }
}
