/* =========================================================================
   SIGNAL — Components.  Depends on tokens.css.
   ========================================================================= */

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

/* A class that sets `display` outranks the hidden attribute's UA rule, which
   would silently render every "hidden" state at once. Restore the contract. */
[hidden] { display: none !important; }

body {
  margin: 0; background: var(--bg); color: var(--text);
  font-family: var(--font-body); font-size: var(--fs-base); line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}
h1,h2,h3,h4 { margin: 0; font-family: var(--font-display); font-weight: 400; }
p { margin: 0; }
a { color: inherit; }
img { max-width: 100%; }

/* ------------------------------------------------------------------- LAYOUT */
.wrap { max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: var(--section-py); }
.section--alt  { background: var(--bg-alt); }
.section--dark { background: var(--dark-bg); color: var(--dark-text); }
.section--dark h1, .section--dark h2, .section--dark h3 { color: var(--dark-text); }
.section--dark .lede, .section--dark .body { color: var(--dark-muted); }

/* Stripe's vertical container rules: hairlines marking the content column,
   running down the page. Drawn as borders on each section's container rather
   than one fixed overlay — an overlay sits behind the opaque section
   backgrounds and never shows. */
.section > .wrap, .ctaband__in, .footer > .wrap {
  border-inline: 1px solid var(--line);
}
.section--dark > .wrap, .footer > .wrap { border-color: var(--dark-line); }
.ctaband__in { border-color: rgba(18,16,28,.18); }
@media (max-width: 1280px) {
  .section > .wrap, .ctaband__in, .footer > .wrap { border-inline: 0; }
}

.grid { display: grid; gap: var(--s5); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
.split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s8); align-items: center; }

/* --------------------------------------------------------------- TYPOGRAPHY */
.eyebrow {
  display: inline-flex; align-items: center; gap: var(--s2);
  font-size: var(--fs-xs); font-weight: var(--fw-semi);
  letter-spacing: var(--ls-eyebrow); text-transform: uppercase; color: var(--accent);
}
.section--dark .eyebrow { color: var(--pop); }

.display  { font-size: var(--fs-hero); line-height: var(--lh-hero);    letter-spacing: var(--ls-hero); }
.title    { font-size: var(--fs-2xl);  line-height: var(--lh-display); letter-spacing: var(--ls-display); }
.subtitle { font-size: var(--fs-xl);   line-height: var(--lh-head);    letter-spacing: var(--ls-head); }

/* Stripe's two-tone headline: statement clause in full contrast, continuation
   clause dropped back. Carries the hierarchy without a size change. */
.two-tone > .cont { color: var(--text-muted); }
.section--dark .two-tone > .cont { color: var(--dark-muted); }
.hero .two-tone > .cont { color: var(--hero-head-2); }

.lede { font-size: var(--fs-md); color: var(--text-muted); max-width: 58ch; }
.body { font-size: var(--fs-base); color: var(--text-muted); }
.measure { max-width: 62ch; }
.num { font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ BUTTONS */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 46px; padding: 12px 24px;
  border: 0; border-radius: var(--r-pill);
  background: var(--accent); color: var(--on-accent);
  font-family: var(--font-body); font-size: var(--fs-sm); font-weight: var(--fw-semi);
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
}
.btn:hover  { background: var(--violet-700); }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.btn--pop { background: var(--pop); color: var(--ink); }
.btn--pop:hover { background: var(--pop-deep); }
.btn--outline { background: transparent; color: var(--text); box-shadow: inset 0 0 0 var(--bw) var(--line-strong); }
.btn--outline:hover { background: var(--ink); color: var(--white); }
.btn--white { background: var(--white); color: var(--ink); box-shadow: inset 0 0 0 var(--bw) var(--ink); }
.btn--white:hover { background: var(--ink-050); }
.btn--ghost { background: transparent; color: currentColor; box-shadow: inset 0 0 0 1px currentColor; }
.btn--lg { min-height: 54px; padding: 15px 32px; font-size: var(--fs-md); }
/* Visually 38px to keep dense rows dense, but the hit area is extended to the
   44px minimum with a transparent overlay rather than by growing the button. */
.btn--sm { min-height: 38px; padding: 8px 16px; font-size: var(--fs-xs); position: relative; }
.btn--sm::after { content: ""; position: absolute; inset: -3px 0; }
.btn[disabled] { opacity: .45; pointer-events: none; }

.link-arrow {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--accent); font-weight: var(--fw-semi); font-size: var(--fs-sm); text-decoration: none;
}
.link-arrow::after { content: "→"; transition: transform var(--dur) var(--ease); }
.link-arrow:hover::after { transform: translateX(3px); }
.section--dark .link-arrow { color: var(--pop); }

/* --------------------------------------------------------------------- NAV */
.nav {
  position: sticky; top: 0; z-index: var(--z-sticky);
  background: var(--hero-bg); color: var(--hero-text);
  border-bottom: 1px solid var(--hero-line);
}
.nav__in { display: flex; align-items: center; gap: var(--s6); padding-block: var(--s4); }
.logo {
  display: inline-flex; align-items: center; gap: var(--s2);
  font-family: var(--font-display); font-size: var(--fs-lg); color: inherit; text-decoration: none;
  letter-spacing: -0.02em;
}
/* Lockup follows the parent brand's pattern: a mark carrying the distinctive
   letters, with the wordmark completing the name — DK + PAY, as D7 + Pay. */
/* 真实 logo SVG。高度锁死、宽度按比例,避免各页尺寸漂移。 */
.logo__img { display: block; height: 30px; width: auto; }
.side .logo__img { height: 27px; }
.footer .logo__img { height: 30px; }

