/* public/css/layout.css —— 骨架栅格与三档断点(DESIGN §11.4;v7 罗盘留白 SPEC-v7 §5)
 *
 * 为什么用一整块 grid 覆盖层,而不是给每个控件写 position:absolute:
 * 1. 地图是全屏底(#map fixed inset:0),UI 全部叠在上面。若各控件各自 absolute + 硬编码
 *    偏移,三个断点就要维护三套坐标,还挡不住互相重叠。一块 grid 用具名区域一次排完,断点只换几个变量。
 * 2. 覆盖层默认 pointer-events:none,只有插槽里的**实际控件**(.slot > *)吃指针事件 ——
 *    这样插槽之间的空白仍然能拖地图。UI 模块只管往插槽里塞自己的根元素,不用关心穿透。
 * 3. 高度用 100dvh:移动端浏览器地址栏收起/展开会改变 vh,用 vh 时间轴会被顶出屏幕。
 * 4. 安全区:覆盖层整体加 env(safe-area-inset-*) 内边距(index.html 已声明 viewport-fit=cover)。
 *
 * 插槽契约(app.js 按 §5.2a 把它们喂给各 mount*):
 *   #map 地图容器 | #topbar{#search} 顶部 | #layer-bar 图层 | #legend 图例 | #model-picker 模式
 *   #attribution 署名 | #timeline 时间轴 | #detail 详情 | #menu 浮层(设置/关于/抽屉) | #toasts 提示
 *   v7 新增:#caption 铭牌标题(ui/stage.js)| #globe-tools 地球工具(ui/compass.js)
 *            #plate 铭牌、#dock 坞(包装层,非插槽)| #compass 罗盘环宿主(#ui 之外,ui/compass.js)
 *
 * v7 罗盘留白:"读在左上,做在底部,方位在球外" —— 四行栅格 "top / stage / dock / foot":
 *   top   = #topbar(右上三件:搜索 · 平面|球形 · 齿轮;min-height = --cz-top-band,UI 挂载前后一致 →
 *           首访放球量到的就是最终占位,LESSONS B1)与 #plate(左上铭牌,跨 top + stage 两行、不撑行高)
 *   stage = 地球;#globe-tools 贴右上(只在需要时出现)
 *   dock  = #dock(1120 宽实底坞,静态高;#timeline 撑满它的时间行 → #timeline 顶 = 坞顶 = 可用区下沿)
 *   foot  = #attribution(坞下署名沟,右对齐,实底药丸)
 * 第 15 轮 A 版本块(文末,成对注释为界;SPEC-R15 §4.2):≥ 1024 坞改两行 92(触屏 100)、封顶 1680 —— 上行 52 = #timeline
 *   ("tl" 仍在第一行 → #timeline 顶 = 坞顶,上面四处测量不变),下行 = 图层 · 日期组 · 署名;#attribution 改 fixed 贴坞下行右端,
 *   foot 行缩成 8 px 底缝(--cz-foot-h 8,模态留口 --cz-modal-foot 48 / 触屏 56)。整块删掉即回上面的 v7 单行坞。
 * 球的可用区 = #topbar 底 → #timeline 顶(app.js firstVisitGlobeZoom 与 map.js availableArea 量同一对矩形),
 * 左右对称无侧栏 → 画布中心即可用区中心。桌面 ≥ 1024 的 #map 零 transform;< 1024 只做"静态让位"
 * translateY(--cz-stage-y),并按盘半径夹紧(--cz-lim-y,compass.js 写),放大时平移量连续收回 0,不露画布直边(LESSONS B3)。
 */

/* ─────────────────────────── 底:地图 ─────────────────────────── */

