/* ==========================================================================
   pr.Web1 —— 通用样式
   移动优先,自 640px / 1024px 断点向上增强;跟随系统深浅色。
   ========================================================================== */

:root {
  --brand-50: #eef4ff;
  --brand-100: #dbe7ff;
  --brand-200: #bdd2ff;
  --brand-400: #6a94f0;
  --brand-500: #3b6fe0;
  --brand-600: #2b57bd;
  --brand-700: #22459a;

  --success-500: #12a06a;
  --success-100: #dcf5ea;
  --warning-500: #c8860d;
  --warning-100: #fdf0d5;
  --danger-500: #d64545;
  --danger-100: #fce4e4;

  /* 资金增减色:沿用国内「增红减绿」惯例(与股票行情一致)。 */
  --money-in: #cf3b3b;
  --money-out: #0f9a63;

  --bg: #f4f6fb;
  --bg-elevated: #ffffff;
  --bg-subtle: #f8fafc;
  --bg-inset: #eef1f7;
  --border: #e2e7f0;
  --border-strong: #cdd6e5;

  --text: #1b2430;
  --text-secondary: #55637a;
  --text-muted: #8a94a6;

  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 18px;
  --shadow-sm: 0 1px 2px rgba(23, 36, 58, 0.06), 0 1px 3px rgba(23, 36, 58, 0.04);
  --shadow: 0 4px 14px rgba(23, 36, 58, 0.08);
  --shadow-lg: 0 18px 48px rgba(23, 36, 58, 0.16);

  --header-h: 56px;

  --font: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
  --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --brand-50: #17243d;
    --brand-100: #1d2f4f;
    --brand-200: #263f6b;
    --brand-400: #6f9bf0;
    --brand-500: #5b8cf0;
    --brand-600: #7ba6f5;
    --brand-700: #9dbcff;

    --success-500: #3ec78e;
    --success-100: #163226;
    --warning-500: #e0ab4a;
    --warning-100: #3a2f14;
    --danger-500: #ef6b6b;
    --danger-100: #3b1f1f;

    /* 深色下的资金增减色:提高明度以保证对比度。 */
    --money-in: #f08387;
    --money-out: #45cd92;

    --bg: #0f141c;
    --bg-elevated: #171e29;
    --bg-subtle: #1b232f;
    --bg-inset: #121924;
    --border: #28323f;
    --border-strong: #3a4553;

    --text: #e8edf5;
    --text-secondary: #a3afc2;
    --text-muted: #78849a;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
    --shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.6);
  }
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

body.has-modal {
  overflow: hidden;
}

h1,
h2,
h3,
p {
  margin: 0;
}

a {
  color: var(--brand-500);
  text-decoration: none;
}

[hidden] {
  display: none !important;
}

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

/* ---------------------------------------------------------------- 布局 --- */

.app-header {
  position: sticky;
  top: 0;
  z-index: 40;
  height: var(--header-h);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 16px;
  background: color-mix(in srgb, var(--bg-elevated) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
}

.app-header__brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
  font-size: 16px;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.app-header__mark {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: linear-gradient(135deg, var(--brand-500), var(--brand-700));
  color: #fff;
  font-size: 14px;
  font-weight: 700;
}

/* 窄屏下隐藏品牌文字,为导航与操作区让出空间。 */
.app-header__title {
  display: none;
}

/*
 * 导航随视口收缩。
 *
 * 导航项总宽是固定的(每项 nowrap),而可用空间随视口变化:实测在 ≤414px 与
 * 640–766px 两个区间内,导航加上品牌与账号区后超出视口,页头整体横向溢出、
 * 右侧「退出」按钮被推出屏幕。640–766px 的区间由品牌文字(≥640px 起显示)
 * 造成,属于既有缺陷,导航项增多后区间进一步扩大。
 *
 * 处理方式:放开 flex 收缩下限并允许横向滚动(滚动条隐藏,不改变页头高度),
 * 使页头始终不溢出,品牌、账号区与退出按钮位置稳定。
 */
.app-header__nav {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -ms-overflow-style: none;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-radius: 999px;
}

.app-header__nav::-webkit-scrollbar {
  display: none;
}

/*
 * 导航可横向滚动时,右缘渐隐:把「被截断的那个入口」柔和淡出,提示后面还有入口。
 *
 * 注意不能用背景渐变遮挡 —— 背景画在元素内容之下,盖不住链接文字;
 * 只有 mask 作用在整层上才有效(代价是胶囊右端轮廓一并淡出,读作「还有内容」)。
 * 标记由 header.js 按实际 scrollWidth 切换,宽度足够时该规则不生效。
 */
.app-header__nav.is-scrollable {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 22px), transparent);
  mask-image: linear-gradient(90deg, #000 calc(100% - 22px), transparent);
}

.nav-link {
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 13px;
  font-size: 13px;
  color: var(--text-secondary);
  text-decoration: none;
  border-radius: 999px;
  white-space: nowrap;
  transition: color 0.16s ease, background 0.16s ease;
  -webkit-tap-highlight-color: transparent;
}

.nav-link:hover {
  color: var(--text);
}

.nav-link.is-active {
  color: #fff;
  font-weight: 500;
  background: var(--brand-500);
}

.app-header__spacer {
  flex: 1;
}

.app-header__user {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 340px;
  padding: 5px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 13px;
  color: var(--text-secondary);
  background: var(--bg-subtle);
}

.app-header__user-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 余额:点击进入资金记录页。 */
.app-header__balance {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding-left: 8px;
  border-left: 1px solid var(--border);
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.16s ease;
  -webkit-tap-highlight-color: transparent;
}

.app-header__balance:hover {
  color: var(--brand-500);
}

.app-header__balance-label {
  font-size: 12px;
  color: var(--text-muted);
}

/* 渠道余额(账号自有渠道在上游的余额):由 header.js 在已配置且启用渠道时注入,
   与平台余额并列,靠自身的左边框作为分隔,不可点击。 */
.app-header__balance--channel {
  cursor: default;
}

.app-header__balance--channel:hover {
  color: var(--text);
}

.app-header__balance--channel .app-header__balance-value {
  color: var(--brand-500);
}

/* 渠道余额的「刷新」按钮:手动跳过后端短缓存、直接查上游。
   默认弱化避免抢注意力,悬停/聚焦点亮;请求中禁用并转圈(复用全局 spin 动画),
   宽度压到 20px,配合 align-self:center 不改变页头行高。 */
.app-header__refresh {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  width: 20px;
  height: 20px;
  padding: 0;
  font-family: inherit;
  font-size: 13px;
  line-height: 1;
  color: var(--text-muted);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: color 0.16s ease, border-color 0.16s ease;
  -webkit-tap-highlight-color: transparent;
}

