/* ==========================================================================
   买家账户区（第 28 轮）：登录 / 注册 / 找回密码 / 我的订单 / 个人信息
   —— 对应 templates/front/account/*.html

   ★ 三条硬原则（与全站一致，改前必读）：
     1. **只用逻辑属性**（`margin-inline-start` 而不是 `margin-left`）——
        一套样式同时适配 LTR（英/中）与 RTL（阿语），不必维护两份会漂移的样式。
     2. **颜色只引用变量**（`var(--primary)` / `var(--ok)` 等），不写死色值。
     3. **移动优先**：基础样式先写给手机，宽屏用 min-width 媒体查询增强。
        触控目标 ≥ 44px（`--tap-min`）。
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. 闪存消息（front/base.html 用）
   —— 前台原先完全没有 flash 渲染，"操作成功"没有任何反馈。
   -------------------------------------------------------------------------- */
.flash-stack {
  display: grid; gap: 8px;
  margin-block-start: 12px;
}
.flash {
  padding: 10px 14px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--bg-soft);
  color: var(--ink-2); font-size: .875rem;
}
/* ⚠️ 分类必须**逐个定义**，不能只写 success —— 实测全站在用的有
   `error`(44 处) / `ok`(18) / `success`(18)，另有 18 处 `flash()` **没写分类**
   （Flask 默认给 `message`）。缺一个定义，那一类就退化成中性灰，
   「保存成功」和「操作失败」看起来一模一样。模板侧已把未知分类归到 `info`。 */
.flash--success,
.flash--ok      { background: var(--ok-bg);   border-color: var(--ok);   color: var(--ok); }
.flash--error   { background: var(--err-bg);  border-color: var(--err);  color: var(--err); }
.flash--warn    { background: var(--warn-bg); border-color: var(--warn); color: var(--warn); }
.flash--info    { background: var(--info-bg); border-color: var(--info); color: var(--info); }

/* --------------------------------------------------------------------------
   2. 提示条 / 徽章 / 键值对（账户区通用小件）
   -------------------------------------------------------------------------- */
.alert {
  padding: 12px 14px; border-radius: var(--radius-sm);
  font-size: .875rem; line-height: 1.55;
}
.alert--error { background: var(--err-bg); border: 1px solid var(--err); color: var(--err); }
.alert--warn  { background: var(--warn-bg); border: 1px solid var(--warn-border); color: var(--warn); }
.alert--info  { background: var(--info-bg); border: 1px solid var(--info); color: var(--info); }
.alert__list { margin: 0; padding-inline-start: 18px; display: grid; gap: 4px; }

/* ★ 第 47 轮（业主需求 3）：可关闭的提示条（顶部"建议绑定邮箱"）。
   为什么用 flex + `margin-inline-start:auto` 而不是绝对定位：
   阿语下 `dir=rtl` 会自动把"关闭按钮在末尾"镜像过去，不用写第二份样式。
   ⚠️ 关闭按钮要 ≥ 44px 命中区（`--tap-min`）—— 它是可点目标，
      不能只按 × 字形大小给尺寸（手机上按不中）。 */
.alert--dismissible {
  display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center;
}
.alert__text { flex: 1 1 12rem; min-inline-size: 0; }
.alert__action {
  color: inherit; font-weight: 700; text-decoration: underline;
  flex: 0 0 auto;
}
.alert__close {
  flex: 0 0 auto;
  min-inline-size: var(--tap-min); min-block-size: var(--tap-min);
  display: inline-flex; align-items: center; justify-content: center;
  margin-inline-start: auto;
  padding: 0; border: 0; background: none;
  color: inherit; font-size: 1.25rem; line-height: 1;
  cursor: pointer; opacity: .7;
  border-radius: var(--radius-sm);
}
.alert__close:hover { opacity: 1; background: rgb(0 0 0 / .06); }

.pill {
  display: inline-block; padding: 3px 10px; border-radius: var(--radius-pill);
  font-size: .75rem; font-weight: 600; white-space: nowrap;
  background: var(--bg-soft); color: var(--ink-2); border: 1px solid var(--line);
}
.pill--ok    { background: var(--ok-bg);    color: var(--ok);    border-color: var(--ok); }
.pill--warn  { background: var(--warn-bg);  color: var(--warn);  border-color: var(--warn-border); }
.pill--info  { background: var(--info-bg);  color: var(--info);  border-color: var(--info); }
.pill--muted { background: var(--bg-soft);  color: var(--ink-3); }
/* ★ 第 59 轮（业主反馈）：**已取消**要给提醒色，不能和"灰掉的次要信息"一样。
   语义色名由模型层 `Order.status_tone` 统一给出（前后台共用一套词汇）。 */
.pill--danger { background: var(--err-bg); color: var(--err); border-color: var(--err); }
/* ★ 第 97 轮：样品标记。用主题色描边而不是某个语义色 ——
   它不是"警告"也不是"成功"，是一种**单据类型**（和"含样品"这件事等义）。
   买家在购物车/订单列表/订单详情、卖家在后台订单里看到的都是同一个视觉。 */
.pill--sample { background: var(--primary-soft); color: var(--primary); border-color: var(--primary); }

.tag--ok { background: var(--ok-bg); color: var(--ok); }
/* ★ 第 47 轮：未绑定 / 未验证的徽章（原来只有 `tag--ok`，
   于是"未绑定"会退化成无色文字，与普通正文分不开）。 */
.tag--warn { background: var(--warn-bg); color: var(--warn); border-color: var(--warn-border); }

/* 键值对（订单/资料详情）——移动端竖排，宽屏两列 */
.kv { display: grid; gap: 6px 16px; margin: 0; }
.kv dt { color: var(--ink-3); font-size: .8125rem; }
.kv dd { margin: 0; color: var(--ink); font-size: .9375rem; word-break: break-word; }
@media (min-width: 640px) {
  .kv { grid-template-columns: minmax(96px, max-content) 1fr; }
  .kv dt { padding-block: 2px; }
  .kv dd { padding-block: 2px; }
}

.panel__note {
  margin: 10px 0 0; font-size: .8125rem; color: var(--ink-3); line-height: 1.6;
}