/* 球外 = "墨池 + 暖纸白日冕"(浅色:"暖纸 + 墨色接触影"):#map 的 CSS 背景(一次栅格化,GL 画布是独立合成层,拖动 / 播放不重绘它)。
   球心恒在 #map 的 50% 50%,所以径向渐变天然与球同心;尺寸用 vmin 写死(LESSONS G:不用 farthest-corner 百分比)。
   内圈 44 vmin 内恒为 --bg → 球缘外紧邻处 = limb 的太空色(深色 SPACE_COLOR / 浅色 LIMB_THEMES.light.space),不出色环。
   第三轮把平坦圈从 36 放到 44 vmin(JUDGE-v7-R3 §2.1 G1,两主题共用):首访盘半径在 1440×900 是 34.6 vmin,但 1920×1080
   约 36.05、768×1024 与 390×844 约 42.5 vmin —— 36 vmin 时这几档的球缘落进渐变带;44 vmin 下各视口余量 ≥ 5.8 px。
   放大到盘半径 > 44 vmin 后球缘落进 --cz-space-mid 一段,与 --bg 差 7–8 级,可接受。顶光走令牌(浅色为 transparent)。刻意不画星星。 */
#map {
  position: fixed;
  inset: 0;
  z-index: var(--z-map);
  background-color: var(--bg);
  background-image:
    radial-gradient(ellipse 60% 48% at 50% 34%, var(--cz-space-glow), transparent 70%),
    radial-gradient(circle at 50% 50%,
      var(--bg) 0, var(--bg) 44vmin, var(--cz-space-mid) 54vmin, var(--cz-space-deep) 68vmin, var(--cz-space-corner) 105vmax);
}

/* 平移 #map(< 1024 的静态让位)时露出的一条是 body:取墨池外圈色,接缝不可见 */
body { background-color: var(--cz-space-corner); }

/* 标注 Canvas(map/label-layer.js 自己插进 #map)压在地图上、UI 之下,不吃事件(§7.5);
   纯平移中 label-layer 只改它的 transform(整幅平移,见该文件头),will-change 让它常驻合成层 —— 挪层不重光栅化 */
#map canvas.aeolus-labels {
  position: absolute;
  inset: 0;
  z-index: var(--z-labels);
  pointer-events: none;
  will-change: transform;
}

/* 投影切换的快照交叉淡化层(map/map.js setGlobe 插进 #map,第 7 轮):切换前一帧的 GL 画面 + 标注画布,盖住新投影的
   首帧编译与源重载;在标注之上、UI 之下,不吃事件。canvas 是替换元素,inset:0 不会把它拉伸到容器,宽高要显式 100 %。
   淡出 280 ms,map.js 在 transitionend(或 320 ms 兜底)后移除 */
.proj-xfade {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: var(--z-xfade);
  pointer-events: none;
  will-change: opacity;
  transition: opacity 280ms;
}

/* 罗盘环宿主:fixed 全屏、不吃指针(只有环带与"北"吃);在标注之上、快照与 #ui 之下 */
#compass {
  position: fixed;
  inset: 0;
  z-index: var(--z-compass);
  pointer-events: none;
}

/* ─────────────────────────── UI 覆盖层 ─────────────────────────── */

#ui {
  position: fixed;
  inset: 0;
  z-index: var(--z-ui);
  height: 100vh;
  height: 100dvh;
  display: grid;
  gap: 0;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) var(--cz-dock-h) var(--cz-foot-h);
  grid-template-areas:
    "top"
    "stage"
    "dock"
    "foot";
  padding:
    env(safe-area-inset-top) calc(var(--cz-edge) + env(safe-area-inset-right))
    env(safe-area-inset-bottom) calc(var(--cz-edge) + env(safe-area-inset-left));
  pointer-events: none;
}

/* 插槽本身透明于指针,插槽里的控件正常交互 */
.slot { pointer-events: none; }
.slot > * { pointer-events: auto; }

/* ── 右上三件:搜索 · 平面|球形 · 齿轮(后两件由 settings-panel 运行时插在末尾,顺序测试钉死)。
   #topbar 不得成为层叠上下文(不加 transform / filter / opacity < 1 / 定位 + z-index):模式下拉、搜索结果是它的后代。 ── */
