/* base.css - reset + layout + cross-cutting components (V-2-5b split from style.css): navbar/buttons/landing/auth/forms/client-shell/modal/onboarding/ui-scale. */

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* 需求六·item5：根字号挂 --ui-scale 系数（默认 1）。全站 rem 字号/rem 尺寸随滑块整体缩放（正文/标题/小字），
   px 尺寸走下方各组件 calc()。卡片与页面框架（list-card/client-page/container 等）不挂系数 = 框架不变。 */
html { font-size: calc(16px * var(--ui-scale, 1)); -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }
body {
  font-family: var(--font);
  color: var(--text);
  /* body 背景唯一主人 = glass.css（transparent，让玻璃舞台透出）；此处不再设色，
     旧 --paper 底曾与 glass.css 抢 body 背景、靠加载顺序决定谁盖住光球——已删（用户纪律：竞争删一方）。 */
  line-height: 1.6;
  min-height: 100vh;
  letter-spacing: .005em;
}
a { color: var(--accent-deep); text-decoration: none; }
:where(button:not(.glass)) { cursor: pointer; border: none; background: none; font-family: inherit; font-size: inherit; color: inherit; } /* 非玻璃按钮透明重置。:where 特异性 0：组件类自带 font-size/color（如 .sidebar-footnote .62rem）永远胜出，不被重置打回继承；玻璃按钮填充交引擎 */
input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
::selection { background: var(--ink); color: var(--paper); }

#app { min-height: 100vh; display: flex; flex-direction: column; }
.container { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 clamp(20px, 4vw, 40px); }

/* 键盘焦点：克制的全局描边 */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ============================================================
   Navbar — 扁平；落地页时延续二分背景到顶
   ============================================================ */
