/* 中行渠道 H5 样式。

   【视觉方向 2026-08 改版】原方向是"银行权益"：金色只做点缀、不大面积铺，
   刻意压低促销感。现已确认调头为"促销活动"——首屏由「说明文字」改为「利益点」主导：
   顶部沉浸式横幅 + 卡片大面额（¥20/¥30）+ 本周额度强调条 + 底部固定券包入口，
   说明类内容（怎么用、活动规则）全部收进默认折叠块。
   金色降级为分隔与点睛，主色让位给红，因为面额和按钮要抢注意力。

   保留的老类名（.hd/.entry/.card 等）仍被其它页面使用，不要因为首页不用了就删。

   中行对第三方页面有《UI设计规范》，拿到后按其调整（标题栏/返回/字号下限可能有硬性要求）。 */
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

:root {
  --boc-red: #AE1C27;
  --boc-red-lt: #B9242F;
  --boc-red-dark: #7E1119;
  --boc-gold: #C9A227;
  --boc-gold-lt: #E0C883;
  --ink: #1F2328;
  --ink-2: #4A5058;
  /* 原 #8A9099 对比度只有 3.4:1，低于 WCAG AA；调深到 5.4:1 */
  --muted: #6B7280;
  --line: #ECEEF1;
  --bg: #F5F6F8;
  --radius-card: 16px;
  --radius-ctl: 10px;
  --radius-btn: 12px;

  /* 全站顶部横幅的两层背景，首页(.hero)与其余页面(.hd)共用同一套，
     换素材只改这一行。url 相对本 css 文件解析 → /boc/img/banner.jpg。
     veil 的不透明度 .88~.94 是调出来的：再低车影会抢标题，再高照片就等于白放。
     注意 /boc/img/ 必须在 security.redission.ignored 里放行，
     否则登录拦截器会把图片请求拦成 401，表现为"样式正常但图不显示"。 */
  --banner-img: url('../img/banner.jpg');
  --banner-veil: linear-gradient(160deg, rgba(194,46,51,.94) 0%, rgba(174,30,35,.88) 45%, rgba(142,21,25,.92) 100%);
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
  background: var(--bg);
  color: var(--ink);
  min-height: 100vh;
  font-size: 18px;
  line-height: 1.5;
}

/* ---------- 头部 ---------- */
/* 底部圆角收口：原来是直角，红色会从下方白卡两侧漏出一条脏边 */
/* 背景与首页横幅同一套（红色遮罩盖实拍图），高度仍由各页自己的 padding 决定：
   .hd 常规 / .hd-slim 矮。background-size:cover 会自动适配，
   矮头部只是把同一张图裁得更窄，不需要另做素材。 */
.hd {
  background-color: var(--boc-red);
  background-image: var(--banner-veil), var(--banner-img);
  background-size: cover, cover;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
  color: #fff;
  padding: 22px 18px 44px;
  position: relative;
  border-radius: 0 0 22px 22px;
  /* 下面那颗暗纹圆是负偏移的，不裁掉会顶出横向滚动条 */
  overflow: hidden;
}
/* 右上角暗纹，避免大块纯色发闷 */
.hd::before {
  content: ''; position: absolute; right: -40px; top: -60px;
  width: 180px; height: 180px; border-radius: 50%;
  background: rgba(255,255,255,.05);
}
/* 全页唯一的金色横线，只在头部与内容之间出现一次。
   bottom 必须落在「头部文字底部」与「白卡顶边」之间那条露出来的红条里：
   白卡上移 26px（.wrap margin-top），压住 26px 以下的一切，写小了这条线直接看不见 */
.hd::after {
  content: ''; position: absolute; left: 18px; right: 18px; bottom: 35px; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(224,200,131,.85) 22%, rgba(224,200,131,.85) 78%, transparent);
}
.hd h1 { font-size: 24px; font-weight: 700; letter-spacing: .5px; position: relative; }
.hd p { margin-top: 5px; font-size: 12.5px; color: rgba(255,255,255,.82); position: relative; }
.hd .back {
  position: absolute; right: 16px; top: 20px; z-index: 1;
  font-size: 17px; color: #fff;
  border: 1px solid rgba(255,255,255,.45); border-radius: 13px; padding: 3px 11px;
  background: rgba(255,255,255,.08);
}
.hd .back:active { background: rgba(255,255,255,.2); }
/* 无副标题的页面（领取记录、协议长文）用矮头部，否则红块空一大片 */
.hd-slim { padding-bottom: 34px; }
.hd-slim::after { bottom: 30px; }

.wrap { padding: 0 14px 26px; margin-top: -26px; position: relative; }
/* 首页改版后内容区不再上移压住头部：它上面是额度条(浅红底)，
   压上去会把额度条切掉一半。其它页面仍用默认的 -26px 压住 .hd */
.wrap-flat { margin-top: 14px; }

/* ---------- 卡片与小节标题 ---------- */
.card {
  background: #fff; border-radius: var(--radius-card); border: 1px solid #EEF0F3;
  box-shadow: 0 3px 14px rgba(20,30,50,.07); padding: 18px 16px; margin-bottom: 12px;
}
/* 小节标题：左侧金色竖条，全页统一 */
.card h2, .ct {
  display: flex; align-items: center; gap: 7px;
  font-size: 14px; font-weight: 600; margin-bottom: 11px;
}
.card h2::before, .ct::before {
  content: ''; width: 3px; height: 13px; border-radius: 2px;
  background: linear-gradient(180deg, var(--boc-gold-lt), var(--boc-gold));
}