/* 旧的 DK 方块标记 —— 已被 logo.svg 取代,保留规则仅为兼容尚未迁移的引用 */
.logo__mark {
  display: grid; place-items: center;
  min-width: 34px; height: 30px; padding-inline: 6px;
  background: var(--pop); color: var(--ink); border-radius: var(--r-sm);
  font-size: 14px; letter-spacing: -0.02em;
}
.nav__links { display: flex; align-items: stretch; gap: var(--s5); margin-inline: auto; }
/* 导航里有两种元素:普通链接 <a> 与带菜单的 <button class="nav__trigger">。
   两者必须用**同一套**垂直定位,否则文字基线会差几个像素 —— 之前 <a> 靠
   padding-block 撑高、trigger 靠 flex 居中,实测错位 5px。统一为 flex 居中。 */
.nav__links > a,
.nav__trigger {
  display: inline-flex; align-items: center;
  min-height: 44px; padding-block: 0;
  font-size: var(--fs-sm); line-height: 1;
}
.nav__links > a {
  color: rgba(255,255,255,.82); text-decoration: none;
}
.nav__links a:hover, .nav__links a[aria-current] { color: #fff; box-shadow: 0 -3px 0 inset var(--pop); }
/* ---------------------------------------------------------------- MEGA MENU */
/* Panel carries the system's hard outline + offset block. A blurred dropdown
   shadow is the conventional choice here and is deliberately not used. */
.nav__item { position: relative; display: flex; }
/* 尺寸与垂直定位由上面 `.nav__links > a, .nav__trigger` 的共用规则统一给出,
   这里只补 trigger 独有的外观。不要在此重设 padding-block / min-height,
   否则会把两类元素的对齐重新拆开。 */
.nav__trigger {
  gap: 6px;
  background: none; border: 0; cursor: pointer;
  font-family: var(--font-body);
  color: rgba(255,255,255,.82);
}
.nav__trigger:hover, .nav__trigger[aria-expanded="true"] { color: #fff; }
.nav__trigger:focus-visible { outline: 2px solid var(--pop); outline-offset: 3px; }
.nav__trigger .ico { width: 14px; height: 14px; stroke-width: 2.5;
                     transition: transform var(--dur) var(--ease); }
.nav__trigger[aria-expanded="true"] .ico { transform: rotate(180deg); }
.nav--light .nav__trigger { color: var(--text-muted); }
.nav--light .nav__trigger:hover,
.nav--light .nav__trigger[aria-expanded="true"] { color: var(--text); }
.nav--light .nav__trigger:focus-visible { outline-color: var(--accent); }

/* 面板与触发器之间那 14px 空隙,鼠标必须穿过它才能够到子项 —— 一穿过就触发
   .nav__item 的 pointerleave,菜单在指针到达之前就关了。用一条透明的桥把空隙
   纳入面板自身的悬停区域(纯视觉不可见,不影响布局)。
   仅有 JS 侧的关闭延迟不够:延迟能救"快速划过",救不了"停在空隙里"。 */
.menu::before {
  content: ""; position: absolute; left: 0; right: 0;
  top: -14px; height: 14px;
}
.menu {
  position: absolute; top: calc(100% + 14px); left: 0;
  z-index: var(--z-menu);
  width: var(--menu-w); max-width: calc(100vw - 2 * var(--gutter));
  padding: var(--s5);
  background: var(--white); color: var(--text);
  border: var(--outline); border-radius: var(--r-sm);
  box-shadow: var(--block);
  display: none;
}
/* Without JS, hover and focus-within open the panel so it still works.
   With JS (html.js), those CSS rules are switched off and nav.js becomes the
   single source of truth — otherwise :focus-within re-opens the panel the
   instant Escape returns focus to the trigger. */
html:not(.js) .nav__item:hover > .menu,
html:not(.js) .nav__item:focus-within > .menu,
.menu[data-open="true"] { display: block; }
.menu__grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s5); }
.menu__col h4 {
  font-family: var(--font-body); font-size: var(--fs-2xs); font-weight: var(--fw-bold);
  letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted);
  margin-bottom: var(--s3);
}
.menu__link {
  display: flex; gap: var(--s3); align-items: flex-start;
  padding: var(--s3); margin-inline: calc(-1 * var(--s3));
  border-radius: var(--r-sm); text-decoration: none; color: var(--text);
}
.menu__link:hover { background: var(--violet-050); }
.menu__link:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.menu__link .ico { color: var(--accent); margin-top: 2px; }
.menu__link b { display: block; font-size: var(--fs-sm); font-weight: var(--fw-semi); }
.menu__link span { display: block; font-size: var(--fs-xs); color: var(--text-muted); }

/* Below 900px there is no room for a panel — fall back to the plain
   scrollable nav that already exists. */
@media (max-width: 900px) {
  .menu { display: none !important; }
  .nav__trigger .ico { display: none; }
}

.nav--light { background: var(--white); color: var(--text); border-bottom: 1px solid var(--line); }
.nav--light .nav__links a { color: var(--text-muted); }
.nav--light .nav__links a:hover, .nav--light .nav__links a[aria-current] { color: var(--text); }

/* -------------------------------------------------------------------- HERO */
.hero { position: relative; background: var(--hero-bg); color: var(--hero-text); overflow: hidden; }
/* 主视觉已经是本系统配色的平涂图(Pictor 生成、紫底墨黑白块+酸黄点缀),
   所以不再需要当初为 aurora.svg 调的双色调 filter 与 overlay 混合 ——
   那套处理会把这张图整个洗掉。原样呈现即可。 */
.hero__art {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: right center;
}
/* 遮罩只压左侧承载文案的区域;右侧图形保持原样。
   左 52% 本就是干净紫底(选片时量过),所以这里是轻遮罩而非重压。 */