.app-header__refresh:hover:not(:disabled),
.app-header__refresh:focus-visible {
  color: var(--brand-500);
  border-color: var(--border);
}

.app-header__refresh:focus-visible {
  border-color: var(--brand-500);
  outline: none;
}

.app-header__refresh:disabled {
  cursor: default;
  opacity: 0.6;
}

.app-header__refresh.is-busy {
  animation: spin 0.7s linear infinite;
}

.app-header__balance-value {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* 加载中 / 加载失败时弱化显示,避免被误读为真实余额。 */
.app-header__balance[data-state="loading"] .app-header__balance-value,
.app-header__balance[data-state="error"] .app-header__balance-value {
  font-weight: 400;
  color: var(--text-muted);
}

/* --------------------------------------------------------------- 账号菜单 --- */
/*
 * 一个常驻按钮 + 下拉菜单(渠道配置 / 修改密码 / 退出登录)。
 *
 * 用绝对定位而不是流内展开:菜单展开不应把导航与账号区挤动。
 * 右对齐(top: 100% + 6px; right: 0),因此窄屏下也不会溢出视口右侧。
 *
 * .account-menu 自身不承担显隐职责 —— 触发按钮必须始终可见,
 * 收起/展开只切换 .menu 的 hidden。故这里不设 display,只提供定位上下文。
 */
.account-menu {
  position: relative;
  flex: none;
}

.menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 60;
  min-width: 148px;
  padding: 5px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* 显式声明:若后续给 .menu 加了 display,hidden 会失效。 */
.menu[hidden] {
  display: none;
}

/*
 * 下单页「历史账号」建议下拉:复用 .menu 的卡片样式,锚定在输入框正下方。
 * .field__control 默认不是定位上下文,故用修饰类显式声明 relative。
 */
.field__control--suggest {
  position: relative;
}

.menu--suggest {
  right: auto;
  left: 0;
  min-width: 100%;
  max-height: 216px;
  overflow-y: auto;
}

.menu__item {
  display: block;
  width: 100%;
  padding: 8px 10px;
  font: inherit;
  font-size: 13.5px;
  color: var(--text-secondary);
  text-align: left;
  white-space: nowrap;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: color 0.16s ease, background 0.16s ease;
}

.menu__item:hover,
.menu__item:focus-visible {
  color: var(--text);
  background: var(--bg-inset);
}

/* 退出登录:唯一的破坏性动作,与上方两项的「打开配置」区分开。 */
.menu__item--danger {
  color: var(--danger-500);
}

.menu__item--danger:hover,
.menu__item--danger:focus-visible {
  color: var(--danger-500);
  background: var(--danger-100);
}

.menu__sep {
  height: 1px;
  margin: 5px 4px;
  background: var(--border);
}

/*
 * 主内容区:PC 端全屏自适应。
 *
 * 原实现有 1120px 上限(--app-max),在 1920 / 2560 屏上两侧留出大片空白,
 * 内容既未铺满也未能利用横向空间。现改为**不设宽度上限**,内容随视口铺满,
 * 仅靠分级内边距控制呼吸感(见下方 640 / 1024 / 1280 / 1920 断点)。
 *
 * 约束:页头 .app-header 的左右内边距必须与本文件中的 .app-main 保持同值,
 * 否则页头与内容的左边缘会错位(页头是全宽 flex,没有自己的宽度上限)。
 */
.app-main {
  width: 100%;
  margin: 0 auto;
  padding: 16px;
}

/* 窄屏:仅保留余额(隐藏账号名),保证导航与操作区不被挤压。 */
@media (max-width: 639px) {
  .app-header {
    gap: 8px;
    padding: 0 12px;
  }

  /*
   * 两个余额(平台 / 渠道)在窄屏改为上下两行。
   *
   * 横排时它们各自吃一份宽度:加上渠道余额与刷新按钮后,账号区从 77px 涨到 167px,
   * 导航被压到只剩 86px —— 连第二个导航项都显示不全,链接被拦腰截断,页面看着像排版错乱。
   * 竖排后账号区宽度只取两行中较宽的那行(约 120px),导航能保住约 130px;
   * 两行总高约 43px,仍在 --header-h(56px) 之内,页头高度不变。
   */
  .app-header__user {
    flex-direction: column;
    align-items: flex-end;
    gap: 1px;
    max-width: none;
    padding: 5px 9px;
  }

  .app-header__user-name,
  .app-header__balance-label {
    display: none;
  }

  /*
   * 平台余额是页面主数字,沿用上面的「只显示数值」;
   * 渠道余额必须带标签 —— 否则两串金额堆在一起根本分不清哪个是哪个。
   * 完整标签「渠道余额」在窄屏偏宽,这里用 ::before 输出短标签「渠道」。
   */
  .app-header__balance--channel::before {
    content: "渠道";
    font-size: 12px;
    color: var(--text-muted);
  }

  .app-header__balance {
    padding-left: 0;
    border-left: 0;
  }

  .nav-link {
    padding: 0 10px;
    font-size: 12.5px;
  }
}

/* 更窄的机型上隐藏品牌标记,为导航与余额让位。 */
@media (max-width: 379px) {
  .app-header__mark {
    display: none;
  }
}

@media (min-width: 640px) {
  .app-header {
    padding: 0 24px;
  }

  .app-header__title {
    display: inline;
  }

  .app-main {
    padding: 24px;
  }
}

@media (min-width: 1024px) {
  .app-main {
    padding: 32px 24px 48px;
  }
}

/*
 * 宽屏 / 超宽屏:内边距分级放大,避免内容贴边或大面积空白。
 * 页头与主内容必须同步,保证两者左边缘始终对齐。
 */
@media (min-width: 1280px) {
  .app-header {
    padding: 0 40px;
  }

  .app-main {
    padding: 32px 40px 56px;
  }
}

@media (min-width: 1920px) {
  .app-header {
    padding: 0 56px;
  }

  .app-main {
    padding: 36px 56px 64px;
  }
}

/* ------------------------------------------------ 开关类控件(滑块 / 开关) --- */
/*
 * 两套控件都基于原生表单元素(radio / checkbox),视觉上隐藏原生控件但保留
 * 键盘可达与无障碍语义:空格切换、方向键切换 radio、:focus-visible 显示焦点环。
 *
 *   .switch-seg —— 二选一分段滑块(选项自带文字,选中项用滑块高亮)
 *   .switch     —— 开关(启用 / 禁用)
 */

/* 分段滑块:高亮滑块用 background-image 表达,宽度取 50% 减去内边距,
   切换时只改 background-position —— 无需知道选项的实际像素宽度,
   因此选项文字长度变化也不会错位。 */
.switch-seg {
  position: relative;
  display: inline-flex;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background-color: var(--bg-inset);
  background-image: linear-gradient(var(--bg-elevated), var(--bg-elevated));
  background-repeat: no-repeat;
  background-size: calc(50% - 3px) calc(100% - 6px);
  background-position: 3px 50%;
  transition: background-position 0.18s ease;
}

.switch-seg[data-value='2'] {
  background-position: calc(100% - 3px) 50%;
}

.switch-seg__item {
  position: relative;
  z-index: 1;
  flex: 1 1 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 5px 14px;
  border-radius: 999px;
  font-size: 12.5px;
  color: var(--text-secondary);
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.18s ease;
}

.switch-seg__input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.switch-seg__input:checked + .switch-seg__text {
  color: var(--text);
  font-weight: 600;
}

.switch-seg__input:focus-visible + .switch-seg__text {
  outline: 2px solid var(--brand-400);
  outline-offset: 3px;
  border-radius: 6px;
}

/* 开关:轨道 + 滑块,勾选态用主色强调。 */
.switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}