/* ---------- 按钮 ---------- */
.btn {
  display: block; width: 100%; border-radius: var(--radius-btn);
  /* 透明边框而不是 border:0 —— 双栏里一栏实心一栏 ghost 时，
     两个按钮不会因为 ghost 多出 1px 边框而差 2px 高 */
  border: 1px solid transparent;
  background: linear-gradient(135deg, var(--boc-red-lt), var(--boc-red-dark));
  color: #fff; font-size: 18px; font-weight: 600; padding: 12px 0;
  text-align: center; text-decoration: none;   /* .btn 也用在 <a> 上 */
  box-shadow: 0 4px 12px rgba(174,28,39,.24);
  transition: transform .12s, filter .12s;
}
/* 原来 tap-highlight 被禁用又没补按压态，真机上点着像坏了 */
.btn:active { transform: scale(.98); filter: brightness(.93); }
.btn:disabled, .btn.is-disabled {
  background: #EDEFF2; color: #9AA0A8; box-shadow: none; transform: none; filter: none;
}
.btn.ghost {
  background: #fff; color: var(--boc-red); border: 1px solid var(--boc-red); box-shadow: none;
}
.btn.ghost:active { background: #FDF3F4; }

/* ==================================================================
   首页改版：沉浸式横幅 / 额度条 / 大面额卡片 / 折叠块 / 底部操作条
   ================================================================== */

/* ---------- 顶部沉浸式横幅 ---------- */
/* 背景用 :root 里的 --banner-veil / --banner-img 两层，与其余页面的 .hd 同一套 */
.hero {
  position: relative; color: #fff; overflow: hidden;
  /* 单独留一层 --hero-img 而不是直接用 --banner-img：运营在后台给领取规则配了
     page_bg_url 时，JS 只覆盖这个变量，遮罩层和其余页面的背景都不受影响 */
  --hero-img: var(--banner-img);
  background-color: var(--boc-red);
  background-image: var(--banner-veil), var(--hero-img);
  background-size: cover, cover;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
  padding-bottom: 30px;
}
/* 右上角光晕，避免大块纯色发闷。负偏移，靠 overflow:hidden 裁掉 */
.hero::after {
  content: ''; position: absolute; right: -60px; top: -70px;
  width: 220px; height: 220px; border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,.14), transparent 68%);
}
.hero-nav, .hero-body { position: relative; z-index: 1; }

/* 导航行：左箭头 + 居中标题，对齐中行 App 原生导航的观感。
   高度 44px 是 iOS 导航条标准高度，中行 WebView 若自带导航条，
   这一行会显得重复 —— 那时把 .hero-nav 整行 display:none 即可，不影响下面的横幅 */
