/* ───────────────────────────────────────────────────────────
   The Library · shelf
   wall · plank · books (3D ring + flat bookcase spines) · bookcase
   ─────────────────────────────────────────────────────────── */
:root{
  /* procedural wood grain (themes can switch it off with `none`) */
  --wood-h:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='640' height='96'><filter id='w' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='.0035 .42' numOctaves='3' seed='4' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 .13  0 0 0 0 .07  0 0 0 0 .02  0 0 0 1.5 -.62'/></filter><rect width='100%25' height='100%25' filter='url(%23w)'/></svg>");
  --wood-v:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='96' height='640'><filter id='w' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='.42 .0035' numOctaves='3' seed='9' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 .13  0 0 0 0 .07  0 0 0 0 .02  0 0 0 1.5 -.62'/></filter><rect width='100%25' height='100%25' filter='url(%23w)'/></svg>");
  --gut:28px;
  --chromeTop:178px;
}

/* ── wall (behind everything) ──────────────────────────── */
.wall{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden;background:var(--wall)}
.w-spot{position:absolute;left:50%;top:calc(var(--railTop) + var(--H) * .4);width:min(150vw,1900px);aspect-ratio:1.55;transform:translate(-50%,-50%);
  background:radial-gradient(closest-side,var(--spot) 0%,transparent 100%);opacity:var(--spot-o,1);transition:opacity .8s}
html[data-view="case"] .w-spot{top:34%}
.w-dots,.w-floor{display:none}
.fx{position:fixed;inset:0;width:100%;height:100%;pointer-events:none;display:none}
.fx-back{z-index:0}
.fx-front{z-index:4}
.fx.on{display:block}

/* ── shelf stage ───────────────────────────────────────── */
.shelf{position:fixed;inset:0;z-index:1}
.stage{position:absolute;inset:0;touch-action:pan-y;user-select:none;-webkit-user-select:none}
/* the view you are not looking at is locked with content-visibility: its subtree is neither styled,
   laid out, painted nor hit-tested, so a theme change only re-styles what is actually on screen */
html[data-view="case"] .stage{content-visibility:hidden}
html.flow-pre .stage{content-visibility:visible}        /* going back: the carousel is unlocked early (still folded away) so the swap is cheap */
html[data-view="case"] .now-wrap{visibility:hidden;pointer-events:none}
.vig{position:absolute;inset:0;z-index:5;pointer-events:none;background:radial-gradient(125% 105% at 50% 46%,transparent 56%,var(--vig) 100%)}

/* the dark gap behind the books and the plank they stand on */
.back{position:absolute;left:0;right:0;top:calc(var(--railTop) - 40px);height:calc(var(--H) + 40px);pointer-events:none;
  background:linear-gradient(180deg,transparent 0,var(--ao-mid) 52%,var(--ao-low) 100%)}
.plank{position:absolute;left:-3%;right:-3%;top:calc(var(--railTop) + var(--H) - 26px);height:calc(26px + var(--topH) + var(--lipH));pointer-events:none}
.plank i{position:absolute;left:0;right:0;display:block}
.pk-top{top:0;height:calc(26px + var(--topH));background:var(--wood-h) 0 0/640px 96px,var(--plank-top)}
.pk-front{top:calc(26px + var(--topH));height:var(--lipH);background:var(--wood-h) 0 40px/640px 96px,var(--plank-front);
  box-shadow:inset 0 1px 0 var(--plank-edge),inset 0 2px 0 rgba(255,255,255,.07),inset 0 -2px 0 rgba(0,0,0,.2),inset 0 -1px 0 rgba(0,0,0,.34),var(--plank-glow,0 0 0 0 transparent)}
.pk-top::before{content:'';position:absolute;left:0;right:0;bottom:0;height:1px;background:rgba(0,0,0,.22)}   /* the seam where the top meets the front */
.pk-shadow{top:calc(26px + var(--topH) + var(--lipH));height:110px;background:linear-gradient(180deg,rgba(var(--shadow),calc(var(--pk-sh,.34) * 1.5)) 0,rgba(var(--shadow),var(--pk-sh,.34)) 7px,rgba(var(--shadow),.12) 42%,transparent)}