/* --------------------------------------------------------------------------
   3. 登录 / 注册 / 找回密码（居中卡片，对应 _auth.html）
   -------------------------------------------------------------------------- */
.auth-wrap {
  max-inline-size: 460px; margin-inline: auto;
  display: grid; gap: 18px;
}
.auth-card {
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 24px 20px;
}
.auth-card__head { text-align: center; margin-block-end: 20px; }
.auth-card__title { font-size: 1.375rem; margin: 0 0 6px; }
.auth-card__sub { margin: 0; color: var(--ink-3); font-size: .875rem; line-height: 1.6; }
.auth-card__foot {
  margin-block-start: 18px; padding-block-start: 16px;
  border-block-start: 1px solid var(--line);
  text-align: center; font-size: .875rem; color: var(--ink-3);
}
.auth-card__foot a { font-weight: 600; }
.auth-card .alert { margin-block-end: 16px; }

/* 侧边的"注册有什么用"清单：B2B 客户会犹豫要不要留手机号 */
.auth-aside {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 8px;
  font-size: .8125rem; color: var(--ink-3); line-height: 1.6;
}
.auth-aside li {
  display: flex; gap: 8px; align-items: flex-start;
}
.auth-aside li::before {
  content: "✓"; color: var(--ok); font-weight: 700; flex: 0 0 auto;
}

.auth-inline { text-align: end; font-size: .8125rem; }
.auth-note {
  margin: 14px 0 0; padding: 10px 12px;
  background: var(--info-bg); border-radius: var(--radius-sm);
  color: var(--info); font-size: .8125rem; line-height: 1.6;
}

/* 复选框行：label 里带 checkbox + 富文本（含链接），要能正常换行 */
.form__label--check {
  display: flex; gap: 10px; align-items: flex-start;
  font-weight: 400; line-height: 1.6;
}
.form__label--check input { margin-block-start: 3px; flex: 0 0 auto; }
.form__label--check a { text-decoration: underline; }

/* --------------------------------------------------------------------------
   4. 验证码区块（_verify_field.html）
   -------------------------------------------------------------------------- */
.verify-block { display: grid; gap: 14px; }
.verify-row { display: grid; gap: 8px; }
/* 号码 + 「发送验证码」按钮。
   ⚠️ 国码下拉已经**不在这一行**了 —— 国家/地区单独占一行（业主第 28 轮要求
      「填入手机号的时候，都应该单独选择国家/地区」）。原先 110px 的首列是给
      国码下拉留的，现在没有那一列了，留着会把号码框挤窄，故改为 `1fr`。 */
.verify-row__fields {
  display: grid; gap: 8px;
  grid-template-columns: 1fr;          /* 手机端：号码一行，按钮独占下一行 */
}
@media (min-width: 520px) {
  .verify-row__fields { grid-template-columns: 1fr auto; }
}
/* 「发送验证码」按钮：在 `1fr auto` 里按内容宽度排。
   ⚠️ 必须阻止标签折行 —— 中文「获取验证码」/ 阿语「إرسال الرمز」一折行，
      按钮就比输入框高一截，两者不在一条线上（视觉上像"没对齐"）。 */
.verify-send { white-space: nowrap; }
/* 国家/地区下拉：长名字（如「United Arab Emirates (+971)」）要能放得下 */
.form__select--country { max-width: 100%; }

/* 6 位码：等宽 + 字距，方便核对 */
.ac-code { letter-spacing: .28em; font-weight: 600; }

.verify-msg {
  margin: 0; font-size: .8125rem; line-height: 1.6;
}
.verify-msg--ok  { color: var(--ok); }
.verify-msg--err { color: var(--err); }

/* 开发模式提示：只在 dev 通道出现（见 app/verify.py），生产不会渲染出内容 */
.dev-code {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--warn-bg); border: 1px dashed var(--warn-border);
  color: var(--warn); font-size: .8125rem;
}
.dev-code__tag {
  padding: 1px 8px; border-radius: var(--radius-pill);
  background: var(--warn); color: var(--on-accent);
  font-size: .6875rem; font-weight: 700;
}
.dev-code__code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1rem; font-weight: 700; letter-spacing: .16em;
}

/* 接收方式选择（只有站点配了多个通道时才显示） */
.channel-picker { display: flex; flex-wrap: wrap; gap: 8px; }
.channel-chip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 40px; padding-inline: 14px;
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  background: var(--bg); color: var(--ink-2);
  font-size: .875rem; font-weight: 600; cursor: pointer;
  transition: border-color .15s, color .15s, background-color .15s;
}
.channel-chip input { accent-color: var(--primary); }
.channel-chip:has(input:checked) {
  border-color: var(--primary); color: var(--primary); background: var(--primary-soft);
}

/* 登录方式（手机号 / 邮箱）双面板。
   ★ 用 CSS `:has()` 决定显示哪一栏，**不靠 JS** —— 脚本挂了客户也能登录；
     `account.js` 只负责把隐藏那栏的输入 `disabled`（免得它的 required 卡住提交）。 */
[data-login-pane] {
  /* ⚠️ 面板内部的国家块与号码块是并列的 `.verify-row`，它们自带 gap
     只管各自内部；**面板本身**也要有间距，否则两行会贴在一起
     （实测「国名提示」和「手机号」标签会挨到 0 间距）。 */
  display: grid;
  gap: 14px;
}
[data-login-form]:has(input[value="phone"]:checked) [data-login-pane="email"],
[data-login-form]:has(input[value="email"]:checked) [data-login-pane="phone"] {
  display: none;
}
[data-login-pane][hidden] { display: none; }

/* --------------------------------------------------------------------------
   4b. 页头「登录 / 我的账户」入口
   ⚠️ 第 35 轮：`.account-link` 的样式**已挪到 03-components.css**，
      跟同排的 `.cart-link` 放一起（两者是一对，分居两个文件时
      改一个忘一个，两个按钮高度就会对不齐）。
   -------------------------------------------------------------------------- */

