/* ==========================================================================
   汇损雷达 FX RADAR — 页面样式
   全部取自设计系统 token（assets/ds/styles.css），本文件不新增硬编码色值与字号，
   改品牌只需改 token。设计稿见 docs/design/。
   ========================================================================== */

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }

body {
  font-family: var(--font-sans);
  color: var(--text-body);
  background: var(--surface-page);
  -webkit-font-smoothing: antialiased;
}

/* 只给读屏与复制的文本：不能用 display:none，那样读屏也读不到 */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

a { color: var(--link); text-decoration: none; }
a:hover { color: var(--link-hover); }
::selection { background: var(--brand-soft); }

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

.page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* 设计稿的右上角品牌光晕 */
  background:
    radial-gradient(1100px 520px at 88% -20%, #F2FAF5 0%, rgba(242, 250, 245, 0) 55%),
    var(--surface-page);
}

/*
 * 页面外框宽度只有这一个来源：顶栏、内容区、页脚共用 --shell-max，
 * 改宽度只改这一处，三者不会左右对不齐。
 *
 * 应用内页面（body.app）放宽到 1600px：它们是图表 + 多列表格，
 * 1180 会把走势图和平台表各压到 500 多像素，币种网格也只排得下 3 列。
 * 左右各留 32px（.container 的 padding）作为最小边距，视口不足 1600 时
 * 核心区就按视口铺满——目的是把宽度让给内容，而不是留大片空白。
 * 首页（介绍页）是 body.landing，1280px——它的主视觉、图文分栏、步骤条与大页脚
 * 都取这同一个值，顶栏才和下面的内容左右对齐（原来顶栏写死 1180、内容 1280，差 50px）。
 */
:root { --shell-max: 1180px; }
body.app { --shell-max: 1600px; }
body.landing { --shell-max: 1280px; }

.container {
  width: 100%;
  max-width: var(--shell-max);
  margin: 0 auto;
  padding: 0 var(--space-8);
}

.main { flex: 1; padding: var(--space-10) 0 var(--space-16); }

/* ---------------------------------- 顶栏 --------------------------------- */

.topbar {
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: saturate(180%) blur(8px);
  position: sticky;
  top: 0;
  z-index: 20;
}

.topbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  padding: var(--space-4) var(--space-8);
  max-width: var(--shell-max);
  margin: 0 auto;
}

.brand { display: flex; align-items: center; gap: var(--space-3); }

.brand__mark {
  width: 30px; height: 30px;
  border-radius: var(--radius-pill);
  background: var(--grad-brand);
  display: grid; place-items: center;
  box-shadow: var(--shadow-sm);
}
.brand__mark::after {
  content: "";
  width: 11px; height: 11px;
  border-radius: var(--radius-pill);
  border: 2px solid #fff;
  border-right-color: transparent;
  transform: rotate(-35deg);
}

.brand__name { font-size: 17px; font-weight: var(--fw-black); color: var(--text-strong); line-height: 1.1; }
.brand__latin { font-size: 10px; font-weight: var(--fw-bold); color: var(--text-subtle); letter-spacing: var(--ls-wider); }

.nav { display: flex; align-items: center; gap: var(--space-6); }

.nav__link {
  font-size: 13.5px;
  font-weight: var(--fw-medium);
  color: var(--text-muted);
  padding: var(--space-1) 0;
  border-bottom: var(--bw-thick) solid transparent;
  transition: color var(--dur-fast) var(--ease-standard);
}
.nav__link:hover { color: var(--brand-strong); }
.nav__link--active { color: var(--text-strong); font-weight: var(--fw-bold); border-bottom-color: var(--brand); }

/* 后端尚未支持的入口：明确置灰并标注，不做假交互 */
.nav__link--todo { color: var(--ink-400); cursor: not-allowed; }
.nav__link--todo:hover { color: var(--ink-400); }
.nav__todo-tag {
  margin-left: var(--space-1);
  font-size: 10px;
  font-weight: var(--fw-bold);
  color: var(--ink-400);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-pill);
  padding: 1px 6px;
}

.tier-pill {
  font-size: 12px;
  font-weight: var(--fw-bold);
  color: var(--text-muted);
  background: var(--surface-sunken);
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-3);
}

/* ---------------------------------- 标题 --------------------------------- */

.eyebrow {
  display: flex; align-items: center; gap: var(--space-3);
  font-size: 11.5px; font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider); color: var(--brand-strong);
  text-transform: uppercase;
  margin-bottom: var(--space-3);
}
.eyebrow::before {
  content: ""; width: 26px; height: 3px;
  background: var(--brand); border-radius: var(--radius-xs);
}

.page-title { font-size: var(--fs-h4); font-weight: var(--fw-black); color: var(--text-strong); margin: 0 0 var(--space-2); letter-spacing: var(--ls-tight); }
.page-desc { font-size: 13.5px; color: var(--text-muted); margin: 0 0 var(--space-8); line-height: var(--lh-snug); }

.section-title { font-size: var(--fs-h5); font-weight: var(--fw-bold); color: var(--text-strong); margin: var(--space-10) 0 var(--space-4); }

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

.card {
  background: var(--surface-card);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-lg);
  /* 压灰的底色上 xs 阴影几乎看不出来；sm 有两层、边缘更柔 */
  box-shadow: var(--shadow-sm);
}
.card__body { padding: var(--space-5) var(--space-6); }

.statusbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-6); flex-wrap: wrap;
  padding: var(--space-4) var(--space-6);
  margin-bottom: var(--space-5);
}

.meta { display: flex; align-items: center; gap: var(--space-6); flex-wrap: wrap; }
.meta__item { display: flex; flex-direction: column; gap: 2px; }
.meta__label { font-size: var(--ui-xs); color: var(--text-subtle); letter-spacing: var(--ls-wide); }
.meta__value { font-size: var(--ui-lg); font-weight: var(--fw-bold); color: var(--text-strong); font-variant-numeric: tabular-nums; }

/* 昵称行的就地编辑：值右侧的铅笔小标，点击后值原地换成输入框 */
.nick-row { display: inline-flex; align-items: center; gap: var(--space-2); }
/* 作者样式的 display 会压过 hidden 属性的 UA 规则，必须显式补一条 */
.nick-row[hidden] { display: none; }
.nick-edit {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0;
  border: none; border-radius: var(--radius-xs);
  background: none; color: var(--text-subtle); cursor: pointer;
}
.nick-edit:hover { color: var(--brand-strong); background: var(--brand-soft); }
.nick-input { max-width: 220px; padding: 4px 10px; font-size: var(--ui-lg); font-weight: var(--fw-bold); }
.nick-hint { display: block; margin-top: 3px; font-size: 11px; color: var(--text-subtle); }

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

.btn {
  font-family: inherit; font-size: var(--ui-md); font-weight: var(--fw-bold);
  padding: 9px var(--space-5);
  border-radius: var(--radius-md);
  border: var(--bw-hairline) solid transparent;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.btn:focus-visible { outline: none; box-shadow: var(--ring-brand); }
.btn--primary { background: var(--brand); color: var(--brand-on); box-shadow: var(--shadow-sm); }
.btn--primary:hover:not(:disabled) { background: var(--brand-strong); }
.btn--ghost { background: var(--surface-card); color: var(--text-muted); border-color: var(--border-strong); }
.btn--ghost:hover:not(:disabled) { color: var(--brand-strong); border-color: var(--brand); }
/*
 * 不可撤销的操作（注销账号）。用实心红而不是"红字白底"：
 * 这类按钮要在扫视页面时就显出不一样，描边款容易被当成普通次要按钮点下去。
 */
.btn--danger { background: var(--danger); color: #fff; box-shadow: var(--shadow-sm); }
.btn--danger:hover:not(:disabled) { background: #C43A30; }
.btn:disabled { opacity: 0.55; cursor: not-allowed; box-shadow: none; }

/* ---------------------------------- 表格 --------------------------------- */

.table-wrap { overflow-x: auto; border-radius: var(--radius-lg); border: var(--bw-hairline) solid var(--border-hairline); }

table.rates { width: 100%; border-collapse: collapse; background: var(--surface-card); }

table.rates th {
  font-size: var(--ui-xs); font-weight: var(--fw-bold); color: var(--text-subtle);
  letter-spacing: var(--ls-wide);
  text-align: right; padding: var(--space-3) var(--space-4);
  background: var(--surface-sunken);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
  white-space: nowrap;
}
table.rates th:first-child, table.rates td:first-child { text-align: left; }

table.rates td {
  font-size: var(--ui-md); color: var(--text-body);
  text-align: right; padding: 14px var(--space-4);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
table.rates tbody tr:last-child td { border-bottom: none; }
table.rates tbody tr:hover { background: var(--brand-soft); }

.pair { font-weight: var(--fw-bold); color: var(--text-strong); }
.pair__cn { margin-left: var(--space-2); font-size: var(--ui-sm); font-weight: var(--fw-regular); color: var(--text-subtle); }
.rate--key { font-weight: var(--fw-bold); color: var(--brand-strong); }
.cell--empty { color: var(--ink-400); }

/* --------------------------------- 徽标 ---------------------------------- */

.badge {
  display: inline-block;
  font-size: 11px; font-weight: var(--fw-bold);
  border-radius: var(--radius-pill);
  padding: 2px var(--space-2);
}
.badge--on { background: var(--brand-soft); color: var(--brand-strong); }
.badge--off { background: var(--surface-sunken); color: var(--text-subtle); }

.chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.chip {
  font-size: 12px; font-weight: var(--fw-medium);
  color: var(--text-body);
  background: var(--surface-card);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-3);
}
.chip__cn { color: var(--text-subtle); margin-left: var(--space-1); }

/* ------------------------------ 状态与提示 -------------------------------- */

.note { font-size: var(--ui-sm); color: var(--text-subtle); margin-top: var(--space-3); line-height: var(--lh-snug); }

.state {
  text-align: center; padding: var(--space-16) var(--space-6);
  color: var(--text-muted);
}
.state__title { font-size: 15px; font-weight: var(--fw-bold); color: var(--text-strong); margin-bottom: var(--space-2); }
.state__desc { font-size: 13px; margin-bottom: var(--space-5); }

.alert {
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  font-size: 13px;
  margin-bottom: var(--space-5);
}
.alert--error { background: #FDECEA; color: #A3271D; border: var(--bw-hairline) solid #F3C6C1; }
.alert--ok { background: var(--brand-soft); color: var(--brand-strong); border: var(--bw-hairline) solid var(--green-200); }
/* 样本偏少一类的提醒：不是错误（结果照出），但读数时要知道样本量 */
.alert--warn { background: #FFF7E6; color: #8A5A00; border: var(--bw-hairline) solid #F5D9A0; }

.skeleton {
  height: 14px; border-radius: var(--radius-xs);
  background: linear-gradient(90deg, var(--ink-150) 25%, var(--ink-100) 37%, var(--ink-150) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.2s ease-in-out infinite;
}
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }

/* ======================== 首页（未登录介绍页）专用 ========================= */

/* 未登录首页没有应用内导航，只有登录 / 免费扫描两个入口 */
.topbar--landing .topbar__inner { padding: var(--space-5) var(--space-8); }
.landing-actions { display: flex; align-items: center; gap: var(--space-6); }

/*
 * 落地页顶栏右上角唯一的入口。
 *
 * 做成<b>描边胶囊</b>而不是实心绿：主视觉里的「免费扫描我的汇损」才是首要动作，
 * 顶栏再来一颗同样重的实心按钮，两个 CTA 互相抢，反而不知道先点哪个。
 * 但右上角只剩这一个元素，太素又会让顶栏右侧看着空——描边 + 人像图标
 * 既有按钮的实体感，又明确让位给主 CTA。
 */
.btn--enter {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-5);
  border-radius: var(--radius-pill);
  background: var(--surface-card);
  color: var(--brand-strong);
  border-color: var(--brand);
}
.btn--enter:hover { background: var(--brand-soft); color: var(--brand-strong); }
.btn--enter svg { width: 14px; height: 14px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.7; }

.section { border-top: var(--bw-hairline) solid var(--border-hairline); }
.section--white { background: var(--surface-card); }
.section--tint { background: #F5FAF7; }

.split {
  max-width: var(--shell-max); margin: 0 auto;
  padding: var(--space-12) var(--space-8) var(--space-16);
  display: grid; grid-template-columns: 0.9fr 1.1fr;
  gap: var(--space-12); align-items: center;
}
.split--wide-left { grid-template-columns: 1.1fr 0.9fr; }

/* ---------------------------------- 主视觉 -------------------------------- */

.hero {
  flex: 1;
  display: grid; grid-template-columns: 1.05fr 0.95fr;
  gap: var(--space-16); align-items: center;
  max-width: var(--shell-max); width: 100%; margin: 0 auto;
  padding: var(--space-6) var(--space-8) var(--space-10);
}
.hero__title {
  margin: var(--space-5) 0 0;
  font-size: 56px; line-height: 1.14; font-weight: var(--fw-black);
  letter-spacing: var(--ls-tight); color: var(--text-strong); text-wrap: balance;
}
.hero__lead {
  margin: var(--space-6) 0 0; max-width: 520px;
  font-size: var(--fs-lead); line-height: var(--lh-body); color: var(--text-muted);
}
.hero__cta { display: flex; align-items: center; gap: var(--space-4); margin-top: var(--space-8); flex-wrap: wrap; }
.hero__platforms { margin-top: var(--space-10); display: flex; flex-direction: column; gap: var(--space-3); }

.section-eyebrow { font-size: 12px; font-weight: var(--fw-bold); letter-spacing: var(--ls-wide); color: var(--text-subtle); text-transform: uppercase; }

.section-h2 {
  margin: var(--space-4) 0 0;
  font-size: var(--fs-h3); line-height: var(--lh-heading);
  font-weight: var(--fw-black); letter-spacing: var(--ls-tight); color: var(--text-strong);
}
.section-lead { margin: var(--space-4) 0 0; max-width: 440px; font-size: var(--fs-body); line-height: var(--lh-body); color: var(--text-muted); }

.ticks { margin-top: var(--space-6); display: flex; flex-direction: column; gap: var(--space-3); }
.tick { display: flex; align-items: center; gap: var(--space-3); font-size: 14px; color: var(--text-body); }
.tick::before {
  content: "✓"; flex: none;
  width: 20px; height: 20px; border-radius: var(--radius-pill);
  background: var(--brand-soft); color: var(--brand-strong);
  display: inline-flex; align-items: center; justify-content: center; font-size: 12px;
}

.btn--lg { font-size: 17px; padding: var(--space-4) var(--space-8); box-shadow: var(--shadow-md); }
.btn--md { font-size: 16px; padding: var(--space-3) var(--space-6); box-shadow: var(--shadow-md); }

/* 后端尚未支持的纯文本入口：置灰不可点 */
.link--todo { color: var(--text-subtle); cursor: not-allowed; font-size: 14.5px; }

/*
 * 介绍页主 CTA 指向的功能尚未开放。这里保留设计稿的视觉重量，
 * 但点击后如实告知「开发中」并给出已开放的入口——置灰按钮会让整页看起来是坏的，
 * 弹一句实话则既不骗人也不破版。
 */
.toast {
  position: fixed; left: 50%; bottom: var(--space-8); transform: translateX(-50%);
  max-width: min(560px, calc(100vw - var(--space-8)));
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-md);
  background: var(--surface-dark); color: var(--text-on-dark);
  box-shadow: var(--shadow-lg);
  font-size: 13.5px; line-height: var(--lh-snug);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur-base) var(--ease-standard), visibility var(--dur-base);
  z-index: 60;
}
.toast.is-open { opacity: 1; visibility: visible; }
.toast a { color: var(--green-300); font-weight: var(--fw-bold); white-space: nowrap; }
.toast a:hover { color: var(--green-200); }

.hint { font-size: 13.5px; color: var(--text-subtle); }

/* ------------------------------ 汇损报告示例卡 ----------------------------- */

.report-card { overflow: hidden; box-shadow: var(--shadow-md); }
.report-card__accent { height: 4px; background: var(--brand); }
.report-card__body { padding: var(--space-8) var(--space-8) var(--space-6); }
.report-card__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.report-card__amount { display: flex; align-items: baseline; gap: var(--space-1); margin-top: var(--space-1); }
.report-card__symbol { font-size: 22px; font-weight: var(--fw-bold); color: var(--text-strong); }
.report-card__value { font-size: 62px; font-weight: var(--fw-black); line-height: 1; letter-spacing: -0.03em; color: var(--text-strong); }
.report-card__annual { margin-top: var(--space-2); font-size: 13.5px; font-weight: var(--fw-bold); color: var(--brand-strong); }
.report-card__foot {
  margin-top: var(--space-6); padding-top: var(--space-4);
  border-top: var(--bw-hairline) solid var(--border-hairline);
  font-size: 12.5px; color: var(--text-subtle);
}

.bars { margin-top: var(--space-6); display: flex; flex-direction: column; gap: var(--space-4); }
.bar__label { display: flex; justify-content: space-between; font-size: 12.5px; color: var(--text-muted); margin-bottom: var(--space-1); }
.bar__track { height: 8px; border-radius: var(--radius-pill); background: var(--ink-100); overflow: hidden; }
.bar__fill { height: 100%; background: var(--brand); }
.bar__fill--alt { background: var(--sky-500); }

/* 示例数据标记：与真实牌价区分开，避免被当成实时数字 */
.sample-tag {
  display: inline-block;
  font-size: 10.5px; font-weight: var(--fw-bold); letter-spacing: var(--ls-wide);
  color: var(--text-subtle); background: var(--surface-sunken);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-pill); padding: 2px var(--space-2);
}

/* ------------------------------- 实时牌价卡 ------------------------------- */

.quote-card { overflow: hidden; box-shadow: var(--shadow-lg); }
.quote-card__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
}
.quote-card__tag { padding: 5px var(--space-4); border-radius: var(--radius-pill); background: var(--brand); color: var(--brand-on); font-size: 13px; font-weight: var(--fw-bold); }
.quote-card__origin { font-size: 12.5px; color: var(--text-subtle); }
.quote-card__stamp { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--text-muted); }
.quote-card__dot { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--green-400); }

