/* ═══ 闸门簇：登录 · 两步验证 · 同意页 · 改密 · 首次接入 · 隐私说明 / 使用须知 ═══
   这几屏不套应用外壳，整屏自己承担滚动。
   色值一律取令牌；带 GAP 的行是令牌里没有、被迫写死的几何量，与 base.css 记的是同一批缺口。 */

/* ── 滚动归属 ──
   body 是 overflow:hidden，#app 没有高度，所以闸门屏必须自己是那个滚动容器。
   少这一条，同意页和使用须知超出一屏的部分就永远滚不到——用户读不完，
   而「读完才能勾」正是这一屏存在的理由。 */
.gate {
  height: 100vh; height: 100dvh; overflow-y: auto;
  /* 内容比一屏高时 align-items:center 会把顶部裁掉，改成 flex-start + margin:auto：
     有余量时仍然居中，没余量时从顶部开始，两种情况都读得完。 */
  align-items: flex-start;
}
.gate > .box { margin: auto; }

/* ═══ 一、登录（两栏）═══════════════════════════════════════════════ */
.gate.gate-split {
  display: grid; grid-template-columns: 1fr 440px;         /* GAP form-col-440 */
  align-items: stretch; padding: 0; background: var(--c-neutral-25);
}

.hero {
  position: relative; overflow: hidden;
  padding: var(--space-7) 56px 44px;                        /* GAP hero-pad-56/44 */
  display: flex; flex-direction: column;
}
.hero > *:not(.backdrop) { position: relative; z-index: 1; }

.wordrow { display: flex; align-items: center; gap: var(--space-3); margin-bottom: 44px; }  /* GAP wordrow-mb-44 */
.wordrow svg { color: var(--c-neutral-900); }
.wordname { font-size: var(--size-xl); font-weight: 600; letter-spacing: -.02em; }

.herotitle {
  font-size: var(--size-3xl); font-weight: 600; letter-spacing: -.025em;
  line-height: var(--leading-tight); margin: 0 0 var(--space-3); color: var(--c-neutral-900);
}
.herosub { font-size: var(--size-md); color: var(--c-neutral-600); margin: 0 0 var(--space-4); }
.sampletag { margin-bottom: var(--space-3); }

.samplecards { display: flex; flex-direction: column; gap: var(--space-3); max-width: 38em; }
/* 示例卡不可点、没有 hover、没有时间戳 —— 它一旦看起来像活的，
   登录页就成了公网上的「谁在被监控」清单。 */
.card.static { cursor: default; }
.card.static:hover { background: var(--c-neutral-0); border-color: var(--c-neutral-100); }
.card.static.now:hover { border-left-color: var(--c-severity-high); }

.herostats {
  display: flex; gap: 38px; margin-top: 26px; padding-top: 26px;   /* GAP herostat-gap-38 */
  border-top: 1px solid var(--border-hairline);
}
.hstat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.hstat .hv {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--size-lg); font-weight: 600; color: var(--c-neutral-900);
}
.hstat .ht { font-size: var(--size-sm); color: var(--c-neutral-500); }

/* 底图：六格店铺网格。纯 opacity 交叉淡入，不位移、不缩放、不发光。
   这是对「system_initiated ≤200ms」的一处已报备偏离：底图不承担信息，
   目标恰恰是不被注意到，所以 1500ms。 */
.backdrop { position: absolute; inset: 0; z-index: 0; opacity: .34; pointer-events: none; }
.bcell {
  position: absolute; width: 24%; height: 7%;
  border: 1px solid var(--c-neutral-200); border-radius: var(--radius-10);
  background: none; opacity: .4;
  transition: opacity var(--motion-duration-backdrop-fade) var(--motion-easing-loop);
}

.formcol {
  display: flex; flex-direction: column; justify-content: center;
  padding: var(--space-7); gap: var(--space-4);
  background: var(--c-neutral-0); border-left: 1px solid var(--border-hairline);
}
.formslot { flex: 0 0 auto; }

.gform { display: flex; flex-direction: column; gap: var(--space-3); }
.gform .field + .field { margin-top: 0; }
.gtitle {
  font-size: var(--size-3xl); font-weight: 600; letter-spacing: -.025em;
  line-height: var(--leading-tight); margin: 0;
}
.gform .gtitle { font-size: var(--size-2xl); margin-bottom: var(--space-1); }
.gtitle:focus-visible { outline-offset: 3px; }