#topbar {
  grid-area: top;
  display: flex;
  justify-content: flex-end;
  align-items: flex-start;
  gap: 8px;
  min-width: 0;
  min-height: var(--cz-top-band);
  box-sizing: border-box;
  padding: var(--cz-edge) 0 12px;
  pointer-events: none;
}

#search {
  flex: none;
  min-width: 0;
}

/* ── 铭牌(左上):读 —— 图层 · 层次 · 模式 · 时刻 · 色标。跨 top + stage 两行(跨弹性行的项不参与 auto 行的
   内在尺寸,所以不撑高顶带),实底(评审 M1),本身吃指针(铭牌上的缝隙不把点击漏给地图)。 ── */
#plate {
  grid-row: 1 / 3;
  grid-column: 1;
  justify-self: start;
  align-self: start;
  margin-top: var(--cz-edge);
  width: var(--cz-plate-w);
  position: relative;
  z-index: 0;
  pointer-events: auto;
  box-sizing: border-box;
  background: var(--cz-plate);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--cz-shadow-plate);
  padding: 13px 16px 10px 18px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "cap model"
    "legend legend"
    "power power"
    "lmp lmp";
  column-gap: 8px;
}

#caption { grid-area: cap; min-width: 0; }
/* 电力键(fix1,stage.js 挂在铭牌末尾;只在有电力开关开着时出现,隐藏时这一行高 0) */
#plate > .pl-power { grid-area: power; min-width: 0; }
/* 节点电价铭牌行(第 13 轮,stage.js 挂在铭牌末尾;只在门解锁且 LMP 视图打开时出现,隐藏时这一行高 0) */
#plate > .pl-lmp { grid-area: lmp; min-width: 0; }
#model-picker { grid-area: model; align-self: start; min-width: 0; display: flex; justify-content: flex-end; }
#legend { grid-area: legend; min-width: 0; }

/* ── 地球工具:舞台右上竖排(迷你罗盘 + 整球;只在需要时出现,compass.js) ── */
#globe-tools {
  grid-area: stage;
  justify-self: end;
  align-self: start;
  padding-top: 12px;
}

/* ── 坞:做 —— 常用图层 + 全部图层 | 播放 · 速度 · 日条 / 轨道。
   不得带 transform / filter / backdrop-filter / contain:paint / overflow:hidden(全部图层 sheet、时间气泡是它的 fixed / absolute 后代)。
   自身是层叠上下文(z 3):内部 .lm-pop(全部图层 sheet)z −2 < ::before 背板 z −1 < 控件。
   pointer-events:auto —— 坞上控件之间的缝隙不把点击漏给地图。背板实底(评审 M1),静息态永不淡它。 ── */
#dock {
  grid-area: dock;
  justify-self: center;
  width: var(--cz-col);
  height: var(--cz-dock-h);
  position: relative;
  z-index: 3;
  pointer-events: auto;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  grid-template-areas: "bar tl";
  align-items: stretch;
  padding: 0 10px 0 8px;
}

#dock::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: var(--radius-lg);
  background: var(--cz-plate);
  border: 1px solid var(--border);
  box-shadow: var(--cz-shadow-plate);
  pointer-events: none;
}

#layer-bar {
  grid-area: bar;
  min-width: 0;
  min-height: 0;
  display: flex;
  align-items: center;
  overflow: visible;
}

/* 时间段左侧一道 1 × 28 发丝分隔线;#timeline 撑满坞的时间行(它的顶 = 坞顶 = 可用区下沿) */
#timeline {
  grid-area: tl;
  position: relative;
  min-width: 0;
  min-height: 0;
  height: 100%;
  display: flex;
  align-items: center;
  margin-left: 12px;
  padding-left: 12px;
}

#timeline::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  height: 28px;
  margin-top: -14px;
  width: 1px;
  background: var(--cz-hair);
  pointer-events: none;
}