.quote-card__hero {
  padding: var(--space-6) var(--space-6) var(--space-5);
  background: linear-gradient(180deg, #F5FAF7 0%, var(--surface-card) 100%);
  border-bottom: var(--bw-hairline) solid var(--ink-100);
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--space-5); flex-wrap: wrap;
}
.quote-card__pair { font-size: 12.5px; font-weight: var(--fw-bold); color: var(--text-muted); letter-spacing: var(--ls-wide); }
.quote-card__price { display: flex; align-items: baseline; gap: var(--space-3); margin-top: var(--space-1); }
.quote-card__price b { font-size: 46px; font-weight: var(--fw-black); letter-spacing: -0.03em; line-height: 1; color: var(--text-strong); }
.quote-card__range { margin-top: var(--space-2); font-size: 12px; color: var(--text-subtle); }
.quote-card__spark { width: 186px; height: 64px; flex: none; }

.quote-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px var(--space-6);
  border-bottom: var(--bw-hairline) solid var(--ink-100);
}
.quote-row__pair { font-weight: var(--fw-bold); color: var(--text-strong); font-size: 14px; }
.quote-row__cn { font-size: 11.5px; font-weight: var(--fw-medium); color: var(--text-subtle); margin-left: var(--space-2); }
.quote-row__value { font-weight: var(--fw-bold); font-size: 17px; color: var(--text-strong); font-variant-numeric: tabular-nums; }

.quote-card__note {
  padding: 13px var(--space-6); font-size: 11.5px; color: var(--text-subtle);
  background: var(--surface-sunken); border-top: var(--bw-hairline) solid var(--ink-100);
}

.delta { font-size: 12px; font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }
/*
 * 涨跌用国内行情惯例：红涨、绿跌（与 A 股行情软件、银行 App 一致）。
 * 面向境内用户的产品用国际惯例（绿涨红跌）会被直接读反。
 * 红色与错误提示共用 --danger 色值，但语义不同——涨不是错误，
 * 这里的红只表示方向。
 */
.delta--up { color: var(--danger); }
.delta--down { color: var(--brand-strong); }
.delta--flat { color: var(--text-subtle); }

/* -------------------------------- 时机示意卡 ------------------------------ */

.window-card { overflow: hidden; box-shadow: var(--shadow-md); }
.window-card__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
}
.window-card__title { font-size: 26px; font-weight: var(--fw-black); color: var(--text-strong); letter-spacing: var(--ls-tight); margin-top: var(--space-1); }
.window-card__chart { margin-top: var(--space-4); display: flex; align-items: flex-end; gap: 4px; height: 88px; }
.window-card__chart i { flex: 1; background: var(--brand); border-radius: 2px 2px 0 0; }
.window-card__chart i.is-past { background: var(--ink-200); }
.window-card__foot {
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: var(--bw-hairline) solid var(--border-hairline);
  display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap;
  font-size: 12.5px; color: var(--text-muted);
}
.window-card__gain { font-size: 20px; font-weight: var(--fw-black); color: var(--brand-strong); }

/* --------------------------------- 步骤条 --------------------------------- */

.steps {
  max-width: var(--shell-max); margin: 0 auto;
  padding: var(--space-8) var(--space-8);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-10);
}
.step { display: flex; gap: var(--space-4); }
.step__no { font-size: 34px; font-weight: var(--fw-black); color: var(--brand); line-height: 1; }
.step__title { font-size: 16px; font-weight: var(--fw-bold); color: var(--text-strong); }
.step__desc { margin-top: 5px; font-size: 13.5px; line-height: var(--lh-snug); color: var(--text-muted); }

/* ============================== 登录 / 注册页 ============================= */

.auth-page {
  min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-10) var(--space-4);
  background:
    radial-gradient(800px 440px at 50% -10%, #F2FAF5 0%, rgba(242, 250, 245, 0) 55%),
    var(--surface-page);
}
.auth-box { width: 100%; max-width: 420px; }
.auth-brand { display: flex; align-items: center; justify-content: center; gap: var(--space-3); margin-bottom: var(--space-8); }
.auth-card { padding: var(--space-8); box-shadow: var(--shadow-md); }

.auth-tabs {
  display: flex; gap: 6px; padding: 4px;
  background: var(--surface-sunken); border-radius: var(--radius-md);
  margin-bottom: var(--space-6);
}
.auth-tab {
  flex: 1; padding: 9px; border: none; border-radius: var(--radius-sm);
  background: transparent; color: var(--text-muted);
  font-family: var(--font-sans); font-size: 14px; font-weight: var(--fw-medium);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.auth-tab[aria-selected="true"] {
  background: var(--surface-card); color: var(--text-strong);
  font-weight: var(--fw-bold); box-shadow: var(--shadow-xs);
}

.field { margin-bottom: var(--space-5); }
.field__label { display: block; font-size: 13px; font-weight: var(--fw-bold); color: var(--text-body); margin-bottom: 7px; }
/* 必填星标：只在注册模式（form.is-signup）显示，语义由输入框的 required 承担 */
.field__req { display: none; margin-left: 3px; color: var(--danger); font-style: normal; }
.is-signup .field__req { display: inline; }

.field__error { display: none; margin-top: 6px; font-size: 12px; color: var(--danger); }
.field.is-invalid .field__error { display: block; }
.field.is-invalid .input { border-color: var(--danger); }

.input {
  width: 100%; padding: 13px var(--space-4);
  border: var(--bw-hairline) solid var(--border-strong);
  border-radius: var(--radius-md);
  font-family: inherit; font-size: 15px; color: var(--text-strong);
  outline: none;
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.input:focus { border-color: var(--brand); box-shadow: var(--ring-brand); }

.btn--block { width: 100%; justify-content: center; font-size: 16px; padding: var(--space-4); }


.auth-terms { margin-top: var(--space-5); text-align: center; font-size: 12px; line-height: var(--lh-snug); color: var(--text-subtle); }
/* 登录表单下的辅助入口（忘记密码 / 返回登录） */
.auth-links { margin: var(--space-4) 0 0; text-align: center; font-size: 13px; }
.auth-links a { color: var(--text-muted); text-decoration: underline; text-underline-offset: 3px; }
.auth-links a:hover { color: var(--brand-strong); }
.auth-links a[hidden] { display: none; }

/* --------------------------------- 法律文本 -------------------------------- */

/*
 * 用户协议 / 隐私政策的排版。窄栏（760px）而不是跟落地页同宽：
 * 长段中文一行超过 40 字左右，眼睛回到行首时容易串行，法律条款尤其读不下去。
 */
.legal {
  max-width: 760px;
  margin: 0 auto;
  padding: var(--space-12) var(--space-8) var(--space-16);
}
.legal__title { font-size: 30px; font-weight: var(--fw-black); color: var(--text-strong); margin: 0; }
.legal__meta {
  margin: var(--space-3) 0 var(--space-8);
  font-size: 12.5px; color: var(--text-subtle);
}

/* 开头的适用说明：加个底色，和正文条款区分开 */
.legal__lead {
  background: var(--surface-sunken);
  border-radius: var(--radius-lg);
  padding: var(--space-5) var(--space-6);
  font-size: 13.5px; line-height: var(--lh-relaxed); color: var(--text-body);
}
.legal__lead p { margin: 0 0 var(--space-3); }
.legal__lead p:last-child { margin-bottom: 0; }

/* 重点条款：左侧品牌色竖线。法规要求"以显著方式提示"，加粗之外再给个位置标记 */
.legal__strong {
  border-left: 3px solid var(--brand);
  padding-left: var(--space-4);
}

.legal__toc {
  margin: var(--space-8) 0;
  padding: var(--space-5) var(--space-6);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-lg);
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5);
  font-size: 13px;
}
.legal__toc-title {
  width: 100%;
  font-size: 12px; font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider); color: var(--text-subtle);
}

.legal__section { margin-top: var(--space-10); }
.legal__section h2 {
  font-size: 17px; font-weight: var(--fw-black); color: var(--text-strong);
  margin: 0 0 var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
  /* 从目录跳过来时标题不要贴着视口顶边 */
  scroll-margin-top: var(--space-6);
}
.legal__section p { margin: 0 0 var(--space-4); font-size: 13.5px; line-height: var(--lh-relaxed); color: var(--text-body); }
.legal__section ul { margin: 0 0 var(--space-4); padding-left: var(--space-6); }
.legal__section li {
  margin-bottom: 6px;
  font-size: 13.5px; line-height: var(--lh-relaxed); color: var(--text-body);
}
.legal__section b { font-weight: var(--fw-bold); color: var(--text-strong); }
.legal__note { font-size: 12.5px; color: var(--text-subtle); }

@media (max-width: 900px) {
  .legal { padding-left: var(--space-4); padding-right: var(--space-4); }
}

/* ----------------------------- AI 结果复用提示 ----------------------------- */

/*
 * 做成一条淡黄提示条而不是灰色小字：它解释的是"为什么点了按钮结论没变"，
 * 属于用户主动追问才会看的信息，但必须一眼找得到，否则会被当成 bug。
 */
.ai-cache-note {
  margin-bottom: var(--space-5);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  border-left: 3px solid var(--warning);
  background: #FFF9EC;
  font-size: var(--ui-sm); line-height: var(--lh-snug); color: var(--text-muted);
}
.ai-cache-note b { color: var(--text-strong); }

/* -------------------------------- 币种旗帜 -------------------------------- */

/*
 * 圆角靠 clip-path 裁，不靠 border-radius：SVG 里的条纹是矩形，
 * 只加 border-radius 时四角的色块会露在圆角之外。
 * 边框画在 SVG 内部（见 app.js 的 currencyFlag），因为 clip-path 会把 box-shadow 一起裁掉。
 */
.flag {
  width: 18px; height: 12.6px; flex: none; display: block;
  border-radius: 2px;
  clip-path: inset(0 round 2px);
}
.flag--sm { width: 15px; height: 10.5px; }

/* 旗帜挂在币种前：文字与旗帜基线对齐，别让旗帜把行高撑开 */
.convert__ccy { display: inline-flex; align-items: center; gap: 6px; }
.pair-row__name { display: inline-flex; align-items: center; gap: var(--space-2); }
.pair-cell { display: inline-flex; align-items: center; gap: var(--space-2); }
.pair-cell .pair__cn { margin-left: 0; }

/* --------------------------- 数据来源与免责声明 --------------------------- */

/*
 * 展示他方公开数据的页面必须写清来源与免责。做成一张独立的卡片而不是一行小字：
 * 小字容易被当成脚注跳过，而这几条（不是实时行情、不构成投资建议、
 * 本站不做结售汇）恰恰是读者按这个价做决定之前必须看到的。
 */
.compliance { padding: var(--space-5) var(--space-6); margin-top: var(--space-6); }

/*
 * 项目符号自绘，不用 <ul> 默认的 disc：默认符号的大小、颜色与缩进各浏览器不一致，
 * 和站内其他列表对不齐，看着像另一套排版。标题则直接复用 .step-label，
 * 不再自己写一套同样的"绿短线 + 粗体"。
 */