.switch__input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.switch__track {
  position: relative;
  flex: none;
  width: 40px;
  height: 22px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--bg-inset);
  transition: background-color 0.18s ease, border-color 0.18s ease;
}

.switch__track::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--bg-elevated);
  box-shadow: var(--shadow-sm);
  transition: transform 0.18s ease, background-color 0.18s ease;
}

.switch__input:checked + .switch__track {
  background: var(--brand-500);
  border-color: var(--brand-500);
}

.switch__input:checked + .switch__track::after {
  transform: translateX(18px);
  background: #fff;
}

.switch__input:focus-visible + .switch__track {
  outline: 2px solid var(--brand-400);
  outline-offset: 2px;
}

.switch__text {
  font-size: 12.5px;
  color: var(--text-secondary);
}

.switch__text-on {
  display: none;
}

.switch__input:checked ~ .switch__text .switch__text-on {
  display: inline;
}

.switch__input:checked ~ .switch__text .switch__text-off {
  display: none;
}

/* -------------------------------------------------------------- 外壳页 --- */
/*
 * 外壳页(shell.html):固定页头 + iframe 内容区。
 * 外壳自身不滚动(overflow: hidden),滚动全部发生在 iframe 内,
 * 因此页头在任何滚动位置都可见 —— 不依赖 sticky,内嵌场景下也成立。
 */
body.app-shell-root {
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

body.app-shell-root .app-header {
  /* 头部不参与伸缩,内容区占满剩余高度。 */
  flex: none;
}

.app-shell {
  flex: 1;
  min-height: 0;
  /* 内容区本身不滚动,滚动由 iframe 内部的文档负责。 */
  display: flex;
  overflow: hidden;
}

.app-shell__frame {
  flex: 1;
  display: block;
  width: 100%;
  border: 0;
  background: var(--bg);
}

/*
 * 内容页被外壳 iframe 内嵌时隐藏自身页头(页头由外壳提供),避免双页头。
 * 由 header.js 依据 window.self !== window.top 添加标记。
 */
html.is-embedded .app-header {
  display: none;
}

/* ------------------------------------------------------------ 登录页面 --- */

.auth {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  padding: 24px 16px calc(24px + env(safe-area-inset-bottom, 0px));
  background:
    radial-gradient(1100px 520px at 12% -8%, var(--brand-100), transparent 62%),
    radial-gradient(820px 420px at 100% 108%, var(--brand-50), transparent 60%),
    var(--bg);
}

.auth__panel {
  width: 100%;
  max-width: 420px;
  padding: 28px 22px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.auth__head {
  margin-bottom: 22px;
  text-align: center;
}

.auth__logo {
  display: inline-grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin-bottom: 14px;
  border-radius: 15px;
  background: linear-gradient(135deg, var(--brand-500), var(--brand-700));
  color: #fff;
  font-size: 20px;
  font-weight: 700;
  box-shadow: 0 10px 24px rgba(43, 87, 189, 0.28);
}

.auth__title {
  font-size: 21px;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.auth__subtitle {
  margin-top: 6px;
  font-size: 13.5px;
  color: var(--text-muted);
}

.auth__footer {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px dashed var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 12.5px;
  color: var(--text-muted);
}

.auth__endpoint {
  font-family: var(--font-mono);
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (min-width: 640px) {
  .auth__panel {
    padding: 36px 32px;
  }
}

/* -------------------------------------------------------------- 表单 --- */

.field {
  margin-bottom: 16px;
}

.field__label {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
}

.field__req {
  color: var(--danger-500);
  margin-left: 2px;
}

.field__control {
  position: relative;
  display: flex;
  align-items: center;
}

.input {
  width: 100%;
  min-height: 46px;
  padding: 11px 13px;
  font-family: inherit;
  font-size: 15px;
  color: var(--text);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  transition: border-color 0.16s ease, box-shadow 0.16s ease, background 0.16s ease;
  appearance: none;
}

.input::placeholder {
  color: var(--text-muted);
}

.input:hover {
  border-color: var(--border-strong);
}

.input:focus {
  outline: none;
  background: var(--bg-elevated);
  border-color: var(--brand-500);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-500) 18%, transparent);
}

.input.is-invalid {
  border-color: var(--danger-500);
}

.input.is-invalid:focus {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger-500) 18%, transparent);
}

.input--password {
  padding-right: 60px;
}

.field__toggle {
  position: absolute;
  right: 6px;
  height: 34px;
  padding: 0 10px;
  font-size: 12.5px;
  color: var(--text-secondary);
  background: transparent;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
}

.field__toggle:hover {
  color: var(--brand-500);
  background: var(--bg-inset);
}

.field__error {
  display: block;
  min-height: 0;
  margin-top: 5px;
  font-size: 12.5px;
  color: var(--danger-500);
}

.field__error:empty {
  display: none;
}

.field__hint {
  margin-top: 5px;
  font-size: 12.5px;
  color: var(--text-muted);
}

/* 电费户号的「所属地区」提示:复用 .field__hint,用颜色区分识别结果。 */
.field__hint--area.is-ok {
  color: var(--success-500);
}

.field__hint--area.is-warn {
  color: var(--warning-500);
}

.field-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 4px 0 20px;
}

.checkbox {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
  color: var(--text-secondary);
  cursor: pointer;
  user-select: none;
}

.checkbox input {
  width: 16px;
  height: 16px;
  accent-color: var(--brand-500);
  cursor: pointer;
}