/* ── 署名沟:法定常驻,压在任何 sheet 之上(z 4) ── */
#attribution {
  grid-area: foot;
  justify-self: end;
  align-self: center;
  position: relative;
  z-index: 4;
  max-width: 100%;
}

/* ─────────────────────────── 详情:坞宽卡片 sheet(≥ 600) ───────────────────────────
 * 宽 = v7 坞宽(左右各让 --cz-gutter,封顶 --cz-dock-max 1120),从坞身后升起(z 1 < 坞 3);三档复用 store ui.sheet / body[data-sheet]:peek / half / full。
 * 第 15 轮定稿 A 在 ≥ 1024 只把坞(--cz-col)放宽到封顶 1680,sheet 不跟:视口 ≤ 1168 时两者同宽,更宽时 sheet 比坞窄、居中(DESIGN §10.3)。
 * 高 = 档高 + 坞高 + 8(坞压在 sheet 下端,内容停在坞上方);高度一步到位、不过渡 height(会每帧重排整张表)。
 * #map 不平移(桌面零 transform):选点后由 stage.js 用 easeTo({ offset }) 把点送进 sheet 上方的留白窗口。
 * 内层 .detail 的版式、配色归 detail.css(Build B);这里只管外框几何。 */
@media (min-width: 600px) {
  #detail {
    position: fixed;
    left: var(--cz-gutter);
    right: var(--cz-gutter);
    bottom: calc(var(--cz-foot-h) + env(safe-area-inset-bottom));
    top: auto;
    z-index: 1;
    width: auto;
    max-width: none;
    height: calc(var(--cz-sheet-half) + var(--cz-dock-h) + var(--cz-sheet-lift) + 8px);
    padding: 0;
    overflow: visible;
  }

  #detail:empty { display: none; }

  body[data-sheet="peek"] #detail { height: calc(var(--cz-sheet-peek) + var(--cz-dock-h) + var(--cz-sheet-lift) + 8px); }
  body[data-sheet="full"] #detail { height: calc(var(--cz-sheet-full) + var(--cz-dock-h) + var(--cz-sheet-lift) + 8px); z-index: 2; }

  #detail > .detail {
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    padding-bottom: calc(var(--cz-dock-h) + var(--cz-sheet-lift) + 8px);
    border: 1px solid var(--border);
    border-radius: var(--cz-radius-sheet) var(--cz-radius-sheet) var(--radius-lg) var(--radius-lg);
    background: var(--cz-surface);
    box-shadow: var(--cz-shadow-sheet);
  }

  /* 情境 sheet(全部图层 / 模式下拉)打开时详情让位:同一时刻最多一张 sheet(菜单 > 详情) */
  body[data-menu="layers"] #detail { visibility: hidden; }
}

/* 模式下拉是 #plate 的后代(.mp-pop),#plate z 0 在 #dock(z 3)之下:矮屏下拉伸到坞顶时底部的说明句被盖。
   只在下拉开着时把铭牌抬过坞(第 15 轮决定 32,评-UI F9;data-menu 由 app.js#bindDocumentState 写)。 */
@media (min-width: 600px) {
  body[data-menu="models"] #plate { z-index: 4; }
}

/* 矮屏:半屏 sheet 收矮,留白窗口不至于太窄 */
@media (min-width: 600px) and (max-height: 800px) {
  :root { --cz-sheet-half: clamp(300px, 48dvh, 420px); }
}

@media (min-width: 600px) and (max-height: 700px) {
  :root { --cz-sheet-half: clamp(280px, 44dvh, 400px); }
}

/* ─────────────────────────── 平板 600–1023 ─────────────────────────── */

