/* 書庫首頁（中文頁與英文頁共用）的樣式。字體由各頁自己用 --font 指定。
   動態效果由 shelf.js 驅動，兩邊靠名稱約定（html.motion、.tools、.motion-toggle、.cord、.theme-cord、data-theme、.cover-wrap、.hero-canvas、--open、data-hover、--soon-opacity、--accent）；
   改這些名稱時要同步改 shelf.js，約定清單寫在 shelf.js 開頭的註解。
   頁尾印章（.studio-seal、data-stamp-state）由 assets/footer-stamp.mjs 驅動；footer-stamp.js 也讀 html.motion 決定要不要播蓋印動畫。

   與書（book.css）共用「材質」：同一張紙、同一管墨水、同一條細線、同一套字體渲染；
   版面與動態則書庫自己一套（書庫是展示，書是閱讀）。紙與墨的色值要跟 book.css 同步改。
   翻開書封時露出的紙頁，就是書裡的那張紙。 */
:root {
  --soon-opacity: 0.55;   /* 灰色（還在寫）書卡的淡色程度；shelf.js 動態模式也讀這個值 */
  --bg: #f9f8f6;          /* 跟 book.css --bg-canvas 同一張紙 */
  --fg: #1a1918;          /* 跟 book.css --text-primary 同一管墨水 */
  --muted: #66645e;       /* 跟 book.css --text-secondary 同一灰 */
  --card: #fff;
  --border: #e2e0d8;      /* 跟 book.css --border-hairline 同一條線 */
  --accent: #2a5d8f;      /* 強調色；shelf.js 的背景格線也讀這個值 */
  --cover-radius: 6px;    /* 書封、紙頁與影子層、焦點框共用的圓角 */
  --cover-bg: #f0eee9;    /* 書封圖片載入前的底色；跟 book.css --code-bg 同一灰 */
  color-scheme: light dark;   /* 跟 book.css 一致：捲軸與表單控制項跟著亮暗切換 */
}