.hero::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, var(--violet) 0%, rgba(75,42,239,.92) 34%, rgba(75,42,239,.24) 62%, rgba(75,42,239,0) 82%);
}
/* 视频态下这层遮罩要退场。
   它原本的用途是压暗左侧、保证直接压在插画上的文字够对比度;文字改坐在实色底衬上之后
   这个用途就没有了,而它左侧是 100% 实色紫,等于把视频左半边整个糊掉 ——
   底衬又恰好是同一个紫,于是紫压紫,底衬立不起来。
   现在只保留一层很轻的品牌色统一,让视频在底衬四周真正露出来。 */
.hero--video::after {
  /* 强遮罩带覆盖到 66%：用 Range 量的**文字本身**边界，中文标题最远到 64.1%
     （英文 61.1%，lede 52.5%）。此前按 46% 设计，量的还是盒子不是文字 ——
     范围量错，等于没量。CTA 按钮有自己的实色底，不依赖这层遮罩。
     文案区内最弱 72% 墨黑；按四段片源各 24 帧的最坏像素(叠加后 sRGB≈0.347)算：
     主句 7.06 / 续句 3.35 / lede 4.76 / 酸黄 6.32，全部达标。
     改这里的任何数值或换片源，都必须重跑 scratchpad/measure.sh。 */
  background: linear-gradient(90deg,
    rgba(18,16,28,.90) 0%,
    rgba(18,16,28,.84) 35%,
    rgba(18,16,28,.72) 66%,
    rgba(18,16,28,.40) 82%,
    rgba(75,42,239,.16) 100%);
}
/* 文案必须留在强遮罩带内 —— 越界的部分对比度就没被验证过 */
.hero--video .display { max-width: 13ch; }
html[data-lang="zh"] .hero--video .display { max-width: 9em; }
.hero--video .lede { max-width: 44ch; }
/* ---- 全幅视频 hero ----
   文案直接压在会动的画面上，所以"某张图的哪块像素"这个前提没了：
   逐帧量过四段片源，**每一段在文案区都存在接近纯白的高光像素**（四段实测最坏值
   完全一致，就是白），也就是遮罩必须独力扛下全部对比度，不能指望画面本身够暗。
   下面这层遮罩在文案区（左 0~46%）最弱处仍有 70% 墨黑，按最坏帧算：
   主句 7.06 / 续句 3.35 / lede 4.76 / 酸黄 6.32 —— 全部达标。
   改这层的任何一个数值，都必须重跑 scratchpad 的 measure.sh 重新验证。 */
.hero__reel { position: absolute; inset: 0; overflow: hidden; }
.hero__reel video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  opacity: 0; transition: opacity 900ms var(--ease, ease);
}
/* 只有第一路真的播起来（play() resolved）才盖住海报，否则海报一直留在原处 */
.hero__reel.is-live video.is-on { opacity: 1; }


.hero__in { position: relative; z-index: var(--z-base); padding-block: clamp(56px, 8vw, 112px); }
.hero .display { color: var(--hero-text); max-width: 15ch; margin-block: var(--s5) var(--s6); }
.hero .lede { color: var(--hero-body); }
.hero__cta { display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s7); }
.hero__ticker { font-size: var(--fs-sm); color: var(--hero-body); }
.hero__ticker strong { color: var(--pop); font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------- LOGO STRIP */
/* Stripe puts customer logos here. We have no customer logos — the coverage
   cards are the stronger local equivalent, so the strip shows markets. */
.strip { background: var(--white); border-block: var(--bw) solid var(--ink); overflow: hidden; }
.strip__rail {
  display: flex; gap: 0; overflow-x: auto; scrollbar-width: none;
}
.strip__rail::-webkit-scrollbar { display: none; }
.strip__item {
  flex: 0 0 auto; width: 200px; height: 130px;
  border-right: 1px solid var(--line);
  display: grid; place-items: center; padding: var(--s3);
}
.strip__item img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }

/* -------------------------------------------------------------------- CARD */
.card {
  background: var(--surface); border: var(--outline); border-radius: var(--r-sm);
  padding: var(--s6);
}
.card--block { box-shadow: var(--block-sm); }
.card--soft  { border: var(--outline-soft); }
.card__icon {
  display: grid; place-items: center; width: 44px; height: 44px; margin-bottom: var(--s5);
  border: var(--outline); border-radius: var(--r-sm); background: var(--surface-2);
}
/* Inline SVG icon set. Simple geometry only (lines, arcs, rects, circles),
   stroked with currentColor so an icon takes the colour of whatever context it
   lands in. Replaces the borrowed raster art that was re-tinted by CSS filter. */
.ico {
  width: 24px; height: 24px; display: block; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.ico--sm { width: 18px; height: 18px; stroke-width: 2.2; }
.ico--lg { width: 30px; height: 30px; stroke-width: 1.8; }
.card__icon { color: var(--accent); }
.card h3 { font-size: var(--fs-md); margin-bottom: var(--s3); letter-spacing: -0.01em; }
.card p  { font-size: var(--fs-sm); color: var(--text-muted); }
.section--dark .card { background: var(--dark-surface); border-color: var(--dark-line); color: var(--dark-text); }
.section--dark .card p { color: var(--dark-muted); }

/* ------------------------------------------------------------------- STATS */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0;
         border: var(--bw) solid currentColor; }
.stat { padding: var(--s6); border-right: 1px solid currentColor; }
.stat:last-child { border-right: 0; }
.stat__value {
  display: block; font-family: var(--font-display); font-size: var(--fs-2xl);
  line-height: 1; letter-spacing: var(--ls-display); font-variant-numeric: tabular-nums;
}
.stat__label { display: block; margin-top: var(--s3); font-size: var(--fs-sm); opacity: .72; }
.stat--pop .stat__value { color: var(--pop); }