/* 结算页的"当前登录"提示条 */
.ck-account {
  display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center;
  padding: 10px 14px; margin-block-end: 16px;
  background: var(--ok-bg); border: 1px solid var(--ok);
  border-radius: var(--radius-sm); color: var(--ink-2); font-size: .875rem;
}
.ck-account__ico {
  inline-size: 22px; block-size: 22px; border-radius: var(--radius-pill);
  background: var(--ok); color: var(--on-accent);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .8125rem; font-weight: 700; flex: 0 0 auto;
}
.ck-account__text { flex: 1 1 auto; min-inline-size: 0; }
.ck-account__phone { color: var(--ink-3); margin-inline-start: 6px; }
.ck-account__link { font-weight: 600; }

/* --------------------------------------------------------------------------
   5. 账户区布局（已登录：左侧导航 + 右侧内容）
   -------------------------------------------------------------------------- */.account-layout { display: grid; gap: 20px; }
@media (min-width: 860px) {
  .account-layout { grid-template-columns: 236px 1fr; align-items: start; }
  .account-side { position: sticky; inset-block-start: calc(var(--header-h) + 16px); }
}

.account-side {
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px;
}
.account-side__user {
  display: flex; gap: 10px; align-items: center;
  padding-block-end: 12px; margin-block-end: 10px;
  border-block-end: 1px solid var(--line);
}
.account-side__avatar {
  flex: 0 0 auto;
  inline-size: 40px; block-size: 40px; border-radius: var(--radius-pill);
  background: var(--primary-soft); color: var(--primary);
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 1.05rem;
}
.account-side__meta { display: grid; gap: 2px; min-inline-size: 0; }
.account-side__name {
  font-size: .9375rem; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.account-side__phone { font-size: .75rem; color: var(--ink-3); }

.account-nav { display: grid; gap: 2px; }
.account-nav__item {
  display: flex; align-items: center; gap: 8px;
  min-height: var(--tap-min);
  padding-inline: 12px; border-radius: var(--radius-sm);
  color: var(--ink-2); font-size: .9375rem; text-decoration: none;
  transition: background-color .15s, color .15s;
}
.account-nav__item:hover { background: var(--bg-soft); color: var(--ink); }
.account-nav__item.is-active {
  background: var(--primary-soft); color: var(--primary); font-weight: 600;
}
.account-nav__item--out { color: var(--ink-3); }

.account-main { min-inline-size: 0; display: grid; gap: 16px; }
.account-head { display: grid; gap: 4px; }
.account-head__title { font-size: 1.25rem; margin: 0; }
.account-head__sub { margin: 0; color: var(--ink-3); font-size: .875rem; }
.account-head__sub .ltr-value { color: var(--ink-2); font-weight: 600; }
/* ★ 第61轮：订单详情页"返回我的订单列表"入口
   ★ 第108轮：挪到 h1 **上面**当面包屑 → 去掉上外边距，并靠左对齐
     （父级是 grid，默认会被拉伸成整行宽，`justify-self` 让它只占自己的宽度）。 */
.account-head__back {
  display: inline-block; margin: 0; justify-self: start;
  color: var(--primary); text-decoration: none;
  font-size: .8125rem; font-weight: 600;
}
.account-head__back:hover { text-decoration: underline; }
/* 阿语页整体镜像后，"←" 仍指向左 = 反方向；按 `dir` 把箭头水平翻转
   （全站已有同款写法：`.bn-hero__img` 在 rtl 下 scaleX(-1)）。 */
.account-head__arrow { display: inline-block; }
[dir="rtl"] .account-head__arrow { transform: scaleX(-1); }

/* --------------------------------------------------------------------------
   第 108 轮：订单号 + 下单时间（详情页页头那行小字）
   --------------------------------------------------------------------------
   ★ 订单号 `user-select: all` —— 双击（乃至单击）就选中**整串**，而且只选它：
     买家要把单号贴到 WhatsApp / 邮件里，不需要小心翼翼地拖鼠标。
     单号本身不含空白，所以"整段选中"就等于"只选中单号"。
   ★ 数字用 `tabular-nums`：单号与时间都是等宽数字，复制时不会看串行。 */
.order-meta {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px; row-gap: 2px;
}
.order-meta__id { position: relative; display: inline-flex; align-items: center; gap: 6px; min-inline-size: 0; }
.order-meta__no {
  color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
  -webkit-user-select: all; user-select: all;
  cursor: text;
}
.order-meta__copy {
  display: inline-flex; align-items: center; justify-content: center;
  inline-size: 22px; block-size: 22px; padding: 0;
  border: 1px solid transparent; border-radius: 6px;
  background: transparent; color: var(--ink-3); cursor: pointer;
  flex: none;
  transition: color .15s, background-color .15s, border-color .15s;
}
.order-meta__copy:hover { color: var(--primary); border-color: var(--primary-border); background: var(--primary-soft); }
.order-meta__copy:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.order-meta__copy.is-copied { color: var(--ok); border-color: var(--ok); background: transparent; }
/* 成功 → 复制图标换成勾（一个字符大小，零布局变化）；失败才弹文字条 */
.order-meta__check { display: none; }
.order-meta__copy.is-copied .order-meta__icon { display: none; }
.order-meta__copy.is-copied .order-meta__check { display: block; }
/* 复制结果提示：只做"已复制/请手动复制"，靠 `hidden` 控制显隐（JS 只写 textContent）。
   ★ **绝对定位**，不占位 —— 否则"已复制"三个字出现的瞬间会把"·"和日期往右顶一下，
     2 秒后又弹回来（实测桌面端会晃一行，看着像页面抖了）。
     做成浮在订单号右侧的小胶囊，2 秒后自己消失，全程零重排。 */
.order-meta__tip {
  position: absolute; inset-inline-start: calc(100% + 6px); inset-block-start: 50%;
  transform: translateY(-50%);
  padding: 1px 8px; border-radius: 999px;
  background: var(--ok-bg); color: var(--ok);
  font-size: .75rem; font-weight: 600; line-height: 1.5;
  white-space: nowrap; pointer-events: none; z-index: 2;
}
.order-meta__tip.is-error { background: var(--err-bg); color: var(--err); }
/* 成功时不显示文字条（图标已给"勾"，再叠一条会盖住旁边的日期），
   但文字仍写进 DOM —— `role=status` 会念给读屏用户听（无障碍不能因为好看而丢）。 */
.order-meta__tip.is-sr {
  position: absolute; inline-size: 1px; block-size: 1px; padding: 0;
  margin: -1px; border: 0; overflow: hidden; background: none;
  clip-path: inset(50%); white-space: nowrap;
}
.order-meta__sep { color: var(--ink-3); opacity: .5; }
.order-meta__date {
  color: var(--ink-3); font-weight: 500; font-variant-numeric: tabular-nums;
}
/* ★ 第 61 轮：订单详情页"关闭订单"（软删除，仅未发货未付款可见）
   ★ 第 108 轮：从"状态条下方一个独立块"改到页面底部按钮行里，
     所以外边距归零，并推到行尾（`margin-inline-start` 在 RTL 下自动镜像）。 */
.order-close { margin: 0; margin-inline-start: auto; }

.account-actions {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
}

/* --------------------------------------------------------------------------
   6. 订单列表
   -------------------------------------------------------------------------- */
.order-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }

