/*
 * Couplink 基础样式。
 *
 * 这是给两个人用的东西，不是给运维看的。所以：
 *   - 不用等宽字体（那是终端与日志的语言）；
 *   - 界面上不出现协议、密钥、字节数这些词，原始数据一律收进 ?debug 面板；
 *   - 配色取暖奶油与珊瑚，避开冷灰蓝那套「管理后台」的观感。
 *
 * 单一外壳与它的三个视图共用本文件（通话另有 call.css、相册 space.css、观影 watch.css）。
 */

:root {
  --bg: #fdf8f3;
  --surface: #fffdfb;
  --surface-sunk: #fbf5ef;

  --ink: #3b2f29;
  --ink-2: #7d6a5e;
  --ink-3: #ab9a8d;

  --line: #f2e6db;
  --line-2: #e9d9c9;

  --accent: #e0705a;
  --accent-deep: #c85a45;
  --accent-soft: #fdeee8;

  --ok: #658c66;
  --ok-soft: #edf4ec;
  --warn: #bf8940;
  --warn-soft: #fbf0df;
  --bad: #c05a4a;
  --bad-soft: #fbe9e5;

  --video-bg: #2b2420;
  --radius: 18px;
  --radius-sm: 13px;
  --shadow: 0 1px 2px rgba(150, 100, 70, .05), 0 10px 26px -18px rgba(150, 100, 70, .34);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.65 -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* 顶部的暖光，给整页一点温度，不抢内容 */
body::before {
  content: '';
  position: fixed;
  inset: 0 0 auto 0;
  height: 420px;
  background: radial-gradient(620px 320px at 50% -40px, rgba(224, 112, 90, .085), transparent 72%);
  pointer-events: none;
  z-index: 0;
}

/* ---- 顶栏 ---- */

.bar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: nowrap;
  padding: 12px 20px;
  background: rgba(253, 248, 243, .88);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  flex: none;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}

.brand::before {
  content: '';
  width: 11px;
  height: 11px;
  flex: none;
  border-radius: 50%;
  background: linear-gradient(135deg, #f2957a, var(--accent));
  box-shadow: 0 0 0 3.5px var(--accent-soft);
}

.nav {
  display: flex;
  gap: 3px;
  margin-right: auto;
  min-width: 0;
  overflow: hidden;
}

.nav a {
  flex: none;
  font-size: 13.5px;
  color: var(--ink-2);
  text-decoration: none;
  padding: 6px 14px;
  border-radius: 999px;
  white-space: nowrap;
  transition: background .15s, color .15s;
}

.nav a:hover { background: var(--accent-soft); color: var(--accent-deep); }
.nav a.active { background: var(--accent); color: #fff; }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  font-size: 12px;
  padding: 4px 12px;
  border-radius: 999px;
  white-space: nowrap;
}

.pill::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: .65;
}

.pill-idle { background: #f4efe9; color: var(--ink-3); }
.pill-live { background: var(--ok-soft); color: var(--ok); }
.pill-warn { background: var(--warn-soft); color: var(--warn); }
.pill-bad  { background: var(--bad-soft); color: var(--bad); }

/* ---- 对方在不在 ----
   状态灯说的是「我这条连接通不通」，这枚说的是「她在不在这个空间里」。
   两件事分开放，也不许别的模块去写它们。 */

.avatar {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  color: var(--ink-3);
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  transition: color .2s ease, background .2s ease, border-color .2s ease;
}

.avatar svg { width: 17px; height: 17px; }

/* 在线才亮。不靠颜色区分「谁是谁」——图样本身已经区分了。 */
.avatar.online {
  color: var(--ok);
  background: var(--ok-soft);
  border-color: var(--ok-soft);
}

.avatar.mini { width: 22px; height: 22px; }
.avatar.mini svg { width: 13px; height: 13px; }

/* ---- 浮条 ----
   全站唯一会主动弹出来的东西，所以放在顶栏正下方、几秒后自己退场，
   并且不接鼠标事件——它只是通报一声，不该挡住任何东西。 */

.toast {
  position: fixed;
  top: 66px;
  left: 50%;
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 7px 16px 7px 8px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--line-2);
  box-shadow: 0 12px 28px -12px rgba(150, 100, 70, .38);
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink);
  opacity: 0;
  transform: translate(-50%, -8px);
  transition: opacity .22s ease, transform .22s ease;
  pointer-events: none;
}