/* 登录会记录时间 / IP / 设备 —— 这一行必须在表单上方，登录本身就是一次处理。 */
.notice-line {
  font-size: var(--size-sm); color: var(--c-neutral-500); margin: 0 0 var(--space-1);
  line-height: var(--leading-snug);
}
.gform .hint { margin: 0; color: var(--c-neutral-500); line-height: var(--leading-snug); }
.gform .hint.under { margin-top: var(--space-1); }
.btn.wide { width: 100%; }
a.btn { text-decoration: none; }

.pwwrap { position: relative; display: block; }
.pwwrap .input { padding-right: 52px; }                     /* GAP pw-input-pr-52 */
.btn.reveal {
  position: absolute; right: 2px; top: 50%; transform: translateY(-50%);
  min-width: var(--a11y-floor-target-used); height: 28px;   /* GAP reveal-h-28（命中框由 min-width 与 .pwwrap 行高共同保证 ≥32） */
  padding: 0 var(--space-2); font-size: var(--size-sm);
}
.input.code {
  font-family: var(--font-mono); letter-spacing: .38em; font-size: var(--size-lg);
  text-align: center;
}

/* 表单错误：边框色 + 图标 + 框下一行说明，三样都要（WCAG 1.4.1）。 */
.formerr:empty { display: none; }
.formerr {
  display: flex; align-items: flex-start; gap: var(--space-2);
  font-size: var(--size-base); line-height: var(--leading-snug);
  color: var(--c-severity-high);
}
.formerr > svg { flex-shrink: 0; margin-top: 2px; }
.formerr .btn { margin-top: var(--space-1); }

.gfoot {
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  margin-top: auto; padding-top: var(--space-4); font-size: var(--size-sm);
  color: var(--c-neutral-500);
}
/* 页脚只有产品名与两个法定文档：无人名、无公司名、无邮箱。 */
.brand { font-weight: 600; color: var(--c-neutral-900); letter-spacing: -.02em; }

/* 窄屏：Hero 逐级减到只剩字标行，一个字段都不删表单。 */
@media (max-width: 900px) {
  .gate.gate-split { grid-template-columns: minmax(0, 1fr); }
  .hero { padding: var(--space-5) var(--space-4); }
  .hero .herosub, .hero .herostats, .hero .c2, .hero .c3 { display: none; }
  .formcol { border-left: 0; border-top: 1px solid var(--border-hairline);
             padding: var(--space-5) var(--space-4); }
  .formcol .gform, .formcol .gfoot { max-width: 440px; margin-left: auto; margin-right: auto; width: 100%; }  /* GAP form-col-440 */
}
@media (max-width: 768px) {
  .hero .herotitle, .hero .sampletag, .hero .samplecards, .hero .backdrop { display: none; }
  .wordrow { margin-bottom: 0; }
}

/* ═══ 二、长文页（同意 / 隐私说明 / 使用须知 / 首次接入）═══════════ */
.gate.gate-doc { display: block; padding: 0; background: var(--c-neutral-25); }
.doc {
  max-width: 78ch; margin: 0 auto; padding: var(--space-6) var(--space-6) var(--space-8);
  color: var(--c-neutral-900);
}
.doc.wide { max-width: 880px; }                              /* GAP firstrun-col-880 */
.doc p { font-size: var(--size-md); line-height: var(--leading-loose); color: var(--c-neutral-600); }
.doc .lead { font-size: var(--size-md); color: var(--c-neutral-900); }

.dochead {
  display: flex; align-items: center; gap: var(--space-3);
  padding-bottom: var(--space-5); font-size: var(--size-sm); color: var(--c-neutral-500);
}
.dochead .brand { margin-left: auto; }
.docver { font-size: var(--size-sm); color: var(--c-neutral-500); margin: var(--space-2) 0 var(--space-5); }
.docsec { margin-bottom: var(--space-6); }
.docsec > h2 { font-size: var(--size-lg); margin-bottom: var(--space-2); }
.doclist { margin: 0 0 var(--space-3); padding-left: 1.2em; font-size: var(--size-md);
           line-height: var(--leading-loose); color: var(--c-neutral-600); }
.doclist li { margin-bottom: var(--space-1); }
.docfoot { border-top: 1px solid var(--c-neutral-100); padding-top: var(--space-4);
           font-size: var(--size-sm); color: var(--c-neutral-500); }
/* 法务页的表格是散文表，不是数字表：720px 的通用下限会让它在桌面上也横向滚动。
   下调到 460px —— 窄屏仍然在 .tablewrap 里横向滚动、不挤压列（组件层第 ② 条），
   桌面上正好放得下。 */
table.t.doctable { min-width: 460px; }                       /* GAP doctable-minw-460 */

/* 六项告知：全部展开，不折叠、不 accordion、不「查看更多」。
   折叠 = 用户没看到 = 告知没发生。 */