@media (max-width: 1023px) {
  :root {
    --bar-w: 48px;
    --detail-w: 340px;
    --gap: 10px;
    --cz-edge: 16px;
    --cz-dock-h: 104px;
    --cz-foot-h: 24px;
    --cz-plate-w: 260px;
    /* 静态让位:可用区中心 = (顶带 + 坞顶) / 2,比画布中心高 (坞带 − 顶带) / 2 → 整颗球上移这么多 */
    --cz-stage-y: calc((var(--cz-top-band) - var(--cz-dock-band)) / 2);
  }

  /* 两行坞:上行 = 时间(时间行在上,保证 #timeline 顶 = 坞顶);下行 = 常用图层 + 全部 */
  #dock {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: 56px minmax(0, 1fr);
    grid-template-areas:
      "tl"
      "bar";
    padding: 0 10px;
  }

  #timeline {
    margin-left: 0;
    padding-left: 0;
  }

  /* 两行之间一道发丝横线(代替桌面的竖线) */
  #timeline::before {
    left: 4px;
    right: 4px;
    top: auto;
    bottom: 0;
    width: auto;
    height: 1px;
    margin-top: 0;
  }

  /* 球形时 #map 与罗盘环宿主一起静态让位;按盘半径夹紧(--cz-lim-y = max(0, H/2 − (1.21 r + 4)),compass.js 在 r 取整变化时写),
     放大到盘接近画布边时平移量连续收回 0,不露画布直边。只改 transform,不触发 map.resize()。 */
  body[data-globe="1"] #map,
  body[data-globe="1"] #compass {
    transform: translateY(clamp(calc(-1 * var(--cz-lim-y, 0px)), var(--cz-stage-y), var(--cz-lim-y, 0px)));
    transition: transform var(--cz-dur-3) var(--cz-ease-out);
  }

  /* 平面不平移(LESSONS B2:主线程忙时归零过渡会拖慢,期间露边) */
  body[data-globe="0"] #map,
  body[data-globe="0"] #compass { transform: none; transition: none; }
}

/* ─────────────────────────── 手机 < 600 ───────────────────────────
 * 与桌面同一套四行栅格;铭牌两行(图层 + 模式 / 色标),右上三枚图标钮,坞两行(上行时间、下行常用图层)。
 * 详情 / 设置 / 关于由 ui/mobile.js 搬进 .a-sheet 抽屉;细节皮肤归 mobile.css(Build B)。 */
