/* 像素筆記本佈景（`<body data-theme="px">`）── 方格筆記本上畫的 NES 橫向捲軸
 * ═════════════════════════════════════════════════════════════════════
 * 老師 2026-09-11：「NES 的馬力歐風格，但是配色可以維持白底黑線（有種筆記本風格的感覺）」
 *   ＋「底部的像素風遊戲人偶依照投影片撥放進度逐步走到結尾，
 *     然後應該要有前後景的物件」
 *
 * ⭐ 三樣東西組成：
 *   紙　＝ 近白的紙 ＋ 淡到幾乎看不見的方格（一格＝8 個像素）
 *   墨　＝ 所有的字與框線都是墨色 #1a1a1f（字 ⛔ 不上彩色）
 *   色　＝ ⭐ 老師 2026-09-11：「目前的顏色還是太少了，nes好像低彩度至少可以配8種顏色」
 *          ⇒ 像素圖用一套 NES 低彩度色盤（13 色，`--px-c-*`）；內容區的框用同一套色的**淡色**當底
 *            （`--px-tint-*`），字維持墨色 ⇒ 對比不會掉。
 *   字　＝ ⭐ 老師 2026-09-11：「除了封面頁，內頁都用Noto黑」
 *          ⇒ 預設全部是 Noto Sans CJK TC（`--f-*`），標題用 700；
 *          只有封面自己把字換成俐方體 11 號（`--px-f-pixel`，像素字型，授權允許散布）。
 *   配套的 JS 在 `元件/像素.js`（像素圖、底部場景、跟著翻頁走的小人）。
 *
 * ⛔⛔ 這支放在 `工作區/` 根目錄，⛔ 不要搬進 `元件/`（2026-09-11 實測）：
 *   編譯器處理頁面的 `<link href>` 時**只留檔名、丟掉資料夾**（deck_compile.py 約 6207 行，
 *   `asset_dir + Path(href).name`）⇒ `元件/像素筆記本.css` 編譯後變成 `像素筆記本.css`，
 *   指到不存在的檔，⚠ **整份佈景靜靜消失**（單張 HTML 完全正常）。JS 那邊 2026-08-27 修過會保留資料夾，CSS 還沒。
 *   ⇒ 所以 `.gitignore` 要逐個放行它（`工作區/*.css` 其餘都是 deck assets 的副本）。
 *
 * ⛔⛔ 這支是**課程自己的佈景**，⛔ 還沒進 presentationDeck：
 *   ① 字型直接 `url()` 指到 `fonts-src/Cubic.ttf`（2.7 MB，沒子集化）——
 *     本機預覽（caddy／`播放-*.html`）會對，⚠ `build/` 那份**不保證帶得到字型**，
 *     會退回 Noto Sans。⬜ 定案後要進 `build_deck.py` 的 FACES（optional=True）。
 *   ② 只在這個資料夾裡。換一台機器 clone 下來它會跟著 git 走（`工作區/元件/` 有收），
 *     ⛔ 但字型檔不會（`fonts-src/` 沒收）⇒ 那台要自己放一份 Cubic.ttf。
 *
 * ⛔ 沿用的硬規矩（gamedesignbyHistory101 的 版面POC 實測出來的）：
 *   陰影一律零模糊（`box-shadow: x y 0`）——有模糊半徑的影子印進 PDF 會變點陣圖。
 *   會動的東西 `@media print` 一定要定格。
 *   頁面裡要覆寫這裡的元件，一律寫 `.slide .px-xxx{}`（編譯後頁內 CSS 會被加上 `#sNN` 前綴，
 *   而 data-theme 就掛在 #sNN 那個 section 自己身上 ⇒ 頁面裡寫 `[data-theme="px"] .x` 會選不到）。
 *   黃只能當填色，⛔ 不可以當字的顏色（淺底上黃字讀不到）。
 */

@font-face{
  font-family:"Cubic 11";
  src:local("Cubic 11"), url("fonts-src/Cubic.ttf") format("truetype");
  font-display:block;
}

/* 鏡頭在世界裡的位置、小人在畫面上的位置（單位都是 cqw，JS 寫進來）。
   ⭐ 註冊成 <number> 才能用 transition 走過去——各層與小人都從這兩個數字算，一起動。 */
@property --px-cam{ syntax:"<number>"; inherits:true; initial-value:0 }
@property --px-x{ syntax:"<number>"; inherits:true; initial-value:14 }

[data-theme="px"]{
  /* ── 色 ── */
  --bg:#f8f8f4; --card:#ffffff; --line:#cfd4dc; --line-strong:#1a1a1f;
  --dim:#4f5058;              /* 次要字 7.6:1 */
  --accent:#1a1a1f;
  --px-ink:#1a1a1f;           /* 墨 */
  --px-paper:#f8f8f4;         /* 紙。⚠ 不用純白：大螢幕會刺眼（deck.css 同一條理由）*/
  --px-card:#ffffff;          /* 放在紙上的東西（方塊、表格、對話框）比紙再亮一階 */
  --px-grid:#e1e5ec;          /* 方格。對紙只有 1.13 倍——格線要淡到幾乎看不見，只有放上去的東西是實的 */
  --px-soft:#ecece6;          /* 表頭那種「不是主角」的底 */
  --px-hi:#ffd98a;            /* 暖黃：螢光筆、? 方塊、金幣（學校 loadingGame 亮燈窗戶的色）*/
  --px-pencil:#b2b6be;        /* 鉛筆灰。⚠ 只給裝飾用，⛔ 不當字色 */
  /* 學校配色：像素圖用（字母對照在 像素.js 的檔頭）。⛔ 都不當字色
     ⭐ 2026-09-11 老師：「sheet-machine…loadinggame，那裏有真正的學生制服、學校標誌色配色，直接抄過來」
        ⇒ 色碼抄自 sheet-machine 的 src/theme/colors.config.js（校徽像素化：#020180 深藍、#00A000 綠，
          補色蜜桃橘 #EAB88F、奶油米 #EFE0C8、石墨灰 #5B5B5D、珊瑚紅 #c0392b）與 loadingScene2d.js。 */
  --px-c-a:#c8a048;  /* A 金褐 */     --px-c-o:#c0392b;  /* O 珊瑚紅磚 */ --px-c-q:#f0755a;  /* Q 磚亮 */
  --px-c-d:#8e2418;  /* D 磚暗 */     --px-c-g:#00a000;  /* G 校徽綠 */   --px-c-h:#2f5e2c;  /* H 深綠 */
  --px-c-l:#6ab04c;  /* L 草綠 */     --px-c-m:#a8c8d6;  /* M 遠山 */     --px-c-v:#93b8c9;  /* V 遠山輪廓 */
  --px-c-c:#a2d7f3;  /* C 天藍 */     --px-c-b:#020180;  /* B 校徽深藍 */ --px-c-f:#f2c79c;  /* F 膚色 */
  --px-c-r:#d84c30;  /* R 屋瓦紅 */   --px-c-e:#efe0c8;  /* E 制服奶油米 */ --px-c-n:#5b5b5d; /* N 石墨灰 */
  --px-c-p:#2c2c34;  /* P 黑絲襪 */   --px-c-u:#4a2b12;  /* U 鞋深棕 */   --px-c-i:#f4f0e0;  /* I 米白 */
  --px-c-j:#2f6bd8;  /* J 藍鵲的藍（sheet-machine loadingArt.js 的 BIRD_PAL.B）*/
  /* 同一套色的淡色：當內容區方框的底。上面放墨色的字，對比都在 14:1 以上 */
  --px-tint-sky:#d8f0fc;    /* 天空最淡那一階（loadingGame 的 SKY_BANDS）*/
  --px-tint-leaf:#e2f2d8;   /* 淡綠 */
  --px-tint-peach:#f7d6b8;  /* 蜜桃橘淡階（colors.config 的 warning.gradient.start）*/
  --px-tint-sun:#fff3c4;    /* 太陽（loadingGame）*/
  --px-tint-cream:#efe0c8;  /* 奶油米（colors.config 的 alert 底）*/

  /* ── 尺寸 ──
     一個像素 --u ＝ 4.5px（1080p）／3px（720p）。像素圖一律用 --u 當單位，⛔ 不要混別的比例。
     方格一格 ＝ 8u。 */
  --u:.41667cqh;
  --cell:calc(var(--u) * 8);
  --px-gh:calc(var(--u) * 16);     /* 地面高 */
  --px-scene-h:20cqh;              /* 底部場景的高度 ⇒ ⛔ 內容不可以進到這一條。
                                      ⚠ 2026-09-11 從 16 加到 20：旗竿、城堡、雲要放得下 */
  --px-dur:.9s;                    /* 換頁時走多久（JS 的「走多久」要跟著改）*/

  /* ── 字 ──
     ⭐ 內頁一律 Noto 黑（老師 2026-09-11）；像素字只給封面，由封面自己用 --px-f-pixel。
     ⛔ 每一條 stack 都要接 "Jigmo2"（deck.css 的規矩：漏了的話擴充區的字會靜靜掉成系統字型）。
     ⚠ Noto Sans CJK TC 走 `./deck fonts` 子集化打包（build_deck.py 的 FACES 有它）⇒ 加了新字要重跑一次。 */
  --px-f-sans: "Noto Sans CJK TC","Jigmo2",sans-serif;
  --px-f-pixel:"Cubic 11","Noto Sans CJK TC","Jigmo2",sans-serif;
  --f-display:var(--px-f-sans);
  --f-head:   var(--px-f-sans);
  --f-body:   var(--px-f-sans);
  --f-ui:     var(--px-f-sans);
  --lh-body:1.5; --lh-head:1.3; --ls:.02em;
  /* 字級：12 的倍數。⭐ 當初是為了像素字（Cubic 11 一個 em 是 12 格，1080p 上才落在整數像素）；
     內頁換成 Noto 之後這條不必要了，但數字本身都在 deck.css 的下限以上，就沿用。 */
  --t-display:8.8889cqh;   /* 96px */
  --t-h1:     6.6667cqh;   /* 72px */
  --t-h2:     4.4444cqh;   /* 48px */
  --t-body:   4.4444cqh;   /* 48px */
  --t-min:    3.3333cqh;   /* 36px，比 deck.css 的下限 3.2cqh 大 */
  --t-cap:    2.2222cqh;   /* 24px，⚠ 只給 HUD 那種裝飾字 */
}

