# 安立甘日課 PHP 重構版

由 Swift（SwiftUI iOS 應用）逐行移植的安立甘禮儀年曆引擎為核心，日課與教會年曆。

**無框架、無 Composer 依賴、無資料庫**，PHP 8.1+（用到枚舉與 `readonly` 語法）即可運行。

## 目錄結構

```
liturgy-php/
├── index.php                    # 總入口首頁（三系統入口；突出安立甘日課經；獨立、不讀取日課狀態）
├── anglicanoffice/              # 安立甘日課經主站（核心系統，見下）
│   ├── src/                         # 核心邏輯層
│   │   ├── bootstrap.php            # 統一載入入口（require 一次即可）
│   │   ├── helpers.php              # numberToChinese / getWeekdaySuffix / getWeekdayName / liturgyText / formatVerse
│   │   ├── LiturgicalSeason.php     # 節期枚舉（原 Swift 未附定義，依用法補全）
│   │   ├── LiturgicalRank.php       # 禮儀等級枚舉（原 Double 原始值均為整數，改用 int 枚舉）
│   │   ├── Models.php               # SeasonInfo / Feast / DailyLiturgy / TemporalDay
│   │   ├── Sanctorale.php           # 固定聖日資料庫（全年聖日表，同日多聖日）
│   │   ├── LiturgicalNameMapper.php # 中文名稱 → JSON 英文鍵名映射
│   │   ├── LiturgyCoreService.php   # 核心引擎：節期計算、聖日衝突裁決、早晚禱規則
│   │   ├── ViewHelpers.php          # 顯示層輔助：齋戒、顏色、節期標識、資料檔讀取
│   │   ├── BibleJSONService.php     # 聖經 JSON 解析服務（CUV / KJV / 次經）
│   │   ├── BibleSentencesLoader.php # 聖經選句載入器（按節期與主日標題）
│   │   ├── MemorialAntiphonsLoader.php # 季節／聖母紀念對經載入器
│   │   ├── PrimePrayerService.php     # 一時禱邏輯層（詩篇計畫、對經、季節判定）
│   │   ├── MinorHourPrayerService.php # 小時禱邏輯層（三／六／九時禱共用，依 hour 參數區分）
│   │   └── PatristicReadingService.php # 教父誦讀邏輯層（依節期／週次／星期對應 patristic 檔案）
│   ├── public/                      # 網頁入口（部署時可將網站根目錄指向這裡）
│   │   ├── index.php                # 主頁別名
│   │   ├── month.php                # 禮儀月表（?year=2026&month=12）
│   │   ├── api.php                  # JSON API（?date=… 或 ?month=YYYY-MM）
│   │   ├── layout.php               # 共用頁面骨架與樣式
│   │   ├── about.php                # 關於頁面
│   │   ├── settings.php             # 設置頁面
│   │   └── blog.php                 # 博客模組（列表＋單篇 ?post=slug；資料 data/blog_posts.json）
│   ├── components/                  # 日課各模組 UI 組件
│   │   ├── pre_office.php           # 預備禱文
│   │   ├── bible_sentences.php      # 聖經選句
│   │   ├── confession.php           # 認罪文、赦罪文、主禱文、啟應文
│   │   ├── venite.php               # 皆來頌與動態對經
│   │   ├── invitatory_hymn.php      # 邀請聖詩
│   │   ├── psalter.php              # 詩篇（多種誦讀表）
│   │   ├── lesson.php               # 第一/第二經課（由 $lessonNumber 控制）
│   │   ├── canticle_1.php           # 第一讚美詩
│   │   ├── canticle_2.php           # 第二讚美詩（以色列頌 / 歡呼頌）
│   │   ├── morning_hymn.php         # 早禱聖詩
│   │   ├── evening_hymn.php         # 晚禱日課聖詩（第一經課後；專用/平日 fallback）
│   │   ├── evening_canticle_1.php   # 晚禱第一頌歌：尊主頌（專用/週間對經）
│   │   ├── evening_canticle_2.php   # 晚禱第二頌歌（西面頌含對經 / 憐憫頌 / 心靈頌）
│   │   ├── patristic_reading.php    # 教父誦讀（第二頌歌後；無資料整段隱藏）
│   │   ├── biography.php            # 聖人小傳
│   │   ├── creed.php                # 信經（使徒 / 尼西亞 / 亞他那修）
│   │   ├── prayers.php              # 祈禱啟應（The Suffrages）
│   │   ├── memorial_antiphons.php   # 季節／聖母紀念對經
│   │   ├── general_prayers.php      # 通用祝禱（The Prayers）
│   │   ├── conclusion.php           # 結束祈禱（The Conclusion）
│   │   ├── st_patricks_breastplate.php # 聖帕特里克鎧甲歌（選誦）
│   │   ├── prime_shared.php           # 一時禱共用渲染函數（標題/啟應/對經/切換按鈕）
│   │   ├── prime_opening.php          # 一時禱：開端
│   │   ├── prime_hymn.php             # 一時禱：聖詩（季節結尾替換）
│   │   ├── prime_psalms.php           # 一時禱：詩篇（54 + 119 分段與季節對經）
│   │   ├── prime_athanasian.php       # 一時禱：亞他拿修信經（顯示/省略）
│   │   ├── prime_reading.php          # 一時禱：讀經（三選項）
│   │   ├── prime_responsory.php       # 一時禱：簡短啟應
│   │   ├── prime_prayers.php          # 一時禱：祈禱（顯示/省略）
│   │   ├── prime_collects.php         # 一時禱：祝文（第一式/第二式）與結束禱文
│   │   ├── prime_martyrology.php      # 一時禱：殉道錄、紀念亡者、禮成
│   │   ├── minor_shared.php           # 小時禱共用渲染函數（標題/啟應/對經/切換按鈕）
│   │   ├── minor_opening.php          # 小時禱：開端（禮規說明 + 開始啟應）
│   │   ├── minor_hymn.php             # 小時禱：聖詩（季節結尾替換；三時禱五旬節聖詩）
│   │   ├── minor_psalms.php           # 小時禱：詩篇（120-128，主日全唸平日輪唸，季節對經）
│   │   ├── minor_reading.php          # 小時禱：讀經（全年平日/主日與瞻禮日（慶節）/復活節期）
│   │   ├── minor_responsory.php       # 小時禱：簡短啟應（全年/慶節，慶節組復活期換復活組）
│   │   ├── minor_prayers.php          # 小時禱：祈禱（主日慶節八日慶期省略，顯示/省略）
│   │   ├── minor_collects.php         # 小時禱：祝文（本日祝文＋紀念祝文＋結束啟應）
│   │   ├── minor_closing.php          # 小時禱：結束經文與結尾
│   │   └── footer.php               # 通用頁腳版權
│   ├── offices/                     # 日課組合檔
│   │   ├── morning_prayer.php       # 早禱（已實作）
│   │   ├── evening_prayer.php       # 晚禱（已實作）
│   │   ├── prime_prayer.php         # 一時禱（已實作）
│   │   ├── terce_prayer.php         # 三時禱（已實作）
│   │   ├── sext_prayer.php          # 六時禱（已實作）
│   │   └── none_prayer.php          # 九時禱（已實作）
│   ├── docs/                        # 開發規範文件
│   │   └── style-guide.md           # 統一排版與元件樣式規範
│   ├── data/                        # JSON 資料檔（見下文）
│   │   ├── fixed_texts.json         # 固定禮儀文本（預備禱、認罪文、皆來頌等）
│   │   ├── invitatory_hymns.json    # 邀請聖詩資料庫
│   │   ├── morning_hymns.json       # 早禱聖詩資料庫
│   │   ├── evening_hymns.json       # 晚禱平日聖詩資料庫（主日至禮拜六，三語 en 待補）
│   │   ├── morning_sentences.json   # 早禱聖經選句
│   │   ├── evening_sentences.json   # 晚禱聖經選句
│   │   ├── memorial_antiphons.json  # 季節／聖母紀念對經資料
│   │   ├── psalms_db.json           # 詩篇正文資料庫
│   │   ├── prime_prayer.json        # 一時禱全部文本（三語，en 待補）
│   │   ├── terce_prayer.json        # 三時禱全部文本（三語，en 待補）
│   │   ├── sext_prayer.json         # 六時禱全部文本（三語，en 待補）
│   │   ├── nona_prayer.json         # 九時禱全部文本（三語，en 待補）
│   │   ├── martyrology/             # 殉道錄日條目（martyrologyMMDD.json，可多檔缺漏）
│   │   ├── psalm_schedules.json     # 詩篇誦讀表
│   │   ├── canticles.json           # 讚美詩資料
│   │   ├── sanctorale_index.json    # 聖日索引
│   │   ├── Sanctorale/              # 個別聖日專用文本
│   │   ├── patristic/               # 教父誦讀（patristic_{season}_{week}.json；缺檔整段隱藏）
│   │   ├── Temporal/                # 移動節期文本
│   │   ├── lectionary_1928/         # 1928 公禱書經課表
│   │   ├── lectionary_1943/         # 1943 經課表
│   │   ├── lectionary_1962/         # 1962 加拿大公禱書經課表
│   │   ├── CUV/                     # 聖經和合本 JSON
│   │   ├── KJV/                     # 英皇欽定本 JSON
│   │   └── APO1933/                 # 1933 次經全書 JSON
│   └── fonts/                       # 字型檔（EB Garamond、汇文明朝体備用）
├── dailyoffice/                 # 1928 年版《公禱書》日課增補本（靜態網頁，入口 index.html）
├── divineoffice-bcp79/          # 1979 年版《公禱書》日課（PHP，入口 index.php）
└── README.md
```

## 運行方式

```bash
# 本機開發（根目錄即可，index.php 為三系統總入口；anglicanoffice/index.php 依瀏覽器本地時間自動跳轉）
cd liturgy-php
php -S 127.0.0.1:8000
# 瀏覽器開啟 http://127.0.0.1:8000/

# 命令列直接使用核心引擎
php -r 'require "anglicanoffice/src/bootstrap.php";
$r = LiturgyCoreService::shared()->resolve(new DateTimeImmutable("2026-04-05"));
echo $r->mainTitle, PHP_EOL;'   # 輸出：復活日
```

部署到 Apache/Nginx 時，建議將文件根目錄指向專案根目錄（`index.php` 為三系統總入口）；若只暴露安立甘日課經主站，可指向 `anglicanoffice/public/`（網頁入口與 API）。

## 已實作功能

### 1. 教會年曆核心
- 完整節期計算：降臨期、聖誕期、顯現期、大齋期、聖週、復活期、升天期、聖靈降臨期、三一期
- 固定聖日資料庫（`Sanctorale.php`）：全年約 300+ 條聖日，含等級、八日慶期、望日
- 聖日與節期衝突裁決：等級比較、遷移、紀念、前夕晚禱規則
- 特殊規則：三一主日不紀念、聖靈降臨三日隔離、聖誕期主日遷移、望日提前至禮拜六等
- 齋戒判定與禮儀顏色輸出

