/*
 * planet-gardener 主题。
 *
 * 两件事，分得很清楚：
 *
 * ① **令牌覆盖**（`--gs-*`）——换皮只动这一段，绝不覆盖 `.gs-*` 选择器。
 *    覆盖组件的选择器会把 44×44 触控下限、安全区、焦点环一起改坏，
 *    而这三样都不会在手机上被肉眼发现。
 * ② **本作自己的结构类**（`.pg-*`）——分区容器、星球画布、HUD、种子槽、
 *    焦土条这些组件库里没有的形态。它们是新增，不是覆盖。
 *
 * 版式只有一套：手机竖屏。视口比手机宽时由共用库末尾的「手机画布锁定」
 * 把 `#app` 收成 540×960 居中，桌面玩到的就是手机上验收过的那一屏。
 * 所以本文件里**没有任何不带 `max-height` 的 `@media (min-width: …)`**。
 * 手机横屏那一档统一写成 `(orientation: landscape) and (max-height: 560px)`，
 * 560 这个数的唯一真值是 `shared/phone-canvas.json`。
 *
 * 配色取自 S2 的界面稿（SCREEN_REVIEW.json 逐屏判词）：深紫蓝星云底、
 * 青蓝描边的深蓝发光面板、亮绿渐变主按钮、金色大数字、赤陶橙的星球盘。
 */

:root {
  /* ---- 令牌覆盖 ---- */
  --gs-ink: #f4f7ff;
  --gs-ink-soft: rgba(226, 233, 255, 0.76);
  --gs-ink-dim: rgba(198, 208, 240, 0.5);
  --gs-ink-on-light: #0d1030;

  --gs-surface: rgba(19, 27, 62, 0.86);
  --gs-surface-raised: rgba(30, 42, 88, 0.94);
  --gs-surface-sunken: rgba(9, 12, 32, 0.66);
  --gs-hairline: rgba(120, 214, 255, 0.24);

  --gs-accent: #45e08a;
  --gs-accent-2: #33d6d0;
  --gs-gold: #ffcf5c;
  --gs-danger: #ff6a52;

  --gs-glow-accent: 0 0 0 1px rgba(69, 224, 138, 0.55), 0 0 26px rgba(69, 224, 138, 0.32);
  --gs-glow-gold: 0 0 26px rgba(255, 207, 92, 0.5);
  --gs-shadow-card: 0 20px 44px rgba(4, 6, 22, 0.55);
  --gs-shadow-button: 0 6px 0 rgba(3, 6, 20, 0.42), 0 14px 26px rgba(4, 6, 22, 0.46);
  --gs-shadow-press: 0 2px 0 rgba(3, 6, 20, 0.42), 0 6px 12px rgba(4, 6, 22, 0.46);

  --gs-cta: linear-gradient(135deg, #45e08a, #7ef0a4 55%, #33d6d0);
  --gs-bg-focus: 50% 42%;

  /* 底部安全区**至少留 16px**。没有刘海的机器上 `env(safe-area-inset-bottom)` 是 0，
     于是分区一直贴到屏幕最下沿——手机横过来时 `side` 分区底部那两枚圆按钮的下沿
     离屏幕边只剩 4px，正是平台基线「底部按钮不要贴到屏幕最下沿」要拦的那种。
     只覆盖变量，不覆盖 `.gs-*` 选择器。 */
  --gs-safe-bottom: max(env(safe-area-inset-bottom, 0px), 16px);

  /* ---- 本作自己的绘图令牌（画布与 DOM 共用一份来源）----
     `render.mjs` 通过 getComputedStyle 读它们，所以换涂装只改这一段，
     画布和 HUD 不会各说各话。三个物种的**形状**永不改变（§15）。 */
  --pg-void: #0a0d24;
  --pg-plate: #b4542c;
  --pg-plate-dark: #6d2f1a;
  --pg-plate-rim: #ffa04a;
  --pg-core: #14183a;
  --pg-groove: rgba(9, 12, 32, 0.72);
  --pg-empty: rgba(255, 220, 190, 0.16);
  --pg-scorch: #1b1414;
  --pg-scorch-crack: #5d2a1c;
  --pg-moss: #9cd94a;
  --pg-fern: #46cfe0;
  --pg-hopper: #ec5fc0;
  --pg-soil: #ffb545;
  --pg-water: #4aa8ff;
  --pg-air: #63f2d8;
  --pg-bloom: #ffcf5c;
  --pg-feed: #45e08a;
  --pg-wither: #ff8a3d;
  --pg-pip-lit: #ffd79a;
  --pg-pip-dim: rgba(255, 215, 154, 0.22);
}

/* 涂装只换配色与粒子色相（§5.2）。**它不改任何判定**——
   这里没有一条规则碰得到生命流失、窗口、成环或计分。 */
:root[data-skin='neonNight'] {
  --pg-sprite-filter: hue-rotate(40deg) saturate(1.3);
  --pg-plate: #7a2e63;
  --pg-plate-dark: #40163a;
  --pg-plate-rim: #ff5fd2;
  --pg-moss: #b6ff3d;
  --pg-fern: #35e8ff;
  --pg-hopper: #ff4fa8;
  --gs-accent: #35e8ff;
  --gs-accent-2: #ff5fd2;
  --gs-bg-focus: 50% 46%;
}

:root[data-skin='aurora'] {
  --pg-sprite-filter: hue-rotate(150deg) saturate(0.7);
  --pg-plate: #2b5f6b;
  --pg-plate-dark: #133440;
  --pg-plate-rim: #7dfbd0;
  --pg-moss: #a8f07a;
  --pg-fern: #7fd0ff;
  --pg-hopper: #c79bff;
  --gs-accent: #7dfbd0;
  --gs-accent-2: #8ea9ff;
}

:root[data-skin='terracotta'] {
  --pg-sprite-filter: saturate(0.5) sepia(0.2);
  --pg-plate: #a9673c;
  --pg-plate-dark: #5f341d;
  --pg-plate-rim: #ffd2a0;
  --pg-moss: #cbd96a;
  --pg-fern: #7fc4b0;
  --pg-hopper: #e08f7a;
  --gs-accent: #e8b06a;
  --gs-accent-2: #cbd96a;
}

/* ============================ 根容器 ============================ */

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: #05060f;
  color: var(--gs-ink);
  font-family: 'Trebuchet MS', 'Hiragino Sans', 'Noto Sans', system-ui, -apple-system, sans-serif;
  overscroll-behavior: none;
  -webkit-text-size-adjust: 100%;
}

