/* ============================================================
   chat-friend-map · M3 Expressive（Material You 3）风格
   设计语言复刻自 blankroom / bus 站点：圆角 + tonal 色彩角色 +
   明暗映射 + 顶部栏 + FAB + 底部 sheet + 对话框 + ripple 状态层。
   零外部字体 / 零外部组件库（仅地图用 Leaflet）。
   ============================================================ */

:root{
  color-scheme:light;
  --primary:#4f55b8;--on-primary:#fff;--primary-container:#e2e1ff;
  --on-primary-container:#111553;--secondary-container:#dce8ff;--on-secondary-container:#101c35;
  --tertiary:#a8436e;--tertiary-container:#ffd8e8;--on-tertiary-container:#3c001d;
  --surface:#fcf8ff;--surface-lowest:#ffffff;
  --surface-low:#f6f2fc;--surface-mid:#f1ecf9;--surface-high:#ebe5f4;--surface-highest:#e5deef;
  --on-surface:#1b1b21;--on-surface-variant:#46434e;--outline:#78717e;--outline-variant:#cac4d4;
  --map-wash:rgba(79,85,184,.10);
}
/* 兜底深色值（--d-*），主题块会覆盖 */
:root{
  --d-primary:#c7c2ff;--d-on-primary:#262a72;--d-primary-container:#393b75;
  --d-on-primary-container:#e2e1ff;--d-secondary-container:#304365;
  --d-on-secondary-container:#dce8ff;--d-tertiary:#f2a8c8;--d-tertiary-container:#63304a;
  --d-on-tertiary-container:#ffd8e8;--d-surface:#131218;--d-surface-lowest:#0c0b10;
  --d-surface-low:#1c1b21;--d-surface-mid:#211f26;--d-surface-high:#2b2931;--d-surface-highest:#36343c;
  --d-on-surface:#e6e0ec;--d-on-surface-variant:#c9c4d1;--d-outline:#938f9c;
  --d-outline-variant:#48454f;--d-map-wash:rgba(199,194,255,.15);
  --d-scrim:rgba(0,0,0,.6);
  --d-elev-1:0 1px 2px rgba(0,0,0,.4),0 2px 6px rgba(0,0,0,.3);
  --d-elev-2:0 1px 2px rgba(0,0,0,.4),0 6px 16px rgba(0,0,0,.36);
  --d-elev-3:0 4px 12px rgba(0,0,0,.44),0 16px 36px rgba(0,0,0,.5);
  --error:#b3261e;--error-container:#f9dedc;--on-error-container:#410e0b;
  --d-error:#f2b8b5;--d-error-container:#8c1d18;--d-on-error-container:#ffdad6;
  --scrim:rgba(29,27,32,.42);
  --elev-1:0 1px 2px rgba(28,27,31,.16),0 2px 6px rgba(28,27,31,.08);
  --elev-2:0 1px 2px rgba(28,27,31,.16),0 6px 16px rgba(28,27,31,.12);
  --elev-3:0 4px 12px rgba(28,27,31,.14),0 16px 36px rgba(28,27,31,.16);
  --sh-xs:8px; --sh-sm:12px; --sh-md:16px; --sh-lg:24px; --sh-xl:28px;
  --on-error:#fff;
  --topbar-h:68px; --sat:0px;
  --hairline:color-mix(in srgb,var(--outline-variant) 76%,transparent);
  --ease:cubic-bezier(.2,0,0,1);
  --spring:cubic-bezier(.34,1.56,.64,1);
}
/* ===== 可选主题色（data-theme 切换，保存到本地） ===== */
:root[data-theme="indigo"]{--primary:#4f55b8;--on-primary:#fff;--primary-container:#e2e1ff;--on-primary-container:#111553;--secondary-container:#dce8ff;--on-secondary-container:#101c35;--tertiary:#a8436e;--tertiary-container:#ffd8e8;--on-tertiary-container:#3c001d;--surface:#fcf8ff;--surface-lowest:#ffffff;--surface-low:#f6f2fc;--surface-mid:#f1ecf9;--surface-high:#ebe5f4;--surface-highest:#e5deef;--on-surface:#1b1b21;--on-surface-variant:#46434e;--outline:#78717e;--outline-variant:#cac4d4;--map-wash:rgba(79,85,184,.10);}
:root[data-theme="indigo"]{--d-primary:#c7c2ff;--d-on-primary:#262a72;--d-primary-container:#393b75;--d-on-primary-container:#e2e1ff;--d-secondary-container:#304365;--d-on-secondary-container:#dce8ff;--d-tertiary:#f2a8c8;--d-tertiary-container:#63304a;--d-on-tertiary-container:#ffd8e8;--d-surface:#131218;--d-surface-lowest:#0c0b10;--d-surface-low:#1c1b21;--d-surface-mid:#211f26;--d-surface-high:#2b2931;--d-surface-highest:#36343c;--d-on-surface:#e6e0ec;--d-on-surface-variant:#c9c4d1;--d-outline:#938f9c;--d-outline-variant:#48454f;--d-map-wash:rgba(199,194,255,.15);}
:root[data-theme="teal"]{--primary:#006a60;--on-primary:#fff;--primary-container:#9cf3e7;--on-primary-container:#00201c;--secondary-container:#c8e8e2;--on-secondary-container:#08201d;--tertiary:#825500;--tertiary-container:#ffddae;--on-tertiary-container:#291600;--surface:#f5fbf8;--surface-lowest:#ffffff;--surface-low:#eef7f3;--surface-mid:#e7f2ed;--surface-high:#dfede7;--surface-highest:#d6e7e0;--on-surface:#131c19;--on-surface-variant:#3f4946;--outline:#6f7975;--outline-variant:#bfc9c4;--map-wash:rgba(0,106,96,.10);}
:root[data-theme="teal"]{--d-primary:#6ff7e7;--d-on-primary:#003731;--d-primary-container:#00504a;--d-on-primary-container:#9cf3e7;--d-secondary-container:#234e49;--d-on-secondary-container:#c8e8e2;--d-tertiary:#e0bb5a;--d-tertiary-container:#523c00;--d-on-tertiary-container:#ffddae;--d-surface:#0d1513;--d-surface-lowest:#070e0c;--d-surface-low:#15201d;--d-surface-mid:#1a2522;--d-surface-high:#24302c;--d-surface-highest:#2e3b36;--d-on-surface:#dde5e1;--d-on-surface-variant:#c0c9c4;--d-outline:#8a938f;--d-outline-variant:#3f4946;--d-map-wash:rgba(111,247,231,.15);}
:root[data-theme="rose"]{--primary:#ba478f;--on-primary:#fff;--primary-container:#ffd7ee;--on-primary-container:#3f0a2e;--secondary-container:#ffd9e4;--on-secondary-container:#3f1228;--tertiary:#7a4b00;--tertiary-container:#ffddae;--on-tertiary-container:#291600;--surface:#fff8f9;--surface-lowest:#ffffff;--surface-low:#fdf0f3;--surface-mid:#f9e9ee;--surface-high:#f5e0e7;--surface-highest:#efd7df;--on-surface:#1f1418;--on-surface-variant:#4c3f44;--outline:#7e7176;--outline-variant:#d0c3c8;--map-wash:rgba(186,71,143,.10);}
:root[data-theme="rose"]{--d-primary:#f2a8c8;--d-on-primary:#5c113f;--d-primary-container:#7d285d;--d-on-primary-container:#ffd7ee;--d-secondary-container:#62314a;--d-on-secondary-container:#ffd9e4;--d-tertiary:#e0bb5a;--d-tertiary-container:#523c00;--d-on-tertiary-container:#ffddae;--d-surface:#181113;--d-surface-lowest:#110b0d;--d-surface-low:#221a1d;--d-surface-mid:#261e21;--d-surface-high:#31282b;--d-surface-highest:#3d3336;--d-on-surface:#ecdde1;--d-on-surface-variant:#d1c2c7;--d-outline:#9a8b90;--d-outline-variant:#4b3f43;--d-map-wash:rgba(242,168,200,.15);}
:root[data-theme="amber"]{--primary:#8a5a00;--on-primary:#fff;--primary-container:#ffd9a3;--on-primary-container:#2c1800;--secondary-container:#ffe2bf;--on-secondary-container:#2c1700;--tertiary:#6b538c;--tertiary-container:#e7d9ff;--on-tertiary-container:#241a36;--surface:#fffbf4;--surface-lowest:#ffffff;--surface-low:#fdf6ea;--surface-mid:#faf0e0;--surface-high:#f6e9d4;--surface-highest:#f1e1c8;--on-surface:#1e1a12;--on-surface-variant:#4b463a;--outline:#7c7668;--outline-variant:#cec7b7;--map-wash:rgba(138,90,0,.11);}
:root[data-theme="amber"]{--d-primary:#ffb95c;--d-on-primary:#4a2e00;--d-primary-container:#5e4200;--d-on-primary-container:#ffd9a3;--d-secondary-container:#5f4521;--d-on-secondary-container:#ffe2bf;--d-tertiary:#cbb2e8;--d-tertiary-container:#3f2d63;--d-on-tertiary-container:#e7d9ff;--d-surface:#16130c;--d-surface-lowest:#0f0d07;--d-surface-low:#201c14;--d-surface-mid:#241f17;--d-surface-high:#2f2a20;--d-surface-highest:#3a352a;--d-on-surface:#ebe2d3;--d-on-surface-variant:#d0c7b8;--d-outline:#9a9283;--d-outline-variant:#4b463a;--d-map-wash:rgba(255,185,92,.15);}
:root[data-theme="graphite"]{--primary:#4c5c68;--on-primary:#fff;--primary-container:#d7e3ec;--on-primary-container:#08141c;--secondary-container:#dde3e8;--on-secondary-container:#171c20;--tertiary:#6b5a7d;--tertiary-container:#e8def7;--on-tertiary-container:#231431;--surface:#f9f9fb;--surface-lowest:#ffffff;--surface-low:#f3f3f6;--surface-mid:#ededf1;--surface-high:#e6e6eb;--surface-highest:#dfdfe5;--on-surface:#1a1c1e;--on-surface-variant:#43474a;--outline:#74777b;--outline-variant:#c4c7cb;--map-wash:rgba(76,92,104,.09);}
:root[data-theme="graphite"]{--d-primary:#b9c7d2;--d-on-primary:#22323d;--d-primary-container:#36434d;--d-on-primary-container:#d7e3ec;--d-secondary-container:#373d42;--d-on-secondary-container:#dde3e8;--d-tertiary:#cdc2e0;--d-tertiary-container:#3a2c47;--d-on-tertiary-container:#e8def7;--d-surface:#121316;--d-surface-lowest:#0b0c0e;--d-surface-low:#1b1d20;--d-surface-mid:#202225;--d-surface-high:#2a2c30;--d-surface-highest:#35373c;--d-on-surface:#e3e4e8;--d-on-surface-variant:#c6c7cc;--d-outline:#8f9196;--d-outline-variant:#45474b;--d-map-wash:rgba(185,199,210,.13);}

/* ===== 明暗映射：跟随系统 / 手动指定 ===== */
@media (prefers-color-scheme:dark){
  :root:not([data-mode="light"]){
    color-scheme:dark;
    --primary:var(--d-primary);--on-primary:var(--d-on-primary);--primary-container:var(--d-primary-container);--on-primary-container:var(--d-on-primary-container);--secondary-container:var(--d-secondary-container);--on-secondary-container:var(--d-on-secondary-container);--tertiary:var(--d-tertiary);--tertiary-container:var(--d-tertiary-container);--on-tertiary-container:var(--d-on-tertiary-container);--surface:var(--d-surface);--surface-lowest:var(--d-surface-lowest);--surface-low:var(--d-surface-low);--surface-mid:var(--d-surface-mid);--surface-high:var(--d-surface-high);--surface-highest:var(--d-surface-highest);--on-surface:var(--d-on-surface);--on-surface-variant:var(--d-on-surface-variant);--outline:var(--d-outline);--outline-variant:var(--d-outline-variant);--map-wash:var(--d-map-wash);--scrim:var(--d-scrim);--elev-1:var(--d-elev-1);--elev-2:var(--d-elev-2);--elev-3:var(--d-elev-3);--error:var(--d-error);--error-container:var(--d-error-container);--on-error-container:var(--d-on-error-container);
  }
}
:root[data-mode="dark"]{
  color-scheme:dark;
  --primary:var(--d-primary);--on-primary:var(--d-on-primary);--primary-container:var(--d-primary-container);--on-primary-container:var(--d-on-primary-container);--secondary-container:var(--d-secondary-container);--on-secondary-container:var(--d-on-secondary-container);--tertiary:var(--d-tertiary);--tertiary-container:var(--d-tertiary-container);--on-tertiary-container:var(--d-on-tertiary-container);--surface:var(--d-surface);--surface-lowest:var(--d-surface-lowest);--surface-low:var(--d-surface-low);--surface-mid:var(--d-surface-mid);--surface-high:var(--d-surface-high);--surface-highest:var(--d-surface-highest);--on-surface:var(--d-on-surface);--on-surface-variant:var(--d-on-surface-variant);--outline:var(--d-outline);--outline-variant:var(--d-outline-variant);--map-wash:var(--d-map-wash);--scrim:var(--d-scrim);--elev-1:var(--d-elev-1);--elev-2:var(--d-elev-2);--elev-3:var(--d-elev-3);--error:var(--d-error);--error-container:var(--d-error-container);--on-error-container:var(--d-on-error-container);
}
:root[data-mode="light"]{color-scheme:light}

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0;height:100%;overflow:hidden}
body{
  background:
    radial-gradient(120% 90% at 100% 0%,color-mix(in srgb,var(--primary-container) 74%,transparent) 0%,transparent 58%),
    radial-gradient(95% 72% at 0% 100%,color-mix(in srgb,var(--tertiary-container) 54%,transparent) 0%,transparent 56%),
    var(--surface);
  color:var(--on-surface);
  font:400 14px/1.5 "Google Sans","Roboto Flex",-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei","Noto Sans SC","Apple Color Emoji","Noto Color Emoji","Segoe UI Emoji",sans-serif;
  -webkit-font-smoothing:antialiased;
}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;border:0;background:none}
h1,h2,h3,p{margin:0}

/* ---------- state layer / ripple ---------- */
.state{position:relative;overflow:hidden;isolation:isolate}
.state::before{content:"";position:absolute;inset:0;background:currentColor;opacity:0;pointer-events:none;transition:opacity .18s var(--ease);z-index:-1}
.state:hover::before{opacity:var(--state-hover,.08)}
.state:active::before{opacity:var(--state-press,.12)}
.state:focus-visible{outline:2px solid var(--primary);outline-offset:2px}
.ripple{position:absolute;border-radius:50%;background:currentColor;opacity:.22;transform:scale(0);pointer-events:none;animation:ripple .55s var(--ease) forwards}
@keyframes ripple{to{transform:scale(2.6);opacity:0}}

.app{display:flex;flex-direction:column;height:100vh;height:100dvh;min-height:100vh;min-height:100dvh}

/* ---------- top app bar ---------- */
.topbar{
  flex:0 0 auto;display:flex;align-items:center;gap:12px;
  height:calc(var(--topbar-h) + var(--sat));
  padding:var(--sat) 16px 0;
  background:transparent;z-index:20;
  box-shadow:inset 0 -1px 0 var(--hairline);
  transition:box-shadow .2s var(--ease),background .2s var(--ease);
}
.brand-mark{
  width:42px;height:42px;flex:0 0 auto;border-radius:var(--sh-md);
  background:var(--primary-container);color:var(--on-primary-container);
  display:grid;place-items:center;
}
.brand-mark svg{width:24px;height:24px}
.titles{min-width:0}
.titles h1{font-size:20px;font-weight:500;letter-spacing:0;line-height:1.3}
.titles small{display:block;font-size:11px;color:var(--on-surface-variant);font-weight:400;line-height:1.2}
.spacer{flex:1 1 auto}
.status-chip{
  display:inline-flex;align-items:center;gap:8px;height:34px;padding:0 14px;
  border-radius:999px;background:var(--surface-high);color:var(--on-surface-variant);
  font-size:12px;font-weight:500;white-space:nowrap;flex:0 0 auto;
}
.status-chip .pulse{width:8px;height:8px;border-radius:50%;background:var(--outline);flex:0 0 auto}
.status-chip.live{background:var(--primary-container);color:var(--on-primary-container)}
.status-chip.live .pulse{background:var(--primary);animation:pulse 2s infinite}
.status-chip.warn{background:var(--tertiary-container);color:var(--on-tertiary-container)}
.status-chip.warn .pulse{background:var(--tertiary)}
@keyframes pulse{0%,100%{box-shadow:0 0 0 0 var(--map-wash)}50%{box-shadow:0 0 0 6px transparent}}
.icon-button{
  width:42px;height:42px;flex:0 0 auto;border-radius:999px;color:var(--on-surface-variant);
  display:grid;place-items:center;transition:background .18s var(--ease),transform .3s var(--spring);
}
.icon-button svg{width:21px;height:21px}
.icon-button:hover{background:var(--surface-high);color:var(--primary)}
.icon-button.spin svg{animation:spin .9s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---------- map stage ---------- */
.stage{flex:1 1 auto;position:relative;min-height:0;background:var(--surface-highest);overflow:hidden}
#map{position:absolute;inset:0;width:100%;height:100%;background:var(--surface-highest);z-index:2}
/* 主题色纱盖在地图上方，切主题时地图氛围跟着变 */
.map-wash{position:absolute;inset:0;z-index:3;pointer-events:none;
  background:
    radial-gradient(120% 80% at 100% 0%,color-mix(in srgb,var(--primary-container) 30%,transparent),transparent 60%),
    radial-gradient(90% 70% at 0% 100%,color-mix(in srgb,var(--tertiary-container) 26%,transparent),transparent 60%),
    var(--map-wash);
  mix-blend-mode:normal;}
.map-credit{
  position:absolute;right:10px;bottom:8px;z-index:4;
  font-size:10px;color:var(--on-surface-variant);opacity:.7;
  background:color-mix(in srgb,var(--surface-lowest) 92%,transparent);
  padding:2px 7px;border-radius:var(--sh-xs);pointer-events:none;
}
/* Leaflet 弹窗/控件跟随主题 */
.leaflet-container{background:var(--surface-highest);font:inherit}
.leaflet-control-attribution{background:color-mix(in srgb,var(--surface-lowest) 80%,transparent)!important;color:var(--on-surface-variant)!important}
.leaflet-bar a{background:var(--surface-lowest)!important;color:var(--on-surface-variant)!important;border-color:var(--outline-variant)!important}
.leaflet-popup-content-wrapper{background:var(--surface-lowest);color:var(--on-surface);border-radius:var(--sh-md);box-shadow:var(--elev-2)}
.leaflet-popup-tip{background:var(--surface-lowest)}

/* ---------- 头像标记（他人 / 自己） ---------- */
.av-marker{position:relative;width:44px;height:44px;display:grid;place-items:center;transform:translate(-50%,-50%)}
.av-marker .ring{
  position:absolute;inset:0;border-radius:50%;
  background:var(--primary-container);color:var(--on-primary-container);
  display:grid;place-items:center;font-weight:600;font-size:17px;
  box-shadow:var(--elev-2);border:2px solid var(--surface-lowest);
  transition:transform .3s var(--spring),background .2s var(--ease);
}
.av-marker.me .ring{background:var(--primary);color:var(--on-primary);width:40px;height:40px;inset:2px}
.av-marker.known .ring{background:var(--tertiary-container);color:var(--on-tertiary-container)}
.av-marker:hover .ring{transform:scale(1.08)}
.av-marker .pulse-ring{position:absolute;inset:0;border-radius:50%;border:2px solid var(--primary);opacity:.5;animation:avpulse 2.2s infinite}
.av-marker.me .pulse-ring{border-color:var(--primary)}
@keyframes avpulse{0%{transform:scale(.7);opacity:.6}70%{transform:scale(1.25);opacity:0}100%{opacity:0}}
/* 飞过的表情 */
.float-emoji{position:absolute;left:50%;top:-6px;transform:translate(-50%,0);font-size:30px;z-index:30;pointer-events:none;animation:floatup 1.6s var(--ease) forwards}
@keyframes floatup{0%{opacity:0;transform:translate(-50%,10px) scale(.5)}20%{opacity:1}100%{opacity:0;transform:translate(-50%,-46px) scale(1.2)}}

/* ---------- floating info / HUD ---------- */
.hud{position:absolute;left:16px;top:16px;z-index:6;display:flex;flex-direction:column;gap:8px;align-items:flex-start;max-width:min(330px,calc(100vw - 32px))}
.stat-card{
  background:color-mix(in srgb,var(--surface-lowest) 94%,var(--primary) 6%);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  border-radius:var(--sh-lg);padding:12px 16px;box-shadow:var(--elev-2);
  display:flex;align-items:center;gap:12px;
}
.stat-card .big{font-size:30px;font-weight:500;line-height:1;letter-spacing:-1px;color:var(--primary)}
.stat-card .txt{font-size:11.5px;color:var(--on-surface-variant);line-height:1.4}
.stat-card .txt b{display:block;font-size:12.5px;color:var(--on-surface);font-weight:500}
.stat-card .txt span{display:block;margin-top:3px;font-size:10.5px;color:var(--on-surface-variant);white-space:nowrap}

/* 可查找开关卡（仿 near-card） */
.near-card{
  display:flex;align-items:center;gap:10px;text-align:left;
  width:min(330px,calc(100vw - 32px));padding:9px 12px 9px 9px;
  border-radius:var(--sh-lg);background:var(--primary-container);color:var(--on-primary-container);
  box-shadow:var(--elev-2);transition:transform .3s var(--spring),background .2s var(--ease);
}
.near-card:hover{transform:translateY(-2px)}
.near-card:active{transform:scale(.98)}
.near-card[data-state="off"]{background:var(--surface-high);color:var(--on-surface-variant)}
.near-ic{width:34px;height:34px;flex:0 0 auto;border-radius:50%;display:grid;place-items:center;background:var(--surface-lowest);color:var(--primary)}
.near-ic svg{width:19px;height:19px}
.near-txt{min-width:0;flex:1 1 auto}
.near-txt b{display:block;font-size:13px;font-weight:500;line-height:1.35;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.near-txt small{display:block;font-size:11px;line-height:1.45;opacity:.78;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* M3 switch */
.switch{width:42px;height:24px;border-radius:999px;background:var(--outline-variant);position:relative;flex:0 0 auto;transition:background .2s var(--ease)}
.switch i{position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:50%;background:#fff;box-shadow:var(--elev-1);transition:transform .25s var(--spring),background .2s var(--ease)}
.near-card[data-state="on"] .switch{background:var(--primary)}
.near-card[data-state="on"] .switch i{transform:translateX(18px);background:var(--on-primary)}

/* ---------- fabs ---------- */
.fabs{position:absolute;right:16px;top:16px;z-index:6;display:flex;flex-direction:column;gap:10px;align-items:center}
.fab{
  width:48px;height:48px;border-radius:var(--sh-md);display:grid;place-items:center;
  background:var(--surface-lowest);color:var(--on-surface-variant);box-shadow:var(--elev-2);
  transition:transform .3s var(--spring),background .18s var(--ease),color .18s var(--ease);
}
.fab:hover{transform:scale(1.06);color:var(--primary)}
.fab:active{transform:scale(.94)}
.fab svg{width:21px;height:21px}
.fab.primary{width:56px;height:56px;background:var(--primary-container);color:var(--on-primary-container)}
.fab.active{background:var(--primary);color:var(--on-primary)}
.seg{display:flex;gap:2px;padding:4px;border-radius:999px;background:var(--surface-lowest);box-shadow:var(--elev-2);margin-top:2px}
.seg button{width:38px;height:34px;border-radius:999px;font-size:11px;font-weight:500;color:var(--on-surface-variant);transition:background .2s var(--ease),color .2s var(--ease)}
.seg button.on{background:var(--secondary-container);color:var(--on-secondary-container)}

.zoom-ctl{position:absolute;right:16px;bottom:24px;z-index:6;display:flex;flex-direction:column;overflow:hidden;border-radius:var(--sh-md);background:var(--surface-lowest);box-shadow:var(--elev-2)}
.zoom-ctl button{width:46px;height:42px;display:grid;place-items:center;color:var(--on-surface-variant);font-size:19px;font-weight:500;line-height:1;transition:background .18s var(--ease),color .18s var(--ease)}
.zoom-ctl button+button{border-top:1px solid var(--outline-variant)}
.zoom-ctl button:hover{background:var(--surface-high);color:var(--primary)}

/* ---------- M3 bottom sheet ---------- */
.sheet{
  position:absolute;left:16px;bottom:16px;width:min(420px,calc(100% - 32px));z-index:8;
  background:color-mix(in srgb,var(--surface-low) 97%,var(--primary) 3%);
  border-radius:var(--sh-xl);box-shadow:var(--elev-3);
  max-height:120px;overflow:hidden;
  transition:max-height .42s var(--ease),border-radius .3s var(--ease);
}
.sheet.expanded{max-height:min(72vh,560px);max-height:min(72dvh,560px);overflow-y:auto}
.sheet-handle{display:block;width:100%;height:22px;flex:0 0 auto;display:grid;place-items:center}
.sheet-handle i{width:32px;height:4px;border-radius:999px;background:var(--outline-variant);display:block}
.sheet-head{display:flex;align-items:center;gap:10px;padding:2px 20px 12px}
.sheet-head h2{font-size:17px;font-weight:500;letter-spacing:0}
.live-pill{margin-left:auto;flex:0 0 auto;height:28px;padding:0 12px;border-radius:999px;background:var(--tertiary-container);color:var(--on-tertiary-container);font-size:11px;font-weight:500;display:grid;place-items:center}
.live-pill.on{background:var(--primary-container);color:var(--on-primary-container)}

/* ---------- 对话框（设置 / 资料 / 大厅） ---------- */
.scrim{position:fixed;inset:0;background:var(--scrim);z-index:40;opacity:0;pointer-events:none;transition:opacity .25s var(--ease)}
.scrim.show{opacity:1;pointer-events:auto}
.dialog{
  position:fixed;left:50%;top:50%;transform:translate(-50%,-48%) scale(.98);
  width:min(520px,calc(100vw - 28px));max-height:min(86vh,720px);max-height:min(86dvh,720px);overflow:hidden;z-index:50;
  background:var(--surface-low);border-radius:var(--sh-xl);box-shadow:var(--elev-3);
  display:flex;flex-direction:column;opacity:0;pointer-events:none;
  transition:opacity .25s var(--ease),transform .3s var(--spring);
}
.dialog.show{opacity:1;pointer-events:auto;transform:translate(-50%,-50%) scale(1)}
.dialog-head{padding:22px 22px 6px}
.dialog-head h2{font-size:20px;font-weight:500}
.dialog-head p{font-size:12.5px;color:var(--on-surface-variant);margin-top:4px}
.dialog-body{padding:10px 22px 4px;overflow-y:auto}
.dialog-actions{display:flex;justify-content:flex-end;gap:8px;padding:14px 18px 18px}
.field{margin-bottom:14px}
.field>label{display:block;font-size:12px;font-weight:500;color:var(--on-surface-variant);margin-bottom:7px}
.input,.textarea{
  width:100%;padding:11px 14px;border-radius:var(--sh-md);
  background:var(--surface-high);color:var(--on-surface);
  border:1px solid transparent;outline:none;transition:border-color .2s var(--ease),background .2s var(--ease);
}
.input:focus,.textarea:focus{border-color:var(--primary);background:var(--surface-mid)}
.textarea{resize:vertical;min-height:64px}
.row{display:flex;gap:10px}
.row>*{flex:1 1 0;min-width:0}
.hint{font-size:11px;color:var(--on-surface-variant);margin-top:6px;line-height:1.5}
.divider{border:0;border-top:1px solid var(--hairline);margin:14px 0}

/* 主题色板 */
.theme-row{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
.theme-row .lbl{font-size:12px;color:var(--on-surface-variant);margin-right:4px}
.swatch{width:34px;height:34px;border-radius:50%;box-shadow:var(--elev-1);transition:transform .2s var(--spring);outline:2px solid transparent}
.swatch:hover{transform:scale(1.1)}
.swatch.sel{outline-color:var(--primary);outline-offset:2px}
.mode-row{display:flex;gap:8px}
.mode-btn{flex:1;height:38px;border-radius:999px;background:var(--surface-high);color:var(--on-surface-variant);font-size:12.5px;font-weight:500;transition:background .2s var(--ease),color .2s var(--ease)}
.mode-btn.on{background:var(--secondary-container);color:var(--on-secondary-container)}
.switch-row{display:flex;align-items:center;gap:12px;width:100%;padding:10px 0;text-align:left}
.switch-txt b{font-size:13.5px;font-weight:500}
.switch-txt small{display:block;font-size:11px;color:var(--on-surface-variant);margin-top:2px}
.switch-row .switch{margin-left:auto}
.switch-row[aria-checked="true"] .switch{background:var(--primary)}
.switch-row[aria-checked="true"] .switch i{transform:translateX(18px);background:var(--on-primary)}

/* 按钮 */
.filled-btn{height:40px;padding:0 20px;border-radius:999px;background:var(--primary);color:var(--on-primary);font-weight:500;font-size:13.5px;transition:transform .2s var(--spring),filter .2s var(--ease)}
.filled-btn:hover{filter:brightness(1.05)}
.filled-btn:active{transform:scale(.96)}
.filled-btn[disabled]{opacity:.5;pointer-events:none}
.text-btn{height:40px;padding:0 16px;border-radius:999px;color:var(--primary);font-weight:500;font-size:13.5px;transition:background .18s var(--ease)}
.text-btn:hover{background:var(--surface-high)}
.mini{height:34px;padding:0 14px;border-radius:999px;background:var(--surface-high);color:var(--on-surface-variant);font-size:12px;font-weight:500}

/* ---------- 对方资料 sheet 内容 ---------- */
.peer{display:flex;align-items:center;gap:12px;padding:4px 20px 14px}
.peer .av{width:52px;height:52px;border-radius:50%;background:var(--tertiary-container);color:var(--on-tertiary-container);display:grid;place-items:center;font-size:22px;font-weight:600;flex:0 0 auto}
.peer .meta{min-width:0}
.peer .meta b{font-size:17px;font-weight:600;display:block}
.peer .meta small{font-size:11.5px;color:var(--on-surface-variant)}
.kv{display:flex;gap:10px;padding:8px 20px;align-items:baseline}
.kv .k{font-size:12px;color:var(--on-surface-variant);flex:0 0 72px}
.kv .v{font-size:13px;font-weight:500;word-break:break-all;flex:1 1 auto;min-width:0}
.kv .v.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}
.chips{display:flex;flex-wrap:wrap;gap:8px;padding:2px 20px 6px}
.game-chip{height:30px;padding:0 12px;border-radius:999px;background:var(--secondary-container);color:var(--on-secondary-container);font-size:12px;font-weight:500;display:inline-flex;align-items:center;gap:6px}
.game-chip b{font-weight:600}
.section-t{font-size:12px;font-weight:500;color:var(--on-surface-variant);padding:10px 20px 6px}
.label-input{display:flex;gap:8px;padding:4px 20px 8px}
.label-input input{flex:1}

/* emoji 网格 */
.emoji-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;padding:6px 16px 14px}
.emoji-grid button{height:46px;border-radius:var(--sh-sm);font-size:24px;background:var(--surface-high);transition:transform .2s var(--spring),background .18s var(--ease)}
.emoji-grid button:hover{transform:scale(1.12);background:var(--surface-mid)}
.emoji-grid button:active{transform:scale(.9)}

/* 互认后的联系方式条 */
.contact-bar{display:flex;gap:10px;padding:6px 20px 14px}
.contact-bar button{flex:1;height:44px;border-radius:var(--sh-md);display:flex;align-items:center;justify-content:center;gap:8px;font-size:13.5px;font-weight:500;background:var(--primary-container);color:var(--on-primary-container);transition:transform .2s var(--spring)}
.contact-bar button:active{transform:scale(.96)}
.contact-bar button svg{width:19px;height:19px}
.willing-banner{margin:2px 16px 12px;padding:12px 14px;border-radius:var(--sh-md);background:var(--tertiary-container);color:var(--on-tertiary-container);font-size:13px;display:flex;align-items:center;gap:10px}
.willing-banner .acts{margin-left:auto;display:flex;gap:8px}
.willing-banner button{height:32px;padding:0 14px;border-radius:999px;font-weight:500;font-size:12.5px}
.willing-banner .ok{background:var(--primary);color:var(--on-primary)}
.willing-banner .no{background:var(--surface-high);color:var(--on-surface-variant)}

/* ---------- 游戏大厅 ---------- */
.lobby-list{display:flex;flex-direction:column;gap:10px;padding:4px 0 8px}
.lobby-empty{text-align:center;color:var(--on-surface-variant);font-size:13px;padding:30px 10px}
.lobby-card{background:var(--surface-high);border-radius:var(--sh-md);padding:12px 14px}
.lobby-card .top{display:flex;align-items:center;gap:10px}
.lobby-card .game{font-size:15px;font-weight:600}
.lobby-card .by{font-size:11px;color:var(--on-surface-variant);margin-left:auto}
.lobby-card .code{margin-top:6px;font-size:12.5px}
.lobby-card .code b{font-family:ui-monospace,Menlo,monospace;font-weight:600}
.lobby-card .cmd{margin-top:4px;font-size:11.5px;color:var(--on-surface-variant);word-break:break-all}
.lobby-card .acts{display:flex;gap:8px;margin-top:10px}
.lobby-card .acts button{height:34px;padding:0 14px;border-radius:999px;font-size:12.5px;font-weight:500}
.lobby-card .acts .join{background:var(--primary);color:var(--on-primary)}
.lobby-card .acts .copy{background:var(--surface-lowest);color:var(--on-surface-variant);box-shadow:var(--elev-1)}
.lobby-card .acts .del{background:var(--error-container);color:var(--on-error-container)}
.quick-games{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:10px}
.quick-games button{height:32px;padding:0 14px;border-radius:999px;background:var(--surface-high);color:var(--on-surface-variant);font-size:12px;font-weight:500}

/* ---------- snackbar ---------- */
.snackbar{
  position:absolute;left:50%;bottom:26px;transform:translate(-50%,24px);z-index:30;
  background:var(--on-surface);color:var(--surface);font-size:13px;font-weight:500;
  padding:11px 18px;border-radius:var(--sh-md);box-shadow:var(--elev-3);opacity:0;pointer-events:none;
  transition:opacity .25s var(--ease),transform .3s var(--spring);max-width:calc(100vw - 32px);
}
.snackbar.show{opacity:1;transform:translate(-50%,0)}

/* ---------- 移动端适配 ---------- */
@media (max-width:640px){
  :root{--topbar-h:56px;--sat:max(env(safe-area-inset-top,0px),10px)}
  .topbar{padding-left:10px;padding-right:10px;gap:8px}
  .titles small{display:none}
  .sheet{left:0;right:0;bottom:0;width:100%;border-radius:var(--sh-xl) var(--sh-xl) 0 0;max-height:120px;padding-bottom:env(safe-area-inset-bottom)}
  .sheet.expanded{max-height:82vh;max-height:82dvh}
  .dialog{width:100vw;height:100vh;height:100dvh;max-height:100vh;max-height:100dvh;border-radius:0;top:0;left:0;transform:translateY(8%)}
  .dialog.show{transform:translateY(0)}
  .dialog-actions{padding-bottom:calc(18px + env(safe-area-inset-bottom,0px))}
  .fabs{right:calc(10px + env(safe-area-inset-right));top:10px;gap:8px}
  .zoom-ctl{right:calc(10px + env(safe-area-inset-right));bottom:calc(140px + env(safe-area-inset-bottom))}
  .map-credit{bottom:calc(130px + env(safe-area-inset-bottom));right:calc(10px + env(safe-area-inset-right))}
  .hud{left:10px;top:10px}
}