@media (max-width: 599px) {
  :root {
    --timeline-h: var(--timeline-h-compact);
    --gap: 8px;
    --cz-edge: 12px;
    --cz-ctl-h: 44px;
    --cz-top-band: 76px;
    --cz-dock-h: 108px;
    --cz-foot-h: 22px;
    /* 右上 = 搜索 44 + 投影 84 + 齿轮 44 + 两道 8 的缝;铭牌占其余(390 宽 → 170) */
    --cz-plate-w: calc(100vw - 2 * var(--cz-edge) - 2 * 44px - 2 * 8px - 84px - 8px);
  }

  /* 署名沟最少 22 px、按内容长高(LESSONS C3:开电力层后署名折成两行,固定行高会把第二行裁出屏幕) */
  #ui {
    grid-template-rows: auto minmax(0, 1fr) var(--cz-dock-h) minmax(var(--cz-foot-h), auto);
  }

  #plate {
    margin-top: var(--cz-edge);
    padding: 7px 10px 6px 12px;
    border-radius: var(--radius);
    min-width: 150px;
  }

  #topbar { position: relative; }

  #dock {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: 58px minmax(0, 1fr);
    grid-template-areas:
      "tl"
      "bar";
    padding: 0 8px;
  }

  #timeline {
    margin-left: 0;
    padding-left: 0;
  }

  #timeline::before {
    left: 4px;
    right: 4px;
    top: auto;
    bottom: 0;
    width: auto;
    height: 1px;
    margin-top: 0;
  }

  #attribution {
    align-self: end;
    padding: 0 2px 1px;
  }

  /* 详情面板变成底部抽屉:脱离栅格,高度由 ui/mobile.js 按 peek/half/full 控制 */
  #detail {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    z-index: var(--z-panel);
    width: auto;
    max-width: none;
    height: auto;
    max-height: 100dvh;
    padding: 0;
    padding-bottom: env(safe-area-inset-bottom);
  }

  #detail:empty { display: none; }

  /* 抽屉展开时把图例/署名让出去,避免叠在抽屉上。
     LESSONS C1(基线遗留,第一天就修):三条都加 [data-sheet-open="1"] 守卫 —— ui.sheet 在关掉详情后不复位,
     不带守卫时关闭 full / half 抽屉后署名与图例会永久 visibility:hidden。 */
  body[data-sheet-open="1"][data-sheet="half"] #legend,
  body[data-sheet-open="1"][data-sheet="full"] #legend,
  body[data-sheet-open="1"][data-sheet="full"] #attribution { visibility: hidden; }

  /* 抽屉在 peek 档(96 px)时把坞抬到抽屉之上:抽屉是 fixed bottom:0,不抬就会盖住时间滑块 ——
     手机上"开着城市详情同时拖时间"是主用例(§11.4 紧凑时间轴与抽屉共存)。half/full 档抽屉本来就该覆盖坞。
     做法是给整个 #ui 栅格加一段等于 peek 高的下内边距(border-box),1fr 那一行(舞台)缩短,坞 / 署名整体上移。 */
  body[data-detail="open"][data-sheet="peek"] #ui {
    padding-bottom: calc(env(safe-area-inset-bottom) + var(--sheet-peek));
  }

  /* 静态让位同平板;详情抽屉 half 档(fix1 起全部图层抽屉也一样)时整颗球升到抽屉上方:让位换成 (50dvh − 顶带) / 2(同一夹紧规则) */
  :root { --cz-stage-y: calc((var(--cz-top-band) - var(--cz-dock-band)) / 2); }

  /* 手机首屏 #map 上移约 27 px,底边在坞 / 署名两侧 12 px 露出 body。那里 #map 的径向渐变落在外圈与四角之间
     (390×844:t ≈ 0.25–0.35),body 若取四角色会差 4–6 级(浅色;深色 2–3 级)—— 取外圈与四角各半,两主题都 ≤ 3 级
     (第三轮浅色 C 段;≥ 600 仍是上面的四角色,768×1024 A 段已验 0 级)。 */
  body { background-color: color-mix(in srgb, var(--cz-space-deep) 50%, var(--cz-space-corner)); }

  body[data-globe="1"][data-sheet-open="1"][data-sheet="half"],
  body[data-globe="1"][data-menu="layers"] {
    --cz-stage-y: calc(-1 * (50dvh - var(--cz-top-band)) / 2);
  }

  body[data-globe="1"] #map,
  body[data-globe="1"] #compass {
    transform: translateY(clamp(calc(-1 * var(--cz-lim-y, 0px)), var(--cz-stage-y), var(--cz-lim-y, 0px)));
    transition: transform var(--cz-dur-3) var(--cz-ease-out);
  }

  body[data-globe="0"] #map,
  body[data-globe="0"] #compass { transform: none; transition: none; }
}

/* ─────────────────────────── 浮层:设置 / 关于 / 抽屉 ─────────────────────────── */

#menu {
  position: fixed;
  inset: 0;
  z-index: var(--z-menu);
  pointer-events: none;
  padding:
    env(safe-area-inset-top) env(safe-area-inset-right)
    env(safe-area-inset-bottom) env(safe-area-inset-left);
}

#menu:empty { display: none; }

/* ─────────────────────────── 提示条:"通知从上垂下" ───────────────────────────
 * v7:≥ 1280 顶部居中、与右上簇同一水平线(避开铭牌与右上簇);< 1280 落在顶带下方。
 * 与所有 sheet(从下升起)永不冲突。皮肤在 stage.css(.toast 普通选择器;toast.js 的 :where() 兜底不动)。 */
#toasts {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  top: calc(var(--cz-top-band) + 8px + env(safe-area-inset-top));
  bottom: auto;
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-sm);
  width: max-content;
  max-width: min(520px, calc(100vw - 2 * var(--gap)));
  pointer-events: none;
}