.compliance__list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--space-2);
  font-size: var(--ui-sm); line-height: var(--lh-snug); color: var(--text-muted);
}
.compliance__list li { position: relative; padding-left: var(--space-4); }
.compliance__list li::before {
  content: "";
  position: absolute; left: 2px; top: 0.5em;
  width: 4px; height: 4px; border-radius: var(--radius-pill); background: var(--brand);
}
.compliance__list b { color: var(--text-body); font-weight: var(--fw-bold); }

/* ---------------------------------- 覆层 --------------------------------- */

/*
 * 登录覆层。面板内容与 login.html 同一份（app.js 的 renderAuthPanel），
 * 这里只负责"盖上去"这件事：遮罩、居中、进场动效、滚动锁。
 */
.modal {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  padding: var(--space-8) var(--space-4);
  overflow-y: auto;
  animation: modal-fade var(--dur-base) var(--ease-out);
}
.modal[hidden] { display: none; }

/*
 * 背板只用半透明压暗，不加 backdrop-filter 毛玻璃。
 *
 * 这里原来有 blur(2px)，是登录覆层"打开慢、打字卡"的直接原因：
 * 全屏 backdrop-filter 让合成器在每一帧（包括光标闪烁、每次击键）都要
 * 对整个视口重算模糊。实测（软件渲染下）打字帧时间中位 34ms / p95 132ms，
 * 去掉后稳定 17ms（满 60fps）。顶栏那条 8px 毛玻璃无罪——它只有几十像素高，
 * 且打字不会使其下方内容失效——予以保留。
 * 压暗从 0.48 提到 0.55，补偿失去模糊后的前后景分离度。
 */
.modal__backdrop {
  position: absolute; inset: 0;
  background: rgba(11, 15, 13, 0.55);
}

.modal__dialog {
  position: relative;
  width: 100%; max-width: 420px;
  animation: modal-rise var(--dur-base) var(--ease-out);
}

/* 关闭键放在卡片外的遮罩上：卡片顶部是选项卡，压进去会挤掉「注册」那一格 */
.modal__close {
  position: absolute; top: -36px; right: 0;
  width: 28px; height: 28px; padding: 0;
  display: grid; place-items: center;
  background: none; border: none; border-radius: var(--radius-sm);
  font-family: inherit; font-size: 15px; line-height: 1;
  color: var(--text-on-dark-mut); cursor: pointer;
  transition: color var(--dur-fast) var(--ease-standard);
}
.modal__close:hover { color: var(--text-on-dark); }
.modal__close:focus-visible { outline: none; box-shadow: var(--ring-brand); }

/* 覆层打开时锁住身后的滚动，否则滚轮会带着落地页在遮罩下面跑 */
body.is-modal-open { overflow: hidden; }

@keyframes modal-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-rise {
  from { opacity: 0; transform: translateY(10px) scale(0.985); }
  to { opacity: 1; transform: none; }
}

/* 覆层里的条款行落在深色遮罩上，用浅色字才读得清 */
.modal__dialog .auth-terms { color: var(--text-on-dark-mut); }

@media (prefers-reduced-motion: reduce) {
  .modal, .modal__dialog { animation: none; }
}

/* ---------------------------------- 页脚 --------------------------------- */

.footer {
  border-top: var(--bw-accent) solid var(--brand);
  background: var(--surface-sunken);
  padding: var(--space-6) 0;
}
.footer__bottom-links { display: flex; gap: var(--space-6); }

/*
 * 应用内紧凑页脚：三行。
 *
 * 首页那份分栏大页脚有介绍文案与联系方式卡片，铺在工具页底下要占掉将近半屏
 * （实测 440px）。用户来应用页是看行情的，页脚只需要在需要时能查到
 * 备案号和联系方式，不需要再推销一遍产品。
 * 首页 index.html 的静态大页脚不受影响，两份的关键事实仍由
 * SiteFooterConsistencyTest 钉住。
 */
.footer--app { padding: var(--space-5) 0 var(--space-4); }
/* 应用页内容区是灰底，页脚若也用 sunken 会和它糊成一片，改白底靠绿线分隔 */
body.app .footer--app { background: var(--surface-card); }
.footer-app { max-width: var(--shell-max); margin: 0 auto; padding: 0 var(--space-8); }

.footer-app__row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-5); flex-wrap: wrap;
}

.footer-app__brand { display: flex; align-items: center; gap: var(--space-3); }
/* 品牌缩一号并把中英文排成一行：两行品牌会把这一行撑成页脚里最高的东西 */
.footer-app__brand .brand__mark { width: 24px; height: 24px; }
.footer-app__brand .brand__mark::after { width: 9px; height: 9px; }
.footer-app__brand-name { font-size: 14.5px; font-weight: var(--fw-black); color: var(--text-strong); }
.footer-app__brand-name i {
  margin-left: var(--space-2); font-style: normal;
  font-size: 10px; font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider); color: var(--text-subtle);
}

.footer-app__links { display: flex; gap: var(--space-5); font-size: var(--ui-md); }

.footer-app__contact {
  display: flex; gap: var(--space-5);
  font-size: var(--ui-sm); font-weight: var(--fw-bold); color: var(--text-strong);
}
.footer-app__contact-item { display: flex; align-items: center; gap: 6px; }
/* 图标只做前缀，不再是 30px 的方块卡片——那是撑高原页脚的主因之一 */
.footer-app__contact-item i {
  font-style: normal; font-size: 12px; font-weight: var(--fw-medium); color: var(--brand-strong);
}

.footer-app__legal {
  margin: var(--space-3) 0 0;
  font-size: var(--ui-sm); line-height: var(--lh-snug); color: var(--text-subtle);
}

.footer-app__bottom {
  margin-top: var(--space-3); padding-top: var(--space-3);
  border-top: var(--bw-hairline) solid var(--border-hairline);
  display: flex; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap;
  font-size: 12px; color: var(--text-subtle);
}

/* 窄屏（本期为 PC 页面，仅做不破版处理） */
@media (max-width: 1080px) {
  .hero, .split, .split--wide-left { grid-template-columns: 1fr; }
  .steps { grid-template-columns: 1fr; gap: var(--space-8); }
  .hero__title { font-size: 42px; }
}
@media (max-width: 900px) {
  .topbar__inner, .container, .footer-app, .steps {
    padding-left: var(--space-4); padding-right: var(--space-4);
  }
  .hero, .split { padding-left: var(--space-4); padding-right: var(--space-4); }
  .nav { gap: var(--space-4); }
}

/* ==========================================================================
   应用内三栏外壳：左导航 + 中内容 + 右日历
   ========================================================================== */

/*
 * 导航从顶栏搬到左侧。
 *
 * 为什么值得改：顶栏横向排 3 个入口时，右边一大片空着，而内容区反而被
 * 1600px 的外框卡住；应用页面又是"选币种 → 看图 → 看测算"的纵向流程，
 * 导航固定在左侧后，视线不必在页面顶部和内容之间来回跳。
 *
 * 三栏都是 sticky：滚到走势图深处时导航与日历仍在原位，
 * 不必滚回顶部才能换页面或看日期。
 */
body.app {
  --side-w: 248px;
  --rail-w: 324px;
  --bar-h: 64px;

  /*
   * 界面字号梯度。
   *
   * 设计系统的 --fs-* 是<b>内容型</b>梯度（12/14/16/18/22…），跨度太大，
   * 界面控件需要更细的档位；原先各处直接写 11 / 11.5 / 12 / 12.5 / 13 / 13.5px，
   * 既改不动，整体也偏小——导航 13.5px 在大屏上要凑近了看。
   * 这里收成四档，整体上调约 1px，导航单独用 --ui-lg。
   */
  --ui-xs: 12px;
  --ui-sm: 13px;
  --ui-md: 14px;
  --ui-lg: 15px;
}

/* 底层压一层浅灰，白卡片浮在上面——比"白底 + 描边卡片"更容易分清层次 */
body.app .page--shell { background: var(--surface-app); }

/*
 * 顶栏通栏跨三列，下面才是三栏。
 * 品牌与账号是"我是谁、我在哪个产品里"，属于全站身份，横跨整幅页面；
 * 侧栏只留导航，收窄成图标条时也不会把品牌和邮箱一起挤没。
 */
.page--shell {
  display: grid;
  grid-template-columns: var(--side-w) minmax(0, 1fr) var(--rail-w);
  /* 顶栏 / 三栏 / 页脚：首尾两行都跨满三列 */
  grid-template-rows: auto minmax(0, 1fr) auto;
  align-items: start;
  min-height: 100vh;
}

/*
 * 页脚也通栏。它是站点级信息（公司、备案号、联系方式），
 * 被夹在中列里就成了"内容的一部分"，左右两栏旁边空着两条白边，看着像没铺满。
 * 内部的 .footer-app 按 --shell-max 居中，所以铺满不等于把内容拉散。
 */
.page--shell > .footer {
  grid-column: 1 / -1;
  /*
   * 必须压在侧栏与右栏之上。sticky 元素本该被自己的网格区域夹住，
   * 但侧栏高 100vh、又是 sticky，浏览器实测并没有在行尾把它停住
   * （滚到底时侧栏底边到 1000px，而三栏那一行 605px 就结束了），
   * 于是白色侧栏盖住了页脚左侧的公司信息。页脚背景不透明，盖回去即可。
   */
  position: relative;
  z-index: 21;
}

.appbar {
  grid-column: 1 / -1;
  position: sticky;
  top: 0;
  /* 比侧栏与右栏高一层：它们贴着顶栏底边滚动，不能盖住它 */
  z-index: 30;
  height: var(--bar-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  padding: 0 var(--space-6);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
  /* 内容区压了灰，顶栏与侧栏保持纯白：白 → 灰 → 白卡，三层各自分明 */
  background: var(--surface-card);
}

/* 账号区在顶栏里横排：这里宽度充裕，不必像侧栏那样折行 */
.appbar__user { display: flex; align-items: center; gap: var(--space-4); }

/* ------------------------------ 站内消息铃铛 ------------------------------ */

.msg-bell { position: relative; display: inline-flex; }
.bell {
  position: relative;
  width: 34px; height: 34px;
  display: inline-flex; align-items: center; justify-content: center;
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: 999px; background: var(--surface-card);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-standard);
}
.bell:hover { border-color: var(--brand); }
.bell svg { width: 16px; height: 16px; fill: none; stroke: var(--text-muted); stroke-width: 1.4; }
.bell:hover svg { stroke: var(--brand-strong); }
/* 未读角标：红点带数字，压在铃铛右上角 */
.bell__badge {
  position: absolute; top: -5px; right: -6px;
  min-width: 16px; height: 16px; padding: 0 4px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 999px; background: var(--danger, #D64545); color: #fff;
  font-size: 10px; font-weight: var(--fw-bold); line-height: 1;
  box-shadow: 0 0 0 2px var(--surface-card);
}
.bell__badge[hidden] { display: none; }
/* 面板 fixed 定位：appbar 是 sticky 容器，absolute 会被它的高度夹住 */
.bell-panel {
  position: fixed; top: calc(var(--bar-h) + 8px); right: var(--space-6);
  width: 340px; max-height: 60vh; display: flex; flex-direction: column;
  background: var(--surface-card);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-md);
  box-shadow: 0 12px 32px rgba(15, 40, 30, .14);
  z-index: 40;
}
.bell-panel[hidden] { display: none; }
.bell-panel__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
  font-size: 14px; color: var(--text-strong);
}
.bell-panel__readall {
  border: none; background: none; padding: 0; cursor: pointer;
  font-size: 12.5px; color: var(--brand-strong); font-family: inherit;
}
.bell-panel__readall:hover { text-decoration: underline; }
.bell-panel__list { overflow-y: auto; }
.bell-panel__empty { padding: var(--space-8); text-align: center; font-size: 13px; color: var(--text-subtle); }
.bell-item {
  position: relative;
  padding: var(--space-4) var(--space-5) var(--space-4) var(--space-6);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
}
.bell-item:last-child { border-bottom: none; }
.bell-item__title { font-size: 13.5px; font-weight: var(--fw-bold); color: var(--text-strong); }
.bell-item__body { margin-top: 3px; font-size: 12.5px; line-height: var(--lh-snug); color: var(--text-muted); }
.bell-item__time { margin-top: 4px; font-size: 11.5px; color: var(--text-subtle); }
/* 未读：左侧绿点 + 微微压底色；读过的自然褪下去 */
.bell-item--unread { background: var(--brand-soft); }
.bell-item--unread::before {
  content: ''; position: absolute; left: 10px; top: 22px;
  width: 6px; height: 6px; border-radius: 999px; background: var(--brand);
}

/* ------------------------------ 咨询悬浮入口 ------------------------------ */

.support { position: fixed; right: var(--space-6); bottom: var(--space-6); z-index: 45; }
.support-fab {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 10px 18px;
  border: none; border-radius: 999px; cursor: pointer;
  background: var(--brand); color: #fff;
  font-family: inherit; font-size: 14px; font-weight: var(--fw-bold);
  box-shadow: 0 8px 24px rgba(0, 120, 60, .3);
  transition: transform var(--dur-fast) var(--ease-standard),
    box-shadow var(--dur-fast) var(--ease-standard);
}
.support-fab:hover { transform: translateY(-2px); box-shadow: 0 12px 28px rgba(0, 120, 60, .35); }
.support-fab svg { width: 16px; height: 16px; fill: none; stroke: #fff; stroke-width: 1.4; }
.support-panel {
  position: absolute; right: 0; bottom: calc(100% + var(--space-3));
  width: 340px;
  padding: var(--space-5);
  background: var(--surface-card);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-md);
  box-shadow: 0 16px 40px rgba(15, 40, 30, .16);
}
.support-panel[hidden] { display: none; }
.support-panel__head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--space-4); font-size: 14px; color: var(--text-strong);
}
.support-panel__close {
  border: none; background: none; cursor: pointer; padding: 0 var(--space-1);
  font-size: 20px; line-height: 1; color: var(--text-subtle); font-family: inherit;
}
.support-panel__close:hover { color: var(--text-strong); }
.support-tabs { display: flex; gap: var(--space-2); }
.support-tab {
  flex: 1; padding: 7px 0;
  border: var(--bw-hairline) solid var(--border-hairline); border-radius: 999px;
  background: var(--surface-card); cursor: pointer;
  font-family: inherit; font-size: 13px; color: var(--text-muted);
  transition: border-color var(--dur-fast) var(--ease-standard),
    background var(--dur-fast) var(--ease-standard);
}
.support-tab[aria-pressed="true"] {
  border-color: var(--brand); background: var(--brand-soft);
  color: var(--brand-strong); font-weight: var(--fw-bold);
}
.support-hint {
  margin: var(--space-3) 0 var(--space-3);
  font-size: 12.5px; line-height: var(--lh-snug); color: var(--text-subtle);
}
.support-text { resize: vertical; min-height: 88px; }
.support-contact { margin-top: var(--space-3); }
.support-panel .btn { margin-top: var(--space-4); }
.support-panel .alert { margin: var(--space-3) 0 0; }
@media (max-width: 720px) {
  .support { right: var(--space-4); bottom: var(--space-4); }
  .support-panel { width: min(340px, calc(100vw - 32px)); }
  .bell-panel { right: var(--space-3); width: min(340px, calc(100vw - 24px)); }
}