### 2. 網頁界面
- 智能跳轉：依瀏覽器本地時間自動選擇日期與日課時段
- 七種日課切換：早禱、一時禱、三時禱、六時禱、九時禱、晚禱、寢前禱
- 多語言：繁體中文、簡體中文、英文，支援中英對照雙欄排版
- 主題切換：自動跟隨系統、明亮模式、黑暗模式
- 日期導航：前一日 / 後一日 / 日期選擇器
- 禮儀月表：整月每日主標題、顏色、等級、紀念、遷移
- 設置與關於頁面

### 3. 早禱日課模組（已完整串接）
按傳統順序組合以下組件：

1. `pre_office.php` — 預備禱文（可選省略）
2. `bible_sentences.php` — 聖經選句（聖日優先，節期回退）
3. `confession.php` — 認罪文、赦罪文（神職/平信徒版）、主禱文、啟應文
4. `venite.php` — 皆來頌與動態邀請選句
5. `invitatory_hymn.php` — 邀請聖詩
6. `psalter.php` — 詩篇
7. `lesson.php` — 第一/第二經課（由 `$lessonNumber` 控制）
8. `canticle_1.php` — 第一讚美詩
9. `morning_hymn.php` — 早禱聖詩
10. `canticle_2.php` — 第二讚美詩
11. `biography.php` — 聖人小傳
12. `creed.php` — 信經
13. `prayers.php` — 祈禱啟應
14. `collects.php` — 祝文（本日、求安、求恩、紀念）
15. `memorial_antiphons.php` — 季節／聖母紀念對經
16. `general_prayers.php` — 通用祝禱
17. `conclusion.php` — 結束祈禱
18. `st_patricks_breastplate.php` — 聖帕特里克鎧甲歌（選誦）

### 4. 詩篇系統
`components/psalter.php` 支援多種誦讀表：

| 模式 | 說明 |
|---|---|
| 月度循環 | 每月 1–30 日固定詩篇編排 |
| 專用詩篇 | 當日聖日或節期專用詩篇 |
| 1928 經課表 | 1928 美國公禱書日課詩篇 |
| 1943 經課表 | 持續安立甘教會通用經課表，分組輪替 |
| 1962 經課表 | 1962 加拿大公禱書日課詩篇 |
| 兩週循環 A/B | 兩週誦讀一遍詩篇 |

### 5. 聖經經文服務
`BibleJSONService.php` 提供：
- 根據書卷與章節範圍動態拼裝經文
- 支援跨章範圍（如 `5:20-7:1`）
- 支援中英聖經與次經（CUV / KJV / APO1933）
- 節號標紅、花括號轉斜體、頁邊註釋移除

## JSON API

| 請求 | 說明 |
|---|---|
| `public/api.php?date=2026-06-29` | 當日早禱裁決 |
| `public/api.php?date=2026-06-29&evening=1` | 當日晚禱裁決（含前夕晚禱規則） |
| `public/api.php?month=2026-12` | 整月每日裁決 |

返回欄位包括：`date`、`isEvening`、`seasonInfo`、`fasting`、`fileKeys`，以及 `liturgy` 下的 `mainTitle`、`color`、`rank`、`rankName`、`season`、`seasonName`、`commemorations`、`transferred`、`isFirstVespers`、`parentheticalCommemorations`。

## 可選資料檔（data/ 目錄）

對應 Swift 版從 Bundle 讀取的 JSON，改為放在 `data/` 下，存在即顯示、缺失自動略過：

- `fixed_texts.json` — 固定禮儀文本，包含預備禱、早/晚禱認罪文、皆來頌、主禱文、啟應文等
- `invitatory_hymns.json` / `morning_hymns.json` — 聖詩資料庫
- `morning_sentences.json` / `evening_sentences.json` — 聖經選句（按節期回退）
- `psalms_db.json` / `psalm_schedules.json` — 詩篇正文與誦讀表
- `sanctorale_index.json` — 聖日索引，用於查找 `Sanctorale/` 下的個別聖日檔案
- `Sanctorale/{key}.json` — 個別聖日專用文本（邀請選句、聖詩、詩篇、經課等）
- `Temporal/{season}{week}-{day}.json` — 移動節期文本
- `lectionary_1928/` / `lectionary_1943/` / `lectionary_1962/` — 三套經課表 JSON
- `CUV/` / `KJV/` / `APO1933/` — 聖經與次經 JSON（按 `{BOOKCODE}_{chapter}.json` 命名）
- `martyr_MMDD.json` — 殉道錄，如 `martyr_0629.json`
- `intro_{identifier}.json` — 節期/聖日介紹，identifier 由 `ViewHelpers::feastIdentifier()` 產生

日課/彌撒經文檔可按 `LiturgicalNameMapper::allFileKeys()` 返回的英文鍵命名。

## 開發進度

### ✅ 已完成
- [x] 教會年曆核心引擎與節期計算
- [x] 固定聖日資料庫（Sanctorale）
- [x] 聖日衝突裁決、紀念、遷移、前夕晚禱規則
- [x] JSON API（單日與整月）
- [x] 禮儀月表
- [x] 網頁主界面（日期導航、日課切換、語言切換、主題切換）
- [x] 早禱日課完整組裝（pre_office → general_prayers）
- [x] 聖經選句與經文 JSON 服務
- [x] 詩篇多模式誦讀表
- [x] 中英對照排版
- [x] 多語言國際化架構（zh-hant / zh-hans / en）
- [x] 聖人小傳模組
- [x] 祈禱啟應模組
- [x] 統一排版規範（docs/style-guide.md）
- [x] 祝文模組（Collects of the Day / Commemorations）
- [x] 聖人小傳特殊段落排版（subtitle / centered / source）
- [x] 信經與聖人小傳首字下沉規則
- [x] 通用祝禱獨立模組（位於紀念對經之後）
- [x] 結束祈禱模組（使徒禱文）
- [x] 聖帕特里克鎧甲歌選誦模組
- [x] 一時禱（Prime）完整模組
- [x] 三時禱、六時禱、九時禱（Terce / Sext / None）完整模組
- [x] 晚禱日課聖詩（第一經課後，專用／平日 fallback）
- [x] 晚禱第一頌歌（尊主頌，專用／週間對經）
- [x] 晚禱第二頌歌（西面頌含對經／憐憫頌／心靈頌）
- [x] 教父誦讀（按節期顯示，無資料自動隱藏）
- [x] 晚禱信經、祈禱（沿用早禱組件）
- [x] 晚禱祝文（祝文前啟應、本日／紀念／五旬節八日附加、晚禱版求安／求恩）
- [x] 晚禱季節／聖母紀念對經（切換鈕，早／晚禱共用）
- [x] 晚禱其他禱文（evening 版五篇）
- [x] 晚禱結束（結束祈禱、聖帕特里克鎧甲歌、晚禱結束詞）
- [x] 博客模組（兩篇文章：費舍爾與莫爾／依納爵·羅耀拉）

### 📝 開發日記（2026-09-14）

#### 1. 兩週循環B（Biweekly Psalter B）與小時禱循環詩篇
- 資料：`data/psalm_schedules.json` 新增 `biweekly_2`（用戶提供全文）——早禱／晚禱／一時禱（prime）／三時禱（terce）／六時禱（sext）／九時禱（nona）／寢前禱（compline）各兩週表，鍵為主日 0…禮拜六 6；全部鍵存在於 psalms_db（含 119 篇 8 節分段鍵 119_1_8 等）。默認仍為默認詩篇（月度循環／小時禱原計畫）。
- 早晚禱（`components/psalter.php`）：`biweekly_2` 由空殼改為實作（ISO 週數奇→week_1、偶→week_2，與兩週循環A同規則），按鈕沿用 `psalter_biweekly_2` 標籤（兩週循環B）。
- 小時禱（`components/minor_psalms.php`、`components/prime_psalms.php`）：新增「默認詩篇／兩週循環B」切換按鈕（樣式同 psalter 循環按鈕；`psalter_default` 新標籤），與早晚禱共用 `psalm_cycle` cookie；`none` 對應資料鍵 `nona`；選 B 時整個詩篇計畫替換（一時禱不帶詩篇 54 起唸，按 B 表 119 分段）。
- 特權日省略（`ViewHelpers::isPrivilegedPsalmDay`）：聖誕日及八日慶期（12/25–1/1）、復活日及八日慶期（Easter+0…7）、聖靈降臨日及八日慶期（Easter+49…56）、逾越三日慶典（Easter−3…−1）——早晚禱與小時禱一律不顯示兩週循環B按鈕；已選 B 則回退默認（月度／原計畫），該日按日課規程詩篇誦念。
- 寢前禱（`components/compline_psalms.php`）：同加入「默認詩篇／兩週循環B」切換（共用 `psalm_cycle`，特權日隱藏並回退固定詩篇 4/31/91/134）；拉丁副題原僅內建 4/31/91/134，其餘詩篇（6、7、10-17、34、91、133、134、137、138、140-142）改由 `psalms_db` 的 `latin` 欄位遞補（三語同填，因 `complinePsalmTitle` 依 currentLang 取鍵）。
- 驗證（寢前禱）：09-15（week_2 禮二）B＝詩篇 133/134＋拉丁 Ecce, quam bonum／Ecce nunc；09-16（禮三）＝137/138＋Super flumina；特權日（聖週五、復活日、五旬日、聖誕日、聖誕八日）B 鈕隱藏並回退 4/31/91/134；8 日期 × 雙設定 16 頁零錯誤。
- 驗證：2026-09-15（ISO 週 38 偶→week_2、禮拜二）——早禱 B 為詩篇 45/46/47＝表列；三時禱 75、六時禱 76、九時禱 82、一時禱 119:113-128 分段（無詩篇 54）；默認無參數時顯示默認計畫且 B 按鈕在列。特權日 12-25、12-28、01-01、04-03（聖週五）、04-05、04-12、05-24、05-31——早禱與三時禱 B 按鈕全隱藏；邊界日 12-24、01-02、04-13、05-23 按鈕恢復；聖誕日三時禱回退 120-128 默認計畫。12 日期 × 7 辦公強制 B 參數 HTTP 掃描（84 頁）零 PHP 錯誤。

#### 2. 聖日「通用日課＋專用覆蓋」合併機制（對應 Swift 加載邏輯）
- 背景：用戶更新聖日檔後，十月約 17 檔改為精簡格式（多僅含 collect，少數另有 office_hymn／nunc_dimittis_antiphon），以 `common_office` 欄位指向通用日課檔 identifier；九月 26 檔維持自足全量格式。PHP 原先只載入單一專用檔，`common_office` 無人引用，精簡檔聖日會整段缺漏（實測 2026-10-08 早禱僅 collect）。
- 引擎（`src/ViewHelpers.php`）：
  - `loadSanctoraleCommonOffice($identifier)`：掃描 `data/Sanctorale/` 非 `sanctorale_` 前綴檔案（19 個中文檔名通用檔），以 identifier 建單次請求靜態快取映射並載入；找不到回傳 null。
  - `mergeSanctoraleCommonOffice($sanctoraleData)`：有 `common_office` 時，對 morning／evening／vigil 逐區塊以通用檔為底、`array_replace` 專用鍵覆蓋（專用存在的鍵全量取代，缺鍵由通用補足）；無 `common_office` 或通用檔缺失時原樣返回。
  - `loadOfficeSection()` Sanctorale 分支改經合併後再按原邏輯取值（前夕晚禱 vigil 優先、禮拜六特敬聖母與 Temporal 回退不變）。