/* -------------------------------------------------------------- CODE BLOCK */
.code {
  border: var(--bw) solid var(--ink); border-radius: var(--r-sm);
  background: var(--ink); color: #E8E4F6; overflow: hidden;
  box-shadow: var(--block);
}
.section--dark .code { box-shadow: var(--block-accent); border-color: var(--dark-line); }
.code__tabs { display: flex; gap: 0; border-bottom: 1px solid var(--dark-line); }
.code__tab {
  /* 视觉高度保持紧凑,但命中区补到 44px —— 与 .btn--sm 同一手法 */
  position: relative;
  padding: 10px 16px; background: transparent; border: 0; border-right: 1px solid var(--dark-line);
  color: var(--dark-muted); font-family: var(--font-mono); font-size: var(--fs-xs); cursor: pointer;
}
.code__tab::after { content: ""; position: absolute; inset: -4px 0; }
.code__tab[aria-selected="true"] { background: var(--violet); color: #fff; }
.code__body {
  margin: 0; padding: var(--s5); overflow-x: auto;
  font-family: var(--font-mono); font-size: var(--fs-xs); line-height: 1.75;
  letter-spacing: var(--ls-mono); tab-size: 2;
}
.code__body .k { color: #C4B5FD; }   /* keyword  */
.code__body .s { color: var(--pop); } /* string   */
.code__body .c { color: #8B84A8; }   /* comment — raised from #6F6790, which
                                        measured 3.6:1 on the code surface and
                                        failed AA at 12px; this is 5.34:1 */
.code__body .n { color: #7DD3A8; }   /* number   */

/* -------------------------------------------------------------------- TABLE */
.tablewrap { border: var(--bw) solid var(--ink); border-radius: var(--r-sm); overflow: auto; background: var(--surface); }
table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
thead th {
  position: sticky; top: 0; padding: 12px var(--s4); text-align: left; white-space: nowrap;
  background: var(--ink); color: var(--white);
  font-size: var(--fs-2xs); font-weight: var(--fw-semi);
  letter-spacing: .08em; text-transform: uppercase;
}
tbody td { padding: 14px var(--s4); border-bottom: 1px solid var(--line); white-space: nowrap; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: var(--violet-050); }

/* Rows open a detail drawer, so they must read as targets and be reachable by
   keyboard. The hover tint above existed before the rows did anything — a
   hover response with no click response is worse than no affordance at all. */
tbody[data-body="populated"] tr { cursor: pointer; }
tbody[data-body="populated"] tr:focus-visible {
  outline: var(--focus-w) solid var(--focus); outline-offset: -2px;
}

/* 锚点跳转:目标不能顶到视口最上沿,否则被吸顶导航盖住半截。
   给所有可跳转目标留出导航高度 + 一点呼吸。 */
:target, [id] { scroll-margin-top: 92px; }

.drawer {
  border-top: 1px solid var(--line);
  padding: var(--s5) var(--s4);
  background: var(--violet-050);
}
.drawer__head { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s4); }
.drawer__head strong { font-family: var(--font-mono); font-size: var(--fs-sm); }
.drawer__close {
  margin-left: auto; min-width: 44px; min-height: 44px;
  border: 0; background: none; cursor: pointer; font-size: var(--fs-sm); color: var(--text-muted);
}
.drawer__close:hover { color: var(--ink); }
.drawer__list {
  display: grid; grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--s2) var(--s5); margin: 0; font-size: var(--fs-sm);
}
.drawer__list dt { color: var(--text-muted); }
.drawer__list dd { margin: 0; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }

.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: var(--r-pill);
  font-size: var(--fs-2xs); font-weight: var(--fw-semi);
}
.badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.badge--ok   { background: var(--ok-bg);   color: var(--ok); }
.badge--warn { background: var(--warn-bg); color: var(--warn); }
.badge--fail { background: var(--fail-bg); color: var(--fail); }

/* ------------------------------------------------------------------ PRICING */
.tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s5); align-items: start; }
.tier { background: var(--surface); border: var(--outline); border-radius: var(--r-sm); padding: var(--s6); }
.tier--featured { box-shadow: var(--block-accent); }
.tier__name { font-family: var(--font-display); font-size: var(--fs-lg); letter-spacing: -0.02em; }
.tier__price { display: flex; align-items: baseline; gap: 6px; margin-block: var(--s4) var(--s2); }
.tier__amount { font-family: var(--font-display); font-size: var(--fs-2xl); line-height: 1;
                letter-spacing: var(--ls-display); font-variant-numeric: tabular-nums; }
.tier__unit { font-size: var(--fs-sm); color: var(--text-muted); }
.tier__note { font-size: var(--fs-xs); color: var(--text-muted); }
.tier ul { list-style: none; margin: var(--s5) 0 var(--s6); padding: 0; display: grid; gap: var(--s3); }
.tier li { display: flex; gap: var(--s3); font-size: var(--fs-sm); }
.tier li::before { content: "✓"; color: var(--accent); font-weight: 700; flex: 0 0 auto; }
.tier li.off { color: var(--text-muted); }
.tier li.off::before { content: "—"; color: var(--text-muted); }
.tier__flag {
  display: inline-block; margin-bottom: var(--s3); padding: 3px 10px;
  background: var(--pop); color: var(--ink); border-radius: var(--r-pill);
  font-size: var(--fs-2xs); font-weight: var(--fw-bold); letter-spacing: .06em; text-transform: uppercase;
}

/* ----------------------------------------------------------------- SHOWCASE */
.showcase { position: relative; }
.showcase img { border: var(--bw) solid var(--ink); border-radius: var(--r-sm); display: block; }
.showcase__back  { width: 68%; box-shadow: var(--block-lg); }
.showcase__front { position: absolute; right: 0; top: 18%; width: 38%; box-shadow: var(--block-accent); }

/* -------------------------------------------------------------------- QUOTE */
.quote { border-left: var(--bw) solid var(--accent); padding-left: var(--s6); }
.quote p { font-family: var(--font-display); font-size: var(--fs-xl); line-height: var(--lh-head);
           letter-spacing: var(--ls-head); }