.toast.show { opacity: 1; transform: translate(-50%, 0); }

.toast-text { padding-right: 4px; }

@media (prefers-reduced-motion: reduce) {
  .toast { transition: none; transform: translate(-50%, 0); }
}

@media (max-width: 560px) {
  .avatar { width: 26px; height: 26px; }
  .avatar svg { width: 15px; height: 15px; }
  .toast { top: 54px; font-size: 12.5px; }
}

/* ---- 版面 ---- */

main {
  position: relative;
  z-index: 1;
  max-width: 720px;
  margin: 0 auto;
  padding: 26px 18px 72px;
}

/* 相册是网格，给它宽一点；另两块是单列，窄一点更好读 */
body[data-view="space"] main { max-width: 960px; }

/*
 * 内容少的两块（通话、一起看）垂直居中。
 * 不居中的话底下会空一大截，整页看着像没做完。
 */
body[data-view="call"],
body[data-view="watch"] {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

body[data-view="call"] main,
body[data-view="watch"] main {
  flex: 1;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-bottom: 52px;
}

.card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 22px 24px;
  margin-bottom: 16px;
  box-shadow: var(--shadow);
}

/* 首屏上方不放说明文字。这里是给两个人用的东西，不是给别人介绍它怎么做的。 */

h2 {
  font-size: 15px;
  font-weight: 600;
  margin: 0 0 6px;
}

.hint {
  font-size: 13px;
  line-height: 1.7;
  color: var(--ink-2);
  margin: 0 0 14px;
}

/* ---- 顶栏上的两个小图标 ----
   锁：忘掉这台设备上记着的词。
   更多：低频的东西（备份）都收在这里，不占正地方。 */

.lock-btn,
.icon-btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
  transition: background .15s, color .15s;
}

.lock-btn svg,
.icon-btn svg { width: 17px; height: 17px; display: block; }

.lock-btn:hover,
.icon-btn:hover {
  background: var(--accent-soft);
  color: var(--accent-deep);
  border: none;
}

.menu { position: relative; flex: none; }

.menu > summary { list-style: none; cursor: pointer; }
.menu > summary::-webkit-details-marker { display: none; }

.menu-pop {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 30;
  min-width: 208px;
  padding: 7px;
  background: var(--surface);
  border-radius: var(--radius-sm);
  box-shadow:
    0 2px 4px rgba(150, 100, 70, .06),
    0 18px 40px -22px rgba(150, 90, 70, .5);
}

.menu-pop button {
  display: block;
  width: 100%;
  padding: 9px 12px;
  font-size: 13.5px;
  text-align: left;
  border: none;
  border-radius: 9px;
  background: transparent;
  color: var(--ink);
}

.menu-pop button:hover:not(:disabled) {
  background: var(--accent-soft);
  color: var(--accent-deep);
  border: none;
}

.menu-hint {
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--ink-3);
  margin: 8px 12px 4px;
}

/* ---- 表单 ---- */

label {
  display: block;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-2);
  margin-bottom: 7px;
}

input[type=password],
input[type=text],
input[type=search],
textarea {
  width: 100%;
  padding: 12px 15px;
  font: inherit;
  color: var(--ink);
  background: var(--surface-sunk);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  transition: border-color .15s, box-shadow .15s, background .15s;
}

textarea { resize: vertical; }

input:focus, textarea:focus {
  outline: none;
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-soft);
}

::placeholder { color: var(--ink-3); }