/* ------------------------------ 币种资讯（换汇时机右栏） ------------------------------ */

.news-card { margin-top: var(--space-5); padding: var(--space-5); }
.news-card__head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--space-3);
}
.news-empty { padding: var(--space-6) 0; text-align: center; font-size: 12.5px; color: var(--text-subtle); }
.news-item {
  display: block; width: 100%; text-align: left;
  padding: var(--space-3) 0;
  border: none; border-bottom: var(--bw-hairline) solid var(--border-hairline);
  background: none; cursor: pointer; font-family: inherit;
}
.news-item:last-child { border-bottom: none; }
.news-item__title {
  font-size: 13px; font-weight: var(--fw-bold); color: var(--text-strong);
  line-height: var(--lh-snug);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.news-item:hover .news-item__title { color: var(--brand-strong); }
.news-item__meta { margin-top: 3px; font-size: 11.5px; color: var(--text-subtle); }

/* 新闻详情弹窗：白卡（登录覆层的暗色关闭键规则不适用，自己带一枚）。
   标题与正文完整展示不截断；正文过长时在弹窗内滚动。
   不做站外跳转：原文地址以文本呈现，需要时自行复制。 */
.news-modal {
  max-width: 640px;
  background: var(--surface-card);
  border-radius: var(--radius-lg);
  padding: var(--space-8); /* 间距刻度 6 之后直接是 8，没有 --space-7 */
}
.news-modal .modal__close {
  position: absolute; top: var(--space-3); right: var(--space-4);
  border: none; background: none; cursor: pointer; padding: var(--space-1);
  font-size: 22px; line-height: 1; color: var(--text-subtle); font-family: inherit;
}
.news-modal .modal__close:hover { color: var(--text-strong); }
.news-modal__meta {
  font-size: 12.5px; color: var(--text-subtle);
  padding-right: var(--space-8); /* 给右上角关闭键让位，长来源名不与其重叠 */
}
.news-modal__title {
  margin: var(--space-2) 0 var(--space-4);
  font-size: 19px; line-height: var(--lh-snug); color: var(--text-strong);
  overflow-wrap: break-word;
}
.news-modal__body {
  font-size: 14px; line-height: var(--lh-body); color: var(--text-muted);
  max-height: 56vh; overflow-y: auto;
  overflow-wrap: break-word;
}
.news-modal__body p { margin: 0 0 var(--space-3); }
.news-modal__source {
  display: flex; align-items: baseline; gap: var(--space-3);
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-sunken);
  border-radius: var(--radius-md);
}
.news-modal__source-label {
  flex: none; font-size: 12px; font-weight: var(--fw-bold); color: var(--text-subtle);
}
.news-modal__url {
  font-size: 12px; color: var(--text-muted);
  word-break: break-all; user-select: all; /* 一点即全选，方便整段复制 */
}
.news-modal__note {
  margin: var(--space-3) 0 0; font-size: 12px; color: var(--text-subtle);
}

/* ------------------------------ 反馈管理（运营） ------------------------------ */

.fb-filters { display: flex; gap: var(--space-2); max-width: 360px; }
.fb-item { margin-bottom: var(--space-4); }
.fb-item__meta { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); }
.fb-badge {
  display: inline-block; padding: 2px 10px; border-radius: 999px;
  font-size: 12px; font-weight: var(--fw-bold);
  background: var(--surface-sunken); color: var(--text-muted);
}
.fb-badge--FEEDBACK { background: var(--brand-soft); color: var(--brand-strong); }
.fb-badge--CONSULT { background: #E8F1FD; color: #1D5FBF; }
.fb-badge--COOPERATION { background: #FFF3E0; color: #9A5B00; }
.fb-badge--pending { background: #FFF7E6; color: #8A5A00; }
.fb-badge--done { background: var(--brand-soft); color: var(--brand-strong); }
.fb-item__content {
  margin: var(--space-3) 0 0; font-size: 14px; line-height: var(--lh-normal);
  color: var(--text-strong); white-space: pre-wrap; word-break: break-word;
}
.fb-item__reply {
  margin-top: var(--space-3); padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--brand); border-radius: var(--radius-xs);
  background: var(--surface-sunken);
  font-size: 13px; color: var(--text-muted); white-space: pre-wrap; word-break: break-word;
}
.fb-item__actions { display: flex; gap: var(--space-3); margin-top: var(--space-4); align-items: flex-start; }
.fb-item__actions textarea { flex: 1; resize: vertical; }
.fb-item__actions .btn { flex: none; white-space: nowrap; }
@media (max-width: 720px) { .fb-item__actions { flex-direction: column; } }

/*
 * 中列撑到至少一屏高：页脚移出去之后，它还负责把三栏这一行顶到视口高度，
 * 否则内容短的页面（如设置页）里，侧栏 100vh 的高度会溢出到页脚上面去。
 */
.appmain {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - var(--bar-h));
  min-width: 0;
}

/* ------------------------------ 左侧导航栏 ------------------------------- */

.appside {
  position: sticky;
  /* 贴在顶栏底边，不是视口顶边——否则滚动时会滑到顶栏底下 */
  top: var(--bar-h);
  height: calc(100vh - var(--bar-h));
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-3) var(--space-5);
  border-right: var(--bw-hairline) solid var(--border-hairline);
  background: var(--surface-card);
  overflow-y: auto;
}

.sidenav { display: flex; flex-direction: column; gap: 2px; }
.sidenav--main { flex: 1; }

/* 分组标签 12px + 0.08em 字距：原先 10.5px 配 0.18em，字小、字距又散，读成了一串孤立的字 */
.sidenav__group {
  font-size: var(--ui-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  color: var(--text-subtle);
  padding: var(--space-5) var(--space-3) var(--space-2);
}
.sidenav--main .sidenav__group:first-child { padding-top: var(--space-4); }

.sidenav__link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px var(--space-3);
  border-radius: var(--radius-lg);
  font-size: var(--ui-lg);
  font-weight: var(--fw-medium);
  color: var(--text-body);
  transition: background var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
.sidenav__link:hover { background: var(--surface-sunken); color: var(--brand-strong); }
/*
 * 选中态：淡绿药丸 + 同色描边。侧栏是白底，只填一层淡绿时边界很虚，
 * 扫一眼分不清选中的是哪一项；描边把边界交代清楚，又不至于看成一颗按钮。
 */
.sidenav__link--active {
  background: var(--brand-soft);
  color: var(--brand-strong);
  font-weight: var(--fw-bold);
  box-shadow: inset 0 0 0 1px var(--green-100);
}

/* 图标用 currentColor 描边，选中态跟着文字一起变绿，不必再写一套颜色 */
.sidenav__icon { width: 19px; height: 19px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.7; }

/* 后端尚未支持的入口：置灰并标注，不做假交互 */
.sidenav__link--todo { color: var(--ink-400); cursor: not-allowed; }
.sidenav__link--todo:hover { background: none; color: var(--ink-400); }
.sidenav__tag {
  margin-left: auto;
  font-size: 10px;
  font-weight: var(--fw-bold);
  color: var(--ink-400);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-pill);
  padding: 1px 6px;
}

/* ------------------------------ 右侧日历栏 ------------------------------- */

.apprail {
  position: sticky;
  top: var(--bar-h);
  max-height: calc(100vh - var(--bar-h));
  overflow-y: auto;
  padding: var(--space-6) var(--space-6) var(--space-6) 0;
}

@media (max-width: 1440px) {
  /* 日历是辅助信息，宽度不够时先让给内容，而不是把走势图挤扁 */
  .page--shell { grid-template-columns: var(--side-w) minmax(0, 1fr); }
  .apprail { display: none; }
}
@media (max-width: 1080px) {
  body.app { --side-w: 64px; }
  /* 顶栏里账号名最先让位：品牌和「退出」比它更需要一直在 */
  .appbar { padding: 0 var(--space-4); }
  .appbar__user .user-chip__name { max-width: 140px; }
  .appside { padding-left: var(--space-2); padding-right: var(--space-2); }
  .sidenav__label, .sidenav__group, .sidenav__tag { display: none; }
  .sidenav__link { justify-content: center; padding: var(--space-3) 0; }
}

/* ==========================================================================
   应用内页面（汇损分析 / 币种管理 / 换汇时机）
   仍然只用设计系统 token，不新增硬编码色值与字号。
   ========================================================================== */

.step-label {
  display: flex; align-items: center; gap: var(--space-3);
  font-size: var(--ui-md); font-weight: var(--fw-bold); color: var(--text-strong);
  margin-bottom: var(--space-4);
}
.step-label::before { content: ""; width: 18px; height: 2px; background: var(--brand); flex: none; }

.page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--space-6); flex-wrap: wrap; margin-bottom: var(--space-8);
}

.quota { display: flex; align-items: center; gap: var(--space-2); font-size: 13px; color: var(--text-muted); }
.quota__dot { width: 7px; height: 7px; border-radius: var(--radius-pill); background: var(--brand); flex: none; }
.quota__num { font-weight: var(--fw-black); color: var(--text-strong); }

.split-2 { display: grid; grid-template-columns: 0.95fr 1.05fr; gap: var(--space-8); align-items: start; }

/* ------------------------------- 汇损分析 -------------------------------- */