#app {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: radial-gradient(120% 90% at 50% 18%, #241b52 0%, #120e30 46%, #05060f 100%);
}

/* 舞台：**方向判定量的就是它**（`ui.mjs::readOrientation`）。
   桌面上视口是横的、画布是竖的，读视口会把横屏分区套进竖画布。 */
.pg-stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  touch-action: none;
}

/* ============================ 分区 ============================ */

/*
 * 分区是 S2 冻结的几何（`art/SCREEN_SPEC.json` 的 `zones`，两套朝向各一份），
 * 由 `tools/sync_config.py` 机械同步进 `game.config.json.zones`，
 * 再由 `ui.mjs::mountZones()` 逐个写成 inline 的 left/top/width/height。
 * 用绝对定位而不是 flex 栅格，是因为闸门与走查判的是
 * 「每个可交互元素完整落在恰好一个分区内」——绝对定位是唯一能逐像素对上的做法。
 */
.pg-screen {
  position: absolute;
  inset: 0;
  padding:
    var(--gs-safe-top)
    var(--gs-safe-right)
    var(--gs-safe-bottom)
    var(--gs-safe-left);
  box-sizing: border-box;
}

.pg-screen[hidden] {
  display: none;
}

.pg-zonebox {
  position: absolute;
  inset: var(--gs-safe-top) var(--gs-safe-right) var(--gs-safe-bottom) var(--gs-safe-left);
}

.pg-zone {
  position: absolute;
  display: flex;
  flex-direction: column;
  gap: var(--gs-space-3);
  box-sizing: border-box;
  min-height: 0;
}

/* 内容比分区高时在分区**内部**滚，绝不溢出去压住隔壁分区。 */
.pg-zone--scroll {
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}

.pg-zone--pad {
  padding: 0 var(--gs-space-4);
}

.pg-zone--center {
  align-items: center;
  justify-content: center;
  text-align: center;
}

.pg-zone--end {
  justify-content: flex-end;
}

/* ============================ 排版 ============================ */

.pg-display-xl {
  margin: 0;
  font-size: clamp(30px, 8.6vw, 42px);
  font-weight: 800;
  letter-spacing: 0.012em;
  line-height: 1.08;
  text-shadow: 0 2px 18px rgba(69, 224, 138, 0.28);
}

.pg-display-md {
  margin: 0;
  font-size: clamp(22px, 6.2vw, 30px);
  font-weight: 800;
  line-height: 1.12;
}

.pg-display-sm {
  margin: 0;
  font-size: var(--gs-text-lg);
  font-weight: 700;
  color: var(--gs-ink);
}

.pg-body {
  margin: 0;
  font-size: var(--gs-text-md);
  line-height: 1.45;
  color: var(--gs-ink-soft);
}

.pg-body--sm {
  font-size: var(--gs-text-sm);
}

.pg-caption {
  margin: 0;
  font-size: var(--gs-text-xs);
  color: var(--gs-ink-dim);
  letter-spacing: 0.04em;
}

.pg-num-lg {
  font-variant-numeric: tabular-nums;
  font-size: clamp(28px, 7.4vw, 38px);
  font-weight: 800;
  line-height: 1;
}

.pg-num-sm {
  font-variant-numeric: tabular-nums;
  font-size: var(--gs-text-sm);
  font-weight: 700;
}

.pg-gold {
  color: var(--gs-gold);
  text-shadow: var(--gs-glow-gold);
}

.pg-cool {
  color: #cfe0ff;
}

.pg-up {
  color: var(--gs-accent);
}

.pg-down {
  color: var(--gs-danger);
}

.pg-emblem {
  display: block;
  width: clamp(56px, 18vw, 96px);
  height: auto;
  filter: drop-shadow(0 0 18px rgba(255, 207, 92, 0.35));
}

/* ============================ 面板与卡片 ============================ */