/* -------------------------------------------------------------- 按钮 --- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 44px;
  padding: 10px 18px;
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--text);
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.16s ease, border-color 0.16s ease, color 0.16s ease, transform 0.1s ease,
    box-shadow 0.16s ease;
  -webkit-tap-highlight-color: transparent;
}

.btn:hover:not(:disabled) {
  background: var(--bg-inset);
}

.btn:active:not(:disabled) {
  transform: translateY(1px);
}

.btn:disabled {
  opacity: 0.62;
  cursor: not-allowed;
}

.btn--primary {
  color: #fff;
  background: linear-gradient(135deg, var(--brand-500), var(--brand-600));
  border-color: transparent;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--brand-600) 26%, transparent);
}

.btn--primary:hover:not(:disabled) {
  background: linear-gradient(135deg, var(--brand-600), var(--brand-700));
  box-shadow: 0 6px 16px color-mix(in srgb, var(--brand-600) 34%, transparent);
}

.btn--block {
  width: 100%;
}

.btn--sm {
  min-height: 36px;
  padding: 7px 13px;
  font-size: 13.5px;
}

.btn--icon {
  min-height: 36px;
  padding: 7px 11px;
  font-size: 13.5px;
}

/*
 * 行内极简按钮:用于「已收款」徽标旁的「取消」这类次级入口。
 *
 * 常规 .btn--sm 的内边距与字号会让它与徽标一起超出「操作」列内容宽
 * (150px 列宽下内容区 122px,徽标 67px + 按钮 53px + 间隙 = 124px)从而折行、
 * 把整行撑高。这里压缩内边距与字号,保证两者同处一行。
 */
.btn--compact {
  min-height: 26px;
  padding: 3px 8px;
  font-size: 12.5px;
}

.btn.is-loading {
  pointer-events: none;
  opacity: 0.8;
}