.order-card {
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
  transition: border-color .15s, box-shadow .15s;
}
.order-card:hover { border-color: var(--primary-border); box-shadow: var(--shadow-md); }

.order-card__head {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  justify-content: space-between;
  padding: 12px 14px; background: var(--bg-soft);
  border-block-end: 1px solid var(--line);
}
.order-card__no { font-weight: 700; color: var(--ink); text-decoration: none; }
.order-card__no:hover { color: var(--primary); }

/* 明细行：复用 `.mini-line` 那套 5 列网格（封面图→标题→单价→数量→金额），
   见 40-page-cart.css —— 全站订单行**只有这一份定义**，不要在这里另起一套。
   这里只补"卡片内"的边距。 */
.order-card__items {
  padding: 10px 14px 4px;
  margin-block-end: 0;
  border-block-end: 1px dashed var(--line);
}
.order-card__more-lines {
  margin: 2px 0 0; font-size: .75rem; color: var(--ink-3);
}

.order-card__meta {
  display: flex; flex-wrap: wrap; gap: 6px 16px;
  padding: 10px 14px 0;
  font-size: .8125rem; color: var(--ink-3);
}

/* 付款状态小胶囊：B2B 客户看订单第一眼就是「这笔付了没」，
   默认（unpaid）用警示色**主动引起注意**，付清了才转绿。 */
.order-card__pay {
  display: inline-block; padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: var(--warn-bg); color: var(--warn);
  font-size: .75rem; font-weight: 600;
}
.order-card__pay--paid { background: var(--ok-bg); color: var(--ok); }
.order-card__pay--refunded { background: var(--bg-soft); color: var(--ink-2); }

/* 底部：左边是"订单金额 + 数字"（★ 第 57 轮改成**同一行**，
   业主反馈"金额字眼跟金额没在一行，看不明白"），右边是详情按钮。 */
.order-card__foot {
  padding: 10px 14px; border-block-start: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
}
.order-card__total {
  display: inline-flex; align-items: baseline; gap: 8px;
  font-size: .8125rem; color: var(--ink-3);
}
.order-card__total-label { white-space: nowrap; }
.order-card__total strong { font-size: 1.0625rem; color: var(--ink); }

.order-status { display: flex; flex-wrap: wrap; gap: 8px; }

/* --------------------------------------------------------------------------
   7. 分页 / 空状态
   -------------------------------------------------------------------------- */
.pager {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 14px;
  padding-block: 6px;
}
/* ★ 第 117 轮：本文件在产品页之后加载，这里的 gap 会覆盖 20-page-products.css 的窄屏值。
   产品列表页同样加载本文件，手机上 14px 间距会让 6 个页码差 1px 折行 —— 必须再压一次。 */
@media (max-width: 640px) {
  .pager { gap: 10px 6px; }
}
.pager__btn {
  min-height: var(--tap-min); display: inline-flex; align-items: center;
  padding-inline: 14px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  color: var(--ink-2); text-decoration: none; font-size: .875rem;
}
.pager__btn:hover { border-color: var(--primary); color: var(--primary); }
.pager__info { color: var(--ink-3); font-size: .875rem; }
/* ★ 第61轮：订单列表"每页条数"选择器 */
.pager__size {
  display: inline-flex; align-items: center; gap: 6px;
  margin-inline-start: 6px; color: var(--ink-3); font-size: .875rem;
}
.pager__size select {
  min-height: var(--tap-min); padding: 2px 6px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg); color: inherit; font: inherit;
}

.empty-state {
  display: grid; gap: 8px; justify-items: center;
  text-align: center; padding: 40px 16px;
  background: var(--bg); border: 1px dashed var(--line); border-radius: var(--radius);
}
.empty-state__ico { font-size: 1.75rem; color: var(--ink-3); }
.empty-state__title { margin: 0; font-weight: 600; color: var(--ink); }
.empty-state__sub { margin: 0 0 6px; color: var(--ink-3); font-size: .875rem; }

/* 订单明细里的单品备注（颜色/包装要求），弱化处理不抢主信息 */
.mini-line__note { color: var(--ink-3); font-style: normal; font-size: .8125rem; }

/* ==========================================================================
   8. 反滥用组件（第 37 轮）：蜜罐字段 + 图形码
   -------------------------------------------------------------------------- */

/* 蜜罐字段：真人看不见、屏幕阅读器也读不到，但**必须真实存在于 DOM**
   —— 自动填表机器人正是靠"把页面上每个 input 都填一遍"来工作的。
   ⚠️ 绝不能用 `display:none` 或 `type="hidden"`：那两类字段机器人会跳过，
      蜜罐就白设了。正解是"视觉移出视口、但仍参与表单提交"。 */
.hp-field {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
  padding: 0;
  margin: -1px;
}

/* 图形码（L3）。图片按 2 倍画、按 160×46 显示（视网膜屏不糊）。
   ★ 第 47 轮：从 132×44 放大到 160×46 —— 字符从 4 位加到 5 位，
     原尺寸下字会挤在一起，真人反而认不出（强化不能以牺牲可读性为代价）。 */