.field { margin-bottom: 14px; }
.field:last-child { margin-bottom: 0; }

.row {
  display: flex;
  gap: 10px;
  margin-top: 16px;
  flex-wrap: wrap;
}

/* ---- 按钮 ---- */

button {
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  padding: 11px 22px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: 999px;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s, transform .1s;
}

button:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent-deep);
  background: var(--accent-soft);
}

button:active:not(:disabled) { transform: translateY(1px); }
button:disabled { opacity: .4; cursor: default; }

button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  box-shadow: 0 8px 18px -10px rgba(200, 90, 69, .75);
}

button.primary:hover:not(:disabled) {
  background: var(--accent-deep);
  border-color: var(--accent-deep);
  color: #fff;
}

button.ghost {
  background: transparent;
  border-color: var(--line-2);
  color: var(--ink-2);
}

button.danger:hover:not(:disabled) {
  border-color: var(--bad);
  color: var(--bad);
  background: var(--bad-soft);
}

/* ---- 通话画面 ---- */

/*
 * 通话画面。它常驻在 main 之外，靠下面这几组规则在大画面与小窗之间切换——
 * 元素自始至终是同一个，所以切到别的模块不会打断通话。
 */
#call-stage {
  position: relative;
  z-index: 2;
  width: min(720px, calc(100% - 36px));
  margin: 22px auto 0;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--video-bg);
  transition: width .26s ease, border-radius .26s ease, box-shadow .26s ease;
}

/* 切到相册或一起看：缩到右下角，变成一个小窗 */
body[data-view="space"] #call-stage,
body[data-view="watch"] #call-stage {
  position: fixed;
  z-index: 40;
  right: 16px;
  bottom: 16px;
  width: 168px;
  margin: 0;
  border-radius: 14px;
  box-shadow: 0 14px 34px -14px rgba(50, 26, 18, .62);
}

/* 相册右下角有个加号，小窗让开它 */
body[data-view="space"] #call-stage { bottom: 88px; }

body[data-view="space"] #call-stage > video,
body[data-view="watch"] #call-stage > video { aspect-ratio: 4 / 3; }

/* 小窗太小，本机画面与那行字都塞不下 */
body[data-view="space"] #call-stage .self,
body[data-view="watch"] #call-stage .self,
body[data-view="space"] #call-stage .stage-hint,
body[data-view="watch"] #call-stage .stage-hint { display: none; }

/* 「只留声」：画面整个撤掉，只留一条能挂断的窄条 */
body.call-audio-only #call-stage { width: 132px; border-radius: 999px; }
body.call-audio-only #call-stage > video,
body.call-audio-only #call-stage .stage-empty,
body.call-audio-only #call-stage .self { display: none; }
body.call-audio-only #call-stage .dock-bar {
  position: static;
  background: var(--video-bg);
  justify-content: space-between;
  padding: 7px 10px;
}

/* 缩成小窗时才出现的那一条。放不下字，所以只有图标。 */
.dock-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  padding: 6px 7px;
  background: linear-gradient(to top, rgba(26, 19, 16, .92), rgba(26, 19, 16, .1));
}

.dock-bar[hidden] { display: none; }

/*
 * 媒体路径角标。走中继就意味着画面与声音经过那台租来的服务器——
 * 这是隐私信息而不是排障信息，所以它常驻在画面上，不收进 ?debug 面板。
 * 位置取左上角：右下角是本机预览，底部这一条是缩小时的工具条。
 */
.path-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 3;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 12px;
  line-height: 1.6;
  color: #f4ece6;
  background: rgba(26, 19, 16, .55);
  pointer-events: none;
}

/* 中继那一档给个暖色：它比直连更该被注意到 */
.path-badge[data-path="relay"] {
  background: rgba(122, 74, 30, .8);
}

.dock-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #7fbf82;
  flex: none;
  margin-right: auto;
  animation: dock-pulse 1.9s ease-in-out infinite;
}

