/* basing 公开站：版面 + 族。
   颜色、字体、字号、字重、圆角、描边、阴影一律读 basing_tokens.css 的变量；本文件出现的
   字面值只有版面尺寸（宽、高、间距）与动效时长。换风格改 themes/，不改这里。

   族（登记表在 scripts/site_family_audit.js 的 FAMILIES，与 app 同名同角色）：
     .pseg.brand  字标 Basing                         ┐
     .pbtn        键：申请邀请                         │ 规则都在 basing_family.css：与 app 共用的同一份
     .dtab        文字动作：顶栏、页脚、语言切换、已有邀请码 │（从 app 抄过来，2026-09-25）；这里只管它们
     .ln          单行输入：邮箱                       │ 在这一页的位置
     .gbtn        图标键：动效旁的两个十字              ┘
     .peek        十字点开的示意卡
     .lstack      层叠动效（static/lstack.js 画）
   版面区域：.page .bar .bl .br .stage .low .ident .act .subrow .foot .soon */

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--surface);
  color: var(--ink);
  font-family: var(--ff-ui);
  font-size: var(--fs-body);
  line-height: var(--lh-ui);
  -webkit-font-smoothing: antialiased;
}

/* 双语：两份内容都在 DOM 里，由 html[lang] 决定谁出场。 */
html[lang="zh"] .en, html[lang="en"] .zh { display: none; }

/* ══ 版面 ══════════════════════════════════════════════════════════════ */

.page {
  min-height: 100vh; min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);   /* 不让最宽的内容把整列撑出视口 */
  grid-template-rows: auto 1fr auto auto;
  grid-template-areas: "bar" "stage" "low" "foot";
  padding: 0 32px;
}

/* 顶栏：与 app 同高；字标在左上角，其后是关于；右边是登录与语言 */
.bar {
  grid-area: bar;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 16px;
  min-height: var(--bar-h);
}
.bar .bl { display: flex; align-items: center; gap: 24px; min-height: var(--bar-h); }
/* 最窄的屏上一行放不下时，登录与语言换到第二行，仍靠右 */
.bar .br { display: flex; align-items: center; gap: 20px; margin-left: auto; }
.bar .pseg.brand { margin-right: 8px; }

.stage {
  grid-area: stage;
  display: grid; place-items: center;
  padding: 8px 0;
}

.low {
  grid-area: low;
  display: flex; align-items: flex-end; justify-content: space-between; gap: 32px;
  padding: 8px 0 32px;
}
.ident { max-width: 480px; }
.ident .hero {
  margin: 0;
  font: var(--fw-strong) calc(var(--fs-hero) * var(--hero-scale, 1))/1.3 var(--ff-ui);
  color: var(--ink);
}
/* 一句占一行：site.js 量过最长那一句、放不下时写一个缩小的比例（--hero-scale）以后才挂 .fit（脚本没跑就照常折行） */
.ident .hero.fit { white-space: nowrap; }
.ident .desc {
  margin: 12px 0 0; max-width: 26em;
  font-size: var(--fs-note); line-height: var(--lh-ui); color: var(--ink3);
}

/* 申请邀请靠右，与页面右缘对齐 */
.act { position: relative; display: flex; flex-direction: column; align-items: flex-end; gap: 12px; }
.subrow { display: flex; gap: 12px; }
/* 没做成的一行（没填／不像邮箱／没交上）；做成了弹致谢窗（auth.js 开 app 的 /requested）。
   浮在输入这一排的上面：这一块贴着页面底部往上长，排进去会把输入框顶上去一行 */
.suberr {
  position: absolute; right: 0; bottom: calc(100% + 4px);
  margin: 0; font-size: var(--fs-note); line-height: 1.4; color: var(--bad); white-space: nowrap;
}
/* 蜜罐：移出视口，人碰不到，自动提交的会填。 */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

.foot {
  grid-area: foot;
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px 24px;
  padding: 16px 0 24px;
  border-top: var(--edge-w) solid var(--hair);
}
.foot .copy { font-size: var(--fs-note); color: var(--ink5); }

.soon { text-align: center; }
.soon .soont { margin: 0; font: var(--fw-strong) var(--fs-read)/1.3 var(--ff-ui); color: var(--ink); }
.soon .soons { margin: 10px 0 0; font-size: var(--fs-note); color: var(--ink4); }

/* ══ 族 ════════════════════════════════════════════════════════════════ */

/* 字标（.pseg.brand）与键（.pbtn）的规则在 basing_family.css，与 app 共用；这里只管它们在这一页的位置 */
.pseg.brand { padding: 8px 0; }

/* 文字动作在这一页的一行多高、点击区多大（公开站的字小，一行 1.2，上下各 6px 凑够 24px 的点击区） */
.page .dtab { padding: 6px 0; min-width: 24px; line-height: 1.2; }

/* 层叠动效。形状由 lstack.js 算，颜色与线宽全在这里读 token；
   --spread（0 静止，1 展开）由 lstack.js 写在容器上。 */