.quote footer { margin-top: var(--s5); font-size: var(--fs-sm); color: var(--text-muted); }

/* ----------------------------------------------------------------- CTA BAND */
.ctaband { background: var(--pop); color: var(--ink); border-block: var(--bw) solid var(--ink); }
.ctaband__in { display: flex; flex-wrap: wrap; gap: var(--s5); align-items: center;
               justify-content: space-between; padding-block: var(--s8); }
.ctaband h2 { font-size: var(--fs-2xl); line-height: var(--lh-display); letter-spacing: var(--ls-display);
              max-width: 18ch; }

/* ------------------------------------------------------------------- FOOTER */
.footer { background: var(--ink); color: var(--dark-muted); padding-block: var(--s9) var(--s7); }
.footer__cols { display: grid; grid-template-columns: 1.4fr repeat(4, 1fr); gap: var(--s6); }
.footer h4 { font-family: var(--font-body); font-size: var(--fs-xs); font-weight: var(--fw-bold);
             letter-spacing: .1em; text-transform: uppercase; color: var(--white); margin-bottom: var(--s4); }
.footer a { display: block; margin-bottom: var(--s3); font-size: var(--fs-sm); color: var(--dark-muted);
            text-decoration: none; }
.footer a:hover { color: var(--white); }
.footer__brand .logo { color: var(--white); margin-bottom: var(--s4); }
.footer__bottom { display: flex; flex-wrap: wrap; gap: var(--s4); justify-content: space-between;
                  margin-top: var(--s8); padding-top: var(--s5); border-top: 1px solid var(--dark-line);
                  font-size: var(--fs-xs); }

/* ================================================================ APP SHELL */
.app { display: grid; grid-template-columns: 228px 1fr; min-height: 640px;
       border: var(--bw) solid var(--ink); border-radius: var(--r-sm); overflow: hidden; background: var(--white); }