@keyframes dock-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: .35; }
}

.dock-btn {
  width: 26px;
  height: 26px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .24);
  background: rgba(255, 255, 255, .12);
  color: rgba(255, 255, 255, .92);
  cursor: pointer;
}

.dock-btn svg { width: 14px; height: 14px; display: block; }
.dock-btn:hover { background: rgba(255, 255, 255, .26); }

/* 没有话要说的时候这行整个不存在，不占地方 */
#connect-note:empty { display: none; }

.stage-video > video {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
  background: var(--video-bg);
}

/* 还没接通时盖在画面上的等待态，免得空着一个黑框 */
.stage-empty {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  padding: 24px;
  text-align: center;
  background: linear-gradient(160deg, #332b26, #241e1a);
}

.stage-hint {
  font-size: 13.5px;
  color: rgba(255, 255, 255, .45);
}

/* 等待时慢慢荡开的三圈水纹。比一行静止的字更像「在等人」。 */
.stage-rings {
  position: relative;
  display: block;
  width: 74px;
  height: 74px;
}

.stage-rings i {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid rgba(242, 149, 122, .5);
  animation: ring-out 3s ease-out infinite;
}

.stage-rings i:nth-child(2) { animation-delay: 1s; }
.stage-rings i:nth-child(3) { animation-delay: 2s; }

@keyframes ring-out {
  0%   { transform: scale(.34); opacity: 0; }
  25%  { opacity: .85; }
  100% { transform: scale(1); opacity: 0; }
}

/* 自己的画面缩成角上一小块，像照镜子 */
.self {
  position: absolute;
  right: 12px;
  bottom: 12px;
  width: 108px;
  border-radius: 12px;
  overflow: hidden;
  background: #000;
  border: 2px solid rgba(255, 255, 255, .85);
  box-shadow: 0 8px 20px -8px rgba(0, 0, 0, .55);
}

.self video {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  background: #000;
}

@media (max-width: 520px) {
  .self { width: 88px; right: 8px; bottom: 8px; }
}

/* ---- 拨号键 ----
   四个圆键，像电话那样。文字挂在键下面，不写进键里——
   键里装的是图标，状态靠类名和那行小字表达，观感不会被状态冲掉。 */

.dialer {
  display: flex;
  /* 五个键在窄屏上放不下一行。允许换行 + 间距跟着视口收，
     否则手机上会把「挂断」挤出屏幕——那是唯一一个不能找不到的键。 */
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(12px, 4vw, 28px);
  margin-top: 22px;
}

.ctl {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
}

.dial {
  width: 60px;
  height: 60px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--line-2);
  color: var(--ink-2);
  box-shadow: 0 2px 6px -2px rgba(150, 100, 70, .2);
  transition: background .15s, border-color .15s, color .15s, transform .1s;
}

.dial svg { width: 25px; height: 25px; }

.dial:hover:not(:disabled) {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-deep);
}

.dial:active:not(:disabled) { transform: translateY(1px); }

/* 按不动的键就退回灰底灰字，别让人对着一颗发光的绿键发呆 */
.dial:disabled {
  opacity: 1;
  background: var(--surface-sunk);
  border-color: var(--line);
  color: var(--ink-3);
  box-shadow: none;
}

/* 绿色的那个键：通话里唯一「往前走」的动作 */
.dial-go {
  background: var(--ok);
  border-color: var(--ok);
  color: #fff;
  box-shadow: 0 10px 22px -12px rgba(101, 140, 102, .95);
}

.dial-go:hover:not(:disabled) {
  background: #57795a;
  border-color: #57795a;
  color: #fff;
}

/* 对方在呼叫：这个键该被按下去，让它自己动起来 */
.dial-ringing { animation: dial-pulse 1.6s ease-out infinite; }

