@import url('https://fonts.googleapis.com/css2?family=Caveat:wght@600&family=DM+Sans:wght@400;500&display=swap');
:root{font-family:'DM Sans',sans-serif;color:#cfcec8;background:#03070d;color-scheme:dark;font-synthesis:none;--paper:#ede9dd;--muted:#a5a69e}
*{box-sizing:border-box}
body{margin:0;overflow:hidden}
button{-webkit-tap-highlight-color:transparent;font:inherit;color:inherit;cursor:pointer;border:0;background:transparent;touch-action:manipulation}
button:disabled{opacity:.24;cursor:default}
button:focus-visible{outline:1px solid #e7e3d4;outline-offset:3px;border-radius:5px}
[hidden]{display:none!important}
.symbol-library{position:absolute;width:0;height:0;overflow:hidden}
svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.3;stroke-linecap:round;stroke-linejoin:round;flex:none;pointer-events:none}
#scene{position:fixed;inset:0}
#scene canvas{display:block;width:100%;height:100%;touch-action:none}
/* Zoomed in, dragging moves around; the sky's own pointer cursor (over a star) still wins, as an inline style. */
#scene canvas.zoomed{cursor:grab}#scene canvas.zoomed:active{cursor:grabbing}
.book-note{position:fixed;top:max(30px,env(safe-area-inset-top));left:50%;transform:translateX(-50%);width:min(480px,calc(100% - 40px));margin:0;text-align:center;font-size:12px;line-height:1.6;font-weight:400;color:#c5cdd6;text-shadow:0 1px 15px #000;pointer-events:none;text-wrap:balance}
.book-note span{display:block;margin-top:5px;font-size:11px;color:#92a0b3;text-wrap:balance}
.book-note .book-disclaimer{margin-top:3px;font-size:10px;letter-spacing:.02em;color:#6f7d91}
.icon-button{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border-radius:50%;flex:none;transition:color .18s,background .18s}
.icon-button:hover:enabled{color:#fff;background:#ffffff09}
.book-controls,.reading-nav{position:fixed;bottom:max(28px,env(safe-area-inset-bottom));left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:2px;padding:5px 8px;background:#07111dc9;border:1px solid #ffffff0c;border-radius:32px;backdrop-filter:blur(20px);z-index:1}
.page-button{height:44px;display:flex;align-items:center;justify-content:center;gap:11px;padding:0 10px;min-width:112px;border-radius:4px;font-size:11px;letter-spacing:.05em;font-variant-numeric:tabular-nums;white-space:nowrap}
.page-button svg{width:12px;height:12px;opacity:.6}
.page-button:hover{color:#fff}
.page-button[aria-expanded=true]{color:#fff}
/* A turn in progress dims the arrows without disabling them, so keyboard focus stays put. */
.icon-button.busy{opacity:.24;cursor:default}
.separator{width:1px;height:14px;background:#ffffff16;margin:0 8px}
#loading{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;gap:12px}
.loading-line{display:block;position:relative;height:1px;width:96px;background:#aaa2;overflow:hidden}
.loading-line:after{content:'';display:block;height:1px;width:20px;background:#e4e1d2}
/* Animations run only while shown: WebKit keeps ticking them under display:none. */
#loading:not([hidden]) .loading-line:after{animation:loading 1s infinite ease-in-out}
#loadingBar{position:absolute;left:0;top:0;height:1px;width:0;background:#e4e1d2;transition:width .2s}
#loading.determinate .loading-line:after{display:none}
.loading-text{font-size:12px;letter-spacing:.04em;color:#a5a69e}
@keyframes loading{from{transform:translateX(-24px)}to{transform:translateX(100px)}}
#error{position:fixed;top:45%;left:50%;transform:translate(-50%,-50%);background:#050b13;padding:24px;text-align:center;width:min(90vw,360px);font-size:13px}
#error button{padding:12px 16px;border:1px solid #ffffff20;margin:4px}
#pageIndex{position:fixed;inset:auto 0 96px;margin:0 auto;width:min(640px,calc(100vw - 32px));max-height:calc(100dvh - 144px);padding:46px 20px 20px;overflow:auto;border:1px solid #ffffff13;border-radius:14px;background:#07111df2;color:#d9d8ce;box-shadow:0 20px 80px #0004;backdrop-filter:blur(24px)}
#pageIndex::backdrop{background:#0002}
.index-close{position:absolute;top:4px;right:7px}
.index-close svg{width:16px;height:16px}
#thumbnails{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px 12px}
.thumb{padding:5px;border-radius:3px;min-height:44px;text-align:left;border:1px solid transparent;opacity:.7}
.thumb[aria-current=page]{border-color:#c8c4aa70;opacity:1}
.thumb:hover{opacity:1;background:#ffffff05}
.thumb img{width:100%;aspect-ratio:1.42;object-fit:cover;display:block;background:#d9d4c5}
.thumb span{display:block;font-size:11px;margin-top:7px;font-variant-numeric:tabular-nums;letter-spacing:.06em}
/* The reader handles its own pinch; the dark bands around the page must not zoom the whole page instead. */
#reading{position:fixed;inset:0;width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;margin:0;border:0;padding:0;background:#050b13;color:#d9d8ce;touch-action:none}
#reading::backdrop{background:#050b13}
#readingViewport{position:absolute;inset:72px 0 90px;overflow:auto;padding:24px;touch-action:pan-x pan-y;display:flex;align-items:safe center;justify-content:safe center}
#readingImage{display:block;flex:none;max-width:none;height:auto;user-select:none;box-shadow:0 10px 44px #0003;cursor:zoom-in}
#readingImage.zoom-out{cursor:zoom-out}
.reading-tools{position:absolute;top:18px;left:50%;transform:translateX(-50%);display:flex;gap:2px}
.reading-close{position:absolute;top:18px;right:22px}
.reading-nav{gap:8px;border:0;background:transparent}
#readingCount{min-width:68px;text-align:center;font-size:11px;letter-spacing:.08em;font-variant-numeric:tabular-nums}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
@media(max-width:700px){.book-controls,.reading-nav{bottom:max(20px,env(safe-area-inset-bottom))}#pageIndex{bottom:86px;padding:44px 14px 16px}#thumbnails{grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 8px}.reading-tools{top:12px}.reading-close{top:12px;right:10px}#readingViewport{inset:64px 0 82px;padding:12px}}
/* A small pill, so the hint stays readable over anything behind it. */
.sky-hint{position:fixed;left:50%;bottom:calc(max(28px,env(safe-area-inset-bottom)) + 70px);transform:translateX(-50%);margin:0;padding:5px 12px 5px 10px;border:1px solid #ffffff10;border-radius:999px;background:#07111dc4;backdrop-filter:blur(12px);font-size:11px;letter-spacing:.04em;color:#c3cedc;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity 1.2s}
.sky-hint.visible{opacity:1}
.sky-hint:before{content:'✦';display:inline-block;margin-right:8px;color:#e5c6a6}
.sky-hint:not([hidden]):before{animation:twinkle 2.4s ease-in-out infinite}
@keyframes twinkle{50%{opacity:.35;transform:scale(.7) rotate(45deg)}}
/* The keyboard's (and a screen reader's) way to write in the sky. Taps and clicks reach the sky itself, so the button
   stays out of sight until it has focus, then shows where the sky hint sits. */
.sky-wish{position:fixed;left:50%;bottom:calc(max(28px,env(safe-area-inset-bottom)) + 70px);transform:translateX(-50%);z-index:2;display:flex;align-items:center;gap:8px;min-height:36px;padding:0 14px 0 12px;border:1px solid #ffffff18;border-radius:999px;background:#07111de6;backdrop-filter:blur(12px);font-size:12px;letter-spacing:.04em;color:#dfe6ef;white-space:nowrap}
.sky-wish span{color:#e5c6a6}
.sky-wish:focus-visible{border-radius:999px;outline-offset:2px}
.sky-wish:not(:focus){width:1px;height:1px;min-height:0;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);border:0}
.sky-tip{position:fixed;left:0;top:0;z-index:3;max-width:min(260px,calc(100vw - 32px));padding:10px 13px 11px;border:1px solid #ffffff14;border-radius:10px;background:#07111dd9;backdrop-filter:blur(16px);box-shadow:0 10px 40px #0006;font-size:11px;line-height:1.5;color:#b9c4d2;pointer-events:none;opacity:0;translate:0 4px;transition:opacity .18s,translate .18s}
.sky-tip.visible{opacity:1;translate:0 0}
.sky-tip strong{display:block;font-size:12px;font-weight:500;color:#f1eee3;overflow-wrap:anywhere}
.sky-tip span{display:block;margin-top:3px;font-family:Caveat,cursive;font-size:18px;line-height:1.15;color:#dfe6ef;overflow-wrap:anywhere}
.sky-tip em{display:block;margin-top:5px;font-style:normal;font-size:11px;letter-spacing:.05em;color:#8898ae}
/* On a phone "Find your name" is an icon only: until it is first used, a bubble with the same icon names it (and opens
   the search) where the sky hint goes, before the sky hint, while the button glows. */
.find-hint{position:fixed;left:50%;bottom:calc(max(28px,env(safe-area-inset-bottom)) + 70px);transform:translateX(-50%);z-index:2;display:flex;align-items:center;gap:8px;min-height:40px;margin:0;padding:0 16px 0 12px;border:1px solid #e5c6a64d;border-radius:999px;background:#07111de8;backdrop-filter:blur(12px);box-shadow:0 8px 30px #0008;font-size:13px;letter-spacing:.03em;color:#eef1f5;white-space:nowrap;opacity:0;translate:0 6px;transition:opacity .5s,translate .5s}
.find-hint.visible{opacity:1;translate:0 0}
.find-hint:not(.visible){pointer-events:none}
.find-hint svg{width:19px;height:19px;color:#f6ddb4}
.find-hint:focus-visible{border-radius:999px}
.find-name.hinted{color:#fff;background:#e5c6a61f;box-shadow:0 0 0 1px #e5c6a666,0 0 18px #e5c6a640}
@media(max-width:700px){.sky-hint,.sky-wish,.find-hint{bottom:calc(max(20px,env(safe-area-inset-bottom)) + 66px)}}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}}

#motionToggle svg{width:16px;height:16px;opacity:.7}
@media(max-width:440px){.book-controls{gap:0;padding:4px}.page-button{min-width:96px;padding:0 7px}.separator{margin:0 4px}}
/* 320 px phones: six controls still fit, 40 px wide (and still 44 px tall). */
@media(max-width:350px){.book-controls .icon-button,.book-controls .find-name{width:40px}.page-button{min-width:84px}}
/* The view controls sit bottom-left; on narrow portrait screens they move above the page controls. */
@media(max-width:780px) and (min-height:501px){:root{--view-bottom:calc(max(20px,env(safe-area-inset-bottom)) + 66px)}}
/* On narrow screens the view controls sit above the page controls, so the sky hint moves above both. */
@media(max-width:780px) and (min-height:501px){.sky-hint,.sky-wish,.find-hint{bottom:calc(max(20px,env(safe-area-inset-bottom)) + 142px)}}
/* Phones held sideways: the book fills the height, so everything moves to its edges. The headline sits top-right beside
   the mode switch, both control bars share the bottom row, the reader gets side rails and the index uses the height.
   There is no free sky for the hint there. */
@media(orientation:landscape) and (max-height:500px){
 html body:not(.live-body) .book-note{top:max(16px,env(safe-area-inset-top));left:auto;right:max(16px,env(safe-area-inset-right));transform:none;width:auto;max-width:calc(100% - 270px);text-align:right;line-height:1.45}
 .book-note span:not(.book-disclaimer){display:none}
 :root{--view-bottom:max(12px,env(safe-area-inset-bottom))}
 .book-controls{left:auto;right:max(12px,env(safe-area-inset-right));transform:none;bottom:max(12px,env(safe-area-inset-bottom))}
 .sky-hint{display:none}
 .find-hint{left:auto;right:max(12px,env(safe-area-inset-right));transform:none;bottom:calc(max(12px,env(safe-area-inset-bottom)) + 64px)}
 .sky-wish{left:28px;bottom:calc(var(--view-bottom) + 56px);transform:none}
 #readingViewport{inset:0 64px;padding:8px}
 .reading-tools{top:50%;left:10px;transform:translateY(-50%);flex-direction:column}
 .reading-close{top:10px;right:10px}
 #reading .reading-nav{top:50%;bottom:auto;left:auto;right:10px;transform:translateY(-50%);flex-direction:column;padding:0;gap:4px}
 #readingCount{min-width:0}
 #pageIndex{inset:10px 0 auto;width:min(760px,calc(100vw - 32px));max-height:calc(100dvh - 20px);padding:40px 14px 14px}
 #thumbnails{grid-template-columns:repeat(5,minmax(0,1fr));gap:10px}
}
/* The smallest of these phones share the bottom row between two pills; pinching still zooms, so the zoom buttons go. */
@media(orientation:landscape) and (max-height:500px) and (max-width:700px){#viewZoomOut,#viewZoomIn,.view-controls .view-sep{display:none}}
/* Touch screens: 44 px zoom buttons (the book's pill only; Sign together sizes its own) and no text under 12.5 px. */
@media(pointer:coarse){
 .view-controls .view-button{width:44px}
 .book-note span,.page-button,.thumb span,#readingCount,.sky-hint,.sky-wish,.sky-tip,.sky-tip em{font-size:12.5px}
 .sky-tip strong{font-size:13.5px}
 .sky-tip em,.book-note span{color:#a3b0c2}
}

/* ── Find your name ─────────────────────────────────────────────────────────
   A button in the book controls (with its words beside it where there is room) opens a search panel at the top of the
   screen, clear of a phone's keyboard; name-search.js keeps the panel above the keyboard and the reader draws a glowing
   box on the name. Until the search is first used, a little star twinkles on the button. */
.find-name{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:8px;width:44px;height:44px;padding:0;border-radius:22px;flex:none;font-size:12px;letter-spacing:.03em;white-space:nowrap;transition:color .18s,background .18s}
.find-name:hover,.find-name[aria-expanded=true]{color:#fff;background:#ffffff09}
.find-name:focus-visible{border-radius:22px}
.find-name-label{display:none}
@media(min-width:900px) and (min-height:501px){.find-name{width:auto;padding:0 15px 0 12px}.find-name-label{display:inline}}
.find-name.fresh:after{content:'✦';content:'✦'/'';position:absolute;left:26px;top:7px;font-size:9px;line-height:1;color:#e5c6a6;text-shadow:0 0 6px #e5c6a6aa;pointer-events:none}
.find-name.fresh:not(:hover):after{animation:twinkle 2.4s ease-in-out infinite}
.name-search{position:fixed;inset:max(20px,11vh) 0 auto;margin:0 auto;width:min(440px,calc(100vw - 24px));max-width:none;max-height:min(var(--name-room,640px),calc(100dvh - 40px));padding:0 0 8px;overflow:hidden;border:1px solid #ffffff15;border-radius:18px;background:#07111d;color:#d9d8ce;box-shadow:0 24px 90px #000a}
/* Title and close button, the field, then everything else in one scrolling body (results, notes, the Sign together link). */
.name-search[open]{display:grid;grid-template:"title close" auto "field field" auto "body body" minmax(0,1fr)/minmax(0,1fr) auto}
.name-search::backdrop{background:#01040a73}
.name-search h2{grid-area:title;align-self:center;margin:0;padding-left:18px;font-size:12.5px;font-weight:500;letter-spacing:.05em;color:#b3bfce}
.name-search h2 span{margin-right:8px;color:#e5c6a6}
#closeNameSearch{grid-area:close;margin:4px 4px 0 0}#closeNameSearch svg{width:16px;height:16px}
/* The close button's words: for screen readers beside the cross, and on phones in its place (below). */
.name-close-text{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.name-body{grid-area:body;min-height:0;overflow-y:auto;overscroll-behavior:contain}
.name-field{grid-area:field;position:relative;display:flex;align-items:center;margin:2px 14px 10px}
.name-field>svg{position:absolute;left:13px;width:18px;height:18px;color:#8d9cb2}
/* 16 px: iOS zooms the whole page into a smaller field. */
.name-field input{width:100%;height:48px;margin:0;padding:0 46px 0 42px;border:1px solid #ffffff1c;border-radius:12px;background:#ffffff0b;color:#f3f1e8;font:inherit;font-size:16px;outline:none;-webkit-appearance:none;appearance:none}
.name-field input::placeholder{color:#7d8ba1}
.name-field input:focus{border-color:#8fa3c8;background:#ffffff10;box-shadow:0 0 0 3px #8fa3c833}
.name-field input::-webkit-search-cancel-button{display:none}
#nameClear{position:absolute;right:4px;display:grid;place-items:center;width:40px;height:40px;border-radius:9px;color:#aeb9c9}
/* Clearing the field is a filled circle, unlike the panel's close button. */
#nameClear svg{width:18px;height:18px;padding:4px;border-radius:50%;background:#7f8da2;color:#07111d;stroke-width:2.6}
#nameClear:hover{background:#ffffff12}#nameClear:hover svg{background:#aeb9c9}
.name-closest{margin:0 22px 6px;font-size:12.5px;line-height:1.5;color:#b3bfce;overflow-wrap:anywhere}
.name-closest bdi{color:#f6ddb4;font-weight:500}
.name-results{margin:0;padding:0 8px;list-style:none}
.name-option{display:flex;align-items:center;gap:10px;min-height:48px;padding:8px 12px;border-radius:12px;cursor:pointer;font-size:16px;color:#dfe5ee;-webkit-user-select:none;user-select:none}
.name-option:before{content:'✦';content:'✦'/'';flex:none;width:12px;font-size:11px;color:#e5c6a6;opacity:0;transition:opacity .15s}
.name-option-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.name-option mark{background:none;color:#f6ddb4;font-weight:500}
.name-option-where{flex:none;font-size:12px;letter-spacing:.02em;color:#8795aa}
.name-option:hover{background:#ffffff08}
.name-option[aria-selected=true]{background:#ffffff12;color:#fff}.name-option[aria-selected=true]:before{opacity:1}
.name-more,.name-note,.name-foot{margin:6px 22px 4px;font-size:12.5px;line-height:1.5;color:#93a1b5}
.name-note{margin-top:0}
.name-foot{margin-top:10px}
.name-foot a,#nameRetry{color:#e5c6a6;text-decoration:underline;text-underline-offset:3px;text-decoration-color:#e5c6a666}
#nameRetry{padding:0;font-size:inherit}
.name-foot a:focus-visible,.name-sign:focus-visible,#nameRetry:focus-visible{outline:1px solid #e7e3d4;outline-offset:3px;border-radius:5px}
.name-none{padding:2px 22px 8px}
.name-none p{margin:0 0 14px;font-size:14px;line-height:1.5;color:#c9d2de;overflow-wrap:anywhere}
.name-sign{display:inline-flex;align-items:center;gap:9px;min-height:44px;padding:0 18px 0 15px;border-radius:999px;background:#e9e8de;color:#192335;font-size:13.5px;font-weight:500;text-decoration:none}
.name-sign span{color:#b07a3c}.name-sign:hover{background:#fff}
/* Phones: the panel sits at the very top, so the keyboard leaves the most room under it, and the close button moves
   up beside the field as a word, "Cancel", as in iOS search bars, so it can't be taken for the field's clear button
   (the title stays for screen readers). The headline and mode switch under the panel step out of the way. */
@media(pointer:coarse),(max-width:600px){
 .name-search{top:max(10px,env(safe-area-inset-top));width:min(520px,calc(100vw - 20px))}
 .name-search[open]{grid-template:"field close" auto "body body" minmax(0,1fr)/minmax(0,1fr) auto}
 .name-search h2{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
 .name-field{margin:10px 2px 10px 10px}
 #closeNameSearch{align-self:center;width:auto;min-width:44px;margin:0 4px 0 0;padding:0 12px 0 10px;border-radius:12px;font-size:15px;color:#dfe6ef}
 #closeNameSearch svg{display:none}
 #closeNameSearch .name-close-text{position:static;width:auto;height:auto;overflow:visible;clip-path:none}
 body:has(.name-search[open]) :is(.book-note,.mode-nav){visibility:hidden}
}
/* The box around a found name, over the cover in the reader. It glows a few times, then stays lit; landing, a ring
   ripples out from it and a handful of sparkles burst away. */
.reading-mark{position:absolute;left:0;top:0;border-radius:7px;pointer-events:none;background:#ffd76a33;box-shadow:0 0 0 2px #ffab2e,0 0 0 6px #ffab2e3d,0 0 30px 10px #ff9a2a73}
.reading-mark:not([hidden]){animation:name-glow 1.8s ease-in-out 4}
@keyframes name-glow{50%{box-shadow:0 0 0 2px #ffc764,0 0 0 11px #ffab2e24,0 0 48px 18px #ff9a2a99}}
.reading-mark.landed:after{content:'';position:absolute;inset:-4px;border:2px solid #ffab2e;border-radius:10px;opacity:0;animation:name-ping 1.1s ease-out}
@keyframes name-ping{from{opacity:1}to{inset:-30px;border-radius:24px;opacity:0}}
.reading-mark i{position:absolute;left:50%;top:50%;font-style:normal;font-size:var(--s);line-height:1;color:var(--c);text-shadow:0 0 1px #fff,0 0 3px #fff,0 0 12px var(--c),0 0 22px var(--c);opacity:0;animation:sparkle 1.35s cubic-bezier(.15,.8,.3,1) var(--d) forwards}
@keyframes sparkle{0%{opacity:0;transform:translate(-50%,-50%) scale(.3)}14%{opacity:1;transform:translate(calc(-50% + var(--x)*.3),calc(-50% + var(--y)*.3)) scale(1.25)}70%{opacity:1}100%{opacity:0;transform:translate(calc(-50% + var(--x)),calc(-50% + var(--y))) scale(.55) rotate(var(--r))}}