.navbar {
  padding: 14px 0;
  position: sticky; top: 0; z-index: 100;
} /* G3：背景/border 单源 glass.css（286/287），此处删死直写 */
/* G8：landing 视图无上边栏——navbar 隐藏，logo+登录/注册由 .stage-nav 浮在舞台顶 */
body:has(#view-landing:not(.hidden)) .navbar { display: none; }
.stage-nav {
  position: absolute; top: 0; left: 0; right: 0; z-index: 300; /* ZT-1 (2026-08-27): above modal-overlay z-200 — first-visit guide must not swallow the landing login/register clicks */
  pointer-events: none; /* ZT-1: container never intercepts — short viewports put the guide modal-header x inside the nav band; a full-width click-trap would kill it (ZT audit FAIL1). Interactive children re-enable below. */
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px clamp(20px, 4vw, 40px);
}
.stage-nav-actions { display: flex; align-items: center; gap: 12px; pointer-events: auto; } /* ZT-1: login/register stay clickable above the overlay (ZT-F2 re-audit FAIL3: the original flex rule was replaced, not extended — buttons stacked vertically on mobile) */
.navbar-brand { pointer-events: auto; } /* ZT-1: brand stays clickable (go home) above the overlay */
/* 内层客户端：顶栏退场，侧边栏顶天立地（移动端恢复顶栏供汉堡开合抽屉） */
body:has(#view-client:not(.hidden)) .navbar { display: none; }
.navbar .container { display: flex; align-items: center; justify-content: space-between; min-height: 36px; }
.navbar-brand { display: flex; align-items: center; gap: 12px; cursor: pointer; } /* A7：光标移入 CSS，index.html 内联 style 删除 */

/* 品牌点阵：呼应参考图卡片的圆点母题（3 墨 + 1 强调） */
.navbar-logo {
  width: 30px; height: 30px;
  display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
  gap: 4px;
}
.navbar-logo span { background: var(--ink); display: block; }
.navbar-logo span:nth-child(4) { background: var(--accent); }
.navbar-title { font-size: 1.18rem; font-weight: 700; letter-spacing: -.02em; color: var(--ink); line-height: 1.1; }
.navbar-subtitle { font-size: .7rem; color: var(--muted); font-weight: 500; letter-spacing: .04em; }
.navbar-actions { display: flex; align-items: center; gap: 14px; }
.navbar-user { display: flex; align-items: center; gap: 12px; font-size: .85rem; color: var(--text); font-weight: 500; }
.user-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; color: var(--accent-deep);
  font-size: .68rem; font-weight: 700; letter-spacing: .04em;
}
.admin-badge { color: var(--warn-deep); }

/* ============================================================
   Buttons — 统一参数化组件：变体只设 --g-fill / --g-fg；hover/focus/active 用 inset 叠层；无擦除母题、无 per-variant 散件
   ============================================================ */
.btn {
  /* 统一参数化按钮（刮骨整合）：变体只设 --g-fill / --g-fg；填充画在元素自身玻璃体（实心，绝不渐隐→文字永远可读）；
     hover/focus/active 用 inset 0 0 0 9999px 叠层（对"颜色或渐变"填充都生效）+ --g-ring 聚焦环。
     无方向性擦除母题、无 per-variant hover 背景/文字色——散件归零，glass 层只覆盖参数即换肤。 */
  /* 视觉（填充/字色/浮影/环/交互叠层）一律住 glass.css 接口家；本层只配结构 */
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: calc(11px * var(--ui-scale, 1)) calc(22px * var(--ui-scale, 1)); font-weight: 600; font-size: .875rem; letter-spacing: .01em; /* 需求六·item5：按钮尺寸随滑块 */
  line-height: 1.4; white-space: nowrap;
  position: relative; overflow: hidden; isolation: isolate;
  border: var(--g-border, none); color: var(--g-fg); cursor: pointer; /* --g-border 语义 token（需求八·item4 flat 发丝描边）；液态回落 none 等价原值 */
  transition: transform var(--t-fast) var(--ease-out), color var(--t-base) var(--ease-out);
}
.btn:disabled { opacity: .45; cursor: not-allowed; }
/* 变体 = 仅参数（无 hover/无擦除/无背景重写） */
.btn-ghost   { padding: calc(8px * var(--ui-scale, 1)) calc(12px * var(--ui-scale, 1)); }
.btn-sm { padding: calc(8px * var(--ui-scale, 1)) calc(14px * var(--ui-scale, 1)); font-size: .8rem; }
.btn-xs { padding: calc(4px * var(--ui-scale, 1)) calc(9px * var(--ui-scale, 1)); font-size: .7rem; }
.btn-icon { width: calc(36px * var(--ui-scale, 1)); height: calc(36px * var(--ui-scale, 1)); padding: 0; }
label.btn { cursor: pointer; } /* 原生 label 充当按钮（头像上传等）补指针手型 */

/* ============================================================
   Landing — 满屏编辑式二分舞台
   ============================================================ */
.landing { flex: 1; display: flex; flex-direction: column; }

.landing-stage {
  position: relative;
  flex: 1;
  display: flex;
  min-height: 100vh; min-height: 100dvh; /* G8：navbar 已从 landing 移除，舞台独占满屏 */
  overflow: hidden;
} /* G20：二分底色死（glass.css:291 透明舞台胜，光球透出=设计意图），删直写 */

/* 装饰层：右半细线网格 */
.stage-deco-grid {
  position: absolute; top: 0; right: 0; width: 50%; height: 100%;
  pointer-events: none; z-index: 0;
  background-image:
    linear-gradient(var(--g-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--g-grid) 1px, transparent 1px);
  background-size: 88px 88px;
  -webkit-mask-image: linear-gradient(135deg, transparent, #000 28%, #000 72%, transparent);
          mask-image: linear-gradient(135deg, transparent, #000 28%, #000 72%, transparent);
}
/* 流场方块：内联于左栏下半；线段方向随坐标平滑变化，呈场线流动感；无淡出、无漂移 */
.flow-field {
  align-self: start;
  width: clamp(210px, 22vw, 300px);
  aspect-ratio: 1 / 1;
  background-color: currentColor; /* SVG 无法读主题变量，暗色下黑线不可见 */
  -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%20320%20320'%20fill%3D'none'%20stroke%3D'%23000'%20stroke-width%3D'1.3'%20stroke-linecap%3D'round'%3E%3Cline%20x1%3D'10.8'%20y1%3D'16.0'%20x2%3D'25.2'%20y2%3D'20.0'%2F%3E%3Cline%20x1%3D'10.6'%20y1%3D'45.2'%20x2%3D'25.4'%20y2%3D'47.6'%2F%3E%3Cline%20x1%3D'10.5'%20y1%3D'75.6'%20x2%3D'25.5'%20y2%3D'74.0'%2F%3E%3Cline%20x1%3D'11.1'%20y1%3D'106.0'%20x2%3D'24.9'%20y2%3D'100.4'%2F%3E%3Cline%20x1%3D'11.8'%20y1%3D'135.8'%20x2%3D'24.2'%20y2%3D'127.4'%2F%3E%3Cline%20x1%3D'12.0'%20y1%3D'164.5'%20x2%3D'24.0'%20y2%3D'155.5'%2F%3E%3Cline%20x1%3D'11.6'%20y1%3D'192.3'%20x2%3D'24.4'%20y2%3D'184.5'%2F%3E%3Cline%20x1%3D'10.9'%20y1%3D'219.2'%20x2%3D'25.1'%20y2%3D'214.4'%2F%3E%3Cline%20x1%3D'10.5'%20y1%3D'245.8'%20x2%3D'25.5'%20y2%3D'244.6'%2F%3E%3Cline%20x1%3D'10.5'%20y1%3D'273.2'%20x2%3D'25.5'%20y2%3D'274.0'%2F%3E%3Cline%20x1%3D'10.5'%20y1%3D'301.8'%20x2%3D'25.5'%20y2%3D'302.2'%2F%3E%3Cline%20x1%3D'41.1'%20y1%3D'12.7'%20x2%3D'51.7'%20y2%3D'23.3'%2F%3E%3Cline%20x1%3D'40.4'%20y1%3D'41.9'%20x2%3D'52.4'%20y2%3D'50.9'%2F%3E%3Cline%20x1%3D'39.4'%20y1%3D'72.2'%20x2%3D'53.4'%20y2%3D'77.4'%2F%3E%3Cline%20x1%3D'38.9'%20y1%3D'102.9'%20x2%3D'53.9'%20y2%3D'103.5'%2F%3E%3Cline%20x1%3D'39.1'%20y1%3D'133.2'%20x2%3D'53.7'%20y2%3D'130.0'%2F%3E%3Cline%20x1%3D'39.2'%20y1%3D'162.2'%20x2%3D'53.6'%20y2%3D'157.8'%2F%3E%3Cline%20x1%3D'39.1'%20y1%3D'190.0'%20x2%3D'53.7'%20y2%3D'186.8'%2F%3E%3Cline%20x1%3D'38.9'%20y1%3D'216.9'%20x2%3D'53.9'%20y2%3D'216.7'%2F%3E%3Cline%20x1%3D'39.1'%20y1%3D'243.6'%20x2%3D'53.7'%20y2%3D'246.8'%2F%3E%3Cline%20x1%3D'39.4'%20y1%3D'271.0'%20x2%3D'53.4'%20y2%3D'276.2'%2F%3E%3Cline%20x1%3D'39.3'%20y1%3D'299.5'%20x2%3D'53.5'%20y2%3D'304.5'%2F%3E%3Cline%20x1%3D'71.5'%20y1%3D'11.3'%20x2%3D'78.1'%20y2%3D'24.7'%2F%3E%3Cline%20x1%3D'70.4'%20y1%3D'40.3'%20x2%3D'79.2'%20y2%3D'52.5'%2F%3E%3Cline%20x1%3D'68.7'%20y1%3D'70.5'%20x2%3D'80.9'%20y2%3D'79.1'%2F%3E%3Cline%20x1%3D'67.5'%20y1%3D'101.3'%20x2%3D'82.1'%20y2%3D'105.1'%2F%3E%3Cline%20x1%3D'67.3'%20y1%3D'131.8'%20x2%3D'82.3'%20y2%3D'131.4'%2F%3E%3Cline%20x1%3D'67.4'%20y1%3D'161.1'%20x2%3D'82.2'%20y2%3D'158.9'%2F%3E%3Cline%20x1%3D'67.3'%20y1%3D'189.0'%20x2%3D'82.3'%20y2%3D'187.8'%2F%3E%3Cline%20x1%3D'67.3'%20y1%3D'215.9'%20x2%3D'82.3'%20y2%3D'217.7'%2F%3E%3Cline%20x1%3D'67.7'%20y1%3D'242.7'%20x2%3D'81.9'%20y2%3D'247.7'%2F%3E%3Cline%20x1%3D'68.2'%20y1%3D'270.0'%20x2%3D'81.4'%20y2%3D'277.2'%2F%3E%3Cline%20x1%3D'68.2'%20y1%3D'298.4'%20x2%3D'81.4'%20y2%3D'305.6'%2F%3E%3Cline%20x1%3D'100.4'%20y1%3D'11.0'%20x2%3D'106.0'%20y2%3D'25.0'%2F%3E%3Cline%20x1%3D'99.0'%20y1%3D'40.2'%20x2%3D'107.4'%20y2%3D'52.6'%2F%3E%3Cline%20x1%3D'97.1'%20y1%3D'70.5'%20x2%3D'109.3'%20y2%3D'79.1'%2F%3E%3Cline%20x1%3D'95.9'%20y1%3D'101.5'%20x2%3D'110.5'%20y2%3D'104.9'%2F%3E%3Cline%20x1%3D'95.7'%20y1%3D'132.2'%20x2%3D'110.7'%20y2%3D'131.0'%2F%3E%3Cline%20x1%3D'95.9'%20y1%3D'161.7'%20x2%3D'110.5'%20y2%3D'158.3'%2F%3E%3Cline%20x1%3D'95.8'%20y1%3D'189.7'%20x2%3D'110.6'%20y2%3D'187.1'%2F%3E%3Cline%20x1%3D'95.7'%20y1%3D'216.6'%20x2%3D'110.7'%20y2%3D'217.0'%2F%3E%3Cline%20x1%3D'96.0'%20y1%3D'243.2'%20x2%3D'110.4'%20y2%3D'247.2'%2F%3E%3Cline%20x1%3D'96.4'%20y1%3D'270.4'%20x2%3D'110.0'%20y2%3D'276.8'%2F%3E%3Cline%20x1%3D'96.6'%20y1%3D'298.5'%20x2%3D'109.8'%20y2%3D'305.5'%2F%3E%3Cline%20x1%3D'127.5'%20y1%3D'11.7'%20x2%3D'135.7'%20y2%3D'24.3'%2F%3E%3Cline%20x1%3D'126.1'%20y1%3D'41.3'%20x2%3D'137.1'%20y2%3D'51.5'%2F%3E%3Cline%20x1%3D'124.6'%20y1%3D'72.2'%20x2%3D'138.6'%20y2%3D'77.4'%2F%3E%3Cline%20x1%3D'124.1'%20y1%3D'103.7'%20x2%3D'139.1'%20y2%3D'102.7'%2F%3E%3Cline%20x1%3D'124.7'%20y1%3D'134.5'%20x2%3D'138.5'%20y2%3D'128.7'%2F%3E%3Cline%20x1%3D'125.2'%20y1%3D'163.9'%20x2%3D'138.0'%20y2%3D'156.1'%2F%3E%3Cline%20x1%3D'125.0'%20y1%3D'191.9'%20x2%3D'138.2'%20y2%3D'184.9'%2F%3E%3Cline%20x1%3D'124.4'%20y1%3D'218.8'%20x2%3D'138.8'%20y2%3D'214.8'%2F%3E%3Cline%20x1%3D'124.1'%20y1%3D'245.3'%20x2%3D'139.1'%20y2%3D'245.1'%2F%3E%3Cline%20x1%3D'124.3'%20y1%3D'272.1'%20x2%3D'138.9'%20y2%3D'275.1'%2F%3E%3Cline%20x1%3D'124.4'%20y1%3D'300.0'%20x2%3D'138.8'%20y2%3D'304.0'%2F%3E%3Cline%20x1%3D'153.8'%20y1%3D'13.8'%20x2%3D'166.2'%20y2%3D'22.2'%2F%3E%3Cline%20x1%3D'152.9'%20y1%3D'44.1'%20x2%3D'167.1'%20y2%3D'48.7'%2F%3E%3Cline%20x1%3D'152.5'%20y1%3D'75.7'%20x2%3D'167.5'%20y2%3D'73.9'%2F%3E%3Cline%20x1%3D'153.6'%20y1%3D'107.2'%20x2%3D'166.4'%20y2%3D'99.2'%2F%3E%3Cline%20x1%3D'155.3'%20y1%3D'137.5'%20x2%3D'164.7'%20y2%3D'125.7'%2F%3E%3Cline%20x1%3D'156.2'%20y1%3D'166.5'%20x2%3D'163.8'%20y2%3D'153.5'%2F%3E%3Cline%20x1%3D'155.8'%20y1%3D'194.6'%20x2%3D'164.2'%20y2%3D'182.2'%2F%3E%3Cline%20x1%3D'154.4'%20y1%3D'221.8'%20x2%3D'165.6'%20y2%3D'211.8'%2F%3E%3Cline%20x1%3D'153.2'%20y1%3D'248.4'%20x2%3D'166.8'%20y2%3D'242.0'%2F%3E%3Cline%20x1%3D'152.6'%20y1%3D'275.0'%20x2%3D'167.4'%20y2%3D'272.2'%2F%3E%3Cline%20x1%3D'152.5'%20y1%3D'302.6'%20x2%3D'167.5'%20y2%3D'301.4'%2F%3E%3Cline%20x1%3D'180.9'%20y1%3D'17.6'%20x2%3D'195.9'%20y2%3D'18.4'%2F%3E%3Cline%20x1%3D'181.1'%20y1%3D'48.3'%20x2%3D'195.7'%20y2%3D'44.5'%2F%3E%3Cline%20x1%3D'182.7'%20y1%3D'79.6'%20x2%3D'194.1'%20y2%3D'70.0'%2F%3E%3Cline%20x1%3D'185.4'%20y1%3D'110.1'%20x2%3D'191.4'%20y2%3D'96.3'%2F%3E%3Cline%20x1%3D'187.8'%20y1%3D'139.1'%20x2%3D'189.0'%20y2%3D'124.1'%2F%3E%3Cline%20x1%3D'188.8'%20y1%3D'167.5'%20x2%3D'188.0'%20y2%3D'152.5'%2F%3E%3Cline%20x1%3D'188.1'%20y1%3D'195.9'%20x2%3D'188.7'%20y2%3D'180.9'%2F%3E%3Cline%20x1%3D'186.1'%20y1%3D'223.9'%20x2%3D'190.7'%20y2%3D'209.7'%2F%3E%3Cline%20x1%3D'183.9'%20y1%3D'251.2'%20x2%3D'192.9'%20y2%3D'239.2'%2F%3E%3Cline%20x1%3D'182.4'%20y1%3D'278.1'%20x2%3D'194.4'%20y2%3D'269.1'%2F%3E%3Cline%20x1%3D'181.8'%20y1%3D'305.6'%20x2%3D'195.0'%20y2%3D'298.4'%2F%3E%3Cline%20x1%3D'210.2'%20y1%3D'21.6'%20x2%3D'223.4'%20y2%3D'14.4'%2F%3E%3Cline%20x1%3D'211.7'%20y1%3D'51.9'%20x2%3D'221.9'%20y2%3D'40.9'%2F%3E%3Cline%20x1%3D'214.7'%20y1%3D'82.0'%20x2%3D'218.9'%20y2%3D'67.6'%2F%3E%3Cline%20x1%3D'218.0'%20y1%3D'110.6'%20x2%3D'215.6'%20y2%3D'95.8'%2F%3E%3Cline%20x1%3D'220.3'%20y1%3D'138.2'%20x2%3D'213.3'%20y2%3D'125.0'%2F%3E%3Cline%20x1%3D'221.0'%20y1%3D'166.2'%20x2%3D'212.6'%20y2%3D'153.8'%2F%3E%3Cline%20x1%3D'220.2'%20y1%3D'195.1'%20x2%3D'213.4'%20y2%3D'181.7'%2F%3E%3Cline%20x1%3D'218.0'%20y1%3D'224.2'%20x2%3D'215.6'%20y2%3D'209.4'%2F%3E%3Cline%20x1%3D'215.3'%20y1%3D'252.5'%20x2%3D'218.3'%20y2%3D'237.9'%2F%3E%3Cline%20x1%3D'213.0'%20y1%3D'280.1'%20x2%3D'220.6'%20y2%3D'267.1'%2F%3E%3Cline%20x1%3D'212.0'%20y1%3D'307.8'%20x2%3D'221.6'%20y2%3D'296.2'%2F%3E%3Cline%20x1%3D'240.9'%20y1%3D'24.1'%20x2%3D'249.5'%20y2%3D'11.9'%2F%3E%3Cline%20x1%3D'243.1'%20y1%3D'53.6'%20x2%3D'247.3'%20y2%3D'39.2'%2F%3E%3Cline%20x1%3D'246.5'%20y1%3D'82.2'%20x2%3D'243.9'%20y2%3D'67.4'%2F%3E%3Cline%20x1%3D'249.5'%20y1%3D'109.4'%20x2%3D'240.9'%20y2%3D'97.0'%2F%3E%3Cline%20x1%3D'251.1'%20y1%3D'136.2'%20x2%3D'239.3'%20y2%3D'127.0'%2F%3E%3Cline%20x1%3D'251.4'%20y1%3D'164.2'%20x2%3D'239.0'%20y2%3D'155.8'%2F%3E%3Cline%20x1%3D'250.7'%20y1%3D'193.5'%20x2%3D'239.7'%20y2%3D'183.3'%2F%3E%3Cline%20x1%3D'248.7'%20y1%3D'223.4'%20x2%3D'241.7'%20y2%3D'210.2'%2F%3E%3Cline%20x1%3D'245.8'%20y1%3D'252.7'%20x2%3D'244.6'%20y2%3D'237.7'%2F%3E%3Cline%20x1%3D'243.2'%20y1%3D'280.8'%20x2%3D'247.2'%20y2%3D'266.4'%2F%3E%3Cline%20x1%3D'241.8'%20y1%3D'308.7'%20x2%3D'248.6'%20y2%3D'295.3'%2F%3E%3Cline%20x1%3D'271.0'%20y1%3D'25.0'%20x2%3D'276.2'%20y2%3D'11.0'%2F%3E%3Cline%20x1%3D'273.5'%20y1%3D'53.9'%20x2%3D'273.7'%20y2%3D'38.9'%2F%3E%3Cline%20x1%3D'276.6'%20y1%3D'81.7'%20x2%3D'270.6'%20y2%3D'67.9'%2F%3E%3Cline%20x1%3D'279.1'%20y1%3D'108.3'%20x2%3D'268.1'%20y2%3D'98.1'%2F%3E%3Cline%20x1%3D'280.3'%20y1%3D'135.0'%20x2%3D'266.9'%20y2%3D'128.2'%2F%3E%3Cline%20x1%3D'280.4'%20y1%3D'163.2'%20x2%3D'266.8'%20y2%3D'156.8'%2F%3E%3Cline%20x1%3D'279.6'%20y1%3D'192.8'%20x2%3D'267.6'%20y2%3D'184.0'%2F%3E%3Cline%20x1%3D'277.6'%20y1%3D'223.1'%20x2%3D'269.6'%20y2%3D'210.5'%2F%3E%3Cline%20x1%3D'274.6'%20y1%3D'252.6'%20x2%3D'272.6'%20y2%3D'237.8'%2F%3E%3Cline%20x1%3D'271.8'%20y1%3D'280.9'%20x2%3D'275.4'%20y2%3D'266.3'%2F%3E%3Cline%20x1%3D'270.4'%20y1%3D'308.8'%20x2%3D'276.8'%20y2%3D'295.2'%2F%3E%3Cline%20x1%3D'299.6'%20y1%3D'25.1'%20x2%3D'304.4'%20y2%3D'10.9'%2F%3E%3Cline%20x1%3D'302.0'%20y1%3D'53.9'%20x2%3D'302.0'%20y2%3D'38.9'%2F%3E%3Cline%20x1%3D'305.0'%20y1%3D'81.7'%20x2%3D'299.0'%20y2%3D'67.9'%2F%3E%3Cline%20x1%3D'307.3'%20y1%3D'108.5'%20x2%3D'296.7'%20y2%3D'97.9'%2F%3E%3Cline%20x1%3D'308.4'%20y1%3D'135.5'%20x2%3D'295.6'%20y2%3D'127.7'%2F%3E%3Cline%20x1%3D'308.4'%20y1%3D'163.9'%20x2%3D'295.6'%20y2%3D'156.1'%2F%3E%3Cline%20x1%3D'307.3'%20y1%3D'193.7'%20x2%3D'296.7'%20y2%3D'183.1'%2F%3E%3Cline%20x1%3D'304.8'%20y1%3D'223.7'%20x2%3D'299.2'%20y2%3D'209.9'%2F%3E%3Cline%20x1%3D'301.5'%20y1%3D'252.7'%20x2%3D'302.5'%20y2%3D'237.7'%2F%3E%3Cline%20x1%3D'298.8'%20y1%3D'280.4'%20x2%3D'305.2'%20y2%3D'266.8'%2F%3E%3Cline%20x1%3D'297.5'%20y1%3D'308.0'%20x2%3D'306.5'%20y2%3D'296.0'%2F%3E%3C%2Fsvg%3E");
  mask: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%20320%20320'%20fill%3D'none'%20stroke%3D'%23000'%20stroke-width%3D'1.3'%20stroke-linecap%3D'round'%3E%3Cline%20x1%3D'10.8'%20y1%3D'16.0'%20x2%3D'25.2'%20y2%3D'20.0'%2F%3E%3Cline%20x1%3D'10.6'%20y1%3D'45.2'%20x2%3D'25.4'%20y2%3D'47.6'%2F%3E%3Cline%20x1%3D'10.5'%20y1%3D'75.6'%20x2%3D'25.5'%20y2%3D'74.0'%2F%3E%3Cline%20x1%3D'11.1'%20y1%3D'106.0'%20x2%3D'24.9'%20y2%3D'100.4'%2F%3E%3Cline%20x1%3D'11.8'%20y1%3D'135.8'%20x2%3D'24.2'%20y2%3D'127.4'%2F%3E%3Cline%20x1%3D'12.0'%20y1%3D'164.5'%20x2%3D'24.0'%20y2%3D'155.5'%2F%3E%3Cline%20x1%3D'11.6'%20y1%3D'192.3'%20x2%3D'24.4'%20y2%3D'184.5'%2F%3E%3Cline%20x1%3D'10.9'%20y1%3D'219.2'%20x2%3D'25.1'%20y2%3D'214.4'%2F%3E%3Cline%20x1%3D'10.5'%20y1%3D'245.8'%20x2%3D'25.5'%20y2%3D'244.6'%2F%3E%3Cline%20x1%3D'10.5'%20y1%3D'273.2'%20x2%3D'25.5'%20y2%3D'274.0'%2F%3E%3Cline%20x1%3D'10.5'%20y1%3D'301.8'%20x2%3D'25.5'%20y2%3D'302.2'%2F%3E%3Cline%20x1%3D'41.1'%20y1%3D'12.7'%20x2%3D'51.7'%20y2%3D'23.3'%2F%3E%3Cline%20x1%3D'40.4'%20y1%3D'41.9'%20x2%3D'52.4'%20y2%3D'50.9'%2F%3E%3Cline%20x1%3D'39.4'%20y1%3D'72.2'%20x2%3D'53.4'%20y2%3D'77.4'%2F%3E%3Cline%20x1%3D'38.9'%20y1%3D'102.9'%20x2%3D'53.9'%20y2%3D'103.5'%2F%3E%3Cline%20x1%3D'39.1'%20y1%3D'133.2'%20x2%3D'53.7'%20y2%3D'130.0'%2F%3E%3Cline%20x1%3D'39.2'%20y1%3D'162.2'%20x2%3D'53.6'%20y2%3D'157.8'%2F%3E%3Cline%20x1%3D'39.1'%20y1%3D'190.0'%20x2%3D'53.7'%20y2%3D'186.8'%2F%3E%3Cline%20x1%3D'38.9'%20y1%3D'216.9'%20x2%3D'53.9'%20y2%3D'216.7'%2F%3E%3Cline%20x1%3D'39.1'%20y1%3D'243.6'%20x2%3D'53.7'%20y2%3D'246.8'%2F%3E%3Cline%20x1%3D'39.4'%20y1%3D'271.0'%20x2%3D'53.4'%20y2%3D'276.2'%2F%3E%3Cline%20x1%3D'39.3'%20y1%3D'299.5'%20x2%3D'53.5'%20y2%3D'304.5'%2F%3E%3Cline%20x1%3D'71.5'%20y1%3D'11.3'%20x2%3D'78.1'%20y2%3D'24.7'%2F%3E%3Cline%20x1%3D'70.4'%20y1%3D'40.3'%20x2%3D'79.2'%20y2%3D'52.5'%2F%3E%3Cline%20x1%3D'68.7'%20y1%3D'70.5'%20x2%3D'80.9'%20y2%3D'79.1'%2F%3E%3Cline%20x1%3D'67.5'%20y1%3D'101.3'%20x2%3D'82.1'%20y2%3D'105.1'%2F%3E%3Cline%20x1%3D'67.3'%20y1%3D'131.8'%20x2%3D'82.3'%20y2%3D'131.4'%2F%3E%3Cline%20x1%3D'67.4'%20y1%3D'161.1'%20x2%3D'82.2'%20y2%3D'158.9'%2F%3E%3Cline%20x1%3D'67.3'%20y1%3D'189.0'%20x2%3D'82.3'%20y2%3D'187.8'%2F%3E%3Cline%20x1%3D'67.3'%20y1%3D'215.9'%20x2%3D'82.3'%20y2%3D'217.7'%2F%3E%3Cline%20x1%3D'67.7'%20y1%3D'242.7'%20x2%3D'81.9'%20y2%3D'247.7'%2F%3E%3Cline%20x1%3D'68.2'%20y1%3D'270.0'%20x2%3D'81.4'%20y2%3D'277.2'%2F%3E%3Cline%20x1%3D'68.2'%20y1%3D'298.4'%20x2%3D'81.4'%20y2%3D'305.6'%2F%3E%3Cline%20x1%3D'100.4'%20y1%3D'11.0'%20x2%3D'106.0'%20y2%3D'25.0'%2F%3E%3Cline%20x1%3D'99.0'%20y1%3D'40.2'%20x2%3D'107.4'%20y2%3D'52.6'%2F%3E%3Cline%20x1%3D'97.1'%20y1%3D'70.5'%20x2%3D'109.3'%20y2%3D'79.1'%2F%3E%3Cline%20x1%3D'95.9'%20y1%3D'101.5'%20x2%3D'110.5'%20y2%3D'104.9'%2F%3E%3Cline%20x1%3D'95.7'%20y1%3D'132.2'%20x2%3D'110.7'%20y2%3D'131.0'%2F%3E%3Cline%20x1%3D'95.9'%20y1%3D'161.7'%20x2%3D'110.5'%20y2%3D'158.3'%2F%3E%3Cline%20x1%3D'95.8'%20y1%3D'189.7'%20x2%3D'110.6'%20y2%3D'187.1'%2F%3E%3Cline%20x1%3D'95.7'%20y1%3D'216.6'%20x2%3D'110.7'%20y2%3D'217.0'%2F%3E%3Cline%20x1%3D'96.0'%20y1%3D'243.2'%20x2%3D'110.4'%20y2%3D'247.2'%2F%3E%3Cline%20x1%3D'96.4'%20y1%3D'270.4'%20x2%3D'110.0'%20y2%3D'276.8'%2F%3E%3Cline%20x1%3D'96.6'%20y1%3D'298.5'%20x2%3D'109.8'%20y2%3D'305.5'%2F%3E%3Cline%20x1%3D'127.5'%20y1%3D'11.7'%20x2%3D'135.7'%20y2%3D'24.3'%2F%3E%3Cline%20x1%3D'126.1'%20y1%3D'41.3'%20x2%3D'137.1'%20y2%3D'51.5'%2F%3E%3Cline%20x1%3D'124.6'%20y1%3D'72.2'%20x2%3D'138.6'%20y2%3D'77.4'%2F%3E%3Cline%20x1%3D'124.1'%20y1%3D'103.7'%20x2%3D'139.1'%20y2%3D'102.7'%2F%3E%3Cline%20x1%3D'124.7'%20y1%3D'134.5'%20x2%3D'138.5'%20y2%3D'128.7'%2F%3E%3Cline%20x1%3D'125.2'%20y1%3D'163.9'%20x2%3D'138.0'%20y2%3D'156.1'%2F%3E%3Cline%20x1%3D'125.0'%20y1%3D'191.9'%20x2%3D'138.2'%20y2%3D'184.9'%2F%3E%3Cline%20x1%3D'124.4'%20y1%3D'218.8'%20x2%3D'138.8'%20y2%3D'214.8'%2F%3E%3Cline%20x1%3D'124.1'%20y1%3D'245.3'%20x2%3D'139.1'%20y2%3D'245.1'%2F%3E%3Cline%20x1%3D'124.3'%20y1%3D'272.1'%20x2%3D'138.9'%20y2%3D'275.1'%2F%3E%3Cline%20x1%3D'124.4'%20y1%3D'300.0'%20x2%3D'138.8'%20y2%3D'304.0'%2F%3E%3Cline%20x1%3D'153.8'%20y1%3D'13.8'%20x2%3D'166.2'%20y2%3D'22.2'%2F%3E%3Cline%20x1%3D'152.9'%20y1%3D'44.1'%20x2%3D'167.1'%20y2%3D'48.7'%2F%3E%3Cline%20x1%3D'152.5'%20y1%3D'75.7'%20x2%3D'167.5'%20y2%3D'73.9'%2F%3E%3Cline%20x1%3D'153.6'%20y1%3D'107.2'%20x2%3D'166.4'%20y2%3D'99.2'%2F%3E%3Cline%20x1%3D'155.3'%20y1%3D'137.5'%20x2%3D'164.7'%20y2%3D'125.7'%2F%3E%3Cline%20x1%3D'156.2'%20y1%3D'166.5'%20x2%3D'163.8'%20y2%3D'153.5'%2F%3E%3Cline%20x1%3D'155.8'%20y1%3D'194.6'%20x2%3D'164.2'%20y2%3D'182.2'%2F%3E%3Cline%20x1%3D'154.4'%20y1%3D'221.8'%20x2%3D'165.6'%20y2%3D'211.8'%2F%3E%3Cline%20x1%3D'153.2'%20y1%3D'248.4'%20x2%3D'166.8'%20y2%3D'242.0'%2F%3E%3Cline%20x1%3D'152.6'%20y1%3D'275.0'%20x2%3D'167.4'%20y2%3D'272.2'%2F%3E%3Cline%20x1%3D'152.5'%20y1%3D'302.6'%20x2%3D'167.5'%20y2%3D'301.4'%2F%3E%3Cline%20x1%3D'180.9'%20y1%3D'17.6'%20x2%3D'195.9'%20y2%3D'18.4'%2F%3E%3Cline%20x1%3D'181.1'%20y1%3D'48.3'%20x2%3D'195.7'%20y2%3D'44.5'%2F%3E%3Cline%20x1%3D'182.7'%20y1%3D'79.6'%20x2%3D'194.1'%20y2%3D'70.0'%2F%3E%3Cline%20x1%3D'185.4'%20y1%3D'110.1'%20x2%3D'191.4'%20y2%3D'96.3'%2F%3E%3Cline%20x1%3D'187.8'%20y1%3D'139.1'%20x2%3D'189.0'%20y2%3D'124.1'%2F%3E%3Cline%20x1%3D'188.8'%20y1%3D'167.5'%20x2%3D'188.0'%20y2%3D'152.5'%2F%3E%3Cline%20x1%3D'188.1'%20y1%3D'195.9'%20x2%3D'188.7'%20y2%3D'180.9'%2F%3E%3Cline%20x1%3D'186.1'%20y1%3D'223.9'%20x2%3D'190.7'%20y2%3D'209.7'%2F%3E%3Cline%20x1%3D'183.9'%20y1%3D'251.2'%20x2%3D'192.9'%20y2%3D'239.2'%2F%3E%3Cline%20x1%3D'182.4'%20y1%3D'278.1'%20x2%3D'194.4'%20y2%3D'269.1'%2F%3E%3Cline%20x1%3D'181.8'%20y1%3D'305.6'%20x2%3D'195.0'%20y2%3D'298.4'%2F%3E%3Cline%20x1%3D'210.2'%20y1%3D'21.6'%20x2%3D'223.4'%20y2%3D'14.4'%2F%3E%3Cline%20x1%3D'211.7'%20y1%3D'51.9'%20x2%3D'221.9'%20y2%3D'40.9'%2F%3E%3Cline%20x1%3D'214.7'%20y1%3D'82.0'%20x2%3D'218.9'%20y2%3D'67.6'%2F%3E%3Cline%20x1%3D'218.0'%20y1%3D'110.6'%20x2%3D'215.6'%20y2%3D'95.8'%2F%3E%3Cline%20x1%3D'220.3'%20y1%3D'138.2'%20x2%3D'213.3'%20y2%3D'125.0'%2F%3E%3Cline%20x1%3D'221.0'%20y1%3D'166.2'%20x2%3D'212.6'%20y2%3D'153.8'%2F%3E%3Cline%20x1%3D'220.2'%20y1%3D'195.1'%20x2%3D'213.4'%20y2%3D'181.7'%2F%3E%3Cline%20x1%3D'218.0'%20y1%3D'224.2'%20x2%3D'215.6'%20y2%3D'209.4'%2F%3E%3Cline%20x1%3D'215.3'%20y1%3D'252.5'%20x2%3D'218.3'%20y2%3D'237.9'%2F%3E%3Cline%20x1%3D'213.0'%20y1%3D'280.1'%20x2%3D'220.6'%20y2%3D'267.1'%2F%3E%3Cline%20x1%3D'212.0'%20y1%3D'307.8'%20x2%3D'221.6'%20y2%3D'296.2'%2F%3E%3Cline%20x1%3D'240.9'%20y1%3D'24.1'%20x2%3D'249.5'%20y2%3D'11.9'%2F%3E%3Cline%20x1%3D'243.1'%20y1%3D'53.6'%20x2%3D'247.3'%20y2%3D'39.2'%2F%3E%3Cline%20x1%3D'246.5'%20y1%3D'82.2'%20x2%3D'243.9'%20y2%3D'67.4'%2F%3E%3Cline%20x1%3D'249.5'%20y1%3D'109.4'%20x2%3D'240.9'%20y2%3D'97.0'%2F%3E%3Cline%20x1%3D'251.1'%20y1%3D'136.2'%20x2%3D'239.3'%20y2%3D'127.0'%2F%3E%3Cline%20x1%3D'251.4'%20y1%3D'164.2'%20x2%3D'239.0'%20y2%3D'155.8'%2F%3E%3Cline%20x1%3D'250.7'%20y1%3D'193.5'%20x2%3D'239.7'%20y2%3D'183.3'%2F%3E%3Cline%20x1%3D'248.7'%20y1%3D'223.4'%20x2%3D'241.7'%20y2%3D'210.2'%2F%3E%3Cline%20x1%3D'245.8'%20y1%3D'252.7'%20x2%3D'244.6'%20y2%3D'237.7'%2F%3E%3Cline%20x1%3D'243.2'%20y1%3D'280.8'%20x2%3D'247.2'%20y2%3D'266.4'%2F%3E%3Cline%20x1%3D'241.8'%20y1%3D'308.7'%20x2%3D'248.6'%20y2%3D'295.3'%2F%3E%3Cline%20x1%3D'271.0'%20y1%3D'25.0'%20x2%3D'276.2'%20y2%3D'11.0'%2F%3E%3Cline%20x1%3D'273.5'%20y1%3D'53.9'%20x2%3D'273.7'%20y2%3D'38.9'%2F%3E%3Cline%20x1%3D'276.6'%20y1%3D'81.7'%20x2%3D'270.6'%20y2%3D'67.9'%2F%3E%3Cline%20x1%3D'279.1'%20y1%3D'108.3'%20x2%3D'268.1'%20y2%3D'98.1'%2F%3E%3Cline%20x1%3D'280.3'%20y1%3D'135.0'%20x2%3D'266.9'%20y2%3D'128.2'%2F%3E%3Cline%20x1%3D'280.4'%20y1%3D'163.2'%20x2%3D'266.8'%20y2%3D'156.8'%2F%3E%3Cline%20x1%3D'279.6'%20y1%3D'192.8'%20x2%3D'267.6'%20y2%3D'184.0'%2F%3E%3Cline%20x1%3D'277.6'%20y1%3D'223.1'%20x2%3D'269.6'%20y2%3D'210.5'%2F%3E%3Cline%20x1%3D'274.6'%20y1%3D'252.6'%20x2%3D'272.6'%20y2%3D'237.8'%2F%3E%3Cline%20x1%3D'271.8'%20y1%3D'280.9'%20x2%3D'275.4'%20y2%3D'266.3'%2F%3E%3Cline%20x1%3D'270.4'%20y1%3D'308.8'%20x2%3D'276.8'%20y2%3D'295.2'%2F%3E%3Cline%20x1%3D'299.6'%20y1%3D'25.1'%20x2%3D'304.4'%20y2%3D'10.9'%2F%3E%3Cline%20x1%3D'302.0'%20y1%3D'53.9'%20x2%3D'302.0'%20y2%3D'38.9'%2F%3E%3Cline%20x1%3D'305.0'%20y1%3D'81.7'%20x2%3D'299.0'%20y2%3D'67.9'%2F%3E%3Cline%20x1%3D'307.3'%20y1%3D'108.5'%20x2%3D'296.7'%20y2%3D'97.9'%2F%3E%3Cline%20x1%3D'308.4'%20y1%3D'135.5'%20x2%3D'295.6'%20y2%3D'127.7'%2F%3E%3Cline%20x1%3D'308.4'%20y1%3D'163.9'%20x2%3D'295.6'%20y2%3D'156.1'%2F%3E%3Cline%20x1%3D'307.3'%20y1%3D'193.7'%20x2%3D'296.7'%20y2%3D'183.1'%2F%3E%3Cline%20x1%3D'304.8'%20y1%3D'223.7'%20x2%3D'299.2'%20y2%3D'209.9'%2F%3E%3Cline%20x1%3D'301.5'%20y1%3D'252.7'%20x2%3D'302.5'%20y2%3D'237.7'%2F%3E%3Cline%20x1%3D'298.8'%20y1%3D'280.4'%20x2%3D'305.2'%20y2%3D'266.8'%2F%3E%3Cline%20x1%3D'297.5'%20y1%3D'308.0'%20x2%3D'306.5'%20y2%3D'296.0'%2F%3E%3C%2Fsvg%3E") no-repeat center / contain;
  mask-repeat: no-repeat; mask-size: contain; mask-position: center;
  opacity: 0;
}

/* 手部蒙版 — 可复用入场组件：
   拆成两半，各自从外侧向中间收敛并淡入；#view-landing 每次由 display:none 恢复时动画自动重放。
   方向随视口切换：PC 横向（左右两半沿 X 收敛）；移动竖屏见下方 orientation 查询（上下两半沿 Y 收敛 + 旋转 90° 蒙版）。 */
.hand-mask { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.hand-part {
  position: absolute; inset: 0;
  background-image: url("/hand-mask.png");
  background-repeat: no-repeat; background-size: cover; background-position: center;
  --mask-op: .14; --enter: 1.5s;
  will-change: transform, opacity;
  /* 就绪前停在起始姿态并隐藏；.site-ready 由内联脚本在蒙版图 + 字体加载后添加，避免"没加载好就播完" */
  opacity: 0; transform: var(--from);
}
.site-ready .hand-part { animation: hand-enter var(--enter) var(--ease-snap) .08s both; }
.hand-part--a { clip-path: inset(0 50% 0 0); --from: translateX(clamp(-150px, -11vw, -64px)); }
.hand-part--b { clip-path: inset(0 0 0 50%); --from: translateX(clamp(64px, 11vw, 150px)); }
@keyframes hand-enter {
  from { transform: var(--from); opacity: 0; }
  to   { transform: none;        opacity: var(--mask-op); }
}

/* 内容网格 */
.stage-grid {
  position: relative; z-index: 1;
  flex: 1;
  display: grid; grid-template-columns: 1fr 1fr;
  align-items: stretch;
  gap: clamp(40px, 6vw, 96px);
  padding-block: clamp(40px, 7vh, 88px);
}

.stage-left {
  max-width: 560px;
  display: flex; flex-direction: column; justify-content: space-between;
  align-self: stretch; gap: 28px;
}
.stage-text { display: flex; flex-direction: column; }
.eyebrow {
  display: inline-flex; align-items: center; gap: 12px;
  font-size: .74rem; font-weight: 600; letter-spacing: .22em;
  color: var(--muted); text-transform: none; margin-bottom: 26px;
  opacity: 0;
}
.eyebrow-rule { width: 30px; height: 2px; background: var(--ink); display: inline-block; }

.hero-title {
  display: grid; grid-template-columns: repeat(3, auto);
  justify-content: start; column-gap: .12em; row-gap: .04em;
  font-size: clamp(46px, 7.4vw, 92px);
  font-weight: 900; line-height: .96; letter-spacing: -.02em;
  color: var(--ink); margin: 6px 0 26px;
}
.hero-title span {
  display: block;
  opacity: 0;
}
.stage-copy {
  font-size: 1.02rem; line-height: 1.75; color: var(--ink-3);
  max-width: 440px; font-weight: 400;
  opacity: 0;
}

.stage-right {
  display: flex; flex-direction: column; justify-content: center;
  max-width: 460px; margin-left: auto; width: 100%;
}
.stage-kicker {
  font-size: .8rem; font-weight: 600; letter-spacing: .05em;
  color: var(--ink); margin-bottom: 22px;
  opacity: 0;
}
.entry-list { display: flex; flex-direction: column; gap: 14px; }

/* 入口块：纯墨直角实心 */
.entry {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 20px; width: 100%; text-align: left;
  color: var(--ink); /* 入口已接入标准玻璃（浅透镜），文字转深（原 --paper 白字配紫块） */
  padding: 22px 26px; height: 96px; box-sizing: border-box; position: relative; overflow: hidden; isolation: isolate;
  transition: background-color var(--t-base) var(--ease-out), transform var(--t-base) var(--ease-snap);
  opacity: 0;
} /* v1.4.11：height 硬编码固定（min-height 是下限——25 字 desc 换行处仍撑高；固定后移动/PC 恒等高，内容超出由 overflow 裁剪） */
/* 入口块：紫条已连根拔（悬停/聚焦左竖条是老效果，用户定性删）；悬停=箭头微动+整钮上浮（--g-raise） */
.entry:focus-visible { outline-color: var(--accent-bright); transform: translateY(var(--g-raise, -1px)); }
.entry-index { font-family: var(--font); font-size: 1.5rem; font-weight: 700; color: var(--accent-bright); letter-spacing: -.02em; }
.entry-body { display: flex; flex-direction: column; gap: 3px; }
.entry-title { font-size: 1.18rem; font-weight: 700; color: var(--ink); letter-spacing: -.01em; }
.entry-desc { font-size: .8rem; color: var(--ink-2); line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } /* v1.4.10：简介锁两行（行数差异不撑高按钮） */
.entry-arrow { font-size: 1.4rem; color: var(--ink); transition: transform var(--t-base) var(--ease-snap), color var(--t-base) var(--ease-out); }
.entry:hover .entry-arrow, .entry:focus-visible .entry-arrow { transform: translateX(6px); color: var(--accent-bright); }

/* ============================================================
   R28：主页入口按钮定制——liquid × flat 融合开始按钮
   调研收敛（成熟开始按钮语言）：光标跟随光斑 + hover 辉光边缘 + 微光扫过 + 弹簧按压。
   liquid 面（光斑/辉光/扫光走玻璃引擎 token），flat 底（实心对比/弹簧按压）——
   一键融合站点两种风格，替代「标准按钮效果」。
   光斑 --mx/--my 由 app-auth mousemove 委托更新（JS 只写变量，视觉全在 CSS 层）。
   ============================================================ */
.entry-glow {
  position: absolute; inset: 0; z-index: -1; /* 引擎玻璃面之后、文字之前 */
  pointer-events: none;
  opacity: 0; transition: opacity var(--t-base) var(--ease-out);
  background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 50%),
    color-mix(in srgb, var(--accent-bright) 30%, transparent), transparent 70%); /* v1.4.10：光斑改回发光紫（用户：v1.4.4 改白后混入卡片原色、动效等于没有） */
}
.entry:hover .entry-glow, .entry:focus-visible .entry-glow { opacity: 1; } /* 光标光斑（liquid 透镜感） */
.entry::after { /* 微光扫过：hover 触发一次自左至右横扫整钮的光泽带（经典开始按钮动效）
   v0.25.95 修正：原 width 36% + top -40% + 斜扫只覆盖按钮左半/上区（用户实测「扫过小半个按钮」）。
   改 width 62% 横向盖大部分 + height 200% / top -50% 垂直盖满 + translateX 横扫全宽（先平移后旋转保持斜姿）。 */
  content: ''; position: absolute; z-index: -1; top: -50%; left: 0;
  width: 62%; height: 200%;
  transform: translateX(-150%) rotate(18deg);
  background: linear-gradient(105deg, transparent 0%, color-mix(in srgb, var(--accent-bright) 26%, #fff 40%) 50%, transparent 100%); /* v1.4.10：扫光紫白带（浅底上纯白不可见——混入提亮填充；紫调白光清晰） */
  pointer-events: none;
}
.entry:hover::after { animation: entry-sheen 1.15s var(--ease-out) .1s; } /* v1.4.4：扫光更慢（原 .7s），更清晰可见 */
@keyframes entry-sheen { to { transform: translateX(320%) rotate(18deg); } }
/* v1.4.4 用户需求：平面简约（flat）下入口按钮与底区分不开——深灰细边框 + 提亮填充（--g-fill-mid → 纸面亮档）。
   liquid 透镜有玻璃边缘不涉及；dark 保留透镜。 */
[data-style="flat"] .entry.glass {
  border: 1px solid color-mix(in srgb, var(--ink) 16%, transparent);
  --g-fill: var(--g-paper-bright);
}
/* hover 辉光边缘（liquid）：完整保留引擎浮影列表（--g-lift/--g-liquid/--g-surface + hover 白洗 inset），
   末尾追加主题色辉光——直接覆盖列表会丢浮影与 hover 白洗（玻璃引擎教训 v0.19.17：列表禁混 none）。
   .entry.glass 提特异性：glass.css 后加载，同特异性 (.entry:hover vs .glass:hover) 会被引擎规则覆盖（实测） */
.entry.glass:hover, .entry.glass:focus-visible {
  --g-hover: rgba(255,255,255,.30); /* v1.4.4：hover 变亮（原主题灰洗 120,120,132 → 白亮） */
  box-shadow: var(--g-lift), var(--g-liquid, none), var(--g-surface, none),
    inset 0 0 0 9999px var(--g-hover),
    0 0 0 1px color-mix(in srgb, var(--accent-bright) 45%, transparent), /* v1.4.10：辉光边缘改回发光紫（用户反馈） */
    0 12px 36px -10px color-mix(in srgb, var(--accent-bright) 55%, transparent); /* v1.4.10：紫色发光感（用户反馈） */
}
.entry:active { transform: translateY(1px) scale(.985); transition-duration: 60ms; } /* 弹簧按压（flat 触感） */

.stage-note {
  margin-top: 22px; font-size: .78rem; color: var(--muted); letter-spacing: .03em;
  opacity: 0;
}

.landing-footer {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  padding: 16px 0; font-size: .76rem; color: var(--muted); letter-spacing: .03em;
}

@keyframes rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes flow-in { from { opacity: 0; } to { opacity: .5; } }

/* 入场动效门控：资源就绪（.site-ready，见 index.html 内联脚本）后才播放；
   每次 #view-landing 由 display:none 恢复时随重排重放。就绪前各元素 opacity:0 作"幕布"。
   入口仅淡入（不带动画 transform），以免覆盖悬停的 translateX 位移。 */
.site-ready .eyebrow         { animation: rise .6s var(--ease-snap) both; }
.site-ready .hero-title span { animation: rise .5s var(--ease-snap) both; animation-delay: calc(.12s + var(--i) * .045s); }
.site-ready .stage-kicker    { animation: rise .6s var(--ease-snap) .25s both; }
.site-ready .stage-note      { animation: rise .6s var(--ease-snap) .4s both; }
.site-ready .stage-copy      { animation: rise .6s var(--ease-snap) .55s both; }
.site-ready .flow-field      { animation: flow-in .8s var(--ease-out) .45s both; }
.site-ready .entry-list .entry:nth-child(1) { animation: fade-in .6s var(--ease-out) .5s both; }
.site-ready .entry-list .entry:nth-child(2) { animation: fade-in .6s var(--ease-out) .6s both; }

/* ============================================================
   Auth
   ============================================================ */
/* 用户反馈「登录/注册点进去一片空白」（2026-08-19 实证）：auth 视图由 auth feature append 到 body
   （非 #app）。原 flex:1 要求父容器 flex，但 body 非 flex、#app 独占 min-height:100vh → auth 视图掉到
   视口外 y=100vh+，landing 隐藏后视口全空白。改 fixed 覆盖视口。 */
.auth-view { position: fixed; inset: 0; z-index: 20; display: flex; align-items: center; justify-content: center; padding: 40px 20px; overflow-y: auto; }
.auth-card {
  padding: 44px 40px; width: 100%; max-width: 440px;
  position: relative; animation: rise .4s var(--ease-snap) both;
}
.auth-header { text-align: center; margin-bottom: 30px; }
.auth-header h2 { font-size: 1.6rem; font-weight: 900; letter-spacing: -.02em; margin-bottom: 6px; color: var(--ink); }
.auth-header p { font-size: .85rem; color: var(--muted); }

/* 角色切换：下划条形态连根删，收编标准分段控件 .seg-tabs（glass.css 单点）。
   登录页专属：下边距 + 内衬随 UI 滑块 */
.seg-tabs--role { margin-bottom: 24px; }
.seg-tabs--role .seg-tab { padding: calc(9px * var(--ui-scale, 1)) 8px; font-size: .85rem; letter-spacing: .02em; }

.auth-footer { text-align: center; margin-top: 26px; font-size: .8rem; color: var(--muted); }
.auth-footer a { font-weight: 700; color: var(--accent-deep); }
/* 登录页页脚「验证码登录」与「立即注册」两个交互点原本内联紧贴只隔一个「·」，
   视觉上像一个按钮（用户反馈）。flex + gap 拉开链接与分隔符；sep 居中于间隙；链接 hover 下划线
   增强可点性识别。仅作用于登录页变体，注册页页脚（文本+单链接）不受影响。 */
.auth-footer--split { display: flex; align-items: center; justify-content: center; gap: 14px; }
.auth-footer--split .sep { opacity: .7; }
.auth-footer--split a:hover { text-decoration: underline; }

/* 需求三十：注册页用户协议/隐私政策两行轻量勾选——复用 .checkbox-item 同款勾选视觉，
   文本右侧文档名高亮为链接（点击浮窗看全文）；两行间留 10px 空隙，压住「轻量不喧宾」 */
.agree-row { display: flex; align-items: center; gap: 9px; margin-top: 10px; font-size: .8rem; font-weight: 500; cursor: pointer; }
.agree-row + .agree-row { margin-top: 8px; }
.agree-check {
  appearance: none; -webkit-appearance: none;
  width: calc(15px * var(--ui-scale, 1)); height: calc(15px * var(--ui-scale, 1)); border: 2px solid var(--faint); background: transparent;
  cursor: pointer; transition: all var(--t-fast); flex-shrink: 0; position: relative; margin: 0;
}
.agree-check:checked { background: var(--accent); border-color: var(--accent); }
.agree-check:checked::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 36%; height: 66%;
  border: solid var(--white); border-width: 0 2px 2px 0;
  transform: translate(-50%, -50%) rotate(45deg); transform-origin: center;
  animation: check-pop .18s var(--ease-out);
}
.agree-check:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.agree-text { color: var(--ink-3); }
.agree-link { font-weight: 700; color: var(--accent-deep); text-decoration: underline; text-underline-offset: 2px; }
.agree-link:hover { color: var(--accent); }
/* 协议/政策浮窗正文：长文排印（标题分级 + 段距拉开 + 行高加高，纯文本阅读舒适）
   R21：md 排印统一——标题紧缩小阶梯（少用 1/2 级）、正文比标题右缩进、列表编号进一步右缩进 */
.policy-body { line-height: 1.9; }
/* v0.25.94：md 排版口径扩展到 .contract-md——合同浮窗正文同协议同口径
   （全局 *{padding:0} 清零 ol/ul 默认缩进，无此规则则列表编号画在负空间、从左边戳出正文）。 */
.policy-body h1, .policy-body h2, .contract-md h1, .contract-md h2 { font-size: 1.05rem; font-weight: 900; color: var(--ink); margin: 16px 0 7px; } /* R21④：1/2 级不再巨大 */
.policy-body h3, .contract-md h3 { font-size: .98rem; font-weight: 800; color: var(--ink-2); margin: 14px 0 6px; }
.policy-body h4, .contract-md h4 { font-size: .94rem; font-weight: 800; color: var(--ink-2); margin: 12px 0 5px; }
.policy-body h5, .contract-md h5 { font-size: .9rem; font-weight: 700; color: var(--ink-3); margin: 10px 0 4px; }
.policy-body h6, .contract-md h6 { font-size: .88rem; font-weight: 700; color: var(--ink-3); margin: 8px 0 3px; }
.policy-body p, .contract-md p { margin: 0 0 8px 12px; font-size: .86rem; color: var(--ink-3); } /* R21②③：正文字号 .86 + 比标题右缩进 */
.policy-body ul, .policy-body ol, .contract-md ul, .contract-md ol { margin: 0 0 8px 20px; padding-left: 16px; } /* R21②：列表编号进一步右缩进（padding 是编号立足区） */
.policy-body ul, .contract-md ul { list-style: disc; }
.policy-body ol, .contract-md ol { list-style: decimal; }
.policy-body li, .contract-md li { font-size: .86rem; line-height: 1.8; color: var(--ink-3); margin: 2px 0; }
.policy-body strong, .contract-md strong { color: var(--ink); }
/* policy/contract 同口径补 blockquote/img/code（原只有 md-preview 有，合同/政策正文含引用/图/代码时无样式） */
.policy-body blockquote, .contract-md blockquote {
  margin: 6px 0 6px 12px; padding: 4px 12px; /* 随正文缩进线（比标题右缩进） */
  border-left: 3px solid var(--accent-tint, rgba(122,104,224,.3));
  color: var(--ink-3); font-size: .86rem; line-height: 1.8; /* 正文口径 */
}
.policy-body blockquote p, .contract-md blockquote p { margin: 2px 0; }
.policy-body img, .contract-md img { display: block; max-width: 100%; margin: 8px 0; border: 1px solid var(--border-light); }
/* settings avatar picker preview (2026-08-26): the picked image rendered at natural size
   and overflowed the modal — constrain to the modal bounds (contain keeps aspect ratio) */
.avatar-preview { display: flex; justify-content: center; padding: 4px 0; }
.avatar-preview img { display: block; max-width: 100%; max-height: 52vh; object-fit: contain; border-radius: var(--lg-r, 12px); }
.policy-body code, .contract-md code {
  font-family: var(--mono); font-size: .78em;
  padding: 1px 5px; border-radius: 5px;
  background: var(--g-fill-weak, rgba(255,255,255,.5));
  color: var(--accent-deep, #4B3DB0);
  overflow-wrap: anywhere;
}

/* 浏览器自动填充的蓝底抹掉：录入区底色 = 浮窗底色 */
input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus,
textarea:-webkit-autofill, textarea:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px var(--g-autofill, var(--white)) inset;
  -webkit-text-fill-color: var(--text);
  caret-color: var(--accent);
}

.remember-me {
  display: flex; align-items: center; gap: 8px; margin-bottom: 20px;
  cursor: pointer; font-size: .8rem; color: var(--muted); user-select: none;
}
.remember-me input[type="checkbox"] {
  width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; flex-shrink: 0;
}

/* ============================================================
   Forms — 登记簿式录入：项名在左、信息在右，项间细米线分隔。
   录入区无米色框：文字直接落在纯色底上——
   下拉以文字右侧的 v 字示意，输入以文字下方极细下划线示意。
   ============================================================ */
.form-group {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 22px;
  margin-bottom: 0; padding: 15px 0;
}
/* U8：起草合同浮窗应用资料栏去横线方案（glass.css .form-group + .form-group 细线去掉，
   与 .profile-form 同口径），不引入分段标题——组间靠 15px 空隙分组 */
.contract-form .form-group + .form-group { border-top: none; }
/* 细米线只用于项与项之间：首项之前不出现（条件段落自带顶线保持连续） */
#d-address-section + .form-group { border-top: 1px solid var(--paper-3); } /* G22：.form-group + .form-group 部分被 glass.css:298 胜，删 */
#d-address-section { border-top: 1px solid var(--paper-3); }
/* 右侧录入控件撑满剩余宽度（省份选择包裹层 / 成绩区 / 预算行等） */
.form-group > span[id$="-wrap"], .form-group > div { flex: 1 1 0; min-width: 0; }
/* 辅助内容（角色提示/地区提醒等）独占整行，排在项下方。
   v0.25.50 教训（需求七·第143条）：form-group 内尾部灰字提示若不加此接口，会以 flex:0 1 auto
   与控件同排抢宽（起草/签约浮窗时间组件被提示行挤到 ~63px 塌零叠字）。新增尾部提示必须走独占整行
   接口（[id$="-note"] 或此条），禁止裸放。 */
.form-group > .login-username-hint, .form-group > [id$="-note"] { flex-basis: 100%; margin-top: -4px; }

/* 登录页：用户名命中现有账户时的灰字角色提示（固定占位防表单跳动） */
.login-username-hint { min-height: 17px; margin-top: 5px; font-size: .74rem; color: var(--muted); letter-spacing: .02em; }
/* 「不存在的账户」红字提示 */
.login-hint--missing { color: var(--danger) !important; font-weight: 600; }

/* canvas 拼图 + 拖拽轨道 + 失败抖动
   B4 修复（用户反馈：滑块只能滑到左边一半 + 拼图块没渲染）：
   原 #captcha-canvas width:100% 把 280 内部坐标 canvas 拉伸到容器宽（实测 532px），
   轨道同宽，而 JS 滑块 max=CAPTCHA_W-SLIDER_W=240px（固定 CSS 像素）→ 滑块只能到轨道 45%
   （左半边）、缺口按内部坐标画被拉伸错位、永远够不到。修复：canvas/轨道固定 280px，
   内部坐标=视觉坐标，滑块 0~240 全轨对齐缺口；拼图块 #captcha-puzzle 跟随 --captcha-x。 */
.captcha-box { display: flex; flex-direction: column; gap: 10px; align-items: center; position: relative;
  width: 280px; margin: 0 auto; } /* box 固定 280：canvas/track/puzzle 同左 0，拼图块对齐缺口 */
#captcha-canvas { width: 280px; height: 120px; border-radius: 10px; display: block; touch-action: none; }
#captcha-puzzle { position: absolute; left: 0; top: 40px; width: 40px; height: 40px; pointer-events: none;
  transform: translateX(var(--captcha-x, 0px)); will-change: transform; z-index: 2;
  filter: drop-shadow(0 2px 8px rgba(0,0,0,.28)); } /* R-4 全迁移：阴影跟随异形 alpha（box-shadow 恒为矩形） */
.captcha-slider-track { position: relative; width: 280px; height: 42px; border-radius: 21px; overflow: hidden;
  background: var(--g-fill, rgba(128,128,128,.14)); box-shadow: inset 0 1px 3px rgba(0,0,0,.12); }
.captcha-slider-fill { position: absolute; left: 0; top: 0; bottom: 0; width: calc(var(--captcha-x, 0px) + 40px);
  background: linear-gradient(90deg, rgba(76,175,80,.35), rgba(76,175,80,.5)); border-radius: 21px; }
.captcha-slider-knob { position: absolute; left: 0; top: 0; width: 40px; height: 40px; margin: 1px;
  display: flex; align-items: center; justify-content: center; cursor: grab; touch-action: none;
  border-radius: 50%; background: #fff; color: #333; font-size: 18px; user-select: none;
  box-shadow: 0 2px 8px rgba(0,0,0,.25); transform: translateX(var(--captcha-x, 0px)); will-change: transform; }
.captcha-slider-knob:active { cursor: grabbing; }
.captcha--dragging .captcha-slider-knob { box-shadow: 0 3px 12px rgba(0,0,0,.35); }
.captcha-slider-knob.captcha--pass { background: #4caf50; color: #fff; }
.captcha-slider-knob.captcha--fail { background: #e53935; color: #fff; }
.captcha-slider-track.captcha--shake { animation: captcha-shake .4s ease; }
@keyframes captcha-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); } 40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); } 80% { transform: translateX(4px); }
}
.captcha-tip { font-size: .74rem; color: var(--muted); text-align: center; letter-spacing: .02em; margin: 0; }
.captcha-tip--fail { color: var(--danger); font-weight: 600; }
.captcha-tip--pass { color: #4caf50; font-weight: 600; }

/* v0.26.0 手机号输入行（地区前缀 + 号码）与验证码输入框（内部右缘发送按钮，不占左半边输入区） */
/* .phone-input-row/.phone-prefix-select 随地区前缀连根移除（用户拍板只支持大陆手机号），零引用 */
.code-input-wrap { position: relative; flex: 1; min-width: 0; }
.code-input-wrap .form-input { width: 100%; padding-right: 116px; } /* 预留右缘按钮空间，文字不顶按钮 */
/* 发送验证码按钮聚焦/按下往下动太多）：
   原 top:50% + transform:translateY(-50%) 垂直居中——transform 是引擎 hover(translateY(-1px) 上浮)/
   active(scale .97) 的财产，引擎规则(:hover/:active 特异性 0-2-0)覆盖本类(0-1-0)后居中位移丢失，
   按钮从 -50% 掉到 -1px 下坠近半高。改 top:0+bottom:0+margin:auto 0+height:fit-content 居中，
   transform 完全还给引擎 → 悬停上浮/按下收缩/聚焦双色环全部走标准 .btn 效果，零特例。 */
.code-send-btn { position: absolute; right: 6px; top: 0; bottom: 0; margin: auto 0; height: fit-content;
  max-width: 104px;
  font-size: .72rem; padding: 4px 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 验证码输入框是文本框组件，倒计时灰字不该再叠一层毛玻璃底（backdrop-filter blur
   在输入框右缘糊出一块「底板」，倒计时文字溢出时视觉更乱）。倒计时（disabled）态去掉毛玻璃 + 玻璃阴影，
   只剩 .btn:disabled 的 .45 灰字——名副其实的「灰字」，输入框右缘干净。正常态保持标准玻璃按钮。 */
.code-send-btn:disabled { backdrop-filter: none; box-shadow: none; }
@media (max-width: 480px) {
  .code-send-btn { max-width: 92px; padding: 4px 6px; font-size: .66rem; }
  .code-input-wrap .form-input { padding-right: 104px; }
  /* 移动端验证码行（登录/注册/绑定）：label 固定 116px + 列 gap 22px + 右缘按钮预留 104px
     把输入可视区挤到 33px（375px 屏实测），6 位验证码 + placeholder 全被吞。gap 收窄 + label
     按内容宽 → 输入框顶到 label、拉满剩余。必须高特异性（:470 .form-label 在本块之后，
     同特异性源序后胜会覆盖失效）。 */
  .form-group:has(.code-input-wrap) { gap: 8px; }
  .form-group:has(.code-input-wrap) > .form-label { flex: 0 0 auto; min-width: 0; }
}
.form-label {
  flex: 0 0 116px; margin: 0;
  font-size: .8rem; font-weight: 700; color: var(--ink-3); letter-spacing: .02em; line-height: 1.5;
}
.form-label .req { color: var(--danger); }
/* 标签下的小注（签约后展示之类补充说明） */
.form-label-note { display: block; margin-top: 2px; font-size: .66rem; font-weight: 500; color: var(--faint); letter-spacing: .02em; }
/* 联系方式「签约后向对方展示」小注（教师弹窗 / 需求卡） */
.contact-sign-note { font-size: .74rem; color: var(--muted); letter-spacing: .02em; }

.form-input, .form-select {
  flex: 1; min-width: 0; width: auto;
  padding: calc(8px * var(--ui-scale, 1)) 12px; border: none; outline: none; /* 输入框尺寸随滑块（水平 12px 与 glass.css 输入族同值，勿再分叉） */
  font-size: .92rem; color: var(--text); caret-color: var(--accent);
  text-align: left; /* 录入内容一律左对齐 */
}
/* 手动输入区：文字下方短下划线示意（聚焦擦墨）；下拉栏不加底线 */
.form-input {
  background-image: linear-gradient(var(--ink), var(--ink)),
                    linear-gradient(var(--paper-3), var(--paper-3));
  background-repeat: no-repeat, no-repeat;
  background-position: left bottom, left bottom;
  background-size: 0 1px, min(56%, 200px) 1px;
  transition: background-size .3s var(--ease-snap);
}
.form-input:focus { background-size: min(56%, 200px) 1px, min(56%, 200px) 1px; }
.form-input::placeholder { color: var(--faint); }
textarea.form-input {
  background-image: none; border-bottom: 1px solid var(--paper-3);
  resize: vertical; min-height: 88px; line-height: 1.65;
}

/* 下拉：裸文字 + 右侧 v 字，无任何底线。
   v0.20.0 箭头改 mask + currentColor（SVG data URI 无法读主题变量，暗色下黑箭头不可见） */
.form-select {
  appearance: none; cursor: pointer;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23000' stroke-width='1.6'/%3E%3C/svg%3E") no-repeat right 3px center / 12px 8px;
  mask: url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23000' stroke-width='1.6'/%3E%3C/svg%3E") no-repeat right 3px center / 12px 8px;
  padding-right: calc(24px * var(--ui-scale, 1));
}

/* ============================================================
   自定义下拉组件（app.js initCustomSelects 包装原生 select）：
   透明触发器 + v 形箭头开合翻转；选项面板 = 浮窗纸面玻璃（glass--float，
   --g-fill: --g-paper 同 modal/profile-panel），选项直接放玻璃上、面板自身滚动。
   ============================================================ */
.custom-select { position: relative; z-index: 1; }
.custom-select.open { z-index: 50; } /* 展开时容器浮起：面板(z-index:40)随容器盖过下方卡片/兄弟 */
.form-group .custom-select, .filter-group .custom-select { flex: 1 1 0; min-width: 0; width: 100%; }
.gaokao-row .custom-select { flex: 1; min-width: 110px; }
/* 需求五：上海精细地址选择（区·镇/街道 二级联动）——两下拉横向排列，紧贴是缺陷（CLAUDE.md 组件间距纪律）；
   子件为 .custom-select 包装（app-ui initCustomSelects）或原生 .form-select，各自 flex:1 均分行宽 */
.sh-addr-picker { display: flex; gap: 10px; width: 100%; align-items: stretch; }
.sh-addr-picker > .custom-select, .sh-addr-picker > .form-select { flex: 1 1 0; min-width: 0; }
@media (max-width: 420px) { .sh-addr-picker { flex-direction: column; gap: 6px; } }
.custom-select-trigger {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; padding: calc(8px * var(--ui-scale, 1)) 12px; /* 下拉触发器尺寸随滑块（水平 12px 与 glass.css 输入族同值） */
  min-height: calc(40px * var(--ui-scale, 1)); /* v0.25.94：默认空纵向高度——空态（无选项/纯 disabled 提示）不塌成细条 */
  cursor: pointer;
  font-size: .92rem; color: var(--text); text-align: left;
  transition: color var(--t-fast) var(--ease-out);
}
.filter-group .custom-select-trigger { font-size: .8rem; }
.custom-select-trigger:hover { color: var(--ink); }
.custom-select-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.custom-select-empty { color: var(--faint); }
.custom-select-trigger .drop-caret { color: var(--faint); flex-shrink: 0; transition: transform .28s var(--ease-snap), color var(--t-fast) var(--ease-out); }
.custom-select.open .drop-caret { color: var(--ink); }
.custom-select-panel {
  position: fixed; z-index: 300; /* 挂 body + fixed + 顶层 z：脱离玻璃 isolation 堆叠上下文 */
  margin-top: 6px; padding: 4px;
  /* 面板不滚：玻璃体住面板元素自身，滚动交内部透明通道。
     动画走纯 transform——Chromium bug 983252：
     backdrop-filter + opacity 动画同元素 → 磨砂渲染失效=白色不透明 */
  opacity: 1; visibility: hidden; transform: translateY(-6px);
  transform-origin: top center;
  transition: transform .22s var(--ease-snap), visibility 0s .22s;
}
.custom-select-panel.open { visibility: visible; transform: none; transition: none; } /* 983252：frost+transform 过渡冻结，改瞬开瞬关 */
/* 透明滚动通道：无背景无玻璃类无边框——选项透在面板玻璃上滚，磨砂钉住不跟滚 */
.custom-select-list { max-height: 256px; overflow-y: auto; }
.custom-option {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: calc(8px * var(--ui-scale, 1)) calc(12px * var(--ui-scale, 1)); font-size: .84rem; color: var(--ink-3); /* 需求六·item5：下拉选项随滑块 */
  border: none;
  transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
/* 选项间横线分割（大面板内不叠玻璃珠） */
.custom-option + .custom-option { border-top: 1px solid var(--g-option-line); }
.custom-option:hover { background: var(--g-option-hover); color: var(--ink); }
.custom-option.selected { background: var(--g-option-sel); color: var(--ink); font-weight: 600; }

/* ============================================================
   结构化时间组件：期望开课 / 可授课时间段
   纵向多条组件、无分隔线、组件间空几 px 缝隙；行内 = 星期下拉 + 起止时间栏 + 删除按钮。
   时间栏 = 文本框外观 + 内部靠右小 v（整点下拉），冒号两侧独立数字框。
   ============================================================ */
.time-slots { display: flex; flex-direction: column; gap: 6px; width: 100%; }
.time-slot { display: flex; align-items: center; gap: 8px; }
.time-slot .custom-select { flex: 0 0 calc(96px * var(--ui-scale, 1)); } /* 星期下拉栏定宽（随滑块） */
.time-range { flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px; } /* 起止时间对（桌面与删除按钮共享一行） */
.time-field {
  position: relative; flex: 1; min-width: 0;
  display: flex; align-items: center; justify-content: center; gap: 1px;
  padding: calc(6px * var(--ui-scale, 1)) 2px calc(6px * var(--ui-scale, 1)) calc(12px * var(--ui-scale, 1)); /* 需求六·item5：时间栏随滑块 */
  background-color: var(--g-fill-weak);
  border-radius: var(--lg-r-sm);
  box-shadow: var(--glass-lift-sm), var(--g-liquid-sm); /* 需求六·item4：与表单控件同款标准玻璃边缘（删淡化） */
}
.time-field:focus-within { box-shadow: var(--glass-lift-sm), var(--g-liquid-sm), 0 0 0 3px var(--g-focus-soft); }
.time-field input {
  width: 26px; border: none; outline: none; background: transparent;
  text-align: center; font-size: .92rem; color: var(--text); caret-color: var(--accent); padding: 0;
}
.time-field input::selection { background: var(--accent); color: #fff; }
/* 时/分/冒号组：relative 锚点，ghost 的 inset:0 精确居中于本组（hh/mm 等宽对称 → 冒号=组中心）。
   v0.25.27 空栏冒号恒显：冒号不再隐藏（打字党可见结构），灰字占位让位夹住它 */
.time-hms { position: relative; display: flex; align-items: center; justify-content: center; gap: 1px; } /* 去 min-width:0——hms 默认 min-width:auto（内容下限），时/分输入框永不塌零叠字 */
.time-colon { color: var(--faint); font-size: .92rem; flex: 0 0 auto; } /* 空态与灰字同色（融进「开始:时间」观感） */
.time-field.has-value .time-colon { color: var(--muted); } /* 填入后变实色 */
.time-field-ghost {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center; gap: 5px; /* 两半之间的间隙恰好容纳冒号 */
  font-size: .78rem; color: var(--faint); pointer-events: none; white-space: nowrap;
  transition: opacity var(--t-fast) var(--ease-out);
}
.time-field.has-value .time-field-ghost { opacity: 0; }
/* 内部整点下拉：只显小 v（隐藏文字段），触发器去玻璃底（小 v 无独立组件框） */
/* .time-picker 复用 .custom-select 类，被表单布局规则
   `.form-group .custom-select { flex:1; width:100% }` 泄漏命中 → 下拉包装被撑满整个时间栏、
   数字框被挤到左缘溢出（与文本框错位）。显式把时间栏内下拉收缩为内容宽并禁伸缩。 */
.time-field .time-picker { flex: 0 0 auto; width: auto; min-width: 0; }
.time-field .time-picker .custom-select { width: auto; }
.time-field .time-picker .custom-select-trigger {
  width: auto; gap: 0; padding: 3px 3px; margin-left: 2px;
  min-height: 0; /* 通用空态撑高 min-height:40px 漏被本特判覆盖——
     整点小 v 无独立框无需撑高，漏盖会把时间栏从 ~38px 撑到 ~78px（通用撑高 × 特判叠加，Chrome 实测） */
  background-color: transparent; box-shadow: none; border-radius: 0;
  color: var(--faint); font-size: inherit;
}
.time-field .time-picker .custom-select-trigger:hover { color: var(--ink); }
.time-field .time-picker .custom-select-text { display: none; }
/* 整点面板挂 body（脱离 .time-field），面板类由 initCustomSelects 按 select.time-pick-select 加 */
.time-pick-panel { min-width: 104px; }
.time-pick-panel .custom-select-list { max-height: 320px; }
.time-slot-tilde { color: var(--faint); font-size: .9rem; flex: 0 0 auto; }
.time-slot-del {
  flex: 0 0 auto; width: calc(24px * var(--ui-scale, 1)); height: calc(24px * var(--ui-scale, 1)); border: none; cursor: pointer; /* 需求六·item5：删除钮随滑块 */
  display: flex; align-items: center; justify-content: center;
  font-size: .95rem; color: var(--muted); background: transparent; border-radius: 50%;
  transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.time-slot-del:hover { background: var(--g-option-hover); color: var(--danger); }
/* 「+ 新建时间段」行：默认在首条组件位置；新增组件插到它前，它即自然落位新组件正下方 */
.time-slots-add { display: flex; align-items: center; gap: 8px; }
.time-add-btn {
  flex: 0 0 auto; width: calc(36px * var(--ui-scale, 1)); height: calc(36px * var(--ui-scale, 1)); border: none; cursor: pointer; /* v0.25.1：与时间组件本体等高的圆角正方形（原 26px 过小）；需求六·item5 随滑块 */
  display: flex; align-items: center; justify-content: center;
  font-size: 1.15rem; line-height: 1; color: var(--accent);
  background-color: var(--g-fill-weak); border-radius: var(--lg-r-sm);
  box-shadow: var(--glass-lift-sm), var(--g-liquid-sm); /* 需求六·item4：与表单控件同款标准玻璃边缘（删淡化） */
  transition: background-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.time-add-btn:hover { background: var(--g-option-hover); }
.time-add-btn:disabled { opacity: .45; cursor: default; }
.time-add-label { font-size: .78rem; color: var(--faint); letter-spacing: .02em; }

/* 窄屏（≤860px）结构化时间组件：纵向排布——星期 + 删除按钮一行，起止时间段独占一行。
   窄屏 form-group 控件区仅剩 ~170px，一行五件必挤爆；双行排布让时间段全宽展开。
   order 只在移动端生效（桌面保持 DOM 序 [星期][时间段][删除]） */
@media (max-width: 860px) {
  .time-slot { flex-wrap: wrap; row-gap: 6px; }
  .time-slot .custom-select { order: 1; flex: 1 1 0; }
  .time-slot-del { order: 2; margin-left: auto; }
  .time-range { order: 3; flex: 1 1 100%; }
  /* 时间栏内容最小宽（两个数字框 + 冒号 + 小 v）在 ~170px 控件区内会溢出 82px 字段——
     紧凑化：数字框收窄、小 v 贴得更近（桌面宽度充裕不受影响） */
  .time-field { padding: 6px 1px 6px 8px; }
  .time-field input { width: 21px; font-size: .86rem; }
  .time-field .time-picker .custom-select-trigger { padding: 3px 2px; margin-left: 0; }
}

/* ============================================================
   分段日期输入：复用 .time-field 玻璃面
   （--g-fill-weak/圆角/阴影/聚焦环），仅叠 3 段输入 + 分隔连字符 + 居中灰字占位。
   类名独立（seg-*），不碰 .time-field 时间专用子件（.time-hms/.time-colon/.time-picker）。
   ============================================================ */
/* M5：首次上课日期重做——三个独立输入框 + 单位后缀【】年【】月【】日。
   弃旧长条玻璃面 + 居中 ghost（用户反馈「长条、输入区集中中间、灰字像能点但只能输」）。
   每 part = 独立输入框 + 单位文本；校验逻辑（readDateField/clampDateDay）不变。 */
.seg-date { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; }
.seg-date .seg-part { display: inline-flex; align-items: center; gap: 4px; }
.seg-date .seg-input {
  /* U6：日期输入框接入玻璃输入族（原 --field 固定色 + 实线边框未绑定风格包，
     liquid 下不成玻璃、flat 下不成纸面）——background-color longhand 防吃 focus 态，liquid 半透白
     磨砂玻璃 / flat 自动变纸面，随风格包与主题自适应。 */
  width: 54px; padding: calc(6px * var(--ui-scale, 1)) 0;
  text-align: center; font-size: .9rem; color: var(--text);
  background-color: var(--g-fill-weak); border: none; border-radius: var(--lg-r-sm);
  box-shadow: var(--glass-lift-sm), var(--g-liquid-sm);
  caret-color: var(--accent);
}
.seg-date .seg-input:focus { outline: none; box-shadow: var(--glass-lift-sm), var(--g-liquid-sm), 0 0 0 3px var(--g-focus-soft); }
.seg-date .seg-year { width: 66px; } /* 4 位年份框比 2 位月/日宽 */
.seg-date .seg-unit { font-size: .78rem; color: var(--muted); flex: 0 0 auto; }
@media (max-width: 860px) {
  .seg-date { gap: 4px; }
  .seg-date .seg-input { width: 44px; }
  .seg-date .seg-year { width: 52px; }
}


.checkbox-grid { flex: 1; min-width: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.checkbox-item {
  display: flex; align-items: center; gap: 8px; padding: calc(8px * var(--ui-scale, 1)) calc(10px * var(--ui-scale, 1)); /* 需求六·item5：勾选件尺寸随滑块 */
  cursor: pointer; font-size: .8rem; font-weight: 500;
  transition: color var(--t-fast) var(--ease-out), background-color var(--t-fast) var(--ease-out);
}
/* v0.25.24 文字色走引擎 --g-fg 单点（base=--muted / hover=--ink / checked=--ink，glass.css 定义）。
   v0.25.19 注释曾宣告收敛，但 style.css 残留 color: var(--muted) 特异性(0,1,0) 压过 :where(.glass) 的
   color: var(--g-fg)(0,0,0)，导致选中态实际是「灰字压紫底」——本次连根删净真正落地。 */
.checkbox-item input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: calc(15px * var(--ui-scale, 1)); height: calc(15px * var(--ui-scale, 1)); border: 2px solid var(--faint); background: transparent;
  cursor: pointer; transition: all var(--t-fast); flex-shrink: 0; position: relative; margin: 0;
}
.checkbox-item input[type="checkbox"]:checked { background: var(--accent); border-color: var(--accent); }
/* M6：勾画法从固定像素 left:3px/top:0（随 --ui-scale 缩放后失中 → 勾歪）改为
   百分比尺寸 + translate(-50%,-50%) 居中——勾随盒子任意缩放恒居中。 */
.checkbox-item input[type="checkbox"]:checked::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 36%; height: 66%;
  border: solid var(--white); border-width: 0 2px 2px 0;
  transform: translate(-50%, -50%) rotate(45deg); transform-origin: center;
  animation: check-pop .18s var(--ease-out); /* 勾选弹入：纯 transform+opacity 关键帧（非玻璃子树无 backdrop-filter，transition 亦安全） */
}
.checkbox-item input[type="checkbox"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@keyframes check-pop {
  from { opacity: 0; transform: translate(-50%, -50%) rotate(45deg) scale(.35); }
  to { opacity: 1; transform: translate(-50%, -50%) rotate(45deg) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .checkbox-item input[type="checkbox"]:checked::after { animation: none; } /* 关入场动画，保留终态对勾（选中提示本身是信息） */
}
@media (forced-colors: active) {
  .checkbox-item input[type="checkbox"] { appearance: auto; } /* 高对比模式还原原生控件（白勾用 border 画法在 HCM 下不可见） */
}

.score-row { display: flex; align-items: center; gap: 12px; padding: 8px 0; flex-wrap: wrap; }
.score-subject { flex: 0 0 50px; font-size: .8rem; font-weight: 700; color: var(--ink-3); }
.form-divider { height: 1px; background: var(--line); margin: 24px 0; }
.form-actions { display: flex; gap: 10px; margin-top: 24px; }
.form-actions .btn { flex: 1; }

/* 发帖/广播组件：文本编辑区独占整行，功能按钮（H2/H3/加粗/插图）移到其下方横排 */
.form-group > textarea.form-input { flex-basis: 100%; order: 2; }
.form-group > .md-toolbar { flex-basis: 100%; order: 3; margin-top: 10px; }

/* 区间行：最低~最高 两个输入框横排（教师报价区间/需求预算区间原两处内联 flex 重复，抽类单源） */
.range-row { display: flex; gap: var(--s3); align-items: center; }
.range-row .form-input { flex: 1; min-width: 0; }

/* 定位上下文：档案页复用聊天区 .sr-file-input（absolute 1px 透明文件框）时，
   无此上下文则其 containing block 直落 ICB——脱离 main/壳的 overflow 裁剪，
   把 document 撑出第二条滚动条（profile-credential-file absolute 撑高 html） */
.profile-form { position: relative; max-width: 640px; margin: 0 auto; padding: 8px; }

/* 教师档案内联成绩 */
.gaokao-section { margin-bottom: 18px; padding-top: 4px; } /* padding-top：与上方设置项的体面空隙 */
.gaokao-section h4 { font-size: .8rem; font-weight: 700; color: var(--ink-3); margin-bottom: 14px; }
/* R14：等第 pill 组多行换行时与科目名顶对齐（原 center 居中整组，首行 pill 被顶到科目名上方错位）；
   科目名与值组件（分数输入/等第 pill/下拉）同一直线、左对齐同列 */
.gaokao-row { display: flex; align-items: start; gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
/* 略低于 .form-label 但高于选项文字，可读性优先 */
.gaokao-row .subject-name, .score-row .score-subject {
  flex: 0 0 52px; min-width: 0;
  text-align: left;
  font-size: .78rem; font-weight: 700; color: var(--ink-2);
}
/* R14：等第 pill 组 = 科目名同行的值组件——flex-basis 0 + min-width 0：父行 wrap 按 flex-basis
   断行（此前整组掉到科目名下一行，与分数行「科目名右边」不一致），改 0 基础永远占首行，
   grow 吃满剩余宽、pills 组内换行——与分数输入同列左对齐（科目名 52px + gap 12px = 64px） */
.grade-selector { display: flex; flex-wrap: wrap; gap: 4px; flex: 1 1 0; min-width: 0; }
.grade-option {
  padding: calc(3px * var(--ui-scale, 1)) calc(9px * var(--ui-scale, 1)); font-size: .68rem; color: var(--muted); /* 需求六·item5：等第/年级 pill 随滑块 */
  cursor: pointer; transition: all var(--t-fast); font-weight: 600;
} /* G2：background 交还引擎（玻璃体在元素自身），删元素直写 */
.grade-option:hover { color: var(--ink); }
.grade-option.selected { color: var(--ink); } /* v0.25.24 选中底单源 glass.css（软紫 tint + 紫环，同勾选/标签口径）；文字色 style.css 单源（base/hover/selected 三态同处） */
.score-inline {
  width: calc(70px * var(--ui-scale, 1)); padding: calc(4px * var(--ui-scale, 1)) calc(8px * var(--ui-scale, 1)); border: none; /* 需求六·item5：赋分输入框随滑块 */
  background-color: transparent;
  background-image: linear-gradient(var(--ink), var(--ink));
  background-repeat: no-repeat; background-position: left bottom; background-size: 100% 1.5px;
  font-size: .8rem; text-align: center; outline: none; caret-color: var(--accent);
  transition: background-size .3s var(--ease-snap);
}
.score-inline:focus { background-size: 100% 2px; }
.score-max { font-size: .72rem; color: var(--muted); }

/* ============================================================
   Client 壳 — 可扩展侧边栏 + 页面区
   侧边栏（主页右半同款淡紫）与页面区（米色）仅以颜色为界：无边框线、无投影。
   栏目 hover/active 沿用全站竖条擦入母题（active = 常驻态）。
   ============================================================ */
/* 顶天立地：内层无顶栏，壳占满视口；侧边栏宽 = 屏幕约 1/7.5（较旧版 20vw 收窄 1/3，下限 144px 防窄屏挤爆） */
.client-shell {
  display: grid; grid-template-columns: max(calc(144px * var(--ui-scale, 1)), calc(13.3vw * var(--ui-scale, 1))) 1fr; /* 需求六·item5：侧边栏宽度随滑块（13.3vw 也乘系数——桌面端旧式被 vw 项压制导致滑块无效） */
  height: 100vh; height: 100dvh;
  overflow: hidden;
}

.client-sidebar {
  display: flex; flex-direction: column;
  position: relative; overflow: hidden; /* 滚动交给内层 .sidebar-scroll，背景网格不随之动 */
  isolation: isolate;
} /* G22：background:var(--lilac) 被 glass.css 玻璃条胜，删 */
.sidebar-scroll {
  position: relative; z-index: 1;
  flex: 1; min-height: 0;
  overflow-y: auto;
  display: flex; flex-direction: column;
  padding-top: 18px;
}

/* 栏目区：删绝对定位 .sidebar-pill 覆盖层特例栈——选中高亮由条目自身
   .sidebar-item.active 的 background 承载（流内标准组件，缩放/拖动/重排天然同帧，零 JS 几何）。 */
.sidebar-nav { position: relative; z-index: 1; display: flex; flex-direction: column; gap: calc(16px * var(--ui-scale, 1)); padding: 0; } /* 需求六·item5：卡片间距随滑块 */
.sidebar-item {
  position: relative; z-index: 1; isolation: isolate;
  display: grid; grid-template-columns: auto 1fr; align-items: start; gap: calc(11px * var(--ui-scale, 1)); /* 需求六·item5：卡片内间距随滑块 */
  width: 100%; text-align: left;
  padding: calc(13px * var(--ui-scale, 1)) calc(14px * var(--ui-scale, 1)) calc(13px * var(--ui-scale, 1)) calc(13px * var(--ui-scale, 1)); /* 需求六·item5：卡片尺寸随滑块（原固定 px，滑块拉大后内边距与缩放字号脱节——v0.25.25 归树） */
  color: var(--ink-3);
  transition: color var(--t-base) var(--ease-out), background-color var(--t-base) var(--ease-out),
              padding var(--t-slow) var(--ease-snap);
}
.sidebar-item:hover:not(.active) { color: var(--ink); }
.sidebar-item.active { color: var(--ink); background: var(--g-fill-strong); padding: calc(21px * var(--ui-scale, 1)) calc(14px * var(--ui-scale, 1)) calc(24px * var(--ui-scale, 1)) calc(13px * var(--ui-scale, 1)); } /* 需求六·item5：选中态内边距随滑块；v0.25.94：高亮随条目自身（原 sidebar-pill 的 --g-fill-strong 同档） */
/* 序号：主页 entry 同款亮紫；选中时字号额外增大（黑块随之同步长高） */
.sidebar-item-index {
  font-family: var(--font); font-size: 1.25rem; font-weight: 700; letter-spacing: -.02em;
  line-height: 1.2; color: var(--accent-bright);
  transition: font-size var(--t-slow) var(--ease-snap);
}
.sidebar-item.active .sidebar-item-index { font-size: 1.6rem; } /* G7：删白字（适配旧紫卡），交还 base 亮紫 */
.sidebar-item-body { display: flex; flex-direction: column; min-width: 0; }
.sidebar-item-label {
  display: flex; align-items: center;
  font-size: 1.04rem; font-weight: 700; letter-spacing: -.01em; line-height: 1.3;
  transition: font-size var(--t-slow) var(--ease-snap);
}
.sidebar-item.active .sidebar-item-label { font-size: 1.18rem; }
/* 简介：选中时 0fr→1fr 展开，下方栏目随之流畅退让 */
.sidebar-item-descwrap {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows var(--t-slow) var(--ease-snap);
}
.sidebar-item-desc {
  display: block; overflow: hidden; min-height: 0;
  font-size: .74rem; line-height: 1.5; letter-spacing: .01em;
  color: var(--muted);
  transition: color var(--t-base) var(--ease-out), padding var(--t-slow) var(--ease-snap);
}
.sidebar-item.active .sidebar-item-descwrap { grid-template-rows: 1fr; }
.sidebar-item.active .sidebar-item-desc { color: var(--ink-2); padding-top: calc(6px * var(--ui-scale, 1)); } /* G7：白字交还深色（卡已白化）；需求六·item5：间距随滑块 */
/* 页面顶部 title 旁「i」信息按钮（加小 i 的地方是页面内顶上 title 旁边，不是侧边栏内）：
   selectPage 幂等注入 .page-header h2 后；小圆 i，垂直居中对齐标题行 */
.page-header-info {
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; /* margin-left 删：v0.25.12 间距交给 .page-header-title 组 gap */
  font-size: .66rem; font-weight: 800; line-height: 1; /* v0.25.18：去 font-style:italic——i 用正体（用户反馈斜体多此一举） */
  border-radius: 50%; border: 1px solid var(--faint);
  color: var(--ink-3); cursor: pointer; user-select: none; vertical-align: middle;
  transition: color var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out);
}
.page-header-info:hover { color: var(--ink); border-color: var(--muted); }
.page-header-info:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* 用户信息：白框落地栏底（静态 flex 末位，不参与滚动、不随内容变化位移）；
   上层头像 + id/属性，白框内最下层为运营脚注（细黑体小字，点击直达「关于平台」） */
.sidebar-user {
  position: relative; z-index: 1; flex-shrink: 0;
  display: flex; flex-direction: column;
  padding: calc(13px * var(--ui-scale, 1)) calc(13px * var(--ui-scale, 1)); /* 需求六·item5：用户信息区高度随滑块 */
}
.sidebar-user-top { display: flex; align-items: center; gap: calc(12px * var(--ui-scale, 1)); } /* 需求六·item5：用户卡间距随滑块 */
/* 用户块整体可点（登录态 → 个人信息右栏；访客态 → 登录通路）：button 复位为纯容器 */
.sidebar-user-btn { width: 100%; background: none; border: none; padding: 0; text-align: left; cursor: pointer; font: inherit; color: inherit; }
.sidebar-user-name--guest { color: var(--muted); font-weight: 700; }
.avatar--guest { color: var(--muted); } /* S8/G30：边框唯一主人 = glass.css；元素 background none 与引擎 .glass 基类重复，删 */
.sidebar-user-avatar { width: calc(42px * var(--ui-scale, 1)); height: calc(42px * var(--ui-scale, 1)); font-size: 1.15rem; } /* 需求六·item5：头像随滑块 */
.sidebar-user-text { min-width: 0; }
.sidebar-user-name { font-weight: 800; font-size: 1rem; color: var(--ink); letter-spacing: -.01em; overflow-wrap: anywhere; }
.sidebar-user-role { margin-top: 3px; font-size: .7rem; font-weight: 600; color: var(--muted); letter-spacing: .1em; }
.sidebar-footnote {
  width: 100%; margin-top: 11px; padding-top: 9px;
  border-top: 1px solid var(--g-line-dark);
  text-align: left; cursor: pointer;
  font-size: .62rem; line-height: 1.7; font-weight: 300; letter-spacing: .02em;
  color: var(--g-foot-text);
  transition: color var(--t-fast) var(--ease-out);
}
.sidebar-footnote:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

.sidebar-close { display: none; margin: 8px 10px 6px; padding: 10px 14px; color: var(--muted); font-size: .8rem; font-weight: 600; text-align: left; }
.sidebar-close:hover { color: var(--ink); }

/* 侧边栏展开/收起箭头：仅移动端（≤860px）启用，见媒体查询 */
.sidebar-expand-toggle { display: none; }

/* 侧边栏网格装饰：钉死在侧边栏盒底的背景层（内容在 .sidebar-scroll 内滚动，
   选项卡增宽退让完全不触碰它）；主页同款 44px 细网格，底部实、向上渐隐 */
.sidebar-deco-grid {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 0;
  height: 46%; min-height: 150px;
  pointer-events: none;
  background-image:
    linear-gradient(var(--g-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--g-grid) 1px, transparent 1px);
  background-size: 44px 44px;
  -webkit-mask-image: linear-gradient(to top, #000 55%, transparent 100%);
          mask-image: linear-gradient(to top, #000 55%, transparent 100%);
}

/* 抽屉遮罩：仅移动端启用（见 Responsive） */
.sidebar-backdrop {
  position: fixed; inset: 0; z-index: 140;
  opacity: 0; pointer-events: none; transition: opacity var(--t-base) var(--ease-out);
  display: none;
} /* G22：background 移动端被 glass.css:314 胜（桌面端 display:none），删 */
body.sidebar-open .sidebar-backdrop { opacity: 1; pointer-events: auto; }

.client-main { background: transparent; overflow-y: auto; padding: 28px clamp(20px, 4vw, 40px) 56px; }
.client-page { max-width: 920px; margin: 0 auto; animation: fade-in .2s ease; }
/* 通栏页（我的会话）：三栏贴边零间隙，独占整高；沟通页自身负责内部布局 */
.client-page--flush { max-width: none; margin: 0; height: 100%; animation: none; }
.client-page--flush .page-header { display: none; }
.client-page--flush > div { height: 100%; }
#client-main:has(.client-page--flush:not(.hidden)) { padding: 0; overflow: hidden; }
.page-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 20px; flex-wrap: wrap; }
.page-header h2 { font-size: 1.35rem; font-weight: 900; letter-spacing: -.02em; color: var(--ink); }
/* 标题 + i 按钮同组靠左（.page-header 为 space-between，i 直接插 h2 后会被顶到最右） */
.page-header-title { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
/* 页头右侧操作按钮组（通知页：屏蔽系统通知 + 发通知）：整体右对齐，窄屏自然换行 */
.page-header-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* 系统广播通知：标题加粗成行，正文另起一行灰小字（pre-wrap 保留换行） */
.notif-broadcast-title { display: block; font-weight: 800; font-size: .84rem; color: var(--ink); line-height: 1.5; }
.notif-broadcast-body { display: block; margin-top: 5px; font-size: .78rem; color: var(--ink-3); line-height: 1.65; white-space: pre-wrap; }

/* 关于平台：logo 卡片同信息卡左区布局；用法块细线分隔；支持卡含反馈入口 */
.about-card { display: flex; gap: 22px; align-items: flex-start; }
.about-logo { width: 52px; height: 52px; gap: 7px; flex-shrink: 0; }
.about-card-body { min-width: 0; }
.about-title { font-size: 1.05rem; font-weight: 900; letter-spacing: -.01em; color: var(--ink); margin-bottom: 10px; }
.about-text { font-size: .86rem; color: var(--ink-3); line-height: 1.75; }
/* 需求四：平台不走资金声明——关于页「我们是谁」卡内醒目分块（弱纸面 + 平台色左缘条，非警告） */
.about-funds { margin-top: 14px; padding: 12px 14px; border-radius: var(--lg-r-sm); background: var(--g-fill-weak); } /* 2026-08-09 反馈：左竖线强调连根删，卡片存在本身足够 */
.about-funds-title { font-size: .82rem; font-weight: 800; color: var(--accent-deep); margin-bottom: 6px; }
.about-funds-text { font-size: .8rem; color: var(--ink-3); line-height: 1.7; }
/* 需求四：资金触点浮窗（签约/起草合同）内的同款声明——弱纸面 + 平台色左缘条，用户必见 */
.funds-note { margin: 4px 0 0; padding: 8px 11px; border-radius: var(--lg-r-sm); background: var(--g-fill-weak); font-size: .74rem; color: var(--ink-3); line-height: 1.6; } /* 2026-08-09 反馈：同删左竖线 */
.about-card-block + .about-card-block { margin-top: 0; }
/* 平台基本用法卡底部：重温新手引导按钮 */
.about-flow-revisit { margin-top: 16px; display: flex; gap: 10px; }
.about-support-lines { font-size: .82rem; color: var(--ink-3); line-height: 2; margin-bottom: 16px; }
.about-feedback-btns { display: flex; gap: 10px; }
/* 详细用法介绍浮窗：分区标题 + 段落，行距舒适 */
.usage-guide { display: flex; flex-direction: column; gap: 14px; }
.usage-guide-section { display: flex; flex-direction: column; gap: 6px; }
.usage-guide-title { font-size: .92rem; font-weight: 800; letter-spacing: .02em; color: var(--ink); }
.usage-guide-text { font-size: .82rem; line-height: 1.75; color: var(--ink-2, #444); }
/* 关于平台 · 安全与隐私保护：「小盾标 + 粗体小标题 + 一句白话」逐条，建立学生与家长的信任 */
.about-security-list { display: flex; flex-direction: column; margin-top: 14px; }
.about-sec-item { display: flex; gap: 12px; align-items: flex-start; padding: 11px 0; }
.about-sec-item + .about-sec-item { border-top: 1px solid var(--paper-3); }
.about-sec-mark {
  flex-shrink: 0; width: 22px; height: 22px; margin-top: 1px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent-deep);
  font-size: .72rem; font-weight: 900; /* 圆角交还引擎 --g-r: 50%（glass.css 单点），删此处重复直写 */
}
.about-sec-mark::after { content: '✓'; }
.about-sec-body { min-width: 0; }
.about-sec-title { display: block; font-size: .84rem; font-weight: 800; color: var(--ink); margin-bottom: 3px; }
.about-sec-desc { font-size: .78rem; color: var(--ink-3); line-height: 1.7; margin: 0; }

/* A1 审计：.feedback-kind-row 已删——M11 后 openFeedbackModal 仅从 chooser 三选进入
   （kind 固定），内层 Bug/建议 切换 tab 是冗余入口（chooser 选择可被推翻），连根移除 */

/* 管理员反馈卡：Bug 左侧红色警示边 + 浅红底；已处理整卡淡出 */
.feedback-card--resolved { opacity: .62; }
.feedback-content { white-space: pre-wrap; }
.feedback-tags { display: inline-flex; gap: 6px; }
.feedback-foot { margin-top: 10px; display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }

/* ============================================================
   需求六·item5 UI 大小滑块（liquid glass 风格，独立类名防作用域污染）——
   方案参考（2026-08 web 调研，CLAUDE.md「新机制先上网查」铁律）：
     - 原生 <input type=range> + ::-webkit/moz-slider-* 伪元素定制轨道/拇指（纯 CSS 玻璃，
       无 JS 重绘，保持键盘/读屏可达性）——来源：educative.io CSS Design Patterns Glass Range Slider、
       CSS Glassmorphism Generator 实现综述；
     - 轨道半透明玻璃底 + 品牌紫填充渐变（--ui-fill 由 JS 写 CSS 变量）+ 液体边缘 --g-liquid-sm
       （复用本站玻璃 token，与表单控件同视觉同源）；
     - 拇指 = 弯月径向玻璃珠（--g-card-fill + --g-liquid-sm + 白描边）。
     交互：原生 input 拖动即与手部 x 轴同步（滑块本体不随 --ui-scale 缩放，保证任何 UI 大小时可抓取）。
   ============================================================ */
.ui-scale-row { align-items: center; }
.ui-scale-control { display: flex; align-items: center; gap: 12px; flex: 0 1 240px; min-width: 0; }
.ui-scale-slider {
  -webkit-appearance: none; appearance: none;
  flex: 1; min-width: 0; height: 8px; margin: 0;
  border: none; border-radius: 999px; background: transparent;
  cursor: pointer;
}
.ui-scale-slider::-webkit-slider-runnable-track {
  height: 8px; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent) var(--ui-fill, 100%), var(--g-fill-weak) var(--ui-fill, 100%));
  box-shadow: var(--glass-lift-sm), var(--g-liquid-sm);
}
.ui-scale-slider::-moz-range-track {
  height: 8px; border-radius: 999px;
  /* 空轨从透明白改中性深线（--g-line-dark）+ 发丝边——UI 大小拉到 80% 时
     --ui-fill=0% 全轨为空段，原透明白叠加近白玻璃卡上不可辨；中性线任意填充率下都可见 */
  background: linear-gradient(90deg, var(--accent) var(--ui-fill, 100%), var(--g-line-dark) var(--ui-fill, 100%));
  box-shadow: var(--glass-lift-sm), var(--g-liquid-sm), inset 0 0 0 1px var(--g-line-dark);
}
.ui-scale-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 20px; height: 20px; border-radius: 50%;
  margin-top: -6px; /* 垂直居中在 8px 轨道上 */
  /* v0.25.10：拖动球改淡紫（--g-slider-thumb 单源 THEME light/dark）——原白玻璃珠在 80% 空轨上白对白不可辨 */
  background: var(--g-slider-thumb, var(--g-card-fill)), var(--g-fill-strong);
  box-shadow: var(--glass-lift-sm), var(--g-liquid-sm), inset 0 0 0 1px var(--g-avatar-border);
  cursor: grab; transition: box-shadow var(--t-fast) var(--ease-out);
}
.ui-scale-slider::-moz-range-thumb {
  width: 20px; height: 20px; border: none; border-radius: 50%;
  background: var(--g-slider-thumb, var(--g-card-fill)), var(--g-fill-strong);
  box-shadow: var(--glass-lift-sm), var(--g-liquid-sm), inset 0 0 0 1px var(--g-avatar-border);
  cursor: grab;
}
.ui-scale-slider:active::-webkit-slider-thumb { box-shadow: var(--glass-lift-sm), 0 0 0 3px var(--g-focus-soft), inset 0 0 0 1px var(--g-avatar-border); }
/* ============================================================
   v0.26.5 B3 UI 大小拖动真实页面分块缩放（用户返工 B3：删预览图 mockup，
   「原来的组件冻结、整体缩放逻辑是可以的，只是要分三块以保证边缘位置不动」）：
   拖动期 JS 只写 --ui-preview-scale + html[data-ui-previewing] 门控，真实页面
   顶栏（.navbar）/侧栏（头 .sidebar-expand-toggle+.sidebar-scroll、脚 .sidebar-user）/
   内容区（.client-main）由 CSS 分块 transform: scale(var(--ui-preview-scale)) 消费
   （transform 合成器只读——零 reflow 零重绘真实页面，帧率不受拖动影响）。
   区域锚点（用户要求）：顶栏/侧栏头 left top（左上）、侧栏脚 left bottom（左下）、
   内容区 right top（右上）。预览期块间错位/缝隙是预览本性（各块独立缩放、向锚点对侧展开），
   松手 commit 才一次性落 --ui-scale 真排版对齐。门控保证平时无 transform——
   即使 scale(1) 也会建 stacking context / containing block（干扰 fixed 定位），不能常驻。
   ============================================================ */
html[data-ui-previewing] .navbar,
html[data-ui-previewing] .sidebar-expand-toggle,
html[data-ui-previewing] .sidebar-scroll {
  transform: scale(var(--ui-preview-scale, 1));
  transform-origin: left top;
  will-change: transform;
}
html[data-ui-previewing] .sidebar-user {
  transform: scale(var(--ui-preview-scale, 1));
  transform-origin: left bottom;
  will-change: transform;
}
html[data-ui-previewing] .client-main {
  transform: scale(var(--ui-preview-scale, 1));
  transform-origin: right top;
  will-change: transform;
}
/* 采样必须禁全站 transition——.sidebar-item 等有 padding var(--t-slow) 过渡，
   设 --ui-scale 后 padding 停在动画起点，同帧读 rect 读到旧高度（生产实测采样 h=50 vs 实际 60），
   box target 全错。html[data-ui-sampling] 只在 ui-scale-reflow sampleTargets 期间挂载（JS 管理），
   平时零影响；禁全站 transition 即让采样读到真实 reflow 后的几何。 */
html[data-ui-sampling] *,
html[data-ui-sampling] *::before,
html[data-ui-sampling] *::after {
  transition: none !important;
}
/* V-3-1c2：reflow 引擎每单元 transform 走 --ui-rf-transform 自定义属性数据通道（JS setProperty，
   样式声明零内联）；identity 单元置 none（不建 stacking context，与 v1 跳过规则语义等价）。
   门控 html[data-ui-reflowing] 仅拖动预览期由 state.js 挂载（与 data-ui-previewing 互斥），
   平时 transform 归 none 零干扰。特异性注记：属性选择器不论带值与否均为 (0,1,0)（审计校正
   a9d413da）——本规则与旧注入式特异性相同，真实差异在源序：旧注入样式排 head 末尾，本规则
   在 base.css 偏前，其后源序的同特异性 transform 规则可能胜出；已实证当前 CSS 无此类规则命中
   单元类，后续新增需自查。 */
[data-ui-reflow-unit] { transform-origin: 0 0; transform: var(--ui-rf-transform, none); }
html[data-ui-reflowing] [data-ui-reflow-unit] { transition: none !important; }
.ui-scale-slider:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.ui-scale-val { flex: 0 0 auto; font-size: .82rem; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; min-width: 38px; text-align: right; }
/* 新手引导浮窗：内测政策小盾标逐条，同关于页安全区语言 */
.onboard-intro { font-size: .88rem; color: var(--ink-3); line-height: 1.75; margin-bottom: 12px; }
.onboard-policy { display: flex; flex-direction: column; }
.onboard-policy-item { display: flex; gap: 12px; align-items: flex-start; padding: 9px 0; }
.onboard-policy-item + .onboard-policy-item { border-top: 1px solid var(--line); }
.onboard-policy-item p { font-size: .82rem; color: var(--ink-3); line-height: 1.65; }
/* 登录设备管理（v1.4.16：设置栏 → 底部按钮 + 浮窗）；设备行样式浮窗内复用 */
.settings-hint { font-size: .72rem; color: var(--muted); margin: -1px 0 10px; } /* 设置页各行提示（主题/风格/光球/设备） */
.settings-bottom-actions { display: flex; gap: var(--sp-3); margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px solid var(--g-line-soft); }
.settings-bottom-actions .settings-logout { flex: 1; }
.settings-bottom-actions .settings-devices-btn { flex: 1; }
.device-manager-modal { max-width: 460px; }
.device-manager-body .device-row { padding: 10px 0; }
.device-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 11px var(--sp-2); border-top: 1px solid var(--g-line-soft); /* v0.31.7 横线统一 */
}
.device-row:first-child { border-top: none; }
.device-info { min-width: 0; }
.device-label { font-size: .86rem; font-weight: 600; color: var(--ink); display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.device-current {
  font-size: .62rem; font-weight: 700; letter-spacing: .05em; color: var(--accent, #6B5BD2);
  padding: 1px 6px;
} /* G11：删直写 border/border-radius，交还引擎 --g-r:999px 药丸 */
.device-meta { font-size: .72rem; color: var(--muted); margin-top: 2px; font-variant-numeric: tabular-nums; }

/* 汉堡按钮：桌面隐藏；≤860px 且处于壳内时由 body:has 启用 */
.sidebar-toggle {
  display: none; width: 36px; height: 36px; flex-direction: column;
  align-items: center; justify-content: center; gap: 4px;
  flex-shrink: 0;
  transition: background-color var(--t-fast) var(--ease-out);
}
.sidebar-toggle span { display: block; width: 16px; height: 2px; background: var(--ink); }

/* 需求卡头部工具区（日期 + 编辑按钮） */
.demand-card-tools { display: inline-flex; align-items: center; gap: var(--sp-3); }

/* 需求卡底部行：联系方式 + 意向开关（学生「我的需求」，按钮靠右下贴近意向栏） */
.demand-card-foot {
  margin-top: var(--sp-3); padding-top: var(--sp-3); border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap;
}
.demand-card-foot .list-card-contact { margin-top: 0; padding-top: 0; border-top: none; }
/* 卡片操作按钮统一右下角、独占底栏右侧（与左侧说明文案同排） */
.demand-card-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-2); flex-wrap: wrap; min-width: 0; }

/* 统一下拉开关：透明底 + 右侧 v 形箭头（展开翻转 180°），
   替换试课意向 / 筛选等一切「展开/收起栏目」按钮 */
/* .drop-toggle 基础规则连根删——全站 3 处（教师/需求页头筛选 toggle + my-demands 意向
   展开）已接入 .btn .btn-soft 按钮组件（透明磨砂+12px 与相邻按钮同族），该独立样式族零消费者。 */
/* 「所有本质上是按钮而非输入框的下拉栏组件都应该用按钮配置」）：
   页头排序下拉 / 筛选面板选项下拉在 JS 端已挂 .btn .btn-soft .glass .glass--pressable——
   标准按钮玻璃面（透明磨砂透镜+弯月环+白洗 hover+涟漪+12px 圆角）由按钮组件提供。
   Q7曾在此设 --g-fill/--g-frost 引擎变量但不挂 .glass：引擎不消费，只显高度/字重，
   观感仍是输入框（用户：「单纯统一高度到40px是没法解决观感问题的」）。本层只留按钮语境的布局适配；
   表单/其他面板下拉保持输入控件族（无 .btn/.glass，不受影响）。 */
.page-header-actions .custom-select-trigger {
  --g-r: var(--lg-r); /* 与 .btn 按钮同圆角（引擎默认 --lg-r-sm 9px；页头无 12px 继承，须显式对齐按钮） */
  justify-content: center; gap: 8px;
  height: var(--btn-h); /* 标准按钮高度（与并列按钮/筛选开关同高） */
  width: auto;
  color: var(--ink); /* 按钮字色（--g-fg 由 .btn-soft 提供，color 兜底） */
  font-size: .875rem; font-weight: 600; letter-spacing: .01em; /* 标准按钮字面（同 .btn） */
  padding: calc(7px * var(--ui-scale, 1)) calc(12px * var(--ui-scale, 1));
  min-width: calc(120px * var(--ui-scale, 1)); /* K1 排序下拉定宽随滑块 */
}
/* 下拉箭头随按钮字色（非灰 --faint，与按钮内图标同色惯例） */
.page-header-actions .custom-select-trigger .drop-caret,
.filter-group .custom-select-trigger .drop-caret { color: currentColor; }
.page-header-actions .custom-select { flex: none; }
/* 页头筛选按钮（已接 .btn .btn-soft 组件，透明磨砂+12px 与排序下拉同族）——
   仅留页头布局适配：标准按钮高度/字面/圆角对齐（--g-r 12px 同排序下拉，非 .drop-toggle 旧 9px 实心面） */
.page-header-actions .filter-toggle {
  --g-r: var(--lg-r);
  height: var(--btn-h); /* 标准按钮高度（与相邻排序下拉同高，不再矮一截） */
  font-size: .875rem; font-weight: 600; letter-spacing: .01em;
  color: var(--ink);
  padding: calc(7px * var(--ui-scale, 1)) calc(12px * var(--ui-scale, 1));
  min-width: calc(90px * var(--ui-scale, 1)); /* K1 筛选按钮定宽随滑块 */
  justify-content: center;
}
/* 筛选项下拉栏（筛选面板内 filter-group 的选项下拉）：紧凑按钮字面（面板内小空间） */
.filter-group .custom-select-trigger {
  --g-r: var(--lg-r);
  justify-content: center; gap: 8px;
  height: var(--btn-h); /* 标准按钮高度（筛选项下拉与排序/筛选按钮同高） */
  width: auto;
  color: var(--ink);
  font-size: .8rem; font-weight: 600; letter-spacing: .01em;
  padding: calc(4px * var(--ui-scale, 1)) calc(10px * var(--ui-scale, 1));
  min-width: calc(90px * var(--ui-scale, 1)); /* K1 筛选项下拉定宽随滑块 */
}
.drop-caret { display: inline-flex; transition: transform .28s var(--ease-snap); }
/* T1：预览期文本包裹 span——容器定宽 + 文字等比两层。transform 对 inline 无效，必须 inline-block
   （collectUnits 包入、teardown 还原，正常 DOM 无此元素） */
.ui-reflow-text { display: inline-block; }

/* 开关右上角红点：待处理意向等未读标记 */
.corner-dot { position: absolute; top: 0; right: 0; width: 8px; height: 8px; border-radius: 50%; background: var(--danger); }

/* 通用展开容器：grid-rows 0fr→1fr 开合动效（筛选栏等统一走这套）。
   内容须包在无内边距的 .drop-clip 内——带 padding 的子项在 0fr 态会泄漏高度；
   展开态放开 overflow，让内部自定义下拉面板能探出筛选栏（z-index 40 盖住下方卡片） */
.drop-wrap { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .32s var(--ease-snap); }
.drop-wrap.open { grid-template-rows: 1fr; }
.drop-clip { overflow: hidden; min-height: 0; }
.drop-wrap.open .drop-clip { overflow: visible; }

/* 侧边栏未读红点（语义圆点）：钉在条目右上角——窄栏形态下依然可见 */
.sidebar-dot { position: absolute; top: 8px; right: 13px; width: 7px; height: 7px; border-radius: 50%; background: var(--danger); }

/* 教师意向按钮状态：待处理灰（禁点）；已建立联系→绿可点击跳会话（R26，光标指针由 glass--pressable 提供）。
   opacity 不随 :disabled 衰减 */
.btn-intent-wait { cursor: default; }
.btn-intent-wait:disabled, .btn-intent-ok:disabled { opacity: 1; }

/* 需求卡内嵌意向列表（模块3）：grid-rows 0fr→1fr 展开动效，内容淡入 */
.intents-box { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .3s var(--ease-out); }
.intents-box.open { grid-template-rows: 1fr; }
.intents-box-inner { overflow: hidden; min-height: 0; }
.intents-box-content {
  margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--border-light);
  opacity: 0; transition: opacity .25s var(--ease-out) .06s;
}
.intents-box.open .intents-box-content { opacity: 1; }
.intents-box .admin-row { margin-top: var(--s2); }

/* 管理面板邀请码条（已迁入侧边栏，留空占位防孤儿注释）*/

/* 教师信息展示（卡片与弹窗共用）：无深色框；灰小标题 + 纵向极细分隔行 */
.section-title { font-size: .72rem; font-weight: 700; color: var(--muted); letter-spacing: .08em; margin-bottom: 2px; }

/* 教师卡悬停聚焦动效已取消（信息展示卡保持静态、错落） */

/* ============================================================
   Modal — 白实心直角，墨色顶条，无毛玻璃
   ============================================================ */
.modal-overlay {
  position: fixed; inset: 0;
  display: flex; overflow-y: auto; /* 整页滚动上移到 overlay（去表头独立层后模态不再内滚）；
    .modal 用 margin:auto 居中——内容高于视口时 auto margin 归零、从顶部自然滚动 */
  z-index: 200; padding: 20px;
} /* G22：background 被 glass.css:297 毛玻璃胜，删；v0.19.37：fade-in opacity 帧连根删——
    overlay 是 .modal 的祖先，opacity 动画期间整子树合成 → modal 的 backdrop-filter 采样失效（Chromium 983252，
    v0.19.33 只改了 modal 自身的动画没改 overlay）→ 弹窗打开前 0.2s 是白板=「不毛」第一印象。
    删动画后与 profile-panel 路径同构：无 opacity 帧，backdrop 全程正常采样 */
#modal-container .modal {
  /* h5a-g2: default max-width mirrors CONFIG.MODAL_W_ONBOARD (src/shared/config.js);
     onboarding passes that same width via ui-modal cssText. Keep both in sync —
     locked by test/modal-width-parity.test.js. */
  width: 100%; max-width: 580px;
  margin: auto; position: relative; /* v0.25.10：max-height/内滚已删——滚动交 overlay */
  animation: modal-in .32s var(--ease-snap); /* v0.19.37：删 both——终态 transform 归 none，合成层释放（同 profile-panel 路径） */
  /* 需求三十一：纯文本浮窗拓宽——长文阅读舒适（政策/合同/使用指南/预览等文本浮窗 opt-in）；
     width:100% 保证移动端仍受视口约束（max-width 只提升上限，窄屏天然不触发），不担心过宽 */
  /* 玻璃引擎 hover 规则（.glass:hover box-shadow，
     玻璃.css 后载且特异性 0,2,0）否则会盖掉本压暗、悬停弹窗即闪去灰化（审计发现） */
  box-shadow: var(--g-lift), var(--g-liquid, none), var(--g-surface, none), 0 0 0 200vmax var(--g-modal-dim, rgba(17, 17, 20, .42));
}
/* 需求三十一：纯文本浮窗拓宽（opt-in 类）——政策/合同/使用指南/预览等长文阅读更舒适；
   移动端由 width:100% 兜住视口（max-width 只提上限，窄屏天然不触发），不会过宽 */
#modal-container .modal.modal--wide { max-width: 760px; }
.modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 22px 24px 16px;
} /* 去独立玻璃层/分隔线/sticky——标题直接坐弹窗顶端，整页滚动，无内滚通道 */
.modal-header h2 { font-size: 1.15rem; font-weight: 700; letter-spacing: -.01em; color: var(--ink); } /* v1.4.0：字重 800→700（原理#42 字重纪律：600/700 并存是混乱，标题用字号不用字重堆层次） */
.modal-body { padding: 20px 24px 24px; }
.modal-footer { margin-top: 22px; display: flex; gap: 10px; justify-content: flex-end; }
/* 任务三需求表单 wizard：圆点步进进度条 + 分步页 + 页脚。
   v0.31.7 R3 重构（用户要求「页面切换用侧滑+淡出入而非无动画；进度点用线串起来」）：
   sliding track——8 步并排 flex，JS 只写 --dw-step-active（0 基索引）到 #demand-form，
   track translateX(calc(var(--dw-step-active) * -100%)) 侧滑（合成器只读），步内淡入淡出。
   视口定高内滚（min-height 340 + max-height 56vh）——页面间高度不再跳变（统一高度）。 */
.dw-stepper { display: flex; align-items: flex-start; gap: 0; margin-bottom: 20px; padding: 4px 0 2px; }
.dw-step-chip { display: flex; flex-direction: column; align-items: center; gap: 5px; flex: 1;
  min-width: 0; padding: 6px 2px 4px; position: relative; }
.dw-step-chip:not(:first-child)::before { content: ''; position: absolute; top: 10px; left: calc(-50% + 7px);
  width: calc(100% - 14px); height: 2px; background: var(--g-border, rgba(0,0,0,.08));
  z-index: 0; transition: background .2s; }
.dw-step-chip-dot { width: 14px; height: 14px; border-radius: 50%; background: var(--g-fill-weak, var(--g-paper));
  border: 2px solid var(--g-border, rgba(0,0,0,.18)); position: relative; z-index: 1;
  transition: background .2s, border-color .2s, box-shadow .2s; }
.dw-step-chip-label { font-size: .7rem; color: var(--muted); white-space: nowrap; opacity: .8;
  transition: color .2s, opacity .2s; }
/* 连接线推进 = done∪visited 连续前缀实紫（JS 挂 --lined），非前缀孤立 done 点实紫但连线浅——
   进度条不跟当前页、也不跳段（用户「进度条推到哪里逻辑同上，不要跟着当前停留页走」）。 */
.dw-step-chip--lined::before { background: var(--accent, #6B5BD2); }
/* done 曾用 --g-fill-strong（半透白透镜，
   light 浅底上合成后不实、与未到达点区分弱）。改实色 accent（主题紫）——三态分明：未到达=浅描边空心、
   已完成=实紫、当前=墨实+光圈。连接线 done 段已实色（--g-fg），色系自洽。 */
.dw-step-chip--done .dw-step-chip-dot { background: var(--accent, #6B5BD2); border-color: var(--accent, #6B5BD2); }
.dw-step-chip--done .dw-step-chip-label { color: var(--ink); opacity: 1; }
.dw-step-chip--active .dw-step-chip-dot { background: var(--g-fg, var(--ink)); border-color: var(--g-fg, var(--ink));
  box-shadow: 0 0 0 3px var(--g-focus-soft, rgba(0,0,0,.12)); }
.dw-step-chip--active .dw-step-chip-label { color: var(--ink); opacity: 1; font-weight: 700; }
.dw-steps-viewport { overflow-x: hidden; overflow-y: auto; min-height: 340px; max-height: 56vh; padding: 2px 4px; }
.dw-steps-track { display: flex; transform: translateX(calc(var(--dw-step-active, 0) * -100%)); transition: transform .32s var(--ease-out, ease); }
/* JS 写 --dw-step-active（0 基索引）到 #demand-form，本规则 translateX 消费——
   曾漏写 transform 属性（只有 transition），8 步并排后 P2-P8 全被视口 overflow-x:hidden 裁剪，表单空白。 */
.dw-step { flex: 0 0 100%; min-width: 100%; visibility: hidden; opacity: 0; transform: translateY(8px);
  transition: opacity .28s ease, transform .28s ease, visibility 0s linear .28s; }
.dw-step--active { visibility: visible; opacity: 1; transform: none;
  transition: opacity .28s ease, transform .28s ease; }
.dw-footer { margin-top: 22px; display: flex; gap: 10px; justify-content: flex-end; align-items: center; flex-wrap: wrap; }
.dw-footer .btn-text-danger { margin-right: auto; }
/* 非学科技能现状文本框（每勾选项目一行，标签 + 输入） */
.skill-note-row { margin-bottom: 10px; }
.skill-note-label { font-size: .78rem; font-weight: 600; color: var(--ink); display: block; margin-bottom: 4px; }
.skill-note-input { width: 100%; }
@media (max-width: 480px) {
  .dw-step-chip-label { display: none; } /* 窄屏只留圆点步进 */
}
/* 确认弹窗正文（confirm() 原语）：统一间距，表头无独立层后正文自然流；
   AI-9: pre-wrap 支持结构化多行危险正文（\n + · 行列表），既有单行 confirm 零影响 */
.confirm-msg { margin: 0 0 16px; white-space: pre-wrap; line-height: 1.7; }
/* 二次认证密码行（原内联 style 改类）：去 .form-group 上分隔线 + 错误行红字显隐 */
.reauth-group { border-top: none !important; }
.form-hint--error { color: var(--danger); }
/* 表单辅助说明：小字灰，只做引导不做主视觉（注册页登录凭证说明等） */
.form-hint { margin: 6px 0 0; font-size: .76rem; line-height: 1.5; color: var(--muted); }
/* v0.19.33：去 opacity 帧——Chromium bug 983252：元素自身 backdrop-filter + opacity 动画 → backdrop 渲染失效（毛玻璃变白板）。
   纯 transform 动画（profile-panel 路径）不触发，modal 复刻之
   v0.19.37：删 fill both——动画结束后 transform 不再常驻 translateY(0)，合成层释放，backdrop 回普通渲染路径；
   与 profile-panel 的 transition（终态归 none）完全同构 */
@keyframes modal-in { from { transform: translateY(18px); } to { transform: translateY(0); } }

/* ============================================================
   新手引导多步走（v0.25 需求三）：全屏灰化 + 亮区洞 + 文字气泡
   层高纪律：z-index 400 覆盖 modal(200) / profile-panel(150) / 侧栏遮罩(140) / navbar(100)。
   JS 只切类 + transform 定位亮区；压暗由 .tour-hole 的 box-shadow 承担（真孔透视，目标可点）。
   毛玻璃纪律：气泡是 backdrop-filter 子树，入场用纯 transform animation（复刻 modal-in），
   禁 transition（Chromium 983252 冻结首帧）。类名独立 .tour- 前缀防作用域后代选择器污染。
   ============================================================ */
.tour-overlay {
  position: fixed; inset: 0; z-index: 400;
  /* v1.4.7（用户反馈：遮罩两层、亮区也灰）：overlay 无常驻背景——压暗只由 .tour-hole 的 box-shadow
     承担（洞内透明干净，洞外 .4 一层）。洞隐藏时（等待/retry）由 .tour-overlay--dim 弱压暗占位防闪回
     （需求五十三初衷保留，但不再全屏常驻造成两层）。 */
}
.tour-overlay--dim { background: rgba(17, 17, 20, .28); } /* 洞隐藏占位（_tourHideHole 加 / _tourPlace 撤） */
.tour-hole {
  position: fixed; left: 0; top: 0; z-index: 2;
  width: 0; height: 0; opacity: 0;
  border-radius: var(--lg-r);
  pointer-events: none; /* 隐藏态不挡点击 */
  /* 需求五十三：亮区延时——遮罩先落，亮区延迟淡入（洞无 backdrop-filter，opacity transition 无 983252 风险） */
  transition: opacity .26s ease-out .16s;
}
.tour-hole--show {
  opacity: 1; pointer-events: auto; /* 亮区可点：引擎透传真实点击给目标本体 */
  box-shadow: 0 0 0 200vmax rgba(17, 17, 20, .4); /* 200vmax 恒盖满视口（含对角），洞内透明透视目标；
     总压暗 = overlay .28 + 洞外 .4 ≈ .57（与原 .55 同量级），洞内仅 .28 保持聚光对比 */
}
/* 气泡层高于亮区洞（z 3 > 2）：否则会被洞的 200vmax box-shadow 压暗成「被灰化层压住」（需求三·3 bug 根因）。
   pointer-events:none 让点击穿过气泡：与洞重叠时仍点到洞（H1 兜底），不重叠时落到 overlay 点击拦截层。 */
.tour-bubble-pos { position: fixed; left: 0; top: 0; z-index: 3; pointer-events: none; }
/* 气泡玻璃观感直接用 CSS 变量（同 .modal 预设配方），不套 .glass 基类——基类带
   transform transition + hover 抬升，对 backdrop-filter 子树有 983252 冻结风险；
   纯 transform animation 入场（复刻 modal-in），禁 transition */
.tour-bubble {
  position: relative;
  width: min(300px, calc(100vw - 32px));
  padding: 14px 16px;
  border-radius: var(--lg-r);
  /*——灰底上玻璃必须额外提亮：
     标准 --g-paper（.22）叠 200vmax 暗影上发灰，换 --g-paper-bright 高不透明白面 */
  background: var(--g-paper-bright, var(--g-paper));
  -webkit-backdrop-filter: var(--g-f-modal, blur(16px) saturate(180%) brightness(1.04));
  backdrop-filter: var(--g-f-modal, blur(16px) saturate(180%) brightness(1.04));
  box-shadow: var(--glass-lift), var(--g-liquid, none);
  animation: modal-in .32s var(--ease-snap); /* 纯 transform，复刻 modal-in（983252 安全路径） */
  /* 需求五十三：气泡随亮区延迟入场——backwards 使延迟期持 from 态，动画结束后不留 fill（同 v0.19.37 删 both 的理由） */
  animation-delay: .18s;
  animation-fill-mode: backwards;
}
.tour-bubble-text { font-size: .85rem; line-height: 1.7; color: var(--ink-2); }
/* 右上角全局「跳过引导」按钮（需求三·6）：引导全程常亮，z 高于一切（overlay 内最高），
   固定定位右上角不随页面滚动；纯客户端跳转，无毛玻璃子树动画风险 */
.tour-global-skip {
  position: fixed; top: 14px; right: 14px; z-index: 5;
  padding: 8px 14px;
  border: 1px solid var(--g-line-dark); border-radius: var(--lg-r-sm);
  background: var(--g-paper-bright, var(--g-paper)); /* v0.25.12：压暗灰底上的玻璃提亮（同气泡） */
  font-size: .78rem; font-weight: 700; letter-spacing: .04em; color: var(--ink-2);
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.tour-global-skip:hover { background: var(--g-hover-wash); color: var(--ink); }
.contract-demo-head { font-weight: 700; font-size: .95rem; color: var(--ink); }
.contract-demo-hint { font-size: .8rem; color: var(--ink-2); line-height: 1.55; margin: 6px 0 10px; } /* v1.4.9：示例合同卡提示（展示组件骨架） */

/* 需求五十三：减弱动效下亮区/气泡的延迟归零（全局规则只压 duration，transition/animation-delay 需显式清） */
@media (prefers-reduced-motion: reduce) {
  .tour-hole { transition-delay: 0s; }
  .tour-bubble { animation-delay: 0s; }
}

/* 星级输入 */
.star-rating-input { flex: 1; display: flex; justify-content: flex-end; gap: 4px; font-size: 1.5rem; cursor: pointer; }
.star-rating-input .star-btn { color: var(--star-empty); transition: color var(--t-fast); background: none; border: none; cursor: pointer; padding: 0; }
.star-rating-input .star-btn.active { color: var(--star); }
.star-rating-input .star-btn:hover { color: var(--star); }

/* v0.25.99：Alert 提示条组件连根删——表单校验/错误/成功提示全站改走底部 Toast（showToast 全风格）。
   原 .alert/.alert-error/.alert-success/.alert-warn 及 --g-surface 左竖条一并清除（见 glass.css 删除记录） */
/* 独立静态提示（非浮层）：教师端高考政策不匹配警告，渲染进成绩区持久显示（区域编辑器 gaokao-mismatch-warn） */
.gaokao-mismatch-warn {
  --g-fill: var(--g-warn-fill); --g-fg: var(--warn-deep); --g-r: var(--lg-r-sm);
  padding: 11px 14px; font-size: .8rem; font-weight: 600; margin-bottom: 16px;
}

/* ---------- spinner ---------- */
/* 加载中：三根有规律伸缩的纵向柱体（全站统一，非圆圈）。柱体取 currentColor 随环境文字色
   自适应（深色按钮上偏白、浅底上偏墨）；liquid glass 阶段改 .loader 的 color 即可切毛玻璃强白 */
@keyframes loader-bar { 0%,100% { transform: scaleY(.35); opacity: .5; } 50% { transform: scaleY(1); opacity: 1; } }
.loader, .spinner { display: inline-flex; align-items: center; }
.loader { height: 26px; gap: 6px; color: var(--accent-bright); }
.spinner { height: 13px; gap: 3px; vertical-align: -2px; }
.loader i, .spinner i { display: block; width: 4px; height: 100%; border-radius: 2px; background: currentColor; transform-origin: center; animation: loader-bar 1s ease-in-out infinite; }
.spinner i { width: 3px; }
.loader i:nth-child(2), .spinner i:nth-child(2) { animation-delay: .15s; }
.loader i:nth-child(3), .spinner i:nth-child(3) { animation-delay: .3s; }

/* ===== A7内联样式改类 ===== */
.text-ink-3 { color: var(--ink-3); }                 /* 档案不完整提示（--ink-3 ≠ --muted，独立语义类） */
.img-broken { visibility: hidden; }                  /* 图片加载失败静默隐藏（保留占位，display 不动） */

/* M11：投诉与反馈通道选择浮窗——大按钮竖排 */
.chooser-grid { display: flex; flex-direction: column; gap: 10px; padding: 4px 0; }
.chooser-item { justify-content: center; }