/* ── 紙 ── ⚠ 質地要下在 .slide 上：.slide 自己有不透明的底色，下在外層會整片被蓋掉 */
[data-theme="px"] .slide{
  background-color:var(--px-paper);
  background-image:
    repeating-linear-gradient(to right,  var(--px-grid) 0 .1cqh, transparent .1cqh var(--cell)),
    repeating-linear-gradient(to bottom, var(--px-grid) 0 .1cqh, transparent .1cqh var(--cell));
  color:var(--px-ink);
  font-family:var(--f-body);
  letter-spacing:var(--ls);
}

/* ── HUD：NES 畫面最上面那一排（兩列：標籤／值）── 裝飾字，不受字級下限 */
/* ⛔⛔ 外框一定要用 <div class="px-hud">，⛔ 不可以用 <header>：編譯器剝 <head> 的規則（`</?head[^>]*>`）
      也會吃掉 <header …> ⇒ 編譯後 class 跟著消失，HUD 散成一團，⚠ 單張 HTML 完全正常（2026-09-11 踩過）。 */
[data-theme="px"] .px-hud{
  position:absolute; left:5%; right:5%; top:2.2cqh; z-index:4;
  display:flex; justify-content:space-between; align-items:flex-start;
  font-family:var(--f-ui); font-size:var(--t-cap); line-height:1.25; color:var(--dim);
  letter-spacing:.08em;
}
[data-theme="px"] .px-hud > div{ display:flex; flex-direction:column; min-width:14cqw }
[data-theme="px"] .px-hud > div:last-child{ align-items:flex-end }
[data-theme="px"] .px-hud b{ font-weight:400; color:var(--px-ink); display:flex; align-items:center; gap:.3em }
[data-theme="px"] .px-hud .px-spr{ --u:.2083cqh }
/* 金幣數（出現過幾組問答）：靜態＝這一張做完的數（.fin），播放器裡＝即時的數（.live）*/
[data-theme="px"] .px-hud [data-px="coins"] > i{ font-style:normal }
[data-theme="px"] .px-hud [data-px="coins"] > .live{ display:none }
@media screen{
  .reveal [data-theme="px"] .px-hud [data-px="coins"] > .fin{ display:none }
  .reveal [data-theme="px"] .px-hud [data-px="coins"] > .live{ display:inline }
}

/* ── 內容區：HUD 底下到場景上緣 ── */
[data-theme="px"] .px-main{
  position:absolute; left:5%; right:5%; top:9.5cqh; bottom:var(--px-scene-h); z-index:3;
  display:flex; flex-direction:column;
}
[data-theme="px"] .px-title{
  font-family:var(--f-head); font-weight:700; font-size:var(--t-h1); line-height:1.2;
  margin:0 0 2.8cqh;
}
/* 標題底下一道螢光筆（只塗下半截，像真的劃過去）*/
[data-theme="px"] .px-title > span{
  background:linear-gradient(transparent 60%, var(--px-hi) 60% 94%, transparent 94%);
  -webkit-box-decoration-break:clone; box-decoration-break:clone;
  padding:0 .15em;
}

/* ── 像素圖 ── */
[data-theme="px"] .px-spr{ display:inline-block; vertical-align:middle; line-height:0 }
[data-theme="px"] .px-svg{ display:block; width:calc(var(--w) * var(--u)); height:calc(var(--h) * var(--u)); overflow:visible }
[data-theme="px"] .px-svg .k{ fill:var(--px-ink) }
[data-theme="px"] .px-svg .w{ fill:var(--px-card) }
[data-theme="px"] .px-svg .y{ fill:var(--px-hi) }
[data-theme="px"] .px-svg .s{ fill:var(--px-pencil) }
[data-theme="px"] .px-svg .o{ fill:var(--px-c-o) } [data-theme="px"] .px-svg .q{ fill:var(--px-c-q) }
[data-theme="px"] .px-svg .d{ fill:var(--px-c-d) } [data-theme="px"] .px-svg .g{ fill:var(--px-c-g) }
[data-theme="px"] .px-svg .h{ fill:var(--px-c-h) } [data-theme="px"] .px-svg .l{ fill:var(--px-c-l) }
[data-theme="px"] .px-svg .m{ fill:var(--px-c-m) } [data-theme="px"] .px-svg .c{ fill:var(--px-c-c) }
[data-theme="px"] .px-svg .b{ fill:var(--px-c-b) } [data-theme="px"] .px-svg .f{ fill:var(--px-c-f) }
[data-theme="px"] .px-svg .r{ fill:var(--px-c-r) }
[data-theme="px"] .px-svg .a{ fill:var(--px-c-a) } [data-theme="px"] .px-svg .v{ fill:var(--px-c-v) }
[data-theme="px"] .px-svg .e{ fill:var(--px-c-e) } [data-theme="px"] .px-svg .n{ fill:var(--px-c-n) }
[data-theme="px"] .px-svg .p{ fill:var(--px-c-p) } [data-theme="px"] .px-svg .u{ fill:var(--px-c-u) }
[data-theme="px"] .px-svg .i{ fill:var(--px-c-i) } [data-theme="px"] .px-svg .j{ fill:var(--px-c-j) }

/* ── 像素框：四邊各一格、四個角缺一格（NES 的視窗），右下一道硬邊影子 ──
   ⭐ 用 box-shadow 畫：每一道只往一個方向位移 ⇒ 角落沒被蓋到，就是缺角。零模糊 ⇒ PDF 裡是向量。 */
[data-theme="px"] .px-box{
  --b:var(--u);
  position:relative; background:var(--px-card); margin:var(--b);
  box-shadow:
    0 calc(var(--b) * -1) 0 0 var(--px-ink),
    0 var(--b) 0 0 var(--px-ink),
    calc(var(--b) * -1) 0 0 0 var(--px-ink),
    var(--b) 0 0 0 var(--px-ink),
    calc(var(--b) * 2) calc(var(--b) * 2) 0 0 var(--px-ink);
}
[data-theme="px"] .px-box.hi{ background:var(--px-hi) }
[data-theme="px"] .px-box.sky{ background:var(--px-tint-sky) }
[data-theme="px"] .px-box.leaf{ background:var(--px-tint-leaf) }
[data-theme="px"] .px-box.peach{ background:var(--px-tint-peach) }
[data-theme="px"] .px-box.sun{ background:var(--px-tint-sun) }
[data-theme="px"] .px-box.cream{ background:var(--px-tint-cream) }

/* ── 表格：底色是墨、格子間距一個像素 ⇒ 格線就是一個像素寬 ── */
[data-theme="px"] .px-table{
  border-collapse:separate; border-spacing:var(--u); background:var(--px-ink);
  box-shadow:calc(var(--u) * 2) calc(var(--u) * 2) 0 0 var(--px-ink);
  font-size:var(--t-body); line-height:1.3;
}
[data-theme="px"] .px-table th,
[data-theme="px"] .px-table td{ background:var(--px-card); padding:1.4cqh 2cqh; font-weight:400 }
[data-theme="px"] .px-table thead th{ background:var(--px-tint-sky) }
[data-theme="px"] .px-table tbody th{ background:var(--px-tint-leaf) }

/* ── 版型（2026-09-11 從親職日的各頁抽出來，老師：「以後這個專案下所有人都可以共用這些元素和版型」）──
   以前這幾種的樣式各自寫在頁面的 <style> 裡（親職日一份、範本一份），改一邊另一邊不會跟著變 ⇒ 搬到這裡。
   ⚠ 這幾條要排在 .px-box、.px-title、.px-table 後面：選擇器一樣重，後面的蓋前面的。 */