/* 设计稿里每一屏的主体容器：深蓝半透明底 + 青蓝描边 + 外发光。 */
.pg-panel {
  position: relative;
  border-radius: var(--gs-radius-lg);
  background:
    linear-gradient(160deg, rgba(38, 52, 108, 0.9), rgba(15, 21, 52, 0.94));
  border: 1px solid var(--gs-hairline);
  box-shadow: var(--gs-shadow-card), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  padding: var(--gs-space-4);
  box-sizing: border-box;
}

.pg-card {
  position: relative;
  display: flex;
  gap: var(--gs-space-3);
  align-items: stretch;
  width: 100%;
  min-height: var(--gs-tap-min);
  padding: var(--gs-space-3);
  border-radius: var(--gs-radius-md);
  border: 1px solid var(--gs-hairline);
  background: linear-gradient(150deg, rgba(34, 47, 100, 0.82), rgba(14, 20, 50, 0.9));
  color: var(--gs-ink);
  text-align: left;
  box-sizing: border-box;
  cursor: pointer;
  transition: transform var(--gs-fast) var(--gs-ease-out), box-shadow var(--gs-fast);
}

.pg-card:active {
  transform: translateY(2px);
}

/* 选中态：亮绿描边 + 左缘竖条（界面稿上的做法）。 */
.pg-card[aria-pressed='true'],
.pg-card[aria-checked='true'] {
  border-color: var(--gs-accent);
  box-shadow: var(--gs-glow-accent);
}

.pg-card[aria-pressed='true']::before,
.pg-card[aria-checked='true']::before {
  content: '';
  position: absolute;
  left: 0;
  top: 14%;
  bottom: 14%;
  width: 4px;
  border-radius: 999px;
  background: var(--gs-accent);
}

/* 锁着的入口**照样显示、照样能聚焦**（否则新玩家不知道游戏里有这回事）。
   用 aria-disabled 而不是 disabled：disabled 会让它从 Tab 序里消失，
   读屏也不再念解锁条件。走查认这个标准信号，不会报成假控件。 */
.pg-card[aria-disabled='true'] {
  filter: saturate(0.35) brightness(0.72);
}

.pg-card__art {
  flex: 0 0 30%;
  max-width: 118px;
  border-radius: var(--gs-radius-sm);
  overflow: hidden;
  background: rgba(6, 9, 26, 0.55);
  display: grid;
  place-items: center;
}

.pg-card__art > * {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.pg-card__art--badged {
  position: relative;
}

/* 模式图标叠在缩略局面的右下角：局面说「这个模式长什么样」，
   图标说「它叫什么类型」，两条通道各说一半。 */
.pg-card__badge {
  position: absolute;
  right: 4px;
  bottom: 4px;
  width: 26px !important;
  height: 26px !important;
  padding: 4px;
  box-sizing: border-box;
  border-radius: 50%;
  background: rgba(6, 9, 26, 0.82);
  border: 1px solid var(--gs-hairline);
  filter: var(--gs-icon-tint-ink);
}

.pg-card__text {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.pg-card__title {
  margin: 0;
  font-size: var(--gs-text-lg);
  font-weight: 800;
}

.pg-row {
  display: flex;
  align-items: center;
  gap: var(--gs-space-2);
  flex-wrap: wrap;
}

.pg-row--between {
  justify-content: space-between;
  flex-wrap: nowrap;
}

.pg-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--gs-radius-pill);
  background: rgba(8, 12, 34, 0.7);
  border: 1px solid var(--gs-hairline);
  font-size: var(--gs-text-xs);
  color: var(--gs-ink-soft);
  white-space: nowrap;
}

/* 胶囊有两种用法：`<span>` 是只读标签（成绩、等级、解锁条件），
   `<button>` 是真的能按的入口（模式切换、选择线导航）。
   **能按的那一种必须满足 44×44 的触控下限**——只读的那一种不需要，
   把它们一起撑大只会把 header 顶开。判据挂在标签名上而不是修饰类上，
   因为「它能不能按」是由标签决定的，不由命名决定。 */
button.pg-chip {
  min-height: var(--gs-tap-min);
  padding: 10px 14px;
  cursor: pointer;
}

button.pg-chip:active {
  transform: translateY(2px);
}

.pg-chip--locked {
  border-style: dashed;
  color: var(--gs-ink-dim);
}

.pg-chip--gold {
  border-color: rgba(255, 207, 92, 0.5);
  color: var(--gs-gold);
}

.pg-chip__icon {
  width: 14px;
  height: 14px;
  filter: var(--gs-icon-tint-ink);
  opacity: 0.85;
}

/* 三段难度指示（§5.2：三颗星球是三档难度，不是三种风格）。 */
.pg-meter3 {
  display: inline-flex;
  gap: 3px;
  align-items: flex-end;
}

.pg-meter3 i {
  display: block;
  width: 7px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.16);
}

.pg-meter3 i:nth-child(1) { height: 8px; }
.pg-meter3 i:nth-child(2) { height: 12px; }
.pg-meter3 i:nth-child(3) { height: 16px; }
.pg-meter3 i[data-on='1'] { background: var(--gs-gold); box-shadow: 0 0 8px rgba(255, 207, 92, 0.6); }

