/*
 * layout.css —— 布局壳样式层（地图壳/覆盖层）【TSD §1.5 styles 目录"布局"职责】。
 * 全部颜色/字号走 token.css 变量，禁临时十六进制【ui-design-style §3.4】；
 * 位置类坐标为布局常量非设计令牌。map-shell.js 运行时注入尺寸真源
 * （回家按钮直径 = constants.MAP_HOME_BUTTON_PX）。
 */

/* —— 手势基线：body 与 #map 容器及 Leaflet 容器三层级都要 none，
      防双指捏合触发页面橡皮筋【tasks_M1 T-M1-03 避坑❷】；
      overscroll-behavior:none 补 standalone 主屏态橡皮筋抑制（iOS 16+ 渐进，
      T-PWA-01）—— */
html,
body {
  height: 100%;
  overflow: hidden;
  touch-action: none;
  overscroll-behavior: none;
}

#map,
.leaflet-container {
  width: 100%;
  height: 100%;
  position: fixed;
  inset: 0;
  /* 海洋底色 = OCEAN_BASE 渐变【PRD §6.3 / F-01 奶白海洋】，陆地由 SVG 环叠绘 */
  background: linear-gradient(180deg, var(--ocean-base), var(--ocean-base-end));
  touch-action: none;
}

/* geodata 缺失/校验失败时的降级网格底色【TSD §6.1 降级基调：不阻断沙盘】。
   经纬示意干网纹 + 保持海洋渐变底，弱对比不喧宾夺主。 */
#map.map-grid-fallback {
  background:
    repeating-linear-gradient(
      90deg,
      transparent 0,
      transparent 79px,
      rgba(120, 144, 156, 0.12) 79px,
      rgba(120, 144, 156, 0.12) 80px
    ),
    repeating-linear-gradient(
      0deg,
      transparent 0,
      transparent 55px,
      rgba(120, 144, 156, 0.12) 55px,
      rgba(120, 144, 156, 0.12) 56px
    ),
    linear-gradient(180deg, var(--ocean-base), var(--ocean-base-end));
}

/* —— 海域角标：右下角 DOM 覆盖层（非 Leaflet 控件，防缩放动画遮挡）
      【PRD F-01 / TSD §2.2 海域角标行】文案由 map-shell 注入；任意 zoom 常驻可见 —— */
.map-badge {
  position: fixed;
  right: 14px;
  bottom: 12px;
  z-index: 900; /* Leaflet 各 pane 上限约 700，覆盖其上且低于交互控件 */
  margin: 0;
  padding: 4px 10px;
  border-radius: 10px;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop); /* 角标也守桌面正文下限 16px，禁小灰字【ui-design-style 反面教材】 */
  line-height: 1.35;
  background: var(--paper-card);
  opacity: 0.92;
  user-select: none;
  pointer-events: none;
  font-variant-numeric: tabular-nums;
}

/* —— 降级三态灯：顶部中央 DOM 覆盖层（同海域角标体系：非 Leaflet 控件，
      任意 zoom 常驻可见；UAT 2026-09-05 从右上角移到顶部中央——原右上角与
      重置钮 top 12/14 几乎重叠致误读为可点按钮【用户拍板 B1 错位防混淆】）
      【PRD §10.3 三态灯映射】灯色经 data-lamp 消费 token.css 状态三色令牌 —— */
.status-lamp {
  position: fixed;
  top: 12px;
  left: calc((100% - var(--dock-w)) / 2);
  transform: translateX(-50%);
  z-index: 900; /* Leaflet 各 pane 上限约 700，覆盖其上且低于交互控件 */
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 4px 10px;
  border-radius: 10px;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop); /* 守桌面正文下限 16px，禁小灰字【ui-design-style 反面教材】 */
  line-height: 1.35;
  background: var(--paper-card);
  opacity: 0.92;
  user-select: none;
  pointer-events: none;
}
.status-lamp-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--status-grey); /* 装配初帧兜底，initStatusLamp 立即置 normal 绿 */
  transition: background-color var(--dur-pop-in) ease-out; /* N-3.4 仅过渡不位移 */
}
.status-lamp[data-lamp='green'] .status-lamp-dot {
  background: var(--status-green);
}
.status-lamp[data-lamp='yellow'] .status-lamp-dot {
  background: var(--status-yellow);
}
.status-lamp[data-lamp='grey'] .status-lamp-dot {
  background: var(--status-grey);
}

/* —— 回家按钮：左下角圆形（视觉形状归本文件，直径由 JS 注入 ≥56px）
      【PRD F-01 / TSD §2.2 回家按钮行】—— */
.home-button {
  position: fixed;
  left: 18px;
  bottom: 18px;
  z-index: 950;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  background: var(--cta-main);          /* 主行动色 CTA_MAIN【§3.3】 */
  box-shadow: 0 3px 10px rgba(55, 71, 79, 0.25); /* INK_TEXT 投影系中性阴影 */
}
.home-button svg {
  width: 62%;
  height: 62%;
  display: block;
}

/* —— 矢量底图图层：Leaflet SVG attribute 不支持 var()，
      因此颜色一律经 className + 此处规则消费 token.css 变量—— */
.geo-land {
  fill: var(--land-fill);
  fill-opacity: 1;
  stroke: var(--land-edge); /* 海岸描边 LAND_EDGE【§3.1】 */
  stroke-width: 1px;
  stroke-linejoin: round;
}

.geo-border {
  fill: none;
  stroke: var(--border-country); /* 国界细线 BORDER_COUNTRY【§3.1】 */
  stroke-width: 0.8px;
}

/* 南海十段线示意虚线（契约 V2 dashes；数据未注入前零元素零影响）
   色取国界同款令牌不发明新色【§3.4】，虚线形态区别于实线国界 */
.geo-dashline {
  fill: none;
  stroke: var(--border-country);
  stroke-width: 0.9px;
  stroke-dasharray: 7px 5px;
}

/* 省界虚线：zoom≥4 懒激活渲染，zoom<4 时 DOM 节点被全量卸载（非 CSS 隐藏）
   消费 --border-province 令牌【token.css §3.1】，细于国界以建立层级区分【TSD §2.2 / §3.4】 */
.geo-province {
  fill: none;
  stroke: var(--border-province);
  stroke-width: 0.5px;
  stroke-dasharray: 3px 2px;
}

/* ============ T-M1-07 渲染管线与播放控制基本盘 ============ */

/* —— Canvas 动态实体层：挂 #map 容器内、底图 SVG 之上、DOM 控件之下
      【TSD §2.3 双图层策略】点击交互由 map click 承担，canvas 自身不收指针 —— */
.render-canvas {
  position: absolute;
  inset: 0;
  /* ⚠【2026-09-02 DPR 修复 · 城市灯牌/台风路径偏移真根因】：canvas 是替换型元素，
     缺显式 CSS 尺寸时会以固有尺寸（attribute 物理像素 = viewW×dpr）显示，inset 的
     right/bottom 被 over-constrained 忽略——高 DPI（Windows 125%/150% 缩放）下整个
     Canvas 层被放大 dpr 倍，画在其上的灯牌/台风/实体相对 Leaflet SVG 陆地系统性
     偏移（越靠右下偏得越多）。显式 100% 钉回容器几何尺寸，物理分辨率仍由
     render-layer.syncCanvasSize 的 width=viewW*dpr 保证（清晰度不降）。 */
  width: 100%;
  height: 100%;
  z-index: 650; /* overlayPane(400)/markerPane(600) 之上，控件(900+)之下 */
  pointer-events: none;
}

/* —— dev 帧率面板：仅 ?dev=1 时由 render-layer 注入（AC-a 取证），console-free —— */
.fps-badge {
  position: fixed;
  left: 50%;
  top: 12px;
  transform: translateX(-50%);
  z-index: 960;
  padding: 2px 10px;
  border-radius: 8px;
  background: var(--paper-card);
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
  font-variant-numeric: tabular-nums;
  opacity: 0.92;
  pointer-events: none;
  user-select: none;
}

/* —— 播放控制条：底部居中悬浮胶囊【PRD F-05 播放控制表 / TSD §2.7】 —— */
.playback-bar {
  position: fixed;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  z-index: 950;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  background: var(--paper-card);
  border-radius: 999px;
  box-shadow: 0 3px 10px rgba(55, 71, 79, 0.25); /* INK_TEXT 投影系中性阴影（同 .home-button） */
}

/* 播放/暂停主按钮：CTA_MAIN 圆形主行动【§3.3】，热区 ≥48px【§4】 */
.playback-play {
  width: 52px;
  height: 52px;
  border: none;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: #ffffff;
  background: var(--cta-main);
  box-shadow: 0 2px 6px rgba(55, 71, 79, 0.2);
  padding: 0;
}
.playback-play svg {
  display: block;
}

.playback-speeds {
  display: flex;
  gap: 4px;
}

/* 变速分段按钮：选中态 INK_TEXT 反白；字号守 iPad 18px 下限【tasks_M1 避坑❶】 */
.playback-speed {
  min-width: 52px;
  height: 48px;
  border: none;
  border-radius: var(--radius-cta);
  cursor: pointer;
  background: transparent;
  color: var(--ink-sub);
  font-family: inherit;
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 0 6px;
}
.playback-speed.is-active {
  background: var(--ink-text);
  color: var(--paper-card);
}

/* —— 时间牌：左下悬浮、回家按钮上方【PRD §6.1 布局壳 / tasks_M1 T-M1-07③】 —— */
.time-badge {
  position: fixed;
  left: 18px;
  bottom: 86px; /* home-button(18px + 56px) 上方留 12px 间隙 */
  z-index: 950;
  padding: 6px 14px;
  border-radius: 12px;
  background: var(--paper-card);
  color: var(--ink-text);
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 3px 10px rgba(55, 71, 79, 0.2);
  user-select: none;
  pointer-events: none;
}

/* —— 重置按钮：右上图标药丸（location.reload 级软复位，卡通弹窗归 M2） —— */
.reset-button {
  position: fixed;
  right: 14px;
  top: 14px;
  z-index: 950;
  display: flex;
  align-items: center;
  gap: 6px;
  height: 48px;
  padding: 0 16px;
  border: none;
  border-radius: 999px;
  cursor: pointer;
  background: var(--paper-card);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  box-shadow: 0 3px 10px rgba(55, 71, 79, 0.2);
}

/* —— 开局演出跳过按钮【tasks_M2 T-M2-08①】：专用出口防 MAP_CLICK 语义冲突；
   hidden 属性控显隐（编排期可见，演出完成/跳过后隐藏）；热区 ≥48px —— */
.opening-skip {
  position: fixed;
  right: 14px;
  bottom: 84px;
  z-index: 950;
  height: 48px;
  padding: 0 18px;
  border: none;
  border-radius: 999px;
  cursor: pointer;
  background: var(--paper-card);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  box-shadow: 0 3px 10px rgba(55, 71, 79, 0.2);
}

.opening-skip[hidden] {
  display: none;
}

/* —— 信息卡【ui-design-style §5.3 / PRD F-05 渲染规格表】 —— */
/* 外层定位层：每帧 inline transform 跟随台风，静态定位非动效；
   hidden 时整体隐身且不收指针，不挡地图点击 */
.info-card-wrap {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 960;
  pointer-events: none;
}
.info-card-wrap[hidden] {
  display: none;
}

/* 内层动效层：pop-in 出现（scale/opacity 白名单）+ 卡面样式 */
.info-card {
  position: relative;
  width: min(320px, calc(100vw - 24px));
  padding: 16px 18px 14px;
  border-radius: 24px;
  background: var(--paper-card-glass); /* UAT 拍板 60% 透明 + 毛玻璃高级感，不遮背景地图【§3.4/N-6.7】 */
  box-shadow: inset 0 1px 0 var(--glass-sheen), inset 0 0 0 1px var(--glass-edge), 0 6px 18px rgba(55, 71, 79, 0.28); /* B 方案玻璃工艺 2026-09-05 拍板 */
  pointer-events: auto;
  will-change: transform, opacity;
  -webkit-backdrop-filter: blur(8px) saturate(1.2); /* 毛玻璃高级感（用户 2026-09-05 拍板，忽略低端 iPad 性能） */
  backdrop-filter: blur(8px) saturate(1.2);
}

.info-name {
  font-size: var(--fs-card-title); /* 22px 标题下限【§4】 */
  font-weight: 700;
  color: var(--ink-text);
  padding-right: 44px; /* 给右上关闭钮让位 */
}

.info-grade-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
}
.info-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  flex: none;
}
.info-grade {
  font-size: var(--fs-body-ipad);
  font-weight: 700;
}

.info-nums {
  display: flex;
  gap: 18px;
  margin-top: 10px;
}
.info-num {
  font-size: var(--fs-core-num); /* 核心数值 40–48px 取上限【§4】 */
  font-weight: 700;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--ink-text);
}
.info-num-block {
  display: flex;
  flex-direction: column;
}
.info-unit {
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
  margin-top: 2px;
}

.info-quote {
  margin-top: 10px;
  font-size: var(--fs-body-ipad);
  color: var(--ink-text);
}

/* 关闭钮：≥44px（TSD §2.7 热区例外下限） */
.info-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--ink-sub);
  padding: 0;
}
.info-close:active {
  color: var(--ink-text);
}

/* ============ T-M2-01 右侧停靠栏与生成器面板 ============ */

/* 停靠栏宽度 = 布局常量非设计令牌【layout.css 头注】；320–360px 规格区间响应式
   clamp（26vw 中段：1920 桌面取上限 360、1180 iPad 横屏约 307、窄窗落 300 下限）
   【PRD §6.1 / ui-design-style §2】。地图区与悬浮控件坐标全部由本变量派生。
   折叠态（:root.dock-collapsed 由 dock-rail.js 切换）缩为 72px 图标药丸列，
   释放约 270px 地图面积【PRD §6.1 桌面折叠条款】。 */
:root {
  --dock-w: clamp(300px, 26vw, 360px);
}
:root.dock-collapsed {
  --dock-w: 72px;
}

/* 极小窗兜底（TSD §9.2 尽力而为口径）：320px 级窗口下 clamp 下限仍会挤没地图区，
   窄屏断点缩至半宽仅防布局错乱（AC-F01-e），不追求可用性；
   折叠态规则特异性更高（:root.dock-collapsed），不受本断点影响 */
@media (max-width: 640px) {
  :root {
    --dock-w: min(180px, 40vw);
  }
}

/* 地图主画布为停靠栏让位（~72% 宽【PRD §6.1 布局壳】）：
   #map 与 .leaflet-container 是同一元素（L.map 注入类），后序规则覆盖 M1 的 inset:0。
   width/height 必须回 auto：固定定位下显式 100% 与 right 内缩过约束，
   right 会被静默忽略（地图实际全窗宽，正是「海域偏右、左侧大片浪费」的根因）；
   auto + 四向 inset 才真正拉伸出 dock 让位后的地图区矩形 */
#map {
  inset: 0 var(--dock-w) 0 0;
  width: auto;
  height: auto;
}