@keyframes dial-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(101, 140, 102, .40), 0 10px 22px -12px rgba(101, 140, 102, .95); }
  70%  { box-shadow: 0 0 0 15px rgba(101, 140, 102, 0), 0 10px 22px -12px rgba(101, 140, 102, .95); }
  100% { box-shadow: 0 0 0 0 rgba(101, 140, 102, 0), 0 10px 22px -12px rgba(101, 140, 102, .95); }
}

.dial-end { color: var(--bad); }

.dial-end:hover:not(:disabled) {
  background: var(--bad);
  border-color: var(--bad);
  color: #fff;
}

/* 关掉的键：底色沉下去，再拉一道斜线，一眼看出现在是关着的 */
.dial.switch-off {
  position: relative;
  background: var(--surface-sunk);
  border-color: var(--line);
  color: var(--ink-3);
}

.dial.switch-off svg { opacity: .4; }

.dial.switch-off::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 34px;
  height: 1.5px;
  border-radius: 2px;
  background: currentColor;
  transform: translate(-50%, -50%) rotate(-45deg);
}

.ctl-label {
  font-size: 11.5px;
  color: var(--ink-3);
  white-space: nowrap;
}

.ctl:has(.dial:disabled) .ctl-label { opacity: .45; }

/* ---- 设备选择 ----
   默认就是系统默认设备，这里只是让人能换。放在按键上面，
   因为该在按下绿色那个键之前决定。没有设备时整条不显示——
   摆一个空下拉比不摆更让人困惑。 */

.device-bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 18px;
  margin-top: 18px;
}

.device-field {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.device-key {
  font-size: 11.5px;
  color: var(--ink-3);
  white-space: nowrap;
}

.device-field select {
  max-width: 190px;
  padding: 5px 8px;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: 8px;
  text-overflow: ellipsis;
}

.device-field select:hover:not(:disabled) { border-color: var(--accent); }

.device-field select:disabled {
  color: var(--ink-3);
  background: var(--surface-sunk);
}

/* 首次进来还没有权限时的那个键。整条设备栏里只有它。 */
.device-allow {
  padding: 6px 13px;
  font-size: 12.5px;
  border-radius: 999px;
}

/* 对方在不在，一句话说清 */
.peer-line {
  font-size: 13px;
  color: var(--ink-3);
  margin: 16px 0 0;
  text-align: center;
}

.peer-line.here { color: var(--ok); }

/* ---- 拖放区 ---- */

.drop {
  border: 1.5px dashed var(--line-2);
  border-radius: var(--radius);
  padding: 30px 18px;
  text-align: center;
  color: var(--ink-2);
  font-size: 13.5px;
  background: var(--surface-sunk);
  cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
}

.drop:hover { border-color: var(--accent); color: var(--accent-deep); }
.drop.over { border-color: var(--accent); color: var(--accent-deep); background: var(--accent-soft); }

/* ---- 提示行 ---- */

.note-line {
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-2);
  margin: 12px 0 0;
  min-height: 20px;
}

.note-line.bad { color: var(--bad); }
.note-line.ok { color: var(--ok); }
/* 不是错误，但也不是顺利——比如「摄像头用不了，已按语音通话接通」 */
.note-line.warn { color: var(--warn); }

/* ---- 排障面板（仅 ?debug 时挂载） ---- */

.debug {
  background: var(--surface-sunk);
  box-shadow: none;
  border: 1px dashed var(--line-2);
}

.debug h2 {
  font-size: 13px;
  color: var(--ink-3);
  font-weight: 500;
  letter-spacing: .02em;
}

.debug dl {
  display: grid;
  grid-template-columns: 92px 1fr;
  gap: 6px 14px;
  margin: 0 0 4px;
  font-size: 13px;
}

.debug dt { color: var(--ink-3); }
.debug dd {
  margin: 0;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 12.5px;
  word-break: break-all;
}

.log {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 12px;
  color: var(--ink-2);
  max-height: 220px;
  overflow-y: auto;
}

