/* ============================================================
   The tome — about page
   A five-leaf book. Pages are authored as plain <article>s and
   the book is assembled from them at runtime, so with JS off (or
   reduced motion on) you just read the articles.
   ============================================================ */

/* clip, not hidden: hidden here would make the body a scroll container and
   break the sticky topbar. This stops turned pages swinging off the left of a
   phone from creating a horizontal scrollbar. */
.tome-page{ background:#e9dac9; overflow-x:clip; }
html:has(.tome-page){ overflow-x:clip }
.tome-page main{ padding-bottom:clamp(40px,7vw,90px) }

.tome-head{ text-align:center; padding:clamp(26px,5vw,54px) 0 clamp(10px,2vw,20px) }
.tome-head .runic{ display:block; margin-bottom:10px }
.tome-head h1{ margin:0; font-size:clamp(1.6rem,3vw,2.3rem) }

/* ---------- the stage ---------- */
.tome{
  position:relative; margin:0 auto;
  width:min(860px, 84vw, calc((100svh - 360px) * 1.42));
  touch-action:pan-y;
}
.tome-stage{ transform:rotate(-.55deg) }   /* set down, not pasted in */
.tome-viewport{ position:relative; width:100%; padding-bottom:5%; }
.tome-stage{
  position:relative; width:100%; aspect-ratio:1.42/1; margin:0 auto;
}
.book::after{                     /* the soft shadow it throws on the paper */
  content:""; position:absolute; z-index:-2;
  left:calc(50% - 5%); right:-3%; bottom:-6%; height:16%;
  background:radial-gradient(58% 50% at 50% 34%, rgba(64,44,24,.34), transparent 70%);
  filter:blur(16px); transition:left 1.05s cubic-bezier(.55,.06,.28,1);
}
.tome[data-open="1"] .book::after{ left:-3% }

/* Perspective lives here, and the book itself stays FLAT. That is the whole
   trick: with transform-style:preserve-3d on the book, the five coplanar
   leaves z-fight and the compositor paints half of one and half of another.
   Flat + plain z-index composites them like the sheets of paper they are,
   while each leaf still gets its own 3D space for its two faces. */
.book{
  position:absolute; inset:0;
  perspective:2400px; perspective-origin:50% 45%;
  transform:translateX(var(--shift,-25%));
  transition:transform 1.9s cubic-bezier(.55,.06,.28,1);
  will-change:transform;
}
.book.thump{ animation:tome-thump .5s cubic-bezier(.3,1.5,.5,1) }
@keyframes tome-thump{
  0%{ transform:translateX(var(--shift,-25%)) translateY(0) }
  35%{ transform:translateX(var(--shift,-25%)) translateY(.55%) scale(.997) }
  100%{ transform:translateX(var(--shift,-25%)) translateY(0) }
}

/* the slab of pages at the fore-edges — this is most of the "weight".
   These live inside .book so they travel with it when it opens. */
.edge{
  position:absolute; top:1.5%; height:97%; z-index:1; pointer-events:none;
  background:
    repeating-linear-gradient(to right,
      #ddceb2 0 1px, #bda98a 1px 2px, #e4d8bf 2px 3px, #c7b494 3px 4px);
  box-shadow:0 2px 6px rgba(40,26,14,.45), inset 0 0 8px rgba(70,48,24,.35);
  transition:width 1.05s cubic-bezier(.55,.06,.28,1);
}
.edge.right{ left:calc(100% - 2px); width:calc(var(--right,1) * 3.4%); border-radius:0 3px 3px 0 }
.edge.left { right:calc(100% - 2px); width:calc(var(--left,0) * 3.4%); border-radius:3px 0 0 3px }

/* The boards: the leather sticks out past the paper on every side, which is
   most of what makes this read as an object rather than an embed. */
.back-cover{
  position:absolute; z-index:0;
  left:calc(50% - 1.1%); top:-1.5%; width:calc(50% + 2.2%); height:103%;
  background:#5a3325 url("../tome/leather.jpg") center/cover;
  border-radius:3px 9px 9px 3px;
  box-shadow:
    0 1px 0 rgba(255,226,190,.12) inset,
    0 4px 0 -1px #5c3526,            /* the board has thickness */
    0 7px 0 -2px #34190f,
    0 9px 1px -3px rgba(0,0,0,.55),
    0 20px 28px -18px rgba(30,18,10,.8),
    0 46px 62px -30px rgba(40,26,14,.5);
  transition:left 1.05s cubic-bezier(.55,.06,.28,1), width 1.05s cubic-bezier(.55,.06,.28,1);
}
.tome[data-open="1"] .back-cover{ left:-1.1%; width:calc(100% + 2.2%); border-radius:9px }

/* contact shadow — a tight dark line where the book meets the paper */
.book::before{
  content:""; position:absolute; z-index:-1;
  left:calc(50% + 1%); right:1%; bottom:-1.2%; height:3%;
  background:linear-gradient(to bottom, rgba(46,30,16,.45), transparent);
  filter:blur(4px);
  transition:left 1.05s cubic-bezier(.55,.06,.28,1);
}
.tome[data-open="1"] .book::before{ left:1% }

/* ---------- leaves ---------- */
.leaf{
  position:absolute; left:50%; top:.6%; width:50%; height:98.8%;
  transform-origin:left center; transform-style:preserve-3d;
  transform:rotateY(0deg);
}
.leaf.flipped{ transform:rotateY(-180deg) }

/* Keyframes rather than a transition, because an easing curve can't do what
   this needs: move slowly through the angles where the sheet is actually
   visible, hurry through edge-on where there's nothing to see, and still
   start and land heavily. The sheet also lifts toward you mid-arc. */
@keyframes leaf-fwd{
  0%   { transform:translateZ(0)     rotateY(0deg) }
  8%   { transform:translateZ(6px)   rotateY(-6deg) }
  25%  { transform:translateZ(20px)  rotateY(-34deg) }
  42%  { transform:translateZ(28px)  rotateY(-66deg) }
  55%  { transform:translateZ(30px)  rotateY(-92deg) }
  64%  { transform:translateZ(28px)  rotateY(-118deg) }
  82%  { transform:translateZ(16px)  rotateY(-150deg) }
  94%  { transform:translateZ(4px)   rotateY(-173deg) }
  100% { transform:translateZ(0)     rotateY(-180deg) }
}
@keyframes leaf-back{
  0%   { transform:translateZ(0)     rotateY(-180deg) }
  8%   { transform:translateZ(6px)   rotateY(-174deg) }
  25%  { transform:translateZ(20px)  rotateY(-146deg) }
  42%  { transform:translateZ(28px)  rotateY(-114deg) }
  55%  { transform:translateZ(30px)  rotateY(-88deg) }
  64%  { transform:translateZ(28px)  rotateY(-62deg) }
  82%  { transform:translateZ(16px)  rotateY(-30deg) }
  94%  { transform:translateZ(4px)   rotateY(-7deg) }
  100% { transform:translateZ(0)     rotateY(0deg) }
}
.leaf.turn-fwd { animation:leaf-fwd  1.9s linear forwards }
.leaf.turn-back{ animation:leaf-back 1.9s linear forwards }

.face{
  position:absolute; inset:0; backface-visibility:hidden; overflow:hidden;
  background:#efe4cd url("../tome/page.jpg") center/cover;
  border-radius:1px 5px 5px 1px;
  box-shadow:inset 0 0 34px rgba(112,84,44,.30), 0 1px 3px rgba(60,40,18,.25);
}
.face.back{ transform:rotateY(180deg); border-radius:1px 5px 5px 1px }

/* the gutter shadow, so pages look bound rather than floating */
.face::after{
  content:""; position:absolute; top:0; bottom:0; width:13%; pointer-events:none;
  background:linear-gradient(to right, rgba(76,52,26,.34), rgba(76,52,26,.04) 55%, transparent);
}
.face.front::after{ left:0 }
.face.back::after{ right:0; transform:scaleX(-1) }

/* ---------- the curl ----------
   A sheet of paper does not turn as a rigid plane. During a turn the face's
   content is rebuilt as five nested slices, each rotated a few degrees more
   than the last, which bends the page into a cylinder. JS drives --curl
   frame by frame so the bend peaks in the middle of the arc and relaxes at
   both ends. Each slice is shaded a little darker toward the free edge. */
.face.curled{
  background:none; box-shadow:none; overflow:visible;
  /* the 3D chain has to stay unbroken or the slices flatten into the face */
  transform-style:preserve-3d;
}
/* Backface culling is unreliable once the subtree is 3D and the face is
   mirrored, so which face is showing is decided explicitly instead: JS adds
   .past-half once the sheet is more than 90 degrees over. */
.leaf.turning:not(.past-half) .face.back{ visibility:hidden }
.leaf.turning.past-half .face.front{ visibility:hidden }
.face.curled > .sheet, .face.curled > .cover-inner{ display:none }
.cslice{
  position:absolute; top:0; left:0; width:12.5%; height:100%;
  transform-origin:left center;
  transform:rotateY(var(--curl,0deg));
  transform-style:preserve-3d;
  /* The face's own backface-visibility stops applying once its subtree is
     3D, so each slice has to hide its own back or you see the front face's
     text mirrored through the sheet. */
  backface-visibility:hidden;
}
.cslice .cslice{ left:100%; width:100% }
.cclip{ position:absolute; top:0; bottom:0; left:0; right:-1px; overflow:hidden; backface-visibility:hidden }
/* the texture lives on the wrap, which is a whole page wide, so it runs
   continuously across the slices instead of restarting at every seam */
.cwrap{
  position:absolute; top:0; left:calc(var(--i,0) * -100%); width:800%; height:100%;
  background:#efe4cd url("../tome/page.jpg") center/cover;
}
.cclip.leather + *, .cwrap.leather{
  background:#5a3325 url("../tome/leather.jpg") center/cover;
}
/* Shading across the bend.
   It has to live on .cwrap, not on the slice. Every cwrap is a full page wide
   and they all line up on the same origin, so a gradient drawn here is one
   continuous ramp across the whole sheet — each slice just shows its slot of
   it. Anything painted per slice (a gradient that restarts, or a flat tint
   that steps by index) draws a visible vertical line at every seam. That was
   the artifact. --k is the current curl, 0..1, from JS. */
.cwrap::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(90deg,
    rgba(255,250,232,.42) 0%,
    rgba(255,250,232,.16) 22%,
    rgba(54,33,12,.05) 52%,
    rgba(54,33,12,.20) 78%,
    rgba(54,33,12,.34) 100%);
  opacity:var(--k,0);
}

/* light rolling across the page as it turns */
.sheen{
  position:absolute; inset:0; pointer-events:none; opacity:0;
  background:linear-gradient(102deg, rgba(255,250,232,.86) 0%, rgba(255,244,216,.15) 38%, rgba(58,36,14,.16) 62%, rgba(48,30,12,.44) 100%);
  transition:opacity .28s ease;
}
.leaf.turning .sheen{ opacity:1 }
/* NO filter anywhere on the turning sheet. On a slice it flattens
   transform-style:preserve-3d and you get seams; on the leaf it forces the
   whole sheet to be rasterised to a bitmap at its untransformed size and then
   3D-transformed, which is what made the page and its edges look soft. The
   shadow the sheet casts is drawn as its own element on the page below. */
.cast{
  position:absolute; top:1.2%; height:97.6%; z-index:3; pointer-events:none;
  opacity:0; transform:scaleX(0);
  background:linear-gradient(90deg, rgba(48,30,12,.34) 0%, rgba(48,30,12,.16) 48%, rgba(48,30,12,0) 100%);
}
.cast.r{ left:50%; width:50%; transform-origin:left center }
.cast.l{ left:0;   width:50%; transform-origin:right center;
         background:linear-gradient(270deg, rgba(48,30,12,.34) 0%, rgba(48,30,12,.16) 48%, rgba(48,30,12,0) 100%) }

/* ---------- page contents ---------- */
.sheet{
  position:absolute; inset:0; display:flex; flex-direction:column;
  padding:clamp(20px,3.4vw,46px) clamp(20px,3.6vw,50px);
  color:#3b2f22; font-size:clamp(.74rem,1.02vw,1rem); line-height:1.62;
}
.face.front .sheet{ padding-left:clamp(30px,5vw,68px) }
.face.back  .sheet{ padding-right:clamp(30px,5vw,68px) }
.sheet h2{
  font-size:clamp(1.05rem,1.7vw,1.6rem); margin:0 0 .55em; letter-spacing:-.01em; color:#2f2418;
}
.sheet .kicker{
  font-family:var(--sans); font-size:.6rem; letter-spacing:.3em; text-transform:uppercase;
  color:#8a7457; margin:0 0 14px;
}
.sheet p{ margin:0 0 .85em; max-width:46ch }
.sheet p.drop::first-letter{
  float:left; font-size:3.1em; line-height:.82; padding:.06em .1em 0 0; color:#7a4a1e; font-weight:600;
}
.sheet .folio{
  margin-top:auto; padding-top:14px; font-family:var(--sans); font-size:.58rem;
  letter-spacing:.26em; text-transform:uppercase; color:#9c8768;
}
.face.back .folio{ text-align:right }
.sheet ul{ margin:.2em 0 .9em; padding-left:1.1em }
.sheet li{ margin:.3em 0 }
.sheet a{ color:#7a4a1e; text-underline-offset:3px }
.sheet .marginal{
  font-style:italic; color:#7c6a52; border-left:2px solid rgba(122,74,30,.35);
  padding-left:12px; margin:.4em 0 1em; max-width:38ch;
}
.plate{
  width:min(62%,230px); align-self:center; margin:auto 0;
  border:1px solid rgba(90,66,36,.4); padding:7px; background:rgba(255,250,238,.55);
  box-shadow:0 12px 26px -14px rgba(60,40,18,.7);
}
.plate img{ width:100%; height:auto; filter:sepia(.34) contrast(1.03) }
.plate figcaption{
  font-family:var(--sans); font-size:.56rem; letter-spacing:.22em; text-transform:uppercase;
  color:#8a7457; text-align:center; margin-top:8px;
}

/* ---------- the cover ---------- */
.face.cover{
  background:#5a3325 url("../tome/leather.jpg") center/cover;
  box-shadow:
    inset 0 0 46px rgba(30,14,6,.30),
    inset 0 0 14px rgba(30,14,6,.24),
    inset 2px 0 0 rgba(255,228,186,.08);
  border-radius:2px 8px 8px 2px;
}
/* age on top of the leather: uneven darkening and a couple of old stains */
.face.cover::before{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:2;
  background:
    radial-gradient(40% 28% at 78% 16%, rgba(58,32,14,.16), transparent 72%),
    radial-gradient(32% 24% at 14% 74%, rgba(58,32,14,.14), transparent 74%),
    radial-gradient(58% 46% at 44% 46%, rgba(224,186,140,.16), transparent 72%),
    linear-gradient(200deg, rgba(40,20,8,.10), transparent 38%, rgba(40,20,8,.14));
  mix-blend-mode:multiply;
}
.cover-inner{
  position:absolute; inset:clamp(12px,2vw,26px);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:clamp(10px,2vw,22px); padding:clamp(14px,2.6vw,30px);
}
/* The tooling is masked with the wear map so the gold has rubbed off in
   patches, the way gilt does. Two rules, an outer and an inner. */
.cover-inner::before{
  content:""; position:absolute; inset:0; pointer-events:none;
  border:1.5px solid rgba(226,188,120,.68); border-radius:2px;
  box-shadow:inset 0 0 0 5px transparent, inset 0 0 0 6px rgba(226,188,120,.28);
  -webkit-mask-image:url("../tome/wear.png"); mask-image:url("../tome/wear.png");
  -webkit-mask-size:260% 380%; mask-size:260% 380%;
  -webkit-mask-position:34% 46%; mask-position:34% 46%;
}
/* the debossed line under the gilt, so the tooling has depth */
.cover-inner::after{
  content:""; position:absolute; inset:-1.5px; pointer-events:none;
  border:1.5px solid rgba(20,10,6,.5); border-radius:3px; z-index:-1;
}
.cover-mark{
  width:min(78%,320px);
  -webkit-mask-image:url("../tome/wear.png"); mask-image:url("../tome/wear.png");
  -webkit-mask-size:300% 780%; mask-size:300% 780%;
  -webkit-mask-position:28% 38%; mask-position:28% 38%;
  filter:drop-shadow(0 1px 0 rgba(12,6,3,.7));
}
.cover-portrait{
  width:min(52%,190px); aspect-ratio:1/1.22; overflow:hidden;
  border:1px solid rgba(214,172,104,.5);
  box-shadow:0 0 0 5px rgba(20,10,6,.6), 0 0 0 6px rgba(214,172,104,.18), inset 0 0 26px rgba(0,0,0,.65), 0 14px 30px -14px #000;
}
.cover-portrait{ position:relative }
.cover-portrait::after{      /* an old print, foxed and darkened at the edges */
  content:""; position:absolute; inset:0; pointer-events:none;
  background:
    radial-gradient(78% 68% at 50% 45%, transparent 45%, rgba(50,28,12,.38) 100%),
    linear-gradient(160deg, rgba(120,86,48,.22), transparent 45%);
  mix-blend-mode:multiply;
}
.cover-portrait img{
  width:100%; height:100%; object-fit:cover;
  filter:sepia(.72) contrast(1.10) brightness(.80) saturate(.5);
}
.cover-sub{
  font-family:var(--sans); font-size:clamp(.52rem,.78vw,.68rem); letter-spacing:.42em;
  text-transform:uppercase; color:#c9a86e;
}
.cover-dust{
  position:absolute; inset:0; pointer-events:none; transition:opacity 1.4s ease;
  background:
    radial-gradient(38% 26% at 24% 18%, rgba(226,214,190,.20), transparent 70%),
    radial-gradient(46% 30% at 74% 76%, rgba(226,214,190,.16), transparent 72%),
    radial-gradient(30% 22% at 62% 32%, rgba(226,214,190,.13), transparent 70%);
}
.tome[data-open="1"] .cover-dust{ opacity:0 }

/* ---------- dust canvas ---------- */
.dust{ position:absolute; left:-22%; top:-26%; width:144%; height:150%; pointer-events:none; z-index:40 }

/* ---------- controls ---------- */
.tome-controls{
  display:flex; align-items:center; justify-content:center; gap:clamp(12px,2.4vw,26px);
  margin:clamp(18px,3vw,32px) auto 0; font-family:var(--sans);
}
.tome-btn{
  appearance:none; border:1px solid rgba(58,44,28,.35); background:rgba(255,250,240,.5);
  color:#3b2f22; font:inherit; font-size:.72rem; letter-spacing:.16em; text-transform:uppercase;
  padding:10px 18px; border-radius:2px; cursor:pointer; transition:.2s;
}
.tome-btn:hover:not(:disabled){ background:#3b2f22; color:#f2e8d6; border-color:#3b2f22 }
.tome-btn:disabled{ opacity:.32; cursor:default }
.tome-progress{
  font-size:.64rem; letter-spacing:.24em; text-transform:uppercase; color:#8a7457; min-width:9ch; text-align:center;
}
.tome-hint{
  text-align:center; font-family:var(--sans); font-size:.62rem; letter-spacing:.24em;
  text-transform:uppercase; color:#9c8768; margin-top:14px; transition:opacity .6s;
}
.tome[data-open="1"] ~ .tome-hint{ opacity:0 }

/* click zones sit over the book */
.turn-zone{
  position:absolute; top:0; height:100%; width:50%; z-index:35; cursor:pointer;
  background:transparent; border:0; padding:0;
}
.turn-zone.prev{ left:0 } .turn-zone.next{ right:0 }
.turn-zone:disabled{ cursor:default }

/* ---------- one page at a time on a phone ----------
   Not a clipped window onto a spread — that's what made it read as a frame
   stuck on the page. On a phone the book IS one page wide: boards, shadows
   and dust all sit on the paper, and a turned sheet swings away off to the
   left over the page rather than being sliced off at a border. */
@media (max-width:820px){
  .tome{ width:min(330px, 76vw, calc((100svh - 340px) * .70)) }
  .tome-stage{ width:100%; transform:rotate(-.7deg); aspect-ratio:.72/1 }
  .tome-viewport{ overflow:visible; padding:3% 0 10% }

  .book{ --shift:0% !important; perspective:1400px }
  .leaf{ left:0; width:100% }
  .back-cover,
  .tome[data-open="1"] .back-cover{
    left:-1.8%; width:103.6%; border-radius:3px 9px 9px 3px;
  }
  .book::before,
  .tome[data-open="1"] .book::before{ left:2%; right:2% }
  .book::after,
  .tome[data-open="1"] .book::after{ left:-6%; right:-6%; bottom:-7%; height:18% }

  /* Once open, the book stays open: the verso and the left board run off the
     left of the screen and remain there, so you're looking at the right-hand
     page of a real open book rather than at a single floating leaf. */
  .tome[data-open="1"] .back-cover{ left:-103%; width:206.6%; border-radius:9px }
  .tome[data-open="1"] .book::before{ left:-100%; right:2% }
  .tome[data-open="1"] .book::after{ left:-104%; right:-6% }

  .dust{ left:-40%; top:-24%; width:180%; height:146% }
  .sheet{ font-size:clamp(.84rem,3.6vw,1.02rem) }
  .sheet p{ max-width:none }
  .face, .face.back{ border-radius:2px 6px 6px 2px }
  .edge.left{ display:none }
}

/* ---------- no JS / reduced motion: just read it ----------
   If this block is on screen at all, the book never got built, so it can be
   styled as the plain document it is. */
.tome-fallback{ max-width:64ch; margin:0 auto }
.tome-fallback .page-src{ margin:0 0 clamp(26px,4.5vw,46px) }
.tome-fallback .page-src[data-type="cover"]{ display:none }
.tome-fallback .folio{ display:none }
.tome-fallback .kicker{
  font-family:var(--sans); font-size:.6rem; letter-spacing:.3em; text-transform:uppercase;
  color:var(--ink-faint); margin:0 0 8px;
}
.tome-fallback h2{ font-size:clamp(1.3rem,2.2vw,1.75rem); margin:0 0 .5em }
.tome-fallback p{ margin:0 0 .9em }
.tome-fallback .marginal{
  font-style:italic; color:var(--ink-soft);
  border-left:2px solid rgba(122,74,30,.35); padding-left:14px; margin:1em 0 1.2em;
}
.tome-fallback .plate{
  width:min(260px,62%); margin:0 auto 8px; padding:8px;
  border:1px solid var(--parchment-edge); background:rgba(255,250,238,.6);
}
.tome-fallback .plate figcaption{
  font-family:var(--sans); font-size:.6rem; letter-spacing:.22em; text-transform:uppercase;
  color:var(--ink-faint); text-align:center; margin-top:8px;
}
.tome-fallback .plate img{ filter:sepia(.3) }
body:has(.tome-fallback) .tome-hint{ display:none }
.tome[hidden]{ display:none }

@media (prefers-reduced-motion:reduce){
  .book,.leaf,.edge{ transition-duration:.001ms !important }
  .book.thump{ animation:none }
}