/* 悬浮控件坐标随地图区联动（保持相对地图区居中/贴边） */
.playback-bar {
  left: calc((100% - var(--dock-w)) / 2);
}
.fps-badge {
  left: calc((100% - var(--dock-w)) / 2);
}
.map-badge {
  right: calc(var(--dock-w) + 14px);
}
.reset-button {
  right: calc(var(--dock-w) + 14px);
}
/* 静音键排在重置钮正下方（top 70 = 重置钮 top14 + 高48 + 8 间距），
   随停靠栏贴边让位；三态灯已移至顶部中央（UAT B1），与本列控件零交集 */
.sound-toggle {
  right: calc(var(--dock-w) + 14px);
}

/* —— 停靠栏壳：PAPER_CARD 底，折叠钮行 + 页签导航 + 内容区【PRD §6.1/§6.2】 —— */
.dock-rail {
  position: fixed;
  right: 0;
  top: 0;
  bottom: 0;
  width: var(--dock-w);
  /* border-box 必须：本栏有 2px 左边框，content-box 下外框实宽 = --dock-w + 2，
     而 #map 仅让出 --dock-w，地图区右缘会与停靠栏重叠 2px（取证 LF-3b/LF-5 实测
     362 vs 360、74 vs 72）。border-box 使 width 含边框，DOM 实宽与 --dock-w 严格
     相等，#map inset 与 view-bounds 贴边判定三者口径归一【布局适配取证 LF-3b】。 */
  box-sizing: border-box;
  z-index: 900;
  display: flex;
  flex-direction: column;
  background: var(--paper-card);
  border-left: 2px solid var(--land-edge);
  box-shadow: -3px 0 10px rgba(55, 71, 79, 0.12);
}

/* 折叠钮行：停靠栏顶部通栏（折叠/展开一键切换，桌面与 iPad 通用） */
.dock-head {
  padding: 10px 12px 0;
}
.dock-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 48px; /* 触控热区下限【§4 / N-6.3】 */
  padding: 0 12px;
  border: none;
  border-radius: var(--radius-cta);
  background: var(--ocean-base);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
}

/* 折叠态：图标药丸列（汉字标签隐藏、内容区卸下、图标居中）——
   仅类切换无过渡动画（宽度跳变走 Leaflet invalidateSize 重排，非 CSS 动效范畴） */
.dock-rail.is-collapsed .dock-head {
  padding: 10px 8px 0;
}
.dock-rail.is-collapsed .dock-toggle {
  justify-content: center;
  padding: 0;
}
.dock-rail.is-collapsed .dock-toggle span,
.dock-rail.is-collapsed .dock-tab span {
  display: none;
}
.dock-rail.is-collapsed .dock-tab {
  justify-content: center;
  padding: 0;
}
.dock-rail.is-collapsed .dock-tabs {
  padding: 10px 8px 6px;
}
.dock-rail.is-collapsed .dock-panel-host {
  display: none;
}

/* 页签导航：竖排，图标 + 汉字常驻（色弱冗余编码【ui-design-style §5.8】） */
.dock-tabs {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 12px 6px;
  border-bottom: 2px dashed var(--border-province);
}
.dock-tab {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px; /* 触控热区下限【§4 / N-6.3】 */
  padding: 0 12px;
  border: none;
  border-radius: var(--radius-cta);
  background: transparent;
  color: var(--ink-sub);
  font-family: inherit;
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  cursor: pointer;
}
.dock-tab.is-active {
  background: var(--ocean-base);
  color: var(--ink-text);
}

/* 内容区：页签内独立滚动、触摸不穿透地图【PRD §6.1 "永不拖拽地图"】——
   body 全局 touch-action:none，此处恢复纵向滚动手势 */
.dock-panel-host {
  flex: 1;
  overflow-y: auto;
  touch-action: pan-y;
  overscroll-behavior: contain;
}

/* —— 生成器面板 —— */
.create-panel {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 14px 16px 20px;
}

/* 名字区：名池轮换预览 + 骰子（零自由文本输入【N-7.1 / F13-2 同款纪律】） */
.cp-name-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 16px;
  background: var(--ocean-base);
}
.cp-name-label {
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
}
.cp-name {
  font-size: var(--fs-card-title);
  font-weight: 700;
  color: var(--ink-text);
}
.cp-dice {
  margin-left: auto;
  width: 48px;
  height: 48px;
  border: none;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: var(--paper-card);
  color: var(--ink-text);
  box-shadow: 0 2px 6px rgba(55, 71, 79, 0.18);
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.cp-dice:active {
  transform: scale(0.92); /* 骰子掷出手感（合成层属性白名单） */
}

/* 参数分区：头行 / 步进行 / 滑块 / 口语句 四行结构 */
.cp-param {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.cp-param-head {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
}
.cp-param-title {
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  color: var(--ink-text);
}
.cp-quote {
  margin: 0;
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
  line-height: 1.4;
}

/* 步进行：加减钮（热区 48px）+ 大显数值输入框（核心数值 48px tabular-nums【§4】） */
.cp-stepper {
  display: flex;
  align-items: center;
  gap: 8px;
}
.cp-step {
  width: 48px;
  height: 48px;
  flex: none;
  border: none;
  border-radius: var(--radius-cta);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: var(--ocean-base);
  color: var(--ink-text);
  padding: 0;
}
.cp-step:disabled {
  opacity: 0.35;
  cursor: default;
}
.cp-numinput {
  width: 100%;
  min-width: 0;
  height: 56px;
  border: none;
  border-radius: var(--radius-cta);
  background: var(--ocean-base);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-core-num); /* 核心数值大显 40–48px【§4】 */
  font-weight: 700;
  line-height: 1;
  text-align: center;
  font-variant-numeric: tabular-nums;
  outline: none;
}
.cp-numinput:focus {
  box-shadow: 0 0 0 3px var(--ts-yellow); /* 聚焦环取等级黄令牌，不发明新色【§3.4】 */
}
/* 隐藏原生 spinner：加减步进已由 自实现，原生箭头过小且破坏大显排版 */
.cp-numinput::-webkit-outer-spin-button,
.cp-numinput::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.cp-numinput {
  appearance: textfield;
  -moz-appearance: textfield;
}

/* 滑块：自定义加粗轨道 + 48px 大拇指热区（iPad 触控条过细对策【tasks_M2 避坑❷】） */
.cp-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 48px; /* 热区行高：thumb 垂直居中于此 */
  background: transparent;
  cursor: pointer;
  margin: 0;
}
.cp-slider::-webkit-slider-runnable-track {
  height: 14px;
  border-radius: 7px;
  background: linear-gradient(90deg, var(--ocean-base-end), var(--rainband-light));
}
.cp-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 48px;
  height: 48px;
  margin-top: -17px; /* (14-48)/2 大拇指对中轨道 */
  border-radius: 50%;
  background: var(--paper-card);
  border: 5px solid var(--cta-main);
  box-shadow: 0 2px 6px rgba(55, 71, 79, 0.25);
}
.cp-slider::-moz-range-track {
  height: 14px;
  border-radius: 7px;
  background: linear-gradient(90deg, var(--ocean-base-end), var(--rainband-light));
}
.cp-slider::-moz-range-thumb {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--paper-card);
  border: 5px solid var(--cta-main);
  box-shadow: 0 2px 6px rgba(55, 71, 79, 0.25);
}

/* 副高三段开关：弱/中/强 汉字档位（展示层仅文案档位，不示数【TSD §2.5①】） */
.cp-ridge-seg {
  display: flex;
  gap: 6px;
}
.cp-ridge-btn {
  flex: 1;
  height: 48px; /* 热区【§4 / N-6.3】 */
  border: none;
  border-radius: var(--radius-cta);
  background: var(--ocean-base);
  color: var(--ink-sub);
  font-family: inherit;
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  cursor: pointer;
  transition: opacity var(--dur-pop-in) ease-out;
}
.cp-ridge-btn.is-active {
  background: var(--ink-text);
  color: var(--paper-card);
}

/* 小手推力视觉：档位越高点亮推力线越多（opacity 过渡白名单） */
.cp-push {
  color: var(--rainband-mid);
}
.cp-push .cp-push-line {
  opacity: 0;
  transition: opacity var(--dur-pop-in) ease-out;
}
.cp-push[data-level='weak'] .cp-push-line:nth-child(2) {
  opacity: 1;
}
.cp-push[data-level='mid'] .cp-push-line:nth-child(2),
.cp-push[data-level='mid'] .cp-push-line:nth-child(3) {
  opacity: 1;
}
.cp-push[data-level='strong'] .cp-push-line {
  opacity: 1;
}