.side { background: var(--ink); padding: var(--s5) 0; }
.side .logo { color: var(--white); padding-inline: var(--s5); margin-bottom: var(--s6); font-size: var(--fs-md); }
.side__group { padding-inline: var(--s5); margin-bottom: var(--s2);
               font-size: var(--fs-2xs); letter-spacing: .1em; text-transform: uppercase; color: #9A92B8; }
.side__link { display: flex; align-items: center; gap: var(--s3); margin: 2px var(--s3);
              padding: 9px var(--s4); border-radius: var(--r-sm);
              font-size: var(--fs-sm); color: #A79FC4; text-decoration: none; cursor: pointer; }
.side__link:hover { background: rgba(255,255,255,.07); color: #fff; }
.side__link[aria-current] { background: var(--violet); color: #fff; font-weight: var(--fw-semi); }
.topbar { display: flex; align-items: center; gap: var(--s4); padding: var(--s4) var(--s5);
          border-bottom: 1px solid var(--line); }
.topbar h3 { font-size: var(--fs-md); letter-spacing: -0.01em; }
.panel { padding: var(--s5); display: grid; gap: var(--s5); }
.kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s4); }
.kpi { padding: var(--s5); border: var(--outline); border-radius: var(--r-sm); }
.kpi__label { font-size: var(--fs-xs); color: var(--text-muted); }
.kpi__value { display: block; margin-top: 6px; white-space: nowrap;
              font-family: var(--font-display); font-size: var(--fs-xl); line-height: 1;
              letter-spacing: var(--ls-display); font-variant-numeric: tabular-nums; }
.kpi__delta { font-size: var(--fs-xs); color: var(--ok); }
.kpi__delta--down { color: var(--fail); }

.field { width: 100%; min-height: 44px; padding: 10px var(--s4);
         border: 1px solid var(--line); border-radius: var(--r-sm);
         background: var(--white); color: var(--text);
         font-family: var(--font-body); font-size: var(--fs-sm); }
.field::placeholder { color: var(--text-muted); }
.field:focus { outline: none; border-color: var(--accent); box-shadow: var(--focus-ring); }
.filters { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; }
.filters .field { width: auto; min-width: 150px; }
.avatar { width: 34px; height: 34px; border-radius: var(--r-pill); background: var(--violet-100);
          color: var(--violet); display: grid; place-items: center;
          font-size: var(--fs-xs); font-weight: var(--fw-bold); }

/* ================================================================== CASHIER */
.phone { width: 380px; max-width: 100%; background: var(--white);
         border: var(--bw) solid var(--ink); border-radius: var(--r-md);
         box-shadow: var(--block); overflow: hidden; }
.phone__bar { display: flex; justify-content: space-between; padding: var(--s4) var(--s5);
              background: var(--ink); color: var(--dark-muted); font-size: var(--fs-xs); }
.phone__body { padding: var(--s5); display: grid; gap: var(--s4); }
.amount { text-align: center; padding-block: var(--s4); border-bottom: 1px solid var(--line); }
.amount__label { font-size: var(--fs-xs); color: var(--text-muted); }
.amount__value { display: block; margin-top: 6px; font-family: var(--font-display);
                 font-size: 42px; line-height: 1; letter-spacing: var(--ls-display);
                 font-variant-numeric: tabular-nums; }
.methods { display: grid; gap: var(--s2); }
.method { display: flex; align-items: center; gap: var(--s3); padding: 12px var(--s4);
          border: 1px solid var(--line); border-radius: var(--r-sm); cursor: pointer; font-size: var(--fs-sm); }
.method:hover { border-color: var(--accent); }
.method[aria-checked="true"] { border: var(--bw) solid var(--ink); background: var(--violet-050);
                               box-shadow: var(--block-sm); }
.method img { width: 46px; height: 26px; object-fit: contain; flex: 0 0 auto; }
.method__meta { margin-left: auto; font-size: var(--fs-xs); color: var(--text-muted); }
.timer { text-align: center; font-size: var(--fs-xs); color: var(--text-muted); }
.timer strong { font-variant-numeric: tabular-nums; color: var(--warn); }
.success { text-align: center; padding: var(--s8) var(--s5); }
.success__mark { width: 64px; height: 64px; margin: 0 auto var(--s5); border-radius: var(--r-pill);
                 display: grid; place-items: center; background: var(--ok-bg); color: var(--ok); font-size: 28px; }

/* ================================================================== I18N */
/* 中文态下换字体栈:Archivo 没有中文字形,不换的话中文会掉到浏览器默认字体,
   和 Archivo Black 的重量感对不上。 */
html[data-lang="zh"] body { font-family: var(--font-zh-body); }
html[data-lang="zh"] h1, html[data-lang="zh"] h2,
html[data-lang="zh"] h3, html[data-lang="zh"] h4,
html[data-lang="zh"] .display, html[data-lang="zh"] .title,
html[data-lang="zh"] .logo, html[data-lang="zh"] .stat__value,
html[data-lang="zh"] .kpi__value, html[data-lang="zh"] .amount__value,
html[data-lang="zh"] .tier__amount, html[data-lang="zh"] .market__name {
  font-family: var(--font-zh-display);
}
/* 中文没有词间空格,极紧的字距会糊成一片 —— 放松到接近 0 */
html[data-lang="zh"] .display { letter-spacing: -0.01em; line-height: 1.15; }
html[data-lang="zh"] .title   { letter-spacing: -0.01em; line-height: 1.25; }
/* `ch` 单位以「0」的宽度为准,对中文严重低估(一个汉字≈2ch),
   英文按 15ch 限宽的标题换成中文会被切字;但放开限宽又会横穿到主视觉上、
   在任意位置硬折行。中文标题改为:限宽用 em、且两个分句各自成行不拆断。 */
/* 静态 hero 下中文标题需要自己限宽（否则会横穿插画）；视频 hero 下由底衬限宽，
   两者不能叠加，否则中文被挤成「在八个市/场收款」这种词中断行。 */
html[data-lang="zh"] .hero:not(.hero--video) .display { max-width: 14em; }
html[data-lang="zh"] .two-tone > .cont,
html[data-lang="zh"] .two-tone > [data-i18n] { display: block; }
html[data-lang="zh"] .title,
html[data-lang="zh"] .section-head h2 { max-width: 20em; }
html[data-lang="zh"] .lede, html[data-lang="zh"] .body { max-width: 36em; }
/* 中文正文行高略放大更好读 */
html[data-lang="zh"] .lede, html[data-lang="zh"] .body { line-height: 1.75; }

/* 语言切换控件。默认 hidden,由 i18n.js 揭示 —— 无 JS 时不给点不动的按钮。 */
.lang {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 52px; min-height: 44px; padding: 8px 12px;
  background: transparent; border: 0; cursor: pointer;
  border-radius: var(--r-sm);
  font-family: var(--font-body); font-size: var(--fs-xs); font-weight: var(--fw-semi);
  letter-spacing: .04em; color: rgba(255,255,255,.82);
}
.lang:hover { color: #fff; background: rgba(255,255,255,.10); }
.lang:focus-visible { outline: 2px solid var(--pop); outline-offset: 2px; }
.nav--light .lang { color: var(--text-muted); }
.nav--light .lang:hover { color: var(--text); background: var(--ink-050); }
.nav--light .lang:focus-visible { outline-color: var(--accent); }

/* ============================================================ MARKET CARD */
/* 国家覆盖卡片。改成 HTML 而不是整图,是因为:①国家名要跟站点语言切换;
   ②新增市场/渠道只改 markets.js;③圆角与描边跟随系统而不是各图各样。 */
.markets { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s5); }
@media (max-width: 1000px) { .markets { grid-template-columns: 1fr 1fr; } }
@media (max-width: 640px)  { .markets { grid-template-columns: 1fr; } }

.market {
  display: flex; flex-direction: column;
  background: var(--surface);
  border: var(--outline);           /* 统一 1.5px 墨黑 */
  border-radius: var(--r-sm);       /* 统一 4px —— 各卡片不再各行其是 */
  box-shadow: var(--block-sm);
  overflow: hidden;
}
.market__head {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--line);
}
.market__flag { font-size: 22px; line-height: 1; }
.market__name { font-family: var(--font-display); font-size: var(--fs-md);
                letter-spacing: -0.01em; }
.market__meta { margin-left: auto; display: flex; align-items: center; gap: var(--s2); }
.market__settle {
  font-family: var(--font-mono); font-size: var(--fs-2xs);
  color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.market__grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2);
  padding: var(--s4) var(--s5) var(--s5);
}
.market__chip {
  display: grid; place-items: center;
  min-height: 46px; padding: 6px;
  background: var(--surface-2); border-radius: var(--r-xs);
}
.market__chip img { max-width: 100%; max-height: 34px; object-fit: contain; display: block; }
/* 没有真实标识的渠道:显示名字,不画近似 logo */
.market__chip--text {
  font-size: var(--fs-2xs); font-weight: var(--fw-semi);
  color: var(--text-muted); text-align: center; line-height: 1.2;
}