.btn__spinner {
  width: 14px;
  height: 14px;
  border: 2px solid color-mix(in srgb, currentColor 32%, transparent);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* --------------------------------------------------------- 页面工具栏 --- */

.toolbar {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 16px;
}

.toolbar__heading h1 {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.toolbar__heading p {
  margin-top: 3px;
  font-size: 13px;
  color: var(--text-muted);
}

/*
 * 工具栏操作区。
 *
 * 必须允许换行:管理员在订单页会多出「查看范围」切换(我的订单 / 全部用户),
 * 这一行的最小宽度实测达 503px —— 390 / 360 / 320 三档窄屏下 nowrap 会把整个
 * 文档撑宽(390 视口下文档 519px,横向溢出 129px),于是整页被推偏、卡片里的
 * 字段名被挤出屏幕,看着像布局错乱。其余同类操作行(.card__actions /
 * .filters__quicks / .row-actions / .result__actions)本就都带换行,此处补齐一致。
 */
.toolbar__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.toolbar__actions .btn--primary {
  flex: 1;
}

@media (min-width: 640px) {
  .toolbar {
    flex-direction: row;
    align-items: flex-end;
    justify-content: space-between;
  }

  .toolbar__heading h1 {
    font-size: 22px;
  }

  .toolbar__actions .btn--primary {
    flex: none;
  }
}

/* ------------------------------------------------------------ 统计条 --- */

.stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 16px;
}

.stat {
  padding: 12px 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.stat__label {
  font-size: 12px;
  color: var(--text-muted);
}

.stat__value {
  margin-top: 2px;
  font-size: 19px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

@media (min-width: 640px) {
  .stats {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* ------------------------------------------------------------ 筛选栏 --- */

.filters {
  margin-bottom: 16px;
  padding: 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.filters__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.filters__grid .field {
  margin-bottom: 0;
}

.filters__grid .input {
  min-height: 42px;
  padding: 9px 12px;
  font-size: 14px;
}

/* 日期控件在 iOS 上默认高度偏小,统一对齐。 */
.filters__grid input[type="date"] {
  min-height: 42px;
  line-height: 1.4;
}

.filters__foot {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
}

.filters__quicks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* 订单状态多选:芯片组跟在输入框位置,换行排布;校验占位对齐其它字段。 */
.filters__states {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-height: 38px;
  align-items: center;
}

/* 工具栏内的统计行:订单数量与金额合计,弱化显示避免与标题抢注意力。 */
.toolbar__summary {
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--text-muted);
}

/*
 * 副标题里的「筛选:…」描述:窄屏隐藏。
 *
 * 该描述会在状态多选时展开成一长串(如「筛选:状态 已完成、待完成、申请退款、部分成功」),
 * 窄屏下把副标题撑成两行、把列表整体往下压;而筛选栏里的状态芯片与「筛选」按钮上的
 * 计数角标已表达了同一信息,重复展示只会显得杂乱。
 */
@media (max-width: 639px) {
  .toolbar__filters-summary {
    display: none;
  }
}

.filters__actions {
  display: flex;
  gap: 8px;
}

.filters__actions .btn {
  flex: 1;
}

.chip {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 11px;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--text-secondary);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.16s ease, border-color 0.16s ease, background 0.16s ease;
  -webkit-tap-highlight-color: transparent;
}

.chip:hover {
  color: var(--brand-500);
  border-color: var(--brand-500);
}

.chip.is-active {
  color: #fff;
  background: var(--brand-500);
  border-color: var(--brand-500);
}

.filter-badge {
  display: inline-grid;
  place-items: center;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  margin-left: 5px;
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  color: #fff;
  background: var(--brand-500);
  border-radius: 999px;
}

@media (min-width: 640px) {
  .filters__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  /* 条件少于 4 个时按实际数量铺列,避免出现空槽。 */
  .filters__grid--three {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  /*
   * 订单页有 6 个条件(充值账号 / 订单状态 / 支付方式 / 是否已收款 / 创建时间起止):
   *   640–1279px 铺 3 列(两行 3+3),1280px 起铺 6 列(见下方 1280 断点,单行铺满);
   *   管理员「全部用户」范围另有「下单账号」共 7 个条件,统一按 4 列铺(两行 4+3)。
   */
  .filters__grid--six {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  html.is-all-scope .filters__grid--six {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .filters__foot {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }

  .filters__actions .btn {
    flex: none;
    min-width: 88px;
  }
}

/* 宽屏:6 个条件单行铺满,「创建时间(止)」不会被拆到第二行。 */
@media (min-width: 1280px) {
  .filters__grid--six {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

/* 移动端默认收起,由「筛选」按钮展开。 */
@media (max-width: 639px) {
  .filters {
    display: none;
  }

  .filters.is-open {
    display: block;
  }
}

/* -------------------------------------------------------------- 卡片 --- */

.card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-subtle);
}

.card__title {
  font-size: 14.5px;
  font-weight: 600;
}

.card__count {
  font-size: 12.5px;
  color: var(--text-muted);
}

/* ------------------------------------------------------------ 数据表 --- */

.table-wrap {
  width: 100%;
  overflow-x: auto;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.data-table th,
.data-table td {
  padding: 12px 14px;
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--border);
}

.data-table th {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
  background: var(--bg-subtle);
}

.data-table tbody tr:last-child td {
  border-bottom: 0;
}

.data-table tbody tr:hover td {
  background: var(--bg-subtle);
}

.data-table .col-code {
  font-family: var(--font-mono);
  font-size: 12.5px;
  white-space: nowrap;
}

.data-table .col-time {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
}

.cell-primary {
  font-weight: 500;
}

.cell-sub {
  display: block;
  margin-top: 1px;
  font-size: 12px;
  color: var(--text-muted);
}

/* 金额列:表头右对齐,数字等宽并右对齐,便于纵向比对。 */
.data-table th.col-amount {
  text-align: right;
}

.data-table td.cell-amount {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* 订单备注:PC 端限宽单行省略(全文保留在 title),移动端由下方媒体查询放开换行。 */
.data-table td.col-remark {
  max-width: 260px;
  color: var(--text-secondary);
}

/* -------------------------------------------------- 订单表列宽(宽屏) --- */
/*
 * 订单表有 11 列,其中「订单编号」(18 位单号)、「重试次数」(耗时 HH:mm:ss)
 * 与两个时间列都是不可断行内容,其最小宽度是硬性的;「产品」列内容可逐字换行,
 * 最小宽度几乎为 0。自动布局在容器不够宽时会把产品列压到最窄并折成 2~3 行,
 * 该行因此明显高于其他行。
 *
 * 宽屏下改用固定布局,按 colgroup 声明的宽度分配:不可断行列保持 nowrap,
 * 产品名单行省略(全文见 title),剩余宽度全部给备注列。窗口窄于表格最小宽度
 * 时由 .table-wrap 横向滚动兜底(移动端 ≤767px 已转卡片,不受此影响)。
 *
 * 固定列合计 1188px(含「操作」列 150px),配 150px 备注 → 最小宽度 1338px;
 * 管理员「全部用户」范围另有「下单账号」列 150px → 最小宽度 1488px。
 * 主内容区已取消旧的 1120px 上限(PC 端全屏自适应),备注列吃掉全部剩余宽度:
 * 1440px 视口约 100px、1920px 约 580px、2560px 约 1220px —— 窗口越宽备注越完整。
 *
 * 「操作」列 150px:该列现在要同时容纳「已收款」徽标与「取消」按钮(已完成且已收款的行),
 * 120px 会把两者挤到折行、行高被撑高。
 */
/*
 * 管理员「全部用户」订单范围的专属内容:下单账号筛选条件与列表列。
 *
 * 默认(非该范围)一律隐藏 —— 用 html:not(.is-all-scope) 提高优先级,是为了压过
 * 移动端把 td 改成 flex 卡片的 `.data-table td { display: flex }`,否则窄屏下
 * 该列会始终显示。范围标记由 orders.js 在确认管理员身份并切到该范围后加上。
 */
html:not(.is-all-scope) .field--account,
html:not(.is-all-scope) .col-user {
  display: none;
}

@media (min-width: 768px) {
  .data-table--orders {
    table-layout: fixed;
    min-width: 1338px;
  }

  /* 「操作」列(退单申请 / 标记已收款 / 取消已收款):定宽 150px。 */
  .data-table--orders .colw-action {
    width: 150px;
  }

  /* 「下单账号」列(仅全部用户范围存在):定宽 150px,并把表格最小宽度抬高同值,
     避免其余固定列被压窄。 */
  .data-table--orders .colw-user {
    width: 150px;
  }

  /* 多一列「下单账号」(150px):最小宽度同步抬高,避免其余列被压窄。 */
  html.is-all-scope .data-table--orders {
    min-width: 1488px;
  }

  .data-table--orders .colw-code {
    width: 168px;
  }

  .data-table--orders .colw-product {
    width: 168px;
  }

  .data-table--orders .colw-amount {
    width: 92px;
  }

  .data-table--orders .colw-phone {
    width: 118px;
  }

  .data-table--orders .colw-state {
    width: 92px;
  }

  /* 「重试次数」列上下两行:次数 + 累计耗时 HH:mm:ss。 */
  .data-table--orders .colw-retry {
    width: 108px;
  }

  .data-table--orders .colw-time {
    width: 146px;
  }

  /* 产品名单行省略,与其余列保持同一行高基线。 */
  .data-table--orders td.cell-product .cell-name {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* 固定布局下列宽已由 colgroup 决定,解除备注列的限宽。 */
  .data-table--orders td.col-remark {
    max-width: none;
  }
}

.cell-truncate {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.amount {
  font-weight: 600;
}

.amount--in {
  color: var(--money-in);
}

.amount--out {
  color: var(--money-out);
}

/* 移动端:表格转为卡片布局 */
@media (max-width: 767px) {
  .data-table thead {
    display: none;
  }

  .data-table,
  .data-table tbody,
  .data-table tr,
  .data-table td {
    display: block;
    width: 100%;
  }

  .data-table tbody tr {
    position: relative;
    margin: 0;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border);
  }

  .data-table tbody tr:last-child {
    border-bottom: 0;
  }

  .data-table tbody tr:hover td {
    background: transparent;
  }

  .data-table td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 3px 0;
    border: 0;
    text-align: right;
  }

  .data-table td::before {
    content: attr(data-label);
    flex: none;
    font-size: 12.5px;
    color: var(--text-muted);
    text-align: left;
  }

  .data-table td.cell-lead {
    display: flex;
    align-items: center;
    padding-bottom: 8px;
    margin-bottom: 8px;
    border-bottom: 1px dashed var(--border);
    text-align: left;
  }

  .data-table td.cell-lead::before {
    display: none;
  }

  .data-table .col-code {
    white-space: normal;
    word-break: break-all;
  }

  /* 卡片模式下备注随宽度换行,避免省略号让内容不可见。 */
  .data-table td.col-remark {
    max-width: none;
  }

  /*
   * 备注往往较长(上游回调写入的失败原因等),换行是常态。
   * 沿用「标签 + 右对齐内容」的 flex 行,换行后左边缘参差不齐,长备注像排版错乱;
   * 这里改为「标签独占一行 + 内容整行左对齐换行」,与卡片里其它短字段互不影响。
   */
  .data-table td.col-remark {
    display: block;
    text-align: left;
  }

  .data-table td.col-remark::before {
    display: block;
    margin-bottom: 2px;
  }

  .data-table .col-remark .cell-truncate {
    white-space: normal;
    overflow: visible;
    word-break: break-word;
  }

  /* 卡片模式下隐藏空的收 / 支行,减少噪声(另一方向非零即为资金方向)。 */
  .data-table td.cell-amount.is-empty {
    display: none;
  }
}

/* -------------------------------------------------------------- 徽章 --- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.5;
  border-radius: 999px;
  white-space: nowrap;
  border: 1px solid transparent;
}

.badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.badge--success {
  color: var(--success-500);
  background: var(--success-100);
  border-color: color-mix(in srgb, var(--success-500) 24%, transparent);
}

.badge--pending {
  color: var(--brand-600);
  background: var(--brand-50);
  border-color: color-mix(in srgb, var(--brand-500) 24%, transparent);
}

.badge--warning {
  color: var(--warning-500);
  background: var(--warning-100);
  border-color: color-mix(in srgb, var(--warning-500) 26%, transparent);
}

.badge--danger {
  color: var(--danger-500);
  background: var(--danger-100);
  border-color: color-mix(in srgb, var(--danger-500) 26%, transparent);
}

.badge--muted {
  color: var(--text-muted);
  background: var(--bg-inset);
  border-color: var(--border);
}

/* -------------------------------------------------------- 空态 / 骨架 --- */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 52px 20px;
  text-align: center;
}

.empty__icon {
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 16px;
  background: var(--bg-inset);
  color: var(--text-muted);
}

.empty__title {
  font-size: 15px;
  font-weight: 600;
}

.empty__text {
  max-width: 320px;
  font-size: 13px;
  color: var(--text-muted);
}

.empty__action {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 10px;
}

.skeleton-row {
  display: flex;
  gap: 16px;
  padding: 14px;
  border-bottom: 1px solid var(--border);
}

.skeleton {
  display: block;
  height: 12px;
  border-radius: 6px;
  background: linear-gradient(90deg, var(--bg-inset) 25%, var(--border) 37%, var(--bg-inset) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
}

.skeleton--line {
  flex: 1;
}

@keyframes shimmer {
  0% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0 50%;
  }
}

/* -------------------------------------------------------------- 分页 --- */

.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  border-top: 1px solid var(--border);
  background: var(--bg-subtle);
}

.pager__info {
  font-size: 12.5px;
  color: var(--text-muted);
  white-space: nowrap;
}

.pager__controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pager__page {
  min-width: 68px;
  font-size: 13px;
  text-align: center;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 479px) {
  .pager {
    flex-direction: column;
    align-items: stretch;
  }

  .pager__controls {
    justify-content: space-between;
  }

  .pager__controls .btn {
    flex: 1;
  }
}

/* ------------------------------------------------------------ 模态框 --- */

.modal {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0;
  background: rgba(15, 20, 28, 0.5);
  backdrop-filter: blur(2px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.22s ease, visibility 0.22s ease;
}

.modal.is-open {
  opacity: 1;
  visibility: visible;
}

.modal__dialog {
  width: 100%;
  max-width: 480px;
  max-height: 90vh;
  max-height: 90dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  box-shadow: var(--shadow-lg);
  transform: translateY(16px);
  transition: transform 0.26s cubic-bezier(0.32, 0.72, 0, 1);
}

.modal.is-open .modal__dialog {
  transform: translateY(0);
}

.modal__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 18px 18px 14px;
  border-bottom: 1px solid var(--border);
}

.modal__title {
  font-size: 16.5px;
  font-weight: 600;
}

.modal__desc {
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--text-muted);
}

/*
 * 弹层正文里的一行弱化说明(如「目标账号:…」)。
 *
 * 不能复用 .card__note:它带 --bg-subtle 底色 + 边框 + 圆角,视觉上等同于一个
 * 禁用的输入框 —— 放在表单字段下方会被读成「这里本该填东西但填不了」。
 * 这行文字只是标明操作对象,不需要「可输入」的暗示。
 */
.modal__meta {
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--text-muted);
}

.modal__close {
  flex: none;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  font-size: 18px;
  line-height: 1;
  color: var(--text-muted);
  background: transparent;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
}

.modal__close:hover {
  color: var(--text);
  background: var(--bg-inset);
}

.modal__body {
  flex: 1;
  overflow-y: auto;
  padding: 18px;
  -webkit-overflow-scrolling: touch;
}

.modal__foot {
  display: flex;
  gap: 10px;
  padding: 14px 18px calc(14px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--border);
  background: var(--bg-subtle);
}

.modal__foot .btn {
  flex: 1;
}

@media (min-width: 640px) {
  .modal {
    align-items: center;
    padding: 24px;
  }

  .modal__dialog {
    border-radius: var(--radius-lg);
    transform: translateY(10px) scale(0.98);
  }

  .modal.is-open .modal__dialog {
    transform: translateY(0) scale(1);
  }

  .modal__foot {
    justify-content: flex-end;
  }

  .modal__foot .btn {
    flex: none;
    min-width: 104px;
  }
}

/* -------------------------------------------------------------- 提示 --- */

.toast-host {
  position: fixed;
  top: calc(12px + env(safe-area-inset-top, 0px));
  left: 50%;
  z-index: 120;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: calc(100% - 24px);
  max-width: 400px;
  transform: translateX(-50%);
  pointer-events: none;
}

.toast {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 14px;
  font-size: 13.5px;
  color: var(--text);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity 0.22s ease, transform 0.22s ease;
  pointer-events: auto;
  cursor: pointer;
}

.toast.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.toast__dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-muted);
}

.toast--success .toast__dot {
  background: var(--success-500);
}

.toast--error .toast__dot {
  background: var(--danger-500);
}

.toast--warning .toast__dot {
  background: var(--warning-500);
}

.toast--info .toast__dot {
  background: var(--brand-500);
}

.toast__text {
  flex: 1;
  word-break: break-word;
}

/* ------------------------------------------------------------ 提示条 --- */

.notice {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 11px 13px;
  margin-bottom: 14px;
  font-size: 13px;
  line-height: 1.55;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-subtle);
  color: var(--text-secondary);
}

.notice--error {
  color: var(--danger-500);
  background: var(--danger-100);
  border-color: color-mix(in srgb, var(--danger-500) 26%, transparent);
}

.notice--warning {
  color: var(--warning-500);
  background: var(--warning-100);
  border-color: color-mix(in srgb, var(--warning-500) 26%, transparent);
}

.notice__icon {
  flex: none;
  font-weight: 700;
}

/* --------------------------------------------------- 产品浏览 / 筛选 --- */

.browse {
  margin-bottom: 16px;
  padding: 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.browse__row + .browse__row {
  margin-top: 12px;
}

.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.browse__row--fields {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.browse__row--fields .field {
  margin-bottom: 0;
}

.browse__row--fields .input {
  min-height: 42px;
  padding: 9px 12px;
  font-size: 14px;
}

.browse__note {
  margin-top: 12px;
  padding-top: 10px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--text-muted);
  border-top: 1px dashed var(--border);
}

/* 类型标签区的说明:类型不可用时给出原因,避免只看到一行空白。 */
.browse__hint {
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--danger-500);
}

.browse__hint[hidden] {
  display: none;
}

@media (min-width: 640px) {
  .browse__row--fields {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  }
}

/* -------------------------------------------------------------- 标签 --- */

.tag {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 8px;
  font-size: 11.5px;
  color: var(--text-secondary);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 6px;
  white-space: nowrap;
}

.tag--type {
  color: var(--brand-600);
  background: var(--brand-50);
  border-color: color-mix(in srgb, var(--brand-500) 24%, transparent);
}

.tag--muted {
  color: var(--text-muted);
}

/* ---------------------------------------------------------- 产品分组 --- */

.product-group {
  margin-bottom: 20px;
}

.product-group__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.product-group__name {
  font-size: 15px;
  font-weight: 600;
}

.product-group__count {
  font-size: 12.5px;
  color: var(--text-muted);
}

/* 分类规则说明较长,默认折叠。 */
.rule {
  margin-bottom: 12px;
  padding: 9px 12px;
  font-size: 12.5px;
  color: var(--text-secondary);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.rule>summary {
  color: var(--brand-500);
  cursor: pointer;
  list-style: none;
}

.rule>summary::-webkit-details-marker {
  display: none;
}

.rule>summary::before {
  content: "▸ ";
}

.rule[open]>summary::before {
  content: "▾ ";
}

.rule>p {
  margin-top: 8px;
  line-height: 1.7;
  color: var(--text-muted);
}

/* ---------------------------------------------------------- 产品卡片 --- */

/*
 * 产品卡片网格:列数由容器宽度自动决定。
 * 全屏自适应后容器可宽达 2400px+,若沿用 156px 下限会被切成十几列、
 * 每张卡片窄到放不下产品名,故在宽屏分级抬高下限(列数变少、卡片变宽)。
 */
.products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(156px, 1fr));
  gap: 10px;
}