/* ── 3D ring ───────────────────────────────────────────── */
.rail{position:absolute;left:0;right:0;top:var(--railTop);height:var(--H);perspective:1700px;perspective-origin:50% 46%}
.item{position:absolute;left:0;top:0;width:var(--W);height:var(--H);transform-style:preserve-3d;visibility:hidden}
.item.vis{visibility:visible;will-change:transform}
.book{position:absolute;inset:0;transform-style:preserve-3d;transform-origin:50% 100% 0}
.face{position:absolute;backface-visibility:hidden;-webkit-backface-visibility:hidden}
.shadow{position:absolute;left:-7%;right:-7%;bottom:-11px;height:26px;pointer-events:none;
  background:radial-gradient(closest-side at 50% 50%,rgba(var(--shadow),.85) 0%,rgba(var(--shadow),.52) 38%,rgba(var(--shadow),.15) 74%,rgba(var(--shadow),0) 100%)}
.item.vis .book{will-change:transform}
.item.vis .shadow{will-change:transform,opacity}
/* NB: never put opacity / filter / will-change:opacity on .item or .book - it flattens the 3D context */

.cover{inset:0;border-radius:3px 6px 6px 3px;overflow:hidden;background:var(--sbg,#ddd);
  box-shadow:0 0 0 1px rgba(20,18,12,.16),var(--cover-glow,0 0 0 0 transparent);transform:translateZ(calc(var(--T) / 2))}
.cover .art{position:absolute;inset:0;background:#fff center/cover no-repeat;opacity:0}
.cover img{width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .45s}
.cover img.on{opacity:1}
.cover .art::after{content:'';position:absolute;inset:0;pointer-events:none;background:linear-gradient(112deg,rgba(255,255,255,.34) 0%,rgba(255,255,255,0) 34%,rgba(0,0,0,0) 70%,rgba(0,0,0,.07) 100%)}
/* pointer-following glare on the lifted cover */
.cover::after{content:'';position:absolute;inset:0;z-index:3;pointer-events:none;opacity:var(--gl,0);transition:opacity .45s;
  background:radial-gradient(circle at var(--gx,50%) var(--gy,0%),var(--glare),transparent 52%),radial-gradient(circle at calc(100% - var(--gx,50%)) calc(100% - var(--gy,0%)),var(--glare2,transparent),transparent 46%)}
.hinge{position:absolute;inset:0;pointer-events:none;z-index:2;
  background:linear-gradient(90deg,rgba(0,0,0,.34) 0,rgba(0,0,0,.10) 1.1%,rgba(255,255,255,.6) 2.5%,rgba(255,255,255,0) 4.8%,rgba(0,0,0,0) 91%,rgba(0,0,0,.09) 100%)}
.item.lifted .cover,.item.lifted .shadow{visibility:hidden}

/* ── spine : one look, used by the 3D ring and the flat bookcase ── */
.spine{top:0;left:calc(var(--T) / -2);width:var(--T);height:100%;transform:rotateY(-90deg)}
/* every dimension below is in em, and the spine's font-size is its own thickness (--T):
   one var() per book instead of ~25, which keeps style recalculation cheap with 200+ spines */
.sp{display:flex;flex-direction:column;align-items:center;overflow:hidden;
  font-size:var(--T);
  padding:.24em 0 .2em;
  color:var(--sink);border-radius:2px;
  --band:color-mix(in srgb,var(--sacc) calc(var(--bands,.5) * 100%),transparent);
  --L:calc(var(--H) * .585);
  /* gilt bands, a soft edge-lighting gradient, leather grain, then the cover colour - one element, no pseudo-elements */
  background:
    linear-gradient(var(--band),var(--band)) 50% .07em / 62% 1px no-repeat,
    linear-gradient(var(--band),var(--band)) 50% .105em / 62% 1px no-repeat,
    linear-gradient(var(--band),var(--band)) 50% calc(100% - .07em) / 62% 1px no-repeat,
    linear-gradient(var(--band),var(--band)) 50% calc(100% - .105em) / 62% 1px no-repeat,
    linear-gradient(90deg,rgba(0,0,0,.24) 0,rgba(0,0,0,.04) 9%,rgba(255,255,255,.16) 27%,rgba(255,255,255,0) 54%,rgba(0,0,0,.08) 88%,rgba(0,0,0,.26) 100%),
    var(--grain-s) 0 0 / 180px 180px,
    var(--sbg);
  box-shadow:inset 0 0 0 1px var(--sline)}
.sp .emb{display:block;flex:none;width:.42em;height:.42em;background:var(--sacc);margin-bottom:.2em}
.sp[data-e="0"] .emb{border-radius:50%}
.sp[data-e="1"] .emb{background:none;border:.05em solid var(--sacc);border-radius:50%}
.sp[data-e="2"] .emb{border-radius:999px 999px 0 0;height:.21em;margin-top:.1em;margin-bottom:.3em}
.sp[data-e="3"] .emb{clip-path:polygon(50% 0,100% 50%,50% 100%,0 50%)}
.sp[data-e="4"] .emb{clip-path:polygon(50% 6%,100% 94%,0 94%)}
.sp[data-e="5"] .emb{clip-path:polygon(34% 0,66% 0,66% 34%,100% 34%,100% 66%,66% 66%,66% 100%,34% 100%,34% 66%,0 66%,0 34%,34% 34%)}
.sp[data-e="6"] .emb{background:repeating-linear-gradient(180deg,var(--sacc) 0 .05em,transparent .05em .1em)}
.sp .ttl{
  flex:1;min-height:0;display:flex;align-items:center;justify-content:center;
  writing-mode:vertical-rl;white-space:nowrap;font-family:var(--display);font-weight:var(--sp-wt,620);text-transform:uppercase;letter-spacing:var(--sp-ls,.012em);line-height:1;
  font-size:min(.43em,calc(var(--L) / (var(--chars) * var(--sp-k,.66))));
  font-variation-settings:'opsz' 18;text-shadow:var(--sp-glow,none)}
.sp .no{flex:none;font:600 .16em/1 var(--ui);letter-spacing:.08em;margin:.875em 0 .625em;opacity:.78;font-variant-numeric:tabular-nums}
.sp .tag{flex:none;font:700 .17em/1 var(--ui);letter-spacing:.06em;text-decoration:none;padding:.588em .588em .5em;border:1px solid var(--sink);border-radius:2px}

/* ── book in flight (bookcase ⇄ detail) ────────────────── */
.flyer{position:fixed;inset:0;z-index:35;pointer-events:none;perspective:1700px;perspective-origin:50% 50%}
.flyer .item{visibility:visible}
.flyer .cover{box-shadow:0 0 0 1px rgba(20,18,12,.16),0 40px 60px -26px rgba(var(--shadow),.55),var(--cover-glow,0 0 0 0 transparent)}

/* ═══════════════════════ bookcase ═══════════════════════ */
.case{position:absolute;inset:0;z-index:0;content-visibility:hidden;opacity:0;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,transparent calc(var(--chromeTop) - 46px),#000 var(--chromeTop),#000 calc(100% - 70px),transparent calc(100% - 22px));
  mask-image:linear-gradient(180deg,transparent 0,transparent calc(var(--chromeTop) - 46px),#000 var(--chromeTop),#000 calc(100% - 70px),transparent calc(100% - 22px))}
html[data-view="case"] .case,html.warm-case .case{content-visibility:visible}
html[data-view="case"] .case{z-index:2;opacity:1;transition:opacity .7s var(--ease)}
/* while the carousel is sinking away the bookcase is already unlocked, invisible and underneath, so its first paint
   happens at the click rather than mid-animation */
html.case-pre .case{content-visibility:visible;opacity:.004}      /* 1/255: invisible, but not zero, so the compositor rasterises it now */
html.case-pre .bc-row,html.case-pre .bc-crown,.bc.anim .bc-row,.bc.anim .bc-crown{will-change:transform,opacity}
.case-scroll{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;
  padding:calc(var(--chromeTop) + 4px) 0 110px;scrollbar-width:thin;scrollbar-color:var(--line-2) transparent;scrollbar-gutter:stable both-edges}
.bc{position:relative;width:min(1280px,calc(100% - var(--gut) * 2));margin:0 auto;
  --bookH:244px;--side:36px;--rowPad:16px;--plankH:30px;--crownH:70px;--rowH:calc(var(--bookH) + 34px);--bgap:2px}
.bc-crown{position:relative;z-index:4;display:flex;align-items:center;justify-content:space-between;gap:20px;height:var(--crownH);padding:0 calc(var(--side) + 18px);
  background:var(--wood-h) 0 0/640px 96px,var(--case-frame);border-radius:var(--r-case,5px) var(--r-case,5px) 0 0;
  box-shadow:inset 0 1px 0 var(--plank-edge),inset 0 -1px 0 rgba(0,0,0,.38),var(--plank-glow,0 0 0 0 transparent)}
.bc-title{font:500 clamp(20px,2.4vw,28px)/1 var(--display);letter-spacing:.03em;color:var(--engrave);text-shadow:var(--engrave-sh,none)}
.bc-count{font:700 10px/1 var(--ui);letter-spacing:.2em;text-transform:uppercase;color:var(--engrave);text-shadow:var(--engrave-sh,none)}
.bc-body{position:relative;padding:0 var(--side);background:var(--case-back);min-height:120px}
.bc-body::before,.bc-body::after{content:'';position:absolute;top:0;bottom:0;width:var(--side);z-index:5;background:var(--wood-v) 0 0/96px 640px,var(--case-frame-v,var(--case-frame))}
.bc-body::before{left:0;box-shadow:inset -1px 0 0 rgba(0,0,0,.3),inset 1px 0 0 var(--plank-edge-soft,transparent),6px 0 14px -6px rgba(var(--shadow),.5)}
.bc-body::after{right:0;box-shadow:inset 1px 0 0 rgba(0,0,0,.3),inset -1px 0 0 var(--plank-edge-soft,transparent),-6px 0 14px -6px rgba(var(--shadow),.5)}
.bc-base{position:relative;z-index:4;height:calc(var(--crownH) * .55);background:var(--wood-h) 0 0/640px 96px,var(--case-frame);border-radius:0 0 var(--r-case,5px) var(--r-case,5px);
  box-shadow:inset 0 1px 0 var(--plank-edge),0 30px 50px -20px rgba(var(--shadow),.55)}
/* shelves far from the viewport are skipped (no paint) until you scroll near them; their height is known, so the scrollbar
   never jumps. warmCase() lays every shelf out once up front so revealing one later costs paint only. */
.bc-row{position:relative;content-visibility:auto;contain-intrinsic-size:auto calc(var(--rowH) + var(--plankH))}
html.warm-case .bc-row,.bc-row.pre{content-visibility:visible}
.bc-books{position:relative;z-index:1;display:flex;align-items:flex-end;gap:var(--bgap);height:var(--rowH);padding:0 var(--rowPad)}
.bc-row::before{content:'';position:absolute;left:0;right:0;top:0;height:calc(var(--rowH) * .8);z-index:2;pointer-events:none;background:linear-gradient(180deg,var(--led),transparent)}
.bc-row::after{content:'';position:absolute;left:0;right:0;top:0;bottom:var(--plankH);z-index:2;pointer-events:none;
  background:linear-gradient(180deg,rgba(var(--shadow),.34) 0,transparent 36px,transparent calc(100% - 14px),rgba(var(--shadow),.32) 100%)}
.bc-plank{position:relative;z-index:4;height:var(--plankH);display:flex;align-items:center;justify-content:space-between;padding:0 calc(var(--rowPad) + 2px);
  background:var(--wood-h) 0 40px/640px 96px,var(--case-frame);
  box-shadow:inset 0 1px 0 var(--plank-edge),inset 0 -1px 0 rgba(0,0,0,.42),0 16px 22px -12px rgba(var(--shadow),.6),var(--plank-glow,0 0 0 0 transparent)}
.bc-label{display:inline-flex;align-items:center;gap:10px;padding:5px 11px 4px;border-radius:2px;background:var(--brass-bg);color:var(--brass-ink);
  font:700 9px/1 var(--ui);letter-spacing:.2em;text-transform:uppercase;box-shadow:inset 0 1px 0 rgba(255,255,255,.45),inset 0 -1px 0 rgba(0,0,0,.28),0 1px 1px rgba(0,0,0,.35)}
.bc-label em{font-style:normal;font-weight:600;opacity:.72}
.bc-part{font:700 9px/1 var(--ui);letter-spacing:.2em;text-transform:uppercase;color:var(--engrave);text-shadow:var(--engrave-sh,none)}
.bk{position:relative;flex:none;width:var(--T);height:var(--H);cursor:pointer;transform-origin:50% 100%;
  transition:transform .6s var(--ease),box-shadow .5s var(--ease)}
.bk:hover,.bk:focus-visible{transform:translateY(-11px);z-index:3;box-shadow:inset 0 0 0 1px var(--sline),0 20px 24px -12px rgba(var(--shadow),.7)}
.bk:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.bk.out{visibility:hidden}
.bk.pulse{animation:bkPulse 1.8s var(--ease)}
@keyframes bkPulse{
  0%{box-shadow:inset 0 0 0 1px var(--sline),0 0 0 0 var(--accent);transform:translateY(0)}
  30%{box-shadow:inset 0 0 0 1px var(--sline),0 0 0 3px var(--accent),0 0 34px 8px color-mix(in srgb,var(--accent) 55%,transparent);transform:translateY(-16px)}
  100%{box-shadow:inset 0 0 0 1px var(--sline),0 0 0 0 transparent;transform:translateY(0)}}
.bookend{position:relative;flex:none;align-self:flex-end;width:12px;height:calc(var(--bookH) * .64);margin-left:9px;background:var(--bookend);border-radius:2px 2px 0 0;
  box-shadow:inset 1px 0 0 rgba(255,255,255,.4),inset -1px 0 0 rgba(0,0,0,.32),4px 0 10px -3px rgba(var(--shadow),.6)}
.bookend::after{content:'';position:absolute;left:-15px;bottom:0;width:30px;height:5px;background:var(--bookend);border-radius:1px;z-index:-1}

.tip{position:fixed;left:0;top:0;z-index:55;width:244px;pointer-events:none;display:grid;grid-template-columns:52px 1fr;gap:13px;align-items:center;padding:10px 12px 10px 10px;
  border-radius:calc(var(--r) + 3px);background:var(--glass);border:1px solid var(--glass-line);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);
  box-shadow:0 24px 44px -18px rgba(var(--shadow),.65);opacity:0;transform:translate3d(-999px,0,0);transition:opacity .22s,transform .35s var(--ease)}
.tip.on{opacity:1}
.tip.snap{transition:opacity .22s}
.tip-th{display:block;width:52px;aspect-ratio:4/5;border-radius:2px;background:var(--thumb-bg) center/cover;box-shadow:0 0 0 1px var(--line)}
.tip-tx b{display:block;font:500 15px/1.2 var(--display);letter-spacing:-.005em;color:var(--ink)}
.tip-tx i{display:block;margin-top:6px;font:600 9px/1.35 var(--ui);letter-spacing:.14em;text-transform:uppercase;color:var(--mute);font-style:normal}

/* ── responsive ────────────────────────────────────────── */
@media (max-width:1100px){
  .bc{--bookH:214px;--side:28px}
}
@media (max-width:720px){
  :root{--gut:8px;--chromeTop:172px}
  .bc{--bookH:172px;--side:12px;--rowPad:8px;--plankH:26px;--crownH:54px;--bgap:1.5px}
  .bc-crown{padding:0 calc(var(--side) + 12px)}
  .bc-count{display:none}
  .bc-label{padding:4px 9px 3px;font-size:8.5px}
  .tip{display:none}
}
@media (max-height:560px){
  :root{--chromeTop:136px}
}
@media (pointer:coarse){
  .tip{display:none}
}