/* 暗色模式：預設跟著讀者的系統設定走；右上角的切換鈕（shelf.js）會在 <html> 上寫 data-theme="light" 或 "dark" 蓋過系統設定。
   色值與 book.css 的暗色版同步。--accent 調亮：亮色版的 #2a5d8f 在深底上對比不足，書名與格線會看不清。
   暗色色值要寫兩份（系統為暗且沒手動選亮；手動選暗），改色時兩處一起改 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #161616;
    --fg: #dedede;
    --muted: #888888;
    --card: #1e1e1e;
    --border: #2c2c2c;
    --accent: #6a9bc8;
    --cover-bg: #202020;
  }
}
:root[data-theme="dark"] {
  --bg: #161616;
  --fg: #dedede;
  --muted: #888888;
  --card: #1e1e1e;
  --border: #2c2c2c;
  --accent: #6a9bc8;
  --cover-bg: #202020;
  color-scheme: dark;
}
:root[data-theme="light"] { color-scheme: light; }
* { box-sizing: border-box; }
body {
  margin: 0;
  font-family: var(--font);
  background: var(--bg);
  color: var(--fg);
  line-height: 1.7;
  /* 跟 book.css 同樣的字體渲染，筆畫粗細與邊緣感一致 */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-kerning: normal;
}
.wrap {
  max-width: 760px;
  margin: 0 auto;
  padding: 4rem 1.5rem 6rem;
  position: relative;
}
.lang-toggle {
  position: absolute;
  top: 1.5rem;
  right: 1.5rem;
  font-size: 0.8rem;
  color: var(--muted);
  text-decoration: none;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--card);
  transition: border-color 0.15s, color 0.15s;
}
.lang-toggle:hover {
  border-color: var(--accent);
  color: var(--accent);
}
header { margin-bottom: 3rem; }
h1 {
  font-size: 2rem;
  margin: 0 0 0.5rem;
  letter-spacing: 0.02em;
}
.subtitle {
  color: var(--muted);
  font-size: 0.95rem;
  margin: 0;
}
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem 1.25rem;
}
@media (max-width: 520px) {
  .grid { grid-template-columns: repeat(2, 1fr); gap: 1.25rem 1rem; }
}
.card {
  display: block;
  text-decoration: none;
  color: inherit;
}
/* 書封（連同它後面的紙頁與影子）包在 .cover-wrap 裡；游標移上去時只有它會動，書名與副標在外面，才不影響閱讀 */
.cover-wrap {
  margin-bottom: 0.7rem;
}
.cover {
  position: relative;
  aspect-ratio: 2 / 3;
  background: var(--cover-bg);
  border: 1px solid var(--border);
  border-radius: var(--cover-radius);
  overflow: hidden;
}
.cover img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.card.soon {
  cursor: default;
  opacity: var(--soon-opacity);
  filter: grayscale(1);
}
/* 靜態版（動態關閉或沒有 JavaScript）的游標效果。動態模式的游標效果全由 shelf.js 負責，所以這些規則只在 html:not(.motion) 生效 */
html:not(.motion) .cover-wrap { transition: transform 0.15s; }
html:not(.motion) .cover { transition: border-color 0.15s, box-shadow 0.15s; }
html:not(.motion) .card:hover .cover-wrap { transform: translateY(-3px); }
html:not(.motion) .card:hover .cover {
  border-color: var(--accent);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
}
html:not(.motion) .card.soon:hover .cover-wrap { transform: none; }
html:not(.motion) .card.soon:hover .cover { border-color: var(--border); box-shadow: none; }
.card h2 {
  font-size: 1rem;
  line-height: 1.4;
  min-height: 2.8em;
  margin: 0 0 0.25rem;
  color: var(--accent);
}
.card p {
  margin: 0;
  color: var(--muted);
  font-size: 0.8rem;
  line-height: 1.5;
}
/* 封面上的小標籤：灰色卡寫「還在寫」，其他書寫章數與預估閱讀時間（文字直接寫在各頁 HTML） */
.note {
  position: absolute;
  left: 50%;
  bottom: 0.8rem;
  transform: translateX(-50%);
  padding: 0.25rem 0.8rem;
  font-size: 0.8rem;
  line-height: 1.5;
  white-space: nowrap;
  color: var(--fg);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 999px;
}
/* 手機的書封很窄：標籤縮小並允許換行，免得被封面邊緣切掉 */
@media (max-width: 520px) {
  .note {
    font-size: 0.7rem;
    padding: 0.2rem 0.6rem;
    white-space: normal;
    text-align: center;
    width: max-content;   /* 先照內容寬度排成一行，超過封面寬度才換行；沒有這行，靠 left: 50% 定位的標籤只有封面一半寬可用，會被擠成多行 */
    max-width: calc(100% - 0.8rem);
  }
}
/* 有滑鼠時，標籤平常藏起來，指到（或用鍵盤選到）才出現；觸控裝置沒有「指到」，所以一直顯示。
   靜態版交給瀏覽器的 :hover／:focus-visible；動態模式由 shelf.js 加上 data-hover，標籤與書封姿勢才出自同一個判斷 */
@media (hover: hover) and (pointer: fine) {
  .note { opacity: 0; }
  html:not(.motion) .card:hover .note,
  html:not(.motion) .card:focus-visible .note,
  html.motion .card[data-hover] .note { opacity: 1; }
}
/* 工具列：動態切換鈕（圖示）與語言切換鈕並排在右上角；右邊留出位置給亮暗拉繩（.cord）。工具列由 shelf.js 建立；沒有 JS 時語言鈕維持 .lang-toggle 自己的定位。
   position 不能拿掉、不加 border：shelf.js 用「工具列位置 + 按鈕的 offsetLeft／offsetTop」算按鈕原位（見 shelf.js 的 frame()），工具列不是按鈕最近的有定位上層時會算錯 */