/* 招牌：外框兩格粗、裡面再一道細線（NES 標題畫面那塊牌子）。封面、歡迎畫面共用 */
[data-theme="px"] .px-plaque{
  --b:calc(var(--u) * 2);
  box-shadow:
    inset 0 0 0 var(--u) var(--px-card), inset 0 0 0 calc(var(--u) * 2) var(--px-ink),
    0 calc(var(--b) * -1) 0 0 var(--px-ink), 0 var(--b) 0 0 var(--px-ink),
    calc(var(--b) * -1) 0 0 0 var(--px-ink), var(--b) 0 0 0 var(--px-ink),
    calc(var(--b) * 2) calc(var(--b) * 2) 0 0 var(--px-ink);
}
[data-theme="px"] .px-plaque .k1{ font-size:var(--t-h2); line-height:1.3; letter-spacing:.12em }
[data-theme="px"] .px-plaque .k2{ font-size:var(--t-display); line-height:1.2 }

/* 封面（`.px-cover`）：⭐ 唯一用像素字的一頁（老師：「除了封面頁，內頁都用Noto黑」），連 HUD 一起 */
[data-theme="px"] .px-cover, [data-theme="px"] .slide:has(> .px-cover) .px-hud{ font-family:var(--px-f-pixel); letter-spacing:0 }
[data-theme="px"] .px-cover{
  position:absolute; left:5%; right:5%; top:9.5cqh; bottom:var(--px-scene-h); z-index:3;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4cqh;
}
[data-theme="px"] .px-cover .px-plaque{ padding:3.4cqh 6.5cqh 3.8cqh; text-align:center }
[data-theme="px"] .px-cover .px-plaque .k2{ margin-top:1.2cqh }
[data-theme="px"] .px-cover-sub{ font-size:var(--t-h2); line-height:1.3 }
/* 天上的裝飾（雲、一排浮空方塊）：位置寫在頁面的 style（left／top／right／bottom）*/
[data-theme="px"] .px-deco{ position:absolute; z-index:2 }
[data-theme="px"] .px-deco-row{ display:flex }

/* 歡迎畫面（`.px-welcome`）：左邊招牌＋選單（＋一段提醒），右邊大 QR（`.px-qrbox`）。不是封面 ⇒ Noto 黑 */
[data-theme="px"] .px-welcome{
  position:absolute; left:5%; top:11cqh; width:56cqw; bottom:var(--px-scene-h); z-index:3;
  display:flex; flex-direction:column; justify-content:center; gap:3.6cqh;
}
[data-theme="px"] .px-welcome .px-plaque{ align-self:flex-start; padding:2.8cqh 5cqh 3.2cqh }
[data-theme="px"] .px-welcome .px-plaque .k2{ font-weight:700 }
[data-theme="px"] .px-menu{ display:flex; flex-direction:column; gap:1.6cqh; padding-left:.6cqw }
[data-theme="px"] .px-menu .item{ display:flex; align-items:center; gap:1.6cqh; font-size:4cqh; line-height:1.4 }
[data-theme="px"] .px-menu .item .px-spr{ --u:.5cqh; flex:none }
[data-theme="px"] .px-menu .item.sub{ padding-left:calc(7 * .5cqh + 1.6cqh) }
/* ⛔ 不要叫 .note：deck.css 的 .note 是灰色小字，deck overlap 也會把 .note 當講者備註、整塊不檢查（親職日第 2 張踩過）*/
[data-theme="px"] .px-welcome-note{ align-self:flex-start; width:54cqw; box-sizing:border-box; padding:1.6cqh 1.4cqw; font-size:var(--t-min); line-height:1.6 }
[data-theme="px"] .px-qrbox{ position:absolute; right:5.5cqw; top:11.5cqh; width:60cqh; height:60cqh; z-index:3; padding:0 }

/* 流程格（`.px-flow`）：上排幾站＋箭頭，下面每一列是一件事在各站的日期。
   欄與列寫在頁面：style="--flow-cols:16cqw 1fr 2.4cqw 1fr 2.4cqw 1fr"（列名｜站｜▶｜站…），每一格用 grid-column／grid-row 擺 */
[data-theme="px"] .px-flow{
  flex:1; display:grid; align-content:start; column-gap:0; row-gap:1.6cqh;
  grid-template-columns:var(--flow-cols, 16cqw 1fr 2.4cqw 1fr 2.4cqw 1fr); grid-template-rows:var(--flow-rows, none);
}
[data-theme="px"] .px-flow-stage{
  grid-row:1; display:flex; align-items:center; justify-content:center; gap:1cqh;
  min-height:calc(var(--u) * 20); padding:0 1cqh; font-size:var(--t-min); line-height:1.25; text-align:center;
}
[data-theme="px"] .px-flow-stage .px-spr{ --u:.3333cqh }
[data-theme="px"] .px-flow-arrow{ grid-row:1; align-self:center; justify-self:center }
[data-theme="px"] .px-flow-label, [data-theme="px"] .px-flow-date{ font-size:var(--t-body); line-height:1.3; align-self:center }
[data-theme="px"] .px-flow-label{ grid-column:1 }
[data-theme="px"] .px-flow-date{ text-align:center }
/* 好幾列合併成一塊告示（位置寫在頁面：grid-column:6; grid-row:2 / 5）。⛔ 一樣不要叫 .note */
[data-theme="px"] .px-flow-note{
  align-self:stretch; display:flex; align-items:center; justify-content:center; text-align:center;
  padding:1.6cqh 1cqh; font-size:var(--t-min); line-height:1.4;
}

/* 打勾表格（`.px-table.px-check`）：格子置中、列名靠左、打勾用金幣 <i class="px-spr" data-s="金幣" title="✓"> */
[data-theme="px"] .px-check{ align-self:center; margin-top:1cqh }
[data-theme="px"] .px-check th, [data-theme="px"] .px-check td{ text-align:center; min-width:22cqh }
[data-theme="px"] .px-check tbody th{ text-align:left; min-width:0; padding-right:3cqh }
[data-theme="px"] .px-check th{ padding-top:1cqh; padding-bottom:1cqh }
[data-theme="px"] .px-check td{ height:calc(var(--u) * 17); padding-top:0; padding-bottom:0 }
[data-theme="px"] .px-check td .px-spr{ display:inline-block }

/* 訊息框（`.px-box.px-msg`）：一頁只講一句話，置中、字放大；重點用 <em> */
[data-theme="px"] .px-msg{ align-self:center; margin-top:3cqh; padding:3.4cqh 3.2cqw; font-size:var(--t-body); line-height:1.75 }

/* 謝謝聆聽的大字（`<h1 class="px-title px-thanks">`）：放左邊，右邊留給旗竿、城堡、煙火 */
[data-theme="px"] .px-thanks{ font-size:14cqh; margin:16cqh 0 0 1.5cqw }

/* ── 雲朵長條：當進度條用的 stacked bar ──
   老師 2026-09-11：「上方需要一格當作進度條用的雲朵bar，區分為"大考報名"和"大學升學"，
   兩類雲朵其實是當作stack bar chart用，比例按照我給你的大考報名時間和"個人申請"時間去劃分」
   ⭐ 頁面只寫 `<div class="px-cloudbar" data-now="…">`，段、天數、刻度、紅三角都是 `像素.js` 的「雲條」畫的。
   ⭐ 高度先用 min-height 留好 ⇒ JS 還沒畫之前版面就不會跳（`deck overlap` 量到的也是對的高度）。 */
[data-theme="px"] .px-cloudbar{ position:relative; display:flex; gap:var(--u); padding-bottom:3.2cqh; margin-bottom:1.6cqh;
  box-sizing:border-box; min-height:calc(var(--u) * 17 + 3.2cqh); flex:none }
[data-theme="px"] .px-cb-seg{ position:relative; flex:var(--days) 1 0; min-width:0; height:calc(var(--u) * 17) }
[data-theme="px"] .px-cb-seg > .px-tile{ position:absolute; inset:0; overflow:hidden }
[data-theme="px"] .px-svg.px-strip{ display:block; width:100%; height:100% }   /* 蓋過 .px-svg 用 --w×--u 算的寬高 */
[data-theme="px"] .px-cb-seg > b{
  position:relative; z-index:1; display:flex; align-items:center; justify-content:center; height:100%;
  font-size:var(--t-min); font-weight:700; line-height:1;
}
/* 段名放在一塊白色小招牌上：直接壓在雲的輪廓線上會讀不清楚（2026-09-11 截圖看到的）*/
[data-theme="px"] .px-cb-seg > b > span{
  background:var(--px-card); padding:.5cqh 1.4cqh .6cqh;
  box-shadow:0 calc(var(--u) * -1) 0 0 var(--px-ink), 0 var(--u) 0 0 var(--px-ink),
             calc(var(--u) * -1) 0 0 0 var(--px-ink), var(--u) 0 0 0 var(--px-ink);
}
[data-theme="px"] .px-cb-seg:not(.on){ opacity:.38 }
[data-theme="px"] .px-cb-ticks{ position:absolute; left:0; right:0; bottom:0; height:3.2cqh; font-size:var(--t-cap); color:var(--dim); line-height:1 }
[data-theme="px"] .px-cb-ticks > span{ position:absolute; top:.6cqh; transform:translateX(-50%); white-space:nowrap }
[data-theme="px"] .px-cb-ticks > span:first-child{ transform:none }
[data-theme="px"] .px-cb-ticks > span:last-child{ transform:translateX(-100%) }
/* 紅三角：這一張投影片講到的時間點（JS 照 data-now 算 --now，0～1）。
   老師 2026-09-11：「給我一個紅三角標記目前的進度」「"重要期程"那張投影片的紅三角標記放在8/3後面」
   ⭐ 剛好落在底下某個日期字上的話，那一頁寫 `--now-dx`（例如 3.2cqw）往右挪到字的後面。 */