@media (min-width: 1280px) {
  .products {
    grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
    gap: 12px;
  }
}

@media (min-width: 1700px) {
  .products {
    grid-template-columns: repeat(auto-fill, minmax(228px, 1fr));
    gap: 14px;
  }
}

.product {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 13px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  transition: border-color 0.16s ease, box-shadow 0.16s ease;
}

.product:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow);
}

.product__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.product__name {
  display: -webkit-box;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
  overflow: hidden;
  text-overflow: ellipsis;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.product__top .badge {
  flex: none;
  padding: 2px 7px;
  font-size: 11.5px;
}

/* 价格采用中文场景惯用的红色强调。 */
.product__price {
  font-size: 20px;
  font-weight: 600;
  line-height: 1.1;
  color: var(--danger-500);
  font-variant-numeric: tabular-nums;
}

.product__currency {
  margin-right: 2px;
  font-size: 13px;
  font-weight: 500;
}

.product__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  min-height: 22px;
}

.product__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: auto;
  padding-top: 4px;
  border-top: 1px solid var(--border);
}

.product__id {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--text-muted);
}

/* -------------------------------------------------------- 产品骨架屏 --- */

.skeleton-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 13px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.skeleton--short {
  flex: none;
  width: 56%;
}

/* ---------------------------------------------------- 下单产品摘要 --- */

