/* 01 / THEME — 内容仍由 content.js 管理。动作时长集中在 app.js 的 FLIGHT_MS。
   所有持续/施法动画只改变 transform 或 opacity，不动画化滤镜、阴影或布局尺寸。 */
@import url('https://fonts.googleapis.com/css2?family=Cinzel+Decorative:wght@400;700&family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&display=swap');
:root {
  color-scheme: dark;
  --night: #080b13; --gold: #c5a469; --pale: #f0d7a0; --ice: #8bc7e6; --ink: #483729;
  --serif: 'Cormorant Garamond', Georgia, serif;
  --display: 'Cinzel Decorative', Georgia, serif;
  --chinese: 'STKaiti','KaiTi','楷体','Kaiti SC','Noto Serif SC','Songti SC',serif;
  --book-height: min(560px, 64svh, 112vw);
  --cover-width: calc(var(--book-height) * .6667);
  --letter-width: min(550px, calc(100vw - 44px));
  --letter-height: min(700px, calc(100svh - 64px));
  --orb: 260px;
  --parchment: #eadbb9;
}
* { box-sizing: border-box; }
body { margin: 0; background: var(--night); color: var(--gold); font-family: var(--chinese); }
button { font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }
button:focus-visible, [tabindex]:focus-visible { outline: 2px solid #96c5d5; outline-offset: 6px; }
[hidden] { display: none !important; }
::selection { background: #715444; color: #fff1d2; }
.world { min-height: 100svh; position: relative; overflow: hidden; isolation: isolate;
  background: radial-gradient(ellipse at 50% 48%, #1b2e3c80, transparent 52%), radial-gradient(ellipse at 50% 88%, #1f36412b, transparent 55%), var(--night); }
.vignette { position: absolute; inset: 0; background: radial-gradient(ellipse, transparent 36%, #03060b88); pointer-events: none; }
.world main { min-height: 100svh; display: grid; align-items: center; padding: 32px 0; position: relative; z-index: 2; }
#atmosphere { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 6; pointer-events: none; }
.sanctum { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); place-items: center; }

/* 02 / RITUAL — 稳定的慢旋转不会在开合时从零重启。
   整张 SVG 统一转动，避免内部多个几何组分别重绘。 */
.celestial-halo { position: absolute; top: 50%; left: 50%; width: min(770px, 104vw); aspect-ratio: 1;
  transform: translate(-50%, -50%); color: #b9a477; opacity: .3; pointer-events: none; }
.celestial-halo > svg { width: 100%; height: 100%; overflow: visible; animation: orbit 160s linear infinite; }
.halo-inner { opacity: .42; }
.halo-runes { opacity: .86; }
.floor-portal { position: absolute; left: 50%; top: calc(50% + var(--book-height) * .46);
  width: min(840px, 132vw); aspect-ratio: 1; color: #d4b372; opacity: .46;
  transform: translate(-50%, -50%) rotateX(73deg); pointer-events: none; }
.floor-portal > svg { width: 100%; height: 100%; animation: orbit 110s linear infinite reverse; }
.floor-glow { position: absolute; top: calc(50% + var(--book-height) * .48); width: min(620px, 90vw); height: 140px;
  transform: translateY(-50%); background: radial-gradient(ellipse, #88d1db1d, transparent 68%); pointer-events: none; }
.spell-ring { position: absolute; top: 50%; left: 50%; z-index: 3; width: min(710px, 104vw); aspect-ratio: 1;
  border: 1px solid #d8c89c; border-radius: 50%; opacity: 0; transform: translate(-50%, -50%) scale(.5); pointer-events: none; }
.spell-ring::before { content: ''; position: absolute; inset: 8px; border: 1px dashed #a6cfd37d; border-radius: inherit; }
.spell-ring-alt { width: min(570px, 88vw); border-color: #9bd5e0; }
.spell-ring-alt::before { inset: 18px; border: 1px solid #c2c9a42b; }
.cast-flare { position: absolute; left: 50%; top: 50%; width: min(700px, 110vw); aspect-ratio: 1; z-index: 4;
  opacity: 0; pointer-events: none; transform: translate(-50%, -50%);
  background: radial-gradient(ellipse, #d4f4ff42 0, #8fc5dc18 24%, transparent 62%); }

/* 03 / BOOK — 预留完整信纸的舞台尺寸。信纸出现时不会撑开网格、挤动封面。
   悬浮与退场使用不同的父子元素，避免覆盖 transform 或重启动画。 */
.stage { position: relative; z-index: 10; width: var(--letter-width); height: var(--letter-height); perspective: 1500px; }
.book-carrier { position: absolute; width: var(--cover-width); height: var(--book-height); left: 50%; top: 50%;
  margin-left: calc(var(--cover-width) / -2); margin-top: calc(var(--book-height) / -2); }
.book-hover { width: 100%; height: 100%; animation: book-float 7s ease-in-out infinite; }
.book-cover { position: relative; display: block; width: 100%; height: 100%; padding: 0; border: 0; border-radius: 4px 7px 7px 4px;
  background: #211519 url('assets/grimoire-cover.png') center / 100% 100% no-repeat;
  box-shadow: inset 0 0 0 1px #d0a06380, 6px 7px 0 -2px #3a2722, 9px 11px 0 -4px #af966044, 0 22px 45px #0008; }
.book-cover::after { content: ''; position: absolute; inset: 0; border-radius: inherit;
  background: radial-gradient(ellipse at 50% 57%, #bfdcea24, transparent 58%); opacity: 0; transition: opacity .4s; pointer-events: none; }
.book-cover:hover::after { opacity: 1; }
.cover-glint { position: absolute; inset: 0; overflow: hidden; border-radius: inherit; pointer-events: none; }
.cover-glint::before { content: ''; position: absolute; inset: -10% -80%;
  background: linear-gradient(108deg, transparent 42%, #fff0b70e 49%, #fff2cb18 50%, transparent 58%);
  animation: glint 11s ease-in-out infinite; }
.gem-light { position: absolute; left: 39%; top: 48%; width: 22%; aspect-ratio: 1;
  background: radial-gradient(circle, #c9f1ff5c, #8cddff22 22%, transparent 66%); transform-origin: 50% 50%; pointer-events: none; animation: breathe 4s ease-in-out infinite; }
.spine-light { position: absolute; left: 7%; right: 6%; top: -5%; height: 12%; opacity: 0;
  background: radial-gradient(ellipse, #f5f2c69c 0, #a2dcef55 16%, transparent 65%); pointer-events: none; }
.world[data-state='reading'] .book-carrier { opacity: .18; transform: translate3d(0, 28px, -100px) scale(.93); }
.world[data-state='reading'] .celestial-halo { opacity: .16; }
.world[data-state='reading'] .floor-portal { opacity: .23; }
.world[data-state='reading'] .book-hover,
.world[data-state='opening'] .book-hover,
.world[data-state='closing'] .book-hover { animation-play-state: paused; }

/* 04 / LETTER — 三段折纸：上下两片围绕真正的折线旋转，中间纸页承接飞行。
   preserve-3d 的父元素不能设 overflow:hidden、filter 或 opacity<1，避免被浏览器压平。 */
.letter { position: absolute; inset: 0; z-index: 3; transform-style: preserve-3d; color-scheme: light; color: var(--ink);
  transform-origin: 50% 50%; pointer-events: none; }
.paper-panel { position: absolute; width: 100%; height: 33.4%; transform-style: preserve-3d; }
.paper-center { top: 33.3%; z-index: 1; }
.paper-top { top: 0; z-index: 3; transform-origin: 50% 100%; transform: rotateX(-179deg); }
.paper-bottom { top: 66.6%; z-index: 4; transform-origin: 50% 0; transform: rotateX(179deg); }
.paper-face { position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden;
  background: radial-gradient(ellipse at 0 50%, #a8803830, transparent 35%), radial-gradient(ellipse at 100% 50%, #a8803824, transparent 30%),
    repeating-linear-gradient(8deg, #9b7d3207 0 1px, transparent 1px 5px), var(--parchment);
  border-left: 1px solid #f8ebc478; border-right: 1px solid #a78c5355; }
.paper-top .paper-front { border-radius: 3px 5px 0 0; background-color: #eddfbe; }
.paper-bottom .paper-front { border-radius: 0 0 4px 2px; background-color: #e6d6b1; }
.paper-top .paper-front::after, .paper-center .paper-face::after { content: ''; position: absolute; left: 1px; right: 1px; bottom: 0; height: 10px;
  background: linear-gradient(0deg, #75512114, transparent); border-bottom: 1px solid #fff8db59; pointer-events: none; }
.paper-back { transform: rotateX(180deg); background-color: #decca7; box-shadow: 0 7px 15px #39270e25; }
.paper-back::before { content: ''; position: absolute; inset: 16px 22px; border: 1px solid #98703e3b; }
.paper-shadow { position: absolute; inset: 1px; border-radius: 4px; box-shadow: 0 24px 55px #0007, 0 2px 1px #0005; opacity: 0; }
.postal-seal { position: absolute; z-index: 8; left: calc(50% - 25px); top: calc(50% - 25px); width: 50px; height: 50px;
  display: grid; place-items: center; background: radial-gradient(circle at 34% 28%, #a2503e, #672b29 68%); border: 1px solid #bb775947;
  border-radius: 45% 49% 44% 48%; color: #dbb486; font: 31px var(--serif); box-shadow: inset 0 0 0 4px #58271f50, 0 3px 6px #4a2f1933;
  transform: translateZ(2px); }
.letter-content { position: absolute; inset: 0; z-index: 10; display: flex; flex-direction: column; opacity: 0; transform: translateZ(1px); }
.letter-content::before { content: ''; position: absolute; inset: 16px; border: 1px solid #926e3638; pointer-events: none; }
.letter-crest { flex: 0 0 65px; display: flex; justify-content: center; align-items: center; gap: 13px;
  color: #88683c; font: 22px var(--serif); padding-top: 12px; }
.letter-crest i { font-size: 13px; font-style: normal; }
.letter-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 4px 50px 24px;
  scrollbar-width: thin; scrollbar-color: #ac966b transparent; outline-offset: -8px; }
.letter-body:focus-visible { outline: 1px solid #96784970; outline-offset: -8px; }
.letter-kicker { font: 10px var(--display); letter-spacing: .22em; color: #927043; text-align: center; margin: 0 0 27px; }
.letter-date { font-size: 14px; color: #937a52; margin: 0 0 27px; }
.letter-salutation { font-size: 21px; letter-spacing: .04em; color: #653d2f; margin: 0 0 19px; }
.letter-paragraph { font-size: 18px; line-height: 1.98; margin: 0 0 16px; text-indent: 2em; text-align: justify; }
.letter-lead { text-indent: 0; }
.letter-lead::first-letter { font-size: 35px; float: left; line-height: 1.1; margin: 4px 7px 0 0; color: #824935; }
.letter-signature { font-size: 17px; text-align: right; color: #774c38; margin: 27px 0 0; }
.letter-postscript { font-size: 14px; color: #89704b; line-height: 1.9; margin: 24px 0 0; padding-top: 15px; border-top: 1px solid #8a6e3c3d; }
.letter-endmark { flex: 0 0 37px; color: #9f875a; text-align: center; font: 10px var(--display); letter-spacing: .22em; padding: 6px 0 18px; }
.letter-close { position: absolute; top: 22px; right: 22px; z-index: 3; width: 35px; height: 35px;
  display: grid; place-items: center; border: 1px solid #97713c40; border-radius: 50%; background: #ecdfbf80; color: #846641; font-size: 14px; transition: opacity .2s; }
.letter-close:hover { opacity: .65; }
.world[data-state='reading'] .letter { pointer-events: auto; }
.world[data-state='reading'] .paper-top, .world[data-state='reading'] .paper-bottom { transform: rotateX(0deg); }
.world[data-state='reading'] .letter-content, .world[data-state='reading'] .paper-shadow { opacity: 1; }
.world[data-state='reading'] .postal-seal { opacity: 0; }
.world.is-animating .letter, .world.is-animating .paper-panel, .world.is-animating .book-carrier { will-change: transform, opacity; }
.world.is-animating .gem-light, .world.is-animating .orb-ring, .world.is-animating .orb-bloom span { will-change: transform, opacity; }

/* 05 / ORB — 宝珠是信纸唯一的出入口，本体只剩一圈符文环：
   封面水晶先被点亮，信笺由环心射出，也由环心吸回。
   两层分工——.orb 在信纸下方（符环），.orb-bloom 在信纸上方（爆发与封印的过曝光）。
   盒子的 left/top 由 app.js 写入水晶实测中心，负外边距把盒子本身对中，符环只改 transform / opacity。 */
.orb, .orb-bloom { position: absolute; left: 50%; top: 50%; z-index: 1; width: var(--orb); height: var(--orb);
  margin: calc(var(--orb) / -2) 0 0 calc(var(--orb) / -2); pointer-events: none; opacity: 0; }
.orb-bloom { z-index: 5; }
/* 符环：环上有符文与四向刻痕，转起来才看得出在转。 */
.orb-ring { position: absolute; inset: 0; margin: auto; width: 152px; height: 152px; overflow: visible;
  transform-origin: 50% 50%; color: #cfe9f7; }
.orb-bloom > span { position: absolute; display: block; border-radius: 50%; inset: 0; transform-origin: 50% 50%;
  background: radial-gradient(circle, #ffffffde 0, #e2f7ffb4 18%, #8fd2ef5e 40%, transparent 70%); }

@keyframes orbit { to { transform: rotate(360deg); } }
@keyframes book-float { 0%,100% { transform: translate3d(0,0,0); } 50% { transform: translate3d(0,-8px,0); } }
@keyframes breathe { 0%,100% { opacity: .5; } 50% { opacity: 1; } }
@keyframes glint { 0%,25% { transform: translate3d(-42%,0,0); } 70%,100% { transform: translate3d(42%,0,0); } }
@media(max-width:700px) {
  :root { --book-height: min(470px, 60svh, 112vw); --letter-width: calc(100vw - 36px); --letter-height: min(690px, calc(100svh - 48px)); --orb: 215px; }
  .world main { padding: 24px 0; }
  .celestial-halo { width: min(670px, 150vw); opacity: .26; }
  .floor-portal { width: min(680px, 175vw); }
  .letter-body { padding: 2px 28px 22px; }
  .letter-paragraph { font-size: 17px; line-height: 1.9; }
  .letter-salutation { font-size: 19px; }
  .letter-crest { flex-basis: 57px; }
  .letter-close { top: 18px; right: 18px; width: 32px; height: 32px; }
}
@media(max-width:360px) { .letter-body { padding-inline: 24px; } .letter-kicker { font-size: 8px; letter-spacing: .15em; } }
@media(max-height:580px) { .letter-crest { flex-basis: 43px; } .letter-close { top: 13px; } .letter-endmark { flex-basis: 27px; padding-bottom: 10px; } }
@media(prefers-reduced-motion:reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } }
.world.is-suspended *, .world.is-suspended *::before { animation-play-state: paused !important; }
