主題系統¶
本檔角色:視覺 / 音訊主題(theme)——受控 CSS、樣式 token、資產映射、分類註冊表、fallback、選用、社群 PR。 對應模組(實作):程式架構/themes.md。 設計動機:樣式 / 圖檔 / 圖示 /LOGO/ 音樂與程式碼脫鉤——程式碼只保證流程與功能,並公開版本化的穩定 theme part;外觀交給各主題自己的 token、資產與受控 CSS。新增主題不改 Angular/ 共用 SCSS/
ThemeService,可客製差異、可分類、逐主題留歷史。
1. 定位與鐵則¶
- 只換 Skin、不換語意與行為:DOM 結構 / 頁面流程 / 資訊層級 / 文案(i18n 管)不歸主題;主題可透過受控 token 與
theme.css改變字體角色、元件形狀、邊框、陰影、表面、裝飾、主視覺構圖位置與受控動態,但不得改變閱讀順序、權限、必要操作、核心 CTA 可達性或共用 RWD 安全下限。Skin Layer 與套用強度見 美術資源/主題外觀與 RWD.md。 - 不碰 gameplay 資訊視覺(保留 token):過熱漸變色、警告色、對手 / 自車辨識色等玩法資訊 token 列入保留清單
THEME_RESERVED_TOKENS(ui.md §14)——主題不可覆蓋(CI 擋 + runtime 防禦忽略)。 - 品牌錨點固定:OG 圖 /PWA manifest icons/SEO 爬蟲所見 = 官方預設(manifest 為 origin 級、無法 per-user);app 內 LOGO/ 圖示可主題化。
- 純 client 資源:不上鏈、不影響配對、不進版本六欄位;任何主題 / 分類變更 = patch(版本規範.md §3 純資源家族、§4
src/themes//public/assets/themes/path 規則)。 - 主題 ⊥ i18n:文字歸 i18n、外觀歸主題,兩軸正交(4 語系 × N 主題);分類顯示名走 i18n dict(§4)、主題自身名稱內嵌多語系(§5)。
2. 模型總覽¶
受控 CSS + token + manifest + fallback 四件組:
- 受控 CSS:Angular 只公開版本化的
[data-theme-part='…']穩定部位;主題以自己資料夾內的theme.css組合表面、形狀、裝飾與主視覺,CI 禁止依賴內部 class。 - token:共用程式與基礎樣式引用 CSS custom properties(色彩 / 字體 / 間距…)與已註冊的真實資產 key family(
brand-emblem、landing-*、scene-*、empty-*、core-loop-*、race-countdown-*、race-start*、sfx-*、bgm-*)。 - manifest:每主題一份
theme.json宣告 Style API 版本、可選 stylesheet、token 覆蓋、資產映射、受控字型角色與僅顯示層使用的renderProfile(§5、§5.3)。 - fallback:Default CSS、token 與資產是完整基線;非 default 主題可省略 stylesheet、token 或資產項目,缺項保留 / 解析到 Default——輕主題(只換色票)與全套主題(含獨立 CSS、插畫、BGM)使用同一模型。
3. 目錄結構(自包含+分類註冊表)¶
src/themes/
├── categories.json ← 分類註冊表(合法分類唯一來源)
├── retired-ids.json ← 退役 id 清單(僅授權/法律下架時登錄;CI 拒重用,§5.2)
├── generated/registry.ts ← public manifests 的生成式 bundle bridge(禁手改)
└── *.ts ← ThemeService、stylesheet loader 與測試
public/assets/themes/
├── default/ ← 預設主題 = fallback 骨幹(CSS / token / 資產 key 完備;SW 永遠預快取)
│ ├── theme.json
│ ├── theme.css
│ └── assets/…
└── <theme-id>/ ← 每主題自包含
├── theme.json
├── theme.css ← 可省略;省略表示只使用 Default CSS+自身 token/資產
└── assets/…
- 執行期由
/assets/themes/<id>/…靜態服務;可部署 payload 位於public/assets/themes/。i18n 則是 bundle lazy chunk,兩者不是同一資產模式。分類、退役 id 與 TypeScript 實作留在src/themes/,不得公開。 - 資產隔離鐵則:主題資料夾只放自己的資產、磁碟零混放;跨主題共用一律靠 fallback 到 default,禁止跨主題引用(theme A 不得指向 theme B 的檔案,validate 擋路徑越界)。
4. 分類系統(資料可變、非程式 enum)¶
分類集合做成資料、不做成程式——現在無法預知會有哪些分類(淺色系 / 日系風格 / 端午節…),所以:
categories.json= 合法分類清單[{ id, i18nKey }];顯示名走 i18n dictthemes.category.<id>(四語系,語系清單.md §3)。- 起始註冊表僅
basic(基本),所有主題預設落此;主題累積後由 PR 新增分類 + 改各主題category欄——分類演化 = 純資料變更(patch、零程式變更),且分類變遷留在各主題自己的 git 歷史(社群討論與歷史累積的分辨單位)。 - theme.json
category值必須存在於註冊表(CI 驗證,擋 typo 與分類碎裂)。 - 分類粒度不設限:「端午節」分類下逐年累積
duanwu-2026-a1b2c3、duanwu-2027-9d8e7f… 各為獨立主題、永久可選。 - 機制一次完整、演化的是資料:註冊表 + 欄位 + 藝廊分組自始即完整功能,長大的只有註冊表內容。
5. theme.json Manifest¶
{
"id": "duanwu-2026-a1b2c3", // = 資料夾名;<slug>-<6 位自產尾碼>(§5.2)、不可改(歷史錨點)
"styleApiVersion": 1, // 必填;不支援的版本拒絕啟用
"stylesheet": "theme.css", // 非 default 可省略;只能指向主題內安全 .css 相對路徑
"name": { "zh-TW": "端午 2026", "zh-CN": "…", "en": "…", "ja": "…" }, // 內嵌多語系(主題名是內容、非 UI 框架文字;**`name.en` 必填**(§7)、其餘缺語系 → en)
"category": "basic", // 必須存在於 categories.json
"authors": ["<貢獻者>"],
"tokens": { "--color-primary": "#e8590c" }, // CSS custom properties 覆蓋(保留 token 除外)
"assets": { "brand-emblem": "assets/brand-emblem.svg", "bgm-home": "assets/home.ogg" }, // 已註冊 key → 主題內相對路徑或 null
"fonts": [
{
"role": "base",
"faces": [
{
"src": "assets/fonts/identity.woff2",
"weight": "100 900",
"style": "normal",
"license": "assets/fonts/OFL-1.1.txt",
},
],
},
],
"renderProfile": {
// 可省略;省略/無效=安全 default PBR
"version": 1,
"materialMode": "toon",
"toonSteps": 3,
"lighting": {
"ambientColor": "#bfd4e6",
"ambientIntensity": 1,
"keyColor": "#ffd1a3",
"keyIntensity": 1.6,
},
"stage": {
"groundColor": "#111820",
"surfaceColor": "#252d35",
"raisedColor": "#343e48",
"metalColor": "#77828d",
"accentColor": "#f26422",
"markerColor": "#f0e6d2",
},
},
}
5.1 Style API 與受控 CSS¶
styleApiVersion: 1 的公開 API 是 Angular 模板上的 [data-theme-part='…']。完整機器名錄只由 scripts/theme-css.mjs 維護,本檔只記穩定語意;增加、移除或更名 part 必須在同一正式 PR 原子更新 registry、production emitter、builtin theme、測試與規範,不能由單一主題私自要求。themes:validate 雙向檢查每個 registry part 至少有一個 production emitter,且每個 production literal emitter 都已註冊;掃描 Angular HTML、component host metadata 與封閉的 literal themePart input,排除 specs、fixtures、dist 與 generated。真正動態 emitter 必須提供封閉來源映射,不得以全面忽略放行。主題選擇不覆寫某個活 part 仍屬合法。
game-scene-decoration 是 backdrop 與功能內容之間、覆蓋完整場景且不接收輸入的主題裝飾層;garage-decoration 是對應的 Garage shell 全覆蓋、aria-hidden、pointer-events: none 非互動裝飾表面。兩者可承載 background、gradient、texture、mask 與 pseudo-elements,但不保證固定角落、邊框、位置構圖或具體幾何。Garage 的 stage-art/stage-vignette 維持核心結構層,不另公開專用 part。首頁 hero-art-surface 是 Hero artwork 的 viewport/clip surface;hero-art 才是實際圖像層。v1 名錄不包含 shell-accent、panel-corner 或 hero-art-frame,也不提供這些名稱的 alias。
app-backdrop 是所有路由唯一的固定 viewport 主題底層;公開頁、玩家頁與沉浸頁皆保留,頁面可用自己的不透明 DOM 背景、Canvas 或 Three.js 場景覆蓋。landing-info-surface 只負責首頁 Hero 下方資訊區的滿寬底色,不得替兩張資訊面板增加第三層外框。兩者的尺寸、stacking、pointer-event 與可存取性由共用層固定,主題只控制圖像、濾鏡、顏色與表面。
LOCAL 徽章是 local: 本機測試資產的共用語意標記,車位、Editor、零件 picker 與 Race Config
必須使用同一組 --o4-local-badge-* token;主題可改外觀但不得隱藏、改字或套到鏈上資產。
設定頁外層 tint 與 settings-shell/settings-navigation/settings-panel 的背景皆由主題控制;
共用層只負責內容填滿與互動。Default/ 月兔目前 tint = 0%、shell = 76–82%,局部控制表面
可維持 88–96%;其他主題可自行覆寫並接受 RWD/ 對比驗收,不需新增主題名稱專屬 class。
theme.css只可用已註冊的 stable part selector;可搭配元素、屬性、狀態 pseudo-class/pseudo-element 與:lang(),但不可選取 Angular/UI Kit 的內部 class,也不可用[class…]旁路。- 允許
@media、@container、@supports、@keyframes;作者提供的theme.css仍禁止@import、@font-face、未知 at-rule、!important與position: fixed。主題字型只能走下述結構化 manifest 契約,由 runtime 產生不可自行命名的@font-face。 url()只能引用同一主題已由 manifestassets或previewAsset註冊、位於assets/的相對路徑;禁止外部 URL、絕對路徑、data URL、query/fragment、跨主題與../。:scope只可宣告主題私有的--theme-*custom properties;主題 CSS 可讀 manifest token、共用 token 與自己的--theme-*,不得憑空依賴其他未註冊全域變數。- Root scope 由 runtime 自動包裝;主題檔不得自行依賴 theme id、
festival/default等 class 或ThemeServiceenum。 - CSS 可重排已公開 part 在既有容器內的視覺位置,但不得以隱藏、遮蔽、改寫閱讀順序或移出可達範圍的方式改變功能;觸控下限、focus、安全區、文件無水平溢位等仍由共用 safety layer 最終守門。
- Angular template 與 SVG 的結構、外部引用及重置頁例外只由 ui-frontend.md §3 定義;主題不得另開放 inline 幾何或資料 URL。
5.1.1 結構化主題字型¶
fonts可省略;只允許唯一的base、mono、display語意角色,每個角色含一個以上 face,單主題合計最多THEME_FONT_MAX_FILES = 4個 WOFF2、壓縮 bytes 合計最多THEME_FONT_MAX_BYTES = 524288(512 KiB),且仍計入 20 MB 主題總預算。- 每個 face 精確宣告
src、weight、style、license。src只能是同主題assets/下.woff2;license只能是同主題.txt且內容為 SIL Open Font License 1.1。這兩者由fonts直接形成 manifest 引用,不塞入需與 Default key 對齊的一般assets映射。 weight只收 1–1000 整數或遞增的"min max"range;style只收normal | italic。同角色、同 style 的 weight range 不得重疊;同一 WOFF2 不得重複引用。初版不開放作者自訂 family、src list、local()、unicode-range、variation setting 或 metrics override。- runtime family 固定為由 theme id+role namespaced 的全域名稱,產生
font-display: swap的@font-face;禁止外部、絕對、data、query/fragment、../、跨主題路徑與 font collection。字型 face 本身是 CSS 全域名稱,安全邊界靠不可碰撞的 runtime naming,而不是假設@scope能隔離 face。 base/mono分別映射既有--font-family-base/--font-family-mono,display映射--o4-display-font;另提供--theme-font-base/--theme-font-mono/--theme-font-display給 stable part 使用。自帶字型永遠排在既有 locale-aware stack 前面;缺 glyph、下載 404 或瀏覽器解碼失敗都回退既有字型,display未提供時回退base。- 主題提交不等待字型下載完成;首次啟用可發生受控 FOUT。字型失敗不得將整個主題標成
load-failed,也不得回退已成功提交的 stylesheet、token 或資產。
5.2 id 命名與生命週期¶
結構 = <slug>-<尾碼>:slug 為語意 kebab 名(作者自取、不要求唯一、系列慣例 <系列>-<年份>);尾碼為作者自產隨機 6 位 [a-z0-9]。
- 自動檢核(
themes:validate):格式正則^[a-z0-9]+(?:-[a-z0-9]+)*-[a-z0-9]{6}$+ 總長 ≤ 40——從字尾錨定,slug 長度不固定不影響檢核;default為唯一免尾碼保留 id。 - 唯一性保證鏈:硬保證 = 資料夾名即 id、重複 CI 必紅(100% 機械);尾碼隨機 = 讓撞名機率趨近零的慣例——「是否真隨機」不需檢核,撞了重產一個即可。
- 命名零仲裁:slug 不獨占(
dark-aaaaaa不擋dark-bbbbbb)→ 無搶名、無先到先得問題;review 僅審 IP/ 蹭名(與顯示名同標準)。id ⊥ 顯示名:好聽的名字放name(多語系、不要求全域唯一,藝廊以名稱 + 作者 + 分類消歧義)。 - 不可改、不重用:id 被 settings persist/ 社群討論 /git 歷史三處引用——改名 = 視為新主題;主題原則永久保留(歷史累積),僅授權 / 法律問題下架,其 id 登錄
themes/retired-ids.json永久退役、CI 拒絕重用(否則舊玩家 persist 設定會被偷換成不同主題);涉法律要求清除 git 歷史時走 GitHub DMCA 流程(repo 側機制,與 pinning provider 的 UGC DMCA 案件分屬兩層)。
5.3 車輛 renderProfile(僅顯示層)¶
renderProfile 只控制車庫展示、比賽 / 觀戰與離線縮圖的材質、燈光、背景 / 霧及可選描邊;改裝編輯器固定中性 PBR,避免風格化明暗遮蔽零件接點與材質判讀。完整契約如下:
version:正整數;只用於顯示快取失效。materialMode:pbr | toon;toonSteps可省略,僅允許整數2 | 3 | 4 | 5。outline可省略:enabled: boolean、color為#RGB/#RRGGBB/#RRGGBBAA、strength介於 0–5、thickness介於 0–4。lighting必填:ambientColor、keyColor為上述十六進位色;ambientIntensity、keyIntensity介於 0–4;rimColor/rimIntensity可省略,強度同為 0–4。environment可省略:backgroundColor、fogColor為上述十六進位色;fogNear/fogFar為非負有限數,兩者並存時必須fogFar > fogNear。stage可省略:groundColor、surfaceColor、raisedColor、metalColor、accentColor、markerColor皆為上述十六進位色;控制 Hemisphere ground、showroom/workshop/arena 舞台材質、分隔線、起點標記與 grid helper。缺項逐欄回退安全 Default palette,不得由presets.ts判斷主題 id。
manifest 缺少或任何欄位無效時,runtime 整份退回 default PBR,不做部分接受。描邊不受支援、建構 / 渲染失敗或 GPU 壓力時只降級為原材質模式直接渲染;Toon 主題仍可用,不因 Outline 失敗讓頁面失效。
此設定不上鏈、不是車輛資料,不得進 gameplay、CID、loadout hash 或版本六欄位協商。切換主題會重用既有 GLB/ 組裝快取,只更新 render view、舞台與帶 themeId + renderProfile.version 的縮圖快取 key。
5.4 賽內倒數與起跑視覺資產¶
網站主題可完整擁有賽內 3、2、1 與起跑效果,但不得改變倒數語意或正式 GO 時序。每個主題 使用下列八個 manifest 槽;default 必須完整,其他主題省略時依一般規則回退 default:
| 動態槽 | 靜態槽 | 內容 |
|---|---|---|
race-countdown-3 |
race-countdown-3-static |
數字 3 |
race-countdown-2 |
race-countdown-2-static |
數字 2 |
race-countdown-1 |
race-countdown-1-static |
數字 1 |
race-start |
race-start-static |
發令喇叭、煙火、彩炮等無語系起跑效果 |
- 全部使用 512×512、含 alpha 的 WebP。動態槽 2–18 幀、loop metadata 固定為 1;數字總時長 最多 1000ms、起跑最多 800ms,動態檔最多 768 KiB。靜態槽只能有一幀、最多 128 KiB。
- 3/2/1 可使用 0–9 例外;
race-start禁止 GO、其他文字、商標與浮水印。亮度變化不得在 一秒內形成超過三次閃光;起跑效果只允許單次明亮爆發。 - 動畫造型、粒子、速度、光影與緩動全部烘入 WebP;共用 CSS 只負責固定 HUD 位置、尺寸、
safe area、
object-fit與 z-index,不建立主題專屬 keyframes 或動畫 profile。 - effective reduced motion 直接選靜態槽。一般模式載入失敗依序嘗試目前主題動態、目前主題 靜態、default 動態、default 靜態,最後才顯示 DOM 數字/本地化 GO;重複 URL 去除。
- participant 與 spectator 各用自己的本機 active theme;圖片一律
aria-hidden,固定aria-live容器仍保留真實 3/2/1 與本地化 GO。每筆事件建立新的圖片世代,使後續回合 收到相同秒數仍從第一幀播放。 - 下載、解碼、播放與失敗降級都只是呈現,不得 await、延後或取消 match-start、race-ready、
secondsLeft === 0或 frame pump。可在進房或主題啟用時 best-effort 預載 bytes,但不得用 隱藏<img>預播動畫。
首批 default 與 moon-rabbit-workshop-2026-97c954 runtime 成品位於各自
assets/race-countdown/;提示詞、透明母圖、逐幀 PNG 與可重跑工程位於
美術資源/提示詞/賽內倒數與起跑動畫/、release-input/ui/race-countdown/ 及
美術資源/實際使用圖/賽內倒數與起跑動畫/;前者保存圖像 bytes,後者只保存受版控的設定與生成工具。
6. 資產解析與快取¶
- 解析順序:
themes/<選中>/assets/<key>→ 查無 →themes/default/assets/<key>;default 必須完備(全 token/ 資產 key 覆蓋,CI 驗證——它是 fallback 底)。音訊 key 例外:名錄必列、值可null= 該槽靜音;主題可寫null明確靜音蓋掉 default(§7、程式架構/audio-system.md §3)。 - SW 快取:default 的 stylesheet、一般資產、字型與授權檔列入 install 預快取;其他主題全部 cache-first lazy(選用時抓)——首載 bundle 不含非 default 主題資產,主題逐年累積不影響首載,repo 大小靠 per-theme 預算控(§7)。
- 升版後自癒:client 升版 =
CACHE_NAME換新、lazy 快取的非 default 主題被清——升版後首次啟動背景重跑setTheme(當前主題)補滿快取;離線且資產缺 → 該 session 暫以 default 呈現、不改 persistedthemeId(回線補抓後自動恢復)。 - 降級原因可見:設定頁主題區必須以目前語系顯示精簡警告,區分所選 id 查無(
unknown-id)、主題已退役(retired)與資源/樣式載入失敗(load-failed)。警告不得揭露內部例外;成功套用任一主題後立即清除。啟動時已發生的降級,以及設定頁內切換或重設造成的降級,都讀取ThemeService.fallbackReason的同一權威結果。 - 切換即時生效(CSS variables swap+ 資產 URL 重解析;BGM= 當前槽重解析、異檔即 crossfade,程式架構/audio-system.md §4),不需 reload;3D 場景經
ThemeServicetoken 鏡像同步(Three.js 不讀 CSS 變數,程式架構/themes.md §2)。
實作守門補充:正式主題名錄包含 default 與中秋「月兔工坊」;setTheme 使用遞增 request generation,只有最後一次請求可提交 token、persist 與音訊刷新,避免慢回應覆蓋玩家較新的選擇。SSR 與瀏覽器的主題根路徑都由 deployment basePath 推導;Angular 公開資產只複製 runtime manifest/ 圖像 / 音訊,不公開主題 .ts 或測試原始碼。
正式主題選單的 manifest 註冊表由 public/assets/themes/*/theme.json 自動生成;新增主題不手改 ThemeService。生成物內建完整 Default manifest(首啟 fallback)與非 Default 的小型選單摘要,不從 public/ 反向 import;WebP/SVG/ 音訊及非 Default 完整 manifest 仍依選用結果 lazy 載入。start 與 build 都會在 Angular 編譯前重建 registry 與 Default token SCSS,避免部署新 payload 搭配舊 bundle;themes:validate 仍以 --check 比對已提交生成物,防止 PR 漏列或手改漂移。
7. Schema 驗證(CI,pnpm run themes:validate)¶
- id 格式
^[a-z0-9]+(?:-[a-z0-9]+)*-[a-z0-9]{6}$+ 總長 ≤ 40(default免尾碼例外);資料夾重複 = 紅(§5.2) styleApiVersion必須是 runtime 支援版本;Default 的stylesheet必填,非 default 可省略;有填時必須是主題內安全.css相對路徑且檔案存在theme.css通過 Style API validator:只用已註冊 stable part、不得碰內部 class/ 危險 at-rule/!important/fixed 定位;URL 與 custom property 依 §5.1 白名單驗證- id 未列於
retired-ids.json(退役不重用) - 正式主題生成註冊表與所有非 default
theme.json一致(漏列 / 手改 / 排序漂移 = 紅) category存在於categories.json- default 主題 token/ 資產 key 完備——機器定義:程式碼引用集 ⊆ default 提供集(CI 掃描原始碼的
var(--*)與resolveAsset('key')字面值);其他主題 keys ⊆ default keys(未知 key = 錯字防呆、直接紅) name.en必填(fallback 鏈「缺語系 → en」的前提;與 i18n「en 缺 key 升 error」同哲學)- token 值禁含
url((資產一律走 assets 映射,防繞過資產隔離) - SVG 資產 sanitize:禁
<script>/ 事件屬性(on*)/ 外部引用——主題 SVG 為不可信來源,僅<img>/CSS url 引用、禁 inline(ui-frontend.md §3) - 音訊 key(
bgm-*/sfx-*):default 必列全部槽位、值可null(名錄完備、檔案可缺——程式架構/audio-system.md §6);槽位與保留清單權威為src/audio-system/slots.ts,保留槽出現於非 default 主題 = 警告(供檔會被忽略);音訊檔解碼煙測(ogg/opus) fontsschema、角色/face/descriptor 唯一性、4 檔/512 KiB 子預算、安全同主題路徑、檔案存在與 OFL 1.1 內容;WOFF2 須通過 signature、header 宣告長度、table directory/壓縮區段邊界及禁止 collection 的結構檢查,並在 CI 以 headless ChromiumFontFace.load()真實解碼,不能只驗wOF2magic bytes- 資產 key/token 引用一律字面值、禁動態組字串(lint;§7 完備掃描的前提,否則靜默漏報)
- manifest 引用的檔案必須存在;資料夾內每個檔案必須被 manifest 引用(防垃圾累積)
- 保留 token(
THEME_RESERVED_TOKENS)未被覆蓋 - 單主題大小 ≤
THEME_SIZE_MAX_MB(ui.md §14;BGM 為大頭) - 路徑越界(
../)擋下 - 官方預設主題另過 Lighthouse a11y 門檻(程式架構/seo.md §7)
8. 選用與 persist¶
- 設定頁「顯示」分類選主題(遊戲機制.md §9;
DisplaySettings.themeId,預設'default',程式架構/settings.md)。 - 本地 persist、不上鏈;域名遷移歸零重設(低價值類,部署資訊.md §8.1)。
- 主題藝廊:依分類分組 + 名稱 / 作者排序。
- persisted
themeId查無(主題已因授權 / 法律下架)→ 回default並提示(程式架構/themes.md §1setThemeguard;不留懸空狀態)。
9. 社群 PR 流程(同 語系清單.md §10 模式)¶
官方 runtime 的正式主題只能透過 Git PR 納入,並受 repository review、CI 與資產授權檢查約束。其他使用者自行 fork、修改且不送 PR 的版本不在官方審查、相容性承諾或 runtime 信任範圍內。
- Fork repo → 自產 id(§5.2:
<slug>-<6 位隨機尾碼>)→ 新增public/assets/themes/<id>/(theme.json + 可選 theme.css+assets) - 跑
pnpm run themes:validate - 提 PR → review(Style API/ 外部 URL 與內部 class 禁用 / 保留 token 尊重 / 視覺品質 /a11y 對比與鍵盤 focus/ 公開首頁、車庫、顯示設定、Race Config、Editor 五個代表頁的桌面、手機直向、手機橫向、高直向與超寬截圖(ui-frontend.md §14)/ 自帶字型的 OFL 檔、缺 glyph fallback、文字 overflow 與必要操作可達性 / 圖檔禁字:主題資產不得內含文字、數字與中立符號可(ui-frontend.md §16)/ 資產授權與大小:須為貢獻者原創或與專案 license 相容,並符合單主題預算;PR 模板要求聲明來源)
- merge → patch bump 隨版發佈
- 分類調整(新增分類 / 搬移主題)走同一管道
10. 跨模組對接¶
| 模組 | 內容 |
|---|---|
| 程式架構/themes.md | ThemeService/token 套用/fallback 解析/SW 快取/validate 實作 |
| 程式架構/settings.md | DisplaySettings.themeId(顯示分類) |
| 語系清單.md · 程式架構/i18n.md | 分類顯示名 dict themes.*;語系 × 主題正交 |
| 版本規範.md §3/§4 | 純資源 → patch;src/themes//public/assets/themes/ path 規則 |
| 美術資源.md | 預設主題視覺 = 現行設計系統(design-system) |
| 程式架構/audio-system.md | bgm-*/sfx-* 槽位名錄權威;音訊 key 三態(路徑/省略=fallback/null=靜音);保留 SFX 槽恆取 default |
| ui-frontend.md | UI 側銜接:o4-* 元件庫 = token 消費層(全站強制 = 主題覆蓋率保證)、token 命名慣例、build 生成 :root 基準、Three.js token 鏡像 |
| 美術資源/主題外觀與 RWD.md | Skin token/資產最小契約、頁面套用強度、Default/月兔方向、多比例 RWD 與代表頁驗收 |
| ui.md §14 | THEME_RESERVED_TOKENS/THEME_SIZE_MAX_MB/THEME_FONT_MAX_FILES/THEME_FONT_MAX_BYTES |