.picked {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  margin-bottom: 16px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.picked__main {
  min-width: 0;
}

.picked__name {
  display: block;
  font-size: 14.5px;
  font-weight: 600;
}

.picked__meta {
  display: block;
  margin-top: 3px;
  font-size: 12px;
  color: var(--text-muted);
}

.picked__price {
  flex: none;
  font-size: 20px;
  font-weight: 600;
  color: var(--danger-500);
  font-variant-numeric: tabular-nums;
}

.picked__currency {
  margin-right: 2px;
  font-size: 13px;
  font-weight: 500;
}

/* -------------------------------------------------------------- 杂项 --- */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.text-mono {
  font-family: var(--font-mono);
}

.text-muted {
  color: var(--text-muted);
}

.mobile-only {
  display: initial;
}

@media (min-width: 640px) {
  .mobile-only {
    display: none;
  }
}

/* ------------------------------------------------------ 账户管理页 --- */

/*
 * 转账 / 创建账户的操作入口。
 *
 * 两个功能已由内联长表单改为「按钮 + 弹窗」:页面上只保留入口卡片,
 * 表单移入各自弹层。此处让按钮在窄屏各占一行、宽屏并排且等宽,
 * 避免两个入口挤在一行被压成窄条。
 */
.card__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.card__actions .btn {
  flex: 1 1 150px;
}

.card__body {
  padding: 16px;
}

.card__body .field:last-child {
  margin-bottom: 0;
}

.card__foot {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 13px 16px;
  border-top: 1px solid var(--border);
  background: var(--bg-subtle);
}

.card__note {
  padding: 9px 11px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-secondary);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

/* 金额输入:左侧货币符号 + 右侧「全部」快捷按钮,与 .field__toggle 共用定位基准。 */
.input-prefix {
  position: absolute;
  left: 13px;
  font-size: 15px;
  color: var(--text-muted);
  pointer-events: none;
}

.input--amount {
  padding-left: 30px;
  padding-right: 68px;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* 键值明细(确认弹层与操作结果共用) */
.kv {
  margin: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.kv__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 12px;
  font-size: 13.5px;
}

.kv__row + .kv__row {
  border-top: 1px solid var(--border);
}

.kv__row dt {
  flex: none;
  color: var(--text-muted);
}

.kv__row dd {
  margin: 0;
  font-weight: 600;
  text-align: right;
  word-break: break-all;
}

/* 操作结果面板 */
.result__title {
  margin-bottom: 12px;
  font-size: 15px;
  font-weight: 600;
}

.result__title--success {
  color: var(--success-500);
}

.result__note {
  margin-top: 12px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-muted);
}

.result__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}

/* ------------------------------------------ 账号菜单的两个弹层(渠道 / 改密) --- */
/*
 * 渠道配置与修改密码是**两个独立弹层**(账号菜单里各占一项,见 account-settings.js),
 * 故不再需要分区之间的分隔线与「分区右侧账号文案」这类同层排布样式;
 * 保留的是每个弹层内部「标题 + 状态徽章 + 重新读取」这一行的排布。
 * 指定用户的渠道弹层(accounts.js)复用同一组类名。
 */