.hero-nav {
  height: 44px; display: flex; align-items: center; justify-content: center;
  padding: 0 44px;
}
.hero-nav h1 {
  font-size: 19px; font-weight: 600; letter-spacing: .5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 纯 CSS 画的返回箭头，省一个图标请求。点击区域撑到 44x44 满足触控下限 */
.hero-back {
  position: absolute; left: 0; top: 0; width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
}
.hero-back::before {
  content: ''; width: 11px; height: 11px;
  border-left: 2px solid #fff; border-bottom: 2px solid #fff;
  transform: rotate(45deg); border-radius: 1px;
}
.hero-back:active { opacity: .6; }

.hero-body { padding: 14px 20px 0; }
.hero-eyebrow {
  font-size: 11px; letter-spacing: 3px; font-weight: 500;
  color: rgba(255,255,255,.72); text-transform: uppercase;
}
.hero-title {
  font-size: 27px; line-height: 1.28; font-weight: 700; margin-top: 9px;
  text-shadow: 0 2px 12px rgba(80,8,14,.35);
}
/* 单行标题（后台只配了 heroTitle1）。27px 排 12 个汉字在 360px 屏上必折行，
   收到 24px 才排得下；小屏再降一档。不用 nowrap —— 万一文案配得更长，
   折行也比被 .hero 的 overflow:hidden 裁掉半个字要好看 */
.hero-title.one-line { font-size: 27px; letter-spacing: -.2px; }
@media (max-width: 359px) {
  .hero-title.one-line { font-size: 21px; }
}
.hero-sub { font-size: 15px; color: rgba(255,255,255,.9); margin-top: 10px; }
.hero-date {
  display: flex; align-items: center; gap: 5px;
  font-size: 12px; color: rgba(255,255,255,.76); margin-top: 8px; min-height: 17px;
}
.hero-date-ico { width: 13px; height: 13px; stroke: rgba(255,255,255,.76); fill: none; stroke-width: 1.6; flex: none; }

/* ---------- 本周额度强调条 ---------- */
/* 贴在横幅正下方，是横幅到卡片之间的过渡带。
   JS 填不出内容时 innerHTML 为空，这条整体不占位（靠 :empty） */
.quota { background: #FDF1F2; }
.quota:empty { display: none; }
.quota-in {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  padding: 12px 16px; font-size: 16px; color: var(--boc-red); font-weight: 500;
}
.quota-in b { font-size: 16px; font-weight: 700; margin: 0 1px; }
.quota-ico { width: 15px; height: 15px; stroke: none; fill: var(--boc-red); flex: none; }

/* ---------- 双栏领取卡（改版：通栏图 + 大面额） ---------- */
/* 两栏等宽等高，视觉上不分主次——它们是两个独立入口，不是主次关系。
   align-items:stretch 是默认值，这里靠它保证一栏文案多时两栏仍等高 */
.duo { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; margin-bottom: 10px; }
.duo-item {
  background: #fff; border-radius: var(--radius-card); overflow: hidden;
  border: 1px solid #EEF0F3; box-shadow: 0 4px 16px rgba(20,30,50,.08);
  display: flex; flex-direction: column;
}
/* 卡片顶部分类彩条。::before 在 flex 列里就是第一个子项，天然排在图片上方。
   它和标签同色，是两栏"这是两种不同的券"的第二重信号 —— 标签会被图片深色区吃掉，
   这条彩条压在纯白卡沿上，任何图都盖不住 */
.duo-item::before { content: ''; display: block; height: 4px; flex: none; }
.wash.duo-item::before { background: #2C72C6; }
.oil.duo-item::before  { background: #E07B1E; }

/* 顶部通栏图。固定 16:10，两栏永远等高。
   分类默认图随包发布，后端给了 couponImgUrl/giftImgUrl 时由内联 style 覆盖
   （内联优先级高于样式表）—— 所以这里永远有图，不存在空白态。 */
.duo-pic {
  position: relative; width: 100%; padding-top: 62.5%;
  background-size: cover; background-position: center; background-repeat: no-repeat;
  background-color: #F2F3F5;
}
.wash .duo-pic { background-image: url('../img/card-wash.jpg'); }
.oil  .duo-pic { background-image: url('../img/card-oil.jpg'); }
/* 分类标签：洗车蓝 / 加油橙。这是全页仅有的两处非红色强调色，
   作用是让用户在 0.5 秒内分清左右两栏是两种不同的券 */
.duo-tag {
  position: absolute; left: 8px; top: 8px;
  font-size: 18px; font-weight: 600; color: #fff;
  padding: 3px 9px; border-radius: 20px; letter-spacing: .5px;
  box-shadow: 0 2px 6px rgba(0,0,0,.18);
}
.wash .duo-tag { background: #2C72C6; }
.oil  .duo-tag { background: #E07B1E; }

/* 上下内边距刻意比左右紧：卡片里只剩「券名 + 按钮 + 状态提示」三块，
   原来的间距是按还有面额、门槛两行时调的，现在会显得空 */
.duo-body {
  flex: 1; display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 12px 10px 11px;
}
/* 面额：整张卡的视觉焦点。用等宽数字字体避免 20/30 宽度跳动 */
.duo-amt {
  display: flex; align-items: baseline; justify-content: center;
  color: var(--boc-red); line-height: 1; margin-bottom: 7px;
}
.duo-amt .cny { font-size: 17px; font-weight: 700; margin-right: 2px; }
.duo-amt b {
  font-size: 36px; font-weight: 700; letter-spacing: -1px;
  font-family: 'DIN Alternate', 'Helvetica Neue', sans-serif;
}
/* margin-bottom 是券名和按钮之间的下限：按钮的 margin-top:auto 只在有富余空间时
   才撑开,两栏一样高时富余为 0,不给下限的话券名会贴到按钮上 */
.duo-item h3 { font-size: 18px; font-weight: 600; line-height: 1.35; margin-bottom: 12px; }
/* min-height 保证「无门槛」和「满 100 元可用」换行与否都不影响两栏按钮对齐 */
.duo-sub { font-size: 11.5px; color: var(--muted); margin-top: 4px; min-height: 32px; }
/* 按钮撑满卡片宽度并顶到底部，margin-top:auto 让文案长短不影响按钮位置 */
.duo-btn { font-size: 14px; padding: 11px 0; border-radius: 22px; margin-top: auto; }
/* 按钮下面的状态提示（已领取/暂不可领的原因）。
   字号必须压到 12px：卡片只有半屏宽，正文区实宽约 155px，
   「已领取，8月24日可再领」在 15px 下要占 172px，一折行两栏按钮就不齐了。
   min-height 兜住这一行的高度，让补空占位的那一栏和有提示的那一栏一样高 */
.next-tip {
  font-size: 13.5px; color: var(--muted); line-height: 1.4;
  margin-top: 8px; min-height: 17px;
}
.next-tip b { color: var(--ink-2); font-weight: 600; }

/* 卡片下方那句「额度独立计算」。位置在卡片正下方是有意的，
   它回答的是用户看到两张卡时的第一个疑问：是二选一还是都能领 */
.duo-note {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  font-size: 11.5px; color: var(--muted); margin-bottom: 14px; line-height: 1.5;
}
.duo-note-ico { width: 13px; height: 13px; stroke: #B4BAC2; fill: none; stroke-width: 1.7; flex: none; }

/* 卡内金线：改版后卡片里不再有它，保留定义供其它页面复用 */
.gold-line {
  width: 44px; height: 1px; margin: 9px auto 11px;
  background: linear-gradient(90deg, transparent, var(--boc-gold-lt), transparent);
}

/* ---------- 折叠块（怎么用 / 活动规则） ---------- */
/* 默认收起。改版前这两块常驻展开，加起来吃掉大半屏，把领取卡挤出首屏 */
.fold {
  background: #fff; border-radius: var(--radius-card); border: 1px solid #EEF0F3;
  box-shadow: 0 3px 14px rgba(20,30,50,.07); margin-bottom: 12px; overflow: hidden;
}
.fold-hd {
  display: flex; align-items: center; gap: 7px;
  padding: 15px 16px; font-size: 18px; font-weight: 600; position: relative;
}
/* 沿用全页统一的金色竖条小节标题 */
.fold-hd::before {
  content: ''; width: 3px; height: 13px; border-radius: 2px; flex: none;
  background: linear-gradient(180deg, var(--boc-gold-lt), var(--boc-gold));
}
.fold-hd:active { background: #FAFBFC; }
.fold-arrow {
  position: absolute; right: 16px; top: 50%; width: 8px; height: 8px;
  border-right: 1.8px solid #B4BAC2; border-bottom: 1.8px solid #B4BAC2;
  transform: translateY(-70%) rotate(45deg); transition: transform .2s;
}
.fold.on .fold-arrow { transform: translateY(-25%) rotate(-135deg); }
/* 用 max-height 而不是 display:none，收起/展开有过渡；
   1000px 是够用的上限（使用须知在窄屏上能排到 500px 上下），
   条目再多也不会被截断，超过就只是没有过渡效果而已 */
.fold-bd { max-height: 0; overflow: hidden; transition: max-height .25s ease; padding: 0 16px; }
.fold.on .fold-bd { max-height: 1000px; padding-bottom: 14px; }

/* ---------- 底部固定操作条 ---------- */
/* body 要加 .has-dock 留出等高内边距，否则最后一屏内容会被压在条下面 */
body.has-dock { padding-bottom: 78px; }
.dock {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  background: rgba(255,255,255,.96); border-top: 1px solid var(--line);
  backdrop-filter: saturate(180%) blur(10px);
}
.dock-sub {
  flex: none; width: 86px; text-align: center; font-size: 16px;
  color: var(--ink-2); text-decoration: none; padding: 12px 0;
}
.dock-sub:active { color: var(--boc-red); }
.dock-main { flex: 1; border-radius: 24px; font-size: 15.5px; padding: 13px 0; }

/* ---------- 次级入口：一行两列，替代两个全宽红框大按钮，省出约 100px 纵向空间 ---------- */
.entry {
  background: #fff; border-radius: var(--radius-card); border: 1px solid #EEF0F3;
  box-shadow: 0 3px 14px rgba(20,30,50,.07); display: flex; overflow: hidden;
}
.entry a {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 7px;
  padding: 14px 0; font-size: 13.5px; color: var(--ink); text-decoration: none;
}
.entry a:active { background: #F7F8FA; }
.entry a + a { border-left: 1px solid var(--line); }
.entry svg { width: 17px; height: 17px; stroke: var(--boc-red); fill: none; stroke-width: 1.6; }
.entry em { font-style: normal; color: #C2C6CC; font-size: 15px; margin-left: 1px; }

/* ---------- 使用流程 / 规则 / 说明 ---------- */
/* 使用须知：带序号的条目。序号用 counter 画，文案里就不用再写"1、"，
   运营改文案时不会把序号改乱。红色小圆点和领取按钮同一套渐变 */
.notes { list-style: none; counter-reset: n; }
/* 序号用绝对定位而不是 flex：第 2 条里还嵌了一层步骤 ol，
   flex 会把它和"使用方法："排成左右两列 */
.notes > li {
  counter-increment: n; position: relative; padding: 8px 0 8px 24px;
  font-size: 16px; color: var(--ink-2); line-height: 1.85;
}
.notes > li + li { border-top: 1px dashed var(--line); }
.notes > li::before {
  content: counter(n); position: absolute; left: 0; top: 11px;
  width: 16px; height: 16px; border-radius: 50%;
  background: linear-gradient(135deg, var(--boc-red-lt), var(--boc-red-dark));
  color: #fff; font-size: 10.5px; font-weight: 700; line-height: 16px; text-align: center;
}
/* 二级步骤：用 1. 2. 3. 而不是再套一层圆点，免得和一级序号混淆 */
.notes .sub { list-style: none; counter-reset: m; margin-top: 2px; }
.notes .sub li { counter-increment: m; position: relative; padding-left: 16px; }
.notes .sub li::before {
  content: counter(m) '.'; position: absolute; left: 0;
  color: var(--boc-red); font-weight: 700;
}

.rules { list-style: none; }
.rules li { font-size: 12px; color: var(--ink-2); line-height: 1.85; padding-left: 12px; position: relative; }
.rules li::before {
  content: ''; position: absolute; left: 0; top: 9px;
  width: 4px; height: 4px; border-radius: 50%; background: var(--boc-gold);
}

.why { list-style: none; }
.why li { display: flex; gap: 8px; font-size: 16px; color: var(--ink-2); line-height: 1.7; padding: 6px 0; }
.why svg { width: 14px; height: 14px; stroke: var(--boc-gold); fill: none; stroke-width: 1.9; flex: none; margin-top: 3px; }

.desc { font-size: 12px; color: var(--ink-2); line-height: 1.9; }
.desc li { margin-left: 16px; }

/* ---------- 券包 ---------- */
.tabs {
  display: flex; background: #fff; border-radius: var(--radius-card);
  border: 1px solid #EEF0F3; overflow: hidden; margin-bottom: 12px;
}
.tabs div { flex: 1; text-align: center; padding: 12px 0; font-size: 18px; color: var(--muted); position: relative; }
.tabs div.on { color: var(--boc-red); font-weight: 600; }
.tabs div.on::after {
  content: ''; position: absolute; left: 50%; bottom: 6px; transform: translateX(-50%);
  width: 20px; height: 2.5px; background: var(--boc-red); border-radius: 2px;
}
/* 数量角标：只有该 tab 加载过才渲染，没加载过不显示，避免为了角标多打两次接口 */
.tabs div span {
  display: inline-block; min-width: 16px; height: 16px; line-height: 16px; padding: 0 4px; margin-left: 3px;
  background: #F1F2F4; color: var(--muted); border-radius: 8px; font-size: 10.5px; font-weight: 600;
}
.tabs div.on span { background: #FBEAEC; color: var(--boc-red); }

/* 券卡：左面额 / 右信息，中间虚线 + 上下缺口，票券语汇但克制 */
.coupon {
  display: flex; background: #fff; border-radius: var(--radius-card);
  border: 1px solid #EEF0F3; box-shadow: 0 3px 14px rgba(20,30,50,.06);
  margin-bottom: 11px; position: relative;
}
/* 缺口：左栏固定 98px，缺口圆心压在分隔线上 */
.coupon::before, .coupon::after {
  content: ''; position: absolute; left: 92px; width: 12px; height: 12px;
  border-radius: 50%; background: var(--bg);
}
.coupon::before { top: -6px; }
.coupon::after { bottom: -6px; }
.coupon .amt {
  width: 98px; flex: none; padding: 16px 6px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  color: var(--boc-red); font-weight: 700; line-height: 1; position: relative;
}
.coupon .amt::after {
  content: ''; position: absolute; right: 0; top: 12px; bottom: 12px; width: 1px;
  background: repeating-linear-gradient(180deg, #E3E6EA 0 4px, transparent 4px 8px);
}
.coupon .amt .yuan { font-size: 24px; margin-right: 1px; }
.coupon .amt b { font-size: 36px; letter-spacing: -1px; font-family: 'DIN Alternate', 'Helvetica Neue', sans-serif; }
.coupon .amt .limit { display: block; font-size: 14px; color: var(--muted); margin-top: 5px; font-weight: 400; }
.coupon .info { flex: 1; min-width: 0; padding: 14px 13px 13px 15px; }
.coupon .info h3 { font-size: 18px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.coupon .info p { font-size: 14px; color: var(--muted); margin-top: 5px; }
/* 不要叫 .foot：那是页脚小字的类名，会把 padding / 灰色继承过来 */
.coupon .cp-foot { display: flex; align-items: center; justify-content: space-between; margin-top: 10px; }
.coupon .go {
  border: 0; background: linear-gradient(135deg, var(--boc-red-lt), var(--boc-red-dark)); color: #fff;
  font-size: 12.5px; font-weight: 600; border-radius: 14px; padding: 6px 14px;
  transition: transform .12s, filter .12s;
}
.coupon .go:active { transform: scale(.96); filter: brightness(.93); }
/* 失效态整卡降饱和，而不是只灰按钮 */
.coupon.off .amt, .coupon.off .info h3 { color: #A8AEB6; }
.coupon.off .go { background: #E9EBEE; color: #A8AEB6; box-shadow: none; }

.tag { font-size: 14px; border-radius: 4px; padding: 2px 6px; border: 1px solid; letter-spacing: .3px; }
.tag.gold { color: #9A7B18; border-color: var(--boc-gold-lt); background: #FDF9EF; }
.tag.grey { color: var(--muted); border-color: #E1E4E8; background: #F7F8FA; }

/* ---------- 券详情 ---------- */
/* 券头卡：分类底图 + 红色渐变遮罩，左券名右大面额。
   底图复用首页卡片那两张，按分类走 CSS 默认值 —— 券详情接口没有图片字段，
   与其为了一张背景图去改共用的 SdkCouponDetailVO，不如让分类决定。 */
.cp-hero {
  position: relative; height: 92px; overflow: hidden;
  background-size: cover; background-position: center; background-color: var(--boc-red);
}
.cp-hero.wash { background-image: url('../img/card-wash.jpg'); }
.cp-hero.oil  { background-image: url('../img/card-oil.jpg'); }
/* 左深右浅：左侧压住文字保证可读，右侧留出照片,不做成一整块死红 */
.cp-hero::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(174,30,35,.92) 0%, rgba(174,30,35,.42) 100%);
}
.cp-hero-in {
  position: relative; z-index: 1; height: 100%;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 0 16px; color: #fff;
}
.cp-hero-l { min-width: 0; }
.cp-hero-l h2 {
  font-size: 20px; font-weight: 600; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cp-hero-l p { font-size: 16px; color: rgba(255,255,255,.86); margin-top: 4px; }
.cp-hero-amt { flex: none; display: flex; align-items: baseline; }
.cp-hero-amt span { font-size: 16px; font-weight: 600; margin-right: 1px; }
.cp-hero-amt b {
  font-size: 34px; font-weight: 700; line-height: 1; letter-spacing: -1px;
  font-family: 'DIN Alternate', 'Helvetica Neue', sans-serif;
}
/* 有效期 + 状态标签，贴在券头卡下沿 */
.cp-meta {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 16px; font-size: 14px; color: var(--muted);
}
.cp-meta b { color: var(--ink); font-weight: 500; }
.tag.on { color: var(--boc-red); border-color: #F0C9CD; background: #FDF1F2; }

/* 券码区。失效态压一层遮罩而不是把码藏起来 —— 用户仍需要看到自己领过什么 */
.cp-redeem { position: relative; text-align: center; padding: 18px 16px 16px; }
.cp-redeem-tip { font-size: 15.5px; color: var(--muted); margin-bottom: 14px; }
.cp-mask {
  position: absolute; inset: 0; background: rgba(255,255,255,.82);
  display: flex; align-items: center; justify-content: center;
}
.cp-mask span {
  border: 2px solid #A8AEB6; color: #7C838C; border-radius: 8px;
  font-size: 17px; font-weight: 700; letter-spacing: 3px; padding: 7px 18px;
  transform: rotate(-12deg); background: rgba(255,255,255,.9);
}

.code-box { text-align: center; padding: 4px 0 0; }
/* 二维码容器。选择器故意不限定在 .code-box 下 —— detail 页的二维码挂在 .cp-redeem 里，
   原来那两条够不着它，手机上就偏左了。
   偏左的原因在 qrcode.js：它先画 canvas，再把结果换成一张 <img> 并内联写死 display:block；
   块级元素不吃父级的 text-align:center，所以容器先 flex 居中，图自己再 auto 兜一次。
   table 是 canvas 不可用时的降级分支，一并带上 */
.qr { display: flex; justify-content: center; margin: 0 auto 14px; }
.qr img, .qr canvas, .qr table { display: block; margin: 0 auto; }
.code-box .code {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 19px; letter-spacing: 2px; word-break: break-all; color: var(--ink);
  background: #F7F8FA; border: 1px dashed #DDE1E6; border-radius: var(--radius-ctl); padding: 12px 8px;
}
.meta { border-top: 1px solid var(--line); margin-top: 14px; padding-top: 12px; }
.meta div { display: flex; justify-content: space-between; font-size: 12.5px; padding: 4px 0; }
.meta span { color: var(--muted); flex: none; }
.meta b { font-weight: 500; color: var(--ink-2); text-align: right; margin-left: 12px; }

/* ---------- 空态：图标 + 主副文案 + 行动按钮 ---------- */
.empty { text-align: center; padding: 46px 20px 0; color: var(--muted); font-size: 13px; }
.empty .ico {
  width: 76px; height: 76px; margin: 0 auto 16px; border-radius: 50%;
  background: linear-gradient(160deg, #F3F4F6, #EAECEF);
  display: flex; align-items: center; justify-content: center;
}
.empty .ico svg { width: 34px; height: 34px; stroke: #C3C8CE; fill: none; stroke-width: 1.4; }
.empty h4 { font-size: 18px; font-weight: 600; color: var(--ink-2); }
.empty p { font-size: 15px; color: var(--muted); margin-top: 6px; line-height: 1.7; }
.empty .empty-go {
  display: inline-block; margin-top: 18px; border: 1px solid var(--boc-red); color: var(--boc-red);
  background: #fff; border-radius: var(--radius-btn); font-size: 13.5px; font-weight: 600; padding: 9px 26px;
}
.empty .empty-go:active { background: #FDF3F4; }

.loading { text-align: center; color: var(--muted); font-size: 13px; padding: 40px 0; }

/* ---------- 领取结果 ---------- */
.rs { text-align: center; padding: 30px 20px 26px; }
/* 这里的 h2 是结果标题，不是小节标题，去掉 .card h2 的金色竖条与 flex 布局 */
.card.rs h2 { display: block; font-size: 24px; font-weight: 600; margin: 0 0 8px; }
.card.rs h2::before { display: none; }
.rs-ico {
  width: 64px; height: 64px; border-radius: 50%; margin: 0 auto 14px;
  display: flex; align-items: center; justify-content: center;
}
.rs-ico svg { width: 30px; height: 30px; fill: none; stroke-width: 2; }
.rs-ico.ok { background: linear-gradient(150deg, #FCEFF0, #F8E3E5); }
.rs-ico.ok svg { stroke: var(--boc-red); }
.rs-ico.fail { background: linear-gradient(160deg, #F3F4F6, #EAECEF); }
.rs-ico.fail svg { stroke: #9AA0A8; }
.rs-sub { font-size: 16px; color: var(--muted); line-height: 1.7; }

/* 本次领到的券。异步补上来的，拿不到就整块不渲染 —— 结果页的核心是"领取成功"
   那四个字，它由服务端直出，绝不能因为这块加载失败而受影响 */
.rs-cp {
  background: #fff; border-radius: var(--radius-card); border: 1px solid #EEF0F3;
  box-shadow: 0 3px 14px rgba(20,30,50,.07); margin-bottom: 12px; overflow: hidden;
  text-align: left;
}
.rs-cp-top { display: flex; align-items: center; gap: 14px; padding: 16px; }
/* 面额块。底色按分类走，与首页彩条、券包标签、记录页标签同一套配色 */
.rs-cp-amt {
  flex: none; width: 76px; height: 66px; border-radius: 12px;
  display: flex; align-items: baseline; justify-content: center;
  color: var(--boc-red); background: #FBEAEC;
}
.wash.rs-cp .rs-cp-amt { color: #2C72C6; background: #E8F1FB; }
.oil.rs-cp  .rs-cp-amt { color: #C86A14; background: #FDF0E2; }
.rs-cp-amt span { font-size: 15px; font-weight: 700; margin-right: 1px; align-self: center; }
.rs-cp-amt b {
  font-size: 20px; font-weight: 700; letter-spacing: -1px; align-self: center;
  font-family: 'DIN Alternate', 'Helvetica Neue', sans-serif;
}
.rs-cp-info { flex: 1; min-width: 0; }
.rs-cp-info h3 {
  font-size: 17px; font-weight: 600; line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rs-cp-exp { font-size: 15px; color: var(--muted); margin-top: 6px; }
/* 券码行。虚线分隔沿用票券语汇，与券包/券详情一致 */
/* 券码行。虚线分隔沿用票券语汇，与券包/券详情一致。
   按钮文案从「复制」变成「复制并去小程序使用」后，手机上一行放不下券码 + 按钮，
   所以让按钮换行独占整宽 —— 它现在是主操作（复制 + 拉起小程序），
   和券详情页底部那颗是同一件事，挤在右边的小按钮既放不下也不像主操作 */
.rs-cp-code {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px;
  margin: 0 16px; padding: 12px 0 14px;
  border-top: 1px dashed #DDE1E6;
}
.rs-cp-code-txt span { display: block; font-size: 18px; color: var(--muted); }
.rs-cp-code-txt b {
  display: block; margin-top: 3px; font-size: 17px; font-weight: 600; letter-spacing: 1.5px;
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace; word-break: break-all;
  /* 这里展示的是打码后的券码，长按选中抄下来也没用；
     保留可选中只是不想让文字变得"死板"，真要手抄的场景在跳转失败的弹窗里 */
  -webkit-user-select: text; user-select: text;
}
.rs-cp-copy {
  flex: 1 0 100%; border: 1px solid var(--boc-red); background: #fff;
  color: var(--boc-red); font-size: 13px; font-weight: 600;
  border-radius: var(--radius-ctl); padding: 8px 18px;
}
.rs-cp-copy:active { background: #FDF3F4; }
/* "几号可再领"。给个 min-height 占位，避免异步填入时页面往下跳 */
.rs-next {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  font-size: 14px; color: var(--muted); margin: 0 0 14px; min-height: 17px;
}
.rs-next-ico { width: 13px; height: 13px; fill: #B4BAC2; stroke: none; flex: none; }

/* ---------- 领取记录 ---------- */
/* 券种筛选。吸顶,长列表往下翻时仍能切换 */
.chips {
  display: flex; gap: 9px; padding: 10px 0 12px;
  position: sticky; top: 0; z-index: 5; background: var(--bg);
}
.chip {
  border: 1px solid #DDE1E6; background: #fff; color: var(--ink-2);
  font-size: 18px; border-radius: 20px; padding: 6px 16px; white-space: nowrap;
}
.chip.on { border-color: var(--boc-red); color: var(--boc-red); background: #FDF1F2; font-weight: 600; }

/* 分组头："本周 · 08.17–08.23 ... 共 2 次"。
   按【周】分组而不是按天：活动本身就是每周一次额度,按周切段与用户的心理模型一致,
   同一天领的两张也不会被拆成两组 */
.rec-day {
  display: flex; align-items: baseline; gap: 8px;
  padding: 4px 2px 9px; margin-top: 14px;
}
.rec-day:first-child { margin-top: 0; }
.rec-day b { font-size: 16px; font-weight: 600; color: var(--ink); flex: none; }
.rec-day span { font-size: 15px; color: var(--muted); flex: none; }
.rec-day .cnt { margin-left: auto; }
/* 一条记录 = 分类图标 + 券名/状态 + 领取/核销时间 + 面额 + 进详情箭头。
   改版前是"点开展开看券信息"，现在直接跳券详情页 —— 那一页已经把券码、二维码、
   有效期、使用须知都做全了，在列表里再展开一份小抄是重复建设。 */
.rec {
  background: #fff; border-radius: var(--radius-card); border: 1px solid #EEF0F3;
  box-shadow: 0 3px 14px rgba(20,30,50,.06); margin-bottom: 10px; overflow: hidden;
}
.rec .top { display: flex; align-items: center; gap: 11px; padding: 13px 14px; }
.rec .top:active { background: #FAFBFC; }
/* 分类图标块。用色块+文字而不是图标字体：不引第三方图标库，也不再多下一张图 */
.rec .ico {
  flex: none; width: 42px; height: 42px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 600; letter-spacing: .5px;
}
.rec.wash .ico { background: #E8F1FB; color: #2C72C6; }
.rec.oil  .ico { background: #FDF0E2; color: #C86A14; }
.rec .info { flex: 1; min-width: 0; }
.rec .nm { display: flex; align-items: center; gap: 6px; }
.rec .nm h3 {
  font-size: 17px; font-weight: 600; line-height: 1.4; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rec .time { font-size: 14px; color: var(--muted); margin-top: 5px; }
/* 面额靠右，与券名同一视觉高度 */
.rec .amt {
  flex: none; font-size: 21px; font-weight: 700; color: var(--boc-red);
  font-family: 'DIN Alternate', 'Helvetica Neue', sans-serif;
}
.rec .arrow {
  flex: none; width: 7px; height: 7px; margin-left: 2px;
  border-right: 1.8px solid #C2C6CC; border-bottom: 1.8px solid #C2C6CC;
  transform: rotate(-45deg);
}
/* 已使用/已过期整条降饱和,而不是只把标签灰掉 —— 一眼扫过去就知道哪些还能用 */
.rec.off { background: #FCFCFD; }
.rec.off .ico { background: #F1F2F4; color: #A8AEB6; }
.rec.off .nm h3, .rec.off .amt { color: #A8AEB6; }
/* 列表底部的再领入口。记录页看完通常就是想再领一张，不给出口用户只能按返回 */
.rec-more { margin: 18px 0 4px; text-align: center; }
.rec-more a {
  display: inline-block; border: 1px solid var(--boc-red); color: var(--boc-red);
  background: #fff; border-radius: var(--radius-btn); font-size: 18px; font-weight: 600;
  padding: 9px 30px; text-decoration: none;
}
.rec-more a:active { background: #FDF3F4; }

/* ---------- 弹窗 / toast ---------- */
.mask { position: fixed; inset: 0; background: rgba(0,0,0,.45); display: none; align-items: center; justify-content: center; z-index: 99; }
.mask.on { display: flex; }
.dlg {
  background: #fff; border-radius: var(--radius-card); width: 78%; max-width: 320px;
  padding: 22px 18px 16px; text-align: center;
}
.dlg h3 { font-size: 16px; font-weight: 600; margin-bottom: 8px; }
.dlg p { font-size: 16px; color: var(--muted); margin-bottom: 12px; word-break: break-all; }
/* 自动复制失败时用户要长按选中这段码，所以显式声明可选中，并做成券码样式 */
.dlg .dlg-code {
  font-family: 'SFMono-Regular', Menlo, Consolas, monospace; font-size: 17px; letter-spacing: 1.5px;
  color: var(--ink); background: #F7F8FA; border: 1px dashed #DDE1E6;
  border-radius: var(--radius-ctl); padding: 10px 8px; margin-bottom: 16px;
  word-break: break-all; -webkit-user-select: text; user-select: text;
}

.toast {
  position: fixed; left: 50%; top: 45%; transform: translate(-50%,-50%);
  background: rgba(0,0,0,.78); color: #fff; font-size: 13px;
  padding: 10px 18px; border-radius: 8px; z-index: 200; max-width: 78%; text-align: center;
  display: none;
}
.toast.on { display: block; }

/* ---------- 协议类长文 ---------- */
.article {
  background: #fff; border-radius: var(--radius-card); border: 1px solid #EEF0F3;
  box-shadow: 0 3px 14px rgba(20,30,50,.07); padding: 20px 16px; line-height: 1.85;
}
.article .updated { font-size: 16px; color: var(--muted); margin-bottom: 16px; }
.article h2 {
  font-size: 15px; font-weight: 600; margin: 22px 0 8px;
  display: flex; align-items: center; gap: 7px;
}
.article h2::before {
  content: ''; width: 3px; height: 13px; border-radius: 2px; flex: none;
  background: linear-gradient(180deg, var(--boc-gold-lt), var(--boc-gold));
}
.article h2:first-of-type { margin-top: 4px; }
.article h3 { font-size: 14px; font-weight: 600; margin: 14px 0 6px; }
.article p { font-size: 15px; color: var(--ink-2); margin-bottom: 8px; }
.article ul { margin: 6px 0 10px 18px; }
.article li { font-size: 15px; color: var(--ink-2); margin-bottom: 5px; }
.article .note {
  background: linear-gradient(180deg, #FDF4F5, #FCF7F7); border: 1px solid #F5E3E5;
  border-left: 3px solid var(--boc-red); border-radius: var(--radius-ctl);
  padding: 12px; margin: 12px 0; font-size: 14.5px; color: #7A4046; line-height: 1.75;
}
.article strong { color: var(--ink); }

/* ---------- 客服 / 页脚 ---------- */
.service {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  font-size: 12.5px; color: var(--boc-red); padding: 14px 0 6px;
}
.service svg { width: 14px; height: 14px; stroke: var(--boc-red); fill: none; stroke-width: 1.7; }
/* 底部兜底小字，同时承担安全区留白 */
.foot { text-align: center; font-size: 15px; color: #A8AEB6; line-height: 1.9; padding: 8px 22px 18px; }

/* 调试模式角标。只有 boc.mock.enabled=true 且不在中行 App 内才会被 JS 插进来，
   生产看不到。故意用刺眼的黄黑条，避免把模拟身份的数据当成真实数据 */
.mock-bar {
  background: #FFC53D; color: #3A2E00; font-size: 12px; font-weight: 600;
  text-align: center; padding: 6px 10px; letter-spacing: .5px;
}

/* ---------- 首次进入手机号验证 ---------- */
/* 改成登录页的语汇：顶部只留一条导航栏，正文用大标题 + 裸表单（不套卡片）。
   原来是"红头部 + 说明色块 + 卡片里的表单 + 常驻的说明卡"，四层容器套下来
   表单被挤到屏幕中段，读起来像一篇带输入框的文章，而不是一个要你填的登录页。 */
.hero-bar { padding-bottom: 0; }

.bind-wrap { margin-top: 22px; }
.bind-title { font-size: 22px; font-weight: 700; line-height: 1.4; color: var(--ink); }
.bind-desc {
  font-size: 14px; color: var(--muted); line-height: 1.75; margin: 10px 0 22px;
}
.bind-desc b { color: var(--ink-2); font-weight: 600; }
/* 表单直接落在页面底色上，输入框自己是白的 —— 少一层卡片，视觉上离用户更近 */
.bind-form { margin-bottom: 18px; }
.bind-safe {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  font-size: 14px; color: var(--muted); margin: 14px 0 20px;
}
.bind-safe svg { width: 13px; height: 13px; stroke: #B4BAC2; fill: none; stroke-width: 1.7; flex: none; }
.form-label { display: block; font-size: 15px; color: var(--ink-2); font-weight: 500; margin: 0 0 7px; }
.form-input {
  display: block; width: 100%; height: 46px; border: 1px solid #DDE1E6;
  border-radius: var(--radius-ctl); padding: 0 13px; outline: none; background: #fff;
  color: var(--ink); font-size: 16px; margin-bottom: 15px;
}
.form-input:focus { border-color: var(--boc-red); box-shadow: 0 0 0 3px rgba(174,28,39,.09); }
.form-input::placeholder { color: #AEB4BB; font-size: 14px; }
.sms-row { display: flex; gap: 10px; }
.sms-row .form-input { flex: 1; min-width: 0; }
.sms-btn {
  flex: none; width: 112px; height: 46px; border: 1px solid var(--boc-red);
  border-radius: var(--radius-ctl); background: #fff; color: var(--boc-red); font-size: 13px;
  margin-bottom: 15px;
}
.sms-btn:active { background: #FDF3F4; }
.sms-btn:disabled { border-color: #D5D9DE; color: #A8AEB6; background: #fff; }
.consent-row {
  display: flex; align-items: flex-start; gap: 8px; margin: 3px 0 0;
  color: var(--muted); font-size: 16px; line-height: 1.6;
}
.consent-row input { width: 17px; height: 17px; flex: none; margin-top: 1px; accent-color: var(--boc-red); }
.consent-row a { color: var(--boc-red); text-decoration: none; }
.form-error { min-height: 22px; margin-top: 8px; color: #D93025; font-size: 12px; }
.bind-submit { margin-top: 4px; }
.bind-restart { display: none; margin-top: 10px; }
.bind-restart.on { display: block; }