.log li { padding: 3px 0; border-bottom: 1px solid var(--line); }
.log li:last-child { border-bottom: none; }
.log time { color: var(--ink-3); margin-right: 8px; }

/* ---- 右下角那个加号 ---- */

.fab {
  position: fixed;
  right: max(22px, calc(50vw - 460px));
  bottom: 28px;
  z-index: 25;
  width: 56px;
  height: 56px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  box-shadow: 0 14px 30px -12px rgba(200, 90, 69, .85);
  transition: background .16s;
}

.fab svg { width: 26px; height: 26px; transition: transform .22s; }

.fab:hover:not(:disabled) {
  background: var(--accent-deep);
  border: none;
  color: #fff;
}

/* 抽屉开着时它转成叉，同一个键负责开和关 */
.fab.fab-open svg { transform: rotate(45deg); }

/* ---- 从底部浮上来的抽屉 ---- */

.sheet {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 24;
  display: flex;
  justify-content: center;
  padding: 0 16px 100px;
  pointer-events: none;
  animation: sheet-up .22s ease-out;
}

.sheet-inner {
  pointer-events: auto;
  width: 100%;
  max-width: 520px;
  padding: 20px 22px;
  background: var(--surface);
  border-radius: 20px;
  box-shadow:
    0 -2px 8px -4px rgba(150, 100, 70, .12),
    0 -20px 50px -26px rgba(150, 90, 70, .55);
}

.sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}

.sheet-head h2 { margin: 0; }
.sheet .drop { margin-bottom: 12px; }