[data-theme="px"] .px-cb-now{
  position:absolute; z-index:2; bottom:calc(3.2cqh - var(--u) * 5);
  left:calc(var(--now, 0) * 100% + var(--now-dx, 0cqw));
  --u:.5cqh; transform:translateX(-50%);
}
[data-theme="px"] .px-cb-nonow .px-cb-now{ display:none }
[data-theme="px"] .px-cb-ticks > span.px-cb-away{ transform:translateX(calc(-50% + 2.7cqw)) }   /* 紅三角壓在這個分界字上時，字往右讓開 */

/* ── 時間軸（`.px-tl`）：磚塊一排當時間軸，每個階段一顆金幣磚 ──
   老師 2026-09-11：「用磚塊當作時間軸，每一個階段就是一個金幣brick，brick下面寫日期，上面讓金幣每案下一次下一頁
   就會由小人撞擊後炸出一顆金幣來，然後上面會寫步驟名稱」
   由上往下：步驟名稱（fragment）→ 金幣磚 → 跑者的跑道 → 磚塊時間軸 → 日期。
   每個階段 `.px-tl-stage` 寫 `style="--x:16.667%"`（在時間軸上的位置，中心點）。
   ⭐ 撞磚、噴金幣、跑步都是 `像素.js` 做的；這裡只管擺位與「撞過了」（`.hit`）的樣子。 */
[data-theme="px"] .px-tl{ position:relative; flex:1; min-height:0;
  --tl-blk:8cqh;      /* 金幣磚的上緣 */
  --tl-row:26.3cqh;   /* 磚塊時間軸的上緣（＝跑者腳底）*/ }
/* 好幾條時間軸：每一條是一個 `.px-tl-lane`（style 寫 --top 與 --lane-h，也可以各自改 --tl-blk／--tl-row）*/
[data-theme="px"] .px-tl-lane{ position:absolute; left:0; right:0; top:var(--top, 0); height:var(--lane-h, 100%) }
[data-theme="px"] .px-tl-row{ position:absolute; left:0; right:0; top:var(--tl-row); height:var(--tl-rowh, calc(var(--u) * 16)) }
/* 時間軸的招牌（兩層時才需要：這一條是哪一種管道）*/
[data-theme="px"] .px-tl-label{ position:absolute; z-index:1; left:.8cqw; top:50%; transform:translateY(-50%);
  background:var(--px-card); padding:.2cqh 1.2cqh; font-size:var(--t-note); font-weight:700; line-height:1.3;
  box-shadow:0 calc(var(--u) * -1) 0 0 var(--px-ink), 0 var(--u) 0 0 var(--px-ink), calc(var(--u) * -1) 0 0 0 var(--px-ink), var(--u) 0 0 0 var(--px-ink) }
[data-theme="px"] .px-tl-row > .px-tile{ position:absolute; inset:0; overflow:hidden }
[data-theme="px"] .px-tl-stage{ position:absolute; top:0; bottom:0; width:var(--sw, 28cqw); left:calc(var(--x) - var(--sw, 28cqw) / 2) }   /* --sw：一個階段多寬（五個階段的那一條要窄一點）*/
[data-theme="px"] .px-tl-name{ position:absolute; left:0; right:0; top:0; text-align:center;
  font-size:3.6cqh; font-weight:700; line-height:1.3 }
[data-theme="px"] .px-tl-blk{ position:absolute; top:var(--tl-blk); left:50%; margin-left:calc(var(--u) * -8); width:calc(var(--u) * 16) }
[data-theme="px"] .px-tl-blk > .px-spr{ display:block }
[data-theme="px"] .px-tl-blk > .used, [data-theme="px"] .px-tl-blk > .coin{ position:absolute; left:0; top:0 }
[data-theme="px"] .px-tl-blk > .used{ visibility:hidden }
[data-theme="px"] .px-tl-blk > .coin{ left:calc(var(--u) * 3); top:calc(var(--u) * -15); visibility:hidden }
[data-theme="px"] .px-tl-stage.hit .px-tl-blk > .q{ visibility:hidden }
[data-theme="px"] .px-tl-stage.hit .px-tl-blk > .used{ visibility:visible }
[data-theme="px"] .px-tl-date{ position:absolute; left:0; right:0; top:calc(var(--tl-row) + var(--tl-rowh, calc(var(--u) * 16)) + 1.2cqh);
  text-align:center; font-size:var(--t-min); line-height:1.3 }
[data-theme="px"] .px-tl-date small{ display:block; font-size:var(--t-note); color:var(--dim) }
/* 跑者的預設位置＝時間軸左端（通道版＝地板那條的左端）；JS 用 translateX 從這裡挪（列印時 transform 拿掉就回到這裡）。 */
[data-theme="px"] .px-tl-runner{ position:absolute; left:0; top:var(--tl-runner-top, calc(var(--tl-row) - var(--u) * 17)); z-index:2 }
[data-theme="px"] .px-tl-runner.px-back .px-hop{ transform:scaleX(-1) }
/* ── 兩條磚、中間留通道（`.px-tl.px-tl-duo`，第 8 張）──
   老師 2026-09-11：「繁星應該放下層，申請都放頂層，然後我們在兩條磚之間留孔道，
     這樣小人可以上下跳一下之後差不多同時擊中同時間的兩個事件（就是這麼忙碌）」
   老師第三輪：「我以為你要讓小人先去撞繁星，然後在從繁星的牆體破洞爬上去撞同時間的個人申請（符合遊戲的人物行為）」
   ⇒ 由下往上：場景的地面（小人在這裡跑）→ 下面那條 `.px-tl-lower`（繁星，磚列底貼著場景上緣）
      → 繁星的字 → 通道 → 上面那條 `.px-tl-upper`（申請）→ 申請的字。
      金幣磚嵌在磚列裡，⭐ 一律從底下頂（跟遊戲一樣，⛔ 不從上面踩）。
   ⭐ 兩條共用一把時間尺：同時間的兩件事寫**同一個 --x**，名稱寫**同一個 data-fragment-index**。
   ⭐ 字的格式兩條一樣（老師：「和繁星對齊」）：名稱（撞到才出現）→ 日期 → 副標（小字），整塊放在自己那條磚上面。
      每一條的副標最多幾行寫在 .px-tl 的 --tl-sub-hi／--tl-sub-lo（字的區塊多高照這個算）。 */
[data-theme="px"] .px-tl-duo{
  --tl-rowh:6cqh;                                  /* 磚列高＝金幣磚寬＝撞破的洞寬（小人 14u＝5.8cqh，要鑽得過去）*/
  --tl-nameh:calc(var(--t-min) * 1.15); --tl-dateh:calc(var(--t-min) * 1.3); --tl-subh:calc(var(--t-note) * 1.3);
  --tl-band-lo:calc(var(--tl-nameh) + var(--tl-dateh) + var(--tl-sub-lo, 1) * var(--tl-subh) + 1.6cqh);
  --tl-band-hi:calc(var(--tl-nameh) + var(--tl-dateh) + var(--tl-sub-hi, 1) * var(--tl-subh) + 2cqh);
  --tl-lo:calc(100% - var(--tl-rowh));                                        /* 下面那條的上緣：磚列底＝內容區底＝場景上緣 */
  /* 上面那條的上緣。--tl-gap＝繁星的字和上面那條之間空多少：太近的話繁星的字看起來像是掛在申請那條底下 */
  --tl-hi:calc(var(--tl-lo) - var(--tl-band-lo) - var(--tl-gap, 6cqh) - var(--tl-rowh));
  /* 跑者站在場景的地面上，起點＝場景小人站的地方（--tl-x0，像素.js 填；換成跑者時看不出來換過）*/
  --tl-runner-top:calc(100% + var(--px-scene-h) - var(--px-gh) - var(--u) * 17);
}
[data-theme="px"] .px-tl-duo .px-tl-runner{ left:calc(var(--tl-x0, 5) * 1cqw - 5cqw) }
[data-theme="px"] .px-tl-duo .px-tl-upper{ --tl-row:var(--tl-hi); --tl-band:var(--tl-band-hi) }
[data-theme="px"] .px-tl-duo .px-tl-lower{ --tl-row:var(--tl-lo); --tl-band:var(--tl-band-lo) }
[data-theme="px"] .px-tl-duo .px-tl-blk{ --u:calc(var(--tl-rowh) / 16); top:var(--tl-row) }   /* 金幣磚嵌在磚列裡，跟磚列一樣高 */
/* 名稱照 HTML 裡的 <br> 換行，⛔ 不讓瀏覽器自己斷 */
[data-theme="px"] .px-tl-duo .px-tl-name{ top:calc(var(--tl-row) - var(--tl-band)); font-size:var(--t-min); line-height:1.15; white-space:nowrap }
[data-theme="px"] .px-tl-duo .px-tl-date{ top:calc(var(--tl-row) - var(--tl-band) + var(--tl-nameh)) }
[data-theme="px"] .px-tl-duo .px-tl-date small + small{ margin-top:.4cqh }   /* 一個階段兩句副標：中間空一點，看得出是兩句 */
[data-theme="px"] .px-tl-duo .px-tl-label{ font-size:var(--t-min); line-height:1.2 }
/* 撞破的洞：繁星那顆被頂破（上下都有事的那一欄），小人從洞裡跳上去撞申請。洞＝紙色蓋掉後面那條磚 */
[data-theme="px"] .px-tl-stage.broken .px-tl-blk{ background:var(--px-paper) }
[data-theme="px"] .px-tl-stage.broken .px-tl-blk > .q, [data-theme="px"] .px-tl-stage.broken .px-tl-blk > .used{ visibility:hidden }
/* 碎磚：JS 撞破時放進去、動畫完就拿掉 */
[data-theme="px"] .px-debris{ position:absolute; width:calc(var(--u) * 6); height:calc(var(--u) * 6);
  background:var(--px-c-r); box-shadow:inset 0 0 0 var(--u) var(--px-ink) }