.picker { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
/*
 * 平台磁贴走紧凑密度：原版一格 130px 高，7 格吃掉大半屏，
 * 选中态只有一圈细边框，扫一眼分不清选没选。
 * 现在：小磁贴 + 选中加内描边压底色 + 右上角悬出的勾形角标（最强的"已选"信号）。
 */
.picker__item {
  position: relative;
  text-align: left; padding: 10px var(--space-4);
  background: var(--surface-card);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-md);
  font-family: inherit; cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-standard),
    background var(--dur-fast) var(--ease-standard),
    box-shadow var(--dur-fast) var(--ease-standard);
}
.picker__item:hover:not(:disabled) { border-color: var(--brand); }
/* 未收录模板的平台置灰：能看到会有、但现在点不了；文案在磁贴副标题（模板准备中） */
.picker__item:disabled {
  cursor: not-allowed;
  background: var(--surface-sunken);
  border-color: var(--border-hairline);
}
.picker__item:disabled .picker__name { color: var(--text-subtle); }
.picker__item:disabled .picker__sub { color: var(--text-subtle); opacity: .8; }
.picker__item[aria-pressed="true"] {
  border-color: var(--brand); background: var(--brand-soft);
  /* 内描边把选中边框加厚一倍，又不像改 border-width 那样引起布局抖动 */
  box-shadow: inset 0 0 0 1px var(--brand);
}
.picker__item[aria-pressed="true"]::after {
  content: '✓';
  position: absolute; top: -7px; right: -7px;
  width: 18px; height: 18px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand); color: #fff;
  font-size: 11px; font-weight: var(--fw-bold);
  box-shadow: 0 1px 3px rgba(15, 40, 30, .25);
}
.picker__name { display: block; font-size: 14px; font-weight: var(--fw-bold); color: var(--text-strong); }
.picker__sub {
  display: block; margin-top: 2px; font-size: 11.5px; color: var(--text-subtle);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* 步骤头：编号进绿色圆标，比"① 灰字"更像一条流程的两步 */
.step-row {
  display: flex; align-items: center; gap: var(--space-3);
  margin: 0 0 var(--space-4);
  font-size: 13.5px; font-weight: var(--fw-bold); color: var(--text-strong);
}
.step-row__num {
  flex: none; width: 20px; height: 20px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 999px; background: var(--brand); color: #fff;
  font-size: 11.5px; font-weight: var(--fw-bold);
}

.dropzone {
  margin-top: var(--space-4);
  border: var(--bw-thick) dashed var(--border-strong);
  border-radius: var(--radius-md);
  /* 高度按内容定：一格屏那么高的空白框不会让上传更好用，只会把按钮挤出视口 */
  padding: var(--space-8) var(--space-5);
  text-align: center;
  transition: border-color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.dropzone.is-active { border-color: var(--brand); background: var(--brand-soft); }
/* 图标坐进浅绿圆底：空态也有一个视觉锚点，选中后由 has-file 换成实心打勾圆 */
.dropzone__icon {
  width: 44px; height: 44px; margin: 0 auto;
  display: flex; align-items: center; justify-content: center;
  border-radius: 999px; background: var(--brand-soft);
  font-size: 20px; color: var(--brand); line-height: 1;
}
.dropzone__title { margin-top: var(--space-3); font-size: 14px; font-weight: var(--fw-bold); color: var(--text-strong); }
.dropzone__hint { margin-top: var(--space-1); font-size: 12.5px; color: var(--text-subtle); }

/*
 * 汇损分析页去掉右侧日历栏（page--norail）：报告是这一页的主角，
 * 要放得下 8 列的逐笔明细表；交易日历讲的是"哪天能结汇"，
 * 与"过去结汇亏了多少"的分析没有直接关系，摆在旁边只是占宽度。
 */
.page--shell.page--norail { grid-template-columns: var(--side-w) minmax(0, 1fr); }

/*
 * 汇损分析页的两列：左列是操作表单（选平台、传文件），定宽就够；
 * 右列吃掉全部剩余宽度，明细表在常见分辨率下不再需要横向滚动。
 * 窄屏下沿用 .split-2 的统一断点收成单列。
 */
.split-2--scan { grid-template-columns: minmax(340px, 420px) minmax(0, 1fr); }

/*
 * 左列操作卡吸顶：报告很长，滚到明细底部想换个文件重新分析时，
 * 控件跟着视口走，不必翻回页首。折叠说明收起后卡片高度低于一屏，吸顶才有意义。
 */
.scan-ops { position: sticky; top: calc(var(--bar-h) + var(--space-6)); }
@media (max-width: 960px) { .scan-ops { position: static; } }

/* 参考信息折叠：表头规则与导出教程是"需要才看"的内容，默认收起降噪 */
.scan-fold {
  margin-top: var(--space-5);
  border-top: var(--bw-hairline) solid var(--border-hairline);
  padding-top: var(--space-4);
}
.scan-fold summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; gap: var(--space-2);
  font-size: 13px; font-weight: var(--fw-bold); color: var(--text-muted);
}
.scan-fold summary::-webkit-details-marker { display: none; }
.scan-fold summary::before {
  content: '▸'; font-size: 11px;
  transition: transform var(--dur-fast) var(--ease-standard);
}
.scan-fold[open] summary::before { transform: rotate(90deg); }
.scan-fold summary:hover { color: var(--brand-strong); }
.scan-fold > :not(summary) { margin-top: var(--space-3); }
/*
 * fr 轨道的自动最小宽是 min-content：明细表整列 nowrap 后 min-content 很大，
 * 会把右列撑到布局外、压进日历栏。放开收缩，让宽表在 .table-wrap 里横向滚动。
 */
.split-2--scan > * { min-width: 0; }
/* 明细表的时间列整体不换行；表格宽出容器时由 .table-wrap 横向滚动兜底 */
.cell-time { white-space: nowrap; }

/*
 * 上传区的三个阶段要一眼可辨：
 * 选中文件后虚线框变成实线品牌色 + 打勾圆标 + "文件已就绪"徽章（只换文字太容易看漏）；
 * 分析中整块降透明并锁点击，按钮带转圈；完成后报告卡闪一圈品牌色描边把视线引过去。
 */
.dropzone.has-file { border-style: solid; border-color: var(--brand); background: var(--brand-soft); }
.dropzone.has-file .dropzone__icon {
  width: 44px; height: 44px; margin: 0 auto;
  display: flex; align-items: center; justify-content: center;
  border-radius: 999px; background: var(--brand);
  color: #fff; font-size: 22px; font-weight: var(--fw-bold);
}
.dropzone__badge {
  display: inline-block; margin-top: var(--space-3);
  font-size: 12.5px; font-weight: var(--fw-bold); color: var(--brand-strong);
  background: var(--surface-card); border: var(--bw-hairline) solid var(--brand);
  border-radius: 999px; padding: 3px 12px;
}
/* display:inline-block 会压过 [hidden] 的 UA 样式（display:none），必须显式补回，
   否则还没选文件就常驻"文件已就绪"——与 .nick-row[hidden] 同一个坑 */
.dropzone__badge[hidden] { display: none; }
.dropzone.is-busy { opacity: .65; pointer-events: none; }
@keyframes dz-pop { 0% { transform: scale(.98); } 60% { transform: scale(1.012); } 100% { transform: scale(1); } }
.dropzone.dz-pop { animation: dz-pop .28s var(--ease-standard); }
.btn__spin {
  display: inline-block; width: 14px; height: 14px; margin-right: 8px; vertical-align: -2px;
  border: 2px solid rgba(255, 255, 255, .45); border-top-color: #fff; border-radius: 50%;
  animation: btn-spin .8s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
@keyframes report-flash { from { box-shadow: 0 0 0 3px var(--brand); } to { box-shadow: 0 0 0 6px rgba(0, 0, 0, 0); } }
.report-flash { border-radius: var(--radius-md); animation: report-flash 1.2s var(--ease-standard); }
@media (prefers-reduced-motion: reduce) {
  .dropzone.dz-pop, .btn__spin, .report-flash { animation: none; }
}

/*
 * 汇损分析结果区的空态：一个去掉文字的报告骨架（磁贴、双色拆分条、明细行），
 * 让人先"看到"报告的形状，再用标签点名内容——比一段居中说明更能解释这块区域。
 * 骨架纯装饰（aria-hidden），条宽随手错开：整齐划一反而像加载中的 skeleton。
 */
.scan-empty { text-align: center; padding: var(--space-8) var(--space-6); }
.scan-empty__ghost {
  max-width: 400px;
  margin: 0 auto var(--space-6);
  padding: var(--space-5);
  background: var(--surface-sunken);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-md);
}
.scan-empty__tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
.scan-empty__tile i { display: block; height: 10px; border-radius: 999px; background: var(--border-hairline); }
.scan-empty__tile i:first-child { height: 16px; margin-bottom: 7px; background: var(--border-strong); }
.scan-empty__bar {
  height: 8px; margin-top: var(--space-4);
  border-radius: 999px; background: var(--border-hairline); overflow: hidden;
}
.scan-empty__bar i { display: block; height: 100%; border-radius: 999px; background: var(--brand); opacity: .5; }
.scan-empty__bar--alt i { background: var(--sky-500); opacity: .4; }
.scan-empty__rows { margin-top: var(--space-5); padding-top: var(--space-2); border-top: var(--bw-hairline) solid var(--border-hairline); }
.scan-empty__rows i { display: block; height: 9px; margin-top: var(--space-3); border-radius: 999px; background: var(--border-hairline); }
.scan-empty__rows i:nth-child(1) { width: 92%; }
.scan-empty__rows i:nth-child(2) { width: 74%; }
.scan-empty__rows i:nth-child(3) { width: 84%; }
.scan-empty__title { font-size: 16px; font-weight: var(--fw-black); color: var(--text-strong); letter-spacing: var(--ls-tight); }
.scan-empty__desc { margin: var(--space-2) 0 0; font-size: 13.5px; color: var(--text-muted); }
.scan-empty__tags {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--space-2); margin-top: var(--space-4);
}
.scan-empty__tags span {
  font-size: 12.5px; font-weight: var(--fw-bold); color: var(--brand-strong);
  background: var(--brand-soft); border-radius: 999px; padding: 4px 12px;
}
.scan-empty__note { margin: var(--space-5) 0 0; font-size: 12.5px; color: var(--text-subtle); }

.tutorial { border-top: var(--bw-hairline) dashed var(--border-hairline); margin-top: var(--space-6); padding-top: var(--space-5); }
.tutorial__row {
  display: grid; grid-template-columns: 90px 1fr auto;
  gap: var(--space-4); align-items: center;
  padding: var(--space-2) 0; font-size: 13px; color: var(--text-muted);
}
.tutorial__name { font-weight: var(--fw-bold); color: var(--text-strong); }

table.grid { width: 100%; border-collapse: collapse; background: var(--surface-card); }
table.grid th {
  font-size: 11.5px; font-weight: var(--fw-bold); color: var(--text-subtle);
  letter-spacing: var(--ls-wide); text-align: left;
  padding: var(--space-3) var(--space-5);
  background: var(--surface-sunken);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
  white-space: nowrap;
}
table.grid td {
  font-size: 13.5px; color: var(--text-body);
  /* 纵向 space-4：原来 space-3 让 5 行报价挤成一坨 */
  padding: var(--space-4) var(--space-5);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
  font-variant-numeric: tabular-nums;
}
table.grid tbody tr:last-child td { border-bottom: none; }
table.grid tbody tr.is-highlight { background: var(--brand-soft); }
.num { text-align: right; font-variant-numeric: tabular-nums; }
/*
 * th.num 必须显式写出来：`table.grid th { text-align: left }` 的权重是 (0,1,2)，
 * 压过只有 (0,1,0) 的 .num，结果数字列表头一直左对齐、单元格右对齐，
 * 表头和它下面的数字整列错开。
 */
table.grid th.num { text-align: right; }
.strong { font-weight: var(--fw-bold); color: var(--text-strong); }
.brand-strong { font-weight: var(--fw-bold); color: var(--brand-strong); }

.stat-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
.stat__value { font-size: 26px; font-weight: var(--fw-black); color: var(--text-strong); letter-spacing: var(--ls-tight); }
.stat__value--brand { color: var(--brand-strong); }
.stat__label { margin-top: 3px; font-size: 12.5px; color: var(--text-subtle); }

/* ------------------------------- 币种管理 -------------------------------- */

/* 两步上下排布：每步一整行，标题与操作在同一行的头部 */
.step-block { margin-bottom: var(--space-10); }
.step-block:last-child { margin-bottom: 0; }

.step-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4); flex-wrap: wrap;
  margin-bottom: var(--space-4);
}
.step-head__actions { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.step-head__actions .btn { padding: var(--space-2) var(--space-4); font-size: 12.5px; }

/*
 * 币种卡片按可用宽度自动分列。用 auto-fill + minmax 而不是固定列数：
 * 币种数量会随抓取配置变化，写死列数在币种增减时必然留下空洞或挤压。
 */
.ccy-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  /*
   * 所有行统一取最高行的高度。小币种（IDR 0.00037412）的说明文字会折成两行，
   * 不统一的话只有那一行卡片变高，看着像坏的。
   * 不选"截断汇率保证单行"：卡片上的汇率是给人核对用的，截掉小数位就没意义了。
   */
  grid-auto-rows: 1fr;
  gap: var(--space-3);
}
/* 空状态是一段说明文字，不该只占一格 */
.ccy-cards > .state { grid-column: 1 / -1; }

.ccy-item {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  transition: border-color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.ccy-item.is-on { border-color: var(--brand); background: var(--brand-soft); }
.ccy-item__icon {
  width: 30px; height: 30px; flex: none;
  border-radius: var(--radius-pill);
  background: var(--surface-sunken); color: var(--text-muted);
  display: grid; place-items: center;
  font-size: 13px; font-weight: var(--fw-bold);
}
.ccy-item.is-on .ccy-item__icon { background: var(--brand); color: var(--brand-on); }

/*
 * 徽标里放旗帜时去掉圆形底：圆底 + 矩形旗帜会在上下露出两道底色弧，
 * 选中态的绿底更明显，看着像旗帜被裁成了圆的。
 * 这三条必须写在上面两条<b>之后</b>——同为 0,1,0 / 0,2,0 特指度，靠顺序取胜。
 */
.ccy-item__icon--flag,
.ccy-item.is-on .ccy-item__icon--flag { background: none; border-radius: var(--radius-sm); }
.ccy-item__icon--flag .flag { width: 26px; height: 18.2px; }
.ccy-item__body { flex: 1; min-width: 0; }
/* 币种对与中文名各占一行：同一行里挤会在窄列下断成"USD / CNY美元 · 元" */
.ccy-item__pair {
  display: block; white-space: nowrap;
  font-size: 14px; font-weight: var(--fw-bold); color: var(--text-strong);
}
.ccy-item__sub {
  display: block; margin-top: 2px;
  font-size: 12px; color: var(--text-subtle); font-variant-numeric: tabular-nums;
}

/* 开关：原生 checkbox 保证可键盘操作与读屏可达，外观用兄弟元素画 */
.switch { position: relative; flex: none; width: 42px; height: 24px; }
.switch input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.switch__track {
  display: block; width: 42px; height: 24px;
  border-radius: var(--radius-pill); background: var(--ink-200);
  transition: background var(--dur-fast) var(--ease-standard);
  pointer-events: none;
}
.switch__track::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 18px; height: 18px; border-radius: var(--radius-pill);
  background: var(--surface-card); box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease-standard);
}
.switch input:checked ~ .switch__track { background: var(--brand); }
.switch input:checked ~ .switch__track::after { transform: translateX(18px); }
.switch input:focus-visible ~ .switch__track { box-shadow: var(--ring-brand); }
.switch input:disabled ~ .switch__track { opacity: 0.5; }

.input--bp {
  width: 72px; padding: var(--space-2) var(--space-3);
  text-align: right; font-size: 14px; font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
}
.bp-cell { display: flex; align-items: center; gap: 6px; }
.bp-unit { font-size: 11.5px; color: var(--text-subtle); }
.bp-permille { margin-top: 4px; font-size: 11.5px; font-weight: var(--fw-bold); color: var(--brand-strong); }
.fill-all {
  display: block; margin-top: 3px;
  background: none; border: none; padding: 0;
  font-family: inherit; font-size: 12px; font-weight: var(--fw-bold);
  color: var(--brand-strong); cursor: pointer;
}
.fill-all:hover { color: var(--brand); }
.fill-all:disabled { color: var(--text-subtle); cursor: not-allowed; }

/* ----------------------------- 换汇时机页布局 ----------------------------- */

/*
 * 左栏放"选哪个币种 / 要不要评估"两个决定，右栏放内容。
 * 决定始终可见，看内容时不用滚回顶部找选择器。
 * 260px：放得下 "USD / CNY" 这样的币种对和一个整行按钮，又不吃掉右栏太多宽度。
 */
.timing-layout {
  display: grid; grid-template-columns: 260px minmax(0, 1fr);
  gap: var(--space-6);
  align-items: start;
}
.timing-side { display: flex; flex-direction: column; gap: var(--space-5); }
.timing-main { min-width: 0; }

/* 币种对竖排：横排 chip 在 260px 里会折成好几行 */
.pair-list { display: flex; flex-direction: column; gap: var(--space-2); }
.pair-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-md);
  background: var(--surface-card); color: var(--text-body);
  font-family: inherit; font-size: 14px; font-weight: var(--fw-bold);
  cursor: pointer; text-align: left;
  transition: background var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
.pair-row:hover { border-color: var(--brand); color: var(--brand-strong); }
.pair-row[aria-pressed="true"] {
  background: var(--brand); color: var(--brand-on); border-color: var(--brand);
}

/* 评估触发器 */
.side-action { border-color: var(--border-brand); }
.side-action__title { font-size: 15px; font-weight: var(--fw-black); color: var(--text-strong); }
.side-action__desc {
  margin: var(--space-2) 0 var(--space-4);
  font-size: 12px; line-height: var(--lh-snug); color: var(--text-muted);
}
/* 按钮下方的状态行：解释按钮此刻为什么写着"重新测算" */
.side-action__state {
  display: flex; align-items: center; gap: 5px;
  margin-top: var(--space-3);
  font-size: 11.5px; color: var(--text-subtle);
}
.side-action__state::before {
  content: ""; width: 6px; height: 6px; flex: none;
  border-radius: var(--radius-pill); background: var(--ink-300);
}
.side-action__state.is-ready { color: var(--brand-strong); }
.side-action__state.is-ready::before { background: var(--brand); }
.side-action__state.is-running::before {
  background: var(--warning); animation: tabPulse 1s ease-in-out infinite;
}

/* 右栏窄了，走势与成交价改上下排 */
@media (min-width: 1181px) {
  .timing-main .timing-cols { grid-template-columns: minmax(0, 1fr); }
}
/* 平板及以下左栏落到上方，按钮与币种对横排省高度 */
@media (max-width: 1080px) {
  .timing-layout { grid-template-columns: 1fr; }
  .timing-side { flex-direction: row; flex-wrap: wrap; }
  .timing-side > * { flex: 1; min-width: 260px; }
  .pair-list { flex-direction: row; flex-wrap: wrap; }
  .pair-row { flex: 0 0 auto; }
}

/* --------------------------------- 视图切换 -------------------------------- */