.tools {
  position: absolute;
  top: 1.5rem;
  right: 4.5rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.tools .lang-toggle { position: static; }
/* 動態鈕：圖示按鈕。開啟時顯示「暫停」（按下去會停）、關閉時顯示「播放」（按下去會動），兩個圖形依 aria-pressed 淡入淡出；
   文字說明在 aria-label 與 title（shelf.js 寫入），螢幕閱讀器與游標停留時讀得到 */
.motion-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--card);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.motion-toggle svg { display: block; fill: currentColor; }
.motion-toggle .icon-play,
.motion-toggle .icon-pause {
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 0.18s, transform 0.18s;
}
.motion-toggle .icon-pause { opacity: 0; transform: scale(0.6); }
.motion-toggle[aria-pressed="true"] .icon-pause { opacity: 1; transform: none; }
.motion-toggle[aria-pressed="true"] .icon-play { opacity: 0; transform: scale(0.6); }
.motion-toggle:hover,
.motion-toggle:focus-visible,
.motion-toggle[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
}
/* 亮暗拉繩（shelf.js 建立）：固定在視窗上緣右側，一根繩子垂下，尾端掛墜是按鈕（亮色太陽、深色彎月）。
   容器本身不接游標（pointer-events: none），只有掛墜接，免得繩子的位置擋住底下的書；
   掛墜的位置、繩子的形狀（游標劃過時中段會被撥彎）、日蝕外觀都由 shelf.js 每一幀寫進 style 與 SVG 屬性。
   繩子不接游標也偵測得到「劃過」：shelf.js 看的是整頁的游標移動。顏色只在這裡定義 */
.cord {
  position: fixed;
  top: 0;
  right: 1.25rem;
  width: var(--cord-w);
  height: 0;
  z-index: 10;
  pointer-events: none;
}
/* 視窗窄時（約 860px 以下，右邊沒有空白邊可以放繩子）繩子改成跟著頁面捲走，不固定在視窗上：
   固定的話，捲到中段掛墜會壓在右欄書封上，點擊區還會擋住那塊書封 */
@media (max-width: 860px) {
  .cord { position: absolute; }
}
.cord-line { position: absolute; left: 0; top: 0; overflow: visible; }
/* 繩子與掛墜同色：掛墜變成強調色（游標移上去、鍵盤選到、深色模式）時，繩子一起變。
   繩子在掛墜前面，只能靠 :has() 從外層看掛墜的狀態；不支援 :has() 的瀏覽器，繩子維持次要灰 */