- 顯示層：7 個直接讀 Sanctorale 檔的元件（`morning_hymn`、`invitatory_hymn`、`venite`、`canticle_2`、`lesson`、`bible_sentences`、`psalter`）載入後統一過 `mergeSanctoraleCommonOffice`，保留各自原有查找與回退順序（Temporal 檔亦有 invitatory 鍵，不可直接換用 loadOfficeSection）。
- 資料面：無檔案改名；16 種被引用 identifier 全部有對應通用檔。已知待補：`sanctorale_1010_paulinus_of_york.json`、`sanctorale_1029_martyrs_of_uganda.json` 缺檔（index 已指向）。
- 「聖（某某）」佔位符替換：通用檔（聖婦用內／外、精修者主教外）含「聖（某某）」佔位符，合併後依當日聖人 `name` 產生短名替換——剷除教會聖師／大聖／聖婦／聖童貞／童貞女／精修者／殉道者／傳福音者／主教／院長／教宗／聖師／使徒／蒙福／真福／義者等稱謂（繁簡並列、長詞優先）、「錫耶納的」類地名前綴與結尾「日」，統一「聖XXX」形式（削去「聖」字的稱謂補回前綴；簡體補「圣」）。逐葉節點按語言碼選對應短名。
- 前夕晚禱（First Vespers）補丁：`bible_sentences.php`／`psalter.php` 原先用當日日期＋`mainTitle`（實為明日慶節）查 index 必然落空，退回通用經句／詩篇；改為與 `lesson.php` 一致——`isFirstVespers` 時以明日日期查找專用檔，且區塊鍵優先取 `vigil`（無 vigil 回退 evening）。`evening_canticle_1/2`、`evening_hymn` 本就經 `loadOfficeSection(effectiveDate, preferVigil)` 載入，對經無此問題。
- 多組祝文切換：`collect_of_the_day` 為 list 時（全庫 50 個區塊，三組如 0914 聖十字架日、兩組如 0908 聖母誕辰），`collects.php` 正規化為選項陣列，顯示 `option_label` 切換按鈕（默認祝文／又祝文／另一祝文；兩組則默認／另一），按鈕樣式與 psalter 循環按鈕一致（`--btn-container` 圓角容器、啟用項紅底白字 `--rubric-red`、透明未選、`renderButtonLabelHtml` 式雙語主上副下標籤），GET+cookie 參數 `collect_option`、fetch 局部重載模組，越界回退 0；單組維持原樣無按鈕。`minor_collects.php` 對 list 取第一組。修復前 list 型祝文整段空白（標題與正文皆無）。當日祝文下不顯示聖日／季節標題（`collect.title` 不渲染，標題僅保留於紀念祝文）；`minor_collects.php` 的本日祝文標題同時移除。
- 晚禱尊主頌省略啟應標籤：`renderCanticleResponsiveVerse` 新增 `$showLabels` 參數（預設 true 不影響早禱頌歌等），`evening_canticle_1.php` 頌歌正文與榮耀頌傳 false——啟／應紅色前綴移除，經文與 ※ 標記、對經維持不變。
- 祈禱模組啟應格式修正：`prayers_intro`（啟：願主與你們同在／應：願主與你的心靈同在）原先作純段落渲染，啟應前綴混在正文且「我們要禱告。」無啟標；改為逐行解析（支援 啟：/应：/℣/℟ 前綴），紅色啟／應標籤獨立行（同 collects 祝文前啟應格式），「我們要禱告。」歸啟列；主憐憫頌（求主憐憫等）維持置中段。早禱、晚禱、雙語（℣./℟. 標籤）均驗證。
- 前夕晚禱祝文：`loadCollects` 原先未傳 `preferVespers`／`effectiveDate`，First Vespers 晚禱以當日日期＋明日慶節名查 index 落空，誤用 Temporal 祝文；改為 `isFirstVespers` 時以 `+1 day` 日期取 `vigil` 區塊（與 evening_canticle_1/2 一致）。實例：0914 晚（七苦聖母前夕）現載入 0915 vigil 祝文。
- 驗證（多組祝文）：0914 早禱三按鈕（繁體 默認祝文／又祝文／另一祝文、簡體 默认祝文）且 `collect_option=0/1/2` 各渲染對應組、`=9` 回退 0；0908 早禱兩按鈕；0915 單組無按鈕；0914 晚（First Vespers）載入七苦聖母祝文；72 聖日 × 雙辦公＋47 前夕晚禱 HTTP 掃描零錯誤。
- 驗證：2026-10-08／10-01 早／晚禱補出通用 invitatory、office_hymn、psalm_antiphons、benedictus_antiphon、bible_sentences＋保留專用 collect（聖婦彼濟達／聖雷米吉烏斯）；10-07 晚禱保留專用 nunc_dimittis_antiphon；10-22（殉道者通用）、10-28（使徒通用）、11-01（諸聖）、10-31 諸聖望日 vigil 區塊正常；0912／0901 九月全量檔回歸不變（專用鍵全覆蓋）；9/1–11/30 逐日 CLI 掃描 loadOfficeSection 273 區塊（含 preferVigil）無警告、無「某某」殘留——僅降臨第一主日 Temporal 資料從缺（既有資料缺口，與本次無關）；72 聖日 × 早／晚禱 HTTP 頁面掃描＋5 日 × 雙辦公 × 三語（繁／簡／英＋對照）共 174 頁零 PHP 錯誤；佔位符替換後 10-08 繁簡頁面斷言「在聖彼濟達的隆重慶節中／在圣彼济达的隆重庆节中」渲染正確；前夕晚禱斷言——09-01 晚載入 0902 檔 vigil 選句「有福之人清早起來」、09-07 晚載入 0908 vigil 選句、09-20 晚（1962 循環）詩篇第十五／十九篇＝0921 vigil 詩篇而 09-21 第二晚禱為第三十七篇＝evening 詩篇、09-02 第二晚禱維持 evening 選句「寶座中的羔羊」；47 個前夕晚禱日期 HTTP 掃描零錯誤。

#### 3. 寢前禱（Compline）完整模組
- 邏輯層 `src/ComplinePrayerService.php`（對應 Swift ComplinePrayerData／ComplinePrayerViewModel）：季節詩篇對經（全年／降臨／聖誕／大齋／復活，顯現期與三一期歸全年通用）、經課（尾部書卷引用拆紅色小字）、簡短啟應（復活節期外／復活期，苦難期不唸榮耀頌禮規）、聖詩四選項（平日／慶節／大齋期／復活期，復活分支依升天／五旬節再選專詩）、繼抒詠（Easter+49…51 聖靈降臨三日）、聖聖詩季節結尾（與早／晚禱同一季節鍵表）、聖詩後啟應（普通／復活）、西面頌對經（與晚禱第二頌歌同一優先序，兜底 defaultNuncDimittisAntiphon）、祈禱顯示判定（主日／複式以上慶節／八日慶期省略）、認罪文＋赦罪文（會長）、祝文三選項（求護／聖安波羅修／希望；復活／升天預設希望）、紀念聖母與諸聖對經（復活期加哈利路亞）。不輸出 HTML。
- 資料檔 `data/compline_prayer.json`：用戶提供文本逐字保留（三語節點，en 待補），補 `office_title` 與 `ui`（啟應標籤、經課出處、主禱文、詩篇禮規與拉丁副題、切換標籤、省略註、結尾等）。
- 顯示層 `components/compline_shared.php`（reloadModule JS＋共用函數）與 12 段落元件，組裝檔 `offices/compline_prayer.php`；`index.php` 原路由 `office=compline` 直接生效。
- 切換參數：`compline_hymn`（weekday/feast/lent/easter）、`compline_responsory`（ordinary/easter）、`compline_collect`（protection/ambrose/hope）、`compline_prayers`（show/omit）——GET + cookie + fetch 局部重載。
- 純前夜不列年曆慣例不變；西面頌頌前、榮耀頌後各一對經。
- 驗證：場景斷言（主日省略祈禱／平日顯示、識別復活組、大齋聖詩、安波羅修祝文、復活日希望祝文、將臨／復活對經、繼抒詠、聖心季節結尾、顯現八日結尾＋中文序號保留）；33 日期 × 3 語言 × 雙語 99 連線掃描零 PHP 錯誤。

### 📝 開發日記（2026-08-27）

#### 1. 修復聖路易九日以色列頌對經
- `components/canticle_2.php` 的 `renderAntiphon()` 現在能正確讀取 `{"normal": {"zh-hant": "…", "zh-hans": "…", "en": ""}}` 嵌套多語言節點。
- 8 月 25 日聖路易九世頁面已可正確顯示以色列頌對經。

#### 2. 修復簡體中文聖經與次經路徑
- 新增 `BibleJSONService::setPathByLanguage($lang, $isApocrypha)`，自動根據語言選擇：
  - 簡體正典：`CUV_zh-hans/`
  - 簡體次經：`APO1933_zh-Hans/`
  - 其他：`CUV/` / `APO1933/`
- 修正 `components/first_lesson.php` 與 `components/second_lesson.php` 原本錯誤的 `CUV_Hans/`、`APO1933_Hans/` 路徑。
- 同時將 `BibleJSONService` 預設路徑從不存在的 `data/bible/` 改為 `data/CUV/`。

#### 3. 中英對照按鈕雙語顯示
- 將認罪文、皆來頌結尾、詩篇、第一/第二經課的選擇按鈕文本統一移入 `data/fixed_texts.json`。
- 新增按鈕雙語標籤 helper，中英對照模式下按鈕同時顯示主語言與副語言（如「認罪文 / General Confession」）。
- 移除 `first_lesson.php` / `second_lesson.php` 中硬編碼的 `$fallbackLec` 備用字典，達成「文本寫入 JSON，不寫在 PHP」的目標。

#### 4. 皆來頌 ※ 改為紅色
- `components/venite.php` 的 `$renderStanza()` 與 `$renderInvitatoryLine()` 現在會將 ※ 渲染為紅色，與詩篇一致。

#### 5. 補充以色列頌英文
- 在 `data/canticles.json` 的 `benedictus` 節點補充英文標題、副標題、10 段經文、頌榮（doxology）與平日對經（weekdayAntiphons）。

#### 6. 新增三部信經資料
- 在 `data/fixed_texts.json` 新增 `apostles_creed`、`nicene_creed`、`athanasian_creed`，各含繁中、簡中、英文的標題、禮規與段落。

#### 7. 第二頌歌標題精簡
- `components/canticle_2.php` 移除按鈕下方的具體頌歌名稱（以色列頌 / 歡呼頌），僅保留副標題（經文出處），避免與按鈕標題重複。

