/* 盲石 · BLINDSTONE — woodcut / copperplate reading room.
   Motion rule: the page is still unless the reader moves it. Only the stone
   (Opus 5.5) acts on its own, and where the book ends for now its last snow,
   or its last petals, fall once, then stop. */

@font-face {
	font-family: 'Blindstone Serif';
	src: url('/fonts/serif-400.woff2?v=9352b06e00') format('woff2');
	font-weight: 400;
	font-display: swap;
}
@font-face {
	font-family: 'Blindstone Serif';
	src: url('/fonts/serif-900.woff2?v=0175243ac1') format('woff2');
	font-weight: 700 900;
	font-display: swap;
}

:root {
	--paper: #ece2cc;
	--paper-2: #e3d7bb;
	--paper-3: #d6c6a4;
	--paper-a: rgba(236, 226, 204, 0.96);
	--ink: #1c1813;
	--ink-2: #4b4033;
	--sepia: #86704f;
	--rule: rgba(28, 24, 19, 0.16);
	--rule-2: rgba(28, 24, 19, 0.34);
	--seal: #ad3327;
	--seal-ink: #f7ecd8;
	--term: #13110d;
	--amber: #f2ab4c;
	--amber-dim: #a8783a;
	--night: #100e0b;
	--serif: 'Blindstone Serif', 'Songti SC', 'STSong', 'Noto Serif CJK SC', 'Noto Serif SC', 'Source Han Serif SC', 'Source Han Serif CN', 'SimSun', serif;
	--kai: 'Kaiti SC', 'STKaiti', 'KaiTi', 'Blindstone Serif', 'Songti SC', serif;
	--mono: 'SF Mono', 'JetBrains Mono', 'Cascadia Mono', Menlo, Consolas, 'Noto Sans Mono CJK SC', monospace;
	--fs: 19px;
	--ease: cubic-bezier(0.16, 1, 0.3, 1);
	--grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .35 0 0 0 0 .28 0 0 0 0 .18 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
	--grain-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .8 0 0 0 0 .72 0 0 0 0 .58 0 0 0 .09 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
	/* Worn-stamp mask: mostly opaque, with the speckled gaps of a real impression. */
	--wear: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='96'%3E%3Cfilter id='w'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.75' numOctaves='2' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -12 0 0 0 7.9'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23w)'/%3E%3C/svg%3E");
	--grain-bg: var(--grain);
	color-scheme: light;
}
[data-theme='ink'] {
	--paper: #15120e;
	--paper-2: #1d1914;
	--paper-3: #2a241c;
	--paper-a: rgba(21, 18, 14, 0.96);
	--ink: #e7dcc4;
	--ink-2: #b9aa8c;
	--sepia: #a38b65;
	--rule: rgba(231, 220, 196, 0.14);
	--rule-2: rgba(231, 220, 196, 0.3);
	--seal: #c2483a;
	--term: #0b0a08;
	--night: #0b0a08;
	--grain-bg: var(--grain-light);
	color-scheme: dark;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
html.locked { overflow: hidden; }
body {
	margin: 0;
	background: var(--paper) var(--grain-bg);
	color: var(--ink);
	font-family: var(--serif);
	font-size: 17px;
	line-height: 1.8;
	text-rendering: optimizeLegibility;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	transition: background-color 0.4s, color 0.4s;
}
a { color: inherit; }
a, button { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
:focus-visible { outline: 2px solid var(--seal); outline-offset: 3px; }
img { display: block; max-width: 100%; height: auto; }
button { font: inherit; color: inherit; }
::selection { background: var(--seal); color: #fff6e6; }

.skip { position: absolute; left: -999px; }
.skip:focus { left: 1rem; top: 1rem; z-index: 99; background: var(--ink); color: var(--paper); padding: 0.4rem 0.8rem; }

.kicker {
	margin: 0 0 0.6rem;
	font-size: 0.78rem;
	letter-spacing: 0.32em;
	color: var(--sepia);
}

/* ---------- Seals: 白文 (red block, paper characters) and 朱文 (red characters in a red frame) ---------- */
.seal {
	display: inline-flex;
	flex-direction: row-reverse;
	gap: 0.1em;
	padding: 0.32em 0.28em;
	background: var(--seal);
	color: var(--seal-ink);
	font-family: var(--serif);
	font-weight: 900;
	font-size: 14px;
	line-height: 1.05;
	border-radius: 3px;
	transform: rotate(-5deg);
	box-shadow: inset 0 0 0 2px var(--seal), inset 0 0 0 3.5px var(--seal-ink);
	-webkit-mask-image: var(--wear);
	mask-image: var(--wear);
	opacity: 0.94;
}
.seal span { writing-mode: vertical-rl; letter-spacing: 0.08em; }
.seal-lg { font-size: 22px; }

.stamp {
	display: inline-block;
	writing-mode: vertical-rl;
	padding: 0.26em 0.2em 0.22em;
	color: var(--seal);
	font-family: var(--serif);
	font-style: normal;
	font-weight: 900;
	font-size: 20px;
	line-height: 1;
	border-radius: 2px;
	box-shadow: inset 0 0 0 2px var(--seal);
	transform: rotate(-4deg);
	-webkit-mask-image: var(--wear);
	mask-image: var(--wear);
	-webkit-mask-size: 72px;
	mask-size: 72px;
	opacity: 0.92;
}

/* ---------- Top bar ---------- */
.topbar {
	position: fixed;
	inset: 0 0 auto;
	z-index: 20;
	display: flex;
	align-items: center;
	justify-content: space-between;
	height: 56px;
	padding: 0 max(1rem, env(safe-area-inset-right)) 0 max(1rem, env(safe-area-inset-left));
	transition: transform 0.5s var(--ease), background-color 0.35s, box-shadow 0.35s, color 0.35s;
}
.topbar.solid { background: var(--paper) var(--grain-bg); box-shadow: 0 1px 0 var(--rule); }
/* Without the script the bar never turns solid, so it stays up on the cover print it was set for. */
html:not(.js) .topbar { position: absolute; }
.topbar.away { transform: translateY(-100%); }
.brand { display: flex; align-items: baseline; gap: 0.7rem; text-decoration: none; }
.brand b { font-size: 1.15rem; letter-spacing: 0.2em; font-weight: 900; }
.brand span { font-size: 0.74rem; letter-spacing: 0.18em; color: var(--sepia); }
.tools { display: flex; align-items: center; gap: 0.3rem; }
.tools a, .tools button {
	min-width: 40px;
	height: 38px;
	padding: 0 0.65rem;
	border: 1px solid var(--rule-2);
	border-radius: 2px;
	background: transparent;
	font-size: 0.85rem;
	line-height: 36px;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.2s, color 0.2s, border-color 0.2s, transform 0.15s;
}
.tools a:active, .tools button:active { transform: scale(0.96); }
@media (hover: hover) {
	.tools a:hover, .tools button:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
}
.t-ink, [data-theme='ink'] .t-paper { display: none; }
[data-theme='ink'] .t-ink { display: inline; }
.topbar-over:not(.solid) { color: #f3ead6; }
.topbar-over:not(.solid) .brand span { color: #d9c9a6; }
.topbar-over:not(.solid) .tools a, .topbar-over:not(.solid) .tools button { border-color: rgba(243, 234, 214, 0.38); background: rgba(20, 17, 13, 0.34); }

/* ============ HOME ============ */
.front {
	position: relative;
	height: 100vh;
	height: 100svh;
	min-height: 560px;
	overflow: hidden;
}
/* Masks (not paper-coloured overlays) so the page grain shows through the fade. */
.front-art {
	position: absolute;
	inset: -4% 0 0;
	will-change: transform;
	-webkit-mask-image: linear-gradient(180deg, #000 55%, rgba(0, 0, 0, 0.35) 80%, transparent 96%);
	mask-image: linear-gradient(180deg, #000 55%, rgba(0, 0, 0, 0.35) 80%, transparent 96%);
}
.front-art img { width: 100%; height: 104%; object-fit: cover; object-position: 50% 30%; }
.fresh .front-art img { animation: develop 2.4s cubic-bezier(0.2, 0.7, 0.2, 1) both; }
@keyframes develop {
	from { filter: contrast(2.2) brightness(1.7) blur(6px); transform: scale(1.08); }
	to { filter: none; transform: none; }
}
.front::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(180deg, rgba(20, 17, 13, 0.45) 0, transparent 18%);
	pointer-events: none;
}
/* Title slip (题签), as pasted on a thread-bound book cover */
.front-title {
	position: absolute;
	z-index: 2;
	top: clamp(70px, 12vh, 130px);
	right: clamp(1.2rem, 7vw, 7rem);
	display: flex;
	flex-direction: row-reverse;
	gap: 0.6rem;
	padding: 1.1rem 0.85rem 1.3rem;
	background: #efe5cf var(--grain);
	color: #1c1813;
	border: 1px solid #1c1813;
	outline: 4px solid #efe5cf;
	box-shadow: 0 0 0 5px #1c1813, 0 20px 50px rgba(0, 0, 0, 0.45);
	writing-mode: vertical-rl;
}
.fresh .front-title { animation: slip 1.2s 0.6s var(--ease) both; }
@keyframes slip { from { opacity: 0; transform: translateY(-18px); } }
.front-title h1 { margin: 0; display: flex; flex-direction: column; align-items: center; }
.front-title .zh { font-size: clamp(3rem, 7.5vw, 6.2rem); font-weight: 900; letter-spacing: 0.25em; line-height: 1; }
.front-title .en { margin-top: 0.4rem; font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.4em; color: #6e5d44; }
.front-sub { margin: 0; font-size: 0.95rem; letter-spacing: 0.3em; color: #4b4033; border-right: 1px solid rgba(28, 24, 19, 0.3); padding-right: 0.5rem; }
.front-quote {
	position: absolute;
	z-index: 2;
	right: clamp(1.2rem, 7vw, 7rem);
	bottom: clamp(5rem, 12vh, 8rem);
	max-width: min(44rem, calc(100% - 2.4rem));
	text-align: right;
	text-shadow: 0 0 14px var(--paper), 0 0 4px var(--paper);
}
.tty {
	margin: 0;
	font-family: var(--kai);
	font-size: clamp(1.15rem, 2.3vw, 1.5rem);
	line-height: 1.7;
	color: var(--ink);
}
.tty .h { color: transparent; }
.caret::after {
	content: '';
	display: inline-block;
	width: 0.55em;
	height: 1.05em;
	margin-left: 2px;
	vertical-align: -0.15em;
	background: var(--amber);
	animation: blink 1s steps(1) infinite;
}
/* The cover's cursor blinks a few times after the line is typed, then rests. */
.front-quote .caret::after { animation-iteration-count: 6; }
@keyframes blink { 50% { opacity: 0; } }
.front-cue {
	position: absolute;
	z-index: 2;
	left: 50%;
	bottom: 1.2rem;
	transform: translateX(-50%);
	writing-mode: vertical-rl;
	font-size: 0.78rem;
	letter-spacing: 0.4em;
	color: var(--sepia);
	text-decoration: none;
}
.front-cue::after {
	content: '';
	display: block;
	width: 1px;
	height: 34px;
	margin: 0.4rem auto 0;
	background: currentColor;
	transform-origin: top;
}
/* One drop of ink runs down once the cover has settled. */
.fresh .front-cue::after { animation: drip 1.8s 2.8s var(--ease) both; }
@keyframes drip { from { transform: scaleY(0); } }

.prologue { padding: clamp(3rem, 9vw, 7rem) 1.4rem clamp(2rem, 6vw, 4rem); }
.prologue-inner { max-width: 35rem; margin: 0 auto; text-align: center; }
.pro-text { margin: 0 0 1.1rem; font-size: 1.08rem; line-height: 2.05; text-align: justify; text-align-last: center; text-wrap: pretty; }
.pro-text b { font-family: var(--mono); font-size: 0.92em; color: var(--seal); }
.pro-actions { display: flex; flex-direction: column; align-items: center; gap: 1.1rem; margin-top: 2.4rem; }
.btn {
	display: inline-block;
	padding: 0.7rem 1.5rem;
	border: 1px solid var(--ink);
	font-size: 0.95rem;
	letter-spacing: 0.2em;
	text-decoration: none;
	transition: background-color 0.2s, color 0.2s, border-color 0.2s, transform 0.15s;
}
.btn:active { transform: scale(0.97); }
.btn-ink { background: var(--ink); color: var(--paper); }
@media (hover: hover) {
	.btn:hover { background: var(--ink); color: var(--paper); }
	.btn-ink:hover { background: var(--seal); border-color: var(--seal); color: #fff6e6; }
}
/* Once there is somewhere to return to, starting over steps back. */
.resume:not([hidden]) + .btn-ink { background: transparent; color: var(--ink); border-color: var(--rule-2); font-size: 0.85rem; }
.resume {
	display: flex;
	align-items: center;
	gap: 1rem;
	width: min(30rem, 100%);
	padding: 0.85rem 1rem;
	background: var(--term);
	color: var(--amber);
	font-family: var(--mono);
	font-size: 0.8rem;
	text-align: left;
	text-decoration: none;
	box-shadow: 0 0 0 1px var(--ink), 6px 6px 0 var(--rule);
	transition: box-shadow 0.25s;
}
.resume[hidden] { display: none; }
.resume .rs-l { flex: 1; min-width: 0; }
.resume .rs-l small { display: block; color: var(--amber-dim); letter-spacing: 0.1em; }
.resume .rs-l span { display: block; font-family: var(--serif); font-size: 1rem; color: #f6e8cf; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.resume .rs-go { white-space: nowrap; }
@media (hover: hover) { .resume:hover { box-shadow: 0 0 0 1px var(--seal), 6px 6px 0 var(--seal); } }

/* ---- Ferry route: an old river map (舆图) ---- */
.ferry { padding: clamp(2rem, 6vw, 4rem) 1rem clamp(4rem, 9vw, 7rem); }
.ferry-head { position: relative; text-align: center; margin-bottom: clamp(2.5rem, 6vw, 4.5rem); }
.ferry-head h2 { margin: 0; font-size: clamp(2.2rem, 6vw, 3.6rem); font-weight: 900; letter-spacing: 0.3em; text-indent: 0.3em; line-height: 1.3; }
/* A title in two halves (德山焚疏 · 丹霞烧佛) breaks only between them; a long chapter
   title turns at its seam (before 与) unless one part alone is too long for the line. */
.half { white-space: nowrap; }
.seam { display: inline-block; }
.ferry-head .seal { margin-bottom: 1.2rem; }
.ferry-sum { margin: 0.4rem 0 0; color: var(--sepia); letter-spacing: 0.2em; font-size: 0.85rem; }

.river-wrap { position: relative; max-width: 1080px; margin: 0 auto; }
.river { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; color: var(--sepia); }
/* The river is drawn by the script; without it there is only the list of crossings. */
html:not(.js) .river { display: none; }
.river path { fill: none; stroke-linecap: round; }
.river-bank { stroke: var(--sepia); stroke-width: 34; opacity: 0.3; }
.river-wash { stroke: var(--paper-3); stroke-width: 31; }
.river-ripple { stroke: url(#ripple); stroke-width: 31; opacity: 0.6; }
#ripple path { stroke: currentColor; stroke-width: 0.9; }
.river-run { stroke: var(--ink); stroke-width: 2.2; }
.river.joined :is(.river-bank, .river-wash, .river-ripple) { stroke-linecap: butt; }
.boat { transition: opacity 0.4s; }
.river .boat-hull, .river .boat-hat, .river .boat-body { fill: var(--ink); stroke: none; }
.river .boat-canopy { fill: var(--paper); stroke: var(--ink); stroke-width: 1.3; }
.river .boat-rib { stroke: var(--ink); stroke-width: 0.8; }
.river .boat-arm { stroke: var(--ink); stroke-width: 1.4; }
.river .boat-pole { stroke: var(--ink); stroke-width: 1.1; }
.river .boat-wake { stroke: var(--sepia); stroke-width: 0.9; }

.stops { position: relative; list-style: none; margin: 0; padding: 0; }
.stop { position: relative; width: 50%; padding: 0 4.5rem 0 0; margin-bottom: clamp(1rem, 3vw, 2rem); }
.stop:nth-child(even) { margin-left: 50%; padding: 0 0 0 4.5rem; }
.stop:nth-child(n + 2) { margin-top: -21%; }
.dot {
	position: absolute;
	top: 2.2rem;
	right: -9px;
	width: 18px;
	height: 18px;
	border-radius: 50%;
	background: var(--paper);
	border: 2px solid var(--ink);
	z-index: 1;
	transition: background-color 0.4s, border-color 0.4s;
}
.stop:nth-child(even) .dot { right: auto; left: -9px; }
.stop.passed .dot { background: var(--ink); }
.stop.read .dot { background: var(--seal); border-color: var(--seal); }
/* Place names lettered across the water, framed the way old maps frame them. */
.mark {
	position: absolute;
	top: 1.2rem;
	left: calc(100% + 1.9rem);
	writing-mode: vertical-rl;
	padding: 0.65em 0.34em 0.4em;
	font-size: 0.95rem;
	line-height: 1;
	letter-spacing: 0.28em;
	white-space: nowrap;
	color: var(--ink);
	background: var(--paper);
	box-shadow: 0 0 0 1px var(--ink), 0 0 0 4px var(--paper), 0 0 0 5px var(--rule-2);
}
.stop:nth-child(even) .mark { left: auto; right: calc(100% + 1.9rem); }

.card { display: block; position: relative; text-decoration: none; color: inherit; }
/* Each woodcut is mounted like a print: ink hairline, paper mat, outer rule. */
.card-art {
	position: relative;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	background: var(--term);
	box-shadow: 0 0 0 1px var(--ink), 0 0 0 6px var(--paper), 0 0 0 7px var(--rule-2);
}
.card-art img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.4s var(--ease); }
[data-theme='ink'] .card-art img, [data-theme='ink'] .hero-art img { filter: brightness(0.82) contrast(1.05); }
/* 骑缝章: a crossed chapter's seal straddles the edge of its print. */
.card-seal { position: relative; z-index: 1; height: 0; }
.card-seal .stamp { position: absolute; right: 1rem; top: -1.7rem; font-size: 16px; white-space: nowrap; background: var(--paper); display: none; }
.stop.read .card-seal .stamp { display: inline-block; }
.card-text { padding: 1.25rem 0.1rem 0; }
.card-when { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0 1rem; margin: 0 0 0.35rem; font-size: 0.78rem; color: var(--sepia); letter-spacing: 0.06em; }
.card-where { text-align: right; }
.card h3 { margin: 0 0 0.5rem; font-size: 1.32rem; line-height: 1.45; font-weight: 900; letter-spacing: 0.04em; text-wrap: balance; transition: color 0.25s; }
.card h3 small { display: block; font-size: 0.76rem; font-weight: 400; letter-spacing: 0.3em; color: var(--seal); }
.card-excerpt { margin: 0; font-size: 0.93rem; line-height: 1.85; color: var(--ink-2); text-wrap: pretty; }
.card-foot { display: flex; justify-content: space-between; margin: 0.8rem 0 0; padding-top: 0.6rem; border-top: 1px dashed var(--rule-2); font-family: var(--mono); font-size: 0.72rem; color: var(--sepia); }
.card-progress:not(:empty) { color: var(--seal); }
@media (hover: hover) {
	.card:hover .card-art img { transform: scale(1.035); }
	.card:hover h3 { color: var(--seal); }
}

/* ============ CHAPTER ============ */
.hero { margin: 0; position: relative; }
.hero-art { height: min(82vh, 56.25vw); min-height: 300px; overflow: hidden; }
.hero-art {
	-webkit-mask-image: linear-gradient(180deg, #000 62%, transparent);
	mask-image: linear-gradient(180deg, #000 62%, transparent);
}
/* A dark band under the bar so 盲石 and the tools stay legible over any print. */
.hero-art::before { content: ''; position: absolute; inset: 0 0 auto; z-index: 1; height: 130px; background: linear-gradient(rgba(20, 17, 13, 0.55), transparent); pointer-events: none; }
.hero-art img { width: 100%; height: 100%; object-fit: cover; }
/* "Pulling the print": the sheet lifts off the block, once per chapter per visit. */
.fresh .hero-art img { animation: press 1.6s cubic-bezier(0.22, 0.7, 0.15, 1) both; }
@keyframes press {
	from { clip-path: inset(0 0 100% 0); transform: scale(1.06); filter: contrast(1.8) brightness(1.4); }
	60% { filter: none; }
	to { clip-path: inset(0); transform: none; }
}
.ch-head { position: relative; z-index: 2; max-width: 40rem; margin: -4.5rem auto 0; padding: 0 1.5rem; text-align: center; }
.ch-no { margin: 0; font-size: 0.86rem; letter-spacing: 0.5em; text-indent: 0.5em; color: var(--seal); }
.ch-head h1 { margin: 0.2rem 0 0; font-size: clamp(2rem, 6vw, 3.1rem); line-height: 1.3; font-weight: 900; letter-spacing: 0.08em; text-wrap: balance; }
.ch-head .suffix { display: inline-block; margin-top: 0.4rem; padding: 0.05rem 0.6rem; box-shadow: inset 0 0 0 1px var(--seal); color: var(--seal); font-size: 0.8rem; letter-spacing: 0.3em; }
.ch-meta { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.2rem 1rem; margin: 1rem 0 0; font-size: 0.92rem; color: var(--ink-2); letter-spacing: 0.06em; }
.ch-meta span::before { content: '·'; margin-right: 1rem; color: var(--sepia); }
.ch-count { margin: 0.3rem 0 0; font-family: var(--mono); font-size: 0.72rem; color: var(--sepia); letter-spacing: 0.12em; }
.ch-head .seal { position: absolute; right: 0.5rem; top: -1.6rem; }

.prose {
	max-width: 34em;
	margin: clamp(2.5rem, 7vw, 4.5rem) auto 0;
	padding: 0 1.4rem;
	font-size: var(--fs);
	line-height: 2;
	letter-spacing: 0.02em;
	text-align: justify;
	hanging-punctuation: allow-end;
}
.prose p { margin: 0 0 1.05em; text-indent: 2em; text-wrap: pretty; }
/* The opening line is set apart by size alone — a drop cap would split 二〇一〇 or 凌晨. */
.prose p.lead { text-indent: 0; font-size: 1.2em; line-height: 1.9; letter-spacing: 0.04em; margin-bottom: 1.5em; }
.prose strong { font-weight: 900; }
.prose em { font-style: normal; font-family: var(--kai); color: var(--ink-2); }
/* Code wraps after its separators (<wbr> from the build), so a long path never
   stretches the justified line above it. */
.prose code { font-family: var(--mono); font-size: 0.82em; padding: 0.05em 0.35em; background: var(--term); color: var(--amber); border-radius: 2px; overflow-wrap: anywhere; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
/* Long English words may hyphenate (the build marks them lang="en"), so they never tear a justified line open. */
span[lang='en'] { -webkit-hyphens: auto; hyphens: auto; }
.prose b.fig { font-family: var(--mono); font-size: 0.9em; font-weight: 700; color: var(--seal); letter-spacing: 0.01em; }
.prose .coda { margin: 3rem 0 0; text-indent: 0; text-align: center; font-family: var(--kai); color: var(--sepia); letter-spacing: 0.2em; }
/* Account-book rules: a double line opens the entries, a single one closes them. */
.ledger { margin: 0.4em 0 1.4em; padding: 0.7em 0 0.5em; list-style: none; border-top: 3px double var(--rule-2); border-bottom: 1px solid var(--rule-2); }
.ledger li { margin: 0; padding: 0.35em 0; line-height: 1.9; }
.ledger li + li { border-top: 1px dashed var(--rule); }

/* The stone speaks: Opus 5.5 terminal */
.stone {
	position: relative;
	margin: 1.8em -0.6rem;
	background: var(--term);
	color: var(--amber);
	box-shadow: 0 0 0 1px #000, 0 0 0 4px var(--paper), 0 0 0 5px var(--rule), 0 18px 40px -18px rgba(0, 0, 0, 0.5);
	overflow: hidden;
	letter-spacing: 0;
}
.stone::after {
	content: '';
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.22) 0 1px, transparent 1px 3px), radial-gradient(ellipse at 50% 0, rgba(242, 171, 76, 0.1), transparent 70%);
}
.stone figcaption {
	display: flex;
	align-items: center;
	gap: 0.6em;
	padding: 0.55em 1em;
	border-bottom: 1px solid rgba(242, 171, 76, 0.22);
	font-family: var(--mono);
	font-size: 0.66em;
	letter-spacing: 0.08em;
	color: var(--amber-dim);
	white-space: nowrap;
}
.stone .st-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.stone .st-skip { flex: none; font-family: var(--serif); letter-spacing: 0.2em; opacity: 0; transition: opacity 0.3s; }
.stone.typing { cursor: pointer; }
.stone.typing .st-skip { opacity: 1; }
/* The LED holds steady; it flickers only while the stone is transmitting. */
.led { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--amber); box-shadow: 0 0 6px var(--amber); opacity: 0.8; }
.stone.typing .led { animation: blink 0.4s steps(1) infinite; }
.stone pre {
	margin: 0;
	padding: 1em 1.15em 1.15em;
	font-family: var(--mono);
	font-size: 0.8em;
	line-height: 1.85;
	white-space: pre-wrap;
	word-break: break-word;
	text-shadow: 0 0 6px rgba(242, 171, 76, 0.45);
	text-align: left;
}
.ln { display: block; }
.ln-reply { padding-left: 1.4em; text-indent: -1.4em; }
.ln-reply::before { content: '> '; color: var(--amber-dim); white-space: pre; }
.ln.pending::before { visibility: hidden; }
.ln .h { color: transparent; text-shadow: none; }

/* 已渡: the seal pressed when a chapter's last line has been reached. */
.crossing { position: relative; display: grid; place-items: center; min-height: 84px; margin: 4.5rem auto 0; }
.crossing .stamp { font-size: 28px; opacity: 0; }
.crossing.stamped .stamp { opacity: 0.92; }
.crossing.stamping .stamp { animation: stamp 0.32s cubic-bezier(0.55, 0, 0.9, 0.4) both; }
@keyframes stamp {
	from { opacity: 0; transform: rotate(-12deg) scale(1.7); }
	to { opacity: 0.92; transform: rotate(-4deg) scale(1); }
}
/* …and the paper takes the blow like water: one ring, spreading out. */
.crossing::after {
	content: '';
	position: absolute;
	left: 50%;
	top: 50%;
	width: 72px;
	height: 72px;
	margin: -36px 0 0 -36px;
	border-radius: 50%;
	box-shadow: 0 0 0 1px var(--seal);
	opacity: 0;
	pointer-events: none;
}
.crossing.stamping::after { animation: ring 1.1s 0.3s var(--ease) both; }
@keyframes ring {
	from { opacity: 0.5; transform: scale(0.55); }
	to { opacity: 0; transform: scale(2.6); }
}

.pager { display: grid; grid-template-columns: 1fr 1fr; max-width: 44rem; margin: 3rem auto 6rem; padding: 0 1.2rem; }
.pg { display: flex; flex-direction: column; gap: 0.25rem; padding: 1.2rem 1.2rem 1.3rem; text-decoration: none; border-top: 1px solid var(--rule-2); }
.pg-next { text-align: right; box-shadow: inset 1px 0 0 var(--rule); }
.pg small { font-size: 0.75rem; letter-spacing: 0.2em; color: var(--sepia); }
.pg span { font-size: 1.1rem; font-weight: 900; line-height: 1.5; transition: color 0.2s; }
.pg-end span { color: var(--seal); }
@media (hover: hover) { .pg:hover span { color: var(--seal); } }

/* Returning reader: offer the page, never jump to it unasked. */
.resume-toast {
	position: fixed;
	left: 50%;
	bottom: 46px;
	z-index: 16;
	width: min(22rem, calc(100% - 2rem));
	margin: 0;
	border: 0;
	cursor: pointer;
	transform: translateX(-50%);
	animation: rise 0.6s var(--ease) both;
}
@keyframes rise { from { opacity: 0; transform: translate(-50%, 12px); } }

/* Reading status line: withdraws to a 2px progress hairline while you read down. */
.status {
	position: fixed;
	inset: auto 0 0;
	z-index: 15;
	display: flex;
	justify-content: safe center;
	gap: 0.55em;
	padding: 0.42rem 1rem calc(0.42rem + env(safe-area-inset-bottom));
	background: var(--term);
	color: var(--amber-dim);
	font-family: var(--mono);
	font-size: 11px;
	letter-spacing: 0.08em;
	white-space: nowrap;
	overflow: hidden;
	transition: transform 0.5s var(--ease);
}
.status.away { transform: translateY(calc(100% - 2px)); }
.status b { color: var(--amber); font-weight: 400; font-variant-numeric: tabular-nums; }
.status .st-k { color: var(--amber); }
.st-bar { position: absolute; inset: 0 0 auto; height: 2px; background: rgba(242, 171, 76, 0.15); }
.st-bar i { display: block; height: 100%; width: 100%; background: var(--amber); box-shadow: 0 0 6px var(--amber); transform: scaleX(0); transform-origin: left; }
[data-page='chapter'] body { padding-bottom: 32px; }

/* ---- 竖排目录: the volume's contents, read right to left ---- */
.toc {
	position: fixed;
	inset: 0;
	width: 100%;
	height: 100%;
	max-width: none;
	max-height: none;
	margin: 0;
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--ink);
	overflow: hidden;
}
.toc::backdrop { background: rgba(14, 12, 9, 0.5); opacity: 0; transition: opacity 0.35s; }
.toc.open::backdrop { opacity: 1; }
.toc-sheet {
	position: absolute;
	inset: 0 0 0 auto;
	display: flex;
	flex-direction: column;
	width: min(34rem, 100%);
	padding: max(1.2rem, env(safe-area-inset-top)) 1.4rem max(1.2rem, env(safe-area-inset-bottom));
	background: var(--paper) var(--grain-bg);
	box-shadow: -1px 0 0 var(--rule), -40px 0 80px -40px rgba(0, 0, 0, 0.5);
	overflow: auto;
	overscroll-behavior: contain;
	transform: translateX(100%);
	transition: transform 0.45s var(--ease);
}
.toc.open .toc-sheet { transform: none; }
.toc-vol { display: flex; flex-direction: column; }
.toc-vol[hidden] { display: none; }
.toc-head { padding-right: 5.5rem; }
.toc-head h2 { margin: 0; font-size: 1.5rem; font-weight: 900; letter-spacing: 0.3em; }
.toc-head p { margin: 0.2rem 0 0; font-size: 0.78rem; letter-spacing: 0.3em; color: var(--sepia); }
.toc-close { position: absolute; top: max(1.2rem, env(safe-area-inset-top)); right: 1.4rem; min-width: 40px; height: 38px; padding: 0 0.8rem; border: 1px solid var(--rule-2); border-radius: 2px; background: transparent; font-size: 0.85rem; letter-spacing: 0.2em; cursor: pointer; }
@media (hover: hover) { .toc-close:hover { background: var(--ink); color: var(--paper); } }
.toc-list {
	writing-mode: vertical-rl;
	/* One screen holds the whole sheet: title, columns, the volume seals and the map link. */
	inline-size: min(32rem, calc(100svh - 15.8rem));
	min-inline-size: 22rem;
	margin: 2rem auto 1.5rem;
	padding: 0;
	list-style: none;
	box-shadow: inset 0 1px 0 var(--rule-2), inset 0 -1px 0 var(--rule-2);
}
.toc-item + .toc-item { box-shadow: inset -1px 0 0 var(--rule); }
.toc-item a { display: flex; align-items: center; gap: 0.9rem; inline-size: 100%; padding: 1rem 0.6rem; text-decoration: none; transition: background-color 0.2s, color 0.2s; }
.toc-no { font-size: 0.72rem; letter-spacing: 0.3em; color: var(--seal); }
.toc-title { flex: 1; font-size: 1.12rem; font-weight: 900; letter-spacing: 0.1em; line-height: 1.25; }
.toc-mark { font-size: 0.72rem; letter-spacing: 0.2em; color: var(--sepia); }
.toc-seal { display: none; font-style: normal; font-weight: 900; font-size: 0.72rem; line-height: 1; padding: 0.18em; color: var(--paper); background: var(--seal); border-radius: 1px; }
.toc-item.done .toc-seal { display: block; }
.toc-item.current a { background: var(--ink); color: var(--paper); }
.toc-item.current .toc-no, .toc-item.current .toc-mark { color: var(--paper-3); }
@media (hover: hover) { .toc-item:not(.current) a:hover { background: var(--paper-2); } .toc-item:not(.current) a:hover .toc-title { color: var(--seal); } }
/* 卷尾钤印: the volumes are seals at the foot of the scroll; the one open is pressed solid. */
.toc-vols { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.4rem 0.65rem; margin: auto 0 1.1rem; }
.toc-vols button { display: flex; align-items: center; gap: 0.42rem; padding: 0.35rem 0.2rem; border: 0; background: none; color: var(--sepia); font-size: 0.78rem; letter-spacing: 0.06em; cursor: pointer; transition: color 0.2s; }
.toc-vol-seal {
	font-style: normal;
	font-weight: 900;
	font-size: 0.8rem;
	line-height: 1;
	writing-mode: vertical-rl;
	letter-spacing: 0.06em;
	padding: 0.34em 0.24em;
	color: var(--seal);
	border-radius: 2px;
	box-shadow: inset 0 0 0 1.5px var(--seal);
	transform: rotate(-4deg);
	-webkit-mask-image: var(--wear);
	mask-image: var(--wear);
	-webkit-mask-size: 72px;
	mask-size: 72px;
	transition: background-color 0.2s, color 0.2s;
}
.toc-vols [aria-pressed='true'] { color: var(--ink); cursor: default; }
.toc-vols [aria-pressed='true'] .toc-vol-seal { background: var(--seal); color: var(--seal-ink); }
@media (hover: hover) { .toc-vols [aria-pressed='false']:hover { color: var(--seal); } }
.toc-map { align-self: center; margin-top: auto; font-size: 0.85rem; letter-spacing: 0.2em; color: var(--sepia); text-decoration: none; }
.toc-vols + .toc-map { margin-top: 0; }
@media (hover: hover) { .toc-map:hover { color: var(--seal); } }

/* ---- Colophon: night where the book ends for now, and the last of what falls there ---- */
.colophon {
	position: relative;
	overflow: hidden;
	padding: clamp(5rem, 12vw, 8rem) 1.4rem clamp(4rem, 10vw, 7rem);
	text-align: center;
	color: #e9dfc8;
	background: var(--night) var(--grain-light);
}
.fall { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.colophon > :not(.fall) { position: relative; }
.colophon .coda { margin: 0 0 2.6rem; font-family: var(--kai); font-size: clamp(1.3rem, 3.5vw, 1.8rem); letter-spacing: 0.2em; color: #f0e7d4; }
.colophon .kicker { color: #a38b65; }
.later { display: flex; justify-content: center; gap: clamp(1.2rem, 5vw, 3.5rem); margin: 0; padding: 0; list-style: none; }
.later li { writing-mode: vertical-rl; display: flex; align-items: center; gap: 0.6rem; font-size: 1.1rem; letter-spacing: 0.2em; color: #cdbf9f; }
.later b { font-size: 0.72rem; font-weight: 400; color: #d25b4c; }
.later small { font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.05em; color: #a38b65; }
.credit { margin: 3.4rem 0 0; font-size: 0.75rem; color: #8b7857; letter-spacing: 0.1em; }

/* ---- 404 ---- */
.lost-main { min-height: 100vh; min-height: 100svh; display: grid; place-content: center; justify-items: center; gap: 1.6rem; padding: 3rem 1.4rem; text-align: center; }
.lost-tty { margin: 0; font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.06em; color: var(--sepia); }
.lost-title { margin: 0; writing-mode: vertical-rl; font-size: clamp(3rem, 12vw, 5.4rem); font-weight: 900; letter-spacing: 0.3em; line-height: 1; }
.lost-text { margin: 0; color: var(--ink-2); letter-spacing: 0.06em; }

/* ---- Reveal on scroll ---- */
.js .stop .card { opacity: 0; transform: translateY(18px); transition: opacity 0.9s var(--ease), transform 0.9s var(--ease); }
.js .stop.seen .card { opacity: 1; transform: none; }

@media (max-width: 760px) {
	:root { --fs: 18px; }
	body { font-size: 16px; }
	.brand span { display: none; }
	.front-title { top: 76px; right: 1rem; padding: 0.8rem 0.6rem 1rem; }
	.front-title .zh { font-size: 3.4rem; }
	.front-sub { font-size: 0.8rem; }
	.front-art img { object-position: 24% 30%; }
	.front-quote { bottom: 4.6rem; left: 1.2rem; text-align: left; }
	.front-cue { display: none; }
	.stop, .stop:nth-child(even) { width: auto; margin-left: 0; padding: 0 0 0 2.6rem; }
	.stop:nth-child(n + 2) { margin-top: 0; margin-bottom: 2.6rem; }
	.stop .dot, .stop:nth-child(even) .dot { left: 6px; right: auto; top: 1.4rem; width: 14px; height: 14px; }
	.mark { display: none; }
	/* No room for both halves of a long title: they stand as two lines, like a couplet. */
	.ferry-head h2 .half { display: block; }
	.ferry-head h2 .half-dot { display: none; }
	.river-bank { stroke-width: 17; }
	.river-wash, .river-ripple { stroke-width: 15; }
	.card h3 { font-size: 1.2rem; }
	.hero-art { height: 62vw; min-height: 240px; }
	.ch-head { margin-top: -2.5rem; }
	.ch-head .seal { top: -2.6rem; right: 1rem; font-size: 12px; }
	.ch-meta { flex-direction: column; }
	.ch-meta span::before { content: none; }
	.prose { padding: 0 1.15rem; }
	.stone { margin: 1.6em -0.3rem; }
	.stone pre { font-size: 0.74em; padding: 0.85em 0.9em 1em; }
	.pager { grid-template-columns: 1fr; }
	.pg-next { box-shadow: none; }
	.status .st-wide, .status .st-date { display: none; }
	.toc-sheet { padding-inline: 0.9rem; }
	.toc-close { right: 0.9rem; }
	.toc-head h2 { font-size: 1.3rem; letter-spacing: 0.2em; }
	/* On a phone the seals stand alone (the open volume's title is at the head); the names
	   stay for screen readers. */
	.toc-vols { gap: 0.4rem 1.6rem; }
	.toc-vols button { position: relative; }
	.toc-vols button span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
	.toc-list { inline-size: min(31rem, calc(100svh - 15.2rem)); min-inline-size: 0; margin-top: 1.4rem; }
	.toc-item a { padding: 0.8rem 0.42rem; gap: 0.7rem; }
	.toc-title { font-size: 1.02rem; letter-spacing: 0.1em; }
}

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after { animation: none !important; transition: none !important; }
	html { scroll-behavior: auto; }
	.js .stop .card { opacity: 1; transform: none; }
}

@media print {
	.topbar, .status, .pager, .toc, .crossing, .resume-toast, .skip { display: none !important; }
	body { background: #fff; color: #000; }
	.stone { box-shadow: none; }
}