/* 主行动按钮 CTA【ui-design-style §5.1】：CTA_MAIN + 圆角16 + 热区 ≥48 + 白字 ≥22 Bold */
.cp-cta {
  height: 56px;
  border: none;
  border-radius: var(--radius-cta);
  background: var(--cta-main);
  color: #ffffff;
  font-family: inherit;
  font-size: var(--fs-card-title);
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 3px 10px rgba(55, 71, 79, 0.25);
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.cp-cta:active {
  transform: scale(0.97);
}

/* —— 词典 ？点读卡【TSD §7.6.1】：圆点热区 48px，小卡挂在参数头行下 —— */
.dict-dot {
  width: 48px;
  height: 48px;
  border: none;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: transparent;
  color: var(--rainband-mid);
  padding: 0;
}
.dict-card {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 970;
  width: min(280px, calc(var(--dock-w) - 40px));
  padding: 10px 14px;
  border-radius: 16px;
  background: var(--paper-card-glass);
  box-shadow: inset 0 1px 0 var(--glass-sheen), inset 0 0 0 1px var(--glass-edge), 0 6px 18px rgba(55, 71, 79, 0.28); /* B 方案玻璃工艺 2026-09-05 拍板 */
  border: 2px solid var(--rainband-light);
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
  backdrop-filter: blur(8px) saturate(1.2);
}
.dict-sci {
  margin: 0;
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  color: var(--ink-text);
}
.dict-kid {
  margin: 4px 0 0;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  color: var(--rainband-deep);
}
.dict-explain {
  margin: 4px 0 0;
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
  line-height: 1.4;
}

/* —— 生成气泡【PRD F-02 出生点行】：点击点定位小卡，参数摘要 +【造出来！】—— */
.spawn-bubble-wrap {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 955; /* 信息卡(960)之下、Leaflet pane 之上 */
  pointer-events: none;
}
.spawn-bubble-wrap[hidden] {
  display: none;
}
.spawn-bubble {
  position: relative;
  width: 216px;
  padding: 12px 14px;
  border-radius: 24px;
  background: var(--paper-card-glass);
  box-shadow: inset 0 1px 0 var(--glass-sheen), inset 0 0 0 1px var(--glass-edge), 0 6px 18px rgba(55, 71, 79, 0.28); /* B 方案玻璃工艺 2026-09-05 拍板 */
  pointer-events: auto;
  will-change: transform, opacity;
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
  backdrop-filter: blur(8px) saturate(1.2);
}
.bubble-summary {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.bubble-summary li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.bubble-label {
  font-size: var(--fs-body-desktop); /* 辅助标签守桌面下限，禁小灰字变体 */
  color: var(--ink-sub);
}
.bubble-summary b {
  font-size: var(--fs-body-ipad); /* 值守 iPad 正文下限【ui-design-style §4】 */
  font-weight: 700;
  color: var(--ink-text);
  font-variant-numeric: tabular-nums;
}
.bubble-summary b i {
  font-style: normal;
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
  margin-left: 2px;
}
.bubble-confirm {
  margin-top: 10px;
  width: 100%;
  height: 48px; /* 热区下限【§4 / N-6.3】 */
  border: none;
  border-radius: var(--radius-cta);
  background: var(--cta-main);
  color: #ffffff;
  font-family: inherit;
  font-size: var(--fs-card-title); /* 主行动按钮白字 ≥22px Bold【§5.1】 */
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(55, 71, 79, 0.2);
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.bubble-confirm:active {
  transform: scale(0.97);
}

/* —— 事件横幅队列【ui-design-style §5.4】：地图区顶部滑入，≤2 条同屏排队【PRD F-04】 —— */
.banner-queue {
  position: fixed;
  top: 12px;
  left: calc((100% - var(--dock-w)) / 2);
  transform: translateX(-50%);
  z-index: 970;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}
.banner-item {
  padding: 10px 20px;
  border-radius: 16px;
  background: var(--paper-card);
  color: var(--ink-text);
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  box-shadow: 0 4px 14px rgba(55, 71, 79, 0.28);
  opacity: 0;
  transform: translateY(-16px);
  /* §5.4 唯一合法动效：顶部滑入 translateY 400ms ease-out（白名单属性） */
  transition: transform 400ms ease-out, opacity 250ms ease-out;
  white-space: nowrap;
}
.banner-item.is-on {
  opacity: 1;
  transform: translateY(0);
}

/* —— dev 性能徽章【tasks_M2 T-M2-03⑤ AC-a】：fps 徽章下方，tick/longtask 双 P95 —— */
.dev-perf-badge {
  position: fixed;
  left: calc((100% - var(--dock-w)) / 2);
  transform: translateX(-50%);
  top: 44px;
  z-index: 960;
  padding: 2px 10px;
  border-radius: 8px;
  background: var(--paper-card);
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
  font-variant-numeric: tabular-nums;
  opacity: 0.92;
  pointer-events: none;
  user-select: none;
}

/* —— 信息卡小扫帚单删钮【PRD F-05「单删」行】：关闭钮左侧，44px=信息卡例外下限 —— */
.info-sweep {
  position: absolute;
  top: 10px;
  right: 58px;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--ink-sub);
  padding: 0;
}
.info-sweep:active {
  color: var(--ink-text);
}

/* —— Toast 轻反馈【ui-design-style §5.5】：地图区顶部居中、≤2s 自散 —— */
.kid-toast {
  position: fixed;
  top: 64px;
  left: calc((100% - var(--dock-w)) / 2);
  z-index: 980;
  max-width: min(420px, calc(100% - var(--dock-w) - 48px));
  padding: 10px 18px;
  border-radius: 16px;
  background: var(--paper-card);
  color: var(--ink-text);
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  box-shadow: 0 4px 14px rgba(55, 71, 79, 0.28);
  opacity: 0;
  transform: translateY(-12px);
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
  pointer-events: none;
  user-select: none;
}
.kid-toast.is-on {
  opacity: 1;
  transform: translateY(0);
}

/* —— 动效白名单：唯一合法 keyframes，只走 transform/opacity【ui-design-style §6】 —— */
@keyframes ty-pop-in {
  from {
    opacity: 0;
    transform: scale(0.92);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
.pop-in {
  animation: ty-pop-in var(--dur-pop-in) ease-out;
}
/* 积分角标：上浮淡出（只走 transform/opacity，白名单合规【N-3.4】） */
@keyframes score-badge-float {
  from {
    opacity: 0;
    transform: translateY(6px) scale(0.9);
  }
  30% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
  to {
    opacity: 0;
    transform: translateY(-26px) scale(1);
  }
}
.score-badge.is-floating {
  animation: score-badge-float var(--dur-celebrate) ease-out forwards;
}
/* 救援扶正 Bounce-In：先压后弹再立正（transform-only，禁碎裂/散架【§7.1】） */
@keyframes rescue-bounce-in {
  0% {
    transform: scale(1.12, 0.82);
  }
  45% {
    transform: scale(0.94, 1.08);
  }
  75% {
    transform: scale(1.03, 0.97);
  }
  to {
    transform: scale(1, 1);
  }
}
.rescue-bounce-in {
  animation: rescue-bounce-in var(--dur-celebrate) ease-out;
}
/* 台风离场优雅收起【T-M2-05③】：只走 opacity 过渡（白名单合规）；reduced-motion 直跳 */
.info-card-leave {
  opacity: 0;
  transition: opacity var(--dur-pop-in) ease-out;
}

/* —— 气泡通用副钮（幽灵次钮）【ui-design-style §5.1「一屏只有一个主按钮」】：
      T-M4-03 海面气泡的「观察帆船」与陆地气泡的「小轿车/小卫士家庭」共用；
      常态为 PAPER_CARD 底 + INK_TEXT 字，绝不抢 .bubble-confirm 的主行动身份。 —— */
.bubble-ghost {
  margin-top: 8px;
  width: 100%;
  min-height: 48px; /* 热区下限【§4 / N-6.3】 */
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0 12px;
  border: 2px solid var(--land-edge);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-ipad); /* 守 iPad 正文下限【§4】 */
  font-weight: 700;
  cursor: pointer;
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.bubble-ghost:active {
  transform: scale(0.97);
}
.bubble-ghost[hidden] {
  display: none;
}
.bubble-ghost-icon {
  display: inline-flex;
  align-items: center;
  color: var(--ink-text);
}
.bubble-ghost-icon svg {
  display: block;
}
.bubble-ghost-label {
  white-space: nowrap;
}

/* —— 实体放置气泡【tasks_M4 T-M4-03① / PRD F-09 放置交互】：
      复用 .spawn-bubble-wrap/.spawn-bubble 浮层工艺，仅增动作钮行（1~2 钮，N-6.2）。 —— */
.entity-bubble {
  width: auto;
  min-width: 168px;
  padding: 12px;
}
.bubble-title {
  margin: 0 0 8px;
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
  text-align: center;
}
.bubble-title[hidden] {
  display: none;
}
.bubble-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.bubble-actions .bubble-ghost:first-child {
  margin-top: 0;
}

/* —— 实体抽屉【tasks_M4 T-M4-03①④ / PRD F-09 放置规则 / §6.2 创造签】：
      【创造】签内生成器面板下方的兄弟 section，三枚实体卡 + 名额余量条 + 一键清场。 —— */
.entity-drawer {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 16px 16px;
  border-top: 2px dashed var(--border-province);
}
.ed-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  min-height: 48px; /* 热区下限【§4 / N-6.3】 */
  padding: 0 10px;
  border: none;
  border-radius: 16px;
  background: var(--ocean-base);
  color: var(--ink-text);
  font-family: inherit;
  cursor: pointer;
}
.ed-title {
  font-size: var(--fs-card-title); /* 卡片标题下限【§4】 */
  font-weight: 700;
}
.ed-chevron {
  display: inline-flex;
  transition: transform var(--dur-move) ease-out; /* 仅 transform，白名单合规 */
}
.entity-drawer.is-collapsed .ed-chevron {
  transform: rotate(180deg);
}
.entity-drawer.is-collapsed .ed-body,
.entity-drawer.is-collapsed .ed-clear {
  display: none;
}

.ed-body {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.ed-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 8px 4px 6px;
  border: 2px solid var(--land-edge);
  border-radius: 16px;
  background: var(--paper-card);
  transition: opacity var(--dur-pop-in) ease-out;
}
/* 满载：整卡降饱和（余量条已三段全填，视觉自解释；不弹任何拒斥提示） */
.ed-card.is-full {
  opacity: 0.55;
}
.ed-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  color: var(--ink-text);
}
.ed-icon svg {
  display: block;
}
.ed-label {
  font-size: var(--fs-body-desktop); /* 桌面正文下限；三列布局下取紧凑档 */
  line-height: 1.25;
  text-align: center;
  color: var(--ink-text);
}
/* 名额余量条：三段胶囊 = 该类 3 位名额的唯一可视表达（静音/读屏信息无损） */
.ed-bar {
  display: flex;
  gap: 3px;
  width: 100%;
  padding: 0 6px;
}
.ed-pip {
  flex: 1;
  height: 7px;
  border: 1.5px solid var(--land-edge);
  border-radius: 4px;
  background: transparent;
  transition: background-color var(--dur-pop-in) ease-out; /* 仅颜色过渡，非位移 */
}
.ed-pip.is-used {
  background: var(--cta-main);
  border-color: var(--cta-main);
}
.ed-remain {
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
  font-variant-numeric: tabular-nums;
}

/* —— 顶栏静音开关【PRD §6.7「顶栏喇叭键一键静音」/ ui-design-style §8】：
      重置钮正下方 48×48 圆形纸白钮，程序化喇叭 SVG 双态（禁 emoji【§7】）；
      静音态仅换图标 + aria-pressed，视觉孪生表现（铃铛/警示牌/角标）完全不变。 —— */
.sound-toggle {
  position: fixed;
  top: 70px;
  right: 14px;
  z-index: 950;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  background: var(--paper-card);
  color: var(--ink-text);
  box-shadow: 0 3px 10px rgba(55, 71, 79, 0.2);
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.sound-toggle:active {
  transform: scale(0.92);
}
.sound-toggle.is-muted {
  color: var(--ink-sub); /* 静音态降饱和（不改用警告色，无负面暗示） */
}

/* —— 救援队浮标【T-M4-03③ / PRD F-09 通用规定①「呼叫救援队！」】：
      待援实体旁浮出的可拖拽徽标；定位由 JS 走 transform（合成层，不触发重排）。 —— */
.rescue-team {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 954; /* 气泡(955)之下、Leaflet pane 之上 */
  width: 48px;
  height: 48px; /* 热区 ≥48px【§4 / N-6.3】—— 视觉图形 28px，热区由按钮补足 */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  padding: 0;
  border: 2px solid var(--cta-main);
  border-radius: 999px;
  cursor: grab;
  background: var(--paper-card);
  color: var(--ink-text);
  box-shadow: 0 3px 10px rgba(55, 71, 79, 0.25);
  touch-action: none; /* 复用地图拖拽经验：防 iPad Safari 的 pointercancel */
  user-select: none;
  will-change: transform;
}
.rescue-team:active {
  cursor: grabbing;
}
.rescue-team[hidden] {
  display: none;
}
.rescue-team.is-dragging {
  opacity: 0.9;
}
/* 徽标下方常驻汉字短标（PRD 通用规定原文；同时是音效的视觉孪生） */
.rescue-team-label {
  font-size: 11px; /* 徽标内辅助短标，主语义由 aria-label 承担 */
  line-height: 1;
  color: var(--cta-main);
  font-weight: 700;
}

/* —— 「+20」预演积分角标【T-M4-03③ / PRD F-13 积分事件表】：
      本地预演展示，不入账、不落库；定位由 JS 走 transform，动效仅 transform/opacity。 —— */
.score-badge {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 958;
  padding: 4px 12px;
  border: 2px solid var(--cta-main);
  border-radius: 999px;
  background: var(--paper-card);
  color: var(--cta-main);
  font-family: inherit;
  font-size: var(--fs-card-title); /* 卡片标题下限 22px【§4】 */
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  user-select: none;
  will-change: transform, opacity;
}
.score-badge[hidden] {
  display: none;
}

/* 清场按钮：次级幽灵钮（一屏一主按钮纪律：主 CTA 仍是【创造台风！】） */
.ed-clear {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 48px; /* 热区下限【§4 / N-6.3】 */
  border: 2px solid var(--land-edge);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  cursor: pointer;
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.ed-clear:active {
  transform: scale(0.97);
}

/* —— prefers-reduced-motion：CSS 分支全关（JS 侧同步停 rAF，双保险）【tasks_M1 T-M1-07⑤ / AC-d】 —— */
@media (prefers-reduced-motion: reduce) {
  .pop-in,
  .score-badge.is-floating,
  .rescue-bounce-in {
    animation: none;
  }
  .info-card,
  .playback-bar,
  .time-badge,
  .reset-button,
  .playback-speed,
  .info-close,
  .info-card-leave,
  .cp-dice,
  .cp-cta,
  .cp-ridge-btn,
  .cp-push .cp-push-line,
  .kid-toast,
  .bubble-confirm,
  .bubble-ghost,
  .ed-head,
  .ed-chevron,
  .ed-card,
  .ed-pip,
  .ed-clear,
  .ap-head,
  .ap-chevron,
  .ap-card,
  .score-badge,
  .rescue-team,
  .sound-toggle,
  .banner-item {
    transition: none;
    animation: none;
  }
}

/* T-M2-07 */

.confirm-mask{position:fixed;inset:0;z-index:900;background:rgba(10,30,50,.45);display:flex;align-items:center;justify-content:center;touch-action:none}
.confirm-dialog{background:#fff;border-radius:16px;padding:20px 18px;width:min(320px,calc(100vw - 48px));display:flex;flex-direction:column;gap:14px;box-shadow:0 12px 32px rgba(10,30,50,.25)}
.confirm-title{margin:0;font-size:17px;line-height:1.5;color:#17324d;text-align:center}
.confirm-btn{min-height:48px;border:none;border-radius:12px;font-size:16px;cursor:pointer;transition:opacity .15s}
.confirm-yes{background:#e05555;color:#fff}
.confirm-no{background:#eef3f8;color:#17324d}

/* —— T-M2-07 三层漏斗历史浏览【PRD F-03 / tasks_M2 T-M2-07】——
   面板挂载于【历史】签 .dock-panel-host，宽度随停靠栏；全部颜色/字号走 token 变量
   【ui-design-style §3.4】，动效仅 transform/opacity【N-3.4】，热区 ≥48px【§4】。 */
.history-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 100%;
  padding: 12px 14px 20px;
}
.history-panel[hidden],
.history-l1[hidden],
.history-l2[hidden],
.history-l3[hidden] {
  display: none; /* 作者 display 规则会压过 UA [hidden]，显式补回 */
}

/* 面包屑：L2/L3 回退路径（AC-a 返回路径正确） */
.history-crumb {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 48px;
}
.history-crumb-back {
  min-width: 48px;
  min-height: 48px;
  padding: 0 12px;
  border: none;
  border-radius: var(--radius-cta);
  background: var(--ocean-base);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
}
.history-crumb-here {
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  color: var(--ink-text);
}

/* L1 六张年代大卡：2 列网格，意象 SVG + 趣味命名 + 年份跨度 */
.history-l1 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.history-era-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 104px;
  padding: 12px 8px;
  border: 2px solid var(--land-edge);
  border-radius: var(--radius-cta);
  background: var(--ocean-base);
  color: var(--ink-text);
  font-family: inherit;
  cursor: pointer;
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.history-era-card:active {
  transform: scale(0.96);
}
.history-era-card svg {
  width: 44px;
  height: 44px;
  color: var(--cta-main);
}
.history-era-label {
  font-size: var(--fs-body-ipad);
  font-weight: 700;
}
.history-era-years {
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
  font-variant-numeric: tabular-nums;
}
.history-era-card.is-grey {
  opacity: 0.45; /* F03-4 置灰：绝不裸错误文本 */
  cursor: default;
}

/* L2 年份格子墙：每屏 ≤20 格【避坑❶】；平静年贴纸 + 台数角标 */
.history-year-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
.history-year-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 76px;
  padding: 8px 4px;
  border: 2px solid var(--border-province);
  border-radius: 14px;
  background: var(--paper-card);
  color: var(--ink-text);
  font-family: inherit;
  cursor: pointer;
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.history-year-cell:active {
  transform: scale(0.94);
}
.history-year-num {
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.history-year-count {
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
}
.history-calm-badge {
  position: absolute;
  top: -8px;
  right: -4px;
  padding: 2px 8px;
  border-radius: 10px;
  background: var(--ts-yellow);
  color: var(--ink-text);
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  transform: rotate(8deg);
}
.history-year-cell.is-empty,
.history-year-cell.is-grey {
  opacity: 0.4;
  cursor: default;
}

/* 分页控件（手势可达 AC-a） */
.history-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 14px;
}
.history-pager-btn {
  min-height: 48px;
  padding: 0 16px;
  border: none;
  border-radius: var(--radius-cta);
  background: var(--ocean-base);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
}
.history-pager-btn:disabled {
  opacity: 0.35;
  cursor: default;
}
.history-pager-indicator {
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
  font-variant-numeric: tabular-nums;
}

/* L3 工具行：手气不错 + 六档筛选芯片（单选可叠加皇冠【PRD F-03】） */
.history-tools {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 12px;
}
.history-lucky-btn {
  min-height: 48px;
  border: none;
  border-radius: var(--radius-cta);
  background: var(--cta-main);
  color: var(--paper-card);
  font-family: inherit;
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 3px 10px rgba(55, 71, 79, 0.25);
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.history-lucky-btn:active {
  transform: scale(0.96);
}
.history-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.history-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 48px;
  padding: 0 14px;
  border: 2px solid var(--border-province);
  border-radius: 999px;
  background: var(--paper-card);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.history-chip.is-active {
  border-color: var(--grade-color, var(--cta-main));
  background: var(--ocean-base);
  box-shadow: inset 0 0 0 2px var(--grade-color, var(--cta-main));
}
.history-chip-crown svg {
  width: 18px;
  height: 14px;
  color: var(--ts-yellow);
}

/* 台风卡列表：三键排序（著名优先  */
.history-storm-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.history-storm-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 64px;
  padding: 10px 12px;
  border: 2px solid var(--land-edge);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-text);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.history-storm-card:active {
  transform: scale(0.97);
}
.history-storm-grade {
  flex: none;
  width: 14px;
  height: 40px;
  border-radius: 7px;
  background: var(--grade-color, var(--td-blue));
}
.history-storm-name {
  font-size: var(--fs-card-title);
  font-weight: 700;
}
.history-storm-meta {
  margin-left: auto;
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.history-storm-crown {
  flex: none;
  display: flex;
  color: var(--ts-yellow);
}
.history-storm-crown svg {
  width: 20px;
  height: 16px;
}
.history-empty {
  margin: 0;
  padding: 18px 4px;
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
  text-align: center;
}

/* reduced-motion 补充块：历史面板交互元素过渡全关（与上方白名单块同口径） */
@media (prefers-reduced-motion: reduce) {
  .history-era-card,
  .history-year-cell,
  .history-lucky-btn,
  .history-chip,
  .history-storm-card {
    transition: none;
    animation: none;
  }
}

/* 等级色签类：CSP default-src self 禁内联 style，改类切换消费 token.css 六档色【§3.2】（T-M2-07） */
.grade-td { --grade-color: var(--td-blue); }
.grade-ts { --grade-color: var(--ts-yellow); }
.grade-sts { --grade-color: var(--sts-orange); }
.grade-ty { --grade-color: var(--ty-red); }
.grade-sty { --grade-color: var(--sty-edge); }
.grade-super { --grade-color: var(--super-purple); }

/* confirm-mask 显式 hidden 补回：作者 display:flex 压过 UA [hidden] 规则，
   否则遮罩自 boot 起常驻全屏吞掉地图交互（F05-4 组件级缺陷，2026-08-28 冒烟逼出） */
.confirm-mask[hidden] {
  display: none;
}

/* —— T-M3-05【在线】签：20 城灯牌墙 + 城市天气卡【PRD F-10③ / tasks_M3 T-M3-05④】——
   面板挂载于【在线】签 .dock-panel-host；全部颜色/字号走 token 变量【ui-design-style §3.4】，
   动效仅 transform/opacity【N-3.4】，热区 ≥48px【§4】。 */
.online-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
}
.online-intro {
  margin: 0;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
}

/* 城市灯牌墙：4 列网格，PAPER_CARD 底圆角胶囊；选中态描边加粗 + 汉字常驻（色弱冗余【§5.8】） */
.city-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
.city-chip {
  min-height: 48px;
  padding: 0 4px;
  border: 2px solid transparent;
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(55, 71, 79, 0.12);
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.city-chip:active {
  transform: scale(0.94);
}
.city-chip.is-selected {
  border-color: var(--cta-main);
  background: var(--ocean-base);
}

/* 天气卡四态宿主：空态 / 加载骨架 / 卡片 / 错误话术 */
.weather-card-host {
  min-height: 200px;
}
.weather-empty,
.weather-error {
  margin: 0;
  padding: 14px;
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
}
.weather-error {
  color: var(--ink-text);
}
.weather-loading {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  border-radius: var(--radius-cta);
  background: var(--paper-card);
}
.weather-loading-bar {
  height: 16px;
  border-radius: 8px;
  background: var(--ocean-base);
  animation: weather-breath 1.2s ease-in-out infinite;
}
.weather-loading-bar:nth-child(2) {
  width: 72%;
}
.weather-loading-bar:nth-child(3) {
  width: 48%;
}
@keyframes weather-breath {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}

/* 天气卡主体：头部（城市名+图标）/ 温度大数字 / 正文一句 / 五行字段 */
.weather-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px;
  border-radius: var(--radius-cta);
  background: var(--paper-card-glass);
  box-shadow: inset 0 1px 0 var(--glass-sheen), inset 0 0 0 1px var(--glass-edge), 0 3px 10px rgba(55, 71, 79, 0.15); /* B 方案玻璃工艺 2026-09-05 拍板 */
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
  backdrop-filter: blur(8px) saturate(1.2);
}
.weather-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.weather-city {
  font-size: var(--fs-card-title);
  font-weight: 700;
  color: var(--ink-text);
}
.weather-icon {
  display: inline-flex;
  color: var(--rainband-mid);
}
.weather-temp {
  margin: 0;
  font-size: var(--fs-core-num);
  font-weight: 700;
  line-height: 1.1;
  color: var(--ink-text);
}
.weather-summary {
  margin: 0;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
}
.weather-rows {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
}

/* 数据来源归因行：卡片底部小字（和风 attributions 合规展示【§3.4】） */
.weather-attribution {
  margin: 0;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
  text-align: right;
  opacity: 0.85;
}
.weather-row {
  position: relative; /* dict-card 小卡贴行定位锚【dict-card.js anchorEl.after】 */
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  border-top: 1px dashed var(--border-province);
  font-size: var(--fs-body-desktop);
}
.weather-row-label {
  color: var(--ink-sub);
}
.weather-row-value {
  color: var(--ink-text);
  font-weight: 700;
}

/* —— T-M3-06【在线】签实况台风区：列表卡 + 虚线开关 + 演化进行时话术
      【PRD F-10② / tasks_M3 T-M3-06】颜色/字号走 token 变量，热区 ≥48px【§4】—— */
.live-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
  border-radius: var(--radius-cta);
  background: var(--ocean-base);
}
.live-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.live-title {
  margin: 0;
  font-size: var(--fs-card-title);
  font-weight: 700;
  color: var(--ink-text);
}
.live-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 48px;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
  cursor: pointer;
}
.live-toggle input {
  width: 20px;
  height: 20px;
  accent-color: var(--cta-main);
}
.live-card-host {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.live-empty {
  margin: 0;
  padding: 10px 14px;
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
}
.live-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px;
  border-radius: var(--radius-cta);
  background: var(--paper-card-glass);
  box-shadow: inset 0 1px 0 var(--glass-sheen), inset 0 0 0 1px var(--glass-edge), 0 3px 10px rgba(55, 71, 79, 0.15); /* B 方案玻璃工艺 2026-09-05 拍板 */
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
  backdrop-filter: blur(8px) saturate(1.2);
}
.live-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.live-grade-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  flex: none;
}
.live-name {
  font-size: var(--fs-card-title);
  font-weight: 700;
  color: var(--ink-text);
}
.live-grade {
  margin-left: auto;
  padding: 2px 10px;
  border-radius: 10px;
  background: var(--ocean-base);
  color: var(--ink-text);
  font-size: var(--fs-body-desktop);
}
.live-rows {
  margin: 0;
  padding: 0;
  list-style: none;
}
.live-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 32px;
  border-top: 1px dashed var(--border-province);
  font-size: var(--fs-body-desktop);
}
.live-row-label {
  color: var(--ink-sub);
}
.live-row-value {
  color: var(--ink-text);
  font-weight: 700;
}
.live-inject-btn {
  min-height: 48px;
  border: none;
  border-radius: var(--radius-cta);
  background: var(--cta-main);
  color: #ffffff;
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.live-inject-btn:active {
  transform: scale(0.96);
}
.live-inject-btn:disabled {
  opacity: 0.5;
  cursor: default;
}
.live-note {
  margin: 0;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
  line-height: 1.5;
}

/* reduced-motion 补充块：天气卡骨架呼吸与灯牌过渡全关（与上方白名单块同口径） */
@media (prefers-reduced-motion: reduce) {
  .weather-loading-bar {
    animation: none;
  }
  .city-chip {
    transition: none;
  }
  .live-inject-btn {
    transition: none;
  }
}

/* ============================================================
 * T-M4-04 登陆愿望单【PRD F-06 / tasks_M4 T-M4-04】
 *   ① 愿望单面板（【在线】签内 online-panel 的兄弟 section）
 *   ② 里程碑卡 / 复盘卡（居中纸白卡，无遮罩不打断演化）
 * 颜色一律令牌引用，禁临时十六进制【ui-design-style §3.4】。
 * ============================================================ */

.wish-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 14px;
  padding: 12px 16px 16px;
  border-top: 2px dashed var(--land-edge);
}
.wp-head {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 48px; /* 热区下限【§4 / N-6.3】 */
  padding: 0 2px;
  border: none;
  background: transparent;
  color: var(--ink-text);
  font-family: inherit;
  cursor: pointer;
}
.wp-head-icon {
  display: inline-flex;
  align-items: center;
}
.wp-title {
  font-size: var(--fs-card-title); /* 卡片标题下限 22px【§4】 */
  font-weight: 700;
}
.wp-chevron {
  display: inline-flex;
  margin-left: auto;
  transition: transform var(--dur-move) ease-out; /* 仅 transform，白名单合规 */
}
.wish-panel.is-collapsed .wp-chevron {
  transform: rotate(180deg);
}
.wish-panel.is-collapsed .wp-body {
  display: none;
}
.wp-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* —— 三槽位：余量的唯一可视表达（静音 / 读屏信息无损【§10】） —— */
.wp-slots {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.wp-slot {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 48px; /* 热区下限【§4 / N-6.3】 */
  padding: 6px 10px;
  border-radius: var(--radius-cta);
  border: 2px dashed var(--land-edge);
  background: transparent;
}
.wp-slot.is-filled {
  border-style: solid;
  border-color: var(--cta-main);
  background: var(--paper-card);
}
.wp-slot-lamp {
  display: inline-flex;
  flex: none;
}
.wp-slot-name {
  font-size: var(--fs-card-title);
  font-weight: 700;
  color: var(--ink-text);
}
.wp-slot-status {
  margin-left: auto;
  padding: 2px 10px;
  border-radius: 10px;
  background: var(--ocean-base);
  color: var(--ink-text);
  font-size: var(--fs-body-desktop);
  white-space: nowrap;
}
.wp-slot-off {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 48px;
  height: 48px; /* 热区下限【§4 / N-6.3】 */
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-sub);
  cursor: pointer;
  transition: transform var(--dur-pop-in) ease-out;
}
.wp-slot-off:active {
  transform: scale(0.92);
}
.wp-slot-plus {
  width: 100%;
  text-align: left;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
}
.wp-full-hint {
  margin: 0;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
  line-height: 1.5;
}
.wp-hint {
  margin: 0;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
  line-height: 1.5;
}
.wp-grid {
  margin-top: 2px;
}

/* —— 里程碑卡 / 复盘卡：居中偏上、无遮罩（不打断沙盘演化【任务书避坑❷】）—— */
.wish-card {
  position: fixed;
  left: 50%;
  top: 18vh;
  z-index: 960;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(360px, calc(100vw - 48px));
  padding: 18px 18px 16px;
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  box-shadow: 0 12px 32px rgba(10, 30, 50, 0.22);
  opacity: 0;
  transform: translate(-50%, 0) scale(0.92);
  transition: opacity var(--dur-pop-in) ease-out, transform var(--dur-pop-in) ease-out;
}
.wish-card.is-on {
  opacity: 1;
  transform: translate(-50%, 0) scale(1);
}
.wish-card[hidden] {
  display: none;
}
.wish-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.wish-card-icon {
  display: inline-flex;
  flex: none;
}
.wish-card-title {
  font-size: var(--fs-card-title);
  font-weight: 700;
}
.wish-card--hit .wish-card-title {
  color: var(--cta-main);
}
/* 复盘卡主色降为辅助墨色：禁用红色警告与警示底抖动【§7.1 / §6.5④】 */
.wish-card--miss .wish-card-title {
  color: var(--ink-sub);
}
.wish-card-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px; /* 热区下限【§4 / N-6.3】 */
  margin-left: auto;
  margin-right: -8px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-sub);
  cursor: pointer;
}
.wish-card-city {
  margin: 0;
  font-size: var(--fs-core-num); /* 核心数值大显 40–48px【§4】 */
  font-weight: 700;
  line-height: 1.1;
  text-align: center;
}
.wish-card-lines {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.wish-card-line {
  margin: 0;
  color: var(--ink-text);
  font-size: var(--fs-body-ipad); /* 正文下限 18px，两行线索要读得清【§4】 */
  line-height: 1.6;
}
.wish-card-foot {
  margin: 0;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop);
  line-height: 1.6;
}
.wish-card-ok {
  min-height: 48px; /* 热区下限【§4 / N-6.3】 */
  border: none;
  border-radius: var(--radius-cta);
  background: var(--cta-main);
  color: #ffffff;
  font-family: inherit;
  font-size: var(--fs-card-title);
  font-weight: 700;
  cursor: pointer;
  transition: transform var(--dur-pop-in) ease-out;
}
.wish-card-ok:active {
  transform: scale(0.97);
}
/* 复盘卡主钮降为次级幽灵钮（一屏一主按钮纪律【§5.1】：庆祝才是主 CTA） */
.wish-card--miss .wish-card-ok {
  border: 2px solid var(--land-edge);
  background: var(--paper-card);
  color: var(--ink-text);
}

/* reduced-motion 补充块：愿望单面板与卡片的过渡全关（内容照常呈现，仅退化为静态） */
@media (prefers-reduced-motion: reduce) {
  .wp-chevron,
  .wp-slot-off,
  .wish-card,
  .wish-card-ok {
    transition: none;
  }
  .wish-card {
    transform: translate(-50%, 0) scale(1); /* 直跳终态，不做 pop-in 缩放 */
  }
}

/* ============================================================
 * T-M4-05 平行宇宙擂台·环境卡三选一【PRD F-07/§12.1 / tasks_M4 T-M4-05③】
 *   【创造】签内 entity-drawer 之后的兄弟 section，折叠默认收起
 *   （用户裁决 2026-08-29）。颜色一律令牌引用，禁临时十六进制【§3.4】。
 * ============================================================ */

.arena-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 14px;
  padding: 12px 16px 16px;
  border-top: 2px dashed var(--border-province);
}
.ap-head {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 48px; /* 热区下限【§4 / N-6.3】 */
  padding: 0 2px;
  border: none;
  background: transparent;
  color: var(--ink-text);
  font-family: inherit;
  cursor: pointer;
}
.ap-head-icon {
  display: inline-flex;
  align-items: center;
}
.ap-title {
  font-size: var(--fs-card-title); /* 卡片标题下限 22px【§4】 */
  font-weight: 700;
}
.ap-chevron {
  display: inline-flex;
  margin-left: auto;
  transition: transform var(--dur-move) ease-out; /* 仅 transform，白名单合规 */
}
.arena-panel.is-collapsed .ap-chevron {
  transform: rotate(180deg);
}
.arena-panel.is-collapsed .ap-body {
  display: none;
}