/* ── 豌豆苗（`.px-vine`）：第 8 張從天上掉下來、第 9 張從雲上垂到學習歷程那條磚 ──
   老師 2026-09-11：「再申請的"學習歷程"那邊給一個從天上掉下來的豌豆苗"，下一張是小人會走到豌豆苗那邊被吸過去」
   ⭐ 圖是 像素.js 的「豌豆苗頂」＋「豌豆苗」直的平鋪；這裡只管擺位。第 8 張沒撞到那一下之前藏著（只在播放器裡）。 */
/* ⭐ 比小人細一點（--u .3cqh ⇒ 寬 4.8cqh）：第 8 張它夾在兩欄的字中間，只有 7cqh 寬的空隙 */
[data-theme="px"] .px-vine{ position:absolute; z-index:1; --u:.3cqh; width:calc(var(--u) * 16); pointer-events:none }
[data-theme="px"] .px-vine > .px-vine-top{ position:absolute; left:0; top:0 }
[data-theme="px"] .px-vine > .px-vine-top > svg{ display:block }
/* ⛔ 一定要 overflow:hidden：.px-svg 預設 overflow:visible，平鋪切剩的那一截會一路垂到地面（2026-09-11 截圖看到的）*/
[data-theme="px"] .px-vine > .px-vstrip{ position:absolute; left:0; top:calc(var(--u) * 13); width:100%; height:calc(100% - var(--u) * 13); overflow:hidden }
[data-theme="px"] .px-tl .px-vine{ left:calc(var(--x) - var(--u) * 8); top:0; height:var(--tl-lo) }
[data-theme="px"] .px-tl-runner.px-gone, [data-theme="px"] .px-sky-runner.px-gone{ visibility:hidden }   /* 被豌豆苗吸上去了 */
@media screen{ .reveal [data-theme="px"] .px-tl .px-vine:not(.on){ visibility:hidden } }

/* ── 雲上世界（`.px-sky`，第 9 張；內容＝原稿 s14 學習歷程檔案流程圖）──
   老師 2026-09-11：「我們用馬力歐的雲上世界，學生製作成果和上傳會有藍鵲（去sheetmachine那邊抄回來）飛過來，
     然後小人跳上去捕捉鳥，抓到身後就會累積一堆箱子，勾選階段小人就會把箱子丟到雲底下去，變成大金剛遊戲XDD
     但是右邊給一個HUD顯示……（這也是一個階段的時間軸），然後這樣循環三次之後，小人就會往下爬下豌豆苗，
     學習歷程那邊就會多出三個箱子（下方文字備註：每個系最多可以收3件學習歷程）」
   老師第二輪：「那個箱子要堆在個人申請的學習歷程那一塊才行」
   ⇒ 左下角是「個人申請」那條磚的一段（招牌同第 8 張），學習歷程那一顆（撞過的空塊）嵌在裡面；
      豌豆苗垂到它左邊（跟第 8 張一樣的左右關係），最後三個箱子直直疊在那一顆上面。
   老師第三輪：「不錯耶，不過地板不用再放箱子了，然後你沒做到小人撞到藍鵲才會新增箱子，其實這要搭配一個提醒，
     有些沒有被撞到的藍鵲，左邊的警告區就要顯示"只上傳沒勾選就不能被中央資料庫使用"」
   ⇒ 撞到的藍鵲才變箱子；沒撞到的飛進左上角的警告區（`.px-sky-warn`）。丟下去的箱子掉進水管（中央資料庫），⛔ 地面不堆箱子。
   位置全部從 .px-sky 的左上角量（cqw／cqh），寫成下面這幾個變數；箱子的格子是 像素.js 照這些變數排的。
   ⭐ 靜態（列印、單張 HTML）＝三年做完的樣子：身後那一堆空了、雲底下 9 個、學習歷程那邊 3 個、備註出現。 */
[data-theme="px"] .px-sky{ position:relative; flex:1; min-height:0; margin-top:1.2cqh;
  --sky-floor:22cqh;        /* 小人在雲上的腳底 */
  --sky-cloud-l:14cqw; --sky-cloud-w:40cqw;     /* 雲；右邊緣就是箱子丟下去的地方 */
  --sky-vine-x:25cqw;       /* 豌豆苗中心（讓開左邊那塊招牌）*/
  --sky-vine-top:1cqh;
  --sky-ledge-top:44cqh; --sky-ledge-w:38cqw;   /* 個人申請那條磚（的一段）*/
  --sky-take-x:29.2cqw;     /* 學習歷程那一顆（左緣）＝三個箱子疊的地方 */
  --sky-walk-x:40cqw;       /* 小人在雲上站的地方（左緣）*/
  --sky-pile-x:29cqw;       /* 身後那一堆（左緣）*/
  --sky-arch-x:55cqw;       /* 雲底下的水管（中央資料庫，左緣）*/
}
[data-theme="px"] .px-sky-cloud{ position:absolute; left:var(--sky-cloud-l); width:var(--sky-cloud-w); top:calc(var(--sky-floor) - 1.4cqh); height:6cqh }
[data-theme="px"] .px-sky-cloud > .px-tile{ position:absolute; inset:0; overflow:hidden }
[data-theme="px"] .px-sky .px-vine{ left:calc(var(--sky-vine-x) - var(--u) * 8); top:var(--sky-vine-top); height:calc(var(--sky-ledge-top) - var(--sky-vine-top)) }
[data-theme="px"] .px-sky-ledge{ position:absolute; left:0; width:var(--sky-ledge-w); top:var(--sky-ledge-top); height:5cqh; --tl-row:0cqh; --tl-rowh:5cqh }
[data-theme="px"] .px-sky-ledge .px-tl-label{ font-size:var(--t-min); line-height:1.2 }
/* 學習歷程那一顆：第 8 張撞過了 ⇒ 空塊；跟磚列一樣高（16 格＝5cqh），箱子（12u 寬＝5cqh）剛好疊在正上方 */
[data-theme="px"] .px-sky-blk{ position:absolute; z-index:1; top:0; left:var(--sky-take-x); --u:calc(5cqh / 16) }
[data-theme="px"] .px-sky-blk > svg{ display:block }
[data-theme="px"] .px-sky-blkname{ position:absolute; left:calc(var(--sky-take-x) + 4.2cqw); bottom:100%; margin-bottom:.6cqh;
  font-size:var(--t-min); line-height:1.25; white-space:nowrap }
[data-theme="px"] .px-sky-blkname b{ display:block }
/* 備註：老師「下方文字備註」⇒ 在那一顆的正下方。
   ⛔ 置中不可以用 transform：它是 fragment，列印時播放器會把 fragment 的 transform 清掉 ⇒ PDF 裡往右偏半個字串寬，
      壓到「中央資料庫封存」（2026-09-11 PDF 看到的；單張 HTML 與 deck overlap 都看不出來）。⇒ 給固定寬度、文字置中。 */
[data-theme="px"] .px-sky-note{ position:absolute; left:calc(var(--sky-take-x) + 1.4cqw - 20cqw); width:40cqw; text-align:center;
  top:calc(var(--sky-ledge-top) + 5.8cqh); font-size:var(--t-min); font-weight:700; line-height:1.3; white-space:nowrap }
[data-theme="px"] .px-sky-arch-label{ position:absolute; left:calc(var(--sky-arch-x) + var(--u) * 16 - 9cqw); width:18cqw; top:calc(var(--sky-ledge-top) + 3cqh);
  font-size:var(--t-min); font-weight:700; line-height:1.3; text-align:center; white-space:nowrap }