/* ============================ 游玩：星球画布 ============================ */

.pg-board {
  position: relative;
  width: 100%;
  height: 100%;
  touch-action: none;
  /* 画布本来就把圆盘裁在自己的矩形里（`inset: 0`）；热区是绝对定位的兄弟元素，
     不裁的话它那点溢出会被走查记成「play 分区的内容比它高 4px」。
     裁掉的那一条**本来就没画出来**，所以命中区与看得见的圆盘仍然一致。 */
  overflow: hidden;
  /* 后果画在画布上的控件：DOM 指纹看不见它，所以必须自己声明
     （容器上的 data-canvas-driven="true" 由 ui.mjs 写）。 */
}

.pg-board canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* 星球热区：圆盘的外接正方形（SCREEN_SPEC `planet-surface.visual_area`）。
   走查、验收剧本与指针捕获都认这一个元素；它不画任何东西，圆盘仍然由画布画。

   **几何写成百分比，不由 JS 写像素。** `render.mjs::boardGeometry` 的
   竖屏是 `cx = 50%w、cy = 54.4%h、r = min(44%w, 47%h)`，横屏是
   `cx = 50%w、cy = 50%h、r = min(38.3%w, 43%h)`；下面这几行是它逐字的 CSS 副本
   （`width` + `max-height` + `aspect-ratio: 1/1` 就是那个 `min()`），
   由 `tests/units.test.mjs` 的「热区 CSS 与 boardGeometry 同一份几何」逐值核对。
   写百分比是因为**画布尺寸变了浏览器自己会跟过去**：旋转那一瞬间 JS 若抢着写一次
   像素，写进去的就是过渡态的尺寸，而且要等下一次重排才纠正——真机上是「刚转过来那一下
   按不到星球」，闸门里是热区与圆盘对不上。百分比没有这个窗口。 */
.pg-planet-hit {
  position: absolute;
  left: 50%;
  top: 54.4%;
  width: 88%;
  max-height: 94%;
  aspect-ratio: 1 / 1;
  transform: translate(-50%, -50%);
  touch-action: none;
  background: transparent;
}

/* 横屏那一档：朝向由 `ui.mjs` 按**画布**判定后写在容器上，不看视口。 */
.pg-board[data-orientation='landscape'] .pg-planet-hit {
  top: 50%;
  width: 76.6%;
  max-height: 86%;
}

/* ============================ HUD ============================ */

.pg-hud {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas:
    'seed score btns'
    'clock clock clock';
  align-items: center;
  gap: 4px 8px;
  padding: 4px 8px;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}

.pg-hud__seeds { grid-area: seed; display: flex; align-items: center; gap: var(--gs-space-2); }
.pg-hud__score { grid-area: score; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.pg-hud__btns  { grid-area: btns; display: flex; flex-direction: column; gap: var(--gs-tap-gap); }
.pg-hud__clock { grid-area: clock; display: flex; align-items: center; gap: var(--gs-space-2); }
.pg-hud__clock .pg-caption { font-size: 10px; line-height: 1; }
.pg-hud-control { width: 64px; height: 64px; flex: 0 0 64px; }
.pg-hud__score .pg-row { flex-wrap: wrap; }
.pg-scorch { flex-wrap: wrap; }

/* 种子槽 + 倒计时环。环是 DOM 的 conic-gradient——它要跟着种子槽走
   并接受读屏描述（SCREEN_SPEC `canvas_vs_dom_boundary`）。 */
.pg-seedslot {
  position: relative;
  width: 68px;
  height: 68px;
  flex: 0 0 auto;
  border-radius: 50%;
  background:
    conic-gradient(from -90deg, var(--pg-ring-color, var(--gs-accent-2)) calc(var(--pg-ring, 1) * 360deg), rgba(255, 255, 255, 0.1) 0)
    ;
  display: grid;
  place-items: center;
  filter: drop-shadow(0 0 10px rgba(51, 214, 208, 0.35));
}

.pg-seedslot[data-urgent='1'] {
  --pg-ring-color: var(--gs-danger);
  animation: pg-pulse 0.5s ease-in-out infinite;
}

.pg-seedslot__well {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 35%, rgba(48, 64, 128, 0.95), rgba(9, 13, 34, 0.98));
  display: grid;
  place-items: center;
  position: relative;
}

.pg-seedslot__pod {
  width: 34px;
  height: 34px;
  object-fit: contain;
  display: block;
}

/* 倒计时读数**画在种子槽井内的下缘**，不是挂在槽外。
   挂在外面会被圆形槽的边界裁掉半个字（实测 430×932 上「4.8」只剩上半截）。 */
.pg-seedslot__time {
  position: absolute;
  bottom: 3px;
  left: 50%;
  transform: translateX(-50%);
  padding: 0 4px;
  border-radius: 999px;
  background: rgba(6, 9, 26, 0.72);
  font-size: 11px;
  line-height: 1.25;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--gs-ink);
}

.pg-seedslot--flash {
  animation: pg-flash 0.28s ease-out 1;
}

.pg-preview {
  display: flex;
  gap: 6px;
}

.pg-preview__card {
  width: 34px;
  height: 40px;
  border-radius: 8px;
  background: rgba(9, 13, 34, 0.72);
  border: 1px solid var(--gs-hairline);
  display: grid;
  place-items: center;
}