/* ==================================================================== DOCS */
.docs {
  display: grid;
  grid-template-columns: var(--docs-nav-w) minmax(0, 1fr) var(--docs-toc-w);
  gap: var(--s8);
  align-items: start;
  padding-block: var(--s7) var(--s10);
}
/* Both side columns scroll independently of the content column. */
.docs__side, .docs__toc {
  position: sticky; top: calc(var(--nav-h) + var(--s5));
  max-height: calc(100dvh - var(--nav-h) - var(--s8));
  overflow-y: auto; overscroll-behavior: contain;
  font-size: var(--fs-sm);
}
.docs__side h4, .docs__toc h4 {
  font-family: var(--font-body); font-size: var(--fs-2xs); font-weight: var(--fw-bold);
  letter-spacing: .1em; text-transform: uppercase; color: var(--text-muted);
  margin-bottom: var(--s3);
}
.docs__side a, .docs__toc a {
  display: block; padding: 6px 10px; margin-inline: -10px;
  border-radius: var(--r-sm); color: var(--text-muted); text-decoration: none;
}
.docs__side a:hover, .docs__toc a:hover { background: var(--surface-2); color: var(--text); }
.docs__side a[aria-current] {
  background: var(--ink); color: var(--white); font-weight: var(--fw-semi);
}
.docs__side + .docs__side, .docs__group + .docs__group { margin-top: var(--s5); }
.docs__toc a { border-left: 2px solid var(--line); border-radius: 0; margin-inline: 0; }
.docs__toc a[aria-current] { border-left-color: var(--accent); color: var(--text); font-weight: var(--fw-semi); }

.docs__body > * + * { margin-top: var(--s5); }
.docs__body h1 { font-size: var(--fs-2xl); line-height: var(--lh-display);
                 letter-spacing: var(--ls-display); }
.docs__body h2 { font-size: var(--fs-lg); letter-spacing: var(--ls-head); margin-top: var(--s8); }
.docs__body h3 { font-size: var(--fs-md); letter-spacing: -0.01em; margin-top: var(--s6); }
.docs__body p  { color: var(--text-muted); max-width: 68ch; }
.docs__body code:not(pre code) {
  font-family: var(--font-mono); font-size: .9em;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-xs); padding: 1px 5px;
}
/* Required parameters are marked by a word and a border, not only a colour. */
.req {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px; border: 1px solid var(--fail); border-radius: var(--r-pill);
  font-size: var(--fs-2xs); font-weight: var(--fw-semi); color: var(--fail);
  text-transform: uppercase; letter-spacing: .06em;
}
.opt {
  display: inline-flex; padding: 1px 7px;
  border: 1px dashed var(--line-strong); border-radius: var(--r-pill);
  font-size: var(--fs-2xs); color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .06em;
}

@media (max-width: 1080px) {
  /* `1fr` 在 grid 里的隐含 min-width 是 auto,子项不肯收缩到内容宽度以下,
     窄屏时会把整列撑到内容宽(实测 650px)并造成页面级横向滚动。
     必须写成 minmax(0, 1fr) 并给子项 min-width: 0。 */
  .docs { grid-template-columns: minmax(0, 1fr); gap: var(--s6); }
  .docs__side, .docs__body, .docs__toc { min-width: 0; }
  .docs__side, .docs__toc { position: static; max-height: none; overflow: visible; }
  .docs__toc { display: none; }   /* on-page contents is redundant in one column */
  .docs__side { border-bottom: 1px solid var(--line); padding-bottom: var(--s5); }
}

/* ============================================================ DATA STATES */
/* One primitive for every non-happy data state. Rendered inside .tablewrap
   beneath the real thead so the table chrome never unmounts and the page
   does not reflow when the state changes. */
.state {
  display: grid; justify-items: center; text-align: center;
  gap: var(--s3); padding: var(--s9) var(--s5);
}
.state__icon {
  display: grid; place-items: center; width: 52px; height: 52px;
  border: var(--outline); border-radius: var(--r-sm);
  background: var(--surface-2); color: var(--text-muted);
}
.state--error .state__icon { color: var(--fail); border-color: var(--fail); background: var(--fail-bg); }
.state--filtered .state__icon { color: var(--warn); border-color: var(--warn); background: var(--warn-bg); }
.state__title { font-family: var(--font-display); font-size: var(--fs-lg);
                letter-spacing: var(--ls-head); }
.state__body { font-size: var(--fs-sm); color: var(--text-muted); max-width: 46ch; }
.state__actions { display: flex; gap: var(--s3); flex-wrap: wrap; justify-content: center;
                  margin-top: var(--s3); }
/* --text-faint is decorative-only (2.93:1). These carry the reason code an
   operator has to read, so they take the muted role instead. */
.state__detail { font-family: var(--font-mono); font-size: var(--fs-2xs);
                 color: var(--text-muted); margin-top: var(--s2); }

/* Skeleton rows. Flat fills — a blurred pulse would contradict the system's
   elevation language. Heights match real row metrics so nothing shifts. */
/* Height is 1.6em — the same line box a real table cell's text occupies
   (--fs-sm x --lh-body) — so a loading table is exactly as tall as the
   populated one and switching between them cannot shift the page. */
.skeleton { display: block; height: 1.6em; border-radius: var(--r-xs);
            background: var(--skeleton); }
.skeleton--wide { width: 100%; }
.skeleton--60 { width: 60%; }
.skeleton--40 { width: 40%; }
/* The status column's real content is a .badge, which is taller than a text
   line box and therefore sets the row height. Its skeleton has to reproduce
   the badge's box, not the text one, or loading rows come up short. */
.skeleton--badge {
  width: 76px; border-radius: var(--r-pill);
  height: calc(var(--fs-2xs) * var(--lh-body) + 8px);
}
@media (prefers-reduced-motion: no-preference) {
  .skeleton {
    background: linear-gradient(90deg, var(--skeleton) 0%, var(--skeleton-hi) 50%, var(--skeleton) 100%);
    background-size: 200% 100%;
    animation: skeleton-sweep 1.4s ease-in-out infinite;
  }
  @keyframes skeleton-sweep { from { background-position: 200% 0; } to { background-position: -200% 0; } }
}

/* KPI with no value yet — visibly not a zero. */
.kpi__value--none { color: var(--text-muted); font-family: var(--font-body);
                    font-size: var(--fs-lg); letter-spacing: 0; }