.captcha { margin-block-start: 2px; }
.captcha[hidden] { display: none; }
.captcha__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
/* ★ 第 48 轮修正：输入框给足宽度，placeholder 不再被截断成 "ENTER THE IMAG…"。
   `flex: 1 1 auto` + `min-inline-size: 9rem`＝144px 起步（够放 "Enter the image code"
   这类提示），上限 12rem。**不能再设死 max-inline-size 太小** ——
   设小了浏览器就把提示文字裁掉，客户看不出这里要填什么。 */
.captcha__input {
  flex: 1 1 auto;
  min-inline-size: 9rem;
  max-inline-size: 12rem;
  /* ⚠️ 不设 text-transform: uppercase：图形码本身不分大小写（提示里已写明），
     强行转大写只会让客户以为自己输错了；而且会把 placeholder 也一起转掉。 */
}
/* 图片：`flex: 0 0 auto` ＋ 显式宽高，**必须**配 `object-fit: contain`。
   ★ 第 48 轮踩坑：只给 width/height 属性、不给 CSS 尺寸时，flex 收缩会
     按比例压扁图片 → 图形码字形被拉伸变形（业主截图实录）。
   `flex-shrink: 0` 是关键：宁可让这一行换行，也不让图片被挤扁。 */
.captcha__img {
  flex: 0 0 auto;
  inline-size: 160px;
  block-size: 46px;
  object-fit: contain;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  user-select: none;
  -webkit-user-drag: none;
}
.captcha__refresh {
  flex: 0 0 auto;
  min-inline-size: var(--tap-min);
  min-block-size: var(--tap-min);
  padding-inline: 0;
  font-size: 1.125rem;
  line-height: 1;
}

/* ★ 第 48 轮：图形码弹窗（点「Send code」才弹）
   —— `_verify_field.html` 里的 <dialog class="modal modal--captcha">
   基础样式复用 `36-inquiry.css` 的 `.modal`（原生 dialog 的框/遮罩/圆角），
   这里只补三件事：① 弹窗比询盘表单窄；② 底部的「取消 / 确认并发送」按钮条；
   ③ 给图形码行留够宽度。

   ⚠️ **宽度别压太狠**：420px 减掉两侧 22px 内边距只剩 376px，
      装不下「输入框 + 160px 图片 + 刷新按钮」→ 图片被 flex 压扁变形。
      460px 是实测能舒服放下这三件的最小值（窄屏仍走 `calc(100vw - 32px)`）。 */
.modal--captcha { inline-size: min(460px, calc(100vw - 32px)); }
.modal--captcha .modal__body { padding-block-end: 8px; }

/* ★ 第 74 轮：「改手机号 / 改邮箱」弹窗。
   复用 `.modal` 的框与遮罩，只把宽度压到 520px —— 比询盘表单窄一点，
   又能放下「输入框 + 发送验证码」这一行（460px 会把输入框挤到只剩一半）。 */
.modal--auth { inline-size: min(520px, calc(100vw - 32px)); }
/* 弹窗里的表单**自带** `.modal__body` 的滚动与内边距，
   别再让 `.form` 的默认约束把宽度收窄一层。 */
.modal .form.modal__body { max-inline-size: none; }

/* 登录信息（个人信息页）：一行 = 标签 · 值 · 状态 · 操作按钮。
   ★★ 第 75 轮（业主）：**不再用输入框**（只读 input 看着能随手改，还白占高度）。
      纯文本展示 + 右侧按钮，改邮箱/改手机号一律走弹窗。 */
.login-key { display: grid; gap: 6px; margin-block-end: 16px; }
.login-key:last-of-type { margin-block-end: 0; }
.login-key__row {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px;
  min-block-size: 38px;
}
.login-key__label {
  flex: 0 0 auto; min-inline-size: 64px; white-space: nowrap;
  color: var(--ink-3); font-size: .875rem;
}
/* 值 + 状态标签绑成一组：标签永远紧跟值，不会被 flex 推到按钮旁边 */
.login-key__main {
  flex: 1 1 auto; min-inline-size: 0;
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px;
}
.login-key__val {
  min-inline-size: 0;
  font-weight: 600; overflow-wrap: anywhere;
}
.login-key__row .tag { flex: 0 0 auto; }
.login-key__val--none { color: var(--ink-3); font-weight: 400; }
/* 按钮永远贴右，值长短不同也不会让按钮左右跳 */
.login-key__act { margin-inline-start: auto; }
.login-key > .form__hint { padding-inline-start: 0; }
/* 只在大屏把说明文字缩进到值的位置，窄屏跟着换行更省空间 */
@media (min-width: 560px) {
  .login-key > .form__hint { padding-inline-start: 74px; }
}
/* 窄屏：标签当小标题独占一行，值一行，按钮整行 —— 两行长得一致，
   不会出现"手机号跟值同行、邮箱却各占一行"的参差感。 */
@media (max-width: 559px) {
  .login-key__label { flex: 0 0 100%; min-inline-size: 0; }
  .login-key__act { flex: 0 0 100%; margin-inline-start: 0; }
}
/* 弹窗内的图形码行：窄屏时让「图片 + 刷新」自成一行，别把输入框挤没 */
.modal--captcha .captcha__row { gap: 10px; }

.modal__foot {
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 10px;
  padding: 14px var(--modal-pad) var(--modal-pad);
  border-block-start: 1px solid var(--line);
  background: var(--bg-soft);
}
/* 窄屏：两个按钮各占一行，避免「确认并发送验证码」这种长文案被挤断 */
@media (max-width: 420px) {
  .modal__foot { flex-direction: column-reverse; }
  .modal__foot .btn { inline-size: 100%; }
}
/* ★ 窄屏图形码行：输入框独占一行，图片与刷新按钮另起一行并列。
   ⚠️ 图片**绝不能**用 `inline-size: auto` + `flex: 1 1 auto` 去拉伸 ——
      高度被 `block-size: 46px` 锁死时，横向拉伸会把比例从 3.48 变成 5.52，
      图形码字形横向拉长（比原截图那种压扁更难认）。
      正确做法：宽度按 `aspect-ratio` 自然推导（或干脆给固定 160px），
      只让**高度**受限。这里保留固定宽度最稳。 */