.pg-preview__card img {
  width: 24px;
  height: 24px;
  object-fit: contain;
}

/* 焦土 5 格条。**可数的格**，不是渐变条（§15）。 */
.pg-scorch {
  display: flex;
  align-items: center;
  gap: 5px;
}

.pg-scorch__cells {
  display: flex;
  gap: 3px;
}

.pg-scorch__cell {
  width: 15px;
  height: 9px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.16);
  box-sizing: border-box;
}

.pg-scorch__cell[data-lit='1'] {
  background: var(--gs-danger);
  border-color: var(--gs-danger);
  box-shadow: 0 0 8px rgba(255, 106, 82, 0.75);
}

.pg-scorch--danger .pg-scorch__cells {
  animation: pg-pulse 0.6s ease-in-out 1;
}

/* 环数：可数的点，不是一个数字（横屏稿把它画成圆章，那是 rev-1 的偏差，
   SCREEN_SPEC 的 `pip-row-4` 才是契约）。 */
.pg-pips {
  display: flex;
  gap: 4px;
  align-items: center;
}

.pg-pips i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
}

.pg-pips i[data-on='1'] {
  background: var(--gs-gold);
  box-shadow: 0 0 8px rgba(255, 207, 92, 0.7);
}

/* 局内计时细线。长夜模式没有上限，这条线改成「已过的时间」不断向右走。 */
.pg-hairline {
  position: relative;
  flex: 1 1 auto;
  height: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  overflow: hidden;
}

.pg-hairline > i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: linear-gradient(90deg, var(--gs-accent-2), var(--gs-accent));
  border-radius: 999px;
}

.pg-hairline[data-late='1'] {
  height: 6px;
}

/* 局内提示条：**钉在 hint 分区里，不是浮层**。不拦输入、不圈焦点、不进弹窗栈。 */
.pg-hint {
  display: flex;
  align-items: center;
  gap: var(--gs-space-2);
  width: 100%;
  padding: 8px var(--gs-space-3);
  border-radius: var(--gs-radius-pill);
  background: rgba(12, 18, 46, 0.86);
  border: 1px solid var(--gs-hairline);
  box-sizing: border-box;
  pointer-events: none;
}

.pg-hint__dot {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--gs-accent);
  color: #06210f;
  font-weight: 900;
  font-size: 13px;
}

.pg-hint__text {
  margin: 0;
  font-size: var(--gs-text-sm);
  line-height: 1.3;
  color: var(--gs-ink);
}

/* 引导箭头：指向当前高亮扇区的方向，逐步换指向。 */
.pg-hint__arrow {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  filter: var(--gs-icon-tint-accent);
  transform: rotate(var(--pg-arrow, 0deg));
  transition: transform var(--gs-normal) var(--gs-ease-out);
}

.pg-steps {
  display: flex;
  gap: 5px;
  flex: 0 0 auto;
}

/* `display: flex` 会盖掉浏览器给 `[hidden]` 的 `display: none`，于是
   `node.hidden = true` 变成一句没人听的话。凡是本文件显式给过 display 的元素，
   都要把 `[hidden]` 补回来——长夜那一档「不画计时线」靠的就是这一条。 */
.pg-steps[hidden],
.pg-hud__clock[hidden],
.pg-hint__arrow[hidden],
/* 这一朝向没有的分区（横屏才有的 `side`）必须真的收起来。留着一块看不见但仍占位的
   盒子，旋转回竖屏之后它会顶着上一套朝向的矩形压在 `play` 上——分区互相压住。 */
.pg-zone[hidden] {
  display: none;
}

.pg-steps i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.24);
}

.pg-steps i[data-on='1'] {
  background: var(--gs-accent);
  width: 16px;
  border-radius: 999px;
}

@keyframes pg-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.06); }
}

@keyframes pg-flash {
  0% { filter: brightness(2.4); }
  100% { filter: brightness(1); }
}

/* ============================ 浮层 ============================ */

.pg-overlay {
  position: absolute;
  inset: 0;
  z-index: 40;
}

.pg-overlay[hidden] {
  display: none;
}

/* 收起的浮层，**里面那块面板自己也要是 display:none**。
   `display: none` 不会写进后代的计算值：只藏外壳的话，
   任何按 `[data-screen]` 逐个读计算样式的检查（走查、验收剧本的 openModals）
   都会认为暂停浮层一直开着——「关掉之后它还开着」正是这么来的。 */
.pg-overlay[hidden] .pg-dialog {
  display: none;
}

/* 遮罩：整屏压暗。**它是模态的视觉定义**，配合 trapFocus 的
   role=dialog / aria-modal 一起说明「背后不可达」。 */
.pg-overlay__scrim {
  position: absolute;
  inset: 0;
  background: rgba(4, 6, 20, 0.62);
  backdrop-filter: blur(4px) saturate(0.6);
}

.pg-overlay__panel {
  position: absolute;
  inset: 0;
}

.pg-dialog {
  position: absolute;
  inset: var(--gs-safe-top) var(--gs-safe-right) var(--gs-safe-bottom) var(--gs-safe-left);
  border-radius: var(--gs-radius-lg);
  overflow: hidden;
}