.six { margin-bottom: var(--space-4); }
.sixt { font-size: var(--size-md); font-weight: 500; margin: 0 0 var(--space-1);
        color: var(--c-neutral-900); }
.sixb { margin: 0; }
/* 撤回同意的后果：跟在六项之后，不编号、不当第七项，所以视觉上要和它们分开一档。 */
.sixnote { margin: var(--space-4) 0 0; padding-top: var(--space-3);
           border-top: 1px solid var(--border-hairline); color: var(--c-neutral-600); }
.doclinks { display: flex; gap: var(--space-4); flex-wrap: wrap; margin: var(--space-5) 0 0; }

/* ── 同意页的 sticky 底条 ──
   两个勾和「继续」必须一直看得见，否则用户会以为读完才出现。 */
.gate-consent .doc { padding-bottom: 180px; }                /* GAP consent-pb-180 */
.consentbar {
  position: sticky; bottom: 0; z-index: 20;
  background: var(--c-neutral-0); border-top: 1px solid var(--c-neutral-100);
  padding: var(--space-4) var(--space-6);
  display: flex; flex-direction: column; gap: var(--space-3);
}
.consentbar .cks { display: flex; flex-direction: column; gap: var(--space-2);
                   max-width: 78ch; margin: 0 auto; width: 100%; }
.consentbar .formerr { max-width: 78ch; margin: 0 auto; width: 100%; }
.consentacts { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
               max-width: 78ch; margin: 0 auto; width: 100%; }
.consentacts .hint { margin: 0; color: var(--c-neutral-500); }
.cklabel { font-size: var(--size-base); line-height: var(--leading-snug); }
.consentrow.err .cklabel { color: var(--c-severity-high); }
.consentrow.err .ck { border-color: var(--c-severity-high); }
/* disabled 的按钮 pointer-events:none，说明为什么不能点只能挂在外层。 */
.tipwrap { display: inline-flex; }

/* ═══ 三、改密（首登全屏态）══════════════════════════════════════════ */
.gate-pw .box { gap: var(--space-3); }
.gate-pw .gform { gap: var(--space-3); }
.pwpage { max-width: 560px; }                                /* GAP pwpage-560 */
.pwpage .box {
  margin-top: var(--space-3); background: var(--c-neutral-0);
  border: 1px solid var(--c-neutral-100); border-radius: var(--radius-lg);
  padding: var(--space-6);
}
/* 只给长度，不给复杂度评分条：评分条会诱导用户去凑「一个大写一个符号」，
   那种密码更短、更容易猜。 */
.gform .hint.mono { font-variant-numeric: tabular-nums; }
.gform .hint.mono.ok { color: var(--c-neutral-900); }

/* ═══ 四、首次接入 ═══════════════════════════════════════════════════ */
.gate-fr .doc { padding-bottom: 120px; }                     /* GAP firstrun-pb-120 */
.stepline { font-size: var(--size-11); color: var(--c-neutral-500); margin: 0 0 var(--space-2);
            letter-spacing: .04em; }
.leadlines { margin: var(--space-3) 0 var(--space-5); }
.leadlines p { margin: 0 0 var(--space-2); }

.shoplist {
  max-height: 60vh; overflow-y: auto;
  border: 1px solid var(--c-neutral-100); border-radius: var(--radius-10);
  background: var(--c-neutral-0);
}
.shopgroup + .shopgroup { border-top: 1px solid var(--c-neutral-100); }
.grouphead {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3); background: var(--c-neutral-25);
  position: sticky; top: 0; z-index: 2;
}
.grouphead .gname { font-size: var(--size-base); font-weight: 500; }
.ck .dash { display: block; width: 8px; height: 2px; background: currentColor; border-radius: 1px; }

/* 窄屏纵向堆叠、一个字段都不删（plan「移动端是核心场景，不是适配」）：
   行高改成 min-height，归属 / 档位 / 在售 / 首次发现换行排到店名下面。
   写死 36px 时实测在 375px 下 meta 涨到 47–77px，直接压到下一行上——
   而被压掉的正是「未抓到 / 未标注」那几格。 */
.shoprow {
  display: flex; align-items: flex-start; gap: var(--space-2);
  min-height: var(--control-h-lg); padding: var(--space-1) var(--space-3); margin: 0 6px;  /* GAP row-inset-6 */
  border-radius: var(--radius-md); cursor: pointer; min-width: 0;
}
.shoprow:hover { background: var(--c-neutral-50); }
/* 复选框占位一直预留、一直可见：选中态是默认态，选完就消失会让人以为点错了。 */
.shoprow .ck-hit { opacity: 1; }
.shoprow[aria-checked="true"] .ck {
  background: var(--c-neutral-900); border-color: var(--c-neutral-900); color: var(--c-neutral-0);
}
.shoprow .ck svg { width: 12px; height: 12px; }
.shopmain { display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
            min-width: 0; flex: 1; }