#### 8. 新增信經模組
- 新增 `components/creed.php`，並在 `offices/morning_prayer.php` 的第二頌歌後串接。
- 提供三個選擇按鈕：使徒信經、尼西亞信經、亞他那修信經，支援雙語並排與 AJAX 局部更新。
- 預設顯示使徒信經；在聖誕日、顯現日、復活主日、升天日、聖靈降臨日、聖三一主日，以及聖馬提亞、聖雅各、聖巴多羅買、聖馬太、聖西門與聖猶大、聖安德烈、施洗聖約翰等聖徒節日，自動切換為亞他那修信經。
- 八日慶期內不誦唸亞他那修信經，自動回退使徒信經。

#### 9. 信經英文首字下沉
- 亞他那修信經英文的 `W`（WHOSOEVER）、`A`（AND）、`F`（FURTHERMORE），以及使徒信經與尼西亞信經首段的 `I`（I BELIEVE）均設為紅色首字下沉（drop cap）。

### 📝 開發日記（2026-08-28）

#### 1. 第二頌歌禮規位置調整與新增
- 將通用禮規 `canticle_2_general_rubric` 移至頌歌選擇按鈕上方，順序為：標題 → 通用禮規 → 選擇按鈕。
- 通用禮規內容：
  - 繁中：¶ 在啓應後，應唸專用對經，然後唸此頌歌。季節與慶節中，對經可以在相應的專用或通用部分找到。
  - 英文：¶ After the ℣. and ℟., there is said the proper Antiphon, followed by this Canticle. In certain seasons and feasts, the Antiphon will be found in the appropriate Proper or Common, as indicated.
- 選擇歡呼頌時，在副標題「詩篇 100篇 | Psalm 100」下方顯示 `canticles.json` 內的專用禮規：「¶ 在平日，也可改唸歡呼頌。」/ "¶ Or, on ferial days may be said:"

#### 2. 第二經課宣告修正
- 將 `data/fixed_texts.json` 的 `second_lesson_reader_prefix` 中文由「第二經課，記載在：」改為「讀經員：」。
- 新增 `second_lesson_intro_format`（僅繁中、簡中），中文宣告統一使用「第二經課記載在%s %s。」。
- 英文宣告保留原有 BCP 風格："Here beginneth the ... chapter of ..."，不套用中文格式。

#### 3. 新增聖人小傳模組
- 新增 `components/biography.php`，在 `offices/morning_prayer.php` 中置於第二頌歌與信經之間。
- 新增 `ViewHelpers::loadBiography()`：優先從當日 Sanctorale 聖日檔案讀取 `biography`；聖日無資料則 fallback 到 Temporal 節期檔案。
- 若當日聖日與節期均無 `biography` 資料，則整個模組不渲染。
- 支援 `title`、`rubric`、`paragraphs`、`source` 多語欄位；`paragraphs` 同時相容純字串陣列與 `{type, text}` 物件格式。
- 當 `source` 欄位有內容時，於禮規正下方置中顯示來源說明；無內容則隱藏。
- 來源宣告不再帶「來源：」/ "Source: " 前綴，且與禮規段之間的間距統一為 12px，與其他模組的禮規說明保持一致。

#### 4. 新增祈禱啟應模組（The Suffrages）
- 新增 `components/prayers.php`，在 `offices/morning_prayer.php` 中信經之後顯示。
- 於 `data/fixed_texts.json` 新增 `prayers_title`、`prayers_rubric`、`prayers_intro`、`prayers_kyrie`、`prayers_lords_prayer`、兩種啟應對答陣列，以及選擇按鈕標籤。
- 中文提供兩種啟應翻譯：「1932 年公禱書」與「現代中文」，以紅底按鈕切換（URL 參數 `prayers_response`，並以 cookie 記憶），預設為 1932 年公禱書。
- 英文語境下不顯示切換按鈕，直接顯示 BCP 英文啟應。
- 中英對照時，主欄顯示中文啟應，副欄顯示英文啟應；啟應對答標示中文為紅色「啟：」/「應：」，英文為紅色加粗 ℣. / ℟.。 
- 主憐憫頌區塊改為置中對齊（含英文）。
- 引言維持居左對齊。
- 引言中的「啟：」/「應：」與英文 ℣. / ℟. 標示均改為紅色加粗。

### 📝 開發日記（2026-08-29）

#### 1. 建立統一排版規範
- 新增 `docs/style-guide.md`，整理全站元件樣式規則：模組標題、禮規、內文、啟應排版、按鈕、詩歌標題、英文首字下沉、空資料提示等。

#### 2. 排版統一化調整
- 禮規段落下邊距統一為 `12px`：`confession.php`、`venite.php`、`biography.php`、`canticle_2.php`。
- `venite.php` 結尾切換按鈕 active 狀態統一為紅底白字（`var(--rubric-red)` / `#ffffff`）。
- `canticle_1.php`、`canticle_2.php`、`prayers.php` 的啟應排版統一為 flex 獨立行，間距 `6px`。
- 英文首字下沉統一使用 `.en-drop-cap` class：`first_lesson.php`、`second_lesson.php`、`creed.php`。
- 雙語副標題統一使用 `bcp-en-title` class 與 inline 樣式。
- 邀請聖詩標題 `invitatory_hymn.php` 與早禱聖詩 `morning_hymn.php` 一致：紅色、斜體、粗體。
- `pre_office.php` 與 `bible_sentences.php` 模組補上 `margin-top: 32px`；`bible_sentences.php` 補上 `id="module-bible-sentences"`。

#### 3. 小傳來源宣告修正
- `components/biography.php` 移除「來源：」/ "Source: " 前綴；來源文字改為置中顯示。
- 統一禮規段與來源宣告的整體下間距為 12px，與其他模組禮規一致。
- `data/fixed_texts.json` 移除不再使用的 `biography_source_prefix`。

#### 4. 統一空資料提示
- `src/helpers.php` 新增 `renderEmptyMessage()` 輔助函式。
- `psalter.php`、`canticle_1.php`、`canticle_2.php`、`first_lesson.php`、`second_lesson.php` 全部改用統一空資料提示樣式。

### 📝 開發日記（2026-08-30）

#### 1. 以色列頌、摩西頌、安波羅修頌排版修正
- `components/canticle_2.php` 的以色列頌（Benedictus）改以散文式渲染，不再顯示「啟：」/「應：」或 ℣. / ℟. 標籤。
- `components/canticle_1.php` 的摩西頌（Cantemus Domino）、安波羅修頌（Te Laudamus）以及我祖頌（Benedictus es, Domine）同樣改以散文式渲染，不帶啟應標籤。

#### 2. 修正以色列頌對經錯誤套用主日對經
- 問題：`components/canticle_2.php` 在搜尋 Temporal 節期檔案時，使用過於寬鬆的 `temporal_{$sCode}_{$week}*.json` 等 pattern，導致週間平日（如三一主日後第十三主日禮拜四）錯誤讀取到同一主日禮拜日檔案（`temporal_trinity_13_sunday.json`）中的專用對經（如「我就是從天上降下來生命的糧…」）。
- 修正：
  - 限制 Temporal 對經搜尋僅使用「精確符合當日星期」或「無星期後綴整週」的檔案。
  - 排除含有其他禮拜日後綴的檔案，避免平日誤用主日對經。
  - 無精確對經時，正確回退至 `canticles.json` 的預設週間對經（如禮拜四的「主叫我們從仇敵手中被救出來…」）。
- 驗證 2026-09-03（三一主日後第十三主日禮拜四）不再顯示主日對經，2026-09-06（主日）仍正確顯示該主日專用對經。
- 啟句與應句連接為同一行，星號（※）後不換行；取消應句的 `font-weight: 500` 加粗。
- 首段僅於英文時套用 `.en-drop-cap`；中文維持正常排版；啟應句連接後的行間距改為與讚美頌一致（`margin-bottom: 2px`）。
- 以色列頌的榮耀頌（Doxology）同樣改為散文式、無啟應標籤。

#### 2. 主禱文首字下沉
- `components/confession.php` 與 `components/prayers.php` 的主禱文僅在英文時套用 `.en-drop-cap`；中文維持正常排版。

#### 3. 主日第一頌歌選擇按鈕
- `components/canticle_1.php` 主日邏輯改為顯示讚美頌 / 摩西頌 / 安波羅修頌三個選擇按鈕（原本僅聖日顯示），預設為讚美頌。

#### 4. 祈禱啟應加粗修正
- `components/prayers.php` 的啟應對答中，僅「啟：」/「應：」與 ℣. / ℟. 標示保持紅色加粗；啟句與應句正文取消加粗。

#### 5. 聖人小傳來源說明排版
- `components/biography.php` 的來源說明改為與正文相同排版，僅內容置中；不再使用較小字級或斜體等特殊樣式。

### 📝 開發日記（2026-08-31）

#### 1. 跨章與多段落經文排版修正
- `src/BibleJSONService.php` 的 `fetchScripture()` 回傳類型由字串改為段落 HTML 陣列。
- 修正跨章節範圍後接續節號的解析（如 `哈巴谷書 1:12-2:4,14` 中的 `,14` 現正確指向第 2 章 14 節）。
- 若引用以逗號分隔多段（如 `1:12-2:4,14` 或 `13:1-5,7-11`），每段獨立為一個段落；只有第一段首節省略節號，後續段落首節恢復顯示紅色上標節號。
- 更新 `components/first_lesson.php` 與 `components/second_lesson.php`，以迴圈渲染多個經文段落，並僅於首段套用英文首字下沉。

### 📝 開發日記（2026-09-01）

#### 1. 新增祝文模組
- 新增 `ViewHelpers::loadOfficeSection()`，從原有 `loadBiography()` 抽出「查找當日活躍日課檔案（Sanctorale → Temporal）」的邏輯，供 `loadBiography()` 與新模組复用。
- 新增 `ViewHelpers::loadCollects()`，對應 Swift `DashboardViewModel` 的 collects 邏輯：
  - 讀取當日祝文（`collect_of_the_day`）。
  - 讀取檔案內嵌紀念祝文（`morning.commemorations`）。
  - 從 `liturgy->commemorations` 經 `LiturgicalNameMapper` 解析後載入額外紀念祝文。
  - 合併後按 `rank` 降冪、名稱升冪排序；望日紀念自動退回 `vigil` 區塊尋找對經／短誦／祝文。
- 新增 `components/collects.php`：顯示當日祝文，以及各紀念的名稱、對經、短誦、祝文；支援雙語對照與英文首字下沉。
- 於 `data/fixed_texts.json` 新增 `collects_title`、`collects_rubric`、`collects_commemoration_label`、`collects_antiphon_label`、`collects_versicle_label`。
- 在 `index.php` 計算 `$collects`，並於 `offices/morning_prayer.php` 的第二頌歌與聖人小傳之間插入 `components/collects.php`。

#### 2. 修復 Temporal 檔案星期對應錯誤
- `ViewHelpers::loadOfficeSection()` 的 `$weekdayNames` 陣列原本為 `['monday', 'tuesday', …, 'sunday']`，但 `SeasonInfo::weekday` 是 `1=主日 … 7=禮拜六`，導致主日被對到 `monday`。
- 修正為 `['sunday', 'monday', 'tuesday', …, 'saturday']`，使 8 月 30 日（三一主日後第十三主日）正確載入 `temporal_trinity_13_sunday.json`，不再錯誤顯示「禮拜一」資料。
- 同時強化 Temporal 檔案搜尋順序：先嘗試 `temporal_{season_name}_{week}_{weekday}.json` 等精確命名，再 fallback 到較寬鬆的 pattern；完全符合當日星期的檔案優先排列。