@media (max-width: 420px) {
  .captcha__row { gap: 10px; }
  .captcha__input { flex: 1 1 100%; max-inline-size: none; }
  .captcha__img { flex: 0 0 auto; inline-size: 160px; block-size: 46px; }
}

/* 无 JS 降级块（`<noscript>` 里的图形码）与弹窗版视觉一致，
   但它是**常驻**的，所以给它一点上边距与表单分开。 */
[data-captcha-noscript] { margin-block-start: 4px; }

/* ★ 第 53 轮：滑块拼图方案（provider = slider）
   —— `_verify_field.html` / `profile.html` 里的 [data-cap-kind="slide"]

   ⚠️ 三条与"图形码变形"同源的教训（第 48 轮踩过，这里预先规避）：
     ① 主图**只许等比缩放**：给它 `inline-size: 100%` + `block-size: auto`，
        绝不写死宽高又不给 `object-fit`（那会让 CSS 尺寸与固有比例打架 → 拉伸）。
        主图 600×300（2 倍图），显示口径 300×150，比例恒为 2:1。
     ② 拼图块**必须绝对定位**在主图上（它是叠加层，不参与主图的尺寸计算）。
     ③ 手柄与轨道同高，窄屏下也不许换行（换行会让拖拽坐标系错乱）。 */
.captcha--slide .slide {
  position: relative;
  inline-size: 100%;
  max-inline-size: 300px;
  margin-inline: auto;
  line-height: 0;                 /* 消除 img 的基线间隙 */
  border-radius: var(--radius-sm, 6px);
  overflow: hidden;
  background: var(--bg-soft);
}
.captcha--slide .slide__main {
  display: block;
  inline-size: 100%;
  block-size: auto;               /* ★ 等比：高度由宽度自动推导 */
  aspect-ratio: 2 / 1;            /* 600×300 —— 与 slider.py 的 MAIN_W/H 同步 */
  user-select: none;
  -webkit-user-drag: none;
}
.captcha--slide .slide__piece {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;          /* 用 left（非逻辑属性）—— 与 JS 的像素坐标一一对应 */
  inline-size: 48px;              /* 96px(2 倍图) / 2 */
  block-size: 48px;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  filter: drop-shadow(0 4px 8px rgba(0, 0, 0, .28));   /* ★ 第59轮b：块浮起，参考方案 */
}
/* 轨道条：手柄沿它滑动 */
.captcha--slide .slide__bar {
  position: relative;
  max-inline-size: 300px;
  margin: 8px auto 0;
  block-size: 40px;
}
.captcha--slide .slide__rail {
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 40px;
  border: 1px solid #e6ebf2;      /* ★ 第59轮b：浅色轨道，参考方案 */
  border-radius: 8px;
  background: #f2f4f9;
  overflow: hidden;
}
.captcha--slide .slide__fill {
  block-size: 100%;
  inline-size: 0;
  background: rgba(51, 176, 100, .22);   /* ★ 第59轮b：浅绿填充，参考方案 */
}
.captcha--slide .slide__arrow {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--ink-muted, #888);
  font-size: 1rem;
}
/* 手柄：可拖动的方块。
   ⚠️ 必须 `touch-action: none` —— 否则移动端浏览器会把横向拖动
      当成页面横滚，`pointermove` 根本收不到（表现为"手指一拖页面跟着晃"）。 */
.captcha--slide .slide__handle {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  inline-size: 48px;
  block-size: 40px;
  border: none;                   /* ★ 第59轮b：白色圆钮带投影，参考方案 */
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .18);
  cursor: grab;
  touch-action: none;
  padding: 0;
}
.captcha--slide .slide__handle::after {
  content: "⇄";
  display: grid;
  place-items: center;
  block-size: 100%;
  color: #3a8ff0;                 /* ★ 第59轮b：蓝色手柄图标，参考方案 */
}
.captcha--slide .slide__handle:active { cursor: grabbing; }
.captcha--slide .slide__handle[disabled] { opacity: .5; cursor: default; }

/* 窄屏：主图与轨道跟着弹窗宽度走（弹窗已由 calc(100vw - 32px) 限宽） */
@media (max-width: 420px) {
  .captcha--slide .slide,
  .captcha--slide .slide__bar { max-inline-size: 100%; }
}

/* --------------------------------------------------------------------------
   9. 注册方式面板（第 47 轮，业主需求 4）
   —— `_verify_field.html` 里的 [data-vf-pane="phone"|"email"]
   --------------------------------------------------------------------------

   ⚠️ 为什么用 CSS :has() 兜住显隐而不是只靠 JS：
      `account.js` 会摘掉 `hidden` 并把隐藏面板的控件 `disabled`（必须做，
      否则它的 required 会卡住提交）；但如果脚本没跑（被拦截/加载失败），
      `hidden` 属性本身就已经能正确隐藏了 —— CSS 这里只是**双保险**，
      防止某些浏览器把 `hidden` 覆盖掉（`display:grid` 就会）。

   ★ 与登录页 `[data-login-pane]` 是同一手法，**故意分开写**：
     登录页那套靠 `:has(input[value=...]:checked)` 从 radio 推显隐，
     这里靠 `hidden` 属性 —— 因为注册页的面板可能来自**服务端回填**
     （表单报错重渲染时哪一面板可见由 `target_kind` 决定，不是 radio 状态）。 */
[data-vf-pane] { display: grid; gap: 14px; }
[data-vf-pane][hidden] { display: none; }

/* 号码位数不符时的即时提示（第 47 轮）：用警示色，但**不**用红色 ——
   它不是错误，只是"请你核对一下"，红色会让客户以为号码被拒了。 */
.form__hint--warn { color: var(--warn); }


/* ---------- 订单明细行的产品缩略图（第 55 轮；第 57 轮补齐占位块）----------
   ⚠️ 固定外框 + `object-fit: contain`：不同比例的图不会把行高撑乱，
      也不裁掉产品边缘（业主第 56 轮报过"图撑爆表格"）。
   ⚠️ 尺寸由 CSS 与 `<img width/height>` 属性**双保险**给出 ——
      属性那份是"不依赖 CSS 的最后兜底"（第 56 轮的教训）。 */