/* —— 卡片墙：A/B/C 可选 + D 锁定，窄屏纵排 —— */
.ap-body {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
@media (max-width: 900px) {
  .ap-body {
    grid-template-columns: 1fr;
  }
}
.ap-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-height: 48px; /* 热区下限【N-6.3】 */
  padding: 10px 6px 8px;
  border: 2px solid var(--land-edge);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-text);
  font-family: inherit;
  cursor: pointer;
  transition:
    transform var(--dur-pop-in) ease-out,
    border-color var(--dur-pop-in) ease-out,
    opacity var(--dur-pop-in) ease-out; /* 仅 transform/opacity/色，白名单合规 */
}
/* 选中态：CTA_MAIN 描边 + 轻微上浮（250ms ease-out【§6.5】） */
.ap-card.is-selected {
  border-color: var(--cta-main);
  transform: translateY(-2px);
}
/* D 卡锁定态：整体降饱和 + 弱化（可见不可选【AC-c】） */
.ap-card.is-locked {
  filter: grayscale(1);
  opacity: 0.6;
  cursor: default;
}
.ap-name {
  font-weight: 700;
  font-size: 15px;
}
.ap-params {
  color: var(--ink-sub);
  font-size: 13px;
  text-align: center;
}
/* 版本号徽标：ENV_X_v1 字样胶囊（赛季感【任务书③】；tabular-nums【§4】） */
.ap-ver {
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--ocean-base);
  color: var(--ink-sub);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.ap-lock {
  display: inline-flex;
  align-items: center;
  color: var(--ink-sub);
}
.ap-lock-hint {
  color: var(--ink-sub);
  font-size: 12px;
}

/* ============================================================
 * T-M4-07 开机引导五幕【tasks_M4 T-M4-07 / PRD F-11 行为表 / F11-2】
 *   overlay 全屏拦截层（演化继续，唯 UI 输入拦截——F-11 边界表 z-index 纪律）；
 *   动效仅 transform/opacity 白名单【§6】；热区 ≥48px【§4】；颜色一律令牌【§3.4】。
 * ============================================================ */