/* 水管＝中央資料庫：站在場景的地面上（管口＋一節管身＝16u 高）*/
[data-theme="px"] .px-sky-pipe{ position:absolute; z-index:1; left:var(--sky-arch-x); top:calc(100% + var(--px-scene-h) - var(--px-gh) - var(--u) * 16) }
[data-theme="px"] .px-sky-pipe > .px-svg{ display:block }
/* 左上角的警告區：沒撞到的藍鵲飛進來就亮（播放器裡第一次沒撞到之前藏著；靜態＝一直在）*/
[data-theme="px"] .px-sky-warn{ position:absolute; left:.5cqw; top:.4cqh; width:22cqw; box-sizing:border-box; padding:.8cqh .9cqw;
  font-size:var(--t-min); font-weight:700; line-height:1.3; white-space:nowrap }
[data-theme="px"] .px-sky-warn > .px-spr{ --u:.45cqh; margin-right:.5cqw; vertical-align:-.2em }
[data-theme="px"] .px-sky-arch-label small{ display:block; font-size:var(--t-note); font-weight:400; color:var(--dim) }
[data-theme="px"] .px-crate{ position:absolute; display:block }
[data-theme="px"] .px-crate > svg{ display:block }
[data-theme="px"] .px-crate.px-off{ visibility:hidden }
[data-theme="px"] .px-sky-runner{ position:absolute; z-index:2; left:var(--sky-walk-x); top:calc(var(--sky-floor) - var(--u) * 17) }
[data-theme="px"] .px-sky-runner.px-back .px-hop{ transform:scaleX(-1) }
/* 藍鵲：原圖只有 14×4（描邊後 16×6）⇒ 一格 .7cqh（寬 11.2cqh，約小人寬的 1.9 倍），兩格拍翅。
   ⛔ 無限循環 ⇒ 播放器的動畫閘不會等它。
   ⚠ 大小的來回：.8cqh（老師「為什麼我還是沒看到藍鵲飛過來啊」——真正的原因是作業系統的減少動態，見 像素.js 的「靜」）
      → .95cqh → 老師「有鳥了，不過讓鳥小一點吧」→ .7cqh。 */
[data-theme="px"] .px-bird{ position:absolute; z-index:3; --u:.7cqh }
/* 靜態（列印、縮圖、單張 HTML）的兩隻：一隻飛向小人、一隻已經從他頭上飛過去（往警告區）。播放器裡藏起來。
   ⚠ 第二隻不要貼著警告區：那裡緊鄰豌豆苗，會壓在豌豆苗的頂上 */
[data-theme="px"] .px-bird-still.s0{ left:calc(var(--sky-walk-x) + 9cqw); top:2.5cqh }
[data-theme="px"] .px-bird-still.s1{ left:calc(var(--sky-vine-x) + 4cqw); top:4.5cqh }
[data-theme="px"] .px-bird > span{ display:block }
[data-theme="px"] .px-bird > .b1{ position:absolute; left:0; top:0; visibility:hidden }
[data-theme="px"] .px-bird > .b0{ animation:px-dog .3s steps(1) infinite }
[data-theme="px"] .px-bird > .b1{ animation:px-dog .3s steps(1) -.15s infinite }
/* 右邊的 HUD：年份＋兩個階段（老師：「這也是一個階段的時間軸」）。播放器裡亮目前那一年、那一個階段 */
[data-theme="px"] .px-sky-hud{ position:absolute; right:0; top:0; width:27cqw; box-sizing:border-box; padding:1.4cqh 1.2cqw; line-height:1.3 }
[data-theme="px"] .px-sky-title{ font-size:var(--t-min) }
[data-theme="px"] .px-sky-title b{ display:block; font-size:var(--t-body); line-height:1.2 }
[data-theme="px"] .px-sky-years{ display:flex; gap:.8cqw; margin:1.4cqh 0 .4cqh; font-size:var(--t-min); font-weight:700; line-height:1.3 }
[data-theme="px"] .px-sky-years > span{ padding:0 .7cqw; background:var(--px-card);
  box-shadow:0 calc(var(--u) * -1) 0 0 var(--px-ink), 0 var(--u) 0 0 var(--px-ink), calc(var(--u) * -1) 0 0 0 var(--px-ink), var(--u) 0 0 0 var(--px-ink) }
[data-theme="px"] .px-sky-stage{ margin-top:1.2cqh; padding:.3cqh .6cqw; font-size:var(--t-min) }
[data-theme="px"] .px-sky-stage p{ margin:0 }
[data-theme="px"] .px-n{ font-weight:700 }
[data-theme="px"] .px-n > i{ font-style:normal }
[data-theme="px"] .px-n > .live{ display:none }
@media screen{
  .reveal [data-theme="px"] .px-n > .fin{ display:none }
  .reveal [data-theme="px"] .px-n > .live{ display:inline }
  .reveal [data-theme="px"] .px-sky-years > span.on, .reveal [data-theme="px"] .px-sky-stage.on{ background:var(--px-hi) }
  .reveal [data-theme="px"] .px-sky-note{ opacity:0; transition:opacity .3s steps(3) }
  .reveal [data-theme="px"] .px-sky:not(.px-warned) .px-sky-warn{ visibility:hidden }
  .reveal [data-theme="px"] .px-bird-still{ display:none }
  .reveal [data-theme="px"] .px-sky.px-done .px-sky-note{ opacity:1 }
}

/* ── 煙火（`.px-fw`，最後一張）──
   老師 2026-09-11：「插入最後一張投影片，小人跳上旗子，放個煙火，寫"謝謝聆聽！"」
   ⭐ 一顆火花＝一個有墨線的小方塊（學校配色）；炸開、掉落是 像素.js 的 element.animate()。
   ⭐ 靜態（列印、單張 HTML）：三朵定格的（.px-fw-still）；播放器裡藏起來。 */