.mini-line__thumb {
  inline-size: 40px; block-size: 40px; flex: 0 0 auto;
  border-radius: var(--radius-sm); border: 1px solid var(--line);
  background: var(--bg-soft); object-fit: contain;
  display: block;
}
.mini-line__thumb--ph { display: block; }

/* ==========================================================================
   9. 收货地址簿（第 57 轮，业主需求 1 / 2）
      —— 结算页的「选地址」与个人信息页的「管理地址」**共用**这一套样式，
         所以两处的卡片长得一样（客户不用学两遍）。
   -------------------------------------------------------------------------- */
.addr-picker { display: grid; gap: 12px; }

.addr-list {
  display: grid; gap: 10px;
  list-style: none; margin: 0; padding: 0;
}

/* 一张地址卡：整卡可点（label 包住 radio），触控目标够大 */
.addr-card {
  position: relative;
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg);
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.addr-card:hover { border-color: var(--primary-border); }
/* ⚠️ 选中态用 `:has()` 而不是"JS 加类"：
    JS 挂了/首屏未执行时，客户**仍然看得见**自己选的是哪一条。
    （`:has()` 不支持的老浏览器退化为"没有高亮"，功能不受影响。） */
.addr-card:has(input:checked) {
  border-color: var(--primary);
  background: var(--primary-soft, var(--bg-soft));
}
.addr-card input[type="radio"] {
  flex: 0 0 auto; margin-block-start: 3px;
  inline-size: 18px; block-size: 18px;
}
.addr-card--static { cursor: default; }
.addr-card__body { display: grid; gap: 3px; min-inline-size: 0; }
.addr-card__top {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px;
}
.addr-card__name { color: var(--ink); }
.addr-card__co { color: var(--ink-3); font-size: .8125rem; }
.addr-card__line {
  color: var(--ink-2); font-size: .8125rem;
  overflow-wrap: anywhere;
}
/* 结算页卡片右上角的「编辑」小按钮：不能触发放大整卡选中，
   所以单独做成 button 并 `stopPropagation`（见 addresses.js） */
.addr-card__edit {
  flex: 0 0 auto; margin-inline-start: auto;
  align-self: flex-start;
  background: none; border: 0; padding: 2px 4px;
  color: var(--primary); font-size: .8125rem; cursor: pointer;
  text-decoration: underline;
}
.addr-card__ops {
  margin-inline-start: auto;
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  justify-content: flex-end;
}
.addr-picker__foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
}
.addr-empty {
  margin: 0; padding: 12px 14px;
  border: 1px dashed var(--line); border-radius: var(--radius);
  background: var(--bg-soft); color: var(--ink-2); font-size: .875rem;
}

/* 第 93 轮：结算页「一条地址都没有」的显著提示。
   ★ 业主原话「增加地址的按钮要显著提示（特别是用户尚未设置任何收货地址的时候）」——
     这时候按钮是页面上**唯一**能往前走的路，所以给足尺寸与主色，
     不做成小号描边按钮（那种在密集表单里等于隐形）。
   ★ 用虚线框而不是实心块：表达"这里还是空的，等你填"。 */
.addr-empty-state {
  display: grid;
  justify-items: center;
  gap: 6px;
  padding: 24px 18px;
  border: 1.5px dashed var(--primary-border);
  border-radius: var(--radius);
  background: var(--primary-soft, var(--bg-soft));
  text-align: center;
}
.addr-empty-state__ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; margin-block-end: 2px;
  border-radius: var(--radius-pill);
  background: var(--primary); color: #fff;
  font-size: 1.25rem; font-weight: 700; line-height: 1;
}
.addr-empty-state__title {
  margin: 0; color: var(--ink);
  font-size: 1rem; font-weight: 600; line-height: 1.4;
}
.addr-empty-state__hint {
  margin: 0 0 8px; max-inline-size: 42ch;
  color: var(--ink-2); font-size: .875rem; line-height: 1.6;
}
.addr-empty-state .btn { min-inline-size: 200px; }
/* 无 JS 时删除/设为默认也要能提交 → 表单本身不能占一整行 */
.u-inline { display: inline; }

/* ==========================================================================
   第 85 轮：商家改单提示（买家付款前必须看到「旧值 → 新值」）
   —— 黄条只在"改过且还没确认"时出现；确认后消失（提示常驻会让人无视）
   ★ 只用逻辑属性，RTL（阿语）自动镜像。
   ========================================================================== */
.order-rev--todo {
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
}
.order-rev__hint {
  margin: 0 0 12px;
  color: var(--warn);
  font-size: .9375rem;
  line-height: 1.55;
}
.order-rev__list {
  list-style: none;
  margin: 0 0 14px;
  padding: 0;
  border-block-start: 1px solid var(--warn-border);
}
.order-rev__item {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  align-items: baseline;
  justify-content: space-between;
  padding-block: 9px;
  border-block-end: 1px solid var(--warn-border);
  font-size: .9375rem;
}
.order-rev__k { color: var(--ink-2); }
.order-rev__sku { font-size: .8125rem; }
.order-rev__v {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
}
/* 旧值划掉：让"变了什么"是**一眼可见**的，不用逐字比对 */
.order-rev__old { color: var(--ink-2); text-decoration: line-through; }
.order-rev__arrow { color: var(--ink-2); }

/* ==========================================================================
   第 92 轮：付款指引（确认改单之后，把买家送到"付款"这一步）
   —— 只在「还在等钱 + 没有待确认改动」时出现，见 order_detail.html 的条件注释
   ★ 用主色描边的面板与黄条区分：黄条是"要你核对"，这里是"该付钱了"，
     两块同时出现会互相削弱（实际不会同时出现，但视觉语言要一致）。
   ★ 金额用大字号：付款页最重要的一句话就是"要付多少"。
   ========================================================================== */