@media (min-width: 1280px) {
  #toasts {
    top: calc(var(--cz-edge) + env(safe-area-inset-top));
    max-width: min(440px, calc(100vw - 2 * 456px));
  }

  /* fix1(QA m2 / 设计评审 m6):顶带里一次只露最新一条 —— 第二条往下叠会压住环顶的方位读数与"北"(也是回正入口)。
     旧的那条没有被移除:最新一条消失后它按自己的计时继续显示(或已到期) */
  #toasts > .toast:not(:last-child) { display: none; }
}

/* ─────────────────────────── 触控设备:控件放大到 44 px ─────────────────────────── */

@media (pointer: coarse) {
  :root { --cz-ctl-h: 44px; }

  #layer-bar .a-btn,
  #topbar .a-btn,
  #timeline .a-btn {
    min-width: var(--tap);
    min-height: var(--tap);
  }
}

/* ─────────────────────────── 极矮视口(横屏手机) ─────────────────────────── */

@media (max-height: 480px) {
  #legend { display: none; }
}

/* ═══ 第 15 轮 A 版本块 开始(SPEC-R15 §4.2,决定 35 / 36 / 37;layout.css 段)═══
 * 2026-11-03 产品方选定 A 为定稿;块保留成对边界以便一次回滚(回滚时 test/shell-r15.test.js 的 #dock 首行 "tl" 红线一并删)。
 * 只作用于 ≥ 1024:两行坞 · 坞封顶 1680 · 署名进坞下行右端。正文 = SPEC §4.2 原文 + 偏离 A-4(触屏那条 @media 多一行 #attribution,
 * 见 notes/r15-fix-a.md);改动先改 SPEC。test/timeline-version-a.test.js 逐字钉着这段正文。
 * 回滚(§7 路径 3):从本行删到本段末尾的结束注释(含),即回 v7 单行坞画法;test/timeline-version-a.test.js 同时删;
 * base.css 的 --cz-dock-h / --cz-foot-h / --cz-modal-foot / --cz-dock-band 四行行尾注释与本文件头注释里提到 A 版本块的三行一并还原(只是注释,不影响画法)。 */
/* 第 15 轮 A:桌面两行坞 —— 时间独占上行(#timeline 顶 = 坞顶,四处测量不变),下行 = 图层 · 日期 · 署名;署名从 28 px 沟搬进坞,沟缩成 8 px 底缝 */
@media (min-width: 1024px) {
  :root { --cz-dock-h: 92px; --cz-foot-h: 8px; --cz-modal-foot: 48px; --cz-col: min(100vw - 2 * var(--cz-edge), 1680px); --timeline-h: 100px; }
  #dock { grid-template-columns: minmax(0, 1fr); grid-template-rows: 52px minmax(0, 1fr); grid-template-areas: "tl" "bar"; padding: 0 10px; }
  #timeline { margin-left: 0; padding-left: 0; }
  #timeline::before { left: 4px; right: 4px; top: auto; bottom: 0; width: auto; height: 1px; margin-top: 0; }
  #attribution { position: fixed; right: calc((100vw - var(--cz-col)) / 2 + 10px); bottom: calc(var(--cz-foot-h) + env(safe-area-inset-bottom) + 8px); z-index: 4; }
  #attribution-link { background: transparent; box-shadow: none; padding: 3px 4px; }
}
@media (min-width: 1024px) and (pointer: coarse) {
  :root { --cz-dock-h: 100px; --cz-modal-foot: 56px; --timeline-h: 108px; }
  /* 偏离 A-4:触屏下行 48(非 40),署名要与图层钮 / 日期组同心,底距 12(= (48 − 24) / 2);SPEC §4.2 原文沿用 ≥ 1024 细指针的 8 */
  #attribution { bottom: calc(var(--cz-foot-h) + env(safe-area-inset-bottom) + 12px); }
}
/* ═══ 第 15 轮 A 版本块 结束 ═══ */