/* ================================================================ NOTICE */
.notice {
  display: flex; gap: var(--s3); align-items: flex-start;
  padding: var(--s4); border: var(--outline); border-radius: var(--r-sm);
  font-size: var(--fs-sm); text-align: left;
}
.notice .ico { margin-top: 1px; }
.notice__title { display: block; font-weight: var(--fw-semi); margin-bottom: 2px; }
.notice__body  { display: block; color: var(--text-muted); font-size: var(--fs-xs); }
.notice--warn { background: var(--warn-bg); border-color: var(--warn); color: var(--warn); }
.notice--fail { background: var(--fail-bg); border-color: var(--fail); color: var(--fail); }
.notice--info { background: var(--violet-100); border-color: var(--accent); color: var(--violet-700); }
.notice--warn .notice__body, .notice--fail .notice__body, .notice--info .notice__body { color: inherit; opacity: .85; }

/* ========================================================== FIELD STATES */
/* Invalid is marked by outline weight and a glyph as well as colour, so the
   state survives for anyone who cannot separate red from grey. */
.field--invalid { border: var(--bw) solid var(--field-invalid); padding-right: 38px;
                  background-image: none; }
.field-wrap { position: relative; display: block; }
.field-wrap__flag { position: absolute; right: 12px; top: 50%; translate: 0 -50%;
                    color: var(--field-invalid); pointer-events: none; }
.field-error { display: flex; align-items: flex-start; gap: 6px; margin-top: 6px;
               font-size: var(--fs-xs); color: var(--fail); }
.field-hint  { display: block; margin-top: 6px; font-size: var(--fs-xs); color: var(--text-muted); }
.field--disabled, .field:disabled {
  background: var(--ink-050); color: var(--text-faint);
  border-style: dashed; cursor: not-allowed;
}
/* Read-only is filled and solid-bordered — it holds a real value, unlike
   disabled which holds none. */
.field[readonly] { background: var(--readonly-bg); border-style: solid; color: var(--text); }

/* =============================================== CASHIER STATE ADDITIONS */
.method--disabled {
  opacity: .6; cursor: not-allowed; border-style: dashed;
}
.method--disabled:hover { border-color: var(--line); }
.method__reason { margin-left: auto; font-size: var(--fs-2xs); color: var(--warn);
                  text-align: right; max-width: 12ch; }
.amount-diff {
  display: grid; gap: 6px; padding: var(--s4);
  border: var(--outline); border-radius: var(--r-sm); background: var(--warn-bg);
  font-size: var(--fs-sm);
}
.amount-diff div { display: flex; justify-content: space-between; gap: var(--s4); }
.amount-diff .n { font-variant-numeric: tabular-nums; }
.amount-diff .short { font-weight: var(--fw-bold); color: var(--warn);
                      border-top: 1px solid var(--warn); padding-top: 6px; }

/* State switcher — prototype affordance so every state is reviewable. */
.switch { display: flex; flex-wrap: wrap; gap: var(--s2); margin-bottom: var(--s5); }
.switch button {
  min-height: 44px; padding: 8px 14px;
  border: 1px solid var(--line); border-radius: var(--r-pill);
  background: var(--white); color: var(--text-muted);
  font-family: var(--font-body); font-size: var(--fs-xs); cursor: pointer;
}
.switch button:hover { border-color: var(--line-strong); color: var(--text); }
.switch button[aria-pressed="true"] {
  background: var(--ink); border-color: var(--ink); color: var(--white);
  font-weight: var(--fw-semi);
}
.switch button:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ============================================================== RESPONSIVE */
@media (max-width: 1000px) {
  .grid--3, .grid--4, .tiers, .stats, .kpis, .footer__cols { grid-template-columns: 1fr 1fr; }
  .split { grid-template-columns: 1fr; gap: var(--s6); }
  .stat { border-right: 0; border-bottom: 1px solid currentColor; }
  .app { grid-template-columns: 1fr; }
  .side { display: none; }
  .showcase__front { position: static; width: 100%; margin-top: var(--s5); }
  .showcase__back { width: 100%; }
}
@media (max-width: 640px) {
  .grid--3, .grid--4, .tiers, .stats, .kpis, .footer__cols { grid-template-columns: 1fr; }
  .nav__in { flex-wrap: wrap; gap: var(--s3); }
  .nav__links { order: 3; flex-basis: 100%; overflow-x: auto; margin-inline: 0; }
  .nav__links a { white-space: nowrap; }
  .hero .display { max-width: none; }
}

/* ------------------------------------------------- 常驻 TELEGRAM 联系入口 */
/* 对齐 d7pay 的右下角悬浮块；这是本站唯一的转化路径，所以常驻。
   外观走 Signal 的硬块语言（实色 + 硬描边 + 硬偏移阴影），不用圆浮标 + 模糊阴影。 */
.tg-affix {
  position: fixed; right: 20px; bottom: 20px; z-index: var(--z-sticky);
  display: inline-flex; align-items: center; gap: var(--s2);
  min-height: 48px; padding: 12px 20px;
  background: var(--pop); color: var(--ink);
  border: var(--outline); border-radius: var(--r-pill);
  box-shadow: var(--block-sm);
  font-size: var(--fs-sm); font-weight: var(--fw-semi); text-decoration: none;
  transition: transform var(--dur) var(--ease);
}
.tg-affix:hover { transform: translate(-1px, -1px); }
.tg-affix:active { transform: translate(1px, 1px); box-shadow: none; }
.tg-affix:focus-visible { outline: none; box-shadow: var(--focus-ring), var(--block-sm); }
.tg-affix .ico { width: 20px; height: 20px; }

/* 窄屏收成图标，避免压住底部 CTA */
@media (max-width: 560px) {
  .tg-affix { right: 14px; bottom: 14px; padding: 12px; }
  .tg-affix span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
}
/* 悬浮块常驻在右下角，页脚最后一行要留出它的高度，否则会被盖住 */
.footer { padding-bottom: 96px; }