.pay-guide {
  border: 1px solid var(--primary-border, #E7C4A6);
  background: var(--primary-soft, #FDF3EA);
}
.pay-guide__due {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 10px;
  margin: 0 0 12px;
  color: var(--ink-2);
}
.pay-guide__due strong {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.2;
}
.pay-guide__tag {
  font-size: .75rem;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--warn-bg, #FDF3DD);
  color: var(--warn, #8A5A00);
}
.pay-guide__hint {
  margin: 0 0 12px;
  color: var(--ink-2);
  font-size: .9375rem;
  line-height: 1.6;
}
.pay-guide__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* ---- 第 94 轮：订单文件（买家**只读**：只有下载，没有删除/改名）---- */
.order-files {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.order-files__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm, 8px);
  background: var(--bg-soft);
}
.order-files__ico { flex: 0 0 auto; color: var(--ink-3); }
.order-files__name {
  flex: 1 1 auto;
  min-inline-size: 0;
  font-weight: 600;
  /* 超长文件名（很多客户发 "PI-2026-...-final-v3.xlsx"）必须能折行，
     否则 375 宽下会把整页撑出横向滚动 */
  overflow-wrap: anywhere;
}
.order-files__meta {
  flex: 0 0 auto;
  color: var(--ink-3);
  font-size: .8125rem;
  white-space: nowrap;
}
@media (max-width: 560px) {
  .order-files__row { flex-wrap: wrap; }
  .order-files__meta { inline-size: 100%; }
  .order-files__row .btn { inline-size: 100%; }
}

/* =====================================================================
   第 113 轮：买家订单详情的「物流」与「售后」两块
   ===================================================================== */

/* ---- 物流：每一票一块 ----
   ★ 用 `<ol>` 而不是 `<ul>`：分批发货时"第 1 批 / 第 2 批"的顺序对买家有意义
     （先到的是补发还是首批，直接决定他该去查哪一个）。 */
.order-logi__empty {
  margin: 0; font-size: 14px; line-height: 1.7; color: var(--ink-3);
}
.order-logi__list {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 12px;
}
.order-logi__item {
  padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--bg-card);
}
.order-logi__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; margin-bottom: 8px;
}
.order-logi__carrier { font-size: 15px; }

/* 运单号：等宽 + 可整段选中（双击只选单号，方便对照箱单） */
.order-logi__no {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 14px; letter-spacing: .02em;
  user-select: all; -webkit-user-select: all;
  word-break: break-all;
}

/* `kv--tight`：物流这栏是"标签 + 值"，比地址栏窄一点，行距收紧一些 */
.kv--tight { row-gap: 6px; }
.kv--tight dt { font-size: 13px; }
.kv--tight dd { font-size: 13.5px; margin: 0; }

.order-logi__track { margin-top: 8px; }
.order-logi__alt { margin: 8px 0 0; font-size: 13px; color: var(--ink-3); }
.order-logi__alt a { color: var(--primary); }

/* ---- 售后 ---- */
.order-as__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.order-as__item {
  padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--bg-soft);
}
.order-as__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; margin-bottom: 6px;
}
.order-as__reason {
  margin: 0 0 8px; font-size: 13.5px; line-height: 1.65;
  white-space: pre-line; word-break: break-word;
}
.order-as__addr {
  margin: 0 0 8px; padding: 8px 10px; border-radius: 8px;
  background: var(--bg-card); border: 1px dashed var(--line);
  font-size: 13px; line-height: 1.6;
}
.order-as__label { display: block; color: var(--ink-3); font-size: 12px; margin-bottom: 2px; }
.order-as__addrtext { white-space: pre-line; word-break: break-word; }
.order-as__note {
  margin: 0 0 6px; font-size: 13px; line-height: 1.6; color: var(--ink-2);
  white-space: pre-line;
}
.order-as__meta { margin: 0; font-size: 12px; color: var(--ink-3); }

/* 窄屏：卡片内边距收紧，别让两栏挤成一团 */
@media (max-width: 480px) {
  .order-logi__item, .order-as__item { padding: 10px 11px; }
  .order-logi__head, .order-as__head { align-items: flex-start; }
}

/* --------------------------------------------------------------------------
   产品目录（第 129 轮，业主 2026-11-02）
   —— 对应 templates/front/account/catalog.html

   ★ 这一页的视觉目标是「可信的文件交付」，不是营销页：
     文件行要像收据（扩展名徽标 + 名称 + 大小 + 动作），版本号要能一眼对上邮件。
   ★ `.alert--success` 之前全站没定义过（只用过 error/warn/info），
     这里补上：已申请成功若不显示绿色条，客户以为没成功，会反复点。
   -------------------------------------------------------------------------- */
.alert--success {
  background: var(--ok-bg); border: 1px solid var(--ok); color: var(--ok);
}

.cat-ver {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .9375rem; color: var(--ink-2);
  margin-inline-start: 6px; letter-spacing: .02em;
}
/* 标题里的徽标不要跟标题挤成一行（窄屏会换行，垂直居中更稳） */
.cat-file-panel .panel__title { display: flex; flex-wrap: wrap; gap: 6px 8px; align-items: center; }

.cat-files { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 8px; }
.cat-file {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg);
}
.cat-file__ext {
  flex: 0 0 auto; min-inline-size: 44px; text-align: center;
  font-size: .6875rem; font-weight: 700; letter-spacing: .04em;
  padding: 4px 6px; border-radius: 4px;
  background: var(--primary-soft); color: var(--primary-hover);
  border: 1px solid var(--primary-border);
}
.cat-file__main { flex: 1 1 auto; min-inline-size: 0; display: grid; gap: 2px; }
.cat-file__name { font-size: .9375rem; word-break: break-word; }
.cat-file__meta { font-size: .75rem; color: var(--ink-3); }
.cat-file__locked { flex: 0 0 auto; font-size: .75rem; color: var(--ink-3); }

/* 历史记录：版本 · 日期 · 状态 · 文件链接，一行读完；窄屏两行 */
.cat-history { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 8px; }
.cat-history__row {
  display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  font-size: .8125rem;
}
.cat-history__ver { font-family: ui-monospace, Menlo, Consolas, monospace; color: var(--ink-2); }
.cat-history__time { color: var(--ink-3); }
.cat-history__files { flex: 1 1 100%; color: var(--ink-2); }
.cat-history__files a { color: var(--accent); text-decoration: underline; }