### 📝 開發日記（2026-09-02）

#### 1. 聖人小傳特殊段落排版
- 根據 Swift `BiographyJSON.Paragraph` enum，擴充 `components/biography.php` 支援四種段落：
  - `text`：一般正文
  - `source`：紅色、居中、斜體、14px
  - `subtitle`：紅色、粗體、18px、上方留白
  - `centered`：居中正文
- 新增預設標題「聖人小傳」與預設禮規「¶ 在信經之前，誦讀以下聖人小傳。」，當 JSON 缺少時自動補上。
- 在段落後加入結束啟應「啟：求主憐憫。／應：感謝上帝。」。
- 於 `data/fixed_texts.json` 新增 `biography_default_title`、`biography_default_rubric`、`biography_ending_v`、`biography_ending_r`。
- 已驗證 9 月 12 日（聖母聖名日）正確渲染小標題「第二篇講道：論天使報喜」與居中段落「摘自聖伯爾納鐸院長的一篇講道」。

#### 2. 信經與聖人小傳首字下沉規則修正
- `components/creed.php`：
  - 使徒信經與尼西亞信經：僅第一段英文首字母下沉。
  - 亞他那修信經：第一段，以及以 `AND the Catholic Faith is this:` 和 `FURTHERMORE, it is necessary to everlasting salvation` 開頭的段落首字母下沉；其餘段落不套用。
- `components/biography.php`：僅第一段套用英文首字下沉，後續段落不套用。

#### 3. 開發復盤與優化
- 重構 `ViewHelpers::loadOfficeSection()`：
  - 新增靜態快取 `$officeSectionCache`，以 `(date|office|mainTitle)` 為鍵，避免同一頁面同時載入聖人小傳與祝文時重複搜尋檔案。
  - 將所有早期 `return` 改為寫入 `$result` 並統一快取後回傳，保留單一回傳點。
- 提取全域輔助函數到 `src/helpers.php`：
  - `liturgyText($node, $lang)`：安全取得多語節點文字，並 fallback 繁體中文。
  - `formatVerse($text, $markResponses)`：統一格式化禮儀經文（HTML 轉義、換行、`*`/`※` 轉紅色，可選啟/應/℣/℟ 紅色加粗）。
- 將 `components/collects.php`、`components/prayers.php`、`components/creed.php`、`components/biography.php` 內的重複 closure 移除，改為呼叫全域輔助函數，減少重複程式碼並避免未來不一致。
- 以 `php -l` 與本機 `php -S` 實際瀏覽 `index.php?date=2026-09-02&office=morning` 驗證，無 Fatal / Warning / Notice。

#### 4. 修正本日祝文重複與對經換行縮排
- `offices/morning_prayer.php` 原本在 `canticle_2.php` 之後與 `prayers.php` 之後各 `include` 一次 `components/collects.php`，導致「本日祝文」區塊出現兩次；已刪除第一次，保留第二次。
- 新增 `src/helpers.php::formatIndentedAfterColon()`：
  - 偵測第一個全形或半形冒號，將文字拆分為前綴與後綴。
  - 以 `inline-flex` 排列，使後綴換行時自動與冒號後第一個字對齊。
- 更新 `components/collects.php` 的 `renderAntiphon()`，對經文字透過 `formatIndentedAfterColon()` 渲染。
- 修正 `ViewHelpers::buildCommemorationFromOfficeData()`：解開 Sanctorale 檔案中 `benedictus_antiphon: { normal: { zh-hant: ... } }` 的包裝，使動態載入的紀念對經能正確顯示。
- 擴充 `formatIndentedAfterColon()` 支援傳入 `$prefixHtml`，讓「對經：」這類標籤也能套用相同的換行縮排；改用 `display: grid; grid-template-columns: auto 1fr`，使第一行盡量填滿，換行後準確對齊冒號後第一個字。
- 將相同排版套用到其他所有「對經：」開頭的渲染處：
  - `components/canticle_2.php`（以色列頌對經）
  - `components/psalter.php`（詩篇對經）
  - `components/venite.php`（皆來頌對經）
- 調整 `components/psalter.php` 對經位置：
  - 單首詩篇的對經（包含從聖日、季節 JSON 引入者）改放在詩篇拉丁文標題下方，再進入詩篇正文。
  - 多首詩篇共享同一對經時，維持在組首顯示，避免重複。

#### 5. 早禱固定祝文：求安、求恩
- 於 `data/fixed_texts.json` 新增：
  - `morning_collect_peace_title` / `morning_collect_peace_text`（求安祝文）
  - `morning_collect_grace_title` / `morning_collect_grace_text`（求恩祝文）
  - 同步提供繁中、簡中、英文。
- 於 `components/collects.php` 在本日祝文後、紀念祝文前固定渲染求安祝文與求恩祝文；僅於 `office === 'morning'` 時顯示。

#### 6. 通用祝禱（The Prayers / 祈禱）
- 於 `data/fixed_texts.json` 新增 `general_prayers_title`、`general_prayers_rubric` 與 `general_prayers` 陣列：
  - 收錄五段通用祝禱：為國家及政府、為聖品人暨會眾、為普天下人、總謝文、金口聖約翰禱文。
  - 每段以 `zh-hant` / `zh-hans` / `en` 三語節點儲存，`en` 採用 1928 BCP 文本。
  - 「為國家及政府」英文標題改為 `For our Country.`，兩段英文禱文中的 `The President of the United States` 改為 `our country`，以貼合通用國家祝禱語境。
  - 「為普天下人禱文」與「總謝文」中的可選段落標記（中文 `【…】`、英文 `[…]`）改以紅色顯示。
- 新增獨立模組 `components/general_prayers.php`（與啟應禱文 `components/prayers.php` 分開）：
  - 渲染模組標題、通用禮規、各段標題與段落。
  - 以 `¶` 開頭的段落（如 `¶ 或唸此文：` / `¶ Or this,`）視為禮規，以紅色斜體樣式渲染，不套用首字下沉。
  - 英文禱文段落自動套用 `en-drop-cap`，使每段首字母下沉。
  - 透過 `$colorOptionalBrackets()` 將全形 `【…】` 與半形 `[…]` 可選段落標記統一標為紅色。
- 於 `offices/morning_prayer.php` 將 `general_prayers.php` 放在 `memorial_antiphons.php` 之後。
- 驗證中文、英文、雙語模式皆正常顯示，無 Fatal / Warning / Notice。

#### 7. 結束祈禱（The Conclusion）
- 於 `data/fixed_texts.json` 新增：
  - `conclusion_title`：「結束祈禱 / The Conclusion」
  - `conclusion_rubric`：「¶ 以下文結束日課： / ¶ The Office always concludes in this manner:」
  - `conclusion_versicles`：三段啟應對答（願主與你們同在／我們要讚美主／願信友靈魂安息），含 `zh-hant` / `zh-hans` / `en`。
  - `conclusion_prayer`：使徒禱文正文（不含參考出處），含三語。
  - `conclusion_reference`：「（哥林多後書13:14） / 2 Cor. xiii. 14.」，含三語。
- 新增 `components/conclusion.php`：
  - 渲染標題、禮規、啟應對答、使徒禱文。
  - 英文使徒禱文套用 `en-drop-cap` 首字下沉。
  - 啟應標籤沿用全站 `v_label` / `r_label`，雙語模式下中英並列。
  - 使徒禱文後的聖經參考出處獨立渲染，採用與聖經選句一致的紅色斜體 14px 樣式。
- 於 `offices/morning_prayer.php` 將 `conclusion.php` 置於 `general_prayers.php` 之後。
- 驗證中文、英文、雙語模式皆正常顯示，無 Fatal / Warning / Notice。

#### 8. 聖帕特里克鎧甲歌（St. Patrick's Breastplate，選誦）
- 於 `data/fixed_texts.json` 新增 `st_patricks_breastplate`：
  - `title`：「聖帕特里克鎧甲歌 / St. Patrick's Breastplate」
  - `rubric`：「¶ 以下聖帕特里克鎧甲歌可選誦。 / ¶ The following St. Patrick's Breastplate may be said.」
  - `paragraphs`：七段歌詞，每段含 `zh-hant` / `zh-hans` / `en` 三語；中文段落開頭帶有「一、」「二、」…「七、」序號，且每一逗號後斷行。
- 新增 `components/st_patricks_breastplate.php`：
  - 置於 `offices/morning_prayer.php` 的 `conclusion.php` 之後，成為早禱最末可選模組。
  - 提供「誦念 / Recite」與「省略 / Omit」兩顆切換按鈕，預設顯示內容。
  - 支援雙語對照；英文第一段套用 `en-drop-cap` 首字下沉。
  - 中文序號排版與邀請聖詩一致：提取段落開頭「一、」等前綴，以紅色 `font-weight: 500` 懸掛於行首，內文與序號以 flex 並排。
- 驗證中文、英文、雙語模式皆正常顯示，無 Fatal / Warning / Notice。

#### 9. 早禱結束提示詞與頁腳版權
- 於 `data/fixed_texts.json` 新增 `morning_prayer_ending`：
  - 「早禱結束。 / Here endeth the Order of Mattins.」
- 於 `offices/morning_prayer.php` 最後渲染結束提示詞：
  - 文字置中，顏色與字級同禮規（紅色 14px）。
  - 雙語模式下主、副語言並列，副語言字級 0.85em。
- 於 `data/fixed_texts.json` 新增 `footer_copyright` 三語版權文字：
  - 繁中：「2026 ©️ 聖博德宣教中心 · 日課編輯與網頁設計：Fr Patrick Anthony Lim」
  - 簡中：「2026 ©️ 圣博德宣教中心 · 日课编辑与网页设计：Fr Patrick Anthony Lim」
  - 英文：「2026 ©️ the-mission-of-st-patrick · Daily Office editing and web design by Fr Patrick Anthony Lim」
- 新增通用頁腳 `components/footer.php`：
  - 單語時依 `$lang` 顯示對應語言版權。
  - 雙語時僅顯示英文版權說明。
  - 文字置中，上方 1px 邊框分隔，與主內容間距 24px。
- 於 `public/layout.php` 的 `renderFooter()` 中引入 `components/footer.php`，使所有使用該 layout 的頁面（index、about、settings、month）均自動帶出版權頁腳。
- 驗證中文、英文、雙語模式及各頁面均正常顯示，無 Fatal / Warning / Notice。

#### 10. 季節／聖母紀念對經
- 新增 `data/memorial_antiphons.json`：收錄 `seasonal_antiphons`（降臨期主日／週間、顯現期、七旬期、大齋期、復活期、三一節期主日／週間）與 `marian_antiphons`（救主之母、萬福天上母后、聖母喜樂經、又聖母經）。每條對經內容以 `zh-hant` / `zh-hans` / `en` 三語節點標記，`en` 預留空位，與其他聖日 JSON 格式一致。
- 新增 `src/MemorialAntiphonsLoader.php`：
  - 載入 JSON 並依目前節期解析對應的季節對經或聖母對經。
  - 支援 `seasonal` / `marian` / `omit` 三種選擇。