[data-theme="px"] .px-fw{ position:absolute; left:0; right:0; top:8cqh; bottom:var(--px-scene-h); z-index:2; pointer-events:none }
[data-theme="px"] .px-spark{ position:absolute; width:1.2cqh; height:1.2cqh; margin:-.6cqh 0 0 -.6cqh; box-shadow:0 0 0 .2cqh var(--px-ink) }
/* 顏色：底色＋color（光暈用 currentColor）*/
[data-theme="px"] .px-fw .o{ background:var(--px-c-o); color:var(--px-c-o) } [data-theme="px"] .px-fw .y{ background:var(--px-hi); color:#ffc44d }
[data-theme="px"] .px-fw .g{ background:var(--px-c-g); color:var(--px-c-g) } [data-theme="px"] .px-fw .c{ background:var(--px-c-c); color:#4fb3e8 }
[data-theme="px"] .px-fw .q{ background:var(--px-c-q); color:var(--px-c-q) } [data-theme="px"] .px-fw .b{ background:var(--px-c-b); color:#3b3bd6 }
/* 炸開那一下的中心閃光（只有播放器裡、JS 放的才有）*/
[data-theme="px"] .px-flash{ position:absolute; width:12cqh; height:12cqh; margin:-6cqh 0 0 -6cqh; border-radius:50%;
  background:radial-gradient(circle, #fff 0 18%, currentColor 32%, transparent 68%) !important }
/* ⭐ 光暈（老師：「讓煙火更炫一些，可以用css的grow之類的吧？」）：模糊的 box-shadow。
   ⛔ 只給播放器裡飛的那些（.px-fly）：模糊陰影印成 PDF 會變成點陣圖（PDF 要全向量），定格的那三朵不加 */
@media screen{
  .reveal [data-theme="px"] .px-fw-still{ display:none }
  .reveal [data-theme="px"] .px-spark.px-fly{ box-shadow:0 0 0 .2cqh var(--px-ink), 0 0 1.2cqh .35cqh currentColor, 0 0 3cqh .8cqh currentColor }
  .reveal [data-theme="px"] .px-spark.px-tail{ box-shadow:0 0 1.2cqh .4cqh currentColor }
}
.px-still [data-theme="px"] .px-fw-still{ display:block !important }

/* 畫面上只能有一個小人：小人跳上時間軸（.px-up）時，場景裡的他藏起來；還在地面走的時候，時間軸上的藏起來 */
/* ⛔ 用 display:none，⛔ 不要用 visibility:hidden：列印時「站著那一格」被 !important 強制 visible，
      子元素的 visible 會蓋過父元素的 hidden ⇒ 藏起來的小人在 PDF 裡又冒出來（2026-09-11 踩過，PDF 裡兩個小人）。 */
[data-theme="px"] .px-scene.px-up .px-walker{ display:none }
[data-theme="px"] .px-tl.px-tl-off .px-tl-runner{ display:none }
/* 小黑狗（sheet-machine loadingGame 的 DOG）：兩格輪播。⛔ 無限循環 ⇒ 播放器的動畫閘不會等它 */
/* 亂走（老師 2026-09-12：「小黑狗隨機移動」）：位置與朝向由 像素.js 每一格寫進 --dx／--df。
   ⛔ 路線寫不進 @keyframes（是亂數），而且有限次數的 CSS 動畫會被播放器的動畫閘等 ⇒ 一定要 JS 寫。
   ⚠ 圖本來面朝左 ⇒ 往右走時 --df 是 -1（翻過來）。 */
[data-theme="px"] .px-dog{ transform:translateX(calc(var(--dx, 0) * 1cqw)) scaleX(var(--df, 1)) }
[data-theme="px"] .px-dog > span{ display:block }
[data-theme="px"] .px-dog > .d1{ position:absolute; left:0; bottom:0; visibility:hidden }
[data-theme="px"] .px-dog > .d0{ animation:px-dog .56s steps(1) infinite }
[data-theme="px"] .px-dog > .d1{ animation:px-dog .56s steps(1) -.28s infinite }
@keyframes px-dog{ 0%{ visibility:visible } 50%{ visibility:hidden } }
/* 播放器裡：步驟名稱等「撞到了」才出現（⛔ 不是 fragment 一 visible 就出現，要等跑者撞完）*/
@media screen{
  .reveal [data-theme="px"] .px-tl .px-tl-name{ opacity:0; transform:translateY(1.6cqh); transition:opacity .01s steps(1), transform .25s steps(4) }
  .reveal [data-theme="px"] .px-tl .px-tl-stage.hit .px-tl-name{ opacity:1; transform:none; transition-delay:.35s }   /* 等噴出來的金幣飛過去再出現 */
}

/* ── QR code：一定要夠大、夠白、四周留白（qrcode 產生時已經帶 4 格白邊）── */
[data-theme="px"] .px-qrsvg{ display:block; width:100%; height:100% }
[data-theme="px"] .px-qrsvg .w{ fill:#ffffff }
[data-theme="px"] .px-qrsvg .k{ fill:#000000 }     /* ⛔ QR 用純黑純白，不要用墨色／紙色：對比掉了手機會掃不到 */

/* ── 問答：? 方塊一撞，答案跳出來 ──
   ⭐ 答案是 reveal 的 fragment（老師按「下一步」才出現）。
   ⛔ 藏起來只在播放器裡（`.reveal` 底下）：單張 HTML 與 PDF 一律看得到答案
      （PDF 那邊 deck-player.css 會把 `.reveal .fragment` 全部強制顯示）。 */
[data-theme="px"] .px-qblock{ position:relative; --u:.8333cqh; flex:none }
[data-theme="px"] .px-qblock > .px-spr{ display:block }
[data-theme="px"] .px-qblock > .used,
[data-theme="px"] .px-qblock > .coin{ position:absolute; left:0; top:0 }
[data-theme="px"] .px-qblock > .used{ visibility:hidden }
[data-theme="px"] .px-qblock > .coin{ left:calc(var(--u) * 3); top:calc(var(--u) * -15); visibility:hidden }
.reveal [data-theme="px"] .px-pop{ transition:opacity .01s steps(1), visibility 0s, transform .3s steps(4) }
.reveal [data-theme="px"] .px-pop:not(.visible){ opacity:0; visibility:hidden; transform:translateY(3cqh) }
/* 撞到之後：? 變成空方塊。⭐ 只看**答案**（`.px-ans`）出來了沒——
   問句本身也可能是 fragment（對話版），⛔ 不能拿「有任何 .px-pop 出來」當判準，不然問句一出來方塊就空了。
   ⭐ 方塊彈一下、金幣往上噴是 `像素.js` 在 fragmentshown 時用 element.animate() 做的
      ⇒ ⛔ 不寫成 CSS @keyframes：倒退回這一頁時答案全都已經顯示，CSS 動畫會在「到達」那一刻重播，
         被播放器的動畫閘當成「動畫播放中」擋住翻頁。 */
[data-theme="px"] .px-qa:has(.px-ans.visible) .px-qblock > .q{ visibility:hidden }
[data-theme="px"] .px-qa:has(.px-ans.visible) .px-qblock > .used{ visibility:visible }

/* ── 對話：訊息一則一則進來，舊的往上推、推出頂端就淡掉 ──
   老師 2026-09-11：「用你剛剛做的對話版型…對話訊息會向上消失（一種類似一直在對話的機制）」
   結構：`.px-chat`（視窗）＞ `.px-chat-log`（整串）＞ 每一組 `.px-qa`（問＋答）。
   ⭐ 兩種樣子：
     單張 HTML／列印（沒有人按下一步）＝ 全部排開的緊湊版，⛔ 一個字都不能少
     播放器（`.reveal` 底下、螢幕上）＝ 聊天室：字大一號，`像素.js` 把整串往上捲到最新一則在底部 */
[data-theme="px"] .px-chat{ position:relative; flex:1; min-height:0 }
/* 靜態（單張 HTML／列印）：兩欄排開，一組問答不跨欄 ⇒ 上面多了雲朵 HUD 也塞得下。
   ⚠ 字已經是下限（--t-min），塞不下只能收間距：2026-09-11「集轉個」那張（四組、答案又長）左欄多出 11.7cqh，
      ⛔ 而且是**壓進底下的場景**——`.slide` 沒溢出、字也沒互相蓋，deck overlap 抓不到，只有看 PDF 才發現。
      ⇒ 收緊間距、行高 1.25、答案泡泡只縮一點（不再對齊問句）。播放器裡的樣子另外寫在下面（.reveal），不受影響。 */
[data-theme="px"] .px-chat-log{ column-count:2; column-gap:2.4cqw }
[data-theme="px"] .px-chat .px-qa{ display:flex; flex-direction:column; gap:.6cqh; break-inside:avoid; margin-bottom:1.2cqh }
[data-theme="px"] .px-chat .px-q{ display:flex; align-items:center; gap:1.6cqh }
[data-theme="px"] .px-chat .px-qblock{ --u:.36cqh }
[data-theme="px"] .px-chat .px-ask,
[data-theme="px"] .px-chat .px-ansbox{ padding:.5cqh 1.4cqh; font-size:var(--t-min); line-height:1.25 }
[data-theme="px"] .px-chat .px-ans{ margin-left:2cqh }
[data-theme="px"] .px-chat p{ margin:0 }
[data-theme="px"] .px-chat .px-ansbox{ display:inline-block; max-width:100% }   /* 泡泡照字的長度，不要撐滿整行 */
/* 播放器裡：聊天室 */
@media screen{
  .reveal [data-theme="px"] .px-chat{ overflow:hidden }
  .reveal [data-theme="px"] .px-chat.px-scrolled{
    -webkit-mask-image:linear-gradient(to bottom, transparent 0, #000 16%); mask-image:linear-gradient(to bottom, transparent 0, #000 16%) }
  .reveal [data-theme="px"] .px-chat-log{ position:absolute; left:0; right:0; top:0; gap:2.2cqh;
    column-count:auto; display:flex; flex-direction:column;
    transition:transform .45s steps(9, end) }
  .reveal [data-theme="px"] .px-chat .px-qa{ gap:2.2cqh; margin-bottom:0 }
  .reveal [data-theme="px"] .px-chat .px-qblock{ --u:.55cqh }
  .reveal [data-theme="px"] .px-chat .px-ask,
  .reveal [data-theme="px"] .px-chat .px-ansbox{ padding:1.8cqh 3cqh; font-size:var(--t-h2); line-height:1.45 }
  .reveal [data-theme="px"] .px-chat .px-ans{ margin-left:calc(16 * .55cqh + 2.2cqh) }
}

/* ══════════════════════════════════════════════════════════════════
   底部場景（`像素.js` 塞進每一張 .slide 的最後面）
   ══════════════════════════════════════════════════════════════════
   ⭐ 一條很長的世界 ＋ 跟著小人走的鏡頭（`--px-cam`）。每一層乘上自己的倍率 `--f` 往左移：
      遠雲 .15／遠山 .3／中雲 .5／中山 .62／地面 1／前景 1.3 ⇒ 遠的慢、近的快，才有深度。
   ⭐ 各層的寬度、物件的位置都是 JS 算好寫在 style 上的（單位 cqw）。 */
[data-theme="px"] .px-scene{
  position:absolute; left:0; right:0; bottom:0; height:var(--px-scene-h);
  /* ⭐ 只裁橫向（各層比畫面寬，要切掉）；縱向放開，小人跳起來、金幣噴上去才不會被切頭 */
  overflow-x:clip; overflow-y:visible; pointer-events:none; z-index:1;
}
[data-theme="px"] .px-layer{
  position:absolute; left:0; top:0; bottom:0;
  transform:translateX(calc(var(--px-cam) * var(--f) * -1cqw));
}
[data-theme="px"] .px-scene .px-o{ position:absolute; bottom:var(--px-gh) }   /* 預設站在地面那道線上 */
[data-theme="px"] .px-ground{ position:absolute; left:0; bottom:0 }
[data-theme="px"] .px-pipe .px-svg:last-child{ margin-left:calc(var(--u) * 2) }
/* 旗子：平常掛在竿頂；最後一張（.px-clear，過關後）降到竿底。JS 的登竿動畫是「從竿頂演回竿底」 */
[data-theme="px"] .px-scene .px-flag{ bottom:calc(var(--px-gh) + var(--u) * 19) }
[data-theme="px"] .px-clear .px-flag{ bottom:calc(var(--px-gh) + var(--u) * 5) }
/* 城堡上的小旗：只有過關（最後一張）才升起來 */
[data-theme="px"] .px-cflag{ position:absolute; left:calc(var(--u) * 15); bottom:calc(var(--u) * 24); display:none }
[data-theme="px"] .px-clear .px-cflag{ display:block }
[data-theme="px"] .px-walker{
  position:absolute; z-index:2; bottom:var(--px-gh);
  left:calc(var(--px-x) * 1cqw);
}
[data-theme="px"] .px-near{ z-index:3 }
[data-theme="px"] .px-near .px-o{ bottom:calc(var(--px-gh) - var(--u) * 4) }   /* 壓在地面上緣，蓋住小人的腳 */

/* 走路：四格輪播（loadingGame 的跑步四幀）。⛔ 無限循環 ⇒ 播放器的動畫閘不會等它；停下來靠 JS 拿掉 .px-walk */
[data-theme="px"] .px-hop{ display:block; position:relative }
[data-theme="px"] .px-hop > span{ display:block }
[data-theme="px"] .px-hop > .f1, [data-theme="px"] .px-hop > .f2,
[data-theme="px"] .px-hop > .f3, [data-theme="px"] .px-hop > .f4,
[data-theme="px"] .px-hop > .fj{ position:absolute; left:0; bottom:0; visibility:hidden }
[data-theme="px"] .px-walk .px-hop > .f0{ visibility:hidden }
[data-theme="px"] .px-walk .px-hop > .f1{ animation:px-step .48s steps(1) infinite }
[data-theme="px"] .px-walk .px-hop > .f2{ animation:px-step .48s steps(1) -.36s infinite }
[data-theme="px"] .px-walk .px-hop > .f3{ animation:px-step .48s steps(1) -.24s infinite }
[data-theme="px"] .px-walk .px-hop > .f4{ animation:px-step .48s steps(1) -.12s infinite }
/* 跳：JS 用 element.animate() 讓 .px-hop 往上跳；這裡只負責換成舉手那一格 */
[data-theme="px"] .px-jump .px-hop > .f0, [data-theme="px"] .px-jump .px-hop > .f1,
[data-theme="px"] .px-jump .px-hop > .f2, [data-theme="px"] .px-jump .px-hop > .f3,
[data-theme="px"] .px-jump .px-hop > .f4{ visibility:hidden; animation:none }
[data-theme="px"] .px-jump .px-hop > .fj{ visibility:visible }
/* 路上的書包／外套（老師 2026-09-12：「把撞不存在的金幣改成 sheetmachine loading game 裡的
   撞道路上的書包／外套，也一樣會導致換衣服或外套」）。⛔ 舊版那顆「頭上噴出來的金幣」整個拿掉了：
   小人頭上根本沒有方塊，那是在撞空氣。
   ⭐ 這一張走完會撿的那一件（.px-take）平常**不畫**——靜態與列印就是「已經撿走了」的樣子；
      只有往前翻、走過去的那段路上（.px-fetch）才看得到，撞到就收走。 */
[data-theme="px"] .px-scene .px-item{ z-index:4 }   /* ⚠ 要比前景草（.px-near，z-index:3）高，不然躺在地上的那一件被草蓋掉一半 */
[data-theme="px"] .px-scene .px-item.px-take{ display:none }
[data-theme="px"] .px-fetch .px-scene .px-item.px-take{ display:block }
/* 背上的書包：撿到書包才看得見（再撿一次就拿下來）。⭐ 貼在背側（小人面朝右 ⇒ 背在左邊）。 */
[data-theme="px"] .px-hop > .px-pack{ position:absolute; left:calc(var(--u) * -1); bottom:calc(var(--u) * 5); display:none }
[data-theme="px"] .px-wear-bag .px-hop > .px-pack{ display:block }
/* 穿上外套：制服（E）換成珊瑚紅、領帶（B）收進外套變深色——跟 sheet-machine 的 JACKET_ON 同一套。
   ⭐ 直接改 SVG 的填色 ⇒ ⛔ 不必另外畫一整套「穿外套」的像素圖（站／走四格／跳，兩種人＝十二張）。 */
[data-theme="px"] .px-wear-jacket .px-hop .px-svg .e{ fill:var(--px-c-o) }
[data-theme="px"] .px-wear-jacket .px-hop .px-svg .b{ fill:#2c2c34 }
@keyframes px-step{ 0%{ visibility:visible } 25%{ visibility:hidden } }
[data-theme="px"] .px-back .px-walker{ transform:scaleX(-1) }
[data-theme="px"] .px-anim{ transition:--px-cam var(--px-dur) linear, --px-x var(--px-dur) linear }

/* ⛔ 列印與「減少動態」：一律定格在站好的樣子 */
@media print{
  [data-theme="px"] .px-scene, [data-theme="px"] .px-scene *{ animation:none !important; transition:none !important }
  [data-theme="px"] .px-hop > .f0{ visibility:visible !important }
  [data-theme="px"] .px-hop > .f1, [data-theme="px"] .px-hop > .f2,
  [data-theme="px"] .px-hop > .f3, [data-theme="px"] .px-hop > .f4,
  [data-theme="px"] .px-hop > .fj{ visibility:hidden !important }
  [data-theme="px"] .px-back .px-walker{ transform:none }
  [data-theme="px"] .px-qblock, [data-theme="px"] .px-qblock > *{ animation:none !important }
  [data-theme="px"] .px-dog{ transform:none !important }   /* 亂走的位移不帶進 PDF */
  [data-theme="px"] .px-dog > .d0{ visibility:visible !important }
  [data-theme="px"] .px-dog > .d1{ visibility:hidden !important }
  /* 路上那一件：列印一律是「已經撿走了」⇒ 先按下一頁再列印、跟直接列印，印出來一樣 */
  [data-theme="px"] .px-item.px-take{ display:none !important }
  /* 時間軸：跑者停在起點、不要帶著走到一半的位移去印 */
  [data-theme="px"] .px-tl-runner{ transform:none !important }
  [data-theme="px"] .px-tl-runner .px-hop{ transform:none !important }
  /* ⛔ 對話在列印時一律是「全部排開」：JS 寫在行內的往上捲要拿掉，不然前面幾則會被推出頁面 */
  [data-theme="px"] .px-chat-log{ transform:none !important }
  /* ⭐ 列印一律印「?」方塊：不然先按開答案再印跟直接印，同一頁會印出兩種樣子 */
  [data-theme="px"] .px-qblock > .q{ visibility:visible !important }
  [data-theme="px"] .px-qblock > .used{ visibility:hidden !important }
  /* 時間軸的金幣磚也一樣：列印一律是「?」，不看播放時撞到哪（不然撞完再印跟直接印會印出兩種樣子）*/
  [data-theme="px"] .px-tl-blk > .q{ visibility:visible !important }
  [data-theme="px"] .px-tl-blk > .used{ visibility:hidden !important }
  [data-theme="px"] .px-tl-stage.broken .px-tl-blk{ background:none !important }
  /* 被豌豆苗吸走的跑者：列印一律站在起點 */
  [data-theme="px"] .px-tl-runner.px-gone{ visibility:visible !important }
  /* 雲上世界：印「三年做完」的樣子——身後那一排空了、學習歷程那一顆上面三個箱子、警告與備註都在；飛到一半的東西不印 */
  [data-theme="px"] .px-sky-take.px-off{ visibility:visible !important }
  [data-theme="px"] .px-sky-warn{ visibility:visible !important; transform:none !important }
  [data-theme="px"] .px-sky-pile{ display:none !important }
  [data-theme="px"] .px-sky .px-fly{ display:none !important }
  /* 登竿動畫（JS）播到一半就按列印：旗子、城堡小旗會停在動畫中途（小旗還是半透明）⇒ 一律印最後的樣子 */
  [data-theme="px"] .px-scene .px-flag, [data-theme="px"] .px-scene .px-cflag{ transform:none !important; opacity:1 !important }
  [data-theme="px"] .px-fw .px-fly{ display:none !important }
  [data-theme="px"] .px-fw-still{ display:block !important }
  [data-theme="px"] .px-bird-still{ display:block !important }
  [data-theme="px"] .px-bird > .b0{ visibility:visible !important; animation:none !important }
  [data-theme="px"] .px-bird > .b1{ visibility:hidden !important; animation:none !important }
  [data-theme="px"] .px-sky-runner{ transform:none !important; visibility:visible !important }
  [data-theme="px"] .px-sky-runner .px-hop{ transform:none !important }
}
/* ⛔ 不用 @media (prefers-reduced-motion)：學校電腦常把 Windows 的動畫效果關掉，Chrome 就回報 reduce，
   整份的走路、跳、藍鵲都會消失（2026-09-11 老師看不到藍鵲）。真的要關動畫：網址加 ?still（像素.js 掛 .px-still）。 */
.px-still [data-theme="px"] .px-scene, .px-still [data-theme="px"] .px-scene *{ animation:none !important; transition:none !important }
.px-still [data-theme="px"] .px-qblock, .px-still [data-theme="px"] .px-qblock > *{ animation:none !important }