.modal-section__head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.modal-section__title {
  font-size: 14.5px;
  font-weight: 600;
}

/* 状态徽章与「重新读取」按钮靠右:标题占满剩余空间,二者不被挤压换行。 */
.modal-section__head .modal-section__title {
  flex: 1;
  min-width: 0;
}

.modal-section__note {
  margin-bottom: 14px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-muted);
}

/* ------------------------------------------- 用户表列宽(宽屏固定布局) --- */
/*
 * 与订单表同理:自动布局下「账号」与「接口地址」是不可断行的长内容,
 * 会把「商户号」「创建时间」挤到换行,造成行高参差。宽屏改用固定布局,
 * 「接口地址」列不设宽度以吃满剩余空间,窄于最小宽度时由 .table-wrap 横向滚动兜底。
 *
 * 固定列合计 1004px,接口地址列取剩余宽度 → 最小宽度 1144px。
 *
 * 操作列 208px 是量出来的,不是估的:单元格左右各 14px padding,
 * 故内容宽 = 208 - 28 = 180px;而两个 .btn--sm 按钮(各 82px,4 个汉字 @13.5px
 * + 13px 左右 padding)并排需要 82 + 6 + 82 = 170px。
 * 早先写的 168px 只给出 140px 内容宽 —— 比需求少 30px,于是**在所有视口**
 * 都会换行(实测 768/900/1024/1280/1440/1600 六档无一例外),行高被撑到 103px,
 * 与「两个次要按钮并排」的本意相反。留 10px 余量以吸收字体度量差异。
 */
@media (min-width: 768px) {
  .data-table--users {
    table-layout: fixed;
    min-width: 1264px;
  }

  .data-table--users .colw-id {
    width: 76px;
  }

  .data-table--users .colw-account {
    width: 176px;
  }

  .data-table--users .colw-phone {
    width: 124px;
  }

  /* 用户余额列:金额等宽字体展示(单元格另带 .text-mono),定宽避免金额位数变化时抖列。 */
  .data-table--users .colw-balance {
    width: 120px;
  }

  .data-table--users .colw-state {
    width: 108px;
  }

  .data-table--users .colw-merchant {
    width: 156px;
  }

  .data-table--users .colw-time {
    width: 156px;
  }

  .data-table--users .colw-action {
    width: 208px;
  }
}

/* 行内操作:两个次要按钮并排(渠道配置 / 重置密码或修改密码)。
 *
 * 列宽必须容得下 2 × 按钮宽 + 6px 间隙(见上方 .colw-action 的算式),
 * 否则 flex-wrap 会让两个按钮竖排、把行高从 ~57px 撑到 ~103px。
 * 保留 flex-wrap 是兜底:移动端卡片模式下由字段名占位,极窄时宁可换行也不要溢出裁切。 */
.row-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* 账号单元格:账号名 + 「当前」标记同行,账号名单行省略。 */
.cell-account {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.cell-account .cell-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cell-account .tag {
  flex: none;
}

/* 移动端卡片模式下左侧已有字段名,改为右对齐并放开省略。 */
@media (max-width: 767px) {
  .cell-account {
    justify-content: flex-end;
  }

  .cell-account .cell-name {
    flex: none;
    white-space: normal;
    word-break: break-all;
  }
}

/* 管理员账号标识(窄屏隐藏,避免挤压页头)。 */
.app-header__user-name.is-admin::after {
  content: "管理员";
  margin-left: 6px;
  padding: 1px 6px;
  font-size: 11px;
  color: #fff;
  background: var(--brand-500);
  border-radius: 999px;
}

@media (max-width: 639px) {
  .app-header__user-name.is-admin::after {
    content: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* 下单弹层的支付方式选择(余额支付 / 渠道支付)。
   选中态与禁用态由 JS 打 class,不依赖 :has(),避免旧内核下样式失效。 */
.paytype {
  display: grid;
  gap: 8px;
}

.paytype__option {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas:
    "radio main"
    "radio sub";
  gap: 2px 10px;
  align-items: center;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  cursor: pointer;
}

.paytype__option.is-selected {
  border-color: var(--brand-500);
  background: var(--brand-50);
}

.paytype__option.is-disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

.paytype__option input {
  grid-area: radio;
  margin: 0;
}

.paytype__main {
  grid-area: main;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}

.paytype__sub {
  grid-area: sub;
  font-size: 12px;
  color: var(--text-muted);
}

/* -------------------------------------------------------- 统计折线图 --- */
/* 卡片头部的右侧操作区(趋势范围标签 + 月份切换下拉)。 */
.card__head-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* 卡片头部内的紧凑下拉:高度与徽章对齐,不撑高卡片头。 */
.input--compact {
  min-height: 30px;
  padding: 4px 8px;
  font-size: 12.5px;
}

/* 手写内联 SVG(见 stats.js):取色统一走主题变量,明暗模式自动跟随。 */
.chart__svg {
  display: block;
  width: 100%;
  height: auto;
}

.chart__grid {
  stroke: var(--border);
  stroke-width: 1;
}

.chart__axis-line {
  stroke: var(--border-strong);
  stroke-width: 1;
}

.chart__axis {
  fill: var(--text-muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.chart__line {
  fill: none;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.chart__line--completed {
  stroke: var(--brand-500);
}

.chart__line--refunded {
  stroke: var(--warning-500);
}

.chart__dot--completed {
  fill: var(--brand-500);
}

.chart__dot--refunded {
  fill: var(--warning-500);
}

.chart__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--text-secondary);
}

.chart__legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.chart__swatch {
  width: 10px;
  height: 10px;
  border-radius: 2px;
}

.chart__swatch--completed {
  background: var(--brand-500);
}

.chart__swatch--refunded {
  background: var(--warning-500);
}

/* 收益系列(走独立右轴):用成功色与「已完成金额」区分;
   右轴刻度同色,读者一眼能对上是哪条轴的数字。 */
.chart__line--profit {
  stroke: var(--success-500);
}

.chart__dot--profit {
  fill: var(--success-500);
}

.chart__swatch--profit {
  background: var(--success-500);
}

.chart__axis--profit {
  fill: var(--success-500);
}

/*
 * 卡片头部的计数/范围标签不换行。
 *
 * 「按月趋势」卡片的头部右侧同时放了「图 / 列表」切换、月份范围(如 2025-10 ~ 2026-09)
 * 和月份下拉,宽度紧;范围文本被折成 3–4 行会把整个头部撑高,看着像排版错乱。
 * 这类标签都是短文本,nowrap 后由弹性布局自行压缩其它部分即可。
 */
.card__count {
  white-space: nowrap;
}