.lstack {
  position: relative;
  height: clamp(320px, calc(100svh - 300px), 660px); aspect-ratio: 640 / 700; max-width: 100%;
  touch-action: pan-y pinch-zoom; --spread: 0;          /* 上下划照旧滚页面；左右拖交给 lstack.js 转块 */
}
/* 一层一张 SVG，叠在一起；只有上层四块 report 接鼠标 */
.lstack .ls-sv { position: absolute; inset: 0; display: block; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
/* 磨砂纸：每块板一张，剪成板的轮廓（lstack.js 每帧写 clip-path），透出后面、并把后面糊开 */
.lstack .frost {
  position: absolute; inset: 0; pointer-events: none;
  background: var(--frost-face);
  -webkit-backdrop-filter: var(--frost-blur); backdrop-filter: var(--frost-blur);
}
.lstack .frost.a1 { background: var(--frost-a1); }
.lstack .frost.a2 { background: var(--frost-a2); }
.lstack .frost.a3 { background: var(--frost-a3); }
/* 板面的颜色由磨砂纸给；SVG 只画线、侧壁的一层暗 */
.lstack .fc { fill: var(--stack-face-tint); }
.lstack .wl { fill: var(--stack-wall); }
.lstack mask { mask-type: alpha; }                  /* 网格渐隐只看透明度，不看颜色 */
.lstack .fc, .lstack .eg, .lstack .nd, .lstack .gl, .lstack .cn, .lstack .tick, .lstack .rowln {
  stroke: var(--stack-line); stroke-width: var(--stack-stroke);
  stroke-linejoin: round; stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.lstack .eg, .lstack .gl, .lstack .cn, .lstack .rowln, .lstack .tick { fill: none; }
.lstack .dsh { stroke-dasharray: 3 4; }
.lstack .grid { stroke: var(--stack-grid); stroke-width: 1; fill: none; vector-effect: non-scaling-stroke; }
.lstack .nd { fill: var(--stack-face); }
/* report 块上的标题条、字行、引注点；红蓝块上用纸色 */
.lstack .gf { fill: var(--stack-line); stroke: none; }
.lstack .gf.lt { fill: var(--stack-face); }
.lstack .gl.lt { stroke: var(--stack-face); }
/* 四块 report 的面是透明的（颜色在磨砂纸上），所以要用 all 才接得到鼠标 */
.lstack .tile { cursor: pointer; pointer-events: all; }
/* 依据线：展开时以虚线出现 */
.lstack .cn { stroke-dasharray: 2 4; opacity: calc(var(--spread) * .8); }
/* 被指到的那份 report：它的依据线、落到的那一行、那个节点都换成它的颜色 */
.lstack .cn.on { stroke-dasharray: none; stroke-width: calc(var(--stack-stroke) * 2); opacity: 1; }
.lstack .cn.on.k1 { stroke: var(--accent-1); }
.lstack .cn.on.k2 { stroke: var(--accent-2); }
.lstack .cn.on.k3 { stroke: var(--accent-3); }
.lstack .rowln.on { stroke-width: calc(var(--stack-stroke) * 3.5); }
.lstack .rowln.on.k1 { stroke: var(--accent-1); }
.lstack .rowln.on.k2 { stroke: var(--accent-2); }
.lstack .rowln.on.k3 { stroke: var(--accent-3); }
.lstack .nd.on.k1 { fill: var(--accent-1); }
.lstack .nd.on.k2 { fill: var(--accent-2); }
.lstack .nd.on.k3 { fill: var(--accent-3); }
.lstack .nd.on.k0 { fill: var(--stack-line); }
/* chain walk：墨色衬底上压一条彩线（贴纸式描边），走点在最前 */
.lstack .walk, .lstack .walk-u {
  fill: none; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke;
  opacity: 0; transition: opacity .2s;
}
.lstack .walk-u { stroke: var(--stack-line); stroke-width: calc(var(--stack-stroke) * 4.2); }
.lstack .walk { stroke-width: calc(var(--stack-stroke) * 2.4); }
.lstack .walk.on, .lstack .walk-u.on { opacity: 1; }
.lstack .walk.k0 { stroke: var(--stack-face); }
.lstack .walk.k1 { stroke: var(--accent-1); }
.lstack .walk.k2 { stroke: var(--accent-2); }
.lstack .walk.k3 { stroke: var(--accent-3); }
.lstack .walker {
  stroke: var(--stack-line); stroke-width: var(--stack-stroke); vector-effect: non-scaling-stroke;
  opacity: 0;
}
.lstack .walker.on { opacity: 1; }
.lstack .walker.k0 { fill: var(--stack-face); }
.lstack .walker.k1 { fill: var(--accent-1); }
.lstack .walker.k2 { fill: var(--accent-2); }
.lstack .walker.k3 { fill: var(--accent-3); }

/* 动效旁的两个十字：点上面的看 report 的结构，点下面的看探针。点开的卡片在十字右边。 */
.lwrap { position: relative; }
.lwrap .gbtn { position: absolute; left: 5.3%; transform: translate(-50%, -50%); }
.lwrap .gbtn.at-top { top: 10%; }
.lwrap .gbtn.at-bottom { top: 91.4%; }
/* 卡片不压在三层块上（用户 09-25）：左边放得下就放在十字左边，放不下（窄屏）就放在块的下面。
   哪一种由 site.js 打开时量一下再定（at-left / at-under） */
.lwrap .peek.at-top { top: calc(10% - 14px); }
.lwrap .peek.at-bottom { bottom: calc(8.6% - 14px); }
.lwrap .peek.at-left { right: calc(100% - 5.3% + 26px); width: min(320px, calc(50vw - 50% + 5.3% - 64px)); }
.lwrap .peek.at-under { left: 0; right: 0; width: auto; top: calc(100% + 12px); bottom: auto; }

/* 动效旁的两个十字（图标键 .gbtn，规则在 basing_family.css）：十字画成动效同一种线，打开时转成 × */
.lwrap .gbtn svg { width: 22px; height: 22px; transition: transform .2s; }
.lwrap .gbtn svg path { stroke: currentColor; stroke-width: var(--stack-stroke); stroke-linecap: round; fill: none; }
.lwrap .gbtn.on svg { transform: rotate(45deg); }

/* 点开的示意卡：report 的结构 / 探针。纸面、墨边、与键同一种阴影 */
.peek {
  position: absolute; z-index: 5;
  width: 320px;
  padding: 16px 18px 18px;
  background: var(--glass-bg); color: var(--ink);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: var(--edge-w) solid var(--stack-line); border-radius: var(--r-sm);
  box-shadow: var(--peek-shadow);
}
.peek .pk-k {
  margin: 0 0 6px;
  font: var(--fw-strong) var(--fs-note)/1.2 var(--ff-ui);
  text-transform: var(--pbtn-tt); letter-spacing: var(--pbtn-ls);
}
.peek .pk-def { margin: 0 0 12px; font-size: var(--fs-note); line-height: var(--lh-ui); color: var(--ink3); }
.peek .pk-h { margin: 10px 0 4px; font: var(--fw-strong) var(--fs-note)/1.3 var(--ff-ui); }
.peek svg { display: block; width: 100%; height: auto; overflow: visible; }
.peek .pl { stroke: var(--stack-line); stroke-width: var(--stack-stroke); stroke-linecap: round; fill: none; vector-effect: non-scaling-stroke; }
.peek .pl.lt { stroke: var(--ink5); }
.peek .pl.bar { stroke-width: calc(var(--stack-stroke) * 4); }
.peek .pd { stroke: var(--stack-line); stroke-width: var(--stack-stroke); vector-effect: non-scaling-stroke; }
.peek .pd.a1 { fill: var(--accent-1); }
.peek .pd.a2 { fill: var(--accent-2); }
.peek .pd.a3 { fill: var(--accent-3); }
.peek .pd.fc { fill: var(--stack-face); }
.peek .pc { fill: none; stroke-width: calc(var(--stack-stroke) * 1.4); vector-effect: non-scaling-stroke; }
.peek .pc.a1 { stroke: var(--accent-1); }
.peek .pc.a2 { stroke: var(--accent-2); }
.peek .pc.a3 { stroke: var(--accent-3); }
/* 探针：左边一份 report，三条线分到三类去处 */
.peek .pk-probe { display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: 0 10px; margin-top: 4px; }
.peek .pk-rows { list-style: none; margin: 0; padding: 0; display: grid; grid-template-rows: repeat(3, 44px); }
.peek .pk-rows li { display: flex; flex-direction: column; justify-content: center; }
.peek .pk-rows .pk-h { margin: 0 0 4px; }

/* 键盘焦点：全站一种，在 basing_family.css */

/* ══ 窄屏 ══════════════════════════════════════════════════════════════ */

@media (max-width: 899px) {
  .low { flex-direction: column; align-items: stretch; gap: 24px; }
  .act { align-items: flex-end; }
}

/* 手机：主句在前，然后是申请邀请、动效、页脚 */
@media (max-width: 599px) {
  .page {
    padding: 0 16px;
    grid-template-rows: auto;
    grid-template-areas: "bar" "ident" "act" "stage" "foot";
  }
  .low { display: contents; }
  .ident { grid-area: ident; padding: 20px 0 20px; }
  .act { grid-area: act; align-items: stretch; padding-bottom: 8px; }
  .subrow { width: 100%; }
  /* 手机上输入这一排上面是主句，放到下面左边，与右边的「已有邀请码」同一行 */
  .suberr { right: auto; left: 0; bottom: auto; top: calc(var(--pbtn-h) + 8px); }
  .ln { flex: 1 1 auto; width: auto; }
  .act .dtab { align-self: flex-end; }
  .stage { padding: 16px 0 24px; }
  .lwrap { justify-self: stretch; }
  .lstack { width: 100%; height: auto; }
  .bar .bl { gap: 16px; }
  .bar .br { gap: 14px; }
}