.pg-dialog::before {
  content: '';
  position: absolute;
  inset: 4%;
  border-radius: var(--gs-radius-lg);
  background: linear-gradient(165deg, rgba(30, 42, 92, 0.90), rgba(11, 16, 42, 0.95));
  border: 1px solid var(--gs-hairline);
  box-shadow: var(--gs-shadow-card), 0 0 34px rgba(51, 214, 208, 0.18);
  pointer-events: none;
}

/* 关闭键**钉在面板右上角，同时把标题的右侧留白顶出来**。
   只做绝对定位会压住标题（实测帮助页的 X 正好盖在「How to play」上）。 */
.pg-close {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
}

.pg-dialog .pg-zone[data-zone='header'] {
  padding-right: 64px;
  padding-top: var(--gs-space-2);
}

/* 结算的共生曲线：canvas 画线，标题与峰值说明是 DOM。 */
.pg-curve {
  width: 100%;
  height: 120px;
  display: block;
  border-radius: var(--gs-radius-sm);
  background: rgba(6, 9, 26, 0.55);
}

.pg-statcard {
  display: flex;
  gap: var(--gs-space-3);
  align-items: center;
  padding: var(--gs-space-3);
  border-radius: var(--gs-radius-md);
  background: rgba(8, 12, 34, 0.62);
  border: 1px solid var(--gs-hairline);
}

.pg-statcard__thumb {
  flex: 0 0 auto;
  width: 56px;
  height: 56px;
  border-radius: var(--gs-radius-sm);
  background: rgba(4, 6, 20, 0.7);
  display: block;
}

.pg-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gs-space-3);
  width: 100%;
  min-height: var(--gs-tap-min);
  padding: 10px var(--gs-space-3);
  border-radius: var(--gs-radius-md);
  background: rgba(8, 12, 34, 0.62);
  border: 1px solid var(--gs-hairline);
  color: var(--gs-ink);
  box-sizing: border-box;
  cursor: pointer;
}

.pg-toggle__label {
  display: flex;
  align-items: center;
  gap: var(--gs-space-2);
  font-size: var(--gs-text-md);
}

.pg-toggle__label img {
  width: 20px;
  height: 20px;
  filter: var(--gs-icon-tint-ink);
}

.pg-toggle__state {
  font-size: var(--gs-text-xs);
  color: var(--gs-ink-dim);
  white-space: nowrap;
}

/* 三态开关：减少动态有「跟随系统 / 开 / 关」三档，所以它不是两态拨钮。 */
.pg-toggle__track {
  position: relative;
  flex: 0 0 auto;
  width: 52px;
  height: 30px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
  transition: background var(--gs-fast);
}

.pg-toggle__track > i {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #e8eeff;
  transition: transform var(--gs-fast) var(--gs-ease-out);
}

.pg-toggle[aria-checked='true'] .pg-toggle__track { background: var(--gs-accent); }
.pg-toggle[aria-checked='true'] .pg-toggle__track > i { transform: translateX(22px); }

/* 「跟随系统」这一档要一眼看得出**不是开也不是关**：旋钮停在正中，
   轨道改成条纹而不是另一种实色。实色只是换了个颜色，扫一眼仍然读成「开着」
   （走查原话：「显示 Follows your device 字样但仍是一个普通开关且处于开态外观」）。 */
.pg-toggle[aria-checked='mixed'] .pg-toggle__track {
  background: repeating-linear-gradient(
    -45deg,
    rgba(255, 255, 255, 0.3) 0 5px,
    rgba(255, 255, 255, 0.1) 5px 10px
  );
}

.pg-toggle[aria-checked='mixed'] .pg-toggle__track > i {
  transform: translateX(11px);
  background: var(--gs-accent-2);
}

.pg-toggle[aria-checked='mixed'] .pg-toggle__state {
  color: var(--gs-accent-2);
}

/* ============================ 图鉴 / 涂装 / 进度 ============================ */

.pg-grid {
  display: grid;
  gap: var(--gs-space-2);
  width: 100%;
}

.pg-grid--3 { grid-template-columns: repeat(3, 1fr); }
.pg-grid--2 { grid-template-columns: repeat(2, 1fr); }

.pg-seal {
  position: relative;
  aspect-ratio: 1;
  min-width: var(--gs-tap-min);
  min-height: var(--gs-tap-min);
  border-radius: 50%;
  border: 1px solid var(--gs-hairline);
  background: rgba(8, 12, 34, 0.6);
  display: grid;
  place-items: center;
  cursor: pointer;
  padding: 4px;
  box-sizing: border-box;
}

.pg-seal img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.pg-seal[aria-disabled='true'] { filter: saturate(0.2) brightness(0.6); }
.pg-seal[aria-pressed='true'] { border-color: var(--gs-accent); box-shadow: var(--gs-glow-accent); }

.pg-seal__no {
  position: absolute;
  right: 2px;
  bottom: 0;
  font-size: 10px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--gs-ink-dim);
  text-shadow: 0 1px 2px #000;
}

/* 最后一行印章不该被分区下沿切掉——网格是可滚的，但滚到底也要留出余量。 */
.pg-screen[data-screen='codex'] .pg-zone[data-zone='play'] {
  padding-bottom: var(--gs-space-5);
}

