@font-face{font-family:Inter;src:url("/login-ui/assets/fonts/inter-latin.woff2") format('woff2');font-style:normal;font-weight:100 900;font-display:swap}
@font-face{font-family:Geist Mono;src:url("/login-ui/assets/fonts/geist-mono-regular.ttf") format('truetype');font-weight:400;font-display:swap}
:root{--space-black:#08090b;--moon-white:#f2f2ee;--lunar-gray:#a4a3a0;--signal-orange:#d98859;--signal-orange-rgb:217 136 89;--font-mono-cjk:"Geist Mono","PingFang SC","Microsoft YaHei",sans-serif;--line:rgba(242,242,238,.19);--font-sans:Inter,"PingFang SC","Microsoft YaHei",sans-serif;--font-mono:"Geist Mono",monospace;color-scheme:dark}
*{box-sizing:border-box}html,body{margin:0;min-height:100%;background:var(--space-black);color:var(--moon-white);font-family:var(--font-sans);-webkit-font-smoothing:antialiased}button,input,a{-webkit-tap-highlight-color:transparent}button,input{font:inherit}button,a{touch-action:manipulation}button{color:inherit;cursor:pointer}a{color:inherit;text-decoration:none}a,button{transition:color .2s,background .2s,border-color .2s,opacity .2s,transform .2s}button:focus-visible,a:focus-visible,input:focus-visible{outline:2px solid var(--signal-orange);outline-offset:5px}button{border:0;background:none}button:disabled{cursor:default}::selection{background:#8b4735;color:#fff}.mono{font-family:var(--font-mono);font-size:10px;letter-spacing:.12em;font-weight:400}.space-page{--page-gutter:3.4vw;--login-column:400px;position:relative;isolation:isolate;min-height:100vh;min-height:100svh;padding:0 3.4vw;display:grid;grid-template-columns:1fr 400px;--header-row:clamp(56px,9svh,92px);grid-template-rows:var(--header-row) 1fr auto;column-gap:6vw}.scene,.scene-shade{position:fixed;inset:0;width:100vw;height:100vh;height:100svh;z-index:-2;pointer-events:none}.scene{--scene-image:url("/login-ui/assets/images/scene-flat.webp");--scene-position:42% center}.scene-shade{z-index:-1;background:linear-gradient(90deg,rgba(8,9,11,.1) 0%,transparent 40%,rgba(8,9,11,.2) 60%,rgba(8,9,11,.69) 100%),linear-gradient(0deg,rgba(8,9,11,.94) 0%,rgba(8,9,11,.27) 16%,transparent 40%,rgba(8,9,11,.08) 83%,rgba(8,9,11,.55) 100%)}.site-header{grid-column:1/-1;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line);gap:25px}.wordmark{display:flex;align-items:center;flex-shrink:0}.brand-logo{display:block;width:112px;height:auto;filter:invert(1);}.header-center{display:flex;align-items:center;gap:11px;font-size:9px;color:#c1bdb6;letter-spacing:.18em}.signal-dot{display:inline-block;width:5px;height:5px;border-radius:50%;background:var(--signal-orange);flex-shrink:0}.language-switch{display:flex;align-items:center;gap:11px;font-family:var(--font-mono);font-size:11px}.language-switch>svg{margin-right:5px;color:#b2afa7}.language-switch>span{color:#726e65}.language-switch button{padding:10px 0;color:#999890;font-size:11px}.language-switch button[aria-pressed=true]{color:var(--moon-white)}.language-switch button:hover{color:var(--signal-orange)}.scene-story{grid-column:1;grid-row:2;align-self:start;padding-top:70px}.eyebrow{margin:0;display:flex;align-items:center;gap:10px;color:#c8c2b9;font-size:9px;letter-spacing:.18em}.tiny-line{width:20px;height:1px;background:var(--signal-orange)}h1{font-size:clamp(28px,2.5vw,42px);font-weight:400;line-height:1.25;letter-spacing:.065em;margin:21px 0 13px;text-shadow:0 2px 25px #08090b44}.story-caption{font-size:11px;letter-spacing:.18em;color:#bcb4a8;margin:0}.login-panel{grid-column:2;grid-row:2;width:100%;max-width:376px;margin:clamp(16px,3svh,48px) 1.5vw clamp(20px,4svh,78px) 0;align-self:center;justify-self:start;position:relative}.panel-topline{display:flex;justify-content:space-between;align-items:center;border-top:1px solid rgba(242,242,238,.38);padding-top:13px;color:#b5b1a9}.panel-topline .mono{font-size:9px;letter-spacing:.16em}.welcome-eyebrow{margin-top:36px;font-size:9px;color:#cac2b6;letter-spacing:.19em}.welcome-eyebrow .signal-dot{width:4px;height:4px}h2{margin:17px 0 0;font-weight:400}h2>span{display:block;font-size:20px;letter-spacing:.04em;font-weight:350;line-height:1.5}h2 strong{display:flex;align-items:flex-start;gap:5px;font-size:39px;line-height:1.2;font-weight:650;letter-spacing:-1.9px;margin-top:3px;white-space:nowrap}.registered-mark{font-size:.36em;line-height:1;font-weight:400;letter-spacing:0;margin-top:.3em}.login-description{color:#b9b6ae;font-size:11px;letter-spacing:.065em;margin:16px 0 29px}.login-methods{display:flex;gap:30px;border-bottom:1px solid var(--line)}.login-methods button{padding:0 0 13px;font-size:12px;letter-spacing:.05em;color:#a4a099;position:relative}.login-methods button[aria-pressed=true]{color:var(--moon-white)}.login-methods button[aria-pressed=true]::after{content:"";position:absolute;height:2px;bottom:-1px;left:0;right:0;background:var(--signal-orange)}.login-methods button:hover{color:var(--moon-white)}.fields{margin-top:22px}.field{display:block;border-bottom:1px solid rgba(242,242,238,.3);transition:border-color .2s}.field:focus-within{border-color:var(--signal-orange)}.field-label{display:flex;align-items:center;justify-content:space-between;font-size:10px;color:#d5d0c7;letter-spacing:.08em}.field-label .mono{color:#928d83;font-size:8px}.input-row{display:flex;align-items:center;min-height:46px;gap:14px}.input-row input{width:100%;min-width:0;border:0;background:transparent;color:var(--moon-white);padding:12px 0;font-size:13px;outline:none;box-shadow:none;border-radius:0}.input-row input::placeholder{color:#a29b90;font-size:12px;letter-spacing:.025em}.input-row input:focus-visible{outline:none}.input-row input:-webkit-autofill{-webkit-box-shadow:none!important;box-shadow:none!important;-webkit-background-clip:text!important;background-clip:text!important;caret-color:#f2f2ee;-webkit-text-fill-color:var(--moon-white)}.country-code{display:flex;gap:10px;align-items:center;font-size:12px;letter-spacing:0;color:#e2dcd1;white-space:nowrap;padding-right:13px;border-right:1px solid var(--line)}.country-code>span{color:#aaa195;font-size:13px}.password-field{margin-top:23px}.reveal-password{padding:10px 0 10px 12px;color:#b3ab9f;display:flex;min-width:34px;justify-content:center}.reveal-password:hover{color:var(--moon-white)}.form-options{display:flex;justify-content:flex-end;margin:13px 0 23px;font-size:10px;letter-spacing:.035em;color:#c4bbad}.form-options a:hover,.consent a:hover,.legal-footer a:hover{color:var(--moon-white)}.enter-button{width:100%;padding:0 20px;min-height:50px;display:flex;align-items:center;justify-content:space-between;background:var(--moon-white);color:#171613;font-size:11px;font-weight:600;letter-spacing:.07em;border:1px solid var(--moon-white)}.enter-button:hover{background:#fff4da;border-color:#fff4da}.enter-button:hover svg{transform:translateX(4px)}.enter-button svg{transition:transform .2s}.enter-button:active{transform:translateY(1px)}.consent{margin:14px 0 0;font-size:9px;line-height:1.9;color:#b3aaa0;text-align:center;letter-spacing:.015em}.consent a{color:#ddd5c9}.apply-row{margin-top:28px;padding-top:22px;border-top:1px solid var(--line);font-size:11px}.apply-content{position:relative;display:flex;align-items:center;justify-content:space-between;gap:12px}.apply-content>span{color:#b6ada1;font-size:10px}.apply-row a{display:flex;gap:12px;align-items:center}.apply-row a:hover{color:var(--signal-orange)}.scene-credit{position:absolute;top:50%;transform:translateY(-50%);left:calc(2 * var(--page-gutter) + var(--login-column) - 100vw);width:max-content;display:flex;gap:13px;align-items:center}.credit-marker{display:flex;color:#d5c3aa}.scene-credit p{font-size:9px;margin:0;letter-spacing:.16em;color:#e4d7c5}.site-footer{grid-column:1/-1;grid-row:3}.footer-line{min-height:53px;display:flex;justify-content:space-between;align-items:center;gap:20px;border-bottom:1px solid var(--line);border-top:1px solid var(--line);color:#d0c9bc}.location{display:flex;gap:10px;align-items:center}.coordinates{margin-left:16px;color:#b2ab9f;font-size:9px;letter-spacing:.06em}.footer-dash{color:#a89985}.footer-mission{font-size:8px;color:#a69f94;letter-spacing:.18em}.legal-footer{padding:17px 0 19px;display:flex;justify-content:space-between;align-items:center;gap:14px;font-size:8px;color:#a09b93;line-height:1.6}.legal-footer>div{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:14px}.preview-notice{font-size:11px;line-height:1.8;padding:13px 0 0;color:#f2d1bc}.preview-notice a{display:flex;align-items:center;gap:5px;text-decoration:underline;text-underline-offset:3px}.skip-link{position:fixed;top:8px;left:8px;z-index:20;background:#f2f2ee;color:#08090b;padding:12px;transform:translateY(-180%)}.skip-link:focus{transform:translateY(0)}
@media(min-width:1600px){.space-page{--page-gutter:4vw;--login-column:420px;grid-template-columns:1fr 420px;column-gap:9vw;padding:0 4vw}.login-panel{max-width:390px;margin-right:1vw}.scene-story{padding-top:85px}.space-page{--header-row:clamp(56px,9svh,100px)}}
@media(max-width:1100px){.space-page{--page-gutter:4vw;--login-column:350px;grid-template-columns:1fr 350px;column-gap:5vw;padding:0 4vw}.login-panel{max-width:350px;margin-right:0}.header-center{font-size:8px;letter-spacing:.09em}h1{font-size:29px}.scene-story{padding-top:50px}.scene{--scene-position:38% center}.footer-mission{display:none}.legal-footer{align-items:flex-start}.legal-footer>div{gap:8px 12px;max-width:62%}.coordinates{margin-left:5px;font-size:8px}}
@media(max-width:760px){.scene,.scene-shade{height:100svh}.space-page{display:flex;flex-direction:column;padding:0 24px;min-height:100svh}.scene{--scene-image:url("/login-ui/assets/images/scene-flat-mobile.webp");--scene-position:28% top;--scene-size:auto 800px}.scene-shade{background:linear-gradient(180deg,rgba(8,9,11,.18) 0%,rgba(8,9,11,.14) 13%,rgba(8,9,11,.71) 31%,rgba(8,9,11,.87) 66%,#08090b 93%)}.site-header{min-height:74px;gap:14px}.brand-logo{width:96px}.header-center{display:none}.language-switch{gap:10px}.scene-story{padding:36px 0 34px}.scene-story .eyebrow{font-size:8px}h1{font-size:27px;line-height:1.25;margin:13px 0 0}.story-caption{display:none}.login-panel{width:100%;max-width:400px;margin:0 auto 36px;align-self:initial}.panel-topline{padding-top:11px}.welcome-eyebrow{margin-top:26px}h2>span{font-size:18px}h2 strong{font-size:35px}.login-description{margin-bottom:25px}.input-row input{font-size:16px}.input-row{min-height:49px}.enter-button{min-height:52px}.consent{font-size:10px}.apply-row{margin-top:24px}.scene-credit{display:none}.site-footer{margin-top:auto}.footer-line{min-height:48px}.footer-line>.mono,.location{font-size:8px}.location{gap:7px}.coordinates{display:none}.legal-footer{flex-direction:column;font-size:8px;gap:10px;padding:15px 0 20px}.legal-footer>div{max-width:100%;justify-content:flex-start;gap:8px 12px}.reveal-password{min-width:42px;min-height:44px}}
/* A quiet audio control beside the wordmark, with the same HUD typography. */
.header-brand{display:flex;align-items:center;gap:22px;flex-shrink:0}
.sound-control{position:relative}
.music-switch{display:flex;align-items:center;gap:10px;min-height:44px;padding:0 0 0 20px;position:relative;color:#bcb6ad;font-size:10px;letter-spacing:.08em;white-space:nowrap}
.music-switch::before{content:"";position:absolute;left:0;top:14px;height:16px;width:1px;background:var(--line)}
.music-switch:hover{color:var(--moon-white)}
.music-switch[data-state=on]{color:var(--moon-white)}
.sound-label{display:block;min-width:58px;text-align:left}
.sound-wave{display:flex;align-items:center;justify-content:center;gap:2px;width:18px;height:18px;flex-shrink:0}
.sound-wave i{display:block;width:2px;height:3px;background:currentColor;transform-origin:center;transition:height .3s,color .3s}
.sound-wave i:nth-child(2),.sound-wave i:nth-child(4){height:6px}
.sound-wave i:nth-child(3){height:9px}
.music-switch[data-state=on] .sound-wave{color:var(--signal-orange)}
.music-switch[data-state=on] .sound-wave i{height:15px;animation:sound-wave 1.15s ease-in-out infinite alternate}
.music-switch[data-state=on] .sound-wave i:nth-child(2){animation-delay:-.65s}
.music-switch[data-state=on] .sound-wave i:nth-child(3){animation-delay:-.3s}
.music-switch[data-state=on] .sound-wave i:nth-child(4){animation-delay:-.9s}
.music-switch[data-state=on] .sound-wave i:nth-child(5){animation-delay:-.45s}
.music-switch[data-state=loading] .sound-wave{opacity:.55}
.music-switch[data-state=error]{color:#e9a488}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
@keyframes sound-wave{0%{transform:scaleY(.2)}45%{transform:scaleY(.72)}100%{transform:scaleY(1)}}
@media(max-width:1000px){.header-center{display:none}}
@media(max-width:760px){.header-brand{gap:16px}.music-switch{padding-left:16px;gap:8px}}
@media(max-width:420px){.header-brand{gap:10px}.music-switch{padding-left:12px;gap:7px}.sound-word{display:none}.sound-label{min-width:30px}.site-header{gap:10px}.language-switch{gap:8px}.language-switch>svg{margin-right:0}}
@media(max-width:350px){.header-brand .brand-logo{width:88px}.space-page{padding-left:18px;padding-right:18px}}
/* Shared cover/crop coordinates keep all eight source canvases aligned. */
.scene{overflow:hidden;background:#08090b}
.scene-surface{position:absolute;inset:0;background-image:var(--scene-image);background-size:var(--scene-size,cover);background-position:var(--scene-position);background-repeat:no-repeat;background-color:#08090b}
.scene-layers{position:absolute;inset:0;visibility:hidden}
.scene-canvas{display:block;width:100%;height:100%;pointer-events:none;user-select:none}
.scene[data-ready=true] .scene-layers{visibility:visible}
@media(min-width:761px) and (prefers-reduced-motion:no-preference) and (any-pointer:fine){.scene-surface{background-size:max(106vw,189.359224svh) auto}}
.space-page[data-spatial-ready=true]{cursor:grab}
.space-page[data-spatial-ready=true] :is(.site-header,.scene-story,.login-panel,.site-footer){cursor:auto}
.space-page[data-spatial-dragging=true],.space-page[data-spatial-dragging=true] *{cursor:grabbing!important;user-select:none}
@media(max-width:760px),(prefers-reduced-motion:reduce){.scene-layers{display:none}}
/* Tighten vertical whitespace on laptop screens without scaling or clipping the UI.
   Keep the background tied to the viewport, independent of translated content. */
@media(max-height:850px){
  .space-page{--compact-space:clamp(0px,calc(10svh - 60px),25px)}
  .scene-story{padding-top:clamp(24px,6svh,50px)}
  .login-panel{margin-top:1.5svh;margin-bottom:1.5svh}
  .panel-topline{padding-top:8px}
  .welcome-eyebrow{margin-top:calc(8px + var(--compact-space));line-height:1.4}
  h2{margin-top:clamp(6px,1.5svh,12px)}
  h2>span{font-size:18px;line-height:1.4}
  h2 strong{font-size:35px;line-height:1.15}
  .login-description{line-height:1.4;margin:8px 0 calc(10px + var(--compact-space) * .3)}
  .login-methods button{padding-bottom:8px;line-height:1.3}
  .fields{margin-top:calc(10px + var(--compact-space) * .3)}
  .field-label{line-height:14px}
  .input-row{min-height:44px}
  .password-field{margin-top:calc(8px + var(--compact-space) * .4)}
  .form-options{margin:8px 0 12px;line-height:14px}
  .enter-button{min-height:46px}
  .consent{margin-top:10px;line-height:1.6}
  .apply-row{margin-top:12px;padding-top:12px}
  .apply-content{line-height:16px}
  .footer-line{min-height:38px}
  .legal-footer{padding:10px 0;gap:8px}
}
@media(min-width:761px) and (max-height:640px){
  .space-page{--header-row:52px}
  .login-panel{margin-top:6px;margin-bottom:6px}
  .welcome-eyebrow{margin-top:6px}
  h2{margin-top:6px}
  .login-description{margin:6px 0 8px}
  .form-options{margin:6px 0 8px}
  .apply-row{margin-top:10px;padding-top:10px}
  .footer-line{min-height:32px}
  .legal-footer{padding:8px 0}
}
@media(max-width:760px) and (max-height:850px){
  .site-header{min-height:60px;flex-shrink:0}
  .scene-story{padding:18px 0 20px}
  .login-panel{margin:0 auto 16px}
  .welcome-eyebrow{margin-top:12px}
  .legal-footer{gap:6px}
}
@media(max-width:760px) and (max-height:740px){
  .site-header{min-height:54px}
  .scene-story{padding:12px 0 14px}
  h1{font-size:23px;margin-top:8px}
  .login-panel{margin-bottom:10px}
  .welcome-eyebrow{margin-top:6px}
  h2{margin-top:6px}
  .login-description{margin:6px 0 8px}
  .fields{margin-top:8px}
  .password-field{margin-top:8px}
  .apply-row{margin-top:10px;padding-top:10px}
  .legal-footer{padding:8px 0}
}
@media(prefers-reduced-motion:no-preference){.login-panel{animation:arrive .7s ease-out both}.scene-story{animation:arrive .9s ease-out both}@keyframes arrive{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important;scroll-behavior:auto!important}}

/* Requested spacing between wordmark and login methods. */
.login-panel h2{margin-bottom:28px}

/* User-requested welcome row and relocated orange dot. */
.login-panel h2{margin-top:36px}
.login-panel h2>.welcome-row{display:flex;align-items:center;gap:10px}

/* Raise only the user-marked content; preserve submit and footer positions. */
.login-panel #login-title,.login-panel .login-methods,.login-panel .fields,.login-panel .form-options{position:relative;top:-36px}
.panel-topline>svg{margin-left:auto}

.login-panel .enter-button{position:relative;top:-16px}

/* ── owner 2026-09-22 登录页验收改点(④⑤⑥⑦)────────────────────────────────
   ④⑥ 字段标签(手机号码 / 验证码 / 邮箱地址 / 密码)对客不再显示——占位符已经
      承载了字段身份。🔴 用**视觉隐藏**而不是删 DOM:<label for> 删掉输入框就
      没有可访问名字了,读屏会念成「编辑框」。DOM 留着,只是不占像素。
   ⑤⑦ 占位符与「已输入的文字」靠两件事拉开:更暗的颜色 + 等宽字族。
      🔴 字族末尾绝不能收在 monospace:中文没有 Geist Mono 字形,会回落到
      宋体 / Courier 衬线(v1 踩过这个坑,见 brand.ts 字体注释),所以显式垫
      PingFang / 雅黑,最后收 sans-serif。 */
.field-label{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
.input-row input::placeholder{font-family:var(--font-mono-cjk);color:#7b756c;font-size:11.5px;letter-spacing:.06em}

/* ── owner 2026-09-22:先只做中文版 ⇒ 关掉 CN/EN 切换器 ────────────────────
   🔴 只藏控件、不拆 i18n:文案字典(login-ui.js 的 copy)、update() 的换词逻辑、
      login-auth.js 的 T() 全部原样留着 —— 语言默认 'zh'、控件不可达 ⇒ 全站中文。
      要恢复双语,删掉下面这一条规则即可,不用回头重写任何文案。 */
.language-switch{display:none!important}

/* ── owner 2026-09-22 第二轮改点(①②④⑤⑥)──────────────────────────────── */

/* ② 中文 slogan 下压一行小字英文。跟 h1 同一视觉块 ⇒ 用负 margin 贴上去,
      字号/字距照 .eyebrow 那一档(它已被删,这里承接它的角色)。 */
.story-sub{margin:10px 0 0;font-size:10px;letter-spacing:.22em;color:#d8d0c4;text-shadow:0 2px 18px #08090b99}  /* 压在亮橙山体上会糊掉 ⇒ 提亮一档 + 沿用 h1 同一招投影(她给 h1 写的 text-shadow) */

/* ④⑤ 「登录即表示同意…」与「还没有账号？申请开通」并成一行:
      左边贴左、右边贴右 —— 右缘正好落在上面那颗白色按钮的右缘(同一父宽度)。
      原来 .apply-row 顶上那条分隔线随之取消:两件事并排了,不再需要横线分段。 */
.login-foot{display:flex;align-items:baseline;justify-content:space-between;gap:18px;margin-top:11px}
.login-foot .consent{margin:0;text-align:left;white-space:nowrap}
.login-foot .apply-row{margin:0;padding:0;border-top:none;flex-shrink:0}
.login-foot .apply-content{gap:10px}

/* ⑥ 页脚左下角:可点的心。空心 = 没点过,填实 = 点过(状态在本机 localStorage)。
      🔴 它是装饰 + 轻互动,不承载状态语义 ⇒ 用品牌橘,不碰状态色梯。 */
.page-like{display:inline-flex;align-items:center;padding:0;margin:0 3px 0 0;border:0;background:none;color:#a89985;vertical-align:-2px;line-height:0}
.page-like:hover{color:var(--signal-orange)}
.page-like[data-liked=true]{color:var(--signal-orange)}
.page-like .page-like-heart{fill:none;transition:fill .18s ease,transform .18s ease}
.page-like[data-liked=true] .page-like-heart{fill:currentColor}
.page-like:active .page-like-heart{transform:scale(.86)}

/* ── owner 2026-09-22 第三轮改点(①②④)──────────────────────────────── */

/* ① slogan 放大一号；英文副标放大两号（原 10px → 13px） */
h1{font-size:clamp(32px,2.85vw,47px)}
.story-sub{font-size:13px}

/* ② 登录区收紧：主要空档来自 .form-options（手机 tab 下「忘记密码」只是隐藏、仍占位），
      上下外边距各收一档，按钮连同按钮以下的两行一起往输入区靠。 */
.form-options{margin:9px 0 13px}
.password-field{margin-top:18px}
.fields{margin-top:18px}

/* ④ 火星当地平太阳时，跟坐标同一档灰、同样拉开间距 */
.lmst{margin-left:16px;color:#b2ab9f;font-size:9px;letter-spacing:.06em}

/* ③ 登录区整体下移，底缘对齐宇航员头盔的正中（1440×900 实测：面板底 573 → 头盔中心 ≈669，差 96px）。
   🔴 用 position 的 top 而不是 margin/transform：
      · margin 会跟 align-self:center 的居中算法打架（加 N 只下移 N/2）；
      · transform 被 .login-panel 的 arrive 入场动画占着，改它动画就废了。
   🔴 这是「DOM 元素对齐 cover 背景图里的一个物件」，**只在接近 1440×900 的比例下严格成立**：
      视口比例一变，背景图的裁切位置就变，头盔会跑。所以用 svh 跟随视口高度做近似，
      并在上限处收口（短屏不至于把面板推到页脚里）。真要严丝合缝只能把头盔做成前景层。 */
.login-panel{top:clamp(0px,5.3svh,48px)}  /* owner 2026-09-22 二次调:原来对齐头盔中心(96px)时，密码占位符正落在火星大气边缘那条亮带上、糊成一片 ⇒ 整体上提约一行(48px)，把输入区推回太空黑底。上提量取 48px 而非更多:再往上，登录区会压到右上那颗太阳及它在大气层上的倒影。 */

/* ⑤ 备案标识合规加固(2026-09-22 核对):
   · 位置本来就合规 —— 未登录 `/` 307 到 `/login`,登录页即首页,备案号在首页底部、三个链接都对。
   · 🔴 但字号原为 8px:法规没定最小字号,反复出现的措辞是「在首页**显著位置**标明」,
     8px + 低对比容易被判为不显著。对齐我们自己另一个公开页 app/s/[code] 的 11.5px 档。
   · 🔴 公安备案号前的警徽图标原本漏了 —— app/s/[code] 那版一直带着(注释还写着「同 /login」),
     v2 新登录页反而弄丢了。补回,两处口径重新一致。 */
.legal-footer{font-size:11px;color:#b5b0a8}
.legal-footer>div{gap:14px 16px}
.beian-police{display:inline-flex;align-items:center;gap:4px}
.beian-police img{display:block}

/* ── owner 2026-09-22 第四轮改点(①②)──────────────────────────────────── */

/* ① 音频开关移到顶栏右侧(原来贴在品牌标右边)。
      那条竖分隔线是为「紧挨 logo」画的,挪到右边孤零零一条反而碍眼 ⇒ 去掉,左内距一并收掉。
      .sound-label 原来按「SOUND OFF」留了 58px,现在只剩 ON/OFF ⇒ 收窄并右对齐,
      让文字紧贴右缘、切换 ON↔OFF 时不左右跳。 */
.music-switch{padding-left:0;gap:7px}  /* 图标与文字收到 7px:它们是一个控件,不该读成两件东西 */
.music-switch::before{display:none}
.sound-label{min-width:26px;text-align:left}  /* 文字左对齐紧贴声波图标(右对齐时 ON 比 OFF 窄,会被推出去、看着像两个不相干的元素);     宽度仍固定 ⇒ ON↔OFF 切换时图标不左右跳,预留的空隙落在文字右侧、不夹在中间。 */

/* ② 英文副标跟中文 slogan 一样吃 proximity hover 动效。
      🔴 动效靠的是把字重从 base 推到 900(font-variation-settings "wght"),
         所以字体必须是可变字重的 —— 原来挂的 Geist Mono 是定重 400,推不动。
         换成 Inter(@font-face 声明 font-weight:100 900,可变),与 .proximity-run
         强制的字族一致 ⇒ 动效起来时不会再有一次字体跳变。 */
.story-sub{font-family:var(--font-sans);font-weight:400}

/* ── owner 2026-09-22 第五轮改点(①)────────────────────────────────────
   音频开关不要那个橙色焦点框(全局 :focus-visible 的 2px signal-orange + 5px offset,
   挪到顶栏右上角之后特别抢眼)。
   🔴 但**不能就这么把焦点指示抹掉** —— 键盘用户全靠它知道焦点在哪,去掉等于这个按钮
      对键盘不可用。换成与 :hover 同一档的提亮(文字转月白 + 声波恢复满不透明),
      既没有框,焦点又看得见。左侧那条竖分隔线在第四轮已 display:none,这里不重复。 */
.music-switch:focus-visible{outline:none;color:var(--moon-white)}
.music-switch:focus-visible .sound-wave{opacity:1}

/* ── owner 2026-09-22 第六轮：页脚合规行的排版口径 ──────────────────────
   它此前既比旁边大一档、字族又跟整条页脚不是一路（正文无衬线 vs 上一行的等宽感），
   读起来像另一块内容贴上来的。现在：字号收到 9.5px、跟上一行同一套等宽字族与字距。
   🔴 字族走 --font-mono-cjk 而不是 --font-mono：后者末尾收在 monospace，
      「琼ICP备…号」这种中文没有 Geist Mono 字形，会回落宋体/Courier 衬线（v1 踩过）。
   🔴 合规底线：法规只说「首页**显著位置**标明」、未定字号。9.5px + 提亮后的 #b5b0a8
      仍明显优于交付原版的 8px + #a09b93（更小且更暗）。再往下走要 owner 自己权衡。 */
.legal-footer{font-size:9.5px;letter-spacing:.06em;font-family:var(--font-mono-cjk);color:#b5b0a8}
.legal-footer>div{gap:12px 14px}

/* ── owner 2026-09-22 第七轮：音频开关的悬停提示 ────────────────────────
   原来用的是浏览器原生 title —— 系统那只纯白圆角小框压在夜空上太重，而且它说的是
   「开启背景音乐 · 火星暮色」：开还是关，右边的 ON/OFF 已经说了，提示再说一遍是噪音。
   ⇒ 只留曲名，且不要框：纯白文字浮在原处，侵入感压到文字这一级。
   🔴 动作式措辞没有删掉，只是移出视觉层——它还在 aria-label 里（读屏用户靠它认这个按钮），
      加载失败那一档仍出完整错误话术，否则用户不知道为什么点不响（见 login-ui.js update）。
   🔴 落在按钮**左侧**而不是下方：下方会撞顶栏那条分隔线——按钮底到线的间距随视口高度
      在 10px（700 高）到 24px（1200 高）之间浮动，固定偏移躲不开它。左侧同一行则恒定，
      而且读起来就是「火星暮色 · 声波 · ON」一句话。左边是空的（CN/EN 那排早已 display:none）。
   🔴 字族走 --font-mono-cjk 不是按钮自带的 --font-mono：后者末尾收在 monospace，
      「火星暮色」没有 Geist Mono 字形会回落宋体/Courier 衬线（第六轮同一个坑）。 */
.music-switch::after{
  content:attr(data-hint);
  position:absolute;right:calc(100% + 11px);top:50%;
  font-family:var(--font-mono-cjk);font-size:10.5px;letter-spacing:.07em;white-space:nowrap;
  color:var(--moon-white);text-shadow:0 1px 6px rgba(8,9,11,.6);
  opacity:0;transform:translate(3px,-50%);
  transition:opacity .18s ease,transform .18s ease;
  pointer-events:none;
}
.music-switch:hover::after,.music-switch:focus-visible::after{opacity:1;transform:translate(0,-50%)}
@media(hover:none){.music-switch::after{content:none}}  /* 触屏没有 hover，提示只会变成一块永不消失的字 */

/* ── owner 2026-09-23：页脚版权句与右侧备案文字「一样大」──────────────────
   两边 CSS 字号本来就同为 9.5px，但看起来左边明显小一号：左边是纯拉丁文
   （Geist Mono 大写高 0.73em、x 高 0.55em），右边是汉字（方块字墨迹 ≈ 0.9em），
   同一字号下汉字天然比拉丁字母高出约两成。对齐的是**墨迹高度**不是 font-size：
   版权句抬到 11px，大写字母 ≈ 8.1px、与 9.5px 汉字的墨迹齐平（10.5 仍偏小、11.5 已反超，
   PC 2000/1440 与手机 390 三档真渲染比过）。
   🔴 只抬版权 <span>，备案链接一律不动：右边的数字/字母夹在汉字中间、跟着汉字读，
      抬了反而把「琼ICP备…号」撑散。若日后版权句里混进中文，这条 11px 要重新量。 */
.legal-footer>span{font-size:11px}

/* ── owner 2026-09-23（阮义龙反馈「登录页文字太小」）：主视区文字整体 +2px ─────────
   范围 = 顶栏分隔线以下、页脚以上那一整块（slogan / 英文副标 / 登录表单到「申请开通」），
   每一处在**上一轮生效值**上各加 2px，字距、行高、间距一律不动，只动字号：
     slogan         clamp(32,2.85vw,47) → clamp(34,2.85vw+2,49)
     英文副标        13 → 15   登录方式 tab   12 → 14   输入文字  13 → 15   占位符  11.5 → 13.5
     +86            12 → 14   忘记密码        10 → 12   进入按钮  11 → 13
     登录即表示同意   9 → 11   还没有账号      10 → 12   申请开通  11 → 13
   （手机 tab 的「发送验证码」按钮与发码后的兜底提示住 sms.css，那边同轮 +2，见其文末。）
   🔴 输入框在手机端保持 16px：iOS 对 <16px 的输入框聚焦时会整页放大，
      base 那条 @media(max-width:760px){.input-row input{font-size:16px}} 会被这里的后置
      同权规则盖掉，所以手机档必须在下面重新断言一次。
   🔴 顶栏、页脚（含备案行）不在范围内，一字未动。 */
h1{font-size:clamp(34px,calc(2.85vw + 2px),49px)}
.story-sub{font-size:15px}
.login-methods button{font-size:14px}
.input-row input{font-size:15px}
.input-row input::placeholder{font-size:13.5px}
.country-code{font-size:14px}
.form-options{font-size:12px}
.enter-button{font-size:13px}
.consent{font-size:11px}
.apply-content>span{font-size:12px}
.apply-row{font-size:13px}
@media(max-width:760px){.input-row input{font-size:16px}}
/* 🔴 手机端（390 宽、面板 342px）：+2 之后「登录即表示同意…」188px 与「还没有账号？申请开通」161px
   一行放不下（实测右缘 391 > 面板右缘 366，溢出 25px）⇒ 只在手机档允许折成两行：
   第一行同意句贴左、第二行「申请开通」贴右（延续 PC 版它落在按钮右缘的口径）。PC 三档不溢出、不折。 */
@media(max-width:760px){.login-foot{flex-wrap:wrap;row-gap:8px}.login-foot .apply-row{margin-left:auto}}

/* ── owner 2026-09-23 夜（截图反馈两点）──────────────────────────────────────
   ① 按钮底下那一行「登录即表示同意 服务协议 与 隐私政策 ／ 还没有账号？申请开通」字号统一。
      上一轮 +2 沿用了交付原稿的三档阶梯（同意句 11 / 还没有账号 12 / 申请开通 13）——
      原稿里这三段分住两行、阶梯读不出来；并成一行之后三段字坐同一条基线、大小却各不相同。
      收成一档 11.5px（同意句 +0.5、还没有账号 −0.5、申请开通 −1.5），整行墨迹齐平；
      字距、颜色、行高一律不动（申请开通仍靠月白 + 箭头当行动点，不再靠字号）。
      🔴 为什么不是整 12：PC 面板 376px 一行只容 376，12px 下三段 205.7 + 18 + 157 = 380.7、
         「申请开通」右缘探出按钮右缘 5px（1440×900 实测），破了 09-22「右缘落在按钮右缘」的口径；
         11.5px 下 197 + 18 + 152 = 367、留 9px 余量（客户机字体不同、拉丁字符与空格宽度会飘）。
      🔴 用 .login-foot 前缀提高特异性盖掉上面三条 +2 规则，手机档同值（390 宽 367 > 342 仍走上面那条折两行）。
   ② 「进入 MEOW SPACE」按钮跟全站 D18 一样收小圆角（控件档 8px，docs/ui-v2-upgrade.md §1.12）。
      🔴 登录页不加载 app/v14-theme.css，这里**镜像**那三档 token（同名同值）——改主题的档位要同步这里。
      直角在 button.css 里写死（它在本文件之后加载、同权后者胜），所以圆角本身写在 button.css /
      sms.css 文末，这里只放 token。手机 tab 的「发送验证码」同一表单、同一档，一起收（sms.css 文末）。
      弹窗（重置密码 / 申请开通）与 /auth/forgot 仍是直角，owner 要跟再改。 */
:root{--v14-r-panel:12px;--v14-r-ctrl:8px;--v14-r-chip:6px}
.login-foot .consent,.login-foot .apply-content>span,.login-foot .apply-row{font-size:11.5px}

/* ── owner 2026-09-23 夜（截图反馈）：顶栏分割线离 logo 太远，把线收上来 ─────────────
   顶栏 = 网格首行，行高统一记在 --header-row（基线 clamp(56px,9svh,92px)、≥1600 封顶 100、
   PC 矮屏 ≤640 定 52；三处原先各写一遍 grid-template-rows，现在只改变量）。header 原本撑满整行、
   内容垂直居中、分割线是它的 border-bottom 贴行底 ⇒ 1080p 下 logo 底到线 32px、900p 下 24px，
   和 logo 顶到页顶对称。
   只动线、不动 logo：PC 档 header 改 align-self:start 不再撑满整行，上内边距 = 原来居中时的空档
   （(--header-row − 44px) / 2，44 = 音频开关 min-height，是行内最高的一件），logo 在任何视口高度
   都停在原位；下内边距收成 10px ⇒ logo 底到线固定 ≈ 16px（10 + (44 − 31) / 2），不再随屏高长。
   🔴 别改成把线整体上提固定像素：行高随 svh 缩到 65px（1280×720）时线已经只离 logo 16px，再提就压字。
   行高 < 66px 时 header 比行高出几像素（52 行时 7px），落进透明的第二行、离故事块与登录面板都远，看不见。
   手机档（≤760，flex 纵排、min-height 74/60/54）不动，按「PC 先、手机后」回头再收。 */
@media(min-width:761px){.site-header{align-self:start;padding-top:calc((var(--header-row) - 44px) / 2);padding-bottom:10px}}