@keyframes sheet-up {
  from { transform: translateY(14px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}

/* 相册要更宽一些，照片才排得开 */
/*
 * 入口。它是外壳内的一层遮罩，不是另一个页面——
 * 填完就地消失，下面三个模块已经在等着了，不会重新加载任何东西。
 */
.gate {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 18px 48px;
  overflow-y: auto;
  background:
    radial-gradient(720px 420px at 50% -8%, rgba(224, 112, 90, .16), transparent 68%),
    radial-gradient(560px 380px at 82% 108%, rgba(232, 160, 110, .14), transparent 70%),
    radial-gradient(480px 320px at 8% 96%, rgba(190, 130, 170, .10), transparent 72%),
    var(--bg);
}

.gate-card {
  width: 100%;
  max-width: 400px;
  background: var(--surface);
  border-radius: 26px;
  padding: 36px 32px 28px;
  box-shadow:
    0 1px 2px rgba(150, 100, 70, .05),
    0 26px 60px -34px rgba(150, 90, 70, .5);
}

.gate-card h1 {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -.01em;
  margin: 0 0 6px;
}

.gate-lead {
  font-size: 13.5px;
  color: var(--ink-2);
  margin: 0 0 28px;
}

.gate-field {
  display: block;
  margin-bottom: 16px;
}

.gate-field > span {
  display: block;
  font-size: 12.5px;
  letter-spacing: .02em;
  color: var(--ink-2);
  margin-bottom: 7px;
}

.gate-field input { width: 100%; }

.gate-go {
  width: 100%;
  margin-top: 10px;
  padding: 13px 22px;
  font-size: 15px;
}

#gate-note { text-align: center; }
#gate-note:not(:empty) { margin-top: 14px; }

/* 入口底下那句「本设备会记住」。留它是为了让人知道暗号记在本机、下次不用再输，
   不是解释这套东西怎么实现的——实现解释不摆在界面上。 */
.gate-hint {
  font-size: 12px;
  line-height: 1.7;
  color: var(--ink-3);
  text-align: center;
  margin: 18px 0 0;
}

/* 备案编号。挂在入口卡片最底下——入口是全站唯一对外公开的一屏，
   进去之后都是私密内容，不需要带着这行字走。 */
.gate-foot {
  margin: 20px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-size: 11.5px;
  text-align: center;
}

.gate-foot a {
  color: var(--ink-3);
  text-decoration: none;
}

.gate-foot a:hover { text-decoration: underline; }

/* 相册锁是个弹窗，不是一整页：底下一层薄雾，中间一张窄卡片，解锁即收。
   点「取消」或点雾都回通话——相册没解锁时停在那儿也没内容可看。 */
.lock {
  position: fixed;
  inset: 0;
  z-index: 95;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 22px;
  background: rgba(59, 47, 41, .34);
}

.lock-card {
  width: 100%;
  max-width: 320px;
  background: var(--surface);
  border-radius: 20px;
  padding: 20px 20px 16px;
  box-shadow:
    0 1px 2px rgba(150, 100, 70, .06),
    0 26px 54px -28px rgba(150, 90, 70, .6);
}

.lock-title {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.005em;
  color: var(--ink);
  margin: 0 0 12px;
}

/* 只在「首次设置」时露出来：说清规则，说一次就够。
   已有内容的相册不显示它——那时候人只是来输一串已知的密码。 */
.lock-hint {
  font-size: 12px;
  line-height: 1.6;
  color: var(--ink-3);
  margin: 10px 0 0;
}

.lock-card input { width: 100%; }

.lock-row {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.lock-row button { padding: 11px 14px; font-size: 14px; }
.lock-row .ghost { flex: none; }
.lock-row .primary { flex: 1; }

#space-lock-note { text-align: center; }

/* 提示行没话说的时候不该占位置。留着 min-height 会在卡片中间凭空压出一段空白，
   按钮被推得离输入框很远，整张卡片就散了。 */
.lock-card .note-line:empty { margin-top: 0; min-height: 0; }

/* 换密码是「说明在上、连输两遍」的排法，跟相册锁（一个框、下面补一句规则）
   不是同一套节奏，所以这里的间距单独定。两个框贴在一起会被读成一个。 */
#space-repass .lock-hint { margin: 0 0 12px; }
#space-repass input + input { margin-top: 10px; }
#space-repass .lock-row { margin-top: 16px; }
#space-repass .lock-row .ghost { flex: 1; }

@media (max-width: 520px) {
  .gate { padding: 20px 14px 36px; align-items: flex-start; }
  .gate-card { padding: 28px 22px 24px; border-radius: 22px; }
  .gate-card h1 { font-size: 20px; }
}

.hidden { display: none !important; }

@media (max-width: 560px) {
  main { padding: 18px 14px 56px; }
  main.center { padding-bottom: 36px; }
  .card { padding: 18px 18px; border-radius: 16px; }

  .bar { gap: 7px; padding: 9px 12px; }

  /* 顶栏在窄屏上挤不下：品牌名收成一个圆点，备份菜单也让位给导航 */
  .brand { font-size: 0; gap: 0; }
  .brand::before { width: 13px; height: 13px; }
  .nav { gap: 1px; }
  .nav a { font-size: 12.5px; padding: 6px 9px; }
  .pill { font-size: 11px; gap: 5px; padding: 3px 9px; }
  .lock-btn, .icon-btn { width: 28px; height: 28px; }
  .lock-btn svg, .icon-btn svg { width: 15px; height: 15px; }
  .menu { display: none; }

  .dialer { gap: 18px; }
  .dial { width: 54px; height: 54px; }
  .dial svg { width: 22px; height: 22px; }
  .ctl-label { font-size: 11px; }

  /* 窄屏上并排放不下两个下拉，改成上下两行，各占满宽度 */
  .device-bar { flex-direction: column; align-items: stretch; gap: 9px; }
  .device-field { justify-content: space-between; }
  .device-field select { flex: 1; max-width: none; }
  /* 但授权键不该跟着拉满整行——它不是输入项，是个动作 */
  .device-allow { align-self: center; }

  .fab { right: 18px; bottom: 22px; width: 52px; height: 52px; }
  .sheet { padding: 0 10px 86px; }
  .sheet-inner { padding: 18px 16px; border-radius: 18px; }
}
