/* 站点外壳。
 *
 * 引擎（kg3d.js）是「整屏独占」的写法：body 高 100%、overflow 藏起来，
 * .app 撑满。这里只做一件事 —— 在它下面接一条页脚，并且让 .app 让出
 * 那一条的高度。所以 body 改成竖向 flex，.app 由 height:100% 改成 flex:1。
 *
 * 不用 position:fixed 把页脚浮在上面：那样它会盖住球面底部的节点，
 * 而且卡片弹出时页脚还露在外面。占一行的位置更干净。
 */

html, body { height: 100% }
body {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* 引擎给 .app 写的是 height:100%。在有页脚的情况下那会溢出，
   所以改成「吃掉剩下的高度」。min-height:0 是必须的 ——
   不给的话 flex 子项的最小高度按内容算，canvas 就不会收缩。 */
body > .app {
  flex: 1 1 auto;
  height: auto;
  min-height: 0;
}

/* ── 页脚 ────────────────────────────────────────────────────────── */
.icp {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px 14px;
  padding: 7px 18px calc(7px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--line-soft);
  background: var(--surface);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--ink-3);
  position: relative;
  z-index: 5;                    /* 压在球面上面，别被 canvas 的边界盖住 */
}
.icp a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color .16s, border-color .16s;
}
.icp a:hover { color: var(--ink-2); border-bottom-color: var(--line) }
.icp .sep { opacity: .5; user-select: none }
/* 备案号用小一号的等宽字体 —— 它是个编号，等宽读起来更像编号 */
.icp .beian {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: .01em;
}

/* 窄屏上把「Powered by」那段收掉，只留备案号 ——
   备案是必须露出来的，其余的是装饰。 */
@media (max-width: 560px) {
  .icp { gap: 4px 10px; font-size: 11px }
  .icp .opt { display: none }
}

/* ── 首屏：树还没到手时先摆一个安静的等待态 ─────────────────────── */
/* 引擎 mount 之后会往 body 里塞一整套 DOM，这个占位就没了。
   有它，用户看到的是「正在起」而不是「白屏」。 */
#boot {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  background: var(--bg);
  color: var(--ink-3);
  font-size: 13px;
  z-index: 50;
  transition: opacity .35s;
}
#boot.gone { opacity: 0; pointer-events: none }
#boot .b-title {
  font-family: "Archivo", "IBM Plex Sans", "PingFang SC", "Microsoft YaHei", sans-serif;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--ink-2);
}
#boot .b-bar {
  width: 156px; height: 2px; border-radius: 2px;
  background: var(--line); overflow: hidden;
}
#boot .b-bar i {
  display: block; width: 40%; height: 100%; border-radius: 2px;
  background: var(--ink-3);
  animation: bootslide 1.15s cubic-bezier(.5,0,.5,1) infinite;
}
@keyframes bootslide {
  0%   { transform: translateX(-110%) }
  100% { transform: translateX(360%) }
}
#boot .b-err { color: var(--warn); font-size: 12.5px; max-width: 30rem; text-align: center; line-height: 1.7 }
@media (prefers-reduced-motion: reduce) {
  #boot .b-bar i { animation-duration: 2.6s }
}

/* ── 令牌弹窗：点树根球心时先过的那道门（auth.js 的 ask()）─────────
   它和卡片面罩（kg3d.css 的 .veil）是两件事，所以另起一套类名：
   卡片是「看这一颗节点」，这个是「证明你进得来」——样式上也不跟着卡片走
   （卡片 47rem、内容自己滚；这个只有 26rem、永远不滚）。
   z-index 80 压在预览层（70）和终端（68）上面：它是门，得挡在所有东西
   前面，包括已经开着的终端。
   颜色全走 :root 那套变量，所以深色模式不用再写一遍。 */
.ask {
  position: fixed; inset: 0; z-index: 80;
  display: grid; place-items: center;
  padding: max(16px, env(safe-area-inset-top, 0px)) 16px max(16px, env(safe-area-inset-bottom, 0px));
  background: var(--veil);
  -webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px);
  animation: askin .16s ease;
}
@keyframes askin { from { opacity: 0 } }
.ask-panel {
  width: min(26rem, 100%);
  display: flex; flex-direction: column; gap: 11px;
  padding: 20px 20px 17px;
  background: var(--surface);
  border: 1px solid var(--line); border-radius: 16px;
  box-shadow: var(--shadow-3);
}
.ask-title { font-size: 15px; font-weight: 600; color: var(--ink) }
.ask-sub { font-size: 12.5px; line-height: 1.75; color: var(--ink-2) }
/* 令牌是个机器串，用等宽 —— 和文件区那个框（.attform input）同一套 */
.ask-in {
  font-family: "IBM Plex Mono", ui-monospace, monospace; font-size: 12px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: 9px; padding: 8px 11px;
}
.ask-in::placeholder { color: var(--ink-3) }
.ask-err { font-size: 12.5px; color: var(--warn) }
.ask-row { display: flex; justify-content: flex-end; gap: 8px; margin-top: 2px }
.ask-row button {
  cursor: pointer; font-size: 12.5px; font-weight: 600;
  border: 1px solid var(--line); border-radius: 9px; padding: 7px 15px;
  background: var(--surface-2); color: var(--ink);
  transition: background .16s, border-color .16s, opacity .16s;
}
.ask-row button:hover { background: var(--surface); border-color: var(--ink-3) }
.ask-cancel { color: var(--ink-2); font-weight: 400 }
.ask-go { background: var(--ink); border-color: var(--ink); color: var(--surface) }
.ask-go:hover { background: var(--ink); opacity: .86 }
.ask-go:disabled { opacity: .5; cursor: progress }
.ask :focus-visible { outline: 2px solid var(--ink-3); outline-offset: 2px }
@media (prefers-reduced-motion: reduce) { .ask { animation: none } }