/* 展开的日志条目：**就地展开的一张卡，不是模态**（SCREEN_SPEC 明写）。 */
.pg-entry {
  width: 100%;
  padding: var(--gs-space-3);
  border-radius: var(--gs-radius-md);
  background: rgba(10, 15, 40, 0.86);
  border: 1px solid var(--gs-hairline);
  box-sizing: border-box;
}

.pg-track {
  display: flex;
  flex-direction: column;
  gap: 0;
  width: 100%;
}

.pg-track__row {
  position: relative;
  display: grid;
  grid-template-columns: 26px auto 1fr auto;
  align-items: center;
  gap: var(--gs-space-2);
  padding: 7px 0;
}

.pg-track__dot {
  position: relative;
  width: 14px;
  height: 14px;
  margin-inline: 6px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.28);
  box-sizing: border-box;
}

.pg-track__row[data-state='done'] .pg-track__dot { background: var(--gs-accent); border-color: var(--gs-accent); }
.pg-track__row[data-state='next'] .pg-track__dot { border-color: var(--gs-accent); box-shadow: var(--gs-glow-accent); }

.pg-track__row::after {
  content: '';
  position: absolute;
  left: 12px;
  top: 50%;
  height: 100%;
  width: 2px;
  background: var(--gs-hairline);
  z-index: -1;
}

.pg-track__row:last-child::after { display: none; }
.pg-track__row[data-state='next'] { border-radius: 10px; box-shadow: var(--gs-glow-accent); }
.pg-track__cost { display: flex; align-items: center; gap: 4px; font-variant-numeric: tabular-nums; }
.pg-track__cost img { width: 16px; height: 16px; }

.pg-preview-wide {
  width: 100%;
  height: 100%;
  display: block;
  border-radius: var(--gs-radius-md);
  background: transparent;
}