/*
 * 分段控件（一个凹槽 + 选中段浮起）而不是下划线：
 * 下划线太轻，夹在币种对卡片和内容卡片之间根本立不住。
 * 也不用散排胶囊——胶囊已经被币种对 chip 和区间 tab 用掉了，
 * 散排会读成"又一个筛选器"；套进凹槽、块头比 chip 大一号，才像页面级的视图切换。
 */
.tabs {
  display: inline-flex; gap: var(--space-1);
  padding: var(--space-2);
  border-radius: var(--radius-lg);
  background: var(--surface-sunken);
  border: var(--bw-hairline) solid var(--border-hairline);
  margin-bottom: var(--space-6);
  max-width: 100%; overflow-x: auto;
}
.tab {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-6);
  border: none; border-radius: var(--radius-md);
  background: none;
  font-family: inherit; font-size: 16px; font-weight: var(--fw-bold);
  color: var(--text-muted); cursor: pointer; white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
.tab:hover { color: var(--brand-strong); }
/* 选中段：品牌色实底 + 白字，一眼看出当前在哪个视图 */
.tab[aria-selected="true"] {
  background: var(--brand);
  color: var(--brand-on);
  box-shadow: var(--shadow-sm);
}
.tab[aria-selected="true"]:hover { background: var(--brand-strong); color: var(--brand-on); }
.tab:focus-visible { outline: none; box-shadow: var(--ring-brand); }

/*
 * tab 上的状态点：评估结果要花两秒才算得出来，切走后必须能看出它算完没有，
 * 否则用户只能反复切回去确认。
 */
.tab__state {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: var(--fw-medium); color: var(--text-subtle);
}
.tab__state::before {
  content: ""; width: 6px; height: 6px; flex: none;
  border-radius: var(--radius-pill); background: var(--ink-300);
}
.tab__state.is-ready { color: var(--brand-strong); }
.tab__state.is-ready::before { background: var(--brand); }
/* 选中段是绿底：状态点与文字必须转成白系，绿底上的绿点等于看不见 */
.tab[aria-selected="true"] .tab__state { color: var(--text-on-dark-mut); }
.tab[aria-selected="true"] .tab__state::before { background: rgba(255, 255, 255, 0.55); }
.tab[aria-selected="true"] .tab__state.is-ready { color: var(--brand-on); }
.tab[aria-selected="true"] .tab__state.is-ready::before { background: var(--brand-on); }
/* 测算中同理转白（琥珀点落在绿底上会糊成一团），呼吸动画仍在 */
.tab[aria-selected="true"] .tab__state.is-running::before { background: var(--brand-on); }
.tab__state.is-running::before { background: var(--warning); animation: tabPulse 1s ease-in-out infinite; }
@keyframes tabPulse { 50% { opacity: 0.25; } }

/* 切换时给一点淡入，避免整块内容硬闪 */
.tab-panel { animation: panelIn var(--dur-base) var(--ease-out); }
@keyframes panelIn { from { opacity: 0; transform: translateY(4px); } }

@media (max-width: 520px) {
  .tab { padding: var(--space-3) var(--space-4); font-size: 14px; }
  .tab__state { display: none; }
}

/* 结果区标题行：说明 + 重新测算，替掉原来那条和结论卡重复的绿色横条 */
.result-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4); flex-wrap: wrap;
  margin-bottom: var(--space-4);
}
.result-head__meta {
  display: flex; align-items: center; gap: var(--space-4);
  font-size: 12px; color: var(--text-subtle);
}

/* 切换时给一点淡入，避免整块内容硬闪 */
.tab-panel { animation: panelIn var(--dur-base) var(--ease-out); }
@keyframes panelIn { from { opacity: 0; transform: translateY(4px); } }

@media (max-width: 520px) {
  .tabs { gap: var(--space-5); }
  .tab { font-size: 14px; }
  .tab__state { display: none; }
}

/* ------------------------------- 换汇时机 -------------------------------- */

/*
 * 走势与平台表两栏，走势略宽（1.15 : 1）。
 * 原来是「260px 控制列 + 右侧再对半分」，1440px 下每块只剩约 500px，
 * 图被压扁、平台名折行。把控制列提到顶部横条后两块各多约 130px。
 */
.timing-cols {
  display: grid;
  /*
   * 右栏按数据自身宽度收到 600px 以内（4 列内容加内边距约 595px），剩下的都给走势图。
   * 原来是 1.15fr / 1fr，成交价表拿到 629px，平台名一列独占 223px，数字之间空得发散。
   */
  grid-template-columns: minmax(0, 1fr) minmax(0, 600px);
  gap: var(--space-6);
  /*
   * start 而不是 stretch：拉平两卡高度会在成交价表最后一行下面留一大片空白，
   * 行距收紧后这片空白反而更明显。两卡各自按内容收高。
   */
  align-items: start;
  margin-bottom: var(--space-6);
}
.timing-cols > .card { display: flex; flex-direction: column; }
.timing-cols > .card > .card__body { flex: 1; }
.timing-cols > .card > .table-wrap--flush { flex: 1; }

/* 顶部工具条：币种对选择 + 提示 */
.toolbar {
  display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap;
  padding: var(--space-4) var(--space-6);
  margin-bottom: var(--space-6);
}
.toolbar__label { font-size: 12.5px; font-weight: var(--fw-bold); color: var(--text-subtle); white-space: nowrap; }
.toolbar__hint { margin-left: auto; font-size: 12px; color: var(--text-subtle); }

/* 页头右侧的基准价：原来只是一行小字，信息层级太弱 */
/*
 * 页头统计条：标题右侧的三格（币种对 / 当前基准 / 窗口涨跌）。
 * 竖分隔线沿用 plan-cells 的分栏语言；page-head 本身 flex-wrap，
 * 窄屏时整条换到标题下方。
 */
.head-stats { display: flex; align-items: stretch; flex-wrap: wrap; row-gap: var(--space-4); }
.head-stat {
  display: flex; flex-direction: column; justify-content: flex-end;
  min-width: 140px; padding: 0 var(--space-6);
  border-left: var(--bw-hairline) solid var(--border-hairline);
}
.head-stat:first-child { border-left: 0; padding-left: 0; }
.head-stat:last-child { padding-right: 0; }
.head-stat__label { font-size: 11.5px; color: var(--text-subtle); white-space: nowrap; }
.head-stat__value {
  display: flex; align-items: center; gap: var(--space-2);
  margin-top: 2px; font-size: 21px; font-weight: var(--fw-black);
  color: var(--text-strong); line-height: 1.25; white-space: nowrap;
}
.head-stat__value--num { font-variant-numeric: tabular-nums; }
/*
 * 涨跌色（国内惯例红涨绿跌）要压过本组件的默认字色：
 * .delta--up 与 .head-stat__value 同为单类选择器，按声明顺序后者胜出，
 * 只挂 .delta--up 类在这格上不起作用——必须用组合选择器提高特异性。
 */
.head-stat__value.delta--up { color: var(--danger); }
.head-stat__value.delta--down { color: var(--brand-strong); }
.head-stat__value.delta--flat { color: var(--text-subtle); }
.head-stat__value .flag { width: 22px; height: 15.4px; }
.head-stat__sub { margin-top: 2px; font-size: 11.5px; color: var(--text-subtle); white-space: nowrap; }

/* ---------------------------- 自动刷新环 ---------------------------- */

.autorefresh {
  position: relative;
  width: 30px; height: 30px; flex: none;
  padding: 0; border: 0; background: none; cursor: pointer;
  display: grid; place-items: center;
  color: var(--brand);
}
.autorefresh__ring { position: absolute; inset: 0; width: 100%; height: 100%; }
.autorefresh__ring circle {
  fill: none; stroke-width: 2.5;
  /* 从 12 点开始顺时针走，默认是 3 点方向起步 */
  transform: rotate(-90deg); transform-origin: 50% 50%;
}
.autorefresh__track { stroke: var(--ink-200); }
.autorefresh__sweep {
  stroke: currentColor; stroke-linecap: round;
  /* 只过渡 0.9 秒：整秒跳一格会显得一顿一顿，但也不能长到盖住下一次跳变 */
  transition: stroke-dashoffset .9s linear;
}
.autorefresh__num {
  position: relative;
  font-size: var(--ui-xs); font-weight: var(--fw-bold);
  color: var(--text-muted); font-variant-numeric: tabular-nums;
  line-height: 1;
}
.autorefresh:hover .autorefresh__num { color: var(--text-strong); }
/* 暂停态整体转灰，环空着——一眼能看出"它没在数" */
.autorefresh.is-off { color: var(--ink-300); }
.autorefresh.is-off .autorefresh__num { color: var(--text-subtle); font-size: var(--ui-sm); }
/* 刷新中：环填满并转起来，不用再额外放一个 loading 图标 */
.autorefresh.is-busy .autorefresh__sweep { transition: none; animation: autorefresh-spin 900ms linear infinite; }
@keyframes autorefresh-spin {
  from { transform: rotate(-90deg); }
  to { transform: rotate(270deg); }
}
.autorefresh:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: var(--radius-pill); }
/* 所在的 meta 行是 baseline 对齐，环没有文字基线，按基线排会掉下去半个环 */
.quote-line__meta .autorefresh { align-self: center; }

/* --------------------------- 数据免责声明浮层 --------------------------- */

.disclaimer { position: relative; display: inline-flex; }
.disclaimer__trigger {
  padding: 0; border: 0; background: none; cursor: pointer;
  font-size: var(--ui-xs); color: var(--text-subtle);
  font-family: inherit; line-height: var(--lh-snug);
}
.disclaimer__link { color: var(--brand); text-decoration: underline; text-underline-offset: 2px; }
.disclaimer__trigger:hover .disclaimer__link { text-decoration-thickness: 2px; }
.disclaimer__trigger:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: var(--radius-xs); }

.disclaimer__panel {
  position: absolute; z-index: 40;
  /*
   * 向上弹出：触发链接在卡片底部，往下弹会被页脚截断。
   * 右对齐：链接贴在卡片右下角，从它的左边缘往右展开 420px 会溢出卡片；
   * 若哪天把链接挪回左侧，这里要跟着改成 left: 0（否则会溢出卡片左边）。
   */
  bottom: calc(100% + 10px); right: 0;
  width: min(420px, calc(100vw - 2 * var(--space-6)));
  padding: var(--space-5);
  background: var(--surface-card);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  text-align: left;
}
.disclaimer__panel[hidden] { display: none; }
/* 小尖角指回触发的链接，说明这段话是它展开的 */
.disclaimer__panel::after {
  content: ''; position: absolute; top: 100%; right: 18px;
  border: 7px solid transparent; border-top-color: var(--surface-card);
}
.disclaimer__title {
  font-size: var(--ui-lg); font-weight: var(--fw-bold);
  color: var(--text-strong); margin-bottom: var(--space-3);
}
.disclaimer__text {
  margin: 0 0 var(--space-2);
  font-size: var(--ui-sm); line-height: var(--lh-body); color: var(--text-muted);
}
.disclaimer__text:last-child { margin-bottom: 0; }

/* 卡片头/脚：把标题与说明从 body 里拆出来，内容区才有完整的呼吸空间 */
.card__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4); flex-wrap: wrap;
  padding: var(--space-4) var(--space-6);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
}
.card__foot {
  padding: var(--space-4) var(--space-6);
  border-top: var(--bw-hairline) solid var(--border-hairline);
  font-size: 12px; line-height: var(--lh-snug); color: var(--text-subtle);
}
/* 表格直接贴在卡片头下方，不再嵌一层圆角边框 */
.table-wrap--flush { border: none; border-radius: 0; }
/*
 * 成交价表把行距与列内边距都收一档（纵向 space-4 → space-3，横向 space-5 → space-4）：
 * 一屏只有 6 行、每行 4 个数，宽松的间距让同一行的数字看着不像一组。
 */
table.grid--quote th, table.grid--quote td { padding: var(--space-3) var(--space-4); }

/* ------------------------- 推荐换汇执行方案 ------------------------- */

/*
 * 四个关键结论横排一行，用竖分隔线切开而不是四张卡：
 * 它们是同一个方案的四个侧面，拆成卡片会读成四件互不相干的事。
 */
.plan-cells { display: grid; grid-template-columns: repeat(4, 1fr); }
.plan-cell {
  padding: var(--space-5) var(--space-6);
  border-right: var(--bw-hairline) solid var(--border-hairline);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
}
.plan-cell:last-child { border-right: none; }
.plan-cell__label { font-size: 12px; color: var(--text-subtle); }
.plan-cell__value {
  margin-top: var(--space-2);
  font-size: 19px; font-weight: var(--fw-black); color: var(--text-strong);
  letter-spacing: var(--ls-tight); font-variant-numeric: tabular-nums;
}
.plan-cell__sub { margin-top: 2px; font-size: 11.5px; color: var(--text-muted); }

@media (max-width: 900px) {
  .plan-cells { grid-template-columns: repeat(2, 1fr); }
  .plan-cell:nth-child(2n) { border-right: none; }
}
/* 平台名不折行（"万里汇 WorldFirst" 原来会断成两行）；列宽不够时整表横向滚动 */
.table-wrap--flush td:first-child,
.table-wrap--flush th:first-child { white-space: nowrap; }

.pair-picker { display: flex; gap: var(--space-3); flex-wrap: wrap; }
.pair-chip {
  padding: var(--space-2) var(--space-3);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-pill);
  background: var(--surface-card); color: var(--text-muted);
  font-family: inherit; font-size: 13px; font-weight: var(--fw-bold);
  cursor: pointer; white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.pair-chip[aria-pressed="true"] { background: var(--brand); color: var(--brand-on); border-color: var(--brand); }

.range-tabs { display: flex; gap: var(--space-2); }
.range-tab {
  padding: var(--space-2) var(--space-4);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-pill);
  background: var(--surface-card); color: var(--text-muted);
  font-family: inherit; font-size: 12.5px; font-weight: var(--fw-bold); cursor: pointer;
}
.range-tab[aria-pressed="true"] { background: var(--brand); color: var(--brand-on); border-color: var(--brand); }

/*
 * 汇率区（换算器 + 摘要行 + 走势）参考行业内实时汇率页的信息顺序：
 * 先给「多少钱换多少钱」这个用户真正要的答案，再给单位汇率与更新时间，最后才是走势。
 */