- 新增 `components/memorial_antiphons.php`：
  - 置於 `offices/morning_prayer.php` 的 `collects.php` 之後（即求恩祝文之後）。
  - 提供三顆切換按鈕；以 fetch 局部更新模組內容並同步 URL/cookie。
  - 渲染禮規、標題（聖母對經）、對經、啟應、祝文；對經沿用 `formatIndentedAfterColon()` 排版。
  - 於 `data/fixed_texts.json` 新增 `memorial_antiphon_title`、`memorial_antiphon_seasonal_rubric` 與三個選項標籤。
- 於 `src/bootstrap.php` 載入 `MemorialAntiphonsLoader.php`；於 `index.php` 解析 `$memorialAntiphonSelection` 與 `$memorialAntiphon`。
- 驗證 `index.php?date=2026-09-02&office=morning` HTTP 200，切換 `seasonal`/`marian`/`omit` 正常，無 Fatal / Warning / Notice。

### 📝 開發日記（2026-09-06）

#### 1. 一時禱（Prime）完整模組
- 邏輯層 `src/PrimePrayerService.php`（對應 Swift PrimePrayerData／ViewModel）：詩篇計畫、季節對經、聖詩季節結尾、祈禱顯示判定、讀經預設、簡短啟應選組、亞他拿修信經規則、殉道錄望日動態判定；不輸出 HTML。
- 資料檔 `data/prime_prayer.json`：全部文本以 `zh-hant` / `zh-hans` / `en` 三語節點收錄（en 待補），含 `ui` 標籤字典、`gloria` 榮耀頌、五期別對經（含 `full` 完整對經）、季節聖詩結尾。
- 顯示層 `components/prime_shared.php`（共用渲染函數＋`primeReloadModule` JS，GET + cookie 持久化、fetch 局部重載）與 9 個段落元件：開端、聖詩、詩篇、亞他拿修信經、讀經、簡短啟應、祈禱、祝文（第一式／第二式）、殉道錄＋紀念亡者＋禮成。
- 組裝檔 `offices/prime_prayer.php`；`index.php` 原已路由 `office=prime` 直接生效。
- 殉道錄：讀取 `data/martyrology/martyrologyMMDD.json`（缺檔跳過），12 條望日規則完全交由程式依當年曆法動態判定（遇主日提前一日），資料檔不寫死望日宣告；新增 `data/martyrology/_template.json` 範本。
- 切換參數：`prime_reading`（ordinary / feast / easter）、`prime_prayers`（show / omit）、`prime_collect`（1 / 2）、`prime_athanasian`（show / omit）。
- 驗證：多日期 × 三語 × 對照模式截圖確認（平日、主日、獻聖嬰日、聖母慶節、望日遞移），無 Fatal / Warning / Notice。

#### 2. 一時禱覆核修正（依用戶指示）
- 詩篇方案：每日以第 54 篇起唸（對經附於其前）；主日續唸 119:1-16、17-32、33-48 全六段，禮拜一／四 1-16、二／五 17-32、三／六 33-48。
- 對經期別修訂為五組（優先序）：聖母慶節 → 聖誕日至獻聖嬰日（12/25–翌年 2/2，獻聖嬰日不再視為聖母對經）→ 降臨期 → 大齋預備期與大齋期（自 Septuagesima，即 `daysFromEaster >= -63`）→ 復活期 → 全年通用；聖母判定改用標題關鍵字（馬利亞／聖母／童貞），移除月日特例。
- 詩篇 119 分段經節重複過濾修正：分段鍵（`119_1_8`…）即為分段內容，直接採用不再按節號截取（原邏輯會導致首段經文消失）。
- 亞他拿修信經：禮規（`ui.athanasian_rubric`）置於 顯示／省略 按鈕「上方」；預設改為 省略；顯示日規則不變（三一期各主日＋顯現期至 Septuagesima 前之主日）。
- 簡短啟應「應」文字不再加粗：`renderCanticleResponsiveVerse()` 新增 `$peopleBold` 參數，一時禱首先傳入 `false`。
- 驗證：162 組合掃描（3 日課 × 日期 × 3 語 × 對照）全數通過。

#### 3. 經課與聖經服務修正
- `data/lectionary_1928/1928_tr14-0-E.json` 第一經課更正為 **列王紀上** `22:10-18,29-37`（原誤作列王紀下並跨章標記；王上 22 章共 53 節，恢復同章省略式寫法）。
- `src/BibleJSONService.php`：`parseSegments()` 支援後段範圍明標章號（如 `22:10-18,23:29-37`）；空段落加 `error_log` 診斷。
- 驗證：2026-09-06 晚禱（1928 經課）王上 22:10-18（米該雅預言）＋ 22:29-37（亞哈陣亡）兩段落正確渲染。

### 📝 開發日記（2026-09-12）

#### 1. 博客模組（public/blog.php）
- 主頂欄「設置」前新增「博客」按鈕；模組沿用全站佈景（renderHeader/renderFooter、明暗模式）。
- 資料層 `data/blog_posts.json`：區塊式結構（p 段落／quote 引文／note 來源註〔含連結〕／image 圖片＋caption／footnotes 腳註），收錄用戶兩篇文章全文（聖約翰·費舍爾與聖托馬斯·莫爾／依納爵·羅耀拉），逐字自 thedailyoffice.app 拷貝，含粗體行內標記與 [1][2] 腳註標記。
- 圖片三張下載至 `public/blog/images/`（原 PNG 轉 JPEG q90：891KB→146KB、3.8MB→1.8MB）。
- 顯示層：列表（縮圖＋標題＋作者日期＋節錄卡片）；單篇（匯文明朝體深紅標題、紅色左線引文、紅斜體來源註、置中圖片＋說明、腳註清單、**粗體**支援）。
- 驗證：22 項連線斷言全過（列表兩篇、圖片、日期格式、兩文關鍵段落／引文／腳註／粗體、無效 slug 回列表、無 PHP 錯誤）；截圖確認列表、單篇、主頂欄按鈕位置。

#### 2. 日課日期改依「瀏覽器本地時區」判定
- 背景：伺服器設於美國，用戶本地已進入 12 號時，網頁「今天」仍跳服務器日期 11 號。
- 根目錄 `index.php`：① 智能跳轉條件由「date 與 office 皆缺」放寬為「缺任一即補齊」，跳轉腳本只補缺少的參數（office 依瀏覽器本地小時、時段不變）；② 頂欄「今天」按鈕改以 `goToLocalToday()` 以瀏覽器本地日期跳轉並保留 office／lang 等參數（原伺服器日期 href 保留作無 JS 退路）。
- `divineoffice-bcp79/index.php`：① 新增同款本地時區補齊腳本（缺 date／office 即補，office 5–11 時為早禱、其餘晚禱，與原 PHP 判定一致）；② 「今日」按鈕改以瀏覽器本地日期跳轉並保留目前 office。
- 驗證：headless Chrome 以 `TZ=US/Hawaii`（慢 1 日）與 `TZ=Pacific/Kiritimati` 兩種時區實測——兩站無參數進入皆顯示瀏覽器當地日期；Hawaii 13:32 時根目錄正確判為六時禱、1979 判為晚禱；顯式帶參數不重定向、無循環；兩站零 PHP 錯誤、日課模組回歸正常。

#### 3. divineoffice-bcp79 手機版頂欄改隨頁滾動
- 原 `@media (max-width:768px)` 僅把頂欄改直排但仍 `position: fixed`，大標題與按鈕常佔畫面頂部。改為手機版 `.top-nav { position: static }`（隨網頁滾動），`#content-frame` 對應改 `margin-top: 0; height: 100vh` 回到文件流；桌面版（>768px）維持 fixed 不變。
- 驗證：420px 截圖見標題→日期→按鈕→iframe 自然排列可滾走；1200px 桌面版面不變；iframe 內文 420px 寬正常換行（與獨立開啟 morningprayer.php 逐行一致）。
- 實機回饋修正：模擬 iPhone 390×844 量測 `getComputedStyle` 確認手機寬度下頂欄確為 `static`、可隨頁滾動；實機未生效經排查為**手機瀏覽器快取舊頁**（或誤開桌面版網站使視口變 980px＞768 斷點），已加 `Cache-Control: no-store` 等 no-cache meta 防止舊版面殘留。
- 雙層滾動修正：原手機版 iframe 固定 `100vh` 致「外層頁面＋iframe 內部」兩條滾動軸。改為同源 JS 自動把 iframe 撐至內容實高（`load`＋延遲 300ms 校正＋`ResizeObserver` 監看內容變動；轉桌面寬度時清除行內高度恢復 CSS），全頁單軸滾動。驗證：手機寬度 `innerScroll=false`、外層文件高 = 頂欄＋內容全高；桌面版維持 iframe 內滾不變。
- 依用戶指示：安立甘日課經主頂欄移除「美國公禱書日課」按鈕（入口頁後續改為根目錄 `index.php`，見 2026-09-12 第 4 點）。

#### 4. 目錄重組：安立甘日課經歸入 `anglicanoffice/`，首頁改版
- 用戶將所有安立甘日課經相關檔案移入 `anglicanoffice/`，與 `dailyoffice/`、`divineoffice-bcp79/` 同級；三套日課系統各自獨立、互不影響。
- `portal.php` 刪除，改以根目錄 `index.php` 作為三系統總入口：
  - 視覺絕對突出「安立甘日課經」（深紅漸層大卡＋大白膠囊按鈕）。
  - 「美國公禱書日課」保留於下方，以白底小卡呈現，降低視覺比重。
- 將安立甘日課經主頂欄的「博客」按鈕移除，改置於根入口頂欄主菜單（連結 `anglicanoffice/public/blog.php`）。
- 更新 README 目錄結構與部署說明，使其反映 `anglicanoffice/` 新位置。
- 驗證：根入口連線四連結全過（安立甘主站、1928、1979、博客）；手機 390×844 與桌面 1280×900 截圖確認版面；安立甘主頂欄博客按鈕已移除；零 PHP 錯誤。

### 📝 開發日記（2026-09-11）

#### 1. 美國公禱書日課入口首頁（portal.php）
- 用戶加入兩套已編輯完成的獨立日課系統：`dailyoffice/`（1928 年版《公禱書》日課增補本，靜態網頁）與 `divineoffice-bcp79/`（1979 年版《公禱書》日課，PHP）。
- 新增 `portal.php` 作為兩套日課的統一入口（後續已整併為根目錄 `index.php`，見 2026-09-12 第 4 點）：沿用全站佈景主題（`renderHeader`／`renderFooter`、明暗模式），兩張系統卡片（1928 增補版：早禱／晚禱／寢前禱／一時禱／三時禱／亡者日課；1979 版：早禱／晚禱、依時自動判斷）＋「← 安立甘日課經」回鏈。
- **獨立性保證**：入口頁不讀取、不寫入任何日課狀態（`date`／`office`／`lang`／切換 cookie 一律忽略，已驗證帶參數存取無異）；兩套子系統各自獨立目錄與內部連結，互不改動。
- 安立甘日課經主頂欄僅新增一個「美國公禱書日課」導航按鈕（`index.php`），原有功能零變動。
- 驗證：入口頁／主頁／1928 index.html／1979 index.php 及子頁（matins／vespers／compline／morningprayer／eveningprayer）連線全過、無 PHP 錯誤；截圖確認入口版面與主頂欄。
- 後續修正（依用戶指示）：① 修復 `dailyoffice/index.html` 全部按鈕失靈——根因為 `function 1979bcpmp()`／`1979bcpep()` 以數字開頭的非法識別字令整個 `<script>` 編譯失敗（非路徑問題），並順應要求移除 1979 年公禱書段落與按鈕（含外站連結）；node 語法檢查＋headless Chrome 函式存在性診斷 8/8 全數定義。② `portal.php` 精簡：移除英文副標題與兩卡「內容」清單，改為單顆膠囊式「進入日課」按鈕（暗色模式另有配色）。