.pg-loading-planet { max-width: 50%; }
.pg-version { text-align: center; }
.pg-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.pg-seal .pg-seal__species { position: absolute; inset: 18%; width: 64%; height: 64%; }
.pg-entry__art { float: left; width: 72px; height: 72px; object-fit: contain; margin: 0 12px 8px 0; }
.pg-level-medal { min-width: 64px; min-height: 64px; border-radius: 50%; box-shadow: var(--gs-glow-gold); }
.pg-title-modes > button { flex: 1 1 26%; justify-content: center; }
.pg-title-modes > button:nth-child(-n+3) { background: radial-gradient(ellipse at bottom, #593684, #11182e); }
.pg-title-modes > button:nth-child(2) { background: radial-gradient(ellipse at bottom, #945231, #11182e); }
.pg-title-modes > button:nth-child(3) { background: radial-gradient(ellipse at bottom, #313866, #090e26); }
.pg-title-modes > button:nth-child(-n+3) .pg-chip__icon { width: 24px; height: 24px; }
.pg-dialog .pg-zonebox { inset: 0; }
.pg-dialog .pg-zone[data-zone='header'] { min-height: 54px; }
.pg-overlay[data-result='scorched'] .pg-overlay__scrim { backdrop-filter: grayscale(0.85); background: rgba(4,6,20,0.24); }
.pg-overlay[data-result='scorched'] .pg-dialog::before { background: linear-gradient(165deg, rgba(22,36,64,.55), rgba(11,16,42,.90)); }
.pg-result-block { min-width: 0; }
.pg-overlay[data-result='scorched'] .pg-result-body {
  --gs-text-hero: 32px;
  --gs-gold: #c6dcff;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  align-content: start;
}
.pg-overlay[data-result='scorched'] .pg-result-body > * {
  background: rgba(9,20,45,.88);
  border: 1px solid var(--gs-hairline);
  border-radius: 12px;
  padding: 8px;
  box-sizing: border-box;
  min-width: 0;
  overflow-wrap: anywhere;
}
.pg-overlay[data-result='scorched'] .pg-statcard { flex-direction: column; align-items: flex-start; }
.pg-overlay[data-result='scorched'] .pg-curve { height: 100px; }
.pg-overlay[data-result='scorched'] .pg-statcard__thumb { width: 64px; height: 64px; }
.pg-overlay[data-overlay='result'] .pg-zone[data-zone='header'] { padding-right: 16px; gap: 4px; }
.pg-overlay[data-overlay='result'] .pg-zone[data-zone='header'] .pg-display-md { font-size: 22px; }
.pg-overlay[data-overlay='result'] .pg-zone[data-zone='header'] .pg-body { font-size: 12px; line-height: 1.3; }
.pg-screen[data-screen='title'] .pg-zone[data-zone='play'] { overflow-y: auto; padding-bottom: 8px; }
.pg-screen[data-screen='title'] .pg-preview-wide { flex-basis: 160px !important; }

/* ======================= 矮竖屏（站内嵌入框那一档） ======================= */
/*
 * 视口是竖的、却只有 403px 高：前台详情页把游戏嵌在一块 342×403 的框里，
 * 画布锁定这一档不生效（宽度没超过一台手机），于是竖屏版式要原样塞进半屏高度。
 * 不处理的话，HUD 那一列 64px 的圆按钮会顶出 `hud` 分区、落到星球画布上——
 * 走查报的是「Sound 的中心点被 canvas 盖住」，玩家遇到的是「静音键点不动」。
 *
 * 这一档只收**尺寸**，不动版式：分区表、栅格、层级、热区一律照旧，
 * 所以它不是第二套设计。出口高度 560px 与手机横屏同一个数
 * （`shared/phone-canvas.json.shortViewportMaxHeightPx`），横屏那一档写在下面、
 * 规则更靠后，所以横屏仍然按横屏走。
 */
@media (orientation: portrait) and (max-height: 560px) {
  :root {
    --gs-space-3: 6px;
    --gs-space-4: 10px;
  }

  /* HUD：两枚圆按钮改横排，其余等比收一档。44×44 是触控下限，收到这里为止。 */
  .pg-hud { gap: 2px 6px; padding: 2px 6px; }
  .pg-hud__score { gap: 2px; }
  .pg-hud__btns { flex-direction: row; }
  .pg-hud-control { width: 44px; height: 44px; flex: 0 0 44px; }
  .pg-hud__clock .pg-caption { font-size: 9px; }
  .pg-seedslot { width: 46px; height: 46px; }
  .pg-seedslot__well { width: 38px; height: 38px; }
  .pg-seedslot__time { font-size: 12px; }
  .pg-preview__card { width: 26px; height: 32px; }
  .pg-preview__card img { width: 18px; height: 18px; }
  .pg-num-lg { font-size: 20px; }
  .pg-scorch__cell { width: 11px; height: 7px; }

  /* 提示条：留白收紧、字号降一档，两行仍然装得下 `hint` 分区。 */
  .pg-hint { padding: 4px 8px; gap: 6px; }
  .pg-hint__text { font-size: 11px; line-height: 1.25; }
  .pg-hint__dot { width: 16px; height: 16px; font-size: 11px; }
  .pg-hint__arrow { width: 18px; height: 18px; }

  /* 标题页的品牌块。 */
  .pg-emblem { width: 36px; }
  .pg-display-xl { font-size: 22px; }
  .pg-display-md { font-size: 18px; }
  .pg-body--sm { font-size: 11px; }
  .pg-screen[data-screen='title'] .pg-preview-wide { flex-basis: 96px !important; }

  /* 兜底：**除了 `play` 这一屏**，分区内容装不下时在分区内部滚，
     绝不溢出去压住隔壁分区。`play` 那一屏不给滚——它的三块都必须一眼全在，
     而且星球分区一旦变成滚动容器就会把落种的指针吃掉。 */
  .pg-screen:not([data-screen='play']) .pg-zone,
  .pg-dialog .pg-zone {
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;
  }
}

/* ============================ 手机横屏 ============================ */
/*
 * 手机横过来是**手机的一个朝向**，不是桌面。出口高度 560px 的唯一真值是
 * `shared/phone-canvas.json.shortViewportMaxHeightPx`——两个数中间那一段高度
 * 会两套规则都不管：画布不锁、横屏样式也不生效。
 */
@media (orientation: landscape) and (max-height: 560px) {
  .pg-hud {
    grid-template-columns: 1fr;
    grid-template-areas:
      'seed'
      'score'
      'clock';
    align-content: start;
    gap: var(--gs-space-2);
  }

  .pg-hud__seeds { flex-direction: row; align-items: center; }
  .pg-hud__btns { flex-direction: row; }
  .pg-screen[data-screen='play'] .pg-zone[data-zone='side'] { padding: 4px 8px; justify-content: space-between; gap: 8px; }
  .pg-screen[data-screen='play'] .pg-zone[data-zone='side'] .pg-hint { flex: 1; min-height: 0; }
  .pg-hud-control { width: 64px; height: 64px; flex-basis: 64px; }
  .pg-hud__btns { flex: 0 0 64px; justify-content: flex-end; }
  .pg-preview { flex-direction: row; }

  .pg-display-xl { font-size: clamp(24px, 4.6vh, 32px); }
  .pg-display-md { font-size: clamp(18px, 3.8vh, 24px); }
  .pg-num-lg { font-size: clamp(22px, 4.4vh, 30px); }
  .pg-curve { height: 92px; }
  .pg-seedslot { width: 58px; height: 58px; }
  .pg-seedslot__well { width: 46px; height: 46px; }
}

@keyframes pg-nudge { 50% { filter: brightness(1.7); } }
.pg-hint--nudge { animation: pg-nudge 180ms ease-out; }

/* ============================ 减少动态 ============================ */
/*
 * 只去掉「动」，**离散状态变化一个不去**（§10.5）：高亮、生命环的格数、
 * 焦土条、三角的亮灭照旧。判定完全不受影响——`logic.mjs` 拿不到这些开关。
 */
:root[data-reduced-motion='on'] .pg-seedslot,
:root[data-reduced-motion='on'] .pg-scorch--danger .pg-scorch__cells {
  animation: none;
}

:root[data-reduced-motion='on'] * {
  transition-duration: 1ms !important;
}

@media (prefers-reduced-motion: reduce) {
  :root:not([data-reduced-motion='off']) .pg-seedslot {
    animation: none;
  }
}