.convert {
  display: flex; align-items: stretch; gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.convert__field {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-md);
  background: var(--surface-card);
}
/* 结果侧不可编辑，用浅底把它和输入框区分开 */
.convert__field--result { background: var(--surface-sunken); }
.convert__field:focus-within { border-color: var(--brand); box-shadow: var(--ring-brand); }
.convert__amount {
  flex: 1; min-width: 0;
  border: none; background: none; padding: 0;
  font-family: inherit; font-size: 22px; font-weight: var(--fw-black);
  color: var(--text-strong); letter-spacing: var(--ls-tight);
  font-variant-numeric: tabular-nums;
}
.convert__amount:focus { outline: none; box-shadow: none; }
/* 结果是 span，靠 overflow 兜住超长数字，不撑破卡片 */
.convert__amount--result { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.convert__ccy {
  flex: none; font-size: 13px; font-weight: var(--fw-bold);
  color: var(--text-muted); letter-spacing: var(--ls-wide);
}
.convert__swap {
  flex: none; width: 36px;
  border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-md);
  background: var(--surface-card); color: var(--brand);
  font-family: inherit; font-size: 16px; cursor: pointer;
  transition: background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.convert__swap:hover { background: var(--brand); color: var(--brand-on); border-color: var(--brand); }

.quote-line {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-4); flex-wrap: wrap;
  padding-bottom: var(--space-5);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
}
.quote-line__main {
  font-size: 15px; font-weight: var(--fw-bold); color: var(--text-strong);
  font-variant-numeric: tabular-nums;
}
/* 口径与更新时间必须跟着摘要一起给：不写清是哪个价、什么时候的，数字就没法用 */
.quote-line__meta {
  display: flex; align-items: baseline; gap: var(--space-3);
  font-size: 11.5px; color: var(--text-subtle);
}

.chart-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4); flex-wrap: wrap;
  margin: var(--space-5) 0 var(--space-2);
}

.chart { width: 100%; height: 280px; display: block; }
/*
 * SVG 里的 <text> 不会继承页面字体，不写就退回浏览器默认字体（多半是衬线体），
 * 刻度和正文看着是两套字。数字用等宽数位，横轴时刻不会因为字宽不同左右跳动。
 */
.chart text {
  font-family: var(--font-sans);
  font-variant-numeric: tabular-nums;
}
/*
 * 图下的一整条：口径说明 + 靠右的免责声明。
 *
 * 说明本身是"窗口起点 / 数据点数 / 窗口终点"三段 space-between 排布，实测要 556px。
 * 这里给它 470px 的基准宽：加上声明的 72px 与间距，容器窄于约 558px 时
 * 声明会自己掉到下一行（仍靠右），而不是把说明挤成两行。
 *
 * 分隔线移到这里：两块共用一条，各自画一条会出现两道细线。
 */
.chart-foot {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: var(--bw-hairline) solid var(--border-hairline);
}
.chart-foot > .chart-note {
  flex: 1 1 470px; min-width: 0;
  margin-top: 0; padding-top: 0; border-top: 0;
}
/* margin-left:auto：同一行时贴右边，换到下一行时仍然右对齐 */
.chart-foot > .disclaimer { flex: none; margin-left: auto; }

.chart-note {
  display: flex; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap;
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: var(--bw-hairline) solid var(--border-hairline);
  font-size: 11.5px; color: var(--text-subtle);
}

/*
 * 评估区横条：入口 / 进度 / 结论三态共用。
 * 原来是左栏里一个窄深色卡，按钮被压成两行、和上面的币种选择器黏在一起。
 */
.eval-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-8); flex-wrap: wrap;
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  border: var(--bw-hairline) solid var(--border-hairline);
  background: var(--surface-card);
  margin-bottom: var(--space-6);
}
.eval-bar__main { flex: 1; min-width: 260px; }
.eval-bar__title { margin-top: var(--space-2); font-size: 20px; font-weight: var(--fw-black); color: var(--text-strong); letter-spacing: var(--ls-tight); }
.eval-bar__desc { margin-top: var(--space-2); font-size: 13px; line-height: var(--lh-snug); color: var(--text-muted); }

/* 入口态用深色强调"去点这里"，与页面其余白底卡片区分开 */
.eval-bar--cta { background: var(--surface-dark); border-color: var(--surface-dark); }
.eval-bar--cta .eval-bar__title { color: var(--text-on-dark); }
.eval-bar--cta .eval-bar__desc { color: var(--text-on-dark-mut); max-width: 62ch; }
/* 深底上的步骤清单：浅底的灰在这里几乎看不见 */
.eval-bar--cta .eval-step { color: var(--text-on-dark-mut); }
.eval-bar--cta .eval-step__mark { border-color: var(--night-700); }
.eval-bar--cta .eval-step__no { color: var(--text-on-dark-mut); }
/* 入口态的清单只是"接下来会算什么"，序号立在前面，勾还没有意义 */
.eval-bar--cta .eval-steps { margin-top: var(--space-5); }
/* 右栏入口态不放按钮：同一屏两个同功能按钮会让人不知道点哪个 */
.eval-bar__hint {
  margin-top: var(--space-5);
  font-size: 12.5px; font-weight: var(--fw-bold); color: var(--green-300);
}

.eval-bar--done { border-color: var(--brand); background: var(--brand-soft); }
.eval-bar--running .eval-bar__title { font-size: 16px; font-weight: var(--fw-bold); }

.progress { height: 6px; border-radius: var(--radius-pill); background: var(--ink-200); overflow: hidden; margin: var(--space-3) 0 var(--space-4); }
.progress__bar { height: 100%; background: var(--brand); transition: width var(--dur-slow) var(--ease-standard); }

.eval-steps { display: flex; gap: var(--space-6); flex-wrap: wrap; }
/*
 * 序号只在还没开始（入口态）时露出来，一旦某步进入运行/完成态就交给圆圈标记，
 * 免得同一个位置既有序号又有勾。
 */
.eval-step__no {
  font-size: 11.5px; font-weight: var(--fw-bold); color: var(--text-subtle);
  margin-left: calc(-1 * var(--space-2));
}
.eval-step.is-running .eval-step__no,
.eval-step.is-done .eval-step__no { display: none; }
.eval-step { display: flex; align-items: center; gap: var(--space-3); font-size: 13px; color: var(--text-muted); }
.eval-step__mark {
  width: 18px; height: 18px; flex: none;
  border-radius: var(--radius-pill);
  border: var(--bw-thick) solid var(--ink-200);
  display: grid; place-items: center; font-size: 11px; color: transparent;
}
.eval-step.is-done { color: var(--text-strong); }
.eval-step.is-done .eval-step__mark { background: var(--brand); border-color: var(--brand); color: var(--brand-on); }
.eval-step.is-running .eval-step__mark {
  border-color: var(--brand); border-right-color: transparent;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ------------------------------- AI 走势解读 ------------------------------ */

/* 入口卡标题上的 Agent 标记 */
.ai-tag {
  margin-left: var(--space-3);
  padding: 2px var(--space-3);
  border-radius: var(--radius-pill);
  border: var(--bw-hairline) solid var(--green-400);
  background: rgba(0, 168, 77, 0.16);
  font-size: 11px; font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide); color: var(--green-300);
  vertical-align: middle;
}

/*
 * 模型观点刻意和确定性结论卡长得不一样：左侧竖条 + 浅蓝底 + 「模型生成」标记。
 * 两者可信度不同——统计同样输入必得同样输出，模型输出可能出错——
 * 长得一样会让用户把模型的措辞当成统计结论。
 */
.forecast {
  margin-top: var(--space-5);
  padding: var(--space-5) var(--space-6);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-left: 4px solid var(--sky-500);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
}
.forecast__head {
  display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap;
  margin-bottom: var(--space-3);
}
.forecast__badge {
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken); color: var(--text-strong);
  font-size: 12px; font-weight: var(--fw-bold);
}
/* 方向着色按国内惯例红涨绿跌，只用于区分方向，不代表"好/坏"——结汇方向不同，涨跌的利弊也相反 */
.forecast__badge.is-up { background: #FDECEA; color: #A3271D; }
.forecast__badge.is-down { background: rgba(0, 168, 77, 0.12); color: var(--brand-strong); }
.forecast__meta { font-size: 12px; color: var(--text-muted); }
/* 「模型生成」这行必须在，且要跟模型名与时间绑在一起 */
.forecast__origin {
  margin-left: auto;
  font-size: 11.5px; color: var(--sky-600);
  font-variant-numeric: tabular-nums;
}
.forecast__summary {
  font-size: 15px; font-weight: var(--fw-bold); line-height: var(--lh-snug);
  color: var(--text-strong);
}
.forecast__groups {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6);
  margin-top: var(--space-4);
}
.forecast__group-title {
  font-size: 11.5px; font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide); color: var(--text-subtle);
  margin-bottom: var(--space-2);
}
.forecast__group ul { margin: 0; padding-left: var(--space-5); }
.forecast__group li {
  font-size: 13px; line-height: var(--lh-body); color: var(--text-body);
  margin-bottom: 2px;
}
.forecast__foot {
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: var(--bw-hairline) solid var(--border-hairline);
  font-size: 11.5px; line-height: var(--lh-snug); color: var(--text-subtle);
}

/*
 * 联网检索深度分析。
 * 与上面那块模型解读用不同的左边条颜色区分来源：那块只看我们自己的历史统计，
 * 这块是联网检索来的外部信息，两者结论可能不一致，视觉上必须能分开。
 */
.deep {
  margin-top: var(--space-5);
  padding: var(--space-5) var(--space-6);
  border: var(--bw-hairline) solid var(--border-hairline);
  border-left: 4px solid var(--brand);
  border-radius: var(--radius-lg);
  background: var(--surface-card);
}
.deep__head {
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  padding-bottom: var(--space-3);
  border-bottom: var(--bw-hairline) solid var(--border-hairline);
}
.deep__tag {
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--brand); color: #fff;
  font-size: 12px; font-weight: var(--fw-bold);
}
.deep__meta { font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
/* 引擎名与生成时间必须在，且要跟内容绑在一起 */
.deep__origin {
  margin-left: auto;
  font-size: 11.5px; color: var(--brand-strong);
  font-variant-numeric: tabular-nums;
}
.deep__outlook { margin-top: var(--space-4); }
.deep__bias-row { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.deep__bias {
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken); color: var(--text-strong);
  font-size: 13px; font-weight: var(--fw-bold);
}
/* 方向着色按国内惯例红涨绿跌，只用于区分方向，不代表"好/坏"——结汇方向不同，涨跌的利弊也相反 */
.deep__bias.is-up { background: #FDECEA; color: #A3271D; }
.deep__bias.is-down { background: rgba(0, 168, 77, 0.12); color: var(--brand-strong); }
.deep__bias-meaning {
  margin-top: var(--space-2);
  font-size: 14px; font-weight: var(--fw-bold); line-height: var(--lh-snug);
  color: var(--text-strong);
}
.deep__narrative {
  margin-top: var(--space-2);
  font-size: 13px; line-height: var(--lh-body); color: var(--text-body);
}
.deep__driver { display: block; margin-top: 2px; font-size: 12px; color: var(--text-muted); }
.deep__cols {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6);
  margin-top: var(--space-4);
  align-items: start;
}
.deep__group { min-width: 0; }
/* 表格各自占满整行：挤成半宽时日期与短标签会在词中间折行 */
.deep__block { margin-top: var(--space-5); }
/*
 * 短列不折行。要压过 table.grid td 的默认设置，所以带上 table.grid 前缀——
 * .nowrap 单独写(0,1,0)排不过 table.grid td(0,1,2)。
 */
table.grid th.nowrap, table.grid td.nowrap { white-space: nowrap; }
.deep__group-title {
  font-size: 11.5px; font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide); color: var(--text-subtle);
  margin-bottom: var(--space-2);
}
.deep__group-note { font-weight: var(--fw-medium); letter-spacing: 0; }
.deep__group ul, .deep__gaps ul { margin: 0; padding-left: var(--space-5); }
.deep__group li, .deep__gaps li {
  font-size: 13px; line-height: var(--lh-body); color: var(--text-body);
  margin-bottom: 2px;
}
/* 反面观点独立成块并描边：它与上面的倾向对立，混排会被当成同一段结论读 */
.deep__counter {
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: var(--bw-hairline) dashed var(--border-strong);
  border-radius: var(--radius-md);
  font-size: 13px; line-height: var(--lh-body); color: var(--text-body);
}
.deep__counter-tag {
  display: inline-block; margin-right: var(--space-2);
  font-size: 11.5px; font-weight: var(--fw-bold); color: var(--text-subtle);
}
.deep__evidence {
  margin-top: var(--space-5); padding-top: var(--space-4);
  border-top: var(--bw-hairline) solid var(--border-hairline);
}
.deep__chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.deep__chips--site { margin-top: var(--space-2); }
.deep__chip {
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken); color: var(--text-muted);
  font-size: 11.5px;
}
.deep__chips--site .deep__chip { color: var(--brand-strong); }
.deep__note { margin-top: 2px; font-size: 11.5px; line-height: var(--lh-snug); color: var(--text-muted); }
.deep__src { margin-left: var(--space-2); font-size: 11.5px; color: var(--text-subtle); white-space: nowrap; }
.deep__link { color: var(--link); text-decoration: underline; }
.deep__link:hover { color: var(--link-hover); }
.deep__gaps {
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: var(--bw-hairline) solid var(--border-hairline);
}
.deep__foot {
  margin-top: var(--space-4); padding-top: var(--space-3);
  border-top: var(--bw-hairline) solid var(--border-hairline);
  font-size: 11.5px; line-height: var(--lh-snug); color: var(--text-subtle);
}

@media (max-width: 900px) {
  .deep__cols { grid-template-columns: 1fr; gap: var(--space-4); }
  .deep__origin { margin-left: 0; }
  .forecast__groups { grid-template-columns: 1fr; gap: var(--space-4); }
  .forecast__origin { margin-left: 0; }
}

/* 结论条：设计稿的深色总结块 */
.verdict {
  border-radius: var(--radius-lg); overflow: hidden;
  background: var(--surface-dark); color: var(--text-on-dark);
  padding: var(--space-6);
  display: grid; grid-template-columns: 1.4fr 1fr; gap: var(--space-8);
}
/*
 * 结汇窗口的起止。原来是「08-05 – 08-07」一行大字：两个月日夹一根短横，
 * 既像一个整体（08-05-08-07）又像减号。改成起、止各自带标签成块、
 * 中间箭头指向、末尾给工作日天数，日期用等宽数字对齐。
 */