/* 全屏拦截层：透明背景（视觉不遮沙盘与预演气泡），pointer 拦截防误触生成 */
.tour-overlay {
  position: fixed;
  inset: 0;
  z-index: 990; /* banner(980) 之上，引导件自成堆叠上下文 */
  background: transparent;
  transition: opacity var(--dur-pop-in) ease-out;
}
.tour-overlay.is-leaving {
  opacity: 0;
  pointer-events: none;
}

/* 聚焦高亮框：CTA_MAIN 描边柔光，transform 400ms 移动【任务书①】 */
.tour-focus {
  position: fixed;
  left: 0;
  top: 0;
  width: 120px;
  height: 120px;
  border: 3px solid var(--cta-main);
  border-radius: 20px;
  box-shadow: 0 0 0 6px rgba(255, 112, 67, 0.18);
  pointer-events: none;
  transition: transform var(--dur-move) ease-out;
}

/* 风奇气泡：PAPER_CARD 底 + 圆角 24px + 正文 18px（≤60 字【§6.8】）+ 朗读小喇叭 */
.tour-bubble {
  position: fixed;
  left: 50%;
  top: 64px;
  transform: translateX(-50%);
  z-index: 2;
  max-width: min(420px, calc(100vw - 48px));
  background: var(--paper-card);
  border-radius: 24px;
  padding: 14px 56px 14px 18px;
  box-shadow: 0 12px 32px rgba(10, 30, 50, 0.22);
  display: flex;
  gap: 10px;
  align-items: flex-start;
}
.tour-cloud {
  flex: none;
  line-height: 0;
}
.tour-text {
  margin: 0;
  font-size: 18px; /* iPad 正文下限【§4】 */
  line-height: 1.55;
  color: var(--ink-text);
  font-weight: 500;
}
.tour-speak {
  position: absolute;
  right: 8px;
  top: 8px;
  width: 44px; /* 信息卡关闭钮例外下限 44px【TSD §2.7】 */
  height: 44px;
  border: none;
  background: transparent;
  color: var(--ink-sub);
  border-radius: 12px;
  cursor: pointer;
}
.tour-speak:hover {
  color: var(--ink-text);
}

/* 底部两钮纪律：[下一步] 主 CTA（一屏唯一主按钮【§5.1】）+ [跳过] 幽灵次钮；
   [跳过] 常驻可见绝不弹挽留【N-8】；热区 ≥48px【§4】 */
.tour-actions {
  position: fixed;
  left: 50%;
  bottom: 120px;
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  gap: 14px;
}
.tour-next {
  min-width: 120px;
  height: 48px;
  padding: 0 26px;
  border: none;
  border-radius: var(--radius-cta);
  background: var(--cta-main);
  color: #fff;
  font-size: 20px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
}
.tour-skip {
  min-width: 96px;
  height: 48px;
  padding: 0 22px;
  border: 2px solid var(--land-edge);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-text);
  font-size: 18px;
  font-family: inherit;
  cursor: pointer;
}

/* 徽章贴纸：第五幕从气泡旁飞落顶栏护照位（transform 900ms 庆祝量级【§6】）；
   is-landed = 脱离引导层驻留顶栏（会话内纪念，T-M4-08 护照页接管） */
.tour-sticker {
  position: fixed;
  z-index: 3;
  width: 48px;
  height: 52px;
  margin-left: -24px;
  margin-top: -26px;
  transition: transform 900ms ease-out;
  pointer-events: none;
}
.tour-sticker.is-landed {
  z-index: 940; /* 驻留层：低于气泡(955)，不挡任何交互 */
}

/* 诞生旋涡绽放（第三幕预演纯视觉演出；示意效果） */
.tour-vortex {
  position: fixed;
  z-index: 930; /* overlay(990) 之下视觉可见（透明 overlay 不遮），无交互 */
  transform: translate(-50%, -50%);
  opacity: 0;
  animation: tour-vortex 900ms ease-out forwards;
  pointer-events: none;
}
@keyframes tour-vortex {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
  55% { opacity: 0.95; transform: translate(-50%, -50%) scale(1.15); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.5); }
}

/* reduced-motion：引导动效全关（聚焦直跳/贴纸直落/旋涡不播），功能不受损【§6】 */
@media (prefers-reduced-motion: reduce) {
  .tour-focus,
  .tour-sticker {
    transition: none;
  }
  .tour-vortex {
    animation: none;
    opacity: 0;
  }
}

/* 【创造】页签底部「再看一次教学」幽灵按钮【T-M4-07② / 用户裁决 2026-08-30】：
   当前无设置面板暂落此处，T-M4-08 建成【我】护照页后迁入 */
.cp-replay-tour {
  margin-top: 12px;
  min-height: 48px; /* 热区下限【§4 / N-6.3】 */
  padding: 0 18px;
  border: 2px solid var(--land-edge);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-text);
  font-size: 16px;
  font-family: inherit;
  cursor: pointer;
}
.cp-replay-tour:hover {
  border-color: var(--cta-main);
}

/* ============================================================
 * T-M4-08 徽章仪式卡【PRD F-11 L558 金色旋转边框 ≤2s / tasks_M4 T-M4-08③】
 *   垂直居中 z-index 980（高于 wish-card 960：同帧错层口径见组件头注）；
 *   金边工艺 = conic-gradient 方层旋转（transform 白名单）+ 内层纸白卡裁边。
 *   时长常量真源 constants.js（BADGE_CEREMONY_*），CSS 同值不同源禁互相复用。
 * ============================================================ */
.badge-ceremony {
  position: fixed;
  left: 50%;
  top: 50%;
  z-index: 980;
  width: min(340px, calc(100vw - 48px));
  padding: 4px; /* 金边厚度 */
  border-radius: 24px;
  overflow: hidden;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.92);
  transition: opacity 900ms ease-out, transform 900ms ease-out; /* BADGE_CEREMONY_POP_MS 同值 */
}
.badge-ceremony::before {
  content: '';
  position: absolute;
  inset: -60%;
  background: conic-gradient(
    var(--badge-gold) 0deg,
    var(--badge-gold-soft) 90deg,
    var(--badge-gold) 180deg,
    var(--badge-gold-soft) 270deg,
    var(--badge-gold) 360deg
  );
  animation: badge-gold-spin 2s linear 1; /* BADGE_CEREMONY_BORDER_MS 同值（PRD ≤2s） */
}
@keyframes badge-gold-spin {
  to {
    transform: rotate(360deg);
  }
}
.badge-ceremony.is-on {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
.badge-ceremony[hidden] {
  display: none;
}
.badge-ceremony-inner {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 18px 14px;
  border-radius: 20px;
  background: var(--badge-card-glass); /* UAT 拍板 72% 透明 + 毛玻璃（70%+ 档，金边不参与）；同 info-card 工艺 */
  box-shadow: inset 0 1px 0 var(--glass-sheen), inset 0 0 0 1px var(--glass-edge); /* B 方案玻璃工艺 2026-09-05 拍板（原无外阴影，金边在外层不参与） */
  -webkit-backdrop-filter: blur(8px) saturate(1.2); /* 毛玻璃高级感（用户 2026-09-05 拍板） */
  backdrop-filter: blur(8px) saturate(1.2);
}
.badge-ceremony-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.badge-ceremony-icon {
  display: inline-flex;
}
.badge-ceremony-kicker {
  flex: 1;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  color: var(--badge-gold);
}
.badge-ceremony-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: var(--radius-cta);
  background: transparent;
  color: var(--ink-sub);
  cursor: pointer;
}
.badge-ceremony-name {
  margin: 0;
  font-size: var(--fs-card-title);
  font-weight: 700;
  color: var(--ink-text);
}
.badge-ceremony-fact {
  margin: 0;
  font-size: var(--fs-body-desktop);
  line-height: 1.5;
  color: var(--ink-sub);
}
.badge-ceremony-task {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  color: var(--ink-text);
}
.badge-ceremony-star {
  display: inline-flex;
}
.badge-ceremony-ok {
  min-height: 48px; /* 热区下限【§4 / N-6.3】 */
  border: none;
  border-radius: var(--radius-cta);
  background: var(--cta-main);
  color: #ffffff;
  font-family: inherit;
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  cursor: pointer;
}
@media (prefers-reduced-motion: reduce) {
  .badge-ceremony::before {
    animation: none; /* 金边直跳静态渐变【§6.5④】 */
  }
  .badge-ceremony {
    transition: none;
    transform: translate(-50%, -50%) scale(1); /* 直跳终态，不做 pop-in 缩放 */
  }
}