.shopname { font-size: var(--size-md); font-weight: 500; }
.shopmeta { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
            font-size: var(--size-sm); color: var(--c-neutral-600); }
@media (min-width: 761px) {
  .shoprow { align-items: center; }
  .shopmain { flex-direction: row; align-items: baseline; gap: var(--space-3); }
  .shopname { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .shopmeta { margin-left: auto; }
}
.shopmeta .sepdot { color: var(--c-neutral-200); }
/* 「状态未知」是异常二档：有形无色。不用斜纹（那是「未抓到」），
   也不用虚线框（那是「未标注 / 时候未到」）——两种质地都有专属含义，借哪个都会冲淡它。 */
.unknownnote { display: inline-flex; align-items: center; gap: var(--space-1);
               color: var(--c-neutral-600); }

/* 二档 · 局部不全 · **有形无色**：3px 灰左条，就地插在受影响的那一行上方。
   这一档刻意不给颜色——红是一档「屏上的数不能信」专用的。 */
.rowwrap.degraded { border-left: 3px solid var(--c-neutral-200); margin: var(--space-1) 6px; }  /* GAP row-inset-6 */
.rowwrap.degraded .shoprow { margin: 0; }
.degnote {
  display: flex; align-items: center; gap: var(--space-1);
  font-size: var(--size-sm); color: var(--c-neutral-600); margin: 0; padding: 2px var(--space-3);
}

.frbar {
  position: sticky; bottom: 0; z-index: 10;
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  margin-top: var(--space-4); padding: var(--space-3) 0;
  background: var(--c-neutral-25); border-top: 1px solid var(--c-neutral-100);
}
.frbarleft { display: flex; align-items: center; gap: var(--space-3); font-size: var(--size-base);
             color: var(--c-neutral-600); }
.frbarright { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }
.frbar .formerr { flex-basis: 100%; }
.pickcount { font-family: var(--font-mono); font-variant-numeric: tabular-nums;
             color: var(--c-neutral-900); }

.shopcards { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
             gap: var(--space-3); margin: var(--space-4) 0; }
.shopcard { border: 1px solid var(--c-neutral-100); border-radius: var(--radius-10);
            padding: var(--space-3); background: var(--c-neutral-0); }
.scname { font-size: var(--size-md); font-weight: 500; margin-bottom: var(--space-1);
          overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.scrow { font-size: var(--size-sm); color: var(--c-neutral-600); line-height: var(--leading-snug); }

.frstats { display: flex; gap: var(--space-4); flex-wrap: wrap; margin: var(--space-4) 0; }
.frstat { border: 1px solid var(--c-neutral-100); border-radius: var(--radius-10);
          padding: var(--space-3) var(--space-4); background: var(--c-neutral-0); min-width: 180px; }
.frstat .l { font-size: var(--size-11); color: var(--c-neutral-500); }
.frstat .v { font-size: var(--size-2xl); font-weight: 600; line-height: var(--leading-tight);
             margin: 4px 0; }
.frstat .note { font-size: var(--size-sm); color: var(--c-neutral-600); line-height: var(--leading-snug); }

.frcols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
          gap: var(--space-4); align-items: start; }
.frcols.one { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 760px) { .frcols { grid-template-columns: minmax(0, 1fr); } }
.frblock { border: 1px solid var(--c-neutral-100); border-radius: var(--radius-10);
           padding: var(--space-4); background: var(--c-neutral-0); }
.frblock > h3 { margin-bottom: var(--space-2); }
.frblock .hint { font-size: var(--size-sm); color: var(--c-neutral-600);
                 line-height: var(--leading-snug); margin: var(--space-2) 0 0; }
.frblock .feed { margin-top: var(--space-3); }
.frblock .empty { padding: var(--space-6) var(--space-3); }

/* ── 减少动效：底图静止常亮，不是消失 ── */
@media (prefers-reduced-motion: reduce) {
  .bcell { opacity: .5 !important; transition: none; }
}

/* 法务三页的草稿条。二档异常那一套：就地插、有形无色 —— 不用红。
   它说的不是「出事了」，是「这份文本还没定」，而红是「多急」那一套的最高档。 */
.gate .docdraft { border: 1px solid var(--border-control); border-radius: var(--radius-md);
                  padding: var(--space-3); margin-bottom: var(--space-3);
                  font-size: var(--size-base); line-height: var(--leading-snug);
                  color: var(--c-neutral-900); background: var(--c-neutral-25); }