### 📝 開發日記（2026-09-08）

#### 1. 晚禱祝文（祈禱後）
- `components/collects.php` 擴充為早／晚禱共用，依 `$office` 分支：
  - **晚禱禮規**（新鍵 `collects_rubric_evening`）：「¶ 此後，誦唸本日祝文，然後接著誦唸合時的紀念祝文；然後以下面兩篇祝文作為結束。」
  - **祝文前啟應**（晚禱專用，對應 Swift 祝文前啟應）：啟：願主與你們同在。／ 應：願主與你的心靈同在。／ 啟：我們要禱告。（僅啟無應；新鍵 `collects_prelude_v1/r1/v2`）
  - **順序**：禮規 → 祝文前啟應 → 本日祝文 → 紀念祝文 → 五旬節八日附加祝文 → 求安祝文 → 求恩祝文（晚禱固定兩篇置於紀念祝文之後，與早禱「求安／求恩在紀念祝文之前」不同；`isEveningOffice` 分支各排其序）。
  - **五旬節八日慶期每日附加祝文**（對應 Swift `shouldShowPentecostOctaveAppendix`，`mainTitle` 六標題精確匹配：聖靈降臨後一／二日、八日慶期內禮拜三／四／五／六）：新鍵 `evening_pentecost_octave_title/text`。
  - **晚禱固定祝文**（新鍵 `evening_collect_peace/grace_title/text`，文本取自 Swift `evening_prayer_data_zh-Hant/zh-Hans`，zh-hans 以 ICU Hant-Hans 轉簡）：求安「上帝啊，一切潔淨的心願…」、求恩「求主發光明…」；早禱固定祝文維持 morning 鍵不變。
- fixed_texts.json 新增 10 個晚禱鍵（105 鍵）。en：啟應沿用 BCP 慣用英譯，晚禱固定祝文／附加祝文 en 留空待補（Swift 無 en 資料檔）。
- 驗證：晚禱 18 項斷言全過（禮規、祝文前啟應三句、本日祝文、晚禱版求安／求恩文本、早禱版文本隔離、五旬節八日〔05-25〕附加祝文標題與文本、zh-hans 全套轉簡、模組內順序）；早禱回歸 6 項全過；220 連線大掃描（55 日期 × 早／晚 × 雙語）零 PHP 錯誤；截圖確認版面與紅色啟應標籤。
- 已知資料缺口（非本次回歸）：Temporal 資料檔僅覆蓋復活至降臨段＋主要聖日，將臨／聖誕／顯現等期日 `loadOfficeSection` 回傳 null 時祝文模組整體隱藏（含固定祝文），早禱一向同此行為；其餘靜態結尾模組不受影響照常顯示。

#### 2. 晚禱季節／聖母紀念對經（求恩祝文後）
- `components/memorial_antiphons.php` 放寬為早／晚禱共用（原 morning-only 閘門改為 morning＋evening）；`MemorialAntiphonsLoader::resolve` 本為節期／日期導向、日課無關，直接沿用；切換鈕（季節對經／聖母對經／省略，GET+cookie+局部重載）兩日課各自獨立運作。
- 掛入 `offices/evening_prayer.php`（collects 之後），對應 Swift `EveningPrayerView` memorialAntiphonSection（結構與早禱相同：seasonal/marian/omit 三態，禮規＋對經＋啟應＋禱文）。
- 驗證：晚禱 6 項斷言全過（模組存在、季節對經內文與 data 檔一致、聖母對經切換與隔離、zh-hans 按鈕、平日鍵、collects→對經順序）；早禱回歸不變。

#### 3. 晚禱其他禱文（紀念對經後）
- 早／晚禱五篇文本不同（「為國家及政府」全文各異〔早禱 330 字／晚禱 187 字〕；其餘四篇晚禱作「無所不能」、早禱作「無所能」），`fixed_texts.json` 新增 `general_prayers_evening`（五篇 trilingual 節點，取自 Swift evening_prayer_data_zh-Hant/zh-Hans；標題 en 沿用早禱版，正文 en 留空待補）；`components/general_prayers.php` 依 office 取鍵，其餘渲染邏輯（五篇全列、總謝文禮規、¶ 禮規段判定）不變。
- 驗證：晚禱 evening 版文本 5 項、早禱 morning 版隔離 2 項、zh-hans 1 項全過。

#### 4. 晚禱結束（其他禱文後）
- `offices/evening_prayer.php` 續接 `components/conclusion.php`（結束祈禱：三啟應＋使徒禱文＋林後 13:14 出處；早／晚禱文本相同，直接共用）、`components/st_patricks_breastplate.php`（鎧甲歌；Swift 兩日課文本逐字相同）、`components/morning_prayer_ending.php`（泛化為日課無關：依 office 取 `morning_prayer_ending`／新鍵 `evening_prayer_ending`「❦ 晚禱至此結束。」，模組 id 改為 `module-{office}-prayer-ending`，早禱 id 維持不變）。
- 對應 Swift `endingSection`：endingResponses → 使徒禱文 → 聖帕特里克鎧甲歌（誦讀／省略切換）→「❦ 晚禱至此結束。」
- 驗證：晚禱模組鏈 6 連塊存在且順序正確（collects→紀念對經→其他禱文→結束祈禱→鎧甲歌→結束詞）；結束三啟應、使徒禱文、鎧甲歌內文、結束詞斷言全過；早禱結束詞回歸；zh-hans 全過。
- **晚禱（Evening Prayer）至此全模組完成**（pre_office → 結束詞）。

### 📝 開發日記（2026-09-07）

#### 1. 三時禱、六時禱、九時禱（小時禱）完整模組
- 邏輯層 `src/MinorHourPrayerService.php`：三個日課共用一套邏輯，`MinorHourPrayerService::shared('terce'|'sext'|'none')` 依小時載入對應 JSON；對應 Swift MinorHourPrayerData／MinorHourPrayerView 的全部判定。
- 資料檔 `data/terce_prayer.json`、`data/sext_prayer.json`、`data/nona_prayer.json`：用戶提供文本原樣保留（逐鍵比對零變動），各補上 `office_title`、`ui`（章節標題、禮規、按鈕標籤，en 待補）、`gloria` 三區塊。
- 移植規則：詩篇（三時 120-122、六時 123-125、九時 126-128；主日三篇全唸，平日一／四首篇、二／五次篇、三／六末篇）；對經五期別（聖母慶節 → 降臨期／聖誕期／大齋期（自 Septuagesima）／復活期 → 全年通用）；聖詩季節結尾（聖誕至獻聖嬰、顯現八日、復活、升天、聖心、易容、基督君王、聖母）；三時禱五旬節週（Easter+49…55）整首換 *Veni, Creator Spiritus* 並顯示拉丁題名；讀經三選項（復活節期→easter；主日與慶節→feast〔三時作「瞻禮日」，六、九時作「慶節」〕；其餘→ordinary）；簡短啟應（慶節組於復活期自動換復活組）；祈禱（主日、複式以上慶節、八日慶期〔等級 ≥ 60〕預設省略）；祝文（本日祝文＋紀念祝文：三時用 `dailyCollectText`、六時用 `sextMemorialCollect`、九時用 `nonaMemorialCollect`）。
- 顯示層 `components/minor_shared.php`（＋`minorReloadModule` JS）與 8 個段落元件（開端／聖詩／詩篇／讀經／簡短啟應／祈禱／祝文／結束），組裝檔 `offices/terce_prayer.php`、`sext_prayer.php`、`none_prayer.php`。
- 切換參數依日課獨立命名：`{terce|sext|none}_reading`、`_responsory`、`_prayers`（GET + cookie + fetch 局部重載）。
- 驗證：90 連線掃描（3 日課 × 10 日期 × 3 語言）零錯誤；32 項場景斷言全過（含主日三篇／平日單篇、省略提示、五旬節聖詩、四季對經、聖母對經〔含禮拜六特敬聖母〕、三份紀念祝文、切換覆核、簡體、雙語）；截圖確認版面。

#### 2. 晚禱日課聖詩（第一經課後）
- 新增 `data/evening_hymns.json`：平日聖詩 8 首（主日至禮拜五＋禮拜六兩季節變體），zh-hant 與 Swift 原版逐字比對零差異；zh-hans 以 Swift 同款 `Hant-Hans`（ICU）引擎轉簡，en 留空待補；結構同 `morning_hymns.json`。
- 新增 `components/evening_hymn.php`，掛於 `offices/evening_prayer.php` 第一經課之後；選詩規則與早禱一致：
  1. 專用：Sanctorale／Temporal 專用 JSON 的 `evening` 區塊（`office_hymn` 內嵌或 `office_hymn_key` 引用）；前夕晚禱以明日日期查找、`vigil` 區塊優先。
  2. 禮拜六特敬聖母專屬聖詩（`saturday_bvm.json` evening／vigil 區塊）。
  3. 平日 fallback：按星期取鍵；禮拜六 `saturdayTrinity`（缺則 `saturdayEpiphany`），與 Swift 相同。
- `src/ViewHelpers.php`：`loadOfficeSection()` 新增向後相容參數 `$preferVigil`（Sanctorale 與 Temporal 兩支皆支援 vigil 優先，現有呼叫者零影響）。
- 渲染沿用早禱聖詩元件排版：拉丁題名紅色斜體、中文數字紅色懸掛縮排、雙語欄、啟應文（℣／℟）。
- 驗證：10 項場景斷言全過（平日、主日、禮拜六、特敬聖母、前夕 vigil 詩、聖母誕辰第二晚禱、升天節 Temporal 專用、簡體、雙語、啟應文）；66 連線掃描（22 日期 × 3 語言）零錯誤；早禱／一時禱／小時禱回歸零錯誤；截圖確認 第一經課 → 日課聖詩 順序與版面。