/* T-M5-07 到时战报仪式（badge-ceremony 同族工艺；无遮罩 N-8.2，z 980 同族） */
.battle-report {
  position: fixed;
  left: 50%;
  top: 50%;
  z-index: 980;
  width: min(340px, calc(100vw - 48px));
  padding: 4px;
  border-radius: 24px;
  overflow: hidden;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.92);
  transition: opacity 900ms ease-out, transform 900ms ease-out;
}
.battle-report.is-on {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
.battle-report-inner {
  background: var(--surface-card, #fff);
  border-radius: 20px;
  padding: 18px 16px 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.battle-report-kicker {
  font-size: 13px;
  font-weight: 700;
  color: var(--cta-main, #ff7043);
  letter-spacing: 2px;
}
.battle-report-storm {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text-main, #37474f);
}
.battle-report-storm-name {
  font-size: 18px;
  font-weight: 700;
}
.battle-report-wall {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.battle-report-badge {
  font-size: 13px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--badge-gold-soft, #f9a825);
  color: var(--text-main, #37474f);
}
.battle-report-badge.is-empty {
  background: var(--border-province, #cfd8dc);
}
.battle-report-fact {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-main, #37474f);
}
.battle-report-fact-label {
  font-weight: 700;
  margin-right: 6px;
}
.battle-report-no-ticket {
  font-size: 12px;
  color: var(--text-sub, #78909c);
  margin: 0;
}
.battle-report-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.battle-report-btn {
  min-height: 48px;
  border-radius: 14px;
  font-size: 16px;
  font-weight: 700;
  border: 2px solid transparent;
  cursor: pointer;
}
.battle-report-btn.is-redeem {
  background: var(--cta-main, #ff7043);
  color: #fff;
}
.battle-report-btn.is-redeem:disabled {
  background: var(--border-province, #cfd8dc);
  cursor: default;
}
.battle-report-btn.is-stay {
  background: var(--surface-card, #fff);
  border-color: var(--border-province, #cfd8dc);
  color: var(--text-main, #37474f);
}

/* ============================================================
 * T-M4-08 【我】护照页雏形【PRD F-11 护照页行 / §6.2 页签分配表 / tasks_M4 T-M4-08④】
 *   徽章墙（十枚按 BADGES 枚举序，未解锁灰态+判据小字）+ 任务进度区（三卡
 *   idle 领取/active 进度/done 打勾）+ 荣誉册页脚。不落库仅会话内存。
 * ============================================================ */
.profile-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 16px 18px;
}
.pp-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: var(--fs-card-title);
  font-weight: 700;
  color: var(--ink-text);
}
.pp-title-icon {
  display: inline-flex;
  color: var(--ink-text);
}
.pp-hint {
  margin: 0;
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
}
.pp-wall {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.pp-badge {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 2px solid var(--border-province);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
}
.pp-badge-icon {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--ink-sub);
  filter: grayscale(1); /* 未解锁灰态：形状记忆保留、色彩退场 */
  opacity: 0.55;
}
.pp-badge-name {
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  color: var(--ink-sub);
}
.pp-badge-criteria {
  font-size: 13px;
  color: var(--ink-sub);
}
.pp-badge.is-owned {
  border-color: var(--badge-gold);
}
.pp-badge.is-owned .pp-badge-icon {
  filter: none;
  opacity: 1;
  color: var(--ink-text);
}
.pp-badge.is-owned .pp-badge-name {
  color: var(--ink-text);
}
.pp-tasks {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pp-task {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border: 2px solid var(--border-province);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
}
.pp-task.is-active {
  border-color: var(--cta-main);
}
.pp-task.is-done {
  border-color: var(--status-green);
}
.pp-task-goal {
  flex: 1;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  color: var(--ink-text);
}
.pp-task-progress {
  font-size: 13px;
  color: var(--ink-sub);
}
.pp-task-done-mark {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  color: var(--status-green);
}
.pp-task-btn {
  min-height: 44px;
  padding: 0 14px;
  border: 2px solid var(--land-edge);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
}
.pp-task-btn.is-claim {
  border-color: var(--cta-main);
  color: var(--cta-main);
}
.pp-task-btn:hover {
  border-color: var(--cta-main);
}
.pp-foot {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-sub);
}

/* ============================================================
 * T-M5-03 云端护照区【tasks_M5 T-M5-03②③ / PRD F-13 / §6.2 页签表】
 *   三态容器（is-loading skeleton 微光 / is-online 云端档案 / is-offline
 *   离线纪念册标注）。skeleton 动画仅 transform【§6.5】，reduced-motion 退化。
 * ============================================================ */
.pp-cloud {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* —— skeleton 微光占位（形状记忆：档案行/双轨卡/称号行） —— */
.pp-sk {
  position: relative;
  overflow: hidden;
  border-radius: 12px;
  background: var(--ocean-base);
}
.pp-sk::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
  animation: pp-shimmer 1.2s ease-in-out infinite;
}
@keyframes pp-shimmer {
  to { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
  .pp-sk::after { animation: none; }
}
.pp-cloud-row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.pp-sk-avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  flex-shrink: 0;
}
.pp-cloud-lines {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.pp-sk-line { height: 14px; }
.pp-sk-line.is-w70 { width: 70%; }
.pp-sk-line.is-w60 { width: 60%; }
.pp-sk-line.is-w45 { width: 45%; }
.pp-sk-card { height: 72px; }

/* —— online 态：档案卡 —— */
.pp-id-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 2px solid var(--border-province);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
}
.pp-avatar {
  display: inline-flex;
  width: 48px;
  height: 48px;
  flex-shrink: 0;
}
.pp-avatar svg { width: 100%; height: 100%; }
.pp-id-text { min-width: 0; }
.pp-nickname {
  font-size: 18px;
  font-weight: 700;
  color: var(--ink-text);
  overflow-wrap: anywhere;
}
.pp-friend-code {
  font-size: 13px;
  letter-spacing: 2px;
  color: var(--ink-sub);
}

/* —— online 态：双轨积分两卡（颜色仅装饰性区分，语义由文字标签承载【§5.8】） —— */
.pp-balances {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.pp-balance {
  padding: 8px 10px 10px;
  border: 2px solid var(--border-province);
  border-top-width: 4px;
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  text-align: center;
}
.pp-balance.is-game { border-top-color: var(--td-blue); }
.pp-balance.is-quiz { border-top-color: var(--ts-yellow); }
.pp-balance-label {
  font-size: 13px;
  color: var(--ink-sub);
}
.pp-balance-num {
  font-size: var(--fs-core-num);
  line-height: 1.15;
  font-weight: 700;
  color: var(--ink-text);
}

/* —— online 态：称号行 + 防沉迷环占位 —— */
.pp-cloud-title {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 4px 0;
}
.pp-cloud-title-icon {
  display: inline-flex;
  color: var(--ink-text);
}
.pp-cloud-title-name {
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  color: var(--ink-text);
}

/* 称号进度条（T-M5-05③）：填充 scaleX transform 白名单【§6】，reduced-motion 直跳 */
.pp-title-progress {
  margin: 6px 4px 0;
  height: 8px;
  border-radius: 4px;
  background: var(--border-province);
  overflow: hidden;
}
.pp-title-progress-bar {
  height: 100%;
  border-radius: 4px;
  background: var(--cta-main);
  transform-origin: left center;
  transform: scaleX(0);
  transition: transform var(--dur-celebrate) ease-out;
}
.pp-title-next {
  margin: 4px 4px 0;
  font-size: var(--fs-caption);
  color: var(--ink-sub);
}
@media (prefers-reduced-motion: reduce) {
  .pp-title-progress-bar {
    transition: none;
  }
}

.pp-focus {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border: 2px solid var(--border-province);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
}
.pp-focus-ring {
  display: inline-flex;
  flex-shrink: 0;
}
.pp-focus-text {
  font-size: var(--fs-body-desktop);
  color: var(--ink-sub);
}

/* —— offline 态：离线纪念册标注（本地数据照常渲染，小字诚实标注未上云） —— */
.pp-cloud.is-offline {
  padding: 10px 12px;
  border: 2px dashed var(--border-province);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
}
.pp-offline-note {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-sub);
}
.pp-offline-icon {
  display: inline-flex;
  flex-shrink: 0;
  color: var(--status-grey);
}

/* ============================================================
 * T-M4-09 【学堂】台风小学堂壳 + 词典卡通用化【PRD F-12 学堂容器行 / §11.4 /
 *   tasks_M4 T-M4-09②③ / ui-design-style §4·§5.8·§9】
 *   四栏目导航（选中态 = 底色 + 加粗 + 左侧色条三重冗余编码，不靠颜色单独
 *   表意）+ 栏目卡（栏目名 / 学习目标 / 词条行挂 ？圆点 / 互动件空槽）+
 *   朗读总开关（默认关，关态不渲染卡片喇叭，禁灰置死控件）。
 *   词典小卡：贴边翻转（is-flip-x / is-flip-y）防出屏【AC-a】；右上喇叭。
 * ============================================================ */
.school-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 16px 18px;
}
.school-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: var(--fs-card-title);
  color: var(--ink-text);
}
.school-title-icon {
  display: inline-flex;
  color: var(--rainband-deep);
}
.school-hint {
  margin: 0;
  font-size: var(--fs-body-desktop);
  line-height: 1.5;
  color: var(--ink-sub);
}

/* —— 朗读总开关：整行 48px 热区，开态高对比（关态为幽灵态）—— */
.school-tts-row {
  display: flex;
}
.school-tts {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 48px; /* 触控热区下限【§4 / N-6.3】 */
  padding: 0 14px;
  border: 2px solid var(--rainband-light);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-sub);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
}
.school-tts.is-on {
  border-color: var(--rainband-mid);
  background: var(--ocean-base);
  color: var(--rainband-deep);
}

/* —— 四栏目导航：2×2 网格（dock 宽度 300–360px，四个栏目名 4–5 字）—— */
.school-nav {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.school-tab {
  min-height: 48px; /* 触控热区下限【§4 / N-6.3】 */
  padding: 0 8px;
  border: 2px solid var(--border-province);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  color: var(--ink-sub);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
}
/* 选中态三重冗余编码：底色 + 字色 + 左侧色条（色弱可达【§5.8】） */
.school-tab.is-active {
  border-color: var(--rainband-mid);
  background: var(--ocean-base);
  color: var(--ink-text);
  box-shadow: inset 4px 0 0 var(--rainband-deep);
}

.school-cards {
  display: flex;
  flex-direction: column;
}
.school-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px 14px;
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  border: 2px solid var(--rainband-light);
}
.school-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.school-card-name {
  margin: 0;
  font-size: var(--fs-body-ipad);
  color: var(--ink-text);
}
.school-speak {
  width: 48px; /* 触控热区下限【§4】 */
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--rainband-mid);
  cursor: pointer;
  padding: 0;
}
.school-goal {
  display: flex;
  gap: 8px;
  margin: 0;
  font-size: var(--fs-body-desktop);
  line-height: 1.5;
  color: var(--ink-text);
}
.school-goal-label {
  flex: none;
  color: var(--ink-sub);
  font-weight: 700;
}
.school-terms-label {
  margin: 0;
  font-size: 13px;
  color: var(--ink-sub);
}
.school-terms {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
}
/* ？圆点定位锚：position:relative 供 dict-card 贴行挂卡 */
.school-term {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 48px;
}
.school-term-name {
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  color: var(--ink-text);
  /* 最长词条「最佳路径数据」防溢出【AC-c】：按字断行，禁撑破卡片 */
  overflow-wrap: anywhere;
}
/* 互动件槽：T-M4-10 题库 / T-M4-11 家园保卫回填，本任务空槽零占位 */
.school-slot {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.school-slot:empty {
  display: none;
}

/* —— 词典小卡通用化补强【T-M4-09③】：贴边翻转 + 朗读喇叭 —— */
.dict-card.is-flip-x {
  left: auto;
  right: 0;
}
.dict-card.is-flip-y {
  top: auto;
  bottom: calc(100% + 4px);
}
.dict-card:has(.dict-speak) {
  padding-right: 52px; /* 让位右上喇叭，防正文压字 */
}
.dict-speak {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 44px; /* 词典卡内嵌次级控件：同信息卡单删钮 44px 例外下限 */
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--rainband-mid);
  cursor: pointer;
  padding: 0;
}
/* 最长词条防溢出：科学名按字断行，卡内三件套禁撑破宽度【AC-c】 */
.dict-sci {
  overflow-wrap: anywhere;
}

/* ============================================================
 * T-M4-10 【学堂】题库作答流【PRD 附录C 15 题 / F-12 行为表「学堂题库」行 /
 *   tasks_M4 T-M4-10②③④ / ui-design-style §4·§5.8·§9】
 *   一屏一题 + 章节进度点 + 零惩罚错答流（冷知识就地展开 + 中性思考短音 +
 *   可原地重选）。错答零打击元素：禁红色警示样式（§6.7 禁项），答对仅暖橙
 *   ✔ 标记与正向短语；进度点用雨带蓝表示"已答满格"（等级色/状态灯色禁挪用
 *   【token.css §3.4】，故不取 status-green）。
 * ============================================================ */
.quiz-flow {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 2px;
}
.quiz-progress-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.quiz-progress-text {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-sub);
  font-variant-numeric: tabular-nums;
}
.quiz-dots {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.quiz-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid var(--rainband-light);
  background: transparent;
  transition: background var(--dur-pop-in) ease-out, border-color var(--dur-pop-in) ease-out;
}
.quiz-dot.is-done {
  border-color: var(--rainband-mid);
  background: var(--rainband-mid);
}
.quiz-dot.is-current {
  border-color: var(--cta-main);
  background: var(--cta-main);
}

.quiz-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px;
  border: 2px solid var(--rainband-light);
  border-radius: var(--radius-cta);
  background: var(--paper-card);
}
.quiz-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.quiz-type {
  display: inline-flex;
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--ocean-base);
  color: var(--rainband-deep);
  font-size: 12px;
  font-weight: 700;
}
.quiz-correct-hint {
  font-size: 13px;
  font-weight: 700;
  color: var(--cta-main);
}
.quiz-question {
  margin: 0;
  font-size: var(--fs-body-desktop);
  line-height: 1.6;
  font-weight: 700;
  color: var(--ink-text);
  overflow-wrap: anywhere;
}
.quiz-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.quiz-option {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px; /* 触控热区下限【§4 / N-6.3】 */
  padding: 6px 12px 6px 8px;
  border: 2px solid var(--border-province);
  border-radius: 12px;
  background: #ffffff;
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--dur-pop-in) ease-out, background var(--dur-pop-in) ease-out;
}
.quiz-option:hover:not(:disabled) {
  border-color: var(--cta-main);
}
.quiz-option-idx {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid var(--rainband-light);
  color: var(--rainband-mid);
  font-size: 13px;
  font-weight: 700;
}
/* 答对高亮（暖橙，非红色警示）：✔ 标记 + 底色，选项区整体锁定 */
.quiz-option.is-correct {
  border-color: var(--cta-main);
  background: #FFF3E0;
}
.quiz-option-mark {
  display: inline-flex;
  flex: none;
  margin-left: auto;
  color: var(--cta-main);
}
.quiz-option:disabled {
  cursor: default;
}

/* —— 连线型（点选配对：环行 + 数字牌行） —— */
.quiz-match {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.quiz-match-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.quiz-match-rings .quiz-ring,
.quiz-match-pads .quiz-pad {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 48px;
  min-width: 72px;
  padding: 4px 14px;
  border: 2px solid var(--rainband-light);
  border-radius: 12px;
  background: #ffffff;
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
  transition: border-color var(--dur-pop-in) ease-out, background var(--dur-pop-in) ease-out;
}
.quiz-ring.is-selected {
  border-color: var(--cta-main);
  background: #FFF3E0;
}
.quiz-ring.is-matched,
.quiz-pad.is-matched {
  border-color: var(--rainband-mid);
  background: var(--ocean-base);
  color: var(--rainband-deep);
}
.quiz-ring:disabled,
.quiz-pad:disabled {
  cursor: default;
}

/* —— 冷知识条：错答必现，就地展开（PRD 冷知识列原文），零打击元素 —— */
.quiz-fact {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  padding: 8px 10px;
  border: 2px solid var(--rainband-light);
  border-radius: 10px;
  background: var(--ocean-base);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-text);
}
.quiz-fact-icon {
  display: inline-flex;
  flex: none;
  margin-top: 2px;
  color: var(--rainband-deep);
}
.quiz-fact-label {
  flex: none;
  font-weight: 700;
  color: var(--rainband-deep);
}
.quiz-fact-text {
  overflow-wrap: anywhere;
}

/* —— 翻页：上一题 / 下一题（末题答对变「完成」），48px 热区 —— */
.quiz-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.quiz-prev,
.quiz-next {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 48px;
  padding: 0 14px;
  border: 2px solid var(--rainband-mid);
  border-radius: var(--radius-cta);
  background: #ffffff;
  color: var(--rainband-deep);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
}
.quiz-prev:disabled,
.quiz-next:disabled {
  opacity: 0.45;
  cursor: default;
}

/* ============================================================
 * F-08 防灾课堂三件套【tasks_M4 T-M4-11 / PRD F-08 规格②③】
 * 纸白卡底 + 雨带蓝信息色 + 暖橙行动色；全程零红色、零警示、零否定符号
 * 【N-5.x 温和呈现 / ui-design-style §3.4 等级色禁挪交互语义】。
 * ============================================================ */

/* —— 第四栏目同槽分区：题库区（data-widget="quiz"）与家园保卫区
     （data-widget="home-guard"）同挂在 .school-slot 内，间距落在此处统一管
     【tasks_M4 T-M4-10 裁决③ 同槽共存】 —— */
.school-slot > .home-guard {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 2px dashed var(--rainband-light);
}

/* —— 家园保卫小游戏（拖拽题）—— */
.home-guard {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.home-guard-prompt {
  margin: 0;
  font-size: var(--fs-card-title);
  font-weight: 700;
  line-height: 1.4;
  color: var(--ink-text);
}

/* 三个落位槽：虚线空槽 → 吸附高亮 → 填满 → 集齐 */
.home-guard-slots {
  display: flex;
  align-items: stretch;
  gap: 8px;
}
.home-guard-slot {
  display: flex;
  flex: 1 1 0;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  padding: 4px;
  border: 2px dashed var(--rainband-light);
  border-radius: 12px;
  background: #ffffff;
  transition: border-color var(--dur-pop-in) ease-out,
              background-color var(--dur-pop-in) ease-out;
}
.home-guard-slot.is-hover {
  border-color: var(--cta-main);
  background: var(--ocean-base);
}
.home-guard-slot.is-filled {
  border-style: solid;
  border-color: var(--rainband-mid);
  background: var(--ocean-base);
}
.home-guard-slot.is-done {
  border-color: var(--cta-main);
}

/* 六张物品卡：3×2 网格；≥48px 热区【ui-design-style §4】；程序化 SVG 图标 */
.home-guard-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
.home-guard-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 64px;
  padding: 8px 4px;
  border: 2px solid var(--rainband-light);
  border-radius: 12px;
  background: var(--paper-card);
  color: var(--ink-text);
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  line-height: 1.3;
  cursor: grab;
  /* touch-action:none 防 iPad Safari 把拖拽判成滚动手势后抛 pointercancel
     【任务书避坑❷ / 地图拖拽同源经验】；JS 侧另设一次防样式被覆盖 */
  touch-action: none;
  user-select: none;
  transition: transform var(--dur-pop-in) ease-out,
              border-color var(--dur-pop-in) ease-out,
              box-shadow var(--dur-pop-in) ease-out;
}
.home-guard-card.is-dragging {
  z-index: 20;
  cursor: grabbing;
  border-color: var(--cta-main);
  box-shadow: 0 8px 18px rgba(10, 30, 50, 0.2);
  /* 拖拽中禁过渡：位移须实时跟手，不能插值滞后 */
  transition: none;
}
.home-guard-card.is-selected {
  border-color: var(--cta-main);
  box-shadow: 0 0 0 3px var(--ocean-base);
}
.home-guard-card.is-placed {
  width: 100%;
  min-height: 48px;
  cursor: default;
  border-color: var(--rainband-mid);
  background: #ffffff;
}
.home-guard-card-icon {
  display: inline-flex;
  color: var(--rainband-deep);
}
.home-guard-card-label {
  text-align: center;
  overflow-wrap: anywhere;
}

/* 错配抖动：温柔小幅（±6° / 250ms），无红色、无 ✕、无位移惩罚【零惩罚总则】 */
@keyframes home-guard-shake {
  0% { transform: rotate(0deg); }
  25% { transform: rotate(-6deg); }
  55% { transform: rotate(6deg); }
  80% { transform: rotate(-3deg); }
  100% { transform: rotate(0deg); }
}
.home-guard-card.is-shake {
  animation: home-guard-shake var(--dur-pop-in) ease-in-out;
  border-color: var(--rainband-mid); /* 中性信息色，禁 TY_RED 等警示色 */
}

/* 冷知识式提示条（正解理由 / 干扰项专属反馈语 / 集齐庆祝语共用） */
.home-guard-tip {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin: 0;
  padding: 8px 10px;
  border: 2px solid var(--rainband-light);
  border-radius: 10px;
  background: var(--ocean-base);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-text);
  opacity: 0;
  transition: opacity var(--dur-pop-in) ease-out;
}
.home-guard-tip.is-on {
  opacity: 1;
}
.home-guard-tip-icon {
  display: inline-flex;
  flex: none;
  margin-top: 2px;
  color: var(--rainband-deep);
}
.home-guard-tip-label {
  flex: none;
  font-weight: 700;
  color: var(--rainband-deep);
}
.home-guard-tip-text {
  overflow-wrap: anywhere;
}

/* 集齐庆祝：整区轻微回弹（庆祝 900ms 量级【§6】），仅 transform */
@keyframes home-guard-cheer {
  0% { transform: scale(1); }
  35% { transform: scale(1.04); }
  70% { transform: scale(0.99); }
  100% { transform: scale(1); }
}
.home-guard.is-complete .home-guard-slots {
  animation: home-guard-cheer var(--dur-celebrate) ease-out;
}

/* 再来一局：CTA 主行动（暖橙 + 圆角 16px + ≥48px 热区） */
.home-guard-again {
  min-height: 48px;
  padding: 0 16px;
  border: none;
  border-radius: var(--radius-cta);
  background: var(--cta-main);
  color: #ffffff;
  font-family: inherit;
  font-size: var(--fs-body-desktop);
  font-weight: 700;
  cursor: pointer;
}

/* —— 登陆联动事件卡（全局浮层·两句式情境卡）——
   定位：地图区顶部居中（避开信息卡落点与 Toast 带），z-index 低于 Toast
   （980）高于里程碑卡（960）；可点击关闭，故 pointer-events 保持 auto。 */
.event-card {
  position: fixed;
  top: 96px;
  left: calc((100% - var(--dock-w)) / 2);
  z-index: 970;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  max-width: min(420px, calc(100% - var(--dock-w) - 48px));
  padding: 12px 14px;
  border-radius: var(--radius-cta);
  background: var(--paper-card-glass);
  color: var(--ink-text);
  box-shadow: inset 0 1px 0 var(--glass-sheen), inset 0 0 0 1px var(--glass-edge), 0 8px 22px rgba(10, 30, 50, 0.22); /* B 方案玻璃工艺 2026-09-05 拍板 */
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
  backdrop-filter: blur(8px) saturate(1.2);
  opacity: 0;
  transform: translateX(-50%) translateY(-12px);
  transition: transform var(--dur-pop-in) ease-out, opacity var(--dur-pop-in) ease-out;
}
.event-card.is-on {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.event-card-icon {
  display: inline-flex;
  flex: none;
  margin-top: 2px;
  color: var(--rainband-deep);
}
.event-card-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.event-card-phenomenon {
  margin: 0;
  font-size: var(--fs-body-ipad);
  font-weight: 400;
  line-height: 1.45;
  color: var(--ink-text);
}
.event-card-action {
  margin: 0;
  font-size: var(--fs-body-ipad);
  font-weight: 700;
  line-height: 1.45;
  color: var(--cta-main); /* 行动句用暖橙主行动色，呼应"我们可以做" */
}
.event-card-close {
  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-sub);
  cursor: pointer;
}

/* —— 动效降级：prefers-reduced-motion 一律直跳终态【ui-design-style §6】—— */
@media (prefers-reduced-motion: reduce) {
  .home-guard-card.is-shake {
    animation: none;
  }
  .home-guard.is-complete .home-guard-slots {
    animation: none;
  }
  .event-card {
    transition: opacity var(--dur-pop-in) ease-out;
    transform: translateX(-50%);
  }
  .event-card.is-on {
    transform: translateX(-50%);
  }
}

/* ============================================================
 * T-M4-12 螺旋雨带「示意效果」双件【PRD §5.4 科普示意值口径声明 / §11.3 降雨
 *   可视化规格】——ui/rain-legend.js 消费（initRainNote 装配，app.js 经既有
 *   STATE 消费点驱动显隐）。
 *   ① 常驻角标「示意效果」+ §5.4 文案模板逐字（三类示意值共用，故常驻）；
 *   ② 色阶图例条：三色块 + 小雨/大雨/暴雨口语档，仅雨带显现时出现。
 *   载体：DOM 覆盖层（同 .map-badge 海域角标先例），非 Leaflet 控件——
 *   规避控件位随缩放动画位移/遮挡；色值经 class 消费 token.css 变量
 *   （CSP default-src 'self' 禁内联 style【§3.4 / TSD §13.4】）。
 *   落位：地图区左下角、回家按钮正上方（home-button bottom18 + 直径56 + 12 间距
 *   = 86px），与右下角海域角标成对角，互不遮挡；pointer-events:none 全程不吃点击。
 * ============================================================ */
.rain-note {
  position: fixed;
  left: 18px;
  bottom: 86px;
  z-index: 900; /* 与 .map-badge 同层：高于 Leaflet 各 pane（上限约 700），低于交互控件 */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  max-width: min(300px, calc(100% - var(--dock-w) - 36px));
  pointer-events: none; /* 纯说明性覆盖层，禁拦截地图拖拽/点击 */
}

/* —— ① 色阶图例条：槽位恒定保留（visibility 切换而非 display），
      故出现/消失零布局抖动，且可做 250ms 淡入淡出 —— */
.rain-legend {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 8px 12px;
  border-radius: var(--radius-cta);
  background: var(--paper-card);
  box-shadow: 0 3px 10px rgba(55, 71, 79, 0.25); /* INK_TEXT 投影系中性阴影（同 .home-button） */
  opacity: 0;
  visibility: hidden;
  transform: translateY(6px);
  transition:
    opacity var(--dur-pop-in) ease-out,
    transform var(--dur-pop-in) ease-out,
    visibility 0s linear var(--dur-pop-in);
}
.rain-legend.is-on {
  opacity: 0.94;
  visibility: visible;
  transform: translateY(0);
  transition:
    opacity var(--dur-pop-in) ease-out,
    transform var(--dur-pop-in) ease-out,
    visibility 0s;
}

.rain-legend-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

/* 色块：等级色禁挪交互语义【§3.4】，雨带三色为降水语义专用，与 --td-blue 等
   等级色互不相干；圆角 6px 弱化"按钮感"，读作"色卡"而非"可点控件" */
.rain-swatch {
  display: block;
  width: 26px;
  height: 12px;
  border-radius: 6px;
}
.rain-swatch--light {
  background: var(--rainband-light); /* 小雨 */
}
.rain-swatch--mid {
  background: var(--rainband-mid); /* 大雨 */
}
.rain-swatch--deep {
  background: var(--rainband-deep); /* 暴雨 */
}

.rain-legend-label {
  font-size: var(--fs-body-desktop); /* 守桌面正文下限 16px【§4】 */
  font-weight: 500;
  color: var(--ink-text);
  line-height: 1.2;
}

/* —— ② 常驻「示意效果」角标：纸白半透明胶囊 + 深墨正文（同 .map-badge 同族） —— */
.rain-note-badge {
  margin: 0;
  padding: 6px 10px;
  border-radius: 10px;
  background: var(--paper-card);
  opacity: 0.92;
  color: var(--ink-sub);
  font-size: var(--fs-body-desktop); /* 角标也守桌面正文下限 16px，禁小灰字【§4】 */
  line-height: 1.35;
  user-select: none;
}
.rain-note-title {
  display: block;
  color: var(--ink-text);
  font-weight: 600;
  letter-spacing: 0.5px;
}
.rain-note-text {
  display: block;
}

/* iPad 正文下限 18px【§4】——与全站既有 iPad 分支同口径 */
@media (min-width: 1024px) and (pointer: coarse) {
  .rain-legend-label,
  .rain-note-badge {
    font-size: var(--fs-body-ipad);
  }
}

/* 窄视口：让位停靠栏与地图主体，缩窄但不隐藏（§5.4 常驻底线不可让渡） */
@media (max-width: 640px) {
  .rain-note {
    max-width: calc(100% - 36px);
    bottom: 80px;
  }
}

/* —— 动效降级：prefers-reduced-motion 直显直隐【ui-design-style §6】—— */
@media (prefers-reduced-motion: reduce) {
  .rain-legend {
    transition: none;
    transform: translateY(0);
  }
}

/* T-M5-08 egg-gift + parent-admin */
.egg-gift{position:fixed;left:50%;top:50%;z-index:980;width:min(340px,calc(100vw - 48px));padding:4px;border-radius:24px;overflow:hidden;opacity:0;transform:translate(-50%,-50%) scale(0.92);transition:opacity 900ms ease-out,transform 900ms ease-out;}
.egg-gift.is-on{opacity:1;transform:translate(-50%,-50%) scale(1);}
.egg-gift-inner{background:var(--surface-card,#fff);border-radius:20px;padding:18px 16px 14px;display:flex;flex-direction:column;gap:10px;}
.egg-gift-grandpa{color:var(--cta-main,#ff7043);}
.egg-gift-intro{font-size:16px;font-weight:700;color:var(--text-main,#37474f);margin:0;}
.egg-gift-progress{font-size:12px;color:var(--text-sub,#78909c);margin:0;}
.egg-gift-question{font-size:15px;line-height:1.6;color:var(--text-main,#37474f);margin:0;}
.egg-gift-options{display:flex;flex-direction:column;gap:8px;}
.egg-gift-option{min-height:48px;border-radius:14px;border:2px solid var(--border-province,#cfd8dc);background:var(--surface-card,#fff);font-size:15px;color:var(--text-main,#37474f);cursor:pointer;}
.egg-gift-feedback{font-size:14px;line-height:1.6;margin:0;color:var(--text-sub,#78909c);}
.egg-gift-feedback.is-good{color:var(--cta-main,#ff7043);font-weight:700;}
.egg-gift-actions{display:flex;flex-direction:column;gap:8px;}
.egg-gift-btn{min-height:48px;border-radius:14px;font-size:16px;font-weight:700;border:2px solid transparent;cursor:pointer;background:var(--cta-main,#ff7043);color:#fff;}
.egg-gift-btn.is-finish{background:var(--surface-card,#fff);border-color:var(--border-province,#cfd8dc);color:var(--text-main,#37474f);}
@media (prefers-reduced-motion: reduce){.egg-gift{transition:none;}}
/* T-M5-08 瀹堕暱瑙傛祴绔欐帶鍒跺彴锛堥潰鍚戝闀匡紱浣庤皟鍏ュ彛 pp-admin-key锛?*/
.pp-admin-key{display:block;margin:10px auto 0;padding:4px 10px;font-size:11px;color:var(--text-sub,#78909c);background:none;border:none;cursor:pointer;text-decoration:underline dotted;}
.parent-admin{position:fixed;left:50%;top:50%;z-index:990;width:min(360px,calc(100vw - 48px));padding:4px;border-radius:24px;overflow:hidden;opacity:0;transform:translate(-50%,-50%) scale(0.92);transition:opacity 300ms ease-out,transform 300ms ease-out;}
.parent-admin.is-on{opacity:1;transform:translate(-50%,-50%) scale(1);}
.parent-admin-inner{background:var(--surface-card,#fff);border-radius:20px;padding:18px 16px 14px;display:flex;flex-direction:column;gap:12px;}
.parent-admin-title{font-size:15px;font-weight:700;color:var(--text-main,#37474f);margin:0;}
.parent-admin-body{display:flex;flex-direction:column;gap:10px;}
.parent-admin-passcode{min-height:44px;border-radius:12px;border:2px solid var(--border-province,#cfd8dc);padding:0 12px;font-size:15px;}
.parent-admin-btn{min-height:44px;border-radius:12px;font-size:15px;font-weight:700;border:none;cursor:pointer;background:var(--cta-main,#ff7043);color:#fff;}
.parent-admin-btn:disabled{background:var(--border-province,#cfd8dc);cursor:default;}
.parent-admin-field{display:flex;align-items:center;justify-content:space-between;gap:8px;font-size:14px;color:var(--text-main,#37474f);}
.parent-admin-select{min-height:40px;border-radius:10px;border:2px solid var(--border-province,#cfd8dc);font-size:14px;color:var(--text-main,#37474f);}
.parent-admin-note{font-size:13px;line-height:1.6;margin:0;color:var(--text-sub,#78909c);}
.parent-admin-note.is-good{color:#2e7d32;font-weight:700;}
.parent-admin-note.is-hint{font-size:12px;}
.parent-admin-close{align-self:flex-end;min-height:36px;padding:0 14px;border-radius:10px;border:2px solid var(--border-province,#cfd8dc);background:var(--surface-card,#fff);font-size:13px;cursor:pointer;color:var(--text-main,#37474f);}
@media (prefers-reduced-motion: reduce){.parent-admin{transition:none;}}
/* ============================================================
 * T-M6-03 同学圈挑战面板（ghost-challenge-panel）+ 护照页入口
 * 【tasks_M6 T-M6-03③ / PRD F-14 / ui-design-style §4/§5/§6】
 *   居中大卡（battle-report 同族）+ is-docked 右上小条（arena-hud 同位，
 *   awaiting/running/submitting 态让出地图选点观演）；
 *   practice 灰色中性气泡（B2-7：无红色警示系/无人格定性）。
 * ============================================================ */
.ghost-challenge{position:fixed;left:50%;top:50%;z-index:980;width:min(340px,calc(100vw - 48px));max-height:calc(100vh - 48px);max-height:calc(100dvh - 48px);padding:4px;border-radius:24px;overflow:hidden;opacity:0;transform:translate(-50%,-50%) scale(0.92);transition:opacity 300ms ease-out,transform 300ms ease-out;}
.ghost-challenge.is-on{opacity:1;transform:translate(-50%,-50%) scale(1);}
.ghost-challenge.is-docked{left:auto;top:14px;right:calc(var(--dock-w) + 14px);width:min(260px,calc(100vw - var(--dock-w) - 42px));transform:scale(0.92);}
.ghost-challenge.is-docked.is-on{transform:scale(1);}
.gc-inner{background:var(--surface-card,#fff);border-radius:20px;padding:18px 16px 14px;display:flex;flex-direction:column;gap:10px;max-height:calc(100vh - 56px);max-height:calc(100dvh - 56px);overflow-y:auto;}
.gc-kicker{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:700;color:var(--cta-main,#ff7043);letter-spacing:2px;}
.gc-hint{font-size:13px;line-height:1.6;color:var(--text-sub,#78909c);margin:0;}
.gc-list{display:flex;flex-direction:column;gap:8px;}
.gc-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;min-height:48px;padding:8px 12px;border-radius:14px;border:2px solid var(--border-province,#cfd8dc);background:var(--surface-card,#fff);cursor:pointer;text-align:left;}
.gc-row.is-expanded{border-color:var(--cta-main,#ff7043);}
.gc-avatar{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:50%;color:#fff;flex:none;}
.gc-avatar-icon{display:inline-flex;}
.gc-nick{flex:1;min-width:0;font-size:15px;font-weight:700;color:var(--text-main,#37474f);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.gc-title-band{width:26px;height:8px;border-radius:999px;flex:none;}
.gc-chips{display:flex;flex-wrap:wrap;gap:6px;width:100%;}
.gc-chip{padding:5px 12px;border-radius:999px;background:var(--border-province,#cfd8dc);font-size:13px;color:var(--text-main,#37474f);cursor:pointer;}
.gc-chip.is-selected{background:var(--cta-main,#ff7043);color:#fff;font-weight:700;}
.gc-sk-wrap{display:flex;flex-direction:column;gap:8px;}
.gc-sk{border-radius:12px;background:#eceff1;animation:gc-shimmer 1.4s ease-in-out infinite;}
.gc-sk-row{height:48px;}
@keyframes gc-shimmer{0%,100%{opacity:1;}50%{opacity:0.55;}}
.gc-dock-line{font-size:14px;line-height:1.6;color:var(--text-main,#37474f);margin:0;}
.gc-actions{display:flex;flex-direction:column;gap:8px;}
.gc-btn{min-height:48px;border-radius:14px;font-size:16px;font-weight:700;border:2px solid transparent;cursor:pointer;}
.gc-btn.is-primary{background:var(--cta-main,#ff7043);color:#fff;}
.gc-btn.is-primary:disabled{background:var(--border-province,#cfd8dc);cursor:default;}
.gc-btn.is-secondary{background:var(--surface-card,#fff);border-color:var(--border-province,#cfd8dc);color:var(--text-main,#37474f);}
.gc-result{display:flex;flex-direction:column;align-items:center;gap:6px;text-align:center;}
.gc-result-star{display:inline-flex;color:var(--cta-main,#ff7043);}
.gc-result-title{font-size:18px;font-weight:700;color:var(--text-main,#37474f);margin:0;}
.gc-result-points{padding:3px 14px;border-radius:999px;background:var(--badge-gold-soft,#f9a825);font-size:16px;font-weight:700;color:var(--text-main,#37474f);}
.gc-result-sub{font-size:13px;line-height:1.6;color:var(--text-sub,#78909c);margin:0;}
/* 「练习」徽记【T-M6-05】：本局成绩不计入个人曲线（服务端 practice 零账本写入）。
   灰色中性化强制执行——禁做成醒目红色警示角标（人格贬损红线）：底色纸白 +
   中性灰描边 + 深墨灰字（--ink-text 对纸白 9.6:1），全链路零红色系元素。 */
.gc-badge-practice{display:inline-block;align-self:flex-start;margin-bottom:10px;padding:4px 14px;border-radius:999px;background:var(--surface-card,#fff);border:1.5px solid var(--bubble-neutral,#cfd8dc);font-size:13px;font-weight:700;letter-spacing:2px;color:var(--ink-text,#37474f);}
.gc-bubble-practice{padding:12px 14px;border-radius:14px;background:var(--bubble-neutral,#cfd8dc);font-size:14px;line-height:1.6;color:var(--ink-text,#37474f);}
.pp-challenge-entry{min-height:48px;margin-top:4px;border:none;border-radius:14px;background:var(--cta-main,#ff7043);color:#fff;font-size:15px;font-weight:700;cursor:pointer;}
@media (prefers-reduced-motion: reduce){.ghost-challenge{transition:none;}.gc-sk{animation:none;}}
/* ---- 幽灵对局复盘浮层【T-M6-04③】（gc-* 同族工艺） ---- */
.ghost-review{position:fixed;inset:0;z-index:1200;display:flex;align-items:center;justify-content:center;background:rgba(55,71,79,0.35);opacity:0;transition:opacity 0.25s ease;}
.ghost-review.is-on{opacity:1;}
.ghost-review[hidden]{display:none;}
.grv-inner{width:min(360px,calc(100vw - 32px));padding:20px;border-radius:16px;background:var(--paper-card,#fff9f0);box-shadow:0 12px 32px rgba(55,71,79,0.18);}
.grv-title{font-size:20px;font-weight:700;color:var(--text-main,#37474f);margin:0 0 10px;}
.grv-svg{border-radius:12px;background:var(--surface-card,#fff);border:1px solid var(--border-province,#cfd8dc);overflow:hidden;}
.grv-legend{display:flex;align-items:center;gap:6px;font-size:14px;color:var(--text-sub,#78909c);margin:10px 0 14px;}
.grv-dot{width:18px;height:0;border-top:3px solid var(--cta-main,#ff7043);}
.grv-dot.is-ghost{border-top-style:dashed;border-top-color:var(--ghost-track,#9575cd);}
.grv-actions{display:flex;flex-direction:column;gap:8px;}
.grv-btn{min-height:48px;border-radius:14px;font-size:18px;font-weight:700;border:2px solid transparent;cursor:pointer;}
.grv-btn.is-primary{background:var(--cta-main,#ff7043);color:#fff;}
.grv-btn.is-secondary{background:var(--surface-card,#fff);border-color:var(--border-province,#cfd8dc);color:var(--text-main,#37474f);}
@media (prefers-reduced-motion: reduce){.ghost-review{transition:none;}}

/* ============================================================
 * T-M6-06 同学录好友区块【tasks_M6 T-M6-06③ / PRD §9.3 关系图 / F-14 隐私行】
 *   绘本纸感 · 同学录一页：纸卡底 + 圆角卡 + 程序化头像，与护照页同纸卡体系。
 *   零分数零排序位次零序号：好友卡片上不出现任何数字（称号走**名**不走级别）。
 *   移除钮中性灰（--bubble-neutral）——好友解除是儿童主导权，绝非惩戒，
 *   禁用红色警示系【B2-7 像素级中性：好友解除是儿童主导权，绝非惩戒性视觉】。
 *   热区纪律：移除钮 / 键盘按键 / 主行动钮一律 ≥48px【ui-design-style §4】。
 *   色值纪律：全部取自 token.css 既有令牌，禁新增随意 hex【ui-design-style §3.4】。
 * ============================================================ */
.pp-friends{display:flex;flex-direction:column;gap:8px;padding:12px;border-radius:16px;background:var(--paper-card,#fff9f0);border:1px solid var(--border-province,#dccba4);}
.pp-friends[hidden]{display:none;}
.fr-list{display:flex;flex-direction:column;gap:8px;}
.fr-empty{margin:0;padding:8px 0;font-size:15px;line-height:1.6;color:var(--ink-sub,#78909c);}
.fr-row{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:14px;background:var(--surface-card,#fff);border:1px solid var(--border-province,#dccba4);}
.fr-avatar{display:inline-flex;width:32px;height:32px;flex:0 0 32px;border-radius:50%;overflow:hidden;background:var(--ocean-base,#dff1fc);}
.fr-avatar svg{width:32px;height:32px;display:block;}
.fr-text{flex:1 1 auto;min-width:0;}
.fr-nickname{font-size:16px;font-weight:700;color:var(--ink-text,#37474f);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.fr-title{display:flex;align-items:center;gap:4px;font-size:14px;color:var(--ink-sub,#78909c);}
.fr-title-icon{display:inline-flex;color:var(--ink-sub,#78909c);}
/* 移除钮：中性灰胶囊（禁红色警示系），热区 ≥48px */
.fr-remove{flex:0 0 auto;min-height:48px;padding:0 16px;border:none;border-radius:999px;background:var(--bubble-neutral,#cfd8dc);color:var(--ink-text,#37474f);font-family:inherit;font-size:15px;font-weight:700;cursor:pointer;}
.fr-remove:active{transform:scale(0.97);}
/* ---- 好友码绑定区：4 码位方格 + 32 键点选键盘 ---- */
.fr-bind{display:flex;flex-direction:column;gap:8px;padding:10px;border-radius:14px;background:var(--surface-card,#fff);border:1px solid var(--border-province,#dccba4);}
.fr-bind-label{margin:0;font-size:15px;font-weight:700;color:var(--ink-text,#37474f);}
.fr-slots{display:grid;grid-template-columns:repeat(4,48px);gap:8px;justify-content:start;}
.fr-slot{display:flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:12px;border:2px dashed var(--border-province,#dccba4);background:var(--ocean-base,#dff1fc);font-size:22px;font-weight:700;color:var(--ink-text,#37474f);}
.fr-slot.is-filled{border-style:solid;border-color:var(--cta-main,#ff7043);background:var(--paper-card,#fff9f0);}
.fr-hint{margin:0;font-size:14px;line-height:1.5;color:var(--ink-sub,#78909c);}
.fr-hint[hidden]{display:none;}
.fr-kbd{display:flex;flex-direction:column;gap:6px;}
.fr-kbd-row{display:grid;grid-template-columns:repeat(8,1fr);gap:6px;}
.fr-key{min-height:48px;border:1px solid var(--border-province,#dccba4);border-radius:12px;background:var(--paper-card,#fff9f0);color:var(--ink-text,#37474f);font-family:inherit;font-size:17px;font-weight:700;cursor:pointer;}
.fr-key:active{transform:scale(0.96);}
.fr-key.is-del{min-height:48px;border-radius:12px;background:var(--bubble-neutral,#cfd8dc);}
.fr-bind-btn{min-height:48px;border:none;border-radius:14px;background:var(--bubble-neutral,#cfd8dc);color:var(--ink-text,#37474f);font-family:inherit;font-size:16px;font-weight:700;cursor:default;}
.fr-bind-btn.is-ready{background:var(--cta-main,#ff7043);color:#fff;cursor:pointer;}
.fr-bind-btn:disabled{cursor:default;}
/* iPad 与窄栏：正文 ≥18px【ui-design-style §4】，好友卡文字不换行、钮换行行尾 */
@media (max-width: 480px){
  .fr-row{flex-wrap:wrap;}
  .fr-remove{margin-left:auto;}
  .fr-nickname{font-size:18px;}
  .fr-title{font-size:16px;}
}
@media (prefers-reduced-motion: reduce){
  .fr-key:active,.fr-remove:active{transform:none;}
}

/* ============================================================
 * T-M6-07 同学圈友好榜区块【tasks_M6 T-M6-07 / PRD F-14 同学圈行 / §7.4 /
 * §9.3 / TSD §8.5 V1.16 / openapi.yaml 0.16.0-M6 /api/ranking/*】
 *   绘本纸感 · 与同学录同纸卡体系（米白纸卡底 + 大圆角 + 既有令牌色）。
 *   气泡大小是人群规模的唯一编码维度：可见面不写人数数字（data-count +
 *   aria-label 承载）；count=0 虚线空槽；本人档叠「我」徽标（无坐标无比较）。
 *   自我曲线只与上一次的自己比：末点标注中性灰，负向同灰——全区块禁用红色
 *   警示系【B2-7 像素级中性、零惩罚视觉】。
 *   色值纪律：全部取自 token.css 既有令牌，禁新增随意 hex【ui-design-style §3.4】。
 * ============================================================ */
.pp-circle{display:flex;flex-direction:column;gap:8px;padding:12px;border-radius:16px;background:var(--paper-card,#fff9f0);border:1px solid var(--border-province,#dccba4);}
.pp-circle[hidden]{display:none;}
/* ---- 七档气泡图：横向七等分槽位，窄屏等比缩小不换行 ---- */
.tb-chart{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;}
.tb-slot{position:relative;display:flex;align-items:flex-end;justify-content:center;min-height:64px;padding:6px 2px 10px;border:none;border-radius:12px;background:transparent;font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent;}
.tb-slot:active{transform:scale(0.97);}
.tb-bubble{display:block;width:28px;height:28px;border-radius:50%;box-shadow:0 2px 6px rgba(55,71,79,0.18);}
.tb-bubble.is-empty{width:18px;height:18px;background:transparent;border:2px dashed var(--border-province,#dccba4);box-shadow:none;}
/* 本人档「我」徽标：气泡右上角小圆牌（纸卡底描边，非坐标非比较） */
.tb-me{position:absolute;top:2px;right:6px;display:flex;align-items:center;justify-content:center;min-width:20px;height:20px;padding:0 5px;border-radius:999px;background:var(--surface-card,#fff);border:1.5px solid var(--cta-main,#ff7043);color:var(--ink-text,#37474f);font-size:12px;font-weight:700;line-height:1;}
/* 点击槽位后的公开阈值提示条：150ms 淡入上浮微动效（transform/opacity 合成层） */
.tb-hint{margin:0;padding:8px 12px;border-radius:12px;background:var(--surface-card,#fff);border:1px solid var(--border-province,#dccba4);font-size:14px;line-height:1.5;color:var(--ink-text,#37474f);animation:tb-hint-in 150ms ease-out;}
.tb-hint[hidden]{display:none;}
@keyframes tb-hint-in{from{opacity:0;transform:translateY(4px);}to{opacity:1;transform:translateY(0);}}
.tb-invite{margin:0;padding:6px 0 0;font-size:14px;line-height:1.6;color:var(--ink-sub,#78909c);}
.tb-invite[hidden]{display:none;}
/* ---- 自我参照曲线：无刻度无坐标轴，末点标注中性灰（负向同灰禁红） ---- */
.sc-title{margin:6px 0 0;font-size:15px;font-weight:700;color:var(--ink-text,#37474f);}
.sc-curve{padding:4px 0 0;}
.sc-curve svg{display:block;}
.sc-delta{margin:0;padding:0 4px;text-align:right;font-size:14px;font-weight:700;color:var(--ink-sub,#78909c);}
.sc-delta[hidden]{display:none;}
.sc-empty{margin:0;padding:6px 0;font-size:14px;line-height:1.6;color:var(--ink-sub,#78909c);}
.sc-empty[hidden]{display:none;}
/* iPad 与窄栏：七槽等比缩小不换行，触控热区仍 ≥44px */
@media (max-width: 480px){
  .tb-slot{min-height:56px;padding:4px 1px 8px;}
  .tb-me{min-width:18px;height:18px;font-size:11px;}
}
@media (prefers-reduced-motion: reduce){
  .tb-slot:active{transform:none;}
  .tb-hint{animation:none;}
}

/* ============================================================
 * T-PWA-01 添加到主屏幕引导卡：底部浮出玻璃卡（B 方案工艺真源），
 * 无全屏遮罩（N-8.2：pointer-events 仅卡体，地图照常可玩）；
 * 入场 translateY+opacity 300ms ease-out 对齐 ghost-challenge 浮层节奏。
 * ============================================================ */
.pwa-hint{position:fixed;left:50%;bottom:16px;z-index:970;width:min(340px,calc(100vw - 48px));transform:translate(-50%,16px);opacity:0;transition:opacity 300ms ease-out,transform 300ms ease-out;pointer-events:none;}
.pwa-hint.is-on{transform:translate(-50%,0);opacity:1;pointer-events:auto;}
.pwa-hint-card{background:var(--paper-card-glass);border-radius:24px;padding:18px 16px 14px;display:flex;flex-direction:column;gap:10px;box-shadow:inset 0 1px 0 var(--glass-sheen),inset 0 0 0 1px var(--glass-edge),0 6px 18px rgba(55,71,79,0.28);-webkit-backdrop-filter:blur(8px) saturate(1.2);backdrop-filter:blur(8px) saturate(1.2);}
.pwa-hint-title{margin:0;font-size:17px;font-weight:700;line-height:1.4;color:var(--ink-text,#37474F);}
.pwa-hint-steps{margin:0;font-size:14px;line-height:1.6;color:var(--ink-sub,#78909C);}
.pwa-hint-ok{min-height:48px;border:none;border-radius:14px;background:var(--cta-main,#FF7043);color:#fff;font-size:16px;font-weight:700;cursor:pointer;transition:opacity .15s;}
.pwa-hint-ok:active{opacity:.85;}
@media (prefers-reduced-motion: reduce){
  .pwa-hint{transition:none;}
}