.verdict__window {
  display: flex; align-items: baseline; flex-wrap: wrap;
  gap: var(--space-2) var(--space-3); margin-top: var(--space-2);
}
/* 没有起止日期（库内无牌价）时退回一行人话描述，仍保持原来的字号 */
.verdict__window--plain { display: block; font-size: 30px; font-weight: var(--fw-black); letter-spacing: var(--ls-tight); }
.verdict__window-end { display: flex; align-items: baseline; gap: var(--space-2); }
.verdict__window-tag {
  font-size: 12px; font-weight: var(--fw-bold);
  color: var(--text-on-dark-mut);
}
.verdict__window-date {
  font-size: 30px; font-weight: var(--fw-black); letter-spacing: var(--ls-tight);
  font-variant-numeric: tabular-nums;
}
.verdict__window-day {
  font-size: 12px; font-weight: var(--fw-medium); color: var(--text-on-dark);
  padding: 2px var(--space-2); border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.14);
}
/*
 * 箭头恒为向右。不按视口宽度旋转成向下——媒体查询判断的是视口而不是
 * 这一行是否真的折了，宽度到点但还排得下时就会出现"两块并排、箭头朝下"。
 * 真折行时起、止各占一行、箭头收在行尾，照样读得通。
 */
.verdict__window-arrow { font-size: 20px; color: var(--text-on-dark-mut); }
.verdict__window-days {
  font-size: 12px; color: var(--text-on-dark-mut);
  padding-left: var(--space-3);
  border-left: var(--bw-hairline) solid rgba(255, 255, 255, 0.18);
}
.verdict__desc { margin-top: var(--space-3); font-size: 13px; color: var(--text-on-dark-mut); line-height: var(--lh-snug); }
.verdict__diff { margin-top: var(--space-5); padding-top: var(--space-4); border-top: var(--bw-hairline) solid rgba(255, 255, 255, 0.14); font-size: 12.5px; color: var(--text-on-dark-mut); }
.verdict__diff b { font-size: 18px; color: var(--green-300); margin-left: var(--space-2); }
.verdict__pct { font-size: 46px; font-weight: var(--fw-black); color: var(--green-300); line-height: 1; }
.verdict__pct small { font-size: 20px; }
/* overflow 不能裁：游标要露在轨道外侧才看得清 */
.verdict__gauge {
  position: relative; height: 6px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.18);
  margin: var(--space-3) 0 var(--space-2);
}
.verdict__gauge-fill { height: 100%; border-radius: var(--radius-pill); background: var(--green-300); }
/*
 * 当前位置游标：分位低到 2.5% 时填充几乎不可见，光看填充像是没算出来。
 * 游标让"处在最左侧"和"没有数据"区分得开。
 */
.verdict__gauge-knob {
  position: absolute; top: 50%;
  width: 12px; height: 12px; margin: -6px 0 0 -6px;
  border-radius: var(--radius-pill);
  background: var(--brand-on);
  box-shadow: 0 0 0 2px var(--green-300);
}
.verdict__scale { display: flex; justify-content: space-between; font-size: 11.5px; color: var(--text-on-dark-mut); }
/* 刻度口径必须写出来：排名分位与价格线性位置只在端点重合，中间对不上 */
.verdict__scale-note { margin-top: var(--space-2); font-size: 11px; color: var(--text-on-dark-mut); opacity: 0.75; }
.verdict__pair { display: flex; gap: var(--space-8); margin-top: var(--space-4); }
.verdict__pair span { font-size: 11.5px; color: var(--text-on-dark-mut); }
.verdict__pair b { display: block; margin-top: 2px; font-size: 18px; color: var(--text-on-dark); }

/* 柱状图：纯 div 画，避免为几个柱子引入图表库 */
.bars-chart { display: flex; align-items: flex-end; gap: 3px; height: 150px; }
.bars-chart i { flex: 1; min-width: 3px; border-radius: 2px 2px 0 0; background: var(--ink-200); }
.bars-chart i.is-above { background: var(--brand); }
.bars-legend { display: flex; align-items: center; gap: var(--space-5); margin-top: var(--space-3); font-size: 11.5px; color: var(--text-subtle); }
.bars-legend span { display: flex; align-items: center; gap: 6px; }
.bars-legend em { width: 9px; height: 9px; border-radius: 2px; background: var(--brand); }
.bars-legend em.is-muted { background: var(--ink-200); }

.week-chart { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--space-3); align-items: end; height: 150px; }
.week-bar { display: flex; flex-direction: column; justify-content: flex-end; height: 100%; }
.week-bar i { background: var(--ink-200); border-radius: var(--radius-xs); }
.week-bar.is-best i { background: var(--brand); }
.week-bar span { margin-top: var(--space-2); text-align: center; font-size: 12px; color: var(--text-subtle); }
.week-bar.is-best span { color: var(--brand-strong); font-weight: var(--fw-bold); }

/*
 * 最佳换汇窗口的周柱：柱顶标周均价、柱底标周起始日。
 * 没有这两个标注时整张图只剩相对高矮——而柱高是 min-max 相对缩放出来的，
 * 差异被刻意放大以便比较，光看高矮会把几十个 BP 的差读成好几倍。
 */
.win-bars { display: flex; align-items: stretch; gap: var(--space-2); height: 190px; }
.win-bar {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; justify-content: flex-end; align-items: stretch;
}
.win-bar b {
  text-align: center; font-size: 10.5px; font-weight: var(--fw-bold);
  color: var(--text-subtle); font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; margin-bottom: 3px;
}
.win-bar.is-best b { color: var(--brand-strong); }
.win-bar i { display: block; background: var(--ink-200); border-radius: 3px 3px 0 0; }
.win-bar.is-best i { background: var(--brand); }
.win-bar span {
  margin-top: var(--space-2); text-align: center; font-size: 11px;
  color: var(--text-subtle); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.win-bar.is-best span { color: var(--brand-strong); font-weight: var(--fw-bold); }
/* 窄屏下柱宽摆不下 6 位数值：收起柱顶标注（悬浮提示仍在），日期标注缩号 */
@media (max-width: 720px) {
  .win-bar b { display: none; }
  .win-bar span { font-size: 9.5px; }
}

.advice-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
.advice { display: flex; gap: var(--space-4); padding: var(--space-5); }
.advice__no { font-size: 20px; font-weight: var(--fw-black); color: var(--brand); line-height: 1.1; }
.advice__title { font-size: 14px; font-weight: var(--fw-bold); color: var(--text-strong); }
.advice__desc { margin-top: var(--space-2); font-size: 12.5px; line-height: var(--lh-snug); color: var(--text-muted); }

@media (max-width: 1180px) {
  .split-2, .timing-cols, .advice-grid { grid-template-columns: 1fr; }
  .verdict { grid-template-columns: 1fr; }
  .stat-row { grid-template-columns: 1fr 1fr; }
}

/*
 * 手机宽度下换算器改上下排：金额是 22px 的数字，横排时两个框各只剩约 100px，
 * 六位数金额会被 ellipsis 截掉。翻转按钮跟着转成整行。
 * （这里不解决窄屏顶栏溢出——用户邮箱把 topbar 撑宽是全站既有问题，本期页面按 PC 设计。）
 */
@media (max-width: 520px) {
  .convert { flex-direction: column; }
  .convert__swap { width: 100%; height: 32px; }
}

/* --------------------------- 顶栏当前用户与退出 --------------------------- */

.user-chip {
  display: flex; align-items: center; gap: var(--space-3);
  font-size: var(--ui-sm); color: var(--text-muted);
}
/* 账号名：通往账号设置（改密 / 注销）的入口 */
.user-chip__name {
  max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: var(--fw-bold); color: var(--text-strong);
  text-decoration: none;
}
.user-chip__name:hover { color: var(--brand-strong); text-decoration: underline; text-underline-offset: 3px; }
.user-chip__name:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: var(--radius-xs); }
.user-chip__out {
  background: none; border: none; padding: 0;
  font-family: inherit; font-size: 12px; color: var(--text-subtle); cursor: pointer;
}
.user-chip__out:hover { color: var(--brand-strong); }

/* mock 账号体系的提示条：不能让人以为接口已经受保护 */
.mock-note {
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
  border: var(--bw-hairline) solid var(--border-hairline);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-5);
  font-size: 12.5px; line-height: var(--lh-snug); color: var(--text-muted);
}

/* ------------------------------ 走势图 hover ----------------------------- */

.chart-wrap { position: relative; }

/*
 * 竖线 / 焦点 / 气泡都是绝对定位的 DOM，不画进 SVG：
 * SVG 用 preserveAspectRatio="none" 拉伸（viewBox 640 → 显示约 534px），
 * 画在里面的圆会被横向压成椭圆、文字也会变形。
 */
.chart-guide,
.chart-dot,
.chart-tip {
  position: absolute;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-standard);
}
.chart-guide.is-open,
.chart-dot.is-open,
.chart-tip.is-open { opacity: 1; }

.chart-guide {
  width: 0;
  border-left: var(--bw-hairline) dashed var(--border-strong);
  transform: translateX(-0.5px);
}

.chart-dot {
  width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px;
  border-radius: var(--radius-pill);
  background: var(--brand);
  box-shadow: 0 0 0 3px var(--surface-card), var(--shadow-sm);
}

.chart-tip {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--surface-dark);
  box-shadow: var(--shadow-md);
  white-space: nowrap;
  z-index: 5;
}
.chart-tip__time {
  display: flex; align-items: baseline; gap: var(--space-2);
  font-size: 11px; color: var(--text-on-dark-mut); font-variant-numeric: tabular-nums;
}
/* 休市沿用标记：比日期再淡一档，别抢走真实报价的注意力 */
.chart-tip__note { font-size: 10.5px; font-style: normal; opacity: 0.75; }
/* 一行：标签写明是哪个价，数值右对齐。走势只画一个口径，不再列对照价。 */
.chart-tip__row { display: flex; align-items: center; gap: var(--space-2); }
.chart-tip__label { flex: 1; font-size: 11.5px; color: var(--text-on-dark-mut); }
.chart-tip__rate {
  font-size: 15px; font-weight: var(--fw-black);
  color: var(--text-on-dark); font-variant-numeric: tabular-nums;
}

/* 图区域给出"可探查"的手感 */
.chart-wrap { cursor: crosshair; }

/* ------------------------------- 交易日历 -------------------------------- */

/*
 * 「工作日」与「有牌价」是两件事，视觉上也分成两层：
 * 底色说的是这天银行办不办结汇（推算），角标圆点说的是这天中行发没发牌价（事实）。
 * 合成一个标记就等于用推算去覆盖事实——中行周末也挂牌，而调休的工作日银行不营业。
 */
.calendar { padding: var(--space-4); }

.calendar__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); margin-bottom: var(--space-2);
}
.calendar__title { font-size: 15.5px; font-weight: var(--fw-black); color: var(--text-strong); }
.calendar__nav { display: flex; gap: var(--space-1); }
.calendar__nav-btn {
  width: 24px; height: 24px; padding: 0;
  display: grid; place-items: center;
  background: none; border: var(--bw-hairline) solid var(--border-hairline);
  border-radius: var(--radius-sm);
  font-family: inherit; font-size: 12px; color: var(--text-muted); cursor: pointer;
  transition: color var(--dur-fast) var(--ease-standard),
              border-color var(--dur-fast) var(--ease-standard);
}
.calendar__nav-btn:hover { color: var(--brand-strong); border-color: var(--border-brand); }

/* 格间留 4px：底色块彼此贴着时，一整周会糊成一条绿带，数不清是哪天 */
.calendar__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }

.calendar__dow {
  text-align: center; padding: var(--space-2) 0 var(--space-1);
  font-size: var(--ui-xs); font-weight: var(--fw-bold); color: var(--text-subtle);
}

.calendar__cell {
  aspect-ratio: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  border-radius: var(--radius-md);
  font-size: 13.5px; font-variant-numeric: tabular-nums;
  color: var(--text-subtle);
}
/*
 * 圆点位永远占位（没牌价时透明）。用绝对定位挂在格子底部的话，
 * 有点的格子数字被挤上去、没点的居中，同一行的数字就对不齐了。
 */
.calendar__cell::after {
  content: "";
  width: 4px; height: 4px; border-radius: var(--radius-pill);
  background: transparent;
}
/* 邻月补位：留着日期读得出周次，但压到最淡，免得被当成本月 */
.calendar__cell--other { opacity: 0.32; }
/* 工作日 = 预计可结汇：底色 + 加粗，一眼能数出这个月还剩几天 */
.calendar__cell--workday {
  background: var(--brand-soft);
  color: var(--text-strong);
  font-weight: var(--fw-bold);
}
.calendar__cell--today {
  background: var(--brand);
  color: var(--text-on-brand);
  font-weight: var(--fw-black);
  box-shadow: var(--shadow-sm);
}
/* 有牌价：数字下面一个点。今天那格底色是品牌绿，点要反白才看得见 */
.calendar__cell--quoted::after { background: var(--brand-strong); }
.calendar__cell--today.calendar__cell--quoted::after { background: var(--brand-on); }

/*
 * 图例与口径说明做成<b>通栏页脚</b>：负边距抵掉卡片内边距，分隔线一直拉到卡片两边。
 * 图例也从竖排改成横向流式——竖排时每行右边空着一大半，
 * 三行加一段说明把卡片底部撑掉一大块，横排后高度直接减半。
 */
.calendar__foot {
  margin: var(--space-4) calc(-1 * var(--space-4)) calc(-1 * var(--space-4));
  padding: var(--space-2) var(--space-4) var(--space-3);
  border-top: var(--bw-hairline) solid var(--border-hairline);
  background: var(--surface-sunken);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

/*
 * 三项等分成一行，不用 flex-wrap——wrap 在宽度差一点时会折成两行，
 * 页脚高度随之跳变，而这一行本来就只有三个短标签。
 */
.calendar__legend {
  display: grid; grid-template-columns: repeat(3, auto);
  justify-content: space-between; gap: var(--space-2);
  /* 比 --ui-xs 再小半档：三项要在 266px 宽里排成一行，12px 会把「天」挤到第二行 */
  font-size: 11.5px; color: var(--text-muted);
}
.calendar__legend-item { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.calendar__swatch {
  width: 11px; height: 11px; border-radius: var(--radius-sm); flex: none;
  background: var(--brand-soft);
}
.calendar__swatch--today { background: var(--brand); }
.calendar__swatch--quoted {
  background: var(--surface-card); position: relative;
  border: var(--bw-hairline) solid var(--border-hairline);
}
.calendar__swatch--quoted::after {
  content: "";
  position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%);
  width: 4px; height: 4px; border-radius: var(--radius-pill); background: var(--brand-strong);
}
/* 口径说明：法定节假日尚未接入，这句话不能省，否则日历会被当成准确的营业日历 */
.calendar__caveat {
  margin: 6px 0 0;
  font-size: 11.5px; line-height: 1.5; color: var(--text-subtle);
}
/* 加载失败时没有页脚壳，说明文字自己要留出边距 */
.calendar > .calendar__caveat { margin: 0; }