#### 3. 晚禱第二頌歌（第二經課後）
- 新增 `components/evening_canticle_2.php`，掛於 `offices/evening_prayer.php` 第二經課之後；三選一切換（`evening_canticle_2`，GET + cookie + fetch 局部重載）：**西面頌**（預設，路加福音 2:29-32，顯示對經，頌前頌後各一遍）、**憐憫頌**（詩篇 67）、**心靈頌**（詩篇 103）；後兩者禮規「¶ 或唸此詩篇。」，不帶對經。文本沿用 `data/canticles.json` 既有三語節點，並補上三首各自的 `rubric`（en 依用戶提供原文收錄）。
- 西面頌對經優先序（對應 Swift `secondCanticleAntiphon`）：① 基督聖體節至其八日慶期前夕晚禱（Easter+60…67，聖心節前夕除外）硬編碼聖體對經 → ② Sanctorale／Temporal 專用檔 `nunc_dimittis_antiphon`（前夕晚禱以明日日期查找、vigil 優先）→ ③ 諸聖日專用 → ④ 節期回退（將臨／聖誕／顯現八日／大齋一二週／大齋三四週／苦難期與聖週／復活／升天／聖靈降臨／三一）→ ⑤ 全年通用；硬編碼回退表附 zh-hans（ICU Hant-Hans 轉簡），en 待補。
- `src/ViewHelpers.php` `loadOfficeSection()` Temporal 分支修正（對照 Swift `DailyOfficeLoader`）：新增 dfe 固定節日檔查（`loadTemporalFixed` 同款：聖灰日、聖週各日、復活各主日、祈求日、升天、聖靈降臨、三一主日、基督聖體節、耶穌聖心節等）；每週檔案 glob 結果過濾為「精確符合當日星期」或「無星期後綴」，杜絕同週其他日子對經／聖詩錯套（例：三一主日不再吃到基督聖體節週五檔的對經）。
- 驗證：34 項斷言全過（預設西面頌＋對經×2、憐憫頌／心靈頌切換無對經、15 個節期對經案例〔含聖體節硬編碼、聖心節前夕排除、三一主日、聖週、前夕 vigil 專用、聖母對經〕、簡體對經轉簡、英文禮規、雙語）；204 連線大掃描（17 日期 × 3 語 × 4 狀態）零錯誤；早禱／一時禱／三時／六時／九時與晚禱聖詩回歸全過；截圖確認 第二經課 → 第二頌歌 版面。

#### 4. 晚禱第一頌歌（日課聖詩後、第二經課前）
- 新增 `components/evening_canticle_1.php`，固定 **尊主頌**（路加福音 1:46-55，無切換），掛於 `offices/evening_prayer.php` 日課聖詩之後、第二經課之前；文本沿用 `data/canticles.json` 既有 `magnificat` 三語節點。
- 對經規則（對應 Swift `benedictusAntiphon(isEvening: true)`，與早禱同一優先序）：① 對應聖日／季節 JSON 專用檔 `benedictus_antiphon` 優先——**前夕晚禱讀 `vigil` 區塊、晚禱讀 `evening` 區塊**（以明日日期查找，經 `loadOfficeSection` 統一解析，含禮拜六特敬聖母）；`normals` 陣列按年份輪替（`year % count`）、`normal` 固定對經。② 無專用對經回退 `canticles.json` 平日週間對經（鍵 1…5，僅禮拜一至五；主日／禮拜六無對經，除非專用檔提供）。對經於頌前、榮耀頌後各顯示一遍。
- 驗證：18 項斷言全過（模組順序 聖詩→第一頌歌→第二經課→第二頌歌、平日週四週間對經、主日 Temporal 專用對經〔十四主日十潔淨者〕、大齋期禮拜六無對經、09-07 前夕 vigil 專用、09-08 正日專用、禮拜六特敬聖母 normals 輪替、五旬節專用、簡體、英文、雙語）；120 連線大掃描（20 日期 × 3 語 × 2 狀態）零錯誤；早禱／一時禱／三時與晚禱第二頌歌回歸全過；截圖確認版面。

#### 5. 排版規則統一：啟應「應」後正文不加粗；晚禱第二頌歌取消啟應標籤
- 依用戶指示定為全局規則：`renderCanticleResponsiveVerse()` 的 `$peopleBold` 預設值改為 `false`，早禱／晚禱各頌歌、信經啟應等所有呼叫點一律生效（紅色「啟／應」標籤本身保留粗體）。
- 晚禱第二頌歌（西面頌／憐憫頌／心靈頌）依用戶指示與 Swift `canticleVerseRow` 同款改為**一般排版**：頌文與榮耀頌均不顯示啟／應標籤，啟、應兩行以普通段落連排（`$renderPlainVerse`），※ 標記照舊轉紅；對經、禮規、切換鈕不變。第一頌歌（尊主頌）維持啟應式不變。
- 其餘啟應渲染器（`prayers.php`、`conclusion.php`、`formatVerse`、小時禱啟應）本就無加粗，無需變更。
- 驗證：六日課 × 三語 × 兩日期掃描，「應」後正文零 `font-weight: 500`；第二頌歌三狀態（含簡體、雙語）無啟應標籤、※ 保留；第一頌歌與早禱啟應未受影響；48 連線掃描零錯誤；截圖確認。

#### 6. 教父誦讀（第二頌歌後、信經前）
- 邏輯層 `src/PatristicReadingService.php`（對應 Swift PatristicReadingLoader／Data）：以**實際日期**判定（前夕晚禱不讀明日檔案），依 `data/patristic/命名範本.json` 規則映射 `patristic_{season}_{week}.json`，再按星期取 `readings[day]`（0=主日…6=禮拜六）。PHP 語意調整：聖誕期週數恆為 1，改依禮日標題映射（聖誕日→0、聖誕後第一／二主日→1／2、受割禮日→3）；顯現日→epiphany_0；大齋首日→lent_0、苦難主日→lent_5、棕樹主日→lent_6、聖週→holyweek_1；升天期／聖靈降臨期併入 easter 檔；降臨前主日及其前一週映射 `pre_advent_k`（k=距降臨第一主日之週數，公式 22+(w+6)%7 求降臨第一主日）。檔案不存在或該日無條目→回傳 null。
- 顯示層 `components/patristic_reading.php`：無資料時**整段隱藏**（不影響晚禱流程）；有資料時依 Swift 原版式：標題「教父誦讀」＋禮規「¶ 此後，誦讀教父著作選段。」→「讀經員：」行（紅色標籤，兼容 `reader`／`source` 兩種鍵）→ 置中紅色副標題 → 分隔線 → 正文段落（依資料 `\n` 分段，每段獨立區塊、段間留白 12px）→ 啟應「求主憐憫。／感謝上帝。」。條目為純文字欄位依資料原樣呈現。UI 文案新增 `patristic_title`／`patristic_rubric`／`patristic_reader_label` 三鍵。
- 現有資料：`trinity_4…22`（簡體）、`advent_1`（繁體）、`pre_advent_1…5`（簡體）；`epiphany`／`lent`／`prelenten` 舊名空檔不採用（依命名範本讀取，待補檔案自動生效）。
- 驗證：服務層 26 日期鍵值對照全符預期（trinity_14 主日／週四、advent_1、pre_advent_1／2／3 主日與週間、缺檔季節 nil）；頁面 16 項斷言全過（位置在第二頌歌後、有資料正確渲染、無資料整段隱藏〔復活後第一主日／聖誕日／大齋第一主日〕、簡體／英文／雙語）；90 連線大掃描（30 日期 × 3 語）零錯誤；早禱／一時禱／三時回歸零錯誤；截圖確認版面。

#### 7. 晚禱信經與祈禱（沿用早禱組件）
- `offices/evening_prayer.php` 於教父誦讀之後直接引用 `components/creed.php`、`components/prayers.php`（兩組件本為日課無關的通用實作，切換參數 `creed`／祈禱啟應版本鈕照常運作）。
- 連帶修正（兩日課共用）：`creed.php` 亞他那修信經預設判定，原以標題子字串比對（`三一主日` 等），會把三一期每個平日誤判為亞他那修日；改為對應 Swift `CreedsDataLoader.shouldShowAthanasianCreed`——固定聖日月日精確匹配（12/25、1/6、2/24、6/24、7/25、8/24、9/21、10/28、11/30）＋移動節日 dfe 判定（0 復活日、39 升天日、49 聖靈降臨日、56 且主日=三一主日）；八日慶期主日不再誤判。手動切換不受影響。
- 驗證：11 個預設判定案例全過（三一期平日／主日→使徒信經；三一主日、聖誕日、顯現日、復活日、升天日、聖靈降臨日→亞他那修；聖誕後第一主日〔八日慶期〕→使徒；早禱回歸一致）；手動切換雙向可用；96 連線大掃描（16 日期〔含全部固定聖日〕× 3 語 × 早／晚禱）零錯誤；截圖確認版面。

### 🚧 進行中 / 待完成
- [x] 晚禱（Evening Prayer）模組 — 全模組完成（pre_office → 結束詞；Temporal 資料未覆蓋期日祝文模組依資料現況隱藏）
- [x] 寢前禱（Compline）模組
- [ ] 更多 Sanctorale 與 Temporal JSON 資料檔補充
- [ ] 小時課 en 文本補全（`terce_prayer.json` 已補，`sext_prayer.json` / `nona_prayer.json` 待補）
- [x] 一時禱（Prime）模組
- [x] 三時禱、六時禱、九時禱（Terce / Sext / None）模組
- [ ] 彌撒經文（Mass Proper）模組

## 移植說明與已知差異

1. **LiturgicalRank 改用 int 枚舉**：原 Swift 為 `Double` 原始值，但所有取值皆為整數，比較語義不變；大小比較用 `->value` 或 `gte()/lt()` 等輔助方法。
2. **星期編號**：全站統一 `1=主日 … 7=禮拜六`（對齊 Swift 的 `Calendar.component(.weekday)`），內部由 `(int)$date->format('w') + 1` 轉換。
3. **日期正規化**：所有計算先正規化到當日中午 12:00，避免時區/夏令時誤差，與 Swift 版一致。
4. **LiturgicalSeason 定義**：原 Swift 檔案中引用但未附上枚舉定義，已依程式碼實際使用的十個節期補全（含 `prelenten`、`holyWeek`）。
5. **已額外實作的原 Swift 未移植部分**：
   - 以本地 JSON 實現了聖詩與選句載入（取代原 `InvitatoryHymnLoader` / `OfficeHymnLoader`）
   - 以 `BibleJSONService` 實現聖經經文動態解析
   - 以 `BibleSentencesLoader` 實現聖經選句回退邏輯
   - `firstCanticleType()` 已移植，回傳字串 `'te_deum' / 'benedicite' / 'benedictus_es'` 取代原 `CanticleType` 枚舉
6. **未移植的部分**（原 Swift 檔案引用但附件中未提供實作）：
   - `MassProper` / `MassProperDetailView`：彌撒經文模型
   - `DailyOfficeLoader`：原日課載入器（現由本地 JSON 與組件直接渲染取代）
7. **時區**：Swift 版使用 `TimeZone.current`；PHP 版使用 PHP 預設時區（`date.timezone`），如需固定時區請在 `bootstrap.php` 加 `date_default_timezone_set('Asia/Taipei');`。

## 驗證

已通過：全年 365 天 ×（早禱+晚禱）遍歷無異常；復活節算法對照 2020/2026/2027/2030 正確；大齋首日、聖週、升天、聖靈降臨、三一主日、降臨第一主日、聖誕、顯現、受割禮日、6/24、6/29 及 6/28 晚禱（前夕晚禱）等關鍵日期抽樣全部符合預期。