.cord-line path {
  fill: none;   /* 繩子是曲線，不填色，否則彎起來時會填出一塊 */
  stroke: var(--muted);
  stroke-width: 1.5;
  stroke-linecap: round;
  transition: stroke 0.15s;
}
.cord:has(.theme-cord:hover) .cord-line path,
.cord:has(.theme-cord:focus-visible) .cord-line path,
.cord:has(.theme-cord[aria-pressed="true"]) .cord-line path {
  stroke: var(--accent);
}
.theme-cord {
  position: absolute;
  left: 0;
  top: var(--cord-rest);
  width: var(--cord-w);
  height: var(--cord-w);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  border: 0;
  border-radius: 50%;
  background: none;
  cursor: pointer;
  pointer-events: auto;
  transition: color 0.15s;
  -webkit-tap-highlight-color: transparent;
}
.theme-cord:hover,
.theme-cord:focus-visible,
.theme-cord[aria-pressed="true"] {
  color: var(--accent);
}
.theme-cord:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-cord svg { display: block; }
.cord-core { fill: currentColor; }
.cord-rays line { stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; }
/* 日蝕遮罩：白色處顯示、黑色處遮住（遮罩圓蓋到的地方就是彎月缺掉的那塊） */
.cord-mask-lit { fill: #fff; }
.cord-mask-dark { fill: #000; }
@media (prefers-reduced-motion: reduce) {
  .motion-toggle .icon-play,
  .motion-toggle .icon-pause { transition: none; }
}
/* ===== 動態模式：只有 shelf.js 加上 html.motion 才生效，沒有它頁面就是上面的靜態版 =====
   位置、角度、縮放、透明度全部由 shelf.js 每一幀用物理計算後直接寫進 style，
   所以這裡不放任何 @keyframes，書卡與書封也不放 transition（只有標籤浮出時的淡入由 CSS 自己做），只負責「讓這些值能生效」。
   整張卡只在進場時一起飛進定位；之後游標、點書的效果都只作用在 .cover-wrap（書封），書名與副標不動。
   動畫只動 transform 與 opacity（GPU 加速的屬性）；影子與紙頁邊緣用一層疊在後面的元素，
   以透明度顯示，不去動 box-shadow。 */
html.motion header { position: relative; }
html.motion .hero-canvas { position: absolute; left: 0; top: 0; z-index: 0; pointer-events: none; }
html.motion header h1,
html.motion header .subtitle { position: relative; z-index: 1; }
html.motion .grid { position: relative; }
html.motion .card { position: relative; }
html.motion .cover-wrap {
  position: relative;
  perspective: 900px;
  /* 縮放、傾斜、透視的基準都放在書封下緣：書封放大或掀開時只往上長，下緣不會往下壓到自己的書名；代價是往上長的部分可能蓋到上一排的字 */
  transform-origin: 50% 100%;
  perspective-origin: 50% 100%;
  will-change: transform;
}
html.motion .card:not(.soon) .cover {
  position: relative;
  z-index: 1;
  transform-origin: left center;
  will-change: transform;
}
/* 書掀開時露出的紙頁邊緣（::before）與影子（::after）；--open 由 shelf.js 依游標移上去的掀開程度填 0 到 1（點書大幅翻開時一律是 1） */
html.motion .card:not(.soon) .cover-wrap::before,
html.motion .card:not(.soon) .cover-wrap::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  border-radius: var(--cover-radius);
  opacity: var(--open, 0);
}
html.motion .card:not(.soon) .cover-wrap::before {
  border: 1px solid var(--border);
  background: var(--bg);   /* 翻開後露出的紙，就是書裡那張紙 */
  box-shadow: 2px 0 0 var(--bg), 3px 0 0 var(--border), 5px 0 0 var(--bg), 6px 0 0 var(--border);
}
html.motion .card:not(.soon) .cover-wrap::after {
  z-index: -1;
  box-shadow: 6px 8px 18px rgba(0, 0, 0, 0.18);
}
html.motion .card:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; border-radius: var(--cover-radius); }
html.motion .note { transition: opacity 0.4s cubic-bezier(0.22, 0.61, 0.36, 1); }
footer {
  margin-top: 4rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 0.85rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 1.25rem 2rem;
}
/* 共用落款：朱紅只用在小印記；紙色、字體與動態仍用書庫自己的設定。 */
.studio-signature {
  gap: 0.75rem;
}
.studio-seal {
  display: block;
  flex: 0 0 40px;
  width: 40px;
  height: 40px;
  background: #c83a2a;
  border-radius: 3px;
  mask: linear-gradient(#000 0 0), url("assets/studio-colophon.png") center / 88% no-repeat;
  mask-composite: exclude;
}
/* 印章預設看得到（沒有 JavaScript 時頁面仍完整）；狀態只由 assets/footer-stamp.mjs 寫：
   等著蓋印時藏起來，蓋印中由程式逐幀寫透明度（行內樣式蓋過這裡），蓋好後移除行內樣式、回到預設 */
.studio-seal[data-stamp-state="pending"],
.studio-seal[data-stamp-state="stamping"] { opacity: 0; }
.footer-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.25rem;
}
footer a {
  display: inline-flex;
  align-items: center;
  color: inherit;
  text-decoration: none;
  transition: color 0.15s;
}
footer .footer-link-label {
  border-bottom: 1px solid var(--border);
  transition: border-color 0.15s;
}
footer a:hover {
  color: var(--accent);
}
footer a:hover .footer-link-label {
  border-color: var(--accent);
}
footer a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}
